gnomancer 0.3.1__py3-none-any.whl
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.
- gnomancer/__init__.py +2 -0
- gnomancer/__main__.py +2 -0
- gnomancer/cli.py +155 -0
- gnomancer/clinvar.py +133 -0
- gnomancer/context.py +32 -0
- gnomancer/data/haplogroup_context.tsv +72 -0
- gnomancer/data/markers.tsv +115 -0
- gnomancer/data/rCRS_NC_012920.1.fasta +239 -0
- gnomancer/haplogroups.py +130 -0
- gnomancer/load.py +67 -0
- gnomancer/mcp_server.py +200 -0
- gnomancer/panel.py +141 -0
- gnomancer/paths.py +47 -0
- gnomancer/pharmcat.py +120 -0
- gnomancer/qc.py +60 -0
- gnomancer/report.py +141 -0
- gnomancer/report_html.py +325 -0
- gnomancer/roh.py +60 -0
- gnomancer/setup_cmd.py +97 -0
- gnomancer/summary.py +181 -0
- gnomancer/yleaf.py +71 -0
- gnomancer-0.3.1.dist-info/METADATA +211 -0
- gnomancer-0.3.1.dist-info/RECORD +27 -0
- gnomancer-0.3.1.dist-info/WHEEL +5 -0
- gnomancer-0.3.1.dist-info/entry_points.txt +3 -0
- gnomancer-0.3.1.dist-info/licenses/LICENSE +21 -0
- gnomancer-0.3.1.dist-info/top_level.txt +1 -0
gnomancer/__init__.py
ADDED
gnomancer/__main__.py
ADDED
gnomancer/cli.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""Command-line entry point: python -m gnomancer <raw file> [--out DIR]"""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import json
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from . import __version__
|
|
10
|
+
from .load import load
|
|
11
|
+
from .qc import chromosome_table, summary
|
|
12
|
+
from .roh import find_roh, interpret
|
|
13
|
+
from .panel import load_markers, evaluate, combos
|
|
14
|
+
from .haplogroups import call_y, call_mt
|
|
15
|
+
from .report import write
|
|
16
|
+
from . import clinvar as clinvar_mod
|
|
17
|
+
from . import pharmcat as pharmcat_mod
|
|
18
|
+
from . import yleaf as yleaf_mod
|
|
19
|
+
from . import summary as summary_mod
|
|
20
|
+
from .report_html import write_html
|
|
21
|
+
|
|
22
|
+
from .paths import DATA, ancestry_python
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def run_ezancestry(inp: Path, loaded) -> dict | None:
|
|
26
|
+
"""Run ezancestry in a separate interpreter (it needs Python <=3.11) if .venv-ancestry exists, else in-process."""
|
|
27
|
+
import json as _json
|
|
28
|
+
import subprocess
|
|
29
|
+
code = ("import json,sys\nfrom snps import SNPs\nr=SNPs(sys.argv[1]).predict_ancestry()\n"
|
|
30
|
+
"print(json.dumps({k:v for k,v in r.items() if k!='ezancestry_df'}, default=str))")
|
|
31
|
+
venv_py = ancestry_python()
|
|
32
|
+
py = str(venv_py) if venv_py else sys.executable
|
|
33
|
+
try:
|
|
34
|
+
p = subprocess.run([py, "-c", code, str(inp)], capture_output=True, text=True, timeout=1800)
|
|
35
|
+
if p.returncode != 0:
|
|
36
|
+
raise RuntimeError(p.stderr.strip().splitlines()[-1] if p.stderr.strip() else "unknown error")
|
|
37
|
+
return _json.loads(p.stdout.strip().splitlines()[-1])
|
|
38
|
+
except Exception as e: # noqa: BLE001
|
|
39
|
+
loaded.notes.append(f"ezancestry failed: {e}")
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def main(argv=None):
|
|
44
|
+
argv = list(sys.argv[1:] if argv is None else argv)
|
|
45
|
+
if argv[:1] == ["serve"]:
|
|
46
|
+
from .mcp_server import main as serve
|
|
47
|
+
return serve()
|
|
48
|
+
if argv[:1] == ["setup"]:
|
|
49
|
+
from .setup_cmd import run as setup
|
|
50
|
+
return setup(argv[1:])
|
|
51
|
+
ap = argparse.ArgumentParser(prog="gnomancer", description="Analyze a consumer raw DNA file locally. Subcommands: `gnomancer setup` (download tools), `gnomancer serve` (MCP server).")
|
|
52
|
+
ap.add_argument("input", help="raw data file (.txt/.csv/.tsv/.vcf, optionally .zip/.gz)")
|
|
53
|
+
ap.add_argument("--out", default=None, help="output directory (default: <input>_analysis)")
|
|
54
|
+
ap.add_argument("--markers", default=str(DATA / "markers.tsv"), help="marker panel TSV")
|
|
55
|
+
ap.add_argument("--no-y", action="store_true", help="skip Y haplogroup")
|
|
56
|
+
ap.add_argument("--no-mt", action="store_true", help="skip mtDNA haplogroup")
|
|
57
|
+
ap.add_argument("--ancestry", action="store_true", help="run ezancestry population prediction (uses .venv-ancestry if present)")
|
|
58
|
+
ap.add_argument("--no-clinvar", action="store_true", help="skip the ClinVar scan")
|
|
59
|
+
ap.add_argument("--no-yleaf", action="store_true", help="skip the Yleaf second-opinion Y call")
|
|
60
|
+
ap.add_argument("--no-pharmcat", action="store_true", help="skip PharmCAT")
|
|
61
|
+
ap.add_argument("--summary", default=None, help="Markdown/text file with a narrative summary (e.g. written by your AI agent) to show at the top of the report")
|
|
62
|
+
ap.add_argument("--ai", action="store_true", help="have Claude write the narrative summary (sends the structured results, not the raw file, to the Anthropic API; needs credentials)")
|
|
63
|
+
ap.add_argument("--version", action="version", version=__version__)
|
|
64
|
+
a = ap.parse_args(argv)
|
|
65
|
+
run_args = argv
|
|
66
|
+
|
|
67
|
+
inp = Path(a.input)
|
|
68
|
+
out = Path(a.out) if a.out else inp.with_name(inp.stem.replace(".", "_") + "_analysis")
|
|
69
|
+
out.mkdir(parents=True, exist_ok=True)
|
|
70
|
+
|
|
71
|
+
print(f"[1/6] loading {inp} ...", file=sys.stderr)
|
|
72
|
+
loaded = load(str(inp))
|
|
73
|
+
df = loaded.df
|
|
74
|
+
print(f" {loaded.source}, build {loaded.build}, {loaded.count:,} SNPs, sex {loaded.sex or '?'}", file=sys.stderr)
|
|
75
|
+
|
|
76
|
+
print("[2/6] quality metrics ...", file=sys.stderr)
|
|
77
|
+
ct = chromosome_table(df)
|
|
78
|
+
qc = summary(df, ct, loaded.sex)
|
|
79
|
+
ct.to_csv(out / "chromosome-qc.tsv", sep="\t", index=False)
|
|
80
|
+
|
|
81
|
+
print("[3/6] runs of homozygosity ...", file=sys.stderr)
|
|
82
|
+
roh = find_roh(df)
|
|
83
|
+
roh.to_csv(out / "roh.tsv", sep="\t", index=False)
|
|
84
|
+
roh_text = interpret(roh)
|
|
85
|
+
|
|
86
|
+
print("[4/6] marker panel ...", file=sys.stderr)
|
|
87
|
+
markers = load_markers(Path(a.markers))
|
|
88
|
+
panel = evaluate(df, markers)
|
|
89
|
+
panel.to_csv(out / "marker-panel.tsv", sep="\t", index=False)
|
|
90
|
+
combo = combos(df)
|
|
91
|
+
|
|
92
|
+
is_male = qc["sex_inferred"] == "Male"
|
|
93
|
+
y = dict(error="skipped (sample is not male)" if not is_male else "skipped (--no-y)")
|
|
94
|
+
if is_male and not a.no_y:
|
|
95
|
+
print("[5/6] Y haplogroup (yhaplo) ...", file=sys.stderr)
|
|
96
|
+
y = call_y(df, out)
|
|
97
|
+
if not a.no_yleaf:
|
|
98
|
+
print(" second opinion on current trees (Yleaf) ...", file=sys.stderr)
|
|
99
|
+
y["yleaf"] = yleaf_mod.run(df, out)
|
|
100
|
+
mt = dict(error="skipped (--no-mt)")
|
|
101
|
+
if not a.no_mt:
|
|
102
|
+
print("[5/6] mtDNA haplogroup (haplogrep3) ...", file=sys.stderr)
|
|
103
|
+
mt = call_mt(df, out, loaded.build_original)
|
|
104
|
+
|
|
105
|
+
cv = dict(available=False, hits=None, note="skipped (--no-clinvar)")
|
|
106
|
+
if not a.no_clinvar:
|
|
107
|
+
print("[6/8] ClinVar scan of every typed site ...", file=sys.stderr)
|
|
108
|
+
cv = clinvar_mod.scan(df)
|
|
109
|
+
if cv["available"] and cv["hits"] is not None and not cv["hits"].empty:
|
|
110
|
+
cv["hits"].to_csv(out / "clinvar-hits.tsv", sep="\t", index=False)
|
|
111
|
+
cv_text = clinvar_mod.interpret(cv) if not a.no_clinvar else cv["note"]
|
|
112
|
+
pc = dict(available=False, calls=None, error="skipped (--no-pharmcat)", stats={})
|
|
113
|
+
if not a.no_pharmcat:
|
|
114
|
+
print("[7/8] PharmCAT pharmacogenomics ...", file=sys.stderr)
|
|
115
|
+
pc = pharmcat_mod.run(df, out)
|
|
116
|
+
if pc.get("calls") is not None and not pc["calls"].empty:
|
|
117
|
+
pc["calls"].to_csv(out / "pharmcat-calls.tsv", sep="\t", index=False)
|
|
118
|
+
pc_text = pharmcat_mod.interpret(pc) if not a.no_pharmcat else pc["error"]
|
|
119
|
+
ancestry = None
|
|
120
|
+
if a.ancestry:
|
|
121
|
+
print("[8/8] ancestry prediction (ezancestry) ...", file=sys.stderr)
|
|
122
|
+
ancestry = run_ezancestry(inp, loaded)
|
|
123
|
+
|
|
124
|
+
glance = summary_mod.at_a_glance(loaded, qc, roh, roh_text, combo, y, mt, ancestry, panel, cv, pc)
|
|
125
|
+
prompt = summary_mod.build_prompt(glance, combo, y, mt, ancestry, panel, cv, pc, qc)
|
|
126
|
+
summary_mod.write_prompt_file(out, prompt)
|
|
127
|
+
narrative = None
|
|
128
|
+
if a.summary:
|
|
129
|
+
narrative = Path(a.summary).read_text().strip()
|
|
130
|
+
elif a.ai:
|
|
131
|
+
print(" narrative summary (Claude) ...", file=sys.stderr)
|
|
132
|
+
try:
|
|
133
|
+
narrative = summary_mod.ai_summary(prompt)
|
|
134
|
+
(out / "summary.md").write_text(narrative + "\n")
|
|
135
|
+
except Exception as e: # noqa: BLE001
|
|
136
|
+
loaded.notes.append(f"AI summary failed: {e}")
|
|
137
|
+
extra = dict(clinvar=cv, clinvar_text=cv_text, pharmcat=pc, pharmcat_text=pc_text, glance=glance, narrative=narrative)
|
|
138
|
+
rep = write(out / "REPORT.md", loaded, qc, ct, roh, roh_text, panel, combo, y, mt, ancestry, extra)
|
|
139
|
+
html = write_html(out / "REPORT.html", loaded, qc, ct, roh, roh_text, panel, combo, y, mt, ancestry, input_name=inp.name, extra=extra)
|
|
140
|
+
json.dump(dict(input=str(inp.resolve()), args=[str(Path(x).resolve()) if Path(x).exists() else x for x in run_args],
|
|
141
|
+
report_html=str((out / "REPORT.html").resolve()), report_md=str((out / "REPORT.md").resolve()), glance=glance,
|
|
142
|
+
source=loaded.source, build=loaded.build, count=loaded.count, qc=qc,
|
|
143
|
+
roh_total_mb=float(roh.length_mb.sum()) if not roh.empty else 0.0, y=y, mt=mt,
|
|
144
|
+
combos=combo, ancestry=ancestry, notes=loaded.notes,
|
|
145
|
+
clinvar=dict(sites_in_clinvar=cv.get("sites_in_clinvar"), pathogenic_sites_typed=cv.get("pathogenic_sites_typed"),
|
|
146
|
+
hits=(cv["hits"].to_dict("records") if cv.get("hits") is not None and not cv["hits"].empty else [])),
|
|
147
|
+
pharmcat=dict(stats={k: v for k, v in pc.get("stats", {}).items() if k != "genes"}, error=pc.get("error"),
|
|
148
|
+
calls=(pc["calls"].to_dict("records") if pc.get("calls") is not None and not pc["calls"].empty else []))),
|
|
149
|
+
open(out / "summary.json", "w"), indent=1, default=str)
|
|
150
|
+
print(f"\nReport: {html}\n {rep}", file=sys.stderr)
|
|
151
|
+
if y.get("haplogroup"):
|
|
152
|
+
print(f"Y: {y['haplogroup']} ", end="", file=sys.stderr)
|
|
153
|
+
if mt.get("haplogroup"):
|
|
154
|
+
print(f"MT: {mt['haplogroup']}", end="", file=sys.stderr)
|
|
155
|
+
print(file=sys.stderr)
|
gnomancer/clinvar.py
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""Scan every typed site against ClinVar (GRCh37 VCF) and report pathogenic / likely pathogenic alleles carried.
|
|
2
|
+
|
|
3
|
+
Why this matters: the curated panel covers ~110 sites; consumer chips type several thousand sites that ClinVar
|
|
4
|
+
classifies. This finds the rest. Why to be careful: arrays have a high false-positive rate at rare sites
|
|
5
|
+
(Tandy-Connor et al. 2018, Genetics in Medicine, doi:10.1038/gim.2018.38: 40% of variants from consumer raw data
|
|
6
|
+
were false positives on clinical confirmation), so every hit here is "worth confirming with a clinical test",
|
|
7
|
+
never a diagnosis.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import gzip
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
import pandas as pd
|
|
15
|
+
|
|
16
|
+
from .paths import tool
|
|
17
|
+
|
|
18
|
+
DEFAULT_VCF = tool("clinvar", "clinvar_GRCh37.vcf.gz")
|
|
19
|
+
PATHOGENIC = ("Pathogenic", "Likely_pathogenic")
|
|
20
|
+
STAR = {"practice_guideline": 4, "reviewed_by_expert_panel": 3, "criteria_provided,_multiple_submitters,_no_conflicts": 2,
|
|
21
|
+
"criteria_provided,_single_submitter": 1, "criteria_provided,_conflicting_classifications": 1,
|
|
22
|
+
"criteria_provided,_conflicting_interpretations": 1, "no_assertion_criteria_provided": 0, "no_classification_provided": 0}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _conditions(raw: str, limit: int = 4) -> str:
|
|
26
|
+
"""'Disease_A|not_provided|Disease_B' -> 'Disease A; Disease B' (deduplicated, generic entries dropped, at most `limit`)."""
|
|
27
|
+
seen, out = set(), []
|
|
28
|
+
for c in raw.replace("_", " ").split("|"):
|
|
29
|
+
c = c.strip()
|
|
30
|
+
if not c or c.lower() in ("not provided", "not specified", "see cases") or c in seen:
|
|
31
|
+
continue
|
|
32
|
+
seen.add(c)
|
|
33
|
+
out.append(c)
|
|
34
|
+
return "; ".join(out[:limit]) + (f" (+{len(out) - limit} more)" if len(out) > limit else "")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _info(s: str) -> dict:
|
|
38
|
+
d = {}
|
|
39
|
+
for kv in s.split(";"):
|
|
40
|
+
if "=" in kv:
|
|
41
|
+
k, v = kv.split("=", 1)
|
|
42
|
+
d[k] = v
|
|
43
|
+
return d
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def scan(df: pd.DataFrame, vcf: Path = DEFAULT_VCF) -> dict:
|
|
47
|
+
"""df: normalized SNP table (chrom, pos, genotype). Returns dict with hits table and coverage stats."""
|
|
48
|
+
res = dict(available=vcf.exists(), vcf=str(vcf), sites_in_clinvar=0, pathogenic_sites_typed=0, hits=pd.DataFrame(), note="")
|
|
49
|
+
if not vcf.exists():
|
|
50
|
+
res["note"] = "ClinVar VCF not found; run `gnomancer setup` (downloads ~200 MB from NCBI)."
|
|
51
|
+
return res
|
|
52
|
+
called = df[df.genotype.notna()]
|
|
53
|
+
key = {}
|
|
54
|
+
for chrom, pos, gt in zip(called.chrom, called.pos, called.genotype):
|
|
55
|
+
key[(chrom, int(pos))] = gt
|
|
56
|
+
hits = []
|
|
57
|
+
n_in = n_path = 0
|
|
58
|
+
with gzip.open(vcf, "rt") as f:
|
|
59
|
+
for line in f:
|
|
60
|
+
if line[0] == "#":
|
|
61
|
+
continue
|
|
62
|
+
p = line.rstrip("\n").split("\t", 8)
|
|
63
|
+
chrom = p[0]
|
|
64
|
+
if chrom == "MT":
|
|
65
|
+
chrom = "MT"
|
|
66
|
+
k = (chrom, int(p[1]))
|
|
67
|
+
gt = key.get(k)
|
|
68
|
+
if gt is None:
|
|
69
|
+
continue
|
|
70
|
+
n_in += 1
|
|
71
|
+
info = _info(p[7])
|
|
72
|
+
sig = info.get("CLNSIG", "")
|
|
73
|
+
if not any(s in sig for s in PATHOGENIC) or sig.startswith("Benign") or sig.startswith("Likely_benign"):
|
|
74
|
+
continue
|
|
75
|
+
n_path += 1
|
|
76
|
+
ref, alts = p[3], p[4].split(",")
|
|
77
|
+
if len(ref) != 1 or any(len(a) != 1 for a in alts):
|
|
78
|
+
continue # indels are not reliably comparable to array I/D calls
|
|
79
|
+
carried = [a for a in gt if a in alts]
|
|
80
|
+
if not carried:
|
|
81
|
+
continue
|
|
82
|
+
if any(a not in alts and a != ref for a in gt):
|
|
83
|
+
continue # allele mismatch (likely strand issue); do not report
|
|
84
|
+
zyg = "homozygous" if len(gt) == 2 and gt[0] == gt[1] else ("hemizygous" if len(gt) == 1 else "heterozygous")
|
|
85
|
+
rev = info.get("CLNREVSTAT", "")
|
|
86
|
+
# Allele frequency of the ALT allele, from whichever population resource ClinVar carries.
|
|
87
|
+
af = None
|
|
88
|
+
for k_ in ("AF_EXAC", "AF_TGP", "AF_ESP"):
|
|
89
|
+
if k_ in info:
|
|
90
|
+
try:
|
|
91
|
+
af = max(float(x) for x in info[k_].split(","))
|
|
92
|
+
except ValueError:
|
|
93
|
+
pass
|
|
94
|
+
break
|
|
95
|
+
flags = []
|
|
96
|
+
ambiguous = {ref, alts[0]} in ({"A", "T"}, {"C", "G"})
|
|
97
|
+
if ambiguous:
|
|
98
|
+
flags.append("strand-ambiguous SNP (A/T or C/G): a homozygous-reference call reported on the other strand looks exactly like this")
|
|
99
|
+
if af is not None and af >= 0.05:
|
|
100
|
+
flags.append(f"ALT allele is common (AF {af:.1%}): classification is likely outdated or low-penetrance")
|
|
101
|
+
if zyg != "heterozygous" and (af is None or af < 0.01):
|
|
102
|
+
flags.append("homozygous for a rare allele: statistically far more likely a genotyping/strand artifact than a true homozygote")
|
|
103
|
+
if "conflicting" in rev:
|
|
104
|
+
flags.append("submitters disagree on classification")
|
|
105
|
+
confidence = "low" if (ambiguous or (zyg != "heterozygous" and (af is None or af < 0.01)) or STAR.get(rev, 0) == 0) else ("medium" if (af or 0) >= 0.05 else "high")
|
|
106
|
+
hits.append(dict(rsid=("rs" + info["RS"]) if info.get("RS") else p[2], chrom=chrom, pos=k[1], genotype=gt,
|
|
107
|
+
ref=ref, alt=",".join(alts), zygosity=zyg, gene=info.get("GENEINFO", "").split(":")[0],
|
|
108
|
+
significance=sig.replace("_", " "), review=rev.replace("_", " "), stars=STAR.get(rev, 0),
|
|
109
|
+
condition=_conditions(info.get("CLNDN", "")),
|
|
110
|
+
variant=info.get("CLNHGVS", ""), alt_af=af, confidence=confidence, flags="; ".join(flags)))
|
|
111
|
+
res["sites_in_clinvar"], res["pathogenic_sites_typed"] = n_in, n_path
|
|
112
|
+
out = pd.DataFrame(hits)
|
|
113
|
+
if not out.empty:
|
|
114
|
+
out["conf_rank"] = out.confidence.map({"high": 0, "medium": 1, "low": 2})
|
|
115
|
+
out = out.sort_values(["conf_rank", "stars"], ascending=[True, False]).drop(columns="conf_rank")
|
|
116
|
+
res["hits"] = out
|
|
117
|
+
return res
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def interpret(res: dict) -> str:
|
|
121
|
+
if not res["available"]:
|
|
122
|
+
return res["note"]
|
|
123
|
+
h = res["hits"]
|
|
124
|
+
base = (f"{res['sites_in_clinvar']:,} typed sites have a ClinVar record; {res['pathogenic_sites_typed']:,} of those are "
|
|
125
|
+
f"classified pathogenic or likely pathogenic for at least one submitter. ")
|
|
126
|
+
if h.empty:
|
|
127
|
+
return base + "No pathogenic or likely-pathogenic alternate allele was called at any of them."
|
|
128
|
+
hi = h[h.confidence == "high"]
|
|
129
|
+
return base + (f"{len(h)} site(s) carry a pathogenic/likely-pathogenic allele; {len(hi)} pass the plausibility checks "
|
|
130
|
+
"(heterozygous or common, unambiguous strand, reviewed). The rest are flagged as probable artifacts. "
|
|
131
|
+
"Array calls at rare sites are often wrong: when a clinical lab re-tested variants reported in consumer raw data, "
|
|
132
|
+
"40% were false positives (Tandy-Connor et al., Genetics in Medicine 2018, doi:10.1038/gim.2018.38). Treat every row as "
|
|
133
|
+
"'confirm with a clinical test', not as a diagnosis. Heterozygous hits for recessive conditions are carrier states.")
|
gnomancer/context.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Short, population-level context for Y and mtDNA haplogroups (data/haplogroup_context.tsv)."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import csv
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from .paths import DATA as _DATA
|
|
8
|
+
|
|
9
|
+
DATA = _DATA / "haplogroup_context.tsv"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _rows():
|
|
13
|
+
with open(DATA, newline="") as f:
|
|
14
|
+
lines = [l for l in f if l.strip() and not l.startswith("#")]
|
|
15
|
+
return list(csv.DictReader(lines, delimiter="\t"))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def lookup(kind: str, *labels: str) -> list[dict]:
|
|
19
|
+
"""Return context rows for a haplogroup, most specific first.
|
|
20
|
+
|
|
21
|
+
kind: 'Y' or 'MT'. labels: any names for the call (e.g. short 'R-M269' and long 'R1b1a2a1a2').
|
|
22
|
+
Matching is by prefix on each label; results are the chain of matching prefixes, longest first,
|
|
23
|
+
so a report can show the lineage from broad to specific.
|
|
24
|
+
"""
|
|
25
|
+
hits = {}
|
|
26
|
+
for r in _rows():
|
|
27
|
+
if r["type"] != kind:
|
|
28
|
+
continue
|
|
29
|
+
for lab in labels:
|
|
30
|
+
if lab and (lab == r["prefix"] or lab.startswith(r["prefix"])):
|
|
31
|
+
hits.setdefault(r["name"], r) # one entry per lineage name, whichever prefix matched first
|
|
32
|
+
return sorted(hits.values(), key=lambda r: -int(r.get("depth") or len(r["prefix"])))
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Population-level context for haplogroups. Matched by prefix against the caller's labels
|
|
2
|
+
# (Y: ISOGG 2016 long form as emitted by yhaplo, and the short SNP form; MT: PhyloTree 17 name).
|
|
3
|
+
# Keep entries short, hedged, and about populations, never individuals.
|
|
4
|
+
type prefix depth name text
|
|
5
|
+
Y A 1 Haplogroup A The deepest branches of the human Y tree, found mainly in Southern and Eastern Africa (Khoisan, Ethiopian and Sudanese groups).
|
|
6
|
+
Y B 1 Haplogroup B An old African lineage, most common among Central African hunter-gatherer groups and in East Africa.
|
|
7
|
+
Y C 1 Haplogroup C Spread across Asia, Oceania and the Americas: C-M217 is common in Mongolia, Siberia and East Asia; C-M38 in New Guinea and Melanesia; C-M130 branches reach Australia.
|
|
8
|
+
Y D 1 Haplogroup D Found mainly in Japan (D-M55, including Ainu), Tibet and the Andaman Islands.
|
|
9
|
+
Y E 1 Haplogroup E The dominant African paternal lineage, with branches that also spread into the Near East and around the Mediterranean.
|
|
10
|
+
Y E1b1a 2 E-M2 The lineage carried by the Bantu expansion: the majority Y lineage across West, Central and Southern Africa and in the African diaspora.
|
|
11
|
+
Y E1b1b 2 E-M215 / E-M35 Originated in East Africa and spread to North Africa, the Near East and Southern Europe; a major lineage in Ethiopia, Somalia, the Maghreb, Greece and the Balkans.
|
|
12
|
+
Y E1b1b1a 3 E-M78 Common from Egypt and Sudan through the Balkans and Southern Europe; E-V13 is a signature Balkan branch.
|
|
13
|
+
Y E1b1b1b1 3 E-M81 The characteristic Berber lineage of the Maghreb, also present in Iberia.
|
|
14
|
+
Y E1b1b1b2 3 E-M123 / E-M34 A Near-Eastern and East-Mediterranean branch: frequent in Ethiopia, the Levant, Anatolia and Arabia, a well-known component (around a tenth) of Ashkenazi, Sephardic and Mizrahi Jewish paternal lineages, and present at low frequency in Italy, Iberia and the Balkans.
|
|
15
|
+
Y E1b1b1b2a1a1 4 E-M84 The main sub-branch of E-M34 (YFull: E-M84). Frequent in Ethiopia and Eritrea, the Levant, Arabia and Anatolia; one of the characteristic lineages of Jewish communities from all three main diasporas; sporadic in Southern Europe.
|
|
16
|
+
Y E-M84 4 E-M84 The main sub-branch of E-M34. Frequent in Ethiopia and Eritrea, the Levant, Arabia and Anatolia; one of the characteristic lineages of Jewish communities from all three main diasporas; sporadic in Southern Europe.
|
|
17
|
+
Y E-L795 5 E-L795 A branch within E-M84 (FamilyTreeDNA naming), found in the Levant, Arabia and among Jewish lineages.
|
|
18
|
+
Y G 1 Haplogroup G Peaks in the Caucasus and Anatolia; carried by early Neolithic farmers into Europe (the Tyrolean Iceman was G2a), today scattered at low frequency across Europe and the Near East.
|
|
19
|
+
Y H 1 Haplogroup H Mostly South Asian; H1a1 is the main lineage of the Roma, reflecting their Indian origin.
|
|
20
|
+
Y I 1 Haplogroup I A European lineage present since the Palaeolithic, with little presence outside Europe.
|
|
21
|
+
Y I1 2 I-M253 Concentrated in Scandinavia and Germanic-speaking regions; strongly associated with Norse and Anglo-Saxon migrations.
|
|
22
|
+
Y I2 2 I-M438 I2a1 peaks in the Balkans and Sardinia; I2a2 is found across Northwest Europe including Germany, Britain and Ireland.
|
|
23
|
+
Y J 1 Haplogroup J Originated in the Near East and spread with Neolithic farming and later movements across the Mediterranean, Caucasus and South Asia.
|
|
24
|
+
Y J1 2 J-M267 Most frequent in Arabia, the Levant and the Caucasus (Dagestan); the J-P58 branch is associated with Semitic-speaking populations.
|
|
25
|
+
Y J2 2 J-M172 Peaks in the Fertile Crescent, Anatolia, the Caucasus and Iran; common around the Mediterranean (Italy, Greece, Balkans) and in South Asia.
|
|
26
|
+
Y L 1 Haplogroup L Mainly South Asian, especially Pakistan and western India, with pockets in the Near East.
|
|
27
|
+
Y N 1 Haplogroup N Spread from Siberia westward with Uralic speakers; the main lineage in Finland, the Baltic states and northern Russia.
|
|
28
|
+
Y O 1 Haplogroup O The dominant lineage of East and Southeast Asia: O-M122 (Han Chinese and neighbours), O-M119 (coastal China, Taiwan, Austronesians), O-M95 (Southeast Asia).
|
|
29
|
+
Y Q 1 Haplogroup Q Siberian in origin; Q-M3 is the principal Native American paternal lineage, and other branches are found in Siberia and Central Asia.
|
|
30
|
+
Y R 1 Haplogroup R A widespread Eurasian lineage whose main branches dominate Europe, Central Asia and South Asia.
|
|
31
|
+
Y R1a 2 R-M420 Most common in Eastern Europe (Poland, Russia, Ukraine), Central Asia and northern India; associated with Bronze Age steppe migrations.
|
|
32
|
+
Y R1b 2 R-M343 The most common paternal lineage in Western Europe (peaking in Ireland, Wales, the Basque Country); the R-V88 branch is found in Central Africa.
|
|
33
|
+
Y R1b1a2 3 R-M269 The main Western European branch, carried by Bronze Age migrations; R-U106 is typical of Germanic regions, R-P312 and R-L21 of Atlantic Europe, R-U152 of the Alpine region and Italy.
|
|
34
|
+
Y R2 2 R-M479 Mainly South Asian.
|
|
35
|
+
Y T 1 Haplogroup T A scattered lineage with pockets in the Near East, East Africa (Somalia), Sardinia and parts of Iberia.
|
|
36
|
+
MT L0 2 Haplogroup L0 Among the oldest maternal lineages, concentrated in Southern Africa (Khoisan) and East Africa.
|
|
37
|
+
MT L1 2 Haplogroup L1 A deep African lineage found mainly in Central and West Africa.
|
|
38
|
+
MT L2 2 Haplogroup L2 Widespread across Sub-Saharan Africa and the most common maternal lineage among African Americans.
|
|
39
|
+
MT L3 2 Haplogroup L3 East African in origin and the ancestor of every non-African maternal lineage; also common across Africa.
|
|
40
|
+
MT M 1 Haplogroup M One of the two founding non-African lineages, now concentrated in South Asia, East Asia and among Native Americans (via branches C and D).
|
|
41
|
+
MT D 1 Haplogroup D An East Asian and Siberian lineage; D1 and D4h3 are Native American founder lineages.
|
|
42
|
+
MT C 1 Haplogroup C Found across Siberia, Central Asia and East Asia, and a Native American founder lineage (C1).
|
|
43
|
+
MT N 1 Haplogroup N The other founding non-African lineage; its branches cover Europe, the Near East, Asia and the Americas.
|
|
44
|
+
MT A 1 Haplogroup A East Asian and Siberian, and one of the main Native American founder lineages (A2).
|
|
45
|
+
MT B 1 Haplogroup B East and Southeast Asian; B4 spread with Austronesians to Polynesia and B2 is a Native American founder lineage.
|
|
46
|
+
MT I 1 Haplogroup I A minor European and Near Eastern lineage at a few percent frequency.
|
|
47
|
+
MT W 1 Haplogroup W A minor lineage of Europe, the Near East and South Asia.
|
|
48
|
+
MT X 1 Haplogroup X A rare lineage in Europe and the Near East; the X2a branch is a Native American founder lineage.
|
|
49
|
+
MT R 1 Haplogroup R A large branch of N whose descendants include most European lineages.
|
|
50
|
+
MT F 1 Haplogroup F Common in Southeast Asia and southern China.
|
|
51
|
+
MT U 1 Haplogroup U An old West Eurasian lineage with branches in Europe, the Near East, North Africa and South Asia.
|
|
52
|
+
MT U5 2 Haplogroup U5 The characteristic lineage of European hunter-gatherers; today most frequent in Finland and the Saami.
|
|
53
|
+
MT U6 2 Haplogroup U6 Mainly North African (Berber populations) and Iberian.
|
|
54
|
+
MT K 1 Haplogroup K A branch of U8 common across Europe and the Near East; three K sub-lineages account for about a third of Ashkenazi maternal lines.
|
|
55
|
+
MT HV 1 Haplogroup HV The parent of H and V, found across Europe, the Near East and the Caucasus.
|
|
56
|
+
MT H 1 Haplogroup H The most common maternal lineage in Europe (around 40%), also frequent in the Near East and North Africa; it spread widely after the last Ice Age.
|
|
57
|
+
MT H1 2 Haplogroup H1 The largest H branch and the most common maternal lineage in Western Europe; it peaks in Iberia and the Basque Country and is also found in North Africa and the Near East.
|
|
58
|
+
MT H2 2 Haplogroup H2 Found across Europe and the Caucasus; H2a is more frequent in Eastern Europe.
|
|
59
|
+
MT H3 2 Haplogroup H3 A Western European branch with a peak in Iberia and Western France.
|
|
60
|
+
MT H5 2 Haplogroup H5 Found across Europe with higher frequency in the Balkans and Central Europe.
|
|
61
|
+
MT H13 2 Haplogroup H13 Most frequent in the Caucasus and Near East, with a presence in Sardinia.
|
|
62
|
+
MT V 1 Haplogroup V A sister of H found across Europe, with high frequency among the Saami, in Iberia and the Basque Country.
|
|
63
|
+
MT J 1 Haplogroup J Spread from the Near East into Europe with Neolithic farmers; around a tenth of Europeans, higher in the Near East.
|
|
64
|
+
MT J1 2 Haplogroup J1 The main European J branch (J1c is the most common form in Europe).
|
|
65
|
+
MT J2 2 Haplogroup J2 Found around the Mediterranean and the Near East.
|
|
66
|
+
MT T 1 Haplogroup T A Near Eastern and European lineage at about a tenth of the population in parts of Europe; associated with early farming and pastoralism.
|
|
67
|
+
MT T2 2 Haplogroup T2 The more common T branch in Europe, especially Northern and Central Europe.
|
|
68
|
+
MT N1 2 Haplogroup N1 Includes N1b, common among Ashkenazi Jews, and N1a, carried by early Neolithic farmers into Europe.
|
|
69
|
+
MT G 1 Haplogroup G Mainly East Asian and Siberian, including Japan and Kamchatka.
|
|
70
|
+
MT Z 1 Haplogroup Z Found in Siberia, Central Asia and among the Saami.
|
|
71
|
+
MT Q 1 Haplogroup Q Found in New Guinea and Melanesia.
|
|
72
|
+
MT P 1 Haplogroup P Found in Australia and New Guinea.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Curated marker panel. Alleles are on the GRCh37 forward strand (what all major vendors report).
|
|
2
|
+
# category: ancestry | trait | health | carrier | pgx. effect = the allele being counted.
|
|
3
|
+
# interp0/1/2 = text for 0/1/2 copies of the effect allele (optional).
|
|
4
|
+
rsid category gene label ref effect interp0 interp1 interp2 note
|
|
5
|
+
rs1426654 ancestry SLC24A5 Skin pigmentation A111T G A ancestral allele on both copies (typical of Sub-Saharan African and East Asian ancestry) one light-skin allele light-skin allele on both copies (near-fixed in Europe, West and South Asia)
|
|
6
|
+
rs16891982 ancestry SLC45A2 Skin/hair pigmentation L374F C G ancestral on both copies one European light-pigmentation allele European light-pigmentation allele on both copies
|
|
7
|
+
rs3827760 ancestry EDAR V370A hair thickness / shovel incisors A G ancestral; no East Asian/Native American hair-thickness allele one copy of the East Asian/Native American allele homozygous for the East Asian/Native American allele
|
|
8
|
+
rs2814778 ancestry ACKR1 (DARC) Duffy null (FY*O) T C Duffy-positive one Duffy-null allele (common in West/Central African ancestry) Duffy-null: resistant to P. vivax malaria; benign lower neutrophil counts
|
|
9
|
+
rs4988235 ancestry LCT Lactase persistence -13910 G A non-persistent at this site persistent (dominant) persistent the European persistence allele; other populations use different alleles
|
|
10
|
+
rs182549 ancestry LCT Lactase persistence -22018 C T non-persistent at this site persistent (linked to -13910) persistent
|
|
11
|
+
rs671 ancestry ALDH2 ALDH2*2 alcohol flush G A no flush allele flush reaction, reduced acetaldehyde clearance (common in East Asia) strong flush; alcohol poorly tolerated
|
|
12
|
+
rs1229984 ancestry ADH1B ADH1B*2 (His48) C T *1/*1 typical of Europe and Africa one fast-metabolizing *2 allele *2/*2 fast alcohol metabolism (common in East Asia)
|
|
13
|
+
rs12913832 trait HERC2 Eye color (main determinant) A G brown eyes likely brown or hazel likely, green possible blue or grey eyes likely
|
|
14
|
+
rs1800407 trait OCA2 Eye color modifier R419Q C T no modifier green/hazel modifier present homozygous modifier
|
|
15
|
+
rs12896399 trait SLC24A4 Eye/hair color G T darker-associated intermediate lighter-associated
|
|
16
|
+
rs1042602 trait TYR S192Y pigmentation / freckling C A no lighter allele one lighter/freckling allele lighter skin, freckling more likely
|
|
17
|
+
rs1393350 trait TYR Eye/hair color G A darker-associated intermediate lighter-associated
|
|
18
|
+
rs12203592 trait IRF4 Freckles, lighter hair, sun sensitivity C T no freckle allele one freckle / lighter-hair allele freckles and sun sensitivity likely
|
|
19
|
+
rs1805007 trait MC1R R151C red hair C T no variant red-hair carrier (R allele) red hair likely
|
|
20
|
+
rs1805008 trait MC1R R160W red hair C T no variant red-hair carrier (R allele) red hair likely
|
|
21
|
+
rs1805009 trait MC1R D294H red hair G C no variant red-hair carrier (R allele) red hair likely
|
|
22
|
+
rs1805006 trait MC1R D84E red hair C A no variant red-hair carrier (R allele) red hair likely
|
|
23
|
+
rs11547464 trait MC1R R142H red hair G A no variant red-hair carrier (R allele) red hair likely
|
|
24
|
+
rs1110400 trait MC1R I155T red hair T C no variant red-hair carrier (R allele) red hair likely
|
|
25
|
+
rs885479 trait MC1R R163Q (weak variant) G A no variant one weak r allele homozygous weak variant (common in East Asia)
|
|
26
|
+
rs11803731 trait TCHH Hair curl (European) T A curlier-associated intermediate straight-associated
|
|
27
|
+
rs17822931 trait ABCC11 Earwax type / underarm odor C T wet earwax, typical body odor wet earwax (C is dominant) dry earwax, little underarm odor
|
|
28
|
+
rs4481887 trait OR2M7 region Asparagus metabolite smell G A less likely to smell it intermediate likely smells asparagus metabolites
|
|
29
|
+
rs10427255 trait ZEB2 region Photic sneeze reflex T C less likely intermediate more likely to sneeze in bright light
|
|
30
|
+
rs1815739 trait ACTN3 R577X sprint/power muscle C T RR: two working copies, power-leaning RX: mixed XX: no alpha-actinin-3, endurance-leaning (~18% of Europeans)
|
|
31
|
+
rs762551 trait CYP1A2 Caffeine metabolism *1F A C AA: fast caffeine metabolizer intermediate slow caffeine metabolizer
|
|
32
|
+
rs2472297 trait CYP1A1/2 region Caffeine intake tendency C T lower-intake alleles intermediate higher-intake alleles
|
|
33
|
+
rs4410790 trait AHR Caffeine intake tendency T C lower-intake alleles intermediate higher-intake alleles
|
|
34
|
+
rs713598 trait TAS2R38 Bitter taste PTC (A49P) C G non-taster allele on both copies taster taster see combined TAS2R38 reading
|
|
35
|
+
rs1726866 trait TAS2R38 Bitter taste (V262A) A G non-taster allele on both copies taster taster see combined TAS2R38 reading
|
|
36
|
+
rs10246939 trait TAS2R38 Bitter taste (I296V) T C non-taster allele on both copies taster taster see combined TAS2R38 reading
|
|
37
|
+
rs72921001 trait OR6A2 Cilantro soapy taste A C no soapy-taste allele one soapy-taste allele cilantro likely tastes soapy
|
|
38
|
+
rs9939609 trait FTO BMI/obesity risk T A no risk allele one risk allele (~+1.2 kg on average) two risk alleles (~+3 kg on average)
|
|
39
|
+
rs17782313 trait MC4R BMI T C no risk allele one risk allele two risk alleles
|
|
40
|
+
rs16969968 trait CHRNA5 Nicotine dependence D398N G A no risk allele one risk allele: heavier smoking if a smoker two risk alleles
|
|
41
|
+
rs4680 trait COMT Val158Met G A Val/Val: higher COMT activity Val/Met Met/Met: lower COMT activity popular but weak-effect marker
|
|
42
|
+
rs6265 trait BDNF Val66Met C T Val/Val (most common) Val/Met Met/Met weak-effect marker
|
|
43
|
+
rs1799971 trait OPRM1 A118G A G reference one G allele two G alleles weak-effect marker
|
|
44
|
+
rs601338 trait FUT2 Secretor status W154X G A secretor secretor (one non-secretor allele) non-secretor: resistant to common norovirus strains; altered gut flora
|
|
45
|
+
rs2180439 trait PAX1 region Male pattern hair loss T C no risk allele one risk allele two risk alleles
|
|
46
|
+
rs53576 trait OXTR Oxytocin receptor G A no variant allele one variant allele two variant alleles weak-effect marker, popular online but poorly replicated
|
|
47
|
+
rs1800497 trait ANKK1/DRD2 TaqIA G A A2/A2 A1/A2 A1/A1 weak-effect marker
|
|
48
|
+
rs8176719 trait ABO O allele (261delG) I D no O allele one O allele blood group O see combined ABO reading
|
|
49
|
+
rs8176746 trait ABO B allele G T no B allele one B allele B/B see combined ABO reading
|
|
50
|
+
rs1050828 health G6PD G6PD A- (V68M) C T no deficiency allele carrier / affected if male deficient X-linked; hemizygous in males
|
|
51
|
+
rs429358 health APOE e4-defining site (C112R) T C no e4 allele one e4 allele two e4 alleles see combined APOE reading
|
|
52
|
+
rs7412 health APOE e2-defining site (R158C) C T no e2 allele one e2 allele two e2 alleles see combined APOE reading
|
|
53
|
+
rs6025 health F5 Factor V Leiden R506Q C T negative heterozygous: ~5x venous thrombosis risk; relevant for surgery, estrogen, long flights homozygous: substantially elevated clotting risk
|
|
54
|
+
rs1799963 health F2 Prothrombin G20210A G A negative heterozygous: ~2-3x venous thrombosis risk homozygous
|
|
55
|
+
rs1800562 health HFE Hemochromatosis C282Y G A negative carrier; iron overload uncommon unless compound heterozygous with H63D C282Y homozygous: high risk of iron overload, check ferritin/transferrin saturation
|
|
56
|
+
rs1799945 health HFE Hemochromatosis H63D C G negative carrier; little risk alone H63D homozygous: mild iron overload possible
|
|
57
|
+
rs1800730 health HFE S65C A T negative carrier homozygous
|
|
58
|
+
rs1801133 health MTHFR C677T (A222V) G A normal activity one T allele, ~65% activity, usually no consequence TT: ~30% activity; mildly higher homocysteine if folate is low widely over-interpreted online
|
|
59
|
+
rs1801131 health MTHFR A1298C T G normal heterozygous, benign homozygous, little effect alone
|
|
60
|
+
rs2187668 health HLA-DQA1 DQ2.5 tag (celiac) C T no DQ2.5 DQ2.5 present (most celiac patients carry it; most carriers never develop it) DQ2.5 homozygous
|
|
61
|
+
rs7454108 health HLA-DQB1 DQ8 tag (celiac) T C no DQ8 DQ8 present DQ8 homozygous
|
|
62
|
+
rs3135388 health HLA-DRB1 DRB1*15:01 tag (multiple sclerosis) G A non-carrier carrier (~3x MS odds, still low absolute risk) homozygous
|
|
63
|
+
rs2476601 health PTPN22 R620W autoimmunity G A negative one risk allele (RA, T1D, thyroid autoimmunity) two risk alleles
|
|
64
|
+
rs2066844 health NOD2 R702W (Crohn's) C T negative carrier homozygous
|
|
65
|
+
rs2066845 health NOD2 G908R (Crohn's) G C negative carrier homozygous
|
|
66
|
+
rs7903146 health TCF7L2 Type 2 diabetes C T no risk allele one risk allele (~1.4x odds) two risk alleles (~2x odds; ~10% of Europeans) strongest common T2D variant
|
|
67
|
+
rs1061170 health CFH Y402H macular degeneration T C no risk allele one risk allele (~2.5x AMD odds) two risk alleles (~6x AMD odds) smoking interacts strongly
|
|
68
|
+
rs10490924 health ARMS2 A69S macular degeneration G T no risk allele one risk allele two risk alleles
|
|
69
|
+
rs1333049 health CDKN2B-AS1 (9p21) Coronary artery disease G C no risk haplotype one copy (~1.25x) two copies (~1.5x)
|
|
70
|
+
rs10455872 health LPA High Lp(a) tag A G no high-Lp(a) allele elevated Lp(a) likely (~2x CAD odds); a direct Lp(a) blood test is cheap homozygous
|
|
71
|
+
rs3798220 health LPA I4399M high Lp(a) T C no high-Lp(a) allele elevated Lp(a) likely homozygous
|
|
72
|
+
rs11136000 health CLU Alzheimer's (protective T) C T no protective allele one protective allele (small effect) two protective alleles
|
|
73
|
+
rs75932628 health TREM2 R47H Alzheimer's C T negative carrier (~3x AD odds) homozygous
|
|
74
|
+
rs76763715 health GBA N370S (Gaucher / Parkinson's) T C negative carrier: ~5x Parkinson's odds; Gaucher carrier Gaucher type 1 likely
|
|
75
|
+
rs34637584 health LRRK2 G2019S Parkinson's G A negative carrier: elevated Parkinson's risk (penetrance ~30% by 80) homozygous
|
|
76
|
+
rs2802292 health FOXO3 Longevity-associated T G no longevity allele one copy two copies (modest association with reaching 90+)
|
|
77
|
+
rs1800629 health TNF -308 promoter G A no variant allele one variant allele two variant alleles weak-effect marker
|
|
78
|
+
rs113993960 carrier CFTR deltaF508 cystic fibrosis I D negative CF carrier (most common CF allele) affected arrays type 1-3 CFTR sites of 2000+
|
|
79
|
+
rs333 carrier CCR5 delta32 I D negative one delta32 copy homozygous: resistant to R5-tropic HIV-1
|
|
80
|
+
rs80357906 carrier BRCA1 185delAG (Ashkenazi founder) I D negative at this site pathogenic variant present: confirm clinically homozygous
|
|
81
|
+
rs80359550 carrier BRCA2 6174delT (Ashkenazi founder) I D negative at this site pathogenic variant present: confirm clinically homozygous
|
|
82
|
+
rs11571833 carrier BRCA2 K3326X A T negative modest cancer risk increase (not a classic BRCA2 pathogenic allele) homozygous
|
|
83
|
+
rs334 carrier HBB Sickle cell HbS T A negative sickle cell trait sickle cell disease
|
|
84
|
+
rs33930165 carrier HBB HbC C T negative HbC trait HbC disease
|
|
85
|
+
rs33950507 carrier HBB HbE C T negative HbE trait HbE
|
|
86
|
+
rs1799853 pgx CYP2C9 *2 (R144C) C T no *2 one *2: reduced warfarin/NSAID/phenytoin metabolism *2/*2
|
|
87
|
+
rs1057910 pgx CYP2C9 *3 (I359L) A C no *3 one *3: markedly reduced metabolism *3/*3 poor metabolizer
|
|
88
|
+
rs28371686 pgx CYP2C9 *5 C G no *5 one *5 (African ancestry) *5/*5
|
|
89
|
+
rs9332131 pgx CYP2C9 *6 I D no *6 one *6 *6/*6
|
|
90
|
+
rs28371685 pgx CYP2C9 *11 C T no *11 one *11 *11/*11
|
|
91
|
+
rs4244285 pgx CYP2C19 *2 (loss of function) G A no *2 one *2: intermediate metabolizer (clopidogrel less effective) *2/*2 poor metabolizer
|
|
92
|
+
rs4986893 pgx CYP2C19 *3 (loss of function) G A no *3 one *3 *3/*3 mostly East Asian
|
|
93
|
+
rs12248560 pgx CYP2C19 *17 (increased function) C T no *17 one *17: rapid metabolizer *17/*17 ultrarapid
|
|
94
|
+
rs9923231 pgx VKORC1 -1639G>A warfarin sensitivity C T normal warfarin dose requirement intermediate: lower warfarin dose high sensitivity: low warfarin dose
|
|
95
|
+
rs9934438 pgx VKORC1 1173C>T (proxy for -1639) G A normal intermediate sensitive in near-perfect LD with rs9923231
|
|
96
|
+
rs2108622 pgx CYP4F2 V433M C T normal slightly higher warfarin dose higher warfarin dose
|
|
97
|
+
rs3892097 pgx CYP2D6 *4 (null) C T no *4 one *4 allele *4/*4 poor metabolizer CNV not detectable on arrays
|
|
98
|
+
rs1065852 pgx CYP2D6 *10 (reduced) / also on *4 G A no *10 one reduced-function allele two reduced-function alleles
|
|
99
|
+
rs28371725 pgx CYP2D6 *41 (reduced) C T no *41 one *41 *41/*41
|
|
100
|
+
rs776746 pgx CYP3A5 *3 vs *1 (expressor) C T *3/*3 non-expressor (most Europeans; standard tacrolimus dosing) *1/*3 expressor: higher tacrolimus dose *1/*1 expressor
|
|
101
|
+
rs3745274 pgx CYP2B6 *6 (516G>T) G T *1/*1 one *6: slower efavirenz/bupropion clearance *6/*6 poor metabolizer
|
|
102
|
+
rs4149056 pgx SLCO1B1 *5 (V174A) statin myopathy T C normal statin transport one C: ~4x simvastatin myopathy risk two C: ~17x; avoid high-dose simvastatin
|
|
103
|
+
rs2231142 pgx ABCG2 Q141K G T normal reduced transport: higher rosuvastatin/allopurinol exposure homozygous reduced
|
|
104
|
+
rs3918290 pgx DPYD *2A (IVS14+1G>A) C T normal DPD deficiency carrier: fluoropyrimidine (5-FU, capecitabine) toxicity risk, dose reduction needed DPD deficient: avoid fluoropyrimidines
|
|
105
|
+
rs67376798 pgx DPYD D949V T A normal reduced DPD activity homozygous
|
|
106
|
+
rs887829 pgx UGT1A1 *28 proxy (Gilbert) C T no *28 one *28 *28/*28 Gilbert syndrome: irinotecan toxicity, benign high bilirubin
|
|
107
|
+
rs4148323 pgx UGT1A1 *6 (G71R) G A no *6 one *6 *6/*6 mostly East Asian
|
|
108
|
+
rs1801280 pgx NAT2 *5 (I114T) T C no *5 one slow allele slow combine with *6/*7
|
|
109
|
+
rs1799930 pgx NAT2 *6 (R197Q) G A no *6 one slow allele slow
|
|
110
|
+
rs1799931 pgx NAT2 *7 (G286E) G A no *7 one slow allele slow
|
|
111
|
+
rs1495741 pgx NAT2 acetylator tag A G slow acetylator (tag) intermediate rapid acetylator (tag)
|
|
112
|
+
rs1800460 pgx TPMT *3B C T no *3B one *3B (thiopurine dose reduction) *3B/*3B
|
|
113
|
+
rs1142345 pgx TPMT *3C T C no *3C one *3C (thiopurine dose reduction) *3C/*3C
|
|
114
|
+
rs2395029 pgx HCP5 HLA-B*57:01 tag T G negative HLA-B*57:01 carrier: abacavir hypersensitivity, avoid homozygous
|
|
115
|
+
rs1800566 pgx NQO1 P187S (*2) G A normal one null allele NQO1 null
|