1
+ #include < cassert>
2
+ #include < cmath>
3
+ #include < cstdint>
4
+ #include < limits>
5
+
1
6
#include < graphtyper/utilities/logging.hpp>
2
7
#include < graphtyper/utilities/snp_hwe.hpp>
3
8
@@ -28,6 +33,9 @@ double p_hwe_excess_het(int obs_hets, int obs_hom1, int obs_hom2)
28
33
exit (EXIT_FAILURE);
29
34
}
30
35
36
+ if (obs_hets == 0 && (obs_hom1 == 0 || obs_hom2 == 0 ))
37
+ return 1.0 ;
38
+
31
39
int obs_homc = obs_hom1 < obs_hom2 ? obs_hom2 : obs_hom1;
32
40
int obs_homr = obs_hom1 < obs_hom2 ? obs_hom1 : obs_hom2;
33
41
@@ -37,7 +45,11 @@ double p_hwe_excess_het(int obs_hets, int obs_hom1, int obs_hom2)
37
45
std::vector<double > het_probs (rare_copies + 1 , 0.0 );
38
46
39
47
// start at midpoint
40
- int mid = rare_copies * (2 * genotypes - rare_copies) / (2 * genotypes);
48
+ double mid_double = static_cast <double >(rare_copies) * static_cast <double >(2 * genotypes - rare_copies) /
49
+ static_cast <double >(2 * genotypes);
50
+
51
+ assert (mid_double < static_cast <double >(std::numeric_limits<int >::max ()));
52
+ int mid = std::lround (mid_double);
41
53
42
54
// check to ensure that midpoint and rare alleles have same parity
43
55
if ((rare_copies & 1 ) ^ (mid & 1 ))
@@ -47,11 +59,15 @@ double p_hwe_excess_het(int obs_hets, int obs_hom1, int obs_hom2)
47
59
int curr_homr = (rare_copies - mid) / 2 ;
48
60
int curr_homc = genotypes - curr_hets - curr_homr;
49
61
62
+ assert (mid < static_cast <int >(het_probs.size ()));
50
63
het_probs[mid] = 1.0 ;
51
64
double sum = het_probs[mid];
52
65
53
66
for (/* curr_hets = mid*/ ; curr_hets > 1 ; curr_hets -= 2 )
54
67
{
68
+ assert (curr_hets < static_cast <int >(het_probs.size ()));
69
+ assert (curr_hets > 1 );
70
+
55
71
het_probs[curr_hets - 2 ] =
56
72
het_probs[curr_hets] * curr_hets * (curr_hets - 1.0 ) / (4.0 * (curr_homr + 1.0 ) * (curr_homc + 1.0 ));
57
73
@@ -68,8 +84,12 @@ double p_hwe_excess_het(int obs_hets, int obs_hom1, int obs_hom2)
68
84
69
85
for (curr_hets = mid; curr_hets <= rare_copies - 2 ; curr_hets += 2 )
70
86
{
87
+ assert (curr_hets < static_cast <int >(het_probs.size ()));
88
+ assert ((curr_hets + 2 ) < static_cast <int >(het_probs.size ()));
89
+
71
90
het_probs[curr_hets + 2 ] =
72
91
het_probs[curr_hets] * 4.0 * curr_homr * curr_homc / ((curr_hets + 2.0 ) * (curr_hets + 1.0 ));
92
+
73
93
sum += het_probs[curr_hets + 2 ];
74
94
75
95
// add 2 heterozygotes for next iteration -> subtract one rare, one common homozygote
@@ -81,9 +101,10 @@ double p_hwe_excess_het(int obs_hets, int obs_hom1, int obs_hom2)
81
101
het_probs[i] /= sum;
82
102
83
103
// alternate p-value calculation for p_hi
84
- double p_hi = het_probs[obs_hets];
104
+ assert (obs_hets < static_cast <int >(het_probs.size ()));
105
+ double p_hi = 0.0 ;
85
106
86
- for (int i = obs_hets + 1 ; i <= rare_copies; i++)
107
+ for (int i = obs_hets; i <= rare_copies; i++)
87
108
p_hi += het_probs[i];
88
109
89
110
return p_hi > 1.0 ? 1.0 : p_hi;
0 commit comments