@@ -167,6 +167,41 @@ def ibdlen(fpath: str, gmap: GeneticMap) -> Tuple[int, float]:
167167 return breakpoints , total
168168
169169
170+ def compute_likelihood_ratio (obs_rates : np .ndarray , ncase : int , ncontrol : int ) -> np .ndarray :
171+ """Compute per-breakpoint likelihood ratios for the localization test.
172+
173+ Args:
174+ obs_rates: Observed rates for the breakpoint, with case-case and case-control
175+ rates stored in the first two columns.
176+ ncase: Number of cases in the phenotype.
177+ ncontrol: Number of controls in the phenotype.
178+
179+ Returns:
180+ An array of likelihood ratios corresponding to the supplied breakpoints.
181+ """
182+
183+ cscs = ncase * (ncase - 1.0 ) / 2.0
184+ cscn = ncase * ncontrol
185+
186+ obs_counts = obs_rates [:, 0 :2 ].copy ()
187+ obs_counts [:, 0 ] *= cscs
188+ obs_counts [:, 1 ] *= cscn
189+ obs_counts = np .rint (obs_counts ).astype (np .int64 )
190+
191+ weights = np .array ([cscs / (cscs + cscn ), cscn / (cscs + cscn )], dtype = np .float64 )
192+ total_counts = np .sum (obs_counts * weights , axis = 1 )
193+
194+ llik_ratio = np .zeros (obs_counts .shape [0 ], dtype = np .float64 )
195+ for idx in range (obs_counts .shape [0 ]):
196+ null = stats .poisson .logpmf (obs_counts [idx , 0 ], weights [0 ] * total_counts [idx ])
197+ null += stats .poisson .logpmf (obs_counts [idx , 1 ], weights [1 ] * total_counts [idx ])
198+ alt = stats .poisson .logpmf (obs_counts [idx , 0 ], obs_counts [idx , 0 ])
199+ alt += stats .poisson .logpmf (obs_counts [idx , 1 ], obs_counts [idx , 1 ])
200+ llik_ratio [idx ] = - 2 * (null - alt )
201+
202+ return llik_ratio
203+
204+
170205def parse_pheno (ifile : str , phenotype : Optional [str ] = None ) -> Tuple [int , int ]:
171206 """
172207
@@ -332,29 +367,7 @@ def main():
332367 if args .lrt :
333368 ncase , ncontrol = parse_pheno (args .lrt , args .phenotype_name )
334369
335- cscs = ncase * (ncase - 1. ) / 2.
336- cscn = ncase * ncontrol
337-
338- obs_counts = obs_rates [:, 0 :2 ]
339-
340- obs_counts [:, 0 ] *= cscs
341- obs_counts [:, 1 ] *= cscn
342- obs_counts = obs_counts .astype (np .int64 )
343-
344- weights = np .array ([cscs / (cscs + cscn ), cscn / (cscs + cscn )])
345-
346- total_counts = np .sum (obs_counts * weights , 1 )
347- total_counts = total_counts .astype (np .int64 )
348- mean_rates = np .sum (obs_rates [:, 0 :2 ] * weights , 1 )
349-
350- for i in range (len (mean_rates )):
351- # Null is Pois(obs_cscs, Expected_counts[cscs]) * Pois(obs_cscn, Expected_counts[cscn])
352- null = stats .poisson .logpmf (obs_counts [i , 0 ], weights [0 ] * total_counts [i ])
353- null += stats .poisson .logpmf (obs_counts [i , 1 ], weights [1 ] * total_counts [i ])
354- alt = stats .poisson .logpmf (obs_counts [i , 0 ], obs_counts [i , 0 ])
355- alt += stats .poisson .logpmf (obs_counts [i , 1 ], obs_counts [i , 1 ])
356-
357- llik_ratio [i ] = - 2 * (null - alt )
370+ llik_ratio = compute_likelihood_ratio (obs_rates , ncase , ncontrol )
358371
359372 def subtract (a ):
360373 return a - avgs
0 commit comments