[[HWE]Wright's F、3ジェノタイプ、アレル頻度 その他

Fについてはこちら
ジェノタイプ頻度とFの関係については、こちら
SNPがある。アレル頻度をp,(1-p)とする。3ジェノタイプの頻度をg1,g2,g3とする。
g1=Fp+(1-F)p^2
g2=2(1-F)p(1-p)
g3=F(1-p)+(1-F)(1-p)^2
なる関係にあり、
F=1-\frac{g2}{2p(1-p)}
である。
あるアレル頻度p,(1-p)において、Fg2=0のときに最大で1となり、HWEを満足するときに0となり、F=Min(-\frac{p}{1-p},-\frac{1-p}{p}のときに負の数をとって、最小となり、そのとき、g1,g3のいずれかが0となる。
今、同一集団において観測された、相互に独立な複数のSNPの3ジェノタイプ観測値について、共通のFが存在するものとして、その値を求めるとどうなるかについての雑なソースはこちら。

public class EstF {

	public static double THRES=0.0001;
	public static double GETA=0.0000000000001;
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
		int N=10000;
		int Nsample=100;
		double fst =0.3;
		int seed = (int)(Math.random()*100000000);
		Utils.MersenneTwisterFast mz=new Utils.MersenneTwisterFast(seed);
		int[][] d2=new int[N][3];
		for(int i=0;i<d2.length;i++){
			double ftmp = fst *(1+mz.nextGaussian());
			if(ftmp<0){
				ftmp=0;
			}else if(ftmp>1){
				ftmp=1;
			}
			double af=Math.random();
			d2[i][0]=(int)(Nsample*(ftmp*af+(1-ftmp)*af*af));
			d2[i][1]=(int)(Nsample*(2*(1-ftmp)*af*(1-af)));
			d2[i][2]=(int)(Nsample*(ftmp*(1-af)+(1-ftmp)*(1-af)*(1-af)));
		}
		int[][] d ={{10,0,10},
				{20,0,10},
				{5,5,3}
		};
		double f = EstF(d2);
		System.out.println(f);
		double[] like ={1,5,1,0,4};
		int minID=MinFive(like);
		System.out.print(minID);

	}
	public static double EstF(int[][] d){
		double ret = 0;
		
		double[][] cal=new double[d.length][5];
		double minF =-1;
		/*
		 * [0] は有効か否か
		 * [1] は合計
		 * [2] はアレル頻度1
		 * [3] はアレル頻度2
		 * [4] はF
		 * 
		 */
		for(int i=0;i<d.length;i++){
			System.out.print(d[i][0]+"\t"+d[i][1]+"\t"+d[i][2]+"\t");
			int tmpsum=d[i][0]+d[i][1]+d[i][2];
			int tmpa1 =d[i][0]*2+d[i][1];
			int tmpa2 =d[i][2]*2+d[i][1];
			System.out.print(tmpsum+"\t"+tmpa1+"\t"+tmpa2+"\t");
			
			if(tmpsum==0 || tmpa1==0 || tmpa2==0){
				
			}else{
				cal[i][0]=1;
				cal[i][1]=tmpsum;
				cal[i][2]=(double)(tmpa1)/(double)(tmpsum*2);
				cal[i][3]=1-cal[i][2];
				double tmpMinF =-cal[i][3]/cal[i][2];
				if(cal[i][2]<cal[i][3]){
					tmpMinF=-cal[i][2]/cal[i][3];
				}
				cal[i][4]=1-d[i][1]/(2*cal[i][2]*cal[i][3]*cal[i][1]);
				System.out.print(cal[i][0]+"\t"+cal[i][1]+"\t"+cal[i][2]+"\t"+cal[i][3]+"\t"+cal[i][4]+"\t"+tmpMinF+"\n");
				
				if(tmpMinF>minF){
					minF=tmpMinF;
				}
				
			}
		}
		//ret =minF;
		minF+=GETA;
		double[] five={minF,0,(minF+1)/2,0,1};
		five[1]=(five[0]+five[2])/2;
		five[3]=(five[2]+five[4])/2;
		
		double[] like = new double[5];
		for(int i=0;i<like.length;i++){
			like[i]=Like(d,cal,five[i]);
		}
		
		while(five[4]-five[0]>THRES){
			Renew(d,cal,five,like);
			System.out.println(five[0]+"\t"+five[1]+"\t"+five[2]+"\t"+five[3]+"\t"+five[4]);
			System.out.println(like[0]+"\t"+like[1]+"\t"+like[2]+"\t"+like[3]+"\t"+like[4]);
		}
		
		return five[2];
	}
	
	public static double Like(int[][] d,double[][] cal,double f){
		double ret = 0;
		for(int i=0;i<cal.length;i++){
			if(cal[i][0]==1){
				double[] genfreq={
						Math.log(f*cal[i][2]+(1-f)*cal[i][2]*cal[i][2]),
						Math.log(2*(1-f)*cal[i][2]*cal[i][3]),
						Math.log(f*cal[i][3]+(1-f)*cal[i][3]*cal[i][3])
				};
				ret +=d[i][0]*genfreq[0]+d[i][1]*genfreq[1]+d[i][2]*genfreq[2];
			}
		}
		
		return ret;
	}
	
	public static void Renew(int[][] d, double[][] cal, double[] f,double[] like){
		int minID=MaxFive(like);
		if(minID==0){
			f[4]=f[2];
			f[2]=f[1];
			f[1]=(f[0]+f[2])/2;
			f[3]=(f[2]+f[4])/2;
			like[4]=like[2];
			like[2]=like[1];
			like[1]=Like(d,cal,f[1]);
			like[3]=Like(d,cal,f[3]);
		}else if(minID==1){
			f[4]=f[2];
			f[2]=f[1];
			f[1]=(f[0]+f[2])/2;
			f[3]=(f[2]+f[4])/2;
			like[4]=like[2];
			like[2]=like[1];
			like[1]=Like(d,cal,f[1]);
			like[3]=Like(d,cal,f[3]);
		}else if(minID==2){
			f[0]=f[1];
			f[4]=f[3];
			f[1]=(f[0]+f[2])/2;
			f[3]=(f[2]+f[4])/2;
			like[4]=like[3];
			like[0]=like[1];
			like[1]=Like(d,cal,f[1]);
			like[3]=Like(d,cal,f[3]);
		}else if(minID==3){
			f[0]=f[2];
			f[2]=f[3];
			f[1]=(f[0]+f[2])/2;
			f[3]=(f[2]+f[4])/2;
			like[2]=like[3];
			like[0]=like[2];
			like[1]=Like(d,cal,f[1]);
			like[3]=Like(d,cal,f[3]);
		}else if(minID==4){
			f[0]=f[2];
			f[2]=f[3];
			f[1]=(f[0]+f[2])/2;
			f[3]=(f[2]+f[4])/2;
			like[2]=like[3];
			like[0]=like[2];
			like[1]=Like(d,cal,f[1]);
			like[3]=Like(d,cal,f[3]);
		}
	}
	
	public static int MinFive(double[] like){
		
		int minID=5;
		if(like[1]<like[0]){
			if(like[2]<like[1]){
				if(like[3]<like[2]){
					if(like[4]<like[3]){
						minID=4;
					}else{
						minID=3;
					}
				}else{
					if(like[4]<like[2]){
						minID=4;
					}else{
						minID=2;
					}
				}
			}else{
				if(like[3]<like[1]){
					if(like[4]<like[3]){
						minID=4;
					}else{
						minID=3;
					}
				}else{
					if(like[4]<like[1]){
						minID=4;
					}else{
						minID=1;
					}
				}
			}
		}else{
			if(like[2]<like[0]){
				if(like[3]<like[2]){
					if(like[4]<like[3]){
						minID=4;
					}else{
						minID=3;
					}
				}else{
					if(like[4]<like[2]){
						minID=4;
					}else{
						minID=2;
					}
				}
			}else{
				if(like[3]<like[0]){
					if(like[4]<like[3]){
						minID=4;
					}else{
						minID=3;
					}
				}else{
					if(like[4]<like[0]){
						minID=4;
					}else{
						minID=0;
					}
				}
			}
		}
		return minID;
	}
	public static int MaxFive(double[] like){
		
		int minID=5;
		if(like[1]>like[0]){
			if(like[2]>like[1]){
				if(like[3]>like[2]){
					if(like[4]>like[3]){
						minID=4;
					}else{
						minID=3;
					}
				}else{
					if(like[4]>like[2]){
						minID=4;
					}else{
						minID=2;
					}
				}
			}else{
				if(like[3]>like[1]){
					if(like[4]>like[3]){
						minID=4;
					}else{
						minID=3;
					}
				}else{
					if(like[4]>like[1]){
						minID=4;
					}else{
						minID=1;
					}
				}
			}
		}else{
			if(like[2]>like[0]){
				if(like[3]>like[2]){
					if(like[4]>like[3]){
						minID=4;
					}else{
						minID=3;
					}
				}else{
					if(like[4]>like[2]){
						minID=4;
					}else{
						minID=2;
					}
				}
			}else{
				if(like[3]>like[0]){
					if(like[4]>like[3]){
						minID=4;
					}else{
						minID=3;
					}
				}else{
					if(like[4]>like[0]){
						minID=4;
					}else{
						minID=0;
					}
				}
			}
		}
		return minID;
	}

}