strkit 0.11.8__tar.gz → 0.12.0a1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {strkit-0.11.8/strkit.egg-info → strkit-0.12.0a1}/PKG-INFO +1 -1
- strkit-0.12.0a1/strkit/VERSION +1 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/constants.py +0 -13
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/entry.py +4 -7
- strkit-0.12.0a1/strkit/mi/repeathmm.py +92 -0
- strkit-0.12.0a1/strkit/mi/straglr.py +98 -0
- strkit-0.12.0a1/strkit/mi/tandem_genotypes.py +88 -0
- {strkit-0.11.8 → strkit-0.12.0a1/strkit.egg-info}/PKG-INFO +1 -1
- strkit-0.11.8/strkit/VERSION +0 -1
- strkit-0.11.8/strkit/mi/repeathmm.py +0 -192
- strkit-0.11.8/strkit/mi/straglr.py +0 -201
- strkit-0.11.8/strkit/mi/tandem_genotypes.py +0 -172
- {strkit-0.11.8 → strkit-0.12.0a1}/LICENSE +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/MANIFEST.in +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/README.md +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/pyproject.toml +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/setup.cfg +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/setup.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/__init__.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/call/__init__.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/call/align_matrix.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/call/allele.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/call/call_locus.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/call/call_sample.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/call/cigar.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/call/non_daemonic_pool.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/call/realign.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/call/repeats.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/call/snvs.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/call/types.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/call/utils.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/catalog/__init__.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/catalog/combine.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/convert/__init__.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/convert/_bed_4.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/convert/converter.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/convert/expansionhunter.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/convert/gangstr.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/convert/hipstr.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/convert/straglr.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/convert/tandem_genotypes.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/exceptions.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/json.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/logger.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/mi/__init__.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/mi/base.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/mi/expansionhunter.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/mi/gangstr.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/mi/result.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/mi/strkit.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/mi/vcf_utils.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/utils.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/viz/__init__.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/viz/server.py +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/viz/static/logo.png +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit/viz/templates/browser.html +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit.egg-info/SOURCES.txt +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit.egg-info/dependency_links.txt +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit.egg-info/entry_points.txt +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit.egg-info/requires.txt +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/strkit.egg-info/top_level.txt +0 -0
- {strkit-0.11.8 → strkit-0.12.0a1}/tests/test_caller_utils.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.12.0a1
|
|
@@ -3,11 +3,8 @@ __all__ = [
|
|
|
3
3
|
"CALLER_HIPSTR",
|
|
4
4
|
"CALLER_GANGSTR",
|
|
5
5
|
"CALLER_REPEATHMM",
|
|
6
|
-
"CALLER_REPEATHMM_RECALL",
|
|
7
6
|
"CALLER_STRAGLR",
|
|
8
|
-
"CALLER_STRAGLR_RECALL",
|
|
9
7
|
"CALLER_TANDEM_GENOTYPES",
|
|
10
|
-
"CALLER_TANDEM_GENOTYPES_RECALL",
|
|
11
8
|
"CALL_SUPPORTED_CALLERS",
|
|
12
9
|
|
|
13
10
|
"M_CHROMOSOME_NAMES",
|
|
@@ -24,13 +21,10 @@ CALLER_EXPANSIONHUNTER = "expansionhunter"
|
|
|
24
21
|
CALLER_HIPSTR = "hipstr"
|
|
25
22
|
CALLER_GANGSTR = "gangstr"
|
|
26
23
|
CALLER_REPEATHMM = "repeathmm"
|
|
27
|
-
CALLER_REPEATHMM_RECALL = "repeathmm-recall"
|
|
28
24
|
CALLER_STRAGLR = "straglr"
|
|
29
|
-
CALLER_STRAGLR_RECALL = "straglr-recall"
|
|
30
25
|
CALLER_STRKIT = "strkit"
|
|
31
26
|
CALLER_STRKIT_JSON = "strkit-json"
|
|
32
27
|
CALLER_TANDEM_GENOTYPES = "tandem-genotypes"
|
|
33
|
-
CALLER_TANDEM_GENOTYPES_RECALL = "tandem-genotypes-recall"
|
|
34
28
|
|
|
35
29
|
CALL_SUPPORTED_CALLERS = (
|
|
36
30
|
CALLER_REPEATHMM,
|
|
@@ -57,16 +51,9 @@ CHROMOSOMES = (
|
|
|
57
51
|
MI_CALLERS = (
|
|
58
52
|
CALLER_EXPANSIONHUNTER,
|
|
59
53
|
CALLER_GANGSTR,
|
|
60
|
-
"generic-vcf",
|
|
61
|
-
"hipstr",
|
|
62
|
-
"lobstr",
|
|
63
|
-
"pacmonstr",
|
|
64
54
|
CALLER_REPEATHMM,
|
|
65
|
-
CALLER_REPEATHMM_RECALL,
|
|
66
55
|
CALLER_STRAGLR,
|
|
67
|
-
CALLER_STRAGLR_RECALL,
|
|
68
56
|
CALLER_STRKIT,
|
|
69
57
|
CALLER_STRKIT_JSON,
|
|
70
58
|
CALLER_TANDEM_GENOTYPES,
|
|
71
|
-
CALLER_TANDEM_GENOTYPES_RECALL,
|
|
72
59
|
)
|
|
@@ -364,28 +364,25 @@ def _exec_mi(p_args) -> None:
|
|
|
364
364
|
from strkit.mi.base import BaseCalculator
|
|
365
365
|
from strkit.mi.expansionhunter import ExpansionHunterCalculator
|
|
366
366
|
from strkit.mi.gangstr import GangSTRCalculator
|
|
367
|
-
from strkit.mi.repeathmm import RepeatHMMCalculator
|
|
368
|
-
from strkit.mi.straglr import StraglrCalculator
|
|
367
|
+
from strkit.mi.repeathmm import RepeatHMMCalculator
|
|
368
|
+
from strkit.mi.straglr import StraglrCalculator
|
|
369
369
|
from strkit.mi.strkit import StrKitCalculator, StrKitJSONCalculator
|
|
370
|
-
from strkit.mi.tandem_genotypes import TandemGenotypesCalculator
|
|
370
|
+
from strkit.mi.tandem_genotypes import TandemGenotypesCalculator
|
|
371
371
|
|
|
372
372
|
calc_classes: dict[str, Type[BaseCalculator]] = {
|
|
373
373
|
c.CALLER_EXPANSIONHUNTER: ExpansionHunterCalculator,
|
|
374
374
|
c.CALLER_GANGSTR: GangSTRCalculator,
|
|
375
375
|
c.CALLER_REPEATHMM: RepeatHMMCalculator,
|
|
376
|
-
c.CALLER_REPEATHMM_RECALL: RepeatHMMReCallCalculator,
|
|
377
376
|
c.CALLER_STRAGLR: StraglrCalculator,
|
|
378
|
-
c.CALLER_STRAGLR_RECALL: StraglrReCallCalculator,
|
|
379
377
|
c.CALLER_STRKIT: StrKitCalculator,
|
|
380
378
|
c.CALLER_STRKIT_JSON: StrKitJSONCalculator,
|
|
381
379
|
c.CALLER_TANDEM_GENOTYPES: TandemGenotypesCalculator,
|
|
382
|
-
c.CALLER_TANDEM_GENOTYPES_RECALL: TandemGenotypesReCallCalculator,
|
|
383
380
|
}
|
|
384
381
|
|
|
385
382
|
caller = p_args.caller.lower()
|
|
386
383
|
|
|
387
384
|
trf_bed_file = getattr(p_args, "trf_bed") or None
|
|
388
|
-
if trf_bed_file is None and caller
|
|
385
|
+
if trf_bed_file is None and caller == c.CALLER_STRAGLR:
|
|
389
386
|
raise ParamError("Using `strkit mi` with Straglr requires that the --trf-bed flag is used.")
|
|
390
387
|
|
|
391
388
|
exclude_bed_file = p_args.exclude_loci_bed or None
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .base import BaseCalculator
|
|
4
|
+
from .result import MIContigResult, MILocusData
|
|
5
|
+
from ..utils import int_tuple
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"RepeatHMMCalculator",
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class RepeatHMMCalculator(BaseCalculator):
|
|
13
|
+
@staticmethod
|
|
14
|
+
def get_contigs_from_fh(fh) -> set:
|
|
15
|
+
return {ls[0] for ls in (line.split(":") for line in fh)}
|
|
16
|
+
|
|
17
|
+
@staticmethod
|
|
18
|
+
def make_calls_dict(ph, contig):
|
|
19
|
+
return {
|
|
20
|
+
tuple(k.split(":")): int_tuple(v.split("/"))
|
|
21
|
+
for k, v in (pv.split() for pv in ph)
|
|
22
|
+
if k.split(":")[0] == contig
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
def _get_sample_contigs(self, include_sex_chromosomes: bool = False) -> tuple[set, set, set]:
|
|
26
|
+
with open(self._mother_call_file, "r") as mvf, open(self._father_call_file, "r") as fvf, \
|
|
27
|
+
open(self._child_call_file, "r") as cvf:
|
|
28
|
+
|
|
29
|
+
mc = self.get_contigs_from_fh(mvf)
|
|
30
|
+
fc = self.get_contigs_from_fh(fvf)
|
|
31
|
+
cc = self.get_contigs_from_fh(cvf)
|
|
32
|
+
|
|
33
|
+
return mc, fc, cc
|
|
34
|
+
|
|
35
|
+
def calculate_contig(self, contig: str) -> MIContigResult:
|
|
36
|
+
cr = MIContigResult()
|
|
37
|
+
|
|
38
|
+
with open(self._mother_call_file) as mh:
|
|
39
|
+
mother_calls = self.make_calls_dict(mh, contig)
|
|
40
|
+
|
|
41
|
+
with open(self._father_call_file) as fh:
|
|
42
|
+
father_calls = self.make_calls_dict(fh, contig)
|
|
43
|
+
|
|
44
|
+
with open(self._child_call_file) as ch:
|
|
45
|
+
for cv in ch:
|
|
46
|
+
locus_data, call = cv.strip().split(" ")
|
|
47
|
+
lookup = tuple(locus_data.split(":"))
|
|
48
|
+
|
|
49
|
+
if lookup[0] != contig:
|
|
50
|
+
continue
|
|
51
|
+
|
|
52
|
+
bed_k = lookup[:3]
|
|
53
|
+
|
|
54
|
+
# Check to make sure call is present in TRF BED file, if it is specified
|
|
55
|
+
if self._loci_file and self._loci_dict and bed_k not in self._loci_dict:
|
|
56
|
+
continue
|
|
57
|
+
|
|
58
|
+
if self.should_exclude_locus(bed_k):
|
|
59
|
+
continue
|
|
60
|
+
|
|
61
|
+
locus_start: int = int(lookup[1])
|
|
62
|
+
locus_end: int = int(lookup[2])
|
|
63
|
+
|
|
64
|
+
cr.seen_locus(contig, locus_start, locus_end)
|
|
65
|
+
|
|
66
|
+
# Check to make sure call is present in all trio individuals
|
|
67
|
+
if lookup not in mother_calls or lookup not in father_calls:
|
|
68
|
+
continue
|
|
69
|
+
|
|
70
|
+
c_gt = int_tuple(call.split("/"))
|
|
71
|
+
m_gt = mother_calls[lookup]
|
|
72
|
+
f_gt = father_calls[lookup]
|
|
73
|
+
|
|
74
|
+
# Failed calls from RepeatHMM seem to be represented as 0/0, so skip this
|
|
75
|
+
# TODO… Need to decide if we actually want to include these?
|
|
76
|
+
# or at least somehow record them
|
|
77
|
+
if (0, 0) in (c_gt, m_gt, f_gt):
|
|
78
|
+
continue
|
|
79
|
+
|
|
80
|
+
# TODO: Include ref copies... should be in file somewhere?
|
|
81
|
+
cr.append(MILocusData(
|
|
82
|
+
lookup[0],
|
|
83
|
+
locus_start,
|
|
84
|
+
locus_end,
|
|
85
|
+
lookup[3],
|
|
86
|
+
|
|
87
|
+
child_gt=int_tuple(call.split("/")),
|
|
88
|
+
mother_gt=mother_calls[lookup],
|
|
89
|
+
father_gt=father_calls[lookup],
|
|
90
|
+
))
|
|
91
|
+
|
|
92
|
+
return cr
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from .base import BaseCalculator
|
|
6
|
+
from .result import MILocusData, MIContigResult
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"StraglrCalculator",
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class StraglrCalculator(BaseCalculator):
|
|
14
|
+
@staticmethod
|
|
15
|
+
def get_contigs_from_fh(fh) -> set:
|
|
16
|
+
return {ls[0] for ls in (line.split("\t") for line in fh if not line.startswith("#"))}
|
|
17
|
+
|
|
18
|
+
def make_calls_dict(self, ph, contig, cr: Optional[MIContigResult] = None):
|
|
19
|
+
# For reference, dicts are ordered in Python 3.7+ (guaranteed)
|
|
20
|
+
|
|
21
|
+
calls = {}
|
|
22
|
+
|
|
23
|
+
for pv in ph:
|
|
24
|
+
if pv.startswith("#"):
|
|
25
|
+
continue
|
|
26
|
+
|
|
27
|
+
line = pv.strip().split("\t")
|
|
28
|
+
|
|
29
|
+
if line[0] != contig:
|
|
30
|
+
continue
|
|
31
|
+
|
|
32
|
+
locus = tuple(line[:3])
|
|
33
|
+
|
|
34
|
+
orig_motif = self._loci_dict.get(locus)
|
|
35
|
+
orig_motif = orig_motif[-1] if orig_motif else None
|
|
36
|
+
|
|
37
|
+
if not orig_motif:
|
|
38
|
+
continue
|
|
39
|
+
|
|
40
|
+
if self.should_exclude_locus(locus):
|
|
41
|
+
continue
|
|
42
|
+
|
|
43
|
+
if cr:
|
|
44
|
+
cr.seen_locus(locus[0], int(locus[1]), int(locus[2]))
|
|
45
|
+
|
|
46
|
+
# Transform the genotypes into something that is consistent across individuals,
|
|
47
|
+
# using the file with the list of loci.
|
|
48
|
+
gt_fact = len(line[3]) / len(orig_motif)
|
|
49
|
+
|
|
50
|
+
gt = tuple(float(g.split("(")[0]) * gt_fact for g in line[4].split(";"))
|
|
51
|
+
if len(gt) == 1: # If it's homozygous, expand it out to length 2
|
|
52
|
+
gt = gt + gt
|
|
53
|
+
|
|
54
|
+
calls[locus + (orig_motif,)] = gt
|
|
55
|
+
|
|
56
|
+
return calls
|
|
57
|
+
|
|
58
|
+
def _get_sample_contigs(self, include_sex_chromosomes: bool = False) -> tuple[set, set, set]:
|
|
59
|
+
with open(self._mother_call_file, "r") as mvf, open(self._father_call_file, "r") as fvf, \
|
|
60
|
+
open(self._child_call_file, "r") as cvf:
|
|
61
|
+
|
|
62
|
+
mc = self.get_contigs_from_fh(mvf)
|
|
63
|
+
fc = self.get_contigs_from_fh(fvf)
|
|
64
|
+
cc = self.get_contigs_from_fh(cvf)
|
|
65
|
+
|
|
66
|
+
return mc, fc, cc
|
|
67
|
+
|
|
68
|
+
def calculate_contig(self, contig: str):
|
|
69
|
+
cr = MIContigResult()
|
|
70
|
+
|
|
71
|
+
with open(self._mother_call_file, "r") as mh:
|
|
72
|
+
mother_calls = self.make_calls_dict(mh, contig)
|
|
73
|
+
|
|
74
|
+
with open(self._father_call_file, "r") as fh:
|
|
75
|
+
father_calls = self.make_calls_dict(fh, contig)
|
|
76
|
+
|
|
77
|
+
with open(self._child_call_file, "r") as ch:
|
|
78
|
+
child_calls = self.make_calls_dict(ch, contig, cr)
|
|
79
|
+
|
|
80
|
+
for locus_data, c_gt in child_calls.items():
|
|
81
|
+
# Check to make sure call is present in all trio individuals
|
|
82
|
+
if locus_data not in mother_calls or locus_data not in father_calls:
|
|
83
|
+
continue
|
|
84
|
+
|
|
85
|
+
cr.append(MILocusData(
|
|
86
|
+
contig=locus_data[0],
|
|
87
|
+
start=int(locus_data[1]),
|
|
88
|
+
end=int(locus_data[2]),
|
|
89
|
+
motif=locus_data[3],
|
|
90
|
+
|
|
91
|
+
child_gt=c_gt,
|
|
92
|
+
mother_gt=mother_calls[locus_data],
|
|
93
|
+
father_gt=father_calls[locus_data],
|
|
94
|
+
|
|
95
|
+
decimal=True,
|
|
96
|
+
))
|
|
97
|
+
|
|
98
|
+
return cr
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .base import BaseCalculator
|
|
4
|
+
from .result import MIContigResult, MILocusData
|
|
5
|
+
from ..utils import int_tuple
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"TandemGenotypesCalculator",
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TandemGenotypesCalculator(BaseCalculator):
|
|
13
|
+
@staticmethod
|
|
14
|
+
def get_contigs_from_fh(fh) -> set[str]:
|
|
15
|
+
return {ls[0] for ls in (line.split("\t") for line in fh if not line.startswith("#"))}
|
|
16
|
+
|
|
17
|
+
@staticmethod
|
|
18
|
+
def make_calls_dict(ph, contig):
|
|
19
|
+
return {
|
|
20
|
+
tuple(line[:4]): int_tuple(line[6:8])
|
|
21
|
+
for line in (pv.strip().split("\t") for pv in ph if not pv.startswith("#"))
|
|
22
|
+
if line[0] == contig and "." not in line[6:8]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
def _get_sample_contigs(self, include_sex_chromosomes: bool = False) -> tuple[set, set, set]:
|
|
26
|
+
with open(self._mother_call_file, "r") as mvf, open(self._father_call_file, "r") as fvf, \
|
|
27
|
+
open(self._child_call_file, "r") as cvf:
|
|
28
|
+
|
|
29
|
+
mc = self.get_contigs_from_fh(mvf)
|
|
30
|
+
fc = self.get_contigs_from_fh(fvf)
|
|
31
|
+
cc = self.get_contigs_from_fh(cvf)
|
|
32
|
+
|
|
33
|
+
return mc, fc, cc
|
|
34
|
+
|
|
35
|
+
def calculate_contig(self, contig: str) -> MIContigResult:
|
|
36
|
+
cr = MIContigResult()
|
|
37
|
+
|
|
38
|
+
with open(self._mother_call_file) as mh:
|
|
39
|
+
mother_calls = self.make_calls_dict(mh, contig)
|
|
40
|
+
|
|
41
|
+
with open(self._father_call_file) as fh:
|
|
42
|
+
father_calls = self.make_calls_dict(fh, contig)
|
|
43
|
+
|
|
44
|
+
with open(self._child_call_file) as ch:
|
|
45
|
+
for cv in ch:
|
|
46
|
+
locus_data = cv.strip().split("\t")
|
|
47
|
+
lookup = tuple(locus_data[:4])
|
|
48
|
+
|
|
49
|
+
if locus_data[0] != contig:
|
|
50
|
+
continue
|
|
51
|
+
|
|
52
|
+
bed_k = lookup[:3]
|
|
53
|
+
|
|
54
|
+
# Check to make sure call is present in TRF BED file, if it is specified
|
|
55
|
+
if self._loci_file and self._loci_dict and bed_k not in self._loci_dict:
|
|
56
|
+
continue
|
|
57
|
+
|
|
58
|
+
# noinspection PyTypeChecker
|
|
59
|
+
if self.should_exclude_locus(bed_k):
|
|
60
|
+
continue
|
|
61
|
+
|
|
62
|
+
locus_start = int(lookup[1])
|
|
63
|
+
locus_end = int(lookup[2])
|
|
64
|
+
|
|
65
|
+
cr.seen_locus(contig, locus_start, locus_end)
|
|
66
|
+
|
|
67
|
+
# Check to make sure call is present in all trio individuals
|
|
68
|
+
if lookup not in mother_calls or lookup not in father_calls:
|
|
69
|
+
continue
|
|
70
|
+
|
|
71
|
+
child_calls = locus_data[6:8]
|
|
72
|
+
|
|
73
|
+
if "." in child_calls:
|
|
74
|
+
# Failed call
|
|
75
|
+
continue
|
|
76
|
+
|
|
77
|
+
cr.append(MILocusData(
|
|
78
|
+
contig=contig,
|
|
79
|
+
start=locus_start,
|
|
80
|
+
end=locus_end,
|
|
81
|
+
motif=lookup[3],
|
|
82
|
+
|
|
83
|
+
child_gt=int_tuple(child_calls),
|
|
84
|
+
mother_gt=mother_calls[lookup],
|
|
85
|
+
father_gt=father_calls[lookup],
|
|
86
|
+
))
|
|
87
|
+
|
|
88
|
+
return cr
|
strkit-0.11.8/strkit/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.11.8
|
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from .base import BaseCalculator
|
|
4
|
-
from .result import MIContigResult, MILocusData
|
|
5
|
-
from ..utils import int_tuple, parse_cis
|
|
6
|
-
|
|
7
|
-
__all__ = [
|
|
8
|
-
"RepeatHMMCalculator",
|
|
9
|
-
"RepeatHMMReCallCalculator",
|
|
10
|
-
]
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class RepeatHMMCalculator(BaseCalculator):
|
|
14
|
-
@staticmethod
|
|
15
|
-
def get_contigs_from_fh(fh) -> set:
|
|
16
|
-
return {ls[0] for ls in (line.split(":") for line in fh)}
|
|
17
|
-
|
|
18
|
-
@staticmethod
|
|
19
|
-
def make_calls_dict(ph, contig):
|
|
20
|
-
return {
|
|
21
|
-
tuple(k.split(":")): int_tuple(v.split("/"))
|
|
22
|
-
for k, v in (pv.split() for pv in ph)
|
|
23
|
-
if k.split(":")[0] == contig
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
def _get_sample_contigs(self, include_sex_chromosomes: bool = False) -> tuple[set, set, set]:
|
|
27
|
-
with open(self._mother_call_file, "r") as mvf, open(self._father_call_file, "r") as fvf, \
|
|
28
|
-
open(self._child_call_file, "r") as cvf:
|
|
29
|
-
|
|
30
|
-
mc = self.get_contigs_from_fh(mvf)
|
|
31
|
-
fc = self.get_contigs_from_fh(fvf)
|
|
32
|
-
cc = self.get_contigs_from_fh(cvf)
|
|
33
|
-
|
|
34
|
-
return mc, fc, cc
|
|
35
|
-
|
|
36
|
-
def calculate_contig(self, contig: str) -> MIContigResult:
|
|
37
|
-
cr = MIContigResult()
|
|
38
|
-
|
|
39
|
-
with open(self._mother_call_file) as mh:
|
|
40
|
-
mother_calls = self.make_calls_dict(mh, contig)
|
|
41
|
-
|
|
42
|
-
with open(self._father_call_file) as fh:
|
|
43
|
-
father_calls = self.make_calls_dict(fh, contig)
|
|
44
|
-
|
|
45
|
-
with open(self._child_call_file) as ch:
|
|
46
|
-
for cv in ch:
|
|
47
|
-
locus_data, call = cv.strip().split(" ")
|
|
48
|
-
lookup = tuple(locus_data.split(":"))
|
|
49
|
-
|
|
50
|
-
if lookup[0] != contig:
|
|
51
|
-
continue
|
|
52
|
-
|
|
53
|
-
bed_k = lookup[:3]
|
|
54
|
-
|
|
55
|
-
# Check to make sure call is present in TRF BED file, if it is specified
|
|
56
|
-
if self._loci_file and self._loci_dict and bed_k not in self._loci_dict:
|
|
57
|
-
continue
|
|
58
|
-
|
|
59
|
-
if self.should_exclude_locus(bed_k):
|
|
60
|
-
continue
|
|
61
|
-
|
|
62
|
-
locus_start: int = int(lookup[1])
|
|
63
|
-
locus_end: int = int(lookup[2])
|
|
64
|
-
|
|
65
|
-
cr.seen_locus(contig, locus_start, locus_end)
|
|
66
|
-
|
|
67
|
-
# Check to make sure call is present in all trio individuals
|
|
68
|
-
if lookup not in mother_calls or lookup not in father_calls:
|
|
69
|
-
continue
|
|
70
|
-
|
|
71
|
-
c_gt = int_tuple(call.split("/"))
|
|
72
|
-
m_gt = mother_calls[lookup]
|
|
73
|
-
f_gt = father_calls[lookup]
|
|
74
|
-
|
|
75
|
-
# Failed calls from RepeatHMM seem to be represented as 0/0, so skip this
|
|
76
|
-
# TODO… Need to decide if we actually want to include these?
|
|
77
|
-
# or at least somehow record them
|
|
78
|
-
if (0, 0) in (c_gt, m_gt, f_gt):
|
|
79
|
-
continue
|
|
80
|
-
|
|
81
|
-
# TODO: Include ref copies... should be in file somewhere?
|
|
82
|
-
cr.append(MILocusData(
|
|
83
|
-
lookup[0],
|
|
84
|
-
locus_start,
|
|
85
|
-
locus_end,
|
|
86
|
-
lookup[3],
|
|
87
|
-
|
|
88
|
-
child_gt=int_tuple(call.split("/")),
|
|
89
|
-
mother_gt=mother_calls[lookup],
|
|
90
|
-
father_gt=father_calls[lookup],
|
|
91
|
-
))
|
|
92
|
-
|
|
93
|
-
return cr
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
class RepeatHMMReCallCalculator(RepeatHMMCalculator):
|
|
97
|
-
@staticmethod
|
|
98
|
-
def make_calls_dict(ph, contig):
|
|
99
|
-
return {
|
|
100
|
-
tuple(v[0].split(":")): (
|
|
101
|
-
int_tuple(v[1:3]),
|
|
102
|
-
parse_cis(v[3:5], commas=True),
|
|
103
|
-
parse_cis(v[5:7], commas=True),
|
|
104
|
-
)
|
|
105
|
-
for v in (pv.split("\t") for pv in ph)
|
|
106
|
-
if v[0].split(":")[0] == contig and "." not in v[1:3]
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
# TODO: Deduplicate with above
|
|
110
|
-
def calculate_contig(self, contig: str) -> MIContigResult:
|
|
111
|
-
cr = MIContigResult(includes_95_ci=True, includes_99_ci=True)
|
|
112
|
-
|
|
113
|
-
with open(self._mother_call_file) as mh:
|
|
114
|
-
mother_calls = self.make_calls_dict(mh, contig)
|
|
115
|
-
|
|
116
|
-
with open(self._father_call_file) as fh:
|
|
117
|
-
father_calls = self.make_calls_dict(fh, contig)
|
|
118
|
-
|
|
119
|
-
with open(self._child_call_file) as ch:
|
|
120
|
-
for cv in ch:
|
|
121
|
-
locus_data = cv.strip().split("\t")
|
|
122
|
-
lookup = tuple(locus_data[0].split(":"))
|
|
123
|
-
|
|
124
|
-
if lookup[0] != contig:
|
|
125
|
-
continue
|
|
126
|
-
|
|
127
|
-
bed_k = lookup[:3]
|
|
128
|
-
|
|
129
|
-
# Check to make sure call is present in TRF BED file, if it is specified
|
|
130
|
-
if self._loci_file and self._loci_dict and bed_k not in self._loci_dict:
|
|
131
|
-
continue
|
|
132
|
-
|
|
133
|
-
# noinspection PyTypeChecker
|
|
134
|
-
if self.should_exclude_locus(bed_k):
|
|
135
|
-
continue
|
|
136
|
-
|
|
137
|
-
locus_start: int = int(lookup[1])
|
|
138
|
-
locus_end: int = int(lookup[2])
|
|
139
|
-
|
|
140
|
-
cr.seen_locus(contig, locus_start, locus_end)
|
|
141
|
-
|
|
142
|
-
# Check to make sure call is present in all trio individuals
|
|
143
|
-
if lookup not in mother_calls or lookup not in father_calls:
|
|
144
|
-
continue
|
|
145
|
-
|
|
146
|
-
# TODO: What will failed calls look like here? Do we also check for 0?
|
|
147
|
-
|
|
148
|
-
m_gt, m_gt_95_ci, m_gt_99_ci = mother_calls[lookup]
|
|
149
|
-
f_gt, f_gt_95_ci, f_gt_99_ci = father_calls[lookup]
|
|
150
|
-
|
|
151
|
-
# print(m_gt, m_gt_95_ci, m_gt_99_ci)
|
|
152
|
-
|
|
153
|
-
calls = locus_data[1:3]
|
|
154
|
-
|
|
155
|
-
if "." in calls:
|
|
156
|
-
# Failed call
|
|
157
|
-
continue
|
|
158
|
-
|
|
159
|
-
c_gt = int_tuple(calls)
|
|
160
|
-
c_gt_95_ci = parse_cis(locus_data[3:5], commas=True)
|
|
161
|
-
c_gt_99_ci = parse_cis(locus_data[5:7], commas=True)
|
|
162
|
-
|
|
163
|
-
if (0, 0) in (c_gt, m_gt, f_gt): # TODO
|
|
164
|
-
# Failed call
|
|
165
|
-
continue
|
|
166
|
-
|
|
167
|
-
if self._debug: # TODO: Real logging
|
|
168
|
-
print(f"c_gt={c_gt} c_gt_95_ci={c_gt_95_ci}")
|
|
169
|
-
print(f"m_gt={m_gt} m_gt_95_ci={m_gt_95_ci}")
|
|
170
|
-
print(f"f_gt={f_gt} f_gt_95_ci={f_gt_95_ci}")
|
|
171
|
-
|
|
172
|
-
# TODO: Put ref # here, since we have it with the detail thing
|
|
173
|
-
cr.append(MILocusData(
|
|
174
|
-
lookup[0],
|
|
175
|
-
int(lookup[1]),
|
|
176
|
-
int(lookup[2]),
|
|
177
|
-
lookup[3],
|
|
178
|
-
|
|
179
|
-
child_gt=int_tuple(calls),
|
|
180
|
-
mother_gt=m_gt,
|
|
181
|
-
father_gt=f_gt,
|
|
182
|
-
|
|
183
|
-
child_gt_95_ci=c_gt_95_ci,
|
|
184
|
-
mother_gt_95_ci=m_gt_95_ci,
|
|
185
|
-
father_gt_95_ci=f_gt_95_ci,
|
|
186
|
-
|
|
187
|
-
child_gt_99_ci=c_gt_99_ci,
|
|
188
|
-
mother_gt_99_ci=m_gt_99_ci,
|
|
189
|
-
father_gt_99_ci=f_gt_99_ci,
|
|
190
|
-
))
|
|
191
|
-
|
|
192
|
-
return cr
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import Optional
|
|
4
|
-
|
|
5
|
-
from .base import BaseCalculator
|
|
6
|
-
from .result import MILocusData, MIContigResult
|
|
7
|
-
|
|
8
|
-
__all__ = [
|
|
9
|
-
"StraglrCalculator",
|
|
10
|
-
"StraglrReCallCalculator",
|
|
11
|
-
]
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class StraglrCalculator(BaseCalculator):
|
|
15
|
-
@staticmethod
|
|
16
|
-
def get_contigs_from_fh(fh) -> set:
|
|
17
|
-
return {ls[0] for ls in (line.split("\t") for line in fh if not line.startswith("#"))}
|
|
18
|
-
|
|
19
|
-
def make_calls_dict(self, ph, contig, cr: Optional[MIContigResult] = None):
|
|
20
|
-
# For reference, dicts are ordered in Python 3.7+ (guaranteed)
|
|
21
|
-
|
|
22
|
-
calls = {}
|
|
23
|
-
|
|
24
|
-
for pv in ph:
|
|
25
|
-
if pv.startswith("#"):
|
|
26
|
-
continue
|
|
27
|
-
|
|
28
|
-
line = pv.strip().split("\t")
|
|
29
|
-
|
|
30
|
-
if line[0] != contig:
|
|
31
|
-
continue
|
|
32
|
-
|
|
33
|
-
locus = tuple(line[:3])
|
|
34
|
-
|
|
35
|
-
orig_motif = self._loci_dict.get(locus)
|
|
36
|
-
orig_motif = orig_motif[-1] if orig_motif else None
|
|
37
|
-
|
|
38
|
-
if not orig_motif:
|
|
39
|
-
continue
|
|
40
|
-
|
|
41
|
-
if self.should_exclude_locus(locus):
|
|
42
|
-
continue
|
|
43
|
-
|
|
44
|
-
if cr:
|
|
45
|
-
cr.seen_locus(locus[0], int(locus[1]), int(locus[2]))
|
|
46
|
-
|
|
47
|
-
# Transform the genotypes into something that is consistent across individuals,
|
|
48
|
-
# using the file with the list of loci.
|
|
49
|
-
gt_fact = len(line[3]) / len(orig_motif)
|
|
50
|
-
|
|
51
|
-
gt = tuple(float(g.split("(")[0]) * gt_fact for g in line[4].split(";"))
|
|
52
|
-
if len(gt) == 1: # If it's homozygous, expand it out to length 2
|
|
53
|
-
gt = gt + gt
|
|
54
|
-
|
|
55
|
-
calls[locus + (orig_motif,)] = gt
|
|
56
|
-
|
|
57
|
-
return calls
|
|
58
|
-
|
|
59
|
-
def _get_sample_contigs(self, include_sex_chromosomes: bool = False) -> tuple[set, set, set]:
|
|
60
|
-
with open(self._mother_call_file, "r") as mvf, open(self._father_call_file, "r") as fvf, \
|
|
61
|
-
open(self._child_call_file, "r") as cvf:
|
|
62
|
-
|
|
63
|
-
mc = self.get_contigs_from_fh(mvf)
|
|
64
|
-
fc = self.get_contigs_from_fh(fvf)
|
|
65
|
-
cc = self.get_contigs_from_fh(cvf)
|
|
66
|
-
|
|
67
|
-
return mc, fc, cc
|
|
68
|
-
|
|
69
|
-
def calculate_contig(self, contig: str):
|
|
70
|
-
cr = MIContigResult()
|
|
71
|
-
|
|
72
|
-
with open(self._mother_call_file, "r") as mh:
|
|
73
|
-
mother_calls = self.make_calls_dict(mh, contig)
|
|
74
|
-
|
|
75
|
-
with open(self._father_call_file, "r") as fh:
|
|
76
|
-
father_calls = self.make_calls_dict(fh, contig)
|
|
77
|
-
|
|
78
|
-
with open(self._child_call_file, "r") as ch:
|
|
79
|
-
child_calls = self.make_calls_dict(ch, contig, cr)
|
|
80
|
-
|
|
81
|
-
for locus_data, c_gt in child_calls.items():
|
|
82
|
-
# Check to make sure call is present in all trio individuals
|
|
83
|
-
if locus_data not in mother_calls or locus_data not in father_calls:
|
|
84
|
-
continue
|
|
85
|
-
|
|
86
|
-
cr.append(MILocusData(
|
|
87
|
-
contig=locus_data[0],
|
|
88
|
-
start=int(locus_data[1]),
|
|
89
|
-
end=int(locus_data[2]),
|
|
90
|
-
motif=locus_data[3],
|
|
91
|
-
|
|
92
|
-
child_gt=c_gt,
|
|
93
|
-
mother_gt=mother_calls[locus_data],
|
|
94
|
-
father_gt=father_calls[locus_data],
|
|
95
|
-
|
|
96
|
-
decimal=True,
|
|
97
|
-
))
|
|
98
|
-
|
|
99
|
-
return cr
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
class StraglrReCallCalculator(BaseCalculator):
|
|
103
|
-
@staticmethod
|
|
104
|
-
def get_contigs_from_fh(fh) -> set:
|
|
105
|
-
return {ls[0] for ls in (line.split("\t") for line in fh if not line.startswith("#"))}
|
|
106
|
-
|
|
107
|
-
def make_calls_dict(self, ph, contig, cr: Optional[MIContigResult] = None):
|
|
108
|
-
# For reference, dicts are ordered in Python 3.7+ (guaranteed)
|
|
109
|
-
|
|
110
|
-
calls = {}
|
|
111
|
-
|
|
112
|
-
for pv in ph:
|
|
113
|
-
if pv.startswith("#"):
|
|
114
|
-
continue
|
|
115
|
-
|
|
116
|
-
line = pv.strip().split("\t")
|
|
117
|
-
|
|
118
|
-
if line[0] != contig:
|
|
119
|
-
continue
|
|
120
|
-
|
|
121
|
-
locus = tuple(line[:3])
|
|
122
|
-
orig_motif = self._loci_dict.get(locus)
|
|
123
|
-
orig_motif = orig_motif[-1] if orig_motif else None
|
|
124
|
-
if not orig_motif:
|
|
125
|
-
continue
|
|
126
|
-
|
|
127
|
-
if self.should_exclude_locus(locus):
|
|
128
|
-
continue
|
|
129
|
-
|
|
130
|
-
if cr:
|
|
131
|
-
cr.seen_locus(contig, int(locus[1]), int(locus[2]))
|
|
132
|
-
|
|
133
|
-
if "." in line[6:8]:
|
|
134
|
-
continue
|
|
135
|
-
|
|
136
|
-
# Transform the genotypes into something that is consistent across individuals,
|
|
137
|
-
# using the file with the list of loci.
|
|
138
|
-
# Round it to the nearest first decimal place, since that is what Straglr calls.
|
|
139
|
-
|
|
140
|
-
gt_fact = len(line[3]) / len(orig_motif)
|
|
141
|
-
|
|
142
|
-
def _to_tenth(x: str):
|
|
143
|
-
return round(float(x) * gt_fact * 10) / 10
|
|
144
|
-
|
|
145
|
-
gt = tuple(map(_to_tenth, line[6:8]))
|
|
146
|
-
gt_95_ci = tuple(tuple(map(_to_tenth, ci.split(","))) for ci in line[8:10])
|
|
147
|
-
gt_99_ci = tuple(tuple(map(_to_tenth, ci.split(","))) for ci in line[10:12])
|
|
148
|
-
|
|
149
|
-
calls[locus + (orig_motif,)] = (gt, gt_95_ci, gt_99_ci)
|
|
150
|
-
|
|
151
|
-
return calls
|
|
152
|
-
|
|
153
|
-
def _get_sample_contigs(self, include_sex_chromosomes: bool = False) -> tuple[set, set, set]:
|
|
154
|
-
with open(self._mother_call_file, "r") as mvf, open(self._father_call_file, "r") as fvf, \
|
|
155
|
-
open(self._child_call_file, "r") as cvf:
|
|
156
|
-
|
|
157
|
-
mc = self.get_contigs_from_fh(mvf)
|
|
158
|
-
fc = self.get_contigs_from_fh(fvf)
|
|
159
|
-
cc = self.get_contigs_from_fh(cvf)
|
|
160
|
-
|
|
161
|
-
return mc, fc, cc
|
|
162
|
-
|
|
163
|
-
def calculate_contig(self, contig: str):
|
|
164
|
-
cr = MIContigResult(includes_95_ci=True, includes_99_ci=True)
|
|
165
|
-
|
|
166
|
-
with open(self._mother_call_file) as mh:
|
|
167
|
-
mother_calls = self.make_calls_dict(mh, contig)
|
|
168
|
-
|
|
169
|
-
with open(self._father_call_file) as fh:
|
|
170
|
-
father_calls = self.make_calls_dict(fh, contig)
|
|
171
|
-
|
|
172
|
-
with open(self._child_call_file) as ch:
|
|
173
|
-
child_calls = self.make_calls_dict(ch, contig, cr)
|
|
174
|
-
|
|
175
|
-
for locus_data, c_gt_and_cis in child_calls.items():
|
|
176
|
-
# Check to make sure call is present in all trio individuals
|
|
177
|
-
if locus_data not in mother_calls or locus_data not in father_calls:
|
|
178
|
-
continue
|
|
179
|
-
|
|
180
|
-
locus_start = int(locus_data[1])
|
|
181
|
-
locus_end = int(locus_data[2])
|
|
182
|
-
|
|
183
|
-
c_gt, c_gt_95_ci, c_gt_99_ci = c_gt_and_cis
|
|
184
|
-
|
|
185
|
-
m_gt, m_gt_95_ci, m_gt_99_ci = mother_calls[locus_data]
|
|
186
|
-
f_gt, f_gt_95_ci, f_gt_99_ci = father_calls[locus_data]
|
|
187
|
-
|
|
188
|
-
cr.append(MILocusData(
|
|
189
|
-
contig=locus_data[0],
|
|
190
|
-
start=locus_start,
|
|
191
|
-
end=locus_end,
|
|
192
|
-
motif=locus_data[3],
|
|
193
|
-
|
|
194
|
-
child_gt=c_gt, mother_gt=m_gt, father_gt=f_gt,
|
|
195
|
-
child_gt_95_ci=c_gt_95_ci, mother_gt_95_ci=m_gt_95_ci, father_gt_95_ci=f_gt_95_ci,
|
|
196
|
-
child_gt_99_ci=c_gt_99_ci, mother_gt_99_ci=m_gt_99_ci, father_gt_99_ci=f_gt_99_ci,
|
|
197
|
-
|
|
198
|
-
decimal=True,
|
|
199
|
-
))
|
|
200
|
-
|
|
201
|
-
return cr
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from .base import BaseCalculator
|
|
4
|
-
from .result import MIContigResult, MILocusData
|
|
5
|
-
from ..utils import int_tuple, parse_cis
|
|
6
|
-
|
|
7
|
-
__all__ = [
|
|
8
|
-
"TandemGenotypesCalculator",
|
|
9
|
-
"TandemGenotypesReCallCalculator",
|
|
10
|
-
]
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class TandemGenotypesCalculator(BaseCalculator):
|
|
14
|
-
@staticmethod
|
|
15
|
-
def get_contigs_from_fh(fh) -> set[str]:
|
|
16
|
-
return {ls[0] for ls in (line.split("\t") for line in fh if not line.startswith("#"))}
|
|
17
|
-
|
|
18
|
-
@staticmethod
|
|
19
|
-
def make_calls_dict(ph, contig):
|
|
20
|
-
return {
|
|
21
|
-
tuple(line[:4]): int_tuple(line[6:8]) if "." not in line[6:8] else (None, None)
|
|
22
|
-
for line in (pv.strip().split("\t") for pv in ph if not pv.startswith("#"))
|
|
23
|
-
if line[0] == contig
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
def _get_sample_contigs(self, include_sex_chromosomes: bool = False) -> tuple[set, set, set]:
|
|
27
|
-
with open(self._mother_call_file, "r") as mvf, open(self._father_call_file, "r") as fvf, \
|
|
28
|
-
open(self._child_call_file, "r") as cvf:
|
|
29
|
-
|
|
30
|
-
mc = self.get_contigs_from_fh(mvf)
|
|
31
|
-
fc = self.get_contigs_from_fh(fvf)
|
|
32
|
-
cc = self.get_contigs_from_fh(cvf)
|
|
33
|
-
|
|
34
|
-
return mc, fc, cc
|
|
35
|
-
|
|
36
|
-
def calculate_contig(self, contig: str) -> MIContigResult:
|
|
37
|
-
cr = MIContigResult()
|
|
38
|
-
|
|
39
|
-
with open(self._mother_call_file) as mh:
|
|
40
|
-
mother_calls = self.make_calls_dict(mh, contig)
|
|
41
|
-
|
|
42
|
-
with open(self._father_call_file) as fh:
|
|
43
|
-
father_calls = self.make_calls_dict(fh, contig)
|
|
44
|
-
|
|
45
|
-
with open(self._child_call_file) as ch:
|
|
46
|
-
for cv in ch:
|
|
47
|
-
locus_data = cv.strip().split("\t")
|
|
48
|
-
lookup = tuple(locus_data[:4])
|
|
49
|
-
|
|
50
|
-
if locus_data[0] != contig:
|
|
51
|
-
continue
|
|
52
|
-
|
|
53
|
-
bed_k = lookup[:3]
|
|
54
|
-
|
|
55
|
-
# Check to make sure call is present in TRF BED file, if it is specified
|
|
56
|
-
if self._loci_file and self._loci_dict and bed_k not in self._loci_dict:
|
|
57
|
-
continue
|
|
58
|
-
|
|
59
|
-
# noinspection PyTypeChecker
|
|
60
|
-
if self.should_exclude_locus(bed_k):
|
|
61
|
-
continue
|
|
62
|
-
|
|
63
|
-
locus_start = int(lookup[1])
|
|
64
|
-
locus_end = int(lookup[2])
|
|
65
|
-
|
|
66
|
-
cr.seen_locus(contig, locus_start, locus_end)
|
|
67
|
-
|
|
68
|
-
# Check to make sure call is present in all trio individuals
|
|
69
|
-
if lookup not in mother_calls or lookup not in father_calls:
|
|
70
|
-
continue
|
|
71
|
-
|
|
72
|
-
child_calls = locus_data[6:8]
|
|
73
|
-
|
|
74
|
-
if "." in child_calls:
|
|
75
|
-
# Failed call
|
|
76
|
-
continue
|
|
77
|
-
|
|
78
|
-
cr.append(MILocusData(
|
|
79
|
-
contig=contig,
|
|
80
|
-
start=locus_start,
|
|
81
|
-
end=locus_end,
|
|
82
|
-
motif=lookup[3],
|
|
83
|
-
|
|
84
|
-
child_gt=int_tuple(child_calls),
|
|
85
|
-
mother_gt=mother_calls[lookup],
|
|
86
|
-
father_gt=father_calls[lookup],
|
|
87
|
-
))
|
|
88
|
-
|
|
89
|
-
return cr
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
class TandemGenotypesReCallCalculator(TandemGenotypesCalculator):
|
|
93
|
-
@staticmethod
|
|
94
|
-
def make_calls_dict(ph, contig):
|
|
95
|
-
return {
|
|
96
|
-
# Use relative indices because we may have the original calls lurking
|
|
97
|
-
tuple(line[:4]): (
|
|
98
|
-
int_tuple(line[-6:-4]),
|
|
99
|
-
parse_cis(line[-4:-2], commas=True),
|
|
100
|
-
parse_cis(line[-2:], commas=True),
|
|
101
|
-
)
|
|
102
|
-
for line in (pv.strip().split("\t") for pv in ph)
|
|
103
|
-
if line[0] == contig and "." not in line[-6:-4]
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
def calculate_contig(self, contig: str) -> MIContigResult:
|
|
107
|
-
cr = MIContigResult(includes_95_ci=True, includes_99_ci=True)
|
|
108
|
-
|
|
109
|
-
with open(self._mother_call_file) as mh:
|
|
110
|
-
mother_calls = self.make_calls_dict(mh, contig)
|
|
111
|
-
|
|
112
|
-
with open(self._father_call_file) as fh:
|
|
113
|
-
father_calls = self.make_calls_dict(fh, contig)
|
|
114
|
-
|
|
115
|
-
with open(self._child_call_file) as ch:
|
|
116
|
-
for cv in ch:
|
|
117
|
-
locus_data = cv.strip().split("\t")
|
|
118
|
-
lookup = tuple(locus_data[:4])
|
|
119
|
-
|
|
120
|
-
if locus_data[0] != contig:
|
|
121
|
-
continue
|
|
122
|
-
|
|
123
|
-
bed_k = lookup[:3]
|
|
124
|
-
|
|
125
|
-
# Check to make sure call is present in TRF BED file, if it is specified
|
|
126
|
-
if self._loci_file and self._loci_dict and bed_k not in self._loci_dict:
|
|
127
|
-
continue
|
|
128
|
-
|
|
129
|
-
# noinspection PyTypeChecker
|
|
130
|
-
if self.should_exclude_locus(bed_k):
|
|
131
|
-
continue
|
|
132
|
-
|
|
133
|
-
locus_start = int(lookup[1])
|
|
134
|
-
locus_end = int(lookup[2])
|
|
135
|
-
|
|
136
|
-
cr.seen_locus(contig, locus_start, locus_end)
|
|
137
|
-
|
|
138
|
-
# Check to make sure call is present in all trio individuals
|
|
139
|
-
if lookup not in mother_calls or lookup not in father_calls:
|
|
140
|
-
continue
|
|
141
|
-
|
|
142
|
-
m_gt, m_gt_95_ci, m_gt_99_ci = mother_calls[lookup]
|
|
143
|
-
f_gt, f_gt_95_ci, f_gt_99_ci = father_calls[lookup]
|
|
144
|
-
|
|
145
|
-
calls = locus_data[-6:-4]
|
|
146
|
-
|
|
147
|
-
if "." in calls:
|
|
148
|
-
# Failed call
|
|
149
|
-
continue
|
|
150
|
-
|
|
151
|
-
cr.append(MILocusData(
|
|
152
|
-
contig=lookup[0],
|
|
153
|
-
start=int(lookup[1]),
|
|
154
|
-
end=int(lookup[2]),
|
|
155
|
-
motif=lookup[3],
|
|
156
|
-
|
|
157
|
-
child_gt=int_tuple(calls),
|
|
158
|
-
mother_gt=m_gt,
|
|
159
|
-
father_gt=f_gt,
|
|
160
|
-
|
|
161
|
-
child_gt_95_ci=parse_cis(locus_data[-4:-2], commas=True),
|
|
162
|
-
mother_gt_95_ci=m_gt_95_ci,
|
|
163
|
-
father_gt_95_ci=f_gt_95_ci,
|
|
164
|
-
|
|
165
|
-
child_gt_99_ci=parse_cis(locus_data[-2:], commas=True),
|
|
166
|
-
mother_gt_99_ci=m_gt_99_ci,
|
|
167
|
-
father_gt_99_ci=f_gt_99_ci,
|
|
168
|
-
|
|
169
|
-
# TODO: ref count
|
|
170
|
-
))
|
|
171
|
-
|
|
172
|
-
return cr
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|