Model_Name  		= "MGxHKYxF34xGDDxMRV";
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_TVTS = 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 (ModelGeneticCode[0][h]==ModelGeneticCode[0][v]) 
			  		{
			  			if ((Abs(transition-transition2)%2)==1)
			  			{
			  				ModelMatrixName[h-hshift][v-vshift] := globalVariable_TVTS*synRate*EFV__[transition__][nucPosInCodon__];
			  				ModelMatrixName[v-vshift][h-hshift] := globalVariable_TVTS*synRate*EFV__[transition2__][nucPosInCodon__];
			  			
			  			}
			  			else
			  			{
			  				ModelMatrixName[h-hshift][v-vshift] := synRate*EFV__[transition__][nucPosInCodon__];
			  				ModelMatrixName[v-vshift][h-hshift] := synRate*EFV__[transition2__][nucPosInCodon__];
			  			}
				  	}
			  		else
			  		{
			  			if ((Abs(transition-transition2)%2)==1)
			  			{
			  				ModelMatrixName[h-hshift][v-vshift] := globalVariable_TVTS*nonSynRate*EFV__[transition__][nucPosInCodon__];
			  				ModelMatrixName[v-vshift][h-hshift] := globalVariable_TVTS*nonSynRate*EFV__[transition2__][nucPosInCodon__];
			  			
			  			}
			  			else
			  			{
			  				ModelMatrixName[h-hshift][v-vshift] := nonSynRate*EFV__[transition__][nucPosInCodon__];
			  				ModelMatrixName[v-vshift][h-hshift] := nonSynRate*EFV__[transition2__][nucPosInCodon__];
			  			}
				  	}
			  	}
			}
		}
	}
	else
	{
		gdDefString = "";
		gdDefString * 1024;
		for (mi=1; mi<rateClassCount; mi=mi+1)
		{
			gdDefString*("global shapeParameter_PS_"+mi+" = 1/"+((rateClassCount+1)-mi)+";\nshapeParameter_PS_"+mi+":<1;\n");
		}
		
		gdDefString*("\n\nglobal shapeParameter_RS_1 = .3;\nshapeParameter_RS_1:<1;shapeParameter_RS_1:>0.000000001;\n");

		for (mi=3; mi<=rateClassCount; mi=mi+1)
		{
			gdDefString*("global shapeParameter_RS_"+mi+" = 1.5;"+"\nshapeParameter_RS_"+mi+":>1;shapeParameter_RS_"+mi+":<100000;\n");
		} 

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

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

		freqStrMx    = {rateClassCount,1};
		freqStrMx[0] = "shapeParameter_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_PS_"+mi2+")";		
			}
			freqStrMx[mi] = freqStrMx[mi]+"shapeParameter_PS_"+(mi+1);	
		}	

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


		gdDefString*("\n\nglobal shapeParameter_scale:="+rateStrMx[0]+"*"+freqStrMx[0]);

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

		gdDefString*(";\nshapeParameter_categFreqMatrix={{"+freqStrMx[0]);

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

		gdDefString*("}};\nshapeParameter_categRateMatrix={{"+rateStrMx[0]+"/shapeParameter_scale");

		for (mi=1; mi<rateClassCount; mi=mi+1)
		{
			gdDefString*(","+rateStrMx[mi]+"/shapeParameter_scale");
		}

		gdDefString*("}};\n\ncategory categoryVariable  = ("+rateClassCount+", shapeParameter_categFreqMatrix , MEAN, ,shapeParameter_categRateMatrix, 0, 1e25);\n\n");
		gdDefString*0;
		ExecuteCommands (gdDefString);

		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 (ModelGeneticCode[h]==ModelGeneticCode[v]) 
			  		{
			  			if ((Abs(transition-transition2)%2)==1)
			  			{
			  				ModelMatrixName[h-hshift][v-vshift] := categoryVariable*globalVariable_TVTS*synRate*EFV__[transition__][nucPosInCodon__];
			  				ModelMatrixName[v-vshift][h-hshift] := categoryVariable*globalVariable_TVTS*synRate*EFV__[transition2__][nucPosInCodon__];
			  			
			  			}
			  			else
			  			{
			  				ModelMatrixName[h-hshift][v-vshift] := categoryVariable*synRate*EFV__[transition__][nucPosInCodon__];
			  				ModelMatrixName[v-vshift][h-hshift] := categoryVariable*synRate*EFV__[transition2__][nucPosInCodon__];
			  			}
				  	}
			  		else
			  		{
			  			if ((Abs(transition-transition2)%2)==1)
			  			{
			  				ModelMatrixName[h-hshift][v-vshift] := categoryVariable*globalVariable_TVTS*nonSynRate*EFV__[transition__][nucPosInCodon__];
			  				ModelMatrixName[v-vshift][h-hshift] := categoryVariable*globalVariable_TVTS*nonSynRate*EFV__[transition2__][nucPosInCodon__];
			  			
			  			}
			  			else
			  			{
			  				ModelMatrixName[h-hshift][v-vshift] := categoryVariable*nonSynRate*EFV__[transition__][nucPosInCodon__];
			  				ModelMatrixName[v-vshift][h-hshift] := categoryVariable*nonSynRate*EFV__[transition2__][nucPosInCodon__];
			  			}
				  	}
			  	}
			 }
		}		
	}	
	return 0;
}
