Compare commits

...
24 Commits
Author SHA1 Message Date
Heng Li 59f23f7579 Release minimap2-2.14 (r883) 2018-11-06 00:03:16 -05:00
Heng Li 5e55e397e9 r882: guard against -E0 (#263) 2018-11-05 23:36:12 -05:00
Heng Li 88c421e8de r881: a recent change reduces sr accuracy 2018-11-05 22:03:59 -05:00
Heng Li 3db5bfe6e5 r880: fixed false wrong FASTA/Q alert 2018-11-05 20:52:07 -05:00
Heng Li 83dfdd5f50 draft release note 2018-11-05 20:07:57 -05:00
Heng Li 8a2b1cd4c9 updated mappy for extra option max_sw_mat 2018-11-05 19:28:44 -05:00
Heng Li 1ede8ca170 r877: renamed cap-sw-mat to cap-sw-mem 2018-11-05 11:46:38 -05:00
Heng Li 13981404e2 r876: skip DP if taking too much RAM (#259) 2018-11-05 11:43:10 -05:00
Heng Li fd64dd26f6 r875: warn given incorrect FASTA/Q
resolves #252
resolves #255
2018-11-05 10:02:44 -05:00
Heng Li 24df95e4b8 r874: don't call x86_simd() so often
This takes a few percent of time in profiler.
2018-11-05 09:20:35 -05:00
Heng Li a8ee48c2ce r873: comforming to C99/C11; resolves #261 2018-11-05 08:25:07 -05:00
Heng Li 09e089c3dc r872: choose the longest isoform 2018-11-04 23:48:50 -05:00
Heng Li e46cbb7d84 r871: print erroneous genes 2018-11-04 20:37:06 -05:00
Heng Li 57ec73ec6c r870: separate <50% and <10% 2018-11-04 19:31:25 -05:00
Heng Li 9e27575387 r869: classify incomplete genes 2018-11-04 19:21:55 -05:00
Heng Li b4ad8d8bf0 added asmgene
improvements coming; not made public yet
2018-11-04 17:24:05 -05:00
Heng Li e315b9fada hidden options to control bp calculation 2018-11-04 16:36:04 -05:00
Heng Li 42baf287a4 r866: fixed a typo; resolves #262 2018-10-30 09:11:55 -04:00
Heng Li 2ceba22a7a fixed a typo in manpage 2018-10-28 11:51:02 -04:00
Heng Li 9ed56b4a25 r860: MD/cs not working with --eqx 2018-10-26 23:23:53 -04:00
Heng Li ecb6c5c36c Document --no-pairing (#256) 2018-10-23 10:00:21 -04:00
Heng Li 377c7099a8 r858: fixed a bug; resolves #254 2018-10-22 22:47:11 -04:00
Heng Li 51e2abfa60 clarify that minimap2 may miss small exons 2018-10-22 11:16:16 -04:00
Heng Li 7b0a49732e r856: wrongly reported for an unrecognized option
Resolved #250
2018-10-19 20:07:14 -04:00
17 changed files with 258 additions and 51 deletions
+26
View File
@@ -1,3 +1,29 @@
Release 2.14-r883 (5 November 2018)
-----------------------------------
Notable changes:
* Fixed two minor bugs caused by typos (#254 and #266).
* Fixed a bug that made minimap2 abort when --eqx was used together with --MD
or --cs (#257).
* Added --cap-sw-mem to cap the size of DP matrices (#259). Base alignment may
take a lot of memory in the splicing mode. This may lead to issues when we
run minimap2 on a cluster with a hard memory limit. The new option avoids
unlimited memory usage at the cost of missing a few long introns.
* Conforming to C99 and C11 when possible (#261).
* Warn about malformatted FASTA or FASTQ (#252 and #255).
This release occasionally produces base alignments different from v2.13. The
overall alignment accuracy remain similar.
(2.14: 5 November 2018, r883)
Release 2.13-r850 (11 October 2018)
-----------------------------------
+4 -2
View File
@@ -71,8 +71,8 @@ Detailed evaluations are available from the [minimap2 paper][doi] or the
Minimap2 is optimized for x86-64 CPUs. You can acquire precompiled binaries from
the [release page][release] with:
```sh
curl -L https://github.com/lh3/minimap2/releases/download/v2.13/minimap2-2.13_x64-linux.tar.bz2 | tar -jxvf -
./minimap2-2.13_x64-linux/minimap2
curl -L https://github.com/lh3/minimap2/releases/download/v2.14/minimap2-2.14_x64-linux.tar.bz2 | tar -jxvf -
./minimap2-2.14_x64-linux/minimap2
```
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
@@ -355,6 +355,8 @@ mappy` or [from BioConda][mappyconda] via `conda install -c bioconda mappy`.
billion bases or longer (2,147,483,647 to be exact). The total length of all
sequences can well exceed this threshold.
* Minimap2 often misses small exons.
[paf]: https://github.com/lh3/miniasm/blob/master/PAF.md
+5 -4
View File
@@ -300,7 +300,10 @@ static void mm_align_pair(void *km, const mm_mapopt_t *opt, int qlen, const uint
for (i = 0; i < qlen; ++i) fputc("ACGTN"[qseq[i]], stderr);
fputc('\n', stderr);
}
if (opt->flag & MM_F_SPLICE)
if (opt->max_sw_mat > 0 && (int64_t)tlen * qlen > opt->max_sw_mat) {
ksw_reset_extz(ez);
ez->zdropped = 1;
} else if (opt->flag & MM_F_SPLICE)
ksw_exts2_sse(km, qlen, qseq, tlen, tseq, 5, mat, opt->q, opt->e, opt->q2, opt->noncan, zdrop, flag, ez);
else if (opt->q == opt->q2 && opt->e == opt->e2)
ksw_extz2_sse(km, qlen, qseq, tlen, tseq, 5, mat, opt->q, opt->e, w, zdrop, end_bonus, flag, ez);
@@ -414,7 +417,7 @@ static void mm_filter_bad_seeds_alt(void *km, int as1, int cnt1, mm128_t *a, int
gap2 = ((int32_t)a[as1 + j].y - (int32_t)a[as1 + j - 1].y) - (int32_t)(a[as1 + j].x - a[as1 + j - 1].x);
q_span_pre = a[as1 + j - 1].y >> 32 & 0xff;
rs2 = (int32_t)a[as1 + j - 1].x + q_span_pre;
qs2 = (int32_t)a[as1 + j - 1].x + q_span_pre;
qs2 = (int32_t)a[as1 + j - 1].y + q_span_pre;
m = rs2 - re1 < qs2 - qe1? rs2 - re1 : qs2 - qe1;
gap2 = gap2 > 0? gap2 : -gap2;
if (m > gap1 + gap2) break;
@@ -591,11 +594,9 @@ static void mm_align1(void *km, const mm_mapopt_t *opt, const mm_idx_t *mi, int
qs0 = 0, qe0 = qlen;
l = qs;
l += l * opt->a + opt->end_bonus > opt->q? (l * opt->a + opt->end_bonus - opt->q) / opt->e : 0;
l = l < opt->bw? l : opt->bw;
rs0 = rs - l > 0? rs - l : 0;
l = qlen - qe;
l += l * opt->a + opt->end_bonus > opt->q? (l * opt->a + opt->end_bonus - opt->q) / opt->e : 0;
l = l < opt->bw? l : opt->bw;
re0 = re + l < (int32_t)mi->seq[rid].len? re + l : mi->seq[rid].len;
} else {
// compute rs0 and qs0
+7 -2
View File
@@ -39,7 +39,7 @@ mm_bseq_file_t *mm_bseq_open(const char *fn)
{
mm_bseq_file_t *fp;
gzFile f;
f = fn && strcmp(fn, "-")? gzopen(fn, "r") : gzdopen(fileno(stdin), "r");
f = fn && strcmp(fn, "-")? gzopen(fn, "r") : gzdopen(0, "r");
if (f == 0) return 0;
fp = (mm_bseq_file_t*)calloc(1, sizeof(mm_bseq_file_t));
fp->fp = f;
@@ -65,6 +65,8 @@ static inline char *kstrdup(const kstring_t *s)
static inline void kseq2bseq(kseq_t *ks, mm_bseq1_t *s, int with_qual, int with_comment)
{
int i;
if (ks->name.l == 0)
fprintf(stderr, "[WARNING]\033[1;31m empty sequence name in the input.\033[0m\n");
s->name = kstrdup(&ks->name);
s->seq = kstrdup(&ks->seq);
for (i = 0; i < (int)ks->seq.l; ++i) // convert U to T
@@ -78,6 +80,7 @@ static inline void kseq2bseq(kseq_t *ks, mm_bseq1_t *s, int with_qual, int with_
mm_bseq1_t *mm_bseq_read3(mm_bseq_file_t *fp, int chunk_size, int with_qual, int with_comment, int frag_mode, int *n_)
{
int64_t size = 0;
int ret;
kvec_t(mm_bseq1_t) a = {0,0,0};
kseq_t *ks = fp->ks;
*n_ = 0;
@@ -87,7 +90,7 @@ mm_bseq1_t *mm_bseq_read3(mm_bseq_file_t *fp, int chunk_size, int with_qual, int
size = fp->s.l_seq;
memset(&fp->s, 0, sizeof(mm_bseq1_t));
}
while (kseq_read(ks) >= 0) {
while ((ret = kseq_read(ks)) >= 0) {
mm_bseq1_t *s;
assert(ks->seq.l <= INT32_MAX);
if (a.m == 0) kv_resize(mm_bseq1_t, 0, a, 256);
@@ -107,6 +110,8 @@ mm_bseq1_t *mm_bseq_read3(mm_bseq_file_t *fp, int chunk_size, int with_qual, int
break;
}
}
if (ret < -1)
fprintf(stderr, "[WARNING]\033[1;31m wrong FASTA/FASTQ record. Continue anyway.\033[0m\n");
*n_ = a.n;
return a.a;
}
+2 -2
View File
@@ -31,8 +31,8 @@ To acquire the data used in this cookbook and to install minimap2 and paftools,
please follow the command lines below:
```sh
# install minimap2 executables
curl -L https://github.com/lh3/minimap2/releases/download/v2.13/minimap2-2.13_x64-linux.tar.bz2 | tar jxf -
cp minimap2-2.13_x64-linux/{minimap2,k8,paftools.js} . # copy executables
curl -L https://github.com/lh3/minimap2/releases/download/v2.14/minimap2-2.14_x64-linux.tar.bz2 | tar jxf -
cp minimap2-2.14_x64-linux/{minimap2,k8,paftools.js} . # copy executables
export PATH="$PATH:"`pwd` # put the current directory on PATH
# download example datasets
curl -L https://github.com/lh3/minimap2/releases/download/v2.10/cookbook-data.tgz | tar zxf -
+6 -5
View File
@@ -92,7 +92,8 @@ static void sam_write_rg_line(kstring_t *str, const char *s)
if (mm_verbose >= 1) fprintf(stderr, "[ERROR] the read group line contained literal <tab> characters -- replace with escaped tabs: \\t\n");
goto err_set_rg;
}
rg_line = strdup(s);
rg_line = (char*)malloc(strlen(s) + 1);
strcpy(rg_line, s);
mm_escape(rg_line);
if ((p = strstr(rg_line, "\tID:")) == 0) {
if (mm_verbose >= 1) fprintf(stderr, "[ERROR] no ID within the read group line\n");
@@ -139,8 +140,8 @@ static void write_cs_core(kstring_t *s, const uint8_t *tseq, const uint8_t *qseq
if (write_tag) mm_sprintf_lite(s, "\tcs:Z:");
for (i = q_off = t_off = 0; i < (int)r->p->n_cigar; ++i) {
int j, op = r->p->cigar[i]&0xf, len = r->p->cigar[i]>>4;
assert(op >= 0 && op <= 3);
if (op == 0) { // match
assert((op >= 0 && op <= 3) || op == 7 || op == 8);
if (op == 0 || op == 7 || op == 8) { // match
int l_tmp = 0;
for (j = 0; j < len; ++j) {
if (qseq[q_off + j] != tseq[t_off + j]) {
@@ -187,8 +188,8 @@ static void write_MD_core(kstring_t *s, const uint8_t *tseq, const uint8_t *qseq
if (write_tag) mm_sprintf_lite(s, "\tMD:Z:");
for (i = q_off = t_off = 0; i < (int)r->p->n_cigar; ++i) {
int j, op = r->p->cigar[i]&0xf, len = r->p->cigar[i]>>4;
assert(op >= 0 && op <= 3);
if (op == 0) { // match
assert((op >= 0 && op <= 3) || op == 7 || op == 8);
if (op == 0 || op == 7 || op == 8) { // match
for (j = 0; j < len; ++j) {
if (qseq[q_off + j] != tseq[t_off + j]) {
mm_sprintf_lite(s, "%d%c", l_MD, "ACGTN"[tseq[t_off + j]]);
+14 -15
View File
@@ -17,18 +17,20 @@
void __cpuidex(int cpuid[4], int func_id, int subfunc_id)
{
#if defined(__x86_64__)
asm volatile ("cpuid"
__asm__ volatile ("cpuid"
: "=a" (cpuid[0]), "=b" (cpuid[1]), "=c" (cpuid[2]), "=d" (cpuid[3])
: "0" (func_id), "2" (subfunc_id));
#else // on 32bit, ebx can NOT be used as PIC code
asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
__asm__ volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
: "=a" (cpuid[0]), "=r" (cpuid[1]), "=c" (cpuid[2]), "=d" (cpuid[3])
: "0" (func_id), "2" (subfunc_id));
#endif
}
#endif
int x86_simd(void)
static int ksw_simd = -1;
static int x86_simd(void)
{
int flag = 0, cpuid[4], max_id;
__cpuidex(cpuid, 0, 0);
@@ -54,11 +56,10 @@ void ksw_extz2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uin
{
extern void ksw_extz2_sse2(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t q, int8_t e, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez);
extern void ksw_extz2_sse41(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t q, int8_t e, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez);
unsigned simd;
simd = x86_simd();
if (simd & SIMD_SSE4_1)
if (ksw_simd < 0) ksw_simd = x86_simd();
if (ksw_simd & SIMD_SSE4_1)
ksw_extz2_sse41(km, qlen, query, tlen, target, m, mat, q, e, w, zdrop, end_bonus, flag, ez);
else if (simd & SIMD_SSE2)
else if (ksw_simd & SIMD_SSE2)
ksw_extz2_sse2(km, qlen, query, tlen, target, m, mat, q, e, w, zdrop, end_bonus, flag, ez);
else abort();
}
@@ -70,11 +71,10 @@ void ksw_extd2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uin
int8_t q, int8_t e, int8_t q2, int8_t e2, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez);
extern void ksw_extd2_sse41(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat,
int8_t q, int8_t e, int8_t q2, int8_t e2, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez);
unsigned simd;
simd = x86_simd();
if (simd & SIMD_SSE4_1)
if (ksw_simd < 0) ksw_simd = x86_simd();
if (ksw_simd & SIMD_SSE4_1)
ksw_extd2_sse41(km, qlen, query, tlen, target, m, mat, q, e, q2, e2, w, zdrop, end_bonus, flag, ez);
else if (simd & SIMD_SSE2)
else if (ksw_simd & SIMD_SSE2)
ksw_extd2_sse2(km, qlen, query, tlen, target, m, mat, q, e, q2, e2, w, zdrop, end_bonus, flag, ez);
else abort();
}
@@ -86,11 +86,10 @@ void ksw_exts2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uin
int8_t q, int8_t e, int8_t q2, int8_t noncan, int zdrop, int flag, ksw_extz_t *ez);
extern void ksw_exts2_sse41(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat,
int8_t q, int8_t e, int8_t q2, int8_t noncan, int zdrop, int flag, ksw_extz_t *ez);
unsigned simd;
simd = x86_simd();
if (simd & SIMD_SSE4_1)
if (ksw_simd < 0) ksw_simd = x86_simd();
if (ksw_simd & SIMD_SSE4_1)
ksw_exts2_sse41(km, qlen, query, tlen, target, m, mat, q, e, q2, noncan, zdrop, flag, ez);
else if (simd & SIMD_SSE2)
else if (ksw_simd & SIMD_SSE2)
ksw_exts2_sse2(km, qlen, query, tlen, target, m, mat, q, e, q2, noncan, zdrop, flag, ez);
else abort();
}
+4 -2
View File
@@ -6,7 +6,7 @@
#include "mmpriv.h"
#include "ketopt.h"
#define MM_VERSION "2.13-r852-dirty"
#define MM_VERSION "2.14-r883"
#ifdef __linux__
#include <sys/resource.h>
@@ -60,6 +60,7 @@ static ko_longopt_t long_options[] = {
{ "split-prefix", ko_required_argument, 334 },
{ "no-end-flt", ko_no_argument, 335 },
{ "hard-mask-level",ko_no_argument, 336 },
{ "cap-sw-mem", ko_required_argument, 337 },
{ "help", ko_no_argument, 'h' },
{ "max-intron-len", ko_required_argument, 'G' },
{ "version", ko_no_argument, 'V' },
@@ -122,7 +123,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "[ERROR] missing option argument\n");
return 1;
} else if (c == '?') {
fprintf(stderr, "[ERROR] unknown option in \"%s\"\n", argv[o.i]);
fprintf(stderr, "[ERROR] unknown option in \"%s\"\n", argv[o.i - 1]);
return 1;
}
}
@@ -190,6 +191,7 @@ int main(int argc, char *argv[])
else if (c == 334) opt.split_prefix = o.arg; // --split-prefix
else if (c == 335) opt.flag |= MM_F_NO_END_FLT; // --no-end-flt
else if (c == 336) opt.flag |= MM_F_HARD_MLEVEL; // --hard-mask-level
else if (c == 337) opt.max_sw_mat = mm_parse_num(o.arg); // --cap-sw-mat
else if (c == 314) { // --frag
yes_or_no(&opt, MM_F_FRAG_MODE, o.longidx, o.arg, 1);
} else if (c == 315) { // --secondary
+1
View File
@@ -139,6 +139,7 @@ typedef struct {
int32_t mid_occ; // ignore seeds with occurrences above this threshold
int32_t max_occ;
int mini_batch_size; // size of a batch of query bases to process in parallel
int64_t max_sw_mat;
const char *split_prefix;
} mm_mapopt_t;
+11 -2
View File
@@ -1,4 +1,4 @@
.TH minimap2 1 "11 October 2018" "minimap2-2.13 (r850)" "Bioinformatics tools"
.TH minimap2 1 "5 November 2018" "minimap2-2.14 (r883)" "Bioinformatics tools"
.SH NAME
.PP
minimap2 - mapping and alignment between collections of DNA sequences
@@ -274,6 +274,10 @@ Only map to the reverse complement strand of the reference sequences.
.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]
.TP
.B --no-pairing
Treat two reads in a pair as independent reads. The mate related fields in SAM
are still properly populated.
.SS Alignment options
.TP 10
.BI -A \ INT
@@ -369,6 +373,11 @@ It helps to avoid tiny terminal exons. [6]
.B --no-end-flt
Don't filter seeds towards the ends of chains before performing base-level
alignment.
.TP
.BI --cap-sw-mem \ NUM
Skip alignment if the DP matrix size is above
.IR NUM .
Set 0 to disable [0].
.SS Input/output options
.TP 10
.B -a
@@ -493,7 +502,7 @@ Up to 10% sequence divergence.
.B asm20
Long assembly to reference mapping
.RB ( -k19
.B -w10 -A1 -B6 -O6,26 -E2,1 -s200 -z200
.B -w10 -A1 -B4 -O6,26 -E2,1 -s200 -z200
.BR --min-occ-floor=100 ).
Up to 20% sequence divergence.
.TP
+1 -2
View File
@@ -116,8 +116,7 @@ long peakrss(void)
double realtime(void)
{
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
gettimeofday(&tp, NULL);
return tp.tv_sec + tp.tv_usec * 1e-6;
}
+168 -12
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env k8
var paftools_version = '2.13-r850';
var paftools_version = '2.14-r883';
/*****************************
***** Library functions *****
@@ -564,10 +564,12 @@ function paf_call(args)
function paf_asmstat(args)
{
var c, min_seg_len = 10000, max_diff = 0.01;
while ((c = getopt(args, "l:d:")) != null) {
var c, min_seg_len = 10000, max_diff = 0.01, bp_flank_len = 0, bp_gap_len = 0;
while ((c = getopt(args, "l:d:b:g:")) != null) {
if (c == 'l') min_seg_len = parseInt(getopt.arg);
else if (c == 'd') max_diff = parseFloat(getopt.arg);
else if (c == 'b') bp_flank_len = parseInt(getopt.arg);
else if (c == 'g') bp_gap_len = parseInt(getopt.arg);
}
if (getopt.ind == args.length) {
print("Usage: paftools.js asmstat [options] <ref.fa.fai> <asm1.paf> [...]");
@@ -587,7 +589,7 @@ function paf_asmstat(args)
}
file.close();
function process_query(qblocks, qblock_len, bp) {
function process_query(qblocks, qblock_len, bp, qi) {
qblocks.sort(function(a,b) { return a[0]-b[0]; });
var last_k = null, last_blen = null, st = -1, en = -1, qcov = 0;
for (var k = 0; k < qblocks.length; ++k) {
@@ -612,6 +614,7 @@ function paf_asmstat(args)
var min = blen < last_blen? blen : last_blen;
var flank = k == 0? min : blen;
bp.push([flank, gap]);
qi.bp.push([flank, gap]);
}
last_k = k, last_blen = blen;
}
@@ -664,16 +667,22 @@ function paf_asmstat(args)
for (var i = 0; i < n_asm; ++i) {
var n_breaks = 0, qcov = 0;
var fn = args[getopt.ind + 1 + i];
header.push(fn.replace(/.paf(.gz)?$/, ""));
var label = fn.replace(/.paf(.gz)?$/, "");
header.push(label);
var ref_blocks = [], qblock_len = [], qblocks = [], bp = [];
var query = {};
var query = {}, qinfo = {};
var last_qname = null;
file = new File(fn);
while (file.readline(buf) >= 0) {
var m, line = buf.toString();
var t = line.split("\t");
t[1] = parseInt(t[1]);
if (t.length >= 2) query[t[0]] = t[1];
if (t.length >= 2) {
query[t[0]] = t[1];
if (qinfo[t[0]] == null) qinfo[t[0]] = {};
qinfo[t[0]].len = t[1];
qinfo[t[0]].bp = [];
}
if (t.length < 9) continue;
if (!/\ttp:A:[PI]/.test(line)) continue;
if ((m = /\tcg:Z:(\S+)/.exec(line)) == null) continue;
@@ -690,7 +699,7 @@ function paf_asmstat(args)
if (t[3] - t[2] < min_seg_len) continue;
if (t[0] != last_qname) {
if (last_qname != null)
qcov += process_query(qblocks, qblock_len, bp);
qcov += process_query(qblocks, qblock_len, bp, qinfo[last_qname]);
qblocks = [];
last_qname = t[0];
}
@@ -698,7 +707,7 @@ function paf_asmstat(args)
qblocks.push([t[2], t[3], t[4], t[5], t[7], t[8]]);
}
if (last_qname != null)
qcov += process_query(qblocks, qblock_len, bp);
qcov += process_query(qblocks, qblock_len, bp, qinfo[last_qname]);
file.close();
// compute NG50
@@ -733,12 +742,157 @@ function paf_asmstat(args)
rst[5][i] = n_breaks;
rst[6][i] = count_bp(bp, 500, 0);
rst[7][i] = count_bp(bp, 500, 10000);
// nb-plot
var qa = [];
for (var qn in qinfo)
qa.push([qinfo[qn].len, qinfo[qn].bp]);
qa = qa.sort(function(a, b) { return b[0] - a[0] });
var sum = 0, n_bp = 0, next_quantile = 0.1;
for (var j = 0; j < qa.length; ++j) {
sum += qa[j][0];
for (var k = 0; k < qa[j][1].length; ++k)
if (qa[j][1][k][0] >= bp_flank_len && qa[j][1][k][1] >= bp_gap_len)
++n_bp;
if (sum >= ref_len * next_quantile) {
print(label, Math.floor(next_quantile * 100 + .5), qa[j][0], (sum / n_bp).toFixed(0), n_bp);
next_quantile += 0.1;
if (next_quantile >= 1.0) break;
}
}
}
buf.destroy();
if (bp_flank_len <= 0) {
print(header.join("\t"));
for (var i = 0; i < labels.length; ++i)
print(labels[i], rst[i].join("\t"));
}
}
function paf_asmgene(args)
{
var c, opt = { min_cov:0.99, min_iden:0.99 }, print_err = false;
while ((c = getopt(args, "i:c:e")) != null)
if (c == 'i') opt.min_iden = parseFloat(getopt.arg);
else if (c == 'c') opt.min_cov = parseFloat(getopt.arg);
else if (c == 'e') print_err = true;
var n_fn = args.length - getopt.ind;
if (n_fn < 2) {
print("Usage: paftools.js asmgene [options] <ref-splice.paf> <asm-splice.paf> [...]");
print("Options:");
print(" -i FLOAT min identity [" + opt.min_iden + "]");
print(" -c FLOAT min coverage [" + opt.min_cov + "]");
print(" -e print fragmented/missing genes");
exit(1);
}
print(header.join("\t"));
for (var i = 0; i < labels.length; ++i)
print(labels[i], rst[i].join("\t"));
function process_query(opt, a) {
var b = [], cnt = [0, 0, 0];
for (var j = 0; j < a.length; ++j) {
if (a[j][4] < a[j][5] * opt.min_iden)
continue;
b.push(a[j].slice(0));
}
if (b.length == 0) return cnt;
// count full
var n_full = 0;
for (var j = 0; j < b.length; ++j)
if (b[j][3] - b[j][2] >= b[j][1] * opt.min_cov)
++n_full;
cnt[0] = n_full;
// compute coverage
b = b.sort(function(x, y) { return x[2] - y[2] });
var l_cov = 0, st = b[0][2], en = b[0][3];
for (var j = 1; j < b.length; ++j) {
if (b[j][2] <= en)
en = b[j][3] > en? b[j][3] : en;
else l_cov += en - st;
}
l_cov += en - st;
cnt[1] = l_cov / b[0][1];
cnt[2] = b.length;
return cnt;
}
var buf = new Bytes();
var gene = {}, header = [], refpos = {};
for (var i = getopt.ind; i < args.length; ++i) {
var fn = args[i];
var label = fn.replace(/.paf(.gz)?$/, "");
header.push(label);
var file = new File(fn), a = [];
while (file.readline(buf) >= 0) {
var t = buf.toString().split("\t");
var ql = parseInt(t[1]), qs = parseInt(t[2]), qe = parseInt(t[3]), mlen = parseInt(t[9]), blen = parseInt(t[10]), mapq = parseInt(t[11]);
if (i == getopt.ind) refpos[t[0]] = [t[0], t[1], t[5], t[7], t[8]];
if (gene[t[0]] == null) gene[t[0]] = [];
if (a.length && t[0] != a[0][0]) {
gene[t[0]][i - getopt.ind] = process_query(opt, a);
a = [];
}
a.push([t[0], ql, qs, qe, mlen, blen]);
}
if (a.length)
gene[t[0]][i - getopt.ind] = process_query(opt, a);
file.close();
}
// select the longest genes (not optimal, but should be good enough)
var gene_list = [], gene_nr = {};
for (var g in refpos)
gene_list.push(refpos[g]);
gene_list = gene_list.sort(function(a, b) { return a[2] < b[2]? -1 : a[2] > b[2]? 1 : a[3] - b[3] });
var last = 0;
for (var j = 1; j < gene_list.length; ++j) {
if (gene_list[j][2] != gene_list[last][2] || gene_list[j][3] >= gene_list[last][4]) {
gene_nr[gene_list[last][0]] = 1;
last = j;
} else if (gene_list[j][1] > gene_list[last][1]) {
last = j;
}
}
gene_nr[gene_list[last][0]] = 1;
// count and print
var col1 = ["full_sgl", "full_dup", "frag", "part50+", "part10+", "part10-"];
var rst = [];
for (var k = 0; k < col1.length; ++k) {
rst[k] = [];
for (var i = 0; i < n_fn; ++i)
rst[k][i] = 0;
}
for (var g in gene) {
if (gene[g][0] == null || gene[g][0][0] != 1) continue;
if (gene_nr[g] == null) continue;
for (var i = 0; i < n_fn; ++i) {
if (gene[g][i] == null) {
rst[4][i]++;
if (print_err) print('M', header[i], refpos[g].join("\t"));
} else if (gene[g][i][0] == 1) rst[0][i]++;
else if (gene[g][i][0] > 1) {
rst[1][i]++;
if (print_err) print('D', header[i], refpos[g].join("\t"));
} else if (gene[g][i][1] >= opt.min_cov) {
rst[2][i]++;
if (print_err) print('F', header[i], refpos[g].join("\t"));
} else if (gene[g][i][1] >= 0.5) {
rst[3][i]++;
if (print_err) print('5', header[i], refpos[g].join("\t"));
} else if (gene[g][i][1] >= 0.1) {
rst[4][i]++;
if (print_err) print('1', header[i], refpos[g].join("\t"));
} else {
rst[5][i]++;
if (print_err) print('0', header[i], refpos[g].join("\t")); // TODO: reduce code duplicates...
}
}
}
print('H', 'Metric', header.join("\t"));
for (var k = 0; k < rst.length; ++k) {
print('X', col1[k], rst[k].join("\t"));
}
buf.destroy();
}
@@ -2189,6 +2343,7 @@ function main(args)
print("");
print(" stat collect basic mapping information in PAF/SAM");
print(" asmstat collect basic assembly information");
print(" asmgene evaluate gene completeness (EXPERIMENTAL)");
print(" liftover simplistic liftOver");
print(" call call variants from asm-to-ref alignment with the cs tag");
print(" bedcov compute the number of bases covered");
@@ -2210,6 +2365,7 @@ function main(args)
else if (cmd == 'gff2bed') paf_gff2bed(args);
else if (cmd == 'stat') paf_stat(args);
else if (cmd == 'asmstat') paf_asmstat(args);
else if (cmd == 'asmgene') paf_asmgene(args);
else if (cmd == 'liftover' || cmd == 'liftOver') paf_liftover(args);
else if (cmd == 'call') paf_call(args);
else if (cmd == 'mapeval') paf_mapeval(args);
+5
View File
@@ -159,6 +159,11 @@ int mm_check_opt(const mm_idxopt_t *io, const mm_mapopt_t *mo)
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->e <= 0 || mo->q <= 0) {
if (mm_verbose >= 1)
fprintf(stderr, "[ERROR]\033[1;31m -O and -E must be positive\033[0m\n");
return -1;
}
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");
+1 -1
View File
@@ -54,7 +54,7 @@ void mm_set_pe_thru(const int *qlens, int *n_regs, mm_reg1_t **regs)
if (n_pri[0] == 1 && n_pri[1] == 1) {
mm_reg1_t *p = &regs[0][pri[0]];
mm_reg1_t *q = &regs[1][pri[1]];
if (p->rid == q->rid && p->rev == q->rev && abs(p->rs - q->rs) < 3 && abs(p->re - p->re) < 3
if (p->rid == q->rid && p->rev == q->rev && abs(p->rs - q->rs) < 3 && abs(p->re - q->re) < 3
&& ((p->qs == 0 && qlens[1] - q->qe == 0) || (q->qs == 0 && qlens[0] - p->qe == 0)))
{
p->pe_thru = q->pe_thru = 1;
+1
View File
@@ -40,6 +40,7 @@ cdef extern from "minimap.h":
int32_t mid_occ
int32_t max_occ
int mini_batch_size
int64_t max_sw_mat
const char *split_prefix
int mm_set_opt(char *preset, mm_idxopt_t *io, mm_mapopt_t *mo)
+1 -1
View File
@@ -3,7 +3,7 @@ from libc.stdlib cimport free
cimport cmappy
import sys
__version__ = '2.13'
__version__ = '2.14'
cmappy.mm_reset_timer()
+1 -1
View File
@@ -33,7 +33,7 @@ def readme():
setup(
name = 'mappy',
version = '2.13',
version = '2.14',
url = 'https://github.com/lh3/minimap2',
description = 'Minimap2 python binding',
long_description = readme(),