likelihoodFnChoice = 0;
if (Rows("LikelihoodFunction")>1)
{
	ChoiceList  (likelihoodFnChoice,"Choose a Likelihood Function",1,NO_SKIP,LikelihoodFunction);
}		
if (likelihoodFnChoice<0)
{
	return;
} 
LIKELIHOOD_FUNCTION_OUTPUT = response;
GetString(LF_NAME,LikelihoodFunction,likelihoodFnChoice);

GetString(paramName, LF_NAME, 0);
fParams = {};
pC = 1;
while (Abs(paramName))
{
	GetString (dumb, paramName__,0);
	dumb = dumb$"^[0-9]";
	if (dumb[0]==0)
	{
		fParams[paramName] = 1;
	}
	GetString(paramName, LF_NAME__, pC);
	pC = pC+1;
}


fKeys = Rows(fParams);
cKeys = {Abs(fParams),2};

for (k=0; k<Abs(fParams); k=k+1)
{
	cKeys[k][0] = fKeys[k];
	cKeys[k][1] = fKeys[k];
}

ChoiceList  (paramChoice,"Choose parameters to sample over",0,NO_SKIP,cKeys);

if (paramChoice[0]>=0)
{
	COVARIANCE_PARAMETER = {};
	for (k=0; k < Columns(paramChoice); k=k+1)
	{
		aKey = paramChoice[k];
		aKey = cKeys[aKey][0];
		COVARIANCE_PARAMETER[aKey] = 1;
	}
}
else
{
	return 0;
}

SAMPLE_N = 0;
while (SAMPLE_N < 1)
{
	fprintf (stdout, "\nSample size (>=1) ?");
	fscanf (stdin, "Number", SAMPLE_N);
}

SAMPLE_M = 0;
while (SAMPLE_M < 1 || SAMPLE_M > SAMPLE_N)
{
	fprintf (stdout, "\nRe-sample size ([1,",SAMPLE_N,"]) ?");
	fscanf (stdin, "Number", SAMPLE_M);
}

varCount = Abs(COVARIANCE_PARAMETER);
usedVars = Rows(COVARIANCE_PARAMETER);

fprintf (stdout, "\nObtaining profile likeihood bounds...\n");

svpc = COVARIANCE_PRECISION;

COVARIANCE_PRECISION = 0;
while (COVARIANCE_PRECISION >= 1 || COVARIANCE_PRECISION <= 0)
{
	fprintf (stdout, "\nCI Level ([0,1]) ?");
	fscanf (stdin, "Number", COVARIANCE_PRECISION);
}

ExecuteCommands ("CovarianceMatrix (covMx, "+LF_NAME+");");

COVARIANCE_PRECISION = svpc;
stashedValues = {varCount,4};

assignmentString = "";
assignmentString * 256;
assignmentString2 = "";
assignmentString2 * 256;

for (k=0; k<varCount; k=k+1)
{
	aKey = usedVars[k];
	stashedValues[k][0] = covMx[k][1];
	stashedValues[k][1] = covMx[k][0];
	stashedValues[k][2] = covMx[k][2];
	stashedValues[k][3] = (covMx[k][2]-covMx[k][0])/SAMPLE_N;
	assignmentString * (aKey+ "=generatedSamples[itCount]["+k+"];\n");
	assignmentString2 * (aKey+ "=sampledPoints[itCount]["+(k+1)+"];\n");
}

assignmentString * 0;
assignmentString2 * 0;

varCount	= Rows (covMx);
generatedSamples = {SAMPLE_N,varCount};
indexVector		 = {1,SAMPLE_N};

for (k=0; k<SAMPLE_N; k=k+1)
{
	indexVector[k] = k;
}

fprintf (stdout, "\nDoing Latin hypercube sampling...\n");

for (k=0; k<varCount; k=k+1)
{
	permVector = Random (indexVector,1);
	lb = stashedValues[k][1];
	st = stashedValues[k][3];
	for (m = 0; m<SAMPLE_N; m=m+1)
	{
		generatedSamples[m][k] = lb+st*permVector[m];
	}
}

#include "../ChartAddIns/Samplers/srs.ibf";

fprintf (stdout, "\nComputing expected Bayes Factors and expected posterior rates...\n");

ExecuteCommands ("GetInformation(catVars,"+LF_NAME+");");

if (Columns (catVars) > 1)
{
	have2 = 1;
	doSwap = (catVars[0] != "c");
}
else
{
	have2 = 0;
}

ExecuteCommands ("ConstructCategoryMatrix (marginalMatrix0,"+LF_NAME+",COMPLETE);");

rateAssignmentMatrix = {SAMPLE_M, 1+Columns (marginalMatrix0)};
BFMatrix             = {SAMPLE_M, 1+Columns (marginalMatrix0)};
labels				 = {1,Columns (marginalMatrix0)+1};


maxL = -1e100;

timer = Time (0);

