mirror of
https://github.com/lh3/minimap2.git
synced 2026-09-24 17:48:12 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53ce317e59 | ||
|
|
da6947cfa3 | ||
|
|
46d6349af4 | ||
|
|
12a5a5fa3c | ||
|
|
ad18fa490d | ||
|
|
43bfa6199d | ||
|
|
72b9b0e3b6 | ||
|
|
6205fa6f21 | ||
|
|
d676a5314b | ||
|
|
dfc78b39d3 | ||
|
|
7b57c9a619 | ||
|
|
123bc1d91d | ||
|
|
dd18307e66 | ||
|
|
543fa12e68 | ||
|
|
af1a871270 | ||
|
|
2b71181a37 | ||
|
|
0454e6be91 | ||
|
|
33f8157961 |
@@ -1,7 +1,7 @@
|
|||||||
CFLAGS= -g -Wall -O2 -Wc++-compat
|
CFLAGS= -g -Wall -O2 -Wc++-compat
|
||||||
CPPFLAGS= -DHAVE_KALLOC
|
CPPFLAGS= -DHAVE_KALLOC
|
||||||
INCLUDES=
|
INCLUDES=
|
||||||
OBJS= kthread.o kalloc.o misc.o bseq.o sketch.o sdust.o index.o chain.o align.o hit.o map.o format.o pe.o esterr.o ksw2_ll_sse.o
|
OBJS= kthread.o kalloc.o misc.o bseq.o sketch.o sdust.o options.o index.o chain.o align.o hit.o map.o format.o pe.o esterr.o ksw2_ll_sse.o
|
||||||
PROG= minimap2
|
PROG= minimap2
|
||||||
PROG_EXTRA= sdust minimap2-lite
|
PROG_EXTRA= sdust minimap2-lite
|
||||||
LIBS= -lm -lz -lpthread
|
LIBS= -lm -lz -lpthread
|
||||||
@@ -77,7 +77,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*
|
||||||
|
|
||||||
depend:
|
depend:
|
||||||
(LC_ALL=C; export LC_ALL; makedepend -Y -- $(CFLAGS) $(CPPFLAGS) -- *.c)
|
(LC_ALL=C; export LC_ALL; makedepend -Y -- $(CFLAGS) $(CPPFLAGS) -- *.c)
|
||||||
@@ -98,9 +98,12 @@ ksw2_extd2_sse.o: ksw2.h kalloc.h
|
|||||||
ksw2_exts2_sse.o: ksw2.h kalloc.h
|
ksw2_exts2_sse.o: ksw2.h kalloc.h
|
||||||
ksw2_extz2_sse.o: ksw2.h kalloc.h
|
ksw2_extz2_sse.o: ksw2.h kalloc.h
|
||||||
ksw2_ll_sse.o: ksw2.h kalloc.h
|
ksw2_ll_sse.o: ksw2.h kalloc.h
|
||||||
|
kthread.o: kthread.h
|
||||||
main.o: bseq.h minimap.h mmpriv.h getopt.h
|
main.o: bseq.h minimap.h mmpriv.h getopt.h
|
||||||
map.o: kthread.h kvec.h kalloc.h sdust.h mmpriv.h minimap.h bseq.h khash.h
|
map.o: kthread.h kvec.h kalloc.h sdust.h mmpriv.h minimap.h bseq.h khash.h
|
||||||
misc.o: minimap.h ksort.h
|
map.o: ksort.h
|
||||||
|
misc.o: mmpriv.h minimap.h bseq.h ksort.h
|
||||||
|
options.o: mmpriv.h minimap.h bseq.h
|
||||||
pe.o: mmpriv.h minimap.h bseq.h kvec.h kalloc.h ksort.h
|
pe.o: mmpriv.h minimap.h bseq.h kvec.h kalloc.h ksort.h
|
||||||
sdust.o: kalloc.h kdq.h kvec.h sdust.h
|
sdust.o: kalloc.h kdq.h kvec.h sdust.h
|
||||||
sketch.o: kvec.h kalloc.h minimap.h
|
sketch.o: kvec.h kalloc.h mmpriv.h minimap.h bseq.h
|
||||||
|
|||||||
@@ -1,3 +1,32 @@
|
|||||||
|
Release 2.8-r672 (1 February 2018)
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
Notable changes in this release include:
|
||||||
|
|
||||||
|
* Speed up short-read alignment by ~10%. The overall mapping accuracy stays
|
||||||
|
the same, but the output alignments are not always identical to v2.7 due to
|
||||||
|
unstable sorting employed during chaining. Long-read alignment is not
|
||||||
|
affected by this change as the speedup is short-read specific.
|
||||||
|
|
||||||
|
* Mappy now supports paired-end short-read alignment (#87). Please see
|
||||||
|
python/README.rst for details.
|
||||||
|
|
||||||
|
* Added option --for-only and --rev-only to perform alignment against the
|
||||||
|
forward or the reverse strand of the reference genome only (#91).
|
||||||
|
|
||||||
|
* Alleviated the issue with undesired diagonal alignment in the self mapping
|
||||||
|
mode (#10). Even if the output is not ideal, it should not interfere with
|
||||||
|
other alignments. Fully resolving the issue is intricate and may require
|
||||||
|
additional heuristic thresholds.
|
||||||
|
|
||||||
|
* Enhanced error checking against incorrect input (#92 and #96).
|
||||||
|
|
||||||
|
For long query sequences, minimap2 should output identical alignments to v2.7.
|
||||||
|
|
||||||
|
(2.8: 1 February 2018, r672)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Release 2.7-r654 (9 January 2018)
|
Release 2.7-r654 (9 January 2018)
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -68,9 +68,9 @@ Detailed evaluations are available from the [minimap2 preprint][preprint].
|
|||||||
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.7/minimap2-2.7_x64-linux.tar.bz2 \
|
curl -L https://github.com/lh3/minimap2/releases/download/v2.8/minimap2-2.8_x64-linux.tar.bz2 \
|
||||||
| tar -jxvf -
|
| tar -jxvf -
|
||||||
./minimap2-2.7_x64-linux/minimap2
|
./minimap2-2.8_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
|
||||||
@@ -359,10 +359,6 @@ mappy` or [from BioConda][mappyconda] via `conda install -c bioconda mappy`.
|
|||||||
possible to add non-SIMD support, but it would make minimap2 slower by
|
possible to add non-SIMD support, but it would make minimap2 slower by
|
||||||
several times.
|
several times.
|
||||||
|
|
||||||
In general, minimap2 is a young project with most code written since June, 2017.
|
|
||||||
It may have bugs and room for improvements. Bug reports and suggestions are
|
|
||||||
warmly welcomed.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[paf]: https://github.com/lh3/miniasm/blob/master/PAF.md
|
[paf]: https://github.com/lh3/miniasm/blob/master/PAF.md
|
||||||
|
|||||||
@@ -499,6 +499,14 @@ static void mm_align1(void *km, const mm_mapopt_t *opt, const mm_idx_t *mi, int
|
|||||||
re0 = re0 > re1? re0 : re1;
|
re0 = re0 > re1? re0 : re1;
|
||||||
} else re0 = re, qe0 = qe;
|
} else re0 = re, qe0 = qe;
|
||||||
}
|
}
|
||||||
|
if (a[r->as].y & MM_SEED_SELF) {
|
||||||
|
int max_ext = r->qs > r->rs? r->qs - r->rs : r->rs - r->qs;
|
||||||
|
if (r->rs - rs0 > max_ext) rs0 = r->rs - max_ext;
|
||||||
|
if (r->qs - qs0 > max_ext) qs0 = r->qs - max_ext;
|
||||||
|
max_ext = r->qe > r->re? r->qe - r->re : r->re - r->qe;
|
||||||
|
if (re0 - r->re > max_ext) re0 = r->re + max_ext;
|
||||||
|
if (qe0 - r->qe > max_ext) qe0 = r->qe + max_ext;
|
||||||
|
}
|
||||||
|
|
||||||
assert(re0 > rs0);
|
assert(re0 > rs0);
|
||||||
tseq = (uint8_t*)kmalloc(km, re0 - rs0);
|
tseq = (uint8_t*)kmalloc(km, re0 - rs0);
|
||||||
@@ -696,7 +704,7 @@ mm_reg1_t *mm_align_skeleton(void *km, const mm_mapopt_t *opt, const mm_idx_t *m
|
|||||||
regs[i].p->trans_strand = opt->flag&MM_F_SPLICE_FOR? 1 : 2;
|
regs[i].p->trans_strand = opt->flag&MM_F_SPLICE_FOR? 1 : 2;
|
||||||
}
|
}
|
||||||
if (r2.cnt > 0) regs = mm_insert_reg(&r2, i, &n_regs, regs);
|
if (r2.cnt > 0) regs = mm_insert_reg(&r2, i, &n_regs, regs);
|
||||||
if (!(opt->flag&MM_F_SPLICE) && !(opt->flag&MM_F_SR) && i > 0) { // don't try inversion alignment for -xsplice or -xsr
|
if (!(opt->flag&(MM_F_SPLICE|MM_F_SR)) && !(opt->flag&(MM_F_FOR_ONLY|MM_F_REV_ONLY)) && i > 0) { // don't try inversion alignment for -xsplice or -xsr, or --for-only/rev-only
|
||||||
if (mm_align1_inv(km, opt, mi, qlen, qseq0, ®s[i-1], ®s[i], &r2, &ez)) {
|
if (mm_align1_inv(km, opt, mi, qlen, qseq0, ®s[i-1], ®s[i], &r2, &ez)) {
|
||||||
regs = mm_insert_reg(&r2, i, &n_regs, regs);
|
regs = mm_insert_reg(&r2, i, &n_regs, regs);
|
||||||
++i; // skip the inserted INV alignment
|
++i; // skip the inserted INV alignment
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#define __STDC_LIMIT_MACROS
|
||||||
#include "bseq.h"
|
#include "bseq.h"
|
||||||
#include "kvec.h"
|
#include "kvec.h"
|
||||||
#include "kseq.h"
|
#include "kseq.h"
|
||||||
@@ -114,10 +115,15 @@ mm_bseq1_t *mm_bseq_read_frag(int n_fp, mm_bseq_file_t **fp, int chunk_size, int
|
|||||||
*n_ = 0;
|
*n_ = 0;
|
||||||
if (n_fp < 1) return 0;
|
if (n_fp < 1) return 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
int n_read = 0;
|
||||||
for (i = 0; i < n_fp; ++i)
|
for (i = 0; i < n_fp; ++i)
|
||||||
if (kseq_read(fp[i]->ks) < 0)
|
if (kseq_read(fp[i]->ks) >= 0)
|
||||||
break;
|
++n_read;
|
||||||
if (i != n_fp) break; // some file reaches the end
|
if (n_read < n_fp) {
|
||||||
|
if (n_read > 0)
|
||||||
|
fprintf(stderr, "[W::%s]\033[1;31m query files have different number of records; extra records skipped.\033[0m\n", __func__);
|
||||||
|
break; // some file reaches the end
|
||||||
|
}
|
||||||
if (a.m == 0) kv_resize(mm_bseq1_t, 0, a, 256);
|
if (a.m == 0) kv_resize(mm_bseq1_t, 0, a, 256);
|
||||||
for (i = 0; i < n_fp; ++i) {
|
for (i = 0; i < n_fp; ++i) {
|
||||||
mm_bseq1_t *s;
|
mm_bseq1_t *s;
|
||||||
|
|||||||
@@ -390,8 +390,10 @@ mm_seg_t *mm_seg_gen(void *km, uint32_t hash, int n_segs, const int *qlens, int
|
|||||||
for (s = 0; s < n_segs; ++s) {
|
for (s = 0; s < n_segs; ++s) {
|
||||||
regs[s] = mm_gen_regs(km, hash, qlens[s], seg[s].n_u, seg[s].u, seg[s].a);
|
regs[s] = mm_gen_regs(km, hash, qlens[s], seg[s].n_u, seg[s].u, seg[s].a);
|
||||||
n_regs[s] = seg[s].n_u;
|
n_regs[s] = seg[s].n_u;
|
||||||
for (i = 0; i < n_regs[s]; ++i)
|
for (i = 0; i < n_regs[s]; ++i) {
|
||||||
regs[s][i].seg_split = 1;
|
regs[s][i].seg_split = 1;
|
||||||
|
regs[s][i].seg_id = s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return seg;
|
return seg;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#define __STDC_LIMIT_MACROS
|
||||||
#include "kthread.h"
|
#include "kthread.h"
|
||||||
#include "bseq.h"
|
#include "bseq.h"
|
||||||
#include "minimap.h"
|
#include "minimap.h"
|
||||||
|
|||||||
@@ -39,7 +39,24 @@ typedef struct {
|
|||||||
|
|
||||||
#define KSORT_SWAP(type_t, a, b) { register type_t t=(a); (a)=(b); (b)=t; }
|
#define KSORT_SWAP(type_t, a, b) { register type_t t=(a); (a)=(b); (b)=t; }
|
||||||
|
|
||||||
#define KSORT_INIT(name, type_t, __sort_lt) \
|
#define KSORT_INIT(name, type_t, __sort_lt) \
|
||||||
|
void ks_heapdown_##name(size_t i, size_t n, type_t l[]) \
|
||||||
|
{ \
|
||||||
|
size_t k = i; \
|
||||||
|
type_t tmp = l[i]; \
|
||||||
|
while ((k = (k << 1) + 1) < n) { \
|
||||||
|
if (k != n - 1 && __sort_lt(l[k], l[k+1])) ++k; \
|
||||||
|
if (__sort_lt(l[k], tmp)) break; \
|
||||||
|
l[i] = l[k]; i = k; \
|
||||||
|
} \
|
||||||
|
l[i] = tmp; \
|
||||||
|
} \
|
||||||
|
void ks_heapmake_##name(size_t lsize, type_t l[]) \
|
||||||
|
{ \
|
||||||
|
size_t i; \
|
||||||
|
for (i = (lsize >> 1) - 1; i != (size_t)(-1); --i) \
|
||||||
|
ks_heapdown_##name(i, lsize, l); \
|
||||||
|
} \
|
||||||
type_t ks_ksmall_##name(size_t n, type_t arr[], size_t kk) \
|
type_t ks_ksmall_##name(size_t n, type_t arr[], size_t kk) \
|
||||||
{ \
|
{ \
|
||||||
type_t *low, *high, *k, *ll, *hh, *mid; \
|
type_t *low, *high, *k, *ll, *hh, *mid; \
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "kthread.h"
|
||||||
|
|
||||||
#if (defined(WIN32) || defined(_WIN32)) && defined(_MSC_VER)
|
#if (defined(WIN32) || defined(_WIN32)) && defined(_MSC_VER)
|
||||||
#define __sync_fetch_and_add(ptr, addend) _InterlockedExchangeAdd((void*)ptr, addend)
|
#define __sync_fetch_and_add(ptr, addend) _InterlockedExchangeAdd((void*)ptr, addend)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "mmpriv.h"
|
#include "mmpriv.h"
|
||||||
#include "getopt.h"
|
#include "getopt.h"
|
||||||
|
|
||||||
#define MM_VERSION "2.7-r654"
|
#define MM_VERSION "2.8-r672"
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
@@ -28,7 +28,7 @@ static struct option long_options[] = {
|
|||||||
{ "seed", required_argument, 0, 0 },
|
{ "seed", required_argument, 0, 0 },
|
||||||
{ "no-kalloc", no_argument, 0, 0 },
|
{ "no-kalloc", no_argument, 0, 0 },
|
||||||
{ "print-qname", no_argument, 0, 0 },
|
{ "print-qname", no_argument, 0, 0 },
|
||||||
{ "no-self", no_argument, 0, 0 },
|
{ "no-self", no_argument, 0, 'D' },
|
||||||
{ "print-seeds", no_argument, 0, 0 },
|
{ "print-seeds", no_argument, 0, 0 },
|
||||||
{ "max-chain-skip", required_argument, 0, 0 },
|
{ "max-chain-skip", required_argument, 0, 0 },
|
||||||
{ "min-dp-len", required_argument, 0, 0 },
|
{ "min-dp-len", required_argument, 0, 0 },
|
||||||
@@ -37,14 +37,19 @@ static struct option long_options[] = {
|
|||||||
{ "cost-non-gt-ag", required_argument, 0, 'C' },
|
{ "cost-non-gt-ag", required_argument, 0, 'C' },
|
||||||
{ "no-long-join", no_argument, 0, 0 },
|
{ "no-long-join", no_argument, 0, 0 },
|
||||||
{ "sr", no_argument, 0, 0 },
|
{ "sr", no_argument, 0, 0 },
|
||||||
{ "frag", optional_argument, 0, 0 },
|
{ "frag", required_argument, 0, 0 },
|
||||||
{ "secondary", optional_argument, 0, 0 },
|
{ "secondary", required_argument, 0, 0 },
|
||||||
{ "cs", optional_argument, 0, 0 },
|
{ "cs", optional_argument, 0, 0 },
|
||||||
{ "end-bonus", required_argument, 0, 0 },
|
{ "end-bonus", required_argument, 0, 0 },
|
||||||
{ "no-pairing", no_argument, 0, 0 },
|
{ "no-pairing", no_argument, 0, 0 },
|
||||||
{ "splice-flank", optional_argument, 0, 0 },
|
{ "splice-flank", required_argument, 0, 0 },
|
||||||
{ "idx-no-seq", no_argument, 0, 0 },
|
{ "idx-no-seq", no_argument, 0, 0 },
|
||||||
{ "end-seed-pen", required_argument, 0, 0 }, // 21
|
{ "end-seed-pen", required_argument, 0, 0 }, // 21
|
||||||
|
{ "for-only", no_argument, 0, 0 }, // 22
|
||||||
|
{ "rev-only", no_argument, 0, 0 }, // 23
|
||||||
|
{ "heap-sort", required_argument, 0, 0 }, // 24
|
||||||
|
{ "all-chain", no_argument, 0, 'P' },
|
||||||
|
{ "dual", required_argument, 0, 0 }, // 26
|
||||||
{ "help", no_argument, 0, 'h' },
|
{ "help", no_argument, 0, 'h' },
|
||||||
{ "max-intron-len", required_argument, 0, 'G' },
|
{ "max-intron-len", required_argument, 0, 'G' },
|
||||||
{ "version", no_argument, 0, 'V' },
|
{ "version", no_argument, 0, 'V' },
|
||||||
@@ -67,9 +72,22 @@ static inline int64_t mm_parse_num(const char *str)
|
|||||||
return (int64_t)(x + .499);
|
return (int64_t)(x + .499);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void yes_or_no(mm_mapopt_t *opt, int flag, int long_idx, const char *arg, int yes_to_set)
|
||||||
|
{
|
||||||
|
if (yes_to_set) {
|
||||||
|
if (strcmp(arg, "yes") == 0 || strcmp(arg, "y") == 0) opt->flag |= flag;
|
||||||
|
else if (strcmp(arg, "no") == 0 || strcmp(arg, "n") == 0) opt->flag &= ~flag;
|
||||||
|
else fprintf(stderr, "[WARNING]\033[1;31m option '--%s' only accepts 'yes' or 'no'.\033[0m\n", long_options[long_idx].name);
|
||||||
|
} else {
|
||||||
|
if (strcmp(arg, "yes") == 0 || strcmp(arg, "y") == 0) opt->flag &= ~flag;
|
||||||
|
else if (strcmp(arg, "no") == 0 || strcmp(arg, "n") == 0) opt->flag |= flag;
|
||||||
|
else fprintf(stderr, "[WARNING]\033[1;31m option '--%s' only accepts 'yes' or 'no'.\033[0m\n", long_options[long_idx].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
const char *opt_str = "2aSw:k:K:t:r:f:Vv:g:G:I:d:XT:s:x:Hcp:M:n:z:A:B:O:E:m:N:Qu:R:hF:LC:";
|
const char *opt_str = "2aSDw:k:K:t:r:f:Vv:g:G:I:d:XT:s:x:Hcp:M:n:z:A:B:O:E:m:N:Qu:R:hF:LC:";
|
||||||
mm_mapopt_t opt;
|
mm_mapopt_t opt;
|
||||||
mm_idxopt_t ipt;
|
mm_idxopt_t ipt;
|
||||||
int i, c, n_threads = 3, long_idx;
|
int i, c, n_threads = 3, long_idx;
|
||||||
@@ -108,7 +126,9 @@ int main(int argc, char *argv[])
|
|||||||
else if (c == 'p') opt.pri_ratio = atof(optarg);
|
else if (c == 'p') opt.pri_ratio = atof(optarg);
|
||||||
else if (c == 'M') opt.mask_level = atof(optarg);
|
else if (c == 'M') opt.mask_level = atof(optarg);
|
||||||
else if (c == 'c') opt.flag |= MM_F_OUT_CG | MM_F_CIGAR;
|
else if (c == 'c') opt.flag |= MM_F_OUT_CG | MM_F_CIGAR;
|
||||||
else if (c == 'X') opt.flag |= MM_F_AVA | MM_F_NO_SELF;
|
else if (c == 'D') opt.flag |= MM_F_NO_DIAG;
|
||||||
|
else if (c == 'P') opt.flag |= MM_F_ALL_CHAINS;
|
||||||
|
else if (c == 'X') opt.flag |= MM_F_ALL_CHAINS | MM_F_NO_DIAG | MM_F_NO_DUAL | MM_F_NO_LJOIN; // -D -P --no-long-join --dual=no
|
||||||
else if (c == 'a') opt.flag |= MM_F_OUT_SAM | MM_F_CIGAR;
|
else if (c == 'a') opt.flag |= MM_F_OUT_SAM | MM_F_CIGAR;
|
||||||
else if (c == 'Q') opt.flag |= MM_F_NO_QUAL;
|
else if (c == 'Q') opt.flag |= MM_F_NO_QUAL;
|
||||||
else if (c == 'Y') opt.flag |= MM_F_SOFTCLIP;
|
else if (c == 'Y') opt.flag |= MM_F_SOFTCLIP;
|
||||||
@@ -130,7 +150,6 @@ int main(int argc, char *argv[])
|
|||||||
else if (c == 0 && long_idx == 2) opt.seed = atoi(optarg); // --seed
|
else if (c == 0 && long_idx == 2) opt.seed = atoi(optarg); // --seed
|
||||||
else if (c == 0 && long_idx == 3) mm_dbg_flag |= MM_DBG_NO_KALLOC; // --no-kalloc
|
else if (c == 0 && long_idx == 3) mm_dbg_flag |= MM_DBG_NO_KALLOC; // --no-kalloc
|
||||||
else if (c == 0 && long_idx == 4) mm_dbg_flag |= MM_DBG_PRINT_QNAME; // --print-qname
|
else if (c == 0 && long_idx == 4) mm_dbg_flag |= MM_DBG_PRINT_QNAME; // --print-qname
|
||||||
else if (c == 0 && long_idx == 5) opt.flag |= MM_F_NO_SELF; // --no-self
|
|
||||||
else if (c == 0 && long_idx == 6) mm_dbg_flag |= MM_DBG_PRINT_QNAME | MM_DBG_PRINT_SEED, n_threads = 1; // --print-seed
|
else if (c == 0 && long_idx == 6) mm_dbg_flag |= MM_DBG_PRINT_QNAME | MM_DBG_PRINT_SEED, n_threads = 1; // --print-seed
|
||||||
else if (c == 0 && long_idx == 7) opt.max_chain_skip = atoi(optarg); // --max-chain-skip
|
else if (c == 0 && long_idx == 7) opt.max_chain_skip = atoi(optarg); // --max-chain-skip
|
||||||
else if (c == 0 && long_idx == 8) opt.min_ksw_len = atoi(optarg); // --min-dp-len
|
else if (c == 0 && long_idx == 8) opt.min_ksw_len = atoi(optarg); // --min-dp-len
|
||||||
@@ -142,14 +161,12 @@ int main(int argc, char *argv[])
|
|||||||
else if (c == 0 && long_idx ==18) opt.flag |= MM_F_INDEPEND_SEG; // --no-pairing
|
else if (c == 0 && long_idx ==18) opt.flag |= MM_F_INDEPEND_SEG; // --no-pairing
|
||||||
else if (c == 0 && long_idx ==20) ipt.flag |= MM_I_NO_SEQ; // --idx-no-seq
|
else if (c == 0 && long_idx ==20) ipt.flag |= MM_I_NO_SEQ; // --idx-no-seq
|
||||||
else if (c == 0 && long_idx ==21) opt.anchor_ext_shift = atoi(optarg); // --end-seed-pen
|
else if (c == 0 && long_idx ==21) opt.anchor_ext_shift = atoi(optarg); // --end-seed-pen
|
||||||
|
else if (c == 0 && long_idx ==22) opt.flag |= MM_F_FOR_ONLY; // --for-only
|
||||||
|
else if (c == 0 && long_idx ==23) opt.flag |= MM_F_REV_ONLY; // --rev-only
|
||||||
else if (c == 0 && long_idx == 14) { // --frag
|
else if (c == 0 && long_idx == 14) { // --frag
|
||||||
if (optarg == 0 || strcmp(optarg, "yes") == 0 || strcmp(optarg, "y") == 0)
|
yes_or_no(&opt, MM_F_FRAG_MODE, long_idx, optarg, 1);
|
||||||
opt.flag |= MM_F_FRAG_MODE;
|
|
||||||
else opt.flag &= ~MM_F_FRAG_MODE;
|
|
||||||
} else if (c == 0 && long_idx == 15) { // --secondary
|
} else if (c == 0 && long_idx == 15) { // --secondary
|
||||||
if (optarg == 0 || strcmp(optarg, "yes") == 0 || strcmp(optarg, "y") == 0)
|
yes_or_no(&opt, MM_F_NO_PRINT_2ND, long_idx, optarg, 0);
|
||||||
opt.flag &= ~MM_F_NO_PRINT_2ND;
|
|
||||||
else opt.flag |= MM_F_NO_PRINT_2ND;
|
|
||||||
} else if (c == 0 && long_idx == 16) { // --cs
|
} else if (c == 0 && long_idx == 16) { // --cs
|
||||||
opt.flag |= MM_F_OUT_CS | MM_F_CIGAR;
|
opt.flag |= MM_F_OUT_CS | MM_F_CIGAR;
|
||||||
if (optarg == 0 || strcmp(optarg, "short") == 0) {
|
if (optarg == 0 || strcmp(optarg, "short") == 0) {
|
||||||
@@ -162,9 +179,11 @@ int main(int argc, char *argv[])
|
|||||||
fprintf(stderr, "[WARNING]\033[1;31m --cs only takes 'short' or 'long'. Invalid values are assumed to be 'short'.\033[0m\n");
|
fprintf(stderr, "[WARNING]\033[1;31m --cs only takes 'short' or 'long'. Invalid values are assumed to be 'short'.\033[0m\n");
|
||||||
}
|
}
|
||||||
} else if (c == 0 && long_idx == 19) { // --splice-flank
|
} else if (c == 0 && long_idx == 19) { // --splice-flank
|
||||||
if (optarg == 0 || strcmp(optarg, "yes") == 0 || strcmp(optarg, "y") == 0)
|
yes_or_no(&opt, MM_F_SPLICE_FLANK, long_idx, optarg, 1);
|
||||||
opt.flag |= MM_F_SPLICE_FLANK;
|
} else if (c == 0 && long_idx == 24) { // --heap-sort
|
||||||
else opt.flag &= ~MM_F_SPLICE_FLANK;
|
yes_or_no(&opt, MM_F_HEAP_SORT, long_idx, optarg, 1);
|
||||||
|
} else if (c == 0 && long_idx == 26) { // --dual
|
||||||
|
yes_or_no(&opt, MM_F_NO_DUAL, long_idx, optarg, 0);
|
||||||
} else if (c == 'S') {
|
} else if (c == 'S') {
|
||||||
opt.flag |= MM_F_OUT_CS | MM_F_CIGAR | MM_F_OUT_CS_LONG;
|
opt.flag |= MM_F_OUT_CS | MM_F_CIGAR | MM_F_OUT_CS_LONG;
|
||||||
if (mm_verbose >= 2)
|
if (mm_verbose >= 2)
|
||||||
@@ -252,14 +271,18 @@ int main(int argc, char *argv[])
|
|||||||
fprintf(fp_help, " map-ont: -k15 (Oxford Nanopore vs reference mapping)\n");
|
fprintf(fp_help, " map-ont: -k15 (Oxford Nanopore vs reference mapping)\n");
|
||||||
fprintf(fp_help, " asm5: -k19 -w19 -A1 -B19 -O39,81 -E3,1 -s200 -z200 (asm to ref mapping; break at 5%% div.)\n");
|
fprintf(fp_help, " asm5: -k19 -w19 -A1 -B19 -O39,81 -E3,1 -s200 -z200 (asm to ref mapping; break at 5%% div.)\n");
|
||||||
fprintf(fp_help, " asm10: -k19 -w19 -A1 -B9 -O16,41 -E2,1 -s200 -z200 (asm to ref mapping; break at 10%% div.)\n");
|
fprintf(fp_help, " asm10: -k19 -w19 -A1 -B9 -O16,41 -E2,1 -s200 -z200 (asm to ref mapping; break at 10%% div.)\n");
|
||||||
fprintf(fp_help, " ava-pb: -Hk19 -w5 -Xp0 -m100 -g10000 --max-chain-skip 25 (PacBio read overlap)\n");
|
fprintf(fp_help, " ava-pb: -Hk19 -Xw5 -m100 -g10000 --max-chain-skip 25 (PacBio read overlap)\n");
|
||||||
fprintf(fp_help, " ava-ont: -k15 -w5 -Xp0 -m100 -g10000 --max-chain-skip 25 (ONT read overlap)\n");
|
fprintf(fp_help, " ava-ont: -k15 -Xw5 -m100 -g10000 --max-chain-skip 25 (ONT read overlap)\n");
|
||||||
fprintf(fp_help, " splice: long-read spliced alignment (see minimap2.1 for details)\n");
|
fprintf(fp_help, " splice: long-read spliced alignment (see minimap2.1 for details)\n");
|
||||||
fprintf(fp_help, " sr: short single-end reads without splicing (see minimap2.1 for details)\n");
|
fprintf(fp_help, " sr: short single-end reads without splicing (see minimap2.1 for details)\n");
|
||||||
fprintf(fp_help, "\nSee `man ./minimap2.1' for detailed description of command-line options.\n");
|
fprintf(fp_help, "\nSee `man ./minimap2.1' for detailed description of command-line options.\n");
|
||||||
return fp_help == stdout? 0 : 1;
|
return fp_help == stdout? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((opt.flag & MM_F_SR) && argc - optind > 3) {
|
||||||
|
fprintf(stderr, "[ERROR] incorrect input: in the sr mode, please specify no more than two query files.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
idx_rdr = mm_idx_reader_open(argv[optind], &ipt, fnw);
|
idx_rdr = mm_idx_reader_open(argv[optind], &ipt, fnw);
|
||||||
if (idx_rdr == 0) {
|
if (idx_rdr == 0) {
|
||||||
fprintf(stderr, "[ERROR] failed to open file '%s'\n", argv[optind]);
|
fprintf(stderr, "[ERROR] failed to open file '%s'\n", argv[optind]);
|
||||||
|
|||||||
@@ -9,134 +9,6 @@
|
|||||||
#include "bseq.h"
|
#include "bseq.h"
|
||||||
#include "khash.h"
|
#include "khash.h"
|
||||||
|
|
||||||
void mm_mapopt_init(mm_mapopt_t *opt)
|
|
||||||
{
|
|
||||||
memset(opt, 0, sizeof(mm_mapopt_t));
|
|
||||||
opt->seed = 11;
|
|
||||||
opt->mid_occ_frac = 2e-4f;
|
|
||||||
opt->sdust_thres = 0; // no SDUST masking
|
|
||||||
|
|
||||||
opt->min_cnt = 3;
|
|
||||||
opt->min_chain_score = 40;
|
|
||||||
opt->bw = 500;
|
|
||||||
opt->max_gap = 5000;
|
|
||||||
opt->max_gap_ref = -1;
|
|
||||||
opt->max_chain_skip = 25;
|
|
||||||
|
|
||||||
opt->mask_level = 0.5f;
|
|
||||||
opt->pri_ratio = 0.8f;
|
|
||||||
opt->best_n = 5;
|
|
||||||
|
|
||||||
opt->max_join_long = 20000;
|
|
||||||
opt->max_join_short = 2000;
|
|
||||||
opt->min_join_flank_sc = 1000;
|
|
||||||
|
|
||||||
opt->a = 2, opt->b = 4, opt->q = 4, opt->e = 2, opt->q2 = 24, opt->e2 = 1;
|
|
||||||
opt->zdrop = 400;
|
|
||||||
opt->end_bonus = -1;
|
|
||||||
opt->min_dp_max = opt->min_chain_score * opt->a;
|
|
||||||
opt->min_ksw_len = 200;
|
|
||||||
opt->anchor_ext_len = 20, opt->anchor_ext_shift = 6;
|
|
||||||
opt->mini_batch_size = 500000000;
|
|
||||||
|
|
||||||
opt->pe_ori = 0; // FF
|
|
||||||
opt->pe_bonus = 33;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mm_mapopt_update(mm_mapopt_t *opt, const mm_idx_t *mi)
|
|
||||||
{
|
|
||||||
if ((opt->flag & MM_F_SPLICE_FOR) && (opt->flag & MM_F_SPLICE_REV))
|
|
||||||
opt->flag |= MM_F_SPLICE;
|
|
||||||
if (opt->mid_occ <= 0)
|
|
||||||
opt->mid_occ = mm_idx_cal_max_occ(mi, opt->mid_occ_frac);
|
|
||||||
if (mm_verbose >= 3)
|
|
||||||
fprintf(stderr, "[M::%s::%.3f*%.2f] mid_occ = %d\n", __func__, realtime() - mm_realtime0, cputime() / (realtime() - mm_realtime0), opt->mid_occ);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mm_mapopt_max_intron_len(mm_mapopt_t *opt, int max_intron_len)
|
|
||||||
{
|
|
||||||
if ((opt->flag & MM_F_SPLICE) && max_intron_len > 0)
|
|
||||||
opt->max_gap_ref = opt->bw = max_intron_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mm_set_opt(const char *preset, mm_idxopt_t *io, mm_mapopt_t *mo)
|
|
||||||
{
|
|
||||||
if (preset == 0) {
|
|
||||||
mm_idxopt_init(io);
|
|
||||||
mm_mapopt_init(mo);
|
|
||||||
} else if (strcmp(preset, "ava-ont") == 0) {
|
|
||||||
io->flag = 0, io->k = 15, io->w = 5;
|
|
||||||
mo->flag |= MM_F_AVA | MM_F_NO_SELF;
|
|
||||||
mo->min_chain_score = 100, mo->pri_ratio = 0.0f, mo->max_gap = 10000, mo->max_chain_skip = 25;
|
|
||||||
} else if (strcmp(preset, "ava-pb") == 0) {
|
|
||||||
io->flag |= MM_I_HPC, io->k = 19, io->w = 5;
|
|
||||||
mo->flag |= MM_F_AVA | MM_F_NO_SELF;
|
|
||||||
mo->min_chain_score = 100, mo->pri_ratio = 0.0f, mo->max_gap = 10000, mo->max_chain_skip = 25;
|
|
||||||
} else if (strcmp(preset, "map10k") == 0 || strcmp(preset, "map-pb") == 0) {
|
|
||||||
io->flag |= MM_I_HPC, io->k = 19;
|
|
||||||
} else if (strcmp(preset, "map-ont") == 0) {
|
|
||||||
io->flag = 0, io->k = 15;
|
|
||||||
} else if (strcmp(preset, "asm5") == 0) {
|
|
||||||
io->flag = 0, io->k = 19, io->w = 19;
|
|
||||||
mo->a = 1, mo->b = 19, mo->q = 39, mo->q2 = 81, mo->e = 3, mo->e2 = 1, mo->zdrop = 200;
|
|
||||||
mo->min_dp_max = 200;
|
|
||||||
mo->best_n = 50;
|
|
||||||
} else if (strcmp(preset, "asm10") == 0) {
|
|
||||||
io->flag = 0, io->k = 19, io->w = 19;
|
|
||||||
mo->a = 1, mo->b = 9, mo->q = 16, mo->q2 = 41, mo->e = 2, mo->e2 = 1, mo->zdrop = 200;
|
|
||||||
mo->min_dp_max = 200;
|
|
||||||
mo->best_n = 50;
|
|
||||||
} else if (strcmp(preset, "short") == 0 || strcmp(preset, "sr") == 0) {
|
|
||||||
io->flag = 0, io->k = 21, io->w = 11;
|
|
||||||
mo->flag |= MM_F_SR | MM_F_FRAG_MODE | MM_F_NO_PRINT_2ND | MM_F_2_IO_THREADS;
|
|
||||||
mo->pe_ori = 0<<1|1; // FR
|
|
||||||
mo->a = 2, mo->b = 8, mo->q = 12, mo->e = 2, mo->q2 = 24, mo->e2 = 1;
|
|
||||||
mo->zdrop = 100;
|
|
||||||
mo->end_bonus = 10;
|
|
||||||
mo->max_frag_len = 800;
|
|
||||||
mo->max_gap = 100;
|
|
||||||
mo->bw = 100;
|
|
||||||
mo->pri_ratio = 0.5f;
|
|
||||||
mo->min_cnt = 2;
|
|
||||||
mo->min_chain_score = 25;
|
|
||||||
mo->min_dp_max = 40;
|
|
||||||
mo->best_n = 20;
|
|
||||||
mo->mid_occ = 1000;
|
|
||||||
mo->max_occ = 5000;
|
|
||||||
mo->mini_batch_size = 50000000;
|
|
||||||
} else if (strcmp(preset, "splice") == 0 || strcmp(preset, "cdna") == 0) {
|
|
||||||
io->flag = 0, io->k = 15, io->w = 5;
|
|
||||||
mo->flag |= MM_F_SPLICE | MM_F_SPLICE_FOR | MM_F_SPLICE_REV | MM_F_SPLICE_FLANK;
|
|
||||||
mo->max_gap = 2000, mo->max_gap_ref = mo->bw = 200000;
|
|
||||||
mo->a = 1, mo->b = 2, mo->q = 2, mo->e = 1, mo->q2 = 32, mo->e2 = 0;
|
|
||||||
mo->noncan = 9;
|
|
||||||
mo->zdrop = 200;
|
|
||||||
} else return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mm_check_opt(const mm_idxopt_t *io, const mm_mapopt_t *mo)
|
|
||||||
{
|
|
||||||
if ((mo->q != mo->q2 || mo->e != mo->e2) && !(mo->e > mo->e2 && mo->q + mo->e < mo->q2 + mo->e2)) {
|
|
||||||
if (mm_verbose >= 1)
|
|
||||||
fprintf(stderr, "[ERROR]\033[1;31m dual gap penalties violating E1>E2 and O1+E1<O2+E2\033[0m\n");
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
if ((mo->q + mo->e) + (mo->q2 + mo->e2) > 127) {
|
|
||||||
if (mm_verbose >= 1)
|
|
||||||
fprintf(stderr, "[ERROR]\033[1;31m scoring system violating ({-O}+{-E})+({-O2}+{-E2}) <= 127\033[0m\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t n;
|
|
||||||
uint32_t qpos;
|
|
||||||
uint32_t seg_id;
|
|
||||||
const uint64_t *cr;
|
|
||||||
} mm_match_t;
|
|
||||||
|
|
||||||
struct mm_tbuf_s {
|
struct mm_tbuf_s {
|
||||||
void *km;
|
void *km;
|
||||||
};
|
};
|
||||||
@@ -196,88 +68,189 @@ static void collect_minimizers(void *km, const mm_mapopt_t *opt, const mm_idx_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static mm128_t *collect_seed_hits(void *km, const mm_mapopt_t *opt, int max_occ, const mm_idx_t *mi, const char *qname, const mm128_v *mv, int qlen, int64_t *n_a, int *rep_len,
|
#include "ksort.h"
|
||||||
int *n_mini_pos, uint64_t **mini_pos)
|
#define heap_lt(a, b) ((a).x > (b).x)
|
||||||
{
|
KSORT_INIT(heap, mm128_t, heap_lt)
|
||||||
int rep_st = 0, rep_en = 0, i;
|
|
||||||
mm_match_t *m;
|
|
||||||
mm128_t *a;
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t n;
|
||||||
|
uint32_t q_pos, q_span;
|
||||||
|
uint32_t seg_id:31, is_tandem:1;
|
||||||
|
const uint64_t *cr;
|
||||||
|
} mm_match_t;
|
||||||
|
|
||||||
|
static mm_match_t *collect_matches(void *km, int *_n_m, int max_occ, const mm_idx_t *mi, const mm128_v *mv, int64_t *n_a, int *rep_len, int *n_mini_pos, uint64_t **mini_pos)
|
||||||
|
{
|
||||||
|
int i, rep_st = 0, rep_en = 0, n_m;
|
||||||
|
mm_match_t *m;
|
||||||
*n_mini_pos = 0;
|
*n_mini_pos = 0;
|
||||||
*mini_pos = (uint64_t*)kmalloc(km, mv->n * sizeof(uint64_t));
|
*mini_pos = (uint64_t*)kmalloc(km, mv->n * sizeof(uint64_t));
|
||||||
m = (mm_match_t*)kmalloc(km, mv->n * sizeof(mm_match_t));
|
m = (mm_match_t*)kmalloc(km, mv->n * sizeof(mm_match_t));
|
||||||
for (i = 0; i < mv->n; ++i) {
|
for (i = n_m = 0, *rep_len = 0, *n_a = 0; i < mv->n; ++i) {
|
||||||
|
const uint64_t *cr;
|
||||||
|
mm128_t *p = &mv->a[i];
|
||||||
|
uint32_t q_pos = (uint32_t)p->y, q_span = p->x & 0xff;
|
||||||
int t;
|
int t;
|
||||||
mm128_t *p = &mv->a[i];
|
cr = mm_idx_get(mi, p->x>>8, &t);
|
||||||
m[i].qpos = (uint32_t)p->y;
|
if (t >= max_occ) {
|
||||||
m[i].cr = mm_idx_get(mi, p->x>>8, &t);
|
int en = (q_pos >> 1) + 1, st = en - q_span;
|
||||||
m[i].n = t;
|
|
||||||
m[i].seg_id = p->y >> 32;
|
|
||||||
}
|
|
||||||
for (i = 0, *n_a = 0; i < mv->n; ++i) // find the length of a[]
|
|
||||||
if (m[i].n < max_occ) *n_a += m[i].n;
|
|
||||||
a = (mm128_t*)kmalloc(km, *n_a * sizeof(mm128_t));
|
|
||||||
for (i = *rep_len = 0, *n_a = 0; i < mv->n; ++i) {
|
|
||||||
mm128_t *p = &mv->a[i];
|
|
||||||
mm_match_t *q = &m[i];
|
|
||||||
const uint64_t *r = q->cr;
|
|
||||||
int k, q_span = p->x & 0xff, is_tandem = 0;
|
|
||||||
if (q->n >= max_occ) {
|
|
||||||
int en = (q->qpos>>1) + 1, st = en - q_span;
|
|
||||||
if (st > rep_en) {
|
if (st > rep_en) {
|
||||||
*rep_len += rep_en - rep_st;
|
*rep_len += rep_en - rep_st;
|
||||||
rep_st = st, rep_en = en;
|
rep_st = st, rep_en = en;
|
||||||
} else rep_en = en;
|
} else rep_en = en;
|
||||||
continue;
|
} else {
|
||||||
}
|
mm_match_t *q = &m[n_m++];
|
||||||
(*mini_pos)[(*n_mini_pos)++] = (uint64_t)q_span<<32 | q->qpos>>1;
|
q->q_pos = q_pos, q->q_span = q_span, q->cr = cr, q->n = t, q->seg_id = p->y >> 32;
|
||||||
if (i > 0 && p->x>>8 == mv->a[i - 1].x>>8) is_tandem = 1;
|
q->is_tandem = 0;
|
||||||
if (i < mv->n - 1 && p->x>>8 == mv->a[i + 1].x>>8) is_tandem = 1;
|
if (i > 0 && p->x>>8 == mv->a[i - 1].x>>8) q->is_tandem = 1;
|
||||||
for (k = 0; k < q->n; ++k) {
|
if (i < mv->n - 1 && p->x>>8 == mv->a[i + 1].x>>8) q->is_tandem = 1;
|
||||||
int32_t rpos = (uint32_t)r[k] >> 1;
|
*n_a += q->n;
|
||||||
mm128_t *p;
|
(*mini_pos)[(*n_mini_pos)++] = (uint64_t)q_span<<32 | q_pos>>1;
|
||||||
if (qname && (opt->flag&(MM_F_NO_SELF|MM_F_AVA))) {
|
|
||||||
const char *tname = mi->seq[r[k]>>32].name;
|
|
||||||
int cmp;
|
|
||||||
cmp = strcmp(qname, tname);
|
|
||||||
if ((opt->flag&MM_F_NO_SELF) && cmp == 0 && rpos == (q->qpos>>1)) // avoid the diagonal
|
|
||||||
continue;
|
|
||||||
if ((opt->flag&MM_F_AVA) && cmp > 0) // all-vs-all mode: map once
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
p = &a[(*n_a)++];
|
|
||||||
if ((r[k]&1) == (q->qpos&1)) { // forward strand
|
|
||||||
p->x = (r[k]&0xffffffff00000000ULL) | rpos;
|
|
||||||
p->y = (uint64_t)q_span << 32 | q->qpos >> 1;
|
|
||||||
} else { // reverse strand
|
|
||||||
p->x = 1ULL<<63 | (r[k]&0xffffffff00000000ULL) | rpos;
|
|
||||||
p->y = (uint64_t)q_span << 32 | (qlen - ((q->qpos>>1) + 1 - q_span) - 1);
|
|
||||||
}
|
|
||||||
p->y |= (uint64_t)q->seg_id << MM_SEED_SEG_SHIFT;
|
|
||||||
if (is_tandem) p->y |= MM_SEED_TANDEM;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*rep_len += rep_en - rep_st;
|
*rep_len += rep_en - rep_st;
|
||||||
|
*_n_m = n_m;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int skip_seed(int flag, uint64_t r, const mm_match_t *q, const char *qname, int qlen, const mm_idx_t *mi, int *is_self)
|
||||||
|
{
|
||||||
|
*is_self = 0;
|
||||||
|
if (qname && (flag & (MM_F_NO_DIAG|MM_F_NO_DUAL))) {
|
||||||
|
const mm_idx_seq_t *s = &mi->seq[r>>32];
|
||||||
|
int cmp;
|
||||||
|
cmp = strcmp(qname, s->name);
|
||||||
|
if ((flag&MM_F_NO_DIAG) && cmp == 0 && s->len == qlen) {
|
||||||
|
if ((uint32_t)r>>1 == (q->q_pos>>1)) return 1; // avoid the diagnonal anchors
|
||||||
|
if ((r&1) == (q->q_pos&1)) *is_self = 1; // this flag is used to avoid spurious extension on self chain
|
||||||
|
}
|
||||||
|
if ((flag&MM_F_NO_DUAL) && cmp > 0) // all-vs-all mode: map once
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (flag & (MM_F_FOR_ONLY|MM_F_REV_ONLY)) {
|
||||||
|
if ((r&1) == (q->q_pos&1)) { // forward strand
|
||||||
|
if (flag & MM_F_REV_ONLY) return 1;
|
||||||
|
} else {
|
||||||
|
if (flag & MM_F_FOR_ONLY) return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mm128_t *collect_seed_hits_heap(void *km, const mm_mapopt_t *opt, int max_occ, const mm_idx_t *mi, const char *qname, const mm128_v *mv, int qlen, int64_t *n_a, int *rep_len,
|
||||||
|
int *n_mini_pos, uint64_t **mini_pos)
|
||||||
|
{
|
||||||
|
int i, n_m, heap_size = 0;
|
||||||
|
int64_t j, n_for = 0, n_rev = 0;
|
||||||
|
mm_match_t *m;
|
||||||
|
mm128_t *a, *heap;
|
||||||
|
|
||||||
|
m = collect_matches(km, &n_m, max_occ, mi, mv, n_a, rep_len, n_mini_pos, mini_pos);
|
||||||
|
|
||||||
|
heap = (mm128_t*)kmalloc(km, n_m * sizeof(mm128_t));
|
||||||
|
a = (mm128_t*)kmalloc(km, *n_a * sizeof(mm128_t));
|
||||||
|
|
||||||
|
for (i = 0, heap_size = 0; i < n_m; ++i) {
|
||||||
|
if (m[i].n > 0) {
|
||||||
|
heap[heap_size].x = m[i].cr[0];
|
||||||
|
heap[heap_size].y = (uint64_t)i<<32;
|
||||||
|
++heap_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ks_heapmake_heap(heap_size, heap);
|
||||||
|
while (heap_size > 0) {
|
||||||
|
mm_match_t *q = &m[heap->y>>32];
|
||||||
|
mm128_t *p;
|
||||||
|
uint64_t r = heap->x;
|
||||||
|
int32_t is_self, rpos = (uint32_t)r >> 1;
|
||||||
|
if (skip_seed(opt->flag, r, q, qname, qlen, mi, &is_self)) continue;
|
||||||
|
if ((r&1) == (q->q_pos&1)) { // forward strand
|
||||||
|
p = &a[n_for++];
|
||||||
|
p->x = (r&0xffffffff00000000ULL) | rpos;
|
||||||
|
p->y = (uint64_t)q->q_span << 32 | q->q_pos >> 1;
|
||||||
|
} else { // reverse strand
|
||||||
|
p = &a[(*n_a) - (++n_rev)];
|
||||||
|
p->x = 1ULL<<63 | (r&0xffffffff00000000ULL) | rpos;
|
||||||
|
p->y = (uint64_t)q->q_span << 32 | (qlen - ((q->q_pos>>1) + 1 - q->q_span) - 1);
|
||||||
|
}
|
||||||
|
p->y |= (uint64_t)q->seg_id << MM_SEED_SEG_SHIFT;
|
||||||
|
if (q->is_tandem) p->y |= MM_SEED_TANDEM;
|
||||||
|
if (is_self) p->y |= MM_SEED_SELF;
|
||||||
|
// update the heap
|
||||||
|
if ((uint32_t)heap->y < q->n - 1) {
|
||||||
|
++heap[0].y;
|
||||||
|
heap[0].x = m[heap[0].y>>32].cr[(uint32_t)heap[0].y];
|
||||||
|
} else {
|
||||||
|
heap[0] = heap[heap_size - 1];
|
||||||
|
--heap_size;
|
||||||
|
}
|
||||||
|
ks_heapdown_heap(0, heap_size, heap);
|
||||||
|
}
|
||||||
kfree(km, m);
|
kfree(km, m);
|
||||||
|
kfree(km, heap);
|
||||||
|
|
||||||
|
// reverse anchors on the reverse strand, as they are in the descending order
|
||||||
|
for (j = 0; j < n_rev>>1; ++j) {
|
||||||
|
mm128_t t = a[(*n_a) - 1 - j];
|
||||||
|
a[(*n_a) - 1 - j] = a[(*n_a) - (n_rev - j)];
|
||||||
|
a[(*n_a) - (n_rev - j)] = t;
|
||||||
|
}
|
||||||
|
if (*n_a > n_for + n_rev) {
|
||||||
|
memmove(a + n_for, a + (*n_a) - n_rev, n_rev * sizeof(mm128_t));
|
||||||
|
*n_a = n_for + n_rev;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mm128_t *collect_seed_hits(void *km, const mm_mapopt_t *opt, int max_occ, const mm_idx_t *mi, const char *qname, const mm128_v *mv, int qlen, int64_t *n_a, int *rep_len,
|
||||||
|
int *n_mini_pos, uint64_t **mini_pos)
|
||||||
|
{
|
||||||
|
int i, k, n_m;
|
||||||
|
mm_match_t *m;
|
||||||
|
mm128_t *a;
|
||||||
|
m = collect_matches(km, &n_m, max_occ, mi, mv, n_a, rep_len, n_mini_pos, mini_pos);
|
||||||
|
a = (mm128_t*)kmalloc(km, *n_a * sizeof(mm128_t));
|
||||||
|
for (i = 0, *n_a = 0; i < n_m; ++i) {
|
||||||
|
mm_match_t *q = &m[i];
|
||||||
|
const uint64_t *r = q->cr;
|
||||||
|
for (k = 0; k < q->n; ++k) {
|
||||||
|
int32_t is_self, rpos = (uint32_t)r[k] >> 1;
|
||||||
|
mm128_t *p;
|
||||||
|
if (skip_seed(opt->flag, r[k], q, qname, qlen, mi, &is_self)) continue;
|
||||||
|
p = &a[(*n_a)++];
|
||||||
|
if ((r[k]&1) == (q->q_pos&1)) { // forward strand
|
||||||
|
p->x = (r[k]&0xffffffff00000000ULL) | rpos;
|
||||||
|
p->y = (uint64_t)q->q_span << 32 | q->q_pos >> 1;
|
||||||
|
} else { // reverse strand
|
||||||
|
p->x = 1ULL<<63 | (r[k]&0xffffffff00000000ULL) | rpos;
|
||||||
|
p->y = (uint64_t)q->q_span << 32 | (qlen - ((q->q_pos>>1) + 1 - q->q_span) - 1);
|
||||||
|
}
|
||||||
|
p->y |= (uint64_t)q->seg_id << MM_SEED_SEG_SHIFT;
|
||||||
|
if (q->is_tandem) p->y |= MM_SEED_TANDEM;
|
||||||
|
if (is_self) p->y |= MM_SEED_SELF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kfree(km, m);
|
||||||
|
radix_sort_128x(a, a + (*n_a));
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chain_post(const mm_mapopt_t *opt, int max_chain_gap_ref, const mm_idx_t *mi, void *km, int qlen, int n_segs, const int *qlens, int *n_regs, mm_reg1_t *regs, mm128_t *a)
|
static void chain_post(const mm_mapopt_t *opt, int max_chain_gap_ref, const mm_idx_t *mi, void *km, int qlen, int n_segs, const int *qlens, int *n_regs, mm_reg1_t *regs, mm128_t *a)
|
||||||
{
|
{
|
||||||
if (!(opt->flag & MM_F_AVA)) { // don't choose primary mapping(s) for read overlap
|
if (!(opt->flag & MM_F_ALL_CHAINS)) { // don't choose primary mapping(s)
|
||||||
mm_set_parent(km, opt->mask_level, *n_regs, regs, opt->a * 2 + opt->b);
|
mm_set_parent(km, opt->mask_level, *n_regs, regs, opt->a * 2 + opt->b);
|
||||||
if (n_segs <= 1) mm_select_sub(km, opt->pri_ratio, mi->k*2, opt->best_n, n_regs, regs);
|
if (n_segs <= 1) mm_select_sub(km, opt->pri_ratio, mi->k*2, opt->best_n, n_regs, regs);
|
||||||
else mm_select_sub_multi(km, opt->pri_ratio, 0.2f, 0.7f, max_chain_gap_ref, mi->k*2, opt->best_n, n_segs, qlens, n_regs, regs);
|
else mm_select_sub_multi(km, opt->pri_ratio, 0.2f, 0.7f, max_chain_gap_ref, mi->k*2, opt->best_n, n_segs, qlens, n_regs, regs);
|
||||||
if (!(opt->flag & MM_F_SPLICE) && !(opt->flag & MM_F_SR) && !(opt->flag & MM_F_NO_LJOIN))
|
if (!(opt->flag & (MM_F_SPLICE|MM_F_SR|MM_F_NO_LJOIN))) // long join not working well without primary chains
|
||||||
mm_join_long(km, opt, qlen, n_regs, regs, a);
|
mm_join_long(km, opt, qlen, n_regs, regs, a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static mm_reg1_t *align_regs(const mm_mapopt_t *opt, const mm_idx_t *mi, void *km, int qlen, const char *seq, const char *qual, int *n_regs, mm_reg1_t *regs, mm128_t *a)
|
static mm_reg1_t *align_regs(const mm_mapopt_t *opt, const mm_idx_t *mi, void *km, int qlen, const char *seq, int *n_regs, mm_reg1_t *regs, mm128_t *a)
|
||||||
{
|
{
|
||||||
if (!(opt->flag & MM_F_CIGAR)) return regs;
|
if (!(opt->flag & MM_F_CIGAR)) return regs;
|
||||||
regs = mm_align_skeleton(km, opt, mi, qlen, seq, n_regs, regs, a); // this calls mm_filter_regs()
|
regs = mm_align_skeleton(km, opt, mi, qlen, seq, n_regs, regs, a); // this calls mm_filter_regs()
|
||||||
if (!(opt->flag & MM_F_AVA)) {
|
if (!(opt->flag & MM_F_ALL_CHAINS)) { // don't choose primary mapping(s)
|
||||||
mm_set_parent(km, opt->mask_level, *n_regs, regs, opt->a * 2 + opt->b);
|
mm_set_parent(km, opt->mask_level, *n_regs, regs, opt->a * 2 + opt->b);
|
||||||
mm_select_sub(km, opt->pri_ratio, mi->k*2, opt->best_n, n_regs, regs);
|
mm_select_sub(km, opt->pri_ratio, mi->k*2, opt->best_n, n_regs, regs);
|
||||||
mm_set_sam_pri(*n_regs, regs);
|
mm_set_sam_pri(*n_regs, regs);
|
||||||
@@ -285,7 +258,7 @@ static mm_reg1_t *align_regs(const mm_mapopt_t *opt, const mm_idx_t *mi, void *k
|
|||||||
return regs;
|
return regs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mm_map_frag(const mm_idx_t *mi, int n_segs, const int *qlens, const char **seqs, const char **quals, int *n_regs, mm_reg1_t **regs, mm_tbuf_t *b, const mm_mapopt_t *opt, const char *qname)
|
void mm_map_frag(const mm_idx_t *mi, int n_segs, const int *qlens, const char **seqs, int *n_regs, mm_reg1_t **regs, mm_tbuf_t *b, const mm_mapopt_t *opt, const char *qname)
|
||||||
{
|
{
|
||||||
int i, j, rep_len, qlen_sum, n_regs0, n_mini_pos;
|
int i, j, rep_len, qlen_sum, n_regs0, n_mini_pos;
|
||||||
int max_chain_gap_qry, max_chain_gap_ref, is_splice = !!(opt->flag & MM_F_SPLICE), is_sr = !!(opt->flag & MM_F_SR);
|
int max_chain_gap_qry, max_chain_gap_ref, is_splice = !!(opt->flag & MM_F_SPLICE), is_sr = !!(opt->flag & MM_F_SR);
|
||||||
@@ -307,8 +280,8 @@ void mm_map_frag(const mm_idx_t *mi, int n_segs, const int *qlens, const char **
|
|||||||
hash = __ac_Wang_hash(hash);
|
hash = __ac_Wang_hash(hash);
|
||||||
|
|
||||||
collect_minimizers(b->km, opt, mi, n_segs, qlens, seqs, &mv);
|
collect_minimizers(b->km, opt, mi, n_segs, qlens, seqs, &mv);
|
||||||
a = collect_seed_hits(b->km, opt, opt->mid_occ, mi, qname, &mv, qlen_sum, &n_a, &rep_len, &n_mini_pos, &mini_pos);
|
if (opt->flag & MM_F_HEAP_SORT) a = collect_seed_hits_heap(b->km, opt, opt->mid_occ, mi, qname, &mv, qlen_sum, &n_a, &rep_len, &n_mini_pos, &mini_pos);
|
||||||
radix_sort_128x(a, a + n_a);
|
else a = collect_seed_hits(b->km, opt, opt->mid_occ, mi, qname, &mv, qlen_sum, &n_a, &rep_len, &n_mini_pos, &mini_pos);
|
||||||
|
|
||||||
if (mm_dbg_flag & MM_DBG_PRINT_SEED) {
|
if (mm_dbg_flag & MM_DBG_PRINT_SEED) {
|
||||||
fprintf(stderr, "RS\t%d\n", rep_len);
|
fprintf(stderr, "RS\t%d\n", rep_len);
|
||||||
@@ -348,8 +321,8 @@ void mm_map_frag(const mm_idx_t *mi, int n_segs, const int *qlens, const char **
|
|||||||
kfree(b->km, a);
|
kfree(b->km, a);
|
||||||
kfree(b->km, u);
|
kfree(b->km, u);
|
||||||
kfree(b->km, mini_pos);
|
kfree(b->km, mini_pos);
|
||||||
a = collect_seed_hits(b->km, opt, opt->max_occ, mi, qname, &mv, qlen_sum, &n_a, &rep_len, &n_mini_pos, &mini_pos);
|
if (opt->flag & MM_F_HEAP_SORT) a = collect_seed_hits_heap(b->km, opt, opt->max_occ, mi, qname, &mv, qlen_sum, &n_a, &rep_len, &n_mini_pos, &mini_pos);
|
||||||
radix_sort_128x(a, a + n_a);
|
else a = collect_seed_hits(b->km, opt, opt->max_occ, mi, qname, &mv, qlen_sum, &n_a, &rep_len, &n_mini_pos, &mini_pos);
|
||||||
a = mm_chain_dp(max_chain_gap_ref, max_chain_gap_qry, opt->bw, opt->max_chain_skip, opt->min_cnt, opt->min_chain_score, is_splice, n_segs, n_a, a, &n_regs0, &u, b->km);
|
a = mm_chain_dp(max_chain_gap_ref, max_chain_gap_qry, opt->bw, opt->max_chain_skip, opt->min_cnt, opt->min_chain_score, is_splice, n_segs, n_a, a, &n_regs0, &u, b->km);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -366,7 +339,7 @@ void mm_map_frag(const mm_idx_t *mi, int n_segs, const int *qlens, const char **
|
|||||||
if (!is_sr) mm_est_err(mi, qlen_sum, n_regs0, regs0, a, n_mini_pos, mini_pos);
|
if (!is_sr) mm_est_err(mi, qlen_sum, n_regs0, regs0, a, n_mini_pos, mini_pos);
|
||||||
|
|
||||||
if (n_segs == 1) { // uni-segment
|
if (n_segs == 1) { // uni-segment
|
||||||
regs0 = align_regs(opt, mi, b->km, qlens[0], seqs[0], quals? quals[0] : 0, &n_regs0, regs0, a);
|
regs0 = align_regs(opt, mi, b->km, qlens[0], seqs[0], &n_regs0, regs0, a);
|
||||||
mm_set_mapq(n_regs0, regs0, opt->min_chain_score, opt->a, rep_len, is_sr);
|
mm_set_mapq(n_regs0, regs0, opt->min_chain_score, opt->a, rep_len, is_sr);
|
||||||
n_regs[0] = n_regs0, regs[0] = regs0;
|
n_regs[0] = n_regs0, regs[0] = regs0;
|
||||||
} else { // multi-segment
|
} else { // multi-segment
|
||||||
@@ -375,7 +348,7 @@ void mm_map_frag(const mm_idx_t *mi, int n_segs, const int *qlens, const char **
|
|||||||
free(regs0);
|
free(regs0);
|
||||||
for (i = 0; i < n_segs; ++i) {
|
for (i = 0; i < n_segs; ++i) {
|
||||||
mm_set_parent(b->km, opt->mask_level, n_regs[i], regs[i], opt->a * 2 + opt->b); // update mm_reg1_t::parent
|
mm_set_parent(b->km, opt->mask_level, n_regs[i], regs[i], opt->a * 2 + opt->b); // update mm_reg1_t::parent
|
||||||
regs[i] = align_regs(opt, mi, b->km, qlens[i], seqs[i], quals? quals[i] : 0, &n_regs[i], regs[i], seg[i].a);
|
regs[i] = align_regs(opt, mi, b->km, qlens[i], seqs[i], &n_regs[i], regs[i], seg[i].a);
|
||||||
mm_set_mapq(n_regs[i], regs[i], opt->min_chain_score, opt->a, rep_len, is_sr);
|
mm_set_mapq(n_regs[i], regs[i], opt->min_chain_score, opt->a, rep_len, is_sr);
|
||||||
}
|
}
|
||||||
mm_seg_free(b->km, n_segs, seg);
|
mm_seg_free(b->km, n_segs, seg);
|
||||||
@@ -403,7 +376,7 @@ void mm_map_frag(const mm_idx_t *mi, int n_segs, const int *qlens, const char **
|
|||||||
mm_reg1_t *mm_map(const mm_idx_t *mi, int qlen, const char *seq, int *n_regs, mm_tbuf_t *b, const mm_mapopt_t *opt, const char *qname)
|
mm_reg1_t *mm_map(const mm_idx_t *mi, int qlen, const char *seq, int *n_regs, mm_tbuf_t *b, const mm_mapopt_t *opt, const char *qname)
|
||||||
{
|
{
|
||||||
mm_reg1_t *regs;
|
mm_reg1_t *regs;
|
||||||
mm_map_frag(mi, 1, &qlen, &seq, 0, n_regs, ®s, b, opt, qname);
|
mm_map_frag(mi, 1, &qlen, &seq, n_regs, ®s, b, opt, qname);
|
||||||
return regs;
|
return regs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,11 +404,10 @@ typedef struct {
|
|||||||
static void worker_for(void *_data, long i, int tid) // kt_for() callback
|
static void worker_for(void *_data, long i, int tid) // kt_for() callback
|
||||||
{
|
{
|
||||||
step_t *s = (step_t*)_data;
|
step_t *s = (step_t*)_data;
|
||||||
int qlens[MM_MAX_SEG], j, off = s->seg_off[i], pe_ori = s->p->opt->pe_ori, is_sr = !!(s->p->opt->flag & MM_F_SR);
|
int qlens[MM_MAX_SEG], j, off = s->seg_off[i], pe_ori = s->p->opt->pe_ori;
|
||||||
const char *qseqs[MM_MAX_SEG], *quals[MM_MAX_SEG];
|
const char *qseqs[MM_MAX_SEG];
|
||||||
mm_tbuf_t *b = s->buf[tid];
|
mm_tbuf_t *b = s->buf[tid];
|
||||||
assert(s->n_seg[i] <= MM_MAX_SEG);
|
assert(s->n_seg[i] <= MM_MAX_SEG);
|
||||||
memset(quals, 0, sizeof(char*) * MM_MAX_SEG);
|
|
||||||
if (mm_dbg_flag & MM_DBG_PRINT_QNAME)
|
if (mm_dbg_flag & MM_DBG_PRINT_QNAME)
|
||||||
fprintf(stderr, "QR\t%s\t%d\t%d\n", s->seq[off].name, tid, s->seq[off].l_seq);
|
fprintf(stderr, "QR\t%s\t%d\t%d\n", s->seq[off].name, tid, s->seq[off].l_seq);
|
||||||
for (j = 0; j < s->n_seg[i]; ++j) {
|
for (j = 0; j < s->n_seg[i]; ++j) {
|
||||||
@@ -443,13 +415,12 @@ static void worker_for(void *_data, long i, int tid) // kt_for() callback
|
|||||||
mm_revcomp_bseq(&s->seq[off + j]);
|
mm_revcomp_bseq(&s->seq[off + j]);
|
||||||
qlens[j] = s->seq[off + j].l_seq;
|
qlens[j] = s->seq[off + j].l_seq;
|
||||||
qseqs[j] = s->seq[off + j].seq;
|
qseqs[j] = s->seq[off + j].seq;
|
||||||
quals[j] = is_sr? s->seq[off + j].qual : 0;
|
|
||||||
}
|
}
|
||||||
if (s->p->opt->flag & MM_F_INDEPEND_SEG) {
|
if (s->p->opt->flag & MM_F_INDEPEND_SEG) {
|
||||||
for (j = 0; j < s->n_seg[i]; ++j)
|
for (j = 0; j < s->n_seg[i]; ++j)
|
||||||
mm_map_frag(s->p->mi, 1, &qlens[j], &qseqs[j], &quals[j], &s->n_reg[off+j], &s->reg[off+j], b, s->p->opt, s->seq[off+j].name);
|
mm_map_frag(s->p->mi, 1, &qlens[j], &qseqs[j], &s->n_reg[off+j], &s->reg[off+j], b, s->p->opt, s->seq[off+j].name);
|
||||||
} else {
|
} else {
|
||||||
mm_map_frag(s->p->mi, s->n_seg[i], qlens, qseqs, quals, &s->n_reg[off], &s->reg[off], b, s->p->opt, s->seq[off].name);
|
mm_map_frag(s->p->mi, s->n_seg[i], qlens, qseqs, &s->n_reg[off], &s->reg[off], b, s->p->opt, s->seq[off].name);
|
||||||
}
|
}
|
||||||
for (j = 0; j < s->n_seg[i]; ++j) // flip the query strand and coordinate to the original read strand
|
for (j = 0; j < s->n_seg[i]; ++j) // flip the query strand and coordinate to the original read strand
|
||||||
if (s->n_seg[i] == 2 && ((j == 0 && (pe_ori>>1&1)) || (j == 1 && (pe_ori&1)))) {
|
if (s->n_seg[i] == 2 && ((j == 0 && (pe_ori>>1&1)) || (j == 1 && (pe_ori&1)))) {
|
||||||
|
|||||||
@@ -5,26 +5,30 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#define MM_F_NO_SELF 0x001
|
#define MM_F_NO_DIAG 0x001 // no exact diagonal hit
|
||||||
#define MM_F_AVA 0x002
|
#define MM_F_NO_DUAL 0x002 // skip pairs where query name is lexicographically larger than target name
|
||||||
#define MM_F_CIGAR 0x004
|
#define MM_F_CIGAR 0x004
|
||||||
#define MM_F_OUT_SAM 0x008
|
#define MM_F_OUT_SAM 0x008
|
||||||
#define MM_F_NO_QUAL 0x010
|
#define MM_F_NO_QUAL 0x010
|
||||||
#define MM_F_OUT_CG 0x020
|
#define MM_F_OUT_CG 0x020
|
||||||
#define MM_F_OUT_CS 0x040
|
#define MM_F_OUT_CS 0x040
|
||||||
#define MM_F_SPLICE 0x080 // splice mode
|
#define MM_F_SPLICE 0x080 // splice mode
|
||||||
#define MM_F_SPLICE_FOR 0x100 // match GT-AG
|
#define MM_F_SPLICE_FOR 0x100 // match GT-AG
|
||||||
#define MM_F_SPLICE_REV 0x200 // match CT-AC, the reverse complement of GT-AG
|
#define MM_F_SPLICE_REV 0x200 // match CT-AC, the reverse complement of GT-AG
|
||||||
#define MM_F_NO_LJOIN 0x400
|
#define MM_F_NO_LJOIN 0x400
|
||||||
#define MM_F_OUT_CS_LONG 0x800
|
#define MM_F_OUT_CS_LONG 0x800
|
||||||
#define MM_F_SR 0x1000
|
#define MM_F_SR 0x1000
|
||||||
#define MM_F_FRAG_MODE 0x2000
|
#define MM_F_FRAG_MODE 0x2000
|
||||||
#define MM_F_NO_PRINT_2ND 0x4000
|
#define MM_F_NO_PRINT_2ND 0x4000
|
||||||
#define MM_F_2_IO_THREADS 0x8000
|
#define MM_F_2_IO_THREADS 0x8000
|
||||||
#define MM_F_LONG_CIGAR 0x10000
|
#define MM_F_LONG_CIGAR 0x10000
|
||||||
#define MM_F_INDEPEND_SEG 0x20000
|
#define MM_F_INDEPEND_SEG 0x20000
|
||||||
#define MM_F_SPLICE_FLANK 0x40000
|
#define MM_F_SPLICE_FLANK 0x40000
|
||||||
#define MM_F_SOFTCLIP 0x80000
|
#define MM_F_SOFTCLIP 0x80000
|
||||||
|
#define MM_F_FOR_ONLY 0x100000
|
||||||
|
#define MM_F_REV_ONLY 0x200000
|
||||||
|
#define MM_F_HEAP_SORT 0x400000
|
||||||
|
#define MM_F_ALL_CHAINS 0x800000
|
||||||
|
|
||||||
#define MM_I_HPC 0x1
|
#define MM_I_HPC 0x1
|
||||||
#define MM_I_NO_SEQ 0x2
|
#define MM_I_NO_SEQ 0x2
|
||||||
@@ -78,7 +82,7 @@ typedef struct {
|
|||||||
int32_t mlen, blen; // seeded exact match length; seeded alignment block length
|
int32_t mlen, blen; // seeded exact match length; seeded alignment block length
|
||||||
int32_t n_sub; // number of suboptimal mappings
|
int32_t n_sub; // number of suboptimal mappings
|
||||||
int32_t score0; // initial chaining score (before chain merging/spliting)
|
int32_t score0; // initial chaining score (before chain merging/spliting)
|
||||||
uint32_t mapq:8, split:2, rev:1, inv:1, sam_pri:1, proper_frag:1, pe_thru:1, seg_split:1, dummy:16;
|
uint32_t mapq:8, split:2, rev:1, inv:1, sam_pri:1, proper_frag:1, pe_thru:1, seg_split:1, seg_id:8, dummy:8;
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
float div;
|
float div;
|
||||||
mm_extra_t *p;
|
mm_extra_t *p;
|
||||||
@@ -276,6 +280,8 @@ void mm_tbuf_destroy(mm_tbuf_t *b);
|
|||||||
*/
|
*/
|
||||||
mm_reg1_t *mm_map(const mm_idx_t *mi, int l_seq, const char *seq, int *n_regs, mm_tbuf_t *b, const mm_mapopt_t *opt, const char *name);
|
mm_reg1_t *mm_map(const mm_idx_t *mi, int l_seq, const char *seq, int *n_regs, mm_tbuf_t *b, const mm_mapopt_t *opt, const char *name);
|
||||||
|
|
||||||
|
void mm_map_frag(const mm_idx_t *mi, int n_segs, const int *qlens, const char **seqs, int *n_regs, mm_reg1_t **regs, mm_tbuf_t *b, const mm_mapopt_t *opt, const char *qname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Align a fasta/fastq file and print alignments to stdout
|
* Align a fasta/fastq file and print alignments to stdout
|
||||||
*
|
*
|
||||||
|
|||||||
+54
-18
@@ -1,4 +1,4 @@
|
|||||||
.TH minimap2 1 "9 January 2018" "minimap2-2.7 (r654)" "Bioinformatics tools"
|
.TH minimap2 1 "1 February 2018" "minimap2-2.8 (r672)" "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
|
||||||
@@ -129,7 +129,7 @@ Ignore top
|
|||||||
fraction of most frequent minimizers [0.0002]
|
fraction of most frequent minimizers [0.0002]
|
||||||
.TP
|
.TP
|
||||||
.BI -g \ INT
|
.BI -g \ INT
|
||||||
Stop chain enlongation if there are no minimizers in
|
Stop chain enlongation if there are no minimizers within
|
||||||
.IR INT -bp
|
.IR INT -bp
|
||||||
[10000].
|
[10000].
|
||||||
.TP
|
.TP
|
||||||
@@ -148,11 +148,28 @@ Discard chains with chaining score
|
|||||||
[40]. Chaining score equals the approximate number of matching bases minus a
|
[40]. Chaining score equals the approximate number of matching bases minus a
|
||||||
concave gap penalty. It is computed with dynamic programming.
|
concave gap penalty. It is computed with dynamic programming.
|
||||||
.TP
|
.TP
|
||||||
|
.B -D
|
||||||
|
If query sequence name/length are identical to the target name/length, ignore
|
||||||
|
diagonal anchors. This option also reduces DP-based extension along the
|
||||||
|
diagonal.
|
||||||
|
.TP
|
||||||
|
.B -P
|
||||||
|
Retain all chains and don't attempt to set primary chains. Options
|
||||||
|
.B -p
|
||||||
|
and
|
||||||
|
.B -N
|
||||||
|
have no effect when this option is in use.
|
||||||
|
.TP
|
||||||
|
.BR --dual = yes | no
|
||||||
|
During chaining, whether to skip pairs wherein the query name is
|
||||||
|
lexicographically greater than the target name [yes]
|
||||||
|
.TP
|
||||||
.B -X
|
.B -X
|
||||||
Perform all-vs-all mapping. In this mode, if the query sequence name is
|
Equivalent to
|
||||||
lexicographically larger than the target sequence name, the hits between them
|
.RB ' -DP
|
||||||
will be suppressed; if the query sequence name is the same as the target name,
|
.BR --dual = no
|
||||||
diagonal minimizer hits will also be suppressed.
|
.BR --no-long-join '.
|
||||||
|
Primarily used for all-vs-all read overlapping.
|
||||||
.TP
|
.TP
|
||||||
.BI -p \ FLOAT
|
.BI -p \ FLOAT
|
||||||
Minimal secondary-to-primary score ratio to output secondary mappings [0.8].
|
Minimal secondary-to-primary score ratio to output secondary mappings [0.8].
|
||||||
@@ -162,6 +179,9 @@ the chain with a lower score is secondary to the chain with a higher score.
|
|||||||
If the ratio of the scores is below
|
If the ratio of the scores is below
|
||||||
.IR FLOAT ,
|
.IR FLOAT ,
|
||||||
the secondary chain will not be outputted or extended with DP alignment later.
|
the secondary chain will not be outputted or extended with DP alignment later.
|
||||||
|
This option has no effect when
|
||||||
|
.B -X
|
||||||
|
is applied.
|
||||||
.TP
|
.TP
|
||||||
.BI -N \ INT
|
.BI -N \ INT
|
||||||
Output at most
|
Output at most
|
||||||
@@ -179,9 +199,14 @@ Increasing this option slows down spliced alignment. [200k]
|
|||||||
.TP
|
.TP
|
||||||
.BI -F \ NUM
|
.BI -F \ NUM
|
||||||
Maximum fragment length (aka insert size; effective with
|
Maximum fragment length (aka insert size; effective with
|
||||||
.BR -xsr / --frag)
|
.BR -xsr / --frag = yes )
|
||||||
[800]
|
[800]
|
||||||
.TP
|
.TP
|
||||||
|
.BI -M \ FLOAT
|
||||||
|
Mark as secondary a chain that overlaps with a better chain by
|
||||||
|
.I FLOAT
|
||||||
|
or more of the shorter chain [0.5]
|
||||||
|
.TP
|
||||||
.BI --max-chain-skip \ INT
|
.BI --max-chain-skip \ INT
|
||||||
A heuristics that stops chaining early [50]. Minimap2 uses dynamic programming
|
A heuristics that stops chaining early [50]. Minimap2 uses dynamic programming
|
||||||
for chaining. The time complexity is quadratic in the number of seeds. This
|
for chaining. The time complexity is quadratic in the number of seeds. This
|
||||||
@@ -204,8 +229,20 @@ applies a second round of chaining with a higher minimizer occurrence threshold
|
|||||||
if no good chain is found. In addition, minimap2 attempts to patch gaps between
|
if no good chain is found. In addition, minimap2 attempts to patch gaps between
|
||||||
seeds with ungapped alignment.
|
seeds with ungapped alignment.
|
||||||
.TP
|
.TP
|
||||||
.BR --frag [= no | yes ]
|
.BR --frag = no | yes
|
||||||
Whether to enable the fragment mode [no]
|
Whether to enable the fragment mode [no]
|
||||||
|
.TP
|
||||||
|
.B --for-only
|
||||||
|
Only map to the forward strand of the reference sequences. For paired-end
|
||||||
|
reads in the forward-reverse orientation, the first read is mapped to forward
|
||||||
|
strand of the reference and the second read to the reverse stand.
|
||||||
|
.TP
|
||||||
|
.B --rev-only
|
||||||
|
Only map to the reverse complement strand of the reference sequences.
|
||||||
|
.TP
|
||||||
|
.BR --heap-sort = no | yes
|
||||||
|
If yes, sort anchors with heap merge, instead of radix sort. Heap merge is
|
||||||
|
faster for short reads, but slower for long reads. [no]
|
||||||
.SS Alignment options
|
.SS Alignment options
|
||||||
.TP 10
|
.TP 10
|
||||||
.BI -A \ INT
|
.BI -A \ INT
|
||||||
@@ -255,14 +292,13 @@ no attempt to match GT-AG [n]
|
|||||||
.BI --end-bonus \ INT
|
.BI --end-bonus \ INT
|
||||||
Score bonus when alignment extends to the end of the query sequence [0].
|
Score bonus when alignment extends to the end of the query sequence [0].
|
||||||
.TP
|
.TP
|
||||||
.BR --splice-flank [= yes | no ]
|
.BR --splice-flank = yes | no
|
||||||
Assume the next base to a
|
Assume the next base to a
|
||||||
.B GT
|
.B GT
|
||||||
donor site tends to be A/G (91% in human and 92% in mouse) and the preceding
|
donor site tends to be A/G (91% in human and 92% in mouse) and the preceding
|
||||||
base to a
|
base to a
|
||||||
.B AG
|
.B AG
|
||||||
acceptor tends to be C/T [yes with
|
acceptor tends to be C/T [no].
|
||||||
.BR --splice ].
|
|
||||||
This trend is evolutionarily conservative, all the way to S. cerevisiae
|
This trend is evolutionarily conservative, all the way to S. cerevisiae
|
||||||
(PMID:18688272). Specifying this option generally leads to higher junction
|
(PMID:18688272). Specifying this option generally leads to higher junction
|
||||||
accuracy by several percents, so it is applied by default with
|
accuracy by several percents, so it is applied by default with
|
||||||
@@ -352,7 +388,7 @@ K/M/G/k/m/g suffix is accepted. A large
|
|||||||
helps load balancing in the multi-threading mode, at the cost of increased
|
helps load balancing in the multi-threading mode, at the cost of increased
|
||||||
memory.
|
memory.
|
||||||
.TP
|
.TP
|
||||||
.BR --secondary [= yes | no ]
|
.BR --secondary = yes | no
|
||||||
Whether to output secondary alignments [yes]
|
Whether to output secondary alignments [yes]
|
||||||
.TP
|
.TP
|
||||||
.B --version
|
.B --version
|
||||||
@@ -399,13 +435,13 @@ Up to 10% sequence divergence.
|
|||||||
.B ava-pb
|
.B ava-pb
|
||||||
PacBio all-vs-all overlap mapping
|
PacBio all-vs-all overlap mapping
|
||||||
.RB ( -Hk19
|
.RB ( -Hk19
|
||||||
.B -w5 -Xp0 -m100 -g10000 --max-chain-skip
|
.B -Xw5 -m100 -g10000 --max-chain-skip
|
||||||
.BR 25 ).
|
.BR 25 ).
|
||||||
.TP
|
.TP
|
||||||
.B ava-ont
|
.B ava-ont
|
||||||
Oxford Nanopore all-vs-all overlap mapping
|
Oxford Nanopore all-vs-all overlap mapping
|
||||||
.RB ( -k15
|
.RB ( -k15
|
||||||
.B -w5 -Xp0 -m100 -g10000 --max-chain-skip
|
.B -Xw5 -m100 -g10000 --max-chain-skip
|
||||||
.BR 25 ).
|
.BR 25 ).
|
||||||
Similarly, the major difference from
|
Similarly, the major difference from
|
||||||
.B ava-pb
|
.B ava-pb
|
||||||
@@ -427,8 +463,8 @@ tag ignores introns to demote hits to pseudogenes.
|
|||||||
.B sr
|
.B sr
|
||||||
Short single-end reads without splicing
|
Short single-end reads without splicing
|
||||||
.RB ( -k21
|
.RB ( -k21
|
||||||
.B -w11 --sr --frag -A2 -B8 -O12,32 -E2,1 -r50 -p.5 -N20 -f1000,5000 -n2 -m20
|
.B -w11 --sr --frag=yes -A2 -B8 -O12,32 -E2,1 -r50 -p.5 -N20 -f1000,5000 -n2 -m20
|
||||||
.B -s40 -g200 -2K50m
|
.B -s40 -g200 -2K50m --heap-sort=yes
|
||||||
.BR --secondary=no ).
|
.BR --secondary=no ).
|
||||||
.RE
|
.RE
|
||||||
.SS Miscellaneous options
|
.SS Miscellaneous options
|
||||||
@@ -522,8 +558,8 @@ where seed positions may be suboptimal. This should not be a big concern
|
|||||||
because even the optimal alignment may be wrong in such regions.
|
because even the optimal alignment may be wrong in such regions.
|
||||||
.TP
|
.TP
|
||||||
*
|
*
|
||||||
Minimap2 requires SSE2 instructions to compile. It is possible to add
|
Minimap2 requires SSE2 or NEON instructions to compile. It is possible to add
|
||||||
non-SSE2 support, but it would make minimap2 slower by several times.
|
non-SSE2/NEON support, but it would make minimap2 slower by several times.
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.PP
|
.PP
|
||||||
miniasm(1), minimap(1), bwa(1).
|
miniasm(1), minimap(1), bwa(1).
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "minimap.h"
|
#include "mmpriv.h"
|
||||||
|
|
||||||
int mm_verbose = 1;
|
int mm_verbose = 1;
|
||||||
int mm_dbg_flag = 0;
|
int mm_dbg_flag = 0;
|
||||||
|
|||||||
+4
-4
@@ -40,9 +40,9 @@ var re_cs = /([:=*+-])(\d+|[A-Za-z]+)/g;
|
|||||||
var c, min_cov_len = 10000, min_var_len = 50000, gap_thres = 50, min_mapq = 5;
|
var c, min_cov_len = 10000, min_var_len = 50000, gap_thres = 50, min_mapq = 5;
|
||||||
while ((c = getopt(arguments, "l:L:g:q:")) != null) {
|
while ((c = getopt(arguments, "l:L:g:q:")) != null) {
|
||||||
if (c == 'l') min_cov_len = parseInt(getopt.arg);
|
if (c == 'l') min_cov_len = parseInt(getopt.arg);
|
||||||
else if (c == 'L') min_var_len = parseInt(optarg.arg);
|
else if (c == 'L') min_var_len = parseInt(getopt.arg);
|
||||||
else if (c == 'g') gap_thres = parseInt(optarg.arg);
|
else if (c == 'g') gap_thres = parseInt(getopt.arg);
|
||||||
else if (c == 'q') min_mapq = parseInt(optarg.arg);
|
else if (c == 'q') min_mapq = parseInt(getopt.arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments.length == getopt.ind) {
|
if (arguments.length == getopt.ind) {
|
||||||
@@ -55,7 +55,7 @@ if (arguments.length == getopt.ind) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
var file = new File(arguments[getopt.ind]);
|
var file = arguments[getopt.ind] == '-'? new File() : new File(arguments[getopt.ind]);
|
||||||
var buf = new Bytes();
|
var buf = new Bytes();
|
||||||
var tot_len = 0, n_sub = [0, 0, 0], n_ins = [0, 0, 0, 0], n_del = [0, 0, 0, 0];
|
var tot_len = 0, n_sub = [0, 0, 0], n_ins = [0, 0, 0, 0], n_del = [0, 0, 0, 0];
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#define MM_SEED_LONG_JOIN (1ULL<<40)
|
#define MM_SEED_LONG_JOIN (1ULL<<40)
|
||||||
#define MM_SEED_IGNORE (1ULL<<41)
|
#define MM_SEED_IGNORE (1ULL<<41)
|
||||||
#define MM_SEED_TANDEM (1ULL<<42)
|
#define MM_SEED_TANDEM (1ULL<<42)
|
||||||
|
#define MM_SEED_SELF (1ULL<<43)
|
||||||
|
|
||||||
#define MM_SEED_SEG_SHIFT 48
|
#define MM_SEED_SEG_SHIFT 48
|
||||||
#define MM_SEED_SEG_MASK (0xffULL<<(MM_SEED_SEG_SHIFT))
|
#define MM_SEED_SEG_MASK (0xffULL<<(MM_SEED_SEG_SHIFT))
|
||||||
|
|||||||
@@ -0,0 +1,140 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "mmpriv.h"
|
||||||
|
|
||||||
|
void mm_mapopt_init(mm_mapopt_t *opt)
|
||||||
|
{
|
||||||
|
memset(opt, 0, sizeof(mm_mapopt_t));
|
||||||
|
opt->seed = 11;
|
||||||
|
opt->mid_occ_frac = 2e-4f;
|
||||||
|
opt->sdust_thres = 0; // no SDUST masking
|
||||||
|
|
||||||
|
opt->min_cnt = 3;
|
||||||
|
opt->min_chain_score = 40;
|
||||||
|
opt->bw = 500;
|
||||||
|
opt->max_gap = 5000;
|
||||||
|
opt->max_gap_ref = -1;
|
||||||
|
opt->max_chain_skip = 25;
|
||||||
|
|
||||||
|
opt->mask_level = 0.5f;
|
||||||
|
opt->pri_ratio = 0.8f;
|
||||||
|
opt->best_n = 5;
|
||||||
|
|
||||||
|
opt->max_join_long = 20000;
|
||||||
|
opt->max_join_short = 2000;
|
||||||
|
opt->min_join_flank_sc = 1000;
|
||||||
|
|
||||||
|
opt->a = 2, opt->b = 4, opt->q = 4, opt->e = 2, opt->q2 = 24, opt->e2 = 1;
|
||||||
|
opt->zdrop = 400;
|
||||||
|
opt->end_bonus = -1;
|
||||||
|
opt->min_dp_max = opt->min_chain_score * opt->a;
|
||||||
|
opt->min_ksw_len = 200;
|
||||||
|
opt->anchor_ext_len = 20, opt->anchor_ext_shift = 6;
|
||||||
|
opt->mini_batch_size = 500000000;
|
||||||
|
|
||||||
|
opt->pe_ori = 0; // FF
|
||||||
|
opt->pe_bonus = 33;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mm_mapopt_update(mm_mapopt_t *opt, const mm_idx_t *mi)
|
||||||
|
{
|
||||||
|
if ((opt->flag & MM_F_SPLICE_FOR) && (opt->flag & MM_F_SPLICE_REV))
|
||||||
|
opt->flag |= MM_F_SPLICE;
|
||||||
|
if (opt->mid_occ <= 0)
|
||||||
|
opt->mid_occ = mm_idx_cal_max_occ(mi, opt->mid_occ_frac);
|
||||||
|
if (mm_verbose >= 3)
|
||||||
|
fprintf(stderr, "[M::%s::%.3f*%.2f] mid_occ = %d\n", __func__, realtime() - mm_realtime0, cputime() / (realtime() - mm_realtime0), opt->mid_occ);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mm_mapopt_max_intron_len(mm_mapopt_t *opt, int max_intron_len)
|
||||||
|
{
|
||||||
|
if ((opt->flag & MM_F_SPLICE) && max_intron_len > 0)
|
||||||
|
opt->max_gap_ref = opt->bw = max_intron_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mm_set_opt(const char *preset, mm_idxopt_t *io, mm_mapopt_t *mo)
|
||||||
|
{
|
||||||
|
if (preset == 0) {
|
||||||
|
mm_idxopt_init(io);
|
||||||
|
mm_mapopt_init(mo);
|
||||||
|
} else if (strcmp(preset, "ava-ont") == 0) {
|
||||||
|
io->flag = 0, io->k = 15, io->w = 5;
|
||||||
|
mo->flag |= MM_F_ALL_CHAINS | MM_F_NO_DIAG | MM_F_NO_DUAL | MM_F_NO_LJOIN;
|
||||||
|
mo->min_chain_score = 100, mo->pri_ratio = 0.0f, mo->max_gap = 10000, mo->max_chain_skip = 25;
|
||||||
|
} else if (strcmp(preset, "ava-pb") == 0) {
|
||||||
|
io->flag |= MM_I_HPC, io->k = 19, io->w = 5;
|
||||||
|
mo->flag |= MM_F_ALL_CHAINS | MM_F_NO_DIAG | MM_F_NO_DUAL | MM_F_NO_LJOIN;
|
||||||
|
mo->min_chain_score = 100, mo->pri_ratio = 0.0f, mo->max_gap = 10000, mo->max_chain_skip = 25;
|
||||||
|
} else if (strcmp(preset, "map10k") == 0 || strcmp(preset, "map-pb") == 0) {
|
||||||
|
io->flag |= MM_I_HPC, io->k = 19;
|
||||||
|
} else if (strcmp(preset, "map-ont") == 0) {
|
||||||
|
io->flag = 0, io->k = 15;
|
||||||
|
} else if (strcmp(preset, "asm5") == 0) {
|
||||||
|
io->flag = 0, io->k = 19, io->w = 19;
|
||||||
|
mo->a = 1, mo->b = 19, mo->q = 39, mo->q2 = 81, mo->e = 3, mo->e2 = 1, mo->zdrop = 200;
|
||||||
|
mo->min_dp_max = 200;
|
||||||
|
mo->best_n = 50;
|
||||||
|
} else if (strcmp(preset, "asm10") == 0) {
|
||||||
|
io->flag = 0, io->k = 19, io->w = 19;
|
||||||
|
mo->a = 1, mo->b = 9, mo->q = 16, mo->q2 = 41, mo->e = 2, mo->e2 = 1, mo->zdrop = 200;
|
||||||
|
mo->min_dp_max = 200;
|
||||||
|
mo->best_n = 50;
|
||||||
|
} else if (strcmp(preset, "short") == 0 || strcmp(preset, "sr") == 0) {
|
||||||
|
io->flag = 0, io->k = 21, io->w = 11;
|
||||||
|
mo->flag |= MM_F_SR | MM_F_FRAG_MODE | MM_F_NO_PRINT_2ND | MM_F_2_IO_THREADS | MM_F_HEAP_SORT;
|
||||||
|
mo->pe_ori = 0<<1|1; // FR
|
||||||
|
mo->a = 2, mo->b = 8, mo->q = 12, mo->e = 2, mo->q2 = 24, mo->e2 = 1;
|
||||||
|
mo->zdrop = 100;
|
||||||
|
mo->end_bonus = 10;
|
||||||
|
mo->max_frag_len = 800;
|
||||||
|
mo->max_gap = 100;
|
||||||
|
mo->bw = 100;
|
||||||
|
mo->pri_ratio = 0.5f;
|
||||||
|
mo->min_cnt = 2;
|
||||||
|
mo->min_chain_score = 25;
|
||||||
|
mo->min_dp_max = 40;
|
||||||
|
mo->best_n = 20;
|
||||||
|
mo->mid_occ = 1000;
|
||||||
|
mo->max_occ = 5000;
|
||||||
|
mo->mini_batch_size = 50000000;
|
||||||
|
} else if (strcmp(preset, "splice") == 0 || strcmp(preset, "cdna") == 0) {
|
||||||
|
io->flag = 0, io->k = 15, io->w = 5;
|
||||||
|
mo->flag |= MM_F_SPLICE | MM_F_SPLICE_FOR | MM_F_SPLICE_REV | MM_F_SPLICE_FLANK;
|
||||||
|
mo->max_gap = 2000, mo->max_gap_ref = mo->bw = 200000;
|
||||||
|
mo->a = 1, mo->b = 2, mo->q = 2, mo->e = 1, mo->q2 = 32, mo->e2 = 0;
|
||||||
|
mo->noncan = 9;
|
||||||
|
mo->zdrop = 200;
|
||||||
|
} else return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mm_check_opt(const mm_idxopt_t *io, const mm_mapopt_t *mo)
|
||||||
|
{
|
||||||
|
if (mo->best_n < 0) {
|
||||||
|
if (mm_verbose >= 1)
|
||||||
|
fprintf(stderr, "[ERROR]\033[1;31m -N must be no less than 0\033[0m\n");
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
if (mo->best_n == 0 && mm_verbose >= 2)
|
||||||
|
fprintf(stderr, "[WARNING]\033[1;31m '-N 0' reduces mapping accuracy. Please use '--secondary=no' instead.\033[0m\n");
|
||||||
|
if (mo->pri_ratio < 0.0f || mo->pri_ratio > 1.0f) {
|
||||||
|
if (mm_verbose >= 1)
|
||||||
|
fprintf(stderr, "[ERROR]\033[1;31m -p must be within 0 and 1 (including 0 and 1)\033[0m\n");
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
if ((mo->flag & MM_F_FOR_ONLY) && (mo->flag & MM_F_REV_ONLY)) {
|
||||||
|
if (mm_verbose >= 1)
|
||||||
|
fprintf(stderr, "[ERROR]\033[1;31m --for-only and --rev-only can't be applied at the same time\033[0m\n");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
if ((mo->q != mo->q2 || mo->e != mo->e2) && !(mo->e > mo->e2 && mo->q + mo->e < mo->q2 + mo->e2)) {
|
||||||
|
if (mm_verbose >= 1)
|
||||||
|
fprintf(stderr, "[ERROR]\033[1;31m dual gap penalties violating E1>E2 and O1+E1<O2+E2\033[0m\n");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if ((mo->q + mo->e) + (mo->q2 + mo->e2) > 127) {
|
||||||
|
if (mm_verbose >= 1)
|
||||||
|
fprintf(stderr, "[ERROR]\033[1;31m scoring system violating ({-O}+{-E})+({-O2}+{-E2}) <= 127\033[0m\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+8
-2
@@ -81,10 +81,13 @@ This constructor accepts the following arguments:
|
|||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
mappy.Aligner.map(seq)
|
mappy.Aligner.map(seq, seq2=None)
|
||||||
|
|
||||||
This method aligns :code:`seq` against the index. It is a generator, *yielding*
|
This method aligns :code:`seq` against the index. It is a generator, *yielding*
|
||||||
a series of :code:`mappy.Alignment` objects.
|
a series of :code:`mappy.Alignment` objects. If :code:`seq2` is present, mappy
|
||||||
|
performs paired-end alignment, assuming the two ends are in the FR orientation.
|
||||||
|
Alignments of the two ends can be distinguished by the :code:`read_num` field
|
||||||
|
(see below).
|
||||||
|
|
||||||
Class mappy.Alignment
|
Class mappy.Alignment
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
@@ -118,6 +121,9 @@ properties:
|
|||||||
* **is_primary**: if the alignment is primary (typically the best and the first
|
* **is_primary**: if the alignment is primary (typically the best and the first
|
||||||
to generate)
|
to generate)
|
||||||
|
|
||||||
|
* **read_num**: read number that the alignment corresponds to; 1 for the first
|
||||||
|
read and 2 for the second read
|
||||||
|
|
||||||
* **cigar_str**: CIGAR string
|
* **cigar_str**: CIGAR string
|
||||||
|
|
||||||
* **cigar**: CIGAR returned as an array of shape :code:`(n_cigar,2)`. The two
|
* **cigar**: CIGAR returned as an array of shape :code:`(n_cigar,2)`. The two
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ typedef struct {
|
|||||||
int32_t blen, mlen, NM, ctg_len;
|
int32_t blen, mlen, NM, ctg_len;
|
||||||
uint8_t mapq, is_primary;
|
uint8_t mapq, is_primary;
|
||||||
int8_t strand, trans_strand;
|
int8_t strand, trans_strand;
|
||||||
|
int32_t seg_id;
|
||||||
int32_t n_cigar32;
|
int32_t n_cigar32;
|
||||||
uint32_t *cigar32;
|
uint32_t *cigar32;
|
||||||
} mm_hitpy_t;
|
} mm_hitpy_t;
|
||||||
@@ -32,6 +33,7 @@ static inline void mm_reg2hitpy(const mm_idx_t *mi, mm_reg1_t *r, mm_hitpy_t *h)
|
|||||||
h->NM = r->blen - r->mlen + r->p->n_ambi;
|
h->NM = r->blen - r->mlen + r->p->n_ambi;
|
||||||
h->trans_strand = r->p->trans_strand == 1? 1 : r->p->trans_strand == 2? -1 : 0;
|
h->trans_strand = r->p->trans_strand == 1? 1 : r->p->trans_strand == 2? -1 : 0;
|
||||||
h->is_primary = (r->id == r->parent);
|
h->is_primary = (r->id == r->parent);
|
||||||
|
h->seg_id = r->seg_id;
|
||||||
h->n_cigar32 = r->p->n_cigar;
|
h->n_cigar32 = r->p->n_cigar;
|
||||||
h->cigar32 = r->p->cigar;
|
h->cigar32 = r->p->cigar;
|
||||||
}
|
}
|
||||||
@@ -68,4 +70,35 @@ static inline void mm_reset_timer(void)
|
|||||||
mm_realtime0 = realtime();
|
mm_realtime0 = realtime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern unsigned char seq_comp_table[256];
|
||||||
|
static inline mm_reg1_t *mm_map_aux(const mm_idx_t *mi, const char *seq1, const char *seq2, int *n_regs, mm_tbuf_t *b, const mm_mapopt_t *opt)
|
||||||
|
{
|
||||||
|
if (seq2 == 0) {
|
||||||
|
return mm_map(mi, strlen(seq1), seq1, n_regs, b, opt, NULL);
|
||||||
|
} else {
|
||||||
|
int _n_regs[2];
|
||||||
|
mm_reg1_t *regs[2];
|
||||||
|
char *seq[2];
|
||||||
|
int i, len[2];
|
||||||
|
len[0] = strlen(seq1);
|
||||||
|
len[1] = strlen(seq2);
|
||||||
|
seq[0] = (char*)seq1;
|
||||||
|
seq[1] = strdup(seq2);
|
||||||
|
for (i = 0; i < len[1]>>1; ++i) {
|
||||||
|
int t = seq[1][len[1] - i - 1];
|
||||||
|
seq[1][len[1] - i - 1] = seq_comp_table[(uint8_t)seq[1][i]];
|
||||||
|
seq[1][i] = seq_comp_table[t];
|
||||||
|
}
|
||||||
|
if (len[1]&1) seq[1][len[1]>>1] = seq_comp_table[(uint8_t)seq[1][len[1]>>1]];
|
||||||
|
mm_map_frag(mi, 2, len, (const char**)seq, _n_regs, regs, b, opt, NULL);
|
||||||
|
for (i = 0; i < _n_regs[1]; ++i)
|
||||||
|
regs[1][i].rev = !regs[1][i].rev;
|
||||||
|
*n_regs = _n_regs[0] + _n_regs[1];
|
||||||
|
regs[0] = (mm_reg1_t*)realloc(regs[0], sizeof(mm_reg1_t) * (*n_regs));
|
||||||
|
memcpy(®s[0][_n_regs[0]], regs[1], _n_regs[1] * sizeof(mm_reg1_t));
|
||||||
|
free(regs[1]);
|
||||||
|
return regs[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+2
-1
@@ -79,7 +79,6 @@ cdef extern from "minimap.h":
|
|||||||
|
|
||||||
mm_tbuf_t *mm_tbuf_init()
|
mm_tbuf_t *mm_tbuf_init()
|
||||||
void mm_tbuf_destroy(mm_tbuf_t *b)
|
void mm_tbuf_destroy(mm_tbuf_t *b)
|
||||||
mm_reg1_t *mm_map(const mm_idx_t *mi, int l_seq, const char *seq, int *n_regs, mm_tbuf_t *b, const mm_mapopt_t *opt, const char *name)
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Helper header (because it is hard to expose mm_reg1_t with Cython)
|
# Helper header (because it is hard to expose mm_reg1_t with Cython)
|
||||||
@@ -92,11 +91,13 @@ cdef extern from "cmappy.h":
|
|||||||
int32_t blen, mlen, NM, ctg_len
|
int32_t blen, mlen, NM, ctg_len
|
||||||
uint8_t mapq, is_primary
|
uint8_t mapq, is_primary
|
||||||
int8_t strand, trans_strand
|
int8_t strand, trans_strand
|
||||||
|
int32_t seg_id
|
||||||
int32_t n_cigar32
|
int32_t n_cigar32
|
||||||
uint32_t *cigar32
|
uint32_t *cigar32
|
||||||
|
|
||||||
void mm_reg2hitpy(const mm_idx_t *mi, mm_reg1_t *r, mm_hitpy_t *h)
|
void mm_reg2hitpy(const mm_idx_t *mi, mm_reg1_t *r, mm_hitpy_t *h)
|
||||||
void mm_free_reg1(mm_reg1_t *r)
|
void mm_free_reg1(mm_reg1_t *r)
|
||||||
|
mm_reg1_t *mm_map_aux(const mm_idx_t *mi, const char *seq1, const char *seq2, int *n_regs, mm_tbuf_t *b, const mm_mapopt_t *opt)
|
||||||
|
|
||||||
ctypedef struct kstring_t:
|
ctypedef struct kstring_t:
|
||||||
unsigned l, m
|
unsigned l, m
|
||||||
|
|||||||
+10
-4
@@ -10,9 +10,10 @@ cdef class Alignment:
|
|||||||
cdef int _NM, _mlen, _blen
|
cdef int _NM, _mlen, _blen
|
||||||
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 _ctg, _cigar # these are python objects
|
cdef _ctg, _cigar # these are python objects
|
||||||
|
|
||||||
def __cinit__(self, ctg, cl, cs, ce, strand, qs, qe, mapq, cigar, is_primary, mlen, blen, NM, trans_strand):
|
def __cinit__(self, ctg, cl, cs, ce, strand, qs, qe, mapq, cigar, is_primary, mlen, blen, NM, trans_strand, seg_id):
|
||||||
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
|
||||||
@@ -21,6 +22,7 @@ cdef class Alignment:
|
|||||||
self._cigar = cigar
|
self._cigar = cigar
|
||||||
self._is_primary = is_primary
|
self._is_primary = is_primary
|
||||||
self._trans_strand = trans_strand
|
self._trans_strand = trans_strand
|
||||||
|
self._seg_id = seg_id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ctg(self): return self._ctg
|
def ctg(self): return self._ctg
|
||||||
@@ -64,6 +66,9 @@ cdef class Alignment:
|
|||||||
@property
|
@property
|
||||||
def cigar(self): return self._cigar
|
def cigar(self): return self._cigar
|
||||||
|
|
||||||
|
@property
|
||||||
|
def read_num(self): return self._seg_id + 1
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cigar_str(self):
|
def cigar_str(self):
|
||||||
return "".join(map(lambda x: str(x[0]) + 'MIDNSH'[x[1]], self._cigar))
|
return "".join(map(lambda x: str(x[0]) + 'MIDNSH'[x[1]], self._cigar))
|
||||||
@@ -125,7 +130,7 @@ cdef class Aligner:
|
|||||||
def __bool__(self):
|
def __bool__(self):
|
||||||
return (self._idx != NULL)
|
return (self._idx != NULL)
|
||||||
|
|
||||||
def map(self, seq, buf=None):
|
def map(self, seq, seq2=None, buf=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
|
||||||
@@ -134,7 +139,8 @@ 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
|
||||||
regs = cmappy.mm_map(self._idx, len(seq), str.encode(seq), &n_regs, b._b, &self.map_opt, NULL)
|
if seq2 is None: regs = cmappy.mm_map_aux(self._idx, str.encode(seq), NULL, &n_regs, b._b, &self.map_opt)
|
||||||
|
else: regs = cmappy.mm_map_aux(self._idx, str.encode(seq), str.encode(seq2), &n_regs, b._b, &self.map_opt)
|
||||||
|
|
||||||
for i in range(n_regs):
|
for i in range(n_regs):
|
||||||
cmappy.mm_reg2hitpy(self._idx, ®s[i], &h)
|
cmappy.mm_reg2hitpy(self._idx, ®s[i], &h)
|
||||||
@@ -142,7 +148,7 @@ cdef class Aligner:
|
|||||||
for k in range(h.n_cigar32):
|
for k in range(h.n_cigar32):
|
||||||
c = h.cigar32[k]
|
c = h.cigar32[k]
|
||||||
cigar.append([c>>4, c&0xf])
|
cigar.append([c>>4, c&0xf])
|
||||||
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)
|
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)
|
||||||
cmappy.mm_free_reg1(®s[i])
|
cmappy.mm_free_reg1(®s[i])
|
||||||
free(regs)
|
free(regs)
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ def readme():
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name = 'mappy',
|
name = 'mappy',
|
||||||
version = '2.7',
|
version = '2.8',
|
||||||
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(),
|
||||||
@@ -33,13 +33,13 @@ setup(
|
|||||||
keywords = 'sequence-alignment',
|
keywords = 'sequence-alignment',
|
||||||
scripts = ['python/minimap2.py'],
|
scripts = ['python/minimap2.py'],
|
||||||
ext_modules = [Extension('mappy',
|
ext_modules = [Extension('mappy',
|
||||||
sources = [module_src, 'align.c', 'bseq.c', 'chain.c', 'format.c', 'hit.c', 'index.c', 'pe.c',
|
sources = [module_src, 'align.c', 'bseq.c', 'chain.c', 'format.c', 'hit.c', 'index.c', 'pe.c', 'options.c',
|
||||||
'ksw2_extd2_sse.c', 'ksw2_exts2_sse.c', 'ksw2_extz2_sse.c', 'ksw2_ll_sse.c',
|
'ksw2_extd2_sse.c', 'ksw2_exts2_sse.c', 'ksw2_extz2_sse.c', 'ksw2_ll_sse.c',
|
||||||
'kalloc.c', 'kthread.c', 'map.c', 'misc.c', 'sdust.c', 'sketch.c', 'esterr.c'],
|
'kalloc.c', 'kthread.c', 'map.c', 'misc.c', 'sdust.c', 'sketch.c', 'esterr.c'],
|
||||||
depends = ['minimap.h', 'bseq.h', 'kalloc.h', 'kdq.h', 'khash.h', 'kseq.h', 'ksort.h',
|
depends = ['minimap.h', 'bseq.h', 'kalloc.h', 'kdq.h', 'khash.h', 'kseq.h', 'ksort.h',
|
||||||
'ksw2.h', 'kthread.h', 'kvec.h', 'mmpriv.h', 'sdust.h',
|
'ksw2.h', 'kthread.h', 'kvec.h', 'mmpriv.h', 'sdust.h',
|
||||||
'python/cmappy.h', 'python/cmappy.pxd'],
|
'python/cmappy.h', 'python/cmappy.pxd'],
|
||||||
extra_compile_args = ['-msse4'], # WARNING: ancient x86_64 CPUs don't have SSE4
|
extra_compile_args = ['-DHAVE_KALLOC', '-msse4'], # WARNING: ancient x86_64 CPUs don't have SSE4
|
||||||
include_dirs = ['.'],
|
include_dirs = ['.'],
|
||||||
libraries = ['z', 'm', 'pthread'])],
|
libraries = ['z', 'm', 'pthread'])],
|
||||||
classifiers = [
|
classifiers = [
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#define __STDC_LIMIT_MACROS
|
||||||
#include "kvec.h"
|
#include "kvec.h"
|
||||||
#include "minimap.h"
|
#include "mmpriv.h"
|
||||||
|
|
||||||
unsigned char seq_nt4_table[256] = {
|
unsigned char seq_nt4_table[256] = {
|
||||||
0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
|||||||
Reference in New Issue
Block a user