[med-svn] [mrbayes] 02/10: Imported Upstream version 3.2.6+dfsg.orig

Andreas Tille tille at debian.org
Wed Dec 30 21:49:24 UTC 2015


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository mrbayes.

commit 45caa80d684244a4ff64e2ffa58d9fa42a3165a3
Author: Andreas Tille <tille at debian.org>
Date:   Wed Dec 30 22:24:11 2015 +0100

    Imported Upstream version 3.2.6+dfsg.orig
---
 documentation/commref_mb3.2.txt |    83 +-
 documentation/release_note.txt  |    15 +-
 src/bayes.c                     |    11 +-
 src/bayes.h                     |    21 +-
 src/best.c                      |    10 +-
 src/command.c                   |   244 +-
 src/likelihood.c                |    18 +-
 src/mcmc.c                      |   499 +-
 src/mcmc.h                      |     2 +-
 src/model.c                     |   619 ++-
 src/proposal.c                  | 10470 +++++++++++++++-----------------------
 src/proposal.h                  |     9 +-
 src/sumpt.c                     |   375 +-
 src/sumpt.h                     |     1 +
 src/utils.c                     |    54 +-
 15 files changed, 5380 insertions(+), 7051 deletions(-)

diff --git a/documentation/commref_mb3.2.txt b/documentation/commref_mb3.2.txt
index a145cf9..481dc3e 100644
--- a/documentation/commref_mb3.2.txt
+++ b/documentation/commref_mb3.2.txt
@@ -2,7 +2,7 @@
                                                                                  
                                                                                  
                                                                                  
-                   Command Reference for MrBayes ver. 3.2.5                   
+                   Command Reference for MrBayes ver. 3.2.6                   
                                                                                  
                    (c) John P. Huelsenbeck, Fredrik Ronquist                     
                                and Maxim Teslenko                                
@@ -231,9 +231,9 @@
    tree distance values.                                                         
                                                                                  
    Note that the "Sumt" command provides a different set of convergence diag-  
-   nostics tools that you may also want to explore. Unlike "Comparetree", "Sumt"
-   can compare more than two tree samples and will calculate consensus trees and 
-   split frequencies from the pooled samples.                                    
+   nostics tools that you may also want to explore. Unlike "Comparetree",      
+   "Sumt" can compare more than two tree samples and will calculate consensus  
+   trees and split frequencies from the pooled samples.                          
                                                                                  
    Options:                                                                      
                                                                                  
@@ -676,9 +676,9 @@
                 above and a large number of others, with or without name.        
    Code      -- Enforces the use of a particular genetic code. The default       
                 is the universal code. Other options include "vertmt" for      
-                vertebrate mitocondrial DNA, "mycoplasma", "yeast",          
-                "ciliates", and "metmt" (for metazoan mitochondrial DNA      
-                except vertebrates).                                             
+                vertebrate mitocondrial, "invermt", "mycoplasma", "yeast", 
+                "ciliate", "echinoderm", "euplotid", and "metmt" (for    
+                metazoan mitochondrial except vertebrates).                      
    Ploidy    -- Specifies the ploidy of the organism. Options are "Haploid",   
                 "Diploid" or "Zlinked". This option is used when a coalescent
                 prior is used on trees.                                          
@@ -740,15 +740,19 @@
                 a specified substitution model (specified using the other        
                 lset options).                                                   
    Coding    -- This specifies how characters were sampled. If all site patterns 
-                had the possibility of being sampled, then "all" should be     
-                specified (the default). Otherwise "variable" (only variable   
-                characters had the possibility of being sampled), "noabsence"  
-                (characters for which all taxa were coded as absent were not     
-                sampled), and "nopresence" (characters for which all taxa were 
-                coded as present were not sampled. "All" works for all data    
-                types. However, the others only work for morphological (all/     
-                variable) or restriction site (all/variable/noabsence/nopresence)
-                data.                                                            
+                had the possibility of being sampled, then "All" should be     
+                specified (the default). Otherwise "Variable" (only variable   
+                characters had the possibility of being sampled), "Informative"
+                (only parsimony informative characters has the possibility of    
+                being sampled), "Nosingletons" (characters which are constant  
+                in all but one taxon were not sampled), "Noabsencesites" (char-
+                acters for which all taxa were coded as absent were not sampled),
+                "Nopresencesites" (characters for which all taxa were coded as 
+                present were not sampled). "All" works for all data types.     
+                However, the others only work for morphological (All/Variable/   
+                Informative/Nosingletons) or restriction site (All/Variable/     
+                Informative/Nosingletons/Noabsencesites/Nopresencesites/         
+                Nosingletonpresence/Nosingletonabsence) data.                    
    Parsmodel -- This forces calculation under the so-called parsimony model      
                 described by Tuffley and Steel (1998). The options are "yes"   
                 or "no". Note that the biological assumptions of this model    
@@ -762,20 +766,21 @@
                                                                                  
    Parameter    Options                               Current Setting            
    ------------------------------------------------------------------            
-   Nucmodel     4by4/Doublet/Codon/Protein            4by4                         
-   Nst          1/2/6/Mixed                           1                         
-   Code         Universal/Vertmt/Mycoplasma/                                     
-                Yeast/Ciliates/Metmt                  Universal                         
-   Ploidy       Haploid/Diploid/Zlinked               Diploid                         
+   Nucmodel     4by4/Doublet/Codon/Protein              4by4                       
+   Nst          1/2/6/Mixed                             1                       
+   Code         Universal/Vertmt/Invermt/Yeast/Mycoplasma/                       
+                Ciliate/Echinoderm/Euplotid/Metmt       Universal                       
+   Ploidy       Haploid/Diploid/Zlinked                 Diploid                       
    Rates        Equal/Gamma/LNorm/Propinv/                                       
-                Invgamma/Adgamma                      Equal                         
-   Ngammacat    <number>                              4                         
-   Nbetacat     <number>                              5                         
-   Omegavar     Equal/Ny98/M3                         Equal                         
-   Covarion     No/Yes                                No                         
-   Coding       All/Variable/Noabsencesites/                                     
-                Nopresencesites                       All                         
-   Parsmodel    No/Yes                                No                         
+                Invgamma/Adgamma                        Equal                       
+   Ngammacat    <number>                                4                       
+   Nbetacat     <number>                                5                       
+   Omegavar     Equal/Ny98/M3                           Equal                       
+   Covarion     No/Yes                                  No                       
+   Coding       All/Variable/Informative/Nosingletons                            
+                Noabsencesites/Nopresencesites/                                  
+                Nosingletonabsence/Nosingletonpresence  All                       
+   Parsmodel    No/Yes                                  No                       
    ------------------------------------------------------------------            
                                                                                  
    ---------------------------------------------------------------------------   
@@ -788,7 +793,7 @@
                                                                                  
    Parameter       Options                  Current Setting                      
    --------------------------------------------------------                      
-   Filename        <name>                   commref_mb3.2.5-svn.txt                                   
+   Filename        <name>                   commref_mb3.2.7-svn.txt                                   
                                                                                  
    ---------------------------------------------------------------------------   
    ---------------------------------------------------------------------------   
@@ -1472,18 +1477,18 @@
                     The fact that the labelling of morphological characters is   
                     arbitrary makes it difficult to allow unequal character-     
                     state frequencies. MrBayes gets around this problem by       
-                    assuming that the states have a dirichlet prior, with all    
-                    states having equal frequency. The variation in the diri-    
-                    chlet can be controlled by this parameter--symdirihyperpr.   
-                    Symdirihyperpr specifies the distribution on the variance    
-                    parameter of the dirichlet. The valid options are:           
+                    assuming that the states have a symmetric Dirichlet prior    
+                    (i.e. all Dirichlet parameters are equal). The variation in  
+                    the Dirichlet can be controlled by this parameter.           
+                    Symdirihyperpr specifies the distribution on the parameter   
+                    of the symmetric Dirichlet. The valid options are:           
                                                                                  
                        prset Symdirihyperpr = uniform(<number>,<number>)         
                        prset Symdirihyperpr = exponential(<number>)              
                        prset Symdirihyperpr = fixed(<number>)                    
                        prset Symdirihyperpr = fixed(infinity)                    
                                                                                  
-                    If "fixed(infinity)" is chosen, the dirichlet prior is     
+                    If "fixed(infinity)" is chosen, the Dirichlet prior is     
                     fixed such that all character states have equal frequency.   
    Topologypr    -- This parameter specifies the prior probabilities of          
                     phylogenies. The options are:                                
@@ -1938,7 +1943,7 @@
                     Truncatednormal/Lognormal/   
                     Offsetlognormal/Offsetgamma/ 
                     Offsetexponential            
-   Speciationpr     Uniform/Exponential/Fixed    Exponential(1.0)
+   Speciationpr     Uniform/Exponential/Fixed    Exponential(10.0)
    Extinctionpr     Beta/Fixed                   Beta(1.0,1.0)
    Fossilizationpr  Beta/Fixed                   Beta(1.0,1.0)
    SampleStrat      Random/Diversity/Cluster/    Random
@@ -2237,8 +2242,8 @@
                                                                                  
    Parameter          Options               Current Setting                      
    --------------------------------------------------------                      
-   Seed               <number>              1428420230                                  
-   Swapseed           <number>              1428420230                                  
+   Seed               <number>              1448443295                                  
+   Swapseed           <number>              1448443295                                  
    Dir                <name>                ""
    Partition          <name>                ""
    Speciespartition   <name>                ""
diff --git a/documentation/release_note.txt b/documentation/release_note.txt
index c08e730..7e92f45 100644
--- a/documentation/release_note.txt
+++ b/documentation/release_note.txt
@@ -1,10 +1,16 @@
 Release Note
 
+v3.2.6 (Nov 25 2015)
+  1. Add invertebrate mt, Echinoderm and Euplotid codes [lset code=invermt].
+  2. Fix a bug of updating brls in tree-stretch move.
+  3. Correct the proposal ratio in the add/delete branch move.
+  4. Add more coding options for restriction site chars.
+
 v3.2.5 (Apr 8 2015)
   1. Fix pdf in the coalescent prior.
   2. Fix a few issues when appending to the previous run.
   3. Improve the efficiency of moving ancestral fossils.
-  4. Add lognormal rate variation among sites.
+  4. Add lognormal rate variation among sites [lset rate=lnorm].
   5. Add parsimony-biased SPR and TBR proposals (for developers).
   6. Other minor bug fixes and improvements.
 
@@ -18,12 +24,13 @@ v3.2.4 (Jan 27 2015)
   7. Fix prior pdf of relative rates (rate multipliers).
 
 v3.2.3 (Oct 22 2014)
-  1. Correct the proposal ratio in the extending SPR move for non-clock tree.
+  1. Correct the proposal ratio in the extending TBR move for non-clock tree.
   2. Fix numerical error of calculating proposal ratio in parsimony-biased SPR moves.
   3. Set unconstrained:gammadir prior as default to help avoid overestimating branch lengths.
   4. Add clock:fossilization prior for total-evidence dating analysis.
-  5. Add LG model to Aamodelpr [=fixed(LG)].
-  6. Other minor bug fixes and improvements.
+  5. Add LG model to Aamodelpr [prset aamodelpr=fixed(LG)].
+  6. Rearrange the code to be more concise.
+  7. Other minor bug fixes and improvements.
 
 v3.2.2 (Aug 22 2013)
   1. Disable LIKE_EPSILON warning for standard users.
diff --git a/src/bayes.c b/src/bayes.c
index 0b423bf..0c4ec75 100644
--- a/src/bayes.c
+++ b/src/bayes.c
@@ -40,7 +40,7 @@
 #include "sumpt.h"
 #include "utils.h"
 
-       const char* const svnRevisionBayesC = "$Rev: 1008 $";   /* Revision keyword which is expended/updated by svn on each commit/update */
+       const char* const svnRevisionBayesC = "$Rev: 1068 $";   /* Revision keyword which is expended/updated by svn on each commit/update */
 extern const char* const svnRevisionBestC;
 extern const char* const svnRevisionCommandC;
 extern const char* const svnRevisionLikeliC;
@@ -570,7 +570,8 @@ int InitializeMrBayes (void)
     
     /* Prior model settings */
     defaultModel.dataType = DNA;                        /* datatype                                     */
-    strcpy(defaultModel.coding, "All");                 /* ascertainment bias                           */
+    defaultModel.coding = 0;                            /* ascertainment bias                           */
+    strcpy(defaultModel.codingString, "All");           /* ascertainment bias string                    */
     strcpy(defaultModel.nucModel, "4by4");              /* nucleotide model                             */
     strcpy(defaultModel.nst, "1");                      /* number of substitution types                 */
     strcpy(defaultModel.aaModelPr, "Fixed");            /* amino acid model prior                       */
@@ -724,10 +725,10 @@ int InitializeMrBayes (void)
     defaultModel.clockRateExp = 1.0;
     defaultModel.clockRateFix = 1.0;
     strcpy(defaultModel.speciationPr, "Exponential");   /* prior on speciation rate (net diversification) */
-    defaultModel.speciationFix = 1.0;
+    defaultModel.speciationFix = 0.1;
     defaultModel.speciationUni[0] = 0.0;
     defaultModel.speciationUni[1] = 10.0;
-    defaultModel.speciationExp = 1.0;
+    defaultModel.speciationExp = 10.0;
     strcpy(defaultModel.extinctionPr, "Beta");          /* prior on extinction rate (turnover)          */
     defaultModel.extinctionFix = 0.5;
     defaultModel.extinctionBeta[0] = 1;
@@ -986,7 +987,7 @@ int ReinitializeMrBayes (void)
     /* comparetree parameters */
     strcpy(comptreeParams.comptFileName1, "temp.t"); /* input name for comparetree command            */
     strcpy(comptreeParams.comptFileName2, "temp.t"); /* input name for comparetree command            */
-    strcpy(comptreeParams.comptOutfile, "temp.comp");/* input name for comparetree command            */
+    strcpy(comptreeParams.comptOutfile, "temp.comp");/* output name for comparetree command           */
     comptreeParams.minPartFreq = 0.0;                /* minimum frequency of partitions to include    */
 
     /* plot parameters */
diff --git a/src/bayes.h b/src/bayes.h
index abd57c7..c2716ae 100644
--- a/src/bayes.h
+++ b/src/bayes.h
@@ -37,9 +37,9 @@
 /* uncomment the following line when releasing, also modify the VERSION_NUMBER below */
 #define RELEASE
 #ifdef RELEASE
-#define VERSION_NUMBER  "3.2.5"
+#define VERSION_NUMBER  "3.2.6"
 #else
-#define VERSION_NUMBER  "3.2.6-svn"
+#define VERSION_NUMBER  "3.2.7-svn"
 #endif
 
 #if !defined (UNIX_VERSION) && !defined (WIN_VERSION) && !defined (MAC_VERSION)
@@ -240,6 +240,7 @@ typedef float CLFlt;        /* single-precision float used for cond likes (CLFlt
 #define RIGHTCURL               26
 #define DOLLAR                  27
 #define AMPERSAND               28
+#define VERTICALBAR             29
 
 #define MAX_Q_RATE              100.0f
 #define MIN_SHAPE_PARAM         0.00001f
@@ -446,6 +447,18 @@ enum ConstraintType
     HARD
     };
 
+enum CodingType
+    {
+    ALL                 = 0,
+    NOABSENCESITES      = 1,
+    NOPRESENCESITES     = 2,
+    VARIABLE            = 3,
+    NOSINGLETONPRESENCE = 4,
+    NOSINGLETONABSENCE  = 8,
+    NOSINGLETONS        = 12,
+    INFORMATIVE         = 15
+    };
+
 /* typedef for calibration */
 typedef struct calibration
     {
@@ -901,7 +914,8 @@ typedef struct model
     char        nst[100];          /* number of substitution types                 */
     char        parsModel[100];    /* use the (so-called) parsimony model          */
     char        geneticCode[100];  /* genetic code used                            */
-    char        coding[100];       /* type of patterns encoded                     */
+    int         coding;            /* type of patterns encoded                     */
+    char        codingString[100]; /* string describing type of patterns encoded   */
     char        ploidy[100];       /* ploidy level                                 */
     char        omegaVar[100];     /* type of omega variation model                */
     char        ratesModel[100];   /* rates across sites model                     */
@@ -1419,6 +1433,7 @@ typedef struct charinfo
     int cType;
     int nStates;
     int constant[10];
+    int singleton[10];
     int variable;
     int informative;
     } CharInfo;
diff --git a/src/best.c b/src/best.c
index 849bf2d..80ece57 100644
--- a/src/best.c
+++ b/src/best.c
@@ -23,7 +23,7 @@
 #include    "proposal.h"
 #include    "utils.h"
 
-const char* const svnRevisionBestC = "$Rev: 1002 $";   /* Revision keyword which is expended/updated by svn on each commit/update */
+const char* const svnRevisionBestC = "$Rev: 1040 $";   /* Revision keyword which is expended/updated by svn on each commit/update */
 
 /****************************** Local functions converted by Fredrik from BEST code *****************************/
 int         CompareDepths (const void *x, const void *y);
@@ -385,8 +385,8 @@ int GetMinDepthMatrix (Tree **geneTrees, int numGeneTrees, double *depthMatrix)
 
     // Allocate space for species partitions
     nLongsNeeded   = ((numSpecies -1) / nBitsInALong) + 1;   // number of longs needed in a bitfield representing a species set
-    speciesSets    = (BitsLong **) SafeCalloc (2*numLocalTaxa-1, sizeof(BitsLong *));
-    speciesSets[0] = (BitsLong *)  SafeCalloc ((2*numLocalTaxa-1)*nLongsNeeded, sizeof(BitsLong));
+    speciesSets    = (BitsLong **) SafeCalloc ((2*(size_t)numLocalTaxa-1), sizeof(BitsLong *));
+    speciesSets[0] = (BitsLong *)  SafeCalloc ((2*(size_t)numLocalTaxa-1)*nLongsNeeded, sizeof(BitsLong));
     for (i=1; i<2*numLocalTaxa-1; i++)
         speciesSets[i] = speciesSets[0] + i*nLongsNeeded;
 
@@ -417,7 +417,7 @@ int GetMinDepthMatrix (Tree **geneTrees, int numGeneTrees, double *depthMatrix)
 
         // Now order the interior nodes in terms of node depth. We rely on the fact that the
         // ordered sequence is a valid downpass sequence. O(log n).
-        qsort((void *)(geneTrees[w]->intDownPass), (size_t) geneTrees[w]->nIntNodes, sizeof(TreeNode *), CompareNodes);
+        qsort((void *)(geneTrees[w]->intDownPass), (size_t)(geneTrees[w]->nIntNodes), sizeof(TreeNode *), CompareNodes);
 
         // Finally find the minimum for each cell in the upper triangular matrix
         // This is the time critical step with complexity O(n^3) in the simplest
@@ -865,7 +865,7 @@ double LnPriorProbGeneTree (Tree *geneTree, double mu, Tree *speciesTree, double
     MapGeneTreeToSpeciesTree(geneTree, speciesTree);
 
     // Sort gene tree interior nodes first by speciestree branch on which they coalesce, then in time order
-    qsort((void *)(geneTree->intDownPass), (size_t) geneTree->nIntNodes, sizeof(TreeNode *), CompareNodesByX);
+    qsort((void *)(geneTree->intDownPass), (size_t)(geneTree->nIntNodes), sizeof(TreeNode *), CompareNodesByX);
 
     // Debug output of qsort result
     if (trace) {
diff --git a/src/command.c b/src/command.c
index 8fe78c5..96b86e3 100644
--- a/src/command.c
+++ b/src/command.c
@@ -45,11 +45,10 @@
 #include "SIOUX.h"
 #endif
 
-const char* const svnRevisionCommandC = "$Rev: 1012 $";   /* Revision keyword which is expended/updated by svn on each commit/update */
+const char* const svnRevisionCommandC = "$Rev: 1072 $";   /* Revision keyword which is expended/updated by svn on each commit/update */
 
-#define NUMCOMMANDS                     61  /* Note: NUMCOMMANDS gives the total number  */
-                                            /*       of commands in the program          */
-#define NUMPARAMS                       276
+#define NUMCOMMANDS                     62    /* The total number of commands in the program  */
+#define NUMPARAMS                       276   /* The total number of parameters  */
 #define PARAM(i, s, f, l)               p->string = s;    \
                                         p->fp = f;        \
                                         p->valueList = l; \
@@ -282,7 +281,7 @@ CmdType     commands[] =
                     6 = List of valid parameters (parmList) 
                     7 = Expecting (2^TokenType) (expect) (PARAMETER = 4; SEMICOLON = 32; ALPHA = 16384; 
                         ALPHA | QUESTIONMARK | DASH | NUMBER | ASTERISK | EXCLAMATIONMARK | PERCENT | WEIRD | SEMICOLON = 11715360;
-                        ALPHA | QUESTIONMARK | DASH | NUMBER | ASTERISK | EXCLAMATIONMARK | PERCENT | WEIRD | SEMICOLON | LEFTPAR | RIGHTPAR | LEFTCURL | RIGHTCURL = 112381728;
+                        ALPHA | QUESTIONMARK | DASH | NUMBER | ASTERISK | EXCLAMATIONMARK | PERCENT | WEIRD | VERTICALBAR | SEMICOLON | LEFTPAR | RIGHTPAR | LEFTCURL | RIGHTCURL = 649252640;
                         PARAMETER | SEMICOLON = 36; NUMBER | ALPHA = 49152; ALPHA | SEMICOLON = 16416; EQUALSIGN = 8; NUMBER = 32768)
                     8 = Description of the command (cmdDescription)
                     9 = Where should the command be used (cmdUse) (IN_CMD = used from command line or mrbayes block; IN_FILE = used in data block or in tree block)
@@ -317,7 +316,7 @@ CmdType     commands[] =
             { 23,             "Log",  NO,             DoLog,  5,                                                                                 {85,86,87,88,89},        4,                               "Logs screen output to a file",  IN_CMD, SHOW },
             { 24,            "Lset",  NO,            DoLset, 16,                                             {28,29,30,31,32,33,34,40,51,52,53,90,91,131,188,189},        4,                "Sets the parameters of the likelihood model",  IN_CMD, SHOW },
             { 25,          "Manual",  NO,          DoManual,  1,                                                                                            {126},       36,                  "Prints a command reference to a text file",  IN_CMD, SHOW },
-            { 26,          "Matrix", YES,          DoMatrix,  1,                                                                                             {11},112381728,                 "Defines matrix of characters in data block", IN_FILE, SHOW },
+            { 26,          "Matrix", YES,          DoMatrix,  1,                                                                                             {11},649252640,                 "Defines matrix of characters in data block", IN_FILE, SHOW },
             { 27,            "Mcmc",  NO,            DoMcmc, 46,  {17,18,19,20,21,22,23,24,25,26,27,84,98,112,113,114,115,116,132,142,143,144,148,149,150,151,152,
                                                                                      153,154,155,156,157,158,159,160,166,169,190,191,198,199,200,202,213,214,215},       36,                   "Starts Markov chain Monte Carlo analysis",  IN_CMD, SHOW },
             { 28,           "Mcmcp",  NO,           DoMcmcp, 46,  {17,18,19,20,21,22,23,24,25,26,27,84,98,112,113,114,115,116,132,142,143,144,148,149,150,151,152,
@@ -358,6 +357,7 @@ CmdType     commands[] =
                                                                                                                                                      270,273,274},        4,             "Unlinks parameters across character partitions",  IN_CMD, SHOW },
             { 59,        "Usertree", YES,        DoUserTree,  1,                                                                                            {203},        8,                                 "Defines a single user tree",  IN_CMD, HIDE },
             { 60,         "Version",  NO,         DoVersion,  0,                                                                                             {-1},       32,                                      "Shows program version",  IN_CMD, SHOW },
+            { 61,      "Compareref",  NO,     DoCompRefTree,  7,                                                                    {127,128,129,130,221,222,223},       36,                     "Compares the tree to the reference trees",  IN_CMD, HIDE },
             /* NOTE: If you add a command here, make certain to change NUMCOMMANDS (above, in this file) appropriately! */
             { 999,             NULL,  NO,              NULL,  0,                                                                                             {-1},       32,                                                           "",  IN_CMD, HIDE }  
             };
@@ -452,7 +452,7 @@ int AddNameSet (NameSet **nameSetList, int numNameSets, char **nameSet, int numN
 {
     int     i;
 
-    (*nameSetList) = (NameSet*) SafeRealloc ((void*)(*nameSetList), (size_t)(((numNameSets+1)*sizeof(NameSet))));
+    (*nameSetList) = (NameSet*) SafeRealloc ((void*)(*nameSetList), ((size_t)numNameSets+1)*sizeof(NameSet));
 
     (*nameSetList)[numNameSets].names    = NULL;
     (*nameSetList)[numNameSets].numNames = numNames;
@@ -469,11 +469,11 @@ int AddNameSet (NameSet **nameSetList, int numNameSets, char **nameSet, int numN
       the counter holding the length of the list. */
 int AddString (char ***list, int len, char *token)
 {
-    (*list) = (char **) SafeRealloc ((void *)(*list), (size_t)((len+1)*sizeof(char*)));
+    (*list) = (char **) SafeRealloc ((void *)(*list), ((size_t)len+1)*sizeof(char*));
     if (!(*list))
         return ERROR;
 
-    (*list)[len] = (char *) SafeCalloc ((size_t)(strlen(token)+1), sizeof(char));
+    (*list)[len] = (char *) SafeCalloc ((strlen(token)+1), sizeof(char));
     if (!(*list)[len])
         return ERROR;
 
@@ -489,7 +489,7 @@ int AllocCharacters (void)
 
     if (memAllocs[ALLOC_MATRIX] == YES)
         goto errorExit;
-    matrix = (int *)SafeMalloc((size_t) (numTaxa * numChar * sizeof(int)));
+    matrix = (int *) SafeMalloc((size_t)numTaxa * (size_t)numChar * sizeof(int));
     if (!matrix)
         {
         MrBayesPrint ("%s   Problem allocating matrix (%d)\n", spacer, numTaxa * numChar * sizeof(int));
@@ -501,7 +501,7 @@ int AllocCharacters (void)
 
     if (memAllocs[ALLOC_CHARINFO] == YES)
         goto errorExit;
-    charInfo = (CharInformation *)SafeMalloc((size_t) (numChar * sizeof(CharInformation)));
+    charInfo = (CharInformation *) SafeMalloc ((size_t)numChar * sizeof(CharInformation));
     if (!charInfo)
         {
         MrBayesPrint ("%s   Problem allocating charInfo (%d)\n", spacer, numChar * sizeof(CharInformation));
@@ -530,9 +530,9 @@ int AllocCharacters (void)
     if (memAllocs[ALLOC_PARTITIONS] == YES)
         goto errorExit;
     partitionNames = NULL;
-    partitionId = (int**) SafeMalloc ((size_t)(numChar*sizeof(int*)));
+    partitionId = (int**) SafeMalloc ((size_t)numChar * sizeof(int*));
     for (i=0; i<numChar; i++)
-        partitionId[i] = (int *) SafeMalloc ((size_t)(1 * sizeof(int)));
+        partitionId[i] = (int *) SafeMalloc (sizeof(int));
     numDefinedPartitions = 0;   /* number of defined partitions */
     memAllocs[ALLOC_PARTITIONS] = YES;  /* safe to do free */
 
@@ -559,8 +559,8 @@ int AllocCharacters (void)
         tempSetSize = numChar;
     else
         tempSetSize = numTaxa;
-    tempSet = (int *)SafeRealloc((void *)tempSet, (size_t) (tempSetSize * sizeof(int)));
-    tempSetNeg = (int *)SafeRealloc((void *)tempSetNeg, (size_t) (tempSetSize * sizeof(int)));
+    tempSet = (int *) SafeRealloc ((void *)tempSet, (size_t)tempSetSize * sizeof(int));
+    tempSetNeg = (int *) SafeRealloc ((void *)tempSetNeg, (size_t)tempSetSize * sizeof(int));
     if (!tempSet || !tempSetNeg)
         {
         MrBayesPrint ("%s   Problem reallocating tempSet (%d)\n", spacer, tempSetSize * sizeof(int));
@@ -605,12 +605,12 @@ int AllocTaxa (void)
     if (memAllocs[ALLOC_TAXA] == YES)
         goto errorExit;
     taxaNames = NULL;   /* This variable is allocated in AddString */
-    taxaInfo = (TaxaInformation *)SafeMalloc((size_t) (numTaxa * sizeof(TaxaInformation)));
+    taxaInfo = (TaxaInformation *) SafeMalloc ((size_t)numTaxa * sizeof(TaxaInformation));
     if (!taxaInfo)
         {
         goto errorExit;
         }
-    tipCalibration = (Calibration *)SafeMalloc((size_t) (numTaxa * sizeof(Calibration)));
+    tipCalibration = (Calibration *) SafeMalloc ((size_t)numTaxa * sizeof(Calibration));
     if (!tipCalibration)
         {
         free (taxaInfo);
@@ -637,10 +637,10 @@ int AllocTaxa (void)
         goto errorExit;
     speciespartitionNames = NULL;
     speciesNameSets = NULL;
-    speciespartitionId = (int**) SafeMalloc ((size_t)(numTaxa*sizeof(int*)));
+    speciespartitionId = (int**) SafeMalloc ((size_t)numTaxa * sizeof(int*));
     for (i=0; i<numTaxa; i++)
         {
-        speciespartitionId[i] = (int *) SafeMalloc ((size_t)(1 * sizeof(int)));
+        speciespartitionId[i] = (int *) SafeMalloc (sizeof(int));
         speciespartitionId[i][0] = i + 1;   /* 1-based taxon index, do not ask me why */
         }
     numDefinedSpeciespartitions = 0;   /* number of defined species partitions */
@@ -667,8 +667,8 @@ int AllocTaxa (void)
     /* tempSet */
     if (memAllocs[ALLOC_TMPSET] == YES)
         goto errorExit;
-    tempSet = (int *) SafeMalloc ((size_t)(numTaxa*sizeof(int)));
-    tempSetNeg = (int *) SafeMalloc ((size_t)(numTaxa*sizeof(int)));
+    tempSet = (int *) SafeMalloc ((size_t)numTaxa * sizeof(int));
+    tempSetNeg = (int *) SafeMalloc ((size_t)numTaxa * sizeof(int));
     if (!tempSet || !tempSetNeg)
         goto errorExit;
     memAllocs[ALLOC_TMPSET] = YES;
@@ -1667,7 +1667,7 @@ int DoCharsetParm (char *parmName, char *tkn)
             
             fromI = toJ = everyK = -1;
             foundDash = foundSlash = NO;
-            MrBayesPrint ("%s   Defining charset called %s\n", spacer, tkn);
+            MrBayesPrint ("%s   Defining charset called '%s'\n", spacer, tkn);
             expecting = Expecting(EQUALSIGN);
             }
         else
@@ -1685,12 +1685,12 @@ int DoCharsetParm (char *parmName, char *tkn)
            return an error. */
         if (numCharSets < 1)
             {
-            MrBayesPrint ("%s   Could not find a character set called %s\n", spacer, tkn);
+            MrBayesPrint ("%s   Could not find a character set called '%s'\n", spacer, tkn);
             return (ERROR);
             }
         if (CheckString (charSetNames, numCharSets, tkn, &index) == ERROR)
             {
-            MrBayesPrint ("%s   Could not find a character set called %s\n", spacer, tkn);
+            MrBayesPrint ("%s   Could not find a character set called '%s'\n", spacer, tkn);
             return (ERROR);
             }
         /* add characters from charset "tkn" to new tempset */
@@ -2487,14 +2487,14 @@ int DoConstraint (void)
         }
     else
         {
-        definedConstraintTwo = (BitsLong **) SafeRealloc ((void *)(definedConstraintTwo), (size_t)((numDefinedConstraints+1)*sizeof(BitsLong *)));
+        definedConstraintTwo = (BitsLong **) SafeRealloc ((void *)(definedConstraintTwo), ((size_t)numDefinedConstraints+1)*sizeof(BitsLong *));
         if (definedConstraintTwo==NULL)
             return ERROR;
         definedConstraintTwo[numDefinedConstraints]=NULL;
         }
     
     /* add a default node calibration */
-    nodeCalibration = (Calibration *) SafeRealloc ((void *)nodeCalibration, (size_t)((numDefinedConstraints+1)*sizeof(Calibration)));
+    nodeCalibration = (Calibration *) SafeRealloc ((void *)nodeCalibration, ((size_t)numDefinedConstraints+1)*sizeof(Calibration));
     nodeCalibration[numDefinedConstraints].prior            = defaultCalibration.prior;
     nodeCalibration[numDefinedConstraints].priorParams[0]   = defaultCalibration.priorParams[0];
     nodeCalibration[numDefinedConstraints].priorParams[1]   = defaultCalibration.priorParams[1];
@@ -2511,25 +2511,25 @@ int DoConstraint (void)
     /* reallocate and initialize space for activeConstraints */
     for (i=0; i<numCurrentDivisions; i++)
         {
-        modelParams[i].activeConstraints = (int *) SafeRealloc((void *)(modelParams[i].activeConstraints), (size_t)(numDefinedConstraints*sizeof(int)));
+        modelParams[i].activeConstraints = (int *) SafeRealloc((void *)(modelParams[i].activeConstraints), (size_t)numDefinedConstraints*sizeof(int));
         modelParams[i].activeConstraints[numDefinedConstraints-1] = NO;
         }
 
     /* reallocate and initialize space for tempActiveConstraints */
-    tempActiveConstraints = (int *) SafeRealloc((void *)(tempActiveConstraints), (size_t)(numDefinedConstraints*sizeof(int)));
+    tempActiveConstraints = (int *) SafeRealloc((void *)(tempActiveConstraints), (size_t)numDefinedConstraints*sizeof(int));
     tempActiveConstraints[numDefinedConstraints-1] = NO;
 
-    definedConstraintsType = (enum ConstraintType *) SafeRealloc((void *)(definedConstraintsType), (size_t)(numDefinedConstraints*sizeof(enum ConstraintType)));
+    definedConstraintsType = (enum ConstraintType *) SafeRealloc((void *)(definedConstraintsType), (size_t)numDefinedConstraints*sizeof(enum ConstraintType));
     if (definedConstraintsType==NULL)
         return ERROR;
     definedConstraintsType[numDefinedConstraints-1] = consrtainType;
 
-    definedConstraintPruned = (BitsLong **) SafeRealloc ((void *)(definedConstraintPruned), (size_t)((numDefinedConstraints)*sizeof(BitsLong *)));
+    definedConstraintPruned = (BitsLong **) SafeRealloc ((void *)(definedConstraintPruned), (size_t)numDefinedConstraints*sizeof(BitsLong *));
     if (definedConstraintPruned==NULL)
         return ERROR;
     definedConstraintPruned[numDefinedConstraints-1]=NULL;
 
-    definedConstraintTwoPruned = (BitsLong **) SafeRealloc ((void *)(definedConstraintTwoPruned), (size_t)((numDefinedConstraints)*sizeof(BitsLong *)));
+    definedConstraintTwoPruned = (BitsLong **) SafeRealloc ((void *)(definedConstraintTwoPruned), (size_t)numDefinedConstraints*sizeof(BitsLong *));
     if (definedConstraintTwoPruned==NULL)
         return ERROR;
     definedConstraintTwoPruned[numDefinedConstraints-1]=NULL;
@@ -2678,12 +2678,12 @@ int DoConstraintParm (char *parmName, char *tkn)
                 {
                 if (numTaxaSets < 1)
                     {
-                    MrBayesPrint ("%s   Could not find a taxset called %s\n", spacer, tkn);
+                    MrBayesPrint ("%s   Could not find a taxset called '%s'\n", spacer, tkn);
                     return (ERROR);
                     }
                 if (CheckString (taxaSetNames, numTaxaSets, tkn, &index) == ERROR)
                     {
-                    MrBayesPrint ("%s   Could not find a taxset called %s\n", spacer, tkn);
+                    MrBayesPrint ("%s   Could not find a taxset called '%s'\n", spacer, tkn);
                     return (ERROR);
                     }
                 /* add taxa from taxset tkn to new tempSet */
@@ -3041,12 +3041,12 @@ int DoCtypeParm (char *parmName, char *tkn)
             {
             if (numCharSets < 1)
                 {
-                MrBayesPrint ("%s   Could not find a character set called %s\n", spacer, tkn);
+                MrBayesPrint ("%s   Could not find a character set called '%s'\n", spacer, tkn);
                 return (ERROR);
                 }
             if (CheckString (charSetNames, numCharSets, tkn, &index) == ERROR)
                 {
-                MrBayesPrint ("%s   Could not find a character set called %s\n", spacer, tkn);
+                MrBayesPrint ("%s   Could not find a character set called '%s'\n", spacer, tkn);
                 return (ERROR);
                 }
                 
@@ -3247,12 +3247,12 @@ int DoDeleteParm (char *parmName, char *tkn)
                 /* we are using a pre-defined taxa set */
                 if (numTaxaSets < 1)
                     {
-                    MrBayesPrint ("%s   Could not find a taxset called %s\n", spacer, tkn);
+                    MrBayesPrint ("%s   Could not find a taxset called '%s'\n", spacer, tkn);
                     return (ERROR);
                     }
                 if (CheckString (taxaSetNames, numTaxaSets, tkn, &index) == ERROR)
                     {
-                    MrBayesPrint ("%s   Could not find a taxset called %s\n", spacer, tkn);
+                    MrBayesPrint ("%s   Could not find a taxset called '%s'\n", spacer, tkn);
                     return (ERROR);
                     }
                 /* add taxa from taxset tkn to new tempSet */
@@ -3620,7 +3620,7 @@ int DoExecute (void)
     */
 
     /* allocate a string long enough to hold a line */
-    s = (char *)SafeMalloc((size_t) (longestLineLength * sizeof(char)));
+    s = (char *)SafeMalloc((size_t)longestLineLength * sizeof(char));
     if (!s)
         {
         MrBayesPrint ("%s   Problem allocating string for reading file\n", spacer);
@@ -3934,12 +3934,12 @@ int DoExcludeParm (char *parmName, char *tkn)
             /* we are using a pre-defined character set */
             if (numCharSets < 1)
                 {
-                MrBayesPrint ("%s   Could not find a character set called %s\n", spacer, tkn);
+                MrBayesPrint ("%s   Could not find a character set called '%s'\n", spacer, tkn);
                 return (ERROR);
                 }
             if (CheckString (charSetNames, numCharSets, tkn, &index) == ERROR)
                 {
-                MrBayesPrint ("%s   Could not find a character set called %s\n", spacer, tkn);
+                MrBayesPrint ("%s   Could not find a character set called '%s'\n", spacer, tkn);
                 return (ERROR);
                 }
             /* add characters from charset tkn to new tempSet */
@@ -4411,6 +4411,7 @@ int DoFormatParm (char *parmName, char *tkn)
                 expecting |= Expecting(EXCLAMATIONMARK);
                 expecting |= Expecting(PERCENT);
                 expecting |= Expecting(WEIRD);
+                expecting |= Expecting(VERTICALBAR);
                 }
             else if (((expecting & Expecting(ALPHA)) == Expecting(ALPHA)) || 
                      ((expecting & Expecting(QUESTIONMARK)) == Expecting(QUESTIONMARK)) || 
@@ -4419,7 +4420,8 @@ int DoFormatParm (char *parmName, char *tkn)
                      ((expecting & Expecting(ASTERISK)) == Expecting(ASTERISK)) || 
                      ((expecting & Expecting(EXCLAMATIONMARK)) == Expecting(EXCLAMATIONMARK)) || 
                      ((expecting & Expecting(PERCENT)) == Expecting(PERCENT)) || 
-                     ((expecting & Expecting(WEIRD)) == Expecting(WEIRD)))
+                     ((expecting & Expecting(WEIRD)) == Expecting(WEIRD)) ||
+                     ((expecting & Expecting(VERTICALBAR)) == Expecting(VERTICALBAR)))
                 {
                 if (strlen(tkn) == 1)
                     {
@@ -4454,6 +4456,7 @@ int DoFormatParm (char *parmName, char *tkn)
                 expecting |= Expecting(EXCLAMATIONMARK);
                 expecting |= Expecting(PERCENT);
                 expecting |= Expecting(WEIRD);
+                expecting |= Expecting(VERTICALBAR);
                 }
             else if (((expecting & Expecting(ALPHA)) == Expecting(ALPHA)) || 
                      ((expecting & Expecting(QUESTIONMARK)) == Expecting(QUESTIONMARK)) || 
@@ -4462,7 +4465,8 @@ int DoFormatParm (char *parmName, char *tkn)
                      ((expecting & Expecting(ASTERISK)) == Expecting(ASTERISK)) || 
                      ((expecting & Expecting(EXCLAMATIONMARK)) == Expecting(EXCLAMATIONMARK)) || 
                      ((expecting & Expecting(PERCENT)) == Expecting(PERCENT)) || 
-                     ((expecting & Expecting(WEIRD)) == Expecting(WEIRD)))
+                     ((expecting & Expecting(WEIRD)) == Expecting(WEIRD)) ||
+                     ((expecting & Expecting(VERTICALBAR)) == Expecting(VERTICALBAR)))
                 {
                 if (strlen(tkn) == 1)
                     {
@@ -4497,6 +4501,7 @@ int DoFormatParm (char *parmName, char *tkn)
                 expecting |= Expecting(EXCLAMATIONMARK);
                 expecting |= Expecting(PERCENT);
                 expecting |= Expecting(WEIRD);
+                expecting |= Expecting(VERTICALBAR);
                 }
             else if (((expecting & Expecting(ALPHA)) == Expecting(ALPHA)) || 
                      ((expecting & Expecting(QUESTIONMARK)) == Expecting(QUESTIONMARK)) || 
@@ -4505,7 +4510,8 @@ int DoFormatParm (char *parmName, char *tkn)
                      ((expecting & Expecting(ASTERISK)) == Expecting(ASTERISK)) || 
                      ((expecting & Expecting(EXCLAMATIONMARK)) == Expecting(EXCLAMATIONMARK)) || 
                      ((expecting & Expecting(PERCENT)) == Expecting(PERCENT)) || 
-                     ((expecting & Expecting(WEIRD)) == Expecting(WEIRD)))
+                     ((expecting & Expecting(WEIRD)) == Expecting(WEIRD)) ||
+                     ((expecting & Expecting(VERTICALBAR)) == Expecting(VERTICALBAR)))
                 {
                 if (strlen(tkn) == 1)
                     {
@@ -4758,12 +4764,12 @@ int DoIncludeParm (char *parmName, char *tkn)
             /* we are using a pre-defined character set */
             if (numCharSets < 1)
                 {
-                MrBayesPrint ("%s   Could not find a character set called %s\n", spacer, tkn);
+                MrBayesPrint ("%s   Could not find a character set called '%s'\n", spacer, tkn);
                 return (ERROR);
                 }
             if (CheckString (charSetNames, numCharSets, tkn, &index) == ERROR)
                 {
-                MrBayesPrint ("%s   Could not find a character set called %s\n", spacer, tkn);
+                MrBayesPrint ("%s   Could not find a character set called '%s'\n", spacer, tkn);
                 return (ERROR);
                 }
             /* add characters from charset tkn to new tempSet */
@@ -5263,6 +5269,7 @@ int DoMatrixParm (char *parmName, char *tkn)
     expecting |= Expecting(EXCLAMATIONMARK);
     expecting |= Expecting(PERCENT);
     expecting |= Expecting(WEIRD);
+    expecting |= Expecting(VERTICALBAR);
     expecting |= Expecting(SEMICOLON);
     expecting |= Expecting(LEFTPAR);
     expecting |= Expecting(RIGHTPAR);
@@ -5765,7 +5772,7 @@ int DoPartition (void)
         
     /* add new partition */
     for (i=0; i<numChar; i++) {
-        partitionId[i] = (int *) SafeRealloc ((void *)(partitionId[i]), (size_t)((numDefinedPartitions + 1) * sizeof(int)));
+        partitionId[i] = (int *) SafeRealloc ((void *)(partitionId[i]), ((size_t)numDefinedPartitions + 1) * sizeof(int));
         if (!partitionId[i])
             return ERROR;
     }
@@ -5831,7 +5838,7 @@ int DoPartitionParm (char *parmName, char *tkn)
             whichPartition = 0;
             foundFirst = NO;
             numDivisions = 0;
-            MrBayesPrint ("%s   Defining partition called %s\n", spacer, tkn);
+            MrBayesPrint ("%s   Defining partition called '%s'\n", spacer, tkn);
             expecting = Expecting(EQUALSIGN);
             }
         else
@@ -5848,12 +5855,12 @@ int DoPartitionParm (char *parmName, char *tkn)
            return an error. */
         if (numCharSets < 1)
             {
-            MrBayesPrint ("%s   Could not find a character set called %s\n", spacer, tkn);
+            MrBayesPrint ("%s   Could not find a character set called '%s'\n", spacer, tkn);
             return (ERROR);
             }
         if (CheckString (charSetNames, numCharSets, tkn, &index) == ERROR)
             {
-            MrBayesPrint ("%s   Could not find a character set called %s\n", spacer, tkn);
+            MrBayesPrint ("%s   Could not find a character set called '%s'\n", spacer, tkn);
             return (ERROR);
             }
         /* add characters from charset tkn to new tempSet */
@@ -6087,12 +6094,12 @@ int DoRestoreParm (char *parmName, char *tkn)
                 /* we are using a pre-defined taxa set */
                 if (numTaxaSets < 1)
                     {
-                    MrBayesPrint ("%s   Could not find a taxset called %s\n", spacer, tkn);
+                    MrBayesPrint ("%s   Could not find a taxset called '%s'\n", spacer, tkn);
                     return (ERROR);
                     }
                 if (CheckString (taxaSetNames, numTaxaSets, tkn, &index) == ERROR)
                     {
-                    MrBayesPrint ("%s   Could not find a taxset called %s\n", spacer, tkn);
+                    MrBayesPrint ("%s   Could not find a taxset called '%s'\n", spacer, tkn);
                     return (ERROR);
                     }
                 /* add taxa from taxset tkn to new tempSet */
@@ -7313,7 +7320,7 @@ int DoSpeciespartition (void)
     /* add new partition */
     for (i=0; i<numTaxa; i++)
         {
-        speciespartitionId[i] = (int *) SafeRealloc ((void *)(speciespartitionId[i]), (size_t)((numDefinedSpeciespartitions + 1) * sizeof(int)));
+        speciespartitionId[i] = (int *) SafeRealloc ((void *)(speciespartitionId[i]), ((size_t)numDefinedSpeciespartitions + 1) * sizeof(int));
         if (!speciespartitionId[i])
             {
             for (i=0; i<numDivisions; i++)
@@ -7397,7 +7404,7 @@ int DoSpeciespartitionParm (char *parmName, char *tkn)
             whichPartition = 0;
             foundFirst = NO;
             numDivisions = 0;
-            MrBayesPrint ("%s   Defining speciespartition called %s\n", spacer, tkn);
+            MrBayesPrint ("%s   Defining speciespartition called '%s'\n", spacer, tkn);
             expecting = Expecting(EQUALSIGN);
             }
         else
@@ -7422,7 +7429,7 @@ int DoSpeciespartitionParm (char *parmName, char *tkn)
                return an error. */
             if (CheckString (taxaNames, numTaxa, tkn, &index) == ERROR)
                 {
-                MrBayesPrint ("%s   Could not find a tip called %s\n", spacer, tkn);
+                MrBayesPrint ("%s   Could not find a tip called '%s'\n", spacer, tkn);
                 return (ERROR);
                 }
             /* add index of the tip named tkn to new tempSet */
@@ -7690,7 +7697,7 @@ int DoTaxasetParm (char *parmName, char *tkn)
             
             fromI = toJ = everyK = -1;
             foundDash = foundSlash = NO;
-            MrBayesPrint ("%s   Defining taxset called %s\n", spacer, tkn);
+            MrBayesPrint ("%s   Defining taxset called '%s'\n", spacer, tkn);
             expecting = Expecting(EQUALSIGN);
             }
         else
@@ -7710,12 +7717,12 @@ int DoTaxasetParm (char *parmName, char *tkn)
             {
             if (numTaxaSets < 1)
                 {
-                MrBayesPrint ("%s   Could not find a taxset called %s\n", spacer, tkn);
+                MrBayesPrint ("%s   Could not find a taxset called '%s'\n", spacer, tkn);
                 return (ERROR);
                 }
             if (CheckString (taxaSetNames, numTaxaSets, tkn, &index) == ERROR)
                 {
-                MrBayesPrint ("%s   Could not find a taxset called %s\n", spacer, tkn);
+                MrBayesPrint ("%s   Could not find a taxset called '%s'\n", spacer, tkn);
                 return (ERROR);
                 }
             /* add taxa from taxset tkn to new tempSet */
@@ -8286,9 +8293,9 @@ int DoTreeParm (char *parmName, char *tkn)
                 t->nEvents  = (int **) SafeRealloc ((void *)t->nEvents, t->nESets*sizeof(int *));
                 t->position = (MrBFlt ***) SafeRealloc ((void *)t->position, t->nESets*sizeof(MrBFlt **));
                 t->rateMult = (MrBFlt ***) SafeRealloc ((void *)t->rateMult, t->nESets*sizeof(MrBFlt **));
-                t->nEvents[t->nESets-1]  = (int *) SafeCalloc ((size_t)(2*numTaxa), sizeof(int));
-                t->position[t->nESets-1] = (MrBFlt **) SafeCalloc ((size_t)(2*numTaxa), sizeof(MrBFlt *));
-                t->rateMult[t->nESets-1] = (MrBFlt **) SafeCalloc ((size_t)(2*numTaxa), sizeof(MrBFlt *));
+                t->nEvents[t->nESets-1]  = (int *) SafeCalloc (2*(size_t)numTaxa, sizeof(int));
+                t->position[t->nESets-1] = (MrBFlt **) SafeCalloc (2*(size_t)numTaxa, sizeof(MrBFlt *));
+                t->rateMult[t->nESets-1] = (MrBFlt **) SafeCalloc (2*(size_t)numTaxa, sizeof(MrBFlt *));
                 t->eSetName = (char **) SafeRealloc ((void *)t->eSetName, t->nESets*sizeof(char **));
                 }
             SafeStrcpy (&tempNameString,tkn);
@@ -8305,12 +8312,12 @@ int DoTreeParm (char *parmName, char *tkn)
                 {
                 t->nBSets++;
                 t->isRelaxed = YES;
-                t->effectiveBrLen = (MrBFlt **) SafeRealloc ((void *)t->effectiveBrLen, (size_t)(t->nBSets*sizeof(MrBFlt *)));
-                t->effectiveBrLen[t->nBSets-1] = (MrBFlt *) SafeCalloc ((size_t)(2*numTaxa),sizeof(MrBFlt));
+                t->effectiveBrLen = (MrBFlt **) SafeRealloc ((void *)t->effectiveBrLen, (size_t)(t->nBSets)*sizeof(MrBFlt *));
+                t->effectiveBrLen[t->nBSets-1] = (MrBFlt *) SafeCalloc (2*(size_t)numTaxa, sizeof(MrBFlt));
                 for (i=0; i<2*numTaxa; i++)
                     t->effectiveBrLen[t->nBSets-1][i] = 1.0;
-                t->bSetName = (char **) SafeRealloc ((void *)t->bSetName, t->nBSets*sizeof(char **));
-                t->bSetName[t->nBSets-1] = (char *) SafeCalloc (strlen(tkn)+1,sizeof(char));
+                t->bSetName = (char **) SafeRealloc ((void *)t->bSetName, (size_t)(t->nBSets)*sizeof(char *));
+                t->bSetName[t->nBSets-1] = (char *) SafeCalloc (strlen(tkn)+1, sizeof(char));
                 }
             SafeStrcpy (&tempNameString,tkn);
             foundName = YES;
@@ -9055,8 +9062,8 @@ int FreeCharacters (void)
     if (memAllocs[ALLOC_TMPSET] == YES)
         {
         if (numChar > numTaxa)
-            tempSet = (int *) SafeRealloc ((void *) tempSet, (size_t)(numTaxa*sizeof(int)));
-            tempSetNeg = (int *) SafeRealloc ((void *) tempSetNeg, (size_t)(numTaxa*sizeof(int)));
+            tempSet = (int *) SafeRealloc ((void *)tempSet, (size_t)numTaxa*sizeof(int));
+            tempSetNeg = (int *) SafeRealloc ((void *)tempSetNeg, (size_t)numTaxa*sizeof(int));
         }
     if (memAllocs[ALLOC_MATRIX] == YES)
         {
@@ -9486,11 +9493,16 @@ int GetToken (char *token, int *tokenType, char **sourceH)
         *temp++ = *(*sourceH)++;
         *tokenType = AMPERSAND;
         }
-    else if (IsIn(**sourceH,"~+^@|{}`><"))
+    else if (IsIn(**sourceH,"~+^@{}`><"))
         {
         *temp++ = *(*sourceH)++;
         *tokenType = WEIRD;
         }
+    else if (IsIn(**sourceH,"|"))
+        {
+        *temp++ = *(*sourceH)++;
+        *tokenType = VERTICALBAR;
+        }
 
     *temp = '\0';
     return (NO_ERROR);
@@ -10327,9 +10339,9 @@ int GetUserHelp (char *helpTkn)
         MrBayesPrint ("                above and a large number of others, with or without name.        \n");
         MrBayesPrint ("   Code      -- Enforces the use of a particular genetic code. The default       \n");
         MrBayesPrint ("                is the universal code. Other options include \"vertmt\" for      \n");
-        MrBayesPrint ("                vertebrate mitocondrial DNA, \"mycoplasma\", \"yeast\",          \n");
-        MrBayesPrint ("                \"ciliates\", and \"metmt\" (for metazoan mitochondrial DNA      \n");
-        MrBayesPrint ("                except vertebrates).                                             \n");
+        MrBayesPrint ("                vertebrate mitocondrial, \"invermt\", \"mycoplasma\", \"yeast\", \n");
+        MrBayesPrint ("                \"ciliate\", \"echinoderm\", \"euplotid\", and \"metmt\" (for    \n");
+        MrBayesPrint ("                metazoan mitochondrial except vertebrates).                      \n");
         MrBayesPrint ("   Ploidy    -- Specifies the ploidy of the organism. Options are \"Haploid\",   \n");
         MrBayesPrint ("                \"Diploid\" or \"Zlinked\". This option is used when a coalescent\n");
         MrBayesPrint ("                prior is used on trees.                                          \n");
@@ -10423,15 +10435,19 @@ int GetUserHelp (char *helpTkn)
         MrBayesPrint ("                a specified substitution model (specified using the other        \n");
         MrBayesPrint ("                lset options).                                                   \n");
         MrBayesPrint ("   Coding    -- This specifies how characters were sampled. If all site patterns \n");
-        MrBayesPrint ("                had the possibility of being sampled, then \"all\" should be     \n");
-        MrBayesPrint ("                specified (the default). Otherwise \"variable\" (only variable   \n");
-        MrBayesPrint ("                characters had the possibility of being sampled), \"noabsence\"  \n");
-        MrBayesPrint ("                (characters for which all taxa were coded as absent were not     \n");
-        MrBayesPrint ("                sampled), and \"nopresence\" (characters for which all taxa were \n");
-        MrBayesPrint ("                coded as present were not sampled. \"All\" works for all data    \n");
-        MrBayesPrint ("                types. However, the others only work for morphological (all/     \n");
-        MrBayesPrint ("                variable) or restriction site (all/variable/noabsence/nopresence)\n");
-        MrBayesPrint ("                data.                                                            \n");
+        MrBayesPrint ("                had the possibility of being sampled, then \"All\" should be     \n");
+        MrBayesPrint ("                specified (the default). Otherwise \"Variable\" (only variable   \n");
+        MrBayesPrint ("                characters had the possibility of being sampled), \"Informative\"\n");
+        MrBayesPrint ("                (only parsimony informative characters has the possibility of    \n");
+        MrBayesPrint ("                being sampled), \"Nosingletons\" (characters which are constant  \n");
+        MrBayesPrint ("                in all but one taxon were not sampled), \"Noabsencesites\" (char-\n");
+        MrBayesPrint ("                acters for which all taxa were coded as absent were not sampled),\n");
+        MrBayesPrint ("                \"Nopresencesites\" (characters for which all taxa were coded as \n");
+        MrBayesPrint ("                present were not sampled). \"All\" works for all data types.     \n");
+        MrBayesPrint ("                However, the others only work for morphological (All/Variable/   \n");
+        MrBayesPrint ("                Informative/Nosingletons) or restriction site (All/Variable/     \n");
+        MrBayesPrint ("                Informative/Nosingletons/Noabsencesites/Nopresencesites/         \n");
+        MrBayesPrint ("                Nosingletonpresence/Nosingletonabsence) data.                    \n");
         MrBayesPrint ("   Parsmodel -- This forces calculation under the so-called parsimony model      \n");
         MrBayesPrint ("                described by Tuffley and Steel (1998). The options are \"yes\"   \n");
         MrBayesPrint ("                or \"no\". Note that the biological assumptions of this model    \n");
@@ -10463,26 +10479,27 @@ int GetUserHelp (char *helpTkn)
             MrBayesPrint ("                                                                                 \n");
             MrBayesPrint ("   Parameter    Options                               Current Setting            \n");
             MrBayesPrint ("   ------------------------------------------------------------------            \n");       
-            MrBayesPrint ("   Nucmodel     4by4/Doublet/Codon/Protein            %s                         \n", mp->nucModel);
-            MrBayesPrint ("   Nst          1/2/6/Mixed                           %s                         \n", mp->nst);
-            MrBayesPrint ("   Code         Universal/Vertmt/Mycoplasma/                                     \n");
-            MrBayesPrint ("                Yeast/Ciliates/Metmt                  %s                         \n", mp->geneticCode);
-            MrBayesPrint ("   Ploidy       Haploid/Diploid/Zlinked               %s                         \n", mp->ploidy);
+            MrBayesPrint ("   Nucmodel     4by4/Doublet/Codon/Protein              %s                       \n", mp->nucModel);
+            MrBayesPrint ("   Nst          1/2/6/Mixed                             %s                       \n", mp->nst);
+            MrBayesPrint ("   Code         Universal/Vertmt/Invermt/Yeast/Mycoplasma/                       \n");
+            MrBayesPrint ("                Ciliate/Echinoderm/Euplotid/Metmt       %s                       \n", mp->geneticCode);
+            MrBayesPrint ("   Ploidy       Haploid/Diploid/Zlinked                 %s                       \n", mp->ploidy);
             MrBayesPrint ("   Rates        Equal/Gamma/LNorm/Propinv/                                       \n");
-            MrBayesPrint ("                Invgamma/Adgamma                      %s                         \n", mp->ratesModel);
-            MrBayesPrint ("   Ngammacat    <number>                              %d                         \n", mp->numGammaCats);
+            MrBayesPrint ("                Invgamma/Adgamma                        %s                       \n", mp->ratesModel);
+            MrBayesPrint ("   Ngammacat    <number>                                %d                       \n", mp->numGammaCats);
 #if 0
 /* Temporarily disable this because of conflict with likelihood calculators. It should be renamed to samplerates when reintroduced. */
-            MrBayesPrint ("   Usegibbs     Yes/No                                %s                         \n", mp->useGibbs);
-            MrBayesPrint ("   Gibbsfreq    <number>                              %d                         \n", mp->gibbsFreq);
+            MrBayesPrint ("   Usegibbs     Yes/No                                  %s                       \n", mp->useGibbs);
+            MrBayesPrint ("   Gibbsfreq    <number>                                %d                       \n", mp->gibbsFreq);
 #endif
-            MrBayesPrint ("   Nbetacat     <number>                              %d                         \n", mp->numBetaCats);
-            MrBayesPrint ("   Omegavar     Equal/Ny98/M3                         %s                         \n", mp->omegaVar);
-            MrBayesPrint ("   Covarion     No/Yes                                %s                         \n", mp->covarionModel);
-            MrBayesPrint ("   Coding       All/Variable/Noabsencesites/                                     \n");
-            MrBayesPrint ("                Nopresencesites                       %s                         \n", mp->coding);
-            MrBayesPrint ("   Parsmodel    No/Yes                                %s                         \n", mp->parsModel);
-        /*  MrBayesPrint ("   Augment      No/Yes                                %s                         \n", mp->augmentData); */
+            MrBayesPrint ("   Nbetacat     <number>                                %d                       \n", mp->numBetaCats);
+            MrBayesPrint ("   Omegavar     Equal/Ny98/M3                           %s                       \n", mp->omegaVar);
+            MrBayesPrint ("   Covarion     No/Yes                                  %s                       \n", mp->covarionModel);
+            MrBayesPrint ("   Coding       All/Variable/Informative/Nosingletons                            \n");
+            MrBayesPrint ("                Noabsencesites/Nopresencesites/                                  \n");
+            MrBayesPrint ("                Nosingletonabsence/Nosingletonpresence  %s                       \n", mp->codingString);
+            MrBayesPrint ("   Parsmodel    No/Yes                                  %s                       \n", mp->parsModel);
+        /*  MrBayesPrint ("   Augment      No/Yes                                  %s                       \n", mp->augmentData); */
             MrBayesPrint ("   ------------------------------------------------------------------            \n");       
             MrBayesPrint ("                                                                                 \n");
             }
@@ -10765,18 +10782,18 @@ int GetUserHelp (char *helpTkn)
         MrBayesPrint ("                    The fact that the labelling of morphological characters is   \n");
         MrBayesPrint ("                    arbitrary makes it difficult to allow unequal character-     \n");
         MrBayesPrint ("                    state frequencies. MrBayes gets around this problem by       \n");
-        MrBayesPrint ("                    assuming that the states have a dirichlet prior, with all    \n");
-        MrBayesPrint ("                    states having equal frequency. The variation in the diri-    \n");
-        MrBayesPrint ("                    chlet can be controlled by this parameter--symdirihyperpr.   \n");
-        MrBayesPrint ("                    Symdirihyperpr specifies the distribution on the variance    \n");
-        MrBayesPrint ("                    parameter of the dirichlet. The valid options are:           \n");
+        MrBayesPrint ("                    assuming that the states have a symmetric Dirichlet prior    \n");
+        MrBayesPrint ("                    (i.e. all Dirichlet parameters are equal). The variation in  \n");
+        MrBayesPrint ("                    the Dirichlet can be controlled by this parameter.           \n");
+        MrBayesPrint ("                    Symdirihyperpr specifies the distribution on the parameter   \n");
+        MrBayesPrint ("                    of the symmetric Dirichlet. The valid options are:           \n");
         MrBayesPrint ("                                                                                 \n");
         MrBayesPrint ("                       prset Symdirihyperpr = uniform(<number>,<number>)         \n");
         MrBayesPrint ("                       prset Symdirihyperpr = exponential(<number>)              \n");
         MrBayesPrint ("                       prset Symdirihyperpr = fixed(<number>)                    \n");
         MrBayesPrint ("                       prset Symdirihyperpr = fixed(infinity)                    \n");
         MrBayesPrint ("                                                                                 \n");
-        MrBayesPrint ("                    If \"fixed(infinity)\" is chosen, the dirichlet prior is     \n");
+        MrBayesPrint ("                    If \"fixed(infinity)\" is chosen, the Dirichlet prior is     \n");
         MrBayesPrint ("                    fixed such that all character states have equal frequency.   \n");
         MrBayesPrint ("   Topologypr    -- This parameter specifies the prior probabilities of          \n");
         MrBayesPrint ("                    phylogenies. The options are:                                \n");
@@ -12930,9 +12947,9 @@ else if (!strcmp(helpTkn, "Set"))
         MrBayesPrint ("   tree distance values.                                                         \n");
         MrBayesPrint ("                                                                                 \n");
         MrBayesPrint ("   Note that the \"Sumt\" command provides a different set of convergence diag-  \n");
-        MrBayesPrint ("   nostics tools that you may also want to explore. Unlike \"Comparetree\", \"Sumt\"\n");
-        MrBayesPrint ("   can compare more than two tree samples and will calculate consensus trees and \n");
-        MrBayesPrint ("   split frequencies from the pooled samples.                                    \n");
+        MrBayesPrint ("   nostics tools that you may also want to explore. Unlike \"Comparetree\",      \n");
+        MrBayesPrint ("   \"Sumt\" can compare more than two tree samples and will calculate consensus  \n");
+        MrBayesPrint ("   trees and split frequencies from the pooled samples.                          \n");
         MrBayesPrint ("                                                                                 \n");
         MrBayesPrint ("   Options:                                                                      \n");
         MrBayesPrint ("                                                                                 \n");
@@ -14187,17 +14204,17 @@ int SetPartition (int part)
         }
     memAllocs[ALLOC_MODEL] = YES;
 
-    numVars = (int *) SafeRealloc ((void *) numVars, (size_t)(3 * numCurrentDivisions * sizeof(int)));
+    numVars = (int *) SafeRealloc ((void *) numVars, 3 * (size_t)numCurrentDivisions * sizeof(int));
     tempLinkUnlinkVec = numVars + numCurrentDivisions;
     activeParts       = numVars + 2*numCurrentDivisions;
 
-    tempNum = (MrBFlt *) SafeRealloc ((void *) tempNum, (size_t)(6 * sizeof(MrBFlt)));
+    tempNum = (MrBFlt *) SafeRealloc ((void *) tempNum, 6 * sizeof(MrBFlt));
 
-    activeParams[0] = (int *) SafeRealloc ((void *) (activeParams[0]), (size_t)(NUM_LINKED * numCurrentDivisions * sizeof(int)));
+    activeParams[0] = (int *) SafeRealloc ((void *) (activeParams[0]), (size_t)NUM_LINKED * (size_t)numCurrentDivisions * sizeof(int));
     for (i=1; i<NUM_LINKED; i++)
         activeParams[i] = activeParams[0] + i*numCurrentDivisions;
  
-    linkTable[0] = (int *) SafeRealloc ((void *) (linkTable[0]), (size_t)(3 * NUM_LINKED * numCurrentDivisions * sizeof(int)));
+    linkTable[0] = (int *) SafeRealloc ((void *) (linkTable[0]), 3 * (size_t)NUM_LINKED * (size_t)numCurrentDivisions * sizeof(int));
     tempLinkUnlink[0] = linkTable[0] + NUM_LINKED*numCurrentDivisions;
     for (i=1; i<NUM_LINKED; i++)
         {
@@ -14289,8 +14306,8 @@ void SetUpParms (void)
     PARAM  (30, "Aamodel",        DoLsetParm,        "Poisson|Equalin|Jones|Dayhoff|Mtrev|Mtmam|Wag|Rtrev|Cprev|Vt|Blosum|Blossum|LG|\0");
     PARAM  (31, "Parsmodel",      DoLsetParm,        "Yes|No|\0");
     PARAM  (32, "Omegavar",       DoLsetParm,        "Equal|Ny98|M3|M10|\0");
-    PARAM  (33, "Code",           DoLsetParm,        "Universal|Vertmt|Mycoplasma|Yeast|Ciliates|Metmt|\0");
-    PARAM  (34, "Coding",         DoLsetParm,        "All|Variable|Noabsencesites|Nopresencesites|Informative|\0");
+    PARAM  (33, "Code",           DoLsetParm,        "Universal|Vertmt|Invermt|Mycoplasma|Yeast|Ciliate|Echinoderm|Euplotid|Metmt|\0");
+    PARAM  (34, "Coding",         DoLsetParm,        "All|Variable|Informative|Nosingletons|Noabsencesites|Nopresencesites|Nosingletonpresence|Nosingletonabsence|\0");
     PARAM  (35, "Seqerror",       DoPrsetParm,       "\0");
     PARAM  (36, "Tratiopr",       DoPrsetParm,       "Beta|Fixed|\0");
     PARAM  (37, "Revmatpr",       DoPrsetParm,       "Dirichlet|Fixed|\0");
@@ -14911,6 +14928,13 @@ void WhatVariableExp (BitsLong exp, char *st)
             strcat(st, " <whatever>");
             n++;
             }
+        if ((exp & Expecting(VERTICALBAR)) == Expecting(VERTICALBAR))
+            {
+            if (n > 0)
+                strcat(st, " or");
+            strcat(st, " |");
+            n++;
+            }
         if ((exp & Expecting(UNKNOWN_TOKEN_TYPE)) == Expecting(UNKNOWN_TOKEN_TYPE))
             {
             if (n > 0)
diff --git a/src/likelihood.c b/src/likelihood.c
index e1e7834..8fb631c 100644
--- a/src/likelihood.c
+++ b/src/likelihood.c
@@ -4915,9 +4915,9 @@ int CondLikeScaler_Std (TreeNode *p, int division, int chain)
     for (c=0; c<m->numChars; c++)
         {
         if (m->nStates[c] == 2)
-                numReps += m->numBetaCats * 2;
-            else
-                numReps += m->nStates[c];
+            numReps += m->numBetaCats * 2;
+        else
+            numReps += m->nStates[c];
         }
 
     /* find conditional likelihood pointers */
@@ -6560,9 +6560,9 @@ int Likelihood_Std (TreeNode *p, int division, int chain, MrBFlt *lnL, int which
     for (c=0; c<m->numChars; c++)
         {
         if (m->nStates[c] == 2)
-                numReps += m->numBetaCats * 2;
-            else
-                numReps += m->nStates[c];
+            numReps += m->numBetaCats * 2;
+        else
+            numReps += m->nStates[c];
         }
     /* find conditional likelihood pointers */
     clPtr = m->condLikes[m->condLikeIndex[chain][p->index]];
@@ -6578,7 +6578,7 @@ int Likelihood_Std (TreeNode *p, int division, int chain, MrBFlt *lnL, int which
 
     /* find gamma category number and frequencies */
     nGammaCats = m->numGammaCats;
-    gammaFreq = 1.0 /  nGammaCats;
+    gammaFreq = 1.0 / nGammaCats;
 
     /* find site scaler */
     lnScaler = m->scalers[m->siteScalerIndex[chain]];
@@ -6653,7 +6653,7 @@ int Likelihood_Std (TreeNode *p, int division, int chain, MrBFlt *lnL, int which
             if (nStates == 2)
                 {
                 nBetaCats = m->numBetaCats;
-                catFreq = gammaFreq /  nBetaCats;
+                catFreq = gammaFreq / nBetaCats;
                 }
             else
                 {
@@ -6687,7 +6687,7 @@ int Likelihood_Std (TreeNode *p, int division, int chain, MrBFlt *lnL, int which
             if (nStates == 2)
                 {
                 nBetaCats = m->numBetaCats;
-                catFreq = gammaFreq /  nBetaCats;
+                catFreq = gammaFreq / nBetaCats;
                 }
             else
                 {
diff --git a/src/mcmc.c b/src/mcmc.c
index 7984be8..4912f17 100644
--- a/src/mcmc.c
+++ b/src/mcmc.c
@@ -49,7 +49,7 @@
 #endif
 #include <signal.h>
 
-const char* const svnRevisionMcmcC = "$Rev: 1031 $";   /* Revision keyword which is expanded/updated by svn on each commit/update */
+const char* const svnRevisionMcmcC = "$Rev: 1072 $";   /* Revision keyword which is expanded/updated by svn on each commit/update */
 
 #if defined (WIN_VERSION) && !defined (__GNUC__)
 #define VISUAL
@@ -205,6 +205,7 @@ void      PrintTiProbs (CLFlt *tP, MrBFlt *bs, int nStates);
 int       PrintTopConvInfo (void);
 void      PrintToScreen (int curGen, int startGen, time_t endingT, time_t startingT);
 int       PrintTree (int curGen, Param *treeParam, int chain, int showBrlens, MrBFlt clockRate);
+MrBFlt    PropAncFossil (Param *param, int chain);
 #if defined (MPI_ENABLED)
 int       ReassembleMoveInfo (void);
 int       ReassembleParamVals (int *curId);
@@ -341,6 +342,9 @@ int             lowestLocalRunId;            /* lowest local run Id
 int             highestLocalRunId;           /* highest local run Id                         */
 #endif
 
+#if defined (PRINT_DUMP)
+FILE            **fpDump = NULL;             /* pointer to .dump file(s)                     */
+#endif
 
 /* AddPartition: Add a partition to the tree keeping track of partition frequencies */
 PFNODE *AddPartition (PFNODE *r, BitsLong *p, int runId)
@@ -444,7 +448,7 @@ int AddTreeSamples (int from, int to, int saveToList)
         return (NO_ERROR);
 #   endif
 
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         {
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
@@ -503,12 +507,12 @@ int AddTreeSamples (int from, int to, int saveToList)
                 {
                 do {
                     if (fgets (lineBuf, longestLine, fp) == NULL) 
-                            {
-                            SafeFclose (&fp);
-                            free (lineBuf);
-                            free (tempStr);
+                        {
+                        SafeFclose (&fp);
+                        free (lineBuf);
+                        free (tempStr);
                         return ERROR;
-                                                }
+                        }
                     word = strtok (lineBuf, " ");
                     } while (strcmp (word, "tree") != 0);
                 if (k>=from)
@@ -1704,7 +1708,7 @@ void CalcPartFreqStats (PFNODE *p, STATS *stat)
 
     n = chainParams.numRuns;
     min = (int)(chainParams.minPartFreq * stat->numSamples);
-    if (((MrBFlt)min) != chainParams.minPartFreq * stat->numSamples)
+    if ((MrBFlt)min != chainParams.minPartFreq * stat->numSamples)
         min++;
 
     /* recursively compute partition frequencies for all subpartitions */
@@ -1813,6 +1817,56 @@ void CalcTopoConvDiagn (int numSamples)
 }
 
 
+/* used in DoCompRefTree */
+void PartFreq (PFNODE *p, STATS *stat, int *ntrees)
+{
+    int     i, n = chainParams.numRuns;
+    MrBFlt  f, sum, sumsq, stdev;
+    
+    /* recursively compute partition frequencies for all subpartitions */
+    if (p->left != NULL)
+        PartFreq (p->left, stat, ntrees);
+    if (p->right != NULL)
+        PartFreq (p->right, stat, ntrees);
+    
+    sum = sumsq = 0.0;
+    for (i=0; i<chainParams.numRuns; i++)
+        {
+        f = (MrBFlt)(p->count[i]) / (MrBFlt)ntrees[i];
+        sum += f;
+        sumsq += f * f;
+        }
+    
+    f = (sumsq - sum * sum / n) / (n - 1);
+    if (f < 0.0)
+        stdev = 0.0;
+    else
+        stdev = sqrt (f);
+    
+    stat->sum += stdev;
+    if (stat->max < stdev)
+        stat->max = stdev;
+    
+    stat->numPartitions++;
+}
+void CalcTopoConvDiagn2 (int *nTrees)
+{
+    int     n;
+    STATS   *stat;
+    
+    for (n=0; n<numTopologies; n++)
+        {
+        stat = &chainParams.stat[n];
+        stat->numPartitions = 0.0;
+        stat->sum = stat->max = 0.0;
+    
+        PartFreq (partFreqTreeRoot[n], stat, nTrees);
+        
+        stat->avgStdDev = stat->sum / stat->numPartitions;
+        }
+}
+
+
 int CheckTemperature (void)
 {
     if (chainParams.userDefinedTemps == YES)
@@ -1830,38 +1884,30 @@ int CheckTemperature (void)
 
 void CloseMBPrintFiles (void)
 {
-    int     i, k, n;
+    int     i, n;
 
-    for (n=0; n<chainParams.numRuns; n++)
-        {
 #   if defined (MPI_ENABLED)
-        if (proc_id == 0)
-            {
+    if (proc_id != 0)
+        return;
 #   endif
-        k = n;
 
-        SafeFclose (&fpParm[k]);
+    for (n=0; n<chainParams.numRuns; n++)
+        {
+        SafeFclose (&fpParm[n]);
+#if defined (PRINT_DUMP)
+        SafeFclose (&fpDump[n]);
+#endif
 
         for (i=0; i<numTrees; i++)
             {
-            if (fpTree[k][i])
+            if (fpTree[n][i])
                 {
-                fprintf (fpTree[k][i], "end;\n");
-                SafeFclose (&fpTree[k][i]);
+                fprintf (fpTree[n][i], "end;\n");
+                SafeFclose (&fpTree[n][i]);
                 }
-            fpTree[k][i] = NULL;
             }
-
-#   if defined (MPI_ENABLED)
-            }
-#   endif
         }
 
-#   if defined (MPI_ENABLED)
-    if (proc_id != 0)
-        return;
-#   endif
-
     if (chainParams.mcmcDiagn == YES)
         SafeFclose (&fpMcmc);
 
@@ -2045,7 +2091,7 @@ void CopySiteScalers (ModelInfo *m, int chain)
 #   endif
     from = m->scalers[m->siteScalerScratchIndex];
     to   = m->scalers[m->siteScalerIndex[chain]];
-    memcpy ((void*) to, (void*) from, (size_t)(m->numChars*sizeof(CLFlt)));
+    memcpy ((void*) to, (void*) from, (size_t)(m->numChars) * sizeof(CLFlt));
 }
 
 
@@ -2385,8 +2431,8 @@ int DoMcmc (void)
        
         /* Get starting values from checkpoint file */
         MrBayesPrint ("%s   Getting values from previous run\n", spacer);
-        strcpy(inputFileName,chainParams.chainFileName);
-        strcat(inputFileName,".ckp");
+        strcpy(inputFileName, chainParams.chainFileName);
+        strcat(inputFileName, ".ckp");
         if (OpenTextFileR(inputFileName) == NULL)
             {
             MrBayesPrint ("%s   Could not find the checkpoint file '%s'.\n", spacer, inputFileName);
@@ -2736,7 +2782,7 @@ int DoMcmcParm (char *parmName, char *tkn)
     char        *tempStr;
     int         tempStrSize = TEMPSTRSIZE;
     
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         {
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
@@ -4162,7 +4208,7 @@ int FillNumSitesOfPat (void)
             }
         
         /* allocate memory */
-        increased = (int *)SafeMalloc((size_t) (2 * numCompressedChars * sizeof(int)));
+        increased = (int *)SafeMalloc(2 * (size_t)numCompressedChars * sizeof(int));
         if (!increased)
             {
             MrBayesPrint ("%s   Problem reallocating increased (%d)\n", spacer, numCompressedChars * chainParams.numChains * sizeof(int));
@@ -8204,7 +8250,7 @@ int LnBirthDeathPriorPrRandom (Tree *t, MrBFlt clockRate, MrBFlt *prob, MrBFlt s
     TreeNode        *p;
 
     /* allocate space for the speciation times */
-    nt = (MrBFlt *)SafeMalloc((size_t) (t->nIntNodes) * sizeof(MrBFlt));
+    nt = (MrBFlt *)SafeMalloc((size_t)(t->nIntNodes) * sizeof(MrBFlt));
     if (!nt)
         {
         MrBayesPrint ("\n   ERROR: Problem allocating nt\n");
@@ -8264,7 +8310,7 @@ int LnBirthDeathPriorPrDiversity (Tree *t, MrBFlt clockRate, MrBFlt *prob, MrBFl
     TreeNode        *p;
     
     /* allocate space for the speciation times */
-    nt = (MrBFlt *)SafeMalloc((size_t) (t->nIntNodes) * sizeof(MrBFlt));
+    nt = (MrBFlt *)SafeMalloc((size_t)(t->nIntNodes) * sizeof(MrBFlt));
     if (!nt)
         {
         MrBayesPrint ("\n   ERROR: Problem allocating nt\n");
@@ -8335,7 +8381,7 @@ int LnBirthDeathPriorPrCluster (Tree *t, MrBFlt clockRate, MrBFlt *prob, MrBFlt
     TreeNode        *p;
     
     /* allocate space for the speciation times */
-    nt = (MrBFlt *)SafeMalloc((size_t) (t->nIntNodes) * sizeof(MrBFlt));
+    nt = (MrBFlt *)SafeMalloc((size_t)(t->nIntNodes) * sizeof(MrBFlt));
     if (!nt)
         {
         MrBayesPrint ("\n   ERROR: Problem allocating nt\n");
@@ -8672,7 +8718,7 @@ int LnFossilizedBDPriorFossilTip (Tree *t, MrBFlt clockRate, MrBFlt *prob, MrBFl
  |   Gavryushkina, A., D. Welch, T. Stadler, and A. Drummond. 2014. 
  |       Bayesian inference of sampled ancestor trees for epidemiology and fossil calibration. PLoS Comp. Biol.
  |   Zhang C., T. Stadler, S. Klopfstein, T. A. Heath, and F. Ronquist. 2015.
- |       Total-Evidence Dating under the Fossilized Birth-Death Process.
+ |       Total-Evidence Dating under the Fossilized Birth-Death Process. Syst. Biol.
  |
  |
  |                                       0  _____________  t3, rho3
@@ -8717,17 +8763,17 @@ int LnFossilizedBDPriorRandom (Tree *t, MrBFlt clockRate, MrBFlt *prob, MrBFlt *
     sl = mp->sampleFSNum;
     
     /* alloc memory for time of each slice, t_f[sl] = 0 */
-    t_f    = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
+    t_f    = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
     /* lambda, mu, psi */
-    lambda = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
-    mu     = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
-    psi    = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
+    lambda = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
+    mu     = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
+    psi    = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
     /* for sampling prob in each slice, including extant */
-    rho    = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
+    rho    = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
     /* A_i, B_i, ... */
-    c1     = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
-    c2     = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
-    p_t    = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
+    c1     = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
+    c2     = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
+    p_t    = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
     
     if (!lambda || !mu || !psi || !rho || !t_f || !c1 || !c2 || !p_t)
         {
@@ -8826,7 +8872,10 @@ int LnFossilizedBDPriorRandom (Tree *t, MrBFlt clockRate, MrBFlt *prob, MrBFlt *
                 }
             else
                 {
-                (*prob) += log(rho[sl]);
+                if (rho[sl] > 0.0)
+                    {
+                    (*prob) += log(rho[sl]);
+                    }
                 E++;              /* number of extant taxa */
                 }
             }
@@ -8849,7 +8898,7 @@ int LnFossilizedBDPriorRandom (Tree *t, MrBFlt clockRate, MrBFlt *prob, MrBFlt *
         (*prob) += mp->treeAgePr.LnPriorProb(tmrca, mp->treeAgePr.priorParams);
     
     /* conversion to labeled tree from oriented tree */
-    (*prob) += (M + E - 1) * log(2.0) - LnFactorial(E) - LnFactorial(M + K);
+    (*prob) += (M + E - 1) * log(2.0);  // - LnFactorial(E + M + K) (# permutation is constant given data)
     
 #   ifdef DEBUG_FBDPR
     printf ("K=%d M=%d E=%d\n", K, M, E);
@@ -8869,13 +8918,13 @@ int LnFossilizedBDPriorRandom (Tree *t, MrBFlt clockRate, MrBFlt *prob, MrBFlt *
  |   LnFossilizedBDPriorDiversity
  | 
  |   Zhang C., T. Stadler, S. Klopfstein, T. A. Heath, and F. Ronquist. 2015.
- |       Total-Evidence Dating under the Fossilized Birth-Death Process.
+ |       Total-Evidence Dating under the Fossilized Birth-Death Process. Syst. Biol.
  |
  ---------------------------------------------------------------------------------*/
 int LnFossilizedBDPriorDiversity (Tree *t, MrBFlt clockRate, MrBFlt *prob, MrBFlt *sR, MrBFlt *eR, MrBFlt sF, MrBFlt *fR)
 {
     /* Fossils in the past are sampled with piecewise constant rates, 
-       also in several time slices each with a seperate probability. 
+       also in several time slices each with a seperate probability.
        Extant taxa are sampled with prop sF to maximize diversity. */
     
     int         i, j, sl, K, M, E;
@@ -8888,23 +8937,21 @@ int LnFossilizedBDPriorDiversity (Tree *t, MrBFlt clockRate, MrBFlt *prob, MrBFl
     /* time of most recent common ancestor */
     tmrca = t->root->left->nodeDepth / clockRate;
     
-    /* get the number of fossil slice sampling events, s >= 0 */
-    sl = mp->sampleFSNum;
-    /* plus 1 extra slice (x_cut) to shift psi to 0 */
-    sl += 1;
+    /* get the number of fossil slice sampling events, plus 1 extra slice (x_cut) to shift psi to 0 */
+    sl = mp->sampleFSNum + 1;
     
     /* alloc memory for time of each slice */
-    t_f    = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
+    t_f    = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
     /* lambda, mu, psi */
-    lambda = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
-    mu     = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
-    psi    = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
+    lambda = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
+    mu     = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
+    psi    = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
     /* for sampling prob in each slice, including extant */
-    rho    = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
+    rho    = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
     /* A_i, B_i, ... */
-    c1     = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
-    c2     = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
-    p_t    = (MrBFlt *)SafeMalloc((size_t) (sl+1) * sizeof(MrBFlt));
+    c1     = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
+    c2     = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
+    p_t    = (MrBFlt *)SafeMalloc((size_t)(sl+1) * sizeof(MrBFlt));
     
     if (!lambda || !mu || !psi || !rho || !t_f || !c1 || !c2 || !p_t)
         {
@@ -9029,7 +9076,7 @@ int LnFossilizedBDPriorDiversity (Tree *t, MrBFlt clockRate, MrBFlt *prob, MrBFl
                 }
             else
                 {
-                (*prob) += log(rho[sl]);
+                //  (*prob) += log(rho[sl]);  // rho[sl] == 1
                 E++;              /* number of extant taxa */
                 }
             }
@@ -9058,7 +9105,7 @@ int LnFossilizedBDPriorDiversity (Tree *t, MrBFlt clockRate, MrBFlt *prob, MrBFl
         (*prob) += mp->treeAgePr.LnPriorProb(tmrca, mp->treeAgePr.priorParams);
     
     /* conversion to labeled tree from oriented tree */
-    (*prob) += (M + E - 1) * log(2.0) - LnFactorial(E) - LnFactorial(M + K);
+    (*prob) += (M + E - 1) * log(2.0);  // - LnFactorial(E + M + K) (# permutation is constant given data)
     
 #   ifdef DEBUG_FBDPR
     printf ("K=%d M=%d E=%d\n", K, M, E);
@@ -9135,7 +9182,7 @@ int LnCoalescencePriorPr (Tree *t, MrBFlt *prob, MrBFlt theta, MrBFlt growth)
     TreeNode        *p;
 
     /* allocate space for the coalescence times */
-    ct = (MrBFlt *)SafeMalloc((size_t) (t->nIntNodes) * sizeof(MrBFlt));
+    ct = (MrBFlt *)SafeMalloc((size_t)(t->nIntNodes) * sizeof(MrBFlt));
     if (!ct)
         {
         MrBayesPrint ("\n   ERROR: Problem allocating ct\n");
@@ -10204,8 +10251,6 @@ int PreparePrintFiles (void)
     oldAutoOverwrite = autoOverwrite;
 
     /* Allocate space for file pointers */
-    n = chainParams.numRuns;
-
     if (memAllocs[ALLOC_FILEPOINTERS] == YES)
         {
         MrBayesPrint ("%s   File pointers already allocated in PreparePrintFiles\n", spacer);
@@ -10215,26 +10260,26 @@ int PreparePrintFiles (void)
     fpSS = NULL;
     fpParm = NULL;
     fpTree = NULL;  
-    fpParm = (FILE **) SafeCalloc (n, sizeof (FILE *)); 
+    fpParm = (FILE **) SafeCalloc (chainParams.numRuns, sizeof (FILE *));
     if (fpParm == NULL)
         {
         MrBayesPrint ("%s   Could not allocate fpParm in PreparePrintFiles\n", spacer);
         return ERROR;
         }
     memAllocs[ALLOC_FILEPOINTERS] = YES;
-    fpTree = (FILE ***) SafeCalloc (n, sizeof (FILE **));   
+    fpTree = (FILE ***) SafeCalloc (chainParams.numRuns, sizeof (FILE **));
     if (fpTree == NULL)
         {
         MrBayesPrint ("%s   Could not allocate fpTree in PreparePrintFiles\n", spacer);
         return ERROR;
         }
-    fpTree[0] = (FILE **) SafeCalloc (numTrees*n, sizeof (FILE *));
+    fpTree[0] = (FILE **) SafeCalloc (numTrees*chainParams.numRuns, sizeof (FILE *));
     if (fpTree[0] == NULL)
         {
         MrBayesPrint ("%s   Could not allocate fpTree[0] in PreparePrintFiles\n", spacer);
         return ERROR;
         }
-    for (i=1; i<n; i++)
+    for (i=1; i<chainParams.numRuns; i++)
         fpTree[i] = fpTree[0] + i*numTrees;
 
     /* Get root of local file name */
@@ -10314,7 +10359,6 @@ int PreparePrintFiles (void)
             return (ERROR);
             }
         }
-
     
     /* Prepare the .p and .t files */
     for (n=0; n<chainParams.numRuns; n++)
@@ -10367,6 +10411,21 @@ int PreparePrintFiles (void)
     strcat (bkupName, "~");
     remove (bkupName);
     rename (fileName, bkupName);
+    
+#   if defined (PRINT_DUMP)
+    fpDump = (FILE **) SafeCalloc (chainParams.numRuns, sizeof (FILE *));
+
+    for (n=0; n<chainParams.numRuns; n++)
+        {
+        if (chainParams.numRuns == 1)
+            sprintf (fileName, "%s.dump", localFileName);
+        else
+            sprintf (fileName, "%s.run%d.dump", localFileName, n+1);
+        
+        if ((fpDump[n] = OpenNewMBPrintFile (fileName)) == NULL)
+            return (ERROR);
+        }
+#   endif
 
     return (NO_ERROR);
 }
@@ -10387,7 +10446,7 @@ int PrintAncStates_Bin (TreeNode *p, int division, int chain)
     int             tempStrSize = TEMPSTRSIZE;
     ModelInfo       *m;
     
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         {
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
@@ -10474,7 +10533,7 @@ int PrintAncStates_Gen (TreeNode *p, int division, int chain)
     int             tempStrSize = TEMPSTRSIZE;
     ModelInfo       *m;
     
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         {
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
@@ -10661,7 +10720,7 @@ int PrintAncStates_NUC4 (TreeNode *p, int division, int chain)
     int             tempStrSize = TEMPSTRSIZE;
     ModelInfo       *m;
     
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         {
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
@@ -10832,7 +10891,7 @@ int PrintAncStates_Std (TreeNode *p, int division, int chain)
     int             tempStrSize = TEMPSTRSIZE;
     ModelInfo       *m;
     
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         {
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
@@ -11803,7 +11862,7 @@ int PrintMPISlaves (FILE *fp)
         /* reallocate string s on processor 0 if necessary */
         if (nErrors == 0 && proc_id == 0 && len+5 > strlen(s))
             {
-            if ((s = (char *) SafeRealloc ((void *)s, (size_t)((len+5)*sizeof(char)))) == NULL)
+            if ((s = (char *) SafeRealloc ((void *)s, ((size_t)len+5)*sizeof(char))) == NULL)
                 {
                 MrBayesPrint ("%s   Problem reallocating %d chars to string 's' on proc 0 in PrintMPISlaves()\n", spacer, len+5);
                 nErrors++;
@@ -11976,7 +12035,7 @@ int PrintSiteRates_Gen (TreeNode *p, int division, int chain)
     int             tempStrSize = TEMPSTRSIZE;
     ModelInfo       *m;
     
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         {
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
@@ -12119,7 +12178,7 @@ int PrintSiteRates_Std (TreeNode *p, int division, int chain)
     int             tempStrSize = TEMPSTRSIZE;
     ModelInfo       *m;
     
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         {
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
@@ -12191,8 +12250,8 @@ int PrintStates (int curGen, int coldId)
 
     /* allocate the print string */
     printStringSize = tempStrSize = TEMPSTRSIZE;
-    printString = (char *)SafeMalloc((size_t) (printStringSize * sizeof(char)));
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    printString = (char *)SafeMalloc((size_t)printStringSize * sizeof(char));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
 
     if (!printString)
         {
@@ -12216,7 +12275,7 @@ int PrintStates (int curGen, int coldId)
             MrBayesPrint ("%s   posSelProbs not free in PrintStates\n", spacer);
             goto errorExit;
             }
-        posSelProbs = (MrBFlt *)SafeMalloc((size_t) (numCompressedChars * sizeof(MrBFlt)));
+        posSelProbs = (MrBFlt *)SafeMalloc((size_t)numCompressedChars * sizeof(MrBFlt));
         if (!posSelProbs)
             {
             MrBayesPrint ("%s   Problem allocating posSelProbs (%d)\n", spacer, numCompressedChars * sizeof(MrBFlt));
@@ -12228,7 +12287,7 @@ int PrintStates (int curGen, int coldId)
         }
     if (inferPosSel == YES || inferSiteOmegas == YES || inferSiteRates == YES || inferAncStates == YES)
         {
-        printedChar = (int *)SafeMalloc((size_t) (numChar * sizeof(int)));
+        printedChar = (int *)SafeMalloc((size_t)numChar * sizeof(int));
         if (!printedChar)
             {
             MrBayesPrint ("%s   Problem allocating printedChar (%d)\n", spacer, numChar * sizeof(int));
@@ -12250,13 +12309,12 @@ int PrintStates (int curGen, int coldId)
         SafeSprintf (&tempStr, &tempStrSize, "\tLnPr");
         if (AddToPrintString (tempStr) == ERROR) goto errorExit;
 
-        /* print tree lengths or heights for all trees */
         for (i=0; i<numParams; i++)
             {
             p = &params[i];
-
             if (p->paramType == P_BRLENS)
                 {
+                /* print tree lengths or heights for all trees */
                 tree = GetTree (p, coldId, state[coldId]);
                 if (tree->isRooted == YES)
                     {
@@ -12264,6 +12322,7 @@ int PrintStates (int curGen, int coldId)
                         SafeSprintf (&tempStr, &tempStrSize, "\tTH%s\tTL%s", partString, partString);
                     else
                         SafeSprintf (&tempStr, &tempStrSize, "\tTH\tTL");
+                    if (AddToPrintString (tempStr) == ERROR) goto errorExit;
                     }
                 else
                     {
@@ -12271,18 +12330,9 @@ int PrintStates (int curGen, int coldId)
                         SafeSprintf (&tempStr, &tempStrSize, "\tTL%s", partString);
                     else
                         SafeSprintf (&tempStr, &tempStrSize, "\tTL");
+                    if (AddToPrintString (tempStr) == ERROR) goto errorExit;
                     }
-
-                if (AddToPrintString (tempStr) == ERROR) goto errorExit;
-                }
-            }
-
-        /* print # events for cpp model, or relaxed clock model indicator */
-        for (i=0; i<numPrintTreeParams; i++)
-            {
-            p = printTreeParam[i];
-            if (p->paramType == P_BRLENS)
-                {
+                /* print # cpp events, or relaxed clock model indicator */
                 for (j=0; j<p->nSubParams; j++)
                     {
                     if (p->subParams[j]->paramType == P_CPPEVENTS)
@@ -12303,6 +12353,20 @@ int PrintStates (int curGen, int coldId)
                         }
                     }
                 }
+            /* print proportion of ancestral fossils */
+            else if (p->paramType == P_FOSLRATE)
+                {
+                if (FillRelPartsString(p, &partString) == YES)
+                    {
+                    SafeSprintf (&tempStr, &tempStrSize, "\tprop_ancfossil%s", partString);
+                    if (AddToPrintString (tempStr) == ERROR) goto errorExit;
+                    }
+                else
+                    {
+                    SafeSprintf (&tempStr, &tempStrSize, "\tprop_ancfossil");
+                    if (AddToPrintString (tempStr) == ERROR) goto errorExit;
+                    }
+                }
             }
 
         /* print ordinary parameters header */
@@ -12560,15 +12624,14 @@ int PrintStates (int curGen, int coldId)
     SafeSprintf (&tempStr, &tempStrSize, "\t%s", MbPrintNum(curLnPr[coldId]));
     if (AddToPrintString (tempStr) == ERROR) goto errorExit;
 
-    /* print tree lengths or heights for all trees */
     for (i=0; i<numParams; i++)
         {
         p = &params[i];
-
         if (p->paramType == P_BRLENS)
             {
+            /* print tree lengths or heights for all trees */
             tree = GetTree (p, coldId, state[coldId]);
-            if (tree->isClock == NO)
+            if (tree->isRooted == NO)
                 {
                 SafeSprintf (&tempStr, &tempStrSize, "\t%s", MbPrintNum(TreeLength(p, coldId)));
                 if (AddToPrintString (tempStr) == ERROR) goto errorExit;
@@ -12580,15 +12643,7 @@ int PrintStates (int curGen, int coldId)
                 SafeSprintf (&tempStr, &tempStrSize, "\t%s", MbPrintNum(TreeLength(p, coldId)));
                 if (AddToPrintString (tempStr) == ERROR) goto errorExit;
                 }
-            }
-        }
-
-    /* print # cpp events, or relaxed clock model indicator */
-    for (i=0; i<numParams; i++)
-        {
-        p = &params[i];
-        if (p->paramType == P_BRLENS)
-            {   
+            /* print # cpp events, or relaxed clock model indicator */
             for (j=0; j<p->nSubParams; j++)
                 {
                 if (p->subParams[j]->paramType == P_CPPEVENTS)
@@ -12603,6 +12658,12 @@ int PrintStates (int curGen, int coldId)
                     }
                 }
             }
+        else if (p->paramType == P_FOSLRATE)
+            {
+            /* print proportion of ancestral fossils */
+            SafeSprintf (&tempStr, &tempStrSize, "\t%s", MbPrintNum(PropAncFossil(p, coldId)));
+            if (AddToPrintString (tempStr) == ERROR) goto errorExit;
+            }
         }
 
     /* print ordinary parameters */
@@ -12810,7 +12871,8 @@ int PrintStates (int curGen, int coldId)
                     }
                 SafeSprintf (&tempStr, &tempStrSize, "\t%s", MbPrintNum(posSelProbs[compressedCharPosition]));
                 if (AddToPrintString (tempStr) == ERROR) goto errorExit;
-                /* printf ("%4d -> (%3d,%3d,%3d) %1.25le\n", i, origAlignmentChars[0]+1, origAlignmentChars[1]+1, origAlignmentChars[2]+1, posSelProbs[compressedCharPosition]); */
+                /* printf ("%4d -> (%3d,%3d,%3d) %1.25le\n", i, origAlignmentChars[0]+1, origAlignmentChars[1]+1,
+                                                                origAlignmentChars[2]+1, posSelProbs[compressedCharPosition]); */
                 }
             }
         }
@@ -12851,7 +12913,8 @@ int PrintStates (int curGen, int coldId)
                     }
                 SafeSprintf (&tempStr, &tempStrSize, "\t%s", MbPrintNum(posSelProbs[compressedCharPosition]));
                 if (AddToPrintString (tempStr) == ERROR) goto errorExit;
-                /* printf ("%4d -> (%3d,%3d,%3d) %1.25le\n", i, origAlignmentChars[0]+1, origAlignmentChars[1]+1, origAlignmentChars[2]+1, posSelProbs[compressedCharPosition]); */
+                /* printf ("%4d -> (%3d,%3d,%3d) %1.25le\n", i, origAlignmentChars[0]+1, origAlignmentChars[1]+1,
+                                                                origAlignmentChars[2]+1, posSelProbs[compressedCharPosition]); */
                 }
             }
         }
@@ -13087,7 +13150,7 @@ int PrintStatesToFiles (int curGen)
                         MrBayesPrint ("%s   Problem receiving printStringSize from proc_id = %d\n", spacer, procWithChain);
                         nErrors++;
                         }
-                    printString = (char *)SafeMalloc((size_t) (printStringSize * sizeof(char)));
+                    printString = (char *)SafeMalloc((size_t)printStringSize * sizeof(char));
                     if (!printString)
                         {
                         MrBayesPrint ("%s   Problem allocating printString (%d)\n", spacer, printStringSize * sizeof(char));
@@ -13206,7 +13269,7 @@ int PrintStatesToFiles (int curGen)
                             MrBayesPrint ("%s   Problem receiving printStringSize from proc_id = %d\n", spacer, procWithChain);
                             nErrors++;
                             }
-                        printString = (char *)SafeMalloc((size_t) (printStringSize * sizeof(char)));
+                        printString = (char *)SafeMalloc((size_t)printStringSize * sizeof(char));
                         if (!printString)
                             {
                             MrBayesPrint ("%s   Problem allocating printString (%d)\n", spacer, printStringSize * sizeof(char));
@@ -13333,7 +13396,7 @@ int PrintSwapInfo (void)
 #   endif
 
     tempStrSize = TEMPSTRSIZE;
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         {
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
@@ -13591,7 +13654,7 @@ int PrintTopConvInfo (void)
 #   endif
 
     tempStrSize = TEMPSTRSIZE;
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         {
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
@@ -13850,7 +13913,7 @@ int PrintTree (int curGen, Param *treeParam, int chain, int showBrlens, MrBFlt c
 
     /* allocate the print string */
     printStringSize = 200;
-    printString = (char *)SafeMalloc((size_t) (printStringSize * sizeof(char)));
+    printString = (char *)SafeMalloc((size_t)printStringSize * sizeof(char));
     if (!printString)
         {
         MrBayesPrint ("%s   Problem allocating printString (%d)\n", spacer, printStringSize * sizeof(char));
@@ -13859,7 +13922,7 @@ int PrintTree (int curGen, Param *treeParam, int chain, int showBrlens, MrBFlt c
     *printString = '\0';
 
     tempStrSize = TEMPSTRSIZE;
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         {
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
@@ -15011,7 +15074,7 @@ int RemoveTreeSamples (int from, int to)
         return (NO_ERROR);
 #   endif
 
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         {
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
@@ -15167,26 +15230,27 @@ int RemoveTreeSamples (int from, int to)
 
 int ReopenMBPrintFiles (void)
 {
-    int     i, k, n;
+    int     i, n;
     char    fileName[120], localFileName[100];
     
+    /* Take care of the mpi procs that do not have a file */
+#   if defined (MPI_ENABLED)
+    if (proc_id != 0)
+        return (NO_ERROR);
+#   endif
+
     /* Get root of local file name */
     strcpy (localFileName, chainParams.chainFileName);
 
     /* Reopen the .p and .t files */
     for (n=0; n<chainParams.numRuns; n++)
         {
-        k = n;
-
         if (chainParams.numRuns == 1)
             sprintf (fileName, "%s.p", localFileName);
         else
             sprintf (fileName, "%s.run%d.p", localFileName, n+1);
 
-#       if defined (MPI_ENABLED)
-        if (proc_id == 0)
-#       endif
-        if ((fpParm[k] = OpenTextFileA (fileName)) == NULL)
+        if ((fpParm[n] = OpenTextFileA (fileName)) == NULL)
             return (ERROR);
 
         for (i=0; i<numTrees; i++)
@@ -15200,29 +15264,32 @@ int ReopenMBPrintFiles (void)
             else
                 sprintf (fileName, "%s.tree%d.run%d.t", localFileName, i+1, n+1);
 
-#           if defined (MPI_ENABLED)
-            if (proc_id == 0)
-#           endif
-            if ((fpTree[k][i] = OpenTextFileA (fileName)) == NULL)
+            if ((fpTree[n][i] = OpenTextFileA (fileName)) == NULL)
                 return (ERROR);
             }
-
         }
 
-    /* Take care of the mpi procs that do not have a mcmc file */
-#   if defined (MPI_ENABLED)
-    if (proc_id != 0)
-        return (NO_ERROR);
-#   endif
-
     /* Reopen the .mcmc file */
     if (chainParams.mcmcDiagn == YES)
         {
-        sprintf (fileName, "%s.mcmc", chainParams.chainFileName);
+        sprintf (fileName, "%s.mcmc", localFileName);
 
         if ((fpMcmc = OpenTextFileA (fileName)) == NULL)
             return (ERROR);
         }
+    
+#   if defined (PRINT_DUMP)
+    for (n=0; n<chainParams.numRuns; n++)
+        {
+        if (chainParams.numRuns == 1)
+            sprintf (fileName, "%s.dump", localFileName);
+        else
+            sprintf (fileName, "%s.run%d.dump", localFileName, n+1);
+
+        if ((fpDump[n] = OpenTextFileA (fileName)) == NULL)
+            return (ERROR);
+        }
+#   endif
 
     return (NO_ERROR);
 }
@@ -15666,7 +15733,7 @@ void ResetSiteScalers (ModelInfo *m, int chain)
 ------------------------------------------------------------------------*/
 int ReusePreviousResults (int *numSamples, int steps)
 {
-    int         i, k, n;
+    int         i, n;
     char        localFileName[100], fileName[220], bkupName[220];
 
     (*numSamples) = 0;
@@ -15677,8 +15744,6 @@ int ReusePreviousResults (int *numSamples, int steps)
 #   endif
 
     /* Allocate space for file pointers */
-    n = chainParams.numRuns;
-
     if (memAllocs[ALLOC_FILEPOINTERS] == YES)
         {
         MrBayesPrint ("%s   File pointers already allocated in ReusePreviousResults\n", spacer);
@@ -15688,26 +15753,26 @@ int ReusePreviousResults (int *numSamples, int steps)
     fpSS = NULL;
     fpParm = NULL;
     fpTree = NULL;  
-    fpParm = (FILE **) SafeCalloc (n, sizeof (FILE *)); 
+    fpParm = (FILE **) SafeCalloc (chainParams.numRuns, sizeof (FILE *));
     if (fpParm == NULL)
         {
         MrBayesPrint ("%s   Could not allocate fpParm in ReusePreviousResults\n", spacer);
         return ERROR;
         }
     memAllocs[ALLOC_FILEPOINTERS] = YES;
-    fpTree = (FILE ***) SafeCalloc (n, sizeof (FILE **));   
+    fpTree = (FILE ***) SafeCalloc (chainParams.numRuns, sizeof (FILE **));
     if (fpTree == NULL)
         {
         MrBayesPrint ("%s   Could not allocate fpTree in ReusePreviousResults\n", spacer);
         return ERROR;
         }
-    fpTree[0] = (FILE **) SafeCalloc (numTrees*n, sizeof (FILE *));
+    fpTree[0] = (FILE **) SafeCalloc (numTrees*chainParams.numRuns, sizeof (FILE *));
     if (fpTree[0] == NULL)
         {
         MrBayesPrint ("%s   Could not allocate fpTree[0] in ReusePreviousResults\n", spacer);
         return ERROR;
         }
-    for (i=1; i<n; i++)
+    for (i=1; i<chainParams.numRuns; i++)
         fpTree[i] = fpTree[0] + i*numTrees;
 
     /* Get root of local file name */
@@ -15716,8 +15781,6 @@ int ReusePreviousResults (int *numSamples, int steps)
     /* Store old and prepare new .p and .t files */
     for (n=0; n<chainParams.numRuns; n++)
         {
-        k = n;
-
         if (chainParams.numRuns == 1)
             sprintf (fileName, "%s%s.p", workingDir, localFileName);
         else
@@ -15731,9 +15794,9 @@ int ReusePreviousResults (int *numSamples, int steps)
             return ERROR;
             }
 
-        if ((fpParm[k] = OpenNewMBPrintFile (fileName+strlen(workingDir))) == NULL)
+        if ((fpParm[n] = OpenNewMBPrintFile (fileName+strlen(workingDir))) == NULL)
             return (ERROR);
-        else if (CopyResults(fpParm[k],bkupName+strlen(workingDir),numPreviousGen) == ERROR)
+        else if (CopyResults(fpParm[n],bkupName+strlen(workingDir),numPreviousGen) == ERROR)
             return (ERROR);
 
         for (i=0; i<numTrees; i++)
@@ -15754,9 +15817,9 @@ int ReusePreviousResults (int *numSamples, int steps)
                 MrBayesPrint ("%s   Could not rename file %s\n", spacer, fileName);
                 return ERROR;
                 }
-            if ((fpTree[k][i] = OpenNewMBPrintFile (fileName+strlen(workingDir))) == NULL)
+            if ((fpTree[n][i] = OpenNewMBPrintFile (fileName+strlen(workingDir))) == NULL)
                 return (ERROR);
-            else if (CopyTreeResults(fpTree[k][i],bkupName+strlen(workingDir),numPreviousGen,numSamples) == ERROR)
+            else if (CopyTreeResults(fpTree[n][i],bkupName+strlen(workingDir),numPreviousGen,numSamples) == ERROR)
                 return (ERROR);
             }
         }
@@ -15796,6 +15859,21 @@ int ReusePreviousResults (int *numSamples, int steps)
         else if (CopyResults(fpMcmc,bkupName+strlen(workingDir),numPreviousGen)==ERROR)
             return (ERROR);
         }
+    
+#   if defined (PRINT_DUMP)
+    fpDump = (FILE **) SafeCalloc (chainParams.numRuns, sizeof (FILE *));
+    
+    for (n=0; n<chainParams.numRuns; n++)
+        {
+        if (chainParams.numRuns == 1)
+            sprintf (fileName, "%s.dump", localFileName);
+        else
+            sprintf (fileName, "%s.run%d.dump", localFileName, n+1);
+        
+        if ((fpDump[n] = OpenTextFileA (fileName)) == NULL)
+            return (ERROR);
+    }
+#   endif
 
     return (NO_ERROR);
 }
@@ -15843,12 +15921,6 @@ int RunChain (RandLong *seed)
 #   if defined (DEBUG_RUNCHAIN)
     ModelInfo   *m;
 #   endif
-
-#   if defined (PRINT_DUMP)
-    char tempName[150];
-    sprintf (tempName, "%s.dump.txt", chainParams.chainFileName);
-    dumpFile = OpenNewMBPrintFile (tempName);
-#   endif
     
     /* set nErrors to 0 */
     nErrors = 0;
@@ -15869,29 +15941,18 @@ int RunChain (RandLong *seed)
             }
         }
 
-    /* Adjust default comparetree file name; we know now how many trees we have */
-    if (numTrees > 1 && chainParams.numRuns > 1)
-        sprintf (comptreeParams.comptFileName1, "%s.tree1.run1.t", chainParams.chainFileName);
-    else if (numTrees > 1 && chainParams.numRuns == 1)
-        sprintf (comptreeParams.comptFileName1, "%s.tree1.t", chainParams.chainFileName);
-    else if (numTrees == 1 && chainParams.numRuns > 1)
-        sprintf (comptreeParams.comptFileName1, "%s.run1.t", chainParams.chainFileName);
-    else if (numTrees == 1 && chainParams.numRuns == 1)
-        sprintf (comptreeParams.comptFileName1, "%s.t", chainParams.chainFileName);
-    strcpy (comptreeParams.comptFileName2, comptreeParams.comptFileName1);
-
     /* allocate some memory for the chains */
     if (memAllocs[ALLOC_CURLNL] == YES)
         {
         MrBayesPrint ("%s   curLnL is already allocated\n", spacer);
         nErrors++;
         }
-    else if ((curLnL = (MrBFlt *)SafeMalloc((size_t) (numLocalChains * sizeof(MrBFlt)))) == NULL)
+    else if ((curLnL = (MrBFlt *)SafeMalloc((size_t)numLocalChains * sizeof(MrBFlt))) == NULL)
         {
         MrBayesPrint ("%s   Problem allocating curLnL (%d)\n", spacer, numLocalChains * sizeof(MrBFlt));
         nErrors++;
         }
-    else if ((maxLnL0 = (MrBFlt *) SafeCalloc (chainParams.numRuns * chainParams.numChains, sizeof(MrBFlt))) == NULL)
+    else if ((maxLnL0 = (MrBFlt *) SafeCalloc ((size_t)(chainParams.numRuns) * (size_t)(chainParams.numChains), sizeof(MrBFlt))) == NULL)
         {
         MrBayesPrint ("%s   Problem allocating maxLnL0\n", spacer, numLocalChains * sizeof(MrBFlt));
         free (curLnL);
@@ -15916,7 +15977,7 @@ int RunChain (RandLong *seed)
         MrBayesPrint ("%s   curLnPr is already allocated\n", spacer);
         nErrors++;
         }
-    else if ((curLnPr = (MrBFlt *)SafeMalloc((size_t) (numLocalChains * sizeof(MrBFlt)))) == NULL)
+    else if ((curLnPr = (MrBFlt *)SafeMalloc((size_t)numLocalChains * sizeof(MrBFlt))) == NULL)
         {
         MrBayesPrint ("%s   Problem allocating curLnPr (%d)\n", spacer, numLocalChains * sizeof(MrBFlt));
         nErrors++;
@@ -15940,7 +16001,7 @@ int RunChain (RandLong *seed)
         MrBayesPrint ("%s   chainId is already allocated\n", spacer);
         nErrors++;
         }
-    else if ((chainId = (int *)SafeMalloc((size_t) (numLocalChains * sizeof(int)))) == NULL)
+    else if ((chainId = (int *)SafeMalloc((size_t)numLocalChains * sizeof(int))) == NULL)
         {
         MrBayesPrint ("%s   Problem allocating chainId (%d)\n", spacer, numLocalChains * sizeof(int));
         nErrors++;
@@ -16091,16 +16152,15 @@ int RunChain (RandLong *seed)
             for (i=0; i<numTopologies; i++)
                 chainParams.stat[i].pair = NULL;
             }
-        if (chainParams.relativeBurnin == YES)
+            
+        if ((chainParams.dtree = AllocateTree (numLocalTaxa)) == NULL)
             {
-            if ((chainParams.dtree = AllocateTree (numLocalTaxa)) == NULL)
-                {
-                MrBayesPrint ("%s   Could not allocate chainParams.dtree in RunChain\n", spacer);
-                return ERROR;
-                }
-            else
-                memAllocs[ALLOC_DIAGNTREE] = YES;
+            MrBayesPrint ("%s   Could not allocate chainParams.dtree in RunChain\n", spacer);
+            return ERROR;
             }
+        else
+            memAllocs[ALLOC_DIAGNTREE] = YES;
+        
         if (chainParams.allComps == YES)
             {
             for (i=0; i<numTopologies; i++)
@@ -16325,7 +16385,7 @@ int RunChain (RandLong *seed)
                     }
                 else
                     {
-                    if (setFilePositions(removeTo) == ERROR) nErrors++;
+                    if (SetFilePositions(removeTo) == ERROR) nErrors++;
                     if (AddTreeSamples(removeTo+1,i,chainParams.saveTrees) == ERROR) nErrors++;
                     }
                 }
@@ -16663,11 +16723,11 @@ int RunChain (RandLong *seed)
                 abortMove = YES;
                 }
 
-            /* calculate likelihood ratio -- abortMove is set to YES if the calculation fails because the likelihood is too small */
+            /* abortMove is set to YES if the calculation fails because the likelihood is too small */
             if (abortMove == NO)
                 lnLike = LogLike(chn);
 
-            /* determine whether we want to accept the move */
+            /* calculate acceptance probability */
             if (abortMove == NO)
                 {
                 lnLikelihoodRatio = lnLike - curLnL[chn];
@@ -16822,7 +16882,9 @@ int RunChain (RandLong *seed)
             {
             PrintToScreen(n, numPreviousGen, time(0), startingT);
 #   if defined (TIMING_ANALIZ)
-            MrBayesPrint ("%s   Time elapsed:%f CondlikeDownTime:%f CondLikeRoot:%f Likelihood:%f ScalersTime:%f ScalersRemove:%f\n", spacer, CPUTime,CPUCondLikeDown/(MrBFlt) CLOCKS_PER_SEC,CPUCondLikeRoot/(MrBFlt) CLOCKS_PER_SEC,CPULilklihood/(MrBFlt) CLOCKS_PER_SEC, CPUScalers/(MrBFlt) CLOCKS_PER_SEC, CPUScalersRemove/(MrBFlt) CLOCKS_PER_SEC);
+            MrBayesPrint ("%s   Time elapsed:%f CondlikeDownTime:%f CondLikeRoot:%f Likelihood:%f ScalersTime:%f ScalersRemove:%f\n", spacer,
+                          CPUTime, CPUCondLikeDown/(MrBFlt)CLOCKS_PER_SEC, CPUCondLikeRoot/(MrBFlt)CLOCKS_PER_SEC, CPULilklihood/(MrBFlt)CLOCKS_PER_SEC,
+                          CPUScalers/(MrBFlt)CLOCKS_PER_SEC, CPUScalersRemove/(MrBFlt)CLOCKS_PER_SEC);
 #   endif
             }
 
@@ -16858,12 +16920,13 @@ int RunChain (RandLong *seed)
             }
 
         /* print mcmc diagnostics. Blocking for MPI */
-        if (chainParams.mcmcDiagn == YES && (n % chainParams.diagnFreq == 0 || n == chainParams.numGen || (chainParams.isSS == YES && (n-lastStepEndSS) % numGenInStepSS == 0)))
+        if (chainParams.mcmcDiagn == YES && (n % chainParams.diagnFreq == 0
+                                             || n == chainParams.numGen
+                                             || (chainParams.isSS == YES && (n-lastStepEndSS) % numGenInStepSS == 0)))
             {
-            if (chainParams.numRuns > 1
-                && ((n > 0 && chainParams.relativeBurnin == YES &&
-                     (chainParams.isSS == NO || (n > chainParams.burninSS * chainParams.sampleFreq && (n-lastStepEndSS) > numGenInStepBurninSS)))
-                    || (n >= chainParams.chainBurnIn * chainParams.sampleFreq && chainParams.relativeBurnin == NO)))
+            if (chainParams.numRuns > 1 &&
+                ((n > 0 && chainParams.relativeBurnin == YES && (chainParams.isSS == NO || (n > chainParams.burninSS * chainParams.sampleFreq && (n-lastStepEndSS) > numGenInStepBurninSS)))
+                 || (n >= chainParams.chainBurnIn * chainParams.sampleFreq && chainParams.relativeBurnin == NO)))
                 {
                 /* we need some space for coming output */
                 MrBayesPrint ("\n");
@@ -16979,7 +17042,7 @@ int RunChain (RandLong *seed)
                             }
                         if (chainParams.isSS == YES)
                             splitfreqSS[i*chainParams.numStepsSS+chainParams.numStepsSS-stepIndexSS-1] = f;
-                        if (chainParams.stat[i].numPartitions == 0 && f > chainParams.stopVal)
+                        if (chainParams.stat[i].numPartitions == 0 || f > chainParams.stopVal)
                             stopChain = NO;
                         }
                     if (n < chainParams.numGen - chainParams.printFreq && (chainParams.stopRule == NO || stopChain == NO))
@@ -17523,10 +17586,6 @@ int RunChain (RandLong *seed)
             MrBayesPrint ("%s   tuning MCMC proposal or heating parameters.                               \n", spacer);
             }
         }
-
-#   if defined (PRINT_DUMP)
-    SafeFclose (&dumpFile);
-#   endif
     
     return (NO_ERROR);
 }
@@ -17648,8 +17707,8 @@ void SetChainIds (void)
 }
 
 
-/* setFilePositions sets chainParams.tFilePos[] to point immidiatly after sampled tree in position "samplePos" for all .t files.  */
-int setFilePositions (int samplePos)
+/* It sets chainParams.tFilePos[] to point immidiatly after sampled tree in position "samplePos" for all .t files. */
+int SetFilePositions (int samplePos)
 {
     int i, j, k, longestLine;
     BitsLong    lastBlock;
@@ -17663,7 +17722,7 @@ int setFilePositions (int samplePos)
         return (NO_ERROR);
 #   endif
 
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         {
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
@@ -17747,18 +17806,19 @@ void SetFileNames (void)
     strcpy (sumpParams.sumpFileName, chainParams.chainFileName);
     strcpy (sumpParams.sumpOutfile, chainParams.chainFileName);
     if (chainParams.numRuns == 1)
-        sprintf (comptreeParams.comptFileName1, "%s.run1.t", chainParams.chainFileName);
-    else /* if (chainParams.numRuns > 1) */
+        {
         sprintf (comptreeParams.comptFileName1, "%s.t", chainParams.chainFileName);
-    strcpy (comptreeParams.comptFileName2, comptreeParams.comptFileName1);
-    if (chainParams.numRuns == 1)
-        sprintf (plotParams.plotFileName, "%s.run1.p", chainParams.chainFileName);
-    else /* if (chainParams.numRuns > 1) */
+        sprintf (comptreeParams.comptFileName2, "%s.t", chainParams.chainFileName);
         sprintf (plotParams.plotFileName, "%s.p", chainParams.chainFileName);
-    if (chainParams.numRuns > 1)
-        MrBayesPrint ("%s   Setting chain output file names to \"%s.run<i>.<p/t>\"\n", spacer, chainParams.chainFileName);
-    else
         MrBayesPrint ("%s   Setting chain output file names to \"%s.<p/t>\"\n", spacer, chainParams.chainFileName);
+        }
+    else /* if (chainParams.numRuns > 1) */
+        {
+        sprintf (comptreeParams.comptFileName1, "%s.run1.t", chainParams.chainFileName);
+        sprintf (comptreeParams.comptFileName2, "%s.run2.t", chainParams.chainFileName);
+        sprintf (plotParams.plotFileName, "%s.run1.p", chainParams.chainFileName);
+        MrBayesPrint ("%s   Setting chain output file names to \"%s.run<i>.<p/t>\"\n", spacer, chainParams.chainFileName);
+        }
 }
 
 
@@ -18974,3 +19034,36 @@ MrBFlt TreeLength (Param *param, int chain)
     return (tl);
 }
 
+
+/* proportion of ancestral fossils in a FBD tree */
+MrBFlt PropAncFossil (Param *param, int chain)
+{
+    int             i, m, k;
+    Tree            *t;
+    TreeNode        *p;
+ 
+    t = GetTree (param, chain, state[chain]);
+    
+    if (t->isRooted == NO)
+        return 0.0;
+    
+    /* count # of tip and ancestral fossils */
+    m = k = 0;
+    for (i = 0; i < t->nNodes -2; i++)
+        {
+        p = t->allDownPass[i];
+        if (p->left == NULL && p->right == NULL && p->nodeDepth > 0.0)
+            {
+            if (p->length > 0.0)
+                m++;
+            else
+                k++;
+            }
+        }
+    
+    if (k == 0)
+        return 0.0;
+    else
+        return (MrBFlt)k / (m+k);
+}
+
diff --git a/src/mcmc.h b/src/mcmc.h
index cd20ceb..f231cff 100644
--- a/src/mcmc.h
+++ b/src/mcmc.h
@@ -28,7 +28,7 @@ MrBFlt  LogOmegaPrior (MrBFlt w1, MrBFlt w2, MrBFlt w3);
 FILE    *OpenNewMBPrintFile (char *fileName);
 int     ResetScalersPartition (int *isScalerNode, Tree* t, unsigned rescaleFreq);
 int     SafeSprintf (char **target, int *targetLen, char *fmt, ...);
-int     setFilePositions (int samplePos);
+int     SetFilePositions (int samplePos);
 MrBFlt  TreeLength (Param *param, int chain);
 
 #endif  /* __MCMC_H__ */
diff --git a/src/model.c b/src/model.c
index fbf7c32..1053f23 100644
--- a/src/model.c
+++ b/src/model.c
@@ -46,7 +46,7 @@
 #include "SIOUX.h"
 #endif
 
-const char* const svnRevisionModelC = "$Rev: 1032 $";   /* Revision keyword which is expended/updated by svn on each commit/update */
+const char* const svnRevisionModelC = "$Rev: 1067 $";   /* Revision keyword which is expended/updated by svn on each commit/update */
 
 #undef  DEBUG_ADDDUMMYCHARS
 #undef  DEBUG_CONSTRAINTS
@@ -201,20 +201,22 @@ int AddDummyChars (void)
 
         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->coding & NOABSENCESITES)
+                m->numDummyChars++;
+            if (mp->coding & NOPRESENCESITES)
+                m->numDummyChars++;
+            if (mp->coding & NOSINGLETONABSENCE)
+                m->numDummyChars += numLocalTaxa;
+            if (mp->coding & NOSINGLETONPRESENCE)
+                m->numDummyChars += 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;
+            if (mp->coding & VARIABLE)
+                m->numDummyChars += 2;
+            if (mp->coding & NOSINGLETONS)
+                m->numDummyChars += 2*numLocalTaxa;
             numStdChars += (m->numChars + m->numDummyChars);
             }
 
@@ -267,22 +269,10 @@ int AddDummyChars (void)
             {
             // 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 (k=0; k<2; k++)
+                if (((mp->coding & NOSINGLETONPRESENCE) && k == 0) || ((mp->coding & NOSINGLETONABSENCE) && k == 1))
                     {
                     for (i=0; i< numLocalTaxa; i++)
                         {
@@ -301,7 +291,7 @@ int AddDummyChars (void)
                     }
                 }
 
-            if (!strcmp(mp->coding, "Noabsencesites"))
+            if (mp->coding & NOABSENCESITES)
                 {
                 for (i=0; i<numLocalTaxa; i++)
                     tempMatrix[pos(i,newColumn,newRowSize)] = 1;
@@ -311,7 +301,7 @@ int AddDummyChars (void)
                 newColumn++;
                 }
 
-            if (!strcmp(mp->coding, "Nopresencesites"))
+            if (mp->coding & NOPRESENCESITES)
                 {
                 for (i=0; i<numLocalTaxa; i++)
                     tempMatrix[pos(i,newColumn,newRowSize)] = 2;
@@ -338,14 +328,36 @@ int AddDummyChars (void)
                 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 (mp->coding & VARIABLE)
+                    {
+                    if((mp->coding & VARIABLE) == VARIABLE && cinfo.variable == NO)
+                        {
+                        isCompat = NO;
+                        }
+                    else if((mp->coding & NOABSENCESITES) && cinfo.constant[0] == YES)
+                        {
+                        isCompat = NO;
+                        }
+                    else if((mp->coding & NOPRESENCESITES) && cinfo.constant[1] == YES)
+                        {
+                        isCompat = NO;
+                        }
+                    }
+                if (mp->coding & NOSINGLETONS)
+                    {
+                    if((mp->coding & NOSINGLETONS) == NOSINGLETONS && cinfo.informative == NO && cinfo.variable == YES)
+                        {
+                        isCompat = NO;
+                        }
+                    else if((mp->coding & NOSINGLETONABSENCE) && cinfo.singleton[0] == YES && cinfo.informative == NO)
+                        {
+                        isCompat = NO;
+                        }
+                    else if((mp->coding & NOSINGLETONPRESENCE) && cinfo.singleton[1] == YES && cinfo.informative == NO)
+                        {
+                        isCompat = NO;
+                        }
+                    }
                 }
 
             if (isCompat == NO)
@@ -1201,7 +1213,7 @@ int ChangeNumChains (int from, int to)
     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*)));
+    mcmcTree = (Tree **) SafeRealloc ((void *)(mcmcTree), 2 * (size_t)numGlobalChains * (size_t)numTrees * sizeof(Tree*));
     for (i=0; i<2*nRuns*to*numTrees; i++)
         mcmcTree[i] = NULL;
 
@@ -1285,7 +1297,7 @@ int ChangeNumChains (int from, int to)
         {
         assert (memAllocs[ALLOC_STDSTATEFREQS] == YES);
         stdStateFreqsOld=stdStateFreqs;
-        stdStateFreqs = (MrBFlt *) SafeMalloc ((size_t)stdStateFreqsRowSize * 2 * numGlobalChains * sizeof (MrBFlt));
+        stdStateFreqs = (MrBFlt *) SafeMalloc (2 * (size_t)stdStateFreqsRowSize * (size_t)numGlobalChains * sizeof (MrBFlt));
         if (!stdStateFreqs)
             {
             MrBayesPrint ("%s   Problem reallocating stdStateFreqs\n", spacer);
@@ -1559,15 +1571,15 @@ int ChangeNumRuns (int from, int to)
     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)));
+        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 * (size_t)(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]->relProposalProb = (MrBFlt *) SafeRealloc ((void *) moves[i]->relProposalProb, 4 * (size_t)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]->nAccepted = (int *) SafeRealloc ((void *) moves[i]->nAccepted, 5* (size_t)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;
@@ -1664,7 +1676,7 @@ void CheckCharCodingType (Matrix *m, CharInfo *ci)
     /* set constant to no and state counters to 0 for all states */
     for (i=0; i<10; i++)
         {
-        ci->constant[i] = NO;
+        ci->constant[i] = ci->singleton[i] = NO;
         n1[i] = n2[i] = 0;
         }
 
@@ -1700,10 +1712,14 @@ void CheckCharCodingType (Matrix *m, CharInfo *ci)
             ci->constant[i] = YES;
             ci->variable = ci->informative = NO;
             }
+            else if (n1[i] == 1)
+            {
+            ci->singleton[i] = YES;
+            }
         }
 
-    /* return if variable is no or if a restriction site char */
-    if (ci->variable == NO || ci->dType == RESTRICTION)
+    /* return if variable is no */
+    if (ci->variable == NO)
         return;
 
     /* the character is either (variable and uninformative) or informative */
@@ -1939,7 +1955,7 @@ int CheckExpandedModels (void)
     int             tempStrSize=100;
     ModelParams     *mp;
     
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         {
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
@@ -2240,6 +2256,76 @@ int CheckExpandedModels (void)
     return (NO_ERROR);
 }
 
+void CodingToString(int coding, char* string)
+{
+    if(coding == ALL)
+        strcpy(string, "All");
+    else if(coding == INFORMATIVE)
+        strcpy(string, "Informative");
+    else if((coding & VARIABLE) == VARIABLE)
+        {
+        if (coding == VARIABLE)
+            {
+            strcpy(string, "Variable");
+            }
+        else if (coding & NOSINGLETONABSENCE)
+            {
+            strcpy(string, "Variable|Nosingletonabsence");
+            }
+        else if (coding & NOSINGLETONPRESENCE)
+            {
+            strcpy(string, "Variable|Nosingletonpresence");
+            }
+        }
+    else if((coding & NOSINGLETONS) == NOSINGLETONS)
+        {
+        if (coding == NOSINGLETONS)
+            {
+            strcpy(string, "Nosingletons");
+            }
+        else if (coding & NOABSENCESITES)
+            {
+            strcpy(string, "Noabsencesites|Nosingletons");
+            }
+        else if (coding & NOPRESENCESITES)
+            {
+            strcpy(string, "Nopresencesites|Nosingletons");
+            }
+        }
+    else if(coding == NOABSENCESITES)
+        {
+        strcpy(string, "Noabsencesites");
+        }
+    else if(coding == NOPRESENCESITES)
+        {
+        strcpy(string, "Nopresencesites");
+        }
+    else if(coding == NOSINGLETONABSENCE)
+        {
+        strcpy(string, "Nosingletonabsence");
+        }
+    else if(coding == NOSINGLETONPRESENCE)
+        {
+        strcpy(string, "Nosingletonpresence");
+        }
+    else if(coding == (NOABSENCESITES | NOSINGLETONABSENCE))
+        {
+        strcpy(string, "Noabsencesites|Nosingletonabsence");
+        }
+    else if(coding == (NOABSENCESITES | NOSINGLETONPRESENCE))
+        {
+        strcpy(string, "Noabsencesites|Nosingletonpresence");
+        }
+    else if(coding == (NOPRESENCESITES | NOSINGLETONABSENCE))
+        {
+        strcpy(string, "Nopresencesites|Nosingletonabsence");
+        }
+    else if(coding == (NOPRESENCESITES | NOSINGLETONPRESENCE))
+        {
+        strcpy(string, "Nopresencesites|Nosingletonpresence");
+        }
+}
+
 
 /*-----------------------------------------------------------
 |
@@ -2273,7 +2359,7 @@ int CompressData (void)
         compColPos = NULL;
         memAllocs[ALLOC_COMPCOLPOS] = NO;
         }
-    compColPos = (int *)SafeMalloc((size_t) (numChar * sizeof(int)));
+    compColPos = (int *)SafeMalloc((size_t)numChar * sizeof(int));
     if (!compColPos)
         {
         MrBayesPrint ("%s   Problem allocating compColPos (%d)\n", spacer, numChar * sizeof(int));
@@ -2289,7 +2375,7 @@ int CompressData (void)
         compCharPos = NULL;
         memAllocs[ALLOC_COMPCHARPOS] = NO;
         }
-    compCharPos = (int *)SafeMalloc((size_t) (numChar * sizeof(int)));
+    compCharPos = (int *)SafeMalloc((size_t)numChar * sizeof(int));
     if (!compCharPos)
         {
         MrBayesPrint ("%s   Problem allocating compCharPos (%d)\n", spacer, numChar * sizeof(int));
@@ -2518,7 +2604,7 @@ int CompressData (void)
         origChar = NULL;
         memAllocs[ALLOC_ORIGCHAR] = NO;
         }
-    origChar = (int *)SafeMalloc((size_t) (compMatrixRowSize * sizeof(int)));
+    origChar = (int *)SafeMalloc((size_t)compMatrixRowSize * sizeof(int));
     if (!origChar)
         {
         MrBayesPrint ("%s   Problem allocating origChar (%d)\n", spacer, numCompressedChars * sizeof(int));
@@ -2864,7 +2950,7 @@ int DoLset (void)
     int         i, nApplied, lastActive=0;
     
     nApplied = NumActiveParts ();
-    for (i=numCurrentDivisions; i>=0; i--)
+    for (i=numCurrentDivisions-1; i>=0; i--)
         {
         if (activeParts[i] == YES)
             {
@@ -3559,6 +3645,13 @@ int DoLsetParm (char *parmName, char *tkn)
         else if (!strcmp(parmName, "Coding"))
             {
             if (expecting == Expecting(EQUALSIGN))
+                {
+                for (i=0; i<numCurrentDivisions; i++)
+                    modelParams[i].coding = ALL;
+                
+                expecting = Expecting(ALPHA);
+                }
+            else if (expecting == Expecting(VERTICALBAR))
                 expecting = Expecting(ALPHA);
             else if (expecting == Expecting(ALPHA))
                 {
@@ -3569,11 +3662,50 @@ int DoLsetParm (char *parmName, char *tkn)
                         {
                         if ((activeParts[i] == YES || nApplied == 0) && (modelParams[i].dataType == RESTRICTION || modelParams[i].dataType == STANDARD))
                             {
-                            strcpy(modelParams[i].coding, tempStr);
+                            if(!strcmp(tempStr, "Nosingletons"))
+                                {
+                                modelParams[i].coding |= NOSINGLETONS;
+                                }
+                            else if(!strcmp(tempStr, "Variable"))
+                                {
+                                modelParams[i].coding |= VARIABLE;
+                                }
+                            else if(!strcmp(tempStr, "Informative"))
+                                {
+                                modelParams[i].coding |= INFORMATIVE;
+                                }
+                            else
+                                {
+                                if(modelParams[i].dataType != RESTRICTION)
+                                    {
+                                    MrBayesPrint ("%s   Invalid coding for standard characters: %s\n", spacer, tempStr);
+                                    return (ERROR);
+                                    }
+                                
+                                if(!strcmp(tempStr, "Noabsencesites"))
+                                    {
+                                    modelParams[i].coding |= NOABSENCESITES;
+                                    }
+                                else if(!strcmp(tempStr, "Nopresencesites"))
+                                    {
+                                    modelParams[i].coding |= NOPRESENCESITES;
+                                    }
+                                else if(!strcmp(tempStr, "Nosingletonpresence"))
+                                    {
+                                    modelParams[i].coding |= NOSINGLETONPRESENCE;
+                                    }
+                                else if(!strcmp(tempStr, "Nosingletonabsence"))
+                                    {
+                                    modelParams[i].coding |= NOSINGLETONABSENCE;
+                                    }
+                                }
+                            
+                            CodingToString(modelParams[i].coding, modelParams[i].codingString);
+                            
                             if (nApplied == 0 && numCurrentDivisions == 1)
-                                MrBayesPrint ("%s   Setting Coding to %s\n", spacer, modelParams[i].coding);
+                                MrBayesPrint ("%s   Enabling Coding %s\n", spacer, tempStr);
                             else
-                                MrBayesPrint ("%s   Setting Coding to %s for partition %d\n", spacer, modelParams[i].coding, i+1);
+                                MrBayesPrint ("%s   Enabling Coding %s for partition %d\n", spacer, tempStr, i+1);
                             }
                         }
                     }
@@ -3582,7 +3714,7 @@ int DoLsetParm (char *parmName, char *tkn)
                     MrBayesPrint ("%s   Invalid argument for missing patterns\n", spacer);
                     return (ERROR);
                     }
-                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
+                expecting = Expecting(PARAMETER) | Expecting(SEMICOLON) | Expecting(VERTICALBAR);
                 }
             else
                 return (ERROR);
@@ -4197,7 +4329,7 @@ int DoPrset (void)
     int         i, nApplied, lastActive=0;
 
     nApplied = NumActiveParts ();
-    for (i=numCurrentDivisions; i>=0; i--)
+    for (i=numCurrentDivisions-1; i>=0; i--)
         {
         if (activeParts[i] == YES)
             {
@@ -6191,8 +6323,9 @@ int DoPrsetParm (char *parmName, char *tkn)
                             }
                         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);
+                            MrBayesPrint ("%s   Warning: %s can be set only for partition containing data", spacer, parmName);
+                            MrBayesPrint ("  of at least one of the following type: STANDARD, RESTRICTION.");
+                            MrBayesPrint ("Currently there is no active partition with such data. ");
                             return (ERROR);
                             }
                         }
@@ -6970,7 +7103,6 @@ int DoPrsetParm (char *parmName, char *tkn)
                                 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)
@@ -7501,8 +7633,8 @@ int DoPrsetParm (char *parmName, char *tkn)
                                 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)));
+                            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);
@@ -7869,9 +8001,9 @@ int DoPrsetParm (char *parmName, char *tkn)
                             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]);
+                                    MrBayesPrint ("%s   Setting Clockratepr to Normal(%1.6lf,%1.6lf)\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);
+                                    MrBayesPrint ("%s   Setting Clockratepr to Normal(%1.6lf,%1.6lf) for partition %d\n", spacer, modelParams[i].clockRateNormal[0], modelParams[i].clockRateNormal[1], i+1);
                                 expecting  = Expecting(RIGHTPAR);
                                 }
                             }
@@ -10987,7 +11119,7 @@ int FillNormalParams (RandLong *seed, int fromChain, int toChain)
                     if (p->paramId == SPECRATE_FIX)
                         value[j] = mp->speciationFix;
                     else
-                        value[j] = 1.0;
+                        value[j] = 0.1;
                     }
                 }
             else if (p->paramType == P_EXTRATE)
@@ -10998,7 +11130,7 @@ int FillNormalParams (RandLong *seed, int fromChain, int toChain)
                     if (p->paramId == EXTRATE_FIX)
                         value[j] = mp->extinctionFix;
                     else
-                        value[j] = 0.5;
+                        value[j] = 0.8;
                     }
                 }
             else if (p->paramType == P_FOSLRATE)
@@ -11009,7 +11141,7 @@ int FillNormalParams (RandLong *seed, int fromChain, int toChain)
                     if (p->paramId == FOSLRATE_FIX)
                         value[j] = mp->fossilizationFix;
                     else
-                        value[j] = 0.5;
+                        value[j] = 0.2;
                     }
                 }
             else if (p->paramType == P_GROWTH)
@@ -11206,7 +11338,7 @@ int FillRelPartsString (Param *p, char **relPartString)
     char        *tempStr;
     int             tempStrSize=50;
 
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         {
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
@@ -12227,6 +12359,11 @@ int GetEmpiricalFreqs (int *relParts, int nRelParts)
                 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, "Invermt"))
+                {
+                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, "Mycoplasma"))
                 {
                 for (i=0; i<62; i++)
@@ -12237,11 +12374,21 @@ int GetEmpiricalFreqs (int *relParts, int nRelParts)
                 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"))
+            else if (!strcmp(modelParams[firstRel].geneticCode, "Ciliate"))
                 {
                 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, "Echinoderm"))
+                {
+                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, "Euplotid"))
+                {
+                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, "Metmt"))
                 {
                 for (i=0; i<62; i++)
@@ -13137,7 +13284,7 @@ int IsModelSame (int whichParam, int part1, int part2, int *isApplic1, int *isAp
         /* 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))
+            if (strcmp(modelParams[part1].geneticCode, modelParams[part2].geneticCode))
                 isSame = NO; /* the models have different genetic codes */
             }
         
@@ -14877,12 +15024,18 @@ int NumStates (int part)
                 return (61);
             else if (!strcmp(modelParams[part].geneticCode, "Vertmt"))
                 return (60);
+            else if (!strcmp(modelParams[part].geneticCode, "Invermt"))
+                return (62);
             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"))
+            else if (!strcmp(modelParams[part].geneticCode, "Ciliate"))
                 return (63);
+            else if (!strcmp(modelParams[part].geneticCode, "Echinoderm"))
+                return (62);
+            else if (!strcmp(modelParams[part].geneticCode, "Euplotid"))
+                return (62);
             else if (!strcmp(modelParams[part].geneticCode, "Metmt"))
                 return (62);
             }
@@ -15138,7 +15291,7 @@ int ProcessStdChars (RandLong *seed)
         stdType = NULL;
         memAllocs[ALLOC_STDTYPE] = NO;
         }
-    stdType = (int *)SafeCalloc((size_t) (4 * numStandardChars), sizeof(int));
+    stdType = (int *)SafeCalloc(4 * (size_t)numStandardChars, sizeof(int));
     if (!stdType)
         {
         MrBayesPrint ("%s   Problem allocating stdType (%d ints)\n", 4 * numStandardChars);
@@ -17059,6 +17212,17 @@ void SetCode (int part)
         modelParams[part].codon[12] = 13; /* ATA Met  */
         modelParams[part].codon[56] = 18; /* TGA Trp  */
         }
+    if (!strcmp(modelParams[part].geneticCode, "Invermt"))
+        {
+        /* 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 if (!strcmp(modelParams[part].geneticCode, "Mycoplasma"))
         {
         /* UGA: Ter -> Trp */
@@ -17079,13 +17243,29 @@ void SetCode (int part)
         modelParams[part].codon[31] = 17; /* CTT Thr */
         modelParams[part].codon[56] = 18; /* TGA Trp */
         }
-    else if (!strcmp(modelParams[part].geneticCode, "Ciliates"))
+    else if (!strcmp(modelParams[part].geneticCode, "Ciliate"))
         {
         /* 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, "Echinoderm"))
+        {
+        /* AAA: Lys -> Asn
+           AGA: Arg -> Ser
+           AGG: Arg -> Ser
+           UGA: Ter -> Trp */
+        modelParams[part].codon[ 0] = 3;  /* AAA Asn */
+        modelParams[part].codon[ 8] = 16; /* AGA Ser */
+        modelParams[part].codon[10] = 16; /* AGG Ser */
+        modelParams[part].codon[56] = 18; /* TGA Trp */
+        }
+    else if (!strcmp(modelParams[part].geneticCode, "Euplotid"))
+        {
+        /* UGA: Ter -> Cys */
+        modelParams[part].codon[56] = 5;  /* TGA Cys */
+        }
     else if (!strcmp(modelParams[part].geneticCode, "Metmt"))
         {
         /* UGA: Ter -> Trp
@@ -17099,7 +17279,6 @@ void SetCode (int part)
         }
     else
         {
-        
         }
     
     ns = 0;
@@ -17152,12 +17331,12 @@ int SetLocalTaxa (void)
         }
         
     /* allocate memory */
-    localTaxonNames = (char **)SafeCalloc((size_t) numLocalTaxa, sizeof(char *));
+    localTaxonNames = (char **)SafeCalloc((size_t)numLocalTaxa, sizeof(char *));
     if (!localTaxonNames)
         return (ERROR);
     memAllocs[ALLOC_LOCTAXANAMES] = YES;
 
-    localTaxonCalibration = (Calibration **)SafeCalloc((size_t) numLocalTaxa, sizeof(Calibration *));
+    localTaxonCalibration = (Calibration **)SafeCalloc((size_t)numLocalTaxa, sizeof(Calibration *));
     if (!localTaxonCalibration)
         return (ERROR);
     memAllocs[ALLOC_LOCALTAXONCALIBRATION] = YES;
@@ -17219,12 +17398,21 @@ int SetModelDefaults (void)
         
         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"); 
+        if (modelParams[j].dataType == STANDARD)
+            {   /* set default ascertainment bias for partition */
+            modelParams[j].coding = VARIABLE;
+            strcpy(modelParams[j].codingString, "Variable"); 
+            }
         else if (modelParams[j].dataType == RESTRICTION)
-            strcpy(modelParams[j].coding, "Noabsencesites");
+            {
+            modelParams[j].coding = NOABSENCESITES;
+            strcpy(modelParams[j].codingString, "Noabsencesites");   
+            }
         else
-            strcpy(modelParams[j].coding, "All");
+            {
+            modelParams[j].coding = ALL;
+            strcpy(modelParams[j].codingString, "All");
+            }
 
         SetCode (j);
         modelParams[j].nStates = NumStates (j);             /* number of states for partition             */
@@ -17649,8 +17837,8 @@ int SetModelParams (void)
     ModelInfo       *m;
     int             tempStrSize = 300;
 
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
-    isPartTouched = (int *) SafeMalloc ((size_t) (numCurrentDivisions * sizeof (int)));
+    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,
@@ -19777,11 +19965,10 @@ int SetUpLinkTable (void)
                 isFirst, isSame;
     int         *check, *modelId;
 
-    check = (int *) SafeMalloc ((size_t) (2*numCurrentDivisions * sizeof (int)));
+    check = (int *) SafeMalloc (2 * (size_t)numCurrentDivisions * sizeof (int));
     if (!check)
         {
-        MrBayesPrint ("%s   Problem allocating check (%d)\n", spacer,
-            2*numCurrentDivisions * sizeof(int));
+        MrBayesPrint ("%s   Problem allocating check (%d)\n", spacer, 2 * numCurrentDivisions * sizeof(int));
         return (ERROR);
         }
     modelId = check + numCurrentDivisions;
@@ -20145,7 +20332,7 @@ void SetUpMoveTypes (void)
     mt->maximum[1] = 100.0;
     mt->parsimonyBased = NO;
     mt->level = STANDARD_USER;
-    mt->isApplicable = &IsApplicable_FiveTaxaOrMore;
+    mt->isApplicable = &IsApplicable_FourTaxaOrMore;
 
     /* Move_ExtSPR1 */
     mt = &moveTypes[i++];
@@ -20154,15 +20341,20 @@ void SetUpMoveTypes (void)
     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_ExtSPR1;
     mt->relProposalProb = 0.0;
-    mt->numTuningParams = 1;
+    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 = DEVELOPER;
     mt->isApplicable = &IsApplicable_FiveTaxaOrMore;
@@ -20269,26 +20461,6 @@ void SetUpMoveTypes (void)
     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";
@@ -20809,8 +20981,9 @@ void SetUpMoveTypes (void)
     mt->maximum[1] = 0.99999;
     mt->parsimonyBased = YES;
     mt->level = DEVELOPER;
+    mt->isApplicable = &IsApplicable_FiveTaxaOrMore;
 
-    /* Move_ParsSPR */
+    /* Move_ParsSPR asym */
     mt = &moveTypes[i++];
     mt->name = "Parsimony-biased SPR";
     mt->shortName = "ParsSPR";
@@ -20831,7 +21004,7 @@ void SetUpMoveTypes (void)
     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[2] = 0.03;             /* 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;
@@ -20845,7 +21018,7 @@ void SetUpMoveTypes (void)
     mt->level = STANDARD_USER;
     mt->isApplicable = &IsApplicable_FourTaxaOrMore;
 
-    /* Move_ParsSPR1 */
+    /* Move_ParsSPR1 e^{-S} */
     mt = &moveTypes[i++];
     mt->name = "Parsimony-biased SPR variant 1";
     mt->shortName = "ParsSPR1";
@@ -20866,11 +21039,51 @@ void SetUpMoveTypes (void)
     mt->moveFxn = &Move_ParsSPR1;
     mt->relProposalProb = 0.0;
     mt->numTuningParams = 5;
+    mt->tuningParam[0] = 0.5;              /* warp */
+    mt->tuningParam[1] = 0.05;             /* upweight and downweight probability */
+    mt->tuningParam[2] = 0.03;             /* typical branch length */
+    mt->tuningParam[3] = 2.0 * log (1.05); /* multiplier tuning parameter lambda */
+    mt->tuningParam[4] = 10.0;             /* distance to move picked branch */
+    mt->minimum[0] = 0.0;
+    mt->maximum[0] = 5.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_FourTaxaOrMore;
+
+    /* Move_ParsSPR2 S/N */
+    mt = &moveTypes[i++];
+    mt->name = "Parsimony-biased SPR variant 2";
+    mt->shortName = "ParsSPR2";
+    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_ParsSPR2;
+    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[2] = 0.03;             /* 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->tuningParam[4] = 10.0;             /* distance to move picked branch */
     mt->minimum[0] = 0.0;
     mt->maximum[0] = 1.0;
     mt->minimum[1] = 0.0;
@@ -20883,7 +21096,7 @@ void SetUpMoveTypes (void)
     mt->maximum[4] = 1000.0;
     mt->parsimonyBased = YES;
     mt->level = DEVELOPER;
-    mt->isApplicable = &IsApplicable_FiveTaxaOrMore;
+    mt->isApplicable = &IsApplicable_FourTaxaOrMore;
 
     /* Move_ParsSPRClock */
     mt = &moveTypes[i++];
@@ -20910,7 +21123,7 @@ void SetUpMoveTypes (void)
     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->tuningParam[2] = 0.03; /* typical branch length */
     mt->minimum[0] = 0.0;
     mt->maximum[0] = 1.0;
     mt->minimum[1] = 0.0;
@@ -20921,10 +21134,50 @@ void SetUpMoveTypes (void)
     mt->level = STANDARD_USER;
     mt->isApplicable = &IsApplicable_ThreeTaxaOrMore;
 
-    /* Move_ParsTBR */
+    /* Move_ParsTBR1 e^{-S} */
+    mt = &moveTypes[i++];
+    mt->name = "Parsimony-biased TBR variant 1";
+    mt->shortName = "ParsTBR1";
+    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_ParsTBR1;
+    mt->relProposalProb = 0.0;
+    mt->numTuningParams = 5;
+    mt->tuningParam[0] = 0.5;              /* 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] = 5.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_ParsTBR2 S/N */
     mt = &moveTypes[i++];
-    mt->name = "Parsimony-biased TBR";
-    mt->shortName = "ParsTBR";
+    mt->name = "Parsimony-biased TBR variant 2";
+    mt->shortName = "ParsTBR2";
     mt->subParams = YES;
     mt->tuningName[0] = "parsimony warp factor";
     mt->shortTuningName[0] = "warp";
@@ -20939,7 +21192,7 @@ void SetUpMoveTypes (void)
     mt->applicableTo[0] = TOPOLOGY_NCL_UNIFORM_HOMO;
     mt->applicableTo[1] = TOPOLOGY_NCL_CONSTRAINED_HOMO;
     mt->nApplicable = 2;
-    mt->moveFxn = &Move_ParsTBR;
+    mt->moveFxn = &Move_ParsTBR2;
     mt->relProposalProb = 0.0;
     mt->numTuningParams = 5;
     mt->tuningParam[0] = 0.1;              /* warp */
@@ -21002,102 +21255,6 @@ void SetUpMoveTypes (void)
     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";
@@ -21862,9 +22019,7 @@ int ShowModel (void)
                             
                         /* 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)
@@ -21946,7 +22101,7 @@ int ShowModel (void)
                 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);
+                    MrBayesPrint ("%s         Coding    = %s\n", spacer, modelParams[i].codingString);
                     }
                     
                 /* is there rate variation in a single site across the tree? */
@@ -21983,12 +22138,18 @@ int ShowModel (void)
                         ns = 61;
                     else if (!strcmp(modelParams[i].geneticCode, "Vertmt"))
                         ns = 60;
+                    else if (!strcmp(modelParams[i].geneticCode, "Invermt"))
+                        ns = 62;
                     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"))
+                    else if (!strcmp(modelParams[i].geneticCode, "Ciliate"))
                         ns = 63;
+                    else if (!strcmp(modelParams[i].geneticCode, "Echinoderm"))
+                        ns = 62;
+                    else if (!strcmp(modelParams[i].geneticCode, "Euplotid"))
+                        ns = 62;
                     else if (!strcmp(modelParams[i].geneticCode, "Metmt"))
                         ns = 62;
                     }
@@ -22009,15 +22170,15 @@ int ShowModel (void)
                             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);
+                                MrBayesPrint ("%s                     Symmetric Dirichlet alpha 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]);
+                            MrBayesPrint ("%s                     Symmetric Dirichlet alpha 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);
+                            MrBayesPrint ("%s                     Symmetric Dirichlet alpha has a Exponential(%1.2lf) prior\n", spacer, modelParams[i].symBetaExp);
                             }
                         }
                     else if (modelSettings[i].dataType == RESTRICTION)
@@ -22827,10 +22988,10 @@ int ShowParameters (int showStartVals, int showMoves, int showAllAvailable)
                     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);
+                    if (AreDoublesEqual(mp->symBetaFix, -1.0, ETA)==YES)
+                        MrBayesPrint ("%s            Prior      = Symmetric dirichlet with all parameters equal to infinity\n", spacer);
                     else
-                        MrBayesPrint ("%s            Prior      = Symmetric dirichlet with fixed(%1.2lf) variance parameter\n", spacer, mp->symBetaFix);
+                        MrBayesPrint ("%s            Prior      = Symmetric dirichlet with all parameters equal to %1.2lf\n", spacer, mp->symBetaFix);
                     }
                 }
             else if (ms->dataType == PROTEIN)
@@ -23212,7 +23373,7 @@ int ShowParameters (int showStartVals, int showMoves, int showAllAvailable)
         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]);
+                MrBayesPrint ("%s            Prior      = Normal(%1.6lf,%1.6lf)\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"))
@@ -23820,8 +23981,8 @@ int UpdateClockRate (MrBFlt clockRate, int chain)
         {
         if (minClockRate > maxClockRate)
             {
-            MrBayesPrint ("%s   ERROR: Calibrated trees require compatible clockrates for run:%d chain:%d.\n",
-                          spacer, chain/chainParams.numChains, chain%chainParams.numChains);
+            MrBayesPrint ("%s   ERROR: Calibrated trees require compatible clockrates but they are incompatible for run %d, chain %d.\n",
+                          spacer, chain/chainParams.numChains + 1, chain%chainParams.numChains + 1);
             *clockRatep=0;
             return (ERROR);
             }
@@ -23840,8 +24001,8 @@ int UpdateClockRate (MrBFlt clockRate, int chain)
             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);
+                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 + 1, chain%chainParams.numChains + 1);
                 *clockRatep=0;
                 return (ERROR);
                 }
@@ -23849,7 +24010,7 @@ int UpdateClockRate (MrBFlt clockRate, int chain)
                 {
                 if (AreDoublesEqual (*clockRatep, clockRate, 0.0001) == NO)
                     {
-                    MrBayesPrint ("%s   ERROR: Requested clockrate:%f does not match fixed clockrate prior :%f.\n", spacer, clockRate, *clockRatep);
+                    MrBayesPrint ("%s   ERROR: Requested clockrate:%f does not match fixed clockrate prior:%f.\n", spacer, clockRate, *clockRatep);
                     *clockRatep=0;
                     return (ERROR);
                     }
@@ -23864,8 +24025,8 @@ int UpdateClockRate (MrBFlt clockRate, int chain)
                 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);
+                    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 + 1, chain%chainParams.numChains + 1);
                     *clockRatep=0;
                     return (ERROR);
                     }
diff --git a/src/proposal.c b/src/proposal.c
index 9b40a2b..ac1218c 100644
--- a/src/proposal.c
+++ b/src/proposal.c
@@ -42,7 +42,7 @@
 #include "proposal.h"
 #include "utils.h"
 
-const char* const svnRevisionProposalC = "$Rev: 1032 $";   /* Revision keyword which is expanded/updated by svn on each commit/update */
+const char* const svnRevisionProposalC = "$Rev: 1069 $";   /* Revision keyword which is expanded/updated by svn on each commit/update */
 
 /* debugging compiler statements */
 #undef  DEBUG_LOCAL
@@ -59,7 +59,6 @@ const char* const svnRevisionProposalC = "$Rev: 1032 $";   /* Revision keyword w
 
 
 extern int *chainId;
-int  gTopologyHasChanged;  /* flag whether topology has changed */
 
 void TouchAllTreeNodes (ModelInfo *m, int chain);
 
@@ -1272,7 +1271,7 @@ int Move_AddBranch (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRati
     //   (*lnProposalRatio) += log(2.0);
     
     /* add the Jacobian term */
-    (*lnProposalRatio) += log(maxDepth - minDepth);
+    (*lnProposalRatio) += log((maxDepth - minDepth) / clockRate);
             
     /* adjust proposal and prior ratio for relaxed clock models */
     for (i=0; i<param->nSubParams; i++)
@@ -1506,7 +1505,7 @@ int Move_DelBranch (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRati
     //  (*lnProposalRatio) += log(0.5);
 
     /* add the Jacobian term */
-    (*lnProposalRatio) -= log(maxDepth - minDepth);
+    (*lnProposalRatio) -= log((maxDepth - minDepth) / clockRate);
 
     /* adjust proposal and prior ratio for relaxed clock models */
     for (i=0; i<param->nSubParams; i++)
@@ -1601,7 +1600,7 @@ int Move_Extinction (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRat
     
     /* get minimum and maximum values */
     minM = 0.0;
-    maxM = 0.999999;
+    maxM = 0.99999;
 
     /* get pointer to value to be changed */
     valIndex = (int)(RandomNumber(seed) * param->nValues);
@@ -1660,6 +1659,7 @@ int Move_Extinction (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRat
             return (ERROR);
             }
         *valPtr = newM;  // update with new value
+        // for (i=0; i<param->nValues; i++)  *(GetParamVals(param, chain, state[chain]) + i) = newM;
         if (LnFossilizationPriorPr (t, clockRate, &newLnPrior, sR, eR, sF, fR, sS) == ERROR)
             {
             MrBayesPrint ("%s   Problem calculating prior for fossilized birth-death process\n", spacer);
@@ -1710,7 +1710,7 @@ int Move_Fossilization (Param *param, int chain, RandLong *seed, MrBFlt *lnPrior
     m = &modelSettings[param->relParts[0]];
     
     /* get minimum and maximum values */
-    minM = 0.0;
+    minM = 0.00001;
     maxM = 1.0;
     
     /* get pointer to value to be changed */
@@ -1781,18 +1781,13 @@ int Move_Fossilization (Param *param, int chain, RandLong *seed, MrBFlt *lnPrior
 
 int Move_ExtSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
 {
-    /* Change branch lengths and topology (potentially) using SPR (unrooted) 
-       with extension probability (rather than window). */
-
-    /* For a description, see Lakner et al. (2008).
-
-       This move type has been tested on all combinations of rooted and unrooted,
-       constrained and unconstrained trees */
+    /* Change topology (and branch lengths) using SPR (unrooted) with extension probability.
+       Pick either external or internal branches instead of just internal branches. */
     
     int         i, j, topologyHasChanged, nCrownNodes, nRootNodes, directionLeft, directionUp, 
                 isVPriorExp, moveInRoot, isStartConstrained, isStopConstrained;
     MrBFlt      m, x, y, tuning, maxV, minV, extensionProb, brlensExp=0.0;
-    TreeNode    *p, *a, *b, *c, *d, *u, *v, *brlenNode[7];
+    TreeNode    *p, *q, *a, *b, *c, *d, *u, *v;
     Tree        *t;
     ModelParams *mp;
     
@@ -1800,6 +1795,8 @@ int Move_ExtSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
     extensionProb = mvp[0]; /* extension probability */
     tuning = mvp[1];        /* Larget & Simon's tuning parameter lambda */
 
+    (*lnProposalRatio) = (*lnPriorRatio) = 0.0;
+
     /* get tree */
     t = GetTree (param, chain, state[chain]);
 
@@ -1810,7 +1807,7 @@ int Move_ExtSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
     if (param->subParams[0]->paramId == BRLENS_UNI)
         {
         minV = mp->brlensUni[0] > BRLENS_MIN ? mp->brlensUni[0] : BRLENS_MIN;
-        maxV = mp->brlensUni[1];
+        maxV = mp->brlensUni[1] < BRLENS_MAX ? mp->brlensUni[1] : BRLENS_MAX;
         isVPriorExp = NO;
         }
     else if (param->subParams[0]->paramId == BRLENS_GamDir)
@@ -1831,7 +1828,7 @@ int Move_ExtSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
         maxV = BRLENS_MAX;
         isVPriorExp = 4;
         }
-    else
+    else  /* (param->subParams[0]->paramId == BRLENS_EXP) */
         {
         minV = BRLENS_MIN;
         maxV = BRLENS_MAX;
@@ -1851,36 +1848,25 @@ int Move_ExtSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
     getchar();
 #   endif
     
-    /* pick an internal branch that is free to move in either end
-       (i and j keep track of number of locked directions) */
+    /* pick a random branch */
     do  {
-        p = t->intDownPass[(int)(RandomNumber(seed) * (t->nIntNodes-1))];
-        if (p->anc->left == p)
-            a = p->anc->right;
-        else
-            a = p->anc->left;
+        p = t->allDownPass[(int)(RandomNumber(seed) * (t->nNodes -1))];
+        q = p->anc->right;  if (q == p) q = p->anc->left;
         i = j = 0;
-        if (a->isLocked == YES || a->left == NULL)
+        if (p->left == NULL)
+            j = 2;
+        if (p->anc->anc == NULL)
+            i = 2;
+        if (p->anc->anc != NULL && (p->anc->isLocked == YES || p->anc->anc->anc == NULL))
             i++;
-        if (p->anc->isLocked == YES || p->anc->anc->anc == NULL)
+        if (p->anc->anc != NULL && (q->isLocked == YES || q->left == NULL))
             i++;
-        if (p->left->isLocked == YES || p->left->left == NULL)
+        if (p->left != NULL && (p->left->isLocked == YES || p->left->left == NULL))
             j++;
-        if (p->right->isLocked == YES || p->right->left == NULL)
+        if (p->left != NULL && (p->right->isLocked == YES || p->right->left == NULL))
             j++;
         } while (i == 2 && j == 2);
-        
-    /* set up pointers for nodes around the picked branch */
-    /* cut the tree into crown, root and attachment part */
-    /* change the relevant lengths in the attachment part */
-    /* the lengths of a and v are automatically contained in the */
-    /* "attachment" part but the length of c has to be stored in x */
-    v = p;
-    u = p->anc;
-
-    /* store brlen node */
-    brlenNode[3] = v;
-
+    
     /* change in root tree ? */
     if (j == 2)
         moveInRoot = YES;
@@ -1898,104 +1884,78 @@ int Move_ExtSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
     else if (moveInRoot == NO && j == 1)
         isStartConstrained = YES;
 
-    /* set up pointers for crown part */
-    /* also determine direction of move in crown part */
-    if (v->right->left == NULL || v->right->isLocked == YES)
-        directionLeft = YES;
-    else if (v->left->left == NULL || v->left->isLocked == YES)
-        directionLeft = NO;
-    else if (RandomNumber(seed) < 0.5)
-        directionLeft = YES;
-    else
-        directionLeft = NO;
-    if (directionLeft == YES)
-        {
-        c = v->left;
-        d = v->right;
-        }
-    else
-        {
-        c = v->right;
-        d = v->left;
-        }
-
-    /* store brlen nodes and brlen to move */
-    brlenNode[0] = d;
-    brlenNode[1] = c;
-    x = c->length;
-
-    /* cut and reconnect crown part */
-    c->anc = d;
-    d->anc = c;
-    
-    /* mark nodes in root part */
-    /* also determine direction of move in root part */
-    if (u->left == v)
-        a = u->right;
-    else
-        a = u->left;
-    b = u->anc;
-    if (u->anc->anc == NULL || u->isLocked == YES)
-        directionUp = YES;
-    else if (a->left == NULL || a->isLocked == YES)
-        directionUp = NO;
-    else if (RandomNumber(seed) < 0.5)
-        directionUp = YES;
-    else
-        directionUp = NO;
-    if (directionUp == NO)
-        {
-        /* switch a and b */
-        b = a;
-        a = u->anc;
-        }
+    /* set up pointers for nodes around the picked branch */
+    /* cut the tree into crown, root and attachment part  */
+    /* change the relevant lengths in the attachment part */
+    v = p;
+    u = p->anc;
 
-    /* store brlen nodes */
-    if (directionUp == YES)
-        {
-        brlenNode[4] = u;
-        brlenNode[5] = a;
-        }
-    else
+    /* modify length of middle branch */
+    m = v->length;
+    x = m * exp(tuning * (RandomNumber(seed) - 0.5));
+    while (x < minV || x > maxV)
         {
-        brlenNode[4] = b;
-        brlenNode[5] = u;
+        if (x < minV) x = minV * minV / x;
+        if (x > maxV) x = maxV * maxV / x;
         }
+    v->length = x;
+    v->upDateTi = YES;
 
-    /* cut root part*/
-    if (directionUp == NO)
-        {
-        b->anc = a;
-        if (a->left == u)
-            a->left = b;
-        else
-            a->right = b;
-        }
-    else 
-        {
-        a->anc = b;
-        if (b->left == u)
-            b->left = a;
-        else
-            b->right = a;
-        y = a->length;
-        a->length = u->length;
-        u->length = y;
-        a->upDateTi = YES;
-        u->upDateTi = YES;
-        }
+    /* update proposal and prior ratio based on length modification */
+    (*lnProposalRatio) += log (x / m);
+    if (isVPriorExp == YES)
+        (*lnPriorRatio) += brlensExp * (m - x);
 
     /* move around in root subtree */
     nRootNodes = 0;
     if (moveInRoot == YES)
         {
+        /* mark nodes in root part */
+        /* also determine direction of move in root part */
+        if (u->left == v)
+            a = u->right;
+        else
+            a = u->left;
+        b = u->anc;
+        if (u->anc->anc == NULL || u->isLocked == YES)
+            directionUp = YES;
+        else if (a->left == NULL || a->isLocked == YES)
+            directionUp = NO;
+        else if (RandomNumber(seed) < 0.5)
+            directionUp = YES;
+        else
+            directionUp = NO;
+        /* cut root part*/
+        if (directionUp == NO)
+            {
+            b = a;  /* switch a and b */
+            a = u->anc;
+            b->anc = a;
+            if (a->left == u)
+                a->left = b;
+            else
+                a->right = b;
+            }
+        else  // if (directionUp == YES)
+            {
+            a->anc = b;
+            if (b->left == u)
+                b->left = a;
+            else
+                b->right = a;
+            y = a->length;
+            a->length = u->length;
+            u->length = y;
+            a->upDateTi = YES;
+            u->upDateTi = YES;
+            }
+
         for (nRootNodes=0; RandomNumber(seed)<extensionProb || nRootNodes==0; nRootNodes++) 
             {
             if (directionUp == YES) 
                 {   /* going up tree */
                 if (a->left == NULL || a->isLocked == YES)
                     break;      /* can't go further */
-                topologyHasChanged = YES;
                 b = a;
                 if (RandomNumber(seed) < 0.5)
                     a = a->left;
@@ -2009,12 +1969,11 @@ int Move_ExtSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
                     u->lockID = 0;
                     }
                 }
-            else 
+            else  // directionUp == NO
                 {   /* going down tree */
                 if (a->anc == NULL || u->isLocked == YES)
                     break;      /* can't go further */
-                topologyHasChanged = YES;
-                if (RandomNumber(seed)<0.5) 
+                if (RandomNumber(seed) < 0.5)
                     {
                     directionUp = YES; /* switch direction */
                     /* find sister of a */
@@ -2028,9 +1987,8 @@ int Move_ExtSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
                         b = a;
                         a = a->left;
                         }
-                    /* as long as we are moving upwards
-                    the cond likes to update will be
-                    flagged by the last pass from u to the root */
+                    /* as long as we are moving upwards, the cond likes to update
+                       will be flagged by the last pass from u to the root */
                     }   
                 else 
                     {   /* continue down */
@@ -2047,44 +2005,103 @@ int Move_ExtSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
                     }
                 }
             }
+            
+        topologyHasChanged = YES;
         /* check whether stop is constrained */
-        if (directionUp == YES) 
-            {
-            if (a->left == NULL || a->isLocked == YES) 
-                isStopConstrained = YES;
-            }
-        else 
+        if (directionUp == YES && (a->left == NULL || a->isLocked == YES))
+            isStopConstrained = YES;
+        if (directionUp == NO  && (a->anc  == NULL || u->isLocked == YES))
+            isStopConstrained = YES;
+        
+        /* modify branch length */
+        m = u->length;
+        x = m * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
             {
-            if (a->anc  == NULL || u->isLocked == YES)
-                isStopConstrained = YES;
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
             }
-        }
+        u->length = x;
+        u->upDateTi = YES;
 
-    /* store brlen nodes */
-    if (nRootNodes > 0)
-        {
+        /* update proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / m);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (m - x);
+
+        /* combine the subtrees */
         if (directionUp == YES)
             {
-            brlenNode[6] = a;
-            brlenNode[5] = u;
+            u->anc = b;
+            if (u->left == v)
+                u->right = a;
+            else 
+                u->left = a;
+            a->anc = u;
+            if (b->left == a)
+                b->left = u;
+            else
+                b->right = u;
             }
-        else
+        else  // if (directionUp == NO)
             {
-            brlenNode[6] = u;
-            brlenNode[5] = b;
+            u->anc = a;
+            if (u->left == v)
+                u->right = b;
+            else 
+                u->left = b;
+            b->anc = u;
+            if (a->left == b)
+                a->left = u;
+            else
+                a->right = u;
+            /* the modified branch contained in u->length will have to be moved to b->length to enable back move
+               BUT if we haven't moved, it is better to keep it in place (necessary for rooted trees) */
+            y = u->length;
+            u->length = b->length;
+            b->length = y;
+            b->upDateTi = YES;
+            u->upDateTi = YES;
             }
         }
 
     /* move around in crown subtree */
     nCrownNodes = 0;
-    if (moveInRoot == NO)       
+    if (moveInRoot == NO)
         {
+        /* set up pointers for crown part */
+        /* also determine direction of move in crown part */
+        if (v->right->left == NULL || v->right->isLocked == YES)
+            directionLeft = YES;
+        else if (v->left->left == NULL || v->left->isLocked == YES)
+            directionLeft = NO;
+        else if (RandomNumber(seed) < 0.5)
+            directionLeft = YES;
+        else
+            directionLeft = NO;
+        if (directionLeft == YES)
+            {
+            c = v->left;
+            d = v->right;
+            }
+        else
+            {
+            c = v->right;
+            d = v->left;
+            }
+
+        /* store brlen nodes and brlen to move */
+        x = c->length;
+
+        /* cut and reconnect crown part */
+        c->anc = d;
+        d->anc = c;
+    
         for (nCrownNodes=0; RandomNumber(seed)<extensionProb || nCrownNodes==0; nCrownNodes++) 
             {
             if (c->left == NULL || c->isLocked == YES)
                 break;  /* can't go further */
-            topologyHasChanged = YES;
-            if (RandomNumber(seed) < 0.5) 
+            if (RandomNumber(seed) < 0.5)
                 {
                 /* rotate c anticlockwise - prepare pointers for move left */
                 c->anc = c->left;  /* the root will be in the direction we are heading */
@@ -2098,189 +2115,60 @@ int Move_ExtSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
                 c->right = c->left;
                 c->left = d;  
                 }
-            /* OK - let's move!; c->anc points in the right direction
-            don't forget to move the branch lengths as well */
+            /* OK - let's move! c->anc points in the right direction
+               don't forget to move the branch lengths as well */
             d = c;
             c = c->anc;
-            d->length = c->length;
+            d->length = c->length;  /* also rotate other info ?? */
             d->upDateCl = YES; 
             d->upDateTi = YES;
             }
+            
+        topologyHasChanged = YES;
         /* check if stop constrained */
         if (c->left == NULL || c->isLocked == YES)
             isStopConstrained = YES;
-        }
-
-    /* store brlen nodes */
-    if (nCrownNodes > 0)
-        {
-        brlenNode[2] = c;
-        brlenNode[1] = d;
-        }
-
-    /* adjust proposal ratio for constraints */
-    if (isStartConstrained == NO && isStopConstrained == YES)
-        (*lnProposalRatio) += log (2.0 * (1.0 - extensionProb));
-    else if (isStartConstrained == YES && isStopConstrained == NO)
-        (*lnProposalRatio) -= log (2.0 * (1.0 - extensionProb));
-
-    /* combine the subtrees */
-    c->anc = v;
-    d->anc = v;
-    if (directionLeft == YES) 
-        {
-        v->left = c;
-        v->right = d;
-        }
-    else 
-        {
-        v->left = d;
-        v->right = c;
-        }
-
-    /* the dangling branch is inserted in reverted position
-       such that the back move will be possible
-       if we have moved around in crown subtree
-       otherwise it is left in its original position */
-    if (nCrownNodes > 0)
-        {
-        d->length = x;
-        d->upDateTi = YES;
-        }
-    else
-        {
-        c->length = x;
-        }
-
-    if (directionUp == YES) 
-        {
-        u->anc = b;
-        if (u->left == v)
-            u->right = a;
-        else 
-            u->left = a;
-        a->anc = u;
-        if (b->left == a)
-            b->left = u;
-        else
-            b->right = u;
-        /* the dangling branch is contained in u->length
-           and will automatically be inserted in the right position
-           to enable the back move regardless of whether it was
-           initially directed upwards or downwards
-           BUT if we haven't moved in root subtree, it is advantageous (necessary
-           for rooted trees) to avoid switching branches, which occurs otherwise
-           if directionUp == YES */
-        if (nRootNodes == 0) 
+        
+        /* combine the subtrees */
+        c->anc = v;
+        d->anc = v;
+        if (directionLeft == YES)
             {
-            x = u->length;
-            u->length = a->length;
-            a->length = x;
-            a->upDateTi = NO;
-            u->upDateTi = NO;
+            v->left = c;
+            v->right = d;
             }
-        }
-    else 
-        {
-        u->anc = a;
-        if (u->left == v)
-            u->right = b;
-        else 
-            u->left = b;
-        b->anc = u;
-        if (a->left == b)
-            a->left = u;
         else
-            a->right = u;
-        /* the modified branch contained in u->length will have
-           to be moved to b->length to enable back move
-           BUT if we haven't moved, it is better to keep it in place
-           (necessary for rooted trees) */
-        if (nRootNodes > 0) 
             {
-            x = u->length;
-            u->length = b->length;
-            b->length = x;
-            b->upDateTi = YES;
-            u->upDateTi = YES;
+            v->left = d;
+            v->right = c;
             }
-        }
-    
-    /* modify branch lengths */
-    /* first modify length of middle branch */
-    m = brlenNode[3]->length;
-    x = m * exp(tuning * (RandomNumber(seed) - 0.5));
-    while (x < minV || x > maxV)
-        {
-        if (x < minV)
-            x = minV * minV / x;
-        else if (x > maxV)
-            x = maxV * maxV / x;
-        }
-    brlenNode[3]->length = x;
-    brlenNode[3]->upDateTi = YES;
-
-    /* update proposal and prior ratio based on length modification */
-    (*lnProposalRatio) += log (x / m);
-    if (isVPriorExp == YES)
-        (*lnPriorRatio) += brlensExp * (m - x);
-
-    if (moveInRoot == NO)
-        {
-        /* if no move in crown, then select randomly, otherwise always the moved branch */
-        if (nCrownNodes == 0 && RandomNumber(seed) < 0.5)
-            p = brlenNode[0];
-        else
-            p = brlenNode[1];
-
+        
+        /* the dangling branch is inserted in reverted position such that the back move will be possible
+           if we have moved around in crown subtree otherwise it is left in its original position */
+        d->length = x;
+        
         /* modify branch length */
-        m = p->length;
+        m = d->length;
         x = m * exp(tuning * (RandomNumber(seed) - 0.5));
         while (x < minV || x > maxV)
             {
-            if (x < minV)
-                x = minV * minV / x;
-            else if (x > maxV)
-                x = maxV * maxV / x;
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
             }
-        p->length = x;
-        p->upDateTi = YES;
+        d->length = x;
+        d->upDateTi = YES;
 
         /* update proposal and prior ratio based on length modification */
         (*lnProposalRatio) += log (x / m);
         if (isVPriorExp == YES)
             (*lnPriorRatio) += brlensExp * (m - x);
         }
-            
-    if (moveInRoot == YES)
-        {
-        /* if no move in root, then select randomly, otherwise always the moved branch */
-        if (nRootNodes == 0 && RandomNumber(seed) < 0.5)
-            p = brlenNode[4];
-        else
-            p = brlenNode[5];
-        
-        /* modify branch length but not if 'root' branch in rooted tree */
-        if (t->isRooted == NO || p->anc->anc != NULL)
-            {
-            m = p->length;
-            x = m * exp(tuning * (RandomNumber(seed) - 0.5));
-            while (x < minV || x > maxV)
-                {
-                if (x < minV)
-                    x = minV * minV / x;
-                else if (x > maxV)
-                    x = maxV * maxV / x;
-                }
-            p->length = x;
-            p->upDateTi = YES;
 
-            /* update proposal and prior ratio based on length modification */
-            (*lnProposalRatio) += log (x / m);
-            if (isVPriorExp == YES)
-                (*lnPriorRatio) += brlensExp * (m - x); 
-            }
-        }
+    /* adjust proposal ratio for constraints */
+    if (isStartConstrained == NO && isStopConstrained == YES)
+        (*lnProposalRatio) += log (2.0 * (1.0 - extensionProb));
+    else if (isStartConstrained == YES && isStopConstrained == NO)
+        (*lnProposalRatio) -= log (2.0 * (1.0 - extensionProb));
 
     /* set flags for update of cond likes from v and down to root */
     p = v;
@@ -2305,7 +2193,7 @@ int Move_ExtSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
     ShowNodes (t->root, 2, NO);
     getchar();
     printf ("Proposal ratio: %f\n",(*lnProposalRatio));
-    printf ("v: %d  u: %d  c: %d  d: %d  a: %d  b: %d\n",v->index, u->index, 
+    printf ("v: %d  u: %d  c: %d  d: %d  a: %d  b: %d\n",v->index, u->index,
             c->index, d->index, a->index, b->index);
     printf ("No. nodes moved in root subtree: %d\n",nRootNodes);
     printf ("No. nodes moved in crown subtree: %d\n",nCrownNodes);
@@ -2313,36 +2201,70 @@ int Move_ExtSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
     getchar();
 #   endif
 
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-    gNodeMoves = nCrownNodes + nRootNodes;
-#   endif
-
-    assert (nCrownNodes > 0 || nRootNodes > 0);
-    
     return (NO_ERROR);
 }
 
 
 int Move_ExtSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
 {
-    /* Change topology using SPR (unrooted) with extension probability. Map branch lengths without modification */
-
+    /* Change topology (and branch lengths) using SPR (unrooted) with extension probability. */
+    /* Pick only internal branches. For a description, see Lakner et al. (2008). */
+    
     int         i, j, topologyHasChanged, nCrownNodes, nRootNodes, directionLeft, directionUp, 
-                moveInRoot, isStartConstrained, isStopConstrained;
-    MrBFlt      x, y, extensionProb;
-    TreeNode    *p, *a, *b, *c, *d, *u, *v;
+                isVPriorExp, moveInRoot, isStartConstrained, isStopConstrained;
+    MrBFlt      m, x, y, tuning, maxV, minV, extensionProb, brlensExp=0.0;
+    TreeNode    *p, *a, *b, *c, *d, *u, *v, *brlenNode[7];
     Tree        *t;
+    ModelParams *mp;
     
+    /* these parameters should be possible to set by user */
     extensionProb = mvp[0]; /* extension probability */
+    tuning = mvp[1];        /* Larget & Simon's tuning parameter lambda */
 
     (*lnProposalRatio) = (*lnPriorRatio) = 0.0;
 
     /* get tree */
     t = GetTree (param, chain, state[chain]);
+
+    /* get model params */
+    mp = &modelParams[param->relParts[0]];
+    
+    /* max and min brlen */
+    if (param->subParams[0]->paramId == BRLENS_UNI)
+        {
+        minV = mp->brlensUni[0] > BRLENS_MIN ? mp->brlensUni[0] : BRLENS_MIN;
+        maxV = mp->brlensUni[1] < BRLENS_MAX ? mp->brlensUni[1] : BRLENS_MAX;
+        isVPriorExp = NO;
+        }
+    else if (param->subParams[0]->paramId == BRLENS_GamDir)
+        {
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        isVPriorExp = 2;
+        }
+    else if (param->subParams[0]->paramId == BRLENS_iGmDir)
+        {
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        isVPriorExp = 3;
+        }
+    else if (param->subParams[0]->paramId == BRLENS_twoExp)
+        {
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        isVPriorExp = 4;
+        }
+    else
+        {
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        brlensExp = mp->brlensExp;
+        isVPriorExp = YES;
+        }
+
+    /* Dirichlet or twoExp prior */
+    if (isVPriorExp > 1)
+        (*lnPriorRatio) = -LogDirPrior(t, mp, isVPriorExp);
     
     topologyHasChanged = NO;
 
@@ -2351,8 +2273,9 @@ int Move_ExtSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
     ShowNodes (t->root, 2, NO);
     getchar();
 #   endif
-
-    /* pick an internal branch that is free to move in either end */
+    
+    /* pick an internal branch that is free to move in either end
+       (i and j keep track of number of locked directions) */
     do  {
         p = t->intDownPass[(int)(RandomNumber(seed) * (t->nIntNodes-1))];
         if (p->anc->left == p)
@@ -2368,8 +2291,7 @@ int Move_ExtSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
             j++;
         if (p->right->isLocked == YES || p->right->left == NULL)
             j++;
-        }
-    while (i == 2 && j == 2);
+        } while (i == 2 && j == 2);
         
     /* set up pointers for nodes around the picked branch */
     /* cut the tree into crown, root and attachment part */
@@ -2379,6 +2301,9 @@ int Move_ExtSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
     v = p;
     u = p->anc;
 
+    /* store brlen node */
+    brlenNode[3] = v;
+
     /* change in root tree ? */
     if (j == 2)
         moveInRoot = YES;
@@ -2418,6 +2343,8 @@ int Move_ExtSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
         }
 
     /* store brlen nodes and brlen to move */
+    brlenNode[0] = d;
+    brlenNode[1] = c;
     x = c->length;
 
     /* cut and reconnect crown part */
@@ -2446,6 +2373,18 @@ int Move_ExtSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
         a = u->anc;
         }
 
+    /* store brlen nodes */
+    if (directionUp == YES)
+        {
+        brlenNode[4] = u;
+        brlenNode[5] = a;
+        }
+    else
+        {
+        brlenNode[4] = b;
+        brlenNode[5] = u;
+        }
+
     /* cut root part*/
     if (directionUp == NO)
         {
@@ -2544,6 +2483,21 @@ int Move_ExtSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
             }
         }
 
+    /* store brlen nodes */
+    if (nRootNodes > 0)
+        {
+        if (directionUp == YES)
+            {
+            brlenNode[6] = a;
+            brlenNode[5] = u;
+            }
+        else
+            {
+            brlenNode[6] = u;
+            brlenNode[5] = b;
+            }
+        }
+
     /* move around in crown subtree */
     nCrownNodes = 0;
     if (moveInRoot == NO)       
@@ -2580,6 +2534,13 @@ int Move_ExtSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
             isStopConstrained = YES;
         }
 
+    /* store brlen nodes */
+    if (nCrownNodes > 0)
+        {
+        brlenNode[2] = c;
+        brlenNode[1] = d;
+        }
+
     /* adjust proposal ratio for constraints */
     if (isStartConstrained == NO && isStopConstrained == YES)
         (*lnProposalRatio) += log (2.0 * (1.0 - extensionProb));
@@ -2667,9 +2628,85 @@ int Move_ExtSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
             u->upDateTi = YES;
             }
         }
-
-    /* set flags for update of cond likes from v and down to root */
-    p = v;
+    
+    /* modify branch lengths */
+    /* first modify length of middle branch */
+    m = brlenNode[3]->length;
+    x = m * exp(tuning * (RandomNumber(seed) - 0.5));
+    while (x < minV || x > maxV)
+        {
+        if (x < minV)
+            x = minV * minV / x;
+        else if (x > maxV)
+            x = maxV * maxV / x;
+        }
+    brlenNode[3]->length = x;
+    brlenNode[3]->upDateTi = YES;
+
+    /* update proposal and prior ratio based on length modification */
+    (*lnProposalRatio) += log (x / m);
+    if (isVPriorExp == YES)
+        (*lnPriorRatio) += brlensExp * (m - x);
+
+    if (moveInRoot == NO)
+        {
+        /* if no move in crown, then select randomly, otherwise always the moved branch */
+        if (nCrownNodes == 0 && RandomNumber(seed) < 0.5)
+            p = brlenNode[0];
+        else
+            p = brlenNode[1];
+
+        /* modify branch length */
+        m = p->length;
+        x = m * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV)
+                x = minV * minV / x;
+            else if (x > maxV)
+                x = maxV * maxV / x;
+            }
+        p->length = x;
+        p->upDateTi = YES;
+
+        /* update proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / m);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (m - x);
+        }
+            
+    if (moveInRoot == YES)
+        {
+        /* if no move in root, then select randomly, otherwise always the moved branch */
+        if (nRootNodes == 0 && RandomNumber(seed) < 0.5)
+            p = brlenNode[4];
+        else
+            p = brlenNode[5];
+        
+        /* modify branch length but not if 'root' branch in rooted tree */
+        if (t->isRooted == NO || p->anc->anc != NULL)
+            {
+            m = p->length;
+            x = m * exp(tuning * (RandomNumber(seed) - 0.5));
+            while (x < minV || x > maxV)
+                {
+                if (x < minV)
+                    x = minV * minV / x;
+                else if (x > maxV)
+                    x = maxV * maxV / x;
+                }
+            p->length = x;
+            p->upDateTi = YES;
+
+            /* update proposal and prior ratio based on length modification */
+            (*lnProposalRatio) += log (x / m);
+            if (isVPriorExp == YES)
+                (*lnPriorRatio) += brlensExp * (m - x); 
+            }
+        }
+
+    /* set flags for update of cond likes from v and down to root */
+    p = v;
     while (p->anc != NULL)
         {
         p->upDateCl = YES;
@@ -2682,6 +2719,10 @@ int Move_ExtSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
         GetDownPass (t);
         }
 
+    /* Dirichlet or twoExp prior */
+    if (isVPriorExp > 1)
+        (*lnPriorRatio) += LogDirPrior(t, mp, isVPriorExp);
+
 #   if defined (DEBUG_ExtSPR)
     printf ("After:\n");
     ShowNodes (t->root, 2, NO);
@@ -2695,14 +2736,6 @@ int Move_ExtSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
     getchar();
 #   endif
 
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-    gNodeMoves = nCrownNodes + nRootNodes;
-#   endif
-    
     return (NO_ERROR);
 }
 
@@ -2763,7 +2796,8 @@ int Move_ExtSPRClock (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRa
         b = p->anc->right;
         }
     while (p->anc->isLocked == YES || p->anc->anc->anc == NULL
-           || (p == b && a->length < TIME_MIN) || (p == a && b->length < TIME_MIN) || (p->length < TIME_MIN && p->calibration->prior == fixed));
+           || (p == b && a->length < TIME_MIN) || (p == a && b->length < TIME_MIN)
+           || (p->length < TIME_MIN && p->calibration->prior == fixed));
     /* skip constraints, siblings of root (and root); and consider ancestral fossils in fbd tree */
     
     /* set up pointers for nodes around the picked branch */
@@ -4038,16 +4072,13 @@ int Move_ExtSSClock (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRat
 
 int Move_ExtTBR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
 {
-    /* Change branch lengths and topology (potentially) using TBR (unrooted) 
-       with extension probability (rather than window). */
+    /* Change topology (and branch lengths) using TBR with extension probability. */
 
-    /* this move type picks a branch and two "danglies", modifies their length
+    /* This move picks an internal branch and two "danglies", modifies their lengths
        independently according to the method of Larget & Simon (1999: MBE); it then
        moves the danglies away from their original position one node at a time with
-       a probability determined by the extensionProb parameter
-
-       when the danglies are moved, their direction is changed
-       this "reflection" is necessary to enable the back move
+       a probability determined by the extensionProb parameter. When the danglies are moved,
+       their direction is changed -- "reflection" necessary to enable the back move.
 
        This move type has been tested on all combinations of rooted and unrooted,
        constrained and unconstrained trees */
@@ -4063,6 +4094,8 @@ int Move_ExtTBR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
     extensionProb = mvp[0]; /* extension probability */
     tuning = mvp[1];        /* Larget & Simon's tuning parameter lambda */
     
+    (*lnProposalRatio) = (*lnPriorRatio) = 0.0;
+
     /* get tree */
     t = GetTree (param, chain, state[chain]);
 
@@ -4073,7 +4106,7 @@ int Move_ExtTBR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
     if (param->subParams[0]->paramId == BRLENS_UNI)
         {
         minV = mp->brlensUni[0] > BRLENS_MIN ? mp->brlensUni[0] : BRLENS_MIN;
-        maxV = mp->brlensUni[1];
+        maxV = mp->brlensUni[1] < BRLENS_MAX ? mp->brlensUni[1] : BRLENS_MAX;
         isVPriorExp = NO;
         }
     else if (param->subParams[0]->paramId == BRLENS_GamDir)
@@ -4187,10 +4220,8 @@ int Move_ExtTBR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
     x = c->length * exp(tuning * (RandomNumber(seed) - 0.5));       /* save the modified dangling branch for later use */
     while (x < minV || x > maxV)
         {
-        if (x < minV)
-            x = minV * minV / x;
-        else if (x > maxV)
-            x = maxV * maxV / x;
+        if (x < minV) x = minV * minV / x;
+        if (x > maxV) x = maxV * maxV / x;
         }
     
     /* calculate proposal and prior ratio based on length modification */
@@ -4342,16 +4373,10 @@ int Move_ExtTBR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
 
     /* adjust proposal ratio for root move if unbalanced */
     isStopConstrained = NO;
-    if (directionUp == YES) 
-        {
-        if (a->left == NULL || a->isLocked == YES)
-            isStopConstrained = YES;
-        }
-    else 
-        {
-        if (a->anc  == NULL || u->isLocked == YES)
-            isStopConstrained = YES;
-        }
+    if (directionUp == YES && (a->left == NULL || a->isLocked == YES))
+        isStopConstrained = YES;
+    if (directionUp == NO && (a->anc  == NULL || u->isLocked == YES))
+        isStopConstrained = YES;
     if (nRootNodes > 0)
         {
         if (isRootStartConstrained == YES && isStopConstrained == NO)
@@ -4451,9 +4476,9 @@ int Move_ExtTBR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
            if directionUp == YES */
         if (nRootNodes == 0) 
             {
-            x = u->length;
+            y = u->length;
             u->length = a->length;
-            a->length = x;
+            a->length = y;
             a->upDateTi = YES;
             u->upDateTi = NO;   /* u retains its old length */
             }
@@ -4476,9 +4501,9 @@ int Move_ExtTBR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
            (necessary for rooted trees) */
         if (nRootNodes > 0) 
             {
-            x = u->length;
+            y = u->length;
             u->length = b->length;
-            b->length = x;
+            b->length = y;
             b->upDateTi = YES;
             }
         }
@@ -4514,554 +4539,160 @@ int Move_ExtTBR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
     getchar();
 #   endif
 
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-    gNodeMoves = nCrownNodes + nRootNodes;
-#   endif
-
-    assert (nCrownNodes > 0 || nRootNodes > 0);
-
     return (NO_ERROR);
 }
 
 
-int Move_ExtTBR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+/*----------------------------------------------------------------
+|
+|   Move_GeneRate_Dir: Change gene rate multiplier using Dirichlet
+|      proposal.
+|
+----------------------------------------------------------------*/
+int Move_GeneRate_Dir (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
 {
-    /* Change topology using TBR (unrooted) with extension probability. Map branch lengths without modification */
-    
-    int         i, j, topologyHasChanged, nCrownNodes, nRootNodes, directionLeft, directionUp, 
-                alwaysMoveRoot, isCrownStartConstrained, isRootStartConstrained, isStopConstrained;
-    MrBFlt      x, y, extensionProb;
-    TreeNode    *p, *a, *b, *c, *d, *u, *v;
-    Tree        *t;
-
-    extensionProb = mvp[0]; /* extension probability */
-    
-    (*lnProposalRatio) = (*lnPriorRatio) = 0.0;
+    int         i, nRates, isValid;
+    MrBFlt      alphaPi, *value, *subValue, numSites, *alphaDir, x, y, sum,
+                rate_pot, *dirParm, *oldRate, *newRate;
 
-    /* get tree */
-    t = GetTree (param, chain, state[chain]);
-    
-    topologyHasChanged = NO;
+    /* allocate memory */
+    dirParm = (MrBFlt *) SafeCalloc (3*(numTopologies-1), sizeof(MrBFlt));
+    oldRate = dirParm + numCurrentDivisions;
+    newRate = dirParm + 2*numCurrentDivisions;
 
-#   if defined (DEBUG_ExtTBR)
-    printf ("Before:\n");
-    ShowNodes (t->root, 2, NO);
-    getchar();
-#   endif
-    
-    /* pick an internal branch */
-    do  {
-        p = t->intDownPass[(int)(RandomNumber(seed) * (t->nIntNodes-1))];
-        if (p->anc->left == p)
-            a = p->anc->right;
-        else
-            a = p->anc->left;
-        i = j = 0;
-        if (a->isLocked == YES || a->left == NULL)
-            i++;
-        if (p->anc->isLocked == YES || p->anc->anc->anc == NULL)
-            i++;
-        if (p->left->isLocked == YES || p->left->left == NULL)
-            j++;
-        if (p->right->isLocked == YES || p->right->left == NULL)
-            j++;
-        }
-    while (i == 2 && j == 2);
+    /* get number of rates */
+    nRates = param->nValues;
 
-    /* determine whether to move first step unconditionally in root or in crown */
-    if (j == 2)
-        alwaysMoveRoot = YES;
-    else if (i == 2)
-        alwaysMoveRoot = NO;
-    else if (RandomNumber(seed) < 0.5)
-        alwaysMoveRoot = YES;
-    else
-        alwaysMoveRoot = NO;
+    /* get pointer to rates and number of uncompressed chars */
+    value = GetParamVals(param, chain, state[chain]);
+    subValue = GetParamSubVals(param, chain, state[chain]);
 
-    /* determine any starting constraints */
-    isCrownStartConstrained = isRootStartConstrained = NO;
-    if (i >= 1)
-        isRootStartConstrained = YES;
-    if (j >= 1)
-        isCrownStartConstrained = YES;
+    /* get Dirichlet parameters */
+    alphaDir = subValue + nRates;
 
-    /* set up pointers for nodes around the picked branch */
-    /* cut the tree into crown, root and attachment part */
-    /* change the relevant lengths in the attachment part */
-    /* the lengths of a and v are automatically contained in the */
-    /* "attachment" part but the length of c has to be stored in x */
-    v = p;
-    u = p->anc;
+    /* calculate old ratesum proportions */
+    numSites = 0.0;
+    for (i=0; i<nRates; i++)
+        numSites += subValue[i];  /* numSites should be equal to the number of sites */
+    for (i=0; i<nRates; i++)
+        oldRate[i] = value[i] * subValue[i] / numSites;
+    
+    /* get so called alphaPi parameter */
+    alphaPi = mvp[0] * nRates;
+    
+    /* multiply old ratesum proportions with some large number to get new values close to the old ones */
+    for (i=0; i<nRates; i++)
+        dirParm[i] = oldRate[i] * alphaPi;
+    
+    /* get new values */
+    DirichletRandomVariable (dirParm, newRate, nRates, seed);
 
-    /* set up pointers for crown part */
-    /* also determine direction of move in crown part */
-    if (v->right->left == NULL || v->right->isLocked == YES)
-        directionLeft = YES;
-    else if (v->left->left == NULL || v->left->isLocked == YES)
-        directionLeft = NO;
-    else if (RandomNumber(seed) < 0.5)
-        directionLeft = YES;
-    else
-        directionLeft = NO;
-    if (directionLeft == YES)
-        {
-        c = v->left;
-        d = v->right;
-        }
-    else
+    /* check new values. we rely on newRate be already normalized  */
+    while (1)
         {
-        c = v->right;
-        d = v->left;
+        sum = 0.0;
+        rate_pot = 1.0;
+        isValid=1;
+        for (i=0; i<nRates; i++)
+            {
+            if (newRate[i] <= DIR_MIN)
+                {
+                if (newRate[i] < DIR_MIN)
+                    {
+                    newRate[i] = DIR_MIN;
+                    isValid=0;
+                    }
+                rate_pot -= DIR_MIN;
+                }
+            else
+                sum += newRate[i];
+            }
+        if (isValid==1) break;
+        for (i=0; i<nRates; i++)
+            {
+            if (newRate[i]!=DIR_MIN)
+                newRate[i] = rate_pot * newRate[i] / sum;
+            }
         }
 
-    /* cut and reconnect crown part */
-    c->anc = d;
-    d->anc = c;
-    
-    /* record c length */
-    x = c->length;
+    /* calculate and copy new rate ratio values back */
+    for (i=0; i<nRates; i++)
+        value[i] = newRate[i] * (numSites / subValue[i]);
+    
+    /* get proposal ratio */
+    sum = 0.0;
+    for (i=0; i<nRates; i++)
+        sum += newRate[i]*alphaPi;
+    x = LnGamma(sum);
+    for (i=0; i<nRates; i++)
+        x -= LnGamma(newRate[i]*alphaPi);
+    for (i=0; i<nRates; i++)
+        x += (newRate[i]*alphaPi-1.0)*log(oldRate[i]);
+    sum = 0.0;
+    for (i=0; i<nRates; i++)
+        sum += oldRate[i]*alphaPi;
+    y = LnGamma(sum);
+    for (i=0; i<nRates; i++)
+        y -= LnGamma(oldRate[i]*alphaPi);
+    for (i=0; i<nRates; i++)
+        y += (oldRate[i]*alphaPi-1.0)*log(newRate[i]);
+    (*lnProposalRatio) = x - y;
 
-    /* mark nodes in root part */
-    /* also determine direction of move in root part */
-    if (u->left == v)
-        a = u->right;
-    else
-        a = u->left;
-    b = u->anc;
-    if (u->anc->anc == NULL || u->isLocked == YES)
-        directionUp = YES;
-    else if (a->left == NULL || a->isLocked == YES)
-        directionUp = NO;
-    else if (RandomNumber(seed) < 0.5)
-        directionUp = YES;
-    else
-        directionUp = NO;
-    if (directionUp == NO)
-        {
-        /* switch a and b */
-        b = a;
-        a = u->anc;
-        }
+    /* get prior ratio */
+    x = y = 0.0;
+    for (i=0; i<nRates; i++)
+        x += (alphaDir[i]-1.0)*log(newRate[i]);
+    for (i=0; i<nRates; i++)
+        y += (alphaDir[i]-1.0)*log(oldRate[i]);
+    (*lnPriorRatio) = x - y;
 
-    /* cut root part */
-    if (directionUp == NO)
-        {
-        b->anc = a;
-        if (a->left == u)
-            a->left = b;
-        else
-            a->right = b;
-        }
-    else 
-        {
-        a->anc = b;
-        if (b->left == u)
-            b->left = a;
-        else
-            b->right = a;
-        y = a->length;
-        a->length = u->length;
-        u->length = y;
-        a->upDateTi = YES;
-        }
-    u->upDateTi = YES;
+    /* Set update flags for all partitions that share the rate multiplier. Note that the conditional
+       likelihood update flags have been set before we even call this function. */
+    for (i=0; i<param->nRelParts; i++)
+        TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
+        
+    /* may need to hit update flag for cijks when you have a covarion model */
+    for (i=0; i<param->nRelParts; i++)
+        if (modelSettings[param->relParts[i]].nCijkParts > 1)
+            modelSettings[param->relParts[i]].upDateCijk = YES;
 
-    /* move around in root subtree */
-    for (nRootNodes=0; (alwaysMoveRoot == YES && nRootNodes == 0) || RandomNumber(seed) < extensionProb; nRootNodes++)
-        {
-        if (directionUp == YES) 
-            {   /* going up tree */
-            if (a->left == NULL || a->isLocked == YES)
-                break;      /* can't go further */
-            topologyHasChanged = YES;
-            b = a;
-            if (RandomNumber(seed) < 0.5)
-                a = a->left;
-            else
-                a = a->right;
-            if (u->isLocked == YES)
-                {
-                b->isLocked = YES;
-                u->isLocked = NO;
-                b->lockID = u->lockID;
-                u->lockID = 0;
-                }
-            }
-        else 
-            {   /* going down tree */
-            if (a->anc == NULL || u->isLocked == YES)
-                break;      /* can't go further */
-            topologyHasChanged = YES;
-            if (RandomNumber(seed)<0.5) 
-                {
-                directionUp = YES; /* switch direction */
-                /* find sister of a */
-                if (a->left == b) 
-                    {
-                    b = a;
-                    a = a->right;
-                    }
-                else 
-                    {  
-                    b = a;
-                    a = a->left;
-                    }
-                /* as long as we are moving upwards
-                the cond likes to update will be
-                flagged by the last pass from u to the root */
-                }   
-            else 
-                {   /* continue down */
-                b = a;
-                a = a->anc;
-                b->upDateCl = YES; 
-                if (b->isLocked == YES)
-                    {
-                    u->isLocked = YES;
-                    b->isLocked = NO;
-                    u->lockID = b->lockID;
-                    b->lockID = 0;
-                    }
-                }
-            }
-        }
+    free (dirParm);
 
-    /* adjust proposal ratio for root move if unbalanced */
-    isStopConstrained = NO;
-    if (directionUp == YES) 
-        {
-        if (a->left == NULL || a->isLocked == YES)
-            isStopConstrained = YES;
-        }
-    else 
-        {
-        if (a->anc  == NULL || u->isLocked == YES)
-            isStopConstrained = YES;
-        }
-    if (nRootNodes > 0)
-        {
-        if (isRootStartConstrained == YES && isStopConstrained == NO)
-            (*lnProposalRatio) -= log (2.0 * (1.0 - extensionProb));
-        else if (isRootStartConstrained == NO && isStopConstrained == YES)
-            (*lnProposalRatio) += log (2.0 * (1.0 - extensionProb));
-        }
+    return (NO_ERROR);
+}
 
-    /* move around in crown subtree */
-    for (nCrownNodes=0; (alwaysMoveRoot == NO && nCrownNodes == 0) || RandomNumber(seed) < extensionProb; nCrownNodes++)
-        {
-        if (c->left == NULL || c->isLocked == YES)
-            break;  /* can't go further */
-        topologyHasChanged = YES;
-        if (RandomNumber(seed) < 0.5) 
-            {
-            /* rotate c anticlockwise - prepare pointers for move left */
-            c->anc = c->left;  /* the root will be in the direction we are heading */
-            c->left = c->right;
-            c->right = d;
-            }
-        else 
-            {
-            /* rotate c clockwise - prepare pointers for move right */
-            c->anc = c->right;  /* the root will be in the direction we are heading */
-            c->right = c->left;
-            c->left = d;  
-            }
-        /* OK - let's move!; c->anc points in the right direction
-        don't forget to move the branch lengths as well */
-        d = c;
-        c = c->anc;
-        d->length = c->length;
-        d->upDateCl = YES; 
-        d->upDateTi = YES;
-        }
 
-    /* adjust proposal ratio for crown move if unbalanced */
-    isStopConstrained = NO;
-    if (c->left == NULL || c->isLocked == YES)
-        isStopConstrained = YES;
-    if (nCrownNodes > 0)
-        {
-        if (isCrownStartConstrained == YES && isStopConstrained == NO)
-            (*lnProposalRatio) -= log (2.0 * (1.0 - extensionProb));
-        else if (isCrownStartConstrained == NO && isStopConstrained == YES)
-            (*lnProposalRatio) += log (2.0 * (1.0 - extensionProb));
-        }
+int Move_RateShape_M (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+{
+    /* change gamma/lnorm shape parameter using multiplier */
+    
+    int         i, isAPriorExp, isValidA;
+    MrBFlt      oldA, newA, minA, maxA, alphaExp=0.0, ran, factor, tuning, *rates;
+    ModelParams *mp;
 
-    /* combine the subtrees */
-    c->anc = v;
-    d->anc = v;
-    if (directionLeft == YES) 
-        {
-        v->left = c;
-        v->right = d;
-        }
-    else 
-        {
-        v->left = d;
-        v->right = c;
-        }
+    /* get tuning parameter */
+    tuning = mvp[0];
 
-    /* the dangling branch is inserted in reverted position
-       such that the back move will be possible
-       if we have moved around in crown subtree
-       otherwise it is left in its original position */
-    if (nCrownNodes > 0)
+    /* get model params */
+    mp = &modelParams[param->relParts[0]];
+    
+    /* get minimum and maximum values for alpha */
+    if (param->paramId == SHAPE_UNI)
         {
-        d->length = x;
-        d->upDateTi = YES;
+        minA = mp->shapeUni[0];
+        maxA = mp->shapeUni[1];
+        if (minA < MIN_SHAPE_PARAM)
+            minA = MIN_SHAPE_PARAM;
+        if (maxA > MAX_SHAPE_PARAM)
+            maxA = MAX_SHAPE_PARAM;
+        isAPriorExp = NO;
         }
     else
         {
-        c->length = x;
-        c->upDateTi = YES;
-        }
-
-    if (directionUp == YES) 
-        {
-        u->anc = b;
-        if (u->left == v)
-            u->right = a;
-        else 
-            u->left = a;
-        a->anc = u;
-        if (b->left == a)
-            b->left = u;
-        else
-            b->right = u;
-        /* the dangling branch is contained in u->length
-           and will automatically be inserted in the right position
-           to enable the back move regardless of whether it was
-           initially directed upwards or downwards
-           BUT if we haven't moved in root subtree, it is advantageous (necessary
-           for rooted trees) to avoid switching branches, which occurs otherwise
-           if directionUp == YES */
-        if (nRootNodes == 0) 
-            {
-            x = u->length;
-            u->length = a->length;
-            a->length = x;
-            a->upDateTi = YES;
-            u->upDateTi = NO;   /* u retains its old length */
-            }
-        }
-    else 
-        {
-        u->anc = a;
-        if (u->left == v)
-            u->right = b;
-        else
-            u->left = b;
-        b->anc = u;
-        if (a->left == b)
-            a->left = u;
-        else
-            a->right = u;
-        /* the modified branch contained in u->length will have
-           to be moved to b->length to enable back move
-           BUT if we haven't moved, it is better to keep it in place
-           (necessary for rooted trees) */
-        if (nRootNodes > 0) 
-            {
-            x = u->length;
-            u->length = b->length;
-            b->length = x;
-            b->upDateTi = YES;
-            }
-        }
-        
-    /* set flags for update of cond likes from v and down to root */
-    p = v;
-    while (p->anc != NULL)
-        {
-        p->upDateCl = YES;
-        p = p->anc;
-        }
-
-    /* get down pass sequence if tree topology has changed */
-    if (topologyHasChanged == YES)
-        {
-        GetDownPass (t);
-        }
-
-#   if defined (DEBUG_ExtTBR)
-    printf ("After:\n");
-    ShowNodes (t->root, 2, NO);
-    getchar();
-    printf ("Proposal ratio: %f\n",(*lnProposalRatio));
-    printf ("v: %d  u: %d  c: %d  d: %d  a: %d  b: %d\n",v->index, u->index,
-            c->index, d->index, a->index, b->index);
-    printf ("No. nodes moved in root subtree: %d\n",nRootNodes);
-    printf ("No. nodes moved in crown subtree: %d\n",nCrownNodes);
-    printf ("Has topology changed? %d\n",topologyHasChanged);
-    getchar();
-#   endif
-
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-    gNodeMoves = nCrownNodes + nRootNodes;
-#   endif
-
-    return (NO_ERROR);
-}
-
-
-/*----------------------------------------------------------------
-|
-|   Move_GeneRate_Dir: Change gene rate multiplier using Dirichlet
-|      proposal.
-|
-----------------------------------------------------------------*/
-int Move_GeneRate_Dir (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
-{
-    int         i, nRates, isValid;
-    MrBFlt      alphaPi, *value, *subValue, numSites, *alphaDir, x, y, sum,
-                rate_pot, *dirParm, *oldRate, *newRate;
-
-    /* allocate memory */
-    dirParm = (MrBFlt *) SafeCalloc (3*(numTopologies-1), sizeof(MrBFlt));
-    oldRate = dirParm + numCurrentDivisions;
-    newRate = dirParm + 2*numCurrentDivisions;
-
-    /* get number of rates */
-    nRates = param->nValues;
-
-    /* get pointer to rates and number of uncompressed chars */
-    value = GetParamVals(param, chain, state[chain]);
-    subValue = GetParamSubVals(param, chain, state[chain]);
-
-    /* get Dirichlet parameters */
-    alphaDir = subValue + nRates;
-
-    /* calculate old ratesum proportions */
-    numSites = 0.0;
-    for (i=0; i<nRates; i++)
-        numSites += subValue[i];  /* numSites should be equal to the number of sites */
-    for (i=0; i<nRates; i++)
-        oldRate[i] = value[i] * subValue[i] / numSites;
-    
-    /* get so called alphaPi parameter */
-    alphaPi = mvp[0] * nRates;
-    
-    /* multiply old ratesum proportions with some large number to get new values close to the old ones */
-    for (i=0; i<nRates; i++)
-        dirParm[i] = oldRate[i] * alphaPi;
-    
-    /* get new values */
-    DirichletRandomVariable (dirParm, newRate, nRates, seed);
-
-    /* check new values. we rely on newRate be already normalized  */
-    while (1)
-        {
-        sum = 0.0;
-        rate_pot = 1.0;
-        isValid=1;
-        for (i=0; i<nRates; i++)
-            {
-            if (newRate[i] <= DIR_MIN)
-                {
-                if (newRate[i] < DIR_MIN)
-                    {
-                    newRate[i] = DIR_MIN;
-                    isValid=0;
-                    }
-                rate_pot -= DIR_MIN;
-                }
-            else
-                sum += newRate[i];
-            }
-        if (isValid==1) break;
-        for (i=0; i<nRates; i++)
-            {
-            if (newRate[i]!=DIR_MIN)
-                newRate[i] = rate_pot * newRate[i] / sum;
-            }
-        }
-
-    /* calculate and copy new rate ratio values back */
-    for (i=0; i<nRates; i++)
-        value[i] = newRate[i] * (numSites / subValue[i]);
-    
-    /* get proposal ratio */
-    sum = 0.0;
-    for (i=0; i<nRates; i++)
-        sum += newRate[i]*alphaPi;
-    x = LnGamma(sum);
-    for (i=0; i<nRates; i++)
-        x -= LnGamma(newRate[i]*alphaPi);
-    for (i=0; i<nRates; i++)
-        x += (newRate[i]*alphaPi-1.0)*log(oldRate[i]);
-    sum = 0.0;
-    for (i=0; i<nRates; i++)
-        sum += oldRate[i]*alphaPi;
-    y = LnGamma(sum);
-    for (i=0; i<nRates; i++)
-        y -= LnGamma(oldRate[i]*alphaPi);
-    for (i=0; i<nRates; i++)
-        y += (oldRate[i]*alphaPi-1.0)*log(newRate[i]);
-    (*lnProposalRatio) = x - y;
-
-    /* get prior ratio */
-    x = y = 0.0;
-    for (i=0; i<nRates; i++)
-        x += (alphaDir[i]-1.0)*log(newRate[i]);
-    for (i=0; i<nRates; i++)
-        y += (alphaDir[i]-1.0)*log(oldRate[i]);
-    (*lnPriorRatio) = x - y;
-
-    /* Set update flags for all partitions that share the rate multiplier. Note that the conditional
-       likelihood update flags have been set before we even call this function. */
-    for (i=0; i<param->nRelParts; i++)
-        TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
-        
-    /* may need to hit update flag for cijks when you have a covarion model */
-    for (i=0; i<param->nRelParts; i++)
-        if (modelSettings[param->relParts[i]].nCijkParts > 1)
-            modelSettings[param->relParts[i]].upDateCijk = YES;
-
-    free (dirParm);
-
-    return (NO_ERROR);
-}
-
-
-int Move_RateShape_M (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
-{
-    /* change gamma/lnorm shape parameter using multiplier */
-    
-    int         i, isAPriorExp, isValidA;
-    MrBFlt      oldA, newA, minA, maxA, alphaExp=0.0, ran, factor, tuning, *rates;
-    ModelParams *mp;
-
-    /* get tuning parameter */
-    tuning = mvp[0];
-
-    /* get model params */
-    mp = &modelParams[param->relParts[0]];
-    
-    /* get minimum and maximum values for alpha */
-    if (param->paramId == SHAPE_UNI)
-        {
-        minA = mp->shapeUni[0];
-        maxA = mp->shapeUni[1];
-        if (minA < MIN_SHAPE_PARAM)
-            minA = MIN_SHAPE_PARAM;
-        if (maxA > MAX_SHAPE_PARAM)
-            maxA = MAX_SHAPE_PARAM;
-        isAPriorExp = NO;
-        }
-    else
-        {
-        minA = MIN_SHAPE_PARAM;
-        maxA = MAX_SHAPE_PARAM;
-        alphaExp = mp->shapeExp;
-        isAPriorExp = YES;
+        minA = MIN_SHAPE_PARAM;
+        maxA = MAX_SHAPE_PARAM;
+        alphaExp = mp->shapeExp;
+        isAPriorExp = YES;
         }
 
     /* get old value of alpha */
@@ -6053,13 +5684,6 @@ int Move_Local (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, M
     getchar();
 #   endif
 
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-#   endif
-    
     return (NO_ERROR);
 }
 
@@ -6548,16 +6172,7 @@ int Move_LocalClock (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRat
     printf ("After:\n");
     ShowNodes (t->root, 2, YES);
     printf ("Has topology changed? %d\n",topologyHasChanged);
-#   endif
-    
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-#   endif
 
-#if defined (DEBUG_LOCAL)
     /* check branch lengths and node depths */
     for (i=0; i<t->nNodes-2; i++) {
         p = t->allDownPass[i];
@@ -6581,13 +6196,12 @@ int Move_LocalClock (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRat
 /*--------------------------------------------------------------------
 |
 |   Move_LSPR: Change topology using move based on likelihood scores
-|        TODO: Make this work for constrained trees
 |
 |--------------------------------------------------------------------*/
 int Move_LSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
 {
     /* Change branch lengths and topology (potentially) using SPR-type move 
-       biased according to likelihood scores. */
+       biased according to likelihood scores. NOT work for constrained trees. */
     
     int         i, j, n, division, topologyHasChanged, isVPriorExp, nNodes;
     BitsLong    *pA, *pV, *pP;
@@ -6750,7 +6364,7 @@ int Move_LSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, Mr
         }
 
     /* find number of site patterns and modify randomly */
-    globalNSitesOfPat = numSitesOfPat + ((chainId[chain] % chainParams.numChains) * numCompressedChars) + m->compCharStart;
+    globalNSitesOfPat = numSitesOfPat + (chainId[chain] % chainParams.numChains) * numCompressedChars + m->compCharStart;
     nSitesOfPat = (CLFlt *) SafeCalloc (numCompressedChars, sizeof(CLFlt));
     if (!nSitesOfPat)
         {
@@ -6974,14 +6588,6 @@ int Move_LSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, Mr
     getchar();
 #   endif
 
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-    gNodeMoves = nRootNodes;
-#   endif
-
     return (NO_ERROR);
 }
 
@@ -6989,13 +6595,12 @@ int Move_LSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, Mr
 /*--------------------------------------------------------------------
 |
 |  Move_LSPR1: Change topology using move based on likelihood scores
-|        TODO: Make this work for constrained trees
 |
 |--------------------------------------------------------------------*/
 int Move_LSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
 {
     /* Change branch lengths and topology (potentially) using SPR-type move 
-       biased according to likelihood scores. */
+       biased according to likelihood scores. NOT work for constrained trees. */
     
     int         i, j, n, division, topologyHasChanged, isVPriorExp, nNodes;
     BitsLong    *pA, *pV, *pP;
@@ -7353,14 +6958,6 @@ int Move_LSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, M
     getchar();
 #   endif
 
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-    gNodeMoves = nRootNodes;
-#   endif
-
     return (NO_ERROR);
 }
 #endif
@@ -8623,2954 +8220,709 @@ int Move_OmegaCat (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio
        distribution for omega too */
     if (!strcmp(mp->omegaVar, "M10"))
         {
-        for (i=0; i<mp->numM10BetaCats; i++)
-            newSubVals[i] = newFreqs[0] / mp->numM10BetaCats;
-        for (i=mp->numM10BetaCats; i<mp->numM10BetaCats+mp->numM10GammaCats; i++)
-            newSubVals[i] = newFreqs[1] / mp->numM10GammaCats;
-        }
-
-    /* get proposal ratio */
-    sum = 0.0;
-    for (i=0; i<localNumCats; i++)
-        sum += newFreqs[i]*alpha;
-    x = LnGamma(sum);
-    for (i=0; i<localNumCats; i++)
-        x -= LnGamma(newFreqs[i]*alpha);
-    for (i=0; i<localNumCats; i++)
-        x += (newFreqs[i]*alpha-1.0)*log(oldFreqs[i]);
-    sum = 0.0;
-    for (i=0; i<localNumCats; i++)
-        sum += oldFreqs[i]*alpha;
-    y = LnGamma(sum);
-    for (i=0; i<localNumCats; i++)
-        y -= LnGamma(oldFreqs[i]*alpha);
-    for (i=0; i<localNumCats; i++)
-        y += (oldFreqs[i]*alpha-1.0)*log(newFreqs[i]);
-    (*lnProposalRatio) = x - y;
-
-    /* get prior ratio */
-    x = y = 0.0;        /* ignore the gamma part, it is identical */
-    for (i=0; i<localNumCats; i++)
-        x += (priorParams[i]-1.0)*log(newFreqs[i]);
-    for (i=0; i<localNumCats; i++)
-        y += (priorParams[i]-1.0)*log(oldFreqs[i]);
-    (*lnPriorRatio) = x - y;
-        
-    /* Set update flags for all partitions that share this omega. Note that the conditional
-       likelihood update flags have been set before we even call this function. */
-    for (i=0; i<param->nRelParts; i++)
-        TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
-
-    /* Set update flags for cijks for all affected partitions. */
-    for (i=0; i<param->nRelParts; i++)
-        modelSettings[param->relParts[i]].upDateCijk = YES;
-
-    return (NO_ERROR);
-}
-
-
-/*----------------------------------------------------------------
-|
-|   Move_OmegaM3: Change the nonysnonymous/synonymous rate ratio
-|      of one class of the M3 model
-|
-----------------------------------------------------------------*/
-int Move_OmegaM3 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
-{
-    int         i, isValidO, whichOmega;
-    MrBFlt      newO, window, minO, maxO, ran, *value, *oldValue, x, y;
-
-    /* get size of window, centered on current omega value */
-    window = mvp[0];
-
-    /* get old value of omega */
-    value = GetParamVals(param, chain, state[chain]);
-    oldValue = GetParamVals(param, chain, state[chain] ^ 1);
-    whichOmega = (int) (RandomNumber(seed)*3.0);
-    
-    /* get minimum and maximum values for omega */
-    if (whichOmega == 0)
-        minO = 0.0;
-    else
-        minO = value[whichOmega-1];
-    if (whichOmega == 2)
-        maxO = OMEGA_MAX;
-    else
-        maxO = value[whichOmega+1];
-
-    /* change value for omega */
-    ran = RandomNumber(seed);
-     if (maxO-minO < window)
-        {
-        window = maxO-minO;
-        }
-    newO = oldValue[whichOmega] + window * (ran - 0.5);
-    
-    /* check that new value is valid */
-    isValidO = NO;
-    do
-        {
-        if (newO < minO)
-            newO = 2* minO - newO;
-        else if (newO > maxO)
-            newO = 2 * maxO - newO;
-        else
-            isValidO = YES;
-        } while (isValidO == NO);
-
-    /* copy new omega value back */
-    value[whichOmega] = newO;
-
-    /* get proposal ratio */
-    *lnProposalRatio = 0.0;
-    
-    /* get prior ratio */
-    x = LogOmegaPrior (value[0], value[1], value[2]);
-    y = LogOmegaPrior (oldValue[0], oldValue[1], oldValue[2]);
-    *lnPriorRatio = x - y;
-
-    /* Set update flags for all partitions that share this omega. Note that the conditional
-       likelihood update flags have been set before we even call this function. */
-    for (i=0; i<param->nRelParts; i++)
-        TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
-
-    /* Set update flags for cijks for all affected partitions. */
-    for (i=0; i<param->nRelParts; i++)
-        modelSettings[param->relParts[i]].upDateCijk = YES;
-
-    return (NO_ERROR);
-}
-
-
-/*----------------------------------------------------------------
-|
-|   Move_OmegaNeu: Change the nonysnonymous/synonymous rate ratio
-|      for neutral sites
-|
-----------------------------------------------------------------*/
-int Move_OmegaNeu (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
-{
-    int         i, isOPriorExp, isValidO;
-    MrBFlt      oldO, newO, window, minO, maxO, ran, *value, x, y;
-
-    /* get size of window, centered on current omega value */
-    window = mvp[0];
-
-    /* get old value of omega */
-    value = GetParamVals(param, chain, state[chain]);
-    newO = oldO = value[1];
-
-    /* get minimum and maximum values for omega */
-    minO = value[0];
-    maxO = value[2];
-    
-    /* the only way we would be updating the middle category (omega2) is
-       if we have an exponential prior on all three omegas */
-    isOPriorExp = YES;
-
-    /* change value for omega */
-    ran = RandomNumber(seed);
-    if (maxO-minO < window)
-        {
-        window = maxO-minO;
-        }
-    newO = oldO + window * (ran - 0.5);
-    
-    /* check that new value is valid */
-    isValidO = NO;
-    do
-        {
-        if (newO < minO)
-            newO = 2 * minO - newO;
-        else if (newO > maxO)
-            newO = 2 * maxO - newO;
-        else
-            isValidO = YES;
-        } while (isValidO == NO);
-
-    /* get proposal ratio */
-    *lnProposalRatio = 0.0;
-    
-    /* copy new omega value back */
-    value[1] = newO;
-
-    /* get prior ratio */
-    if (isOPriorExp == NO)
-        {
-        *lnPriorRatio = 0.0;
-        }
-    else
-        {
-        x = LogOmegaPrior (value[0], newO, value[2]);
-        y = LogOmegaPrior (value[0], oldO, value[2]);
-        *lnPriorRatio = x - y;
-        }
-
-    /* Set update flags for all partitions that share this omega. Note that the conditional
-       likelihood update flags have been set before we even call this function. */
-    for (i=0; i<param->nRelParts; i++)
-        TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
-
-    /* Set update flags for cijks for all affected partitions. */
-    for (i=0; i<param->nRelParts; i++)
-        modelSettings[param->relParts[i]].upDateCijk = YES;
-
-    return (NO_ERROR);
-}
-
-
-/*----------------------------------------------------------------
-|
-|   Move_OmegaPos: Change the nonysnonymous/synonymous rate ratio
-|      for positively selected sites
-|
-----------------------------------------------------------------*/
-int Move_OmegaPos (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
-{
-    int         i, isValidO, omegaUni, omegaExp1, omegaExp2;
-    MrBFlt      oldO, newO, window, minO=0.0, maxO=0.0, ran, *value, x, y;
-    ModelParams *mp;
-
-    /* get size of window, centered on current omega value */
-    window = mvp[0];
-
-    /* get model params */
-    mp = &modelParams[param->relParts[0]];
-
-    /* get old value of omega */
-    value = GetParamVals(param, chain, state[chain]);
-    newO = oldO = value[2];
-    
-    /* determine prior for omega */
-    omegaUni = omegaExp1 = omegaExp2 = NO;
-    if (param->paramId == OMEGA_BUD || param->paramId == OMEGA_BUF || param->paramId == OMEGA_FUD || param->paramId == OMEGA_FUF)
-        omegaUni = YES;
-    else if (param->paramId == OMEGA_BED || param->paramId == OMEGA_BEF || param->paramId == OMEGA_FED || param->paramId == OMEGA_FEF)
-        omegaExp1 = YES;
-    else if (param->paramId == OMEGA_ED || param->paramId == OMEGA_EF)
-        omegaExp2 = YES;
-        
-    /* get minimum and maximum values for omega */
-    if (omegaUni == YES)
-        {
-        minO = mp->ny98omega3Uni[0];
-        if (minO < value[1])
-            minO = value[1];
-        maxO = mp->ny98omega3Uni[1];
-        if (maxO > KAPPA_MAX)
-            maxO = KAPPA_MAX;
-        }
-    else if (omegaExp1 == YES || omegaExp2 == YES)
-        {
-        minO = value[1];
-        maxO = KAPPA_MAX;
-        }
-
-    /* change value for omega */
-    ran = RandomNumber(seed);
-    if (maxO-minO < window)
-        {
-        window = maxO-minO;
-        }
-    newO = oldO + window * (ran - 0.5);
-    
-    /* check that new value is valid */
-    isValidO = NO;
-    do
-        {
-        if (newO < minO)
-            newO = 2* minO - newO;
-        else if (newO > maxO)
-            newO = 2 * maxO - newO;
-        else
-            isValidO = YES;
-        } while (isValidO == NO);
-
-    /* get proposal ratio */
-    *lnProposalRatio = 0.0;
-    
-    /* copy new omega value back */
-    value[2] = newO;
-
-    /* get prior ratio (part 2) */
-    if (omegaUni == YES)
-        {
-        *lnPriorRatio = 0.0;
-        }
-    else if (omegaExp1 == YES)
-        {
-        *lnPriorRatio = mp->ny98omega3Exp * (oldO - newO);
-        }
-    else if (omegaExp2 == YES)
-        {
-        x = LogOmegaPrior (value[0], value[1], newO);
-        y = LogOmegaPrior (value[0], value[1], oldO);
-        *lnPriorRatio = x - y;
-        }
-
-    /* Set update flags for all partitions that share this omega. Note that the conditional
-       likelihood update flags have been set before we even call this function. */
-    for (i=0; i<param->nRelParts; i++)
-        TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
-
-    /* Set update flags for cijks for all affected partitions. */
-    for (i=0; i<param->nRelParts; i++)
-        modelSettings[param->relParts[i]].upDateCijk = YES;
-
-    return (NO_ERROR);
-}
-
-
-/*----------------------------------------------------------------
-|
-|   Move_OmegaPur: Change the nonysnonymous/synonymous rate ratio
-|      for purifying selection sites
-|
-----------------------------------------------------------------*/
-int Move_OmegaPur (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
-{
-    int         i, isOPriorExp, isValidO;
-    MrBFlt      oldO, newO, window, minO, maxO, ran, *value, x, y;
-
-    /* get size of window, centered on current omega value */
-    window = mvp[0];
-
-    /* get old value of omega */
-    value = GetParamVals(param, chain, state[chain]);
-    newO = oldO = value[0];
-    
-    /* get minimum and maximum values for omega */
-    minO = 0.0;
-    maxO = value[1];
-    
-    /* get prior for omega */
-    if (param->paramId == OMEGA_BUD || param->paramId == OMEGA_BUF || param->paramId == OMEGA_BED || 
-        param->paramId == OMEGA_BEF || param->paramId == OMEGA_BFD || param->paramId == OMEGA_BFF) 
-        isOPriorExp = NO;
-    else
-        isOPriorExp = YES;
-
-    /* change value for omega */
-    ran = RandomNumber(seed);
-    if (maxO-minO < window)
-        {
-        window = maxO-minO;
-        }
-    newO = oldO + window * (ran - 0.5);
-    
-    /* check that new value is valid */
-    isValidO = NO;
-    do
-        {
-        if (newO < minO)
-            newO = 2* minO - newO;
-        else if (newO > maxO)
-            newO = 2 * maxO - newO;
-        else
-            isValidO = YES;
-        } while (isValidO == NO);
-
-    /* get proposal ratio */
-    *lnProposalRatio = 0.0;
-    
-    /* copy new omega value back */
-    value[0] = newO;
-
-    /* get prior ratio (part 2) */
-    if (isOPriorExp == NO)
-        {
-        *lnPriorRatio = 0.0;
-        }
-    else
-        {
-        x = LogOmegaPrior (newO, value[1], value[2]);
-        y = LogOmegaPrior (oldO, value[1], value[2]);
-        *lnPriorRatio = x - y;
-        }
-
-    /* Set update flags for all partitions that share this omega. Note that the conditional
-       likelihood update flags have been set before we even call this function. */
-    for (i=0; i<param->nRelParts; i++)
-        TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
-
-    /* Set update flags for cijks for all affected partitions. */
-    for (i=0; i<param->nRelParts; i++)
-        modelSettings[param->relParts[i]].upDateCijk = YES;
-
-    return (NO_ERROR);
-}
-
-
-/*----------------------------------------------------------------
-|
-|   Move_ParsEraser1: This proposal mechanism changes the topology and
-|      branch lengths of an unrooted tree. A randomly chosen region of
-|      the tree is erased. Parsimony is used to guide the selection of
-|      a new topology for the erased part of the tree. The parsimony
-|      branch lengths are used to guide the proposal of new branch
-|      lengths. This variant (1) uses exhaustive enumeration.
-|
-|      Programmed by FR 2004-10-23--
-|
-----------------------------------------------------------------*/
-int Move_ParsEraser1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
-{
-    int         i, j, isVPriorExp, nSubTerminals, nEmbeddedTrees;
-    MrBFlt      alphaPi, warp, minV, maxV, minP, maxP, brlensExp=0.0, newM, oldM, maxLen,
-                *brlensCur, *brlensNew, *parslensCur, *parslensNew,
-                curLength, newLength, lnJacobian, lnRandomRatio, alpha[2], prob[2],
-                minLenCur, minLenNew, f;
-    TreeNode    *p=NULL;
-    Tree        *t, *subtree, *subtree1, memTree[2];
-    ModelParams *mp;
-    ModelInfo   *m;
-    TreeInfo    tInfo;
-
-    /* set pointers to NULL */
-    subtree = subtree1 = NULL;
-    brlensCur = NULL;
-    for (i=0; i<2; i++)
-        {
-        memTree[i].allDownPass = NULL;
-        memTree[i].intDownPass = NULL;
-        memTree[i].nodes = NULL;
-        }
-    tInfo.leaf = NULL;
-
-    /* Set alpha Pi for Dirichlet p generator */
-    alphaPi = mvp[0];
-    alphaPi = 0.05;
-    
-    /* Set the parsimony warp factor */
-    warp = mvp[1];
-    warp = 0.2;
-    
-    /* Set the number of terminals (nSubTerminals, column 3) in erased tree */
-    /* Erased Nodes => Leaves => Terminals => Embedded trees => Embedded histories => New trees
-                  2 => 3      => 4         => 2              => 2 = 2!             => 3 = 1*3
-                  3 => 4      => 5         => 5              => 6 = 3!             => 15 = 1*3*5
-                  4 => 5      => 6         => 14             => 24 = 4!            => 105 = 1*3*5*7
-                  5 => 6      => 7         => 42             => 120 = 5!           => 945 = 1*3*5*7*9
-                  etc               */  
-    nSubTerminals = (int) (RandomNumber(seed) * 4) + 4;
-    nSubTerminals = 7;
-
-    /* initialize log prior and log proposal probabilities */
-    *lnPriorRatio = *lnProposalRatio = 0.0;
-    
-    /* get tree */
-    t = GetTree (param, chain, state[chain]);
-
-    /* get model params */
-    mp = &modelParams[param->relParts[0]];
-    
-    /* max and min brlen */
-    if (param->subParams[0]->paramId == BRLENS_UNI)
-        {
-        minV = mp->brlensUni[0] > BRLENS_MIN ? mp->brlensUni[0] : BRLENS_MIN;
-        maxV = mp->brlensUni[1];
-        isVPriorExp = NO;
-        }
-    else
-        {
-        minV = BRLENS_MIN;
-        maxV = BRLENS_MAX;
-        brlensExp = mp->brlensExp;
-        isVPriorExp = YES;
-        }
-    minP = 3.0 * ((1.0 / 4.0) - ((1.0 / 4.0) * exp (-4.0 * minV / 3.0)));
-    maxP = 3.0 * ((1.0 / 4.0) - ((1.0 / 4.0) * exp (-4.0 * maxV / 3.0)));
-
-    /* allocate some memory for this move */
-    brlensCur = (MrBFlt *) SafeMalloc (8 * nSubTerminals * sizeof (MrBFlt));
-    if (!brlensCur)
-        {
-        MrBayesPrint ("%s   ERROR: Could not allocate brlensCur\n", spacer);
-        goto errorExit;
-        }
-    brlensNew = brlensCur + 2*nSubTerminals;
-    parslensCur = brlensCur + 4 * nSubTerminals;
-    parslensNew = brlensCur + 6 * nSubTerminals;
-
-    subtree = &memTree[0];
-    subtree->nNodes = 2 * nSubTerminals - 2;
-    subtree->nIntNodes = nSubTerminals - 2;
-    subtree->nodes = (TreeNode *) SafeCalloc (subtree->nNodes, sizeof (TreeNode));
-    subtree->allDownPass = (TreeNode **) SafeCalloc (subtree->nNodes, sizeof (TreeNode *));
-    subtree->intDownPass = (TreeNode **) SafeCalloc (subtree->nIntNodes, sizeof (TreeNode *));
-    if (!subtree->nodes || !subtree->intDownPass || !subtree->allDownPass)
-        {
-        MrBayesPrint ("%s   ERROR: Could not allocate subtree\n", spacer);
-        goto errorExit;
-        }
-
-    subtree1 = &memTree[1];
-    subtree1->nNodes = 2 * nSubTerminals - 2;
-    subtree1->nIntNodes = nSubTerminals - 2;
-    subtree1->nodes = (TreeNode *) SafeCalloc (subtree1->nNodes, sizeof (TreeNode));
-    subtree1->allDownPass = (TreeNode **) SafeCalloc (subtree1->nNodes, sizeof (TreeNode *));
-    subtree1->intDownPass = (TreeNode **) SafeCalloc (subtree1->nIntNodes, sizeof (TreeNode *));
-    if (!subtree1->nodes || !subtree1->intDownPass || !subtree1->allDownPass)
-        {
-        MrBayesPrint ("%s   ERROR: Could not allocate subtree1\n", spacer);
-        goto errorExit;
-        }
-
-    tInfo.leaf = (TreeNode **) SafeCalloc (t->nNodes, sizeof(TreeNode *));
-    if (!tInfo.leaf)
-        {
-        MrBayesPrint ("%s   ERROR: Could not allocate tInfo.leaf\n", spacer);
-        goto errorExit;
-        }
-    tInfo.vertex = tInfo.leaf + t->nNodes - t->nIntNodes;
-
-    /* Select a random embedded subtree with nSubTerminals terminals */
-    if (GetRandomEmbeddedSubtree (t, nSubTerminals, seed, &nEmbeddedTrees) == ERROR)
-        {
-        MrBayesPrint ("%s   ERROR: Could not get subtree\n", spacer);
-        goto errorExit;
-        }
-
-    /* Set update flags (We'd better do it before the marked nodes disappear) */
-    for (i=0; i<t->nIntNodes; i++)
-        {
-        p = t->intDownPass[i];
-        if (p->marked == YES)
-            {
-            p->upDateCl = YES; 
-            p->upDateTi = YES;
-            }
-        else if (p->left->upDateCl == YES || p->right->upDateCl == YES)
-                p->upDateCl = YES; 
-        }
-
-    /* Fill in subtrees */
-    CopyTreeToSubtree (t, subtree); 
-    CopyTreeToSubtree (t, subtree1);
-
-    /* Calculate downstates and upstate of root node of subtree */
-    GetParsDP (t, t->root->left, chain);
-    for (i=0; i<t->nIntNodes; i++)
-        {
-        p = t->intDownPass[i];
-        if (p->marked == YES && p->anc->marked == NO)
-            break;
-        }
-    GetParsimonySubtreeRootstate (t, p->anc, chain);
-
-    /* Get parsimony length of current tree */
-    curLength = GetParsimonyLength (subtree, chain);
-    
-    /* Get the Markov and parsimony branch lengths of the current subtree */
-    GetParsimonyBrlens (subtree, chain, parslensCur);
-    for (i=0; i<subtree->nNodes-1; i++)
-        brlensCur[i] = subtree->allDownPass[i]->length;
-
-    /* Calculate parsimony score of all trees relative to shortest tree (1.0) */
-    tInfo.totalScore = 0.0;
-    tInfo.stopScore = -1.0;
-    tInfo.minScore = curLength;
-    tInfo.warp = warp;
-    ExhaustiveParsimonySearch (subtree, chain, &tInfo);
-        
-    /* Choose one of these trees randomly based on its score */
-    tInfo.stopScore = RandomNumber(seed) * tInfo.totalScore;
-    tInfo.totalScore = 0.0;
-    ExhaustiveParsimonySearch (subtree1, chain, &tInfo);
-    /* ShowNodes (subtree1->root, 0 , NO); */
-    /* getchar(); */
-
-    /* Get length of that tree */
-
-    newLength = GetParsimonyLength (subtree1, chain);
-
-    /* Get the parsimony branch lengths of the new subtree */
-    GetParsimonyBrlens (subtree1, chain, parslensNew);
-
-    /* Find the maximum length of a branch */
-    maxLen = 0.0;
-    for (i=0; i<t->nRelParts; i++)
-        {
-        j = t->relParts[i];
-        m = &modelSettings[j];
-        maxLen += m->numUncompressedChars;
-        }
-    
-    /* Find the Markov branch lengths of the new subtree */
-    /* Calculate Jacobian and prob ratio for the Dirichlet random number generator */
-    lnJacobian = lnRandomRatio = 0.0;
-    minLenCur = minLenNew = 0.0;
-    for (i=0; i<subtree1->nNodes-1; i++)
-        {
-        minLenCur += parslensCur[i];
-        minLenNew += parslensNew[i];
-        }
-    for (i=0; i<subtree1->nNodes-1; i++)
-        {
-        p = subtree1->allDownPass[i];
-        f = newLength / minLenNew;
-        alpha[0] = parslensNew[i] * f * alphaPi + 1.0;
-        alpha[1] = (maxLen - parslensNew[i] * f) * alphaPi + 1.0;
-        DirichletRandomVariable (alpha, prob, 2, seed);
-        if (prob[0] >= maxP || prob[0] <= minP)
-            {
-            abortMove = YES;
-            return NO_ERROR;
-            }
-
-        p->length = (-3.0 / 4.0) * log (1.0 - 4.0 * prob[0] / 3.0);
-        lnJacobian += (-4.0 * brlensCur[i] / 3.0) - log (1.0 - 4.0 * prob[0] / 3.0);
-        lnRandomRatio -= log (pow (prob[0], alpha[0] - 1.0) * pow (prob[1], alpha[1] - 1.0));
-        f = curLength / minLenNew;
-        alpha[0] = parslensCur[i] * f * alphaPi + 1.0;
-        alpha[1] = (maxLen - parslensCur[i] * f) * alphaPi + 1.0;
-        prob[0] = 3.0 * ((1.0 / 4.0) - ((1.0 / 4.0) * exp (-4.0 * brlensCur[i] / 3.0)));
-        prob[1] = 1.0 - prob[0];
-        lnRandomRatio += log (pow (prob[0], alpha[0] - 1.0) * pow (prob[1], alpha[1] - 1.0));
-        }
-
-    /* Store the new Markov branch lengths */
-    for (i=0; i<subtree1->nNodes-1; i++)
-        brlensNew[i] = subtree1->allDownPass[i]->length;
-
-    /* Calculate the proposal ratio */
-    (*lnProposalRatio) = lnJacobian + lnRandomRatio + log (warp/3.0) * (curLength - newLength) + log (1.0-warp) * (newLength - curLength);
-
-    /* Calculate the prior ratio */
-    if (isVPriorExp == YES)
-        {
-        newM = oldM = 0.0;
-        for (i=0; i<subtree->nNodes-1; i++)
-            {
-            oldM += brlensCur[i];
-            newM += brlensNew[i];
-            }
-        (*lnPriorRatio) += brlensExp * (oldM - newM);
-        }
-
-    /* Copy subtree into tree */
-    CopySubtreeToTree (subtree1, t);
-    /* ShowNodes (subtree1->root, 0, NO); */
-    /* ShowNodes (t->root, 0, NO); */
-
-    /* Update node sequences */
-    GetDownPass (t);
-    
-    /* correct for difference in number of embedded subtrees */
-    if (GetRandomEmbeddedSubtree (t, nSubTerminals, seed, &i) == ERROR)
-        {
-        MrBayesPrint ("%s   Could not count number of subtrees in Move_ParsEraser1\n", spacer);
-        goto errorExit;
-        }
-    if (i != nEmbeddedTrees)
-        (*lnProposalRatio) += log ((MrBFlt) nEmbeddedTrees / (MrBFlt) i);
-
-    /* Free memory allocated for this move */
-    free (subtree->allDownPass);
-    free (subtree->intDownPass);
-    free (subtree->nodes);
-    free (subtree1->allDownPass);
-    free (subtree1->intDownPass);
-    free (subtree1->nodes);
-    free (brlensCur);
-    free (tInfo.leaf);
-
-    return (NO_ERROR);
-
-errorExit:
-
-    free (subtree->allDownPass);
-    free (subtree->intDownPass);
-    free (subtree->nodes);
-    free (subtree1->allDownPass);
-    free (subtree1->intDownPass);
-    free (subtree1->nodes);
-    free (brlensCur);
-    free (tInfo.leaf);
-
-    return (ERROR);
-}
-
-
-int Move_ParsSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
-{
-    /* Change branch lengths and topology (potentially) using unbalanced (rooted asymmetrically) SPR-type move
-       biased according to parsimony scores. */
-
-    int         i, j, n, division, topologyHasChanged, isVPriorExp;
-    BitsLong    *pA, *pV, *pP, y[2];
-    MrBFlt      x, minV, maxV, brlensExp=0.0, minLength=0.0, length=0.0,
-                cumulativeProb, warpFactor, ran, tuning, increaseProb, decreaseProb,
-                divFactor, nStates, rateMult, v_typical, sum1, sum2, tempsum, tempc, tempy;
-    CLFlt       *nSitesOfPat, *nSites, *globalNSitesOfPat;
-    TreeNode    *p, *q, *a, *b, *u, *v, *c=NULL, *d;
-    Tree        *t;
-    ModelParams *mp;
-    ModelInfo   *m = NULL;
-
-    warpFactor = mvp[0];                  /* tuning parameter determining how heavily to weight according to parsimony scores */
-    increaseProb = decreaseProb = mvp[1]; /* reweighting probabilities */
-    v_typical = mvp[2];                   /* typical branch length for conversion of parsimony score to log prob ratio */
-    tuning = mvp[3];                      /* multiplier tuning parameter */
-
-    (*lnProposalRatio) = (*lnPriorRatio) = 0.0;
-
-    /* get model params and model info */
-    mp = &modelParams[param->relParts[0]];
-    m = &modelSettings[param->relParts[0]];
-    
-    /* get tree */
-    t = GetTree (param, chain, state[chain]);
-
-    /* max and min brlen */
-    if (param->subParams[0]->paramId == BRLENS_UNI)
-        {
-        minV = mp->brlensUni[0] > BRLENS_MIN ? mp->brlensUni[0] : BRLENS_MIN;
-        maxV = mp->brlensUni[1];
-        isVPriorExp = NO;
-        }
-    else if (param->subParams[0]->paramId == BRLENS_GamDir)
-        {
-        minV = BRLENS_MIN;
-        maxV = BRLENS_MAX;
-        isVPriorExp = 2;
-        }
-    else if (param->subParams[0]->paramId == BRLENS_iGmDir)
-        {
-        minV = BRLENS_MIN;
-        maxV = BRLENS_MAX;
-        isVPriorExp = 3;
-        }
-    else if (param->subParams[0]->paramId == BRLENS_twoExp)
-        {
-        minV = BRLENS_MIN;
-        maxV = BRLENS_MAX;
-        isVPriorExp = 4;
-        }
-    else
-        {
-        minV = BRLENS_MIN;
-        maxV = BRLENS_MAX;
-        brlensExp = mp->brlensExp;
-        isVPriorExp = YES;
-        }
-
-    /* Dirichlet or twoExp prior */
-    if (isVPriorExp > 1)
-        (*lnPriorRatio) = -LogDirPrior(t, mp, isVPriorExp);
-
-#   if defined (DEBUG_ParsSPR)
-    // WriteTopologyToFile (stdout, t->root->left, t->isRooted);  fprintf (stdout, ";\t");
-    printf ("Before:\n");
-    ShowNodes (t->root, 2, YES);
-    getchar();
-#   endif
-    
-    /* set topologyHasChanged to NO */
-    topologyHasChanged = NO;
-    
-    /* reset node variables that will be used */
-    for (i=0; i<t->nNodes; i++)
-        {
-        p = t->allDownPass[i];
-        p->marked = NO;
-        p->d = 0;
-        }
-
-    /* pick a random branch */
-    p = t->allDownPass[(int)(RandomNumber(seed) * (t->nNodes -2))];
-    q = p->anc->right;
-    if (q == p)
-        q = p->anc->left;
-    if ((p->anc->anc->anc == NULL || p->anc->isLocked == YES) && (q->left == NULL || q->isLocked == YES))
-        {
-        abortMove = YES;
-        return (NO_ERROR);
-        }
-        
-    /* set up pointers for nodes around the picked branch */
-    v = p;
-    u = p->anc;
-    if (u->left == v)
-        a = u->right;
-    else
-        a = u->left;
-    b = u->anc;
-
-    /* clip tree */
-    a->anc = b;
-    if (b->left == u)
-        b->left = a;
-    else
-        b->right = a;
-
-    /* get final parsimony states for the root part */
-    GetParsDP (t, t->root->left, chain);
-    GetParsFP (t, t->root->left, chain);
-
-    /* get downpass parsimony states for the crown part */
-    GetParsDP (t, v, chain);
-
-    /* mark all nodes in the root part of the tree, taking constraints into account */
-    /* first mark a */
-    a->marked = YES;
-    /* then move down towards root */
-    if (u->isLocked == NO)
-        {
-        p = a->anc;
-        while (p->anc != NULL)
-            {
-            p->marked = YES;
-            if (p->isLocked == YES)
-                break;
-            p = p->anc;
-            }
-        }
-
-    /* finally move up */
-    for (i=t->nNodes-2; i>=0; i--)
-        {
-        p = t->allDownPass[i];
-        if (p->marked == NO && p->anc->marked == YES && p->anc->isLocked == NO && p != u)
-            p->marked = YES;
-        }
-
-    /* find number of site patterns and modify randomly */
-    globalNSitesOfPat = numSitesOfPat + (chainId[chain] % chainParams.numChains) * numCompressedChars + m->compCharStart;
-    nSitesOfPat = (CLFlt *) SafeCalloc (numCompressedChars, sizeof(CLFlt));
-    if (!nSitesOfPat)
-        {
-        MrBayesPrint ("%s   Problem allocating nSitesOfPat in Move_ParsSPR\n", spacer);
-        return (ERROR);
-        }
-    for (i=0; i<numCompressedChars; i++)
-        {
-        nSitesOfPat[i] = globalNSitesOfPat[i];
-        for (j=0; j<globalNSitesOfPat[i]; j++)
-            {
-            ran = RandomNumber(seed);
-            if (ran < decreaseProb)
-                nSitesOfPat[i]--;
-            else if (ran > 1.0 - increaseProb)
-                nSitesOfPat[i]++;
-            }
-        }
-
-    /* cycle through the possibilities and record the parsimony length */
-    for (i=0; i<t->nNodes; i++)
-        {
-        p = t->allDownPass[i];
-        if (p->marked == NO)
-            continue;
-        /* find the parsimony length */
-        p->d = 0.0;
-        for (n=0; n<t->nRelParts; n++)
-            {
-            division = t->relParts[n];
-            
-            /* Find model settings */
-            m = &modelSettings[division];
-
-            /* find nStates and ratemult */
-            nStates = m->numModelStates;
-            if (m->dataType == STANDARD)
-                nStates = 2;
-            rateMult = GetRate(division, chain);
-
-            /* find nSitesOfPat */
-            nSites = nSitesOfPat + m->compCharStart;
-
-            /* get division warp factor */
-            divFactor = - warpFactor * log((1.0/nStates) - exp(-nStates/(nStates-1)*v_typical*rateMult)/nStates);
-
-            /* find downpass parsimony sets for the node and its environment */
-            pP   = m->parsSets[p->index     ];
-            pA   = m->parsSets[p->anc->index];
-            pV   = m->parsSets[v->index     ];
-        
-            length = 0.0;
-            if (m->nParsIntsPerSite == 1)
-                {
-                for (j=0; j<m->numChars; j++)
-                    {
-                    y[0] = (pP[j] | pA[j]) & pV[j];
-                    if (y[0] == 0)
-                        length += nSites[j];
-                    }
-                }
-            else /* if (m->nParsIntsPerSite == 2) */
-                {
-                for (j=0; j<2*m->numChars; j+=2)
-                    {
-                    y[0] = (pP[j] | pA[j]) & pV[j];
-                    y[1] = (pP[j+1] | pA[j+1]) & pV[j+1];
-                    if ((y[0] | y[1]) == 0)
-                        length += nSites[j/2];
-                    }
-                }
-            p->d += divFactor * length;
-            }
-        }
-
-    /* find the min length and the sum for the forward move */    
-    minLength = -1.0;
-    for (i=0; i<t->nNodes; i++)
-        {
-        p = t->allDownPass[i];
-        if (p->marked == NO || p == a)
-            continue;
-        if (minLength < 0.0 || p->d < minLength)
-            minLength = p->d;
-        }
-    sum1 = 0.0; tempc = 0.0;
-    for (i=0; i<t->nNodes; i++)
-        {
-        p = t->allDownPass[i];
-        if (p->marked == YES && p != a)
-            {
-            /* Kahan summation to reduce numerical error */
-            tempy = exp (minLength - p->d) - tempc;
-            tempsum = sum1 + tempy;
-            tempc = (tempsum - sum1) - tempy;
-            sum1 = tempsum;
-            }
-        }
-    
-    /* generate a random uniform */
-    ran = RandomNumber(seed) * sum1;
-
-    /* select the appropriate reattachment point */
-    cumulativeProb = 0.0; tempc = 0.0;
-    for (i=0; i<t->nNodes; i++)
-        {
-        p = t->allDownPass[i];
-        if (p->marked == YES && p != a)
-            {
-            c = p;
-            /* Kahan summation to reduce numerical error */
-            tempy = exp (minLength - p->d) - tempc;
-            tempsum = cumulativeProb + tempy;
-            tempc = (tempsum - cumulativeProb) - tempy;
-            cumulativeProb = tempsum;
-            if (cumulativeProb > ran)
-                break;
-            }
-        }
-
-    /* calculate the proposal ratio */
-    (*lnProposalRatio) = c->d - minLength + log(sum1);
-
-    /* find the min length and the sum for the backward move */
-    minLength = -1.0;
-    for (i=0; i<t->nNodes; i++)
-        {
-        p = t->allDownPass[i];
-        if (p->marked == NO || p == c)
-            continue;
-        if (minLength < 0.0 || p->d < minLength)
-            minLength = p->d;
-        }
-    sum2 = 0.0; tempc = 0.0;
-    for (i=0; i<t->nNodes; i++)
-        {
-        p = t->allDownPass[i];
-        if (p->marked == YES && p != c)
-            {
-            /* Kahan summation to reduce numerical error */
-            tempy = exp (minLength - p->d) - tempc;
-            tempsum = sum2 + tempy;
-            tempc = (tempsum - sum2) - tempy;
-            sum2 = tempsum;
-            }
-        }
-
-    /* calculate the proposal ratio */
-    (*lnProposalRatio) += minLength - a->d - log(sum2);
-
-    /* reattach */
-    d = c->anc;
-    c->anc = u;
-    if (u->left == v)
-        u->right = c;
-    else
-        u->left = c;
-    if (d->left == c)
-        d->left = u;
-    else
-        d->right = u;
-    u->anc = d;
-
-    /* c cannot be a, as a is skiped in the selection for reattachment point */
-    assert (c != a);
-    /* transfer lock if necessary */
-    /* if u is locked, then we have moved upwards and need to leave the u lock behind */
-    if (u->isLocked == YES)
-        {
-        u->isLocked = NO;
-        a->isLocked = YES;
-        a->lockID = u->lockID;
-        u->lockID = -1;
-        }
-    /* if c is on root path and locked, we need to transfer lock to u */
-    p = b;
-    while (p != NULL)
-        {
-        if (p == c)
-            break;
-        p = p->anc;
-        }
-    if (p == c && c->isLocked == YES)
-        {
-        u->isLocked = YES;
-        u->lockID = c->lockID;
-        c->isLocked = NO;
-        c->lockID = -1;
-        }
-
-    /* reassign branch lengths */
-    p = c;
-    while (p->anc->anc != NULL)
-        {
-        if (p == a)
-            break;
-        p = p->anc;
-        }
-    if (p == a)
-        {
-        /* c is descendant to a so move a->length and not u->length */
-        x = u->length;
-        u->length = a->length;
-        a->length = x;
-        }
-    p = a;
-    while (p->anc->anc != NULL)
-        {
-        if (p == c)
-            break;
-        p = p->anc;
-        }
-    if (p == c)
-        {
-        /* c is ancestor to a so insert above instead of below */
-        x = c->length;
-        c->length = u->length;
-        u->length = x;
-        }
-
-    topologyHasChanged = YES;
-
-    /* hit c length with multiplier (a and u dealt with below) */
-    x = c->length * exp(tuning * (RandomNumber(seed) - 0.5));
-    while (x < minV || x > maxV)
-        {
-        if (x < minV)
-            x = minV * minV / x;
-        else if (x > maxV)
-            x = maxV * maxV / x;
-        }
-    /* calculate proposal and prior ratio based on length modification */
-    (*lnProposalRatio) += log (x / c->length);
-    if (isVPriorExp == YES)
-        (*lnPriorRatio) += brlensExp * (c->length - x);
-    c->length = x;
-    
-    /* hit a length with multiplier */
-    x = a->length * exp(tuning * (RandomNumber(seed) - 0.5));
-    while (x < minV || x > maxV)
-        {
-        if (x < minV)
-            x = minV * minV / x;
-        else if (x > maxV)
-            x = maxV * maxV / x;
-        }
-    /* calculate proposal and prior ratio based on length modification */
-    (*lnProposalRatio) += log (x / a->length);
-    if (isVPriorExp == YES)
-        (*lnPriorRatio) += brlensExp * (a->length - x);
-    a->length = x;
-
-    /* hit u length with multiplier */
-    x = u->length * exp(tuning * (RandomNumber(seed) - 0.5));
-    while (x < minV || x > maxV)
-        {
-        if (x < minV)
-            x = minV * minV / x;
-        else if (x > maxV)
-            x = maxV * maxV / x;
-        }
-    /* calculate proposal and prior ratio based on length modification */
-    (*lnProposalRatio) += log (x / u->length);
-    if (isVPriorExp == YES)
-        (*lnPriorRatio) += brlensExp * (u->length - x);
-    u->length = x;
-
-    /* set tiprobs update flags */
-    a->upDateTi = YES;
-    u->upDateTi = YES;
-    c->upDateTi = YES;  /* could be same as a but that does not matter */
-
-    /* set flags for update of cond likes from u and down to root */
-    p = u;
-    while (p->anc != NULL)
-        {
-        p->upDateCl = YES;
-        p = p->anc;
-        }
-
-    /* set flags for update of cond likes from b and down to root */
-    p = b;
-    while (p->anc != NULL && p->upDateCl == NO)
-        {
-        p->upDateCl = YES; 
-        p = p->anc;
-        }
-
-    /* get down pass sequence if tree topology has changed */
-    if (topologyHasChanged == YES)
-        {
-        GetDownPass (t);
-        }
-
-    /* Dirichlet or twoExp prior */
-    if (isVPriorExp > 1)
-        (*lnPriorRatio) += LogDirPrior(t, mp, isVPriorExp);
-    
-#   if defined (DEBUG_ParsSPR)
-    // WriteTopologyToFile (stdout, t->root->left, t->isRooted);
-    // fprintf (stdout, ";\t");  fprintf (stdout, "%lf\n", *lnProposalRatio);
-    printf ("After:\n");
-    ShowNodes (t->root, 2, YES);
-    getchar();
-    printf ("Proposal ratio: %f\n",(*lnProposalRatio));
-    printf ("v: %d  u: %d  a: %d  b: %d\n",v->index, u->index, a->index, b->index);
-    printf ("Has topology changed? %d\n",topologyHasChanged);
-    getchar();
-#   endif
-
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-    gNodeMoves = nRootNodes;
-#   endif
-    
-    free (nSitesOfPat);
-
-    return (NO_ERROR);
-}
-
-
-int Move_ParsSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
-{
-    /* Change topology and map branch lengths using SPR-type move biased according to parsimony scores,
-       controlled by a window defined by a certain node distance radius. */
-    
-    int         i, j, k, n, division, topologyHasChanged, moveInRoot, nNeighbor, nRoot, nCrown, iA, jC, isVPriorExp;
-    BitsLong    *pA, *pB, *pC, *pD, y[2];
-    MrBFlt      x, minV, maxV, brlensExp=0.0, minLength=0.0, length=0.0, *parLength=NULL, prob, ran, tuning, warpFactor,
-                increaseProb, decreaseProb, v_typical, divFactor, nStates, rateMult, sum1, sum2, tempsum, tempc, tempy;
-    CLFlt       *nSites, *nSitesOfPat=NULL, *globalNSitesOfPat;
-    TreeNode    *p, *q, *r, *a, *b, *u, *v, *c, *d, *newB, *newA, *newC, **pRoot=NULL, **pCrown=NULL, *old=NULL, *tmp=NULL;
-    Tree        *t;
-    ModelParams *mp;
-    ModelInfo   *m=NULL;
-    
-    warpFactor = mvp[0];                  /* tuning parameter determining how heavily to weight according to parsimony scores */
-    increaseProb = decreaseProb = mvp[1]; /* reweighting probabilities */
-    v_typical = mvp[2];                   /* typical branch length for conversion of parsimony score to log prob ratio */
-    tuning = mvp[3];                      /* multiplier tuning parameter */
-    nNeighbor = (int)mvp[4];              /* distance to move picked branch in root and crown part */
-    
-    (*lnProposalRatio) = (*lnPriorRatio) = 0.0;
-    
-    /* get model params and model info */
-    mp = &modelParams[param->relParts[0]];
-    m = &modelSettings[param->relParts[0]];
-    
-    /* get tree */
-    t = GetTree (param, chain, state[chain]);
-    
-    /* max and min brlen */
-    if (param->subParams[0]->paramId == BRLENS_UNI)
-        {
-        minV = mp->brlensUni[0] > BRLENS_MIN ? mp->brlensUni[0] : BRLENS_MIN;
-        maxV = mp->brlensUni[1];
-        isVPriorExp = NO;
-        }
-    else if (param->subParams[0]->paramId == BRLENS_GamDir)
-        {
-        minV = BRLENS_MIN;
-        maxV = BRLENS_MAX;
-        isVPriorExp = 2;
-        }
-    else if (param->subParams[0]->paramId == BRLENS_iGmDir)
-        {
-        minV = BRLENS_MIN;
-        maxV = BRLENS_MAX;
-        isVPriorExp = 3;
-        }
-    else if (param->subParams[0]->paramId == BRLENS_twoExp)
-        {
-        minV = BRLENS_MIN;
-        maxV = BRLENS_MAX;
-        isVPriorExp = 4;
-        }
-    else
-        {
-        minV = BRLENS_MIN;
-        maxV = BRLENS_MAX;
-        brlensExp = mp->brlensExp;
-        isVPriorExp = YES;
-        }
-
-    /* Dirichlet or twoExp prior */
-    if (isVPriorExp > 1)
-        (*lnPriorRatio) = -LogDirPrior(t, mp, isVPriorExp);
-    
-    /* set topologyHasChanged to NO */
-    topologyHasChanged = NO;
-    
-    /* pick an internal branch */
-    do  {
-        p = t->intDownPass[(int)(RandomNumber(seed) * (t->nIntNodes - 1))];
-        q = p->anc->left;  if (q == p) q = p->anc->right;
-        i = j = 0;
-        if (q->isLocked == YES || q->left == NULL)
-            i++;
-        if (p->anc->isLocked == YES || p->anc->anc->anc == NULL)
-            i++;
-        if (p->left->isLocked == YES || p->left->left == NULL)
-            j++;
-        if (p->right->isLocked == YES || p->right->left == NULL)
-            j++;
-        }
-    while (i == 2 && j == 2);
-    
-    /* determine moving direction */
-    if (j == 2)
-        moveInRoot = YES;
-    else if (i == 2)
-        moveInRoot = NO;
-    else if (RandomNumber(seed) < 0.5)
-        moveInRoot = YES;
-    else
-        moveInRoot = NO;
-
-    /* set up pointers for nodes around the picked branch */
-    v = p;            u = p->anc;
-    c = p->left;      d = p->right;
-    if (u->left == v) a = u->right;
-    else              a = u->left;
-    b = u->anc;
-    /* clip root part of tree */
-    a->anc = b;
-    if (b->left == u) b->left = a;
-    else              b->right = a;
-    /* clip crown part of tree */
-    c->anc = d;
-    d->anc = c;
-    /* should never change u, v, a, b, c, d pointers */
-    
-    /* reset node variables that will be used */
-    for (i=0; i<t->nNodes; i++)
-        {
-        p = t->allDownPass[i];
-        p->x = 0;
-        p->marked = NO;
-        }
-
-    /* mark nodes nNeighbor away in root (negative) or crown (positive) respecting constraints */
-    nRoot = nCrown = 0;
-    /* mark the root part if moveInRoot is YES */
-    if (u->isLocked == NO && moveInRoot == YES)
-        {
-        p = a; q = b; n = 0;
-        while (q->anc != NULL)
-            {
-            q->marked = YES;
-            q->x = n;    // temporary, for MarkDistance below
-            if (q->left == p)
-                MarkDistance(q->right, YES, nNeighbor, &nRoot);
-            else
-                MarkDistance(q->left,  YES, nNeighbor, &nRoot);
-            q->x = --n;  // final
-            nRoot++;
-            if (q->isLocked == YES || abs(q->x) >= nNeighbor)
-                break;
-            p = q; q = q->anc;
-            }
-        }
-    a->marked = YES; nRoot++;
-    if (a->isLocked == NO && moveInRoot == YES)
-        {
-        MarkDistance(a->left,  YES, nNeighbor, &nRoot);
-        MarkDistance(a->right, YES, nNeighbor, &nRoot);
-        }
-    /* mark the crown part if moveInRoot is NO */
-    c->marked = YES; nCrown++;
-    if (c->isLocked == NO && moveInRoot == NO)
-        {
-        MarkDistance(c->left,  NO, nNeighbor, &nCrown);
-        MarkDistance(c->right, NO, nNeighbor, &nCrown);
-        }
-    if (d->isLocked == NO && moveInRoot == NO)
-        {
-        MarkDistance(d->left,  NO, nNeighbor, &nCrown);
-        MarkDistance(d->right, NO, nNeighbor, &nCrown);
-        }
-    
-    /* need to alloc a matrix for parsimony lengths, an array of pointers to crown part,
-       and an array of pointers to root part. */
-    parLength = (MrBFlt *) SafeCalloc (nRoot*nCrown, sizeof(MrBFlt));
-    pRoot  = (TreeNode **) SafeCalloc(nRoot,  sizeof(TreeNode *));
-    pCrown = (TreeNode **) SafeCalloc(nCrown, sizeof(TreeNode *));
-    if (!parLength || !pRoot || !pCrown)  goto errorExit;
-    /* starting position */
-    pRoot[0] = a; pCrown[0] = c;
-    for (i=j=1, n=t->nNodes-2; n>=0; n--)
-        {  /* and the rest */
-        p = t->allDownPass[n];
-        if (p->marked == YES && p->x < 0)
-            pRoot[i++] = p;
-        if (p->marked == YES && p->x > 0)
-            pCrown[j++] = p;
-        }
-    assert(i==nRoot && j==nCrown);
-    
-    /* get final parsimony state sets for the root part */
-    GetParsDP (t, t->root->left, chain);
-    GetParsFP (t, t->root->left, chain);
-    /* get final parsimony state sets for the crown part */
-    GetParsDP (t, c, chain);
-    GetParsDP (t, d, chain);
-    GetParsFP (t, c, chain);
-    GetParsFP (t, d, chain);
-    
-    /* find number of site patterns and modify randomly */
-    globalNSitesOfPat = numSitesOfPat + (chainId[chain] % chainParams.numChains) * numCompressedChars + m->compCharStart;
-    nSitesOfPat = (CLFlt *) SafeCalloc (numCompressedChars, sizeof(CLFlt));
-    if (!nSitesOfPat)  goto errorExit;
-    for (i=0; i<numCompressedChars; i++)
-        {
-        nSitesOfPat[i] = globalNSitesOfPat[i];
-        for (j=0; j<globalNSitesOfPat[i]; j++)
-            {
-            ran = RandomNumber(seed);
-            if (ran < decreaseProb)
-                nSitesOfPat[i]--;
-            else if (ran > 1.0 - increaseProb)
-                nSitesOfPat[i]++;
-            }
-        }
-    
-    /* cycle through the possibilities and record the parsimony length */
-    for (j=0; j<nCrown; j++)
-        {
-        for (i=0; i<nRoot; i++)
-            {
-            parLength[i+j*nRoot] = 0.0;
-            for (n=0; n<t->nRelParts; n++)
-                {
-                division = t->relParts[n];
-                
-                /* Find model settings */
-                m = &modelSettings[division];
-                
-                /* find nStates and ratemult */
-                nStates = m->numModelStates;
-                if (m->dataType == STANDARD)
-                    nStates = 2;
-                rateMult = GetRate(division, chain);
-                
-                /* find nSitesOfPat */
-                nSites = nSitesOfPat + m->compCharStart;
-                
-                /* get division warp factor (prop. to prob. of change) */
-                divFactor = - warpFactor * log((1.0/nStates) - exp(-nStates/(nStates-1)*v_typical*rateMult)/nStates);
-                
-                /* find downpass parsimony sets for the potential new connection nodes and their environment */
-                pA = m->parsSets[pRoot[i]->index];
-                pB = m->parsSets[pRoot[i]->anc->index];
-                pC = m->parsSets[pCrown[j]->index];
-                pD = m->parsSets[pCrown[j]->anc->index];
-                
-                length = 0.0;
-                if (m->nParsIntsPerSite == 1)
-                    {
-                    for (k=0; k<m->numChars; k++)
-                        {
-                        y[0] = (pC[k] | pD[k]) & (pA[k] | pB[k]);
-                        if (y[0] == 0)
-                            length += nSites[k];
-                        }
-                    }
-                else /* if (m->nParsIntsPerSite == 2) */
-                    {
-                    for (k=0; k<2*m->numChars; k+=2)
-                        {
-                        y[0] = (pC[k] | pD[k]) & (pA[k] | pB[k]);
-                        y[1] = (pC[k+1] | pD[k+1]) & (pA[k+1] | pB[k+1]);;
-                        if ((y[0] | y[1]) == 0)
-                            length += nSites[k/2];
-                        }
-                    }
-                parLength[i+j*nRoot] += divFactor * length;
-                }
-            }
-        }
-    
-    /* find the min length and the sum for the forward move */
-    minLength = -1.0;
-    for (j=0; j<nCrown; j++)
-        for (i=0; i<nRoot; i++)
-            {
-            if (i == 0 && j == 0)  // exclude original position
-                continue;
-            if (minLength > parLength[i+j*nRoot] || minLength < 0.0)
-                minLength = parLength[i+j*nRoot];
-            }
-    sum1 = 0.0; tempc = 0.0;
-    for (j=0; j<nCrown; j++)
-        for (i=0; i<nRoot; i++)
-            {
-            if (i == 0 && j == 0)  // exclude original position
-                continue;
-            /* Kahan summation to reduce numerical error */
-            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
-            tempsum = sum1 + tempy;  tempc = (tempsum - sum1) - tempy;
-            sum1 = tempsum;
-            // sum1 += exp(minLength - parLength[i+j*nRoot]);
-            // printf("%d %d %lf\n", i, j, exp(minLength - parLength[i+j*nRoot]));
-            }
-
-    /* generate a random uniform */
-    ran = RandomNumber(seed) * sum1;
-    
-    /* select the appropriate reattachment point */
-    newA = a; newC = c;
-    prob = 0.0; tempc = 0.0;
-    for (j=0; j<nCrown; j++)
-        for (i=0; i<nRoot; i++)
-            {
-            if (i == 0 && j == 0)  // exclude original position
-                continue;
-            // prob += exp (minLength - parLength[i+j*nRoot]);
-            /* Kahan summation to reduce numerical error */
-            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
-            tempsum = prob + tempy;  tempc = (tempsum - prob) - tempy;
-            prob = tempsum;
-            if (prob > ran) {
-                /* proposed new attaching position */
-                newA = pRoot[i];
-                newC = pCrown[j];
-                goto outLoop;
-                }
-            }
-outLoop:;
-    iA = i; jC = j;
-    
-    /* calculate the proposal ratio */
-    (*lnProposalRatio) = parLength[i+j*nRoot] - minLength + log(sum1);
-    
-    /* find the min length and the sum for the backward move */
-    minLength = -1.0;
-    for (j=0; j<nCrown; j++)
-        for (i=0; i<nRoot; i++)
-            {
-            if (i == iA && j == jC)  // exclude new position
-                continue;
-            if (minLength > parLength[i+j*nRoot] || minLength < 0.0)
-                minLength = parLength[i+j*nRoot];
-            }
-    sum2 = 0.0; tempc = 0.0;
-    for (j=0; j<nCrown; j++)
-        for (i=0; i<nRoot; i++)
-            {
-            if (i == iA && j == jC)  // exclude new position
-                continue;
-            /* Kahan summation to reduce numerical error */
-            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
-            tempsum = sum2 + tempy;  tempc = (tempsum - sum2) - tempy;
-            sum2 = tempsum;
-            // sum2 += exp (minLength - parLength[i+j*nRoot]);
-            // printf("%d %d %lf\n", i, j, exp(minLength - parLength[i+j*nRoot]));
-            }
-    
-    /* calculate the proposal ratio */
-    (*lnProposalRatio) += minLength - parLength[0] - log(sum2);
-    
-    /* reattach the root part */
-    newB = newA->anc;
-    newA->anc = u;
-    if (u->left == v)
-        u->right = newA;
-    else
-        u->left = newA;
-    u->anc = newB;
-    if (newB->left == newA)
-        newB->left = u;
-    else
-        newB->right = u;
-    
-    /* transfer lock and reassign branch lengths, if necessary */
-    if (newA != a)
-        {
-        /* if u is locked, then we have moved upwards and need to leave the u lock behind */
-        if (u->isLocked == YES)
-            {
-            u->isLocked = NO;
-            a->isLocked = YES;
-            a->lockID = u->lockID;
-            u->lockID = -1;
-            }
-        
-        p = newA;
-        while (p->anc != NULL)
-            {
-            if (p == a) break;
-            p = p->anc;
-            }
-        if (p == a)
-            {
-            /* newA is descendant to a so move a->length not u->length */
-            x = u->length;
-            u->length = a->length;
-            a->length = x;
-            }
-
-        p = b;
-        while (p->anc != NULL)
-            {
-            if (p == newA) break;
-            p = p->anc;
-            }
-        if (p == newA)
-            {
-            /* newA is ancestor to a so insert above instead of below */
-            x = newA->length;
-            newA->length = u->length;
-            u->length = x;
-            /* newA is on root path and locked, we need to transfer lock to u */
-            if (newA->isLocked == YES) {
-                u->isLocked = YES;
-                u->lockID = newA->lockID;
-                newA->isLocked = NO;
-                newA->lockID = -1;
-                }
-            }
-        
-        /* hit a length with multiplier */
-        x = a->length * exp(tuning * (RandomNumber(seed) - 0.5));
-        while (x < minV || x > maxV)
-            {
-            if (x < minV)
-                x = minV * minV / x;
-            else if (x > maxV)
-                x = maxV * maxV / x;
-            }
-        /* calculate proposal and prior ratio based on length modification */
-        (*lnProposalRatio) += log (x / a->length);
-        if (isVPriorExp == YES)
-            (*lnPriorRatio) += brlensExp * (a->length - x);
-        a->length = x;
-
-        /* hit u length with multiplier */
-        x = u->length * exp(tuning * (RandomNumber(seed) - 0.5));
-        while (x < minV || x > maxV)
-            {
-            if (x < minV)
-                x = minV * minV / x;
-            else if (x > maxV)
-                x = maxV * maxV / x;
-            }
-        /* calculate proposal and prior ratio based on length modification */
-        (*lnProposalRatio) += log (x / u->length);
-        if (isVPriorExp == YES)
-            (*lnPriorRatio) += brlensExp * (u->length - x);
-        u->length = x;
-
-        /* hit newA length with multiplier */
-        x = newA->length * exp(tuning * (RandomNumber(seed) - 0.5));
-        while (x < minV || x > maxV)
-            {
-            if (x < minV)
-                x = minV * minV / x;
-            else if (x > maxV)
-                x = maxV * maxV / x;
-            }
-        /* calculate proposal and prior ratio based on length modification */
-        (*lnProposalRatio) += log (x / newA->length);
-        if (isVPriorExp == YES)
-            (*lnPriorRatio) += brlensExp * (newA->length - x);
-        newA->length = x;
-         
-        /* set tiprobs update flags */
-        newA->upDateTi = YES;
-        a->upDateTi = YES;
-        u->upDateTi = YES;
-        }
-    
-    /* alloc temp tree nodes */
-    old = (TreeNode *) SafeCalloc (1, sizeof (TreeNode));
-    tmp = (TreeNode *) SafeCalloc (1, sizeof (TreeNode));
-    if (old == NULL || tmp == NULL)  goto errorExit;
-    
-    r = newC;
-    q = newB = newC->anc;
-    if (newC != c)  // crown part has changed
-        {
-        /* rotate nodes from newC to c or d (whichever is closest) */
-        CopyTreeNodes (old, r, 0);
-        while (r != c && r != d)
-            {
-            p = q->anc;
-            /* rotate pointers of q */
-            if (q->left == r)
-                q->left = p;
-            else
-                q->right = p;
-            q->anc = r;
-            /* swap q and old */
-            CopyTreeNodes (tmp, q, 0);
-            CopyTreeNodes (q, old, 0);
-            CopyTreeNodes (old, tmp, 0);
-            /* make sure we get q and r initialized for next round */
-            r = q;
-            q = p;
-            }
-        CopyTreeNodes (newC->anc, old, 0);
-        
-        /* hit q length with multiplier while we are at it */
-        x = q->length * exp(tuning * (RandomNumber(seed) - 0.5));
-        while (x < minV || x > maxV)
-            {
-            if (x < minV)
-                x = minV * minV / x;
-            else if (x > maxV)
-                x = maxV * maxV / x;
-            }        
-        /* calculate proposal and prior ratio based on length modification */
-        (*lnProposalRatio) += log (x / q->length);
-        if (isVPriorExp == YES)
-            (*lnPriorRatio) += brlensExp * (q->length - x);
-        q->length = x;
-        q->upDateTi = YES;
-
-        /* hit newB length with multiplier */
-        x = newB->length * exp(tuning * (RandomNumber(seed) - 0.5));
-        while (x < minV || x > maxV)
-            {
-            if (x < minV)
-                x = minV * minV / x;
-            else if (x > maxV)
-                x = maxV * maxV / x;
-            }
-        /* calculate proposal and prior ratio based on length modification */
-        (*lnProposalRatio) += log (x / newB->length);
-        if (isVPriorExp == YES)
-            (*lnPriorRatio) += brlensExp * (newB->length - x);
-        newB->length = x;
-        newB->upDateTi = YES;
-
-        /* hit newC length with multiplier */
-        x = newC->length * exp(tuning * (RandomNumber(seed) - 0.5));
-        while (x < minV || x > maxV)
-            {
-            if (x < minV)
-                x = minV * minV / x;
-            else if (x > maxV)
-                x = maxV * maxV / x;
-            }
-        /* calculate proposal and prior ratio based on length modification */
-        (*lnProposalRatio) += log (x / newC->length);
-        if (isVPriorExp == YES)
-            (*lnPriorRatio) += brlensExp * (newC->length - x);
-        newC->length = x;
-        newC->upDateTi = YES;
-        }
-    
-    /* reattach the crown part */
-    v->left = newC;
-    v->right = newB;
-    newC->anc = newB->anc = v;
-    
-    topologyHasChanged = YES;
-
-    /* set flags for update of cond likes */
-    if (moveInRoot == YES)
-        {
-        p = u;
-        while (p->anc != NULL)
-            {
-            p->upDateCl = YES;
-            p = p->anc;
-            }
-        p = b;
-        while (p->anc != NULL)
-            {
-            p->upDateCl = YES;
-            p = p->anc;
-            }
-        }
-    if (moveInRoot == NO)
-        {
-        p = newC;
-        while (p->anc != NULL)
-            {
-            p->upDateCl = YES;
-            p = p->anc;
-            }
-        p = r;
-        while (p->anc != NULL)
-            {
-            p->upDateCl = YES;
-            p = p->anc;
-            }
-        }
-    
-    /* get down pass sequence if tree topology has changed */
-    if (topologyHasChanged == YES)
-        {
-        GetDownPass (t);
-        }
-    
-    /* Dirichlet or twoExp prior */
-    if (isVPriorExp > 1)
-        (*lnPriorRatio) += LogDirPrior(t, mp, isVPriorExp);
-    
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-    gNodeMoves = nRootNodes;
-#   endif
-    
-    /* free up local memory */
-    free (parLength); free (pRoot); free (pCrown);
-    free (nSitesOfPat); free (old); free (tmp);
-    
-    return (NO_ERROR);
-    
-errorExit:
-    MrBayesPrint ("%s   Problem allocating memory in Move_ParsSPR\n", spacer);
-    free (parLength); free (pRoot); free (pCrown);
-    free (nSitesOfPat); free (old); free (tmp);
-    
-    return (ERROR);
-}
-
-
-int Move_ParsSPR2 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
-{
-    /* Change topology using SPR-type move biased according to parsimony scores. Map branch lengths without modification */
-    
-    int         i, j, n, division, topologyHasChanged,  moveInRoot;
-    BitsLong    *pA, *pV, *pP, *pU, y[2];
-    MrBFlt      x, minLength=0.0, length=0.0, cumulativeProb, warpFactor, ran, increaseProb, decreaseProb,
-                divFactor, nStates, rateMult, v_typical, sum1, sum2, tempsum, tempc, tempy;
-    CLFlt       *nSitesOfPat, *nSites, *globalNSitesOfPat;
-    TreeNode    *p, *q, *r, *a, *b, *u, *v, *c, *d, *newA=NULL, *newB, *newC=NULL, *old=NULL, *tmp=NULL;
-    Tree        *t;
-    ModelInfo   *m = NULL;
-    
-    warpFactor = mvp[0];                  /* tuning parameter determining how heavily to weight according to parsimony scores */
-    increaseProb = decreaseProb = mvp[1]; /* reweighting probabilities */
-    v_typical = mvp[2];                   /* typical branch length for conversion of parsimony score to log prob ratio */
-    
-    (*lnProposalRatio) = (*lnPriorRatio) = 0.0;
-    
-    /* get model params and model info */
-    m = &modelSettings[param->relParts[0]];
-    
-    /* get tree */
-    t = GetTree (param, chain, state[chain]);
-    
-    /* Dirichlet or twoExp prior for brls
-    if (isVPriorExp > 1)
-        (*lnPriorRatio) = -LogDirPrior(t, mp, isVPriorExp); */
-    
-    /* set topologyHasChanged to NO */
-    topologyHasChanged = NO;
-    
-    /* reset node variables that will be used */
-    for (i=0; i<t->nNodes; i++)
-        {
-        p = t->allDownPass[i];
-        p->marked = NO;
-        p->d = 0;
-        }
-    
-    /* pick a random branch */
-    p = t->allDownPass[(int)(RandomNumber(seed) * (t->nNodes -1))];
-    q = p->anc->right;
-    if (q == p)
-        q = p->anc->left;
-    if (p->left == NULL)
-        moveInRoot = YES;
-    else if (p->anc->anc == NULL)
-        moveInRoot = NO;
-    else if ((p->anc->isLocked == YES || p->anc->anc->anc == NULL) && (q->isLocked == YES || q->left == NULL))
-        {
-        if ((p->left->isLocked == YES || p->left->left == NULL) && (p->right->isLocked == YES || p->right->left == NULL))
-            {
-            abortMove = YES;
-            return (NO_ERROR);
-            }
-        moveInRoot = NO;
-        }
-    else if ((p->left->isLocked == YES || p->left->left == NULL) && (p->right->isLocked == YES || p->right->left == NULL))
-        moveInRoot = YES;
-    else if (RandomNumber(seed) < 0.5)
-        moveInRoot = YES;
-    else
-        moveInRoot = NO;
- 
-    /* find number of site patterns and modify randomly */
-    globalNSitesOfPat = numSitesOfPat + (chainId[chain] % chainParams.numChains) * numCompressedChars + m->compCharStart;
-    nSitesOfPat = (CLFlt *) SafeCalloc (numCompressedChars, sizeof(CLFlt));
-    if (!nSitesOfPat)
-        {
-        MrBayesPrint ("%s   Problem allocating nSitesOfPat in Move_ParsSPR\n", spacer);
-        return (ERROR);
-        }
-    for (i=0; i<numCompressedChars; i++)
-        {
-        nSitesOfPat[i] = globalNSitesOfPat[i];
-        for (j=0; j<globalNSitesOfPat[i]; j++)
-            {
-            ran = RandomNumber(seed);
-            if (ran < decreaseProb)
-                nSitesOfPat[i]--;
-            else if (ran > 1.0 - increaseProb)
-                nSitesOfPat[i]++;
-            }
-        }
-
-    /* set up pointers for nodes around the picked branch */
-    v = p;
-    u = p->anc;
-    if (u->left == v)
-        a = u->right;
-    else
-        a = u->left;
-    b = u->anc;
-    c = p->left;
-    d = p->right;
-
-    if (moveInRoot == YES)
-        {
-        /* clip tree */
-        a->anc = b;
-        if (b->left == u)
-            b->left = a;
-        else
-            b->right = a;
-
-        /* get final parsimony states for the root part */
-        GetParsDP (t, t->root->left, chain);
-        GetParsFP (t, t->root->left, chain);
-        
-        /* get downpass parsimony states for the crown part */
-        GetParsDP (t, v, chain);
-        
-        /* mark all nodes in the root part of the tree, taking constraints into account */
-        a->marked = YES;
-        if (u->isLocked == NO)
-            {
-            p = a->anc;
-            while (p->anc != NULL)
-                {
-                p->marked = YES;
-                if (p->isLocked == YES)
-                    break;
-                p = p->anc;
-                }
-            }
-        for (i=t->nNodes-2; i>=0; i--)
-            {
-            p = t->allDownPass[i];
-            if (p->marked == NO && p->anc->marked == YES && p->anc->isLocked == NO && p != u)
-                p->marked = YES;
-            }
-            
-        /* cycle through the possibilities and record the parsimony length */
-        for (i=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            if (p->marked == NO)
-                continue;
-            /* find the parsimony length */
-            p->d = 0.0;
-            for (n=0; n<t->nRelParts; n++)
-                {
-                division = t->relParts[n];
-                
-                /* Find model settings */
-                m = &modelSettings[division];
-                
-                /* find nStates and ratemult */
-                nStates = m->numModelStates;
-                if (m->dataType == STANDARD)
-                    nStates = 2;
-                rateMult = GetRate(division, chain);
-                
-                /* find nSitesOfPat */
-                nSites = nSitesOfPat + m->compCharStart;
-                
-                /* get division warp factor */
-                divFactor = - warpFactor * log((1.0/nStates) - exp(-nStates/(nStates-1)*v_typical*rateMult)/nStates);
-                
-                /* find downpass parsimony sets for the node and its environment */
-                pP   = m->parsSets[p->index     ];
-                pA   = m->parsSets[p->anc->index];
-                pV   = m->parsSets[v->index     ];
-                
-                length = 0.0;
-                if (m->nParsIntsPerSite == 1)
-                    {
-                    for (j=0; j<m->numChars; j++)
-                        {
-                        y[0] = (pP[j] | pA[j]) & pV[j];
-                        if (y[0] == 0)
-                            length += nSites[j];
-                        }
-                    }
-                else /* if (m->nParsIntsPerSite == 2) */
-                    {
-                    for (j=0; j<2*m->numChars; j+=2)
-                        {
-                        y[0] = (pP[j] | pA[j]) & pV[j];
-                        y[1] = (pP[j+1] | pA[j+1]) & pV[j+1];
-                        if ((y[0] | y[1]) == 0)
-                            length += nSites[j/2];
-                        }
-                    }
-                p->d += divFactor * length;
-                }
-            }
-        
-        /* find the min length and the sum for the forward move */
-        minLength = -1.0;
-        for (i=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            if (p->marked == NO || p == a)
-                continue;
-            if (minLength < 0.0 || p->d < minLength)
-                minLength = p->d;
-            }
-        sum1 = 0.0; tempc = 0.0;
-        for (i=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            if (p->marked == YES && p != a)
-                {
-                /* Kahan summation to reduce numerical error */
-                tempy = exp (minLength - p->d) - tempc;
-                tempsum = sum1 + tempy;
-                tempc = (tempsum - sum1) - tempy;
-                sum1 = tempsum;
-                }
-            }
-        
-        /* generate a random uniform */
-        ran = RandomNumber(seed) * sum1;
-        
-        /* select the appropriate reattachment point */
-        cumulativeProb = 0.0; tempc = 0.0;
-        for (i=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            if (p->marked == YES && p != a)
-                {
-                newA = p;
-                /* Kahan summation to reduce numerical error */
-                tempy = exp (minLength - p->d) - tempc;
-                tempsum = cumulativeProb + tempy;
-                tempc = (tempsum - cumulativeProb) - tempy;
-                cumulativeProb = tempsum;
-                if (cumulativeProb > ran)
-                    break;
-                }
-            }
-        
-        /* calculate the proposal ratio */
-        (*lnProposalRatio) = newA->d - minLength + log(sum1);
-        
-        /* find the min length and the sum for the backward move */
-        minLength = -1.0;
-        for (i=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            if (p->marked == NO || p == newA)
-                continue;
-            if (minLength < 0.0 || p->d < minLength)
-                minLength = p->d;
-            }
-        sum2 = 0.0; tempc = 0.0;
-        for (i=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            if (p->marked == YES && p != newA)
-                {
-                /* Kahan summation to reduce numerical error */
-                tempy = exp (minLength - p->d) - tempc;
-                tempsum = sum2 + tempy;
-                tempc = (tempsum - sum2) - tempy;
-                sum2 = tempsum;
-                }
-            }
-        
-        /* calculate the proposal ratio */
-        (*lnProposalRatio) += minLength - a->d - log(sum2);
-        
-        /* reattach */
-        newB = newA->anc;
-        newA->anc = u;
-        if (u->left == v)
-            u->right = newA;
-        else
-            u->left = newA;
-        if (newB->left == newA)
-            newB->left = u;
-        else
-            newB->right = u;
-        u->anc = newB;
-        
-        /* transfer lock if necessary */
-        /* if u is locked, then we have moved upwards and need to leave the u lock behind */
-        if (u->isLocked == YES)
-            {
-            u->isLocked = NO;
-            a->isLocked = YES;
-            a->lockID = u->lockID;
-            u->lockID = -1;
-            }
-        /* if newA is on root path and locked, we need to transfer lock to u */
-        p = b;
-        while (p != NULL)
-            {
-            if (p == newA)
-                break;
-            p = p->anc;
-            }
-        if (p == newA && newA->isLocked == YES)
-            {
-            u->isLocked = YES;
-            u->lockID = newA->lockID;
-            newA->isLocked = NO;
-            newA->lockID = -1;
-            }
-        
-        /* reassign branch lengths */
-        p = newA;
-        while (p->anc != NULL)
-            {
-            if (p == a)
-                break;
-            p = p->anc;
-            }
-        if (p == a)
-            {
-            /* newA is descendant to a so move a->length and not u->length */
-            x = u->length;
-            u->length = a->length;
-            a->length = x;
-            }
-        p = a;
-        while (p->anc != NULL)
-            {
-            if (p == newA)
-                break;
-            p = p->anc;
-            }
-        if (p == newA)
-            {
-            /* newA is ancestor to a so insert above instead of below */
-            x = newA->length;
-            newA->length = u->length;
-            u->length = x;
-            }
-        
-        /* set tiprobs update flags */
-        a->upDateTi = YES;
-        u->upDateTi = YES;
-        newA->upDateTi = YES;
-        
-        /* set flags for update of cond likes from u and down to root */
-        p = u;
-        while (p->anc != NULL)
-            {
-            p->upDateCl = YES;
-            p = p->anc;
-            }
-        
-        /* set flags for update of cond likes from b and down to root */
-        p = b;
-        while (p->anc != NULL && p->upDateCl == NO)
-            {
-            p->upDateCl = YES;
-            p = p->anc;
-            }
-        }
-
-    else  // moveInRoot == NO
-        {
-        if (u->anc != NULL)  // so that a and b != NULL
-            {
-            /* clip root part of tree */
-            a->anc = b;
-            if (b->left == u)
-                b->left = a;
-            else
-                b->right = a;
-            
-            /* get final parsimony states for the root part */
-            GetParsDP (t, t->root->left, chain);
-            GetParsFP (t, t->root->left, chain);
-            
-            /* get union of final parsimony states of u */
-            for (n=0; n<t->nRelParts; n++)
-                {
-                division = t->relParts[n];                
-                /* Find model settings */
-                m = &modelSettings[division];                
-                /* find final parsimony sets for u from its environment */
-                pA   = m->parsSets[a->index];
-                pP   = m->parsSets[b->index];
-                pU   = m->parsSets[u->index];
-                for (j=0; j<m->numChars*m->nParsIntsPerSite; j++)
-                    pU[j] = (pP[j] | pA[j]);
-                }
-            }
-        
-        /* clip crown part of tree */
-        c->anc = d;
-        d->anc = c;
-        
-        /* get final parsimony states for the crown part */
-        GetParsDP (t, c, chain);
-        GetParsFP (t, c, chain);
-        GetParsDP (t, d, chain);
-        GetParsFP (t, d, chain);
-                
-        /* mark nodes in the crown tree, respecting constraints */
-        MarkUnconstrained (c);
-        MarkUnconstrained (d);        
-        /* skip d (same as c) */
-        d->marked = NO;
-
-        /* cycle through the possibilities and record the parsimony length */
-        for (i=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            if (p->marked == NO)
-                continue;
-            /* find the parsimony length */
-            p->d = 0.0;
-            for (n=0; n<t->nRelParts; n++)
-                {
-                division = t->relParts[n];
-                
-                /* Find model settings */
-                m = &modelSettings[division];
-                
-                /* find nStates and ratemult */
-                nStates = m->numModelStates;
-                if (m->dataType == STANDARD)
-                    nStates = 2;
-                rateMult = GetRate(division, chain);
-                
-                /* find nSitesOfPat */
-                nSites = nSitesOfPat + m->compCharStart;
-                
-                /* get division warp factor (prop. to prob. of change) */
-                divFactor = - warpFactor * log((1.0/nStates) - exp(-nStates/(nStates-1)*v_typical*rateMult)/nStates);
-                
-                /* find downpass parsimony sets for the node and its environment */
-                pP   = m->parsSets[p->index     ];
-                pA   = m->parsSets[p->anc->index];
-                pU   = m->parsSets[u->index     ];
-                
-                length = 0.0;
-                if (m->nParsIntsPerSite == 1)
-                    {
-                    for (j=0; j<m->numChars; j++)
-                        {
-                        y[0] = (pP[j] | pA[j]) & pU[j];
-                        if (y[0] == 0)
-                            length += nSites[j];
-                        }
-                    }
-                else /* if (m->nParsIntsPerSite == 2) */
-                    {
-                    for (j=0; j<2*m->numChars; j+=2)
-                        {
-                        y[0] = (pP[j] | pA[j]) & pU[j];
-                        y[1] = (pP[j+1] | pA[j+1]) & pU[j+1];
-                        if ((y[0] | y[1]) == 0)
-                            length += nSites[j/2];
-                        }
-                    }
-                p->d += divFactor * length;
-                }
-            }
-        
-        /* find the min length and the sum for the forward move */
-        minLength = -1.0;
-        for (i=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            if (p->marked == NO || p == c)
-                continue;
-            if (minLength < 0.0 || p->d < minLength)
-                minLength = p->d;
-            }
-        sum1 = 0.0; tempc = 0.0;
-        for (i=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            if (p->marked == YES && p != c)
-                {
-                /* Kahan summation to reduce numerical error */
-                tempy = exp (minLength - p->d) - tempc;
-                tempsum = sum1 + tempy;
-                tempc = (tempsum - sum1) - tempy;
-                sum1 = tempsum;
-                }
-            }
-        
-        /* generate a random uniform */
-        ran = RandomNumber(seed) * sum1;
-        
-        /* select the appropriate reattachment point */
-        cumulativeProb = 0.0; tempc = 0.0;
-        for (i=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            if (p->marked == YES && p != c)
-                {
-                newC = p;
-                /* Kahan summation to reduce numerical error */
-                tempy = exp (minLength - p->d) - tempc;
-                tempsum = cumulativeProb + tempy;
-                tempc = (tempsum - cumulativeProb) - tempy;
-                cumulativeProb = tempsum;
-                if (cumulativeProb > ran)
-                    break;
-                }
-            }
-        
-        /* calculate the proposal ratio */
-        (*lnProposalRatio) = newC->d - minLength + log(sum1);
-        
-        /* find the min length and the sum for the backward move */
-        minLength = -1.0;
-        for (i=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            if (p->marked == NO || p == newC)
-                continue;
-            if (minLength < 0.0 || p->d < minLength)
-                minLength = p->d;
-            }
-        sum2 = 0.0; tempc = 0.0;
-        for (i=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            if (p->marked == YES && p != newC)
-                {
-                /* Kahan summation to reduce numerical error */
-                tempy = exp (minLength - p->d) - tempc;
-                tempsum = sum2 + tempy;
-                tempc = (tempsum - sum2) - tempy;
-                sum2 = tempsum;
-                }
-            }
-        
-        /* calculate the proposal ratio */
-        (*lnProposalRatio) += minLength - c->d - log(sum2);
-
-        /* alloc temp tree nodes */
-        old = (TreeNode *) SafeCalloc (1, sizeof (TreeNode));
-        tmp = (TreeNode *) SafeCalloc (1, sizeof (TreeNode));
-        if (old == NULL || tmp == NULL)
-            {
-            free (nSitesOfPat);
-            free (old); free (tmp);
-            return (ERROR);
-            }
-        
-        /* rotate nodes from newC to c or d (whichever is closest)         */
-        /* label node we come from as r, node we rotate q, and next node p */
-        r = newC; q = r->anc;
-        assert (t->bitsets == NULL);
-        CopyTreeNodes (old, r, 0);
-        do  {
-            p = q->anc;
-            /* rotate pointers of q */
-            if (q->left == r)
-                q->left = p;
-            else
-                q->right = p;
-            q->anc = r;
-            /* swap q and old */            
-            CopyTreeNodes (tmp, q, 0);
-            CopyTreeNodes (q, old, 0);
-            CopyTreeNodes (old, tmp, 0);
-            /* make sure we get q and r initialized for next round */
-            r = q;
-            q = p;
-            }
-        while (r != c && r != d);
-
-        /* now reattach crown to v */
-        newB = newC->anc;
-        v->left = newC;
-        v->right = newB;
-        newC->anc = newB->anc = v;
-        CopyTreeNodes (newB, old, 0);
-        
-        /* and reattach root to u (u pointers are unchanged) */
-        if (u->anc != NULL)
-            {
-            a->anc = u;
-            if (b->left == a)
-                b->left = u;
-            else
-                b->right = u;
-            }
-        
-        /* set flags for update of cond likes from newC and down to root */
-        p = newC;
-        while (p->anc != NULL)
-            {
-            p->upDateCl = YES;
-            p = p->anc;
-            }
-        
-        /* set flags for update of cond likes from r and down to root */
-        p = r;
-        while (p->anc != NULL)
-            {
-            p->upDateCl = YES;
-            p = p->anc;
-            }
-
-        /* free memory */
-        free (old); free (tmp);
-        }
-
-    topologyHasChanged = YES;
-    
-    /* get down pass sequence if tree topology has changed */
-    if (topologyHasChanged == YES)
-        {
-        GetDownPass (t);
+        for (i=0; i<mp->numM10BetaCats; i++)
+            newSubVals[i] = newFreqs[0] / mp->numM10BetaCats;
+        for (i=mp->numM10BetaCats; i<mp->numM10BetaCats+mp->numM10GammaCats; i++)
+            newSubVals[i] = newFreqs[1] / mp->numM10GammaCats;
         }
-    
-    /* Dirichlet or twoExp prior
-    if (isVPriorExp > 1)
-        (*lnPriorRatio) += LogDirPrior(t, mp, isVPriorExp); */
-    
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-    gNodeMoves = nRootNodes;
-#   endif
-    
-    free (nSitesOfPat);
+
+    /* get proposal ratio */
+    sum = 0.0;
+    for (i=0; i<localNumCats; i++)
+        sum += newFreqs[i]*alpha;
+    x = LnGamma(sum);
+    for (i=0; i<localNumCats; i++)
+        x -= LnGamma(newFreqs[i]*alpha);
+    for (i=0; i<localNumCats; i++)
+        x += (newFreqs[i]*alpha-1.0)*log(oldFreqs[i]);
+    sum = 0.0;
+    for (i=0; i<localNumCats; i++)
+        sum += oldFreqs[i]*alpha;
+    y = LnGamma(sum);
+    for (i=0; i<localNumCats; i++)
+        y -= LnGamma(oldFreqs[i]*alpha);
+    for (i=0; i<localNumCats; i++)
+        y += (oldFreqs[i]*alpha-1.0)*log(newFreqs[i]);
+    (*lnProposalRatio) = x - y;
+
+    /* get prior ratio */
+    x = y = 0.0;        /* ignore the gamma part, it is identical */
+    for (i=0; i<localNumCats; i++)
+        x += (priorParams[i]-1.0)*log(newFreqs[i]);
+    for (i=0; i<localNumCats; i++)
+        y += (priorParams[i]-1.0)*log(oldFreqs[i]);
+    (*lnPriorRatio) = x - y;
+        
+    /* Set update flags for all partitions that share this omega. Note that the conditional
+       likelihood update flags have been set before we even call this function. */
+    for (i=0; i<param->nRelParts; i++)
+        TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
+
+    /* Set update flags for cijks for all affected partitions. */
+    for (i=0; i<param->nRelParts; i++)
+        modelSettings[param->relParts[i]].upDateCijk = YES;
 
     return (NO_ERROR);
 }
 
 
-int Move_ParsSPRClock (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+/*----------------------------------------------------------------
+|
+|   Move_OmegaM3: Change the nonysnonymous/synonymous rate ratio
+|      of one class of the M3 model
+|
+----------------------------------------------------------------*/
+int Move_OmegaM3 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
 {
-    /* Change branch lengths and topology (potentially) using SPR-type move, parsimony-biased */
+    int         i, isValidO, whichOmega;
+    MrBFlt      newO, window, minO, maxO, ran, *value, *oldValue, x, y;
 
-    /* This move picks a branch and then chooses a reattachment point based on
-       the parsimony score. On the ending branch, the attachment point is reinserted
-       randomly along the branch (below the minimum age of the node). Since 2010-11-02
-       the move is Metropolized to improve efficiency. */
-    
-    int         i, j, n, division, n1=0, n2=0, n3=0, n4=0, n5=0, *nEvents;
-    BitsLong    *pA, *pV, *pP, y[2];
-    MrBFlt      x, oldBrlen=0.0, newBrlen=0.0, v1=0.0, v2=0.0, v3=0.0, v4=0.0, v5=0.0,
-                v3new=0.0, lambda, **position=NULL, **rateMultiplier=NULL, *brlens,
-                igrvar, *igrRate=NULL, nu, *tk02Rate=NULL, minLength=0.0, length=0.0,
-                cumulativeProb, warpFactor, sum1, sum2, ran, increaseProb, decreaseProb,
-                divFactor, nStates, rateMult, v_typical, minV;
-    CLFlt       *nSitesOfPat, *nSites, *globalNSitesOfPat;
-    TreeNode    *p, *a, *b, *u, *v, *c=NULL, *d;
-    Tree        *t;
-    ModelInfo   *m=NULL;
-    Param       *subParm;
+    /* get size of window, centered on current omega value */
+    window = mvp[0];
 
-    warpFactor = mvp[0];                  /* tuning parameter determining how heavily to weight according to parsimony scores */
-    increaseProb = decreaseProb = mvp[1]; /* reweighting probabilities */
-    v_typical = mvp[2];                   /* typical branch length for converting parsimony scores to log prob ratios */
+    /* get old value of omega */
+    value = GetParamVals(param, chain, state[chain]);
+    oldValue = GetParamVals(param, chain, state[chain] ^ 1);
+    whichOmega = (int) (RandomNumber(seed)*3.0);
+    
+    /* get minimum and maximum values for omega */
+    if (whichOmega == 0)
+        minO = 0.0;
+    else
+        minO = value[whichOmega-1];
+    if (whichOmega == 2)
+        maxO = OMEGA_MAX;
+    else
+        maxO = value[whichOmega+1];
 
-    (*lnProposalRatio) = (*lnPriorRatio) = 0.0;
+    /* change value for omega */
+    ran = RandomNumber(seed);
+     if (maxO-minO < window)
+        {
+        window = maxO-minO;
+        }
+    newO = oldValue[whichOmega] + window * (ran - 0.5);
+    
+    /* check that new value is valid */
+    isValidO = NO;
+    do
+        {
+        if (newO < minO)
+            newO = 2* minO - newO;
+        else if (newO > maxO)
+            newO = 2 * maxO - newO;
+        else
+            isValidO = YES;
+        } while (isValidO == NO);
 
-    /* get tree */
-    t = GetTree (param, chain, state[chain]);
+    /* copy new omega value back */
+    value[whichOmega] = newO;
 
-    /* get model params and model info */
-    m = &modelSettings[param->relParts[0]];
+    /* get proposal ratio */
+    *lnProposalRatio = 0.0;
     
-    /* get min and max brlen in relative time and subst units */
-    minV = BRLENS_MIN;
+    /* get prior ratio */
+    x = LogOmegaPrior (value[0], value[1], value[2]);
+    y = LogOmegaPrior (oldValue[0], oldValue[1], oldValue[2]);
+    *lnPriorRatio = x - y;
 
-#   if defined (DEBUG_ParsSPRClock)
-    printf ("Before:\n");
-    ShowNodes (t->root, 2, YES);
-    getchar();
-#   endif
-    
-    /* pick a branch */
-    do  {
-        p = t->allDownPass[(int)(RandomNumber(seed) * (t->nNodes - 2))];
-        a = p->anc->left;
-        b = p->anc->right;
-        }
-    while (p->anc->isLocked == YES || p->anc->anc->anc == NULL
-           || (p == b && a->length < TIME_MIN) || (p == a && b->length < TIME_MIN));
-    /* skip constraints, siblings of root (and root); and consider ancestral fossils in fbd tree */
+    /* Set update flags for all partitions that share this omega. Note that the conditional
+       likelihood update flags have been set before we even call this function. */
+    for (i=0; i<param->nRelParts; i++)
+        TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
 
-    /* set up pointers for nodes around the picked branch */
-    v = p;
-    u = p->anc;
-    if (u->left == v)
-        a = u->right;
-    else
-        a = u->left;
-    b = u->anc;
+    /* Set update flags for cijks for all affected partitions. */
+    for (i=0; i<param->nRelParts; i++)
+        modelSettings[param->relParts[i]].upDateCijk = YES;
 
-    /* record branch length for insertion in back move */
-    if (v->length > 0.0)  /* side branch, not anc fossil */
-        {
-        if (v->nodeDepth > a->nodeDepth)
-            oldBrlen = b->nodeDepth - v->nodeDepth - 2.0*minV;
-        else
-            oldBrlen = b->nodeDepth - a->nodeDepth - 2.0*minV;
-        }
-    v1 = a->length;
-    v2 = u->length;
-    v3 = v->length;
+    return (NO_ERROR);
+}
 
-    /* reassign events for CPP and adjust prior and proposal ratios for relaxed clock models */
-    for (i=0; i<param->subParams[0]->nSubParams; i++)
-        {
-        subParm = param->subParams[0]->subParams[i];
-        if (subParm->paramType == P_CPPEVENTS)
-            {
-            nEvents = subParm->nEvents[2*chain+state[chain]];
-            position = subParm->position[2*chain+state[chain]];
-            rateMultiplier = subParm->rateMult[2*chain+state[chain]];
-            n1 = nEvents[a->index];
-            n2 = nEvents[u->index];
-            n3 = nEvents[v->index];
-            if (n2 > 0)
-                {
-                position[a->index] = (MrBFlt *) SafeRealloc ((void *) position[a->index], (n1+n2) * sizeof (MrBFlt));
-                rateMultiplier[a->index] = (MrBFlt *) SafeRealloc ((void *) rateMultiplier[a->index], (n1+n2) * sizeof (MrBFlt));
-                }
-            for (j=0; j<n1; j++)
-                position[a->index][j] *= v1 / (v1+v2);
-            for (j=n1; j<n1+n2; j++)
-                {
-                position[a->index][j] = (position[u->index][j-n1] * v2 + v1) / (v1+v2);
-                rateMultiplier[a->index][j] = rateMultiplier[u->index][j-n1];
-                }
-            nEvents[a->index] = n1+n2;
-            nEvents[u->index] = 0;
-            if (n2 > 0)
-                {
-                free (position[u->index]);
-                free (rateMultiplier[u->index]);
-                position[u->index] = rateMultiplier[u->index] = NULL;
-                }
-            /* adjust effective branch lengths */
-            brlens = GetParamSubVals (subParm, chain, state[chain]);
-            brlens[a->index] += brlens[u->index];   /* only change in effective branch lengths so far */
-            }   /* end CPP events parm */
-        else if ( subParm->paramType == P_TK02BRANCHRATES ||
-                 (subParm->paramType == P_MIXEDBRCHRATES && *GetParamIntVals(subParm, chain, state[chain]) == RCL_TK02))
-            {
-            /* adjust prior ratio */
-            if (subParm->paramType == P_TK02BRANCHRATES)
-                nu = *GetParamVals (modelSettings[subParm->relParts[0]].tk02var, chain, state[chain]);
-            else
-                nu = *GetParamVals (modelSettings[subParm->relParts[0]].mixedvar, chain, state[chain]);
-            tk02Rate = GetParamVals (subParm, chain, state[chain]);
-            if (v->length > 0.0)
-                (*lnPriorRatio) -= LnProbTK02LogNormal(tk02Rate[v->anc->index], nu*v->length, tk02Rate[v->index]);
-            (*lnPriorRatio) -= LnProbTK02LogNormal(tk02Rate[a->anc->index], nu*a->length, tk02Rate[a->index]);
-            (*lnPriorRatio) -= LnProbTK02LogNormal(tk02Rate[u->anc->index], nu*u->length, tk02Rate[u->index]);
-            (*lnPriorRatio) += LnProbTK02LogNormal(tk02Rate[u->anc->index], nu*(a->length+u->length), tk02Rate[a->index]);
-            
-            /* adjust effective branch lengths */
-            brlens = GetParamSubVals (subParm, chain, state[chain]);
-            brlens[a->index] = (tk02Rate[a->index] + tk02Rate[b->index]) / 2.0 * (a->length + u->length);
-            }   /* end tk02 branch rate parameter */
-        else if ( subParm->paramType == P_IGRBRANCHRATES ||
-                 (subParm->paramType == P_MIXEDBRCHRATES && *GetParamIntVals(subParm, chain, state[chain]) == RCL_IGR))
-            {
-            if (subParm->paramType == P_IGRBRANCHRATES)
-                igrvar = *GetParamVals (modelSettings[subParm->relParts[0]].igrvar, chain, state[chain]);
-            else
-                igrvar = *GetParamVals (modelSettings[subParm->relParts[0]].mixedvar, chain, state[chain]);
-            igrRate = GetParamVals (subParm, chain, state[chain]);
 
-            /* adjust prior ratio for old branches */
-            if (v->length > 0.0)
-                (*lnPriorRatio) -= LnProbGamma(v->length/igrvar, v->length/igrvar, igrRate[v->index]);
-            (*lnPriorRatio) -= LnProbGamma(a->length/igrvar, a->length/igrvar, igrRate[a->index]);
-            (*lnPriorRatio) -= LnProbGamma(u->length/igrvar, u->length/igrvar, igrRate[u->index]);
-            (*lnPriorRatio) += LnProbGamma((a->length+u->length)/igrvar, (a->length+u->length)/igrvar, igrRate[a->index]);
+/*----------------------------------------------------------------
+|
+|   Move_OmegaNeu: Change the nonysnonymous/synonymous rate ratio
+|      for neutral sites
+|
+----------------------------------------------------------------*/
+int Move_OmegaNeu (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+{
+    int         i, isOPriorExp, isValidO;
+    MrBFlt      oldO, newO, window, minO, maxO, ran, *value, x, y;
+
+    /* get size of window, centered on current omega value */
+    window = mvp[0];
+
+    /* get old value of omega */
+    value = GetParamVals(param, chain, state[chain]);
+    newO = oldO = value[1];
+
+    /* get minimum and maximum values for omega */
+    minO = value[0];
+    maxO = value[2];
+    
+    /* the only way we would be updating the middle category (omega2) is
+       if we have an exponential prior on all three omegas */
+    isOPriorExp = YES;
+
+    /* change value for omega */
+    ran = RandomNumber(seed);
+    if (maxO-minO < window)
+        {
+        window = maxO-minO;
+        }
+    newO = oldO + window * (ran - 0.5);
+    
+    /* check that new value is valid */
+    isValidO = NO;
+    do
+        {
+        if (newO < minO)
+            newO = 2 * minO - newO;
+        else if (newO > maxO)
+            newO = 2 * maxO - newO;
+        else
+            isValidO = YES;
+        } while (isValidO == NO);
 
-            /* adjust effective branch lengths */
-            brlens = GetParamSubVals (subParm, chain, state[chain]);
-            brlens[a->index] = igrRate[a->index] * (a->length + u->length);
-            }
-        }   /* next subparameter */
+    /* get proposal ratio */
+    *lnProposalRatio = 0.0;
+    
+    /* copy new omega value back */
+    value[1] = newO;
 
-    /* cut tree */
-    a->anc = b;
-    if (b->left == u)
-        b->left = a;
+    /* get prior ratio */
+    if (isOPriorExp == NO)
+        {
+        *lnPriorRatio = 0.0;
+        }
     else
-        b->right = a;
-    a->length += u->length;
-    a->upDateTi = YES;
+        {
+        x = LogOmegaPrior (value[0], newO, value[2]);
+        y = LogOmegaPrior (value[0], oldO, value[2]);
+        *lnPriorRatio = x - y;
+        }
 
-    /* get final parsimony states for the root part */
-    GetParsDP (t, t->root->left, chain);
-    GetParsFP (t, t->root->left->left, chain);
-    GetParsFP (t, t->root->left->right, chain);
+    /* Set update flags for all partitions that share this omega. Note that the conditional
+       likelihood update flags have been set before we even call this function. */
+    for (i=0; i<param->nRelParts; i++)
+        TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
 
-    /* get downpass parsimony states for the crown part */
-    GetParsDP (t, v, chain);
+    /* Set update flags for cijks for all affected partitions. */
+    for (i=0; i<param->nRelParts; i++)
+        modelSettings[param->relParts[i]].upDateCijk = YES;
 
-    /* reset node variables that will be used */
-    for (i=0; i<t->nNodes; i++)
+    return (NO_ERROR);
+}
+
+
+/*----------------------------------------------------------------
+|
+|   Move_OmegaPos: Change the nonysnonymous/synonymous rate ratio
+|      for positively selected sites
+|
+----------------------------------------------------------------*/
+int Move_OmegaPos (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+{
+    int         i, isValidO, omegaUni, omegaExp1, omegaExp2;
+    MrBFlt      oldO, newO, window, minO=0.0, maxO=0.0, ran, *value, x, y;
+    ModelParams *mp;
+
+    /* get size of window, centered on current omega value */
+    window = mvp[0];
+
+    /* get model params */
+    mp = &modelParams[param->relParts[0]];
+
+    /* get old value of omega */
+    value = GetParamVals(param, chain, state[chain]);
+    newO = oldO = value[2];
+    
+    /* determine prior for omega */
+    omegaUni = omegaExp1 = omegaExp2 = NO;
+    if (param->paramId == OMEGA_BUD || param->paramId == OMEGA_BUF || param->paramId == OMEGA_FUD || param->paramId == OMEGA_FUF)
+        omegaUni = YES;
+    else if (param->paramId == OMEGA_BED || param->paramId == OMEGA_BEF || param->paramId == OMEGA_FED || param->paramId == OMEGA_FEF)
+        omegaExp1 = YES;
+    else if (param->paramId == OMEGA_ED || param->paramId == OMEGA_EF)
+        omegaExp2 = YES;
+        
+    /* get minimum and maximum values for omega */
+    if (omegaUni == YES)
         {
-        p = t->allDownPass[i];
-        p->marked = NO;
-        p->d = 0.0;
+        minO = mp->ny98omega3Uni[0];
+        if (minO < value[1])
+            minO = value[1];
+        maxO = mp->ny98omega3Uni[1];
+        if (maxO > KAPPA_MAX)
+            maxO = KAPPA_MAX;
+        }
+    else if (omegaExp1 == YES || omegaExp2 == YES)
+        {
+        minO = value[1];
+        maxO = KAPPA_MAX;
         }
 
-    /* mark nodes in the root part of the tree, first mark a */
-    a->marked = YES;
-    /* then move down towards root taking constraints into account */
-    p = b;
-    while (p->isLocked == NO && p->anc->anc != NULL)
+    /* change value for omega */
+    ran = RandomNumber(seed);
+    if (maxO-minO < window)
         {
-        p->marked = YES;
-        p = p->anc;
+        window = maxO-minO;
         }
-    /* make sure sisters of last node are marked otherwise it will not be marked in the uppass */
-    p->left->marked = YES;
-    p->right->marked = YES;
-    /* finally move up, skip constraints and ancestral fossil */
-    for (i=t->nNodes-2; i>=0; i--)
+    newO = oldO + window * (ran - 0.5);
+    
+    /* check that new value is valid */
+    isValidO = NO;
+    do
         {
-        p = t->allDownPass[i];
-        if (p != u && p->marked == NO && p->anc->marked == YES && p->anc->isLocked == NO
-            && p->anc->nodeDepth > v->nodeDepth + minV && p->length > 0.0)
-            p->marked = YES;
+        if (newO < minO)
+            newO = 2* minO - newO;
+        else if (newO > maxO)
+            newO = 2 * maxO - newO;
+        else
+            isValidO = YES;
+        } while (isValidO == NO);
+
+    /* get proposal ratio */
+    *lnProposalRatio = 0.0;
+    
+    /* copy new omega value back */
+    value[2] = newO;
+
+    /* get prior ratio (part 2) */
+    if (omegaUni == YES)
+        {
+        *lnPriorRatio = 0.0;
+        }
+    else if (omegaExp1 == YES)
+        {
+        *lnPriorRatio = mp->ny98omega3Exp * (oldO - newO);
+        }
+    else if (omegaExp2 == YES)
+        {
+        x = LogOmegaPrior (value[0], value[1], newO);
+        y = LogOmegaPrior (value[0], value[1], oldO);
+        *lnPriorRatio = x - y;
         }
 
-    /* unmark nodes if the picked branch is 0 (ancestral fossil) */
-    if (v->length < TIME_MIN)
+    /* Set update flags for all partitions that share this omega. Note that the conditional
+       likelihood update flags have been set before we even call this function. */
+    for (i=0; i<param->nRelParts; i++)
+        TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
+
+    /* Set update flags for cijks for all affected partitions. */
+    for (i=0; i<param->nRelParts; i++)
+        modelSettings[param->relParts[i]].upDateCijk = YES;
+
+    return (NO_ERROR);
+}
+
+
+/*----------------------------------------------------------------
+|
+|   Move_OmegaPur: Change the nonysnonymous/synonymous rate ratio
+|      for purifying selection sites
+|
+----------------------------------------------------------------*/
+int Move_OmegaPur (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+{
+    int         i, isOPriorExp, isValidO;
+    MrBFlt      oldO, newO, window, minO, maxO, ran, *value, x, y;
+
+    /* get size of window, centered on current omega value */
+    window = mvp[0];
+
+    /* get old value of omega */
+    value = GetParamVals(param, chain, state[chain]);
+    newO = oldO = value[0];
+    
+    /* get minimum and maximum values for omega */
+    minO = 0.0;
+    maxO = value[1];
+    
+    /* get prior for omega */
+    if (param->paramId == OMEGA_BUD || param->paramId == OMEGA_BUF || param->paramId == OMEGA_BED || 
+        param->paramId == OMEGA_BEF || param->paramId == OMEGA_BFD || param->paramId == OMEGA_BFF) 
+        isOPriorExp = NO;
+    else
+        isOPriorExp = YES;
+
+    /* change value for omega */
+    ran = RandomNumber(seed);
+    if (maxO-minO < window)
         {
-        n = 0;
-        for (i=0; i<t->nNodes-1; i++)
-            {
-            p = t->allDownPass[i];
-            if (p->nodeDepth > v->nodeDepth - minV || p->anc->nodeDepth < v->nodeDepth + minV)
-                p->marked = NO;
-            if (p->marked == YES)
-                n++;
-            }
-        if (n < 2)  /* no new position to move */
-            {
-            abortMove = YES;
-            return (NO_ERROR);
-            }
+        window = maxO-minO;
         }
+    newO = oldO + window * (ran - 0.5);
     
-    /* find number of site patterns and modify randomly */
-    globalNSitesOfPat = numSitesOfPat + ((chainId[chain] % chainParams.numChains) * numCompressedChars) + m->compCharStart;
-    nSitesOfPat = (CLFlt *) SafeCalloc (numCompressedChars, sizeof(CLFlt));
-    if (!nSitesOfPat)
+    /* check that new value is valid */
+    isValidO = NO;
+    do
+        {
+        if (newO < minO)
+            newO = 2* minO - newO;
+        else if (newO > maxO)
+            newO = 2 * maxO - newO;
+        else
+            isValidO = YES;
+        } while (isValidO == NO);
+
+    /* get proposal ratio */
+    *lnProposalRatio = 0.0;
+    
+    /* copy new omega value back */
+    value[0] = newO;
+
+    /* get prior ratio (part 2) */
+    if (isOPriorExp == NO)
         {
-        MrBayesPrint ("%s   Problem allocating nSitesOfPat in Move_ParsSPRClock\n", spacer);
-        return (ERROR);
+        *lnPriorRatio = 0.0;
         }
-    for (i=0; i<numCompressedChars; i++)
+    else
         {
-        nSitesOfPat[i] = globalNSitesOfPat[i];
-        for (j=0; j<globalNSitesOfPat[i]; j++)
-            {
-            ran = RandomNumber(seed);
-            if (ran < decreaseProb)
-                nSitesOfPat[i]--;
-            else if (ran > 1.0 - increaseProb)
-                nSitesOfPat[i]++;
-            }
+        x = LogOmegaPrior (newO, value[1], value[2]);
+        y = LogOmegaPrior (oldO, value[1], value[2]);
+        *lnPriorRatio = x - y;
         }
 
-    /* cycle through the possibilities and record the parsimony length */
-    for (i=0; i<t->nNodes; i++)
-        {
-        p = t->allDownPass[i];
-        if (p->marked == NO)
-            continue;
-        /* find the parsimony length */
-        p->d = 0.0;
-        for (n=0; n<t->nRelParts; n++)
-            {
-            division = t->relParts[n];
-            
-            /* Find model settings */
-            m = &modelSettings[division];
+    /* Set update flags for all partitions that share this omega. Note that the conditional
+       likelihood update flags have been set before we even call this function. */
+    for (i=0; i<param->nRelParts; i++)
+        TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
 
-            /* find nStates and ratemult */
-            nStates = m->numModelStates;
-            if (m->dataType == STANDARD)
-                nStates = 2;
-            rateMult = GetRate(division, chain);
+    /* Set update flags for cijks for all affected partitions. */
+    for (i=0; i<param->nRelParts; i++)
+        modelSettings[param->relParts[i]].upDateCijk = YES;
 
-            /* find nSitesOfPat */
-            nSites = nSitesOfPat + m->compCharStart;
+    return (NO_ERROR);
+}
 
-            /* get division warp factor */
-            divFactor = - warpFactor * log((1.0/nStates) - exp(-nStates/(nStates-1)*v_typical*rateMult)/nStates);
 
-            /* find downpass parsimony sets for the node and its environment */
-            pP   = m->parsSets[p->index     ];
-            pA   = m->parsSets[p->anc->index];
-            pV   = m->parsSets[v->index     ];
-            
-            length = 0.0;
-            if (m->nParsIntsPerSite == 1)
-                {
-                for (j=0; j<m->numChars; j++)
-                    {
-                    y[0] = (pP[j] | pA[j]) & pV[j];
-                    if (y[0] == 0)
-                        length += nSites[j];
-                    }
-                }
-            else /* if (m->nParsIntsPerSite == 2) */
-                {
-                for (j=0; j<2*m->numChars; j+=2)
-                    {
-                    y[0] = (pP[j] | pA[j]) & pV[j];
-                    y[1] = (pP[j+1] | pA[j+1]) & pV[j+1];
-                    if ((y[0] | y[1]) == 0)
-                        length += nSites[j/2];
-                    }
-                }
-            p->d += divFactor * length;
-            }
+/*----------------------------------------------------------------
+|
+|   Move_ParsEraser1: This proposal mechanism changes the topology and
+|      branch lengths of an unrooted tree. A randomly chosen region of
+|      the tree is erased. Parsimony is used to guide the selection of
+|      a new topology for the erased part of the tree. The parsimony
+|      branch lengths are used to guide the proposal of new branch
+|      lengths. This variant (1) uses exhaustive enumeration.
+|
+|      Programmed by FR 2004-10-23--
+|
+----------------------------------------------------------------*/
+int Move_ParsEraser1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+{
+    int         i, j, isVPriorExp, nSubTerminals, nEmbeddedTrees;
+    MrBFlt      alphaPi, warp, minV, maxV, minP, maxP, brlensExp=0.0, newM, oldM, maxLen,
+                *brlensCur, *brlensNew, *parslensCur, *parslensNew,
+                curLength, newLength, lnJacobian, lnRandomRatio, alpha[2], prob[2],
+                minLenCur, minLenNew, f;
+    TreeNode    *p=NULL;
+    Tree        *t, *subtree, *subtree1, memTree[2];
+    ModelParams *mp;
+    ModelInfo   *m;
+    TreeInfo    tInfo;
+
+    /* set pointers to NULL */
+    subtree = subtree1 = NULL;
+    brlensCur = NULL;
+    for (i=0; i<2; i++)
+        {
+        memTree[i].allDownPass = NULL;
+        memTree[i].intDownPass = NULL;
+        memTree[i].nodes = NULL;
         }
+    tInfo.leaf = NULL;
 
-    /* find the min length and the sum for the forward move */
-    minLength = -1.0;
-    for (i=0; i<t->nNodes; i++)
+    /* Set alpha Pi for Dirichlet p generator */
+    alphaPi = mvp[0];
+    alphaPi = 0.05;
+    
+    /* Set the parsimony warp factor */
+    warp = mvp[1];
+    warp = 0.2;
+    
+    /* Set the number of terminals (nSubTerminals, column 3) in erased tree */
+    /* Erased Nodes => Leaves => Terminals => Embedded trees => Embedded histories => New trees
+                  2 => 3      => 4         => 2              => 2 = 2!             => 3 = 1*3
+                  3 => 4      => 5         => 5              => 6 = 3!             => 15 = 1*3*5
+                  4 => 5      => 6         => 14             => 24 = 4!            => 105 = 1*3*5*7
+                  5 => 6      => 7         => 42             => 120 = 5!           => 945 = 1*3*5*7*9
+                  etc               */  
+    nSubTerminals = (int) (RandomNumber(seed) * 4) + 4;
+    nSubTerminals = 7;
+
+    /* initialize log prior and log proposal probabilities */
+    *lnPriorRatio = *lnProposalRatio = 0.0;
+    
+    /* get tree */
+    t = GetTree (param, chain, state[chain]);
+
+    /* get model params */
+    mp = &modelParams[param->relParts[0]];
+    
+    /* max and min brlen */
+    if (param->subParams[0]->paramId == BRLENS_UNI)
         {
-        p = t->allDownPass[i];
-        if (p->marked == NO || p == a)
-            continue;
-        if (minLength < 0.0 || p->d < minLength)
-            minLength = p->d;
+        minV = mp->brlensUni[0] > BRLENS_MIN ? mp->brlensUni[0] : BRLENS_MIN;
+        maxV = mp->brlensUni[1];
+        isVPriorExp = NO;
         }
-    sum1 = 0.0;
-    for (i=0; i<t->nNodes; i++)
+    else
         {
-        p = t->allDownPass[i];
-        if (p->marked == YES && p != a)
-            sum1 += exp (minLength - p->d);
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        brlensExp = mp->brlensExp;
+        isVPriorExp = YES;
         }
+    minP = 3.0 * ((1.0 / 4.0) - ((1.0 / 4.0) * exp (-4.0 * minV / 3.0)));
+    maxP = 3.0 * ((1.0 / 4.0) - ((1.0 / 4.0) * exp (-4.0 * maxV / 3.0)));
 
-    /* generate a random uniform */
-    ran = RandomNumber(seed) * sum1;
-
-    /* select the appropriate reattachment point (not a!) */
-    cumulativeProb = 0.0;
-    for (i=0; i<t->nNodes; i++)
+    /* allocate some memory for this move */
+    brlensCur = (MrBFlt *) SafeMalloc (8 * nSubTerminals * sizeof (MrBFlt));
+    if (!brlensCur)
         {
-        p = t->allDownPass[i];
-        if (p->marked == YES && p != a)
-            {
-            c = p;
-            cumulativeProb += exp (minLength - p->d);
-            if (cumulativeProb > ran)
-                break;
-            }
+        MrBayesPrint ("%s   ERROR: Could not allocate brlensCur\n", spacer);
+        goto errorExit;
         }
+    brlensNew = brlensCur + 2*nSubTerminals;
+    parslensCur = brlensCur + 4 * nSubTerminals;
+    parslensNew = brlensCur + 6 * nSubTerminals;
 
-    /* calculate the proposal ratio */
-    (*lnProposalRatio) = c->d - minLength + log(sum1);
+    subtree = &memTree[0];
+    subtree->nNodes = 2 * nSubTerminals - 2;
+    subtree->nIntNodes = nSubTerminals - 2;
+    subtree->nodes = (TreeNode *) SafeCalloc (subtree->nNodes, sizeof (TreeNode));
+    subtree->allDownPass = (TreeNode **) SafeCalloc (subtree->nNodes, sizeof (TreeNode *));
+    subtree->intDownPass = (TreeNode **) SafeCalloc (subtree->nIntNodes, sizeof (TreeNode *));
+    if (!subtree->nodes || !subtree->intDownPass || !subtree->allDownPass)
+        {
+        MrBayesPrint ("%s   ERROR: Could not allocate subtree\n", spacer);
+        goto errorExit;
+        }
 
-    /* find the min length and the sum for the backward move */
-    minLength = -1.0;
-    for (i=0; i<t->nNodes; i++)
+    subtree1 = &memTree[1];
+    subtree1->nNodes = 2 * nSubTerminals - 2;
+    subtree1->nIntNodes = nSubTerminals - 2;
+    subtree1->nodes = (TreeNode *) SafeCalloc (subtree1->nNodes, sizeof (TreeNode));
+    subtree1->allDownPass = (TreeNode **) SafeCalloc (subtree1->nNodes, sizeof (TreeNode *));
+    subtree1->intDownPass = (TreeNode **) SafeCalloc (subtree1->nIntNodes, sizeof (TreeNode *));
+    if (!subtree1->nodes || !subtree1->intDownPass || !subtree1->allDownPass)
         {
-        p = t->allDownPass[i];
-        if (p->marked == NO || p == c)
-            continue;
-        if (minLength < 0.0 || p->d < minLength)
-            minLength = p->d;
+        MrBayesPrint ("%s   ERROR: Could not allocate subtree1\n", spacer);
+        goto errorExit;
         }
-    sum2 = 0.0;
-    for (i=0; i<t->nNodes; i++)
+
+    tInfo.leaf = (TreeNode **) SafeCalloc (t->nNodes, sizeof(TreeNode *));
+    if (!tInfo.leaf)
         {
-        p = t->allDownPass[i];
-        if (p->marked == YES && p != c)
-            sum2 += exp (minLength - p->d);
+        MrBayesPrint ("%s   ERROR: Could not allocate tInfo.leaf\n", spacer);
+        goto errorExit;
         }
-    
-    /* calculate the proposal ratio */
-    (*lnProposalRatio) += minLength - a->d - log(sum2);
+    tInfo.vertex = tInfo.leaf + t->nNodes - t->nIntNodes;
 
-    /* reattach u */
-    d = c->anc;
-    c->anc = u;
-    if (u->left == v)
-        u->right = c;
-    else
-        u->left = c;
-    u->anc = d;
-    if (d->left == c)
-        d->left = u;
-    else
-        d->right = u;
+    /* Select a random embedded subtree with nSubTerminals terminals */
+    if (GetRandomEmbeddedSubtree (t, nSubTerminals, seed, &nEmbeddedTrees) == ERROR)
+        {
+        MrBayesPrint ("%s   ERROR: Could not get subtree\n", spacer);
+        goto errorExit;
+        }
 
-    if (v->length > 0.0)  /* side branch, not anc fossil */
+    /* Set update flags (We'd better do it before the marked nodes disappear) */
+    for (i=0; i<t->nIntNodes; i++)
         {
-        if (c->nodeDepth > v->nodeDepth)
-            newBrlen = d->nodeDepth - c->nodeDepth - 2.0*minV;
-        else
-            newBrlen = d->nodeDepth - v->nodeDepth - 2.0*minV;
-        if (newBrlen <= 0.0)
+        p = t->intDownPass[i];
+        if (p->marked == YES)
             {
-            abortMove = YES;
-            free (nSitesOfPat);
-            return (NO_ERROR);
+            p->upDateCl = YES; 
+            p->upDateTi = YES;
             }
+        else if (p->left->upDateCl == YES || p->right->upDateCl == YES)
+                p->upDateCl = YES; 
+        }
 
-        /* adjust lengths */
-        u->nodeDepth = d->nodeDepth - minV - RandomNumber(seed) * newBrlen;
-        v->length = u->nodeDepth - v->nodeDepth;
-            
-        /* calculate proposal ratio for tree change */
-        (*lnProposalRatio) += log (newBrlen / oldBrlen);
+    /* Fill in subtrees */
+    CopyTreeToSubtree (t, subtree); 
+    CopyTreeToSubtree (t, subtree1);
+
+    /* Calculate downstates and upstate of root node of subtree */
+    GetParsDP (t, t->root->left, chain);
+    for (i=0; i<t->nIntNodes; i++)
+        {
+        p = t->intDownPass[i];
+        if (p->marked == YES && p->anc->marked == NO)
+            break;
         }
-    u->length = d->nodeDepth - u->nodeDepth;
-    c->length = u->nodeDepth - c->nodeDepth;
+    GetParsimonySubtreeRootstate (t, p->anc, chain);
+
+    /* Get parsimony length of current tree */
+    curLength = GetParsimonyLength (subtree, chain);
     
-    v3new = v->length;
-    v4 = c->length;
-    v5 = u->length;
+    /* Get the Markov and parsimony branch lengths of the current subtree */
+    GetParsimonyBrlens (subtree, chain, parslensCur);
+    for (i=0; i<subtree->nNodes-1; i++)
+        brlensCur[i] = subtree->allDownPass[i]->length;
 
-    /* reassign events for CPP and adjust prior and proposal ratios for relaxed clock models */
-    for (i=0; i<param->subParams[0]->nSubParams; i++)
-        {
-        subParm = param->subParams[0]->subParams[i];
-        if (subParm->paramType == P_CPPEVENTS)
-            {
-            nEvents = subParm->nEvents[2*chain+state[chain]];
-            position = subParm->position[2*chain+state[chain]];
-            rateMultiplier = subParm->rateMult[2*chain+state[chain]];
-            for (j=0; j<nEvents[c->index]; j++)
-                {
-                if (position[c->index][j] > v4 / (v4+v5))
-                    break;
-                }
-            n4 = j;
-            n5 = nEvents[c->index] - j;
-            nEvents[u->index] = n5;
-            if (n5 > 0)
-                {
-                position[u->index] = (MrBFlt *) SafeRealloc ((void *) position[u->index], n5 * sizeof (MrBFlt));
-                rateMultiplier[u->index] = (MrBFlt *) SafeRealloc ((void *) rateMultiplier[u->index], n5 * sizeof (MrBFlt));            
-                for (j=n4; j<nEvents[c->index]; j++)
-                    {
-                    position[u->index][j-n4] = (position[c->index][j] * (v4+v5) - v4) / v5;
-                    rateMultiplier[u->index][j-n4] = rateMultiplier[c->index][j];
-                    }
-                if (n4 > 0)
-                    {
-                    position[c->index] = (MrBFlt *) SafeRealloc ((void *) position[c->index], n4 * sizeof (MrBFlt));
-                    rateMultiplier[c->index] = (MrBFlt *) SafeRealloc ((void *) rateMultiplier[c->index], n4 * sizeof (MrBFlt));
-                    for (j=0; j<n4; j++)
-                        position[c->index][j] *= ((v4+v5) / v4);
-                    }
-                else
-                    {
-                    free (position[c->index]);
-                    free (rateMultiplier[c->index]);
-                    position[c->index] = rateMultiplier[c->index] = NULL;
-                    }
-                nEvents[c->index] = n4;
-                }
-            else
-                {
-                for (j=0; j<nEvents[c->index]; j++)
-                    position[c->index][j] *= ((v4+v5) / v4);
-                }
+    /* Calculate parsimony score of all trees relative to shortest tree (1.0) */
+    tInfo.totalScore = 0.0;
+    tInfo.stopScore = -1.0;
+    tInfo.minScore = curLength;
+    tInfo.warp = warp;
+    ExhaustiveParsimonySearch (subtree, chain, &tInfo);
+        
+    /* Choose one of these trees randomly based on its score */
+    tInfo.stopScore = RandomNumber(seed) * tInfo.totalScore;
+    tInfo.totalScore = 0.0;
+    ExhaustiveParsimonySearch (subtree1, chain, &tInfo);
+    /* ShowNodes (subtree1->root, 0 , NO); */
+    /* getchar(); */
 
-            /* adjust proposal ratio */
-            (*lnProposalRatio) += n3 * log (v3new / v3);
+    /* Get length of that tree */
 
-            /* adjust prior ratio */
-            lambda = *GetParamVals (modelSettings[subParm->relParts[0]].cppRate, chain, state[chain]);
-            (*lnPriorRatio) += lambda * (v3 - v3new);
+    newLength = GetParsimonyLength (subtree1, chain);
 
-            /* update effective branch lengths */
-            if (UpdateCppEvolLengths (subParm, a, chain) == ERROR)
-                {
-                abortMove = YES;
-                free (nSitesOfPat);
-                return (NO_ERROR);
-                }
+    /* Get the parsimony branch lengths of the new subtree */
+    GetParsimonyBrlens (subtree1, chain, parslensNew);
 
-            if (UpdateCppEvolLengths (subParm, u, chain) == ERROR)
-                {
-                abortMove = YES;
-                free (nSitesOfPat);
-                return (NO_ERROR);
-                }
-            }   /* end cpp events parameter */
-        else if ( subParm->paramType == P_TK02BRANCHRATES ||
-                 (subParm->paramType == P_MIXEDBRCHRATES && *GetParamIntVals(subParm, chain, state[chain]) == RCL_TK02))
+    /* Find the maximum length of a branch */
+    maxLen = 0.0;
+    for (i=0; i<t->nRelParts; i++)
+        {
+        j = t->relParts[i];
+        m = &modelSettings[j];
+        maxLen += m->numUncompressedChars;
+        }
+    
+    /* Find the Markov branch lengths of the new subtree */
+    /* Calculate Jacobian and prob ratio for the Dirichlet random number generator */
+    lnJacobian = lnRandomRatio = 0.0;
+    minLenCur = minLenNew = 0.0;
+    for (i=0; i<subtree1->nNodes-1; i++)
+        {
+        minLenCur += parslensCur[i];
+        minLenNew += parslensNew[i];
+        }
+    for (i=0; i<subtree1->nNodes-1; i++)
+        {
+        p = subtree1->allDownPass[i];
+        f = newLength / minLenNew;
+        alpha[0] = parslensNew[i] * f * alphaPi + 1.0;
+        alpha[1] = (maxLen - parslensNew[i] * f) * alphaPi + 1.0;
+        DirichletRandomVariable (alpha, prob, 2, seed);
+        if (prob[0] >= maxP || prob[0] <= minP)
             {
-            /* adjust prior ratio */
-            if (subParm->paramType == P_TK02BRANCHRATES)
-                nu = *GetParamVals (modelSettings[subParm->relParts[0]].tk02var, chain, state[chain]);
-            else
-                nu = *GetParamVals (modelSettings[subParm->relParts[0]].mixedvar, chain, state[chain]);
-            tk02Rate = GetParamVals (subParm, chain, state[chain]);
-            (*lnPriorRatio) -= LnProbTK02LogNormal(tk02Rate[u->anc->index], nu*(c->length+u->length), tk02Rate[c->index]);
-            (*lnPriorRatio) += LnProbTK02LogNormal(tk02Rate[c->anc->index], nu*c->length, tk02Rate[c->index]);
-            (*lnPriorRatio) += LnProbTK02LogNormal(tk02Rate[u->anc->index], nu*u->length, tk02Rate[u->index]);
-            if (v->length > 0.0)
-                (*lnPriorRatio) += LnProbTK02LogNormal(tk02Rate[v->anc->index], nu*v->length, tk02Rate[v->index]);
+            abortMove = YES;
+            return NO_ERROR;
+            }
 
-            /* adjust effective branch lengths */
-            brlens = GetParamSubVals (subParm, chain, state[chain]);
-            brlens[c->index] = c->length * (tk02Rate[c->index] + tk02Rate[c->anc->index]) / 2.0;
-            brlens[v->index] = v->length * (tk02Rate[v->index] + tk02Rate[v->anc->index]) / 2.0;
-            brlens[u->index] = u->length * (tk02Rate[u->index] + tk02Rate[u->anc->index]) / 2.0;
-            }   /* end tk02 branch rate parameter */
-        else if ( subParm->paramType == P_IGRBRANCHRATES ||
-                 (subParm->paramType == P_MIXEDBRCHRATES && *GetParamIntVals(subParm, chain, state[chain]) == RCL_IGR))
-            {
-            /* adjust prior ratio */
-            if (subParm->paramType == P_IGRBRANCHRATES)
-                igrvar = *GetParamVals (modelSettings[subParm->relParts[0]].igrvar, chain, state[chain]);
-            else
-                igrvar = *GetParamVals (modelSettings[subParm->relParts[0]].mixedvar, chain, state[chain]);
-            igrRate = GetParamVals (subParm, chain, state[chain]);
-            (*lnPriorRatio) -= LnProbGamma ((c->length+u->length)/igrvar, (c->length+u->length)/igrvar, igrRate[c->index]);
-            (*lnPriorRatio) += LnProbGamma (c->length/igrvar, c->length/igrvar, igrRate[c->index]);
-            (*lnPriorRatio) += LnProbGamma (u->length/igrvar, u->length/igrvar, igrRate[u->index]);
-            if (v->length > 0.0)
-                (*lnPriorRatio) += LnProbGamma (v->length/igrvar, v->length/igrvar, igrRate[v->index]);
+        p->length = (-3.0 / 4.0) * log (1.0 - 4.0 * prob[0] / 3.0);
+        lnJacobian += (-4.0 * brlensCur[i] / 3.0) - log (1.0 - 4.0 * prob[0] / 3.0);
+        lnRandomRatio -= log (pow (prob[0], alpha[0] - 1.0) * pow (prob[1], alpha[1] - 1.0));
+        f = curLength / minLenNew;
+        alpha[0] = parslensCur[i] * f * alphaPi + 1.0;
+        alpha[1] = (maxLen - parslensCur[i] * f) * alphaPi + 1.0;
+        prob[0] = 3.0 * ((1.0 / 4.0) - ((1.0 / 4.0) * exp (-4.0 * brlensCur[i] / 3.0)));
+        prob[1] = 1.0 - prob[0];
+        lnRandomRatio += log (pow (prob[0], alpha[0] - 1.0) * pow (prob[1], alpha[1] - 1.0));
+        }
 
-            /* adjust effective branch lengths */
-            brlens = GetParamSubVals (subParm, chain, state[chain]);
-            brlens[v->index] = igrRate[v->index] * v->length;
-            brlens[u->index] = igrRate[u->index] * u->length;
-            brlens[c->index] = igrRate[c->index] * c->length;
-            }   /* end igr branch rate parameter */
-        }   /* next subparameter */
+    /* Store the new Markov branch lengths */
+    for (i=0; i<subtree1->nNodes-1; i++)
+        brlensNew[i] = subtree1->allDownPass[i]->length;
 
-    /* set tiprobs update flags */
-    c->upDateTi = YES;
-    u->upDateTi = YES;
-    v->upDateTi = YES;
+    /* Calculate the proposal ratio */
+    (*lnProposalRatio) = lnJacobian + lnRandomRatio + log (warp/3.0) * (curLength - newLength) + log (1.0-warp) * (newLength - curLength);
 
-    /* set flags for update of cond likes down to root */
-    p = u;
-    while (p->anc != NULL)
+    /* Calculate the prior ratio */
+    if (isVPriorExp == YES)
         {
-        p->upDateCl = YES; 
-        p = p->anc;
+        newM = oldM = 0.0;
+        for (i=0; i<subtree->nNodes-1; i++)
+            {
+            oldM += brlensCur[i];
+            newM += brlensNew[i];
+            }
+        (*lnPriorRatio) += brlensExp * (oldM - newM);
         }
-    p = b;
-    while (p->anc != NULL)
+
+    /* Copy subtree into tree */
+    CopySubtreeToTree (subtree1, t);
+    /* ShowNodes (subtree1->root, 0, NO); */
+    /* ShowNodes (t->root, 0, NO); */
+
+    /* Update node sequences */
+    GetDownPass (t);
+    
+    /* correct for difference in number of embedded subtrees */
+    if (GetRandomEmbeddedSubtree (t, nSubTerminals, seed, &i) == ERROR)
         {
-        p->upDateCl = YES; 
-        p = p->anc;
+        MrBayesPrint ("%s   Could not count number of subtrees in Move_ParsEraser1\n", spacer);
+        goto errorExit;
         }
+    if (i != nEmbeddedTrees)
+        (*lnProposalRatio) += log ((MrBFlt) nEmbeddedTrees / (MrBFlt) i);
+
+    /* Free memory allocated for this move */
+    free (subtree->allDownPass);
+    free (subtree->intDownPass);
+    free (subtree->nodes);
+    free (subtree1->allDownPass);
+    free (subtree1->intDownPass);
+    free (subtree1->nodes);
+    free (brlensCur);
+    free (tInfo.leaf);
 
-    /* get down pass sequence */
-    GetDownPass (t);
+    return (NO_ERROR);
 
-    /* adjust prior ratio for clock tree */
-    if (LogClockTreePriorRatio (param, chain, &x) == ERROR)
-        {
-        free (nSitesOfPat);
-        return (ERROR);
-        }
-    (*lnPriorRatio) += x;
+errorExit:
 
-#   if defined (DEBUG_ParsSPRClock)
-    ShowNodes (t->root, 2, YES);
-    printf ("After\nProposal ratio: %f\n",(*lnProposalRatio));
-    printf ("v: %d  u: %d  a: %d  b: %d c: %d\n",v->index, u->index, a->index, b->index, c->index);
-    getchar();
-#   endif
+    free (subtree->allDownPass);
+    free (subtree->intDownPass);
+    free (subtree->nodes);
+    free (subtree1->allDownPass);
+    free (subtree1->intDownPass);
+    free (subtree1->nodes);
+    free (brlensCur);
+    free (tInfo.leaf);
 
-    free (nSitesOfPat);
-    return (NO_ERROR);
+    return (ERROR);
 }
 
 
-int Move_ParsTBR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+int Move_ParsSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
 {
-    /* Change topology and map branch lengths using TBR-type move biased according to parsimony scores,
-       controlled by a window defined by a certain node distance radius. */
-    
-    int         i, j, k, n, division, topologyHasChanged, nNeighbor, nRoot, nCrown, iA, jC, isVPriorExp;
-    BitsLong    *pA, *pB, *pC, *pD, y[2];
-    MrBFlt      x, minV, maxV, brlensExp=0.0, minLength=0.0, length=0.0, *parLength=NULL, prob, ran, tuning, warpFactor,
-                increaseProb, decreaseProb, v_typical, divFactor, nStates, rateMult, sum1, sum2, tempsum, tempc, tempy;
-    CLFlt       *nSites, *nSitesOfPat=NULL, *globalNSitesOfPat;
-    TreeNode    *p, *q, *r, *a, *b, *u, *v, *c, *d, *newB, *newA, *newC, **pRoot=NULL, **pCrown=NULL, *old=NULL, *tmp=NULL;
+    /* Change topology (and branch lengths) using SPR (asymmetric) biased according to parsimony scores. */
+
+    int         i, j, n, division, topologyHasChanged, isVPriorExp;
+    BitsLong    *pA, *pV, *pP, y[2];
+    MrBFlt      x, minV, maxV, brlensExp=0.0, minLength=0.0, length=0.0,
+                cumulativeProb, warpFactor, ran, tuning, increaseProb, decreaseProb,
+                divFactor, nStates, rateMult, v_typical, sum1, sum2, tempsum, tempc, tempy;
+    CLFlt       *nSitesOfPat, *nSites, *globalNSitesOfPat;
+    TreeNode    *p, *q, *a, *b, *u, *v, *c=NULL, *d;
     Tree        *t;
     ModelParams *mp;
-    ModelInfo   *m=NULL;
-    
+    ModelInfo   *m = NULL;
+
     warpFactor = mvp[0];                  /* tuning parameter determining how heavily to weight according to parsimony scores */
     increaseProb = decreaseProb = mvp[1]; /* reweighting probabilities */
     v_typical = mvp[2];                   /* typical branch length for conversion of parsimony score to log prob ratio */
-    tuning = mvp[3];                   /* multiplier tuning parameter */
-    nNeighbor = (int)mvp[4];              /* distance to move picked branch in root and crown part */
+    tuning = mvp[3];                      /* multiplier tuning parameter */
 
     (*lnProposalRatio) = (*lnPriorRatio) = 0.0;
-    
+
     /* get model params and model info */
     mp = &modelParams[param->relParts[0]];
     m = &modelSettings[param->relParts[0]];
     
     /* get tree */
     t = GetTree (param, chain, state[chain]);
-    
+
     /* max and min brlen */
     if (param->subParams[0]->paramId == BRLENS_UNI)
         {
         minV = mp->brlensUni[0] > BRLENS_MIN ? mp->brlensUni[0] : BRLENS_MIN;
-        maxV = mp->brlensUni[1];
+        maxV = mp->brlensUni[1] < BRLENS_MAX ? mp->brlensUni[1] : BRLENS_MAX;
         isVPriorExp = NO;
         }
     else if (param->subParams[0]->paramId == BRLENS_GamDir)
@@ -11602,6 +8954,13 @@ int Move_ParsTBR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
     /* Dirichlet or twoExp prior */
     if (isVPriorExp > 1)
         (*lnPriorRatio) = -LogDirPrior(t, mp, isVPriorExp);
+
+#   if defined (DEBUG_ParsSPR)
+    // WriteTopologyToFile (stdout, t->root->left, t->isRooted);  fprintf (stdout, ";\t");
+    printf ("Before:\n");
+    ShowNodes (t->root, 2, YES);
+    getchar();
+#   endif
     
     /* set topologyHasChanged to NO */
     topologyHasChanged = NO;
@@ -11610,114 +8969,76 @@ int Move_ParsTBR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
     for (i=0; i<t->nNodes; i++)
         {
         p = t->allDownPass[i];
-        p->x = 0;
         p->marked = NO;
+        p->d = 0;
         }
 
-    /* pick an internal branch */
-    do  {
-        p = t->intDownPass[(int)(RandomNumber(seed)*(t->nIntNodes-1))];
+    /* pick a random branch */
+    p = t->allDownPass[(int)(RandomNumber(seed) * (t->nNodes -2))];
+    q = p->anc->right;
+    if (q == p)
         q = p->anc->left;
-        if (q == p)  q = p->anc->right;
-        i = j = 0;
-        if (q->isLocked == YES || q->left == NULL)
-            i++;
-        if (p->anc->isLocked == YES || p->anc->anc->anc == NULL)
-            i++;
-        if (p->left->isLocked == YES || p->left->left == NULL)
-            j++;
-        if (p->right->isLocked == YES || p->right->left == NULL)
-            j++;
+    if ((p->anc->anc->anc == NULL || p->anc->isLocked == YES) && (q->left == NULL || q->isLocked == YES))
+        {
+        abortMove = YES;
+        return (NO_ERROR);
         }
-    while (i == 2 && j == 2);
-    
+        
     /* set up pointers for nodes around the picked branch */
-    v = p;            u = p->anc;
-    c = p->left;      d = p->right;
-    if (u->left == v) a = u->right;
-    else              a = u->left;
+    v = p;
+    u = p->anc;
+    if (u->left == v)
+        a = u->right;
+    else
+        a = u->left;
     b = u->anc;
-    /* clip root part of tree */
+
+    /* clip tree */
     a->anc = b;
-    if (b->left == u) b->left = a;
-    else              b->right = a;
-    /* clip crown part of tree */
-    c->anc = d;
-    d->anc = c;
-    /* should never change u, v, a, b, c, d pointers */
+    if (b->left == u)
+        b->left = a;
+    else
+        b->right = a;
 
-    /* mark nodes nNeighbor away in root (negative) and crown (positive) respecting constraints */
-    /* first move down towards root */
-    nRoot = nCrown = 0;
+    /* get final parsimony states for the root part */
+    GetParsDP (t, t->root->left, chain);
+    GetParsFP (t, t->root->left, chain);
+
+    /* get downpass parsimony states for the crown part */
+    GetParsDP (t, v, chain);
+
+    /* mark all nodes in the root part of the tree, taking constraints into account */
+    /* first mark a */
+    a->marked = YES;
+    /* then move down towards root */
     if (u->isLocked == NO)
         {
-        p = a; q = b; n = 0;
-        while (q->anc != NULL)
+        p = a->anc;
+        while (p->anc != NULL)
             {
-            q->marked = YES;
-            q->x = n;    // temporary, for MarkDistance below
-            if (q->left == p)
-                MarkDistance(q->right, YES, nNeighbor, &nRoot);
-            else
-                MarkDistance(q->left,  YES, nNeighbor, &nRoot);
-            q->x = --n;  // final
-            nRoot++;
-            if (q->isLocked == YES || abs(q->x) >= nNeighbor)
+            p->marked = YES;
+            if (p->isLocked == YES)
                 break;
-            p = q; q = q->anc;
+            p = p->anc;
             }
         }
-    /* then move up in root part */
-    a->marked = YES; nRoot++;
-    if (a->isLocked == NO)
-        {
-        MarkDistance(a->left,  YES, nNeighbor, &nRoot);
-        MarkDistance(a->right, YES, nNeighbor, &nRoot);
-        }
-    /* finally in crown part */
-    c->marked = YES; nCrown++;
-    if (c->isLocked == NO)
-        {
-        MarkDistance(c->left,  NO, nNeighbor, &nCrown);
-        MarkDistance(c->right, NO, nNeighbor, &nCrown);
-        }
-    if (d->isLocked == NO)
-        {
-        MarkDistance(d->left,  NO, nNeighbor, &nCrown);
-        MarkDistance(d->right, NO, nNeighbor, &nCrown);
-        }
 
-    /* need to alloc a matrix for parsimony lengths, an array of pointers to crown part,
-       and an array of pointers to root part. */
-    parLength = (MrBFlt *) SafeCalloc (nRoot*nCrown, sizeof(MrBFlt));
-    pRoot  = (TreeNode **) SafeCalloc(nRoot,  sizeof(TreeNode *));
-    pCrown = (TreeNode **) SafeCalloc(nCrown, sizeof(TreeNode *));
-    if (!parLength || !pRoot || !pCrown)  goto errorExit;
-    /* starting position */
-    pRoot[0] = a; pCrown[0] = c;
-    for (i=j=1, n=t->nNodes-2; n>=0; n--)
-        {  /* and the rest */
-        p = t->allDownPass[n];
-        if (p->marked == YES && p->x < 0)
-            pRoot[i++] = p;
-        if (p->marked == YES && p->x > 0)
-            pCrown[j++] = p;
+    /* finally move up */
+    for (i=t->nNodes-2; i>=0; i--)
+        {
+        p = t->allDownPass[i];
+        if (p->marked == NO && p->anc->marked == YES && p->anc->isLocked == NO && p != u)
+            p->marked = YES;
         }
-    assert(i==nRoot && j==nCrown);
-
-    /* get final parsimony state sets for the root part */
-    GetParsDP (t, t->root->left, chain);
-    GetParsFP (t, t->root->left, chain);
-    /* get final parsimony state sets for the crown part */
-    GetParsDP (t, c, chain);
-    GetParsDP (t, d, chain);
-    GetParsFP (t, c, chain);
-    GetParsFP (t, d, chain);
 
     /* find number of site patterns and modify randomly */
     globalNSitesOfPat = numSitesOfPat + (chainId[chain] % chainParams.numChains) * numCompressedChars + m->compCharStart;
     nSitesOfPat = (CLFlt *) SafeCalloc (numCompressedChars, sizeof(CLFlt));
-    if (!nSitesOfPat)  goto errorExit;
+    if (!nSitesOfPat)
+        {
+        MrBayesPrint ("%s   Problem allocating nSitesOfPat in Move_ParsSPR\n", spacer);
+        return (ERROR);
+        }
     for (i=0; i<numCompressedChars; i++)
         {
         nSitesOfPat[i] = globalNSitesOfPat[i];
@@ -11732,278 +9053,211 @@ int Move_ParsTBR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
         }
 
     /* cycle through the possibilities and record the parsimony length */
-    for (j=0; j<nCrown; j++)
+    for (i=0; i<t->nNodes; i++)
         {
-        for (i=0; i<nRoot; i++)
+        p = t->allDownPass[i];
+        if (p->marked == NO)
+            continue;
+        /* find the parsimony length */
+        p->d = 0.0;
+        for (n=0; n<t->nRelParts; n++)
             {
-            parLength[i+j*nRoot] = 0.0;
-            for (n=0; n<t->nRelParts; n++)
+            division = t->relParts[n];
+            
+            /* Find model settings */
+            m = &modelSettings[division];
+
+            /* find nSitesOfPat */
+            nSites = nSitesOfPat + m->compCharStart;
+
+            /* find downpass parsimony sets for the node and its environment */
+            pP   = m->parsSets[p->index];
+            pA   = m->parsSets[p->anc->index];
+            pV   = m->parsSets[v->index];
+        
+            length = 0.0;
+            if (m->nParsIntsPerSite == 1)
                 {
-                division = t->relParts[n];
-                
-                /* Find model settings */
-                m = &modelSettings[division];
-                
-                /* find nStates and ratemult */
-                nStates = m->numModelStates;
-                if (m->dataType == STANDARD)
-                    nStates = 2;
-                rateMult = GetRate(division, chain);
-                
-                /* find nSitesOfPat */
-                nSites = nSitesOfPat + m->compCharStart;
-                
-                /* get division warp factor (prop. to prob. of change) */
-                divFactor = - warpFactor * log((1.0/nStates) - exp(-nStates/(nStates-1)*v_typical*rateMult)/nStates);
-                
-                /* find downpass parsimony sets for the potential new connection nodes and their environment */
-                pA = m->parsSets[pRoot[i]->index];
-                pB = m->parsSets[pRoot[i]->anc->index];
-                pC = m->parsSets[pCrown[j]->index];
-                pD = m->parsSets[pCrown[j]->anc->index];
-                    
-                length = 0.0;
-                if (m->nParsIntsPerSite == 1)
+                for (j=0; j<m->numChars; j++)
                     {
-                    for (k=0; k<m->numChars; k++)
-                        {
-                        y[0] = (pC[k] | pD[k]) & (pA[k] | pB[k]);
-                        if (y[0] == 0)
-                            length += nSites[k];
-                        }
+                    y[0] = (pP[j] | pA[j]) & pV[j];
+                    if (y[0] == 0)
+                        length += nSites[j];
                     }
-                else /* if (m->nParsIntsPerSite == 2) */
+                }
+            else /* if (m->nParsIntsPerSite == 2) */
+                {
+                for (j=0; j<2*m->numChars; j+=2)
                     {
-                    for (k=0; k<2*m->numChars; k+=2)
-                        {
-                        y[0] = (pC[k] | pD[k]) & (pA[k] | pB[k]);
-                        y[1] = (pC[k+1] | pD[k+1]) & (pA[k+1] | pB[k+1]);;
-                        if ((y[0] | y[1]) == 0)
-                            length += nSites[k/2];
-                        }
+                    y[0] = (pP[j] | pA[j]) & pV[j];
+                    y[1] = (pP[j+1] | pA[j+1]) & pV[j+1];
+                    if ((y[0] | y[1]) == 0)
+                        length += nSites[j/2];
                     }
-                parLength[i+j*nRoot] += divFactor * length;
                 }
+
+            /* find nStates and ratemult */
+            nStates = m->numModelStates;
+            if (m->dataType == STANDARD)
+                nStates = 2;
+            rateMult = GetRate(division, chain);
+
+            /* get division warp factor */
+            divFactor = - warpFactor * log((1.0/nStates) - exp(-nStates/(nStates-1)*v_typical*rateMult)/nStates);
+
+            p->d += divFactor * length;
             }
         }
 
-    /* find the min length and the sum for the forward move */
+    /* find the min length and the sum for the forward move */    
     minLength = -1.0;
-    for (j=0; j<nCrown; j++)
-        for (i=0; i<nRoot; i++)
-            {
-            if (i == 0 && j == 0)  // exclude original position
-                continue;
-            if (minLength > parLength[i+j*nRoot] || minLength < 0.0)
-                minLength = parLength[i+j*nRoot];
-            }
+    for (i=0; i<t->nNodes; i++)
+        {
+        p = t->allDownPass[i];
+        if (p->marked == NO || p == a)
+            continue;
+        if (minLength < 0.0 || p->d < minLength)
+            minLength = p->d;
+        }
     sum1 = 0.0; tempc = 0.0;
-    for (j=0; j<nCrown; j++)
-        for (i=0; i<nRoot; i++)
+    for (i=0; i<t->nNodes; i++)
+        {
+        p = t->allDownPass[i];
+        if (p->marked == YES && p != a)
             {
-            if (i == 0 && j == 0)  // exclude original position
-                continue;
             /* Kahan summation to reduce numerical error */
-            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
-            tempsum = sum1 + tempy;  tempc = (tempsum - sum1) - tempy;
+            tempy = exp (minLength - p->d) - tempc;
+            tempsum = sum1 + tempy;
+            tempc = (tempsum - sum1) - tempy;
             sum1 = tempsum;
-            // sum1 += exp(minLength - parLength[i+j*nRoot]);
-            // printf("%d %d %lf\n", i, j, exp(minLength - parLength[i+j*nRoot]));
             }
-
+        }
+    
     /* generate a random uniform */
     ran = RandomNumber(seed) * sum1;
 
     /* select the appropriate reattachment point */
-    newA = a; newC = c;
-    prob = 0.0; tempc = 0.0;
-    for (j=0; j<nCrown; j++)
-        for (i=0; i<nRoot; i++)
+    cumulativeProb = 0.0; tempc = 0.0;
+    for (i=0; i<t->nNodes; i++)
+        {
+        p = t->allDownPass[i];
+        if (p->marked == YES && p != a)
             {
-            if (i == 0 && j == 0)  // exclude original position
-                continue;
-            // prob += exp (minLength - parLength[i+j*nRoot]);
+            c = p;
             /* Kahan summation to reduce numerical error */
-            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
-            tempsum = prob + tempy;  tempc = (tempsum - prob) - tempy;
-            prob = tempsum;
-            if (prob > ran) {
-                /* proposed new attaching position */
-                newA = pRoot[i];
-                newC = pCrown[j];
-                goto outLoop;
-                }
+            tempy = exp (minLength - p->d) - tempc;
+            tempsum = cumulativeProb + tempy;
+            tempc = (tempsum - cumulativeProb) - tempy;
+            cumulativeProb = tempsum;
+            if (cumulativeProb > ran)
+                break;
             }
-outLoop:;
-    iA = i; jC = j;
+        }
 
     /* calculate the proposal ratio */
-    (*lnProposalRatio) = parLength[i+j*nRoot] - minLength + log(sum1);
+    (*lnProposalRatio) = c->d - minLength + log(sum1);
 
     /* find the min length and the sum for the backward move */
     minLength = -1.0;
-    for (j=0; j<nCrown; j++)
-        for (i=0; i<nRoot; i++)
-            {
-            if (i == iA && j == jC)  // exclude new position
-                continue;
-            if (minLength > parLength[i+j*nRoot] || minLength < 0.0)
-                minLength = parLength[i+j*nRoot];
-            }
+    for (i=0; i<t->nNodes; i++)
+        {
+        p = t->allDownPass[i];
+        if (p->marked == NO || p == c)
+            continue;
+        if (minLength < 0.0 || p->d < minLength)
+            minLength = p->d;
+        }
     sum2 = 0.0; tempc = 0.0;
-    for (j=0; j<nCrown; j++)
-        for (i=0; i<nRoot; i++)
+    for (i=0; i<t->nNodes; i++)
+        {
+        p = t->allDownPass[i];
+        if (p->marked == YES && p != c)
             {
-            if (i == iA && j == jC)  // exclude new position
-                continue;
             /* Kahan summation to reduce numerical error */
-            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
-            tempsum = sum2 + tempy;  tempc = (tempsum - sum2) - tempy;
+            tempy = exp (minLength - p->d) - tempc;
+            tempsum = sum2 + tempy;
+            tempc = (tempsum - sum2) - tempy;
             sum2 = tempsum;
-            // sum2 += exp (minLength - parLength[i+j*nRoot]);
-            // printf("%d %d %lf\n", i, j, exp(minLength - parLength[i+j*nRoot]));
             }
+        }
 
     /* calculate the proposal ratio */
-    (*lnProposalRatio) += minLength - parLength[0] - log(sum2);
+    (*lnProposalRatio) += minLength - a->d - log(sum2);
 
-    /* reattach the root part */
-    newB = newA->anc;
-    newA->anc = u;
+    /* reattach */
+    d = c->anc;
+    c->anc = u;
     if (u->left == v)
-        u->right = newA;
+        u->right = c;
     else
-        u->left = newA;
-    u->anc = newB;
-    if (newB->left == newA)
-        newB->left = u;
+        u->left = c;
+    if (d->left == c)
+        d->left = u;
     else
-        newB->right = u;
+        d->right = u;
+    u->anc = d;
 
-    /* transfer lock and reassign branch lengths, if necessary */
-    if (newA != a)
+    /* c cannot be a, as a is skiped in the selection for reattachment point */
+    assert (c != a);
+    /* transfer lock if necessary */
+    /* if u is locked, then we have moved upwards and need to leave the u lock behind */
+    if (u->isLocked == YES)
         {
-        /* if u is locked, then we have moved upwards and need to leave the u lock behind */
-        if (u->isLocked == YES)
-            {
-            u->isLocked = NO;
-            a->isLocked = YES;
-            a->lockID = u->lockID;
-            u->lockID = -1;
-            }
+        u->isLocked = NO;
+        a->isLocked = YES;
+        a->lockID = u->lockID;
+        u->lockID = -1;
+        }
+    /* if c is on root path and locked, we need to transfer lock to u */
+    p = b;
+    while (p != NULL)
+        {
+        if (p == c)
+            break;
+        p = p->anc;
+        }
+    if (p == c && c->isLocked == YES)
+        {
+        u->isLocked = YES;
+        u->lockID = c->lockID;
+        c->isLocked = NO;
+        c->lockID = -1;
+        }
 
-        p = newA;
-        while (p->anc != NULL)
-            {
-            if (p == a) break;
-            p = p->anc;
-            }
+    /* reassign branch lengths */
+    p = c;
+    while (p->anc->anc != NULL)
+        {
         if (p == a)
-            {
-            /* newA is descendant to a so move a->length not u->length */
-            x = u->length;
-            u->length = a->length;
-            a->length = x;
-            }
-
-        p = b;
-        while (p->anc != NULL)
-            {
-            if (p == newA) break;
-            p = p->anc;
-            }
-        if (p == newA)
-            {
-            /* newA is ancestor to a so insert above instead of below */
-            x = newA->length;
-            newA->length = u->length;
-            u->length = x;
-            /* newA is on root path and locked, we need to transfer lock to u */
-            if (newA->isLocked == YES) {
-                u->isLocked = YES;
-                u->lockID = newA->lockID;
-                newA->isLocked = NO;
-                newA->lockID = -1;
-                }
-            }
-            
-        /* hit u length with multiplier */
-        x = u->length * exp(tuning * (RandomNumber(seed) - 0.5));
-        while (x < minV || x > maxV)
-            {
-            if (x < minV)
-                x = minV * minV / x;
-            else if (x > maxV)
-                x = maxV * maxV / x;
-            }
-        /* calculate proposal and prior ratio based on length modification */
-        (*lnProposalRatio) += log (x / u->length);
-        if (isVPriorExp == YES)
-            (*lnPriorRatio) += brlensExp * (u->length - x);
-        u->length = x;
-
-        /* set tiprobs update flags */
-        u->upDateTi = YES;
-        newA->upDateTi = YES;
-        a->upDateTi = YES;
+            break;
+        p = p->anc;
+        }
+    if (p == a)
+        {
+        /* c is descendant to a so move a->length and not u->length */
+        x = u->length;
+        u->length = a->length;
+        a->length = x;
+        }
+    p = a;
+    while (p->anc->anc != NULL)
+        {
+        if (p == c)
+            break;
+        p = p->anc;
         }
-    
-    /* alloc temp tree nodes */
-    old = (TreeNode *) SafeCalloc (1, sizeof (TreeNode));
-    tmp = (TreeNode *) SafeCalloc (1, sizeof (TreeNode));
-    if (old == NULL || tmp == NULL)  goto errorExit;
-        
-    r = newC;
-    q = newB = newC->anc;
-    if (newC != c)  // crown part has changed
+    if (p == c)
         {
-        /* rotate nodes from newC to c or d (whichever is closest) */
-        CopyTreeNodes (old, r, 0);
-        while (r != c && r != d)
-            {
-            p = q->anc;
-            /* rotate pointers of q */
-            if (q->left == r)
-                q->left = p;
-            else
-                q->right = p;
-            q->anc = r;
-            /* swap q and old */
-            CopyTreeNodes (tmp, q, 0);
-            CopyTreeNodes (q, old, 0);
-            CopyTreeNodes (old, tmp, 0);
-            /* make sure we get q and r initialized for next round */
-            r = q;
-            q = p;
-            }
-        CopyTreeNodes (newC->anc, old, 0);
-        
-        /* hit newB length with multiplier */
-        x = newB->length * exp(tuning * (RandomNumber(seed) - 0.5));
-        while (x < minV || x > maxV)
-            {
-            if (x < minV)
-                x = minV * minV / x;
-            else if (x > maxV)
-                x = maxV * maxV / x;
-            }
-        /* calculate proposal and prior ratio based on length modification */
-        (*lnProposalRatio) += log (x / newB->length);
-        if (isVPriorExp == YES)
-            (*lnPriorRatio) += brlensExp * (newB->length - x);
-        newB->length = x;
-        newB->upDateTi = YES;
+        /* c is ancestor to a so insert above instead of below */
+        x = c->length;
+        c->length = u->length;
+        u->length = x;
         }
-    
-    /* reattach the crown part */
-    v->left = newC;
-    v->right = newB;
-    newC->anc = newB->anc = v;
-    
+
     topologyHasChanged = YES;
-    
-    /* hit v length with multiplier */
-    x = v->length * exp(tuning * (RandomNumber(seed) - 0.5));
+
+    /* hit c length with multiplier (a and u dealt with below) */
+    x = c->length * exp(tuning * (RandomNumber(seed) - 0.5));
     while (x < minV || x > maxV)
         {
         if (x < minV)
@@ -12012,38 +9266,62 @@ outLoop:;
             x = maxV * maxV / x;
         }
     /* calculate proposal and prior ratio based on length modification */
-    (*lnProposalRatio) += log (x / v->length);
+    (*lnProposalRatio) += log (x / c->length);
     if (isVPriorExp == YES)
-        (*lnPriorRatio) += brlensExp * (v->length - x);
-    v->length = x;
-    v->upDateTi = YES;
- 
-    /* set flags for update of cond likes */
-    p = u;
-    while (p->anc != NULL)
+        (*lnPriorRatio) += brlensExp * (c->length - x);
+    c->length = x;
+    
+    /* hit a length with multiplier */
+    x = a->length * exp(tuning * (RandomNumber(seed) - 0.5));
+    while (x < minV || x > maxV)
         {
-        p->upDateCl = YES;
-        p = p->anc;
+        if (x < minV)
+            x = minV * minV / x;
+        else if (x > maxV)
+            x = maxV * maxV / x;
         }
-    p = b;
-    while (p->anc != NULL)
+    /* calculate proposal and prior ratio based on length modification */
+    (*lnProposalRatio) += log (x / a->length);
+    if (isVPriorExp == YES)
+        (*lnPriorRatio) += brlensExp * (a->length - x);
+    a->length = x;
+
+    /* hit u length with multiplier */
+    x = u->length * exp(tuning * (RandomNumber(seed) - 0.5));
+    while (x < minV || x > maxV)
         {
-        p->upDateCl = YES;
-        p = p->anc;
+        if (x < minV)
+            x = minV * minV / x;
+        else if (x > maxV)
+            x = maxV * maxV / x;
         }
-    p = newC;
+    /* calculate proposal and prior ratio based on length modification */
+    (*lnProposalRatio) += log (x / u->length);
+    if (isVPriorExp == YES)
+        (*lnPriorRatio) += brlensExp * (u->length - x);
+    u->length = x;
+
+    /* set tiprobs update flags */
+    a->upDateTi = YES;
+    u->upDateTi = YES;
+    c->upDateTi = YES;  /* could be same as a but that does not matter */
+
+    /* set flags for update of cond likes from u and down to root */
+    p = u;
     while (p->anc != NULL)
         {
         p->upDateCl = YES;
         p = p->anc;
         }
-    p = r;
-    while (p->anc != NULL)
+
+    /* set flags for update of cond likes from b and down to root */
+    p = b;
+    while (p->anc != NULL && p->upDateCl == NO)
         {
-        p->upDateCl = YES;
+        p->upDateCl = YES; 
         p = p->anc;
         }
-    
+
     /* get down pass sequence if tree topology has changed */
     if (topologyHasChanged == YES)
         {
@@ -12054,2056 +9332,2459 @@ outLoop:;
     if (isVPriorExp > 1)
         (*lnPriorRatio) += LogDirPrior(t, mp, isVPriorExp);
     
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-    gNodeMoves = nRootNodes;
+#   if defined (DEBUG_ParsSPR)
+    // WriteTopologyToFile (stdout, t->root->left, t->isRooted);
+    // fprintf (stdout, ";\t");  fprintf (stdout, "%lf\n", *lnProposalRatio);
+    printf ("After:\n");
+    ShowNodes (t->root, 2, YES);
+    getchar();
+    printf ("Proposal ratio: %f\n",(*lnProposalRatio));
+    printf ("v: %d  u: %d  a: %d  b: %d\n",v->index, u->index, a->index, b->index);
+    printf ("Has topology changed? %d\n",topologyHasChanged);
+    getchar();
 #   endif
-    
-    /* free up local memory */
-    free (parLength); free (pRoot); free (pCrown);
-    free (nSitesOfPat); free (old); free (tmp);
-
-    return (NO_ERROR);
 
-errorExit:
-    MrBayesPrint ("%s   Problem allocating memory in Move_ParsTBR\n", spacer);
-    free (parLength); free (pRoot); free (pCrown);
-    free (nSitesOfPat); free (old); free (tmp);
+    free (nSitesOfPat);
 
-    return (ERROR);
+    return (NO_ERROR);
 }
 
 
-int Move_Pinvar (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+int Move_ParsSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
 {
-    /* change proportion of invariable sites (pInvar) */
-
-    int             i, c, isValidP, *rateCat, nGammaCats;
-    MrBFlt          oldP, newP, window, minP, maxP, ran, lnInvarRatio, lnVarRatio;
-    CLFlt           *nSitesOfPat;
-    ModelParams     *mp;
-    ModelInfo       *m;
-
-    /* get size of window, centered on current pInvar value */
-    window = mvp[0];
-
-    /* get model params */
+    /* Change topology (and branch lengths) using SPR (symmetric) biased according to parsimony scores,
+       controlled by a window defined by a certain node distance radius. Note: w = e^{-S} */
+    
+    int         i, j, k, n, division, topologyHasChanged, moveInRoot, nNeighbor, nRoot, nCrown, iA, jC, isVPriorExp;
+    BitsLong    *pA, *pB, *pP, *pC, *pD, y[2];
+    MrBFlt      x, minV, maxV, brlensExp=0.0, minLength=0.0, length=0.0, *parLength=NULL, prob, ran, tuning, warpFactor,
+                sum1, sum2, tempsum, tempc, tempy;
+    CLFlt       *nSites, *nSitesOfPat=NULL, *globalNSitesOfPat;
+    TreeNode    *p, *q, *r, *a, *b, *u, *v, *c, *d, *newB, *newA, *newC, **pRoot=NULL, **pCrown=NULL;
+    Tree        *t;
+    ModelParams *mp;
+    ModelInfo   *m=NULL;
+    
+    warpFactor = mvp[0];                  /* tuning parameter determining how heavily to weight according to parsimony scores */
+//  increaseProb = decreaseProb = mvp[1]; /* reweighting probabilities */
+//  v_typical = mvp[2];                   /* typical branch length for conversion of parsimony score to log prob ratio */
+    tuning = mvp[3];                      /* multiplier tuning parameter */
+    nNeighbor = (int)mvp[4];              /* distance to move picked branch in root and crown part */
+    
+    (*lnProposalRatio) = (*lnPriorRatio) = 0.0;
+    
+    /* get model params and model info */
     mp = &modelParams[param->relParts[0]];
+    m = &modelSettings[param->relParts[0]];
     
-    /* get minimum and maximum values for pInvar */
-    minP = mp->pInvarUni[0];
-    maxP = mp->pInvarUni[1];
+    /* get tree */
+    t = GetTree (param, chain, state[chain]);
+    
+    /* max and min brlen */
+    if (param->subParams[0]->paramId == BRLENS_UNI)
+        {
+        minV = mp->brlensUni[0] > BRLENS_MIN ? mp->brlensUni[0] : BRLENS_MIN;
+        maxV = mp->brlensUni[1] < BRLENS_MAX ? mp->brlensUni[1] : BRLENS_MAX;
+        isVPriorExp = NO;
+        }
+    else if (param->subParams[0]->paramId == BRLENS_GamDir)
+        {
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        isVPriorExp = 2;
+        }
+    else if (param->subParams[0]->paramId == BRLENS_iGmDir)
+        {
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        isVPriorExp = 3;
+        }
+    else if (param->subParams[0]->paramId == BRLENS_twoExp)
+        {
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        isVPriorExp = 4;
+        }
+    else
+        {
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        brlensExp = mp->brlensExp;
+        isVPriorExp = YES;
+        }
 
-    /* get old value of pInvar */
-    newP = oldP = *GetParamVals(param, chain, state[chain]);
+    /* Dirichlet or twoExp prior */
+    if (isVPriorExp > 1)
+        (*lnPriorRatio) = -LogDirPrior(t, mp, isVPriorExp);
+    
+    /* set topologyHasChanged to NO */
+    topologyHasChanged = NO;
+    
+    /* pick a random branch */
+    do  {
+        p = t->allDownPass[(int)(RandomNumber(seed) * (t->nNodes -1))];
+        q = p->anc->right;  if (q == p) q = p->anc->left;
+        i = j = 0;
+        if (p->left == NULL)
+            j = 2;
+        if (p->anc->anc == NULL)
+            i = 2;
+        if (p->anc->anc != NULL && (p->anc->isLocked == YES || p->anc->anc->anc == NULL))
+            i++;
+        if (p->anc->anc != NULL && (q->isLocked == YES || q->left == NULL))
+            i++;
+        if (p->left != NULL && (p->left->isLocked == YES || p->left->left == NULL))
+            j++;
+        if (p->left != NULL && (p->right->isLocked == YES || p->right->left == NULL))
+            j++;
+        } while (i == 2 && j == 2);
+    
+    /* determine moving direction */
+    if (j == 2)
+        moveInRoot = YES;
+    else if (i == 2)
+        moveInRoot = NO;
+    else if (RandomNumber(seed) < 0.5)
+        moveInRoot = YES;
+    else
+        moveInRoot = NO;
 
-    /* change value for pInvar */
-    ran = RandomNumber(seed);
-    if (maxP-minP < window)
+    /* set up pointers for nodes around the picked branch */
+    /* should never change u, v, a, b, c, d pointers */
+    v = p;
+    u = p->anc;
+    if (u->left == v)
+        a = u->right;
+    else
+        a = u->left;
+    b = u->anc;
+    c = v->left;
+    d = v->right;
+
+    /* reset node variables that will be used */
+    for (i=0; i<t->nNodes; i++)
         {
-        window = maxP-minP;
+        p = t->allDownPass[i];
+        p->x = 0;
+        p->marked = NO;
         }
 
-    newP = oldP + window * (ran - 0.5);
-
-    /* check validity */
-    isValidP = NO;
-    do
+    /* mark nodes nNeighbor away in root (negative) or crown (positive) respecting constraints */
+    nRoot = nCrown = 1;
+    if (moveInRoot == YES)
         {
-        if (newP < minP)
-            newP = 2* minP - newP;
-        else if (newP > maxP)
-            newP = 2 * maxP - newP;
+        /* clip root part of tree */
+        a->anc = b;
+        if (b->left == u)
+            b->left = a;
         else
-            isValidP = YES;
-        } while (isValidP == NO);
-
-    /* get proposal ratio */
-    *lnProposalRatio = 0.0;
+            b->right = a;
     
-    /* get prior ratio */
-    *lnPriorRatio = 0.0;
-    lnInvarRatio = log(newP) - log(oldP);
-    lnVarRatio = log(1.0-newP) - log(1.0-oldP);
-    for (i=0; i<param->nRelParts; i++)
-        {
-        m = &modelSettings[param->relParts[i]];
-        if (m->gibbsGamma == YES)
+        /* mark the root part */
+        if (u->isLocked == NO )
             {
-            /* find rate category index and number of gamma categories */
-            rateCat = m->tiIndex + chain * m->numChars;
-            nGammaCats = m->numGammaCats;
-
-            /* find nSitesOfPat */
-            nSitesOfPat = numSitesOfPat + ((chainId[chain] % chainParams.numChains)*numCompressedChars) + m->compCharStart;
-            
-            /* loop over characters */
-            for (c=0; c<m->numChars; c++)
+            p = a; q = b; n = 0;
+            while (q->anc != NULL)
                 {
-                if (rateCat[c] < nGammaCats)
-                    *lnPriorRatio += lnVarRatio * nSitesOfPat[c];
+                q->marked = YES;
+                q->x = n;    // temporary, for MarkDistance below
+                if (q->left == p)
+                    MarkDistance(q->right, YES, nNeighbor, &nRoot);
                 else
-                    *lnPriorRatio += lnInvarRatio * nSitesOfPat[c];
+                    MarkDistance(q->left,  YES, nNeighbor, &nRoot);
+                q->x = --n;  // final
+                nRoot++;
+                if (q->isLocked == YES || abs(q->x) >= nNeighbor)
+                    break;
+                p = q; q = q->anc;
                 }
             }
+        if (a->isLocked == NO)
+            {
+            MarkDistance(a->left,  YES, nNeighbor, &nRoot);
+            MarkDistance(a->right, YES, nNeighbor, &nRoot);
+            }
+            
+        /* get final parsimony states for the root part */
+        GetParsDP (t, t->root->left, chain);
+        GetParsFP (t, t->root->left, chain);
+        /* get final parsimony states for the crown part */
+        GetParsDP (t, v, chain);
+        GetParsFP (t, v, chain);
         }
-    
-    /* copy new pInvar value back */
-    *GetParamVals(param, chain, state[chain]) = newP;
+    else  /* moveInRoot == NO */
+        {
+        /* clip crown part of tree */
+        c->anc = d;
+        d->anc = c;
 
-    /* Set update flags for all partitions that share this pInvar. Note that the conditional
-       likelihood update flags for divisions have been set before we even call this function. */
-    for (i=0; i<param->nRelParts; i++)
-        TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
-    
-    /* However, you do need to update cijk flags if this is a covarion model */
-    /* TO DO */
+        /* mark the crown part */
+        if (c->isLocked == NO)
+            {
+            MarkDistance(c->left,  NO, nNeighbor, &nCrown);
+            MarkDistance(c->right, NO, nNeighbor, &nCrown);
+            }
+        if (d->isLocked == NO)
+            {
+            MarkDistance(d->left,  NO, nNeighbor, &nCrown);
+            MarkDistance(d->right, NO, nNeighbor, &nCrown);
+            }
+        
+        /* get final parsimony states for the root part */
+        if (u->anc != NULL) {
+            a->anc = b;  /* clip */
+            if (b->left == u) b->left = a;
+            else             b->right = a;
+            GetParsDP (t, t->root->left, chain);
+            GetParsFP (t, t->root->left, chain);
+            a->anc = u;  /* change back */
+            if (b->left == a) b->left = u;
+            else             b->right = u;
+            }
+        /* get final parsimony states for the crown part */
+        GetParsDP (t, c, chain);
+        GetParsDP (t, d, chain);
+        GetParsFP (t, c, chain);
+        GetParsFP (t, d, chain);
+        }
     
-    return (NO_ERROR);
-}
-
-
-int Move_PopSize_M (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
-{
-    int             isValidN, valIndex;
-    MrBFlt          *valPtr, oldN, newN, tuning, minN, maxN, ran, oldLnPrior, newLnPrior, growth,
-                    oldT, newT, clockRate;
-    ModelParams     *mp;
-    ModelInfo       *m;
-    Tree            *t;
-
-    /* get multiplier tuning parameter */
-    tuning = mvp[0];
+    /* find number of site patterns and modify randomly */
+    globalNSitesOfPat = numSitesOfPat + (chainId[chain] % chainParams.numChains) * numCompressedChars + m->compCharStart;
+    nSitesOfPat = (CLFlt *) SafeCalloc (numCompressedChars, sizeof(CLFlt));
+    if (!nSitesOfPat)  goto errorExit;
+    for (i=0; i<numCompressedChars; i++)
+        {
+        nSitesOfPat[i] = globalNSitesOfPat[i];
+    /*  for (j=0; j<globalNSitesOfPat[i]; j++)
+            {
+            ran = RandomNumber(seed);
+            if (ran < decreaseProb)
+                nSitesOfPat[i]--;
+            else if (ran > 1.0 - increaseProb)
+                nSitesOfPat[i]++;
+            }  // this is slow at the moment */
+        }
 
-    /* get model params */
-    mp = &modelParams[param->relParts[0]];
+    /* need to alloc a matrix for parsimony lengths, an array of pointers to crown part,
+       and an array of pointers to root part. */
+    parLength = (MrBFlt *) SafeCalloc ((size_t)nRoot * (size_t)nCrown, sizeof(MrBFlt));
+    pRoot  = (TreeNode **) SafeCalloc(nRoot,  sizeof(TreeNode *));
+    pCrown = (TreeNode **) SafeCalloc(nCrown, sizeof(TreeNode *));
+    if (!parLength || !pRoot || !pCrown)  goto errorExit;
     
-    /* get model settings */
-    m = &modelSettings[param->relParts[0]];
-
-    /* get minimum and maximum values for population size */
-    if (param->paramId == POPSIZE_UNI)
-        {
-        minN = mp->popSizeUni[0];
-        maxN = mp->popSizeUni[1];
+    /* starting position */
+    pRoot[0] = a; pCrown[0] = c;
+    for (i=j=1, n=t->nNodes-2; n>=0; n--)
+        {  /* and the rest */
+        p = t->allDownPass[n];
+        if (p->marked == YES && p->x < 0)
+            pRoot[i++] = p;
+        if (p->marked == YES && p->x > 0)
+            pCrown[j++] = p;
         }
-    else
+    assert (i==nRoot && j==nCrown);
+    
+    /* cycle through the possibilities and record the parsimony length */
+    for (j=0; j<nCrown; j++)
         {
-        minN = 0.00001;
-        maxN = 10000000;
+        for (i=0; i<nRoot; i++)
+            {
+            parLength[i+j*nRoot] = 0.0;
+            for (n=0; n<t->nRelParts; n++)
+                {
+                division = t->relParts[n];
+                
+                /* Find model settings */
+                m = &modelSettings[division];
+                
+                /* find nSitesOfPat */
+                nSites = nSitesOfPat + m->compCharStart;
+                
+                /* find parsimony length for each candidate position */
+                length = 0.0;
+                if (moveInRoot == YES)
+                    {
+                    pA = m->parsSets[pRoot[i]->index];
+                    pB = m->parsSets[pRoot[i]->anc->index];
+                    pP = m->parsSets[v->index];
+                    
+                    if (m->nParsIntsPerSite == 1)
+                        {
+                        for (k=0; k<m->numChars; k++)
+                            {
+                            y[0] = (pA[k] | pB[k]) & pP[k];
+                            if (y[0] == 0)
+                                length += nSites[k];
+                            }
+                        }
+                    else /* if (m->nParsIntsPerSite == 2) */
+                        {
+                        for (k=0; k<2*m->numChars; k+=2)
+                            {
+                            y[0] = (pA[k] | pB[k]) & pP[k];
+                            y[1] = (pA[k+1] | pB[k+1]) & pP[k+1];
+                            if ((y[0] | y[1]) == 0)
+                                length += nSites[k/2];
+                            }
+                        }
+                    }
+                else if (u->anc == NULL)
+                    {
+                    pP = m->parsSets[u->index];
+                    pC = m->parsSets[pCrown[j]->index];
+                    pD = m->parsSets[pCrown[j]->anc->index];
+                    
+                    if (m->nParsIntsPerSite == 1)
+                        {
+                        for (k=0; k<m->numChars; k++)
+                            {
+                            y[0] = pP[k] & (pC[k] | pD[k]);
+                            if (y[0] == 0)
+                                length += nSites[k];
+                            }
+                        }
+                    else /* if (m->nParsIntsPerSite == 2) */
+                        {
+                        for (k=0; k<2*m->numChars; k+=2)
+                            {
+                            y[0] = pP[k] & (pC[k] | pD[k]);
+                            y[1] = pP[k+1] & (pC[k+1] | pD[k+1]);
+                            if ((y[0] | y[1]) == 0)
+                                length += nSites[k/2];
+                            }
+                        }
+                    }
+                else
+                    {
+                    pA = m->parsSets[a->index];
+                    pB = m->parsSets[b->index];
+                    pC = m->parsSets[pCrown[j]->index];
+                    pD = m->parsSets[pCrown[j]->anc->index];
+                    
+                    if (m->nParsIntsPerSite == 1)
+                        {
+                        for (k=0; k<m->numChars; k++)
+                            {
+                            y[0] = (pA[k] | pB[k]) & (pC[k] | pD[k]);
+                            if (y[0] == 0)
+                                length += nSites[k];
+                            }
+                        }
+                    else /* if (m->nParsIntsPerSite == 2) */
+                        {
+                        for (k=0; k<2*m->numChars; k+=2)
+                            {
+                            y[0] = (pA[k] | pB[k]) & (pC[k] | pD[k]);
+                            y[1] = (pA[k+1] | pB[k+1]) & (pC[k+1] | pD[k+1]);
+                            if ((y[0] | y[1]) == 0)
+                                length += nSites[k/2];
+                            }
+                        }
+                    }
+                
+                /* get division warp factor */
+                parLength[i+j*nRoot] += warpFactor * length;
+                }
+            }
         }
+    
+    /* find the min length and the sum for the forward move */
+    minLength = -1.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
+            {
+            if (i == 0 && j == 0)  // exclude original position
+                continue;
+            if (minLength > parLength[i+j*nRoot] || minLength < 0.0)
+                minLength = parLength[i+j*nRoot];
+            }
+    sum1 = 0.0; tempc = 0.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
+            {
+            if (i == 0 && j == 0)  // exclude original position
+                continue;
+            /* Kahan summation to reduce numerical error */
+            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
+            tempsum = sum1 + tempy;  tempc = (tempsum - sum1) - tempy;
+            sum1 = tempsum;
+            // sum1 += exp(minLength - parLength[i+j*nRoot]);
+            // printf("%d %d %lf\n", i, j, exp(minLength - parLength[i+j*nRoot]));
+            }
 
-    /* get pointer to value to be changed */
-    valIndex = (int)(RandomNumber(seed) * param->nValues);
-    valPtr = GetParamVals(param, chain, state[chain]) + valIndex;
-
-    /* get old value of population size */
-    oldN = *valPtr;
-
-    /* get old prior for species tree coalescence */
-    if (m->brlens->paramId == BRLENS_CLOCK_SPCOAL)
-        {
-        oldLnPrior = LnSpeciesTreeProb(chain);
-        }
+    /* generate a random uniform */
+    ran = RandomNumber(seed) * sum1;
     
-    /* change value for theta */
-    ran = RandomNumber(seed);
-    newN = oldN * exp(tuning * (ran - 0.5));
+    /* select the appropriate reattachment point */
+    newA = a; newC = c;
+    prob = 0.0; tempc = 0.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
+            {
+            if (i == 0 && j == 0)  // exclude original position
+                continue;
+            // prob += exp (minLength - parLength[i+j*nRoot]);
+            /* Kahan summation to reduce numerical error */
+            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
+            tempsum = prob + tempy;  tempc = (tempsum - prob) - tempy;
+            prob = tempsum;
+            if (prob > ran) {
+                /* proposed new attaching position */
+                newA = pRoot[i];
+                newC = pCrown[j];
+                goto outLoop;
+                }
+            }
+outLoop:;
+    iA = i; jC = j;
+    
+    /* calculate the proposal ratio */
+    (*lnProposalRatio) = parLength[i+j*nRoot] - minLength + log(sum1);
+    
+    /* find the min length and the sum for the backward move */
+    minLength = -1.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
+            {
+            if (i == iA && j == jC)  // exclude new position
+                continue;
+            if (minLength > parLength[i+j*nRoot] || minLength < 0.0)
+                minLength = parLength[i+j*nRoot];
+            }
+    sum2 = 0.0; tempc = 0.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
+            {
+            if (i == iA && j == jC)  // exclude new position
+                continue;
+            /* Kahan summation to reduce numerical error */
+            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
+            tempsum = sum2 + tempy;  tempc = (tempsum - sum2) - tempy;
+            sum2 = tempsum;
+            // sum2 += exp (minLength - parLength[i+j*nRoot]);
+            // printf("%d %d %lf\n", i, j, exp(minLength - parLength[i+j*nRoot]));
+            }
     
-    /* check that new value is valid */
-    isValidN = NO;
-    do {
-        if (newN < minN)
-            newN = 2* minN - newN;
-        else if (newN > maxN)
-            newN = 2 * maxN - newN;
-        else
-            isValidN = YES;
-        }
-    while (isValidN == NO);
-
-    /* copy new population size value back */
-    (*valPtr) = newN;
-
-    /* get proposal ratio */
-    *lnProposalRatio = log (newN / oldN);
+    /* calculate the proposal ratio */
+    (*lnProposalRatio) += minLength - parLength[0] - log(sum2);
     
-    /* get prior ratio */
-    if (m->brlens->paramId == BRLENS_CLOCK_SPCOAL)
-        {
-        newLnPrior = LnSpeciesTreeProb(chain);
-        }
-    else
+    if (moveInRoot == YES)  /* root part has changed */
         {
-        t = GetTree(modelSettings[param->relParts[0]].brlens,chain,state[chain]);
-        m = &modelSettings[param->relParts[0]];
-        clockRate = *GetParamVals(m->clockRate, chain, state[chain]);
-        if (!strcmp(mp->ploidy, "Diploid"))
-            clockRate *= 4.0;
-        else if (!strcmp(mp->ploidy, "Zlinked"))
-            clockRate *= 3.0;
+        /* reattach the root part */
+        newB = newA->anc;
+        newA->anc = u;
+        if (u->left == v)
+            u->right = newA;
         else
-            clockRate *= 2.0;
-        newT = oldN * clockRate;
-        oldT = newN * clockRate;
-        if (!strcmp(mp->growthPr, "Fixed"))
-            growth = mp->growthFix;
+            u->left = newA;
+        u->anc = newB;
+        if (newB->left == newA)
+            newB->left = u;
         else
-            growth = *(GetParamVals (m->growthRate, chain, state[chain]));
-        if (LnCoalescencePriorPr (t, &oldLnPrior, oldT, growth) == ERROR)
+            newB->right = u;
+
+        /* if u is locked, then we have moved upwards and need to leave the u lock behind */
+        if (u->isLocked == YES)
             {
-            MrBayesPrint ("%s   Problem calculating prior for coalescent process\n", spacer);
-            return (ERROR);
+            u->isLocked = NO;
+            a->isLocked = YES;
+            a->lockID = u->lockID;
+            u->lockID = -1;
             }
-        if (LnCoalescencePriorPr (t, &newLnPrior, newT, growth) == ERROR)
+        
+        p = newA;
+        while (p->anc != NULL)
             {
-            MrBayesPrint ("%s   Problem calculating prior for coalescent process\n", spacer);
-            return (ERROR);
+            if (p == a) break;
+            p = p->anc;
+            }
+        if (p == a)
+            {
+            /* newA is descendant to a so move a->length not u->length */
+            x = u->length;
+            u->length = a->length;
+            a->length = x;
             }
-        }
-
-    (*lnPriorRatio) = param->LnPriorRatio(newN, oldN, param->priorParams);
-    (*lnPriorRatio) += newLnPrior - oldLnPrior;
-
-    return (NO_ERROR);
-}
-
-
-/* Generalized lognormal move for positive real random variables */
-int Move_PosRealLognormal (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
-{
-    int         i;
-    MrBFlt      oldX, newX, minX, maxX, tuning, u, z;
 
-    /* get tuning parameter */
-    tuning = mvp[0];
+        p = b;
+        while (p->anc != NULL)
+            {
+            if (p == newA) break;
+            p = p->anc;
+            }
+        if (p == newA)
+            {
+            /* newA is ancestor to a so insert above instead of below */
+            x = newA->length;
+            newA->length = u->length;
+            u->length = x;
+            /* newA is on root path and locked, we need to transfer lock to u */
+            if (newA->isLocked == YES) {
+                u->isLocked = YES;
+                u->lockID = newA->lockID;
+                newA->isLocked = NO;
+                newA->lockID = -1;
+                }
+            }
+        
+        /* hit a length with multiplier */
+        x = a->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
+            }
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / a->length);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (a->length - x);
+        a->length = x;
 
-    /* get minimum and maximum values for X */
-    minX = param->min;
-    maxX = param->max;
+        /* hit u length with multiplier */
+        x = u->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
+            }
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / u->length);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (u->length - x);
+        u->length = x;
 
-    /* get old value of X */
-    newX = oldX = *GetParamVals(param, chain, state[chain]);
+        /* hit newA length with multiplier */
+        x = newA->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
+            }
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / newA->length);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (newA->length - x);
+        newA->length = x;
+         
+        /* set tiprobs update flags */
+        newA->upDateTi = YES;
+        a->upDateTi = YES;
+        u->upDateTi = YES;
+            
+        /* set flags for update of cond likes */
+        p = u;
+        while (p->anc != NULL)
+            {
+            p->upDateCl = YES;
+            p = p->anc;
+            }
+        p = b;
+        while (p->anc != NULL)
+            {
+            p->upDateCl = YES;
+            p = p->anc;
+            }
+        }
+    
+    if (moveInRoot == NO)  /* crown part has changed */
+        {
+        r = newC;
+        q = newB = newC->anc;
+        /* rotate nodes from newC to c or d (whichever is closest) */
+        tempc = r->length;
+        while (r != c && r != d)
+            {
+            p = q->anc;
+            /* rotate pointers of q */
+            if (q->left == r)
+                q->left = p;
+            else
+                q->right = p;
+            q->anc = r;
+            /* swap q and old */
+            tempy = q->length;
+            q->length = tempc;
+            q->upDateTi = YES;
+            tempc = tempy;
+            /* make sure we get q and r initialized for next round */
+            r = q;
+            q = p;
+            }
+        newB->length = tempc;
+            
+        /* hit q length with multiplier while we are at it */
+        x = q->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
+            }        
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / q->length);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (q->length - x);
+        q->length = x;
+        q->upDateTi = YES;
 
-    /* change value of X */
-    u = RandomNumber(seed);
-    z = PointNormal(u);
+        /* hit newB length with multiplier */
+        x = newB->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
+            }
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / newB->length);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (newB->length - x);
+        newB->length = x;
+        newB->upDateTi = YES;
 
-    newX = exp (log(oldX) + z * tuning);
-    
-    /* check that new value is valid */
-    if (newX < minX || newX > maxX) {
-        abortMove = YES;
-        return (NO_ERROR);
-    }
-    
-    /* get proposal ratio */
-    (*lnProposalRatio) = log (newX / oldX);
-    
-    /* get prior ratio */
-    (*lnPriorRatio) = param->LnPriorRatio(newX, oldX, param->priorParams);
+        /* hit newC length with multiplier */
+        x = newC->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
+            }
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / newC->length);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (newC->length - x);
+        newC->length = x;
+        newC->upDateTi = YES;
+ 
+        /* reattach the crown part */
+        v->left = newC;
+        v->right = newB;
+        newC->anc = newB->anc = v;
+        
+        /* set flags for update of cond likes */
+        p = newC;
+        while (p->anc != NULL)
+            {
+            p->upDateCl = YES;
+            p = p->anc;
+            }
+        p = r;
+        while (p->anc != NULL)
+            {
+            p->upDateCl = YES;
+            p = p->anc;
+            }
+        }
     
-    /* copy new value back */
-    (*GetParamVals(param, chain, state[chain])) = newX;
+    topologyHasChanged = YES;
 
-    /* Set update flags for tree nodes if relevant */
-    if (param->affectsLikelihood == YES)
+    /* get down pass sequence if tree topology has changed */
+    if (topologyHasChanged == YES)
         {
-        for (i=0; i<param->nRelParts; i++)
-            TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
+        GetDownPass (t);
         }
-
-    return (NO_ERROR);
-}
-
-
-/* Generalized multiplier move for positive real random variables */
-int Move_PosRealMultiplier (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
-{
-    int         i, isValid;
-    MrBFlt      oldX, newX, minX, maxX, tuning, ran, factor;
-
-    /* get tuning parameter */
-    tuning = mvp[0];
-
-    /* get minimum and maximum values for X */
-    minX = param->min;
-    maxX = param->max;
-
-    /* get old value of X */
-    newX = oldX = *GetParamVals(param, chain, state[chain]);
-
-    /* change value of X */
-    ran = RandomNumber(seed);
-    factor = exp(tuning * (ran - 0.5));
-    newX = oldX * factor;
     
-    /* check that new value is valid */
-    isValid = NO;
-    do
-        {
-        if (newX < minX)
-            newX = minX * minX / newX;
-        else if (newX > maxX)
-            newX = maxX * maxX / newX;
-        else
-            isValid = YES;
-        } while (isValid == NO);
-
-    /* get proposal ratio */
-    (*lnProposalRatio) = log (newX / oldX);
+    /* Dirichlet or twoExp prior */
+    if (isVPriorExp > 1)
+        (*lnPriorRatio) += LogDirPrior(t, mp, isVPriorExp);
     
-    /* get prior ratio */
-    (*lnPriorRatio) = param->LnPriorRatio(newX, oldX, param->priorParams);
+    /* free up local memory */
+    free (parLength); free (pRoot); free (pCrown); free (nSitesOfPat);
     
-    /* copy new value back */
-    *(GetParamVals(param, chain, state[chain])) = newX;
-
-    /* Set update flags for tree nodes if relevant */
-    if (param->affectsLikelihood == YES)
-        {
-        for (i=0; i<param->nRelParts; i++)
-            TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
-        }
-
     return (NO_ERROR);
+    
+errorExit:
+    MrBayesPrint ("%s   Problem allocating memory in Move_ParsSPR\n", spacer);
+    free (parLength); free (pRoot); free (pCrown); free (nSitesOfPat);
+    
+    return (ERROR);
 }
 
 
-int Move_RanSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+int Move_ParsSPR2 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
 {
-    /* Change branch lengths and topology (potentially) using random SPR (unrooted) */
-
-    /* This move type picks a random interior branch and another randomly chosen interior
-       or terminal branch. The path connecting these branches is found and the two subtrees
-       are swapped along this path. This is the move studied in Lakner et al. (2008).
-       
-       This move is not yet safe for constrained trees. */
+    /* Change topology (and branch lengths) using SPR (symmetric) biased according to parsimony scores,
+       controlled by a window defined by a certain node distance radius. Note: S/N */
     
-    int         i, topologyHasChanged, nCrownNodes, nRootNodes, directionLeft, directionUp, 
-                isVPriorExp, moveInRoot, foundFirst;
-    MrBFlt      m, x, y, tuning, maxV, minV, extensionProb, brlensExp=0.0;
-    TreeNode    *p, *a, *b, *c, *d, *u, *v, *brlenNode[7], *q;
+    int         i, j, k, n, division, topologyHasChanged, moveInRoot, nNeighbor, nRoot, nCrown, iA, jC, isVPriorExp;
+    BitsLong    *pA, *pB, *pP, *pC, *pD, y[2];
+    MrBFlt      x, minV, maxV, brlensExp=0.0, minLength=0.0, length=0.0, *parLength=NULL, prob, ran, tuning, warpFactor,
+                v_typical, divFactor, nStates, sum1, sum2, tempsum, tempc, tempy;
+    CLFlt       *nSites, *nSitesOfPat=NULL, *globalNSitesOfPat;
+    TreeNode    *p, *q, *r, *a, *b, *u, *v, *c, *d, *newB, *newA, *newC, **pRoot=NULL, **pCrown=NULL;
     Tree        *t;
     ModelParams *mp;
-
-    /* these parameters should be possible to set by user */
-    extensionProb = mvp[0]; /* extension probability */
-    tuning = mvp[1];        /* Larget & Simon's tuning parameter lambda */
+    ModelInfo   *m=NULL;
+    
+    warpFactor = mvp[0];                  /* tuning parameter determining how heavily to weight according to parsimony scores */
+//  increaseProb = decreaseProb = mvp[1]; /* reweighting probabilities */
+    v_typical = mvp[2];                   /* typical branch length for conversion of parsimony score to log prob ratio */
+    tuning = mvp[3];                      /* multiplier tuning parameter */
+    nNeighbor = (int)mvp[4];              /* distance to move picked branch in root and crown part */
+    
+    (*lnProposalRatio) = (*lnPriorRatio) = 0.0;
+    
+    /* get model params and model info */
+    mp = &modelParams[param->relParts[0]];
+    m = &modelSettings[param->relParts[0]];
     
     /* get tree */
     t = GetTree (param, chain, state[chain]);
-
-    /* get model params */
-    mp = &modelParams[param->relParts[0]];
     
     /* max and min brlen */
     if (param->subParams[0]->paramId == BRLENS_UNI)
         {
         minV = mp->brlensUni[0] > BRLENS_MIN ? mp->brlensUni[0] : BRLENS_MIN;
-        maxV = mp->brlensUni[1];
+        maxV = mp->brlensUni[1] < BRLENS_MAX ? mp->brlensUni[1] : BRLENS_MAX;
         isVPriorExp = NO;
         }
-    else
+    else if (param->subParams[0]->paramId == BRLENS_GamDir)
         {
         minV = BRLENS_MIN;
         maxV = BRLENS_MAX;
-        brlensExp = mp->brlensExp;
-        isVPriorExp = YES;
-        }
-
-    topologyHasChanged = NO;
-
-#   if defined (DEBUG_RanSPR)
-    printf ("Before:\n");
-    ShowNodes (t->root, 2, NO);
-    getchar();
-#   endif
-    
-    /* pick an internal branch */
-    do
-        {
-        p = t->intDownPass[(int)(RandomNumber(seed)*t->nIntNodes)];
-        } while (p->anc->anc == NULL);
-
-    /* select another random branch */
-    if (RandomNumber(seed) > extensionProb)
-        q = p->left;
-    else
-        {
-        do
-            {
-            q = t->allDownPass[(int)(RandomNumber(seed)*(t->nNodes - 1))];
-            } while (q == p || q->anc == p || q == p->anc || q->anc == p->anc);
-        }
-    
-    /* set up pointers for nodes around the picked branch */
-    /* cut the tree into crown, root and attachment part */
-    /* change the relevant lengths in the attachment part */
-    /* the lengths of a and v are automatically contained in the */
-    /* "attachment" part but the length of c has to be stored in x */
-    v = p;
-    u = p->anc;
-
-    /* store brlen node */
-    brlenNode[3] = v;
-
-    /* mark crown subtree */
-    for (i=0; i<t->nNodes; i++)
-        {
-        p = t->allDownPass[i];
-        p->x = 0;
-        }
-    v->x = 1;
-
-    for (i=t->nNodes-2; i>=0; i--)
-        {
-        p = t->allDownPass[i];
-        if (p->anc->x == 1)
-            p->x = 1;
-        }
-
-    /* find the subtree */
-    if (q->x == 1)
-        moveInRoot = NO;
-    else
-        moveInRoot = YES;
-
-    /* mark the path of the move */
-    for (i=0; i<t->nNodes; i++)
-        t->allDownPass[i]->marked = NO;
-
-    if (moveInRoot == NO)
-        {
-        p = q;
-        while (p != v)
-            {
-            p->marked = YES;
-            p = p->anc;
-            }
-        v->marked = YES;
+        isVPriorExp = 2;
         }
-    else
+    else if (param->subParams[0]->paramId == BRLENS_iGmDir)
         {
-        p = q;
-        while (p != NULL)
-            {
-            p->marked = YES;
-            p = p->anc;
-            }
-        foundFirst = NO;
-        p = v;
-        while (p != NULL)
-            {
-            if (p->marked == NO)
-                p->marked = YES;
-            else if (foundFirst == YES)
-                p->marked = NO;
-            else
-                foundFirst = YES;
-            p = p->anc;
-            }
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        isVPriorExp = 3;
         }
-
-    /* set up pointers for crown part */
-    /* this also determines direction of move in crown part */
-    if (v->left->marked == YES)
+    else if (param->subParams[0]->paramId == BRLENS_twoExp)
         {
-        c = v->left;
-        d = v->right;
-        directionLeft = YES;
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        isVPriorExp = 4;
         }
     else
         {
-        c = v->right;
-        d = v->left;
-        directionLeft = NO;
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        brlensExp = mp->brlensExp;
+        isVPriorExp = YES;
         }
 
-    /* store brlen nodes and brlen to move */
-    brlenNode[0] = d;
-    brlenNode[1] = c;
-    x = c->length;
-
-    /* cut and reconnect crown part */
-    c->anc = d;
-    d->anc = c;
+    /* Dirichlet or twoExp prior */
+    if (isVPriorExp > 1)
+        (*lnPriorRatio) = -LogDirPrior(t, mp, isVPriorExp);
     
-    /* mark nodes in root part */
-    /* also determines direction of move in root part */
-    if (u->anc->marked == NO)
-        {
-        if (u->left == v)
-            a = u->right;
-        else
-            a = u->left;
-        b = u->anc;
-        directionUp = YES;
-        }
-    else
-        {
-        if (u->left == v)
-            b = u->right;
-        else
-            b = u->left;
-        a = u->anc;
-        directionUp = NO;
-        }
+    /* set topologyHasChanged to NO */
+    topologyHasChanged = NO;
+    
+    /* pick a random branch */
+    do  {
+        p = t->allDownPass[(int)(RandomNumber(seed) * (t->nNodes -1))];
+        q = p->anc->right;  if (q == p) q = p->anc->left;
+        i = j = 0;
+        if (p->left == NULL)
+            j = 2;
+        if (p->anc->anc == NULL)
+            i = 2;
+        if (p->anc->anc != NULL && (p->anc->isLocked == YES || p->anc->anc->anc == NULL))
+            i++;
+        if (p->anc->anc != NULL && (q->isLocked == YES || q->left == NULL))
+            i++;
+        if (p->left != NULL && (p->left->isLocked == YES || p->left->left == NULL))
+            j++;
+        if (p->left != NULL && (p->right->isLocked == YES || p->right->left == NULL))
+            j++;
+        } while (i == 2 && j == 2);
+    
+    /* pick an internal branch
+    do  {
+        p = t->intDownPass[(int)(RandomNumber(seed)*(t->nIntNodes-1))];
+        q = p->anc->left;  if (q == p)  q = p->anc->right;
+        i = j = 0;
+        if (q->isLocked == YES || q->left == NULL)
+            i++;
+        if (p->anc->isLocked == YES || p->anc->anc->anc == NULL)
+            i++;
+        if (p->left->isLocked == YES || p->left->left == NULL)
+            j++;
+        if (p->right->isLocked == YES || p->right->left == NULL)
+            j++;
+        } while (i == 2 && j == 2);
+    */
+
+    /* determine moving direction */
+    if (j == 2)
+        moveInRoot = YES;
+    else if (i == 2)
+        moveInRoot = NO;
+    else if (RandomNumber(seed) < 0.5)
+        moveInRoot = YES;
+    else
+        moveInRoot = NO;
 
-    /* store brlen nodes */
-    if (directionUp == YES)
-        {
-        brlenNode[4] = u;
-        brlenNode[5] = a;
-        }
+    /* set up pointers for nodes around the picked branch */
+    /* should never change u, v, a, b, c, d pointers */
+    v = p;
+    u = p->anc;
+    if (u->left == v)
+        a = u->right;
     else
-        {
-        brlenNode[4] = b;
-        brlenNode[5] = u;
-        }
+        a = u->left;
+    b = u->anc;
+    c = v->left;
+    d = v->right;
 
-    /* cut root part*/
-    /* store branch to move in u->length */
-    if (directionUp == NO) 
+    /* reset node variables that will be used */
+    for (i=0; i<t->nNodes; i++)
         {
-        b->anc = a;
-        if (a->left == u)
-            a->left = b;
-        else
-            a->right = b;
+        p = t->allDownPass[i];
+        p->x = 0;
+        p->marked = NO;
         }
-    else 
+
+    /* mark nodes nNeighbor away in root (negative) or crown (positive) respecting constraints */
+    nRoot = nCrown = 1;
+    if (moveInRoot == YES)
         {
+        /* clip root part of tree */
         a->anc = b;
         if (b->left == u)
             b->left = a;
         else
             b->right = a;
-        y = a->length;
-        a->length = u->length;
-        u->length = y;
-        a->upDateTi = YES;
-        u->upDateTi = YES;
+    
+        /* mark the root part */
+        if (u->isLocked == NO )
+            {
+            p = a; q = b; n = 0;
+            while (q->anc != NULL)
+                {
+                q->marked = YES;
+                q->x = n;    // temporary, for MarkDistance below
+                if (q->left == p)
+                    MarkDistance(q->right, YES, nNeighbor, &nRoot);
+                else
+                    MarkDistance(q->left,  YES, nNeighbor, &nRoot);
+                q->x = --n;  // final
+                nRoot++;
+                if (q->isLocked == YES || abs(q->x) >= nNeighbor)
+                    break;
+                p = q; q = q->anc;
+                }
+            }
+        if (a->isLocked == NO)
+            {
+            MarkDistance(a->left,  YES, nNeighbor, &nRoot);
+            MarkDistance(a->right, YES, nNeighbor, &nRoot);
+            }
+            
+        /* get final parsimony states for the root part */
+        GetParsDP (t, t->root->left, chain);
+        GetParsFP (t, t->root->left, chain);
+        /* get final parsimony states for the crown part */
+        GetParsDP (t, v, chain);
+        GetParsFP (t, v, chain);
         }
+    else  /* moveInRoot == NO */
+        {
+        /* clip crown part of tree */
+        c->anc = d;
+        d->anc = c;
 
-    /* move around in root subtree */
-    nRootNodes = 0;
-    if (moveInRoot == YES)
+        /* mark the crown part */
+        if (c->isLocked == NO)
+            {
+            MarkDistance(c->left,  NO, nNeighbor, &nCrown);
+            MarkDistance(c->right, NO, nNeighbor, &nCrown);
+            }
+        if (d->isLocked == NO)
+            {
+            MarkDistance(d->left,  NO, nNeighbor, &nCrown);
+            MarkDistance(d->right, NO, nNeighbor, &nCrown);
+            }
+        
+        /* get final parsimony states for the root part */
+        if (u->anc != NULL) {
+            a->anc = b;  /* clip */
+            if (b->left == u) b->left = a;
+            else             b->right = a;
+            GetParsDP (t, t->root->left, chain);
+            GetParsFP (t, t->root->left, chain);
+            a->anc = u;  /* change back */
+            if (b->left == a) b->left = u;
+            else             b->right = u;
+            }
+        /* get final parsimony states for the crown part */
+        GetParsDP (t, c, chain);
+        GetParsDP (t, d, chain);
+        GetParsFP (t, c, chain);
+        GetParsFP (t, d, chain);
+        }
+    
+    /* find number of site patterns and modify randomly */
+    globalNSitesOfPat = numSitesOfPat + (chainId[chain] % chainParams.numChains) * numCompressedChars + m->compCharStart;
+    nSitesOfPat = (CLFlt *) SafeCalloc (numCompressedChars, sizeof(CLFlt));
+    if (!nSitesOfPat)  goto errorExit;
+    for (i=0; i<numCompressedChars; i++)
         {
-        for (nRootNodes=0; a->marked == YES; nRootNodes++) 
+        nSitesOfPat[i] = globalNSitesOfPat[i];
+    /*  for (j=0; j<globalNSitesOfPat[i]; j++)
             {
-            if (directionUp == YES) 
+            ran = RandomNumber(seed);
+            if (ran < decreaseProb)
+                nSitesOfPat[i]--;
+            else if (ran > 1.0 - increaseProb)
+                nSitesOfPat[i]++;
+            }  // this is slow at the moment */
+        }
+
+    /* need to alloc a matrix for parsimony lengths, an array of pointers to crown part,
+       and an array of pointers to root part. */
+    parLength = (MrBFlt *) SafeCalloc ((size_t)nRoot * (size_t)nCrown, sizeof(MrBFlt));
+    pRoot  = (TreeNode **) SafeCalloc(nRoot,  sizeof(TreeNode *));
+    pCrown = (TreeNode **) SafeCalloc(nCrown, sizeof(TreeNode *));
+    if (!parLength || !pRoot || !pCrown)  goto errorExit;
+    
+    /* starting position */
+    pRoot[0] = a; pCrown[0] = c;
+    for (i=j=1, n=t->nNodes-2; n>=0; n--)
+        {  /* and the rest */
+        p = t->allDownPass[n];
+        if (p->marked == YES && p->x < 0)
+            pRoot[i++] = p;
+        if (p->marked == YES && p->x > 0)
+            pCrown[j++] = p;
+        }
+    assert (i==nRoot && j==nCrown);
+    
+    /* cycle through the possibilities and record the parsimony length */
+    for (j=0; j<nCrown; j++)
+        {
+        for (i=0; i<nRoot; i++)
+            {
+            parLength[i+j*nRoot] = 0.0;
+            for (n=0; n<t->nRelParts; n++)
                 {
-                /* going up tree */
-                if (a->left == NULL)
-                    break;
-                else if (a->left->marked == NO && a->right->marked == NO)
-                    break;      /* don't go further */
-                topologyHasChanged = YES;
-                b = a;
-                if (a->left->marked == YES)
-                    a = a->left;
-                else
-                    a = a->right;
-                if (u->isLocked == YES)
+                division = t->relParts[n];
+                
+                /* Find model settings */
+                m = &modelSettings[division];
+                
+                /* find nSitesOfPat */
+                nSites = nSitesOfPat + m->compCharStart;
+                
+                /* find parsimony length for each candidate position */
+                length = 0.0;
+                if (moveInRoot == YES)
                     {
-                    b->isLocked = YES;
-                    u->isLocked = NO;
-                    b->lockID = u->lockID;
-                    u->lockID = 0;
+                    pA = m->parsSets[pRoot[i]->index];
+                    pB = m->parsSets[pRoot[i]->anc->index];
+                    pP = m->parsSets[v->index];
+                    
+                    if (m->nParsIntsPerSite == 1)
+                        {
+                        for (k=0; k<m->numChars; k++)
+                            {
+                            y[0] = (pA[k] | pB[k]) & pP[k];
+                            if (y[0] == 0)
+                                length += nSites[k];
+                            }
+                        }
+                    else /* if (m->nParsIntsPerSite == 2) */
+                        {
+                        for (k=0; k<2*m->numChars; k+=2)
+                            {
+                            y[0] = (pA[k] | pB[k]) & pP[k];
+                            y[1] = (pA[k+1] | pB[k+1]) & pP[k+1];
+                            if ((y[0] | y[1]) == 0)
+                                length += nSites[k/2];
+                            }
+                        }
                     }
-                }
-            else 
-                {
-                /* going down tree */
-                if (a->anc == NULL || u->isLocked == YES)
-                    break;      /* can't go further */
-                topologyHasChanged = YES;
-                if (a->anc->marked == NO) 
+                else if (u->anc == NULL)
                     {
-                    /* try switching direction */
-                    /* find sister of a */
-                    if (a->left == b) 
+                    pP = m->parsSets[u->index];
+                    pC = m->parsSets[pCrown[j]->index];
+                    pD = m->parsSets[pCrown[j]->anc->index];
+                    
+                    if (m->nParsIntsPerSite == 1)
                         {
-                        a = a->right;
-                        }
-                    else 
-                        {  
-                        a = a->left;
+                        for (k=0; k<m->numChars; k++)
+                            {
+                            y[0] = pP[k] & (pC[k] | pD[k]);
+                            if (y[0] == 0)
+                                length += nSites[k];
+                            }
                         }
-                    /* as long as we are moving upwards
-                    the cond likes to update will be
-                    flagged by the last pass from u to the root */
-                    if (a->marked == NO)
+                    else /* if (m->nParsIntsPerSite == 2) */
                         {
-                        b = a->anc;
-                        b->upDateCl = YES;
-                        a = a->anc->anc;
-                        break;          /* go back and one node down, unsuccessful attempt */
+                        for (k=0; k<2*m->numChars; k+=2)
+                            {
+                            y[0] = pP[k] & (pC[k] | pD[k]);
+                            y[1] = pP[k+1] & (pC[k+1] | pD[k+1]);
+                            if ((y[0] | y[1]) == 0)
+                                length += nSites[k/2];
+                            }
                         }
-                    else
+                    }
+                else
+                    {
+                    pA = m->parsSets[a->index];
+                    pB = m->parsSets[b->index];
+                    pC = m->parsSets[pCrown[j]->index];
+                    pD = m->parsSets[pCrown[j]->anc->index];
+                    
+                    if (m->nParsIntsPerSite == 1)
                         {
-                        b = a->anc;
-                        directionUp = YES;  /* successful attempt */
+                        for (k=0; k<m->numChars; k++)
+                            {
+                            y[0] = (pA[k] | pB[k]) & (pC[k] | pD[k]);
+                            if (y[0] == 0)
+                                length += nSites[k];
+                            }
                         }
-                    }   
-                else 
-                    {   /* continue down */                 
-                    b = a;
-                    a = a->anc;
-                    b->upDateCl = YES; 
-                    if (b->isLocked == YES)
+                    else /* if (m->nParsIntsPerSite == 2) */
                         {
-                        u->isLocked = YES;
-                        b->isLocked = NO;
-                        u->lockID = b->lockID;
-                        b->lockID = 0;
+                        for (k=0; k<2*m->numChars; k+=2)
+                            {
+                            y[0] = (pA[k] | pB[k]) & (pC[k] | pD[k]);
+                            y[1] = (pA[k+1] | pB[k+1]) & (pC[k+1] | pD[k+1]);
+                            if ((y[0] | y[1]) == 0)
+                                length += nSites[k/2];
+                            }
                         }
                     }
+                
+                /* find nStates and ratemult */
+                nStates = m->numModelStates;
+                if (m->dataType == STANDARD)
+                    nStates = 2;
+                v_typical = length/m->numUncompressedChars + 0.0001;
+                
+                /* get division warp factor (prop. to prob. of change) */
+                divFactor = - warpFactor * log(1.0/nStates - exp(-nStates/(nStates-1)*v_typical)/nStates);
+                parLength[i+j*nRoot] += divFactor * length;
                 }
             }
         }
+    
+    /* find the min length and the sum for the forward move */
+    minLength = -1.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
+            {
+            if (i == 0 && j == 0)  // exclude original position
+                continue;
+            if (minLength > parLength[i+j*nRoot] || minLength < 0.0)
+                minLength = parLength[i+j*nRoot];
+            }
+    sum1 = 0.0; tempc = 0.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
+            {
+            if (i == 0 && j == 0)  // exclude original position
+                continue;
+            /* Kahan summation to reduce numerical error */
+            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
+            tempsum = sum1 + tempy;  tempc = (tempsum - sum1) - tempy;
+            sum1 = tempsum;
+            // sum1 += exp(minLength - parLength[i+j*nRoot]);
+            // printf("%d %d %lf\n", i, j, exp(minLength - parLength[i+j*nRoot]));
+            }
 
-    /* store brlen nodes */
-    if (nRootNodes > 0)
-        {
-        if (directionUp == YES)
+    /* generate a random uniform */
+    ran = RandomNumber(seed) * sum1;
+    
+    /* select the appropriate reattachment point */
+    newA = a; newC = c;
+    prob = 0.0; tempc = 0.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
             {
-            brlenNode[6] = a;
-            brlenNode[5] = u;
+            if (i == 0 && j == 0)  // exclude original position
+                continue;
+            // prob += exp (minLength - parLength[i+j*nRoot]);
+            /* Kahan summation to reduce numerical error */
+            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
+            tempsum = prob + tempy;  tempc = (tempsum - prob) - tempy;
+            prob = tempsum;
+            if (prob > ran) {
+                /* proposed new attaching position */
+                newA = pRoot[i];
+                newC = pCrown[j];
+                goto outLoop;
+                }
             }
-        else
+outLoop:;
+    iA = i; jC = j;
+    
+    /* calculate the proposal ratio */
+    (*lnProposalRatio) = parLength[i+j*nRoot] - minLength + log(sum1);
+    
+    /* find the min length and the sum for the backward move */
+    minLength = -1.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
             {
-            brlenNode[6] = u;
-            brlenNode[5] = b;
+            if (i == iA && j == jC)  // exclude new position
+                continue;
+            if (minLength > parLength[i+j*nRoot] || minLength < 0.0)
+                minLength = parLength[i+j*nRoot];
             }
-        }
-
-    /* move around in crown subtree */
-    nCrownNodes = 0;
-    if (moveInRoot == NO)       
-        {
-        for (nCrownNodes=0; c->left != NULL; nCrownNodes++) 
+    sum2 = 0.0; tempc = 0.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
             {
-            if (c->left->marked == NO && c->right->marked == NO)
-                break;  /* can't go further */
-            topologyHasChanged = YES;
-            if (c->left->marked == YES) 
-                {
-                /* rotate c anticlockwise - prepare pointers for move left */
-                c->anc = c->left;  /* the root will be in the direction we are heading */
-                c->left = c->right;
-                c->right = d;
-                }
-            else 
-                {
-                /* rotate c clockwise - prepare pointers for move right */
-                c->anc = c->right;  /* the root will be in the direction we are heading */
-                c->right = c->left;
-                c->left = d;  
-                }
-            /* OK - let's move!; c->anc points in the right direction
-            don't forget to move the branch lengths as well */
-            d = c;
-            c = c->anc;
-            d->length = c->length;
-            d->upDateCl = YES; 
-            d->upDateTi = YES;
+            if (i == iA && j == jC)  // exclude new position
+                continue;
+            /* Kahan summation to reduce numerical error */
+            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
+            tempsum = sum2 + tempy;  tempc = (tempsum - sum2) - tempy;
+            sum2 = tempsum;
+            // sum2 += exp (minLength - parLength[i+j*nRoot]);
+            // printf("%d %d %lf\n", i, j, exp(minLength - parLength[i+j*nRoot]));
             }
-        }
-
-    /* store brlen nodes */
-    if (nCrownNodes > 0)
-        {
-        brlenNode[2] = c;
-        brlenNode[1] = d;
-        }
-
-    /* combine the subtrees */
-    c->anc = v;
-    d->anc = v;
-    if (directionLeft == YES) 
-        {
-        v->left = c;
-        v->right = d;
-        }
-    else 
-        {
-        v->left = d;
-        v->right = c;
-        }
-
-    /* the dangling branch is inserted in reverted position
-       such that the back move will be possible
-       if we have moved around in crown subtree
-       otherwise it is left in its original position */
-    if (nCrownNodes > 0)
-        {
-        d->length = x;
-        d->upDateTi = YES;
-        }
-    else
-        {
-        c->length = x;
-        }
-
-    if (directionUp == YES) 
+    
+    /* calculate the proposal ratio */
+    (*lnProposalRatio) += minLength - parLength[0] - log(sum2);
+    
+    if (moveInRoot == YES)  /* root part has changed */
         {
-        u->anc = b;
+        /* reattach the root part */
+        newB = newA->anc;
+        newA->anc = u;
         if (u->left == v)
-            u->right = a;
-        else 
-            u->left = a;
-        a->anc = u;
-        if (b->left == a)
-            b->left = u;
+            u->right = newA;
         else
-            b->right = u;
-        /* the dangling branch is contained in u->length
-           and will automatically be inserted in the right position
-           to enable the back move regardless of whether it was
-           initially directed upwards or downwards
-           BUT if we haven't moved in root subtree, it is advantageous (necessary
-           for rooted trees) to avoid switching branches, which occurs otherwise
-           if directionUp == YES */
-        if (nRootNodes == 0) 
+            u->left = newA;
+        u->anc = newB;
+        if (newB->left == newA)
+            newB->left = u;
+        else
+            newB->right = u;
+
+        /* if u is locked, then we have moved upwards and need to leave the u lock behind */
+        if (u->isLocked == YES)
+            {
+            u->isLocked = NO;
+            a->isLocked = YES;
+            a->lockID = u->lockID;
+            u->lockID = -1;
+            }
+        
+        p = newA;
+        while (p->anc != NULL)
+            {
+            if (p == a) break;
+            p = p->anc;
+            }
+        if (p == a)
             {
+            /* newA is descendant to a so move a->length not u->length */
             x = u->length;
             u->length = a->length;
             a->length = x;
-            a->upDateTi = NO;
-            u->upDateTi = NO;
             }
-        }
-    else 
-        {
-        u->anc = a;
-        if (u->left == v)
-            u->right = b;
-        else 
-            u->left = b;
-        b->anc = u;
-        if (a->left == b)
-            a->left = u;
-        else
-            a->right = u;
-        /* the modified branch contained in u->length will have
-           to be moved to b->length to enable back move
-           BUT if we haven't moved, it is better to keep it in place
-           (necessary for rooted trees) */
-        if (nRootNodes > 0) 
+
+        p = b;
+        while (p->anc != NULL)
             {
-            x = u->length;
-            u->length = b->length;
-            b->length = x;
-            b->upDateTi = YES;
-            u->upDateTi = YES;
+            if (p == newA) break;
+            p = p->anc;
             }
-        }
-    
-    /* modify branch lengths */
-    /* first modify length of middle branch */
-    m = brlenNode[3]->length;
-    x = m * exp(tuning * (RandomNumber(seed) - 0.5));       /* save the modified dangling branch for later use */
-    while (x < minV || x > maxV)
-        {
-        if (x < minV)
-            x = minV * minV / x;
-        else if (x > maxV)
-            x = maxV * maxV / x;
-        }
-    brlenNode[3]->length = x;
-    brlenNode[3]->upDateTi = YES;
-
-    /* update proposal and prior ratio based on length modification */
-    (*lnProposalRatio) += log (x / m);
-    if (isVPriorExp == YES)
-        (*lnPriorRatio) += brlensExp * (m - x);
-
-    /* if no move in crown, then select randomly, otherwise always the moved branch */
-    if (nCrownNodes == 0 && RandomNumber(seed) < 0.5)
-        p = brlenNode[0];
-    else
-        p = brlenNode[1];
+        if (p == newA)
+            {
+            /* newA is ancestor to a so insert above instead of below */
+            x = newA->length;
+            newA->length = u->length;
+            u->length = x;
+            /* newA is on root path and locked, we need to transfer lock to u */
+            if (newA->isLocked == YES) {
+                u->isLocked = YES;
+                u->lockID = newA->lockID;
+                newA->isLocked = NO;
+                newA->lockID = -1;
+                }
+            }
+        
+        /* hit a length with multiplier */
+        x = a->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
+            }
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / a->length);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (a->length - x);
+        a->length = x;
 
-    /* modify branch length */
-    m = p->length;
-    x = m * exp(tuning * (RandomNumber(seed) - 0.5));
-    while (x < minV || x > maxV)
-        {
-        if (x < minV)
-            x = minV * minV / x;
-        else if (x > maxV)
-            x = maxV * maxV / x;
-        }
-    p->length = x;
-    p->upDateTi = YES;
+        /* hit u length with multiplier */
+        x = u->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
+            }
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / u->length);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (u->length - x);
+        u->length = x;
 
-    /* update proposal and prior ratio based on length modification */
-    (*lnProposalRatio) += log (x / m);
-    if (isVPriorExp == YES)
-        (*lnPriorRatio) += brlensExp * (m - x); 
-        
-    /* if no move in root, then select randomly, otherwise always the moved branch */
-    if (nRootNodes == 0 && RandomNumber(seed) < 0.5)
-        p = brlenNode[4];
-    else
-        p = brlenNode[5];
+        /* hit newA length with multiplier */
+        x = newA->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
+            }
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / newA->length);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (newA->length - x);
+        newA->length = x;
+         
+        /* set tiprobs update flags */
+        newA->upDateTi = YES;
+        a->upDateTi = YES;
+        u->upDateTi = YES;
+            
+        /* set flags for update of cond likes */
+        p = u;
+        while (p->anc != NULL)
+            {
+            p->upDateCl = YES;
+            p = p->anc;
+            }
+        p = b;
+        while (p->anc != NULL)
+            {
+            p->upDateCl = YES;
+            p = p->anc;
+            }
+        }
     
-    /* modify branch length but not if 'root' branch in rooted tree */
-    if (t->isRooted == NO || p->anc->anc != NULL)
+    if (moveInRoot == NO)  /* crown part has changed */
         {
-        m = p->length;
-        x = m * exp(tuning * (RandomNumber(seed) - 0.5));
-        while (x < minV || x > maxV)
+        r = newC;
+        q = newB = newC->anc;
+        /* rotate nodes from newC to c or d (whichever is closest) */
+        tempc = r->length;
+        while (r != c && r != d)
             {
-            if (x < minV)
-                x = minV * minV / x;
-            else if (x > maxV)
-                x = maxV * maxV / x;
+            p = q->anc;
+            /* rotate pointers of q */
+            if (q->left == r)
+                q->left = p;
+            else
+                q->right = p;
+            q->anc = r;
+            /* swap q and old */
+            tempy = q->length;
+            q->length = tempc;
+            q->upDateTi = YES;
+            tempc = tempy;
+            /* make sure we get q and r initialized for next round */
+            r = q;
+            q = p;
             }
-        p->length = x;
-        p->upDateTi = YES;
+        newB->length = tempc;
+            
+        /* hit q length with multiplier while we are at it */
+        x = q->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
+            }        
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / q->length);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (q->length - x);
+        q->length = x;
+        q->upDateTi = YES;
 
-        /* update proposal and prior ratio based on length modification */
-        (*lnProposalRatio) += log (x / m);
+        /* hit newB length with multiplier */
+        x = newB->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
+            }
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / newB->length);
         if (isVPriorExp == YES)
-            (*lnPriorRatio) += brlensExp * (m - x); 
-        }
+            (*lnPriorRatio) += brlensExp * (newB->length - x);
+        newB->length = x;
+        newB->upDateTi = YES;
 
-    /* set flags for update of cond likes from v and down to root */
-    p = v;
-    while (p->anc != NULL)
-        {
-        p->upDateCl = YES;
-        p = p->anc;
+        /* hit newC length with multiplier */
+        x = newC->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
+            }
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / newC->length);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (newC->length - x);
+        newC->length = x;
+        newC->upDateTi = YES;
+ 
+        /* reattach the crown part */
+        v->left = newC;
+        v->right = newB;
+        newC->anc = newB->anc = v;
+        
+        /* set flags for update of cond likes */
+        p = newC;
+        while (p->anc != NULL)
+            {
+            p->upDateCl = YES;
+            p = p->anc;
+            }
+        p = r;
+        while (p->anc != NULL)
+            {
+            p->upDateCl = YES;
+            p = p->anc;
+            }
         }
+    
+    topologyHasChanged = YES;
 
     /* get down pass sequence if tree topology has changed */
     if (topologyHasChanged == YES)
         {
         GetDownPass (t);
         }
-
-#   if defined (DEBUG_RanSPR)
-    printf ("After:\n");
-    ShowNodes (t->root, 2, NO);
-    getchar();
-    printf ("Proposal ratio: %f\n",(*lnProposalRatio));
-    printf ("v: %d  u: %d  c: %d  d: %d  a: %d  b: %d q: %d\n",v->index, u->index, 
-            c->index, d->index, a->index, b->index, q->index);
-    printf ("No. nodes moved in root subtree: %d\n",nRootNodes);
-    printf ("No. nodes moved in crown subtree: %d\n",nCrownNodes);
-    printf ("Has topology changed? %d\n",topologyHasChanged);
-    getchar();
-#   endif
-
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-    gNodeMoves = nCrownNodes + nRootNodes;
-#   endif
-
+    
+    /* Dirichlet or twoExp prior */
+    if (isVPriorExp > 1)
+        (*lnPriorRatio) += LogDirPrior(t, mp, isVPriorExp);
+    
+    /* free up local memory */
+    free (parLength); free (pRoot); free (pCrown); free (nSitesOfPat);
+    
     return (NO_ERROR);
+    
+errorExit:
+    MrBayesPrint ("%s   Problem allocating memory in Move_ParsSPR\n", spacer);
+    free (parLength); free (pRoot); free (pCrown); free (nSitesOfPat);
+    
+    return (ERROR);
 }
 
 
-int Move_RanSPR2 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+int Move_ParsSPRClock (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
 {
-    /* This move is like Move_RanSPR1, except that branches are chosen with equal probability in two subtrees
-       defined by the initially chosen interior branch */
+    /* Change branch lengths and topology (potentially) using SPR-type move, parsimony-biased */
+
+    /* This move picks a branch and then chooses a reattachment point based on
+       the parsimony score. On the ending branch, the attachment point is reinserted
+       randomly along the branch (below the minimum age of the node). Since 2010-11-02
+       the move is Metropolized to improve efficiency. */
     
-    int         i, topologyHasChanged, nCrownNodes, nRootNodes, directionLeft, directionUp, 
-                isVPriorExp, moveInRoot, foundFirst;
-    MrBFlt      m, x, y, tuning, maxV, minV, extensionProb, brlensExp=0.0;
-    TreeNode    *p, *a, *b, *c, *d, *u, *v, *brlenNode[7], *q;
+    int         i, j, n, division, n1=0, n2=0, n3=0, n4=0, n5=0, *nEvents;
+    BitsLong    *pA, *pV, *pP, y[2];
+    MrBFlt      x, oldBrlen=0.0, newBrlen=0.0, v1=0.0, v2=0.0, v3=0.0, v4=0.0, v5=0.0,
+                v3new=0.0, lambda, **position=NULL, **rateMultiplier=NULL, *brlens,
+                igrvar, *igrRate=NULL, nu, *tk02Rate=NULL, minLength=0.0, length=0.0,
+                cumulativeProb, warpFactor, sum1, sum2, ran, increaseProb, decreaseProb,
+                divFactor, nStates, rateMult, v_typical, minV;
+    CLFlt       *nSitesOfPat, *nSites, *globalNSitesOfPat;
+    TreeNode    *p, *a, *b, *u, *v, *c=NULL, *d;
     Tree        *t;
-    ModelParams *mp;
+    ModelInfo   *m=NULL;
+    Param       *subParm;
+
+    warpFactor = mvp[0];                  /* tuning parameter determining how heavily to weight according to parsimony scores */
+    increaseProb = decreaseProb = mvp[1]; /* reweighting probabilities */
+    v_typical = mvp[2];                   /* typical branch length for converting parsimony scores to log prob ratios */
+
+    (*lnProposalRatio) = (*lnPriorRatio) = 0.0;
 
-    /* these parameters should be possible to set by user */
-    extensionProb = mvp[0]; /* extension probability */
-    tuning = mvp[1];        /* Larget & Simon's tuning parameter lambda */
-    
     /* get tree */
     t = GetTree (param, chain, state[chain]);
 
-    /* get model params */
-    mp = &modelParams[param->relParts[0]];
-    
-    /* max and min brlen */
-    if (param->subParams[0]->paramId == BRLENS_UNI)
-        {
-        minV = mp->brlensUni[0] > BRLENS_MIN ? mp->brlensUni[0] : BRLENS_MIN;
-        maxV = mp->brlensUni[1];
-        isVPriorExp = NO;
-        }
-    else
-        {
-        minV = BRLENS_MIN;
-        maxV = BRLENS_MAX;
-        brlensExp = mp->brlensExp;
-        isVPriorExp = YES;
-        }
+    /* get model params and model info */
+    m = &modelSettings[param->relParts[0]];
+    
+    /* get min and max brlen in relative time and subst units */
+    minV = BRLENS_MIN;
+
+#   if defined (DEBUG_ParsSPRClock)
+    printf ("Before:\n");
+    ShowNodes (t->root, 2, YES);
+    getchar();
+#   endif
+    
+    /* pick a branch */
+    do  {
+        p = t->allDownPass[(int)(RandomNumber(seed) * (t->nNodes - 2))];
+        a = p->anc->left;
+        b = p->anc->right;
+        }
+    while (p->anc->isLocked == YES || p->anc->anc->anc == NULL
+           || (p == b && a->length < TIME_MIN) || (p == a && b->length < TIME_MIN));
+    /* skip constraints, siblings of root (and root); and consider ancestral fossils in fbd tree */
+
+    /* set up pointers for nodes around the picked branch */
+    v = p;
+    u = p->anc;
+    if (u->left == v)
+        a = u->right;
+    else
+        a = u->left;
+    b = u->anc;
+
+    /* record branch length for insertion in back move */
+    if (v->length > 0.0)  /* side branch, not anc fossil */
+        {
+        if (v->nodeDepth > a->nodeDepth)
+            oldBrlen = b->nodeDepth - v->nodeDepth - 2.0*minV;
+        else
+            oldBrlen = b->nodeDepth - a->nodeDepth - 2.0*minV;
+        }
+    v1 = a->length;
+    v2 = u->length;
+    v3 = v->length;
+
+    /* reassign events for CPP and adjust prior and proposal ratios for relaxed clock models */
+    for (i=0; i<param->subParams[0]->nSubParams; i++)
+        {
+        subParm = param->subParams[0]->subParams[i];
+        if (subParm->paramType == P_CPPEVENTS)
+            {
+            nEvents = subParm->nEvents[2*chain+state[chain]];
+            position = subParm->position[2*chain+state[chain]];
+            rateMultiplier = subParm->rateMult[2*chain+state[chain]];
+            n1 = nEvents[a->index];
+            n2 = nEvents[u->index];
+            n3 = nEvents[v->index];
+            if (n2 > 0)
+                {
+                position[a->index] = (MrBFlt *) SafeRealloc ((void *) position[a->index], (n1+n2) * sizeof (MrBFlt));
+                rateMultiplier[a->index] = (MrBFlt *) SafeRealloc ((void *) rateMultiplier[a->index], (n1+n2) * sizeof (MrBFlt));
+                }
+            for (j=0; j<n1; j++)
+                position[a->index][j] *= v1 / (v1+v2);
+            for (j=n1; j<n1+n2; j++)
+                {
+                position[a->index][j] = (position[u->index][j-n1] * v2 + v1) / (v1+v2);
+                rateMultiplier[a->index][j] = rateMultiplier[u->index][j-n1];
+                }
+            nEvents[a->index] = n1+n2;
+            nEvents[u->index] = 0;
+            if (n2 > 0)
+                {
+                free (position[u->index]);
+                free (rateMultiplier[u->index]);
+                position[u->index] = rateMultiplier[u->index] = NULL;
+                }
+            /* adjust effective branch lengths */
+            brlens = GetParamSubVals (subParm, chain, state[chain]);
+            brlens[a->index] += brlens[u->index];   /* only change in effective branch lengths so far */
+            }   /* end CPP events parm */
+        else if ( subParm->paramType == P_TK02BRANCHRATES ||
+                 (subParm->paramType == P_MIXEDBRCHRATES && *GetParamIntVals(subParm, chain, state[chain]) == RCL_TK02))
+            {
+            /* adjust prior ratio */
+            if (subParm->paramType == P_TK02BRANCHRATES)
+                nu = *GetParamVals (modelSettings[subParm->relParts[0]].tk02var, chain, state[chain]);
+            else
+                nu = *GetParamVals (modelSettings[subParm->relParts[0]].mixedvar, chain, state[chain]);
+            tk02Rate = GetParamVals (subParm, chain, state[chain]);
+            if (v->length > 0.0)
+                (*lnPriorRatio) -= LnProbTK02LogNormal(tk02Rate[v->anc->index], nu*v->length, tk02Rate[v->index]);
+            (*lnPriorRatio) -= LnProbTK02LogNormal(tk02Rate[a->anc->index], nu*a->length, tk02Rate[a->index]);
+            (*lnPriorRatio) -= LnProbTK02LogNormal(tk02Rate[u->anc->index], nu*u->length, tk02Rate[u->index]);
+            (*lnPriorRatio) += LnProbTK02LogNormal(tk02Rate[u->anc->index], nu*(a->length+u->length), tk02Rate[a->index]);
+            
+            /* adjust effective branch lengths */
+            brlens = GetParamSubVals (subParm, chain, state[chain]);
+            brlens[a->index] = (tk02Rate[a->index] + tk02Rate[b->index]) / 2.0 * (a->length + u->length);
+            }   /* end tk02 branch rate parameter */
+        else if ( subParm->paramType == P_IGRBRANCHRATES ||
+                 (subParm->paramType == P_MIXEDBRCHRATES && *GetParamIntVals(subParm, chain, state[chain]) == RCL_IGR))
+            {
+            if (subParm->paramType == P_IGRBRANCHRATES)
+                igrvar = *GetParamVals (modelSettings[subParm->relParts[0]].igrvar, chain, state[chain]);
+            else
+                igrvar = *GetParamVals (modelSettings[subParm->relParts[0]].mixedvar, chain, state[chain]);
+            igrRate = GetParamVals (subParm, chain, state[chain]);
+
+            /* adjust prior ratio for old branches */
+            if (v->length > 0.0)
+                (*lnPriorRatio) -= LnProbGamma(v->length/igrvar, v->length/igrvar, igrRate[v->index]);
+            (*lnPriorRatio) -= LnProbGamma(a->length/igrvar, a->length/igrvar, igrRate[a->index]);
+            (*lnPriorRatio) -= LnProbGamma(u->length/igrvar, u->length/igrvar, igrRate[u->index]);
+            (*lnPriorRatio) += LnProbGamma((a->length+u->length)/igrvar, (a->length+u->length)/igrvar, igrRate[a->index]);
+
+            /* adjust effective branch lengths */
+            brlens = GetParamSubVals (subParm, chain, state[chain]);
+            brlens[a->index] = igrRate[a->index] * (a->length + u->length);
+            }
+        }   /* next subparameter */
 
-    topologyHasChanged = NO;
+    /* cut tree */
+    a->anc = b;
+    if (b->left == u)
+        b->left = a;
+    else
+        b->right = a;
+    a->length += u->length;
+    a->upDateTi = YES;
 
-#   if defined (DEBUG_RanSPR)
-    printf ("Before:\n");
-    ShowNodes (t->root, 2, NO);
-    getchar();
-#   endif
-    
-    /* pick an internal branch */
-    do
-        {
-        p = t->intDownPass[(int)(RandomNumber(seed)*t->nIntNodes)];
-        } while (p->anc->anc == NULL);
-        
-    /* set up pointers for nodes around the picked branch */
-    /* cut the tree into crown, root and attachment part */
-    /* change the relevant lengths in the attachment part */
-    /* the lengths of a and v are automatically contained in the */
-    /* "attachment" part but the length of c has to be stored in x */
-    v = p;
-    u = p->anc;
+    /* get final parsimony states for the root part */
+    GetParsDP (t, t->root->left, chain);
+    GetParsFP (t, t->root->left->left, chain);
+    GetParsFP (t, t->root->left->right, chain);
 
-    /* store brlen node */
-    brlenNode[3] = v;
+    /* get downpass parsimony states for the crown part */
+    GetParsDP (t, v, chain);
 
-    /* mark crown subtree */
+    /* reset node variables that will be used */
     for (i=0; i<t->nNodes; i++)
         {
         p = t->allDownPass[i];
-        if (p->left == NULL)
-            p->x = 1;
-        else if (p->right != NULL)
-            p->x = p->left->x + p->right->x;
         p->marked = NO;
+        p->d = 0.0;
         }
-    v->marked = YES;
 
+    /* mark nodes in the root part of the tree, first mark a */
+    a->marked = YES;
+    /* then move down towards root taking constraints into account */
+    p = b;
+    while (p->isLocked == NO && p->anc->anc != NULL)
+        {
+        p->marked = YES;
+        p = p->anc;
+        }
+    /* make sure sisters of last node are marked otherwise it will not be marked in the uppass */
+    p->left->marked = YES;
+    p->right->marked = YES;
+    /* finally move up, skip constraints and ancestral fossil */
     for (i=t->nNodes-2; i>=0; i--)
         {
         p = t->allDownPass[i];
-        if (p->anc->marked == YES)
+        if (p != u && p->marked == NO && p->anc->marked == YES && p->anc->isLocked == NO
+            && p->anc->nodeDepth > v->nodeDepth + minV && p->length > 0.0)
             p->marked = YES;
         }
 
-    /* find the subtree */
-    if (v->x <= 2)
-        moveInRoot = YES;
-    else if (t->nNodes - t->nIntNodes - v->x <= 2)
-        moveInRoot = NO;
-    else if (RandomNumber(seed) < 0.5)
-        moveInRoot = NO;
-    else
-        moveInRoot = YES;
-
-    /* find the attachment point */
-    if (RandomNumber(seed) > extensionProb)
-        {
-        q = v->left;
-        moveInRoot = NO;
-        }
-    else
-        {
-        do
-            {
-            q = t->allDownPass[(int)(RandomNumber(seed)*(t->nNodes-1))];
-            } while (q == v || q->anc == v || q == v->anc || q->anc == v->anc ||
-                (moveInRoot == NO && q->marked == NO) || (moveInRoot == YES && q->marked == YES));
-        }
-    
-    /* mark the path of the move */
-    for (i=0; i<t->nNodes; i++)
-        t->allDownPass[i]->marked = NO;
-
-    if (moveInRoot == NO)
-        {
-        p = q;
-        while (p != v)
-            {
-            p->marked = YES;
-            p = p->anc;
-            }
-        v->marked = YES;
-        }
-    else
+    /* unmark nodes if the picked branch is 0 (ancestral fossil) */
+    if (v->length < TIME_MIN)
         {
-        p = q;
-        while (p != NULL)
+        n = 0;
+        for (i=0; i<t->nNodes-1; i++)
             {
-            p->marked = YES;
-            p = p->anc;
+            p = t->allDownPass[i];
+            if (p->nodeDepth > v->nodeDepth - minV || p->anc->nodeDepth < v->nodeDepth + minV)
+                p->marked = NO;
+            if (p->marked == YES)
+                n++;
             }
-        foundFirst = NO;
-        p = v;
-        while (p != NULL)
+        if (n < 2)  /* no new position to move */
             {
-            if (p->marked == NO)
-                p->marked = YES;
-            else if (foundFirst == YES)
-                p->marked = NO;
-            else
-                foundFirst = YES;
-            p = p->anc;
+            abortMove = YES;
+            return (NO_ERROR);
             }
         }
-
-    /* set up pointers for crown part */
-    /* this also determines direction of move in crown part */
-    if (v->left->marked == YES)
-        {
-        c = v->left;
-        d = v->right;
-        directionLeft = YES;
-        }
-    else
-        {
-        c = v->right;
-        d = v->left;
-        directionLeft = NO;
-        }
-
-    /* store brlen nodes and brlen to move */
-    brlenNode[0] = d;
-    brlenNode[1] = c;
-    x = c->length;
-
-    /* cut and reconnect crown part */
-    c->anc = d;
-    d->anc = c;
     
-    /* mark nodes in root part */
-    /* also determines direction of move in root part */
-    if (u->anc->marked == NO)
-        {
-        if (u->left == v)
-            a = u->right;
-        else
-            a = u->left;
-        b = u->anc;
-        directionUp = YES;
-        }
-    else
-        {
-        if (u->left == v)
-            b = u->right;
-        else
-            b = u->left;
-        a = u->anc;
-        directionUp = NO;
-        }
-
-    /* store brlen nodes */
-    if (directionUp == YES)
-        {
-        brlenNode[4] = u;
-        brlenNode[5] = a;
-        }
-    else
-        {
-        brlenNode[4] = b;
-        brlenNode[5] = u;
-        }
-
-    /* cut root part*/
-    /* store branch to move in u->length */
-    if (directionUp == NO) 
-        {
-        b->anc = a;
-        if (a->left == u)
-            a->left = b;
-        else
-            a->right = b;
-        }
-    else 
-        {
-        a->anc = b;
-        if (b->left == u)
-            b->left = a;
-        else
-            b->right = a;
-        y = a->length;
-        a->length = u->length;
-        u->length = y;
-        a->upDateTi = YES;
-        u->upDateTi = YES;
-        }
-
-    /* move around in root subtree */
-    nRootNodes = 0;
-    if (moveInRoot == YES)
-        {
-        for (nRootNodes=0; a->marked == YES; nRootNodes++) 
-            {
-            if (directionUp == YES) 
-                {
-                /* going up tree */
-                if (a->left == NULL)
-                    break;
-                else if (a->left->marked == NO && a->right->marked == NO)
-                    break;      /* don't go further */
-                topologyHasChanged = YES;
-                b = a;
-                if (a->left->marked == YES)
-                    a = a->left;
-                else
-                    a = a->right;
-                if (u->isLocked == YES)
-                    {
-                    b->isLocked = YES;
-                    u->isLocked = NO;
-                    b->lockID = u->lockID;
-                    u->lockID = 0;
-                    }
-                }
-            else 
-                {
-                /* going down tree */
-                if (a->anc == NULL || u->isLocked == YES)
-                    break;      /* can't go further */
-                topologyHasChanged = YES;
-                if (a->anc->marked == NO) 
-                    {
-                    /* try switching direction */
-                    /* find sister of a */
-                    if (a->left == b) 
-                        {
-                        a = a->right;
-                        }
-                    else 
-                        {  
-                        a = a->left;
-                        }
-                    /* as long as we are moving upwards
-                    the cond likes to update will be
-                    flagged by the last pass from u to the root */
-                    if (a->marked == NO)
-                        {
-                        b = a->anc;
-                        b->upDateCl = YES;
-                        a = a->anc->anc;
-                        break;          /* go back and one node down, unsuccessful attempt */
-                        }
-                    else
-                        {
-                        b = a->anc;
-                        directionUp = YES;  /* successful attempt */
-                        }
-                    }   
-                else 
-                    {   /* continue down */                 
-                    b = a;
-                    a = a->anc;
-                    b->upDateCl = YES; 
-                    if (b->isLocked == YES)
-                        {
-                        u->isLocked = YES;
-                        b->isLocked = NO;
-                        u->lockID = b->lockID;
-                        b->lockID = 0;
-                        }
-                    }
-                }
-            }
+    /* find number of site patterns and modify randomly */
+    globalNSitesOfPat = numSitesOfPat + (chainId[chain] % chainParams.numChains) * numCompressedChars + m->compCharStart;
+    nSitesOfPat = (CLFlt *) SafeCalloc (numCompressedChars, sizeof(CLFlt));
+    if (!nSitesOfPat)
+        {
+        MrBayesPrint ("%s   Problem allocating nSitesOfPat in Move_ParsSPRClock\n", spacer);
+        return (ERROR);
         }
-
-    /* store brlen nodes */
-    if (nRootNodes > 0)
+    for (i=0; i<numCompressedChars; i++)
         {
-        if (directionUp == YES)
-            {
-            brlenNode[6] = a;
-            brlenNode[5] = u;
-            }
-        else
+        nSitesOfPat[i] = globalNSitesOfPat[i];
+        for (j=0; j<globalNSitesOfPat[i]; j++)
             {
-            brlenNode[6] = u;
-            brlenNode[5] = b;
+            ran = RandomNumber(seed);
+            if (ran < decreaseProb)
+                nSitesOfPat[i]--;
+            else if (ran > 1.0 - increaseProb)
+                nSitesOfPat[i]++;
             }
         }
 
-    /* move around in crown subtree */
-    nCrownNodes = 0;
-    if (moveInRoot == NO)       
+    /* cycle through the possibilities and record the parsimony length */
+    for (i=0; i<t->nNodes; i++)
         {
-        for (nCrownNodes=0; c->left != NULL; nCrownNodes++) 
+        p = t->allDownPass[i];
+        if (p->marked == NO)
+            continue;
+        /* find the parsimony length */
+        p->d = 0.0;
+        for (n=0; n<t->nRelParts; n++)
             {
-            if (c->left->marked == NO && c->right->marked == NO)
-                break;  /* can't go further */
-            topologyHasChanged = YES;
-            if (c->left->marked == YES) 
+            division = t->relParts[n];
+            
+            /* Find model settings */
+            m = &modelSettings[division];
+
+            /* find nStates and ratemult */
+            nStates = m->numModelStates;
+            if (m->dataType == STANDARD)
+                nStates = 2;
+            rateMult = GetRate(division, chain);
+
+            /* find nSitesOfPat */
+            nSites = nSitesOfPat + m->compCharStart;
+
+            /* get division warp factor */
+            divFactor = - warpFactor * log((1.0/nStates) - exp(-nStates/(nStates-1)*v_typical*rateMult)/nStates);
+
+            /* find downpass parsimony sets for the node and its environment */
+            pP   = m->parsSets[p->index     ];
+            pA   = m->parsSets[p->anc->index];
+            pV   = m->parsSets[v->index     ];
+            
+            length = 0.0;
+            if (m->nParsIntsPerSite == 1)
                 {
-                /* rotate c anticlockwise - prepare pointers for move left */
-                c->anc = c->left;  /* the root will be in the direction we are heading */
-                c->left = c->right;
-                c->right = d;
+                for (j=0; j<m->numChars; j++)
+                    {
+                    y[0] = (pP[j] | pA[j]) & pV[j];
+                    if (y[0] == 0)
+                        length += nSites[j];
+                    }
                 }
-            else 
+            else /* if (m->nParsIntsPerSite == 2) */
                 {
-                /* rotate c clockwise - prepare pointers for move right */
-                c->anc = c->right;  /* the root will be in the direction we are heading */
-                c->right = c->left;
-                c->left = d;  
+                for (j=0; j<2*m->numChars; j+=2)
+                    {
+                    y[0] = (pP[j] | pA[j]) & pV[j];
+                    y[1] = (pP[j+1] | pA[j+1]) & pV[j+1];
+                    if ((y[0] | y[1]) == 0)
+                        length += nSites[j/2];
+                    }
                 }
-            /* OK - let's move!; c->anc points in the right direction
-            don't forget to move the branch lengths as well */
-            d = c;
-            c = c->anc;
-            d->length = c->length;
-            d->upDateCl = YES; 
-            d->upDateTi = YES;
+            p->d += divFactor * length;
             }
         }
 
-    /* store brlen nodes */
-    if (nCrownNodes > 0)
+    /* find the min length and the sum for the forward move */
+    minLength = -1.0;
+    for (i=0; i<t->nNodes; i++)
         {
-        brlenNode[2] = c;
-        brlenNode[1] = d;
+        p = t->allDownPass[i];
+        if (p->marked == NO || p == a)
+            continue;
+        if (minLength < 0.0 || p->d < minLength)
+            minLength = p->d;
         }
-
-    /* combine the subtrees */
-    c->anc = v;
-    d->anc = v;
-    if (directionLeft == YES) 
+    sum1 = 0.0;
+    for (i=0; i<t->nNodes; i++)
         {
-        v->left = c;
-        v->right = d;
+        p = t->allDownPass[i];
+        if (p->marked == YES && p != a)
+            sum1 += exp (minLength - p->d);
         }
-    else 
+
+    /* generate a random uniform */
+    ran = RandomNumber(seed) * sum1;
+
+    /* select the appropriate reattachment point (not a!) */
+    cumulativeProb = 0.0;
+    for (i=0; i<t->nNodes; i++)
         {
-        v->left = d;
-        v->right = c;
+        p = t->allDownPass[i];
+        if (p->marked == YES && p != a)
+            {
+            c = p;
+            cumulativeProb += exp (minLength - p->d);
+            if (cumulativeProb > ran)
+                break;
+            }
         }
 
-    /* the dangling branch is inserted in reverted position
-       such that the back move will be possible
-       if we have moved around in crown subtree
-       otherwise it is left in its original position */
-    if (nCrownNodes > 0)
+    /* calculate the proposal ratio */
+    (*lnProposalRatio) = c->d - minLength + log(sum1);
+
+    /* find the min length and the sum for the backward move */
+    minLength = -1.0;
+    for (i=0; i<t->nNodes; i++)
         {
-        d->length = x;
-        d->upDateTi = YES;
+        p = t->allDownPass[i];
+        if (p->marked == NO || p == c)
+            continue;
+        if (minLength < 0.0 || p->d < minLength)
+            minLength = p->d;
         }
-    else
+    sum2 = 0.0;
+    for (i=0; i<t->nNodes; i++)
         {
-        c->length = x;
+        p = t->allDownPass[i];
+        if (p->marked == YES && p != c)
+            sum2 += exp (minLength - p->d);
         }
+    
+    /* calculate the proposal ratio */
+    (*lnProposalRatio) += minLength - a->d - log(sum2);
 
-    if (directionUp == YES) 
-        {
-        u->anc = b;
-        if (u->left == v)
-            u->right = a;
-        else 
-            u->left = a;
-        a->anc = u;
-        if (b->left == a)
-            b->left = u;
-        else
-            b->right = u;
-        /* the dangling branch is contained in u->length
-           and will automatically be inserted in the right position
-           to enable the back move regardless of whether it was
-           initially directed upwards or downwards
-           BUT if we haven't moved in root subtree, it is advantageous (necessary
-           for rooted trees) to avoid switching branches, which occurs otherwise
-           if directionUp == YES */
-        if (nRootNodes == 0) 
-            {
-            x = u->length;
-            u->length = a->length;
-            a->length = x;
-            a->upDateTi = NO;
-            u->upDateTi = NO;
-            }
-        }
-    else 
+    /* reattach u */
+    d = c->anc;
+    c->anc = u;
+    if (u->left == v)
+        u->right = c;
+    else
+        u->left = c;
+    u->anc = d;
+    if (d->left == c)
+        d->left = u;
+    else
+        d->right = u;
+
+    if (v->length > 0.0)  /* side branch, not anc fossil */
         {
-        u->anc = a;
-        if (u->left == v)
-            u->right = b;
-        else 
-            u->left = b;
-        b->anc = u;
-        if (a->left == b)
-            a->left = u;
+        if (c->nodeDepth > v->nodeDepth)
+            newBrlen = d->nodeDepth - c->nodeDepth - 2.0*minV;
         else
-            a->right = u;
-        /* the modified branch contained in u->length will have
-           to be moved to b->length to enable back move
-           BUT if we haven't moved, it is better to keep it in place
-           (necessary for rooted trees) */
-        if (nRootNodes > 0) 
+            newBrlen = d->nodeDepth - v->nodeDepth - 2.0*minV;
+        if (newBrlen <= 0.0)
             {
-            x = u->length;
-            u->length = b->length;
-            b->length = x;
-            b->upDateTi = YES;
-            u->upDateTi = YES;
+            abortMove = YES;
+            free (nSitesOfPat);
+            return (NO_ERROR);
             }
+
+        /* adjust lengths */
+        u->nodeDepth = d->nodeDepth - minV - RandomNumber(seed) * newBrlen;
+        v->length = u->nodeDepth - v->nodeDepth;
+            
+        /* calculate proposal ratio for tree change */
+        (*lnProposalRatio) += log (newBrlen / oldBrlen);
         }
+    u->length = d->nodeDepth - u->nodeDepth;
+    c->length = u->nodeDepth - c->nodeDepth;
     
-    /* modify branch lengths */
-    /* first modify length of middle branch */
-    m = brlenNode[3]->length;
-    x = m * exp(tuning * (RandomNumber(seed) - 0.5));       /* save the modified dangling branch for later use */
-    while (x < minV || x > maxV)
-        {
-        if (x < minV)
-            x = minV * minV / x;
-        else if (x > maxV)
-            x = maxV * maxV / x;
-        }
-    brlenNode[3]->length = x;
-    brlenNode[3]->upDateTi = YES;
+    v3new = v->length;
+    v4 = c->length;
+    v5 = u->length;
+
+    /* reassign events for CPP and adjust prior and proposal ratios for relaxed clock models */
+    for (i=0; i<param->subParams[0]->nSubParams; i++)
+        {
+        subParm = param->subParams[0]->subParams[i];
+        if (subParm->paramType == P_CPPEVENTS)
+            {
+            nEvents = subParm->nEvents[2*chain+state[chain]];
+            position = subParm->position[2*chain+state[chain]];
+            rateMultiplier = subParm->rateMult[2*chain+state[chain]];
+            for (j=0; j<nEvents[c->index]; j++)
+                {
+                if (position[c->index][j] > v4 / (v4+v5))
+                    break;
+                }
+            n4 = j;
+            n5 = nEvents[c->index] - j;
+            nEvents[u->index] = n5;
+            if (n5 > 0)
+                {
+                position[u->index] = (MrBFlt *) SafeRealloc ((void *) position[u->index], n5 * sizeof (MrBFlt));
+                rateMultiplier[u->index] = (MrBFlt *) SafeRealloc ((void *) rateMultiplier[u->index], n5 * sizeof (MrBFlt));            
+                for (j=n4; j<nEvents[c->index]; j++)
+                    {
+                    position[u->index][j-n4] = (position[c->index][j] * (v4+v5) - v4) / v5;
+                    rateMultiplier[u->index][j-n4] = rateMultiplier[c->index][j];
+                    }
+                if (n4 > 0)
+                    {
+                    position[c->index] = (MrBFlt *) SafeRealloc ((void *) position[c->index], n4 * sizeof (MrBFlt));
+                    rateMultiplier[c->index] = (MrBFlt *) SafeRealloc ((void *) rateMultiplier[c->index], n4 * sizeof (MrBFlt));
+                    for (j=0; j<n4; j++)
+                        position[c->index][j] *= ((v4+v5) / v4);
+                    }
+                else
+                    {
+                    free (position[c->index]);
+                    free (rateMultiplier[c->index]);
+                    position[c->index] = rateMultiplier[c->index] = NULL;
+                    }
+                nEvents[c->index] = n4;
+                }
+            else
+                {
+                for (j=0; j<nEvents[c->index]; j++)
+                    position[c->index][j] *= ((v4+v5) / v4);
+                }
 
-    /* update proposal and prior ratio based on length modification */
-    (*lnProposalRatio) += log (x / m);
-    if (isVPriorExp == YES)
-        (*lnPriorRatio) += brlensExp * (m - x);
+            /* adjust proposal ratio */
+            (*lnProposalRatio) += n3 * log (v3new / v3);
 
-    /* if no move in crown, then select randomly, otherwise always the moved branch */
-    if (nCrownNodes == 0 && RandomNumber(seed) < 0.5)
-        p = brlenNode[0];
-    else
-        p = brlenNode[1];
+            /* adjust prior ratio */
+            lambda = *GetParamVals (modelSettings[subParm->relParts[0]].cppRate, chain, state[chain]);
+            (*lnPriorRatio) += lambda * (v3 - v3new);
 
-    /* modify branch length */
-    m = p->length;
-    x = m * exp(tuning * (RandomNumber(seed) - 0.5));
-    while (x < minV || x > maxV)
-        {
-        if (x < minV)
-            x = minV * minV / x;
-        else if (x > maxV)
-            x = maxV * maxV / x;
-        }
-    p->length = x;
-    p->upDateTi = YES;
+            /* update effective branch lengths */
+            if (UpdateCppEvolLengths (subParm, a, chain) == ERROR)
+                {
+                abortMove = YES;
+                free (nSitesOfPat);
+                return (NO_ERROR);
+                }
 
-    /* update proposal and prior ratio based on length modification */
-    (*lnProposalRatio) += log (x / m);
-    if (isVPriorExp == YES)
-        (*lnPriorRatio) += brlensExp * (m - x); 
-        
-    /* if no move in root, then select randomly, otherwise always the moved branch */
-    if (nRootNodes == 0 && RandomNumber(seed) < 0.5)
-        p = brlenNode[4];
-    else
-        p = brlenNode[5];
-    
-    /* modify branch length but not if 'root' branch in rooted tree */
-    if (t->isRooted == NO || p->anc->anc != NULL)
-        {
-        m = p->length;
-        x = m * exp(tuning * (RandomNumber(seed) - 0.5));
-        while (x < minV || x > maxV)
+            if (UpdateCppEvolLengths (subParm, u, chain) == ERROR)
+                {
+                abortMove = YES;
+                free (nSitesOfPat);
+                return (NO_ERROR);
+                }
+            }   /* end cpp events parameter */
+        else if ( subParm->paramType == P_TK02BRANCHRATES ||
+                 (subParm->paramType == P_MIXEDBRCHRATES && *GetParamIntVals(subParm, chain, state[chain]) == RCL_TK02))
             {
-            if (x < minV)
-                x = minV * minV / x;
-            else if (x > maxV)
-                x = maxV * maxV / x;
-            }
-        p->length = x;
-        p->upDateTi = YES;
+            /* adjust prior ratio */
+            if (subParm->paramType == P_TK02BRANCHRATES)
+                nu = *GetParamVals (modelSettings[subParm->relParts[0]].tk02var, chain, state[chain]);
+            else
+                nu = *GetParamVals (modelSettings[subParm->relParts[0]].mixedvar, chain, state[chain]);
+            tk02Rate = GetParamVals (subParm, chain, state[chain]);
+            (*lnPriorRatio) -= LnProbTK02LogNormal(tk02Rate[u->anc->index], nu*(c->length+u->length), tk02Rate[c->index]);
+            (*lnPriorRatio) += LnProbTK02LogNormal(tk02Rate[c->anc->index], nu*c->length, tk02Rate[c->index]);
+            (*lnPriorRatio) += LnProbTK02LogNormal(tk02Rate[u->anc->index], nu*u->length, tk02Rate[u->index]);
+            if (v->length > 0.0)
+                (*lnPriorRatio) += LnProbTK02LogNormal(tk02Rate[v->anc->index], nu*v->length, tk02Rate[v->index]);
 
-        /* update proposal and prior ratio based on length modification */
-        (*lnProposalRatio) += log (x / m);
-        if (isVPriorExp == YES)
-            (*lnPriorRatio) += brlensExp * (m - x); 
-        }
+            /* adjust effective branch lengths */
+            brlens = GetParamSubVals (subParm, chain, state[chain]);
+            brlens[c->index] = c->length * (tk02Rate[c->index] + tk02Rate[c->anc->index]) / 2.0;
+            brlens[v->index] = v->length * (tk02Rate[v->index] + tk02Rate[v->anc->index]) / 2.0;
+            brlens[u->index] = u->length * (tk02Rate[u->index] + tk02Rate[u->anc->index]) / 2.0;
+            }   /* end tk02 branch rate parameter */
+        else if ( subParm->paramType == P_IGRBRANCHRATES ||
+                 (subParm->paramType == P_MIXEDBRCHRATES && *GetParamIntVals(subParm, chain, state[chain]) == RCL_IGR))
+            {
+            /* adjust prior ratio */
+            if (subParm->paramType == P_IGRBRANCHRATES)
+                igrvar = *GetParamVals (modelSettings[subParm->relParts[0]].igrvar, chain, state[chain]);
+            else
+                igrvar = *GetParamVals (modelSettings[subParm->relParts[0]].mixedvar, chain, state[chain]);
+            igrRate = GetParamVals (subParm, chain, state[chain]);
+            (*lnPriorRatio) -= LnProbGamma ((c->length+u->length)/igrvar, (c->length+u->length)/igrvar, igrRate[c->index]);
+            (*lnPriorRatio) += LnProbGamma (c->length/igrvar, c->length/igrvar, igrRate[c->index]);
+            (*lnPriorRatio) += LnProbGamma (u->length/igrvar, u->length/igrvar, igrRate[u->index]);
+            if (v->length > 0.0)
+                (*lnPriorRatio) += LnProbGamma (v->length/igrvar, v->length/igrvar, igrRate[v->index]);
 
-    /* set flags for update of cond likes from v and down to root */
-    p = v;
+            /* adjust effective branch lengths */
+            brlens = GetParamSubVals (subParm, chain, state[chain]);
+            brlens[v->index] = igrRate[v->index] * v->length;
+            brlens[u->index] = igrRate[u->index] * u->length;
+            brlens[c->index] = igrRate[c->index] * c->length;
+            }   /* end igr branch rate parameter */
+        }   /* next subparameter */
+
+    /* set tiprobs update flags */
+    c->upDateTi = YES;
+    u->upDateTi = YES;
+    v->upDateTi = YES;
+
+    /* set flags for update of cond likes down to root */
+    p = u;
     while (p->anc != NULL)
         {
-        p->upDateCl = YES;
+        p->upDateCl = YES; 
+        p = p->anc;
+        }
+    p = b;
+    while (p->anc != NULL)
+        {
+        p->upDateCl = YES; 
         p = p->anc;
         }
 
-    /* get down pass sequence if tree topology has changed */
-    if (topologyHasChanged == YES)
+    /* get down pass sequence */
+    GetDownPass (t);
+
+    /* adjust prior ratio for clock tree */
+    if (LogClockTreePriorRatio (param, chain, &x) == ERROR)
         {
-        GetDownPass (t);
+        free (nSitesOfPat);
+        return (ERROR);
         }
+    (*lnPriorRatio) += x;
 
-#   if defined (DEBUG_RanSPR)
-    printf ("After:\n");
-    ShowNodes (t->root, 2, NO);
-    getchar();
-    printf ("Proposal ratio: %f\n",(*lnProposalRatio));
-    printf ("v: %d  u: %d  c: %d  d: %d  a: %d  b: %d q: %d\n",v->index, u->index, 
-            c->index, d->index, a->index, b->index, q->index);
-    printf ("No. nodes moved in root subtree: %d\n",nRootNodes);
-    printf ("No. nodes moved in crown subtree: %d\n",nCrownNodes);
-    printf ("Has topology changed? %d\n",topologyHasChanged);
+#   if defined (DEBUG_ParsSPRClock)
+    ShowNodes (t->root, 2, YES);
+    printf ("After\nProposal ratio: %f\n",(*lnProposalRatio));
+    printf ("v: %d  u: %d  a: %d  b: %d c: %d\n",v->index, u->index, a->index, b->index, c->index);
     getchar();
 #   endif
 
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-    gNodeMoves = nCrownNodes + nRootNodes;
-#   endif
-
+    free (nSitesOfPat);
     return (NO_ERROR);
 }
 
 
-int Move_RanSPR3 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+int Move_ParsTBR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
 {
-    /* This is a random SPR move controlled by a window defined by a certain node distance radius,
-       within which the random subtree swapping occurs */
+    /* Change topology and map branch lengths using TBR-type move biased according to parsimony scores,
+       controlled by a window defined by a certain node distance radius. */
     
-    int         i, topologyHasChanged, nCrownNodes, nRootNodes, directionLeft, directionUp, 
-                isVPriorExp, moveInRoot, foundFirst, windowDiameter, numWindowNodes, newNumWindowNodes;
-    MrBFlt      m, x, y, tuning, maxV, minV, moveProb, brlensExp=0.0;
-    TreeNode    *p, *a, *b, *c, *d, *u, *v, *brlenNode[7], *q, *windowNode[120];
+    int         i, j, k, n, division, topologyHasChanged, nNeighbor, nRoot, nCrown, iA, jC, isVPriorExp;
+    BitsLong    *pA, *pB, *pC, *pD, y[2];
+    MrBFlt      x, minV, maxV, brlensExp=0.0, minLength=0.0, length=0.0, *parLength=NULL, prob, ran, tuning, warpFactor,
+                sum1, sum2, tempsum, tempc, tempy;
+    CLFlt       *nSites, *nSitesOfPat=NULL, *globalNSitesOfPat;
+    TreeNode    *p, *q, *r, *a, *b, *u, *v, *c, *d, *newB, *newA, *newC, **pRoot=NULL, **pCrown=NULL;
     Tree        *t;
     ModelParams *mp;
-
-    /* these parameters should be possible to set by user */
-    moveProb = mvp[0];  /* extension probability */
-    tuning = mvp[1];        /* Larget & Simon's tuning parameter lambda */
-    windowDiameter = 4;     /* window diameter in number of nodes away from the cut branch */
-                            /* set it to a value between 1 and 4 (above 4 requires more space in windowNode) */
-    /* get tree */
-    t = GetTree (param, chain, state[chain]);
-
-    /* get model params */
-    mp = &modelParams[param->relParts[0]];
+    ModelInfo   *m=NULL;
     
-    /* max and min brlen */
-    if (param->subParams[0]->paramId == BRLENS_UNI)
-        {
-        minV = mp->brlensUni[0] > BRLENS_MIN ? mp->brlensUni[0] : BRLENS_MIN;
-        maxV = mp->brlensUni[1];
-        isVPriorExp = NO;
-        }
-    else
-        {
-        minV = BRLENS_MIN;
-        maxV = BRLENS_MAX;
-        brlensExp = mp->brlensExp;
-        isVPriorExp = YES;
-        }
-
-    topologyHasChanged = NO;
+    warpFactor = mvp[0];                  /* tuning parameter determining how heavily to weight according to parsimony scores */
+//  increaseProb = decreaseProb = mvp[1]; /* reweighting probabilities */
+//  v_typical = mvp[2];                   /* typical branch length for conversion of parsimony score to log prob ratio */
+    tuning = mvp[3];                      /* multiplier tuning parameter */
+    nNeighbor = (int)mvp[4];              /* distance to move picked branch in root and crown part */
 
-#   if defined (DEBUG_RanSPR)
-    printf ("Before:\n");
-    ShowNodes (t->root, 2, NO);
-    getchar();
-#   endif
+    (*lnProposalRatio) = (*lnPriorRatio) = 0.0;
     
-    /* pick an internal branch */
-    do
-        {
-        p = t->intDownPass[(int)(RandomNumber(seed)*t->nIntNodes)];
-        } while (p->anc->anc == NULL);
-        
-    /* set up pointers for nodes around the picked branch */
-    /* cut the tree into crown, root and attachment part */
-    /* change the relevant lengths in the attachment part */
-    /* the lengths of a and v are automatically contained in the */
-    /* "attachment" part but the length of c has to be stored in x */
-    v = p;
-    u = p->anc;
-
-    /* store brlen node */
-    brlenNode[3] = v;
-
-    /* mark distance of nodes from the node v */
-    for (i=0; i<t->nNodes; i++)
-        {
-        p = t->allDownPass[i];
-        p->x = -1;
-        }
+    /* get model params and model info */
+    mp = &modelParams[param->relParts[0]];
+    m = &modelSettings[param->relParts[0]];
     
-    v->x = 0;
-    u->x = 0;
-
-    /* downpass */
-    for (p=u; p->anc!= NULL; p=p->anc)
-        {
-        p->anc->x = p->x+1;
-        }
-        
-    /* uppass */
-    for (i=t->nNodes-2; i>=0; i--)
+    /* get tree */
+    t = GetTree (param, chain, state[chain]);
+    
+    /* max and min brlen */
+    if (param->subParams[0]->paramId == BRLENS_UNI)
         {
-        p = t->allDownPass[i];
-        if (p->x < 0)
-            p->x = p->anc->x + 1;
+        minV = mp->brlensUni[0] > BRLENS_MIN ? mp->brlensUni[0] : BRLENS_MIN;
+        maxV = mp->brlensUni[1] < BRLENS_MAX ? mp->brlensUni[1] : BRLENS_MAX;
+        isVPriorExp = NO;
         }
-        
-    /* now collect nodes */
-    for (i=numWindowNodes=0; i<t->nNodes; i++)
+    else if (param->subParams[0]->paramId == BRLENS_GamDir)
         {
-        p = t->allDownPass[i];
-        if (p->x >= 2 && p->x <= windowDiameter+1)
-            windowNode[numWindowNodes++] = p;
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        isVPriorExp = 2;
         }
-    if (numWindowNodes > 120)
+    else if (param->subParams[0]->paramId == BRLENS_iGmDir)
         {
-        printf ("error\n");
-        ShowNodes (t->root, 0, t->isRooted);
-        for (i=0; i<t->nNodes; i++)
-            printf ("%d\t%d\n", t->allDownPass[i]->index, t->allDownPass[i]->x);
-        getchar();
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        isVPriorExp = 3;
         }
-
-    /* find the attachment point */
-    if (RandomNumber(seed) > moveProb)
+    else if (param->subParams[0]->paramId == BRLENS_twoExp)
         {
-        q = v->left;
-        moveInRoot = NO;
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        isVPriorExp = 4;
         }
     else
         {
-        q = windowNode[(int)(RandomNumber(seed)*numWindowNodes)];
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        brlensExp = mp->brlensExp;
+        isVPriorExp = YES;
         }
+
+    /* Dirichlet or twoExp prior */
+    if (isVPriorExp > 1)
+        (*lnPriorRatio) = -LogDirPrior(t, mp, isVPriorExp);
+    
+    /* set topologyHasChanged to NO */
+    topologyHasChanged = NO;
     
-    /* mark crown subtree */
+    /* reset node variables that will be used */
     for (i=0; i<t->nNodes; i++)
         {
         p = t->allDownPass[i];
+        p->x = 0;
         p->marked = NO;
         }
-    v->marked = YES;
 
-    for (i=t->nNodes-2; i>=0; i--)
-        {
-        p = t->allDownPass[i];
-        if (p->anc->marked == YES)
-            p->marked = YES;
+    /* pick an internal branch */
+    do  {
+        p = t->intDownPass[(int)(RandomNumber(seed)*(t->nIntNodes-1))];
+        q = p->anc->left;
+        if (q == p)  q = p->anc->right;
+        i = j = 0;
+        if (q->isLocked == YES || q->left == NULL)
+            i++;
+        if (p->anc->isLocked == YES || p->anc->anc->anc == NULL)
+            i++;
+        if (p->left->isLocked == YES || p->left->left == NULL)
+            j++;
+        if (p->right->isLocked == YES || p->right->left == NULL)
+            j++;
         }
+    while (i == 2 && j == 2);
+    
+    /* set up pointers for nodes around the picked branch */
+    v = p;            u = p->anc;
+    c = p->left;      d = p->right;
+    if (u->left == v) a = u->right;
+    else              a = u->left;
+    b = u->anc;
+    /* clip root part of tree */
+    a->anc = b;
+    if (b->left == u) b->left = a;
+    else              b->right = a;
+    /* clip crown part of tree */
+    c->anc = d;
+    d->anc = c;
+    /* should never change u, v, a, b, c, d pointers */
 
-    /* find the subtree */
-    if (q->marked == YES)
-        moveInRoot = NO;
-    else
-        moveInRoot = YES;
-
-    /* mark the path of the move */
-    for (i=0; i<t->nNodes; i++)
-        t->allDownPass[i]->marked = NO;
-
-    if (moveInRoot == NO)
-        {
-        p = q;
-        while (p != v)
-            {
-            p->marked = YES;
-            p = p->anc;
-            }
-        v->marked = YES;
-        }
-    else
+    /* mark nodes nNeighbor away in root (negative) and crown (positive) respecting constraints */
+    /* first move down towards root */
+    nRoot = nCrown = 0;
+    if (u->isLocked == NO)
         {
-        p = q;
-        while (p != NULL)
-            {
-            p->marked = YES;
-            p = p->anc;
-            }
-        foundFirst = NO;
-        p = v;
-        while (p != NULL)
+        p = a; q = b; n = 0;
+        while (q->anc != NULL)
             {
-            if (p->marked == NO)
-                p->marked = YES;
-            else if (foundFirst == YES)
-                p->marked = NO;
+            q->marked = YES;
+            q->x = n;    // temporary, for MarkDistance below
+            if (q->left == p)
+                MarkDistance(q->right, YES, nNeighbor, &nRoot);
             else
-                foundFirst = YES;
-            p = p->anc;
+                MarkDistance(q->left,  YES, nNeighbor, &nRoot);
+            q->x = --n;  // final
+            nRoot++;
+            if (q->isLocked == YES || abs(q->x) >= nNeighbor)
+                break;
+            p = q; q = q->anc;
             }
         }
-
-    /* set up pointers for crown part */
-    /* this also determines direction of move in crown part */
-    if (v->left->marked == YES)
-        {
-        c = v->left;
-        d = v->right;
-        directionLeft = YES;
-        }
-    else
+    /* then move up in root part */
+    a->marked = YES; nRoot++;
+    if (a->isLocked == NO)
         {
-        c = v->right;
-        d = v->left;
-        directionLeft = NO;
+        MarkDistance(a->left,  YES, nNeighbor, &nRoot);
+        MarkDistance(a->right, YES, nNeighbor, &nRoot);
         }
-
-    /* store brlen nodes and brlen to move */
-    brlenNode[0] = d;
-    brlenNode[1] = c;
-    x = c->length;
-
-    /* cut and reconnect crown part */
-    c->anc = d;
-    d->anc = c;
-    
-    /* mark nodes in root part */
-    /* also determines direction of move in root part */
-    if (u->anc->marked == NO)
+    /* finally in crown part */
+    c->marked = YES; nCrown++;
+    if (c->isLocked == NO)
         {
-        if (u->left == v)
-            a = u->right;
-        else
-            a = u->left;
-        b = u->anc;
-        directionUp = YES;
+        MarkDistance(c->left,  NO, nNeighbor, &nCrown);
+        MarkDistance(c->right, NO, nNeighbor, &nCrown);
         }
-    else
+    if (d->isLocked == NO)
         {
-        if (u->left == v)
-            b = u->right;
-        else
-            b = u->left;
-        a = u->anc;
-        directionUp = NO;
+        MarkDistance(d->left,  NO, nNeighbor, &nCrown);
+        MarkDistance(d->right, NO, nNeighbor, &nCrown);
         }
 
-    /* store brlen nodes */
-    if (directionUp == YES)
-        {
-        brlenNode[4] = u;
-        brlenNode[5] = a;
-        }
-    else
-        {
-        brlenNode[4] = b;
-        brlenNode[5] = u;
+    /* need to alloc a matrix for parsimony lengths, an array of pointers to crown part,
+       and an array of pointers to root part. */
+    parLength = (MrBFlt *) SafeCalloc ((size_t)nRoot * (size_t)nCrown, sizeof(MrBFlt));
+    pRoot  = (TreeNode **) SafeCalloc(nRoot,  sizeof(TreeNode *));
+    pCrown = (TreeNode **) SafeCalloc(nCrown, sizeof(TreeNode *));
+    if (!parLength || !pRoot || !pCrown)  goto errorExit;
+    /* starting position */
+    pRoot[0] = a; pCrown[0] = c;
+    for (i=j=1, n=t->nNodes-2; n>=0; n--)
+        {  /* and the rest */
+        p = t->allDownPass[n];
+        if (p->marked == YES && p->x < 0)
+            pRoot[i++] = p;
+        if (p->marked == YES && p->x > 0)
+            pCrown[j++] = p;
         }
+    assert (i==nRoot && j==nCrown);
 
-    /* cut root part*/
-    /* store branch to move in u->length */
-    if (directionUp == NO) 
-        {
-        b->anc = a;
-        if (a->left == u)
-            a->left = b;
-        else
-            a->right = b;
-        }
-    else 
+    /* get final parsimony state sets for the root part */
+    GetParsDP (t, t->root->left, chain);
+    GetParsFP (t, t->root->left, chain);
+    /* get final parsimony state sets for the crown part */
+    GetParsDP (t, c, chain);
+    GetParsDP (t, d, chain);
+    GetParsFP (t, c, chain);
+    GetParsFP (t, d, chain);
+
+    /* find number of site patterns and modify randomly */
+    globalNSitesOfPat = numSitesOfPat + (chainId[chain] % chainParams.numChains) * numCompressedChars + m->compCharStart;
+    nSitesOfPat = (CLFlt *) SafeCalloc (numCompressedChars, sizeof(CLFlt));
+    if (!nSitesOfPat)  goto errorExit;
+    for (i=0; i<numCompressedChars; i++)
         {
-        a->anc = b;
-        if (b->left == u)
-            b->left = a;
-        else
-            b->right = a;
-        y = a->length;
-        a->length = u->length;
-        u->length = y;
-        a->upDateTi = YES;
-        u->upDateTi = YES;
+        nSitesOfPat[i] = globalNSitesOfPat[i];
+    /*  for (j=0; j<globalNSitesOfPat[i]; j++)
+            {
+            ran = RandomNumber(seed);
+            if (ran < decreaseProb)
+                nSitesOfPat[i]--;
+            else if (ran > 1.0 - increaseProb)
+                nSitesOfPat[i]++;
+            }  // this is not used at the moment */
         }
 
-    /* move around in root subtree */
-    nRootNodes = 0;
-    if (moveInRoot == YES)
+    /* cycle through the possibilities and record the parsimony length */
+    for (j=0; j<nCrown; j++)
         {
-        for (nRootNodes=0; a->marked == YES; nRootNodes++) 
+        for (i=0; i<nRoot; i++)
             {
-            if (directionUp == YES) 
-                {
-                /* going up tree */
-                if (a->left == NULL)
-                    break;
-                else if (a->left->marked == NO && a->right->marked == NO)
-                    break;      /* don't go further */
-                topologyHasChanged = YES;
-                b = a;
-                if (a->left->marked == YES)
-                    a = a->left;
-                else
-                    a = a->right;
-                if (u->isLocked == YES)
-                    {
-                    b->isLocked = YES;
-                    u->isLocked = NO;
-                    b->lockID = u->lockID;
-                    u->lockID = 0;
-                    }
-                }
-            else 
+            parLength[i+j*nRoot] = 0.0;
+            for (n=0; n<t->nRelParts; n++)
                 {
-                /* going down tree */
-                if (a->anc == NULL || u->isLocked == YES)
-                    break;      /* can't go further */
-                topologyHasChanged = YES;
-                if (a->anc->marked == NO) 
+                division = t->relParts[n];
+                
+                /* Find model settings */
+                m = &modelSettings[division];
+                
+                /* find nSitesOfPat */
+                nSites = nSitesOfPat + m->compCharStart;
+                    
+                /* find downpass parsimony sets for the potential new connection nodes and their environment */
+                pA = m->parsSets[pRoot[i]->index];
+                pB = m->parsSets[pRoot[i]->anc->index];
+                pC = m->parsSets[pCrown[j]->index];
+                pD = m->parsSets[pCrown[j]->anc->index];
+                    
+                length = 0.0;
+                if (m->nParsIntsPerSite == 1)
                     {
-                    /* try switching direction */
-                    /* find sister of a */
-                    if (a->left == b) 
-                        {
-                        a = a->right;
-                        }
-                    else 
-                        {  
-                        a = a->left;
-                        }
-                    /* as long as we are moving upwards
-                    the cond likes to update will be
-                    flagged by the last pass from u to the root */
-                    if (a->marked == NO)
-                        {
-                        b = a->anc;
-                        b->upDateCl = YES;
-                        a = a->anc->anc;
-                        break;          /* go back and one node down, unsuccessful attempt */
-                        }
-                    else
+                    for (k=0; k<m->numChars; k++)
                         {
-                        b = a->anc;
-                        directionUp = YES;  /* successful attempt */
+                        y[0] = (pC[k] | pD[k]) & (pA[k] | pB[k]);
+                        if (y[0] == 0)
+                            length += nSites[k];
                         }
-                    }   
-                else 
-                    {   /* continue down */                 
-                    b = a;
-                    a = a->anc;
-                    b->upDateCl = YES; 
-                    if (b->isLocked == YES)
+                    }
+                else /* if (m->nParsIntsPerSite == 2) */
+                    {
+                    for (k=0; k<2*m->numChars; k+=2)
                         {
-                        u->isLocked = YES;
-                        b->isLocked = NO;
-                        u->lockID = b->lockID;
-                        b->lockID = 0;
+                        y[0] = (pC[k] | pD[k]) & (pA[k] | pB[k]);
+                        y[1] = (pC[k+1] | pD[k+1]) & (pA[k+1] | pB[k+1]);;
+                        if ((y[0] | y[1]) == 0)
+                            length += nSites[k/2];
                         }
                     }
+                parLength[i+j*nRoot] += warpFactor * length;
                 }
             }
         }
 
-    /* store brlen nodes */
-    if (nRootNodes > 0)
-        {
-        if (directionUp == YES)
+    /* find the min length and the sum for the forward move */
+    minLength = -1.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
             {
-            brlenNode[6] = a;
-            brlenNode[5] = u;
+            if (i == 0 && j == 0)  // exclude original position
+                continue;
+            if (minLength > parLength[i+j*nRoot] || minLength < 0.0)
+                minLength = parLength[i+j*nRoot];
             }
-        else
+    sum1 = 0.0; tempc = 0.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
             {
-            brlenNode[6] = u;
-            brlenNode[5] = b;
+            if (i == 0 && j == 0)  // exclude original position
+                continue;
+            /* Kahan summation to reduce numerical error */
+            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
+            tempsum = sum1 + tempy;  tempc = (tempsum - sum1) - tempy;
+            sum1 = tempsum;
+            // sum1 += exp(minLength - parLength[i+j*nRoot]);
+            // printf("%d %d %lf\n", i, j, exp(minLength - parLength[i+j*nRoot]));
             }
-        }
 
-    /* move around in crown subtree */
-    nCrownNodes = 0;
-    if (moveInRoot == NO)       
-        {
-        for (nCrownNodes=0; c->left != NULL; nCrownNodes++) 
+    /* generate a random uniform */
+    ran = RandomNumber(seed) * sum1;
+
+    /* select the appropriate reattachment point */
+    newA = a; newC = c;
+    prob = 0.0; tempc = 0.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
             {
-            if (c->left->marked == NO && c->right->marked == NO)
-                break;  /* can't go further */
-            topologyHasChanged = YES;
-            if (c->left->marked == YES) 
-                {
-                /* rotate c anticlockwise - prepare pointers for move left */
-                c->anc = c->left;  /* the root will be in the direction we are heading */
-                c->left = c->right;
-                c->right = d;
-                }
-            else 
-                {
-                /* rotate c clockwise - prepare pointers for move right */
-                c->anc = c->right;  /* the root will be in the direction we are heading */
-                c->right = c->left;
-                c->left = d;  
+            if (i == 0 && j == 0)  // exclude original position
+                continue;
+            // prob += exp (minLength - parLength[i+j*nRoot]);
+            /* Kahan summation to reduce numerical error */
+            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
+            tempsum = prob + tempy;  tempc = (tempsum - prob) - tempy;
+            prob = tempsum;
+            if (prob > ran) {
+                /* proposed new attaching position */
+                newA = pRoot[i];
+                newC = pCrown[j];
+                goto outLoop;
                 }
-            /* OK - let's move!; c->anc points in the right direction
-            don't forget to move the branch lengths as well */
-            d = c;
-            c = c->anc;
-            d->length = c->length;
-            d->upDateCl = YES; 
-            d->upDateTi = YES;
             }
-        }
+outLoop:;
+    iA = i; jC = j;
 
-    /* store brlen nodes */
-    if (nCrownNodes > 0)
-        {
-        brlenNode[2] = c;
-        brlenNode[1] = d;
-        }
+    /* calculate the proposal ratio */
+    (*lnProposalRatio) = parLength[i+j*nRoot] - minLength + log(sum1);
 
-    /* combine the subtrees */
-    c->anc = v;
-    d->anc = v;
-    if (directionLeft == YES) 
-        {
-        v->left = c;
-        v->right = d;
-        }
-    else 
-        {
-        v->left = d;
-        v->right = c;
-        }
+    /* find the min length and the sum for the backward move */
+    minLength = -1.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
+            {
+            if (i == iA && j == jC)  // exclude new position
+                continue;
+            if (minLength > parLength[i+j*nRoot] || minLength < 0.0)
+                minLength = parLength[i+j*nRoot];
+            }
+    sum2 = 0.0; tempc = 0.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
+            {
+            if (i == iA && j == jC)  // exclude new position
+                continue;
+            /* Kahan summation to reduce numerical error */
+            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
+            tempsum = sum2 + tempy;  tempc = (tempsum - sum2) - tempy;
+            sum2 = tempsum;
+            // sum2 += exp (minLength - parLength[i+j*nRoot]);
+            // printf("%d %d %lf\n", i, j, exp(minLength - parLength[i+j*nRoot]));
+            }
 
-    /* the dangling branch is inserted in reverted position
-       such that the back move will be possible
-       if we have moved around in crown subtree
-       otherwise it is left in its original position */
-    if (nCrownNodes > 0)
-        {
-        d->length = x;
-        d->upDateTi = YES;
-        }
+    /* calculate the proposal ratio */
+    (*lnProposalRatio) += minLength - parLength[0] - log(sum2);
+
+    /* reattach the root part */
+    newB = newA->anc;
+    newA->anc = u;
+    if (u->left == v)
+        u->right = newA;
     else
-        {
-        c->length = x;
-        }
+        u->left = newA;
+    u->anc = newB;
+    if (newB->left == newA)
+        newB->left = u;
+    else
+        newB->right = u;
 
-    if (directionUp == YES) 
+    /* transfer lock and reassign branch lengths, if necessary */
+    if (newA != a)
         {
-        u->anc = b;
-        if (u->left == v)
-            u->right = a;
-        else 
-            u->left = a;
-        a->anc = u;
-        if (b->left == a)
-            b->left = u;
-        else
-            b->right = u;
-        /* the dangling branch is contained in u->length
-           and will automatically be inserted in the right position
-           to enable the back move regardless of whether it was
-           initially directed upwards or downwards
-           BUT if we haven't moved in root subtree, it is advantageous (necessary
-           for rooted trees) to avoid switching branches, which occurs otherwise
-           if directionUp == YES */
-        if (nRootNodes == 0) 
+        /* if u is locked, then we have moved upwards and need to leave the u lock behind */
+        if (u->isLocked == YES)
+            {
+            u->isLocked = NO;
+            a->isLocked = YES;
+            a->lockID = u->lockID;
+            u->lockID = -1;
+            }
+
+        p = newA;
+        while (p->anc != NULL)
+            {
+            if (p == a) break;
+            p = p->anc;
+            }
+        if (p == a)
+            {
+            /* newA is descendant to a so move a->length not u->length */
+            x = u->length;
+            u->length = a->length;
+            a->length = x;
+            }
+
+        p = b;
+        while (p->anc != NULL)
+            {
+            if (p == newA) break;
+            p = p->anc;
+            }
+        if (p == newA)
+            {
+            /* newA is ancestor to a so insert above instead of below */
+            x = newA->length;
+            newA->length = u->length;
+            u->length = x;
+            /* newA is on root path and locked, we need to transfer lock to u */
+            if (newA->isLocked == YES) {
+                u->isLocked = YES;
+                u->lockID = newA->lockID;
+                newA->isLocked = NO;
+                newA->lockID = -1;
+                }
+            }
+            
+        /* hit u length with multiplier */
+        x = u->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
             {
-            x = u->length;
-            u->length = a->length;
-            a->length = x;
-            a->upDateTi = NO;
-            u->upDateTi = NO;
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
             }
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / u->length);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (u->length - x);
+        u->length = x;
+
+        /* set tiprobs update flags */
+        u->upDateTi = YES;
+        newA->upDateTi = YES;
+        a->upDateTi = YES;
         }
-    else 
+    
+    r = newC;
+    q = newB = newC->anc;
+    if (newC != c)  // crown part has changed
         {
-        u->anc = a;
-        if (u->left == v)
-            u->right = b;
-        else 
-            u->left = b;
-        b->anc = u;
-        if (a->left == b)
-            a->left = u;
-        else
-            a->right = u;
-        /* the modified branch contained in u->length will have
-           to be moved to b->length to enable back move
-           BUT if we haven't moved, it is better to keep it in place
-           (necessary for rooted trees) */
-        if (nRootNodes > 0) 
+        /* rotate nodes from newC to c or d (whichever is closest) */
+        tempc = r->length;
+        while (r != c && r != d)
             {
-            x = u->length;
-            u->length = b->length;
-            b->length = x;
-            b->upDateTi = YES;
-            u->upDateTi = YES;
+            p = q->anc;
+            /* rotate pointers of q */
+            if (q->left == r)
+                q->left = p;
+            else
+                q->right = p;
+            q->anc = r;
+            /* swap q and old */
+            tempy = q->length;
+            q->length = tempc;
+            q->upDateTi = YES;
+            tempc = tempy;
+            /* make sure we get q and r initialized for next round */
+            r = q;
+            q = p;
             }
+        newB->length = tempc;
+        
+        /* hit newB length with multiplier */
+        x = newB->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
+            }
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / newB->length);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (newB->length - x);
+        newB->length = x;
+        newB->upDateTi = YES;
         }
     
-    /* modify branch lengths */
-    /* first modify length of middle branch */
-    m = brlenNode[3]->length;
-    x = m * exp(tuning * (RandomNumber(seed) - 0.5));       /* save the modified dangling branch for later use */
+    /* reattach the crown part */
+    v->left = newC;
+    v->right = newB;
+    newC->anc = newB->anc = v;
+    
+    topologyHasChanged = YES;
+    
+    /* hit v length with multiplier */
+    x = v->length * exp(tuning * (RandomNumber(seed) - 0.5));
     while (x < minV || x > maxV)
         {
-        if (x < minV)
-            x = minV * minV / x;
-        else if (x > maxV)
-            x = maxV * maxV / x;
+        if (x < minV) x = minV * minV / x;
+        if (x > maxV) x = maxV * maxV / x;
         }
-    brlenNode[3]->length = x;
-    brlenNode[3]->upDateTi = YES;
-
-    /* update proposal and prior ratio based on length modification */
-    (*lnProposalRatio) += log (x / m);
+    /* calculate proposal and prior ratio based on length modification */
+    (*lnProposalRatio) += log (x / v->length);
     if (isVPriorExp == YES)
-        (*lnPriorRatio) += brlensExp * (m - x);
-
-    /* if no move in crown, then select randomly, otherwise always the moved branch */
-    if (nCrownNodes == 0 && RandomNumber(seed) < 0.5)
-        p = brlenNode[0];
-    else
-        p = brlenNode[1];
-
-    /* modify branch length */
-    m = p->length;
-    x = m * exp(tuning * (RandomNumber(seed) - 0.5));
-    while (x < minV || x > maxV)
+        (*lnPriorRatio) += brlensExp * (v->length - x);
+    v->length = x;
+    v->upDateTi = YES;
+ 
+    /* set flags for update of cond likes */
+    p = u;
+    while (p->anc != NULL)
         {
-        if (x < minV)
-            x = minV * minV / x;
-        else if (x > maxV)
-            x = maxV * maxV / x;
+        p->upDateCl = YES;
+        p = p->anc;
         }
-    p->length = x;
-    p->upDateTi = YES;
-
-    /* update proposal and prior ratio based on length modification */
-    (*lnProposalRatio) += log (x / m);
-    if (isVPriorExp == YES)
-        (*lnPriorRatio) += brlensExp * (m - x); 
-        
-    /* if no move in root, then select randomly, otherwise always the moved branch */
-    if (nRootNodes == 0 && RandomNumber(seed) < 0.5)
-        p = brlenNode[4];
-    else
-        p = brlenNode[5];
-    
-    /* modify branch length but not if 'root' branch in rooted tree */
-    if (t->isRooted == NO || p->anc->anc != NULL)
+    p = b;
+    while (p->anc != NULL)
         {
-        m = p->length;
-        x = m * exp(tuning * (RandomNumber(seed) - 0.5));
-        while (x < minV || x > maxV)
-            {
-            if (x < minV)
-                x = minV * minV / x;
-            else if (x > maxV)
-                x = maxV * maxV / x;
-            }
-        p->length = x;
-        p->upDateTi = YES;
-
-        /* update proposal and prior ratio based on length modification */
-        (*lnProposalRatio) += log (x / m);
-        if (isVPriorExp == YES)
-            (*lnPriorRatio) += brlensExp * (m - x); 
+        p->upDateCl = YES;
+        p = p->anc;
         }
-
-    /* set flags for update of cond likes from v and down to root */
-    p = v;
+    p = newC;
     while (p->anc != NULL)
         {
         p->upDateCl = YES;
         p = p->anc;
         }
-
+    p = r;
+    while (p->anc != NULL)
+        {
+        p->upDateCl = YES;
+        p = p->anc;
+        }
+    
     /* get down pass sequence if tree topology has changed */
     if (topologyHasChanged == YES)
         {
         GetDownPass (t);
         }
 
-    /* calculate new number of nodes */
-    if (topologyHasChanged == YES)
-        {
-        /* first, mark distance of nodes from the new position of node v */
-        for (i=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            p->x = -1;
-            }
+    /* Dirichlet or twoExp prior */
+    if (isVPriorExp > 1)
+        (*lnPriorRatio) += LogDirPrior(t, mp, isVPriorExp);
     
-        v->x = 0;
-        v->anc->x = 0;
-
-        /* downpass */
-        for (p=u; p->anc!= NULL; p=p->anc)
-            {
-            p->anc->x = p->x+1;
-            }
-        
-        /* uppass */
-        for (i=t->nNodes-2; i>=0; i--)
-            {
-            p = t->allDownPass[i];
-            if (p->x < 0)
-                p->x = p->anc->x + 1;
-            }
-        
-        /* now count nodes */
-        for (i=newNumWindowNodes=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            if (p->x >= 2 && p->x <= windowDiameter+1)
-                newNumWindowNodes++;
-            }
-
-        /* update proposal ratio */
-        (*lnProposalRatio) += log (newNumWindowNodes / numWindowNodes);
-        }
+    /* free up local memory */
+    free (parLength); free (pRoot); free (pCrown); free (nSitesOfPat);
 
-#   if defined (DEBUG_RanSPR)
-    printf ("After:\n");
-    ShowNodes (t->root, 2, NO);
-    getchar();
-    printf ("Proposal ratio: %f\n",(*lnProposalRatio));
-    printf ("v: %d  u: %d  c: %d  d: %d  a: %d  b: %d q: %d\n",v->index, u->index, 
-            c->index, d->index, a->index, b->index, q->index);
-    printf ("No. nodes moved in root subtree: %d\n",nRootNodes);
-    printf ("No. nodes moved in crown subtree: %d\n",nCrownNodes);
-    printf ("Has topology changed? %d\n",topologyHasChanged);
-    getchar();
-#   endif
+    return (NO_ERROR);
 
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-    gNodeMoves = nCrownNodes + nRootNodes;
-#   endif
+errorExit:
+    MrBayesPrint ("%s   Problem allocating memory in Move_ParsTBR\n", spacer);
+    free (parLength); free (pRoot); free (pCrown); free (nSitesOfPat);
 
-    return (NO_ERROR);
+    return (ERROR);
 }
 
 
-int Move_RanSPR4 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+int Move_ParsTBR2 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
 {
-    /* This move is like Move_RanSPR3, except that it swaps branches in subtrees with equal probabilities */
+    /* Change topology and map branch lengths using TBR-type move biased according to parsimony scores,
+       controlled by a window defined by a certain node distance radius. */
     
-    int         i, topologyHasChanged, nCrownNodes, nRootNodes, directionLeft, directionUp, 
-                isVPriorExp, moveInRoot, foundFirst, windowDiameter, numWindowNodes, newNumWindowNodes;
-    MrBFlt      m, x, y, tuning, maxV, minV, moveProb, brlensExp=0.0;
-    TreeNode    *p, *a, *b, *c, *d, *u, *v, *brlenNode[7], *q, *windowNode[120];
+    int         i, j, k, n, division, topologyHasChanged, nNeighbor, nRoot, nCrown, iA, jC, isVPriorExp;
+    BitsLong    *pA, *pB, *pC, *pD, y[2];
+    MrBFlt      x, minV, maxV, brlensExp=0.0, minLength=0.0, length=0.0, *parLength=NULL, prob, ran, tuning, warpFactor,
+                v_typical, divFactor, nStates, sum1, sum2, tempsum, tempc, tempy;
+    CLFlt       *nSites, *nSitesOfPat=NULL, *globalNSitesOfPat;
+    TreeNode    *p, *q, *r, *a, *b, *u, *v, *c, *d, *newB, *newA, *newC, **pRoot=NULL, **pCrown=NULL;
     Tree        *t;
     ModelParams *mp;
+    ModelInfo   *m=NULL;
+    
+    warpFactor = mvp[0];                  /* tuning parameter determining how heavily to weight according to parsimony scores */
+//  increaseProb = decreaseProb = mvp[1]; /* reweighting probabilities */
+    v_typical = mvp[2];                   /* typical branch length for conversion of parsimony score to log prob ratio */
+    tuning = mvp[3];                      /* multiplier tuning parameter */
+    nNeighbor = (int)mvp[4];              /* distance to move picked branch in root and crown part */
 
-    /* these parameters should be possible to set by user */
-    moveProb = mvp[0];  /* extension probability */
-    tuning = mvp[1];        /* Larget & Simon's tuning parameter lambda */
-    windowDiameter = 4;     /* window diameter in number of nodes away from the cut branch */
-                            /* set it to a value between 1 and 4 (above 4 requires more space in windowNode) */
+    (*lnProposalRatio) = (*lnPriorRatio) = 0.0;
+    
+    /* get model params and model info */
+    mp = &modelParams[param->relParts[0]];
+    m = &modelSettings[param->relParts[0]];
+    
     /* get tree */
     t = GetTree (param, chain, state[chain]);
-
-    /* get model params */
-    mp = &modelParams[param->relParts[0]];
     
     /* max and min brlen */
     if (param->subParams[0]->paramId == BRLENS_UNI)
         {
         minV = mp->brlensUni[0] > BRLENS_MIN ? mp->brlensUni[0] : BRLENS_MIN;
-        maxV = mp->brlensUni[1];
+        maxV = mp->brlensUni[1] < BRLENS_MAX ? mp->brlensUni[1] : BRLENS_MAX;
         isVPriorExp = NO;
         }
+    else if (param->subParams[0]->paramId == BRLENS_GamDir)
+        {
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        isVPriorExp = 2;
+        }
+    else if (param->subParams[0]->paramId == BRLENS_iGmDir)
+        {
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        isVPriorExp = 3;
+        }
+    else if (param->subParams[0]->paramId == BRLENS_twoExp)
+        {
+        minV = BRLENS_MIN;
+        maxV = BRLENS_MAX;
+        isVPriorExp = 4;
+        }
     else
         {
         minV = BRLENS_MIN;
@@ -14112,626 +11793,755 @@ int Move_RanSPR4 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio,
         isVPriorExp = YES;
         }
 
-    topologyHasChanged = NO;
-
-#   if defined (DEBUG_RanSPR)
-    printf ("Before:\n");
-    ShowNodes (t->root, 2, NO);
-    getchar();
-#   endif
+    /* Dirichlet or twoExp prior */
+    if (isVPriorExp > 1)
+        (*lnPriorRatio) = -LogDirPrior(t, mp, isVPriorExp);
     
-    /* pick an internal branch */
-    do
-        {
-        p = t->intDownPass[(int)(RandomNumber(seed)*t->nIntNodes)];
-        } while (p->anc->anc == NULL);
-        
-    /* set up pointers for nodes around the picked branch */
-    /* cut the tree into crown, root and attachment part */
-    /* change the relevant lengths in the attachment part */
-    /* the lengths of a and v are automatically contained in the */
-    /* "attachment" part but the length of c has to be stored in x */
-    v = p;
-    u = p->anc;
-
-    /* store brlen node */
-    brlenNode[3] = v;
-
-    /* mark distance of nodes from the node v */
+    /* set topologyHasChanged to NO */
+    topologyHasChanged = NO;
+    
+    /* reset node variables that will be used */
     for (i=0; i<t->nNodes; i++)
         {
         p = t->allDownPass[i];
-        p->x = -1;
+        p->x = 0;
+        p->marked = NO;
+        }
+
+    /* pick an internal branch */
+    do  {
+        p = t->intDownPass[(int)(RandomNumber(seed)*(t->nIntNodes-1))];
+        q = p->anc->left;
+        if (q == p)  q = p->anc->right;
+        i = j = 0;
+        if (q->isLocked == YES || q->left == NULL)
+            i++;
+        if (p->anc->isLocked == YES || p->anc->anc->anc == NULL)
+            i++;
+        if (p->left->isLocked == YES || p->left->left == NULL)
+            j++;
+        if (p->right->isLocked == YES || p->right->left == NULL)
+            j++;
         }
+    while (i == 2 && j == 2);
     
-    v->x = 0;
-    u->x = 0;
+    /* set up pointers for nodes around the picked branch */
+    v = p;            u = p->anc;
+    c = p->left;      d = p->right;
+    if (u->left == v) a = u->right;
+    else              a = u->left;
+    b = u->anc;
+    /* clip root part of tree */
+    a->anc = b;
+    if (b->left == u) b->left = a;
+    else              b->right = a;
+    /* clip crown part of tree */
+    c->anc = d;
+    d->anc = c;
+    /* should never change u, v, a, b, c, d pointers */
 
-    /* downpass */
-    for (p=u; p->anc!= NULL; p=p->anc)
+    /* mark nodes nNeighbor away in root (negative) and crown (positive) respecting constraints */
+    /* first move down towards root */
+    nRoot = nCrown = 0;
+    if (u->isLocked == NO)
         {
-        p->anc->x = p->x+1;
+        p = a; q = b; n = 0;
+        while (q->anc != NULL)
+            {
+            q->marked = YES;
+            q->x = n;    // temporary, for MarkDistance below
+            if (q->left == p)
+                MarkDistance(q->right, YES, nNeighbor, &nRoot);
+            else
+                MarkDistance(q->left,  YES, nNeighbor, &nRoot);
+            q->x = --n;  // final
+            nRoot++;
+            if (q->isLocked == YES || abs(q->x) >= nNeighbor)
+                break;
+            p = q; q = q->anc;
+            }
         }
-        
-    /* uppass */
-    for (i=t->nNodes-2; i>=0; i--)
+    /* then move up in root part */
+    a->marked = YES; nRoot++;
+    if (a->isLocked == NO)
         {
-        p = t->allDownPass[i];
-        if (p->x < 0)
-            p->x = p->anc->x + 1;
+        MarkDistance(a->left,  YES, nNeighbor, &nRoot);
+        MarkDistance(a->right, YES, nNeighbor, &nRoot);
         }
-        
-    /* mark crown part of tree */
-    for (i=0; i<t->nNodes; i++)
+    /* finally in crown part */
+    c->marked = YES; nCrown++;
+    if (c->isLocked == NO)
         {
-        p = t->allDownPass[i];
-        p->marked = NO;
+        MarkDistance(c->left,  NO, nNeighbor, &nCrown);
+        MarkDistance(c->right, NO, nNeighbor, &nCrown);
         }
-    v->marked = YES;
-    for (i=t->nNodes-2; i>=0; i--)
+    if (d->isLocked == NO)
         {
-        p = t->allDownPass[i];
-        if (p->anc->marked == YES)
-            p->marked = YES;
+        MarkDistance(d->left,  NO, nNeighbor, &nCrown);
+        MarkDistance(d->right, NO, nNeighbor, &nCrown);
         }
 
-    /* count number of root and crownnodes */
-    for (i=nRootNodes=nCrownNodes=0; i<t->nNodes; i++)
-        {
-        p = t->allDownPass[i];
-        if (p->x >= 2 && p->x <= windowDiameter+1)
-            {
-            if (p->marked == YES)
-                nCrownNodes++;
-            else
-                nRootNodes++;
-            }
+    /* need to alloc a matrix for parsimony lengths, an array of pointers to crown part,
+       and an array of pointers to root part. */
+    parLength = (MrBFlt *) SafeCalloc ((size_t)nRoot * (size_t)nCrown, sizeof(MrBFlt));
+    pRoot  = (TreeNode **) SafeCalloc(nRoot,  sizeof(TreeNode *));
+    pCrown = (TreeNode **) SafeCalloc(nCrown, sizeof(TreeNode *));
+    if (!parLength || !pRoot || !pCrown)  goto errorExit;
+    /* starting position */
+    pRoot[0] = a; pCrown[0] = c;
+    for (i=j=1, n=t->nNodes-2; n>=0; n--)
+        {  /* and the rest */
+        p = t->allDownPass[n];
+        if (p->marked == YES && p->x < 0)
+            pRoot[i++] = p;
+        if (p->marked == YES && p->x > 0)
+            pCrown[j++] = p;
         }
+    assert (i==nRoot && j==nCrown);
 
-    /* choose subtree */
-    if (nCrownNodes == 0)
-        moveInRoot = YES;
-    else if (nRootNodes == 0)
-        moveInRoot = NO;
-    else if (RandomNumber(seed) < 0.5)
-        moveInRoot = YES;
-    else
-        moveInRoot = NO;
-    nRootNodes = nCrownNodes = 0;
+    /* get final parsimony state sets for the root part */
+    GetParsDP (t, t->root->left, chain);
+    GetParsFP (t, t->root->left, chain);
+    /* get final parsimony state sets for the crown part */
+    GetParsDP (t, c, chain);
+    GetParsDP (t, d, chain);
+    GetParsFP (t, c, chain);
+    GetParsFP (t, d, chain);
 
-    /* now collect nodes */
-    for (i=numWindowNodes=0; i<t->nNodes; i++)
+    /* find number of site patterns and modify randomly */
+    globalNSitesOfPat = numSitesOfPat + (chainId[chain] % chainParams.numChains) * numCompressedChars + m->compCharStart;
+    nSitesOfPat = (CLFlt *) SafeCalloc (numCompressedChars, sizeof(CLFlt));
+    if (!nSitesOfPat)  goto errorExit;
+    for (i=0; i<numCompressedChars; i++)
         {
-        p = t->allDownPass[i];
-        if (p->x >= 2 && p->x <= windowDiameter+1 &&
-            ((moveInRoot == YES && p->marked == NO) || (moveInRoot == NO && p->marked == YES)))
-            windowNode[numWindowNodes++] = p;
+        nSitesOfPat[i] = globalNSitesOfPat[i];
+    /*  for (j=0; j<globalNSitesOfPat[i]; j++)
+            {
+            ran = RandomNumber(seed);
+            if (ran < decreaseProb)
+                nSitesOfPat[i]--;
+            else if (ran > 1.0 - increaseProb)
+                nSitesOfPat[i]++;
+            }  // this is not used at the moment */
         }
-    if (numWindowNodes > 120)
+
+    /* cycle through the possibilities and record the parsimony length */
+    for (j=0; j<nCrown; j++)
         {
-        printf ("error\n");
-        ShowNodes (t->root, 0, t->isRooted);
-        for (i=0; i<t->nNodes; i++)
-            printf ("%d\t%d\n", t->allDownPass[i]->index, t->allDownPass[i]->x);
-        getchar();
+        for (i=0; i<nRoot; i++)
+            {
+            parLength[i+j*nRoot] = 0.0;
+            for (n=0; n<t->nRelParts; n++)
+                {
+                division = t->relParts[n];
+                
+                /* Find model settings */
+                m = &modelSettings[division];
+                
+                /* find nSitesOfPat */
+                nSites = nSitesOfPat + m->compCharStart;
+                
+                /* find downpass parsimony sets for the potential new connection nodes and their environment */
+                pA = m->parsSets[pRoot[i]->index];
+                pB = m->parsSets[pRoot[i]->anc->index];
+                pC = m->parsSets[pCrown[j]->index];
+                pD = m->parsSets[pCrown[j]->anc->index];
+                    
+                length = 0.0;
+                if (m->nParsIntsPerSite == 1)
+                    {
+                    for (k=0; k<m->numChars; k++)
+                        {
+                        y[0] = (pC[k] | pD[k]) & (pA[k] | pB[k]);
+                        if (y[0] == 0)
+                            length += nSites[k];
+                        }
+                    }
+                else /* if (m->nParsIntsPerSite == 2) */
+                    {
+                    for (k=0; k<2*m->numChars; k+=2)
+                        {
+                        y[0] = (pC[k] | pD[k]) & (pA[k] | pB[k]);
+                        y[1] = (pC[k+1] | pD[k+1]) & (pA[k+1] | pB[k+1]);;
+                        if ((y[0] | y[1]) == 0)
+                            length += nSites[k/2];
+                        }
+                    }
+                    
+                /* find nStates and ratemult */
+                nStates = m->numModelStates;
+                if (m->dataType == STANDARD)
+                    nStates = 2;
+                v_typical = length/m->numUncompressedChars + 0.0001;
+                
+                /* get division warp factor (prop. to prob. of change) */
+                divFactor = - warpFactor * log(1.0/nStates - exp(-nStates/(nStates-1)*v_typical)/nStates);
+                parLength[i+j*nRoot] += divFactor * length;
+                }
+            }
         }
 
-    /* find the attachment point */
-    if (RandomNumber(seed) > moveProb)
-        {
-        q = v->left;
-        moveInRoot = NO;
-        }
+    /* find the min length and the sum for the forward move */
+    minLength = -1.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
+            {
+            if (i == 0 && j == 0)  // exclude original position
+                continue;
+            if (minLength > parLength[i+j*nRoot] || minLength < 0.0)
+                minLength = parLength[i+j*nRoot];
+            }
+    sum1 = 0.0; tempc = 0.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
+            {
+            if (i == 0 && j == 0)  // exclude original position
+                continue;
+            /* Kahan summation to reduce numerical error */
+            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
+            tempsum = sum1 + tempy;  tempc = (tempsum - sum1) - tempy;
+            sum1 = tempsum;
+            // sum1 += exp(minLength - parLength[i+j*nRoot]);
+            // printf("%d %d %lf\n", i, j, exp(minLength - parLength[i+j*nRoot]));
+            }
+
+    /* generate a random uniform */
+    ran = RandomNumber(seed) * sum1;
+
+    /* select the appropriate reattachment point */
+    newA = a; newC = c;
+    prob = 0.0; tempc = 0.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
+            {
+            if (i == 0 && j == 0)  // exclude original position
+                continue;
+            // prob += exp (minLength - parLength[i+j*nRoot]);
+            /* Kahan summation to reduce numerical error */
+            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
+            tempsum = prob + tempy;  tempc = (tempsum - prob) - tempy;
+            prob = tempsum;
+            if (prob > ran) {
+                /* proposed new attaching position */
+                newA = pRoot[i];
+                newC = pCrown[j];
+                goto outLoop;
+                }
+            }
+outLoop:;
+    iA = i; jC = j;
+
+    /* calculate the proposal ratio */
+    (*lnProposalRatio) = parLength[i+j*nRoot] - minLength + log(sum1);
+
+    /* find the min length and the sum for the backward move */
+    minLength = -1.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
+            {
+            if (i == iA && j == jC)  // exclude new position
+                continue;
+            if (minLength > parLength[i+j*nRoot] || minLength < 0.0)
+                minLength = parLength[i+j*nRoot];
+            }
+    sum2 = 0.0; tempc = 0.0;
+    for (j=0; j<nCrown; j++)
+        for (i=0; i<nRoot; i++)
+            {
+            if (i == iA && j == jC)  // exclude new position
+                continue;
+            /* Kahan summation to reduce numerical error */
+            tempy = exp(minLength - parLength[i+j*nRoot]) - tempc;
+            tempsum = sum2 + tempy;  tempc = (tempsum - sum2) - tempy;
+            sum2 = tempsum;
+            // sum2 += exp (minLength - parLength[i+j*nRoot]);
+            // printf("%d %d %lf\n", i, j, exp(minLength - parLength[i+j*nRoot]));
+            }
+
+    /* calculate the proposal ratio */
+    (*lnProposalRatio) += minLength - parLength[0] - log(sum2);
+
+    /* reattach the root part */
+    newB = newA->anc;
+    newA->anc = u;
+    if (u->left == v)
+        u->right = newA;
     else
-        {
-        q = windowNode[(int)(RandomNumber(seed)*numWindowNodes)];
-        }
-    
-    /* mark crown subtree */
-    for (i=0; i<t->nNodes; i++)
-        {
-        p = t->allDownPass[i];
-        p->marked = NO;
-        }
-    v->marked = YES;
+        u->left = newA;
+    u->anc = newB;
+    if (newB->left == newA)
+        newB->left = u;
+    else
+        newB->right = u;
 
-    for (i=t->nNodes-2; i>=0; i--)
+    /* transfer lock and reassign branch lengths, if necessary */
+    if (newA != a)
         {
-        p = t->allDownPass[i];
-        if (p->anc->marked == YES)
-            p->marked = YES;
-        }
-
-    /* mark the path of the move */
-    for (i=0; i<t->nNodes; i++)
-        t->allDownPass[i]->marked = NO;
+        /* if u is locked, then we have moved upwards and need to leave the u lock behind */
+        if (u->isLocked == YES)
+            {
+            u->isLocked = NO;
+            a->isLocked = YES;
+            a->lockID = u->lockID;
+            u->lockID = -1;
+            }
 
-    if (moveInRoot == NO)
-        {
-        p = q;
-        while (p != v)
+        p = newA;
+        while (p->anc != NULL)
             {
-            p->marked = YES;
+            if (p == a) break;
             p = p->anc;
             }
-        v->marked = YES;
-        }
-    else
-        {
-        p = q;
-        while (p != NULL)
+        if (p == a)
             {
-            p->marked = YES;
-            p = p->anc;
+            /* newA is descendant to a so move a->length not u->length */
+            x = u->length;
+            u->length = a->length;
+            a->length = x;
             }
-        foundFirst = NO;
-        p = v;
-        while (p != NULL)
+
+        p = b;
+        while (p->anc != NULL)
             {
-            if (p->marked == NO)
-                p->marked = YES;
-            else if (foundFirst == YES)
-                p->marked = NO;
-            else
-                foundFirst = YES;
+            if (p == newA) break;
             p = p->anc;
             }
-        }
-
-    /* set up pointers for crown part */
-    /* this also determines direction of move in crown part */
-    if (v->left->marked == YES)
-        {
-        c = v->left;
-        d = v->right;
-        directionLeft = YES;
-        }
-    else
-        {
-        c = v->right;
-        d = v->left;
-        directionLeft = NO;
-        }
-
-    /* store brlen nodes and brlen to move */
-    brlenNode[0] = d;
-    brlenNode[1] = c;
-    x = c->length;
-
-    /* cut and reconnect crown part */
-    c->anc = d;
-    d->anc = c;
-    
-    /* mark nodes in root part */
-    /* also determines direction of move in root part */
-    if (u->anc->marked == NO)
-        {
-        if (u->left == v)
-            a = u->right;
-        else
-            a = u->left;
-        b = u->anc;
-        directionUp = YES;
-        }
-    else
-        {
-        if (u->left == v)
-            b = u->right;
-        else
-            b = u->left;
-        a = u->anc;
-        directionUp = NO;
-        }
-
-    /* store brlen nodes */
-    if (directionUp == YES)
-        {
-        brlenNode[4] = u;
-        brlenNode[5] = a;
-        }
-    else
-        {
-        brlenNode[4] = b;
-        brlenNode[5] = u;
-        }
-
-    /* cut root part*/
-    /* store branch to move in u->length */
-    if (directionUp == NO) 
-        {
-        b->anc = a;
-        if (a->left == u)
-            a->left = b;
-        else
-            a->right = b;
-        }
-    else 
-        {
-        a->anc = b;
-        if (b->left == u)
-            b->left = a;
-        else
-            b->right = a;
-        y = a->length;
-        a->length = u->length;
-        u->length = y;
-        a->upDateTi = YES;
-        u->upDateTi = YES;
-        }
-
-    /* move around in root subtree */
-    nRootNodes = 0;
-    if (moveInRoot == YES)
-        {
-        for (nRootNodes=0; a->marked == YES; nRootNodes++) 
+        if (p == newA)
             {
-            if (directionUp == YES) 
-                {
-                /* going up tree */
-                if (a->left == NULL)
-                    break;
-                else if (a->left->marked == NO && a->right->marked == NO)
-                    break;      /* don't go further */
-                topologyHasChanged = YES;
-                b = a;
-                if (a->left->marked == YES)
-                    a = a->left;
-                else
-                    a = a->right;
-                if (u->isLocked == YES)
-                    {
-                    b->isLocked = YES;
-                    u->isLocked = NO;
-                    b->lockID = u->lockID;
-                    u->lockID = 0;
-                    }
-                }
-            else 
-                {
-                /* going down tree */
-                if (a->anc == NULL || u->isLocked == YES)
-                    break;      /* can't go further */
-                topologyHasChanged = YES;
-                if (a->anc->marked == NO) 
-                    {
-                    /* try switching direction */
-                    /* find sister of a */
-                    if (a->left == b) 
-                        {
-                        a = a->right;
-                        }
-                    else 
-                        {  
-                        a = a->left;
-                        }
-                    /* as long as we are moving upwards
-                    the cond likes to update will be
-                    flagged by the last pass from u to the root */
-                    if (a->marked == NO)
-                        {
-                        b = a->anc;
-                        b->upDateCl = YES;
-                        a = a->anc->anc;
-                        break;          /* go back and one node down, unsuccessful attempt */
-                        }
-                    else
-                        {
-                        b = a->anc;
-                        directionUp = YES;  /* successful attempt */
-                        }
-                    }   
-                else 
-                    {   /* continue down */                 
-                    b = a;
-                    a = a->anc;
-                    b->upDateCl = YES; 
-                    if (b->isLocked == YES)
-                        {
-                        u->isLocked = YES;
-                        b->isLocked = NO;
-                        u->lockID = b->lockID;
-                        b->lockID = 0;
-                        }
-                    }
+            /* newA is ancestor to a so insert above instead of below */
+            x = newA->length;
+            newA->length = u->length;
+            u->length = x;
+            /* newA is on root path and locked, we need to transfer lock to u */
+            if (newA->isLocked == YES) {
+                u->isLocked = YES;
+                u->lockID = newA->lockID;
+                newA->isLocked = NO;
+                newA->lockID = -1;
                 }
             }
-        }
+            
+        /* hit u length with multiplier */
+        x = u->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
+            }
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / u->length);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (u->length - x);
+        u->length = x;
 
-    /* store brlen nodes */
-    if (nRootNodes > 0)
+        /* set tiprobs update flags */
+        u->upDateTi = YES;
+        newA->upDateTi = YES;
+        a->upDateTi = YES;
+        }
+    
+    r = newC;
+    q = newB = newC->anc;
+    if (newC != c)  // crown part has changed
         {
-        if (directionUp == YES)
+        /* rotate nodes from newC to c or d (whichever is closest) */
+        tempc = r->length;
+        while (r != c && r != d)
             {
-            brlenNode[6] = a;
-            brlenNode[5] = u;
+            p = q->anc;
+            /* rotate pointers of q */
+            if (q->left == r)
+                q->left = p;
+            else
+                q->right = p;
+            q->anc = r;
+            /* swap q and old */
+            tempy = q->length;
+            q->length = tempc;
+            q->upDateTi = YES;
+            tempc = tempy;
+            /* make sure we get q and r initialized for next round */
+            r = q;
+            q = p;
             }
-        else
-            {
-            brlenNode[6] = u;
-            brlenNode[5] = b;
+        newB->length = tempc;
+        
+        /* hit newB length with multiplier */
+        x = newB->length * exp(tuning * (RandomNumber(seed) - 0.5));
+        while (x < minV || x > maxV)
+            {
+            if (x < minV) x = minV * minV / x;
+            if (x > maxV) x = maxV * maxV / x;
             }
+        /* calculate proposal and prior ratio based on length modification */
+        (*lnProposalRatio) += log (x / newB->length);
+        if (isVPriorExp == YES)
+            (*lnPriorRatio) += brlensExp * (newB->length - x);
+        newB->length = x;
+        newB->upDateTi = YES;
         }
-
-    /* move around in crown subtree */
-    nCrownNodes = 0;
-    if (moveInRoot == NO)       
+    
+    /* reattach the crown part */
+    v->left = newC;
+    v->right = newB;
+    newC->anc = newB->anc = v;
+    
+    topologyHasChanged = YES;
+    
+    /* hit v length with multiplier */
+    x = v->length * exp(tuning * (RandomNumber(seed) - 0.5));
+    while (x < minV || x > maxV)
         {
-        for (nCrownNodes=0; c->left != NULL; nCrownNodes++) 
-            {
-            if (c->left->marked == NO && c->right->marked == NO)
-                break;  /* can't go further */
-            topologyHasChanged = YES;
-            if (c->left->marked == YES) 
-                {
-                /* rotate c anticlockwise - prepare pointers for move left */
-                c->anc = c->left;  /* the root will be in the direction we are heading */
-                c->left = c->right;
-                c->right = d;
-                }
-            else 
-                {
-                /* rotate c clockwise - prepare pointers for move right */
-                c->anc = c->right;  /* the root will be in the direction we are heading */
-                c->right = c->left;
-                c->left = d;  
-                }
-            /* OK - let's move!; c->anc points in the right direction
-            don't forget to move the branch lengths as well */
-            d = c;
-            c = c->anc;
-            d->length = c->length;
-            d->upDateCl = YES; 
-            d->upDateTi = YES;
-            }
+        if (x < minV) x = minV * minV / x;
+        if (x > maxV) x = maxV * maxV / x;
         }
-
-    /* store brlen nodes */
-    if (nCrownNodes > 0)
+    /* calculate proposal and prior ratio based on length modification */
+    (*lnProposalRatio) += log (x / v->length);
+    if (isVPriorExp == YES)
+        (*lnPriorRatio) += brlensExp * (v->length - x);
+    v->length = x;
+    v->upDateTi = YES;
+ 
+    /* set flags for update of cond likes */
+    p = u;
+    while (p->anc != NULL)
         {
-        brlenNode[2] = c;
-        brlenNode[1] = d;
+        p->upDateCl = YES;
+        p = p->anc;
         }
-
-    /* combine the subtrees */
-    c->anc = v;
-    d->anc = v;
-    if (directionLeft == YES) 
+    p = b;
+    while (p->anc != NULL)
         {
-        v->left = c;
-        v->right = d;
+        p->upDateCl = YES;
+        p = p->anc;
         }
-    else 
+    p = newC;
+    while (p->anc != NULL)
         {
-        v->left = d;
-        v->right = c;
+        p->upDateCl = YES;
+        p = p->anc;
         }
-
-    /* the dangling branch is inserted in reverted position
-       such that the back move will be possible
-       if we have moved around in crown subtree
-       otherwise it is left in its original position */
-    if (nCrownNodes > 0)
+    p = r;
+    while (p->anc != NULL)
         {
-        d->length = x;
-        d->upDateTi = YES;
+        p->upDateCl = YES;
+        p = p->anc;
         }
-    else
+    
+    /* get down pass sequence if tree topology has changed */
+    if (topologyHasChanged == YES)
         {
-        c->length = x;
+        GetDownPass (t);
         }
 
-    if (directionUp == YES) 
+    /* Dirichlet or twoExp prior */
+    if (isVPriorExp > 1)
+        (*lnPriorRatio) += LogDirPrior(t, mp, isVPriorExp);
+    
+    /* free up local memory */
+    free (parLength); free (pRoot); free (pCrown); free (nSitesOfPat);
+
+    return (NO_ERROR);
+
+errorExit:
+    MrBayesPrint ("%s   Problem allocating memory in Move_ParsTBR\n", spacer);
+    free (parLength); free (pRoot); free (pCrown); free (nSitesOfPat);
+
+    return (ERROR);
+}
+
+
+int Move_Pinvar (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+{
+    /* change proportion of invariable sites (pInvar) */
+
+    int             i, c, isValidP, *rateCat, nGammaCats;
+    MrBFlt          oldP, newP, window, minP, maxP, ran, lnInvarRatio, lnVarRatio;
+    CLFlt           *nSitesOfPat;
+    ModelParams     *mp;
+    ModelInfo       *m;
+
+    /* get size of window, centered on current pInvar value */
+    window = mvp[0];
+
+    /* get model params */
+    mp = &modelParams[param->relParts[0]];
+    
+    /* get minimum and maximum values for pInvar */
+    minP = mp->pInvarUni[0];
+    maxP = mp->pInvarUni[1];
+
+    /* get old value of pInvar */
+    newP = oldP = *GetParamVals(param, chain, state[chain]);
+
+    /* change value for pInvar */
+    ran = RandomNumber(seed);
+    if (maxP-minP < window)
         {
-        u->anc = b;
-        if (u->left == v)
-            u->right = a;
-        else 
-            u->left = a;
-        a->anc = u;
-        if (b->left == a)
-            b->left = u;
-        else
-            b->right = u;
-        /* the dangling branch is contained in u->length
-           and will automatically be inserted in the right position
-           to enable the back move regardless of whether it was
-           initially directed upwards or downwards
-           BUT if we haven't moved in root subtree, it is advantageous (necessary
-           for rooted trees) to avoid switching branches, which occurs otherwise
-           if directionUp == YES */
-        if (nRootNodes == 0) 
-            {
-            x = u->length;
-            u->length = a->length;
-            a->length = x;
-            a->upDateTi = NO;
-            u->upDateTi = NO;
-            }
+        window = maxP-minP;
         }
-    else 
+
+    newP = oldP + window * (ran - 0.5);
+
+    /* check validity */
+    isValidP = NO;
+    do
         {
-        u->anc = a;
-        if (u->left == v)
-            u->right = b;
-        else 
-            u->left = b;
-        b->anc = u;
-        if (a->left == b)
-            a->left = u;
+        if (newP < minP)
+            newP = 2* minP - newP;
+        else if (newP > maxP)
+            newP = 2 * maxP - newP;
         else
-            a->right = u;
-        /* the modified branch contained in u->length will have
-           to be moved to b->length to enable back move
-           BUT if we haven't moved, it is better to keep it in place
-           (necessary for rooted trees) */
-        if (nRootNodes > 0) 
+            isValidP = YES;
+        } while (isValidP == NO);
+
+    /* get proposal ratio */
+    *lnProposalRatio = 0.0;
+    
+    /* get prior ratio */
+    *lnPriorRatio = 0.0;
+    lnInvarRatio = log(newP) - log(oldP);
+    lnVarRatio = log(1.0-newP) - log(1.0-oldP);
+    for (i=0; i<param->nRelParts; i++)
+        {
+        m = &modelSettings[param->relParts[i]];
+        if (m->gibbsGamma == YES)
             {
-            x = u->length;
-            u->length = b->length;
-            b->length = x;
-            b->upDateTi = YES;
-            u->upDateTi = YES;
+            /* find rate category index and number of gamma categories */
+            rateCat = m->tiIndex + chain * m->numChars;
+            nGammaCats = m->numGammaCats;
+
+            /* find nSitesOfPat */
+            nSitesOfPat = numSitesOfPat + (chainId[chain] % chainParams.numChains)*numCompressedChars + m->compCharStart;
+            
+            /* loop over characters */
+            for (c=0; c<m->numChars; c++)
+                {
+                if (rateCat[c] < nGammaCats)
+                    *lnPriorRatio += lnVarRatio * nSitesOfPat[c];
+                else
+                    *lnPriorRatio += lnInvarRatio * nSitesOfPat[c];
+                }
             }
         }
     
-    /* modify branch lengths */
-    /* first modify length of middle branch */
-    m = brlenNode[3]->length;
-    x = m * exp(tuning * (RandomNumber(seed) - 0.5));       /* save the modified dangling branch for later use */
-    while (x < minV || x > maxV)
-        {
-        if (x < minV)
-            x = minV * minV / x;
-        else if (x > maxV)
-            x = maxV * maxV / x;
-        }
-    brlenNode[3]->length = x;
-    brlenNode[3]->upDateTi = YES;
+    /* copy new pInvar value back */
+    *GetParamVals(param, chain, state[chain]) = newP;
+
+    /* Set update flags for all partitions that share this pInvar. Note that the conditional
+       likelihood update flags for divisions have been set before we even call this function. */
+    for (i=0; i<param->nRelParts; i++)
+        TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
+    
+    /* However, you do need to update cijk flags if this is a covarion model */
+    /* TO DO */
+    
+    return (NO_ERROR);
+}
+
+
+int Move_PopSize_M (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+{
+    int             isValidN, valIndex;
+    MrBFlt          *valPtr, oldN, newN, tuning, minN, maxN, ran, oldLnPrior, newLnPrior, growth,
+                    oldT, newT, clockRate;
+    ModelParams     *mp;
+    ModelInfo       *m;
+    Tree            *t;
 
-    /* update proposal and prior ratio based on length modification */
-    (*lnProposalRatio) += log (x / m);
-    if (isVPriorExp == YES)
-        (*lnPriorRatio) += brlensExp * (m - x);
+    /* get multiplier tuning parameter */
+    tuning = mvp[0];
 
-    /* if no move in crown, then select randomly, otherwise always the moved branch */
-    if (nCrownNodes == 0 && RandomNumber(seed) < 0.5)
-        p = brlenNode[0];
-    else
-        p = brlenNode[1];
+    /* get model params */
+    mp = &modelParams[param->relParts[0]];
+    
+    /* get model settings */
+    m = &modelSettings[param->relParts[0]];
 
-    /* modify branch length */
-    m = p->length;
-    x = m * exp(tuning * (RandomNumber(seed) - 0.5));
-    while (x < minV || x > maxV)
+    /* get minimum and maximum values for population size */
+    if (param->paramId == POPSIZE_UNI)
         {
-        if (x < minV)
-            x = minV * minV / x;
-        else if (x > maxV)
-            x = maxV * maxV / x;
+        minN = mp->popSizeUni[0];
+        maxN = mp->popSizeUni[1];
         }
-    p->length = x;
-    p->upDateTi = YES;
-
-    /* update proposal and prior ratio based on length modification */
-    (*lnProposalRatio) += log (x / m);
-    if (isVPriorExp == YES)
-        (*lnPriorRatio) += brlensExp * (m - x); 
-        
-    /* if no move in root, then select randomly, otherwise always the moved branch */
-    if (nRootNodes == 0 && RandomNumber(seed) < 0.5)
-        p = brlenNode[4];
     else
-        p = brlenNode[5];
-    
-    /* modify branch length but not if 'root' branch in rooted tree */
-    if (t->isRooted == NO || p->anc->anc != NULL)
         {
-        m = p->length;
-        x = m * exp(tuning * (RandomNumber(seed) - 0.5));
-        while (x < minV || x > maxV)
-            {
-            if (x < minV)
-                x = minV * minV / x;
-            else if (x > maxV)
-                x = maxV * maxV / x;
-            }
-        p->length = x;
-        p->upDateTi = YES;
-
-        /* update proposal and prior ratio based on length modification */
-        (*lnProposalRatio) += log (x / m);
-        if (isVPriorExp == YES)
-            (*lnPriorRatio) += brlensExp * (m - x); 
+        minN = 0.00001;
+        maxN = 10000000;
         }
 
-    /* set flags for update of cond likes from v and down to root */
-    p = v;
-    while (p->anc != NULL)
+    /* get pointer to value to be changed */
+    valIndex = (int)(RandomNumber(seed) * param->nValues);
+    valPtr = GetParamVals(param, chain, state[chain]) + valIndex;
+
+    /* get old value of population size */
+    oldN = *valPtr;
+
+    /* get old prior for species tree coalescence */
+    if (m->brlens->paramId == BRLENS_CLOCK_SPCOAL)
         {
-        p->upDateCl = YES;
-        p = p->anc;
+        oldLnPrior = LnSpeciesTreeProb(chain);
+        }
+    
+    /* change value for theta */
+    ran = RandomNumber(seed);
+    newN = oldN * exp(tuning * (ran - 0.5));
+    
+    /* check that new value is valid */
+    isValidN = NO;
+    do {
+        if (newN < minN)
+            newN = 2* minN - newN;
+        else if (newN > maxN)
+            newN = 2 * maxN - newN;
+        else
+            isValidN = YES;
         }
+    while (isValidN == NO);
 
-    /* get down pass sequence if tree topology has changed */
-    if (topologyHasChanged == YES)
+    /* copy new population size value back */
+    (*valPtr) = newN;
+
+    /* get proposal ratio */
+    *lnProposalRatio = log (newN / oldN);
+    
+    /* get prior ratio */
+    if (m->brlens->paramId == BRLENS_CLOCK_SPCOAL)
         {
-        GetDownPass (t);
+        newLnPrior = LnSpeciesTreeProb(chain);
         }
-
-    /* calculate new number of nodes */
-    if (topologyHasChanged == YES)
+    else
         {
-        /* first, mark distance of nodes from the new position of node v */
-        for (i=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            p->x = -1;
-            }
-    
-        v->x = 0;
-        v->anc->x = 0;
-
-        /* downpass */
-        for (p=u; p->anc!= NULL; p=p->anc)
-            {
-            p->anc->x = p->x+1;
-            }
-        
-        /* uppass */
-        for (i=t->nNodes-2; i>=0; i--)
-            {
-            p = t->allDownPass[i];
-            if (p->x < 0)
-                p->x = p->anc->x + 1;
-            }
-        
-        /* mark crown part of tree */
-        for (i=0; i<t->nNodes; i++)
+        t = GetTree(modelSettings[param->relParts[0]].brlens,chain,state[chain]);
+        m = &modelSettings[param->relParts[0]];
+        clockRate = *GetParamVals(m->clockRate, chain, state[chain]);
+        if (!strcmp(mp->ploidy, "Diploid"))
+            clockRate *= 4.0;
+        else if (!strcmp(mp->ploidy, "Zlinked"))
+            clockRate *= 3.0;
+        else
+            clockRate *= 2.0;
+        newT = oldN * clockRate;
+        oldT = newN * clockRate;
+        if (!strcmp(mp->growthPr, "Fixed"))
+            growth = mp->growthFix;
+        else
+            growth = *(GetParamVals (m->growthRate, chain, state[chain]));
+        if (LnCoalescencePriorPr (t, &oldLnPrior, oldT, growth) == ERROR)
             {
-            p = t->allDownPass[i];
-            p->marked = NO;
+            MrBayesPrint ("%s   Problem calculating prior for coalescent process\n", spacer);
+            return (ERROR);
             }
-        v->marked = YES;
-        for (i=t->nNodes-2; i>=0; i--)
+        if (LnCoalescencePriorPr (t, &newLnPrior, newT, growth) == ERROR)
             {
-            p = t->allDownPass[i];
-            if (p->anc->marked == YES)
-                p->marked = YES;
+            MrBayesPrint ("%s   Problem calculating prior for coalescent process\n", spacer);
+            return (ERROR);
             }
+        }
 
-        /* now count nodes */
-        for (i=newNumWindowNodes=0; i<t->nNodes; i++)
-            {
-            p = t->allDownPass[i];
-            if (p->x >= 2 && p->x <= windowDiameter+1 &&
-                ((moveInRoot == YES && p->marked == NO) || (moveInRoot == NO && p->marked == YES)))
-                newNumWindowNodes++;
-            }
+    (*lnPriorRatio) = param->LnPriorRatio(newN, oldN, param->priorParams);
+    (*lnPriorRatio) += newLnPrior - oldLnPrior;
+
+    return (NO_ERROR);
+}
+
+
+/* Generalized lognormal move for positive real random variables */
+int Move_PosRealLognormal (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+{
+    int         i;
+    MrBFlt      oldX, newX, minX, maxX, tuning, u, z;
+
+    /* get tuning parameter */
+    tuning = mvp[0];
+
+    /* get minimum and maximum values for X */
+    minX = param->min;
+    maxX = param->max;
+
+    /* get old value of X */
+    newX = oldX = *GetParamVals(param, chain, state[chain]);
+
+    /* change value of X */
+    u = RandomNumber(seed);
+    z = PointNormal(u);
+
+    newX = exp (log(oldX) + z * tuning);
+    
+    /* check that new value is valid */
+    if (newX < minX || newX > maxX) {
+        abortMove = YES;
+        return (NO_ERROR);
+    }
+    
+    /* get proposal ratio */
+    (*lnProposalRatio) = log (newX / oldX);
+    
+    /* get prior ratio */
+    (*lnPriorRatio) = param->LnPriorRatio(newX, oldX, param->priorParams);
+    
+    /* copy new value back */
+    (*GetParamVals(param, chain, state[chain])) = newX;
 
-        /* update proposal ratio */
-        (*lnProposalRatio) += log (newNumWindowNodes / numWindowNodes);
+    /* Set update flags for tree nodes if relevant */
+    if (param->affectsLikelihood == YES)
+        {
+        for (i=0; i<param->nRelParts; i++)
+            TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
         }
 
-#   if defined (DEBUG_RanSPR)
-    printf ("After:\n");
-    ShowNodes (t->root, 2, NO);
-    getchar();
-    printf ("Proposal ratio: %f\n",(*lnProposalRatio));
-    printf ("v: %d  u: %d  c: %d  d: %d  a: %d  b: %d q: %d\n",v->index, u->index, 
-            c->index, d->index, a->index, b->index, q->index);
-    printf ("No. nodes moved in root subtree: %d\n",nRootNodes);
-    printf ("No. nodes moved in crown subtree: %d\n",nCrownNodes);
-    printf ("Has topology changed? %d\n",topologyHasChanged);
-    getchar();
-#   endif
+    return (NO_ERROR);
+}
 
-#   if defined (TOPOLOGY_MOVE_STATS)
-    if (topologyHasChanged == YES)
-        gTopologyHasChanged = YES;
-    else
-        gTopologyHasChanged = NO;
-    gNodeMoves = nCrownNodes + nRootNodes;
-#   endif
+
+/* Generalized multiplier move for positive real random variables */
+int Move_PosRealMultiplier (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp)
+{
+    int         i, isValid;
+    MrBFlt      oldX, newX, minX, maxX, tuning, ran, factor;
+
+    /* get tuning parameter */
+    tuning = mvp[0];
+
+    /* get minimum and maximum values for X */
+    minX = param->min;
+    maxX = param->max;
+
+    /* get old value of X */
+    newX = oldX = *GetParamVals(param, chain, state[chain]);
+
+    /* change value of X */
+    ran = RandomNumber(seed);
+    factor = exp(tuning * (ran - 0.5));
+    newX = oldX * factor;
+    
+    /* check that new value is valid */
+    isValid = NO;
+    do
+        {
+        if (newX < minX)
+            newX = minX * minX / newX;
+        else if (newX > maxX)
+            newX = maxX * maxX / newX;
+        else
+            isValid = YES;
+        } while (isValid == NO);
+
+    /* get proposal ratio */
+    (*lnProposalRatio) = log (newX / oldX);
+    
+    /* get prior ratio */
+    (*lnPriorRatio) = param->LnPriorRatio(newX, oldX, param->priorParams);
+    
+    /* copy new value back */
+    *(GetParamVals(param, chain, state[chain])) = newX;
+
+    /* Set update flags for tree nodes if relevant */
+    if (param->affectsLikelihood == YES)
+        {
+        for (i=0; i<param->nRelParts; i++)
+            TouchAllTreeNodes(&modelSettings[param->relParts[i]],chain);
+        }
 
     return (NO_ERROR);
 }
@@ -16011,6 +13821,7 @@ int Move_Speciation (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRat
             return (ERROR);
             }
         *valPtr = newL;  // update with new value
+        // for (i=0; i<param->nValues; i++)  *(GetParamVals(param, chain, state[chain]) + i) = newL;
         if (LnFossilizationPriorPr (t, clockRate, &newLnPrior, sR, eR, sF, fR, sS) == ERROR)
             {
             MrBayesPrint ("%s   Problem calculating prior for fossilized birth-death process\n", spacer);
@@ -16120,6 +13931,7 @@ int Move_Speciation_M (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorR
             return (ERROR);
             }
         *valPtr = newL;  // update with new value
+        // for (i=0; i<param->nValues; i++)  *(GetParamVals(param, chain, state[chain]) + i) = newL;
         if (LnFossilizationPriorPr (t, clockRate, &newLnPrior, sR, eR, sF, fR, sS) == ERROR)
             {
             MrBayesPrint ("%s   Problem calculating prior for fossilized birth-death process\n", spacer);
@@ -16895,7 +14707,7 @@ int Move_TreeStretch (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRa
     /* determine multiplication factor */
     factor = exp(tuning * (RandomNumber(seed) - 0.5));
 
-    /* multiply all branch lengths and node depths by this factor  */
+    /* multiply all changeable ages and node depths by this factor */
     numChangedNodes = 0;
     for (i=0; i<t->nNodes-1; i++)
         {
@@ -16926,10 +14738,9 @@ int Move_TreeStretch (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRa
         p->nodeDepth *= factor;
         numChangedNodes++;
         
-        /* update brls, be careful with ancestral fossil */
+        /* deal with ancestral fossils */
         if (p->left != NULL)
             {
-            assert (p->left->length >= 0.0 && p->right->length >= 0.0);
             if (p->left->length < TIME_MIN)
                 {
                 p->left->length = 0.0;
@@ -16946,7 +14757,7 @@ int Move_TreeStretch (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRa
                     }
                 numChangedNodes--;
                 }
-            else if (p->right->length < TIME_MIN)
+            if (p->right->length < TIME_MIN)
                 {
                 p->right->length = 0.0;
                 p->nodeDepth = p->right->nodeDepth;
@@ -16962,17 +14773,22 @@ int Move_TreeStretch (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRa
                     }
                 numChangedNodes--;
                 }
+            assert (!(p->left->length == 0.0 && p->right->length == 0.0));
+            }
+        }
+    
+    /* update brls */
+    for (i=0; i<t->nNodes-1; i++)
+        {
+        p = t->allDownPass[i];
+        if (p->left != NULL)
+            {
             if (p->left->length > 0.0)
                 p->left->length = p->nodeDepth - p->left->nodeDepth;
             if (p->right->length > 0.0)
                 p->right->length = p->nodeDepth - p->right->nodeDepth;
             }
         }
-    
-    /* in case the ancestor cannot be moved */
-    p = t->root->left;
-    p->left->length = p->nodeDepth - p->left->nodeDepth;
-    p->right->length = p->nodeDepth - p->right->nodeDepth;
 
     /* check that all branch lengths are proper, which need not be the case */
     for (i = 0; i < t->nNodes -2; i++)
diff --git a/src/proposal.h b/src/proposal.h
index b862505..f598523 100644
--- a/src/proposal.h
+++ b/src/proposal.h
@@ -22,7 +22,6 @@ int     Move_ExtSPRClock (Param *param, int chain, RandLong *seed, MrBFlt *lnPri
 int     Move_ExtSS (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_ExtSSClock (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_ExtTBR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
-int     Move_ExtTBR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_GeneRate_Dir (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_Growth_M (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_IgrVar (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
@@ -49,17 +48,15 @@ int     Move_OmegaPur (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorR
 int     Move_ParsEraser1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_ParsSPR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_ParsSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
+int     Move_ParsSPR2 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_ParsSPRClock (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
-int     Move_ParsTBR (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
+int     Move_ParsTBR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
+int     Move_ParsTBR2 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_PopSize (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_PosRealLognormal (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_PosRealMultiplier (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_PopSize_M (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_Pinvar (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
-int     Move_RanSPR1 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
-int     Move_RanSPR2 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
-int     Move_RanSPR3 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
-int     Move_RanSPR4 (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_RateMult_Dir (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_RateMult_Slider (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
 int     Move_RateShape_M (Param *param, int chain, RandLong *seed, MrBFlt *lnPriorRatio, MrBFlt *lnProposalRatio, MrBFlt *mvp);
diff --git a/src/sumpt.c b/src/sumpt.c
index df7ae56..4f9618b 100644
--- a/src/sumpt.c
+++ b/src/sumpt.c
@@ -43,7 +43,7 @@
 #include "SIOUX.h"
 #endif
 
-const char* const svnRevisionSumptC = "$Rev: 1031 $";   /* Revision keyword which is expended/updated by svn on each commit/update */
+const char* const svnRevisionSumptC = "$Rev: 1072 $";   /* Revision keyword which is expended/updated by svn on each commit/update */
 
 typedef struct partctr
     {
@@ -93,6 +93,11 @@ extern int DoUserTree (void);
 extern int DoUserTreeParm (char *parmName, char *tkn);
 extern int SafeFclose(FILE **);
 
+extern int  SetUpPartitionCounters (void);
+extern int  AddTreeToPartitionCounters (Tree *tree, int treeId, int runId);
+extern void CalcTopoConvDiagn2 (int *nTrees);
+extern void FreeChainMemory (void);
+
 /* local prototypes */
 int      CompareModelProbs (const void *x, const void *y);
 int      PrintModelStats (char *fileName, char **headerNames, int nHeaders, ParameterSample *parameterSamples, int nRuns, int nSamples);
@@ -1659,7 +1664,7 @@ int ExamineSumpFile (char *fileName, SumpFileInfo *fileInfo, char ***headerNames
     fileInfo->longestLineLength += 10;      /* better safe than sorry; if you fgets with raw longestLineLength, you run into problems */
 
     /* allocate string long enough to hold a line */
-    s = (char *)SafeMalloc((size_t) (2*(fileInfo->longestLineLength + 10) * sizeof(char)));
+    s = (char *)SafeMalloc(2 * ((size_t)(fileInfo->longestLineLength) +10) * sizeof(char));
     if (!s)
         {
         MrBayesPrint ("%s   Problem allocating string for reading sump file\n", spacer);
@@ -1984,11 +1989,7 @@ int PrintMargLikes (char *fileName, char **headerNames, int nHeaders, ParameterS
                 break;
         if (modelIndicatorParams[j][0]!='\0')
             continue;
-        if (!strcmp (temp, "Gen"))
-            continue;
-        if (!strcmp (temp, "LnL") == SAME)
-            continue;
-        if (!strcmp (temp, "LnPr") == SAME)
+        if (!strcmp (temp, "Gen") || !strcmp (temp, "LnL") || !strcmp (temp, "LnPr"))
             continue;
         if (len > longestHeader)
             longestHeader = len;
@@ -2048,11 +2049,7 @@ int PrintMargLikes (char *fileName, char **headerNames, int nHeaders, ParameterS
         for (j=0; modelIndicatorParams[j][0]!='\0'; j++)
             if (IsSame (temp,modelIndicatorParams[j]) != DIFFERENT)
                 break;
-        if (IsSame (temp, "Gen") == SAME)
-            continue;
-        if (IsSame (temp, "LnL") == SAME)
-            continue;
-        if (!strcmp (temp, "LnPr") == SAME)
+        if (!strcmp (temp, "Gen") || !strcmp (temp, "LnL") || !strcmp (temp, "LnPr"))
             continue;
 
         GetSummary (parameterSamples[i].values, nRuns, sampleCounts, &theStats, sumpParams.HPD);
@@ -2245,7 +2242,7 @@ int PrintModelStats (char *fileName, char **headerNames, int nHeaders, Parameter
             }
 
         /* sort in terms of decreasing probabilities */
-        qsort((void *) elem, (size_t) nElements, (size_t) sizeof(ModelProb), CompareModelProbs);
+        qsort((void *)elem, (size_t)nElements, sizeof(ModelProb), CompareModelProbs);
 
         for (j1=0; j1<nElements; j1++)
             {
@@ -2490,11 +2487,7 @@ int PrintParamStats (char *fileName, char **headerNames, int nHeaders, Parameter
                 break;
         if (modelIndicatorParams[j][0]!='\0')
             continue;
-        if (!strcmp (temp, "Gen"))
-            continue;
-        if (!strcmp (temp, "LnL") == SAME)
-            continue;
-        if (!strcmp (temp, "LnPr") == SAME)
+        if (!strcmp (temp, "Gen") || !strcmp (temp, "LnL") || !strcmp (temp, "LnPr"))
             continue;
         if (len > longestHeader)
             longestHeader = len;
@@ -2557,11 +2550,7 @@ int PrintParamStats (char *fileName, char **headerNames, int nHeaders, Parameter
                 break;
         if (modelIndicatorParams[j][0]!='\0')
             continue;
-        if (IsSame (temp, "Gen") == SAME)
-            continue;
-        if (IsSame (temp, "LnL") == SAME)
-            continue;
-        if (!strcmp (temp, "LnPr") == SAME)
+        if (!strcmp (temp, "Gen") || !strcmp (temp, "LnL") || !strcmp (temp, "LnPr"))
             continue;
 
         GetSummary (parameterSamples[i].values, nRuns, sampleCounts, &theStats, sumpParams.HPD);
@@ -2948,26 +2937,26 @@ PartCtr *AddSumtPartition (PartCtr *r, PolyTree *t, PolyNode *p, int runId)
                 {
                 /* allocate more space */
                 if (sumtParams.brlensDef == YES)
-                    r->length[runId] = (MrBFlt *) SafeRealloc ((void *)r->length[runId],(size_t)((n+ALLOC_LEN)*sizeof(MrBFlt)));
+                    r->length[runId] = (MrBFlt *) SafeRealloc ((void *)r->length[runId], ((size_t)n+ALLOC_LEN)*sizeof(MrBFlt));
                 if (sumtParams.isClock == YES)
-                    r->height[runId] = (MrBFlt *) SafeRealloc ((void *)r->height[runId],(size_t)((n+ALLOC_LEN)*sizeof(MrBFlt)));
+                    r->height[runId] = (MrBFlt *) SafeRealloc ((void *)r->height[runId], ((size_t)n+ALLOC_LEN)*sizeof(MrBFlt));
                 if (sumtParams.isCalibrated == YES)
-                    r->age[runId] = (MrBFlt *) SafeRealloc ((void *)r->age[runId],(size_t)((n+ALLOC_LEN)*sizeof(MrBFlt)));
+                    r->age[runId] = (MrBFlt *) SafeRealloc ((void *)r->age[runId], ((size_t)n+ALLOC_LEN)*sizeof(MrBFlt));
                 if (sumtParams.nESets > 0)
                     {
                     for (i=0; i<sumtParams.nESets; i++)
-                        r->nEvents[i][runId] = (int *) SafeRealloc ((void *)r->nEvents[i][runId], (size_t)(n+ALLOC_LEN)*sizeof(int));
+                        r->nEvents[i][runId] = (int *) SafeRealloc ((void *)r->nEvents[i][runId], ((size_t)n+ALLOC_LEN)*sizeof(int));
                     }
                 if (sumtParams.nBSets > 0)
                     {
                     for (i=0; i<sumtParams.nBSets; i++)
                         {
-                        r->bRate[i][runId]   = (MrBFlt *) SafeRealloc ((void *)r->bRate[i][runId], (size_t)(n+ALLOC_LEN)*sizeof(MrBFlt));
-                        r->bLen [i][runId]   = (MrBFlt *) SafeRealloc ((void *)r->bLen [i][runId], (size_t)(n+ALLOC_LEN)*sizeof(MrBFlt));
+                        r->bRate[i][runId]   = (MrBFlt *) SafeRealloc ((void *)r->bRate[i][runId], ((size_t)n+ALLOC_LEN)*sizeof(MrBFlt));
+                        r->bLen [i][runId]   = (MrBFlt *) SafeRealloc ((void *)r->bLen [i][runId], ((size_t)n+ALLOC_LEN)*sizeof(MrBFlt));
                         }
                     }
                 if (sumtParams.popSizeSet == YES)
-                    r->popSize[runId] = (MrBFlt *) SafeRealloc ((void *)r->popSize[runId],(size_t)((n+ALLOC_LEN)*sizeof(MrBFlt)));
+                    r->popSize[runId] = (MrBFlt *) SafeRealloc ((void *)r->popSize[runId], ((size_t)n+ALLOC_LEN)*sizeof(MrBFlt));
                 }
             /* record values */
             r->count[runId]++;
@@ -3078,55 +3067,55 @@ PartCtr *AllocPartCtr ()
     PartCtr         *r;
     
     /* allocate basic stuff */
-    r = (PartCtr *) SafeCalloc ((size_t) 1, sizeof(PartCtr));
+    r = (PartCtr *) SafeCalloc (1, sizeof(PartCtr));
     r->left = r->right = NULL;
-    r->partition = (BitsLong *) SafeCalloc ((size_t) sumtParams.BitsLongsNeeded, sizeof(BitsLong));
-    r->count = (int *) SafeCalloc ((size_t) sumtParams.numRuns, sizeof (int));
+    r->partition = (BitsLong *) SafeCalloc ((size_t)(sumtParams.BitsLongsNeeded), sizeof(BitsLong));
+    r->count = (int *) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof (int));
     if (sumtParams.brlensDef)
         {
-        r->length = (MrBFlt **) SafeCalloc ((size_t) sumtParams.numRuns, sizeof (MrBFlt *));
+        r->length = (MrBFlt **) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof (MrBFlt *));
         for (i=0; i<sumtParams.numRuns; i++)
-            r->length[i] = (MrBFlt *) SafeCalloc (ALLOC_LEN, sizeof(MrBFlt));
+            r->length[i] = (MrBFlt *) SafeCalloc ((size_t)ALLOC_LEN, sizeof(MrBFlt));
         }
     if (sumtParams.isClock)
         {
-        r->height = (MrBFlt **) SafeCalloc ((size_t) sumtParams.numRuns, sizeof (MrBFlt *));
+        r->height = (MrBFlt **) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof (MrBFlt *));
         for (i=0; i<sumtParams.numRuns; i++)
-            r->height[i] = (MrBFlt *) SafeCalloc (ALLOC_LEN, sizeof(MrBFlt));
-        r->age = (MrBFlt **) SafeCalloc ((size_t) sumtParams.numRuns, sizeof (MrBFlt *));
+            r->height[i] = (MrBFlt *) SafeCalloc ((size_t)ALLOC_LEN, sizeof(MrBFlt));
+        r->age = (MrBFlt **) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof (MrBFlt *));
         for (i=0; i<sumtParams.numRuns; i++)
-            r->age[i] = (MrBFlt *) SafeCalloc (ALLOC_LEN, sizeof(MrBFlt));
+            r->age[i] = (MrBFlt *) SafeCalloc ((size_t)ALLOC_LEN, sizeof(MrBFlt));
         }
 
     /* allocate relaxed clock parameters: eRate, nEvents, bRate */
     if (sumtParams.nESets > 0)
-        r->nEvents = (int    ***) SafeCalloc ((size_t) sumtParams.nESets, sizeof(int **));
+        r->nEvents = (int    ***) SafeCalloc ((size_t)(sumtParams.nESets), sizeof(int **));
     for (i=0; i<sumtParams.nESets; i++)
         {
-        r->nEvents[i] = (int    **) SafeCalloc ((size_t) sumtParams.numRuns, sizeof(int *));
+        r->nEvents[i] = (int    **) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof(int *));
         for (j=0; j<sumtParams.numRuns; j++)
             r->nEvents[i][j] = (int    *) SafeCalloc ((size_t) ALLOC_LEN, sizeof(int));
         }
     if (sumtParams.nBSets > 0)
         {
-        r->bLen  = (MrBFlt ***) SafeCalloc ((size_t) sumtParams.nBSets, sizeof(MrBFlt **));
-        r->bRate = (MrBFlt ***) SafeCalloc ((size_t) sumtParams.nBSets, sizeof(MrBFlt **));
+        r->bLen  = (MrBFlt ***) SafeCalloc ((size_t)(sumtParams.nBSets), sizeof(MrBFlt **));
+        r->bRate = (MrBFlt ***) SafeCalloc ((size_t)(sumtParams.nBSets), sizeof(MrBFlt **));
         }
     for (i=0; i<sumtParams.nBSets; i++)
         {
-        r->bLen[i]    = (MrBFlt **) SafeCalloc ((size_t) sumtParams.numRuns, sizeof(MrBFlt *));
-        r->bRate[i]   = (MrBFlt **) SafeCalloc ((size_t) sumtParams.numRuns, sizeof(MrBFlt *));
+        r->bLen[i]    = (MrBFlt **) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof(MrBFlt *));
+        r->bRate[i]   = (MrBFlt **) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof(MrBFlt *));
         for (j=0; j<sumtParams.numRuns; j++)
             {
-            r->bLen[i][j]    = (MrBFlt *) SafeCalloc ((size_t) ALLOC_LEN, sizeof(MrBFlt));
-            r->bRate[i][j]   = (MrBFlt *) SafeCalloc ((size_t) ALLOC_LEN, sizeof(MrBFlt));
+            r->bLen[i][j]    = (MrBFlt *) SafeCalloc ((size_t)ALLOC_LEN, sizeof(MrBFlt));
+            r->bRate[i][j]   = (MrBFlt *) SafeCalloc ((size_t)ALLOC_LEN, sizeof(MrBFlt));
             }
         }
     if (sumtParams.popSizeSet == YES)
         {
-        r->popSize = (MrBFlt **) SafeCalloc ((size_t) sumtParams.numRuns, sizeof (MrBFlt *));
+        r->popSize = (MrBFlt **) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof (MrBFlt *));
         for (i=0; i<sumtParams.numRuns; i++)
-            r->popSize[i] = (MrBFlt *) SafeCalloc (ALLOC_LEN, sizeof(MrBFlt));
+            r->popSize[i] = (MrBFlt *) SafeCalloc ((size_t)ALLOC_LEN, sizeof(MrBFlt));
         }
 
     return r;
@@ -3138,11 +3127,11 @@ TreeCtr *AllocTreeCtr ()
 {
     TreeCtr     *r;
 
-    r = (TreeCtr *) SafeCalloc ((size_t) 1, sizeof(TreeCtr));
+    r = (TreeCtr *) SafeCalloc (1, sizeof(TreeCtr));
     
     r->left = r->right = NULL;
     
-    r->order = (int *) SafeCalloc ((size_t) sumtParams.orderLen, sizeof(int));
+    r->order = (int *) SafeCalloc ((size_t)(sumtParams.orderLen), sizeof(int));
 
     return r;
 }
@@ -3204,7 +3193,7 @@ void CalculateTreeToTreeDistance (Tree *tree1, Tree *tree2, MrBFlt *d1, MrBFlt *
 }
 
 
-/* ConTree: Construct consensus tree FIXME: numTreeParts is not used*/
+/* ConTree: Construct consensus tree */
 int ConTree (PartCtr **treeParts, int numTreeParts)
 {
     int         i, j, targetNode, nBits, isCompat, numTerminalsEncountered;
@@ -3735,7 +3724,7 @@ int DoCompareTree (void)
     
     /* Allocate space for command string */
     longestLineLength += 10;
-    s = (char *)SafeMalloc((size_t) (longestLineLength * sizeof(char)));
+    s = (char *)SafeMalloc((size_t)longestLineLength * sizeof(char));
     if (!s)
         {
         MrBayesPrint ("%s   Problem allocating string for reading tree file\n", spacer);
@@ -3779,7 +3768,7 @@ int DoCompareTree (void)
         MrBayesPrint ("%s   Using absolute burnin ('relburnin=no'), discarding the first %d ('burnin=%d') sampled trees\n",
             spacer, chainParams.chainBurnIn, chainParams.chainBurnIn);
 
-    MrBayesPrint ("%s   Writing statistics to file %s\n", spacer, comptreeParams.comptOutfile);
+    MrBayesPrint ("%s   Writing statistics to file %s.<dists|pairs>\n", spacer, comptreeParams.comptOutfile);
 
     /* Set up cheap status bar. */
     MrBayesPrint ("\n%s   Tree reading status:\n\n", spacer);
@@ -3856,7 +3845,7 @@ int DoCompareTree (void)
 
     /* Read file 2 for real */
     if ((fp = OpenTextFileR(comptreeParams.comptFileName2)) == NULL)
-        return ERROR;
+        goto errorExit;
         
     /* ...and fast forward to beginning of last tree block. */
     for (i=0; i<lastTreeBlockBegin[1] + 1; i++)
@@ -3911,7 +3900,6 @@ int DoCompareTree (void)
     MrBayesPrint ("\n\n");
     
     /* tell user how many trees were successfully read */
-    /* tell user how many trees were successfully read */
     MrBayesPrint ("%s   Read %d trees from last tree block of file \"%s\" (sampling %d of them)\n", spacer,
         sumtParams.numFileTrees[0],
         comptreeParams.comptFileName1,
@@ -4068,7 +4056,7 @@ int DoCompareTree (void)
     minNumTrees = sumtParams.numFileTreesSampled[0];
     if (sumtParams.numFileTreesSampled[1] < minNumTrees)
         minNumTrees = sumtParams.numFileTreesSampled[1];
-    dT1 = (MrBFlt *)SafeMalloc((size_t) (3 * minNumTrees * sizeof(MrBFlt)));
+    dT1 = (MrBFlt *) SafeMalloc (3 * (size_t)minNumTrees * sizeof(MrBFlt));
     tree1 = AllocateFixedTree (sumtParams.numTaxa, sumtParams.isRooted);
     tree2 = AllocateFixedTree (sumtParams.numTaxa, sumtParams.isRooted);
     if (!dT1 || !tree1 || !tree2)
@@ -4130,7 +4118,7 @@ int DoCompareTree (void)
     maxX = maxY = -1000000000.0;
     for (i=0; i<minNumTrees; i++)
         {
-        xVal = (MrBFlt) (i + chainParams.chainBurnIn);
+        xVal = (MrBFlt) (i + comptreeParams.burnin);
         yVal = dT1[i];
         if (xVal < minX)
             minX = xVal;
@@ -4148,7 +4136,7 @@ int DoCompareTree (void)
         }
     for (i=0; i<minNumTrees; i++)
         {
-        xVal = (MrBFlt) (i + chainParams.chainBurnIn);
+        xVal = (MrBFlt) (i + comptreeParams.burnin);
         yVal = dT1[i];
         k = (int)(((xVal - minX) / (maxX - minX)) * screenWidth);
         if (k >= screenWidth)
@@ -4576,6 +4564,229 @@ int DoCompareTreeParm (char *parmName, char *tkn)
 }
 
 
+int DoCompRefTree (void)
+{
+    /* Compare a tree file with the reference tree files to generate the SDSFs.
+       Use parameters in CompareTree and MCMCP (lazy option) */
+    
+    char         outName[130], inName[130], inRefName[130], treeName[100], *lineBuf=NULL, *s;
+    FILE         *fpTre=NULL, *fpOut=NULL;
+    int          i, n, longestL=0, burnin, gen, nRefRun, nTre[100]={0};
+    SumtFileInfo tFileInfo;
+    Tree         *t;
+
+#   if defined (MPI_ENABLED)
+    if (proc_id != 0)
+        return NO_ERROR;
+#   endif
+
+    /* Check that a data set has been read in. We check taxon names against those read in. */
+    if (isTaxsetDef == NO)
+        {
+        MrBayesPrint ("%s   A matrix or set of taxon labels must be specified before compareref can be used\n", spacer);
+        return (ERROR);
+        }
+
+    /* this is a hack to account for the additional comparing tree sample 
+       chainParams.numRuns is used in AddTreeToPartitionCounters to alloc mem correctly */
+    nRefRun = chainParams.numRuns;
+    chainParams.numRuns += 1;
+
+    /* initialize */
+    if ((t = AllocateTree (numLocalTaxa)) == NULL)
+        {
+        MrBayesPrint ("%s   Problem allocating diagn tree\n", spacer);
+        goto errorExit;
+        }
+    if (SetUpPartitionCounters () == ERROR)
+        goto errorExit;
+    if ((chainParams.stat = (STATS *) SafeCalloc (numTopologies, sizeof (STATS))) == NULL)
+        goto errorExit;
+    else
+        memAllocs[ALLOC_STATS] = YES;
+
+    /* deal with the reference tree files */
+    // for (k=0; k<numTopologies; k++)
+    for (n=0; n<nRefRun; n++)
+        {
+        if (nRefRun == 1)
+            sprintf (inRefName, "%s.t", comptreeParams.comptFileName2);
+        else
+            sprintf (inRefName, "%s.run%d.t", comptreeParams.comptFileName2, n+1);
+        
+        /* Examine each ref tree file, save info to tFileInfo */
+        if (ExamineSumtFile(inRefName, &tFileInfo, treeName, &sumtParams.brlensDef) == ERROR)
+            goto errorExit;
+        if (longestL < tFileInfo.longestLineLength)
+            {
+            longestL = tFileInfo.longestLineLength;
+            lineBuf = (char *) SafeRealloc (lineBuf, (size_t)longestL * sizeof(char));
+            if (!lineBuf)
+                {
+                MrBayesPrint ("%s   Problem allocating string for reading tree file\n", spacer);
+                goto errorExit;
+                }
+            }
+        
+        /* calculate burnin */
+        if (chainParams.relativeBurnin == YES)
+            burnin = (int)(chainParams.burninFraction * tFileInfo.numTreesInLastBlock);
+        else
+            burnin = chainParams.chainBurnIn;
+        if (burnin >= tFileInfo.numTreesInLastBlock)
+            {
+            MrBayesPrint ("%s   Burnin should be smaller than the total number of trees\n", spacer);
+            goto errorExit;
+            }
+       
+        /* open the ref tree file */
+        if ((fpTre = OpenTextFileR (inRefName)) == NULL)
+            goto errorExit;
+        /* ...and fast forward to beginning in last tree block */
+        for (i=0; i <= tFileInfo.lastTreeBlockBegin; i++)
+            {
+            if (fgets(lineBuf, longestL-2, fpTre) == NULL)
+                goto errorExit;
+            }
+        
+        /* process each ref tree */
+        for (i=1; i <= tFileInfo.numTreesInLastBlock; i++)
+            {
+            do {
+                if (fgets (lineBuf, longestL-2, fpTre) == NULL)
+                    goto errorExit;
+                s = strtok (lineBuf, " ");
+                }
+            while (strcmp (s, "tree") != 0);
+            
+            /* add reference trees to partition counters, discarding burnin */
+            if (i > burnin)
+                {
+                s = strtok (NULL, ";");
+                while (*s != '(')
+                    s++;
+                StripComments(s);
+
+                if (ResetTopology (t, s) == ERROR)
+                    goto errorExit;
+                if (AddTreeToPartitionCounters (t, 0, n) == ERROR)
+                    goto errorExit;
+                nTre[n]++;
+                }
+            }
+
+        /* close the tree file */
+        SafeFclose (&fpTre);
+        }
+    /* end reference tree files */
+    
+    /* open output file */
+    strcpy (outName, comptreeParams.comptOutfile);
+    strcat (outName, ".sdsf");
+    if ((fpOut = OpenNewMBPrintFile (outName)) == NULL)
+        goto errorExit;
+    /* print stamp and header */
+    if ((int)strlen(stamp) > 1)
+        MrBayesPrintf (fpOut, "[ID: %s]\n", stamp);
+    if (chainParams.diagnStat == AVGSTDDEV)
+        MrBayesPrintf (fpOut, "Gen\tASDSF\n");
+    else  // MAXSTDDEV
+        MrBayesPrintf (fpOut, "Gen\tMSDSF\n");
+
+    /* Examine the tree file to be compared, save info to tFileInfo */
+    strcpy(inName, comptreeParams.comptFileName1);
+    if (ExamineSumtFile(inName, &tFileInfo, treeName, &sumtParams.brlensDef) == ERROR)
+        goto errorExit;
+    if (longestL < tFileInfo.longestLineLength)
+        {
+        longestL = tFileInfo.longestLineLength;
+        lineBuf = (char *) SafeRealloc (lineBuf, (size_t)longestL * sizeof(char));
+        if (!lineBuf)
+            {
+            MrBayesPrint ("%s   Problem allocating string for reading tree file\n", spacer);
+            goto errorExit;
+            }
+        }
+
+    /* open the tree file to be compared */
+    if ((fpTre = OpenTextFileR (inName)) == NULL)
+        goto errorExit;
+    /* ...and fast forward to beginning in last tree block */
+    for (i=0; i <= tFileInfo.lastTreeBlockBegin; i++)
+        {
+        if (fgets(lineBuf, longestL-2, fpTre) == NULL)
+            goto errorExit;
+        }
+
+    /* process each tree to be compared and print SDSF to file */
+    for (i=1; i <= tFileInfo.numTreesInLastBlock; i++)
+        {
+        do {
+            if (fgets (lineBuf, longestL-2, fpTre) == NULL)
+                goto errorExit;
+            s = strtok (lineBuf, " ");
+            }
+        while (strcmp (s, "tree") != 0);
+        
+        s = strtok (NULL, ";");
+        gen = atoi(s+4);  // 4 is offset to get rid of "rep." in tree name
+        while (*s != '(')
+            s++;
+        StripComments(s);
+
+        /* add the tree to partition counters */
+        if (ResetTopology (t, s) == ERROR)
+            goto errorExit;
+        if (AddTreeToPartitionCounters (t, 0, nRefRun) == ERROR)
+            goto errorExit;
+        nTre[nRefRun]++;
+            
+        /* calculate and write stdev of split freq */
+        CalcTopoConvDiagn2 (nTre);
+        if (chainParams.stat[0].numPartitions == 0)
+            {
+            MrBayesPrintf (fpOut, "%d\tNA\n", gen);
+            }
+        else if (chainParams.diagnStat == AVGSTDDEV)
+            {
+            MrBayesPrintf (fpOut, "%d\t%lf\n", gen, chainParams.stat[0].avgStdDev);
+            }
+        else  // MAXSTDDEV
+            {
+            MrBayesPrintf (fpOut, "%d\t%lf\n", gen, chainParams.stat[0].max);
+            }
+        }
+    
+    /* change back to the actual numRuns, end of hack */
+    chainParams.numRuns -= 1;
+    
+    /* close tree file */
+    SafeFclose (&fpTre);
+    /* close output file */
+    SafeFclose (&fpOut);
+    /* free memory */
+    free(lineBuf);
+    FreeTree (t);
+    FreeChainMemory();
+    
+    return (NO_ERROR);
+    
+    /* error exit */
+errorExit:
+    MrBayesPrint ("%s   Error in DoCompRefTree\n", spacer);
+    
+    chainParams.numRuns -= 1;
+    SafeFclose (&fpTre);
+    SafeFclose (&fpOut);
+    
+    FreeTree (t);
+    FreeChainMemory();
+    free(lineBuf);
+    
+    return (ERROR);
+}
+
+
 #if defined (PRINT_RATEMUL_CPP)
 int DELETE_ME_count_taxa(PolyNode *p)
 {
@@ -4805,7 +5016,7 @@ int DoSumt (void)
             /* Now we read the file for real. First, allocate a string for reading the file... */
             if (sumtParams.runId == 0 && treeNo == 0)
                 {
-                s = (char *)SafeMalloc((size_t) (sumtFileInfo.longestLineLength * sizeof(char)));
+                s = (char *) SafeMalloc ((size_t)(sumtFileInfo.longestLineLength) * sizeof(char));
                 if (!s)
                     {
                     MrBayesPrint ("%s   Problem allocating string for reading sumt file\n", spacer);
@@ -4815,7 +5026,7 @@ int DoSumt (void)
             else
                 {
                 free (s);
-                s = (char *) SafeMalloc (sizeof (char) * sumtFileInfo.longestLineLength);
+                s = (char *) SafeMalloc ((size_t)(sumtFileInfo.longestLineLength) * sizeof (char));
                 if (!s)
                     {
                     MrBayesPrint ("%s   Problem reallocating string for reading sumt file\n", spacer);
@@ -4932,7 +5143,7 @@ int DoSumt (void)
             }   /* next run for this tree */
                 
         /* Extract partition counter pointers */
-        treeParts = (PartCtr **) SafeCalloc ((size_t)(numUniqueSplitsFound), sizeof(PartCtr *));
+        treeParts = (PartCtr **) SafeCalloc ((size_t)numUniqueSplitsFound, sizeof(PartCtr *));
         i = 0;
         PartCtrUppass(partCtrRoot, treeParts, &i);
 
@@ -5512,25 +5723,25 @@ int DoSumt (void)
             MrBayesPrint ("\n\n");
             }
             
-            /* Exclude trivial splits when calculating average standard deviation of split frequencies. */
-            avgStdDev = sumStdDev / (numTreePartsToPrint-sumtParams.numTaxa-1);
-            avgPSRF   = sumPSRF / numPSRFSamples;
-
-            if (sumtParams.numRuns > 1 && sumtParams.summary == YES)
-                {
-                MrBayesPrint ("%s   Summary statistics for partitions with frequency >= %1.2lf in at least one run:\n", spacer, sumtParams.minPartFreq);
-                MrBayesPrint ("%s       Average standard deviation of split frequencies = %1.6lf\n", spacer, avgStdDev);
-                MrBayesPrint ("%s       Maximum standard deviation of split frequencies = %1.6lf\n", spacer, maxStdDev);
-                }
-            if (sumtParams.brlensDef == YES && sumtParams.numRuns > 1 && sumtParams.summary == YES)
-                {
-                MrBayesPrint ("%s       Average PSRF for parameter values (excluding NA and >10.0) = %1.3lf\n", spacer, avgPSRF);
-                if (maxPSRF == 10)
-                    MrBayesPrint ("%s       Maximum PSRF for parameter values = NA\n", spacer);
-                else
-                    MrBayesPrint ("%s       Maximum PSRF for parameter values = %1.3lf\n", spacer, maxPSRF);
-                }
-            MrBayesPrint ("\n");
+        /* Exclude trivial splits when calculating average standard deviation of split frequencies. */
+        avgStdDev = sumStdDev / (numTreePartsToPrint-sumtParams.numTaxa-1);
+        avgPSRF   = sumPSRF / numPSRFSamples;
+        
+        if (sumtParams.numRuns > 1 && sumtParams.summary == YES)
+            {
+            MrBayesPrint ("%s   Summary statistics for partitions with frequency >= %1.2lf in at least one run:\n", spacer, sumtParams.minPartFreq);
+            MrBayesPrint ("%s       Average standard deviation of split frequencies = %1.6lf\n", spacer, avgStdDev);
+            MrBayesPrint ("%s       Maximum standard deviation of split frequencies = %1.6lf\n", spacer, maxStdDev);
+            }
+        if (sumtParams.brlensDef == YES && sumtParams.numRuns > 1 && sumtParams.summary == YES)
+            {
+            MrBayesPrint ("%s       Average PSRF for parameter values (excluding NA and >10.0) = %1.3lf\n", spacer, avgPSRF);
+            if (maxPSRF == 10)
+                MrBayesPrint ("%s       Maximum PSRF for parameter values = NA\n", spacer);
+            else
+                MrBayesPrint ("%s       Maximum PSRF for parameter values = %1.3lf\n", spacer, maxPSRF);
+            }
+        MrBayesPrint ("\n");
 
         SortPartCtr (treeParts, 0, numUniqueSplitsFound-1); /* We sort again but this time we sort all partitions instead of just first numTreePartsToPrintNow */
         /* make the majority rule consensus tree */
@@ -6439,7 +6650,7 @@ int ExamineSumtFile (char *fileName, SumtFileInfo *sumtFileInfo, char *treeName,
     sumtFileInfo->longestLineLength += 10;
     
     /* allocate a string long enough to hold a line */
-    s = (char *)SafeMalloc((size_t) (sumtFileInfo->longestLineLength * sizeof(char)));
+    s = (char *)SafeMalloc((size_t)(sumtFileInfo->longestLineLength) * sizeof(char));
     if (!s)
         {
         MrBayesPrint ("%s   Problem allocating string for examining file \"%s\"\n", spacer, fileName);
diff --git a/src/sumpt.h b/src/sumpt.h
index 21daf25..82ce273 100644
--- a/src/sumpt.h
+++ b/src/sumpt.h
@@ -39,6 +39,7 @@ int     ReadParamSamples (char *fileName, SumpFileInfo *fileInfo, ParameterSampl
 
 int     DoCompareTree (void);
 int     DoCompareTreeParm (char *parmName, char *tkn);
+int     DoCompRefTree (void);
 int     DoSumt (void);
 int     DoSumtParm (char *parmName, char *tkn);
 int     DoSumtTree (void);
diff --git a/src/utils.c b/src/utils.c
index 42b1c32..59c6389 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -41,7 +41,7 @@
 #include "model.h"
 #include "utils.h"
 
-const char* const svnRevisionUtilsC = "$Rev: 1020 $";   /* Revision keyword which is expended/updated by svn on each commit/update */
+const char* const svnRevisionUtilsC = "$Rev: 1062 $";   /* Revision keyword which is expended/updated by svn on each commit/update */
 
 #define MAX_GAMMA_CATS                      20
 #define PI                                  3.14159265358979324
@@ -141,11 +141,11 @@ int AddBitfield (BitsLong ***list, int listLen, int *set, int setLen)
 
     nLongsNeeded = (setLen - 1) / nBitsInALong + 1;
 
-    (*list) = (BitsLong **) SafeRealloc ((void *)(*list), (size_t)((listLen+1)*sizeof(BitsLong *)));
+    (*list) = (BitsLong **) SafeRealloc ((void *)(*list), ((size_t)listLen+1)*sizeof(BitsLong *));
     if (!(*list))
         return ERROR;
     
-    (*list)[listLen] = (BitsLong *) SafeMalloc ((size_t)(nLongsNeeded*sizeof(BitsLong)));
+    (*list)[listLen] = (BitsLong *) SafeMalloc ((size_t)nLongsNeeded*sizeof(BitsLong));
     if (!(*list)[listLen])
         return ERROR;
 
@@ -637,7 +637,7 @@ void GetSummary (MrBFlt **vals, int nRows, int *rowCount, Stat *theStats, int HP
     p = theValues;
     for (i=0; i<nRows; i++)
         {
-        memcpy ((void *)(p),(void *)(vals[i]),(size_t)(rowCount[i]*sizeof(MrBFlt)));
+        memcpy ((void *)(p), (void *)(vals[i]), (size_t)rowCount[i] * sizeof(MrBFlt));
         p += rowCount[i];
         }
     
@@ -650,7 +650,7 @@ void GetSummary (MrBFlt **vals, int nRows, int *rowCount, Stat *theStats, int HP
     if (nRows > 1)
         theStats->PSRF = PotentialScaleReduction (vals, nRows, rowCount);
 
-    ESS =   (MrBFlt *) SafeMalloc ((size_t) nRows * sizeof(MrBFlt));
+    ESS = (MrBFlt *) SafeMalloc ((size_t)nRows * sizeof(MrBFlt));
 
     EstimatedSampleSize (vals, nRows, rowCount, ESS);
     theStats->avrESS = theStats->minESS = ESS[0];
@@ -1560,10 +1560,10 @@ char *SafeStrcat (char **target, const char *source)
     if (*target == NULL)
         *target = (char *) SafeCalloc (strlen(source)+1, sizeof(char));
     else
-        *target = (char *) SafeRealloc ((void *)*target, (size_t)(strlen(source)+strlen(*target)+1)*sizeof(char));
+        *target = (char *) SafeRealloc ((void *)*target, (strlen(source)+strlen(*target)+1)*sizeof(char));
 
     if (*target)
-        strcat(*target,source);
+        strcat(*target, source);
 
     return (*target);
 }
@@ -1572,7 +1572,7 @@ char *SafeStrcat (char **target, const char *source)
 /* SafeStrcpy: Allocate or reallocate target to fit result; assumes ptr is NULL if not allocated */
 char *SafeStrcpy (char **target, const char *source)
 {
-    *target = (char *) SafeRealloc ((void *)*target, (size_t)(strlen(source)+1)*sizeof(char));
+    *target = (char *) SafeRealloc ((void *)*target, (strlen(source)+1)*sizeof(char));
 
     if (*target)
         strcpy(*target,source);
@@ -2144,7 +2144,7 @@ int AllocateTreePartitions (Tree *t)
     nLongsNeeded = (numTaxa - 1) / nBitsInALong + 1;
 
     /* reallocate space */
-    t->bitsets = (BitsLong *) SafeRealloc ((void *) t->bitsets, (size_t)(t->nNodes*nLongsNeeded*sizeof(BitsLong)));
+    t->bitsets = (BitsLong *) SafeRealloc ((void *)(t->bitsets), (size_t)(t->nNodes) * (size_t)nLongsNeeded * sizeof(BitsLong));
     if (!t->bitsets)
         return (ERROR);
     
@@ -3460,11 +3460,11 @@ void CopyTreeNodes (TreeNode *p, TreeNode *q, int nLongsNeeded)
     p->nodeDepth              = q->nodeDepth;
     p->calibration            = q->calibration;
     p->age                    = q->age;
-    if (nLongsNeeded!=0)
+    if (nLongsNeeded != 0)
         {
         assert (p->partition);
         assert (q->partition);
-        memcpy (p->partition,q->partition, nLongsNeeded*sizeof(BitsLong));
+        memcpy (p->partition, q->partition, nLongsNeeded*sizeof(BitsLong));
         }
 }
 
@@ -8473,7 +8473,7 @@ void WriteEventTreeToPrintString (TreeNode *p, int chain, Param *param, int prin
     int             i, j, nEvents, tempStrSize = TEMPSTRSIZE;
     MrBFlt          brlen, *position, *rateMult;
 
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
 
@@ -8629,7 +8629,7 @@ void WriteNoEvtTreeToPrintString (TreeNode *p, int chain, Param *param, int show
     int             i, tempStrSize = TEMPSTRSIZE, nEvents;
     MrBFlt          brlen, N;
 
-    tempStr = (char *) SafeMalloc((size_t) (tempStrSize * sizeof(char)));
+    tempStr = (char *) SafeMalloc((size_t)tempStrSize * sizeof(char));
     if (!tempStr)
         MrBayesPrint ("%s   Problem allocating tempString (%d)\n", spacer, tempStrSize * sizeof(char));
 
@@ -8789,13 +8789,13 @@ complex **AllocateSquareComplexMatrix (int dim)
     int         i;
     complex     **m;
 
-    m = (complex **) SafeMalloc((size_t)((dim)*sizeof(complex*)));
+    m = (complex **) SafeMalloc ((size_t)dim * sizeof(complex*));
     if (!m) 
         {
         MrBayesPrint ("%s   Error: Problem allocating a square complex matrix.\n", spacer);
         exit (0);
         }
-    m[0]=(complex *) SafeMalloc((size_t)((dim*dim)*sizeof(complex)));
+    m[0]=(complex *) SafeMalloc ((size_t)dim * (size_t)dim *sizeof(complex));
     if (!m[0]) 
         {
         MrBayesPrint ("%s   Error: Problem allocating a square complex matrix.\n", spacer);
@@ -8822,13 +8822,13 @@ MrBFlt **AllocateSquareDoubleMatrix (int dim)
     int         i;
     MrBFlt      **m;
     
-    m = (MrBFlt **)SafeMalloc((size_t)((dim)*sizeof(MrBFlt*)));
+    m = (MrBFlt **) SafeMalloc ((size_t)dim * sizeof(MrBFlt*));
     if (!m)
         {
         MrBayesPrint ("%s   Error: Problem allocating a square matrix of doubles.\n", spacer);
         exit(1);
         }
-    m[0] = (MrBFlt *)SafeMalloc((size_t)((dim*dim)*sizeof(MrBFlt)));
+    m[0] = (MrBFlt *) SafeMalloc ((size_t)dim * (size_t)dim * sizeof(MrBFlt));
     if (!m[0])
         {
         MrBayesPrint ("%s   Error: Problem allocating a square matrix of doubles.\n", spacer);
@@ -8854,13 +8854,13 @@ int **AllocateSquareIntegerMatrix (int dim)
 {
     int     i, **m;
     
-    m = (int **)SafeMalloc((size_t)((dim)*sizeof(int*)));
+    m = (int **) SafeMalloc ((size_t)dim * sizeof(int*));
     if (!m)
         {
         MrBayesPrint ("%s   Error: Problem allocating a square matrix of integers.\n", spacer);
         exit(1);
         }
-    m[0] = (int *)SafeMalloc((size_t)((dim*dim)*sizeof(int)));
+    m[0] = (int *) SafeMalloc ((size_t)dim * (size_t)dim * sizeof(int));
     if (!m[0])
         {
         MrBayesPrint ("%s   Error: Problem allocating a square matrix of integers.\n", spacer);
@@ -11033,7 +11033,7 @@ void GaussianElimination (int dim, MrBFlt **a, MrBFlt **bMat, MrBFlt **xMat)
 
     lMat = AllocateSquareDoubleMatrix (dim);
     uMat = AllocateSquareDoubleMatrix (dim);
-    bVec = (MrBFlt *)SafeMalloc((size_t) ((dim) * sizeof(MrBFlt)));
+    bVec = (MrBFlt *) SafeMalloc ((size_t)dim * sizeof(MrBFlt));
     if (!bVec)
         {
         MrBayesPrint ("%s   Error: Problem allocating bVec\n", spacer);
@@ -11080,8 +11080,8 @@ int GetEigens (int dim, MrBFlt **q, MrBFlt *eigenValues, MrBFlt *eigvalsImag, Mr
     complex     **cWork, *Ccol;
 
     /* allocate memory */
-    dWork = (MrBFlt *)SafeMalloc((size_t) (dim * sizeof(MrBFlt)));
-    iWork = (int *)SafeMalloc((size_t) (dim * sizeof(int)));
+    dWork = (MrBFlt *) SafeMalloc ((size_t)dim * sizeof(MrBFlt));
+    iWork = (int *) SafeMalloc ((size_t)dim * sizeof(int));
     if (!dWork || !iWork)
         {
         MrBayesPrint ("%s   Error: Problem in GetEigens\n", spacer);
@@ -11136,7 +11136,7 @@ int GetEigens (int dim, MrBFlt **q, MrBFlt *eigenValues, MrBFlt *eigvalsImag, Mr
                     }
                 }
             }
-        Ccol = (complex *)SafeMalloc((size_t) (dim * sizeof(complex)));
+        Ccol = (complex *) SafeMalloc ((size_t)dim * sizeof(complex));
         if (!Ccol)
             {
             MrBayesPrint ("%s   Error: Problem in GetEigens\n", spacer);
@@ -12737,11 +12737,10 @@ MrBFlt LnPriorProbTruncatedNormal (MrBFlt val, MrBFlt *params)
     MrBFlt z, z_0, normConst;
 
     z = (val - params[0]) / params[1];
-
     z_0 = (0.0 - params[0]) / params[1];
     normConst = CdfNormal(z_0);
-
-    return - log(params[1] * sqrt(2.0 * PI)) - z * z / 2.0 - log(normConst);
+    
+    return - log(params[1] * sqrt(2.0 * PI)) - z * z / 2.0 - log(1.0 - normConst);
 }
 
 
@@ -12751,11 +12750,10 @@ MrBFlt LnPriorProbTruncatedNormal_Param_Trunc_Mean_Sd (MrBFlt val, MrBFlt *param
     MrBFlt z, z_trunc, normConst;
 
     z = (val - params[1]) / params[2];
-
     z_trunc = (params[0] - params[1]) / params[2];
     normConst = CdfNormal(z_trunc);
 
-    return - log(params[2] * sqrt(2.0 * PI)) - z * z / 2.0 - log(normConst);
+    return - log(params[2] * sqrt(2.0 * PI)) - z * z / 2.0 - log(1.0 - normConst);
 }
 
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/mrbayes.git



More information about the debian-med-commit mailing list