Compare commits

...
11 Commits
Author SHA1 Message Date
Heng Li 581f2d7123 Release minimap2-2.21 (r1071) 2021-07-06 13:18:55 -04:00
Heng Li 52dbd439bc r1080: re-versioning 2021-07-02 20:26:13 -04:00
John Marshall 260a68d232 Use #defines for CIGAR operators in C code
Give the CIGAR constants names to clarify the code. So that ksw2.h
remains self-contained, define KSW_* versions of the CIGAR operators
it needs for use within ksw2.h. Other code should in general use the
full set of MM_CIGAR_* constants in minimap.h.
2021-07-02 13:03:03 -04:00
John Marshall 177eef259d Use the full MIDNSHP=X string whenever printing CIGAR strings
Define MM_CIGAR_STR to the full string of CIGAR operators (including
the 'B' operator as well) and use it throughout the C code.

It would be possible to use it from the Cython code too, but it's easier
to keep that as a Cython string literal to avoid adding extra runtime
code to handle locale conversion.
2021-07-02 13:03:03 -04:00
Heng Li 459ce04c84 r1069: fixed a regression in comparison to v2.18
for PE short reads. An interesting omission. Resolves #776
2021-07-02 11:45:21 -04:00
Heng Li e6cce019e4 r1068: fixed a bug caused by 3f71478
Resolves #752 (again)
2021-06-30 19:20:06 -04:00
Heng Li 7025b0b941 Merge branch 'master' of github.com:lh3/minimap2 2021-06-16 10:18:40 -04:00
Heng Li fe6a0bb337 r1064: fixed another uninitialized condition
This one should also be harmless. It affects a min value, but that value is not
actually used.
2021-06-16 10:16:36 -04:00
Heng Li 3f7147864b r1063: fixed an uninitialized access (#752)
This one is harmless.
2021-06-16 09:27:30 -04:00
Torsten Houwaart c83589b9ea Update README.md
Clarification on approximate mapping
2021-06-10 09:36:39 -04:00
Heng Li ce7a59f412 Fixed a typo in README
I just hate my butterfly keyboard!
2021-05-27 15:43:04 -04:00
16 changed files with 113 additions and 81 deletions
+11
View File
@@ -1,3 +1,14 @@
Release 2.21-r1071 (6 July 2021)
--------------------------------
This release fixed a regression in short-read mapping introduced in v2.19
(#776). It also fixed invalid comparisons of uninitialized variables, though
these are harmless (#752). Long-read alignment should be identical to v2.20.
(2.21: 6 July 2021)
Release 2.20-r1061 (27 May 2021) Release 2.20-r1061 (27 May 2021)
-------------------------------- --------------------------------
+4 -4
View File
@@ -14,7 +14,7 @@ cd minimap2 && make
# use presets (no test data) # use presets (no test data)
./minimap2 -ax map-pb ref.fa pacbio.fq.gz > aln.sam # PacBio CLR genomic reads ./minimap2 -ax map-pb ref.fa pacbio.fq.gz > aln.sam # PacBio CLR genomic reads
./minimap2 -ax map-ont ref.fa ont.fq.gz > aln.sam # Oxford Nanopore genomic reads ./minimap2 -ax map-ont ref.fa ont.fq.gz > aln.sam # Oxford Nanopore genomic reads
./minimap2 -ax map-hifi ref.fa pacbio-ccs.fq.gz > aln.sam # PacBio HiFi/CCS genomic reads (v2.19 or lateer) ./minimap2 -ax map-hifi ref.fa pacbio-ccs.fq.gz > aln.sam # PacBio HiFi/CCS genomic reads (v2.19 or later)
./minimap2 -ax asm20 ref.fa pacbio-ccs.fq.gz > aln.sam # PacBio HiFi/CCS genomic reads (v2.18 or earlier) ./minimap2 -ax asm20 ref.fa pacbio-ccs.fq.gz > aln.sam # PacBio HiFi/CCS genomic reads (v2.18 or earlier)
./minimap2 -ax sr ref.fa read1.fa read2.fa > aln.sam # short genomic paired-end reads ./minimap2 -ax sr ref.fa read1.fa read2.fa > aln.sam # short genomic paired-end reads
./minimap2 -ax splice ref.fa rna-reads.fa > aln.sam # spliced long reads (strand unknown) ./minimap2 -ax splice ref.fa rna-reads.fa > aln.sam # spliced long reads (strand unknown)
@@ -74,8 +74,8 @@ Detailed evaluations are available from the [minimap2 paper][doi] or the
Minimap2 is optimized for x86-64 CPUs. You can acquire precompiled binaries from Minimap2 is optimized for x86-64 CPUs. You can acquire precompiled binaries from
the [release page][release] with: the [release page][release] with:
```sh ```sh
curl -L https://github.com/lh3/minimap2/releases/download/v2.20/minimap2-2.20_x64-linux.tar.bz2 | tar -jxvf - curl -L https://github.com/lh3/minimap2/releases/download/v2.21/minimap2-2.21_x64-linux.tar.bz2 | tar -jxvf -
./minimap2-2.20_x64-linux/minimap2 ./minimap2-2.21_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
@@ -96,7 +96,7 @@ with the ARM related command lines given above.
Without any options, minimap2 takes a reference database and a query sequence Without any options, minimap2 takes a reference database and a query sequence
file as input and produce approximate mapping, without base-level alignment file as input and produce approximate mapping, without base-level alignment
(i.e. no CIGAR), in the [PAF format][paf]: (i.e. coordinates are only approximate and no CIGAR in output), in the [PAF format][paf]:
```sh ```sh
minimap2 ref.fa query.fq > approx-mapping.paf minimap2 ref.fa query.fq > approx-mapping.paf
``` ```
+31 -31
View File
@@ -53,16 +53,16 @@ static int mm_test_zdrop(void *km, const mm_mapopt_t *opt, const uint8_t *qseq,
// find the score and the region where score drops most along diagonal // find the score and the region where score drops most along diagonal
for (k = 0, score = 0; k < n_cigar; ++k) { for (k = 0, score = 0; k < n_cigar; ++k) {
uint32_t l, op = cigar[k]&0xf, len = cigar[k]>>4; uint32_t l, op = cigar[k]&0xf, len = cigar[k]>>4;
if (op == 0) { if (op == MM_CIGAR_MATCH) {
for (l = 0; l < len; ++l) { for (l = 0; l < len; ++l) {
score += mat[tseq[i + l] * 5 + qseq[j + l]]; score += mat[tseq[i + l] * 5 + qseq[j + l]];
update_max_zdrop(score, i+l, j+l, &max, &max_i, &max_j, opt->e, &max_zdrop, pos); update_max_zdrop(score, i+l, j+l, &max, &max_i, &max_j, opt->e, &max_zdrop, pos);
} }
i += len, j += len; i += len, j += len;
} else if (op == 1 || op == 2 || op == 3) { } else if (op == MM_CIGAR_INS || op == MM_CIGAR_DEL || op == MM_CIGAR_N_SKIP) {
score -= opt->q + opt->e * len; score -= opt->q + opt->e * len;
if (op == 1) j += len; // insertion if (op == MM_CIGAR_INS) j += len;
else i += len; // deletion else i += len;
update_max_zdrop(score, i, j, &max, &max_i, &max_j, opt->e, &max_zdrop, pos); update_max_zdrop(score, i, j, &max, &max_i, &max_j, opt->e, &max_zdrop, pos);
} }
} }
@@ -98,12 +98,12 @@ static void mm_fix_cigar(mm_reg1_t *r, const uint8_t *qseq, const uint8_t *tseq,
for (k = 0; k < p->n_cigar; ++k) { // indel left alignment for (k = 0; k < p->n_cigar; ++k) { // indel left alignment
uint32_t op = p->cigar[k]&0xf, len = p->cigar[k]>>4; uint32_t op = p->cigar[k]&0xf, len = p->cigar[k]>>4;
if (len == 0) to_shrink = 1; if (len == 0) to_shrink = 1;
if (op == 0) { if (op == MM_CIGAR_MATCH) {
toff += len, qoff += len; toff += len, qoff += len;
} else if (op == 1 || op == 2) { // insertion or deletion } else if (op == MM_CIGAR_INS || op == MM_CIGAR_DEL) {
if (k > 0 && k < p->n_cigar - 1 && (p->cigar[k-1]&0xf) == 0 && (p->cigar[k+1]&0xf) == 0) { if (k > 0 && k < p->n_cigar - 1 && (p->cigar[k-1]&0xf) == 0 && (p->cigar[k+1]&0xf) == 0) {
int l, prev_len = p->cigar[k-1] >> 4; int l, prev_len = p->cigar[k-1] >> 4;
if (op == 1) { if (op == MM_CIGAR_INS) {
for (l = 0; l < prev_len; ++l) for (l = 0; l < prev_len; ++l)
if (qseq[qoff - 1 - l] != qseq[qoff + len - 1 - l]) if (qseq[qoff - 1 - l] != qseq[qoff + len - 1 - l])
break; break;
@@ -116,9 +116,9 @@ static void mm_fix_cigar(mm_reg1_t *r, const uint8_t *qseq, const uint8_t *tseq,
p->cigar[k-1] -= l<<4, p->cigar[k+1] += l<<4, qoff -= l, toff -= l; p->cigar[k-1] -= l<<4, p->cigar[k+1] += l<<4, qoff -= l, toff -= l;
if (l == prev_len) to_shrink = 1; if (l == prev_len) to_shrink = 1;
} }
if (op == 1) qoff += len; if (op == MM_CIGAR_INS) qoff += len;
else toff += len; else toff += len;
} else if (op == 3) { } else if (op == MM_CIGAR_N_SKIP) {
toff += len; toff += len;
} }
} }
@@ -128,13 +128,13 @@ static void mm_fix_cigar(mm_reg1_t *r, const uint8_t *qseq, const uint8_t *tseq,
uint32_t l, s[3] = {0,0,0}; uint32_t l, s[3] = {0,0,0};
for (l = k; l < p->n_cigar; ++l) { // count number of adjacent I and D for (l = k; l < p->n_cigar; ++l) { // count number of adjacent I and D
uint32_t op = p->cigar[l]&0xf; uint32_t op = p->cigar[l]&0xf;
if (op == 1 || op == 2 || p->cigar[l]>>4 == 0) if (op == MM_CIGAR_INS || op == MM_CIGAR_DEL || p->cigar[l]>>4 == 0)
s[op] += p->cigar[l] >> 4; s[op] += p->cigar[l] >> 4;
else break; else break;
} }
if (s[1] > 0 && s[2] > 0 && l - k > 2) { // turn to a single I and a single D if (s[1] > 0 && s[2] > 0 && l - k > 2) { // turn to a single I and a single D
p->cigar[k] = s[1]<<4|1; p->cigar[k] = s[1]<<4|MM_CIGAR_INS;
p->cigar[k+1] = s[2]<<4|2; p->cigar[k+1] = s[2]<<4|MM_CIGAR_DEL;
for (k += 2; k < l; ++k) for (k += 2; k < l; ++k)
p->cigar[k] &= 0xf; p->cigar[k] &= 0xf;
to_shrink = 1; to_shrink = 1;
@@ -154,9 +154,9 @@ static void mm_fix_cigar(mm_reg1_t *r, const uint8_t *qseq, const uint8_t *tseq,
else p->cigar[k+1] += p->cigar[k]>>4<<4; // add length to the next CIGAR operator else p->cigar[k+1] += p->cigar[k]>>4<<4; // add length to the next CIGAR operator
p->n_cigar = l; p->n_cigar = l;
} }
if ((p->cigar[0]&0xf) == 1 || (p->cigar[0]&0xf) == 2) { // get rid of leading I or D if ((p->cigar[0]&0xf) == MM_CIGAR_INS || (p->cigar[0]&0xf) == MM_CIGAR_DEL) { // get rid of leading I or D
int32_t l = p->cigar[0] >> 4; int32_t l = p->cigar[0] >> 4;
if ((p->cigar[0]&0xf) == 1) { if ((p->cigar[0]&0xf) == MM_CIGAR_INS) {
if (r->rev) r->qe -= l; if (r->rev) r->qe -= l;
else r->qs += l; else r->qs += l;
*qshift = l; *qshift = l;
@@ -174,7 +174,7 @@ static void mm_update_cigar_eqx(mm_reg1_t *r, const uint8_t *qseq, const uint8_t
if (r->p == 0) return; if (r->p == 0) return;
for (k = 0; k < r->p->n_cigar; ++k) { for (k = 0; k < r->p->n_cigar; ++k) {
uint32_t op = r->p->cigar[k]&0xf, len = r->p->cigar[k]>>4; uint32_t op = r->p->cigar[k]&0xf, len = r->p->cigar[k]>>4;
if (op == 0) { if (op == MM_CIGAR_MATCH) {
while (len > 0) { while (len > 0) {
for (l = 0; l < len && qseq[qoff + l] == tseq[toff + l]; ++l) {} // run of "="; TODO: N<=>N is converted to "=" for (l = 0; l < len && qseq[qoff + l] == tseq[toff + l]; ++l) {} // run of "="; TODO: N<=>N is converted to "="
if (l > 0) { ++n_EQX; len -= l; toff += l; qoff += l; } if (l > 0) { ++n_EQX; len -= l; toff += l; qoff += l; }
@@ -183,11 +183,11 @@ static void mm_update_cigar_eqx(mm_reg1_t *r, const uint8_t *qseq, const uint8_t
if (l > 0) { ++n_EQX; len -= l; toff += l; qoff += l; } if (l > 0) { ++n_EQX; len -= l; toff += l; qoff += l; }
} }
++n_M; ++n_M;
} else if (op == 1) { // insertion } else if (op == MM_CIGAR_INS) {
qoff += len; qoff += len;
} else if (op == 2) { // deletion } else if (op == MM_CIGAR_DEL) {
toff += len; toff += len;
} else if (op == 3) { // intron } else if (op == MM_CIGAR_N_SKIP) {
toff += len; toff += len;
} }
} }
@@ -195,7 +195,7 @@ static void mm_update_cigar_eqx(mm_reg1_t *r, const uint8_t *qseq, const uint8_t
if (n_EQX == n_M) { if (n_EQX == n_M) {
for (k = 0; k < r->p->n_cigar; ++k) { for (k = 0; k < r->p->n_cigar; ++k) {
uint32_t op = r->p->cigar[k]&0xf, len = r->p->cigar[k]>>4; uint32_t op = r->p->cigar[k]&0xf, len = r->p->cigar[k]>>4;
if (op == 0) r->p->cigar[k] = len << 4 | 7; if (op == MM_CIGAR_MATCH) r->p->cigar[k] = len << 4 | MM_CIGAR_EQ_MATCH;
} }
return; return;
} }
@@ -209,25 +209,25 @@ static void mm_update_cigar_eqx(mm_reg1_t *r, const uint8_t *qseq, const uint8_t
toff = qoff = m = 0; toff = qoff = m = 0;
for (k = 0; k < r->p->n_cigar; ++k) { for (k = 0; k < r->p->n_cigar; ++k) {
uint32_t op = r->p->cigar[k]&0xf, len = r->p->cigar[k]>>4; uint32_t op = r->p->cigar[k]&0xf, len = r->p->cigar[k]>>4;
if (op == 0) { // match/mismatch if (op == MM_CIGAR_MATCH) {
while (len > 0) { while (len > 0) {
// match // match
for (l = 0; l < len && qseq[qoff + l] == tseq[toff + l]; ++l) {} for (l = 0; l < len && qseq[qoff + l] == tseq[toff + l]; ++l) {}
if (l > 0) p->cigar[m++] = l << 4 | 7; if (l > 0) p->cigar[m++] = l << 4 | MM_CIGAR_EQ_MATCH;
len -= l; len -= l;
toff += l, qoff += l; toff += l, qoff += l;
// mismatch // mismatch
for (l = 0; l < len && qseq[qoff + l] != tseq[toff + l]; ++l) {} for (l = 0; l < len && qseq[qoff + l] != tseq[toff + l]; ++l) {}
if (l > 0) p->cigar[m++] = l << 4 | 8; if (l > 0) p->cigar[m++] = l << 4 | MM_CIGAR_X_MISMATCH;
len -= l; len -= l;
toff += l, qoff += l; toff += l, qoff += l;
} }
continue; continue;
} else if (op == 1) { // insertion } else if (op == MM_CIGAR_INS) {
qoff += len; qoff += len;
} else if (op == 2) { // deletion } else if (op == MM_CIGAR_DEL) {
toff += len; toff += len;
} else if (op == 3) { // intron } else if (op == MM_CIGAR_N_SKIP) {
toff += len; toff += len;
} }
p->cigar[m++] = r->p->cigar[k]; p->cigar[m++] = r->p->cigar[k];
@@ -248,7 +248,7 @@ static void mm_update_extra(mm_reg1_t *r, const uint8_t *qseq, const uint8_t *ts
r->blen = r->mlen = 0; r->blen = r->mlen = 0;
for (k = 0; k < p->n_cigar; ++k) { for (k = 0; k < p->n_cigar; ++k) {
uint32_t op = p->cigar[k]&0xf, len = p->cigar[k]>>4; uint32_t op = p->cigar[k]&0xf, len = p->cigar[k]>>4;
if (op == 0) { // match/mismatch if (op == MM_CIGAR_MATCH) {
int n_ambi = 0, n_diff = 0; int n_ambi = 0, n_diff = 0;
for (l = 0; l < len; ++l) { for (l = 0; l < len; ++l) {
int cq = qseq[qoff + l], ct = tseq[toff + l]; int cq = qseq[qoff + l], ct = tseq[toff + l];
@@ -260,7 +260,7 @@ static void mm_update_extra(mm_reg1_t *r, const uint8_t *qseq, const uint8_t *ts
} }
r->blen += len - n_ambi, r->mlen += len - (n_ambi + n_diff), p->n_ambi += n_ambi; r->blen += len - n_ambi, r->mlen += len - (n_ambi + n_diff), p->n_ambi += n_ambi;
toff += len, qoff += len; toff += len, qoff += len;
} else if (op == 1) { // insertion } else if (op == MM_CIGAR_INS) {
int n_ambi = 0; int n_ambi = 0;
for (l = 0; l < len; ++l) for (l = 0; l < len; ++l)
if (qseq[qoff + l] > 3) ++n_ambi; if (qseq[qoff + l] > 3) ++n_ambi;
@@ -268,7 +268,7 @@ static void mm_update_extra(mm_reg1_t *r, const uint8_t *qseq, const uint8_t *ts
s -= q + e * len; s -= q + e * len;
if (s < 0) s = 0; if (s < 0) s = 0;
qoff += len; qoff += len;
} else if (op == 2) { // deletion } else if (op == MM_CIGAR_DEL) {
int n_ambi = 0; int n_ambi = 0;
for (l = 0; l < len; ++l) for (l = 0; l < len; ++l)
if (tseq[toff + l] > 3) ++n_ambi; if (tseq[toff + l] > 3) ++n_ambi;
@@ -276,7 +276,7 @@ static void mm_update_extra(mm_reg1_t *r, const uint8_t *qseq, const uint8_t *ts
s -= q + e * len; s -= q + e * len;
if (s < 0) s = 0; if (s < 0) s = 0;
toff += len; toff += len;
} else if (op == 3) { // intron } else if (op == MM_CIGAR_N_SKIP) {
toff += len; toff += len;
} }
} }
@@ -333,7 +333,7 @@ static void mm_align_pair(void *km, const mm_mapopt_t *opt, int qlen, const uint
int i; int i;
fprintf(stderr, "score=%d, cigar=", ez->score); fprintf(stderr, "score=%d, cigar=", ez->score);
for (i = 0; i < ez->n_cigar; ++i) for (i = 0; i < ez->n_cigar; ++i)
fprintf(stderr, "%d%c", ez->cigar[i]>>4, "MIDN"[ez->cigar[i]&0xf]); fprintf(stderr, "%d%c", ez->cigar[i]>>4, MM_CIGAR_STR[ez->cigar[i]&0xf]);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
} }
@@ -730,7 +730,7 @@ static void mm_align1(void *km, const mm_mapopt_t *opt, const mm_idx_t *mi, int
if (qseq[j] >= 4 || tseq[j] >= 4) ez->score += opt->e2; if (qseq[j] >= 4 || tseq[j] >= 4) ez->score += opt->e2;
else ez->score += qseq[j] == tseq[j]? opt->a : -opt->b; else ez->score += qseq[j] == tseq[j]? opt->a : -opt->b;
} }
ez->cigar = ksw_push_cigar(km, &ez->n_cigar, &ez->m_cigar, ez->cigar, 0, qe - qs); ez->cigar = ksw_push_cigar(km, &ez->n_cigar, &ez->m_cigar, ez->cigar, MM_CIGAR_MATCH, qe - qs);
} else { // perform normal gapped alignment } else { // perform normal gapped alignment
mm_align_pair(km, opt, qe - qs, qseq, re - rs, tseq, junc, mat, bw1, -1, opt->zdrop, extra_flag|KSW_EZ_APPROX_MAX, ez); // first pass: with approximate Z-drop mm_align_pair(km, opt, qe - qs, qseq, re - rs, tseq, junc, mat, bw1, -1, opt->zdrop, extra_flag|KSW_EZ_APPROX_MAX, ez); // first pass: with approximate Z-drop
} }
+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: please follow the command lines below:
```sh ```sh
# install minimap2 executables # install minimap2 executables
curl -L https://github.com/lh3/minimap2/releases/download/v2.20/minimap2-2.20_x64-linux.tar.bz2 | tar jxf - curl -L https://github.com/lh3/minimap2/releases/download/v2.21/minimap2-2.21_x64-linux.tar.bz2 | tar jxf -
cp minimap2-2.20_x64-linux/{minimap2,k8,paftools.js} . # copy executables cp minimap2-2.21_x64-linux/{minimap2,k8,paftools.js} . # copy executables
export PATH="$PATH:"`pwd` # put the current directory on PATH export PATH="$PATH:"`pwd` # put the current directory on PATH
# download example datasets # download example datasets
curl -L https://github.com/lh3/minimap2/releases/download/v2.10/cookbook-data.tgz | tar zxf - curl -L https://github.com/lh3/minimap2/releases/download/v2.10/cookbook-data.tgz | tar zxf -
+1 -1
View File
@@ -47,7 +47,7 @@ int main(int argc, char *argv[])
printf("%s\t%d\t%d\t%d\t%c\t", ks->name.s, ks->seq.l, r->qs, r->qe, "+-"[r->rev]); printf("%s\t%d\t%d\t%d\t%c\t", ks->name.s, ks->seq.l, r->qs, r->qe, "+-"[r->rev]);
printf("%s\t%d\t%d\t%d\t%d\t%d\t%d\tcg:Z:", mi->seq[r->rid].name, mi->seq[r->rid].len, r->rs, r->re, r->mlen, r->blen, r->mapq); printf("%s\t%d\t%d\t%d\t%d\t%d\t%d\tcg:Z:", mi->seq[r->rid].name, mi->seq[r->rid].len, r->rs, r->re, r->mlen, r->blen, r->mapq);
for (i = 0; i < r->p->n_cigar; ++i) // IMPORTANT: this gives the CIGAR in the aligned regions. NO soft/hard clippings! for (i = 0; i < r->p->n_cigar; ++i) // IMPORTANT: this gives the CIGAR in the aligned regions. NO soft/hard clippings!
printf("%d%c", r->p->cigar[i]>>4, "MIDNSH"[r->p->cigar[i]&0xf]); printf("%d%c", r->p->cigar[i]>>4, MM_CIGAR_STR[r->p->cigar[i]&0xf]);
putchar('\n'); putchar('\n');
free(r->p); free(r->p);
} }
+12 -12
View File
@@ -144,8 +144,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:"); if (write_tag) mm_sprintf_lite(s, "\tcs:Z:");
for (i = q_off = t_off = 0; i < (int)r->p->n_cigar; ++i) { 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; int j, op = r->p->cigar[i]&0xf, len = r->p->cigar[i]>>4;
assert((op >= 0 && op <= 3) || op == 7 || op == 8); assert((op >= MM_CIGAR_MATCH && op <= MM_CIGAR_N_SKIP) || op == MM_CIGAR_EQ_MATCH || op == MM_CIGAR_X_MISMATCH);
if (op == 0 || op == 7 || op == 8) { // match if (op == MM_CIGAR_MATCH || op == MM_CIGAR_EQ_MATCH || op == MM_CIGAR_X_MISMATCH) {
int l_tmp = 0; int l_tmp = 0;
for (j = 0; j < len; ++j) { for (j = 0; j < len; ++j) {
if (qseq[q_off + j] != tseq[t_off + j]) { if (qseq[q_off + j] != tseq[t_off + j]) {
@@ -166,12 +166,12 @@ static void write_cs_core(kstring_t *s, const uint8_t *tseq, const uint8_t *qseq
} else mm_sprintf_lite(s, ":%d", l_tmp); } else mm_sprintf_lite(s, ":%d", l_tmp);
} }
q_off += len, t_off += len; q_off += len, t_off += len;
} else if (op == 1) { // insertion to ref } else if (op == MM_CIGAR_INS) {
for (j = 0, tmp[len] = 0; j < len; ++j) for (j = 0, tmp[len] = 0; j < len; ++j)
tmp[j] = "acgtn"[qseq[q_off + j]]; tmp[j] = "acgtn"[qseq[q_off + j]];
mm_sprintf_lite(s, "+%s", tmp); mm_sprintf_lite(s, "+%s", tmp);
q_off += len; q_off += len;
} else if (op == 2) { // deletion from ref } else if (op == MM_CIGAR_DEL) {
for (j = 0, tmp[len] = 0; j < len; ++j) for (j = 0, tmp[len] = 0; j < len; ++j)
tmp[j] = "acgtn"[tseq[t_off + j]]; tmp[j] = "acgtn"[tseq[t_off + j]];
mm_sprintf_lite(s, "-%s", tmp); mm_sprintf_lite(s, "-%s", tmp);
@@ -192,8 +192,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:"); if (write_tag) mm_sprintf_lite(s, "\tMD:Z:");
for (i = q_off = t_off = 0; i < (int)r->p->n_cigar; ++i) { 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; int j, op = r->p->cigar[i]&0xf, len = r->p->cigar[i]>>4;
assert((op >= 0 && op <= 3) || op == 7 || op == 8); assert((op >= MM_CIGAR_MATCH && op <= MM_CIGAR_N_SKIP) || op == MM_CIGAR_EQ_MATCH || op == MM_CIGAR_X_MISMATCH);
if (op == 0 || op == 7 || op == 8) { // match if (op == MM_CIGAR_MATCH || op == MM_CIGAR_EQ_MATCH || op == MM_CIGAR_X_MISMATCH) {
for (j = 0; j < len; ++j) { for (j = 0; j < len; ++j) {
if (qseq[q_off + j] != tseq[t_off + j]) { if (qseq[q_off + j] != tseq[t_off + j]) {
mm_sprintf_lite(s, "%d%c", l_MD, "ACGTN"[tseq[t_off + j]]); mm_sprintf_lite(s, "%d%c", l_MD, "ACGTN"[tseq[t_off + j]]);
@@ -201,15 +201,15 @@ static void write_MD_core(kstring_t *s, const uint8_t *tseq, const uint8_t *qseq
} else ++l_MD; } else ++l_MD;
} }
q_off += len, t_off += len; q_off += len, t_off += len;
} else if (op == 1) { // insertion to ref } else if (op == MM_CIGAR_INS) {
q_off += len; q_off += len;
} else if (op == 2) { // deletion from ref } else if (op == MM_CIGAR_DEL) {
for (j = 0, tmp[len] = 0; j < len; ++j) for (j = 0, tmp[len] = 0; j < len; ++j)
tmp[j] = "ACGTN"[tseq[t_off + j]]; tmp[j] = "ACGTN"[tseq[t_off + j]];
mm_sprintf_lite(s, "%d^%s", l_MD, tmp); mm_sprintf_lite(s, "%d^%s", l_MD, tmp);
l_MD = 0; l_MD = 0;
t_off += len; t_off += len;
} else if (op == 3) { // reference skip } else if (op == MM_CIGAR_N_SKIP) {
t_off += len; t_off += len;
} }
} }
@@ -271,7 +271,7 @@ double mm_event_identity(const mm_reg1_t *r)
if (r->p == 0) return -1.0f; if (r->p == 0) return -1.0f;
for (i = 0; i < r->p->n_cigar; ++i) { for (i = 0; i < r->p->n_cigar; ++i) {
int32_t op = r->p->cigar[i] & 0xf, len = r->p->cigar[i] >> 4; int32_t op = r->p->cigar[i] & 0xf, len = r->p->cigar[i] >> 4;
if (op == 1 || op == 2) if (op == MM_CIGAR_INS || op == MM_CIGAR_DEL)
++n_gapo, n_gap += len; ++n_gapo, n_gap += len;
} }
return (double)r->mlen / (r->blen + r->p->n_ambi - n_gap + n_gapo); return (double)r->mlen / (r->blen + r->p->n_ambi - n_gap + n_gapo);
@@ -325,7 +325,7 @@ void mm_write_paf3(kstring_t *s, const mm_idx_t *mi, const mm_bseq1_t *t, const
uint32_t k; uint32_t k;
mm_sprintf_lite(s, "\tcg:Z:"); mm_sprintf_lite(s, "\tcg:Z:");
for (k = 0; k < r->p->n_cigar; ++k) for (k = 0; k < r->p->n_cigar; ++k)
mm_sprintf_lite(s, "%d%c", r->p->cigar[k]>>4, "MIDNSHP=XB"[r->p->cigar[k]&0xf]); mm_sprintf_lite(s, "%d%c", r->p->cigar[k]>>4, MM_CIGAR_STR[r->p->cigar[k]&0xf]);
} }
if (r->p && (opt_flag & (MM_F_OUT_CS|MM_F_OUT_MD))) if (r->p && (opt_flag & (MM_F_OUT_CS|MM_F_OUT_MD)))
write_cs_or_MD(km, s, mi, t, r, !(opt_flag&MM_F_OUT_CS_LONG), opt_flag&MM_F_OUT_MD, 1); write_cs_or_MD(km, s, mi, t, r, !(opt_flag&MM_F_OUT_CS_LONG), opt_flag&MM_F_OUT_MD, 1);
@@ -382,7 +382,7 @@ static void write_sam_cigar(kstring_t *s, int sam_flag, int in_tag, int qlen, co
assert(clip_len[0] < qlen && clip_len[1] < qlen); assert(clip_len[0] < qlen && clip_len[1] < qlen);
if (clip_len[0]) mm_sprintf_lite(s, "%d%c", clip_len[0], clip_char); if (clip_len[0]) mm_sprintf_lite(s, "%d%c", clip_len[0], clip_char);
for (k = 0; k < r->p->n_cigar; ++k) for (k = 0; k < r->p->n_cigar; ++k)
mm_sprintf_lite(s, "%d%c", r->p->cigar[k]>>4, "MIDNSHP=XB"[r->p->cigar[k]&0xf]); mm_sprintf_lite(s, "%d%c", r->p->cigar[k]>>4, MM_CIGAR_STR[r->p->cigar[k]&0xf]);
if (clip_len[1]) mm_sprintf_lite(s, "%d%c", clip_len[1], clip_char); if (clip_len[1]) mm_sprintf_lite(s, "%d%c", clip_len[1], clip_char);
} }
} }
+1 -1
View File
@@ -247,7 +247,7 @@ int main(void) {
unsigned char dir[KRMQ_MAX_DEPTH]; \ unsigned char dir[KRMQ_MAX_DEPTH]; \
int i, d = 0, cmp; \ int i, d = 0, cmp; \
unsigned cnt = 0; \ unsigned cnt = 0; \
fake.__head.p[0] = *root_, fake.__head.p[1] = 0; \ fake = **root_, fake.__head.p[0] = *root_, fake.__head.p[1] = 0; \
if (cnt_) *cnt_ = 0; \ if (cnt_) *cnt_ = 0; \
if (x) { \ if (x) { \
for (cmp = -1, p = &fake; cmp; cmp = __cmp(x, p)) { \ for (cmp = -1, p = &fake; cmp; cmp = __cmp(x, p)) { \
+13 -6
View File
@@ -16,6 +16,13 @@
#define KSW_EZ_SPLICE_REV 0x200 #define KSW_EZ_SPLICE_REV 0x200
#define KSW_EZ_SPLICE_FLANK 0x400 #define KSW_EZ_SPLICE_FLANK 0x400
// The subset of CIGAR operators used by ksw code.
// Use MM_CIGAR_* from minimap.h if you need the full list.
#define KSW_CIGAR_MATCH 0
#define KSW_CIGAR_INS 1
#define KSW_CIGAR_DEL 2
#define KSW_CIGAR_N_SKIP 3
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -137,13 +144,13 @@ static inline void ksw_backtrack(void *km, int is_rot, int is_rev, int min_intro
else if (!(tmp >> (state + 2) & 1)) state = 0; // if requesting other states, _state_ stays the same if it is a continuation; otherwise, set to H else if (!(tmp >> (state + 2) & 1)) state = 0; // if requesting other states, _state_ stays the same if it is a continuation; otherwise, set to H
if (state == 0) state = tmp & 7; // TODO: probably this line can be merged into the "else if" line right above; not 100% sure if (state == 0) state = tmp & 7; // TODO: probably this line can be merged into the "else if" line right above; not 100% sure
if (force_state >= 0) state = force_state; if (force_state >= 0) state = force_state;
if (state == 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 0, 1), --i, --j; // match if (state == 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, KSW_CIGAR_MATCH, 1), --i, --j;
else if (state == 1 || (state == 3 && min_intron_len <= 0)) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 2, 1), --i; // deletion else if (state == 1 || (state == 3 && min_intron_len <= 0)) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, KSW_CIGAR_DEL, 1), --i;
else if (state == 3 && min_intron_len > 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 3, 1), --i; // intron else if (state == 3 && min_intron_len > 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, KSW_CIGAR_N_SKIP, 1), --i;
else cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 1, 1), --j; // insertion else cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, KSW_CIGAR_INS, 1), --j;
} }
if (i >= 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, min_intron_len > 0 && i >= min_intron_len? 3 : 2, i + 1); // first deletion if (i >= 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, min_intron_len > 0 && i >= min_intron_len? KSW_CIGAR_N_SKIP : KSW_CIGAR_DEL, i + 1); // first deletion
if (j >= 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 1, j + 1); // first insertion if (j >= 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, KSW_CIGAR_INS, j + 1); // first insertion
if (!is_rev) if (!is_rev)
for (i = 0; i < n_cigar>>1; ++i) // reverse CIGAR for (i = 0; i < n_cigar>>1; ++i) // reverse CIGAR
tmp = cigar[i], cigar[i] = cigar[n_cigar-1-i], cigar[n_cigar-1-i] = tmp; tmp = cigar[i], cigar[i] = cigar[n_cigar-1-i], cigar[n_cigar-1-i] = tmp;
+3 -2
View File
@@ -114,8 +114,9 @@ static inline int32_t comput_sc(const mm128_t *ai, const mm128_t *aj, int32_t ma
float lin_pen, log_pen; float lin_pen, log_pen;
lin_pen = chn_pen_gap * (float)dd + chn_pen_skip * (float)dg; lin_pen = chn_pen_gap * (float)dd + chn_pen_skip * (float)dg;
log_pen = dd >= 1? mg_log2(dd + 1) : 0.0f; // mg_log2() only works for dd>=2 log_pen = dd >= 1? mg_log2(dd + 1) : 0.0f; // mg_log2() only works for dd>=2
if (is_cdna) { if (is_cdna || sidi != sidj) {
if (dr > dq) sc -= (int)(lin_pen < log_pen? lin_pen : log_pen); // deletion or jump between paired ends if (sidi != sidj && dr == 0) ++sc; // possibly due to overlapping paired ends; give a minor bonus
else if (dr > dq || sidi != sidj) sc -= (int)(lin_pen < log_pen? lin_pen : log_pen); // deletion or jump between paired ends
else sc -= (int)(lin_pen + .5f * log_pen); else sc -= (int)(lin_pen + .5f * log_pen);
} else sc -= (int)(lin_pen + .5f * log_pen); } else sc -= (int)(lin_pen + .5f * log_pen);
} }
+1 -1
View File
@@ -7,7 +7,7 @@
#include "mmpriv.h" #include "mmpriv.h"
#include "ketopt.h" #include "ketopt.h"
#define MM_VERSION "2.20-r1061" #define MM_VERSION "2.21-r1071"
#ifdef __linux__ #ifdef __linux__
#include <sys/resource.h> #include <sys/resource.h>
+12
View File
@@ -46,6 +46,18 @@
#define MM_MAX_SEG 255 #define MM_MAX_SEG 255
#define MM_CIGAR_MATCH 0
#define MM_CIGAR_INS 1
#define MM_CIGAR_DEL 2
#define MM_CIGAR_N_SKIP 3
#define MM_CIGAR_SOFTCLIP 4
#define MM_CIGAR_HARDCLIP 5
#define MM_CIGAR_PADDING 6
#define MM_CIGAR_EQ_MATCH 7
#define MM_CIGAR_X_MISMATCH 8
#define MM_CIGAR_STR "MIDNSHP=XB"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
+3 -3
View File
@@ -1,4 +1,4 @@
.TH minimap2 1 "27 May 2021" "minimap2-2.20 (r1061)" "Bioinformatics tools" .TH minimap2 1 "6 July 2021" "minimap2-2.21 (r1071)" "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
@@ -592,8 +592,8 @@ Long-read splice alignment for PacBio CCS reads
.B sr .B sr
Short single-end reads without splicing Short single-end reads without splicing
.RB ( -k21 .RB ( -k21
.B -w11 --sr --frag=yes -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 -r100 -p.5 -N20 -f1000,5000 -n2 -m20
.B -s40 -g200 -2K50m --heap-sort=yes .B -s40 -g100 -2K50m --heap-sort=yes
.BR --secondary=no ). .BR --secondary=no ).
.TP .TP
.B ava-pb .B ava-pb
+4 -4
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env k8 #!/usr/bin/env k8
var paftools_version = '2.20-r1061'; var paftools_version = '2.21-r1071';
/***************************** /*****************************
***** Library functions ***** ***** Library functions *****
@@ -1419,7 +1419,7 @@ function paf_view(args)
var s_ref = new Bytes(), s_qry = new Bytes(), s_mid = new Bytes(); // these are used to show padded alignment var s_ref = new Bytes(), s_qry = new Bytes(), s_mid = new Bytes(); // these are used to show padded alignment
var re_cs = /([:=\-\+\*])(\d+|[A-Za-z]+)/g; var re_cs = /([:=\-\+\*])(\d+|[A-Za-z]+)/g;
var re_cg = /(\d+)([MIDNSH])/g; var re_cg = /(\d+)([MIDNSHP=X])/g;
var buf = new Bytes(); var buf = new Bytes();
var file = args[getopt.ind] == "-"? new File() : new File(args[getopt.ind]); var file = args[getopt.ind] == "-"? new File() : new File(args[getopt.ind]);
@@ -1899,7 +1899,7 @@ function paf_splice2bed(args)
a.length = 0; a.length = 0;
} }
var re = /(\d+)([MIDNSH])/g; var re = /(\d+)([MIDNSHP=X])/g;
var c, fmt = "bed", fn_name_conv = null, keep_multi = false; var c, fmt = "bed", fn_name_conv = null, keep_multi = false;
while ((c = getopt(args, "f:n:m")) != null) { while ((c = getopt(args, "f:n:m")) != null) {
if (c == 'f') fmt = getopt.arg; if (c == 'f') fmt = getopt.arg;
@@ -2369,7 +2369,7 @@ function paf_junceval(args)
file = getopt.ind+1 >= args.length || args[getopt.ind+1] == '-'? new File() : new File(args[getopt.ind+1]); file = getopt.ind+1 >= args.length || args[getopt.ind+1] == '-'? new File() : new File(args[getopt.ind+1]);
var last_qname = null; var last_qname = null;
var re_cigar = /(\d+)([MIDNSHX=])/g; var re_cigar = /(\d+)([MIDNSHP=X])/g;
while (file.readline(buf) >= 0) { while (file.readline(buf) >= 0) {
var m, t = buf.toString().split("\t"); var m, t = buf.toString().split("\t");
var ctg_name = null, cigar = null, pos = null, qname = t[0]; var ctg_name = null, cigar = null, pos = null, qname = t[0];
+2 -2
View File
@@ -3,7 +3,7 @@ from libc.stdlib cimport free
cimport cmappy cimport cmappy
import sys import sys
__version__ = '2.20' __version__ = '2.21'
cmappy.mm_reset_timer() cmappy.mm_reset_timer()
@@ -82,7 +82,7 @@ cdef class Alignment:
@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]) + 'MIDNSHP=XB'[x[1]], self._cigar))
def __str__(self): def __str__(self):
if self._strand > 0: strand = '+' if self._strand > 0: strand = '+'
+12 -11
View File
@@ -46,19 +46,20 @@ void mm_seed_select(int32_t n, mm_seed_t *a, int len, int max_occ, int max_max_o
int32_t pe = i == n? len : (uint32_t)a[i].q_pos>>1; int32_t pe = i == n? len : (uint32_t)a[i].q_pos>>1;
int32_t j, k, st = last0 + 1, en = i; int32_t j, k, st = last0 + 1, en = i;
int32_t max_high_occ = (int32_t)((double)(pe - ps) / dist + .499); int32_t max_high_occ = (int32_t)((double)(pe - ps) / dist + .499);
//fprintf(stderr, "Y\t%d\t%d\n", ps, pe); if (max_high_occ > 0) {
if (max_high_occ > MAX_MAX_HIGH_OCC) if (max_high_occ > MAX_MAX_HIGH_OCC)
max_high_occ = MAX_MAX_HIGH_OCC; max_high_occ = MAX_MAX_HIGH_OCC;
for (j = st, k = 0; j < en && k < max_high_occ; ++j, ++k) for (j = st, k = 0; j < en && k < max_high_occ; ++j, ++k)
b[k] = (uint64_t)a[j].n<<32 | j; b[k] = (uint64_t)a[j].n<<32 | j;
ks_heapmake_uint64_t(k, b); // initialize the binomial heap ks_heapmake_uint64_t(k, b); // initialize the binomial heap
for (; j < en; ++j) { // if there are more, choose top max_high_occ for (; j < en; ++j) { // if there are more, choose top max_high_occ
if (a[j].n < (int32_t)(b[0]>>32)) { // then update the heap if (a[j].n < (int32_t)(b[0]>>32)) { // then update the heap
b[0] = (uint64_t)a[j].n<<32 | j; b[0] = (uint64_t)a[j].n<<32 | j;
ks_heapdown_uint64_t(0, k, b); ks_heapdown_uint64_t(0, k, b);
}
} }
for (j = 0; j < k; ++j) a[(uint32_t)b[j]].flt = 1;
} }
for (j = 0; j < k; ++j) a[(uint32_t)b[j]].flt = 1;
for (j = st; j < en; ++j) a[j].flt ^= 1; for (j = st; j < en; ++j) a[j].flt ^= 1;
for (j = st; j < en; ++j) for (j = st; j < en; ++j)
if (a[j].n > max_max_occ) if (a[j].n > max_max_occ)
+1 -1
View File
@@ -23,7 +23,7 @@ def readme():
setup( setup(
name = 'mappy', name = 'mappy',
version = '2.20', version = '2.21',
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(),