mirror of
https://github.com/lh3/minimap2.git
synced 2026-09-24 17:38:12 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eec02c07b1 | ||
|
|
736301fa6b | ||
|
|
a3337c09f1 | ||
|
|
81b3da7677 | ||
|
|
870f2cc2b9 | ||
|
|
ee9f561e2f | ||
|
|
514612bda2 | ||
|
|
3508ac9817 | ||
|
|
87d12c3307 | ||
|
|
d302ab2ad7 | ||
|
|
15d8cb178f | ||
|
|
049674df4b | ||
|
|
cbed28eaf1 | ||
|
|
4e1456af51 | ||
|
|
0764af1545 | ||
|
|
5064a10574 | ||
|
|
6e656adc55 | ||
|
|
7fffff3a85 | ||
|
|
12acf35622 | ||
|
|
fa695beddd | ||
|
|
646e7770e7 | ||
|
|
f42feba7be | ||
|
|
8764e92127 | ||
|
|
1ed1f6619f | ||
|
|
9c8f34216a | ||
|
|
264d85d003 | ||
|
|
f65e8c38e0 | ||
|
|
25fed6646d | ||
|
|
d3f4fd619a | ||
|
|
f41bb0e327 |
@@ -1,4 +0,0 @@
|
||||
.*.swp
|
||||
*.a
|
||||
*.o
|
||||
*.dSYM
|
||||
-23
@@ -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.
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
theme: jekyll-theme-modernist
|
||||
@@ -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(®s[i + 2], ®s[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, ®s[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, ®s[i-1], ®s[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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 = ®[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;
|
||||
}
|
||||
@@ -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 = ®s[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)
|
||||
}
|
||||
@@ -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 = ®s[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 = ®s[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 = ®s[(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 = ®s[(int32_t)aux[i-1]], *r1 = ®s[(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 = ®s[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 = ®s[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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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__
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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 - </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>
|
||||
<A HREF=#4>Indexing options</A><BR>
|
||||
<A HREF=#5>Mapping options</A><BR>
|
||||
<A HREF=#6>Alignment options</A><BR>
|
||||
<A HREF=#7>Input/output options</A><BR>
|
||||
<A HREF=#8>Preset options</A><BR>
|
||||
<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> >
|
||||
<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> >
|
||||
<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> >
|
||||
<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> 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%> </TD><TD>
|
||||
Don’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%> </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> 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%> </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%> </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%> </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%> </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
|
||||
<<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
|
||||
<<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’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%> </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
|
||||
’<B>-DP</B> <B>--dual</B>=<B>no</B> <B>--no-long-join</B>’. 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%> </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%> </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%> </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%> </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%> </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%> </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%> </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%> </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%> </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%> </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%> </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%> </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%> </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> 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%> </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%> </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%> </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%> </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%> </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%> </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%> </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) ‘+’ or ‘-’, 4) ‘D’ or ‘A’, and 5) score,
|
||||
where offset is the number of bases before a splice junction, ‘D’ indicates the
|
||||
line corresponds to a donor site and ‘A’ 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%> </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%> </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 ‘paftools.js gff2bed anno.gtf’
|
||||
[].
|
||||
</TD></TR>
|
||||
<TR valign=top><TD colspan=2>
|
||||
<B>--junc-bonus</B> INT </TD></TR><TR valign=top><TD width=10%> </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%> </TD><TD>
|
||||
Drop a terminal anchor if
|
||||
<I>s</I><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%> </TD><TD>
|
||||
Don’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%> </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%> </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> 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 >65535 operators at the CG tag. Older tools are unable to
|
||||
convert alignments with >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 ‘cg’ 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%> </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%> </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%> </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%> </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%> </TD><TD>
|
||||
In PAF, output unmapped queries; the strand and the reference name fields are
|
||||
set to ‘*’. 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%> </TD><TD>
|
||||
In SAM, don’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> 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 <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
|
||||
‘<B>N</B>’ CIGAR operator; 2) long insertions are disabled; 3) deletion and insertion gap
|
||||
costs are different during chaining; 4) the computation of the
|
||||
‘<B>ms</B>’ 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> 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%> </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%> </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%> </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>‘+’ if query/target on the same strand; ‘-’ 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>
|
||||
@@ -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
@@ -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]);
|
||||
}
|
||||
@@ -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));
|
||||
@@ -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();
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user