Compare commits

...
18 Commits
Author SHA1 Message Date
Heng Li 53ce317e59 Release minimap2-2.8 (r672) 2018-02-01 12:50:20 -05:00
Heng Li da6947cfa3 r671: cleanup command line options 2018-01-31 13:59:52 -05:00
Heng Li 46d6349af4 r670: added PE support to mappy
and minor code cleanup
2018-01-31 11:33:08 -05:00
Heng Li 12a5a5fa3c r669: improved self chain extension (#10)
This has not fully resolved #10, only alleviated the issue.
2018-01-30 20:05:02 -05:00
Heng Li ad18fa490d fixed typos 2018-01-30 10:11:50 -05:00
Heng Li 43bfa6199d r667: warn if one query file has fewer records #92 2018-01-28 17:36:21 -05:00
Heng Li 72b9b0e3b6 r666: report if >=3 query files in SR mode #92 2018-01-28 17:15:57 -05:00
Heng Li 6205fa6f21 document --heap-sort 2018-01-26 15:15:40 -05:00
Heng Li d676a5314b r664: use --heat-sort for sr by default 2018-01-26 12:25:42 -05:00
Heng Li dfc78b39d3 refactor the old sorting 2018-01-26 09:37:48 -05:00
Heng Li 7b57c9a619 heap sort working on MT 2018-01-26 09:21:45 -05:00
Heng Li 123bc1d91d put option operations in another file 2018-01-26 08:38:37 -05:00
Heng Li dd18307e66 code backup 2018-01-25 21:52:49 -05:00
Heng Li 543fa12e68 r659: for C++ compatibility 2018-01-19 10:40:18 -05:00
Heng Li af1a871270 r658: gives a warning if -N0 is used 2018-01-19 08:33:20 -05:00
Heng Li 2b71181a37 r657: check -p (#96)
Well, in principle, every option should be checked. Will do when someone raise
issues...
2018-01-19 01:03:38 -05:00
Heng Li 0454e6be91 explain -M in the manpage 2018-01-18 11:47:11 -05:00
Heng Li 33f8157961 r655: options to map to one strand of the ref #91 2018-01-16 10:34:30 -05:00
23 changed files with 567 additions and 280 deletions
+7 -4
View File
@@ -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
+29
View File
@@ -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)
--------------------------------- ---------------------------------
+2 -6
View File
@@ -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
+9 -1
View File
@@ -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, &regs[i-1], &regs[i], &r2, &ez)) { if (mm_align1_inv(km, opt, mi, qlen, qseq0, &regs[i-1], &regs[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
+9 -3
View File
@@ -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;
+3 -1
View File
@@ -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;
} }
+1
View File
@@ -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"
+18 -1
View File
@@ -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; \
+1
View File
@@ -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)
+42 -19
View File
@@ -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]);
+167 -196
View File
@@ -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, &regs, b, opt, qname); mm_map_frag(mi, 1, &qlen, &seq, n_regs, &regs, 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)))) {
+21 -15
View File
@@ -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
View File
@@ -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 -1
View File
@@ -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
View File
@@ -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];
+1
View File
@@ -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))
+140
View File
@@ -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
View File
@@ -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
+33
View File
@@ -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(&regs[0][_n_regs[0]], regs[1], _n_regs[1] * sizeof(mm_reg1_t));
free(regs[1]);
return regs[0];
}
}
#endif #endif
+2 -1
View File
@@ -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
View File
@@ -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, &regs[i], &h) cmappy.mm_reg2hitpy(self._idx, &regs[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(&regs[i]) cmappy.mm_free_reg1(&regs[i])
free(regs) free(regs)
+3 -3
View File
@@ -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 -1
View File
@@ -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,