treeCount = Rows ("Tree");

if (treeCount > 0)
{
	treeChoices = {treeCount,2};
	for (k=0; k<treeCount; k=k+1)
	{
		GetString (treeID, Tree, k);
		treeChoices [k][0] = treeID;
		treeChoices [k][1] = "Tree " + treeID;
	}
	
	chosenTree = 0;
	if (treeCount > 1)
	{
		ChoiceList (chosenTree, "Which tree?", 1, SKIP_NONE, treeChoices);
		if (chosenTree < 0)
		{
			return;
		}
	}
	
	fprintf (stdout, "Enter a regular expression to pick a subset of leaves: ");
	fscanf  (stdin,  "String", regExp);
		
	ExecuteCommands ("treeAVL2 = "+treeChoices[chosenTree][0] + " ^ 0;bn = BranchName("+treeChoices[chosenTree][0]+",-1);"); 
	
	leafCount   = 0;
	matchedNodes	= {};
	for (k=0; k<Columns (bn)-1; k=k+1)
	{
		rem = bn[k] $ regExp;
		if (rem[0]>=0)
		{
			leafCount = leafCount + 1;
			rem = bn[k];
			matchedNodes [rem] = 1;
		}
	}
	
	multFactors 	= {};
	
	for (k=1; k<Abs(treeAVL2); k=k+1)
	{
		aNode 		= treeAVL2[k];
		aNodeName 	= aNode["Name"];
		parentIndex = aNode["Parent"];
		k2 			= Abs(aNode["Children"]);
		
		if (k2)
		{
			currentDepth = aNode["Below"];
			multFactors[aNodeName] = currentDepth;		
			if (currentDepth > 0 && currentDepth < leafCount)
			{
				fprintf (stdout, "Tagged internal node ", aNodeName, "\n");
				matchedNodes [aNodeName] = 1;
			}
			if (parentIndex > 0 && currentDepth < leafCount)
			{
				pInfo = treeAVL2[parentIndex];
				pInfo ["Below"] = pInfo ["Below"] + currentDepth;
				treeAVL2[parentIndex] = pInfo;
			}
		}
		else
		{
			rem 							= aNodeName $ regExp;
			if (rem[0] >= 0)
			{
				fprintf 						(stdout, "Matched leaf ", aNodeName, "\n");
				multFactors[aNodeName] 			= 1;
				pInfo 							= treeAVL2[parentIndex];
				pInfo ["Below"] 				= pInfo ["Below"] + 1;
				treeAVL2[parentIndex] 			= pInfo;
			}
		}
		
	}

	if (leafCount  < 2)
	{
		fprintf (stdout, "\nERROR: only matched ", leafCount, " leaves, but needed at least 2.\n");
		return 0;
	}
	fprintf (stdout, "\nMatched ", leafCount, " leaves.\n");
	
	pKeys 			= Rows(multFactors);

	for (k=0; k<Columns(pKeys); k=k+1)
	{
		aNodeName = pKeys[k];
		multFactors[aNodeName] = multFactors[aNodeName] * (leafCount-multFactors[aNodeName]);
	}

	divInfo 		=	 computeTotalDivergence (treeChoices[chosenTree][0]);
	pInfo 			= 	2*divInfo[0]/leafCount/(leafCount-1);
	currentDepth	= 	divInfo[1]/(Abs(treeAVL2)-2);
	
	fprintf (stdout, "Mean pairwise divergence for ",treeChoices[chosenTree][0], " is ", pInfo, 	   "\n");
	fprintf (stdout, "Mean branch length for ",      treeChoices[chosenTree][0], " is ", currentDepth, "\n");

	lf_Count						    = Rows ("LikelihoodFunction");
	if (lf_Count > 0)
	{
		for (lf_ID = 0; lf_ID < lf_Count; lf_ID = lf_ID + 1)
		{
			GetString (treeID, LikelihoodFunction,lf_ID);
			ExecuteCommands ("GetString(lfInfo,"+treeID+",-1);");
			lfTrees = lfInfo["Trees"];
			for (k = 0; k<Columns(lfTrees); k=k+1)
			{
				if (lfTrees[k] == treeChoices[chosenTree][0])
				{
					break;
				}
			}
			if (k < Columns(lfTrees))
			{
				fprintf (stdout, "\nTree ",Columns(lfTrees)," is a part of likelihood function ", treeID, "\n");
				global			TreeScalerParameter = 1;
				ExecuteCommands	("ClearConstraints("+treeChoices[chosenTree][0]+");");
				
				mNodeNames = Rows (matchedNodes);
				for (k2 = 0; k2 < Abs(matchedNodes); k2 = k2 + 1)
				{
					cte = "ReplicateConstraint (\"this1."+mNodeNames[k2]+".?:=TreeScalerParameter*this2."+mNodeNames[k2]+".?__\","+treeChoices[chosenTree][0]+","+treeChoices[chosenTree][0]+");\n";
					ExecuteCommands(cte);
				}
				COVARIANCE_PRECISION = 0.95;
				COVARIANCE_PARAMETER = "TreeScalerParameter";
				ExecuteCommands ("CovarianceMatrix(cmx,"+treeID+");");
				fprintf (stdout, "\nMultiplicative range ", cmx[0], "-", cmx[2], "\n");
				fprintf (stdout, "Mean pairwise divergence: ", pInfo, " (", pInfo*cmx[0],",",pInfo*cmx[2],")\n");
				fprintf (stdout, "Mean branch length divergence: ", currentDepth, " (", currentDepth*cmx[0],",",currentDepth*cmx[2],")\n");
				
			}
		}
	}
	
}

/*---------------------------------------------------------*/

function computeTotalDivergence (treeID)
{
	ExecuteCommands ("bNames = BranchName   ("+treeID+",-1);");
	ExecuteCommands ("bLen   = BranchLength ("+treeID+",-1);");
	
	sum  = 0;
	sum2 = 0;
	
	for (k=0; k<Columns(bNames); k=k+1)
	{
		aNodeName = bNames[k];
		sum  = sum  + bLen[k]*multFactors[aNodeName];
		sum2 = sum2 + bLen[k]*(multFactors[aNodeName]>0);
	}	
	return {{sum,sum2}};
}

