Model_Name  		= "MG94xREV_3x4_DualRV_GDD";
Model_Options 		= 2;
Model_Dimension 	= 64;
Model_EFV_Type		= "Observed Nuc 9 params.";

function GUIBuildCodonFrequencies (EFV)
{
	PIStop = 1.0;
	result = {ModelMatrixDimension,1};
	hshift = 0;
	
	for (h=0; h<64; h=h+1)
	{
		first = h$16;
		second = h%16$4;
		third = h%4;
		if (ModelGeneticCode[h]==10) 
		{
			hshift = hshift+1;
			PIStop = PIStop-EFV[first][0]*EFV[second][1]*EFV[third][2];
			continue; 
		}
		result[h-hshift][0]=EFV[first][0]*EFV[second][1]*EFV[third][2];
	}
	return result*(1.0/PIStop);
}

function GUIPopulateModelMatrix (ModelMatrixName&, EFV)
{
	global globalVariable_AC=1;
	global globalVariable_AT=1;
	global globalVariable_CG=1;
	global globalVariable_CT=1;
	global globalVariable_GT=1;
	
	if (!ModelMatrixDimension)
	{
		ModelMatrixDimension = 64;
		for (h = 0 ;h<64; h=h+1)
		{
			if (ModelGeneticCode[h]==10)
			{
				ModelMatrixDimension = ModelMatrixDimension-1;
			}
		}
	}
	
	ModelMatrixName = {ModelMatrixDimension,ModelMatrixDimension}; 

	hshift = 0;
	
	if (modelType == 0)
	{
		for (h=0; h<64; h=h+1)
		{
			if (ModelGeneticCode[h]==10) 
			{
				hshift = hshift+1;
				continue; 
			}
			vshift = hshift;
			for (v = h+1; v<64; v=v+1)
			{
				diff = v-h;
				if (ModelGeneticCode[v]==10) 
				{
					vshift = vshift+1;
					continue; 
				}
				nucPosInCodon = 2;
				if ((h$4==v$4)||((diff%4==0)&&(h$16==v$16))||(diff%16==0))
				{
					if (h$4==v$4)
					{
						transition = v%4;
						transition2= h%4;
					}
					else
					{
						if(diff%16==0)
						{
							transition = v$16;
							transition2= h$16;
							nucPosInCodon = 0;
						}
						else
						{
							transition = v%16$4;
							transition2= h%16$4;
							nucPosInCodon = 1;
						}
					}
					if (transition<transition2)
					{
						trSM = transition;
						trLG = transition2;
					}
					else
					{
						trSM = transition2;
						trLG = transition;
					}
					
					if (trSM==0)
					{
						if (trLG==1)
						{
							if (ModelGeneticCode[h]==ModelGeneticCode[v]) 
							{
								ModelMatrixName[h-hshift][v-vshift] := globalVariable_AC*synRate*EFV__[transition__][nucPosInCodon__];
								ModelMatrixName[v-vshift][h-hshift] := globalVariable_AC*synRate*EFV__[transition2__][nucPosInCodon__];
							}
							else
							{
								ModelMatrixName[h-hshift][v-vshift] := globalVariable_AC*nonSynRate*EFV__[transition__][nucPosInCodon__];
								ModelMatrixName[v-vshift][h-hshift] := globalVariable_AC*nonSynRate*EFV__[transition2__][nucPosInCodon__];
							}
						}
						else
						{
							if (trLG==2)
							{
								if (ModelGeneticCode[h]==ModelGeneticCode[v]) 
								{
									ModelMatrixName[h-hshift][v-vshift] := synRate*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := synRate*EFV__[transition2__][nucPosInCodon__];
								}
								else
								{
									ModelMatrixName[h-hshift][v-vshift] := nonSynRate*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := nonSynRate*EFV__[transition2__][nucPosInCodon__];									
								}							
							}
							else
							{
								if (ModelGeneticCode[h]==ModelGeneticCode[v]) 
								{
									ModelMatrixName[h-hshift][v-vshift] := globalVariable_AT*synRate*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := globalVariable_AT*synRate*EFV__[transition2__][nucPosInCodon__];
								}
								else
								{
									ModelMatrixName[h-hshift][v-vshift] := globalVariable_AT*nonSynRate*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := globalVariable_AT*nonSynRate*EFV__[transition2__][nucPosInCodon__];									
								}							
							}
						}
					}
					else
					{
						if (trSM==1)
						{
							if (trLG==2)
							{
								if (ModelGeneticCode[h]==ModelGeneticCode[v]) 
								{
									ModelMatrixName[h-hshift][v-vshift] := globalVariable_CG*synRate*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := globalVariable_CG*synRate*EFV__[transition2__][nucPosInCodon__];
								}
								else
								{
									ModelMatrixName[h-hshift][v-vshift] := globalVariable_CG*nonSynRate*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := globalVariable_CG*nonSynRate*EFV__[transition2__][nucPosInCodon__];									
								}
							}
							else
							{
								if (ModelGeneticCode[h]==ModelGeneticCode[v]) 
								{
									ModelMatrixName[h-hshift][v-vshift] := globalVariable_CT*synRate*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := globalVariable_CT*synRate*EFV__[transition2__][nucPosInCodon__];
								}
								else
								{
									ModelMatrixName[h-hshift][v-vshift] := globalVariable_CT*nonSynRate*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := globalVariable_CT*nonSynRate*EFV__[transition2__][nucPosInCodon__];
								}							
							}
						}
						else
						{
							if (ModelGeneticCode[h]==ModelGeneticCode[v]) 
							{
								ModelMatrixName[h-hshift][v-vshift] := globalVariable_GT*synRate*EFV__[transition__][nucPosInCodon__];
								ModelMatrixName[v-vshift][h-hshift] := globalVariable_GT*synRate*EFV__[transition2__][nucPosInCodon__];
							}
							else
							{
								ModelMatrixName[h-hshift][v-vshift] := globalVariable_GT*nonSynRate*EFV__[transition__][nucPosInCodon__];
								ModelMatrixName[v-vshift][h-hshift] := globalVariable_GT*nonSynRate*EFV__[transition2__][nucPosInCodon__];								
							}							
						}
					}
				}
		    }
	    }		
	}
	else
	{
		global  globalVariable_R  = 1.;
		global shapeParameter_alpha = .5;
		shapeParameter_alpha:>0.01;
		shapeParameter_alpha:<100;
		category     categoryVariable_alpha = 
					(rateClassCount, EQUAL, MEAN, GammaDist(_x_,shapeParameter_alpha,shapeParameter_alpha), CGammaDist(_x_,shapeParameter_alpha,shapeParameter_alpha), 0 , 
			  									  1e25,CGammaDist(_x_,shapeParameter_alpha+1,shapeParameter_alpha));



		global shapeParameter_beta = .5;
		shapeParameter_beta:>0.01;
		shapeParameter_beta:<100;
		
		category     categoryVariable_beta = 
					(rateClassCount, EQUAL, MEAN, GammaDist(_x_,shapeParameter_beta,shapeParameter_beta), CGammaDist(_x_,shapeParameter_beta,shapeParameter_beta), 0 , 
			  									  1e25,CGammaDist(_x_,shapeParameter_beta+1,shapeParameter_beta));



		executeMePlease = "";
		for (mi=1; mi<rateClassCount; mi=mi+1)
		{
			executeMePlease = executeMePlease + "global shapeParameter_alpha_PS_" + mi + " = 1/" +  
							  ((rateClassCount+1)-mi) + ";\nshapeParameter_alpha_PS_" + mi + ":<1;\n";
		}

		executeMePlease = executeMePlease + "\nglobal shapeParameter_alpha_RS_1=.3;shapeParameter_alpha_RS_1:<1;";

		for (mi=3; mi<=rateClassCount; mi=mi+1)
		{
			executeMePlease = executeMePlease + "global shapeParameter_alpha_RS_" + mi + " = 1.5;" + "\nshapeParameter_alpha_RS_" + mi + ":>1;\n";
		} 

		rateStrMx    = {rateClassCount,1};
		rateStrMx[0] = "shapeParameter_alpha_RS_1";
		rateStrMx[1] = "1";

		for (mi=3; mi<=rateClassCount; mi=mi+1)
		{
			rateStrMx[mi-1] = rateStrMx[mi-2]+"*shapeParameter_alpha_RS_"+mi;
		} 	

		freqStrMx    = {rateClassCount,1};
		freqStrMx[0] = "shapeParameter_alpha_PS_1";

		for (mi=1; mi<rateClassCount-1; mi=mi+1)
		{
			freqStrMx[mi] = "";
			for (mi2=1;mi2<=mi;mi2=mi2+1)
			{
				freqStrMx[mi] = freqStrMx[mi]+"(1-shapeParameter_alpha_PS_"+mi2+")";		
			}
			freqStrMx[mi] = freqStrMx[mi]+"shapeParameter_alpha_PS_"+(mi+1);	
		}	

		freqStrMx[mi] = "";
		for (mi2=1;mi2<mi;mi2=mi2+1)
		{
			freqStrMx[mi] = freqStrMx[mi]+"(1-shapeParameter_alpha_PS_"+mi2+")";		
		}
		freqStrMx[mi] = freqStrMx[mi]+"(1-shapeParameter_alpha_PS_"+mi+")";	

		executeMePlease = executeMePlease + "\n\nglobal shapeParameter_alpha_Scale:="+rateStrMx[0]+"*"+freqStrMx[0];

		for (mi=1; mi<rateClassCount; mi=mi+1)
		{
			executeMePlease = executeMePlease + "+" + rateStrMx[mi] + "*" + freqStrMx[mi];
		}


		executeMePlease = executeMePlease + ";\nshapeParameter_alpha_CFM={{" + freqStrMx[0];

		for (mi=1; mi<rateClassCount; mi=mi+1)
		{
			executeMePlease = executeMePlease + "," + freqStrMx[mi];
		}

		executeMePlease = executeMePlease + "}};\nshapeParameter_alpha_CRM={{" + rateStrMx[0] + "/shapeParameter_alpha_Scale";

		for (mi=1; mi<rateClassCount; mi=mi+1)
		{
			executeMePlease = executeMePlease +  "," + rateStrMx[mi] + "/shapeParameter_alpha_Scale";
		}

		executeMePlease = executeMePlease + "}};\n\ncategory categoryVariable_alpha   = (" + rateClassCount + ", shapeParameter_alpha_CFM , MEAN, ,shapeParameter_alpha_CRM, 0, 1e25);\n\n";

		for (mi=1; mi<rateClassCount; mi=mi+1)
		{
			executeMePlease = executeMePlease + "global shapeParameter_beta_PS_" + mi + " = 1/" +  
							  ((rateClassCount+1)-mi) + ";\nshapeParameter_beta_PS_" + mi + ":<1;\n";
		}

		executeMePlease = executeMePlease + "\nglobal shapeParameter_beta_RS_1=.3;shapeParameter_beta_RS_1:<1;";

		for (mi=3; mi<=rateClassCount; mi=mi+1)
		{
			executeMePlease = executeMePlease + "global shapeParameter_beta_RS_" + mi + " = 1.5;" + "\nshapeParameter_beta_RS_" + mi + ":>1;\n";
		} 

		rateStrMx    = {rateClassCount,1};
		rateStrMx[0] = "shapeParameter_beta_RS_1";
		rateStrMx[1] = "1";

		for (mi=3; mi<=rateClassCount; mi=mi+1)
		{
			rateStrMx[mi-1] = rateStrMx[mi-2]+"*shapeParameter_beta_RS_"+mi;
		} 	

		freqStrMx    = {rateClassCount,1};
		freqStrMx[0] = "shapeParameter_beta_PS_1";

		for (mi=1; mi<rateClassCount-1; mi=mi+1)
		{
			freqStrMx[mi] = "";
			for (mi2=1;mi2<=mi;mi2=mi2+1)
			{
				freqStrMx[mi] = freqStrMx[mi]+"(1-shapeParameter_beta_PS_"+mi2+")";		
			}
			freqStrMx[mi] = freqStrMx[mi]+"shapeParameter_beta_PS_"+(mi+1);	
		}	

		freqStrMx[mi] = "";
		for (mi2=1;mi2<mi;mi2=mi2+1)
		{
			freqStrMx[mi] = freqStrMx[mi]+"(1-shapeParameter_beta_PS_"+mi2+")";		
		}
		freqStrMx[mi] = freqStrMx[mi]+"(1-shapeParameter_beta_PS_"+mi+")";	

		executeMePlease = executeMePlease + "\n\nglobal shapeParameter_beta_Scale:="+rateStrMx[0]+"*"+freqStrMx[0];

		for (mi=1; mi<rateClassCount; mi=mi+1)
		{
			executeMePlease = executeMePlease + "+" + rateStrMx[mi] + "*" + freqStrMx[mi];
		}


		executeMePlease = executeMePlease + ";\nshapeParameter_beta_CFM={{" + freqStrMx[0];

		for (mi=1; mi<rateClassCount; mi=mi+1)
		{
			executeMePlease = executeMePlease + "," + freqStrMx[mi];
		}

		executeMePlease = executeMePlease + "}};\nshapeParameter_beta_CRM={{" + rateStrMx[0] + "/shapeParameter_beta_Scale";

		for (mi=1; mi<rateClassCount; mi=mi+1)
		{
			executeMePlease = executeMePlease +  "," + rateStrMx[mi] + "/shapeParameter_beta_Scale";
		}

		executeMePlease = executeMePlease + "}};\n\ncategory categoryVariable_beta   = (" + rateClassCount + ", shapeParameter_beta_CFM , MEAN, ,shapeParameter_beta_CRM, 0, 1e25);\n\n";
		ExecuteCommands (executeMePlease);
		executeMePlease = "";

		for (h=0; h<64; h=h+1)
		{
			if (ModelGeneticCode[h]==10) 
			{
				hshift = hshift+1;
				continue; 
			}
			vshift = hshift;
			for (v = h+1; v<64; v=v+1)
			{
				diff = v-h;
				if (ModelGeneticCode[v]==10) 
				{
					vshift = vshift+1;
					continue; 
				}
				nucPosInCodon = 2;
				if ((h$4==v$4)||((diff%4==0)&&(h$16==v$16))||(diff%16==0))
				{
					if (h$4==v$4)
					{
						transition = v%4;
						transition2= h%4;
					}
					else
					{
						if(diff%16==0)
						{
							transition = v$16;
							transition2= h$16;
							nucPosInCodon = 0;
						}
						else
						{
							transition = v%16$4;
							transition2= h%16$4;
							nucPosInCodon = 1;
						}
					}
					if (transition<transition2)
					{
						trSM = transition;
						trLG = transition2;
					}
					else
					{
						trSM = transition2;
						trLG = transition;
					}
					
					if (trSM==0)
					{
						if (trLG==1)
						{
							if (ModelGeneticCode[h]==ModelGeneticCode[v]) 
							{
								ModelMatrixName[h-hshift][v-vshift] := globalVariable_AC*synRate*categoryVariable_alpha*EFV__[transition__][nucPosInCodon__];
								ModelMatrixName[v-vshift][h-hshift] := globalVariable_AC*synRate*categoryVariable_alpha*EFV__[transition2__][nucPosInCodon__];
							}
							else
							{
								ModelMatrixName[h-hshift][v-vshift] := globalVariable_AC*globalVariable_R*synRate*categoryVariable_beta*EFV__[transition__][nucPosInCodon__];
								ModelMatrixName[v-vshift][h-hshift] := globalVariable_AC*globalVariable_R*synRate*categoryVariable_beta*EFV__[transition2__][nucPosInCodon__];
							}
						}
						else
						{
							if (trLG==2)
							{
								if (ModelGeneticCode[h]==ModelGeneticCode[v]) 
								{
									ModelMatrixName[h-hshift][v-vshift] := synRate*categoryVariable_alpha*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := synRate*categoryVariable_alpha*EFV__[transition2__][nucPosInCodon__];
								}
								else
								{
									ModelMatrixName[h-hshift][v-vshift] := globalVariable_R*synRate*categoryVariable_beta*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := globalVariable_R*synRate*categoryVariable_beta*EFV__[transition2__][nucPosInCodon__];
								}							
							}
							else
							{
								if (ModelGeneticCode[h]==ModelGeneticCode[v]) 
								{
									ModelMatrixName[h-hshift][v-vshift] := globalVariable_AT*synRate*categoryVariable_alpha*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := globalVariable_AT*synRate*categoryVariable_alpha*EFV__[transition2__][nucPosInCodon__];
								}
								else
								{
									ModelMatrixName[h-hshift][v-vshift] := globalVariable_AT*globalVariable_R*synRate*categoryVariable_beta*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := globalVariable_AT*globalVariable_R*synRate*categoryVariable_beta*EFV__[transition2__][nucPosInCodon__];
								}							
							}
						}
					}
					else
					{
						if (trSM==1)
						{
							if (trLG==2)
							{
								if (ModelGeneticCode[h]==ModelGeneticCode[v]) 
								{
									ModelMatrixName[h-hshift][v-vshift] := globalVariable_CG*synRate*categoryVariable_alpha*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := globalVariable_CG*synRate*categoryVariable_alpha*EFV__[transition2__][nucPosInCodon__];
								}
								else
								{
									ModelMatrixName[h-hshift][v-vshift] := globalVariable_CG*globalVariable_R*synRate*categoryVariable_beta*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := globalVariable_CG*globalVariable_R*synRate*categoryVariable_beta*EFV__[transition2__][nucPosInCodon__];
								}
							}
							else
							{
								if (ModelGeneticCode[h]==ModelGeneticCode[v]) 
								{
									ModelMatrixName[h-hshift][v-vshift] := globalVariable_CT*synRate*categoryVariable_alpha*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := globalVariable_CT*synRate*categoryVariable_alpha*EFV__[transition2__][nucPosInCodon__];
								}
								else
								{
									ModelMatrixName[h-hshift][v-vshift] := globalVariable_CT*globalVariable_R*synRate*categoryVariable_beta*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := globalVariable_CT*globalVariable_R*synRate*categoryVariable_beta*EFV__[transition2__][nucPosInCodon__];									
								}							
							}
						}
						else
						{
							if (ModelGeneticCode[h]==ModelGeneticCode[v]) 
							{
								ModelMatrixName[h-hshift][v-vshift] := globalVariable_GT*synRate*categoryVariable_alpha*EFV__[transition__][nucPosInCodon__];
								ModelMatrixName[v-vshift][h-hshift] := globalVariable_GT*synRate*categoryVariable_alpha*EFV__[transition2__][nucPosInCodon__];
							}
							else
							{
								ModelMatrixName[h-hshift][v-vshift] := globalVariable_GT*globalVariable_R*synRate*categoryVariable_beta*EFV__[transition__][nucPosInCodon__];
								ModelMatrixName[v-vshift][h-hshift] := globalVariable_GT*globalVariable_R*synRate*categoryVariable_beta*EFV__[transition2__][nucPosInCodon__];
							}							
						}
					}
				}
		    }
	     }	
	  }
	  return 0;
}
