Model_Name  		= "MG94xREV_3x4";
Model_Options 		= 3;
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;
	global globalVariable_AT;
	global globalVariable_CG;
	global globalVariable_CT;
	global globalVariable_GT;
	global globalVariable_R;

	
	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 < 2)
	{
		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
							{
								if (modelType)
								{
									ModelMatrixName[h-hshift][v-vshift] := globalVariable_AC*globalVariable_R*synRate*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := globalVariable_AC*globalVariable_R*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
								{
									if (modelType)
									{
										ModelMatrixName[h-hshift][v-vshift] := globalVariable_R*synRate*EFV__[transition__][nucPosInCodon__];
										ModelMatrixName[v-vshift][h-hshift] := globalVariable_R*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
								{
									if (modelType)
									{
										ModelMatrixName[h-hshift][v-vshift] := globalVariable_AT*globalVariable_R*synRate*EFV__[transition__][nucPosInCodon__];
										ModelMatrixName[v-vshift][h-hshift] := globalVariable_AT*globalVariable_R*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
								{
									if (modelType)
									{
										ModelMatrixName[h-hshift][v-vshift] := globalVariable_CG*globalVariable_R*synRate*EFV__[transition__][nucPosInCodon__];
										ModelMatrixName[v-vshift][h-hshift] := globalVariable_CG*globalVariable_R*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
								{
									if (modelType)
									{
										ModelMatrixName[h-hshift][v-vshift] := globalVariable_CT*globalVariable_R*synRate*EFV__[transition__][nucPosInCodon__];
										ModelMatrixName[v-vshift][h-hshift] := globalVariable_CT*globalVariable_R*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
							{
								if (modelType)
								{
									ModelMatrixName[h-hshift][v-vshift] := globalVariable_GT*globalVariable_R*synRate*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := globalVariable_GT*globalVariable_R*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 shapeParameter_betaP = 1;
		global shapeParameter_betaQ = 1;
		shapeParameter_betaP:>0.05;shapeParameter_betaP:<85;
		shapeParameter_betaQ:>0.05;shapeParameter_betaQ:<85;
		category categoryVariable_Beta = (rateClassCount-1, EQUAL, MEAN, 
						_x_^(shapeParameter_betaP-1)*(1-_x_)^(shapeParameter_betaQ-1)/Beta(shapeParameter_betaP,shapeParameter_betaQ), /* density */
						IBeta(_x_,shapeParameter_betaP,shapeParameter_betaQ), /*CDF*/
						0, 				   /*left bound*/
						1, 			   /*right bound*/
						IBeta(_x_,shapeParameter_betaP+1,shapeParameter_betaQ)*shapeParameter_betaP/(shapeParameter_betaP+shapeParameter_betaQ)
		);

		global shapeParameter = .5;
		shapeParameter:>0.01;
		shapeParameter:<100;
		category     categoryVariable = 
					(rateClassCount, categoryVariable_Beta, MEAN, GammaDist(_x_,shapeParameter,shapeParameter), CGammaDist(_x_,shapeParameter,shapeParameter), 0 , 
			  									  1e25,CGammaDist(_x_,shapeParameter+1,shapeParameter));

		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] := categoryVariable*globalVariable_AC*synRate*EFV__[transition__][nucPosInCodon__];
								ModelMatrixName[v-vshift][h-hshift] := categoryVariable*globalVariable_AC*synRate*EFV__[transition2__][nucPosInCodon__];
							}
							else
							{
								ModelMatrixName[h-hshift][v-vshift] := categoryVariable*globalVariable_AC*globalVariable_R*synRate*EFV__[transition__][nucPosInCodon__];
								ModelMatrixName[v-vshift][h-hshift] := categoryVariable*globalVariable_AC*globalVariable_R*synRate*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] := categoryVariable*globalVariable_R*synRate*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := categoryVariable*globalVariable_R*synRate*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] := categoryVariable*globalVariable_AT*globalVariable_R*synRate*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := categoryVariable*globalVariable_AT*globalVariable_R*synRate*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] := categoryVariable*globalVariable_CG*globalVariable_R*synRate*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := categoryVariable*globalVariable_CG*globalVariable_R*synRate*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] := categoryVariable*globalVariable_CT*globalVariable_R*synRate*EFV__[transition__][nucPosInCodon__];
									ModelMatrixName[v-vshift][h-hshift] := categoryVariable*globalVariable_CT*globalVariable_R*synRate*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] := categoryVariable*globalVariable_GT*globalVariable_R*synRate*EFV__[transition__][nucPosInCodon__];
								ModelMatrixName[v-vshift][h-hshift] := categoryVariable*globalVariable_GT*globalVariable_R*synRate*EFV__[transition2__][nucPosInCodon__];
							}							
						}
					}
				}
		    }
	    }	
	}
	
	return 0;
}
