Skip to content

Commit 4aa5882

Browse files
committed
implement pedrel
1 parent a64cb89 commit 4aa5882

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed

CHANGES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
v0.3.1
2+
======
3+
+ add new `pedrel` command to report kinship value for samples from a pedigree file
4+
15
v0.3.0
26
======
37
+ fix compilation with nim > 2 and some sex inference stuff

src/somalier.nim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import ./somalierpkg/relate
1313
import ./somalierpkg/findsites
1414
import ./somalierpkg/ancestry
1515
import ./somalierpkg/depthview
16+
import ./somalierpkg/pedrel
1617
import strformat
1718
import argparse
1819
import strutils
@@ -254,6 +255,7 @@ proc main() =
254255
"ancestry": pair(f:ancestry_main, description: "perform ancestry prediction on a set of samples, given a set of labeled samples"),
255256
#"depthview": pair(f:depth_main, description: "plot per-chromosome depth for each sample for quick quality-control"),
256257
"find-sites": pair(f:findsites_main, description: "create a new sites.vcf.gz file from a population VCF (this is rarely needed)."),
258+
"pedrel": pair(f:pedrel_main, description: "report kinship calculated from a pedigree file."),
257259
}.toOrderedTable
258260

259261

src/somalierpkg/pedrel.nim

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import strutils
2+
import strformat
3+
import argparse
4+
import pedfile
5+
import sequtils
6+
import algorithm
7+
8+
proc pedrel_main*() =
9+
var argv = commandLineParams()
10+
if argv[0] == "pedrel":
11+
argv = argv[1..argv.high]
12+
13+
var p = newParser("somalier pedrel"):
14+
help("report pairwise relationships from pedigree file")
15+
option("-o", "--output", help="output file path", default="stdout")
16+
option("-m", "--min-relatedness", help="minimum relatedness to report", default="0.01")
17+
arg("pedfile", help="pedigry (fam) file path")
18+
19+
let opts = p.parse(argv)
20+
if opts.help:
21+
quit 0
22+
23+
if opts.pedfile == "":
24+
echo p.help
25+
quit "[somalier] pedfile argument required"
26+
27+
# Parse the pedigree file
28+
var samples = parse_ped(opts.pedfile)
29+
30+
let min_rel = parseFloat(opts.min_relatedness)
31+
32+
# Calculate pairwise relatedness for all sample pairs
33+
var output_file: File
34+
if opts.output == "stdout":
35+
output_file = stdout
36+
else:
37+
if not open(output_file, opts.output, fmWrite):
38+
quit "[somalier] couldn't open output file: " & opts.output
39+
40+
# Write header
41+
output_file.write_line("sample_a\tsample_b\trelatedness")
42+
43+
# Iterate through all sample pairs and report those with min_rel threshold
44+
for i in 0..<samples.len:
45+
let sampleA = samples[i]
46+
for j in (i+1)..<samples.len:
47+
let sampleB = samples[j]
48+
let rel = sampleA.relatedness(sampleB)
49+
50+
if rel > min_rel:
51+
# Ensure consistent ordering (alphabetical by sample ID)
52+
let (sample1, sample2) = if sampleA.id < sampleB.id:
53+
(sampleA.id, sampleB.id)
54+
else:
55+
(sampleB.id, sampleA.id)
56+
output_file.write_line(&"{sample1}\t{sample2}\t{rel:.6f}")
57+
58+
if opts.output != "stdout":
59+
output_file.close()
60+
stderr.write_line(&"[somalier] wrote {samples.len} sample relationships to: {opts.output}")

0 commit comments

Comments
 (0)