for (itCount=0; itCount<SAMPLE_M; itCount=itCount+1)
{
	if (sampledPoints[itCount][0]>maxL)
	{
		maxL = sampledPoints[itCount][0];
	}
	ExecuteCommands (assignmentString2);
	ExecuteCommands ("ConstructCategoryMatrix (marginalMatrix,"+LF_NAME+",COMPLETE);");
	GetInformation (distribMX,c);
	if (have2)
	{
		GetInformation (distribMX2,d);	
		D1 = Columns(distribMX2);
		D2 = Columns(distribMX);
			
		distribMXR = {2,D1*D2};
		
		if (doSwap == 0)
		{
			for (k=0; k<D2; k=k+1)
			{
				E = k*D1;
				for (k2 = 0; k2<D1; k2=k2+1)
				{
					distribMXR [0][E+k2] = R*distribMX2[0][k2]-distribMX[0][k];
					distribMXR [1][E+k2] = R*distribMX2[1][k2]*distribMX[1][k];
				}
			}
		}
		else
		{
			for (k=0; k<D1; k=k+1)
			{
				E = k*D2;
				for (k2 = 0; k2<D2; k2=k2+1)
				{
					distribMXR [0][E+k2] = R*distribMX2[0][k]-distribMX[0][k2];
					distribMXR [1][E+k2] = distribMX2[1][k]*distribMX[1][k2];
				}
			}		
		}
		distribMX = distribMXR;
	}
	else
	{
		D1 = Columns(distribMX);
		for (k=0; k<D1; k=k+1)
		{
			distribMX[0][k] = distribMX[0][k]-1;
		}
	}
	
	
	ComputePosteriors (itCount);	
	if ((1+itCount) % 10 == 0)
	{
		fprintf (stdout, itCount+1, "/", SAMPLE_M, " samples processed. Estimated remaining time: ",Format (((SAMPLE_M-itCount-1)/(itCount+1))*(Time(0)-timer),5,2)," seconds \n");
	}
}

sum = 0;

for (itCount=0; itCount<SAMPLE_M; itCount=itCount+1)
{
	sum = sum + Exp(sampledPoints[itCount][0]-maxL);
}

for (itCount=0; itCount<SAMPLE_M; itCount=itCount+1)
{
	rateAssignmentMatrix[itCount][0] = Exp(sampledPoints[itCount][0]-maxL)/sum;
	BFMatrix[itCount][0] = Exp(sampledPoints[itCount][0]-maxL)/sum;	
}

for (k=0; k<varCount; k=k+1)
{
	aKey = usedVars[k];
	ExecuteCommands (aKey + "=" + stashedValues[k][0] + ";");
}	

labels[0] = "Weight";
for (k=Columns (marginalMatrix0); k; k=k-1)
{
	labels[k] = "Codon " + k;
}	

OpenWindow (CHARTWINDOW,{{"Bayes Factors for dN>dS"}
					   {"labels"},
					   {"BFMatrix"},
					   {""},
					   {"Index"},
					   {""},
					   {""},
					   {""},
					   {""},
					   {"3"}},
					   "(SCREEN_WIDTH-200);(SCREEN_HEIGHT-200);90;110");
					   
OpenWindow (CHARTWINDOW,{{"Posterior estimates of dN-dS)"}
					   {"labels"},
					   {"rateAssignmentMatrix"},
					   {""},
					   {"Index"},
					   {""},
					   {""},
					   {""},
					   {""},
					   {"3"}},
					   "(SCREEN_WIDTH-200);(SCREEN_HEIGHT-200);100;120");

function ComputePosteriors (sampleIndex)
{
	rMMX  = Rows(marginalMatrix);
	counter3 	 = 0;
	ratesOverOne = {Columns(distribMX),1};
	
	for (counter1=0; counter1<Columns(distribMX); counter1=counter1+1)
	{
		if (distribMX [0][counter1]>0)
		{
			ratesOverOne[counter3][0] = counter1;
			counter3 = counter3 + 1;
		}
	}

	priorOdds = 0;
	for (k=0; k<Columns(distribMX); k=k+1)
	{
		if (distribMX [0][k]>0)
		{
			priorOdds = priorOdds + distribMX [1][k];
		}
	}
	priorOdds = priorOdds/(1-priorOdds);

	for (counter1 = 0; counter1 < Columns (marginalMatrix); counter1=counter1+1)
	{
		columnSum = 0;				
		for (counter2 = 0; counter2 < rMMX; counter2 = counter2+1)
		{
			tempVal   = marginalMatrix [counter2][counter1];
			columnSum = columnSum + tempVal*distribMX[1][counter2];
			marginalMatrix [counter2][counter1] = tempVal * distribMX[1][counter2];
		}
		
		tempVal   = 0;
		
		for (counter2 = 0; counter2 < rMMX; counter2 = counter2+1)
		{
			tempVal   = tempVal + distribMX[0][counter2]*marginalMatrix [counter2][counter1];
		}
		
		rateAssignmentMatrix[sampleIndex][1+counter1] = tempVal/columnSum;

		tempVal   = 0;
		
		for (counter2 = 0; counter2 < counter3; counter2 = counter2+1)
		{
			indexVal  = ratesOverOne [counter2][0];
			tempVal   = tempVal + marginalMatrix [indexVal][counter1];
		}

		tempVal = tempVal/columnSum;
		BFMatrix[sampleIndex][1+counter1] = Log(tempVal/(1-tempVal)/priorOdds);
	}
	return 0;
}

