Compare commits

..
30 Commits
Author SHA1 Message Date
Heng Li eec02c07b1 updated the manpage 2025-04-01 09:25:01 -04:00
Heng Li 736301fa6b Updated the manpage 2021-11-18 17:28:31 -05:00
Heng Li a3337c09f1 updated the manpage to v2.21 2021-07-07 11:38:14 -04:00
Heng Li 81b3da7677 updated the manpage 2021-06-26 19:29:14 -04:00
Heng Li 870f2cc2b9 updated the manpage 2021-04-09 13:53:14 -04:00
Heng Li ee9f561e2f Update the manpage to v2.17 2019-05-05 09:30:56 -04:00
Heng Li 514612bda2 updated manpage to v2.16 2019-02-28 15:59:13 -05:00
Heng Li 3508ac9817 updated manpage to v2.13 2018-10-11 13:35:09 -04:00
Heng Li 87d12c3307 updated citation 2018-05-30 11:15:28 -04:00
Heng Li d302ab2ad7 Updated the manpage to v2.10 2018-03-27 12:29:09 -04:00
Heng Li 15d8cb178f Fixed incorrect description of --dual 2018-02-01 15:12:24 -05:00
Heng Li 049674df4b Updated the manpage to v2.8 2018-02-01 15:06:52 -05:00
Heng Li cbed28eaf1 updated manpage 2017-12-13 09:03:19 -05:00
Heng Li 4e1456af51 added git clone 2017-11-27 10:21:33 -05:00
Heng Li 0764af1545 changed the formatting 2017-11-27 10:11:38 -05:00
Heng Li 5064a10574 added sections to the index page 2017-11-27 10:07:01 -05:00
Heng Li 6e656adc55 minor format changes 2017-11-24 12:02:22 -05:00
Heng Li 7fffff3a85 minor changes 2017-11-24 11:57:53 -05:00
Heng Li 12acf35622 don't put README here 2017-11-24 11:55:45 -05:00
Heng Li fa695beddd merged README into index 2017-11-24 11:50:46 -05:00
Heng Li 646e7770e7 the minimap2 README 2017-11-24 11:48:21 -05:00
Heng Li f42feba7be more links 2017-11-24 11:36:31 -05:00
Heng Li 8764e92127 more info 2017-11-24 11:29:09 -05:00
Heng Li 1ed1f6619f Set theme jekyll-theme-modernist 2017-11-24 11:23:15 -05:00
Heng Li 9c8f34216a changed theme 2017-11-24 11:22:51 -05:00
Heng Li 264d85d003 rename 2017-11-24 11:20:58 -05:00
Heng Li f65e8c38e0 Merge branch 'gh-pages' of github.com:lh3/minimap2 into gh-pages 2017-11-24 11:12:27 -05:00
Heng Li 25fed6646d added toy README 2017-11-24 11:11:09 -05:00
Heng Li d3f4fd619a Set theme jekyll-theme-minimal 2017-11-24 11:07:11 -05:00
Heng Li f41bb0e327 manpage 2017-11-24 10:59:58 -05:00
43 changed files with 949 additions and 7053 deletions
-4
View File
@@ -1,4 +0,0 @@
.*.swp
*.a
*.o
*.dSYM
-23
View File
@@ -1,23 +0,0 @@
The MIT License
Copyright (c) 2017 Broad Institute, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-59
View File
@@ -1,59 +0,0 @@
CC= gcc
CFLAGS= -g -Wall -O2 -Wc++-compat
CPPFLAGS= -DHAVE_KALLOC
INCLUDES= -I.
OBJS= kthread.o kalloc.o ksw2_extz2_sse.o ksw2_extd2_sse.o ksw2_ll_sse.o misc.o bseq.o \
sketch.o sdust.o index.o chain.o align.o hit.o map.o format.o
PROG= minimap2
PROG_EXTRA= sdust minimap2-lite
LIBS= -lm -lz -lpthread
ifeq ($(sse2only),)
CFLAGS+=-msse4
endif
.SUFFIXES:.c .o
.c.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) $(INCLUDES) $< -o $@
all:$(PROG)
extra:all $(PROG_EXTRA)
minimap2:main.o libminimap2.a
$(CC) $(CFLAGS) $< -o $@ -L. -lminimap2 $(LIBS)
minimap2-lite:example.o libminimap2.a
$(CC) $(CFLAGS) $< -o $@ -L. -lminimap2 $(LIBS)
libminimap2.a:$(OBJS)
$(AR) -csru $@ $(OBJS)
sdust:sdust.c kalloc.o kalloc.h kdq.h kvec.h kseq.h sdust.h
$(CC) -D_SDUST_MAIN $(CFLAGS) $< kalloc.o -o $@ -lz
clean:
rm -fr gmon.out *.o a.out $(PROG) $(PROG_EXTRA) *~ *.a *.dSYM session*
depend:
(LC_ALL=C; export LC_ALL; makedepend -Y -- $(CFLAGS) $(CPPFLAGS) -- *.c)
# DO NOT DELETE
align.o: minimap.h mmpriv.h bseq.h ksw2.h kalloc.h
bseq.o: bseq.h kseq.h
chain.o: minimap.h mmpriv.h bseq.h kalloc.h
example.o: minimap.h kseq.h
format.o: mmpriv.h minimap.h bseq.h
hit.o: mmpriv.h minimap.h bseq.h kalloc.h
index.o: kthread.h bseq.h minimap.h mmpriv.h kvec.h kalloc.h khash.h
kalloc.o: kalloc.h
ksw2_extd2_sse.o: ksw2.h kalloc.h
ksw2_extz2_sse.o: ksw2.h kalloc.h
ksw2_ll_sse.o: ksw2.h kalloc.h
main.o: bseq.h minimap.h mmpriv.h
map.o: kthread.h kvec.h kalloc.h sdust.h mmpriv.h minimap.h bseq.h
misc.o: minimap.h ksort.h
sdust.o: kalloc.h kdq.h kvec.h sdust.h
sketch.o: kvec.h kalloc.h minimap.h
-34
View File
@@ -1,34 +0,0 @@
Release 2.0rc1-r232 (30 July 2017)
----------------------------------
This release improves the accuracy of long-read alignment and added several
minor features.
* Improved mapping quality estimate for short alignments containing few seed
hits.
* Fixed a minor bug that affects the chaining accuracy towards the ends of a
chain. Changed the gap cost for chaining to reduce false seeding.
* Skip potentially wrong seeding and apply dynamic programming more frequently.
This slightly increases run time, but greatly reduces false long gaps.
* Perform local alignment at Z-drop break point to recover potential inversion
alignment. Output the SA tag in the SAM format. Added scripts to evaluate
mapping accuracy for reads simulated with pbsim.
This release completes features intended for v2.0. No major features will be
added to the master branch before the final v2.0.
(2.0rc1: 30 July 2017, r232)
Release r191 (19 July 2017)
---------------------------
This is the first public release of minimap2, an aligner for long reads and
assemblies. This release has a few issues and is generally not recommended for
production uses.
(19 July 2017, r191)
-110
View File
@@ -1,110 +0,0 @@
## Getting Started
```sh
git clone https://github.com/lh3/minimap2
cd minimap2 && make
# long reads against a reference genome
./minimap2 -ax map10k test/MT-human.fa test/MT-orang.fa > test.sam
# create an index first and then map
./minimap2 -x map10k -d MT-human.mmi test/MT-human.fa
./minimap2 -ax map10k MT-human.mmi test/MT-orang.fa > test.sam
# long-read overlap (no test data)
./minimap2 -x ava-pb your-reads.fa your-reads.fa > overlaps.paf
# man page
man ./minimap2.1
```
## Introduction
Minimap2 is a fast sequence mapping and alignment program that can find
overlaps between long noisy reads, or map long reads or their assemblies to a
reference genome optionally with detailed alignment (i.e. CIGAR). At present,
it works efficiently with query sequences from a few kilobases to ~100
megabases in length at an error rate ~15%. Minimap2 outputs in the [PAF][paf] or
the [SAM format][sam]. On limited test data sets, minimap2 is over 20 times
faster than most other long-read aligners. It will replace BWA-MEM for long
reads and contig alignment.
Minimap2 is the successor of [minimap][minimap]. It uses a similar
minimizer-based indexing and seeding algorithm, and improves the original
minimap with homopolyer-compressed k-mers (see also [SMARTdenovo][smartdenovo]
and [longISLND][longislnd]), better chaining and the ability to produce CIGAR
with fast extension alignment (see also [libgaba][gaba] and [ksw2][ksw2]) and
piece-wise affine gap cost.
## Installation
For modern x86-64 CPUs, just type `make` in the source code directory. This
will compile a binary `minimap2` which you can copy to your desired location.
If you see compilation errors, try `make sse2only=1` to disable SSE4. Minimap2
will run a little slower. At present, minimap2 does not work with non-x86 CPUs
or ancient CPUs that do not support SSE2. SSE2 is critical to the performance
of minimap2.
## Algorithm Overview
In the following, minimap2 command line options have a dash ahead and are
highlighted in bold.
1. Read **-I** [=*4G*] reference bases, extract (**-k**,**-w**)-minimizers and
index them in a hash table.
2. Read **-K** [=*200M*] query bases. For each query sequence, do step 3
through 7:
3. For each (**-k**,**-w**)-minimizer on the query, check against the reference
index. If a reference minimizer is not among the top **-f** [=*2e-4*] most
frequent, collect its the occurrences in the reference, which are called
*seeds*.
4. Sort seeds by position in the reference. Chain them with dynamic
programming. Each chain represents a potential mapping. For read
overlapping, report all chains and then go to step 8. For reference mapping,
do step 5 through 7:
5. Let *P* be the set of primary mappings, which is an empty set initially. For
each chain from the best to the worst according to their chaining scores: if
on the query, the chain overlaps with a chain in *P* by **--mask-level**
[=*0.5*] or higher fraction of the shorter chain, mark the chain as
*secondary* to the chain in *P*; otherwise, add the chain to *P*.
6. Retain all primary mappings. Also retain up to **-N** [=*5*] top secondary
mappings if their chaining scores are higher than **-p** [=*0.8*] of their
corresponding primary mappings.
7. If alignment is requested, filter out an internal seed if it potentially
leads to both a long insertion and a long deletion. Extend from the
left-most seed. Perform global alignments between internal seeds. Split the
chain if the accumulative score along the global alignment drops by **-z**
[=*400*], disregarding long gaps. Extend from the right-most seed. Output
chains and their alignments.
8. If there are more query sequences in the input, go to step 2 until no more
queries are left.
9. If there are more reference sequences, reopen the query file from the start
and go to step 1; otherwise stop.
## Limitations
* Minimap2 may produce suboptimal alignments through long low-complexity
regions where seed positions may be suboptimal. This should not be a big
concern because even the optimal alignment may be wrong in such regions.
* Minimap2 does not work well with Illumina short reads as of now.
* Minimap2 requires SSE2 instructions to compile. It is possible to add
non-SSE2 support, but it would make minimap2 slower by 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
[sam]: https://samtools.github.io/hts-specs/SAMv1.pdf
[minimap]: https://github.com/lh3/minimap
[smartdenovo]: https://github.com/ruanjue/smartdenovo
[longislnd]: https://www.ncbi.nlm.nih.gov/pubmed/27667791
[gaba]: https://github.com/ocxtal/libgaba
[ksw2]: https://github.com/lh3/ksw2
+1
View File
@@ -0,0 +1 @@
theme: jekyll-theme-modernist
-454
View File
@@ -1,454 +0,0 @@
#include <assert.h>
#include <string.h>
#include "minimap.h"
#include "mmpriv.h"
#include "ksw2.h"
static void ksw_gen_simple_mat(int m, int8_t *mat, int8_t a, int8_t b)
{
int i, j;
a = a < 0? -a : a;
b = b > 0? -b : b;
for (i = 0; i < m - 1; ++i) {
for (j = 0; j < m - 1; ++j)
mat[i * m + j] = i == j? a : b;
mat[i * m + m - 1] = 0;
}
for (j = 0; j < m; ++j)
mat[(m - 1) * m + j] = 0;
}
static inline void mm_seq_rev(uint32_t len, uint8_t *seq)
{
uint32_t i;
uint8_t t;
for (i = 0; i < len>>1; ++i)
t = seq[i], seq[i] = seq[len - 1 - i], seq[len - 1 - i] = t;
}
static inline int test_zdrop_aux(int32_t score, int i, int j, int32_t *max, int *max_i, int *max_j, int e, int zdrop)
{
if (score < *max) {
int li = i - *max_i;
int lj = j - *max_j;
int diff = li > lj? li - lj : lj - li;
if (*max - score > zdrop + diff * e)
return 1;
} else *max = score, *max_i = i, *max_j = j;
return 0;
}
static int mm_check_zdrop(const uint8_t *qseq, const uint8_t *tseq, uint32_t n_cigar, uint32_t *cigar, const int8_t *mat, int8_t q, int8_t e, int zdrop)
{
uint32_t k;
int32_t score = 0, max = 0, max_i = -1, max_j = -1, i = 0, j = 0;
for (k = 0; k < n_cigar; ++k) {
uint32_t l, op = cigar[k]&0xf, len = cigar[k]>>4;
if (op == 0) {
for (l = 0; l < len; ++l) {
score += mat[tseq[i + l] * 5 + qseq[j + l]];
if (test_zdrop_aux(score, i+l, j+l, &max, &max_i, &max_j, e, zdrop)) return 1;
}
i += len, j += len;
} else if (op == 1) {
score -= q + e * len, j += len;
if (test_zdrop_aux(score, i, j, &max, &max_i, &max_j, e, zdrop)) return 1;
} else if (op == 2) {
score -= q + e * len, i += len;
if (test_zdrop_aux(score, i, j, &max, &max_i, &max_j, e, zdrop)) return 1;
}
}
return 0;
}
static void mm_update_extra(mm_extra_t *p, const uint8_t *qseq, const uint8_t *tseq, const int8_t *mat, int8_t q, int8_t e)
{
uint32_t k, l, toff = 0, qoff = 0;
int32_t s = 0, max = 0;
if (p == 0) return;
for (k = 0; k < p->n_cigar; ++k) {
uint32_t op = p->cigar[k]&0xf, len = p->cigar[k]>>4;
if (op == 0) {
for (l = 0; l < len; ++l) {
int cq = qseq[qoff + l], ct = tseq[toff + l];
if (ct > 3 || cq > 3) ++p->n_ambi;
else if (ct != cq) ++p->n_diff;
s += mat[ct * 5 + cq];
if (s < 0) s = 0;
else max = max > s? max : s;
}
toff += len, qoff += len, p->blen += len;
} else if (op == 1) {
int n_ambi = 0;
for (l = 0; l < len; ++l)
if (qseq[qoff + l] > 3) ++n_ambi;
qoff += len, p->blen += len;
p->n_ambi += n_ambi, p->n_diff += len - n_ambi;
s -= q + e * len;
if (s < 0) s = 0;
} else if (op == 2) {
int n_ambi = 0;
for (l = 0; l < len; ++l)
if (tseq[toff + l] > 3) ++n_ambi;
toff += len, p->blen += len;
p->n_ambi += n_ambi, p->n_diff += len - n_ambi;
s -= q + e * len;
if (s < 0) s = 0;
}
}
p->dp_max = max;
}
static void mm_append_cigar(mm_reg1_t *r, uint32_t n_cigar, uint32_t *cigar) // TODO: this calls the libc realloc()
{
mm_extra_t *p;
if (n_cigar == 0) return;
if (r->p == 0) {
uint32_t capacity = n_cigar + sizeof(mm_extra_t);
kroundup32(capacity);
r->p = (mm_extra_t*)calloc(capacity, 4);
r->p->capacity = capacity;
} else if (r->p->n_cigar + n_cigar + sizeof(mm_extra_t) > r->p->capacity) {
r->p->capacity = r->p->n_cigar + n_cigar + sizeof(mm_extra_t);
kroundup32(r->p->capacity);
r->p = (mm_extra_t*)realloc(r->p, r->p->capacity * 4);
}
p = r->p;
if (p->n_cigar > 0 && (p->cigar[p->n_cigar-1]&0xf) == (cigar[0]&0xf)) { // same CIGAR op at the boundary
p->cigar[p->n_cigar-1] += cigar[0]>>4<<4;
if (n_cigar > 1) memcpy(p->cigar + p->n_cigar, cigar + 1, (n_cigar - 1) * 4);
p->n_cigar += n_cigar - 1;
} else {
memcpy(p->cigar + p->n_cigar, cigar, n_cigar * 4);
p->n_cigar += n_cigar;
}
}
static void mm_align_pair(void *km, const mm_mapopt_t *opt, int qlen, const uint8_t *qseq, int tlen, const uint8_t *tseq, const int8_t *mat, int w, int flag, ksw_extz_t *ez)
{
if (mm_dbg_flag & MM_DBG_PRINT_ALN_SEQ) {
int i;
fprintf(stderr, "===> q=(%d,%d), e=(%d,%d), bw=%d, flag=%d, zdrop=%d <===\n", opt->q, opt->q2, opt->e, opt->e2, w, flag, opt->zdrop);
for (i = 0; i < tlen; ++i) fputc("ACGTN"[tseq[i]], stderr); fputc('\n', stderr);
for (i = 0; i < qlen; ++i) fputc("ACGTN"[qseq[i]], stderr); fputc('\n', stderr);
}
if (opt->q == opt->q2 && opt->e == opt->e2)
ksw_extz2_sse(km, qlen, qseq, tlen, tseq, 5, mat, opt->q, opt->e, w, opt->zdrop, flag, ez);
else
ksw_extd2_sse(km, qlen, qseq, tlen, tseq, 5, mat, opt->q, opt->e, opt->q2, opt->e2, w, opt->zdrop, flag, ez);
}
static inline int mm_get_hplen_back(const mm_idx_t *mi, uint32_t rid, uint32_t x)
{
int64_t i, off0 = mi->seq[rid].offset, off = off0 + x;
int c = mm_seq4_get(mi->S, off);
for (i = off - 1; i >= off0; --i)
if (mm_seq4_get(mi->S, i) != c) break;
return (int)(off - i);
}
static inline void mm_adjust_minier(const mm_idx_t *mi, uint8_t *const qseq0[2], mm128_t *a, int32_t *r, int32_t *q)
{
if (mi->is_hpc) {
const uint8_t *qseq = qseq0[a->x>>63];
int i, c;
*q = (int32_t)a->y;
for (i = *q - 1, c = qseq[*q]; i > 0; --i)
if (qseq[i] != c) break;
*q = i + 1;
c = mm_get_hplen_back(mi, a->x<<1>>33, (int32_t)a->x);
*r = (int32_t)a->x + 1 - c;
} else {
*r = (int32_t)a->x + 1;
*q = (int32_t)a->y + 1;
}
}
static void mm_filter_bad_seeds(void *km, int as1, int cnt1, mm128_t *a, int min_gap, int diff_thres, int max_ext_len, int max_ext_cnt)
{
int max_st, max_en, n, i, k, max, *K;
for (i = 1, n = 0; i < cnt1; ++i) { // count the number of gaps longer than min_gap
int gap = ((int32_t)a[as1 + i].y - a[as1 + i - 1].y) - ((int32_t)a[as1 + i].x - a[as1 + i - 1].x);
if (gap < -min_gap || gap > min_gap) ++n;
}
if (n <= 1) return;
K = (int*)kmalloc(km, n * sizeof(int));
for (i = 1, n = 0; i < cnt1; ++i) { // store the positions of long gaps
int gap = ((int32_t)a[as1 + i].y - a[as1 + i - 1].y) - ((int32_t)a[as1 + i].x - a[as1 + i - 1].x);
if (gap < -min_gap || gap > min_gap)
K[n++] = i;
}
max = 0, max_st = max_en = -1;
for (k = 0;; ++k) { // traverse long gaps
int gap, l, n_ins = 0, n_del = 0, qs, rs, max_diff = 0, max_diff_l = -1;
if (k == n || k >= max_en) {
if (max_en > 0)
for (i = K[max_st]; i < K[max_en]; ++i)
a[as1 + i].y |= MM_SEED_IGNORE;
max = 0, max_st = max_en = -1;
if (k == n) break;
}
i = K[k];
gap = ((int32_t)a[as1 + i].y - a[as1 + i - 1].y) - ((int32_t)a[as1 + i].x - a[as1 + i - 1].x);
if (gap > 0) n_ins += gap;
else n_del += -gap;
qs = (int32_t)a[as1 + i - 1].y;
rs = (int32_t)a[as1 + i - 1].x;
for (l = k + 1; l < n && l <= k + max_ext_cnt; ++l) {
int j = K[l], diff;
if ((int32_t)a[as1 + j].y - qs > max_ext_len || (int32_t)a[as1 + j].x - rs > max_ext_len) break;
gap = ((int32_t)a[as1 + j].y - (int32_t)a[as1 + j - 1].y) - (a[as1 + j].x - a[as1 + j - 1].x);
if (gap > 0) n_ins += gap;
else n_del += -gap;
diff = n_ins + n_del - abs(n_ins - n_del);
if (max_diff < diff)
max_diff = diff, max_diff_l = l;
}
if (max_diff > diff_thres && max_diff > max)
max = max_diff, max_st = k, max_en = max_diff_l;
}
kfree(km, K);
}
static void mm_fix_bad_ends(const mm_reg1_t *r, const mm128_t *a, int bw, int32_t *as, int32_t *cnt)
{
int32_t i, l;
*as = r->as, *cnt = r->cnt;
if (r->cnt < 3) return;
l = a[r->as].y >> 32 & 0xff;
for (i = r->as + 1; i < r->as + r->cnt - 1; ++i) {
int32_t lq, lr, min, max;
lr = (int32_t)a[i].x - (int32_t)a[i-1].x;
lq = (int32_t)a[i].y - (int32_t)a[i-1].y;
min = lr < lq? lr : lq;
max = lr > lq? lr : lq;
if (max - min > l >> 1) *as = i;
l += min;
if (l >= bw << 1) break;
}
*cnt = r->as + r->cnt - *as;
l = a[r->as + r->cnt - 1].y >> 32 & 0xff;
for (i = r->as + r->cnt - 2; i > *as; --i) {
int32_t lq, lr, min, max;
lr = (int32_t)a[i+1].x - (int32_t)a[i].x;
lq = (int32_t)a[i+1].y - (int32_t)a[i].y;
min = lr < lq? lr : lq;
max = lr > lq? lr : lq;
if (max - min > l >> 1) *cnt = i + 1 - *as;
l += min;
if (l >= bw) break;
}
}
static void mm_align1(void *km, const mm_mapopt_t *opt, const mm_idx_t *mi, int qlen, uint8_t *qseq0[2], mm_reg1_t *r, mm_reg1_t *r2, mm128_t *a, ksw_extz_t *ez)
{
int32_t rid = a[r->as].x<<1>>33, rev = a[r->as].x>>63, as1, cnt1;
uint8_t *tseq, *qseq;
int32_t i, l, bw, dropped = 0, rs0, re0, qs0, qe0;
int32_t rs, re, qs, qe;
int32_t rs1, qs1, re1, qe1;
int8_t mat[25];
if (r->cnt == 0) return;
ksw_gen_simple_mat(5, mat, opt->a, opt->b);
bw = (int)(opt->bw * 1.5 + 1.);
r2->cnt = 0;
mm_fix_bad_ends(r, a, opt->bw, &as1, &cnt1);
mm_filter_bad_seeds(km, as1, cnt1, a, 10, 40, opt->max_gap>>1, 10);
mm_adjust_minier(mi, qseq0, &a[as1], &rs, &qs);
mm_adjust_minier(mi, qseq0, &a[as1 + cnt1 - 1], &re, &qe);
// compute rs0 and qs0
if (r->split && as1 > 0) {
mm_adjust_minier(mi, qseq0, &a[as1-1], &rs0, &qs0);
} else {
if (qs > 0 && rs > 0) { // actually this is always true
l = qs < opt->max_gap? qs : opt->max_gap;
qs0 = qs - l;
l += l * opt->a > opt->q? (l * opt->a - opt->q) / opt->e : 0;
l = l < opt->max_gap? l : opt->max_gap;
l = l < rs? l : rs;
rs0 = rs - l;
} else rs0 = rs, qs0 = qs;
}
// compute re0 and qe0
if (qe < qlen && re < mi->seq[rid].len) {
l = qlen - qe < opt->max_gap? qlen - qe : opt->max_gap;
qe0 = qe + l;
l += l * opt->a > opt->q? (l * opt->a - opt->q) / opt->e : 0;
l = l < opt->max_gap? l : opt->max_gap;
l = l < mi->seq[rid].len - re? l : mi->seq[rid].len - re;
re0 = re + l;
} else re0 = re, qe0 = qe;
assert(re0 > rs0);
tseq = (uint8_t*)kmalloc(km, re0 - rs0);
if (qs > 0 && rs > 0) { // left extension
qseq = &qseq0[rev][qs0];
mm_idx_getseq(mi, rid, rs0, rs, tseq);
mm_seq_rev(qs - qs0, qseq);
mm_seq_rev(rs - rs0, tseq);
mm_align_pair(km, opt, qs - qs0, qseq, rs - rs0, tseq, mat, bw, KSW_EZ_EXTZ_ONLY|KSW_EZ_RIGHT|KSW_EZ_REV_CIGAR, ez);
if (ez->n_cigar > 0) {
mm_append_cigar(r, ez->n_cigar, ez->cigar);
r->p->dp_score += ez->max;
}
rs1 = rs - (ez->max_t + 1);
qs1 = qs - (ez->max_q + 1);
mm_seq_rev(qs - qs0, qseq);
} else rs1 = rs, qs1 = qs;
re1 = rs, qe1 = qs;
assert(qs1 >= 0 && rs1 >= 0);
for (i = 1; i < cnt1; ++i) { // gap filling
if ((a[as1+i].y & (MM_SEED_IGNORE|MM_SEED_TANDEM)) && i != cnt1 - 1) continue;
mm_adjust_minier(mi, qseq0, &a[as1 + i], &re, &qe);
re1 = re, qe1 = qe;
if (i == cnt1 - 1 || (a[as1+i].y&MM_SEED_LONG_JOIN) || (qe - qs >= opt->min_ksw_len && re - rs >= opt->min_ksw_len)) {
int bw1 = bw;
if (a[as1+i].y & MM_SEED_LONG_JOIN)
bw1 = qe - qs > re - rs? qe - qs : re - rs;
qseq = &qseq0[rev][qs];
mm_idx_getseq(mi, rid, rs, re, tseq);
mm_align_pair(km, opt, qe - qs, qseq, re - rs, tseq, mat, bw1, KSW_EZ_APPROX_MAX, ez);
if (mm_check_zdrop(qseq, tseq, ez->n_cigar, ez->cigar, mat, opt->q, opt->e, opt->zdrop))
mm_align_pair(km, opt, qe - qs, qseq, re - rs, tseq, mat, bw1, 0, ez);
if (ez->n_cigar > 0)
mm_append_cigar(r, ez->n_cigar, ez->cigar);
if (ez->zdropped) { // truncated by Z-drop; TODO: sometimes Z-drop kicks in because the next seed placement is wrong. This can be fixed in principle.
int j;
for (j = i - 1; j >= 0; --j)
if ((int32_t)a[as1 + j].x < re + ez->max_t)
break;
dropped = 1;
r->p->dp_score += ez->max;
re1 = rs + (ez->max_t + 1);
qe1 = qs + (ez->max_q + 1);
if (cnt1 - (j + 1) >= opt->min_cnt)
mm_split_reg(r, r2, j + 1, qlen, a);
break;
} else r->p->dp_score += ez->score;
rs = re, qs = qe;
}
}
if (!dropped && qe < qe0 && re < re0) { // right extension
qseq = &qseq0[rev][qe];
mm_idx_getseq(mi, rid, re, re0, tseq);
mm_align_pair(km, opt, qe0 - qe, qseq, re0 - re, tseq, mat, bw, KSW_EZ_EXTZ_ONLY, ez);
if (ez->n_cigar > 0) {
mm_append_cigar(r, ez->n_cigar, ez->cigar);
r->p->dp_score += ez->max;
}
re1 = re + (ez->max_t + 1);
qe1 = qe + (ez->max_q + 1);
}
assert(qe1 <= qlen);
r->rs = rs1, r->re = re1;
if (rev) r->qs = qlen - qe1, r->qe = qlen - qs1;
else r->qs = qs1, r->qe = qe1;
assert(re1 - rs1 <= re0 - rs0);
if (r->p) {
mm_idx_getseq(mi, rid, rs1, re1, tseq);
mm_update_extra(r->p, &qseq0[r->rev][qs1], tseq, mat, opt->q, opt->e);
}
kfree(km, tseq);
}
static int mm_align1_inv(void *km, const mm_mapopt_t *opt, const mm_idx_t *mi, int qlen, uint8_t *qseq0[2], const mm_reg1_t *r1, const mm_reg1_t *r2, mm_reg1_t *r_inv, ksw_extz_t *ez)
{
int tl, ql, score, ret = 0, q_off, t_off;
uint8_t *tseq, *qseq;
int8_t mat[25];
void *qp;
memset(r_inv, 0, sizeof(mm_reg1_t));
if (!(r1->split&1) || !(r2->split&2)) return 0;
if (r1->id != r1->parent && r1->parent != MM_PARENT_TMP_PRI) return 0;
if (r2->id != r2->parent && r2->parent != MM_PARENT_TMP_PRI) return 0;
if (r1->rid != r2->rid || r1->rev != r2->rev) return 0;
ql = r2->qs - r1->qe;
tl = r2->rs - r1->re;
if (ql < opt->min_chain_score || ql > opt->max_gap) return 0;
if (tl < opt->min_chain_score || tl > opt->max_gap) return 0;
ksw_gen_simple_mat(5, mat, opt->a, opt->b);
tseq = (uint8_t*)kmalloc(km, tl);
mm_idx_getseq(mi, r1->rid, r1->re, r2->rs, tseq);
qseq = &qseq0[!r1->rev][qlen - r2->qs];
mm_seq_rev(ql, qseq);
mm_seq_rev(tl, tseq);
qp = ksw_ll_qinit(km, 2, ql, qseq, 5, mat);
score = ksw_ll_i16(qp, tl, tseq, opt->q, opt->e, &q_off, &t_off);
kfree(km, qp);
mm_seq_rev(ql, qseq);
mm_seq_rev(tl, tseq);
if (score < opt->min_dp_max) goto end_align1_inv;
q_off = ql - (q_off + 1), t_off = tl - (t_off + 1);
mm_align_pair(km, opt, ql - q_off, qseq + q_off, tl - t_off, tseq + t_off, mat, (int)(opt->bw * 1.5), KSW_EZ_EXTZ_ONLY, ez);
if (ez->n_cigar == 0) goto end_align1_inv; // should never be here
mm_append_cigar(r_inv, ez->n_cigar, ez->cigar);
r_inv->p->dp_score = ez->max;
mm_update_extra(r_inv->p, qseq + q_off, tseq + t_off, mat, opt->q, opt->e);
r_inv->id = -1;
r_inv->parent = MM_PARENT_UNSET;
r_inv->inv = 1;
r_inv->rev = !r1->rev;
r_inv->qs = r1->qe + q_off, r_inv->qe = r_inv->qs + ez->max_q + 1;
r_inv->rs = r1->re + t_off, r_inv->re = r_inv->rs + ez->max_t + 1;
ret = 1;
end_align1_inv:
kfree(km, tseq);
return ret;
}
static inline mm_reg1_t *mm_insert_reg(const mm_reg1_t *r, int i, int *n_regs, mm_reg1_t *regs)
{
regs = (mm_reg1_t*)realloc(regs, (*n_regs + 1) * sizeof(mm_reg1_t));
if (i + 1 != *n_regs)
memmove(&regs[i + 2], &regs[i + 1], sizeof(mm_reg1_t) * (*n_regs - i - 1));
regs[i + 1] = *r;
++*n_regs;
return regs;
}
mm_reg1_t *mm_align_skeleton(void *km, const mm_mapopt_t *opt, const mm_idx_t *mi, int qlen, const char *qstr, int *n_regs_, mm_reg1_t *regs, mm128_t *a)
{
extern unsigned char seq_nt4_table[256];
int32_t i, n_regs = *n_regs_;
uint8_t *qseq0[2];
ksw_extz_t ez;
// encode the query sequence
qseq0[0] = (uint8_t*)kmalloc(km, qlen);
qseq0[1] = (uint8_t*)kmalloc(km, qlen);
for (i = 0; i < qlen; ++i) {
qseq0[0][i] = seq_nt4_table[(uint8_t)qstr[i]];
qseq0[1][qlen - 1 - i] = qseq0[0][i] < 4? 3 - qseq0[0][i] : 4;
}
// align through seed hits
memset(&ez, 0, sizeof(ksw_extz_t));
for (i = 0; i < n_regs; ++i) {
mm_reg1_t r2;
mm_align1(km, opt, mi, qlen, qseq0, &regs[i], &r2, a, &ez);
if (r2.cnt > 0) regs = mm_insert_reg(&r2, i, &n_regs, regs);
if (i > 0 && mm_align1_inv(km, opt, mi, qlen, qseq0, &regs[i-1], &regs[i], &r2, &ez)) {
regs = mm_insert_reg(&r2, i, &n_regs, regs);
++i; // skip the inserted INV alignment
}
}
*n_regs_ = n_regs;
kfree(km, qseq0[0]); kfree(km, qseq0[1]);
kfree(km, ez.cigar);
mm_filter_regs(km, opt, n_regs_, regs);
mm_hit_sort_by_dp(km, n_regs_, regs);
return regs;
}
-64
View File
@@ -1,64 +0,0 @@
#include <zlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "bseq.h"
#include "kseq.h"
KSEQ_INIT(gzFile, gzread)
struct mm_bseq_file_s {
int is_eof;
gzFile fp;
kseq_t *ks;
};
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");
if (f == 0) return 0;
fp = (mm_bseq_file_t*)calloc(1, sizeof(mm_bseq_file_t));
fp->fp = f;
fp->ks = kseq_init(fp->fp);
return fp;
}
void mm_bseq_close(mm_bseq_file_t *fp)
{
kseq_destroy(fp->ks);
gzclose(fp->fp);
free(fp);
}
mm_bseq1_t *mm_bseq_read(mm_bseq_file_t *fp, int chunk_size, int with_qual, int *n_)
{
int size = 0, m, n;
mm_bseq1_t *seqs;
kseq_t *ks = fp->ks;
m = n = 0; seqs = 0;
while (kseq_read(ks) >= 0) {
mm_bseq1_t *s;
assert(ks->seq.l <= INT32_MAX);
if (n >= m) {
m = m? m<<1 : 256;
seqs = (mm_bseq1_t*)realloc(seqs, m * sizeof(mm_bseq1_t));
}
s = &seqs[n];
s->name = strdup(ks->name.s);
s->seq = strdup(ks->seq.s);
s->qual = with_qual && ks->qual.l? strdup(ks->qual.s) : 0;
s->l_seq = ks->seq.l;
size += seqs[n++].l_seq;
if (size >= chunk_size) break;
}
if (size < chunk_size) fp->is_eof = 1;
*n_ = n;
return seqs;
}
int mm_bseq_eof(mm_bseq_file_t *fp)
{
return fp->is_eof;
}
-29
View File
@@ -1,29 +0,0 @@
#ifndef MM_BSEQ_H
#define MM_BSEQ_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct mm_bseq_file_s;
typedef struct mm_bseq_file_s mm_bseq_file_t;
typedef struct {
int l_seq, rid;
char *name, *seq, *qual;
} mm_bseq1_t;
mm_bseq_file_t *mm_bseq_open(const char *fn);
void mm_bseq_close(mm_bseq_file_t *fp);
mm_bseq1_t *mm_bseq_read(mm_bseq_file_t *fp, int chunk_size, int with_qual, int *n_);
int mm_bseq_eof(mm_bseq_file_t *fp);
extern unsigned char seq_nt4_table[256];
#ifdef __cplusplus
}
#endif
#endif
-143
View File
@@ -1,143 +0,0 @@
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "minimap.h"
#include "mmpriv.h"
#include "kalloc.h"
static const char LogTable256[256] = {
#define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
};
static inline int ilog2_32(uint32_t v)
{
register uint32_t t, tt;
if ((tt = v>>16)) return (t = tt>>8) ? 24 + LogTable256[t] : 16 + LogTable256[tt];
return (t = v>>8) ? 8 + LogTable256[t] : LogTable256[v];
}
int mm_chain_dp(int max_dist, int bw, int max_skip, int min_cnt, int min_sc, int64_t n, mm128_t *a, uint64_t **_u, void *km)
{ // TODO: make sure this works when n has more than 32 bits
int32_t st = 0, k, *f, *p, *t, *v, n_u, n_v;
int64_t i, j;
uint64_t *u, *u2, sum_qspan = 0;
float avg_qspan;
mm128_t *b, *w;
if (_u) *_u = 0;
f = (int32_t*)kmalloc(km, n * 4);
p = (int32_t*)kmalloc(km, n * 4);
t = (int32_t*)kmalloc(km, n * 4);
v = (int32_t*)kmalloc(km, n * 4);
memset(t, 0, n * 4);
for (i = 0; i < n; ++i) sum_qspan += a[i].y>>32&0xff;
avg_qspan = (float)sum_qspan / n;
// fill the score and backtrack arrays
for (i = 0; i < n; ++i) {
uint64_t ri = a[i].x;
int32_t qi = (int32_t)a[i].y, q_span = a[i].y>>32&0xff; // NB: only 8 bits of span is used!!!
int32_t max_f = q_span, max_j = -1, n_skip = 0, min_d, max_f_past = -INT32_MAX;
while (st < i && ri - a[st].x > max_dist) ++st;
for (j = i - 1; j >= st; --j) {
int64_t dr = ri - a[j].x;
int32_t dq = qi - (int32_t)a[j].y, dd, sc;
if (dr == 0 || dq <= 0 || dq > max_dist) continue;
dd = dr > dq? dr - dq : dq - dr;
if (dd > bw) continue;
max_f_past = max_f_past > f[j]? max_f_past : f[j];
min_d = dq < dr? dq : dr;
sc = min_d > q_span? q_span : dq < dr? dq : dr;
sc -= (int)(dd * .01 * avg_qspan) + (ilog2_32(dd)>>1);
sc += f[j];
if (sc > max_f) {
max_f = sc, max_j = j;
if (n_skip > 0) --n_skip;
} else if (t[j] == i) {
if (++n_skip > max_skip)
break;
}
if (p[j] >= 0) t[p[j]] = i;
}
f[i] = max_f, p[i] = max_j, v[i] = max_f_past; // v[] keeps the max score in the previous chain
}
// find the ending positions of chains
memset(t, 0, n * 4);
for (i = 0; i < n; ++i)
if (p[i] >= 0) t[p[i]] = 1;
for (i = n_u = 0; i < n; ++i)
if (t[i] == 0 && v[i] >= min_sc)
++n_u;
if (n_u == 0) {
kfree(km, f); kfree(km, p); kfree(km, t); kfree(km, v);
return 0;
}
u = (uint64_t*)kmalloc(km, n_u * 8);
for (i = n_u = 0; i < n; ++i) {
if (t[i] == 0 && v[i] >= min_sc) {
j = i;
while (j >= 0 && f[j] < v[j]) j = p[j]; // find the point that maximizes f[]
if (j < 0) j = i; // TODO: this should really be assert(j>=0)
u[n_u++] = (uint64_t)f[j] << 32 | j;
}
}
radix_sort_64(u, u + n_u);
for (i = 0; i < n_u>>1; ++i) { // reverse, s.t. the highest scoring chain is the first
uint64_t t = u[i];
u[i] = u[n_u - i - 1], u[n_u - i - 1] = t;
}
// backtrack
memset(t, 0, n * 4);
for (i = n_v = k = 0; i < n_u; ++i) { // starting from the highest score
int32_t n_v0 = n_v, k0 = k;
j = (int32_t)u[i];
do {
v[n_v++] = j;
t[j] = 1;
j = p[j];
} while (j >= 0 && t[j] == 0);
if (j < 0) {
if (n_v - n_v0 >= min_cnt) u[k++] = u[i]>>32<<32 | (n_v - n_v0);
} else if ((int32_t)(u[i]>>32) - f[j] >= min_sc) {
if (n_v - n_v0 >= min_cnt) u[k++] = ((u[i]>>32) - f[j]) << 32 | (n_v - n_v0);
}
if (k0 == k) n_v = n_v0; // no new chain added, reset
}
n_u = k, *_u = u; // NB: note that u[] may not be sorted by score here
// free
kfree(km, f); kfree(km, p); kfree(km, t);
// write the result to b[]
b = (mm128_t*)kmalloc(km, n_v * sizeof(mm128_t));
for (i = 0, k = 0; i < n_u; ++i) {
int32_t k0 = k, ni = (int32_t)u[i];
for (j = 0; j < ni; ++j)
b[k] = a[v[k0 + (ni - j - 1)]], ++k;
}
kfree(km, v);
// sort u[] and a[] by a[].x, such that adjacent chains may be joined (required by mm_join_long)
w = (mm128_t*)kmalloc(km, n_u * sizeof(mm128_t));
for (i = k = 0; i < n_u; ++i) {
w[i].x = b[k].x, w[i].y = (uint64_t)k<<32|i;
k += (int32_t)u[i];
}
radix_sort_128x(w, w + n_u);
u2 = (uint64_t*)kmalloc(km, n_u * 8);
for (i = k = 0; i < n_u; ++i) {
int32_t j = (int32_t)w[i].y, n = (int32_t)u[j];
u2[i] = u[j];
memcpy(&a[k], &b[w[i].y>>32], n * sizeof(mm128_t));
k += n;
}
memcpy(u, u2, n_u * 8);
kfree(km, b); kfree(km, w); kfree(km, u2);
return n_u;
}
-61
View File
@@ -1,61 +0,0 @@
// To compile:
// gcc -g -O2 example.c libminimap2.a -lz
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <zlib.h>
#include "minimap.h"
#include "kseq.h"
KSEQ_INIT(gzFile, gzread)
int main(int argc, char *argv[])
{
mm_verbose = 2; // disable message output to stderr
if (argc < 3) {
fprintf(stderr, "Usage: minimap2-lite <target.fa> <query.fa>\n");
return 1;
}
// open query file for reading; you may use your favorite FASTA/Q parser
gzFile f = gzopen(argv[2], "r");
assert(f);
kseq_t *ks = kseq_init(f);
// create index for target; we are creating one index for all target sequence
int n_threads = 4, w = 10, k = 15, is_hpc = 0;
mm_idx_t *mi = mm_idx_build(argv[1], w, k, is_hpc, n_threads);
assert(mi);
// mapping
mm_mapopt_t opt;
mm_mapopt_init(&opt); // initialize mapping parameters
mm_mapopt_update(&opt, mi); // this sets the maximum minimizer occurrence; TODO: set a better default in mm_mapopt_init()!
opt.flag |= MM_F_CIGAR; // perform alignment
mm_tbuf_t *tbuf = mm_tbuf_init(); // thread buffer; for multi-threading, allocate one tbuf for each thread
while (kseq_read(ks) >= 0) { // each kseq_read() call reads one query sequence
const mm_reg1_t *reg;
int j, i, n_reg;
// get all hits for the query
reg = mm_map(mi, ks->seq.l, ks->seq.s, &n_reg, tbuf, &opt, 0);
// traverse hits and print them out
for (j = 0; j < n_reg; ++j) {
const mm_reg1_t *r = &reg[j];
assert(r->p); // with MM_F_CIGAR, this should not be NULL
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->p->blen - r->p->n_ambi - r->p->n_diff, r->p->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!
printf("%d%c", r->p->cigar[i]>>4, "MIDSHN"[r->p->cigar[i]&0xf]);
putchar('\n');
}
}
mm_tbuf_destroy(tbuf);
// deallocate index and close the query file
mm_idx_destroy(mi);
kseq_destroy(ks);
gzclose(f);
return 0;
}
-175
View File
@@ -1,175 +0,0 @@
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "mmpriv.h"
static inline void str_enlarge(kstring_t *s, int l)
{
if (s->l + l + 1 > s->m) {
s->m = s->l + l + 1;
kroundup32(s->m);
s->s = (char*)realloc(s->s, s->m);
}
}
static inline void str_copy(kstring_t *s, const char *st, const char *en)
{
str_enlarge(s, en - st);
memcpy(&s->s[s->l], st, en - st);
s->l += en - st;
}
static void mm_sprintf_lite(kstring_t *s, const char *fmt, ...)
{
char buf[16]; // for integer to string conversion
const char *p, *q;
va_list ap;
va_start(ap, fmt);
for (q = p = fmt; *p; ++p) {
if (*p == '%') {
if (p > q) str_copy(s, q, p);
++p;
if (*p == 'd') {
int c, i, l = 0;
unsigned int x;
c = va_arg(ap, int);
x = c >= 0? c : -c;
do { buf[l++] = x%10 + '0'; x /= 10; } while (x > 0);
if (c < 0) buf[l++] = '-';
str_enlarge(s, l);
for (i = l - 1; i >= 0; --i) s->s[s->l++] = buf[i];
} else if (*p == 's') {
char *r = va_arg(ap, char*);
str_copy(s, r, r + strlen(r));
} else if (*p == 'c') {
str_enlarge(s, 1);
s->s[s->l++] = va_arg(ap, int);
} else abort();
q = p + 1;
}
}
if (p > q) str_copy(s, q, p);
va_end(ap);
s->s[s->l] = 0;
}
static inline void write_tags(kstring_t *s, const mm_reg1_t *r)
{
int type = r->inv? 'I' : r->id == r->parent? 'P' : 'S';
mm_sprintf_lite(s, "\ttp:A:%c\tcm:i:%d\ts1:i:%d", type, r->cnt, r->score);
if (r->parent == r->id) mm_sprintf_lite(s, "\ts2:i:%d", r->subsc);
if (r->split) mm_sprintf_lite(s, "\tzd:i:%d", r->split);
if (r->p) mm_sprintf_lite(s, "\tNM:i:%d\tms:i:%d\tAS:i:%d\tnn:i:%d", r->p->n_diff, r->p->dp_max, r->p->dp_score, r->p->n_ambi);
}
void mm_write_paf(kstring_t *s, const mm_idx_t *mi, const mm_bseq1_t *t, const mm_reg1_t *r)
{
s->l = 0;
mm_sprintf_lite(s, "%s\t%d\t%d\t%d\t%c\t", t->name, t->l_seq, r->qs, r->qe, "+-"[r->rev]);
if (mi->seq[r->rid].name) mm_sprintf_lite(s, "%s", mi->seq[r->rid].name);
else mm_sprintf_lite(s, "%d", r->rid);
mm_sprintf_lite(s, "\t%d\t%d\t%d", mi->seq[r->rid].len, r->rs, r->re);
if (r->p) mm_sprintf_lite(s, "\t%d\t%d", r->p->blen - r->p->n_ambi - r->p->n_diff, r->p->blen);
else mm_sprintf_lite(s, "\t%d\t%d", r->fuzzy_mlen, r->fuzzy_blen);
mm_sprintf_lite(s, "\t%d", r->mapq);
write_tags(s, r);
if (r->p) {
uint32_t k;
mm_sprintf_lite(s, "\tcg:Z:");
for (k = 0; k < r->p->n_cigar; ++k)
mm_sprintf_lite(s, "%d%c", r->p->cigar[k]>>4, "MID"[r->p->cigar[k]&0xf]);
}
}
static char comp_tab[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 'T', 'V', 'G', 'H', 'E', 'F', 'C', 'D', 'I', 'J', 'M', 'L', 'K', 'N', 'O',
'P', 'Q', 'Y', 'S', 'A', 'A', 'B', 'W', 'X', 'R', 'Z', 91, 92, 93, 94, 95,
64, 't', 'v', 'g', 'h', 'e', 'f', 'c', 'd', 'i', 'j', 'm', 'l', 'k', 'n', 'o',
'p', 'q', 'y', 's', 'a', 'a', 'b', 'w', 'x', 'r', 'z', 123, 124, 125, 126, 127
};
static void sam_write_sq(kstring_t *s, char *seq, int l, int rev, int comp)
{
if (rev) {
int i;
str_enlarge(s, l);
for (i = 0; i < l; ++i) {
int c = seq[l - 1 - i];
s->s[s->l + i] = c < 128 && comp? comp_tab[c] : c;
}
s->l += l;
} else str_copy(s, seq, seq + l);
}
void mm_write_sam(kstring_t *s, const mm_idx_t *mi, const mm_bseq1_t *t, const mm_reg1_t *r, int n_regs, const mm_reg1_t *regs)
{
int flag = 0;
s->l = 0;
if (r == 0) {
mm_sprintf_lite(s, "%s\t4\t*\t0\t0\t*\t*\t0\t0\t", t->name);
sam_write_sq(s, t->seq, t->l_seq, 0, 0);
mm_sprintf_lite(s, "\t");
if (t->qual) sam_write_sq(s, t->qual, t->l_seq, 0, 0);
else mm_sprintf_lite(s, "*");
} else {
if (r->rev) flag |= 0x10;
if (r->parent != r->id) flag |= 0x100;
else if (!r->sam_pri) flag |= 0x800;
mm_sprintf_lite(s, "%s\t%d\t%s\t%d\t%d\t", t->name, flag, mi->seq[r->rid].name, r->rs+1, r->mapq);
if (r->p) { // actually this should always be true for SAM output
uint32_t k, clip_len = r->rev? t->l_seq - r->qe : r->qs;
int clip_char = (flag&0x800)? 'H' : 'S';
if (clip_len) mm_sprintf_lite(s, "%d%c", clip_len, clip_char);
for (k = 0; k < r->p->n_cigar; ++k)
mm_sprintf_lite(s, "%d%c", r->p->cigar[k]>>4, "MID"[r->p->cigar[k]&0xf]);
clip_len = r->rev? r->qs : t->l_seq - r->qe;
if (clip_len) mm_sprintf_lite(s, "%d%c", clip_len, clip_char);
} else mm_sprintf_lite(s, "*");
mm_sprintf_lite(s, "\t*\t0\t0\t");
if ((flag & 0x900) == 0) {
sam_write_sq(s, t->seq, t->l_seq, r->rev, r->rev);
mm_sprintf_lite(s, "\t");
if (t->qual) sam_write_sq(s, t->qual, t->l_seq, r->rev, 0);
else mm_sprintf_lite(s, "*");
} else if (flag & 0x100) {
mm_sprintf_lite(s, "*\t*");
} else {
sam_write_sq(s, t->seq + r->qs, r->qe - r->qs, r->rev, r->rev);
mm_sprintf_lite(s, "\t");
if (t->qual) sam_write_sq(s, t->qual + r->qs, r->qe - r->qs, r->rev, 0);
else mm_sprintf_lite(s, "*");
}
write_tags(s, r);
if (r->parent == r->id && r->p && n_regs > 1 && regs && r >= regs && r - regs < n_regs) { // supplementary aln may exist
int i, n_sa = 0; // n_sa: number of SA fields
for (i = 0; i < n_regs; ++i)
if (i != r - regs && regs[i].parent == regs[i].id && regs[i].p)
++n_sa;
if (n_sa > 0) {
mm_sprintf_lite(s, "\tSA:Z:");
for (i = 0; i < n_regs; ++i) {
const mm_reg1_t *q = &regs[i];
int l_M, l_I = 0, l_D = 0, clip5 = 0, clip3 = 0;
if (r == q || q->parent != q->id || q->p == 0) continue;
if (q->qe - q->qs < q->re - q->rs) l_M = q->qe - q->qs, l_D = (q->re - q->rs) - l_M;
else l_M = q->re - q->rs, l_I = (q->qe - q->qs) - l_M;
clip5 = q->rev? t->l_seq - q->qe : q->qs;
clip3 = q->rev? q->qs : t->l_seq - q->qe;
mm_sprintf_lite(s, "%s,%d,%c,", mi->seq[q->rid].name, q->rs+1, "+-"[q->rev]);
if (clip5) mm_sprintf_lite(s, "%dS", clip5);
if (l_M) mm_sprintf_lite(s, "%dM", l_M);
if (l_I) mm_sprintf_lite(s, "%dI", l_I);
if (l_D) mm_sprintf_lite(s, "%dD", l_D);
if (clip3) mm_sprintf_lite(s, "%dS", clip3);
mm_sprintf_lite(s, ",%d,%d;", q->mapq, q->p->n_diff);
}
}
}
}
s->s[s->l] = 0; // we always have room for an extra byte (see str_enlarge)
}
-311
View File
@@ -1,311 +0,0 @@
#include <string.h>
#include <math.h>
#include "mmpriv.h"
#include "kalloc.h"
static inline void mm_cal_fuzzy_len(mm_reg1_t *r, const mm128_t *a)
{
int i;
r->fuzzy_mlen = r->fuzzy_blen = 0;
if (r->cnt <= 0) return;
r->fuzzy_mlen = r->fuzzy_blen = a[r->as].y>>32&0xff;
for (i = r->as + 1; i < r->as + r->cnt; ++i) {
int span = a[i].y>>32&0xff;
int tl = (int32_t)a[i].x - (int32_t)a[i-1].x;
int ql = (int32_t)a[i].y - (int32_t)a[i-1].y;
r->fuzzy_blen += tl > ql? tl : ql;
r->fuzzy_mlen += tl > span && ql > span? span : tl < ql? tl : ql;
}
}
static inline void mm_reg_set_coor(mm_reg1_t *r, int32_t qlen, const mm128_t *a)
{ // NB: r->as and r->cnt MUST BE set correctly for this function to work
int32_t k = r->as, q_span = (int32_t)(a[k].y>>32&0xff);
r->rev = a[k].x>>63;
r->rid = a[k].x<<1>>33;
r->rs = (int32_t)a[k].x + 1 > q_span? (int32_t)a[k].x + 1 - q_span : 0; // NB: target span may be shorter, so this test is necessary
r->re = (int32_t)a[k + r->cnt - 1].x + 1;
if (!r->rev) {
r->qs = (int32_t)a[k].y + 1 - q_span;
r->qe = (int32_t)a[k + r->cnt - 1].y + 1;
} else {
r->qs = qlen - ((int32_t)a[k + r->cnt - 1].y + 1);
r->qe = qlen - ((int32_t)a[k].y + 1 - q_span);
}
mm_cal_fuzzy_len(r, a);
}
mm_reg1_t *mm_gen_regs(void *km, int qlen, int n_u, uint64_t *u, mm128_t *a) // convert chains to hits
{
mm128_t *z, tmp;
mm_reg1_t *r;
int i, k;
if (n_u == 0) return 0;
// sort by score
z = (mm128_t*)kmalloc(km, n_u * 16);
for (i = k = 0; i < n_u; ++i) {
z[i].x = u[i] >> 32;
z[i].y = (uint64_t)k << 32 | (int32_t)u[i];
k += (int32_t)u[i];
}
radix_sort_128x(z, z + n_u);
for (i = 0; i < n_u>>1; ++i) // reverse, s.t. larger score first
tmp = z[i], z[i] = z[n_u-1-i], z[n_u-1-i] = tmp;
// populate r[]
r = (mm_reg1_t*)calloc(n_u, sizeof(mm_reg1_t));
for (i = 0; i < n_u; ++i) {
mm_reg1_t *ri = &r[i];
ri->id = i;
ri->parent = MM_PARENT_UNSET;
ri->score = z[i].x;
ri->cnt = (int32_t)z[i].y;
ri->as = z[i].y >> 32;
mm_reg_set_coor(ri, qlen, a);
}
kfree(km, z);
return r;
}
void mm_split_reg(mm_reg1_t *r, mm_reg1_t *r2, int n, int qlen, mm128_t *a)
{
if (n <= 0 || n >= r->cnt) return;
*r2 = *r;
r2->id = -1;
r2->sam_pri = 0;
r2->p = 0;
r2->cnt = r->cnt - n;
r2->score = (int32_t)(r->score * ((float)r2->cnt / r->cnt) + .499);
r2->as = r->as + n;
if (r->parent == r->id) r2->parent = MM_PARENT_TMP_PRI;
mm_reg_set_coor(r2, qlen, a);
r->cnt -= r2->cnt;
r->score -= r2->score;
mm_reg_set_coor(r, qlen, a);
r->split |= 1, r2->split |= 2;
}
void mm_set_parent(void *km, float mask_level, int n, mm_reg1_t *r) // and compute mm_reg1_t::subsc
{
int i, j, k, *w;
if (n <= 0) return;
for (i = 0; i < n; ++i) r[i].id = i;
w = (int*)kmalloc(km, n * sizeof(int));
w[0] = 0, r[0].parent = 0;
for (i = 1, k = 1; i < n; ++i) {
mm_reg1_t *ri = &r[i];
int si = ri->qs, ei = ri->qe;
for (j = 0; j < k; ++j) {
mm_reg1_t *rp = &r[w[j]];
int sj = rp->qs, ej = rp->qe;
int min = ej - sj < ei - si? ej - sj : ei - si;
int ol = si < sj? (ei < sj? 0 : ei < ej? ei - sj : ej - sj) : (ej < si? 0 : ej < ei? ej - si : ei - si);
if (ol > mask_level * min) {
ri->parent = rp->parent;
rp->subsc = rp->subsc > ri->score? rp->subsc : ri->score;
if (rp->p && ri->p)
rp->p->dp_max2 = rp->p->dp_max2 > ri->p->dp_max? rp->p->dp_max2 : ri->p->dp_max;
break;
}
}
if (j == k) w[k++] = i, ri->parent = i;
}
kfree(km, w);
}
void mm_hit_sort_by_dp(void *km, int *n_regs, mm_reg1_t *r)
{
int32_t i, n_aux, n = *n_regs;
uint64_t *aux;
mm_reg1_t *t;
if (n <= 1) return;
aux = (uint64_t*)kmalloc(km, n * 8);
t = (mm_reg1_t*)kmalloc(km, n * sizeof(mm_reg1_t));
for (i = n_aux = 0; i < n; ++i) {
if (r[i].inv || r[i].cnt > 0) { // squeeze out elements with cnt==0 (soft deleted)
assert(r[i].p);
aux[n_aux++] = (uint64_t)r[i].p->dp_max << 32 | i;
} else if (r[i].p) {
free(r[i].p);
r[i].p = 0;
}
}
radix_sort_64(aux, aux + n_aux);
for (i = n_aux - 1; i >= 0; --i)
t[n_aux - 1 - i] = r[(int32_t)aux[i]];
memcpy(r, t, sizeof(mm_reg1_t) * n_aux);
*n_regs = n_aux;
kfree(km, aux);
kfree(km, t);
}
int mm_set_sam_pri(int n, mm_reg1_t *r)
{
int i, n_pri = 0;
for (i = 0; i < n; ++i)
if (r[i].id == r[i].parent) {
++n_pri;
r[i].sam_pri = (n_pri == 1);
} else r[i].sam_pri = 0;
return n_pri;
}
void mm_sync_regs(void *km, int n_regs, mm_reg1_t *regs) // keep mm_reg1_t::{id,parent} in sync; also reset id
{
int *tmp, i, max_id = -1, n_tmp;
if (n_regs <= 0) return;
for (i = 0; i < n_regs; ++i) // NB: doesn't work if mm_reg1_t::id is negative
max_id = max_id > regs[i].id? max_id : regs[i].id;
n_tmp = max_id + 1;
tmp = (int*)kmalloc(km, n_tmp * sizeof(int));
for (i = 0; i < n_tmp; ++i) tmp[i] = -1;
for (i = 0; i < n_regs; ++i)
if (regs[i].id >= 0) tmp[regs[i].id] = i;
for (i = 0; i < n_regs; ++i) {
mm_reg1_t *r = &regs[i];
r->id = i;
if (r->parent == MM_PARENT_TMP_PRI)
r->parent = i;
else if (r->parent >= 0 && tmp[r->parent] >= 0)
r->parent = tmp[r->parent];
else r->parent = MM_PARENT_UNSET;
}
kfree(km, tmp);
mm_set_sam_pri(n_regs, regs);
}
void mm_select_sub(void *km, float mask_level, float pri_ratio, int min_diff, int best_n, int *n_, mm_reg1_t *r)
{
if (pri_ratio > 0.0f && *n_ > 0) {
int i, k, n = *n_, n_2nd = 0;
for (i = k = 0; i < n; ++i)
if (r[i].parent == i) r[k++] = r[i];
else if ((r[i].score >= r[r[i].parent].score * pri_ratio || r[i].score + min_diff >= r[r[i].parent].score) && n_2nd++ < best_n)
r[k++] = r[i];
else if (r[i].p) free(r[i].p);
if (k != n) mm_sync_regs(km, k, r); // removing hits requires sync()
*n_ = k;
}
}
void mm_filter_regs(void *km, const mm_mapopt_t *opt, int *n_regs, mm_reg1_t *regs)
{ // NB: after this call, mm_reg1_t::parent can be -1 if its parent filtered out
int i, k;
for (i = k = 0; i < *n_regs; ++i) {
mm_reg1_t *r = &regs[i];
int flt = 0;
if (!r->inv && r->cnt < opt->min_cnt) flt = 1;
if (r->p) {
if (r->p->blen - r->p->n_ambi - r->p->n_diff < opt->min_chain_score) flt = 1;
else if (r->p->dp_max < opt->min_dp_max) flt = 1;
if (flt) free(r->p);
}
if (!flt) {
if (k < i) regs[k++] = regs[i];
else ++k;
}
}
*n_regs = k;
}
int mm_squeeze_a(void *km, int n_regs, mm_reg1_t *regs, mm128_t *a)
{ // squeeze out regions in a[] that are not referenced by regs[]
int i, as = 0;
uint64_t *aux;
aux = (uint64_t*)kmalloc(km, n_regs * 8);
for (i = 0; i < n_regs; ++i)
aux[i] = (uint64_t)regs[i].as << 32 | i;
radix_sort_64(aux, aux + n_regs);
for (i = 0; i < n_regs; ++i) {
mm_reg1_t *r = &regs[(int32_t)aux[i]];
if (r->as != as) {
memmove(&a[as], &a[r->as], r->cnt * 16);
r->as = as;
}
as += r->cnt;
}
kfree(km, aux);
return as;
}
void mm_join_long(void *km, const mm_mapopt_t *opt, int qlen, int *n_regs_, mm_reg1_t *regs, mm128_t *a)
{
int i, n_aux, n_regs = *n_regs_, n_drop = 0;
uint64_t *aux;
if (n_regs < 2) return; // nothing to join
mm_squeeze_a(km, n_regs, regs, a);
aux = (uint64_t*)kmalloc(km, n_regs * 8);
for (i = n_aux = 0; i < n_regs; ++i)
if (regs[i].parent == i || regs[i].parent < 0)
aux[n_aux++] = (uint64_t)regs[i].as << 32 | i;
radix_sort_64(aux, aux + n_aux);
for (i = n_aux - 1; i >= 1; --i) {
mm_reg1_t *r0 = &regs[(int32_t)aux[i-1]], *r1 = &regs[(int32_t)aux[i]];
mm128_t *a0e, *a1s;
int max_gap, min_gap, sc_thres;
// test
if (r0->as + r0->cnt != r1->as) continue; // not adjacent in a[]
if (r0->rid != r1->rid || r0->rev != r1->rev) continue; // make sure on the same target and strand
a0e = &a[r0->as + r0->cnt - 1];
a1s = &a[r1->as];
if (a1s->x <= a0e->x || (int32_t)a1s->y <= (int32_t)a0e->y) continue; // keep colinearity
max_gap = min_gap = (int32_t)a1s->y - (int32_t)a0e->y;
max_gap = max_gap > a1s->x - a0e->x? max_gap : a1s->x - a0e->x;
min_gap = min_gap < a1s->x - a0e->x? min_gap : a1s->x - a0e->x;
if (max_gap > opt->max_join_long || min_gap > opt->max_join_short) continue;
sc_thres = (int)((float)opt->min_join_flank_sc / opt->max_join_long * max_gap + .499);
if (r0->score < sc_thres || r1->score < sc_thres) continue; // require good flanking chains
if (r0->re - r0->rs < max_gap>>1 || r0->qe - r0->qs < max_gap>>1) continue; // require enough flanking length
if (r1->re - r1->rs < max_gap>>1 || r1->qe - r1->qs < max_gap>>1) continue;
// all conditions satisfied; join
a[r1->as].y |= MM_SEED_LONG_JOIN;
r0->cnt += r1->cnt, r0->score += r1->score;
mm_reg_set_coor(r0, qlen, a);
r1->cnt = 0;
r1->parent = r0->id;
++n_drop;
}
kfree(km, aux);
if (n_drop > 0) { // then fix the hits hierarchy
for (i = 0; i < n_regs; ++i) { // adjust the mm_reg1_t::parent
mm_reg1_t *r = &regs[i];
if (r->parent >= 0 && r->id != r->parent) { // fix for secondary hits only
if (regs[r->parent].parent >= 0 && regs[r->parent].parent != r->parent)
r->parent = regs[r->parent].parent;
}
}
mm_filter_regs(km, opt, n_regs_, regs);
mm_sync_regs(km, *n_regs_, regs);
}
}
void mm_set_mapq(int n_regs, mm_reg1_t *regs, int min_chain_sc)
{
static const float q_coef = 30.0f;
int i;
for (i = 0; i < n_regs; ++i) {
mm_reg1_t *r = &regs[i];
if (r->inv) {
r->mapq = 0;
} else if (r->parent == r->id) {
int mapq, subsc;
float pen_cm = r->cnt >= 10? 1.0f : 0.1f * r->cnt;
subsc = r->subsc > min_chain_sc? r->subsc : min_chain_sc;
if (r->p && r->p->dp_max2 > 0 && r->p->dp_max > 0) {
float identity = (float)(r->p->blen - r->p->n_diff - r->p->n_ambi) / (r->p->blen - r->p->n_ambi);
mapq = (int)(identity * pen_cm * q_coef * (1. - (float)r->p->dp_max2 * subsc / r->p->dp_max / r->score) * logf(r->score));
} else mapq = (int)(pen_cm * q_coef * (1. - (float)subsc / r->score) * logf(r->score));
mapq = mapq > 0? mapq : 0;
r->mapq = mapq < 60? mapq : 60;
} else r->mapq = 0;
}
}
-427
View File
@@ -1,427 +0,0 @@
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include "kthread.h"
#include "bseq.h"
#include "minimap.h"
#include "mmpriv.h"
#include "kvec.h"
#include "khash.h"
#define idx_hash(a) ((a)>>1)
#define idx_eq(a, b) ((a)>>1 == (b)>>1)
KHASH_INIT(idx, uint64_t, uint64_t, 1, idx_hash, idx_eq)
typedef khash_t(idx) idxhash_t;
#define kroundup64(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, (x)|=(x)>>32, ++(x))
mm_idx_t *mm_idx_init(int w, int k, int b, int is_hpc)
{
mm_idx_t *mi;
if (k*2 < b) b = k * 2;
if (w < 1) w = 1;
mi = (mm_idx_t*)calloc(1, sizeof(mm_idx_t));
mi->w = w, mi->k = k, mi->b = b, mi->is_hpc = is_hpc;
mi->B = (mm_idx_bucket_t*)calloc(1<<b, sizeof(mm_idx_bucket_t));
if (!(mm_dbg_flag & 1)) mi->km = km_init();
return mi;
}
void mm_idx_destroy(mm_idx_t *mi)
{
int i;
if (mi == 0) return;
for (i = 0; i < 1<<mi->b; ++i) {
free(mi->B[i].p);
free(mi->B[i].a.a);
kh_destroy(idx, (idxhash_t*)mi->B[i].h);
}
if (!mi->km) {
for (i = 0; i < mi->n_seq; ++i)
free(mi->seq[i].name);
free(mi->seq);
} else km_destroy(mi->km);
free(mi->B); free(mi->S); free(mi);
}
const uint64_t *mm_idx_get(const mm_idx_t *mi, uint64_t minier, int *n)
{
int mask = (1<<mi->b) - 1;
khint_t k;
mm_idx_bucket_t *b = &mi->B[minier&mask];
idxhash_t *h = (idxhash_t*)b->h;
*n = 0;
if (h == 0) return 0;
k = kh_get(idx, h, minier>>mi->b<<1);
if (k == kh_end(h)) return 0;
if (kh_key(h, k)&1) { // special casing when there is only one k-mer
*n = 1;
return &kh_val(h, k);
} else {
*n = (uint32_t)kh_val(h, k);
return &b->p[kh_val(h, k)>>32];
}
}
void mm_idx_stat(const mm_idx_t *mi)
{
int i, n = 0, n1 = 0;
uint64_t sum = 0, len = 0;
fprintf(stderr, "[M::%s] kmer size: %d; skip: %d; is_HPC: %d; #seq: %d\n", __func__, mi->k, mi->w, mi->is_hpc, mi->n_seq);
for (i = 0; i < mi->n_seq; ++i)
len += mi->seq[i].len;
for (i = 0; i < 1<<mi->b; ++i)
if (mi->B[i].h) n += kh_size((idxhash_t*)mi->B[i].h);
for (i = 0; i < 1<<mi->b; ++i) {
idxhash_t *h = (idxhash_t*)mi->B[i].h;
khint_t k;
if (h == 0) continue;
for (k = 0; k < kh_end(h); ++k)
if (kh_exist(h, k)) {
sum += kh_key(h, k)&1? 1 : (uint32_t)kh_val(h, k);
if (kh_key(h, k)&1) ++n1;
}
}
fprintf(stderr, "[M::%s::%.3f*%.2f] distinct minimizers: %d (%.2f%% are singletons); average occurrences: %.3lf; average spacing: %.3lf\n",
__func__, realtime() - mm_realtime0, cputime() / (realtime() - mm_realtime0), n, 100.0*n1/n, (double)sum / n, (double)len / sum);
}
int mm_idx_getseq(const mm_idx_t *mi, uint32_t rid, uint32_t st, uint32_t en, uint8_t *seq)
{
uint64_t i, st1, en1;
if (rid >= mi->n_seq || st >= mi->seq[rid].len) return -1;
if (en > mi->seq[rid].len) en = mi->seq[rid].len;
st1 = mi->seq[rid].offset + st;
en1 = mi->seq[rid].offset + en;
for (i = st1; i < en1; ++i)
seq[i - st1] = mm_seq4_get(mi->S, i);
return en - st;
}
uint32_t mm_idx_cal_max_occ(const mm_idx_t *mi, float f)
{
int i;
size_t n = 0;
uint32_t thres;
khint_t *a, k;
if (f <= 0.) return UINT32_MAX;
for (i = 0; i < 1<<mi->b; ++i)
if (mi->B[i].h) n += kh_size((idxhash_t*)mi->B[i].h);
a = (uint32_t*)malloc(n * 4);
for (i = n = 0; i < 1<<mi->b; ++i) {
idxhash_t *h = (idxhash_t*)mi->B[i].h;
if (h == 0) continue;
for (k = 0; k < kh_end(h); ++k) {
if (!kh_exist(h, k)) continue;
a[n++] = kh_key(h, k)&1? 1 : (uint32_t)kh_val(h, k);
}
}
thres = ks_ksmall_uint32_t(n, a, (uint32_t)((1. - f) * n)) + 1;
free(a);
return thres;
}
/*********************************
* Sort and generate hash tables *
*********************************/
static void worker_post(void *g, long i, int tid)
{
int j, start_a, start_p, n, n_keys;
idxhash_t *h;
mm_idx_t *mi = (mm_idx_t*)g;
mm_idx_bucket_t *b = &mi->B[i];
if (b->a.n == 0) return;
// sort by minimizer
radix_sort_128x(b->a.a, b->a.a + b->a.n);
// count and preallocate
for (j = 1, n = 1, n_keys = 0, b->n = 0; j <= b->a.n; ++j) {
if (j == b->a.n || b->a.a[j].x>>8 != b->a.a[j-1].x>>8) {
++n_keys;
if (n > 1) b->n += n;
n = 1;
} else ++n;
}
h = kh_init(idx);
kh_resize(idx, h, n_keys);
b->p = (uint64_t*)calloc(b->n, 8);
// create the hash table
for (j = 1, n = 1, start_a = start_p = 0; j <= b->a.n; ++j) {
if (j == b->a.n || b->a.a[j].x>>8 != b->a.a[j-1].x>>8) {
khint_t itr;
int absent;
mm128_t *p = &b->a.a[j-1];
itr = kh_put(idx, h, p->x>>8>>mi->b<<1, &absent);
assert(absent && j - start_a == n);
if (n == 1) {
kh_key(h, itr) |= 1;
kh_val(h, itr) = p->y;
} else {
int k;
for (k = 0; k < n; ++k)
b->p[start_p + k] = b->a.a[start_a + k].y;
radix_sort_64(&b->p[start_p], &b->p[start_p + n]); // sort by position; needed as in-place radix_sort_128x() is not stable
kh_val(h, itr) = (uint64_t)start_p<<32 | n;
start_p += n;
}
start_a = j, n = 1;
} else ++n;
}
b->h = h;
assert(b->n == start_p);
// deallocate and clear b->a
free(b->a.a);
b->a.n = b->a.m = 0, b->a.a = 0;
}
static void mm_idx_post(mm_idx_t *mi, int n_threads)
{
kt_for(n_threads, worker_post, mi, 1<<mi->b);
}
/******************
* Generate index *
******************/
#include <string.h>
#include <zlib.h>
#include "bseq.h"
typedef struct {
int mini_batch_size, keep_name;
uint64_t batch_size, sum_len;
mm_bseq_file_t *fp;
mm_idx_t *mi;
} pipeline_t;
typedef struct {
int n_seq;
mm_bseq1_t *seq;
mm128_v a;
} step_t;
static void mm_idx_add(mm_idx_t *mi, int n, const mm128_t *a)
{
int i, mask = (1<<mi->b) - 1;
for (i = 0; i < n; ++i) {
mm128_v *p = &mi->B[a[i].x>>8&mask].a;
kv_push(mm128_t, 0, *p, a[i]);
}
}
static void *worker_pipeline(void *shared, int step, void *in)
{
int i;
pipeline_t *p = (pipeline_t*)shared;
if (step == 0) { // step 0: read sequences
step_t *s;
if (p->sum_len > p->batch_size) return 0;
s = (step_t*)calloc(1, sizeof(step_t));
s->seq = mm_bseq_read(p->fp, p->mini_batch_size, 0, &s->n_seq); // read a mini-batch
if (s->seq) {
uint32_t old_m, m;
uint64_t sum_len, old_max_len, max_len;
assert((uint64_t)p->mi->n_seq + s->n_seq <= UINT32_MAX); // to prevent integer overflow
// make room for p->mi->seq
old_m = p->mi->n_seq, m = p->mi->n_seq + s->n_seq;
kroundup32(m); kroundup32(old_m);
if (old_m != m)
p->mi->seq = (mm_idx_seq_t*)krealloc(p->mi->km, p->mi->seq, m * sizeof(mm_idx_seq_t));
// make room for p->mi->S
for (i = 0, sum_len = 0; i < s->n_seq; ++i) sum_len += s->seq[i].l_seq;
old_max_len = (p->sum_len + 7) / 8;
max_len = (p->sum_len + sum_len + 7) / 8;
kroundup64(old_max_len); kroundup64(max_len);
if (old_max_len != max_len) {
p->mi->S = (uint32_t*)realloc(p->mi->S, max_len * 4);
memset(&p->mi->S[old_max_len], 0, 4 * (max_len - old_max_len));
}
// populate p->mi->seq
for (i = 0; i < s->n_seq; ++i) {
mm_idx_seq_t *seq = &p->mi->seq[p->mi->n_seq];
uint32_t j;
if (p->keep_name) {
assert(strlen(s->seq[i].name) <= 254); // a long query name breaks BAM
seq->name = (char*)kmalloc(p->mi->km, strlen(s->seq[i].name) + 1);
strcpy(seq->name, s->seq[i].name);
} else seq->name = 0;
seq->len = s->seq[i].l_seq;
seq->offset = p->sum_len;
// copy the sequence
for (j = 0; j < seq->len; ++j) { // TODO: this is not the fastest way, but let's first see if speed matters here
uint64_t o = p->sum_len + j;
int c = seq_nt4_table[(uint8_t)s->seq[i].seq[j]];
mm_seq4_set(p->mi->S, o, c);
}
// update p->sum_len and p->mi->n_seq
p->sum_len += seq->len;
s->seq[i].rid = p->mi->n_seq++;
}
return s;
} else free(s);
} else if (step == 1) { // step 1: compute sketch
step_t *s = (step_t*)in;
for (i = 0; i < s->n_seq; ++i) {
mm_bseq1_t *t = &s->seq[i];
mm_sketch(0, t->seq, t->l_seq, p->mi->w, p->mi->k, t->rid, p->mi->is_hpc, &s->a);
free(t->seq); free(t->name);
}
free(s->seq); s->seq = 0;
return s;
} else if (step == 2) { // dispatch sketch to buckets
step_t *s = (step_t*)in;
mm_idx_add(p->mi, s->a.n, s->a.a);
free(s->a.a); free(s);
}
return 0;
}
mm_idx_t *mm_idx_gen(mm_bseq_file_t *fp, int w, int k, int b, int is_hpc, int mini_batch_size, int n_threads, uint64_t batch_size, int keep_name)
{
pipeline_t pl;
memset(&pl, 0, sizeof(pipeline_t));
pl.mini_batch_size = mini_batch_size < batch_size? mini_batch_size : batch_size;
pl.keep_name = keep_name;
pl.batch_size = batch_size;
pl.fp = fp;
if (pl.fp == 0) return 0;
pl.mi = mm_idx_init(w, k, b, is_hpc);
kt_pipeline(n_threads < 3? n_threads : 3, worker_pipeline, &pl, 3);
if (mm_verbose >= 3)
fprintf(stderr, "[M::%s::%.3f*%.2f] collected minimizers\n", __func__, realtime() - mm_realtime0, cputime() / (realtime() - mm_realtime0));
mm_idx_post(pl.mi, n_threads);
if (mm_verbose >= 3)
fprintf(stderr, "[M::%s::%.3f*%.2f] sorted minimizers\n", __func__, realtime() - mm_realtime0, cputime() / (realtime() - mm_realtime0));
return pl.mi;
}
mm_idx_t *mm_idx_build(const char *fn, int w, int k, int is_hpc, int n_threads) // a simpler interface
{
mm_bseq_file_t *fp;
mm_idx_t *mi;
fp = mm_bseq_open(fn);
if (fp == 0) return 0;
mi = mm_idx_gen(fp, w, k, MM_IDX_DEF_B, is_hpc, 1<<18, n_threads, UINT64_MAX, 1);
mm_bseq_close(fp);
return mi;
}
/*************
* index I/O *
*************/
void mm_idx_dump(FILE *fp, const mm_idx_t *mi)
{
uint64_t sum_len = 0;
uint32_t x[5];
int i;
x[0] = mi->w, x[1] = mi->k, x[2] = mi->b, x[3] = mi->n_seq, x[4] = mi->is_hpc;
fwrite(MM_IDX_MAGIC, 1, 4, fp);
fwrite(x, 4, 5, fp);
for (i = 0; i < mi->n_seq; ++i) {
uint8_t l;
l = strlen(mi->seq[i].name);
fwrite(&l, 1, 1, fp);
fwrite(mi->seq[i].name, 1, l, fp);
fwrite(&mi->seq[i].len, 4, 1, fp);
sum_len += mi->seq[i].len;
}
for (i = 0; i < 1<<mi->b; ++i) {
mm_idx_bucket_t *b = &mi->B[i];
khint_t k;
idxhash_t *h = (idxhash_t*)b->h;
uint32_t size = h? h->size : 0;
fwrite(&b->n, 4, 1, fp);
fwrite(b->p, 8, b->n, fp);
fwrite(&size, 4, 1, fp);
if (size == 0) continue;
for (k = 0; k < kh_end(h); ++k) {
uint64_t x[2];
if (!kh_exist(h, k)) continue;
x[0] = kh_key(h, k), x[1] = kh_val(h, k);
fwrite(x, 8, 2, fp);
}
}
fwrite(mi->S, 4, (sum_len + 7) / 8, fp);
fflush(fp);
}
mm_idx_t *mm_idx_load(FILE *fp)
{
int i;
char magic[4];
uint32_t x[5];
uint64_t sum_len = 0;
mm_idx_t *mi;
if (fread(magic, 1, 4, fp) != 4) return 0;
if (strncmp(magic, MM_IDX_MAGIC, 4) != 0) return 0;
if (fread(x, 4, 5, fp) != 5) return 0;
mi = mm_idx_init(x[0], x[1], x[2], x[4]);
mi->n_seq = x[3];
mi->seq = (mm_idx_seq_t*)kcalloc(mi->km, mi->n_seq, sizeof(mm_idx_seq_t));
for (i = 0; i < mi->n_seq; ++i) {
uint8_t l;
mm_idx_seq_t *s = &mi->seq[i];
fread(&l, 1, 1, fp);
s->name = (char*)kmalloc(mi->km, l + 1);
fread(s->name, 1, l, fp);
s->name[l] = 0;
fread(&s->len, 4, 1, fp);
s->offset = sum_len;
sum_len += s->len;
}
for (i = 0; i < 1<<mi->b; ++i) {
mm_idx_bucket_t *b = &mi->B[i];
uint32_t j, size;
khint_t k;
idxhash_t *h;
fread(&b->n, 4, 1, fp);
b->p = (uint64_t*)malloc(b->n * 8);
fread(b->p, 8, b->n, fp);
fread(&size, 4, 1, fp);
if (size == 0) continue;
b->h = h = kh_init(idx);
kh_resize(idx, h, size);
for (j = 0; j < size; ++j) {
uint64_t x[2];
int absent;
fread(x, 8, 2, fp);
k = kh_put(idx, h, x[0], &absent);
assert(absent);
kh_val(h, k) = x[1];
}
}
mi->S = (uint32_t*)malloc((sum_len + 7) / 8 * 4);
fread(mi->S, 4, (sum_len + 7) / 8, fp);
return mi;
}
int mm_idx_is_idx(const char *fn)
{
int fd, is_idx = 0;
off_t ret;
char magic[4];
if (strcmp(fn, "-") == 0) return 0; // read from pipe; not an index
fd = open(fn, O_RDONLY);
if (fd < 0) return -1; // error
if ((ret = lseek(fd, 0, SEEK_END)) >= 4) {
lseek(fd, 0, SEEK_SET);
ret = read(fd, magic, 4);
if (ret == 4 && strncmp(magic, MM_IDX_MAGIC, 4) == 0)
is_idx = 1;
}
close(fd);
return is_idx;
}
+23
View File
@@ -0,0 +1,23 @@
## Getting help
* [README][doc]: general documentation
* [Manpage](minimap2.html): explanation of command-line options
* [Peer-reviewed paper][doi]: algorithms and evaluations (please cite if you use minimap2)
* [Preprint][arxiv]: similar to the paper but free of charge
* [GitHub Issues page][issue]: report bugs, request features and ask questions
## Acquiring minimap2
* `git clone https://github.com/lh3/minimap2.git`
* [GitHub Release page][release]: versioned packages and precompiled binaries
* Also [available from BioConda][bioconda]
* Python binding [via PyPI][pypi] or [via BioConda][mappy-bc]
[doc]: https://github.com/lh3/minimap2/blob/master/README.md
[arxiv]: https://arxiv.org/abs/1708.01492
[pypi]: https://pypi.python.org/pypi/mappy
[mappy-bc]: https://anaconda.org/bioconda/mappy
[bioconda]: https://anaconda.org/bioconda/minimap2
[release]: https://github.com/lh3/minimap2/releases
[issue]: https://github.com/lh3/minimap2/issues
[doi]: https://doi.org/10.1093/bioinformatics/bty191
-214
View File
@@ -1,214 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "kalloc.h"
/* The whole thing is: ("@" for the kheader_t of the block, "-" for free
* memory, and "+" for allocated memory. One char for one unit.)
*
* This region is core 1. This region is core 2.
*
* @-------@++++++@++++++++++++@------------ @----------@++++++++++++@+++++++@------------
* | | | |
* p=p->ptr->ptr->ptr->ptr p->ptr p->ptr->ptr p->ptr->ptr->ptr
*/
#define PTR(p) ((size_t*)((size_t*)p)[1])
typedef struct _allocated_t {
struct _allocated_t *next;
size_t *ptr;
} allocated_t;
typedef struct {
size_t base[2], *loop_head;
allocated_t list_head, *list_tail;
size_t total_allocated;
} kmem_t;
void *km_init()
{
return calloc(1, sizeof(kmem_t));
}
static void kerror(const char *s)
{
fprintf(stderr, "%s\n", s);
exit(1);
}
static size_t *morecore(kmem_t *km, size_t nu)
{
size_t rnu, *up;
rnu = (nu + 0xfffff) & (~(size_t)0xfffff);
up = (size_t*)malloc(rnu * sizeof(size_t));
if (!up) { /* fail to allocate memory */
km_stat(km);
fprintf(stderr, "[morecore] %lu bytes requested but not available.\n", rnu * sizeof(size_t));
exit(1);
}
/* put the pointer in km->list_head */
if (km->list_tail == 0) km->list_tail = &km->list_head;
km->list_tail->ptr = up;
km->list_tail->next = (allocated_t*)calloc(1, sizeof(allocated_t));
km->list_tail = km->list_tail->next;
km->total_allocated += rnu * sizeof(size_t);
*up = rnu; /* the size of the current block, and in this case the block is the same as the new core */
kfree(km, up + 1); /* initialize the new "core" */
return km->loop_head;
}
void km_destroy(void *_km)
{
kmem_t *km = (kmem_t*)_km;
allocated_t *p, *q;
if (km == 0) return;
p = &km->list_head;
do {
q = p->next;
free(p->ptr);
if (p != &km->list_head) free(p);
p = q;
} while (p && p->next);
if (p != &km->list_head) free(p);
free(km);
}
void kfree(void *_km, void *ap)
{
size_t *p, *q;
kmem_t *km = (kmem_t*)_km;
if (!ap) return;
if (km == 0) {
free(ap);
return;
}
p = (size_t*)ap - 1; /* *p is the size of the current block */
/* Find the pointer that points to the block to be freed. The following loop can stop on two conditions:
*
* a) "p>q && p<q->ptr": @------@++++++++@+++++++@------- @---------------@+++++++@-------
* (can also be in | | | -> | |
* two cores) q p q->ptr q q->ptr
*
* @-------- @+++++++++@-------- @-------- @------------------
* | | | -> | |
* q p q->ptr q q->ptr
*
* b) "q>=q->ptr && (p>q || p<q->ptr)": @-------@+++++ @--------@+++++++ @-------@+++++ @----------------
* | | | -> | |
* q->ptr q p q->ptr q
*
* @+++++++@----- @++++++++@------- @------------- @++++++++@-------
* | | | -> | |
* p q->ptr q q->ptr q
*/
for (q = km->loop_head; !(p > q && p < PTR(q)); q = PTR(q))
if (q >= PTR(q) && (p > q || p < PTR(q))) break;
if (p + (*p) == PTR(q)) { /* two adjacent blocks, merge p and q->ptr (the 2nd and 4th cases) */
*p += *PTR(q); /* this is the new q->ptr size */
p[1] = (size_t)PTR(PTR(q)); /* this is the new q->ptr->ptr */
/* p is actually the new q->ptr. The actual change happens a few lines below. */
} else if (p + (*p) > PTR(q) && PTR(q) >= p) { /* the end of the allocated block is in the next free block */
kerror("[kfree] The end of the allocated block enters a free block.");
} else p[1] = (size_t)PTR(q); /* backup q->ptr */
if (q + (*q) == p) { /* two adjacent blocks, merge q and p (the other two cases) */
*q += *p;
q[1] = (size_t)PTR(p);
km->loop_head = q;
} else if (q + (*q) > p && p >= q) { /* the end of a free block in the allocated block */
kerror("[kfree] The end of a free block enters the allocated block.");
} else km->loop_head = p, q[1] = (size_t)p; /* in two cores, cannot be merged */
}
void *krealloc(void *_km, void *ap, size_t n_bytes)
{
kmem_t *km = (kmem_t*)_km;
size_t n_units, *p, *q;
if (n_bytes == 0) {
kfree(km, ap); return 0;
}
if (km == 0) return realloc(ap, n_bytes);
if (!ap) return kmalloc(km, n_bytes);
n_units = 1 + (n_bytes + sizeof(size_t) - 1) / sizeof(size_t);
p = (size_t*)ap - 1;
if (*p >= n_units) return ap; /* TODO: this prevents shrinking */
q = (size_t*)kmalloc(km, n_bytes);
memcpy(q, ap, (*p - 1) * sizeof(size_t));
kfree(km, ap);
return q;
}
void *kmalloc(void *_km, size_t n_bytes)
{
kmem_t *km = (kmem_t*)_km;
size_t n_units, *p, *q;
if (n_bytes == 0) return 0;
if (km == 0) return malloc(n_bytes);
/* "n_units" means the number of units. The size of one unit equals to sizeof(kheader_t).
* "1" is the kheader_t of a block, which is always required. */
n_units = 1 + (n_bytes + sizeof(size_t) - 1) / sizeof(size_t);
if (n_units&1) ++n_units; /* make n_units an even number, or it will segfault if only one unit remains */
if (!(q = km->loop_head)) { /* the first time when kmalloc() is called, intialization */
km->base[1] = (size_t)(km->loop_head = q = km->base); *q = 0;
}
for (p = PTR(q);; q = p, p = PTR(p)) { /* search for a suitable block */
if (*p >= n_units) { /* p->size if the size of current block. This line means the current block is large enough. */
if (*p == n_units) q[1] = (size_t)PTR(p); /* no need to split the block */
else { /* split the block */
/* memory is allocated at the end of the block */
*p -= n_units; /* reduce the size of the free block */
p += *p; /* skip to the kheader_t of the allocated block */
*p = n_units; /* set the size */
}
km->loop_head = q; /* set the end of chain */
return p + 1; /* skip the kheader_t */
}
if (p == km->loop_head) { /* then ask for more "cores" */
if ((p = morecore(km, n_units)) == 0) return 0;
}
}
}
void *kcalloc(void *_km, size_t count, size_t size)
{
kmem_t *km = (kmem_t*)_km;
void *p;
if (size == 0 || count == 0) return 0;
if (km == 0) return calloc(count, size);
p = kmalloc(km, count * size);
memset(p, 0, count * size);
return p;
}
void km_stat(const void *_km)
{
kmem_t *km = (kmem_t*)_km;
unsigned n_blocks, n_units;
size_t max_block = 0, *p, *q;
float frag;
if (km == 0 || !(p = km->loop_head)) return;
n_blocks = n_units = 0;
do {
q = PTR(p);
if (*p > max_block) max_block = *p;
n_units += *p;
if (p + (*p) > q && q > p)
kerror("[kr_stat] The end of a free block enters another free block.");
p = q;
++n_blocks;
} while (p != km->loop_head);
--n_blocks;
frag = 1.0/1024.0 * n_units * sizeof(size_t) / n_blocks;
fprintf(stderr, "[kr_stat] tot=%lu, free=%lu, n_block=%u, max_block=%lu, frag_len=%.3fK\n",
km->total_allocated, n_units * sizeof(size_t), n_blocks, max_block * sizeof(size_t), frag);
}
-26
View File
@@ -1,26 +0,0 @@
#ifndef _KALLOC_H_
#define _KALLOC_H_
#include <stdlib.h>
#define km_size(x) (*(((size_t*)(x))-1) * sizeof(size_t))
#ifdef __cplusplus
extern "C" {
#endif
void *kmalloc(void *km, size_t size);
void *krealloc(void *km, void *ptr, size_t size);
void *kcalloc(void *km, size_t count, size_t size);
void kfree(void *km, void *ptr);
void *km_init(void);
void km_destroy(void *km);
void km_stat(const void *km); // TODO: return numbers instead of print to stderr
#ifdef __cplusplus
}
#endif
#endif
-131
View File
@@ -1,131 +0,0 @@
#ifndef __AC_KDQ_H
#define __AC_KDQ_H
#include <stdlib.h>
#include <string.h>
#include "kalloc.h"
#define __KDQ_TYPE(type) \
typedef struct { \
size_t front:58, bits:6, count, mask; \
type *a; \
void *km; \
} kdq_##type##_t;
#define kdq_t(type) kdq_##type##_t
#define kdq_size(q) ((q)->count)
#define kdq_first(q) ((q)->a[(q)->front])
#define kdq_last(q) ((q)->a[((q)->front + (q)->count - 1) & (q)->mask])
#define kdq_at(q, i) ((q)->a[((q)->front + (i)) & (q)->mask])
#define __KDQ_IMPL(type, SCOPE) \
SCOPE kdq_##type##_t *kdq_init_##type(void *km) \
{ \
kdq_##type##_t *q; \
q = (kdq_##type##_t*)kcalloc(km, 1, sizeof(kdq_##type##_t)); \
q->bits = 2, q->mask = (1ULL<<q->bits) - 1; \
q->a = (type*)kmalloc(km, (1<<q->bits) * sizeof(type)); \
q->km = km; \
return q; \
} \
SCOPE void kdq_destroy_##type(kdq_##type##_t *q) \
{ \
if (q == 0) return; \
kfree(q->km, q->a); kfree(q->km, q); \
} \
SCOPE int kdq_resize_##type(kdq_##type##_t *q, int new_bits) \
{ \
size_t new_size = 1ULL<<new_bits, old_size = 1ULL<<q->bits; \
if (new_size < q->count) { /* not big enough */ \
int i; \
for (i = 0; i < 64; ++i) \
if (1ULL<<i > q->count) break; \
new_bits = i, new_size = 1ULL<<new_bits; \
} \
if (new_bits == q->bits) return q->bits; /* unchanged */ \
if (new_bits > q->bits) q->a = (type*)krealloc(q->km, q->a, (1ULL<<new_bits) * sizeof(type)); \
if (q->front + q->count <= old_size) { /* unwrapped */ \
if (q->front + q->count > new_size) /* only happens for shrinking */ \
memmove(q->a, q->a + new_size, (q->front + q->count - new_size) * sizeof(type)); \
} else { /* wrapped */ \
memmove(q->a + (new_size - (old_size - q->front)), q->a + q->front, (old_size - q->front) * sizeof(type)); \
q->front = new_size - (old_size - q->front); \
} \
q->bits = new_bits, q->mask = (1ULL<<q->bits) - 1; \
if (new_bits < q->bits) q->a = (type*)krealloc(q->km, q->a, (1ULL<<new_bits) * sizeof(type)); \
return q->bits; \
} \
SCOPE type *kdq_pushp_##type(kdq_##type##_t *q) \
{ \
if (q->count == 1ULL<<q->bits) kdq_resize_##type(q, q->bits + 1); \
return &q->a[((q->count++) + q->front) & (q)->mask]; \
} \
SCOPE void kdq_push_##type(kdq_##type##_t *q, type v) \
{ \
if (q->count == 1ULL<<q->bits) kdq_resize_##type(q, q->bits + 1); \
q->a[((q->count++) + q->front) & (q)->mask] = v; \
} \
SCOPE type *kdq_unshiftp_##type(kdq_##type##_t *q) \
{ \
if (q->count == 1ULL<<q->bits) kdq_resize_##type(q, q->bits + 1); \
++q->count; \
q->front = q->front? q->front - 1 : (1ULL<<q->bits) - 1; \
return &q->a[q->front]; \
} \
SCOPE void kdq_unshift_##type(kdq_##type##_t *q, type v) \
{ \
type *p; \
p = kdq_unshiftp_##type(q); \
*p = v; \
} \
SCOPE type *kdq_pop_##type(kdq_##type##_t *q) \
{ \
return q->count? &q->a[((--q->count) + q->front) & q->mask] : 0; \
} \
SCOPE type *kdq_shift_##type(kdq_##type##_t *q) \
{ \
type *d = 0; \
if (q->count == 0) return 0; \
d = &q->a[q->front++]; \
q->front &= q->mask; \
--q->count; \
return d; \
}
#define KDQ_INIT2(type, SCOPE) \
__KDQ_TYPE(type) \
__KDQ_IMPL(type, SCOPE)
#ifndef klib_unused
#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3)
#define klib_unused __attribute__ ((__unused__))
#else
#define klib_unused
#endif
#endif /* klib_unused */
#define KDQ_INIT(type) KDQ_INIT2(type, static inline klib_unused)
#define KDQ_DECLARE(type) \
__KDQ_TYPE(type) \
kdq_##type##_t *kdq_init_##type(); \
void kdq_destroy_##type(kdq_##type##_t *q); \
int kdq_resize_##type(kdq_##type##_t *q, int new_bits); \
type *kdq_pushp_##type(kdq_##type##_t *q); \
void kdq_push_##type(kdq_##type##_t *q, type v); \
type *kdq_unshiftp_##type(kdq_##type##_t *q); \
void kdq_unshift_##type(kdq_##type##_t *q, type v); \
type *kdq_pop_##type(kdq_##type##_t *q); \
type *kdq_shift_##type(kdq_##type##_t *q);
#define kdq_init(type, km) kdq_init_##type(km)
#define kdq_destroy(type, q) kdq_destroy_##type(q)
#define kdq_resize(type, q, new_bits) kdq_resize_##type(q, new_bits)
#define kdq_pushp(type, q) kdq_pushp_##type(q)
#define kdq_push(type, q, v) kdq_push_##type(q, v)
#define kdq_pop(type, q) kdq_pop_##type(q)
#define kdq_unshiftp(type, q) kdq_unshiftp_##type(q)
#define kdq_unshift(type, q, v) kdq_unshift_##type(q, v)
#define kdq_shift(type, q) kdq_shift_##type(q)
#endif
-615
View File
@@ -1,615 +0,0 @@
/* The MIT License
Copyright (c) 2008, 2009, 2011 by Attractive Chaos <attractor@live.co.uk>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
An example:
#include "khash.h"
KHASH_MAP_INIT_INT(32, char)
int main() {
int ret, is_missing;
khiter_t k;
khash_t(32) *h = kh_init(32);
k = kh_put(32, h, 5, &ret);
kh_value(h, k) = 10;
k = kh_get(32, h, 10);
is_missing = (k == kh_end(h));
k = kh_get(32, h, 5);
kh_del(32, h, k);
for (k = kh_begin(h); k != kh_end(h); ++k)
if (kh_exist(h, k)) kh_value(h, k) = 1;
kh_destroy(32, h);
return 0;
}
*/
/*
2013-05-02 (0.2.8):
* Use quadratic probing. When the capacity is power of 2, stepping function
i*(i+1)/2 guarantees to traverse each bucket. It is better than double
hashing on cache performance and is more robust than linear probing.
In theory, double hashing should be more robust than quadratic probing.
However, my implementation is probably not for large hash tables, because
the second hash function is closely tied to the first hash function,
which reduce the effectiveness of double hashing.
Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php
2011-12-29 (0.2.7):
* Minor code clean up; no actual effect.
2011-09-16 (0.2.6):
* The capacity is a power of 2. This seems to dramatically improve the
speed for simple keys. Thank Zilong Tan for the suggestion. Reference:
- http://code.google.com/p/ulib/
- http://nothings.org/computer/judy/
* Allow to optionally use linear probing which usually has better
performance for random input. Double hashing is still the default as it
is more robust to certain non-random input.
* Added Wang's integer hash function (not used by default). This hash
function is more robust to certain non-random input.
2011-02-14 (0.2.5):
* Allow to declare global functions.
2009-09-26 (0.2.4):
* Improve portability
2008-09-19 (0.2.3):
* Corrected the example
* Improved interfaces
2008-09-11 (0.2.2):
* Improved speed a little in kh_put()
2008-09-10 (0.2.1):
* Added kh_clear()
* Fixed a compiling error
2008-09-02 (0.2.0):
* Changed to token concatenation which increases flexibility.
2008-08-31 (0.1.2):
* Fixed a bug in kh_get(), which has not been tested previously.
2008-08-31 (0.1.1):
* Added destructor
*/
#ifndef __AC_KHASH_H
#define __AC_KHASH_H
/*!
@header
Generic hash table library.
*/
#define AC_VERSION_KHASH_H "0.2.8"
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "kalloc.h"
/* compiler specific configuration */
#if UINT_MAX == 0xffffffffu
typedef unsigned int khint32_t;
#elif ULONG_MAX == 0xffffffffu
typedef unsigned long khint32_t;
#endif
#if ULONG_MAX == ULLONG_MAX
typedef unsigned long khint64_t;
#else
typedef unsigned long long khint64_t;
#endif
#ifndef kh_inline
#ifdef _MSC_VER
#define kh_inline __inline
#else
#define kh_inline inline
#endif
#endif /* kh_inline */
#ifndef klib_unused
#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3)
#define klib_unused __attribute__ ((__unused__))
#else
#define klib_unused
#endif
#endif /* klib_unused */
typedef khint32_t khint_t;
typedef khint_t khiter_t;
#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2)
#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1)
#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3)
#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1)))
#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1)))
#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1)))
#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1))
#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4)
#ifndef kroundup32
#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
#endif
static const double __ac_HASH_UPPER = 0.77;
#define __KHASH_TYPE(name, khkey_t, khval_t) \
typedef struct kh_##name##_s { \
khint_t n_buckets, size, n_occupied, upper_bound; \
khint32_t *flags; \
khkey_t *keys; \
khval_t *vals; \
} kh_##name##_t;
#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \
extern kh_##name##_t *kh_init_##name(void); \
extern void kh_destroy_##name(kh_##name##_t *h); \
extern void kh_clear_##name(kh_##name##_t *h); \
extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \
extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \
extern void kh_del_##name(kh_##name##_t *h, khint_t x);
#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
SCOPE kh_##name##_t *kh_init_##name(void) { \
return (kh_##name##_t*)kcalloc(0, 1, sizeof(kh_##name##_t)); \
} \
SCOPE void kh_destroy_##name(kh_##name##_t *h) \
{ \
if (h) { \
kfree(0, (void *)h->keys); kfree(0, h->flags); \
kfree(0, (void *)h->vals); \
kfree(0, h); \
} \
} \
SCOPE void kh_clear_##name(kh_##name##_t *h) \
{ \
if (h && h->flags) { \
memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \
h->size = h->n_occupied = 0; \
} \
} \
SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \
{ \
if (h->n_buckets) { \
khint_t k, i, last, mask, step = 0; \
mask = h->n_buckets - 1; \
k = __hash_func(key); i = k & mask; \
last = i; \
while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
i = (i + (++step)) & mask; \
if (i == last) return h->n_buckets; \
} \
return __ac_iseither(h->flags, i)? h->n_buckets : i; \
} else return 0; \
} \
SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \
{ /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \
khint32_t *new_flags = 0; \
khint_t j = 1; \
{ \
kroundup32(new_n_buckets); \
if (new_n_buckets < 4) new_n_buckets = 4; \
if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \
else { /* hash table size to be changed (shrink or expand); rehash */ \
new_flags = (khint32_t*)kmalloc(0, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
if (!new_flags) return -1; \
memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
if (h->n_buckets < new_n_buckets) { /* expand */ \
khkey_t *new_keys = (khkey_t*)krealloc(0, (void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
if (!new_keys) { kfree(0, new_flags); return -1; } \
h->keys = new_keys; \
if (kh_is_map) { \
khval_t *new_vals = (khval_t*)krealloc(0, (void *)h->vals, new_n_buckets * sizeof(khval_t)); \
if (!new_vals) { kfree(0, new_flags); return -1; } \
h->vals = new_vals; \
} \
} /* otherwise shrink */ \
} \
} \
if (j) { /* rehashing is needed */ \
for (j = 0; j != h->n_buckets; ++j) { \
if (__ac_iseither(h->flags, j) == 0) { \
khkey_t key = h->keys[j]; \
khval_t val; \
khint_t new_mask; \
new_mask = new_n_buckets - 1; \
if (kh_is_map) val = h->vals[j]; \
__ac_set_isdel_true(h->flags, j); \
while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \
khint_t k, i, step = 0; \
k = __hash_func(key); \
i = k & new_mask; \
while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \
__ac_set_isempty_false(new_flags, i); \
if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \
{ khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \
if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \
__ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \
} else { /* write the element and jump out of the loop */ \
h->keys[i] = key; \
if (kh_is_map) h->vals[i] = val; \
break; \
} \
} \
} \
} \
if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \
h->keys = (khkey_t*)krealloc(0, (void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
if (kh_is_map) h->vals = (khval_t*)krealloc(0, (void *)h->vals, new_n_buckets * sizeof(khval_t)); \
} \
kfree(0, h->flags); /* free the working space */ \
h->flags = new_flags; \
h->n_buckets = new_n_buckets; \
h->n_occupied = h->size; \
h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \
} \
return 0; \
} \
SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \
{ \
khint_t x; \
if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \
if (h->n_buckets > (h->size<<1)) { \
if (kh_resize_##name(h, h->n_buckets - 1) < 0) { /* clear "deleted" elements */ \
*ret = -1; return h->n_buckets; \
} \
} else if (kh_resize_##name(h, h->n_buckets + 1) < 0) { /* expand the hash table */ \
*ret = -1; return h->n_buckets; \
} \
} /* TODO: to implement automatically shrinking; resize() already support shrinking */ \
{ \
khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \
x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \
if (__ac_isempty(h->flags, i)) x = i; /* for speed up */ \
else { \
last = i; \
while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
if (__ac_isdel(h->flags, i)) site = i; \
i = (i + (++step)) & mask; \
if (i == last) { x = site; break; } \
} \
if (x == h->n_buckets) { \
if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \
else x = i; \
} \
} \
} \
if (__ac_isempty(h->flags, x)) { /* not present at all */ \
h->keys[x] = key; \
__ac_set_isboth_false(h->flags, x); \
++h->size; ++h->n_occupied; \
*ret = 1; \
} else if (__ac_isdel(h->flags, x)) { /* deleted */ \
h->keys[x] = key; \
__ac_set_isboth_false(h->flags, x); \
++h->size; \
*ret = 2; \
} else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \
return x; \
} \
SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \
{ \
if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \
__ac_set_isdel_true(h->flags, x); \
--h->size; \
} \
}
#define KHASH_DECLARE(name, khkey_t, khval_t) \
__KHASH_TYPE(name, khkey_t, khval_t) \
__KHASH_PROTOTYPES(name, khkey_t, khval_t)
#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
__KHASH_TYPE(name, khkey_t, khval_t) \
__KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
KHASH_INIT2(name, static kh_inline klib_unused, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
/* --- BEGIN OF HASH FUNCTIONS --- */
/*! @function
@abstract Integer hash function
@param key The integer [khint32_t]
@return The hash value [khint_t]
*/
#define kh_int_hash_func(key) (khint32_t)(key)
/*! @function
@abstract Integer comparison function
*/
#define kh_int_hash_equal(a, b) ((a) == (b))
/*! @function
@abstract 64-bit integer hash function
@param key The integer [khint64_t]
@return The hash value [khint_t]
*/
#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11)
/*! @function
@abstract 64-bit integer comparison function
*/
#define kh_int64_hash_equal(a, b) ((a) == (b))
/*! @function
@abstract const char* hash function
@param s Pointer to a null terminated string
@return The hash value
*/
static kh_inline khint_t __ac_X31_hash_string(const char *s)
{
khint_t h = (khint_t)*s;
if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s;
return h;
}
/*! @function
@abstract Another interface to const char* hash function
@param key Pointer to a null terminated string [const char*]
@return The hash value [khint_t]
*/
#define kh_str_hash_func(key) __ac_X31_hash_string(key)
/*! @function
@abstract Const char* comparison function
*/
#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0)
static kh_inline khint_t __ac_Wang_hash(khint_t key)
{
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return key;
}
#define kh_int_hash_func2(key) __ac_Wang_hash((khint_t)key)
/* --- END OF HASH FUNCTIONS --- */
/* Other convenient macros... */
/*!
@abstract Type of the hash table.
@param name Name of the hash table [symbol]
*/
#define khash_t(name) kh_##name##_t
/*! @function
@abstract Initiate a hash table.
@param name Name of the hash table [symbol]
@return Pointer to the hash table [khash_t(name)*]
*/
#define kh_init(name) kh_init_##name()
/*! @function
@abstract Destroy a hash table.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
*/
#define kh_destroy(name, h) kh_destroy_##name(h)
/*! @function
@abstract Reset a hash table without deallocating memory.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
*/
#define kh_clear(name, h) kh_clear_##name(h)
/*! @function
@abstract Resize a hash table.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
@param s New size [khint_t]
*/
#define kh_resize(name, h, s) kh_resize_##name(h, s)
/*! @function
@abstract Insert a key to the hash table.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
@param k Key [type of keys]
@param r Extra return code: -1 if the operation failed;
0 if the key is present in the hash table;
1 if the bucket is empty (never used); 2 if the element in
the bucket has been deleted [int*]
@return Iterator to the inserted element [khint_t]
*/
#define kh_put(name, h, k, r) kh_put_##name(h, k, r)
/*! @function
@abstract Retrieve a key from the hash table.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
@param k Key [type of keys]
@return Iterator to the found element, or kh_end(h) if the element is absent [khint_t]
*/
#define kh_get(name, h, k) kh_get_##name(h, k)
/*! @function
@abstract Remove a key from the hash table.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
@param k Iterator to the element to be deleted [khint_t]
*/
#define kh_del(name, h, k) kh_del_##name(h, k)
/*! @function
@abstract Test whether a bucket contains data.
@param h Pointer to the hash table [khash_t(name)*]
@param x Iterator to the bucket [khint_t]
@return 1 if containing data; 0 otherwise [int]
*/
#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x)))
/*! @function
@abstract Get key given an iterator
@param h Pointer to the hash table [khash_t(name)*]
@param x Iterator to the bucket [khint_t]
@return Key [type of keys]
*/
#define kh_key(h, x) ((h)->keys[x])
/*! @function
@abstract Get value given an iterator
@param h Pointer to the hash table [khash_t(name)*]
@param x Iterator to the bucket [khint_t]
@return Value [type of values]
@discussion For hash sets, calling this results in segfault.
*/
#define kh_val(h, x) ((h)->vals[x])
/*! @function
@abstract Alias of kh_val()
*/
#define kh_value(h, x) ((h)->vals[x])
/*! @function
@abstract Get the start iterator
@param h Pointer to the hash table [khash_t(name)*]
@return The start iterator [khint_t]
*/
#define kh_begin(h) (khint_t)(0)
/*! @function
@abstract Get the end iterator
@param h Pointer to the hash table [khash_t(name)*]
@return The end iterator [khint_t]
*/
#define kh_end(h) ((h)->n_buckets)
/*! @function
@abstract Get the number of elements in the hash table
@param h Pointer to the hash table [khash_t(name)*]
@return Number of elements in the hash table [khint_t]
*/
#define kh_size(h) ((h)->size)
/*! @function
@abstract Get the number of buckets in the hash table
@param h Pointer to the hash table [khash_t(name)*]
@return Number of buckets in the hash table [khint_t]
*/
#define kh_n_buckets(h) ((h)->n_buckets)
/*! @function
@abstract Iterate over the entries in the hash table
@param h Pointer to the hash table [khash_t(name)*]
@param kvar Variable to which key will be assigned
@param vvar Variable to which value will be assigned
@param code Block of code to execute
*/
#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
if (!kh_exist(h,__i)) continue; \
(kvar) = kh_key(h,__i); \
(vvar) = kh_val(h,__i); \
code; \
} }
/*! @function
@abstract Iterate over the values in the hash table
@param h Pointer to the hash table [khash_t(name)*]
@param vvar Variable to which value will be assigned
@param code Block of code to execute
*/
#define kh_foreach_value(h, vvar, code) { khint_t __i; \
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
if (!kh_exist(h,__i)) continue; \
(vvar) = kh_val(h,__i); \
code; \
} }
/* More conenient interfaces */
/*! @function
@abstract Instantiate a hash set containing integer keys
@param name Name of the hash table [symbol]
*/
#define KHASH_SET_INIT_INT(name) \
KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal)
/*! @function
@abstract Instantiate a hash map containing integer keys
@param name Name of the hash table [symbol]
@param khval_t Type of values [type]
*/
#define KHASH_MAP_INIT_INT(name, khval_t) \
KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal)
/*! @function
@abstract Instantiate a hash map containing 64-bit integer keys
@param name Name of the hash table [symbol]
*/
#define KHASH_SET_INIT_INT64(name) \
KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal)
/*! @function
@abstract Instantiate a hash map containing 64-bit integer keys
@param name Name of the hash table [symbol]
@param khval_t Type of values [type]
*/
#define KHASH_MAP_INIT_INT64(name, khval_t) \
KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal)
typedef const char *kh_cstr_t;
/*! @function
@abstract Instantiate a hash map containing const char* keys
@param name Name of the hash table [symbol]
*/
#define KHASH_SET_INIT_STR(name) \
KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal)
/*! @function
@abstract Instantiate a hash map containing const char* keys
@param name Name of the hash table [symbol]
@param khval_t Type of values [type]
*/
#define KHASH_MAP_INIT_STR(name, khval_t) \
KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
#endif /* __AC_KHASH_H */
-248
View File
@@ -1,248 +0,0 @@
/* The MIT License
Copyright (c) 2008, 2009, 2011 Attractive Chaos <attractor@live.co.uk>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/* Last Modified: 05MAR2012 */
#ifndef AC_KSEQ_H
#define AC_KSEQ_H
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define KS_SEP_SPACE 0 // isspace(): \t, \n, \v, \f, \r
#define KS_SEP_TAB 1 // isspace() && !' '
#define KS_SEP_LINE 2 // line separator: "\n" (Unix) or "\r\n" (Windows)
#define KS_SEP_MAX 2
#define __KS_TYPE(type_t) \
typedef struct __kstream_t { \
int begin, end; \
int is_eof:2, bufsize:30; \
type_t f; \
unsigned char *buf; \
} kstream_t;
#define ks_eof(ks) ((ks)->is_eof && (ks)->begin >= (ks)->end)
#define ks_rewind(ks) ((ks)->is_eof = (ks)->begin = (ks)->end = 0)
#define __KS_BASIC(SCOPE, type_t, __bufsize) \
SCOPE kstream_t *ks_init(type_t f) \
{ \
kstream_t *ks = (kstream_t*)calloc(1, sizeof(kstream_t)); \
ks->f = f; ks->bufsize = __bufsize; \
ks->buf = (unsigned char*)malloc(__bufsize); \
return ks; \
} \
SCOPE void ks_destroy(kstream_t *ks) \
{ \
if (!ks) return; \
free(ks->buf); \
free(ks); \
}
#define __KS_INLINED(__read) \
static inline int ks_getc(kstream_t *ks) \
{ \
if (ks->is_eof && ks->begin >= ks->end) return -1; \
if (ks->begin >= ks->end) { \
ks->begin = 0; \
ks->end = __read(ks->f, ks->buf, ks->bufsize); \
if (ks->end < ks->bufsize) ks->is_eof = 1; \
if (ks->end == 0) return -1; \
} \
return (int)ks->buf[ks->begin++]; \
} \
static inline int ks_getuntil(kstream_t *ks, int delimiter, kstring_t *str, int *dret) \
{ return ks_getuntil2(ks, delimiter, str, dret, 0); }
#ifndef KSTRING_T
#define KSTRING_T kstring_t
typedef struct __kstring_t {
unsigned l, m;
char *s;
} kstring_t;
#endif
#ifndef kroundup32
#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
#endif
#define __KS_GETUNTIL(SCOPE, __read) \
SCOPE int ks_getuntil2(kstream_t *ks, int delimiter, kstring_t *str, int *dret, int append) \
{ \
if (dret) *dret = 0; \
str->l = append? str->l : 0; \
if (ks->begin >= ks->end && ks->is_eof) return -1; \
for (;;) { \
int i; \
if (ks->begin >= ks->end) { \
if (!ks->is_eof) { \
ks->begin = 0; \
ks->end = __read(ks->f, ks->buf, ks->bufsize); \
if (ks->end < ks->bufsize) ks->is_eof = 1; \
if (ks->end == 0) break; \
} else break; \
} \
if (delimiter == KS_SEP_LINE) { \
for (i = ks->begin; i < ks->end; ++i) \
if (ks->buf[i] == '\n') break; \
} else if (delimiter > KS_SEP_MAX) { \
for (i = ks->begin; i < ks->end; ++i) \
if (ks->buf[i] == delimiter) break; \
} else if (delimiter == KS_SEP_SPACE) { \
for (i = ks->begin; i < ks->end; ++i) \
if (isspace(ks->buf[i])) break; \
} else if (delimiter == KS_SEP_TAB) { \
for (i = ks->begin; i < ks->end; ++i) \
if (isspace(ks->buf[i]) && ks->buf[i] != ' ') break; \
} else i = 0; /* never come to here! */ \
if (str->m - str->l < (size_t)(i - ks->begin + 1)) { \
str->m = str->l + (i - ks->begin) + 1; \
kroundup32(str->m); \
str->s = (char*)realloc(str->s, str->m); \
} \
memcpy(str->s + str->l, ks->buf + ks->begin, i - ks->begin); \
str->l = str->l + (i - ks->begin); \
ks->begin = i + 1; \
if (i < ks->end) { \
if (dret) *dret = ks->buf[i]; \
break; \
} \
} \
if (str->s == 0) { \
str->m = 1; \
str->s = (char*)calloc(1, 1); \
} else if (delimiter == KS_SEP_LINE && str->l > 1 && str->s[str->l-1] == '\r') --str->l; \
str->s[str->l] = '\0'; \
return str->l; \
}
#define KSTREAM_INIT2(SCOPE, type_t, __read, __bufsize) \
__KS_TYPE(type_t) \
__KS_BASIC(SCOPE, type_t, __bufsize) \
__KS_GETUNTIL(SCOPE, __read) \
__KS_INLINED(__read)
#define KSTREAM_INIT(type_t, __read, __bufsize) KSTREAM_INIT2(static, type_t, __read, __bufsize)
#define KSTREAM_DECLARE(type_t, __read) \
__KS_TYPE(type_t) \
extern int ks_getuntil2(kstream_t *ks, int delimiter, kstring_t *str, int *dret, int append); \
extern kstream_t *ks_init(type_t f); \
extern void ks_destroy(kstream_t *ks); \
__KS_INLINED(__read)
/******************
* FASTA/Q parser *
******************/
#define kseq_rewind(ks) ((ks)->last_char = (ks)->f->is_eof = (ks)->f->begin = (ks)->f->end = 0)
#define __KSEQ_BASIC(SCOPE, type_t) \
SCOPE kseq_t *kseq_init(type_t fd) \
{ \
kseq_t *s = (kseq_t*)calloc(1, sizeof(kseq_t)); \
s->f = ks_init(fd); \
return s; \
} \
SCOPE void kseq_destroy(kseq_t *ks) \
{ \
if (!ks) return; \
free(ks->name.s); free(ks->comment.s); free(ks->seq.s); free(ks->qual.s); \
ks_destroy(ks->f); \
free(ks); \
}
/* Return value:
>=0 length of the sequence (normal)
-1 end-of-file
-2 truncated quality string
*/
#define __KSEQ_READ(SCOPE) \
SCOPE int kseq_read(kseq_t *seq) \
{ \
int c; \
kstream_t *ks = seq->f; \
if (seq->last_char == 0) { /* then jump to the next header line */ \
while ((c = ks_getc(ks)) != -1 && c != '>' && c != '@'); \
if (c == -1) return -1; /* end of file */ \
seq->last_char = c; \
} /* else: the first header char has been read in the previous call */ \
seq->comment.l = seq->seq.l = seq->qual.l = 0; /* reset all members */ \
if (ks_getuntil(ks, 0, &seq->name, &c) < 0) return -1; /* normal exit: EOF */ \
if (c != '\n') ks_getuntil(ks, KS_SEP_LINE, &seq->comment, 0); /* read FASTA/Q comment */ \
if (seq->seq.s == 0) { /* we can do this in the loop below, but that is slower */ \
seq->seq.m = 256; \
seq->seq.s = (char*)malloc(seq->seq.m); \
} \
while ((c = ks_getc(ks)) != -1 && c != '>' && c != '+' && c != '@') { \
if (c == '\n') continue; /* skip empty lines */ \
seq->seq.s[seq->seq.l++] = c; /* this is safe: we always have enough space for 1 char */ \
ks_getuntil2(ks, KS_SEP_LINE, &seq->seq, 0, 1); /* read the rest of the line */ \
} \
if (c == '>' || c == '@') seq->last_char = c; /* the first header char has been read */ \
if (seq->seq.l + 1 >= seq->seq.m) { /* seq->seq.s[seq->seq.l] below may be out of boundary */ \
seq->seq.m = seq->seq.l + 2; \
kroundup32(seq->seq.m); /* rounded to the next closest 2^k */ \
seq->seq.s = (char*)realloc(seq->seq.s, seq->seq.m); \
} \
seq->seq.s[seq->seq.l] = 0; /* null terminated string */ \
if (c != '+') return seq->seq.l; /* FASTA */ \
if (seq->qual.m < seq->seq.m) { /* allocate memory for qual in case insufficient */ \
seq->qual.m = seq->seq.m; \
seq->qual.s = (char*)realloc(seq->qual.s, seq->qual.m); \
} \
while ((c = ks_getc(ks)) != -1 && c != '\n'); /* skip the rest of '+' line */ \
if (c == -1) return -2; /* error: no quality string */ \
while (ks_getuntil2(ks, KS_SEP_LINE, &seq->qual, 0, 1) >= 0 && seq->qual.l < seq->seq.l); \
seq->last_char = 0; /* we have not come to the next header line */ \
if (seq->seq.l != seq->qual.l) return -2; /* error: qual string is of a different length */ \
return seq->seq.l; \
}
#define __KSEQ_TYPE(type_t) \
typedef struct { \
kstring_t name, comment, seq, qual; \
int last_char; \
kstream_t *f; \
} kseq_t;
#define KSEQ_INIT2(SCOPE, type_t, __read) \
KSTREAM_INIT2(SCOPE, type_t, __read, 16384) \
__KSEQ_TYPE(type_t) \
__KSEQ_BASIC(SCOPE, type_t) \
__KSEQ_READ(SCOPE)
#define KSEQ_INIT(type_t, __read) KSEQ_INIT2(static, type_t, __read)
#define KSEQ_DECLARE(type_t) \
__KS_TYPE(type_t) \
__KSEQ_TYPE(type_t) \
extern kseq_t *kseq_init(type_t fd); \
void kseq_destroy(kseq_t *ks); \
int kseq_read(kseq_t *seq);
#endif
-133
View File
@@ -1,133 +0,0 @@
/* The MIT License
Copyright (c) 2008, 2011 Attractive Chaos <attractor@live.co.uk>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// This is a simplified version of ksort.h
#ifndef AC_KSORT_H
#define AC_KSORT_H
#include <stdlib.h>
#include <string.h>
typedef struct {
void *left, *right;
int depth;
} ks_isort_stack_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) \
type_t ks_ksmall_##name(size_t n, type_t arr[], size_t kk) \
{ \
type_t *low, *high, *k, *ll, *hh, *mid; \
low = arr; high = arr + n - 1; k = arr + kk; \
for (;;) { \
if (high <= low) return *k; \
if (high == low + 1) { \
if (__sort_lt(*high, *low)) KSORT_SWAP(type_t, *low, *high); \
return *k; \
} \
mid = low + (high - low) / 2; \
if (__sort_lt(*high, *mid)) KSORT_SWAP(type_t, *mid, *high); \
if (__sort_lt(*high, *low)) KSORT_SWAP(type_t, *low, *high); \
if (__sort_lt(*low, *mid)) KSORT_SWAP(type_t, *mid, *low); \
KSORT_SWAP(type_t, *mid, *(low+1)); \
ll = low + 1; hh = high; \
for (;;) { \
do ++ll; while (__sort_lt(*ll, *low)); \
do --hh; while (__sort_lt(*low, *hh)); \
if (hh < ll) break; \
KSORT_SWAP(type_t, *ll, *hh); \
} \
KSORT_SWAP(type_t, *low, *hh); \
if (hh <= k) low = ll; \
if (hh >= k) high = hh - 1; \
} \
} \
#define ks_ksmall(name, n, a, k) ks_ksmall_##name(n, a, k)
#define ks_lt_generic(a, b) ((a) < (b))
#define ks_lt_str(a, b) (strcmp((a), (b)) < 0)
typedef const char *ksstr_t;
#define KSORT_INIT_GENERIC(type_t) KSORT_INIT(type_t, type_t, ks_lt_generic)
#define KSORT_INIT_STR KSORT_INIT(str, ksstr_t, ks_lt_str)
#define RS_MIN_SIZE 64
#define KRADIX_SORT_INIT(name, rstype_t, rskey, sizeof_key) \
typedef struct { \
rstype_t *b, *e; \
} rsbucket_##name##_t; \
void rs_insertsort_##name(rstype_t *beg, rstype_t *end) \
{ \
rstype_t *i; \
for (i = beg + 1; i < end; ++i) \
if (rskey(*i) < rskey(*(i - 1))) { \
rstype_t *j, tmp = *i; \
for (j = i; j > beg && rskey(tmp) < rskey(*(j-1)); --j) \
*j = *(j - 1); \
*j = tmp; \
} \
} \
void rs_sort_##name(rstype_t *beg, rstype_t *end, int n_bits, int s) \
{ \
rstype_t *i; \
int size = 1<<n_bits, m = size - 1; \
rsbucket_##name##_t *k, b[size], *be = b + size; \
for (k = b; k != be; ++k) k->b = k->e = beg; \
for (i = beg; i != end; ++i) ++b[rskey(*i)>>s&m].e; \
for (k = b + 1; k != be; ++k) \
k->e += (k-1)->e - beg, k->b = (k-1)->e; \
for (k = b; k != be;) { \
if (k->b != k->e) { \
rsbucket_##name##_t *l; \
if ((l = b + (rskey(*k->b)>>s&m)) != k) { \
rstype_t tmp = *k->b, swap; \
do { \
swap = tmp; tmp = *l->b; *l->b++ = swap; \
l = b + (rskey(tmp)>>s&m); \
} while (l != k); \
*k->b++ = tmp; \
} else ++k->b; \
} else ++k; \
} \
for (b->b = beg, k = b + 1; k != be; ++k) k->b = (k-1)->e; \
if (s) { \
s = s > n_bits? s - n_bits : 0; \
for (k = b; k != be; ++k) \
if (k->e - k->b > RS_MIN_SIZE) rs_sort_##name(k->b, k->e, n_bits, s); \
else if (k->e - k->b > 1) rs_insertsort_##name(k->b, k->e); \
} \
} \
void radix_sort_##name(rstype_t *beg, rstype_t *end) \
{ \
if (end - beg <= RS_MIN_SIZE) rs_insertsort_##name(beg, end); \
else rs_sort_##name(beg, end, 8, sizeof_key * 8 - 8); \
}
#endif
-166
View File
@@ -1,166 +0,0 @@
#ifndef KSW2_H_
#define KSW2_H_
#include <stdint.h>
#define KSW_NEG_INF -0x40000000
#define KSW_EZ_SCORE_ONLY 0x01 // don't record alignment path/cigar
#define KSW_EZ_RIGHT 0x02 // right-align gaps
#define KSW_EZ_GENERIC_SC 0x04 // without this flag: match/mismatch only; last symbol is a wildcard
#define KSW_EZ_APPROX_MAX 0x08 // approximate max; this is faster with sse
#define KSW_EZ_APPROX_DROP 0x10 // approximate Z-drop; faster with sse
#define KSW_EZ_EXTZ_ONLY 0x40 // only perform extension
#define KSW_EZ_REV_CIGAR 0x80 // reverse CIGAR in the output
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint32_t max:31, zdropped:1;
int max_q, max_t; // max extension coordinate
int mqe, mqe_t; // max score when reaching the end of query
int mte, mte_q; // max score when reaching the end of target
int score; // max score reaching both ends; may be KSW_NEG_INF
int m_cigar, n_cigar;
uint32_t *cigar;
} ksw_extz_t;
/**
* NW-like extension
*
* @param km memory pool, when used with kalloc
* @param qlen query length
* @param query query sequence with 0 <= query[i] < m
* @param tlen target length
* @param target target sequence with 0 <= target[i] < m
* @param m number of residue types
* @param mat m*m scoring mattrix in one-dimension array
* @param gapo gap open penalty; a gap of length l cost "-(gapo+l*gape)"
* @param gape gap extension penalty
* @param w band width (<0 to disable)
* @param zdrop off-diagonal drop-off to stop extension (positive; <0 to disable)
* @param flag flag (see KSW_EZ_* macros)
* @param ez (out) scores and cigar
*/
void ksw_extz(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 flag, ksw_extz_t *ez);
void ksw_extz2_sse(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 flag, ksw_extz_t *ez);
void ksw_extd(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat,
int8_t gapo, int8_t gape, int8_t gapo2, int8_t gape2, int w, int zdrop, int flag, ksw_extz_t *ez);
void ksw_extd2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat,
int8_t gapo, int8_t gape, int8_t gapo2, int8_t gape2, int w, int zdrop, int flag, ksw_extz_t *ez);
void ksw_extf2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t mch, int8_t mis, int8_t e, int w, int xdrop, ksw_extz_t *ez);
/**
* Global alignment
*
* (first 10 parameters identical to ksw_extz_sse())
* @param m_cigar (modified) max CIGAR length; feed 0 if cigar==0
* @param n_cigar (out) number of CIGAR elements
* @param cigar (out) BAM-encoded CIGAR; caller need to deallocate with kfree(km, )
*
* @return score of the alignment
*/
int ksw_gg(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t gapo, int8_t gape, int w, int *m_cigar_, int *n_cigar_, uint32_t **cigar_);
int ksw_gg2(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t gapo, int8_t gape, int w, int *m_cigar_, int *n_cigar_, uint32_t **cigar_);
int ksw_gg2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t gapo, int8_t gape, int w, int *m_cigar_, int *n_cigar_, uint32_t **cigar_);
void *ksw_ll_qinit(void *km, int size, int qlen, const uint8_t *query, int m, const int8_t *mat);
int ksw_ll_i16(void *q, int tlen, const uint8_t *target, int gapo, int gape, int *qe, int *te);
#ifdef __cplusplus
}
#endif
/************************************
*** Private macros and functions ***
************************************/
#ifdef HAVE_KALLOC
#include "kalloc.h"
#else
#include <stdlib.h>
#define kmalloc(km, size) malloc((size))
#define kcalloc(km, count, size) calloc((count), (size))
#define krealloc(km, ptr, size) realloc((ptr), (size))
#define kfree(km, ptr) free((ptr))
#endif
static inline uint32_t *ksw_push_cigar(void *km, int *n_cigar, int *m_cigar, uint32_t *cigar, uint32_t op, int len)
{
if (*n_cigar == 0 || op != (cigar[(*n_cigar) - 1]&0xf)) {
if (*n_cigar == *m_cigar) {
*m_cigar = *m_cigar? (*m_cigar)<<1 : 4;
cigar = (uint32_t*)krealloc(km, cigar, (*m_cigar) << 2);
}
cigar[(*n_cigar)++] = len<<4 | op;
} else cigar[(*n_cigar)-1] += len<<4;
return cigar;
}
// In the backtrack matrix, value p[] has the following structure:
// bit 0-2: which type gets the max - 0 for H, 1 for E, 2 for F, 3 for \tilde{E} and 4 for \tilde{F}
// bit 3/0x08: 1 if a continuation on the E state (bit 5/0x20 for a continuation on \tilde{E})
// bit 4/0x10: 1 if a continuation on the F state (bit 6/0x40 for a continuation on \tilde{F})
static inline void ksw_backtrack(void *km, int is_rot, int is_rev, const uint8_t *p, const int *off, const int *off_end, int n_col, int i0, int j0, int *m_cigar_, int *n_cigar_, uint32_t **cigar_)
{ // p[] - lower 3 bits: which type gets the max; bit
int n_cigar = 0, m_cigar = *m_cigar_, i = i0, j = j0, r, state = 0;
uint32_t *cigar = *cigar_, tmp;
while (i >= 0 && j >= 0) { // at the beginning of the loop, _state_ tells us which state to check
int force_state = -1;
if (is_rot) {
r = i + j;
if (i < off[r]) force_state = 2;
if (off_end && i > off_end[r]) force_state = 1;
tmp = force_state < 0? p[r * n_col + i - off[r]] : 0;
} else {
if (j < off[i]) force_state = 2;
if (off_end && j > off_end[i]) force_state = 1;
tmp = force_state < 0? p[i * n_col + j - off[i]] : 0;
}
if (state == 0) state = tmp & 7; // if requesting the H state, find state one maximizes it.
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 (force_state >= 0) state = force_state;
if (state == 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 0, 1), --i, --j; // match
else if (state == 1 || state == 3) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 2, 1), --i; // deletion
else cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 1, 1), --j; // insertion
}
if (i >= 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 2, i + 1); // first deletion
if (j >= 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 1, j + 1); // first insertion
if (!is_rev)
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;
*m_cigar_ = m_cigar, *n_cigar_ = n_cigar, *cigar_ = cigar;
}
static inline void ksw_reset_extz(ksw_extz_t *ez)
{
ez->max_q = ez->max_t = ez->mqe_t = ez->mte_q = -1;
ez->max = 0, ez->score = ez->mqe = ez->mte = KSW_NEG_INF;
ez->n_cigar = 0, ez->zdropped = 0;
}
static inline int ksw_apply_zdrop(ksw_extz_t *ez, int is_rot, int32_t H, int a, int b, int zdrop, int8_t e)
{
int r, t;
if (is_rot) r = a, t = b;
else r = a + b, t = a;
if (H > (int32_t)ez->max) {
ez->max = H, ez->max_t = t, ez->max_q = r - t;
} else if (t >= ez->max_t && r - t >= ez->max_q) {
int tl = t - ez->max_t, ql = (r - t) - ez->max_q, l;
l = tl > ql? tl - ql : ql - tl;
if (zdrop >= 0 && ez->max - H > zdrop + l * e) {
ez->zdropped = 1;
return 1;
}
}
return 0;
}
#endif
-371
View File
@@ -1,371 +0,0 @@
#include <string.h>
#include <stdio.h>
#include "ksw2.h"
#ifdef __SSE2__
#include <emmintrin.h>
#ifdef __SSE4_1__
#include <smmintrin.h>
#endif
void ksw_extd2_sse(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 flag, ksw_extz_t *ez)
{
#define __dp_code_block1 \
z = _mm_load_si128(&s[t]); \
xt1 = _mm_load_si128(&x[t]); /* xt1 <- x[r-1][t..t+15] */ \
tmp = _mm_srli_si128(xt1, 15); /* tmp <- x[r-1][t+15] */ \
xt1 = _mm_or_si128(_mm_slli_si128(xt1, 1), x1_); /* xt1 <- x[r-1][t-1..t+14] */ \
x1_ = tmp; \
vt1 = _mm_load_si128(&v[t]); /* vt1 <- v[r-1][t..t+15] */ \
tmp = _mm_srli_si128(vt1, 15); /* tmp <- v[r-1][t+15] */ \
vt1 = _mm_or_si128(_mm_slli_si128(vt1, 1), v1_); /* vt1 <- v[r-1][t-1..t+14] */ \
v1_ = tmp; \
a = _mm_add_epi8(xt1, vt1); /* a <- x[r-1][t-1..t+14] + v[r-1][t-1..t+14] */ \
ut = _mm_load_si128(&u[t]); /* ut <- u[t..t+15] */ \
b = _mm_add_epi8(_mm_load_si128(&y[t]), ut); /* b <- y[r-1][t..t+15] + u[r-1][t..t+15] */ \
x2t1= _mm_load_si128(&x2[t]); \
tmp = _mm_srli_si128(x2t1, 15); \
x2t1= _mm_or_si128(_mm_slli_si128(x2t1, 1), x21_); \
x21_= tmp; \
a2= _mm_add_epi8(x2t1, vt1); \
b2= _mm_add_epi8(_mm_load_si128(&y2[t]), ut);
#define __dp_code_block2 \
_mm_store_si128(&u[t], _mm_sub_epi8(z, vt1)); /* u[r][t..t+15] <- z - v[r-1][t-1..t+14] */ \
_mm_store_si128(&v[t], _mm_sub_epi8(z, ut)); /* v[r][t..t+15] <- z - u[r-1][t..t+15] */ \
tmp = _mm_sub_epi8(z, q_); \
a = _mm_sub_epi8(a, tmp); \
b = _mm_sub_epi8(b, tmp); \
tmp = _mm_sub_epi8(z, q2_); \
a2= _mm_sub_epi8(a2, tmp); \
b2= _mm_sub_epi8(b2, tmp);
int r, t, qe = q + e, n_col_, *off = 0, *off_end = 0, tlen_, qlen_, last_st, last_en, wl, wr, max_sc, min_sc, long_thres, long_diff;
int with_cigar = !(flag&KSW_EZ_SCORE_ONLY), approx_max = !!(flag&KSW_EZ_APPROX_MAX);
int32_t *H = 0, H0 = 0, last_H0_t = 0;
uint8_t *qr, *sf, *mem, *mem2 = 0;
__m128i q_, q2_, qe_, qe2_, zero_, sc_mch_, sc_mis_, m1_;
__m128i *u, *v, *x, *y, *x2, *y2, *s, *p = 0;
ksw_reset_extz(ez);
if (m <= 1 || qlen <= 0 || tlen <= 0) return;
if (q2 + e2 < q + e) t = q, q = q2, q2 = t, t = e, e = e2, e2 = t; // make sure q+e no larger than q2+e2
zero_ = _mm_set1_epi8(0);
q_ = _mm_set1_epi8(q);
q2_ = _mm_set1_epi8(q2);
qe_ = _mm_set1_epi8(q + e);
qe2_ = _mm_set1_epi8(q2 + e2);
sc_mch_ = _mm_set1_epi8(mat[0]);
sc_mis_ = _mm_set1_epi8(mat[1]);
m1_ = _mm_set1_epi8(m - 1); // wildcard
if (w < 0) w = tlen > qlen? tlen : qlen;
wl = wr = w;
tlen_ = (tlen + 15) / 16;
n_col_ = ((w + 1 < tlen? (w + 1 < qlen? w + 1 : qlen): tlen) + 15) / 16 + 1;
qlen_ = (qlen + 15) / 16;
for (t = 1, max_sc = mat[0], min_sc = mat[1]; t < m * m; ++t) {
max_sc = max_sc > mat[t]? max_sc : mat[t];
min_sc = min_sc < mat[t]? min_sc : mat[t];
}
if (-min_sc > 2 * (q + e)) return; // otherwise, we won't see any mismatches
long_thres = e != e2? (q2 - q) / (e - e2) - 1 : 0;
if (q2 + e2 + long_thres * e2 > q + e + long_thres * e)
++long_thres;
long_diff = long_thres * (e - e2) - (q2 - q) - e2;
mem = (uint8_t*)kcalloc(km, tlen_ * 8 + qlen_ + 1, 16);
u = (__m128i*)(((size_t)mem + 15) >> 4 << 4); // 16-byte aligned
v = u + tlen_, x = v + tlen_, y = x + tlen_, x2 = y + tlen_, y2 = x2 + tlen_;
s = y2 + tlen_, sf = (uint8_t*)(s + tlen_), qr = sf + tlen_ * 16;
memset(u, -q - e, tlen_ * 16);
memset(v, -q - e, tlen_ * 16);
memset(x, -q - e, tlen_ * 16);
memset(y, -q - e, tlen_ * 16);
memset(x2, -q2 - e2, tlen_ * 16);
memset(y2, -q2 - e2, tlen_ * 16);
if (!approx_max) {
H = (int32_t*)kmalloc(km, tlen_ * 16 * 4);
for (t = 0; t < tlen_ * 16; ++t) H[t] = KSW_NEG_INF;
}
if (with_cigar) {
mem2 = (uint8_t*)kmalloc(km, ((qlen + tlen - 1) * n_col_ + 1) * 16);
p = (__m128i*)(((size_t)mem2 + 15) >> 4 << 4);
off = (int*)kmalloc(km, (qlen + tlen - 1) * sizeof(int) * 2);
off_end = off + qlen + tlen - 1;
}
for (t = 0; t < qlen; ++t) qr[t] = query[qlen - 1 - t];
memcpy(sf, target, tlen);
for (r = 0, last_st = last_en = -1; r < qlen + tlen - 1; ++r) {
int st = 0, en = tlen - 1, st0, en0, st_, en_;
int8_t x1, x21, v1;
uint8_t *qrr = qr + (qlen - 1 - r);
int8_t *u8 = (int8_t*)u, *v8 = (int8_t*)v, *x8 = (int8_t*)x, *x28 = (int8_t*)x2;
__m128i x1_, x21_, v1_;
// find the boundaries
if (st < r - qlen + 1) st = r - qlen + 1;
if (en > r) en = r;
if (st < (r-wr+1)>>1) st = (r-wr+1)>>1; // take the ceil
if (en > (r+wl)>>1) en = (r+wl)>>1; // take the floor
if (st > en) {
ez->zdropped = 1;
break;
}
st0 = st, en0 = en;
st = st / 16 * 16, en = (en + 16) / 16 * 16 - 1;
// set boundary conditions
if (st > 0) {
if (st - 1 >= last_st && st - 1 <= last_en) {
x1 = x8[st - 1], x21 = x28[st - 1], v1 = v8[st - 1]; // (r-1,s-1) calculated in the last round
} else {
x1 = -q - e, x21 = -q2 - e2;
v1 = -q - e;
}
} else {
x1 = -q - e, x21 = -q2 - e2;
v1 = r == 0? -q - e : r < long_thres? -e : r == long_thres? long_diff : -e2;
}
if (en >= r) {
((int8_t*)y)[r] = -q - e, ((int8_t*)y2)[r] = -q2 - e2;
u8[r] = r == 0? -q - e : r < long_thres? -e : r == long_thres? long_diff : -e2;
}
// loop fission: set scores first
if (!(flag & KSW_EZ_GENERIC_SC)) {
for (t = st0; t <= en0; t += 16) {
__m128i sq, st, tmp, mask;
sq = _mm_loadu_si128((__m128i*)&sf[t]);
st = _mm_loadu_si128((__m128i*)&qrr[t]);
mask = _mm_or_si128(_mm_cmpeq_epi8(sq, m1_), _mm_cmpeq_epi8(st, m1_));
tmp = _mm_cmpeq_epi8(sq, st);
#ifdef __SSE4_1__
tmp = _mm_blendv_epi8(sc_mis_, sc_mch_, tmp);
#else
tmp = _mm_or_si128(_mm_andnot_si128(tmp, sc_mis_), _mm_and_si128(tmp, sc_mch_));
#endif
tmp = _mm_andnot_si128(mask, tmp);
_mm_storeu_si128((__m128i*)((int8_t*)s + t), tmp);
}
} else {
for (t = st0; t <= en0; ++t)
((uint8_t*)s)[t] = mat[sf[t] * m + qrr[t]];
}
// core loop
x1_ = _mm_cvtsi32_si128((uint8_t)x1);
x21_ = _mm_cvtsi32_si128((uint8_t)x21);
v1_ = _mm_cvtsi32_si128((uint8_t)v1);
st_ = st / 16, en_ = en / 16;
if (!with_cigar) { // score only
for (t = st_; t <= en_; ++t) {
__m128i z, a, b, a2, b2, xt1, x2t1, vt1, ut, tmp;
__dp_code_block1;
#ifdef __SSE4_1__
z = _mm_max_epi8(z, a);
z = _mm_max_epi8(z, b);
z = _mm_max_epi8(z, a2);
z = _mm_max_epi8(z, b2);
z = _mm_min_epi8(z, sc_mch_);
__dp_code_block2; // save u[] and v[]; update a, b, a2 and b2
_mm_store_si128(&x[t], _mm_sub_epi8(_mm_max_epi8(a, zero_), qe_));
_mm_store_si128(&y[t], _mm_sub_epi8(_mm_max_epi8(b, zero_), qe_));
_mm_store_si128(&x2[t], _mm_sub_epi8(_mm_max_epi8(a2, zero_), qe2_));
_mm_store_si128(&y2[t], _mm_sub_epi8(_mm_max_epi8(b2, zero_), qe2_));
#else
tmp = _mm_cmpgt_epi8(a, z);
z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, a));
tmp = _mm_cmpgt_epi8(b, z);
z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, b));
tmp = _mm_cmpgt_epi8(a2, z);
z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, a2));
tmp = _mm_cmpgt_epi8(b2, z);
z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, b2));
tmp = _mm_cmplt_epi8(sc_mch_, z);
z = _mm_or_si128(_mm_and_si128(tmp, sc_mch_), _mm_andnot_si128(tmp, z));
__dp_code_block2;
tmp = _mm_cmpgt_epi8(a, zero_);
_mm_store_si128(&x[t], _mm_sub_epi8(_mm_and_si128(tmp, a), qe_));
tmp = _mm_cmpgt_epi8(b, zero_);
_mm_store_si128(&y[t], _mm_sub_epi8(_mm_and_si128(tmp, b), qe_));
tmp = _mm_cmpgt_epi8(a2, zero_);
_mm_store_si128(&x2[t], _mm_sub_epi8(_mm_and_si128(tmp, a2), qe2_));
tmp = _mm_cmpgt_epi8(b2, zero_);
_mm_store_si128(&y2[t], _mm_sub_epi8(_mm_and_si128(tmp, b2), qe2_));
#endif
}
} else if (!(flag&KSW_EZ_RIGHT)) { // gap left-alignment
__m128i *pr = p + r * n_col_ - st_;
off[r] = st, off_end[r] = en;
for (t = st_; t <= en_; ++t) {
__m128i d, z, a, b, a2, b2, xt1, x2t1, vt1, ut, tmp;
__dp_code_block1;
#ifdef __SSE4_1__
d = _mm_and_si128(_mm_cmpgt_epi8(a, z), _mm_set1_epi8(1)); // d = a > z? 1 : 0
z = _mm_max_epi8(z, a);
d = _mm_blendv_epi8(d, _mm_set1_epi8(2), _mm_cmpgt_epi8(b, z)); // d = b > z? 2 : d
z = _mm_max_epi8(z, b);
d = _mm_blendv_epi8(d, _mm_set1_epi8(3), _mm_cmpgt_epi8(a2, z)); // d = a2 > z? 3 : d
z = _mm_max_epi8(z, a2);
d = _mm_blendv_epi8(d, _mm_set1_epi8(4), _mm_cmpgt_epi8(b2, z)); // d = a2 > z? 3 : d
z = _mm_max_epi8(z, b2);
z = _mm_min_epi8(z, sc_mch_);
#else // we need to emulate SSE4.1 intrinsics _mm_max_epi8() and _mm_blendv_epi8()
tmp = _mm_cmpgt_epi8(a, z);
d = _mm_and_si128(tmp, _mm_set1_epi8(1));
z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, a));
tmp = _mm_cmpgt_epi8(b, z);
d = _mm_or_si128(_mm_andnot_si128(tmp, d), _mm_and_si128(tmp, _mm_set1_epi8(2)));
z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, b));
tmp = _mm_cmpgt_epi8(a2, z);
d = _mm_or_si128(_mm_andnot_si128(tmp, d), _mm_and_si128(tmp, _mm_set1_epi8(3)));
z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, a2));
tmp = _mm_cmpgt_epi8(b2, z);
d = _mm_or_si128(_mm_andnot_si128(tmp, d), _mm_and_si128(tmp, _mm_set1_epi8(4)));
z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, b2));
tmp = _mm_cmplt_epi8(sc_mch_, z);
z = _mm_or_si128(_mm_and_si128(tmp, sc_mch_), _mm_andnot_si128(tmp, z));
#endif
__dp_code_block2;
tmp = _mm_cmpgt_epi8(a, zero_);
_mm_store_si128(&x[t], _mm_sub_epi8(_mm_and_si128(tmp, a), qe_));
d = _mm_or_si128(d, _mm_and_si128(tmp, _mm_set1_epi8(0x08))); // d = a > 0? 1<<3 : 0
tmp = _mm_cmpgt_epi8(b, zero_);
_mm_store_si128(&y[t], _mm_sub_epi8(_mm_and_si128(tmp, b), qe_));
d = _mm_or_si128(d, _mm_and_si128(tmp, _mm_set1_epi8(0x10))); // d = b > 0? 1<<4 : 0
tmp = _mm_cmpgt_epi8(a2, zero_);
_mm_store_si128(&x2[t], _mm_sub_epi8(_mm_and_si128(tmp, a2), qe2_));
d = _mm_or_si128(d, _mm_and_si128(tmp, _mm_set1_epi8(0x20))); // d = a > 0? 1<<5 : 0
tmp = _mm_cmpgt_epi8(b2, zero_);
_mm_store_si128(&y2[t], _mm_sub_epi8(_mm_and_si128(tmp, b2), qe2_));
d = _mm_or_si128(d, _mm_and_si128(tmp, _mm_set1_epi8(0x40))); // d = b > 0? 1<<6 : 0
_mm_store_si128(&pr[t], d);
}
} else { // gap right-alignment
__m128i *pr = p + r * n_col_ - st_;
off[r] = st, off_end[r] = en;
for (t = st_; t <= en_; ++t) {
__m128i d, z, a, b, a2, b2, xt1, x2t1, vt1, ut, tmp;
__dp_code_block1;
#ifdef __SSE4_1__
d = _mm_andnot_si128(_mm_cmpgt_epi8(z, a), _mm_set1_epi8(1)); // d = z > a? 0 : 1
z = _mm_max_epi8(z, a);
d = _mm_blendv_epi8(_mm_set1_epi8(2), d, _mm_cmpgt_epi8(z, b)); // d = z > b? d : 2
z = _mm_max_epi8(z, b);
d = _mm_blendv_epi8(_mm_set1_epi8(3), d, _mm_cmpgt_epi8(z, a2)); // d = z > a2? d : 3
z = _mm_max_epi8(z, a2);
d = _mm_blendv_epi8(_mm_set1_epi8(4), d, _mm_cmpgt_epi8(z, b2)); // d = z > b2? d : 4
z = _mm_max_epi8(z, b2);
z = _mm_min_epi8(z, sc_mch_);
#else // we need to emulate SSE4.1 intrinsics _mm_max_epi8() and _mm_blendv_epi8()
tmp = _mm_cmpgt_epi8(z, a);
d = _mm_andnot_si128(tmp, _mm_set1_epi8(1));
z = _mm_or_si128(_mm_and_si128(tmp, z), _mm_andnot_si128(tmp, a));
tmp = _mm_cmpgt_epi8(z, b);
d = _mm_or_si128(_mm_and_si128(tmp, d), _mm_andnot_si128(tmp, _mm_set1_epi8(2)));
z = _mm_or_si128(_mm_and_si128(tmp, z), _mm_andnot_si128(tmp, b));
tmp = _mm_cmpgt_epi8(z, a2);
d = _mm_or_si128(_mm_and_si128(tmp, d), _mm_andnot_si128(tmp, _mm_set1_epi8(3)));
z = _mm_or_si128(_mm_and_si128(tmp, z), _mm_andnot_si128(tmp, a2));
tmp = _mm_cmpgt_epi8(z, b2);
d = _mm_or_si128(_mm_and_si128(tmp, d), _mm_andnot_si128(tmp, _mm_set1_epi8(4)));
z = _mm_or_si128(_mm_and_si128(tmp, z), _mm_andnot_si128(tmp, b2));
tmp = _mm_cmplt_epi8(sc_mch_, z);
z = _mm_or_si128(_mm_and_si128(tmp, sc_mch_), _mm_andnot_si128(tmp, z));
#endif
__dp_code_block2;
tmp = _mm_cmpgt_epi8(zero_, a);
_mm_store_si128(&x[t], _mm_sub_epi8(_mm_andnot_si128(tmp, a), qe_));
d = _mm_or_si128(d, _mm_andnot_si128(tmp, _mm_set1_epi8(0x08))); // d = a > 0? 1<<3 : 0
tmp = _mm_cmpgt_epi8(zero_, b);
_mm_store_si128(&y[t], _mm_sub_epi8(_mm_andnot_si128(tmp, b), qe_));
d = _mm_or_si128(d, _mm_andnot_si128(tmp, _mm_set1_epi8(0x10))); // d = b > 0? 1<<4 : 0
tmp = _mm_cmpgt_epi8(zero_, a2);
_mm_store_si128(&x2[t], _mm_sub_epi8(_mm_andnot_si128(tmp, a2), qe2_));
d = _mm_or_si128(d, _mm_andnot_si128(tmp, _mm_set1_epi8(0x20))); // d = a > 0? 1<<5 : 0
tmp = _mm_cmpgt_epi8(zero_, b2);
_mm_store_si128(&y2[t], _mm_sub_epi8(_mm_andnot_si128(tmp, b2), qe2_));
d = _mm_or_si128(d, _mm_andnot_si128(tmp, _mm_set1_epi8(0x40))); // d = b > 0? 1<<6 : 0
_mm_store_si128(&pr[t], d);
}
}
if (!approx_max) { // find the exact max with a 32-bit score array
int32_t max_H, max_t;
// compute H[], max_H and max_t
if (r > 0) {
int32_t HH[4], tt[4], en1 = st0 + (en0 - st0) / 4 * 4, i;
__m128i max_H_, max_t_;
max_H = H[en0] = en0 > 0? H[en0-1] + u8[en0] : H[en0] + v8[en0]; // special casing the last element
max_t = en0;
max_H_ = _mm_set1_epi32(max_H);
max_t_ = _mm_set1_epi32(max_t);
for (t = st0; t < en1; t += 4) { // this implements: H[t]+=v8[t]-qe; if(H[t]>max_H) max_H=H[t],max_t=t;
__m128i H1, tmp, t_;
H1 = _mm_loadu_si128((__m128i*)&H[t]);
t_ = _mm_setr_epi32(v8[t], v8[t+1], v8[t+2], v8[t+3]);
H1 = _mm_add_epi32(H1, t_);
_mm_storeu_si128((__m128i*)&H[t], H1);
t_ = _mm_set1_epi32(t);
tmp = _mm_cmpgt_epi32(H1, max_H_);
#ifdef __SSE4_1__
max_H_ = _mm_blendv_epi8(max_H_, H1, tmp);
max_t_ = _mm_blendv_epi8(max_t_, t_, tmp);
#else
max_H_ = _mm_or_si128(_mm_and_si128(tmp, H1), _mm_andnot_si128(tmp, max_H_));
max_t_ = _mm_or_si128(_mm_and_si128(tmp, t_), _mm_andnot_si128(tmp, max_t_));
#endif
}
_mm_storeu_si128((__m128i*)HH, max_H_);
_mm_storeu_si128((__m128i*)tt, max_t_);
for (i = 0; i < 4; ++i)
if (max_H < HH[i]) max_H = HH[i], max_t = tt[i] + i;
for (; t < en0; ++t) { // for the rest of values that haven't been computed with SSE
H[t] += (int32_t)v8[t];
if (H[t] > max_H)
max_H = H[t], max_t = t;
}
} else H[0] = v8[0] - qe, max_H = H[0], max_t = 0; // special casing r==0
// update ez
if (en0 == tlen - 1 && H[en0] > ez->mte)
ez->mte = H[en0], ez->mte_q = r - en;
if (r - st0 == qlen - 1 && H[st0] > ez->mqe)
ez->mqe = H[st0], ez->mqe_t = st0;
if (ksw_apply_zdrop(ez, 1, max_H, r, max_t, zdrop, e2)) break;
if (r == qlen + tlen - 2 && en0 == tlen - 1)
ez->score = H[tlen - 1];
} else { // find approximate max; Z-drop might be inaccurate, too.
if (r > 0) {
if (last_H0_t >= st0 && last_H0_t <= en0 && last_H0_t + 1 >= st0 && last_H0_t + 1 <= en0) {
int32_t d0 = v8[last_H0_t];
int32_t d1 = u8[last_H0_t + 1];
if (d0 > d1) H0 += d0;
else H0 += d1, ++last_H0_t;
} else if (last_H0_t >= st0 && last_H0_t <= en0) {
H0 += v8[last_H0_t];
} else {
++last_H0_t, H0 += u8[last_H0_t];
}
} else H0 = v8[0] - qe, last_H0_t = 0;
if ((flag & KSW_EZ_APPROX_DROP) && ksw_apply_zdrop(ez, 1, H0, r, last_H0_t, zdrop, e2)) break;
if (r == qlen + tlen - 2 && en0 == tlen - 1)
ez->score = H0;
}
last_st = st, last_en = en;
//for (t = st0; t <= en0; ++t) printf("(%d,%d)\t(%d,%d,%d,%d)\t%d\n", r, t, ((int8_t*)u)[t], ((int8_t*)v)[t], ((int8_t*)x)[t], ((int8_t*)y)[t], H[t]); // for debugging
}
kfree(km, mem);
if (!approx_max) kfree(km, H);
if (with_cigar) { // backtrack
int rev_cigar = !!(flag & KSW_EZ_REV_CIGAR);
if (!ez->zdropped && !(flag&KSW_EZ_EXTZ_ONLY))
ksw_backtrack(km, 1, rev_cigar, (uint8_t*)p, off, off_end, n_col_*16, tlen-1, qlen-1, &ez->m_cigar, &ez->n_cigar, &ez->cigar);
else if (ez->max_t >= 0 && ez->max_q >= 0)
ksw_backtrack(km, 1, rev_cigar, (uint8_t*)p, off, off_end, n_col_*16, ez->max_t, ez->max_q, &ez->m_cigar, &ez->n_cigar, &ez->cigar);
kfree(km, mem2); kfree(km, off);
}
}
#endif // __SSE2__
-284
View File
@@ -1,284 +0,0 @@
#include <string.h>
#include "ksw2.h"
#ifdef __SSE2__
#include <emmintrin.h>
#ifdef __SSE4_1__
#include <smmintrin.h>
#endif
void ksw_extz2_sse(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 flag, ksw_extz_t *ez)
{
#define __dp_code_block1 \
z = _mm_add_epi8(_mm_load_si128(&s[t]), qe2_); \
xt1 = _mm_load_si128(&x[t]); /* xt1 <- x[r-1][t..t+15] */ \
tmp = _mm_srli_si128(xt1, 15); /* tmp <- x[r-1][t+15] */ \
xt1 = _mm_or_si128(_mm_slli_si128(xt1, 1), x1_); /* xt1 <- x[r-1][t-1..t+14] */ \
x1_ = tmp; \
vt1 = _mm_load_si128(&v[t]); /* vt1 <- v[r-1][t..t+15] */ \
tmp = _mm_srli_si128(vt1, 15); /* tmp <- v[r-1][t+15] */ \
vt1 = _mm_or_si128(_mm_slli_si128(vt1, 1), v1_); /* vt1 <- v[r-1][t-1..t+14] */ \
v1_ = tmp; \
a = _mm_add_epi8(xt1, vt1); /* a <- x[r-1][t-1..t+14] + v[r-1][t-1..t+14] */ \
ut = _mm_load_si128(&u[t]); /* ut <- u[t..t+15] */ \
b = _mm_add_epi8(_mm_load_si128(&y[t]), ut); /* b <- y[r-1][t..t+15] + u[r-1][t..t+15] */
#define __dp_code_block2 \
z = _mm_max_epu8(z, b); /* z = max(z, b); this works because both are non-negative */ \
z = _mm_min_epu8(z, max_sc_); \
_mm_store_si128(&u[t], _mm_sub_epi8(z, vt1)); /* u[r][t..t+15] <- z - v[r-1][t-1..t+14] */ \
_mm_store_si128(&v[t], _mm_sub_epi8(z, ut)); /* v[r][t..t+15] <- z - u[r-1][t..t+15] */ \
z = _mm_sub_epi8(z, q_); \
a = _mm_sub_epi8(a, z); \
b = _mm_sub_epi8(b, z);
int r, t, qe = q + e, n_col_, *off = 0, *off_end = 0, tlen_, qlen_, last_st, last_en, wl, wr, max_sc, min_sc;
int with_cigar = !(flag&KSW_EZ_SCORE_ONLY), approx_max = !!(flag&KSW_EZ_APPROX_MAX);
int32_t *H = 0, H0 = 0, last_H0_t = 0;
uint8_t *qr, *sf, *mem, *mem2 = 0;
__m128i q_, qe2_, zero_, flag1_, flag2_, flag8_, flag16_, sc_mch_, sc_mis_, m1_, max_sc_;
__m128i *u, *v, *x, *y, *s, *p = 0;
ksw_reset_extz(ez);
if (m <= 0 || qlen <= 0 || tlen <= 0) return;
zero_ = _mm_set1_epi8(0);
q_ = _mm_set1_epi8(q);
qe2_ = _mm_set1_epi8((q + e) * 2);
flag1_ = _mm_set1_epi8(1);
flag2_ = _mm_set1_epi8(2);
flag8_ = _mm_set1_epi8(0x08);
flag16_ = _mm_set1_epi8(0x10);
sc_mch_ = _mm_set1_epi8(mat[0]);
sc_mis_ = _mm_set1_epi8(mat[1]);
m1_ = _mm_set1_epi8(m - 1); // wildcard
max_sc_ = _mm_set1_epi8(mat[0] + (q + e) * 2);
if (w < 0) w = tlen > qlen? tlen : qlen;
wl = wr = w;
tlen_ = (tlen + 15) / 16;
n_col_ = ((w + 1 < tlen? (w + 1 < qlen? w + 1 : qlen): tlen) + 15) / 16 + 1;
qlen_ = (qlen + 15) / 16;
for (t = 1, max_sc = mat[0], min_sc = mat[1]; t < m * m; ++t) {
max_sc = max_sc > mat[t]? max_sc : mat[t];
min_sc = min_sc < mat[t]? min_sc : mat[t];
}
if (-min_sc > 2 * (q + e)) return; // otherwise, we won't see any mismatches
mem = (uint8_t*)kcalloc(km, tlen_ * 6 + qlen_ + 1, 16);
u = (__m128i*)(((size_t)mem + 15) >> 4 << 4); // 16-byte aligned
v = u + tlen_, x = v + tlen_, y = x + tlen_, s = y + tlen_, sf = (uint8_t*)(s + tlen_), qr = sf + tlen_ * 16;
if (!approx_max) {
H = (int32_t*)kmalloc(km, tlen_ * 16 * 4);
for (t = 0; t < tlen_ * 16; ++t) H[t] = KSW_NEG_INF;
}
if (with_cigar) {
mem2 = (uint8_t*)kmalloc(km, ((qlen + tlen - 1) * n_col_ + 1) * 16);
p = (__m128i*)(((size_t)mem2 + 15) >> 4 << 4);
off = (int*)kmalloc(km, (qlen + tlen - 1) * sizeof(int) * 2);
off_end = off + qlen + tlen - 1;
}
for (t = 0; t < qlen; ++t) qr[t] = query[qlen - 1 - t];
memcpy(sf, target, tlen);
for (r = 0, last_st = last_en = -1; r < qlen + tlen - 1; ++r) {
int st = 0, en = tlen - 1, st0, en0, st_, en_;
int8_t x1, v1;
uint8_t *qrr = qr + (qlen - 1 - r), *u8 = (uint8_t*)u, *v8 = (uint8_t*)v;
__m128i x1_, v1_;
// find the boundaries
if (st < r - qlen + 1) st = r - qlen + 1;
if (en > r) en = r;
if (st < (r-wr+1)>>1) st = (r-wr+1)>>1; // take the ceil
if (en > (r+wl)>>1) en = (r+wl)>>1; // take the floor
if (st > en) {
ez->zdropped = 1;
break;
}
st0 = st, en0 = en;
st = st / 16 * 16, en = (en + 16) / 16 * 16 - 1;
// set boundary conditions
if (st > 0) {
if (st - 1 >= last_st && st - 1 <= last_en)
x1 = ((uint8_t*)x)[st - 1], v1 = v8[st - 1]; // (r-1,s-1) calculated in the last round
else x1 = v1 = 0; // not calculated; set to zeros
} else x1 = 0, v1 = r? q : 0;
if (en >= r) ((uint8_t*)y)[r] = 0, u8[r] = r? q : 0;
// loop fission: set scores first
if (!(flag & KSW_EZ_GENERIC_SC)) {
for (t = st0; t <= en0; t += 16) {
__m128i sq, st, tmp, mask;
sq = _mm_loadu_si128((__m128i*)&sf[t]);
st = _mm_loadu_si128((__m128i*)&qrr[t]);
mask = _mm_or_si128(_mm_cmpeq_epi8(sq, m1_), _mm_cmpeq_epi8(st, m1_));
tmp = _mm_cmpeq_epi8(sq, st);
#ifdef __SSE4_1__
tmp = _mm_blendv_epi8(sc_mis_, sc_mch_, tmp);
#else
tmp = _mm_or_si128(_mm_andnot_si128(tmp, sc_mis_), _mm_and_si128(tmp, sc_mch_));
#endif
tmp = _mm_andnot_si128(mask, tmp);
_mm_storeu_si128((__m128i*)((uint8_t*)s + t), tmp);
}
} else {
for (t = st0; t <= en0; ++t)
((uint8_t*)s)[t] = mat[sf[t] * m + qrr[t]];
}
// core loop
x1_ = _mm_cvtsi32_si128(x1);
v1_ = _mm_cvtsi32_si128(v1);
st_ = st / 16, en_ = en / 16;
if (!with_cigar) { // score only
for (t = st_; t <= en_; ++t) {
__m128i z, a, b, xt1, vt1, ut, tmp;
__dp_code_block1;
#ifdef __SSE4_1__
z = _mm_max_epi8(z, a); // z = z > a? z : a (signed)
#else // we need to emulate SSE4.1 intrinsics _mm_max_epi8()
z = _mm_and_si128(z, _mm_cmpgt_epi8(z, zero_)); // z = z > 0? z : 0;
z = _mm_max_epu8(z, a); // z = max(z, a); this works because both are non-negative
#endif
__dp_code_block2;
#ifdef __SSE4_1__
_mm_store_si128(&x[t], _mm_max_epi8(a, zero_));
_mm_store_si128(&y[t], _mm_max_epi8(b, zero_));
#else
tmp = _mm_cmpgt_epi8(a, zero_);
_mm_store_si128(&x[t], _mm_and_si128(a, tmp));
tmp = _mm_cmpgt_epi8(b, zero_);
_mm_store_si128(&y[t], _mm_and_si128(b, tmp));
#endif
}
} else if (!(flag&KSW_EZ_RIGHT)) { // gap left-alignment
__m128i *pr = p + r * n_col_ - st_;
off[r] = st, off_end[r] = en;
for (t = st_; t <= en_; ++t) {
__m128i d, z, a, b, xt1, vt1, ut, tmp;
__dp_code_block1;
d = _mm_and_si128(_mm_cmpgt_epi8(a, z), flag1_); // d = a > z? 1 : 0
#ifdef __SSE4_1__
z = _mm_max_epi8(z, a); // z = z > a? z : a (signed)
tmp = _mm_cmpgt_epi8(b, z);
d = _mm_blendv_epi8(d, flag2_, tmp); // d = b > z? 2 : d
#else // we need to emulate SSE4.1 intrinsics _mm_max_epi8() and _mm_blendv_epi8()
z = _mm_and_si128(z, _mm_cmpgt_epi8(z, zero_)); // z = z > 0? z : 0;
z = _mm_max_epu8(z, a); // z = max(z, a); this works because both are non-negative
tmp = _mm_cmpgt_epi8(b, z);
d = _mm_or_si128(_mm_andnot_si128(tmp, d), _mm_and_si128(tmp, flag2_)); // d = b > z? 2 : d; emulating blendv
#endif
__dp_code_block2;
tmp = _mm_cmpgt_epi8(a, zero_);
_mm_store_si128(&x[t], _mm_and_si128(tmp, a));
d = _mm_or_si128(d, _mm_and_si128(tmp, flag8_)); // d = a > 0? 0x08 : 0
tmp = _mm_cmpgt_epi8(b, zero_);
_mm_store_si128(&y[t], _mm_and_si128(tmp, b));
d = _mm_or_si128(d, _mm_and_si128(tmp, flag16_)); // d = b > 0? 0x10 : 0
_mm_store_si128(&pr[t], d);
}
} else { // gap right-alignment
__m128i *pr = p + r * n_col_ - st_;
off[r] = st, off_end[r] = en;
for (t = st_; t <= en_; ++t) {
__m128i d, z, a, b, xt1, vt1, ut, tmp;
__dp_code_block1;
d = _mm_andnot_si128(_mm_cmpgt_epi8(z, a), flag1_); // d = z > a? 0 : 1
#ifdef __SSE4_1__
z = _mm_max_epi8(z, a); // z = z > a? z : a (signed)
tmp = _mm_cmpgt_epi8(z, b);
d = _mm_blendv_epi8(flag2_, d, tmp); // d = z > b? d : 2
#else // we need to emulate SSE4.1 intrinsics _mm_max_epi8() and _mm_blendv_epi8()
z = _mm_and_si128(z, _mm_cmpgt_epi8(z, zero_)); // z = z > 0? z : 0;
z = _mm_max_epu8(z, a); // z = max(z, a); this works because both are non-negative
tmp = _mm_cmpgt_epi8(z, b);
d = _mm_or_si128(_mm_andnot_si128(tmp, flag2_), _mm_and_si128(tmp, d)); // d = z > b? d : 2; emulating blendv
#endif
__dp_code_block2;
tmp = _mm_cmpgt_epi8(zero_, a);
_mm_store_si128(&x[t], _mm_andnot_si128(tmp, a));
d = _mm_or_si128(d, _mm_andnot_si128(tmp, flag8_)); // d = 0 > a? 0 : 0x08
tmp = _mm_cmpgt_epi8(zero_, b);
_mm_store_si128(&y[t], _mm_andnot_si128(tmp, b));
d = _mm_or_si128(d, _mm_andnot_si128(tmp, flag16_)); // d = 0 > b? 0 : 0x10
_mm_store_si128(&pr[t], d);
}
}
if (!approx_max) { // find the exact max with a 32-bit score array
int32_t max_H, max_t;
// compute H[], max_H and max_t
if (r > 0) {
int32_t HH[4], tt[4], en1 = st0 + (en0 - st0) / 4 * 4, i;
__m128i max_H_, max_t_, qe_;
max_H = H[en0] = en0 > 0? H[en0-1] + u8[en0] - qe : H[en0] + v8[en0] - qe; // special casing the last element
max_t = en0;
max_H_ = _mm_set1_epi32(max_H);
max_t_ = _mm_set1_epi32(max_t);
qe_ = _mm_set1_epi32(q + e);
for (t = st0; t < en1; t += 4) { // this implements: H[t]+=v8[t]-qe; if(H[t]>max_H) max_H=H[t],max_t=t;
__m128i H1, tmp, t_;
H1 = _mm_loadu_si128((__m128i*)&H[t]);
t_ = _mm_setr_epi32(v8[t], v8[t+1], v8[t+2], v8[t+3]);
H1 = _mm_add_epi32(H1, t_);
H1 = _mm_sub_epi32(H1, qe_);
_mm_storeu_si128((__m128i*)&H[t], H1);
t_ = _mm_set1_epi32(t);
tmp = _mm_cmpgt_epi32(H1, max_H_);
#ifdef __SSE4_1__
max_H_ = _mm_blendv_epi8(max_H_, H1, tmp);
max_t_ = _mm_blendv_epi8(max_t_, t_, tmp);
#else
max_H_ = _mm_or_si128(_mm_and_si128(tmp, H1), _mm_andnot_si128(tmp, max_H_));
max_t_ = _mm_or_si128(_mm_and_si128(tmp, t_), _mm_andnot_si128(tmp, max_t_));
#endif
}
_mm_storeu_si128((__m128i*)HH, max_H_);
_mm_storeu_si128((__m128i*)tt, max_t_);
for (i = 0; i < 4; ++i)
if (max_H < HH[i]) max_H = HH[i], max_t = tt[i] + i;
for (; t < en0; ++t) { // for the rest of values that haven't been computed with SSE
H[t] += (int32_t)v8[t] - qe;
if (H[t] > max_H)
max_H = H[t], max_t = t;
}
} else H[0] = v8[0] - qe - qe, max_H = H[0], max_t = 0; // special casing r==0
// update ez
if (en0 == tlen - 1 && H[en0] > ez->mte)
ez->mte = H[en0], ez->mte_q = r - en;
if (r - st0 == qlen - 1 && H[st0] > ez->mqe)
ez->mqe = H[st0], ez->mqe_t = st0;
if (ksw_apply_zdrop(ez, 1, max_H, r, max_t, zdrop, e)) break;
if (r == qlen + tlen - 2 && en0 == tlen - 1)
ez->score = H[tlen - 1];
} else { // find approximate max; Z-drop might be inaccurate, too.
if (r > 0) {
if (last_H0_t >= st0 && last_H0_t <= en0 && last_H0_t + 1 >= st0 && last_H0_t + 1 <= en0) {
int32_t d0 = v8[last_H0_t] - qe;
int32_t d1 = u8[last_H0_t + 1] - qe;
if (d0 > d1) H0 += d0;
else H0 += d1, ++last_H0_t;
} else if (last_H0_t >= st0 && last_H0_t <= en0) {
H0 += v8[last_H0_t] - qe;
} else {
++last_H0_t, H0 += u8[last_H0_t] - qe;
}
if ((flag & KSW_EZ_APPROX_DROP) && ksw_apply_zdrop(ez, 1, H0, r, last_H0_t, zdrop, e)) break;
} else H0 = v8[0] - qe - qe, last_H0_t = 0;
if (r == qlen + tlen - 2 && en0 == tlen - 1)
ez->score = H0;
}
last_st = st, last_en = en;
//for (t = st0; t <= en0; ++t) printf("(%d,%d)\t(%d,%d,%d,%d)\t%d\n", r, t, ((int8_t*)u)[t], ((int8_t*)v)[t], ((int8_t*)x)[t], ((int8_t*)y)[t], H[t]); // for debugging
}
kfree(km, mem);
if (!approx_max) kfree(km, H);
if (with_cigar) { // backtrack
int rev_cigar = !!(flag & KSW_EZ_REV_CIGAR);
if (!ez->zdropped && !(flag&KSW_EZ_EXTZ_ONLY))
ksw_backtrack(km, 1, rev_cigar, (uint8_t*)p, off, off_end, n_col_*16, tlen-1, qlen-1, &ez->m_cigar, &ez->n_cigar, &ez->cigar);
else if (ez->max_t >= 0 && ez->max_q >= 0)
ksw_backtrack(km, 1, rev_cigar, (uint8_t*)p, off, off_end, n_col_*16, ez->max_t, ez->max_q, &ez->m_cigar, &ez->n_cigar, &ez->cigar);
kfree(km, mem2); kfree(km, off);
}
}
#endif // __SSE2__
-147
View File
@@ -1,147 +0,0 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <emmintrin.h>
#include "ksw2.h"
#ifdef __GNUC__
#define LIKELY(x) __builtin_expect((x),1)
#define UNLIKELY(x) __builtin_expect((x),0)
#else
#define LIKELY(x) (x)
#define UNLIKELY(x) (x)
#endif
typedef struct {
int qlen, slen;
uint8_t shift, mdiff, max, size;
__m128i *qp, *H0, *H1, *E, *Hmax;
} kswq_t;
/**
* Initialize the query data structure
*
* @param size Number of bytes used to store a score; valid valures are 1 or 2
* @param qlen Length of the query sequence
* @param query Query sequence
* @param m Size of the alphabet
* @param mat Scoring matrix in a one-dimension array
*
* @return Query data structure
*/
void *ksw_ll_qinit(void *km, int size, int qlen, const uint8_t *query, int m, const int8_t *mat)
{
kswq_t *q;
int slen, a, tmp, p;
size = size > 1? 2 : 1;
p = 8 * (3 - size); // # values per __m128i
slen = (qlen + p - 1) / p; // segmented length
q = (kswq_t*)kmalloc(km, sizeof(kswq_t) + 256 + 16 * slen * (m + 4)); // a single block of memory
q->qp = (__m128i*)(((size_t)q + sizeof(kswq_t) + 15) >> 4 << 4); // align memory
q->H0 = q->qp + slen * m;
q->H1 = q->H0 + slen;
q->E = q->H1 + slen;
q->Hmax = q->E + slen;
q->slen = slen; q->qlen = qlen; q->size = size;
// compute shift
tmp = m * m;
for (a = 0, q->shift = 127, q->mdiff = 0; a < tmp; ++a) { // find the minimum and maximum score
if (mat[a] < (int8_t)q->shift) q->shift = mat[a];
if (mat[a] > (int8_t)q->mdiff) q->mdiff = mat[a];
}
q->max = q->mdiff;
q->shift = 256 - q->shift; // NB: q->shift is uint8_t
q->mdiff += q->shift; // this is the difference between the min and max scores
// An example: p=8, qlen=19, slen=3 and segmentation:
// {{0,3,6,9,12,15,18,-1},{1,4,7,10,13,16,-1,-1},{2,5,8,11,14,17,-1,-1}}
if (size == 1) {
int8_t *t = (int8_t*)q->qp;
for (a = 0; a < m; ++a) {
int i, k, nlen = slen * p;
const int8_t *ma = mat + a * m;
for (i = 0; i < slen; ++i)
for (k = i; k < nlen; k += slen) // p iterations
*t++ = (k >= qlen? 0 : ma[query[k]]) + q->shift;
}
} else {
int16_t *t = (int16_t*)q->qp;
for (a = 0; a < m; ++a) {
int i, k, nlen = slen * p;
const int8_t *ma = mat + a * m;
for (i = 0; i < slen; ++i)
for (k = i; k < nlen; k += slen) // p iterations
*t++ = (k >= qlen? 0 : ma[query[k]]);
}
}
return q;
}
int ksw_ll_i16(void *q_, int tlen, const uint8_t *target, int _gapo, int _gape, int *qe, int *te)
{
kswq_t *q = (kswq_t*)q_;
int slen, i, gmax = 0, qlen8;
__m128i zero, gapoe, gape, *H0, *H1, *E, *Hmax;
uint16_t *H8;
#define __max_8(ret, xx) do { \
(xx) = _mm_max_epi16((xx), _mm_srli_si128((xx), 8)); \
(xx) = _mm_max_epi16((xx), _mm_srli_si128((xx), 4)); \
(xx) = _mm_max_epi16((xx), _mm_srli_si128((xx), 2)); \
(ret) = _mm_extract_epi16((xx), 0); \
} while (0)
// initialization
*qe = *te = -1;
zero = _mm_set1_epi32(0);
gapoe = _mm_set1_epi16(_gapo + _gape);
gape = _mm_set1_epi16(_gape);
H0 = q->H0; H1 = q->H1; E = q->E; Hmax = q->Hmax;
slen = q->slen, qlen8 = slen * 8;
memset(E, 0, slen * sizeof(__m128i));
memset(H0, 0, slen * sizeof(__m128i));
memset(Hmax, 0, slen * sizeof(__m128i));
// the core loop
for (i = 0; i < tlen; ++i) {
int j, k, imax;
__m128i e, h, f = zero, max = zero, *S = q->qp + target[i] * slen; // s is the 1st score vector
h = _mm_load_si128(H0 + slen - 1); // h={2,5,8,11,14,17,-1,-1} in the above example
h = _mm_slli_si128(h, 2);
for (j = 0; LIKELY(j < slen); ++j) {
h = _mm_adds_epi16(h, *S++);
e = _mm_load_si128(E + j);
h = _mm_max_epi16(h, e);
h = _mm_max_epi16(h, f);
max = _mm_max_epi16(max, h);
_mm_store_si128(H1 + j, h);
h = _mm_subs_epu16(h, gapoe);
e = _mm_subs_epu16(e, gape);
e = _mm_max_epi16(e, h);
_mm_store_si128(E + j, e);
f = _mm_subs_epu16(f, gape);
f = _mm_max_epi16(f, h);
h = _mm_load_si128(H0 + j);
}
for (k = 0; LIKELY(k < 16); ++k) {
f = _mm_slli_si128(f, 2);
for (j = 0; LIKELY(j < slen); ++j) {
h = _mm_load_si128(H1 + j);
h = _mm_max_epi16(h, f);
_mm_store_si128(H1 + j, h);
h = _mm_subs_epu16(h, gapoe);
f = _mm_subs_epu16(f, gape);
if(UNLIKELY(!_mm_movemask_epi8(_mm_cmpgt_epi16(f, h)))) goto end_loop_i16;
}
}
end_loop_i16:
__max_8(imax, max);
if (imax >= gmax) {
gmax = imax; *te = i;
memcpy(Hmax, H1, slen * sizeof(__m128i));
}
S = H1; H1 = H0; H0 = S;
}
for (i = 0, H8 = (uint16_t*)Hmax; i < qlen8; ++i)
if ((int)H8[i] == gmax) *qe = i / 8 + i % 8 * slen;
return gmax;
}
-151
View File
@@ -1,151 +0,0 @@
#include <pthread.h>
#include <stdlib.h>
#include <limits.h>
/************
* kt_for() *
************/
struct kt_for_t;
typedef struct {
struct kt_for_t *t;
long i;
} ktf_worker_t;
typedef struct kt_for_t {
int n_threads;
long n;
ktf_worker_t *w;
void (*func)(void*,long,int);
void *data;
} kt_for_t;
static inline long steal_work(kt_for_t *t)
{
int i, min_i = -1;
long k, min = LONG_MAX;
for (i = 0; i < t->n_threads; ++i)
if (min > t->w[i].i) min = t->w[i].i, min_i = i;
k = __sync_fetch_and_add(&t->w[min_i].i, t->n_threads);
return k >= t->n? -1 : k;
}
static void *ktf_worker(void *data)
{
ktf_worker_t *w = (ktf_worker_t*)data;
long i;
for (;;) {
i = __sync_fetch_and_add(&w->i, w->t->n_threads);
if (i >= w->t->n) break;
w->t->func(w->t->data, i, w - w->t->w);
}
while ((i = steal_work(w->t)) >= 0)
w->t->func(w->t->data, i, w - w->t->w);
pthread_exit(0);
}
void kt_for(int n_threads, void (*func)(void*,long,int), void *data, long n)
{
if (n_threads > 1) {
int i;
kt_for_t t;
pthread_t *tid;
t.func = func, t.data = data, t.n_threads = n_threads, t.n = n;
t.w = (ktf_worker_t*)alloca(n_threads * sizeof(ktf_worker_t));
tid = (pthread_t*)alloca(n_threads * sizeof(pthread_t));
for (i = 0; i < n_threads; ++i)
t.w[i].t = &t, t.w[i].i = i;
for (i = 0; i < n_threads; ++i) pthread_create(&tid[i], 0, ktf_worker, &t.w[i]);
for (i = 0; i < n_threads; ++i) pthread_join(tid[i], 0);
} else {
long j;
for (j = 0; j < n; ++j) func(data, j, 0);
}
}
/*****************
* kt_pipeline() *
*****************/
struct ktp_t;
typedef struct {
struct ktp_t *pl;
int64_t index;
int step;
void *data;
} ktp_worker_t;
typedef struct ktp_t {
void *shared;
void *(*func)(void*, int, void*);
int64_t index;
int n_workers, n_steps;
ktp_worker_t *workers;
pthread_mutex_t mutex;
pthread_cond_t cv;
} ktp_t;
static void *ktp_worker(void *data)
{
ktp_worker_t *w = (ktp_worker_t*)data;
ktp_t *p = w->pl;
while (w->step < p->n_steps) {
// test whether we can kick off the job with this worker
pthread_mutex_lock(&p->mutex);
for (;;) {
int i;
// test whether another worker is doing the same step
for (i = 0; i < p->n_workers; ++i) {
if (w == &p->workers[i]) continue; // ignore itself
if (p->workers[i].step <= w->step && p->workers[i].index < w->index)
break;
}
if (i == p->n_workers) break; // no workers with smaller indices are doing w->step or the previous steps
pthread_cond_wait(&p->cv, &p->mutex);
}
pthread_mutex_unlock(&p->mutex);
// working on w->step
w->data = p->func(p->shared, w->step, w->step? w->data : 0); // for the first step, input is NULL
// update step and let other workers know
pthread_mutex_lock(&p->mutex);
w->step = w->step == p->n_steps - 1 || w->data? (w->step + 1) % p->n_steps : p->n_steps;
if (w->step == 0) w->index = p->index++;
pthread_cond_broadcast(&p->cv);
pthread_mutex_unlock(&p->mutex);
}
pthread_exit(0);
}
void kt_pipeline(int n_threads, void *(*func)(void*, int, void*), void *shared_data, int n_steps)
{
ktp_t aux;
pthread_t *tid;
int i;
if (n_threads < 1) n_threads = 1;
aux.n_workers = n_threads;
aux.n_steps = n_steps;
aux.func = func;
aux.shared = shared_data;
aux.index = 0;
pthread_mutex_init(&aux.mutex, 0);
pthread_cond_init(&aux.cv, 0);
aux.workers = (ktp_worker_t*)alloca(n_threads * sizeof(ktp_worker_t));
for (i = 0; i < n_threads; ++i) {
ktp_worker_t *w = &aux.workers[i];
w->step = 0; w->pl = &aux; w->data = 0;
w->index = aux.index++;
}
tid = (pthread_t*)alloca(n_threads * sizeof(pthread_t));
for (i = 0; i < n_threads; ++i) pthread_create(&tid[i], 0, ktp_worker, &aux.workers[i]);
for (i = 0; i < n_threads; ++i) pthread_join(tid[i], 0);
pthread_mutex_destroy(&aux.mutex);
pthread_cond_destroy(&aux.cv);
}
-15
View File
@@ -1,15 +0,0 @@
#ifndef KTHREAD_H
#define KTHREAD_H
#ifdef __cplusplus
extern "C" {
#endif
void kt_for(int n_threads, void (*func)(void*,long,int), void *data, long n);
void kt_pipeline(int n_threads, void *(*func)(void*, int, void*), void *shared_data, int n_steps);
#ifdef __cplusplus
}
#endif
#endif
-105
View File
@@ -1,105 +0,0 @@
/* The MIT License
Copyright (c) 2008, by Attractive Chaos <attractor@live.co.uk>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
An example:
#include "kvec.h"
int main() {
kvec_t(int) array;
kv_init(array);
kv_push(int, array, 10); // append
kv_a(int, array, 20) = 5; // dynamic
kv_A(array, 20) = 4; // static
kv_destroy(array);
return 0;
}
*/
/*
2008-09-22 (0.1.0):
* The initial version.
*/
#ifndef AC_KVEC_H
#define AC_KVEC_H
#include <stdlib.h>
#include "kalloc.h"
#define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
#define kvec_t(type) struct { size_t n, m; type *a; }
#define kv_init(v) ((v).n = (v).m = 0, (v).a = 0)
#define kv_destroy(v) free((v).a)
#define kv_A(v, i) ((v).a[(i)])
#define kv_pop(v) ((v).a[--(v).n])
#define kv_size(v) ((v).n)
#define kv_max(v) ((v).m)
#define kv_resize(type, km, v, s) do { \
if ((v).m < (s)) { \
(v).m = (s); \
kv_roundup32((v).m); \
(v).a = (type*)krealloc((km), (v).a, sizeof(type) * (v).m); \
} \
} while (0)
#define kv_copy(type, km, v1, v0) do { \
if ((v1).m < (v0).n) kv_resize(type, (km), (v1), (v0).n); \
(v1).n = (v0).n; \
memcpy((v1).a, (v0).a, sizeof(type) * (v0).n); \
} while (0) \
#define kv_push(type, km, v, x) do { \
if ((v).n == (v).m) { \
(v).m = (v).m? (v).m<<1 : 2; \
(v).a = (type*)krealloc((km), (v).a, sizeof(type) * (v).m); \
} \
(v).a[(v).n++] = (x); \
} while (0)
#define kv_pushp(type, km, v, p) do { \
if ((v).n == (v).m) { \
(v).m = (v).m? (v).m<<1 : 2; \
(v).a = (type*)krealloc((km), (v).a, sizeof(type) * (v).m); \
} \
*(p) = &(v).a[(v).n++]; \
} while (0)
#define kv_reverse(type, v, start) do { \
if ((v).m > 0 && (v).n > (start)) { \
size_t __i, __end = (v).n - (start); \
type *__a = (v).a + (start); \
for (__i = 0; __i < __end>>1; ++__i) { \
type __t = __a[__end - 1 - __i]; \
__a[__end - 1 - __i] = __a[__i]; __a[__i] = __t; \
} \
} \
} while (0)
#endif
-228
View File
@@ -1,228 +0,0 @@
#include <getopt.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/time.h>
#include "bseq.h"
#include "minimap.h"
#include "mmpriv.h"
#define MM_VERSION "2.0rc1-r232"
void liftrlimit()
{
#ifdef __linux__
struct rlimit r;
getrlimit(RLIMIT_AS, &r);
r.rlim_cur = r.rlim_max;
setrlimit(RLIMIT_AS, &r);
#endif
}
static struct option long_options[] = {
{ "bucket-bits", required_argument, 0, 0 },
{ "mb-size", required_argument, 0, 'K' },
{ "int-rname", no_argument, 0, 0 },
{ "no-kalloc", no_argument, 0, 0 },
{ "print-qname", no_argument, 0, 0 },
{ "no-self", no_argument, 0, 0 },
{ "print-seed", no_argument, 0, 0 },
{ "max-chain-skip", required_argument, 0, 0 },
{ "min-dp-len", required_argument, 0, 0 },
{ "print-aln-seq", no_argument, 0, 0 },
{ "version", no_argument, 0, 'V' },
{ "min-count", required_argument, 0, 'n' },
{ "min-chain-score",required_argument, 0, 'm' },
{ "mask-level", required_argument, 0, 'M' },
{ "min-dp-score", required_argument, 0, 's' },
{ "sam", no_argument, 0, 'a' },
{ 0, 0, 0, 0}
};
int main(int argc, char *argv[])
{
mm_mapopt_t opt;
int i, c, k = 15, w = -1, bucket_bits = MM_IDX_DEF_B, n_threads = 3, keep_name = 1, is_idx, is_hpc = 0, long_idx, idx_par_set = 0;
int minibatch_size = 200000000;
uint64_t batch_size = 4000000000ULL;
mm_bseq_file_t *fp = 0;
char *fnw = 0, *s;
FILE *fpr = 0, *fpw = 0;
liftrlimit();
mm_realtime0 = realtime();
mm_mapopt_init(&opt);
while ((c = getopt_long(argc, argv, "aw:k:K:t:r:f:Vv:g:I:d:XT:s:x:Hcp:M:n:z:A:B:O:E:m:N:Q", long_options, &long_idx)) >= 0) {
if (c == 'w') w = atoi(optarg), idx_par_set = 1;
else if (c == 'k') k = atoi(optarg), idx_par_set = 1;
else if (c == 'H') is_hpc = 1, idx_par_set = 1;
else if (c == 'd') fnw = optarg; // the above are indexing related options, except -I
else if (c == 'r') opt.bw = atoi(optarg);
else if (c == 'f') opt.mid_occ_frac = atof(optarg);
else if (c == 't') n_threads = atoi(optarg);
else if (c == 'v') mm_verbose = atoi(optarg);
else if (c == 'g') opt.max_gap = atoi(optarg);
else if (c == 'N') opt.best_n = atoi(optarg);
else if (c == 'p') opt.pri_ratio = atof(optarg);
else if (c == 'M') opt.mask_level = atof(optarg);
else if (c == 'c') opt.flag |= MM_F_CIGAR;
else if (c == 'X') opt.flag |= MM_F_AVA | MM_F_NO_SELF;
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 == 'T') opt.sdust_thres = atoi(optarg);
else if (c == 'n') opt.min_cnt = atoi(optarg);
else if (c == 'm') opt.min_chain_score = atoi(optarg);
else if (c == 'A') opt.a = atoi(optarg);
else if (c == 'B') opt.b = atoi(optarg);
else if (c == 'z') opt.zdrop = atoi(optarg);
else if (c == 's') opt.min_dp_max = atoi(optarg);
else if (c == 0 && long_idx == 0) bucket_bits = atoi(optarg); // --bucket-bits
else if (c == 0 && long_idx == 2) keep_name = 0; // --int-rname
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 == 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; // --print-seed
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 == 9) mm_dbg_flag |= MM_DBG_PRINT_QNAME | MM_DBG_PRINT_ALN_SEQ; // --print-aln-seq
else if (c == 'V') {
puts(MM_VERSION);
return 0;
} else if (c == 'O') {
opt.q = opt.q2 = strtol(optarg, &s, 10);
if (*s == ',') opt.q2 = strtol(s + 1, &s, 10);
} else if (c == 'E') {
opt.e = opt.e2 = strtol(optarg, &s, 10);
if (*s == ',') opt.e2 = strtol(s + 1, &s, 10);
} else if (c == 'I' || c == 'K') {
double x;
char *p;
x = strtod(optarg, &p);
if (*p == 'G' || *p == 'g') x *= 1e9;
else if (*p == 'M' || *p == 'm') x *= 1e6;
else if (*p == 'K' || *p == 'k') x *= 1e3;
if (c == 'I') batch_size = (uint64_t)(x + .499);
else minibatch_size = (uint64_t)(x + .499);
} else if (c == 'x') {
if (strcmp(optarg, "ava-ont") == 0) {
opt.flag |= MM_F_AVA | MM_F_NO_SELF;
opt.min_chain_score = 100, opt.pri_ratio = 0.0f, opt.max_gap = 10000, opt.max_chain_skip = 25;
minibatch_size = 500000000;
k = 15, w = 5;
} else if (strcmp(optarg, "ava-pb") == 0) {
opt.flag |= MM_F_AVA | MM_F_NO_SELF;
opt.min_chain_score = 100, opt.pri_ratio = 0.0f, opt.max_gap = 10000, opt.max_chain_skip = 25;
minibatch_size = 500000000;
is_hpc = 1, k = 19, w = 5;
} else if (strcmp(optarg, "map10k") == 0 || strcmp(optarg, "map-pb") == 0) {
is_hpc = 1, k = 19;
} else if (strcmp(optarg, "map-ont") == 0) {
is_hpc = 0, k = 15;
} else if (strcmp(optarg, "asm5") == 0) {
k = 19, w = 19;
opt.a = 1, opt.b = 19, opt.q = 39, opt.q2 = 81, opt.e = 3, opt.e2 = 1, opt.zdrop = 200;
opt.min_dp_max = 200;
} else if (strcmp(optarg, "asm10") == 0) {
k = 19, w = 19;
opt.a = 1, opt.b = 9, opt.q = 16, opt.q2 = 41, opt.e = 2, opt.e2 = 1, opt.zdrop = 200;
opt.min_dp_max = 200;
} else {
fprintf(stderr, "[E::%s] unknown preset '%s'\n", __func__, optarg);
return 1;
}
}
}
if (w < 0) w = (int)(.6666667 * k + .499);
if (argc == optind) {
fprintf(stderr, "Usage: minimap2 [options] <target.fa>|<target.idx> [query.fa] [...]\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, " Indexing:\n");
fprintf(stderr, " -H use homopolymer-compressed k-mer\n");
fprintf(stderr, " -k INT k-mer size (no larger than 28) [%d]\n", k);
fprintf(stderr, " -w INT minizer window size [{-k}*2/3]\n");
fprintf(stderr, " -I NUM split index for every ~NUM input bases [4G]\n");
fprintf(stderr, " -d FILE dump index to FILE []\n");
fprintf(stderr, " Mapping:\n");
fprintf(stderr, " -f FLOAT filter out top FLOAT fraction of repetitive minimizers [%g]\n", opt.mid_occ_frac);
fprintf(stderr, " -g INT stop chain enlongation if there are no minimizers in INT-bp [%d]\n", opt.max_gap);
fprintf(stderr, " -r INT bandwidth used in chaining and DP-based alignment [%d]\n", opt.bw);
fprintf(stderr, " -n INT minimal number of minimizers on a chain [%d]\n", opt.min_cnt);
fprintf(stderr, " -m INT minimal chaining score (matching bases minus log gap penalty) [%d]\n", opt.min_chain_score);
// fprintf(stderr, " -T INT SDUST threshold; 0 to disable SDUST [%d]\n", opt.sdust_thres); // TODO: this option is never used; might be buggy
fprintf(stderr, " -X skip self and dual mappings (for the all-vs-all mode)\n");
fprintf(stderr, " -p FLOAT min secondary-to-primary score ratio [%g]\n", opt.pri_ratio);
fprintf(stderr, " -N INT retain at most INT secondary alignments [%d]\n", opt.best_n);
fprintf(stderr, " Alignment:\n");
fprintf(stderr, " -A INT matching score [%d]\n", opt.a);
fprintf(stderr, " -B INT mismatch penalty [%d]\n", opt.b);
fprintf(stderr, " -O INT[,INT] gap open penalty [%d,%d]\n", opt.q, opt.q2);
fprintf(stderr, " -E INT[,INT] gap extension penalty; a k-long gap costs min{O1+k*E1,O2+k*E2} [%d,%d]\n", opt.e, opt.e2);
fprintf(stderr, " -z INT Z-drop score [%d]\n", opt.zdrop);
fprintf(stderr, " -s INT minimal peak DP alignment score [%d]\n", opt.min_dp_max);
fprintf(stderr, " Input/Output:\n");
fprintf(stderr, " -Q ignore base quality in the input\n");
fprintf(stderr, " -a output in the SAM format (PAF by default)\n");
fprintf(stderr, " -c output CIGAR in PAF\n");
fprintf(stderr, " -t INT number of threads [%d]\n", n_threads);
fprintf(stderr, " -K NUM minibatch size [200M]\n");
// fprintf(stderr, " -v INT verbose level [%d]\n", mm_verbose);
fprintf(stderr, " -V show version number\n");
fprintf(stderr, " Preset:\n");
fprintf(stderr, " -x STR preset (recommended to be applied before other options) []\n");
fprintf(stderr, " map10k/map-pb: -Hk19 (PacBio/ONT vs reference mapping)\n");
fprintf(stderr, " map-ont: -k15 (slightly more sensitive than 'map10k' for ONT vs reference)\n");
fprintf(stderr, " asm5: -k19 -w19 -A1 -B19 -O39,81 -E3,1 -s200 -z200 (asm to ref mapping; break at 5%% div.)\n");
fprintf(stderr, " asm10: -k19 -w19 -A1 -B9 -O16,41 -E2,1 -s200 -z200 (asm to ref mapping; break at 10%% div.)\n");
fprintf(stderr, " ava-pb: -Hk19 -w5 -Xp0 -m100 -g10000 -K500m --max-chain-skip 25 (PacBio read overlap)\n");
fprintf(stderr, " ava-ont: -k15 -w5 -Xp0 -m100 -g10000 -K500m --max-chain-skip 25 (ONT read overlap)\n");
fprintf(stderr, "\nSee `man ./minimap2.1' for detailed description of command-line options.\n");
return 1;
}
is_idx = mm_idx_is_idx(argv[optind]);
if (is_idx < 0) {
fprintf(stderr, "[E::%s] failed to open file '%s'\n", __func__, argv[optind]);
return 1;
}
if (is_idx) fpr = fopen(argv[optind], "rb");
else fp = mm_bseq_open(argv[optind]);
if (fnw) fpw = fopen(fnw, "wb");
for (;;) {
mm_idx_t *mi = 0;
if (fpr) {
mi = mm_idx_load(fpr);
if (idx_par_set && mm_verbose >= 2 && (mi->k != k || mi->w != w || mi->is_hpc != mi->is_hpc))
fprintf(stderr, "[W::%s::%.3f*%.2f] Indexing parameters on the command line (-k/-w/-H) overridden by parameters in the prebuilt index.\n",
__func__, realtime() - mm_realtime0, cputime() / (realtime() - mm_realtime0));
} else if (!mm_bseq_eof(fp)) {
mi = mm_idx_gen(fp, w, k, bucket_bits, is_hpc, minibatch_size, n_threads, batch_size, keep_name);
}
if (mi == 0) break;
if (mm_verbose >= 3)
fprintf(stderr, "[M::%s::%.3f*%.2f] loaded/built the index for %d target sequence(s)\n",
__func__, realtime() - mm_realtime0, cputime() / (realtime() - mm_realtime0), mi->n_seq);
if (fpw) {
mm_idx_dump(fpw, mi);
if (mm_verbose >= 3)
fprintf(stderr, "[M::%s::%.3f*%.2f] dumpped the (partial) index to disk\n", __func__, realtime() - mm_realtime0, cputime() / (realtime() - mm_realtime0));
}
if (argc != optind + 1) mm_mapopt_update(&opt, mi);
if (mm_verbose >= 3) mm_idx_stat(mi);
for (i = optind + 1; i < argc; ++i)
mm_map_file(mi, argv[i], &opt, n_threads, minibatch_size);
mm_idx_destroy(mi);
}
if (fpw) fclose(fpw);
if (fpr) fclose(fpr);
if (fp) mm_bseq_close(fp);
fprintf(stderr, "[M::%s] Version: %s\n", __func__, MM_VERSION);
fprintf(stderr, "[M::%s] CMD:", __func__);
for (i = 0; i < argc; ++i)
fprintf(stderr, " %s", argv[i]);
fprintf(stderr, "\n[M::%s] Real time: %.3f sec; CPU: %.3f sec\n", __func__, realtime() - mm_realtime0, cputime());
return 0;
}
-387
View File
@@ -1,387 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "kthread.h"
#include "kvec.h"
#include "kalloc.h"
#include "sdust.h"
#include "mmpriv.h"
#include "bseq.h"
void mm_mapopt_init(mm_mapopt_t *opt)
{
memset(opt, 0, sizeof(mm_mapopt_t));
opt->max_occ_frac = 1e-5f;
opt->mid_occ_frac = 2e-4f;
opt->sdust_thres = 0;
opt->min_cnt = 3;
opt->min_chain_score = 40;
opt->bw = 500;
opt->max_gap = 5000;
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->min_dp_max = opt->min_chain_score * opt->a;
opt->min_ksw_len = 200;
}
void mm_mapopt_update(mm_mapopt_t *opt, const mm_idx_t *mi)
{
opt->max_occ = mm_idx_cal_max_occ(mi, opt->max_occ_frac);
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; max_occ = %d\n", __func__, realtime() - mm_realtime0, cputime() / (realtime() - mm_realtime0),
opt->mid_occ, opt->max_occ);
}
typedef struct {
uint32_t n:31, is_alloc:1;
uint32_t qpos;
union {
const uint64_t *cr;
uint64_t *r;
} x;
} mm_match_t;
struct mm_tbuf_s {
sdust_buf_t *sdb;
mm128_v mini;
void *km;
};
mm_tbuf_t *mm_tbuf_init(void)
{
mm_tbuf_t *b;
b = (mm_tbuf_t*)calloc(1, sizeof(mm_tbuf_t));
if (!(mm_dbg_flag & 1)) b->km = km_init();
b->sdb = sdust_buf_init(b->km);
return b;
}
void mm_tbuf_destroy(mm_tbuf_t *b)
{
if (b == 0) return;
kfree(b->km, b->mini.a);
sdust_buf_destroy(b->sdb);
km_destroy(b->km);
free(b);
}
static void mm_dust_minier(mm128_v *mini, int l_seq, const char *seq, int sdust_thres, sdust_buf_t *sdb)
{
int n_dreg, j, k, u = 0;
const uint64_t *dreg;
if (sdust_thres <= 0 || sdb == 0) return;
dreg = sdust_core((const uint8_t*)seq, l_seq, sdust_thres, 64, &n_dreg, sdb);
for (j = k = 0; j < mini->n; ++j) { // squeeze out minimizers that significantly overlap with LCRs
int32_t qpos = (uint32_t)mini->a[j].y>>1, span = mini->a[j].x&0xff;
int32_t s = qpos - (span - 1), e = s + span;
while (u < n_dreg && (uint32_t)dreg[u] <= s) ++u;
if (u < n_dreg && dreg[u]>>32 < e) {
int v, l = 0;
for (v = u; v < n_dreg && dreg[v]>>32 < e; ++v) { // iterate over LCRs overlapping this minimizer
int ss = s > dreg[v]>>32? s : dreg[v]>>32;
int ee = e < (uint32_t)dreg[v]? e : (uint32_t)dreg[v];
l += ee - ss;
}
if (l <= span>>1) mini->a[k++] = mini->a[j]; // keep the minimizer if less than half of it falls in masked region
}
}
mini->n = k;
}
#if 0
int mm_pair_thin_core(mm_tbuf_t *b, uint64_t x, int radius, int rel, int st0, int n, const uint64_t *z, uint64_v *a)
{
int i, st = st0, en = n, mid = en - 1;
while (st < en) {
uint64_t y;
mid = st + ((en - st) >> 1);
y = z[mid];
if (y < x && (x - y)>>1 > radius) st = mid + 1;
else if (y >= x && (y - x)>>1 > radius) en = mid;
else break;
}
if (st < en) {
for (en = mid + 1; en < n; ++en)
if (z[en] > x && (z[en] - x)>>1 > radius)
break;
for (st = mid - 1; st >= st0; --st)
if (z[st] < x && (x - z[st])>>1 > radius)
break;
++st;
for (i = st; i < en; ++i) {
uint64_t y = z[i];
if (((x ^ y) & 1) == rel) {
// printf("* %d,%d\n", (uint32_t)x>>1, (uint32_t)y>>1);
kv_push(uint64_t, b->km, *a, y);
}
}
return en;
} else return st < n && z[st] < x? st + 1 : en;
}
void mm_pair_thin(mm_tbuf_t *b, int radius, mm_match_t *m1, mm_match_t *m2)
{
mm_match_t *m[2];
const uint64_t *z[2];
uint64_v a[2];
int i, n[2], k[2], u = 0, rel = (m1->qpos ^ m2->qpos) & 1;
m[0] = m1, m[1] = m2;
for (i = 0; i < 2; ++i) {
n[i] = m[i]->n;
z[i] = m[i]->x.cr;
k[i] = 0;
kv_init(a[i]);
kv_resize(uint64_t, b->km, a[i], 256);
}
while (k[0] < n[0] && k[1] < n[1]) {
//printf("%d; %d,%d\n", u, k[0], k[1]);
int v = u^1, dist = (int)(m[v]->qpos>>1) - (int)(m[u]->qpos>>1);
uint64_t x = z[u][k[u]];
int uori = (x ^ m[u]->qpos) & 1, last;
int64_t tpos = x>>1 & 0x7fffffff;
tpos = uori == 0? tpos + dist : tpos - dist;
if (tpos < 0) tpos = 0;
x = x>>32<<32 | tpos<<1 | (x&1);
last = a[v].n;
k[v] = mm_pair_thin_core(b, x, radius, rel, k[v], n[v], z[v], &a[v]);
if (a[v].n > last) kv_push(uint64_t, b->km, a[u], z[u][k[u]]);
++k[u];
u ^= 1;
}
for (i = 0; i < 2; ++i)
m[i]->n = a[i].n, m[i]->x.r = a[i].a, m[i]->is_alloc = 1;
// printf("%d,%d; %d,%d\n", m[0]->qpos>>1, m[1]->qpos>>1, m[0]->n, m[1]->n);
}
#endif
mm_reg1_t *mm_map_frag(const mm_mapopt_t *opt, const mm_idx_t *mi, mm_tbuf_t *b, uint32_t m_st, uint32_t m_en, const char *qname, int qlen, const char *seq, int *n_regs)
{
int i, n = m_en - m_st, j, n_u;
int64_t n_a;
uint64_t *u;
mm_match_t *m;
mm128_t *a;
mm_reg1_t *regs;
// convert to local representation
m = (mm_match_t*)kmalloc(b->km, n * sizeof(mm_match_t));
for (i = 0; i < n; ++i) {
int t;
mm128_t *p = &b->mini.a[i + m_st];
m[i].is_alloc = 0;
m[i].qpos = (uint32_t)p->y;
m[i].x.cr = mm_idx_get(mi, p->x>>8, &t);
m[i].n = t;
}
#if 0
int last = -1, last2 = -1;
// pair k-mer thinning
for (i = 0; i < n; ++i) {
if (m[i].n >= opt->mid_occ && m[i].n < opt->max_occ) {
if (last2 < 0) last2 = i;
if (last < 0 || m[last].n < m[i].n) last = i;
if (last >= 0 && (m[last].qpos>>1) + (m[last].span>>1) <= m[i].qpos>>1) {
mm_pair_thin(b, opt->bw, &m[last], &m[i]);
last2 = last = -1;
} else if (last2 >= 0 && (m[last2].qpos>>1) + (m[last2].span>>1) <= m[i].qpos>>1) {
mm_pair_thin(b, opt->bw, &m[last2], &m[i]);
last2 = last = -1;
}
}
}
#endif
// fill the _a_ array
for (i = 0, n_a = 0; i < n; ++i) // find the length of a[]
if (m[i].n < opt->mid_occ) n_a += m[i].n;
a = (mm128_t*)kmalloc(b->km, n_a * sizeof(mm128_t));
for (i = j = 0; i < n; ++i) {
mm128_t *p = &b->mini.a[i + m_st];
mm_match_t *q = &m[i];
const uint64_t *r = q->x.cr;
int k, q_span = p->x & 0xff, is_tandem = 0;
if (q->n >= opt->mid_occ) continue;
if (i > 0 && p->x>>8 == b->mini.a[m_st + i - 1].x>>8) is_tandem = 1;
if (i < n - 1 && p->x>>8 == b->mini.a[m_st + i + 1].x>>8) is_tandem = 1;
for (k = 0; k < q->n; ++k) {
const char *tname = mi->seq[r[k]>>32].name;
int32_t rpos = (uint32_t)r[k] >> 1;
mm128_t *p;
if (qname && (opt->flag&MM_F_NO_SELF) && strcmp(qname, tname) == 0 && rpos == (q->qpos>>1)) // avoid the diagonal
continue;
if (qname && (opt->flag&MM_F_AVA) && strcmp(qname, tname) > 0) // all-vs-all mode: map once
continue;
p = &a[j++];
if ((r[k]&1) == (q->qpos&1)) { // forward strand
p->x = (r[k]&0xffffffff00000000ULL) | (uint32_t)r[k]>>1;
p->y = (uint64_t)q_span << 32 | q->qpos >> 1;
} else { // reverse strand
p->x = 1ULL<<63 | (r[k]&0xffffffff00000000ULL) | (uint32_t)r[k]>>1;
p->y = (uint64_t)q_span << 32 | (qlen - ((q->qpos>>1) + 1 - q_span) - 1);
}
if (is_tandem) p->y |= MM_SEED_TANDEM;
}
}
n_a = j;
radix_sort_128x(a, a + n_a);
for (i = 0; i < n; ++i)
if (m[i].is_alloc) kfree(b->km, m[i].x.r);
kfree(b->km, m);
if (mm_dbg_flag & MM_DBG_PRINT_SEED)
for (i = 0; i < n_a; ++i)
fprintf(stderr, "SD\t%s\t%d\t%c\t%d\t%d\t%d\n", mi->seq[a[i].x<<1>>33].name, (int32_t)a[i].x, "+-"[a[i].x>>63], (int32_t)a[i].y, (int32_t)(a[i].y>>32&0xff),
i == 0? 0 : ((int32_t)a[i].y - (int32_t)a[i-1].y) - ((int32_t)a[i].x - (int32_t)a[i-1].x));
n_u = mm_chain_dp(opt->max_gap, opt->bw, opt->max_chain_skip, opt->min_cnt, opt->min_chain_score, n_a, a, &u, b->km);
regs = mm_gen_regs(b->km, qlen, n_u, u, a);
*n_regs = n_u;
if (mm_dbg_flag & MM_DBG_PRINT_SEED)
for (j = 0; j < n_u; ++j)
for (i = regs[j].as; i < regs[j].as + regs[j].cnt; ++i)
fprintf(stderr, "CN\t%d\t%s\t%d\t%c\t%d\t%d\t%d\n", j, mi->seq[a[i].x<<1>>33].name, (int32_t)a[i].x, "+-"[a[i].x>>63], (int32_t)a[i].y, (int32_t)(a[i].y>>32&0xff),
i == regs[j].as? 0 : ((int32_t)a[i].y - (int32_t)a[i-1].y) - ((int32_t)a[i].x - (int32_t)a[i-1].x));
if (!(opt->flag & MM_F_AVA)) { // don't choose primary mapping(s) for read overlap
mm_set_parent(b->km, opt->mask_level, *n_regs, regs);
mm_select_sub(b->km, opt->mask_level, opt->pri_ratio, mi->k*2, opt->best_n, n_regs, regs);
mm_join_long(b->km, opt, qlen, n_regs, regs, a); // TODO: this can be applied to all-vs-all in principle
}
if (opt->flag & MM_F_CIGAR) {
regs = mm_align_skeleton(b->km, opt, mi, qlen, seq, n_regs, regs, a); // this calls mm_filter_regs()
if (!(opt->flag & MM_F_AVA)) {
mm_set_parent(b->km, opt->mask_level, *n_regs, regs);
mm_select_sub(b->km, opt->mask_level, opt->pri_ratio, mi->k*2, opt->best_n, n_regs, regs);
mm_set_sam_pri(*n_regs, regs);
}
}
mm_set_mapq(*n_regs, regs, opt->min_chain_score);
// free
kfree(b->km, a);
kfree(b->km, u);
return regs;
}
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 *qname)
{
mm_reg1_t *regs;
b->mini.n = 0;
mm_sketch(b->km, seq, l_seq, mi->w, mi->k, 0, mi->is_hpc, &b->mini);
if (opt->sdust_thres > 0)
mm_dust_minier(&b->mini, l_seq, seq, opt->sdust_thres, b->sdb);
regs = mm_map_frag(opt, mi, b, 0, b->mini.n, qname, l_seq, seq, n_regs);
return regs;
}
/**************************
* Multi-threaded mapping *
**************************/
typedef struct {
int mini_batch_size, n_processed, n_threads;
const mm_mapopt_t *opt;
mm_bseq_file_t *fp;
const mm_idx_t *mi;
kstring_t str;
} pipeline_t;
typedef struct {
const pipeline_t *p;
int n_seq;
mm_bseq1_t *seq;
int *n_reg;
mm_reg1_t **reg;
mm_tbuf_t **buf;
} step_t;
static void worker_for(void *_data, long i, int tid) // kt_for() callback
{
step_t *step = (step_t*)_data;
if (mm_dbg_flag & MM_DBG_PRINT_QNAME)
fprintf(stderr, "QR\t%s\t%d\n", step->seq[i].name, tid);
step->reg[i] = mm_map(step->p->mi, step->seq[i].l_seq, step->seq[i].seq, &step->n_reg[i], step->buf[tid], step->p->opt, step->seq[i].name);
}
static void *worker_pipeline(void *shared, int step, void *in)
{
int i, j;
pipeline_t *p = (pipeline_t*)shared;
if (step == 0) { // step 0: read sequences
int with_qual = (!!(p->opt->flag & MM_F_OUT_SAM) && !(p->opt->flag & MM_F_NO_QUAL));
step_t *s;
s = (step_t*)calloc(1, sizeof(step_t));
s->seq = mm_bseq_read(p->fp, p->mini_batch_size, with_qual, &s->n_seq);
if (s->seq) {
s->p = p;
for (i = 0; i < s->n_seq; ++i)
s->seq[i].rid = p->n_processed++;
s->buf = (mm_tbuf_t**)calloc(p->n_threads, sizeof(mm_tbuf_t*));
for (i = 0; i < p->n_threads; ++i)
s->buf[i] = mm_tbuf_init();
s->n_reg = (int*)calloc(s->n_seq, sizeof(int));
s->reg = (mm_reg1_t**)calloc(s->n_seq, sizeof(mm_reg1_t*));
return s;
} else free(s);
} else if (step == 1) { // step 1: map
kt_for(p->n_threads, worker_for, in, ((step_t*)in)->n_seq);
return in;
} else if (step == 2) { // step 2: output
step_t *s = (step_t*)in;
const mm_idx_t *mi = p->mi;
for (i = 0; i < p->n_threads; ++i) mm_tbuf_destroy(s->buf[i]);
free(s->buf);
for (i = 0; i < s->n_seq; ++i) {
mm_bseq1_t *t = &s->seq[i];
for (j = 0; j < s->n_reg[i]; ++j) {
mm_reg1_t *r = &s->reg[i][j];
if (p->opt->flag & MM_F_OUT_SAM) mm_write_sam(&p->str, mi, t, r, s->n_reg[i], s->reg[i]);
else mm_write_paf(&p->str, mi, t, r);
puts(p->str.s);
}
if (s->n_reg[i] == 0 && (p->opt->flag & MM_F_OUT_SAM)) {
mm_write_sam(&p->str, 0, t, 0, 0, 0);
puts(p->str.s);
}
for (j = 0; j < s->n_reg[i]; ++j) free(s->reg[i][j].p);
free(s->reg[i]);
free(s->seq[i].seq); free(s->seq[i].name);
if (s->seq[i].qual) free(s->seq[i].qual);
}
free(s->reg); free(s->n_reg); free(s->seq);
if (mm_verbose >= 3)
fprintf(stderr, "[M::%s::%.3f*%.2f] mapped %d sequences\n", __func__, realtime() - mm_realtime0, cputime() / (realtime() - mm_realtime0), s->n_seq);
free(s);
}
return 0;
}
int mm_map_file(const mm_idx_t *idx, const char *fn, const mm_mapopt_t *opt, int n_threads, int mini_batch_size)
{
pipeline_t pl;
memset(&pl, 0, sizeof(pipeline_t));
pl.fp = mm_bseq_open(fn);
if (pl.fp == 0) return -1;
pl.opt = opt, pl.mi = idx;
pl.n_threads = n_threads, pl.mini_batch_size = mini_batch_size;
if (opt->flag & MM_F_OUT_SAM) {
uint32_t i;
for (i = 0; i < idx->n_seq; ++i)
printf("@SQ\tSN:%s\tLN:%d\n", idx->seq[i].name, idx->seq[i].len);
}
kt_pipeline(n_threads == 1? 1 : 2, worker_pipeline, &pl, 3);
free(pl.str.s);
mm_bseq_close(pl.fp);
return 0;
}
-145
View File
@@ -1,145 +0,0 @@
#ifndef MINIMAP2_H
#define MINIMAP2_H
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
#define MM_IDX_DEF_B 14
#define MM_F_NO_SELF 0x01
#define MM_F_AVA 0x02
#define MM_F_CIGAR 0x04
#define MM_F_OUT_SAM 0x08
#define MM_F_NO_QUAL 0x10
#define MM_IDX_MAGIC "MMI\2"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint64_t x, y;
} mm128_t;
typedef struct { size_t n, m; mm128_t *a; } mm128_v;
typedef struct { size_t n, m; uint64_t *a; } uint64_v;
typedef struct { size_t n, m; uint32_t *a; } uint32_v;
typedef struct {
mm128_v a; // (minimizer, position) array
int32_t n; // size of the _p_ array
uint64_t *p; // position array for minimizers appearing >1 times
void *h; // hash table indexing _p_ and minimizers appearing once
} mm_idx_bucket_t;
typedef struct {
char *name; // name of the db sequence
uint64_t offset; // offset in mm_idx_t::S
uint32_t len; // length
} mm_idx_seq_t;
typedef struct {
int32_t b, w, k, is_hpc;
uint32_t n_seq; // number of reference sequences
mm_idx_seq_t *seq; // sequence name, length and offset
uint32_t *S; // 4-bit packed sequence
mm_idx_bucket_t *B; // index
void *km;
} mm_idx_t;
typedef struct {
uint32_t capacity;
int32_t dp_score, dp_max, dp_max2;
uint32_t blen;
uint32_t n_diff, n_ambi;
uint32_t n_cigar;
uint32_t cigar[];
} mm_extra_t;
typedef struct {
int32_t id;
uint32_t cnt:31, rev:1;
uint32_t rid:31, inv:1;
int32_t score;
int32_t qs, qe, rs, re;
int32_t parent, subsc;
int32_t as;
int32_t fuzzy_mlen, fuzzy_blen;
uint32_t mapq:8, split:2, sam_pri:1, n_sub:21; // TODO: n_sub is not used for now
mm_extra_t *p;
} mm_reg1_t;
typedef struct {
float max_occ_frac;
float mid_occ_frac;
int sdust_thres; // score threshold for SDUST; 0 to disable
int flag; // see MM_F_* macros
int bw; // bandwidth
int max_gap; // break a chain if there are no minimizers in a max_gap window
int max_chain_skip;
int min_cnt;
int min_chain_score;
float mask_level;
float pri_ratio;
int best_n;
int max_join_long, max_join_short;
int min_join_flank_sc;
int a, b, q, e, q2, e2; // matching score, mismatch, gap-open and gap-ext penalties
int zdrop;
int min_dp_max;
int min_ksw_len;
int max_occ;
int mid_occ;
} mm_mapopt_t;
extern int mm_verbose, mm_dbg_flag;
extern double mm_realtime0;
struct mm_tbuf_s;
typedef struct mm_tbuf_s mm_tbuf_t;
struct mm_bseq_file_s;
#define mm_seq4_set(s, i, c) ((s)[(i)>>3] |= (uint32_t)(c) << (((i)&7)<<2))
#define mm_seq4_get(s, i) ((s)[(i)>>3] >> (((i)&7)<<2) & 0xf)
// compute minimizers
void mm_sketch(void *km, const char *str, int len, int w, int k, uint32_t rid, int is_hpc, mm128_v *p);
// minimizer indexing
mm_idx_t *mm_idx_init(int w, int k, int b, int is_hpc);
void mm_idx_destroy(mm_idx_t *mi);
mm_idx_t *mm_idx_gen(struct mm_bseq_file_s *fp, int w, int k, int b, int is_hpc, int mini_batch_size, int n_threads, uint64_t batch_size, int keep_name);
uint32_t mm_idx_cal_max_occ(const mm_idx_t *mi, float f);
void mm_idx_stat(const mm_idx_t *idx);
const uint64_t *mm_idx_get(const mm_idx_t *mi, uint64_t minier, int *n);
int mm_idx_getseq(const mm_idx_t *mi, uint32_t rid, uint32_t st, uint32_t en, uint8_t *seq);
mm_idx_t *mm_idx_build(const char *fn, int w, int k, int is_hpc, int n_threads);
int mm_idx_is_idx(const char *fn);
// minimizer index I/O
void mm_idx_dump(FILE *fp, const mm_idx_t *mi);
mm_idx_t *mm_idx_load(FILE *fp);
// mapping
void mm_mapopt_init(mm_mapopt_t *opt);
void mm_mapopt_update(mm_mapopt_t *opt, const mm_idx_t *mi);
mm_tbuf_t *mm_tbuf_init(void);
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);
int mm_map_file(const mm_idx_t *idx, const char *fn, const mm_mapopt_t *opt, int n_threads, int tbatch_size);
#ifdef __cplusplus
}
#endif
#endif // MINIMAP2_H
-358
View File
@@ -1,358 +0,0 @@
.TH minimap2 1 "30 July 2017" "minimap2-2.0rc1-r232" "Bioinformatics tools"
.SH NAME
.PP
minimap2 - mapping and alignment between collections of DNA sequences
.SH SYNOPSIS
* Indexing the target sequences (optional):
.RS 4
minimap2
.RB [ -x
.IR preset ]
.B -d
.I target.mmi
.I target.fa
.br
minimap2
.RB [ -H ]
.RB [ -k
.IR kmer ]
.RB [ -w
.IR miniWinSize ]
.RB [ -I
.IR batchSize ]
.B -d
.I target.mmi
.I target.fa
.RE
* Long-read alignment with CIGAR:
.RS 4
minimap2
.B -a
.RB [ -x
.IR preset ]
.I target.mmi
.I query.fa
>
.I output.sam
.br
minimap2
.B -c
.RB [ -H ]
.RB [ -k
.IR kmer ]
.RB [ -w
.IR miniWinSize ]
.RB [ ... ]
.I target.fa
.I query.fa
>
.I output.paf
.RE
* Long-read overlap without CIGAR:
.RS 4
minimap2
.B -x
ava-ont
.RB [ -t
.IR nThreads ]
.I target.fa
.I query.fa
>
.I output.paf
.RE
.SH DESCRIPTION
.PP
Minimap2 is a fast sequence mapping and alignment program that can find
overlaps between long noisy reads, or map long reads or their assemblies to a
reference genome optionally with detailed alignment (i.e. CIGAR). At present,
it works efficiently with query sequences from a few kilobases to ~100
megabases in length at a error rate ~15%. Minimap2 outputs in the PAF or the
SAM format.
.SH OPTIONS
.SS Indexing options
.TP 10
.BI -k \ INT
Minimizer k-mer length [15]
.TP
.BI -w \ INT
Minimizer window size [2/3 of k-mer length]. A minimizer is the smallest k-mer
in a window of w consecutive k-mers.
.TP
.B -H
Use homopolymer-compressed (HPC) minimizers. An HPC sequence is constructed by
contracting homopolymer runs to a single base. An HPC minimizer is a minimizer
on the HPC sequence.
.TP
.BI -I \ NUM
Load at most
.I NUM
target bases into RAM for indexing [4G]. If there are more than
.I NUM
bases in
.IR target.fa ,
minimap2 needs to read
.I query.fa
multiple times to map it against each batch of target sequences.
.I NUM
may be ending with k/K/m/M/g/G. NB: mapping quality is incorrect given a
multi-part index.
.TP
.BI -d \ FILE
Save the minimizer index of
.I target.fa
to
.I FILE
[no dump]. Minimap2 indexing is fast. It can index the human genome in a couple
of minutes. If even shorter startup time is desired, use this option to save
the index. Indexing options are fixed in the index file. When an index file is
provided as the target sequences, options
.BR -H ,
.BR -k ,
.BR -w ,
.B -I
will be effectively overridden by the options stored in the index file.
.SS Mapping options
.TP 10
.BI -f \ FLOAT
Ignore top
.I FLOAT
fraction of most frequent minimizers [0.0002]
.TP
.BI -g \ INT
Stop chain enlongation if there are no minimizers in
.IR INT -bp
[10000].
.TP
.BI -r \ INT
Bandwidth used in chaining and DP-based alignment [1000]. This option
approximately controls the maximum gap size.
.TP
.BI -n \ INT
Discard chains consisting of
.RI < INT
number of minimizers [3]
.TP
.BI -m \ INT
Discard chains with chaining score
.RI < INT
[40]. Chaining score equals the approximate number of matching bases minus a
concave gap penalty. It is computed with dynamic programming.
.TP
.B -X
Perform all-vs-all mapping. In this mode, if the query sequence name is
lexicographically larger than the target sequence name, the hits between them
will be suppressed; if the query sequence name is the same as the target name,
diagonal minimizer hits will also be suppressed.
.TP
.BI -p \ FLOAT
Minimal secondary-to-primary score ratio to output secondary mappings [0.8].
Between two chains overlaping over half of the shorter chain (controled by
.BR --mask-level ),
the chain with a lower score is secondary to the chain with a higher score.
If the ratio of the scores is below
.IR FLOAT ,
the secondary chain will not be outputted or extended with DP alignment later.
.TP
.BI -N \ INT
Output at most
.I INT
secondary alignments [5]. This option has no effect when
.B -X
is applied.
.TP
.BI --max-chain-skip \ INT
A heuristics that stops chaining early [50]. Minimap2 uses dynamic programming
for chaining. The time complexity is quadratic in the number of seeds. This
option makes minimap2 exits the inner loop if it repeatedly sees seeds already
on chains. Set
.I INT
to a large number to switch off this heurstics.
.SS Alignment options
.TP 10
.BI -A \ INT
Matching score [2]
.TP
.BI -B \ INT
Mismatching penalty [4]
.TP
.BI -O \ INT1[,INT2]
Gap open penalty [4,24]. If
.I INT2
is not specified, it is set to
.IR INT1 .
.TP
.BI -E \ INT1[,INT2]
Gap extension penalty [2,1]. A gap of length
.I k
costs
.RI min{ O1 + k * E1 , O2 + k * E2 }.
.TP
.BI -z \ INT
Break an alignment if the running score drops too quickly along the diagonal of
the DP matrix (diagonal X-drop, or Z-drop) [400]. Increasing the value improves
the contiguity of the alignment at the cost of poor alignment in the middle
(e.g. caused by a long inversion).
.TP
.BI -s \ INT
Minimal peak DP alignment score to output [40]. The peak score is computed from
the final CIGAR. It is the score of the max scoring segment in the alignment
and may be different from the total alignment score.
.SS Input/output options
.TP 10
.B -Q
Ignore base quality in the input file.
.TP
.B -a
Generate CIGAR and output alignments in the SAM format. Minimap2 outputs in PAF
by default.
.TP
.B -c
Generate CIGAR. In PAF, the CIGAR is written to the `cg' custom tag.
.TP
.BI -t \ INT
Number of threads [3]. Minimap2 uses at most three threads when indexing target
sequences, and uses up to
.IR INT +1
threads when mapping (the extra thread is for I/O, which is frequently idle and
takes little CPU time).
.TP
.BI -K \ NUM
Number of bases loaded into memory to process in a mini-batch [200M].
Similar to option
.BR -I ,
K/M/G/k/m/g suffix is accepted. A large
.I NUM
helps load balancing in the multi-threading mode, at the cost of increased
memory. Preset
.B ava-pb
and
.B ava-ont
use
.BR -K500m .
.TP
.B -V
Print version number to stdout
.SS Preset options
.TP 10
.BI -x \ STR
Preset []. This option applies multiple options at the same time. It should be
applied before other options because options applied later will overwrite the
values set by
.BR -x .
Available
.I STR
are:
.RS
.TP 8
.B map-pb
PacBio/Oxford Nanopore read to reference mapping (-Hk19)
.TP
.B map10k
The same as
.B map-pb
(-Hk19)
.TP
.B map-ont
Slightly more sensitive for Oxford Nanopore to reference mapping (-k15). For
PacBio reads, HPC minimizers consistently leads to faster performance and more
sensitive results in comparison to normal minimizers. For Oxford Nanopore data,
normal minimizers are better, though not much. The effectiveness of HPC is
determined by the sequencing error mode.
.TP
.B asm5
Long assembly to reference mapping (-k19 -w19 -A1 -B19 -O39,81 -E3,1 -s200 -z200).
Typically, the alignment will not extend to regions with 5% or higher sequence
divergence. Only use this preset if the average divergence is far below 5%.
.TP
.B asm10
Long assembly to reference mapping (-k19 -w19 -A1 -B9 -O16,41 -E2,1 -s200 -z200). Up
to 10% sequence divergence.
.TP 8
.B ava-pb
PacBio all-vs-all overlap mapping (-Hk19 -w5 -Xp0 -m100 -K500m -g10000 --max-chain-skip 25)
.TP 8
.B ava-ont
Oxford Nanopore all-vs-all overlap mapping (-k15 -w5 -Xp0 -m100 -K500m -g10000
--max-chain-skip 25). Similarly, the major difference from
.B ava-pb
is that this preset is not using HPC minimizers.
.RE
.SS Miscellaneous options
.TP 10
.B --no-kalloc
Use the libc default allocator instead of the kalloc thread-local allocator.
This debugging option is mostly used with Valgrind to detect invalid memory
accesses. Minimap2 runs slower with this option, especially in the
multi-threading mode.
.TP
.B --print-qname
Print query names to stderr, mostly to see which query is crashing minimap2.
.TP
.B --print-seed
Print seed positions to stderr, for debugging only.
.SH OUTPUT FORMAT
.PP
Minimap2 outputs mapping positions in the Pairwise mApping Format (PAF) by
default. PAF is a TAB-delimited text format with each line consisting of at
least 12 fields as are described in the following table:
.TS
center box;
cb | cb | cb
r | c | l .
Col Type Description
_
1 string Query sequence name
2 int Query sequence length
3 int Query start coordinate (0-based)
4 int Query end coordinate (0-based)
5 char `+' if query/target on the same strand; `-' if opposite
6 string Target sequence name
7 int Target sequence length
8 int Target start coordinate on the original strand
9 int Target end coordinate on the original strand
10 int Number of matching bases in the mapping
11 int Number bases, including gaps, in the mapping
12 int Mapping quality (0-255 with 255 for missing)
.TE
.PP
When alignment is available, column 11 gives the total number of sequence
matches, mismatches and gaps in the alignment; column 10 divided by column 11
gives the BLAST-like alignment identity. When alignment is unavailable,
these two columns are approximate. PAF may optionally have additional fields in
the SAM-like typed key-value format. Minimap2 may output the following tags:
.TS
center box;
cb | cb | cb
r | c | l .
Tag Type Description
_
tp A Type of aln: P/primary, S/secondary and I/inversion
cm i Number of minimizers on the chain
s1 i Chaining score
s2 i Chaining score of the best secondary chain
NM i Total number of mismatches and gaps in the alignment
AS i DP alignment score
ms i DP score of the max scoring segment in the alignment
nn i Number of ambiguous bases in the alignment
cg Z CIGAR string (only in PAF)
.TE
.SH LIMITATIONS
.TP 2
*
Minimap2 may produce suboptimal alignments through long low-complexity regions
where seed positions may be suboptimal. This should not be a big concern
because even the optimal alignment may be wrong in such regions.
.TP
*
Minimap2 does not work well with Illumina short reads as of now.
.TP
*
Minimap2 requires SSE2 instructions to compile. It is possible to add
non-SSE2 support, but it would make minimap2 slower by several times.
.SH SEE ALSO
.PP
miniasm(1), minimap(1), bwa(1).
+925
View File
@@ -0,0 +1,925 @@
<HTML><HEAD>
<style type="text/css">
a:link {
text-decoration: none;
color: #0092e8;
}
a:visited {
text-decoration: none;
color: #0092e8;
}
a:hover {
text-decoration: underline;
color: #0092e8;
}
body, td, th {
font: 12px consolas, andale mono, courier, mono;
}
body {
color: #000;
background: #fff;
margin: 0;
padding: 0;
}
table {
border: solid 0px #ccc;
}
td {
vertical-align: top;
padding: 0.2em;
}
th {
font-weight: bold;
text-align: left;
padding: 0.2em;
}
#tbl table {
border: solid 1px #ccc;
}
#tbl td {
border: solid 1px #ccc;
padding: 0.3em;
}
#wrap {
width: 780px;
text-align: left;
margin: 0 auto;
}
hr {
margin: 1em 0;
color: #C7C7C7;
background: #C7C7C7;
border-color: #C7C7C7;
border-style: none;
height: 1px;
}
h1, h2, h3, h4, h5, h6 {
font-family: "Trebuchet MS", arial, sans-serif;
font-weight: bold;
}
p {
text-align: justify;
}
</style>
<TITLE>minimap2.1</TITLE>
</HEAD>
<BODY bgcolor=#F0F0F0 text=#000000 link=#0000ff vlink=#C000C0 alink=#ff0000><div id="wrap"><A NAME=top></A>
<CENTER>
<H1><HR><I>Manual Reference Pages &nbsp;-&nbsp;</I><NOBR>minimap2 (1)</NOBR><HR></H1>
</CENTER>
<A name=0></A>
<H3>NAME</H3>
<BLOCKQUOTE>
<P>
minimap2 - mapping and alignment between collections of DNA sequences
</BLOCKQUOTE>
<A name=contents></A><H3>CONTENTS</H3></A>
<BLOCKQUOTE>
<A HREF=#1>Synopsis</A><BR>
<A HREF=#2>Description</A><BR>
<A HREF=#3>Options</A><BR>
&nbsp; &nbsp; &nbsp;<A HREF=#4>Indexing options</A><BR>
&nbsp; &nbsp; &nbsp;<A HREF=#5>Mapping options</A><BR>
&nbsp; &nbsp; &nbsp;<A HREF=#6>Alignment options</A><BR>
&nbsp; &nbsp; &nbsp;<A HREF=#7>Input/output options</A><BR>
&nbsp; &nbsp; &nbsp;<A HREF=#8>Preset options</A><BR>
&nbsp; &nbsp; &nbsp;<A HREF=#9>Miscellaneous options</A><BR>
<A HREF=#10>Output Format</A><BR>
<A HREF=#11>Limitations</A><BR>
<A HREF=#12>See Also</A><BR>
</BLOCKQUOTE>
<A name=13></A>
<H3>SYNOPSIS</H3>
<BLOCKQUOTE>
* Indexing the target sequences (optional):
<BLOCKQUOTE>
minimap2
[<B>-x</B> <I>preset</I>] <B>-d</B> <I>target.mmi</I> <I>target.fa</I> <!-- Need break --><BR>
minimap2
[<B>-H</B>] [<B>-k</B> <I>kmer</I>] [<B>-w</B> <I>miniWinSize</I>] [<B>-I</B> <I>batchSize</I>] <B>-d</B> <I>target.mmi</I> <I>target.fa</I> </BLOCKQUOTE>
<P>
* Long-read alignment with CIGAR:
<BLOCKQUOTE>
minimap2
<B>-a</B> [<B>-x</B> <I>preset</I>] <I>target.mmi</I> <I>query.fa</I> &gt;
<I>output.sam</I> <!-- Need break --><BR>
minimap2
<B>-c</B> [<B>-H</B>] [<B>-k</B> <I>kmer</I>] [<B>-w</B> <I>miniWinSize</I>] [<B>...</B>] <I>target.fa</I> <I>query.fa</I> &gt;
<I>output.paf</I> </BLOCKQUOTE>
<P>
* Long-read overlap without CIGAR:
<BLOCKQUOTE>
minimap2
<B>-x</B> ava-ont
[<B>-t</B> <I>nThreads</I>] <I>target.fa</I> <I>query.fa</I> &gt;
<I>output.paf</I> </BLOCKQUOTE>
</BLOCKQUOTE>
<A name=2></A>
<H3>DESCRIPTION</H3>
<BLOCKQUOTE>
<P>
Minimap2 is a fast sequence mapping and alignment program that can find
overlaps between long noisy reads, or map long reads or their assemblies to a
reference genome optionally with detailed alignment (i.e. CIGAR). At present,
it works efficiently with query sequences from a few kilobases to ~100
megabases in length at a error rate ~15%. Minimap2 outputs in the PAF or the
SAM format.
</BLOCKQUOTE>
<A name=3></A>
<H3>OPTIONS</H3>
<BLOCKQUOTE>
</BLOCKQUOTE>
<A name=4></A>
<H4>&nbsp; &nbsp; Indexing options</H4>
<BLOCKQUOTE>
<TABLE cellpadding=3>
<TR valign=top><TD width=10% nowrap>
<B>-k</B><I> INT</I> </TD><TD valign=bottom>
Minimizer k-mer length [15]
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-w</B><I> INT</I> </TD><TD valign=bottom>
Minimizer window size [10]. A minimizer is the smallest k-mer
in a window of w consecutive k-mers.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-j</B><I> INT</I> </TD><TD valign=bottom>
Syncmer submer size [10]. Option
<B>-j</B> and
<B>-w</B> will override each: if
<B>-w</B> is applied after
<B>-j</B>, <B>-j</B> will have no effect, and vice versa.
<P>
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-H</B> </TD><TD valign=bottom>
Use homopolymer-compressed (HPC) minimizers. An HPC sequence is constructed by
contracting homopolymer runs to a single base. An HPC minimizer is a minimizer
on the HPC sequence.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-I</B><I> NUM</I> </TD><TD valign=bottom>
Load at most
<I>NUM</I> target bases into RAM for indexing [8G]. If there are more than
<I>NUM</I> bases in
<I>target.fa</I>, minimap2 needs to read
<I>query.fa</I> multiple times to map it against each batch of target sequences. This would create a multi-part index.
<I>NUM</I> may be ending with k/K/m/M/g/G. NB: mapping quality is incorrect given a
multi-part index. See also option
<B>--split-prefix</B>. </TD></TR>
<TR valign=top><TD colspan=2>
<B>--idx-no-seq</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Don&#146;t store target sequences in the index. It saves disk space and memory but
the index generated with this option will not work with
<B>-a</B> or
<B>-c</B>. When base-level alignment is not requested, this option is automatically applied.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-d</B><I> FILE</I> </TD><TD valign=bottom>
Save the minimizer index of
<I>target.fa</I> to
<I>FILE</I> [no dump]. Minimap2 indexing is fast. It can index the human genome in a couple
of minutes. If even shorter startup time is desired, use this option to save
the index. Indexing options are fixed in the index file. When an index file is
provided as the target sequences, options
<B>-H</B>, <B>-k</B>, <B>-w</B>, <B>-I</B> will be effectively overridden by the options stored in the index file.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>--alt</B><I> FILE</I> </TD><TD valign=bottom>
List of ALT contigs [null]
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--alt-drop</B><I> FLOAT</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Drop ALT hits by
<I>FLOAT</I> fraction when ranking and computing mapping quality [0.15]
</TD></TR>
<TR></TR></TABLE></BLOCKQUOTE>
<A name=5></A>
<H4>&nbsp; &nbsp; Mapping options</H4>
<BLOCKQUOTE>
<TABLE cellpadding=3>
<TR valign=top><TD colspan=2>
<B>-f</B><I> FLOAT</I><B>|</B><I>INT1</I><B>[,</B><I>INT2</I><B>]</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
If fraction, ignore top
<I>FLOAT</I> fraction of most frequent minimizers [0.0002]. If integer,
ignore minimizers occuring more than
<I>INT1</I> times.
<I>INT2</I> is only effective in the
<B>--sr</B> or
<B>-xsr</B> mode, which sets the threshold for a second round of seeding.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>-U</B><I> INT1</I><B>[,</B><I>INT2</I><B>]</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Lower and upper bounds of k-mer occurrences [10,1000000]. The final k-mer occurrence threshold is
max{<I>INT1</I>, min{<I>INT2</I>, <B>-f</B>}}. This option prevents excessively small or large
<B>-f</B> estimated from the input reference. Available since r1034 and deprecating
<B>--min-occ-floor</B> in earlier versions of minimap2.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--q-occ-frac</B><I> FLOAT</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Discard a query minimizer if its occurrence is higher than
<I>FLOAT</I> fraction of query minimizers and than the reference occurrence threshold
[0.01]. Set 0 to disable. Available since r1105.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-e</B><I> INT</I> </TD><TD valign=bottom>
Sample a high-frequency minimizer every
<I>INT</I> basepairs [500].
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-g</B><I> NUM</I> </TD><TD valign=bottom>
Stop chain enlongation if there are no minimizers within
<I>NUM</I>-bp [10k].
</TD></TR>
<TR valign=top><TD colspan=2>
<B>-r</B><I> NUM1</I><B>[,</B><I>NUM2</I><B>]</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Bandwidth for chaining and base alignment [500,20k].
<I>NUM1</I> is used for initial chaining and alignment extension;
<I>NUM2</I> for RMQ-based re-chaining and closing gaps in alignments.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-n</B><I> INT</I> </TD><TD valign=bottom>
Discard chains consisting of
&lt;<I>INT</I> number of minimizers [3]
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-m</B><I> INT</I> </TD><TD valign=bottom>
Discard chains with chaining score
&lt;<I>INT</I> [40]. Chaining score equals the approximate number of matching bases minus a
concave gap penalty. It is computed with dynamic programming.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-D</B> </TD><TD valign=bottom>
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.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-P</B> </TD><TD valign=bottom>
Retain all chains and don&#146;t attempt to set primary chains. Options
<B>-p</B> and
<B>-N</B> have no effect when this option is in use.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--dual</B>=<B>yes</B>|<B>no</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
If
<B>no</B>, skip query-target pairs wherein the query name is lexicographically greater
than the target name [yes]
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-X</B> </TD><TD valign=bottom>
Equivalent to
&#146;<B>-DP</B> <B>--dual</B>=<B>no</B> <B>--no-long-join</B>&#146;. Primarily used for all-vs-all read overlapping.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-p</B><I> FLOAT</I> </TD><TD valign=bottom>
Minimal secondary-to-primary score ratio to output secondary mappings [0.8].
Between two chains overlaping over half of the shorter chain (controlled by
<B>-M</B>), the chain with a lower score is secondary to the chain with a higher score.
If the ratio of the scores is below
<I>FLOAT</I>, the secondary chain will not be outputted or extended with DP alignment later.
This option has no effect when
<B>-X</B> is applied.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-N</B><I> INT</I> </TD><TD valign=bottom>
Output at most
<I>INT</I> secondary alignments [5]. This option has no effect when
<B>-X</B> is applied.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-G</B><I> NUM</I> </TD><TD valign=bottom>
Maximum gap on the reference (effective with
<B>-xsplice</B>/<B>--splice</B>). This option also changes the chaining and alignment band width to
<I>NUM</I>. Increasing this option slows down spliced alignment. [200k]
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-F</B><I> NUM</I> </TD><TD valign=bottom>
Maximum fragment length (aka insert size; effective with
<B>-xsr</B>/<B>--frag</B>=<B>yes</B>) [800]
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-M</B><I> FLOAT</I> </TD><TD valign=bottom>
Mark as secondary a chain that overlaps with a better chain by
<I>FLOAT</I> or more of the shorter chain [0.5]
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--rmq</B>=<B>no</B>|<B>yes</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Use the minigraph chaining algorithm [no]. The minigraph algorithm is better
for aligning contigs through long INDELs.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--rmq-inner</B><I> NUM</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Apply full dynamic programming for anchors within distance
<I>NUM</I> [1000].
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--hard-mask-level</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Honor option
<B>-M</B> and disable a heurstic to save unmapped subsequences and disables
<B>--mask-len</B>. </TD></TR>
<TR valign=top><TD colspan=2>
<B>--mask-len</B><I> NUM</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Keep an alignment if dropping it leaves an unaligned region on query longer than
<I>INT</I> [inf]. Effective without
<B>--hard-mask-level</B>. </TD></TR>
<TR valign=top><TD colspan=2>
<B>--max-chain-skip</B><I> INT</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
A heuristics that stops chaining early [25]. Minimap2 uses dynamic programming
for chaining. The time complexity is quadratic in the number of seeds. This
option makes minimap2 exits the inner loop if it repeatedly sees seeds already
on chains. Set
<I>INT</I> to a large number to switch off this heurstics.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--max-chain-iter</B><I> INT</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Check up to
<I>INT</I> partial chains during chaining [5000]. This is a heuristic to avoid quadratic
time complexity in the worst case.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--chain-gap-scale</B><I> FLOAT</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Scale of gap cost during chaining [1.0]
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--no-long-join</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Disable the long gap patching heuristic. When this option is applied, the
maximum alignment gap is mostly controlled by
<B>-r</B>. </TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>--splice</B> </TD><TD valign=bottom>
Enable the splice alignment mode.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>--sr</B> </TD><TD valign=bottom>
Enable short-read alignment heuristics. In the short-read mode, minimap2
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
seeds with ungapped alignment.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--split-prefix</B><I> STR</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Prefix to create temporary files. Typically used for a multi-part index.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--frag</B>=<B>no</B>|<B>yes</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Whether to enable the fragment mode [no]
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>--for-only</B> </TD><TD valign=bottom>
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.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>--rev-only</B> </TD><TD valign=bottom>
Only map to the reverse complement strand of the reference sequences.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--heap-sort</B>=<B>no</B>|<B>yes</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
If yes, sort anchors with heap merge, instead of radix sort. Heap merge is
faster for short reads, but slower for long reads. [no]
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--no-pairing</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Treat two reads in a pair as independent reads. The mate related fields in SAM
are still properly populated.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--no-hash-name</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Produce the same alignment for identical sequences regardless of their sequence names.
</TD></TR>
<TR></TR></TABLE></BLOCKQUOTE>
<A name=6></A>
<H4>&nbsp; &nbsp; Alignment options</H4>
<BLOCKQUOTE>
<TABLE cellpadding=3>
<TR valign=top><TD width=10% nowrap>
<B>-A</B><I> INT</I> </TD><TD valign=bottom>
Matching score [2]
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-B</B><I> INT</I> </TD><TD valign=bottom>
Mismatching penalty [4]
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-b</B><I> INT</I> </TD><TD valign=bottom>
Mismatching penalty for transitions [same as
<B>-B</B>]. </TD></TR>
<TR valign=top><TD colspan=2>
<B>-O</B><I> INT1[,INT2]</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Gap open penalty [4,24]. If
<I>INT2</I> is not specified, it is set to
<I>INT1</I>. </TD></TR>
<TR valign=top><TD colspan=2>
<B>-E</B><I> INT1[,INT2]</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Gap extension penalty [2,1]. A gap of length
<I>k</I> costs
min{<I>O1</I>+<I>k</I>*<I>E1</I>,<I>O2</I>+<I>k</I>*<I>E2</I>}. In the splice mode, the second gap penalties are not used.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-J</B><I> INT</I> </TD><TD valign=bottom>
Splice model [1]. 0 for the original minimap2 splice model that always penalizes non-GT-AG splicing;
1 for the miniprot model that considers non-GT-AG. Option
<B>-C</B> has no effect with the default
<B>-J1</B>. <B>-J0</B>. </TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-C</B><I> INT</I> </TD><TD valign=bottom>
Cost for a non-canonical GT-AG splicing (effective with
<B>--splice</B> <B>-J0</B>) [0].
</TD></TR>
<TR valign=top><TD colspan=2>
<B>-z</B><I> INT1[,INT2]</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Truncate an alignment if the running alignment score drops too quickly along
the diagonal of the DP matrix (diagonal X-drop, or Z-drop) [400,200]. If the
drop of score is above
<I>INT2</I>, minimap2 will reverse complement the query in the related region and align
again to test small inversions. Minimap2 truncates alignment if there is an
inversion or the drop of score is greater than
<I>INT1</I>. Decrease
<I>INT2</I> to find small inversions at the cost of performance and false positives.
Increase
<I>INT1</I> to improves the contiguity of alignment at the cost of poor alignment in the
middle.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-s</B><I> INT</I> </TD><TD valign=bottom>
Minimal peak DP alignment score to output [40]. The peak score is computed from
the final CIGAR. It is the score of the max scoring segment in the alignment
and may be different from the total alignment score.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-u</B><I> CHAR</I> </TD><TD valign=bottom>
How to find canonical splicing sites GT-AG -
<B>f</B>: transcript strand;
<B>b</B>: both strands;
<B>n</B>: no attempt to match GT-AG [n]
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--end-bonus</B><I> INT</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Score bonus when alignment extends to the end of the query sequence [0].
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--score-N</B><I> INT</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Score of a mismatch involving ambiguous bases [1].
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--pe-ind-chain</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
For paired-end short reads, perform chaining for each end independently.
By default, minimap2 chains the two ends together.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--splice-flank</B>=<B>yes</B>|<B>no</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Assume the next base to a
<B>GT</B> donor site tends to be A/G (91% in human and 92% in mouse) and the preceding
base to a
<B>AG</B> acceptor tends to be C/T [no].
This trend is evolutionarily conservative, all the way to S. cerevisiae
(PMID:18688272). Specifying this option generally leads to higher junction
accuracy by several percents, so it is applied by default with
<B>--splice</B>. However, the SIRV control does not honor this trend
(only ~60%). This option reduces accuracy. If you are benchmarking minimap2
on SIRV data, please add
<B>--splice-flank=no</B> to the command line.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>--spsc</B> FILE </TD><TD valign=bottom>
Splice scores []. Each line consists of five fields: 1) contig, 2) offset, 3) &#145;+&#146; or &#145;-&#146;, 4) &#145;D&#146; or &#145;A&#146;, and 5) score,
where offset is the number of bases before a splice junction, &#145;D&#146; indicates the
line corresponds to a donor site and &#145;A&#146; for an acceptor site.
A positive score suggests the junction is preferred and a negative score
suggests the junction is not preferred.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--junc-pen</B> INT </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Penalty for a position not in FILE specified by
<B>--spsc</B> [5]. Effective with
<B>--spsc</B> but not
<B>--junc-bed</B>. </TD></TR>
<TR valign=top><TD colspan=2>
<B>--junc-bed</B> FILE </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Gene annotations in the BED12 format (aka 12-column BED), or intron positions
in 5-column BED. With this option, minimap2 prefers splicing in annotations.
BED12 file can be converted from GTF/GFF3 with &#145;paftools.js gff2bed anno.gtf&#146;
[].
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--junc-bonus</B> INT </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Score bonus for a splice donor or acceptor found in annotation [9]. Effective with
<B>--junc-bed</B> but not
<B>--spsc</B>. </TD></TR>
<TR valign=top><TD colspan=2>
<B>--end-seed-pen</B><I> INT</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Drop a terminal anchor if
<I>s</I>&lt;log(<I>g</I>)+<I>INT</I>, where
<I>s</I> is the local alignment score around the anchor and
<I>g</I> the length of the terminal gap in the chain. This option is only effective
with
<B>--splice</B>. It helps to avoid tiny terminal exons. [6]
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--no-end-flt</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Don&#146;t filter seeds towards the ends of chains before performing base-level
alignment.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--cap-sw-mem</B><I> NUM</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Skip alignment if the DP matrix size is above
<I>NUM</I>. Set 0 to disable [100m].
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--cap-kalloc</B><I> NUM</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Free thread-local kalloc memory reservoir if after the alignment the size of the reservoir above
<I>NUM</I>. Set 0 to disable [500m].
</TD></TR>
<TR></TR></TABLE></BLOCKQUOTE>
<A name=7></A>
<H4>&nbsp; &nbsp; Input/output options</H4>
<BLOCKQUOTE>
<TABLE cellpadding=3>
<TR valign=top><TD width=10% nowrap>
<B>-a</B> </TD><TD valign=bottom>
Generate CIGAR and output alignments in the SAM format. Minimap2 outputs in PAF
by default.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-o</B><I> FILE</I> </TD><TD valign=bottom>
Output alignments to
<I>FILE</I> [stdout].
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-Q</B> </TD><TD valign=bottom>
Ignore base quality in the input file.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-L</B> </TD><TD valign=bottom>
Write CIGAR with &gt;65535 operators at the CG tag. Older tools are unable to
convert alignments with &gt;65535 CIGAR ops to BAM. This option makes minimap2 SAM
compatible with older tools. Newer tools recognizes this tag and reconstruct
the real CIGAR in memory.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-R</B><I> STR</I> </TD><TD valign=bottom>
SAM read group line in a format like
<B>@RG\\tID:foo\\tSM:bar</B> [].
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-y</B> </TD><TD valign=bottom>
Copy input FASTA/Q comments to output.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-c</B> </TD><TD valign=bottom>
Generate CIGAR. In PAF, the CIGAR is written to the &#145;cg&#146; custom tag.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--cs[=</B><I>STR</I><B>]</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Output the
<B>cs</B> tag.
<I>STR</I> can be either
<I>short</I> or
<I>long</I>. If no
<I>STR</I> is given,
<I>short</I> is assumed. [none]
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>--MD</B> </TD><TD valign=bottom>
Output the MD tag (see the SAM spec).
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>--eqx</B> </TD><TD valign=bottom>
Output =/X CIGAR operators for sequence match/mismatch.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-Y</B> </TD><TD valign=bottom>
In SAM output, use soft clipping for supplementary alignments.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--secondary-seq</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
In SAM output, show query sequences for secondary alignments.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>--seed</B><I> INT</I> </TD><TD valign=bottom>
Integer seed for randomizing equally best hits. Minimap2 hashes
<I>INT</I> and read name when choosing between equally best hits. [11]
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-t</B><I> INT</I> </TD><TD valign=bottom>
Number of threads [3]. Minimap2 uses at most three threads when indexing target
sequences, and uses up to
<I>INT</I>+1 threads when mapping (the extra thread is for I/O, which is frequently idle and
takes little CPU time).
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-2</B> </TD><TD valign=bottom>
Use two I/O threads during mapping. By default, minimap2 uses one I/O thread.
When I/O is slow (e.g. piping to gzip, or reading from a slow pipe), the I/O
thread may become the bottleneck. Apply this option to use one thread for input
and another thread for output, at the cost of increased peak RAM.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>-K</B><I> NUM</I> </TD><TD valign=bottom>
Number of bases loaded into memory to process in a mini-batch [500M].
Similar to option
<B>-I</B>, K/M/G/k/m/g suffix is accepted. A large
<I>NUM</I> helps load balancing in the multi-threading mode, at the cost of increased
memory.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--secondary</B>=<B>yes</B>|<B>no</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Whether to output secondary alignments [yes]
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--max-qlen</B><I> NUM</I> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Filter out query sequences longer than
<I>NUM</I>. </TD></TR>
<TR valign=top><TD colspan=2>
<B>--paf-no-hit</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
In PAF, output unmapped queries; the strand and the reference name fields are
set to &#145;*&#146;. Warning: some paftools.js commands may not work with such output
for the moment.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--sam-hit-only</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
In SAM, don&#146;t output unmapped reads.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>--version</B> </TD><TD valign=bottom>
Print version number to stdout
</TD></TR>
<TR></TR></TABLE></BLOCKQUOTE>
<A name=8></A>
<H4>&nbsp; &nbsp; Preset options</H4>
<BLOCKQUOTE>
<TABLE cellpadding=3>
<TR valign=top><TD width=10% nowrap>
<B>-x</B><I> STR</I> </TD><TD valign=bottom>
Preset []. This option applies multiple options at the same time. It should be
applied before other options because options applied later will overwrite the
values set by
<B>-x</B>. Available
<I>STR</I> are:
<TABLE width=100% cellpadding=3><!-- tsb: Preset []. This option applies multiple options at the same time. It should be
-->
<TR></TR><TR></TR>
<TR valign=top><TD width=10% nowrap>
<B>map-ont</B> </TD><TD valign=bottom>
Align noisy long reads of ~10% error rate to a reference genome. This is the
default mode.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>lr:hq</B> </TD><TD valign=bottom>
Align accurate long reads (error rate &lt;1%) to a reference genome
(<B>-k19</B> <B>-w19 -U50,500</B> <B>-g10k</B>). This was recommended by ONT developers for recent Nanopore reads
produced with chemistry v14 that can reach ~99% in accuracy.
It was shown to work better for accurate Nanopore reads
than
<B>map-hifi</B>. </TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>map-hifi</B> </TD><TD valign=bottom>
Align PacBio high-fidelity (HiFi) reads to a reference genome
(<B>-xlr:hq</B> <B>-A1 -B4 -O6,26 -E2,1</B> <B>-s200</B>). It differs from
<B>lr:hq</B> only in scoring. It has not been tested whether
<B>lr:hq</B> would work better for PacBio HiFi reads.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>map-pb</B> </TD><TD valign=bottom>
Align older PacBio continuous long (CLR) reads to a reference genome
(<B>-Hk19</B>). Note that this data type is effectively deprecated by HiFi.
Unless you work on very old data, you probably want to use
<B>map-hifi</B> or
<B>lr:hq</B>. </TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>map-iclr</B> </TD><TD valign=bottom>
Align Illumina Complete Long Reads (ICLR) to a reference genome
(<B>-k19</B> <B>-B6 -b4</B> <B>-O10,50</B>). This was recommended by Illumina developers.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>asm5</B> </TD><TD valign=bottom>
Long assembly to reference mapping
(<B>-k19</B> <B>-w19 -U50,500 --rmq -r1k,100k -g10k -A1 -B19 -O39,81 -E3,1 -s200 -z200</B> <B>-N50</B>). Typically, the alignment will not extend to regions with 5% or higher sequence
divergence. Use this preset if the average divergence is not much higher than 0.1%.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>asm10</B> </TD><TD valign=bottom>
Long assembly to reference mapping
(<B>-k19</B> <B>-w19 -U50,500 --rmq -r1k,100k -g10k -A1 -B9 -O16,41 -E2,1 -s200 -z200</B> <B>-N50</B>). Use this if the average divergence is around 1%.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>asm20</B> </TD><TD valign=bottom>
Long assembly to reference mapping
(<B>-k19</B> <B>-w10 -U50,500 --rmq -r1k,100k -g10k -A1 -B4 -O6,26 -E2,1 -s200 -z200</B> <B>-N50</B>). Use this if the average divergence is around several percent.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>splice</B> </TD><TD valign=bottom>
Long-read spliced alignment
(<B>-k15</B> <B>-w5 --splice -g2k -G200k -A1 -B2 -O2,32 -E1,0 -C9 -z200 -ub --junc-bonus=9 --cap-sw-mem=0</B> <B>--splice-flank=yes</B>). In the splice mode, 1) long deletions are taken as introns and represented as
the
&#145;<B>N</B>&#146; CIGAR operator; 2) long insertions are disabled; 3) deletion and insertion gap
costs are different during chaining; 4) the computation of the
&#145;<B>ms</B>&#146; tag ignores introns to demote hits to pseudogenes.
</TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>splice:hq</B> </TD><TD valign=bottom>
Spliced alignment for accurate long RNA-seq reads such as PacBio iso-seq
(<B>-xsplice</B> <B>-C5 -O6,24</B> <B>-B4</B>). </TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>splice:sr</B> </TD><TD valign=bottom>
Spliced alignment for short RNA-seq reads
(<B>-xsplice:hq</B> <B>--frag=yes --end-bonus=10 -2K50m --heap-sort=yes --pe-ind-chain</B> <B>--secondary=no</B>). </TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>sr</B> </TD><TD valign=bottom>
Short-read alignment without splicing
(<B>-k21</B> <B>-w11 --sr --frag=yes -A2 -B8 -O12,32 -E2,1 -r100 -p.5 -N20 -f1000,5000 -n2 -m25</B> <B>-s40 -g100 -2K50m --heap-sort=yes</B> <B>--secondary=no</B>). </TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>ava-pb</B> </TD><TD valign=bottom>
PacBio CLR all-vs-all overlap mapping
(<B>-Hk19</B> <B>-Xw5 -e0</B> <B>-m100</B>). </TD></TR>
<TR valign=top><TD width=10% nowrap>
<B>ava-ont</B> </TD><TD valign=bottom>
Oxford Nanopore all-vs-all overlap mapping
(<B>-k15</B> <B>-Xw5 -e0 -m100</B> <B>-r2k</B>). </TD></TR>
<TR></TR></TABLE></TD></TR>
<TR></TR></TABLE></BLOCKQUOTE>
<A name=9></A>
<H4>&nbsp; &nbsp; Miscellaneous options</H4>
<BLOCKQUOTE>
<TABLE cellpadding=3>
<TR valign=top><TD colspan=2>
<B>--no-kalloc</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Use the libc default allocator instead of the kalloc thread-local allocator.
This debugging option is mostly used with Valgrind to detect invalid memory
accesses. Minimap2 runs slower with this option, especially in the
multi-threading mode.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--print-qname</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Print query names to stderr, mostly to see which query is crashing minimap2.
</TD></TR>
<TR valign=top><TD colspan=2>
<B>--print-seeds</B> </TD></TR><TR valign=top><TD width=10%>&nbsp;</TD><TD>
Print seed positions to stderr, for debugging only.
</TD></TR>
<TR></TR></TABLE></BLOCKQUOTE>
<A name=10></A>
<H3>OUTPUT FORMAT</H3>
<BLOCKQUOTE>
<P>
Minimap2 outputs mapping positions in the Pairwise mApping Format (PAF) by
default. PAF is a TAB-delimited text format with each line consisting of at
least 12 fields as are described in the following table:
<P><BLOCKQUOTE><div id='tbl'><TABLE border=1 cellspacing=0 cellpadding=3>
<TR valign=top>
<TD align=center><B>Col</B></TD><TD align=center><B>Type</B></TD><TD align=center><B>Description</B></TD></TR>
<TR></TR><TR></TR>
<TR valign=top>
<TD align=right>1</TD><TD align=center>string</TD><TD>Query sequence name</TD></TR>
<TR valign=top>
<TD align=right>2</TD><TD align=center>int</TD><TD>Query sequence length</TD></TR>
<TR valign=top>
<TD align=right>3</TD><TD align=center>int</TD><TD>Query start coordinate (0-based)</TD></TR>
<TR valign=top>
<TD align=right>4</TD><TD align=center>int</TD><TD>Query end coordinate (0-based)</TD></TR>
<TR valign=top>
<TD align=right>5</TD><TD align=center>char</TD><TD>&#145;+&#146; if query/target on the same strand; &#145;-&#146; if opposite</TD></TR>
<TR valign=top>
<TD align=right>6</TD><TD align=center>string</TD><TD>Target sequence name</TD></TR>
<TR valign=top>
<TD align=right>7</TD><TD align=center>int</TD><TD>Target sequence length</TD></TR>
<TR valign=top>
<TD align=right>8</TD><TD align=center>int</TD><TD>Target start coordinate on the original strand</TD></TR>
<TR valign=top>
<TD align=right>9</TD><TD align=center>int</TD><TD>Target end coordinate on the original strand</TD></TR>
<TR valign=top>
<TD align=right>10</TD><TD align=center>int</TD><TD>Number of matching bases in the mapping</TD></TR>
<TR valign=top>
<TD align=right>11</TD><TD align=center>int</TD><TD>Number bases, including gaps, in the mapping</TD></TR>
<TR valign=top>
<TD align=right>12</TD><TD align=center>int</TD><TD>Mapping quality (0-255 with 255 for missing)</TD></TR>
</TABLE></div></BLOCKQUOTE>
<P>
<P>
When alignment is available, column 11 gives the total number of sequence
matches, mismatches and gaps in the alignment; column 10 divided by column 11
gives the BLAST-like alignment identity. When alignment is unavailable,
these two columns are approximate. PAF may optionally have additional fields in
the SAM-like typed key-value format. Minimap2 may output the following tags:
<P><BLOCKQUOTE><div id='tbl'><TABLE border=1 cellspacing=0 cellpadding=3>
<TR valign=top>
<TD align=center><B>Tag</B></TD><TD align=center><B>Type</B></TD><TD align=center><B>Description</B></TD></TR>
<TR></TR><TR></TR>
<TR valign=top>
<TD align=right>tp</TD><TD align=center>A</TD><TD>Type of aln: P/primary, S/secondary and I,i/inversion</TD></TR>
<TR valign=top>
<TD align=right>cm</TD><TD align=center>i</TD><TD>Number of minimizers on the chain</TD></TR>
<TR valign=top>
<TD align=right>s1</TD><TD align=center>i</TD><TD>Chaining score</TD></TR>
<TR valign=top>
<TD align=right>s2</TD><TD align=center>i</TD><TD>Chaining score of the best secondary chain</TD></TR>
<TR valign=top>
<TD align=right>NM</TD><TD align=center>i</TD><TD>Total number of mismatches and gaps in the alignment</TD></TR>
<TR valign=top>
<TD align=right>MD</TD><TD align=center>Z</TD><TD>To generate the ref sequence in the alignment</TD></TR>
<TR valign=top>
<TD align=right>AS</TD><TD align=center>i</TD><TD>DP alignment score</TD></TR>
<TR valign=top>
<TD align=right>SA</TD><TD align=center>Z</TD><TD>List of other supplementary alignments (with approximate CIGAR strings)</TD></TR>
<TR valign=top>
<TD align=right>ms</TD><TD align=center>i</TD><TD>DP score of the max scoring segment in the alignment</TD></TR>
<TR valign=top>
<TD align=right>nn</TD><TD align=center>i</TD><TD>Number of ambiguous bases in the alignment</TD></TR>
<TR valign=top>
<TD align=right>ts</TD><TD align=center>A</TD><TD>Transcript strand (splice mode only)</TD></TR>
<TR valign=top>
<TD align=right>cg</TD><TD align=center>Z</TD><TD>CIGAR string (only in PAF)</TD></TR>
<TR valign=top>
<TD align=right>cs</TD><TD align=center>Z</TD><TD>Difference string</TD></TR>
<TR valign=top>
<TD align=right>dv</TD><TD align=center>f</TD><TD>Approximate per-base sequence divergence</TD></TR>
<TR valign=top>
<TD align=right>de</TD><TD align=center>f</TD><TD>Gap-compressed per-base sequence divergence</TD></TR>
<TR valign=top>
<TD align=right>rl</TD><TD align=center>i</TD><TD>Length of query regions harboring repetitive seeds</TD></TR>
</TABLE></div></BLOCKQUOTE>
<P>
<P>
The
<B>cs</B> tag encodes difference sequences in the short form or the entire query
<I>AND</I> reference sequences in the long form. It consists of a series of operations:
<P><BLOCKQUOTE><div id='tbl'><TABLE border=1 cellspacing=0 cellpadding=3>
<TR valign=top>
<TD align=center><B>Op</B></TD><TD align=center><B>Regex</B></TD><TD align=center><B>Description</B></TD></TR>
<TR></TR><TR></TR>
<TR valign=top>
<TD align=right> =</TD><TD>[ACGTN]+</TD><TD>Identical sequence (long form)</TD></TR>
<TR valign=top>
<TD align=right> :</TD><TD>[0-9]+</TD><TD>Identical sequence length</TD></TR>
<TR valign=top>
<TD align=right> *</TD><TD>[acgtn][acgtn]</TD><TD>Substitution: ref to query</TD></TR>
<TR valign=top>
<TD align=right> +</TD><TD>[acgtn]+</TD><TD>Insertion to the reference</TD></TR>
<TR valign=top>
<TD align=right> -</TD><TD>[acgtn]+</TD><TD>Deletion from the reference</TD></TR>
<TR valign=top>
<TD align=right> ~</TD><TD>[acgtn]{2}[0-9]+[acgtn]{2}</TD><TD>Intron length and splice signal</TD></TR>
</TABLE></div></BLOCKQUOTE>
<P>
</BLOCKQUOTE>
<A name=11></A>
<H3>LIMITATIONS</H3>
<BLOCKQUOTE>
<TABLE cellpadding=3>
<TR valign=top><TD width=2% nowrap>
*
</TD><TD valign=bottom>
Minimap2 may produce suboptimal alignments through long low-complexity regions
where seed positions may be suboptimal. This should not be a big concern
because even the optimal alignment may be wrong in such regions.
</TD></TR>
<TR valign=top><TD width=2% nowrap>
*
</TD><TD valign=bottom>
Minimap2 requires SSE2 or NEON instructions to compile. It is possible to add
non-SSE2/NEON support, but it would make minimap2 slower by several times.
</TD></TR>
<TR></TR></TABLE></BLOCKQUOTE>
<A name=12></A>
<H3>SEE ALSO</H3>
<BLOCKQUOTE>
<P>
miniasm(1), minimap(1), bwa(1).
</BLOCKQUOTE>
<P><HR>
<TABLE width=100%><TR> <TD width=33%><I>minimap2-2.28-dirty (r1237)</I></TD> <TD width=33% align=center>minimap2 (1)</TD> <TD align=right width=33%><I>30 March 2025</I></TD> </TR></TABLE></div></BODY></HTML>
-32
View File
@@ -1,32 +0,0 @@
#include <sys/resource.h>
#include <sys/time.h>
#include "minimap.h"
int mm_verbose = 3;
int mm_dbg_flag = 0;
double mm_realtime0;
double cputime()
{
struct rusage r;
getrusage(RUSAGE_SELF, &r);
return r.ru_utime.tv_sec + r.ru_stime.tv_sec + 1e-6 * (r.ru_utime.tv_usec + r.ru_stime.tv_usec);
}
double realtime()
{
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
return tp.tv_sec + tp.tv_usec * 1e-6;
}
#include "ksort.h"
#define sort_key_128x(a) ((a).x)
KRADIX_SORT_INIT(128x, mm128_t, sort_key_128x, 8)
#define sort_key_64(x) (x)
KRADIX_SORT_INIT(64, uint64_t, sort_key_64, 8)
KSORT_INIT_GENERIC(uint32_t)
-183
View File
@@ -1,183 +0,0 @@
var getopt = function(args, ostr) {
var oli; // option letter list index
if (typeof(getopt.place) == 'undefined')
getopt.ind = 0, getopt.arg = null, getopt.place = -1;
if (getopt.place == -1) { // update scanning pointer
if (getopt.ind >= args.length || args[getopt.ind].charAt(getopt.place = 0) != '-') {
getopt.place = -1;
return null;
}
if (getopt.place + 1 < args[getopt.ind].length && args[getopt.ind].charAt(++getopt.place) == '-') { // found "--"
++getopt.ind;
getopt.place = -1;
return null;
}
}
var optopt = args[getopt.ind].charAt(getopt.place++); // character checked for validity
if (optopt == ':' || (oli = ostr.indexOf(optopt)) < 0) {
if (optopt == '-') return null; // if the user didn't specify '-' as an option, assume it means null.
if (getopt.place < 0) ++getopt.ind;
return '?';
}
if (oli+1 >= ostr.length || ostr.charAt(++oli) != ':') { // don't need argument
getopt.arg = null;
if (getopt.place < 0 || getopt.place >= args[getopt.ind].length) ++getopt.ind, getopt.place = -1;
} else { // need an argument
if (getopt.place >= 0 && getopt.place < args[getopt.ind].length)
getopt.arg = args[getopt.ind].substr(getopt.place);
else if (args.length <= ++getopt.ind) { // no arg
getopt.place = -1;
if (ostr.length > 0 && ostr.charAt(0) == ':') return ':';
return '?';
} else getopt.arg = args[getopt.ind]; // white space
getopt.place = -1;
++getopt.ind;
}
return optopt;
}
var c, gap_out_len = null;
while ((c = getopt(arguments, "l:")) != null)
if (c == 'l') gap_out_len = parseInt(getopt.arg);
if (getopt.ind == arguments.length) {
print("Usage: k8 mapstat.js [-l gapOutLen] <in.sam>|<in.paf>");
exit(1);
}
var buf = new Bytes();
var file = new File(arguments[getopt.ind]);
var re = /(\d+)([MIDSHNX=])/g;
var lineno = 0, n_pri = 0, n_2nd = 0, n_seq = 0, n_cigar_64k = 0, l_tot = 0, l_cov = 0;
var n_gap = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]];
function cov_len(regs)
{
regs.sort(function(a,b) {return a[0]-b[0]});
var st = regs[0][0], en = regs[0][1], l = 0;
for (var i = 1; i < regs.length; ++i) {
if (regs[i][0] < en)
en = en > regs[i][1]? en : regs[i][1];
else l += en - st, st = regs[i][0], en = regs[i][1];
}
l += en - st;
return l;
}
var last = null, last_qlen = null, regs = [];
while (file.readline(buf) >= 0) {
var line = buf.toString();
++lineno;
if (line.charAt(0) != '@') {
var t = line.split("\t", 12);
var m, rs, cigar = null, is_pri = false, is_sam = false, is_rev = false, tname = null;
var atlen = null, aqlen, qs, qe, mapq, ori_qlen;
if (t[4] == '+' || t[4] == '-') { // PAF
if (!/\ts2:i:\d+/.test(line)) {
++n_2nd;
continue;
}
if ((m = /\tcg:Z:(\S+)/.exec(line)) != null)
cigar = m[1];
if (cigar == null) {
warn("WARNING: no CIGAR at line " + lineno);
continue;
}
tname = t[5];
qs = parseInt(t[2]), qe = parseInt(t[3]);
aqlen = qe - qs;
is_rev = t[4] == '+'? false : true;
rs = parseInt(t[7]);
atlen = parseInt(t[8]) - rs;
mapq = parseInt(t[11]);
ori_qlen = parseInt(t[1]);
} else { // SAM
var flag = parseInt(t[1]);
if (flag & 4) continue;
if (flag & 0x100) {
++n_2nd;
continue;
}
cigar = t[5];
tname = t[2];
rs = parseInt(t[3]) - 1;
mapq = parseInt(t[4]);
aqlen = t[9].length;
is_sam = true;
is_rev = !!(flag&0x10);
}
++n_pri;
if (last != t[0]) {
if (last != null) {
l_tot += last_qlen;
l_cov += cov_len(regs);
}
regs = [];
++n_seq, last = t[0];
}
var M = 0, tl = 0, ql = 0, clip = [0, 0], n_cigar = 0, sclip = 0;
while ((m = re.exec(cigar)) != null) {
var l = parseInt(m[1]);
++n_cigar;
if (m[2] == 'M' || m[2] == '=' || m[2] == 'X') {
tl += l, ql += l, M += l;
} else if (m[2] == 'I' || m[2] == 'D') {
var type;
if (l < 50) type = 0;
else if (l < 100) type = 1;
else if (l < 300) type = 2;
else if (l < 400) type = 3;
else if (l < 1000) type = 4;
else type = 5;
if (m[2] == 'I') ql += l, ++n_gap[0][type];
else tl += l, ++n_gap[1][type];
if (gap_out_len != null && l >= gap_out_len)
print(t[0], ql, is_rev? '-' : '+', tname, rs + tl, m[2], l);
} else if (m[2] == 'N') {
tl += l;
} else if (m[2] == 'S') {
clip[M == 0? 0 : 1] = l, sclip += l;
} else if (m[2] == 'H') {
clip[M == 0? 0 : 1] = l;
}
}
if (n_cigar > 65535) ++n_cigar_64k;
if (ql + sclip != aqlen)
warn("WARNING: aligned query length is inconsistent with CIGAR at line " + lineno + " (" + (ql+sclip) + " != " + aqlen + ")");
if (atlen != null && atlen != tl)
warn("WARNING: aligned reference length is inconsistent with CIGAR at line " + lineno);
if (is_sam) {
qs = clip[is_rev? 1 : 0], qe = qs + ql;
ori_qlen = clip[0] + ql + clip[1];
}
regs.push([qs, qe]);
last_qlen = ori_qlen;
}
}
l_tot += last_qlen;
l_cov += cov_len(regs);
file.close();
buf.destroy();
if (gap_out_len == null) {
print("Number of mapped sequences: " + n_seq);
print("Number of primary alignments: " + n_pri);
print("Number of secondary alignments: " + n_2nd);
print("Number of primary alignments with >65535 CIGAR operations: " + n_cigar_64k);
print("Number of bases in mapped sequences: " + l_tot);
print("Number of mapped bases: " + l_cov);
print("Number of insertions in [0,50): " + n_gap[0][0]);
print("Number of insertions in [50,100): " + n_gap[0][1]);
print("Number of insertions in [100,300): " + n_gap[0][2]);
print("Number of insertions in [300,400): " + n_gap[0][3]);
print("Number of insertions in [400,1000): " + n_gap[0][4]);
print("Number of insertions in [1000,inf): " + n_gap[0][5]);
print("Number of deletions in [0,50): " + n_gap[1][0]);
print("Number of deletions in [50,100): " + n_gap[1][1]);
print("Number of deletions in [100,300): " + n_gap[1][2]);
print("Number of deletions in [300,400): " + n_gap[1][3]);
print("Number of deletions in [400,1000): " + n_gap[1][4]);
print("Number of deletions in [1000,inf): " + n_gap[1][5]);
}
-143
View File
@@ -1,143 +0,0 @@
var getopt = function(args, ostr) {
var oli; // option letter list index
if (typeof(getopt.place) == 'undefined')
getopt.ind = 0, getopt.arg = null, getopt.place = -1;
if (getopt.place == -1) { // update scanning pointer
if (getopt.ind >= args.length || args[getopt.ind].charAt(getopt.place = 0) != '-') {
getopt.place = -1;
return null;
}
if (getopt.place + 1 < args[getopt.ind].length && args[getopt.ind].charAt(++getopt.place) == '-') { // found "--"
++getopt.ind;
getopt.place = -1;
return null;
}
}
var optopt = args[getopt.ind].charAt(getopt.place++); // character checked for validity
if (optopt == ':' || (oli = ostr.indexOf(optopt)) < 0) {
if (optopt == '-') return null; // if the user didn't specify '-' as an option, assume it means null.
if (getopt.place < 0) ++getopt.ind;
return '?';
}
if (oli+1 >= ostr.length || ostr.charAt(++oli) != ':') { // don't need argument
getopt.arg = null;
if (getopt.place < 0 || getopt.place >= args[getopt.ind].length) ++getopt.ind, getopt.place = -1;
} else { // need an argument
if (getopt.place >= 0 && getopt.place < args[getopt.ind].length)
getopt.arg = args[getopt.ind].substr(getopt.place);
else if (args.length <= ++getopt.ind) { // no arg
getopt.place = -1;
if (ostr.length > 0 && ostr.charAt(0) == ':') return ':';
return '?';
} else getopt.arg = args[getopt.ind]; // white space
getopt.place = -1;
++getopt.ind;
}
return optopt;
}
var c, max_mapq = 60, mode = 0, err_out_q = 256, print_err = false, ovlp_ratio = 0.333;
while ((c = getopt(arguments, "Q:r:m:")) != null) {
if (c == 'Q') err_out_q = parseInt(getopt.arg), print_err = true;
else if (c == 'r') ovlp_ratio = parseFloat(getopt.arg);
else if (c == 'm') mode = parseInt(getopt.arg);
}
var file = arguments.length == getopt.ind? new File() : new File(arguments[getopt.ind]);
var buf = new Bytes();
var tot = [], err = [];
for (var q = 0; q <= max_mapq; ++q)
tot[q] = err[q] = 0;
function is_correct(s, b)
{
if (s[0] != b[0] || s[3] != b[3]) return false;
var o, l;
if (s[1] < b[1]) {
if (s[2] <= b[1]) return false;
o = (s[2] < b[2]? s[2] : b[2]) - b[1];
l = (s[2] > b[2]? s[2] : b[2]) - s[1];
} else {
if (b[2] <= s[1]) return false;
o = (s[2] < b[2]? s[2] : b[2]) - s[1];
l = (s[2] > b[2]? s[2] : b[2]) - b[1];
}
return o/l > ovlp_ratio? true : false;
}
function count_err(qname, a, tot, err, mode)
{
var s = qname.split("!");
if (a.length == 0) return;
if (s.length < 5 || (s[4] != '+' && s[4] != '-'))
throw Error("Failed to parse pbsim2fa read names '" + qname + "'");
s[2] = parseInt(s[2]);
s[3] = parseInt(s[3]);
s.shift(); // skip pbsim orginal read name
if (mode == 0 || mode == 1) { // longest only or first only
var max_i = 0;
if (mode == 0) {
var max = 0;
for (var i = 0; i < a.length; ++i)
if (a[i][2] - a[i][1] > max)
max = a[i][2] - a[i][1], max_i = i;
}
var mapq = a[max_i][4];
++tot[mapq];
if (!is_correct(s, a[max_i])) {
if (mapq >= err_out_q)
print('E', qname, a[max_i].join("\t"));
++err[mapq];
}
} else if (mode == 2) { // all primary mode
var max_err_mapq = -1, max_mapq = 0, max_err_i = -1;
for (var i = 0; i < a.length; ++i) {
max_mapq = max_mapq > a[i][4]? max_mapq : a[i][4];
if (!is_correct(s, a[i]))
if (a[i][4] > max_err_mapq)
max_err_mapq = a[i][4], max_err_i = i;
}
if (max_err_mapq >= 0) {
++tot[max_err_mapq], ++err[max_err_mapq];
if (max_err_mapq >= err_out_q)
print('E', qname, a[max_err_i].join("\t"));
} else ++tot[max_mapq];
}
}
var lineno = 0, last = null, a = [];
while (file.readline(buf) >= 0) {
var line = buf.toString();
++lineno;
if (line[0] != '@') {
var t = line.split("\t");
if (last != t[0]) {
if (last != null) count_err(last, a, tot, err, mode);
a = [], last = t[0];
}
if (t[4] == '+' || t[4] == '-') { // PAF
if (/\ts1:i:\d+/.test(line) && !/\ts2:i:\d+/.test(line)) // secondary alignment in minimap2 PAF
continue;
var mapq = parseInt(t[11]);
if (mapq > max_mapq) mapq = max_mapq;
a.push([t[5], parseInt(t[7]), parseInt(t[8]), t[4], mapq]);
}
}
}
if (last != null) count_err(last, a, tot, err, mode);
buf.destroy();
file.close();
var sum_tot = 0, sum_err = 0, q_out = -1, sum_tot2 = 0, sum_err2 = 0;
for (var q = max_mapq; q >= 0; --q) {
if (tot[q] == 0) continue;
if (q_out < 0 || err[q] > 0) {
if (q_out >= 0) print('Q', q_out, sum_tot, sum_err, (sum_err2/sum_tot2).toFixed(9));
sum_tot = sum_err = 0, q_out = q;
}
sum_tot += tot[q], sum_err += err[q];
sum_tot2 += tot[q], sum_err2 += err[q];
}
print('Q', q_out, sum_tot, sum_err, (sum_err2/sum_tot2).toFixed(9));
-81
View File
@@ -1,81 +0,0 @@
Bytes.prototype.reverse = function()
{
for (var i = 0; i < this.length>>1; ++i) {
var tmp = this[i];
this[i] = this[this.length - i - 1];
this[this.length - i - 1] = tmp;
}
}
// reverse complement a DNA string
Bytes.prototype.revcomp = function()
{
if (Bytes.rctab == null) {
var s1 = 'WSATUGCYRKMBDHVNwsatugcyrkmbdhvn';
var s2 = 'WSTAACGRYMKVHDBNwstaacgrymkvhdbn';
Bytes.rctab = [];
for (var i = 0; i < 256; ++i) Bytes.rctab[i] = 0;
for (var i = 0; i < s1.length; ++i)
Bytes.rctab[s1.charCodeAt(i)] = s2.charCodeAt(i);
}
for (var i = 0; i < this.length>>1; ++i) {
var tmp = this[this.length - i - 1];
this[this.length - i - 1] = Bytes.rctab[this[i]];
this[i] = Bytes.rctab[tmp];
}
if (this.length&1)
this[this.length>>1] = Bytes.rctab[this[this.length>>1]];
}
if (arguments.length < 2) {
print("Usage: k8 pbsim2paf.js <chr.list> <pbsim1.maf> [[pbsim2.maf] ...]");
exit(1);
}
var file, buf = new Bytes(), buf2 = new Bytes();
file = new File(arguments[0]);
var chr_list = [];
while (file.readline(buf) >= 0) {
var t = buf.toString().split(/\s+/);
chr_list.push(t[0]);
}
file.close();
for (var k = 1; k < arguments.length; ++k) {
var fn = arguments[k];
file = new File(fn);
var state = 0, reg;
while (file.readline(buf) >= 0) {
var line = buf.toString();
if (state == 0 && line.charAt(0) == 'a') {
state = 1;
} else if (state == 1 && line.charAt(0) == 's') {
var t = line.split(/\s+/);
var st = parseInt(t[2]);
reg = [st, st + parseInt(t[3])];
state = 2;
} else if (state == 2 && line.charAt(0) == 's') {
var m, t = line.split(/\s+/);
if ((m = /S(\d+)_\d+/.exec(t[1])) == null) throw Error("Failed to parse the read name");
var chr_id = parseInt(m[1]) - 1;
if (chr_id >= chr_list.length) throw Error("Index outside the chr list");
var name = [t[1], chr_list[chr_id], reg[0], reg[1], t[4]].join("!");
var seq = t[6].replace(/\-/g, "");
if (seq.length != parseInt(t[5])) throw Error("Inconsistent read length");
if (seq.indexOf("NN") < 0) {
if (t[4] == '-') {
buf2.set(seq, 0);
buf2.length = seq.length;
buf2.revcomp();
seq = buf2.toString();
}
print(">" + name);
print(seq);
}
state = 0;
}
}
file.close();
}
buf.destroy();
buf2.destroy();
-63
View File
@@ -1,63 +0,0 @@
#ifndef MMPRIV2_H
#define MMPRIV2_H
#include <assert.h>
#include "minimap.h"
#include "bseq.h"
#define MM_PARENT_UNSET (-1)
#define MM_PARENT_TMP_PRI (-2)
#define MM_DBG_NO_KALLOC 0x1
#define MM_DBG_PRINT_QNAME 0x2
#define MM_DBG_PRINT_SEED 0x4
#define MM_DBG_PRINT_ALN_SEQ 0x8
#define MM_SEED_LONG_JOIN (1ULL<<40)
#define MM_SEED_IGNORE (1ULL<<41)
#define MM_SEED_TANDEM (1ULL<<42)
#ifndef kroundup32
#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef KSTRING_T
#define KSTRING_T kstring_t
typedef struct __kstring_t {
unsigned l, m;
char *s;
} kstring_t;
#endif
double cputime(void);
double realtime(void);
void radix_sort_128x(mm128_t *beg, mm128_t *end);
void radix_sort_64(uint64_t *beg, uint64_t *end);
uint32_t ks_ksmall_uint32_t(size_t n, uint32_t arr[], size_t kk);
void mm_write_paf(kstring_t *s, const mm_idx_t *mi, const mm_bseq1_t *t, const mm_reg1_t *r);
void mm_write_sam(kstring_t *s, const mm_idx_t *mi, const mm_bseq1_t *t, const mm_reg1_t *r, int n_regs, const mm_reg1_t *regs);
int mm_chain_dp(int max_dist, int bw, int max_skip, int min_cnt, int min_sc, int64_t n, mm128_t *a, uint64_t **_u, void *km);
mm_reg1_t *mm_align_skeleton(void *km, const mm_mapopt_t *opt, const mm_idx_t *mi, int qlen, const char *qstr, int *n_regs_, mm_reg1_t *regs, mm128_t *a);
mm_reg1_t *mm_gen_regs(void *km, int qlen, int n_u, uint64_t *u, mm128_t *a);
void mm_split_reg(mm_reg1_t *r, mm_reg1_t *r2, int n, int qlen, mm128_t *a);
void mm_sync_regs(void *km, int n_regs, mm_reg1_t *regs);
int mm_set_sam_pri(int n, mm_reg1_t *r);
void mm_set_parent(void *km, float mask_level, int n, mm_reg1_t *r);
void mm_select_sub(void *km, float mask_level, float pri_ratio, int min_diff, int best_n, int *n_, mm_reg1_t *r);
void mm_filter_regs(void *km, const mm_mapopt_t *opt, int *n_regs, mm_reg1_t *regs);
void mm_join_long(void *km, const mm_mapopt_t *opt, int qlen, int *n_regs, mm_reg1_t *regs, mm128_t *a);
void mm_hit_sort_by_dp(void *km, int *n_regs, mm_reg1_t *r);
void mm_set_mapq(int n_regs, mm_reg1_t *regs, int min_chain_sc);
#ifdef __cplusplus
}
#endif
#endif
-211
View File
@@ -1,211 +0,0 @@
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "kalloc.h"
#include "kdq.h"
#include "kvec.h"
#include "sdust.h"
#define SD_WLEN 3
#define SD_WTOT (1<<(SD_WLEN<<1))
#define SD_WMSK (SD_WTOT - 1)
typedef struct {
int start, finish;
int r, l;
} perf_intv_t;
typedef kvec_t(perf_intv_t) perf_intv_v;
typedef kvec_t(uint64_t) uint64_v;
KDQ_INIT(int)
#if defined(_NO_NT4_TBL) || defined(_SDUST_MAIN)
unsigned char seq_nt4_table[256] = {
0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 0, 4, 1, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 0, 4, 1, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
};
#else
extern unsigned char seq_nt4_table[256];
#endif
struct sdust_buf_s {
kdq_t(int) *w;
perf_intv_v P; // the list of perfect intervals for the current window, sorted by descending start and then by ascending finish
uint64_v res; // the result
void *km; // memory pool
};
sdust_buf_t *sdust_buf_init(void *km)
{
sdust_buf_t *buf;
buf = (sdust_buf_t*)kcalloc(km, 1, sizeof(sdust_buf_t));
buf->km = km;
buf->w = kdq_init(int, buf->km);
return buf;
}
void sdust_buf_destroy(sdust_buf_t *buf)
{
if (buf == 0) return;
kdq_destroy(int, buf->w);
kfree(buf->km, buf->P.a); kfree(buf->km, buf->res.a); kfree(buf->km, buf);
}
static inline void shift_window(int t, kdq_t(int) *w, int T, int W, int *L, int *rw, int *rv, int *cw, int *cv)
{
int s;
if (kdq_size(w) >= W - SD_WLEN + 1) { // TODO: is this right for SD_WLEN!=3?
s = *kdq_shift(int, w);
*rw -= --cw[s];
if (*L > kdq_size(w))
--*L, *rv -= --cv[s];
}
kdq_push(int, w, t);
++*L;
*rw += cw[t]++;
*rv += cv[t]++;
if (cv[t] * 10 > T<<1) {
do {
s = kdq_at(w, kdq_size(w) - *L);
*rv -= --cv[s];
--*L;
} while (s != t);
}
}
static inline void save_masked_regions(void *km, uint64_v *res, perf_intv_v *P, int start)
{
int i, saved = 0;
perf_intv_t *p;
if (P->n == 0 || P->a[P->n - 1].start >= start) return;
p = &P->a[P->n - 1];
if (res->n) {
int s = res->a[res->n - 1]>>32, f = (uint32_t)res->a[res->n - 1];
if (p->start <= f) // if overlapping with or adjacent to the previous interval
saved = 1, res->a[res->n - 1] = (uint64_t)s<<32 | (f > p->finish? f : p->finish);
}
if (!saved) kv_push(uint64_t, km, *res, (uint64_t)p->start<<32|p->finish);
for (i = P->n - 1; i >= 0 && P->a[i].start < start; --i); // remove perfect intervals that have falled out of the window
P->n = i + 1;
}
static void find_perfect(void *km, perf_intv_v *P, const kdq_t(int) *w, int T, int start, int L, int rv, const int *cv)
{
int c[SD_WTOT], r = rv, i, max_r = 0, max_l = 0;
memcpy(c, cv, SD_WTOT * sizeof(int));
for (i = (long)kdq_size(w) - L - 1; i >= 0; --i) {
int j, t = kdq_at(w, i), new_r, new_l;
r += c[t]++;
new_r = r, new_l = kdq_size(w) - i - 1;
if (new_r * 10 > T * new_l) {
for (j = 0; j < P->n && P->a[j].start >= i + start; ++j) { // find insertion position
perf_intv_t *p = &P->a[j];
if (max_r == 0 || p->r * max_l > max_r * p->l)
max_r = p->r, max_l = p->l;
}
if (max_r == 0 || new_r * max_l >= max_r * new_l) { // then insert
max_r = new_r, max_l = new_l;
if (P->n == P->m) kv_resize(perf_intv_t, km, *P, P->n + 1);
memmove(&P->a[j+1], &P->a[j], (P->n - j) * sizeof(perf_intv_t)); // make room
++P->n;
P->a[j].start = i + start, P->a[j].finish = kdq_size(w) + (SD_WLEN - 1) + start;
P->a[j].r = new_r, P->a[j].l = new_l;
}
}
}
}
const uint64_t *sdust_core(const uint8_t *seq, int l_seq, int T, int W, int *n, sdust_buf_t *buf)
{
int rv = 0, rw = 0, L = 0, cv[SD_WTOT], cw[SD_WTOT];
int i, start, l; // _start_: start of the current window; _l_: length of a contiguous A/C/G/T (sub)sequence
unsigned t; // current word
buf->P.n = buf->res.n = 0;
buf->w->front = buf->w->count = 0;
memset(cv, 0, SD_WTOT * sizeof(int));
memset(cw, 0, SD_WTOT * sizeof(int));
if (l_seq < 0) l_seq = strlen((const char*)seq);
for (i = l = t = 0; i <= l_seq; ++i) {
int b = i < l_seq? seq_nt4_table[seq[i]] : 4;
if (b < 4) { // an A/C/G/T base
++l, t = (t<<2 | b) & SD_WMSK;
if (l >= SD_WLEN) { // we have seen a word
start = (l - W > 0? l - W : 0) + (i + 1 - l); // set the start of the current window
save_masked_regions(buf->km, &buf->res, &buf->P, start); // save intervals falling out of the current window?
shift_window(t, buf->w, T, W, &L, &rw, &rv, cw, cv);
if (rw * 10 > L * T)
find_perfect(buf->km, &buf->P, buf->w, T, start, L, rv, cv);
}
} else { // N or the end of sequence; N effectively breaks input into pieces of independent sequences
start = (l - W + 1 > 0? l - W + 1 : 0) + (i + 1 - l);
while (buf->P.n) save_masked_regions(buf->km, &buf->res, &buf->P, start++); // clear up unsaved perfect intervals
l = t = 0;
}
}
*n = buf->res.n;
return buf->res.a;
}
uint64_t *sdust(void *km, const uint8_t *seq, int l_seq, int T, int W, int *n)
{
uint64_t *ret;
sdust_buf_t *buf;
buf = sdust_buf_init(km);
ret = (uint64_t*)sdust_core(seq, l_seq, T, W, n, buf);
buf->res.a = 0;
sdust_buf_destroy(buf);
return ret;
}
#ifdef _SDUST_MAIN
#include <zlib.h>
#include <stdio.h>
#include <unistd.h>
#include "kseq.h"
KSEQ_INIT(gzFile, gzread)
int main(int argc, char *argv[])
{
gzFile fp;
kseq_t *ks;
int W = 64, T = 20, c;
while ((c = getopt(argc, argv, "w:t:")) >= 0) {
if (c == 'w') W = atoi(optarg);
else if (c == 't') T = atoi(optarg);
}
if (optind == argc) {
fprintf(stderr, "Usage: sdust [-w %d] [-t %d] <in.fa>\n", W, T);
return 1;
}
fp = strcmp(argv[optind], "-")? gzopen(argv[optind], "r") : gzdopen(fileno(stdin), "r");
ks = kseq_init(fp);
while (kseq_read(ks) >= 0) {
uint64_t *r;
int i, n;
r = sdust(0, (uint8_t*)ks->seq.s, -1, T, W, &n);
for (i = 0; i < n; ++i)
printf("%s\t%d\t%d\n", ks->name.s, (int)(r[i]>>32), (int)r[i]);
free(r);
}
kseq_destroy(ks);
gzclose(fp);
return 0;
}
#endif
-25
View File
@@ -1,25 +0,0 @@
#ifndef SDUST_H
#define SDUST_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct sdust_buf_s;
typedef struct sdust_buf_s sdust_buf_t;
// the simple interface
uint64_t *sdust(void *km, const uint8_t *seq, int l_seq, int T, int W, int *n);
// the following interface dramatically reduce heap allocations when sdust is frequently called.
sdust_buf_t *sdust_buf_init(void *km);
void sdust_buf_destroy(sdust_buf_t *buf);
const uint64_t *sdust_core(const uint8_t *seq, int l_seq, int T, int W, int *n, sdust_buf_t *buf);
#ifdef __cplusplus
}
#endif
#endif
-143
View File
@@ -1,143 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "kvec.h"
#include "minimap.h"
unsigned char seq_nt4_table[256] = {
0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 0, 4, 1, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 0, 4, 1, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
};
static inline uint64_t hash64(uint64_t key, uint64_t mask)
{
key = (~key + (key << 21)) & mask; // key = (key << 21) - key - 1;
key = key ^ key >> 24;
key = ((key + (key << 3)) + (key << 8)) & mask; // key * 265
key = key ^ key >> 14;
key = ((key + (key << 2)) + (key << 4)) & mask; // key * 21
key = key ^ key >> 28;
key = (key + (key << 31)) & mask;
return key;
}
typedef struct { // a simplified version of kdq
int front, count;
int a[32];
} tiny_queue_t;
static inline void tq_push(tiny_queue_t *q, int x)
{
q->a[((q->count++) + q->front) & 0x1f] = x;
}
static inline int tq_shift(tiny_queue_t *q)
{
int x;
if (q->count == 0) return -1;
x = q->a[q->front++];
q->front &= 0x1f;
--q->count;
return x;
}
/**
* Find symmetric (w,k)-minimizers on a DNA sequence
*
* @param km thread-local memory pool; using NULL falls back to malloc()
* @param str DNA sequence
* @param len length of $str
* @param w find a minimizer for every $w consecutive k-mers
* @param k k-mer size
* @param rid reference ID; will be copied to the output $p array
* @param is_hpc homopolymer-compressed or not
* @param p minimizers
* p->a[i].x = kMer<<8 | kmerSpan
* p->a[i].y = rid<<32 | lastPos<<1 | strand
* where lastPos is the position of the last base of the i-th minimizer,
* and strand indicates whether the minimizer comes from the top or the bottom strand.
* Callers may want to set "p->n = 0"; otherwise results are appended to p
*/
void mm_sketch(void *km, const char *str, int len, int w, int k, uint32_t rid, int is_hpc, mm128_v *p)
{
uint64_t shift1 = 2 * (k - 1), mask = (1ULL<<2*k) - 1, kmer[2] = {0,0};
int i, j, l, buf_pos, min_pos, kmer_span = 0;
mm128_t *buf, min = { UINT64_MAX, UINT64_MAX };
tiny_queue_t tq;
assert(len > 0 && w > 0 && k > 0 && k <= 28); // 56 bits for k-mer; could use long k-mers, but 28 enough in practice
buf = (mm128_t*)alloca(w * 16);
memset(buf, 0xff, w * 16);
memset(&tq, 0, sizeof(tiny_queue_t));
kv_resize(mm128_t, km, *p, p->n + len/w);
for (i = l = buf_pos = min_pos = 0; i < len; ++i) {
int c = seq_nt4_table[(uint8_t)str[i]];
mm128_t info = { UINT64_MAX, UINT64_MAX };
if (c < 4) { // not an ambiguous base
int z;
if (is_hpc) {
int skip_len = 1;
if (i + 1 < len && seq_nt4_table[(uint8_t)str[i + 1]] == c) {
for (skip_len = 2; i + skip_len < len; ++skip_len)
if (seq_nt4_table[(uint8_t)str[i + skip_len]] != c)
break;
i += skip_len - 1; // put $i at the end of the current homopolymer run
}
tq_push(&tq, skip_len);
kmer_span += skip_len;
if (tq.count > k) kmer_span -= tq_shift(&tq);
if (kmer_span >= 256) continue; // make sure $kmer_span does not take more than 8 bits
} else kmer_span = l + 1 < k? l + 1 : k;
kmer[0] = (kmer[0] << 2 | c) & mask; // forward k-mer
kmer[1] = (kmer[1] >> 2) | (3ULL^c) << shift1; // reverse k-mer
if (kmer[0] == kmer[1]) continue; // skip "symmetric k-mers" as we don't know it strand
z = kmer[0] < kmer[1]? 0 : 1; // strand
if (++l >= k) {
info.x = hash64(kmer[z], mask) << 8 | kmer_span;
info.y = (uint64_t)rid<<32 | (uint32_t)i<<1 | z;
}
} else l = 0, tq.count = tq.front = 0, kmer_span = 0;
buf[buf_pos] = info; // need to do this here as appropriate buf_pos and buf[buf_pos] are needed below
if (l == w + k - 1) { // special case for the first window - because identical k-mers are not stored yet
for (j = buf_pos + 1; j < w; ++j)
if (min.x == buf[j].x && buf[j].y != min.y) kv_push(mm128_t, km, *p, buf[j]);
for (j = 0; j < buf_pos; ++j)
if (min.x == buf[j].x && buf[j].y != min.y) kv_push(mm128_t, km, *p, buf[j]);
}
if (info.x <= min.x) { // a new minimum; then write the old min
if (l >= w + k) kv_push(mm128_t, km, *p, min);
min = info, min_pos = buf_pos;
} else if (buf_pos == min_pos) { // old min has moved outside the window
if (l >= w + k - 1) kv_push(mm128_t, km, *p, min);
for (j = buf_pos + 1, min.x = UINT64_MAX; j < w; ++j) // the two loops are necessary when there are identical k-mers
if (min.x >= buf[j].x) min = buf[j], min_pos = j; // >= is important s.t. min is always the closest k-mer
for (j = 0; j <= buf_pos; ++j)
if (min.x >= buf[j].x) min = buf[j], min_pos = j;
if (l >= w + k - 1) { // write identical k-mers
for (j = buf_pos + 1; j < w; ++j) // these two loops make sure the output is sorted
if (min.x == buf[j].x && min.y != buf[j].y) kv_push(mm128_t, km, *p, buf[j]);
for (j = 0; j <= buf_pos; ++j)
if (min.x == buf[j].x && min.y != buf[j].y) kv_push(mm128_t, km, *p, buf[j]);
}
}
if (++buf_pos == w) buf_pos = 0;
}
if (min.x != UINT64_MAX)
kv_push(mm128_t, km, *p, min);
}
-278
View File
@@ -1,278 +0,0 @@
>MT_human
GATCACAGGTCTATCACCCTATTAACCACTCACGGGAGCTCTCCATGCATTTGGTATTTT
CGTCTGGGGGGTATGCACGCGATAGCATTGCGAGACGCTGGAGCCGGAGCACCCTATGTC
GCAGTATCTGTCTTTGATTCCTGCCTCATCCTATTATTTATCGCACCTACGTTCAATATT
ACAGGCGAACATACTTACTAAAGTGTGTTAATTAATTAATGCTTGTAGGACATAATAATA
ACAATTGAATGTCTGCACAGCCACTTTCCACACAGACATCATAACAAAAAATTTCCACCA
AACCCCCCCTCCCCCGCTTCTGGCCACAGCACTTAAACACATCTCTGCCAAACCCCAAAA
ACAAAGAACCCTAACACCAGCCTAACCAGATTTCAAATTTTATCTTTTGGCGGTATGCAC
TTTTAACAGTCACCCCCCAACTAACACATTATTTTCCCCTCCCACTCCCATACTACTAAT
CTCATCAATACAACCCCCGCCCATCCTACCCAGCACACACACACCGCTGCTAACCCCATA
CCCCGAACCAACCAAACCCCAAAGACACCCCCCACAGTTTATGTAGCTTACCTCCTCAAA
GCAATACACTGAAAATGTTTAGACGGGCTCACATCACCCCATAAACAAATAGGTTTGGTC
CTAGCCTTTCTATTAGCTCTTAGTAAGATTACACATGCAAGCATCCCCGTTCCAGTGAGT
TCACCCTCTAAATCACCACGATCAAAAGGAACAAGCATCAAGCACGCAGCAATGCAGCTC
AAAACGCTTAGCCTAGCCACACCCCCACGGGAAACAGCAGTGATTAACCTTTAGCAATAA
ACGAAAGTTTAACTAAGCTATACTAACCCCAGGGTTGGTCAATTTCGTGCCAGCCACCGC
GGTCACACGATTAACCCAAGTCAATAGAAGCCGGCGTAAAGAGTGTTTTAGATCACCCCC
TCCCCAATAAAGCTAAAACTCACCTGAGTTGTAAAAAACTCCAGTTGACACAAAATAGAC
TACGAAAGTGGCTTTAACATATCTGAACACACAATAGCTAAGACCCAAACTGGGATTAGA
TACCCCACTATGCTTAGCCCTAAACCTCAACAGTTAAATCAACAAAACTGCTCGCCAGAA
CACTACGAGCCACAGCTTAAAACTCAAAGGACCTGGCGGTGCTTCATATCCCTCTAGAGG
AGCCTGTTCTGTAATCGATAAACCCCGATCAACCTCACCACCTCTTGCTCAGCCTATATA
CCGCCATCTTCAGCAAACCCTGATGAAGGCTACAAAGTAAGCGCAAGTACCCACGTAAAG
ACGTTAGGTCAAGGTGTAGCCCATGAGGTGGCAAGAAATGGGCTACATTTTCTACCCCAG
AAAACTACGATAGCCCTTATGAAACTTAAGGGTCGAAGGTGGATTTAGCAGTAAACTAAG
AGTAGAGTGCTTAGTTGAACAGGGCCCTGAAGCGCGTACACACCGCCCGTCACCCTCCTC
AAGTATACTTCAAAGGACATTTAACTAAAACCCCTACGCATTTATATAGAGGAGACAAGT
CGTAACATGGTAAGTGTACTGGAAAGTGCACTTGGACGAACCAGAGTGTAGCTTAACACA
AAGCACCCAACTTACACTTAGGAGATTTCAACTTAACTTGACCGCTCTGAGCTAAACCTA
GCCCCAAACCCACTCCACCTTACTACCAGACAACCTTAGCCAAACCATTTACCCAAATAA
AGTATAGGCGATAGAAATTGAAACCTGGCGCAATAGATATAGTACCGCAAGGGAAAGATG
AAAAATTATAACCAAGCATAATATAGCAAGGACTAACCCCTATACCTTCTGCATAATGAA
TTAACTAGAAATAACTTTGCAAGGAGAGCCAAAGCTAAGACCCCCGAAACCAGACGAGCT
ACCTAAGAACAGCTAAAAGAGCACACCCGTCTATGTAGCAAAATAGTGGGAAGATTTATA
GGTAGAGGCGACAAACCTACCGAGCCTGGTGATAGCTGGTTGTCCAAGATAGAATCTTAG
TTCAACTTTAAATTTGCCCACAGAACCCTCTAAATCCCCTTGTAAATTTAACTGTTAGTC
CAAAGAGGAACAGCTCTTTGGACACTAGGAAAAAACCTTGTAGAGAGAGTAAAAAATTTA
ACACCCATAGTAGGCCTAAAAGCAGCCACCAATTAAGAAAGCGTTCAAGCTCAACACCCA
CTACCTAAAAAATCCCAAACATATAACTGAACTCCTCACACCCAATTGGACCAATCTATC
ACCCTATAGAAGAACTAATGTTAGTATAAGTAACATGAAAACATTCTCCTCCGCATAAGC
CTGCGTCAGATTAAAACACTGAACTGACAATTAACAGCCCAATATCTACAATCAACCAAC
AAGTCATTATTACCCTCACTGTCAACCCAACACAGGCATGCTCATAAGGAAAGGTTAAAA
AAAGTAAAAGGAACTCGGCAAATCTTACCCCGCCTGTTTACCAAAAACATCACCTCTAGC
ATCACCAGTATTAGAGGCACCGCCTGCCCAGTGACACATGTTTAACGGCCGCGGTACCCT
AACCGTGCAAAGGTAGCATAATCACTTGTTCCTTAAATAGGGACCTGTATGAATGGCTCC
ACGAGGGTTCAGCTGTCTCTTACTTTTAACCAGTGAAATTGACCTGCCCGTGAAGAGGCG
GGCATAACACAGCAAGACGAGAAGACCCTATGGAGCTTTAATTTATTAATGCAAACAGTA
CCTAACAAACCCACAGGTCCTAAACTACCAAACCTGCATTAAAAATTTCGGTTGGGGCGA
CCTCGGAGCAGAACCCAACCTCCGAGCAGTACATGCTAAGACTTCACCAGTCAAAGCGAA
CTACTATACTCAATTGATCCAATAACTTGACCAACGGAACAAGTTACCCTAGGGATAACA
GCGCAATCCTATTCTAGAGTCCATATCAACAATAGGGTTTACGACCTCGATGTTGGATCA
GGACATCCCGATGGTGCAGCCGCTATTAAAGGTTCGTTTGTTCAACGATTAAAGTCCTAC
GTGATCTGAGTTCAGACCGGAGTAATCCAGGTCGGTTTCTATCTACaTTCAAATTCCTCC
CTGTACGAAAGGACAAGAGAAATAAGGCCTACTTCACAAAGCGCCTTCCCCCGTAAATGA
TATCATCTCAACTTAGTATTATACCCACACCCACCCAAGAACAGGGTTTGTTAAGATGGC
AGAGCCCGGTAATCGCATAAAACTTAAAACTTTACAGTCAGAGGTTCAATTCCTCTTCTT
AACAACATACCCATGGCCAACCTCCTACTCCTCATTGTACCCATTCTAATCGCAATGGCA
TTCCTAATGCTTACCGAACGAAAAATTCTAGGCTATATACAACTACGCAAAGGCCCCAAC
GTTGTAGGCCCCTACGGGCTACTACAACCCTTCGCTGACGCCATAAAACTCTTCACCAAA
GAGCCCCTAAAACCCGCCACATCTACCATCACCCTCTACATCACCGCCCCGACCTTAGCT
CTCACCATCGCTCTTCTACTATGAACCCCCCTCCCCATACCCAACCCCCTGGTCAACCTC
AACCTAGGCCTCCTATTTATTCTAGCCACCTCTAGCCTAGCCGTTTACTCAATCCTCTGA
TCAGGGTGAGCATCAAACTCAAACTACGCCCTGATCGGCGCACTGCGAGCAGTAGCCCAA
ACAATCTCATATGAAGTCACCCTAGCCATCATTCTACTATCAACATTACTAATAAGTGGC
TCCTTTAACCTCTCCACCCTTATCACAACACAAGAACACCTCTGATTACTCCTGCCATCA
TGACCCTTGGCCATAATATGATTTATCTCCACACTAGCAGAGACCAACCGAACCCCCTTC
GACCTTGCCGAAGGGGAGTCCGAACTAGTCTCAGGCTTCAACATCGAATACGCCGCAGGC
CCCTTCGCCCTATTCTTCATAGCCGAATACACAAACATTATTATAATAAACACCCTCACC
ACTACAATCTTCCTAGGAACAACATATGACGCACTCTCCCCTGAACTCTACACAACATAT
TTTGTCACCAAGACCCTACTTCTAACCTCCCTGTTCTTATGAATTCGAACAGCATACCCC
CGATTCCGCTACGACCAACTCATACACCTCCTATGAAAAAACTTCCTACCACTCACCCTA
GCATTACTTATATGATATGTCTCCATACCCATTACAATCTCCAGCATTCCCCCTCAAACC
TAAGAAATATGTCTGATAAAAGAGTTACTTTGATAGAGTAAATAATAGGAGCTTAAACCC
CCTTATTTCTAGGACTATGAGAATCGAACCCATCCCTGAGAATCCAAAATTCTCCGTGCC
ACCTATCACACCCCATCCTAAAGTAAGGTCAGCTAAATAAGCTATCGGGCCCATACCCCG
AAAATGTTGGTTATACCCTTCCCGTACTAATTAATCCCCTGGCCCAACCCGTCATCTACT
CTACCATCTTTGCAGGCACACTCATCACAGCGCTAAGCTCGCACTGATTTTTTACCTGAG
TAGGCCTAGAAATAAACATGCTAGCTTTTATTCCAGTTCTAACCAAAAAAATAAACCCTC
GTTCCACAGAAGCTGCCATCAAGTATTTCCTCACGCAAGCAACCGCATCCATAATCCTTC
TAATAGCTATCCTCTTCAACAATATACTCTCCGGACAATGAACCATAACCAATACTACCA
ATCAATACTCATCATTAATAATCATAATAGCTATAGCAATAAAACTAGGAATAGCCCCCT
TTCACTTCTGAGTCCCAGAGGTTACCCAAGGCACCCCTCTGACATCCGGCCTGCTTCTTC
TCACATGACAAAAACTAGCCCCCATCTCAATCATATACCAAATCTCTCCCTCACTAAACG
TAAGCCTTCTCCTCACTCTCTCAATCTTATCCATCATAGCAGGCAGTTGAGGTGGATTAA
ACCAAACCCAGCTACGCAAAATCTTAGCATACTCCTCAATTACCCACATAGGATGAATAA
TAGCAGTTCTACCGTACAACCCTAACATAACCATTCTTAATTTAACTATTTATATTATCC
TAACTACTACCGCATTCCTACTACTCAACTTAAACTCCAGCACCACGACCCTACTACTAT
CTCGCACCTGAAACAAGCTAACATGACTAACACCCTTAATTCCATCCACCCTCCTCTCCC
TAGGAGGCCTGCCCCCGCTAACCGGCTTTTTGCCCAAATGGGCCATTATCGAAGAATTCA
CAAAAAACAATAGCCTCATCATCCCCACCATCATAGCCACCATCACCCTCCTTAACCTCT
ACTTCTACCTACGCCTAATCTACTCCACCTCAATCACACTACTCCCCATATCTAACAACG
TAAAAATAAAATGACAGTTTGAACATACAAAACCCACCCCATTCCTCCCCACACTCATCG
CCCTTACCACGCTACTCCTACCTATCTCCCCTTTTATACTAATAATCTTATAGAAATTTA
GGTTAAATACAGACCAAGAGCCTTCAAAGCCCTCAGTAAGTTGCAATACTTAATTTCTGT
AACAGCTAAGGACTGCAAAACCCCACTCTGCATCAACTGAACGCAAATCAGCCACTTTAA
TTAAGCTAAGCCCTTACTAGACCAATGGGACTTAAACCCACAAACACTTAGTTAACAGCT
AAGCACCCTAATCAACTGGCTTCAATCTACTTCTCCCGCCGCCGGGAAAAAAGGCGGGAG
AAGCCCCGGCAGGTTTGAAGCTGCTTCTTCGAATTTGCAATTCAATATGAAAATCACCTC
GGAGCTGGTAAAAAGAGGCCTAACCCCTGTCTTTAGATTTACAGTCCAATGCTTCACTCA
GCCATTTTACCTCACCCCCACTGATGTTCGCCGACCGTTGACTATTCTCTACAAACCACA
AAGACATTGGAACACTATACCTATTATTCGGCGCATGAGCTGGAGTCCTAGGCACAGCTC
TAAGCCTCCTTATTCGAGCCGAGCTGGGCCAGCCAGGCAACCTTCTAGGTAACGACCACA
TCTACAACGTTATCGTCACAGCCCATGCATTTGTAATAATCTTCTTCATAGTAATACCCA
TCATAATCGGAGGCTTTGGCAACTGACTAGTTCCCCTAATAATCGGTGCCCCCGATATGG
CGTTTCCCCGCATAAACAACATAAGCTTCTGACTCTTACCTCCCTCTCTCCTACTCCTGC
TCGCATCTGCTATAGTGGAGGCCGGAGCAGGAACAGGTTGAACAGTCTACCCTCCCTTAG
CAGGGAACTACTCCCACCCTGGAGCCTCCGTAGACCTAACCATCTTCTCCTTACACCTAG
CAGGTGTCTCCTCTATCTTAGGGGCCATCAATTTCATCACAACAATTATCAATATAAAAC
CCCCTGCCATAACCCAATACCAAACGCCCCTCTTCGTCTGATCCGTCCTAATCACAGCAG
TCCTACTTCTCCTATCTCTCCCAGTCCTAGCTGCTGGCATCACTATACTACTAACAGACC
GCAACCTCAACACCACCTTCTTCGACCCCGCCGGAGGAGGAGACCCCATTCTATACCAAC
ACCTATTCTGATTTTTCGGTCACCCTGAAGTTTATATTCTTATCCTACCAGGCTTCGGAA
TAATCTCCCATATTGTAACTTACTACTCCGGAAAAAAAGAACCATTTGGATACATAGGTA
TGGTCTGAGCTATGATATCAATTGGCTTCCTAGGGTTTATCGTGTGAGCACACCATATAT
TTACAGTAGGAATAGACGTAGACACACGAGCATATTTCACCTCCGCTACCATAATCATCG
CTATCCCCACCGGCGTCAAAGTATTTAGCTGACTCGCCACACTCCACGGAAGCAATATGA
AATGATCTGCTGCAGTGCTCTGAGCCCTAGGATTCATCTTTCTTTTCACCGTAGGTGGCC
TGACTGGCATTGTATTAGCAAACTCATCACTAGACATCGTACTACACGACACGTACTACG
TTGTAGCCCACTTCCACTATGTCCTATCAATAGGAGCTGTATTTGCCATCATAGGAGGCT
TCATTCACTGATTTCCCCTATTCTCAGGCTACACCCTAGACCAAACCTACGCCAAAATCC
ATTTCACTATCATATTCATCGGCGTAAATCTAACTTTCTTCCCACAACACTTTCTCGGCC
TATCCGGAATGCCCCGACGTTACTCGGACTACCCCGATGCATACACCACATGAAACATCC
TATCATCTGTAGGCTCATTCATTTCTCTAACAGCAGTAATATTAATAATTTTCATGATTT
GAGAAGCCTTCGCTTCGAAGCGAAAAGTCCTAATAGTAGAAGAACCCTCCATAAACCTGG
AGTGACTATATGGATGCCCCCCACCCTACCACACATTCGAAGAACCCGTATACATAAAAT
CTAGACAAAAAAGGAAGGAATCGAACCCCCCAAAGCTGGTTTCAAGCCAACCCCATGGCC
TCCATGACTTTTTCAAAAAGGTATTAGAAAAACCATTTCATAACTTTGTCAAAGTTAAAT
TATAGGCTAAATCCTATATATCTTAATGGCACATGCAGCGCAAGTAGGTCTACAAGACGC
TACTTCCCCTATCATAGAAGAGCTTATCACCTTTCATGATCACGCCCTCATAATCATTTT
CCTTATCTGCTTCCTAGTCCTGTATGCCCTTTTCCTAACACTCACAACAAAACTAACTAA
TACTAACATCTCAGACGCTCAGGAAATAGAAACCGTCTGAACTATCCTGCCCGCCATCAT
CCTAGTCCTCATCGCCCTCCCATCCCTACGCATCCTTTACATAACAGACGAGGTCAACGA
TCCCTCCCTTACCATCAAATCAATTGGCCACCAATGGTACTGAACCTACGAGTACACCGA
CTACGGCGGACTAATCTTCAACTCCTACATACTTCCCCCATTATTCCTAGAACCAGGCGA
CCTGCGACTCCTTGACGTTGACAATCGAGTAGTACTCCCGATTGAAGCCCCCATTCGTAT
AATAATTACATCACAAGACGTCTTGCACTCATGAGCTGTCCCCACATTAGGCTTAAAAAC
AGATGCAATTCCCGGACGTCTAAACCAAACCACTTTCACCGCTACACGACCGGGGGTATA
CTACGGTCAATGCTCTGAAATCTGTGGAGCAAACCACAGTTTCATGCCCATCGTCCTAGA
ATTAATTCCCCTAAAAATCTTTGAAATAGGGCCCGTATTTACCCTATAGCACCCCCTCTA
CCCCCTCTAGAGCCCACTGTAAAGCTAACTTAGCATTAACCTTTTAAGTTAAAGATTAAG
AGAACCAACACCTCTTTACAGTGAAATGCCCCAACTAAATACTACCGTATGGCCCACCAT
AATTACCCCCATACTCCTTACACTATTCCTCATCACCCAACTAAAAATATTAAACACAAA
CTACCACCTACCTCCCTCACCAAAGCCCATAAAAATAAAAAATTATAACAAACCCTGAGA
ACCAAAATGAACGAAAATCTGTTCGCTTCATTCATTGCCCCCACAATCCTAGGCCTACCC
GCCGCAGTACTGATCATTCTATTTCCCCCTCTATTGATCCCCACCTCCAAATATCTCATC
AACAACCGACTAATCACCACCCAACAATGACTAATCAAACTAACCTCAAAACAAATGATA
ACCATACACAACACTAAAGGACGAACCTGATCTCTTATACTAGTATCCTTAATCATTTTT
ATTGCCACAACTAACCTCCTCGGACTCCTGCCTCACTCATTTACACCAACCACCCAACTA
TCTATAAACCTAGCCATGGCCATCCCCTTATGAGCGGGCACAGTGATTATAGGCTTTCGC
TCTAAGATTAAAAATGCCCTAGCCCACTTCTTACCACAAGGCACACCTACACCCCTTATC
CCCATACTAGTTATTATCGAAACCATCAGCCTACTCATTCAACCAATAGCCCTGGCCGTA
CGCCTAACCGCTAACATTACTGCAGGCCACCTACTCATGCACCTAATTGGAAGCGCCACC
CTAGCAATATCAACCATTAACCTTCCCTCTACACTTATCATCTTCACAATTCTAATTCTA
CTGACTATCCTAGAAATCGCTGTCGCCTTAATCCAAGCCTACGTTTTCACACTTCTAGTA
AGCCTCTACCTGCACGACAACACATAATGACCCACCAATCACATGCCTATCATATAGTAA
AACCCAGCCCATGACCCCTAACAGGGGCCCTCTCAGCCCTCCTAATGACCTCCGGCCTAG
CCATGTGATTTCACTTCCACTCCATAACGCTCCTCATACTAGGCCTACTAACCAACACAC
TAACCATATACCAATGATGGCGCGATGTAACACGAGAAAGCACATACCAAGGCCACCACA
CACCACCTGTCCAAAAAGGCCTTCGATACGGGATAATCCTATTTATTACCTCAGAAGTTT
TTTTCTTCGCAGGATTTTTCTGAGCCTTTTACCACTCCAGCCTAGCCCCTACCCCCCAAT
TAGGAGGGCACTGGCCCCCAACAGGCATCACCCCGCTAAATCCCCTAGAAGTCCCACTCC
TAAACACATCCGTATTACTCGCATCAGGAGTATCAATCACCTGAGCTCACCATAGTCTAA
TAGAAAACAACCGAAACCAAATAATTCAAGCACTGCTTATTACAATTTTACTGGGTCTCT
ATTTTACCCTCCTACAAGCCTCAGAGTACTTCGAGTCTCCCTTCACCATTTCCGACGGCA
TCTACGGCTCAACATTTTTTGTAGCCACAGGCTTCCACGGACTTCACGTCATTATTGGCT
CAACTTTCCTCACTATCTGCTTCATCCGCCAACTAATATTTCACTTTACATCCAAACATC
ACTTTGGCTTCGAAGCCGCCGCCTGATACTGGCATTTTGTAGATGTGGTTTGACTATTTC
TGTATGTCTCCATCTATTGATGAGGGTCTTACTCTTTTAGTATAAATAGTACCGTTAACT
TCCAATTAACTAGTTTTGACAACATTCAAAAAAGAGTAATAAACTTCGCCTTAATTTTAA
TAATCAACACCCTCCTAGCCTTACTACTAATAATTATTACATTTTGACTACCACAACTCA
ACGGCTACATAGAAAAATCCACCCCTTACGAGTGCGGCTTCGACCCTATATCCCCCGCCC
GCGTCCCTTTCTCCATAAAATTCTTCTTAGTAGCTATTACCTTCTTATTATTTGATCTAG
AAATTGCCCTCCTTTTACCCCTACCATGAGCCCTACAAACAACTAACCTGCCACTAATAG
TTATGTCATCCCTCTTATTAATCATCATCCTAGCCCTAAGTCTGGCCTATGAGTGACTAC
AAAAAGGATTAGACTGAACCGAATTGGTATATAGTTTAAACAAAACGAATGATTTCGACT
CATTAAATTATGATAATCATATTTACCAAATGCCCCTCATTTACATAAATATTATACTAG
CATTTACCATCTCACTTCTAGGAATACTAGTATATCGCTCACACCTCATATCCTCCCTAC
TATGCCTAGAAGGAATAATACTATCGCTGTTCATTATAGCTACTCTCATAACCCTCAACA
CCCACTCCCTCTTAGCCAATATTGTGCCTATTGCCATACTAGTCTTTGCCGCCTGCGAAG
CAGCGGTGGGCCTAGCCCTACTAGTCTCAATCTCCAACACATATGGCCTAGACTACGTAC
ATAACCTAAACCTACTCCAATGCTAAAACTAATCGTCCCAACAATTATATTACTACCACT
GACATGACTTTCCAAAAAACACATAATTTGAATCAACACAACCACCCACAGCCTAATTAT
TAGCATCATCCCTCTACTATTTTTTAACCAAATCAACAACAACCTATTTAGCTGTTCCCC
AACCTTTTCCTCCGACCCCCTAACAACCCCCCTCCTAATACTAACTACCTGACTCCTACC
CCTCACAATCATGGCAAGCCAACGCCACTTATCCAGTGAACCACTATCACGAAAAAAACT
CTACCTCTCTATACTAATCTCCCTACAAATCTCCTTAATTATAACATTCACAGCCACAGA
ACTAATCATATTTTATATCTTCTTCGAAACCACACTTATCCCCACCTTGGCTATCATCAC
CCGATGAGGCAACCAGCCAGAACGCCTGAACGCAGGCACATACTTCCTATTCTACACCCT
AGTAGGCTCCCTTCCCCTACTCATCGCACTAATTTACACTCACAACACCCTAGGCTCACT
AAACATTCTACTACTCACTCTCACTGCCCAAGAACTATCAAACTCCTGAGCCAACAACTT
AATATGACTAGCTTACACAATAGCTTTTATAGTAAAGATACCTCTTTACGGACTCCACTT
ATGACTCCCTAAAGCCCATGTCGAAGCCCCCATCGCTGGGTCAATAGTACTTGCCGCAGT
ACTCTTAAAACTAGGCGGCTATGGTATAATACGCCTCACACTCATTCTCAACCCCCTGAC
AAAACACATAGCCTACCCCTTCCTTGTACTATCCCTATGAGGCATAATTATAACAAGCTC
CATCTGCCTACGACAAACAGACCTAAAATCGCTCATTGCATACTCTTCAATCAGCCACAT
AGCCCTCGTAGTAACAGCCATTCTCATCCAAACCCCCTGAAGCTTCACCGGCGCAGTCAT
TCTCATAATCGCCCACGGGCTTACATCCTCATTACTATTCTGCCTAGCAAACTCAAACTA
CGAACGCACTCACAGTCGCATCATAATCCTCTCTCAAGGACTTCAAACTCTACTCCCACT
AATAGCTTTTTGATGACTTCTAGCAAGCCTCGCTAACCTCGCCTTACCCCCCACTATTAA
CCTACTGGGAGAACTCTCTGTGCTAGTAACCACGTTCTCCTGATCAAATATCACTCTCCT
ACTTACAGGACTCAACATACTAGTCACAGCCCTATACTCCCTCTACATATTTACCACAAC
ACAATGGGGCTCACTCACCCACCACATTAACAACATAAAACCCTCATTCACACGAGAAAA
CACCCTCATGTTCATACACCTATCCCCCATTCTCCTCCTATCCCTCAACCCCGACATCAT
TACCGGGTTTTCCTCTTGTAAATATAGTTTAACCAAAACATCAGATTGTGAATCTGACAA
CAGAGGCTTACGACCCCTTATTTACCGAGAAAGCTCACAAGAACTGCTAACTCATGCCCC
CATGTCTAACAACATGGCTTTCTCAACTTTTAAAGGATAACAGCTATCCATTGGTCTTAG
GCCCCAAAAATTTTGGTGCAACTCCAAATAAAAGTAATAACCATGCACACTACTATAACC
ACCCTAACCCTGACTTCCCTAATTCCCCCCATCCTTACCACCCTCGTTAACCCTAACAAA
AAAAACTCATACCCCCATTATGTAAAATCCATTGTCGCATCCACCTTTATTATCAGTCTC
TTCCCCACAACAATATTCATGTGCCTAGACCAAGAAGTTATTATCTCGAACTGACACTGA
GCCACAACCCAAACAACCCAGCTCTCCCTAAGCTTCAAACTAGACTACTTCTCCATAATA
TTCATCCCTGTAGCATTGTTCGTTACATGGTCCATCATAGAATTCTCACTGTGATATATA
AACTCAGACCCAAACATTAATCAGTTCTTCAAATATCTACTCATCTTCCTAATTACCATA
CTAATCTTAGTTACCGCTAACAACCTATTCCAACTGTTCATCGGCTGAGAGGGCGTAGGA
ATTATATCCTTCTTGCTCATCAGTTGATGATACGCCCGAGCAGATGCCAACACAGCAGCC
ATTCAAGCAATCCTATACAACCGTATCGGCGATATCGGTTTCATCCTCGCCTTAGCATGA
TTTATCCTACACTCCAACTCATGAGACCCACAACAAATAGCCCTTCTAAACGCTAATCCA
AGCCTCACCCCACTACTAGGCCTCCTCCTAGCAGCAGCAGGCAAATCAGCCCAATTAGGT
CTCCACCCCTGACTCCCCTCAGCCATAGAAGGCCCCACCCCAGTCTCAGCCCTACTCCAC
TCAAGCACTATAGTTGTAGCAGGAATCTTCTTACTCATCCGCTTCCACCCCCTAGCAGAA
AATAGCCCACTAATCCAAACTCTAACACTATGCTTAGGCGCTATCACCACTCTGTTCGCA
GCAGTCTGCGCCCTTACACAAAATGACATCAAAAAAATCGTAGCCTTCTCCACTTCAAGT
CAACTAGGACTCATAATAGTTACAATCGGCATCAACCAACCACACCTAGCATTCCTGCAC
ATCTGTACCCACGCCTTCTTCAAAGCCATACTATTTATGTGCTCCGGGTCCATCATCCAC
AACCTTAACAATGAACAAGATATTCGAAAAATAGGAGGACTACTCAAAACCATACCTCTC
ACTTCAACCTCCCTCACCATTGGCAGCCTAGCATTAGCAGGAATACCTTTCCTCACAGGT
TTCTACTCCAAAGACCACATCATCGAAACCGCAAACATATCATACACAAACGCCTGAGCC
CTATCTATTACTCTCATCGCTACCTCCCTGACAAGCGCCTATAGCACTCGAATAATTCTT
CTCACCCTAACAGGTCAACCTCGCTTCCCCACCCTTACTAACATTAACGAAAATAACCCC
ACCCTACTAAACCCCATTAAACGCCTGGCAGCCGGAAGCCTATTCGCAGGATTTCTCATT
ACTAACAACATTTCCCCCGCATCCCCCTTCCAAACAACAATCCCCCTCTACCTAAAACTC
ACAGCCCTCGCTGTCACTTTCCTAGGACTTCTAACAGCCCTAGACCTCAACTACCTAACC
AACAAACTTAAAATAAAATCCCCACTATGCACATTTTATTTCTCCAACATACTCGGATTC
TACCCTAGCATCACACACCGCACAATCCCCTATCTAGGCCTTCTTACGAGCCAAAACCTG
CCCCTACTCCTCCTAGACCTAACCTGACTAGAAAAGCTATTACCTAAAACAATTTCACAG
CACCAAATCTCCACCTCCATCATCACCTCAACCCAAAAAGGCATAATTAAACTTTACTTC
CTCTCTTTCTTCTTCCCACTCATCCTAACCCTACTCCTAATCACATAACCTATTCCCCCG
AGCAATCTCAATTACAATATATACACCAACAAACAATGTTCAACCAGTAACTACTACTAA
TCAACGCCCATAATCATACAAAGCCCCCGCACCAATAGGATCCTCCCGAATCAACCCTGA
CCCCTCTCCTTCATAAATTATTCAGCTTCCTACACTATTAAAGTTTACCACAACCACCAC
CCCATCATACTCTTTCACCCACAGCACCAATCCTACCTCCATCGCTAACCCCACTAAAAC
ACTCACCAAGACCTCAACCCCTGACCCCCATGCCTCAGGATACTCCTCAATAGCCATCGC
TGTAGTATATCCAAAGACAACCATCATTCCCCCTAAATAAATTAAAAAAACTATTAAACC
CATATAACCTCCCCCAAAATTCAGAATAATAACACACCCGACCACACCGCTAACAATCAA
TACTAAACCCCCATAAATAGGAGAAGGCTTAGAAGAAAACCCCACAAACCCCATTACTAA
ACCCACACTCAACAGAAACAAAGCATACATCATTATTCTCGCACGGACTACAACCACGAC
CAATGATATGAAAAACCATCGTTGTATTTCAACTACAAGAACACCAATGACCCCAATACG
CAAAACTAACCCCCTAATAAAATTAATTAACCACTCATTCATCGACCTCCCCACCCCATC
CAACATCTCCGCATGATGAAACTTCGGCTCACTCCTTGGCGCCTGCCTGATCCTCCAAAT
CACCACAGGACTATTCCTAGCCATGCACTACTCACCAGACGCCTCAACCGCCTTTTCATC
AATCGCCCACATCACTCGAGACGTAAATTATGGCTGAATCATCCGCTACCTTCACGCCAA
TGGCGCCTCAATATTCTTTATCTGCCTCTTCCTACACATCGGGCGAGGCCTATATTACGG
ATCATTTCTCTACTCAGAAACCTGAAACATCGGCATTATCCTCCTGCTTGCAACTATAGC
AACAGCCTTCATAGGCTATGTCCTCCCGTGAGGCCAAATATCATTCTGAGGGGCCACAGT
AATTACAAACTTACTATCCGCCATCCCATACATTGGGACAGACCTAGTTCAATGAATCTG
AGGAGGCTACTCAGTAGACAGTCCCACCCTCACACGATTCTTTACCTTTCACTTCATCTT
GCCCTTCATTATTGCAGCCCTAGCAACACTCCACCTCCTATTCTTGCACGAAACGGGATC
AAACAACCCCCTAGGAATCACCTCCCATTCCGATAAAATCACCTTCCACCCTTACTACAC
AATCAAAGACGCCCTCGGCTTACTTCTCTTCCTTCTCTCCTTAATGACATTAACACTATT
CTCACCAGACCTCCTAGGCGACCCAGACAATTATACCCTAGCCAACCCCTTAAACACCCC
TCCCCACATCAAGCCCGAATGATATTTCCTATTCGCCTACACAATTCTCCGATCCGTCCC
TAACAAACTAGGAGGCGTCCTTGCCCTATTACTATCCATCCTCATCCTAGCAATAATCCC
CATCCTCCATATATCCAAACAACAAAGCATAATATTTCGCCCACTAAGCCAATCACTTTA
TTGACTCCTAGCCGCAGACCTCCTCATTCTAACCTGAATCGGAGGACAACCAGTAAGCTA
CCCTTTTACCATCATTGGACAAGTAGCATCCGTACTATACTTCACAACAATCCTAATCCT
AATACCAACTATCTCCCTAATTGAAAACAAAATACTCAAATGGGCCTGTCCTTGTAGTAT
AAACTAATACACCAGTCTTGTAAACCGGAGATGAAAACCTTTTTCCAAGGACAAATCAGA
GAAAAAGTCTTTAACTCCACCATTAGCACCCAAAGCTAAGATTCTAATTTAAACTATTCT
CTGTTCTTTCATGGGGAAGCAGATTTGGGTACCACCCAAGTATTGACTCACCCATCAACA
ACCGCTATGTATTTCGTACATTACTGCCAGCCACCATGAATATTGTACGGTACCATAAAT
ACTTGACCACCTGTAGTACATAAAAACCCAATCCACATCAAAACCCCCTCCCCATGCTTA
CAAGCAAGTACAGCAATCAACCCTCAACTATCACACATCAACTGCAACTCCAAAGCCACC
CCTCACCCACTAGGATACCAACAAACCTACCCACCCTTAACAGTACATAGTACATAAAGC
CATTTACCGTACATAGCACATTACAGTCAAATCCCTTCTCGTCCCCATGGATGACCCCCC
TCAGATAGGGGTCCCTTGACCACCATCCTCCGTGAAATCAATATCCCGCACAAGAGTGCT
ACTCTCCTCGCTCCGGGCCCATAACACTTGGGGGTAGCTAAAGTGAACTGTATCCGACAT
CTGGTTCCTACTTCAGGGTCATAAAGCCTAAATAGCCCACACGTTCCCCTTAAATAAGAC
ATCACGATG
-276
View File
@@ -1,276 +0,0 @@
>MT_orang
GTTTATGTAGCTTATTCTATCCAAAGCAATGCACTGAAAATGTCTCGACGGGCCCACACG
CCCCATAAACAAATAGGTTTGGTCCTAGCCTTTCTATTAGCTCTTAGTGAGGTTACACAT
GCAAGCATCCCCGCCCCAGTGAGTCGCCCTCCAAGTCACTCTGACTAAGAGGAGCAAGCA
TCAAGCACGCAACAGCGCAGCTCAAGACGCTCAGCCTAGCCACACCCCCACGGGAGACAG
CAGTGATAAGTCTTTAGCAATAAACGAAAGTTCAACTAAGCTACACTAACCCCAGGGTTG
GTCAACTTCGTGCCAGCCACCGCGGTCACACGATTAGCCCAAGTTAATAGAGATCGGCGT
AGAGAGTGTTTTAGATTCTTTTTCTCCCCAATAAAGCTAAAATTTACCTGAGTTGTAGAA
AACTTAAGCTAATACAAAATAAACTACGAAAGTGGCTTTAATATATCTGAACACACAATA
GCTAAGGCCCAAACTGGGATTAGATACCCCACTATGCTTAGCCCTAAACTTTAACAGTTA
AATCAACAAAACTGCTCGCCAGAACACTACGAGCCACAGCTTAAAACTCAAAGGACCTGG
CGGTGCTTCATATCCCTCTAGAGGAGCCTGTTCTGTAATCGATAAACCCCGATCAACCTC
ACCACCCCTTGCTCAGCCTATATACCGCCATCTTCAGCAAACCCTGATGAAGGCCACGAA
GTAAGCGCAAGCATCCACATAAAGACGTTAGGTCAAGGTGTAGCCCATGGAGTGGCAAGA
AATGGGCTACATTTTCTACTTCAGAAAACTACGATAGCCCTCATGAAACCTGAGGGTCGA
AGGTGGATTTAGCAGTAAACTAAGAGTAGAGTGCTTAGTTGAACAGGGCCCTGAAGCGCG
TACACACCGCCCGTCACCCTCTTCAAGTATATTTCAGGGACTACCTAACTAAAACCCCCA
CGCATCTATATAGAGGAGGCAAGTCGTAACATGGTAAGCGTACTGGAAAGTGCGCTTGGA
CGAACCAGAGGGTAGCTTAACACAAAGCACCCGGCTTACACCTGGGAGATTTCAATTCAA
CCTGGCCCCTCTGAGCTAACCCTAGCCCCAAACCCAACCCACCCTACTACCAACCAACCC
TAACCAAACCATTCACCCAAACAAAGTATAGGCGATAGAAATTACAATCCGGCGCAATAG
ACACAGTACCGTAAGGGAAAGATGAAAAAACACAACCAAGCACAACATAGCAAGGACTAA
CCCCTGTACCTTTTGCATAATGAATTAACTAGAAACAACTTTGCAAGGAGAGCCAAAGCC
AAGACCCCCGAAACCAGACGAGCTACCCATAAACAGCTAAAAGAGCACACCCGTCTATGT
AGCAAAATAGTGGGAAGATTTATGGGTAGAGGCGACAAACCTACCGAGCCTGGTGATAGC
TGGTTGTCCAAGACAGAATCTTAGTTCAACTTTAAATTTACTTACAGAACCCCTAATCCC
CTCGTAAATTTAATTGCTAGTCTAAAGAGGAACAGCTCTTTAGACACTAGGAAAAAACCT
TAAAAAGAGAGTAAAAAACACAACACCCATAGTGGGCCCAAAAGCAGCCATCAATTAAGA
AAGCGTTCAAGCTCGACACCTAAACACCAAAAAATACCAAACACAAAACTGAACTCCTTA
CTCCCCATTGGACTAATCTATTGCCCCATAGAAGAAACAATGTTAGTATAAGTAACATGA
AGATATTCTCCCCCGCATAAGTCTACGTCAGACCGAAACATCACACTGACAATTAACGGT
CCAATATGCATAGTTAACAAATAAACTATTATTTTTTCCCCCCGTTAATCCAACACAGGC
ATGCCTATAAGGAAAGGTTAAAAAAAGTAAAAGGAACTCGGCAAATCTCACCCCGCCTGT
TTACCAAAAACATCACCTCTAGCATTACCAGTATTAGAGGCACCGCCTGCCCGGTGACAT
ACGTTTAACGGCCGCGGTACCCTGACCGTGCAAAGGTAGCATAATCACTTGTTCCTTAAA
TGGGGACTTGTATGAATGGCTTCACGAGGGTTCGACTGTCTCTTACTTTTAACCAGTGAA
ATTGACCTGCCCGTGAAGAGGCGGGCATAACATAACAAGACGAGAAGACCCTATGGAGCT
TCAATTTACCAGTGCAAATAACATACAACAAGCCCACAGGCCCTAAATCACCAAACCTGC
ACTGAAGATTTCGGTTGGGGCGACCTCGGAGCACAACCCAACCTCCGAGAAACACATGTT
AAGACCTCACAAGTCAAAACGAACTTCCACACACAATTGATCCAACAACTTGACCAACGG
AACAAGTTACCCTAGGGATAACAGCGCAATCCTGTTCTAGAGTCCATATCAACAACAGGG
TTTACGACCTCGATGTTGGATCAGGACATCCTAATGGTGCAGCCGCTATTAAAGGTTCGT
TTGTTCAACGATTAAAGTCCTACGTGATCTGAGTTCAGACCGGAGCAATCCAGGTCGGTT
TCTATCTATTTCACATTTCTCCCTGTACGAAAGGACAAGAGAAATGGGGCCTACTTCACA
TAAGCGCCTTTCCCAAACAAATGATATCATCTCAATTTAACACCACACCAACACCCACCC
AAGAAAAGGGCTATGTTAAGATGGCAGAGCCCGGTAACTGCATAAAATTTAAAGCTTTAC
AGTCAGAGGTTCAACTCCTCTTCTTAACAATATGCCCATAATCAACCTCCTACTCCTCAT
TATATCCATCCTAATCGCCATAGCATTTCTAATGCTAACCGAACGAAAAATCCTAGGCCA
CACACAACTACGCAAAGGGCCCAACATTGTGGGCCCCTACGGCTTACTACAACCCTTTGC
CGACGCCCTAAAACTATTCACCAAAGAACCCCTAAAACCCTCCACATCAACCATCACCCT
TTACATTATTTCCCCCGCCCTAGCCCTTACCATTGCCCTCCTACTATGAACCCCCCTCCC
TATGCCCATCCCCCTAATCAACCTCAACTTAGGCCTCCTATTTATCCTAGCCGCGTCAAG
CCTAACCGTCTACTCCATCCTCTGATCAGGATGAGCATCTAACTCAAACTACGCCCTAAT
CGGCGCATTGCGGGCGGTAGCCCAAACGATCTCATACGAAATTACCCTAGCCCTTATCCT
GTTATCAGTACTACTAATAAGCGGCTCTTTTAACCTCTCCGCCCTCATCACAACACAAGA
ACACTCATGACTACTTCTACCATCATGACCTCTAGCCCTAATATGATTTATTTCAACACT
AGCAGAAACCAACCGAGCCCCCTTCGACCTCACCGAAGGAGAATCCGAACTAGTTTCGGG
CTTTAACACTGAATACGCCGCAGGTCCATTCGCCCTATTCTTCATAGCCGAATATACAAA
CATTATCTTAATAAACGCCCTCACCACTATAATTTTCCTAGGAACAACATTCAACATCCA
CTCCCCAGAACTCTACACAACCCTCTTCACCATCAAAACCCTACTCCTAACCTCCCTATT
CCTATGAATTCGATCAACATACCCCCGATTCCGCTACGACCAACTCATGCACCTTCTATG
AAAAAATTTCCTGCCACTCACCCTAGCACTACTAATATGACACATCTCCGTACCCATTGC
AACCTCCGGCATTCCCCCACAAACCTAAGAAATATGTCTGACAAAAGAGTTACTTTGATA
GAGTAAAAAATAGAGGTCTAAATCCCCTTATTTCTAGGATTATGGGAGTTGAACCCACCC
CTGAGAATCCAAAATTCTCCGTGCCACCCATCACACCCTATCCTAAAGTAAGGTCAGCTA
AATAAGCTATCGGGCCCATACCCCGAAAATGTTGGTTATACCCTTCCCGTACTAATTAAC
CCCTTGGCCCAACCCATCATTTACCCCACCATCTTCACAGGCACGCTCATTACAGCACTG
AGCTCCCACTGATTCTTTGCCTGACTGGGACTAGAAATAAATATACTCGCTTTCATCCCA
GTCCTAACCAAAAAAACAAGCCCCCGCTCCACAGAAGCCGCCATTAAATATTTCCTCACA
CAGGCAACCGCATCCATAATCCTCCTGATAGCCATCCTCTACAACAACATACTTTCCGGA
CAGTGAACCACAACCAACACCACCAACCCATATTCATCTCTAATAATCGTAACCGCCCTA
GCAATGAAGCTAGGAATAGCCCCCTTCCACTTTTGAGTCCCAGAAGTCACCCAAGGAGTC
CCCCTGACATCCGGCTTACTCCTCCTTACATGACAAAAATTAGCCCCCATTTCAATTATA
TACCAAATATCTTCATCGGTAGACACAAACATCCTCCTCACCCTCTCAATTCTATCTATC
CTAGTAGGCGGCTGAGGCGGACTAAACCAAACCCAACTACGCAAAATCCTGGCATACTCC
TCAATCACCCATATAGGATGAATAATAGCAGTACTACCATATAACCCAGACATCACTATC
CTCAACCTAATCATCTACATCATCCTGACAACTACCGCATTCCTAATCCTCGACTTAAAC
TCTAGTGTCACAATCCTAATATTAACCCGCACCTGGAACAAGCTGACATGACTAATACCC
TTAATCCCATCAACCTTATTATCCCTAGGGGGCCTGCCACCACTAACCGGCTTCCTGCCC
AAATGAGCCATCATTGAAGAATTTGCAAAAAATGGCAATCTCATTACCCCCACAATCATG
GCTATTATCACCCTCCTCAACCTCTACTTCTACGTACGCCTAATCTACGCCACCTCAATC
ACACTACTCCCCATATCTAACAACGCAAAAATGAAATGACAGTTCGAAAACACAAAACCC
ACCCCTCTTCTCCCCACACTCACCATTCTTACCACCCTACTCCTACCTATCTCCCCTCTC
ATCCTATCTATCTCATAGAAATTTAGGTTAACACAGACCAAGAGCCTTCAAAGCCCTCAG
CAAGTCACAGCACTTAATTTCTGTAACACTAAGGACTGCAAAGCCCCGCTCTGCATCAAC
TGAACGCAAACCAGCCACTTTAATTAAGCTAAGCCCTCCCTAGACCGATGGGACTTAAAC
CCACAAACATTTAGTTAACAGCTAAACACCCTAATCAATTGGCTTCAGTCCACTTCTCCC
GCCGCGGGGAAAAAGGCGGGAGAAGCCCCGGCAGGCCTTAAAGCTGCTCCTTCGAATTTG
CAATTCAACATGACAATCACCTCGGGGCTGGTAAAAAGAGGTCTAACCCCTGTTCTTAGA
TTTACAGCCTAATGCCTTAACTCGGCCATTTTACCCCCCCCCCCCCTTTTTTTCTCCACT
AATGTTCGCCGACCGCTGGCTATTCTCCACGAACCACAAAGACATCGGGACACTATACCT
GTTATTCGGCGCATGGGCTGGAGTCCTAGGCACTGCCCTAAGCCTCCTCATTCGAGCTGA
ACTGGGCCAACCCGGCAACCTTCTAGGCAATGACCATATCTACAATGTCATCGTCACAGC
TCATGCATTCGTAATAATTTTCTTTATAGTCATACCCATTATAATTGGAGGCTTTGGCAA
CTGACTAGTGCCCCTAATAATCGGCGCCCCCGATATAGCATTCCCGCGCATAAATAATAT
AAGCTTCTGACTCCTCCCCCCCTCCTTTCTCCTACTGCTCGCTTCTGCTACAGTAGAGGC
TGGCGCAGGAACAGGCTGAACAGTCTATCCGCCCCTAGCAGGAAACTACTCTCACCCAGG
AGCCTCTGTAGACTTAACAATCTTCTCTTTACACCTAGCAGGCATTTCCTCTATCCTAGG
AGCTATCAATTTCATCACAACAATTATTAATATAAAACCCCCTGCAATATCCCAATACCA
AACCCCCCTCTTCGTCTGATCAGTCTTGATCACAGCAGTCCTACTTCTCCTTTCCCTCCC
AGTCCTAGCCGCTGGCATCACCATACTACTAACAGATCGCAACCTAAACACCACATTCTT
TGACCCAGCCGGAGGTGGAGATCCCATCCTATATCAGCACCTATTCTGATTTTTTGGCCA
CCCTGAAGTCTACATTCTCATCCTGCCGGGTTTCGGCATAATCTCCCACATCGTAACACA
CTATTCCGGAAAAGAAGAGCCATTTGGGTACATAGGCATAGTCTGAGCCATAGTCTCAAT
TGGCTTCCTGGGCTTTATCGTATGGGCCCACCACATATTCACAGTAGGAATAGACGTGGA
CACACGAGCCTACTTCACCTCCGCTACCATAATCATTGCCATCCCCACCGGCGTCAAAGT
ATTTAGCTGACTCGCTACACTCCACGGAAGCAACACTAAATGATCTGCCGCAATCCTCTG
AGCCTTAGGATTCATTTTCCTCTTCACCGTAGGCGGCCTAACAGGCATCGTACTAGCAAA
CTCATCACTAGACATTGTATTACACGATACATACTACGTTGTAGCCCACTTTCATTACGT
CCTATCAATAGGAGCTGTATTCGCCATCATGGGAGGCTTCATCCACTGGTTCCCACTATT
CTCAGGCTACACCTTAGACCAGACCTATGCTAAAATTCACTTCATCACCATATTTATCGG
CGTAAATTTAACTTTCTTCCCACAACATTTCCTCGGCCTGTCAGGCATACCCCGACGCTA
CTCCGACTACCCCGACGCGTACACCACCTGAAATATTTTATCATCCGCAGGCTCATTTAT
CTCCCTAACAGCAGTCATACTAATAATTTTCATAATTTGAGAAGCCTTCGCCTCAAAACG
AAAAGTCCCAATAGTTGAACAACCCTCCACAAGCCTAGAGTGATTGTACGGATGCCCCCC
ACCCTACCACACATTTGAAGAACCCGTCTATATAAAACCAGAACAAAAAAGGAAGGAATC
GAACCTCCTAAAGCTGGTTTCAAGCCAACCCCACAACCTCCATGACTTTTTCAAGAGATA
CTAGAAAAACCATTTCATGACTTTGTCAAAGTTAAGTTACAGGCCAAACCCTGTGTATCT
TAATGGCGCACGCAGCACAGGTAGGTTTACAAGACGCTACCTCTCCTATCATAGAAGAAT
TGGTCATCTTTCACGACCACGCCCTCATAATCATTTTCCTAATCTGCTTCCTAGTCCTGT
ACGCCCTATTCCTAACACTCACAACAAAACTCACCAACACCAGCATCTCAGACGCCCAAG
AGATAGAGACTATTTGAACTATCCTACCGGCCATCATCCTAATTCTAATCGCCCTCCCAT
CCCTACGCATCCTCTACTTAACAGACGAGATCAACGACCCTTCCTTCACCATCAAATCAA
TCGGTCATCAATGATACTGAACCTACGAGTACACTGACTACGGTGGATTGATCTTCAACT
CTTACATGCTCCCACCACTATTCCTAGAACCAGGCGACCTTCGACTCCTCGACGTCGACA
ACCGAGTAGTCCTCCCAGTCGAAGCTCCCGTTCGCATAATAATCACATCCCAAGACGTCT
TACACTCATGAACTGTACCCTCACTAGGCCTGAAAACGGACGCAATCCCCGGACGCCTAA
ACCAAACCACATTCACTGCCACGCGACCAGGAGTGTACTATGGCCAATGCTCAGAAATCT
GTGGAGCTAACCACAGCTTTATGCCTATCGTCCTAGAACTAATCCCCCTAAAAATCTTCG
AAATAGGGCCCGTATTCACTTTATAACTTCCCCCACCCCCACAACCCATCCTACCCCCTT
TCCTGAGGCCCACTGCAAAGCTAATCTAGCATTAACCTTTTAAGTTAAAGACTAAGAGAA
TCAACCCCTCTTTGCAGTGAAATGCCCCAACTAAATACCACCACATGGCCCACCATCATC
ACCCCAATACTCCTTGCACTATTCCTCATCACTCAACTAAAACTACTAAACTCACACCTC
CACCCACCCACCCCACCAAAATTCACTAAACCAAAACTCCACGCCAAACCCTGAGGACCA
AAATGAACGAAAGTCTATTTACCCCATTCATTACCCCCACAGTACTAGGCCTCCCCGCCG
CAGTACTAGTCATCTTATTTCCCCCCTTACTGATCCCCACCTCCAAACATCTCATCAACA
ACCGACTAATTATTATCCAACAATGACTAATCCGACTCATCCTAAAACAAATAATAACCA
CCCATAACGCTAAAGGACGAACTTGATCCCTCATACTAACGTCCCTAATCATTTTCATCG
CCTCAACCAACCTCCTAGGACTCCTCCCCTACTCATTTACACCAACCACCCAACTATCCA
TAAATTTAGCTATAGCAATTCCCTTATGAGCAAGCACGGTAGCTATGGGCCTTCGCTTCA
AAGCCAAAATTACCCTAACCCACCTCTTACCACAAGGTACCCCCACACCTCTCATCCCTA
TACTAATTATTATTGAAACCGTCAGCCTTTTCATTCAACCACTAGCCTTAGCCGTACGCC
TAACTGCTAACATCACTGCAGGCCACCTACTCATGCACCTAATCGGAAGCTCTGCACTAG
CTATACTAGCCATCAACCTCCCCCTAACCCTCATCACCCTTACAATCTTAACCCTGCTAA
CAATCCTGGAGACTGCCATCGCCCTAATTCAAGCCTACGTCTTCACACTTCTAGTAAGCC
TCTACCTGCACGACAACTCATAATGGCCCATCAATCACACGCCTACCACATAGTAAAACC
TAGCCCATGACCCCTAACAGGAGCTCTCTCAGCCCTCCTAACAACATCTGGCCTAACCAT
GTGATTCCACTTCCACTCCACAACCCTACTATTAACAGGCCTACTAACCAATGCACTAAC
CATATACCAATGGTGACGAGATGTAGTGCGAGAAAGCACATACCAAGGCCACCACACACT
ACCCGTCCAAAAAGGCCTCCGATATGGAATAATCCTATTCATCACTTCAGAAGTCTTTTT
CTTCGCCGGATTCTTCTGAGCATTCTACCACTCCAGCCTAGCCCCCACCCCTCAACTTGG
AGGACACTGACCCCCAACAGGCATTATCCCCCTCAACCCCCTAGAAGTCCCACTCCTAAA
CACATCCGTACTACTCGCATCAGGAGTCTCAATTACCTGAGCCCATCACAGCCTGATGGA
AAATAATCGAACCCAAATAATTCAAGCACTACTCATCACAATCTTACTAGGCATCTACTT
CACTCTCCTTCAGGCTTCAGAATACATTGAAGCTCCTTTCACCATCTCTGACGGCATCTA
CGGCTCAACATTCTTCATAGCCACGGGATTCCACGGCCTCCACGTCATTATCGGATCAAC
TTTCCTCACTGTATGCCTAGCCCGCCAGCTATTATTCCACTTCACATCCAAACATCACTT
TGGCTTTGAGGCCGCCGCCTGATACTGGCACTTTGTAGACGTAGTCTGACTGTTTCTGTA
CGTCTCCATCTACTGATGAGGTTCCTACTCTTTTAGTATAAACAGTACCGTTAACTTCCA
ATTAACTAGTTTTGACAACGCCCAAAAAAGAGTAATTAACTTCGTCCTAGCTCTAACAGT
CAACACCCTCCTAGCCCTGCTACTAATAACCATCACATTCTGACTACCACAACTCTACCC
CTACATAGAAAAATCCGACCCATACGAATGTGGATTTGACCCCGCATACCCCGCTCGCAT
TCCTTTCTCCATAAAATTTTTCTTAGTAGCCATCACCTTCCTACTATTCGACCTAGAAAT
CGCCCTGCTACTACCCCTGCCATGGGCCCTACAAACAACCAACTTACCACTAATAACTAC
ATCATCACTTATATTAATTATCATCCTAGCCCTAGGCCTAACTTACGAATGATCACAAAA
AGGATTAGACTGAGCCGAATTGGTAAATAGTTTAAACAAAACAAATGATTTCGACTCATT
AAATTATGACAGCCATATTTACCAAATGCCCCTTATCTACATAAATATCACACTAGCATT
CACCATATCACTCCTAGGCATACTAGTCTACCGCTCACACCTAATATCTTCTCTACTATG
TCTAGAAGGAATAATATTATCATTGTTCATTATAATTACTCTCATAACCCTCAACACCCA
CTCTCTCCTAGCTAACATCATACCCATCACCATGCTAGTCTTCGCTGCCTGCGAAGCAGC
AGTAGGCCTCGCCCTACTAGCCTCAATCTCCAATACATACGGCCTAGACTACGTCAACAA
CCTAAACCTACTTCAATGCTAAAACTAATTATCCCAACAATCATACTGCTGCCCCTAACA
TGACTCTCCAAAACGCACATAATCTGAATCAACACCACCACCCACAGCCTAATCATCAGC
TCCATCCCCCTACTATTCCTCAATCAAACCAACAGCAACCTGTACAGCTACTCCCTTCTT
TTCTCCTCCGACCCCTTATCAACCCCCCTTCTAATACTAACAACCTGACTCCTACCCCTC
ATAATTATAGCAAGCCAACACCATCTATCCAACGAACCCCCATCACGAAAAAAATTATAC
CTCACCATACTAATCTCTCTTCAAATCTCCCTAATCATAACATTCACAGCCACAGAGCTA
ATTATATTTTATATCCTCTTCGAAACCACTCTCATCCCCACCCTAGTCATTATCACCCGC
TGAGGCAACCAGCCAGAGCGCTTAAATGCAGGCACATACTTTCTATTCTACACACTAGTA
GGCTCCCTCCCCCTACTCATTGCCCTAATCCACACCTACAACACCCTAGGCTCGCTTAAC
ATTGTATTACTAACTCTCACCGCCCGGGAGCTAACAGACTCCTGATCCAACAGCCTAATA
TGACTAGCGTACACAATAGCTTTCATAGTAAAAATACCCCTCTACGGACTACACCTATGA
CTCCCTAAAGCCCATGTAGAAGCCCCCATTGCCGGCTCAATAGTACTCGCCGCAGTGCTC
TTAAAACTAGGTGGTTACGGTATAATACGCCTTATCCCCATTCTCAATCCCCTAACTAAA
CACATAGCCTACCCCTTTATCATACTATCCCTATGAGGCATAATCATAACAAGCTCCATC
TGCTTACGACAAACCGACCTAAAATCACTCATCGCATACTCCTCAGTCAGCCACATAGCG
CTTGTTGTAGCAGCTATCCTCATTCAAACCCCCTGAAGCTTCACCGGCGCAACCACCCTC
ATAATTGCCCATGGACTCACATCCTCCCTACTGTTCTGCCTAGCAAACTCAAACTACGAA
CGAACCCACAGCCGCATCATAATCCTCTCTCAAGGCCTTCAAACTCTACTCCCCCTAATA
GCCCTCTGATGACTTCTAGCAAGCCTCACTAACCTTGCCCTACCACCCACCATCAACCTA
CTAGGAGAACTCTCCGTACTAATAGCCATATTCTCTTGATCTAACATCACCATCCTACTA
ACAGGACTCAACATACTAATCACAACCCTATACTCTCTCTATATATTCACCACAACACAA
CGAGGTACACCCACACATCACACCAACAACATAAAACCTTCTTTCACACGTGAAAACACC
CTCATGCTCATACACCTATCCCCCATTCTCCTCTTGTCCCTCAACCCCAGCATCATCGCT
GGATTCGCCTACTGTAAATATAGTTTAACCAAAACATCAGATTGTGAATCTAATAATAGG
GCCCACAACCCCTTATTTACCGAGAAAGCTCACAAGAACTGCTAACTCTCACCCCATGTG
TAACAACATGGCTTTCTCAACTTTTAAAGGATAACAGCTATCCCTTGGTCTTAGGACCCA
AAAATTTTGGTGCAACTCCAAATAAAAGTAACAGCCATGTTTACCACCATAACTGCCCTC
ACCTTGACTTCCCTAATCCCCCCCATTACCGCTACCCTCATTAACCCCAACAAAAAAAAC
TCATACCCCCACTATGTAAAAACTGCCATCGCATCCGCCTTTACTATCAGCCTTATCCCA
ACAACAATATTTATCTGCCTAGGACAAGAAACCATCGTCACAAACTGATGCTGAACAACC
ACCCAGACACTACAACTCTCACTAAGCTTCAAACTTGACTACTTCTCCATAACATTCCTC
CCCGTAGCACTACTCATCACTTGATCCATTATAGAATTTTCACTATGGTATATAGCCTCA
GACCCAAACATCAACCAATTTCTCAAATTCCTCCTTATTTTCCTAATCACCATAATTATC
CTAGTCACTGCCAATAACCTACTCCAACTCTTCATCGGCTGAGAGGGCGTAGGGATCATA
TCCTTCCTGCTCATTAGTTGATGATACGCCCGAACAGACGCCAACACGGCAGCTATTCAA
GCAATCCTATACAATCGTATCGGCGATATTGGCTTCATCCTGGCTCTAGCATGATTCCTC
CTACACTCCAACTCATGGGAACTACAACAAGTATTCCTCCTAAACAATAACCCTAACCTC
CTCCCACTACTAGGACTCCTCCTAGCCGCAGCTGGCAAATCAGCCCAACTAGGCCTTCAC
CCCTGACTACCCTCAGCCATAGAAGGCCCAACCCCCGTCTCAGCCCTACTTCACTCAAGC
ACCATGGTCGTGGCTGGGGTCTTCCTACTCATCCGCTTTCACCCATTAACAGAAAACAGC
CCACATATCCAAACCCTTACACTATGCTTAGGGGCCATCACCACCCTGTTCGCAGCAATC
TGCGCCCTCACACAAAACGACATTAAGAAAATCGTAGCTTTCTCCACCTCAAGTCAACTA
GGACTTATAATGGTCACAATTGGCATTAACCAGCCACACCTGGCACTCCTCCACATCTGC
ACCCACGCCTTCTTCAAAGCCCTTTTATTCATATGTTCTGGGTCCATCATCCACAACCTC
AACAATGAGCAAGACATCCGAAAAATAGGAGGACTACTCAAAACCATACCCCTAACCTCA
ACCTCCCTCACTATCAGCAGCCTAGCCCTCGCAGGAATACCCTTCCTCTCAGGCTTCTAC
TCCAAAGACCTCATTATCGAGACCGCAAACATATCCTATACCAACACCTGAGCCCTGTCT
ATCACTCTCATCGCCACCTCCTTAACAGGCGCCTACAGCACTCGAATAATCCTCCACACC
CTTACAAGCAAACCCCACTTCCCAACCCCAATCTCTATCAATGAAAACAACCCCACTCTA
CTTAAACCCATCAAGCGCCTTATGCTAGGAAGCCTATTCGCAGGATTCCTAATCACCAAC
AACATCCCCCCTATATCCCTGCCCCAAGTAACAACCCCCCCTTACCTAAAACTCGCAGCT
CTAGCTGCCACCCTCCTAGGTCTCCTAGTAGCCCTAGACTTAAACTACCTAGCCAACAAA
CTCAAGACAAAAACCCCTCCACCCACATTCTATTTCTCCATCATACTCGGATTCTACCCT
AGCATCATCCACCGCATAATCCCCCACCTAAGCCTTCTCATAAGCCAAAACTTATCCCTA
CTCCTACTAGACCTAACCTGACTAAAAAAACTAATACCCAAAACAATCTCACAACACCAA
ACCTCAGCCTCCATCACTATTTCAACCCAAAAAGGTTTAATCAAACTCTACTTCCTCTCT
TTCCTCATCCCACTCCTCCTAATCCTCCTTATAATCTCATAACCTATTACCCCGAGCAAT
CTCAATTACAACATAAACACCAACAAATAACGTTCAACCAGTAACCACCACCAACCAACG
CCCATAATCATATAAAGCCCCCGCACCAATAGGATCCTCCCGAATCAACCCCGACCCTTC
CCCTTCATAAATTATCCAGCTCCCCACGCTATTAAAATTCACCACTACCACCACTCCATC
ATACTCTTTTACCCACAACACCAGCCCCACTTCCATCACTAATCCCACCAGAACACTCAC
CAATACCTCAACCCCTGACCCCCATGCCTCAGGATATTCCTCAATAGCTATTGCCGTAGT
ATACCCAAAAACAACCATCATACCCCCTAAATAAATTAAAAAAACCATTAAACCCATATA
ACCTCCCCCACAATTTAAAATAACTGCACACCCAACCGCACCACTAATAATCAACACTAA
ACCCCCATAAATAGGAGAGGGCTTAGAAGAAAACCCCACGAACCCTATCACTAAAATTAC
ACTCAACAGAAACAAAGCATATGTCATTGTTCTCGCATAGACTGTGACTATGACCAATGG
TATGAAAAAACATCGTTGTACCTCAACTACAAGAACACTAATGACCTCAACACGTAAAAC
CAACCCACTAATAAAATTAATCAACCACTCACTTATCGACCTCCCCACCCCATCAAACAT
CTCCGCATGATGGAACTTCGGCTCACTCCTAGGCGCCTGCTTAATCATCCAAATCACCAC
TGGACTATTCCTAGCTATACATTATTCACCAGACGCCTCCACTGCCTTTTCATCAATCGC
CCACATCACTCGAGATGTAAACTACGGCTGAATAATTCGCCACCTCCACGCTAACGGCGC
CTCAATATTCTTTATCTGCCTCTTCTTACATATCGGCCGAGGCCTATACTATGGCTCATT
CACCCACCTAGAAACCTGAAACATCGGCATCATCCTACTATTTACAACTATAATAACAGC
CTTCATAGGTTACGTCCTCCCATGAGGCCAAATATCCTTCTGAGGAGCCACAGTAATCAC
AAATCTACTGTCCGCCATCCCATACATTGGAACAGACCTGGTCCAATGAGTCTGAGGTGG
CTACTCAGTAAATAGCCCCACTCTAACACGATTCTTCACCCTACACTTCATACTACCCTT
CATTATTACAGCCCTAACAACTCTACACCTCTTATTCCTACACGAAACAGGATCAAATAA
CCCCCTGGGAATCCCCTCCCATTCCGACAAAATCACCTTCCACCCCTACTACACAATCAA
AGACATCCTAGGCCTACTCCTTTTTCTCCTCGCCCTAATAACACTAACACTACTCTCACC
AGACCTCCTAAGCGACCCAGACAACTACACCTTAGCTAACCCCCTAAGCACCCCACCCCA
CATTAAACCCGAATGATATTTCCTATTCGCCTACGCAATCCTACGATCCGTCCCCAACAA
ACTAGGAGGTGTAATAGCCCTCATACTATCCATCCTAATCCTAACAACAATCCCTGCCCT
TCACATGTCCAAGCAACAGAGCATAACATTTCGCCCATTGAGCCAATTCCTATATTGACT
TTTAATCGCCGACCTTCTAATTCTCACCTGAATTGGAGGGCAACCAGTAAGCTACCCCTT
CATCACCATTAGCCAAGTAGCATCCACATTGTACTTCACTACTATCCTTCTACTTATACC
AGCCTCTTCCCTGATCGAAAACCACATACTCAAATGAACCTGCCCCTGTAGTACAAATAA
GTACACCAGCCTTGTAACCTGAAAATGAAGACCCTCTTCCATGGGCAAAAAAAATCAGAG
AAAAAGCACTTAACTTCACCGTCAGCCCCCAAAGCCAACATTCTAATTTTAAACTACTCT
CTGTTCTTTCATGGGGGACCAGATTTGGGTGCCACCCCAGTACTGACCCATTTCTAACGG
CCTATGTATTTCGTACATTCCTGCTAGCCAACATGAATATCACCCAACACAACAATCGCT
TAACCAACTATAATGCATACAAAACTCCAACCACACTCGACCTCCACACCCCGCTTACAA
GCAAGTACCCCCCCATGCCCCCCCACCCAAACACATACACCGATCTCTCCACATAACCCC
TCAACCCCCAGCATATCAACAGACCAAACAAACCTTAAAGTACATAGCACATACTATCCT
AACCGCACATAGCACATCCCGTTAAAACCCTGCTCATCCCCACGGATGCCCCCCCTCAGT
TAGTAATCCCTTACTCACCATCCTCCGTGAAATCAATATCCCGCACAAGAGTGCTACTCC
CCTCGCTCCGGGCCCATAAAACCTGGGGGTAGCTAAAGTGAGCTGTATCCGGCATCTGGT
TCTTACTTCAGGGCCATAAAACCCAAGATCGCCCACACGTTCCCCTTAAATAAGACATCA
CGATGGATCACAGGCCTATCACCCTATTAATCACTCACGGGAGCTCTCCATGCATCTGGT
ATTTTTTCGGGGGGGGATGCACGCGATAGCATCGCGGGCCGCTGGAACCGGAGCACCCTA
TGTCGCAGGATCTGTCTTTGATTCCTACCTCATGCCATTATTAATCGCGCCTAATATCCA
ATATCCTAGCCCCACCCTCAGTGTTTGAAGCTGCTATTTAATTTATGCTAGAGGACATAA
AATTACCAAAAAAAAATAAACGAACTCTCAACAACCCTACCCCATCAACCCAACAAAATC
CAATTTTTATCTTTAGGCTATGTGCACTTTCAACAGGCACCCCTCAACTAACACAATCTC
CTTCTTATCCCACCCACCAACCCCCCCCCCCCCTTCCTCCCTCTTTCTCCATTTTCCCCA
CAAACACCGCTACTACCCCCACACCCCAGACCAACCCAACCCAAAAGACACCCCGCACG