minimap2 0.2.30.3 → 1.2.31.0
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.
- checksums.yaml +4 -4
- data/README.md +48 -63
- data/ext/minimap2/Makefile +1 -1
- data/ext/minimap2/format.c +12 -2
- data/ext/minimap2/hit.c +19 -8
- data/ext/minimap2/ksw2_ll_sse.c +2 -2
- data/ext/minimap2/minimap.h +2 -1
- data/ext/minimap2/pe.c +7 -2
- data/ext/ruby_minimap2/extconf.rb +47 -0
- data/ext/ruby_minimap2/native_main.c +15 -0
- data/ext/ruby_minimap2/ruby_minimap2.c +1134 -0
- data/lib/minimap2/aligner.rb +66 -374
- data/lib/minimap2/alignment.rb +22 -11
- data/lib/minimap2/version.rb +2 -1
- data/lib/minimap2.rb +39 -110
- metadata +8 -89
- data/ext/Rakefile +0 -60
- data/ext/cmappy/cmappy.c +0 -134
- data/ext/cmappy/cmappy.h +0 -46
- data/ext/minimap2/FAQ.md +0 -46
- data/ext/minimap2/MANIFEST.in +0 -10
- data/ext/minimap2/Makefile.simde +0 -97
- data/ext/minimap2/NEWS.md +0 -989
- data/ext/minimap2/README.md +0 -428
- data/ext/minimap2/code_of_conduct.md +0 -30
- data/ext/minimap2/cookbook.md +0 -243
- data/ext/minimap2/minimap2.1 +0 -844
- data/ext/minimap2/misc/README.md +0 -180
- data/ext/minimap2/misc/pafcluster.js +0 -241
- data/ext/minimap2/misc/paftools.js +0 -3734
- data/ext/minimap2/pyproject.toml +0 -2
- data/ext/minimap2/python/README.rst +0 -198
- data/ext/minimap2/python/cmappy.h +0 -152
- data/ext/minimap2/python/cmappy.pxd +0 -156
- data/ext/minimap2/python/mappy.pyx +0 -289
- data/ext/minimap2/python/minimap2.py +0 -41
- data/ext/minimap2/setup.py +0 -55
- data/ext/minimap2/test/MT-human.fa +0 -278
- data/ext/minimap2/test/MT-orang.fa +0 -276
- data/ext/minimap2/test/q-inv.fa +0 -4
- data/ext/minimap2/test/q2.fa +0 -2
- data/ext/minimap2/test/t-inv.fa +0 -127
- data/ext/minimap2/test/t2.fa +0 -2
- data/ext/minimap2/test/x3s-aln.txt +0 -5
- data/ext/minimap2/test/x3s-qry.fa +0 -5
- data/ext/minimap2/test/x3s-ref.fa +0 -10
- data/ext/minimap2/tex/Makefile +0 -21
- data/ext/minimap2/tex/bioinfo.cls +0 -930
- data/ext/minimap2/tex/blasr-mc.eval +0 -17
- data/ext/minimap2/tex/bowtie2-s3.sam.eval +0 -28
- data/ext/minimap2/tex/bwa-s3.sam.eval +0 -52
- data/ext/minimap2/tex/bwa.eval +0 -55
- data/ext/minimap2/tex/eval2roc.pl +0 -33
- data/ext/minimap2/tex/graphmap.eval +0 -4
- data/ext/minimap2/tex/hs38-simu.sh +0 -10
- data/ext/minimap2/tex/minialign.eval +0 -49
- data/ext/minimap2/tex/minimap2.bib +0 -460
- data/ext/minimap2/tex/minimap2.tex +0 -724
- data/ext/minimap2/tex/mm2-s3.sam.eval +0 -62
- data/ext/minimap2/tex/mm2-update.tex +0 -240
- data/ext/minimap2/tex/mm2.approx.eval +0 -12
- data/ext/minimap2/tex/mm2.eval +0 -13
- data/ext/minimap2/tex/natbib.bst +0 -1288
- data/ext/minimap2/tex/natbib.sty +0 -803
- data/ext/minimap2/tex/ngmlr.eval +0 -38
- data/ext/minimap2/tex/roc.gp +0 -60
- data/ext/minimap2/tex/snap-s3.sam.eval +0 -62
- data/ext/minimap2.patch +0 -19
- data/lib/minimap2/ffi/constants.rb +0 -267
- data/lib/minimap2/ffi/functions.rb +0 -239
- data/lib/minimap2/ffi/mappy.rb +0 -104
- data/lib/minimap2/ffi.rb +0 -27
data/ext/minimap2/misc/README.md
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
## <a name="started"></a>Getting Started
|
|
2
|
-
|
|
3
|
-
```sh
|
|
4
|
-
# install minimap2
|
|
5
|
-
git clone https://github.com/lh3/minimap2
|
|
6
|
-
cd minimap2 && make
|
|
7
|
-
# install the k8 javascript shell
|
|
8
|
-
curl -L https://github.com/attractivechaos/k8/releases/download/v0.2.4/k8-0.2.4.tar.bz2 | tar -jxf -
|
|
9
|
-
cp k8-0.2.4/k8-`uname -s` k8 # or copy it to a directory on your $PATH
|
|
10
|
-
# export PATH="$PATH:`pwd`:`pwd`/misc" # run this if k8, minimap2 or paftools.js not on your $PATH
|
|
11
|
-
minimap2 --cs test/MT-human.fa test/MT-orang.fa | paftools.js view - # view alignment
|
|
12
|
-
minimap2 -c test/MT-human.fa test/MT-orang.fa | paftools.js stat - # basic alignment statistics
|
|
13
|
-
minimap2 -c --cs test/MT-human.fa test/MT-orang.fa \
|
|
14
|
-
| sort -k6,6 -k8,8n | paftools.js call -L15000 - # calling variants from asm-to-ref alignment
|
|
15
|
-
minimap2 -c test/MT-human.fa test/MT-orang.fa \
|
|
16
|
-
| paftools.js liftover -l10000 - <(echo -e "MT_orang\t2000\t5000") # liftOver
|
|
17
|
-
# no test data for the following examples
|
|
18
|
-
paftools.js junceval -e anno.gtf splice.sam > out.txt # compare splice junctions to annotations
|
|
19
|
-
paftools.js splice2bed splice.sam > splice.bed # convert PAF/SAM to BED12
|
|
20
|
-
paftools.js gff2bed anno.gtf > anno.bed # convert GTF/GFF3 to BED12
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Table of Contents
|
|
24
|
-
|
|
25
|
-
- [Getting Started](#started)
|
|
26
|
-
- [Introduction](#intro)
|
|
27
|
-
- [Evaluation](#eval)
|
|
28
|
-
- [Evaluating mapping accuracy with simulated reads](#mapeval)
|
|
29
|
-
- [Evaluating read overlap sensitivity](#oveval)
|
|
30
|
-
- [Calling Variants from Assemblies](#asmvar)
|
|
31
|
-
|
|
32
|
-
## <a name="intro"></a>Introduction
|
|
33
|
-
|
|
34
|
-
paftools.js is a script that processes alignments in the [PAF format][paf],
|
|
35
|
-
such as converting between formats, evaluating mapping accuracy, lifting over
|
|
36
|
-
BED files based on alignment, and calling variants from assembly-to-assembly
|
|
37
|
-
alignment. This script *requires* the [k8 Javascript shell][k8] to run. On
|
|
38
|
-
Linux or Mac, you can download the precompiled k8 binary with:
|
|
39
|
-
|
|
40
|
-
```sh
|
|
41
|
-
curl -L https://github.com/attractivechaos/k8/releases/download/v0.2.4/k8-0.2.4.tar.bz2 | tar -jxf -
|
|
42
|
-
cp k8-0.2.4/k8-`uname -s` $HOME/bin/k8 # assuming $HOME/bin in your $PATH
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
It is highly recommended to copy the executable `k8` to a directory on your
|
|
46
|
-
`$PATH` such as `/usr/bin/env` can find it. Like python scripts, once you
|
|
47
|
-
install `k8`, you can launch paftools.js in one of the two ways:
|
|
48
|
-
|
|
49
|
-
```sh
|
|
50
|
-
path/to/paftools.js # only if k8 is on your $PATH
|
|
51
|
-
k8 path/to/paftools.js
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
In a nutshell, paftools.js has the following commands:
|
|
55
|
-
|
|
56
|
-
```
|
|
57
|
-
Usage: paftools.js <command> [arguments]
|
|
58
|
-
Commands:
|
|
59
|
-
view convert PAF to BLAST-like (for eyeballing) or MAF
|
|
60
|
-
splice2bed convert spliced alignment in PAF/SAM to BED12
|
|
61
|
-
sam2paf convert SAM to PAF
|
|
62
|
-
delta2paf convert MUMmer's delta to PAF
|
|
63
|
-
gff2bed convert GTF/GFF3 to BED12
|
|
64
|
-
|
|
65
|
-
stat collect basic mapping information in PAF/SAM
|
|
66
|
-
liftover simplistic liftOver
|
|
67
|
-
call call variants from asm-to-ref alignment with the cs tag
|
|
68
|
-
bedcov compute the number of bases covered
|
|
69
|
-
|
|
70
|
-
mapeval evaluate mapping accuracy using mason2/PBSIM-simulated FASTQ
|
|
71
|
-
mason2fq convert mason2-simulated SAM to FASTQ
|
|
72
|
-
pbsim2fq convert PBSIM-simulated MAF to FASTQ
|
|
73
|
-
junceval evaluate splice junction consistency with known annotations
|
|
74
|
-
ov-eval evaluate read overlap sensitivity using read-to-ref mapping
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
paftools.js seamlessly reads both plain text files and gzip'd text files.
|
|
78
|
-
|
|
79
|
-
## <a name="eval"></a>Evaluation
|
|
80
|
-
|
|
81
|
-
### <a name="mapeval"></a>Evaluating mapping accuracy with simulated reads
|
|
82
|
-
|
|
83
|
-
The **pbsim2fq** command of paftools.js converts the MAF output of [pbsim][pbsim]
|
|
84
|
-
to FASTQ and encodes the true mapping position in the read name in a format like
|
|
85
|
-
`S1_33!chr1!225258409!225267761!-`. Similarly, the **mason2fq** command
|
|
86
|
-
converts [mason2][mason2] simulated SAM to FASTQ.
|
|
87
|
-
|
|
88
|
-
Command **mapeval** evaluates mapped SAM/PAF. Here is example output:
|
|
89
|
-
|
|
90
|
-
```
|
|
91
|
-
Q 60 32478 0 0.000000000 32478
|
|
92
|
-
Q 22 16 1 0.000030775 32494
|
|
93
|
-
Q 21 43 1 0.000061468 32537
|
|
94
|
-
Q 19 73 1 0.000091996 32610
|
|
95
|
-
Q 14 66 1 0.000122414 32676
|
|
96
|
-
Q 10 27 3 0.000214048 32703
|
|
97
|
-
Q 8 14 1 0.000244521 32717
|
|
98
|
-
Q 7 13 2 0.000305530 32730
|
|
99
|
-
Q 6 46 1 0.000335611 32776
|
|
100
|
-
Q 3 10 1 0.000366010 32786
|
|
101
|
-
Q 2 20 2 0.000426751 32806
|
|
102
|
-
Q 1 248 94 0.003267381 33054
|
|
103
|
-
Q 0 31 17 0.003778147 33085
|
|
104
|
-
U 3
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
where each Q-line gives the quality threshold, the number of reads mapped with
|
|
108
|
-
mapping quality equal to or greater than the threshold, number of wrong
|
|
109
|
-
mappings, accumulative mapping error rate and the accumulative number of
|
|
110
|
-
mapped reads. The U-line, if present, gives the number of unmapped reads if
|
|
111
|
-
they are present in the SAM file.
|
|
112
|
-
|
|
113
|
-
Suppose the reported mapping coordinate overlap with the true coordinate like
|
|
114
|
-
the following:
|
|
115
|
-
|
|
116
|
-
```
|
|
117
|
-
truth: --------------------
|
|
118
|
-
mapper: ----------------------
|
|
119
|
-
|<- l1 ->|<-- o -->|<-- l2 -->|
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
Let `r=o/(l1+o+l2)`. The reported mapping is considered correct if `r>0.1` by
|
|
123
|
-
default.
|
|
124
|
-
|
|
125
|
-
### <a name="oveval"></a>Evaluating read overlap sensitivity
|
|
126
|
-
|
|
127
|
-
Command **ov-eval** takes *sorted* read-to-reference alignment and read
|
|
128
|
-
overlaps in PAF as input, and evaluates the sensitivity. For example:
|
|
129
|
-
|
|
130
|
-
```sh
|
|
131
|
-
minimap2 -cx map-pb ref.fa reads.fq.gz | sort -k6,6 -k8,8n > reads-to-ref.paf
|
|
132
|
-
minimap2 -x ava-pb reads.fq.gz reads.fq.gz > ovlp.paf
|
|
133
|
-
k8 ov-eval.js reads-to-ref.paf ovlp.paf
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
## <a name="asmvar"></a>Calling Variants from Haploid Assemblies
|
|
137
|
-
|
|
138
|
-
The **call** command of paftools.js calls variants from coordinate-sorted
|
|
139
|
-
assembly-to-reference alignment. It calls variants from the [cs tag][cs] and
|
|
140
|
-
identifies confident/callable regions as those covered by exactly one contig.
|
|
141
|
-
Here are example command lines:
|
|
142
|
-
|
|
143
|
-
```sh
|
|
144
|
-
minimap2 -cx asm5 -t8 --cs ref.fa asm.fa > asm.paf # keeping this file is recommended; --cs required!
|
|
145
|
-
sort -k6,6 -k8,8n asm.paf > asm.srt.paf # sort by reference start coordinate
|
|
146
|
-
k8 paftools.js call asm.srt.paf > asm.var.txt
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
Here is sample output:
|
|
150
|
-
|
|
151
|
-
```
|
|
152
|
-
V chr1 2276040 2276041 1 60 c g LJII01000171.1 1217409 1217410 +
|
|
153
|
-
V chr1 2280409 2280410 1 60 a g LJII01000171.1 1221778 1221779 +
|
|
154
|
-
V chr1 2280504 2280505 1 60 a g LJII01000171.1 1221873 1221874 +
|
|
155
|
-
R chr1 2325140 2436340
|
|
156
|
-
V chr1 2325287 2325287 1 60 - ct LJII01000171.1 1272894 1272896 +
|
|
157
|
-
V chr1 2325642 2325644 1 60 tt - LJII01000171.1 1273251 1273251 +
|
|
158
|
-
V chr1 2326051 2326052 1 60 c t LJII01000171.1 1273658 1273659 +
|
|
159
|
-
V chr1 2326287 2326288 1 60 c t LJII01000171.1 1273894 1273895 +
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
where a line starting with `R` gives regions covered by one query contig, and a
|
|
163
|
-
V-line encodes a variant in the following format: chr, start, end, query depth,
|
|
164
|
-
mapping quality, REF allele, ALT allele, query name, query start, end and the
|
|
165
|
-
query orientation. Generally, you should only look at variants where column 5
|
|
166
|
-
is one.
|
|
167
|
-
|
|
168
|
-
By default, when calling variants, "paftools.js call" ignores alignments 50kb
|
|
169
|
-
or shorter; when deriving callable regions, it ignores alignments 10kb or
|
|
170
|
-
shorter. It uses two thresholds to avoid edge effects. These defaults are
|
|
171
|
-
designed for long-read assemblies. For short reads, both should be reduced.
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
[paf]: https://github.com/lh3/miniasm/blob/master/PAF.md
|
|
176
|
-
[cs]: https://github.com/lh3/minimap2#cs
|
|
177
|
-
[k8]: https://github.com/attractivechaos/k8
|
|
178
|
-
[maf]: https://genome.ucsc.edu/FAQ/FAQformat#format5
|
|
179
|
-
[pbsim]: https://github.com/pfaucon/PBSIM-PacBio-Simulator
|
|
180
|
-
[mason2]: https://github.com/seqan/seqan/tree/master/apps/mason2
|
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env k8
|
|
2
|
-
|
|
3
|
-
"use strict";
|
|
4
|
-
|
|
5
|
-
Array.prototype.delete_at = function(i) {
|
|
6
|
-
for (let j = i; j < this.length - 1; ++j)
|
|
7
|
-
this[j] = this[j + 1];
|
|
8
|
-
--this.length;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function* getopt(argv, ostr, longopts) {
|
|
12
|
-
if (argv.length == 0) return;
|
|
13
|
-
let pos = 0, cur = 0;
|
|
14
|
-
while (cur < argv.length) {
|
|
15
|
-
let lopt = "", opt = "?", arg = "";
|
|
16
|
-
while (cur < argv.length) { // skip non-option arguments
|
|
17
|
-
if (argv[cur][0] == "-" && argv[cur].length > 1) {
|
|
18
|
-
if (argv[cur] == "--") cur = argv.length;
|
|
19
|
-
break;
|
|
20
|
-
} else ++cur;
|
|
21
|
-
}
|
|
22
|
-
if (cur == argv.length) break;
|
|
23
|
-
let a = argv[cur];
|
|
24
|
-
if (a[0] == "-" && a[1] == "-") { // a long option
|
|
25
|
-
pos = -1;
|
|
26
|
-
let c = 0, k = -1, tmp = "", o;
|
|
27
|
-
const pos_eq = a.indexOf("=");
|
|
28
|
-
if (pos_eq > 0) {
|
|
29
|
-
o = a.substring(2, pos_eq);
|
|
30
|
-
arg = a.substring(pos_eq + 1);
|
|
31
|
-
} else o = a.substring(2);
|
|
32
|
-
for (let i = 0; i < longopts.length; ++i) {
|
|
33
|
-
let y = longopts[i];
|
|
34
|
-
if (y[y.length - 1] == "=") y = y.substring(0, y.length - 1);
|
|
35
|
-
if (o.length <= y.length && o == y.substring(0, o.length)) {
|
|
36
|
-
k = i, tmp = y;
|
|
37
|
-
++c; // c is the number of matches
|
|
38
|
-
if (o == y) { // exact match
|
|
39
|
-
c = 1;
|
|
40
|
-
break;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
if (c == 1) { // find a unique match
|
|
45
|
-
lopt = tmp;
|
|
46
|
-
if (pos_eq < 0 && longopts[k][longopts[k].length-1] == "=" && cur + 1 < argv.length) {
|
|
47
|
-
arg = argv[cur+1];
|
|
48
|
-
argv.delete_at(cur + 1);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
} else { // a short option
|
|
52
|
-
if (pos == 0) pos = 1;
|
|
53
|
-
opt = a[pos++];
|
|
54
|
-
let k = ostr.indexOf(opt);
|
|
55
|
-
if (k < 0) {
|
|
56
|
-
opt = "?";
|
|
57
|
-
} else if (k + 1 < ostr.length && ostr[k+1] == ":") { // requiring an argument
|
|
58
|
-
if (pos >= a.length) {
|
|
59
|
-
arg = argv[cur+1];
|
|
60
|
-
argv.delete_at(cur + 1);
|
|
61
|
-
} else arg = a.substring(pos);
|
|
62
|
-
pos = -1;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
if (pos < 0 || pos >= argv[cur].length) {
|
|
66
|
-
argv.delete_at(cur);
|
|
67
|
-
pos = 0;
|
|
68
|
-
}
|
|
69
|
-
if (lopt != "") yield { opt: `--${lopt}`, arg: arg };
|
|
70
|
-
else if (opt != "?") yield { opt: `-${opt}`, arg: arg };
|
|
71
|
-
else yield { opt: "?", arg: "" };
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function* k8_readline(fn) {
|
|
76
|
-
let buf = new Bytes();
|
|
77
|
-
let file = new File(fn);
|
|
78
|
-
while (file.readline(buf) >= 0) {
|
|
79
|
-
yield buf.toString();
|
|
80
|
-
}
|
|
81
|
-
file.close();
|
|
82
|
-
buf.destroy();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function merge_hits(b) {
|
|
86
|
-
if (b.length == 1)
|
|
87
|
-
return { name1:b[0].name1, name2:b[0].name2, len1:b[0].len1, len2:b[0].len2, min_cov:b[0].min_cov, max_cov:b[0].max_cov, cov1:b[0].cov1, cov2:b[0].cov2, s1:b[0].s1, dv:b[0].dv };
|
|
88
|
-
b.sort(function(x, y) { return x.st1 - y.st1 });
|
|
89
|
-
let f = [], bt = [];
|
|
90
|
-
for (let i = 0; i < b.length; ++i)
|
|
91
|
-
f[i] = b[i].s1, bt[i] = -1;
|
|
92
|
-
for (let i = 0; i < b.length; ++i) {
|
|
93
|
-
for (let j = 0; j < i; ++j) {
|
|
94
|
-
if (b[j].st2 < b[i].st2) {
|
|
95
|
-
if (b[j].en1 >= b[i].en1) continue;
|
|
96
|
-
if (b[j].en2 >= b[i].en2) continue;
|
|
97
|
-
const ov1 = b[j].en1 <= b[i].st1? 0 : b[i].st1 - b[j].en1;
|
|
98
|
-
const li1 = b[i].en1 - b[i].st1;
|
|
99
|
-
const s11 = b[i].s1 / li1 * (li1 - ov1);
|
|
100
|
-
const ov2 = b[j].en2 <= b[i].st2? 0 : b[i].st2 - b[j].en2;
|
|
101
|
-
const li2 = b[i].en2 - b[i].st2;
|
|
102
|
-
const s12 = b[i].s1 / li2 * (li2 - ov2);
|
|
103
|
-
const s1 = s11 < s12? s11 : s12;
|
|
104
|
-
if (f[i] < f[j] + s1)
|
|
105
|
-
f[i] = f[j] + s1, bt[i] = j;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
let max_i = -1, max_f = 0, d = [];
|
|
110
|
-
for (let i = 0; i < b.length; ++i)
|
|
111
|
-
if (max_f < f[i])
|
|
112
|
-
max_f = f[i], max_i = i;
|
|
113
|
-
for (let k = max_i; k >= 0; k = bt[k])
|
|
114
|
-
d.push(k);
|
|
115
|
-
d = d.reverse();
|
|
116
|
-
let dv = 0, tot = 0, cov1 = 0, cov2 = 0, st1 = 0, en1 = 0, st2 = 0, en2 = 0;
|
|
117
|
-
for (let k = 0; k < d.length; ++k) {
|
|
118
|
-
const i = d[k];
|
|
119
|
-
tot += b[i].blen;
|
|
120
|
-
dv += b[i].dv * b[i].blen;
|
|
121
|
-
if (b[i].st1 > en1) {
|
|
122
|
-
cov1 += en1 - st1;
|
|
123
|
-
st1 = b[i].st1, en1 = b[i].en1;
|
|
124
|
-
} else en1 = en1 > b[i].en1? en1 : b[i].en1;
|
|
125
|
-
if (b[i].st2 > en2) {
|
|
126
|
-
cov2 += en2 - st2;
|
|
127
|
-
st2 = b[i].st2, en2 = b[i].en2;
|
|
128
|
-
} else en2 = en2 > b[i].en2? en2 : b[i].en2;
|
|
129
|
-
}
|
|
130
|
-
dv /= tot;
|
|
131
|
-
cov1 = (cov1 + (en1 - st1)) / b[0].len1;
|
|
132
|
-
cov2 = (cov2 + (en2 - st2)) / b[0].len2;
|
|
133
|
-
const min_cov = cov1 < cov2? cov1 : cov2;
|
|
134
|
-
const max_cov = cov1 > cov2? cov1 : cov2;
|
|
135
|
-
//warn(d.length, b[0].name1, b[0].name2, min_cov, max_cov);
|
|
136
|
-
return { name1:b[0].name1, name2:b[0].name2, len1:b[0].len1, len2:b[0].len2, min_cov:min_cov, max_cov:max_cov, cov1:cov1, cov2:cov2, s1:max_f, dv:dv };
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function main(args) {
|
|
140
|
-
let opt = { min_cov:.9, max_dv:.015, max_diff:20000 };
|
|
141
|
-
for (const o of getopt(args, "c:d:e:", [])) {
|
|
142
|
-
if (o.opt == '-c') opt.min_cov = parseFloat(o.arg);
|
|
143
|
-
else if (o.opt == '-d') opt.max_dv = parseFloat(o.arg);
|
|
144
|
-
else if (o.opt == '-e') opt.max_diff = parseFloat(o.arg);
|
|
145
|
-
}
|
|
146
|
-
if (args.length == 0) {
|
|
147
|
-
print("Usage: pafcluster.js [options] <ava.paf>");
|
|
148
|
-
print("Options:");
|
|
149
|
-
print(` -c FLOAT min coverage [${opt.min_cov}]`);
|
|
150
|
-
print(` -d FLOAT max divergence [${opt.max_dv}]`);
|
|
151
|
-
print(` -e FLOAT max difference [${opt.max_diff}]`);
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// read
|
|
156
|
-
let a = [], len = {}, name2len = {};
|
|
157
|
-
for (const line of k8_readline(args[0])) {
|
|
158
|
-
let m, t = line.split("\t");
|
|
159
|
-
if (t[4] != "+") continue;
|
|
160
|
-
for (let i = 1; i < 4; ++i) t[i] = parseInt(t[i]);
|
|
161
|
-
for (let i = 6; i < 11; ++i) t[i] = parseInt(t[i]);
|
|
162
|
-
const len1 = t[1], len2 = t[6];
|
|
163
|
-
let s1 = -1, dv = -1.0;
|
|
164
|
-
for (let i = 12; i < t.length; ++i) {
|
|
165
|
-
if ((m = /^(s1|dv):\S:(\S+)/.exec(t[i])) != null) {
|
|
166
|
-
if (m[1] == "s1") s1 = parseInt(m[2]);
|
|
167
|
-
else if (m[1] == "dv") dv = parseFloat(m[2]);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
if (s1 < 0 || dv < 0) continue;
|
|
171
|
-
const cov1 = (parseInt(t[3]) - parseInt(t[2])) / len1;
|
|
172
|
-
const cov2 = (parseInt(t[8]) - parseInt(t[7])) / len2;
|
|
173
|
-
const min_cov = cov1 < cov2? cov1 : cov2;
|
|
174
|
-
const max_cov = cov1 > cov2? cov1 : cov2;
|
|
175
|
-
name2len[t[0]] = len1;
|
|
176
|
-
name2len[t[5]] = len2;
|
|
177
|
-
a.push({ name1:t[0], name2:t[5], len1:len1, len2:len2, min_cov:min_cov, max_cov:max_cov, s1:s1, dv:dv, cov1:cov1, cov2:cov2, st1:t[2], en1:t[3], st2:t[7], en2:t[8], blen:t[10] });
|
|
178
|
-
len[t[0]] = len1, len[t[5]] = len2;
|
|
179
|
-
}
|
|
180
|
-
warn(`Read ${a.length} hits`);
|
|
181
|
-
|
|
182
|
-
// merge duplicated hits
|
|
183
|
-
let h = {};
|
|
184
|
-
for (let i = 0; i < a.length; ++i) {
|
|
185
|
-
const key = `${a[i].name1}\t${a[i].name2}`;
|
|
186
|
-
if (h[key] == null) h[key] = [];
|
|
187
|
-
h[key].push(a[i]);
|
|
188
|
-
}
|
|
189
|
-
a = [];
|
|
190
|
-
for (const key in h)
|
|
191
|
-
a.push(merge_hits(h[key]));
|
|
192
|
-
|
|
193
|
-
// core loop
|
|
194
|
-
while (a.length > 1) {
|
|
195
|
-
// select the sequence with the highest sum of s1
|
|
196
|
-
let h = {};
|
|
197
|
-
for (let i = 0; i < a.length; ++i) {
|
|
198
|
-
if (h[a[i].name1] == null) h[a[i].name1] = 0;
|
|
199
|
-
h[a[i].name1] += a[i].s1;
|
|
200
|
-
}
|
|
201
|
-
let max_s1 = 0, max_name = "";
|
|
202
|
-
for (const name in h)
|
|
203
|
-
if (max_s1 < h[name])
|
|
204
|
-
max_s1 = h[name], max_name = name;
|
|
205
|
-
// find contigs in the same group
|
|
206
|
-
h = {};
|
|
207
|
-
h[max_name] = 1;
|
|
208
|
-
for (let i = 0; i < a.length; ++i) {
|
|
209
|
-
if (a[i].name1 != max_name && a[i].name2 != max_name)
|
|
210
|
-
continue;
|
|
211
|
-
const diff1 = a[i].len1 * (1.0 - a[i].cov1);
|
|
212
|
-
const diff2 = a[i].len2 * (1.0 - a[i].cov2);
|
|
213
|
-
if (a[i].min_cov >= opt.min_cov && a[i].dv <= opt.max_dv && diff1 <= opt.max_diff && diff2 <= opt.max_diff)
|
|
214
|
-
h[a[i].name1] = h[a[i].name2] = 1;
|
|
215
|
-
}
|
|
216
|
-
let n = 0;
|
|
217
|
-
for (const key in h) {
|
|
218
|
-
++n;
|
|
219
|
-
delete name2len[key];
|
|
220
|
-
}
|
|
221
|
-
print(`SD\t${max_name}\t${n}`);
|
|
222
|
-
for (const key in h) print(`CL\t${key}\t${len[key]}`);
|
|
223
|
-
print("//");
|
|
224
|
-
// filter out redundant hits
|
|
225
|
-
let b = [];
|
|
226
|
-
for (let i = 0; i < a.length; ++i)
|
|
227
|
-
if (h[a[i].name1] == null && h[a[i].name2] == null)
|
|
228
|
-
b.push(a[i]);
|
|
229
|
-
warn(`Reduced the number of hits from ${a.length} to ${b.length}`);
|
|
230
|
-
a = b;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// output remaining singletons
|
|
234
|
-
for (const key in name2len) {
|
|
235
|
-
print(`SD\t${key}\t1`);
|
|
236
|
-
print(`CL\t${key}\t${name2len[key]}`);
|
|
237
|
-
print(`//`);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
main(arguments);
|