/*
 *  MrBayes 3
 *
 *  (c) 2002-2013
 *
 *  John P. Huelsenbeck
 *  Dept. Integrative Biology
 *  University of California, Berkeley
 *  Berkeley, CA 94720-3140
 *  johnh@berkeley.edu
 *
 *  Fredrik Ronquist
 *  Swedish Museum of Natural History
 *  Box 50007
 *  SE-10405 Stockholm, SWEDEN
 *  fredrik.ronquist@nrm.se
 *
 *  With important contributions by
 *
 *  Paul van der Mark (paulvdm@sc.fsu.edu)
 *  Maxim Teslenko (maxim.teslenko@nrm.se)
 *
 *  and by many users (run 'acknowledgments' to see more info)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details (www.gnu.org).
 *
 */

#include "bayes.h"
#include "best.h"
#include "command.h"
#include "model.h"
#include "mcmc.h"
#include "proposal.h"
#include "sumpt.h"
#include "utils.h"
#if defined(__MWERKS__)
#include "SIOUX.h"
#endif

const char* const svnRevisionModelC = "$Rev: 1032 $";   /* Revision keyword which is expended/updated by svn on each commit/update */

#undef  DEBUG_ADDDUMMYCHARS
#undef  DEBUG_CONSTRAINTS
#undef  DEBUG_COMPRESSDATA
#undef  DEBUG_CPP

/* local prototypes */
int       AddDummyChars (void);
void      AllocateCppEvents (Param *p);
MCMCMove *AllocateMove (MoveType *moveType, Param *param);
int       AllocateNormalParams (void);
int       AllocateTreeParams (void);
void      CheckCharCodingType (Matrix *m, CharInfo *ci);
int       CheckExpandedModels (void);
int       CompressData (void);
int       InitializeChainTrees (Param *p, int from, int to, int isRooted);
int       FillBrlensSubParams (Param *param, int chn, int state);
void      FreeCppEvents (Param *p);
void      FreeMove (MCMCMove *mv);
void      GetPossibleAAs (int aaCode, int aa[]);
void      GetPossibleNucs (int nucCode, int nuc[]);
void      GetPossibleRestrictionSites (int resSiteCode, int *sites);
int       GetUserTreeFromName (int *index, char *treeName);
void      InitializeMcmcTrees (Param *p);
int       IsApplicable (Param *param);
int       IsApplicable_FiveTaxaOrMore (Param *param);
int       IsApplicable_FourTaxaOrMore (Param *param);
int       IsApplicable_ThreeTaxaOrMore (Param *param);
int       IsApplicableTreeAgeMove (Param *param);
int       IsModelSame (int whichParam, int part1, int part2, int *isApplic1, int *isApplic2);
int       LargestMovableSubtree(Param *treeParam);
int       NumActiveParts (void);
int       NumInformativeHardConstraints (ModelParams *mp);
int       NumNonExcludedChar (void);
int       NumStates (int part);
int       PrintCompMatrix (void);
int       PrintMatrix (void);
int       ProcessStdChars (RandLong *seed);
void      SetCode (int part);
int       SetModelParams (void);
int       SetPopSizeParam (Param *param, int chn, int state, PolyTree *pt);
int       SetRelaxedClockParam (Param *param, int chn, int state, PolyTree *pt);
int       SetUpLinkTable (void);
int       ShowMoves (int used);
int       ShowParameters (int showStartVals, int showMoves, int showAllAvailable);
int       UpdateCppEvolLength (int *nEvents, MrBFlt **pos, MrBFlt **rateMult, MrBFlt *evolLength, TreeNode *p, MrBFlt baseRate);

/* globals */
int             *activeParams[NUM_LINKED];              /* a table holding the parameter link status        */
int             localOutGroup;                          /* outgroup for non-excluded taxa                   */
Calibration     **localTaxonCalibration = NULL;         /* stores local taxon calibrations (ages)           */
char            **localTaxonNames = NULL;               /* points to names of non-excluded taxa             */
Model           *modelParams;                           /* holds model params                               */
ModelInfo       *modelSettings;                         /* stores important info on model params            */
MCMCMove        **moves;                                /* vector of pointers to applicable moves           */
int             numApplicableMoves;                     /* number of moves applicable to model parameters   */
int             numCurrentDivisions;                    /* number of partitions of data                     */
int             numGlobalChains;                        /* number of global chains                          */
int             numLocalTaxa;                           /* number of non-excluded taxa                      */
int             numLocalChar;                           /* number of non-excluded characters                */
int             numParams;                              /* number of parameters in model                    */
int             numTopologies;                          /* number of topologies for one chain and state     */
int             numTrees;                               /* number of trees for one chain and state          */
Param           *params;                                /* vector of parameters                             */
Param           *printParams;                           /* vector of subst model parameters to print        */
ShowmovesParams showmovesParams;                        /* holds parameters for Showmoves command           */
Param           *treePrintparams;                       /* vector of tree parameters to print               */
int             setUpAnalysisSuccess;                   /* Set to YES if analysis is set without error      */

/* globals used to describe and change the current model; allocated in AllocCharacters and SetPartition  */
int         *numVars;                                   /* number of variables in setting arrays         */
int         *activeParts;                               /* partitions changes should apply to            */
int         *linkTable[NUM_LINKED];                     /* how parameters are linked across parts        */
int         *tempLinkUnlink[NUM_LINKED];                /* for changing parameter linkage                */
int         *tempLinkUnlinkVec;                         /* for changing parameter linkage                */
MrBFlt      *tempNum;                                   /* vector of numbers used for setting arrays     */

/* Aamodel parameters */
MrBFlt          aaJones[20][20];             /* rates for Jones model                        */
MrBFlt          aaDayhoff[20][20];           /* rates for Dayhoff model                      */
MrBFlt          aaMtrev24[20][20];           /* rates for mtrev24 model                      */
MrBFlt          aaMtmam[20][20];             /* rates for mtmam model                        */
MrBFlt          aartREV[20][20];             /* rates for rtREV model                        */
MrBFlt          aaWAG[20][20];               /* rates for WAG model                          */
MrBFlt          aacpREV[20][20];             /* rates for aacpREV model                      */
MrBFlt          aaVt[20][20];                /* rates for VT model                           */
MrBFlt          aaBlosum[20][20];            /* rates for Blosum62 model                     */
MrBFlt          aaLG[20][20];                /* rates for LG model                           */
MrBFlt          jonesPi[20];                 /* stationary frequencies for Jones model       */
MrBFlt          dayhoffPi[20];               /* stationary frequencies for Dayhoff model     */
MrBFlt          mtrev24Pi[20];               /* stationary frequencies for mtrev24 model     */
MrBFlt          mtmamPi[20];                 /* stationary frequencies for mtmam model       */
MrBFlt          rtrevPi[20];                 /* stationary frequencies for rtREV model       */
MrBFlt          wagPi[20];                   /* stationary frequencies for WAG model         */
MrBFlt          cprevPi[20];                 /* stationary frequencies for aacpREV model     */
MrBFlt          vtPi[20];                    /* stationary frequencies for VT model          */
MrBFlt          blosPi[20];                  /* stationary frequencies for Blosum62 model    */
MrBFlt          lgPi[20];                    /* stationary frequencies for LG model          */

/* parser flags and variables */
int         fromI, toJ, foundDash, foundComma, foundEqual, foundBeta,
            foundAaSetting, foundExp, modelIsFixed, linkNum, foundLeftPar,
            foundFSNum[999], foundFSTime[999], tempNumStates, isNegative;
MrBFlt      tempStateFreqs[200], tempAaModelPrs[10];
char        colonPr[100], clockPr[30];

/* other local variables (this file) */
MrBFlt          empiricalFreqs[200];         /* emprical base frequencies for partition                 */
int             intValsRowSize = 0;          /* row size of intValues matrix                            */
int             *intValues = NULL;           /* stores int values of chain parameters                   */
Tree            **mcmcTree;                  /* pointers to trees for mcmc                              */
int             paramValsRowSize = 0;        /* row size of paramValues matrix                          */
MrBFlt          *paramValues = NULL;         /* stores actual values and subvalues of chain parameters  */
int             *relevantParts = NULL;       /* partitions that are affected by this move               */
Param           **subParamPtrs;              /* pointer to subparams for topology params                */
int             *stateSize;                  /* # states for each compressed char                       */
// int          foundCurly;
// char         *plotTokenP;                 /* plotToken[CMD_STRING_LENGTH];*/


/*-----------------------------------------------------------------------
|
|   AddDummyChars: Add dummy characters to relevant partitions
|
------------------------------------------------------------------------*/
int AddDummyChars (void)
{
    int         i, j, k, d, numIncompatible, numDeleted, numStdChars, oldRowSize,
                newRowSize, numDummyChars, newColumn, newChar, oldColumn, oldChar, 
                isCompat, *tempChar, numIncompatibleChars;
    BitsLong    *tempMatrix, bitsLongOne = 1;
    CLFlt       *tempSitesOfPat;
    ModelInfo   *m;
    ModelParams *mp;
    CharInfo    cinfo;
    Matrix      matrix;

    /* set pointers to NULL */
    tempMatrix = NULL;
    tempSitesOfPat = NULL;
    tempChar = NULL;

    /* check how many dummy characters needed in total */
    numDummyChars = 0;
    numStdChars = 0;
    for (d=0; d<numCurrentDivisions; d++)
        {
        m = &modelSettings[d];
        mp = &modelParams[d];

        m->numDummyChars = 0;

        if (mp->dataType == RESTRICTION && !strcmp(mp->parsModel,"No"))
            {
            if (!strcmp(mp->coding, "Variable"))
                m->numDummyChars = 2;
            else if (!strcmp(mp->coding, "Noabsencesites") || !strcmp(mp->coding, "Nopresencesites"))
                m->numDummyChars = 1;
            else if (!strcmp(mp->coding, "Informative"))
                m->numDummyChars = 2 + 2 * numLocalTaxa;
            }

        if (mp->dataType == STANDARD && !strcmp(mp->parsModel,"No"))
            {
            if (!strcmp(mp->coding, "Variable"))
                m->numDummyChars = 2;
            else if (!strcmp(mp->coding, "Informative"))
                m->numDummyChars = 2 + 2 * numLocalTaxa;
            numStdChars += (m->numChars + m->numDummyChars);
            }

        numDummyChars += m->numDummyChars;
        m->numChars += m->numDummyChars;
        }

    /* exit if dummy characters not needed */
    if (numDummyChars == 0)
        return NO_ERROR;

    /* print original compressed matrix */
#   if  defined (DEBUG_ADDDUMMYCHARS)
    MrBayesPrint ("Compressed matrix before adding dummy characters...\n");
    PrintCompMatrix();
#   endif

    /* set row sizes for old and new matrices */
    oldRowSize = compMatrixRowSize;
    compMatrixRowSize += numDummyChars;
    newRowSize = compMatrixRowSize;
    numCompressedChars += numDummyChars;

    /* allocate space for new data */
    tempMatrix = (BitsLong *) SafeCalloc (numLocalTaxa * newRowSize, sizeof(BitsLong));
    tempSitesOfPat = (CLFlt *) SafeCalloc (numCompressedChars, sizeof(CLFlt));
    tempChar = (int *) SafeCalloc (compMatrixRowSize, sizeof(int));
    if (!tempMatrix || !tempSitesOfPat || !tempChar)
        {
        MrBayesPrint ("%s   Problem allocating temporary variables in AddDummyChars\n", spacer);
        goto errorExit;
        }

    /* initialize indices */
    oldChar = newChar = newColumn = numDeleted = 0;

    /* set up matrix struct */
    matrix.origin = compMatrix;
    matrix.nRows = numLocalTaxa;
    matrix.rowSize = oldRowSize;

    /* loop over divisions */
    for (d=0; d<numCurrentDivisions; d++)
        {
        m = &modelSettings[d];
        mp = &modelParams[d];

        /* insert the dummy characters first for each division */
        if (m->numDummyChars > 0)
            {
            // MrBayesPrint("%s   Adding dummy characters (unobserved site patterns) for division %d\n", spacer, d+1);
            // do not print this every time
            if (!strcmp(mp->coding, "Variable") || !strcmp(mp->coding, "Informative"))
                {
                for (k=0; k<2; k++)
                    {
                    for (i=0; i<numLocalTaxa; i++)
                        tempMatrix[pos(i,newColumn,newRowSize)] = (bitsLongOne<<k);
                    tempSitesOfPat[newChar] = 0;
                    tempChar[newColumn] = -1;
                    newChar++;
                    newColumn++;
                    }
                }

            if (!strcmp(mp->coding, "Informative"))
                {
                for (k=0; k<2; k++)
                    {
                    for (i=0; i< numLocalTaxa; i++)
                        {
                        for (j=0; j<numLocalTaxa; j++)
                            {
                            if (j == i)
                                tempMatrix[pos(j,newColumn,newRowSize)] = (bitsLongOne << k) ^ 3;
                            else
                                tempMatrix[pos(j,newColumn,newRowSize)] = bitsLongOne << k;
                            }
                        tempSitesOfPat[newChar] = 0;
                        tempChar[newColumn] = -1;
                        newChar++;
                        newColumn++;
                        }
                    }
                }

            if (!strcmp(mp->coding, "Noabsencesites"))
                {
                for (i=0; i<numLocalTaxa; i++)
                    tempMatrix[pos(i,newColumn,newRowSize)] = 1;
                tempSitesOfPat[newChar] = 0;
                tempChar[newColumn] = -1;
                newChar++;
                newColumn++;
                }

            if (!strcmp(mp->coding, "Nopresencesites"))
                {
                for (i=0; i<numLocalTaxa; i++)
                    tempMatrix[pos(i,newColumn,newRowSize)] = 2;
                tempSitesOfPat[newChar] = 0;
                tempChar[newColumn] = -1;
                newChar++;
                newColumn++;
                }
            }

        /* add the normal characters */
        numIncompatible = numIncompatibleChars = 0;
        for (oldColumn=m->compMatrixStart; oldColumn<m->compMatrixStop; oldColumn++)
            {
            isCompat = YES;
            /* first check if the character is supposed to be present */
            if (m->numDummyChars > 0)
                {
                /* set up matrix struct */
                matrix.column = oldColumn;
                /* set up charinfo struct */
                cinfo.dType = mp->dataType;
                cinfo.cType = charInfo[origChar[oldChar]].ctype;
                cinfo.nStates = charInfo[origChar[oldChar]].numStates;
                CheckCharCodingType(&matrix, &cinfo);

                if (!strcmp(mp->coding, "Variable") && cinfo.variable == NO)
                    isCompat = NO;
                else if (!strcmp(mp->coding, "Informative") && cinfo.informative == NO)
                    isCompat = NO;
                else if (!strcmp(mp->coding, "Noabsencesites") && cinfo.constant[0] == YES)
                    isCompat = NO;
                else if (!strcmp(mp->coding, "Nopresencesites") && cinfo.constant[1] == YES)
                    isCompat = NO;
                }

            if (isCompat == NO)
                {
                numIncompatible++;
                numIncompatibleChars += (int) numSitesOfPat[oldChar];
                oldChar++;
                }
            else
                {
                /* add character */
                for (i=0; i<numLocalTaxa; i++)
                    tempMatrix[pos(i,newColumn,newRowSize)] = compMatrix[pos(i,oldColumn,oldRowSize)];
                /* set indices */
                compCharPos[origChar[oldColumn]] = newChar;
                compColPos[origChar[oldColumn]] = newColumn;
                tempSitesOfPat[newChar] = numSitesOfPat[oldChar];
                tempChar[newColumn] = origChar[oldColumn];
                newColumn++;
                if ((oldColumn-m->compMatrixStart+1) % m->nCharsPerSite == 0)
                    {
                    newChar++;
                    oldChar++;
                    }
                }
            }

        /* print a warning if there are incompatible characters */
        if (numIncompatible > 0)
            {
            m->numChars -= numIncompatible;
            m->numUncompressedChars -= numIncompatibleChars;
            numDeleted += numIncompatible;
            if (numIncompatibleChars > 1)
                {
                MrBayesPrint ("%s   WARNING: There are %d characters incompatible with the specified\n", spacer, numIncompatibleChars);
                MrBayesPrint ("%s            coding bias. These characters will be excluded.\n", spacer);
                }
            else
                {
                MrBayesPrint ("%s   WARNING: There is one character incompatible with the specified\n", spacer);
                MrBayesPrint ("%s            coding bias. This character will be excluded.\n", spacer);
                }
            }

        /* update division comp matrix and comp char pointers */
        m->compCharStop = newChar;
        m->compMatrixStop = newColumn;
        m->compCharStart = newChar - m->numChars;
        m->compMatrixStart = newColumn - m->nCharsPerSite * m->numChars;

        }   /* next division */

    /* compress matrix if necessary */
    if (numDeleted > 0)
        {
        for (i=k=0; i<numLocalTaxa; i++)
            {
            for (j=0; j<newRowSize-numDeleted; j++)
                {
                tempMatrix[k++] = tempMatrix[j+i*newRowSize];
                }
            }
        numCompressedChars -= numDeleted;
        compMatrixRowSize -= numDeleted;
        }

    /* free old data, set pointers to new data */
    free (compMatrix);
    free (numSitesOfPat);
    free (origChar);
    
    compMatrix = tempMatrix;
    numSitesOfPat = tempSitesOfPat;
    origChar = tempChar;
    
    tempMatrix = NULL;
    tempSitesOfPat = NULL;
    tempChar = NULL;
    
    /* print new compressed matrix */
#   if  defined (DEBUG_ADDDUMMYCHARS)
    MrBayesPrint ("After adding dummy characters...\n");
    PrintCompMatrix();
#   endif

    return NO_ERROR;

    errorExit:
        if (tempMatrix)
            free (tempMatrix);
        if (tempSitesOfPat)
            free (tempSitesOfPat);
        if (tempChar)
            free (tempChar);

        return ERROR;   
}


/* Allocate space for cpp events */
void AllocateCppEvents (Param *p)
{
    int     i;

    p->nEvents = (int **) SafeCalloc (2*numGlobalChains, sizeof (int *));
    p->nEvents[0] = (int *) SafeCalloc (2*numGlobalChains*(2*numLocalTaxa), sizeof (int));
    for (i=1; i<2*numGlobalChains; i++)
        p->nEvents[i] = p->nEvents[i-1] + (2*numLocalTaxa);
    p->position = (MrBFlt ***) SafeCalloc (2*numGlobalChains, sizeof (MrBFlt **));
    p->position[0] = (MrBFlt **) SafeCalloc (2*numGlobalChains*(2*numLocalTaxa), sizeof (MrBFlt *));
    for (i=1; i<2*numGlobalChains; i++)
        p->position[i] = p->position[i-1] + (2*numLocalTaxa);
    p->rateMult = (MrBFlt ***) SafeCalloc (2*numGlobalChains, sizeof (MrBFlt **));
    p->rateMult[0] = (MrBFlt **) SafeCalloc (2*numGlobalChains*(2*numLocalTaxa), sizeof (MrBFlt *));
    for (i=1; i<2*numGlobalChains; i++)
        p->rateMult[i] = p->rateMult[i-1] + (2*numLocalTaxa);

}


/*----------------------------------------------------------------------------
|
|   AllocateMove: Allocate space for and initialize one applicable move
|
-----------------------------------------------------------------------------*/
MCMCMove *AllocateMove (MoveType *moveType, Param *param)
{
    int         i, j, nameLength;
    char        *partitionDescriptor = "";
    MCMCMove    *temp;

    if ((temp = (MCMCMove *) SafeCalloc (1, sizeof (MCMCMove))) == NULL)
        return (NULL);

    /* calculate length */
    if (strcmp (moveType->paramName, "") == 0)
        nameLength = (int) (strlen (moveType->shortName) + strlen (param->name)) + 10;
    else
        {
        partitionDescriptor = param->name;
        while (*partitionDescriptor != '\0')
            {
            if (*partitionDescriptor == '{')
                break;
            partitionDescriptor++;
            }
        nameLength = (int) (strlen (moveType->shortName) + strlen (moveType->paramName) + strlen (partitionDescriptor)) + 10;
        }
    /* add length of names of subparams */
    if (moveType->subParams == YES)
        {
        for (i=0; i<param->nSubParams; i++)
            nameLength += (int)(strlen(param->subParams[i]->name)) + 1;
        }

    if ((temp->name = (char *) SafeCalloc (nameLength, sizeof (char))) == NULL)
        {
        free (temp);
        return NULL;
        }

    if ((temp->nAccepted = (int *) SafeCalloc (5*numGlobalChains, sizeof (int))) == NULL)
        {
        free (temp->name);
        free (temp);
        return NULL;
        }
    temp->nTried       = temp->nAccepted + numGlobalChains;
    temp->nBatches     = temp->nAccepted + 2*numGlobalChains;
    temp->nTotAccepted = temp->nAccepted + 3*numGlobalChains;
    temp->nTotTried    = temp->nAccepted + 4*numGlobalChains; 
    
    if ((temp->relProposalProb = (MrBFlt *) SafeCalloc (4*numGlobalChains, sizeof (MrBFlt))) == NULL)
        {
        free (temp->nAccepted);
        free (temp->name);
        free (temp);
        return NULL;
        }
    temp->cumProposalProb = temp->relProposalProb + numGlobalChains;
    temp->targetRate = temp->relProposalProb + 2*numGlobalChains;
    temp->lastAcceptanceRate = temp->relProposalProb + 3*numGlobalChains;

    if ((temp->tuningParam = (MrBFlt **) SafeCalloc (numGlobalChains, sizeof (MrBFlt *))) == NULL)
        {
        free (temp->relProposalProb);
        free (temp->nAccepted);
        free (temp->name);
        free (temp);
        return NULL;
        }
    if ((temp->tuningParam[0] = (MrBFlt *) SafeCalloc (moveType->numTuningParams*numGlobalChains, sizeof (MrBFlt))) == NULL)
        {
        free (temp->tuningParam);
        free (temp->relProposalProb);
        free (temp->nAccepted);
        free (temp->name);
        free (temp);
        return NULL;
        }
    for (i=1; i<numGlobalChains; i++)
        temp->tuningParam[i] = temp->tuningParam[0] + (i * moveType->numTuningParams);

    /* set default values */
    if (strcmp(moveType->paramName, "") != 0)
        sprintf (temp->name, "%s(%s%s)", moveType->shortName, moveType->paramName, partitionDescriptor);
    else
        {
        sprintf (temp->name, "%s(%s", moveType->shortName, param->name);
        if (moveType->subParams == YES)
            {
            for (i=0; i<param->nSubParams; i++)
                {
                strcat(temp->name,",");
                strcat(temp->name,param->subParams[i]->name);
                }
            }
        strcat (temp->name,")");
        }
        
    temp->moveType = moveType;
    temp->moveFxn = moveType->moveFxn;
    for (i=0; i<numGlobalChains; i++)
        {
        temp->relProposalProb[i] = moveType->relProposalProb;
        temp->cumProposalProb[i] = 0.0;
        temp->nAccepted[i] = 0;
        temp->nTried[i] = 0;
        temp->nBatches[i] = 0;
        temp->nTotAccepted[i] = 0;
        temp->nTotTried[i] = 0;
        temp->targetRate[i] = moveType->targetRate;
        temp->lastAcceptanceRate[i] = 0.0;
        for (j=0; j<moveType->numTuningParams; j++)
            temp->tuningParam[i][j] = moveType->tuningParam[j];
        }
    return (temp);
}


/*----------------------------------------------------------------------
|
|   AllocateNormalParams: Allocate space for normal parameters
|
-----------------------------------------------------------------------*/
int AllocateNormalParams (void)
{
    int         i, k, nOfParams, nOfIntParams;
    Param       *p;
    
    /* Count the number of param values and subvalues */
    nOfParams = 0;
    nOfIntParams = 0;
    for (k=0; k<numParams; k++)
        {
        nOfParams += params[k].nValues;
        nOfParams += params[k].nSubValues;
        nOfIntParams += params[k].nIntValues;
        }

    /* Set row size and find total number of values */
    paramValsRowSize = nOfParams;
    intValsRowSize = nOfIntParams;
    nOfParams *= (2 * numGlobalChains);
    nOfIntParams *= (2 * numGlobalChains);

    if (memAllocs[ALLOC_PARAMVALUES] == YES)
        {
        paramValues = (MrBFlt *) SafeRealloc ((void *) paramValues, nOfParams * sizeof (MrBFlt));
        for (i=0; i<nOfParams; i++)
            paramValues[i] = 0.0;
        if (nOfIntParams > 0)
            intValues = (int *) SafeRealloc ((void *) intValues, nOfIntParams * sizeof(int));
        }
    else
        {
        paramValues = (MrBFlt *) SafeCalloc (nOfParams, sizeof(MrBFlt));
        if (nOfIntParams > 0)
            intValues = (int *) SafeCalloc (nOfIntParams, sizeof(int));
        else
            intValues = NULL;
        }
    if (!paramValues || (nOfIntParams > 0 && !intValues))
        {
        MrBayesPrint ("%s   Problem allocating paramValues\n", spacer);
        if (paramValues)
            free (paramValues);
        if (intValues)
            free (intValues);
        return ERROR;
        }
    else
        memAllocs[ALLOC_PARAMVALUES] = YES;

    /* set pointers to values for chain 1 state 0            */
    /* this scheme keeps the chain and state values together */
    nOfParams = 0;
    nOfIntParams = 0;
    for (k=0; k<numParams; k++)
        {
        p = &params[k];
        if (p->nValues > 0)
            p->values = paramValues + nOfParams;
        else
            p->values = NULL;
        nOfParams += p->nValues;
        if (p->nSubValues > 0)
            p->subValues = paramValues + nOfParams;
        else
            p->subValues = NULL;
        nOfParams += p->nSubValues;
        if (p->nIntValues > 0)
            p->intValues = intValues + nOfIntParams;
        else
            p->intValues = NULL;
        nOfIntParams += p->nIntValues;
        }
    
    /* allocate space for cpp events */
    for (k=0; k<numParams; k++)
        {
        p = &params[k];
        if (p->paramType == P_CPPEVENTS)
           AllocateCppEvents(p);
        }

    return (NO_ERROR);
}


/*----------------------------------------------------------------------
|
|   AllocateTreeParams: Allocate space for tree parameters
|
-----------------------------------------------------------------------*/
int AllocateTreeParams (void)
{
    int         i, j, k, n, nOfParams, nOfTrees, isRooted, numSubParamPtrs;
    Param       *p, *q;

    /* Count the number of trees and dated trees */
    /* based on branch length parameters */
    /*  One tree is needed for each brlen parameter.
        A topology may apply to several trees; a topology parameter
        contains pointers to all trees it applies to */
    numTrees = 0;
    numTopologies = 0;
    for (k=0; k<numParams; k++)
        {
        if (params[k].paramType == P_BRLENS)
            numTrees++;
        else if (params[k].paramType == P_TOPOLOGY)
            numTopologies++;
        }

    /* We need to add the trees that do not have any branch lengths */
    /* that is, the pure parsimony model trees, and the species trees */
    for (k=0; k<numParams; k++)
        {
        if (params[k].paramType == P_TOPOLOGY)
            {
            if (!strcmp(modelParams[params[k].relParts[0]].parsModel, "Yes"))
                numTrees++;
            }
        else if (params[k].paramType == P_SPECIESTREE)
            {
            numTopologies++;
            numTrees++;
            }
        }

    /* Finally add subparam pointers for relaxed clock parameters and species trees */
    numSubParamPtrs = 0;
    for (k=0; k<numParams; k++)
        {
        if (params[k].paramType == P_TOPOLOGY && params[k].paramId == TOPOLOGY_SPECIESTREE)
            numSubParamPtrs += 1;
        else if (params[k].paramType == P_BRLENS)
            numSubParamPtrs += 1;
        else if (params[k].paramType == P_CPPEVENTS)
            numSubParamPtrs += 3;
        else if (params[k].paramType == P_TK02BRANCHRATES)
            numSubParamPtrs += 2;
        else if (params[k].paramType == P_IGRBRANCHRATES)
            numSubParamPtrs += 2;
        else if (params[k].paramType == P_MIXEDBRCHRATES)
            numSubParamPtrs += 2;
        }
        
    /* Allocate space for trees and subparam pointers */
    if (memAllocs[ALLOC_MCMCTREES] == YES)
        {
        free (subParamPtrs);
        free (mcmcTree);
        subParamPtrs = NULL;
        mcmcTree = NULL;
        memAllocs[ALLOC_MCMCTREES] = NO;
        }
    subParamPtrs = (Param **) SafeCalloc (numSubParamPtrs, sizeof (Param *));
    mcmcTree = (Tree **) SafeCalloc (numTrees * 2 * numGlobalChains, sizeof (Tree *));
    if (!subParamPtrs || !mcmcTree)
        {
        if (subParamPtrs) free (subParamPtrs);
        if (mcmcTree) free (mcmcTree);
        subParamPtrs = NULL;
        mcmcTree = NULL;
        MrBayesPrint ("%s   Problem allocating mcmc trees\n", spacer);
        return (ERROR);
        }
    else
        memAllocs[ALLOC_MCMCTREES] = YES;

    /* Initialize number of subparams, just in case */
    for (k=0; k<numParams; k++)
        params[k].nSubParams = 0;
    
    /* Count number of trees (brlens) for each topology or species tree */
    for (k=0; k<numParams; k++)
        {
        p = &params[k];
        if (params[k].paramType == P_BRLENS)
            {
            q = modelSettings[p->relParts[0]].topology;
            q->nSubParams++;
            if (p->printParam == YES)
                q->nPrintSubParams++;
            }
        else if (params[k].paramType == P_TOPOLOGY)
            {
            q = modelSettings[p->relParts[0]].speciesTree;
            if (q != NULL)
                q->nSubParams++;
            }
        }

    /* Make sure there is also one subparam for a parsimony tree */
    for (k=0; k<numParams; k++)
        if (params[k].paramType == P_TOPOLOGY)
            {
            p = &params[k];
            if (p->nSubParams == 0)
                p->nSubParams = 1;
            }

    /* Count subparams for relaxed clock parameters */
    for (k=0; k<numParams; k++)
        {
        p = &params[k];
        if (p->paramType == P_CPPEVENTS)
            {
            q = modelSettings[p->relParts[0]].cppRate;
            q->nSubParams++;
            q = modelSettings[p->relParts[0]].cppMultDev;
            q->nSubParams++;
            q = modelSettings[p->relParts[0]].brlens;
            q->nSubParams++;
            }
        else if (p->paramType == P_TK02BRANCHRATES)
            {
            q = modelSettings[p->relParts[0]].tk02var;
            q->nSubParams++;
            q = modelSettings[p->relParts[0]].brlens;
            q->nSubParams++;
            }
        else if (p->paramType == P_IGRBRANCHRATES)
            {
            q = modelSettings[p->relParts[0]].igrvar;
            q->nSubParams++;
            q = modelSettings[p->relParts[0]].brlens;
            q->nSubParams++;
            }
        else if (p->paramType == P_MIXEDBRCHRATES)
            {
            q = modelSettings[p->relParts[0]].mixedvar;
            q->nSubParams++;
            q = modelSettings[p->relParts[0]].brlens;
            q->nSubParams++;
            }
        }

    /* set pointers to subparams */
    nOfParams = 0;
    for (k=0; k<numParams; k++)
        {
        p = &params[k];
        if (p->nSubParams > 0)
            {
            p->subParams = subParamPtrs + nOfParams;
            nOfParams += p->nSubParams;
            }
        }
    assert (nOfParams == numSubParamPtrs);

    /* Set brlens param pointers and tree values */
    /* the scheme below keeps trees for the same state and chain together */
    nOfTrees = 0;
    for (k=0; k<numParams; k++)
        {
        p = &params[k];
        if ((p->paramType == P_BRLENS) ||
            (p->paramType == P_TOPOLOGY && p->paramId == TOPOLOGY_PARSIMONY_UNIFORM) ||
            (p->paramType == P_TOPOLOGY && p->paramId == TOPOLOGY_PARSIMONY_CONSTRAINED) ||
            (p->paramType == P_SPECIESTREE))
            {
            /* allocate space for trees and initialize trees */
            p->treeIndex = nOfTrees;
            p->tree = mcmcTree + nOfTrees;
            nOfTrees++;
            }
        }

    /* Set topology params and associated brlen subparams */
    for (k=0; k<numParams; k++)
        {
        p = &params[k];
        if (p->paramType == P_TOPOLOGY)
            {
            if (p->paramId == TOPOLOGY_PARSIMONY_UNIFORM ||
                p->paramId == TOPOLOGY_PARSIMONY_CONSTRAINED)
                /* pure parsimony topology case */
                {
                /* there is no brlen subparam */
                /* so let subparam point to the param itself */
                q = p->subParams[0] = p;
                /* p->tree and p->treeIndex have been set above */
                }
            else
                {
                /* first set brlens pointers for any parsimony partitions */
                for (i=j=0; i<p->nRelParts; i++)
                    {
                    if (modelSettings[p->relParts[i]].parsModelId == YES)
                        {
                        modelSettings[p->relParts[i]].brlens = p;
                        }
                    }

                /* now proceed with pointer assignment */
                q = modelSettings[p->relParts[0]].brlens;
                n = 0;  /* number of stored subParams */
                i = 0;  /* relevant partition number  */
                while (i < p->nRelParts)
                    {
                    for (j=0; j<n; j++)
                        if (q == p->subParams[j])
                            break;
                    
                    if (j == n && q != p)   /* a new tree (brlens) for this topology */
                        {
                        p->subParams[n++] = q;
                        }
                    q = modelSettings[p->relParts[++i]].brlens;
                    }
                
                p->tree = p->subParams[0]->tree;
                p->treeIndex = p->subParams[0]->treeIndex;
                }
            }
        else if (p->paramType == P_SPECIESTREE)
            {
            /* now proceed with pointer assignment */
            q = modelSettings[p->relParts[0]].topology;
            n = 0;  /* number of stored subParams */
            i = 0;  /* relevant partition number  */
            while (i < p->nRelParts)
                {
                for (j=0; j<n; j++)
                    if (q == p->subParams[j])
                        break;

                if (j == n && q != p)   /* a new topology for this species tree */
                    {
                    p->subParams[n++] = q;
                    }
                q = modelSettings[p->relParts[++i]].topology;
                }
            }
        }

    /* Check for constraints */
    for (k=0; k<numParams; k++)
        {
        p = &params[k];
        if (p->paramType == P_TOPOLOGY)
            {
            if (!strcmp(modelParams[p->relParts[0]].topologyPr, "Constraints"))
                {
                for (i=0; i<p->nSubParams; i++)
                    {
                    q = p->subParams[i];
                    q->checkConstraints = YES;
                    }
                }
            else
                {
                for (i=0; i<p->nSubParams; i++)
                    {
                    q = p->subParams[i];
                    q->checkConstraints = NO;
                    }
                }
            }
        }

    /* update paramId */
    for (k=0; k<numParams; k++)
        {
        p = &params[k];
        if (p->paramType == P_TOPOLOGY)
            {
            if (p->nSubParams > 1)
                {
                if (p->paramId == TOPOLOGY_NCL_UNIFORM_HOMO)
                    p->paramId = TOPOLOGY_NCL_UNIFORM_HETERO;
                else if (p->paramId == TOPOLOGY_NCL_CONSTRAINED_HOMO)
                    p->paramId = TOPOLOGY_NCL_CONSTRAINED_HETERO;
                else if (p->paramId == TOPOLOGY_NCL_FIXED_HOMO)
                    p->paramId = TOPOLOGY_NCL_FIXED_HETERO;
                else
                    {
                    MrBayesPrint ("%s   A clock tree cannot have more than one set of branch lengths\n", spacer);
                    printf ("nparam:%d paramid:%d",p->nSubParams,p->paramId);
                    return (ERROR);
                    }
                }
            }
        }

    /* finally initialize trees */
    for (k=0; k<numParams; k++)
        {
        p = &params[k];
        if (p->paramType == P_BRLENS)
            {
            /* find type of tree */
            if (!strcmp(modelParams[p->relParts[0]].brlensPr,"Clock"))
                isRooted = YES;
            else
                isRooted = NO;

            if (InitializeChainTrees (p, 0, numGlobalChains, isRooted) == ERROR)
                return (ERROR);
            }
        else if (p->paramType == P_SPECIESTREE)
            {
            if (InitializeChainTrees (p, 0, numGlobalChains, YES) == ERROR)
                return (ERROR);
            }
        }

    /* now initialize subparam pointers for relaxed clock models */
    /* use nSubParams to point to the next available subParam by first
       resetting all nSubParams to 0 */
    for (k=0; k<numParams; k++)
        {
        p = &params[k];
        if (p->paramType == P_CPPRATE ||
            p->paramType == P_CPPMULTDEV ||
            p->paramType == P_BRLENS ||
            p->paramType == P_TK02VAR ||
            p->paramType == P_IGRVAR ||
            p->paramType == P_MIXEDVAR)
            p->nSubParams = 0;
        }
    for (k=0; k<numParams; k++)
        {
        p = &params[k];
        if (p->paramType == P_CPPEVENTS)
            {
            q = modelSettings[p->relParts[0]].cppRate;
            q->subParams[q->nSubParams++] = p;
            q = modelSettings[p->relParts[0]].cppMultDev;
            q->subParams[q->nSubParams++] = p;
            q = modelSettings[p->relParts[0]].brlens;
            q->subParams[q->nSubParams++] = p;
            p->treeIndex = q->treeIndex;
            p->tree = q->tree;
            if (p->printParam == YES)
                q->nPrintSubParams++;
            }
        else if (p->paramType == P_TK02BRANCHRATES)
            {
            q = modelSettings[p->relParts[0]].tk02var;
            q->subParams[q->nSubParams++] = p;
            q = modelSettings[p->relParts[0]].brlens;
            q->subParams[q->nSubParams++] = p;
            p->treeIndex = q->treeIndex;
            p->tree = q->tree;
            if (p->printParam == YES)
                q->nPrintSubParams++;
            }
        else if (p->paramType == P_IGRBRANCHRATES)
            {
            q = modelSettings[p->relParts[0]].igrvar;
            q->subParams[q->nSubParams++] = p;
            q = modelSettings[p->relParts[0]].brlens;
            q->subParams[q->nSubParams++] = p;
            p->treeIndex = q->treeIndex;
            p->tree = q->tree;
            if (p->printParam == YES)
                q->nPrintSubParams++;
            }
        else if (p->paramType == P_MIXEDBRCHRATES)
            {
            q = modelSettings[p->relParts[0]].mixedvar;
            q->subParams[q->nSubParams++] = p;
            q = modelSettings[p->relParts[0]].brlens;
            q->subParams[q->nSubParams++] = p;
            p->treeIndex = q->treeIndex;
            p->tree = q->tree;
            if (p->printParam == YES)
                q->nPrintSubParams++;
            }
        }

    return (NO_ERROR);
}


int AreDoublesEqual (MrBFlt x, MrBFlt y, MrBFlt tol)
{
    if ((x - y) < -tol || (x - y) > tol)
        return (NO);
    else
        return (YES);
}


int ChangeNumChains (int from, int to)
{
    int         i, i1, j, k, m, st, nRuns, fromIndex, toIndex, run, chn, *tempIntVals, nCppEventParams, *toEvents, *fromEvents;
    MCMCMove    **tempMoves, *fromMove, *toMove;
    Tree        **tempTrees;
    MrBFlt      *tempVals, **toRateMult, **toPosition, **fromRateMult, **fromPosition, *stdStateFreqsOld;
    Param       *p, *q, *cppEventParams = NULL;
    Tree        **oldMcmcTree, *tree;

    if (from == to)
        return (NO_ERROR);

    /* set new number of chains */
    chainParams.numChains = to;
    nRuns = chainParams.numRuns;
    numGlobalChains = chainParams.numRuns * chainParams.numChains;

    /* Do the normal parameters */  
    /* first save old values */
    tempVals = paramValues;
    paramValues = NULL;
    tempIntVals = intValues;
    intValues = NULL;
    memAllocs[ALLOC_PARAMS] = NO;
    /* .. and old cpp events parameters */
    nCppEventParams = 0;
    for (i=0; i<numParams; i++)
        {
        p = &params[i];
        if (p->paramType == P_CPPEVENTS)
            nCppEventParams++;
        }
    cppEventParams = (Param *) SafeCalloc (nCppEventParams, sizeof(Param));
    for (i=0; i<nCppEventParams; i++)
        {
        cppEventParams[i].paramType = P_CPPEVENTS;
        AllocateCppEvents (&cppEventParams[i]);
        }
    for (i=j=0; i<numParams; i++)
        {
        p = &params[i];
        if (p->paramType == P_CPPEVENTS)
            {
            cppEventParams[j].nEvents = p->nEvents;
            p->nEvents = NULL;
            cppEventParams[j].position = p->position;
            p->position = NULL;
            cppEventParams[j].rateMult = p->rateMult;
            p->rateMult = NULL;
            j++;
            }
        }
    if (AllocateNormalParams () == ERROR)
        return (ERROR);

    /* then fill all params */
    FillNormalParams (&globalSeed, 0, numGlobalChains);
    
    /* finally overwrite with old values if present */
    for (run=0; run<nRuns; run++)
        {
        for (chn=0; chn<from; chn++)
            {
            if (chn < to)
                {
                fromIndex = (run*from + chn)*2*paramValsRowSize;
                toIndex = (run*to + chn)*2*paramValsRowSize;
                for (i=0; i<2*paramValsRowSize; i++)
                    paramValues[toIndex++] = tempVals[fromIndex++];
                fromIndex = (run*from + chn)*2*intValsRowSize;
                toIndex = (run*to + chn)*2*intValsRowSize;
                for (i=0; i<2*intValsRowSize; i++)
                    intValues[toIndex++] = tempIntVals[fromIndex++];
                for (i=i1=0; i<numParams; i++)
                    {
                    p = &params[i];
                    if (p->paramType == P_CPPEVENTS)
                        {
                        fromIndex = 2*(run*from + chn);
                        toIndex = 2*(run*to + chn);
                        fromEvents = cppEventParams[i1].nEvents[fromIndex];
                        toEvents = p->nEvents[toIndex];
                        fromPosition = cppEventParams[i1].position[fromIndex];
                        toPosition = p->position[toIndex];
                        fromRateMult = cppEventParams[i1].rateMult[fromIndex];
                        toRateMult = p->rateMult[toIndex];
                        for (j=0; j<2*numLocalTaxa; j++)
                            {
                            toEvents[j] = fromEvents[j];
                            toPosition[j] = (MrBFlt *) SafeRealloc ((void *)toPosition[j], toEvents[j]*sizeof(MrBFlt));
                            toRateMult[j] = (MrBFlt *) SafeRealloc ((void *)toRateMult[j], toEvents[j]*sizeof(MrBFlt));
                            for (k=0; k<toEvents[j]; k++)
                                {
                                toPosition[j][k] = fromPosition[j][k];
                                toRateMult[j][k] = fromRateMult[j][k];
                                }
                            }
                        i1++;
                        }
                    }
                assert (nCppEventParams==i1);
                }
            }
        }
    
    /* and free up space */
    free (tempVals);
    if (intValsRowSize > 0)
        free (tempIntVals);
    for (i=0; i<nCppEventParams; i++)
        {
        numGlobalChains = chainParams.numRuns * from; /* Revert to the old value to clean old Cpp events in FreeCppEvents() */
        FreeCppEvents(&cppEventParams[i]);
        numGlobalChains = chainParams.numRuns * chainParams.numChains; /*Set to proper value again*/
        }
    if (nCppEventParams > 0)
        free (cppEventParams);

    /* then do the trees (they cannot be done before the parameters because otherwise FillTreeParams will overwrite
       relaxed clock parameters that need to be saved) */

    /* reallocate trees */
    tempTrees = (Tree **) SafeCalloc (2*nRuns*from*numTrees, sizeof(Tree *));
    for (i=0; i<2*nRuns*from*numTrees; i++)
        tempTrees[i] = mcmcTree[i];
    oldMcmcTree = mcmcTree;
    mcmcTree = (Tree **) SafeRealloc ((void *)(mcmcTree), (size_t)(2*numGlobalChains*numTrees*sizeof(Tree*)));
    for (i=0; i<2*nRuns*to*numTrees; i++)
        mcmcTree[i] = NULL;

    /* move the old trees over */
    for (run=0; run<nRuns; run++)
        {
        for (chn=0; chn<from; chn++)
            {
            if (chn >= to)
                continue;
            /*Here we move only one tree per chain/state?! Should not we move numTrees??*/
            fromIndex = 2*(run*from + chn)  * numTrees;
            toIndex   = 2*(run*to   + chn)  * numTrees;
            for (k=0;k<2*numTrees;k++)
                {
                mcmcTree[toIndex+k]    = tempTrees[fromIndex+k];
                tempTrees[fromIndex+k] = NULL;
                }
            }
        }

    /* remove any remaining old trees */
    for (i=0; i<2*nRuns*from*numTrees; i++)
        if (tempTrees[i] != NULL)
            FreeTree (tempTrees[i]);
    free (tempTrees);

    /* now fill in the tree parameters */
    for (i=0; i<numParams; i++)
        {
        p = &params[i];
        if (p->paramType == P_TOPOLOGY)
            {
            p->tree += (mcmcTree - oldMcmcTree);    /* calculate new address */
            for (j=0; j<p->nSubParams; j++)
                {
                q = p->subParams[j];
                assert (q->paramType==P_BRLENS);
                q->tree += (mcmcTree - oldMcmcTree);    /* calculate new address */
                if (to > from)
                    for (run=0; run<nRuns; run++)
                        {
                        /*rename old trees because each run has more chains*/
                        for (m=0; m<from; m++)
                            {
                            for (st=0; st<2; st++)
                                {
                                tree = GetTree (q,run*to + m, st);
                                if (numTrees > 1)
                                    sprintf (tree->name, "mcmc.tree%d_%d", p->treeIndex+1, run*to + m +1);
                                else /* if (numTrees == 1) */
                                    sprintf (tree->name, "mcmc.tree_%d", run*to + m +1);
                                }
                            }
                        InitializeChainTrees (q, run*to + from, run*to + to , GetTree (q, 0, 0)->isRooted);
                        }
                }
            }
        else if (p->paramType == P_CPPEVENTS || p->paramType == P_TK02BRANCHRATES || p->paramType == P_IGRBRANCHRATES || p->paramType == P_MIXEDBRCHRATES)
            p->tree += (mcmcTree - oldMcmcTree);
        else
            assert (p->paramType==P_BRLENS || p->tree==NULL);
        }

    
    /* fill new tree parameters */
    if (to > from)
        {
        for (run=0; run<nRuns; run++)
            {
            for (chn=from; chn<to; chn++)
                {
                toIndex = run*to + chn;
                FillTreeParams (&globalSeed, toIndex, toIndex+1);
                }
            }
        }

    /* fix stationary frequencies for standard data */
    if   (stdStateFreqsRowSize > 0)
        {
        assert (memAllocs[ALLOC_STDSTATEFREQS] == YES);
        stdStateFreqsOld=stdStateFreqs;
        stdStateFreqs = (MrBFlt *) SafeMalloc ((size_t)stdStateFreqsRowSize * 2 * numGlobalChains * sizeof (MrBFlt));
        if (!stdStateFreqs)
            {
            MrBayesPrint ("%s   Problem reallocating stdStateFreqs\n", spacer);
            return (ERROR);
            }

        /* set pointers */
        for (k=0; k<numParams; k++)
            {
            p = &params[k];
            if (p->paramType != P_PI || modelParams[p->relParts[0]].dataType != STANDARD)
                continue;
            p->stdStateFreqs += stdStateFreqs-stdStateFreqsOld;
            }
        
        for (run=0; run<nRuns; run++)
            {
            /* copy old chains values*/
            for (chn=0; chn<from; chn++)
                {
                if (chn >= to)
                    break;

                fromIndex = 2*(run*from + chn)*stdStateFreqsRowSize;
                toIndex = 2*(run*to + chn)*stdStateFreqsRowSize;
                for (k=0;k<2*stdStateFreqsRowSize;k++)
                    {
                    stdStateFreqs[toIndex+k]=stdStateFreqsOld[fromIndex+k];
                    }
                }
            /* set new chains */
            FillStdStateFreqs (run*to+from, run*to+to, &globalSeed);
            }
        free(stdStateFreqsOld);
    }

    /* Do the moves */
    /* first allocate space and set up default moves */
    tempMoves = moves;
    moves = NULL;
    memAllocs[ALLOC_MOVES] = NO;
    SetMoves ();
    
    /* then overwrite with old values if present */
    for (i=0; i<numApplicableMoves; i++)
        {
        toMove = moves[i];
        fromMove = tempMoves[i];
        for (run=0; run<nRuns; run++)
            {
            for (chn=0; chn<from; chn++)
                {
                if (chn < to)
                    {
                    fromIndex = run*from + chn;
                    toIndex = run*to + chn;
                    toMove->relProposalProb[toIndex] = fromMove->relProposalProb[fromIndex];
                    for (j=0; j<toMove->moveType->numTuningParams; j++)
                        {
                        toMove->tuningParam[toIndex][j] = fromMove->tuningParam[fromIndex][j];
                        }
                    }
                }
            }
        }
    
    /* and free up space */
    for (i=0; i<numApplicableMoves; i++)
        FreeMove (tempMoves[i]);
    free (tempMoves);
    
    return (NO_ERROR);
}


int ChangeNumRuns (int from, int to)
{
    int         i, i1, j, k, n, nChains;
    Param       *p, *q;
    MoveType    *mvt;
    Tree        **oldMcmcTree;
    MrBFlt      *oldParamValues;
    MrBFlt      *stdStateFreqsOld;
    int         *oldintValues;

    if (from == to)
        return (NO_ERROR);

#if 0
    for (i=0; i<numParams; i++)
        {
        p = &params[i];
        if (p->paramType == P_CPPEVENTS)
            {
            printf ("Trees before changing number of runs\n");
            for (j=0; j<numGlobalChains; j++)
                {
                printf ("Event tree for chain %d\n", j+1);
                for (k=0; k<2*numLocalTaxa; k++)
                    {
                    printf ("%d -- %d:", k, p->nEvents[2*j][k]);
                    for (i1=0; i1<p->nEvents[2*j][k]; i1++)
                        {
                        if (i1 == 0)
                            printf (" (%lf %lf,", p->position[2*j][k], p->rateMult[2*j][k]);
                        else if (i1 == p->nEvents[2*j][k]-1)
                            printf (" %lf %lf)", p->position[2*j][k], p->rateMult[2*j][k]);
                        else
                            printf (" %lf %lf,", p->position[2*j][k], p->rateMult[2*j][k]);
                        }
                    printf ("\n");
                    }
                for (k=0; k<2*numLocalTaxa; k++)
                    {
                    printf ("%d -- %d:", k, p->nEvents[2*j][k]);
                    for (i1=0; i1<p->nEvents[2*j+1][k]; i1++)
                        {
                        if (i1 == 0)
                            printf (" (%lf %lf,", p->position[2*j+1][k], p->rateMult[2*j+1][k]);
                        else if (i1 == p->nEvents[2*j][k]-1)
                            printf (" %lf %lf)", p->position[2*j+1][k], p->rateMult[2*j+1][k]);
                        else
                            printf (" %lf %lf,", p->position[2*j+1][k], p->rateMult[2*j+1][k]);
                        }
                    printf ("\n");
                    }
                }
            }
        }
#endif

    /* set new number of runs */
    chainParams.numRuns = to;
    nChains = chainParams.numChains;
    numGlobalChains = chainParams.numRuns * chainParams.numChains;

    /* do the trees, free tree's memory if we reduce number of trees. */
    for (i=to*2*nChains*numTrees; i<from*2*nChains*numTrees; i++)
        {
        FreeTree (mcmcTree[i]);
        }
    oldMcmcTree = mcmcTree;
    mcmcTree = (Tree **) SafeRealloc ((void *) mcmcTree, numTrees * 2 * numGlobalChains * sizeof (Tree *));
    if (mcmcTree == NULL)
        {
        memAllocs[ALLOC_MCMCTREES] = NO;
        MrBayesPrint ("%s   Problem reallocating mcmcTree\n", spacer);
        return (ERROR);
        }

    for (i=from*2*nChains*numTrees; i<to*2*nChains*numTrees; i++)
        {
        mcmcTree[i]=NULL;
        }  
    /* then the cppevents parameters */
    for (i1=0; i1<numParams; i1++)
        {
        p = &params[i1];
        if (p->paramType == P_CPPEVENTS)
            {
            p->nEvents = (int **) SafeRealloc ((void *)p->nEvents, 2*numGlobalChains*sizeof (int *));
            p->nEvents[0] = (int *) SafeRealloc ((void *)p->nEvents[0], 2*numGlobalChains*(2*numLocalTaxa)*sizeof (int));
            for (i=1; i<2*numGlobalChains; i++)
                p->nEvents[i] = p->nEvents[i-1] + (2*numLocalTaxa);
            if (from > to)
                {
                for (j=numGlobalChains; j<from*nChains; j++)
                    {
                    for (k=0; k<2*numLocalTaxa; k++)
                        {
                        free (p->position[2*j+0][k]);
                        p->position[2*j+0][k] = NULL;
                        free (p->rateMult[2*j+0][k]);
                        p->rateMult[2*j+0][k] = NULL;
                        }
                    }
                }
            p->position = (MrBFlt ***) SafeRealloc ((void *)p->position, 2*numGlobalChains*sizeof (MrBFlt **));
            p->position[0] = (MrBFlt **) SafeRealloc ((void *)p->position[0], 2*numGlobalChains*(2*numLocalTaxa)*sizeof (MrBFlt *));
            for (i=1; i<2*numGlobalChains; i++)
                p->position[i] = p->position[i-1] + (2*numLocalTaxa);
            p->rateMult = (MrBFlt ***) SafeRealloc ((void *)p->rateMult, 2*numGlobalChains*sizeof (MrBFlt **));
            p->rateMult[0] = (MrBFlt **) SafeRealloc ((void *)p->rateMult[0], 2*numGlobalChains*(2*numLocalTaxa)*sizeof (MrBFlt *));
            for (i=1; i<2*numGlobalChains; i++)
                p->rateMult[i] = p->rateMult[i-1] + (2*numLocalTaxa);
            if (to > from)
                {
                for (j=from*nChains; j<numGlobalChains; j++)
                    {
                    for (k=0; k<2*numLocalTaxa; k++)
                        {
                        p->nEvents[2*j+0][k] = 0;
                        p->position[2*j+0][k] = NULL;
                        p->rateMult[2*j+0][k] = NULL;
                        p->nEvents[2*j+1][k] = 0;
                        p->position[2*j+1][k] = NULL;
                        p->rateMult[2*j+1][k] = NULL;
                        }
                    }
                }
            }
        }
    /* and finally the normal parameters */
    oldParamValues = paramValues;
    paramValues = (MrBFlt *) SafeRealloc ((void *) paramValues, paramValsRowSize * 2 * numGlobalChains * sizeof (MrBFlt));
    oldintValues = intValues;
    intValues = (int *) SafeRealloc ((void *) intValues, intValsRowSize * 2 * numGlobalChains * sizeof (int));
    if (paramValues == NULL)
        {
        memAllocs[ALLOC_PARAMVALUES] = NO;
        MrBayesPrint ("%s   Problem reallocating paramValues\n", spacer);
        return (ERROR);
        }
    for (i=0; i<numParams; i++)
        {
        params[i].values += (paramValues - oldParamValues);
        params[i].subValues += (paramValues - oldParamValues);
        params[i].intValues += (intValues - oldintValues);
        }

    /* fill new chains paramiters with appropriate values */
    if (to > from)
        FillNormalParams (&globalSeed, from*nChains, to*nChains);

    /* now fill in the tree parameters */
    for (i=0; i<numParams; i++)
        {
        p = &params[i];
        if (p->paramType == P_TOPOLOGY)
            {
            p->tree += (mcmcTree - oldMcmcTree);    /* calculate new address */
            for (j=0; j<p->nSubParams; j++)
                {
                q = p->subParams[j];
                assert (q->paramType==P_BRLENS);
                q->tree += (mcmcTree - oldMcmcTree);    /* calculate new address */
                InitializeChainTrees (q, from*nChains, to*nChains, GetTree (q, 0, 0)->isRooted);
                }
            }
        else if (p->paramType == P_CPPEVENTS || p->paramType == P_TK02BRANCHRATES || p->paramType == P_IGRBRANCHRATES || p->paramType == P_MIXEDBRCHRATES)
            p->tree += (mcmcTree - oldMcmcTree);
        }

    FillTreeParams (&globalSeed, from*nChains, to*nChains);

    /* fix stationary frequencies for standard data */
    if (stdStateFreqsRowSize > 0)
        {
        assert (memAllocs[ALLOC_STDSTATEFREQS] == YES);
        stdStateFreqsOld=stdStateFreqs;
        stdStateFreqs = (MrBFlt *) SafeRealloc ((void *) stdStateFreqs, stdStateFreqsRowSize * 2 * numGlobalChains * sizeof (MrBFlt));
        if (!stdStateFreqs)
            {
            MrBayesPrint ("%s   Problem reallocating stdStateFreqs\n", spacer);
            return (ERROR);
            }
        
        /* set pointers */
        for (k=n=0; k<numParams; k++)
            {
            p = &params[k];
            if (p->paramType != P_PI || modelParams[p->relParts[0]].dataType != STANDARD)
                continue;
            p->stdStateFreqs += stdStateFreqs-stdStateFreqsOld;
            }
        
        FillStdStateFreqs (from*nChains, to*nChains, &globalSeed);
        }

    /* do the moves */
    for (i=0; i<numApplicableMoves; i++)
        {
        mvt = moves[i]->moveType;
        moves[i]->tuningParam = (MrBFlt **) SafeRealloc ((void *) moves[i]->tuningParam, (size_t) (numGlobalChains * sizeof (MrBFlt *)));
        moves[i]->tuningParam[0] = (MrBFlt *) SafeRealloc ((void *) moves[i]->tuningParam[0], (size_t) (numGlobalChains * mvt->numTuningParams * sizeof (MrBFlt)));
        for (j=1; j<numGlobalChains; j++)
            moves[i]->tuningParam[j] = moves[i]->tuningParam[0] + j * mvt->numTuningParams;
        moves[i]->relProposalProb = (MrBFlt *) SafeRealloc ((void *) moves[i]->relProposalProb, (size_t) (4 * numGlobalChains * sizeof (MrBFlt)));
        moves[i]->cumProposalProb = moves[i]->relProposalProb + numGlobalChains;
        moves[i]->targetRate = moves[i]->relProposalProb + 2*numGlobalChains;
        moves[i]->lastAcceptanceRate = moves[i]->relProposalProb + 3*numGlobalChains;
        moves[i]->nAccepted = (int *) SafeRealloc ((void *) moves[i]->nAccepted, (size_t) (5 * numGlobalChains * sizeof (int)));
        moves[i]->nTried = moves[i]->nAccepted + numGlobalChains;
        moves[i]->nBatches = moves[i]->nAccepted + 2*numGlobalChains;
        moves[i]->nTotAccepted = moves[i]->nAccepted + 3*numGlobalChains;
        moves[i]->nTotTried    = moves[i]->nAccepted + 4*numGlobalChains;
        /* initialize all values to default */
        for (j=0; j<numGlobalChains; j++)
            {
            moves[i]->nAccepted[j] = 0;
            moves[i]->nTried[j] = 0;
            moves[i]->nBatches[j] = 0;
            moves[i]->nTotAccepted[j] = 0;
            moves[i]->nTotTried[j] = 0;
            moves[i]->relProposalProb[j] = mvt->relProposalProb;
            moves[i]->cumProposalProb[j] = 0.0;
            moves[i]->lastAcceptanceRate[j] = 0.0;
            for (k=0; k<mvt->numTuningParams; k++)
                moves[i]->tuningParam[j][k] = mvt->tuningParam[k];
            moves[i]->targetRate[j] = mvt->targetRate;
            }
        }

#if 0
    for (i=0; i<numParams; i++)
        {
        p = &params[i];
        if (p->paramType == P_CPPEVENTS)
            {
            printf ("Trees after changing number of runs\n");
            for (j=0; j<numGlobalChains; j++)
                {
                printf ("Event tree for chain %d\n", j+1);
                for (k=0; k<2*numLocalTaxa; k++)
                    {
                    printf ("%d -- %d:", k, p->nEvents[2*j][k]);
                    assert (p->nEvents[2*j] >= 0);
                    for (i1=0; i1<p->nEvents[2*j][k]; i1++)
                        {
                        if (i1 == 0)
                            printf (" (%lf %lf,", p->position[2*j][k], p->rateMult[2*j][k]);
                        else if (i1 == p->nEvents[2*j][k]-1)
                            printf (" %lf %lf)", p->position[2*j][k], p->rateMult[2*j][k]);
                        else
                            printf (" %lf %lf,", p->position[2*j][k], p->rateMult[2*j][k]);
                        }
                    printf ("\n");
                    }
                for (k=0; k<2*numLocalTaxa; k++)
                    {
                    printf ("%d -- %d:", k, p->nEvents[2*j+1][k]);
                    assert (p->nEvents[2*j+1] >= 0);
                    for (i1=0; i1<p->nEvents[2*j+1][k]; i1++)
                        {
                        if (i1 == 0)
                            printf (" (%lf %lf,", p->position[2*j+1][k], p->rateMult[2*j+1][k]);
                        else if (i1 == p->nEvents[2*j][k]-1)
                            printf (" %lf %lf)", p->position[2*j+1][k], p->rateMult[2*j+1][k]);
                        else
                            printf (" %lf %lf,", p->position[2*j+1][k], p->rateMult[2*j+1][k]);
                        }
                    printf ("\n");
                    }
                }
            }
        }
#endif

    return (NO_ERROR);
}


/*-----------------------------------------------------------
|
|   CheckCharCodingType: check if character is parsimony-
|       informative, variable, or constant
|
-----------------------------------------------------------*/
void CheckCharCodingType (Matrix *m, CharInfo *ci)
{
    int         i, j, k, x, n1[10], n2[10], largest, smallest, numPartAmbig,
                numConsidered, numInformative, lastInformative=0, uniqueBits,
                newPoss, oldPoss;
    BitsLong    combinations[2048], *tempComb, *newComb, *oldComb, bitsLongOne=1;

    /* set up comb pointers */
    oldComb = combinations;
    newComb = oldComb + 1024;

    /* set counters to 0 */
    numPartAmbig = numConsidered = 0;

    /* set variable and informative to yes */
    ci->variable = ci->informative = YES;

    /* set constant to no and state counters to 0 for all states */
    for (i=0; i<10; i++)
        {
        ci->constant[i] = NO;
        n1[i] = n2[i] = 0;
        }

    for (i=0; i<m->nRows; i++)
        {
        /* retrieve character */
        x = (int) m->origin[m->column + i*m->rowSize];

        /* add it to counters if not all ambiguous */
        if (NBits(x) < ci->nStates)
            {
            numConsidered++;
            if (NBits(x) > 1)
                numPartAmbig++;
            for (j=0; j<10; j++)
                {
                if (((bitsLongOne<<j) & x) != 0)
                    {   
                    n1[j]++;
                    if (NBits(x) == 1)
                        n2[j]++;
                    }
                }
            }
        }

    /* if the ambig counter for any state is equal to the number of considered
       states, then set constant for that state and set variable and informative to no */
    for (i=0; i<10; i++)
        {
        if (n1[i] == numConsidered)
            {
            ci->constant[i] = YES;
            ci->variable = ci->informative = NO;
            }
        }

    /* return if variable is no or if a restriction site char */
    if (ci->variable == NO || ci->dType == RESTRICTION)
        return;

    /* the character is either (variable and uninformative) or informative */
    
    /* first consider unambiguous characters */
    /* find smallest and largest unambiguous state for this character */
    smallest = 9;
    largest = 0;
    for (i=0; i<10; i++)
        {
        if (n2[i] > 0)
            {
            if (i < smallest)
                smallest = i;
            if (i > largest)
                largest = i;
            }
        }
        
    /* count the number of informative states in the unambiguous codings */
    for (i=numInformative=0; i<10; i++)
        {
        if (ci->cType == ORD && n2[i] > 0 && i != smallest && i != largest)
            {   
            numInformative++;
            lastInformative = i;
            }
        else if (n2[i] > 1)
            {
            numInformative++;
            lastInformative = i;
            }
        }

    /* set informative */
    if (numInformative > 1)
        ci->informative = YES;
    else
        ci->informative = NO;

    
    /* we can return now unless informative is no and numPartAmbig is not 0 */
    if (!(numPartAmbig > 0 && ci->informative == NO))
        return;

    /* check if partially ambiguous observations make this character informative
       after all */
    
    /* first set the bits for the taken states */
    x = 0;
    for (i=0; i<10; i++)
        {
        if (n2[i] > 0 && i != lastInformative)
            x |= (bitsLongOne<<i);
        }
    oldPoss = 1;
    oldComb[0] = x;

    /* now go through all partambig chars and see if we can add them without
       making the character informative */
    for (i=0; i<m->nRows; i++)
        {
        x = (int) m->origin[m->column + i*m->rowSize];
        /* if partambig */ 
        if (NBits(x) > 1 && NBits(x) < ci->nStates)
            {
            /* remove lastInformative */
            x &= !(bitsLongOne<<lastInformative);
            /* reset newPoss */
            newPoss = 0;
            /* see if we can add it, store all possible combinations */
            for (j=0; j<oldPoss; j++)
                {
                uniqueBits = x & (!oldComb[j]);
                for (k=0; k<10; k++)
                    {
                    if (((bitsLongOne<<k) & uniqueBits) != 0)
                        newComb[newPoss++] = oldComb[j] | (bitsLongOne<<k);
                    }
                }
            /* break out if we could not add it */
            if (newPoss == 0)
                break;
            
            /* prepare for next partAmbig */
            oldPoss = newPoss;
            tempComb = oldComb;
            oldComb = newComb;
            newComb = tempComb;
            }
        }

    if (i < m->nRows)
        ci->informative = YES;

    return;
}


/*-----------------------------------------------------------
|
|   CheckModel: check model and warn user if strange things
|      are discovered.
|
-------------------------------------------------------------*/
int CheckModel (void)
{
    int         i, j, k, answer;
    Tree        *t = NULL;
    TreeNode    *p;
    
    /* there should only be one calibrated tree */
    for (i=0; i<numTrees; i++)
        {
        t = GetTreeFromIndex(i,0,0);
        if (t->isCalibrated == YES)
            break;
        }
    
    if (i < numTrees)
        {
        if (!strcmp(modelParams[t->relParts[0]].clockRatePr, "Fixed") && AreDoublesEqual(modelParams[t->relParts[0]].clockRateFix, 1.0, 1E-6) == YES)
            {
            MrBayesPrint("%s   WARNING: You have calibrated the tree but the clock rate is fixed to 1.0.\n", spacer);
            MrBayesPrint("%s      This means that time is measured in expected changes per time unit. If\n", spacer);
            MrBayesPrint("%s      the calibrations use a different time scale, you need to modify the model\n", spacer);
            MrBayesPrint("%s      by introducing a prior for the clock rate ('prset clockratepr').\n", spacer);

            if (noWarn == NO)
                {
                answer = WantTo("Do you want to continue with the run regardless");
                if (answer == YES)
                    {
                    MrBayesPrint("%s   Continuing with the run...\n\n", spacer);
                    }
                else
                    {
                    MrBayesPrint("%s   Stopping the run...\n\n", spacer);
                    return (ERROR);
                    }
                }
            }
        }

    /* check coalescence model */
    for (i=0; i<numTrees; i++)
        {
        t = GetTreeFromIndex(i, 0, 0);
        if ((!strcmp(modelParams[t->relParts[0]].clockPr,"Coalescence") || !strcmp(modelParams[t->relParts[0]].clockPr,"Speciestreecoalescence"))
            && !strcmp(modelParams[t->relParts[0]].clockRatePr, "Fixed") && AreDoublesEqual(modelParams[t->relParts[0]].clockRateFix, 1.0, 1E-6) == YES)
            {
            MrBayesPrint("%s   WARNING: You are using a coalescent model but the clock rate is fixed to 1.0.\n", spacer);
            MrBayesPrint("%s      This is likely to be incorrect unless you have set the population size prior\n", spacer);
            MrBayesPrint("%s      ('prset popsizepr') to reflect an appropriate prior on theta. \n", spacer);

            if (noWarn == NO)
                {
                answer = WantTo("Do you want to continue with the run regardless");
                if (answer == YES)
                    {
                    MrBayesPrint("%s   Continuing with the run...\n\n", spacer);
                    }
                else
                    {
                    MrBayesPrint("%s   Stopping the run...\n\n", spacer);
                    return (ERROR);
                    }
                }
            }
        }

    /* Check consistency of best model. First we guarantee that if one topology has
       a species tree prior, then all topologies have the same prior. Then we make
       sure that all clock trees have a coalescence prior. */

    j = 0;
    for (i=0; i<numCurrentDivisions; i++)
        {
        if (!strcmp(modelParams[i].topologyPr, "Speciestree"))
            j++;
        }

    if (j > 0)
        {
        if (j != numCurrentDivisions)
            {
            MrBayesPrint("%s   ERROR: If one gene tree has a speciestree prior then all\n", spacer);
            MrBayesPrint("%s          gene trees must have the same prior.\n", spacer);
            return (ERROR);
            }
        for (i=0; i<numTrees-1; i++)
            {
            t = GetTreeFromIndex(i,0,0);
            if (strcmp(modelParams[t->relParts[0]].clockPr,"Speciestreecoalescence") != 0)
                {
                MrBayesPrint("%s   ERROR: All gene trees must have a speciestreecoalescence prior\n", spacer);
                MrBayesPrint("%s          if they fold into a species tree.\n", spacer);
                return (ERROR);
                }
            if (t->isCalibrated == YES)
                {
                for (k=0; k<t->nNodes-1; k++)
                    {
                    p = t->allDownPass[k];
                    if (p->calibration != NULL)
                        {
                        MrBayesPrint("%s   ERROR: Gene trees cannot be individually calibrated\n", spacer);
                        MrBayesPrint("%s          if they fold into a species tree.\n", spacer);
                        return (ERROR);
                        }
                    }
                }
            }
        }

    return NO_ERROR;
}


/*-----------------------------------------------------------
|
|   CheckExpandedModels: check data partitions that have
|   the codon or doublet model specified
|
-------------------------------------------------------------*/
int CheckExpandedModels (void)
{
    int             c, d, i, t, s, s1, s2, s3, whichNuc, uniqueId, numCharsInPart, 
                    firstChar, lastChar, contiguousPart, badBreak, badExclusion,
                    nGone, nuc1, nuc2, nuc3, foundStopCodon, posNucs1[4], posNucs2[4], posNucs3[4],
                    oneGoodCodon, foundUnpaired, nPair, allCheckedOut;
    char            *tempStr;
    int             tempStrSize=100;
    ModelParams     *mp;
    
    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
    if (!tempStr)
        {
        MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
        return (ERROR);
        }

    /* first, set charId to 0 for all characters */
    for (i=0; i<numChar; i++)
        charInfo[i].charId = 0;
    
    /* loop over partitions */
    allCheckedOut = 0;
    uniqueId = 1;
    for (d=0; d<numCurrentDivisions; d++)
        {
        mp = &modelParams[d];
        
        if (mp->dataType == DNA || mp->dataType == RNA)
            {
            if (!strcmp(mp->nucModel,"Codon") || !strcmp(mp->nucModel,"Protein"))
                {
                /* start check that the codon model is appropriate for this partition */
                
                /* find first character in this partition */
                for (c=0; c<numChar; c++)
                    {
                    if (partitionId[c][partitionNum] == d+1)
                        break;
                    }
                firstChar = c;
                /*printf ("   first character = %d\n", firstChar);*/
                
                /* find last character in this partition */
                for (c=numChar-1; c>=0; c--)
                    {
                    if (partitionId[c][partitionNum] == d+1)
                        break;
                    }
                lastChar = c;
                /*printf ("   last character = %d\n", lastChar);*/
                
                /* check that the number of characters in partition is divisible by 3 */
                numCharsInPart = 0;
                for (c=firstChar; c<=lastChar; c++)
                    {
                    if (charInfo[c].isExcluded == YES || partitionId[c][partitionNum] != d+1)
                        continue;
                    numCharsInPart++;
                    }
                /*printf ("   numCharsInPart = %d\n", numCharsInPart);*/
                if (numCharsInPart % 3 != 0)
                    {
                    if (numCurrentDivisions == 1)
                        {
                        MrBayesPrint ("%s   The number of characters is not divisible by three.\n", spacer);
                        MrBayesPrint ("%s   You specified a %s model which requires triplets\n", spacer, mp->nucModel);
                        MrBayesPrint ("%s   However, you have %d characters.\n", spacer, numCharsInPart);
                        }
                    else
                        {
                        MrBayesPrint ("%s   The number of characters in partition %d is not\n", spacer, d+1);
                        MrBayesPrint ("%s   divisible by three. You specified a %s model\n", spacer, mp->nucModel);
                        MrBayesPrint ("%s   which requires triplets. \n", spacer);
                        MrBayesPrint ("%s   However, you have %d characters in this partition\n", spacer, numCharsInPart);
                        }
                    free (tempStr);
                    return (ERROR);
                    }
                
                /* check that all of the characters in the partition are contiguous */
                contiguousPart = YES;
                for (c=firstChar; c<=lastChar; c++)
                    {
                    if (charInfo[c].isExcluded == NO && partitionId[c][partitionNum] != d+1)
                        contiguousPart = NO;
                    }
                if (contiguousPart == NO)
                    {
                    MrBayesPrint ("%s   Partition %d is not contiguous. You specified that\n", spacer, d+1);
                    MrBayesPrint ("%s   a %s model be used for this partition. However, there\n", spacer, mp->nucModel);
                    MrBayesPrint ("%s   is another partition that is between some of the characters\n", spacer);
                    MrBayesPrint ("%s   in this partition. \n", spacer);
                    free (tempStr);
                    return (ERROR);
                    }
                    
                /* check that there is not a break inside a triplet of characters */
                badBreak = NO;
                whichNuc = 0;
                for (c=firstChar; c<=lastChar; c++)
                    {
                    if (charInfo[c].isExcluded == NO)
                        continue;
                    whichNuc++;
                    if (charInfo[c].bigBreakAfter == YES && whichNuc != 3)
                        badBreak = YES;
                    if (whichNuc == 3)
                        whichNuc = 0;
                    }
                if (badBreak == YES)
                    {
                    MrBayesPrint ("%s   You specified a databreak inside of a coding triplet.\n", spacer);
                    MrBayesPrint ("%s   This is a problem, as you imply that part of the codon\n", spacer);
                    MrBayesPrint ("%s   lies in one gene and the remainder in another gene. \n", spacer);
                    free (tempStr);
                    return (ERROR);
                    }

                /* make certain excluded characters are in triplets but allow frameshift exclusions first in sequence */
                badExclusion = NO;
                whichNuc = nGone = 0;
                for (c=firstChar; c<=lastChar; c++)
                    if (charInfo[c].isExcluded == NO)
                        break;
                for (; c<=lastChar; c++)
                    {
                    whichNuc++;
                    if (charInfo[c].isExcluded == YES)
                        nGone++;
                    if (whichNuc == 3)
                        {
                        if (nGone == 1 || nGone == 2)
                            badExclusion = YES;
                        whichNuc = nGone = 0;
                        }
                    }
                if (badExclusion == YES)
                    {
                    MrBayesPrint ("%s   In excluding characters, you failed to remove all of the\n", spacer);
                    MrBayesPrint ("%s   sites of at least one codon. If you exclude sites, make \n", spacer);
                    MrBayesPrint ("%s   certain to exclude all of the sites in the codon(s). \n", spacer);
                    free (tempStr);
                    return (ERROR);
                    }
                
                /* check that there are no stop codons */
                foundStopCodon = NO;
                /* allow frameshifting exclusions in the beginning */
                for (c=firstChar; c<=lastChar; c++)
                    if (charInfo[c].isExcluded == NO)
                        break;
                for (; c<=lastChar; c+=3)
                    {
                    if (charInfo[c].isExcluded == NO)
                        {
                        for (t=0; t<numTaxa; t++)
                            {
                            if (taxaInfo[t].isDeleted == YES)
                                continue;
                            nuc1 = matrix[pos(t,c+0,numChar)];
                            nuc2 = matrix[pos(t,c+1,numChar)];
                            nuc3 = matrix[pos(t,c+2,numChar)];
                            /*nucX is in range 0-15 to represent any possible set of states that nucleatide could be in*/
                            GetPossibleNucs (nuc1, posNucs1);
                            GetPossibleNucs (nuc2, posNucs2);
                            GetPossibleNucs (nuc3, posNucs3);
                            
                            oneGoodCodon = NO;
                            s = 0;
                            for (s1=0; s1<4; s1++)
                                {
                                for (s2=0; s2<4; s2++)
                                    {
                                    for (s3=0; s3<4; s3++)
                                        {
                                        if (posNucs1[s1] == 1 && posNucs2[s2] == 1 && posNucs3[s3] == 1)
                                            {
                                            if (mp->codon[s1*16 + s2*4 + s3] != 21)
                                                oneGoodCodon = YES;
                                            }
                                        s++;
                                        }
                                    }
                                }
                            if (oneGoodCodon == NO)
                                {
                                foundStopCodon = YES;
                                MrBayesPrint ("%s   Stop codon: taxon %s, sites %d to %d (%c%c%c, %s code)\n", spacer, 
                                    taxaNames[t], c+1, c+3, WhichNuc (nuc1), WhichNuc (nuc2), WhichNuc (nuc3), mp->geneticCode);
                                }
                            }
                        }
                    }               
                if (foundStopCodon == YES)
                    {
                    MrBayesPrint ("%s   At least one stop codon was found. Stop codons are not\n", spacer);
                    MrBayesPrint ("%s   allowed under the codon models.  \n", spacer);
                    free (tempStr);
                    return (ERROR);
                    }
                
                /* everything checks out. Now we can initialize charId */
                whichNuc = 0;
                for (c=firstChar; c<=lastChar; c++)
                    {
                    whichNuc++;
                    charInfo[c].charId = uniqueId;
                    if (whichNuc == 3)
                        {
                        whichNuc = 0;
                        uniqueId++;
                        }
                    }
                
                allCheckedOut++;
                /* end check that the codon model is appropriate for this partition */
                }
            else if (!strcmp(mp->nucModel,"Doublet"))
                {
                /* start check that the doublet model is appropriate for this partition */
                
                /* Check that pairsId does not equal 0 for any of the characters in
                   the partition. If it does, then this means that at least one 
                   site was not appropriately paired. Remember, that pairsId is
                   initialized 1, 2, 3, ... for the first pair, second pair, etc. 
                   Also, check that every pair is only represented two times. */
                foundUnpaired = NO;
                for (c=0; c<numChar; c++)
                    {
                    if (partitionId[c][partitionNum] == d+1 && charInfo[c].pairsId == 0 && charInfo[c].isExcluded == NO)
                        foundUnpaired = YES;
                    }
                    
                for (c=0; c<numChar; c++)
                    {
                    if (partitionId[c][partitionNum] == d+1 && charInfo[c].isExcluded == NO)
                        {
                        nPair = 1;
                        for (i=0; i<numChar; i++)
                            {
                            if (i != c && partitionId[i][partitionNum] == d+1 && charInfo[i].isExcluded == NO && charInfo[c].pairsId == charInfo[i].pairsId)
                                nPair++;
                            }
                        if (nPair != 2)
                            foundUnpaired = YES;
                        }
                    }
                if (foundUnpaired == YES)
                    {
                    if (numCurrentDivisions == 1)
                        {
                        MrBayesPrint ("%s   Found unpaired nucleotide sites. The doublet model\n", spacer);
                        MrBayesPrint ("%s   requires that all sites are paired. \n", spacer);
                        }
                    else
                        {
                        MrBayesPrint ("%s   Found unpaired nucleotide sites in partition %d.\n", spacer, d+1);
                        MrBayesPrint ("%s   The doublet model requires that all sites are paired. \n", spacer);
                        }
                    free (tempStr);
                    return (ERROR);
                    }

                /* everything checks out. Now we can initialize charId */
                for (c=0; c<numChar; c++)
                    {
                    nuc1 = nuc2 = -1;
                    if (partitionId[c][partitionNum] == d+1 && charInfo[c].charId == 0)
                        {
                        nuc1 = c;
                        for (i=0; i<numChar; i++)
                            {
                            if (i != c && charInfo[i].charId == 0 && charInfo[c].pairsId == charInfo[i].pairsId)
                                nuc2 = i;
                            }
                        if (nuc1 >= 0 && nuc2 >= 0)
                            {
                            charInfo[nuc1].charId = charInfo[nuc2].charId = uniqueId;
                            uniqueId++;
                            }
                        else
                            {
                            MrBayesPrint ("%s   Weird doublet problem in partition %d.\n", spacer, d+1);
                            free (tempStr);
                            return (ERROR);
                            }
                        }
                    }
                    
                allCheckedOut++;
                /* end check that the doublet model is appropriate for this partition */
                }
            }
        }
        
    /*
    if (allCheckedOut > 0)
        MrBayesPrint ("%s   Codon/Doublet models successfully checked\n", spacer);
    */
        
#   if 0
    for (c=0; c<numChar; c++)
            printf (" %d", charId[c]);
    printf ("\n");
#   endif

    free (tempStr);
    return (NO_ERROR);
}


/*-----------------------------------------------------------
|
|   CompressData: compress original data matrix
|
-------------------------------------------------------------*/
int CompressData (void)
{
    int             a, c, d, i, j, k, t, col[3], isSame, newRow, newColumn,
                    *isTaken, *tempSitesOfPat, *tempChar;
    BitsLong        *tempMatrix;
    ModelInfo       *m;
    ModelParams     *mp;

#   if defined DEBUG_COMPRESSDATA
    if (PrintMatrix() == ERROR)
        goto errorExit;
    getchar();
#   endif

    /* set all pointers that will be allocated locally to NULL */
    isTaken = NULL;
    tempMatrix = NULL;
    tempSitesOfPat = NULL;
    tempChar = NULL;

    /* allocate indices pointing from original to compressed matrix */
    if (memAllocs[ALLOC_COMPCOLPOS] == YES)
        {
        free (compColPos);
        compColPos = NULL;
        memAllocs[ALLOC_COMPCOLPOS] = NO;
        }
    compColPos = (int *)SafeMalloc((size_t) (numChar * sizeof(int)));
    if (!compColPos)
        {
        MrBayesPrint ("%s   Problem allocating compColPos (%d)\n", spacer, numChar * sizeof(int));
        goto errorExit;
        }
    for (i=0; i<numChar; i++)
        compColPos[i] = 0;
    memAllocs[ALLOC_COMPCOLPOS] = YES;

    if (memAllocs[ALLOC_COMPCHARPOS] == YES)
        {
        free (compCharPos);
        compCharPos = NULL;
        memAllocs[ALLOC_COMPCHARPOS] = NO;
        }
    compCharPos = (int *)SafeMalloc((size_t) (numChar * sizeof(int)));
    if (!compCharPos)
        {
        MrBayesPrint ("%s   Problem allocating compCharPos (%d)\n", spacer, numChar * sizeof(int));
        goto errorExit;
        }
    for (i=0; i<numChar; i++)
        compCharPos[i] = 0;
    memAllocs[ALLOC_COMPCHARPOS] = YES;

    /* allocate space for temporary matrix, tempSitesOfPat,             */
    /* vector keeping track of whether a character has been compressed, */
    /* and vector indexing first original char for each compressed char */
    tempMatrix = (BitsLong *) SafeCalloc (numLocalTaxa * numLocalChar, sizeof(BitsLong));
    tempSitesOfPat = (int *) SafeCalloc (numLocalChar, sizeof(int));
    isTaken = (int *) SafeCalloc (numChar, sizeof(int));
    tempChar = (int *) SafeCalloc (numLocalChar, sizeof(int));
    if (!tempMatrix || !tempSitesOfPat || !isTaken || !tempChar)
        {
        MrBayesPrint ("%s   Problem allocating temporary variables in CompressData\n", spacer);
        goto errorExit;
        }

    /* initialize isTaken */
    for (c=0; c<numChar; c++)
        isTaken[c] = NO;

    /* set index to first empty column in temporary matrix */
    newColumn = 0;

    /* initialize number of compressed characters */
    numCompressedChars = 0;

    /* sort and compress data */
    for (d=0; d<numCurrentDivisions; d++)
        {
        /* set pointers to the model params and settings for this division */
        m = &modelSettings[d];
        mp = &modelParams[d];

        /* set column offset for this division in compressed matrix */
        m->compMatrixStart = newColumn;

        /* set compressed character offset for this division */
        m->compCharStart = numCompressedChars;

        /* set number of compressed characters to 0 for this division */
        m->numChars = 0;

        /* find the number of original characters per model site */
        m->nCharsPerSite = 1;
        if (mp->dataType == DNA || mp->dataType == RNA)
            {   
            if (!strcmp(mp->nucModel, "Doublet"))
                m->nCharsPerSite = 2;
            if (!strcmp(mp->nucModel, "Codon") || !strcmp(mp->nucModel, "Protein"))
                m->nCharsPerSite = 3;
            }
        
        /* sort and compress the characters for this division */
        for (c=0; c<numChar; c++)
            {
            if (charInfo[c].isExcluded == YES || partitionId[c][partitionNum] != d+1 || isTaken[c] == YES)
                continue;

            col[0] = c;
            isTaken[c] = YES;
            
            /* find additional columns if more than one character per model site      */
            /* return error if the number of matching characters is smaller or larger */
            /* than the actual number of characters per model site                    */
            if (m->nCharsPerSite > 1)
                {
                j = 1;
                if (charInfo[c].charId == 0)
                    {
                    MrBayesPrint("%s   Character %d is not properly defined\n", spacer, c+1);
                    goto errorExit;
                    }
                for (i=c+1; i<numChar; i++)
                    {
                    if (charInfo[i].charId == charInfo[c].charId)
                        {
                        if (j >= m->nCharsPerSite)
                            {
                            MrBayesPrint("%s   Too many matches in charId (division %d char %d)\n", spacer, d, numCompressedChars);
                            goto errorExit;
                            }
                        else
                            {
                            col[j++] = i;
                            isTaken[i] = YES;
                            }
                        }
                    }
                if (j != m->nCharsPerSite)
                    {
                    MrBayesPrint ("%s   Too few matches in charId (division %d char %d)\n", spacer, d, numCompressedChars);
                    goto errorExit;
                    }
                }
            
            /* add character to temporary matrix in column(s) at newColumn */
            for (t=newRow=0; t<numTaxa; t++)
                {
                if (taxaInfo[t].isDeleted == YES)
                    continue;

                for (k=0; k<m->nCharsPerSite; k++)
                    {
                    tempMatrix[pos(newRow,newColumn+k,numLocalChar)] = matrix[pos(t,col[k],numChar)];
                    }
                newRow++;
                }
            
            /* is it unique? */
            isSame = NO;
            if (mp->dataType != CONTINUOUS)
                {
                for (i=m->compMatrixStart; i<newColumn; i+=m->nCharsPerSite)
                    {
                    isSame = YES;
                    for (j=0; j<numLocalTaxa; j++)
                        {
                        for (k=0; k<m->nCharsPerSite; k++)
                            if (tempMatrix[pos(j,newColumn+k,numLocalChar)] != tempMatrix[pos(j,i+k,numLocalChar)])
                                {
                                isSame = NO;
                                break;
                                }
                        if (isSame == NO)
                            break;
                        }
                    if (isSame == YES)
                        break;
                    }
                }

            /* if subject to data augmentation, it is always unique */
            if (!strcmp(mp->augmentData, "Yes"))
                {
                for (k=0; k<m->nCharsPerSite; k++)
                    {
                    if (charInfo[col[k]].isMissAmbig == YES)
                        isSame = NO;
                    }
                }

            if (isSame == NO)
                {
                /* if it is unique then it should be added */
                tempSitesOfPat[numCompressedChars] = 1;
                for (k=0; k<m->nCharsPerSite; k++)
                    {
                    compColPos[col[k]] = newColumn + k;
                    compCharPos[col[k]] = numCompressedChars;
                    tempChar[newColumn + k] = col[k];
                    }
                newColumn+=m->nCharsPerSite;
                m->numChars++;
                numCompressedChars++;
                }
            else
                {
                /* if it is not unique then simply update tempSitesOfPat     */
                /* calculate compressed character position and put it into a */
                /* (i points to compressed column position)                  */
                a = m->compCharStart + ((i - m->compMatrixStart) / m->nCharsPerSite);
                tempSitesOfPat[a]++;
                for (k=0; k<m->nCharsPerSite; k++)
                    {
                    compColPos[col[k]] = i;
                    compCharPos[col[k]] = a;
                    /* tempChar (pointing from compressed to uncompresed) */
                    /* can only be set for first pattern */
                    }
                }
            }   /* next character */
            
        /* check that the partition has at least a single character */
        if (m->numChars <= 0)
            {
            MrBayesPrint ("%s   You must have at least one site in a partition. Partition %d\n", spacer, d+1);
            MrBayesPrint ("%s   has %d site patterns.\n", spacer, m->numChars);
            goto errorExit;
            }

        m->compCharStop = m->compCharStart + m->numChars;
        m->compMatrixStop = newColumn;

        } /* next division */

    compMatrixRowSize = newColumn;

    /* now we know the size, so we can allocate space for the compressed matrix ... */
    if (memAllocs[ALLOC_COMPMATRIX] == YES)
        {
        free (compMatrix);
        compMatrix = NULL;
        memAllocs[ALLOC_COMPMATRIX] = NO;
        }
    compMatrix = (BitsLong *) SafeCalloc (compMatrixRowSize * numLocalTaxa, sizeof(BitsLong));
    if (!compMatrix)
        {
        MrBayesPrint ("%s   Problem allocating compMatrix (%d)\n", spacer, compMatrixRowSize * numLocalTaxa * sizeof(BitsLong));
        goto errorExit;
        }
    memAllocs[ALLOC_COMPMATRIX] = YES;
    
    if (memAllocs[ALLOC_NUMSITESOFPAT] == YES)
        {
        free (numSitesOfPat);
        numSitesOfPat = NULL;
        memAllocs[ALLOC_NUMSITESOFPAT] = NO;
        }
    numSitesOfPat = (CLFlt *) SafeCalloc (numCompressedChars, sizeof(CLFlt));
    if (!numSitesOfPat)
        {
        MrBayesPrint ("%s   Problem allocating numSitesOfPat (%d)\n", spacer, numCompressedChars * sizeof(MrBFlt));
        goto errorExit;
        }
    memAllocs[ALLOC_NUMSITESOFPAT] = YES;

    if (memAllocs[ALLOC_ORIGCHAR] == YES)
        {
        free (origChar);
        origChar = NULL;
        memAllocs[ALLOC_ORIGCHAR] = NO;
        }
    origChar = (int *)SafeMalloc((size_t) (compMatrixRowSize * sizeof(int)));
    if (!origChar)
        {
        MrBayesPrint ("%s   Problem allocating origChar (%d)\n", spacer, numCompressedChars * sizeof(int));
        goto errorExit;
        }
    memAllocs[ALLOC_ORIGCHAR] = YES;

    /* ... and copy the data there */
    for (i=0; i<numLocalTaxa; i++)
        for (j=0; j<compMatrixRowSize; j++)
            compMatrix[pos(i,j,compMatrixRowSize)] = tempMatrix[pos(i,j,numLocalChar)];

    for (i=0; i<numCompressedChars; i++)
        numSitesOfPat[i] = (CLFlt) tempSitesOfPat[i];

    for (i=0; i<compMatrixRowSize; i++)
        origChar[i] = tempChar[i];

#   if defined (DEBUG_COMPRESSDATA)
    if (PrintCompMatrix() == ERROR)
        goto errorExit;
    getchar();
#   endif

    /* free the temporary variables */
    free (tempSitesOfPat);
    free (tempMatrix);
    free (isTaken);
    free (tempChar);

    return NO_ERROR;

    errorExit:
        if (tempMatrix)
            free (tempMatrix);
        if (tempSitesOfPat)
            free (tempSitesOfPat);
        if (isTaken)
            free (isTaken);
        if (tempChar)
            free (tempChar);

        return ERROR;
}


int DataType (int part)
{
    int     i;

    for (i=0; i<numChar; i++)
        {
        if (partitionId[i][partitionNum] == part + 1)
            break;
        }

    return (charInfo[i].charType);
}


int DoLink (void)
{
    int         i, j, newLine;
    
    MrBayesPrint ("%s   Linking\n", spacer);
    
    /* update status of linkTable */
    for (j=0; j<NUM_LINKED; j++)
        {
        newLine = YES;
        for (i=0; i<numCurrentDivisions; i++)
            {
            if (tempLinkUnlink[j][i] == YES)
                {
                if (newLine == YES)
                    {
                    linkNum++;
                    newLine = NO;
                    }
                linkTable[j][i] = linkNum;
                }
            }
        }
    
#   if 0
    for (j=0; j<NUM_LINKED; j++)
        {
        MrBayesPrint ("%s   ", spacer);
        for (i=0; i<numCurrentDivisions; i++)
            MrBayesPrint ("%d", linkTable[j][i]);
        MrBayesPrint ("\n");
        }
#   endif

    /* reinitialize the temporary table */
    for (j=0; j<NUM_LINKED; j++)
        for (i=0; i<numCurrentDivisions; i++)
            tempLinkUnlink[j][i] = NO;

    /* set up parameters and moves */
    if (SetUpAnalysis (&globalSeed) == ERROR)
        return (ERROR);
    
    return (NO_ERROR);
}


int DoLinkParm (char *parmName, char *tkn)
{
    int         i, j, tempInt;

    if (defMatrix == NO)
        {
        MrBayesPrint ("%s   A matrix must be specified before the model can be defined\n", spacer);
        return (ERROR);
        }
        
    if (inValidCommand == YES)
        {
        for (j=0; j<NUM_LINKED; j++)
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[j][i] = NO;
        inValidCommand = NO;
        }

    if (expecting == Expecting(PARAMETER))
        {
        expecting = Expecting(EQUALSIGN);
        }
    else if (expecting == Expecting(EQUALSIGN))
        {
        expecting = Expecting(LEFTPAR);
        }
    else if (expecting == Expecting(LEFTPAR))
        {
        /* initialize tempLinkUnlinkVec to no */
        for (i=0; i<numCurrentDivisions; i++)
            tempLinkUnlinkVec[i] = NO;
        fromI = toJ = -1;
        foundDash = NO;
        expecting = Expecting(NUMBER) | Expecting(ALPHA);
        }
    else if (expecting == Expecting(RIGHTPAR))
        {
        if (fromI != -1)
            tempLinkUnlinkVec[fromI-1] = YES;
        /* now copy tempLinkUnlinkVec to appropriate row of tempLinkUnlink */
        if (!strcmp(parmName, "Tratio"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_TRATIO][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Revmat"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_REVMAT][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Omega"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_OMEGA][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Statefreq"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_PI][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Shape"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_SHAPE][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Pinvar"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_PINVAR][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Correlation"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_CORREL][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Ratemultiplier"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_RATEMULT][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Switchrates"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_SWITCH][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Topology"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_TOPOLOGY][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Brlens"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_BRLENS][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Speciationrate"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_SPECRATE][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Extinctionrate"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_EXTRATE][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Fossilizationrate")) 
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_FOSLRATE][i] = tempLinkUnlinkVec[i];
            }                                                             
        else if (!strcmp(parmName, "Popsize"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_POPSIZE][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Growthrate"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_GROWTH][i] = tempLinkUnlinkVec[i];
            } 
        else if (!strcmp(parmName, "Aamodel"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_AAMODEL][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Cpprate"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_CPPRATE][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Cppmultdev"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_CPPMULTDEV][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Cppevents"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_CPPEVENTS][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "TK02var") || !strcmp(parmName, "Bmvar"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_TK02VAR][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "TK02branchrates") || !strcmp(parmName, "Bmbranchrates"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_TK02BRANCHRATES][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Igrvar") || !strcmp(parmName, "Ibrvar"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_IGRVAR][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Igrbranchrates") || !strcmp(parmName, "Ibrbranchlens"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_IGRBRANCHRATES][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Mixedvar"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_MIXEDVAR][i] = tempLinkUnlinkVec[i];
            }
        else if (!strcmp(parmName, "Mixedbrchrates"))
            {
            for (i=0; i<numCurrentDivisions; i++)
                tempLinkUnlink[P_MIXEDBRCHRATES][i] = tempLinkUnlinkVec[i];
            }
        else
            {
            MrBayesPrint ("%s   Couldn't find parameter %s to link\n", spacer, parmName);
            }
        
        expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
        }
    else if (expecting == Expecting(COMMA))
        {
        foundComma = YES;
        expecting = Expecting(NUMBER);
        }
    else if (expecting == Expecting(ALPHA))
        {
        if (IsSame ("All", tkn) == DIFFERENT)
            {
            MrBayesPrint ("%s   Do not understand delimiter \"%s\"\n", spacer, tkn);
            return (ERROR);
            }
        for (i=0; i<numCurrentDivisions; i++)
            tempLinkUnlinkVec[i] = YES;
        expecting  = Expecting(RIGHTPAR);
        }
    else if (expecting == Expecting(NUMBER))
        {
        sscanf (tkn, "%d", &tempInt);
        if (tempInt > numCurrentDivisions)
            {
            MrBayesPrint ("%s   Partition delimiter is too large\n", spacer);
            return (ERROR);
            }
        if (fromI == -1)
            fromI = tempInt;
        else if (fromI != -1 && toJ == -1 && foundDash == YES && foundComma == NO)
            {
            toJ = tempInt;
            for (i=fromI-1; i<toJ; i++)
                tempLinkUnlinkVec[i] = YES;
            fromI = toJ = -1;
            foundDash = NO;
            }
        else if (fromI != -1 && toJ == -1 && foundDash == NO && foundComma == YES)
            {
            tempLinkUnlinkVec[fromI-1] = YES;
            fromI = tempInt;
            foundComma = NO;
            }
        expecting  = Expecting(COMMA);
        expecting |= Expecting(DASH);
        expecting |= Expecting(RIGHTPAR);
        }
    else if (expecting == Expecting(DASH))
        {
        foundDash = YES;
        expecting = Expecting(NUMBER);
        }
    else
        return (ERROR);

    return (NO_ERROR);
}


int DoLset (void)
{
    int         i, nApplied, lastActive=0;
    
    nApplied = NumActiveParts ();
    for (i=numCurrentDivisions; i>=0; i--)
        {
        if (activeParts[i] == YES)
            {
            lastActive = i;
            break;
            }
        }
            
    /* MrBayesPrint ("\n"); */
    if (numCurrentDivisions == 1)
        MrBayesPrint ("%s   Successfully set likelihood model parameters\n", spacer);
    else 
        {
        if (nApplied == numCurrentDivisions || nApplied == 0)
            {
            MrBayesPrint ("%s   Successfully set likelihood model parameters to all\n", spacer);
            MrBayesPrint ("%s      applicable data partitions \n", spacer);
            }
        else
            {
            MrBayesPrint ("%s   Successfully set likelihood model parameters to\n", spacer);
            if (nApplied == 1)
                MrBayesPrint ("%s   partition", spacer);
            else
                MrBayesPrint ("%s   partitions", spacer);
            for (i=0; i<numCurrentDivisions; i++)
                {
                if (activeParts[i] == YES)
                    {
                    if (i == lastActive && nApplied > 1)
                        MrBayesPrint (" and %d", i+1);
                    else
                        MrBayesPrint (" %d", i+1);
                    if (nApplied > 2 && i != lastActive)
                        MrBayesPrint (",");
                    }
                }
            MrBayesPrint (" (if applicable)\n");
            }
        }

    if (SetUpAnalysis (&globalSeed) == ERROR)
        return (ERROR);
    
    return (NO_ERROR);
}


int DoLsetParm (char *parmName, char *tkn)
{
    int         i, j, tempInt, nApplied;
    char        tempStr[100];

    if (defMatrix == NO)
        {
        MrBayesPrint ("%s   A matrix must be specified before the model can be defined\n", spacer);
        return (ERROR);
        }
    if (inValidCommand == YES)
        {
        for (i=0; i<numCurrentDivisions; i++)
            activeParts[i] = NO;
        inValidCommand = NO;
        }

    if (expecting == Expecting(PARAMETER))
        {
        expecting = Expecting(EQUALSIGN);
        }
    else
        {
        /* set Applyto (Applyto) *************************************************************/
        if (!strcmp(parmName, "Applyto"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(LEFTPAR);
            else if (expecting == Expecting(LEFTPAR))
                {
                for (i=0; i<numCurrentDivisions; i++)
                    activeParts[i] = NO;
                fromI = toJ = -1;
                foundDash = NO;
                expecting = Expecting(NUMBER) | Expecting(ALPHA);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                if (fromI != -1)
                    activeParts[fromI-1] = YES;
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else if (expecting == Expecting(COMMA))
                {
                foundComma = YES;
                expecting = Expecting(NUMBER);
                }
            else if (expecting == Expecting(ALPHA))
                {
                if (IsSame ("All", tkn) == DIFFERENT)
                    {
                    MrBayesPrint ("%s   Do not understand delimiter \"%s\"\n", spacer, tkn);
                    return (ERROR);
                    }
                for (i=0; i<numCurrentDivisions; i++)
                    activeParts[i] = YES;
                expecting  = Expecting(RIGHTPAR);
                }
            else if (expecting == Expecting(NUMBER))
                {
                sscanf (tkn, "%d", &tempInt);
                if (tempInt > numCurrentDivisions)
                    {
                    MrBayesPrint ("%s   Partition delimiter is too large\n", spacer);
                    return (ERROR);
                    }
                if (fromI == -1)
                    fromI = tempInt;
                else if (fromI != -1 && toJ == -1 && foundDash == YES && foundComma == NO)
                    {
                    toJ = tempInt;
                    for (i=fromI-1; i<toJ; i++)
                        activeParts[i] = YES;
                    fromI = toJ = -1;
                    foundDash = NO;
                    }
                else if (fromI != -1 && toJ == -1 && foundDash == NO && foundComma == YES)
                    {
                    activeParts[fromI-1] = YES;
                    fromI = tempInt;
                    foundComma = NO;
                    }
                    
                expecting  = Expecting(COMMA);
                expecting |= Expecting(DASH);
                expecting |= Expecting(RIGHTPAR);
                }
            else if (expecting == Expecting(DASH))
                {
                foundDash = YES;
                expecting = Expecting(NUMBER);
                }
            else
                return (ERROR);
            }
        /* set Nucmodel (nucModel) ************************************************************/
        else if (!strcmp(parmName, "Nucmodel"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    tempInt = NO;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].nucModel, tempStr);
                            modelParams[i].nStates = NumStates (i);
                            
                            /* set state frequencies back to default */
                            strcpy(modelParams[i].stateFreqPr, "Dirichlet");
                            strcpy(modelParams[i].stateFreqsFixType, "Equal");
                            for (j=0; j<200; j++)
                                {
                                modelParams[i].stateFreqsFix[j] = 0.0;   
                                modelParams[i].stateFreqsDir[j] = 1.0;
                                }    
                            tempInt = YES;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Nucmodel to %s\n", spacer, modelParams[i].nucModel);
                            else
                                MrBayesPrint ("%s   Setting Nucmodel to %s for partition %d\n", spacer, modelParams[i].nucModel, i+1);
                            }
                        }
                    if (tempInt == YES)
                        MrBayesPrint ("%s   Set state frequency prior to default\n", spacer);
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid DNA substitution model\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Nst (nst) **********************************************************************/
        else if (!strcmp(parmName, "Nst"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(NUMBER) | Expecting(ALPHA);
            else if (expecting == Expecting(NUMBER) || expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            if (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA)
                                {
                                strcpy(modelParams[i].nst, tempStr);
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Nst to %s\n", spacer, modelParams[i].nst);
                                else
                                    MrBayesPrint ("%s   Setting Nst to %s for partition %d\n", spacer, modelParams[i].nst, i+1);
                                }
                            else {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Nst =%s unchanged ", spacer, modelParams[i].nst);
                                else
                                    MrBayesPrint ("%s   Nst =%s unchanged for partition %d ", spacer, modelParams[i].nst, i+1);
                                MrBayesPrint ("because dataType is not DNA or RNA\n");
                                }
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Nst argument\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Ncat (numGammaCats) ************************************************************/
        else if (!strcmp(parmName, "Ngammacat"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(NUMBER);
            else if (expecting == Expecting(NUMBER))
                {
                sscanf (tkn, "%d", &tempInt);
                if (tempInt >= 2 && tempInt < MAX_GAMMA_CATS)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType != CONTINUOUS))
                            {
                            modelParams[i].numGammaCats = tempInt;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Ngammacat to %d\n", spacer, modelParams[i].numGammaCats);
                            else
                                MrBayesPrint ("%s   Setting Ngammacat to %d for partition %d\n", spacer, modelParams[i].numGammaCats, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Ngammacat argument (should be between 2 and %d)\n", spacer, MAX_GAMMA_CATS);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Usegibbs (useGibbs) *************************************************************/
        else if (!strcmp(parmName, "Usegibbs"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            if (!strcmp(tempStr, "Yes"))
                                {
                                MrBayesPrint ("%s   Downsampling of site rates ('usegibbs = yes') disabled temporarily because of conflict with likelihood calculators\n", spacer);
                                return (ERROR);
                                strcpy(modelParams[i].useGibbs, "Yes");
                                }
                            else
                                {
                                strcpy(modelParams[i].useGibbs, "No");
                                }

                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Usegibbs to %s (if applicable)\n", spacer, modelParams[i].useGibbs);
                            else
                                MrBayesPrint ("%s   Setting Usegibbs to %s (if applicable) for partition %d\n", spacer, modelParams[i].useGibbs, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid argument for Usegibbs (using Gibbs sampling of discrete gamma)\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }           
        /* set Gibbsfreq (gibbsFreq) ************************************************************/
        else if (!strcmp(parmName, "Gibbsfreq"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(NUMBER);
            else if (expecting == Expecting(NUMBER))
                {
                sscanf (tkn, "%d", &tempInt);
                if (tempInt >= 1 && tempInt <= 1000)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            modelParams[i].gibbsFreq = tempInt;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Gibbsfreq to %d\n", spacer, modelParams[i].gibbsFreq);
                            else
                                MrBayesPrint ("%s   Setting Gibbsfreq to %d for partition %d\n", spacer, modelParams[i].gibbsFreq, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Gibbsgammafreq argument (should be between 1 and 1000)\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set NumM10GammaCats (numM10GammaCats) ************************************************************/
        else if (!strcmp(parmName, "NumM10GammaCats"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(NUMBER);
            else if (expecting == Expecting(NUMBER))
                {
                sscanf (tkn, "%d", &tempInt);
                if (tempInt >= 2 && tempInt < MAX_GAMMA_CATS)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType != CONTINUOUS))
                            {
                            modelParams[i].numM10GammaCats = tempInt;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting NumM10GammaCats to %d\n", spacer, modelParams[i].numM10GammaCats);
                            else
                                MrBayesPrint ("%s   Setting NumM10GammaCats to %d for partition %d\n", spacer, modelParams[i].numM10GammaCats, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid NumM10GammaCats argument (should be between 2 and %d)\n", spacer, MAX_GAMMA_CATS);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set NumM10BetaCats (numM10BetaCats) ************************************************************/
        else if (!strcmp(parmName, "NumM10BetaCats"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(NUMBER);
            else if (expecting == Expecting(NUMBER))
                {
                sscanf (tkn, "%d", &tempInt);
                if (tempInt >= 2 && tempInt < MAX_GAMMA_CATS)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType != CONTINUOUS))
                            {
                            modelParams[i].numM10BetaCats = tempInt;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting NumM10BetaCats to %d\n", spacer, modelParams[i].numM10BetaCats);
                            else
                                MrBayesPrint ("%s   Setting NumM10BetaCats to %d for partition %d\n", spacer, modelParams[i].numM10BetaCats, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid NumM10GammaCats argument (should be between 2 and %d)\n", spacer, MAX_GAMMA_CATS);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Nbetacat (numBetaCats) *****************************************************/
        else if (!strcmp(parmName, "Nbetacat"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(NUMBER);
            else if (expecting == Expecting(NUMBER))
                {
                sscanf (tkn, "%d", &tempInt);
                if (tempInt >= 2 && tempInt < MAX_GAMMA_CATS)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == STANDARD || modelParams[i].dataType == RESTRICTION))
                            {
                            modelParams[i].numBetaCats = tempInt;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Nbetacat to %d\n", spacer, modelParams[i].numBetaCats);
                            else
                                MrBayesPrint ("%s   Setting Nbetacat to %d for partition %d\n", spacer, modelParams[i].numBetaCats, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Nbetacat argument (should be between 2 and %d)\n", spacer, MAX_GAMMA_CATS);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Aamodel (aaModel) **************************************************************/
        else if (!strcmp(parmName, "Aamodel"))
            {
            MrBayesPrint ("%s   Aamodel argument for lset deprecated.\n", spacer);
            MrBayesPrint ("%s   Use 'prset aamodelpr=fixed(<aamodel>)' instead.\n", spacer);
            return (ERROR);
            }
        /* set Parsmodel (useParsModel) *******************************************************/
        else if (!strcmp(parmName, "Parsmodel"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            if (!strcmp(tempStr, "Yes"))
                                strcpy(modelParams[i].parsModel, "Yes");
                            else
                                strcpy(modelParams[i].parsModel, "No");

                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Parsmodel to %s\n", spacer, modelParams[i].parsModel);
                            else
                                MrBayesPrint ("%s   Setting Parsmodel to %s for partition %d\n", spacer, modelParams[i].parsModel, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid argument for using (so-called) parsimony model\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }           
        /* set Augment (augmentData) **********************************************************/
        else if (!strcmp(parmName, "Augment"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && modelParams[i].dataType != CONTINUOUS)
                            {
                            if (!strcmp(tempStr, "Yes"))
                                strcpy(modelParams[i].augmentData, "Yes");
                            else
                                strcpy(modelParams[i].augmentData, "No");

                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Augmentdata to %s\n", spacer, modelParams[i].augmentData);
                            else
                                MrBayesPrint ("%s   Setting Augmentdata to %s for partition %d\n", spacer, modelParams[i].augmentData, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid argument for data augmentation\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }           
        /* set Omegavar (wVarModel) ***********************************************************/
        else if (!strcmp(parmName, "Omegavar"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].omegaVar, tempStr);
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Omegavar to %s\n", spacer, modelParams[i].omegaVar);
                            else
                                MrBayesPrint ("%s   Setting Omegavar to %s for partition %d\n", spacer, modelParams[i].omegaVar, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid omega variation argument\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Code (codeModel) ***************************************************************/
        else if (!strcmp(parmName, "Code"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].geneticCode, tempStr);
                            SetCode (i);
                            modelParams[i].nStates = NumStates (i);
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Code to %s\n", spacer, modelParams[i].geneticCode);
                            else
                                MrBayesPrint ("%s   Setting Code to %s for partition %d\n", spacer, modelParams[i].geneticCode, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid genetic code argument\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Ploidy (ploidy) ***************************************************************/
        else if (!strcmp(parmName, "Ploidy"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].ploidy, tempStr);
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting ploidy level to %s\n", spacer, modelParams[i].ploidy);
                            else
                                MrBayesPrint ("%s   Setting ploidy level to %s for partition %d\n", spacer, modelParams[i].ploidy, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid ploidy level argument\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Rates (ratesModel) *************************************************************/
        else if (!strcmp(parmName, "Rates"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && modelParams[i].dataType != CONTINUOUS)
                            {
                            if (!strcmp(tempStr, "Adgamma") && (modelParams[i].dataType != DNA && modelParams[i].dataType != RNA && modelParams[i].dataType != PROTEIN))
                                {
                                /* we won't apply an adgamma model to anything but DNA, RNA, or PROTEIN data */
                                }
                            else if ((!strcmp(tempStr, "Propinv") ||  !strcmp(tempStr, "Invgamma")) && (modelParams[i].dataType == STANDARD || modelParams[i].dataType == RESTRICTION))
                                {
                                /* we will not apply pinvar to standard or restriction site data */
                                }
                            else
                                {
                                strcpy(modelParams[i].ratesModel, tempStr);
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Rates to %s\n", spacer, modelParams[i].ratesModel);
                                else
                                    MrBayesPrint ("%s   Setting Rates to %s for partition %d\n", spacer, modelParams[i].ratesModel, i+1);
                                }
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Rates argument\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Covarion (covarionModel) *******************************************************/
        else if (!strcmp(parmName, "Covarion"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA || modelParams[i].dataType == PROTEIN))
                            {
                            strcpy(modelParams[i].covarionModel, tempStr);
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Covarion to %s\n", spacer, modelParams[i].covarionModel);
                            else
                                MrBayesPrint ("%s   Setting Covarion to %s for partition %d\n", spacer, modelParams[i].covarionModel, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Rates argument\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Coding (missingType) ***********************************************************/
        else if (!strcmp(parmName, "Coding"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == RESTRICTION || modelParams[i].dataType == STANDARD))
                            {
                            strcpy(modelParams[i].coding, tempStr);
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Coding to %s\n", spacer, modelParams[i].coding);
                            else
                                MrBayesPrint ("%s   Setting Coding to %s for partition %d\n", spacer, modelParams[i].coding, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid argument for missing patterns\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
                
                
                
                
        else
            return (ERROR);
        }

    return (NO_ERROR);
}


int DoPlot (void)
{
    int             i, n, nHeaders, burnin, len, longestHeader, whichIsX, whichIsY, numPlotted;
    char            temp[100], **headerNames = NULL;
    SumpFileInfo    fileInfo;
    ParameterSample *parameterSamples;
    
#   if defined (MPI_ENABLED)
    if (proc_id != 0)
        return NO_ERROR;
#   endif
    
    /* initialize values */
    headerNames = NULL;
    nHeaders = 0;
    parameterSamples = NULL;
    
    /* tell user we are ready to go */
    MrBayesPrint ("%s   Plotting parameters in file %s ...\n", spacer, plotParams.plotFileName);
    
    /* examine plot file */
    if (ExamineSumpFile (plotParams.plotFileName, &fileInfo, &headerNames, &nHeaders) == ERROR)
        return ERROR;
    
    /* Calculate burn in */
    burnin = fileInfo.firstParamLine - fileInfo.headerLine - 1;
    
    /* tell the user that everything is fine */
    MrBayesPrint ("%s   Found %d parameter lines in file \"%s\"\n", spacer, fileInfo.numRows + burnin, plotParams.plotFileName);
    if (burnin > 0)
        MrBayesPrint ("%s   Of the %d lines, %d of them will be summarized (starting at line %d)\n", spacer, fileInfo.numRows+burnin, fileInfo.numRows, fileInfo.firstParamLine);
    else
        MrBayesPrint ("%s   All %d lines will be summarized (starting at line %d)\n", spacer, fileInfo.numRows, fileInfo.firstParamLine);
    MrBayesPrint ("%s   (Only the last set of lines will be read, in case multiple\n", spacer);
    MrBayesPrint ("%s   parameter blocks are present in the same file.)\n", spacer);
    
    /* allocate space to hold parameter information */
    if (AllocateParameterSamples (&parameterSamples, 1, fileInfo.numRows, fileInfo.numColumns) == ERROR)
        goto errorExit;
    
    /* Now we read the file for real. First, rewind file pointer to beginning of file... */
    if (ReadParamSamples (plotParams.plotFileName, &fileInfo, parameterSamples, 0) == ERROR)
        goto errorExit;
    
    /* get length of longest header */
    longestHeader = 9; /* 9 is the length of the word "parameter" (for printing table) */
    for (i=0; i<nHeaders; i++)
        {
        len = (int) strlen(headerNames[i]);
        if (len > longestHeader)
            longestHeader = len;
        }
    
    /* print x-y plot of parameter vs. generation */
    whichIsX = -1;
    for (i=0; i<nHeaders; i++)
        {
        if (IsSame (headerNames[i], "Gen") == SAME)
            whichIsX = i;
        }
    
    if (whichIsX < 0)
        {
        MrBayesPrint ("%s   Could not find a column labelled \"Gen\" \n", spacer);
        goto errorExit;
        }
    
    numPlotted = 0;
    for (n=0; n<nHeaders; n++)
        {
        strcpy (temp, headerNames[n]);
        whichIsY = -1;
        if (!strcmp(plotParams.match, "Perfect"))
            {
            if (IsSame (temp, plotParams.parameter) == SAME)
                whichIsY = n;
            }
        else if (!strcmp(plotParams.match, "All"))
            {
            whichIsY = n;
            }
        else
            {
            if (IsSame (temp, plotParams.parameter) == CONSISTENT_WITH)
                whichIsY = n;
            }
        
        if (whichIsY >= 0 && whichIsX != whichIsY)
            {
            MrBayesPrint ("\n%s   Rough trace plot of parameter %s:\n", spacer, headerNames[whichIsY]);
            if (PrintPlot (parameterSamples[whichIsX].values[0], parameterSamples[whichIsY].values[0], fileInfo.numRows) == ERROR)
                goto errorExit;
            numPlotted++;
            }
        }
    
    if (numPlotted == 0)
        {
        MrBayesPrint ("%s   Did not find any parameters matching \"%s\" to plot\n", spacer, plotParams.parameter);
        }
    
    /* free memory */
    for (i=0; i<nHeaders; i++)
        free (headerNames[i]);
    free(headerNames);
    FreeParameterSamples(parameterSamples);
    
    expecting = Expecting(COMMAND);
    
    return (NO_ERROR);
    
errorExit:
    
    /* free memory */
    for (i=0; i<nHeaders; i++)
        free (headerNames[i]);
    free(headerNames);
    FreeParameterSamples(parameterSamples);
    
    expecting = Expecting(COMMAND);
    
    return (ERROR);
}


int DoPlotParm (char *parmName, char *tkn)
{
    int         tempI;
    MrBFlt      tempD;
    char        tempStr[100];
    
    if (defMatrix == NO)
        {
        MrBayesPrint ("%s   A matrix must be specified before sumt can be used\n", spacer);
        return (ERROR);
        }
    
    if (expecting == Expecting(PARAMETER))
        {
        expecting = Expecting(EQUALSIGN);
        }
    else
        {
        if (!strcmp(parmName, "Xxxxxxxxxx"))
            {
            expecting  = Expecting(PARAMETER);
            expecting |= Expecting(SEMICOLON);
            }
        /* set Filename (plotParams.plotFileName) ***************************************************/
        else if (!strcmp(parmName, "Filename"))
            {
            if (expecting == Expecting(EQUALSIGN))
                {
                expecting = Expecting(ALPHA);
                readWord = YES;
                }
            else if (expecting == Expecting(ALPHA))
                {
                strcpy (plotParams.plotFileName, tkn);
                MrBayesPrint ("%s   Setting plot filename to %s\n", spacer, plotParams.plotFileName);
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Relburnin (chainParams.relativeBurnin) ********************************************************/
        else if (!strcmp(parmName, "Relburnin"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    if (!strcmp(tempStr, "Yes"))
                        chainParams.relativeBurnin = YES;
                    else
                        chainParams.relativeBurnin = NO;
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid argument for Relburnin\n", spacer);
                    return (ERROR);
                    }
                if (chainParams.relativeBurnin == YES)
                    MrBayesPrint ("%s   Using relative burnin (a fraction of samples discarded).\n", spacer);
                else
                    MrBayesPrint ("%s   Using absolute burnin (a fixed number of samples discarded).\n", spacer);
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                {
                return (ERROR);
                }
            }
        /* set Burnin (chainParams.chainBurnIn) *******************************************************/
        else if (!strcmp(parmName, "Burnin"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(NUMBER);
            else if (expecting == Expecting(NUMBER))
                {
                sscanf (tkn, "%d", &tempI);
                chainParams.chainBurnIn = tempI;
                MrBayesPrint ("%s   Setting burnin to %d\n", spacer, chainParams.chainBurnIn);
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Burninfrac (chainParams.burninFraction) ************************************************************/
        else if (!strcmp(parmName, "Burninfrac"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(NUMBER);
            else if (expecting == Expecting(NUMBER))
                {
                sscanf (tkn, "%lf", &tempD);
                if (tempD < 0.01)
                    {
                    MrBayesPrint ("%s   Burnin fraction too low (< 0.01)\n", spacer);
                    return (ERROR);
                    }
                if (tempD > 0.50)
                    {
                    MrBayesPrint ("%s   Burnin fraction too high (> 0.50)\n", spacer);
                    return (ERROR);
                    }
                chainParams.burninFraction = tempD;
                MrBayesPrint ("%s   Setting burnin fraction to %.2f\n", spacer, chainParams.burninFraction);
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                {
                return (ERROR);
                }
            }
        /* set Parameter (plotParams.parameter) *******************************************************/
        else if (!strcmp(parmName, "Parameter"))
            {
            if (expecting == Expecting(EQUALSIGN))
                {
                expecting = Expecting(ALPHA);
                readWord = YES;
                }
            else if (expecting == Expecting(ALPHA))
                {
                strcpy (plotParams.parameter, tkn);
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Parameter (plotParams.match) *******************************************************/
        else if (!strcmp(parmName, "Match"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    strcpy (plotParams.match, tempStr);
                else
                    return (ERROR);
                
                MrBayesPrint ("%s   Setting plot matching to %s\n", spacer, plotParams.match);
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        
        else
            return (ERROR);
        }
    
    return (NO_ERROR);
}


int DoPropset (void)
{
    MrBayesPrint ("%s   Successfully set proposal parameters\n", spacer);
    
    return (NO_ERROR);
}


int DoPropsetParm (char *parmName, char *tkn)
{
    int                 i, j, k, nMatches, tempInt;
    MrBFlt              tempFloat;
    static MCMCMove     *mv = NULL;
    static MrBFlt       *theValue, theValueMin, theValueMax;
    static int          jump, runIndex, chainIndex;
    static char         *temp=NULL, *localTkn=NULL; /*freed at the end of the call*/
    static char         *tempName=NULL;         /*not freed at the end of the call*/

    if (defMatrix == NO)
        {
        MrBayesPrint ("%s   A matrix must be specified before proposal parameters can be changed\n", spacer);
        return (ERROR);
        }

    if (expecting == Expecting(PARAMETER))
        {
        if (!strcmp(parmName, "Xxxxxxxxxx"))
            {
            /* we expect a move name with possible run and chain specification as follows:
               <move_name>$<tuning_param_name>(<run>,<chain>)=<number>   -- apply to run <run> and chain <chain>
               <move_name>$<tuning_param_name>(,<chain>)=<number>        -- apply to chain <chain> for all runs
               <move_name>$<tuning_param_name>(<run>,)=<number>          -- apply to all chains of run <run>
               <move_name>$prob(<run>,<chain>)=<number>                  -- change relative proposal probability
               <move_name>$targetrate(<run>,<chain>)=<number>            -- change target acc rate for autotuning

               the parsing is complicated by the fact that the move name can look something like:
               eTBR(Tau{all})
               eTBR(Tau{1,4,5})
               so we need to assemble the move name from several tokens that are parsed out separately;
               here we receive only the first part (before the left parenthesis)
            */
            
            /* copy to local move name */
            SafeStrcpy(&tempName, tkn);
            mv = NULL;
            foundComma = foundEqual = NO;
            expecting = Expecting(LEFTCURL) | Expecting(RIGHTCURL) | Expecting(COMMA) |
                Expecting(LEFTPAR) | Expecting(RIGHTPAR) | Expecting(NUMBER) | Expecting(ALPHA) |
                Expecting(DOLLAR);
            }
        else
            return (ERROR);
        }
    else if (expecting == Expecting(ALPHA))
        {
        if (mv == NULL)
            {
            /* we are still assembling the move name */
            SafeStrcat(&tempName, tkn);
            expecting = Expecting(LEFTCURL) | Expecting(RIGHTCURL) | Expecting(COMMA) |
                Expecting(LEFTPAR) | Expecting(RIGHTPAR) | Expecting(NUMBER) | Expecting(ALPHA) |
                Expecting(DOLLAR);
            }
        else
            {
            /* we have a parameter name; now find the parameter name, case insensitive */
            SafeStrcpy(&localTkn, tkn);
            for (i=0; i<(int)strlen(localTkn); i++)
                localTkn[i] = tolower(localTkn[i]);
            nMatches = j = 0;
            for (i=0; i<mv->moveType->numTuningParams; i++)
                {
                SafeStrcpy(&temp, mv->moveType->shortTuningName[i]);
                for (k=0; k<(int)strlen(temp); k++)
                    temp[k] = tolower(temp[k]);
                if (strncmp(localTkn,temp,strlen(localTkn)) == 0)
                    {
                    j = i;
                    nMatches++;
                    }
                }
            if (strncmp(localTkn,"prob",strlen(localTkn)) == 0)
                {
                j = -1;
                nMatches++;
                }
            else if (strncmp(localTkn,"targetrate",strlen(localTkn)) == 0)
                {
                j = -2;
                nMatches++;
                }
            if (nMatches == 0)
                {
                MrBayesPrint ("%s   Could not find move parameter to change '%s'\n", spacer, localTkn);  
                return (ERROR);
                }
            else if (nMatches > 1)
                {
                MrBayesPrint ("%s   Several move parameters matched the abbreviated name '%s'\n", spacer, localTkn);
                return (ERROR);
                }
            
            if (j == -1)
                {
                theValue = mv->relProposalProb;
                theValueMin = 0.0;
                theValueMax = 1000.0;
                jump = 1;
                }
            else if (j == -2)
                {
                theValue = mv->targetRate;
                theValueMin = 0.10;
                theValueMax = 0.70;
                jump = 1;
                }
            else
                {
                theValue = &mv->tuningParam[0][j];
                theValueMin = mv->moveType->minimum[j];
                theValueMax = mv->moveType->maximum[j];
                jump = mv->moveType->numTuningParams;
                }
            chainIndex = -1;
            runIndex = -1;
            expecting = Expecting(LEFTPAR) | Expecting(EQUALSIGN);
            }
        }
    else if (expecting == Expecting(LEFTCURL) || expecting == Expecting(RIGHTCURL))
        {
        /* we are still assembling the move name */
        SafeStrcat (&tempName, tkn);
        expecting = Expecting(LEFTCURL) | Expecting(RIGHTCURL) | Expecting(COMMA) |
            Expecting(LEFTPAR) | Expecting(RIGHTPAR) | Expecting(NUMBER) | Expecting(ALPHA) |
            Expecting(DOLLAR);
        }
    else if (expecting == Expecting(DOLLAR))
        {
        /* we know that the name is complete now; find the move by its name, 
           case insensitive */
        SafeStrcpy(&localTkn, tempName);
        j=(int)strlen(localTkn);
        for (i=0; i<j; i++)
            localTkn[i] = tolower(localTkn[i]);
            
        /* find the move */
        nMatches = j = 0;
        for (i=0; i<numApplicableMoves; i++)
            {
            mv = moves[i];
            SafeStrcpy(&temp,mv->name);
            for (k=0; k<(int)strlen(temp); k++)
                temp[k] = tolower(temp[k]);
            if (strncmp(temp,localTkn,strlen(localTkn)) == 0)
                {
                j = i;
                nMatches++;
                }
            }
        if (nMatches == 0)
            {
            MrBayesPrint ("%s   Could not find move '%s'\n", spacer, localTkn);   
            return (ERROR);
            }
        else if (nMatches > 1)
            {
            MrBayesPrint ("%s   Several moves matched the abbreviated name '%s'\n", spacer, localTkn);   
            return (ERROR);
            }
        else
            mv = moves[j];

        foundComma = foundEqual = NO;
        expecting = Expecting(ALPHA);
        }
    else if (expecting == Expecting(LEFTPAR))
        {
        if (mv == NULL)
            {
            /* we are still assembling the move name */
            SafeStrcat (&tempName, tkn);
            expecting = Expecting(LEFTCURL) | Expecting(RIGHTCURL) | Expecting(COMMA) |
                Expecting(LEFTPAR) | Expecting(RIGHTPAR) | Expecting(NUMBER) | Expecting(ALPHA) |
                Expecting(DOLLAR);
            }
        else /* if (mv != NULL) */
            {
            /* we will be reading in run and chain indices */
            expecting = Expecting(NUMBER) | Expecting(COMMA);
            }
        }
    else if (expecting == Expecting(NUMBER))
        {
        if (mv == NULL)
            {
            /* we are still assembling the move name */
            SafeStrcat (&tempName, tkn);
            expecting = Expecting(LEFTCURL) | Expecting(RIGHTCURL) | Expecting(COMMA) |
                Expecting(LEFTPAR) | Expecting(RIGHTPAR) | Expecting(NUMBER) | Expecting(ALPHA) |
                Expecting(DOLLAR);
            }
        else if (foundEqual == YES)
            {
            sscanf (tkn, "%lf", &tempFloat);
            if (tempFloat < theValueMin || tempFloat > theValueMax)
                {
                MrBayesPrint ("%s   The value is out of range (min = %lf; max = %lf)\n", spacer, theValueMin, theValueMax);
                return (ERROR);
                }
            if (runIndex == -1 && chainIndex == -1)
                {
                for (i=0; i<chainParams.numRuns; i++)
                    {
                    for (j=0; j<chainParams.numChains; j++)
                        {
                        *theValue = tempFloat;
                        theValue += jump;
                        }
                    }
                }
            else if (runIndex == -1 && chainIndex >= 0)
                {
                theValue += chainIndex*jump;
                for (i=0; i<chainParams.numRuns; i++)
                    {
                    *theValue = tempFloat;
                    theValue += chainParams.numChains*jump;
                    }
                }
            else if (runIndex >= 0 && chainIndex == -1)
                {
                theValue += runIndex*chainParams.numChains*jump;
                for (i=0; i<chainParams.numChains; i++)
                    {
                    *theValue = tempFloat;
                    theValue += jump;
                    }
                }
            else /* if (runIndex >= 0 && chainIndex >= 0) */
                {
                theValue[runIndex*chainParams.numChains*jump+chainIndex*jump] = tempFloat;
                }
            expecting = Expecting (PARAMETER) | Expecting(SEMICOLON);
            }
        else /* if (foundEqual == NO) */
            {
            sscanf (tkn, "%d", &tempInt);
            if (foundComma == NO)
                {
                if (tempInt <= 0 || tempInt > chainParams.numRuns)
                    {
                    MrBayesPrint ("%s   Run index is out of range (min=1; max=%d)\n", spacer, chainParams.numRuns);
                    return (ERROR);
                    }
                runIndex = tempInt - 1;
                expecting = Expecting(COMMA);
                }
            else
                {
                if (tempInt <= 0 || tempInt > chainParams.numChains)
                    {
                    MrBayesPrint ("%s   Chain index is out of range (min=1; max=%d)\n", spacer, chainParams.numChains);
                    return (ERROR);
                    }
                chainIndex = tempInt - 1;
                expecting = Expecting(RIGHTPAR);
                }
            }
        }
    else if (expecting == Expecting(COMMA))
        {
        if (mv == NULL)
            {
            /* we are still assembling the move name */
            SafeStrcat (&tempName, tkn);
            expecting = Expecting(LEFTCURL) | Expecting(RIGHTCURL) | Expecting(COMMA) |
                Expecting(LEFTPAR) | Expecting(RIGHTPAR) | Expecting(NUMBER) | Expecting(ALPHA) |
                Expecting(DOLLAR);
            }
        else
            {
            /* we will be reading in chain index, if present */
            foundComma = YES;
            expecting = Expecting(RIGHTPAR) | Expecting(NUMBER);
            }
        }
    else if (expecting == Expecting(RIGHTPAR))
        {
        if (mv == NULL)
            {
            /* we are still assembling the move name */
            SafeStrcat (&tempName, tkn);
            expecting = Expecting(LEFTCURL) | Expecting(RIGHTCURL) | Expecting(COMMA) |
                Expecting(LEFTPAR) | Expecting(RIGHTPAR) | Expecting(NUMBER) | Expecting(ALPHA) |
                Expecting(DOLLAR);
            }
        else
            expecting = Expecting(EQUALSIGN);
        }
    else if (expecting == Expecting(EQUALSIGN))
        {
        foundEqual = YES;
        expecting = Expecting(NUMBER);
        }
    else
        return (ERROR);

    SafeFree ((void **)&temp);
    SafeFree ((void **)&localTkn);
    return (NO_ERROR);
}


int DoPrset (void)
{
    int         i, nApplied, lastActive=0;

    nApplied = NumActiveParts ();
    for (i=numCurrentDivisions; i>=0; i--)
        {
        if (activeParts[i] == YES)
            {
            lastActive = i;
            break;
            }
        }
            
    if (numCurrentDivisions == 1)
        MrBayesPrint ("%s   Successfully set prior model parameters\n", spacer);
    else 
        {
        if (nApplied == numCurrentDivisions || nApplied == 0)
            {
            MrBayesPrint ("%s   Successfully set prior model parameters to all\n", spacer);
            MrBayesPrint ("%s   applicable data partitions \n", spacer);
            }
        else
            {
            MrBayesPrint ("%s   Successfully set prior model parameters to\n", spacer);
            if (nApplied == 1)
                MrBayesPrint ("%s   partition", spacer);
            else
                MrBayesPrint ("%s   partitions", spacer);
            for (i=0; i<numCurrentDivisions; i++)
                {
                if (activeParts[i] == YES)
                    {
                    if (i == lastActive && nApplied > 1)
                        MrBayesPrint (" and %d", i+1);
                    else
                        MrBayesPrint (" %d", i+1);
                    if (nApplied > 2 && i != lastActive)
                        MrBayesPrint (",");
                    }
                }
            MrBayesPrint (" (if applicable)\n");
            }
        }
    
    if (SetUpAnalysis (&globalSeed) == ERROR)
        return (ERROR);

    return (NO_ERROR);
}


int DoPrsetParm (char *parmName, char *tkn)
{
    int         i, j, k, tempInt, nApplied, index, ns, flag=0;
    MrBFlt      tempD, sum;
    char        tempStr[100];

    if (defMatrix == NO)
        {
        MrBayesPrint ("%s   A matrix must be specified before the model can be defined\n", spacer);
        return (ERROR);
        }
    if (inValidCommand == YES)
        {
        for (i=0; i<numCurrentDivisions; i++)
            activeParts[i] = NO;
        inValidCommand = NO;
        }

    if (expecting == Expecting(PARAMETER))
        {
        expecting = Expecting(EQUALSIGN);
        }
    else
        {
        /* set Applyto (Applyto) *************************************************************/
        if (!strcmp(parmName, "Applyto"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(LEFTPAR);
            else if (expecting == Expecting(LEFTPAR))
                {
                for (i=0; i<numCurrentDivisions; i++)
                    activeParts[i] = NO;
                fromI = toJ = -1;
                foundDash = NO;
                expecting = Expecting(NUMBER) | Expecting(ALPHA);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                if (fromI != -1)
                    activeParts[fromI-1] = YES;
#               if 0
                for (i=0; i<numCurrentDivisions; i++)
                    MrBayesPrint("%d ", activeParts[i]);
                MrBayesPrint ("\n");
#               endif
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else if (expecting == Expecting(COMMA))
                {
                foundComma = YES;
                expecting = Expecting(NUMBER);
                }
            else if (expecting == Expecting(ALPHA))
                {
                if (IsSame ("All", tkn) == DIFFERENT)
                    {
                    MrBayesPrint ("%s   Do not understand delimiter \"%s\"\n", spacer, tkn);
                    return (ERROR);
                    }
                for (i=0; i<numCurrentDivisions; i++)
                    activeParts[i] = YES;
                expecting  = Expecting(RIGHTPAR);
                }
            else if (expecting == Expecting(NUMBER))
                {
                sscanf (tkn, "%d", &tempInt);
                if (tempInt > numCurrentDivisions)
                    {
                    MrBayesPrint ("%s   Partition delimiter is too large\n", spacer);
                    return (ERROR);
                    }
                if (fromI == -1)
                    fromI = tempInt;
                else if (fromI != -1 && toJ == -1 && foundDash == YES && foundComma == NO)
                    {
                    toJ = tempInt;
                    for (i=fromI-1; i<toJ; i++)
                        activeParts[i] = YES;
                    fromI = toJ = -1;
                    foundDash = NO;
                    }
                else if (fromI != -1 && toJ == -1 && foundDash == NO && foundComma == YES)
                    {
                    activeParts[fromI-1] = YES;
                    fromI = tempInt;
                    foundComma = NO;
                    }
                    
                expecting  = Expecting(COMMA);
                expecting |= Expecting(DASH);
                expecting |= Expecting(RIGHTPAR);
                }
            else if (expecting == Expecting(DASH))
                {
                foundDash = YES;
                expecting = Expecting(NUMBER);
                }
            else
                return (ERROR);
            }
        /* set Tratiopr (tRatioPr) ************************************************************/
        else if (!strcmp(parmName, "Tratiopr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].tRatioPr, tempStr);
                            modelParams[i].tRatioDir[0] = modelParams[i].tRatioDir[1] = 1.0;
                            modelParams[i].tRatioFix = 1.0;
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                        {
                        MrBayesPrint ("%s   Warning: %s can be set only for partition containing either DNA or RNA data.\
                            Currently there is no active partition with such data.\n", spacer, parmName);
                        return (ERROR);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Tratiopr argument \n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                        {
                        if (!strcmp(modelParams[i].tRatioPr,"Beta"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD > ALPHA_MAX)
                                {
                                MrBayesPrint ("%s   Beta parameter cannot be greater than %1.2lf\n", spacer, ALPHA_MAX);
                                return (ERROR);
                                }
                            if (tempD < ALPHA_MIN)
                                {
                                MrBayesPrint ("%s   Beta parameter cannot be less than %1.2lf\n", spacer, ALPHA_MIN);
                                return (ERROR);
                                }
                            modelParams[i].tRatioDir[numVars[i]++] = tempD;
                            if (numVars[i] < 2)
                                expecting = Expecting(COMMA);
                            else
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Tratiopr to Beta(%1.2lf,%1.2lf)\n", spacer, modelParams[i].tRatioDir[0], modelParams[i].tRatioDir[1]);
                                else
                                    MrBayesPrint ("%s   Setting Tratiopr to Beta(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].tRatioDir[0], modelParams[i].tRatioDir[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].tRatioPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].tRatioFix = tempD;
                            if (modelParams[i].tRatioFix > KAPPA_MAX)
                                {
                                MrBayesPrint ("%s   Tratio cannot be greater than %1.2lf\n", spacer, KAPPA_MAX);
                                return (ERROR);
                                }
                            if (modelParams[i].tRatioFix < 0.0)
                                {
                                MrBayesPrint ("%s   Tratio cannot be less than %1.2lf\n", spacer, 0.0);
                                return (ERROR);
                                }
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Tratiopr to Fixed(%1.2lf)\n", spacer, modelParams[i].tRatioFix);
                            else
                                MrBayesPrint ("%s   Setting Tratiopr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].tRatioFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Revmatpr (revMatPr) ************************************************************/
        else if (!strcmp(parmName, "Revmatpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].revMatPr, tempStr);
                            modelParams[i].revMatDir[0] = modelParams[i].revMatDir[1] = 1.0;
                            modelParams[i].revMatDir[2] = modelParams[i].revMatDir[3] = 1.0;
                            modelParams[i].revMatDir[4] = modelParams[i].revMatDir[5] = 1.0;
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                        {
                        MrBayesPrint ("%s   Warning: %s can be set only for partition containing either DNA or RNA data.\
                            Currently there is no active partition with such data.\n", spacer, parmName);
                        return (ERROR);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Revmatpr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                tempNumStates = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                /* find out what type of prior is being set */
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                        strcpy (tempStr,modelParams[i].revMatPr);
                    }
                /* find and store the number */
                sscanf (tkn, "%lf", &tempD);
                if (!strcmp(tempStr,"Dirichlet"))
                    {
                    if (tempD > ALPHA_MAX)
                        {
                        MrBayesPrint ("%s   Dirichlet parameter cannot be greater than %1.2lf\n", spacer, ALPHA_MAX);
                        return (ERROR);
                        }
                    if (tempD < ALPHA_MIN)
                        {
                        MrBayesPrint ("%s   Dirichlet parameter cannot be less than %1.2lf\n", spacer, ALPHA_MIN);
                        return (ERROR);
                        }
                    }
                else if (!strcmp(tempStr,"Fixed"))
                    {
                    if (tempD > KAPPA_MAX)
                        {
                        MrBayesPrint ("%s   Rate value cannot be greater than %1.2lf\n", spacer, KAPPA_MAX);
                        return (ERROR);
                        }
                    if (tempD < 0.0001)
                        {
                        MrBayesPrint ("%s   Rate value cannot be less than %1.2lf\n", spacer, 0.0001);
                        return (ERROR);
                        }
                    }
                tempNum[tempNumStates++] = tempD;
                if (tempNumStates == 1 && !strcmp(tempStr,"Dirichlet"))
                    expecting = Expecting(COMMA) | Expecting(RIGHTPAR);
                else if (tempNumStates < 6)
                    expecting  = Expecting(COMMA);
                else
                    expecting = Expecting(RIGHTPAR);
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                        {
                        if (!strcmp(modelParams[i].revMatPr,"Dirichlet"))
                            {
                            for (j=0; j<6; j++)
                                {
                                if (tempNumStates == 1)
                                    modelParams[i].revMatDir[j] = tempNum[0] / (MrBFlt) 6.0;
                                else
                                    modelParams[i].revMatDir[j] = tempNum[j];
                                }

                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Revmatpr to Dirichlet(%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf)\n", spacer, 
                                modelParams[i].revMatDir[0], modelParams[i].revMatDir[1], modelParams[i].revMatDir[2],
                                modelParams[i].revMatDir[3], modelParams[i].revMatDir[4], modelParams[i].revMatDir[5]);
                            else
                                MrBayesPrint ("%s   Setting Revmatpr to Dirichlet(%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf) for partition %d\n", spacer, 
                                modelParams[i].revMatDir[0], modelParams[i].revMatDir[1], modelParams[i].revMatDir[2],
                                modelParams[i].revMatDir[3], modelParams[i].revMatDir[4], modelParams[i].revMatDir[5], i+1);
                            }
                        else if (!strcmp(modelParams[i].revMatPr,"Fixed"))
                            {
                            for (j=0; j<6; j++)
                                modelParams[i].revMatFix[j] = tempNum[j];
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Revmatpr to Fixed(%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf)\n", spacer, 
                                modelParams[i].revMatFix[0], modelParams[i].revMatFix[1], modelParams[i].revMatFix[2],
                                modelParams[i].revMatFix[3], modelParams[i].revMatFix[4], modelParams[i].revMatFix[5]);
                            else
                                MrBayesPrint ("%s   Setting Revmatpr to Fixed(%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf) for partition %d\n", spacer, 
                                modelParams[i].revMatFix[0], modelParams[i].revMatFix[1], modelParams[i].revMatFix[2],
                                modelParams[i].revMatFix[3], modelParams[i].revMatFix[4], modelParams[i].revMatFix[5], i+1);
                            }
                        }
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Aarevmatpr (aaRevMatPr) ********************************************************/
        else if (!strcmp(parmName, "Aarevmatpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && modelSettings[i].dataType == PROTEIN)
                            {
                            strcpy(modelParams[i].aaRevMatPr, tempStr);
                            for (j=0; j<190; j++)
                                modelParams[i].aaRevMatDir[j] = 1.0;
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                        {
                        MrBayesPrint ("%s   Warning: %s can be set only for partition containing PROTEIN.\
                            Currently there is no active partition with such data.\n", spacer, parmName);
                        return (ERROR);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Aarevmatpr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                tempNumStates = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                /* find out what type of prior is being set */
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && modelSettings[i].dataType == PROTEIN)
                        strcpy (tempStr,modelParams[i].aaRevMatPr);
                    }
                /* find and store the number */
                sscanf (tkn, "%lf", &tempD);
                if (!strcmp(tempStr,"Dirichlet"))
                    {
                    if (tempD > ALPHA_MAX)
                        {
                        MrBayesPrint ("%s   Dirichlet parameter cannot be greater than %1.2lf\n", spacer, ALPHA_MAX);
                        return (ERROR);
                        }
                    if (tempD < ALPHA_MIN)
                        {
                        MrBayesPrint ("%s   Dirichlet parameter cannot be less than %1.2lf\n", spacer, ALPHA_MIN);
                        return (ERROR);
                        }
                    }
                else if (!strcmp(tempStr,"Fixed"))
                    {
                    if (tempD > KAPPA_MAX)
                        {
                        MrBayesPrint ("%s   Rate value cannot be greater than %1.2lf\n", spacer, KAPPA_MAX);
                        return (ERROR);
                        }
                    if (tempD < 0.0001)
                        {
                        MrBayesPrint ("%s   Rate value cannot be less than %1.2lf\n", spacer, 0.0001);
                        return (ERROR);
                        }
                    }
                tempStateFreqs[tempNumStates++] = tempD;
                if (tempNumStates == 1 && !strcmp(tempStr,"Dirichlet"))
                    expecting = Expecting(COMMA) | Expecting(RIGHTPAR);
                else if (tempNumStates < 190)
                    expecting  = Expecting(COMMA);
                else
                    expecting = Expecting(RIGHTPAR);
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && modelParams[i].dataType == PROTEIN)
                        {
                        if (!strcmp(modelParams[i].aaRevMatPr,"Dirichlet"))
                            {
                            for (j=0; j<190; j++)
                                {
                                if (tempNumStates == 1)
                                    modelParams[i].aaRevMatDir[j] = tempStateFreqs[0] / (MrBFlt) 190.0;
                                else
                                    modelParams[i].aaRevMatDir[j] = tempStateFreqs[j];
                                }
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                {
                                for (j=0; j<190; j++)
                                    if (AreDoublesEqual(modelParams[i].aaRevMatDir[0], modelParams[i].aaRevMatDir[j], 0.00001) == NO)
                                        break;
                                if (j == 190)
                                    MrBayesPrint ("%s   Setting Aarevmatpr to Dirichlet(%1.2lf,%1.2lf,...)\n", spacer,
                                        modelParams[i].aaRevMatDir[0], modelParams[i].aaRevMatDir[0]);
                                else
                                    {
                                    MrBayesPrint ("%s   Setting Aarevmatpr to Dirichlet(\n", spacer);
                                    for (j=0; j<190; j++)
                                        {
                                        if (j % 10 == 0)
                                            MrBayesPrint ("%s      ", spacer);
                                        MrBayesPrint ("%1.2lf", modelParams[i].aaRevMatDir[j]);
                                        if (j == 189)
                                            MrBayesPrint (")\n");
                                        else if ((j+1) % 10 == 0)
                                            MrBayesPrint (",\n");
                                        else
                                            MrBayesPrint (",");
                                        }
                                    }
                                }
                            else
                                {
                                for (j=0; j<190; j++)
                                    if (AreDoublesEqual(modelParams[i].aaRevMatDir[0], modelParams[i].aaRevMatDir[j], 0.00001) == NO)
                                        break;
                                if (j == 190)
                                    MrBayesPrint ("%s   Setting Aarevmatpr to Dirichlet(%1.2lf,%1.2lf,...) for partition %d\n",
                                        spacer, modelParams[i].aaRevMatDir[0], modelParams[i].aaRevMatDir[0], i+1);
                                else
                                    {
                                    MrBayesPrint ("%s   Setting Aarevmatpr to Dirichlet(\n", spacer);
                                    for (j=0; j<190; j++)
                                        {
                                        if (j % 10 == 0)
                                            MrBayesPrint ("%s      ", spacer);
                                        MrBayesPrint ("%1.2lf", modelParams[i].aaRevMatDir[j]);
                                        if (j == 189)
                                            MrBayesPrint (")\n");
                                        else if ((j+1) % 10 == 0)
                                            MrBayesPrint (",\n");
                                        else
                                            MrBayesPrint (",");
                                        }
                                    }
                                    MrBayesPrint ("%s      for partition %d\n", spacer, i+1);
                                }
                            }
                        else if (!strcmp(modelParams[i].aaRevMatPr,"Fixed"))
                            {
                            for (j=0; j<190; j++)
                                modelParams[i].aaRevMatFix[j] = tempStateFreqs[j];
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                {
                                for (j=0; j<190; j++)
                                    if (AreDoublesEqual(modelParams[i].aaRevMatFix[0], modelParams[i].aaRevMatFix[j], 0.00001) == NO)
                                        break;
                                if (j == 190)
                                    MrBayesPrint ("%s   Setting Aarevmatpr to Fixed(%1.2lf,%1.2lf,...)\n", spacer, modelParams[i].aaRevMatFix[0],
                                        modelParams[i].aaRevMatFix[0]);
                                else
                                    {
                                    MrBayesPrint ("%s   Setting Aarevmatpr to Fixed(\n", spacer);
                                    for (j=0; j<190; j++)
                                        {
                                        if (j % 10 == 0)
                                            MrBayesPrint ("%s      ", spacer);
                                        MrBayesPrint ("%1.2lf", modelParams[i].aaRevMatFix[j]);
                                        if (j == 189)
                                            MrBayesPrint (")\n");
                                        else if ((j+1) % 10 == 0)
                                            MrBayesPrint (",\n");
                                        else
                                            MrBayesPrint (",");
                                        }
                                    }
                                }
                            else
                                {
                                for (j=0; j<190; j++)
                                    if (AreDoublesEqual(modelParams[i].aaRevMatFix[0], modelParams[i].aaRevMatFix[j], 0.00001) == NO)
                                        break;
                                if (j == 190)
                                    MrBayesPrint ("%s   Setting Aarevmatpr to Fixed(%1.2lf,%1.2lf,...) for partition %d\n", spacer,
                                        modelParams[i].aaRevMatFix[0], modelParams[i].aaRevMatFix[0], i+1);
                                else
                                    {
                                    MrBayesPrint ("%s   Setting Aarevmatpr to Fixed(\n", spacer);
                                    for (j=0; j<190; j++)
                                        {
                                        if (j % 10 == 0)
                                            MrBayesPrint ("%s      ", spacer);
                                        MrBayesPrint ("%1.2lf", modelParams[i].aaRevMatFix[j]);
                                        if (j == 189)
                                            MrBayesPrint (")\n");
                                        else if ((j+1) % 10 == 0)
                                            MrBayesPrint (",\n");
                                        else
                                            MrBayesPrint (",");
                                        }
                                    }
                                    MrBayesPrint ("%s      for partition %d\n", spacer, i+1);
                                }
                            }
                        }
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Revratepr (revSymDirPr) ****************************************************/
        else if (!strcmp(parmName, "Revratepr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == ERROR)  /* we only allow symmetric dirichlet prior, so no need to store the value */
                    {
                    MrBayesPrint ("%s   Invalid Revratepr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if (activeParts[i] == YES || nApplied == 0)
                        {
                        sscanf (tkn, "%lf", &tempD);
                        if (tempD <= 0.0)
                            {
                            MrBayesPrint ("%s   Symmetric Dirichlet parameter must be positive\n", spacer);
                            return (ERROR);
                            }
                        modelParams[i].revMatSymDir = tempD;
                        if (nApplied == 0 && numCurrentDivisions == 1)
                            MrBayesPrint ("%s   Setting Revratepr to Symmetric Dirichlet(%1.2lf)\n", spacer, modelParams[i].revMatSymDir);
                        else
                            MrBayesPrint ("%s   Setting Revratepr to Symmetric Dirichlet(%1.2lf) for partition %d\n", spacer, modelParams[i].revMatSymDir, i+1);
                        expecting  = Expecting(RIGHTPAR);
                        }
                    }
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Omegapr (omegaPr) **************************************************************/
        else if (!strcmp(parmName, "Omegapr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].omegaPr, tempStr);
                            modelParams[i].omegaDir[0] = modelParams[i].omegaDir[1] = 1.0;
                            modelParams[i].omegaFix = 1.0;
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                        {
                        MrBayesPrint ("%s   Warning: %s can be set only for partition containing either DNA or RNA data.\
                            Currently there is no active partition with such data.\n", spacer, parmName);
                        return (ERROR);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Omegapr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                        {
                        if (!strcmp(modelParams[i].omegaPr,"Dirichlet"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD > ALPHA_MAX)
                                {
                                MrBayesPrint ("%s   Dirichlet parameter cannot be greater than %1.2lf\n", spacer, ALPHA_MAX);
                                return (ERROR);
                                }
                            if (tempD < ALPHA_MIN)
                                {
                                MrBayesPrint ("%s   Dirichlet parameter cannot be less than %1.2lf\n", spacer, ALPHA_MIN);
                                return (ERROR);
                                }
                            modelParams[i].omegaDir[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting = Expecting(COMMA);
                            else
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Omegapr to Dirichlet(%1.2lf,%1.2lf)\n", spacer, modelParams[i].omegaDir[0], modelParams[i].omegaDir[1]);
                                else
                                    MrBayesPrint ("%s   Setting Omegapr to Dirichlet(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].omegaDir[0], modelParams[i].omegaDir[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].omegaPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].omegaFix = tempD;
                            if (modelParams[i].omegaFix > KAPPA_MAX)
                                {
                                MrBayesPrint ("%s   Omega ratio cannot be greater than %1.2lf\n", spacer, KAPPA_MAX);
                                return (ERROR);
                                }
                            if (modelParams[i].omegaFix < 0.0)
                                {
                                MrBayesPrint ("%s   Omega ratio cannot be less than %1.2lf\n", spacer, 0.0);
                                return (ERROR);
                                }
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Omegapr to Fixed(%1.2lf)\n", spacer, modelParams[i].omegaFix);
                            else
                                MrBayesPrint ("%s   Setting Omegapr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].omegaFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Ny98omega1pr (ny98omega1pr) ********************************************************/
        else if (!strcmp(parmName, "Ny98omega1pr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].ny98omega1pr, tempStr);
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                        {
                        MrBayesPrint ("%s   Warning: %s can be set only for partition containing either DNA or RNA data.\
                            Currently there is no active partition with such data. The setting is ignored.\n", spacer, parmName);
                        return (ERROR);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Ny98omega1pr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                        {
                        if (!strcmp(modelParams[i].ny98omega1pr,"Beta"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].ny98omega1Beta[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].ny98omega1Beta[0] < 0 || modelParams[i].ny98omega1Beta[1] < 0)
                                    {
                                    MrBayesPrint ("%s   Beta parameter should be greater than 0\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Ny98omega1pr to Beta(%1.2lf,%1.2lf)\n", spacer, modelParams[i].ny98omega1Beta[0], modelParams[i].ny98omega1Beta[1]);
                                else
                                    MrBayesPrint ("%s   Setting Ny98omega1pr to Beta(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].ny98omega1Beta[0], modelParams[i].ny98omega1Beta[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].ny98omega1pr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].ny98omega1Fixed = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Ny98omega1pr to Fixed(%1.2lf)\n", spacer, modelParams[i].ny98omega1Fixed);
                            else
                                MrBayesPrint ("%s   Setting Ny98omega1pr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].ny98omega1Fixed, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Ny98omega3pr (ny98omega3pr) ********************************************************/
        else if (!strcmp(parmName, "Ny98omega3pr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].ny98omega3pr, tempStr);
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                        {
                        MrBayesPrint ("%s   Warning: %s can be set only for partition containing either DNA or RNA data.\
                            Currently there is no active partition with such data. The setting is ignored.\n", spacer, parmName);
                        return (ERROR);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Ny98omega3pr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                        {
                        if (!strcmp(modelParams[i].ny98omega3pr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].ny98omega3Uni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].ny98omega3Uni[0] >= modelParams[i].ny98omega3Uni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Ny98omega3pr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].ny98omega3Uni[0], modelParams[i].ny98omega3Uni[1]);
                                else
                                    MrBayesPrint ("%s   Setting Ny98omega3pr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].ny98omega3Uni[0], modelParams[i].ny98omega3Uni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].ny98omega3pr,"Exponential"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].ny98omega3Exp = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Ny98omega3pr to Exponential(%1.2lf)\n", spacer, modelParams[i].ny98omega3Exp);
                            else
                                MrBayesPrint ("%s   Setting Ny98omega3pr to Exponential(%1.2lf) for partition %d\n", spacer, modelParams[i].ny98omega3Exp, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        else if (!strcmp(modelParams[i].ny98omega3pr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].ny98omega3Fixed = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Ny98omega3pr to Fixed(%1.2lf)\n", spacer, modelParams[i].ny98omega3Fixed);
                            else
                                MrBayesPrint ("%s   Setting Ny98omega3pr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].ny98omega3Fixed, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set M3omegapr (m3omegapr) ********************************************************/
        else if (!strcmp(parmName, "M3omegapr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].m3omegapr, tempStr);
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                        {
                        MrBayesPrint ("%s   Warning: %s can be set only for partition containing either DNA or RNA data.\
                            Currently there is no active partition with such data. The setting is ignored.\n", spacer, parmName);
                        return (ERROR);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid M3omegapr argument\n", spacer);
                    return (ERROR);
                    }
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                        {
                        if (!strcmp(modelParams[i].m3omegapr,"Exponential"))
                            {
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting M3omegapr to Exponential\n", spacer);
                            else
                                MrBayesPrint ("%s   Setting M3omegapr to Exponential for partition %d\n", spacer, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                if (!strcmp(tempStr,"Exponential"))
                    expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                else
                    expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                        {
                        if (!strcmp(modelParams[i].m3omegapr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].m3omegaFixed[numVars[i]++] = tempD;
                            if (numVars[i] == 1 || numVars[i] == 2)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].m3omegaFixed[0] >= modelParams[i].m3omegaFixed[1] || modelParams[i].m3omegaFixed[0] >= modelParams[i].m3omegaFixed[2] || modelParams[i].m3omegaFixed[1] >= modelParams[i].m3omegaFixed[2])
                                    {
                                    MrBayesPrint ("%s   The three omega values must be ordered, such that omega1 < omega2 < omega3\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting M3omegapr to Fixed(%1.2lf,%1.2lf,%1.2lf)\n", spacer, modelParams[i].m3omegaFixed[0], modelParams[i].m3omegaFixed[1], modelParams[i].m3omegaFixed[2]);
                                else
                                    MrBayesPrint ("%s   Setting M3omegapr to Fixed(%1.2lf,%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].m3omegaFixed[0], modelParams[i].m3omegaFixed[1], modelParams[i].m3omegaFixed[2], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Codoncatfreqs (codonCatFreqPr) ********************************************************/
        else if (!strcmp(parmName, "Codoncatfreqs"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].codonCatFreqPr, tempStr);
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                        {
                        MrBayesPrint ("%s   Warning: %s can be set only for partition containing either DNA or RNA data.\
                            Currently there is no active partition with such data. The setting is ignored.\n", spacer, parmName);
                        return (ERROR);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Omegapurpr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                        {
                        if (!strcmp(modelParams[i].codonCatFreqPr,"Dirichlet"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].codonCatDir[numVars[i]++] = tempD;
                            if (numVars[i] == 1 || numVars[i] == 2)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Codoncatfreqs prior to Dirichlet(%1.2lf,%1.2lf,%1.2lf)\n", spacer, modelParams[i].codonCatDir[0], modelParams[i].codonCatDir[1], modelParams[i].codonCatDir[2]);
                                else
                                    MrBayesPrint ("%s   Setting Codoncatfreqs prior to Dirichlet(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].codonCatDir[0], modelParams[i].codonCatDir[1], modelParams[i].codonCatDir[2], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].codonCatFreqPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].codonCatFreqFix[numVars[i]++] = tempD;
                            if (numVars[i] == 1 || numVars[i] == 2)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (AreDoublesEqual (modelParams[i].codonCatFreqFix[0] + modelParams[i].codonCatFreqFix[1] + modelParams[i].codonCatFreqFix[2], (MrBFlt) 1.0, (MrBFlt) 0.001) == NO)
                                    {
                                    MrBayesPrint ("%s   Codon category frequencies must sum to 1\n", spacer);
                                    return (ERROR);
                                    }
                                
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Codoncatfreqs prior to Fixed(%1.2lf,%1.2lf,%1.2lf)\n", spacer, modelParams[i].codonCatFreqFix[0], modelParams[i].codonCatFreqFix[1], modelParams[i].codonCatFreqFix[2]);
                                else
                                    MrBayesPrint ("%s   Setting Codoncatfreqs prior to Fixed(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].codonCatFreqFix[0], modelParams[i].codonCatFreqFix[1], modelParams[i].codonCatFreqFix[2], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }

        /* set Shapepr (shapePr) **************************************************************/
        else if (!strcmp(parmName, "Shapepr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA || modelParams[i].dataType == PROTEIN || modelParams[i].dataType == RESTRICTION || modelParams[i].dataType == STANDARD))
                            {
                            strcpy(modelParams[i].shapePr, tempStr);
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                        {
                        MrBayesPrint ("%s   Warning: %s can be set only for partition containing data of at least one of following type: DNA, RNA, PROTEIN, RESTRICTION, STANDARD.\
                            Currently there is no active partition with such data.\n", spacer, parmName);
                        return (ERROR);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Shapepr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA || modelParams[i].dataType == PROTEIN || modelParams[i].dataType == RESTRICTION || modelParams[i].dataType == STANDARD))
                        {
                        if (!strcmp(modelParams[i].shapePr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].shapeUni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].shapeUni[0] >= modelParams[i].shapeUni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (modelParams[i].shapeUni[1] > MAX_SHAPE_PARAM)
                                    {
                                    MrBayesPrint ("%s   Upper value for uniform cannot be greater than %1.2lf\n", spacer, MAX_SHAPE_PARAM);
                                    return (ERROR);
                                    }
                                if (modelParams[i].shapeUni[0] < MIN_SHAPE_PARAM)
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform cannot be less than %1.2lf\n", spacer, MIN_SHAPE_PARAM);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Shapepr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].shapeUni[0], modelParams[i].shapeUni[1]);
                                else
                                    MrBayesPrint ("%s   Setting Shapepr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].shapeUni[0], modelParams[i].shapeUni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].shapePr,"Exponential"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].shapeExp = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Shapepr to Exponential(%1.2lf)\n", spacer, modelParams[i].shapeExp);
                            else
                                MrBayesPrint ("%s   Setting Shapepr to Exponential(%1.2lf) for partition %d\n", spacer, modelParams[i].shapeExp, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        else if (!strcmp(modelParams[i].shapePr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].shapeFix = tempD;
                            if (modelParams[i].shapeFix > MAX_SHAPE_PARAM)
                                {
                                MrBayesPrint ("%s   Shape parameter cannot be greater than %1.2lf\n", spacer, MAX_SHAPE_PARAM);
                                return (ERROR);
                                }
                            if (modelParams[i].shapeFix < MIN_SHAPE_PARAM)
                                {
                                MrBayesPrint ("%s   Shape parameter cannot be less than %1.2lf\n", spacer, MIN_SHAPE_PARAM);
                                return (ERROR);
                                }
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Shapepr to Fixed(%1.2lf)\n", spacer, modelParams[i].shapeFix);
                            else
                                MrBayesPrint ("%s   Setting Shapepr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].shapeFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Pinvarpr (pInvarPr) ************************************************************/
        else if (!strcmp(parmName, "Pinvarpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA || modelParams[i].dataType == PROTEIN))
                            {
                            strcpy(modelParams[i].pInvarPr, tempStr);
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                        {
                        MrBayesPrint ("%s   Warning: %s can be set only for partition containing data of at least one of the following type: DNA, RNA, PROTEIN.\
                            Currently there is no active partition with such data.\n", spacer, parmName);
                        return (ERROR);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Pinvarpr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA || modelParams[i].dataType == PROTEIN))
                        {
                        if (!strcmp(modelParams[i].pInvarPr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].pInvarUni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].pInvarUni[0] >= modelParams[i].pInvarUni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (modelParams[i].pInvarUni[1] > 1.0)
                                    {
                                    MrBayesPrint ("%s   Upper value for uniform should be less than or equal to 1.0\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Pinvarpr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].pInvarUni[0], modelParams[i].pInvarUni[1]);
                                else
                                    MrBayesPrint ("%s   Setting Pinvarpr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].pInvarUni[0], modelParams[i].pInvarUni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].pInvarPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD > 1.0)
                                {
                                MrBayesPrint ("%s   Value for Pinvar should be in the interval (0, 1)\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].pInvarFix = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Pinvarpr to Fixed(%1.2lf)\n", spacer, modelParams[i].pInvarFix);
                            else
                                MrBayesPrint ("%s   Setting Pinvarpr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].pInvarFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Ratecorrpr (adGammaCorPr) ******************************************************/
        else if (!strcmp(parmName, "Ratecorrpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].adGammaCorPr, tempStr);
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                        {
                        MrBayesPrint ("%s   Warning: %s can be set only for partition containing data of at least one of the following type: DNA, RNA.\
                            Currently there is no active partition with such data.\n", spacer, parmName);
                        return (ERROR);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Ratecorrpr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                foundDash = NO;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting = Expecting(NUMBER) | Expecting(DASH);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                        {
                        if (!strcmp(modelParams[i].adGammaCorPr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (foundDash == YES)
                            tempD *= -1.0;
                            modelParams[i].corrUni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].corrUni[0] >= modelParams[i].corrUni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (modelParams[i].corrUni[1] > 1.0)
                                    {
                                    MrBayesPrint ("%s   Upper value for uniform should be less than or equal to 1.0\n", spacer);
                                    return (ERROR);
                                    }
                                if (modelParams[i].corrUni[0] < -1.0)
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than or equal to -1.0\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Ratecorrpr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].corrUni[0], modelParams[i].corrUni[1]);
                                else
                                    MrBayesPrint ("%s   Setting Ratecorrpr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].corrUni[0], modelParams[i].corrUni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].adGammaCorPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (foundDash == YES)
                                tempD *= -1.0;
                            if (tempD > 1.0 || tempD < -1.0)
                                {
                                MrBayesPrint ("%s   Value for Ratecorrpr should be in the interval (-1, +1)\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].corrFix = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Ratecorrpr to Fixed(%1.2lf)\n", spacer, modelParams[i].corrFix);
                            else
                                MrBayesPrint ("%s   Setting Ratecorrpr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].corrFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                foundDash = NO;
                }
            else if (expecting == Expecting(DASH))
                {
                foundDash = YES;
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER) | Expecting(DASH);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Browncorrpr (brownCorPr) ******************************************************/
        else if (!strcmp(parmName, "Browncorrpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && modelParams[i].dataType == CONTINUOUS)
                            {
                            strcpy(modelParams[i].brownCorPr, tempStr);
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                        {
                        MrBayesPrint ("%s   Warning: %s can be set only for partition containing CONTINUOUS data.\
                            Currently there is no active partition with such data.\n", spacer, parmName);
                        return (ERROR);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Browncorrpr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                foundDash = NO;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting = Expecting(NUMBER) | Expecting(DASH);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && modelParams[i].dataType == CONTINUOUS)
                        {
                        if (!strcmp(modelParams[i].brownCorPr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (foundDash == YES)
                            tempD *= -1.0;
                            modelParams[i].brownCorrUni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].brownCorrUni[0] >= modelParams[i].brownCorrUni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (modelParams[i].brownCorrUni[1] > 1.0)
                                    {
                                    MrBayesPrint ("%s   Upper value for uniform should be less than or equal to 1.0\n", spacer);
                                    return (ERROR);
                                    }
                                if (modelParams[i].brownCorrUni[0] < -1.0)
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than or equal to -1.0\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Browncorrpr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].brownCorrUni[0], modelParams[i].brownCorrUni[1]);
                                else
                                    MrBayesPrint ("%s   Setting Browncorrpr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].brownCorrUni[0], modelParams[i].brownCorrUni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].brownCorPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (foundDash == YES)
                                tempD *= -1.0;
                            if (tempD > 1.0 || tempD < -1.0)
                                {
                                MrBayesPrint ("%s   Value for Browncorrpr should be in the interval (-1, +1)\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].brownCorrFix = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Browncorrpr to Fixed(%1.2lf)\n", spacer, modelParams[i].brownCorrFix);
                            else
                                MrBayesPrint ("%s   Setting Browncorrpr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].brownCorrFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                foundDash = NO;
                }
            else if (expecting == Expecting(DASH))
                {
                foundDash = YES;
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER) | Expecting(DASH);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Ratepr (ratePr) *****************************************************************/
        else if (!strcmp(parmName, "Ratepr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && modelParams[i].dataType != CONTINUOUS)
                            {
                            if (!strcmp(tempStr,"Variable"))
                                strcpy(modelParams[i].ratePr, "Dirichlet");
                            else
                                strcpy(modelParams[i].ratePr, tempStr);
                            modelParams[i].ratePrDir = 1.0;
                            if (!strcmp(tempStr,"Variable") || !strcmp(tempStr,"Fixed"))
                                {
                                if (tempStr[0]=='V')
                                    strcat (tempStr," [Dirichlet(..,1,..)]");
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Ratepr to %s\n", spacer, tempStr);
                                else
                                    MrBayesPrint ("%s   Setting Ratepr to %s for partition %d\n", spacer, tempStr, i+1);
                                if (tempStr[0]=='V')
                                    strcpy (tempStr,"Variable");
                                }
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Ratepr argument\n", spacer);
                    return (ERROR);
                    }
                if (!strcmp(tempStr,"Fixed") || !strcmp(tempStr,"Variable"))
                    expecting  = Expecting(PARAMETER) | Expecting(SEMICOLON);
                else
                    expecting = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting = Expecting (NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                /* find next partition to fill in */
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    if ((activeParts[i] == YES || nApplied == 0) && numVars[i] == 0)
                        break;
                if (i == numCurrentDivisions)
                    {
                    MrBayesPrint ("%s   Could not find first ratemultiplier partition\n", spacer);
                    return (ERROR);
                    }
                numVars[i] = 1;
                /* read in the parameter */
                sscanf (tkn, "%lf", &tempD);
                if (tempD < ALPHA_MIN || tempD > ALPHA_MAX)
                    {
                    MrBayesPrint ("%s   Ratemultiplier Dirichlet parameter %lf out of range\n", spacer, tempD);
                    return (ERROR);
                    }
                /* set the parameter */
                modelParams[i].ratePrDir = tempD;               
                /* check if all partitions have been filled in */
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && numVars[i] == 0)
                        break;
                    }
                /* set expecting accordingly so that we know what should be coming next */
                if (i == numCurrentDivisions)
                    expecting = Expecting (RIGHTPAR);
                else
                    expecting = Expecting (COMMA);
                }
            else if (expecting == Expecting (COMMA))
                expecting = Expecting (NUMBER);
            else if (expecting == Expecting (RIGHTPAR))
                {
                /* print message */
                for (i=j=0; i<numCurrentDivisions; i++)
                    {
                    if (numVars[i] == 1)
                        {
                        j++;
                        if (j == 1)
                            {
                            MrBayesPrint ("%s   Setting Ratepr to Dirichlet(%1.2f",
                                spacer, modelParams[i].ratePrDir);
                            }
                        else
                            MrBayesPrint(",%1.2f", modelParams[i].ratePrDir);
                        }
                    }
                if (numCurrentDivisions == 1)
                    MrBayesPrint (")\n");
                else
                    {
                    MrBayesPrint (") for partition");
                    if (j > 1)
                        MrBayesPrint ("s");
                    for (i=k=0; i<numCurrentDivisions; i++)
                        {
                        if (numVars[i] == 1)
                            {
                            k++;
                            if (k == j && j > 1)
                                MrBayesPrint (", and %d", i+1);
                            else if (k == 1)
                                MrBayesPrint (" %d", i+1);
                            else
                                MrBayesPrint (", %d", i+1);
                            }
                        }
                    MrBayesPrint ("\n");
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Generatepr (generatePr) *****************************************************************/
        else if (!strcmp(parmName, "Generatepr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && modelParams[i].dataType != CONTINUOUS)
                            {
                            if (!strcmp(tempStr,"Variable"))
                                strcpy(modelParams[i].generatePr, "Dirichlet");
                            else
                                strcpy(modelParams[i].generatePr, tempStr);
                            modelParams[i].generatePrDir = 1.0;
                            if (!strcmp(tempStr,"Variable") || !strcmp(tempStr,"Fixed"))
                                {
                                if (tempStr[0]=='V')
                                    strcat (tempStr," [Dirichlet(..,1,..)]");
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Generatepr to %s\n", spacer, tempStr);
                                else
                                    MrBayesPrint ("%s   Setting Generatepr to %s for partition %d\n", spacer, tempStr, i+1);
                                if (tempStr[0]=='V')
                                    strcpy (tempStr,"Variable");
                                }
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Generatepr argument\n", spacer);
                    return (ERROR);
                    }
                if (!strcmp(tempStr,"Fixed") || !strcmp(tempStr,"Variable"))
                    expecting  = Expecting(PARAMETER) | Expecting(SEMICOLON);
                else
                    expecting = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting = Expecting (NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                /* find next partition to fill in */
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    if ((activeParts[i] == YES || nApplied == 0) && numVars[i] == 0)
                        break;
                if (i == numCurrentDivisions)
                    {
                    MrBayesPrint ("%s   Could not find first generate multiplier partition\n", spacer);
                    return (ERROR);
                    }
                numVars[i] = 1;
                /* read in the parameter */
                sscanf (tkn, "%lf", &tempD);
                if (tempD < ALPHA_MIN || tempD > ALPHA_MAX)
                    {
                    MrBayesPrint ("%s   Generate multiplier Dirichlet parameter %lf out of range\n", spacer, tempD);
                    return (ERROR);
                    }
                /* set the parameter */
                modelParams[i].generatePrDir = tempD;
                /* check if all partitions have been filled in */
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && numVars[i] == 0)
                        break;
                    }
                /* set expecting accordingly so that we know what should be coming next */
                if (i == numCurrentDivisions)
                    expecting = Expecting (RIGHTPAR);
                else
                    expecting = Expecting (COMMA);
                }
            else if (expecting == Expecting (COMMA))
                expecting = Expecting (NUMBER);
            else if (expecting == Expecting (RIGHTPAR))
                {
                /* print message */
                for (i=j=0; i<numCurrentDivisions; i++)
                    {
                    if (numVars[i] == 1)
                        {
                        j++;
                        if (j == 1)
                            {
                            MrBayesPrint ("%s   Setting Generatepr to Dirichlet(%1.2f",
                                          spacer, modelParams[i].generatePrDir);
                            }
                        else
                            MrBayesPrint(",%1.2f", modelParams[i].generatePrDir);
                        }
                    }
                if (numCurrentDivisions == 1)
                    MrBayesPrint (")\n");
                else
                    {
                    MrBayesPrint (") for partition");
                    if (j > 1)
                        MrBayesPrint ("s");
                    for (i=k=0; i<numCurrentDivisions; i++)
                        {
                        if (numVars[i] == 1)
                            {
                            k++;
                            if (k == j && j > 1)
                                MrBayesPrint (", and %d", i+1);
                            else if (k == 1)
                                MrBayesPrint (" %d", i+1);
                            else
                                MrBayesPrint (", %d", i+1);
                            }
                        }
                    MrBayesPrint ("\n");
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Covswitchpr (covSwitchPr) ******************************************************/
        else if (!strcmp(parmName, "Covswitchpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA || modelParams[i].dataType == PROTEIN))
                            {
                            strcpy(modelParams[i].covSwitchPr, tempStr);
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                        {
                        MrBayesPrint ("%s   Warning: %s can be set only for partition containing data of at least one of the following type: DNA, RNA, PROTEIN.\
                            Currently there is no active partition with such data. ", spacer, parmName);
                        return (ERROR);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Covswitchpr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA || modelParams[i].dataType == PROTEIN))
                        {
                        if (!strcmp(modelParams[i].covSwitchPr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].covswitchUni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].covswitchUni[0] >= modelParams[i].covswitchUni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Covswitchpr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].covswitchUni[0], modelParams[i].covswitchUni[1]);
                                else
                                    MrBayesPrint ("%s   Setting Covswitchpr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].covswitchUni[0], modelParams[i].covswitchUni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].covSwitchPr,"Exponential"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].covswitchExp = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Covswitchpr to Exponential(%1.2lf)\n", spacer, modelParams[i].covswitchExp);
                            else
                                MrBayesPrint ("%s   Setting Covswitchpr to Exponential(%1.2lf) for partition %d\n", spacer, modelParams[i].covswitchExp, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        else if (!strcmp(modelParams[i].covSwitchPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].covswitchFix[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Covswitchpr to Fixed(%1.4lf,%1.4lf)\n", spacer, modelParams[i].covswitchFix[0], modelParams[i].covswitchFix[1]);
                                else
                                    MrBayesPrint ("%s   Setting Covswitchpr to Fixed(%1.4lf,%1.4lf) for partition %d\n", spacer, modelParams[i].covswitchFix[0], modelParams[i].covswitchFix[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Symdirihyperpr (symPiPr) ******************************************************/
        else if (!strcmp(parmName, "Symdirihyperpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                {
                foundBeta = NO;
                expecting = Expecting(ALPHA);
                }
            else if (expecting == Expecting(ALPHA))
                {
                if (foundBeta == NO)
                    {
                    /* expecting to see Uniform, Exponential, or Fixed */
                    if (IsArgValid(tkn, tempStr) == NO_ERROR)
                        {
                        nApplied = NumActiveParts ();
                        flag = 0;
                        for (i=0; i<numCurrentDivisions; i++)
                            {
                            if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == STANDARD || modelParams[i].dataType == RESTRICTION))
                                {
                                strcpy(modelParams[i].symPiPr, tempStr);
                                flag = 1;
                                }
                            }
                        if (flag == 0)
                            {
                            MrBayesPrint ("%s   Warning: %s can be set only for partition containing data of at least one of the following type: STANDARD, RESTRICTION.\
                            Currently there is no active partition with such data. ", spacer, parmName);
                            return (ERROR);
                            }
                        }
                    else
                        {
                        MrBayesPrint ("%s   Invalid Symdirihyperpr argument\n", spacer);
                        return (ERROR);
                        }
                    expecting  = Expecting(LEFTPAR);
                    for (i=0; i<numCurrentDivisions; i++)
                        numVars[i] = 0;
                    foundBeta = YES;    
                    }   
                else
                    {
                    /* expecting infinity */
                    if (IsSame("Infinity", tkn) == SAME || IsSame("Infinity", tkn) == CONSISTENT_WITH)
                        {
                        nApplied = NumActiveParts ();
                        for (i=0; i<numCurrentDivisions; i++)
                            {
                            if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == STANDARD || modelParams[i].dataType == RESTRICTION))
                                {
                                if (!strcmp(modelParams[i].symPiPr, "Fixed"))
                                    {
                                    modelParams[i].symBetaFix = -1;
                                    if (nApplied == 0 && numCurrentDivisions == 1)
                                        MrBayesPrint ("%s   Setting Symdirihyperpr to Beta(Infinity)\n", spacer);
                                    else
                                        MrBayesPrint ("%s   Setting Symdirihyperpr to Beta(Infinity) for partition %d\n", spacer, i+1);
                                    expecting  = Expecting(RIGHTPAR);
                                    }
                                else
                                    {
                                    MrBayesPrint ("%s   Problem setting Symdirihyperpr\n", spacer);
                                    return (ERROR);
                                    }
                                }
                            }
                        expecting  = Expecting(RIGHTPAR);
                        }
                    }       
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER) | Expecting(ALPHA);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == STANDARD || modelParams[i].dataType == RESTRICTION))
                        {
                        if (!strcmp(modelParams[i].symPiPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].symBetaFix = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Symdirihyperpr to Fixed(%1.2lf)\n", spacer, modelParams[i].symBetaFix);
                            else
                                MrBayesPrint ("%s   Setting Symdirihyperpr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].symBetaFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        else if (!strcmp(modelParams[i].symPiPr,"Exponential"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].symBetaExp = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Symdirihyperpr to Exponential(%1.2lf)\n", spacer, modelParams[i].symBetaExp);
                            else
                                MrBayesPrint ("%s   Setting Symdirihyperpr to Exponential(%1.2lf) for partition %d\n", spacer, modelParams[i].symBetaExp, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        else if (!strcmp(modelParams[i].symPiPr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].symBetaUni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)    
                                expecting = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].symBetaUni[0] >= modelParams[i].symBetaUni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Symdirihyperpr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].symBetaUni[0], modelParams[i].symBetaUni[1]);
                                else
                                    MrBayesPrint ("%s   Setting Symdirihyperpr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].symBetaUni[0], modelParams[i].symBetaUni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else
                            {
                            MrBayesPrint ("%s   Problem setting Symdirihyperpr\n", spacer);
                            return (ERROR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Statefreqpr (stateFreqPr) ******************************************************/
        else if (!strcmp(parmName, "Statefreqpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsSame ("Equal", tkn) == DIFFERENT && IsSame ("Empirical", tkn) == DIFFERENT)
                    {
                    /* the user wants to specify a dirichlet or fixed prior */
                    if (IsArgValid(tkn, tempStr) == NO_ERROR)
                        {
                        nApplied = NumActiveParts ();
                        for (i=0; i<numCurrentDivisions; i++)
                            {
                            if ((activeParts[i] == YES || nApplied == 0) && modelParams[i].dataType != CONTINUOUS)
                                strcpy(modelParams[i].stateFreqPr, tempStr);
                            }
                        /* if (flag == 0)
                            {
                            MrBayesPrint ("%s   Warning: %s can be set only for partition containing CONTINUOUS data.\
                            Currently there is no active partition with such data. ", spacer, parmName);
                            return (ERROR);
                            } */
                        }
                    else
                        {
                        MrBayesPrint ("%s   Invalid Statefreqpr argument\n", spacer);
                        return (ERROR);
                        }
                    /* TODO: Here we set flat dirichlet parameters */
                    expecting  = Expecting(LEFTPAR);
                    }
                else
                    {
                    /* the user wants equal or empirical state frequencies */
                    nApplied = NumActiveParts ();
                    if (IsSame ("Equal", tkn) == SAME || IsSame ("Equal", tkn) == CONSISTENT_WITH)
                        {
                        for (i=0; i<numCurrentDivisions; i++)
                            {
                            if ((activeParts[i] == YES || nApplied == 0) && modelParams[i].dataType != CONTINUOUS)
                                strcpy(modelParams[i].stateFreqsFixType, "Equal");
                            }
                        }
                    else if (IsSame ("Empirical", tkn) == SAME || IsSame ("Empirical", tkn) == CONSISTENT_WITH)
                        {
                        for (i=0; i<numCurrentDivisions; i++)
                            {
                            if ((activeParts[i] == YES || nApplied == 0) && modelParams[i].dataType != CONTINUOUS)
                                strcpy(modelParams[i].stateFreqsFixType, "Empirical");
                            }
                        }
                    else
                        {
                        MrBayesPrint ("%s   Invalid Statefreqpr delimiter\n", spacer);
                        return (ERROR);
                        }
                    expecting  = Expecting(RIGHTPAR);
                    }
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                tempNumStates = 0;
                expecting = Expecting(NUMBER) | Expecting(ALPHA);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                sscanf (tkn, "%lf", &tempD);
                tempStateFreqs[tempNumStates++] = tempD;
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && modelParams[i].dataType != CONTINUOUS)
                        if (!strcmp(modelParams[i].stateFreqPr,"Fixed"))
                            strcpy(modelParams[i].stateFreqsFixType, "User");
                    }
                expecting = Expecting(COMMA) | Expecting(RIGHTPAR);
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && modelParams[i].dataType != CONTINUOUS)
                        {
                        ns = NumStates(i);
                        if (!strcmp(modelParams[i].stateFreqPr,"Dirichlet"))
                            {
                            if (tempNumStates == 1)
                                {
                                for (j=0; j<ns; j++)
                                    modelParams[i].stateFreqsDir[j] = tempStateFreqs[0] / ns;
                                MrBayesPrint ("%s   Setting Statefreqpr to Dirichlet(", spacer);
                                for (j=0; j<ns; j++)
                                    {
                                    MrBayesPrint("%1.2lf", modelParams[i].stateFreqsDir[j]);
                                    if (j == ns - 1)
                                        MrBayesPrint (")");
                                    else
                                        MrBayesPrint (","); 
                                    }   
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("\n");
                                else
                                    MrBayesPrint (" for partition %d\n", i+1); 
                                modelParams[i].numDirParams = ns;
                                }
                            else
                                {
                                if (tempNumStates != ns)
                                    {
                                    MrBayesPrint ("%s   Found %d dirichlet parameters but expecting %d\n", spacer, tempNumStates, modelParams[i].nStates);
                                    return (ERROR);
                                    }
                                else
                                    {
                                    modelParams[i].numDirParams = ns;
                                    for (j=0; j<ns; j++)
                                        modelParams[i].stateFreqsDir[j] = tempStateFreqs[j];
                                    MrBayesPrint ("%s   Setting Statefreqpr to Dirichlet(", spacer);
                                    for (j=0; j<ns; j++)
                                        {
                                        MrBayesPrint("%1.2lf", modelParams[i].stateFreqsDir[j]);
                                        if (j == ns - 1)
                                            MrBayesPrint (")");
                                        else
                                            MrBayesPrint (","); 
                                        }   
                                    if (nApplied == 0 && numCurrentDivisions == 1)
                                        MrBayesPrint ("\n");
                                    else
                                        MrBayesPrint (" for partition %d\n", i+1); 
                                    }
                                }
                            }
                        else if (!strcmp(modelParams[i].stateFreqPr,"Fixed"))
                            {
                            if (tempNumStates == 0)
                                {
                                if (!strcmp(modelParams[i].stateFreqsFixType, "Equal"))
                                    MrBayesPrint ("%s   Setting Statefreqpr to Fixed(Equal)", spacer);
                                else if (!strcmp(modelParams[i].stateFreqsFixType, "Empirical"))
                                    MrBayesPrint ("%s   Setting Statefreqpr to Fixed(Empirical)", spacer);
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("\n");
                                else
                                    MrBayesPrint (" for partition %d\n", i+1); 
                                }
                            else 
                                {
                                if (tempNumStates == ns)
                                    {
                                    sum = 0.0;
                                    for (j=0; j<ns; j++)
                                        sum += tempStateFreqs[j];
                                    if (AreDoublesEqual (sum, (MrBFlt) 1.0, (MrBFlt) 0.001) == NO)
                                        {
                                        MrBayesPrint ("%s   State frequencies do not sum to 1.0\n", spacer);
                                        return (ERROR);
                                        }
                                    strcpy(modelParams[i].stateFreqsFixType, "User");
                                    for (j=0; j<ns; j++)
                                        modelParams[i].stateFreqsFix[j] = tempStateFreqs[j];
                                    MrBayesPrint ("%s   Setting Statefreqpr to Fixed(", spacer);
                                    for (j=0; j<ns; j++)
                                        {
                                        MrBayesPrint("%1.2lf", modelParams[i].stateFreqsFix[j]);
                                        if (j == ns - 1)
                                            MrBayesPrint (")");
                                        else
                                            MrBayesPrint (","); 
                                        }   
                                    if (nApplied == 0 && numCurrentDivisions == 1)
                                        MrBayesPrint ("\n");
                                    else
                                        MrBayesPrint (" for partition %d\n", i+1); 
                                    }
                                else
                                    {
                                    MrBayesPrint ("%s   Found %d state frequencies but expecting %d\n", spacer, tempNumStates, modelParams[i].nStates);
                                    return (ERROR);
                                    }
                                }
                                
                            }
                        }
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Topologypr (topologyPr) ********************************************************/
        else if (!strcmp(parmName, "Topologypr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                {
                foundEqual = YES;
                expecting = Expecting(ALPHA);
                }
            else if (expecting == Expecting(ALPHA))
                {
                if (foundEqual == YES)
                    {
                    if (IsArgValid(tkn, tempStr) == NO_ERROR)
                        {
                        /* set topology prior */
                        nApplied = NumActiveParts ();
                        for (i=0; i<numCurrentDivisions; i++)
                            {
                            if (activeParts[i] == YES || nApplied == 0)
                                {
                                strcpy(modelParams[i].topologyPr, tempStr);
                                /* erase previous constraints, if any */
                                for (j=0; j<numDefinedConstraints; j++)
                                    modelParams[i].activeConstraints[j] = NO;
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Topologypr to %s\n", spacer, modelParams[i].topologyPr);
                                else
                                    MrBayesPrint ("%s   Setting Topologypr to %s for partition %d\n", spacer, modelParams[i].topologyPr, i+1);
                                /* adjust branch length prior if necessary */
                                if (strcmp(modelParams[i].topologyPr,"Fixed") != 0 && strcmp(modelParams[i].brlensPr,"Fixed") == 0)
                                    {
                                    MrBayesPrint ("%s   Resetting Brlenspr to default\n", spacer);
                                    if (strcmp(modelParams[i].clockPr,"Clock") == 0)
                                        strcpy(modelParams[i].brlensPr, "Uniform");
                                    else
                                        strcpy(modelParams[i].brlensPr, defaultModel.brlensPr);
                                    }
                                }
                            }
                        }
                    else
                        {
                        MrBayesPrint ("%s   Invalid Topologypr argument\n", spacer);
                        return (ERROR);
                        }
                    /* make sure we know what to do next */
                    if (!strcmp(tempStr, "Uniform") || !strcmp(tempStr, "Speciestree"))
                        expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                    else
                        expecting = Expecting(LEFTPAR);
                    foundEqual = NO;
                    }
                else
                    {
                    /* find out whether we need a tree name or constraint name */
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        if (activeParts[i] == YES || nApplied == 0)
                            break;

                    if (foundDash == YES)   /* we must be collecting constraint numbers */
                        {
                        MrBayesPrint ("%s   Expecting a number\n", spacer);
                        return (ERROR);
                        }
                    if (!strcmp(modelParams[i].topologyPr,"Constraints"))
                        {
                        /* find constraint number */
                        if (CheckString (constraintNames, numDefinedConstraints, tkn, &index) == ERROR)
                            {
                            MrBayesPrint ("%s   Could not find constraint named %s\n", spacer, tkn);
                            return (ERROR);
                            }
                        tempActiveConstraints[index] = YES;
                        expecting = Expecting(RIGHTPAR);
                        expecting |= Expecting(COMMA);
                        }
                    else
                        {
                        /* find tree number */
                        if (GetUserTreeFromName (&index, tkn) == ERROR)
                            {
                            MrBayesPrint ("%s   Could not set fixed topology from user tree '%s'\n", spacer, tkn);
                            return (ERROR);
                            }
                        fromI = index + 1;        /* fromI is used to hold the index of the user tree, 1-based */
                        expecting = Expecting(RIGHTPAR);
                        }
                    }
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                for (i=0; i<numDefinedConstraints; i++)
                    tempActiveConstraints[i] = NO;
                fromI = toJ = -1;
                foundDash = foundComma = NO;
                expecting = Expecting(NUMBER) | Expecting(ALPHA);
                }
            else if (expecting == Expecting(NUMBER))
                {
                /* find out whether we need a tree number or constraint number */
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    if (activeParts[i] == YES || nApplied == 0)
                        break;

                if (!strcmp(modelParams[i].topologyPr,"Constraints"))
                    {
                    if (numDefinedConstraints == 0)
                        {
                        MrBayesPrint ("%s   No constraints have been defined\n", spacer);
                        return (ERROR);
                        }
                    sscanf (tkn, "%d", &tempInt);
                    if (tempInt > numDefinedConstraints)
                        {
                        MrBayesPrint ("%s   Constraint number is too large\n", spacer);
                        return (ERROR);
                        }
                    if (fromI == -1)
                        {
                        if (foundDash == YES)
                            {
                            MrBayesPrint ("%s   Unexpected dash\n", spacer);
                            return (ERROR);
                            }
                        fromI = tempInt;
                        tempActiveConstraints[fromI-1] = YES;
                        }
                    else if (fromI != -1 && toJ == -1 && foundDash == YES && foundComma == NO)
                        {
                        toJ = tempInt;
                        //for (i=fromI-1; i<toJ; i++)
                        for (i=fromI; i<toJ; i++)
                            tempActiveConstraints[i] = YES;
                        fromI = toJ = -1;
                        foundDash = NO;
                        }
                    else if (fromI != -1 && toJ == -1 && foundDash == NO && foundComma == YES)
                        {
                        fromI = tempInt;
                        tempActiveConstraints[fromI-1] = YES;
                        foundComma = NO;
                        }
                    expecting  = Expecting(COMMA);
                    expecting |= Expecting(DASH);
                    expecting |= Expecting(RIGHTPAR);
                    }
                else /* if (!strcmp(modelParams[i].topologyPr,"Fixed")) */
                    {
                    if (numUserTrees == 0)
                        {
                        MrBayesPrint ("%s   No user trees have been defined\n", spacer);
                        return (ERROR);
                        }
                    sscanf (tkn, "%d", &tempInt);
                    if (tempInt > numUserTrees)
                        {
                        MrBayesPrint ("%s   Tree number is too large\n", spacer);
                        return (ERROR);
                        }
                    if (tempInt < 1)
                        {
                        MrBayesPrint ("%s   Tree number is too small\n", spacer);
                        return (ERROR);
                        }
                    fromI = tempInt;
                    expecting = Expecting(RIGHTPAR);    /* only one tree number acceptable */
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                foundComma = YES;
                expecting = Expecting(NUMBER) | Expecting(ALPHA);
                }
            else if (expecting == Expecting(DASH))
                {
                foundDash = YES;
                expecting = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                /* find out whether we need a tree number or constraint number(s) */
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    if (activeParts[i] == YES || nApplied == 0)
                        break;

                if (!strcmp(modelParams[i].topologyPr,"Constraints"))
                    {
                    /* set constraints */
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            modelParams[i].numActiveConstraints = 0;
                            for (j=0; j<numDefinedConstraints; j++)
                                {
                                if (tempActiveConstraints[j] == YES)
                                    {
                                    modelParams[i].activeConstraints[j] = YES;
                                    modelParams[i].numActiveConstraints++;
                                    }
                                else
                                    modelParams[i].activeConstraints[j] = NO;
                                }
                            if (modelParams[i].numActiveConstraints == 0)
                                {
                                MrBayesPrint ("%s   No constraints have been defined\n", spacer);
                                return (ERROR);
                                }
                            }
                        }
                    }
                else /* if (!strcmp(modelParams[i].topologyPr,"Constraints")) */
                    {
                    /* set start tree index */
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            modelParams[i].topologyFix = fromI-1;
                        }
                    }
#               if 0
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    MrBayesPrint ("%4d -- ", i+1);
                    for (j=0; j<numDefinedConstraints; j++)
                        MrBayesPrint (" %d", modelParams[i].activeConstraints[j]);
                    MrBayesPrint ("\n");
                    }
#               endif               
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Nodeagepr (nodeAgePr) ********************************************************/
        else if (!strcmp(parmName, "Nodeagepr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            strcpy(modelParams[i].nodeAgePr, tempStr);
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Nodeagepr to %s\n", spacer, modelParams[i].nodeAgePr);
                            else
                                MrBayesPrint ("%s   Setting Nodeagepr to %s for partition %d\n", spacer, modelParams[i].nodeAgePr, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Nodeagepr argument\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Clockvarpr (clockVarPr) ********************************************************/
        else if (!strcmp(parmName, "Clockvarpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    if (strcmp(tempStr, "Bm") == 0)
                        strcpy(tempStr, "TK02");
                    else if (strcmp(tempStr, "Ibr") == 0)
                        strcpy(tempStr, "Igr");
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            strcpy(modelParams[i].clockVarPr, tempStr);
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Clockvarpr to %s\n", spacer, modelParams[i].clockVarPr);
                            else
                                MrBayesPrint ("%s   Setting Clockvarpr to %s for partition %d\n", spacer, modelParams[i].clockVarPr, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Clockvarpr argument\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Brlenspr (brlensPr) ************************************************************/
        else if (!strcmp(parmName, "Brlenspr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                {
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = NO;
                foundEqual = YES;
                foundLeftPar = NO;
                expecting = Expecting(ALPHA);
                }
            else if (expecting == Expecting(ALPHA))
                {
                if (foundEqual == YES)
                    {
                    if (IsArgValid(tkn, tempStr) == NO_ERROR)
                        {
                        strcpy (colonPr, tempStr);
                        nApplied = NumActiveParts ();
                        for (i=0; i<numCurrentDivisions; i++)
                            if (activeParts[i] == YES || nApplied == 0)
                                strcpy(modelParams[i].brlensPr, tempStr);
                        }
                    else
                        {
                        MrBayesPrint ("%s   Invalid Brlenspr argument\n", spacer);
                        return (ERROR);
                        }
                    foundEqual = NO;
                    if (!strcmp(colonPr,"Fixed"))
                        expecting = Expecting(LEFTPAR);
                    else
                        expecting = Expecting(COLON);
                    }
                else if (foundLeftPar == YES)
                    {
                    /*process argument of fixed() prior*/
                    /* find tree number */
                    if (GetUserTreeFromName (&tempInt, tkn) == ERROR)
                        {
                        MrBayesPrint ("%s   Could not set fixed branch lengths from the user tree '%s'\n", spacer, tkn);
                        return (ERROR);
                        }
                    fromI = tempInt + 1;        /* fromI is used to hold the index of the user tree, 1-based */
                    expecting = Expecting(RIGHTPAR);
                    foundLeftPar = NO;
                    }
                else
                    {
                    if (!strcmp(colonPr, "Unconstrained"))
                        {
                        /* have unconstrained branch lengths, which we expect to have a uniform or exponential distribution */
                        nApplied = NumActiveParts ();
                        if (IsSame ("Uniform", tkn) == SAME || IsSame ("Uniform", tkn) == CONSISTENT_WITH)
                            {
                            for (i=0; i<numCurrentDivisions; i++)
                                if (activeParts[i] == YES || nApplied == 0)
                                    strcpy(modelParams[i].unconstrainedPr, "Uniform");
                            }
                        else if (IsSame ("Exponential", tkn) == SAME || IsSame ("Exponential", tkn) == CONSISTENT_WITH)
                            {
                            for (i=0; i<numCurrentDivisions; i++)
                                if (activeParts[i] == YES || nApplied == 0)
                                    strcpy(modelParams[i].unconstrainedPr, "Exponential");
                            }
                        else if (IsSame ("GammaDirichlet", tkn) == SAME || IsSame ("GammaDirichlet", tkn) == CONSISTENT_WITH)
                            {
                            for (i=0; i<numCurrentDivisions; i++)
                                if (activeParts[i] == YES || nApplied == 0)
                                    strcpy(modelParams[i].unconstrainedPr, "GammaDir");
                            }
                        else if (IsSame ("invGamDirichlet", tkn) == SAME || IsSame ("invGamDirichlet", tkn) == CONSISTENT_WITH)
                            {
                            for (i=0; i<numCurrentDivisions; i++)
                                if (activeParts[i] == YES || nApplied == 0)
                                    strcpy(modelParams[i].unconstrainedPr, "invGamDir");
                            }
                        else if (IsSame ("twoExponential", tkn) == SAME || IsSame ("twoExponential", tkn) == CONSISTENT_WITH)
                            {
                            for (i=0; i<numCurrentDivisions; i++)
                                if (activeParts[i] == YES || nApplied == 0)
                                    strcpy(modelParams[i].unconstrainedPr, "twoExp");
                            }
                        else
                            {
                            MrBayesPrint ("%s   Do not understand %s\n", spacer, tkn);
                            return (ERROR);
                            }
                        expecting  = Expecting(LEFTPAR);
                        }
                    else if (!strcmp(colonPr, "Clock"))
                        {
                        /* otherwise we have a clock constraint and expect uniform, birthdeath, coalescence or fixed prior */
                        nApplied = NumActiveParts ();
                        if (IsSame ("Uniform", tkn) == SAME || IsSame ("Uniform", tkn) == CONSISTENT_WITH)
                            {
                            strcpy (clockPr, "Uniform");
                            for (i=0; i<numCurrentDivisions; i++)
                                {
                                if (activeParts[i] == YES || nApplied == 0)
                                    strcpy(modelParams[i].clockPr, "Uniform");
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Brlenspr to Clock:Uniform\n", spacer);
                                else
                                    MrBayesPrint ("%s   Setting Brlenspr to Clock:Uniform for partition %d\n", spacer, i+1);
                                }
                            expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                            }
                        else if (IsSame ("Birthdeath", tkn) == SAME || IsSame ("Birthdeath", tkn) == CONSISTENT_WITH)
                            {
                            strcpy (clockPr, "Birthdeath");
                            for (i=0; i<numCurrentDivisions; i++)
                                {
                                if (activeParts[i] == YES || nApplied == 0)
                                    strcpy(modelParams[i].clockPr, "Birthdeath");
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Brlenspr to Clock:Birthdeath\n", spacer);
                                else
                                    MrBayesPrint ("%s   Setting Brlenspr to Clock:Birthdeath for partition %d\n", spacer, i+1);
                                }
                            expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                            }
                        else if (IsSame ("Coalescence", tkn) == SAME || IsSame ("Coalescence", tkn) == CONSISTENT_WITH)
                            {
                            strcpy (clockPr, "Coalescence");
                            for (i=0; i<numCurrentDivisions; i++)
                                {
                                if (activeParts[i] == YES || nApplied == 0)
                                    strcpy(modelParams[i].clockPr, "Coalescence");
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Brlenspr to Clock:Coalescence\n", spacer);
                                else
                                    MrBayesPrint ("%s   Setting Brlenspr to Clock:Coalescence for partition %d\n", spacer, i+1);
                                }
                            expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                            }
                        else if (IsSame ("Speciestreecoalescence", tkn) == SAME || IsSame ("Speciestreecoalescence", tkn) == CONSISTENT_WITH)
                            {
                            strcpy (clockPr, "Speciestreecoalescence");
                            for (i=0; i<numCurrentDivisions; i++)
                                {
                                if (activeParts[i] == YES || nApplied == 0)
                                    strcpy(modelParams[i].clockPr, "Speciestreecoalescence");
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Brlenspr to Clock:Speciestreecoalescence\n", spacer);
                                else
                                    MrBayesPrint ("%s   Setting Brlenspr to Clock:Speciestreecoalescence for partition %d\n", spacer, i+1);
                                }
                            expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                            }
                        else if (IsSame ("Fossilization", tkn) == SAME || IsSame ("Fossilization", tkn) == CONSISTENT_WITH)
                            {
                            strcpy (clockPr, "Fossilization");
                            for (i=0; i<numCurrentDivisions; i++)
                                {
                                if (activeParts[i] == YES || nApplied == 0)
                                    strcpy(modelParams[i].clockPr, "Fossilization");
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Brlenspr to Clock:Fossilization\n", spacer);
                                else
                                    MrBayesPrint ("%s   Setting Brlenspr to Clock:Fossilization for partition %d\n", spacer, i+1);
                                }
                            /* TODO: clock:fossilization is not compatible with clockvarpr=cpp */
                            expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                            }
                        else if (IsSame ("Fixed", tkn) == SAME || IsSame ("Fixed", tkn) == CONSISTENT_WITH)
                            {
                            strcpy (clockPr, "Fixed");
                            for (i=0; i<numCurrentDivisions; i++)
                                {
                                if (activeParts[i] == YES || nApplied == 0)
                                    strcpy(modelParams[i].clockPr, "Fixed");
                                }
                            expecting = Expecting(LEFTPAR);     /* Proceed with tree name */
                            }
                        else
                            {
                            MrBayesPrint ("%s   Do not understand %s\n", spacer, tkn);
                            return (ERROR);
                            }
                        }
                    else
                        {
                        MrBayesPrint ("%s   Do not understand %s\n", spacer, tkn);
                        return (ERROR);
                        }
                    }
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                foundLeftPar = YES;
                expecting  = Expecting(NUMBER);
                if (!strcmp(colonPr,"Fixed") || (!strcmp(colonPr,"Clock") && !strcmp(clockPr,"Fixed")))
                    {
                    expecting |= Expecting(ALPHA);
                    }
                else
                    {
                    for (i=0; i<numCurrentDivisions; i++)
                        numVars[i] = 0;
                    }
                }
            else if (expecting == Expecting(NUMBER))
                {
                if (!strcmp(colonPr, "Unconstrained"))
                    {
                    /* have unconstrained branch lengths */
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            if (!strcmp(modelParams[i].unconstrainedPr,"Uniform"))
                                {
                                sscanf (tkn, "%lf", &tempD);
                                modelParams[i].brlensUni[numVars[i]++] = tempD;
                                if (numVars[i] == 1)
                                    expecting  = Expecting(COMMA);
                                else
                                    {
                                    if (modelParams[i].brlensUni[0] > 0.000001)
                                        {
                                        MrBayesPrint ("%s   Lower value for uniform must equal 0.0\n", spacer);
                                        return (ERROR);
                                        }
                                    if (modelParams[i].brlensUni[0] >= modelParams[i].brlensUni[1])
                                        {
                                        MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                        return (ERROR);
                                        }
                                    if (nApplied == 0 && numCurrentDivisions == 1)
                                        MrBayesPrint ("%s   Setting Brlenspr to Unconstrained:Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].brlensUni[0], modelParams[i].brlensUni[1]);
                                    else
                                        MrBayesPrint ("%s   Setting Brlenspr to Unconstrained:Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].brlensUni[0], modelParams[i].brlensUni[1], i+1);
                                    expecting  = Expecting(RIGHTPAR);
                                    }
                                }
                            else if (!strcmp(modelParams[i].unconstrainedPr,"Exponential"))
                                {
                                sscanf (tkn, "%lf", &tempD);
                                modelParams[i].brlensExp = tempD;
                                if (modelParams[i].brlensExp <= 0.0)
                                    {
                                    MrBayesPrint ("%s   Value for exponential must > 0.0\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Brlenspr to Unconstrained:Exponential(%1.2lf)\n", spacer, modelParams[i].brlensExp);
                                else
                                    MrBayesPrint ("%s   Setting Brlenspr to Unconstrained:Exponential(%1.2lf) for partition %d\n", spacer, modelParams[i].brlensExp, i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            else if (!strcmp(modelParams[i].unconstrainedPr,"GammaDir"))
                                {
                                sscanf (tkn, "%lf", &tempD);
                                modelParams[i].brlensDir[numVars[i]++] = tempD;
                                if (numVars[i] == 1 || numVars[i] == 2 || numVars[i] == 3)
                                    expecting  = Expecting(COMMA);
                                else
                                    {
                                    if (modelParams[i].brlensDir[0] <= 0.0 || modelParams[i].brlensDir[1] <= 0.0 || modelParams[i].brlensDir[2] <= 0.0 || modelParams[i].brlensDir[3] <= 0.0)
                                        {
                                        MrBayesPrint ("%s   alphaT & betaT & a & c for GammaDir prior must > 0.0\n", spacer);
                                        return (ERROR);
                                        }
                                    if (nApplied == 0 && numCurrentDivisions == 1)
                                        MrBayesPrint ("%s   Setting Brlenspr to Unconstrained:GammaDir(%1.2lf,%1.4lf,%1.2lf,%1.2lf)\n", spacer, modelParams[i].brlensDir[0], modelParams[i].brlensDir[1], modelParams[i].brlensDir[2], modelParams[i].brlensDir[3]);
                                    else
                                        MrBayesPrint ("%s   Setting Brlenspr to Unconstrained:GammaDir(%1.2lf,%1.4lf,%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].brlensDir[0], modelParams[i].brlensDir[1], modelParams[i].brlensDir[2], modelParams[i].brlensDir[3], i+1);
                                    expecting  = Expecting(RIGHTPAR);
                                    }
                                }
                            else if (!strcmp(modelParams[i].unconstrainedPr,"invGamDir"))
                                {
                                sscanf (tkn, "%lf", &tempD);
                                modelParams[i].brlensDir[numVars[i]++] = tempD;
                                if (numVars[i] == 1 || numVars[i] == 2 || numVars[i] == 3)
                                    expecting  = Expecting(COMMA);
                                else
                                    {
                                    if (modelParams[i].brlensDir[0] <= 2.0 || modelParams[i].brlensDir[1] <= 0.0 || modelParams[i].brlensDir[2] <= 0.0 || modelParams[i].brlensDir[3] <= 0.0)
                                        {
                                        MrBayesPrint ("%s   alphaT must > 2.0, betaT & a & c for invGamDir prior must > 0.0\n", spacer);
                                        return (ERROR);
                                        }
                                    if (nApplied == 0 && numCurrentDivisions == 1)
                                        MrBayesPrint ("%s   Setting Brlenspr to Unconstrained:invGamDir(%1.2lf,%1.4lf,%1.2lf,%1.2lf)\n", spacer, modelParams[i].brlensDir[0], modelParams[i].brlensDir[1], modelParams[i].brlensDir[2], modelParams[i].brlensDir[3]);
                                    else
                                        MrBayesPrint ("%s   Setting Brlenspr to Unconstrained:invGamDir(%1.2lf,%1.4lf,%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].brlensDir[0], modelParams[i].brlensDir[1], modelParams[i].brlensDir[2], modelParams[i].brlensDir[3], i+1);
                                    expecting  = Expecting(RIGHTPAR);
                                    }
                                }
                            else if (!strcmp(modelParams[i].unconstrainedPr,"twoExp"))
                                {
                                    sscanf (tkn, "%lf", &tempD);
                                    modelParams[i].brlens2Exp[numVars[i]++] = tempD;
                                    if (numVars[i] == 1)
                                        expecting  = Expecting(COMMA);
                                    else
                                    {
                                        if (modelParams[i].brlens2Exp[0] <= 0.0 || modelParams[i].brlens2Exp[1] <= 0.0)
                                            {
                                            MrBayesPrint ("%s   Values for the two exponentials must > 0.0\n", spacer);
                                            return (ERROR);
                                            }
                                        if (nApplied == 0 && numCurrentDivisions == 1)
                                            MrBayesPrint ("%s   Setting Brlenspr to Unconstrained:twoExp(%1.2lf,%1.2lf)\n", spacer, modelParams[i].brlens2Exp[0], modelParams[i].brlens2Exp[1]);
                                        else
                                            MrBayesPrint ("%s   Setting Brlenspr to Unconstrained:twoExp(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].brlens2Exp[0], modelParams[i].brlens2Exp[1], i+1);
                                        expecting  = Expecting(RIGHTPAR);
                                    }
                                }
                            }
                        }
                    }
                else if (!strcmp(colonPr,"Fixed") || !strcmp(colonPr,"Clock"))
                    {
                    sscanf (tkn, "%d", &tempInt);
                    if (tempInt < 1 || tempInt > numUserTrees)
                        {
                        MrBayesPrint ("%s   Tree needs to be in the range %d to %d\n", spacer, 1, numUserTrees);
                        return (ERROR);
                        }
                    fromI = tempInt;
                    expecting = Expecting(RIGHTPAR);
                    }
                foundLeftPar = NO;
                }
            else if (expecting == Expecting(COLON))
                {
                expecting  = Expecting(ALPHA);
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                if (!strcmp(colonPr,"Fixed") || (!strcmp(colonPr,"Clock") && !strcmp(clockPr,"Fixed")))
                    {
                    /* index of a tree which set up branch lengths*/
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            modelParams[i].brlensFix = fromI-1;
                        if (!strcmp(colonPr,"Fixed"))
                            {
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Brlenspr to Fixed(%s)\n", spacer, userTree[fromI-1]->name);
                            else
                                MrBayesPrint ("%s   Setting Brlenspr to Fixed(%s) for partition %d\n", spacer, userTree[fromI-1]->name, i+1);
                            }
                        else
                            {
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Brlenspr to Fixed(%s)\n", spacer, userTree[fromI-1]->name);
                            else
                                MrBayesPrint ("%s   Setting Brlenspr to Fixed(%s) for partition %d\n", spacer, userTree[fromI-1]->name, i+1);
                            }
                        }
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Speciationpr (speciationPr) *************************************************/
        else if (!strcmp(parmName, "Speciationpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        if (activeParts[i] == YES || nApplied == 0)
                            strcpy(modelParams[i].speciationPr, tempStr);
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Speciationpr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if (activeParts[i] == YES || nApplied == 0)
                        {
                        if (!strcmp(modelParams[i].speciationPr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].speciationUni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].speciationUni[0] >= modelParams[i].speciationUni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Speciationpr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].speciationUni[0], modelParams[i].speciationUni[1]);
                                else
                                    MrBayesPrint ("%s   Setting Speciationpr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].speciationUni[0], modelParams[i].speciationUni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].speciationPr,"Exponential"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD <= 0.0)
                                {
                                MrBayesPrint ("%s   Exponential parameter must be positive\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].speciationExp = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Speciationpr to Exponential(%1.2lf)\n", spacer, modelParams[i].speciationExp);
                            else
                                MrBayesPrint ("%s   Setting Speciationpr to Exponential(%1.2lf) for partition %d\n", spacer, modelParams[i].speciationExp, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        else if (!strcmp(modelParams[i].speciationPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD <= 0.0)
                                {
                                MrBayesPrint ("%s   Net speciation rate must be positive\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].speciationFix = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Speciationpr to Fixed(%1.2lf)\n", spacer, modelParams[i].speciationFix);
                            else
                                MrBayesPrint ("%s   Setting Speciationpr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].speciationFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Extinctionpr (extinctionPr) *************************************************/
        else if (!strcmp(parmName, "Extinctionpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        if (activeParts[i] == YES || nApplied == 0)
                            strcpy(modelParams[i].extinctionPr, tempStr);
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Extinctionpr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if (activeParts[i] == YES || nApplied == 0)
                        {
                        if (!strcmp(modelParams[i].extinctionPr,"Beta"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD <= 0.0)
                                {
                                MrBayesPrint ("%s   Beta parameter must be positive\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].extinctionBeta[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Extinctionpr to Beta(%1.2lf,%1.2lf)\n", spacer, modelParams[i].extinctionBeta[0], modelParams[i].extinctionBeta[1]);
                                else
                                    MrBayesPrint ("%s   Setting Extinctionpr to Beta(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].extinctionBeta[0], modelParams[i].extinctionBeta[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].extinctionPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD < 0.0 || tempD >= 1.0)
                                {
                                MrBayesPrint ("%s   Relative extinction rate must be in range [0,1)\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].extinctionFix = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Extinctionpr to Fixed(%1.2lf)\n", spacer, modelParams[i].extinctionFix);
                            else
                                MrBayesPrint ("%s   Setting Extinctionpr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].extinctionFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Fossilizationpr (fossilizationPr) */
        else if (!strcmp(parmName, "Fossilizationpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        if (activeParts[i] == YES || nApplied == 0)
                            strcpy(modelParams[i].fossilizationPr, tempStr);
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Fossilization argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if (activeParts[i] == YES || nApplied == 0)
                        {
                        if (!strcmp(modelParams[i].fossilizationPr,"Beta"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD <= 0.0)
                                {
                                MrBayesPrint ("%s   Beta parameter must be positive\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].fossilizationBeta[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Fossilizationpr to Beta(%1.2lf,%1.2lf)\n", spacer, modelParams[i].fossilizationBeta[0], modelParams[i].fossilizationBeta[1]);
                                else
                                    MrBayesPrint ("%s   Setting Fossilizationpr to Beta(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].fossilizationBeta[0], modelParams[i].fossilizationBeta[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].fossilizationPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD < 0.0 || tempD > 1.0)
                                {
                                MrBayesPrint ("%s   Relative fossilization rate must be in the range (0,1]\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].fossilizationFix = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Fossilizationpr to Fixed(%1.2lf)\n", spacer, modelParams[i].fossilizationFix);
                            else
                                MrBayesPrint ("%s   Setting Fossilizationpr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].fossilizationFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set SampleStrat (sampleStrat) ***************************************************/
        else if (!strcmp(parmName, "Samplestrat"))
            {
            if (expecting == Expecting(EQUALSIGN))
                {
                expecting = Expecting(ALPHA);
                }
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            strcpy(modelParams[i].sampleStrat, tempStr);
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting SampleStrat to %s\n", spacer, modelParams[i].sampleStrat);
                            else
                                MrBayesPrint ("%s   Setting SampleStrat to %s for partition %d\n", spacer, modelParams[i].sampleStrat, i+1);
                            if (!strcmp(modelParams[i].sampleStrat,"Random") || !strcmp(modelParams[i].sampleStrat,"Diversity"))
                                {
                                foundFSNum[i] = foundFSTime[i] = NO;
                                modelParams[i].sampleFSNum = 0;
                                numVars[i] = 0;
                                expecting  = Expecting(NUMBER);
                                expecting |= Expecting(PARAMETER);
                                expecting |= Expecting(SEMICOLON);
                                }
                            else
                                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Samplestrat argument\n", spacer);
                    return (ERROR);
                    }
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if (activeParts[i] == YES || nApplied == 0)
                        {
                        if (foundFSNum[i] == NO)
                            {
                            sscanf (tkn, "%d", &tempInt);
                            if (tempInt <= 0)
                                {
                                MrBayesPrint ("%s   Number of fossil slice sampling events must be > 0\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].sampleFSNum = tempInt;
                            if (memAllocs[ALLOC_SAMPLEFOSSILSLICE] == YES)
                                {
                                free(modelParams[i].sampleFSProb);
                                free(modelParams[i].sampleFSTime);
                                }
                            modelParams[i].sampleFSTime = (MrBFlt *)SafeMalloc((size_t)(tempInt*sizeof(MrBFlt)));
                            modelParams[i].sampleFSProb = (MrBFlt *)SafeMalloc((size_t)(tempInt*sizeof(MrBFlt)));
                            memAllocs[ALLOC_SAMPLEFOSSILSLICE] = YES;
                            foundFSNum[i] = YES;
                            expecting  = Expecting(COLON);
                            }
                        else if (foundFSTime[i] == NO)
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD <= 0.0)
                                {
                                MrBayesPrint ("%s   Time of fossil slice sampling events must be > 0.\n", spacer);
                                return (ERROR);
                                }
                            if (numVars[i] > 0 && modelParams[i].sampleFSTime[numVars[i]-1] < tempD)
                                {
                                MrBayesPrint ("%s   Time of fossil slice sampling events must be in decreasing order\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].sampleFSTime[numVars[i]] = tempD;
                            foundFSTime[i] = YES;
                            expecting  = Expecting(NUMBER);
                            }
                        else
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD < 0.0 || tempD > 1.0)
                                {
                                MrBayesPrint ("%s   Prob of fossil slice sampling events must be in [0,1]\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].sampleFSProb[numVars[i]] = tempD;
                            foundFSTime[i] = NO;
                            expecting  = Expecting(COMMA);
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting %d FSTime FSProb to %1.2lf %1.6lf\n", spacer, numVars[i]+1,
                                              modelParams[i].sampleFSTime[numVars[i]], modelParams[i].sampleFSProb[numVars[i]]);
                            else
                                MrBayesPrint ("%s   Setting %d FSTime FSProb to %1.2lf %1.6lf for partition %d\n", spacer, numVars[i]+1,
                                              modelParams[i].sampleFSTime[numVars[i]], modelParams[i].sampleFSProb[numVars[i]], i+1);
                            numVars[i]++;
                            if (numVars[i] == modelParams[i].sampleFSNum)
                                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COLON) || expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else
                {
                return (ERROR);
                }
            }
        /* set Sampleprob (sampleProb) *****************************************************/
        else if (!strcmp(parmName, "Sampleprob"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(NUMBER);
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0))
                        {
                        sscanf (tkn, "%lf", &tempD);
                        if (tempD <= 0.0 || tempD > 1.0)
                            {
                            MrBayesPrint ("%s   Sampleprob should be in range (0,1]\n", spacer);
                            return (ERROR);
                            }
                        modelParams[i].sampleProb = tempD;
                        if (nApplied == 0 && numCurrentDivisions == 1)
                            MrBayesPrint ("%s   Setting Sampleprob to %1.8lf\n", spacer, modelParams[i].sampleProb);
                        else
                            MrBayesPrint ("%s   Setting Sampleprob to %1.8lf for partition %d\n", spacer, modelParams[i].sampleProb, i+1);
                        }
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Treeagepr (treeAgePr) *******************************************************/
        else if (!strcmp(parmName, "Treeagepr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            strcpy(modelParams[i].treeAgePr.name, tempStr);
                            if (!strcmp(tempStr,"Fixed"))
                                modelParams[i].treeAgePr.prior = fixed;
                            else if (!strcmp(tempStr,"Uniform"))
                                modelParams[i].treeAgePr.prior = uniform;
                            else if (!strcmp(tempStr,"Offsetexponential"))
                                modelParams[i].treeAgePr.prior = offsetExponential;
                            else if (!strcmp(tempStr,"Truncatednormal"))
                                modelParams[i].treeAgePr.prior = truncatedNormal;
                            else if (!strcmp(tempStr,"Lognormal"))
                                modelParams[i].treeAgePr.prior = logNormal;
                            else if (!strcmp(tempStr,"Offsetlognormal"))
                                modelParams[i].treeAgePr.prior = offsetLogNormal;
                            else if (!strcmp(tempStr,"Gamma"))
                                modelParams[i].treeAgePr.prior = standardGamma;
                            else if (!strcmp(tempStr,"Offsetgamma"))
                                modelParams[i].treeAgePr.prior = offsetGamma;
                            }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Treeagepr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    if (activeParts[i] == YES || nApplied == 0)
                        strcat(modelParams[i].treeAgePr.name, "(");
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                sscanf (tkn, "%lf", &tempD);
                sprintf (tempStr, "%1.2lf", tempD);
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if (activeParts[i] == YES || nApplied == 0)
                        {
                        if (numVars[i] == 0 && tempD < 0.0)
                            {
                            if (modelParams[i].treeAgePr.prior == uniform ||
                                modelParams[i].treeAgePr.prior == offsetExponential ||
                                modelParams[i].treeAgePr.prior == truncatedNormal ||
                                modelParams[i].treeAgePr.prior == offsetLogNormal ||
                                modelParams[i].treeAgePr.prior == offsetGamma)
                                MrBayesPrint("%s   Minimum, offset or truncation point must be nonnegative\n", spacer);
                            else if (modelParams[i].treeAgePr.prior == fixed)
                                MrBayesPrint("%s   Fixed age must be nonnegative\n", spacer);
                            else
                                MrBayesPrint("%s   Mean must be nonnegative\n", spacer);
                            break;
                            }
                        else if (numVars[i] == 1)
                            {
                            if (modelParams[i].treeAgePr.prior == uniform && tempD <= modelParams[i].treeAgePr.priorParams[0])
                                {
                                MrBayesPrint("%s   Max of uniform distribution must be larger than min\n", spacer);
                                break;
                                }
                            else if ((modelParams[i].treeAgePr.prior == standardGamma || modelParams[i].treeAgePr.prior == logNormal) && tempD <= 0.0)
                                {
                                MrBayesPrint("%s   Standard deviation must be positive\n", spacer);
                                break;
                                }
                            else if ((modelParams[i].treeAgePr.prior == offsetExponential ||
                                      modelParams[i].treeAgePr.prior == offsetGamma ||
                                      modelParams[i].treeAgePr.prior == offsetLogNormal) && tempD <= modelParams[i].treeAgePr.priorParams[0])
                                {
                                MrBayesPrint("%s   Mean must be larger than offset\n", spacer);
                                break;
                                }
                            }
                        else if (numVars[i] == 2 && tempD <= 0.0)
                            {
                            MrBayesPrint("%s   Standard deviation must be positive\n", spacer);
                            break;
                            }
                        modelParams[i].treeAgePr.priorParams[numVars[i]++] = tempD;
                        sprintf (tempStr, "%1.2lf", tempD);
                        strcat(modelParams[i].treeAgePr.name, tempStr);
                        if (modelParams[i].treeAgePr.prior == fixed || numVars[i] == 3)
                            expecting = Expecting(RIGHTPAR);
                        else if (numVars[i] == 1)
                            expecting = Expecting(COMMA);
                        else if (modelParams[i].treeAgePr.prior == standardGamma ||
                                 modelParams[i].treeAgePr.prior == uniform ||
                                 modelParams[i].treeAgePr.prior == offsetExponential ||
                                 modelParams[i].treeAgePr.prior == logNormal)
                            expecting = Expecting(RIGHTPAR);
                        else
                            expecting = Expecting(COMMA);
                        }
                    }
                if (i < numCurrentDivisions)
                    {
                    /* An error occurred. Reset calibrations and bail out */
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            strcpy(modelParams[i].treeAgePr.name, "Gamma(1.00,1.00)");
                            modelParams[i].treeAgePr.prior = standardGamma;
                            modelParams[i].treeAgePr.priorParams[0] = 1.0;
                            modelParams[i].treeAgePr.priorParams[1] = 1.0;
                            modelParams[i].treeAgePr.priorParams[2] = -1.0;
                            modelParams[i].treeAgePr.min = 0.0;
                            modelParams[i].treeAgePr.max = POS_INFINITY;
                            }
                        }
                    return (ERROR);
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    if (activeParts[i] == YES || nApplied == 0)
                        strcat(modelParams[i].treeAgePr.name, ",");
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if (activeParts[i] == YES || nApplied == 0)
                        {
                        strcat(modelParams[i].treeAgePr.name, ")");
                        MrBayesPrint ("%s   Setting Treeagepr to %s\n", spacer, modelParams[i].treeAgePr.name);

                        if (modelParams[i].treeAgePr.prior == fixed)
                            {
                            modelParams[i].treeAgePr.LnPriorProb   = &LnPriorProbFix;
                            modelParams[i].treeAgePr.LnPriorRatio  = &LnProbRatioFix;
                            modelParams[i].treeAgePr.min           = modelParams[i].treeAgePr.priorParams[0];
                            modelParams[i].treeAgePr.max           = modelParams[i].treeAgePr.priorParams[0];
                            }
                        else if (modelParams[i].treeAgePr.prior == uniform)
                            {
                            modelParams[i].treeAgePr.LnPriorProb   = &LnPriorProbUniform;
                            modelParams[i].treeAgePr.LnPriorRatio  = &LnProbRatioUniform;
                            modelParams[i].treeAgePr.min           = modelParams[i].treeAgePr.priorParams[0];
                            modelParams[i].treeAgePr.max           = modelParams[i].treeAgePr.priorParams[1];
                            }
                        else if (modelParams[i].treeAgePr.prior == offsetExponential)
                            {
                            modelParams[i].treeAgePr.LnPriorProb   = &LnPriorProbOffsetExponential_Param_Offset_Mean;
                            modelParams[i].treeAgePr.LnPriorRatio  = &LnProbRatioOffsetExponential_Param_Offset_Mean;
                            modelParams[i].treeAgePr.min           = modelParams[i].treeAgePr.priorParams[0];
                            modelParams[i].treeAgePr.max           = POS_INFINITY;
                            }
                        else if (modelParams[i].treeAgePr.prior == truncatedNormal)
                            {
                            modelParams[i].treeAgePr.LnPriorProb   = &LnPriorProbTruncatedNormal_Param_Trunc_Mean_Sd;
                            modelParams[i].treeAgePr.LnPriorRatio  = &LnProbRatioTruncatedNormal_Param_Trunc_Mean_Sd;
                            modelParams[i].treeAgePr.min           = modelParams[i].treeAgePr.priorParams[0];
                            modelParams[i].treeAgePr.max           = POS_INFINITY;
                            }
                        else if (modelParams[i].treeAgePr.prior == logNormal)
                            {
                            modelParams[i].treeAgePr.LnPriorProb   = &LnPriorProbLognormal_Param_Mean_Sd;
                            modelParams[i].treeAgePr.LnPriorRatio  = &LnProbRatioLognormal_Param_Mean_Sd;
                            modelParams[i].treeAgePr.min           = 0.0;
                            modelParams[i].treeAgePr.max           = POS_INFINITY;
                            }
                        else if (modelParams[i].treeAgePr.prior == offsetLogNormal)
                            {
                            modelParams[i].treeAgePr.LnPriorProb   = &LnPriorProbOffsetLognormal_Param_Offset_Mean_Sd;
                            modelParams[i].treeAgePr.LnPriorRatio  = &LnProbRatioOffsetLognormal_Param_Offset_Mean_Sd;
                            modelParams[i].treeAgePr.min           = modelParams[i].treeAgePr.priorParams[0];
                            modelParams[i].treeAgePr.max           = POS_INFINITY;
                            }
                        else if (modelParams[i].treeAgePr.prior == standardGamma)
                            {
                            modelParams[i].treeAgePr.LnPriorProb   = &LnPriorProbGamma_Param_Mean_Sd;
                            modelParams[i].treeAgePr.LnPriorRatio  = &LnProbRatioGamma_Param_Mean_Sd;
                            modelParams[i].treeAgePr.min           = 0.0;
                            modelParams[i].treeAgePr.max           = POS_INFINITY;
                            }
                        else if (modelParams[i].treeAgePr.prior == offsetGamma)
                            {
                            modelParams[i].treeAgePr.LnPriorProb   = &LnPriorProbOffsetGamma_Param_Offset_Mean_Sd;
                            modelParams[i].treeAgePr.LnPriorRatio  = &LnProbRatioOffsetGamma_Param_Offset_Mean_Sd;
                            modelParams[i].treeAgePr.min           = modelParams[i].treeAgePr.priorParams[0];
                            modelParams[i].treeAgePr.max           = POS_INFINITY;
                            }
                        }
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Clockratepr (clockRatePr) ****************************************************/
        else if (!strcmp(parmName, "Clockratepr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                {
                foundDash = NO;
                expecting = Expecting(ALPHA);
                }
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            strcpy(modelParams[i].clockRatePr, tempStr);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Clockratepr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                expecting |= Expecting(DASH);   /* negative numbers possible */
                }
            else if (expecting == Expecting(DASH))
                {
                foundDash = YES;
                expecting = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                sscanf (tkn, "%lf", &tempD);
                if (foundDash == YES)
                    {
                    foundDash = NO;
                    tempD *= -1.0;
                    }
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if (activeParts[i] == YES || nApplied == 0)
                        {
                        if (!strcmp(modelParams[i].clockRatePr,"Normal"))
                            {
                            if (tempD <= 0.0)
                                {
                                if (numVars[i] == 0)
                                    MrBayesPrint ("%s   Mean of the normal must be positive\n", spacer);
                                else if (numVars[i] == 1)
                                    MrBayesPrint ("%s   Standard deviation of the normal must be positive\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].clockRateNormal[numVars[i]] = tempD;
                            numVars[i]++;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (nApplied == 0 || numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Clockratepr to Normal(%1.2lf,%1.2lf)\n", spacer, modelParams[i].clockRateNormal[0], modelParams[i].clockRateNormal[1]);
                                else
                                    MrBayesPrint ("%s   Setting Clockratepr to Normal(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].clockRateNormal[0], modelParams[i].clockRateNormal[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].clockRatePr,"Lognormal"))
                            {
                            modelParams[i].clockRateLognormal[numVars[i]] = tempD;
                            numVars[i]++;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (nApplied == 0 || numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Clockratepr to Lognormal(%1.2lf,%1.2lf)\n", spacer, modelParams[i].clockRateLognormal[0], modelParams[i].clockRateLognormal[1]);
                                else
                                    MrBayesPrint ("%s   Setting Clockratepr to Lognormal(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].clockRateLognormal[0], modelParams[i].clockRateLognormal[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].clockRatePr,"Exponential"))
                            {
                            if (tempD <= 0.0)
                                {
                                MrBayesPrint ("%s   Rate of the exponential must be positive\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].clockRateExp = tempD;
                            numVars[i]++;
                            if (nApplied == 0 || numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Clockratepr to Exponential(%1.2lf)\n", spacer, modelParams[i].clockRateExp);
                            else
                                MrBayesPrint ("%s   Setting Clockratepr to Exponential(%1.2lf) for partition %d\n", spacer, modelParams[i].clockRateExp, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        else if (!strcmp(modelParams[i].clockRatePr,"Gamma"))
                            {
                            if (tempD <= 0.0)
                                {
                                if (numVars[i] == 0)
                                    MrBayesPrint ("%s   Shape of the gamma must be positive\n", spacer);
                                else if (numVars[i] == 1)
                                    MrBayesPrint ("%s   Rate (inverse scale) of the gamma must be positive\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].clockRateGamma[numVars[i]] = tempD;
                            numVars[i]++;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (nApplied == 0 || numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Clockratepr to Gamma(%1.2lf,%1.2lf)\n", spacer, modelParams[i].clockRateGamma[0], modelParams[i].clockRateGamma[1]);
                                else
                                    MrBayesPrint ("%s   Setting Clockratepr to Gamma(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].clockRateGamma[0], modelParams[i].clockRateGamma[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].clockRatePr,"Fixed"))
                            {
                            if (tempD <= 0.0)
                                {
                                MrBayesPrint ("%s   Fixed clock rate must be positive\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].clockRateFix = tempD;
                            numVars[i]++;
                            if (nApplied == 0 || numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Clockratepr to Fixed(%1.6lf)\n", spacer, modelParams[i].clockRateFix);
                            else
                                MrBayesPrint ("%s   Setting Clockratepr to Fixed(%1.6lf) for partition %d\n", spacer, modelParams[i].clockRateFix, i+1);
                            for (k=0; k<numGlobalChains; k++)
                                {
                                if (UpdateClockRate(tempD, k) == ERROR) 
                                    return (ERROR);
                                }
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Popsizepr (popSizePr) **************************************************************/
        else if (!strcmp(parmName, "Popsizepr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            strcpy(modelParams[i].popSizePr, tempStr);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Popsizepr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                        {
                        if (!strcmp(modelParams[i].popSizePr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].popSizeUni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                {
                                if (tempD <= 0.0)
                                    {
                                    MrBayesPrint ("%s   Lower value for Uniform must be a positive number\n", spacer);
                                    return (ERROR);
                                    }
                                expecting  = Expecting(COMMA);
                                }
                            else
                                {
                                if (modelParams[i].popSizeUni[0] >= modelParams[i].popSizeUni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for Uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Popsizepr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].popSizeUni[0], modelParams[i].popSizeUni[1]);
                                else
                                    MrBayesPrint ("%s   Setting Popsizepr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].popSizeUni[0], modelParams[i].popSizeUni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].popSizePr,"Lognormal"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].popSizeLognormal[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                {
                                expecting  = Expecting(COMMA);
                                }
                            else
                                {
                                if (modelParams[i].popSizeLognormal[1] <= 0.0)
                                    {
                                    MrBayesPrint ("%s   Standard deviation of Lognormal must be a positive number\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Popsizepr to Lognormal(%1.2lf,%1.2lf)\n", spacer, modelParams[i].popSizeLognormal[0], modelParams[i].popSizeLognormal[1]);
                                else
                                    MrBayesPrint ("%s   Setting Popsizepr to Lognormal(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].popSizeLognormal[0], modelParams[i].popSizeLognormal[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].popSizePr,"Normal"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].popSizeNormal[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                {
                                if (modelParams[i].popSizeNormal[0] <= 0.0)
                                    {
                                    MrBayesPrint ("%s   Mean of Truncated Normal must be a positive number\n", spacer);
                                    return (ERROR);
                                    }
                                expecting  = Expecting(COMMA);
                                }
                            else
                                {
                                if (modelParams[i].popSizeNormal[1] <= 0.0)
                                    {
                                    MrBayesPrint ("%s   Standard deviation of Truncated Normal must be a positive number\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Popsizepr to Truncated Normal(%1.2lf,%1.2lf)\n", spacer, modelParams[i].popSizeNormal[0], modelParams[i].popSizeNormal[1]);
                                else
                                    MrBayesPrint ("%s   Setting Popsizepr to Truncated Normal(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].popSizeNormal[0], modelParams[i].popSizeNormal[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].popSizePr,"Gamma"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].popSizeGamma[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                {
                                if (modelParams[i].popSizeGamma[0] <= 0.0)
                                    {
                                    MrBayesPrint ("%s   Shape (alpha) of Gamma must be a positive number\n", spacer);
                                    return (ERROR);
                                    }
                                expecting  = Expecting(COMMA);
                                }
                            else
                                {
                                if (modelParams[i].popSizeGamma[1] <= 0.0)
                                    {
                                    MrBayesPrint ("%s   Rate (beta) of Gamma must be a positive number\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Popsizepr to Gamma(%1.2lf,%1.2lf)\n", spacer, modelParams[i].popSizeGamma[0], modelParams[i].popSizeGamma[1]);
                                else
                                    MrBayesPrint ("%s   Setting Popsizepr to Gamma(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].popSizeGamma[0], modelParams[i].popSizeGamma[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].popSizePr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (AreDoublesEqual(tempD, 0.0, ETA)==YES)
                                {
                                MrBayesPrint ("%s   Popsizepr cannot be fixed to 0.0\n", spacer);
                                return (ERROR);
                                }
                            modelParams[i].popSizeFix = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Popsizepr to Fixed(%1.5lf)\n", spacer, modelParams[i].popSizeFix);
                            else
                                MrBayesPrint ("%s   Setting Popsizepr to Fixed(%1.5lf) for partition %d\n", spacer, modelParams[i].popSizeFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Popvarpr (popVarPr) **************************************************************/
        else if (!strcmp(parmName, "Popvarpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            strcpy(modelParams[i].popVarPr, tempStr);
                        
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Popvarpr to %s\n", spacer, modelParams[i].popVarPr);
                            else
                                MrBayesPrint ("%s   Setting Popvarpr to %s for partition %d\n", spacer, modelParams[i].popVarPr, i+1);
                            }
                        }
                    expecting  = Expecting(PARAMETER) | Expecting(SEMICOLON);
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Popvarpr argument\n", spacer);
                    return (ERROR);
                    }
                }
            else
                return (ERROR);
            }
        /* set Compound Poisson Process rate prior (cppRatePr) *********************************************************/
        else if (!strcmp(parmName, "Cppratepr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            strcpy(modelParams[i].cppRatePr, tempStr);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Cppratepr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if (activeParts[i] == YES || nApplied == 0)
                        {
                        if (!strcmp(modelParams[i].cppRatePr,"Exponential"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].cppRateExp = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Cppratepr to Exponential(%1.2lf)\n", spacer, modelParams[i].cppRateExp);
                            else
                                MrBayesPrint ("%s   Setting Cppratepr to Exponential(%1.2lf) for partition %d\n", spacer, modelParams[i].cppRateExp, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        else if (!strcmp(modelParams[i].cppRatePr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD < CPPLAMBDA_MIN || tempD > CPPLAMBDA_MAX)
                                {
                                MrBayesPrint ("%s   CPP rate must be in the range %f - %f\n", spacer, CPPLAMBDA_MIN, CPPLAMBDA_MAX);
                                return (ERROR);
                                }
                            modelParams[i].cppRateFix = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Cppratepr to Fixed(%1.2lf)\n", spacer, modelParams[i].cppRateFix);
                            else
                                MrBayesPrint ("%s   Setting Cppratepr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].cppRateFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Compound Poisson Process rate multiplier standard deviation (log scale) ***********************/
        else if (!strcmp(parmName, "Cppmultdevpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            strcpy(modelParams[i].cppMultDevPr, tempStr);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Cppmultdevpr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if (activeParts[i] == YES || nApplied == 0)
                        {
                        if (!strcmp(modelParams[i].cppMultDevPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD < POSREAL_MIN || tempD > POSREAL_MAX)
                                {
                                MrBayesPrint ("%s   The log standard deviation of rate multipliers must be in the range %f - %f\n", spacer, POSREAL_MIN, POSREAL_MAX);
                                return (ERROR);
                                }
                            modelParams[i].cppMultDevFix = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Cppmultdevpr to Fixed(%1.2lf)\n", spacer, modelParams[i].cppMultDevFix);
                            else
                                MrBayesPrint ("%s   Setting Cppmultdevpr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].cppMultDevFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set prior for variance of lognormal of autocorrelated rates (tk02varPr) ***********************/
        else if (!strcmp(parmName, "TK02varpr") || !strcmp(parmName,"Bmvarpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            strcpy(modelParams[i].tk02varPr, tempStr);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid TK02varpr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if (activeParts[i] == YES || nApplied == 0)
                        {
                        if (!strcmp(modelParams[i].tk02varPr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].tk02varUni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].tk02varUni[0] >= modelParams[i].tk02varUni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting TK02varpr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].tk02varUni[0], modelParams[i].tk02varUni[1]);
                                else
                                    MrBayesPrint ("%s   Setting TK02varpr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].tk02varUni[0], modelParams[i].tk02varUni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].tk02varPr,"Exponential"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].tk02varExp = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting TK02varpr to Exponential(%1.2lf)\n", spacer, modelParams[i].tk02varExp);
                            else
                                MrBayesPrint ("%s   Setting TK02varpr to Exponential(%1.2lf) for partition %d\n", spacer, modelParams[i].tk02varExp, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        else if (!strcmp(modelParams[i].tk02varPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD < TK02VAR_MIN || tempD > TK02VAR_MAX)
                                {
                                MrBayesPrint ("%s   Ratevar (nu) must be in the range %f - %f\n", spacer, TK02VAR_MIN, TK02VAR_MAX);
                                return (ERROR);
                                }
                            modelParams[i].tk02varFix = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting TK02varpr to Fixed(%1.2lf)\n", spacer, modelParams[i].tk02varFix);
                            else
                                MrBayesPrint ("%s   Setting TK02varpr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].tk02varFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set prior for shape of independent branch rate gamma distribution (igrvarPr) ***********************/
        else if (!strcmp(parmName, "Igrvarpr") || !strcmp(parmName, "Ibrvarpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            strcpy(modelParams[i].igrvarPr, tempStr);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Igrvarpr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if (activeParts[i] == YES || nApplied == 0)
                        {
                        if (!strcmp(modelParams[i].igrvarPr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].igrvarUni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].igrvarUni[0] >= modelParams[i].igrvarUni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Igrvarpr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].igrvarUni[0], modelParams[i].igrvarUni[1]);
                                else
                                    MrBayesPrint ("%s   Setting Igrvarpr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].igrvarUni[0], modelParams[i].igrvarUni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].igrvarPr,"Exponential"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].igrvarExp = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Igrvarpr to Exponential(%1.2lf)\n", spacer, modelParams[i].igrvarExp);
                            else
                                MrBayesPrint ("%s   Setting Igrvarpr to Exponential(%1.2lf) for partition %d\n", spacer, modelParams[i].igrvarExp, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        else if (!strcmp(modelParams[i].igrvarPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD < IGRVAR_MIN || tempD > IGRVAR_MAX)
                                {
                                MrBayesPrint ("%s   Igrvar must be in the range %f - %f\n", spacer, IGRVAR_MIN, IGRVAR_MAX);
                                return (ERROR);
                                }
                            modelParams[i].igrvarFix = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Igrvarpr to Fixed(%1.2lf)\n", spacer, modelParams[i].igrvarFix);
                            else
                                MrBayesPrint ("%s   Setting Igrvarpr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].igrvarFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set prior for variance of mixed relaxed clock model (mixedvarPr) ***********************/
        else if (!strcmp(parmName, "Mixedvarpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            strcpy(modelParams[i].mixedvarPr, tempStr);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Mixedvarpr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if (activeParts[i] == YES || nApplied == 0)
                        {
                        if (!strcmp(modelParams[i].mixedvarPr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].mixedvarUni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].mixedvarUni[0] >= modelParams[i].mixedvarUni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Mixedvarpr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].mixedvarUni[0], modelParams[i].mixedvarUni[1]);
                                else
                                    MrBayesPrint ("%s   Setting Mixedvarpr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].mixedvarUni[0], modelParams[i].mixedvarUni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].mixedvarPr,"Exponential"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].mixedvarExp = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Mixedvarpr to Exponential(%1.2lf)\n", spacer, modelParams[i].mixedvarExp);
                            else
                                MrBayesPrint ("%s   Setting Mixedvarpr to Exponential(%1.2lf) for partition %d\n", spacer, modelParams[i].mixedvarExp, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        else if (!strcmp(modelParams[i].mixedvarPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (tempD < IGRVAR_MIN || tempD > IGRVAR_MAX || tempD < TK02VAR_MIN || tempD > TK02VAR_MAX)
                                {
                                MrBayesPrint ("%s   Mixedvar must be in the range %f - %f\n", spacer, IGRVAR_MIN, IGRVAR_MAX);
                                return (ERROR);
                                }
                            modelParams[i].mixedvarFix = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Mixedvarpr to Fixed(%1.2lf)\n", spacer, modelParams[i].mixedvarFix);
                            else
                                MrBayesPrint ("%s   Setting Mixedvarpr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].mixedvarFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Growthpr (growthPr) **************************************************************/
        else if (!strcmp(parmName, "Growthpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                {
                expecting = Expecting(ALPHA);
                isNegative = NO;
                }
            else if (expecting == Expecting(ALPHA))
                {
                isNegative = NO;
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            strcpy(modelParams[i].growthPr, tempStr);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Growthpr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER) | Expecting(DASH);
                }
            else if (expecting == Expecting(DASH))
                {
                expecting  = Expecting(NUMBER);
                isNegative = YES;
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                        {
                        if (!strcmp(modelParams[i].growthPr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (isNegative == YES)
                                tempD *= -1.0;
                            modelParams[i].growthUni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].growthUni[0] >= modelParams[i].growthUni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Growthpr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].growthUni[0], modelParams[i].growthUni[1]);
                                else
                                    MrBayesPrint ("%s   Setting Growthpr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].growthUni[0], modelParams[i].growthUni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].growthPr,"Normal"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (isNegative == YES)
                                tempD *= -1.0;
                            modelParams[i].growthNorm[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].growthNorm[1] < 0.0)
                                    {
                                    MrBayesPrint ("%s   Variance for normal distribution should be greater than zero\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Growthpr to Normal(%1.2lf,%1.2lf)\n", spacer, modelParams[i].growthNorm[0], modelParams[i].growthNorm[1]);
                                else
                                    MrBayesPrint ("%s   Setting Growthpr to Normal(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].growthNorm[0], modelParams[i].growthNorm[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].growthPr,"Exponential"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].growthExp = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Growthpr to Exponential(%1.2lf)\n", spacer, modelParams[i].growthExp);
                            else
                                MrBayesPrint ("%s   Setting Growthpr to Exponential(%1.2lf) for partition %d\n", spacer, modelParams[i].growthExp, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        else if (!strcmp(modelParams[i].growthPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            if (isNegative == YES)
                                tempD *= -1.0;
                            modelParams[i].growthFix = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Growthpr to Fixed(%1.2lf)\n", spacer, modelParams[i].growthFix);
                            else
                                MrBayesPrint ("%s   Setting Growthpr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].growthFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                isNegative = NO;
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set Aamodelpr (aaModelPr) **************************************************************/
        else if (!strcmp(parmName, "Aamodelpr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                {
                expecting = Expecting(ALPHA);
                foundAaSetting = foundExp = modelIsFixed = foundDash = NO;
                fromI = 0;
                for (i=0; i<10; i++)
                    tempAaModelPrs[i] = 0.0;
                }
            else if (expecting == Expecting(ALPHA))
                {
                if (foundAaSetting == NO)
                    {
                    if (IsArgValid(tkn, tempStr) == NO_ERROR)
                        {
                        nApplied = NumActiveParts ();
                        for (i=0; i<numCurrentDivisions; i++)
                            {
                            if ((activeParts[i] == YES || nApplied == 0))
                                {
                                strcpy(modelParams[i].aaModelPr, tempStr);
                                if (!strcmp(modelParams[i].aaModelPr, "Mixed"))
                                    {
                                    if (nApplied == 0 && numCurrentDivisions == 1)
                                        MrBayesPrint ("%s   Setting Aamodelpr to %s\n", spacer, modelParams[i].aaModelPr);
                                    else
                                        MrBayesPrint ("%s   Setting Aamodelpr to %s for partition %d\n", spacer, modelParams[i].aaModelPr, i+1);
                                    }
                                }
                            }
                        }
                    else
                        {
                        MrBayesPrint ("%s   Invalid Aamodelpr argument\n", spacer);
                        return (ERROR);
                        }
                    foundAaSetting = YES;
                    if (!strcmp(tempStr, "Fixed"))
                        {
                        modelIsFixed = YES;
                        expecting = Expecting(LEFTPAR);
                        }
                    else
                        {
                        expecting = Expecting(LEFTPAR) | Expecting(PARAMETER) | Expecting(SEMICOLON);
                        }
                    }
                else
                    {
                    if (modelIsFixed == YES)
                        {
                        if (IsSame ("Poisson", tkn) == SAME      || IsSame ("Poisson", tkn) == CONSISTENT_WITH)
                            strcpy (tempStr, "Poisson");
                        else if (IsSame ("Equalin", tkn) == SAME || IsSame ("Equalin", tkn) == CONSISTENT_WITH)
                            strcpy (tempStr, "Equalin");
                        else if (IsSame ("Jones", tkn) == SAME   || IsSame ("Jones", tkn) == CONSISTENT_WITH)
                            strcpy (tempStr, "Jones");
                        else if (IsSame ("Dayhoff", tkn) == SAME || IsSame ("Dayhoff", tkn) == CONSISTENT_WITH)
                            strcpy (tempStr, "Dayhoff");
                        else if (IsSame ("Mtrev", tkn) == SAME   || IsSame ("Mtrev", tkn) == CONSISTENT_WITH)
                            strcpy (tempStr, "Mtrev");
                        else if (IsSame ("Mtmam", tkn) == SAME   || IsSame ("Mtmam", tkn) == CONSISTENT_WITH)
                            strcpy (tempStr, "Mtmam");
                        else if (IsSame ("Wag", tkn) == SAME     || IsSame ("Wag", tkn) == CONSISTENT_WITH)
                            strcpy (tempStr, "Wag");
                        else if (IsSame ("Rtrev", tkn) == SAME   || IsSame ("Rtrev", tkn) == CONSISTENT_WITH)
                            strcpy (tempStr, "Rtrev");
                        else if (IsSame ("Cprev", tkn) == SAME   || IsSame ("Cprev", tkn) == CONSISTENT_WITH)
                            strcpy (tempStr, "Cprev");
                        else if (IsSame ("Vt", tkn) == SAME      || IsSame ("Vt", tkn) == CONSISTENT_WITH)
                            strcpy (tempStr, "Vt");
                        else if (IsSame ("Blosum", tkn) == SAME  || IsSame ("Blosum", tkn) == CONSISTENT_WITH)
                            strcpy (tempStr, "Blosum");
                        else if (IsSame ("Blossum", tkn) == SAME || IsSame ("Blossum", tkn) == CONSISTENT_WITH)
                            strcpy (tempStr, "Blosum");
                        else if (IsSame ("LG", tkn) == SAME      || IsSame ("LG", tkn) == CONSISTENT_WITH)
                            strcpy (tempStr, "LG");
                        else if (IsSame ("Gtr", tkn) == SAME     || IsSame ("Gtr", tkn) == CONSISTENT_WITH)
                            strcpy (tempStr, "Gtr");
                        else
                            {
                            MrBayesPrint ("%s   Invalid amino acid model\n", spacer);
                            return (ERROR);
                            }
                        nApplied = NumActiveParts ();
                        for (i=0; i<numCurrentDivisions; i++)
                            {
                            if ((activeParts[i] == YES || nApplied == 0))
                                {
                                if (!strcmp(modelParams[i].aaModelPr, "Fixed"))
                                    {
                                    strcpy(modelParams[i].aaModel, tempStr);
                                    if (nApplied == 0 && numCurrentDivisions == 1)
                                        MrBayesPrint ("%s   Setting Aamodelpr to Fixed(%s)\n", spacer, modelParams[i].aaModel);
                                    else
                                        MrBayesPrint ("%s   Setting Aamodelpr to Fixed(%s) for partition %d\n", spacer, modelParams[i].aaModel, i+1);
                                    }
                                else
                                    {
                                    MrBayesPrint ("%s   You cannot assign an amino acid matrix for mixed models\n", spacer);
                                    return (ERROR);
                                    }
                                }
                            }
                        expecting = Expecting(RIGHTPAR);
                        }
                    else
                        {
                        if (IsSame ("Exponential", tkn) == SAME || IsSame ("Exponential", tkn) == CONSISTENT_WITH)
                            {
                            foundExp = YES;
                            expecting = Expecting(LEFTPAR);
                            }
                        else    
                            {
                            MrBayesPrint ("%s   Invalid argument \"%s\"\n", spacer, tkn);
                            return (ERROR);
                            }
                        }

                    }
                }
            else if (expecting == Expecting(NUMBER))
                {
                sscanf (tkn, "%lf", &tempD);
                if (fromI >= 10)
                    {
                    MrBayesPrint ("%s   Too many arguments in Aamodelpr\n", spacer);
                    return (ERROR);
                    }
                if (modelIsFixed == NO)
                    {
                    if (foundExp == YES)
                        {
                        if (foundDash == YES)
                            tempAaModelPrs[fromI++] = -tempD;
                        else
                            tempAaModelPrs[fromI++] = tempD;
                        expecting  = Expecting(RIGHTPAR);
                        }
                    else
                        {
                        if (foundDash == YES)
                            {
                            MrBayesPrint ("%s   Unexpected \"-\" in Aamodelpr\n", spacer);
                            return (ERROR);
                            }
                        else
                            {
                            if (tempD <= 0.000000000001)
                                tempAaModelPrs[fromI++] = -1000000000;
                            else
                                tempAaModelPrs[fromI++] = (MrBFlt) log(tempD);
                            }
                        expecting  = Expecting(COMMA) | Expecting(RIGHTPAR);
                        }
                    foundDash = NO;
                    }
                else
                    {
                    MrBayesPrint ("%s   Not expecting a number\n", spacer);
                    return (ERROR);
                    }
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                if (modelIsFixed == YES)
                    expecting  = Expecting(ALPHA);
                else
                    {
                    if (foundExp == YES)
                        expecting  = Expecting(NUMBER) | Expecting(DASH);
                    else
                        expecting  = Expecting(NUMBER) | Expecting(ALPHA);
                    }
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                if (modelIsFixed == YES)
                    expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                else
                    {
                    if (foundExp == YES)
                        {
                        foundExp = NO;
                        expecting = Expecting(COMMA) | Expecting(RIGHTPAR);
                        }
                    else    
                        {
                        if (fromI < 10)
                            {
                            MrBayesPrint ("%s   Too few arguments in Aamodelpr\n", spacer);
                            return (ERROR);
                            }
                        nApplied = NumActiveParts ();
                        for (i=0; i<numCurrentDivisions; i++)
                            {
                            if ((activeParts[i] == YES || nApplied == 0) && modelParams[i].dataType == PROTEIN)
                                {
                                if (!strcmp(modelParams[i].aaModelPr, "Fixed"))
                                    {
                                    MrBayesPrint ("%s   You cannot assign model prior probabilities for a fixed amino acid model\n", spacer);
                                    return (ERROR);
                                    }
                                else
                                    {
                                    for (j=0; j<10; j++)
                                        modelParams[i].aaModelPrProbs[j] = tempAaModelPrs[j];
                                    }
                                }
                            }
                        expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                        }
                    }               
                }
            else if (expecting == Expecting(DASH))
                {
                if (foundExp == YES)
                    {
                    foundDash = YES;
                    expecting  = Expecting(NUMBER);
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid argument \"%s\"\n", spacer, tkn);
                    return (ERROR);
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                if (modelIsFixed == YES)
                    {
                    MrBayesPrint ("%s   Not expecting \"%s\"\n", spacer, tkn);
                    return (ERROR);
                    }
                else
                    expecting  = Expecting(NUMBER) | Expecting(ALPHA);
                }
            else
                return (ERROR);
            }       
        /* set Brownscalepr (brownScalesPr) ****************************************************/
        else if (!strcmp(parmName, "Brownscalepr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && modelParams[i].dataType == CONTINUOUS)
                            {
                            strcpy(modelParams[i].brownScalesPr, tempStr);
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                            {
                            MrBayesPrint ("%s   Warning: %s can be set only for partition containing CONTINUOUS data.\
                            Currently there is no active partition with such data. ", spacer, parmName);
                            return (ERROR);
                            }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid Brownscalepr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && modelParams[i].dataType == CONTINUOUS)
                        {
                        if (!strcmp(modelParams[i].brownScalesPr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].brownScalesUni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].brownScalesUni[0] >= modelParams[i].brownScalesUni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Brownscalepr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].brownScalesUni[0], modelParams[i].brownScalesUni[1]);
                                else
                                    MrBayesPrint ("%s   Setting Brownscalepr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].brownScalesUni[0], modelParams[i].brownScalesUni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].brownScalesPr,"Gamma"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].brownScalesGamma[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting Brownscalepr to Gamma Mean=%1.2lf Var=%1.2lf\n", spacer, modelParams[i].brownScalesGamma[0], modelParams[i].brownScalesGamma[1]);
                                else
                                    MrBayesPrint ("%s   Setting Brownscalepr to Gamma Mean=%1.2lf Var=%1.2lf for partition %d\n", spacer, modelParams[i].brownScalesGamma[0], modelParams[i].brownScalesGamma[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].brownScalesPr,"Gammamean"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].brownScalesGammaMean = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Brownscalepr to Gamma Mean=<char. ave.> Var=%1.2lf\n", spacer, modelParams[i].brownScalesGammaMean);
                            else
                                MrBayesPrint ("%s   Setting Brownscalepr to Gamma Mean=<char.ave.> Var=%1.2lf for partition %d\n", spacer, modelParams[i].brownScalesGammaMean, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        else if (!strcmp(modelParams[i].brownScalesPr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].brownScalesFix = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting Brownscalepr to Fixed(%1.2lf)\n", spacer, modelParams[i].brownScalesFix);
                            else
                                MrBayesPrint ("%s   Setting Brownscalepr to Fixed(%1.2lf) for partition %d\n", spacer, modelParams[i].brownScalesFix, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set M10betapr (m10betapr) ********************************************************/
        else if (!strcmp(parmName, "M10betapr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].m10betapr, tempStr);
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                            {
                            MrBayesPrint ("%s   Warning: %s can be set only for partition containing data of at least one of the following type: DNA, RNA.\
                            Currently there is no active partition with such data. ", spacer, parmName);
                            return (ERROR);
                            }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid M10betapr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                        {
                        if (!strcmp(modelParams[i].m10betapr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].m10betaUni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].m10betaUni[0] >= modelParams[i].m10betaUni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting M10betapr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].m10betaUni[0], modelParams[i].m10betaUni[1]);
                                else
                                    MrBayesPrint ("%s   Setting M10betapr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].m10betaUni[0], modelParams[i].m10betaUni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].m10betapr,"Exponential"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].m10betaExp = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting M10betapr to Exponential(%1.2lf)\n", spacer, modelParams[i].m10betaExp);
                            else
                                MrBayesPrint ("%s   Setting M10betapr to Exponential(%1.2lf) for partition %d\n", spacer, modelParams[i].m10betaExp, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        else if (!strcmp(modelParams[i].m10betapr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].m10betaFix[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting M10betapr to Fixed(%1.2lf,%1.2lf)\n", spacer, modelParams[i].m10betaFix[0], modelParams[i].m10betaFix[1]);
                                else
                                    MrBayesPrint ("%s   Setting M10betapr to Fixed(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].m10betaFix[0], modelParams[i].m10betaFix[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set M10gammapr (m10gammapr) ********************************************************/
        else if (!strcmp(parmName, "M10gammapr"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    flag = 0;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].m10gammapr, tempStr);
                            flag = 1;
                            }
                        }
                    if (flag == 0)
                            {
                            MrBayesPrint ("%s   Warning: %s can be set only for partition containing data of at least one of the following type: DNA, RNA.\
                            Currently there is no active partition with such data. ", spacer, parmName);
                            return (ERROR);
                            }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid M10gammapr argument\n", spacer);
                    return (ERROR);
                    }
                expecting  = Expecting(LEFTPAR);
                for (i=0; i<numCurrentDivisions; i++)
                    numVars[i] = 0;
                }
            else if (expecting == Expecting(LEFTPAR))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(NUMBER))
                {
                nApplied = NumActiveParts ();
                for (i=0; i<numCurrentDivisions; i++)
                    {
                    if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                        {
                        if (!strcmp(modelParams[i].m10gammapr,"Uniform"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].m10gammaUni[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (modelParams[i].m10gammaUni[0] >= modelParams[i].m10gammaUni[1])
                                    {
                                    MrBayesPrint ("%s   Lower value for uniform should be greater than upper value\n", spacer);
                                    return (ERROR);
                                    }
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting M10gammapr to Uniform(%1.2lf,%1.2lf)\n", spacer, modelParams[i].m10gammaUni[0], modelParams[i].m10gammaUni[1]);
                                else
                                    MrBayesPrint ("%s   Setting M10gammapr to Uniform(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].m10gammaUni[0], modelParams[i].m10gammaUni[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        else if (!strcmp(modelParams[i].m10gammapr,"Exponential"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].m10gammaExp = tempD;
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting M10gammapr to Exponential(%1.2lf)\n", spacer, modelParams[i].m10gammaExp);
                            else
                                MrBayesPrint ("%s   Setting M10gammapr to Exponential(%1.2lf) for partition %d\n", spacer, modelParams[i].m10gammaExp, i+1);
                            expecting  = Expecting(RIGHTPAR);
                            }
                        else if (!strcmp(modelParams[i].m10gammapr,"Fixed"))
                            {
                            sscanf (tkn, "%lf", &tempD);
                            modelParams[i].m10gammaFix[numVars[i]++] = tempD;
                            if (numVars[i] == 1)
                                expecting  = Expecting(COMMA);
                            else
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Setting M10gammapr to Fixed(%1.2lf,%1.2lf)\n", spacer, modelParams[i].m10gammaFix[0], modelParams[i].m10gammaFix[1]);
                                else
                                    MrBayesPrint ("%s   Setting M10gammapr to Fixed(%1.2lf,%1.2lf) for partition %d\n", spacer, modelParams[i].m10gammaFix[0], modelParams[i].m10gammaFix[1], i+1);
                                expecting  = Expecting(RIGHTPAR);
                                }
                            }
                        }
                    }
                }
            else if (expecting == Expecting(COMMA))
                {
                expecting  = Expecting(NUMBER);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }

        else
            return (ERROR);
        }

    return (NO_ERROR);
}


int DoQuit (void)
{
    int         i;
    char        tempName[100];
    
    /* free information for model and matrix */
    FreeModel ();
    FreeMatrix ();
    
    SafeFclose (&logFileFp);
    logToFile = NO;
    
    /* check to see if any memory has not been freed */
    for (i=0; i<NUM_ALLOCS; i++)
        {
        if (memAllocs[i] == YES)
            {
            MrBayesPrint ("   WARNING: Memory (%d) has not been freed\n", i);
            if (mode == INTERACTIVE && quitOnError == NO)
                {
                MrBayesPrint ("%s   Hit return key to continue  ", spacer);
                fflush (stdin);
                if (fgets (tempName, 100, stdin) == NULL)
                    {
                    printf ("Error in function: %s at line: %d in file: %s", __FUNCTION__, __LINE__, __FILE__);
                    }
                }
            }
        }
    
    /* free modelIndicatorParams and modelElementNames */
    for (i=0; i<203; i++)
        free (modelElementNames[1][i]);
    for (i=0; i<3; i++)
        free (modelElementNames[i]);
    free (modelElementNames);
    free (modelIndicatorParams);
    
    MrBayesPrint ("   Quitting program\n\n");
    
    /* If we quit while reading a mrbayes block, then we need to make certain
     that we return a NO_ERROR_QUIT so we can break out of DoExecute cleanly,
     and dealloc "s" there. */
    if (inMrbayesBlock == YES)
        {
        inMrbayesBlock = NO;
        return (NO_ERROR_QUIT);
        }
    
    return (NO_ERROR);
}


int DoReport (void)
{
    /* TODO: smart update */
    if (SetUpAnalysis (&globalSeed) == ERROR)
        return (ERROR);
    return (NO_ERROR);
}


int DoReportParm (char *parmName, char *tkn)
{
    int         i, tempInt, nApplied;
    char        tempStr[100];

    if (defMatrix == NO)
        {
        MrBayesPrint ("%s   A matrix must be specified before the report settings can be altered\n", spacer);
        return (ERROR);
        }
    if (inValidCommand == YES)
        {
        for (i=0; i<numCurrentDivisions; i++)
            activeParts[i] = NO;
        inValidCommand = NO;
        }

    if (expecting == Expecting(PARAMETER))
        {
        expecting = Expecting(EQUALSIGN);
        }
    else
        {
        /* set Applyto (Applyto) *************************************************************/
        if (!strcmp(parmName, "Applyto"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(LEFTPAR);
            else if (expecting == Expecting(LEFTPAR))
                {
                for (i=0; i<numCurrentDivisions; i++)
                    activeParts[i] = NO;
                fromI = toJ = -1;
                foundDash = NO;
                expecting = Expecting(NUMBER) | Expecting(ALPHA);
                }
            else if (expecting == Expecting(RIGHTPAR))
                {
                if (fromI != -1)
                    activeParts[fromI-1] = YES;
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else if (expecting == Expecting(COMMA))
                {
                foundComma = YES;
                expecting = Expecting(NUMBER);
                }
            else if (expecting == Expecting(ALPHA))
                {
                if (IsSame ("All", tkn) == DIFFERENT)
                    {
                    MrBayesPrint ("%s   Do not understand delimiter \"%s\"\n", spacer, tkn);
                    return (ERROR);
                    }
                for (i=0; i<numCurrentDivisions; i++)
                    activeParts[i] = YES;
                expecting  = Expecting(RIGHTPAR);
                }
            else if (expecting == Expecting(NUMBER))
                {
                sscanf (tkn, "%d", &tempInt);
                if (tempInt > numCurrentDivisions)
                    {
                    MrBayesPrint ("%s   Partition delimiter is too large\n", spacer);
                    return (ERROR);
                    }
                if (fromI == -1)
                    fromI = tempInt;
                else if (fromI != -1 && toJ == -1 && foundDash == YES && foundComma == NO)
                    {
                    toJ = tempInt;
                    for (i=fromI-1; i<toJ; i++)
                        activeParts[i] = YES;
                    fromI = toJ = -1;
                    foundDash = NO;
                    }
                else if (fromI != -1 && toJ == -1 && foundDash == NO && foundComma == YES)
                    {
                    activeParts[fromI-1] = YES;
                    fromI = tempInt;
                    foundComma = NO;
                    }
                    
                expecting  = Expecting(COMMA);
                expecting |= Expecting(DASH);
                expecting |= Expecting(RIGHTPAR);
                }
            else if (expecting == Expecting(DASH))
                {
                foundDash = YES;
                expecting = Expecting(NUMBER);
                }
            else
                return (ERROR);
            }
        /* set report format of tratio ***************************************************/
        else if (!strcmp(parmName, "Tratio"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting (ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    tempInt = NO;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        /* check that data type is correct; we do not know yet if the user will specify
                        a nst=2 model so we cannot check that tratio is an active parameter */
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].tratioFormat, tempStr);
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting transition/transversion rate ratio (tratio) format to %s\n", spacer, modelParams[i].tratioFormat);
                            else
                                MrBayesPrint ("%s   Setting transition/transversion rate ratio (tratio) format to %s for partition %d\n", spacer, modelParams[i].tratioFormat, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid transition/transversion rate ratio (tratio) format \n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set report format of revmat ***************************************************/
        else if (!strcmp(parmName, "Revmat"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting (ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    tempInt = NO;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        /* check that data type is correct; we do not know yet if the user will specify
                           a nst=6 model so we cannot check that revmat is an active parameter */
                        if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA))
                            {
                            strcpy(modelParams[i].revmatFormat, tempStr);
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting reversible rate matrix (revmat) format to %s\n", spacer, modelParams[i].revmatFormat);
                            else
                                MrBayesPrint ("%s   Setting reversible rate matrix (revmat) format to %s for partition %d\n", spacer, modelParams[i].revmatFormat, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid reversible rate matrix (revmat) format \n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set report format of ratemult *************************************************/
        else if (!strcmp(parmName, "Ratemult"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting (ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    tempInt = NO;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        /* we do not know yet if the user will specify variable rates across partitions 
                           so only check that we have more than one partition in the model */
                        if ((activeParts[i] == YES || nApplied == 0) && numCurrentDivisions > 1)
                            {
                            strcpy(modelParams[i].ratemultFormat, tempStr);
                            if (nApplied == 0 && numCurrentDivisions == 1)
                                MrBayesPrint ("%s   Setting rate multiplier (ratemult) format to %s\n", spacer, modelParams[i].ratemultFormat);
                            else
                                MrBayesPrint ("%s   Setting rate multiplier (ratemult) format to %s for partition %d\n", spacer, modelParams[i].ratemultFormat, i+1);
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid rate multiplier (ratemult) format \n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set report format of tree ***************************************************/
        else if (!strcmp(parmName, "Tree"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting (ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    tempInt = NO;
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        strcpy(modelParams[i].treeFormat, tempStr);
                        if (nApplied == 0 && numCurrentDivisions == 1)
                            MrBayesPrint ("%s   Setting tree report format to %s\n", spacer, modelParams[i].treeFormat);
                        else
                            MrBayesPrint ("%s   Setting tree report format to %s for partition %d\n", spacer, modelParams[i].treeFormat, i+1);
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid tree report format \n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set inferancstates ***********************************************************/
        else if (!strcmp(parmName, "Ancstates"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting (ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            strcpy(modelParams[i].inferAncStates,tempStr);
                            if (!strcmp(tempStr,"Yes"))
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Reporting ancestral states (if applicable)\n", spacer);
                                else
                                    MrBayesPrint ("%s   Reporting ancestral states for partition %d (if applicable)\n", spacer, i+1);
                                }
                            else
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Not reporting ancestral states\n", spacer);
                                else
                                    MrBayesPrint ("%s   Not reporting ancestral states for partition %d\n", spacer, i+1);
                                }
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid ancstates option\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set inferSiteRates ***************************************************************/
        else if (!strcmp(parmName, "Siterates"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting (ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            strcpy (modelParams[i].inferSiteRates, tempStr);
                            if (!strcmp(tempStr,"Yes"))
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Reporting site rates (if applicable)\n", spacer);
                                else
                                    MrBayesPrint ("%s   Reporting site rates for partition %d (if applicable)\n", spacer, i+1);
                                }
                            else
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Not reporting site rates\n", spacer);
                                else
                                    MrBayesPrint ("%s   Not reporting site rates for partition %d\n", spacer, i+1);
                                }
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid siterates option\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set inferpossel *************************************************************/
        else if (!strcmp(parmName, "Possel"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting (ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            strcpy (modelParams[i].inferPosSel, tempStr);
                            if (!strcmp(tempStr, "Yes"))
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Reporting positive selection (if applicable)\n", spacer);
                                else
                                    MrBayesPrint ("%s   Reporting positive selection for partition %d (if applicable)\n", spacer, i+1);
                                }
                            else
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Not reporting positive selection\n", spacer);
                                else
                                    MrBayesPrint ("%s   Not reporting positive selection for partition %d\n", spacer, i+1);
                                }
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid possel option\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        /* set inferSiteOmegas *************************************************************/
        else if (!strcmp(parmName, "Siteomega"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting (ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    nApplied = NumActiveParts ();
                    for (i=0; i<numCurrentDivisions; i++)
                        {
                        if (activeParts[i] == YES || nApplied == 0)
                            {
                            strcpy (modelParams[i].inferSiteOmegas, tempStr);
                            if (!strcmp(tempStr, "Yes"))
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Reporting site omega values (if applicable)\n", spacer);
                                else
                                    MrBayesPrint ("%s   Reporting site omega values for partition %d (if applicable)\n", spacer, i+1);
                                }
                            else
                                {
                                if (nApplied == 0 && numCurrentDivisions == 1)
                                    MrBayesPrint ("%s   Not reporting site omega values\n", spacer);
                                else
                                    MrBayesPrint ("%s   Not reporting site omega values for partition %d\n", spacer, i+1);
                                }
                            }
                        }
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid siteomega option\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        else
            {
            return (ERROR);
            }
        }

    return (NO_ERROR);      
}


int DoStartvals (void)
{
    MrBayesPrint ("%s   Successfully set starting values\n", spacer);
    /*
    for (i=0; i<numParams; i++)
        assert (IsTreeConsistent(&params[i], 0, 0) == YES);
    */
    return (NO_ERROR);
}


int DoStartvalsParm (char *parmName, char *tkn)
{
    int                 i, j, k, nMatches, tempInt, treeIndex, chainId, ret;
    MrBFlt              tempFloat, *value, *subValue;
    Tree                *theTree, *usrTree;
    PolyTree            *thePolyTree;
    MrBFlt              minRate, maxRate, clockRate;
    static Param        *param = NULL;
    static MrBFlt       *theValue, theValueMin, theValueMax;
    static int          useSubvalues, useStdStateFreqs, useIntValues, numExpectedValues, nValuesRead, runIndex, chainIndex, foundName, foundDash;
    static char         *temp=NULL, *tempName=NULL;

    if (defMatrix == NO)
        {
        MrBayesPrint ("%s   A matrix must be specified before starting values can be changed\n", spacer);
        return (ERROR);
        }

    if (expecting == Expecting(PARAMETER))
        {
        if (!strcmp(parmName, "Xxxxxxxxxx"))
            {
            /* we expect a parameter name with possible run and chain specification as follows:
               <param_name>(<run>,<chain>)=(<number>,...)   -- apply to run <run> and chain <chain>
               <param_name>(,<chain>)=(<number>,...)        -- apply to chain <chain> for all runs
               <param_name>(<run>,)=(<number>,...)          -- apply to run <run> for all chains

               topology and branch length parameters are specified like
               <param_name>(<run>,<chain>)=<tree_name>|<Newick_tree_spec>

               parameter names will often be followed by partition specifiers like:
               pi{all}
               pinvar{1,4,5}
               so we need to assemble the parameter name from several tokens that are parsed out separately;
               here we receive only the first part (before the left curly, if present)
            */
            
            /* copy to local parameter name */
            SafeStrcpy (&tempName, tkn);
            param = NULL;
            runIndex = chainIndex = -1;
            useSubvalues = NO;
            useIntValues = NO;
            useStdStateFreqs = NO;
            foundComma = foundEqual = foundName = foundDash = NO;
            expecting = Expecting(LEFTCURL) | Expecting(LEFTPAR) |  Expecting(EQUALSIGN);
            }
        else
            return (ERROR);
        }
    else if (expecting == Expecting(ALPHA))
        {
        if (param == NULL)
            {
            /* we are still assembling the parameter name */
            SafeStrcat (&tempName, tkn);
            expecting = Expecting(RIGHTCURL) | Expecting(COMMA) | Expecting(LEFTPAR) | Expecting(EQUALSIGN);
            }
        else
            {
            /* we have a tree name; now find the tree based on name, case insensitive */
            if (GetUserTreeFromName (&treeIndex, tkn) == ERROR || treeIndex == -1)
                {
                MrBayesPrint ("%s   Error in finding user tree\n", spacer);
                return (ERROR);
                }

            /* set the tree parameter */
            for (i=0; i<chainParams.numRuns; i++)
                {
                if (runIndex != -1 && i != runIndex)
                    continue;
                for (j=0; j<chainParams.numChains; j++)
                    {
                    if (chainIndex != -1 && j != chainIndex)
                        continue;
                    chainId = i*chainParams.numChains + j;
                    if (param->paramType != P_POPSIZE)
                        {
                        if (param->paramType == P_TOPOLOGY || param->paramType == P_BRLENS || param->paramType == P_SPECIESTREE)
                            {
                            /* topology or brlens or speciestree params */
                            theTree = GetTree (param, chainId, 0);
                            usrTree = GetTree (param, chainId, 1); /* use as scratch space */
                            }
                        else
                            {
                            /* relaxed clock params */
                            theTree = GetTree (modelSettings[param->relParts[0]].brlens, chainId, 0);
                            usrTree = GetTree (modelSettings[param->relParts[0]].brlens, chainId, 1);
                            }
                        CopyToTreeFromTree (usrTree, theTree);
                        if (param->paramType == P_SPECIESTREE)
                            thePolyTree = AllocatePolyTree(numSpecies);
                        else
                            thePolyTree = AllocatePolyTree (numTaxa);
                        CopyToPolyTreeFromPolyTree (thePolyTree, userTree[treeIndex]);
                        if (param->paramType == P_SPECIESTREE)
                            {
                            ResetIntNodeIndices(thePolyTree);
                            }
                        else
                            {
                            PrunePolyTree (thePolyTree);
                            ResetTipIndices(thePolyTree);
                            }
                        RandResolve (NULL, thePolyTree, &globalSeed, theTree->isRooted);
                        GetPolyDownPass(thePolyTree);
                        ResetIntNodeIndices(thePolyTree);
                        if (param->paramType == P_SPECIESTREE)
                            {
                            ret=CopyToSpeciesTreeFromPolyTree (usrTree, thePolyTree);
                            }
                        else
                            ret=CopyToTreeFromPolyTree (usrTree, thePolyTree);
                        FreePolyTree (thePolyTree);
                        if (ret==ERROR)
                            return ERROR;
                        }
                    else
                        {
                        /* param->paramType == P_POPSIZE */
                        theTree = GetTree (modelSettings[param->relParts[0]].speciesTree, chainId, 0);
                        usrTree = GetTree (modelSettings[param->relParts[0]].speciesTree, chainId, 1);
                        CopyToTreeFromTree (usrTree, theTree);
                        thePolyTree = AllocatePolyTree(numSpecies);
                        CopyToPolyTreeFromPolyTree (thePolyTree, userTree[treeIndex]);
                        ResetIntNodeIndices(thePolyTree);
                        RandResolve (NULL, thePolyTree, &globalSeed, theTree->isRooted);
                        CopyToSpeciesTreeFromPolyTree (usrTree, thePolyTree);
                        FreePolyTree (thePolyTree);
                        }
                    if (param->paramType == P_TOPOLOGY)
                        {
                        if (theTree->checkConstraints == YES && CheckSetConstraints (usrTree) == ERROR)
                            {
                            MrBayesPrint ("%s   Could not set the constraints for topology parameter '%s'\n", spacer, param->name);
                            return (ERROR);
                            }
                        if (ResetTopologyFromTree (theTree, usrTree) == ERROR)
                            {
                            MrBayesPrint ("%s   Could not set the topology parameter '%s'\n", spacer, param->name);
                            return (ERROR);
                            }
                        if (theTree->checkConstraints == YES && CheckSetConstraints (theTree)==ERROR)
                            {
                            MrBayesPrint ("%s   Could not set the constraints for topology parameter '%s'\n", spacer, param->name);
                            return (ERROR);
                            }
                        FillTopologySubParams (param, chainId, 0, &globalSeed);
                        //MrBayesPrint ("%s   Branch lengths and relaxed clock subparameters of a parameter '%s' are reset.\n", spacer, param->name);
                        if (param->paramId == TOPOLOGY_SPECIESTREE)
                            FillSpeciesTreeParams(&globalSeed, chainId, chainId+1);
                        //assert (IsTreeConsistent(param, chainId, 0) == YES);
                        }
                    else if (param->paramType == P_BRLENS)
                        {
                        if (usrTree->allDownPass[0]->length == 0.0 && param->paramId != BRLENS_CLOCK_FOSSIL)
                            {
                            MrBayesPrint ("%s   User tree '%s' does not have branch lengths so it cannot be used in setting parameter '%s'\n", spacer, userTree[treeIndex]->name, param->name);
                            return (ERROR);
                            }
                        if (AreTopologiesSame (theTree, usrTree) == NO)
                            {
                            MrBayesPrint ("%s   Topology of user tree '%s' wrong in setting parameter '%s'\n", spacer, userTree[treeIndex]->name, param->name);
                            return (ERROR);
                            }
                        //assert (IsTreeConsistent(param, chainId, 0) == YES);
                        /* reset node depths to ensure that non-dated tips have node depth 0.0 */
                        /* if (usrTree->isClock == YES)
                            SetNodeDepths(usrTree);  */
                        if (ResetBrlensFromTree (theTree, usrTree) == ERROR)
                            {
                            MrBayesPrint ("%s   Could not set parameter '%s' from user tree '%s'\n", spacer, param->name, userTree[treeIndex]->name);
                            return (ERROR);
                            }
                        if (theTree->isClock == YES && modelParams[theTree->relParts[0]].treeAgePr.prior == fixed)
                            {
                            if (!strcmp(modelParams[theTree->relParts[0]].clockPr,"Uniform")
                                || !strcmp(modelParams[theTree->relParts[0]].clockPr,"Fossilization"))
                                ResetRootHeight (theTree, modelParams[theTree->relParts[0]].treeAgePr.priorParams[0]);
                            }
                        /* the test will find suitable clock rate and ages of nodes in theTree */
                        if (theTree->isClock == YES && IsClockSatisfied (theTree,0.001) == NO)
                            {
                            MrBayesPrint ("%s   Non-calibrated tips are not at the same level after setting up starting tree branch lengthes(%s) from user tree '%s'.\n",
                                          spacer, param->name, userTree[treeIndex]->name);
                            ShowNodes(theTree->root,0,YES);
                            return (ERROR);
                            }
                        if (theTree->isCalibrated == YES && IsCalibratedClockSatisfied (theTree, &minRate,&maxRate, 0.001) == NO)
                            {
                            MrBayesPrint ("%s   Problem setting calibrated tree parameters\n", spacer);
                            return (ERROR);
                            }
                        if (theTree->isCalibrated == YES && !strcmp(modelParams[theTree->relParts[0]].clockRatePr, "Fixed"))
                            {
                            clockRate = modelParams[theTree->relParts[0]].clockRateFix;
                            if ((clockRate < minRate && AreDoublesEqual (clockRate, minRate , 0.001) == NO) || (clockRate > maxRate && AreDoublesEqual (clockRate, maxRate , 0.001) == NO))
                                {
                                MrBayesPrint("%s   Fixed branch lengths do not satisfy fixed clockrate\n", spacer);
                                return (ERROR);
                                }
                            }
                        theTree->fromUserTree=YES;
                        
                        FillBrlensSubParams (param, chainId, 0);
                        //MrBayesPrint ("%s   Rrelaxed clock subparamiters of a parameter '%s' are reset.\n", spacer, param->name);
                        //assert (IsTreeConsistent(param, chainId, 0) == YES);
                        if (param->paramId == BRLENS_CLOCK_SPCOAL)
                            FillSpeciesTreeParams(&globalSeed, chainId, chainId+1);
                        //assert (IsTreeConsistent(param, chainId, 0) == YES);
                        }
                    else if (param->paramType == P_CPPEVENTS || param->paramType == P_TK02BRANCHRATES ||
                             param->paramType == P_IGRBRANCHRATES || param->paramType == P_MIXEDBRCHRATES)
                        {
                        if (theTree->isCalibrated == YES && theTree->fromUserTree == NO)
                            { /* if theTree is not set from user tree then we can not garanty that branch lenghts will stay the same
                                 by the time we start mcmc run because of clockrate adjustment. */
                            MrBayesPrint ("%s    Set starting values for branch lengthes first before setting starting values of relaxed parameters!\n", spacer);
                            return (ERROR);
                            }
                        if (theTree->isCalibrated == NO && IsClockSatisfied (usrTree, 0.001) == NO) // user tree is not calibrated so do not check it if calibration is in place
                            {
                            MrBayesPrint ("%s   Branch lengths of the user tree '%s' do not satisfy clock in setting parameter '%s'\n", spacer, userTree[treeIndex], param->name);
                            ShowNodes(usrTree->root,0,YES);
                            return (ERROR);
                            }
                        if (AreTopologiesSame (theTree, usrTree) == NO)
                            {
                            MrBayesPrint ("%s   Topology of user tree '%s' is wrong in setting parameter '%s'\n", spacer, userTree[treeIndex]->name, param->name);
                            return (ERROR);
                            }
                        if (SetRelaxedClockParam (param, chainId, 0, userTree[treeIndex]) == ERROR)
                            {
                            MrBayesPrint ("%s   Could not set parameter '%s' from user tree '%s'\n", spacer, param->name, userTree[treeIndex]->name);
                            return (ERROR);
                            }
                        //assert (IsTreeConsistent(param, chainId, 0) == YES);
                        }
                    else if (param->paramType == P_POPSIZE)
                        {
                        if (AreTopologiesSame (theTree, usrTree) == NO)
                            {
                            MrBayesPrint ("%s   Topology of user tree '%s' is wrong in setting parameter '%s'\n", spacer, userTree[treeIndex]->name, param->name);
                            return (ERROR);
                            }
                        if (SetPopSizeParam (param, chainId, 0, userTree[treeIndex]) == ERROR)
                            {
                            MrBayesPrint ("%s   Could not set parameter '%s' from user tree '%s'\n", spacer, param->name, userTree[treeIndex]->name);
                            return (ERROR);
                            }
                        }
                    else if (param->paramType == P_SPECIESTREE)
                        {
                        if (IsSpeciesTreeConsistent (usrTree, chainId) == NO)
                            {
                            MrBayesPrint ("%s   User-specified species tree '%s' is inconsistent with gene trees\n", spacer, userTree[treeIndex]->name);
                            return (ERROR);
                            }
                        if (CopyToTreeFromTree (theTree, usrTree) == ERROR)
                            {
                            MrBayesPrint ("%s   Could not set the species tree parameter '%s'\n", spacer, param->name);
                            return (ERROR);
                            }
                        //assert (IsTreeConsistent(param, chainId, 0) == YES);
                        }
                    }
                }
            expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
            }
        }
    else if (expecting == Expecting(LEFTCURL))
        {
        /* we are still assembling the parameter name */
        SafeStrcat (&tempName, tkn);
        expecting = Expecting(NUMBER) | Expecting(ALPHA) | Expecting(LEFTPAR) | Expecting(EQUALSIGN);
        }
    else if (expecting == Expecting(RIGHTCURL))
        {
        /* we are still assembling the parameter name */
        SafeStrcat (&tempName, tkn);
        foundComma = NO; /*! if there was a comma in the partition part, we should reset this variable. Otherwise we can't parse something like A{1,2}(3,4) */
        expecting = Expecting(LEFTPAR) | Expecting(EQUALSIGN);
        }
    else if (expecting == Expecting(LEFTPAR))
        {
        if (foundEqual == NO)
            {
            foundName = YES;    /* we found the name */
            /* we will be reading in run and chain indices */
            expecting = Expecting(NUMBER) | Expecting(COMMA);
            }
        else
            {
            expecting = Expecting(NUMBER);
            expecting |= Expecting(DASH);
            }
        }
    else if (expecting == Expecting(DASH))
        {
        foundDash = YES;
        expecting = Expecting(NUMBER);
        }
    else if (expecting == Expecting(NUMBER))
        {
        if (foundName == NO)
            {
            /* we are still assembling the parameter name */
            SafeStrcat (&tempName, tkn);
            expecting = Expecting(COMMA) | Expecting(LEFTPAR) | Expecting(RIGHTCURL) | Expecting(EQUALSIGN);
            }
        else if (foundEqual == YES)
            {
            theValueMin = param->min;
            theValueMax = param->max;

            /* we are reading in a parameter value */
            if (param->paramType==P_OMEGA && nValuesRead==numExpectedValues && useSubvalues == NO)
                {
                /* continue with subvalues */
                nValuesRead = 0;
                numExpectedValues = param->nSubValues/2;
                useSubvalues = YES;
                theValueMin = ETA;
                theValueMax = 1.0;
                }
            if (param->paramType==P_OMEGA && nValuesRead==numExpectedValues && useSubvalues == NO)
                {
                /* continue with subvalues */
                nValuesRead = 0;
                numExpectedValues = param->nSubValues/2;
                useSubvalues = YES;
                theValueMin = ETA;
                theValueMax = 1.0;
                }
            if (param->nIntValues > 0 && nValuesRead==numExpectedValues && useIntValues == NO)
                {
                /* continue with intValues */
                nValuesRead = 0;
                numExpectedValues = param->nIntValues;
                useIntValues = YES;
                }
            if (param->paramType==P_PI && modelSettings[param->relParts[0]].dataType == STANDARD && param->paramId != SYMPI_EQUAL
                && nValuesRead==numExpectedValues && useStdStateFreqs == NO)
                {
                /* we have read alpha_symdir, continue with multistate char state freqs */
                nValuesRead = 0;
                numExpectedValues = param->nStdStateFreqs;
                if (param->hasBinaryStd == YES)
                    numExpectedValues -= 2 * modelSettings[param->relParts[0]].numBetaCats;
                useStdStateFreqs = YES;
                theValueMin = ETA;
                theValueMax = 1.0;
                }
            nValuesRead++;
            if (nValuesRead > numExpectedValues)
                {
                if (param->paramType == P_OMEGA)
                    MrBayesPrint ("%s   Only %d values were expected for parameter '%s'\n", spacer, param->nValues+param->nSubValues/2, param->name);
                else if (param->nIntValues > 0)   
                    MrBayesPrint ("%s   Only %d values were expected for parameter '%s'\n", spacer, param->nValues+param->nIntValues, param->name);
                else
                    MrBayesPrint ("%s   Only %d values were expected for parameter '%s'\n", spacer, numExpectedValues, param->name);
                return (ERROR);
                }
            if (useIntValues == YES)
                sscanf (tkn, "%d", &tempInt);
            else
                sscanf (tkn, "%lf", &tempFloat);
            if (foundDash == YES)
                {
                if (useIntValues == NO)
                    tempFloat = -tempFloat;
                else
                    tempInt = -tempInt;
                foundDash = NO;
                }
            if (useIntValues == NO && (tempFloat < theValueMin || tempFloat > theValueMax))
                {
                MrBayesPrint ("%s   The value is out of range (min = %lf; max = %lf)\n", spacer, theValueMin, theValueMax);
                return (ERROR);
                }
            for (i=0; i<chainParams.numRuns; i++)
                {
                if (runIndex != -1 && runIndex != i)
                    continue;
                for (j=0; j<chainParams.numChains; j++)
                    {
                    if (chainIndex != -1 && chainIndex != j)
                        continue;
                    if (useIntValues == YES)
                        {
                        GetParamIntVals (param, i*chainParams.numChains+j, 0)[nValuesRead-1] = tempInt;
                        }
                    else
                        {
                        if (useSubvalues == NO && useStdStateFreqs == NO)
                            theValue = GetParamVals (param, i*chainParams.numChains+j, 0);
                        else if (useSubvalues == YES)
                            theValue = GetParamSubVals (param, i*chainParams.numChains+j, 0);
                        else if (useStdStateFreqs == YES)
                            {
                            theValue = GetParamStdStateFreqs (param, i*chainParams.numChains+j, 0);
                            if (param->hasBinaryStd == YES)
                                theValue += 2 * modelSettings[param->relParts[0]].numBetaCats;
                            }
                        else
                            return (ERROR);
                        if (param->paramType == P_CLOCKRATE)
                            {
                            if (UpdateClockRate(tempFloat, i*chainParams.numChains+j) == ERROR) 
                                {
                                return (ERROR);
                                }
                            }
                        theValue[nValuesRead-1] = tempFloat;
                        }
                    }
                }
            expecting = Expecting (COMMA) | Expecting(RIGHTPAR);
            }
        else /* if (foundEqual == NO) */
            {
            sscanf (tkn, "%d", &tempInt);
            if (foundComma == NO)
                {
                if (tempInt <= 0 || tempInt > chainParams.numRuns)
                    {
                    MrBayesPrint ("%s   Run index is out of range (min=1; max=%d)\n", spacer, chainParams.numRuns);
                    return (ERROR);
                    }
                runIndex = tempInt - 1;
                expecting = Expecting(COMMA);
                }
            else
                {
                if (tempInt <= 0 || tempInt > chainParams.numChains)
                    {
                    MrBayesPrint ("%s   Chain index is out of range (min=1; max=%d)\n", spacer, chainParams.numChains);
                    return (ERROR);
                    }
                chainIndex = tempInt - 1;
                foundComma = NO;
                expecting = Expecting(RIGHTPAR);
                }
            }
        }
    else if (expecting == Expecting(COMMA))
        {
        if (foundEqual == YES)
            {
            /* we expect another parameter value */
            expecting = Expecting(NUMBER);
            }
        else /* if (foundEqual == NO) */
            {
            /* we will be reading in chain index, if present */
            foundComma = YES;
            expecting = Expecting(RIGHTPAR) | Expecting(NUMBER); 
            /* if the comma is in a list of partitions (so between { and }) we have to add the comma to the parameter name */
            if (param == NULL && strchr(tempName, '}')==NULL && strchr(tempName, '{')!=NULL) 
              SafeStrcat (&tempName, ",");
            }
        }
    else if (expecting == Expecting(RIGHTPAR))
        {
        if (foundEqual == NO)
            {
            /* this is the end of the run and chain specification */
            expecting = Expecting(EQUALSIGN);
            }
        else /* if (foundEqual == YES) */
            {
            /* this is the end of the parameter values */
            if (nValuesRead != numExpectedValues)
                {
                MrBayesPrint ("%s   Expected %d values but only found %d values for parameter '%s'\n", spacer, numExpectedValues, nValuesRead, param->name);
                return (ERROR);
                }
            /* Post processing needed for some parameters */
            if (param->paramType == P_SHAPE || param->paramType == P_CORREL)
                {
                for (i=0; i<chainParams.numRuns; i++)
                    {
                    if (runIndex != -1 && runIndex != i)
                        continue;
                    for (j=0; j<chainParams.numChains; j++)
                        {
                        if (chainIndex != -1 && chainIndex != j)
                            continue;
                        value = GetParamVals(param,i*chainParams.numChains+j,0);
                        subValue = GetParamSubVals(param,i*chainParams.numChains+j,0);
                        if (param->paramType == P_SHAPE && !strncmp(param->name, "Alpha", 5))
                            {
                            if (DiscreteGamma (subValue, value[0], value[0], param->nSubValues, 0) == ERROR)
                                return (ERROR);
                            }
                        else if (param->paramType == P_SHAPE && !strncmp(param->name, "Sigma", 5))
                            {
                            if( DiscreteLogNormal(subValue, value[0], param->nSubValues, 1) == ERROR)
                                return (ERROR);
                            }
                        else if (param->paramType == P_CORREL)
                            {
                            if (AutodGamma (subValue, value[0], (int)(sqrt(param->nSubValues) + 0.5)) == ERROR)
                                return (ERROR);
                            }
                        }
                    }
                }
            expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
            }
        }
    else if (expecting == Expecting(EQUALSIGN))
        {
        foundEqual = YES;
        foundName = YES;

        /* we now know that the name is complete; try to find the parameter with this name (case insensitive) */
        for (i=0; i<(int)strlen(tempName); i++)
            tempName[i] = tolower(tempName[i]);
        
        /* first check exact matches */
        nMatches = j = 0;
        for (i=0; i<numParams; i++)
            {
            param = &params[i];
            SafeStrcpy (&temp, param->name);
            for (k=0; k<(int)(strlen(temp)); k++)
                temp[k] = tolower(temp[k]);
            if (strcmp(tempName,temp) == 0)
                {
                j = i;
                nMatches++;
                }
            }
        /* now check unambiguous abbreviation matches */
        if (nMatches == 0)
            {
            nMatches = j = 0;
            for (i=0; i<numParams; i++)
                {
                param = &params[i];
                SafeStrcpy (&temp, param->name);
                for (k=0; k<(int)strlen(temp); k++)
                    temp[k] = tolower(temp[k]);
                if (strncmp(tempName,temp,strlen(tempName)) == 0)
                    {
                    j = i;
                    nMatches++;
                    }
                }
            }

        if (nMatches == 0)
            {
            extern char *tokenP;
            MrBayesPrint ("%s   Could not find parameter '%s': ignoring values\n", spacer, tempName);
            while (*tokenP && *tokenP++!=')') {}; 
            expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
            return (*tokenP ? NO_ERROR:ERROR);
            }
        else if (nMatches > 1)
            {
            MrBayesPrint ("%s   Several parameters matched the abbreviated name '%s'\n", spacer, tempName);
            return (ERROR);
            }
            
        param = &params[j];
        if (param->printParam == NO && !(param->paramType == P_TOPOLOGY && strcmp(modelParams[param->relParts[0]].topologyPr,"Fixed")!=0)
                                    && !(param->paramType == P_CPPEVENTS)
                                    && !(param->paramType == P_TK02BRANCHRATES)
                                    && !(param->paramType == P_IGRBRANCHRATES)
                                    && !(param->paramType == P_MIXEDBRCHRATES)
                                    && !(param->paramType == P_POPSIZE && param->nValues > 1))
            {
            MrBayesPrint ("%s   The parameter '%s' is fixed so the starting value cannot be set\n", spacer, param->name);
            return (ERROR);
            }
        if (param->paramType == P_BRLENS || param->paramType == P_TOPOLOGY || param->paramType == P_CPPEVENTS ||
            param->paramType == P_TK02BRANCHRATES || param->paramType == P_IGRBRANCHRATES || param->paramType == P_MIXEDBRCHRATES ||
            param->paramType == P_SPECIESTREE || (param->paramType == P_POPSIZE && param->nValues > 1))
            {
            /* all these parameters are set from a tree */
            expecting = Expecting (ALPHA);
            }
        else
            /* run of the mill character */
            {
            theValueMin = param->min;
            theValueMax = param->max;
            if ((param->paramType == P_PI && modelParams[param->relParts[0]].dataType != STANDARD))
                {
                useSubvalues = YES;
                useIntValues = NO;
                numExpectedValues = param->nSubValues;
                }
            else if (param->nValues == 0 && param->nIntValues > 0)
                {
                useSubvalues = NO;
                useIntValues = YES;
                numExpectedValues = param->nIntValues;
                }
            else if (param->nValues > 0)
                {
                useSubvalues = NO;
                useIntValues = NO;
                numExpectedValues = param->nValues;
                }
            else
                {
                MrBayesPrint ("%s   Not expecting any values for parameter '%s'\n", spacer, param->name);
                return (ERROR);
                }
            nValuesRead = 0;
            expecting = Expecting(LEFTPAR);
            }
        }
    else
        return (ERROR);

    SafeFree ((void **)&temp);
    return (NO_ERROR);
}


int DoUnlink (void)
{
    int         i, j;
    
    MrBayesPrint ("%s   Unlinking\n", spacer);
    
    /* update status of linkTable */
    for (j=0; j<NUM_LINKED; j++)
        {
        for (i=0; i<numCurrentDivisions; i++)
            {
            if (tempLinkUnlink[j][i] == YES)
                {
                linkTable[j][i] = ++linkNum;
                }
            }
        }
    
#   if 0
    for (j=0; j<NUM_LINKED; j++)
        {
        MrBayesPrint ("%s   ", spacer);
        for (i=0; i<numCurrentDivisions; i++)
            MrBayesPrint ("%d", linkTable[j][i]);
        MrBayesPrint ("\n");
        }
#   endif

    /* reinitialize the temporary table */
    for (j=0; j<NUM_LINKED; j++)
        for (i=0; i<numCurrentDivisions; i++)
            tempLinkUnlink[j][i] = NO;

    /* set up parameters and moves */
    if (SetUpAnalysis (&globalSeed) == ERROR)
        return (ERROR);

    return (NO_ERROR);
}


int DoShowMcmcTrees (void)
{
    int         run, chain, chainIndex, i;
    Tree        *t;

    for (run=0; run<chainParams.numRuns; run++)
        {
        for (chain=0; chain<chainParams.numChains; chain++)
            {
            chainIndex = run*chainParams.numChains + chain;
            for (i=0; i<numTrees; i++)
                {
                t = GetTreeFromIndex (i, chainIndex, 0);
                if (t->isRooted == YES)
                    MrBayesPrint ("\n   Tree '%s' [rooted]:\n\n", t->name);
                else
                    MrBayesPrint ("\n   Tree '%s' [unrooted]:\n\n", t->name);
                if (ShowTree (t) == ERROR)
                    return (ERROR);
                else
                    MrBayesPrint ("\n");
                }
            }
        }

    return (NO_ERROR);
}


int DoShowModel (void)
{
    if (defMatrix == NO)
        {
        MrBayesPrint ("%s   A matrix must be specified before the model can be defined\n", spacer);
        return (ERROR);
        }

    if (ShowModel() == ERROR)
        return (ERROR);

    return (NO_ERROR);
}


int DoShowMoves (void)
{
    if (defMatrix == NO)
        {
        MrBayesPrint ("%s   A matrix must be specified before moves can be assigned\n", spacer);
        return (ERROR);
        }

    MrBayesPrint ("%s   Moves that will be used by MCMC sampler (rel. proposal prob. > 0.0):\n\n", spacer);
    if (ShowMoves(YES) == ERROR)
        return (ERROR);

    if (showmovesParams.allavailable == YES)
        {
        MrBayesPrint ("%s   Other available moves (rel. proposal prob. = 0.0):\n\n", spacer);
        if (ShowMoves(NO) == ERROR)
            return (ERROR);
        }
    else
        MrBayesPrint ("%s   Use 'Showmoves allavailable=yes' to see a list of all available moves\n", spacer);

    return (NO_ERROR);
}


int DoShowmovesParm (char *parmName, char *tkn)
{
    char    tempStr[100];
    
    if (expecting == Expecting(PARAMETER))
        {
        expecting = Expecting(EQUALSIGN);
        }
    else
        {
        /* set Allavailable **********************************************************/
        if (!strcmp(parmName, "Allavailable"))
            {
            if (expecting == Expecting(EQUALSIGN))
                expecting = Expecting(ALPHA);
            else if (expecting == Expecting(ALPHA))
                {
                if (IsArgValid(tkn, tempStr) == NO_ERROR)
                    {
                    if (!strcmp(tempStr, "Yes"))
                        showmovesParams.allavailable = YES;
                    else
                        showmovesParams.allavailable = NO;
                    }
                else
                    {
                    MrBayesPrint ("%s   Invalid argument for allavailable\n", spacer);
                    return (ERROR);
                    }
                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
                }
            else
                return (ERROR);
            }
        else
            return (ERROR);

        }
        
    return (NO_ERROR);
}


int DoShowParams (void)
{
    if (defMatrix == NO)
        {
        MrBayesPrint ("%s   A matrix must be specified before model parameters can be shown\n", spacer);
        return (ERROR);
        }

    if (ShowParameters(YES, YES, YES) == ERROR)
        return (ERROR);

    return (NO_ERROR);
}


/*------------------------------------------------------------------------
|
|   FillNormalParams: Allocate and fill in non-tree parameters
|
-------------------------------------------------------------------------*/
int FillNormalParams (RandLong *seed, int fromChain, int toChain)
{
    int         i, j, k, chn, tempInt, *intValue;
    MrBFlt      *bs, *value, *subValue, scaler;
    Tree        *tree;
    Param       *p;
    ModelInfo   *m;
    ModelParams *mp;

    /* fill in values for nontree params for state 0 of chains */
    for (chn=fromChain; chn<toChain; chn++)
        {
        for (k=0; k<numParams; k++)
            {
            p  = &params[k];
            mp = &modelParams[p->relParts[0]];
            m  = &modelSettings[p->relParts[0]];

            /* find model settings and nStates, pInvar, invar cond likes */

            value = GetParamVals (p, chn, 0);
            subValue = GetParamSubVals (p, chn, 0);
            intValue = GetParamIntVals (p, chn, 0);

            if (p->paramType == P_TRATIO)
                {
                /* Fill in tratios **************************************************************************************/
                if (p->paramId == TRATIO_DIR)
                    value[0] = 1.0;
                else if (p->paramId == TRATIO_FIX)
                    value[0] = mp->tRatioFix;
                }
            else if (p->paramType == P_REVMAT)
                {
                /* Fill in revMat ***************************************************************************************/
                /* rates are stored in order, AC or AR first, using the Dirichlet parameterization */
                if (p->paramId == REVMAT_DIR)
                    {
                    for (j=0; j<p->nValues; j++)
                        value[j] = 1.0 / (MrBFlt) (p->nValues);
                    }
                else if (p->paramId == REVMAT_FIX)
                    {
                    scaler = 0.0;
                    if (m->dataType == PROTEIN)
                        {
                        for (j=0; j<190; j++)
                            scaler += (value[j] = mp->aaRevMatFix[j]);
                        for (j=0; j<190; j++)
                            value[j] /= scaler;
                        }
                    else
                        {
                        for (j=0; j<6; j++)
                            scaler += (value[j] = mp->revMatFix[j]);
                        for (j=0; j<6; j++)
                            value[j] /= scaler;
                        }
                    }
                else if (p->paramId == REVMAT_MIX)
                    {
                    for (j=0; j<6; j++)
                        {
                        value[j] = 1.0 / 6.0;
                        intValue[j] = 0;
                        }
                    }
                }
            else if (p->paramType == P_OMEGA)
                {
                /* Fill in omega ****************************************************************************************/
                if (p->nValues == 1)
                    {
                    if (p->paramId == OMEGA_DIR)
                        value[0] = 1.0;
                    else if (p->paramId == OMEGA_FIX)
                        value[0] = mp->omegaFix;
                    }
                else
                    {
                    if (!strcmp(mp->omegaVar, "Ny98"))
                        {
                        if (p->paramId == OMEGA_BUD || p->paramId == OMEGA_BUF || p->paramId == OMEGA_BED ||
                            p->paramId == OMEGA_BEF || p->paramId == OMEGA_BFD || p->paramId == OMEGA_BFF)
                            value[0] = RandomNumber(seed);
                        else if (p->paramId == OMEGA_FUD || p->paramId == OMEGA_FUF || p->paramId == OMEGA_FED ||
                                 p->paramId == OMEGA_FEF || p->paramId == OMEGA_FFD || p->paramId == OMEGA_FFF)
                            value[0] = mp->ny98omega1Fixed;
                        value[1] = 1.0;
                        if (p->paramId == OMEGA_BUD || p->paramId == OMEGA_BUF || p->paramId == OMEGA_FUD ||
                            p->paramId == OMEGA_FUF)
                            value[2] = mp->ny98omega3Uni[0] + RandomNumber(seed) * (mp->ny98omega3Uni[1] - mp->ny98omega3Uni[0]);
                        else if (p->paramId == OMEGA_BED || p->paramId == OMEGA_BEF || p->paramId == OMEGA_FED ||
                                 p->paramId == OMEGA_FEF)
                            value[2] =  (1.0 - (1.0/mp->ny98omega3Exp) * log(RandomNumber(seed)));
                        else
                            value[2] = mp->ny98omega3Fixed;
                        if (p->paramId == OMEGA_BUD || p->paramId == OMEGA_BED || p->paramId == OMEGA_BFD || 
                            p->paramId == OMEGA_FUD || p->paramId == OMEGA_FED || p->paramId == OMEGA_FFD) 
                            {
                            subValue[3] = mp->codonCatDir[0];
                            subValue[4] = mp->codonCatDir[1];
                            subValue[5] = mp->codonCatDir[2];
                            DirichletRandomVariable (&subValue[3], &subValue[0], 3, seed);
                            }
                        else
                            {
                            subValue[0] = mp->codonCatFreqFix[0];
                            subValue[1] = mp->codonCatFreqFix[1];
                            subValue[2] = mp->codonCatFreqFix[2];
                            subValue[3] = 0.0;
                            subValue[4] = 0.0;
                            subValue[5] = 0.0;
                            }
                        }
                    else if (!strcmp(mp->omegaVar, "M3"))
                        {
                        if (p->paramId == OMEGA_FD || p->paramId == OMEGA_FF)
                            {
                            value[0] = mp->m3omegaFixed[0];
                            value[1] = mp->m3omegaFixed[1];
                            value[2] = mp->m3omegaFixed[2];
                            }
                        else
                            {
                            value[0] =  0.1;
                            value[1] =  1.0;
                            value[2] =  3.0;
                            }
                        if (p->paramId == OMEGA_ED || p->paramId == OMEGA_FD) 
                            {
                            subValue[3] = mp->codonCatDir[0];
                            subValue[4] = mp->codonCatDir[1];
                            subValue[5] = mp->codonCatDir[2];
                            DirichletRandomVariable (&subValue[3], &subValue[0], 3, seed);
                            }
                        else
                            {
                            subValue[0] = mp->codonCatFreqFix[0];
                            subValue[1] = mp->codonCatFreqFix[1];
                            subValue[2] = mp->codonCatFreqFix[2];
                            subValue[3] = 0.0;
                            subValue[4] = 0.0;
                            subValue[5] = 0.0;
                            }
                        }
                    else if (!strcmp(mp->omegaVar, "M10"))
                        {
                        if (p->paramId == OMEGA_10UUB || p->paramId == OMEGA_10UEB || p->paramId == OMEGA_10UFB ||
                            p->paramId == OMEGA_10EUB || p->paramId == OMEGA_10EEB || p->paramId == OMEGA_10EFB ||
                            p->paramId == OMEGA_10FUB || p->paramId == OMEGA_10FEB || p->paramId == OMEGA_10FFB) 
                            {
                            subValue[mp->numM10BetaCats + mp->numM10GammaCats + 2] = mp->codonCatDir[0];
                            subValue[mp->numM10BetaCats + mp->numM10GammaCats + 3] = mp->codonCatDir[1];
                            DirichletRandomVariable (&subValue[mp->numM10BetaCats + mp->numM10GammaCats + 2], &subValue[mp->numM10BetaCats + mp->numM10GammaCats + 0], 2, seed);
                            }
                        else
                            {
                            subValue[mp->numM10BetaCats + mp->numM10GammaCats + 0] = mp->codonCatFreqFix[0];
                            subValue[mp->numM10BetaCats + mp->numM10GammaCats + 1] = mp->codonCatFreqFix[1];
                            subValue[mp->numM10BetaCats + mp->numM10GammaCats + 2] = 0.0;
                            subValue[mp->numM10BetaCats + mp->numM10GammaCats + 3] = 0.0;
                            }
                            
                        for (i=0; i<mp->numM10BetaCats; i++)
                            subValue[i] = subValue[mp->numM10BetaCats + mp->numM10GammaCats + 0] / mp->numM10BetaCats;
                        for (i=mp->numM10BetaCats; i<mp->numM10BetaCats+mp->numM10GammaCats; i++)
                            subValue[i] = subValue[mp->numM10BetaCats + mp->numM10GammaCats + 1] / mp->numM10GammaCats;

                        if (p->paramId == OMEGA_10FUB || p->paramId == OMEGA_10FUF || p->paramId == OMEGA_10FEB ||
                            p->paramId == OMEGA_10FEF || p->paramId == OMEGA_10FFB || p->paramId == OMEGA_10FFF)
                            {
                            subValue[mp->numM10BetaCats + mp->numM10GammaCats + 4] = mp->m10betaFix[0];
                            subValue[mp->numM10BetaCats + mp->numM10GammaCats + 5] = mp->m10betaFix[1];
                            }
                        else
                            {
                            subValue[mp->numM10BetaCats + mp->numM10GammaCats + 4] = 1.0;
                            subValue[mp->numM10BetaCats + mp->numM10GammaCats + 5] = 1.0;
                            }

                        if (p->paramId == OMEGA_10UFB || p->paramId == OMEGA_10UFF || p->paramId == OMEGA_10EFB ||
                            p->paramId == OMEGA_10EFF || p->paramId == OMEGA_10FFB || p->paramId == OMEGA_10FFF)
                            {
                            subValue[mp->numM10BetaCats + mp->numM10GammaCats + 6] = mp->m10gammaFix[0];
                            subValue[mp->numM10BetaCats + mp->numM10GammaCats + 7] = mp->m10gammaFix[1];
                            }
                        else
                            {
                            subValue[mp->numM10BetaCats + mp->numM10GammaCats + 6] = 1.0;
                            subValue[mp->numM10BetaCats + mp->numM10GammaCats + 7] = 1.0;
                            }
                            
                        BetaBreaks (subValue[mp->numM10BetaCats + mp->numM10GammaCats + 4], subValue[mp->numM10BetaCats + mp->numM10GammaCats + 5], &value[0], mp->numM10BetaCats);
                        if (DiscreteGamma (&value[mp->numM10BetaCats], subValue[mp->numM10BetaCats + mp->numM10GammaCats + 6],
                                           subValue[mp->numM10BetaCats + mp->numM10GammaCats + 7], mp->numM10GammaCats, 0) == ERROR)
                            return (ERROR);
                        for (i=0; i<mp->numM10GammaCats; i++)
                            value[mp->numM10BetaCats + i] += 1.0;
                        }
                    }
                }
            else if (p->paramType == P_PI)
                {
                /* Fill in state frequencies ****************************************************************************/
                /* note that standard chars are mainly dealt with in ProcessStdChars in mcmc.c */
                if (p->paramId == SYMPI_UNI || p->paramId == SYMPI_UNI_MS)
                    value[0] = 1.0;
                else if (p->paramId == SYMPI_EXP || p->paramId == SYMPI_EXP_MS)
                    value[0] = 1.0;

                else if (p->paramId == SYMPI_FIX || p->paramId == SYMPI_FIX_MS)
                    value[0] = mp->symBetaFix;

                else if (p->paramId == PI_DIR)
                    {
                    if (mp->numDirParams != mp->nStates && mp->numDirParams != 0)
                        {
                        MrBayesPrint ("%s   Mismatch between number of dirichlet parameters (%d) and the number of states (%d)\n", spacer, mp->numDirParams, m->numStates);
                        return ERROR;
                        }

                    /* if user has not set dirichlet parameters, go with default */
                    /* overall variance equals number of states */
                    if (mp->numDirParams == 0)
                        for (i=0; i<mp->nStates; i++)
                            value[i] = mp->stateFreqsDir[i] = 1.0;
                    else
                        for (i=0; i<m->numStates; i++)
                            value[i] = mp->stateFreqsDir[i];

                    /* now fill in subvalues */
                    for (i=0; i<m->numStates; i++)
                        subValue[i] = 1.0 / mp->nStates;
                    }

                else if (p->paramId == PI_USER)
                    {
                    for (i=0; i<m->numStates; i++)
                        subValue[i] =  mp->stateFreqsFix[i];
                    }
                    
                else if (p->paramId == PI_FIXED)
                    {
                    if (!strcmp(mp->aaModelPr, "Fixed"))
                        {
                        if (!strcmp(mp->aaModel, "Jones"))
                            {
                            for (i=0; i<mp->nStates; i++)
                                subValue[i] = jonesPi[i];
                            }
                        else if (!strcmp(mp->aaModel, "Dayhoff"))
                            {
                            for (i=0; i<mp->nStates; i++)
                                subValue[i] = dayhoffPi[i];
                            }
                        else if (!strcmp(mp->aaModel, "Mtrev"))
                            {
                            for (i=0; i<mp->nStates; i++)
                                subValue[i] = mtrev24Pi[i];
                            }
                        else if (!strcmp(mp->aaModel, "Mtmam"))
                            {
                            for (i=0; i<mp->nStates; i++)
                                subValue[i] = mtmamPi[i];
                            }
                        else if (!strcmp(mp->aaModel, "Wag"))
                            {
                            for (i=0; i<mp->nStates; i++)
                                subValue[i] = wagPi[i];
                            }
                        else if (!strcmp(mp->aaModel, "Rtrev"))
                            {
                            for (i=0; i<mp->nStates; i++)
                                subValue[i] = rtrevPi[i];
                            }
                        else if (!strcmp(mp->aaModel, "Cprev"))
                            {
                            for (i=0; i<mp->nStates; i++)
                                subValue[i] = cprevPi[i];
                            }
                        else if (!strcmp(mp->aaModel, "Vt"))
                            {
                            for (i=0; i<mp->nStates; i++)
                                subValue[i] = vtPi[i];
                            }
                        else if (!strcmp(mp->aaModel, "Blosum"))
                            {
                            for (i=0; i<mp->nStates; i++)
                                subValue[i] = blosPi[i];
                            }
                        else if (!strcmp(mp->aaModel, "LG"))
                            {
                            for (i=0; i<mp->nStates; i++)
                                subValue[i] = lgPi[i];
                            }
                        }
                    }

                else if (p->paramId == PI_EMPIRICAL)
                    {
                    if (GetEmpiricalFreqs (p->relParts, p->nRelParts) == ERROR)
                        return (ERROR);
                    for (i=0; i<mp->nStates; i++)
                        subValue[i] = empiricalFreqs[i];
                    }

                else if (p->paramId == PI_EQUAL)
                    {
                    for (i=0; i<mp->nStates; i++)
                        subValue[i] = 1.0 / mp->nStates;
                    }
                }
            else if (p->paramType == P_SHAPE)
                {
                /* Fill in shape values ********************************************************************************/
                /* first get hyperprior */
                if (p->paramId == SHAPE_UNI)
                    {
                    value[0] = 1.0;
                    if (value[0] < mp->shapeUni[0] || value[0] > mp->shapeUni[1])
                        value[0] = mp->shapeUni[0] + (mp->shapeUni[1] - mp->shapeUni[0]) *  0.5;
                    }
                else if (p->paramId == SHAPE_EXP)
                    value[0] = 1.0;  // was 100.0
                else if (p->paramId == SHAPE_FIX)
                    value[0] = mp->shapeFix;
                /* now fill in rates */
                if (!strcmp(mp->ratesModel, "LNorm"))
                    {
                    if (DiscreteLogNormal (subValue, value[0], mp->numGammaCats, 1) == ERROR)
                        return (ERROR);
                    }
                else  /* gamma rate */
                    {
                    if (DiscreteGamma (subValue, value[0], value[0], mp->numGammaCats, 0) == ERROR)
                        return (ERROR);
                    }
                }
            else if (p->paramType == P_PINVAR)
                {
                /* Fill in pInvar ***************************************************************************************/
                if (p->paramId == PINVAR_UNI)
                    value[0] = 0.0;

                else if (p->paramId == PINVAR_FIX)
                    value[0] =  mp->pInvarFix;
                }
            else if (p->paramType == P_CORREL)
                {
                /* Fill in correlation parameter of adgamma model *******************************************************/
                if (p->paramId == CORREL_UNI)
                    value[0] = 0.0;

                else if (p->paramId == CORREL_FIX)
                    value[0] =  mp->corrFix;
                
                /* Fill in correlation matrices */
                AutodGamma (subValue, value[0], mp->numGammaCats);
                }
            else if (p->paramType == P_SWITCH)
                {
                /* Fill in switchRates for covarion model ***************************************************************/
                for (j=0; j<2; j++)
                    {
                    if (p->paramId == SWITCH_UNI)
                        value[j] = RandomNumber(seed) * (mp->covswitchUni[1] - mp->covswitchUni[0]) + mp->covswitchUni[0];

                    else if (p->paramId == SWITCH_EXP)
                        value[j] = -(1.0/mp->covswitchExp) * log(RandomNumber(seed));

                    else if (p->paramId == SWITCH_FIX)
                        value[j] = mp->covswitchFix[j];
                    }
                }
            else if (p->paramType == P_RATEMULT)
                {
                /* Fill in division rates *****************************************************************************/
                for (j=0; j<p->nValues; j++)
                    {
                    value[j] = 1.0;
                    /* fill in more info about the divisions if this is a true rate multiplier
                       and not a base rate */
                    if (p->nSubValues > 0)
                        {
                        /* num uncompressed chars */
                        subValue[j] = (modelSettings[p->relParts[j]].numUncompressedChars);
                        /* Dirichlet parameters */
                        subValue[p->nValues + j] = modelParams[p->relParts[j]].ratePrDir;
                        }
                    }
                }
            else if (p->paramType == P_GENETREERATE)
                {
                /* Fill in division rates *****************************************************************************/
                for (j=0; j<p->nValues; j++)
                    {
                    value[j] = 1.0;
                    /* Dirichlet parameters fixed to 1.0 for now; ignored if the rate is fixed */
                    subValue[p->nValues + j] = 1.0;
                    /* Get number of uncompressed chars from tree */
                    tree = GetTreeFromIndex(j, 0, 0);
                    subValue[j] = 0.0;
                    for (i=0; i<tree->nRelParts; i++)  /* num uncompressed chars */
                        subValue[j] += modelSettings[tree->relParts[i]].numUncompressedChars;
                    }
                }
            else if (p->paramType == P_SPECRATE)
                {
                /* Fill in speciation rates *****************************************************************************/
                for (j=0; j<p->nValues; j++)
                    {
                    if (p->paramId == SPECRATE_FIX)
                        value[j] = mp->speciationFix;
                    else
                        value[j] = 1.0;
                    }
                }
            else if (p->paramType == P_EXTRATE)
                {
                /* Fill in extinction rates *****************************************************************************/
                for (j=0; j<p->nValues; j++)
                    {
                    if (p->paramId == EXTRATE_FIX)
                        value[j] = mp->extinctionFix;
                    else
                        value[j] = 0.5;
                    }
                }
            else if (p->paramType == P_FOSLRATE)
                {
                /* Fill in fossilization rates */
                for (j=0; j<p->nValues; j++)
                    {
                    if (p->paramId == FOSLRATE_FIX)
                        value[j] = mp->fossilizationFix;
                    else
                        value[j] = 0.5;
                    }
                }
            else if (p->paramType == P_GROWTH)
                {
                /* Fill in growth rate ****************************************************************************************/
                if (p->paramId == GROWTH_FIX)
                    value[0] = mp->growthFix;
                else
                    value[0] = 1.0;
                }
            else if (p->paramType == P_POPSIZE)
                {
                /* Fill in population size ****************************************************************************************/
                for (j=0; j<p->nValues; j++)
                    {
                    if (p->paramId == POPSIZE_UNI)
                        value[j] = RandomNumber(seed) * (mp->popSizeUni[1] - mp->popSizeUni[0]) + mp->popSizeUni[0];
                    else if (p->paramId == POPSIZE_LOGNORMAL)
                        value[j] = exp(mp->popSizeLognormal[0]);
                    else if (p->paramId == POPSIZE_NORMAL)
                        value[j] = mp->popSizeNormal[0];
                    else if (p->paramId == POPSIZE_GAMMA)
                        value[j] = mp->popSizeGamma[0] / mp->popSizeGamma[1];
                    else if (p->paramId == POPSIZE_FIX)
                        value[j] = mp->popSizeFix;
                    }
                }
            else if (p->paramType == P_AAMODEL)
                {
                /* Fill in theta ****************************************************************************************/
                if (p->paramId == AAMODEL_MIX)
                    {
                    /* amino acid model ID's
                        AAMODEL_POISSON         0
                        AAMODEL_JONES           1
                        AAMODEL_DAY             2
                        AAMODEL_MTREV           3
                        AAMODEL_MTMAM           4
                        AAMODEL_WAG             5
                        AAMODEL_RTREV           6 
                        AAMODEL_CPREV           7 
                        AAMODEL_VT              8
                        AAMODEL_BLOSUM          9 */

                    /* set the amino acid model  (the meaning of the numbers is defined) */
                    tempInt = (int)(RandomNumber(seed) * 10);
                    value[0] = tempInt;
                    
                    /* we need to make certain that the aa frequencies are filled in correctly */
                    bs = GetParamSubVals (m->stateFreq, chn, 0);
                    if (tempInt == AAMODEL_POISSON)
                        {
                        for (i=0; i<mp->nStates; i++)
                            bs[i] =  (1.0 / 20.0);
                        }
                    else if (tempInt == AAMODEL_JONES)
                        {
                        for (i=0; i<mp->nStates; i++)
                            bs[i] = jonesPi[i];
                        }
                    else if (tempInt == AAMODEL_DAY)
                        {
                        for (i=0; i<mp->nStates; i++)
                            bs[i] = dayhoffPi[i];
                        }
                    else if (tempInt == AAMODEL_MTREV)
                        {
                        for (i=0; i<mp->nStates; i++)
                            bs[i] = mtrev24Pi[i];
                        }
                    else if (tempInt == AAMODEL_MTMAM)
                        {
                        for (i=0; i<mp->nStates; i++)
                            bs[i] = mtmamPi[i];
                        }
                    else if (tempInt == AAMODEL_WAG)
                        {
                        for (i=0; i<mp->nStates; i++)
                            bs[i] = wagPi[i];
                        }
                    else if (tempInt == AAMODEL_RTREV)
                        {
                        for (i=0; i<mp->nStates; i++)
                            bs[i] = rtrevPi[i];
                        }
                    else if (tempInt == AAMODEL_CPREV)
                        {
                        for (i=0; i<mp->nStates; i++)
                            bs[i] = cprevPi[i];
                        }
                    else if (tempInt == AAMODEL_VT)
                        {
                        for (i=0; i<mp->nStates; i++)
                            bs[i] = vtPi[i];
                        }
                    else if (tempInt == AAMODEL_BLOSUM)
                        {
                        for (i=0; i<mp->nStates; i++)
                            bs[i] = blosPi[i];
                        }
                        
                    for (i=0; i<p->nSubValues; i++)
                        {
                        subValue[i] = mp->aaModelPrProbs[i];
                        }
                    }
                }
            else if (p->paramType == P_CPPRATE)
                {
                /* Fill in lambda (cpp rate) ********************************************************************************************/
                if (p->paramId == CPPRATE_EXP)
                    value[0] = -(1.0/mp->cppRateExp) * log(RandomNumber(seed));
                else if (p->paramId == CPPRATE_FIX)
                    value[0] = mp->cppRateFix;
                }
            else if (p->paramType == P_CPPMULTDEV)
                {
                /* Fill in log standard deviation (for relaxed clock rate multiplier) ***********************************************************/
                if (p->paramId == CPPMULTDEV_FIX)
                    value[0] = mp->cppMultDevFix;
                }
            else if (p->paramType == P_CPPEVENTS)
                {
                /* We fill in these when we fill in tree params **************************************************************************/
                }
            else if (p->paramType == P_TK02VAR)
                {
                /* Fill in variance of relaxed clock lognormal **************************************************************************/
                if (p->paramId == TK02VAR_UNI)
                    value[0] = RandomNumber(seed) * (mp->tk02varUni[1] - mp->tk02varUni[0]) + mp->tk02varUni[0];
                else if (p->paramId == TK02VAR_EXP)
                    value[0] = 2.0/(mp->tk02varExp);
                else if (p->paramId == TK02VAR_FIX)
                    value[0] = mp->tk02varFix;
                }
            else if (p->paramType == P_TK02BRANCHRATES)
                {
                /* We fill in these when we fill in tree params **************************************************************************/
                }
            else if (p->paramType == P_IGRVAR)
                {
                /* Fill in variance of relaxed clock lognormal **************************************************************************/
                if (p->paramId == IGRVAR_UNI)
                    value[0] = RandomNumber(seed) * (mp->igrvarUni[1] - mp->igrvarUni[0]) + mp->igrvarUni[0];
                else if (p->paramId == IGRVAR_EXP)
                    value[0] = 1.0/(mp->igrvarExp);
                else if (p->paramId == IGRVAR_FIX)
                    value[0] = mp->igrvarFix;
                }
            else if (p->paramType == P_IGRBRANCHRATES)
                {
                /* We fill in these when we fill in tree params **************************************************************************/
                }
            else if (p->paramType == P_MIXEDVAR)
                {
                /* Fill in variance of mixed relaxed clock **************************************************************************/
                if (p->paramId == MIXEDVAR_UNI)
                    value[0] = RandomNumber(seed) * (mp->mixedvarUni[1] - mp->mixedvarUni[0]) + mp->mixedvarUni[0];
                else if (p->paramId == MIXEDVAR_EXP)
                    value[0] = 1.0/(mp->mixedvarExp);
                else if (p->paramId == MIXEDVAR_FIX)
                    value[0] = mp->mixedvarFix;
                }
            else if (p->paramType == P_MIXEDBRCHRATES)
                {
                /* initialize the mixed relaxed clock model to TK02 or IGR */
                intValue[0] = (RandomNumber(seed) <0.5) ? RCL_TK02 : RCL_IGR;
                /* We fill in the rest when we fill in tree params **************************************************************************/
                }
            else if (p->paramType == P_CLOCKRATE)
                {
                /* Fill in base rate of molecular clock **************************************************************************/
                if (p->paramId == CLOCKRATE_FIX)
                    value[0] = mp->clockRateFix;
                else if (p->paramId == CLOCKRATE_NORMAL)
                    value[0] = mp->clockRateNormal[0];
                else if (p->paramId == CLOCKRATE_LOGNORMAL)
                    value[0] = exp(mp->clockRateLognormal[0]);
                else if (p->paramId == CLOCKRATE_EXP)
                    value[0] = 1.0/(mp->clockRateExp);
                else if (p->paramId == CLOCKRATE_GAMMA)
                    value[0] = mp->clockRateGamma[0]/mp->clockRateGamma[1];
                }
            }   /* next param */
        }   /* next chain */

    return NO_ERROR;
}

    
int FillRelPartsString (Param *p, char **relPartString)
{
    int         i, n, filledString;
    char        *tempStr;
    int             tempStrSize=50;

    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
    if (!tempStr)
        {
        MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
        return (ERROR);
        }

    if (numCurrentDivisions == 1)
        {
        filledString = NO;
        SafeStrcpy (relPartString, "");
        }
    else
        {
        filledString = YES;
        if (p->nRelParts == numCurrentDivisions)
            {
            SafeStrcpy (relPartString, "{all}");
            }
        else
            {
            SafeStrcpy (relPartString, "{");
            for (i=n=0; i<p->nRelParts; i++)
                {
                n++;
                SafeSprintf (&tempStr, &tempStrSize, "%d", p->relParts[i] + 1);
                SafeStrcat (relPartString, tempStr);
                if (n < p->nRelParts)
                    SafeStrcat (relPartString, ",");
                }
            SafeStrcat (relPartString, "}");
            }
        }
    free (tempStr);
    return (filledString);
}


/*--------------------------------------------------------------
 |
 |  FillStdStateFreqs: fills stationary frequencies for standard data divisions of chains  in range [chfrom, chto)
 |
 ---------------------------------------------------------------*/
void FillStdStateFreqs (int chfrom, int chto, RandLong *seed)
{
    int     chn, n, i, j, k, b, c, nb, index;
    MrBFlt  *subValue, sum, symDir[10];
    Param   *p;
    
    for (chn=chfrom; chn<chto; chn++)
        {
        for (k=0; k<numParams; k++)
            {
            p = &params[k];
            if (p->paramType != P_PI || modelParams[p->relParts[0]].dataType != STANDARD)
                continue;
            subValue = GetParamStdStateFreqs (p, chn, 0);
            if (p->paramId == SYMPI_EQUAL)
                {
                for (n=index=0; n<9; n++)
                    {
                    for (i=0; i<p->nRelParts; i++)
                        if (modelSettings[p->relParts[i]].isTiNeeded[n] == YES)
                            break;
                    if (i < p->nRelParts)
                        {
                        for (j=0; j<(n+2); j++)
                            {
                            subValue[index++] = (1.0 / (n + 2));
                            }
                        }
                    }
                for (n=9; n<13; n++)
                    {
                    for (i=0; i<p->nRelParts; i++)
                        if (modelSettings[p->relParts[i]].isTiNeeded[n] == YES)
                            break;
                    if (i < p->nRelParts)
                        {
                        for (j=0; j<(n-6); j++)
                            {
                            subValue[index++] = (1.0 / (n - 6));
                            }
                        }
                    }
                }
            
            /* Deal with transition asymmetry for standard characters */
            /* First, fill in stationary frequencies for beta categories if needed; */
            /* discard category frequencies (assume equal) */
            if (p->paramId == SYMPI_FIX || p->paramId == SYMPI_UNI || p->paramId == SYMPI_EXP ||
                p->paramId == SYMPI_FIX_MS || p->paramId == SYMPI_UNI_MS || p->paramId == SYMPI_EXP_MS)
                {
                if (p->hasBinaryStd == YES)
                    {
                    nb=modelParams[p->relParts[0]].numBetaCats;
                    BetaBreaks (p->values[0], p->values[0], subValue, nb);
                    b = 2*nb;
                    for (i=b-2; i>0; i-=2)
                        {
                        subValue[i] = subValue[i/2];
                        }
                    for (i=1; i<b; i+=2)
                        {
                        subValue[i] = (1.0 - subValue[i-1]);
                        }
                    subValue += (2 * nb);
                    }
                
                /* Then fill in state frequencies for multistate chars, one set for each */
                for (i=0; i<10; i++)
                    symDir[i] = p->values[0];
                
                for (c=0; c<p->nSympi; c++)
                    {
                    /* now fill in subvalues */
                    DirichletRandomVariable (symDir, subValue, p->sympinStates[c], seed);
                    sum = 0.0;
                    for (i=0; i<p->sympinStates[c]; i++)
                        {
                        if (subValue[i] < 0.0001)
                            subValue[i] = 0.0001;
                        sum += subValue[i];
                        }
                    for (i=0; i<modelParams[p->relParts[0]].nStates; i++)
                        subValue[i] /= sum;
                    subValue += p->sympinStates[c];
                    }
                }
            }   /* next parameter */
        }   /* next chain */
}


/* FillTopologySubParams: Fill subparams (brlens) for a topology */
int FillTopologySubParams (Param *param, int chn, int state, RandLong *seed)
{
    int         i,returnVal;
    Tree        *tree, *tree1;
    Param       *q;
    MrBFlt      clockRate;
    PolyTree    *sourceTree;
    MrBFlt      minRate,maxRate;

    tree = GetTree (param, chn, state);
    
    for (i=1; i<param->nSubParams; i++)
        {
        q = param->subParams[i];
        tree1 = GetTree (q, chn, state);
        if (CopyToTreeFromTree(tree1, tree) == ERROR)
            return (ERROR);
        }
    for (i=0; i<param->nSubParams; i++)
        {
        q = param->subParams[i];
        tree = GetTree (q, chn, state);
        if (q->paramId == BRLENS_FIXED || q->paramId == BRLENS_CLOCK_FIXED)
            {
            if (param->paramId == TOPOLOGY_NCL_FIXED ||
                param->paramId == TOPOLOGY_NCL_FIXED_HOMO ||
                param->paramId == TOPOLOGY_NCL_FIXED_HETERO ||
                param->paramId == TOPOLOGY_CL_FIXED  ||
                param->paramId == TOPOLOGY_RCL_FIXED ||
                param->paramId == TOPOLOGY_CCL_FIXED ||
                param->paramId == TOPOLOGY_RCCL_FIXED||
                param->paramId == TOPOLOGY_FIXED)
                {
                sourceTree = AllocatePolyTree(numTaxa);
                CopyToPolyTreeFromPolyTree (sourceTree, userTree[modelParams[q->relParts[0]].brlensFix]);
                PrunePolyTree (sourceTree);
                ResetTipIndices (sourceTree);
                ResetIntNodeIndices (sourceTree);
                if (tree->isRooted != sourceTree->isRooted)
                    {
                    MrBayesPrint("%s   Cannot set fixed branch lengths because of mismatch in rootedness", spacer);
                    FreePolyTree (sourceTree);
                    return (ERROR);
                    }
                if (CopyToTreeFromPolyTree(tree,sourceTree) == ERROR)
                    {
                    MrBayesPrint("%s   Problem setting fixed branch lengths", spacer);
                    FreePolyTree (sourceTree);
                    return (ERROR);
                    }
                FreePolyTree (sourceTree);
                if (tree->isClock == YES && IsClockSatisfied(tree, 0.0001) == NO)
                    {
                    MrBayesPrint("%s   Fixed branch lengths do not satisfy clock", spacer);
                    return (ERROR);
                    }
                if (tree->isCalibrated == YES && IsCalibratedClockSatisfied(tree,&minRate,&maxRate, 0.0001) == NO)
                    {
                    MrBayesPrint("%s   Fixed branch lengths do not satisfy calibrations", spacer);
                    return (ERROR);
                    }
                if (tree->isCalibrated == YES && !strcmp(modelParams[tree->relParts[0]].clockRatePr, "Fixed"))
                    {
                    clockRate = modelParams[tree->relParts[0]].clockRateFix;
                    if ((clockRate < minRate && AreDoublesEqual (clockRate, minRate , 0.0001) == NO) ||
                        (clockRate > maxRate && AreDoublesEqual (clockRate, maxRate , 0.0001) == NO))
                        {
                        MrBayesPrint("%s   Fixed branch lengths do not satisfy fixed clockrate", spacer);
                        return (ERROR);
                        }
                    }

                tree->fromUserTree=YES;
                returnVal = NO_ERROR;
                }
            else
                {
                MrBayesPrint("%s   Fixed branch lengths can only be used for a fixed topology\n", spacer);
                return (ERROR);
                }
            }
        else if (tree->isCalibrated == YES || (tree->isClock == YES && (!strcmp(modelParams[tree->relParts[0]].clockPr,"Uniform") ||
                                                                        !strcmp(modelParams[tree->relParts[0]].clockPr,"Fossilization"))))
            {
            assert (tree->isClock == YES);
            clockRate = *GetParamVals(modelSettings[tree->relParts[0]].clockRate, chn, state);
            returnVal = InitCalibratedBrlens (tree, clockRate, seed);
            if (IsClockSatisfied (tree,0.0001) == NO)
                {
                MrBayesPrint ("%s   Branch lengths of the tree does not satisfy clock\n",  spacer);
                return (ERROR);
                }
            tree->fromUserTree=NO;
            }
        else if (tree->isClock == YES)
            returnVal = InitClockBrlens (tree);
        else
            returnVal = InitBrlens (tree, 0.02);

        if (returnVal == ERROR)
            return (ERROR);

        if (FillBrlensSubParams (q, chn, state) == ERROR)
            return (ERROR);
        }

    return (NO_ERROR);
}


/* FillBrlensSubParams: Fill any relaxed clock subparams of a brlens param */
int FillBrlensSubParams (Param *param, int chn, int state)
{
    int         i, j, *nEvents;
    MrBFlt      *brlen, *branchRate, **position, **rateMult;
    Tree        *tree;
    TreeNode    *p;
    Param       *q;

    tree = GetTree (param, chn, state);
    
    for (i=0; i<param->nSubParams; i++)
        {
        q = param->subParams[i];
        if (q->paramType == P_CPPEVENTS)
            {
            nEvents = q->nEvents[2*chn+state];
            position = q->position[2*chn+state];
            rateMult = q->rateMult[2*chn+state];
            brlen = GetParamSubVals (q, chn, state);
            for (j=0; j<tree->nNodes-1; j++)
                {
                p = tree->allDownPass[j];
                if (nEvents[p->index] != 0)
                    {
                    free (position[p->index]);
                    position[p->index] = NULL;
                    free (rateMult[p->index]);
                    rateMult[p->index] = NULL;
                    }
                nEvents[p->index] = 0;
                assert (j==tree->nNodes-2 || fabs(p->length - (p->anc->nodeDepth - p->nodeDepth)) < 0.000001);
                brlen[p->index] = p->length;
                }
            }
        else if (q->paramType == P_TK02BRANCHRATES || q->paramType == P_IGRBRANCHRATES || q->paramType == P_MIXEDBRCHRATES)
            {
            branchRate = GetParamVals (q, chn, state);
            brlen = GetParamSubVals (q, chn, state);
            for (j=0; j<tree->nNodes-1; j++)
                {
                p = tree->allDownPass[j];
                assert (j==tree->nNodes-2 || fabs(p->length - (p->anc->nodeDepth - p->nodeDepth)) < 0.000001);
                branchRate[p->index] = 1.0;
                brlen[p->index] = p->length;
                }
            }
        }

    return (NO_ERROR);
}


/* Note: In PruneConstraintPartitions() we can not relay on specific rootnes of a tree since different partitions
   may theoreticly have different clock models, while constraints apply to all partitions/trees */
int PruneConstraintPartitions()
{
    int             i, j, constraintId, nLongsNeeded;
    
    nLongsNeeded = (numLocalTaxa - 1) / nBitsInALong + 1;

    for (constraintId=0; constraintId<numDefinedConstraints; constraintId++)
        {
        definedConstraintPruned[constraintId] = (BitsLong *) SafeRealloc ((void *)definedConstraintPruned[constraintId], nLongsNeeded*sizeof(BitsLong));
        if (!definedConstraintPruned[constraintId])
            {
            MrBayesPrint ("%s   Problems allocating constraintPartition in PruneConstraintPartitions", spacer);
            return (ERROR);
            }

        /* initialize bits in partition to add; get rid of deleted taxa in the process */
        ClearBits(definedConstraintPruned[constraintId], nLongsNeeded);
        for (i=j=0; i<numTaxa; i++)
            {
            if (taxaInfo[i].isDeleted == YES)
                continue;
            if (IsBitSet(i, definedConstraint[constraintId]) == YES)
                SetBit(j, definedConstraintPruned[constraintId]);
            j++;
            }
        assert (j == numLocalTaxa);

        if (definedConstraintsType[constraintId] == PARTIAL)
            {
            definedConstraintTwoPruned[constraintId] = (BitsLong *) SafeRealloc ((void *)definedConstraintTwoPruned[constraintId], nLongsNeeded*sizeof(BitsLong));
            if (!definedConstraintTwoPruned[constraintId])
                {
                MrBayesPrint ("%s   Problems allocating constraintPartition in PruneConstraintPartitions", spacer);
                return (ERROR);
                }

            /* initialize bits in partition to add; get rid of deleted taxa in the process */
            ClearBits(definedConstraintTwoPruned[constraintId], nLongsNeeded);
            for (i=j=0; i<numTaxa; i++)
                {
                if (taxaInfo[i].isDeleted == YES)
                    continue;
                if (IsBitSet(i, definedConstraintTwo[constraintId]) == YES)
                    SetBit(j, definedConstraintTwoPruned[constraintId]);
                j++;
                }
            assert (j == numLocalTaxa);
            }
        else if (definedConstraintsType[constraintId] == NEGATIVE || (definedConstraintsType[constraintId] == HARD))
            {
            /* Here we create definedConstraintTwoPruned[constraintId] which is complemente of definedConstraintPruned[constraintId] */
            definedConstraintTwoPruned[constraintId] = (BitsLong *) SafeRealloc ((void *)definedConstraintTwoPruned[constraintId], nLongsNeeded*sizeof(BitsLong));
            if (!definedConstraintTwoPruned[constraintId])
                {
                MrBayesPrint ("%s   Problems allocating constraintPartition in PruneConstraintPartitions", spacer);
                return (ERROR);
                }

            /* initialize bits in partition to add; get rid of deleted taxa in the process */
            ClearBits(definedConstraintTwoPruned[constraintId], nLongsNeeded);
            for (i=j=0; i<numTaxa; i++)
                {
                if (taxaInfo[i].isDeleted == YES)
                    continue;
                if (IsBitSet(i, definedConstraint[constraintId]) == NO)
                    SetBit(j, definedConstraintTwoPruned[constraintId]);
                j++;
                }
            assert (j == numLocalTaxa);         
            }
    }
    
    return NO_ERROR;
}


int DoesTreeSatisfyConstraints(Tree *t)
{
    int         i, k, numTaxa, nLongsNeeded;
    TreeNode    *p;
    int         CheckFirst, CheckSecond; /*Flag indicating wheather corresponding set(first/second) of partial constraint has to be checked*/
#   if defined (DEBUG_CONSTRAINTS)
    int         locks_count=0;
#   endif

    if (t->checkConstraints == NO)
        return YES;
    /* get some handy numbers */
    numTaxa = t->nNodes - t->nIntNodes - (t->isRooted == YES ? 1 : 0);
    nLongsNeeded = (numTaxa - 1) / nBitsInALong + 1;

    if (t->bitsets == NULL)
        {
        AllocateTreePartitions(t);
        }
    else
        {
        ResetTreePartitions(t);  /*Inefficient function, rewrite faster version*/
        }
#   if defined (DEBUG_CONSTRAINTS)
    for (i=0; i<t->nIntNodes; i++)
        {
        p = t->intDownPass[i];
        if (p->isLocked == YES)
            {
            if (IsUnionEqThird (definedConstraintPruned[p->lockID], definedConstraintPruned[p->lockID], p->partition, nLongsNeeded) == NO && IsUnionEqThird (definedConstraintTwoPruned[p->lockID], definedConstraintTwoPruned[p->lockID], p->partition, nLongsNeeded) == NO)
                {
                printf ("DEBUG ERROR: Locked node does not represent right partition. \n");
                return ABORT;
                }
            else
                {
                locks_count++;
                }
            }
        }

    if (locks_count != t->nLocks)
        {
        printf ("DEBUG ERROR: locks_count:%d should be locks_count:%d\n", locks_count, t->nLocks);
        return ABORT;
        }
#   endif

    for (k=0; k<numDefinedConstraints; k++)
        {
#   if defined (DEBUG_CONSTRAINTS)
        if (t->constraints[k] == YES && definedConstraintsType[k] == HARD)
            {
            if (t->isRooted == YES)
                {
                CheckFirst = YES;
                CheckSecond = NO; 
                }
            else
                {
                /*exactly one of next two will be YES*/
                CheckFirst = IsBitSet(localOutGroup, definedConstraintPruned[k])==YES ? NO : YES;
                CheckSecond = IsBitSet(localOutGroup, definedConstraintTwoPruned[k])==YES ? NO : YES;
                assert ((CheckFirst^CheckSecond)==1);
                }

            for (i=0; i<t->nIntNodes; i++)
                {
                p = t->intDownPass[i];
                if (p->anc != NULL)
                    {
                    if (CheckFirst==YES &&  IsPartNested(definedConstraintPruned[k], p->partition, nLongsNeeded) && IsPartNested(p->partition,definedConstraintPruned[k], nLongsNeeded))
                        break;
                    if (CheckSecond==YES &&  IsPartNested(definedConstraintTwoPruned[k], p->partition, nLongsNeeded) && IsPartNested(p->partition, definedConstraintTwoPruned[k], nLongsNeeded))
                        break;
                    }
                }

            if (i==t->nIntNodes)
                {
                printf ("DEBUG ERROR: Hard constraint is not satisfied. \n");
                return ABORT;
                //assert (0);
                }
            }
#   endif

        if (t->constraints[k] == NO || definedConstraintsType[k] == HARD)
            continue;

        if (definedConstraintsType[k] == PARTIAL)
            {
            /* alternative way
            if (t->isRooted == NO && !IsBitSet(localOutGroup, definedConstraintPruned[k]))
                {
                m = FirstTaxonInPartition (constraintPartition, nLongsNeeded);
                for (i=0; t->nodes[i].index != m; i++)
                    ;
                p = &t->nodes[i];

                p=p->anc;
                while (!IsPartNested(definedConstraintPruned[k], p->partition, nLongsNeeded))
                    p=p->anc;

                if (IsSectionEmpty(definedConstraintTwoPruned[k], p->partition, nLongsNeeded))
                    continue;
                }
            */
            if (t->isRooted == YES)
                {
                CheckFirst = YES;
                CheckSecond = NO; /* In rooted case even if we have a node with partition fully containing second set and not containing the first set it would not satisfy the constraint */
                }
            else
                {
                if (NumBits(definedConstraintPruned[k], nLongsNeeded) == 1 || NumBits(definedConstraintTwoPruned[k], nLongsNeeded) == 1)
                    continue;
                /*one or two of the next two statments will be YES*/
                CheckFirst = IsBitSet(localOutGroup, definedConstraintPruned[k])==YES ? NO : YES;
                CheckSecond = IsBitSet(localOutGroup, definedConstraintTwoPruned[k])==YES ? NO : YES;
                assert ((CheckFirst|CheckSecond)==1);
                }
            for (i=0; i<t->nIntNodes; i++)
                {
                p = t->intDownPass[i];
                if (p->anc != NULL)
                    { 
                    if (CheckFirst== YES && IsPartNested(definedConstraintPruned[k], p->partition, nLongsNeeded) && IsSectionEmpty(definedConstraintTwoPruned[k], p->partition, nLongsNeeded))
                        break;
                    if (CheckSecond==YES && IsPartNested(definedConstraintTwoPruned[k], p->partition, nLongsNeeded) && IsSectionEmpty(definedConstraintPruned[k], p->partition, nLongsNeeded))
                        break;
                    }
                }
            if (i==t->nIntNodes)
                return NO;
            }
        else
            {
            assert (definedConstraintsType[k] == NEGATIVE);
            if (t->isRooted == YES)
                {
                CheckFirst = YES;
                CheckSecond = NO; 
                }
            else
                {
                /*exactly one of next two will be YES*/
                CheckFirst = IsBitSet(localOutGroup, definedConstraintPruned[k])==YES ? NO : YES;
                CheckSecond = IsBitSet(localOutGroup, definedConstraintTwoPruned[k])==YES ? NO : YES;
                assert ((CheckFirst^CheckSecond)==1);
                }

            for (i=0; i<t->nIntNodes; i++)
                {
                p = t->intDownPass[i];
                if (p->anc != NULL)
                    {
                    if (CheckFirst==YES && AreBitfieldsEqual(definedConstraintPruned[k], p->partition, nLongsNeeded))
                        break;
                    if (CheckSecond==YES && AreBitfieldsEqual(definedConstraintTwoPruned[k], p->partition, nLongsNeeded))
                        break;
                    }
                }
            if (i!=t->nIntNodes)
                return NO;
            }
        }
    
    return YES;
}


/*------------------------------------------------------------------
|
|   FillTreeParams: Fill in trees and branch lengths
|                   
|   Note: Should be run after FillNormalParams because
|   clockrate needs to be set if calibrated tree needs
|   to be filled.
|
------------------------------------------------------------------*/
int FillTreeParams (RandLong *seed, int fromChain, int toChain)
{
    int         i, k, chn, nTaxa, tmp;
    Param       *p, *q;
    Tree        *tree;
    PolyTree    *constraintTree;
    PolyTree    *constraintTreeRef;

    if (PruneConstraintPartitions() == ERROR)
        return ERROR;

    /* Build starting trees for state 0 */
    for (chn=fromChain; chn<toChain; chn++)
        {
        for (k=0; k<numParams; k++)
            {
            p = &params[k];
            if (p->paramType == P_TOPOLOGY)
                {
                q = p->subParams[0];
                tree = GetTree (q, chn, 0);
                if (tree->isRooted == YES)
                    nTaxa = tree->nNodes - tree->nIntNodes - 1;
                else
                    nTaxa = tree->nNodes - tree->nIntNodes;
                
                /* fixed topology */
                if (p->paramId == TOPOLOGY_NCL_FIXED ||
                    p->paramId == TOPOLOGY_NCL_FIXED_HOMO ||
                    p->paramId == TOPOLOGY_NCL_FIXED_HETERO ||
                    p->paramId == TOPOLOGY_CL_FIXED  ||
                    p->paramId == TOPOLOGY_RCL_FIXED ||
                    p->paramId == TOPOLOGY_CCL_FIXED ||
                    p->paramId == TOPOLOGY_RCCL_FIXED||
                    p->paramId == TOPOLOGY_FIXED     ||
                    p->paramId == TOPOLOGY_PARSIMONY_FIXED)
                    {
                    constraintTree = AllocatePolyTree (numTaxa);
                    CopyToPolyTreeFromPolyTree (constraintTree, userTree[modelParams[p->relParts[0]].topologyFix]);
                    PrunePolyTree (constraintTree);
                    ResetTipIndices(constraintTree);
                    ResetIntNodeIndices(constraintTree);
                    RandResolve (NULL, constraintTree, seed, constraintTree->isRooted);
                    if (tree->nIntNodes != constraintTree->nIntNodes)
                        {
                        if (tree->isRooted != constraintTree->isRooted)
                            {
                            MrBayesPrint ("%s   Could not fix topology because user tree '%s' differs in rootedness with the model tree.\n", spacer,
                                          userTree[modelParams[p->relParts[0]].topologyFix]->name);
                            MrBayesPrint ("%s   The user tree %s is%srooted, while expected model tree is%srooted.\n", spacer,
                                          userTree[modelParams[p->relParts[0]].topologyFix]->name, (constraintTree->isRooted?" ":" not "), (tree->isRooted?" ":" not "));
                            MrBayesPrint ("%s   Check brlenspr is set correctly before fixing topology.\n", spacer);
                            }
                        else
                            MrBayesPrint ("%s   Could not fix topology because user tree '%s' is not fully resolved.\n",
                                                spacer, userTree[modelParams[p->relParts[0]].topologyFix]->name);
                        FreePolyTree (constraintTree);
                        return (ERROR);
                        }
                    if (CopyToTreeFromPolyTree(tree, constraintTree) == ERROR)
                        {
                        MrBayesPrint ("%s   Could not fix topology according to user tree '%s'\n", spacer, userTree[modelParams[p->relParts[0]].topologyFix]->name);
                        FreePolyTree (constraintTree);
                        return (ERROR);
                        }
                    FreePolyTree (constraintTree);
                    }
                /* constrained topology */
                else if (tree->nConstraints > 0)
                    {
                    constraintTreeRef = AllocatePolyTree (nTaxa);
                    if (!constraintTreeRef)
                        return (ERROR);
                    if (BuildConstraintTree (tree, constraintTreeRef, localTaxonNames) == ERROR)
                        {
                        FreePolyTree (constraintTreeRef);
                        return (ERROR);
                        }
                    if (AllocatePolyTreePartitions (constraintTreeRef) == ERROR)
                        return (ERROR);

                    constraintTree = AllocatePolyTree (nTaxa);
                    if (!constraintTree)
                        return (ERROR);
                    if (AllocatePolyTreePartitions (constraintTree) == ERROR)
                        return (ERROR);

                    for (i=0;i<100;i++)
                        {
                        CopyToPolyTreeFromPolyTree(constraintTree,constraintTreeRef);
                        tmp = RandResolve (tree, constraintTree, &globalSeed, tree->isRooted);
                        if (tmp != NO_ERROR)
                            {
                            if (tmp  == ERROR)
                                {
                                FreePolyTree (constraintTree);
                                return (ERROR);
                                }
                            else
                                {   
                                assert (tmp  == ABORT);
                                continue;
                                }
                            }
                   
                        CopyToTreeFromPolyTree(tree, constraintTree);
                        if (DoesTreeSatisfyConstraints(tree)==YES)
                            break;
                        }
#   if defined (DEBUG_CONSTRAINTS)
                    if (theTree->checkConstraints == YES && CheckConstraints (tree) == ERROR)
                        {
                        printf ("Error in constraints of starting tree\n");
                        getchar();
                        }
#   endif
                    FreePolyTree (constraintTree);
                    FreePolyTree (constraintTreeRef);
                    if (i==100)
                        {
                        MrBayesPrint ("%s   Could not build a starting tree satisfying all constraints\n", spacer);                     
                        return (ERROR);
                        }
                    }
                /* random topology */
                else
                    {
                    if (tree->isRooted == YES)
                        {
                        if (BuildRandomRTopology (tree, &globalSeed) == ERROR)
                            return (ERROR);
                        }
                    else
                        {
                        if (BuildRandomUTopology (tree, &globalSeed) == ERROR)
                            return (ERROR);
                        if (MoveCalculationRoot (tree, localOutGroup) == ERROR)
                            return (ERROR);
                        }
                    }
                
                if (LabelTree (tree, localTaxonNames) == ERROR)
                    return (ERROR);
                if (q == p)
                    continue;   /* this is a parsimony tree without branch lengths */
                if (InitializeTreeCalibrations (tree) == ERROR)
                    return (ERROR);
                if (FillTopologySubParams(p, chn, 0, seed)== ERROR)
                    return (ERROR);
                }
            }
        }

    if (numTopologies > 1 && !strcmp(modelParams[0].topologyPr,"Speciestree"))
        {
        if (FillSpeciesTreeParams(seed, fromChain, toChain) == ERROR)
            return (ERROR);
        }

    return (NO_ERROR);
}


void FreeCppEvents (Param *p)
{
    int i, j;
    
    if (p->paramType != P_CPPEVENTS)
        return;

    if (p->nEvents != NULL)
        {
        free (p->nEvents[0]);
        free (p->nEvents);
        for (i=0; i<numGlobalChains; i++)
            {
            for (j=0; j<2*numLocalTaxa; j++)
                {
                free (p->position[2*i][j]);
                free (p->rateMult[2*i][j]);
                free (p->position[2*i+1][j]);
                free (p->rateMult[2*i+1][j]);
                }
            }
        free (p->position[0]);
        free (p->position);
        free (p->rateMult[0]);
        free (p->rateMult);
        p->nEvents = NULL;
        p->position = NULL;
        p->rateMult = NULL;
        }
}


int FreeModel (void)
{
    int     i;
    Param   *p;
    
    if (memAllocs[ALLOC_MODEL] == YES)
        {
        for (i=0; i<numCurrentDivisions; i++)
            {
            free (modelParams[i].activeConstraints);
            if (memAllocs[ALLOC_SAMPLEFOSSILSLICE] == YES)
                {
                free(modelParams[i].sampleFSProb);
                free(modelParams[i].sampleFSTime);
                memAllocs[ALLOC_SAMPLEFOSSILSLICE] = NO;
                }
            }
        free (modelParams);
        free (modelSettings);
        memAllocs[ALLOC_MODEL] = NO;
        }
    if (memAllocs[ALLOC_MOVES] == YES)
        {
        for (i=0; i<numApplicableMoves; i++)
            FreeMove (moves[i]);
        free (moves);
        moves = NULL;
        numApplicableMoves = 0;
        memAllocs[ALLOC_MOVES] = NO;
        }
    if (memAllocs[ALLOC_COMPMATRIX] == YES)
        {
        free (compMatrix);
        memAllocs[ALLOC_COMPMATRIX] = NO;
        }
    if (memAllocs[ALLOC_NUMSITESOFPAT] == YES)
        {
        free (numSitesOfPat);
        memAllocs[ALLOC_NUMSITESOFPAT] = NO;
        }
    if (memAllocs[ALLOC_COMPCOLPOS] == YES)
        {
        free (compColPos);
        memAllocs[ALLOC_COMPCOLPOS] = NO;
        }
    if (memAllocs[ALLOC_COMPCHARPOS] == YES)
        {
        free (compCharPos);
        memAllocs[ALLOC_COMPCHARPOS] = NO;
        }
    if (memAllocs[ALLOC_ORIGCHAR] == YES)
        {
        free (origChar);
        memAllocs[ALLOC_ORIGCHAR] = NO;
        }
    if (memAllocs[ALLOC_STDTYPE] == YES)
        {
        free (stdType);
        memAllocs[ALLOC_STDTYPE] = NO;
        }
    if (memAllocs[ALLOC_STDSTATEFREQS] == YES)
        {
        free (stdStateFreqs);
        stdStateFreqs = NULL;
        memAllocs[ALLOC_STDSTATEFREQS] = NO;
        }
    if (memAllocs[ALLOC_PARAMVALUES] == YES)
        {
        for (i=0; i<numParams; i++)
            {
            p = &params[i];
            if (p->paramType == P_CPPEVENTS)
                FreeCppEvents(p);
            }
        free (paramValues);
        paramValues = NULL;
        free (intValues);
        intValues = NULL;
        paramValsRowSize = intValsRowSize = 0;
        memAllocs[ALLOC_PARAMVALUES] = NO;
        }
    if (memAllocs[ALLOC_PARAMS] == YES)
        {
        for (i=0; i<numParams; i++)
            {
            SafeFree ((void **)&params[i].name);
            if (params[i].paramHeader)
                {
                free (params[i].paramHeader);
                params[i].paramHeader = NULL;
                }
            }
        free (params);
        free (relevantParts);
        params = NULL;
        relevantParts = NULL;
        numParams = 0;
        memAllocs[ALLOC_PARAMS] = NO;
        }
    if (memAllocs[ALLOC_MCMCTREES] == YES)
        {
        free (mcmcTree);
        free (subParamPtrs);
        mcmcTree = NULL;
        subParamPtrs = NULL;
        memAllocs[ALLOC_MCMCTREES] = NO;
        }
    if (memAllocs[ALLOC_SYMPIINDEX] == YES)
        {
        free (sympiIndex);
        memAllocs[ALLOC_SYMPIINDEX] = NO;
        }
    if (memAllocs[ALLOC_LOCTAXANAMES] == YES)
        {
        free (localTaxonNames);
        memAllocs[ALLOC_LOCTAXANAMES] = NO;
        }
    if (memAllocs[ALLOC_LOCALTAXONCALIBRATION] == YES)
        {
        free (localTaxonCalibration);
        memAllocs[ALLOC_LOCALTAXONCALIBRATION] = NO;
        }

    return (NO_ERROR);
}


void FreeMove (MCMCMove *mv)
{
    free (mv->tuningParam[0]);
    free (mv->tuningParam);
    free (mv->relProposalProb);
    free (mv->nAccepted);
    free (mv->name);
    free (mv);
}


/* Compute empirical state freq are return it in global array empiricalFreqs[] */
int GetEmpiricalFreqs (int *relParts, int nRelParts)
{
    int             i, j, k, m, n, thePartition, nuc[20], ns, temp, isDNA, isProtein, firstRel;
    MrBFlt          freqN[20], sum, sumN[20]/*, rawCounts[20]*/;

    isDNA = isProtein = NO;
    ns = 0;
    firstRel = 0;
    for (i=0; i<nRelParts; i++)
        {
        thePartition = relParts[i];
        if (i == 0)
            {
            if (modelParams[thePartition].dataType == DNA || modelParams[i].dataType == RNA)
                {
                isDNA = YES;
                ns = 4;
                }
            else if (modelParams[thePartition].dataType == PROTEIN)
                {
                isProtein = YES;
                ns = 20;
                }
            else if (modelParams[thePartition].dataType == RESTRICTION)
                {
                ns = 2;
                }
            else
                {
                MrBayesPrint ("%s   Cannot get empirical state frequencies for this datatype (%d)\n", spacer, modelSettings[i].dataType);
                return (ERROR);
                }
            firstRel = thePartition;
            }
        else
            {
            if (modelParams[thePartition].dataType == DNA || modelParams[i].dataType == RNA)
                temp = 4;
            else if (modelParams[thePartition].dataType == PROTEIN)
                temp = 20;
            else if (modelParams[thePartition].dataType == RESTRICTION)
                temp = 2;
            else
                {
                MrBayesPrint ("%s   Unknown data type in GetEmpiricalFreqs\n", spacer);
                return (ERROR);
                }
            if (ns != temp)
                {
                MrBayesPrint ("%s   Averaging state frequencies over partitions with different data types\n", spacer);
                return (ERROR);
                }
            }
        }
    if (ns == 0)
        {
        MrBayesPrint ("%s   Could not find a relevant partition\n", spacer);
        return (ERROR);
        }

    for (i=0; i<200; i++)
        empiricalFreqs[i] = 0.0;
    
    for (m=0; m<ns; m++)
        freqN[m] =  1.0 / ns;
        
    /* for (m=0; m<ns; m++)
       rawCounts[m] = 0.0; NEVER USED */
        
    for (m=0; m<ns; m++)
        sumN[m] = 0.0;
    for (k=0; k<nRelParts; k++)
        {
        thePartition = relParts[k];
        for (i=0; i<numTaxa; i++)
            {
            if (taxaInfo[i].isDeleted == NO)
                {
                for (j=0; j<numChar; j++)
                    {
                    if (charInfo[j].isExcluded == NO && partitionId[j][partitionNum] - 1 == thePartition)
                        {
                        if (isDNA == YES)
                            GetPossibleNucs (matrix[pos(i,j,numChar)], nuc);
                        else if (isProtein == YES)
                            GetPossibleAAs (matrix[pos(i,j,numChar)], nuc);
                        else
                            GetPossibleRestrictionSites (matrix[pos(i,j,numChar)], nuc);
                        sum = 0.0;
                        for (m=0; m<ns; m++)
                            sum += freqN[m] * nuc[m];
                        for (m=0; m<ns; m++)
                            sumN[m] += freqN[m] * nuc[m] / sum;
                        }
                    }
                }
            }
        }
    sum = 0.0;
    for (m=0; m<ns; m++)
        sum += sumN[m];
    for (m=0; m<ns; m++)
        freqN[m] = sumN[m] / sum;

    if (modelParams[firstRel].dataType == DNA || modelParams[firstRel].dataType == RNA)
        {
        if (!strcmp(modelParams[firstRel].nucModel, "4by4"))
            {
            for (m=0; m<ns; m++)
                empiricalFreqs[m] = freqN[m];
            }
        else if (!strcmp(modelParams[firstRel].nucModel, "Doublet"))
            {
            i = 0;
            for (m=0; m<ns; m++)
                for (n=0; n<ns; n++)
                    empiricalFreqs[i++] = freqN[m] * freqN[n];
            }
        else
            {
            if (!strcmp(modelParams[firstRel].geneticCode, "Universal"))
                {
                for (i=0; i<61; i++)
                    empiricalFreqs[i] = freqN[modelParams[firstRel].codonNucs[i][0]] * freqN[modelParams[firstRel].codonNucs[i][1]] * freqN[modelParams[firstRel].codonNucs[i][2]];
                }
            else if (!strcmp(modelParams[firstRel].geneticCode, "Vertmt"))
                {
                for (i=0; i<60; i++)
                    empiricalFreqs[i] = freqN[modelParams[firstRel].codonNucs[i][0]] * freqN[modelParams[firstRel].codonNucs[i][1]] * freqN[modelParams[firstRel].codonNucs[i][2]];
                }
            else if (!strcmp(modelParams[firstRel].geneticCode, "Mycoplasma"))
                {
                for (i=0; i<62; i++)
                    empiricalFreqs[i] = freqN[modelParams[firstRel].codonNucs[i][0]] * freqN[modelParams[firstRel].codonNucs[i][1]] * freqN[modelParams[firstRel].codonNucs[i][2]];
                }
            else if (!strcmp(modelParams[firstRel].geneticCode, "Yeast"))
                {
                for (i=0; i<62; i++)
                    empiricalFreqs[i] = freqN[modelParams[firstRel].codonNucs[i][0]] * freqN[modelParams[firstRel].codonNucs[i][1]] * freqN[modelParams[firstRel].codonNucs[i][2]];
                }
            else if (!strcmp(modelParams[firstRel].geneticCode, "Ciliates"))
                {
                for (i=0; i<63; i++)
                    empiricalFreqs[i] = freqN[modelParams[firstRel].codonNucs[i][0]] * freqN[modelParams[firstRel].codonNucs[i][1]] * freqN[modelParams[firstRel].codonNucs[i][2]];
                }
            else if (!strcmp(modelParams[firstRel].geneticCode, "Metmt"))
                {
                for (i=0; i<62; i++)
                    empiricalFreqs[i] = freqN[modelParams[firstRel].codonNucs[i][0]] * freqN[modelParams[firstRel].codonNucs[i][1]] * freqN[modelParams[firstRel].codonNucs[i][2]];
                }
            sum = 0.0;
            for (i=0; i<64; i++)
                sum += empiricalFreqs[i];
            for (i=0; i<64; i++)
                empiricalFreqs[i] /= sum;
            
            }
        }
    else
        {
        for (m=0; m<ns; m++)
            empiricalFreqs[m] = freqN[m];
        }
        
    return (NO_ERROR);
}


int GetNumDivisionChars (void)
{
    int         c, d, n;
    ModelInfo   *m;

    /* count number of characters in each division */
    for (d=0; d<numCurrentDivisions; d++)
        {
        m = &modelSettings[d];
        
        n = 0;
        for (c=0; c<numChar; c++)
            {
            if (charInfo[c].isExcluded == NO && partitionId[c][partitionNum] == d+1)
                n++;
            }
        if (m->dataType == DNA || m->dataType == RNA)
            {
            if (m->nucModelId == NUCMODEL_DOUBLET)
                n *= 2;
            else if (m->nucModelId == NUCMODEL_CODON)
                n *= 3;
            }

        m->numUncompressedChars = n;
        }
    
    return (NO_ERROR);
}


int *GetParamIntVals (Param *parm, int chain, int state)
{
    return parm->intValues + (2 * chain + state) * intValsRowSize;
}


MrBFlt  *GetParamStdStateFreqs (Param *parm, int chain, int state)
{
    return parm->stdStateFreqs + (2 * chain + state) * stdStateFreqsRowSize;
}


MrBFlt  *GetParamSubVals (Param *parm, int chain, int state)
{
    return parm->subValues + (2 * chain + state) * paramValsRowSize;
}


MrBFlt  *GetParamVals (Param *parm, int chain, int state)
{
    return parm->values + (2 * chain + state) * paramValsRowSize;
}


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
        {
        nuc[0] = 1;
        nuc[1] = 1;
        nuc[2] = 1;
        nuc[3] = 1;
        }
}


void GetPossibleRestrictionSites (int resSiteCode, int *sites)
{
    int     m;
    
    for (m=0; m<2; m++)
        sites[m] = 0;
        
    if (resSiteCode == 1)
        sites[0] = 1;
    else if (resSiteCode == 2)
        sites[1] = 1;
    else
        sites[0] = sites[1] = 1;

#   if 0
    printf ("%2d -- ", aaCode);
    for (m=0; m<20; m++)
        printf ("%d", aa[m]);
    printf ("\n");
#   endif
}


Tree *GetTree (Param *parm, int chain, int state)
{
    return mcmcTree[parm->treeIndex + ((2 * chain + state) * numTrees)];
}


Tree *GetTreeFromIndex (int index, int chain, int state)
{
    return mcmcTree[index + ((2 * chain + state) * numTrees)];
}


/*-----------------------------------------------------------
|
|   GetUserTreeFromName: Do case-insensitive search for user
|      tree, return index if match, -1 and ERROR if error
|
------------------------------------------------------------*/
int GetUserTreeFromName (int *index, char *treeName)
{
    int     i, j, k, nMatches;
    char    localName[100], temp[100];

    (*index) = -1;  /* appropriate return if no match */

    if ((int)strlen(treeName) > 99)
        {
        MrBayesPrint ("%s   Too many characters in tree name\n", spacer);
        return (ERROR);
        }

    strcpy (localName, treeName);
    for (i=0; i<(int)strlen(localName); i++)
        localName[i] = tolower(localName[i]);

    nMatches = j = 0;
    for (i=0; i<numUserTrees; i++)
        {
        strcpy (temp, userTree[i]->name);
        for (k=0; k<(int)strlen(temp); k++)
            temp[k] = tolower(temp[k]);
        if (strcmp(localName,temp) == 0)
            {
            j = i;
            nMatches++;
            }
        }
    if (nMatches==0)
        {
        for (i=0; i<numUserTrees; i++)
            {
            strcpy (temp, userTree[i]->name);
            for (k=0; k<(int)strlen(temp); k++)
                temp[k] = tolower(temp[k]);
            if (strncmp(localName,temp,strlen(localName)) == 0)
                {
                j = i;
                nMatches++;
                }
            }
        }
    if (nMatches == 0)
        {
        MrBayesPrint ("%s   Could not find tree '%s'\n", spacer, localName);  
        return (ERROR);
        }
    else if (nMatches > 1)
        {
        MrBayesPrint ("%s   Several trees matched the abbreviated name '%s'\n", spacer, localName);
        return (ERROR);
        }
    else
        {
        (*index) = j;
        return (NO_ERROR);
        }
}


/*----------------------------------------------------------------------
 |
 |   InitializeChainTrees: 'Constructor' for chain trees
 |
 -----------------------------------------------------------------------*/
int InitializeChainTrees (Param *p, int from, int to, int isRooted)
{
    int     i, st, isCalibrated, isClock, nTaxa, numActiveHardConstraints=0;
    Tree    *tree, **treeHandle;
    Model   *mp;
    
    mp = &modelParams[p->relParts[0]];
    
    if (p->paramType == P_SPECIESTREE)
        nTaxa = numSpecies;
    else
        nTaxa = numLocalTaxa;
    
    /* figure out whether the trees are clock */
    if (!strcmp(mp->brlensPr,"Clock"))
        isClock = YES;
    else
        isClock = NO;
    
    /* figure out whether the trees are calibrated */
    if (!strcmp(mp->brlensPr,"Clock") && (strcmp(mp->nodeAgePr,"Calibrated") == 0 || strcmp(mp->clockRatePr,"Fixed") != 0 ||
                                          (strcmp(mp->clockRatePr, "Fixed") == 0 && AreDoublesEqual(mp->clockRateFix, 1.0, 1E-6) == NO)))
        isCalibrated = YES;
    else
        isCalibrated = NO;
    
    if (p->checkConstraints == YES)
        {
        for (i=0; i<numDefinedConstraints; i++)
            {
            if (mp->activeConstraints[i] == YES && definedConstraintsType[i] == HARD)
                numActiveHardConstraints++;
            }
        }
    
    /* allocate space for and construct the trees */
    /* NOTE: The memory allocation scheme used here must match GetTree and GetTreeFromIndex */
    for (i=from; i<to; i++)
        {
        treeHandle = mcmcTree + p->treeIndex + 2*i*numTrees;
        if (*treeHandle)
            free(*treeHandle);
        if ((*treeHandle = AllocateTree (nTaxa)) == NULL)
            {
            MrBayesPrint ("%s   Problem allocating mcmc trees\n", spacer);
            return (ERROR);
            }
        treeHandle = mcmcTree + p->treeIndex + (2*i + 1)*numTrees;
        if (*treeHandle)
            free(*treeHandle);
        if ((*treeHandle = AllocateTree (nTaxa)) == NULL)
            {
            MrBayesPrint ("%s   Problem allocating mcmc trees\n", spacer);
            return (ERROR);
            }
        }
    
    /* initialize the trees */
    for (i=from; i<to; i++)
        {
        for (st=0; st<2; st++)
            {
            tree = GetTree (p, i, st);
            if (numTrees > 1)
                sprintf (tree->name, "mcmc.tree%d_%d", p->treeIndex+1, i+1);
            else /* if (numTrees == 1) */
                sprintf (tree->name, "mcmc.tree_%d", i+1);
            tree->nRelParts = p->nRelParts;
            tree->relParts = p->relParts;
            tree->isRooted = isRooted;
            tree->isClock = isClock;
            tree->isCalibrated = isCalibrated;
            if (p->paramType == P_SPECIESTREE)
                {
                tree->nNodes = 2*numSpecies;
                tree->nIntNodes = numSpecies - 1;
                }
            else if (tree->isRooted == YES)
                {
                tree->nNodes = 2*numLocalTaxa;
                tree->nIntNodes = numLocalTaxa - 1;
                }
            else /* if (tree->isRooted == NO) */
                {
                tree->nNodes = 2*numLocalTaxa - 2;
                tree->nIntNodes = numLocalTaxa - 2;
                }
            if (p->checkConstraints == YES)
                {
                tree->checkConstraints = YES;
                tree->nLocks = NumInformativeHardConstraints(mp);
                tree->nConstraints = mp->numActiveConstraints;  /* nConstraints is number of constraints to check */
                tree->constraints = mp->activeConstraints;
                }
            else
                {
                tree->checkConstraints = NO;
                tree->nConstraints = tree->nLocks = 0;
                tree->constraints = NULL;
                }
            }
        }
    
    return (NO_ERROR);
}


int InitializeLinks (void)
{
    int         i, j;
    
    linkNum = 0;
    for (i=0; i<NUM_LINKED; i++)
        {
        for (j=0; j<numCurrentDivisions; j++)
            linkTable[i][j] = linkNum;
        }

    return (NO_ERROR);
}


/* InitializeTreeCalibrations: Set calibrations for tree nodes */
int InitializeTreeCalibrations (Tree *t)
{
    int         i;
    TreeNode    *p;
    
    if (t->isCalibrated == NO)
        return (NO_ERROR);
    
    /* Set tip calibrations */
    for (i=0; i<t->nNodes; i++)
        {
        p = t->allDownPass[i];
        if (p->left == NULL && p->right == NULL && localTaxonCalibration[p->index]->prior != unconstrained)
            {
            p->isDated = YES;
            p->calibration = localTaxonCalibration[p->index];
            p->age = p->calibration->min;
            }
        else if (p->left == NULL && p->right == NULL)
            {
            p->isDated = NO;
            p->calibration = NULL;
            p->age = -1.0;
            } 
        }

    /* Initialize interior calibrations */
    if (CheckSetConstraints(t) == ERROR)
        return (ERROR);

    return (NO_ERROR);
}


int IsApplicable (Param *param)
{
    if (param == NULL)
        return NO;

    return YES;
}


int IsApplicable_ThreeTaxaOrMore (Param *param)
{
    if (LargestMovableSubtree (param) >= 3)
        return YES;
    else
        return NO;
}


int IsApplicable_FourTaxaOrMore (Param *param)
{
    if (LargestMovableSubtree (param) >= 4)
        return YES;
    else
        return NO;
}


int IsApplicable_FiveTaxaOrMore (Param *param)
{
    if (LargestMovableSubtree (param) >= 5)
        return YES;
    else
        return NO;
}


int IsApplicable_TreeAgeMove (Param *param)
{
    Tree        *t;
    TreeNode    *p;

    if (param == NULL)
        return NO;

    if (param->paramType != P_BRLENS)
        return NO;
    
    t = GetTree (param, 0, 0);

    p = t->root->left;
    if (p->isDated == NO)
        return NO;
    if (p->calibration->prior == fixed)
        return NO;
    else
        return YES;
}


int IsApplicable_AncestralFossil (Param *param)
{
    ModelParams *mp = &modelParams[param->relParts[0]];

    if (!strcmp(mp->sampleStrat, "FossilTip"))
        return NO;
    else if (mp->fossilizationFix == 0.0)
        return NO;
    else  /* fossils may be ancestors of other fossils or extant species */
        return YES;
}


int IsModelSame (int whichParam, int part1, int part2, int *isApplic1, int *isApplic2)
{
    int         i, isSame, isFirstNucleotide, isSecondNucleotide, isFirstProtein, isSecondProtein, nDiff, temp1, temp2;

    isSame = YES;
    *isApplic1 = YES;
    *isApplic2 = YES;

    /* We cannot rely on SetModelInfo being called first so we need to be smart in figuring out model data type by looking at several model params */
    isFirstNucleotide = isSecondNucleotide = NO;
    if ((modelParams[part1].dataType == DNA || modelParams[part1].dataType == RNA) && strcmp(modelParams[part1].nucModel,"Protein") != 0)
        isFirstNucleotide = YES;
    if ((modelParams[part2].dataType == DNA || modelParams[part2].dataType == RNA) && strcmp(modelParams[part2].nucModel,"Protein") != 0)
        isSecondNucleotide = YES;       
    isFirstProtein = isSecondProtein = NO;
    if (modelParams[part1].dataType == PROTEIN || ((modelParams[part1].dataType == DNA || modelParams[part1].dataType == RNA) && !strcmp(modelParams[part1].nucModel,"Protein")))
        isFirstProtein = YES;
    if (modelParams[part2].dataType == PROTEIN || ((modelParams[part2].dataType == DNA || modelParams[part2].dataType == RNA) && !strcmp(modelParams[part2].nucModel,"Protein")))
        isSecondProtein = YES;      
    
    if (whichParam == P_TRATIO)
        {
        /* Check the ti/tv rate ratio for partitions 1 and 2. */

        /* Check if the model is parsimony for either partition */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; /* part1 has a parsimony model and tratio does not apply */
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; /* part2 has a parsimony model and tratio does not apply */
        
        /* Check that the data are nucleotide for both partitions 1 and 2 */
        if (isFirstNucleotide == NO)
            *isApplic1 = NO; /* part1 is not nucleotide data so tratio does not apply */
        if (isSecondNucleotide == NO)
            *isApplic2 = NO; /* part2 is not nucleotide data so tratio does not apply */
        
        /* check that nst=2 for both partitions */
        if (strcmp(modelParams[part1].nst, "2"))
            *isApplic1 = NO; /* part1 does not have nst=2 and tratio does not apply */
        if (strcmp(modelParams[part2].nst, "2"))
            *isApplic2 = NO; /* part2 does not have nst=2 and tratio does not apply */
        
        /* Check if part1 & part2 are restriction */
        if (modelParams[part1].dataType == RESTRICTION)
            *isApplic1 = NO;
        if (modelParams[part2].dataType == RESTRICTION)
            *isApplic2 = NO;

        /* If Nst = 2 for both part1 and part2, we now need to check if the prior is the same for both. */
        if (!strcmp(modelParams[part1].tRatioPr,"Beta") && !strcmp(modelParams[part2].tRatioPr,"Beta"))
            {
            if (AreDoublesEqual (modelParams[part1].tRatioDir[0], modelParams[part2].tRatioDir[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].tRatioDir[1], modelParams[part2].tRatioDir[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].tRatioPr,"Fixed") && !strcmp(modelParams[part2].tRatioPr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].tRatioFix, modelParams[part2].tRatioFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */

        /* Check to see if tratio is inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO; /* if tratio is inapplicable for either partition, then the parameter cannot be the same */
        }
    else if (whichParam == P_REVMAT)
        {
        /* Check the GTR rates for partitions 1 and 2. */
        
        /* Check if the model is parsimony for either partition */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; /* part1 has a parsimony model and GTR rates do not apply */
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; /* part2 has a parsimony model and GTR rates do not apply */

        /* Check that the data are nucleotide or protein for both partitions 1 and 2 */
        if (isFirstNucleotide == NO && isFirstProtein == NO)
            *isApplic1 = NO; /* part1 is not nucleotide or protein data so GTR rates do not apply */
        if (isSecondNucleotide == NO && isSecondProtein == NO)
            *isApplic2 = NO; /* part2 is not nucleotide or protein data so GTR rates do not apply */

        /* check that nst=6 or mixed for both partitions if nucleotide */
        if (isFirstNucleotide == YES && strcmp(modelParams[part1].nst, "6") && strcmp(modelParams[part1].nst, "Mixed"))
            *isApplic1 = NO; /* part1 does not have nst=6/Mixed and GTR rates do not apply */
        if (isSecondNucleotide == YES && strcmp(modelParams[part2].nst, "6") && strcmp(modelParams[part2].nst, "Mixed"))
            *isApplic2 = NO; /* part2 does not have nst=6/Mixed and GTR rates do not apply */
            
        /* check that model is GTR for both partitions if protein */
        if (isFirstProtein == YES && (strcmp(modelParams[part1].aaModel,"Gtr")!=0 || strcmp(modelParams[part1].aaModelPr,"Fixed")!=0))
            *isApplic1 = NO;
        if (isSecondProtein == YES && (strcmp(modelParams[part2].aaModel,"Gtr")!=0 || strcmp(modelParams[part2].aaModelPr,"Fixed")!=0))
            *isApplic2 = NO;

        /* check that data type is the same for both partitions */
        if (isFirstNucleotide == YES && isSecondNucleotide == NO)
            isSame = NO;
        if (isFirstProtein == YES && isSecondProtein == NO)
            isSame = NO;

        /* GTR applies to both part1 and part2. We now need to check if the prior is the same for both. */
        if (isFirstNucleotide == YES)
            {
            if (strcmp(modelParams[part1].nst, modelParams[part2].nst) != 0)
                isSame = NO;
            if (!strcmp(modelParams[part1].nst,"Mixed"))
                {
                if (AreDoublesEqual (modelParams[part1].revMatSymDir, modelParams[part2].revMatSymDir, (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                }
            else if (!strcmp(modelParams[part1].nst,"6") && !strcmp(modelParams[part1].revMatPr,"Dirichlet") && !strcmp(modelParams[part2].revMatPr,"Dirichlet"))
                {
                for (i=0; i<6; i++)
                    {
                    if (AreDoublesEqual (modelParams[part1].revMatDir[i], modelParams[part2].revMatDir[i], (MrBFlt) 0.00001) == NO)
                        isSame = NO;
                    }
                }
            else if (!strcmp(modelParams[part1].nst,"6") && !strcmp(modelParams[part1].revMatPr,"Fixed") && !strcmp(modelParams[part2].revMatPr,"Fixed"))
                {
                for (i=0; i<6; i++)
                    {
                    if (AreDoublesEqual (modelParams[part1].revMatFix[i], modelParams[part2].revMatFix[i], (MrBFlt) 0.00001) == NO)
                        isSame = NO;
                    }
                }
            else
                isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */
            }
        else /* if (isFirstProtein == YES) */
            {
            if (!strcmp(modelParams[part1].aaRevMatPr,"Dirichlet") && !strcmp(modelParams[part2].aaRevMatPr,"Dirichlet"))
                {
                for (i=0; i<190; i++)
                    {
                    if (AreDoublesEqual (modelParams[part1].aaRevMatDir[i], modelParams[part2].aaRevMatDir[i], (MrBFlt) 0.00001) == NO)
                        isSame = NO;
                    }
                }
            else if (!strcmp(modelParams[part1].aaRevMatPr,"Fixed") && !strcmp(modelParams[part2].aaRevMatPr,"Fixed"))
                {
                for (i=0; i<190; i++)
                    {
                    if (AreDoublesEqual (modelParams[part1].aaRevMatFix[i], modelParams[part2].aaRevMatFix[i], (MrBFlt) 0.00001) == NO)
                        isSame = NO;
                    }
                }
            else
                isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */
            }

        /* Check to see if the GTR rates are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO; /* if GTR rates are inapplicable for either partition, then the parameter cannot be the same */
        }
    else if (whichParam == P_OMEGA)
        {
        /* Check the nonsynonymous/synonymous rate ratio for partitions 1 and 2. */
        
        /* Check if the model is parsimony for either partition */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; /* part1 has a parsimony model and nonsynonymous/synonymous rate ratio does not apply */
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; /* part2 has a parsimony model and nonsynonymous/synonymous rate ratio does not apply */
        
        /* Check that the data are nucleotide for both partitions 1 and 2 */
        if (isFirstNucleotide == NO)
            *isApplic1 = NO; /* part1 is not nucleotide data so a nonsynonymous/synonymous rate ratio does not apply */
        if (isSecondNucleotide == NO)
            *isApplic2 = NO; /* part2 is not nucleotide data so a nonsynonymous/synonymous rate ratio does not apply */
        
        /* Check that the model structure is the same for both. The nucmodel should be "codon". */
        if (strcmp(modelParams[part1].nucModel, "Codon"))
            *isApplic1 = NO; /* part1 does not have Nucmodel = Codon and nonsynonymous/synonymous rate ratio does not apply */
        if (strcmp(modelParams[part2].nucModel, "Codon"))
            *isApplic2 = NO; /* part2 does not have Nucmodel = Codon and nonsynonymous/synonymous rate ratio does not apply */
        
        /* Assuming that Nucmodel = Codon for both part1 and part2, we now need to check if the prior is the
           same for both. */
        if (!strcmp(modelParams[part1].omegaVar, "M3") && !strcmp(modelParams[part2].omegaVar, "M3"))
            {
            if (!strcmp(modelParams[part1].m3omegapr, "Exponential") && !strcmp(modelParams[part2].m3omegapr, "Exponential"))
                {
                }
            else if (!strcmp(modelParams[part1].m3omegapr, "Fixed") && !strcmp(modelParams[part1].m3omegapr, "Fixed"))
                {
                if (AreDoublesEqual (modelParams[part1].m3omegaFixed[0], modelParams[part2].m3omegaFixed[0], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].m3omegaFixed[1], modelParams[part2].m3omegaFixed[1], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                }
            else
                isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */

            if (!strcmp(modelParams[part1].codonCatFreqPr, "Dirichlet") && !strcmp(modelParams[part2].codonCatFreqPr, "Dirichlet"))
                {
                if (AreDoublesEqual (modelParams[part1].codonCatDir[0], modelParams[part2].codonCatDir[0], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].codonCatDir[1], modelParams[part2].codonCatDir[1], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].codonCatDir[2], modelParams[part2].codonCatDir[2], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                }
            else if (!strcmp(modelParams[part1].codonCatFreqPr, "Fixed") && !strcmp(modelParams[part1].codonCatFreqPr, "Fixed"))
                {
                if (AreDoublesEqual (modelParams[part1].codonCatFreqFix[0], modelParams[part2].codonCatFreqFix[0], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].codonCatFreqFix[1], modelParams[part2].codonCatFreqFix[1], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].codonCatFreqFix[2], modelParams[part2].codonCatFreqFix[2], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                }
            else
                isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */
            }
        else if (!strcmp(modelParams[part1].omegaVar, "M10") && !strcmp(modelParams[part2].omegaVar, "M10"))
            {           
            if (!strcmp(modelParams[part1].codonCatFreqPr, "Dirichlet") && !strcmp(modelParams[part2].codonCatFreqPr, "Dirichlet"))
                {
                if (AreDoublesEqual (modelParams[part1].codonCatDir[0], modelParams[part2].codonCatDir[0], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].codonCatDir[1], modelParams[part2].codonCatDir[1], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                }
            else if (!strcmp(modelParams[part1].codonCatFreqPr, "Fixed") && !strcmp(modelParams[part1].codonCatFreqPr, "Fixed"))
                {
                if (AreDoublesEqual (modelParams[part1].codonCatFreqFix[0], modelParams[part2].codonCatFreqFix[0], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].codonCatFreqFix[1], modelParams[part2].codonCatFreqFix[1], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                }
            else
                isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */
            }
        else if (!strcmp(modelParams[part1].omegaVar, "Ny98") && !strcmp(modelParams[part2].omegaVar, "Ny98"))
            {
            if (!strcmp(modelParams[part1].ny98omega1pr, "Beta") && !strcmp(modelParams[part2].ny98omega1pr, "Beta"))
                {
                if (AreDoublesEqual (modelParams[part1].ny98omega1Beta[0], modelParams[part2].ny98omega1Beta[0], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].ny98omega1Beta[1], modelParams[part2].ny98omega1Beta[1], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                }
            else if (!strcmp(modelParams[part1].ny98omega1pr, "Fixed") && !strcmp(modelParams[part1].ny98omega1pr, "Fixed"))
                {
                if (AreDoublesEqual (modelParams[part1].ny98omega1Fixed, modelParams[part2].ny98omega1Fixed, (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                }
            else
                isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */
            if (!strcmp(modelParams[part1].ny98omega3pr, "Uniform") && !strcmp(modelParams[part2].ny98omega3pr, "Uniform"))
                {
                if (AreDoublesEqual (modelParams[part1].ny98omega3Uni[0], modelParams[part2].ny98omega3Uni[0], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].ny98omega3Uni[1], modelParams[part2].ny98omega3Uni[1], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                }
            else if (!strcmp(modelParams[part1].ny98omega3pr, "Exponential") && !strcmp(modelParams[part1].ny98omega3pr, "Exponential"))
                {
                if (AreDoublesEqual (modelParams[part1].ny98omega3Exp, modelParams[part2].ny98omega3Exp, (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                }
            else if (!strcmp(modelParams[part1].ny98omega3pr, "Fixed") && !strcmp(modelParams[part1].ny98omega3pr, "Fixed"))
                {
                if (AreDoublesEqual (modelParams[part1].ny98omega3Fixed, modelParams[part2].ny98omega3Fixed, (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                }
            else
                isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */
            if (!strcmp(modelParams[part1].codonCatFreqPr, "Dirichlet") && !strcmp(modelParams[part2].codonCatFreqPr, "Dirichlet"))
                {
                if (AreDoublesEqual (modelParams[part1].codonCatDir[0], modelParams[part2].codonCatDir[0], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].codonCatDir[1], modelParams[part2].codonCatDir[1], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].codonCatDir[2], modelParams[part2].codonCatDir[2], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                }
            else if (!strcmp(modelParams[part1].codonCatFreqPr, "Fixed") && !strcmp(modelParams[part1].codonCatFreqPr, "Fixed"))
                {
                if (AreDoublesEqual (modelParams[part1].codonCatFreqFix[0], modelParams[part2].codonCatFreqFix[0], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].codonCatFreqFix[1], modelParams[part2].codonCatFreqFix[1], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].codonCatFreqFix[2], modelParams[part2].codonCatFreqFix[2], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                }
            else
                isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */
            }
        else if (!strcmp(modelParams[part1].omegaVar, "Equal") && !strcmp(modelParams[part2].omegaVar, "Equal"))
            {
            if (!strcmp(modelParams[part1].omegaPr,"Dirichlet") && !strcmp(modelParams[part2].omegaPr,"Dirichlet"))
                {
                if (AreDoublesEqual (modelParams[part1].omegaDir[0], modelParams[part2].omegaDir[0], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].omegaDir[1], modelParams[part2].omegaDir[1], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                }
            else if (!strcmp(modelParams[part1].omegaPr,"Fixed") && !strcmp(modelParams[part2].omegaPr,"Fixed"))
                {
                if (AreDoublesEqual (modelParams[part1].omegaFix, modelParams[part2].omegaFix, (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                }
            else
                isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */
            }
        else
            isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */
        
        /* Check to see if omega is inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO; /* if omega is inapplicable for either partition, then the parameter cannot be the same */
        }
    else if (whichParam == P_PI)
        {
        /* Check the state frequencies for partitions 1 and 2. */
        
        /* Check if the model is parsimony for either partition */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; /* part1 has a parsimony model and state frequencies do not apply */
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; /* part2 has a parsimony model and state frequencies do not apply */

        /* Check that the data are not CONTINUOUS for partitions 1 and 2 */
        if (modelParams[part1].dataType == CONTINUOUS)
            *isApplic1 = NO; /* state frequencies do not make sense for part1 */
        if (modelParams[part2].dataType == CONTINUOUS)
            *isApplic2 = NO; /* state frequencies do not make sense for part2 */
            
        /* Now, check that the data are the same (i.e., both nucleotide or both amino acid, or whatever). */
        if (isFirstNucleotide != isSecondNucleotide)
            isSame = NO; /* data are not both nucleotide or both note nucleotide */
        else if (modelParams[part1].dataType != modelParams[part2].dataType && isFirstNucleotide == NO)
            isSame = NO; /* data are not the same */

        /* Check that the model structure is the same for both partitions */
        if (strcmp(modelParams[part1].nucModel, modelParams[part2].nucModel))
            isSame = NO; /* the nucleotide models are different */
        if (strcmp(modelParams[part1].covarionModel, modelParams[part2].covarionModel) && !(!strcmp(modelParams[part1].nucModel, "Codon") && !strcmp(modelParams[part2].nucModel, "Codon")))
            isSame = NO; /* the models have different covarion struture */
            
        /* If both partitions have nucmodel=codon, then we also have to make certain that the same genetic code is used. */
        if (!strcmp(modelParams[part1].nucModel, "Codon") && !strcmp(modelParams[part2].nucModel, "Codon"))
            {
            if (strcmp(modelParams[part1].geneticCode,modelParams[part2].geneticCode))
                isSame = NO; /* the models have different genetic codes */
            }
        
        /* Let's see if the prior is the same. */
        if (modelParams[part1].dataType == STANDARD && modelParams[part2].dataType == STANDARD)
            {
            /* The data are morphological (STANDARD). The state frequencies are specified by a
               symmetric beta distribution, the parameter of which needs to be the same to apply to both
               partitions. Note that symPiPr = -1 is equivalent to setting the variance to 0.0. */
            if (!strcmp(modelParams[part1].symPiPr,"Uniform") && !strcmp(modelParams[part2].symPiPr,"Uniform"))
                {
                if (AreDoublesEqual (modelParams[part1].symBetaUni[0], modelParams[part2].symBetaUni[0], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].symBetaUni[1], modelParams[part2].symBetaUni[1], (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (modelParams[part1].numBetaCats != modelParams[part2].numBetaCats)
                    isSame = NO;    /* can't link because the discrete beta approximation is different */
                }
            else if (!strcmp(modelParams[part1].symPiPr,"Exponential") && !strcmp(modelParams[part2].symPiPr,"Exponential"))
                {
                if (AreDoublesEqual (modelParams[part1].symBetaExp, modelParams[part2].symBetaExp, (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (modelParams[part1].numBetaCats != modelParams[part2].numBetaCats)
                    isSame = NO;    /* can't link because the discrete beta approximation is different */
                }
            else if (!strcmp(modelParams[part1].symPiPr,"Fixed") && !strcmp(modelParams[part2].symPiPr,"Fixed"))
                {
                if (AreDoublesEqual (modelParams[part1].symBetaFix, modelParams[part2].symBetaFix, (MrBFlt) 0.00001) == NO)
                    isSame = NO;
                if (AreDoublesEqual (modelParams[part1].symBetaFix, (MrBFlt) -1.0, (MrBFlt) 0.00001) == NO && modelParams[part1].numBetaCats != modelParams[part2].numBetaCats)
                    isSame = NO;    /* can't link because the discrete beta approximation is different */
                }
            else
                isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */
            }
        if (modelSettings[part1].dataType == PROTEIN && modelSettings[part2].dataType == PROTEIN)
            {
            /* We are dealing with protein data. */
            if (!strcmp(modelParams[part1].aaModelPr, modelParams[part2].aaModelPr))
                {
                if (!strcmp(modelParams[part1].aaModelPr, "Fixed"))
                    {
                    /* only have a single, fixed, amino acid rate matrix */
                    if (!strcmp(modelParams[part1].aaModel, modelParams[part2].aaModel))
                        {}
                    else
                        isSame = NO; /* we have different amino acid models, and the state frequencies must be different */
                    /* if we have an equalin model or Gtr model, then we need to check the prior on the state frequencies */
                    if (!strcmp(modelParams[part1].aaModel, "Equalin") || !strcmp(modelParams[part1].aaModel, "Gtr"))
                        {
                        if (!strcmp(modelParams[part1].stateFreqPr, modelParams[part2].stateFreqPr))
                            {
                            /* the prior form is the same */
                            if (!strcmp(modelParams[part1].stateFreqPr, "Dirichlet")) /* both prior models must be dirichlet */
                                {
                                for (i=0; i<modelParams[part1].nStates; i++)
                                    if (AreDoublesEqual (modelParams[part1].stateFreqsDir[i], modelParams[part2].stateFreqsDir[i], (MrBFlt) 0.00001) == NO)
                                        isSame = NO; /* the dirichlet parameters are different */
                                }
                            else /* both prior models must be fixed */
                                {
                                if (!strcmp(modelParams[part1].stateFreqsFixType, modelParams[part2].stateFreqsFixType))
                                    {
                                    /* if (!strcmp(modelParams[part1].stateFreqsFixType, "Empirical"))
                                        isSame = NO;     Even though it is unlikely that the empirical values for both partitions are exactly the same, we will
                                                         allow isSame to equal YES. This means pooled base frequencies are used to determine the empirical
                                                         base frequencies. The user can still unlink this parameter. */
                                    if (!strcmp(modelParams[part1].stateFreqsFixType, "User"))
                                        {
                                        for (i=0; i<modelParams[part1].nStates; i++)
                                            if (AreDoublesEqual (modelParams[part1].stateFreqsDir[i], modelParams[part2].stateFreqsDir[i], (MrBFlt) 0.00001) == NO)
                                                isSame = NO; /* the user-specified base frequencies are different */
                                        }
                                    /* if the frequencies were both fixed to "equal", we are golden, and they are the same */
                                    }
                                else
                                    isSame = NO; /* the fixed parameters must be the same. The only other possibility is that the
                                                    user specified equal or empirical for one partition and then specified specific
                                                    numbers (user) for the other _and_ happened to set the user values to the equal
                                                    or empirical values. We ignore this possibility. */
                                }
                            }
                        }
                    }
                else
                    {
                    /* averaging over models */
                    if (linkTable[P_AAMODEL][part1] != linkTable[P_AAMODEL][part2])
                        isSame = NO; /* the amino acid model is mixed, but independently estimated */
                    }
                }
            }
        else
            {
            /* Otherwise, we are dealing with RESTRICTION or NUCLEOTIDE data. The dirichlet should be the same
               for both partitions. */
            if (!strcmp(modelParams[part1].stateFreqPr, modelParams[part2].stateFreqPr))
                {
                /* the prior form is the same */
                if (!strcmp(modelParams[part1].stateFreqPr, "Dirichlet")) /* both prior models must be dirichlet */
                    {
                    for (i=0; i<modelParams[part1].nStates; i++)
                        if (AreDoublesEqual (modelParams[part1].stateFreqsDir[i], modelParams[part2].stateFreqsDir[i], (MrBFlt) 0.00001) == NO)
                            isSame = NO; /* the dirichlet parameters are different */
                    }
                else /* both prior models must be fixed */
                    {
                    if (!strcmp(modelParams[part1].stateFreqsFixType, modelParams[part2].stateFreqsFixType))
                        {
                        /* if (!strcmp(modelParams[part1].stateFreqsFixType, "Empirical"))
                            isSame = NO;     Even though it is unlikely that the empirical values for both partitions are exactly the same, we will
                                             allow isSame to equal YES. This means pooled base frequencies are used to determine the empirical
                                             base frequencies. The user can still unlink this parameter. */
                        if (!strcmp(modelParams[part1].stateFreqsFixType, "User"))
                            {
                            for (i=0; i<modelParams[part1].nStates; i++)
                                if (AreDoublesEqual (modelParams[part1].stateFreqsDir[i], modelParams[part2].stateFreqsDir[i], (MrBFlt) 0.00001) == NO)
                                    isSame = NO; /* the user-specified base frequencies are different */
                            }
                        /* if the frequencies were both fixed to "equal", we are golden, and they are the same */
                        }
                    else
                        isSame = NO; /* the fixed parameters must be the same. The only other possibility is that the
                                        user specified equal or empirical for one partition and then specified specific
                                        numbers (user) for the other _and_ happened to set the user values to the equal
                                        or empirical values. We ignore this possibility. */
                    }
                }
            }

        /* Check to see if the state frequencies are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO; /* if the state frequencies are inapplicable for either partition, then the parameter cannot be the same */
        }
    else if (whichParam == P_SHAPE)
        {
        /* Check the shape parameter for partitions 1 and 2. */
        
        /* Check if the model is parsimony for either partition */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; /* part1 has a parsimony model and shape parameter does not apply */
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; /* part2 has a parsimony model and shape parameter does not apply */

        /* Check that the data are not CONTINUOUS for partitions 1 and 2 */
        if (modelParams[part1].dataType == CONTINUOUS)
            *isApplic1 = NO; /* the shape parameter does not make sense for part1 */
        if (modelParams[part2].dataType == CONTINUOUS)
            *isApplic2 = NO; /* the shape parameter does not make sense for part2 */

        /* Now, check that the data are the same (i.e., both nucleotide or both amino acid, or whatever). */
        if (isFirstNucleotide != isSecondNucleotide)
            isSame = NO; /* data are not both nucleotide */
        else if (modelParams[part1].dataType != modelParams[part2].dataType && isFirstNucleotide == NO)
            isSame = NO; /* data are not the same */

        /* Let's check that the shape parameter is even relevant for the two partitions */
        if (!strcmp(modelParams[part1].ratesModel, "Equal") || !strcmp(modelParams[part1].ratesModel, "Propinv"))
            *isApplic1 = NO; /* the shape parameter does not make sense for part1 */
        if (!strcmp(modelParams[part2].ratesModel, "Equal") || !strcmp(modelParams[part2].ratesModel, "Propinv"))
            *isApplic2 = NO; /* the shape parameter does not make sense for part2 */
        
        /* We may have a nucleotide model. Make certain the models are not of type codon. */
        if (!strcmp(modelParams[part1].nucModel, "Codon"))
            *isApplic1 = NO; /* we have a codon model for part1, and a shape parameter does not apply */
        if (!strcmp(modelParams[part2].nucModel, "Codon"))
            *isApplic2 = NO;/* we have a codon model for part2, and a shape parameter does not apply */

        /* Check that the model structure is the same for both partitions */
        if ((!strcmp(modelParams[part1].nucModel, "4by4") || !strcmp(modelParams[part1].nucModel, "Doublet")) && !strcmp(modelParams[part2].nucModel, "Codon"))
            isSame = NO; /* the nucleotide models are incompatible with the same shape parameter */
        if ((!strcmp(modelParams[part2].nucModel, "4by4") || !strcmp(modelParams[part2].nucModel, "Doublet")) && !strcmp(modelParams[part1].nucModel, "Codon"))
            isSame = NO; /* the nucleotide models are incompatible with the same shape parameter */
        /* if (strcmp(modelParams[part1].covarionModel, modelParams[part2].covarionModel))
            isSame = NO; */ /* the models have different covarion struture */
        /* NOTE: Perhaps we should allow the possiblity that the shape parameter is the same for the case
                 where one partition has a covarion model but the other does not and both datatypes are the same. */
        
        /* Check that the number of rate categories is the same */
        if (modelParams[part1].numGammaCats != modelParams[part2].numGammaCats)
            isSame = NO; /* the number of rate categories is not the same, so we cannot set the parameter to be equal for both partitions */

        /* Check that the priors are the same. */
        if (!strcmp(modelParams[part1].shapePr,"Uniform") && !strcmp(modelParams[part2].shapePr,"Uniform"))
            {
            if (AreDoublesEqual (modelParams[part1].shapeUni[0], modelParams[part2].shapeUni[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].shapeUni[1], modelParams[part2].shapeUni[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].shapePr,"Exponential") && !strcmp(modelParams[part2].shapePr,"Exponential"))
            {
            if (AreDoublesEqual (modelParams[part1].shapeExp, modelParams[part2].shapeExp, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].shapePr,"Fixed") && !strcmp(modelParams[part2].shapePr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].shapeFix, modelParams[part2].shapeFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */
        
        /* Check to see if the shape parameter is inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO; /* if the shape parameter is inapplicable for either partition, then the parameter cannot be the same */
        }
    else if (whichParam == P_PINVAR)
        {
        /* Check the proportion of invariable sites parameter for partitions 1 and 2. */
        
        /* Check if the model is parsimony for either partition */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; /* part1 has a parsimony model and proportion of invariable sites parameter does not apply */
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; /* part2 has a parsimony model and proportion of invariable sites parameter does not apply */

        /* Check that the data are not CONTINUOUS for partitions 1 and 2 */
        if (modelParams[part1].dataType == CONTINUOUS)
            *isApplic1 = NO; /* the proportion of invariable sites parameter does not make sense for part1 */
        if (modelParams[part2].dataType == CONTINUOUS)
            *isApplic2 = NO; /* the proportion of invariable sites parameter does not make sense for part2 */

        /* Now, check that the data are the same (i.e., both nucleotide or both amino acid, or whatever). */
        if (isFirstNucleotide != isSecondNucleotide)
            isSame = NO; /* data are not both nucleotide */
        else if (modelParams[part1].dataType != modelParams[part2].dataType && isFirstNucleotide == NO)
            isSame = NO; /* data are not the same */

        /* Let's check that proportion of invariable sites parameter is even relevant for the two partitions */
        if (!strcmp(modelParams[part1].ratesModel, "Equal") || !strcmp(modelParams[part1].ratesModel, "Gamma") ||
            !strcmp(modelParams[part1].ratesModel, "LNorm") || !strcmp(modelParams[part1].ratesModel, "Adgamma"))
            *isApplic1 = NO; /* the proportion of invariable sites parameter does not make sense for part1 */
        if (!strcmp(modelParams[part2].ratesModel, "Equal") || !strcmp(modelParams[part2].ratesModel, "Gamma") ||
            !strcmp(modelParams[part2].ratesModel, "LNorm") || !strcmp(modelParams[part2].ratesModel, "Adgamma"))
            *isApplic2 = NO; /* the proportion of invariable sites parameter does not make sense for part2 */
            
        /* It is not sensible to have a covarion model and a proportion of invariable sites */
        if (!strcmp(modelParams[part1].covarionModel, "Yes"))
            *isApplic1 = NO;
        if (!strcmp(modelParams[part2].covarionModel, "Yes"))
            *isApplic2 = NO;
        
        /* We have a nucleotide model. Make certain the models are not of type codon. */
        if (!strcmp(modelParams[part1].nucModel, "Codon"))
            *isApplic1 = NO; /* we have a codon model for part1, and a proportion of invariable sites parameter does not apply */
        if (!strcmp(modelParams[part2].nucModel, "Codon"))
            *isApplic2 = NO;/* we have a codon model for part2, and a proportion of invariable sites parameter does not apply */

        /* Check that the model structure is the same for both partitions */
        if (strcmp(modelParams[part1].nucModel, modelParams[part2].nucModel))
            isSame = NO; /* the nucleotide models are different */
        if (strcmp(modelParams[part1].covarionModel, modelParams[part2].covarionModel))
            isSame = NO; /* the models have different covarion struture */
        
        /* check the priors */
        if (!strcmp(modelParams[part1].pInvarPr,"Uniform") && !strcmp(modelParams[part2].pInvarPr,"Uniform"))
            {
            if (AreDoublesEqual (modelParams[part1].pInvarUni[0], modelParams[part2].pInvarUni[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].pInvarUni[1], modelParams[part2].pInvarUni[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].pInvarPr,"Fixed") && !strcmp(modelParams[part2].pInvarPr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].pInvarFix, modelParams[part2].pInvarFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */
        
        /* Check to see if the switching rates are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO; /* if the switching rates are inapplicable for either partition, then the parameter cannot be the same */
        }
    else if (whichParam == P_CORREL)
        {
        /* Check the autocorrelation parameter for gamma rates on partitions 1 and 2. */
        
        /* Check if the model is parsimony for either partition */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; /* part1 has a parsimony model and autocorrelation parameter does not apply */
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; /* part2 has a parsimony model and autocorrelation parameter does not apply */

        /* Check that the data are either DNA, RNA, or PROTEIN for partitions 1 and 2 */
        if (modelSettings[part1].dataType != DNA && modelSettings[part1].dataType != RNA && modelSettings[part1].dataType != PROTEIN)
            *isApplic1 = NO; /* the switching rates do not make sense for part1 */
        if (modelSettings[part2].dataType != DNA && modelSettings[part2].dataType != RNA && modelSettings[part2].dataType != PROTEIN)
            *isApplic2 = NO; /* the switching rates do not make sense for part2 */
            
        /* Now, check that the data are the same (i.e., both nucleotide or both amino acid). */
        if (isFirstNucleotide != isSecondNucleotide)
            isSame = NO; /* one or the other is nucleotide, so they cannot be the same */
        else if (modelSettings[part1].dataType != modelSettings[part2].dataType && isFirstNucleotide == NO)
            isSame = NO; /* data are not both nucleotide or both amino acid */

        /* Let's check that autocorrelation parameter is even relevant for the two partitions */
        if (strcmp(modelParams[part1].ratesModel, "Adgamma"))
            *isApplic1 = NO; /* the autocorrelation parameter does not make sense for part1 */
        if (strcmp(modelParams[part2].ratesModel, "Adgamma"))
            *isApplic2 = NO; /* the autocorrelation parameter does not make sense for part2 */

        /* Assuming that we have a nucleotide model, make certain the models are not of type codon. */
        if (!strcmp(modelParams[part1].nucModel, "Codon"))
            *isApplic1 = NO; /* we have a codon model for part1, and a autocorrelation parameter does not apply */
        if (!strcmp(modelParams[part2].nucModel, "Codon"))
            *isApplic2 = NO; /* we have a codon model for part2, and a autocorrelation parameter does not apply */
        
        /* Check that the model structure is the same for both partitions */
        if (strcmp(modelParams[part1].nucModel, modelParams[part2].nucModel))
            isSame = NO; /* the nucleotide models are different */
        if (strcmp(modelParams[part1].covarionModel, modelParams[part2].covarionModel))
            isSame = NO; /* the models have different covarion struture */

        /* Check the priors for both partitions. */
        if (!strcmp(modelParams[part1].adGammaCorPr,"Uniform") && !strcmp(modelParams[part2].adGammaCorPr,"Uniform"))
            {
            if (AreDoublesEqual (modelParams[part1].corrUni[0], modelParams[part2].corrUni[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].corrUni[1], modelParams[part2].corrUni[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].adGammaCorPr,"Fixed") && !strcmp(modelParams[part2].adGammaCorPr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].corrFix, modelParams[part2].corrFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */

        /* Check to see if the switching rates are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO; /* if the switching rates are inapplicable for either partition, then the parameter cannot be the same */
        }
    else if (whichParam == P_SWITCH)
        {
        /* Check the covarion switching rates on partitions 1 and 2. */
        
        /* Check if the model is parsimony for either partition */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; /* part1 has a parsimony model and switching rates do not apply */
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; /* part2 has a parsimony model and switching rates do not apply */
        
        /* Check that the data are either DNA, RNA, or PROTEIN for partitions 1 and 2 */
        if (modelSettings[part1].dataType != DNA && modelSettings[part1].dataType != RNA && modelSettings[part1].dataType != PROTEIN)
            *isApplic1 = NO; /* the switching rates do not make sense for part1 */
        if (modelSettings[part2].dataType != DNA && modelSettings[part2].dataType != RNA && modelSettings[part2].dataType != PROTEIN)
            *isApplic2 = NO; /* the switching rates do not make sense for part2 */
            
        /* Now, check that the data are the same (i.e., both nucleotide or both amino acid). */
        if (isFirstNucleotide != isSecondNucleotide)
            isSame = NO; /* one or the other is nucleotide, so they cannot be the same */
        else if (modelSettings[part1].dataType != modelSettings[part2].dataType && isFirstNucleotide == NO)
            isSame = NO; /* data are not both nucleotide or both amino acid */

        /* Lets check that covarion model has been selected for partitions 1 and 2 */
        if (!strcmp(modelParams[part1].covarionModel, "No"))
            *isApplic1 = NO; /* the switching rates do not make sense for part1 */
        if (!strcmp(modelParams[part2].covarionModel, "No"))
            *isApplic2 = NO; /* the switching rates do not make sense for part2 */

        /* If we have a nucleotide model make certain the models are not of type codon or doublet. */
        if (!strcmp(modelParams[part1].nucModel, "Codon") || !strcmp(modelParams[part1].nucModel, "Doublet"))
            *isApplic1 = NO; /* we have a codon model for part1, and a covarion switch parameter does not apply */
        if (!strcmp(modelParams[part2].nucModel, "Codon") || !strcmp(modelParams[part2].nucModel, "Doublet"))
            *isApplic2 = NO; /* we have a codon model for part2, and a covarion switch parameter does not apply */

        /* Check that the priors are the same. */
        if (!strcmp(modelParams[part1].covSwitchPr,"Uniform") && !strcmp(modelParams[part2].covSwitchPr,"Uniform"))
            {
            if (AreDoublesEqual (modelParams[part1].covswitchUni[0], modelParams[part2].covswitchUni[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].covswitchUni[1], modelParams[part2].covswitchUni[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].covSwitchPr,"Exponential") && !strcmp(modelParams[part2].covSwitchPr,"Exponential"))
            {
            if (AreDoublesEqual (modelParams[part1].covswitchExp, modelParams[part2].covswitchExp, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].covSwitchPr,"Fixed") && !strcmp(modelParams[part2].covSwitchPr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].covswitchFix[0], modelParams[part2].covswitchFix[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].covswitchFix[1], modelParams[part2].covswitchFix[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */

        /* Check to see if the switching rates are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO; /* if the switching rates are inapplicable for either partition, then the parameter cannot be the same */
        }
    else if (whichParam == P_RATEMULT)
        {
        /* Check if the model is parsimony for either partition. If so, then the branch lengths cannot apply (as parsimony is very
           silly and doesn't take this information into account) and a rate multiplier is nonsensical. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; 
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; 
        
        /* Check that the branch lengths are at least proportional. */
        if (IsModelSame (P_BRLENS, part1, part2, &temp1, &temp2) == NO)
            isSame = NO;
        if (linkTable[P_BRLENS][part1] != linkTable[P_BRLENS][part2])
            isSame = NO;

        /* See if the rate prior is the same for the partitions */
        if (strcmp(modelParams[part1].ratePr, modelParams[part2].ratePr) != 0)
            isSame = NO;

        /* Check to see if rate multipliers are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO; 
            
        }
    else if (whichParam == P_TOPOLOGY)
        {
        /* Check the topology for partitions 1 and 2. */
        
        /* If the prior is different, then the topologies cannot be the same. */
        if (strcmp(modelParams[part1].topologyPr, modelParams[part2].topologyPr))
            isSame = NO;

        /* If both partitions have topologies constrained, then we need to make certain that the constraints are the same. */
        /* This also guarantees that any calibrations will be the same. */
        if (!strcmp(modelParams[part1].topologyPr, "Constraints") && !strcmp(modelParams[part2].topologyPr, "Constraints"))
            {
            if (modelParams[part1].numActiveConstraints != modelParams[part2].numActiveConstraints)
                isSame = NO;
            else
                {
                nDiff = 0;
                for (i=0; i<numDefinedConstraints; i++)
                    if (modelParams[part1].activeConstraints[i] != modelParams[part2].activeConstraints[i])
                        nDiff++;
                if (nDiff != 0)
                    isSame = NO;
                }
            }
        }
    else if (whichParam == P_BRLENS)
        {
        /* Check the branch lengths for partitions 1 and 2. */

        /* First, if the topologies are different, the same branch lengths cannot apply. */
        if (IsModelSame (P_TOPOLOGY, part1, part2, &temp1, &temp2) == NO)
            isSame = NO;
        if (linkTable[P_TOPOLOGY][part1] != linkTable[P_TOPOLOGY][part2])
            isSame = NO;

        /* Check if the model is parsimony for either partition. If so, then the branch lengths cannot apply (as parsimony is very
           silly and doesn't take this information into account). */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; 
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO;

        /* Check to see if the branch lengths are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;

        /* Make sure the branch lengths have the same priors and are not unlinked */
        if (*isApplic1 == YES && *isApplic2 == YES)
            {
            /* We are dealing with real branch lengths (not parsimony) for both partitions */
            
            /* The branch length prior should be the same */
            if (strcmp(modelParams[part1].brlensPr, modelParams[part2].brlensPr))
                isSame = NO;
                
            /* if both partitions have unconstrained brlens, then we need to check that the priors on the branch lengths are the same */
            if (!strcmp(modelParams[part1].brlensPr, "Unconstrained") && !strcmp(modelParams[part2].brlensPr, "Unconstrained"))
                {
                if (strcmp(modelParams[part1].unconstrainedPr, modelParams[part2].unconstrainedPr))
                    isSame = NO;
                else
                    {
                    if (!strcmp(modelParams[part1].unconstrainedPr, "Uniform"))
                        {
                        if (AreDoublesEqual (modelParams[part1].brlensUni[0], modelParams[part2].brlensUni[0], (MrBFlt) 0.00001) == NO)
                            isSame = NO;
                        if (AreDoublesEqual (modelParams[part1].brlensUni[1], modelParams[part2].brlensUni[1], (MrBFlt) 0.00001) == NO)
                            isSame = NO;
                        }
                    else if (!strcmp(modelParams[part1].unconstrainedPr, "Exponential"))
                        {
                        if (AreDoublesEqual (modelParams[part1].brlensExp, modelParams[part2].brlensExp, (MrBFlt) 0.00001) == NO)
                            isSame = NO;
                        }
                    else if (!strcmp(modelParams[part1].unconstrainedPr, "twoExp"))
                        {
                            if (AreDoublesEqual (modelParams[part1].brlens2Exp[0], modelParams[part2].brlens2Exp[0], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            if (AreDoublesEqual (modelParams[part1].brlens2Exp[1], modelParams[part2].brlens2Exp[1], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                        }
                    else
                        {
                        if (AreDoublesEqual (modelParams[part1].brlensDir[0], modelParams[part2].brlensDir[0], (MrBFlt) 0.00001) == NO)  
                            isSame = NO;
                        if (AreDoublesEqual (modelParams[part1].brlensDir[1], modelParams[part2].brlensDir[1], (MrBFlt) 0.00001) == NO) 
                            isSame = NO;
                        if (AreDoublesEqual (modelParams[part1].brlensDir[2], modelParams[part2].brlensDir[2], (MrBFlt) 0.00001) == NO)  
                            isSame = NO;
                        if (AreDoublesEqual (modelParams[part1].brlensDir[3], modelParams[part2].brlensDir[3], (MrBFlt) 0.00001) == NO) 
                            isSame = NO;
                        }   
                    }
                }
            
            /* if both partitions have clock brlens, then we need to check that the priors on the clock are the same */
            if (!strcmp(modelParams[part1].brlensPr, "Clock") && !strcmp(modelParams[part2].brlensPr, "Clock"))
                {
                if (strcmp(modelParams[part1].clockPr, modelParams[part2].clockPr))
                    isSame = NO;
                else
                    {
                    if (!strcmp(modelParams[part1].clockPr, "Birthdeath"))
                        {
                        if (!strcmp(modelParams[part1].speciationPr,"Uniform") && !strcmp(modelParams[part2].speciationPr,"Uniform"))
                            {
                            if (AreDoublesEqual (modelParams[part1].speciationUni[0], modelParams[part2].speciationUni[0], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            if (AreDoublesEqual (modelParams[part1].speciationUni[1], modelParams[part2].speciationUni[1], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else if (!strcmp(modelParams[part1].speciationPr,"Exponential") && !strcmp(modelParams[part2].speciationPr,"Exponential"))
                            {
                            if (AreDoublesEqual (modelParams[part1].speciationExp, modelParams[part2].speciationExp, (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else if (!strcmp(modelParams[part1].speciationPr,"Fixed") && !strcmp(modelParams[part2].speciationPr,"Fixed"))
                            {
                            if (AreDoublesEqual (modelParams[part1].speciationFix, modelParams[part2].speciationFix, (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else
                            isSame = NO;

                        if (!strcmp(modelParams[part1].extinctionPr,"Beta") && !strcmp(modelParams[part2].extinctionPr,"Beta"))
                            {
                            if (AreDoublesEqual (modelParams[part1].extinctionBeta[0], modelParams[part2].extinctionBeta[0], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            if (AreDoublesEqual (modelParams[part1].extinctionBeta[1], modelParams[part2].extinctionBeta[1], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else if (!strcmp(modelParams[part1].extinctionPr,"Fixed") && !strcmp(modelParams[part2].extinctionPr,"Fixed"))
                            {
                            if (AreDoublesEqual (modelParams[part1].extinctionFix, modelParams[part2].extinctionFix, (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else
                            isSame = NO;

                        if (AreDoublesEqual (modelParams[part1].sampleProb, modelParams[part2].sampleProb, 0.00001) == NO)
                            isSame = NO;
                        if (strcmp(modelParams[part1].sampleStrat,modelParams[part2].sampleStrat))
                            isSame = NO;
                        }
                    else if (!strcmp(modelParams[part1].clockPr, "Coalescence") || !strcmp(modelParams[part1].clockPr, "Speciestreecoalescence"))
                        {
                        if (!strcmp(modelParams[part1].popSizePr,"Uniform") && !strcmp(modelParams[part2].popSizePr,"Uniform"))
                            {
                            if (AreDoublesEqual (modelParams[part1].popSizeUni[0], modelParams[part2].popSizeUni[0], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            if (AreDoublesEqual (modelParams[part1].popSizeUni[1], modelParams[part2].popSizeUni[1], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else if (!strcmp(modelParams[part1].popSizePr,"Lognormal") && !strcmp(modelParams[part2].popSizePr,"Lognormal"))
                            {
                            if (AreDoublesEqual (modelParams[part1].popSizeLognormal[0], modelParams[part2].popSizeLognormal[0], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            if (AreDoublesEqual (modelParams[part1].popSizeLognormal[1], modelParams[part2].popSizeLognormal[1], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else if (!strcmp(modelParams[part1].popSizePr,"Normal") && !strcmp(modelParams[part2].popSizePr,"Normal"))
                            {
                            if (AreDoublesEqual (modelParams[part1].popSizeNormal[0], modelParams[part2].popSizeNormal[0], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            if (AreDoublesEqual (modelParams[part1].popSizeNormal[1], modelParams[part2].popSizeNormal[1], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else if (!strcmp(modelParams[part1].popSizePr,"Gamma") && !strcmp(modelParams[part2].popSizePr,"Gamma"))
                            {
                            if (AreDoublesEqual (modelParams[part1].popSizeGamma[0], modelParams[part2].popSizeGamma[0], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            if (AreDoublesEqual (modelParams[part1].popSizeGamma[1], modelParams[part2].popSizeGamma[1], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else if (!strcmp(modelParams[part1].popSizePr,"Fixed") && !strcmp(modelParams[part2].popSizePr,"Fixed"))
                            {
                            if (AreDoublesEqual (modelParams[part1].popSizeFix, modelParams[part2].popSizeFix, (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else
                            isSame = NO;

                        if (strcmp(modelParams[part1].ploidy, modelParams[part2].ploidy) != 0)
                            isSame = NO;
                        }
                    if (strcmp(modelParams[part1].clockPr, "Uniform") == 0 && strcmp(modelParams[part1].nodeAgePr, "Calibrated") != 0)
                        {
                        if (modelParams[part1].treeAgePr.prior != modelParams[part2].treeAgePr.prior)
                            isSame = NO;
                        if (modelParams[part1].treeAgePr.prior == fixed)
                            {
                            if (AreDoublesEqual (modelParams[part1].treeAgePr.priorParams[0], modelParams[part2].treeAgePr.priorParams[0], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else if (modelParams[part1].treeAgePr.prior == offsetLogNormal ||
                            modelParams[part1].treeAgePr.prior == truncatedNormal ||
                            modelParams[part1].treeAgePr.prior == offsetGamma)
                            {
                            for (i=0; i<3; i++)
                                {
                                if (AreDoublesEqual (modelParams[part1].treeAgePr.priorParams[i], modelParams[part2].treeAgePr.priorParams[i], (MrBFlt) 0.00001) == NO)
                                    isSame = NO;
                                }
                            }
                        else
                            {
                            for (i=0; i<2; i++)
                                {
                                if (AreDoublesEqual (modelParams[part1].treeAgePr.priorParams[i], modelParams[part2].treeAgePr.priorParams[i], (MrBFlt) 0.00001) == NO)
                                    isSame = NO;
                                }
                            }
                        }
                    else if (strcmp(modelParams[part1].clockPr, "Fossilization") == 0)
                        {
                        if (modelParams[part1].treeAgePr.prior != modelParams[part2].treeAgePr.prior)
                            isSame = NO;
                        if (modelParams[part1].treeAgePr.prior == fixed)
                            {
                            if (AreDoublesEqual (modelParams[part1].treeAgePr.priorParams[0], modelParams[part2].treeAgePr.priorParams[0], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else if (modelParams[part1].treeAgePr.prior == offsetLogNormal ||
                            modelParams[part1].treeAgePr.prior == truncatedNormal ||
                            modelParams[part1].treeAgePr.prior == offsetGamma)
                            {
                            for (i=0; i<3; i++)
                                {
                                if (AreDoublesEqual (modelParams[part1].treeAgePr.priorParams[i], modelParams[part2].treeAgePr.priorParams[i], (MrBFlt) 0.00001) == NO)
                                    isSame = NO;
                                }
                            }
                        else
                            {
                            for (i=0; i<2; i++)
                                {
                                if (AreDoublesEqual (modelParams[part1].treeAgePr.priorParams[i], modelParams[part2].treeAgePr.priorParams[i], (MrBFlt) 0.00001) == NO)
                                    isSame = NO;
                                }
                            }
                        
                        if (!strcmp(modelParams[part1].speciationPr,"Uniform") && !strcmp(modelParams[part2].speciationPr,"Uniform"))
                            {
                            if (AreDoublesEqual (modelParams[part1].speciationUni[0], modelParams[part2].speciationUni[0], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            if (AreDoublesEqual (modelParams[part1].speciationUni[1], modelParams[part2].speciationUni[1], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else if (!strcmp(modelParams[part1].speciationPr,"Exponential") && !strcmp(modelParams[part2].speciationPr,"Exponential"))
                            {
                            if (AreDoublesEqual (modelParams[part1].speciationExp, modelParams[part2].speciationExp, (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else if (!strcmp(modelParams[part1].speciationPr,"Fixed") && !strcmp(modelParams[part2].speciationPr,"Fixed"))
                            {
                            if (AreDoublesEqual (modelParams[part1].speciationFix, modelParams[part2].speciationFix, (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else
                            isSame = NO;
                        
                        if (!strcmp(modelParams[part1].extinctionPr,"Beta") && !strcmp(modelParams[part2].extinctionPr,"Beta"))
                            {
                            if (AreDoublesEqual (modelParams[part1].extinctionBeta[0], modelParams[part2].extinctionBeta[0], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            if (AreDoublesEqual (modelParams[part1].extinctionBeta[1], modelParams[part2].extinctionBeta[1], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else if (!strcmp(modelParams[part1].extinctionPr,"Fixed") && !strcmp(modelParams[part2].extinctionPr,"Fixed"))
                            {
                            if (AreDoublesEqual (modelParams[part1].extinctionFix, modelParams[part2].extinctionFix, (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else
                            isSame = NO;
                        
                        if (!strcmp(modelParams[part1].fossilizationPr,"Beta") && !strcmp(modelParams[part2].fossilizationPr,"Beta"))
                            {
                            if (AreDoublesEqual (modelParams[part1].fossilizationBeta[0], modelParams[part2].fossilizationBeta[0], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            if (AreDoublesEqual (modelParams[part1].fossilizationBeta[1], modelParams[part2].fossilizationBeta[1], (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else if (!strcmp(modelParams[part1].fossilizationPr,"Fixed") && !strcmp(modelParams[part2].fossilizationPr,"Fixed"))
                            {
                            if (AreDoublesEqual (modelParams[part1].fossilizationFix, modelParams[part2].fossilizationFix, (MrBFlt) 0.00001) == NO)
                                isSame = NO;
                            }
                        else
                            isSame = NO;
                        
                        if (AreDoublesEqual (modelParams[part1].sampleProb, modelParams[part2].sampleProb, 0.00001) == NO)
                            isSame = NO;
                        if (strcmp(modelParams[part1].sampleStrat,modelParams[part2].sampleStrat))
                            isSame = NO;
                        }
                    }

                /* if the same clock prior, we need to check calibrations */
                if (strcmp(modelParams[part1].nodeAgePr,modelParams[part2].nodeAgePr) != 0)
                    isSame = NO;
                
                /* If fixed clock brlens, check if the brlens come from the same tree */
                if (!strcmp(modelParams[part1].clockPr, "Fixed") && !strcmp(modelParams[part2].clockPr, "Fixed"))
                    {
                    if (modelParams[part1].brlensFix != modelParams[part2].brlensFix)
                        isSame = NO;
                    }
                }
            /* If fixed brlens, check if the brlens come from the same tree */
            if (!strcmp(modelParams[part1].brlensPr, "Fixed") && !strcmp(modelParams[part2].brlensPr, "Fixed"))
                {
                if (modelParams[part1].brlensFix != modelParams[part2].brlensFix)
                    isSame = NO;
                }
            }
        }
    else if (whichParam == P_SPECRATE)
        {
        /* Check the speciation rates for partitions 1 and 2. */

        /* Check if the model is parsimony for either partition. If so, then the branch lengths cannot apply (as parsimony is very
           silly and doesn't take this information into account) and a speciation rate cannot be estimated. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; 
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; 
            
        /* Check that the branch length prior is a clock:birthdeath or clock:fossilization for both partitions. */
        if (strcmp(modelParams[part1].brlensPr, "Clock"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].brlensPr, "Clock"))
            *isApplic2 = NO;
        if (strcmp(modelParams[part1].clockPr, "Birthdeath") != 0 && strcmp(modelParams[part1].clockPr, "Fossilization") != 0)
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].clockPr, "Birthdeath") != 0 && strcmp(modelParams[part2].clockPr, "Fossilization") != 0)
            *isApplic2 = NO;
        
        /* Now, check that the prior on the speciation rates are the same. */
        if (!strcmp(modelParams[part1].speciationPr,"Uniform") && !strcmp(modelParams[part2].speciationPr,"Uniform"))
            {
            if (AreDoublesEqual (modelParams[part1].speciationUni[0], modelParams[part2].speciationUni[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].speciationUni[1], modelParams[part2].speciationUni[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].speciationPr,"Exponential") && !strcmp(modelParams[part2].speciationPr,"Exponential"))
            {
            if (AreDoublesEqual (modelParams[part1].speciationExp, modelParams[part2].speciationExp, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].speciationPr,"Fixed") && !strcmp(modelParams[part2].speciationPr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].speciationFix, modelParams[part2].speciationFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO;
        
        /* Check to see if the speciation rates are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;
        }
    else if (whichParam == P_EXTRATE)
        {
        /* Check the extinction rates for partitions 1 and 2. */

        /* Check if the model is parsimony for either partition. If so, then the branch lengths cannot apply (as parsimony is very
           silly and doesn't take this information into account) and a extinction rate cannot be estimated. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; 
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; 
            
        /* Check that the branch length prior is a clock:birthdeath or clock:fossilization for both partitions. */
        if (strcmp(modelParams[part1].brlensPr, "Clock"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].brlensPr, "Clock"))
            *isApplic2 = NO;
        if (strcmp(modelParams[part1].clockPr, "Birthdeath")!= 0 && strcmp(modelParams[part1].clockPr, "Fossilization") != 0)
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].clockPr, "Birthdeath")!= 0 && strcmp(modelParams[part2].clockPr, "Fossilization") != 0)
            *isApplic2 = NO;
        
        /* Now, check that the prior on the extinction rates are the same. */
        if (!strcmp(modelParams[part1].extinctionPr,"Beta") && !strcmp(modelParams[part2].extinctionPr,"Beta"))
            {
            if (AreDoublesEqual (modelParams[part1].extinctionBeta[0], modelParams[part2].extinctionBeta[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].extinctionBeta[1], modelParams[part2].extinctionBeta[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].extinctionPr,"Fixed") && !strcmp(modelParams[part2].extinctionPr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].extinctionFix, modelParams[part2].extinctionFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO;
        
        /* Check to see if the extinction rates are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;
        }
    else if (whichParam == P_FOSLRATE)
        {
        /* Check the fossilization rates for partitions 1 and 2. */
        
        /* Check if the model is parsimony for either partition. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO;
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO;
        
        /* Check that the branch length prior is a clock:birthdeath or clock:fossilization for both partitions. */
        if (strcmp(modelParams[part1].brlensPr, "Clock"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].brlensPr, "Clock"))
            *isApplic2 = NO;
        if (strcmp(modelParams[part1].clockPr, "Fossilization") != 0)
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].clockPr, "Fossilization") != 0)
            *isApplic2 = NO;
        
        /* Now, check that the prior on the fossilization rates are the same. */
        if (!strcmp(modelParams[part1].fossilizationPr,"Beta") && !strcmp(modelParams[part2].fossilizationPr,"Beta"))
            {
            if (AreDoublesEqual (modelParams[part1].fossilizationBeta[0], modelParams[part2].fossilizationBeta[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].fossilizationBeta[1], modelParams[part2].fossilizationBeta[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].fossilizationPr,"Fixed") && !strcmp(modelParams[part2].fossilizationPr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].fossilizationFix, modelParams[part2].fossilizationFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO;
        
        /* Check to see if the fossilization rates are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;
        }
    else if (whichParam == P_POPSIZE)
        {
        /* Check population size for partitions 1 and 2. */

        /* Check if the model is parsimony for either partition. If so, then the branch lengths cannot apply (as parsimony is very
           silly and doesn't take this information into account) and population size cannot be estimated. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; 
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; 
            
        /* Check that the branch length prior is a clock:coalescence or clock:speciestreecoalescence for both partitions. */
        if (strcmp(modelParams[part1].brlensPr, "Clock"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].brlensPr, "Clock"))
            *isApplic2 = NO;
        if (strcmp(modelParams[part1].clockPr, "Coalescence") != 0 && strcmp(modelParams[part1].clockPr, "Speciestreecoalescence") != 0)
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].clockPr, "Coalescence") != 0 && strcmp(modelParams[part2].clockPr, "Speciestreecoalescence") != 0)
            *isApplic2 = NO;
        
        /* Now, check that the prior on population size is the same. */
        if (!strcmp(modelParams[part1].popSizePr,"Uniform") && !strcmp(modelParams[part2].popSizePr,"Uniform"))
            {
            if (AreDoublesEqual (modelParams[part1].popSizeUni[0], modelParams[part2].popSizeUni[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].popSizeUni[1], modelParams[part2].popSizeUni[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].popSizePr,"Lognormal") && !strcmp(modelParams[part2].popSizePr,"Lognormal"))
            {
            if (AreDoublesEqual (modelParams[part1].popSizeLognormal[0], modelParams[part2].popSizeLognormal[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].popSizeLognormal[1], modelParams[part2].popSizeLognormal[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].popSizePr,"Normal") && !strcmp(modelParams[part2].popSizePr,"Normal"))
            {
            if (AreDoublesEqual (modelParams[part1].popSizeNormal[0], modelParams[part2].popSizeNormal[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].popSizeNormal[1], modelParams[part2].popSizeNormal[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].popSizePr,"Gamma") && !strcmp(modelParams[part2].popSizePr,"Gamma"))
            {
            if (AreDoublesEqual (modelParams[part1].popSizeGamma[0], modelParams[part2].popSizeGamma[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].popSizeGamma[1], modelParams[part2].popSizeGamma[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].popSizePr,"Fixed") && !strcmp(modelParams[part2].popSizePr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].popSizeFix, modelParams[part2].popSizeFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO;
        
        /* Check to see if population size is inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;
        }
    else if (whichParam == P_GROWTH)
        {
        /* Check growth rate for partitions 1 and 2. */

        /* Check if the model is parsimony for either partition. If so, then the branch lengths cannot apply (as parsimony is very
           silly and doesn't take this information into account) and growth rate cannot be estimated. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; 
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; 
            
        /* Check that the branch length prior is a clock:coalescence for both partitions. */
        if (strcmp(modelParams[part1].brlensPr, "Clock"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].brlensPr, "Clock"))
            *isApplic2 = NO;
        if (strcmp(modelParams[part1].clockPr, "Coalescence"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].clockPr, "Coalescence"))
            *isApplic2 = NO;
        
        /* Now, check that the prior on growth rate is the same. */
        if (!strcmp(modelParams[part1].growthPr,"Uniform") && !strcmp(modelParams[part2].growthPr,"Uniform"))
            {
            if (AreDoublesEqual (modelParams[part1].growthUni[0], modelParams[part2].growthUni[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].growthUni[1], modelParams[part2].growthUni[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].growthPr,"Exponential") && !strcmp(modelParams[part2].growthPr,"Exponential"))
            {
            if (AreDoublesEqual (modelParams[part1].growthExp, modelParams[part2].growthExp, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].growthPr,"Fixed") && !strcmp(modelParams[part2].growthPr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].growthFix, modelParams[part2].growthFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO;
        
        /* Check to see if growth rate is inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO; 
        }
    else if (whichParam == P_AAMODEL)
        {
        /* Check the amino acid model settings for partitions 1 and 2. */

        /* Check if the model is parsimony for either partition */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; /* part1 has a parsimony model and aamodel does not apply */
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; /* part2 has a parsimony model and aamodel does not apply */
        
        /* Check that the data are protein for both partitions 1 and 2 */
        if (isFirstProtein == NO)
            *isApplic1 = NO; /* part1 is not amino acid data so tratio does not apply */
        if (isSecondProtein == NO)
            *isApplic2 = NO; /* part2 is not amino acid data so tratio does not apply */
            
        /* If the model is fixed for a partition, then it is not a free parameter and
           we set it to isApplic = NO */
        if (!strcmp(modelParams[part1].aaModelPr,"Fixed"))
            *isApplic1 = NO; 
        if (!strcmp(modelParams[part2].aaModelPr,"Fixed"))
            *isApplic2 = NO;

        /* We now need to check if the prior is the same for both. */
        if (!strcmp(modelParams[part1].aaModelPr,"Mixed") && !strcmp(modelParams[part2].aaModelPr,"Mixed"))
            {
            }
        else if (!strcmp(modelParams[part1].aaModelPr,"Fixed") && !strcmp(modelParams[part2].aaModelPr,"Fixed"))
            {
            if (strcmp(modelParams[part1].aaModel,modelParams[part2].aaModel))
                isSame = NO;
            }
        else
            isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */

        /* Check to see if amino acid model is inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO; /* if tratio is inapplicable for either partition, then the parameter cannot be the same */
        }
    else if (whichParam == P_BRCORR)
        {
        /* Check the correlation parameter for brownian motion 1 and 2. */
        
        /* Check that the data are either CONTINUOUS for partitions 1 and 2 */
        if (modelParams[part1].dataType != CONTINUOUS)
            *isApplic1 = NO; /* the correlation parameter does not make sense for part1 */
        if (modelParams[part2].dataType != CONTINUOUS)
            *isApplic2 = NO; /* the correlation parameter does not make sense for part2 */
            
        /* Now, check that the data are the same. */
        if (modelParams[part1].dataType != modelParams[part2].dataType)
            isSame = NO; /* data are not both continuous */

        /* Check the priors for both partitions. */
        if (!strcmp(modelParams[part1].brownCorPr,"Uniform") && !strcmp(modelParams[part2].brownCorPr,"Uniform"))
            {
            if (AreDoublesEqual (modelParams[part1].brownCorrUni[0], modelParams[part2].brownCorrUni[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].brownCorrUni[1], modelParams[part2].brownCorrUni[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].brownCorPr,"Fixed") && !strcmp(modelParams[part2].brownCorPr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].brownCorrFix, modelParams[part2].brownCorrFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */

        /* Check to see if the correlation parameters are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO; /* if the correlation parameters are inapplicable for either partition, then the parameter cannot be the same */
        }
    else if (whichParam == P_BRSIGMA)
        {
        /* Check the sigma parameter for brownian motion 1 and 2. */
        
        /* Check that the data are either CONTINUOUS for partitions 1 and 2 */
        if (modelParams[part1].dataType != CONTINUOUS)
            *isApplic1 = NO; /* the sigma parameter does not make sense for part1 */
        if (modelParams[part2].dataType != CONTINUOUS)
            *isApplic2 = NO; /* the sigma parameter does not make sense for part2 */
            
        /* Now, check that the data are the same. */
        if (modelParams[part1].dataType != modelParams[part2].dataType)
            isSame = NO; /* data are not both continuous */

        /* Check the priors for both partitions. */
        if (!strcmp(modelParams[part1].brownScalesPr,"Uniform") && !strcmp(modelParams[part2].brownScalesPr,"Uniform"))
            {
            if (AreDoublesEqual (modelParams[part1].brownScalesUni[0], modelParams[part2].brownScalesUni[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].brownScalesUni[1], modelParams[part2].brownScalesUni[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].brownScalesPr,"Fixed") && !strcmp(modelParams[part2].brownScalesPr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].brownScalesFix, modelParams[part2].brownScalesFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].brownScalesPr,"Gamma") && !strcmp(modelParams[part2].brownScalesPr,"Gamma"))
            {
            if (AreDoublesEqual (modelParams[part1].brownScalesGamma[0], modelParams[part2].brownScalesGamma[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].brownScalesGamma[1], modelParams[part2].brownScalesGamma[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].brownScalesPr,"Gammamean") && !strcmp(modelParams[part2].brownScalesPr,"Gammamean"))
            {
            if (AreDoublesEqual (modelParams[part1].brownScalesGammaMean, modelParams[part2].brownScalesGammaMean, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO; /* the priors are not the same, so we cannot set the parameter to be equal for both partitions */

        /* Check to see if the sigma parameters are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO; /* if the sigma parameters are inapplicable for either partition, then the parameter cannot be the same */
        }
    else if (whichParam == P_CPPRATE)
        {
        /* Check cpp rate for partitions 1 and 2. */
    
        /* Check if the model is parsimony for either partition. If so, then the branch lengths cannot apply (as parsimony is very
        silly and doesn't take this information into account) and cpp rate cannot be estimated. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; 
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO;

        /* Check that the branch length prior is clock for both partitions. */
        if (strcmp(modelParams[part1].brlensPr, "Clock"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].brlensPr, "Clock"))
            *isApplic2 = NO;

        /* Check that the clock rate prior is cpp for both partitions */
        if (strcmp(modelParams[part1].clockVarPr, "Cpp"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].clockVarPr, "Cpp"))
            *isApplic2 = NO;
        
        /* Now, check that the prior on cpp rate is the same. */
        if (!strcmp(modelParams[part1].cppRatePr,"Exponential") && !strcmp(modelParams[part2].cppRatePr,"Exponential"))
            {
            if (AreDoublesEqual (modelParams[part1].cppRateExp, modelParams[part2].cppRateExp, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].cppRatePr,"Fixed") && !strcmp(modelParams[part2].cppRatePr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].cppRateFix, modelParams[part2].cppRateFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO;
    
        /* Check to see if cpp rate is inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;    
        }
    else if (whichParam == P_CPPMULTDEV)
        {
        /* Check cpp multiplier deviation prior for partitions 1 and 2. */
        
        /* Check if the model is parsimony for either partition. If so, then the branch lengths cannot apply (as parsimony is very
        silly and doesn't take this information into account) and this parameter is inapplicable. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; 
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; 
        
        /* Check that the branch length prior is clock for both partitions. */
        if (strcmp(modelParams[part1].brlensPr, "Clock"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].brlensPr, "Clock"))
            *isApplic2 = NO;

        /* Check that the clock rate prior is cpp for both partitions */
        if (strcmp(modelParams[part1].clockVarPr, "Cpp"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].clockVarPr, "Cpp"))
            *isApplic2 = NO;
        
        /* Now, check that the prior on sigma is the same. */
        if (!strcmp(modelParams[part1].cppMultDevPr,"Fixed") && !strcmp(modelParams[part2].cppMultDevPr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].cppMultDevFix, modelParams[part2].cppMultDevFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO;
        
        /* Check to see if cpp multiplier sigma is inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;    
        }
    else if (whichParam == P_CPPEVENTS)
        {
        /* Check cpp events for partitions 1 and 2. */
    
        /* Check if the model is parsimony for either partition. If so, then branch lengths do not apply (as parsimony is very
        silly and doesn't take this information into account) and cpp events are inapplicable. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; 
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO;

        /* Check that the branch length prior is clock for both partitions. */
        if (strcmp(modelParams[part1].brlensPr, "Clock"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].brlensPr, "Clock"))
            *isApplic2 = NO;

        /* Check that the clock rate prior is cpp for both partitions */
        if (strcmp(modelParams[part1].clockVarPr, "Cpp"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].clockVarPr, "Cpp"))
            *isApplic2 = NO;
        
        /* Now, check that the cpp parameter is the same */
        if (IsModelSame (P_CPPRATE, part1, part2, &temp1, &temp2) == NO)
            isSame = NO;
        if (linkTable[P_CPPRATE][part1] != linkTable[P_CPPRATE][part2])
            isSame = NO;
    
        /* ... and that the psigamma parameter is the same */
        if (IsModelSame (P_CPPMULTDEV, part1, part2, &temp1, &temp2) == NO)
            isSame = NO;
        if (linkTable[P_CPPMULTDEV][part1] != linkTable[P_CPPRATE][part2])
            isSame = NO;
    
        /* Not same if branch lengths are not the same */
        if (IsModelSame(P_BRLENS, part1, part2, &temp1, &temp2) == NO)
            isSame = NO;
        if (linkTable[P_BRLENS][part1] != linkTable[P_BRLENS][part2])
            isSame = NO;

        /* Set isSame to NO if cpp events are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;
        }
    else if (whichParam == P_TK02VAR)
        {
        /* Check prior for variance of rate autocorrelation for partitions 1 and 2. */
        
        /* Check if the model is parsimony for either partition. If so, then the branch lengths cannot apply (as parsimony is very
        silly and doesn't take this information into account) and ratevar is inapplicable. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; 
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; 
        
        /* Check that the branch length prior is clock for both partitions. */
        if (strcmp(modelParams[part1].brlensPr, "Clock"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].brlensPr, "Clock"))
            *isApplic2 = NO;

        /* Check that the clock rate prior is tk02 for both partitions */
        if (strcmp(modelParams[part1].clockVarPr, "TK02"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].clockVarPr, "TK02"))
            *isApplic2 = NO;
        
        /* Now, check that the prior on tk02 variance is the same. */
        if (!strcmp(modelParams[part1].tk02varPr,"Uniform") && !strcmp(modelParams[part2].tk02varPr,"Uniform"))
            {
            if (AreDoublesEqual (modelParams[part1].tk02varUni[0], modelParams[part2].tk02varUni[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].tk02varUni[1], modelParams[part2].tk02varUni[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].tk02varPr,"Exponential") && !strcmp(modelParams[part2].tk02varPr,"Exponential"))
            {
            if (AreDoublesEqual (modelParams[part1].tk02varExp, modelParams[part2].tk02varExp, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].tk02varPr,"Fixed") && !strcmp(modelParams[part2].tk02varPr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].tk02varFix, modelParams[part2].tk02varFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO;
        
        /* Check to see if tk02 variance is inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;    
        }
    else if (whichParam == P_TK02BRANCHRATES)
        {
        /* Check TK02 relaxed clock branch rates for partitions 1 and 2. */
    
        /* Check if the model is parsimony for either partition. If so, then branch lengths do not apply (as parsimony is very
        silly and doesn't take this information into account) and tk02 relaxed clock branch rates are inapplicable. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; 
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO;

        /* Check that the branch length prior is clock for both partitions. */
        if (strcmp(modelParams[part1].brlensPr, "Clock"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].brlensPr, "Clock"))
            *isApplic2 = NO;

        /* Check that the clock rate prior is tk02 for both partitions */
        if (strcmp(modelParams[part1].clockVarPr, "TK02"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].clockVarPr, "TK02"))
            *isApplic2 = NO;
        
        /* Now, check that the tk02 variance parameter is the same */
        if (IsModelSame (P_TK02VAR, part1, part2, &temp1, &temp2) == NO)
            isSame = NO;
        if (linkTable[P_TK02VAR][part1] != linkTable[P_TK02VAR][part2])
            isSame = NO;

        /* Not same if branch lengths are not the same */
        if (IsModelSame(P_BRLENS, part1, part2, &temp1, &temp2) == NO)
            isSame = NO;
        if (linkTable[P_BRLENS][part1] != linkTable[P_BRLENS][part2])
            isSame = NO;

        /* Set isSame to NO if tk02 branch rates are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;
        }
    else if (whichParam == P_IGRVAR)
        {
        /* Check prior for igr shape for partitions 1 and 2. */
        
        /* Check if the model is parsimony for either partition. If so, then the branch lengths cannot apply (as parsimony is very
        silly and doesn't take this information into account) and igr shape is inapplicable. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; 
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO; 
        
        /* Check that the branch length prior is clock for both partitions. */
        if (strcmp(modelParams[part1].brlensPr, "Clock"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].brlensPr, "Clock"))
            *isApplic2 = NO;

        /* Check that the clock rate prior is igr for both partitions */
        if (strcmp(modelParams[part1].clockVarPr, "Igr"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].clockVarPr, "Igr"))
            *isApplic2 = NO;
        
        /* Now, check that the prior on igr shape is the same. */
        if (!strcmp(modelParams[part1].igrvarPr,"Uniform") && !strcmp(modelParams[part2].igrvarPr,"Uniform"))
            {
            if (AreDoublesEqual (modelParams[part1].igrvarUni[0], modelParams[part2].igrvarUni[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].igrvarUni[1], modelParams[part2].igrvarUni[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].igrvarPr,"Exponential") && !strcmp(modelParams[part2].igrvarPr,"Exponential"))
            {
            if (AreDoublesEqual (modelParams[part1].igrvarExp, modelParams[part2].igrvarExp, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].igrvarPr,"Fixed") && !strcmp(modelParams[part2].igrvarPr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].igrvarFix, modelParams[part2].igrvarFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO;
        
        /* Check to see if igr variance is inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;    
        }
    else if (whichParam == P_IGRBRANCHRATES)
        {
        /* Check IGR relaxed clock branch rates for partitions 1 and 2. */
    
        /* Check if the model is parsimony for either partition. If so, then branch lengths do not apply (as parsimony is very
        silly and doesn't take this information into account) and igr relaxed clock branch rates are inapplicable. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; 
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO;

        /* Check that the branch length prior is clock for both partitions. */
        if (strcmp(modelParams[part1].brlensPr, "Clock"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].brlensPr, "Clock"))
            *isApplic2 = NO;

        /* Check that the clock rate prior is igr for both partitions */
        if (strcmp(modelParams[part1].clockVarPr, "Igr"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].clockVarPr, "Igr"))
            *isApplic2 = NO;
        
        /* Now, check that the igr shape parameter is the same */
        if (IsModelSame (P_IGRVAR, part1, part2, &temp1, &temp2) == NO)
            isSame = NO;
        if (linkTable[P_IGRVAR][part1] != linkTable[P_IGRVAR][part2])
            isSame = NO;
    
        /* Not same if branch lengths are not the same */
        if (IsModelSame(P_BRLENS, part1, part2, &temp1, &temp2) == NO)
            isSame = NO;
        if (linkTable[P_BRLENS][part1] != linkTable[P_BRLENS][part2])
            isSame = NO;

        /* Set isSame to NO if igr branch rates are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;
        }
    else if (whichParam == P_MIXEDVAR)
        {
        /* Check prior for mixed var for partitions 1 and 2. */
        
        /* Check if the model is parsimony for either partition. If so, then the branch lengths cannot apply (as parsimony is very
         silly and doesn't take this information into account) and variance is inapplicable. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO;
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO;
        
        /* Check that the branch length prior is clock for both partitions. */
        if (strcmp(modelParams[part1].brlensPr, "Clock"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].brlensPr, "Clock"))
            *isApplic2 = NO;
        
        /* Check that the clock rate prior is mixed for both partitions */
        if (strcmp(modelParams[part1].clockVarPr, "Mixed"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].clockVarPr, "Mixed"))
            *isApplic2 = NO;
        
        /* Now, check that the prior on var mixed is the same. */
        if (!strcmp(modelParams[part1].mixedvarPr,"Uniform") && !strcmp(modelParams[part2].mixedvarPr,"Uniform"))
            {
            if (AreDoublesEqual (modelParams[part1].mixedvarUni[0], modelParams[part2].mixedvarUni[0], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            if (AreDoublesEqual (modelParams[part1].mixedvarUni[1], modelParams[part2].mixedvarUni[1], (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].mixedvarPr,"Exponential") && !strcmp(modelParams[part2].mixedvarPr,"Exponential"))
            {
            if (AreDoublesEqual (modelParams[part1].mixedvarExp, modelParams[part2].mixedvarExp, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else if (!strcmp(modelParams[part1].mixedvarPr,"Fixed") && !strcmp(modelParams[part2].mixedvarPr,"Fixed"))
            {
            if (AreDoublesEqual (modelParams[part1].mixedvarFix, modelParams[part2].mixedvarFix, (MrBFlt) 0.00001) == NO)
                isSame = NO;
            }
        else
            isSame = NO;
        
        /* Check to see if variance is inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;
        }
    else if (whichParam == P_MIXEDBRCHRATES)
        {
        /* Check mixed relaxed clock branch rates for partitions 1 and 2. */
        
        /* Check if the model is parsimony for either partition. If so, then branch lengths do not apply (as parsimony is very
         silly and doesn't take this information into account) and relaxed clock branch rates are inapplicable. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO;
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO;
        
        /* Check that the branch length prior is clock for both partitions. */
        if (strcmp(modelParams[part1].brlensPr, "Clock"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].brlensPr, "Clock"))
            *isApplic2 = NO;
        
        /* Check that the clock rate prior is mixed for both partitions */
        if (strcmp(modelParams[part1].clockVarPr, "Mixed"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].clockVarPr, "Mixed"))
            *isApplic2 = NO;
        
        /* Now, check that the var parameter is the same */
        if (IsModelSame (P_MIXEDVAR, part1, part2, &temp1, &temp2) == NO)
            isSame = NO;
        if (linkTable[P_MIXEDVAR][part1] != linkTable[P_MIXEDVAR][part2])
            isSame = NO;
        
        /* Not same if branch lengths are not the same */
        if (IsModelSame(P_BRLENS, part1, part2, &temp1, &temp2) == NO)
            isSame = NO;
        if (linkTable[P_BRLENS][part1] != linkTable[P_BRLENS][part2])
            isSame = NO;
        
        /* Set isSame to NO if mixed branch rates are inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;
        }
    else if (whichParam == P_CLOCKRATE)
        {
        /* Check base substitution rates of clock tree for partitions 1 and 2. */
    
        /* Check if the model is parsimony for either partition. If so, then branch lengths do not apply (as parsimony is very
        silly and doesn't take this information into account) and clock branch rates are inapplicable. */
        if (!strcmp(modelParams[part1].parsModel, "Yes"))
            *isApplic1 = NO; 
        if (!strcmp(modelParams[part2].parsModel, "Yes"))
            *isApplic2 = NO;

        /* Check that the branch length prior is clock for both partitions. */
        if (strcmp(modelParams[part1].brlensPr, "Clock"))
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].brlensPr, "Clock"))
            *isApplic2 = NO;

        /* Set isSame to NO if base substitution rate parameter is inapplicable for either partition. */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;
        }
    else if (whichParam == P_SPECIESTREE)
        {
        /* Species tree; check that it is used in both partitions */
        if (strcmp(modelParams[part1].topologyPr, "Speciestree") != 0)
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].topologyPr, "Speciestree") != 0)
            *isApplic2 = NO;

        /* Not same if inapplicable to either partition */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;
        }
    else if (whichParam == P_GENETREERATE)
        {
        /* Gene tree rate; check that it is used in both partitions */
        if (strcmp(modelParams[part1].topologyPr, "Speciestree") != 0)
            *isApplic1 = NO;
        if (strcmp(modelParams[part2].topologyPr, "Speciestree") != 0)
            *isApplic2 = NO;

        /* Not same if inapplicable to either partition */
        if ((*isApplic1) == NO || (*isApplic2) == NO)
            isSame = NO;
        }
    else
        {
        MrBayesPrint ("%s   Could not find parameter in IsModelSame\n", spacer);
        return (NO);
        }
    
    return (isSame);
}


int LargestMovableSubtree(Param *treeParam)
{
    int         i, j, k, a, nLongsNeeded, numPartitions, largestSubtree;
    BitsLong    **constraintPartition, *subtreePartition, *testPartition, *mask;
    ModelParams *mp;

    mp = &modelParams[treeParam->relParts[0]];

    if (treeParam->paramType == P_SPECIESTREE)
        return numLocalTaxa;    /* no constraints allowed in species tree; set constraints in gene trees instead */
    
    /* This is difficult because we cannot rely on the tree being initialized.
       We need to retrieve the bitfields ourselves and figure out what they mean. */
    nLongsNeeded = ((numLocalTaxa - 1) / nBitsInALong) + 1;
    subtreePartition = (BitsLong *) SafeCalloc(3*nLongsNeeded, sizeof(BitsLong));
    constraintPartition = (BitsLong **) SafeCalloc (numDefinedConstraints+1, sizeof(BitsLong *));
    constraintPartition[0] = (BitsLong *) SafeCalloc ((numDefinedConstraints+1)*nLongsNeeded, sizeof(BitsLong));
    for (i=1; i<numDefinedConstraints+1; i++)
        constraintPartition[i] = constraintPartition[i-1] + nLongsNeeded;
    testPartition = subtreePartition + nLongsNeeded;
    mask = testPartition + nLongsNeeded;
    
    /* set mask (needed to take care of unused bits when flipping partitions) */
    for (i=0; i<numLocalTaxa; i++)
        SetBit (i, mask);
    
    /* retrieve partitions */
    numPartitions = 0;
    for (a=0; a<numDefinedConstraints; a++)
        {
        if (mp->activeConstraints[a] == NO || definedConstraintsType[a] != HARD)
            continue;
        
        /* set bits in partition under consideration */
        ClearBits(constraintPartition[numPartitions], nLongsNeeded);
        for (i=j=0; i<numTaxa; i++)
            {
            if (taxaInfo[i].isDeleted == YES)
                continue;
            if (IsBitSet(i, definedConstraint[a]) == YES)
                SetBit(j, constraintPartition[numPartitions]);
            j++;
            }
        
        /* make sure outgroup is outside constrained partition (marked 0) */
        if (strcmp(mp->brlensPr,"Clock") != 0 && IsBitSet(localOutGroup, constraintPartition[numPartitions]) == YES)
            FlipBits(constraintPartition[numPartitions], nLongsNeeded, mask);
        
        /* skip partition if uninformative */
        k = NumBits(constraintPartition[numPartitions], nLongsNeeded);
        if (k == 0 || k == 1)
            continue;
        
        numPartitions++;
        }
    
    /* Add all-species partition */
    CopyBits(constraintPartition[numPartitions], mask, nLongsNeeded);
    numPartitions++;
    
    /* Now we have all constraints. Calculate the movable subtree for each */
    largestSubtree = 0;
    for (i=0; i<numPartitions; i++)
        {
        CopyBits (subtreePartition, constraintPartition[i], nLongsNeeded);
        k = 0;
        for (j=0; j<numPartitions; j++)
            {
            if (j==i)
                continue;
            if (IsPartNested(constraintPartition[j], constraintPartition[i], nLongsNeeded))
                {
                k++;    /* add one for clade we are removing from subtreePartition */
                CopyBits (testPartition, constraintPartition[j], nLongsNeeded);
                FlipBits (testPartition, nLongsNeeded, mask);
                for (k=0; k<nLongsNeeded; k++)
                    subtreePartition[k] = subtreePartition[k] & testPartition[k];
                }
            }
        k += NumBits (subtreePartition, nLongsNeeded);  /* add remaming free tips in subtreePartition */
        /* add calculation root if an unrooted tree and we are dealing with the root partition */
        if (strcmp(mp->brlensPr,"Clock") != 0 && NumBits (constraintPartition[i], nLongsNeeded) == numLocalTaxa - 1)
            k++;
        if (k > largestSubtree)
            largestSubtree = k;
        }

    free(subtreePartition);
    free(constraintPartition[0]);
    free(constraintPartition);
   
    return largestSubtree;
}


int Link (void)
{
    int         i, j;
    
    for (j=0; j<NUM_LINKED; j++)
        {
        MrBayesPrint ("%4d -- ", j+1);
        for (i=0; i<numCurrentDivisions; i++)
            MrBayesPrint (" %2d", tempLinkUnlink[j][i]);
        MrBayesPrint ("\n");
        }
        
    return (NO_ERROR);
}


int NumActiveParts (void)
{
    int     i, nApplied;
    
    nApplied = 0;
    for (i=0; i<numCurrentDivisions; i++)
        if (activeParts[i] == YES)
            nApplied++;

    return (nApplied);
}


int NumInformativeHardConstraints (ModelParams *mp)
{
    int             i, j, k, a, numInformativeHardConstraints, nLongsNeeded;
    BitsLong        *constraintPartition, *mask;
       
    numInformativeHardConstraints = 0;
    
    nLongsNeeded = ((numLocalTaxa - 1) / nBitsInALong) + 1;
    constraintPartition = (BitsLong *) SafeCalloc (2*nLongsNeeded, sizeof(BitsLong));
    if (!constraintPartition)
        {
            MrBayesPrint ("%s   Problems allocating constraintPartition", spacer);
            return ERROR;
        }
    mask = constraintPartition + nLongsNeeded;

    /* set mask (needed to take care of unused bits when flipping partitions) */
    for (i=0; i<numLocalTaxa; i++)
        SetBit (i, mask);
        
    for (a=0; a<numDefinedConstraints; a++)
        {
        if (mp->activeConstraints[a] == NO || definedConstraintsType[a] != HARD)
            continue;
            
        /* set bits in partition to add */
        ClearBits(constraintPartition, nLongsNeeded);
        for (i=j=0; i<numTaxa; i++)
            {
                if (taxaInfo[i].isDeleted == YES)
                    continue;
                if (IsBitSet(i, definedConstraint[a]) == YES)
                    SetBit(j, constraintPartition);
                j++;
            }
            
        /* make sure outgroup is outside constrained partition (marked 0) */
        if (strcmp(mp->brlensPr,"Clock") != 0 && IsBitSet(localOutGroup, constraintPartition) == YES)
            FlipBits(constraintPartition, nLongsNeeded, mask);
            
        /* skip partition if uninformative */
        k = NumBits(constraintPartition, nLongsNeeded);
        if (k == 0 || k == 1)
            continue;

        numInformativeHardConstraints++;
        }
        
    return numInformativeHardConstraints;
}


int NumNonExcludedChar (void)
{
    int     i, n;
    
    /* count number of non-excluded characters */
    n = 0;
    for (i=0; i<numChar; i++)
        {
        if (charInfo[i].isExcluded == NO)
            {
            n++;
            }
        }
    
    return n;
}


int NumStates (int part)
{
    if (modelParams[part].dataType == DNA || modelParams[part].dataType == RNA)
        {
        if (!strcmp(modelParams[part].nucModel, "4by4"))
            return (4);
        else if (!strcmp(modelParams[part].nucModel, "Doublet"))
            return (16);
        else if (!strcmp(modelParams[part].nucModel, "Protein"))
            return (20);
        else
            {
            if (!strcmp(modelParams[part].geneticCode, "Universal"))
                return (61);
            else if (!strcmp(modelParams[part].geneticCode, "Vertmt"))
                return (60);
            else if (!strcmp(modelParams[part].geneticCode, "Mycoplasma"))
                return (62);
            else if (!strcmp(modelParams[part].geneticCode, "Yeast"))
                return (62);
            else if (!strcmp(modelParams[part].geneticCode, "Ciliates"))
                return (63);
            else if (!strcmp(modelParams[part].geneticCode, "Metmt"))
                return (62);
            }
        }
    else if (modelParams[part].dataType == PROTEIN)
        {
        return (20);
        }
    else if (modelParams[part].dataType == RESTRICTION)
        {
        return (2);
        }
    else if (modelParams[part].dataType == STANDARD)
        {
        return (10);
        }
        
    return (-1);
}


/*-----------------------------------------------------------------------
|
|   PrintCompMatrix: Print compressed matrix
|
------------------------------------------------------------------------*/
int PrintCompMatrix (void)
{
    int             i, j, k, c, d;
    ModelInfo       *m;
    ModelParams     *mp;
    char            tempName[100];
    char            (*whichChar)(int);

    if (!compMatrix)
        return ERROR;

    whichChar = &WhichNuc;
    
    for (d=0; d<numCurrentDivisions; d++)
        {
        m = &modelSettings[d];
        mp = &modelParams[d];

        if (mp->dataType == DNA || mp->dataType == RNA)
            whichChar = &WhichNuc;
        if (mp->dataType == PROTEIN)
            whichChar = &WhichAA;
        if (mp->dataType == RESTRICTION)
            whichChar = &WhichRes;
        if (mp->dataType == STANDARD)
            whichChar = &WhichStand;

        MrBayesPrint ("\nCompressed matrix for division %d\n\n", d+1);
        
        k = 66;
        if (mp->dataType == CONTINUOUS)
            k /= 4;

        for (c=m->compMatrixStart; c<m->compMatrixStop; c+=k)
            {
            for (i=0; i<numLocalTaxa; i++)
                {
                strcpy (tempName, localTaxonNames[i]);
                MrBayesPrint ("%-10.10s   ", tempName);
                for (j=c; j<c+k; j++)
                    {
                    if (j >= m->compMatrixStop)
                        break;
                    if (mp->dataType == CONTINUOUS)
                        MrBayesPrint ("%3d ", compMatrix[pos(i,j,compMatrixRowSize)]);
                    else
                        MrBayesPrint ("%c", whichChar((int)compMatrix[pos(i,j,compMatrixRowSize)]));
                    }
                MrBayesPrint("\n");
                }
            MrBayesPrint("\nNo. sites    ");
            for (j=c; j<c+k; j++)
                {
                if (j >= m->compMatrixStop)
                    break;
                i = (int) numSitesOfPat[m->compCharStart + (0*numCompressedChars) + (j - m->compMatrixStart)/m->nCharsPerSite]; /* NOTE: We are printing the unadulterated site pat nums */
                if (i>9)
                    i = 'A' + i - 10;
                else
                    i = '0' + i;
                if (mp->dataType == CONTINUOUS)
                    MrBayesPrint("   %c ", i);
                else
                    {
                    if ((j-m->compMatrixStart) % m->nCharsPerSite == 0)
                        MrBayesPrint ("%c", i);
                    else
                        MrBayesPrint(" ");
                    }
                }
            MrBayesPrint ("\nOrig. char   ");
            for (j=c; j<c+k; j++)
                {
                if (j >= m->compMatrixStop)
                    break;
                i = origChar[j];
                if (i>9)
                    i = '0' + (i % 10);
                else
                    i = '0' +i;
                if (mp->dataType == CONTINUOUS)
                    MrBayesPrint("   %c ", i);
                else
                    MrBayesPrint ("%c", i);
                }

            if (mp->dataType == STANDARD && m->nStates != NULL)
                {
                MrBayesPrint ("\nNo. states   ");
                for (j=c; j<c+k; j++)
                    {
                    if (j >= m->compMatrixStop)
                        break;
                    i = m->nStates[j-m->compCharStart];
                    MrBayesPrint ("%d", i);
                    }
                MrBayesPrint ("\nCharType     ");
                for (j=c; j<c+k; j++)
                    {
                    if (j >= m->compMatrixStop)
                        break;
                    i = m->cType[j-m->compMatrixStart];
                    if (i == ORD)
                        MrBayesPrint ("%c", 'O');
                    else if (i == UNORD)
                        MrBayesPrint ("%c", 'U');
                    else
                        MrBayesPrint ("%c", 'I');
                    }
                MrBayesPrint ("\ntiIndex      ");
                for (j=c; j<c+k; j++)
                    {
                    if (j >= m->compMatrixStop)
                        break;
                    i = m->tiIndex[j-m->compCharStart];
                    MrBayesPrint ("%d", i % 10);
                    }
                MrBayesPrint ("\nbsIndex      ");
                for (j=c; j<c+k; j++)
                    {
                    if (j >= m->compMatrixStop)
                        break;
                    i = m->bsIndex[j-m->compCharStart];
                    MrBayesPrint ("%d", i % 10);
                    }
                }
            MrBayesPrint ("\n\n");
            }
        MrBayesPrint ("Press return to continue\n");
        getchar();
        }   /* next division */

    return NO_ERROR;
}


/*----------------------------------------------------------------------
|
|   PrintMatrix: Print data matrix
|
|
------------------------------------------------------------------------*/
int PrintMatrix (void)
{
    int             i, j=0, c, printWidth, nextColumn;

    if (!matrix)
        return ERROR;
    
    MrBayesPrint ("\nData matrix\n\n");
    
    printWidth = 79;

    for (c=0; c<numChar; c=j)
        {
        for (i=0; i<numTaxa; i++)
            {
            MrBayesPrint ("%-10.10s   ", taxaNames[i]);
            j = c;
            for (nextColumn=13; nextColumn < printWidth; nextColumn++)
                {
                if (j >= numChar)
                    break;
                if (charInfo[j].charType == CONTINUOUS && nextColumn < printWidth - 3)
                    break;
                if (charInfo[j].charType == CONTINUOUS)
                    {   
                    MrBayesPrint ("%3d ", matrix[pos(i,j,numChar)]);
                    nextColumn += 3;
                    }
                else if (charInfo[j].charType == DNA || charInfo[j].charType == RNA)
                    MrBayesPrint ("%c", WhichNuc(matrix[pos(i,j,numChar)]));
                else if (charInfo[j].charType == PROTEIN)
                    MrBayesPrint ("%c", WhichAA(matrix[pos(i,j,numChar)]));
                else if (charInfo[j].charType == RESTRICTION)
                    MrBayesPrint ("%c", WhichRes(matrix[pos(i,j,numChar)]));
                else if (charInfo[j].charType == STANDARD)
                    MrBayesPrint ("%c", WhichStand(matrix[pos(i,j,numChar)]));
                j++;
                }
            MrBayesPrint("\n");
            }
        MrBayesPrint ("\n");
        }

    return NO_ERROR;
}


/*--------------------------------------------------------------
|
|   ProcessStdChars: process standard characters
|
---------------------------------------------------------------*/
int ProcessStdChars (RandLong *seed)
{
    int             c, d, i, j, k, n, ts, index, numStandardChars, origCharPos, *bsIndex;
    char            piHeader[30];
    ModelInfo       *m;
    ModelParams     *mp=NULL;
    Param           *p;

    /* set character type, no. states, ti index and bs index for standard characters */
    /* first calculate how many standard characters we have */
    numStandardChars = 0;
    for (d=0; d<numCurrentDivisions; d++)
        {
        mp = &modelParams[d];
        m = &modelSettings[d];

        if (mp->dataType != STANDARD)
            continue;

        numStandardChars += m->numChars;
        }
    
    /* return if there are no standard characters */
    if (numStandardChars == 0)
        return (NO_ERROR);

    /* we are still here so we have standard characters and need to deal with them */
    
    /* first allocate space for stdType, stateSize, tiIndex, bsIndex */
    if (memAllocs[ALLOC_STDTYPE] == YES)
        {
        free (stdType);
        stdType = NULL;
        memAllocs[ALLOC_STDTYPE] = NO;
        }
    stdType = (int *)SafeCalloc((size_t) (4 * numStandardChars), sizeof(int));
    if (!stdType)
        {
        MrBayesPrint ("%s   Problem allocating stdType (%d ints)\n", 4 * numStandardChars);
        return ERROR;
        }
    memAllocs[ALLOC_STDTYPE] = YES;
    stateSize = stdType + numStandardChars;
    tiIndex = stateSize + numStandardChars;
    bsIndex = tiIndex + numStandardChars;

    /* then fill in stdType and stateSize, set pointers */
    /* also fill in isTiNeeded for each division and tiIndex for each character */
    for (d=j=0; d<numCurrentDivisions; d++)
        {
        mp = &modelParams[d];
        m = &modelSettings[d];
        
        if (mp->dataType != STANDARD)
            continue;

        m->cType = stdType + j;
        m->nStates = stateSize + j;
        m->tiIndex = tiIndex + j;
        m->bsIndex = bsIndex + j;

        m->cijkLength = 0;
        m->nCijkParts = 0;
        for (c=0; c<m->numChars; c++)
            {
            if (origChar[c+m->compMatrixStart] < 0)
                {
                /* this is a dummy character */
                m->cType[c] = UNORD;
                m->nStates[c] = 2;
                }
            else
                {
                /* this is an ordinary character */
                m->cType[c] = charInfo[origChar[c + m->compMatrixStart]].ctype;
                m->nStates[c] = charInfo[origChar[c + m->compMatrixStart]].numStates;
                }
            
            /* check ctype settings */
            if (m->nStates[c] < 2)
                {
                MrBayesPrint ("%s   WARNING: Compressed character %d (original character %d) of division %d has less \n", spacer, c+m->compCharStart,origChar[c+m->compCharStart]+1, d+1);
                MrBayesPrint ("%s            than two observed states; it will be assumed to have two states.\n", spacer);
                m->nStates[c] = 2;
                }
            if (m->nStates[c] > 6 && m->cType[c] != UNORD)
                {
                MrBayesPrint ("%s   Only unordered model supported for characters with more than 6 states\n", spacer);
                return ERROR;
                }
            if (m->nStates[c] == 2 && m->cType[c] == ORD)
                m->cType[c] = UNORD;
            if (m->cType[c] == IRREV)
                {
                MrBayesPrint ("%s   Irreversible model not yet supported\n", spacer);
                return ERROR;
                }
            
            /* find max number of states */
            if (m->nStates[c] > m->numModelStates)
                m->numModelStates = m->nStates[c];

            /* update Cijk info */
            if (strcmp(mp->symPiPr,"Fixed") != 0 || AreDoublesEqual(mp->symBetaFix, -1.0, 0.00001) == NO)
                {
                /* Asymmetry between stationary state frequencies -- we need one cijk and eigenvalue
                    set for each multistate character */
                if (m->nStates[c] > 2 && (m->cType[c] == UNORD || m->cType[c] == ORD))
                    {
                    ts = m->nStates[c];
                    m->cijkLength += (ts * ts * ts) + (2 * ts);
                    m->nCijkParts++;
                    }
                }

            /* set the ti probs needed */
            if (m->stateFreq->nValues == 0 || m->nStates[c] == 2)
                {
                if (m->cType[c] == UNORD)
                    m->isTiNeeded[m->nStates[c]-2] = YES;
                if (m->cType[c] == ORD)
                    m->isTiNeeded[m->nStates[c]+6] = YES;
                if (m->cType[c] == IRREV)
                    m->isTiNeeded[m->nStates[c]+11] = YES;
                }
            }

        /* set ti index for each compressed character first         */
        /* set bs index later (below)                               */

        /* set base index, valid for binary chars */
        m->tiIndex[c] = 0;

        /* first adjust for unordered characters */
        for (k=0; k<9; k++)
            {
            if (m->isTiNeeded [k] == NO)
                continue;

            for (c=0; c<m->numChars; c++)
                {
                if (m->cType[c] != UNORD || m->nStates[c] > k + 2)
                    {
                    m->tiIndex[c] += (k + 2) * (k + 2) * m->numGammaCats;
                    }
                }
            }

        /* second for ordered characters */
        for (k=9; k<13; k++)
            {
            if (m->isTiNeeded [k] == NO)
                continue;

            for (c=0; c<m->numChars; c++)
                {
                if (m->cType[c] == IRREV || (m->cType[c] == ORD && m->nStates[c] > k - 6))
                    {
                    m->tiIndex[c] += (k - 6) * (k - 6) * m->numGammaCats;
                    }
                }
            }

        /* third for irrev characters */
        for (k=13; k<18; k++)
            {
            if (m->isTiNeeded [k] == NO)
                continue;

            for (c=0; c<m->numChars; c++)
                {
                if (m->cType[c] == IRREV && m->nStates[c] > k - 11)
                    {
                    m->tiIndex[c] += (k - 11) * (k - 11) * m->numGammaCats;
                    }
                }
            }

        /* finally take beta cats into account in tiIndex        */
        /* the beta cats will only be used for binary characters */
        /* multistate characters get their ti indices reset here */
        if (m->numBetaCats > 1 && m->isTiNeeded[0] == YES)
            {
            k = 4 * m->numBetaCats * m->numGammaCats;   /* offset for binary character ti probs */
            for (c=0; c<m->numChars; c++)
                {
                if (m->nStates[c] > 2)
                    {
                    m->tiIndex[c] = k;
                    k += m->nStates[c] * m->nStates[c] * m->numGammaCats;
                    }
                }
            }
        j += m->numChars;
        }
    
    /* deal with bsIndex */
    for (k=0; k<numParams; k++)
        {
        p = &params[k];
        if (p->paramType != P_PI || modelParams[p->relParts[0]].dataType != STANDARD)
            continue;
        p->nSympi = 0;
        p->hasBinaryStd = NO;
        for (i=0; i<p->nRelParts; i++)
            if (modelSettings[p->relParts[i]].isTiNeeded[0] == YES)
                break;
        if (i < p->nRelParts)
            p->hasBinaryStd = YES;
        if (p->paramId == SYMPI_EQUAL)
            {
            /* calculate the number of state frequencies needed */
            /* also set bsIndex appropriately                   */
            for (n=index=0; n<9; n++)
                {
                for (i=0; i<p->nRelParts; i++)
                    if (modelSettings[p->relParts[i]].isTiNeeded[n] == YES)
                        break;
                if (i < p->nRelParts)
                    {
                    for (i=0; i<p->nRelParts; i++)
                        {
                        m = &modelSettings[p->relParts[i]];
                        for (c=0; c<m->numChars; c++)
                            {
                            if (m->cType[c] != UNORD || m->nStates[c] > n + 2)
                                {
                                m->bsIndex[c] += (n + 2);
                                }
                            }
                        }
                    index += (n + 2);
                    }
                }
            for (n=9; n<13; n++)
                {
                for (i=0; i<p->nRelParts; i++)
                    if (modelSettings[p->relParts[i]].isTiNeeded[n] == YES)
                        break;
                if (i < p->nRelParts)
                    {
                    for (i=0; i<p->nRelParts; i++)
                        {
                        m = &modelSettings[p->relParts[i]];
                        for (c=0; c<m->numChars; c++)
                            {
                            if (m->cType[c] == ORD && m->nStates[c] > n - 6)
                                {
                                m->bsIndex[c] += (n - 6);
                                }
                            }
                        }
                    index += (n - 6);
                    }
                }
            p->nStdStateFreqs = index;
            }
        else
            {
            /* if not equal we need space for beta category frequencies */
            index = 0;
            if (p->hasBinaryStd == YES)
                index += (2 * modelSettings[p->relParts[0]].numBetaCats);
            /* as well as one set of frequencies for each multistate character */
            for (i=0; i<p->nRelParts; i++)
                {
                m = &modelSettings[p->relParts[i]];
                for (c=0; c<m->numChars; c++)
                    {
                    if (m->nStates[c] > 2 && (m->cType[c] == UNORD || m->cType[c] == ORD))
                        {
                        m->bsIndex[c] = index;
                        index += m->nStates[c];
                        p->nSympi++;
                        }
                    }
                }
            }
        p->nStdStateFreqs = index;
        }
    
    /* allocate space for bsIndex, sympiIndex, stdStateFreqs; then fill */

    /* first count number of sympis needed */
    for (k=n=i=0; k<numParams; k++)
        {
        p = &params[k];
        n += p->nSympi;     /* nsympi calculated above */
        }
    
    /* then allocate and fill in */
    if (n > 0)
        {
        if (memAllocs[ALLOC_SYMPIINDEX] == YES)
            {
            sympiIndex = (int *) SafeRealloc ((void *) sympiIndex, 3*n * sizeof (int));
            for (i=0; i<3*n; i++)
                sympiIndex[i] = 0;
            }
        else
            sympiIndex = (int *) SafeCalloc (3*n, sizeof (int));
        if (!sympiIndex)
            {
            MrBayesPrint ("%s   Problem allocating sympiIndex\n", spacer);
            return (ERROR);
            }
        else
            memAllocs[ALLOC_SYMPIINDEX] = YES;
        
        /* set up sympi pointers and fill sympiIndex */
        for (k=i=0; k<numParams; k++)
            {
            p = &params[k];
            if (p->nSympi > 0)
                {
                p->printParam = YES;    /* print even if fixed alpha_symdir */
                index = 0;
                p->sympiBsIndex = sympiIndex + i;
                p->sympinStates = sympiIndex + i + n;
                p->sympiCType = sympiIndex + i + (2 * n);
                for (j=0; j<p->nRelParts; j++)
                    {                       
                    m = &modelSettings[p->relParts[j]];
                    for (c=0; c<m->numChars; c++)
                        {
                        if (m->nStates[c] > 2 && (m->cType[c] == UNORD || m->cType[c] == ORD))
                            {
                            p->sympinStates[index] = m->nStates[c];
                            p->sympiBsIndex[index] = m->bsIndex[c];
                            p->sympiCType[index] = m->cType[c];
                            origCharPos = origChar[m->compCharStart + c];
                            for (ts=0; ts<m->nStates[c]; ts++)
                                {
                                sprintf (piHeader, "\tpi_%d(%d)", origCharPos+1, ts);
                                SafeStrcat(&p->paramHeader, piHeader);
                                }
                            index++;
                            }
                        }
                    }
                assert (index == p->nSympi);
                i += p->nSympi;
                }
            }
        assert (i == n);
        }
    
    /* count space needed for state frequencies */
    for (k=n=0; k<numParams; k++)
        {
        p = &params[k];
        if (p->paramType != P_PI || modelParams[p->relParts[0]].dataType != STANDARD)
            continue;
        n += p->nStdStateFreqs;
        }
    
    stdStateFreqsRowSize = n;
    
    /* allocate space */
    if (memAllocs[ALLOC_STDSTATEFREQS] == YES)
        {
        free (stdStateFreqs);
        stdStateFreqs = NULL;
        memAllocs[ALLOC_STDSTATEFREQS] = NO;
        }
    stdStateFreqs = (MrBFlt *) SafeCalloc (n * 2 * numGlobalChains, sizeof (MrBFlt));
    if (!stdStateFreqs)
        {
        MrBayesPrint ("%s   Problem allocating stdStateFreqs in ProcessStdChars\n", spacer);
        return (ERROR);
        }
    else
        memAllocs[ALLOC_STDSTATEFREQS] = YES;
    
    /* set pointers */
    for (k=n=0; k<numParams; k++)
        {
        p = &params[k];
        if (p->paramType != P_PI || modelParams[p->relParts[0]].dataType != STANDARD)
            continue;
        p->stdStateFreqs = stdStateFreqs + n;
        n += p->nStdStateFreqs;
        }
    
    FillStdStateFreqs (0 , numGlobalChains, seed);

    return (NO_ERROR);
}


int SetAARates (void)
{
    int         i, j;
    MrBFlt      diff, sum, scaler;
    
    /* A R N D C Q E G H I L K M F P S T W Y V */

    /* jones */
    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;

    /* dayhoff */
    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;

    /* mtrev24 */
    aaMtrev24[ 0][ 0] =   0.00; aaMtrev24[ 0][ 1] =  23.18; aaMtrev24[ 0][ 2] =  26.95; aaMtrev24[ 0][ 3] =  17.67; aaMtrev24[ 0][ 4] =  59.93;
    aaMtrev24[ 0][ 5] =   1.90; aaMtrev24[ 0][ 6] =   9.77; aaMtrev24[ 0][ 7] = 120.71; aaMtrev24[ 0][ 8] =  13.90; aaMtrev24[ 0][ 9] =  96.49;
    aaMtrev24[ 0][10] =  25.46; aaMtrev24[ 0][11] =   8.36; aaMtrev24[ 0][12] = 141.88; aaMtrev24[ 0][13] =   6.37; aaMtrev24[ 0][14] =  54.31;
    aaMtrev24[ 0][15] = 387.86; aaMtrev24[ 0][16] = 480.72; aaMtrev24[ 0][17] =   1.90; aaMtrev24[ 0][18] =   6.48; aaMtrev24[ 0][19] = 195.06;
    aaMtrev24[ 1][ 0] =  23.18; aaMtrev24[ 1][ 1] =   0.00; aaMtrev24[ 1][ 2] =  13.24; aaMtrev24[ 1][ 3] =   1.90; aaMtrev24[ 1][ 4] = 103.33;
    aaMtrev24[ 1][ 5] = 220.99; aaMtrev24[ 1][ 6] =   1.90; aaMtrev24[ 1][ 7] =  23.03; aaMtrev24[ 1][ 8] = 165.23; aaMtrev24[ 1][ 9] =   1.90;
    aaMtrev24[ 1][10] =  15.58; aaMtrev24[ 1][11] = 141.40; aaMtrev24[ 1][12] =   1.90; aaMtrev24[ 1][13] =   4.69; aaMtrev24[ 1][14] =  23.64;
    aaMtrev24[ 1][15] =   6.04; aaMtrev24[ 1][16] =   2.08; aaMtrev24[ 1][17] =  21.95; aaMtrev24[ 1][18] =   1.90; aaMtrev24[ 1][19] =   7.64;
    aaMtrev24[ 2][ 0] =  26.95; aaMtrev24[ 2][ 1] =  13.24; aaMtrev24[ 2][ 2] =   0.00; aaMtrev24[ 2][ 3] = 794.38; aaMtrev24[ 2][ 4] =  58.94;
    aaMtrev24[ 2][ 5] = 173.56; aaMtrev24[ 2][ 6] =  63.05; aaMtrev24[ 2][ 7] =  53.30; aaMtrev24[ 2][ 8] = 496.13; aaMtrev24[ 2][ 9] =  27.10;
    aaMtrev24[ 2][10] =  15.16; aaMtrev24[ 2][11] = 608.70; aaMtrev24[ 2][12] =  65.41; aaMtrev24[ 2][13] =  15.20; aaMtrev24[ 2][14] =  73.31;
    aaMtrev24[ 2][15] = 494.39; aaMtrev24[ 2][16] = 238.46; aaMtrev24[ 2][17] =  10.68; aaMtrev24[ 2][18] = 191.36; aaMtrev24[ 2][19] =   1.90;
    aaMtrev24[ 3][ 0] =  17.67; aaMtrev24[ 3][ 1] =   1.90; aaMtrev24[ 3][ 2] = 794.38; aaMtrev24[ 3][ 3] =   0.00; aaMtrev24[ 3][ 4] =   1.90;
    aaMtrev24[ 3][ 5] =  55.28; aaMtrev24[ 3][ 6] = 583.55; aaMtrev24[ 3][ 7] =  56.77; aaMtrev24[ 3][ 8] = 113.99; aaMtrev24[ 3][ 9] =   4.34;
    aaMtrev24[ 3][10] =   1.90; aaMtrev24[ 3][11] =   2.31; aaMtrev24[ 3][12] =   1.90; aaMtrev24[ 3][13] =   4.98; aaMtrev24[ 3][14] =  13.43;
    aaMtrev24[ 3][15] =  69.02; aaMtrev24[ 3][16] =  28.01; aaMtrev24[ 3][17] =  19.86; aaMtrev24[ 3][18] =  21.21; aaMtrev24[ 3][19] =   1.90;
    aaMtrev24[ 4][ 0] =  59.93; aaMtrev24[ 4][ 1] = 103.33; aaMtrev24[ 4][ 2] =  58.94; aaMtrev24[ 4][ 3] =   1.90; aaMtrev24[ 4][ 4] =   0.00;
    aaMtrev24[ 4][ 5] =  75.24; aaMtrev24[ 4][ 6] =   1.90; aaMtrev24[ 4][ 7] =  30.71; aaMtrev24[ 4][ 8] = 141.49; aaMtrev24[ 4][ 9] =  62.73;
    aaMtrev24[ 4][10] =  25.65; aaMtrev24[ 4][11] =   1.90; aaMtrev24[ 4][12] =   6.18; aaMtrev24[ 4][13] =  70.80; aaMtrev24[ 4][14] =  31.26;
    aaMtrev24[ 4][15] = 277.05; aaMtrev24[ 4][16] = 179.97; aaMtrev24[ 4][17] =  33.60; aaMtrev24[ 4][18] = 254.77; aaMtrev24[ 4][19] =   1.90;
    aaMtrev24[ 5][ 0] =   1.90; aaMtrev24[ 5][ 1] = 220.99; aaMtrev24[ 5][ 2] = 173.56; aaMtrev24[ 5][ 3] =  55.28; aaMtrev24[ 5][ 4] =  75.24;
    aaMtrev24[ 5][ 5] =   0.00; aaMtrev24[ 5][ 6] = 313.56; aaMtrev24[ 5][ 7] =   6.75; aaMtrev24[ 5][ 8] = 582.40; aaMtrev24[ 5][ 9] =   8.34;
    aaMtrev24[ 5][10] =  39.70; aaMtrev24[ 5][11] = 465.58; aaMtrev24[ 5][12] =  47.37; aaMtrev24[ 5][13] =  19.11; aaMtrev24[ 5][14] = 137.29;
    aaMtrev24[ 5][15] =  54.11; aaMtrev24[ 5][16] =  94.93; aaMtrev24[ 5][17] =   1.90; aaMtrev24[ 5][18] =  38.82; aaMtrev24[ 5][19] =  19.00;
    aaMtrev24[ 6][ 0] =   9.77; aaMtrev24[ 6][ 1] =   1.90; aaMtrev24[ 6][ 2] =  63.05; aaMtrev24[ 6][ 3] = 583.55; aaMtrev24[ 6][ 4] =   1.90;
    aaMtrev24[ 6][ 5] = 313.56; aaMtrev24[ 6][ 6] =   0.00; aaMtrev24[ 6][ 7] =  28.28; aaMtrev24[ 6][ 8] =  49.12; aaMtrev24[ 6][ 9] =   3.31;
    aaMtrev24[ 6][10] =   1.90; aaMtrev24[ 6][11] = 313.86; aaMtrev24[ 6][12] =   1.90; aaMtrev24[ 6][13] =   2.67; aaMtrev24[ 6][14] =  12.83;
    aaMtrev24[ 6][15] =  54.71; aaMtrev24[ 6][16] =  14.82; aaMtrev24[ 6][17] =   1.90; aaMtrev24[ 6][18] =  13.12; aaMtrev24[ 6][19] =  21.14;
    aaMtrev24[ 7][ 0] = 120.71; aaMtrev24[ 7][ 1] =  23.03; aaMtrev24[ 7][ 2] =  53.30; aaMtrev24[ 7][ 3] =  56.77; aaMtrev24[ 7][ 4] =  30.71;
    aaMtrev24[ 7][ 5] =   6.75; aaMtrev24[ 7][ 6] =  28.28; aaMtrev24[ 7][ 7] =   0.00; aaMtrev24[ 7][ 8] =   1.90; aaMtrev24[ 7][ 9] =   5.98;
    aaMtrev24[ 7][10] =   2.41; aaMtrev24[ 7][11] =  22.73; aaMtrev24[ 7][12] =   1.90; aaMtrev24[ 7][13] =   1.90; aaMtrev24[ 7][14] =   1.90;
    aaMtrev24[ 7][15] = 125.93; aaMtrev24[ 7][16] =  11.17; aaMtrev24[ 7][17] =  10.92; aaMtrev24[ 7][18] =   3.21; aaMtrev24[ 7][19] =   2.53;
    aaMtrev24[ 8][ 0] =  13.90; aaMtrev24[ 8][ 1] = 165.23; aaMtrev24[ 8][ 2] = 496.13; aaMtrev24[ 8][ 3] = 113.99; aaMtrev24[ 8][ 4] = 141.49;
    aaMtrev24[ 8][ 5] = 582.40; aaMtrev24[ 8][ 6] =  49.12; aaMtrev24[ 8][ 7] =   1.90; aaMtrev24[ 8][ 8] =   0.00; aaMtrev24[ 8][ 9] =  12.26;
    aaMtrev24[ 8][10] =  11.49; aaMtrev24[ 8][11] = 127.67; aaMtrev24[ 8][12] =  11.97; aaMtrev24[ 8][13] =  48.16; aaMtrev24[ 8][14] =  60.97;
    aaMtrev24[ 8][15] =  77.46; aaMtrev24[ 8][16] =  44.78; aaMtrev24[ 8][17] =   7.08; aaMtrev24[ 8][18] = 670.14; aaMtrev24[ 8][19] =   1.90;
    aaMtrev24[ 9][ 0] =  96.49; aaMtrev24[ 9][ 1] =   1.90; aaMtrev24[ 9][ 2] =  27.10; aaMtrev24[ 9][ 3] =   4.34; aaMtrev24[ 9][ 4] =  62.73;
    aaMtrev24[ 9][ 5] =   8.34; aaMtrev24[ 9][ 6] =   3.31; aaMtrev24[ 9][ 7] =   5.98; aaMtrev24[ 9][ 8] =  12.26; aaMtrev24[ 9][ 9] =   0.00;
    aaMtrev24[ 9][10] = 329.09; aaMtrev24[ 9][11] =  19.57; aaMtrev24[ 9][12] = 517.98; aaMtrev24[ 9][13] =  84.67; aaMtrev24[ 9][14] =  20.63;
    aaMtrev24[ 9][15] =  47.70; aaMtrev24[ 9][16] = 368.43; aaMtrev24[ 9][17] =   1.90; aaMtrev24[ 9][18] =  25.01; aaMtrev24[ 9][19] =1222.94;
    aaMtrev24[10][ 0] =  25.46; aaMtrev24[10][ 1] =  15.58; aaMtrev24[10][ 2] =  15.16; aaMtrev24[10][ 3] =   1.90; aaMtrev24[10][ 4] =  25.65;
    aaMtrev24[10][ 5] =  39.70; aaMtrev24[10][ 6] =   1.90; aaMtrev24[10][ 7] =   2.41; aaMtrev24[10][ 8] =  11.49; aaMtrev24[10][ 9] = 329.09;
    aaMtrev24[10][10] =   0.00; aaMtrev24[10][11] =  14.88; aaMtrev24[10][12] = 537.53; aaMtrev24[10][13] = 216.06; aaMtrev24[10][14] =  40.10;
    aaMtrev24[10][15] =  73.61; aaMtrev24[10][16] = 126.40; aaMtrev24[10][17] =  32.44; aaMtrev24[10][18] =  44.15; aaMtrev24[10][19] =  91.67;
    aaMtrev24[11][ 0] =   8.36; aaMtrev24[11][ 1] = 141.40; aaMtrev24[11][ 2] = 608.70; aaMtrev24[11][ 3] =   2.31; aaMtrev24[11][ 4] =   1.90;
    aaMtrev24[11][ 5] = 465.58; aaMtrev24[11][ 6] = 313.86; aaMtrev24[11][ 7] =  22.73; aaMtrev24[11][ 8] = 127.67; aaMtrev24[11][ 9] =  19.57;
    aaMtrev24[11][10] =  14.88; aaMtrev24[11][11] =   0.00; aaMtrev24[11][12] =  91.37; aaMtrev24[11][13] =   6.44; aaMtrev24[11][14] =  50.10;
    aaMtrev24[11][15] = 105.79; aaMtrev24[11][16] = 136.33; aaMtrev24[11][17] =  24.00; aaMtrev24[11][18] =  51.17; aaMtrev24[11][19] =   1.90;
    aaMtrev24[12][ 0] = 141.88; aaMtrev24[12][ 1] =   1.90; aaMtrev24[12][ 2] =  65.41; aaMtrev24[12][ 3] =   1.90; aaMtrev24[12][ 4] =   6.18;
    aaMtrev24[12][ 5] =  47.37; aaMtrev24[12][ 6] =   1.90; aaMtrev24[12][ 7] =   1.90; aaMtrev24[12][ 8] =  11.97; aaMtrev24[12][ 9] = 517.98;
    aaMtrev24[12][10] = 537.53; aaMtrev24[12][11] =  91.37; aaMtrev24[12][12] =   0.00; aaMtrev24[12][13] =  90.82; aaMtrev24[12][14] =  18.84;
    aaMtrev24[12][15] = 111.16; aaMtrev24[12][16] = 528.17; aaMtrev24[12][17] =  21.71; aaMtrev24[12][18] =  39.96; aaMtrev24[12][19] = 387.54;
    aaMtrev24[13][ 0] =   6.37; aaMtrev24[13][ 1] =   4.69; aaMtrev24[13][ 2] =  15.20; aaMtrev24[13][ 3] =   4.98; aaMtrev24[13][ 4] =  70.80;
    aaMtrev24[13][ 5] =  19.11; aaMtrev24[13][ 6] =   2.67; aaMtrev24[13][ 7] =   1.90; aaMtrev24[13][ 8] =  48.16; aaMtrev24[13][ 9] =  84.67;
    aaMtrev24[13][10] = 216.06; aaMtrev24[13][11] =   6.44; aaMtrev24[13][12] =  90.82; aaMtrev24[13][13] =   0.00; aaMtrev24[13][14] =  17.31;
    aaMtrev24[13][15] =  64.29; aaMtrev24[13][16] =  33.85; aaMtrev24[13][17] =   7.84; aaMtrev24[13][18] = 465.58; aaMtrev24[13][19] =   6.35;
    aaMtrev24[14][ 0] =  54.31; aaMtrev24[14][ 1] =  23.64; aaMtrev24[14][ 2] =  73.31; aaMtrev24[14][ 3] =  13.43; aaMtrev24[14][ 4] =  31.26;
    aaMtrev24[14][ 5] = 137.29; aaMtrev24[14][ 6] =  12.83; aaMtrev24[14][ 7] =   1.90; aaMtrev24[14][ 8] =  60.97; aaMtrev24[14][ 9] =  20.63;
    aaMtrev24[14][10] =  40.10; aaMtrev24[14][11] =  50.10; aaMtrev24[14][12] =  18.84; aaMtrev24[14][13] =  17.31; aaMtrev24[14][14] =   0.00;
    aaMtrev24[14][15] = 169.90; aaMtrev24[14][16] = 128.22; aaMtrev24[14][17] =   4.21; aaMtrev24[14][18] =  16.21; aaMtrev24[14][19] =   8.23;
    aaMtrev24[15][ 0] = 387.86; aaMtrev24[15][ 1] =   6.04; aaMtrev24[15][ 2] = 494.39; aaMtrev24[15][ 3] =  69.02; aaMtrev24[15][ 4] = 277.05;
    aaMtrev24[15][ 5] =  54.11; aaMtrev24[15][ 6] =  54.71; aaMtrev24[15][ 7] = 125.93; aaMtrev24[15][ 8] =  77.46; aaMtrev24[15][ 9] =  47.70;
    aaMtrev24[15][10] =  73.61; aaMtrev24[15][11] = 105.79; aaMtrev24[15][12] = 111.16; aaMtrev24[15][13] =  64.29; aaMtrev24[15][14] = 169.90;
    aaMtrev24[15][15] =   0.00; aaMtrev24[15][16] = 597.21; aaMtrev24[15][17] =  38.58; aaMtrev24[15][18] =  64.92; aaMtrev24[15][19] =   1.90;
    aaMtrev24[16][ 0] = 480.72; aaMtrev24[16][ 1] =   2.08; aaMtrev24[16][ 2] = 238.46; aaMtrev24[16][ 3] =  28.01; aaMtrev24[16][ 4] = 179.97;
    aaMtrev24[16][ 5] =  94.93; aaMtrev24[16][ 6] =  14.82; aaMtrev24[16][ 7] =  11.17; aaMtrev24[16][ 8] =  44.78; aaMtrev24[16][ 9] = 368.43;
    aaMtrev24[16][10] = 126.40; aaMtrev24[16][11] = 136.33; aaMtrev24[16][12] = 528.17; aaMtrev24[16][13] =  33.85; aaMtrev24[16][14] = 128.22;
    aaMtrev24[16][15] = 597.21; aaMtrev24[16][16] =   0.00; aaMtrev24[16][17] =   9.99; aaMtrev24[16][18] =  38.73; aaMtrev24[16][19] = 204.54;
    aaMtrev24[17][ 0] =   1.90; aaMtrev24[17][ 1] =  21.95; aaMtrev24[17][ 2] =  10.68; aaMtrev24[17][ 3] =  19.86; aaMtrev24[17][ 4] =  33.60;
    aaMtrev24[17][ 5] =   1.90; aaMtrev24[17][ 6] =   1.90; aaMtrev24[17][ 7] =  10.92; aaMtrev24[17][ 8] =   7.08; aaMtrev24[17][ 9] =   1.90;
    aaMtrev24[17][10] =  32.44; aaMtrev24[17][11] =  24.00; aaMtrev24[17][12] =  21.71; aaMtrev24[17][13] =   7.84; aaMtrev24[17][14] =   4.21;
    aaMtrev24[17][15] =  38.58; aaMtrev24[17][16] =   9.99; aaMtrev24[17][17] =   0.00; aaMtrev24[17][18] =  26.25; aaMtrev24[17][19] =   5.37;
    aaMtrev24[18][ 0] =   6.48; aaMtrev24[18][ 1] =   1.90; aaMtrev24[18][ 2] = 191.36; aaMtrev24[18][ 3] =  21.21; aaMtrev24[18][ 4] = 254.77;
    aaMtrev24[18][ 5] =  38.82; aaMtrev24[18][ 6] =  13.12; aaMtrev24[18][ 7] =   3.21; aaMtrev24[18][ 8] = 670.14; aaMtrev24[18][ 9] =  25.01;
    aaMtrev24[18][10] =  44.15; aaMtrev24[18][11] =  51.17; aaMtrev24[18][12] =  39.96; aaMtrev24[18][13] = 465.58; aaMtrev24[18][14] =  16.21;
    aaMtrev24[18][15] =  64.92; aaMtrev24[18][16] =  38.73; aaMtrev24[18][17] =  26.25; aaMtrev24[18][18] =   0.00; aaMtrev24[18][19] =   1.90;
    aaMtrev24[19][ 0] = 195.06; aaMtrev24[19][ 1] =   7.64; aaMtrev24[19][ 2] =   1.90; aaMtrev24[19][ 3] =   1.90; aaMtrev24[19][ 4] =   1.90;
    aaMtrev24[19][ 5] =  19.00; aaMtrev24[19][ 6] =  21.14; aaMtrev24[19][ 7] =   2.53; aaMtrev24[19][ 8] =   1.90; aaMtrev24[19][ 9] =1222.94;
    aaMtrev24[19][10] =  91.67; aaMtrev24[19][11] =   1.90; aaMtrev24[19][12] = 387.54; aaMtrev24[19][13] =   6.35; aaMtrev24[19][14] =   8.23;
    aaMtrev24[19][15] =   1.90; aaMtrev24[19][16] = 204.54; aaMtrev24[19][17] =   5.37; aaMtrev24[19][18] =   1.90; aaMtrev24[19][19] =   0.00;

    mtrev24Pi[ 0] = 0.072;
    mtrev24Pi[ 1] = 0.019;
    mtrev24Pi[ 2] = 0.039;
    mtrev24Pi[ 3] = 0.019;
    mtrev24Pi[ 4] = 0.006;
    mtrev24Pi[ 5] = 0.025;
    mtrev24Pi[ 6] = 0.024;
    mtrev24Pi[ 7] = 0.056;
    mtrev24Pi[ 8] = 0.028;
    mtrev24Pi[ 9] = 0.088;
    mtrev24Pi[10] = 0.168;
    mtrev24Pi[11] = 0.023;
    mtrev24Pi[12] = 0.054;
    mtrev24Pi[13] = 0.061;
    mtrev24Pi[14] = 0.054;
    mtrev24Pi[15] = 0.072;
    mtrev24Pi[16] = 0.086;
    mtrev24Pi[17] = 0.029;
    mtrev24Pi[18] = 0.033;
    mtrev24Pi[19] = 0.043;
    
    /* mtmam */
    aaMtmam[ 0][ 0] =   0; aaMtmam[ 0][ 1] =  32; aaMtmam[ 0][ 2] =   2; aaMtmam[ 0][ 3] =  11; aaMtmam[ 0][ 4] =   0;
    aaMtmam[ 0][ 5] =   0; aaMtmam[ 0][ 6] =   0; aaMtmam[ 0][ 7] =  78; aaMtmam[ 0][ 8] =   8; aaMtmam[ 0][ 9] =  75;
    aaMtmam[ 0][10] =  21; aaMtmam[ 0][11] =   0; aaMtmam[ 0][12] =  76; aaMtmam[ 0][13] =   0; aaMtmam[ 0][14] =  53;
    aaMtmam[ 0][15] = 342; aaMtmam[ 0][16] = 681; aaMtmam[ 0][17] =   5; aaMtmam[ 0][18] =   0; aaMtmam[ 0][19] = 398;
    aaMtmam[ 1][ 0] =  32; aaMtmam[ 1][ 1] =   0; aaMtmam[ 1][ 2] =   4; aaMtmam[ 1][ 3] =   0; aaMtmam[ 1][ 4] = 186;
    aaMtmam[ 1][ 5] = 246; aaMtmam[ 1][ 6] =   0; aaMtmam[ 1][ 7] =  18; aaMtmam[ 1][ 8] = 232; aaMtmam[ 1][ 9] =   0;
    aaMtmam[ 1][10] =   6; aaMtmam[ 1][11] =  50; aaMtmam[ 1][12] =   0; aaMtmam[ 1][13] =   0; aaMtmam[ 1][14] =   9;
    aaMtmam[ 1][15] =   3; aaMtmam[ 1][16] =   0; aaMtmam[ 1][17] =  16; aaMtmam[ 1][18] =   0; aaMtmam[ 1][19] =   0;
    aaMtmam[ 2][ 0] =   2; aaMtmam[ 2][ 1] =   4; aaMtmam[ 2][ 2] =   0; aaMtmam[ 2][ 3] = 864; aaMtmam[ 2][ 4] =   0;
    aaMtmam[ 2][ 5] =   8; aaMtmam[ 2][ 6] =   0; aaMtmam[ 2][ 7] =  47; aaMtmam[ 2][ 8] = 458; aaMtmam[ 2][ 9] =  19;
    aaMtmam[ 2][10] =   0; aaMtmam[ 2][11] = 408; aaMtmam[ 2][12] =  21; aaMtmam[ 2][13] =   6; aaMtmam[ 2][14] =  33;
    aaMtmam[ 2][15] = 446; aaMtmam[ 2][16] = 110; aaMtmam[ 2][17] =   6; aaMtmam[ 2][18] = 156; aaMtmam[ 2][19] =   0;
    aaMtmam[ 3][ 0] =  11; aaMtmam[ 3][ 1] =   0; aaMtmam[ 3][ 2] = 864; aaMtmam[ 3][ 3] =   0; aaMtmam[ 3][ 4] =   0;
    aaMtmam[ 3][ 5] =  49; aaMtmam[ 3][ 6] = 569; aaMtmam[ 3][ 7] =  79; aaMtmam[ 3][ 8] =  11; aaMtmam[ 3][ 9] =   0;
    aaMtmam[ 3][10] =   0; aaMtmam[ 3][11] =   0; aaMtmam[ 3][12] =   0; aaMtmam[ 3][13] =   5; aaMtmam[ 3][14] =   2;
    aaMtmam[ 3][15] =  16; aaMtmam[ 3][16] =   0; aaMtmam[ 3][17] =   0; aaMtmam[ 3][18] =   0; aaMtmam[ 3][19] =  10;
    aaMtmam[ 4][ 0] =   0; aaMtmam[ 4][ 1] = 186; aaMtmam[ 4][ 2] =   0; aaMtmam[ 4][ 3] =   0; aaMtmam[ 4][ 4] =   0;
    aaMtmam[ 4][ 5] =   0; aaMtmam[ 4][ 6] =   0; aaMtmam[ 4][ 7] =   0; aaMtmam[ 4][ 8] = 305; aaMtmam[ 4][ 9] =  41;
    aaMtmam[ 4][10] =  27; aaMtmam[ 4][11] =   0; aaMtmam[ 4][12] =   0; aaMtmam[ 4][13] =   7; aaMtmam[ 4][14] =   0;
    aaMtmam[ 4][15] = 347; aaMtmam[ 4][16] = 114; aaMtmam[ 4][17] =  65; aaMtmam[ 4][18] = 530; aaMtmam[ 4][19] =   0;
    aaMtmam[ 5][ 0] =   0; aaMtmam[ 5][ 1] = 246; aaMtmam[ 5][ 2] =   8; aaMtmam[ 5][ 3] =  49; aaMtmam[ 5][ 4] =   0;
    aaMtmam[ 5][ 5] =   0; aaMtmam[ 5][ 6] = 274; aaMtmam[ 5][ 7] =   0; aaMtmam[ 5][ 8] = 550; aaMtmam[ 5][ 9] =   0;
    aaMtmam[ 5][10] =  20; aaMtmam[ 5][11] = 242; aaMtmam[ 5][12] =  22; aaMtmam[ 5][13] =   0; aaMtmam[ 5][14] =  51;
    aaMtmam[ 5][15] =  30; aaMtmam[ 5][16] =   0; aaMtmam[ 5][17] =   0; aaMtmam[ 5][18] =  54; aaMtmam[ 5][19] =  33;
    aaMtmam[ 6][ 0] =   0; aaMtmam[ 6][ 1] =   0; aaMtmam[ 6][ 2] =   0; aaMtmam[ 6][ 3] = 569; aaMtmam[ 6][ 4] =   0;
    aaMtmam[ 6][ 5] = 274; aaMtmam[ 6][ 6] =   0; aaMtmam[ 6][ 7] =  22; aaMtmam[ 6][ 8] =  22; aaMtmam[ 6][ 9] =   0;
    aaMtmam[ 6][10] =   0; aaMtmam[ 6][11] = 215; aaMtmam[ 6][12] =   0; aaMtmam[ 6][13] =   0; aaMtmam[ 6][14] =   0;
    aaMtmam[ 6][15] =  21; aaMtmam[ 6][16] =   4; aaMtmam[ 6][17] =   0; aaMtmam[ 6][18] =   0; aaMtmam[ 6][19] =  20;
    aaMtmam[ 7][ 0] =  78; aaMtmam[ 7][ 1] =  18; aaMtmam[ 7][ 2] =  47; aaMtmam[ 7][ 3] =  79; aaMtmam[ 7][ 4] =   0;
    aaMtmam[ 7][ 5] =   0; aaMtmam[ 7][ 6] =  22; aaMtmam[ 7][ 7] =   0; aaMtmam[ 7][ 8] =   0; aaMtmam[ 7][ 9] =   0;
    aaMtmam[ 7][10] =   0; aaMtmam[ 7][11] =   0; aaMtmam[ 7][12] =   0; aaMtmam[ 7][13] =   0; aaMtmam[ 7][14] =   0;
    aaMtmam[ 7][15] = 112; aaMtmam[ 7][16] =   0; aaMtmam[ 7][17] =   0; aaMtmam[ 7][18] =   1; aaMtmam[ 7][19] =   5;
    aaMtmam[ 8][ 0] =   8; aaMtmam[ 8][ 1] = 232; aaMtmam[ 8][ 2] = 458; aaMtmam[ 8][ 3] =  11; aaMtmam[ 8][ 4] = 305;
    aaMtmam[ 8][ 5] = 550; aaMtmam[ 8][ 6] =  22; aaMtmam[ 8][ 7] =   0; aaMtmam[ 8][ 8] =   0; aaMtmam[ 8][ 9] =   0;
    aaMtmam[ 8][10] =  26; aaMtmam[ 8][11] =   0; aaMtmam[ 8][12] =   0; aaMtmam[ 8][13] =   0; aaMtmam[ 8][14] =  53;
    aaMtmam[ 8][15] =  20; aaMtmam[ 8][16] =   1; aaMtmam[ 8][17] =   0; aaMtmam[ 8][18] =1525; aaMtmam[ 8][19] =   0;
    aaMtmam[ 9][ 0] =  75; aaMtmam[ 9][ 1] =   0; aaMtmam[ 9][ 2] =  19; aaMtmam[ 9][ 3] =   0; aaMtmam[ 9][ 4] =  41;
    aaMtmam[ 9][ 5] =   0; aaMtmam[ 9][ 6] =   0; aaMtmam[ 9][ 7] =   0; aaMtmam[ 9][ 8] =   0; aaMtmam[ 9][ 9] =   0;
    aaMtmam[ 9][10] = 232; aaMtmam[ 9][11] =   6; aaMtmam[ 9][12] = 378; aaMtmam[ 9][13] =  57; aaMtmam[ 9][14] =   5;
    aaMtmam[ 9][15] =   0; aaMtmam[ 9][16] = 360; aaMtmam[ 9][17] =   0; aaMtmam[ 9][18] =  16; aaMtmam[ 9][19] =2220;
    aaMtmam[10][ 0] =  21; aaMtmam[10][ 1] =   6; aaMtmam[10][ 2] =   0; aaMtmam[10][ 3] =   0; aaMtmam[10][ 4] =  27;
    aaMtmam[10][ 5] =  20; aaMtmam[10][ 6] =   0; aaMtmam[10][ 7] =   0; aaMtmam[10][ 8] =  26; aaMtmam[10][ 9] = 232;
    aaMtmam[10][10] =   0; aaMtmam[10][11] =   4; aaMtmam[10][12] = 609; aaMtmam[10][13] = 246; aaMtmam[10][14] =  43;
    aaMtmam[10][15] =  74; aaMtmam[10][16] =  34; aaMtmam[10][17] =  12; aaMtmam[10][18] =  25; aaMtmam[10][19] = 100;
    aaMtmam[11][ 0] =   0; aaMtmam[11][ 1] =  50; aaMtmam[11][ 2] = 408; aaMtmam[11][ 3] =   0; aaMtmam[11][ 4] =   0;
    aaMtmam[11][ 5] = 242; aaMtmam[11][ 6] = 215; aaMtmam[11][ 7] =   0; aaMtmam[11][ 8] =   0; aaMtmam[11][ 9] =   6;
    aaMtmam[11][10] =   4; aaMtmam[11][11] =   0; aaMtmam[11][12] =  59; aaMtmam[11][13] =   0; aaMtmam[11][14] =  18;
    aaMtmam[11][15] =  65; aaMtmam[11][16] =  50; aaMtmam[11][17] =   0; aaMtmam[11][18] =  67; aaMtmam[11][19] =   0;
    aaMtmam[12][ 0] =  76; aaMtmam[12][ 1] =   0; aaMtmam[12][ 2] =  21; aaMtmam[12][ 3] =   0; aaMtmam[12][ 4] =   0;
    aaMtmam[12][ 5] =  22; aaMtmam[12][ 6] =   0; aaMtmam[12][ 7] =   0; aaMtmam[12][ 8] =   0; aaMtmam[12][ 9] = 378;
    aaMtmam[12][10] = 609; aaMtmam[12][11] =  59; aaMtmam[12][12] =   0; aaMtmam[12][13] =  11; aaMtmam[12][14] =   0;
    aaMtmam[12][15] =  47; aaMtmam[12][16] = 691; aaMtmam[12][17] =  13; aaMtmam[12][18] =   0; aaMtmam[12][19] = 832;
    aaMtmam[13][ 0] =   0; aaMtmam[13][ 1] =   0; aaMtmam[13][ 2] =   6; aaMtmam[13][ 3] =   5; aaMtmam[13][ 4] =   7;
    aaMtmam[13][ 5] =   0; aaMtmam[13][ 6] =   0; aaMtmam[13][ 7] =   0; aaMtmam[13][ 8] =   0; aaMtmam[13][ 9] =  57;
    aaMtmam[13][10] = 246; aaMtmam[13][11] =   0; aaMtmam[13][12] =  11; aaMtmam[13][13] =   0; aaMtmam[13][14] =  17;
    aaMtmam[13][15] =  90; aaMtmam[13][16] =   8; aaMtmam[13][17] =   0; aaMtmam[13][18] = 682; aaMtmam[13][19] =   6;
    aaMtmam[14][ 0] =  53; aaMtmam[14][ 1] =   9; aaMtmam[14][ 2] =  33; aaMtmam[14][ 3] =   2; aaMtmam[14][ 4] =   0;
    aaMtmam[14][ 5] =  51; aaMtmam[14][ 6] =   0; aaMtmam[14][ 7] =   0; aaMtmam[14][ 8] =  53; aaMtmam[14][ 9] =   5;
    aaMtmam[14][10] =  43; aaMtmam[14][11] =  18; aaMtmam[14][12] =   0; aaMtmam[14][13] =  17; aaMtmam[14][14] =   0;
    aaMtmam[14][15] = 202; aaMtmam[14][16] =  78; aaMtmam[14][17] =   7; aaMtmam[14][18] =   8; aaMtmam[14][19] =   0;
    aaMtmam[15][ 0] = 342; aaMtmam[15][ 1] =   3; aaMtmam[15][ 2] = 446; aaMtmam[15][ 3] =  16; aaMtmam[15][ 4] = 347;
    aaMtmam[15][ 5] =  30; aaMtmam[15][ 6] =  21; aaMtmam[15][ 7] = 112; aaMtmam[15][ 8] =  20; aaMtmam[15][ 9] =   0;
    aaMtmam[15][10] =  74; aaMtmam[15][11] =  65; aaMtmam[15][12] =  47; aaMtmam[15][13] =  90; aaMtmam[15][14] = 202;
    aaMtmam[15][15] =   0; aaMtmam[15][16] = 614; aaMtmam[15][17] =  17; aaMtmam[15][18] = 107; aaMtmam[15][19] =   0;
    aaMtmam[16][ 0] = 681; aaMtmam[16][ 1] =   0; aaMtmam[16][ 2] = 110; aaMtmam[16][ 3] =   0; aaMtmam[16][ 4] = 114;
    aaMtmam[16][ 5] =   0; aaMtmam[16][ 6] =   4; aaMtmam[16][ 7] =   0; aaMtmam[16][ 8] =   1; aaMtmam[16][ 9] = 360;
    aaMtmam[16][10] =  34; aaMtmam[16][11] =  50; aaMtmam[16][12] = 691; aaMtmam[16][13] =   8; aaMtmam[16][14] =  78;
    aaMtmam[16][15] = 614; aaMtmam[16][16] =   0; aaMtmam[16][17] =   0; aaMtmam[16][18] =   0; aaMtmam[16][19] = 237;
    aaMtmam[17][ 0] =   5; aaMtmam[17][ 1] =  16; aaMtmam[17][ 2] =   6; aaMtmam[17][ 3] =   0; aaMtmam[17][ 4] =  65;
    aaMtmam[17][ 5] =   0; aaMtmam[17][ 6] =   0; aaMtmam[17][ 7] =   0; aaMtmam[17][ 8] =   0; aaMtmam[17][ 9] =   0;
    aaMtmam[17][10] =  12; aaMtmam[17][11] =   0; aaMtmam[17][12] =  13; aaMtmam[17][13] =   0; aaMtmam[17][14] =   7;
    aaMtmam[17][15] =  17; aaMtmam[17][16] =   0; aaMtmam[17][17] =   0; aaMtmam[17][18] =  14; aaMtmam[17][19] =   0;
    aaMtmam[18][ 0] =   0; aaMtmam[18][ 1] =   0; aaMtmam[18][ 2] = 156; aaMtmam[18][ 3] =   0; aaMtmam[18][ 4] = 530;
    aaMtmam[18][ 5] =  54; aaMtmam[18][ 6] =   0; aaMtmam[18][ 7] =   1; aaMtmam[18][ 8] =1525; aaMtmam[18][ 9] =  16;
    aaMtmam[18][10] =  25; aaMtmam[18][11] =  67; aaMtmam[18][12] =   0; aaMtmam[18][13] = 682; aaMtmam[18][14] =   8;
    aaMtmam[18][15] = 107; aaMtmam[18][16] =   0; aaMtmam[18][17] =  14; aaMtmam[18][18] =   0; aaMtmam[18][19] =   0;
    aaMtmam[19][ 0] = 398; aaMtmam[19][ 1] =   0; aaMtmam[19][ 2] =   0; aaMtmam[19][ 3] =  10; aaMtmam[19][ 4] =   0;
    aaMtmam[19][ 5] =  33; aaMtmam[19][ 6] =  20; aaMtmam[19][ 7] =   5; aaMtmam[19][ 8] =   0; aaMtmam[19][ 9] =2220;
    aaMtmam[19][10] = 100; aaMtmam[19][11] =   0; aaMtmam[19][12] = 832; aaMtmam[19][13] =   6; aaMtmam[19][14] =   0;
    aaMtmam[19][15] =   0; aaMtmam[19][16] = 237; aaMtmam[19][17] =   0; aaMtmam[19][18] =   0; aaMtmam[19][19] =   0;

    mtmamPi[ 0] = 0.0692;
    mtmamPi[ 1] = 0.0184;
    mtmamPi[ 2] = 0.0400;
    mtmamPi[ 3] = 0.0186;
    mtmamPi[ 4] = 0.0065;
    mtmamPi[ 5] = 0.0238;
    mtmamPi[ 6] = 0.0236;
    mtmamPi[ 7] = 0.0557;
    mtmamPi[ 8] = 0.0277;
    mtmamPi[ 9] = 0.0905;
    mtmamPi[10] = 0.1675;
    mtmamPi[11] = 0.0221;
    mtmamPi[12] = 0.0561;
    mtmamPi[13] = 0.0611;
    mtmamPi[14] = 0.0536;
    mtmamPi[15] = 0.0725;
    mtmamPi[16] = 0.0870;
    mtmamPi[17] = 0.0293;
    mtmamPi[18] = 0.0340;
    mtmamPi[19] = 0.0428;
    
    /* rtRev */
    aartREV[ 0][ 0] =   0; aartREV[ 1][ 0] =  34; aartREV[ 2][ 0] =  51; aartREV[ 3][ 0] =  10; aartREV[ 4][ 0] = 439;
    aartREV[ 5][ 0] =  32; aartREV[ 6][ 0] =  81; aartREV[ 7][ 0] = 135; aartREV[ 8][ 0] =  30; aartREV[ 9][ 0] =   1;
    aartREV[10][ 0] =  45; aartREV[11][ 0] =  38; aartREV[12][ 0] = 235; aartREV[13][ 0] =   1; aartREV[14][ 0] =  97;
    aartREV[15][ 0] = 460; aartREV[16][ 0] = 258; aartREV[17][ 0] =   5; aartREV[18][ 0] =  55; aartREV[19][ 0] = 197;
    aartREV[ 0][ 1] =  34; aartREV[ 1][ 1] =   0; aartREV[ 2][ 1] =  35; aartREV[ 3][ 1] =  30; aartREV[ 4][ 1] =  92;
    aartREV[ 5][ 1] = 221; aartREV[ 6][ 1] =  10; aartREV[ 7][ 1] =  41; aartREV[ 8][ 1] =  90; aartREV[ 9][ 1] =  24;
    aartREV[10][ 1] =  18; aartREV[11][ 1] = 593; aartREV[12][ 1] =  57; aartREV[13][ 1] =   7; aartREV[14][ 1] =  24;
    aartREV[15][ 1] = 102; aartREV[16][ 1] =  64; aartREV[17][ 1] =  13; aartREV[18][ 1] =  47; aartREV[19][ 1] =  29;
    aartREV[ 0][ 2] =  51; aartREV[ 1][ 2] =  35; aartREV[ 2][ 2] =   0; aartREV[ 3][ 2] = 384; aartREV[ 4][ 2] = 128;
    aartREV[ 5][ 2] = 236; aartREV[ 6][ 2] =  79; aartREV[ 7][ 2] =  94; aartREV[ 8][ 2] = 320; aartREV[ 9][ 2] =  35;
    aartREV[10][ 2] =  15; aartREV[11][ 2] = 123; aartREV[12][ 2] =   1; aartREV[13][ 2] =  49; aartREV[14][ 2] =  33;
    aartREV[15][ 2] = 294; aartREV[16][ 2] = 148; aartREV[17][ 2] =  16; aartREV[18][ 2] =  28; aartREV[19][ 2] =  21;
    aartREV[ 0][ 3] =  10; aartREV[ 1][ 3] =  30; aartREV[ 2][ 3] = 384; aartREV[ 3][ 3] =   0; aartREV[ 4][ 3] =   1;
    aartREV[ 5][ 3] =  78; aartREV[ 6][ 3] = 542; aartREV[ 7][ 3] =  61; aartREV[ 8][ 3] =  91; aartREV[ 9][ 3] =   1;
    aartREV[10][ 3] =   5; aartREV[11][ 3] =  20; aartREV[12][ 3] =   1; aartREV[13][ 3] =   1; aartREV[14][ 3] =  55;
    aartREV[15][ 3] = 136; aartREV[16][ 3] =  55; aartREV[17][ 3] =   1; aartREV[18][ 3] =   1; aartREV[19][ 3] =   6;
    aartREV[ 0][ 4] = 439; aartREV[ 1][ 4] =  92; aartREV[ 2][ 4] = 128; aartREV[ 3][ 4] =   1; aartREV[ 4][ 4] =   0;
    aartREV[ 5][ 4] =  70; aartREV[ 6][ 4] =   1; aartREV[ 7][ 4] =  48; aartREV[ 8][ 4] = 124; aartREV[ 9][ 4] = 104;
    aartREV[10][ 4] = 110; aartREV[11][ 4] =  16; aartREV[12][ 4] = 156; aartREV[13][ 4] =  70; aartREV[14][ 4] =   1;
    aartREV[15][ 4] =  75; aartREV[16][ 4] = 117; aartREV[17][ 4] =  55; aartREV[18][ 4] = 131; aartREV[19][ 4] = 295;
    aartREV[ 0][ 5] =  32; aartREV[ 1][ 5] = 221; aartREV[ 2][ 5] = 236; aartREV[ 3][ 5] =  78; aartREV[ 4][ 5] =  70;
    aartREV[ 5][ 5] =   0; aartREV[ 6][ 5] = 372; aartREV[ 7][ 5] =  18; aartREV[ 8][ 5] = 387; aartREV[ 9][ 5] =  33;
    aartREV[10][ 5] =  54; aartREV[11][ 5] = 309; aartREV[12][ 5] = 158; aartREV[13][ 5] =   1; aartREV[14][ 5] =  68;
    aartREV[15][ 5] = 225; aartREV[16][ 5] = 146; aartREV[17][ 5] =  10; aartREV[18][ 5] =  45; aartREV[19][ 5] =  36;
    aartREV[ 0][ 6] =  81; aartREV[ 1][ 6] =  10; aartREV[ 2][ 6] =  79; aartREV[ 3][ 6] = 542; aartREV[ 4][ 6] =   1;
    aartREV[ 5][ 6] = 372; aartREV[ 6][ 6] =   0; aartREV[ 7][ 6] =  70; aartREV[ 8][ 6] =  34; aartREV[ 9][ 6] =   1;
    aartREV[10][ 6] =  21; aartREV[11][ 6] = 141; aartREV[12][ 6] =   1; aartREV[13][ 6] =   1; aartREV[14][ 6] =  52;
    aartREV[15][ 6] =  95; aartREV[16][ 6] =  82; aartREV[17][ 6] =  17; aartREV[18][ 6] =   1; aartREV[19][ 6] =  35;
    aartREV[ 0][ 7] = 135; aartREV[ 1][ 7] =  41; aartREV[ 2][ 7] =  94; aartREV[ 3][ 7] =  61; aartREV[ 4][ 7] =  48;
    aartREV[ 5][ 7] =  18; aartREV[ 6][ 7] =  70; aartREV[ 7][ 7] =   0; aartREV[ 8][ 7] =  68; aartREV[ 9][ 7] =   1;
    aartREV[10][ 7] =   3; aartREV[11][ 7] =  30; aartREV[12][ 7] =  37; aartREV[13][ 7] =   7; aartREV[14][ 7] =  17;
    aartREV[15][ 7] = 152; aartREV[16][ 7] =   7; aartREV[17][ 7] =  23; aartREV[18][ 7] =  21; aartREV[19][ 7] =   3;
    aartREV[ 0][ 8] =  30; aartREV[ 1][ 8] =  90; aartREV[ 2][ 8] = 320; aartREV[ 3][ 8] =  91; aartREV[ 4][ 8] = 124;
    aartREV[ 5][ 8] = 387; aartREV[ 6][ 8] =  34; aartREV[ 7][ 8] =  68; aartREV[ 8][ 8] =   0; aartREV[ 9][ 8] =  34;
    aartREV[10][ 8] =  51; aartREV[11][ 8] =  76; aartREV[12][ 8] = 116; aartREV[13][ 8] = 141; aartREV[14][ 8] =  44;
    aartREV[15][ 8] = 183; aartREV[16][ 8] =  49; aartREV[17][ 8] =  48; aartREV[18][ 8] = 307; aartREV[19][ 8] =   1;
    aartREV[ 0][ 9] =   1; aartREV[ 1][ 9] =  24; aartREV[ 2][ 9] =  35; aartREV[ 3][ 9] =   1; aartREV[ 4][ 9] = 104;
    aartREV[ 5][ 9] =  33; aartREV[ 6][ 9] =   1; aartREV[ 7][ 9] =   1; aartREV[ 8][ 9] =  34; aartREV[ 9][ 9] =   0;
    aartREV[10][ 9] = 385; aartREV[11][ 9] =  34; aartREV[12][ 9] = 375; aartREV[13][ 9] =  64; aartREV[14][ 9] =  10;
    aartREV[15][ 9] =   4; aartREV[16][ 9] =  72; aartREV[17][ 9] =  39; aartREV[18][ 9] =  26; aartREV[19][ 9] =1048;
    aartREV[ 0][10] =  45; aartREV[ 1][10] =  18; aartREV[ 2][10] =  15; aartREV[ 3][10] =   5; aartREV[ 4][10] = 110;
    aartREV[ 5][10] =  54; aartREV[ 6][10] =  21; aartREV[ 7][10] =   3; aartREV[ 8][10] =  51; aartREV[ 9][10] = 385;
    aartREV[10][10] =   0; aartREV[11][10] =  23; aartREV[12][10] = 581; aartREV[13][10] = 179; aartREV[14][10] =  22;
    aartREV[15][10] =  24; aartREV[16][10] =  25; aartREV[17][10] =  47; aartREV[18][10] =  64; aartREV[19][10] = 112;
    aartREV[ 0][11] =  38; aartREV[ 1][11] = 593; aartREV[ 2][11] = 123; aartREV[ 3][11] =  20; aartREV[ 4][11] =  16;
    aartREV[ 5][11] = 309; aartREV[ 6][11] = 141; aartREV[ 7][11] =  30; aartREV[ 8][11] =  76; aartREV[ 9][11] =  34;
    aartREV[10][11] =  23; aartREV[11][11] =   0; aartREV[12][11] = 134; aartREV[13][11] =  14; aartREV[14][11] =  43;
    aartREV[15][11] =  77; aartREV[16][11] = 110; aartREV[17][11] =   6; aartREV[18][11] =   1; aartREV[19][11] =  19;
    aartREV[ 0][12] = 235; aartREV[ 1][12] =  57; aartREV[ 2][12] =   1; aartREV[ 3][12] =   1; aartREV[ 4][12] = 156;
    aartREV[ 5][12] = 158; aartREV[ 6][12] =   1; aartREV[ 7][12] =  37; aartREV[ 8][12] = 116; aartREV[ 9][12] = 375;
    aartREV[10][12] = 581; aartREV[11][12] = 134; aartREV[12][12] =   0; aartREV[13][12] = 247; aartREV[14][12] =   1;
    aartREV[15][12] =   1; aartREV[16][12] = 131; aartREV[17][12] = 111; aartREV[18][12] =  74; aartREV[19][12] = 236;
    aartREV[ 0][13] =   1; aartREV[ 1][13] =   7; aartREV[ 2][13] =  49; aartREV[ 3][13] =   1; aartREV[ 4][13] =  70;
    aartREV[ 5][13] =   1; aartREV[ 6][13] =   1; aartREV[ 7][13] =   7; aartREV[ 8][13] = 141; aartREV[ 9][13] =  64;
    aartREV[10][13] = 179; aartREV[11][13] =  14; aartREV[12][13] = 247; aartREV[13][13] =   0; aartREV[14][13] =  11;
    aartREV[15][13] =  20; aartREV[16][13] =  69; aartREV[17][13] = 182; aartREV[18][13] =1017; aartREV[19][13] =  92;
    aartREV[ 0][14] =  97; aartREV[ 1][14] =  24; aartREV[ 2][14] =  33; aartREV[ 3][14] =  55; aartREV[ 4][14] =   1;
    aartREV[ 5][14] =  68; aartREV[ 6][14] =  52; aartREV[ 7][14] =  17; aartREV[ 8][14] =  44; aartREV[ 9][14] =  10;
    aartREV[10][14] =  22; aartREV[11][14] =  43; aartREV[12][14] =   1; aartREV[13][14] =  11; aartREV[14][14] =   0;
    aartREV[15][14] = 134; aartREV[16][14] =  62; aartREV[17][14] =   9; aartREV[18][14] =  14; aartREV[19][14] =  25;
    aartREV[ 0][15] = 460; aartREV[ 1][15] = 102; aartREV[ 2][15] = 294; aartREV[ 3][15] = 136; aartREV[ 4][15] =  75;
    aartREV[ 5][15] = 225; aartREV[ 6][15] =  95; aartREV[ 7][15] = 152; aartREV[ 8][15] = 183; aartREV[ 9][15] =   4;
    aartREV[10][15] =  24; aartREV[11][15] =  77; aartREV[12][15] =   1; aartREV[13][15] =  20; aartREV[14][15] = 134;
    aartREV[15][15] =   0; aartREV[16][15] = 671; aartREV[17][15] =  14; aartREV[18][15] =  31; aartREV[19][15] =  39;
    aartREV[ 0][16] = 258; aartREV[ 1][16] =  64; aartREV[ 2][16] = 148; aartREV[ 3][16] =  55; aartREV[ 4][16] = 117;
    aartREV[ 5][16] = 146; aartREV[ 6][16] =  82; aartREV[ 7][16] =   7; aartREV[ 8][16] =  49; aartREV[ 9][16] =  72;
    aartREV[10][16] =  25; aartREV[11][16] = 110; aartREV[12][16] = 131; aartREV[13][16] =  69; aartREV[14][16] =  62;
    aartREV[15][16] = 671; aartREV[16][16] =   0; aartREV[17][16] =   1; aartREV[18][16] =  34; aartREV[19][16] = 196;
    aartREV[ 0][17] =   5; aartREV[ 1][17] =  13; aartREV[ 2][17] =  16; aartREV[ 3][17] =   1; aartREV[ 4][17] =  55;
    aartREV[ 5][17] =  10; aartREV[ 6][17] =  17; aartREV[ 7][17] =  23; aartREV[ 8][17] =  48; aartREV[ 9][17] =  39;
    aartREV[10][17] =  47; aartREV[11][17] =   6; aartREV[12][17] = 111; aartREV[13][17] = 182; aartREV[14][17] =   9;
    aartREV[15][17] =  14; aartREV[16][17] =   1; aartREV[17][17] =   0; aartREV[18][17] = 176; aartREV[19][17] =  26;
    aartREV[ 0][18] =  55; aartREV[ 1][18] =  47; aartREV[ 2][18] =  28; aartREV[ 3][18] =   1; aartREV[ 4][18] = 131;
    aartREV[ 5][18] =  45; aartREV[ 6][18] =   1; aartREV[ 7][18] =  21; aartREV[ 8][18] = 307; aartREV[ 9][18] =  26;
    aartREV[10][18] =  64; aartREV[11][18] =   1; aartREV[12][18] =  74; aartREV[13][18] =1017; aartREV[14][18] =  14;
    aartREV[15][18] =  31; aartREV[16][18] =  34; aartREV[17][18] = 176; aartREV[18][18] =   0; aartREV[19][18] =  59;
    aartREV[ 0][19] = 197; aartREV[ 1][19] =  29; aartREV[ 2][19] =  21; aartREV[ 3][19] =   6; aartREV[ 4][19] = 295;
    aartREV[ 5][19] =  36; aartREV[ 6][19] =  35; aartREV[ 7][19] =   3; aartREV[ 8][19] =   1; aartREV[ 9][19] =1048;
    aartREV[10][19] = 112; aartREV[11][19] =  19; aartREV[12][19] = 236; aartREV[13][19] =  92; aartREV[14][19] =  25;
    aartREV[15][19] =  39; aartREV[16][19] = 196; aartREV[17][19] =  26; aartREV[18][19] =  59; aartREV[19][19] =   0;
    rtrevPi[ 0] = 0.0646;
    rtrevPi[ 1] = 0.0453;
    rtrevPi[ 2] = 0.0376;
    rtrevPi[ 3] = 0.0422;
    rtrevPi[ 4] = 0.0114;
    rtrevPi[ 5] = 0.0606;
    rtrevPi[ 6] = 0.0607;
    rtrevPi[ 7] = 0.0639;
    rtrevPi[ 8] = 0.0273;
    rtrevPi[ 9] = 0.0679;
    rtrevPi[10] = 0.1018;
    rtrevPi[11] = 0.0751;
    rtrevPi[12] = 0.0150;
    rtrevPi[13] = 0.0287;
    rtrevPi[14] = 0.0681;
    rtrevPi[15] = 0.0488;
    rtrevPi[16] = 0.0622;
    rtrevPi[17] = 0.0251;
    rtrevPi[18] = 0.0318;
    rtrevPi[19] = 0.0619;
    
    /* wag */
    aaWAG[ 0][ 0] = 0.0000000; aaWAG[ 1][ 0] = 0.5515710; aaWAG[ 2][ 0] = 0.5098480; aaWAG[ 3][ 0] = 0.7389980; aaWAG[ 4][ 0] = 1.0270400; 
    aaWAG[ 5][ 0] = 0.9085980; aaWAG[ 6][ 0] = 1.5828500; aaWAG[ 7][ 0] = 1.4167200; aaWAG[ 8][ 0] = 0.3169540; aaWAG[ 9][ 0] = 0.1933350; 
    aaWAG[10][ 0] = 0.3979150; aaWAG[11][ 0] = 0.9062650; aaWAG[12][ 0] = 0.8934960; aaWAG[13][ 0] = 0.2104940; aaWAG[14][ 0] = 1.4385500; 
    aaWAG[15][ 0] = 3.3707900; aaWAG[16][ 0] = 2.1211100; aaWAG[17][ 0] = 0.1131330; aaWAG[18][ 0] = 0.2407350; aaWAG[19][ 0] = 2.0060100;
    aaWAG[ 0][ 1] = 0.5515710; aaWAG[ 1][ 1] = 0.0000000; aaWAG[ 2][ 1] = 0.6353460; aaWAG[ 3][ 1] = 0.1473040; aaWAG[ 4][ 1] = 0.5281910;  
    aaWAG[ 5][ 1] = 3.0355000; aaWAG[ 6][ 1] = 0.4391570; aaWAG[ 7][ 1] = 0.5846650; aaWAG[ 8][ 1] = 2.1371500; aaWAG[ 9][ 1] = 0.1869790;  
    aaWAG[10][ 1] = 0.4976710; aaWAG[11][ 1] = 5.3514200; aaWAG[12][ 1] = 0.6831620; aaWAG[13][ 1] = 0.1027110; aaWAG[14][ 1] = 0.6794890;  
    aaWAG[15][ 1] = 1.2241900; aaWAG[16][ 1] = 0.5544130; aaWAG[17][ 1] = 1.1639200; aaWAG[18][ 1] = 0.3815330; aaWAG[19][ 1] = 0.2518490;
    aaWAG[ 0][ 2] = 0.5098480; aaWAG[ 1][ 2] = 0.6353460; aaWAG[ 2][ 2] = 0.0000000; aaWAG[ 3][ 2] = 5.4294200; aaWAG[ 4][ 2] = 0.2652560;  
    aaWAG[ 5][ 2] = 1.5436400; aaWAG[ 6][ 2] = 0.9471980; aaWAG[ 7][ 2] = 1.1255600; aaWAG[ 8][ 2] = 3.9562900; aaWAG[ 9][ 2] = 0.5542360;  
    aaWAG[10][ 2] = 0.1315280; aaWAG[11][ 2] = 3.0120100; aaWAG[12][ 2] = 0.1982210; aaWAG[13][ 2] = 0.0961621; aaWAG[14][ 2] = 0.1950810;  
    aaWAG[15][ 2] = 3.9742300; aaWAG[16][ 2] = 2.0300600; aaWAG[17][ 2] = 0.0719167; aaWAG[18][ 2] = 1.0860000; aaWAG[19][ 2] = 0.1962460;
    aaWAG[ 0][ 3] = 0.7389980; aaWAG[ 1][ 3] = 0.1473040; aaWAG[ 2][ 3] = 5.4294200; aaWAG[ 3][ 3] = 0.0000000; aaWAG[ 4][ 3] = 0.0302949;  
    aaWAG[ 5][ 3] = 0.6167830; aaWAG[ 6][ 3] = 6.1741600; aaWAG[ 7][ 3] = 0.8655840; aaWAG[ 8][ 3] = 0.9306760; aaWAG[ 9][ 3] = 0.0394370;  
    aaWAG[10][ 3] = 0.0848047; aaWAG[11][ 3] = 0.4798550; aaWAG[12][ 3] = 0.1037540; aaWAG[13][ 3] = 0.0467304; aaWAG[14][ 3] = 0.4239840;  
    aaWAG[15][ 3] = 1.0717600; aaWAG[16][ 3] = 0.3748660; aaWAG[17][ 3] = 0.1297670; aaWAG[18][ 3] = 0.3257110; aaWAG[19][ 3] = 0.1523350;
    aaWAG[ 0][ 4] = 1.0270400; aaWAG[ 1][ 4] = 0.5281910; aaWAG[ 2][ 4] = 0.2652560; aaWAG[ 3][ 4] = 0.0302949; aaWAG[ 4][ 4] = 0.0000000;  
    aaWAG[ 5][ 4] = 0.0988179; aaWAG[ 6][ 4] = 0.0213520; aaWAG[ 7][ 4] = 0.3066740; aaWAG[ 8][ 4] = 0.2489720; aaWAG[ 9][ 4] = 0.1701350;  
    aaWAG[10][ 4] = 0.3842870; aaWAG[11][ 4] = 0.0740339; aaWAG[12][ 4] = 0.3904820; aaWAG[13][ 4] = 0.3980200; aaWAG[14][ 4] = 0.1094040;  
    aaWAG[15][ 4] = 1.4076600; aaWAG[16][ 4] = 0.5129840; aaWAG[17][ 4] = 0.7170700; aaWAG[18][ 4] = 0.5438330; aaWAG[19][ 4] = 1.0021400;
    aaWAG[ 0][ 5] = 0.9085980; aaWAG[ 1][ 5] = 3.0355000; aaWAG[ 2][ 5] = 1.5436400; aaWAG[ 3][ 5] = 0.6167830; aaWAG[ 4][ 5] = 0.0988179;  
    aaWAG[ 5][ 5] = 0.0000000; aaWAG[ 6][ 5] = 5.4694700; aaWAG[ 7][ 5] = 0.3300520; aaWAG[ 8][ 5] = 4.2941100; aaWAG[ 9][ 5] = 0.1139170;  
    aaWAG[10][ 5] = 0.8694890; aaWAG[11][ 5] = 3.8949000; aaWAG[12][ 5] = 1.5452600; aaWAG[13][ 5] = 0.0999208; aaWAG[14][ 5] = 0.9333720;  
    aaWAG[15][ 5] = 1.0288700; aaWAG[16][ 5] = 0.8579280; aaWAG[17][ 5] = 0.2157370; aaWAG[18][ 5] = 0.2277100; aaWAG[19][ 5] = 0.3012810;
    aaWAG[ 0][ 6] = 1.5828500; aaWAG[ 1][ 6] = 0.4391570; aaWAG[ 2][ 6] = 0.9471980; aaWAG[ 3][ 6] = 6.1741600; aaWAG[ 4][ 6] = 0.0213520;  
    aaWAG[ 5][ 6] = 5.4694700; aaWAG[ 6][ 6] = 0.0000000; aaWAG[ 7][ 6] = 0.5677170; aaWAG[ 8][ 6] = 0.5700250; aaWAG[ 9][ 6] = 0.1273950;  
    aaWAG[10][ 6] = 0.1542630; aaWAG[11][ 6] = 2.5844300; aaWAG[12][ 6] = 0.3151240; aaWAG[13][ 6] = 0.0811339; aaWAG[14][ 6] = 0.6823550;  
    aaWAG[15][ 6] = 0.7049390; aaWAG[16][ 6] = 0.8227650; aaWAG[17][ 6] = 0.1565570; aaWAG[18][ 6] = 0.1963030; aaWAG[19][ 6] = 0.5887310;
    aaWAG[ 0][ 7] = 1.4167200; aaWAG[ 1][ 7] = 0.5846650; aaWAG[ 2][ 7] = 1.1255600; aaWAG[ 3][ 7] = 0.8655840; aaWAG[ 4][ 7] = 0.3066740;  
    aaWAG[ 5][ 7] = 0.3300520; aaWAG[ 6][ 7] = 0.5677170; aaWAG[ 7][ 7] = 0.0000000; aaWAG[ 8][ 7] = 0.2494100; aaWAG[ 9][ 7] = 0.0304501;  
    aaWAG[10][ 7] = 0.0613037; aaWAG[11][ 7] = 0.3735580; aaWAG[12][ 7] = 0.1741000; aaWAG[13][ 7] = 0.0499310; aaWAG[14][ 7] = 0.2435700;  
    aaWAG[15][ 7] = 1.3418200; aaWAG[16][ 7] = 0.2258330; aaWAG[17][ 7] = 0.3369830; aaWAG[18][ 7] = 0.1036040; aaWAG[19][ 7] = 0.1872470;
    aaWAG[ 0][ 8] = 0.3169540; aaWAG[ 1][ 8] = 2.1371500; aaWAG[ 2][ 8] = 3.9562900; aaWAG[ 3][ 8] = 0.9306760; aaWAG[ 4][ 8] = 0.2489720;  
    aaWAG[ 5][ 8] = 4.2941100; aaWAG[ 6][ 8] = 0.5700250; aaWAG[ 7][ 8] = 0.2494100; aaWAG[ 8][ 8] = 0.0000000; aaWAG[ 9][ 8] = 0.1381900;  
    aaWAG[10][ 8] = 0.4994620; aaWAG[11][ 8] = 0.8904320; aaWAG[12][ 8] = 0.4041410; aaWAG[13][ 8] = 0.6793710; aaWAG[14][ 8] = 0.6961980;  
    aaWAG[15][ 8] = 0.7401690; aaWAG[16][ 8] = 0.4733070; aaWAG[17][ 8] = 0.2625690; aaWAG[18][ 8] = 3.8734400; aaWAG[19][ 8] = 0.1183580;
    aaWAG[ 0][ 9] = 0.1933350; aaWAG[ 1][ 9] = 0.1869790; aaWAG[ 2][ 9] = 0.5542360; aaWAG[ 3][ 9] = 0.0394370; aaWAG[ 4][ 9] = 0.1701350;  
    aaWAG[ 5][ 9] = 0.1139170; aaWAG[ 6][ 9] = 0.1273950; aaWAG[ 7][ 9] = 0.0304501; aaWAG[ 8][ 9] = 0.1381900; aaWAG[ 9][ 9] = 0.0000000;  
    aaWAG[10][ 9] = 3.1709700; aaWAG[11][ 9] = 0.3238320; aaWAG[12][ 9] = 4.2574600; aaWAG[13][ 9] = 1.0594700; aaWAG[14][ 9] = 0.0999288;  
    aaWAG[15][ 9] = 0.3194400; aaWAG[16][ 9] = 1.4581600; aaWAG[17][ 9] = 0.2124830; aaWAG[18][ 9] = 0.4201700; aaWAG[19][ 9] = 7.8213000;
    aaWAG[ 0][10] = 0.3979150; aaWAG[ 1][10] = 0.4976710; aaWAG[ 2][10] = 0.1315280; aaWAG[ 3][10] = 0.0848047; aaWAG[ 4][10] = 0.3842870;  
    aaWAG[ 5][10] = 0.8694890; aaWAG[ 6][10] = 0.1542630; aaWAG[ 7][10] = 0.0613037; aaWAG[ 8][10] = 0.4994620; aaWAG[ 9][10] = 3.1709700;  
    aaWAG[10][10] = 0.0000000; aaWAG[11][10] = 0.2575550; aaWAG[12][10] = 4.8540200; aaWAG[13][10] = 2.1151700; aaWAG[14][10] = 0.4158440;  
    aaWAG[15][10] = 0.3447390; aaWAG[16][10] = 0.3266220; aaWAG[17][10] = 0.6653090; aaWAG[18][10] = 0.3986180; aaWAG[19][10] = 1.8003400;
    aaWAG[ 0][11] = 0.9062650; aaWAG[ 1][11] = 5.3514200; aaWAG[ 2][11] = 3.0120100; aaWAG[ 3][11] = 0.4798550; aaWAG[ 4][11] = 0.0740339;  
    aaWAG[ 5][11] = 3.8949000; aaWAG[ 6][11] = 2.5844300; aaWAG[ 7][11] = 0.3735580; aaWAG[ 8][11] = 0.8904320; aaWAG[ 9][11] = 0.3238320;  
    aaWAG[10][11] = 0.2575550; aaWAG[11][11] = 0.0000000; aaWAG[12][11] = 0.9342760; aaWAG[13][11] = 0.0888360; aaWAG[14][11] = 0.5568960;  
    aaWAG[15][11] = 0.9671300; aaWAG[16][11] = 1.3869800; aaWAG[17][11] = 0.1375050; aaWAG[18][11] = 0.1332640; aaWAG[19][11] = 0.3054340;
    aaWAG[ 0][12] = 0.8934960; aaWAG[ 1][12] = 0.6831620; aaWAG[ 2][12] = 0.1982210; aaWAG[ 3][12] = 0.1037540; aaWAG[ 4][12] = 0.3904820;  
    aaWAG[ 5][12] = 1.5452600; aaWAG[ 6][12] = 0.3151240; aaWAG[ 7][12] = 0.1741000; aaWAG[ 8][12] = 0.4041410; aaWAG[ 9][12] = 4.2574600;  
    aaWAG[10][12] = 4.8540200; aaWAG[11][12] = 0.9342760; aaWAG[12][12] = 0.0000000; aaWAG[13][12] = 1.1906300; aaWAG[14][12] = 0.1713290;  
    aaWAG[15][12] = 0.4939050; aaWAG[16][12] = 1.5161200; aaWAG[17][12] = 0.5157060; aaWAG[18][12] = 0.4284370; aaWAG[19][12] = 2.0584500;
    aaWAG[ 0][13] = 0.2104940; aaWAG[ 1][13] = 0.1027110; aaWAG[ 2][13] = 0.0961621; aaWAG[ 3][13] = 0.0467304; aaWAG[ 4][13] = 0.3980200;  
    aaWAG[ 5][13] = 0.0999208; aaWAG[ 6][13] = 0.0811339; aaWAG[ 7][13] = 0.0499310; aaWAG[ 8][13] = 0.6793710; aaWAG[ 9][13] = 1.0594700;  
    aaWAG[10][13] = 2.1151700; aaWAG[11][13] = 0.0888360; aaWAG[12][13] = 1.1906300; aaWAG[13][13] = 0.0000000; aaWAG[14][13] = 0.1614440;  
    aaWAG[15][13] = 0.5459310; aaWAG[16][13] = 0.1719030; aaWAG[17][13] = 1.5296400; aaWAG[18][13] = 6.4542800; aaWAG[19][13] = 0.6498920;
    aaWAG[ 0][14] = 1.4385500; aaWAG[ 1][14] = 0.6794890; aaWAG[ 2][14] = 0.1950810; aaWAG[ 3][14] = 0.4239840; aaWAG[ 4][14] = 0.1094040;  
    aaWAG[ 5][14] = 0.9333720; aaWAG[ 6][14] = 0.6823550; aaWAG[ 7][14] = 0.2435700; aaWAG[ 8][14] = 0.6961980; aaWAG[ 9][14] = 0.0999288;  
    aaWAG[10][14] = 0.4158440; aaWAG[11][14] = 0.5568960; aaWAG[12][14] = 0.1713290; aaWAG[13][14] = 0.1614440; aaWAG[14][14] = 0.0000000;  
    aaWAG[15][14] = 1.6132800; aaWAG[16][14] = 0.7953840; aaWAG[17][14] = 0.1394050; aaWAG[18][14] = 0.2160460; aaWAG[19][14] = 0.3148870;
    aaWAG[ 0][15] = 3.3707900; aaWAG[ 1][15] = 1.2241900; aaWAG[ 2][15] = 3.9742300; aaWAG[ 3][15] = 1.0717600; aaWAG[ 4][15] = 1.4076600;  
    aaWAG[ 5][15] = 1.0288700; aaWAG[ 6][15] = 0.7049390; aaWAG[ 7][15] = 1.3418200; aaWAG[ 8][15] = 0.7401690; aaWAG[ 9][15] = 0.3194400;  
    aaWAG[10][15] = 0.3447390; aaWAG[11][15] = 0.9671300; aaWAG[12][15] = 0.4939050; aaWAG[13][15] = 0.5459310; aaWAG[14][15] = 1.6132800;  
    aaWAG[15][15] = 0.0000000; aaWAG[16][15] = 4.3780200; aaWAG[17][15] = 0.5237420; aaWAG[18][15] = 0.7869930; aaWAG[19][15] = 0.2327390;
    aaWAG[ 0][16] = 2.1211100; aaWAG[ 1][16] = 0.5544130; aaWAG[ 2][16] = 2.0300600; aaWAG[ 3][16] = 0.3748660; aaWAG[ 4][16] = 0.5129840;  
    aaWAG[ 5][16] = 0.8579280; aaWAG[ 6][16] = 0.8227650; aaWAG[ 7][16] = 0.2258330; aaWAG[ 8][16] = 0.4733070; aaWAG[ 9][16] = 1.4581600;  
    aaWAG[10][16] = 0.3266220; aaWAG[11][16] = 1.3869800; aaWAG[12][16] = 1.5161200; aaWAG[13][16] = 0.1719030; aaWAG[14][16] = 0.7953840;  
    aaWAG[15][16] = 4.3780200; aaWAG[16][16] = 0.0000000; aaWAG[17][16] = 0.1108640; aaWAG[18][16] = 0.2911480; aaWAG[19][16] = 1.3882300;
    aaWAG[ 0][17] = 0.1131330; aaWAG[ 1][17] = 1.1639200; aaWAG[ 2][17] = 0.0719167; aaWAG[ 3][17] = 0.1297670; aaWAG[ 4][17] = 0.7170700;  
    aaWAG[ 5][17] = 0.2157370; aaWAG[ 6][17] = 0.1565570; aaWAG[ 7][17] = 0.3369830; aaWAG[ 8][17] = 0.2625690; aaWAG[ 9][17] = 0.2124830;  
    aaWAG[10][17] = 0.6653090; aaWAG[11][17] = 0.1375050; aaWAG[12][17] = 0.5157060; aaWAG[13][17] = 1.5296400; aaWAG[14][17] = 0.1394050;  
    aaWAG[15][17] = 0.5237420; aaWAG[16][17] = 0.1108640; aaWAG[17][17] = 0.0000000; aaWAG[18][17] = 2.4853900; aaWAG[19][17] = 0.3653690;
    aaWAG[ 0][18] = 0.2407350; aaWAG[ 1][18] = 0.3815330; aaWAG[ 2][18] = 1.0860000; aaWAG[ 3][18] = 0.3257110; aaWAG[ 4][18] = 0.5438330;  
    aaWAG[ 5][18] = 0.2277100; aaWAG[ 6][18] = 0.1963030; aaWAG[ 7][18] = 0.1036040; aaWAG[ 8][18] = 3.8734400; aaWAG[ 9][18] = 0.4201700;  
    aaWAG[10][18] = 0.3986180; aaWAG[11][18] = 0.1332640; aaWAG[12][18] = 0.4284370; aaWAG[13][18] = 6.4542800; aaWAG[14][18] = 0.2160460;  
    aaWAG[15][18] = 0.7869930; aaWAG[16][18] = 0.2911480; aaWAG[17][18] = 2.4853900; aaWAG[18][18] = 0.0000000; aaWAG[19][18] = 0.3147300;
    aaWAG[ 0][19] = 2.0060100; aaWAG[ 1][19] = 0.2518490; aaWAG[ 2][19] = 0.1962460; aaWAG[ 3][19] = 0.1523350; aaWAG[ 4][19] = 1.0021400;  
    aaWAG[ 5][19] = 0.3012810; aaWAG[ 6][19] = 0.5887310; aaWAG[ 7][19] = 0.1872470; aaWAG[ 8][19] = 0.1183580; aaWAG[ 9][19] = 7.8213000;  
    aaWAG[10][19] = 1.8003400; aaWAG[11][19] = 0.3054340; aaWAG[12][19] = 2.0584500; aaWAG[13][19] = 0.6498920; aaWAG[14][19] = 0.3148870;  
    aaWAG[15][19] = 0.2327390; aaWAG[16][19] = 1.3882300; aaWAG[17][19] = 0.3653690; aaWAG[18][19] = 0.3147300; aaWAG[19][19] = 0.0000000;
    wagPi[ 0] = 0.08662790;
    wagPi[ 1] = 0.04397200;
    wagPi[ 2] = 0.03908940;
    wagPi[ 3] = 0.05704510;
    wagPi[ 4] = 0.01930780;
    wagPi[ 5] = 0.03672810;
    wagPi[ 6] = 0.05805890;
    wagPi[ 7] = 0.08325180;
    wagPi[ 8] = 0.02443130;
    wagPi[ 9] = 0.04846600;
    wagPi[10] = 0.08620970;
    wagPi[11] = 0.06202860;
    wagPi[12] = 0.01950273;
    wagPi[13] = 0.03843190;
    wagPi[14] = 0.04576310;
    wagPi[15] = 0.06951790;
    wagPi[16] = 0.06101270;
    wagPi[17] = 0.01438590;
    wagPi[18] = 0.03527420;
    wagPi[19] = 0.07089560;

    /* cpRev */
    aacpREV[ 0][ 0] =    0; aacpREV[ 0][ 1] =  105; aacpREV[ 0][ 2] =  227; aacpREV[ 0][ 3] =  175; aacpREV[ 0][ 4] =  669; 
    aacpREV[ 0][ 5] =  157; aacpREV[ 0][ 6] =  499; aacpREV[ 0][ 7] =  665; aacpREV[ 0][ 8] =   66; aacpREV[ 0][ 9] =  145; 
    aacpREV[ 0][10] =  197; aacpREV[ 0][11] =  236; aacpREV[ 0][12] =  185; aacpREV[ 0][13] =   68; aacpREV[ 0][14] =  490; 
    aacpREV[ 0][15] = 2440; aacpREV[ 0][16] = 1340; aacpREV[ 0][17] =   14; aacpREV[ 0][18] =   56; aacpREV[ 0][19] =  968; 
    aacpREV[ 1][ 0] =  105; aacpREV[ 1][ 1] =    0; aacpREV[ 1][ 2] =  357; aacpREV[ 1][ 3] =   43; aacpREV[ 1][ 4] =  823; 
    aacpREV[ 1][ 5] = 1745; aacpREV[ 1][ 6] =  152; aacpREV[ 1][ 7] =  243; aacpREV[ 1][ 8] =  715; aacpREV[ 1][ 9] =  136; 
    aacpREV[ 1][10] =  203; aacpREV[ 1][11] = 4482; aacpREV[ 1][12] =  125; aacpREV[ 1][13] =   53; aacpREV[ 1][14] =   87; 
    aacpREV[ 1][15] =  385; aacpREV[ 1][16] =  314; aacpREV[ 1][17] =  230; aacpREV[ 1][18] =  323; aacpREV[ 1][19] =   92; 
    aacpREV[ 2][ 0] =  227; aacpREV[ 2][ 1] =  357; aacpREV[ 2][ 2] =    0; aacpREV[ 2][ 3] = 4435; aacpREV[ 2][ 4] =  538; 
    aacpREV[ 2][ 5] =  768; aacpREV[ 2][ 6] = 1055; aacpREV[ 2][ 7] =  653; aacpREV[ 2][ 8] = 1405; aacpREV[ 2][ 9] =  168; 
    aacpREV[ 2][10] =  113; aacpREV[ 2][11] = 2430; aacpREV[ 2][12] =   61; aacpREV[ 2][13] =   97; aacpREV[ 2][14] =  173; 
    aacpREV[ 2][15] = 2085; aacpREV[ 2][16] = 1393; aacpREV[ 2][17] =   40; aacpREV[ 2][18] =  754; aacpREV[ 2][19] =   83; 
    aacpREV[ 3][ 0] =  175; aacpREV[ 3][ 1] =   43; aacpREV[ 3][ 2] = 4435; aacpREV[ 3][ 3] =    0; aacpREV[ 3][ 4] =   10; 
    aacpREV[ 3][ 5] =  400; aacpREV[ 3][ 6] = 3691; aacpREV[ 3][ 7] =  431; aacpREV[ 3][ 8] =  331; aacpREV[ 3][ 9] =   10; 
    aacpREV[ 3][10] =   10; aacpREV[ 3][11] =  412; aacpREV[ 3][12] =   47; aacpREV[ 3][13] =   22; aacpREV[ 3][14] =  170; 
    aacpREV[ 3][15] =  590; aacpREV[ 3][16] =  266; aacpREV[ 3][17] =   18; aacpREV[ 3][18] =  281; aacpREV[ 3][19] =   75; 
    aacpREV[ 4][ 0] =  669; aacpREV[ 4][ 1] =  823; aacpREV[ 4][ 2] =  538; aacpREV[ 4][ 3] =   10; aacpREV[ 4][ 4] =    0; 
    aacpREV[ 4][ 5] =   10; aacpREV[ 4][ 6] =   10; aacpREV[ 4][ 7] =  303; aacpREV[ 4][ 8] =  441; aacpREV[ 4][ 9] =  280; 
    aacpREV[ 4][10] =  396; aacpREV[ 4][11] =   48; aacpREV[ 4][12] =  159; aacpREV[ 4][13] =  726; aacpREV[ 4][14] =  285; 
    aacpREV[ 4][15] = 2331; aacpREV[ 4][16] =  576; aacpREV[ 4][17] =  435; aacpREV[ 4][18] = 1466; aacpREV[ 4][19] =  592; 
    aacpREV[ 5][ 0] =  157; aacpREV[ 5][ 1] = 1745; aacpREV[ 5][ 2] =  768; aacpREV[ 5][ 3] =  400; aacpREV[ 5][ 4] =   10; 
    aacpREV[ 5][ 5] =    0; aacpREV[ 5][ 6] = 3122; aacpREV[ 5][ 7] =  133; aacpREV[ 5][ 8] = 1269; aacpREV[ 5][ 9] =   92; 
    aacpREV[ 5][10] =  286; aacpREV[ 5][11] = 3313; aacpREV[ 5][12] =  202; aacpREV[ 5][13] =   10; aacpREV[ 5][14] =  323; 
    aacpREV[ 5][15] =  396; aacpREV[ 5][16] =  241; aacpREV[ 5][17] =   53; aacpREV[ 5][18] =  391; aacpREV[ 5][19] =   54; 
    aacpREV[ 6][ 0] =  499; aacpREV[ 6][ 1] =  152; aacpREV[ 6][ 2] = 1055; aacpREV[ 6][ 3] = 3691; aacpREV[ 6][ 4] =   10; 
    aacpREV[ 6][ 5] = 3122; aacpREV[ 6][ 6] =    0; aacpREV[ 6][ 7] =  379; aacpREV[ 6][ 8] =  162; aacpREV[ 6][ 9] =  148; 
    aacpREV[ 6][10] =   82; aacpREV[ 6][11] = 2629; aacpREV[ 6][12] =  113; aacpREV[ 6][13] =  145; aacpREV[ 6][14] =  185; 
    aacpREV[ 6][15] =  568; aacpREV[ 6][16] =  369; aacpREV[ 6][17] =   63; aacpREV[ 6][18] =  142; aacpREV[ 6][19] =  200; 
    aacpREV[ 7][ 0] =  665; aacpREV[ 7][ 1] =  243; aacpREV[ 7][ 2] =  653; aacpREV[ 7][ 3] =  431; aacpREV[ 7][ 4] =  303; 
    aacpREV[ 7][ 5] =  133; aacpREV[ 7][ 6] =  379; aacpREV[ 7][ 7] =    0; aacpREV[ 7][ 8] =   19; aacpREV[ 7][ 9] =   40; 
    aacpREV[ 7][10] =   20; aacpREV[ 7][11] =  263; aacpREV[ 7][12] =   21; aacpREV[ 7][13] =   25; aacpREV[ 7][14] =   28; 
    aacpREV[ 7][15] =  691; aacpREV[ 7][16] =   92; aacpREV[ 7][17] =   82; aacpREV[ 7][18] =   10; aacpREV[ 7][19] =   91; 
    aacpREV[ 8][ 0] =   66; aacpREV[ 8][ 1] =  715; aacpREV[ 8][ 2] = 1405; aacpREV[ 8][ 3] =  331; aacpREV[ 8][ 4] =  441; 
    aacpREV[ 8][ 5] = 1269; aacpREV[ 8][ 6] =  162; aacpREV[ 8][ 7] =   19; aacpREV[ 8][ 8] =    0; aacpREV[ 8][ 9] =   29; 
    aacpREV[ 8][10] =   66; aacpREV[ 8][11] =  305; aacpREV[ 8][12] =   10; aacpREV[ 8][13] =  127; aacpREV[ 8][14] =  152; 
    aacpREV[ 8][15] =  303; aacpREV[ 8][16] =   32; aacpREV[ 8][17] =   69; aacpREV[ 8][18] = 1971; aacpREV[ 8][19] =   25; 
    aacpREV[ 9][ 0] =  145; aacpREV[ 9][ 1] =  136; aacpREV[ 9][ 2] =  168; aacpREV[ 9][ 3] =   10; aacpREV[ 9][ 4] =  280; 
    aacpREV[ 9][ 5] =   92; aacpREV[ 9][ 6] =  148; aacpREV[ 9][ 7] =   40; aacpREV[ 9][ 8] =   29; aacpREV[ 9][ 9] =    0; 
    aacpREV[ 9][10] = 1745; aacpREV[ 9][11] =  345; aacpREV[ 9][12] = 1772; aacpREV[ 9][13] =  454; aacpREV[ 9][14] =  117; 
    aacpREV[ 9][15] =  216; aacpREV[ 9][16] = 1040; aacpREV[ 9][17] =   42; aacpREV[ 9][18] =   89; aacpREV[ 9][19] = 4797; 
    aacpREV[10][ 0] =  197; aacpREV[10][ 1] =  203; aacpREV[10][ 2] =  113; aacpREV[10][ 3] =   10; aacpREV[10][ 4] =  396; 
    aacpREV[10][ 5] =  286; aacpREV[10][ 6] =   82; aacpREV[10][ 7] =   20; aacpREV[10][ 8] =   66; aacpREV[10][ 9] = 1745; 
    aacpREV[10][10] =    0; aacpREV[10][11] =  218; aacpREV[10][12] = 1351; aacpREV[10][13] = 1268; aacpREV[10][14] =  219; 
    aacpREV[10][15] =  516; aacpREV[10][16] =  156; aacpREV[10][17] =  159; aacpREV[10][18] =  189; aacpREV[10][19] =  865; 
    aacpREV[11][ 0] =  236; aacpREV[11][ 1] = 4482; aacpREV[11][ 2] = 2430; aacpREV[11][ 3] =  412; aacpREV[11][ 4] =   48; 
    aacpREV[11][ 5] = 3313; aacpREV[11][ 6] = 2629; aacpREV[11][ 7] =  263; aacpREV[11][ 8] =  305; aacpREV[11][ 9] =  345; 
    aacpREV[11][10] =  218; aacpREV[11][11] =    0; aacpREV[11][12] =  193; aacpREV[11][13] =   72; aacpREV[11][14] =  302; 
    aacpREV[11][15] =  868; aacpREV[11][16] =  918; aacpREV[11][17] =   10; aacpREV[11][18] =  247; aacpREV[11][19] =  249; 
    aacpREV[12][ 0] =  185; aacpREV[12][ 1] =  125; aacpREV[12][ 2] =   61; aacpREV[12][ 3] =   47; aacpREV[12][ 4] =  159; 
    aacpREV[12][ 5] =  202; aacpREV[12][ 6] =  113; aacpREV[12][ 7] =   21; aacpREV[12][ 8] =   10; aacpREV[12][ 9] = 1772; 
    aacpREV[12][10] = 1351; aacpREV[12][11] =  193; aacpREV[12][12] =    0; aacpREV[12][13] =  327; aacpREV[12][14] =  100; 
    aacpREV[12][15] =   93; aacpREV[12][16] =  645; aacpREV[12][17] =   86; aacpREV[12][18] =  215; aacpREV[12][19] =  475; 
    aacpREV[13][ 0] =   68; aacpREV[13][ 1] =   53; aacpREV[13][ 2] =   97; aacpREV[13][ 3] =   22; aacpREV[13][ 4] =  726; 
    aacpREV[13][ 5] =   10; aacpREV[13][ 6] =  145; aacpREV[13][ 7] =   25; aacpREV[13][ 8] =  127; aacpREV[13][ 9] =  454; 
    aacpREV[13][10] = 1268; aacpREV[13][11] =   72; aacpREV[13][12] =  327; aacpREV[13][13] =    0; aacpREV[13][14] =   43; 
    aacpREV[13][15] =  487; aacpREV[13][16] =  148; aacpREV[13][17] =  468; aacpREV[13][18] = 2370; aacpREV[13][19] =  317; 
    aacpREV[14][ 0] =  490; aacpREV[14][ 1] =   87; aacpREV[14][ 2] =  173; aacpREV[14][ 3] =  170; aacpREV[14][ 4] =  285; 
    aacpREV[14][ 5] =  323; aacpREV[14][ 6] =  185; aacpREV[14][ 7] =   28; aacpREV[14][ 8] =  152; aacpREV[14][ 9] =  117; 
    aacpREV[14][10] =  219; aacpREV[14][11] =  302; aacpREV[14][12] =  100; aacpREV[14][13] =   43; aacpREV[14][14] =    0; 
    aacpREV[14][15] = 1202; aacpREV[14][16] =  260; aacpREV[14][17] =   49; aacpREV[14][18] =   97; aacpREV[14][19] =  122; 
    aacpREV[15][ 0] = 2440; aacpREV[15][ 1] =  385; aacpREV[15][ 2] = 2085; aacpREV[15][ 3] =  590; aacpREV[15][ 4] = 2331; 
    aacpREV[15][ 5] =  396; aacpREV[15][ 6] =  568; aacpREV[15][ 7] =  691; aacpREV[15][ 8] =  303; aacpREV[15][ 9] =  216; 
    aacpREV[15][10] =  516; aacpREV[15][11] =  868; aacpREV[15][12] =   93; aacpREV[15][13] =  487; aacpREV[15][14] = 1202; 
    aacpREV[15][15] =    0; aacpREV[15][16] = 2151; aacpREV[15][17] =   73; aacpREV[15][18] =  522; aacpREV[15][19] =  167; 
    aacpREV[16][ 0] = 1340; aacpREV[16][ 1] =  314; aacpREV[16][ 2] = 1393; aacpREV[16][ 3] =  266; aacpREV[16][ 4] =  576; 
    aacpREV[16][ 5] =  241; aacpREV[16][ 6] =  369; aacpREV[16][ 7] =   92; aacpREV[16][ 8] =   32; aacpREV[16][ 9] = 1040; 
    aacpREV[16][10] =  156; aacpREV[16][11] =  918; aacpREV[16][12] =  645; aacpREV[16][13] =  148; aacpREV[16][14] =  260; 
    aacpREV[16][15] = 2151; aacpREV[16][16] =    0; aacpREV[16][17] =   29; aacpREV[16][18] =   71; aacpREV[16][19] =  760; 
    aacpREV[17][ 0] =   14; aacpREV[17][ 1] =  230; aacpREV[17][ 2] =   40; aacpREV[17][ 3] =   18; aacpREV[17][ 4] =  435; 
    aacpREV[17][ 5] =   53; aacpREV[17][ 6] =   63; aacpREV[17][ 7] =   82; aacpREV[17][ 8] =   69; aacpREV[17][ 9] =   42; 
    aacpREV[17][10] =  159; aacpREV[17][11] =   10; aacpREV[17][12] =   86; aacpREV[17][13] =  468; aacpREV[17][14] =   49; 
    aacpREV[17][15] =   73; aacpREV[17][16] =   29; aacpREV[17][17] =    0; aacpREV[17][18] =  346; aacpREV[17][19] =   10; 
    aacpREV[18][ 0] =   56; aacpREV[18][ 1] =  323; aacpREV[18][ 2] =  754; aacpREV[18][ 3] =  281; aacpREV[18][ 4] = 1466; 
    aacpREV[18][ 5] =  391; aacpREV[18][ 6] =  142; aacpREV[18][ 7] =   10; aacpREV[18][ 8] = 1971; aacpREV[18][ 9] =   89; 
    aacpREV[18][10] =  189; aacpREV[18][11] =  247; aacpREV[18][12] =  215; aacpREV[18][13] = 2370; aacpREV[18][14] =   97; 
    aacpREV[18][15] =  522; aacpREV[18][16] =   71; aacpREV[18][17] =  346; aacpREV[18][18] =    0; aacpREV[18][19] =  119; 
    aacpREV[19][ 0] =  968; aacpREV[19][ 1] =   92; aacpREV[19][ 2] =   83; aacpREV[19][ 3] =   75; aacpREV[19][ 4] =  592; 
    aacpREV[19][ 5] =   54; aacpREV[19][ 6] =  200; aacpREV[19][ 7] =   91; aacpREV[19][ 8] =   25; aacpREV[19][ 9] = 4797; 
    aacpREV[19][10] =  865; aacpREV[19][11] =  249; aacpREV[19][12] =  475; aacpREV[19][13] =  317; aacpREV[19][14] =  122; 
    aacpREV[19][15] =  167; aacpREV[19][16] =  760; aacpREV[19][17] =   10; aacpREV[19][18] =  119; aacpREV[19][19] =    0;

    cprevPi[0] = 0.076;
    cprevPi[1] = 0.062;
    cprevPi[2] = 0.041;
    cprevPi[3] = 0.037;
    cprevPi[4] = 0.009;
    cprevPi[5] = 0.038;
    cprevPi[6] = 0.049;
    cprevPi[7] = 0.084;
    cprevPi[8] = 0.025;
    cprevPi[9] = 0.081;
    cprevPi[10] = 0.101;
    cprevPi[11] = 0.050;
    cprevPi[12] = 0.022;
    cprevPi[13] = 0.051;
    cprevPi[14] = 0.043;
    cprevPi[15] = 0.062;
    cprevPi[16] = 0.054;
    cprevPi[17] = 0.018;
    cprevPi[18] = 0.031;
    cprevPi[19] = 0.066;
    
    /* VT model */
    aaVt[ 0][ 0] = 0.000000; aaVt[ 0][ 1] = 0.233108; aaVt[ 0][ 2] = 0.199097; aaVt[ 0][ 3] = 0.265145; aaVt[ 0][ 4] = 0.227333; 
    aaVt[ 0][ 5] = 0.310084; aaVt[ 0][ 6] = 0.567957; aaVt[ 0][ 7] = 0.876213; aaVt[ 0][ 8] = 0.078692; aaVt[ 0][ 9] = 0.222972; 
    aaVt[ 0][10] = 0.424630; aaVt[ 0][11] = 0.393245; aaVt[ 0][12] = 0.211550; aaVt[ 0][13] = 0.116646; aaVt[ 0][14] = 0.399143; 
    aaVt[ 0][15] = 1.817198; aaVt[ 0][16] = 0.877877; aaVt[ 0][17] = 0.030309; aaVt[ 0][18] = 0.087061; aaVt[ 0][19] = 1.230985; 
    aaVt[ 1][ 0] = 0.233108; aaVt[ 1][ 1] = 0.000000; aaVt[ 1][ 2] = 0.210797; aaVt[ 1][ 3] = 0.105191; aaVt[ 1][ 4] = 0.031726; 
    aaVt[ 1][ 5] = 0.493763; aaVt[ 1][ 6] = 0.255240; aaVt[ 1][ 7] = 0.156945; aaVt[ 1][ 8] = 0.213164; aaVt[ 1][ 9] = 0.081510; 
    aaVt[ 1][10] = 0.192364; aaVt[ 1][11] = 1.755838; aaVt[ 1][12] = 0.087930; aaVt[ 1][13] = 0.042569; aaVt[ 1][14] = 0.128480; 
    aaVt[ 1][15] = 0.292327; aaVt[ 1][16] = 0.204109; aaVt[ 1][17] = 0.046417; aaVt[ 1][18] = 0.097010; aaVt[ 1][19] = 0.113146; 
    aaVt[ 2][ 0] = 0.199097; aaVt[ 2][ 1] = 0.210797; aaVt[ 2][ 2] = 0.000000; aaVt[ 2][ 3] = 0.883422; aaVt[ 2][ 4] = 0.027495; 
    aaVt[ 2][ 5] = 0.275700; aaVt[ 2][ 6] = 0.270417; aaVt[ 2][ 7] = 0.362028; aaVt[ 2][ 8] = 0.290006; aaVt[ 2][ 9] = 0.087225; 
    aaVt[ 2][10] = 0.069245; aaVt[ 2][11] = 0.503060; aaVt[ 2][12] = 0.057420; aaVt[ 2][13] = 0.039769; aaVt[ 2][14] = 0.083956; 
    aaVt[ 2][15] = 0.847049; aaVt[ 2][16] = 0.471268; aaVt[ 2][17] = 0.010459; aaVt[ 2][18] = 0.093268; aaVt[ 2][19] = 0.049824; 
    aaVt[ 3][ 0] = 0.265145; aaVt[ 3][ 1] = 0.105191; aaVt[ 3][ 2] = 0.883422; aaVt[ 3][ 3] = 0.000000; aaVt[ 3][ 4] = 0.010313; 
    aaVt[ 3][ 5] = 0.205842; aaVt[ 3][ 6] = 1.599461; aaVt[ 3][ 7] = 0.311718; aaVt[ 3][ 8] = 0.134252; aaVt[ 3][ 9] = 0.011720; 
    aaVt[ 3][10] = 0.060863; aaVt[ 3][11] = 0.261101; aaVt[ 3][12] = 0.012182; aaVt[ 3][13] = 0.016577; aaVt[ 3][14] = 0.160063; 
    aaVt[ 3][15] = 0.461519; aaVt[ 3][16] = 0.178197; aaVt[ 3][17] = 0.011393; aaVt[ 3][18] = 0.051664; aaVt[ 3][19] = 0.048769; 
    aaVt[ 4][ 0] = 0.227333; aaVt[ 4][ 1] = 0.031726; aaVt[ 4][ 2] = 0.027495; aaVt[ 4][ 3] = 0.010313; aaVt[ 4][ 4] = 0.000000; 
    aaVt[ 4][ 5] = 0.004315; aaVt[ 4][ 6] = 0.005321; aaVt[ 4][ 7] = 0.050876; aaVt[ 4][ 8] = 0.016695; aaVt[ 4][ 9] = 0.046398; 
    aaVt[ 4][10] = 0.091709; aaVt[ 4][11] = 0.004067; aaVt[ 4][12] = 0.023690; aaVt[ 4][13] = 0.051127; aaVt[ 4][14] = 0.011137; 
    aaVt[ 4][15] = 0.175270; aaVt[ 4][16] = 0.079511; aaVt[ 4][17] = 0.007732; aaVt[ 4][18] = 0.042823; aaVt[ 4][19] = 0.163831; 
    aaVt[ 5][ 0] = 0.310084; aaVt[ 5][ 1] = 0.493763; aaVt[ 5][ 2] = 0.275700; aaVt[ 5][ 3] = 0.205842; aaVt[ 5][ 4] = 0.004315; 
    aaVt[ 5][ 5] = 0.000000; aaVt[ 5][ 6] = 0.960976; aaVt[ 5][ 7] = 0.128660; aaVt[ 5][ 8] = 0.315521; aaVt[ 5][ 9] = 0.054602; 
    aaVt[ 5][10] = 0.243530; aaVt[ 5][11] = 0.738208; aaVt[ 5][12] = 0.120801; aaVt[ 5][13] = 0.026235; aaVt[ 5][14] = 0.156570; 
    aaVt[ 5][15] = 0.358017; aaVt[ 5][16] = 0.248992; aaVt[ 5][17] = 0.021248; aaVt[ 5][18] = 0.062544; aaVt[ 5][19] = 0.112027; 
    aaVt[ 6][ 0] = 0.567957; aaVt[ 6][ 1] = 0.255240; aaVt[ 6][ 2] = 0.270417; aaVt[ 6][ 3] = 1.599461; aaVt[ 6][ 4] = 0.005321; 
    aaVt[ 6][ 5] = 0.960976; aaVt[ 6][ 6] = 0.000000; aaVt[ 6][ 7] = 0.250447; aaVt[ 6][ 8] = 0.104458; aaVt[ 6][ 9] = 0.046589; 
    aaVt[ 6][10] = 0.151924; aaVt[ 6][11] = 0.888630; aaVt[ 6][12] = 0.058643; aaVt[ 6][13] = 0.028168; aaVt[ 6][14] = 0.205134; 
    aaVt[ 6][15] = 0.406035; aaVt[ 6][16] = 0.321028; aaVt[ 6][17] = 0.018844; aaVt[ 6][18] = 0.055200; aaVt[ 6][19] = 0.205868; 
    aaVt[ 7][ 0] = 0.876213; aaVt[ 7][ 1] = 0.156945; aaVt[ 7][ 2] = 0.362028; aaVt[ 7][ 3] = 0.311718; aaVt[ 7][ 4] = 0.050876; 
    aaVt[ 7][ 5] = 0.128660; aaVt[ 7][ 6] = 0.250447; aaVt[ 7][ 7] = 0.000000; aaVt[ 7][ 8] = 0.058131; aaVt[ 7][ 9] = 0.051089; 
    aaVt[ 7][10] = 0.087056; aaVt[ 7][11] = 0.193243; aaVt[ 7][12] = 0.046560; aaVt[ 7][13] = 0.050143; aaVt[ 7][14] = 0.124492; 
    aaVt[ 7][15] = 0.612843; aaVt[ 7][16] = 0.136266; aaVt[ 7][17] = 0.023990; aaVt[ 7][18] = 0.037568; aaVt[ 7][19] = 0.082579; 
    aaVt[ 8][ 0] = 0.078692; aaVt[ 8][ 1] = 0.213164; aaVt[ 8][ 2] = 0.290006; aaVt[ 8][ 3] = 0.134252; aaVt[ 8][ 4] = 0.016695; 
    aaVt[ 8][ 5] = 0.315521; aaVt[ 8][ 6] = 0.104458; aaVt[ 8][ 7] = 0.058131; aaVt[ 8][ 8] = 0.000000; aaVt[ 8][ 9] = 0.020039; 
    aaVt[ 8][10] = 0.103552; aaVt[ 8][11] = 0.153323; aaVt[ 8][12] = 0.021157; aaVt[ 8][13] = 0.079807; aaVt[ 8][14] = 0.078892; 
    aaVt[ 8][15] = 0.167406; aaVt[ 8][16] = 0.101117; aaVt[ 8][17] = 0.020009; aaVt[ 8][18] = 0.286027; aaVt[ 8][19] = 0.068575; 
    aaVt[ 9][ 0] = 0.222972; aaVt[ 9][ 1] = 0.081510; aaVt[ 9][ 2] = 0.087225; aaVt[ 9][ 3] = 0.011720; aaVt[ 9][ 4] = 0.046398; 
    aaVt[ 9][ 5] = 0.054602; aaVt[ 9][ 6] = 0.046589; aaVt[ 9][ 7] = 0.051089; aaVt[ 9][ 8] = 0.020039; aaVt[ 9][ 9] = 0.000000; 
    aaVt[ 9][10] = 2.089890; aaVt[ 9][11] = 0.093181; aaVt[ 9][12] = 0.493845; aaVt[ 9][13] = 0.321020; aaVt[ 9][14] = 0.054797; 
    aaVt[ 9][15] = 0.081567; aaVt[ 9][16] = 0.376588; aaVt[ 9][17] = 0.034954; aaVt[ 9][18] = 0.086237; aaVt[ 9][19] = 3.654430; 
    aaVt[10][ 0] = 0.424630; aaVt[10][ 1] = 0.192364; aaVt[10][ 2] = 0.069245; aaVt[10][ 3] = 0.060863; aaVt[10][ 4] = 0.091709; 
    aaVt[10][ 5] = 0.243530; aaVt[10][ 6] = 0.151924; aaVt[10][ 7] = 0.087056; aaVt[10][ 8] = 0.103552; aaVt[10][ 9] = 2.089890; 
    aaVt[10][10] = 0.000000; aaVt[10][11] = 0.201204; aaVt[10][12] = 1.105667; aaVt[10][13] = 0.946499; aaVt[10][14] = 0.169784; 
    aaVt[10][15] = 0.214977; aaVt[10][16] = 0.243227; aaVt[10][17] = 0.083439; aaVt[10][18] = 0.189842; aaVt[10][19] = 1.337571; 
    aaVt[11][ 0] = 0.393245; aaVt[11][ 1] = 1.755838; aaVt[11][ 2] = 0.503060; aaVt[11][ 3] = 0.261101; aaVt[11][ 4] = 0.004067; 
    aaVt[11][ 5] = 0.738208; aaVt[11][ 6] = 0.888630; aaVt[11][ 7] = 0.193243; aaVt[11][ 8] = 0.153323; aaVt[11][ 9] = 0.093181; 
    aaVt[11][10] = 0.201204; aaVt[11][11] = 0.000000; aaVt[11][12] = 0.096474; aaVt[11][13] = 0.038261; aaVt[11][14] = 0.212302; 
    aaVt[11][15] = 0.400072; aaVt[11][16] = 0.446646; aaVt[11][17] = 0.023321; aaVt[11][18] = 0.068689; aaVt[11][19] = 0.144587; 
    aaVt[12][ 0] = 0.211550; aaVt[12][ 1] = 0.087930; aaVt[12][ 2] = 0.057420; aaVt[12][ 3] = 0.012182; aaVt[12][ 4] = 0.023690; 
    aaVt[12][ 5] = 0.120801; aaVt[12][ 6] = 0.058643; aaVt[12][ 7] = 0.046560; aaVt[12][ 8] = 0.021157; aaVt[12][ 9] = 0.493845; 
    aaVt[12][10] = 1.105667; aaVt[12][11] = 0.096474; aaVt[12][12] = 0.000000; aaVt[12][13] = 0.173052; aaVt[12][14] = 0.010363; 
    aaVt[12][15] = 0.090515; aaVt[12][16] = 0.184609; aaVt[12][17] = 0.022019; aaVt[12][18] = 0.073223; aaVt[12][19] = 0.307309; 
    aaVt[13][ 0] = 0.116646; aaVt[13][ 1] = 0.042569; aaVt[13][ 2] = 0.039769; aaVt[13][ 3] = 0.016577; aaVt[13][ 4] = 0.051127; 
    aaVt[13][ 5] = 0.026235; aaVt[13][ 6] = 0.028168; aaVt[13][ 7] = 0.050143; aaVt[13][ 8] = 0.079807; aaVt[13][ 9] = 0.321020; 
    aaVt[13][10] = 0.946499; aaVt[13][11] = 0.038261; aaVt[13][12] = 0.173052; aaVt[13][13] = 0.000000; aaVt[13][14] = 0.042564; 
    aaVt[13][15] = 0.138119; aaVt[13][16] = 0.085870; aaVt[13][17] = 0.128050; aaVt[13][18] = 0.898663; aaVt[13][19] = 0.247329; 
    aaVt[14][ 0] = 0.399143; aaVt[14][ 1] = 0.128480; aaVt[14][ 2] = 0.083956; aaVt[14][ 3] = 0.160063; aaVt[14][ 4] = 0.011137; 
    aaVt[14][ 5] = 0.156570; aaVt[14][ 6] = 0.205134; aaVt[14][ 7] = 0.124492; aaVt[14][ 8] = 0.078892; aaVt[14][ 9] = 0.054797; 
    aaVt[14][10] = 0.169784; aaVt[14][11] = 0.212302; aaVt[14][12] = 0.010363; aaVt[14][13] = 0.042564; aaVt[14][14] = 0.000000; 
    aaVt[14][15] = 0.430431; aaVt[14][16] = 0.207143; aaVt[14][17] = 0.014584; aaVt[14][18] = 0.032043; aaVt[14][19] = 0.129315; 
    aaVt[15][ 0] = 1.817198; aaVt[15][ 1] = 0.292327; aaVt[15][ 2] = 0.847049; aaVt[15][ 3] = 0.461519; aaVt[15][ 4] = 0.175270; 
    aaVt[15][ 5] = 0.358017; aaVt[15][ 6] = 0.406035; aaVt[15][ 7] = 0.612843; aaVt[15][ 8] = 0.167406; aaVt[15][ 9] = 0.081567; 
    aaVt[15][10] = 0.214977; aaVt[15][11] = 0.400072; aaVt[15][12] = 0.090515; aaVt[15][13] = 0.138119; aaVt[15][14] = 0.430431; 
    aaVt[15][15] = 0.000000; aaVt[15][16] = 1.767766; aaVt[15][17] = 0.035933; aaVt[15][18] = 0.121979; aaVt[15][19] = 0.127700; 
    aaVt[16][ 0] = 0.877877; aaVt[16][ 1] = 0.204109; aaVt[16][ 2] = 0.471268; aaVt[16][ 3] = 0.178197; aaVt[16][ 4] = 0.079511; 
    aaVt[16][ 5] = 0.248992; aaVt[16][ 6] = 0.321028; aaVt[16][ 7] = 0.136266; aaVt[16][ 8] = 0.101117; aaVt[16][ 9] = 0.376588; 
    aaVt[16][10] = 0.243227; aaVt[16][11] = 0.446646; aaVt[16][12] = 0.184609; aaVt[16][13] = 0.085870; aaVt[16][14] = 0.207143; 
    aaVt[16][15] = 1.767766; aaVt[16][16] = 0.000000; aaVt[16][17] = 0.020437; aaVt[16][18] = 0.094617; aaVt[16][19] = 0.740372; 
    aaVt[17][ 0] = 0.030309; aaVt[17][ 1] = 0.046417; aaVt[17][ 2] = 0.010459; aaVt[17][ 3] = 0.011393; aaVt[17][ 4] = 0.007732; 
    aaVt[17][ 5] = 0.021248; aaVt[17][ 6] = 0.018844; aaVt[17][ 7] = 0.023990; aaVt[17][ 8] = 0.020009; aaVt[17][ 9] = 0.034954; 
    aaVt[17][10] = 0.083439; aaVt[17][11] = 0.023321; aaVt[17][12] = 0.022019; aaVt[17][13] = 0.128050; aaVt[17][14] = 0.014584; 
    aaVt[17][15] = 0.035933; aaVt[17][16] = 0.020437; aaVt[17][17] = 0.000000; aaVt[17][18] = 0.124746; aaVt[17][19] = 0.022134; 
    aaVt[18][ 0] = 0.087061; aaVt[18][ 1] = 0.097010; aaVt[18][ 2] = 0.093268; aaVt[18][ 3] = 0.051664; aaVt[18][ 4] = 0.042823; 
    aaVt[18][ 5] = 0.062544; aaVt[18][ 6] = 0.055200; aaVt[18][ 7] = 0.037568; aaVt[18][ 8] = 0.286027; aaVt[18][ 9] = 0.086237; 
    aaVt[18][10] = 0.189842; aaVt[18][11] = 0.068689; aaVt[18][12] = 0.073223; aaVt[18][13] = 0.898663; aaVt[18][14] = 0.032043; 
    aaVt[18][15] = 0.121979; aaVt[18][16] = 0.094617; aaVt[18][17] = 0.124746; aaVt[18][18] = 0.000000; aaVt[18][19] = 0.125733; 
    aaVt[19][ 0] = 1.230985; aaVt[19][ 1] = 0.113146; aaVt[19][ 2] = 0.049824; aaVt[19][ 3] = 0.048769; aaVt[19][ 4] = 0.163831; 
    aaVt[19][ 5] = 0.112027; aaVt[19][ 6] = 0.205868; aaVt[19][ 7] = 0.082579; aaVt[19][ 8] = 0.068575; aaVt[19][ 9] = 3.654430; 
    aaVt[19][10] = 1.337571; aaVt[19][11] = 0.144587; aaVt[19][12] = 0.307309; aaVt[19][13] = 0.247329; aaVt[19][14] = 0.129315; 
    aaVt[19][15] = 0.127700; aaVt[19][16] = 0.740372; aaVt[19][17] = 0.022134; aaVt[19][18] = 0.125733; aaVt[19][19] = 0.000000;

    vtPi[ 0] = 0.078837;
    vtPi[ 1] = 0.051238;
    vtPi[ 2] = 0.042313;
    vtPi[ 3] = 0.053066;
    vtPi[ 4] = 0.015175;
    vtPi[ 5] = 0.036713;
    vtPi[ 6] = 0.061924;
    vtPi[ 7] = 0.070852;
    vtPi[ 8] = 0.023082;
    vtPi[ 9] = 0.062056;
    vtPi[10] = 0.096371;
    vtPi[11] = 0.057324;
    vtPi[12] = 0.023771;
    vtPi[13] = 0.043296;
    vtPi[14] = 0.043911;
    vtPi[15] = 0.063403;
    vtPi[16] = 0.055897;
    vtPi[17] = 0.013272;
    vtPi[18] = 0.034399;
    vtPi[19] = 0.073101;
    
    /* Blosum62 */
    aaBlosum[ 0][ 0] = 0.000000000000; aaBlosum[ 0][ 1] = 0.735790389698; aaBlosum[ 0][ 2] = 0.485391055466; aaBlosum[ 0][ 3] = 0.543161820899; aaBlosum[ 0][ 4] = 1.459995310470; 
    aaBlosum[ 0][ 5] = 1.199705704602; aaBlosum[ 0][ 6] = 1.170949042800; aaBlosum[ 0][ 7] = 1.955883574960; aaBlosum[ 0][ 8] = 0.716241444998; aaBlosum[ 0][ 9] = 0.605899003687; 
    aaBlosum[ 0][10] = 0.800016530518; aaBlosum[ 0][11] = 1.295201266783; aaBlosum[ 0][12] = 1.253758266664; aaBlosum[ 0][13] = 0.492964679748; aaBlosum[ 0][14] = 1.173275900924; 
    aaBlosum[ 0][15] = 4.325092687057; aaBlosum[ 0][16] = 1.729178019485; aaBlosum[ 0][17] = 0.465839367725; aaBlosum[ 0][18] = 0.718206697586; aaBlosum[ 0][19] = 2.187774522005; 
    aaBlosum[ 1][ 0] = 0.735790389698; aaBlosum[ 1][ 1] = 0.000000000000; aaBlosum[ 1][ 2] = 1.297446705134; aaBlosum[ 1][ 3] = 0.500964408555; aaBlosum[ 1][ 4] = 0.227826574209; 
    aaBlosum[ 1][ 5] = 3.020833610064; aaBlosum[ 1][ 6] = 1.360574190420; aaBlosum[ 1][ 7] = 0.418763308518; aaBlosum[ 1][ 8] = 1.456141166336; aaBlosum[ 1][ 9] = 0.232036445142; 
    aaBlosum[ 1][10] = 0.622711669692; aaBlosum[ 1][11] = 5.411115141489; aaBlosum[ 1][12] = 0.983692987457; aaBlosum[ 1][13] = 0.371644693209; aaBlosum[ 1][14] = 0.448133661718; 
    aaBlosum[ 1][15] = 1.122783104210; aaBlosum[ 1][16] = 0.914665954563; aaBlosum[ 1][17] = 0.426382310122; aaBlosum[ 1][18] = 0.720517441216; aaBlosum[ 1][19] = 0.438388343772; 
    aaBlosum[ 2][ 0] = 0.485391055466; aaBlosum[ 2][ 1] = 1.297446705134; aaBlosum[ 2][ 2] = 0.000000000000; aaBlosum[ 2][ 3] = 3.180100048216; aaBlosum[ 2][ 4] = 0.397358949897; 
    aaBlosum[ 2][ 5] = 1.839216146992; aaBlosum[ 2][ 6] = 1.240488508640; aaBlosum[ 2][ 7] = 1.355872344485; aaBlosum[ 2][ 8] = 2.414501434208; aaBlosum[ 2][ 9] = 0.283017326278; 
    aaBlosum[ 2][10] = 0.211888159615; aaBlosum[ 2][11] = 1.593137043457; aaBlosum[ 2][12] = 0.648441278787; aaBlosum[ 2][13] = 0.354861249223; aaBlosum[ 2][14] = 0.494887043702; 
    aaBlosum[ 2][15] = 2.904101656456; aaBlosum[ 2][16] = 1.898173634533; aaBlosum[ 2][17] = 0.191482046247; aaBlosum[ 2][18] = 0.538222519037; aaBlosum[ 2][19] = 0.312858797993; 
    aaBlosum[ 3][ 0] = 0.543161820899; aaBlosum[ 3][ 1] = 0.500964408555; aaBlosum[ 3][ 2] = 3.180100048216; aaBlosum[ 3][ 3] = 0.000000000000; aaBlosum[ 3][ 4] = 0.240836614802; 
    aaBlosum[ 3][ 5] = 1.190945703396; aaBlosum[ 3][ 6] = 3.761625208368; aaBlosum[ 3][ 7] = 0.798473248968; aaBlosum[ 3][ 8] = 0.778142664022; aaBlosum[ 3][ 9] = 0.418555732462; 
    aaBlosum[ 3][10] = 0.218131577594; aaBlosum[ 3][11] = 1.032447924952; aaBlosum[ 3][12] = 0.222621897958; aaBlosum[ 3][13] = 0.281730694207; aaBlosum[ 3][14] = 0.730628272998; 
    aaBlosum[ 3][15] = 1.582754142065; aaBlosum[ 3][16] = 0.934187509431; aaBlosum[ 3][17] = 0.145345046279; aaBlosum[ 3][18] = 0.261422208965; aaBlosum[ 3][19] = 0.258129289418; 
    aaBlosum[ 4][ 0] = 1.459995310470; aaBlosum[ 4][ 1] = 0.227826574209; aaBlosum[ 4][ 2] = 0.397358949897; aaBlosum[ 4][ 3] = 0.240836614802; aaBlosum[ 4][ 4] = 0.000000000000; 
    aaBlosum[ 4][ 5] = 0.329801504630; aaBlosum[ 4][ 6] = 0.140748891814; aaBlosum[ 4][ 7] = 0.418203192284; aaBlosum[ 4][ 8] = 0.354058109831; aaBlosum[ 4][ 9] = 0.774894022794; 
    aaBlosum[ 4][10] = 0.831842640142; aaBlosum[ 4][11] = 0.285078800906; aaBlosum[ 4][12] = 0.767688823480; aaBlosum[ 4][13] = 0.441337471187; aaBlosum[ 4][14] = 0.356008498769; 
    aaBlosum[ 4][15] = 1.197188415094; aaBlosum[ 4][16] = 1.119831358516; aaBlosum[ 4][17] = 0.527664418872; aaBlosum[ 4][18] = 0.470237733696; aaBlosum[ 4][19] = 1.116352478606; 
    aaBlosum[ 5][ 0] = 1.199705704602; aaBlosum[ 5][ 1] = 3.020833610064; aaBlosum[ 5][ 2] = 1.839216146992; aaBlosum[ 5][ 3] = 1.190945703396; aaBlosum[ 5][ 4] = 0.329801504630; 
    aaBlosum[ 5][ 5] = 0.000000000000; aaBlosum[ 5][ 6] = 5.528919177928; aaBlosum[ 5][ 7] = 0.609846305383; aaBlosum[ 5][ 8] = 2.435341131140; aaBlosum[ 5][ 9] = 0.236202451204; 
    aaBlosum[ 5][10] = 0.580737093181; aaBlosum[ 5][11] = 3.945277674515; aaBlosum[ 5][12] = 2.494896077113; aaBlosum[ 5][13] = 0.144356959750; aaBlosum[ 5][14] = 0.858570575674; 
    aaBlosum[ 5][15] = 1.934870924596; aaBlosum[ 5][16] = 1.277480294596; aaBlosum[ 5][17] = 0.758653808642; aaBlosum[ 5][18] = 0.958989742850; aaBlosum[ 5][19] = 0.530785790125; 
    aaBlosum[ 6][ 0] = 1.170949042800; aaBlosum[ 6][ 1] = 1.360574190420; aaBlosum[ 6][ 2] = 1.240488508640; aaBlosum[ 6][ 3] = 3.761625208368; aaBlosum[ 6][ 4] = 0.140748891814; 
    aaBlosum[ 6][ 5] = 5.528919177928; aaBlosum[ 6][ 6] = 0.000000000000; aaBlosum[ 6][ 7] = 0.423579992176; aaBlosum[ 6][ 8] = 1.626891056982; aaBlosum[ 6][ 9] = 0.186848046932; 
    aaBlosum[ 6][10] = 0.372625175087; aaBlosum[ 6][11] = 2.802427151679; aaBlosum[ 6][12] = 0.555415397470; aaBlosum[ 6][13] = 0.291409084165; aaBlosum[ 6][14] = 0.926563934846; 
    aaBlosum[ 6][15] = 1.769893238937; aaBlosum[ 6][16] = 1.071097236007; aaBlosum[ 6][17] = 0.407635648938; aaBlosum[ 6][18] = 0.596719300346; aaBlosum[ 6][19] = 0.524253846338; 
    aaBlosum[ 7][ 0] = 1.955883574960; aaBlosum[ 7][ 1] = 0.418763308518; aaBlosum[ 7][ 2] = 1.355872344485; aaBlosum[ 7][ 3] = 0.798473248968; aaBlosum[ 7][ 4] = 0.418203192284; 
    aaBlosum[ 7][ 5] = 0.609846305383; aaBlosum[ 7][ 6] = 0.423579992176; aaBlosum[ 7][ 7] = 0.000000000000; aaBlosum[ 7][ 8] = 0.539859124954; aaBlosum[ 7][ 9] = 0.189296292376; 
    aaBlosum[ 7][10] = 0.217721159236; aaBlosum[ 7][11] = 0.752042440303; aaBlosum[ 7][12] = 0.459436173579; aaBlosum[ 7][13] = 0.368166464453; aaBlosum[ 7][14] = 0.504086599527; 
    aaBlosum[ 7][15] = 1.509326253224; aaBlosum[ 7][16] = 0.641436011405; aaBlosum[ 7][17] = 0.508358924638; aaBlosum[ 7][18] = 0.308055737035; aaBlosum[ 7][19] = 0.253340790190; 
    aaBlosum[ 8][ 0] = 0.716241444998; aaBlosum[ 8][ 1] = 1.456141166336; aaBlosum[ 8][ 2] = 2.414501434208; aaBlosum[ 8][ 3] = 0.778142664022; aaBlosum[ 8][ 4] = 0.354058109831; 
    aaBlosum[ 8][ 5] = 2.435341131140; aaBlosum[ 8][ 6] = 1.626891056982; aaBlosum[ 8][ 7] = 0.539859124954; aaBlosum[ 8][ 8] = 0.000000000000; aaBlosum[ 8][ 9] = 0.252718447885; 
    aaBlosum[ 8][10] = 0.348072209797; aaBlosum[ 8][11] = 1.022507035889; aaBlosum[ 8][12] = 0.984311525359; aaBlosum[ 8][13] = 0.714533703928; aaBlosum[ 8][14] = 0.527007339151; 
    aaBlosum[ 8][15] = 1.117029762910; aaBlosum[ 8][16] = 0.585407090225; aaBlosum[ 8][17] = 0.301248600780; aaBlosum[ 8][18] = 4.218953969389; aaBlosum[ 8][19] = 0.201555971750; 
    aaBlosum[ 9][ 0] = 0.605899003687; aaBlosum[ 9][ 1] = 0.232036445142; aaBlosum[ 9][ 2] = 0.283017326278; aaBlosum[ 9][ 3] = 0.418555732462; aaBlosum[ 9][ 4] = 0.774894022794; 
    aaBlosum[ 9][ 5] = 0.236202451204; aaBlosum[ 9][ 6] = 0.186848046932; aaBlosum[ 9][ 7] = 0.189296292376; aaBlosum[ 9][ 8] = 0.252718447885; aaBlosum[ 9][ 9] = 0.000000000000; 
    aaBlosum[ 9][10] = 3.890963773304; aaBlosum[ 9][11] = 0.406193586642; aaBlosum[ 9][12] = 3.364797763104; aaBlosum[ 9][13] = 1.517359325954; aaBlosum[ 9][14] = 0.388355409206; 
    aaBlosum[ 9][15] = 0.357544412460; aaBlosum[ 9][16] = 1.179091197260; aaBlosum[ 9][17] = 0.341985787540; aaBlosum[ 9][18] = 0.674617093228; aaBlosum[ 9][19] = 8.311839405458; 
    aaBlosum[10][ 0] = 0.800016530518; aaBlosum[10][ 1] = 0.622711669692; aaBlosum[10][ 2] = 0.211888159615; aaBlosum[10][ 3] = 0.218131577594; aaBlosum[10][ 4] = 0.831842640142; 
    aaBlosum[10][ 5] = 0.580737093181; aaBlosum[10][ 6] = 0.372625175087; aaBlosum[10][ 7] = 0.217721159236; aaBlosum[10][ 8] = 0.348072209797; aaBlosum[10][ 9] = 3.890963773304; 
    aaBlosum[10][10] = 0.000000000000; aaBlosum[10][11] = 0.445570274261; aaBlosum[10][12] = 6.030559379572; aaBlosum[10][13] = 2.064839703237; aaBlosum[10][14] = 0.374555687471; 
    aaBlosum[10][15] = 0.352969184527; aaBlosum[10][16] = 0.915259857694; aaBlosum[10][17] = 0.691474634600; aaBlosum[10][18] = 0.811245856323; aaBlosum[10][19] = 2.231405688913; 
    aaBlosum[11][ 0] = 1.295201266783; aaBlosum[11][ 1] = 5.411115141489; aaBlosum[11][ 2] = 1.593137043457; aaBlosum[11][ 3] = 1.032447924952; aaBlosum[11][ 4] = 0.285078800906; 
    aaBlosum[11][ 5] = 3.945277674515; aaBlosum[11][ 6] = 2.802427151679; aaBlosum[11][ 7] = 0.752042440303; aaBlosum[11][ 8] = 1.022507035889; aaBlosum[11][ 9] = 0.406193586642; 
    aaBlosum[11][10] = 0.445570274261; aaBlosum[11][11] = 0.000000000000; aaBlosum[11][12] = 1.073061184332; aaBlosum[11][13] = 0.266924750511; aaBlosum[11][14] = 1.047383450722; 
    aaBlosum[11][15] = 1.752165917819; aaBlosum[11][16] = 1.303875200799; aaBlosum[11][17] = 0.332243040634; aaBlosum[11][18] = 0.717993486900; aaBlosum[11][19] = 0.498138475304; 
    aaBlosum[12][ 0] = 1.253758266664; aaBlosum[12][ 1] = 0.983692987457; aaBlosum[12][ 2] = 0.648441278787; aaBlosum[12][ 3] = 0.222621897958; aaBlosum[12][ 4] = 0.767688823480; 
    aaBlosum[12][ 5] = 2.494896077113; aaBlosum[12][ 6] = 0.555415397470; aaBlosum[12][ 7] = 0.459436173579; aaBlosum[12][ 8] = 0.984311525359; aaBlosum[12][ 9] = 3.364797763104; 
    aaBlosum[12][10] = 6.030559379572; aaBlosum[12][11] = 1.073061184332; aaBlosum[12][12] = 0.000000000000; aaBlosum[12][13] = 1.773855168830; aaBlosum[12][14] = 0.454123625103; 
    aaBlosum[12][15] = 0.918723415746; aaBlosum[12][16] = 1.488548053722; aaBlosum[12][17] = 0.888101098152; aaBlosum[12][18] = 0.951682162246; aaBlosum[12][19] = 2.575850755315; 
    aaBlosum[13][ 0] = 0.492964679748; aaBlosum[13][ 1] = 0.371644693209; aaBlosum[13][ 2] = 0.354861249223; aaBlosum[13][ 3] = 0.281730694207; aaBlosum[13][ 4] = 0.441337471187; 
    aaBlosum[13][ 5] = 0.144356959750; aaBlosum[13][ 6] = 0.291409084165; aaBlosum[13][ 7] = 0.368166464453; aaBlosum[13][ 8] = 0.714533703928; aaBlosum[13][ 9] = 1.517359325954; 
    aaBlosum[13][10] = 2.064839703237; aaBlosum[13][11] = 0.266924750511; aaBlosum[13][12] = 1.773855168830; aaBlosum[13][13] = 0.000000000000; aaBlosum[13][14] = 0.233597909629; 
    aaBlosum[13][15] = 0.540027644824; aaBlosum[13][16] = 0.488206118793; aaBlosum[13][17] = 2.074324893497; aaBlosum[13][18] = 6.747260430801; aaBlosum[13][19] = 0.838119610178; 
    aaBlosum[14][ 0] = 1.173275900924; aaBlosum[14][ 1] = 0.448133661718; aaBlosum[14][ 2] = 0.494887043702; aaBlosum[14][ 3] = 0.730628272998; aaBlosum[14][ 4] = 0.356008498769; 
    aaBlosum[14][ 5] = 0.858570575674; aaBlosum[14][ 6] = 0.926563934846; aaBlosum[14][ 7] = 0.504086599527; aaBlosum[14][ 8] = 0.527007339151; aaBlosum[14][ 9] = 0.388355409206; 
    aaBlosum[14][10] = 0.374555687471; aaBlosum[14][11] = 1.047383450722; aaBlosum[14][12] = 0.454123625103; aaBlosum[14][13] = 0.233597909629; aaBlosum[14][14] = 0.000000000000; 
    aaBlosum[14][15] = 1.169129577716; aaBlosum[14][16] = 1.005451683149; aaBlosum[14][17] = 0.252214830027; aaBlosum[14][18] = 0.369405319355; aaBlosum[14][19] = 0.496908410676; 
    aaBlosum[15][ 0] = 4.325092687057; aaBlosum[15][ 1] = 1.122783104210; aaBlosum[15][ 2] = 2.904101656456; aaBlosum[15][ 3] = 1.582754142065; aaBlosum[15][ 4] = 1.197188415094; 
    aaBlosum[15][ 5] = 1.934870924596; aaBlosum[15][ 6] = 1.769893238937; aaBlosum[15][ 7] = 1.509326253224; aaBlosum[15][ 8] = 1.117029762910; aaBlosum[15][ 9] = 0.357544412460; 
    aaBlosum[15][10] = 0.352969184527; aaBlosum[15][11] = 1.752165917819; aaBlosum[15][12] = 0.918723415746; aaBlosum[15][13] = 0.540027644824; aaBlosum[15][14] = 1.169129577716; 
    aaBlosum[15][15] = 0.000000000000; aaBlosum[15][16] = 5.151556292270; aaBlosum[15][17] = 0.387925622098; aaBlosum[15][18] = 0.796751520761; aaBlosum[15][19] = 0.561925457442; 
    aaBlosum[16][ 0] = 1.729178019485; aaBlosum[16][ 1] = 0.914665954563; aaBlosum[16][ 2] = 1.898173634533; aaBlosum[16][ 3] = 0.934187509431; aaBlosum[16][ 4] = 1.119831358516; 
    aaBlosum[16][ 5] = 1.277480294596; aaBlosum[16][ 6] = 1.071097236007; aaBlosum[16][ 7] = 0.641436011405; aaBlosum[16][ 8] = 0.585407090225; aaBlosum[16][ 9] = 1.179091197260; 
    aaBlosum[16][10] = 0.915259857694; aaBlosum[16][11] = 1.303875200799; aaBlosum[16][12] = 1.488548053722; aaBlosum[16][13] = 0.488206118793; aaBlosum[16][14] = 1.005451683149; 
    aaBlosum[16][15] = 5.151556292270; aaBlosum[16][16] = 0.000000000000; aaBlosum[16][17] = 0.513128126891; aaBlosum[16][18] = 0.801010243199; aaBlosum[16][19] = 2.253074051176; 
    aaBlosum[17][ 0] = 0.465839367725; aaBlosum[17][ 1] = 0.426382310122; aaBlosum[17][ 2] = 0.191482046247; aaBlosum[17][ 3] = 0.145345046279; aaBlosum[17][ 4] = 0.527664418872; 
    aaBlosum[17][ 5] = 0.758653808642; aaBlosum[17][ 6] = 0.407635648938; aaBlosum[17][ 7] = 0.508358924638; aaBlosum[17][ 8] = 0.301248600780; aaBlosum[17][ 9] = 0.341985787540; 
    aaBlosum[17][10] = 0.691474634600; aaBlosum[17][11] = 0.332243040634; aaBlosum[17][12] = 0.888101098152; aaBlosum[17][13] = 2.074324893497; aaBlosum[17][14] = 0.252214830027; 
    aaBlosum[17][15] = 0.387925622098; aaBlosum[17][16] = 0.513128126891; aaBlosum[17][17] = 0.000000000000; aaBlosum[17][18] = 4.054419006558; aaBlosum[17][19] = 0.266508731426; 
    aaBlosum[18][ 0] = 0.718206697586; aaBlosum[18][ 1] = 0.720517441216; aaBlosum[18][ 2] = 0.538222519037; aaBlosum[18][ 3] = 0.261422208965; aaBlosum[18][ 4] = 0.470237733696; 
    aaBlosum[18][ 5] = 0.958989742850; aaBlosum[18][ 6] = 0.596719300346; aaBlosum[18][ 7] = 0.308055737035; aaBlosum[18][ 8] = 4.218953969389; aaBlosum[18][ 9] = 0.674617093228; 
    aaBlosum[18][10] = 0.811245856323; aaBlosum[18][11] = 0.717993486900; aaBlosum[18][12] = 0.951682162246; aaBlosum[18][13] = 6.747260430801; aaBlosum[18][14] = 0.369405319355; 
    aaBlosum[18][15] = 0.796751520761; aaBlosum[18][16] = 0.801010243199; aaBlosum[18][17] = 4.054419006558; aaBlosum[18][18] = 0.000000000000; aaBlosum[18][19] = 1.000000000000; 
    aaBlosum[19][ 0] = 2.187774522005; aaBlosum[19][ 1] = 0.438388343772; aaBlosum[19][ 2] = 0.312858797993; aaBlosum[19][ 3] = 0.258129289418; aaBlosum[19][ 4] = 1.116352478606; 
    aaBlosum[19][ 5] = 0.530785790125; aaBlosum[19][ 6] = 0.524253846338; aaBlosum[19][ 7] = 0.253340790190; aaBlosum[19][ 8] = 0.201555971750; aaBlosum[19][ 9] = 8.311839405458; 
    aaBlosum[19][10] = 2.231405688913; aaBlosum[19][11] = 0.498138475304; aaBlosum[19][12] = 2.575850755315; aaBlosum[19][13] = 0.838119610178; aaBlosum[19][14] = 0.496908410676; 
    aaBlosum[19][15] = 0.561925457442; aaBlosum[19][16] = 2.253074051176; aaBlosum[19][17] = 0.266508731426; aaBlosum[19][18] = 1.000000000000; aaBlosum[19][19] = 0.000000000000;

    blosPi[ 0] = 0.074; 
    blosPi[ 1] = 0.052; 
    blosPi[ 2] = 0.045; 
    blosPi[ 3] = 0.054;
    blosPi[ 4] = 0.025; 
    blosPi[ 5] = 0.034; 
    blosPi[ 6] = 0.054; 
    blosPi[ 7] = 0.074;
    blosPi[ 8] = 0.026; 
    blosPi[ 9] = 0.068; 
    blosPi[10] = 0.099; 
    blosPi[11] = 0.058;
    blosPi[12] = 0.025; 
    blosPi[13] = 0.047; 
    blosPi[14] = 0.039; 
    blosPi[15] = 0.057;
    blosPi[16] = 0.051; 
    blosPi[17] = 0.013; 
    blosPi[18] = 0.032; 
    blosPi[19] = 0.073;

    /* LG */
    aaLG[ 0][ 0] = 0.000000; aaLG[ 0][ 1] = 0.425093; aaLG[ 0][ 2] = 0.276818; aaLG[ 0][ 3] = 0.395144; aaLG[ 0][ 4] = 2.489084;
    aaLG[ 0][ 5] = 0.969894; aaLG[ 0][ 6] = 1.038545; aaLG[ 0][ 7] = 2.066040; aaLG[ 0][ 8] = 0.358858; aaLG[ 0][ 9] = 0.149830;
    aaLG[ 0][10] = 0.395337; aaLG[ 0][11] = 0.536518; aaLG[ 0][12] = 1.124035; aaLG[ 0][13] = 0.253701; aaLG[ 0][14] = 1.177651;
    aaLG[ 0][15] = 4.727182; aaLG[ 0][16] = 2.139501; aaLG[ 0][17] = 0.180717; aaLG[ 0][18] = 0.218959; aaLG[ 0][19] = 2.547870;
    aaLG[ 1][ 0] = 0.425093; aaLG[ 1][ 1] = 0.000000; aaLG[ 1][ 2] = 0.751878; aaLG[ 1][ 3] = 0.123954; aaLG[ 1][ 4] = 0.534551;
    aaLG[ 1][ 5] = 2.807908; aaLG[ 1][ 6] = 0.363970; aaLG[ 1][ 7] = 0.390192; aaLG[ 1][ 8] = 2.426601; aaLG[ 1][ 9] = 0.126991;
    aaLG[ 1][10] = 0.301848; aaLG[ 1][11] = 6.326067; aaLG[ 1][12] = 0.484133; aaLG[ 1][13] = 0.052722; aaLG[ 1][14] = 0.332533;
    aaLG[ 1][15] = 0.858151; aaLG[ 1][16] = 0.578987; aaLG[ 1][17] = 0.593607; aaLG[ 1][18] = 0.314440; aaLG[ 1][19] = 0.170887;
    aaLG[ 2][ 0] = 0.276818; aaLG[ 2][ 1] = 0.751878; aaLG[ 2][ 2] = 0.000000; aaLG[ 2][ 3] = 5.076149; aaLG[ 2][ 4] = 0.528768;
    aaLG[ 2][ 5] = 1.695752; aaLG[ 2][ 6] = 0.541712; aaLG[ 2][ 7] = 1.437645; aaLG[ 2][ 8] = 4.509238; aaLG[ 2][ 9] = 0.191503;
    aaLG[ 2][10] = 0.068427; aaLG[ 2][11] = 2.145078; aaLG[ 2][12] = 0.371004; aaLG[ 2][13] = 0.089525; aaLG[ 2][14] = 0.161787;
    aaLG[ 2][15] = 4.008358; aaLG[ 2][16] = 2.000679; aaLG[ 2][17] = 0.045376; aaLG[ 2][18] = 0.612025; aaLG[ 2][19] = 0.083688;
    aaLG[ 3][ 0] = 0.395144; aaLG[ 3][ 1] = 0.123954; aaLG[ 3][ 2] = 5.076149; aaLG[ 3][ 3] = 0.000000; aaLG[ 3][ 4] = 0.062556;
    aaLG[ 3][ 5] = 0.523386; aaLG[ 3][ 6] = 5.243870; aaLG[ 3][ 7] = 0.844926; aaLG[ 3][ 8] = 0.927114; aaLG[ 3][ 9] = 0.010690;
    aaLG[ 3][10] = 0.015076; aaLG[ 3][11] = 0.282959; aaLG[ 3][12] = 0.025548; aaLG[ 3][13] = 0.017416; aaLG[ 3][14] = 0.394456;
    aaLG[ 3][15] = 1.240275; aaLG[ 3][16] = 0.425860; aaLG[ 3][17] = 0.029890; aaLG[ 3][18] = 0.135107; aaLG[ 3][19] = 0.037967;
    aaLG[ 4][ 0] = 2.489084; aaLG[ 4][ 1] = 0.534551; aaLG[ 4][ 2] = 0.528768; aaLG[ 4][ 3] = 0.062556; aaLG[ 4][ 4] = 0.000000;
    aaLG[ 4][ 5] = 0.084808; aaLG[ 4][ 6] = 0.003499; aaLG[ 4][ 7] = 0.569265; aaLG[ 4][ 8] = 0.640543; aaLG[ 4][ 9] = 0.320627;
    aaLG[ 4][10] = 0.594007; aaLG[ 4][11] = 0.013266; aaLG[ 4][12] = 0.893680; aaLG[ 4][13] = 1.105251; aaLG[ 4][14] = 0.075382;
    aaLG[ 4][15] = 2.784478; aaLG[ 4][16] = 1.143480; aaLG[ 4][17] = 0.670128; aaLG[ 4][18] = 1.165532; aaLG[ 4][19] = 1.959291;
    aaLG[ 5][ 0] = 0.969894; aaLG[ 5][ 1] = 2.807908; aaLG[ 5][ 2] = 1.695752; aaLG[ 5][ 3] = 0.523386; aaLG[ 5][ 4] = 0.084808;
    aaLG[ 5][ 5] = 0.000000; aaLG[ 5][ 6] = 4.128591; aaLG[ 5][ 7] = 0.267959; aaLG[ 5][ 8] = 4.813505; aaLG[ 5][ 9] = 0.072854;
    aaLG[ 5][10] = 0.582457; aaLG[ 5][11] = 3.234294; aaLG[ 5][12] = 1.672569; aaLG[ 5][13] = 0.035855; aaLG[ 5][14] = 0.624294;
    aaLG[ 5][15] = 1.223828; aaLG[ 5][16] = 1.080136; aaLG[ 5][17] = 0.236199; aaLG[ 5][18] = 0.257336; aaLG[ 5][19] = 0.210332;
    aaLG[ 6][ 0] = 1.038545; aaLG[ 6][ 1] = 0.363970; aaLG[ 6][ 2] = 0.541712; aaLG[ 6][ 3] = 5.243870; aaLG[ 6][ 4] = 0.003499;
    aaLG[ 6][ 5] = 4.128591; aaLG[ 6][ 6] = 0.000000; aaLG[ 6][ 7] = 0.348847; aaLG[ 6][ 8] = 0.423881; aaLG[ 6][ 9] = 0.044265;
    aaLG[ 6][10] = 0.069673; aaLG[ 6][11] = 1.807177; aaLG[ 6][12] = 0.173735; aaLG[ 6][13] = 0.018811; aaLG[ 6][14] = 0.419409;
    aaLG[ 6][15] = 0.611973; aaLG[ 6][16] = 0.604545; aaLG[ 6][17] = 0.077852; aaLG[ 6][18] = 0.120037; aaLG[ 6][19] = 0.245034;
    aaLG[ 7][ 0] = 2.066040; aaLG[ 7][ 1] = 0.390192; aaLG[ 7][ 2] = 1.437645; aaLG[ 7][ 3] = 0.844926; aaLG[ 7][ 4] = 0.569265;
    aaLG[ 7][ 5] = 0.267959; aaLG[ 7][ 6] = 0.348847; aaLG[ 7][ 7] = 0.000000; aaLG[ 7][ 8] = 0.311484; aaLG[ 7][ 9] = 0.008705;
    aaLG[ 7][10] = 0.044261; aaLG[ 7][11] = 0.296636; aaLG[ 7][12] = 0.139538; aaLG[ 7][13] = 0.089586; aaLG[ 7][14] = 0.196961;
    aaLG[ 7][15] = 1.739990; aaLG[ 7][16] = 0.129836; aaLG[ 7][17] = 0.268491; aaLG[ 7][18] = 0.054679; aaLG[ 7][19] = 0.076701;
    aaLG[ 8][ 0] = 0.358858; aaLG[ 8][ 1] = 2.426601; aaLG[ 8][ 2] = 4.509238; aaLG[ 8][ 3] = 0.927114; aaLG[ 8][ 4] = 0.640543;
    aaLG[ 8][ 5] = 4.813505; aaLG[ 8][ 6] = 0.423881; aaLG[ 8][ 7] = 0.311484; aaLG[ 8][ 8] = 0.000000; aaLG[ 8][ 9] = 0.108882;
    aaLG[ 8][10] = 0.366317; aaLG[ 8][11] = 0.697264; aaLG[ 8][12] = 0.442472; aaLG[ 8][13] = 0.682139; aaLG[ 8][14] = 0.508851;
    aaLG[ 8][15] = 0.990012; aaLG[ 8][16] = 0.584262; aaLG[ 8][17] = 0.597054; aaLG[ 8][18] = 5.306834; aaLG[ 8][19] = 0.119013;
    aaLG[ 9][ 0] = 0.149830; aaLG[ 9][ 1] = 0.126991; aaLG[ 9][ 2] = 0.191503; aaLG[ 9][ 3] = 0.010690; aaLG[ 9][ 4] = 0.320627;
    aaLG[ 9][ 5] = 0.072854; aaLG[ 9][ 6] = 0.044265; aaLG[ 9][ 7] = 0.008705; aaLG[ 9][ 8] = 0.108882; aaLG[ 9][ 9] = 0.000000;
    aaLG[ 9][10] = 4.145067; aaLG[ 9][11] = 0.159069; aaLG[ 9][12] = 4.273607; aaLG[ 9][13] = 1.112727; aaLG[ 9][14] = 0.078281;
    aaLG[ 9][15] = 0.064105; aaLG[ 9][16] = 1.033739; aaLG[ 9][17] = 0.111660; aaLG[ 9][18] = 0.232523; aaLG[ 9][19] = 10.649107;
    aaLG[10][ 0] = 0.395337; aaLG[10][ 1] = 0.301848; aaLG[10][ 2] = 0.068427; aaLG[10][ 3] = 0.015076; aaLG[10][ 4] = 0.594007;
    aaLG[10][ 5] = 0.582457; aaLG[10][ 6] = 0.069673; aaLG[10][ 7] = 0.044261; aaLG[10][ 8] = 0.366317; aaLG[10][ 9] = 4.145067;
    aaLG[10][10] = 0.000000; aaLG[10][11] = 0.137500; aaLG[10][12] = 6.312358; aaLG[10][13] = 2.592692; aaLG[10][14] = 0.249060;
    aaLG[10][15] = 0.182287; aaLG[10][16] = 0.302936; aaLG[10][17] = 0.619632; aaLG[10][18] = 0.299648; aaLG[10][19] = 1.702745;
    aaLG[11][ 0] = 0.536518; aaLG[11][ 1] = 6.326067; aaLG[11][ 2] = 2.145078; aaLG[11][ 3] = 0.282959; aaLG[11][ 4] = 0.013266;
    aaLG[11][ 5] = 3.234294; aaLG[11][ 6] = 1.807177; aaLG[11][ 7] = 0.296636; aaLG[11][ 8] = 0.697264; aaLG[11][ 9] = 0.159069;
    aaLG[11][10] = 0.137500; aaLG[11][11] = 0.000000; aaLG[11][12] = 0.656604; aaLG[11][13] = 0.023918; aaLG[11][14] = 0.390322;
    aaLG[11][15] = 0.748683; aaLG[11][16] = 1.136863; aaLG[11][17] = 0.049906; aaLG[11][18] = 0.131932; aaLG[11][19] = 0.185202;
    aaLG[12][ 0] = 1.124035; aaLG[12][ 1] = 0.484133; aaLG[12][ 2] = 0.371004; aaLG[12][ 3] = 0.025548; aaLG[12][ 4] = 0.893680;
    aaLG[12][ 5] = 1.672569; aaLG[12][ 6] = 0.173735; aaLG[12][ 7] = 0.139538; aaLG[12][ 8] = 0.442472; aaLG[12][ 9] = 4.273607;
    aaLG[12][10] = 6.312358; aaLG[12][11] = 0.656604; aaLG[12][12] = 0.000000; aaLG[12][13] = 1.798853; aaLG[12][14] = 0.099849;
    aaLG[12][15] = 0.346960; aaLG[12][16] = 2.020366; aaLG[12][17] = 0.696175; aaLG[12][18] = 0.481306; aaLG[12][19] = 1.898718;
    aaLG[13][ 0] = 0.253701; aaLG[13][ 1] = 0.052722; aaLG[13][ 2] = 0.089525; aaLG[13][ 3] = 0.017416; aaLG[13][ 4] = 1.105251;
    aaLG[13][ 5] = 0.035855; aaLG[13][ 6] = 0.018811; aaLG[13][ 7] = 0.089586; aaLG[13][ 8] = 0.682139; aaLG[13][ 9] = 1.112727;
    aaLG[13][10] = 2.592692; aaLG[13][11] = 0.023918; aaLG[13][12] = 1.798853; aaLG[13][13] = 0.000000; aaLG[13][14] = 0.094464;
    aaLG[13][15] = 0.361819; aaLG[13][16] = 0.165001; aaLG[13][17] = 2.457121; aaLG[13][18] = 7.803902; aaLG[13][19] = 0.654683;
    aaLG[14][ 0] = 1.177651; aaLG[14][ 1] = 0.332533; aaLG[14][ 2] = 0.161787; aaLG[14][ 3] = 0.394456; aaLG[14][ 4] = 0.075382;
    aaLG[14][ 5] = 0.624294; aaLG[14][ 6] = 0.419409; aaLG[14][ 7] = 0.196961; aaLG[14][ 8] = 0.508851; aaLG[14][ 9] = 0.078281;
    aaLG[14][10] = 0.249060; aaLG[14][11] = 0.390322; aaLG[14][12] = 0.099849; aaLG[14][13] = 0.094464; aaLG[14][14] = 0.000000;
    aaLG[14][15] = 1.338132; aaLG[14][16] = 0.571468; aaLG[14][17] = 0.095131; aaLG[14][18] = 0.089613; aaLG[14][19] = 0.296501;
    aaLG[15][ 0] = 4.727182; aaLG[15][ 1] = 0.858151; aaLG[15][ 2] = 4.008358; aaLG[15][ 3] = 1.240275; aaLG[15][ 4] = 2.784478;
    aaLG[15][ 5] = 1.223828; aaLG[15][ 6] = 0.611973; aaLG[15][ 7] = 1.739990; aaLG[15][ 8] = 0.990012; aaLG[15][ 9] = 0.064105;
    aaLG[15][10] = 0.182287; aaLG[15][11] = 0.748683; aaLG[15][12] = 0.346960; aaLG[15][13] = 0.361819; aaLG[15][14] = 1.338132;
    aaLG[15][15] = 0.000000; aaLG[15][16] = 6.472279; aaLG[15][17] = 0.248862; aaLG[15][18] = 0.400547; aaLG[15][19] = 0.098369;
    aaLG[16][ 0] = 2.139501; aaLG[16][ 1] = 0.578987; aaLG[16][ 2] = 2.000679; aaLG[16][ 3] = 0.425860; aaLG[16][ 4] = 1.143480;
    aaLG[16][ 5] = 1.080136; aaLG[16][ 6] = 0.604545; aaLG[16][ 7] = 0.129836; aaLG[16][ 8] = 0.584262; aaLG[16][ 9] = 1.033739;
    aaLG[16][10] = 0.302936; aaLG[16][11] = 1.136863; aaLG[16][12] = 2.020366; aaLG[16][13] = 0.165001; aaLG[16][14] = 0.571468;
    aaLG[16][15] = 6.472279; aaLG[16][16] = 0.000000; aaLG[16][17] = 0.140825; aaLG[16][18] = 0.245841; aaLG[16][19] = 2.188158;
    aaLG[17][ 0] = 0.180717; aaLG[17][ 1] = 0.593607; aaLG[17][ 2] = 0.045376; aaLG[17][ 3] = 0.029890; aaLG[17][ 4] = 0.670128;
    aaLG[17][ 5] = 0.236199; aaLG[17][ 6] = 0.077852; aaLG[17][ 7] = 0.268491; aaLG[17][ 8] = 0.597054; aaLG[17][ 9] = 0.111660;
    aaLG[17][10] = 0.619632; aaLG[17][11] = 0.049906; aaLG[17][12] = 0.696175; aaLG[17][13] = 2.457121; aaLG[17][14] = 0.095131;
    aaLG[17][15] = 0.248862; aaLG[17][16] = 0.140825; aaLG[17][17] = 0.000000; aaLG[17][18] = 3.151815; aaLG[17][19] = 0.189510;
    aaLG[18][ 0] = 0.218959; aaLG[18][ 1] = 0.314440; aaLG[18][ 2] = 0.612025; aaLG[18][ 3] = 0.135107; aaLG[18][ 4] = 1.165532;
    aaLG[18][ 5] = 0.257336; aaLG[18][ 6] = 0.120037; aaLG[18][ 7] = 0.054679; aaLG[18][ 8] = 5.306834; aaLG[18][ 9] = 0.232523;
    aaLG[18][10] = 0.299648; aaLG[18][11] = 0.131932; aaLG[18][12] = 0.481306; aaLG[18][13] = 7.803902; aaLG[18][14] = 0.089613;
    aaLG[18][15] = 0.400547; aaLG[18][16] = 0.245841; aaLG[18][17] = 3.151815; aaLG[18][18] = 0.000000; aaLG[18][19] = 0.249313;
    aaLG[19][ 0] = 2.547870; aaLG[19][ 1] = 0.170887; aaLG[19][ 2] = 0.083688; aaLG[19][ 3] = 0.037967; aaLG[19][ 4] = 1.959291;
    aaLG[19][ 5] = 0.210332; aaLG[19][ 6] = 0.245034; aaLG[19][ 7] = 0.076701; aaLG[19][ 8] = 0.119013; aaLG[19][ 9] = 10.649107;
    aaLG[19][10] = 1.702745; aaLG[19][11] = 0.185202; aaLG[19][12] = 1.898718; aaLG[19][13] = 0.654683; aaLG[19][14] = 0.296501;
    aaLG[19][15] = 0.098369; aaLG[19][16] = 2.188158; aaLG[19][17] = 0.189510; aaLG[19][18] = 0.249313; aaLG[19][19] = 0.000000;

    lgPi[0] = 0.079066;  lgPi[1] = 0.055941;  lgPi[2] = 0.041977;  lgPi[3] = 0.053052;
    lgPi[4] = 0.012937;  lgPi[5] = 0.040767;  lgPi[6] = 0.071586;  lgPi[7] = 0.057337;
    lgPi[8] = 0.022355;  lgPi[9] = 0.062157;  lgPi[10] = 0.099081; lgPi[11] = 0.064600;
    lgPi[12] = 0.022951; lgPi[13] = 0.042302; lgPi[14] = 0.044040; lgPi[15] = 0.061197;
    lgPi[16] = 0.053287; lgPi[17] = 0.012066; lgPi[18] = 0.034155; lgPi[19] = 0.069147;

    /* now, check that the matrices are symmetrical */
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            diff = aaJones[i][j] - aaJones[j][i];
            if (diff < 0.0)
                diff = -diff;
            if (diff > 0.001)
                {
                MrBayesPrint ("%s   ERROR: Jones model is not symmetrical.\n");
                return (ERROR);
                }
            }
        }
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            diff = aaDayhoff[i][j] - aaDayhoff[j][i];
            if (diff < 0.0)
                diff = -diff;
            if (diff > 0.001)
                {
                MrBayesPrint ("%s   ERROR: Dayhoff model is not symmetrical.\n");
                return (ERROR);
                }
            }
        }
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            diff = aaMtrev24[i][j] - aaMtrev24[j][i];
            if (diff < 0.0)
                diff = -diff;
            if (diff > 0.001)
                {
                MrBayesPrint ("%s   ERROR: mtrev24 model is not symmetrical.\n");
                return (ERROR);
                }
            }
        }
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            diff = aaMtmam[i][j] - aaMtmam[j][i];
            if (diff < 0.0)
                diff = -diff;
            if (diff > 0.001)
                {
                MrBayesPrint ("%s   ERROR: mtmam model is not symmetrical.\n");
                return (ERROR);
                }
            }
        }
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            diff = aartREV[i][j] - aartREV[j][i];
            if (diff < 0.0)
                diff = -diff;
            if (diff > 0.001)
                {
                MrBayesPrint ("%s   ERROR: aartREV model is not symmetrical.\n");
                return (ERROR);
                }
            }
        }
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            diff = aaWAG[i][j] - aaWAG[j][i];
            if (diff < 0.0)
                diff = -diff;
            if (diff > 0.001)
                {
                MrBayesPrint ("%s   ERROR: aaWAG model is not symmetrical.\n");
                return (ERROR);
                }
            }
        }
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            diff = aacpREV[i][j] - aacpREV[j][i];
            if (diff < 0.0)
                diff = -diff;
            if (diff > 0.001)
                {
                MrBayesPrint ("%s   ERROR: cpREV model is not symmetrical.\n");
                return (ERROR);
                }
            }
        }
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            diff = aaVt[i][j] - aaVt[j][i];
            if (diff < 0.0)
                diff = -diff;
            if (diff > 0.001)
                {
                MrBayesPrint ("%s   ERROR: Vt model is not symmetrical.\n");
                return (ERROR);
                }
            }
        }
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            diff = aaBlosum[i][j] - aaBlosum[j][i];
            if (diff < 0.0)
                diff = -diff;
            if (diff > 0.001)
                {
                MrBayesPrint ("%s   ERROR: Blosum model is not symmetrical.\n");
                return (ERROR);
                }
            }
        }
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            diff = aaLG[i][j] - aaLG[j][i];
            if (diff < 0.0)
                diff = -diff;
            if (diff > 0.001)
                {
                MrBayesPrint ("%s   ERROR: LG model is not symmetrical.\n");
                return (ERROR);
                }
            }
        }
    
    /* rescale stationary frequencies, to make certain they sum to 1.0 */
    sum = 0.0;
    for (i=0; i<20; i++)
        sum += jonesPi[i];
    for (i=0; i<20; i++)
        jonesPi[i] /= sum;
    sum = 0.0;
    for (i=0; i<20; i++)
        sum += dayhoffPi[i];
    for (i=0; i<20; i++)
        dayhoffPi[i] /= sum;
    sum = 0.0;
    for (i=0; i<20; i++)
        sum += mtrev24Pi[i];
    for (i=0; i<20; i++)
        mtrev24Pi[i] /= sum;
    sum = 0.0;
    for (i=0; i<20; i++)
        sum += mtmamPi[i];
    for (i=0; i<20; i++)
        mtmamPi[i] /= sum;
    sum = 0.0;
    for (i=0; i<20; i++)
        sum += rtrevPi[i];
    for (i=0; i<20; i++)
        rtrevPi[i] /= sum;
    sum = 0.0;
    for (i=0; i<20; i++)
        sum += wagPi[i];
    for (i=0; i<20; i++)
        wagPi[i] /= sum;
    sum = 0.0;
    for (i=0; i<20; i++)
        sum += cprevPi[i];
    for (i=0; i<20; i++)
        cprevPi[i] /= sum;
    sum = 0.0;
    for (i=0; i<20; i++)
        sum += vtPi[i];
    for (i=0; i<20; i++)
        vtPi[i] /= sum;
    sum = 0.0;
    for (i=0; i<20; i++)
        sum += blosPi[i];
    for (i=0; i<20; i++)
        blosPi[i] /= sum;
    sum = 0.0;
    for (i=0; i<20; i++)
        sum += lgPi[i];
    for (i=0; i<20; i++)
        lgPi[i] /= sum;
    
    /* multiply entries by amino acid frequencies */
    for (i=0; i<20; i++)
        {
        for (j=0; j<20; j++)
            {
            aaJones[i][j]   *= jonesPi[j];
            aaDayhoff[i][j] *= dayhoffPi[j];
            aaMtrev24[i][j] *= mtrev24Pi[j];
            aaMtmam[i][j]   *= mtmamPi[j];
            aartREV[i][j]   *= rtrevPi[j];
            aaWAG[i][j]     *= wagPi[j];
            aacpREV[i][j]   *= cprevPi[j];
            aaVt[i][j]      *= vtPi[j];
            aaBlosum[i][j]  *= blosPi[j];
            aaLG[i][j]      *= lgPi[j];
            }
        }
        
    /* rescale, so branch lengths are in terms of expected number of
       amino acid substitutions per site */
    scaler = 0.0;
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            scaler += jonesPi[i] * aaJones[i][j];
            scaler += jonesPi[j] * aaJones[j][i];
            }
        }
    scaler = 1.0 / scaler;
    for (i=0; i<20; i++)
        for (j=0; j<20; j++)
            aaJones[i][j] *= scaler;
    scaler = 0.0;
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            scaler += dayhoffPi[i] * aaDayhoff[i][j];
            scaler += dayhoffPi[j] * aaDayhoff[j][i];
            }
        }
    scaler = 1.0 / scaler;
    for (i=0; i<20; i++)
        for (j=0; j<20; j++)
            aaDayhoff[i][j] *= scaler;
    scaler = 0.0;
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            scaler += mtrev24Pi[i] * aaMtrev24[i][j];
            scaler += mtrev24Pi[j] * aaMtrev24[j][i];
            }
        }
    scaler = 1.0 / scaler;
    for (i=0; i<20; i++)
        for (j=0; j<20; j++)
            aaMtrev24[i][j] *= scaler;
    scaler = 0.0;
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            scaler += mtmamPi[i] * aaMtmam[i][j];
            scaler += mtmamPi[j] * aaMtmam[j][i];
            }
        }
    scaler = 1.0 / scaler;
    for (i=0; i<20; i++)
        for (j=0; j<20; j++)
            aaMtmam[i][j] *= scaler;
    scaler = 0.0;
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            scaler += rtrevPi[i] * aartREV[i][j];
            scaler += rtrevPi[j] * aartREV[j][i];
            }
        }
    scaler = 1.0 / scaler;
    for (i=0; i<20; i++)
        for (j=0; j<20; j++)
            aartREV[i][j] *= scaler;
    scaler = 0.0;
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            scaler += wagPi[i] * aaWAG[i][j];
            scaler += wagPi[j] * aaWAG[j][i];
            }
        }
    scaler = 1.0 / scaler;
    for (i=0; i<20; i++)
        for (j=0; j<20; j++)
            aaWAG[i][j] *= scaler;
    scaler = 0.0;
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            scaler += cprevPi[i] * aacpREV[i][j];
            scaler += cprevPi[j] * aacpREV[j][i];
            }
        }
    scaler = 1.0 / scaler;
    for (i=0; i<20; i++)
        for (j=0; j<20; j++)
            aacpREV[i][j] *= scaler;
    scaler = 0.0;
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            scaler += vtPi[i] * aaVt[i][j];
            scaler += vtPi[j] * aaVt[j][i];
            }
        }
    scaler = 1.0 / scaler;
    for (i=0; i<20; i++)
        for (j=0; j<20; j++)
            aaVt[i][j] *= scaler;
    scaler = 0.0;
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            scaler += blosPi[i] * aaBlosum[i][j];
            scaler += blosPi[j] * aaBlosum[j][i];
            }
        }
    scaler = 1.0 / scaler;
    for (i=0; i<20; i++)
        for (j=0; j<20; j++)
            aaBlosum[i][j] *= scaler;
    scaler = 0.0;
    for (i=0; i<20; i++)
        {
        for (j=i+1; j<20; j++)
            {
            scaler += lgPi[i] * aaLG[i][j];
            scaler += lgPi[j] * aaLG[j][i];
            }
        }
    scaler = 1.0 / scaler;
    for (i=0; i<20; i++)
        for (j=0; j<20; j++)
            aaLG[i][j] *= scaler;
    
    /* set diagonal of matrix */
    for (i=0; i<20; i++)
        {
        sum = 0.0;
        for (j=0; j<20; j++)
            {
            if (i != j)
                sum += aaJones[i][j];
            }
        aaJones[i][i] = -sum;
        }
    for (i=0; i<20; i++)
        {
        sum = 0.0;
        for (j=0; j<20; j++)
            {
            if (i != j)
                sum += aaDayhoff[i][j];
            }
        aaDayhoff[i][i] = -sum;
        }
    for (i=0; i<20; i++)
        {
        sum = 0.0;
        for (j=0; j<20; j++)
            {
            if (i != j)
                sum += aaMtrev24[i][j];
            }
        aaMtrev24[i][i] = -sum;
        }
    for (i=0; i<20; i++)
        {
        sum = 0.0;
        for (j=0; j<20; j++)
            {
            if (i != j)
                sum += aaMtmam[i][j];
            }
        aaMtmam[i][i] = -sum;
        }
    for (i=0; i<20; i++)
        {
        sum = 0.0;
        for (j=0; j<20; j++)
            {
            if (i != j)
                sum += aartREV[i][j];
            }
        aartREV[i][i] = -sum;
        }
    for (i=0; i<20; i++)
        {
        sum = 0.0;
        for (j=0; j<20; j++)
            {
            if (i != j)
                sum += aaWAG[i][j];
            }
        aaWAG[i][i] = -sum;
        }
    for (i=0; i<20; i++)
        {
        sum = 0.0;
        for (j=0; j<20; j++)
            {
            if (i != j)
                sum += aacpREV[i][j];
            }
        aacpREV[i][i] = -sum;
        }
    for (i=0; i<20; i++)
        {
        sum = 0.0;
        for (j=0; j<20; j++)
            {
            if (i != j)
                sum += aaVt[i][j];
            }
        aaVt[i][i] = -sum;
        }
    for (i=0; i<20; i++)
        {
        sum = 0.0;
        for (j=0; j<20; j++)
            {
            if (i != j)
                sum += aaBlosum[i][j];
            }
        aaBlosum[i][i] = -sum;
        }
    for (i=0; i<20; i++)
        {
        sum = 0.0;
        for (j=0; j<20; j++)
            {
            if (i != j)
                sum += aaLG[i][j];
            }
        aaLG[i][i] = -sum;
        }

#   if 0
    for (i=0; i<20; i++)
        {
        MrBayesPrint ("%s   ", spacer);
        for (j=0; j<20; j++)
            {
            if (aaLG[i][j] < 0.0)
                MrBayesPrint ("%1.3lf ", aaLG[i][j]);
            else
                MrBayesPrint (" %1.3lf ", aaLG[i][j]);
            }
        MrBayesPrint ("\n");
        }
#   endif

    return (NO_ERROR);
}


void SetCode (int part)
{
    int     i, s, s1, s2, s3, ns;
    
    modelParams[part].codon[ 0] = 12; /* AAA Lys */
    modelParams[part].codon[ 1] =  3; /* AAC Asn */
    modelParams[part].codon[ 2] = 12; /* AAG Lys */
    modelParams[part].codon[ 3] =  3; /* AAT Asn */
    modelParams[part].codon[ 4] = 17; /* ACA Thr */
    modelParams[part].codon[ 5] = 17; /* ACC Thr */
    modelParams[part].codon[ 6] = 17; /* ACG Thr */
    modelParams[part].codon[ 7] = 17; /* ACT Thr */
    modelParams[part].codon[ 8] =  2; /* AGA Arg */
    modelParams[part].codon[ 9] = 16; /* AGC Ser */
    modelParams[part].codon[10] =  2; /* AGG Arg */
    modelParams[part].codon[11] = 16; /* AGT Ser */
    modelParams[part].codon[12] = 10; /* ATA Ile */
    modelParams[part].codon[13] = 10; /* ATC Ile */
    modelParams[part].codon[14] = 13; /* ATG Met */
    modelParams[part].codon[15] = 10; /* ATT Ile */
    modelParams[part].codon[16] =  6; /* CAA Gln */
    modelParams[part].codon[17] =  9; /* CAC His */
    modelParams[part].codon[18] =  6; /* CAG Gln */
    modelParams[part].codon[19] =  9; /* CAT His */
    modelParams[part].codon[20] = 15; /* CCA Pro */
    modelParams[part].codon[21] = 15; /* CCC Pro */
    modelParams[part].codon[22] = 15; /* CCG Pro */
    modelParams[part].codon[23] = 15; /* CCT Pro */
    modelParams[part].codon[24] =  2; /* CGA Arg */
    modelParams[part].codon[25] =  2; /* CGC Arg */
    modelParams[part].codon[26] =  2; /* CGG Arg */
    modelParams[part].codon[27] =  2; /* CGT Arg */
    modelParams[part].codon[28] = 11; /* CTA Leu */
    modelParams[part].codon[29] = 11; /* CTC Leu */
    modelParams[part].codon[30] = 11; /* CTG Leu */
    modelParams[part].codon[31] = 11; /* CTT Leu */
    modelParams[part].codon[32] =  7; /* GAA Glu */
    modelParams[part].codon[33] =  4; /* GAC Asp */
    modelParams[part].codon[34] =  7; /* GAG Glu */
    modelParams[part].codon[35] =  4; /* GAT Asp */
    modelParams[part].codon[36] =  1; /* GCA Ala */
    modelParams[part].codon[37] =  1; /* GCC Ala */
    modelParams[part].codon[38] =  1; /* GCG Ala */
    modelParams[part].codon[39] =  1; /* GCT Ala */
    modelParams[part].codon[40] =  8; /* GGA Gly */
    modelParams[part].codon[41] =  8; /* GGC Gly */
    modelParams[part].codon[42] =  8; /* GGG Gly */
    modelParams[part].codon[43] =  8; /* GGT Gly */
    modelParams[part].codon[44] = 20; /* GTA Val */
    modelParams[part].codon[45] = 20; /* GTC Val */
    modelParams[part].codon[46] = 20; /* GTG Val */
    modelParams[part].codon[47] = 20; /* GTT Val */
    modelParams[part].codon[48] = 21; /* TAA Stop*/
    modelParams[part].codon[49] = 19; /* TAC Tyr */
    modelParams[part].codon[50] = 21; /* TAG Stop*/
    modelParams[part].codon[51] = 19; /* TAT Tyr */
    modelParams[part].codon[52] = 16; /* TCA Ser */
    modelParams[part].codon[53] = 16; /* TCC Ser */
    modelParams[part].codon[54] = 16; /* TCG Ser */
    modelParams[part].codon[55] = 16; /* TCT Ser */
    modelParams[part].codon[56] = 21; /* TGA Stop*/
    modelParams[part].codon[57] =  5; /* TGC Cys */
    modelParams[part].codon[58] = 18; /* TGG Trp */
    modelParams[part].codon[59] =  5; /* TGT Cys */
    modelParams[part].codon[60] = 11; /* TTA Leu */
    modelParams[part].codon[61] = 14; /* TTC Phe */
    modelParams[part].codon[62] = 11; /* TTG Leu */
    modelParams[part].codon[63] = 14; /* TTT Phe */
    
    if (!strcmp(modelParams[part].geneticCode, "Vertmt"))
        {
        /* UGA: Ter -> Trp
           AUA: Ile -> Met
           AGA: Arg -> Ter
           AGG: Arg -> Ter */
        modelParams[part].codon[ 8] = 21; /* AGA Stop */
        modelParams[part].codon[10] = 21; /* AGG Stop */
        modelParams[part].codon[12] = 13; /* ATA Met  */
        modelParams[part].codon[56] = 18; /* TGA Trp  */
        }
    else if (!strcmp(modelParams[part].geneticCode, "Mycoplasma"))
        {
        /* UGA: Ter -> Trp */
        modelParams[part].codon[56] = 18; /* TGA Trp */
        }
    else if (!strcmp(modelParams[part].geneticCode, "Yeast"))
        {
        /* UGA: Ter -> Trp
           AUA: Ile -> Met
           CUA: Leu -> Thr
           CUC: Leu -> Thr
           CUG: Leu -> Thr
           CUU: Leu -> Thr */
        modelParams[part].codon[12] = 13; /* ATA Met */
        modelParams[part].codon[28] = 17; /* CTA Thr */
        modelParams[part].codon[29] = 17; /* CTC Thr */
        modelParams[part].codon[30] = 17; /* CTG Thr */
        modelParams[part].codon[31] = 17; /* CTT Thr */
        modelParams[part].codon[56] = 18; /* TGA Trp */
        }
    else if (!strcmp(modelParams[part].geneticCode, "Ciliates"))
        {
        /* UAA: Ter -> Gln
           UAG: Ter -> Gln */
        modelParams[part].codon[48] =  6; /* TAA Gln */
        modelParams[part].codon[50] =  6; /* TAG Gln */
        }
    else if (!strcmp(modelParams[part].geneticCode, "Metmt"))
        {
        /* UGA: Ter -> Trp
           AUA: Ile -> Met
           AGA: Arg -> Ser
           AGG: Arg -> Ser */
        modelParams[part].codon[ 8] = 16; /* AGA Ser */
        modelParams[part].codon[10] = 16; /* AGG Ser */
        modelParams[part].codon[12] = 13; /* ATA Met */
        modelParams[part].codon[56] = 18; /* TGA Trp */
        }
    else
        {
        
        }
    
    ns = 0;
    for (i=0; i<64; i++)
        {
        if (modelParams[part].codon[i] != 21)
            ns++;
        }
    /* printf ("ns = %d\n", ns); */
    
    s = 0;
    for (s1=0; s1<4; s1++)
        for (s2=0; s2<4; s2++)
            for (s3=0; s3<4; s3++)
                if (modelParams[part].codon[s1*16 + s2*4 + s3] != 21)
                    {
                    modelParams[part].codonNucs[s][0] = s1;
                    modelParams[part].codonNucs[s][1] = s2;
                    modelParams[part].codonNucs[s][2] = s3;
                    modelParams[part].codonAAs[s] = modelParams[part].codon[s1*16 + s2*4 + s3];
                    s++;
                    }
}


int SetLocalTaxa (void)
{
    int         i, j;
    
    /* free memory if allocated */
    if (memAllocs[ALLOC_LOCTAXANAMES] == YES)
        {
        free (localTaxonNames);
        localTaxonNames = NULL;
        memAllocs[ALLOC_LOCTAXANAMES] = NO;
        }
    if (memAllocs[ALLOC_LOCALTAXONCALIBRATION] == YES)
        {
        free (localTaxonCalibration);
        localTaxonCalibration = NULL;
        memAllocs[ALLOC_LOCALTAXONCALIBRATION] = NO;
        }
    
    /* count number of non-excluded taxa */
    numLocalTaxa = 0;
    for (i=0; i<numTaxa; i++)
        {
        if (taxaInfo[i].isDeleted == NO)
            numLocalTaxa++;
        }
        
    /* allocate memory */
    localTaxonNames = (char **)SafeCalloc((size_t) numLocalTaxa, sizeof(char *));
    if (!localTaxonNames)
        return (ERROR);
    memAllocs[ALLOC_LOCTAXANAMES] = YES;

    localTaxonCalibration = (Calibration **)SafeCalloc((size_t) numLocalTaxa, sizeof(Calibration *));
    if (!localTaxonCalibration)
        return (ERROR);
    memAllocs[ALLOC_LOCALTAXONCALIBRATION] = YES;
        
    /* point to names and calibrations of non-excluded taxa */
    localOutGroup = 0;
    for (i=j=0; i<numTaxa; i++)
        {
        if (taxaInfo[i].isDeleted == NO)
            {
            localTaxonNames[j] = taxaNames[i];
            localTaxonCalibration[j] = &tipCalibration[i];
            if (i == outGroupNum)
                localOutGroup = j;
            j++;
            }
        }

#   if 0
    /* show non-excluded taxa */
    for (i=0; i<numLocalTaxa; i++)
        MrBayesPrint ("%s   %4d %s\n", spacer, i+1, localTaxonNames[i]);
#   endif
        
    return (NO_ERROR);
}


/*----------------------------------------------------------------------------
|
|   SetModelDefaults: This function will set up model defaults in modelParams.
|       It will also initialize parameters and moves by calling SetUpAnalysis.
|
-----------------------------------------------------------------------------*/
int SetModelDefaults (void)
{
    int         j;

    MrBayesPrint ("%s   Setting model defaults\n", spacer);
    MrBayesPrint ("%s   Seed (for generating default start values) = %d\n", spacer, globalSeed);

    if (InitializeLinks () == ERROR)
        {
        MrBayesPrint ("%s   Problem initializing link table\n", spacer);
        return (ERROR);
        }

    /* Check that models are allocated */
    if (memAllocs[ALLOC_MODEL] == NO)
        {
        MrBayesPrint ("%s   Model not allocated in SetModelDefaults\n", spacer);
        return (ERROR);
        }

    /* model parameters */
    for (j=0; j<numCurrentDivisions; j++)
        {
        modelParams[j] = defaultModel;                      /* start with default settings */
        
        modelParams[j].dataType = DataType (j);             /* data type for partition                      */

        if (modelParams[j].dataType == STANDARD)            /* set default ascertainment bias for partition */
            strcpy(modelParams[j].coding, "Variable"); 
        else if (modelParams[j].dataType == RESTRICTION)
            strcpy(modelParams[j].coding, "Noabsencesites");
        else
            strcpy(modelParams[j].coding, "All");

        SetCode (j);
        modelParams[j].nStates = NumStates (j);             /* number of states for partition             */

        modelParams[j].activeConstraints = (int *) SafeCalloc(numDefinedConstraints, sizeof(int));  /* allocate space for active constraints (yes/no) */
        }

    return (NO_ERROR);
}


/*----------------------------------------------------------------------------
|
|   SetModelInfo: This function will set up model info using model
|       params
|
-----------------------------------------------------------------------------*/
int SetModelInfo (void)
{
    int             i, j, chn, ts;
    ModelParams     *mp;
    ModelInfo       *m;
    
    /* wipe all model settings */
    inferSiteRates = NO;
    inferAncStates = NO;
    inferSiteOmegas = NO;

    for (i=0; i<numCurrentDivisions; i++)
        {
        m = &modelSettings[i];

        /* make certain that we set this intentionally to "NO" so we 
           calculate cijk information and calculate cond likes when needed */
        m->upDateCijk = YES;
        m->upDateCl = YES;
        m->upDateAll = YES;

        /* make certain that we start with a parsimony branch length of zero */
        for (j=0; j<MAX_CHAINS; j++)
            m->parsTreeLength[j*2] = m->parsTreeLength[j*2+1] = 0.0;

        m->tRatio = NULL;
        m->revMat = NULL;
        m->omega = NULL;
        m->stateFreq = NULL;
        m->shape = NULL;
        m->pInvar = NULL;
        m->correlation = NULL;
        m->switchRates = NULL;
        m->rateMult = NULL;
        m->topology = NULL;
        m->brlens = NULL;
        m->speciationRates = NULL;
        m->extinctionRates = NULL;
        m->fossilizationRates = NULL;
        m->popSize = NULL;
        m->aaModel = NULL;
        m->cppRate = NULL;
        m->cppEvents = NULL;
        m->cppMultDev = NULL;
        m->tk02var = NULL;
        m->tk02BranchRates = NULL;
        m->igrvar = NULL;
        m->igrBranchRates = NULL;
        m->mixedvar = NULL;
        m->mixedBrchRates = NULL;
        m->clockRate = NULL;

        m->CondLikeDown = NULL;
        m->CondLikeRoot = NULL;
        m->CondLikeScaler = NULL;
        m->Likelihood = NULL;
        m->TiProbs = NULL;

        m->CondLikeUp = NULL;
        m->StateCode = NULL;
        m->PrintAncStates = NULL;
        m->PrintSiteRates = NULL;
        
        m->printPosSel = NO;
        m->printAncStates = NO;
        m->printSiteRates = NO;

        m->nStates = NULL;
        m->bsIndex = NULL;
        m->cType = NULL;
        m->tiIndex = NULL;

        m->gibbsGamma = NO;
        m->gibbsFreq = 0;

        m->parsimonyBasedMove = NO;

#   if defined (BEAGLE_ENABLED)
        m->beagleInstance = -1;               /* beagle instance                              */
        m->logLikelihoods = NULL;             /* array of log likelihoods from Beagle         */
        m->inRates = NULL;                    /* array of category rates for Beagle           */
        m->branchLengths = NULL;              /* array of branch lengths for Beagle           */
        m->tiProbIndices = NULL;              /* array of trans prob indices for Beagle       */
        m->inWeights = NULL;                  /* array of weights for Beagle root likelihood  */
        m->bufferIndices = NULL;              /* array of partial indices for root likelihood */
        m->childBufferIndices = NULL;         /* array of child partial indices (unrooted)    */
        m->childTiProbIndices = NULL;         /* array of child ti prob indices (unrooted)    */
        m->cumulativeScaleIndices = NULL;     /* array of cumulative scale indices            */
#   endif

        /* likelihood calculator flags */
        m->useSSE = NO;                       /* use SSE code for this partition?             */
        m->useBeagle = NO;                    /* use Beagle for this partition?               */

        /* set all memory pointers to NULL */
        m->parsSets = NULL;
        m->numParsSets = 0;
        m->parsNodeLens = NULL;
        m->numParsNodeLens = 0;

        m->condLikes = NULL;
        m->tiProbs = NULL;
        m->scalers = NULL;
        m->numCondLikes = 0;
        m->numTiProbs = 0;
        m->numScalers = 0;

        m->condLikeIndex = NULL;
        m->condLikeScratchIndex = NULL;
        m->tiProbsIndex = NULL;
        m->tiProbsScratchIndex = NULL;
        m->nodeScalerIndex = NULL;
        m->nodeScalerScratchIndex = NULL;
        m->siteScalerIndex = NULL;
        m->siteScalerScratchIndex = -1;

        m->cijks = NULL;
        m->nCijkParts = 0;
        m->cijkIndex = NULL;
        m->cijkScratchIndex = -1;
        }

    /* set state of all chains to zero */
    for (chn=0; chn<numGlobalChains; chn++)
        state[chn] = 0;

    /* fill in modelSettings info with some basic model characteristics */
    for (i=0; i<numCurrentDivisions; i++)
        {
        mp = &modelParams[i];
        m = &modelSettings[i];
        
        if (!strcmp(mp->nucModel,"Protein") && (mp->dataType == DNA || mp->dataType == RNA))
            m->dataType = PROTEIN;
        else
            m->dataType = mp->dataType;

        /* nuc model structure */
        if (!strcmp(mp->nucModel, "4by4"))
            m->nucModelId = NUCMODEL_4BY4;
        else if (!strcmp(mp->nucModel, "Doublet"))
            m->nucModelId = NUCMODEL_DOUBLET;
        else if (!strcmp(mp->nucModel, "Protein"))
            m->nucModelId = NUCMODEL_AA;
        else /* if (!strcmp(mp->nucModelId, "Codon")) */
            m->nucModelId = NUCMODEL_CODON;
            
        /* model nst */
        if (!strcmp(mp->nst, "1"))
            m->nst = 1;
        else if (!strcmp(mp->nst, "2"))
            m->nst = 2;
        else if (!strcmp(mp->nst, "6"))
            m->nst = 6;
        else
            m->nst = NST_MIXED;
            
        /* We set the aa model here. We have two options. First, the model
           could be fixed, in which case mp->aaModel has been set. We then
           go ahead and also set the model settings. Second, the model
           could be mixed. In this case, the amino acid matrix is considered
           a parameter, and we will deal with it below. It doesn't hurt
           to set it here anyway (it will be overwritten later). */
        if (!strcmp(mp->aaModelPr, "Fixed"))
            {
            if (!strcmp(mp->aaModel, "Poisson"))
                m->aaModelId = AAMODEL_POISSON;
            else if (!strcmp(mp->aaModel, "Equalin"))
                m->aaModelId = AAMODEL_EQ;
            else if (!strcmp(mp->aaModel, "Jones"))
                m->aaModelId = AAMODEL_JONES;
            else if (!strcmp(mp->aaModel, "Dayhoff"))
                m->aaModelId = AAMODEL_DAY;
            else if (!strcmp(mp->aaModel, "Mtrev"))
                m->aaModelId = AAMODEL_MTREV;
            else if (!strcmp(mp->aaModel, "Mtmam"))
                m->aaModelId = AAMODEL_MTMAM;
            else if (!strcmp(mp->aaModel, "Wag"))
                m->aaModelId = AAMODEL_WAG;
            else if (!strcmp(mp->aaModel, "Rtrev"))
                m->aaModelId = AAMODEL_RTREV;
            else if (!strcmp(mp->aaModel, "Cprev"))
                m->aaModelId = AAMODEL_CPREV;
            else if (!strcmp(mp->aaModel, "Vt"))
                m->aaModelId = AAMODEL_VT;
            else if (!strcmp(mp->aaModel, "Blosum"))
                m->aaModelId = AAMODEL_BLOSUM;
            else if (!strcmp(mp->aaModel, "LG"))
                m->aaModelId = AAMODEL_LG;
            else if (!strcmp(mp->aaModel, "Gtr"))
                m->aaModelId = AAMODEL_GTR;
            else
                {
                MrBayesPrint ("%s   Uncertain amino acid model\n", spacer);
                return (ERROR);
                }
            }
        else
            m->aaModelId = -1;
            
        /* parsimony model? */
        if (!strcmp(mp->parsModel, "Yes"))
            m->parsModelId = YES;
        else
            m->parsModelId = NO;

        /* number of gamma categories */
        if (activeParams[P_SHAPE][i] > 0)
            m->numGammaCats = mp->numGammaCats;
        else
            m->numGammaCats = 1;

        /* number of beta categories */
        if (mp->dataType == STANDARD && !(AreDoublesEqual(mp->symBetaFix, -1.0, 0.00001) == YES && !strcmp(mp->symPiPr,"Fixed")))
            m->numBetaCats = mp->numBetaCats;
        else
            m->numBetaCats = 1;

        /* number of omega categories */
        if ((mp->dataType == DNA || mp->dataType == RNA) && (!strcmp(mp->omegaVar, "Ny98") || !strcmp(mp->omegaVar, "M3")) && !strcmp(mp->nucModel, "Codon"))
            {
            m->numOmegaCats = 3;
            m->numGammaCats = 1; /* if we are here, then we cannot have gamma or beta variation */
            m->numBetaCats = 1;
            }
        else if ((mp->dataType == DNA || mp->dataType == RNA) && !strcmp(mp->omegaVar, "M10") && !strcmp(mp->nucModel, "Codon"))
            {
            m->numOmegaCats = mp->numM10BetaCats + mp->numM10GammaCats;
            m->numGammaCats = 1; /* if we are here, then we cannot have gamma or beta variation */
            m->numBetaCats = 1;
            }
        else
            m->numOmegaCats = 1;

        /* number of transition matrices depends on numGammaCats, numBetaCats, and numOmegaCats */
        m->numTiCats = m->numGammaCats * m->numBetaCats * m->numOmegaCats;

        /* TODO: check that numStates and numModelStates are set
            appropriately for codon and doublet models */

        /* number of observable states */
        if (m->dataType == STANDARD)
            m->numStates = 0;   /* zero, meaining variable */
        else if (!strcmp(mp->nucModel,"Protein") && (mp->dataType == DNA || mp->dataType == RNA))
            m->numStates = 20;
        else
            m->numStates = mp->nStates;
        
        /* number of model states including hidden ones */
        if ((mp->dataType == DNA || mp->dataType == RNA) && !strcmp (mp->covarionModel, "Yes") && !strcmp(mp->nucModel, "4by4"))
            m->numModelStates = mp->nStates * 2;
        else if (m->dataType == PROTEIN && !strcmp (mp->covarionModel, "Yes"))
            m->numModelStates = mp->nStates * 2;
        else if ((mp->dataType == DNA || mp->dataType == RNA) && !strcmp(mp->nucModel,"Protein") && !strcmp (mp->covarionModel, "Yes"))
            m->numModelStates = 20 * 2;
        else if (mp->dataType == CONTINUOUS)
            m->numModelStates = 0;
        else if (mp->dataType == STANDARD)
            {
            /* use max possible for now; we don't know what chars will be included */
            m->numModelStates = 10;
            }
        else
            m->numModelStates = m->numStates;
            
        /* Fill in some information for calculating cijk. We will use m->cijkLength to 
           figure out if we need to diagonalize Q to calculate transition probabilities.
           If cijkLength = 0, then we won't bother. We use cijkLength later in this function. */
        m->cijkLength = 0;
        m->nCijkParts = 1;
        if (m->dataType == PROTEIN)
            {
            ts = m->numModelStates;
            m->cijkLength = (ts * ts * ts) + (2 * ts);
            if (!strcmp (mp->covarionModel, "Yes"))
                {
                m->cijkLength *= m->numGammaCats;
                m->nCijkParts = m->numGammaCats;
                }
            }
        else if (m->dataType == STANDARD)
            {
            /* set to 0 for now, update in ProcessStdChars */
            m->nCijkParts = 0;
            }
        else if (m->dataType == DNA || m->dataType == RNA)
            {
            if (m->nucModelId == NUCMODEL_4BY4)
                {
                if (!strcmp (mp->covarionModel, "No") && m->nst != 6 && m->nst != 203)
                    m->cijkLength = 0;
                else
                    {
                    ts = m->numModelStates;
                    m->cijkLength = (ts * ts * ts) + (2 * ts);
                    }
                if (!strcmp (mp->covarionModel, "Yes"))
                    {
                    m->cijkLength *= m->numGammaCats;
                    m->nCijkParts = m->numGammaCats;
                    }
                }
            else if (m->nucModelId == NUCMODEL_DOUBLET)
                {
                ts = m->numModelStates;
                m->cijkLength = (ts * ts * ts) + (2 * ts);
                }
            else if (m->nucModelId == NUCMODEL_CODON)
                {
                ts = m->numModelStates;
                m->cijkLength = (ts * ts * ts) + (2 * ts);
                m->cijkLength *= m->numOmegaCats;
                m->nCijkParts = m->numOmegaCats;
                }
            else
                {
                MrBayesPrint ("%s   BUG: Inconsistent model. Please report this as a bug.\n");
                return ERROR;
                }
            }

        /* check if we should calculate ancestral states */
        if (!strcmp(mp->inferAncStates,"Yes"))
            {
            if (m->dataType == PROTEIN && !strcmp(mp->covarionModel, "No"))
                m->printAncStates = YES;
            else if (m->dataType == DNA || m->dataType == RNA)
                {
                if (!strcmp(mp->nucModel,"4by4") && !strcmp(mp->covarionModel, "No"))
                    m->printAncStates = YES;
                if (!strcmp(mp->nucModel,"Doublet"))
                    m->printAncStates = YES;
                if (!strcmp(mp->nucModel,"Codon") && !strcmp(mp->omegaVar,"Equal"))
                    m->printAncStates = YES;
                }
            else if (m->dataType == STANDARD || m->dataType == RESTRICTION)
                m->printAncStates = YES;
            if (m->printAncStates == YES)
                inferAncStates = YES;
            else
                MrBayesPrint ("%s   Print out of ancestral states is not applicable for devision %d.\n",spacer,i);
            }

        /* check if we should calculate site rates */
        if (!strcmp(mp->inferSiteRates,"Yes"))
            {
            if (m->numGammaCats > 1)
                {
                m->printSiteRates = YES;
                inferSiteRates = YES;
                }
            }

        /* check if we should calculate positive selection */
        if (!strcmp(mp->inferPosSel, "Yes"))
            {
            if (m->numOmegaCats > 1)
                {
                m->printPosSel = YES;
                inferPosSel = YES;
                }
            }

        /* check if we should calculate site omegas */
        if (!strcmp(mp->inferSiteOmegas, "Yes"))
            {
            if (m->numOmegaCats > 1)
                {
                m->printSiteOmegas = YES;
                inferSiteOmegas = YES;
                }
            }
        /* check if we should use gibbs sampling of gamma (don't use it with pinvar or invgamma) */
        if (!strcmp(mp->useGibbs,"Yes") && (m->numGammaCats > 1))
            {
            if (m->dataType == DNA || m->dataType == RNA || m->dataType == PROTEIN)
                {
                if (activeParams[P_CORREL][i] <= 0 && m->printSiteRates == NO && activeParams[P_PINVAR][i] <= 0)
                    {
                    m->gibbsGamma = YES;
                    m->gibbsFreq = mp->gibbsFreq;
                    }
                }
            }
        }

    return (NO_ERROR);  
}


/*-----------------------------------------------------------------
|
|   SetModelParams: Set up parameter structs for all model
|       parameters, including trees
|
|----------------------------------------------------------------*/
int SetModelParams (void)
{
    int             c, i, j, k, n, n1, n2, *isPartTouched, numRelParts, nRelParts, areAllPartsParsimony,
                    nClockBrlens, nRelaxedBrlens, nCalibratedBrlens;
    char            tempCodon[15], tempMult[15], *tempStr,temp[30];
    char static     *partString=NULL; /* mad static to avoid posible memory leak on return ERROR if it would be introduced later */
    Param           *p;
    ModelParams     *mp;
    ModelInfo       *m;
    int             tempStrSize = 300;

    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
    isPartTouched = (int *) SafeMalloc ((size_t) (numCurrentDivisions * sizeof (int)));
    if (!tempStr || !isPartTouched)
        {
        MrBayesPrint ("%s   Problem allocating tempString (%d) or isPartTouched (%d)\n", spacer,
            tempStrSize * sizeof(char), numCurrentDivisions * sizeof(int));
        return (ERROR);
        }

#   if defined DEBUG_SETCHAINPARAMS
    /* only for debugging */
    MrBFlt      lnPriorRatio = 0.0, lnProposalRatio = 0.0;
#   endif

    /* allocate space for parameters */
    if (memAllocs[ALLOC_PARAMS] == YES)
        {
        for (i=0; i<numParams; i++)
            {
            SafeFree ((void **)&params[i].name);
            if (params[i].paramHeader)
                {
                free (params[i].paramHeader);
                params[i].paramHeader = NULL;
                }
            }
        free (params);
        free (relevantParts);
        params = NULL;
        relevantParts = NULL;
        memAllocs[ALLOC_PARAMS] = NO;
        }

    /* wipe all chain parameter information */
    numParams = 0;
    numTrees = 0;
    chainHasAdgamma = NO;

    /* figure out number of parameters */
    /* this relies on activeParams[j][i] being set to 1, 2, ..., numParams */
    /* which is taken care of in SetUpLinkTable () */
    nRelParts = 0;
    for (j=0; j<NUM_LINKED; j++)
        {
        for (i=0; i<numCurrentDivisions; i++)
            {
            if (activeParams[j][i] > numParams)
                numParams = activeParams[j][i];
            if (activeParams[j][i] > 0)
                nRelParts++;
            }
        }

    params = (Param *) SafeMalloc (numParams * sizeof(Param));
    relevantParts = (int *) SafeMalloc (nRelParts * sizeof(int));
    if (!params || !relevantParts)
        {
        MrBayesPrint ("%s   Problem allocating params and relevantParts\n", spacer);
        if (params)
            free (params);
        if (relevantParts)
            free (relevantParts);
        free (tempStr);
        return ERROR;
        }
    else
        memAllocs[ALLOC_PARAMS] = YES;

    /* fill in info on each parameter */
    nRelParts = 0;  /* now cumulative number of relevant partitions */
    for (k=0; k<numParams; k++)
        {
        p = &params[k];

        /* find affected partitions */
        numRelParts = 0;
        for (j=0; j<NUM_LINKED; j++)
            {
            for (i=0; i<numCurrentDivisions; i++)
                {
                if (activeParams[j][i] == k + 1)
                    {
                    numRelParts++;
                    isPartTouched[i] = YES;
                    }
                else
                    isPartTouched[i] = NO;
                }
            if (numRelParts > 0)
                break;
            }

        /* find pointer to modelParams and modelSettings of first relevant partition */
        /* this will be handy later on */
        for (i=0; i<numCurrentDivisions; i++)
            if (isPartTouched[i] == YES)
                break;
        mp = &modelParams[i];
        m  = &modelSettings[i];
        
        /* Set default min and max */
        p->min = p->max = NEG_INFINITY;

        /* Parameter nValues and nSubValues, which are needed for memory allocation
           are calculated for each case in the code below. nSympi, however, is
           only used for one special type of parameter and it therefore makes
           sense to initialize it to 0 here. The same applies to hasBinaryStd
           and nIntValues. To be safe, we set all to 0 here. */
        p->nValues = 0;
        p->nSubValues = 0;
        p->nIntValues = 0;
        p->nSympi = 0;
        p->hasBinaryStd = NO;
        
        /* should this parameter be printed to a file? */
        p->printParam = NO;

        /* set print subparams to 0 */
        p->nPrintSubParams = 0;
        
        /* check constraints for tree parameter ? */
        p->checkConstraints = NO;

        /* set index number of parameter */
        p->index = k;
        
        /* set prior function to NULL */
        p->LnPriorRatio = NULL;

        /* set prior paramters to NULL */
        p->priorParams = NULL;

        /* set affectsLikelihood to NO */
        p->affectsLikelihood = NO;

        /* set cpp event pointers to NULL */
        p->nEvents = NULL;
        p->position = NULL;
        p->rateMult = NULL;

        /* set header and name to NULL */
        p->paramHeader = NULL;
        p->name = NULL;

        /* set up relevant partitions */
        p->nRelParts = numRelParts;
        p->relParts = relevantParts + nRelParts;
        nRelParts += numRelParts;
        for (i=n=0; i<numCurrentDivisions; i++)
            if (isPartTouched[i] == YES)
                p->relParts[n++] = i;

        /* get partition descriptor */
        SafeStrcat(&partString,"");
        FillRelPartsString (p, &partString);
            
        /* set up information for parameter */
        if (j == P_TRATIO)
            {
            /* Set up tratio ****************************************************************************************/
            p->paramType = P_TRATIO;
            p->nValues = 1;         /* we store only the ratio */
            p->nSubValues = 0;
            p->min = 0.0;
            p->max = POS_INFINITY;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].tRatio = p;
    
            p->paramTypeName = "Transition and transversion rates";
            SafeStrcat(&p->name, "Tratio");
            SafeStrcat(&p->name, partString);

            /* find the parameter x prior type */
            if (!strcmp(mp->tRatioPr,"Beta"))
                {
                p->paramId = TRATIO_DIR;
                }
            else
                p->paramId = TRATIO_FIX;
                
            if (p->paramId != TRATIO_FIX)
                p->printParam = YES;
            if (!strcmp(mp->tratioFormat,"Ratio"))
                {
                /* report ti/tv ratio */
                SafeStrcat (&p->paramHeader,"kappa");
                SafeStrcat (&p->paramHeader, partString);
                }
            else
                {
                /* report prop. of ratesum (Dirichlet) */
                SafeStrcat (&p->paramHeader,"ti");
                SafeStrcat (&p->paramHeader, partString);
                SafeStrcat (&p->paramHeader, "\ttv");
                SafeStrcat (&p->paramHeader, partString);
                }
            }
        else if (j == P_REVMAT)
            {
            /* Set up revMat ****************************************************************************************/
            p->paramType = P_REVMAT;
            if (m->dataType == PROTEIN)
                p->nValues = 190;
            else
                p->nValues = 6;
            p->nSubValues = 0;
            if (!strcmp(mp->nst, "Mixed"))
                p->nIntValues = 6;
            else
                p->nIntValues = 0;
            p->min = 0.0;
            p->max = 1.0;       /* adjust later for REVMAT_MIX, see a few lines below */
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].revMat = p;

            p->paramTypeName = "Rates of reversible rate matrix";
            SafeStrcat(&p->name, "Revmat");
            SafeStrcat(&p->name, partString);

            /* find the parameter x prior type */
            if (m->dataType == PROTEIN)
                {
                if (!strcmp(mp->aaRevMatPr,"Dirichlet"))
                    p->paramId = REVMAT_DIR;
                else
                    p->paramId = REVMAT_FIX;
                if (p->paramId != REVMAT_FIX)
                    p->printParam = YES;

                for (n1=0; n1<20; n1++)
                    {
                    for (n2=n1+1; n2<20; n2++)
                        {
                        if (n1==0 && n2==1)
                            {
                            sprintf (temp, "r(%c<->%c)", StateCode_AA(n1), StateCode_AA(n2));
                            SafeStrcat (&p->paramHeader, temp);
                            SafeStrcat (&p->paramHeader, partString);
                            }
                        else
                            {
                            sprintf (temp, "\tr(%c<->%c)", StateCode_AA(n1), StateCode_AA(n2));
                            SafeStrcat (&p->paramHeader, temp);
                            SafeStrcat (&p->paramHeader, partString);
                            }
                        }
                    }
                }
            else
                {
                if (!strcmp(mp->nst, "Mixed"))
                    {
                    p->paramId = REVMAT_MIX;
                    p->max = 1E6;   /* some large value */
                    }
                else if (!strcmp(mp->revMatPr,"Dirichlet"))
                    p->paramId = REVMAT_DIR;
                else
                    p->paramId = REVMAT_FIX;
                if (p->paramId != REVMAT_FIX)
                    p->printParam = YES;

                for (n1=0; n1<4; n1++)
                    {
                    for (n2=n1+1; n2<4; n2++)
                        {
                        if (n1==0 && n2==1)
                            {
                            sprintf (temp, "r(%c<->%c)", StateCode_NUC4(n1), StateCode_NUC4(n2));
                            SafeStrcat (&p->paramHeader, temp);
                            SafeStrcat (&p->paramHeader, partString);
                            }
                        else
                            {
                            sprintf (temp, "\tr(%c<->%c)", StateCode_NUC4(n1), StateCode_NUC4(n2));
                            SafeStrcat (&p->paramHeader, temp);
                            SafeStrcat (&p->paramHeader, partString);
                            }
                        }
                    }
                if (p->paramId == REVMAT_MIX)
                    {
                    sprintf (temp, "\tgtrsubmodel");
                    SafeStrcat (&p->paramHeader, temp);
                    SafeStrcat (&p->paramHeader, partString);
                    sprintf (temp, "\tk_revmat");
                    SafeStrcat (&p->paramHeader, temp);
                    SafeStrcat (&p->paramHeader, partString);
                    }
                }
            }
        else if (j == P_OMEGA)
            {
            /* Set up omega *****************************************************************************************/
            p->paramType = P_OMEGA;
            p->min = 0.0;
            p->max = POS_INFINITY;
            if (!strcmp(mp->omegaVar, "M3"))
                {
                p->nValues = 3;         /* omega values */
                p->nSubValues = 6;      /* category frequencies plus cache */
                for (i=0; i<numCurrentDivisions; i++)
                    if (isPartTouched[i] == YES)
                        modelSettings[i].omega = p;
            
                /* find the parameter x prior type */
                if (!strcmp(mp->m3omegapr, "Exponential")      && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_EF;
                else if (!strcmp(mp->m3omegapr, "Exponential") && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_ED;
                else if (!strcmp(mp->m3omegapr, "Fixed")       && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_FF;
                else if (!strcmp(mp->m3omegapr, "Fixed")       && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_FD;

                if (p->paramId != OMEGA_FF)
                    p->printParam = YES;

                SafeStrcat (&p->paramHeader, "omega(1)");
                SafeStrcat (&p->paramHeader, partString);
                SafeStrcat (&p->paramHeader, "\tomega(2)");
                SafeStrcat (&p->paramHeader, partString);
                SafeStrcat (&p->paramHeader, "\tomega(3)");
                SafeStrcat (&p->paramHeader, partString);
                    
                SafeStrcat (&p->paramHeader, "\tpi(1)");
                SafeStrcat (&p->paramHeader, partString);
                SafeStrcat (&p->paramHeader, "\tpi(2)");
                SafeStrcat (&p->paramHeader, partString);
                SafeStrcat (&p->paramHeader, "\tpi(3)");
                SafeStrcat (&p->paramHeader, partString);
                }
            else if (!strcmp(mp->omegaVar, "M10"))
                {
                p->nValues = mp->numM10BetaCats + mp->numM10GammaCats;
                p->nSubValues = mp->numM10BetaCats + mp->numM10GammaCats + 8;
                for (i=0; i<numCurrentDivisions; i++)
                    if (isPartTouched[i] == YES)
                        modelSettings[i].omega = p;

                /* find the parameter x prior type */
                if      (!strcmp(mp->m10betapr, "Uniform")     && !strcmp(mp->m10gammapr, "Uniform")     && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_10UUB;
                else if (!strcmp(mp->m10betapr, "Uniform")     && !strcmp(mp->m10gammapr, "Uniform")     && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_10UUF;
                else if (!strcmp(mp->m10betapr, "Uniform")     && !strcmp(mp->m10gammapr, "Exponential") && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_10UEB;
                else if (!strcmp(mp->m10betapr, "Uniform")     && !strcmp(mp->m10gammapr, "Exponential") && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_10UEF;
                else if (!strcmp(mp->m10betapr, "Uniform")     && !strcmp(mp->m10gammapr, "Fixed")       && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_10UFB;
                else if (!strcmp(mp->m10betapr, "Uniform")     && !strcmp(mp->m10gammapr, "Fixed")       && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_10UFF;
                else if (!strcmp(mp->m10betapr, "Exponential") && !strcmp(mp->m10gammapr, "Uniform")     && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_10EUB;
                else if (!strcmp(mp->m10betapr, "Exponential") && !strcmp(mp->m10gammapr, "Uniform")     && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_10EUF;
                else if (!strcmp(mp->m10betapr, "Exponential") && !strcmp(mp->m10gammapr, "Exponential") && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_10EEB;
                else if (!strcmp(mp->m10betapr, "Exponential") && !strcmp(mp->m10gammapr, "Exponential") && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_10EEF;
                else if (!strcmp(mp->m10betapr, "Exponential") && !strcmp(mp->m10gammapr, "Fixed")       && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_10EFB;
                else if (!strcmp(mp->m10betapr, "Exponential") && !strcmp(mp->m10gammapr, "Fixed")       && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_10EFF;
                else if (!strcmp(mp->m10betapr, "Fixed")       && !strcmp(mp->m10gammapr, "Uniform")     && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_10FUB;
                else if (!strcmp(mp->m10betapr, "Fixed")       && !strcmp(mp->m10gammapr, "Uniform")     && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_10FUF;
                else if (!strcmp(mp->m10betapr, "Fixed")       && !strcmp(mp->m10gammapr, "Exponential") && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_10FEB;
                else if (!strcmp(mp->m10betapr, "Fixed")       && !strcmp(mp->m10gammapr, "Exponential") && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_10FEF;
                else if (!strcmp(mp->m10betapr, "Fixed")       && !strcmp(mp->m10gammapr, "Fixed")       && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_10FFB;
                else if (!strcmp(mp->m10betapr, "Fixed")       && !strcmp(mp->m10gammapr, "Fixed")       && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_10FFF;

                if (p->paramId != OMEGA_10FFF)
                    p->printParam = YES;
                for (i=0; i<p->nValues; i++)
                    {
                    if (i==0)
                        sprintf (temp, "omega(%d)", i+1);
                    else
                        sprintf (temp, "\tomega(%d)", i+1);
                    SafeStrcat (&p->paramHeader, temp);
                    SafeStrcat (&p->paramHeader, partString);
                    }
                SafeStrcat (&p->paramHeader, "\tbeta(alpha)");
                SafeStrcat (&p->paramHeader, partString);
                SafeStrcat (&p->paramHeader, "\tbeta(beta)");
                SafeStrcat (&p->paramHeader, partString);
                SafeStrcat (&p->paramHeader, "\tgamma(alpha)");
                SafeStrcat (&p->paramHeader, partString);
                SafeStrcat (&p->paramHeader, "\tgamma(beta)");
                SafeStrcat (&p->paramHeader, partString);
                SafeStrcat (&p->paramHeader, "\tpi(1)");
                SafeStrcat (&p->paramHeader, partString);
                SafeStrcat (&p->paramHeader, "\tpi(2)");
                SafeStrcat (&p->paramHeader, partString);
                }
            else if (!strcmp(mp->omegaVar, "Ny98"))
                {
                p->nValues = 3;     /* omega values */
                p->nSubValues = 6;  /* omega category frequencies plus cache */
                for (i=0; i<numCurrentDivisions; i++)
                    if (isPartTouched[i] == YES)
                        modelSettings[i].omega = p;
            
                /* find the parameter x prior type */
                if      (!strcmp(mp->ny98omega1pr, "Beta")  && !strcmp(mp->ny98omega3pr, "Uniform")     && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_BUD;
                else if (!strcmp(mp->ny98omega1pr, "Beta")  && !strcmp(mp->ny98omega3pr, "Uniform")     && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_BUF;
                else if (!strcmp(mp->ny98omega1pr, "Beta")  && !strcmp(mp->ny98omega3pr, "Exponential") && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_BED;
                else if (!strcmp(mp->ny98omega1pr, "Beta")  && !strcmp(mp->ny98omega3pr, "Exponential") && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_BEF;
                else if (!strcmp(mp->ny98omega1pr, "Beta")  && !strcmp(mp->ny98omega3pr, "Fixed")       && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_BFD;
                else if (!strcmp(mp->ny98omega1pr, "Beta")  && !strcmp(mp->ny98omega3pr, "Fixed")       && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_BFF;
                else if (!strcmp(mp->ny98omega1pr, "Fixed") && !strcmp(mp->ny98omega3pr, "Uniform")     && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_FUD;
                else if (!strcmp(mp->ny98omega1pr, "Fixed") && !strcmp(mp->ny98omega3pr, "Uniform")     && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_FUF;
                else if (!strcmp(mp->ny98omega1pr, "Fixed") && !strcmp(mp->ny98omega3pr, "Exponential") && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_FED;
                else if (!strcmp(mp->ny98omega1pr, "Fixed") && !strcmp(mp->ny98omega3pr, "Exponential") && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_FEF;
                else if (!strcmp(mp->ny98omega1pr, "Fixed") && !strcmp(mp->ny98omega3pr, "Fixed")       && !strcmp(mp->codonCatFreqPr, "Dirichlet"))
                    p->paramId = OMEGA_FFD;
                else if (!strcmp(mp->ny98omega1pr, "Fixed") && !strcmp(mp->ny98omega3pr, "Fixed")       && !strcmp(mp->codonCatFreqPr, "Fixed"))
                    p->paramId = OMEGA_FFF;
                
                if (p->paramId != OMEGA_FFF)
                    p->printParam = YES;
                SafeStrcat (&p->paramHeader, "omega(-)");
                SafeStrcat (&p->paramHeader, partString);
                SafeStrcat (&p->paramHeader, "\tomega(N)");
                SafeStrcat (&p->paramHeader, partString);
                SafeStrcat (&p->paramHeader, "\tomega(+)");
                SafeStrcat (&p->paramHeader, partString);
                    
                SafeStrcat (&p->paramHeader, "\tpi(-)");
                SafeStrcat (&p->paramHeader, partString);
                SafeStrcat (&p->paramHeader, "\tpi(N)");
                SafeStrcat (&p->paramHeader, partString);
                SafeStrcat (&p->paramHeader, "\tpi(+)");
                SafeStrcat (&p->paramHeader, partString);
                }
            else
                {
                p->nValues = 1;
                p->nSubValues = 0;
                for (i=0; i<numCurrentDivisions; i++)
                    if (isPartTouched[i] == YES)
                        modelSettings[i].omega = p;

                /* find the parameter x prior type */
                if (!strcmp(mp->omegaPr,"Dirichlet"))
                    p->paramId = OMEGA_DIR;
                else
                    p->paramId = OMEGA_FIX;

                if (p->paramId != OMEGA_FIX)
                    p->printParam = YES;
                SafeStrcat (&p->paramHeader, "omega");
                SafeStrcat (&p->paramHeader, partString);
                }
            p->paramTypeName = "Positive selection (omega) model";
            SafeStrcat(&p->name, "Omega");
            SafeStrcat(&p->name, partString);           
            }
        else if (j == P_PI)
            {
            /* Set up state frequencies *****************************************************************************/
            p->paramType = P_PI;
            p->min = 0.0;
            p->max = 1.0;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].stateFreq = p;

            if (mp->dataType == STANDARD)
                {
                p->paramTypeName = "Symmetric diricihlet/beta distribution alpha_i parameter";
                SafeStrcat(&p->name, "Alpha_symdir");
                /* boundaries for alpha_i */
                p->min = ETA;
                p->max = POS_INFINITY;
                }
            else
                {
                p->paramTypeName = "Stationary state frequencies";
                SafeStrcat(&p->name, "Pi");
                }
            SafeStrcat(&p->name, partString);

            /* find the parameter x prior type */
            /* and the number of values and subvalues needed */
            if (mp->dataType == STANDARD)
                {
                /* find number of model states */
                m->numModelStates = 2;
                for (c=0; c<numChar; c++)
                    {
                    for (i=0; i<p->nRelParts; i++)
                        {
                        if (partitionId[c][partitionNum] == p->relParts[i] + 1 && charInfo[c].numStates > m->numModelStates)
                            m->numModelStates = charInfo[c].numStates;
                        }
                    }
                for (i=0; i<p->nRelParts; i++)
                    modelSettings[p->relParts[i]].numModelStates = m->numModelStates;

                /* symmetric hyperprior with only one variable (0 if equal) */
                p->nValues = 1;     /* set to 0 below for the SYMPI_EQUAL model */
                if (!strcmp(mp->symPiPr,"Uniform"))
                    {
                    if (m->numModelStates > 2) 
                        p->paramId = SYMPI_UNI_MS;
                    else
                        p->paramId = SYMPI_UNI;
                    }
                else if (!strcmp(mp->symPiPr,"Exponential"))
                    {
                    if (m->numModelStates > 2)
                        p->paramId = SYMPI_EXP_MS;
                    else
                        p->paramId = SYMPI_EXP;
                    }
                else if (!strcmp(mp->symPiPr,"Fixed"))
                    {
                    if (AreDoublesEqual(mp->symBetaFix, -1.0, 0.00001) == YES)
                        {
                        p->paramId = SYMPI_EQUAL;
                        p->nValues = 0;
                        }
                    else
                        {
                        if (m->numModelStates > 2) 
                            p->paramId = SYMPI_FIX_MS;
                        else
                            p->paramId = SYMPI_FIX;
                        }
                    }
                p->nSubValues = 0;  /* store state frequencies in p->stdStateFreqs */
                if (p->paramId == SYMPI_EXP || p->paramId == SYMPI_EXP_MS || p->paramId == SYMPI_UNI || p->paramId == SYMPI_UNI_MS)
                    p->printParam = YES;
                SafeStrcat (&p->paramHeader, "alpha_symdir");
                SafeStrcat (&p->paramHeader, partString);
                /* further processing done in ProcessStdChars */
                }
            else
                {
                /* deal with all models except standard */
                /* no hyperprior or fixed to one value, set default to 0  */
                p->nValues = 0;
                /* one subvalue for each state */
                p->nSubValues = mp->nStates;    /* mp->nStates is set to 20 if DNA || RNA && nucmodel==PROTEIN */
                if (!strcmp(mp->stateFreqPr, "Dirichlet"))
                    {
                    p->paramId = PI_DIR;
                    p->nValues = mp->nStates;
                    }
                else if (!strcmp(mp->stateFreqPr, "Fixed") && !strcmp(mp->stateFreqsFixType,"User"))
                    p->paramId = PI_USER;
                else if (!strcmp(mp->stateFreqPr, "Fixed") && !strcmp(mp->stateFreqsFixType,"Empirical"))
                    p->paramId = PI_EMPIRICAL;
                else if (!strcmp(mp->stateFreqPr, "Fixed") && !strcmp(mp->stateFreqsFixType,"Equal"))
                    {
                    p->paramId = PI_EQUAL;
                    }
                    
                if (m->dataType == PROTEIN)
                    {
                    if (!strcmp(mp->aaModelPr, "Fixed"))
                        {
                        if (!strcmp(mp->aaModel, "Poisson"))
                            p->paramId = PI_EQUAL;
                        else if (!strcmp(mp->aaModel, "Equalin") || !strcmp(mp->aaModel, "Gtr"))
                            {
                            /* p->paramId stays to what it was set to above */
                            }
                        else
                            p->paramId = PI_FIXED;
                        }
                    else
                        p->paramId = PI_FIXED;
                    }
                    
                if (p->paramId == PI_DIR)
                    p->printParam = YES;
                if (m->dataType == DNA || m->dataType == RNA)
                    {
                    if (!strcmp(mp->nucModel, "4by4"))
                        {
                        sprintf (temp, "pi(%c)", StateCode_NUC4(0));
                        SafeStrcat (&p->paramHeader,temp);
                        SafeStrcat (&p->paramHeader,partString);
                        for (n1=1; n1<4; n1++)
                            {
                            sprintf (temp, "\tpi(%c)", StateCode_NUC4(n1));
                            SafeStrcat (&p->paramHeader,temp);
                            SafeStrcat (&p->paramHeader,partString);
                            }
                        }
                    else if (!strcmp(mp->nucModel, "Doublet"))
                        {
                        State_DOUBLET(tempCodon,0);
                        sprintf (temp, "pi(%s)", tempCodon);
                        SafeStrcat (&p->paramHeader,temp);
                        SafeStrcat (&p->paramHeader,partString);
                        for (n1=1; n1<16; n1++)
                            {
                            State_DOUBLET(tempCodon,n1);
                            sprintf (temp, "\tpi(%s)", tempCodon);
                            SafeStrcat (&p->paramHeader,temp);
                            SafeStrcat (&p->paramHeader,partString);
                            }
                        }
                    else if (!strcmp(mp->nucModel, "Codon"))
                        {
                        for (c=0; c<p->nSubValues; c++)
                            {
                            if (mp->codonNucs[c][0] == 0)
                                strcpy (tempCodon, "pi(A");
                            else if (mp->codonNucs[c][0] == 1)
                                strcpy (tempCodon, "pi(C");
                            else if (mp->codonNucs[c][0] == 2)
                                strcpy (tempCodon, "pi(G");
                            else
                                strcpy (tempCodon, "pi(T");
                            if (mp->codonNucs[c][1] == 0)
                                strcat (tempCodon, "A");
                            else if (mp->codonNucs[c][1] == 1)
                                strcat (tempCodon, "C");
                            else if (mp->codonNucs[c][1] == 2)
                                strcat (tempCodon, "G");
                            else
                                strcat (tempCodon, "T");
                            if (mp->codonNucs[c][2] == 0)
                                strcat (tempCodon, "A)");
                            else if (mp->codonNucs[c][2] == 1)
                                strcat (tempCodon, "C)");
                            else if (mp->codonNucs[c][2] == 2)
                                strcat (tempCodon, "G)");
                            else
                                strcat (tempCodon, "T)");
                            if (c == 0)
                                {
                                SafeStrcat (&p->paramHeader, tempCodon);
                                SafeStrcat (&p->paramHeader, partString);
                                }
                            else
                                {
                                SafeStrcat (&p->paramHeader, "\t");
                                SafeStrcat (&p->paramHeader, tempCodon);
                                SafeStrcat (&p->paramHeader, partString);
                                }
                            }
                        }
                    }
                else if (m->dataType == PROTEIN)
                    {
                    if (FillRelPartsString (p, &partString) == YES)
                        {
                        SafeSprintf (&tempStr, &tempStrSize, "pi(Ala)%s\tpi(Arg)%s\tpi(Asn)%s\tpi(Asp)%s\tpi(Cys)%s\tpi(Gln)%s\tpi(Glu)%s\tpi(Gly)%s\tpi(His)%s\tpi(Ile)%s\tpi(Leu)%s\tpi(Lys)%s\tpi(Met)%s\tpi(Phe)%s\tpi(Pro)%s\tpi(Ser)%s\tpi(Thr)%s\tpi(Trp)%s\tpi(Tyr)%s\tpi(Val)%s",
                        partString, partString, partString, partString, partString, partString, partString, partString, partString, partString,
                        partString, partString, partString, partString, partString, partString, partString, partString, partString, partString);
                        SafeStrcat (&p->paramHeader, tempStr);
                        }
                    else
                        SafeStrcat (&p->paramHeader, "pi(Ala)\tpi(Arg)\tpi(Asn)\tpi(Asp)\tpi(Cys)\tpi(Gln)\tpi(Glu)\tpi(Gly)\tpi(His)\tpi(Ile)\tpi(Leu)\tpi(Lys)\tpi(Met)\tpi(Phe)\tpi(Pro)\tpi(Ser)\tpi(Thr)\tpi(Trp)\tpi(Tyr)\tpi(Val)");
                    }
                else if (mp->dataType == RESTRICTION)
                    {
                    if (FillRelPartsString (p, &partString) == YES)
                        {
                        SafeSprintf (&tempStr, &tempStrSize, "pi(0)%s\tpi(1)%s", partString, partString);
                        SafeStrcat (&p->paramHeader, tempStr);
                        }
                    else
                        SafeStrcat (&p->paramHeader, "pi(0)\tpi(1)");
                    }
                else
                    {
                    MrBayesPrint ("%s   Unknown data type in SetModelParams\n", spacer);
                    }
                }
            }
        else if (j == P_SHAPE)
            {
            /* Set up shape parameter of gamma/lnorm *****************************************************************/
            p->paramType = P_SHAPE;
            p->nValues = 1;
            p->nSubValues = mp->numGammaCats;
            p->min = 1E-5;
            p->max = 100;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].shape = p;
            if(!strcmp(mp->ratesModel, "LNorm"))
                {
                p->paramTypeName = "SD of scaled lognormal distribution of site rates";
                SafeStrcat(&p->name, "Sigma");
                SafeStrcat (&p->paramHeader, "sigma");
                }
            else
                {
                p->paramTypeName = "Shape of scaled gamma distribution of site rates";
                SafeStrcat(&p->name, "Alpha");
                SafeStrcat (&p->paramHeader, "alpha");
                }
            SafeStrcat(&p->name, partString);
            SafeStrcat (&p->paramHeader, partString);

            /* find the parameter x prior type */
            mp = &modelParams[p->relParts[0]];
            if (!strcmp(mp->shapePr,"Uniform"))
                p->paramId = SHAPE_UNI;
            else if (!strcmp(mp->shapePr,"Exponential"))
                p->paramId = SHAPE_EXP;
            else
                p->paramId = SHAPE_FIX;
                
            if (p->paramId != SHAPE_FIX)
                p->printParam = YES;
            }
        else if (j == P_PINVAR)
            {
            /* Set up proportion of invariable sites ****************************************************************/
            p->paramType = P_PINVAR;
            p->nValues = 1;
            p->nSubValues = 0;
            p->min = 0.0;
            p->max = 1.0;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].pInvar = p;

            p->paramTypeName = "Proportion of invariable sites";
            SafeStrcat(&p->name, "Pinvar");
            SafeStrcat(&p->name, partString);

            /* find the parameter x prior type */
            if (!strcmp(mp->pInvarPr,"Uniform"))
                p->paramId = PINVAR_UNI;
            else
                p->paramId = PINVAR_FIX;
                
            if (p->paramId != PINVAR_FIX)
                p->printParam = YES;
            SafeStrcat (&p->paramHeader, "pinvar");
            SafeStrcat (&p->paramHeader, partString);
            }
        else if (j == P_CORREL)
            {
            /* Set up correlation parameter of adgamma model ********************************************************/
            p->paramType = P_CORREL;
            p->nValues = 1;
            p->nSubValues = mp->numGammaCats * mp->numGammaCats;
            p->min = -1.0;
            p->max = 1.0;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].correlation = p;

            p->paramTypeName = "Autocorrelation of gamma distribution of site rates";
            SafeStrcat(&p->name, "Rho");
            SafeStrcat(&p->name, partString);
            chainHasAdgamma = YES;

            /* find the parameter x prior type */
            if (!strcmp(mp->adGammaCorPr,"Uniform"))
                p->paramId = CORREL_UNI;
            else
                p->paramId = CORREL_FIX;

            if (p->paramId != CORREL_FIX)
                p->printParam = YES;
            SafeStrcat (&p->paramHeader, "rho");
            SafeStrcat (&p->paramHeader, partString);
            }
        else if (j == P_SWITCH)
            {
            /* Set up switchRates for covarion model ****************************************************************/
            p->paramType = P_SWITCH;
            p->nValues = 2;
            p->nSubValues = mp->numGammaCats * mp->numGammaCats;
            p->min = 0.0;
            p->max = POS_INFINITY;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].switchRates = p;

            p->paramTypeName = "Switch rates of covarion model";
            SafeStrcat(&p->name, "s_cov");
            SafeStrcat(&p->name, partString);

            /* find the parameter x prior type */
            if (!strcmp(mp->covSwitchPr,"Uniform"))
                p->paramId = SWITCH_UNI;
            else if (!strcmp(mp->covSwitchPr,"Exponential"))
                p->paramId = SWITCH_EXP;
            else
                p->paramId = SWITCH_FIX;
                
            if (p->paramId != SWITCH_FIX)
                p->printParam = YES;

            SafeStrcat (&p->paramHeader, "s(off->on)");
            SafeStrcat (&p->paramHeader, partString);
            SafeStrcat (&p->paramHeader, "\ts(on->off)");
            SafeStrcat (&p->paramHeader, partString);
            }
        else if (j == P_RATEMULT)
            {
            /* Set up rateMult for partition specific rates ***********************************************************/
            p->paramType = P_RATEMULT;
            if (!strcmp(mp->ratePr,"Fixed"))
                {
                p->nValues = 1;
                p->nSubValues = 0;
                }
            else
                {
                p->nValues = p->nRelParts = numRelParts; /* keep scaled division rates in value                        */
                p->nSubValues = p->nValues * 2;          /* keep number of uncompressed chars for scaling in subValue  */
                }                                        /* also keep Dirichlet prior parameters here                  */
            p->min = POS_MIN;
            p->max = POS_INFINITY;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].rateMult = p;

            p->paramTypeName = "Partition-specific rate multiplier";
            SafeStrcat(&p->name, "Ratemultiplier");
            SafeStrcat(&p->name, partString);

            /* find the parameter x prior type */
            if (p->nSubValues == 0)
                p->paramId = RATEMULT_FIX;
            else
                p->paramId = RATEMULT_DIR;

            if (p->paramId != RATEMULT_FIX)
                p->printParam = YES;
            for (i=0; i<numCurrentDivisions; i++)
                {
                if (isPartTouched[i] == YES)
                    {
                    sprintf (tempMult, "m{%d}", i+1);
                    if (i == 0)
                        SafeStrcat (&p->paramHeader, tempMult);
                    else
                        {
                        SafeStrcat (&p->paramHeader, "\t");
                        SafeStrcat (&p->paramHeader, tempMult);
                        }
                    }
                }
            }
        else if (j == P_GENETREERATE)
            {
            /* Set up rateMult for gene specific rates ****************************************************************/
            p->paramType = P_GENETREERATE;
            p->nValues = p->nRelParts = numRelParts;    /* keep scaled division rates in value                        */
            p->nSubValues = p->nValues * 2;             /* keep number of uncompressed chars for scaling in subValue  */
                                                        /* also keep Dirichlet prior parameters here                  */
            p->min = POS_MIN;
            p->max = POS_INFINITY;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].geneTreeRateMult = p;

            p->paramTypeName = "Gene-specific rate multiplier";
            SafeStrcat(&p->name, "Generatemult");
            SafeStrcat(&p->name, partString);

            /* find the parameter x prior type */
            if (strcmp(mp->generatePr,"Fixed") == 0)
                p->paramId = GENETREERATEMULT_FIX;
            else
                p->paramId = GENETREERATEMULT_DIR;

            if (p->paramId == GENETREERATEMULT_FIX)
                p->printParam = NO;
            else
                p->printParam = YES;

            for (i=0; i<numCurrentDivisions; i++)
                {
                if (isPartTouched[i] == YES)
                    {
                    sprintf (tempMult, "g_m{%d}", i+1);
                    if (i == 0)
                        SafeStrcat (&p->paramHeader, tempMult);
                    else
                        {
                        SafeStrcat (&p->paramHeader, "\t");
                        SafeStrcat (&p->paramHeader, tempMult);
                        }
                    }
                }
            }
        else if (j == P_TOPOLOGY)
            {
            /* Set up topology **************************************************************************************/
            p->paramType = P_TOPOLOGY;
            p->nValues = 0;
            p->nSubValues = 0;
            p->min = NEG_INFINITY;  /* NA */
            p->max = NEG_INFINITY;  /* NA */
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].topology = p;

            p->paramTypeName = "Topology";
            SafeStrcat(&p->name, "Tau");
            SafeStrcat(&p->name, partString);
                    
            /* check that the model is not parsimony for all of the relevant partitions */
            areAllPartsParsimony = YES;
            for (i=0; i<p->nRelParts; i++)
                {
                if (modelSettings[p->relParts[i]].parsModelId == NO)
                    areAllPartsParsimony = NO;
                }

            /* check if topology is clock or nonclock */
            nClockBrlens = 0;
            nCalibratedBrlens = 0;
            nRelaxedBrlens = 0;
            if (areAllPartsParsimony == NO)
                {
                for (i=0; i<p->nRelParts; i++)
                    {
                    if (!strcmp(modelParams[p->relParts[i]].brlensPr, "Clock"))
                        {
                        nClockBrlens++;
                        if (strcmp(modelParams[p->relParts[i]].clockVarPr,"Strict") != 0)  /* not strict */
                            nRelaxedBrlens++;
                        if (!strcmp(modelParams[p->relParts[i]].nodeAgePr,"Calibrated"))
                            nCalibratedBrlens++;
                        }
                    }
                }
            
            /* now find the parameter x prior type */
            if (areAllPartsParsimony == YES)
                {
                if (!strcmp(mp->topologyPr, "Uniform"))
                    p->paramId = TOPOLOGY_PARSIMONY_UNIFORM;
                else if (!strcmp(mp->topologyPr,"Constraints"))
                    p->paramId = TOPOLOGY_PARSIMONY_CONSTRAINED;
                else
                    p->paramId = TOPOLOGY_PARSIMONY_FIXED;
                /* For this case, we also need to set the brlens ptr of the relevant partitions
                   so that it points to the topology parameter, since the rest of the
                   program will try to access the tree through this pointer. In FillTreeParams,
                   we will make sure that a pure parsimony topology parameter contains a pointer
                   to the relevant tree (like a brlens parameter would normally) */
                for (i=0; i<p->nRelParts; i++)
                    modelSettings[p->relParts[i]].brlens = p;
                }
            else
                {
                /* we assume for now that there is only one branch length; we will correct this
                   later in AllocateTreeParams if there are more than one set of branch lengths,
                   which is only possible for non-clock trees */
                if (!strcmp(mp->topologyPr, "Speciestree"))
                    p->paramId = TOPOLOGY_SPECIESTREE;
                else if (!strcmp(mp->topologyPr, "Uniform") && nClockBrlens == 0)
                    p->paramId = TOPOLOGY_NCL_UNIFORM_HOMO;
                else if (!strcmp(mp->topologyPr,"Constraints") && nClockBrlens == 0)
                    p->paramId = TOPOLOGY_NCL_CONSTRAINED_HOMO;
                else if (!strcmp(mp->topologyPr,"Fixed") && nClockBrlens == 0)
                    p->paramId = TOPOLOGY_NCL_FIXED_HOMO;
                /* all below have clock branch lengths */
                else if (!strcmp(mp->topologyPr, "Uniform") && nRelaxedBrlens == 0)
                    {
                    if (nCalibratedBrlens >= 1)
                        p->paramId = TOPOLOGY_CCL_UNIFORM;
                    else
                        p->paramId = TOPOLOGY_CL_UNIFORM;
                    }
                else if (!strcmp(mp->topologyPr,"Constraints") && nRelaxedBrlens == 0)
                    {
                    if (nCalibratedBrlens >= 1)
                        p->paramId = TOPOLOGY_CCL_CONSTRAINED;
                    else
                        p->paramId = TOPOLOGY_CL_CONSTRAINED;
                    }
                else if (!strcmp(mp->topologyPr,"Fixed") && nRelaxedBrlens == 0)
                    {
                    if (nCalibratedBrlens >= 1)
                        p->paramId = TOPOLOGY_CCL_FIXED;
                    else
                        p->paramId = TOPOLOGY_CL_FIXED;
                    }
                /* all below have relaxed clock branch lengths */
                else if (!strcmp(mp->topologyPr, "Uniform"))
                    {
                    if (nCalibratedBrlens >= 1)
                        p->paramId = TOPOLOGY_RCCL_UNIFORM;
                    else
                        p->paramId = TOPOLOGY_RCL_UNIFORM;
                    }
                else if (!strcmp(mp->topologyPr,"Constraints"))
                    {
                    if (nCalibratedBrlens >= 1)
                        p->paramId = TOPOLOGY_RCCL_CONSTRAINED;
                    else
                        p->paramId = TOPOLOGY_RCL_CONSTRAINED;
                    }
                else if (!strcmp(mp->topologyPr,"Fixed"))
                    {
                    if (nCalibratedBrlens >= 1)
                        p->paramId = TOPOLOGY_RCCL_FIXED;
                    else
                        p->paramId = TOPOLOGY_RCL_FIXED;
                    }
                }

            /* should we print the topology? */
            for (i=0; i<p->nRelParts; i++)
                if (strcmp(modelParams[p->relParts[i]].treeFormat,"Topology") != 0)
                    break;
            if (i == p->nRelParts)
                p->printParam = YES;
            else
                p->printParam = NO;
            /* but always print parsimony topology */
            if (areAllPartsParsimony == YES)
                p->printParam = YES;
            /* and never print fixed topologies */
            if (p->paramId == TOPOLOGY_RCL_FIXED ||
                p->paramId == TOPOLOGY_RCCL_FIXED ||
                p->paramId == TOPOLOGY_CL_FIXED ||
                p->paramId == TOPOLOGY_CCL_FIXED ||
                p->paramId == TOPOLOGY_NCL_FIXED ||
                p->paramId == TOPOLOGY_PARSIMONY_FIXED)
                p->printParam = NO;
            }
        else if (j == P_BRLENS)
            {
            /* Set up branch lengths ********************************************************************************/
            p->paramType = P_BRLENS;
            p->nValues = 0;
            p->nSubValues = 0;
            p->min = 0.0;
            p->max = POS_INFINITY;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].brlens = p;

            p->paramTypeName = "Branch lengths";
            SafeStrcat(&p->name, "V");
            SafeStrcat(&p->name, partString);

            /* find the parameter x prior type */
            if (modelSettings[p->relParts[0]].parsModelId == YES)
                p->paramId = BRLENS_PARSIMONY;
            else
                {
                if (!strcmp(mp->brlensPr, "Clock"))
                    {
                    if (!strcmp(mp->clockPr,"Uniform"))
                        p->paramId = BRLENS_CLOCK_UNI;
                    else if (!strcmp(mp->clockPr,"Coalescence"))
                        p->paramId = BRLENS_CLOCK_COAL;
                    else if (!strcmp(mp->clockPr,"Birthdeath"))
                        p->paramId = BRLENS_CLOCK_BD;
                    else if (!strcmp(mp->clockPr,"Speciestreecoalescence"))
                        p->paramId = BRLENS_CLOCK_SPCOAL;
                    else if (!strcmp(mp->clockPr,"Fossilization"))
                        p->paramId = BRLENS_CLOCK_FOSSIL;
                    else if (!strcmp(mp->clockPr,"Fixed"))
                        p->paramId = BRLENS_CLOCK_FIXED;
                    }
                else if (!strcmp(mp->brlensPr, "Unconstrained"))
                    {
                    if (!strcmp(mp->unconstrainedPr,"Uniform"))
                        p->paramId = BRLENS_UNI;
                    else if (!strcmp(mp->unconstrainedPr,"Exponential"))
                        p->paramId = BRLENS_EXP;
                    else if (!strcmp(mp->unconstrainedPr,"GammaDir"))
                        p->paramId = BRLENS_GamDir;
                    else if (!strcmp(mp->unconstrainedPr,"invGamDir"))
                        p->paramId = BRLENS_iGmDir;
                    else if (!strcmp(mp->unconstrainedPr,"twoExp"))
                        p->paramId = BRLENS_twoExp;
                    }
                else if (!strcmp(mp->brlensPr,"Fixed"))
                    {
                    p->paramId = BRLENS_FIXED;
                    }
                }

            /* should we print the branch lengths? */
            for (i=0; i<p->nRelParts; i++)
                if (strcmp(modelParams[p->relParts[i]].treeFormat,"Topology") != 0)
                    break;
            if (i < p->nRelParts)
                p->printParam = YES;
            else
                p->printParam = NO;
            }
        else if (j == P_SPECIESTREE)
            {
            /* Set up species tree **************************************************************************************/
            p->paramType = P_SPECIESTREE;
            p->nValues = 0;
            p->nSubValues = 0;
            p->min = NEG_INFINITY;  /* NA */
            p->max = NEG_INFINITY;  /* NA */
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].speciesTree = p;

            p->paramTypeName = "Species tree";
            SafeStrcat(&p->name, "Spt");
            SafeStrcat(&p->name, partString);
                    
            /* check that the model is not parsimony for all of the relevant partitions */
            areAllPartsParsimony = YES;
            for (i=0; i<p->nRelParts; i++)
                {
                if (modelSettings[p->relParts[i]].parsModelId == NO)
                    areAllPartsParsimony = NO;
                }
            
            /* find the parameter x prior type */
            p->paramId = SPECIESTREE_UNIFORM;

            /* should we print the tree? */
            p->printParam = YES;
            }
        else if (j == P_SPECRATE)
            {
            /* Set up speciation rate ******************************************************************************/
            p->paramType = P_SPECRATE;
            if (!strcmp(mp->clockPr,"Fossilization"))
                p->nValues = mp->sampleFSNum +1;  // rate in each time interval
            else
                p->nValues = 1;
            p->nSubValues = 0;
            p->min = POS_MIN;
            p->max = POS_INFINITY;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].speciationRates = p;

            p->paramTypeName = "Speciation rate";
            SafeStrcat(&p->name, "Net_speciation");
            SafeStrcat(&p->name, partString);

            /* find the parameter x prior type */
            if (!strcmp(mp->speciationPr,"Uniform"))
                p->paramId = SPECRATE_UNI;
            else if (!strcmp(mp->speciationPr,"Exponential"))
                p->paramId = SPECRATE_EXP;
            else
                p->paramId = SPECRATE_FIX;

            if (p->paramId != SPECRATE_FIX)
                p->printParam = YES;
                
            if (p->nValues == 1)
                {
                SafeStrcat (&p->paramHeader, "net_speciation");
                SafeStrcat (&p->paramHeader, partString);
                }
            else for (i = 0; i < p->nValues; i++)
                {
                sprintf (tempStr, "\tnet_speciation_%d", i+1);
                SafeStrcat (&p->paramHeader, tempStr);
                SafeStrcat (&p->paramHeader, partString);
                }
            }
        else if (j == P_EXTRATE)
            {
            /* Set up extinction rates ******************************************************************************/
            p->paramType = P_EXTRATE;
            if (!strcmp(mp->clockPr,"Fossilization"))
                p->nValues = mp->sampleFSNum +1;  // rate in each time interval
            else
                p->nValues = 1;
            p->nSubValues = 0;
            p->min = 0.0;
            p->max = 1.0;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].extinctionRates = p;

            p->paramTypeName = "Extinction rate";
            SafeStrcat(&p->name, "Relative_extinction");
            SafeStrcat(&p->name, partString);

            /* find the parameter x prior type */
            if (!strcmp(mp->extinctionPr,"Beta"))
                p->paramId = EXTRATE_BETA;
            else
                p->paramId = EXTRATE_FIX;

            if (p->paramId != EXTRATE_FIX)
                p->printParam = YES;
                
            if (p->nValues == 1)
                {
                SafeStrcat (&p->paramHeader, "relative_extinction");
                SafeStrcat (&p->paramHeader, partString);
                }
            else for (i = 0; i < p->nValues; i++)
                {
                sprintf (tempStr, "\trelative_extinction_%d", i+1);
                SafeStrcat (&p->paramHeader, tempStr);
                SafeStrcat (&p->paramHeader, partString);
                }
            }
        else if (j == P_FOSLRATE)
            {
            /* Set up fossilization rates */
            p->paramType = P_FOSLRATE;
            p->nValues = mp->sampleFSNum +1;  // rate in each time interval
            p->nSubValues = 0;
            p->min = 0.0;
            p->max = 1.0;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].fossilizationRates = p;
            
            p->paramTypeName = "Fossilization rate";
            SafeStrcat(&p->name, "Relative_fossilization");
            SafeStrcat(&p->name, partString);
            
            /* find the parameter x prior type */
            if (!strcmp(mp->fossilizationPr,"Beta"))
                p->paramId = FOSLRATE_BETA;
            else
                p->paramId = FOSLRATE_FIX;
            
            if (p->paramId != FOSLRATE_FIX)
                p->printParam = YES;
            
            if (p->nValues == 1)
                {
                SafeStrcat (&p->paramHeader, "relative_fossilization");
                SafeStrcat (&p->paramHeader, partString);
                }
            else for (i = 0; i < p->nValues; i++)
                {
                sprintf (tempStr, "\trelative_fossilization_%d", i+1);
                SafeStrcat (&p->paramHeader, tempStr);
                SafeStrcat (&p->paramHeader, partString);
                }
            }
        else if (j == P_POPSIZE)
            {
            /* Set up population size *****************************************************************************************/
            p->paramType = P_POPSIZE;
            if (!strcmp(mp->topologyPr,"Speciestree") && !strcmp(mp->popVarPr, "Variable"))
                p->nValues = 2 * numSpecies;
            else
                p->nValues = 1;
            p->nSubValues = 0;
            p->min = POS_MIN;
            p->max = POS_INFINITY;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].popSize = p;

            p->paramTypeName = "Coalescent process population size parameter";
            SafeStrcat(&p->name, "Popsize");
            SafeStrcat(&p->name, partString);

            /* find the parameter x prior type */
            if (!strcmp(mp->popSizePr,"Uniform"))
                {
                p->paramId      = POPSIZE_UNI;
                p->LnPriorRatio = &LnProbRatioUniform;
                p->priorParams  = mp->popSizeUni;
                p->LnPriorProb  = &LnPriorProbUniform;
                }
            else if (!strcmp(mp->popSizePr,"Normal"))
                {
                p->paramId      = POPSIZE_NORMAL;
                p->LnPriorRatio = &LnProbRatioTruncatedNormal;
                p->priorParams  = mp->popSizeNormal;
                p->LnPriorProb  = &LnPriorProbTruncatedNormal;
                }
            else if (!strcmp(mp->popSizePr,"Lognormal"))
                {
                p->paramId      = POPSIZE_LOGNORMAL;
                p->LnPriorRatio = &LnProbRatioLognormal;
                p->priorParams  = mp->popSizeLognormal;
                p->LnPriorProb  = &LnPriorProbLognormal;
                }
            else if (!strcmp(mp->popSizePr,"Gamma"))
                {
                p->paramId      = POPSIZE_GAMMA;
                p->LnPriorRatio = &LnProbRatioGamma;
                p->priorParams  = mp->popSizeGamma;
                p->LnPriorProb  = &LnPriorProbGamma;
                }
            else
                {
                p->paramId      = POPSIZE_FIX;
                p->LnPriorRatio = NULL;
                p->priorParams  = &mp->popSizeFix;
                p->LnPriorProb  = &LnPriorProbFix;
                }

            if (p->paramId != POPSIZE_FIX && p->nValues == 1)
                p->printParam = YES;
            SafeStrcat (&p->paramHeader, "popsize");
            SafeStrcat (&p->paramHeader, partString);
            }
        else if (j == P_GROWTH)
            {
            /* Set up growth rate ************************************************************************************/
            p->paramType = P_GROWTH;
            p->nValues = 1;
            p->nSubValues = 0;
            p->min = 0.0;
            p->max = POS_INFINITY;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].growthRate = p;

            p->paramTypeName = "Population growth rate";
            SafeStrcat(&p->name, "R_pop");
            SafeStrcat(&p->name, partString);

            /* find the parameter x prior type */
            if (!strcmp(mp->growthPr,"Uniform"))
                {
                p->paramId = GROWTH_UNI;
                p->priorParams = mp->growthUni;
                p->min = mp->growthUni[0];
                p->max = mp->growthUni[1];
                p->LnPriorRatio = &LnProbRatioUniform;
                p->LnPriorProb = &LnPriorProbUniform;
                }
            else if (!strcmp(mp->growthPr,"Exponential"))
                {
                p->paramId = GROWTH_EXP;
                p->priorParams = &mp->growthExp;
                p->min = GROWTH_MIN;
                p->max = GROWTH_MAX;
                p->LnPriorRatio = &LnProbRatioExponential;
                p->LnPriorProb = &LnPriorProbExponential;
                }
            else if (!strcmp(mp->growthPr,"Normal"))
                {
                p->paramId = GROWTH_NORMAL;
                p->priorParams = mp->growthNorm;
                p->min = GROWTH_MIN;
                p->max = GROWTH_MAX;
                p->LnPriorRatio = &LnProbRatioTruncatedNormal;
                p->LnPriorProb = &LnPriorProbTruncatedNormal;
                }
            else
                p->paramId = GROWTH_FIX;
                {
                p->paramId = GROWTH_FIX;
                p->priorParams = &mp->growthFix;
                p->min = p->max = mp->growthFix;
                p->LnPriorRatio = &LnProbRatioFix;
                p->LnPriorProb = &LnPriorProbFix;
                }

            if (p->paramId != GROWTH_FIX)
                p->printParam = YES;
            SafeStrcat (&p->paramHeader, "growthRate");
            SafeStrcat (&p->paramHeader, partString);
            }
        else if (j == P_AAMODEL)
            {
            /* Set up aamodel *****************************************************************************************/
            p->paramType = P_AAMODEL;
            p->nValues = 1;
            p->nSubValues = 10;
            p->min = 0;
            p->max = 9;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].aaModel = p;

            p->paramTypeName = "Aminoacid model";
            SafeStrcat(&p->name, "Aamodel");
            SafeStrcat(&p->name, partString);

            /* find the parameter x prior type */
            if (!strcmp(mp->aaModelPr,"Mixed"))
                p->paramId = AAMODEL_MIX;
            else
                p->paramId = AAMODEL_FIX;

            if (p->paramId != AAMODEL_FIX)
                p->printParam = YES;
            SafeStrcat (&p->paramHeader, "aamodel");
            SafeStrcat (&p->paramHeader, partString);
            }
        else if (j == P_CPPRATE)
            {
            /* Set up cpprate *****************************************************************************************/
            p->paramType = P_CPPRATE;
            p->nValues = 1;
            p->nSubValues = 0;
            p->min = 0.0;
            p->max = POS_INFINITY;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].cppRate = p;

            p->paramTypeName = "Rate of rate-multiplying compound Poisson process";
            SafeStrcat(&p->name, "Lambda_cpp");
            SafeStrcat(&p->name, partString);
                    
            /* find the parameter x prior type */
            if (!strcmp(mp->cppRatePr,"Exponential"))
                p->paramId = CPPRATE_EXP;
            else
                p->paramId = CPPRATE_FIX;
            
            if (p->paramId != CPPRATE_FIX)
                p->printParam = YES;
            SafeStrcat (&p->paramHeader, "cppRate");
            SafeStrcat (&p->paramHeader, partString);
            }
        else if (j == P_CPPMULTDEV)
            {
            /* Set up sigma of cpp rate multipliers *****************************************************************************************/
            p->paramType = P_CPPMULTDEV;
            p->nValues = 1;
            p->nSubValues = 0;
            p->min = 0.0;
            p->max = POS_INFINITY;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].cppMultDev = p;

            p->paramTypeName = "Standard deviation (log) of CPP rate multipliers";
            SafeStrcat(&p->name, "Sigma_cpp");
            SafeStrcat(&p->name, partString);
                    
            /* find the parameter x prior type */
            if (!strcmp(mp->cppMultDevPr,"Fixed"))
                p->paramId = CPPMULTDEV_FIX;
            
            if (p->paramId != CPPMULTDEV_FIX)
                p->printParam = YES;
            SafeStrcat (&p->paramHeader, "sigma_cpp");
            SafeStrcat (&p->paramHeader, partString);
            }
        else if (j == P_CPPEVENTS)
            {
            /* Set up cpp events parameter *****************************************************************************************/
            p->paramType = P_CPPEVENTS;
            p->nValues = 0;
            p->nSubValues = 2*numLocalTaxa;     /* keep effective branch lengths here (for all nodes to be on the safe side) */
            p->min = 1E-6;
            p->max = POS_INFINITY;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].cppEvents = p;

            p->paramTypeName = "Events of rate-multiplying compound Poisson process";
            SafeStrcat(&p->name, "CppEvents");
            SafeStrcat(&p->name, partString);
            
            /* find the parameter x prior type */
            p->paramId = CPPEVENTS;
            
            /* should we print values to .p file? */
            p->printParam = NO;
            
            SafeStrcat (&p->paramHeader, "cppEvents");
            SafeStrcat (&p->paramHeader, partString);
            }
        else if (j == P_TK02VAR)
            {
            /* Set up tk02 relaxed clock variance parameter *****************************************************************************************/
            p->paramType = P_TK02VAR;
            p->nValues = 1;
            p->nSubValues = 0;
            p->min = 1E-6;
            p->max = POS_INFINITY;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].tk02var = p;

            p->paramTypeName = "Variance of lognormal distribution of branch rates";
            SafeStrcat(&p->name, "TK02var");
            SafeStrcat(&p->name, partString);
            
            /* find the parameter x prior type */
            if (!strcmp(mp->tk02varPr,"Uniform"))
                p->paramId = TK02VAR_UNI;
            else if (!strcmp(mp->tk02varPr,"Exponential"))
                p->paramId = TK02VAR_EXP;
            else
                p->paramId = TK02VAR_FIX;
            
            if (p->paramId != TK02VAR_FIX)
                p->printParam = YES;
            SafeStrcat (&p->paramHeader, "tk02var");
            SafeStrcat (&p->paramHeader, partString);
            }
        else if (j == P_TK02BRANCHRATES)
            {
            /* Set up tk02 relaxed clock rates parameter *****************************************************************************************/
            p->paramType = P_TK02BRANCHRATES;
            p->nValues = 2*numLocalTaxa;     /* use to hold the branch rates; we need one rate for the root */
            p->nSubValues = 2*numLocalTaxa;  /* use to hold the effective branch lengths */
            p->min = RATE_MIN;
            p->max = RATE_MAX;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].tk02BranchRates = p;
            
            p->paramTypeName = "Branch rates of TK02 relaxed clock";
            SafeStrcat(&p->name, "TK02Brlens");
            SafeStrcat(&p->name, partString);
            
            /* find the parameter x prior type */
            p->paramId = TK02BRANCHRATES;
            
            /* should we print values to .p file? */
            p->printParam = NO;

            SafeStrcat (&p->paramHeader, "tk02_brlens");
            SafeStrcat (&p->paramHeader, partString);
            }
        else if (j == P_IGRVAR)
            {
            /* Set up igr relaxed clock variance parameter *****************************************************************************************/
            p->paramType = P_IGRVAR;
            p->nValues = 1;
            p->nSubValues = 0;
            p->min = 1E-6;
            p->max = POS_INFINITY;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].igrvar = p;

            p->paramTypeName = "Variance increase of igr model branch lenths";
            SafeStrcat(&p->name, "Igrvar");
            SafeStrcat(&p->name, partString);
            
            /* find the parameter x prior type */
            if (!strcmp(mp->igrvarPr,"Uniform"))
                p->paramId = IGRVAR_UNI;
            else if (!strcmp(mp->igrvarPr,"Exponential"))
                p->paramId = IGRVAR_EXP;
            else
                p->paramId = IGRVAR_FIX;
            
            if (p->paramId != IGRVAR_FIX)
                p->printParam = YES;
            SafeStrcat (&p->paramHeader, "igrvar");
            SafeStrcat (&p->paramHeader, partString);
            }
        else if (j == P_IGRBRANCHRATES)
            {
            /* Set up igr relaxed clock rates parameter *****************************************************************************************/
            p->paramType = P_IGRBRANCHRATES;
            p->nValues = 2*numLocalTaxa;     /* use to hold the branch rates; we need one rate for the root */
            p->nSubValues = 2*numLocalTaxa;  /* use to hold the effective branch lengths */
            p->min = RATE_MIN;
            p->max = RATE_MAX;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].igrBranchRates = p;
            
            p->paramTypeName = "Branch lengths of IGR relaxed clock";
            SafeStrcat(&p->name, "IgrBrlens");
            SafeStrcat(&p->name, partString);
            
            /* find the parameter x prior type */
            p->paramId = IGRBRANCHRATES;
            
            /* should we print values to .p file? */
            p->printParam = NO;

            SafeStrcat (&p->paramHeader, "igr_brlens");
            SafeStrcat (&p->paramHeader, partString);
            }
        else if (j == P_MIXEDVAR)
            {
            /* Set up mixed relaxed clock variance parameter *****************************************************************************************/
            p->paramType = P_MIXEDVAR;
            p->nValues = 1;
            p->nSubValues = 0;
            p->min = 1E-6;
            p->max = POS_INFINITY;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].mixedvar = p;
            
            p->paramTypeName = "Variance shared for mixed relaxed clock moodel";
            SafeStrcat(&p->name, "Mixedvar");
            SafeStrcat(&p->name, partString);
            
            /* find the parameter x prior type */
            if (!strcmp(mp->mixedvarPr,"Uniform"))
                p->paramId = MIXEDVAR_UNI;
            else if (!strcmp(mp->mixedvarPr,"Exponential"))
                p->paramId = MIXEDVAR_EXP;
            else
                p->paramId = MIXEDVAR_FIX;
            
            if (p->paramId != MIXEDVAR_FIX)
                p->printParam = YES;
            SafeStrcat (&p->paramHeader, "mixedvar");
            SafeStrcat (&p->paramHeader, partString);
            }
        else if (j == P_MIXEDBRCHRATES)
            {
            /* Set up mixed relaxed clock rates parameter *****************************************************************************************/
            p->paramType = P_MIXEDBRCHRATES;
            p->nValues = 2*numLocalTaxa;     /* use to hold the branch rates; we need one rate for the root */
            p->nSubValues = 2*numLocalTaxa;  /* use to hold the effective branch lengths */
            p->nIntValues = 1;               /* use to hold the model indicator: TK02 or IGR */
            p->min = RATE_MIN;
            p->max = RATE_MAX;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].mixedBrchRates = p;
            
            p->paramTypeName = "Branch rates of mixed relaxed clock";
            SafeStrcat(&p->name, "MixedBrlens");
            SafeStrcat(&p->name, partString);
            
            /* find the parameter x prior type */
            p->paramId = MIXEDBRCHRATES;
            
            /* how to print model indicator (0 or 1) to .p file? */
            p->printParam = NO;
            
            SafeStrcat (&p->paramHeader, "mixed_brlens");
            SafeStrcat (&p->paramHeader, partString);
            }
        else if (j == P_CLOCKRATE)
            {
            /* Set up clockRate ****************************************************************************************/
            p->paramType = P_CLOCKRATE;
            p->nValues = 1;
            p->nSubValues = 0;
            p->min = POS_MIN;
            p->max = POS_INFINITY;
            for (i=0; i<numCurrentDivisions; i++)
                if (isPartTouched[i] == YES)
                    modelSettings[i].clockRate = p;
    
            p->paramTypeName = "Base rate of clock";
            SafeStrcat(&p->name, "Clockrate");
            SafeStrcat(&p->name, partString);

            /* parameter does affect likelihoods */
            p->affectsLikelihood = YES;
            
            /* find the parameter x prior type */
            if (!strcmp(mp->clockRatePr,"Normal"))
                {
                p->paramId      = CLOCKRATE_NORMAL;
                p->LnPriorRatio = &LnProbRatioTruncatedNormal;
                p->priorParams  = mp->clockRateNormal;
                p->LnPriorProb  = &LnPriorProbTruncatedNormal;
                }
            else if (!strcmp(mp->clockRatePr,"Lognormal"))
                {
                p->paramId      = CLOCKRATE_LOGNORMAL;
                p->LnPriorRatio = &LnProbRatioLognormal;
                p->priorParams  = mp->clockRateLognormal;
                p->LnPriorProb  = &LnPriorProbLognormal;
                }
            else if (!strcmp(mp->clockRatePr,"Exponential"))
                {
                p->paramId      = CLOCKRATE_EXP;
                p->LnPriorRatio = &LnProbRatioExponential;
                p->priorParams  = &mp->clockRateExp;
                p->LnPriorProb  = &LnPriorProbExponential;
                }
            else if (!strcmp(mp->clockRatePr,"Gamma"))
                {
                p->paramId      = CLOCKRATE_GAMMA;
                p->LnPriorRatio = &LnProbRatioGamma;
                p->priorParams  = mp->clockRateGamma;
                p->LnPriorProb  = &LnPriorProbGamma;
                }
            else
                {
                p->paramId      = CLOCKRATE_FIX;
                p->LnPriorRatio = NULL;
                p->priorParams  = &mp->clockRateFix;
                p->LnPriorProb  = &LnPriorProbFix;
                }
                
            SafeStrcat (&p->paramHeader, "clockrate");
            SafeStrcat (&p->paramHeader, partString);
            if (p->paramId != CLOCKRATE_FIX)
                p->printParam = YES;
            }
        }
    free (tempStr);
    free (isPartTouched);
    SafeFree ((void **)&partString);

    return (NO_ERROR);
}


/*----------------------------------------------------------------------------
|
|   SetMoves: This function will set up the applicable moves that could
|       potentially be used in updating the model parameters
|
-----------------------------------------------------------------------------*/
int SetMoves (void)
{
    int         i, j, k, moveIndex;
    Param       *param;
    
    /* free up previous moves if any */
    if (memAllocs[ALLOC_MOVES] == YES)
        {
        for (i=0; i<numApplicableMoves; i++)
            FreeMove (moves[i]);
        free (moves);
        moves = NULL;
        memAllocs[ALLOC_MOVES] = NO;
        }

    /* set up applicable moves                                   */
    /* each combination of moveType and param is a separate move */
    
    /* first count applicable moves */
    numApplicableMoves = 0;
    for (k=0; k<numParams; k++)
        {
        param = &params[k];
        for (i=0; i<NUM_MOVE_TYPES; i++)
            {
            if (moveTypes[i].level > userLevel)
                continue;
            if (moveTypes[i].isApplicable(param) == NO)
                continue;
            for (j=0; j<moveTypes[i].nApplicable; j++)
                if (moveTypes[i].applicableTo[j] == param->paramId)
                    {
                    numApplicableMoves++;
                    break;
                    }
            }
        }

    /* then allocate space for move pointers */
    moves = (MCMCMove **) SafeMalloc (numApplicableMoves * sizeof (MCMCMove *));
    if (!moves)
        {
        MrBayesPrint ("%s   Problem allocating moves\n", spacer);
        return (ERROR);
        }
    memAllocs[ALLOC_MOVES] = YES;

    /* finally allocate space for and set move defaults */
    moveIndex = 0;
    for (k=0; k<numParams; k++)
        {
        param = &params[k];
        for (i=0; i<NUM_MOVE_TYPES; i++)
            {   
            if (moveTypes[i].level > userLevel)
                continue;
            if (moveTypes[i].isApplicable(param) == NO)
                continue;
            for (j=0; j<moveTypes[i].nApplicable; j++)
                {
                if (moveTypes[i].applicableTo[j] == param->paramId)
                    {
                    if ((moves[moveIndex] = AllocateMove (&moveTypes[i], param)) == NULL)
                        break;
                    else
                        {
                        moves[moveIndex]->parm = param;
                        moveIndex++;
                        break;
                        }
                    }
                }
            }
        }

    if (moveIndex < numApplicableMoves)
        {
        for (i=0; i<moveIndex; i++)
            FreeMove (moves[i]);
        free (moves);
        memAllocs[ALLOC_MOVES] = NO;
        MrBayesPrint ("%s   Problem setting moves\n", spacer);
        return (ERROR);
        }

    return (NO_ERROR);
}


/** SetPopSizeParam: Set population size values for a species tree from an input tree */
int SetPopSizeParam (Param *param, int chn, int state, PolyTree *pt)
{
    int         i, j, k, nLongsNeeded;
    MrBFlt      *values;
    Tree        *speciesTree;
    PolyNode    *pp;
    TreeNode    *p=NULL;

    nLongsNeeded = 1 + (pt->nNodes - pt->nIntNodes - 1) / nBitsInALong;

    /* Get pointer to values to be set */
    values = GetParamVals (param, chn, state);

    /* Get species tree */
    speciesTree = GetTree (modelSettings[param->relParts[0]].speciesTree, chn, state);

    /* Set them based on index of matching partitions */
    AllocatePolyTreePartitions(pt);
    AllocateTreePartitions(speciesTree);
    for (i=0; i<pt->nNodes; i++)
        {
        pp = pt->allDownPass[i];
        for (j=0; j<speciesTree->nNodes-1; j++)
            {
            p = speciesTree->allDownPass[j];
            for (k=0; k<nLongsNeeded; k++)
                {
                if (pp->partition[k] != p->partition[k])
                    break;
                }
            if (k == nLongsNeeded)
                break;
            }
        if (j == speciesTree->nNodes - 1)
            {
            MrBayesPrint ("%s   Non-matching partitions when setting population size parameter", spacer);
            FreePolyTreePartitions(pt);
            FreeTreePartitions(speciesTree);
            return (ERROR);
            }
        values[p->index] = pt->popSize[pp->index];
    }

    FreePolyTreePartitions(pt);
    FreeTreePartitions(speciesTree);
    
    return (NO_ERROR);
}


/* SetRelaxedClockParam: set values for a relaxed clock param from an input tree */
int SetRelaxedClockParam (Param *param, int chn, int state, PolyTree *pt)
{
    int         i, j, k, *nEvents=NULL, *nEventsP=NULL, nLongsNeeded, isEventSet;
    MrBFlt       *effectiveBranchLengthP=NULL, *branchRate=NULL,
                **position=NULL, **rateMult=NULL, **positionP=NULL, **rateMultP=NULL,
                baseRate;
    Tree        *t;
    PolyNode    *pp;
    TreeNode    *p=NULL, *q;

    nLongsNeeded = 1 + (numLocalTaxa - 1) / nBitsInALong;

    /* set pointers to the right set of values */
    isEventSet = NO;
    if (param->paramType == P_CPPEVENTS)
        {
        /* find the right event set */
        for (i=0; i<pt->nESets; i++)
            {
            if (!strcmp(param->name,pt->eSetName[i]))
                break;
            }
        if (i == pt->nESets)
            {
            for (i=0; i<pt->nBSets; i++)
                if (!strcmp(param->name,pt->bSetName[i]))
                    break;

            if (i == pt->nBSets)
                return (NO_ERROR);
            else
                isEventSet = NO;
            }
        else
            isEventSet = YES;

        if (isEventSet == YES)
            {
            nEventsP  = pt->nEvents[i];
            positionP = pt->position[i];
            rateMultP = pt->rateMult[i];
            }
        else
            effectiveBranchLengthP = pt->effectiveBrLen[i];

        nEvents  = param->nEvents[2*chn+state];
        position = param->position[2*chn+state];
        rateMult = param->rateMult[2*chn+state];
        }
    else if (param->paramType == P_TK02BRANCHRATES || param->paramType == P_IGRBRANCHRATES || param->paramType == P_MIXEDBRCHRATES)
        {
        /* find the right effective branch length set */
        for (i=0; i<pt->nBSets; i++)
            if (!strcmp(param->name,pt->bSetName[i]))
                break;
        if (i == pt->nBSets)
            return (NO_ERROR);

        effectiveBranchLengthP = pt->effectiveBrLen[i];
        branchRate = GetParamVals (param, chn, state);
        }

    t = GetTree (param, chn, state);
    AllocatePolyTreePartitions (pt);
    AllocateTreePartitions (t);
    
    for (i=pt->nNodes-1; i>=0; i--)
        {
        pp = pt->allDownPass[i];
        for (j=0; j<t->nNodes; j++)
            {
            p = t->allDownPass[j];
            for (k=0; k<nLongsNeeded; k++)
                if (p->partition[k] != pp->partition[k])
                    break;
            if (k == nLongsNeeded)
                break;  /* match */
            }
        if (param->paramType == P_CPPEVENTS)
            {
            if (isEventSet == NO)
                {
                if (nEvents[p->index] != 1)
                    {
                    position[p->index] = (MrBFlt *) SafeRealloc ((void *) position[p->index], 1*sizeof(MrBFlt));
                    rateMult[p->index] = (MrBFlt *) SafeRealloc ((void *) rateMult[p->index], 1*sizeof(MrBFlt));
                    nEvents [p->index] = 1;
                    }
                position[p->index][0] = 0.5;
                if (p->anc->anc == NULL)
                    rateMult[p->index][0] = 1.0;
                else
                    {
                    baseRate = 1.0;
                    q = p->anc;
                    while (q->anc != NULL)
                        {
                        baseRate *= rateMult[q->index][0];
                        q = q->anc;
                        }
                    rateMult[p->index][0] = 2.0 * effectiveBranchLengthP[pp->index] / (p->length * baseRate) - 1.0;
                    }
                }
            else
                {
                if (nEvents[p->index] != nEventsP[pp->index])
                    {
                    if (nEventsP[pp->index] == 0)
                        {
                        free (position[p->index]);
                        free (rateMult[p->index]);
                        }
                    else
                        {
                        position[p->index] = (MrBFlt *) SafeRealloc ((void *) position[p->index], nEventsP[pp->index]*sizeof(MrBFlt));
                        rateMult[p->index] = (MrBFlt *) SafeRealloc ((void *) rateMult[p->index], nEventsP[pp->index]*sizeof(MrBFlt));
                        }
                    nEvents[p->index] = nEventsP[pp->index];
                    }
                for (j=0; j<nEventsP[pp->index]; j++)
                    {
                    position[p->index][j] = positionP[pp->index][j];
                    rateMult[p->index][j] = rateMultP[pp->index][j];
                    }
                }
            }
        else if (param->paramType == P_TK02BRANCHRATES ||
                 (param->paramType == P_MIXEDBRCHRATES && *GetParamIntVals(param, chn, state) == RCL_TK02))
            {
            if (p->anc->anc == NULL)
                branchRate[p->index] = 1.0;
            else if (p->length > 0.0)
                branchRate[p->index] = 2.0 * effectiveBranchLengthP[pp->index] / p->length - branchRate[p->anc->index];
            else
                branchRate[p->index] = branchRate[p->anc->index];
            }
        else if (param->paramType == P_IGRBRANCHRATES ||
                 (param->paramType == P_MIXEDBRCHRATES && *GetParamIntVals(param, chn, state) == RCL_IGR))
            {
            if (p->length > 0.0)
                branchRate[p->index] = effectiveBranchLengthP[pp->index] / p->length;
            else
                branchRate[p->index] = branchRate[p->anc->index];
            }  // we are now reading effective branch length for TK02 and IGR
        }

    if (param->paramType == P_CPPEVENTS)
        {
        if (UpdateCppEvolLengths (param, t->root->left, chn) == ERROR)
            return (ERROR);
        }
    else if (param->paramType == P_TK02BRANCHRATES ||
             (param->paramType == P_MIXEDBRCHRATES && *GetParamIntVals(param, chn, state) == RCL_TK02))
        {
        if (UpdateTK02EvolLengths (param, t, chn) == ERROR)
            return (ERROR);
        }
    else if (param->paramType == P_IGRBRANCHRATES ||
             (param->paramType == P_MIXEDBRCHRATES && *GetParamIntVals(param, chn, state) == RCL_IGR))
        {
        if (UpdateIgrBrachLengths (param, t, chn) == ERROR)
            return (ERROR);
        }

    FreePolyTreePartitions (pt);
    FreeTreePartitions (t);

    return (NO_ERROR);
}


/*------------------------------------------------------------------------
|
|   SetUpAnalysis: Set parameters and moves
|
------------------------------------------------------------------------*/
int SetUpAnalysis (RandLong *seed)
{
    setUpAnalysisSuccess=NO;

    /* calculate number of characters and taxa */
    numLocalChar = NumNonExcludedChar ();

    /* we are checking later to make sure no partition is without characters */
    SetLocalTaxa ();
    if (numLocalTaxa <= 2)
        {
        MrBayesPrint ("%s   There must be at least two included taxa, now there is %s\n", spacer,
            numLocalTaxa == 0 ? "none" : "only one");
        return (ERROR);
        }

    /* calculate number of global chains */
    numGlobalChains = chainParams.numRuns * chainParams.numChains;

    /* Set up link table */
    if (SetUpLinkTable () == ERROR)
        return (ERROR);
    
    /* Check that the settings for doublet or codon models are correct. */
    if (CheckExpandedModels() == ERROR)
        return (ERROR);

    /* Set up model info */
    if (SetModelInfo() == ERROR) 
        return (ERROR);
    
    /* Calculate number of (uncompressed) characters for each division */
    if (GetNumDivisionChars() == ERROR)
        return (ERROR);

    /* Compress data and calculate some things needed for setting up params. */
    if (CompressData() == ERROR)
        return (ERROR);

    /* Add dummy characters, if needed. */
    if (AddDummyChars() == ERROR)
        return (ERROR);

    /* Set up parameters for the chain. */
    if (SetModelParams () == ERROR)
        return (ERROR);
    
    /* Allocate normal params */
    if (AllocateNormalParams () == ERROR)
        return (ERROR);
    
    /* Allocate tree params */
    if (AllocateTreeParams () == ERROR)
        return (ERROR);
    
    /* Set default number of trees for sumt to appropriate number */
    sumtParams.numTrees = numTrees;

    /* Fill in normal parameters */
    if (FillNormalParams (seed, 0, numGlobalChains) == ERROR) 
        return (ERROR);

    /* Process standard characters (calculates bsIndex, tiIndex, and more). */
    if (ProcessStdChars(seed) == ERROR)
        return (ERROR);

    /* Fill in trees */
    if (FillTreeParams (seed, 0, numGlobalChains) == ERROR)
        return (ERROR);
    
    /* Set the applicable moves that could be used by the chain. */
    if (SetMoves () == ERROR)
        return (ERROR);
    
    setUpAnalysisSuccess=YES;
    
    return (NO_ERROR);
}


int SetUpLinkTable (void)
{
    int         i, j, k, m, paramCount, isApplicable1, isApplicable2,
                isFirst, isSame;
    int         *check, *modelId;

    check = (int *) SafeMalloc ((size_t) (2*numCurrentDivisions * sizeof (int)));
    if (!check)
        {
        MrBayesPrint ("%s   Problem allocating check (%d)\n", spacer,
            2*numCurrentDivisions * sizeof(int));
        return (ERROR);
        }
    modelId = check + numCurrentDivisions;

    for (j=0; j<NUM_LINKED; j++)
        for (i=0; i<numCurrentDivisions; i++)
            activeParams[j][i] = 0;
    
    if (numCurrentDivisions > 1)
        {
        paramCount = 0;
        for (j=0; j<NUM_LINKED; j++) /* loop over parameters */
            {
            isFirst = YES;
            for (i=0; i<numCurrentDivisions; i++)
                modelId[i] = 0;     
            for (i=0; i<numCurrentDivisions-1; i++) /* loop over partitions */
                {
                for (k=i+1; k<numCurrentDivisions; k++)
                    {
                    if (IsModelSame (j, i, k, &isApplicable1, &isApplicable2) == NO || linkTable[j][i] != linkTable[j][k])
                        {
                        /* we cannot link the parameters */
                        if (isApplicable1 == NO)
                            modelId[i] = -1;
                        if (isApplicable2 == NO)
                            modelId[k] = -1;
                        if (isApplicable1 == YES)
                            {
                            if (isFirst == YES && modelId[i] == 0)
                                {
                                modelId[i] = ++paramCount;
                                isFirst = NO;
                                }
                            else
                                {
                                if (modelId[i] == 0)
                                    modelId[i] = ++paramCount;
                                }
                            }
                        if (modelId[k] == 0 && isApplicable2 == YES)
                            modelId[k] = ++paramCount;
                        }
                    else
                        {
                        /* we can link the parameters */
                        if (isFirst == YES)
                            {
                            if (modelId[i] == 0)
                                modelId[i] = ++paramCount;
                            isFirst = NO;
                            }
                        else
                            {
                            if (modelId[i] == 0)
                                modelId[i] = ++paramCount;
                            }
                        modelId[k] = modelId[i];
                        }
                    }
                }
            for (i=0; i<numCurrentDivisions; i++)
                activeParams[j][i] = modelId[i];
            }
        }
    else
        {
        /* if we have only one partition, then we do things a bit differently */
        paramCount = 0;
        for (j=0; j<NUM_LINKED; j++) /* loop over parameters */
            {
            IsModelSame (j, 0, 0, &isApplicable1, &isApplicable2);
            if (isApplicable1 == YES)
                activeParams[j][0] = ++paramCount;
            else
                activeParams[j][0] = -1;
            }
        }
        
    /* Check that the same report format is specified for all partitions with the same rate multiplier */
    for (i=0; i<numCurrentDivisions; i++)
        check[i] = NO;
    for (i=0; i<numCurrentDivisions; i++)
        {
        m = activeParams[P_RATEMULT][i];
        if (m == -1 || check[i] == YES)
            continue;
        isSame = YES;
        for (j=i+1; j<numCurrentDivisions; j++)
            {
            if (activeParams[P_RATEMULT][j] == m)
                {
                check[i] = YES;
                if (strcmp(modelParams[i].ratemultFormat,modelParams[j].ratemultFormat)!= 0)
                    {
                    isSame = NO;
                    strcpy (modelParams[j].ratemultFormat, modelParams[i].ratemultFormat);
                    }
                }
            }
        if (isSame == NO)
            {
            MrBayesPrint ("%s   WARNING: Report format for ratemult (parameter %d) varies across partitions.\n", spacer);
            MrBayesPrint ("%s      MrBayes will use the format for the first partition, which is %s.\n", spacer, modelParams[i].ratemultFormat);
            }
        }
       
    /* probably a good idea to clean up link table here */
    paramCount = 0;
    for (j=0; j<NUM_LINKED; j++)
        {
        for (i=0; i<numCurrentDivisions; i++)
            check[i] = NO;
        for (i=0; i<numCurrentDivisions; i++)
            {
            if (check[i] == NO && activeParams[j][i] > 0)
                {
                m = activeParams[j][i];
                paramCount++;
                for (k=i; k<numCurrentDivisions; k++)
                    {
                    if (check[k] == NO && activeParams[j][k] == m)
                        {
                        activeParams[j][k] = paramCount;
                        check[k] = YES;
                        }
                    }
                }
            }
        }

    free (check);

    return (NO_ERROR);
}


/*------------------------------------------------------------------------
|
|   SetUpMoveTypes: Set up structs holding info on each move type
|
------------------------------------------------------------------------*/
void SetUpMoveTypes (void)
{
    /* Register the move type here when new move functions are added 
       Remember to check that the number of move types does not exceed NUM_MOVE_TYPES
       defined in bayes.h.         */
    int         i;
    MoveType    *mt;

    /* reset move types */
    for (i=0; i<NUM_MOVE_TYPES; i++)
        {
        mt = &moveTypes[i];
        mt->level = DEVELOPER;
        mt->numTuningParams = 0;
        mt->minimum[0] = mt->minimum[1] = -1000000000.0;
        mt->maximum[0] = mt->maximum[1] =  1000000000.0;
        mt->tuningParam[0] = mt->tuningParam[1] = 0.0;
        mt->nApplicable = 0;
        mt->name = mt->tuningName[0] = mt->tuningName[1] = "";
        mt->paramName = "";
        mt->subParams = NO;
        mt->relProposalProb = 0.0;
        mt->parsimonyBased = NO;
        mt->isApplicable = &IsApplicable;
        mt->Autotune = NULL;
        mt->targetRate = -1.0;
        }

    /* Moves are in alphabetic order after parameter name, which matches the name of a move function if
       there is a separate move function for the parameter. See proposal.h for declaration of move functions.
       Since 2010-10-04, some parameters use generalized move functions and do not have their own. */
    
    i = 0;

    /* Move_Aamodel */
    mt = &moveTypes[i++];
    mt->name = "Uniform random pick";
    mt->shortName = "Uniform";
    mt->applicableTo[0] = AAMODEL_MIX;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_Aamodel;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    
    /* Move_Adgamma */
    mt = &moveTypes[i++];
    mt->name = "Sliding window";
    mt->shortName = "Slider";
    mt->tuningName[0] = "Sliding window size";
    mt->shortTuningName[0] = "delta";
    mt->applicableTo[0] = CORREL_UNI;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_Adgamma;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.5;  /* window size */
    mt->minimum[0] = 0.001;
    mt->maximum[0] = 1.999;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_Beta */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = SYMPI_UNI;
    mt->applicableTo[1] = SYMPI_EXP;
    mt->applicableTo[2] = SYMPI_UNI_MS;
    mt->applicableTo[3] = SYMPI_EXP_MS;
    mt->nApplicable = 4;
    mt->moveFxn = &Move_Beta;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.5);  /* so-called lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_BrLen */
    mt = &moveTypes[i++];
    mt->name = "Random brlen hit with multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";  
    mt->applicableTo[0] = BRLENS_UNI;
    mt->applicableTo[1] = BRLENS_EXP;
    mt->applicableTo[2] = BRLENS_GamDir;
    mt->applicableTo[3] = BRLENS_iGmDir;
    mt->applicableTo[4] = BRLENS_twoExp;
    mt->nApplicable = 5;  // was 2
    mt->moveFxn = &Move_BrLen;
    mt->relProposalProb = 20.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (2.0);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;  /* change it smaller to avoid overflow in the exp function, same for following "smaller" */
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_ClockRate_M */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = CLOCKRATE_NORMAL;
    mt->applicableTo[1] = CLOCKRATE_LOGNORMAL;
    mt->applicableTo[2] = CLOCKRATE_GAMMA;
    mt->applicableTo[3] = CLOCKRATE_EXP;
    mt->nApplicable = 4;
    mt->moveFxn = &Move_ClockRate_M;
    mt->relProposalProb = 2.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.5);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;                 /* smaller */
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_Extinction */
    mt = &moveTypes[i++];
    mt->name = "Sliding window";
    mt->shortName = "Slider";
    mt->tuningName[0] = "Sliding window size";
    mt->shortTuningName[0] = "delta";
    mt->applicableTo[0] = EXTRATE_BETA;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_Extinction;
    mt->relProposalProb = 3.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.1;  /* window size */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 20.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_Fossilization */
    mt = &moveTypes[i++];
    mt->name = "Sliding window";
    mt->shortName = "Slider";
    mt->tuningName[0] = "Sliding window size";
    mt->shortTuningName[0] = "delta";
    mt->applicableTo[0] = FOSLRATE_BETA;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_Fossilization;
    mt->relProposalProb = 3.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.1;  /* window size */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 20.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_AddBranch, for fossilization prior */
    mt = &moveTypes[i++];
    mt->name = "Add branch for FossilizedBD";
    mt->shortName = "AddBranch";
    // mt->subParams = YES;
    mt->applicableTo[0] = BRLENS_CLOCK_FOSSIL;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_AddBranch;
    mt->relProposalProb = 10.0;
    mt->numTuningParams = 0;
    mt->parsimonyBased = NO;
    mt->level =STANDARD_USER;
    mt->isApplicable = &IsApplicable_AncestralFossil;

    /* Move_DelBranch, for fossilization prior */
    mt = &moveTypes[i++];
    mt->name = "Delete branch for FossilizedBD";
    mt->shortName = "DelBranch";
    // mt->subParams = YES;
    mt->applicableTo[0] = BRLENS_CLOCK_FOSSIL;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_DelBranch;
    mt->relProposalProb = 10.0;
    mt->numTuningParams = 0;
    mt->parsimonyBased = NO;
    mt->level =STANDARD_USER;
    mt->isApplicable = &IsApplicable_AncestralFossil;

    /* Move_ExtSPR */
    mt = &moveTypes[i++];
    mt->name = "Extending SPR";
    mt->shortName = "ExtSPR";
    mt->subParams = YES;
    mt->tuningName[0] = "Extension probability";
    mt->shortTuningName[0] = "p_ext";
    mt->tuningName[1] = "Multiplier tuning parameter";
    mt->shortTuningName[1] = "lambda";
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
    mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HOMO;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_ExtSPR;
    mt->relProposalProb = 5.0;
    mt->numTuningParams = 2;
    mt->tuningParam[0] = 0.5; /* extension probability */
    mt->tuningParam[1] = 2.0 * log (1.05);   /* lambda */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 0.99999;
    mt->minimum[1] = 0.00001;
    mt->maximum[1] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->isApplicable = &IsApplicable_FiveTaxaOrMore;

    /* Move_ExtSPR1 */
    mt = &moveTypes[i++];
    mt->name = "Extending SPR variant 1";
    mt->shortName = "ExtSPR1";
    mt->subParams = YES;
    mt->tuningName[0] = "Extension probability";
    mt->shortTuningName[0] = "p_ext";
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
    mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HOMO;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_ExtSPR1;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.5; /* extension probability */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 0.99999;
    mt->parsimonyBased = NO;
    mt->level = DEVELOPER;
    mt->isApplicable = &IsApplicable_FiveTaxaOrMore;

    /* Move_ExtSPRClock */
    mt = &moveTypes[i++];
    mt->name = "Extending SPR for clock trees";
    mt->shortName = "ExtSprClock";
    mt->subParams = YES;
    mt->tuningName[0] = "Extension probability";
    mt->shortTuningName[0] = "p_ext";
    mt->applicableTo[0] = TOPOLOGY_CL_UNIFORM;
    mt->applicableTo[1] = TOPOLOGY_CCL_UNIFORM;
    mt->applicableTo[2] = TOPOLOGY_CL_CONSTRAINED;
    mt->applicableTo[3] = TOPOLOGY_CCL_CONSTRAINED;
    mt->applicableTo[4] = TOPOLOGY_RCL_UNIFORM;
    mt->applicableTo[5] = TOPOLOGY_RCL_CONSTRAINED;
    mt->applicableTo[6] = TOPOLOGY_RCCL_UNIFORM;
    mt->applicableTo[7] = TOPOLOGY_RCCL_CONSTRAINED;
    mt->nApplicable = 8;
    mt->moveFxn = &Move_ExtSPRClock;
    mt->relProposalProb = 10.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.5; /* extension probability */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 0.99999;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->isApplicable = &IsApplicable_ThreeTaxaOrMore;

    /* Move_ExtSS */
    mt = &moveTypes[i++];
    mt->name = "Extending subtree swapper";
    mt->shortName = "ExtSS";
    mt->subParams = YES;
    mt->tuningName[0] = "Extension probability";
    mt->shortTuningName[0] = "p_ext";
    mt->tuningName[1] = "Multiplier tuning parameter";
    mt->shortTuningName[1] = "lambda";
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
    mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HOMO;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_ExtSS;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 2;
    mt->tuningParam[0] = 0.5; /* extension probability */
    mt->tuningParam[1] = 2.0 * log (1.05); /* lambda */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 0.99999;
    mt->minimum[1] = 0.00001;
    mt->maximum[1] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->isApplicable = &IsApplicable_FourTaxaOrMore;

    /* Move_ExtSSClock */
    mt = &moveTypes[i++];
    mt->name = "Extending subtree swapper";
    mt->shortName = "ExtSsClock";
    mt->subParams = YES;
    mt->tuningName[0] = "Extension probability";
    mt->shortTuningName[0] = "p_ext";
    mt->applicableTo[0] = TOPOLOGY_CL_UNIFORM;
    mt->applicableTo[1] = TOPOLOGY_CCL_UNIFORM;
    mt->applicableTo[2] = TOPOLOGY_CL_CONSTRAINED;
    mt->applicableTo[3] = TOPOLOGY_CCL_CONSTRAINED;
    mt->applicableTo[4] = TOPOLOGY_RCL_UNIFORM;
    mt->applicableTo[5] = TOPOLOGY_RCL_CONSTRAINED;
    mt->applicableTo[6] = TOPOLOGY_RCCL_UNIFORM;
    mt->applicableTo[7] = TOPOLOGY_RCCL_CONSTRAINED;
    mt->nApplicable = 8;
    mt->moveFxn = &Move_ExtSSClock;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.5; /* extension probability */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 0.99999;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->isApplicable = &IsApplicable_ThreeTaxaOrMore;

    /* Move_ExtTBR */
    mt = &moveTypes[i++];
    mt->name = "Extending TBR";
    mt->shortName = "ExtTBR";
    mt->subParams = YES;
    mt->tuningName[0] = "Extension probability";
    mt->shortTuningName[0] = "p_ext";
    mt->tuningName[1] = "Multiplier tuning parameter";
    mt->shortTuningName[1] = "lambda";
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
    mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HOMO;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_ExtTBR;
    mt->relProposalProb = 5.0;
    mt->numTuningParams = 2;
    mt->tuningParam[0] = 0.5; /* extension probability */
    mt->tuningParam[1] = 2.0 * log (1.05);   /* lambda */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 0.99999;
    mt->minimum[1] = 0.00001;
    mt->maximum[1] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->isApplicable = &IsApplicable_FiveTaxaOrMore;

    /* Move_ExtTBR1 */
    mt = &moveTypes[i++];
    mt->name = "Extending TBR variant 1";
    mt->shortName = "ExtTBR1";
    mt->subParams = YES;
    mt->tuningName[0] = "Extension probability";
    mt->shortTuningName[0] = "p_ext";
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
    mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HOMO;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_ExtTBR1;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.5; /* extension probability */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 0.99999;
    mt->parsimonyBased = NO;
    mt->level = DEVELOPER;
    mt->isApplicable = &IsApplicable_FiveTaxaOrMore;

    /* Move_RateShape_M */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = SHAPE_UNI;
    mt->applicableTo[1] = SHAPE_EXP;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_RateShape_M;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.5);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 10.0;                 /* smaller */
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_GeneRate_Dir */
    mt = &moveTypes[i++];
    mt->name = "Dirichlet proposal";
    mt->shortName = "Dirichlet";
    mt->tuningName[0] = "Dirichlet parameter";
    mt->shortTuningName[0] = "alpha";
    mt->applicableTo[0] = GENETREERATEMULT_DIR;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_GeneRate_Dir;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 1000.0; /* alphaPi */
    mt->minimum[0] = 0.001;
    mt->maximum[0] = 1000000.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneDirichlet;
    mt->targetRate = 0.25;

    /* Move_GeneTree1 */
    mt = &moveTypes[i++];
    mt->name = "Extending SPR move for gene trees in species trees";
    mt->shortName = "ExtSPRClockGS";
    mt->tuningName[0] = "Extension probability";
    mt->shortTuningName[0] = "prob";
    mt->applicableTo[0] = TOPOLOGY_SPECIESTREE;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_GeneTree1;
    mt->relProposalProb = 10.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.5;       /* Tuning parameter value */
    mt->minimum[0] = 0.00001;       /* Minimum value of tuning param */
    mt->maximum[0] = 0.99999;       /* Maximum value of tuning param */
    mt->parsimonyBased = NO;        /* It does not use parsimony scores */
    mt->level = STANDARD_USER;

    /* Move_GeneTree2 */
    mt = &moveTypes[i++];
    mt->name = "NNI move for gene trees in species trees";
    mt->shortName = "NNIClockGS";
    mt->applicableTo[0] = TOPOLOGY_SPECIESTREE;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_GeneTree2;
    mt->relProposalProb = 10.0;
    mt->numTuningParams = 0;        /* No tuning parameters */
    mt->parsimonyBased = NO;        /* It does not use parsimony scores */
    mt->level = STANDARD_USER;

    /* Move_GeneTree3 */
    mt = &moveTypes[i++];
    mt->name = "Parsimony-biased SPR for gene trees in species trees";
    mt->shortName = "ParsSPRClockGS";
    mt->subParams = YES;
    mt->tuningName[0] = "parsimony warp factor";
    mt->shortTuningName[0] = "warp";
    mt->tuningName[1] = "reweighting probability";
    mt->shortTuningName[1] = "r";
    mt->tuningName[2] = "typical branch length";
    mt->shortTuningName[2] = "v_t";
    mt->applicableTo[0] = TOPOLOGY_SPECIESTREE;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_GeneTree3;
    mt->relProposalProb = 5.0;
    mt->numTuningParams = 3;
    mt->tuningParam[0] = 0.1;  /* warp */
    mt->tuningParam[1] = 0.05; /* upweight and downweight probability */
    mt->tuningParam[2] = 0.05; /* typical branch length */
    mt->minimum[0] = 0.0;
    mt->maximum[0] = 1.0;
    mt->minimum[1] = 0.0;
    mt->maximum[1] = 0.3;
    mt->minimum[2] = 0.0001;
    mt->maximum[2] = 0.5;
    mt->parsimonyBased = YES;
    mt->level = STANDARD_USER;

    /* Move_Growth_M */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = GROWTH_UNI;
    mt->applicableTo[1] = GROWTH_EXP;
    mt->applicableTo[2] = GROWTH_NORMAL;
    mt->nApplicable = 3;
    mt->moveFxn = &Move_Growth_M;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log(1.5);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_Local */
    mt = &moveTypes[i++];
    mt->name = "BAMBE's LOCAL";
    mt->shortName = "Local";
    mt->subParams = YES;
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
    mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HOMO;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_Local;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.1);  /* lambda */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->isApplicable = &IsApplicable_FourTaxaOrMore;

    /* Move_LocalClock */
    mt = &moveTypes[i++];
    mt->name = "Modified LOCAL for clock trees";
    mt->shortName = "LocalClock";
    mt->subParams = YES;
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = TOPOLOGY_CL_UNIFORM;
    mt->applicableTo[1] = TOPOLOGY_CCL_UNIFORM;
    mt->applicableTo[2] = TOPOLOGY_CL_CONSTRAINED;
    mt->applicableTo[3] = TOPOLOGY_CCL_CONSTRAINED;
    mt->nApplicable = 4;
    mt->moveFxn = &Move_LocalClock;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (2.0);  /* lambda */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->isApplicable = &IsApplicable_ThreeTaxaOrMore;

    /* Move_NNI */
    mt = &moveTypes[i++];
    mt->name = "NNI move for parsimony trees";
    mt->shortName = "ParsNNI";
    mt->applicableTo[0] = TOPOLOGY_PARSIMONY_UNIFORM;
    mt->applicableTo[1] = TOPOLOGY_PARSIMONY_CONSTRAINED;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_NNI;
    mt->relProposalProb = 10.0;
    mt->numTuningParams = 0;
    mt->parsimonyBased = NO;    /* no extra parsimony scores are needed */
    mt->level = STANDARD_USER;
    mt->isApplicable = &IsApplicable_FourTaxaOrMore;

    /* Move_NNIClock */
    mt = &moveTypes[i++];
    mt->name = "NNI move for clock trees";
    mt->shortName = "NNIClock";
    mt->subParams = YES;
    mt->applicableTo[0] = TOPOLOGY_CL_UNIFORM;
    mt->applicableTo[1] = TOPOLOGY_CCL_UNIFORM;
    mt->applicableTo[2] = TOPOLOGY_CL_CONSTRAINED;
    mt->applicableTo[3] = TOPOLOGY_CCL_CONSTRAINED;
    mt->applicableTo[4] = TOPOLOGY_RCL_UNIFORM;
    mt->applicableTo[5] = TOPOLOGY_RCL_CONSTRAINED;
    mt->applicableTo[6] = TOPOLOGY_RCCL_UNIFORM;
    mt->applicableTo[7] = TOPOLOGY_RCCL_CONSTRAINED;
    mt->nApplicable = 8;
    mt->moveFxn = &Move_NNIClock;
    mt->relProposalProb = 12.0;
    mt->numTuningParams = 0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->isApplicable = &IsApplicable_ThreeTaxaOrMore;

    /* Move_NNI */
    mt = &moveTypes[i++];
    mt->name = "NNI move";
    mt->shortName = "NNI";
    mt->subParams = YES;
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
    mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HOMO;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_NNI;
    mt->relProposalProb = 5.0;
    mt->numTuningParams = 0;
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->isApplicable = &IsApplicable_FourTaxaOrMore;

    /* Move_NNI_Hetero */
    mt = &moveTypes[i++];
    mt->name = "NNI move for trees with independent brlens";
    mt->shortName = "MultNNI";
    mt->subParams = YES;
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HETERO;
    mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HETERO;
    mt->nApplicable = 2; /* 3; */
    mt->moveFxn = &Move_NNI_Hetero;
    mt->relProposalProb = 15.0;
    mt->numTuningParams = 0;
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->isApplicable = &IsApplicable_FourTaxaOrMore;

    /* Move_NodeSlider */
    mt = &moveTypes[i++];
    mt->name = "Node slider (uniform on possible positions)";
    mt->shortName = "Nodeslider";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = BRLENS_UNI;
    mt->applicableTo[1] = BRLENS_EXP;
    mt->applicableTo[2] = BRLENS_GamDir;
    mt->applicableTo[3] = BRLENS_iGmDir;
    mt->applicableTo[4] = BRLENS_twoExp;
    mt->nApplicable = 5;  // was 2
    mt->moveFxn = &Move_NodeSlider;
    mt->relProposalProb = 7.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.1);  /* lambda */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;

    /* Move_NodeSliderClock */
    mt = &moveTypes[i++];
    mt->name = "Node depth window slider (clock-constrained)";
    mt->shortName = "NodesliderClock";
    mt->tuningName[0] = "Window size";
    mt->shortTuningName[0] = "delta";
    mt->applicableTo[0] = BRLENS_CLOCK_UNI;
    mt->applicableTo[1] = BRLENS_CLOCK_COAL;
    mt->applicableTo[2] = BRLENS_CLOCK_BD;
    mt->applicableTo[3] = BRLENS_CLOCK_FOSSIL;
    mt->nApplicable = 4;
    mt->moveFxn = &Move_NodeSliderClock;
    mt->relProposalProb = 20.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.05; /* window size */
    mt->minimum[0] = 0.000001;
    mt->maximum[0] = 1.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_NodeSliderGeneTree */
    mt = &moveTypes[i++];
    mt->name = "Node depth slider for gene trees";
    mt->shortName = "NodesliderGenetree";
    mt->tuningName[0] = "Window size";
    mt->shortTuningName[0] = "delta";
    mt->applicableTo[0] = BRLENS_CLOCK_SPCOAL;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_NodeSliderGeneTree;
    mt->relProposalProb = 20.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.05; /* window size */
    mt->minimum[0] = 0.000001;
    mt->maximum[0] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_Omega */
    mt = &moveTypes[i++];
    mt->name = "Sliding window";
    mt->shortName = "Slider";
    mt->tuningName[0] = "Sliding window size";
    mt->shortTuningName[0] = "delta";
    mt->applicableTo[0] = OMEGA_DIR;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_Omega;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 1.0; /* sliding window size */
    mt->minimum[0] = 0.000001;
    mt->maximum[0] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_Omega_M */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = OMEGA_DIR;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_Omega_M;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.5);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;                 /* smaller */
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_OmegaBeta_M */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->paramName = "Omega_beta_M10";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = OMEGA_10UUB;
    mt->applicableTo[1] = OMEGA_10UUF;
    mt->applicableTo[2] = OMEGA_10UEB;
    mt->applicableTo[3] = OMEGA_10UEF;
    mt->applicableTo[4] = OMEGA_10UFB;
    mt->applicableTo[5] = OMEGA_10UFF;
    mt->applicableTo[6] = OMEGA_10EUB;
    mt->applicableTo[7] = OMEGA_10EUF;
    mt->applicableTo[8] = OMEGA_10EEB;
    mt->applicableTo[9] = OMEGA_10EEF;
    mt->applicableTo[10] = OMEGA_10EFB;
    mt->applicableTo[11] = OMEGA_10EFF;
    mt->nApplicable = 12;
    mt->moveFxn = &Move_OmegaBeta_M;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.1);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;                 /* smaller */
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_OmegaCat */
    mt = &moveTypes[i++];
    mt->name = "Dirichlet proposal";
    mt->shortName = "Dirichlet";
    mt->paramName = "Omega_pi";
    mt->tuningName[0] = "Dirichlet parameter";
    mt->shortTuningName[0] = "alpha";
    mt->applicableTo[0] = OMEGA_BUD;
    mt->applicableTo[1] = OMEGA_BED;
    mt->applicableTo[2] = OMEGA_BFD;
    mt->applicableTo[3] = OMEGA_FUD;
    mt->applicableTo[4] = OMEGA_FED;
    mt->applicableTo[5] = OMEGA_FFD;
    mt->applicableTo[6] = OMEGA_ED;
    mt->applicableTo[7] = OMEGA_FD;
    mt->applicableTo[8] = OMEGA_10UUB;
    mt->applicableTo[9] = OMEGA_10UEB;
    mt->applicableTo[10] = OMEGA_10UFB;
    mt->applicableTo[11] = OMEGA_10EUB;
    mt->applicableTo[12] = OMEGA_10EEB;
    mt->applicableTo[13] = OMEGA_10EFB;
    mt->applicableTo[14] = OMEGA_10FUB;
    mt->applicableTo[15] = OMEGA_10FEB;
    mt->applicableTo[16] = OMEGA_10FFB;
    mt->nApplicable = 17;
    mt->moveFxn = &Move_OmegaCat;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 300.0;  /* alpha-pi */
    mt->minimum[0] = 0.001;
    mt->maximum[0] = 10000.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneDirichlet;
    mt->targetRate = 0.25;

    /* Move_OmegaGamma_M */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->paramName = "Omega_shape_M10";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = OMEGA_10UUB;
    mt->applicableTo[1] = OMEGA_10UUF;
    mt->applicableTo[2] = OMEGA_10UEB;
    mt->applicableTo[3] = OMEGA_10UEF;
    mt->applicableTo[4] = OMEGA_10EUB;
    mt->applicableTo[5] = OMEGA_10EUF;
    mt->applicableTo[6] = OMEGA_10EEB;
    mt->applicableTo[7] = OMEGA_10EEF;
    mt->applicableTo[8] = OMEGA_10FUB;
    mt->applicableTo[9] = OMEGA_10FUF;
    mt->applicableTo[10] = OMEGA_10FEB;
    mt->applicableTo[11] = OMEGA_10FEF;
    mt->nApplicable = 12;
    mt->moveFxn = &Move_OmegaGamma_M;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.1);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;                 /* smaller */
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_OmegaM3 */
    mt = &moveTypes[i++];
    mt->name = "Sliding window";
    mt->shortName = "Slider";
    mt->tuningName[0] = "Sliding window size";
    mt->shortTuningName[0] = "delta";
    mt->applicableTo[0] = OMEGA_ED;
    mt->applicableTo[1] = OMEGA_EF;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_OmegaM3;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.1;  /* window size */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 1.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_OmegaPur : Let it be here so that omega moves are listed in logical order! */
    mt = &moveTypes[i++];
    mt->name = "Sliding window";
    mt->shortName = "Slider";
    mt->paramName = "Omega_pur";
    mt->tuningName[0] = "Sliding window size";
    mt->shortTuningName[0] = "delta";
    mt->applicableTo[0] = OMEGA_BUD;
    mt->applicableTo[1] = OMEGA_BUF;
    mt->applicableTo[2] = OMEGA_BED;
    mt->applicableTo[3] = OMEGA_BEF;
    mt->applicableTo[4] = OMEGA_BFD;
    mt->applicableTo[5] = OMEGA_BFF;
    mt->nApplicable = 6;
    mt->moveFxn = &Move_OmegaPur;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.1;  /* window size */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 1.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_OmegaPos */
    mt = &moveTypes[i++];
    mt->name = "Sliding window";
    mt->shortName = "Slider";
    mt->paramName = "Omega_pos";
    mt->tuningName[0] = "Sliding window size";
    mt->shortTuningName[0] = "delta";
    mt->applicableTo[0] = OMEGA_BUD;
    mt->applicableTo[1] = OMEGA_BUF;
    mt->applicableTo[2] = OMEGA_BED;
    mt->applicableTo[3] = OMEGA_BEF;
    mt->applicableTo[4] = OMEGA_FUD;
    mt->applicableTo[5] = OMEGA_FUF;
    mt->applicableTo[6] = OMEGA_FED;
    mt->applicableTo[7] = OMEGA_FEF;
    mt->nApplicable = 8;
    mt->moveFxn = &Move_OmegaPos;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 1.0;  /* window size */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_ParsEraser1 */
    mt = &moveTypes[i++];
    mt->name = "Parsimony-biased eraser version 1";
    mt->shortName = "pEraser1";
    mt->subParams = YES;
    mt->tuningName[0] = "Dirichlet parameter";
    mt->shortTuningName[0] = "alpha";
    mt->tuningName[1] = "parsimony warp factor";
    mt->shortTuningName[1] = "warp";
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_ParsEraser1;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 2;
    mt->tuningParam[0] = 0.5; /* alphaPi */
    mt->tuningParam[1] = 0.1; /* warp */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 10000.0;
    mt->minimum[1] = 0.00001;
    mt->maximum[1] = 0.99999;
    mt->parsimonyBased = YES;
    mt->level = DEVELOPER;

    /* Move_ParsSPR */
    mt = &moveTypes[i++];
    mt->name = "Parsimony-biased SPR";
    mt->shortName = "ParsSPR";
    mt->subParams = YES;
    mt->tuningName[0] = "parsimony warp factor";
    mt->shortTuningName[0] = "warp";
    mt->tuningName[1] = "reweighting probability";
    mt->shortTuningName[1] = "r";
    mt->tuningName[2] = "typical branch length";
    mt->shortTuningName[2] = "v_t";
    mt->tuningName[3] = "multiplier tuning parameter";
    mt->shortTuningName[3] = "lambda";
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
    mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HOMO;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_ParsSPR;
    mt->relProposalProb = 5.0;
    mt->numTuningParams = 4;
    mt->tuningParam[0] = 0.1;              /* warp */
    mt->tuningParam[1] = 0.05;             /* upweight and downweight probability */
    mt->tuningParam[2] = 0.05;             /* typical branch length */
    mt->tuningParam[3] = 2.0 * log (1.05); /* multiplier tuning parameter lambda */
    mt->minimum[0] = 0.0;
    mt->maximum[0] = 1.0;
    mt->minimum[1] = 0.0;
    mt->maximum[1] = 0.3;
    mt->minimum[2] = 0.0001;
    mt->maximum[2] = 0.5;
    mt->minimum[3] = 2.0 * log (0.001);
    mt->maximum[3] = 2.0 * log (1000.);
    mt->parsimonyBased = YES;
    mt->level = STANDARD_USER;
    mt->isApplicable = &IsApplicable_FourTaxaOrMore;

    /* Move_ParsSPR1 */
    mt = &moveTypes[i++];
    mt->name = "Parsimony-biased SPR variant 1";
    mt->shortName = "ParsSPR1";
    mt->subParams = YES;
    mt->tuningName[0] = "parsimony warp factor";
    mt->shortTuningName[0] = "warp";
    mt->tuningName[1] = "reweighting probability";
    mt->shortTuningName[1] = "r";
    mt->tuningName[2] = "typical branch length";
    mt->shortTuningName[2] = "v_t";
    mt->tuningName[3] = "multiplier tuning parameter";
    mt->shortTuningName[3] = "lambda";
    mt->tuningName[4] = "moving distance";
    mt->shortTuningName[4] = "d";
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
    mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HOMO;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_ParsSPR1;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 5;
    mt->tuningParam[0] = 0.1;              /* warp */
    mt->tuningParam[1] = 0.05;             /* upweight and downweight probability */
    mt->tuningParam[2] = 0.05;             /* typical branch length */
    mt->tuningParam[3] = 2.0 * log (1.05); /* multiplier tuning parameter lambda */
    mt->tuningParam[4] = 8.0;              /* distance to move picked branch */
    mt->minimum[0] = 0.0;
    mt->maximum[0] = 1.0;
    mt->minimum[1] = 0.0;
    mt->maximum[1] = 0.3;
    mt->minimum[2] = 0.0001;
    mt->maximum[2] = 0.5;
    mt->minimum[3] = 2.0 * log (0.001);
    mt->maximum[3] = 2.0 * log (1000.);
    mt->minimum[4] = 2.0;
    mt->maximum[4] = 1000.0;
    mt->parsimonyBased = YES;
    mt->level = DEVELOPER;
    mt->isApplicable = &IsApplicable_FiveTaxaOrMore;

    /* Move_ParsSPRClock */
    mt = &moveTypes[i++];
    mt->name = "Parsimony-biased SPR for clock trees";
    mt->shortName = "ParsSPRClock";
    mt->subParams = YES;
    mt->tuningName[0] = "parsimony warp factor";
    mt->shortTuningName[0] = "warp";
    mt->tuningName[1] = "reweighting probability";
    mt->shortTuningName[1] = "r";
    mt->tuningName[2] = "typical branch length";
    mt->shortTuningName[2] = "v_t";
    mt->applicableTo[0] = TOPOLOGY_CL_UNIFORM;
    mt->applicableTo[1] = TOPOLOGY_CCL_UNIFORM;
    mt->applicableTo[2] = TOPOLOGY_CL_CONSTRAINED;
    mt->applicableTo[3] = TOPOLOGY_CCL_CONSTRAINED;
    mt->applicableTo[4] = TOPOLOGY_RCL_UNIFORM;
    mt->applicableTo[5] = TOPOLOGY_RCL_CONSTRAINED;
    mt->applicableTo[6] = TOPOLOGY_RCCL_UNIFORM;
    mt->applicableTo[7] = TOPOLOGY_RCCL_CONSTRAINED;
    mt->nApplicable = 8;
    mt->moveFxn = &Move_ParsSPRClock;
    mt->relProposalProb = 8.0;
    mt->numTuningParams = 3;
    mt->tuningParam[0] = 0.1;  /* warp */
    mt->tuningParam[1] = 0.05; /* upweight and downweight probability */
    mt->tuningParam[2] = 0.05; /* typical branch length */
    mt->minimum[0] = 0.0;
    mt->maximum[0] = 1.0;
    mt->minimum[1] = 0.0;
    mt->maximum[1] = 0.3;
    mt->minimum[2] = 0.0001;
    mt->maximum[2] = 0.5;
    mt->parsimonyBased = YES;
    mt->level = STANDARD_USER;
    mt->isApplicable = &IsApplicable_ThreeTaxaOrMore;

    /* Move_ParsTBR */
    mt = &moveTypes[i++];
    mt->name = "Parsimony-biased TBR";
    mt->shortName = "ParsTBR";
    mt->subParams = YES;
    mt->tuningName[0] = "parsimony warp factor";
    mt->shortTuningName[0] = "warp";
    mt->tuningName[1] = "reweighting probability";
    mt->shortTuningName[1] = "r";
    mt->tuningName[2] = "typical branch length";
    mt->shortTuningName[2] = "v_t";
    mt->tuningName[3] = "multiplier tuning parameter";
    mt->shortTuningName[3] = "lambda";
    mt->tuningName[4] = "moving distance";
    mt->shortTuningName[4] = "d";
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
    mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HOMO;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_ParsTBR;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 5;
    mt->tuningParam[0] = 0.1;              /* warp */
    mt->tuningParam[1] = 0.05;             /* upweight and downweight probability */
    mt->tuningParam[2] = 0.05;             /* typical branch length */
    mt->tuningParam[3] = 2.0 * log (1.05); /* multiplier tuning parameter lambda */
    mt->tuningParam[4] = 5.0;              /* distance to move picked branch */
    mt->minimum[0] = 0.0;
    mt->maximum[0] = 1.0;
    mt->minimum[1] = 0.0;
    mt->maximum[1] = 0.3;
    mt->minimum[2] = 0.0001;
    mt->maximum[2] = 0.5;
    mt->minimum[3] = 2.0 * log (0.001);
    mt->maximum[3] = 2.0 * log (1000.);
    mt->minimum[4] = 2.0;
    mt->maximum[4] = 1000.0;
    mt->parsimonyBased = YES;
    mt->level = DEVELOPER;
    mt->isApplicable = &IsApplicable_FiveTaxaOrMore;

    /* Move_Pinvar */
    mt = &moveTypes[i++];
    mt->name = "Sliding window";
    mt->shortName = "Slider";
    mt->tuningName[0] = "Sliding window size";
    mt->shortTuningName[0] = "delta";
    mt->applicableTo[0] = PINVAR_UNI;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_Pinvar;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.1;  /* window size */
    mt->minimum[0] = 0.001;
    mt->maximum[0] = 0.999;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_Popsize_M */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = POPSIZE_UNI;
    mt->applicableTo[1] = POPSIZE_LOGNORMAL;
    mt->applicableTo[2] = POPSIZE_NORMAL;
    mt->applicableTo[3] = POPSIZE_GAMMA;
    mt->nApplicable = 4;
    mt->moveFxn = &Move_PopSize_M;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log(1.5);  /* lambda */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_RanSPR1 */
    mt = &moveTypes[i++];
    mt->name = "Random SPR version 1";
    mt->shortName = "rSPR1";
    mt->subParams = YES;
    mt->tuningName[0] = "Move probability";
    mt->shortTuningName[0] = "p_ext";
    mt->tuningName[1] = "Multiplier tuning parameter";
    mt->shortTuningName[1] = "lambda";
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
    mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HOMO;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_RanSPR1;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 2;
    mt->tuningParam[0] = 0.8; /* move probability */
    mt->tuningParam[1] = 2.0 * log (1.6); /* lambda */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 0.99999;
    mt->minimum[1] = 0.00000001;
    mt->maximum[1] = 10000000.0;
    mt->parsimonyBased = NO;
    mt->level = DEVELOPER;

    /* Move_RanSPR2 */
    mt = &moveTypes[i++];
    mt->name = "Random SPR version 2";
    mt->shortName = "rSPR2";
    mt->subParams = YES;
    mt->tuningName[0] = "Move probability";
    mt->shortTuningName[0] = "p_ext";
    mt->tuningName[1] = "Multiplier tuning parameter";
    mt->shortTuningName[1] = "lambda";
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
    mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HOMO;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_RanSPR2;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 2;
    mt->tuningParam[0] = 0.8; /* move probability */
    mt->tuningParam[1] = 2.0 * log (1.6); /* lambda */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 0.99999;
    mt->minimum[1] = 0.00000001;
    mt->maximum[1] = 10000000.0;
    mt->parsimonyBased = NO;
    mt->level = DEVELOPER;

    /* Move_RanSPR3 */
    mt = &moveTypes[i++];
    mt->name = "Random SPR version 3";
    mt->shortName = "rSPR3";
    mt->subParams = YES;
    mt->tuningName[0] = "Move probability";
    mt->shortTuningName[0] = "p_ext";
    mt->tuningName[1] = "Multiplier tuning parameter";
    mt->shortTuningName[1] = "lambda";
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
    mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HOMO;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_RanSPR3;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 2;
    mt->tuningParam[0] = 0.8; /* move probability */
    mt->tuningParam[1] = 2.0 * log (1.6); /* lambda */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 0.99999;
    mt->minimum[1] = 0.00000001;
    mt->maximum[1] = 10000000.0;
    mt->parsimonyBased = NO;
    mt->level = DEVELOPER;

    /* Move_RanSPR4 */
    mt = &moveTypes[i++];
    mt->name = "Random SPR version 4";
    mt->shortName = "rSPR4";
    mt->subParams = YES;
    mt->tuningName[0] = "Move probability";
    mt->shortTuningName[0] = "p_ext";
    mt->tuningName[1] = "Multiplier tuning parameter";
    mt->shortTuningName[1] = "lambda";
    mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
    mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HOMO;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_RanSPR4;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 2;
    mt->tuningParam[0] = 0.8; /* move probability */
    mt->tuningParam[1] = 2.0 * log (1.6); /* lambda */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 0.99999;
    mt->minimum[1] = 0.00000001;
    mt->maximum[1] = 10000000.0;
    mt->parsimonyBased = NO;
    mt->level = DEVELOPER;

    /* Move_RateMult_Dir */
    mt = &moveTypes[i++];
    mt->name = "Dirichlet proposal";
    mt->shortName = "Dirichlet";
    mt->tuningName[0] = "Dirichlet parameter";
    mt->shortTuningName[0] = "alpha";
    mt->applicableTo[0] = RATEMULT_DIR;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_RateMult_Dir;
    mt->relProposalProb = 0.75;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 50.0; /* alphaPi per site */
    mt->minimum[0] = 0.001;
    mt->maximum[0] = 10000.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneDirichlet;
    mt->targetRate = 0.25;

    /* Move_RateMult_Slider */
    mt = &moveTypes[i++];
    mt->name = "Sliding window";
    mt->shortName = "Slider";
    mt->tuningName[0] = "Sliding window size";
    mt->shortTuningName[0] = "delta";
    mt->applicableTo[0] = RATEMULT_DIR;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_RateMult_Slider;
    mt->relProposalProb = 0.75;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.05;  /* window size */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 1.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_Revmat_Dir */
    mt = &moveTypes[i++];
    mt->name = "Dirichlet proposal";
    mt->shortName = "Dirichlet";
    mt->tuningName[0] = "Dirichlet parameter";
    mt->shortTuningName[0] = "alpha";
    mt->applicableTo[0] = REVMAT_DIR;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_Revmat_Dir;
    mt->relProposalProb = 0.5;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 100.0;  /* alphaPi per rate */
    mt->minimum[0] = 0.001;
    mt->maximum[0] = 10000.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneDirichlet;
    mt->targetRate = 0.25;

    /* Move_Revmat_Slider */
    mt = &moveTypes[i++];
    mt->name = "Sliding window";
    mt->shortName = "Slider";
    mt->tuningName[0] = "Sliding window size";
    mt->shortTuningName[0] = "delta";
    mt->applicableTo[0] = REVMAT_DIR;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_Revmat_Slider;
    mt->relProposalProb = 0.5;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.15;  /* window size */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 1.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_Revmat_DirMix */
    mt = &moveTypes[i++];
    mt->name = "Dirichlet proposal";
    mt->shortName = "Dirichlet";
    mt->tuningName[0] = "Dirichlet parameter";
    mt->shortTuningName[0] = "alpha";
    mt->applicableTo[0] = REVMAT_MIX;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_Revmat_DirMix;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 100.0;  /* alphaPi per rate */
    mt->minimum[0] = 0.01;
    mt->maximum[0] = 10000.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneDirichlet;
    mt->targetRate = 0.25;
    
    /* Move_Revmat_SplitMerge1 */
    mt = &moveTypes[i++];
    mt->name = "Split-merge move 1";
    mt->shortName = "Splitmerge1";
    mt->tuningName[0] = "Dirichlet parameter";
    mt->shortTuningName[0] = "alpha";
    mt->applicableTo[0] = REVMAT_MIX;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_Revmat_SplitMerge1;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 10.0;  /* alphaPi per rate */
    mt->minimum[0] = 0.5;
    mt->maximum[0] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneDirichlet;
    mt->targetRate = 0.25;

    /* Move_Revmat_SplitMerge2 */
    mt = &moveTypes[i++];
    mt->name = "Split-merge move 2";
    mt->shortName = "Splitmerge2";
    mt->tuningName[0] = "Dirichlet parameter";
    mt->shortTuningName[0] = "alpha";
    mt->applicableTo[0] = REVMAT_MIX;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_Revmat_SplitMerge2;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 10.0;  /* alphaPi per rate */
    mt->minimum[0] = 0.5;
    mt->maximum[0] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneDirichlet;
    mt->targetRate = 0.25;

    /* Move_Speciation */
    mt = &moveTypes[i++];
    mt->name = "Sliding window";
    mt->shortName = "Slider";
    mt->tuningName[0] = "Sliding window size";
    mt->shortTuningName[0] = "delta";
    mt->applicableTo[0] = SPECRATE_UNI;
    mt->applicableTo[1] = SPECRATE_EXP;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_Speciation;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 1.0;  /* window size */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_Speciation_M */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = SPECRATE_UNI;
    mt->applicableTo[1] = SPECRATE_EXP;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_Speciation_M;
    mt->relProposalProb = 3.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.1);  /* lambda */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 20.0;                 /* smaller */
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_SpeciesTree */
    mt = &moveTypes[i++];
    mt->name = "Species tree move";
    mt->shortName = "Distmatrixmove";
    mt->tuningName[0] = "Divider of rate of truncated exponential";
    mt->shortTuningName[0] = "lambdadiv";
    mt->applicableTo[0] = SPECIESTREE_UNIFORM;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_SpeciesTree;
    mt->relProposalProb = 10.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 1.2;       /* Default tuning parameter value */
    mt->minimum[0] = 0.00001;       /* Minimum value of tuning param */
    mt->maximum[0] = 1000.0;        /* Maximum value of tuning param */
    mt->parsimonyBased = NO;        /* It does not use parsimony scores */
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier; /* Autotune this move as a mutliplier move (larger is more bold) */
    mt->targetRate = 0.25;              /* Target acceptance rate */

    /* Move_Statefreqs */
    mt = &moveTypes[i++];
    mt->name = "Dirichlet proposal";
    mt->shortName = "Dirichlet";
    mt->tuningName[0] = "Dirichlet parameter";
    mt->shortTuningName[0] = "alpha";
    mt->applicableTo[0] = PI_DIR;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_Statefreqs;
    mt->relProposalProb = 0.5;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 100.0; /* alphaPi per state */
    mt->minimum[0] = 0.001;
    mt->maximum[0] = 10000.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneDirichlet;
    mt->targetRate = 0.25;

    /* Move_Statefreqs_Slider */
    mt = &moveTypes[i++];
    mt->name = "Sliding window";
    mt->shortName = "Slider";
    mt->tuningName[0] = "Sliding window size";
    mt->shortTuningName[0] = "delta";
    mt->applicableTo[0] = PI_DIR;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_Statefreqs_Slider;
    mt->relProposalProb = 0.5;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 0.20;  /* window size (change in proportions) */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 1.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_StatefreqsSymDirMultistate */
    mt = &moveTypes[i++];
    mt->name = "Dirichlet proposal";
    mt->shortName = "Dirichlet";
    mt->paramName = "Pi_symdir";
    mt->tuningName[0] = "Dirichlet parameter";
    mt->shortTuningName[0] = "alpha";
    mt->applicableTo[0] = SYMPI_FIX_MS;
    mt->applicableTo[1] = SYMPI_UNI_MS;
    mt->applicableTo[2] = SYMPI_EXP_MS;
    mt->nApplicable = 3;
    mt->moveFxn = &Move_StatefreqsSymDirMultistate;
    mt->relProposalProb = 5.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 50.0; /* alphaPi */
    mt->minimum[0] = 0.001;
    mt->maximum[0] = 10000.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneDirichlet;
    mt->targetRate = 0.25;

    /* Move_SwitchRate */
    mt = &moveTypes[i++];
    mt->name = "Sliding window";
    mt->shortName = "Slider";
    mt->tuningName[0] = "Sliding window size";
    mt->shortTuningName[0] = "delta";
    mt->applicableTo[0] = SWITCH_UNI;
    mt->applicableTo[1] = SWITCH_EXP;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_SwitchRate;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 1.0;  /* window size */
    mt->minimum[0] = 0.00001;
    mt->maximum[0] = 100.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneSlider;
    mt->targetRate = 0.25;

    /* Move_SwitchRate_M */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = SWITCH_UNI;
    mt->applicableTo[1] = SWITCH_EXP;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_SwitchRate_M;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.5);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;                 /* smaller */
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_Tratio_Dir */
    mt = &moveTypes[i++];
    mt->name = "Dirichlet proposal";
    mt->shortName = "Dirichlet";
    mt->tuningName[0] = "Dirichlet parameter";
    mt->shortTuningName[0] = "alpha";
    mt->applicableTo[0] = TRATIO_DIR;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_Tratio_Dir;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 50.0;  /* alphaPi */
    mt->minimum[0] = 0.001;
    mt->maximum[0] = 10000.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneDirichlet;
    mt->targetRate = 0.25;

    /* Move_TreeStretch */
    mt = &moveTypes[i++];
    mt->name = "Tree stretch";
    mt->shortName = "TreeStretch";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = BRLENS_CLOCK_UNI;
    mt->applicableTo[1] = BRLENS_CLOCK_BD;
    mt->applicableTo[2] = BRLENS_CLOCK_COAL;
    mt->applicableTo[3] = BRLENS_CLOCK_FOSSIL;
    mt->nApplicable = 4;
    mt->moveFxn = &Move_TreeStretch;
    mt->relProposalProb = 3.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log(1.01); /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 2.0 * log(2.0);
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_TreeLen, by Jeremy Brown */
    mt = &moveTypes[i++];
    mt->name = "Whole treelength hit with multiplier";
    mt->shortName = "TLMultiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";  
    mt->applicableTo[0] = BRLENS_UNI;
    mt->applicableTo[1] = BRLENS_EXP;
    mt->applicableTo[2] = BRLENS_GamDir;
    mt->applicableTo[3] = BRLENS_iGmDir;
    mt->applicableTo[4] = BRLENS_twoExp;
    mt->nApplicable = 5;  // was 2
    mt->moveFxn = &Move_TreeLen;
    mt->relProposalProb = 3.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (2.0);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 100.0;                /* smaller */
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_AddDeleteCPPEvent */
    mt = &moveTypes[i++];
    mt->name = "Random addition/deletion of CPP event";
    mt->shortName = "Add_delete";
    mt->applicableTo[0] = CPPEVENTS;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_AddDeleteCPPEvent;
    mt->relProposalProb = 1.0;
    mt->numTuningParams = 0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;

    /* Move_CPPEventPosition */
    mt = &moveTypes[i++];
    mt->name = "Random draw of CPP event position from prior";
    mt->shortName = "Prior_draw_pos";
    mt->applicableTo[0] = CPPEVENTS;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_CPPEventPosition;
    mt->relProposalProb = 2.0;
    mt->numTuningParams = 0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;

    /* Move_CPPRate */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = CPPRATE_EXP;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_CPPRate;
    mt->relProposalProb = 2.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.1);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;                 /* smaller */
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_CPPRateMultiplier_M */
    mt = &moveTypes[i++];
    mt->name = "Random CPP rate multiplier hit with multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = CPPEVENTS;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_CPPRateMultiplier_M;
    mt->relProposalProb = 0.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.1);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;                 /* smaller */
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_CPPRateMultiplierRnd */
    mt = &moveTypes[i++];
    mt->name = "Random draw of CPP rate multiplier from prior";
    mt->shortName = "Prior_draw_mult";
    mt->applicableTo[0] = CPPEVENTS;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_CPPRateMultiplierRnd;
    mt->relProposalProb = 2.0;
    mt->numTuningParams = 0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;

    /* Move_Nu */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = TK02VAR_EXP;
    mt->applicableTo[1] = TK02VAR_UNI;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_Nu;
    mt->relProposalProb = 2.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.1);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;                 /* smaller */
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_TK02BranchRate */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = TK02BRANCHRATES;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_TK02BranchRate;
    mt->relProposalProb = 10.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.1);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_IgrVar */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = IGRVAR_EXP;
    mt->applicableTo[1] = IGRVAR_UNI;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_IgrVar;
    mt->relProposalProb = 2.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.1);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;                 /* smaller */
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_IgrBranchRate */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = IGRBRANCHRATES;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_IgrBranchRate;
    mt->relProposalProb = 10.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.1);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_MixedVar */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = MIXEDVAR_EXP;
    mt->applicableTo[1] = MIXEDVAR_UNI;
    mt->nApplicable = 2;
    mt->moveFxn = &Move_MixedVar;
    mt->relProposalProb = 2.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.1);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;                 /* smaller */
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;
    
    /* Move_MixedBranchRate */
    mt = &moveTypes[i++];
    mt->name = "Multiplier";
    mt->shortName = "Multiplier";
    mt->tuningName[0] = "Multiplier tuning parameter";
    mt->shortTuningName[0] = "lambda";
    mt->applicableTo[0] = MIXEDBRCHRATES;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_MixedBranchRate;
    mt->relProposalProb = 10.0;
    mt->numTuningParams = 1;
    mt->tuningParam[0] = 2.0 * log (1.1);  /* lambda */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 20.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    mt->Autotune = &AutotuneMultiplier;
    mt->targetRate = 0.25;

    /* Move_RelaxedClockModel */
    mt = &moveTypes[i++];
    mt->name = "rjMCMC among Relaxed Clock Models";
    mt->shortName = "rjMCMC_RCL";
    mt->tuningName[0] = "sigma_TK over sigma_IGR";
    mt->shortTuningName[0] = "ratio";
    mt->tuningName[1] = "Sliding window size";
    mt->shortTuningName[1] = "delta";
    mt->applicableTo[0] = MIXEDBRCHRATES;
    mt->nApplicable = 1;
    mt->moveFxn = &Move_RelaxedClockModel;
    mt->relProposalProb = 5.0;
    mt->numTuningParams = 2;
    mt->tuningParam[0] = 100.0; /* TK/IGR var ratio */
    mt->tuningParam[1] = 10.0;  /* window size */
    mt->minimum[0] = 0.0001;
    mt->maximum[0] = 10000.0;
    mt->minimum[1] = 0.0001;
    mt->maximum[1] = 1000.0;
    mt->parsimonyBased = NO;
    mt->level = STANDARD_USER;
    
    numMoveTypes = i;
}


/* ShowModel: Display model on screen */
int ShowModel (void)
{
    int         i, j, ns;

    MrBayesPrint ("%s   Model settings:\n\n", spacer);
    for (i=0; i<numCurrentDivisions; i++)
        {
        ns = 0;

        if (numCurrentDivisions > 1)
            MrBayesPrint ("%s      Settings for partition %d --\n", spacer, i+1);
        else
            MrBayesPrint ("%s      Data not partitioned --\n", spacer);
        
        if (modelParams[i].dataType == DNA)
            {
            MrBayesPrint ("%s         Datatype  = DNA\n", spacer);
            ns = 4;
            }
        else if (modelParams[i].dataType == RNA)
            {
            MrBayesPrint ("%s         Datatype  = RNA\n", spacer);
            ns = 4;
            }
        else if (modelParams[i].dataType == PROTEIN)
            {
            MrBayesPrint ("%s         Datatype  = Protein\n", spacer);
            ns = 20;
            }
        else if (modelParams[i].dataType == RESTRICTION)
            {
            MrBayesPrint ("%s         Datatype  = Restriction\n", spacer);
            ns = 2;
            }
        else if (modelParams[i].dataType == STANDARD)
            {
            MrBayesPrint ("%s         Datatype  = Standard\n", spacer);
            ns = 10;
            }
        else if (modelParams[i].dataType == CONTINUOUS)
            {
            MrBayesPrint ("%s         Datatype  = Continuous\n", spacer);
            }
            
        if (modelSettings[i].dataType == CONTINUOUS)
            {
            /* begin description of continuous models */
              if (!strcmp(modelParams[i].brownCorPr, "Fixed") && AreDoublesEqual(modelParams[i].brownCorrFix, 0.0, ETA)==YES)
                MrBayesPrint ("%s         Model     = Independent Brownian motion\n", spacer);
            else
                MrBayesPrint ("%s         Model     = Correlated Brownian motion\n", spacer);
            /* end description of continuous models */
            }
        else
            {
            /* begin description of discrete models */
            if (!strcmp(modelParams[i].parsModel, "Yes"))
                {
                MrBayesPrint ("%s         Parsmodel = %s\n", spacer, modelParams[i].parsModel);
                }
            else
                {
                /* dna characters in this partition */
                if (modelSettings[i].dataType == DNA || modelSettings[i].dataType == RNA)
                    {
                    /* general form of the rate matrix */ 
                    MrBayesPrint ("%s         Nucmodel  = %s\n", spacer, modelParams[i].nucModel);
                
                    /* constraints on rates of substitution */
                    MrBayesPrint ("%s         Nst       = %s\n", spacer, modelParams[i].nst);
                    if (!strcmp(modelParams[i].nst, "2"))
                        {
                        if (!strcmp(modelParams[i].tRatioPr,"Beta"))
                            {
                            MrBayesPrint ("%s                     Transition and transversion  rates, expressed\n", spacer);
                            MrBayesPrint ("%s                     as proportions of the rate sum, have a\n", spacer);
                            MrBayesPrint ("%s                     Beta(%1.2lf,%1.2lf) prior\n", spacer, modelParams[i].tRatioDir[0], modelParams[i].tRatioDir[1]);
                            }
                        else
                            {
                            MrBayesPrint ("%s                     Transition/transversion rate ratio is fixed to %1.2lf.\n", spacer, modelParams[i].tRatioFix);
                            }
                        }
                    else if (!strcmp(modelParams[i].nst, "6"))
                        {
                        if (!strcmp(modelParams[i].revMatPr,"Dirichlet"))
                            {
                            MrBayesPrint ("%s                     Substitution rates, expressed as proportions\n", spacer);
                            MrBayesPrint ("%s                     of the rate sum, have a Dirichlet prior\n", spacer);
                            MrBayesPrint ("%s                     (%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf)\n", spacer,
                                modelParams[i].revMatDir[0], modelParams[i].revMatDir[1], modelParams[i].revMatDir[2],
                                modelParams[i].revMatDir[3], modelParams[i].revMatDir[4], modelParams[i].revMatDir[5]);
                            }
                        else
                            {
                            MrBayesPrint ("%s                     Substitution rates are fixed to be \n", spacer);
                            MrBayesPrint ("%s                     (%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf).\n", spacer,
                                modelParams[i].revMatFix[0], modelParams[i].revMatFix[1], modelParams[i].revMatFix[2],
                                modelParams[i].revMatFix[3], modelParams[i].revMatFix[4], modelParams[i].revMatFix[5]);
                            }
                        }
                    else if (!strcmp(modelParams[i].nst, "Mixed"))
                        {
                        if (!strcmp(modelParams[i].revMatPr,"Dirichlet"))
                            {
                            MrBayesPrint ("%s                     Substitution rates, expressed as proportions\n", spacer);
                            MrBayesPrint ("%s                     of the rate sum, have a Dirichlet prior\n", spacer);
                            MrBayesPrint ("%s                     (%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf)\n", spacer,
                                modelParams[i].revMatDir[0], modelParams[i].revMatDir[1], modelParams[i].revMatDir[2],
                                modelParams[i].revMatDir[3], modelParams[i].revMatDir[4], modelParams[i].revMatDir[5]);
                            }
                        else
                            {
                            MrBayesPrint ("%s                     Substitution rates are fixed to be \n", spacer);
                            MrBayesPrint ("%s                     (%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf).\n", spacer,
                                modelParams[i].revMatFix[0], modelParams[i].revMatFix[1], modelParams[i].revMatFix[2],
                                modelParams[i].revMatFix[3], modelParams[i].revMatFix[4], modelParams[i].revMatFix[5]);
                            }
                        }
                    
                    if (!strcmp(modelParams[i].nucModel,"Codon"))
                        {
                        /* what is the distribution on the nonsyn./syn. rate ratio */
                        if (!strcmp(modelParams[i].omegaVar, "Equal"))
                            {
                            if (!strcmp(modelParams[i].omegaPr,"Dirichlet"))
                                {
                                MrBayesPrint ("%s                     Nonsynonymous and synonymous rates, expressed\n", spacer);
                                MrBayesPrint ("%s                     as proportions of the rate sum, have a\n", spacer);
                                MrBayesPrint ("%s                     Dirichlet(%1.2lf,%1.2lf) prior\n", spacer, modelParams[i].omegaDir[0], modelParams[i].omegaDir[1]);
                                }
                            else
                                {
                                MrBayesPrint ("%s                     Nonsynonymous/synonymous rate ratio is fixed to %1.2lf.\n", spacer, modelParams[i].omegaFix);
                                }
                            }
                        else if (!strcmp(modelParams[i].omegaVar, "Ny98"))
                            {
                            if (!strcmp(modelParams[i].ny98omega1pr, "Beta"))
                                {
                                MrBayesPrint ("%s                     Nonsynonymous/synonymous rate ratio for purifying selection\n", spacer);
                                MrBayesPrint ("%s                     (class 1) has a Beta(%1.2lf,%1.2lf) on the interval (0,1).\n", spacer, modelParams[i].ny98omega1Beta[0], modelParams[i].ny98omega1Beta[1]);
                                }
                            else
                                {
                                MrBayesPrint ("%s                     Nonsynonymous/synonymous rate ratio for purifying selection\n", spacer);
                                MrBayesPrint ("%s                     (class 1) is fixed to %1.2lf.\n", spacer, modelParams[i].ny98omega1Fixed);
                                }
                            MrBayesPrint ("%s                     Nonsynonymous/synonymous rate ratio for neutral selection\n", spacer);
                            MrBayesPrint ("%s                     (class 2) is fixed to 1.0.\n", spacer);
                            if (!strcmp(modelParams[i].ny98omega3pr, "Uniform"))
                                {
                                MrBayesPrint ("%s                     Nonsynonymous/synonymous rate ratio for positive selection\n", spacer);
                                MrBayesPrint ("%s                     is uniformly distributed on the interval (%1.2lf,%1.2lf).\n", spacer, modelParams[i].ny98omega3Uni[0], modelParams[i].ny98omega3Uni[1]);
                                }
                            else if (!strcmp(modelParams[i].ny98omega3pr, "Exponential"))
                                {
                                MrBayesPrint ("%s                     Nonsynonymous/synonymous rate ratio for positive selection\n", spacer);
                                MrBayesPrint ("%s                     is exponentially distributed with parameter (%1.2lf).\n", spacer, modelParams[i].ny98omega3Exp);
                                }
                            else
                                {
                                MrBayesPrint ("%s                     Nonsynonymous/synonymous rate ratio for positive \n", spacer);
                                MrBayesPrint ("%s                     selection is fixed to %1.2lf.\n", spacer, modelParams[i].ny98omega3Fixed);
                                }
                            }
                        else if (!strcmp(modelParams[i].omegaVar, "M3"))
                            {
                            if (!strcmp(modelParams[i].m3omegapr, "Exponential"))
                                {
                                MrBayesPrint ("%s                     Nonsynonymous and synonymous rates for the tree classes of\n", spacer);
                                MrBayesPrint ("%s                     omega are exponentially distributed random variables.\n", spacer);
                                }
                            else if (!strcmp(modelParams[i].m3omegapr, "Fixed"))
                                {
                                MrBayesPrint ("%s                     Nonsynonymous/synonymous rate ratio for the three omega\n", spacer);
                                MrBayesPrint ("%s                     are fixed to %1.2lf, %1.2lf, and %1.2lf.\n", spacer, modelParams[i].m3omegaFixed[0], modelParams[i].m3omegaFixed[1], modelParams[i].m3omegaFixed[2]);
                                }
                            }
                        else if (!strcmp(modelParams[i].omegaVar, "M10"))
                            {
                            MrBayesPrint ("%s                     Nonsynonymous/synonymous rate ratio for purifying \n", spacer);
                            MrBayesPrint ("%s                     selection (class 1) has a Beta(alpha1,beta1) on the \n", spacer);
                            MrBayesPrint ("%s                     interval (0,1). Nonsynonymous/synonymous rate ratio \n", spacer);
                            MrBayesPrint ("%s                     for positive selection (class 2) has an offset \n", spacer);
                            MrBayesPrint ("%s                     Gamma(alpha2,beta2) on the interval (1,Infinity).\n", spacer);
                            }
                            
                        /* genetic code that is used (if nucmodel=codon) */
                        MrBayesPrint ("%s         Code      = %s\n", spacer, modelParams[i].geneticCode);
                        
                        }
                        
                    }
                /* amino acid characters in this partition */
                else if (modelSettings[i].dataType == PROTEIN)
                    {
                    if (modelParams[i].dataType == DNA || modelParams[i].dataType == RNA)
                        MrBayesPrint ("%s         Nucmodel  = %s\n", spacer, modelParams[i].nucModel);
                    /* constraints on rates of substitution in 20 X 20 matrix */
                    if (!strcmp(modelParams[i].aaModelPr, "Mixed"))
                        MrBayesPrint ("%s         Aamodel   = Mixture of models with fixed rate matrices\n", spacer);
                    else
                        MrBayesPrint ("%s         Aamodel   = %s\n", spacer, modelParams[i].aaModel);
                    /* revmat rates */
                    if (!strcmp(modelParams[i].aaModelPr, "Mixed"))
                        MrBayesPrint ("%s                     Substitution rates come from the mixture of models\n", spacer);
                    else if (!strcmp(modelParams[i].aaModelPr, "Fixed") && (!strcmp(modelParams[i].aaModel, "Poisson") ||
                                !strcmp(modelParams[i].aaModel, "Equalin")))
                        MrBayesPrint ("%s                     Substitution rates are fixed to be equal\n", spacer);
                    else if (!strcmp(modelParams[i].aaModelPr, "Fixed") && strcmp(modelParams[i].aaModel, "Gtr")!=0)
                        MrBayesPrint ("%s                     Substitution rates are fixed to the %s rates\n", spacer, modelParams[i].aaModel);
                    else if (!strcmp(modelParams[i].aaModelPr, "Fixed") && !strcmp(modelParams[i].aaModel, "Gtr"))
                        {
                        if (!strcmp(modelParams[i].aaRevMatPr,"Dirichlet"))
                            {
                            for (j=0; j<190; j++)
                                if (AreDoublesEqual(modelParams[i].aaRevMatDir[0], modelParams[i].aaRevMatDir[j], 0.00001) == NO)
                                    break;
                            if (j == 190)
                                {
                                MrBayesPrint ("%s                     Substitution rates have a Dirichlet(%1.2lf,%1.2lf,...) prior\n",
                                    spacer, modelParams[i].aaRevMatDir[0], modelParams[i].aaRevMatDir[0]);
                                }
                            else
                                {
                                MrBayesPrint ("%s                     Substitution rates have a Dirichlet(\n", spacer);
                                for (j=0; j<190; j++)
                                    {
                                    if (j % 10 == 0)
                                        MrBayesPrint ("%s                        ", spacer);
                                    MrBayesPrint ("%1.2lf", modelParams[i].aaRevMatDir[j]);
                                    if (j == 189)
                                        MrBayesPrint (") prior\n");
                                    else if ((j+1) % 10 == 0)
                                        MrBayesPrint (",\n");
                                    else
                                        MrBayesPrint (",");
                                    }
                                }
                            }
                        else /* if (!strcmp(modelParams[i].aaRevMatPr,"Fixed")) */
                            {
                            for (j=0; j<190; j++)
                                if (AreDoublesEqual(modelParams[i].aaRevMatFix[0], modelParams[i].aaRevMatFix[j], 0.00001) == NO)
                                    break;
                            if (j == 190)
                                {
                                MrBayesPrint ("%s                     Substitution rates are fixed to (%1.1lf,%1.1lf,...)\n",
                                    spacer, modelParams[i].aaRevMatFix[0], modelParams[i].aaRevMatFix[0]);
                                }
                            else
                                {
                                MrBayesPrint ("%s                     Substitution rates are fixed to (\n", spacer);
                                for (j=0; j<190; j++)
                                    {
                                    if (j % 10 == 0)
                                        MrBayesPrint ("%s                        ", spacer);
                                    MrBayesPrint ("%1.1lf", modelParams[i].aaRevMatFix[j]);
                                    if (j == 189)
                                        MrBayesPrint (") prior\n");
                                    else if ((j+1) % 10 == 0)
                                        MrBayesPrint (",\n");
                                    else
                                        MrBayesPrint (",");
                                    }
                                }
                            }
                        }
                    }
                /* restriction site or morphological characters in this partition */
                else if (modelSettings[i].dataType == RESTRICTION || modelSettings[i].dataType == STANDARD)
                    {
                    /* what type of characters are sampled? */
                    MrBayesPrint ("%s         Coding    = %s\n", spacer, modelParams[i].coding);
                    }
                    
                /* is there rate variation in a single site across the tree? */
                if (((modelSettings[i].dataType == DNA || modelSettings[i].dataType == RNA) && !strcmp(modelParams[i].nucModel, "4by4")) || modelSettings[i].dataType == PROTEIN)
                    {
                    /* do rates change on tree accoding to covarion model? */
                    MrBayesPrint ("%s         Covarion  = %s\n", spacer, modelParams[i].covarionModel);
                    if (!strcmp(modelParams[i].covarionModel, "Yes"))
                        {
                        /* distribution on switching parameters, if appropriate */
                        if (!strcmp(modelParams[i].covSwitchPr,"Uniform"))
                            {
                            MrBayesPrint ("%s                     Switching rates have independent uniform dist-\n", spacer);
                            MrBayesPrint ("%s                     ributions on the interval (%1.2lf,%1.2lf).\n", spacer, modelParams[i].covswitchUni[0], modelParams[i].covswitchUni[1]);
                            }
                        else if (!strcmp(modelParams[i].covSwitchPr,"Exponential"))
                            {
                            MrBayesPrint ("%s                     Switching rates have independent exponential\n", spacer);
                            MrBayesPrint ("%s                     distributions with parameters (%1.2lf).\n", spacer, modelParams[i].covswitchExp);
                            }
                        else
                            {
                            MrBayesPrint ("%s                     Switching rates are fixed to %1.2lf and %1.2lf.\n", spacer, modelParams[i].covswitchFix[0], modelParams[i].covswitchFix[0]);
                            }
                        ns *= 2;
                        }
                    }

                /* now, let's deal with variation in omega */
                if ((modelParams[i].dataType == DNA || modelParams[i].dataType == RNA) && !strcmp(modelParams[i].nucModel,"Codon"))
                    {
                    MrBayesPrint ("%s         Omegavar  = %s\n", spacer, modelParams[i].omegaVar);
                    if (!strcmp(modelParams[i].geneticCode, "Universal"))
                        ns = 61;
                    else if (!strcmp(modelParams[i].geneticCode, "Vertmt"))
                        ns = 60;
                    else if (!strcmp(modelParams[i].geneticCode, "Mycoplasma"))
                        ns = 62;
                    else if (!strcmp(modelParams[i].geneticCode, "Yeast"))
                        ns = 62;
                    else if (!strcmp(modelParams[i].geneticCode, "Ciliates"))
                        ns = 63;
                    else if (!strcmp(modelParams[i].geneticCode, "Metmt"))
                        ns = 62;
                    }

                /* what assumptions are made about the state frequencies? */
                if (modelParams[i].dataType != CONTINUOUS)
                    {
                    if (modelParams[i].dataType == STANDARD)
                        MrBayesPrint ("%s         # States  = Variable, up to 10\n", spacer);
                    else if (modelSettings[i].numStates != modelSettings[i].numModelStates)
                        MrBayesPrint ("%s         # States  = %d (in the model)\n", spacer, modelSettings[i].numModelStates);
                    else
                        MrBayesPrint ("%s         # States  = %d\n", spacer, ns);
                    if (modelSettings[i].dataType == STANDARD)
                        {
                        if (!strcmp(modelParams[i].symPiPr,"Fixed"))
                            {
                            if (AreDoublesEqual(modelParams[i].symBetaFix, -1.0, ETA)==YES)
                                MrBayesPrint ("%s                     State frequencies are fixed to be equal\n", spacer);
                            else
                                MrBayesPrint ("%s                     Symmetric Dirichlet is fixed to %1.2lf\n", spacer, modelParams[i].symBetaFix);
                            }
                        else if (!strcmp(modelParams[i].symPiPr,"Uniform"))
                            {
                            MrBayesPrint ("%s                     Symmetric Dirichlet has a Uniform(%1.2lf,%1.2lf) prior\n", spacer, modelParams[i].symBetaUni[0], modelParams[i].symBetaUni[1]);
                            }
                        else
                            {
                            MrBayesPrint ("%s                     Symmetric Dirichlet has a Exponential(%1.2lf) prior\n", spacer, modelParams[i].symBetaExp);
                            }
                        }
                    else if (modelSettings[i].dataType == RESTRICTION)
                        {
                        /* distribution on state frequencies for restriction site model */
                        if (!strcmp(modelParams[i].stateFreqPr,"Dirichlet"))
                            {
                            MrBayesPrint ("%s                     State frequencies have a Dirichlet (%1.2lf,%1.2lf) prior\n", spacer,
                                modelParams[i].stateFreqsDir[0], modelParams[i].stateFreqsDir[1]);
                            }
                        else if (!strcmp(modelParams[i].stateFreqPr,"Fixed") && !strcmp(modelParams[i].stateFreqsFixType,"Equal"))
                            {
                            MrBayesPrint ("%s                     State frequencies are fixed to be equal\n", spacer);
                            }
                        else if (!strcmp(modelParams[i].stateFreqPr,"Fixed") && !strcmp(modelParams[i].stateFreqsFixType,"User"))
                            {
                            MrBayesPrint ("%s                     State frequencies have been fixed by the user\n", spacer);
                            }
                        else if (!strcmp(modelParams[i].stateFreqPr,"Fixed") && !strcmp(modelParams[i].stateFreqsFixType,"Empirical"))
                            {
                            MrBayesPrint ("%s                     State frequencies have been fixed to the empirical frequencies in the data\n", spacer);
                            }
                        }
                    else if (modelSettings[i].dataType == PROTEIN)
                        {
                        /* distribution on state frequencies for aminoacid model */
                        if (!strcmp(modelParams[i].aaModelPr, "Fixed") && (strcmp(modelParams[i].aaModel, "Equalin")==0 ||
                            strcmp(modelParams[i].aaModel, "Gtr")==0))
                            {
                            if (!strcmp(modelParams[i].stateFreqPr,"Dirichlet"))
                                {
                                MrBayesPrint ("%s                     State frequencies have a Dirichlet prior\n", spacer);
                                MrBayesPrint ("%s                     (%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf,", spacer,
                                    modelParams[i].stateFreqsDir[0], modelParams[i].stateFreqsDir[1], modelParams[i].stateFreqsDir[2],
                                    modelParams[i].stateFreqsDir[3], modelParams[i].stateFreqsDir[4]);
                                MrBayesPrint ("%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf,\n",
                                    modelParams[i].stateFreqsDir[5], modelParams[i].stateFreqsDir[6], modelParams[i].stateFreqsDir[7],
                                    modelParams[i].stateFreqsDir[8], modelParams[i].stateFreqsDir[9]);
                                MrBayesPrint ("%s                     %1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf,", spacer,
                                    modelParams[i].stateFreqsDir[10], modelParams[i].stateFreqsDir[11], modelParams[i].stateFreqsDir[12],
                                    modelParams[i].stateFreqsDir[13], modelParams[i].stateFreqsDir[14]);
                                MrBayesPrint ("%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf)\n",
                                    modelParams[i].stateFreqsDir[15], modelParams[i].stateFreqsDir[16], modelParams[i].stateFreqsDir[17],
                                    modelParams[i].stateFreqsDir[18], modelParams[i].stateFreqsDir[19]);
                                }
                            else if (!strcmp(modelParams[i].stateFreqPr,"Fixed") && !strcmp(modelParams[i].stateFreqsFixType,"Equal"))
                                {
                                MrBayesPrint ("%s                     State frequencies are fixed to be equal\n", spacer);
                                }
                            else if (!strcmp(modelParams[i].stateFreqPr,"Fixed") && !strcmp(modelParams[i].stateFreqsFixType,"User"))
                                {
                                MrBayesPrint ("%s                     State frequencies have been fixed by the user\n", spacer);
                                }
                            else if (!strcmp(modelParams[i].stateFreqPr,"Fixed") && !strcmp(modelParams[i].stateFreqsFixType,"Empirical"))
                                {
                                MrBayesPrint ("%s                     State frequencies have been fixed to the empirical frequencies in the data\n", spacer);
                                }
                            }
                        else if (!strcmp(modelParams[i].aaModelPr, "Fixed") && !strcmp(modelParams[i].aaModel, "Poisson"))
                            {
                            MrBayesPrint ("%s                     State frequencies are fixed to be equal\n", spacer);
                            }
                        else if (!strcmp(modelParams[i].aaModelPr, "Fixed") && strcmp(modelParams[i].aaModel, "Equalin") && strcmp(modelParams[i].aaModel, "Poisson"))
                            {
                            MrBayesPrint ("%s                     State frequencies are fixed to the %s frequencies\n", spacer, modelParams[i].aaModel);
                            }
                        else
                            {
                            MrBayesPrint ("%s                     State frequencies come from the mixture of models\n", spacer);
                            }
                        }
                    else
                        {
                        /* distribution on state frequencies for all other models */
                        if (!strcmp(modelParams[i].stateFreqPr,"Dirichlet"))
                            {
                            MrBayesPrint ("%s                     State frequencies have a Dirichlet prior\n", spacer);
                            if (!strcmp(modelParams[i].nucModel, "Doublet"))
                                {
                                MrBayesPrint ("%s                     (%1.2lf,%1.2lf,%1.2lf,%1.2lf,\n", spacer,
                                    modelParams[i].stateFreqsDir[0], modelParams[i].stateFreqsDir[1], modelParams[i].stateFreqsDir[2],
                                    modelParams[i].stateFreqsDir[3]);
                                MrBayesPrint ("%s                     %1.2lf,%1.2lf,%1.2lf,%1.2lf,\n", spacer,
                                    modelParams[i].stateFreqsDir[4], modelParams[i].stateFreqsDir[5], modelParams[i].stateFreqsDir[6],
                                    modelParams[i].stateFreqsDir[7]);
                                MrBayesPrint ("%s                     %1.2lf,%1.2lf,%1.2lf,%1.2lf,\n", spacer,
                                    modelParams[i].stateFreqsDir[8], modelParams[i].stateFreqsDir[9], modelParams[i].stateFreqsDir[10],
                                    modelParams[i].stateFreqsDir[11]);
                                MrBayesPrint ("%s                     %1.2lf,%1.2lf,%1.2lf,%1.2lf)\n", spacer,
                                    modelParams[i].stateFreqsDir[12], modelParams[i].stateFreqsDir[13], modelParams[i].stateFreqsDir[14],
                                    modelParams[i].stateFreqsDir[15]);
                                }
                            else if (!strcmp(modelParams[i].nucModel, "4by4"))
                                {
                                MrBayesPrint ("%s                     (%1.2lf,%1.2lf,%1.2lf,%1.2lf)\n", spacer,
                                    modelParams[i].stateFreqsDir[0], modelParams[i].stateFreqsDir[1], modelParams[i].stateFreqsDir[2],
                                    modelParams[i].stateFreqsDir[3]);
                                }
                            }
                        else if (!strcmp(modelParams[i].stateFreqPr,"Fixed") && !strcmp(modelParams[i].stateFreqsFixType,"Equal"))
                            {
                            MrBayesPrint ("%s                     State frequencies are fixed to be equal\n", spacer);
                            }
                        else if (!strcmp(modelParams[i].stateFreqPr,"Fixed") && !strcmp(modelParams[i].stateFreqsFixType,"User"))
                            {
                            MrBayesPrint ("%s                     State frequencies have been fixed by the user\n", spacer);
                            }
                        else if (!strcmp(modelParams[i].stateFreqPr,"Fixed") && !strcmp(modelParams[i].stateFreqsFixType,"Empirical"))
                            {
                            MrBayesPrint ("%s                     State frequencies have been fixed to the empirical frequencies in the data\n", spacer);
                            }
                        }
                    }
                else
                    MrBayesPrint ("%s         # States  = Infinity\n", spacer);

                /* now, let's deal with rate variation across sites */
                if (modelSettings[i].dataType != CONTINUOUS)
                    {
                    if (((modelSettings[i].dataType == DNA || modelSettings[i].dataType == RNA) && strcmp(modelParams[i].nucModel,"Codon")) ||
                          modelSettings[i].dataType == PROTEIN || modelSettings[i].dataType == RESTRICTION || modelSettings[i].dataType == STANDARD)
                        {
                        if (!strcmp(modelParams[i].covarionModel, "No"))
                            MrBayesPrint ("%s         Rates     = %s\n", spacer, modelParams[i].ratesModel);
                        else
                            {
                            if (!strcmp(modelParams[i].ratesModel, "Propinv"))
                                MrBayesPrint ("%s         Rates     = Equal ", spacer);
                            else if (!strcmp(modelParams[i].ratesModel, "Invgamma"))
                                MrBayesPrint ("%s         Rates     = Gamma ", spacer);
                            else
                                MrBayesPrint ("%s         Rates     = %s ", spacer, modelParams[i].ratesModel);
                            MrBayesPrint ("(+ Propinv induced by covarion model)\n");
                            }
                        
                        if ((modelParams[i].dataType == RESTRICTION || modelParams[i].dataType == STANDARD) && !strcmp(modelParams[i].ratesModel, "Adgamma"))
                            {
                            
                            }
                        else
                            {
                            if (!strcmp(modelParams[i].ratesModel, "Gamma") || !strcmp(modelParams[i].ratesModel, "Invgamma") ||
                                !strcmp(modelParams[i].ratesModel, "LNorm") || !strcmp(modelParams[i].ratesModel, "Adgamma"))
                                {
                                /* how many categories is the continuous gamma approximated by? */
                                MrBayesPrint ("%s                     The distribution is approximated using %d categories.\n", spacer, modelParams[i].numGammaCats);
                                if (!strcmp(modelParams[i].useGibbs,"Yes"))
                                    MrBayesPrint ("%s                     Rate categories sampled using Gibbs sampling.\n", spacer, modelParams[i].numGammaCats);
                                else
                                    MrBayesPrint ("%s                     Likelihood summarized over all rate categories in each generation.\n", spacer, modelParams[i].numGammaCats);
                                /* distribution on shape parameter, if appropriate */
                                if (!strcmp(modelParams[i].shapePr,"Uniform"))
                                    {
                                    MrBayesPrint ("%s                     Shape parameter is uniformly distributed\n", spacer);
                                    MrBayesPrint ("%s                     on the interval (%1.2lf,%1.2lf).\n", spacer, modelParams[i].shapeUni[0], modelParams[i].shapeUni[1]);
                                    }
                                else if (!strcmp(modelParams[i].shapePr,"Exponential"))
                                    {
                                    MrBayesPrint ("%s                     Shape parameter is exponentially\n", spacer);
                                    MrBayesPrint ("%s                     distributed with parameter (%1.2lf).\n", spacer, modelParams[i].shapeExp);
                                    }
                                else
                                    {
                                    MrBayesPrint ("%s                     Shape parameter is fixed to %1.2lf.\n", spacer, modelParams[i].shapeFix);
                                    }
                                }
                            if ((!strcmp(modelParams[i].ratesModel, "Propinv") || !strcmp(modelParams[i].ratesModel, "Invgamma")) && !strcmp(modelParams[i].covarionModel, "No"))
                                {
                                /* distribution on pInvar parameter, if appropriate */
                                if (!strcmp(modelParams[i].pInvarPr,"Uniform"))
                                    {
                                    MrBayesPrint ("%s                     Proportion of invariable sites is uniformly dist-\n", spacer);
                                    MrBayesPrint ("%s                     ributed on the interval (%1.2lf,%1.2lf).\n", spacer, modelParams[i].pInvarUni[0], modelParams[i].pInvarUni[1]);
                                    }
                                else
                                    {
                                    MrBayesPrint ("%s                     Proportion of invariable sites is fixed to %1.2lf.\n", spacer, modelParams[i].pInvarFix);
                                    }
                                }
                            if (!strcmp(modelParams[i].ratesModel, "Adgamma"))
                                {
                                /* distribution on correlation parameter, if appropriate */
                                if (!strcmp(modelParams[i].adGammaCorPr,"Uniform"))
                                    {
                                    MrBayesPrint ("%s                     Rate correlation parameter is uniformly dist-\n", spacer);
                                    MrBayesPrint ("%s                     ributed on the interval (%1.2lf,%1.2lf).\n", spacer, modelParams[i].corrUni[0], modelParams[i].corrUni[1]);
                                    }
                                else
                                    {
                                    MrBayesPrint ("%s                     Rate correlation parameter is fixed to %1.2lf.\n", spacer, modelParams[i].corrFix);
                                    }
                                }
                            }
                        }
                    }
                }
            /* end description of discrete models */
            }

        if (i != numCurrentDivisions - 1)
            MrBayesPrint ("\n");
        
        }

    MrBayesPrint ("\n");
    ShowParameters (NO, NO, NO);
    
    return (NO_ERROR);
}


/*------------------------------------------------------------------------------
|
|   ShowMoves: Show applicable moves
|
------------------------------------------------------------------------------*/
int ShowMoves (int used)
{
    int             i, k, run, chain, chainIndex, areRunsSame, areChainsSame, numPrintedMoves;
    MCMCMove        *mv;
    
    chainIndex = 0;
    numPrintedMoves = 0;
    for (i=0; i<numApplicableMoves; i++)
        {
        mv = moves[i];
        
        for (k=0; k<numGlobalChains; k++)
            {
            if (mv->relProposalProb[k] > 0.000001)
                break;
            }

        if (k == numGlobalChains && used == YES)
            continue;

        if (k < numGlobalChains && used == NO)
            continue;

        numPrintedMoves++;
        
        /* print move number and name */
        MrBayesPrint ("%s   %4d -- Move        = %s\n", spacer, numPrintedMoves, mv->name);
        
        /* print move type */
        MrBayesPrint ("%s           Type        = %s\n", spacer, mv->moveType->name);

        /* print parameter */
        if (mv->parm->nSubParams > 0)
            MrBayesPrint ("%s           Parameters  = %s [param. %d] (%s)\n", spacer, mv->parm->name,
                mv->parm->index+1, mv->parm->paramTypeName);
        else
            MrBayesPrint ("%s           Parameter   = %s [param. %d] (%s)\n", spacer, mv->parm->name,
                mv->parm->index+1, mv->parm->paramTypeName);
        for (k=0; k<mv->parm->nSubParams; k++)
            MrBayesPrint ("%s                         %s [param. %d] (%s)\n", spacer, mv->parm->subParams[k]->name,
                mv->parm->subParams[k]->index+1, mv->parm->subParams[k]->paramTypeName);

        /* print tuning parameters */
        for (k=0; k<mv->moveType->numTuningParams; k++)
            {
            if (k==0)
                MrBayesPrint ("%s           Tuningparam = %s (%s)\n", spacer, mv->moveType->shortTuningName[k], mv->moveType->tuningName[k]);
            else
                MrBayesPrint ("%s                         %s (%s)\n", spacer, mv->moveType->shortTuningName[k], mv->moveType->tuningName[k]);
            }
        
        /* loop over tuning parameters */
        for (k=0; k<mv->moveType->numTuningParams; k++)
            {
            /* find if tuning parameters are different for different runs */
            areRunsSame = YES;
            for (run=1; run<chainParams.numRuns; run++)
                {
                for (chain=0; chain<chainParams.numChains; chain++)
                    {
                    chainIndex = run*chainParams.numChains + chain;
                    if (AreDoublesEqual (mv->tuningParam[chainIndex][k], mv->tuningParam[chain][k], 0.000001) == NO)
                        {
                        areRunsSame = NO;
                        break;
                        }
                    }
                if (areRunsSame == NO)
                    break;
                }
        
            /* now print values */
            for (run=0; run<chainParams.numRuns; run++)
                {
                if (areRunsSame == YES && run >= 1)
                    break;

                /* find out if chains are different within this run */
                areChainsSame = YES;
                for (chain=1; chain<chainParams.numChains; chain++)
                    {
                    chainIndex = run*chainParams.numChains + chain;
                    if (AreDoublesEqual (mv->tuningParam[chainIndex][k], mv->tuningParam[chainIndex-chain][k],0.000001) == NO)
                        {
                        areChainsSame = NO;
                        break;
                        }
                    }
                /* now we can print the values */
                for (chain=0; chain<chainParams.numChains; chain++)
                    {
                    chainIndex = run*chainParams.numChains + chain;
                    if (areChainsSame == YES && chain >= 1)
                        break;
                    
                    if (run == 0 && chain == 0)
                        MrBayesPrint ("%s%22s = %1.3lf", spacer, mv->moveType->shortTuningName[k], mv->tuningParam[chainIndex][k]);
                    else
                        MrBayesPrint ("%s                         %1.3lf", spacer, mv->tuningParam[chainIndex][k]);

                    if (areChainsSame == NO && areRunsSame == YES)
                        MrBayesPrint ("  [chain %d]\n", chain+1);
                    else if (areChainsSame == YES && areRunsSame == NO)
                        MrBayesPrint ("  [run %d]\n", run+1);
                    else if (areChainsSame == NO && areRunsSame == NO)
                        MrBayesPrint ("  [run %d, chain %d]\n", run+1, chain+1);
                    else
                        MrBayesPrint ("\n");
                    }
                }
            }   /* next tuning parameter */

        /* print target acceptance rate for autotuning */
        if (mv->moveType->targetRate > 0.0 && mv->moveType->targetRate < 1.0)
            {

            /* first find out if the targets are different in different runs */         
            areRunsSame = YES;
            for (run=1; run<chainParams.numRuns; run++)
                {
                for (chain=0; chain<chainParams.numChains; chain++)
                    {
                    chainIndex = run*chainParams.numChains + chain;
                    if (AreDoublesEqual (mv->targetRate[chainIndex], mv->targetRate[chain], 0.000001) == NO)
                        {
                        areRunsSame = NO;
                        break;
                        }
                    }
                if (areRunsSame == NO)
                    break;
                }
        
            /* now print values */
            for (run=0; run<chainParams.numRuns; run++)
                {
                if (areRunsSame == YES && run >= 1)
                    break;

                /* find out if chains are different within this run */
                areChainsSame = YES;
                for (chain=1; chain<chainParams.numChains; chain++)
                    {
                    chainIndex = run*chainParams.numChains + chain;
                    if (AreDoublesEqual (mv->targetRate[chainIndex], mv->targetRate[chainIndex-chain], 0.000001) == NO)
                        {
                        areChainsSame = NO;
                        break;
                        }
                    }
                /* now we can print the values */
                for (chain=0; chain<chainParams.numChains; chain++)
                    {
                    chainIndex = run*chainParams.numChains + chain;
                    if (areChainsSame == YES && chain >= 1)
                        break;
                    
                    if (run == 0 && chain == 0)
                        MrBayesPrint ("%s           Targetrate  = %1.3lf", spacer, mv->targetRate[chainIndex]);
                    else
                        MrBayesPrint ("%s                         %1.3lf", spacer, mv->targetRate[chainIndex]);

                    if (areChainsSame == NO && areRunsSame == YES)
                        MrBayesPrint ("  [chain %d]\n", chain+1);
                    else if (areChainsSame == YES && areRunsSame == NO)
                        MrBayesPrint ("  [run %d]\n", run+1);
                    else if (areChainsSame == NO && areRunsSame == NO)
                        MrBayesPrint ("  [run %d, chain %d]\n", run+1, chain+1);
                    else
                        MrBayesPrint ("\n");
                    }
                }
            }

        
        /* finally print the relative proposal probability */
        
        /* first find out if the probabilities are different in different runs */           
        areRunsSame = YES;
        for (run=1; run<chainParams.numRuns; run++)
            {
            for (chain=0; chain<chainParams.numChains; chain++)
                {
                chainIndex = run*chainParams.numChains + chain;
                if (AreDoublesEqual (mv->relProposalProb[chainIndex], mv->relProposalProb[chain], 0.000001) == NO)
                    {
                    areRunsSame = NO;
                    break;
                    }
                }
            if (areRunsSame == NO)
                break;
            }
    
        /* now print values */
        for (run=0; run<chainParams.numRuns; run++)
            {
            if (areRunsSame == YES && run >= 1)
                break;

            /* find out if chains are different within this run */
            areChainsSame = YES;
            for (chain=1; chain<chainParams.numChains; chain++)
                {
                chainIndex = run*chainParams.numChains + chain;
                if (AreDoublesEqual (mv->relProposalProb[chainIndex], mv->relProposalProb[chainIndex-chain], 0.000001) == NO)
                    {
                    areChainsSame = NO;
                    break;
                    }
                }
            /* now we can print the values */
            for (chain=0; chain<chainParams.numChains; chain++)
                {
                chainIndex = run*chainParams.numChains + chain;
                if (areChainsSame == YES && chain >= 1)
                    break;
                
                if (run == 0 && chain == 0)
                    MrBayesPrint ("%s           Rel. prob.  = %1.1lf", spacer, mv->relProposalProb[chainIndex]);
                else
                    MrBayesPrint ("%s                         %1.1lf", spacer, mv->relProposalProb[chainIndex]);

                if (areChainsSame == NO && areRunsSame == YES)
                    MrBayesPrint ("  [chain %d]\n", chain+1);
                else if (areChainsSame == YES && areRunsSame == NO)
                    MrBayesPrint ("  [run %d]\n", run+1);
                else if (areChainsSame == NO && areRunsSame == NO)
                    MrBayesPrint ("  [run %d, chain %d]\n", run+1, chain+1);
                else
                    MrBayesPrint ("\n");
                }
            }
        MrBayesPrint ("\n");
        }   /* next move */
        
    if (numPrintedMoves == 0)
        {
        if (used == YES)
            {
            MrBayesPrint ("%s      No moves currently used for this analysis. All parameters\n", spacer);
            MrBayesPrint ("%s      will be fixed to their starting values.\n\n", spacer);
            }
        else
            {
            MrBayesPrint ("%s      No additional moves available for this model.\n\n", spacer);
            }
        }

    return (NO_ERROR);
}


/*------------------------------------------------------------------------------
|
|   ShowParameters: Show parameter table and parameter info
|
------------------------------------------------------------------------------*/
int ShowParameters (int showStartVals, int showMoves, int showAllAvailable)
{
    int             a, b, d, i, j, k, m, n, run, chain, shouldPrint, isSame, areRunsSame, areChainsSame, nValues,
                    chainIndex, refIndex, numPrinted, numMovedChains, printedCol, screenWidth=100;
    Param           *p;
    Model           *mp;
    ModelInfo       *ms;
    MrBFlt          *value, *refValue, *subValue;
    MCMCMove        *mv;
    
    MrBayesPrint ("%s   Active parameters: \n\n", spacer);
    if (numCurrentDivisions > 1)
        { 
        MrBayesPrint ("%s                          Partition(s)\n", spacer);
        MrBayesPrint ("%s      Parameters        ", spacer);
        for (i=0; i<numCurrentDivisions; i++)
            MrBayesPrint (" %2d", i+1);
        MrBayesPrint ("\n");
        MrBayesPrint ("%s      ------------------", spacer);
        for (i=0; i<numCurrentDivisions; i++)
            MrBayesPrint ("---");
        MrBayesPrint ("\n");
        }
    else
        {
        MrBayesPrint ("%s      Parameters\n", spacer);
        MrBayesPrint ("%s      ---------------------\n", spacer);
        }
    for (j=0; j<NUM_LINKED; j++)
        {
        shouldPrint = NO;
        for (i=0; i<numCurrentDivisions; i++)
            {
            if (activeParams[j][i] == -1)
                {}
            else
                shouldPrint = YES;
            }
        if (shouldPrint == NO)
            continue;
        
        if (j == P_TRATIO)
            {
            MrBayesPrint ("%s      Tratio            ", spacer);
            }
        else if (j == P_REVMAT)
            {
            MrBayesPrint ("%s      Revmat            ", spacer);
            }
        else if (j == P_OMEGA)
            {
            MrBayesPrint ("%s      Omega             ", spacer);
            }
        else if (j == P_PI)
            {
            MrBayesPrint ("%s      Statefreq         ", spacer);
            }
        else if (j == P_SHAPE)
            {
            MrBayesPrint ("%s      Shape             ", spacer);
            }
        else if (j == P_PINVAR)
            {
            MrBayesPrint ("%s      Pinvar            ", spacer);
            }
        else if (j == P_CORREL)
            {
            MrBayesPrint ("%s      Correlation       ", spacer);
            }
        else if (j == P_SWITCH)
            {
            MrBayesPrint ("%s      Switchrates       ", spacer);
            }
        else if (j == P_RATEMULT)
            {
            MrBayesPrint ("%s      Ratemultiplier    ", spacer);
            }
        else if (j == P_GENETREERATE)
            {
            MrBayesPrint ("%s      Generatemult      ", spacer);
            }
        else if (j == P_TOPOLOGY)
            {
            MrBayesPrint ("%s      Topology          ", spacer);
            }
        else if (j == P_BRLENS)
            {
            MrBayesPrint ("%s      Brlens            ", spacer);
            }
        else if (j == P_SPECRATE)
            {
            MrBayesPrint ("%s      Speciationrate    ", spacer);
            }
        else if (j == P_EXTRATE)
            {
            MrBayesPrint ("%s      Extinctionrate    ", spacer);
            }
        else if (j == P_FOSLRATE)
            {
            MrBayesPrint ("%s      Fossilizationrate ", spacer);
            }
        else if (j == P_POPSIZE)
            {
            MrBayesPrint ("%s      Popsize           ", spacer);
            }
        else if (j == P_GROWTH)
            {
            MrBayesPrint ("%s      Growthrate        ", spacer);
            } 
        else if (j == P_AAMODEL)
            {
            MrBayesPrint ("%s      Aamodel           ", spacer);
            }
        else if (j == P_BRCORR)
            {
            MrBayesPrint ("%s      Brownian corr.    ", spacer);
            }
        else if (j == P_BRSIGMA)
            {
            MrBayesPrint ("%s      Brownian sigma    ", spacer);
            }
        else if (j == P_CPPRATE)
            {
            MrBayesPrint ("%s      Cpprate           ", spacer);
            }
        else if (j == P_CPPMULTDEV)
            {
            MrBayesPrint ("%s      Cppmultdev        ", spacer);
            }
        else if (j == P_CPPEVENTS)
            {
            MrBayesPrint ("%s      Cppevents         ", spacer);
            }
        else if (j == P_TK02VAR)
            {
            MrBayesPrint ("%s      TK02var           ", spacer);
            }
        else if (j == P_TK02BRANCHRATES)
            {
            MrBayesPrint ("%s      TK02branchrates   ", spacer);
            }
        else if (j == P_IGRVAR)
            {
            MrBayesPrint ("%s      Igrvar            ", spacer);
            }
        else if (j == P_IGRBRANCHRATES)
            {
            MrBayesPrint ("%s      Igrbranchrates    ", spacer);
            }
        else if (j == P_MIXEDVAR)
            {
            MrBayesPrint ("%s      Mixedvar          ", spacer);
            }
        else if (j == P_MIXEDBRCHRATES)
            {
            MrBayesPrint ("%s      Mixedbranchrates  ", spacer);
            }
        else if (j == P_CLOCKRATE)
            {
            MrBayesPrint ("%s      Clockrate         ", spacer);
            }
        else if (j == P_SPECIESTREE)
            {
            MrBayesPrint ("%s      Speciestree       ", spacer);
            }
        else
            {
            MrBayesPrint ("%s      ERROR: Someone forgot to name parameter type %d", spacer, j);
            return (ERROR);
            }
        
        for (i=0; i<numCurrentDivisions; i++)
            {
            if (activeParams[j][i] == -1)
                MrBayesPrint ("  .");
            else
                MrBayesPrint (" %2d", activeParams[j][i]);
            }
        MrBayesPrint ("\n");
        }
    if (numCurrentDivisions > 1)
        { 
        MrBayesPrint ("%s      ------------------", spacer);
        for (i=0; i<numCurrentDivisions; i++)
            MrBayesPrint ("---");
        MrBayesPrint ("\n");
        }
    else
        {
        MrBayesPrint ("%s      ---------------------\n", spacer);
        }
    
    MrBayesPrint ("\n");
    
    if (numCurrentDivisions > 1)
        MrBayesPrint ("%s      Parameters can be linked or unlinked across partitions using 'link' and 'unlink'\n\n", spacer);
    
    for (i=0; i<numParams; i++)
        {
        p = &params[i];
        j = p->paramType;
        
        mp = &modelParams[p->relParts[0]];
        ms = &modelSettings[p->relParts[0]];
        
        /* print parameter number and name */
        MrBayesPrint ("%s   %4d --  Parameter  = %s\n", spacer, i+1, p->name);
        MrBayesPrint ("%s            Type       = %s\n", spacer, p->paramTypeName);
        /* print prior */
        if (j == P_TRATIO)
            {
            if (!strcmp(mp->tRatioPr,"Beta"))
                MrBayesPrint ("%s            Prior      = Beta(%1.2lf,%1.2lf)\n", spacer, mp->tRatioDir[0], modelParams[i].tRatioDir[1]);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->tRatioFix);
            }
        else if (j == P_REVMAT)
            {
            if (ms->numModelStates != 20)
                {
                if (!strcmp(mp->nst,"Mixed"))
                    {
                    MrBayesPrint ("%s            Prior      = All GTR submodels have equal probability\n", spacer); 
                    MrBayesPrint ("%s                         All revmat rates have a Symmetric Dirichlet(%1.2lf) prior\n", spacer, mp->revMatSymDir);
                    }
                else if (!strcmp(mp->revMatPr,"Dirichlet"))
                    {
                    MrBayesPrint ("%s            Prior      = Dirichlet(%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf)\n", spacer, 
                    mp->revMatDir[0], mp->revMatDir[1], mp->revMatDir[2],
                    mp->revMatDir[3], mp->revMatDir[4], mp->revMatDir[5]);
                    }
                else
                    MrBayesPrint ("%s            Prior      = Fixed(%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf,%1.2lf)\n", spacer, 
                    mp->revMatFix[0], mp->revMatFix[1], mp->revMatFix[2],
                    mp->revMatFix[3], mp->revMatFix[4], mp->revMatFix[5]);
                }
            else if (ms->numModelStates == 20)
                {
                if (!strcmp(mp->aaRevMatPr,"Dirichlet"))
                    MrBayesPrint ("%s            Prior      = Dirichlet\n", spacer);
                else
                    MrBayesPrint ("%s            Prior      = Fixed(user-specified)\n", spacer);
                }
            }
        else if (j == P_OMEGA)
            {
            if (!strcmp(mp->omegaVar,"Equal"))
                {
                if (!strcmp(mp->omegaPr,"Dirichlet"))
                    MrBayesPrint ("%s            Prior      = Dirichlet(%1.2lf,%1.2lf)\n", spacer, mp->omegaDir[0], mp->omegaDir[1]);
                else
                    MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->omegaFix);
                }
            else if (!strcmp(mp->omegaVar,"Ny98"))
                {
                if (!strcmp(mp->ny98omega1pr,"Beta"))
                    MrBayesPrint ("%s            Prior      = Beta(%1.2lf,%1.2lf) on omega(1)\n", spacer, mp->ny98omega1Beta[0], mp->ny98omega1Beta[1]);
                else
                    MrBayesPrint ("%s            Prior      = Fixed(%1.2lf) on omega(1)\n", spacer, mp->ny98omega1Fixed);
                MrBayesPrint ("%s                         Fixed(1.00) on omega(2)\n", spacer);
                if (!strcmp(mp->ny98omega3pr,"Uniform"))
                    MrBayesPrint ("%s                         Uniform(%1.2lf,%1.2lf) on omega(3)\n", spacer, mp->ny98omega3Uni[0], mp->ny98omega3Uni[1]);
                else if (!strcmp(mp->ny98omega3pr,"Exponential"))
                    MrBayesPrint ("%s                         Exponential(%1.2lf) on omega(3)\n", spacer, mp->ny98omega3Exp);
                else
                    MrBayesPrint ("%s                         Fixed(%1.2lf) on omega(3)\n", spacer, mp->ny98omega3Fixed);
                if (!strcmp(mp->codonCatFreqPr,"Dirichlet"))
                    MrBayesPrint ("%s                         Dirichlet(%1.2lf,%1.2lf,%1.2lf) on pi(-), pi(N), and pi(+)\n", spacer, mp->codonCatDir[0], mp->codonCatDir[1], mp->codonCatDir[2]);
                else
                    MrBayesPrint ("%s                         Fixed(%1.2lf,%1.2lf,%1.2lf) on pi(-), pi(N), and pi(+)\n", spacer, mp->codonCatFreqFix[0], mp->codonCatFreqFix[1], mp->codonCatFreqFix[2]);
                }
            else if (!strcmp(mp->omegaVar,"M3"))
                {
                if (!strcmp(mp->m3omegapr,"Exponential"))
                    MrBayesPrint ("%s                         dN1, dN2, dN3, and dS are all exponential random variables\n", spacer);
                else
                    MrBayesPrint ("%s                         Fixed(%1.2lf,%1.2lf,%1.2lf) for the three selection categories\n", spacer, mp->m3omegaFixed[0], mp->m3omegaFixed[1], mp->m3omegaFixed[2]);
                if (!strcmp(mp->codonCatFreqPr,"Dirichlet"))
                    MrBayesPrint ("%s                         Dirichlet(%1.2lf,%1.2lf,%1.2lf) on pi(1), pi(2), and pi(3)\n", spacer, mp->codonCatDir[0], mp->codonCatDir[1], mp->codonCatDir[2]);
                else
                    MrBayesPrint ("%s                         Fixed(%1.2lf,%1.2lf,%1.2lf) on pi(1), pi(2), and pi(3)\n", spacer, mp->codonCatFreqFix[0], mp->codonCatFreqFix[1], mp->codonCatFreqFix[2]);
                }
            else if (!strcmp(mp->omegaVar,"M10"))
                {
                MrBayesPrint ("%s                         With probability pi(1), omega is drawn from a Beta(alpha1,beta1) \n", spacer);
                MrBayesPrint ("%s                         distribution and with probability pi(2), omega is drawn from\n", spacer);
                MrBayesPrint ("%s                         a Gamma(alpha2,beta2) distribution.\n", spacer);
                if (!strcmp(mp->m10betapr,"Uniform"))
                    {
                    MrBayesPrint ("%s                         The parameters of the beta distribution each follow \n", spacer);
                    MrBayesPrint ("%s                         independent Uniform(%1.2lf,%1.2lf) priors\n", spacer, mp->m10betaUni[0], mp->m10betaUni[1]);
                    }
                else if (!strcmp(mp->m10betapr,"Exponential"))
                    {
                    MrBayesPrint ("%s                         The parameters of the beta distribution each follow \n", spacer);
                    MrBayesPrint ("%s                         independent Exponential(%1.2lf) priors\n", spacer, mp->m10betaExp);
                    }
                else
                    {
                    MrBayesPrint ("%s                         The parameters of the beta distribution are fixed to \n", spacer);
                    MrBayesPrint ("%s                         %1.2lf and %1.2lf\n", spacer, mp->m10betaFix[0], mp->m10betaFix[0]);
                    }

                if (!strcmp(mp->m10gammapr,"Uniform"))
                    {
                    MrBayesPrint ("%s                         The parameters of the gamma distribution each follow  \n", spacer);
                    MrBayesPrint ("%s                         independent Uniform(%1.2lf,%1.2lf) priors\n", spacer, mp->m10gammaUni[0], mp->m10gammaUni[1]);
                    }
                else if (!strcmp(mp->m10gammapr,"Exponential"))
                    {
                    MrBayesPrint ("%s                         The parameters of the gamma distribution each follow \n", spacer);
                    MrBayesPrint ("%s                         independent Exponential(%1.2lf) priors\n", spacer, mp->m10gammaExp);
                    }
                else
                    {
                    MrBayesPrint ("%s                         The parameters of the gamma distribution are fixed to \n", spacer);
                    MrBayesPrint ("%s                         %1.2lf and %1.2lf\n", spacer, mp->m10gammaFix[0], mp->m10gammaFix[0]);
                    }

                if (!strcmp(mp->codonCatFreqPr,"Dirichlet"))
                    MrBayesPrint ("%s                         Dirichlet(%1.2lf,%1.2lf) on pi(1) and pi(2)\n", spacer, mp->codonCatDir[0], mp->codonCatDir[1]);
                else
                    MrBayesPrint ("%s                         Fixed(%1.2lf,%1.2lf) on pi(1) and pi(2)\n", spacer, mp->codonCatFreqFix[0], mp->codonCatFreqFix[1]);
                }
            }
        else if (j == P_PI)
            {
            if (ms->dataType == STANDARD)
                {
                if (!strcmp(mp->symPiPr, "Uniform"))
                    MrBayesPrint ("%s            Prior      = Symmetric dirichlet with uniform(%1.2lf,%1.2lf) variance parameter\n", spacer, mp->symBetaUni[0], mp->symBetaUni[1]);
                else if (!strcmp(mp->symPiPr, "Exponential"))
                    MrBayesPrint ("%s            Prior      = Symmetric dirichlet with exponential(%1.2lf) variance parameter\n", spacer, mp->symBetaExp);
                else
                    { /* mp->symBetaFix == -1 */
                    if (AreDoublesEqual(mp->symBetaFix, 1.0, ETA)==YES)
                        MrBayesPrint ("%s            Prior      = State frequencies are equal\n", spacer);
                    else
                        MrBayesPrint ("%s            Prior      = Symmetric dirichlet with fixed(%1.2lf) variance parameter\n", spacer, mp->symBetaFix);
                    }
                }
            else if (ms->dataType == PROTEIN)
                {
                if (!strcmp(mp->aaModelPr, "Fixed") && (!strcmp(mp->aaModel, "Equalin") || !strcmp(mp->aaModel, "Gtr")))
                    {
                    if (!strcmp(mp->stateFreqPr,"Dirichlet"))
                        {
                        MrBayesPrint ("%s            Prior      = Dirichlet\n", spacer);
                        }
                    else if (!strcmp(mp->stateFreqPr,"Fixed") && !strcmp(mp->stateFreqsFixType,"Equal"))
                        {
                        MrBayesPrint ("%s            Prior      = Fixed (equal frequencies)\n", spacer);
                        }
                    else if (!strcmp(mp->stateFreqPr,"Fixed") && !strcmp(mp->stateFreqsFixType,"User"))
                        {
                        MrBayesPrint ("%s            Prior      = Fixed (user-specified)\n", spacer);
                        }
                    else if (!strcmp(mp->stateFreqPr,"Fixed") && !strcmp(mp->stateFreqsFixType,"Empirical"))
                        {
                        MrBayesPrint ("%s            Prior      = Fixed (empirical frequencies)\n", spacer);
                        }
                    }
                else if (!strcmp(mp->aaModelPr, "Fixed") && !strcmp(mp->aaModel, "Poisson"))
                    {
                    MrBayesPrint ("%s            Prior      = Fixed (equal frequencies)\n", spacer);
                    }
                else if (!strcmp(mp->aaModelPr, "Fixed") && strcmp(mp->aaModel, "Equalin") && strcmp(mp->aaModel, "Poisson"))
                    {
                    MrBayesPrint ("%s            Prior      = Fixed (%s frequencies)\n", spacer, mp->aaModel);
                    }
                else
                    {
                    MrBayesPrint ("%s            Prior      = Fixed (from mixture of models)\n", spacer);
                    }
                }
            else
                {
                if (!strcmp(mp->stateFreqPr,"Dirichlet"))
                    MrBayesPrint ("%s            Prior      = Dirichlet\n", spacer);
                else
                    MrBayesPrint ("%s            Prior      = Fixed\n", spacer);
                }
            }
        else if (j == P_SHAPE)
            {
            if (!strcmp(mp->shapePr,"Uniform"))
                MrBayesPrint ("%s            Prior      = Uniform(%1.2lf,%1.2lf)\n", spacer, mp->shapeUni[0], mp->shapeUni[1]);
            else if (!strcmp(mp->shapePr,"Exponential"))
                MrBayesPrint ("%s            Prior      = Exponential(%1.2lf)\n", spacer, mp->shapeExp);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->shapeFix);
            }
        else if (j == P_PINVAR)
            {
            if (!strcmp(mp->pInvarPr,"Uniform"))
                MrBayesPrint ("%s            Prior      = Uniform(%1.2lf,%1.2lf)\n", spacer, mp->pInvarUni[0], mp->pInvarUni[1]);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->pInvarFix);
            }
        else if (j == P_CORREL)
            {
            if (!strcmp(mp->adGammaCorPr,"Uniform"))
                MrBayesPrint ("%s            Prior      = Uniform(%1.2lf,%1.2lf)\n", spacer, mp->corrUni[0], mp->corrUni[1]);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->corrFix);
            }
        else if (j == P_SWITCH)
            {
            if (!strcmp(mp->covSwitchPr,"Uniform"))
                MrBayesPrint ("%s            Prior      = Uniform(%1.2lf,%1.2lf)\n", spacer, mp->covswitchUni[0], mp->covswitchUni[1]);
            else if (!strcmp(mp->covSwitchPr,"Exponential"))
                MrBayesPrint ("%s            Prior      = Exponential(%1.2lf)\n", spacer, mp->covswitchExp);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf,%1.2lf)\n", spacer, mp->covswitchFix[0], mp->covswitchFix[1]);
            }
        else if (j == P_RATEMULT)
            {
            if (!strcmp(mp->ratePr,"Fixed"))
                MrBayesPrint ("%s            Prior      = Fixed(1.0)\n", spacer);
            else
                {
                MrBayesPrint ("%s            Prior      = Dirichlet(", spacer);
                for (d=n=0; d<numCurrentDivisions; d++)
                    {
                    if (activeParams[j][d] == i+1)
                        n++;
                    }
                for (d=m=0; d<numCurrentDivisions; d++)
                    {
                    if (activeParams[j][d] == i+1)
                        {
                        m++;
                        if (m < n)
                            MrBayesPrint ("%1.2lf,", modelParams[d].ratePrDir);
                        else
                            MrBayesPrint ("%1.2lf)\n", modelParams[d].ratePrDir);
                        }
                    }
                }
            }
        else if (j == P_GENETREERATE)
            {
            if (!strcmp(mp->generatePr,"Fixed"))
                MrBayesPrint ("%s            Prior      = Fixed(1.0)\n", spacer);
            else
                {
                MrBayesPrint ("%s            Prior      = Dirichlet(", spacer);
                printedCol = (int)(strlen(spacer)) + 25 + 10;
                for (n=0; n<numTrees-1; n++)
                    {
                    if (printedCol + 5 > screenWidth)
                        {
                        MrBayesPrint("\n%s                                   ", spacer);
                        printedCol = (int)(strlen(spacer)) + 25 + 10;
                        }
                    if (n == numTrees-2)
                        MrBayesPrint ("1.00)\n");
                    else
                        MrBayesPrint ("1.00,");
                    printedCol += 5;
                    }
                }
            }
        else if (j == P_TOPOLOGY)
            {
            if (!strcmp(mp->topologyPr,"Uniform"))
                MrBayesPrint ("%s            Prior      = All topologies equally probable a priori\n", spacer);
            else if (!strcmp(mp->topologyPr,"Speciestree"))
                MrBayesPrint ("%s            Prior      = Topology constrained to fold within species tree\n", spacer);
            else if (!strcmp(mp->topologyPr,"Constraints"))
                MrBayesPrint ("%s            Prior      = Prior on topologies obeys constraints\n", spacer);
            else
                MrBayesPrint ("%s            Prior      = Prior is fixed to the topology of user tree '%s'\n", spacer,
                                                    userTree[mp->topologyFix]->name);
            }
        else if (j == P_BRLENS)
            {
            if (!strcmp(mp->parsModel, "Yes"))
                MrBayesPrint ("%s            Prior      = Reconstructed using parsimony\n", spacer);
            else
                {
                if (!strcmp(mp->brlensPr,"Unconstrained"))
                    {
                    MrBayesPrint ("%s            Prior      = Unconstrained:%s", spacer, mp->unconstrainedPr);
                    if (!strcmp(mp->unconstrainedPr, "Uniform"))
                        MrBayesPrint ("(%1.1lf,%1.1lf)\n", mp->brlensUni[0], mp->brlensUni[1]);
                    else if (!strcmp(mp->unconstrainedPr, "Exponential"))
                        MrBayesPrint ("(%1.1lf)\n", mp->brlensExp);
                    else if (!strcmp(mp->unconstrainedPr, "twoExp"))
                        MrBayesPrint ("(%1.1lf,%1.1lf)\n", mp->brlens2Exp[0], mp->brlens2Exp[1]);
                    else
                        MrBayesPrint ("(%1.1lf,%1.4lf,%1.1lf,%1.1lf)\n", mp->brlensDir[0], mp->brlensDir[1], mp->brlensDir[2], mp->brlensDir[3]);
                    }
                else if (!strcmp(mp->brlensPr, "Clock"))
                    {
                    MrBayesPrint ("%s            Prior      = Clock:%s\n", spacer, mp->clockPr);
                    if ((!strcmp(mp->clockPr,"Uniform") || !strcmp(mp->clockPr,"Fossilization")) && !strcmp(mp->nodeAgePr,"Unconstrained"))
                        {
                        MrBayesPrint ("%s                         Tree age has a %s distribution\n", spacer, mp->treeAgePr.name);
                        }
                    else if (!strcmp(mp->clockPr, "Birthdeath") && !strcmp(mp->nodeAgePr,"Unconstrained"))
                        {
                        MrBayesPrint ("%s                         Tree age has a Uniform(0,infinity) distribution\n", spacer);
                        }
                    if (!strcmp(mp->nodeAgePr,"Calibrated"))
                        {
                        b = 0;
                        for (a=0; a<numTaxa; a++)
                            {
                            if (taxaInfo[a].isDeleted == NO && tipCalibration[a].prior != unconstrained)
                                b++;
                            }
                        for (a=0; a<numDefinedConstraints; a++)
                            {
                            if (mp->activeConstraints[a] == YES && nodeCalibration[a].prior != unconstrained)
                                b++;
                            }
                        if (b > 1)
                            MrBayesPrint ("%s                         Node depths are constrained by the following age constraints:\n", spacer);
                        else
                            MrBayesPrint ("%s                         Node depths are calibrated by the following age constraint:\n", spacer);
                        for (a=0; a<numTaxa; a++)
                            {
                            if (taxaInfo[a].isDeleted == NO && tipCalibration[a].prior != unconstrained)
                                {
                                MrBayesPrint ("%s                         -- The age of terminal \"%s\" is %s\n", spacer, taxaNames[a],
                                    tipCalibration[a].name);
                                }
                            }
                        for (a=b=0; a<numDefinedConstraints; a++)
                            {
                            if (mp->activeConstraints[a] == YES && nodeCalibration[a].prior != unconstrained)
                                {
                                MrBayesPrint ("%s                         -- The age of node '%s' is %s\n", spacer,
                                    constraintNames[a], nodeCalibration[a].name);
                                for (k=0; k<numTaxa; k++)
                                    if (taxaInfo[k].isDeleted == NO && IsBitSet(k,definedConstraint[a]) == NO)
                                        break;
                                if (k == numTaxa)
                                    b = 1;          /* root is calibrated */
                                }
                            }
                        if (b == 0) /* we need to use default calibration for root for uniform and birthdeath */
                            {
                            if (!strcmp(mp->clockPr,"Uniform") || !strcmp(mp->clockPr,"Fossilization"))
                                {
                                MrBayesPrint ("%s                         -- Tree age has a %s distribution\n", spacer, mp->treeAgePr.name);
                                }
                            else if (!strcmp(mp->clockPr,"Birthdeath"))
                                {
                                MrBayesPrint ("%s                         -- Tree age has a Uniform(0,infinity) distribution\n", spacer);
                                }
                            }
                        }
                    else
                        MrBayesPrint ("%s                         Node ages are not constrained\n", spacer);
                    }
                else
                    {
                    assert (!strcmp(mp->brlensPr, "Fixed"));
                    MrBayesPrint ("%s            Prior      = Fixed, branch lengths are fixed to the ones of the user tree '%s'\n", spacer,
                                                    userTree[mp->topologyFix]->name);
                    }
                }
            }
        else if (j == P_SPECRATE)
            {
            if (!strcmp(mp->speciationPr,"Uniform"))
                MrBayesPrint ("%s            Prior      = Uniform(%1.2lf,%1.2lf)\n", spacer, mp->speciationUni[0], mp->speciationUni[1]);
            else if (!strcmp(mp->speciationPr,"Exponential"))
                MrBayesPrint ("%s            Prior      = Exponential(%1.2lf)\n", spacer, mp->speciationExp);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->speciationFix);
            }
        else if (j == P_EXTRATE)
            {
            if (!strcmp(mp->extinctionPr,"Beta"))
                MrBayesPrint ("%s            Prior      = Beta(%1.2lf,%1.2lf)\n", spacer, mp->extinctionBeta[0], mp->extinctionBeta[1]);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->extinctionFix);
            }
        else if (j == P_FOSLRATE)
            {
            if (!strcmp(mp->fossilizationPr,"Beta"))
                MrBayesPrint ("%s            Prior      = Beta(%1.2lf,%1.2lf)\n", spacer, mp->fossilizationBeta[0], mp->fossilizationBeta[1]);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->fossilizationFix);
            }
        else if (j == P_POPSIZE)
            {
            if (!strcmp(mp->popSizePr,"Uniform"))
                MrBayesPrint ("%s            Prior      = Uniform(%1.2lf,%1.2lf)\n", spacer, mp->popSizeUni[0], mp->popSizeUni[1]);
            else if (!strcmp(mp->popSizePr,"Lognormal"))
                MrBayesPrint ("%s            Prior      = Lognormal(%1.2lf,%1.2lf)\n", spacer, mp->popSizeLognormal[0], mp->popSizeLognormal[1]);
            else if (!strcmp(mp->popSizePr,"Normal"))
                MrBayesPrint ("%s            Prior      = Truncated Normal(%1.2lf,%1.2lf)\n", spacer, mp->popSizeNormal[0], mp->popSizeNormal[1]);
            else if (!strcmp(mp->popSizePr,"Gamma"))
                MrBayesPrint ("%s            Prior      = Gamma(%1.2lf,%1.2lf)\n", spacer, mp->popSizeGamma[0], mp->popSizeGamma[1]);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.5lf)\n", spacer, mp->popSizeFix);
            if (!strcmp(mp->topologyPr,"Speciestree"))
                {
                if (!strcmp(mp->popVarPr,"Equal") || !strcmp(mp->popSizePr,"Fixed"))
                    MrBayesPrint ("%s                         Population size the same across species tree\n", spacer);
                else
                    MrBayesPrint ("%s                         Population size varies across branches in species tree\n", spacer);
                }
            }
        else if (j == P_GROWTH)
            {
            if (!strcmp(mp->growthPr,"Uniform"))
                MrBayesPrint ("%s            Prior      = Uniform(%1.2lf,%1.2lf)\n", spacer, mp->growthUni[0], mp->growthUni[1]);
            else if (!strcmp(mp->growthPr,"Exponential"))
                MrBayesPrint ("%s            Prior      = Exponential(%1.2lf)\n", spacer, mp->growthExp);
            else if (!strcmp(mp->growthPr,"Normal"))
                MrBayesPrint ("%s            Prior      = Normal(%1.2lf,%1.2lf)\n", spacer, mp->growthNorm[0], mp->growthNorm[1]);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->growthFix);
            } 
        else if (j == P_AAMODEL)
            {
            if (!strcmp(mp->aaModelPr,"Mixed"))
                {
                /* check to see if you have a uniform prior */
                isSame = YES;
                for (a=0; a<9; a++)
                    for (b=a+1; b<10; b++)
                            /* mp->aaModelPrProbs[a] != mp->aaModelPrProbs[b] */
                    if (AreDoublesEqual(mp->aaModelPrProbs[a], mp->aaModelPrProbs[b], ETA)==FALSE)
                            isSame = NO;
                MrBayesPrint ("%s            Prior      = Poisson, Jones, Dayhoff, Mtrev, Mtmam, Wag, Rtrev,\n", spacer);
                if (isSame == YES)
                    MrBayesPrint ("%s                         Cprev, Vt, and Blosum models have equal prior probability\n", spacer);
                else
                    MrBayesPrint ("%s                         Cprev, Vt, and Blosum models have unequal prior probability\n", spacer);
                }
            else
                MrBayesPrint ("%s            Prior      = Fixed(%s)\n", spacer, mp->aaModel);
            }
        else if (j == P_BRCORR)
            {
            if (!strcmp(mp->brownCorPr,"Uniform"))
                MrBayesPrint ("%s            Prior      = Uniform(%1.2lf,%1.2lf)\n", spacer, mp->brownCorrUni[0], mp->brownCorrUni[1]);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->brownCorrFix);
            }
        else if (j == P_BRSIGMA)
            {
            if (!strcmp(mp->brownScalesPr,"Uniform"))
                MrBayesPrint ("%s            Prior      = Uniform(%1.2lf,%1.2lf)\n", spacer, mp->brownScalesUni[0], mp->brownScalesUni[1]);
            else if (!strcmp(mp->brownScalesPr,"Gammamean"))
                MrBayesPrint ("%s            Prior      = Gamma Mean=<char. ave.> Var=%1.2lf\n", spacer, mp->brownScalesGammaMean);
            else if (!strcmp(mp->brownScalesPr,"Gamma"))
                MrBayesPrint ("%s            Prior      = Gamma Mean=%lf Var=%1.2lf\n", spacer, mp->brownScalesGamma[0], mp->brownScalesGamma[1]);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->brownScalesFix);
            }
        else if (j == P_CPPRATE)
            {
            if (!strcmp(mp->cppRatePr,"Exponential"))
                MrBayesPrint ("%s            Prior      = Exponential(%1.2lf)\n", spacer, mp->cppRateExp);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->cppRateFix);
            }
        else if (j == P_CPPMULTDEV)
            {
            if (!strcmp(mp->cppMultDevPr,"Fixed"))
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->cppMultDevFix);
            }
        else if (j == P_CPPEVENTS)
            {
            MrBayesPrint ("%s            Prior      = Poisson (%s) [Events]\n", spacer, modelSettings[p->relParts[0]].cppRate->name);
            MrBayesPrint ("%s                         Lognormal (0.00,%1.2lf) [Rate multipliers]\n", spacer, mp->cppMultDevFix);
            }
        else if (j == P_TK02VAR)
            {
            if (!strcmp(mp->tk02varPr,"Uniform"))
                MrBayesPrint ("%s            Prior      = Uniform(%1.2lf,%1.2lf)\n", spacer, mp->tk02varUni[0], mp->tk02varUni[1]);
            else if (!strcmp(mp->tk02varPr,"Exponential"))
                MrBayesPrint ("%s            Prior      = Exponential(%1.2lf)\n", spacer, mp->tk02varExp);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->tk02varFix);
            }
        else if (j == P_TK02BRANCHRATES)
            {
            MrBayesPrint ("%s            Prior      = LogNormal (expectation = r_0, variance = %s * v) \n", spacer, modelSettings[p->relParts[0]].tk02var->name);
            MrBayesPrint ("%s                            [r_0 is beginning rate of branch, v is branch length]\n", spacer);
            }
        else if (j == P_IGRVAR)
            {
            if (!strcmp(mp->igrvarPr,"Uniform"))
                MrBayesPrint ("%s            Prior      = Uniform(%1.2lf,%1.2lf)\n", spacer, mp->igrvarUni[0], mp->igrvarUni[1]);
            else if (!strcmp(mp->igrvarPr,"Exponential"))
                MrBayesPrint ("%s            Prior      = Exponential(%1.2lf)\n", spacer, mp->igrvarExp);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->igrvarFix);
            }
        else if (j == P_IGRBRANCHRATES)
            {
            MrBayesPrint ("%s            Prior      = Gamma (expectation = v, variance = %s * v) \n", spacer, modelSettings[p->relParts[0]].igrvar->name);
            MrBayesPrint ("%s                            [where v is branch length]\n", spacer);
            }
        else if (j == P_MIXEDVAR)
            {
            if (!strcmp(mp->mixedvarPr,"Uniform"))
                MrBayesPrint ("%s            Prior      = Uniform(%1.2lf,%1.2lf)\n", spacer, mp->mixedvarUni[0], mp->mixedvarUni[1]);
            else if (!strcmp(mp->mixedvarPr,"Exponential"))
                MrBayesPrint ("%s            Prior      = Exponential(%1.2lf)\n", spacer, mp->mixedvarExp);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.2lf)\n", spacer, mp->mixedvarFix);
            }
        else if (j == P_MIXEDBRCHRATES)
            {
            MrBayesPrint ("%s            Prior      = Mixed TK02 and IGR (variance = %s * v)\n", spacer, modelSettings[p->relParts[0]].mixedvar->name);
            MrBayesPrint ("%s                            [where v is branch length]\n", spacer);
            MrBayesPrint ("%s                         Uniform prior on relaxed clock models [Pr(TK02)=Pr(IGR)=1/2]\n", spacer);
            }
        else if (j == P_CLOCKRATE)
            {
            if (!strcmp(mp->clockRatePr,"Normal"))
                MrBayesPrint ("%s            Prior      = Normal(%1.2lf,%1.2lf)\n", spacer, mp->clockRateNormal[0], mp->clockRateNormal[1]);
            else if (!strcmp(mp->clockRatePr,"Lognormal"))
                MrBayesPrint ("%s            Prior      = Lognormal(%1.2lf,%1.2lf)\n", spacer, mp->clockRateLognormal[0], mp->clockRateLognormal[1]);
            else if (!strcmp(mp->clockRatePr,"Gamma"))
                MrBayesPrint ("%s            Prior      = Gamma(%1.2lf,%1.2lf)\n", spacer, mp->clockRateGamma[0], mp->clockRateGamma[1]);
            else if (!strcmp(mp->clockRatePr,"Exponential"))
                MrBayesPrint ("%s            Prior      = Exponential(%1.2lf)\n", spacer, mp->clockRateExp);
            else
                MrBayesPrint ("%s            Prior      = Fixed(%1.6lf)\n", spacer, mp->clockRateFix);
            if (!strcmp(mp->clockVarPr,"Strict"))
                MrBayesPrint ("%s                         The clock rate is constant (strict clock)\n", spacer);
            else if (!strcmp(mp->clockVarPr,"Cpp"))
                MrBayesPrint ("%s                         The clock rate varies according to a CPP model\n", spacer);
            else if (!strcmp(mp->clockVarPr,"TK02"))
                MrBayesPrint ("%s                         The clock rate varies according to a Brownian motion model\n", spacer);
            else if (!strcmp(mp->clockVarPr,"Igr"))
                MrBayesPrint ("%s                         The clock rate varies according to an independent gamma (white noise) model\n", spacer);
            else /* if (!strcmp(mp->clockVarPr,"Mixed")) */
                MrBayesPrint ("%s                         The clock rate varies according to mixed TK02 and IGR models\n", spacer);
            }
        else if (j == P_SPECIESTREE)
            {
            MrBayesPrint ("%s            Prior      = Uniform on topologies and branch lengths\n", spacer);
            }
                
        /* print partitions */
        if (numCurrentDivisions > 1)
            {
            if (p->nRelParts == 1)
                MrBayesPrint ("%s            Partition  = %d\n", spacer, p->relParts[0]+1);
            else if (p->nRelParts == 2)
                {
                MrBayesPrint ("%s            Partitions = %d and %d\n", spacer, p->relParts[0]+1, p->relParts[1]+1);                    
                }
            else if (p->nRelParts == numCurrentDivisions)
                {
                MrBayesPrint ("%s            Partitions = All\n", spacer);                  
                }           
            else /* if (p->nRelParts > 2) */
                {
                MrBayesPrint ("%s            Partitions = ", spacer);
                for (j=0; j<p->nRelParts; j++)
                    {
                    if (j == p->nRelParts - 2)
                        MrBayesPrint ("%d, and ", p->relParts[j]+1);
                    else if (j == p->nRelParts - 1)
                        MrBayesPrint ("%d\n", p->relParts[j]+1);
                    else
                        MrBayesPrint ("%d, ", p->relParts[j]+1);
                    }               
                }
            }

        /* show subparams */
        if (p->nSubParams > 0)
            {
            if (p->nSubParams == 1)
                MrBayesPrint ("%s            Subparam.  = %s\n", spacer, p->subParams[0]->name);
            else
                {
                printedCol = 0;
                for (k=0; k<p->nSubParams; k++)
                    {
                    if (k == 0)
                        {
                        MrBayesPrint ("%s            Subparams  = %s", spacer, p->subParams[k]->name);
                        printedCol = (int)(strlen(spacer)) + 25 + (int)(strlen(p->subParams[k]->name));
                        }
                    else if (k == p->nSubParams - 1)
                        {
                        if (printedCol + 5 > screenWidth)
                            MrBayesPrint ("\n%s                         and ", spacer);
                        else if (printedCol + (int)(strlen(p->subParams[k]->name)) + 5 > screenWidth)
                            MrBayesPrint (" and \n%s                         ", spacer);
                        else
                            MrBayesPrint (" and ");
                        MrBayesPrint ("%s\n", p->subParams[k]->name);
                        }
                    else
                        {
                        if (printedCol + (int)(strlen(p->subParams[k]->name)) + 2 > screenWidth)
                            {
                            MrBayesPrint (", \n%s                         ", spacer);
                            printedCol = (int)(strlen(spacer)) + 25;
                            }
                        else
                            {
                            MrBayesPrint(", ");
                            printedCol += 2;
                            }
                        MrBayesPrint ("%s", p->subParams[k]->name);
                        printedCol += (int)strlen(p->subParams[k]->name);
                        }
                    }
                }
            }

        /* show used moves */
        if (showMoves == YES && (p->printParam == YES || p->paramType == P_TOPOLOGY || p->paramType == P_BRLENS))
            {
            /* check if runs are same */
            areRunsSame = YES;
            for (run=1; run<chainParams.numRuns; run++)
                {
                for (chain=0; chain<chainParams.numChains; chain++)
                    {
                    for (k=0; k<numApplicableMoves; k++)
                        {
                        mv = moves[k];
                        if (mv->parm != p)
                            continue;
                        chainIndex = run*chainParams.numChains + chain;
                        refIndex = chain;
                        if (AreDoublesEqual (mv->relProposalProb[chainIndex], mv->relProposalProb[refIndex], 0.000001) == NO)
                            areRunsSame = NO;
                        }
                    }
                }

            for (run=0; run<chainParams.numRuns; run++)
                {
                if (run > 0 && areRunsSame == YES)
                    continue;
                
                /* check if chains are same */
                areChainsSame = YES;
                for (chain=1; chain<chainParams.numChains; chain++)
                    {
                    for (k=0; k<numApplicableMoves; k++)
                        {
                        mv = moves[k];
                        if (mv->parm != p)
                            continue;
                        chainIndex = run*chainParams.numChains + chain;
                        refIndex = run*chainParams.numChains;
                        if (AreDoublesEqual (mv->relProposalProb[chainIndex], mv->relProposalProb[refIndex], 0.000001) == NO)
                            areChainsSame = NO;
                        }
                    }

                /* now print moves */
                for (chain=0; chain<chainParams.numChains; chain++)
                    {
                    if (chain > 0 && areChainsSame == YES)
                        continue;
                    if (run==0 && chain==0)
                        MrBayesPrint ("%s            Moves      = ", spacer);
                    else
                        MrBayesPrint ("%s                         ", spacer);
                    numPrinted = 0;
                    printedCol = (int)(strlen(spacer)) + 25;
                    for (k=0; k<numApplicableMoves; k++)
                        {
                        mv = moves[k];
                        if (mv->parm != p)
                            continue;
                        chainIndex = run*chainParams.numChains + chain;
                        if (mv->relProposalProb[chainIndex] <= 0.000001)
                            continue;
                        if (numPrinted == 0)
                            {
                            MrBayesPrint ("%s <prob %.1f>", mv->name, mv->relProposalProb[chainIndex]);
                            printedCol += 9 + (int)strlen(mv->name) + (int)(log10(mv->relProposalProb[chainIndex])) + 3;
                            }
                        else
                            {
                            if (printedCol + 11 + (int)(strlen(mv->name)) + (int)(log10(mv->relProposalProb[chainIndex])) + 3 > screenWidth)
                                {
                                MrBayesPrint(", \n%s                         ", spacer);
                                printedCol = 25 + (int)(strlen(spacer));
                                }
                            else
                                {
                                MrBayesPrint(", ");
                                printedCol += 2;
                                }
                            MrBayesPrint ("%s <prob %.1f>", mv->name, mv->relProposalProb[chainIndex]);
                            printedCol += (9 + (int)(strlen(mv->name)) + (int)(log10(mv->relProposalProb[chainIndex])) + 3);
                            }
                        numPrinted++;
                        }

                    if (numPrinted == 0 && p->paramType == P_BRLENS)
                        {
                        for (k=0; k<numParams; k++)
                            if (params[k].tree == p->tree)
                                break;
                        MrBayesPrint ("For moves, see param. '%s'", params[k].name);
                        }
                    else if (numPrinted == 0)
                        MrBayesPrint ("WARNING! No moves -- param. fixed to startvals");

                    if (areRunsSame == YES && areChainsSame == YES)
                        MrBayesPrint ("\n");
                    else if (areRunsSame == YES && areChainsSame == NO)
                        MrBayesPrint (" [chain %d]\n", chain+1);
                    else if (areRunsSame == NO && areChainsSame == YES)
                        MrBayesPrint (" [run %d]\n", run+1);
                    else /* if (areRunsSame == NO && areChainsSame == NO) */
                            MrBayesPrint (" [run %d, chain %d]\n", run+1, chain+1);
                    }
                }
            }
            
        /* show available moves */
        if (showAllAvailable == YES && (p->printParam == YES || p->paramType == P_TOPOLOGY || p->paramType == P_BRLENS))
            {
            /* loop over moves */
            numPrinted = 0;
            printedCol = 0;
            for (k=0; k<numApplicableMoves; k++)
                {
                mv = moves[k];
                if (mv->parm != p)
                    continue;
                numMovedChains = 0;
                for (run=0; run<chainParams.numRuns; run++)
                    {
                    for (chain=0; chain<chainParams.numChains; chain++)
                        {
                        chainIndex = run*chainParams.numChains + chain;
                        if (mv->relProposalProb[chainIndex] > 0.000001)
                            numMovedChains++;
                        }
                    }
                if (numMovedChains == 0)
                    {
                    if (numPrinted == 0)
                        {
                        MrBayesPrint ("%s            Not used   = ", spacer);
                        printedCol = (int)(strlen(spacer)) + 25;
                        }
                    else if (printedCol + 2 + (int)(strlen(mv->moveType->shortName)) > screenWidth)
                        {
                        MrBayesPrint (", \n%s                         ", spacer);
                        printedCol = (int)(strlen(spacer)) + 25;
                        }
                    else
                        {
                        MrBayesPrint (", ");
                        printedCol += 2;
                        }
                    MrBayesPrint("%s", mv->moveType->shortName);
                    printedCol += (int)strlen(mv->moveType->shortName);
                    numPrinted++;
                    }
                }
                if (numPrinted > 0)
                    MrBayesPrint ("\n");
            }

        /* show startvals */
        if (showStartVals == YES && (p->printParam == YES || p->paramType == P_TOPOLOGY || p->paramType == P_BRLENS || p->paramType == P_SPECIESTREE || p->paramType == P_POPSIZE))
            {                   
            if (p->paramType == P_TOPOLOGY || p->paramType == P_BRLENS || p->paramType == P_SPECIESTREE)
                {
                /* check if they are the same */
                areRunsSame = YES;
                if (p->paramType == P_TOPOLOGY)
                    {
                    for (run=1; run<chainParams.numRuns; run++)
                        {
                        for (chain=0; chain<chainParams.numChains; chain++)
                            {
                            if (AreTopologiesSame (GetTree (p, run*chainParams.numChains + chain, 0), GetTree (p, chain, 0)) == NO)
                                {
                                areRunsSame = NO;
                                break;
                                }
                            }
                        }
                    }
                else if (p->paramType == P_BRLENS)
                    {
                    for (run=1; run<chainParams.numRuns; run++)
                        {
                        for (chain=0; chain<chainParams.numChains; chain++)
                            {
                            if (AreTreesSame (GetTree (p, run*chainParams.numChains + chain, 0), GetTree (p, chain, 0)) == NO)
                                {
                                areRunsSame = NO;
                                break;
                                }
                            }
                        }
                    }
                else if (p->paramType == P_SPECIESTREE)
                    {
                    for (run=1; run<chainParams.numRuns; run++)
                        {
                        for (chain=0; chain<chainParams.numChains; chain++)
                            {
                            if (AreTreesSame (GetTree (p, run*chainParams.numChains + chain, 0), GetTree (p, chain, 0)) == NO)
                                {
                                areRunsSame = NO;
                                break;
                                }
                            }
                        }
                    }
                
                /* print trees */
                for (run=0; run<chainParams.numRuns; run++)
                    {
                    if (run > 0 && areRunsSame == YES)
                        break;
                    for (chain=0; chain<chainParams.numChains; chain++)
                        {
                        if (run == 0 && chain == 0)
                            MrBayesPrint ("%s            Startvals  = tree '%s'", spacer, GetTree (p, run*chainParams.numChains+chain, 0)->name);
                        else
                            MrBayesPrint ("%s                         tree '%s'", spacer, GetTree (p, run*chainParams.numChains+chain, 0)->name);
                        if (chainParams.numChains > 1 && areRunsSame == YES)
                            MrBayesPrint ("  [chain %d]", chain+1);
                        else if (chainParams.numChains == 1 && areRunsSame == NO)
                            MrBayesPrint ("  [run %d]", run+1);
                        else if (areRunsSame == NO)
                            MrBayesPrint ("  [run %d, chain %d]", run+1, chain+1);
                        MrBayesPrint ("\n");
                        }
                    }               
                }   /* end topology and brlens parameters */

            else if (p->paramType == P_OMEGA && p->paramId != OMEGA_DIR && p->paramId != OMEGA_FIX &&
                     p->paramId != OMEGA_FFF && p->paramId != OMEGA_FF && p->paramId != OMEGA_10FFF)
                {
                /* we need to print values and subvalues for the category frequencies in a NY98-like model. */
                areRunsSame = YES;
                for (run=1; run<chainParams.numRuns; run++)
                    {
                    for (chain=0; chain<chainParams.numChains; chain++)
                        {
                        value = GetParamVals (p, run*chainParams.numRuns+chain, 0);
                        refValue = GetParamVals (p, chain, 0);
                        nValues = p->nValues;
                        for (k=0; k<nValues; k++)
                            {
                            if (AreDoublesEqual (value[k], refValue[k], 0.000001) == NO)
                                {
                                areRunsSame = NO;
                                break;
                                }
                            }
                        value = GetParamSubVals (p, run*chainParams.numRuns+chain, 0);
                        refValue = GetParamSubVals (p, chain, 0);
                        if (!strcmp(modelParams[p->relParts[0]].omegaVar, "M10"))
                            {
                            value += (mp->numM10BetaCats + mp->numM10GammaCats);
                            refValue += (mp->numM10BetaCats + mp->numM10GammaCats);
                            for (k=0; k<4; k++)
                                {
                                if (AreDoublesEqual (value[k + 4], refValue[k + 4], 0.000001) == NO)
                                    {
                                    areRunsSame = NO;
                                    break;
                                    }
                                }
                            for (k=0; k<2; k++)
                                {
                                if (AreDoublesEqual (value[k], refValue[k], 0.000001) == NO)
                                    {
                                    areRunsSame = NO;
                                    break;
                                    }
                                }                           
                            }
                        else
                            {
                            for (k=0; k<3; k++)
                                {
                                if (AreDoublesEqual (value[k], refValue[k], 0.000001) == NO)
                                    {
                                    areRunsSame = NO;
                                    break;
                                    }
                                }
                            }
                        if (areRunsSame == NO)
                            break;
                        }
                    if (areRunsSame == NO)
                        break;
                    }
                
                /* now print values */
                for (run=0; run<chainParams.numRuns; run++)
                    {
                    for (chain=0; chain<chainParams.numChains; chain++)
                        {
                        value = GetParamVals (p, run*chainParams.numRuns+chain, 0);
                        subValue = GetParamSubVals (p, run*chainParams.numRuns+chain, 0);
                        nValues = p->nValues;                       
                        if (run == 0 && chain == 0)
                            MrBayesPrint ("%s            Startvals  = (%1.3lf", spacer, value[0]);
                        else
                            MrBayesPrint ("%s                         (%1.3lf", spacer, value[0]);
                        for (k=1; k<nValues; k++)
                            {
                            MrBayesPrint (",%1.3lf", value[k]);
                            }

                        if (!strcmp(modelParams[p->relParts[0]].omegaVar, "M10"))
                            {
                            for (k=0; k<4; k++)
                                {
                                MrBayesPrint (",%1.3lf", subValue[k + mp->numM10BetaCats+mp->numM10GammaCats+4]);
                                }
                            for (k=0; k<2; k++)
                                {
                                MrBayesPrint (",%1.3lf", subValue[k + mp->numM10BetaCats+mp->numM10GammaCats]);
                                }                   
                            }
                        else
                            {
                            for (k=0; k<3; k++)
                                {
                                MrBayesPrint (",%1.3lf", subValue[k]);
                                }
                            }       
                        MrBayesPrint (")");
                        if (chainParams.numChains > 1 && areRunsSame == YES)
                            MrBayesPrint ("  [chain %d]\n", chain+1);
                        else if (chainParams.numChains == 1 && areRunsSame == NO)
                            MrBayesPrint ("  [run %d]\n", run+1);
                        else if (areRunsSame == NO)
                            MrBayesPrint ("  [run %d, chain %d]\n", run+1, chain+1);
                        }
                    }
                }
            else
                {
                /* run of the mill parameter */
                if (p->paramType == P_CLOCKRATE)
                    {
                     for (j=0; j<numGlobalChains; j++)
                        {
                        if (UpdateClockRate(-1.0, j) == ERROR)
                            {
                            MrBayesPrint ("%s            Warning: There is no appropriate clock rate that would satisfy all calibrated trees for run:%d chain%d. Some of calibration, trees or clockprior needs to be changed. ", spacer, j/chainParams.numChains, j%chainParams.numChains);
                            }
                        }
                    }
                areRunsSame = YES;
                for (run=1; run<chainParams.numRuns; run++)
                    {
                    for (chain=0; chain<chainParams.numChains; chain++)
                        {
                        if ((p->paramType == P_PI && modelParams[p->relParts[0]].dataType != STANDARD))
                            {
                            nValues = p->nSubValues;
                            value = GetParamSubVals (p, run*chainParams.numChains+chain, 0);
                            refValue = GetParamSubVals (p, chain, 0);
                            }
                        else
                            {
                            nValues = p->nValues;
                            value = GetParamVals (p, run*chainParams.numChains+chain, 0);
                            refValue = GetParamVals (p, chain, 0);
                            }
                        for (k=0; k<nValues; k++)
                            {
                            if (AreDoublesEqual(value[k], refValue[k], 0.000001) == NO)
                                {
                                areRunsSame = NO;
                                break;
                                }                           
                            }
                        if (areRunsSame == NO)
                            break;                          
                        }
                    if (areRunsSame == NO)
                        break;
                    }

                /* print values */
                for (run=0; run<chainParams.numRuns; run++)
                    {
                    if (run > 0 && areRunsSame == YES)
                        break;
                    areChainsSame = YES;
                    for (chain=1; chain<chainParams.numChains; chain++)
                        {
                        if ((p->paramType == P_PI && modelParams[p->relParts[0]].dataType != STANDARD))
                            {
                            nValues = p->nSubValues;
                            value = GetParamSubVals (p, run*chainParams.numChains+chain, 0);
                            refValue = GetParamSubVals (p, run*chainParams.numChains, 0);
                            }
                        else
                            {
                            nValues = p->nValues;
                            value = GetParamVals (p, run*chainParams.numChains+chain, 0);
                            refValue = GetParamVals (p, run*chainParams.numChains, 0);
                            }
                        for (k=0; k<nValues; k++)
                            {
                            if (AreDoublesEqual(value[k], refValue[k], 0.000001) == NO)
                                {
                                areChainsSame = NO;
                                break;
                                }                           
                            }
                        }
                    for (chain=0; chain<chainParams.numChains; chain++)
                        {
                        if (areChainsSame == YES && chain > 0)
                            continue;

                        if ((p->paramType == P_PI && modelParams[p->relParts[0]].dataType != STANDARD))
                            {
                            nValues = p->nSubValues;
                            value = GetParamSubVals (p, run*chainParams.numChains+chain, 0);
                            }
                        else
                            {
                            nValues = p->nValues;
                            value = GetParamVals (p, run*chainParams.numChains+chain, 0);
                            }

                        if (run == 0 && chain == 0)
                            MrBayesPrint ("%s            Startvals  = (%1.3lf", spacer, value[0]);
                        else
                            MrBayesPrint ("%s                         (%1.3lf", spacer, value[0]);
                        
                        for (k=1; k<nValues; k++)
                            {
                            if (k%10==0)
                                MrBayesPrint (",\n%s                          %1.3lf", spacer, value[k]);
                            else
                                MrBayesPrint (",%1.3lf", value[k]);
                            }
                        MrBayesPrint (")");
                        
                        if (areChainsSame == YES && areRunsSame == NO)
                            MrBayesPrint ("  [run %d]", run+1);
                        else if (areChainsSame == NO && areRunsSame == YES)
                            MrBayesPrint ("  [chain %d]", chain+1);
                        else if (areChainsSame == NO && areRunsSame == NO)
                            MrBayesPrint ("  [run %d, chain %d]", run+1, chain+1);
                        MrBayesPrint ("\n");
                        }   
                    }
                }
            }   /* end print start values */

        MrBayesPrint ("\n");
        }   /* next parameter */

    return (NO_ERROR);
}


int Unlink (void)
{
    return (NO_ERROR);
}


/*-------------------------------------------------
|
|   UpdateClockRate:    Update clockRate of the given chain. Above all it will enforce fixed clockrate prior if it is set.
|                       Error will be returned if fixed clockrate prior may not be respected.
|   @param clockRate    is the new clockRate to setup. Clock rate value could be set as positive, 0.0 or negative value. 
|                       The function does the fallowing depending on one of this three values:
|                        positive    - check that this 'positive' value is suitable rate. At the end re-enforce (update) the 'positive' value as clock rate on all trees. 
|                        0.0         - check if current rate is suitable, if not update it with minimal suitable value. At the end re-enforce (update) the resulting clock rate on all trees. 
|                        negative    - check if current rate is suitable, if not update it with minimal suitable value. At the end re-enforce (update) the resulting clock rate ONLY if clock rate was changed 
|   @return             ERROR if clockRate can not be set up, NO_ERROR otherwise. 
|
--------------------------------------------------*/
int UpdateClockRate (MrBFlt clockRate, int chain)
{
    int         i, updateTrees;
    MrBFlt      *clockRatep;
    Tree        *t, *t_calibrated=NULL;
    MrBFlt      mintmp,maxtmp,minClockRate,maxClockRate;

    clockRatep=NULL;
    minClockRate = 0.0;
    maxClockRate = MRBFLT_MAX;

    for (i=0; i<numTrees; i++)
        {
        t = GetTreeFromIndex(i, chain, 0);
        if (t->isCalibrated == NO)
            continue;

        if (clockRatep == NULL)
            {
            clockRatep = GetParamVals(modelSettings[t->relParts[0]].clockRate, chain, 0);
            t_calibrated = t;
            assert (clockRatep);
            }

        findAllowedClockrate (t, &mintmp, &maxtmp);

        if (minClockRate < mintmp)
            minClockRate = mintmp;

        if (maxClockRate > maxtmp)
            maxClockRate = maxtmp;

        }
    /* clock rate is the same for all trees of a given chain */
    if (clockRatep != NULL)
        {
        if (minClockRate > maxClockRate)
            {
            MrBayesPrint ("%s   ERROR: Calibrated trees require compatible clockrates for run:%d chain:%d.\n",
                          spacer, chain/chainParams.numChains, chain%chainParams.numChains);
            *clockRatep=0;
            return (ERROR);
            }

        if (!strcmp(modelParams[t_calibrated->relParts[0]].clockRatePr, "Fixed"))
            {
            if (clockRate < 0.0 && AreDoublesEqual (*clockRatep, modelParams[t_calibrated->relParts[0]].clockRateFix, 0.0001) == YES)
                {
                updateTrees = NO;
                }
            else
                {
                updateTrees = YES;
                }
            *clockRatep = modelParams[t_calibrated->relParts[0]].clockRateFix;
            if ((*clockRatep < minClockRate && AreDoublesEqual (*clockRatep, minClockRate, 0.0001) == NO) ||
                (*clockRatep > maxClockRate && AreDoublesEqual (*clockRatep, maxClockRate, 0.0001) == NO))
                {
                MrBayesPrint ("%s   ERROR: Calibrated trees require clockrate in range from %f to %f, while clockrate prior is fixed to:%f for run:%d chain:%d.\n",
                              spacer, minClockRate, maxClockRate, *clockRatep, chain/chainParams.numChains, chain%chainParams.numChains);
                *clockRatep=0;
                return (ERROR);
                }
            if (clockRate > 0.0)
                {
                if (AreDoublesEqual (*clockRatep, clockRate, 0.0001) == NO)
                    {
                    MrBayesPrint ("%s   ERROR: Requested clockrate:%f does not match fixed clockrate prior :%f.\n", spacer, clockRate, *clockRatep);
                    *clockRatep=0;
                    return (ERROR);
                    }
                }
            }
        else {
            /* clock prior is not fixed */
            updateTrees = YES;
            if (clockRate > 0.0)
                {
                *clockRatep = clockRate;
                if ((*clockRatep < minClockRate && AreDoublesEqual (*clockRatep, minClockRate, 0.0001) == NO) ||
                    (*clockRatep > maxClockRate && AreDoublesEqual (*clockRatep, maxClockRate, 0.0001) == NO))
                    {
                    MrBayesPrint ("%s   ERROR: Calibrated trees require clockrate in range from %f to %f, while requested clockrate is:%f for run:%d chain:%d.\n",
                                  spacer, minClockRate, maxClockRate, clockRate, chain/chainParams.numChains, chain%chainParams.numChains);
                    *clockRatep=0;
                    return (ERROR);
                    }
                }
            else if (clockRate == 0.0) 
                {
                if ((*clockRatep < minClockRate && AreDoublesEqual (*clockRatep, minClockRate, 0.0001) == NO) ||
                    (*clockRatep > maxClockRate && AreDoublesEqual (*clockRatep, maxClockRate, 0.0001) == NO))
                    {
                    *clockRatep = minClockRate;
                    }
                }
            else // if (clockRate < 0.0)
                {
                if ((*clockRatep < minClockRate && AreDoublesEqual (*clockRatep, minClockRate, 0.0001) == NO) ||
                    (*clockRatep > maxClockRate && AreDoublesEqual (*clockRatep, maxClockRate, 0.0001) == NO))
                    {
                    *clockRatep = minClockRate;
                    }
                else
                    {
                    updateTrees = NO;
                    }
                }
            }

        
        if (updateTrees == YES)
            {
            for (i=0; i<numTrees; i++)
                {
                t = GetTreeFromIndex(i, chain, 0);
                if (t->isCalibrated == NO)
                    continue;
                UpdateTreeWithClockrate (t,*clockRatep);
                }
            }
        }

    return (NO_ERROR);
}


/*----------------------------------------------
|
|   UpdateCppEvolLength: Recursive function to
|      update evolLength of one node for Cpp
|      relaxed clock model
|
-----------------------------------------------*/
int UpdateCppEvolLength (int *nEvents, MrBFlt **pos, MrBFlt **rateMult, MrBFlt *evolLength, TreeNode *p, MrBFlt baseRate)
{
    int     i;
    MrBFlt  endRate;

    if (p != NULL)
        {
#   ifdef DEBUG_CPP
        if (baseRate < POS_MIN || baseRate > POS_INFINITY)
            {
            printf ("baseRate out of bounds (%.15e for node %d\n", baseRate, p->index);
            return (ERROR);
            }
#   endif
        p->upDateTi = YES;
        p->upDateCl = YES;
        if (nEvents[p->index] == 0)
            {
            evolLength[p->index] = p->length * baseRate;
            }
        else
            {
            /* note that event positions are from the top of the branch (more recent)
               to the bottom of the branch (older) */
            /* The algorithm below successively multiplies in the more basal rate multipliers,
               starting from the top of the branch. The length of the branch is first assumed
               to be 1.0; at the end we multiply the result with the true length of the branch. */
            evolLength[p->index] = pos[p->index][0] * rateMult[p->index][0];
            for (i=1; i<nEvents[p->index]; i++)
                {
                evolLength[p->index] += (pos[p->index][i] - pos[p->index][i-1]);
                evolLength[p->index] *= rateMult[p->index][i];
                }
            evolLength[p->index] += (1.0 - pos[p->index][nEvents[p->index]-1]);
            evolLength[p->index] *= baseRate;
            evolLength[p->index] *= p->length;
            }

        /* calculate end rate; we can do this in any order */
        endRate = baseRate;
        for (i=0; i<nEvents[p->index]; i++)
            endRate *= rateMult[p->index][i];

#   ifdef DEBUG_CPP
        if (endRate < POS_MIN || endRate > POS_INFINITY)
            {
            printf ("endRate out of bounds (%.15e for node %d)\n", endRate, p->index);
            return (ERROR);
            }
        if (p->anc != NULL && p->anc->anc != NULL && (evolLength[p->index] < POS_MIN || evolLength[p->index] > POS_INFINITY))
            {
            printf ("Effective branch length out of bounds (%.15e for node %d)\n", evolLength[p->index], p->index);
            return (ERROR);
            }
#   endif
        /* call left and right descendants */
        if (UpdateCppEvolLength (nEvents, pos, rateMult, evolLength, p->left, endRate)==ERROR)
            return (ERROR);
        if (UpdateCppEvolLength (nEvents, pos, rateMult, evolLength, p->right, endRate)==ERROR)
            return (ERROR);
        }

    return (NO_ERROR);
}


/*-------------------------------------------------
 |
 |  UpdateCppEvolLengths: Recalculate effective
 |      evolutionary lengths and set update flags
 |      for Cpp relaxed clock model
 |
 --------------------------------------------------*/
int UpdateCppEvolLengths (Param *param, TreeNode *p, int chain)
{
    int         i, *nEvents;
    TreeNode    *q;
    MrBFlt      baseRate = 1.0, **pos, **rateMult, *evolLength;
    
    i = 2*chain + state[chain];
    nEvents = param->nEvents[i];
    pos = param->position[i];
    rateMult = param->rateMult[i];
    evolLength = GetParamSubVals (param, chain, state[chain]);
    
    q = p->anc;
    while (q->anc != NULL)
        {
        for (i=0; i<nEvents[q->index]; i++)
            baseRate *= rateMult[q->index][i];
        q = q->anc;
        }
    
    if (UpdateCppEvolLength (nEvents, pos, rateMult, evolLength, p, baseRate)==ERROR)
        return (ERROR);
    
    return(NO_ERROR);
}


/* UpdateTK02EvolLengths: update branch lengths for tk02 model */
int UpdateTK02EvolLengths (Param *param, Tree *t, int chain)
{
    int         i;
    MrBFlt      *tk02Rate, *brlens;
    TreeNode    *p;
    
    tk02Rate = GetParamVals (param, chain, state[chain]);
    brlens = GetParamSubVals (param, chain, state[chain]);
    for (i=0; i<t->nNodes-2; i++)
        {
        p = t->allDownPass[i];
        brlens[p->index] = p->length * (tk02Rate[p->index] + tk02Rate[p->anc->index]) / 2.0;
        }
    
    return (NO_ERROR);
}


/* UpdateIgrBranchLengths: update branch lengths for igr model */
int UpdateIgrBrachLengths (Param *param, Tree *t, int chain)
{
    int         i;
    MrBFlt      *igrRate, *brlens;
    TreeNode    *p;
    
    igrRate = GetParamVals (param, chain, state[chain]);
    brlens = GetParamSubVals (param, chain, state[chain]);
    for (i=0; i<t->nNodes-2; i++)
        {
        p = t->allDownPass[i];
        brlens[p->index] = p->length * igrRate[p->index];
        }

    return (NO_ERROR);
}

