HWEの正確検定
わけあって、J.E. Wigginton, G.R. AbecasisらによるHWE正確検定をJava化する必要が出た。このソースは、著者らにより、C/C++,R,Fortranにて公開されている。
N人、2N本染色体、アレル(A/B)、,,、,、と表すこととすると、
,と表せる。
また、2N本のアレルの分け方は全部でであり、N人の3ジェノタイプへの分け方は全部である。
今、ヘテロの人数について、その2アレルの取り方はそれぞれ2通りあるので、N人について、本のAアレルを観測したときに、人のヘテロを観測する確率は
が奇数のときは、も奇数で、は奇数。が偶数である確率は0。逆に、が偶数のときは、も偶数で、も偶数。が奇数となる確率は0となることに留意する。
public class Fisher {
public static double hweFisherAbecasis(int[] da){
int sum = da[0]+da[1] +da[2];
int allele = da[0]*2 +da[1];
double p = (double)allele/((double)sum*2);
double[] genp = new double[3];
genp[0] = p*p;
genp[1] = 2*p*(1-p);
genp[2] = (1-p)*(1-p);
//System.out.println("sum " + sum);
//System.out.println("allele " + allele);
//System.out.println("p " + p);
//System.out.println("genp " + genp[0] + " " + genp[1] + " " + genp[2]);
double exp0 = genp[0] *sum;
//System.out.println("exp0 " + exp0);
boolean less = true;
if(da[0]>exp0){
less = false;
}
double ret =0 ;
double total = 0;
double combin0 = (logfact(sum)+logfact(allele)+logfact(sum*2-allele))
-(logfact(da[0]) + logfact(da[1]) + logfact(da[2]) +logfact(sum*2));
double P0=Math.exp(combin0 + da[1] * Math.log(2) );
//System.out.println("P0 " + P0);
for(int i=0;i<=sum;i++){
int hetero = allele-i*2;
if(hetero<0){
continue;
}
int neghomo = sum-i-hetero;
if(neghomo<0){
continue;
}
//System.out.println("i hetero neghomo " + i + " " + hetero + " " + neghomo);
double combin = (logfact(sum)+logfact(allele)+logfact(sum*2-allele))
-(logfact(i) + logfact(hetero) + logfact(neghomo) +logfact(sum*2));
//System.out.println("combin "+ combin);
double P1 = Math.exp(combin + hetero * Math.log(2) );
if(P0>=P1){
ret += P1;
}
/*
if(less){
if(i<=da[0]){
ret += Math.exp(combin + hetero * Math.log(2) );
total += Math.exp(combin + hetero * Math.log(2) );
}else if(i<=exp0){
total += Math.exp(combin + hetero * Math.log(2) );
}else{
//break;
}
}
if(!less){
if(i>=da[0]){
ret += Math.exp(combin + hetero * Math.log(2) );
total += Math.exp(combin + hetero * Math.log(2) );
}else if(i>=exp0){
total += Math.exp(combin + hetero * Math.log(2) );
}else{
//break;
}
}
*/
//total += Math.exp(combin + i * Math.log(genp[0]) + hetero * Math.log(genp[1]) + neghomo * Math.log(genp[2]));
}
//System.out.println("ret total "+ ret + " " + total);
//ret /= total;
//ret = Math.exp(ret);
return ret;
}
public static double logfact(int a){
double ret =0;
for(int i=1;i<=a;i++){
ret += Math.log(i);
}
return ret;
}
public static double logP(int[] da){
double ret = 0;
double num = logPnumerator(da);
double denom = logPdenominator(da);
ret = num-denom;
return ret;
}
public static double P(int[] da){
double ret =0;
double logP = logP(da);
ret = Math.exp(logP);
return ret;
}
public static double logPdenominator(int[] da){
double ret =0;
for(int i=0;i<da.length;i++){
ret += logfact(da[i]);
}
return ret;
}
public static double logPnumerator(int[] da){
double ret = 0;
int e = da[0] + da[1];
int f = da[2] + da[3];
int g = da[0] + da[2];
int h = da[1] + da[3];
int n = e + f;
ret = logfact(e)+logfact(f)+logfact(g)+logfact(h)-logfact(n);
return ret;
}
}