mirror of
https://github.com/lh3/minimap2.git
synced 2026-09-26 07:08:11 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c28777e7e | ||
|
|
d8371a403b | ||
|
|
e5066c7976 | ||
|
|
f8381755f1 | ||
|
|
80d92c686f | ||
|
|
37a650f58c | ||
|
|
4ca5a951ca | ||
|
|
dd5b2c04b8 | ||
|
|
ca6f4dc5e2 | ||
|
|
de3c6ec646 | ||
|
|
e2542e6425 | ||
|
|
9bb4d2bed4 | ||
|
|
6d49eb690f | ||
|
|
bd0cba5012 | ||
|
|
370f3f8236 | ||
|
|
79c9cc186b | ||
|
|
ea4c8935bd | ||
|
|
3187782b1a | ||
|
|
005c9a1f6b |
@@ -35,7 +35,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Compile with ${{ matrix.compiler }}
|
- name: Compile with ${{ matrix.compiler }}
|
||||||
uses: uraimo/run-on-arch-action@v2
|
uses: uraimo/run-on-arch-action@v3
|
||||||
with:
|
with:
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
distro: ubuntu22.04
|
distro: ubuntu22.04
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ ksw2_exts2_neon.o:ksw2_exts2_sse.c ksw2.h kalloc.h
|
|||||||
# other non-file targets
|
# other non-file targets
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr gmon.out *.o a.out $(PROG) $(PROG_EXTRA) *~ *.a *.dSYM build dist mappy*.so mappy.c python/mappy.c mappy.egg*
|
rm -fr gmon.out *.o a.out $(PROG) $(PROG_EXTRA) *~ *.a *.dSYM build dist mappy*.so mappy.c python/mappy.c mappy.egg* .eggs
|
||||||
|
|
||||||
depend:
|
depend:
|
||||||
(LC_ALL=C; export LC_ALL; makedepend -Y -- $(CFLAGS) $(CPPFLAGS) -- *.c)
|
(LC_ALL=C; export LC_ALL; makedepend -Y -- $(CFLAGS) $(CPPFLAGS) -- *.c)
|
||||||
|
|||||||
@@ -1,3 +1,51 @@
|
|||||||
|
Release 2.31-r1302 (19 May 2026)
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
Notable changes to minimap2:
|
||||||
|
|
||||||
|
* Bugfix: supplementary and secondary alignments were occasionally flagged
|
||||||
|
incorrectly.
|
||||||
|
|
||||||
|
* Bugfix: Smith-Waterman alignment for inversion alignment led to an
|
||||||
|
out-of-bound access in rare cases.
|
||||||
|
|
||||||
|
Changes to paftools.js:
|
||||||
|
|
||||||
|
* New feature: new `sim2bed` subcommand to get a BED file from simulated
|
||||||
|
reads.
|
||||||
|
|
||||||
|
* New feature: new `badread2fa` subcommand to format reads simulated by
|
||||||
|
the Badread simulator.
|
||||||
|
|
||||||
|
Change to the python binding:
|
||||||
|
|
||||||
|
* New feature: mappy optionally writes the `ds` tag.
|
||||||
|
|
||||||
|
* Bugfix: a use-after-free error (#1345)
|
||||||
|
|
||||||
|
The two bugs in minimap2 had existed for years. They were caught by Jeremy Wang
|
||||||
|
at UNC when he ported minimap2 to Rust. Due to the two bug fixes, this version
|
||||||
|
occasionally produces alignment different from the last version.
|
||||||
|
|
||||||
|
(2.31: 19 May 2026, r1302)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Release 2.30-r1287 (15 June 2025)
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
Notable changes:
|
||||||
|
|
||||||
|
* Improvement: consolidated `--spsc`.
|
||||||
|
|
||||||
|
* Deprecation: subcommands `splice2bed`, `gff2bed`, `gff2junc`, `junceval` and
|
||||||
|
`exoneval` in `paftools.js` are deprecated by minigff. They will remain
|
||||||
|
indefinitely for backward compatibility.
|
||||||
|
|
||||||
|
(2.30: 15 June 2025, r1287)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Release 2.29-r1283 (18 April 2025)
|
Release 2.29-r1283 (18 April 2025)
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
[](https://pypi.python.org/pypi/mappy)
|
[](https://pypi.python.org/pypi/mappy)
|
||||||
[](https://github.com/lh3/minimap2/actions)
|
[](https://github.com/lh3/minimap2/actions)
|
||||||
## <a name="started"></a>Getting Started
|
## <a name="started"></a>Getting Started
|
||||||
|
**ALERT:** `minimap2.com` is a [phishing site](https://github.com/lh3/minimap2/issues/1316). Please don't use anything from that website.
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/lh3/minimap2
|
git clone https://github.com/lh3/minimap2
|
||||||
cd minimap2 && make
|
cd minimap2 && make
|
||||||
@@ -77,8 +78,8 @@ Detailed evaluations are available from the [minimap2 paper][doi] or the
|
|||||||
Minimap2 is optimized for x86-64 CPUs. You can acquire precompiled binaries from
|
Minimap2 is optimized for x86-64 CPUs. You can acquire precompiled binaries from
|
||||||
the [release page][release] with:
|
the [release page][release] with:
|
||||||
```sh
|
```sh
|
||||||
curl -L https://github.com/lh3/minimap2/releases/download/v2.29/minimap2-2.29_x64-linux.tar.bz2 | tar -jxvf -
|
curl -L https://github.com/lh3/minimap2/releases/download/v2.31/minimap2-2.31_x64-linux.tar.bz2 | tar -jxvf -
|
||||||
./minimap2-2.29_x64-linux/minimap2
|
./minimap2-2.31_x64-linux/minimap2
|
||||||
```
|
```
|
||||||
If you want to compile from the source, you need to have a C compiler, GNU make
|
If you want to compile from the source, you need to have a C compiler, GNU make
|
||||||
and zlib development files installed. Then type `make` in the source code
|
and zlib development files installed. Then type `make` in the source code
|
||||||
|
|||||||
+2
-2
@@ -31,8 +31,8 @@ To acquire the data used in this cookbook and to install minimap2 and paftools,
|
|||||||
please follow the command lines below:
|
please follow the command lines below:
|
||||||
```sh
|
```sh
|
||||||
# install minimap2 executables
|
# install minimap2 executables
|
||||||
curl -L https://github.com/lh3/minimap2/releases/download/v2.29/minimap2-2.29_x64-linux.tar.bz2 | tar jxf -
|
curl -L https://github.com/lh3/minimap2/releases/download/v2.31/minimap2-2.31_x64-linux.tar.bz2 | tar jxf -
|
||||||
cp minimap2-2.29_x64-linux/{minimap2,k8,paftools.js} . # copy executables
|
cp minimap2-2.31_x64-linux/{minimap2,k8,paftools.js} . # copy executables
|
||||||
export PATH="$PATH:"`pwd` # put the current directory on PATH
|
export PATH="$PATH:"`pwd` # put the current directory on PATH
|
||||||
# download example datasets
|
# download example datasets
|
||||||
curl -L https://github.com/lh3/minimap2/releases/download/v2.10/cookbook-data.tgz | tar zxf -
|
curl -L https://github.com/lh3/minimap2/releases/download/v2.10/cookbook-data.tgz | tar zxf -
|
||||||
|
|||||||
@@ -361,24 +361,34 @@ static void write_cs_ds_or_MD(void *km, kstring_t *s, const mm_idx_t *mi, const
|
|||||||
kfree(km, qseq); kfree(km, tseq); kfree(km, tmp);
|
kfree(km, qseq); kfree(km, tseq); kfree(km, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mm_gen_cs_or_MD(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq, int is_MD, int no_iden, int is_qstrand)
|
int mm_gen_cs_ds_or_MD(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq, int is_MD, int is_ds, int no_iden, int is_qstrand)
|
||||||
{
|
{
|
||||||
mm_bseq1_t t;
|
mm_bseq1_t t;
|
||||||
kstring_t str;
|
kstring_t str;
|
||||||
str.s = *buf, str.l = 0, str.m = *max_len;
|
str.s = *buf, str.l = 0, str.m = *max_len;
|
||||||
t.l_seq = strlen(seq);
|
t.l_seq = strlen(seq);
|
||||||
t.seq = (char*)seq;
|
t.seq = (char*)seq;
|
||||||
write_cs_ds_or_MD(km, &str, mi, &t, r, no_iden, is_MD, 0, 0, is_qstrand);
|
write_cs_ds_or_MD(km, &str, mi, &t, r, no_iden, is_MD, is_ds, 0, is_qstrand);
|
||||||
*max_len = str.m;
|
*max_len = str.m;
|
||||||
*buf = str.s;
|
*buf = str.s;
|
||||||
return str.l;
|
return str.l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mm_gen_cs_or_MD(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq, int is_MD, int no_iden, int is_qstrand)
|
||||||
|
{
|
||||||
|
return mm_gen_cs_ds_or_MD(km, buf, max_len, mi, r, seq, is_MD, 0, no_iden, is_qstrand);
|
||||||
|
}
|
||||||
|
|
||||||
int mm_gen_cs(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq, int no_iden)
|
int mm_gen_cs(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq, int no_iden)
|
||||||
{
|
{
|
||||||
return mm_gen_cs_or_MD(km, buf, max_len, mi, r, seq, 0, no_iden, 0);
|
return mm_gen_cs_or_MD(km, buf, max_len, mi, r, seq, 0, no_iden, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mm_gen_ds(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq, int no_iden)
|
||||||
|
{
|
||||||
|
return mm_gen_cs_ds_or_MD(km, buf, max_len, mi, r, seq, 0, 1, no_iden, 0);
|
||||||
|
}
|
||||||
|
|
||||||
int mm_gen_MD(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq)
|
int mm_gen_MD(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq)
|
||||||
{
|
{
|
||||||
return mm_gen_cs_or_MD(km, buf, max_len, mi, r, seq, 1, 0, 0);
|
return mm_gen_cs_or_MD(km, buf, max_len, mi, r, seq, 1, 0, 0);
|
||||||
|
|||||||
@@ -256,19 +256,25 @@ void mm_select_sub(void *km, float pri_ratio, int min_diff, int best_n, int chec
|
|||||||
{
|
{
|
||||||
if (pri_ratio > 0.0f && *n_ > 0) {
|
if (pri_ratio > 0.0f && *n_ > 0) {
|
||||||
int i, k, n = *n_, n_2nd = 0;
|
int i, k, n = *n_, n_2nd = 0;
|
||||||
for (i = k = 0; i < n; ++i) {
|
uint8_t *keep = (uint8_t*)kmalloc(km, n);
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
int p = r[i].parent;
|
int p = r[i].parent;
|
||||||
|
keep[i] = 0;
|
||||||
if (p == i || r[i].inv) { // primary or inversion
|
if (p == i || r[i].inv) { // primary or inversion
|
||||||
r[k++] = r[i];
|
keep[i] = 1;
|
||||||
} else if ((r[i].score >= r[p].score * pri_ratio || r[i].score + min_diff >= r[p].score) && n_2nd < best_n) {
|
} else if ((r[i].score >= r[p].score * pri_ratio || r[i].score + min_diff >= r[p].score) && n_2nd < best_n) {
|
||||||
if (!(r[i].qs == r[p].qs && r[i].qe == r[p].qe && r[i].rid == r[p].rid && r[i].rs == r[p].rs && r[i].re == r[p].re)) // not identical hits
|
if (!(r[i].qs == r[p].qs && r[i].qe == r[p].qe && r[i].rid == r[p].rid && r[i].rs == r[p].rs && r[i].re == r[p].re)) // not identical hits
|
||||||
r[k++] = r[i], ++n_2nd;
|
keep[i] = 1, ++n_2nd;
|
||||||
else if (r[i].p) free(r[i].p);
|
|
||||||
} else if (check_strand && n_2nd < best_n && r[i].score > min_strand_sc && r[i].rev != r[p].rev) {
|
} else if (check_strand && n_2nd < best_n && r[i].score > min_strand_sc && r[i].rev != r[p].rev) {
|
||||||
r[i].strand_retained = 1;
|
r[i].strand_retained = 1;
|
||||||
r[k++] = r[i], ++n_2nd;
|
keep[i] = 1, ++n_2nd;
|
||||||
} else if (r[i].p) free(r[i].p);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
for (i = k = 0; i < n; ++i) {
|
||||||
|
if (keep[i]) r[k++] = r[i];
|
||||||
|
else if (r[i].p) free(r[i].p);
|
||||||
|
}
|
||||||
|
kfree(km, keep);
|
||||||
if (k != n) mm_sync_regs(km, k, r); // removing hits requires sync()
|
if (k != n) mm_sync_regs(km, k, r); // removing hits requires sync()
|
||||||
*n_ = k;
|
*n_ = k;
|
||||||
}
|
}
|
||||||
@@ -277,13 +283,18 @@ void mm_select_sub(void *km, float pri_ratio, int min_diff, int best_n, int chec
|
|||||||
int mm_filter_strand_retained(int n_regs, mm_reg1_t *r)
|
int mm_filter_strand_retained(int n_regs, mm_reg1_t *r)
|
||||||
{
|
{
|
||||||
int i, k;
|
int i, k;
|
||||||
for (i = k = 0; i < n_regs; ++i) {
|
uint8_t *keep = (uint8_t*)malloc(n_regs);
|
||||||
|
for (i = 0; i < n_regs; ++i) {
|
||||||
int p = r[i].parent;
|
int p = r[i].parent;
|
||||||
if (!r[i].strand_retained || r[i].div < r[p].div * 5.0f || r[i].div < 0.01f) {
|
keep[i] = (!r[i].strand_retained || r[i].div < r[p].div * 5.0f || r[i].div < 0.01f);
|
||||||
|
}
|
||||||
|
for (i = k = 0; i < n_regs; ++i) {
|
||||||
|
if (keep[i]) {
|
||||||
if (k < i) r[k++] = r[i];
|
if (k < i) r[k++] = r[i];
|
||||||
else ++k;
|
else ++k;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free(keep);
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -967,7 +967,7 @@ typedef struct mm_idx_spsc_s {
|
|||||||
uint64_t *a; // pos<<56 | score<<1 | acceptor
|
uint64_t *a; // pos<<56 | score<<1 | acceptor
|
||||||
} mm_idx_spsc_t;
|
} mm_idx_spsc_t;
|
||||||
|
|
||||||
int32_t mm_idx_spsc_read(mm_idx_t *idx, const char *fn, int32_t max_sc)
|
int32_t mm_idx_spsc_read2(mm_idx_t *idx, const char *fn, int32_t max_sc, float scale)
|
||||||
{
|
{
|
||||||
gzFile fp;
|
gzFile fp;
|
||||||
kstring_t str = {0,0,0};
|
kstring_t str = {0,0,0};
|
||||||
@@ -1007,6 +1007,8 @@ int32_t mm_idx_spsc_read(mm_idx_t *idx, const char *fn, int32_t max_sc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i < 4) continue; // not enough fields
|
if (i < 4) continue; // not enough fields
|
||||||
|
if (scale > 0.0f && scale < 1.0f)
|
||||||
|
score = score > 0.0f? (int)(score * scale + .499) : (int)(score * scale - .499);
|
||||||
if (score > max_sc) score = max_sc;
|
if (score > max_sc) score = max_sc;
|
||||||
if (score < -max_sc) score = -max_sc;
|
if (score < -max_sc) score = -max_sc;
|
||||||
cid = mm_idx_name2id(idx, name);
|
cid = mm_idx_name2id(idx, name);
|
||||||
@@ -1030,6 +1032,11 @@ int32_t mm_idx_spsc_read(mm_idx_t *idx, const char *fn, int32_t max_sc)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t mm_idx_spsc_read(mm_idx_t *idx, const char *fn, int32_t max_sc)
|
||||||
|
{
|
||||||
|
return mm_idx_spsc_read2(idx, fn, max_sc, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t mm_idx_find_intv(int32_t n, const uint64_t *a, int64_t x)
|
static int32_t mm_idx_find_intv(int32_t n, const uint64_t *a, int64_t x)
|
||||||
{
|
{
|
||||||
int32_t s = 0, e = n;
|
int32_t s = 0, e = n;
|
||||||
|
|||||||
+2
-2
@@ -67,7 +67,7 @@ void *ksw_ll_qinit(void *km, int size, int qlen, const uint8_t *query, int m, co
|
|||||||
const int8_t *ma = mat + a * m;
|
const int8_t *ma = mat + a * m;
|
||||||
for (i = 0; i < slen; ++i)
|
for (i = 0; i < slen; ++i)
|
||||||
for (k = i; k < nlen; k += slen) // p iterations
|
for (k = i; k < nlen; k += slen) // p iterations
|
||||||
*t++ = (k >= qlen? 0 : ma[query[k]]) + q->shift;
|
*t++ = (k >= qlen? -1 : ma[query[k]]) + q->shift;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int16_t *t = (int16_t*)q->qp;
|
int16_t *t = (int16_t*)q->qp;
|
||||||
@@ -76,7 +76,7 @@ void *ksw_ll_qinit(void *km, int size, int qlen, const uint8_t *query, int m, co
|
|||||||
const int8_t *ma = mat + a * m;
|
const int8_t *ma = mat + a * m;
|
||||||
for (i = 0; i < slen; ++i)
|
for (i = 0; i < slen; ++i)
|
||||||
for (k = i; k < nlen; k += slen) // p iterations
|
for (k = i; k < nlen; k += slen) // p iterations
|
||||||
*t++ = (k >= qlen? 0 : ma[query[k]]);
|
*t++ = (k >= qlen? -1 : ma[query[k]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return q;
|
return q;
|
||||||
|
|||||||
-1
Submodule lib/simde deleted from b30129b3b4
@@ -85,6 +85,8 @@ static ko_longopt_t long_options[] = {
|
|||||||
{ "jump-min-match", ko_required_argument, 360 },
|
{ "jump-min-match", ko_required_argument, 360 },
|
||||||
{ "write-junc", ko_no_argument, 361 },
|
{ "write-junc", ko_no_argument, 361 },
|
||||||
{ "pass1", ko_required_argument, 362 },
|
{ "pass1", ko_required_argument, 362 },
|
||||||
|
{ "spsc-scale", ko_required_argument, 363 },
|
||||||
|
{ "spsc0", ko_required_argument, 364 },
|
||||||
{ "dbg-seed-occ", ko_no_argument, 501 },
|
{ "dbg-seed-occ", ko_no_argument, 501 },
|
||||||
{ "help", ko_no_argument, 'h' },
|
{ "help", ko_no_argument, 'h' },
|
||||||
{ "max-intron-len", ko_required_argument, 'G' },
|
{ "max-intron-len", ko_required_argument, 'G' },
|
||||||
@@ -134,6 +136,7 @@ int main(int argc, char *argv[])
|
|||||||
mm_mapopt_t opt;
|
mm_mapopt_t opt;
|
||||||
mm_idxopt_t ipt;
|
mm_idxopt_t ipt;
|
||||||
int i, c, n_threads = 3, n_parts, old_best_n = -1;
|
int i, c, n_threads = 3, n_parts, old_best_n = -1;
|
||||||
|
float spsc_scale = 0.7f;
|
||||||
char *fnw = 0, *rg = 0, *fn_bed_junc = 0, *fn_bed_jump = 0, *fn_bed_pass1 = 0, *fn_spsc = 0, *s, *alt_list = 0;
|
char *fnw = 0, *rg = 0, *fn_bed_junc = 0, *fn_bed_jump = 0, *fn_bed_pass1 = 0, *fn_spsc = 0, *s, *alt_list = 0;
|
||||||
FILE *fp_help = stderr;
|
FILE *fp_help = stderr;
|
||||||
mm_idx_reader_t *idx_rdr;
|
mm_idx_reader_t *idx_rdr;
|
||||||
@@ -240,7 +243,6 @@ int main(int argc, char *argv[])
|
|||||||
else if (c == 338) opt.max_qlen = mm_parse_num(o.arg); // --max-qlen
|
else if (c == 338) opt.max_qlen = mm_parse_num(o.arg); // --max-qlen
|
||||||
else if (c == 340) fn_bed_junc = o.arg; // --junc-bed
|
else if (c == 340) fn_bed_junc = o.arg; // --junc-bed
|
||||||
else if (c == 341) opt.junc_bonus = atoi(o.arg); // --junc-bonus
|
else if (c == 341) opt.junc_bonus = atoi(o.arg); // --junc-bonus
|
||||||
else if (c == 358) opt.junc_pen = atoi(o.arg); // --junc-pen
|
|
||||||
else if (c == 342) opt.flag |= MM_F_SAM_HIT_ONLY; // --sam-hit-only
|
else if (c == 342) opt.flag |= MM_F_SAM_HIT_ONLY; // --sam-hit-only
|
||||||
else if (c == 343) opt.chain_gap_scale = atof(o.arg); // --chain-gap-scale
|
else if (c == 343) opt.chain_gap_scale = atof(o.arg); // --chain-gap-scale
|
||||||
else if (c == 351) opt.chain_skip_scale = atof(o.arg); // --chain-skip-scale
|
else if (c == 351) opt.chain_skip_scale = atof(o.arg); // --chain-skip-scale
|
||||||
@@ -260,6 +262,8 @@ int main(int argc, char *argv[])
|
|||||||
else if (c == 361) opt.flag |= MM_F_OUT_JUNC | MM_F_CIGAR; // --write-junc
|
else if (c == 361) opt.flag |= MM_F_OUT_JUNC | MM_F_CIGAR; // --write-junc
|
||||||
else if (c == 362) fn_bed_pass1 = o.arg; // --jump-pass1
|
else if (c == 362) fn_bed_pass1 = o.arg; // --jump-pass1
|
||||||
else if (c == 501) mm_dbg_flag |= MM_DBG_SEED_FREQ; // --dbg-seed-occ
|
else if (c == 501) mm_dbg_flag |= MM_DBG_SEED_FREQ; // --dbg-seed-occ
|
||||||
|
else if (c == 363) spsc_scale = atof(o.arg); // --spsc-scale
|
||||||
|
else if (c == 358 || c == 364) opt.junc_pen = atoi(o.arg); // --junc-pen or --spsc0
|
||||||
else if (c == 330) {
|
else if (c == 330) {
|
||||||
fprintf(stderr, "[WARNING] \033[1;31m --lj-min-ratio has been deprecated.\033[0m\n");
|
fprintf(stderr, "[WARNING] \033[1;31m --lj-min-ratio has been deprecated.\033[0m\n");
|
||||||
} else if (c == 313) { // --sr
|
} else if (c == 313) { // --sr
|
||||||
@@ -476,7 +480,7 @@ int main(int argc, char *argv[])
|
|||||||
fprintf(stderr, "[WARNING] failed to load the pass-1 jump BED file\n");
|
fprintf(stderr, "[WARNING] failed to load the pass-1 jump BED file\n");
|
||||||
}
|
}
|
||||||
if (fn_spsc) {
|
if (fn_spsc) {
|
||||||
mm_idx_spsc_read(mi, fn_spsc, mm_max_spsc_bonus(&opt));
|
mm_idx_spsc_read2(mi, fn_spsc, mm_max_spsc_bonus(&opt), spsc_scale);
|
||||||
if (mi->spsc == 0 && mm_verbose >= 2)
|
if (mi->spsc == 0 && mm_verbose >= 2)
|
||||||
fprintf(stderr, "[WARNING] failed to load the splice score file\n");
|
fprintf(stderr, "[WARNING] failed to load the splice score file\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#define MM_VERSION "2.29-r1283"
|
#define MM_VERSION "2.31-r1302"
|
||||||
|
|
||||||
#define MM_F_NO_DIAG (0x001LL) // no exact diagonal hit
|
#define MM_F_NO_DIAG (0x001LL) // no exact diagonal hit
|
||||||
#define MM_F_NO_DUAL (0x002LL) // skip pairs where query name is lexicographically larger than target name
|
#define MM_F_NO_DUAL (0x002LL) // skip pairs where query name is lexicographically larger than target name
|
||||||
@@ -163,7 +163,8 @@ typedef struct {
|
|||||||
int transition; // transition mismatch score (A:G, C:T)
|
int transition; // transition mismatch score (A:G, C:T)
|
||||||
int sc_ambi; // score when one or both bases are "N"
|
int sc_ambi; // score when one or both bases are "N"
|
||||||
int noncan; // cost of non-canonical splicing sites
|
int noncan; // cost of non-canonical splicing sites
|
||||||
int junc_bonus, junc_pen;
|
int junc_bonus; // bonus for a splice site in annotation
|
||||||
|
int junc_pen; // penalty for GT- or -AG not scored in --spsc
|
||||||
int zdrop, zdrop_inv; // break alignment if alignment score drops too fast along the diagonal
|
int zdrop, zdrop_inv; // break alignment if alignment score drops too fast along the diagonal
|
||||||
int end_bonus;
|
int end_bonus;
|
||||||
int min_dp_max; // drop an alignment if the score of the max scoring segment is below this threshold
|
int min_dp_max; // drop an alignment if the score of the max scoring segment is below this threshold
|
||||||
@@ -407,6 +408,7 @@ int mm_map_file_frag(const mm_idx_t *idx, int n_segs, const char **fn, const mm_
|
|||||||
* @return the length of cs
|
* @return the length of cs
|
||||||
*/
|
*/
|
||||||
int mm_gen_cs(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq, int no_iden);
|
int mm_gen_cs(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq, int no_iden);
|
||||||
|
int mm_gen_ds(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq, int no_iden);
|
||||||
int mm_gen_MD(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq);
|
int mm_gen_MD(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq);
|
||||||
|
|
||||||
// query sequence name and sequence in the minimap2 index
|
// query sequence name and sequence in the minimap2 index
|
||||||
@@ -420,6 +422,7 @@ int mm_idx_bed_junc(const mm_idx_t *mi, int32_t ctg, int32_t st, int32_t en, uin
|
|||||||
|
|
||||||
int mm_max_spsc_bonus(const mm_mapopt_t *mo);
|
int mm_max_spsc_bonus(const mm_mapopt_t *mo);
|
||||||
int32_t mm_idx_spsc_read(mm_idx_t *idx, const char *fn, int32_t max_sc);
|
int32_t mm_idx_spsc_read(mm_idx_t *idx, const char *fn, int32_t max_sc);
|
||||||
|
int32_t mm_idx_spsc_read2(mm_idx_t *idx, const char *fn, int32_t max_sc, float scale);
|
||||||
int64_t mm_idx_spsc_get(const mm_idx_t *db, int32_t cid, int64_t st0, int64_t en0, int32_t rev, uint8_t *sc);
|
int64_t mm_idx_spsc_get(const mm_idx_t *db, int32_t cid, int64_t st0, int64_t en0, int32_t rev, uint8_t *sc);
|
||||||
|
|
||||||
// deprecated APIs for backward compatibility
|
// deprecated APIs for backward compatibility
|
||||||
|
|||||||
+12
-3
@@ -1,4 +1,4 @@
|
|||||||
.TH minimap2 1 "18 April 2025" "minimap2-2.29 (r1283)" "Bioinformatics tools"
|
.TH minimap2 1 "19 May 2026" "minimap2-2.31 (r1302)" "Bioinformatics tools"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
minimap2 - mapping and alignment between collections of DNA sequences
|
minimap2 - mapping and alignment between collections of DNA sequences
|
||||||
@@ -443,14 +443,23 @@ line corresponds to a donor site and `A' for an acceptor site.
|
|||||||
A positive score suggests the junction is preferred and a negative score
|
A positive score suggests the junction is preferred and a negative score
|
||||||
suggests the junction is not preferred.
|
suggests the junction is not preferred.
|
||||||
.TP
|
.TP
|
||||||
.BR --junc-pen \ INT
|
.BR --spsc0 \ INT
|
||||||
Penalty for a position not in FILE specified by
|
Penalty for positions not in
|
||||||
|
.I FILE
|
||||||
|
specified by
|
||||||
.B --spsc
|
.B --spsc
|
||||||
[5]. Effective with
|
[5]. Effective with
|
||||||
.B --spsc
|
.B --spsc
|
||||||
but not
|
but not
|
||||||
.BR --junc-bed .
|
.BR --junc-bed .
|
||||||
.TP
|
.TP
|
||||||
|
.BR --spsc-scale \ FLOAT
|
||||||
|
Scale splice scores in
|
||||||
|
.B --spsc
|
||||||
|
by
|
||||||
|
.IR FLOAT
|
||||||
|
rounded to the nearest integer [0.7].
|
||||||
|
.TP
|
||||||
.BR --junc-bed \ FILE
|
.BR --junc-bed \ FILE
|
||||||
Junctions to prefer during base alignment [].
|
Junctions to prefer during base alignment [].
|
||||||
Same format as
|
Same format as
|
||||||
|
|||||||
+108
-5
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env k8
|
#!/usr/bin/env k8
|
||||||
|
|
||||||
var paftools_version = '2.29-r1283';
|
var paftools_version = '2.31-r1302';
|
||||||
|
|
||||||
/*****************************
|
/*****************************
|
||||||
***** Library functions *****
|
***** Library functions *****
|
||||||
@@ -1740,10 +1740,11 @@ function paf_gff2bed(args)
|
|||||||
|
|
||||||
function paf_sam2paf(args)
|
function paf_sam2paf(args)
|
||||||
{
|
{
|
||||||
var c, pri_only = false, long_cs = false, pri_pri_only = false;
|
var c, pri_only = false, long_cs = false, pri_pri_only = false, allow_unmapped = false;
|
||||||
while ((c = getopt(args, "pPL")) != null) {
|
while ((c = getopt(args, "pPUL")) != null) {
|
||||||
if (c == 'p') pri_only = true;
|
if (c == 'p') pri_only = true;
|
||||||
else if (c == 'P') pri_pri_only = pri_only = true;
|
else if (c == 'P') pri_pri_only = pri_only = true;
|
||||||
|
else if (c == 'U') allow_unmapped = true;
|
||||||
else if (c == 'L') long_cs = true;
|
else if (c == 'L') long_cs = true;
|
||||||
}
|
}
|
||||||
if (args.length == getopt.ind) {
|
if (args.length == getopt.ind) {
|
||||||
@@ -1751,6 +1752,7 @@ function paf_sam2paf(args)
|
|||||||
print("Options:");
|
print("Options:");
|
||||||
print(" -p convert primary or supplementary alignments only");
|
print(" -p convert primary or supplementary alignments only");
|
||||||
print(" -P convert primary alignments only");
|
print(" -P convert primary alignments only");
|
||||||
|
print(" -U convert unmapped reads as well");
|
||||||
print(" -L output the cs tag in the long form");
|
print(" -L output the cs tag in the long form");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -1775,7 +1777,15 @@ function paf_sam2paf(args)
|
|||||||
var flag = parseInt(t[1]);
|
var flag = parseInt(t[1]);
|
||||||
if (t[9] != '*' && t[10] != '*' && t[9].length != t[10].length)
|
if (t[9] != '*' && t[10] != '*' && t[9].length != t[10].length)
|
||||||
throw Error("at line " + lineno + ": inconsistent SEQ and QUAL lengths - " + t[9].length + " != " + t[10].length);
|
throw Error("at line " + lineno + ": inconsistent SEQ and QUAL lengths - " + t[9].length + " != " + t[10].length);
|
||||||
if (t[2] == '*' || (flag&4) || t[5] == '*') continue;
|
if (t[2] == '*' || (flag&4) || t[5] == '*') {
|
||||||
|
if (allow_unmapped) {
|
||||||
|
// emit an unmapped PAF line instead of skipping
|
||||||
|
// fields: qname, qlen, qstart, qend, strand, tname, tlen, tstart, tend, n_match, aln_len, mapq
|
||||||
|
var qlen_val = (t[9] == '*' ? 0 : t[9].length);
|
||||||
|
print([t[0], qlen_val, 0, 0, '*', '*', 0, 0, 0, 0, 0, 0].join("\t"));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (pri_only && (flag&0x100)) continue;
|
if (pri_only && (flag&0x100)) continue;
|
||||||
if (pri_pri_only && (flag&0x900)) continue;
|
if (pri_pri_only && (flag&0x900)) continue;
|
||||||
var tlen = ctg_len[t[2]];
|
var tlen = ctg_len[t[2]];
|
||||||
@@ -2338,6 +2348,41 @@ function paf_mason2fq(args)
|
|||||||
buf2.destroy();
|
buf2.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convert Mason read names to BED
|
||||||
|
function paf_sim2bed(args)
|
||||||
|
{
|
||||||
|
if (args.length == 0) {
|
||||||
|
print("Usage: paftools.js sim2bed <sim.txt>");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
var buf = new Bytes();
|
||||||
|
var file = new File(args[0]);
|
||||||
|
while (file.readline(buf) >= 0) {
|
||||||
|
var line = buf.toString();
|
||||||
|
var t = line.split("!");
|
||||||
|
if (t.length < 5) continue;
|
||||||
|
var chr = t[1], st, en, strand;
|
||||||
|
if (t[2].indexOf("_") >= 0) { // mason paired-end
|
||||||
|
var pos = t[2].split("_");
|
||||||
|
var end = t[3].split("_");
|
||||||
|
var m = /^(.)(.)\/([12])$/.exec(t[4]);
|
||||||
|
if (m == null) continue;
|
||||||
|
strand = m[3] == "1" ? m[1] : m[2];
|
||||||
|
var read_no = parseInt(m[3]) - 1;
|
||||||
|
st = parseInt(pos[read_no]);
|
||||||
|
en = parseInt(end[read_no]);
|
||||||
|
} else { // badread/pbsim long reads
|
||||||
|
st = parseInt(t[2]);
|
||||||
|
en = parseInt(t[3]);
|
||||||
|
strand = t[4];
|
||||||
|
}
|
||||||
|
if (st > en) { var tmp = st; st = en; en = tmp; }
|
||||||
|
print([chr, st, en, line, 0, strand].join("\t"));
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
buf.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
// convert pbsim MAF to FASTQ
|
// convert pbsim MAF to FASTQ
|
||||||
function paf_pbsim2fq(args)
|
function paf_pbsim2fq(args)
|
||||||
{
|
{
|
||||||
@@ -2395,6 +2440,53 @@ function paf_pbsim2fq(args)
|
|||||||
buf2.destroy();
|
buf2.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function paf_badread2fa(args)
|
||||||
|
{
|
||||||
|
if (args.length < 2) {
|
||||||
|
print("Usage: paftools.js badread2fa <ref.fa.fai> <badread.fq>");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var len = {}, file, buf = new Bytes();
|
||||||
|
file = new File(args[0]);
|
||||||
|
while (file.readline(buf) >= 0) {
|
||||||
|
var t = buf.toString().split("\t");
|
||||||
|
len[t[0]] = parseInt(t[1]);
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
var id = 0, n_discard = 0;
|
||||||
|
file = new File(args[1]);
|
||||||
|
while (file.readline(buf) >= 0) {
|
||||||
|
var line = buf.toString();
|
||||||
|
var m, tag = '', a = null, is_fq = line[0] == '@'? true : false;
|
||||||
|
if (!/\schimera\s/.test(line) && (m = /\s(\S+),([+-])strand,(\d+)-(\d+).*read_identity=([0-9\.]+)%/.exec(line)) != null) {
|
||||||
|
if (len[m[1]] == null) throw Error("failed to find the contig length of " + m[1]);
|
||||||
|
m[3] = parseInt(m[3]);
|
||||||
|
m[4] = parseInt(m[4]);
|
||||||
|
if (m[2] == '+')
|
||||||
|
a = [ "S" + (id+1), m[1], m[3], m[4], m[2] ];
|
||||||
|
else
|
||||||
|
a = [ "S" + (id+1), m[1], len[m[1]] - m[4], len[m[1]] - m[3], m[2] ];
|
||||||
|
tag = "ri:f:" + m[5];
|
||||||
|
}
|
||||||
|
file.readline(buf);
|
||||||
|
var seq = buf.toString();
|
||||||
|
if (is_fq) {
|
||||||
|
file.readline(buf);
|
||||||
|
file.readline(buf);
|
||||||
|
}
|
||||||
|
if (a != null) {
|
||||||
|
print(">" + a.join("!"), tag);
|
||||||
|
print(seq);
|
||||||
|
} else ++n_discard;
|
||||||
|
++id;
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
buf.destroy();
|
||||||
|
warn("WARNING: discarded " + n_discard + " reads");
|
||||||
|
}
|
||||||
|
|
||||||
function paf_junceval(args)
|
function paf_junceval(args)
|
||||||
{
|
{
|
||||||
var c, l_fuzzy = 0, print_ovlp = false, print_err_only = false, first_only = false, chr_only = false, aa = false, is_bed = false;
|
var c, l_fuzzy = 0, print_ovlp = false, print_err_only = false, first_only = false, chr_only = false, aa = false, is_bed = false;
|
||||||
@@ -2613,7 +2705,8 @@ function paf_junceval(args)
|
|||||||
function paf_exoneval(args) // adapted from paf_junceval()
|
function paf_exoneval(args) // adapted from paf_junceval()
|
||||||
{
|
{
|
||||||
var c, l_fuzzy = 0, print_ovlp = false, print_err_only = false, first_only = false, chr_only = false, aa = false, is_bed = false, use_cds = false, eval_base = false;
|
var c, l_fuzzy = 0, print_ovlp = false, print_err_only = false, first_only = false, chr_only = false, aa = false, is_bed = false, use_cds = false, eval_base = false;
|
||||||
while ((c = getopt(args, "l:epcab1ds")) != null) {
|
var skip_start = false, skip_last = false;
|
||||||
|
while ((c = getopt(args, "l:epcab1dsft")) != null) {
|
||||||
if (c == 'l') l_fuzzy = parseInt(getopt.arg);
|
if (c == 'l') l_fuzzy = parseInt(getopt.arg);
|
||||||
else if (c == 'e') print_err_only = print_ovlp = true;
|
else if (c == 'e') print_err_only = print_ovlp = true;
|
||||||
else if (c == 'p') print_ovlp = true;
|
else if (c == 'p') print_ovlp = true;
|
||||||
@@ -2623,6 +2716,8 @@ function paf_exoneval(args) // adapted from paf_junceval()
|
|||||||
else if (c == '1') first_only = true;
|
else if (c == '1') first_only = true;
|
||||||
else if (c == 'd') use_cds = true;
|
else if (c == 'd') use_cds = true;
|
||||||
else if (c == 's') eval_base = true;
|
else if (c == 's') eval_base = true;
|
||||||
|
else if (c == 'f') skip_start = true;
|
||||||
|
else if (c == 't') skip_last = skip_start = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.length - getopt.ind < 1) {
|
if (args.length - getopt.ind < 1) {
|
||||||
@@ -2635,6 +2730,8 @@ function paf_exoneval(args) // adapted from paf_junceval()
|
|||||||
print(" -e print erroreous overlapping exons");
|
print(" -e print erroreous overlapping exons");
|
||||||
print(" -c only consider alignments to /^(chr)?([0-9]+|X|Y)$/");
|
print(" -c only consider alignments to /^(chr)?([0-9]+|X|Y)$/");
|
||||||
print(" -1 only process the first alignment of each query");
|
print(" -1 only process the first alignment of each query");
|
||||||
|
print(" -f skip the first exon in the miniprot mode");
|
||||||
|
print(" -t skip the first and the last exons");
|
||||||
print(" -b BED as input");
|
print(" -b BED as input");
|
||||||
print(" -s compute base Sn and Sp (more memory)");
|
print(" -s compute base Sn and Sp (more memory)");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -2764,6 +2861,8 @@ function paf_exoneval(args) // adapted from paf_junceval()
|
|||||||
for (var i = tmp_exon.length - 1; i >= 0; --i)
|
for (var i = tmp_exon.length - 1; i >= 0; --i)
|
||||||
exon.push([pos + (glen - tmp_exon[i][1]), pos + (glen - tmp_exon[i][0])]);
|
exon.push([pos + (glen - tmp_exon[i][1]), pos + (glen - tmp_exon[i][0])]);
|
||||||
}
|
}
|
||||||
|
if (skip_start) exon.shift();
|
||||||
|
if (skip_last) exon.pop();
|
||||||
} else {
|
} else {
|
||||||
var tmp_st = pos;
|
var tmp_st = pos;
|
||||||
while ((m = re_cigar.exec(cigar)) != null) {
|
while ((m = re_cigar.exec(cigar)) != null) {
|
||||||
@@ -3686,7 +3785,9 @@ function main(args)
|
|||||||
print(" mapeval evaluate mapping accuracy using mason2/PBSIM-simulated FASTQ");
|
print(" mapeval evaluate mapping accuracy using mason2/PBSIM-simulated FASTQ");
|
||||||
print(" pafcmp compare two PAF files");
|
print(" pafcmp compare two PAF files");
|
||||||
print(" mason2fq convert mason2-simulated SAM to FASTQ");
|
print(" mason2fq convert mason2-simulated SAM to FASTQ");
|
||||||
|
print(" sim2bed convert mason2-simulated read names to BED");
|
||||||
print(" pbsim2fq convert PBSIM-simulated MAF to FASTQ");
|
print(" pbsim2fq convert PBSIM-simulated MAF to FASTQ");
|
||||||
|
print(" badread2fa convert Baderead FASTQ to FASTA");
|
||||||
print(" junceval evaluate splice junction consistency with known annotations");
|
print(" junceval evaluate splice junction consistency with known annotations");
|
||||||
print(" exoneval evaluate exon-level consistency with known annotations");
|
print(" exoneval evaluate exon-level consistency with known annotations");
|
||||||
print(" ov-eval evaluate read overlap sensitivity using read-to-ref mapping");
|
print(" ov-eval evaluate read overlap sensitivity using read-to-ref mapping");
|
||||||
@@ -3711,7 +3812,9 @@ function main(args)
|
|||||||
else if (cmd == 'pafcmp') paf_pafcmp(args);
|
else if (cmd == 'pafcmp') paf_pafcmp(args);
|
||||||
else if (cmd == 'bedcov') paf_bedcov(args);
|
else if (cmd == 'bedcov') paf_bedcov(args);
|
||||||
else if (cmd == 'mason2fq') paf_mason2fq(args);
|
else if (cmd == 'mason2fq') paf_mason2fq(args);
|
||||||
|
else if (cmd == 'sim2bed') paf_sim2bed(args);
|
||||||
else if (cmd == 'pbsim2fq') paf_pbsim2fq(args);
|
else if (cmd == 'pbsim2fq') paf_pbsim2fq(args);
|
||||||
|
else if (cmd == 'badread2fa') paf_badread2fa(args);
|
||||||
else if (cmd == 'junceval') paf_junceval(args);
|
else if (cmd == 'junceval') paf_junceval(args);
|
||||||
else if (cmd == 'exoneval') paf_exoneval(args);
|
else if (cmd == 'exoneval') paf_exoneval(args);
|
||||||
else if (cmd == 'ov-eval') paf_ov_eval(args);
|
else if (cmd == 'ov-eval') paf_ov_eval(args);
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ void mm_select_sub_multi(void *km, float pri_ratio, float pri1, float pri2, int
|
|||||||
if (pri_ratio > 0.0f && *n_ > 0) {
|
if (pri_ratio > 0.0f && *n_ > 0) {
|
||||||
int i, k, n = *n_, n_2nd = 0;
|
int i, k, n = *n_, n_2nd = 0;
|
||||||
int max_dist = n_segs == 2? qlens[0] + qlens[1] + max_gap_ref : 0;
|
int max_dist = n_segs == 2? qlens[0] + qlens[1] + max_gap_ref : 0;
|
||||||
for (i = k = 0; i < n; ++i) {
|
uint8_t *keep = (uint8_t*)kmalloc(km, n);
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
int to_keep = 0;
|
int to_keep = 0;
|
||||||
if (r[i].parent == i) { // primary
|
if (r[i].parent == i) { // primary
|
||||||
to_keep = 1;
|
to_keep = 1;
|
||||||
@@ -34,9 +35,13 @@ void mm_select_sub_multi(void *km, float pri_ratio, float pri1, float pri2, int
|
|||||||
if (to_keep && r[i].parent != i) {
|
if (to_keep && r[i].parent != i) {
|
||||||
if (n_2nd++ >= best_n) to_keep = 0; // don't keep if there are too many secondary hits
|
if (n_2nd++ >= best_n) to_keep = 0; // don't keep if there are too many secondary hits
|
||||||
}
|
}
|
||||||
if (to_keep) r[k++] = r[i];
|
keep[i] = to_keep;
|
||||||
|
}
|
||||||
|
for (i = k = 0; i < n; ++i) {
|
||||||
|
if (keep[i]) r[k++] = r[i];
|
||||||
else if (r[i].p) free(r[i].p);
|
else if (r[i].p) free(r[i].p);
|
||||||
}
|
}
|
||||||
|
kfree(km, keep);
|
||||||
if (k != n) mm_sync_regs(km, k, r); // removing hits requires sync()
|
if (k != n) mm_sync_regs(km, k, r); // removing hits requires sync()
|
||||||
*n_ = k;
|
*n_ = k;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ cdef extern from "minimap.h":
|
|||||||
void mm_tbuf_destroy(mm_tbuf_t *b)
|
void mm_tbuf_destroy(mm_tbuf_t *b)
|
||||||
void *mm_tbuf_get_km(mm_tbuf_t *b)
|
void *mm_tbuf_get_km(mm_tbuf_t *b)
|
||||||
int mm_gen_cs(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq, int no_iden)
|
int mm_gen_cs(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq, int no_iden)
|
||||||
|
int mm_gen_ds(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq, int no_iden)
|
||||||
int mm_gen_MD(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq)
|
int mm_gen_MD(void *km, char **buf, int *max_len, const mm_idx_t *mi, const mm_reg1_t *r, const char *seq)
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
+16
-8
@@ -3,7 +3,7 @@ from libc.stdlib cimport free
|
|||||||
cimport cmappy
|
cimport cmappy
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
__version__ = '2.29'
|
__version__ = '2.31'
|
||||||
|
|
||||||
cmappy.mm_reset_timer()
|
cmappy.mm_reset_timer()
|
||||||
|
|
||||||
@@ -14,9 +14,9 @@ cdef class Alignment:
|
|||||||
cdef int8_t _strand, _trans_strand
|
cdef int8_t _strand, _trans_strand
|
||||||
cdef uint8_t _mapq, _is_primary
|
cdef uint8_t _mapq, _is_primary
|
||||||
cdef int _seg_id
|
cdef int _seg_id
|
||||||
cdef _ctg, _cigar, _cs, _MD # these are python objects
|
cdef _ctg, _cigar, _cs, _ds, _MD # these are python objects
|
||||||
|
|
||||||
def __cinit__(self, ctg, cl, cs, ce, strand, qs, qe, mapq, cigar, is_primary, mlen, blen, NM, trans_strand, seg_id, cs_str, MD_str):
|
def __cinit__(self, ctg, cl, cs, ce, strand, qs, qe, mapq, cigar, is_primary, mlen, blen, NM, trans_strand, seg_id, cs_str, ds_str, MD_str):
|
||||||
self._ctg = ctg if isinstance(ctg, str) else ctg.decode()
|
self._ctg = ctg if isinstance(ctg, str) else ctg.decode()
|
||||||
self._ctg_len, self._r_st, self._r_en = cl, cs, ce
|
self._ctg_len, self._r_st, self._r_en = cl, cs, ce
|
||||||
self._strand, self._q_st, self._q_en = strand, qs, qe
|
self._strand, self._q_st, self._q_en = strand, qs, qe
|
||||||
@@ -27,6 +27,7 @@ cdef class Alignment:
|
|||||||
self._trans_strand = trans_strand
|
self._trans_strand = trans_strand
|
||||||
self._seg_id = seg_id
|
self._seg_id = seg_id
|
||||||
self._cs = cs_str
|
self._cs = cs_str
|
||||||
|
self._ds = ds_str
|
||||||
self._MD = MD_str
|
self._MD = MD_str
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -77,6 +78,9 @@ cdef class Alignment:
|
|||||||
@property
|
@property
|
||||||
def cs(self): return self._cs
|
def cs(self): return self._cs
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ds(self): return self._ds
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def MD(self): return self._MD
|
def MD(self): return self._MD
|
||||||
|
|
||||||
@@ -96,6 +100,7 @@ cdef class Alignment:
|
|||||||
a = [str(self._q_st), str(self._q_en), strand, self._ctg, str(self._ctg_len), str(self._r_st), str(self._r_en),
|
a = [str(self._q_st), str(self._q_en), strand, self._ctg, str(self._ctg_len), str(self._r_st), str(self._r_en),
|
||||||
str(self._mlen), str(self._blen), str(self._mapq), tp, ts, "cg:Z:" + self.cigar_str]
|
str(self._mlen), str(self._blen), str(self._mapq), tp, ts, "cg:Z:" + self.cigar_str]
|
||||||
if self._cs != "": a.append("cs:Z:" + self._cs)
|
if self._cs != "": a.append("cs:Z:" + self._cs)
|
||||||
|
if self._ds != "": a.append("ds:Z:" + self._ds)
|
||||||
if self._MD != "": a.append("MD:Z:" + self._MD)
|
if self._MD != "": a.append("MD:Z:" + self._MD)
|
||||||
return "\t".join(a)
|
return "\t".join(a)
|
||||||
|
|
||||||
@@ -165,7 +170,7 @@ cdef class Aligner:
|
|||||||
def __bool__(self):
|
def __bool__(self):
|
||||||
return (self._idx != NULL)
|
return (self._idx != NULL)
|
||||||
|
|
||||||
def map(self, seq, seq2=None, name=None, buf=None, cs=False, MD=False, max_frag_len=None, extra_flags=None):
|
def map(self, seq, seq2=None, name=None, buf=None, cs=False, ds=False, MD=False, max_frag_len=None, extra_flags=None):
|
||||||
cdef cmappy.mm_reg1_t *regs
|
cdef cmappy.mm_reg1_t *regs
|
||||||
cdef cmappy.mm_hitpy_t h
|
cdef cmappy.mm_hitpy_t h
|
||||||
cdef ThreadBuffer b
|
cdef ThreadBuffer b
|
||||||
@@ -184,7 +189,6 @@ cdef class Aligner:
|
|||||||
if self._idx is NULL: return None
|
if self._idx is NULL: return None
|
||||||
if buf is None: b = ThreadBuffer()
|
if buf is None: b = ThreadBuffer()
|
||||||
else: b = buf
|
else: b = buf
|
||||||
km = cmappy.mm_tbuf_get_km(b._b)
|
|
||||||
|
|
||||||
_seq = seq if isinstance(seq, bytes) else seq.encode()
|
_seq = seq if isinstance(seq, bytes) else seq.encode()
|
||||||
if name is not None:
|
if name is not None:
|
||||||
@@ -206,19 +210,23 @@ cdef class Aligner:
|
|||||||
i = 0
|
i = 0
|
||||||
while i < n_regs:
|
while i < n_regs:
|
||||||
cmappy.mm_reg2hitpy(self._idx, ®s[i], &h)
|
cmappy.mm_reg2hitpy(self._idx, ®s[i], &h)
|
||||||
cigar, _cs, _MD = [], '', ''
|
cigar, _cs, _ds, _MD = [], '', '', ''
|
||||||
for k in range(h.n_cigar32): # convert the 32-bit CIGAR encoding to Python array
|
for k in range(h.n_cigar32): # convert the 32-bit CIGAR encoding to Python array
|
||||||
c = h.cigar32[k]
|
c = h.cigar32[k]
|
||||||
cigar.append([c>>4, c&0xf])
|
cigar.append([c>>4, c&0xf])
|
||||||
if cs or MD: # generate the cs and/or the MD tag, if requested
|
if cs or ds or MD: # generate the cs/ds and/or the MD tag, if requested
|
||||||
|
km = cmappy.mm_tbuf_get_km(b._b)
|
||||||
_cur_seq = _seq2 if h.seg_id > 0 and seq2 is not None else _seq
|
_cur_seq = _seq2 if h.seg_id > 0 and seq2 is not None else _seq
|
||||||
if cs:
|
if cs:
|
||||||
l_cs_str = cmappy.mm_gen_cs(km, &cs_str, &m_cs_str, self._idx, ®s[i], _cur_seq, 1)
|
l_cs_str = cmappy.mm_gen_cs(km, &cs_str, &m_cs_str, self._idx, ®s[i], _cur_seq, 1)
|
||||||
_cs = cs_str[:l_cs_str] if isinstance(cs_str, str) else cs_str[:l_cs_str].decode()
|
_cs = cs_str[:l_cs_str] if isinstance(cs_str, str) else cs_str[:l_cs_str].decode()
|
||||||
|
if ds:
|
||||||
|
l_cs_str = cmappy.mm_gen_ds(km, &cs_str, &m_cs_str, self._idx, ®s[i], _cur_seq, 1)
|
||||||
|
_ds = cs_str[:l_cs_str] if isinstance(cs_str, str) else cs_str[:l_cs_str].decode()
|
||||||
if MD:
|
if MD:
|
||||||
l_cs_str = cmappy.mm_gen_MD(km, &cs_str, &m_cs_str, self._idx, ®s[i], _cur_seq)
|
l_cs_str = cmappy.mm_gen_MD(km, &cs_str, &m_cs_str, self._idx, ®s[i], _cur_seq)
|
||||||
_MD = cs_str[:l_cs_str] if isinstance(cs_str, str) else cs_str[:l_cs_str].decode()
|
_MD = cs_str[:l_cs_str] if isinstance(cs_str, str) else cs_str[:l_cs_str].decode()
|
||||||
yield Alignment(h.ctg, h.ctg_len, h.ctg_start, h.ctg_end, h.strand, h.qry_start, h.qry_end, h.mapq, cigar, h.is_primary, h.mlen, h.blen, h.NM, h.trans_strand, h.seg_id, _cs, _MD)
|
yield Alignment(h.ctg, h.ctg_len, h.ctg_start, h.ctg_end, h.strand, h.qry_start, h.qry_end, h.mapq, cigar, h.is_primary, h.mlen, h.blen, h.NM, h.trans_strand, h.seg_id, _cs, _ds, _MD)
|
||||||
cmappy.mm_free_reg1(®s[i])
|
cmappy.mm_free_reg1(®s[i])
|
||||||
i += 1
|
i += 1
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
+5
-3
@@ -5,7 +5,7 @@ import getopt
|
|||||||
import mappy as mp
|
import mappy as mp
|
||||||
|
|
||||||
def main(argv):
|
def main(argv):
|
||||||
opts, args = getopt.getopt(argv[1:], "x:n:m:k:w:r:cM")
|
opts, args = getopt.getopt(argv[1:], "x:n:m:k:w:r:cdM")
|
||||||
if len(args) < 2:
|
if len(args) < 2:
|
||||||
print("Usage: minimap2.py [options] <ref.fa>|<ref.mmi> <query.fq>")
|
print("Usage: minimap2.py [options] <ref.fa>|<ref.mmi> <query.fq>")
|
||||||
print("Options:")
|
print("Options:")
|
||||||
@@ -16,11 +16,12 @@ def main(argv):
|
|||||||
print(" -w INT minimizer window length")
|
print(" -w INT minimizer window length")
|
||||||
print(" -r INT band width")
|
print(" -r INT band width")
|
||||||
print(" -c output the cs tag")
|
print(" -c output the cs tag")
|
||||||
|
print(" -d output the ds tag")
|
||||||
print(" -M output the MD tag")
|
print(" -M output the MD tag")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
preset = min_cnt = min_sc = k = w = bw = None
|
preset = min_cnt = min_sc = k = w = bw = None
|
||||||
out_cs = out_MD = False
|
out_cs = out_ds = out_MD = False
|
||||||
for opt, arg in opts:
|
for opt, arg in opts:
|
||||||
if opt == '-x': preset = arg
|
if opt == '-x': preset = arg
|
||||||
elif opt == '-n': min_cnt = int(arg)
|
elif opt == '-n': min_cnt = int(arg)
|
||||||
@@ -29,12 +30,13 @@ def main(argv):
|
|||||||
elif opt == '-k': k = int(arg)
|
elif opt == '-k': k = int(arg)
|
||||||
elif opt == '-w': w = int(arg)
|
elif opt == '-w': w = int(arg)
|
||||||
elif opt == '-c': out_cs = True
|
elif opt == '-c': out_cs = True
|
||||||
|
elif opt == '-d': out_ds = True
|
||||||
elif opt == '-M': out_MD = True
|
elif opt == '-M': out_MD = True
|
||||||
|
|
||||||
a = mp.Aligner(args[0], preset=preset, min_cnt=min_cnt, min_chain_score=min_sc, k=k, w=w, bw=bw)
|
a = mp.Aligner(args[0], preset=preset, min_cnt=min_cnt, min_chain_score=min_sc, k=k, w=w, bw=bw)
|
||||||
if not a: raise Exception("ERROR: failed to load/build index file '{}'".format(args[0]))
|
if not a: raise Exception("ERROR: failed to load/build index file '{}'".format(args[0]))
|
||||||
for name, seq, qual in mp.fastx_read(args[1]): # read one sequence
|
for name, seq, qual in mp.fastx_read(args[1]): # read one sequence
|
||||||
for h in a.map(seq, cs=out_cs, MD=out_MD): # traverse hits
|
for h in a.map(seq, cs=out_cs, ds=out_ds, MD=out_MD): # traverse hits
|
||||||
print('{}\t{}\t{}'.format(name, len(seq), h))
|
print('{}\t{}\t{}'.format(name, len(seq), h))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ def readme():
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name = 'mappy',
|
name = 'mappy',
|
||||||
version = '2.29',
|
version = '2.31',
|
||||||
url = 'https://github.com/lh3/minimap2',
|
url = 'https://github.com/lh3/minimap2',
|
||||||
description = 'Minimap2 python binding',
|
description = 'Minimap2 python binding',
|
||||||
long_description = readme(),
|
long_description = readme(),
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
mm2: TGTTATCCCTAGGGTAACTTGTTCCGTTGGTCAAGTTATTGGATCAATTGAGTATAGTAGTGCACTCAC......................................................................................................................................CACTTGGAGCCATTCATACAGGTCCCTATTTAAGGAACAAGTGATTATGCTACCTTTGCACGGTT
|
||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||
|
ref: TGTTATCCCTAGGGTAACTTGTTCCGTTGGTCAAGTTATTGGATCAATTGAGTATAGTAGTGCACTCACctGCTTCGCTTTGACTGGTGAAGTCTTAGCATGTACTGCTCGGAGGTTGGGTTCTGCTCCGAGGTCGCCCCAACCGAAATTTTTAATGCAGGTTTGGTAGTTTAGGACCTGTGGGTTTGTTAGGCTAACCTCacCACTTGGAGCCATTCATACAGGTCCCTATTTAAGGAACAAGTGATTATGCTACCTTTGCACGGTT
|
||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||
|
sta: TGTTATCCCTAGGGTAACTTGTTCCGTTGGTCAAGTTATTGGATCAATTGAGTATAGTAGTGCA......................................................................................................................................CTCACCACTTGGAGCCATTCATACAGGTCCCTATTTAAGGAACAAGTGATTATGCTACCTTTGCACGGTT
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
>query
|
||||||
|
AACCGTGCAAAGGTAGCATAATCACTTGTTCCTTAAATAGGGACCTGTATGAATGGCTCC
|
||||||
|
AAGTG
|
||||||
|
GTGAGTGCA
|
||||||
|
CTACTATACTCAATTGATCCAATAACTTGACCAACGGAACAAGTTACCCTAGGGATAACA
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
>ref
|
||||||
|
TGATCCAACATCGAGGTCGTAAACCCTATTGTTGATATGGACTCTAGAATAGGATTGCGC
|
||||||
|
TGTTATCCCTAGGGTAACTTGTTCCGTTGGTCAAGTTATTGGATCAATTGAGTATAGTAG
|
||||||
|
TGCACTCAC
|
||||||
|
ctGCTTCGCTTTGACTGGTGAAGTCTTAGCATGTACTGCTCGGAGGTTGGGTTCTGCTCC
|
||||||
|
GAGGTCGCCCCAACCGAAATTTTTAATGCAGGTTTGGTAGTTTAGGACCTGTGGGTTTGT
|
||||||
|
TAGGCTAACCTCac
|
||||||
|
CACTTGGAGCCATTCATACAGGTCCCTATTTAAGGAACAAGTGATTATGCTACCTTTGCA
|
||||||
|
CGGTTAGGGTACCGCGGCCGTTAAACATGTGTCACTGGGCAGGCGGTGCCTCTAATACTG
|
||||||
|
GTGAT
|
||||||
Reference in New Issue
Block a user