samtools 0.1.3 → 0.2
raw patch · 76 files changed
+10679/−11452 lines, 76 filesdep ~seqloc
Dependency ranges changed: seqloc
Files
- samtools-0.1.13/bam.c +0/−332
- samtools-0.1.13/bam.h +0/−743
- samtools-0.1.13/bam_aux.c +0/−189
- samtools-0.1.13/bam_endian.h +0/−42
- samtools-0.1.13/bam_import.c +0/−459
- samtools-0.1.13/bam_index.c +0/−711
- samtools-0.1.13/bam_lpileup.c +0/−198
- samtools-0.1.13/bam_maqcns.c +0/−626
- samtools-0.1.13/bam_maqcns.h +0/−61
- samtools-0.1.13/bam_md.c +0/−357
- samtools-0.1.13/bam_pileup.c +0/−437
- samtools-0.1.13/bam_reheader.c +0/−61
- samtools-0.1.13/bam_sort.c +0/−421
- samtools-0.1.13/bgzf.c +0/−671
- samtools-0.1.13/bgzf.h +0/−157
- samtools-0.1.13/errmod.c +0/−130
- samtools-0.1.13/errmod.h +0/−24
- samtools-0.1.13/faidx.c +0/−423
- samtools-0.1.13/faidx.h +0/−103
- samtools-0.1.13/glf.c +0/−236
- samtools-0.1.13/glf.h +0/−56
- samtools-0.1.13/kaln.c +0/−486
- samtools-0.1.13/kaln.h +0/−67
- samtools-0.1.13/khash.h +0/−528
- samtools-0.1.13/knetfile.c +0/−632
- samtools-0.1.13/knetfile.h +0/−75
- samtools-0.1.13/kprobaln.c +0/−278
- samtools-0.1.13/kprobaln.h +0/−49
- samtools-0.1.13/kseq.h +0/−227
- samtools-0.1.13/ksort.h +0/−281
- samtools-0.1.13/kstring.c +0/−212
- samtools-0.1.13/kstring.h +0/−117
- samtools-0.1.13/razf.c +0/−853
- samtools-0.1.13/razf.h +0/−134
- samtools-0.1.13/sam.c +0/−175
- samtools-0.1.13/sam.h +0/−98
- samtools-0.1.13/sam_header.c +0/−735
- samtools-0.1.13/sam_header.h +0/−24
- samtools-0.1.18/bam.c +362/−0
- samtools-0.1.18/bam.h +763/−0
- samtools-0.1.18/bam_aux.c +213/−0
- samtools-0.1.18/bam_endian.h +42/−0
- samtools-0.1.18/bam_import.c +485/−0
- samtools-0.1.18/bam_index.c +719/−0
- samtools-0.1.18/bam_lpileup.c +198/−0
- samtools-0.1.18/bam_md.c +384/−0
- samtools-0.1.18/bam_pileup.c +437/−0
- samtools-0.1.18/bam_reheader.c +61/−0
- samtools-0.1.18/bam_sort.c +438/−0
- samtools-0.1.18/bgzf.c +714/−0
- samtools-0.1.18/bgzf.h +157/−0
- samtools-0.1.18/errmod.c +130/−0
- samtools-0.1.18/errmod.h +24/−0
- samtools-0.1.18/faidx.c +432/−0
- samtools-0.1.18/faidx.h +103/−0
- samtools-0.1.18/kaln.c +486/−0
- samtools-0.1.18/kaln.h +67/−0
- samtools-0.1.18/khash.h +528/−0
- samtools-0.1.18/knetfile.c +632/−0
- samtools-0.1.18/knetfile.h +75/−0
- samtools-0.1.18/kprobaln.c +278/−0
- samtools-0.1.18/kprobaln.h +49/−0
- samtools-0.1.18/kseq.h +224/−0
- samtools-0.1.18/ksort.h +281/−0
- samtools-0.1.18/kstring.c +212/−0
- samtools-0.1.18/kstring.h +117/−0
- samtools-0.1.18/razf.c +853/−0
- samtools-0.1.18/razf.h +134/−0
- samtools-0.1.18/sam.c +179/−0
- samtools-0.1.18/sam.h +98/−0
- samtools-0.1.18/sam_header.c +736/−0
- samtools-0.1.18/sam_header.h +24/−0
- samtools.cabal +38/−38
- src/Bio/SamTools/Bam.hs +2/−2
- src/Bio/SamTools/Cigar.hs +2/−2
- src/Bio/SamTools/FaIdx.hs +2/−2
− samtools-0.1.13/bam.c
@@ -1,332 +0,0 @@-#include <stdio.h>-#include <ctype.h>-#include <errno.h>-#include <assert.h>-#include "bam.h"-#include "bam_endian.h"-#include "kstring.h"-#include "sam_header.h"--int bam_is_be = 0;-char *bam_flag2char_table = "pPuUrR12sfd\0\0\0\0\0";--/**************************- * CIGAR related routines *- **************************/--uint32_t bam_calend(const bam1_core_t *c, const uint32_t *cigar)-{- uint32_t k, end;- end = c->pos;- for (k = 0; k < c->n_cigar; ++k) {- int op = cigar[k] & BAM_CIGAR_MASK;- if (op == BAM_CMATCH || op == BAM_CDEL || op == BAM_CREF_SKIP)- end += cigar[k] >> BAM_CIGAR_SHIFT;- }- return end;-}--int32_t bam_cigar2qlen(const bam1_core_t *c, const uint32_t *cigar)-{- uint32_t k;- int32_t l = 0;- for (k = 0; k < c->n_cigar; ++k) {- int op = cigar[k] & BAM_CIGAR_MASK;- if (op == BAM_CMATCH || op == BAM_CINS || op == BAM_CSOFT_CLIP)- l += cigar[k] >> BAM_CIGAR_SHIFT;- }- return l;-}--/********************- * BAM I/O routines *- ********************/--bam_header_t *bam_header_init()-{- bam_is_be = bam_is_big_endian();- return (bam_header_t*)calloc(1, sizeof(bam_header_t));-}--void bam_header_destroy(bam_header_t *header)-{- int32_t i;- extern void bam_destroy_header_hash(bam_header_t *header);- if (header == 0) return;- if (header->target_name) {- for (i = 0; i < header->n_targets; ++i)- free(header->target_name[i]);- free(header->target_name);- free(header->target_len);- }- free(header->text);- if (header->dict) sam_header_free(header->dict);- if (header->rg2lib) sam_tbl_destroy(header->rg2lib);- bam_destroy_header_hash(header);- free(header);-}--bam_header_t *bam_header_read(bamFile fp)-{- bam_header_t *header;- char buf[4];- int magic_len;- int32_t i = 1, name_len;- // check EOF- i = bgzf_check_EOF(fp);- if (i < 0) {- // If the file is a pipe, checking the EOF marker will *always* fail- // with ESPIPE. Suppress the error message in this case.- if (errno != ESPIPE) perror("[bam_header_read] bgzf_check_EOF");- }- else if (i == 0) fprintf(stderr, "[bam_header_read] EOF marker is absent. The input is probably truncated.\n");- // read "BAM1"- magic_len = bam_read(fp, buf, 4);- if (magic_len != 4 || strncmp(buf, "BAM\001", 4) != 0) {- fprintf(stderr, "[bam_header_read] invalid BAM binary header (this is not a BAM file).\n");- return 0;- }- header = bam_header_init();- // read plain text and the number of reference sequences- bam_read(fp, &header->l_text, 4);- if (bam_is_be) bam_swap_endian_4p(&header->l_text);- header->text = (char*)calloc(header->l_text + 1, 1);- bam_read(fp, header->text, header->l_text);- bam_read(fp, &header->n_targets, 4);- if (bam_is_be) bam_swap_endian_4p(&header->n_targets);- // read reference sequence names and lengths- header->target_name = (char**)calloc(header->n_targets, sizeof(char*));- header->target_len = (uint32_t*)calloc(header->n_targets, 4);- for (i = 0; i != header->n_targets; ++i) {- bam_read(fp, &name_len, 4);- if (bam_is_be) bam_swap_endian_4p(&name_len);- header->target_name[i] = (char*)calloc(name_len, 1);- bam_read(fp, header->target_name[i], name_len);- bam_read(fp, &header->target_len[i], 4);- if (bam_is_be) bam_swap_endian_4p(&header->target_len[i]);- }- return header;-}--int bam_header_write(bamFile fp, const bam_header_t *header)-{- char buf[4];- int32_t i, name_len, x;- // write "BAM1"- strncpy(buf, "BAM\001", 4);- bam_write(fp, buf, 4);- // write plain text and the number of reference sequences- if (bam_is_be) {- x = bam_swap_endian_4(header->l_text);- bam_write(fp, &x, 4);- if (header->l_text) bam_write(fp, header->text, header->l_text);- x = bam_swap_endian_4(header->n_targets);- bam_write(fp, &x, 4);- } else {- bam_write(fp, &header->l_text, 4);- if (header->l_text) bam_write(fp, header->text, header->l_text);- bam_write(fp, &header->n_targets, 4);- }- // write sequence names and lengths- for (i = 0; i != header->n_targets; ++i) {- char *p = header->target_name[i];- name_len = strlen(p) + 1;- if (bam_is_be) {- x = bam_swap_endian_4(name_len);- bam_write(fp, &x, 4);- } else bam_write(fp, &name_len, 4);- bam_write(fp, p, name_len);- if (bam_is_be) {- x = bam_swap_endian_4(header->target_len[i]);- bam_write(fp, &x, 4);- } else bam_write(fp, &header->target_len[i], 4);- }- bgzf_flush(fp);- return 0;-}--static void swap_endian_data(const bam1_core_t *c, int data_len, uint8_t *data)-{- uint8_t *s;- uint32_t i, *cigar = (uint32_t*)(data + c->l_qname);- s = data + c->n_cigar*4 + c->l_qname + c->l_qseq + (c->l_qseq + 1)/2;- for (i = 0; i < c->n_cigar; ++i) bam_swap_endian_4p(&cigar[i]);- while (s < data + data_len) {- uint8_t type;- s += 2; // skip key- type = toupper(*s); ++s; // skip type- if (type == 'C' || type == 'A') ++s;- else if (type == 'S') { bam_swap_endian_2p(s); s += 2; }- else if (type == 'I' || type == 'F') { bam_swap_endian_4p(s); s += 4; }- else if (type == 'D') { bam_swap_endian_8p(s); s += 8; }- else if (type == 'Z' || type == 'H') { while (*s) ++s; ++s; }- }-}--int bam_read1(bamFile fp, bam1_t *b)-{- bam1_core_t *c = &b->core;- int32_t block_len, ret, i;- uint32_t x[8];-- assert(BAM_CORE_SIZE == 32);- if ((ret = bam_read(fp, &block_len, 4)) != 4) {- if (ret == 0) return -1; // normal end-of-file- else return -2; // truncated- }- if (bam_read(fp, x, BAM_CORE_SIZE) != BAM_CORE_SIZE) return -3;- if (bam_is_be) {- bam_swap_endian_4p(&block_len);- for (i = 0; i < 8; ++i) bam_swap_endian_4p(x + i);- }- c->tid = x[0]; c->pos = x[1];- c->bin = x[2]>>16; c->qual = x[2]>>8&0xff; c->l_qname = x[2]&0xff;- c->flag = x[3]>>16; c->n_cigar = x[3]&0xffff;- c->l_qseq = x[4];- c->mtid = x[5]; c->mpos = x[6]; c->isize = x[7];- b->data_len = block_len - BAM_CORE_SIZE;- if (b->m_data < b->data_len) {- b->m_data = b->data_len;- kroundup32(b->m_data);- b->data = (uint8_t*)realloc(b->data, b->m_data);- }- if (bam_read(fp, b->data, b->data_len) != b->data_len) return -4;- b->l_aux = b->data_len - c->n_cigar * 4 - c->l_qname - c->l_qseq - (c->l_qseq+1)/2;- if (bam_is_be) swap_endian_data(c, b->data_len, b->data);- return 4 + block_len;-}--inline int bam_write1_core(bamFile fp, const bam1_core_t *c, int data_len, uint8_t *data)-{- uint32_t x[8], block_len = data_len + BAM_CORE_SIZE, y;- int i;- assert(BAM_CORE_SIZE == 32);- x[0] = c->tid;- x[1] = c->pos;- x[2] = (uint32_t)c->bin<<16 | c->qual<<8 | c->l_qname;- x[3] = (uint32_t)c->flag<<16 | c->n_cigar;- x[4] = c->l_qseq;- x[5] = c->mtid;- x[6] = c->mpos;- x[7] = c->isize;- bgzf_flush_try(fp, 4 + block_len);- if (bam_is_be) {- for (i = 0; i < 8; ++i) bam_swap_endian_4p(x + i);- y = block_len;- bam_write(fp, bam_swap_endian_4p(&y), 4);- swap_endian_data(c, data_len, data);- } else bam_write(fp, &block_len, 4);- bam_write(fp, x, BAM_CORE_SIZE);- bam_write(fp, data, data_len);- if (bam_is_be) swap_endian_data(c, data_len, data);- return 4 + block_len;-}--int bam_write1(bamFile fp, const bam1_t *b)-{- return bam_write1_core(fp, &b->core, b->data_len, b->data);-}--char *bam_format1_core(const bam_header_t *header, const bam1_t *b, int of)-{- uint8_t *s = bam1_seq(b), *t = bam1_qual(b);- int i;- const bam1_core_t *c = &b->core;- kstring_t str;- str.l = str.m = 0; str.s = 0;-- kputsn(bam1_qname(b), c->l_qname-1, &str); kputc('\t', &str);- if (of == BAM_OFDEC) { kputw(c->flag, &str); kputc('\t', &str); }- else if (of == BAM_OFHEX) ksprintf(&str, "0x%x\t", c->flag);- else { // BAM_OFSTR- for (i = 0; i < 16; ++i)- if ((c->flag & 1<<i) && bam_flag2char_table[i])- kputc(bam_flag2char_table[i], &str);- kputc('\t', &str);- }- if (c->tid < 0) kputsn("*\t", 2, &str);- else {- if (header) kputs(header->target_name[c->tid] , &str);- else kputw(c->tid, &str);- kputc('\t', &str);- }- kputw(c->pos + 1, &str); kputc('\t', &str); kputw(c->qual, &str); kputc('\t', &str);- if (c->n_cigar == 0) kputc('*', &str);- else {- for (i = 0; i < c->n_cigar; ++i) {- kputw(bam1_cigar(b)[i]>>BAM_CIGAR_SHIFT, &str);- kputc("MIDNSHP"[bam1_cigar(b)[i]&BAM_CIGAR_MASK], &str);- }- }- kputc('\t', &str);- if (c->mtid < 0) kputsn("*\t", 2, &str);- else if (c->mtid == c->tid) kputsn("=\t", 2, &str);- else {- if (header) kputs(header->target_name[c->mtid], &str);- else kputw(c->mtid, &str);- kputc('\t', &str);- }- kputw(c->mpos + 1, &str); kputc('\t', &str); kputw(c->isize, &str); kputc('\t', &str);- if (c->l_qseq) {- for (i = 0; i < c->l_qseq; ++i) kputc(bam_nt16_rev_table[bam1_seqi(s, i)], &str);- kputc('\t', &str);- if (t[0] == 0xff) kputc('*', &str);- else for (i = 0; i < c->l_qseq; ++i) kputc(t[i] + 33, &str);- } else kputsn("*\t*", 3, &str);- s = bam1_aux(b);- while (s < b->data + b->data_len) {- uint8_t type, key[2];- key[0] = s[0]; key[1] = s[1];- s += 2; type = *s; ++s;- kputc('\t', &str); kputsn((char*)key, 2, &str); kputc(':', &str);- if (type == 'A') { kputsn("A:", 2, &str); kputc(*s, &str); ++s; }- else if (type == 'C') { kputsn("i:", 2, &str); kputw(*s, &str); ++s; }- else if (type == 'c') { kputsn("i:", 2, &str); kputw(*(int8_t*)s, &str); ++s; }- else if (type == 'S') { kputsn("i:", 2, &str); kputw(*(uint16_t*)s, &str); s += 2; }- else if (type == 's') { kputsn("i:", 2, &str); kputw(*(int16_t*)s, &str); s += 2; }- else if (type == 'I') { kputsn("i:", 2, &str); kputuw(*(uint32_t*)s, &str); s += 4; }- else if (type == 'i') { kputsn("i:", 2, &str); kputw(*(int32_t*)s, &str); s += 4; }- else if (type == 'f') { ksprintf(&str, "f:%g", *(float*)s); s += 4; }- else if (type == 'd') { ksprintf(&str, "d:%lg", *(double*)s); s += 8; }- else if (type == 'Z' || type == 'H') { kputc(type, &str); kputc(':', &str); while (*s) kputc(*s++, &str); ++s; }- }- return str.s;-}--char *bam_format1(const bam_header_t *header, const bam1_t *b)-{- return bam_format1_core(header, b, BAM_OFDEC);-}--void bam_view1(const bam_header_t *header, const bam1_t *b)-{- char *s = bam_format1(header, b);- puts(s);- free(s);-}--int bam_validate1(const bam_header_t *header, const bam1_t *b)-{- char *s;-- if (b->core.tid < -1 || b->core.mtid < -1) return 0;- if (header && (b->core.tid >= header->n_targets || b->core.mtid >= header->n_targets)) return 0;-- if (b->data_len < b->core.l_qname) return 0;- s = memchr(bam1_qname(b), '\0', b->core.l_qname);- if (s != &bam1_qname(b)[b->core.l_qname-1]) return 0;-- // FIXME: Other fields could also be checked, especially the auxiliary data-- return 1;-}--// FIXME: we should also check the LB tag associated with each alignment-const char *bam_get_library(bam_header_t *h, const bam1_t *b)-{- const uint8_t *rg;- if (h->dict == 0) h->dict = sam_header_parse2(h->text);- if (h->rg2lib == 0) h->rg2lib = sam_header2tbl(h->dict, "RG", "ID", "LB");- rg = bam_aux_get(b, "RG");- return (rg == 0)? 0 : sam_tbl_get(h->rg2lib, (const char*)(rg + 1));-}
− samtools-0.1.13/bam.h
@@ -1,743 +0,0 @@-/* The MIT License-- Copyright (c) 2008-2010 Genome Research Ltd (GRL).-- 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.-*/--/* Contact: Heng Li <lh3@sanger.ac.uk> */--#ifndef BAM_BAM_H-#define BAM_BAM_H--/*!- @header-- BAM library provides I/O and various operations on manipulating files- in the BAM (Binary Alignment/Mapping) or SAM (Sequence Alignment/Map)- format. It now supports importing from or exporting to TAM, sorting,- merging, generating pileup, and quickly retrieval of reads overlapped- with a specified region.-- @copyright Genome Research Ltd.- */--#define BAM_VERSION "0.1.13 (r926:134)"--#include <stdint.h>-#include <stdlib.h>-#include <string.h>-#include <stdio.h>--#ifndef BAM_LITE-#define BAM_VIRTUAL_OFFSET16-#include "bgzf.h"-/*! @abstract BAM file handler */-typedef BGZF *bamFile;-#define bam_open(fn, mode) bgzf_open(fn, mode)-#define bam_dopen(fd, mode) bgzf_fdopen(fd, mode)-#define bam_close(fp) bgzf_close(fp)-#define bam_read(fp, buf, size) bgzf_read(fp, buf, size)-#define bam_write(fp, buf, size) bgzf_write(fp, buf, size)-#define bam_tell(fp) bgzf_tell(fp)-#define bam_seek(fp, pos, dir) bgzf_seek(fp, pos, dir)-#else-#define BAM_TRUE_OFFSET-#include <zlib.h>-typedef gzFile bamFile;-#define bam_open(fn, mode) gzopen(fn, mode)-#define bam_dopen(fd, mode) gzdopen(fd, mode)-#define bam_close(fp) gzclose(fp)-#define bam_read(fp, buf, size) gzread(fp, buf, size)-/* no bam_write/bam_tell/bam_seek() here */-#endif--/*! @typedef- @abstract Structure for the alignment header.- @field n_targets number of reference sequences- @field target_name names of the reference sequences- @field target_len lengths of the referene sequences- @field dict header dictionary- @field hash hash table for fast name lookup- @field rg2lib hash table for @RG-ID -> LB lookup- @field l_text length of the plain text in the header- @field text plain text-- @discussion Field hash points to null by default. It is a private- member.- */-typedef struct {- int32_t n_targets;- char **target_name;- uint32_t *target_len;- void *dict, *hash, *rg2lib;- size_t l_text, n_text;- char *text;-} bam_header_t;--/*! @abstract the read is paired in sequencing, no matter whether it is mapped in a pair */-#define BAM_FPAIRED 1-/*! @abstract the read is mapped in a proper pair */-#define BAM_FPROPER_PAIR 2-/*! @abstract the read itself is unmapped; conflictive with BAM_FPROPER_PAIR */-#define BAM_FUNMAP 4-/*! @abstract the mate is unmapped */-#define BAM_FMUNMAP 8-/*! @abstract the read is mapped to the reverse strand */-#define BAM_FREVERSE 16-/*! @abstract the mate is mapped to the reverse strand */-#define BAM_FMREVERSE 32-/*! @abstract this is read1 */-#define BAM_FREAD1 64-/*! @abstract this is read2 */-#define BAM_FREAD2 128-/*! @abstract not primary alignment */-#define BAM_FSECONDARY 256-/*! @abstract QC failure */-#define BAM_FQCFAIL 512-/*! @abstract optical or PCR duplicate */-#define BAM_FDUP 1024--#define BAM_OFDEC 0-#define BAM_OFHEX 1-#define BAM_OFSTR 2--/*! @abstract defautl mask for pileup */-#define BAM_DEF_MASK (BAM_FUNMAP | BAM_FSECONDARY | BAM_FQCFAIL | BAM_FDUP)--#define BAM_CORE_SIZE sizeof(bam1_core_t)--/**- * Describing how CIGAR operation/length is packed in a 32-bit integer.- */-#define BAM_CIGAR_SHIFT 4-#define BAM_CIGAR_MASK ((1 << BAM_CIGAR_SHIFT) - 1)--/*- CIGAR operations.- */-/*! @abstract CIGAR: match */-#define BAM_CMATCH 0-/*! @abstract CIGAR: insertion to the reference */-#define BAM_CINS 1-/*! @abstract CIGAR: deletion from the reference */-#define BAM_CDEL 2-/*! @abstract CIGAR: skip on the reference (e.g. spliced alignment) */-#define BAM_CREF_SKIP 3-/*! @abstract CIGAR: clip on the read with clipped sequence present in qseq */-#define BAM_CSOFT_CLIP 4-/*! @abstract CIGAR: clip on the read with clipped sequence trimmed off */-#define BAM_CHARD_CLIP 5-/*! @abstract CIGAR: padding */-#define BAM_CPAD 6--/*! @typedef- @abstract Structure for core alignment information.- @field tid chromosome ID, defined by bam_header_t- @field pos 0-based leftmost coordinate- @field strand strand; 0 for forward and 1 otherwise- @field bin bin calculated by bam_reg2bin()- @field qual mapping quality- @field l_qname length of the query name- @field flag bitwise flag- @field n_cigar number of CIGAR operations- @field l_qseq length of the query sequence (read)- */-typedef struct {- int32_t tid;- int32_t pos;- uint32_t bin:16, qual:8, l_qname:8;- uint32_t flag:16, n_cigar:16;- int32_t l_qseq;- int32_t mtid;- int32_t mpos;- int32_t isize;-} bam1_core_t;--/*! @typedef- @abstract Structure for one alignment.- @field core core information about the alignment- @field l_aux length of auxiliary data- @field data_len current length of bam1_t::data- @field m_data maximum length of bam1_t::data- @field data all variable-length data, concatenated; structure: cigar-qname-seq-qual-aux-- @discussion Notes:- - 1. qname is zero tailing and core.l_qname includes the tailing '\0'.- 2. l_qseq is calculated from the total length of an alignment block- on reading or from CIGAR.- */-typedef struct {- bam1_core_t core;- int l_aux, data_len, m_data;- uint8_t *data;-} bam1_t;--typedef struct __bam_iter_t *bam_iter_t;--#define bam1_strand(b) (((b)->core.flag&BAM_FREVERSE) != 0)-#define bam1_mstrand(b) (((b)->core.flag&BAM_FMREVERSE) != 0)--/*! @function- @abstract Get the CIGAR array- @param b pointer to an alignment- @return pointer to the CIGAR array-- @discussion In the CIGAR array, each element is a 32-bit integer. The- lower 4 bits gives a CIGAR operation and the higher 28 bits keep the- length of a CIGAR.- */-#define bam1_cigar(b) ((uint32_t*)((b)->data + (b)->core.l_qname))--/*! @function- @abstract Get the name of the query- @param b pointer to an alignment- @return pointer to the name string, null terminated- */-#define bam1_qname(b) ((char*)((b)->data))--/*! @function- @abstract Get query sequence- @param b pointer to an alignment- @return pointer to sequence-- @discussion Each base is encoded in 4 bits: 1 for A, 2 for C, 4 for G,- 8 for T and 15 for N. Two bases are packed in one byte with the base- at the higher 4 bits having smaller coordinate on the read. It is- recommended to use bam1_seqi() macro to get the base.- */-#define bam1_seq(b) ((b)->data + (b)->core.n_cigar*4 + (b)->core.l_qname)--/*! @function- @abstract Get query quality- @param b pointer to an alignment- @return pointer to quality string- */-#define bam1_qual(b) ((b)->data + (b)->core.n_cigar*4 + (b)->core.l_qname + (((b)->core.l_qseq + 1)>>1))--/*! @function- @abstract Get a base on read- @param s Query sequence returned by bam1_seq()- @param i The i-th position, 0-based- @return 4-bit integer representing the base.- */-#define bam1_seqi(s, i) ((s)[(i)/2] >> 4*(1-(i)%2) & 0xf)--/*! @function- @abstract Get query sequence and quality- @param b pointer to an alignment- @return pointer to the concatenated auxiliary data- */-#define bam1_aux(b) ((b)->data + (b)->core.n_cigar*4 + (b)->core.l_qname + (b)->core.l_qseq + ((b)->core.l_qseq + 1)/2)--#ifndef kroundup32-/*! @function- @abstract Round an integer to the next closest power-2 integer.- @param x integer to be rounded (in place)- @discussion x will be modified.- */-#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))-#endif--/*!- @abstract Whether the machine is big-endian; modified only in- bam_header_init().- */-extern int bam_is_be;--/*! @abstract Table for converting a nucleotide character to the 4-bit encoding. */-extern unsigned char bam_nt16_table[256];--/*! @abstract Table for converting a 4-bit encoded nucleotide to a letter. */-extern char *bam_nt16_rev_table;--extern char bam_nt16_nt4_table[];--#ifdef __cplusplus-extern "C" {-#endif-- /*********************- * Low-level SAM I/O *- *********************/-- /*! @abstract TAM file handler */- typedef struct __tamFile_t *tamFile;-- /*!- @abstract Open a SAM file for reading, either uncompressed or compressed by gzip/zlib.- @param fn SAM file name- @return SAM file handler- */- tamFile sam_open(const char *fn);-- /*!- @abstract Close a SAM file handler- @param fp SAM file handler- */- void sam_close(tamFile fp);-- /*!- @abstract Read one alignment from a SAM file handler- @param fp SAM file handler- @param header header information (ordered names of chromosomes)- @param b read alignment; all members in b will be updated- @return 0 if successful; otherwise negative- */- int sam_read1(tamFile fp, bam_header_t *header, bam1_t *b);-- /*!- @abstract Read header information from a TAB-delimited list file.- @param fn_list file name for the list- @return a pointer to the header structure-- @discussion Each line in this file consists of chromosome name and- the length of chromosome.- */- bam_header_t *sam_header_read2(const char *fn_list);-- /*!- @abstract Read header from a SAM file (if present)- @param fp SAM file handler- @return pointer to header struct; 0 if no @SQ lines available- */- bam_header_t *sam_header_read(tamFile fp);-- /*!- @abstract Parse @SQ lines a update a header struct- @param h pointer to the header struct to be updated- @return number of target sequences-- @discussion bam_header_t::{n_targets,target_len,target_name} will- be destroyed in the first place.- */- int sam_header_parse(bam_header_t *h);- int32_t bam_get_tid(const bam_header_t *header, const char *seq_name);-- /*!- @abstract Parse @RG lines a update a header struct- @param h pointer to the header struct to be updated- @return number of @RG lines-- @discussion bam_header_t::rg2lib will be destroyed in the first- place.- */- int sam_header_parse_rg(bam_header_t *h);--#define sam_write1(header, b) bam_view1(header, b)--- /********************************- * APIs for string dictionaries *- ********************************/-- int bam_strmap_put(void *strmap, const char *rg, const char *lib);- const char *bam_strmap_get(const void *strmap, const char *rg);- void *bam_strmap_dup(const void*);- void *bam_strmap_init();- void bam_strmap_destroy(void *strmap);--- /*********************- * Low-level BAM I/O *- *********************/-- /*!- @abstract Initialize a header structure.- @return the pointer to the header structure-- @discussion This function also modifies the global variable- bam_is_be.- */- bam_header_t *bam_header_init();-- /*!- @abstract Destroy a header structure.- @param header pointer to the header- */- void bam_header_destroy(bam_header_t *header);-- /*!- @abstract Read a header structure from BAM.- @param fp BAM file handler, opened by bam_open()- @return pointer to the header structure-- @discussion The file position indicator must be placed at the- beginning of the file. Upon success, the position indicator will- be set at the start of the first alignment.- */- bam_header_t *bam_header_read(bamFile fp);-- /*!- @abstract Write a header structure to BAM.- @param fp BAM file handler- @param header pointer to the header structure- @return always 0 currently- */- int bam_header_write(bamFile fp, const bam_header_t *header);-- /*!- @abstract Read an alignment from BAM.- @param fp BAM file handler- @param b read alignment; all members are updated.- @return number of bytes read from the file-- @discussion The file position indicator must be- placed right before an alignment. Upon success, this function- will set the position indicator to the start of the next- alignment. This function is not affected by the machine- endianness.- */- int bam_read1(bamFile fp, bam1_t *b);-- /*!- @abstract Write an alignment to BAM.- @param fp BAM file handler- @param c pointer to the bam1_core_t structure- @param data_len total length of variable size data related to- the alignment- @param data pointer to the concatenated data- @return number of bytes written to the file-- @discussion This function is not affected by the machine- endianness.- */- int bam_write1_core(bamFile fp, const bam1_core_t *c, int data_len, uint8_t *data);-- /*!- @abstract Write an alignment to BAM.- @param fp BAM file handler- @param b alignment to write- @return number of bytes written to the file-- @abstract It is equivalent to:- bam_write1_core(fp, &b->core, b->data_len, b->data)- */- int bam_write1(bamFile fp, const bam1_t *b);-- /*! @function- @abstract Initiate a pointer to bam1_t struct- */-#define bam_init1() ((bam1_t*)calloc(1, sizeof(bam1_t)))-- /*! @function- @abstract Free the memory allocated for an alignment.- @param b pointer to an alignment- */-#define bam_destroy1(b) do { \- if (b) { free((b)->data); free(b); } \- } while (0)-- /*!- @abstract Format a BAM record in the SAM format- @param header pointer to the header structure- @param b alignment to print- @return a pointer to the SAM string- */- char *bam_format1(const bam_header_t *header, const bam1_t *b);-- char *bam_format1_core(const bam_header_t *header, const bam1_t *b, int of);-- /*!- @abstract Check whether a BAM record is plausibly valid- @param header associated header structure, or NULL if unavailable- @param b alignment to validate- @return 0 if the alignment is invalid; non-zero otherwise-- @discussion Simple consistency check of some of the fields of the- alignment record. If the header is provided, several additional checks- are made. Not all fields are checked, so a non-zero result is not a- guarantee that the record is valid. However it is usually good enough- to detect when bam_seek() has been called with a virtual file offset- that is not the offset of an alignment record.- */- int bam_validate1(const bam_header_t *header, const bam1_t *b);-- const char *bam_get_library(bam_header_t *header, const bam1_t *b);--- /***************- * pileup APIs *- ***************/-- /*! @typedef- @abstract Structure for one alignment covering the pileup position.- @field b pointer to the alignment- @field qpos position of the read base at the pileup site, 0-based- @field indel indel length; 0 for no indel, positive for ins and negative for del- @field is_del 1 iff the base on the padded read is a deletion- @field level the level of the read in the "viewer" mode-- @discussion See also bam_plbuf_push() and bam_lplbuf_push(). The- difference between the two functions is that the former does not- set bam_pileup1_t::level, while the later does. Level helps the- implementation of alignment viewers, but calculating this has some- overhead.- */- typedef struct {- bam1_t *b;- int32_t qpos;- int indel, level;- uint32_t is_del:1, is_head:1, is_tail:1, is_refskip:1, aux:28;- } bam_pileup1_t;-- typedef int (*bam_plp_auto_f)(void *data, bam1_t *b);-- struct __bam_plp_t;- typedef struct __bam_plp_t *bam_plp_t;-- bam_plp_t bam_plp_init(bam_plp_auto_f func, void *data);- int bam_plp_push(bam_plp_t iter, const bam1_t *b);- const bam_pileup1_t *bam_plp_next(bam_plp_t iter, int *_tid, int *_pos, int *_n_plp);- const bam_pileup1_t *bam_plp_auto(bam_plp_t iter, int *_tid, int *_pos, int *_n_plp);- void bam_plp_set_mask(bam_plp_t iter, int mask);- void bam_plp_set_maxcnt(bam_plp_t iter, int maxcnt);- void bam_plp_reset(bam_plp_t iter);- void bam_plp_destroy(bam_plp_t iter);-- struct __bam_mplp_t;- typedef struct __bam_mplp_t *bam_mplp_t;-- bam_mplp_t bam_mplp_init(int n, bam_plp_auto_f func, void **data);- void bam_mplp_destroy(bam_mplp_t iter);- void bam_mplp_set_maxcnt(bam_mplp_t iter, int maxcnt);- int bam_mplp_auto(bam_mplp_t iter, int *_tid, int *_pos, int *n_plp, const bam_pileup1_t **plp);-- /*! @typedef- @abstract Type of function to be called by bam_plbuf_push().- @param tid chromosome ID as is defined in the header- @param pos start coordinate of the alignment, 0-based- @param n number of elements in pl array- @param pl array of alignments- @param data user provided data- @discussion See also bam_plbuf_push(), bam_plbuf_init() and bam_pileup1_t.- */- typedef int (*bam_pileup_f)(uint32_t tid, uint32_t pos, int n, const bam_pileup1_t *pl, void *data);-- typedef struct {- bam_plp_t iter;- bam_pileup_f func;- void *data;- } bam_plbuf_t;-- void bam_plbuf_set_mask(bam_plbuf_t *buf, int mask);- void bam_plbuf_reset(bam_plbuf_t *buf);- bam_plbuf_t *bam_plbuf_init(bam_pileup_f func, void *data);- void bam_plbuf_destroy(bam_plbuf_t *buf);- int bam_plbuf_push(const bam1_t *b, bam_plbuf_t *buf);-- int bam_pileup_file(bamFile fp, int mask, bam_pileup_f func, void *func_data);-- struct __bam_lplbuf_t;- typedef struct __bam_lplbuf_t bam_lplbuf_t;-- void bam_lplbuf_reset(bam_lplbuf_t *buf);-- /*! @abstract bam_plbuf_init() equivalent with level calculated. */- bam_lplbuf_t *bam_lplbuf_init(bam_pileup_f func, void *data);-- /*! @abstract bam_plbuf_destroy() equivalent with level calculated. */- void bam_lplbuf_destroy(bam_lplbuf_t *tv);-- /*! @abstract bam_plbuf_push() equivalent with level calculated. */- int bam_lplbuf_push(const bam1_t *b, bam_lplbuf_t *buf);--- /*********************- * BAM indexing APIs *- *********************/-- struct __bam_index_t;- typedef struct __bam_index_t bam_index_t;-- /*!- @abstract Build index for a BAM file.- @discussion Index file "fn.bai" will be created.- @param fn name of the BAM file- @return always 0 currently- */- int bam_index_build(const char *fn);-- /*!- @abstract Load index from file "fn.bai".- @param fn name of the BAM file (NOT the index file)- @return pointer to the index structure- */- bam_index_t *bam_index_load(const char *fn);-- /*!- @abstract Destroy an index structure.- @param idx pointer to the index structure- */- void bam_index_destroy(bam_index_t *idx);-- /*! @typedef- @abstract Type of function to be called by bam_fetch().- @param b the alignment- @param data user provided data- */- typedef int (*bam_fetch_f)(const bam1_t *b, void *data);-- /*!- @abstract Retrieve the alignments that are overlapped with the- specified region.-- @discussion A user defined function will be called for each- retrieved alignment ordered by its start position.-- @param fp BAM file handler- @param idx pointer to the alignment index- @param tid chromosome ID as is defined in the header- @param beg start coordinate, 0-based- @param end end coordinate, 0-based- @param data user provided data (will be transferred to func)- @param func user defined function- */- int bam_fetch(bamFile fp, const bam_index_t *idx, int tid, int beg, int end, void *data, bam_fetch_f func);-- bam_iter_t bam_iter_query(const bam_index_t *idx, int tid, int beg, int end);- int bam_iter_read(bamFile fp, bam_iter_t iter, bam1_t *b);- void bam_iter_destroy(bam_iter_t iter);-- /*!- @abstract Parse a region in the format: "chr2:100,000-200,000".- @discussion bam_header_t::hash will be initialized if empty.- @param header pointer to the header structure- @param str string to be parsed- @param ref_id the returned chromosome ID- @param begin the returned start coordinate- @param end the returned end coordinate- @return 0 on success; -1 on failure- */- int bam_parse_region(bam_header_t *header, const char *str, int *ref_id, int *begin, int *end);--- /**************************- * APIs for optional tags *- **************************/-- /*!- @abstract Retrieve data of a tag- @param b pointer to an alignment struct- @param tag two-character tag to be retrieved-- @return pointer to the type and data. The first character is the- type that can be 'iIsScCdfAZH'.-- @discussion Use bam_aux2?() series to convert the returned data to- the corresponding type.- */- uint8_t *bam_aux_get(const bam1_t *b, const char tag[2]);-- int32_t bam_aux2i(const uint8_t *s);- float bam_aux2f(const uint8_t *s);- double bam_aux2d(const uint8_t *s);- char bam_aux2A(const uint8_t *s);- char *bam_aux2Z(const uint8_t *s);-- int bam_aux_del(bam1_t *b, uint8_t *s);- void bam_aux_append(bam1_t *b, const char tag[2], char type, int len, uint8_t *data);- uint8_t *bam_aux_get_core(bam1_t *b, const char tag[2]); // an alias of bam_aux_get()--- /*****************- * Miscellaneous *- *****************/-- /*! - @abstract Calculate the rightmost coordinate of an alignment on the- reference genome.-- @param c pointer to the bam1_core_t structure- @param cigar the corresponding CIGAR array (from bam1_t::cigar)- @return the rightmost coordinate, 0-based- */- uint32_t bam_calend(const bam1_core_t *c, const uint32_t *cigar);-- /*!- @abstract Calculate the length of the query sequence from CIGAR.- @param c pointer to the bam1_core_t structure- @param cigar the corresponding CIGAR array (from bam1_t::cigar)- @return length of the query sequence- */- int32_t bam_cigar2qlen(const bam1_core_t *c, const uint32_t *cigar);--#ifdef __cplusplus-}-#endif--/*!- @abstract Calculate the minimum bin that contains a region [beg,end).- @param beg start of the region, 0-based- @param end end of the region, 0-based- @return bin- */-static inline int bam_reg2bin(uint32_t beg, uint32_t end)-{- --end;- if (beg>>14 == end>>14) return 4681 + (beg>>14);- if (beg>>17 == end>>17) return 585 + (beg>>17);- if (beg>>20 == end>>20) return 73 + (beg>>20);- if (beg>>23 == end>>23) return 9 + (beg>>23);- if (beg>>26 == end>>26) return 1 + (beg>>26);- return 0;-}--/*!- @abstract Copy an alignment- @param bdst destination alignment struct- @param bsrc source alignment struct- @return pointer to the destination alignment struct- */-static inline bam1_t *bam_copy1(bam1_t *bdst, const bam1_t *bsrc)-{- uint8_t *data = bdst->data;- int m_data = bdst->m_data; // backup data and m_data- if (m_data < bsrc->data_len) { // double the capacity- m_data = bsrc->data_len; kroundup32(m_data);- data = (uint8_t*)realloc(data, m_data);- }- memcpy(data, bsrc->data, bsrc->data_len); // copy var-len data- *bdst = *bsrc; // copy the rest- // restore the backup- bdst->m_data = m_data;- bdst->data = data;- return bdst;-}--/*!- @abstract Duplicate an alignment- @param src source alignment struct- @return pointer to the destination alignment struct- */-static inline bam1_t *bam_dup1(const bam1_t *src)-{- bam1_t *b;- b = bam_init1();- *b = *src;- b->m_data = b->data_len;- b->data = (uint8_t*)calloc(b->data_len, 1);- memcpy(b->data, src->data, b->data_len);- return b;-}--#endif
− samtools-0.1.13/bam_aux.c
@@ -1,189 +0,0 @@-#include <ctype.h>-#include "bam.h"-#include "khash.h"-typedef char *str_p;-KHASH_MAP_INIT_STR(s, int)-KHASH_MAP_INIT_STR(r2l, str_p)--void bam_aux_append(bam1_t *b, const char tag[2], char type, int len, uint8_t *data)-{- int ori_len = b->data_len;- b->data_len += 3 + len;- b->l_aux += 3 + len;- if (b->m_data < b->data_len) {- b->m_data = b->data_len;- kroundup32(b->m_data);- b->data = (uint8_t*)realloc(b->data, b->m_data);- }- b->data[ori_len] = tag[0]; b->data[ori_len + 1] = tag[1];- b->data[ori_len + 2] = type;- memcpy(b->data + ori_len + 3, data, len);-}--uint8_t *bam_aux_get_core(bam1_t *b, const char tag[2])-{- return bam_aux_get(b, tag);-}--#define __skip_tag(s) do { \- int type = toupper(*(s)); \- ++(s); \- if (type == 'C' || type == 'A') ++(s); \- else if (type == 'S') (s) += 2; \- else if (type == 'I' || type == 'F') (s) += 4; \- else if (type == 'D') (s) += 8; \- else if (type == 'Z' || type == 'H') { while (*(s)) ++(s); ++(s); } \- } while (0)--uint8_t *bam_aux_get(const bam1_t *b, const char tag[2])-{- uint8_t *s;- int y = tag[0]<<8 | tag[1];- s = bam1_aux(b);- while (s < b->data + b->data_len) {- int x = (int)s[0]<<8 | s[1];- s += 2;- if (x == y) return s;- __skip_tag(s);- }- return 0;-}-// s MUST BE returned by bam_aux_get()-int bam_aux_del(bam1_t *b, uint8_t *s)-{- uint8_t *p, *aux;- aux = bam1_aux(b);- p = s - 2;- __skip_tag(s);- memmove(p, s, b->l_aux - (s - aux));- b->data_len -= s - p;- b->l_aux -= s - p;- return 0;-}--void bam_init_header_hash(bam_header_t *header)-{- if (header->hash == 0) {- int ret, i;- khiter_t iter;- khash_t(s) *h;- header->hash = h = kh_init(s);- for (i = 0; i < header->n_targets; ++i) {- iter = kh_put(s, h, header->target_name[i], &ret);- kh_value(h, iter) = i;- }- }-}--void bam_destroy_header_hash(bam_header_t *header)-{- if (header->hash)- kh_destroy(s, (khash_t(s)*)header->hash);-}--int32_t bam_get_tid(const bam_header_t *header, const char *seq_name)-{- khint_t k;- khash_t(s) *h = (khash_t(s)*)header->hash;- k = kh_get(s, h, seq_name);- return k == kh_end(h)? -1 : kh_value(h, k);-}--int bam_parse_region(bam_header_t *header, const char *str, int *ref_id, int *begin, int *end)-{- char *s, *p;- int i, l, k;- khiter_t iter;- khash_t(s) *h;-- bam_init_header_hash(header);- h = (khash_t(s)*)header->hash;-- l = strlen(str);- p = s = (char*)malloc(l+1);- /* squeeze out "," */- for (i = k = 0; i != l; ++i)- if (str[i] != ',' && !isspace(str[i])) s[k++] = str[i];- s[k] = 0;- for (i = 0; i != k; ++i) if (s[i] == ':') break;- s[i] = 0;- iter = kh_get(s, h, s); /* get the ref_id */- if (iter == kh_end(h)) { // name not found- *ref_id = -1; free(s);- return -1;- }- *ref_id = kh_value(h, iter);- if (i == k) { /* dump the whole sequence */- *begin = 0; *end = 1<<29; free(s);- return 0;- }- for (p = s + i + 1; i != k; ++i) if (s[i] == '-') break;- *begin = atoi(p);- if (i < k) {- p = s + i + 1;- *end = atoi(p);- } else *end = 1<<29;- if (*begin > 0) --*begin;- free(s);- if (*begin > *end) {- fprintf(stderr, "[bam_parse_region] invalid region.\n");- return -1;- }- return 0;-}--int32_t bam_aux2i(const uint8_t *s)-{- int type;- if (s == 0) return 0;- type = *s++;- if (type == 'c') return (int32_t)*(int8_t*)s;- else if (type == 'C') return (int32_t)*(uint8_t*)s;- else if (type == 's') return (int32_t)*(int16_t*)s;- else if (type == 'S') return (int32_t)*(uint16_t*)s;- else if (type == 'i' || type == 'I') return *(int32_t*)s;- else return 0;-}--float bam_aux2f(const uint8_t *s)-{- int type;- type = *s++;- if (s == 0) return 0.0;- if (type == 'f') return *(float*)s;- else return 0.0;-}--double bam_aux2d(const uint8_t *s)-{- int type;- type = *s++;- if (s == 0) return 0.0;- if (type == 'd') return *(double*)s;- else return 0.0;-}--char bam_aux2A(const uint8_t *s)-{- int type;- type = *s++;- if (s == 0) return 0;- if (type == 'A') return *(char*)s;- else return 0;-}--char *bam_aux2Z(const uint8_t *s)-{- int type;- type = *s++;- if (s == 0) return 0;- if (type == 'Z' || type == 'H') return (char*)s;- else return 0;-}--#ifdef _WIN32-double drand48()-{- return (double)rand() / RAND_MAX;-}-#endif
− samtools-0.1.13/bam_endian.h
@@ -1,42 +0,0 @@-#ifndef BAM_ENDIAN_H-#define BAM_ENDIAN_H--#include <stdint.h>--static inline int bam_is_big_endian()-{- long one= 1;- return !(*((char *)(&one)));-}-static inline uint16_t bam_swap_endian_2(uint16_t v)-{- return (uint16_t)(((v & 0x00FF00FFU) << 8) | ((v & 0xFF00FF00U) >> 8));-}-static inline void *bam_swap_endian_2p(void *x)-{- *(uint16_t*)x = bam_swap_endian_2(*(uint16_t*)x);- return x;-}-static inline uint32_t bam_swap_endian_4(uint32_t v)-{- v = ((v & 0x0000FFFFU) << 16) | (v >> 16);- return ((v & 0x00FF00FFU) << 8) | ((v & 0xFF00FF00U) >> 8);-}-static inline void *bam_swap_endian_4p(void *x)-{- *(uint32_t*)x = bam_swap_endian_4(*(uint32_t*)x);- return x;-}-static inline uint64_t bam_swap_endian_8(uint64_t v)-{- v = ((v & 0x00000000FFFFFFFFLLU) << 32) | (v >> 32);- v = ((v & 0x0000FFFF0000FFFFLLU) << 16) | ((v & 0xFFFF0000FFFF0000LLU) >> 16);- return ((v & 0x00FF00FF00FF00FFLLU) << 8) | ((v & 0xFF00FF00FF00FF00LLU) >> 8);-}-static inline void *bam_swap_endian_8p(void *x)-{- *(uint64_t*)x = bam_swap_endian_8(*(uint64_t*)x);- return x;-}--#endif
− samtools-0.1.13/bam_import.c
@@ -1,459 +0,0 @@-#include <zlib.h>-#include <stdio.h>-#include <ctype.h>-#include <string.h>-#include <stdlib.h>-#include <unistd.h>-#include <assert.h>-#ifdef _WIN32-#include <fcntl.h>-#endif-#include "kstring.h"-#include "bam.h"-#include "sam_header.h"-#include "kseq.h"-#include "khash.h"--KSTREAM_INIT(gzFile, gzread, 8192)-KHASH_MAP_INIT_STR(ref, uint64_t)--void bam_init_header_hash(bam_header_t *header);-void bam_destroy_header_hash(bam_header_t *header);-int32_t bam_get_tid(const bam_header_t *header, const char *seq_name);--unsigned char bam_nt16_table[256] = {- 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,- 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,- 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,- 1, 2, 4, 8, 15,15,15,15, 15,15,15,15, 15, 0 /*=*/,15,15,- 15, 1,14, 2, 13,15,15, 4, 11,15,15,12, 15, 3,15,15,- 15,15, 5, 6, 8,15, 7, 9, 15,10,15,15, 15,15,15,15,- 15, 1,14, 2, 13,15,15, 4, 11,15,15,12, 15, 3,15,15,- 15,15, 5, 6, 8,15, 7, 9, 15,10,15,15, 15,15,15,15,- 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,- 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,- 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,- 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,- 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,- 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,- 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,- 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15-};--unsigned short bam_char2flag_table[256] = {- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,- 0,BAM_FREAD1,BAM_FREAD2,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,- BAM_FPROPER_PAIR,0,BAM_FMREVERSE,0, 0,BAM_FMUNMAP,0,0, 0,0,0,0, 0,0,0,0,- 0,0,0,0, BAM_FDUP,0,BAM_FQCFAIL,0, 0,0,0,0, 0,0,0,0,- BAM_FPAIRED,0,BAM_FREVERSE,BAM_FSECONDARY, 0,BAM_FUNMAP,0,0, 0,0,0,0, 0,0,0,0,- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0-};--char *bam_nt16_rev_table = "=ACMGRSVTWYHKDBN";--struct __tamFile_t {- gzFile fp;- kstream_t *ks;- kstring_t *str;- uint64_t n_lines;- int is_first;-};--char **__bam_get_lines(const char *fn, int *_n) // for bam_plcmd.c only-{- char **list = 0, *s;- int n = 0, dret, m = 0;- gzFile fp = (strcmp(fn, "-") == 0)? gzdopen(fileno(stdin), "r") : gzopen(fn, "r");- kstream_t *ks;- kstring_t *str;- str = (kstring_t*)calloc(1, sizeof(kstring_t));- ks = ks_init(fp);- while (ks_getuntil(ks, '\n', str, &dret) > 0) {- if (n == m) {- m = m? m << 1 : 16;- list = (char**)realloc(list, m * sizeof(char*));- }- if (str->s[str->l-1] == '\r')- str->s[--str->l] = '\0';- s = list[n++] = (char*)calloc(str->l + 1, 1);- strcpy(s, str->s);- }- ks_destroy(ks);- gzclose(fp);- free(str->s); free(str);- *_n = n;- return list;-}--static bam_header_t *hash2header(const kh_ref_t *hash)-{- bam_header_t *header;- khiter_t k;- header = bam_header_init();- header->n_targets = kh_size(hash);- header->target_name = (char**)calloc(kh_size(hash), sizeof(char*));- header->target_len = (uint32_t*)calloc(kh_size(hash), 4);- for (k = kh_begin(hash); k != kh_end(hash); ++k) {- if (kh_exist(hash, k)) {- int i = (int)kh_value(hash, k);- header->target_name[i] = (char*)kh_key(hash, k);- header->target_len[i] = kh_value(hash, k)>>32;- }- }- bam_init_header_hash(header);- return header;-}-bam_header_t *sam_header_read2(const char *fn)-{- bam_header_t *header;- int c, dret, ret, error = 0;- gzFile fp;- kstream_t *ks;- kstring_t *str;- kh_ref_t *hash;- khiter_t k;- if (fn == 0) return 0;- fp = (strcmp(fn, "-") == 0)? gzdopen(fileno(stdin), "r") : gzopen(fn, "r");- if (fp == 0) return 0;- hash = kh_init(ref);- ks = ks_init(fp);- str = (kstring_t*)calloc(1, sizeof(kstring_t));- while (ks_getuntil(ks, 0, str, &dret) > 0) {- char *s = strdup(str->s);- int len, i;- i = kh_size(hash);- ks_getuntil(ks, 0, str, &dret);- len = atoi(str->s);- k = kh_put(ref, hash, s, &ret);- if (ret == 0) {- fprintf(stderr, "[sam_header_read2] duplicated sequence name: %s\n", s);- error = 1;- }- kh_value(hash, k) = (uint64_t)len<<32 | i;- if (dret != '\n')- while ((c = ks_getc(ks)) != '\n' && c != -1);- }- ks_destroy(ks);- gzclose(fp);- free(str->s); free(str);- fprintf(stderr, "[sam_header_read2] %d sequences loaded.\n", kh_size(hash));- if (error) return 0;- header = hash2header(hash);- kh_destroy(ref, hash);- return header;-}-static inline uint8_t *alloc_data(bam1_t *b, int size)-{- if (b->m_data < size) {- b->m_data = size;- kroundup32(b->m_data);- b->data = (uint8_t*)realloc(b->data, b->m_data);- }- return b->data;-}-static inline void parse_error(int64_t n_lines, const char * __restrict msg)-{- fprintf(stderr, "Parse error at line %lld: %s\n", (long long)n_lines, msg);- abort();-}-static inline void append_text(bam_header_t *header, kstring_t *str)-{- size_t x = header->l_text, y = header->l_text + str->l + 2; // 2 = 1 byte dret + 1 byte null- kroundup32(x); kroundup32(y);- if (x < y) - {- header->n_text = y;- header->text = (char*)realloc(header->text, y);- if ( !header->text ) - {- fprintf(stderr,"realloc failed to alloc %ld bytes\n", y);- abort();- }- }- // Sanity check- if ( header->l_text+str->l+1 >= header->n_text )- {- fprintf(stderr,"append_text FIXME: %ld>=%ld, x=%ld,y=%ld\n", header->l_text+str->l+1,header->n_text,x,y);- abort();- }- strncpy(header->text + header->l_text, str->s, str->l+1); // we cannot use strcpy() here.- header->l_text += str->l + 1;- header->text[header->l_text] = 0;-}--int sam_header_parse(bam_header_t *h)-{- char **tmp;- int i;- free(h->target_len); free(h->target_name);- h->n_targets = 0; h->target_len = 0; h->target_name = 0;- if (h->l_text < 3) return 0;- if (h->dict == 0) h->dict = sam_header_parse2(h->text);- tmp = sam_header2list(h->dict, "SQ", "SN", &h->n_targets);- if (h->n_targets == 0) return 0;- h->target_name = calloc(h->n_targets, sizeof(void*));- for (i = 0; i < h->n_targets; ++i)- h->target_name[i] = strdup(tmp[i]);- free(tmp);- tmp = sam_header2list(h->dict, "SQ", "LN", &h->n_targets);- h->target_len = calloc(h->n_targets, 4);- for (i = 0; i < h->n_targets; ++i)- h->target_len[i] = atoi(tmp[i]);- free(tmp);- return h->n_targets;-}--bam_header_t *sam_header_read(tamFile fp)-{- int ret, dret;- bam_header_t *header = bam_header_init();- kstring_t *str = fp->str;- while ((ret = ks_getuntil(fp->ks, KS_SEP_TAB, str, &dret)) >= 0 && str->s[0] == '@') { // skip header- str->s[str->l] = dret; // note that str->s is NOT null terminated!!- append_text(header, str);- if (dret != '\n') {- ret = ks_getuntil(fp->ks, '\n', str, &dret);- str->s[str->l] = '\n'; // NOT null terminated!!- append_text(header, str);- }- ++fp->n_lines;- }- sam_header_parse(header);- bam_init_header_hash(header);- fp->is_first = 1;- return header;-}--int sam_read1(tamFile fp, bam_header_t *header, bam1_t *b)-{- int ret, doff, doff0, dret, z = 0;- bam1_core_t *c = &b->core;- kstring_t *str = fp->str;- kstream_t *ks = fp->ks;-- if (fp->is_first) {- fp->is_first = 0;- ret = str->l;- } else {- do { // special consideration for empty lines- ret = ks_getuntil(fp->ks, KS_SEP_TAB, str, &dret);- if (ret >= 0) z += str->l + 1;- } while (ret == 0);- }- if (ret < 0) return -1;- ++fp->n_lines;- doff = 0;-- { // name- c->l_qname = strlen(str->s) + 1;- memcpy(alloc_data(b, doff + c->l_qname) + doff, str->s, c->l_qname);- doff += c->l_qname;- }- { // flag- long flag;- char *s;- ret = ks_getuntil(ks, KS_SEP_TAB, str, &dret); z += str->l + 1;- flag = strtol((char*)str->s, &s, 0);- if (*s) { // not the end of the string- flag = 0;- for (s = str->s; *s; ++s)- flag |= bam_char2flag_table[(int)*s];- }- c->flag = flag;- }- { // tid, pos, qual- ret = ks_getuntil(ks, KS_SEP_TAB, str, &dret); z += str->l + 1; c->tid = bam_get_tid(header, str->s);- if (c->tid < 0 && strcmp(str->s, "*")) {- if (header->n_targets == 0) {- fprintf(stderr, "[sam_read1] missing header? Abort!\n");- exit(1);- } else fprintf(stderr, "[sam_read1] reference '%s' is recognized as '*'.\n", str->s);- }- ret = ks_getuntil(ks, KS_SEP_TAB, str, &dret); z += str->l + 1; c->pos = isdigit(str->s[0])? atoi(str->s) - 1 : -1;- ret = ks_getuntil(ks, KS_SEP_TAB, str, &dret); z += str->l + 1; c->qual = isdigit(str->s[0])? atoi(str->s) : 0;- if (ret < 0) return -2;- }- { // cigar- char *s, *t;- int i, op;- long x;- c->n_cigar = 0;- if (ks_getuntil(ks, KS_SEP_TAB, str, &dret) < 0) return -3;- z += str->l + 1;- if (str->s[0] != '*') {- for (s = str->s; *s; ++s) {- if (isalpha(*s)) ++c->n_cigar;- else if (!isdigit(*s)) parse_error(fp->n_lines, "invalid CIGAR character");- }- b->data = alloc_data(b, doff + c->n_cigar * 4);- for (i = 0, s = str->s; i != c->n_cigar; ++i) {- x = strtol(s, &t, 10);- op = toupper(*t);- if (op == 'M' || op == '=' || op == 'X') op = BAM_CMATCH;- else if (op == 'I') op = BAM_CINS;- else if (op == 'D') op = BAM_CDEL;- else if (op == 'N') op = BAM_CREF_SKIP;- else if (op == 'S') op = BAM_CSOFT_CLIP;- else if (op == 'H') op = BAM_CHARD_CLIP;- else if (op == 'P') op = BAM_CPAD;- else parse_error(fp->n_lines, "invalid CIGAR operation");- s = t + 1;- bam1_cigar(b)[i] = x << BAM_CIGAR_SHIFT | op;- }- if (*s) parse_error(fp->n_lines, "unmatched CIGAR operation");- c->bin = bam_reg2bin(c->pos, bam_calend(c, bam1_cigar(b)));- doff += c->n_cigar * 4;- } else {- if (!(c->flag&BAM_FUNMAP)) {- fprintf(stderr, "Parse warning at line %lld: mapped sequence without CIGAR\n", (long long)fp->n_lines);- c->flag |= BAM_FUNMAP;- }- c->bin = bam_reg2bin(c->pos, c->pos + 1);- }- }- { // mtid, mpos, isize- ret = ks_getuntil(ks, KS_SEP_TAB, str, &dret); z += str->l + 1;- c->mtid = strcmp(str->s, "=")? bam_get_tid(header, str->s) : c->tid;- ret = ks_getuntil(ks, KS_SEP_TAB, str, &dret); z += str->l + 1;- c->mpos = isdigit(str->s[0])? atoi(str->s) - 1 : -1;- ret = ks_getuntil(ks, KS_SEP_TAB, str, &dret); z += str->l + 1;- c->isize = (str->s[0] == '-' || isdigit(str->s[0]))? atoi(str->s) : 0;- if (ret < 0) return -4;- }- { // seq and qual- int i;- uint8_t *p = 0;- if (ks_getuntil(ks, KS_SEP_TAB, str, &dret) < 0) return -5; // seq- z += str->l + 1;- if (strcmp(str->s, "*")) {- c->l_qseq = strlen(str->s);- if (c->n_cigar && c->l_qseq != (int32_t)bam_cigar2qlen(c, bam1_cigar(b)))- parse_error(fp->n_lines, "CIGAR and sequence length are inconsistent");- p = (uint8_t*)alloc_data(b, doff + c->l_qseq + (c->l_qseq+1)/2) + doff;- memset(p, 0, (c->l_qseq+1)/2);- for (i = 0; i < c->l_qseq; ++i)- p[i/2] |= bam_nt16_table[(int)str->s[i]] << 4*(1-i%2);- } else c->l_qseq = 0;- if (ks_getuntil(ks, KS_SEP_TAB, str, &dret) < 0) return -6; // qual- z += str->l + 1;- if (strcmp(str->s, "*") && c->l_qseq != strlen(str->s))- parse_error(fp->n_lines, "sequence and quality are inconsistent");- p += (c->l_qseq+1)/2;- if (strcmp(str->s, "*") == 0) for (i = 0; i < c->l_qseq; ++i) p[i] = 0xff;- else for (i = 0; i < c->l_qseq; ++i) p[i] = str->s[i] - 33;- doff += c->l_qseq + (c->l_qseq+1)/2;- }- doff0 = doff;- if (dret != '\n' && dret != '\r') { // aux- while (ks_getuntil(ks, KS_SEP_TAB, str, &dret) >= 0) {- uint8_t *s, type, key[2];- z += str->l + 1;- if (str->l < 6 || str->s[2] != ':' || str->s[4] != ':')- parse_error(fp->n_lines, "missing colon in auxiliary data");- key[0] = str->s[0]; key[1] = str->s[1];- type = str->s[3];- s = alloc_data(b, doff + 3) + doff;- s[0] = key[0]; s[1] = key[1]; s += 2; doff += 2;- if (type == 'A' || type == 'a' || type == 'c' || type == 'C') { // c and C for backward compatibility- s = alloc_data(b, doff + 2) + doff;- *s++ = 'A'; *s = str->s[5];- doff += 2;- } else if (type == 'I' || type == 'i') {- long long x;- s = alloc_data(b, doff + 5) + doff;- x = (long long)atoll(str->s + 5);- if (x < 0) {- if (x >= -127) {- *s++ = 'c'; *(int8_t*)s = (int8_t)x;- s += 1; doff += 2;- } else if (x >= -32767) {- *s++ = 's'; *(int16_t*)s = (int16_t)x;- s += 2; doff += 3;- } else {- *s++ = 'i'; *(int32_t*)s = (int32_t)x;- s += 4; doff += 5;- if (x < -2147483648ll)- fprintf(stderr, "Parse warning at line %lld: integer %lld is out of range.",- (long long)fp->n_lines, x);- }- } else {- if (x <= 255) {- *s++ = 'C'; *s++ = (uint8_t)x;- doff += 2;- } else if (x <= 65535) {- *s++ = 'S'; *(uint16_t*)s = (uint16_t)x;- s += 2; doff += 3;- } else {- *s++ = 'I'; *(uint32_t*)s = (uint32_t)x;- s += 4; doff += 5;- if (x > 4294967295ll)- fprintf(stderr, "Parse warning at line %lld: integer %lld is out of range.",- (long long)fp->n_lines, x);- }- }- } else if (type == 'f') {- s = alloc_data(b, doff + 5) + doff;- *s++ = 'f';- *(float*)s = (float)atof(str->s + 5);- s += 4; doff += 5;- } else if (type == 'd') {- s = alloc_data(b, doff + 9) + doff;- *s++ = 'd';- *(float*)s = (float)atof(str->s + 9);- s += 8; doff += 9;- } else if (type == 'Z' || type == 'H') {- int size = 1 + (str->l - 5) + 1;- if (type == 'H') { // check whether the hex string is valid- int i;- if ((str->l - 5) % 2 == 1) parse_error(fp->n_lines, "length of the hex string not even");- for (i = 0; i < str->l - 5; ++i) {- int c = toupper(str->s[5 + i]);- if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')))- parse_error(fp->n_lines, "invalid hex character");- }- }- s = alloc_data(b, doff + size) + doff;- *s++ = type;- memcpy(s, str->s + 5, str->l - 5);- s[str->l - 5] = 0;- doff += size;- } else parse_error(fp->n_lines, "unrecognized type");- if (dret == '\n' || dret == '\r') break;- }- }- b->l_aux = doff - doff0;- b->data_len = doff;- return z;-}--tamFile sam_open(const char *fn)-{- tamFile fp;- gzFile gzfp = (strcmp(fn, "-") == 0)? gzdopen(fileno(stdin), "rb") : gzopen(fn, "rb");- if (gzfp == 0) return 0;- fp = (tamFile)calloc(1, sizeof(struct __tamFile_t));- fp->str = (kstring_t*)calloc(1, sizeof(kstring_t));- fp->fp = gzfp;- fp->ks = ks_init(fp->fp);- return fp;-}--void sam_close(tamFile fp)-{- if (fp) {- ks_destroy(fp->ks);- gzclose(fp->fp);- free(fp->str->s); free(fp->str);- free(fp);- }-}
− samtools-0.1.13/bam_index.c
@@ -1,711 +0,0 @@-#include <ctype.h>-#include <assert.h>-#include "bam.h"-#include "khash.h"-#include "ksort.h"-#include "bam_endian.h"-#ifdef _USE_KNETFILE-#include "knetfile.h"-#endif--/*!- @header-- Alignment indexing. Before indexing, BAM must be sorted based on the- leftmost coordinate of alignments. In indexing, BAM uses two indices:- a UCSC binning index and a simple linear index. The binning index is- efficient for alignments spanning long distance, while the auxiliary- linear index helps to reduce unnecessary seek calls especially for- short alignments.-- The UCSC binning scheme was suggested by Richard Durbin and Lincoln- Stein and is explained by Kent et al. (2002). In this scheme, each bin- represents a contiguous genomic region which can be fully contained in- another bin; each alignment is associated with a bin which represents- the smallest region containing the entire alignment. The binning- scheme is essentially another representation of R-tree. A distinct bin- uniquely corresponds to a distinct internal node in a R-tree. Bin A is- a child of Bin B if region A is contained in B.-- In BAM, each bin may span 2^29, 2^26, 2^23, 2^20, 2^17 or 2^14 bp. Bin- 0 spans a 512Mbp region, bins 1-8 span 64Mbp, 9-72 8Mbp, 73-584 1Mbp,- 585-4680 128Kbp and bins 4681-37449 span 16Kbp regions. If we want to- find the alignments overlapped with a region [rbeg,rend), we need to- calculate the list of bins that may be overlapped the region and test- the alignments in the bins to confirm the overlaps. If the specified- region is short, typically only a few alignments in six bins need to- be retrieved. The overlapping alignments can be quickly fetched.-- */--#define BAM_MIN_CHUNK_GAP 32768-// 1<<14 is the size of minimum bin.-#define BAM_LIDX_SHIFT 14--#define BAM_MAX_BIN 37450 // =(8^6-1)/7+1--typedef struct {- uint64_t u, v;-} pair64_t;--#define pair64_lt(a,b) ((a).u < (b).u)-KSORT_INIT(off, pair64_t, pair64_lt)--typedef struct {- uint32_t m, n;- pair64_t *list;-} bam_binlist_t;--typedef struct {- int32_t n, m;- uint64_t *offset;-} bam_lidx_t;--KHASH_MAP_INIT_INT(i, bam_binlist_t)--struct __bam_index_t {- int32_t n;- uint64_t n_no_coor; // unmapped reads without coordinate- khash_t(i) **index;- bam_lidx_t *index2;-};--// requirement: len <= LEN_MASK-static inline void insert_offset(khash_t(i) *h, int bin, uint64_t beg, uint64_t end)-{- khint_t k;- bam_binlist_t *l;- int ret;- k = kh_put(i, h, bin, &ret);- l = &kh_value(h, k);- if (ret) { // not present- l->m = 1; l->n = 0;- l->list = (pair64_t*)calloc(l->m, 16);- }- if (l->n == l->m) {- l->m <<= 1;- l->list = (pair64_t*)realloc(l->list, l->m * 16);- }- l->list[l->n].u = beg; l->list[l->n++].v = end;-}--static inline void insert_offset2(bam_lidx_t *index2, bam1_t *b, uint64_t offset)-{- int i, beg, end;- beg = b->core.pos >> BAM_LIDX_SHIFT;- end = (bam_calend(&b->core, bam1_cigar(b)) - 1) >> BAM_LIDX_SHIFT;- if (index2->m < end + 1) {- int old_m = index2->m;- index2->m = end + 1;- kroundup32(index2->m);- index2->offset = (uint64_t*)realloc(index2->offset, index2->m * 8);- memset(index2->offset + old_m, 0, 8 * (index2->m - old_m));- }- if (beg == end) {- if (index2->offset[beg] == 0) index2->offset[beg] = offset;- } else {- for (i = beg; i <= end; ++i)- if (index2->offset[i] == 0) index2->offset[i] = offset;- }- index2->n = end + 1;-}--static void merge_chunks(bam_index_t *idx)-{-#if defined(BAM_TRUE_OFFSET) || defined(BAM_VIRTUAL_OFFSET16)- khash_t(i) *index;- int i, l, m;- khint_t k;- for (i = 0; i < idx->n; ++i) {- index = idx->index[i];- for (k = kh_begin(index); k != kh_end(index); ++k) {- bam_binlist_t *p;- if (!kh_exist(index, k) || kh_key(index, k) == BAM_MAX_BIN) continue;- p = &kh_value(index, k);- m = 0;- for (l = 1; l < p->n; ++l) {-#ifdef BAM_TRUE_OFFSET- if (p->list[m].v + BAM_MIN_CHUNK_GAP > p->list[l].u) p->list[m].v = p->list[l].v;-#else- if (p->list[m].v>>16 == p->list[l].u>>16) p->list[m].v = p->list[l].v;-#endif- else p->list[++m] = p->list[l];- } // ~for(l)- p->n = m + 1;- } // ~for(k)- } // ~for(i)-#endif // defined(BAM_TRUE_OFFSET) || defined(BAM_BGZF)-}--static void fill_missing(bam_index_t *idx)-{- int i, j;- for (i = 0; i < idx->n; ++i) {- bam_lidx_t *idx2 = &idx->index2[i];- for (j = 1; j < idx2->n; ++j)- if (idx2->offset[j] == 0)- idx2->offset[j] = idx2->offset[j-1];- }-}--bam_index_t *bam_index_core(bamFile fp)-{- bam1_t *b;- bam_header_t *h;- int i, ret;- bam_index_t *idx;- uint32_t last_bin, save_bin;- int32_t last_coor, last_tid, save_tid;- bam1_core_t *c;- uint64_t save_off, last_off, n_mapped, n_unmapped, off_beg, off_end, n_no_coor;-- idx = (bam_index_t*)calloc(1, sizeof(bam_index_t));- b = (bam1_t*)calloc(1, sizeof(bam1_t));- h = bam_header_read(fp);- c = &b->core;-- idx->n = h->n_targets;- bam_header_destroy(h);- idx->index = (khash_t(i)**)calloc(idx->n, sizeof(void*));- for (i = 0; i < idx->n; ++i) idx->index[i] = kh_init(i);- idx->index2 = (bam_lidx_t*)calloc(idx->n, sizeof(bam_lidx_t));-- save_bin = save_tid = last_tid = last_bin = 0xffffffffu;- save_off = last_off = bam_tell(fp); last_coor = 0xffffffffu;- n_mapped = n_unmapped = n_no_coor = off_end = 0;- off_beg = off_end = bam_tell(fp);- while ((ret = bam_read1(fp, b)) >= 0) {- if (c->tid < 0) ++n_no_coor;- if (last_tid != c->tid) { // change of chromosomes- last_tid = c->tid;- last_bin = 0xffffffffu;- } else if (last_coor > c->pos) {- fprintf(stderr, "[bam_index_core] the alignment is not sorted (%s): %u > %u in %d-th chr\n",- bam1_qname(b), last_coor, c->pos, c->tid+1);- exit(1);- }- if (c->tid >= 0) insert_offset2(&idx->index2[b->core.tid], b, last_off);- if (c->bin != last_bin) { // then possibly write the binning index- if (save_bin != 0xffffffffu) // save_bin==0xffffffffu only happens to the first record- insert_offset(idx->index[save_tid], save_bin, save_off, last_off);- if (last_bin == 0xffffffffu && save_tid != 0xffffffffu) { // write the meta element- off_end = last_off;- insert_offset(idx->index[save_tid], BAM_MAX_BIN, off_beg, off_end);- insert_offset(idx->index[save_tid], BAM_MAX_BIN, n_mapped, n_unmapped);- n_mapped = n_unmapped = 0;- off_beg = off_end;- }- save_off = last_off;- save_bin = last_bin = c->bin;- save_tid = c->tid;- if (save_tid < 0) break;- }- if (bam_tell(fp) <= last_off) {- fprintf(stderr, "[bam_index_core] bug in BGZF/RAZF: %llx < %llx\n",- (unsigned long long)bam_tell(fp), (unsigned long long)last_off);- exit(1);- }- if (c->flag & BAM_FUNMAP) ++n_unmapped;- else ++n_mapped;- last_off = bam_tell(fp);- last_coor = b->core.pos;- }- if (save_tid >= 0) {- insert_offset(idx->index[save_tid], save_bin, save_off, bam_tell(fp));- insert_offset(idx->index[save_tid], BAM_MAX_BIN, off_beg, bam_tell(fp));- insert_offset(idx->index[save_tid], BAM_MAX_BIN, n_mapped, n_unmapped);- }- merge_chunks(idx);- fill_missing(idx);- if (ret >= 0) {- while ((ret = bam_read1(fp, b)) >= 0) {- ++n_no_coor;- if (c->tid >= 0 && n_no_coor) {- fprintf(stderr, "[bam_index_core] the alignment is not sorted: reads without coordinates prior to reads with coordinates.\n");- exit(1);- }- }- }- if (ret < -1) fprintf(stderr, "[bam_index_core] truncated file? Continue anyway. (%d)\n", ret);- free(b->data); free(b);- idx->n_no_coor = n_no_coor;- return idx;-}--void bam_index_destroy(bam_index_t *idx)-{- khint_t k;- int i;- if (idx == 0) return;- for (i = 0; i < idx->n; ++i) {- khash_t(i) *index = idx->index[i];- bam_lidx_t *index2 = idx->index2 + i;- for (k = kh_begin(index); k != kh_end(index); ++k) {- if (kh_exist(index, k))- free(kh_value(index, k).list);- }- kh_destroy(i, index);- free(index2->offset);- }- free(idx->index); free(idx->index2);- free(idx);-}--void bam_index_save(const bam_index_t *idx, FILE *fp)-{- int32_t i, size;- khint_t k;- fwrite("BAI\1", 1, 4, fp);- if (bam_is_be) {- uint32_t x = idx->n;- fwrite(bam_swap_endian_4p(&x), 4, 1, fp);- } else fwrite(&idx->n, 4, 1, fp);- for (i = 0; i < idx->n; ++i) {- khash_t(i) *index = idx->index[i];- bam_lidx_t *index2 = idx->index2 + i;- // write binning index- size = kh_size(index);- if (bam_is_be) { // big endian- uint32_t x = size;- fwrite(bam_swap_endian_4p(&x), 4, 1, fp);- } else fwrite(&size, 4, 1, fp);- for (k = kh_begin(index); k != kh_end(index); ++k) {- if (kh_exist(index, k)) {- bam_binlist_t *p = &kh_value(index, k);- if (bam_is_be) { // big endian- uint32_t x;- x = kh_key(index, k); fwrite(bam_swap_endian_4p(&x), 4, 1, fp);- x = p->n; fwrite(bam_swap_endian_4p(&x), 4, 1, fp);- for (x = 0; (int)x < p->n; ++x) {- bam_swap_endian_8p(&p->list[x].u);- bam_swap_endian_8p(&p->list[x].v);- }- fwrite(p->list, 16, p->n, fp);- for (x = 0; (int)x < p->n; ++x) {- bam_swap_endian_8p(&p->list[x].u);- bam_swap_endian_8p(&p->list[x].v);- }- } else {- fwrite(&kh_key(index, k), 4, 1, fp);- fwrite(&p->n, 4, 1, fp);- fwrite(p->list, 16, p->n, fp);- }- }- }- // write linear index (index2)- if (bam_is_be) {- int x = index2->n;- fwrite(bam_swap_endian_4p(&x), 4, 1, fp);- } else fwrite(&index2->n, 4, 1, fp);- if (bam_is_be) { // big endian- int x;- for (x = 0; (int)x < index2->n; ++x)- bam_swap_endian_8p(&index2->offset[x]);- fwrite(index2->offset, 8, index2->n, fp);- for (x = 0; (int)x < index2->n; ++x)- bam_swap_endian_8p(&index2->offset[x]);- } else fwrite(index2->offset, 8, index2->n, fp);- }- { // write the number of reads coor-less records.- uint64_t x = idx->n_no_coor;- if (bam_is_be) bam_swap_endian_8p(&x);- fwrite(&x, 8, 1, fp);- }- fflush(fp);-}--static bam_index_t *bam_index_load_core(FILE *fp)-{- int i;- char magic[4];- bam_index_t *idx;- if (fp == 0) {- fprintf(stderr, "[bam_index_load_core] fail to load index.\n");- return 0;- }- fread(magic, 1, 4, fp);- if (strncmp(magic, "BAI\1", 4)) {- fprintf(stderr, "[bam_index_load] wrong magic number.\n");- fclose(fp);- return 0;- }- idx = (bam_index_t*)calloc(1, sizeof(bam_index_t)); - fread(&idx->n, 4, 1, fp);- if (bam_is_be) bam_swap_endian_4p(&idx->n);- idx->index = (khash_t(i)**)calloc(idx->n, sizeof(void*));- idx->index2 = (bam_lidx_t*)calloc(idx->n, sizeof(bam_lidx_t));- for (i = 0; i < idx->n; ++i) {- khash_t(i) *index;- bam_lidx_t *index2 = idx->index2 + i;- uint32_t key, size;- khint_t k;- int j, ret;- bam_binlist_t *p;- index = idx->index[i] = kh_init(i);- // load binning index- fread(&size, 4, 1, fp);- if (bam_is_be) bam_swap_endian_4p(&size);- for (j = 0; j < (int)size; ++j) {- fread(&key, 4, 1, fp);- if (bam_is_be) bam_swap_endian_4p(&key);- k = kh_put(i, index, key, &ret);- p = &kh_value(index, k);- fread(&p->n, 4, 1, fp);- if (bam_is_be) bam_swap_endian_4p(&p->n);- p->m = p->n;- p->list = (pair64_t*)malloc(p->m * 16);- fread(p->list, 16, p->n, fp);- if (bam_is_be) {- int x;- for (x = 0; x < p->n; ++x) {- bam_swap_endian_8p(&p->list[x].u);- bam_swap_endian_8p(&p->list[x].v);- }- }- }- // load linear index- fread(&index2->n, 4, 1, fp);- if (bam_is_be) bam_swap_endian_4p(&index2->n);- index2->m = index2->n;- index2->offset = (uint64_t*)calloc(index2->m, 8);- fread(index2->offset, index2->n, 8, fp);- if (bam_is_be)- for (j = 0; j < index2->n; ++j) bam_swap_endian_8p(&index2->offset[j]);- }- if (fread(&idx->n_no_coor, 8, 1, fp) == 0) idx->n_no_coor = 0;- if (bam_is_be) bam_swap_endian_8p(&idx->n_no_coor);- return idx;-}--bam_index_t *bam_index_load_local(const char *_fn)-{- FILE *fp;- char *fnidx, *fn;-- if (strstr(_fn, "ftp://") == _fn || strstr(_fn, "http://") == _fn) {- const char *p;- int l = strlen(_fn);- for (p = _fn + l - 1; p >= _fn; --p)- if (*p == '/') break;- fn = strdup(p + 1);- } else fn = strdup(_fn);- fnidx = (char*)calloc(strlen(fn) + 5, 1);- strcpy(fnidx, fn); strcat(fnidx, ".bai");- fp = fopen(fnidx, "rb");- if (fp == 0) { // try "{base}.bai"- char *s = strstr(fn, "bam");- if (s == fn + strlen(fn) - 3) {- strcpy(fnidx, fn);- fnidx[strlen(fn)-1] = 'i';- fp = fopen(fnidx, "rb");- }- }- free(fnidx); free(fn);- if (fp) {- bam_index_t *idx = bam_index_load_core(fp);- fclose(fp);- return idx;- } else return 0;-}--#ifdef _USE_KNETFILE-static void download_from_remote(const char *url)-{- const int buf_size = 1 * 1024 * 1024;- char *fn;- FILE *fp;- uint8_t *buf;- knetFile *fp_remote;- int l;- if (strstr(url, "ftp://") != url && strstr(url, "http://") != url) return;- l = strlen(url);- for (fn = (char*)url + l - 1; fn >= url; --fn)- if (*fn == '/') break;- ++fn; // fn now points to the file name- fp_remote = knet_open(url, "r");- if (fp_remote == 0) {- fprintf(stderr, "[download_from_remote] fail to open remote file.\n");- return;- }- if ((fp = fopen(fn, "wb")) == 0) {- fprintf(stderr, "[download_from_remote] fail to create file in the working directory.\n");- knet_close(fp_remote);- return;- }- buf = (uint8_t*)calloc(buf_size, 1);- while ((l = knet_read(fp_remote, buf, buf_size)) != 0)- fwrite(buf, 1, l, fp);- free(buf);- fclose(fp);- knet_close(fp_remote);-}-#else-static void download_from_remote(const char *url)-{- return;-}-#endif--bam_index_t *bam_index_load(const char *fn)-{- bam_index_t *idx;- idx = bam_index_load_local(fn);- if (idx == 0 && (strstr(fn, "ftp://") == fn || strstr(fn, "http://") == fn)) {- char *fnidx = calloc(strlen(fn) + 5, 1);- strcat(strcpy(fnidx, fn), ".bai");- fprintf(stderr, "[bam_index_load] attempting to download the remote index file.\n");- download_from_remote(fnidx);- idx = bam_index_load_local(fn);- }- if (idx == 0) fprintf(stderr, "[bam_index_load] fail to load BAM index.\n");- return idx;-}--int bam_index_build2(const char *fn, const char *_fnidx)-{- char *fnidx;- FILE *fpidx;- bamFile fp;- bam_index_t *idx;- if ((fp = bam_open(fn, "r")) == 0) {- fprintf(stderr, "[bam_index_build2] fail to open the BAM file.\n");- return -1;- }- idx = bam_index_core(fp);- bam_close(fp);- if (_fnidx == 0) {- fnidx = (char*)calloc(strlen(fn) + 5, 1);- strcpy(fnidx, fn); strcat(fnidx, ".bai");- } else fnidx = strdup(_fnidx);- fpidx = fopen(fnidx, "wb");- if (fpidx == 0) {- fprintf(stderr, "[bam_index_build2] fail to create the index file.\n");- free(fnidx);- return -1;- }- bam_index_save(idx, fpidx);- bam_index_destroy(idx);- fclose(fpidx);- free(fnidx);- return 0;-}--int bam_index_build(const char *fn)-{- return bam_index_build2(fn, 0);-}--int bam_index(int argc, char *argv[])-{- if (argc < 2) {- fprintf(stderr, "Usage: samtools index <in.bam> [out.index]\n");- return 1;- }- if (argc >= 3) bam_index_build2(argv[1], argv[2]);- else bam_index_build(argv[1]);- return 0;-}--int bam_idxstats(int argc, char *argv[])-{- bam_index_t *idx;- bam_header_t *header;- bamFile fp;- int i;- if (argc < 2) {- fprintf(stderr, "Usage: samtools idxstats <in.bam>\n");- return 1;- }- fp = bam_open(argv[1], "r");- if (fp == 0) { fprintf(stderr, "[%s] fail to open BAM.\n", __func__); return 1; }- header = bam_header_read(fp);- bam_close(fp);- idx = bam_index_load(argv[1]);- if (idx == 0) { fprintf(stderr, "[%s] fail to load the index.\n", __func__); return 1; }- for (i = 0; i < idx->n; ++i) {- khint_t k;- khash_t(i) *h = idx->index[i];- printf("%s\t%d", header->target_name[i], header->target_len[i]);- k = kh_get(i, h, BAM_MAX_BIN);- if (k != kh_end(h))- printf("\t%llu\t%llu", (long long)kh_val(h, k).list[1].u, (long long)kh_val(h, k).list[1].v);- else printf("\t0\t0");- putchar('\n');- }- printf("*\t0\t0\t%llu\n", (long long)idx->n_no_coor);- bam_header_destroy(header);- bam_index_destroy(idx);- return 0;-}--static inline int reg2bins(uint32_t beg, uint32_t end, uint16_t list[BAM_MAX_BIN])-{- int i = 0, k;- if (beg >= end) return 0;- if (end >= 1u<<29) end = 1u<<29;- --end;- list[i++] = 0;- for (k = 1 + (beg>>26); k <= 1 + (end>>26); ++k) list[i++] = k;- for (k = 9 + (beg>>23); k <= 9 + (end>>23); ++k) list[i++] = k;- for (k = 73 + (beg>>20); k <= 73 + (end>>20); ++k) list[i++] = k;- for (k = 585 + (beg>>17); k <= 585 + (end>>17); ++k) list[i++] = k;- for (k = 4681 + (beg>>14); k <= 4681 + (end>>14); ++k) list[i++] = k;- return i;-}--static inline int is_overlap(uint32_t beg, uint32_t end, const bam1_t *b)-{- uint32_t rbeg = b->core.pos;- uint32_t rend = b->core.n_cigar? bam_calend(&b->core, bam1_cigar(b)) : b->core.pos + 1;- return (rend > beg && rbeg < end);-}--struct __bam_iter_t {- int from_first; // read from the first record; no random access- int tid, beg, end, n_off, i, finished;- uint64_t curr_off;- pair64_t *off;-};--// bam_fetch helper function retrieves -bam_iter_t bam_iter_query(const bam_index_t *idx, int tid, int beg, int end)-{- uint16_t *bins;- int i, n_bins, n_off;- pair64_t *off;- khint_t k;- khash_t(i) *index;- uint64_t min_off;- bam_iter_t iter = 0;-- if (beg < 0) beg = 0;- if (end < beg) return 0;- // initialize iter- iter = calloc(1, sizeof(struct __bam_iter_t));- iter->tid = tid, iter->beg = beg, iter->end = end; iter->i = -1;- //- bins = (uint16_t*)calloc(BAM_MAX_BIN, 2);- n_bins = reg2bins(beg, end, bins);- index = idx->index[tid];- if (idx->index2[tid].n > 0) {- min_off = (beg>>BAM_LIDX_SHIFT >= idx->index2[tid].n)? idx->index2[tid].offset[idx->index2[tid].n-1]- : idx->index2[tid].offset[beg>>BAM_LIDX_SHIFT];- if (min_off == 0) { // improvement for index files built by tabix prior to 0.1.4- int n = beg>>BAM_LIDX_SHIFT;- if (n > idx->index2[tid].n) n = idx->index2[tid].n;- for (i = n - 1; i >= 0; --i)- if (idx->index2[tid].offset[i] != 0) break;- if (i >= 0) min_off = idx->index2[tid].offset[i];- }- } else min_off = 0; // tabix 0.1.2 may produce such index files- for (i = n_off = 0; i < n_bins; ++i) {- if ((k = kh_get(i, index, bins[i])) != kh_end(index))- n_off += kh_value(index, k).n;- }- if (n_off == 0) {- free(bins); return iter;- }- off = (pair64_t*)calloc(n_off, 16);- for (i = n_off = 0; i < n_bins; ++i) {- if ((k = kh_get(i, index, bins[i])) != kh_end(index)) {- int j;- bam_binlist_t *p = &kh_value(index, k);- for (j = 0; j < p->n; ++j)- if (p->list[j].v > min_off) off[n_off++] = p->list[j];- }- }- free(bins);- if (n_off == 0) {- free(off); return iter;- }- {- bam1_t *b = (bam1_t*)calloc(1, sizeof(bam1_t));- int l;- ks_introsort(off, n_off, off);- // resolve completely contained adjacent blocks- for (i = 1, l = 0; i < n_off; ++i)- if (off[l].v < off[i].v)- off[++l] = off[i];- n_off = l + 1;- // resolve overlaps between adjacent blocks; this may happen due to the merge in indexing- for (i = 1; i < n_off; ++i)- if (off[i-1].v >= off[i].u) off[i-1].v = off[i].u;- { // merge adjacent blocks-#if defined(BAM_TRUE_OFFSET) || defined(BAM_VIRTUAL_OFFSET16)- for (i = 1, l = 0; i < n_off; ++i) {-#ifdef BAM_TRUE_OFFSET- if (off[l].v + BAM_MIN_CHUNK_GAP > off[i].u) off[l].v = off[i].v;-#else- if (off[l].v>>16 == off[i].u>>16) off[l].v = off[i].v;-#endif- else off[++l] = off[i];- }- n_off = l + 1;-#endif- }- bam_destroy1(b);- }- iter->n_off = n_off; iter->off = off;- return iter;-}--pair64_t *get_chunk_coordinates(const bam_index_t *idx, int tid, int beg, int end, int *cnt_off)-{ // for pysam compatibility- bam_iter_t iter;- pair64_t *off;- iter = bam_iter_query(idx, tid, beg, end);- off = iter->off; *cnt_off = iter->n_off;- free(iter);- return off;-}--void bam_iter_destroy(bam_iter_t iter)-{- if (iter) { free(iter->off); free(iter); }-}--int bam_iter_read(bamFile fp, bam_iter_t iter, bam1_t *b)-{- int ret;- if (iter && iter->finished) return -1;- if (iter == 0 || iter->from_first) {- ret = bam_read1(fp, b);- if (ret < 0 && iter) iter->finished = 1;- return ret;- }- if (iter->off == 0) return -1;- for (;;) {- if (iter->curr_off == 0 || iter->curr_off >= iter->off[iter->i].v) { // then jump to the next chunk- if (iter->i == iter->n_off - 1) { ret = -1; break; } // no more chunks- if (iter->i >= 0) assert(iter->curr_off == iter->off[iter->i].v); // otherwise bug- if (iter->i < 0 || iter->off[iter->i].v != iter->off[iter->i+1].u) { // not adjacent chunks; then seek- bam_seek(fp, iter->off[iter->i+1].u, SEEK_SET);- iter->curr_off = bam_tell(fp);- }- ++iter->i;- }- if ((ret = bam_read1(fp, b)) >= 0) {- iter->curr_off = bam_tell(fp);- if (b->core.tid != iter->tid || b->core.pos >= iter->end) { // no need to proceed- ret = bam_validate1(NULL, b)? -1 : -5; // determine whether end of region or error- break;- }- else if (is_overlap(iter->beg, iter->end, b)) return ret;- } else break; // end of file or error- }- iter->finished = 1;- return ret;-}--int bam_fetch(bamFile fp, const bam_index_t *idx, int tid, int beg, int end, void *data, bam_fetch_f func)-{- int ret;- bam_iter_t iter;- bam1_t *b;- b = bam_init1();- iter = bam_iter_query(idx, tid, beg, end);- while ((ret = bam_iter_read(fp, iter, b)) >= 0) func(b, data);- bam_iter_destroy(iter);- bam_destroy1(b);- return (ret == -1)? 0 : ret;-}
− samtools-0.1.13/bam_lpileup.c
@@ -1,198 +0,0 @@-#include <stdlib.h>-#include <stdio.h>-#include <assert.h>-#include "bam.h"-#include "ksort.h"--#define TV_GAP 2--typedef struct __freenode_t {- uint32_t level:28, cnt:4;- struct __freenode_t *next;-} freenode_t, *freenode_p;--#define freenode_lt(a,b) ((a)->cnt < (b)->cnt || ((a)->cnt == (b)->cnt && (a)->level < (b)->level))-KSORT_INIT(node, freenode_p, freenode_lt)--/* Memory pool, similar to the one in bam_pileup.c */-typedef struct {- int cnt, n, max;- freenode_t **buf;-} mempool_t;--static mempool_t *mp_init()-{- return (mempool_t*)calloc(1, sizeof(mempool_t));-}-static void mp_destroy(mempool_t *mp)-{- int k;- for (k = 0; k < mp->n; ++k) free(mp->buf[k]);- free(mp->buf); free(mp);-}-static inline freenode_t *mp_alloc(mempool_t *mp)-{- ++mp->cnt;- if (mp->n == 0) return (freenode_t*)calloc(1, sizeof(freenode_t));- else return mp->buf[--mp->n];-}-static inline void mp_free(mempool_t *mp, freenode_t *p)-{- --mp->cnt; p->next = 0; p->cnt = TV_GAP;- if (mp->n == mp->max) {- mp->max = mp->max? mp->max<<1 : 256;- mp->buf = (freenode_t**)realloc(mp->buf, sizeof(freenode_t*) * mp->max);- }- mp->buf[mp->n++] = p;-}--/* core part */-struct __bam_lplbuf_t {- int max, n_cur, n_pre;- int max_level, *cur_level, *pre_level;- mempool_t *mp;- freenode_t **aux, *head, *tail;- int n_nodes, m_aux;- bam_pileup_f func;- void *user_data;- bam_plbuf_t *plbuf;-};--void bam_lplbuf_reset(bam_lplbuf_t *buf)-{- freenode_t *p, *q;- bam_plbuf_reset(buf->plbuf);- for (p = buf->head; p->next;) {- q = p->next;- mp_free(buf->mp, p);- p = q;- }- buf->head = buf->tail;- buf->max_level = 0;- buf->n_cur = buf->n_pre = 0;- buf->n_nodes = 0;-}--static int tview_func(uint32_t tid, uint32_t pos, int n, const bam_pileup1_t *pl, void *data)-{- bam_lplbuf_t *tv = (bam_lplbuf_t*)data;- freenode_t *p;- int i, l, max_level;- // allocate memory if necessary- if (tv->max < n) { // enlarge- tv->max = n;- kroundup32(tv->max);- tv->cur_level = (int*)realloc(tv->cur_level, sizeof(int) * tv->max);- tv->pre_level = (int*)realloc(tv->pre_level, sizeof(int) * tv->max);- }- tv->n_cur = n;- // update cnt- for (p = tv->head; p->next; p = p->next)- if (p->cnt > 0) --p->cnt;- // calculate cur_level[]- max_level = 0;- for (i = l = 0; i < n; ++i) {- const bam_pileup1_t *p = pl + i;- if (p->is_head) {- if (tv->head->next && tv->head->cnt == 0) { // then take a free slot- freenode_t *p = tv->head->next;- tv->cur_level[i] = tv->head->level;- mp_free(tv->mp, tv->head);- tv->head = p;- --tv->n_nodes;- } else tv->cur_level[i] = ++tv->max_level;- } else {- tv->cur_level[i] = tv->pre_level[l++];- if (p->is_tail) { // then return a free slot- tv->tail->level = tv->cur_level[i];- tv->tail->next = mp_alloc(tv->mp);- tv->tail = tv->tail->next;- ++tv->n_nodes;- }- }- if (tv->cur_level[i] > max_level) max_level = tv->cur_level[i];- ((bam_pileup1_t*)p)->level = tv->cur_level[i];- }- assert(l == tv->n_pre);- tv->func(tid, pos, n, pl, tv->user_data);- // sort the linked list- if (tv->n_nodes) {- freenode_t *q;- if (tv->n_nodes + 1 > tv->m_aux) { // enlarge- tv->m_aux = tv->n_nodes + 1;- kroundup32(tv->m_aux);- tv->aux = (freenode_t**)realloc(tv->aux, sizeof(void*) * tv->m_aux);- }- for (p = tv->head, i = l = 0; p->next;) {- if (p->level > max_level) { // then discard this entry- q = p->next;- mp_free(tv->mp, p);- p = q;- } else {- tv->aux[i++] = p;- p = p->next;- }- }- tv->aux[i] = tv->tail; // add a proper tail for the loop below- tv->n_nodes = i;- if (tv->n_nodes) {- ks_introsort(node, tv->n_nodes, tv->aux);- for (i = 0; i < tv->n_nodes; ++i) tv->aux[i]->next = tv->aux[i+1];- tv->head = tv->aux[0];- } else tv->head = tv->tail;- }- // clean up- tv->max_level = max_level;- memcpy(tv->pre_level, tv->cur_level, tv->n_cur * 4);- // squeeze out terminated levels- for (i = l = 0; i < n; ++i) {- const bam_pileup1_t *p = pl + i;- if (!p->is_tail)- tv->pre_level[l++] = tv->pre_level[i];- }- tv->n_pre = l;-/*- fprintf(stderr, "%d\t", pos+1);- for (i = 0; i < n; ++i) {- const bam_pileup1_t *p = pl + i;- if (p->is_head) fprintf(stderr, "^");- if (p->is_tail) fprintf(stderr, "$");- fprintf(stderr, "%d,", p->level);- }- fprintf(stderr, "\n");-*/- return 0;-}--bam_lplbuf_t *bam_lplbuf_init(bam_pileup_f func, void *data)-{- bam_lplbuf_t *tv;- tv = (bam_lplbuf_t*)calloc(1, sizeof(bam_lplbuf_t));- tv->mp = mp_init();- tv->head = tv->tail = mp_alloc(tv->mp);- tv->func = func;- tv->user_data = data;- tv->plbuf = bam_plbuf_init(tview_func, tv);- return (bam_lplbuf_t*)tv;-}--void bam_lplbuf_destroy(bam_lplbuf_t *tv)-{- freenode_t *p, *q;- free(tv->cur_level); free(tv->pre_level);- bam_plbuf_destroy(tv->plbuf);- free(tv->aux);- for (p = tv->head; p->next;) {- q = p->next;- mp_free(tv->mp, p); p = q;- }- mp_free(tv->mp, p);- assert(tv->mp->cnt == 0);- mp_destroy(tv->mp);- free(tv);-}--int bam_lplbuf_push(const bam1_t *b, bam_lplbuf_t *tv)-{- return bam_plbuf_push(b, tv->plbuf);-}
− samtools-0.1.13/bam_maqcns.c
@@ -1,626 +0,0 @@-#include <math.h>-#include <assert.h>-#include "bam.h"-#include "bam_maqcns.h"-#include "ksort.h"-#include "errmod.h"-#include "kaln.h"-KSORT_INIT_GENERIC(uint32_t)--#define INDEL_WINDOW_SIZE 50-#define INDEL_EXT_DEP 0.9--typedef struct __bmc_aux_t {- int max;- uint32_t *info;- uint16_t *info16;- errmod_t *em;-} bmc_aux_t;--typedef struct {- float esum[4], fsum[4];- uint32_t c[4];-} glf_call_aux_t;--/*- P(<b1,b2>) = \theta \sum_{i=1}^{N-1} 1/i- P(D|<b1,b2>) = \sum_{k=1}^{N-1} p_k 1/2 [(k/N)^n_2(1-k/N)^n_1 + (k/N)^n1(1-k/N)^n_2]- p_k = 1/k / \sum_{i=1}^{N-1} 1/i- */-static void cal_het(bam_maqcns_t *aa)-{- int k, n1, n2;- double sum_harmo; // harmonic sum- double poly_rate;-- free(aa->lhet);- aa->lhet = (double*)calloc(256 * 256, sizeof(double));- sum_harmo = 0.0;- for (k = 1; k <= aa->n_hap - 1; ++k)- sum_harmo += 1.0 / k;- for (n1 = 0; n1 < 256; ++n1) {- for (n2 = 0; n2 < 256; ++n2) {- long double sum = 0.0;- double lC = aa->errmod == BAM_ERRMOD_SOAP? 0 : lgamma(n1+n2+1) - lgamma(n1+1) - lgamma(n2+1);- for (k = 1; k <= aa->n_hap - 1; ++k) {- double pk = 1.0 / k / sum_harmo;- double log1 = log((double)k/aa->n_hap);- double log2 = log(1.0 - (double)k/aa->n_hap);- sum += pk * 0.5 * (expl(log1*n2) * expl(log2*n1) + expl(log1*n1) * expl(log2*n2));- }- aa->lhet[n1<<8|n2] = lC + logl(sum);- }- }- poly_rate = aa->het_rate * sum_harmo;- aa->q_r = -4.343 * log(2.0 * poly_rate / (1.0 - poly_rate));-}--/** initialize the helper structure */-static void cal_coef(bam_maqcns_t *aa)-{- int k, n, q;- long double sum_a[257], b[256], q_c[256], tmp[256], fk2[256];- double *lC;-- if (aa->errmod == BAM_ERRMOD_MAQ2) return; // no need to do the following- // aa->lhet will be allocated and initialized - free(aa->fk); free(aa->coef);- aa->coef = 0;- aa->fk = (double*)calloc(256, sizeof(double));- aa->fk[0] = fk2[0] = 1.0;- for (n = 1; n != 256; ++n) {- aa->fk[n] = pow(aa->theta, n) * (1.0 - aa->eta) + aa->eta;- fk2[n] = aa->fk[n>>1]; // this is an approximation, assuming reads equally likely come from both strands- }- if (aa->errmod == BAM_ERRMOD_SOAP) return;- aa->coef = (double*)calloc(256*256*64, sizeof(double));- lC = (double*)calloc(256 * 256, sizeof(double));- for (n = 1; n != 256; ++n)- for (k = 1; k <= n; ++k)- lC[n<<8|k] = lgamma(n+1) - lgamma(k+1) - lgamma(n-k+1);- for (q = 1; q != 64; ++q) {- double e = pow(10.0, -q/10.0);- double le = log(e);- double le1 = log(1.0-e);- for (n = 1; n != 256; ++n) {- double *coef = aa->coef + (q<<16|n<<8);- sum_a[n+1] = 0.0;- for (k = n; k >= 0; --k) { // a_k = \sum_{i=k}^n C^n_k \epsilon^k (1-\epsilon)^{n-k}- sum_a[k] = sum_a[k+1] + expl(lC[n<<8|k] + k*le + (n-k)*le1);- b[k] = sum_a[k+1] / sum_a[k];- if (b[k] > 0.99) b[k] = 0.99;- }- for (k = 0; k != n; ++k) // log(\bar\beta_{nk}(\bar\epsilon)^{f_k})- q_c[k] = -4.343 * fk2[k] * logl(b[k] / e);- for (k = 1; k != n; ++k) q_c[k] += q_c[k-1]; // \prod_{i=0}^k c_i- for (k = 0; k <= n; ++k) { // powl() in 64-bit mode seems broken on my Mac OS X 10.4.9- tmp[k] = -4.343 * logl(1.0 - expl(fk2[k] * logl(b[k])));- coef[k] = (k? q_c[k-1] : 0) + tmp[k]; // this is the final c_{nk}- }- }- }- free(lC);-}--bam_maqcns_t *bam_maqcns_init()-{- bam_maqcns_t *bm;- bm = (bam_maqcns_t*)calloc(1, sizeof(bam_maqcns_t));- bm->aux = (bmc_aux_t*)calloc(1, sizeof(bmc_aux_t));- bm->het_rate = 0.001;- bm->theta = 0.83f;- bm->n_hap = 2;- bm->eta = 0.03;- bm->cap_mapQ = 60;- bm->min_baseQ = 13;- return bm;-}--void bam_maqcns_prepare(bam_maqcns_t *bm)-{- if (bm->errmod == BAM_ERRMOD_MAQ2) bm->aux->em = errmod_init(1. - bm->theta);- cal_coef(bm); cal_het(bm);-}--void bam_maqcns_destroy(bam_maqcns_t *bm)-{- if (bm == 0) return;- free(bm->lhet); free(bm->fk); free(bm->coef); free(bm->aux->info); free(bm->aux->info16);- if (bm->aux->em) errmod_destroy(bm->aux->em);- free(bm->aux); free(bm);-}--glf1_t *bam_maqcns_glfgen(int _n, const bam_pileup1_t *pl, uint8_t ref_base, bam_maqcns_t *bm)-{- glf_call_aux_t *b = 0;- int i, j, k, w[8], c, n;- glf1_t *g = (glf1_t*)calloc(1, sizeof(glf1_t));- float p[16], min_p = 1e30;- uint64_t rms;-- g->ref_base = ref_base;- if (_n == 0) return g;-- // construct aux array- if (bm->aux->max < _n) {- bm->aux->max = _n;- kroundup32(bm->aux->max);- bm->aux->info = (uint32_t*)realloc(bm->aux->info, 4 * bm->aux->max);- bm->aux->info16 = (uint16_t*)realloc(bm->aux->info16, 2 * bm->aux->max);- }- for (i = n = 0, rms = 0; i < _n; ++i) {- const bam_pileup1_t *p = pl + i;- uint32_t q, x = 0, qq;- uint16_t y = 0;- if (p->is_del || p->is_refskip || (p->b->core.flag&BAM_FUNMAP)) continue;- q = (uint32_t)bam1_qual(p->b)[p->qpos];- if (q < bm->min_baseQ) continue;- x |= (uint32_t)bam1_strand(p->b) << 18 | q << 8 | p->b->core.qual;- y |= bam1_strand(p->b)<<4;- if (p->b->core.qual < q) q = p->b->core.qual;- c = p->b->core.qual < bm->cap_mapQ? p->b->core.qual : bm->cap_mapQ;- rms += c * c;- x |= q << 24;- y |= q << 5;- qq = bam1_seqi(bam1_seq(p->b), p->qpos);- q = bam_nt16_nt4_table[qq? qq : ref_base];- if (!p->is_del && !p->is_refskip && q < 4) x |= 1 << 21 | q << 16, y |= q;- bm->aux->info16[n] = y;- bm->aux->info[n++] = x;- }- rms = (uint8_t)(sqrt((double)rms / n) + .499);- if (bm->errmod == BAM_ERRMOD_MAQ2) {- errmod_cal(bm->aux->em, n, 4, bm->aux->info16, p);- goto goto_glf;- }- ks_introsort(uint32_t, n, bm->aux->info);- // generate esum and fsum- b = (glf_call_aux_t*)calloc(1, sizeof(glf_call_aux_t));- for (k = 0; k != 8; ++k) w[k] = 0;- for (j = n - 1; j >= 0; --j) { // calculate esum and fsum- uint32_t info = bm->aux->info[j];- if (info>>24 < 4 && (info>>8&0x3f) != 0) info = 4<<24 | (info&0xffffff);- k = info>>16&7;- if (info>>24 > 0) {- b->esum[k&3] += bm->fk[w[k]] * (info>>24);- b->fsum[k&3] += bm->fk[w[k]];- if (w[k] < 0xff) ++w[k];- ++b->c[k&3];- }- }- // rescale ->c[]- for (j = c = 0; j != 4; ++j) c += b->c[j];- if (c > 255) {- for (j = 0; j != 4; ++j) b->c[j] = (int)(254.0 * b->c[j] / c + 0.5);- for (j = c = 0; j != 4; ++j) c += b->c[j];- }- if (bm->errmod == BAM_ERRMOD_MAQ) {- // generate likelihood- for (j = 0; j != 4; ++j) {- // homozygous- float tmp1, tmp3;- int tmp2, bar_e;- for (k = 0, tmp1 = tmp3 = 0.0, tmp2 = 0; k != 4; ++k) {- if (j == k) continue;- tmp1 += b->esum[k]; tmp2 += b->c[k]; tmp3 += b->fsum[k];- }- if (tmp2) {- bar_e = (int)(tmp1 / tmp3 + 0.5);- if (bar_e < 4) bar_e = 4; // should not happen- if (bar_e > 63) bar_e = 63;- p[j<<2|j] = tmp1 + bm->coef[bar_e<<16|c<<8|tmp2];- } else p[j<<2|j] = 0.0; // all the bases are j- // heterozygous- for (k = j + 1; k < 4; ++k) {- for (i = 0, tmp2 = 0, tmp1 = tmp3 = 0.0; i != 4; ++i) {- if (i == j || i == k) continue;- tmp1 += b->esum[i]; tmp2 += b->c[i]; tmp3 += b->fsum[i];- }- if (tmp2) {- bar_e = (int)(tmp1 / tmp3 + 0.5);- if (bar_e < 4) bar_e = 4;- if (bar_e > 63) bar_e = 63;- p[j<<2|k] = p[k<<2|j] = -4.343 * bm->lhet[b->c[j]<<8|b->c[k]] + tmp1 + bm->coef[bar_e<<16|c<<8|tmp2];- } else p[j<<2|k] = p[k<<2|j] = -4.343 * bm->lhet[b->c[j]<<8|b->c[k]]; // all the bases are either j or k- }- //- for (k = 0; k != 4; ++k)- if (p[j<<2|k] < 0.0) p[j<<2|k] = 0.0;- }-- { // fix p[k<<2|k]- float max1, max2, min1, min2;- int max_k, min_k;- max_k = min_k = -1;- max1 = max2 = -1.0; min1 = min2 = 1e30;- for (k = 0; k < 4; ++k) {- if (b->esum[k] > max1) {- max2 = max1; max1 = b->esum[k]; max_k = k;- } else if (b->esum[k] > max2) max2 = b->esum[k];- }- for (k = 0; k < 4; ++k) {- if (p[k<<2|k] < min1) {- min2 = min1; min1 = p[k<<2|k]; min_k = k;- } else if (p[k<<2|k] < min2) min2 = p[k<<2|k];- }- if (max1 > max2 && (min_k != max_k || min1 + 1.0 > min2))- p[max_k<<2|max_k] = min1 > 1.0? min1 - 1.0 : 0.0;- }- } else if (bm->errmod == BAM_ERRMOD_SOAP) { // apply the SOAP model- // generate likelihood- for (j = 0; j != 4; ++j) {- float tmp;- // homozygous- for (k = 0, tmp = 0.0; k != 4; ++k)- if (j != k) tmp += b->esum[k];- p[j<<2|j] = tmp;- // heterozygous- for (k = j + 1; k < 4; ++k) {- for (i = 0, tmp = 0.0; i != 4; ++i)- if (i != j && i != k) tmp += b->esum[i];- p[j<<2|k] = p[k<<2|j] = -4.343 * bm->lhet[b->c[j]<<8|b->c[k]] + tmp;- }- }- }--goto_glf:- // convert necessary information to glf1_t- g->ref_base = ref_base; g->max_mapQ = rms;- g->depth = n > 16777215? 16777215 : n;- for (j = 0; j != 4; ++j)- for (k = j; k < 4; ++k)- if (p[j<<2|k] < min_p) min_p = p[j<<2|k];- g->min_lk = min_p > 255.0? 255 : (int)(min_p + 0.5);- for (j = c = 0; j != 4; ++j)- for (k = j; k < 4; ++k)- g->lk[c++] = p[j<<2|k]-min_p > 255.0? 255 : (int)(p[j<<2|k]-min_p + 0.5);-- free(b);- return g;-}--uint32_t glf2cns(const glf1_t *g, int q_r)-{- int i, j, k, p[10], ref4;- uint32_t x = 0;- ref4 = bam_nt16_nt4_table[g->ref_base];- for (i = k = 0; i < 4; ++i)- for (j = i; j < 4; ++j) {- int prior = (i == ref4 && j == ref4? 0 : i == ref4 || j == ref4? q_r : q_r + 3);- p[k] = (g->lk[k] + prior)<<4 | i<<2 | j;- ++k;- }- for (i = 1; i < 10; ++i) // insertion sort- for (j = i; j > 0 && p[j] < p[j-1]; --j)- k = p[j], p[j] = p[j-1], p[j-1] = k;- x = (1u<<(p[0]&3) | 1u<<(p[0]>>2&3)) << 28; // the best genotype- x |= (uint32_t)g->max_mapQ << 16; // rms mapQ- x |= ((p[1]>>4) - (p[0]>>4) < 256? (p[1]>>4) - (p[0]>>4) : 255) << 8; // consensus Q- for (k = 0; k < 10; ++k)- if ((p[k]&0xf) == (ref4<<2|ref4)) break;- if (k == 10) k = 9;- x |= (p[k]>>4) - (p[0]>>4) < 256? (p[k]>>4) - (p[0]>>4) : 255; // snp Q- return x;-}--uint32_t bam_maqcns_call(int n, const bam_pileup1_t *pl, bam_maqcns_t *bm)-{- glf1_t *g;- uint32_t x;- if (n) {- g = bam_maqcns_glfgen(n, pl, 0xf, bm);- x = g->depth == 0? (0xfU<<28 | 0xfU<<24) : glf2cns(g, (int)(bm->q_r + 0.5));- free(g);- } else x = 0xfU<<28 | 0xfU<<24;- return x;-}--/************** *****************/--bam_maqindel_opt_t *bam_maqindel_opt_init()-{- bam_maqindel_opt_t *mi = (bam_maqindel_opt_t*)calloc(1, sizeof(bam_maqindel_opt_t));- mi->q_indel = 40;- mi->r_indel = 0.00015;- mi->r_snp = 0.001;- //- mi->mm_penalty = 3;- mi->indel_err = 4;- mi->ambi_thres = 10;- return mi;-}--void bam_maqindel_ret_destroy(bam_maqindel_ret_t *mir)-{- if (mir == 0) return;- free(mir->s[0]); free(mir->s[1]); free(mir);-}--int bam_tpos2qpos(const bam1_core_t *c, const uint32_t *cigar, int32_t tpos, int is_left, int32_t *_tpos)-{- int k, x = c->pos, y = 0, last_y = 0;- *_tpos = c->pos;- for (k = 0; k < c->n_cigar; ++k) {- int op = cigar[k] & BAM_CIGAR_MASK;- int l = cigar[k] >> BAM_CIGAR_SHIFT;- if (op == BAM_CMATCH) {- if (c->pos > tpos) return y;- if (x + l > tpos) {- *_tpos = tpos;- return y + (tpos - x);- }- x += l; y += l;- last_y = y;- } else if (op == BAM_CINS || op == BAM_CSOFT_CLIP) y += l;- else if (op == BAM_CDEL || op == BAM_CREF_SKIP) {- if (x + l > tpos) {- *_tpos = is_left? x : x + l;- return y;- }- x += l;- }- }- *_tpos = x;- return last_y;-}--#define MINUS_CONST 0x10000000--bam_maqindel_ret_t *bam_maqindel(int n, int pos, const bam_maqindel_opt_t *mi, const bam_pileup1_t *pl, const char *ref,- int _n_types, int *_types)-{- int i, j, n_types, *types, left, right, max_rd_len = 0;- bam_maqindel_ret_t *ret = 0;- // if there is no proposed indel, check if there is an indel from the alignment- if (_n_types == 0) {- for (i = 0; i < n; ++i) {- const bam_pileup1_t *p = pl + i;- if (!(p->b->core.flag&BAM_FUNMAP) && p->indel != 0) break;- }- if (i == n) return 0; // no indel- }- { // calculate how many types of indels are available (set n_types and types)- int m;- uint32_t *aux;- aux = (uint32_t*)calloc(n + _n_types + 1, 4);- m = 0;- aux[m++] = MINUS_CONST; // zero indel is always a type- for (i = 0; i < n; ++i) {- const bam_pileup1_t *p = pl + i;- if (!(p->b->core.flag&BAM_FUNMAP) && p->indel != 0)- aux[m++] = MINUS_CONST + p->indel;- j = bam_cigar2qlen(&p->b->core, bam1_cigar(p->b));- if (j > max_rd_len) max_rd_len = j;- }- if (_n_types) // then also add this to aux[]- for (i = 0; i < _n_types; ++i)- if (_types[i]) aux[m++] = MINUS_CONST + _types[i];- ks_introsort(uint32_t, m, aux);- // squeeze out identical types- for (i = 1, n_types = 1; i < m; ++i)- if (aux[i] != aux[i-1]) ++n_types;- types = (int*)calloc(n_types, sizeof(int));- j = 0;- types[j++] = aux[0] - MINUS_CONST; - for (i = 1; i < m; ++i) {- if (aux[i] != aux[i-1])- types[j++] = aux[i] - MINUS_CONST;- }- free(aux);- }- { // calculate left and right boundary- left = pos > INDEL_WINDOW_SIZE? pos - INDEL_WINDOW_SIZE : 0;- right = pos + INDEL_WINDOW_SIZE;- if (types[0] < 0) right -= types[0];- // in case the alignments stand out the reference- for (i = pos; i < right; ++i)- if (ref[i] == 0) break;- right = i;- }- { // the core part- char *ref2, *rs, *inscns = 0;- int qr_snp, k, l, *score, *pscore, max_ins = types[n_types-1];- qr_snp = (int)(-4.343 * log(mi->r_snp) + .499);- if (max_ins > 0) { // get the consensus of inserted sequences- int *inscns_aux = (int*)calloc(4 * n_types * max_ins, sizeof(int));- // count occurrences- for (i = 0; i < n_types; ++i) {- if (types[i] <= 0) continue; // not insertion- for (j = 0; j < n; ++j) {- const bam_pileup1_t *p = pl + j;- if (!(p->b->core.flag&BAM_FUNMAP) && p->indel == types[i]) {- for (k = 1; k <= p->indel; ++k) {- int c = bam_nt16_nt4_table[bam1_seqi(bam1_seq(p->b), p->qpos + k)];- if (c < 4) ++inscns_aux[i*max_ins*4 + (k-1)*4 + c];- }- }- }- }- // construct the consensus of inserted sequence- inscns = (char*)calloc(n_types * max_ins, sizeof(char));- for (i = 0; i < n_types; ++i) {- for (j = 0; j < types[i]; ++j) {- int max = 0, max_k = -1, *ia = inscns_aux + i*max_ins*4 + j*4;- for (k = 0; k < 4; ++k) {- if (ia[k] > max) {- max = ia[k];- max_k = k;- }- }- inscns[i*max_ins + j] = max? 1<<max_k : 15;- }- }- free(inscns_aux);- }- // calculate score- ref2 = (char*)calloc(right - left + types[n_types-1] + 2, 1);- rs = (char*)calloc(right - left + max_rd_len + types[n_types-1] + 2, 1);- score = (int*)calloc(n_types * n, sizeof(int));- pscore = (int*)calloc(n_types * n, sizeof(int));- for (i = 0; i < n_types; ++i) {- ka_param_t ap = ka_param_blast;- ap.band_width = 2 * types[n_types - 1] + 2;- ap.gap_end_ext = 0;- // write ref2- for (k = 0, j = left; j <= pos; ++j)- ref2[k++] = bam_nt16_nt4_table[bam_nt16_table[(int)ref[j]]];- if (types[i] <= 0) j += -types[i];- else for (l = 0; l < types[i]; ++l)- ref2[k++] = bam_nt16_nt4_table[(int)inscns[i*max_ins + l]];- if (types[0] < 0) { // mask deleted sequences- int jj, tmp = types[i] >= 0? -types[0] : -types[0] + types[i];- for (jj = 0; jj < tmp && j < right && ref[j]; ++jj, ++j)- ref2[k++] = 4;- }- for (; j < right && ref[j]; ++j)- ref2[k++] = bam_nt16_nt4_table[bam_nt16_table[(int)ref[j]]];- if (j < right) right = j;- // calculate score for each read- for (j = 0; j < n; ++j) {- const bam_pileup1_t *p = pl + j;- int qbeg, qend, tbeg, tend;- if (p->b->core.flag & BAM_FUNMAP) continue;- qbeg = bam_tpos2qpos(&p->b->core, bam1_cigar(p->b), left, 0, &tbeg);- qend = bam_tpos2qpos(&p->b->core, bam1_cigar(p->b), right, 1, &tend);- assert(tbeg >= left);- for (l = qbeg; l < qend; ++l)- rs[l - qbeg] = bam_nt16_nt4_table[bam1_seqi(bam1_seq(p->b), l)];- {- int x, y, n_acigar, ps;- uint32_t *acigar;- ps = 0;- if (tend - tbeg + types[i] <= 0) {- score[i*n+j] = -(1<<20);- pscore[i*n+j] = 1<<20;- continue;- }- acigar = ka_global_core((uint8_t*)ref2 + tbeg - left, tend - tbeg + types[i], (uint8_t*)rs, qend - qbeg, &ap, &score[i*n+j], &n_acigar);- x = tbeg - left; y = 0;- for (l = 0; l < n_acigar; ++l) {- int op = acigar[l]&0xf;- int len = acigar[l]>>4;- if (op == BAM_CMATCH) {- int k;- for (k = 0; k < len; ++k)- if (ref2[x+k] != rs[y+k] && ref2[x+k] < 4)- ps += bam1_qual(p->b)[y+k] < qr_snp? bam1_qual(p->b)[y+k] : qr_snp;- x += len; y += len;- } else if (op == BAM_CINS || op == BAM_CSOFT_CLIP) {- if (op == BAM_CINS && l > 0 && l < n_acigar - 1) ps += mi->q_indel * len;- y += len;- } else if (op == BAM_CDEL) {- if (l > 0 && l < n_acigar - 1) ps += mi->q_indel * len;- x += len;- }- }- pscore[i*n+j] = ps;- /*if (1) { // for debugging only- fprintf(stderr, "id=%d, pos=%d, type=%d, j=%d, score=%d, psore=%d, %d, %d, %d, %d, %d, ",- j, pos+1, types[i], j, score[i*n+j], pscore[i*n+j], tbeg, tend, qbeg, qend, mi->q_indel);- for (l = 0; l < n_acigar; ++l) fprintf(stderr, "%d%c", acigar[l]>>4, "MIDS"[acigar[l]&0xf]);- fprintf(stderr, "\n");- for (l = 0; l < tend - tbeg + types[i]; ++l) fputc("ACGTN"[ref2[l+tbeg-left]], stderr);- fputc('\n', stderr);- for (l = 0; l < qend - qbeg; ++l) fputc("ACGTN"[rs[l]], stderr);- fputc('\n', stderr);- }*/- free(acigar);- }- }- }- { // get final result- int *sum, max1, max2, max1_i, max2_i;- // pick up the best two score- sum = (int*)calloc(n_types, sizeof(int));- for (i = 0; i < n_types; ++i)- for (j = 0; j < n; ++j)- sum[i] += -pscore[i*n+j];- max1 = max2 = -0x7fffffff; max1_i = max2_i = -1;- for (i = 0; i < n_types; ++i) {- if (sum[i] > max1) {- max2 = max1; max2_i = max1_i; max1 = sum[i]; max1_i = i;- } else if (sum[i] > max2) {- max2 = sum[i]; max2_i = i;- }- }- free(sum);- // write ret- ret = (bam_maqindel_ret_t*)calloc(1, sizeof(bam_maqindel_ret_t));- ret->indel1 = types[max1_i]; ret->indel2 = types[max2_i];- ret->s[0] = (char*)calloc(abs(ret->indel1) + 2, 1);- ret->s[1] = (char*)calloc(abs(ret->indel2) + 2, 1);- // write indel sequence- if (ret->indel1 > 0) {- ret->s[0][0] = '+';- for (k = 0; k < ret->indel1; ++k)- ret->s[0][k+1] = bam_nt16_rev_table[(int)inscns[max1_i*max_ins + k]];- } else if (ret->indel1 < 0) {- ret->s[0][0] = '-';- for (k = 0; k < -ret->indel1 && ref[pos + k + 1]; ++k)- ret->s[0][k+1] = ref[pos + k + 1];- } else ret->s[0][0] = '*';- if (ret->indel2 > 0) {- ret->s[1][0] = '+';- for (k = 0; k < ret->indel2; ++k)- ret->s[1][k+1] = bam_nt16_rev_table[(int)inscns[max2_i*max_ins + k]];- } else if (ret->indel2 < 0) {- ret->s[1][0] = '-';- for (k = 0; k < -ret->indel2 && ref[pos + k + 1]; ++k)- ret->s[1][k+1] = ref[pos + k + 1];- } else ret->s[1][0] = '*';- // write count- for (i = 0; i < n; ++i) {- const bam_pileup1_t *p = pl + i;- if (p->indel == ret->indel1) ++ret->cnt1;- else if (p->indel == ret->indel2) ++ret->cnt2;- else ++ret->cnt_anti;- }- { // write gl[]- int tmp, seq_err = 0;- double x = 1.0;- tmp = max1_i - max2_i;- if (tmp < 0) tmp = -tmp;- for (j = 0; j < tmp + 1; ++j) x *= INDEL_EXT_DEP;- seq_err = mi->q_indel * (1.0 - x) / (1.0 - INDEL_EXT_DEP);- ret->gl[0] = ret->gl[1] = 0;- for (j = 0; j < n; ++j) {- int s1 = pscore[max1_i*n + j], s2 = pscore[max2_i*n + j];- //fprintf(stderr, "id=%d, %d, %d, %d, %d, %d\n", j, pl[j].b->core.pos+1, types[max1_i], types[max2_i], s1, s2);- if (s1 > s2) ret->gl[0] += s1 - s2 < seq_err? s1 - s2 : seq_err;- else ret->gl[1] += s2 - s1 < seq_err? s2 - s1 : seq_err;- }- }- // write cnt_ref and cnt_ambi- if (max1_i != 0 && max2_i != 0) {- for (j = 0; j < n; ++j) {- int diff1 = score[j] - score[max1_i * n + j];- int diff2 = score[j] - score[max2_i * n + j];- if (diff1 > 0 && diff2 > 0) ++ret->cnt_ref;- else if (diff1 == 0 || diff2 == 0) ++ret->cnt_ambi;- }- }- }- free(score); free(pscore); free(ref2); free(rs); free(inscns);- }- { // call genotype- int q[3], qr_indel = (int)(-4.343 * log(mi->r_indel) + 0.5);- int min1, min2, min1_i;- q[0] = ret->gl[0] + (ret->s[0][0] != '*'? 0 : 0) * qr_indel;- q[1] = ret->gl[1] + (ret->s[1][0] != '*'? 0 : 0) * qr_indel;- q[2] = n * 3 + (ret->s[0][0] == '*' || ret->s[1][0] == '*'? 1 : 1) * qr_indel;- min1 = min2 = 0x7fffffff; min1_i = -1;- for (i = 0; i < 3; ++i) {- if (q[i] < min1) {- min2 = min1; min1 = q[i]; min1_i = i;- } else if (q[i] < min2) min2 = q[i];- }- ret->gt = min1_i;- ret->q_cns = min2 - min1;- // set q_ref- if (ret->gt < 2) ret->q_ref = (ret->s[ret->gt][0] == '*')? 0 : q[1-ret->gt] - q[ret->gt] - qr_indel - 3;- else ret->q_ref = (ret->s[0][0] == '*')? q[0] - q[2] : q[1] - q[2];- if (ret->q_ref < 0) ret->q_ref = 0;- }- free(types);- return ret;-}
− samtools-0.1.13/bam_maqcns.h
@@ -1,61 +0,0 @@-#ifndef BAM_MAQCNS_H-#define BAM_MAQCNS_H--#include "glf.h"--#define BAM_ERRMOD_MAQ2 0-#define BAM_ERRMOD_MAQ 1-#define BAM_ERRMOD_SOAP 2--struct __bmc_aux_t;--typedef struct {- float het_rate, theta;- int n_hap, cap_mapQ, errmod, min_baseQ;-- float eta, q_r;- double *fk, *coef;- double *lhet;- struct __bmc_aux_t *aux;-} bam_maqcns_t;--typedef struct {- int q_indel; // indel sequencing error, phred scaled- float r_indel; // indel prior- float r_snp; // snp prior- // hidden parameters, unchangeable from command line- int mm_penalty, indel_err, ambi_thres;-} bam_maqindel_opt_t;--typedef struct {- int indel1, indel2;- int cnt1, cnt2, cnt_anti;- int cnt_ref, cnt_ambi;- char *s[2];- //- int gt, gl[2];- int q_cns, q_ref;-} bam_maqindel_ret_t;--#ifdef __cplusplus-extern "C" {-#endif-- bam_maqcns_t *bam_maqcns_init();- void bam_maqcns_prepare(bam_maqcns_t *bm);- void bam_maqcns_destroy(bam_maqcns_t *bm);- glf1_t *bam_maqcns_glfgen(int n, const bam_pileup1_t *pl, uint8_t ref_base, bam_maqcns_t *bm);- uint32_t bam_maqcns_call(int n, const bam_pileup1_t *pl, bam_maqcns_t *bm);- // return: cns<<28 | cns2<<24 | mapQ<<16 | cnsQ<<8 | cnsQ2- uint32_t glf2cns(const glf1_t *g, int q_r);-- bam_maqindel_opt_t *bam_maqindel_opt_init();- bam_maqindel_ret_t *bam_maqindel(int n, int pos, const bam_maqindel_opt_t *mi, const bam_pileup1_t *pl, const char *ref,- int _n_types, int *_types);- void bam_maqindel_ret_destroy(bam_maqindel_ret_t*);--#ifdef __cplusplus-}-#endif--#endif
− samtools-0.1.13/bam_md.c
@@ -1,357 +0,0 @@-#include <unistd.h>-#include <assert.h>-#include <string.h>-#include <ctype.h>-#include <math.h>-#include "faidx.h"-#include "sam.h"-#include "kstring.h"-#include "kaln.h"-#include "kprobaln.h"--char bam_nt16_nt4_table[] = { 4, 0, 1, 4, 2, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4 };--void bam_fillmd1_core(bam1_t *b, char *ref, int is_equal, int max_nm)-{- uint8_t *seq = bam1_seq(b);- uint32_t *cigar = bam1_cigar(b);- bam1_core_t *c = &b->core;- int i, x, y, u = 0;- kstring_t *str;- uint8_t *old_md, *old_nm;- int32_t old_nm_i = -1, nm = 0;-- str = (kstring_t*)calloc(1, sizeof(kstring_t));- for (i = y = 0, x = c->pos; i < c->n_cigar; ++i) {- int j, l = cigar[i]>>4, op = cigar[i]&0xf;- if (op == BAM_CMATCH) {- for (j = 0; j < l; ++j) {- int z = y + j;- int c1 = bam1_seqi(seq, z), c2 = bam_nt16_table[(int)ref[x+j]];- if (ref[x+j] == 0) break; // out of boundary- if ((c1 == c2 && c1 != 15 && c2 != 15) || c1 == 0) { // a match- if (is_equal) seq[z/2] &= (z&1)? 0xf0 : 0x0f;- ++u;- } else {- ksprintf(str, "%d", u);- kputc(ref[x+j], str);- u = 0; ++nm;- }- }- if (j < l) break;- x += l; y += l;- } else if (op == BAM_CDEL) {- ksprintf(str, "%d", u);- kputc('^', str);- for (j = 0; j < l; ++j) {- if (ref[x+j] == 0) break;- kputc(ref[x+j], str);- }- u = 0;- if (j < l) break;- x += l; nm += l;- } else if (op == BAM_CINS || op == BAM_CSOFT_CLIP) {- y += l;- if (op == BAM_CINS) nm += l;- } else if (op == BAM_CREF_SKIP) {- x += l;- }- }- ksprintf(str, "%d", u);- // apply max_nm- if (max_nm > 0 && nm >= max_nm) {- for (i = y = 0, x = c->pos; i < c->n_cigar; ++i) {- int j, l = cigar[i]>>4, op = cigar[i]&0xf;- if (op == BAM_CMATCH) {- for (j = 0; j < l; ++j) {- int z = y + j;- int c1 = bam1_seqi(seq, z), c2 = bam_nt16_table[(int)ref[x+j]];- if (ref[x+j] == 0) break; // out of boundary- if ((c1 == c2 && c1 != 15 && c2 != 15) || c1 == 0) { // a match- seq[z/2] |= (z&1)? 0x0f : 0xf0;- bam1_qual(b)[z] = 0;- }- }- if (j < l) break;- x += l; y += l;- } else if (op == BAM_CDEL || op == BAM_CREF_SKIP) x += l;- else if (op == BAM_CINS || op == BAM_CSOFT_CLIP) y += l;- }- }- // update NM- old_nm = bam_aux_get(b, "NM");- if (c->flag & BAM_FUNMAP) return;- if (old_nm) old_nm_i = bam_aux2i(old_nm);- if (!old_nm) bam_aux_append(b, "NM", 'i', 4, (uint8_t*)&nm);- else if (nm != old_nm_i) {- fprintf(stderr, "[bam_fillmd1] different NM for read '%s': %d -> %d\n", bam1_qname(b), old_nm_i, nm);- bam_aux_del(b, old_nm);- bam_aux_append(b, "NM", 'i', 4, (uint8_t*)&nm);- }- // update MD- old_md = bam_aux_get(b, "MD");- if (!old_md) bam_aux_append(b, "MD", 'Z', str->l + 1, (uint8_t*)str->s);- else {- int is_diff = 0;- if (strlen((char*)old_md+1) == str->l) {- for (i = 0; i < str->l; ++i)- if (toupper(old_md[i+1]) != toupper(str->s[i]))- break;- if (i < str->l) is_diff = 1;- } else is_diff = 1;- if (is_diff) {- fprintf(stderr, "[bam_fillmd1] different MD for read '%s': '%s' -> '%s'\n", bam1_qname(b), old_md+1, str->s);- bam_aux_del(b, old_md);- bam_aux_append(b, "MD", 'Z', str->l + 1, (uint8_t*)str->s);- }- }- free(str->s); free(str);-}--void bam_fillmd1(bam1_t *b, char *ref, int is_equal)-{- bam_fillmd1_core(b, ref, is_equal, 0);-}--int bam_cap_mapQ(bam1_t *b, char *ref, int thres)-{- uint8_t *seq = bam1_seq(b), *qual = bam1_qual(b);- uint32_t *cigar = bam1_cigar(b);- bam1_core_t *c = &b->core;- int i, x, y, mm, q, len, clip_l, clip_q;- double t;- if (thres < 0) thres = 40; // set the default- mm = q = len = clip_l = clip_q = 0;- for (i = y = 0, x = c->pos; i < c->n_cigar; ++i) {- int j, l = cigar[i]>>4, op = cigar[i]&0xf;- if (op == BAM_CMATCH) {- for (j = 0; j < l; ++j) {- int z = y + j;- int c1 = bam1_seqi(seq, z), c2 = bam_nt16_table[(int)ref[x+j]];- if (ref[x+j] == 0) break; // out of boundary- if (c2 != 15 && c1 != 15 && qual[z] >= 13) { // not ambiguous- ++len;- if (c1 && c1 != c2 && qual[z] >= 13) { // mismatch- ++mm;- q += qual[z] > 33? 33 : qual[z];- }- }- }- if (j < l) break;- x += l; y += l; len += l;- } else if (op == BAM_CDEL) {- for (j = 0; j < l; ++j)- if (ref[x+j] == 0) break;- if (j < l) break;- x += l;- } else if (op == BAM_CSOFT_CLIP) {- for (j = 0; j < l; ++j) clip_q += qual[y+j];- clip_l += l;- y += l;- } else if (op == BAM_CHARD_CLIP) {- clip_q += 13 * l;- clip_l += l;- } else if (op == BAM_CINS) y += l;- else if (op == BAM_CREF_SKIP) x += l;- }- for (i = 0, t = 1; i < mm; ++i)- t *= (double)len / (i+1);- t = q - 4.343 * log(t) + clip_q / 5.;- if (t > thres) return -1;- if (t < 0) t = 0;- t = sqrt((thres - t) / thres) * thres;-// fprintf(stderr, "%s %lf %d\n", bam1_qname(b), t, q);- return (int)(t + .499);-}--int bam_prob_realn_core(bam1_t *b, const char *ref, int flag)-{- int k, i, bw, x, y, yb, ye, xb, xe, apply_baq = flag&1, extend_baq = flag>>1&1;- uint32_t *cigar = bam1_cigar(b);- bam1_core_t *c = &b->core;- kpa_par_t conf = kpa_par_def;- uint8_t *bq = 0, *zq = 0, *qual = bam1_qual(b);- if ((c->flag & BAM_FUNMAP) || b->core.l_qseq == 0) return -1; // do nothing- // test if BQ or ZQ is present- if ((bq = bam_aux_get(b, "BQ")) != 0) ++bq;- if ((zq = bam_aux_get(b, "ZQ")) != 0 && *zq == 'Z') ++zq;- if (bq && zq) { // remove the ZQ tag- bam_aux_del(b, zq-1);- zq = 0;- }- if (bq || zq) {- if ((apply_baq && zq) || (!apply_baq && bq)) return -3; // in both cases, do nothing- if (bq && apply_baq) { // then convert BQ to ZQ- for (i = 0; i < c->l_qseq; ++i)- qual[i] = qual[i] + 64 < bq[i]? 0 : qual[i] - ((int)bq[i] - 64);- *(bq - 3) = 'Z';- } else if (zq && !apply_baq) { // then convert ZQ to BQ- for (i = 0; i < c->l_qseq; ++i)- qual[i] += (int)zq[i] - 64;- *(zq - 3) = 'B';- }- return 0;- }- // find the start and end of the alignment - x = c->pos, y = 0, yb = ye = xb = xe = -1;- for (k = 0; k < c->n_cigar; ++k) {- int op, l;- op = cigar[k]&0xf; l = cigar[k]>>4;- if (op == BAM_CMATCH) {- if (yb < 0) yb = y;- if (xb < 0) xb = x;- ye = y + l; xe = x + l;- x += l; y += l;- } else if (op == BAM_CSOFT_CLIP || op == BAM_CINS) y += l;- else if (op == BAM_CDEL) x += l;- else if (op == BAM_CREF_SKIP) return -1; // do nothing if there is a reference skip- }- // set bandwidth and the start and the end- bw = 7;- if (abs((xe - xb) - (ye - yb)) > bw)- bw = abs((xe - xb) - (ye - yb)) + 3;- conf.bw = bw;- xb -= yb + bw/2; if (xb < 0) xb = 0;- xe += c->l_qseq - ye + bw/2;- if (xe - xb - c->l_qseq > bw)- xb += (xe - xb - c->l_qseq - bw) / 2, xe -= (xe - xb - c->l_qseq - bw) / 2;- { // glocal- uint8_t *s, *r, *q, *seq = bam1_seq(b), *bq;- int *state;- bq = calloc(c->l_qseq + 1, 1);- memcpy(bq, qual, c->l_qseq);- s = calloc(c->l_qseq, 1);- for (i = 0; i < c->l_qseq; ++i) s[i] = bam_nt16_nt4_table[bam1_seqi(seq, i)];- r = calloc(xe - xb, 1);- for (i = xb; i < xe; ++i) {- if (ref[i] == 0) { xe = i; break; }- r[i-xb] = bam_nt16_nt4_table[bam_nt16_table[(int)ref[i]]];- }- state = calloc(c->l_qseq, sizeof(int));- q = calloc(c->l_qseq, 1);- kpa_glocal(r, xe-xb, s, c->l_qseq, qual, &conf, state, q);- if (!extend_baq) { // in this block, bq[] is capped by base quality qual[]- for (k = 0, x = c->pos, y = 0; k < c->n_cigar; ++k) {- int op = cigar[k]&0xf, l = cigar[k]>>4;- if (op == BAM_CMATCH) {- for (i = y; i < y + l; ++i) {- if ((state[i]&3) != 0 || state[i]>>2 != x - xb + (i - y)) bq[i] = 0;- else bq[i] = bq[i] < q[i]? bq[i] : q[i];- }- x += l; y += l;- } else if (op == BAM_CSOFT_CLIP || op == BAM_CINS) y += l;- else if (op == BAM_CDEL) x += l;- }- for (i = 0; i < c->l_qseq; ++i) bq[i] = qual[i] - bq[i] + 64; // finalize BQ- } else { // in this block, bq[] is BAQ that can be larger than qual[] (different from the above!)- uint8_t *left, *rght;- left = calloc(c->l_qseq, 1); rght = calloc(c->l_qseq, 1);- for (k = 0, x = c->pos, y = 0; k < c->n_cigar; ++k) {- int op = cigar[k]&0xf, l = cigar[k]>>4;- if (op == BAM_CMATCH) {- for (i = y; i < y + l; ++i)- bq[i] = ((state[i]&3) != 0 || state[i]>>2 != x - xb + (i - y))? 0 : q[i];- for (left[y] = bq[y], i = y + 1; i < y + l; ++i)- left[i] = bq[i] > left[i-1]? bq[i] : left[i-1];- for (rght[y+l-1] = bq[y+l-1], i = y + l - 2; i >= y; --i)- rght[i] = bq[i] > rght[i+1]? bq[i] : rght[i+1];- for (i = y; i < y + l; ++i)- bq[i] = left[i] < rght[i]? left[i] : rght[i];- x += l; y += l;- } else if (op == BAM_CSOFT_CLIP || op == BAM_CINS) y += l;- else if (op == BAM_CDEL) x += l;- }- for (i = 0; i < c->l_qseq; ++i) bq[i] = 64 + (qual[i] <= bq[i]? 0 : qual[i] - bq[i]); // finalize BQ- free(left); free(rght);- }- if (apply_baq) {- for (i = 0; i < c->l_qseq; ++i) qual[i] -= bq[i] - 64; // modify qual- bam_aux_append(b, "ZQ", 'Z', c->l_qseq + 1, bq);- } else bam_aux_append(b, "BQ", 'Z', c->l_qseq + 1, bq);- free(bq); free(s); free(r); free(q); free(state);- }- return 0;-}--int bam_prob_realn(bam1_t *b, const char *ref)-{- return bam_prob_realn_core(b, ref, 1);-}--int bam_fillmd(int argc, char *argv[])-{- int c, is_equal, tid = -2, ret, len, is_bam_out, is_sam_in, is_uncompressed, max_nm, is_realn, capQ, baq_flag;- samfile_t *fp, *fpout = 0;- faidx_t *fai;- char *ref = 0, mode_w[8], mode_r[8];- bam1_t *b;-- is_equal = is_bam_out = is_sam_in = is_uncompressed = is_realn = max_nm = capQ = baq_flag = 0;- mode_w[0] = mode_r[0] = 0;- strcpy(mode_r, "r"); strcpy(mode_w, "w");- while ((c = getopt(argc, argv, "EreubSC:n:A")) >= 0) {- switch (c) {- case 'r': is_realn = 1; break;- case 'e': is_equal = 1; break;- case 'b': is_bam_out = 1; break;- case 'u': is_uncompressed = is_bam_out = 1; break;- case 'S': is_sam_in = 1; break;- case 'n': max_nm = atoi(optarg); break;- case 'C': capQ = atoi(optarg); break;- case 'A': baq_flag |= 1; break;- case 'E': baq_flag |= 2; break;- default: fprintf(stderr, "[bam_fillmd] unrecognized option '-%c'\n", c); return 1;- }- }- if (!is_sam_in) strcat(mode_r, "b");- if (is_bam_out) strcat(mode_w, "b");- else strcat(mode_w, "h");- if (is_uncompressed) strcat(mode_w, "u");- if (optind + 1 >= argc) {- fprintf(stderr, "\n");- fprintf(stderr, "Usage: samtools fillmd [-eubrS] <aln.bam> <ref.fasta>\n\n");- fprintf(stderr, "Options: -e change identical bases to '='\n");- fprintf(stderr, " -u uncompressed BAM output (for piping)\n");- fprintf(stderr, " -b compressed BAM output\n");- fprintf(stderr, " -S the input is SAM with header\n");- fprintf(stderr, " -A modify the quality string\n");- fprintf(stderr, " -r compute the BQ tag (without -A) or cap baseQ by BAQ (with -A)\n");- fprintf(stderr, " -E extended BAQ for better sensitivity but lower specificity\n\n");- return 1;- }- fp = samopen(argv[optind], mode_r, 0);- if (fp == 0) return 1;- if (is_sam_in && (fp->header == 0 || fp->header->n_targets == 0)) {- fprintf(stderr, "[bam_fillmd] input SAM does not have header. Abort!\n");- return 1;- }- fpout = samopen("-", mode_w, fp->header);- fai = fai_load(argv[optind+1]);-- b = bam_init1();- while ((ret = samread(fp, b)) >= 0) {- if (b->core.tid >= 0) {- if (tid != b->core.tid) {- free(ref);- ref = fai_fetch(fai, fp->header->target_name[b->core.tid], &len);- tid = b->core.tid;- if (ref == 0)- fprintf(stderr, "[bam_fillmd] fail to find sequence '%s' in the reference.\n",- fp->header->target_name[tid]);- }- if (is_realn) bam_prob_realn_core(b, ref, baq_flag);- if (capQ > 10) {- int q = bam_cap_mapQ(b, ref, capQ);- if (b->core.qual > q) b->core.qual = q;- }- if (ref) bam_fillmd1_core(b, ref, is_equal, max_nm);- }- samwrite(fpout, b);- }- bam_destroy1(b);-- free(ref);- fai_destroy(fai);- samclose(fp); samclose(fpout);- return 0;-}
− samtools-0.1.13/bam_pileup.c
@@ -1,437 +0,0 @@-#include <stdio.h>-#include <stdlib.h>-#include <ctype.h>-#include <assert.h>-#include "sam.h"--typedef struct {- int k, x, y, end;-} cstate_t;--static cstate_t g_cstate_null = { -1, 0, 0, 0 };--typedef struct __linkbuf_t {- bam1_t b;- uint32_t beg, end;- cstate_t s;- struct __linkbuf_t *next;-} lbnode_t;--/* --- BEGIN: Memory pool */--typedef struct {- int cnt, n, max;- lbnode_t **buf;-} mempool_t;--static mempool_t *mp_init()-{- mempool_t *mp;- mp = (mempool_t*)calloc(1, sizeof(mempool_t));- return mp;-}-static void mp_destroy(mempool_t *mp)-{- int k;- for (k = 0; k < mp->n; ++k) {- free(mp->buf[k]->b.data);- free(mp->buf[k]);- }- free(mp->buf);- free(mp);-}-static inline lbnode_t *mp_alloc(mempool_t *mp)-{- ++mp->cnt;- if (mp->n == 0) return (lbnode_t*)calloc(1, sizeof(lbnode_t));- else return mp->buf[--mp->n];-}-static inline void mp_free(mempool_t *mp, lbnode_t *p)-{- --mp->cnt; p->next = 0; // clear lbnode_t::next here- if (mp->n == mp->max) {- mp->max = mp->max? mp->max<<1 : 256;- mp->buf = (lbnode_t**)realloc(mp->buf, sizeof(lbnode_t*) * mp->max);- }- mp->buf[mp->n++] = p;-}--/* --- END: Memory pool */--/* --- BEGIN: Auxiliary functions */--/* s->k: the index of the CIGAR operator that has just been processed.- s->x: the reference coordinate of the start of s->k- s->y: the query coordiante of the start of s->k- */-static inline int resolve_cigar2(bam_pileup1_t *p, uint32_t pos, cstate_t *s)-{-#define _cop(c) ((c)&BAM_CIGAR_MASK)-#define _cln(c) ((c)>>BAM_CIGAR_SHIFT)-- bam1_t *b = p->b;- bam1_core_t *c = &b->core;- uint32_t *cigar = bam1_cigar(b);- int k, is_head = 0;- // determine the current CIGAR operation-// fprintf(stderr, "%s\tpos=%d\tend=%d\t(%d,%d,%d)\n", bam1_qname(b), pos, s->end, s->k, s->x, s->y);- if (s->k == -1) { // never processed- is_head = 1;- if (c->n_cigar == 1) { // just one operation, save a loop- if (_cop(cigar[0]) == BAM_CMATCH) s->k = 0, s->x = c->pos, s->y = 0;- } else { // find the first match or deletion- for (k = 0, s->x = c->pos, s->y = 0; k < c->n_cigar; ++k) {- int op = _cop(cigar[k]);- int l = _cln(cigar[k]);- if (op == BAM_CMATCH || op == BAM_CDEL) break;- else if (op == BAM_CREF_SKIP) s->x += l;- else if (op == BAM_CINS || op == BAM_CSOFT_CLIP) s->y += l;- }- assert(k < c->n_cigar);- s->k = k;- }- } else { // the read has been processed before- int op, l = _cln(cigar[s->k]);- if (pos - s->x >= l) { // jump to the next operation- assert(s->k < c->n_cigar); // otherwise a bug: this function should not be called in this case- op = _cop(cigar[s->k+1]);- if (op == BAM_CMATCH || op == BAM_CDEL || op == BAM_CREF_SKIP) { // jump to the next without a loop- if (_cop(cigar[s->k]) == BAM_CMATCH) s->y += l;- s->x += l;- ++s->k;- } else { // find the next M/D/N- if (_cop(cigar[s->k]) == BAM_CMATCH) s->y += l;- s->x += l;- for (k = s->k + 1; k < c->n_cigar; ++k) {- op = _cop(cigar[k]), l = _cln(cigar[k]);- if (op == BAM_CMATCH || op == BAM_CDEL || op == BAM_CREF_SKIP) break;- else if (op == BAM_CINS || op == BAM_CSOFT_CLIP) s->y += l;- }- s->k = k;- }- assert(s->k < c->n_cigar); // otherwise a bug- } // else, do nothing- }- { // collect pileup information- int op, l;- op = _cop(cigar[s->k]); l = _cln(cigar[s->k]);- p->is_del = p->indel = p->is_refskip = 0;- if (s->x + l - 1 == pos && s->k + 1 < c->n_cigar) { // peek the next operation- int op2 = _cop(cigar[s->k+1]);- int l2 = _cln(cigar[s->k+1]);- if (op2 == BAM_CDEL) p->indel = -(int)l2;- else if (op2 == BAM_CINS) p->indel = l2;- else if (op2 == BAM_CPAD && s->k + 2 < c->n_cigar) { // no working for adjacent padding- int l3 = 0;- for (k = s->k + 2; k < c->n_cigar; ++k) {- op2 = _cop(cigar[k]); l2 = _cln(cigar[k]);- if (op2 == BAM_CINS) l3 += l2;- else if (op2 == BAM_CDEL || op2 == BAM_CMATCH || op2 == BAM_CREF_SKIP) break;- }- if (l3 > 0) p->indel = l3;- }- }- if (op == BAM_CMATCH) {- p->qpos = s->y + (pos - s->x);- } else if (op == BAM_CDEL || op == BAM_CREF_SKIP) {- p->is_del = 1; p->qpos = s->y; // FIXME: distinguish D and N!!!!!- p->is_refskip = (op == BAM_CREF_SKIP);- } // cannot be other operations; otherwise a bug- p->is_head = (pos == c->pos); p->is_tail = (pos == s->end);- }- return 1;-}--/* --- END: Auxiliary functions */--/*******************- * pileup iterator *- *******************/--struct __bam_plp_t {- mempool_t *mp;- lbnode_t *head, *tail, *dummy;- int32_t tid, pos, max_tid, max_pos;- int is_eof, flag_mask, max_plp, error, maxcnt;- bam_pileup1_t *plp;- // for the "auto" interface only- bam1_t *b;- bam_plp_auto_f func;- void *data;-};--bam_plp_t bam_plp_init(bam_plp_auto_f func, void *data)-{- bam_plp_t iter;- iter = calloc(1, sizeof(struct __bam_plp_t));- iter->mp = mp_init();- iter->head = iter->tail = mp_alloc(iter->mp);- iter->dummy = mp_alloc(iter->mp);- iter->max_tid = iter->max_pos = -1;- iter->flag_mask = BAM_DEF_MASK;- iter->maxcnt = 8000;- if (func) {- iter->func = func;- iter->data = data;- iter->b = bam_init1();- }- return iter;-}--void bam_plp_destroy(bam_plp_t iter)-{- mp_free(iter->mp, iter->dummy);- mp_free(iter->mp, iter->head);- if (iter->mp->cnt != 0)- fprintf(stderr, "[bam_plp_destroy] memory leak: %d. Continue anyway.\n", iter->mp->cnt);- mp_destroy(iter->mp);- if (iter->b) bam_destroy1(iter->b);- free(iter->plp);- free(iter);-}--const bam_pileup1_t *bam_plp_next(bam_plp_t iter, int *_tid, int *_pos, int *_n_plp)-{- if (iter->error) { *_n_plp = -1; return 0; }- *_n_plp = 0;- if (iter->is_eof && iter->head->next == 0) return 0;- while (iter->is_eof || iter->max_tid > iter->tid || (iter->max_tid == iter->tid && iter->max_pos > iter->pos)) {- int n_plp = 0;- lbnode_t *p, *q;- // write iter->plp at iter->pos- iter->dummy->next = iter->head;- for (p = iter->head, q = iter->dummy; p->next; q = p, p = p->next) {- if (p->b.core.tid < iter->tid || (p->b.core.tid == iter->tid && p->end <= iter->pos)) { // then remove- q->next = p->next; mp_free(iter->mp, p); p = q;- } else if (p->b.core.tid == iter->tid && p->beg <= iter->pos) { // here: p->end > pos; then add to pileup- if (n_plp == iter->max_plp) { // then double the capacity- iter->max_plp = iter->max_plp? iter->max_plp<<1 : 256;- iter->plp = (bam_pileup1_t*)realloc(iter->plp, sizeof(bam_pileup1_t) * iter->max_plp);- }- iter->plp[n_plp].b = &p->b;- if (resolve_cigar2(iter->plp + n_plp, iter->pos, &p->s)) ++n_plp; // actually always true...- }- }- iter->head = iter->dummy->next; // dummy->next may be changed- *_n_plp = n_plp; *_tid = iter->tid; *_pos = iter->pos;- // update iter->tid and iter->pos- if (iter->head->next) {- if (iter->tid > iter->head->b.core.tid) {- fprintf(stderr, "[%s] unsorted input. Pileup aborts.\n", __func__);- iter->error = 1;- *_n_plp = -1;- return 0;- }- }- if (iter->tid < iter->head->b.core.tid) { // come to a new reference sequence- iter->tid = iter->head->b.core.tid; iter->pos = iter->head->beg; // jump to the next reference- } else if (iter->pos < iter->head->beg) { // here: tid == head->b.core.tid- iter->pos = iter->head->beg; // jump to the next position- } else ++iter->pos; // scan contiguously- // return- if (n_plp) return iter->plp;- if (iter->is_eof && iter->head->next == 0) break;- }- return 0;-}--int bam_plp_push(bam_plp_t iter, const bam1_t *b)-{- if (iter->error) return -1;- if (b) {- if (b->core.tid < 0) return 0;- if (b->core.flag & iter->flag_mask) return 0;- if (iter->tid == b->core.tid && iter->pos == b->core.pos && iter->mp->cnt > iter->maxcnt) return 0;- bam_copy1(&iter->tail->b, b);- iter->tail->beg = b->core.pos; iter->tail->end = bam_calend(&b->core, bam1_cigar(b));- iter->tail->s = g_cstate_null; iter->tail->s.end = iter->tail->end - 1; // initialize cstate_t- if (b->core.tid < iter->max_tid) {- fprintf(stderr, "[bam_pileup_core] the input is not sorted (chromosomes out of order)\n");- iter->error = 1;- return -1;- }- if ((b->core.tid == iter->max_tid) && (iter->tail->beg < iter->max_pos)) {- fprintf(stderr, "[bam_pileup_core] the input is not sorted (reads out of order)\n");- iter->error = 1;- return -1;- }- iter->max_tid = b->core.tid; iter->max_pos = iter->tail->beg;- if (iter->tail->end > iter->pos || iter->tail->b.core.tid > iter->tid) {- iter->tail->next = mp_alloc(iter->mp);- iter->tail = iter->tail->next;- }- } else iter->is_eof = 1;- return 0;-}--const bam_pileup1_t *bam_plp_auto(bam_plp_t iter, int *_tid, int *_pos, int *_n_plp)-{- const bam_pileup1_t *plp;- if (iter->func == 0 || iter->error) { *_n_plp = -1; return 0; }- if ((plp = bam_plp_next(iter, _tid, _pos, _n_plp)) != 0) return plp;- else { // no pileup line can be obtained; read alignments- *_n_plp = 0;- if (iter->is_eof) return 0;- while (iter->func(iter->data, iter->b) >= 0) {- if (bam_plp_push(iter, iter->b) < 0) {- *_n_plp = -1;- return 0;- }- if ((plp = bam_plp_next(iter, _tid, _pos, _n_plp)) != 0) return plp;- // otherwise no pileup line can be returned; read the next alignment.- }- bam_plp_push(iter, 0);- if ((plp = bam_plp_next(iter, _tid, _pos, _n_plp)) != 0) return plp;- return 0;- }-}--void bam_plp_reset(bam_plp_t iter)-{- lbnode_t *p, *q;- iter->max_tid = iter->max_pos = -1;- iter->tid = iter->pos = 0;- iter->is_eof = 0;- for (p = iter->head; p->next;) {- q = p->next;- mp_free(iter->mp, p);- p = q;- }- iter->head = iter->tail;-}--void bam_plp_set_mask(bam_plp_t iter, int mask)-{- iter->flag_mask = mask < 0? BAM_DEF_MASK : (BAM_FUNMAP | mask);-}--void bam_plp_set_maxcnt(bam_plp_t iter, int maxcnt)-{- iter->maxcnt = maxcnt;-}--/*****************- * callback APIs *- *****************/--int bam_pileup_file(bamFile fp, int mask, bam_pileup_f func, void *func_data)-{- bam_plbuf_t *buf;- int ret;- bam1_t *b;- b = bam_init1();- buf = bam_plbuf_init(func, func_data);- bam_plbuf_set_mask(buf, mask);- while ((ret = bam_read1(fp, b)) >= 0)- bam_plbuf_push(b, buf);- bam_plbuf_push(0, buf);- bam_plbuf_destroy(buf);- bam_destroy1(b);- return 0;-}--void bam_plbuf_set_mask(bam_plbuf_t *buf, int mask)-{- bam_plp_set_mask(buf->iter, mask);-}--void bam_plbuf_reset(bam_plbuf_t *buf)-{- bam_plp_reset(buf->iter);-}--bam_plbuf_t *bam_plbuf_init(bam_pileup_f func, void *data)-{- bam_plbuf_t *buf;- buf = calloc(1, sizeof(bam_plbuf_t));- buf->iter = bam_plp_init(0, 0);- buf->func = func;- buf->data = data;- return buf;-}--void bam_plbuf_destroy(bam_plbuf_t *buf)-{- bam_plp_destroy(buf->iter);- free(buf);-}--int bam_plbuf_push(const bam1_t *b, bam_plbuf_t *buf)-{- int ret, n_plp, tid, pos;- const bam_pileup1_t *plp;- ret = bam_plp_push(buf->iter, b);- if (ret < 0) return ret;- while ((plp = bam_plp_next(buf->iter, &tid, &pos, &n_plp)) != 0)- buf->func(tid, pos, n_plp, plp, buf->data);- return 0;-}--/***********- * mpileup *- ***********/--struct __bam_mplp_t {- int n;- uint64_t min, *pos;- bam_plp_t *iter;- int *n_plp;- const bam_pileup1_t **plp;-};--bam_mplp_t bam_mplp_init(int n, bam_plp_auto_f func, void **data)-{- int i;- bam_mplp_t iter;- iter = calloc(1, sizeof(struct __bam_mplp_t));- iter->pos = calloc(n, 8);- iter->n_plp = calloc(n, sizeof(int));- iter->plp = calloc(n, sizeof(void*));- iter->iter = calloc(n, sizeof(void*));- iter->n = n;- iter->min = (uint64_t)-1;- for (i = 0; i < n; ++i) {- iter->iter[i] = bam_plp_init(func, data[i]);- iter->pos[i] = iter->min;- }- return iter;-}--void bam_mplp_set_maxcnt(bam_mplp_t iter, int maxcnt)-{- int i;- for (i = 0; i < iter->n; ++i)- iter->iter[i]->maxcnt = maxcnt;-}--void bam_mplp_destroy(bam_mplp_t iter)-{- int i;- for (i = 0; i < iter->n; ++i) bam_plp_destroy(iter->iter[i]);- free(iter->iter); free(iter->pos); free(iter->n_plp); free(iter->plp);- free(iter);-}--int bam_mplp_auto(bam_mplp_t iter, int *_tid, int *_pos, int *n_plp, const bam_pileup1_t **plp)-{- int i, ret = 0;- uint64_t new_min = (uint64_t)-1;- for (i = 0; i < iter->n; ++i) {- if (iter->pos[i] == iter->min) {- int tid, pos;- iter->plp[i] = bam_plp_auto(iter->iter[i], &tid, &pos, &iter->n_plp[i]);- iter->pos[i] = (uint64_t)tid<<32 | pos;- }- if (iter->plp[i] && iter->pos[i] < new_min) new_min = iter->pos[i];- }- iter->min = new_min;- if (new_min == (uint64_t)-1) return 0;- *_tid = new_min>>32; *_pos = (uint32_t)new_min;- for (i = 0; i < iter->n; ++i) {- if (iter->pos[i] == iter->min) { // FIXME: valgrind reports "uninitialised value(s) at this line"- n_plp[i] = iter->n_plp[i], plp[i] = iter->plp[i];- ++ret;- } else n_plp[i] = 0, plp[i] = 0;- }- return ret;-}
− samtools-0.1.13/bam_reheader.c
@@ -1,61 +0,0 @@-#include <stdio.h>-#include <stdlib.h>-#include "bgzf.h"-#include "bam.h"--#define BUF_SIZE 0x10000--int bam_reheader(BGZF *in, const bam_header_t *h, int fd)-{- BGZF *fp;- bam_header_t *old;- int len;- uint8_t *buf;- if (in->open_mode != 'r') return -1;- buf = malloc(BUF_SIZE);- old = bam_header_read(in);- fp = bgzf_fdopen(fd, "w");- bam_header_write(fp, h);- if (in->block_offset < in->block_length) {- bgzf_write(fp, in->uncompressed_block + in->block_offset, in->block_length - in->block_offset);- bgzf_flush(fp);- }-#ifdef _USE_KNETFILE- while ((len = knet_read(in->x.fpr, buf, BUF_SIZE)) > 0)- fwrite(buf, 1, len, fp->x.fpw);-#else- while (!feof(in->file) && (len = fread(buf, 1, BUF_SIZE, in->file)) > 0)- fwrite(buf, 1, len, fp->file);-#endif- free(buf);- fp->block_offset = in->block_offset = 0;- bgzf_close(fp);- return 0;-}--int main_reheader(int argc, char *argv[])-{- bam_header_t *h;- BGZF *in;- if (argc != 3) {- fprintf(stderr, "Usage: samtools reheader <in.header.sam> <in.bam>\n");- return 1;- }- { // read the header- tamFile fph = sam_open(argv[1]);- if (fph == 0) {- fprintf(stderr, "[%s] fail to read the header from %s.\n", __func__, argv[1]);- return 1;- }- h = sam_header_read(fph);- sam_close(fph);- }- in = strcmp(argv[2], "-")? bam_open(argv[2], "r") : bam_dopen(fileno(stdin), "r");- if (in == 0) {- fprintf(stderr, "[%s] fail to open file %s.\n", __func__, argv[2]);- return 1;- }- bam_reheader(in, h, fileno(stdout));- bgzf_close(in);- return 0;-}
− samtools-0.1.13/bam_sort.c
@@ -1,421 +0,0 @@-#include <stdlib.h>-#include <ctype.h>-#include <assert.h>-#include <errno.h>-#include <stdio.h>-#include <string.h>-#include <unistd.h>-#include "bam.h"-#include "ksort.h"--static int g_is_by_qname = 0;--static inline int strnum_cmp(const char *a, const char *b)-{- char *pa, *pb;- pa = (char*)a; pb = (char*)b;- while (*pa && *pb) {- if (isdigit(*pa) && isdigit(*pb)) {- long ai, bi;- ai = strtol(pa, &pa, 10);- bi = strtol(pb, &pb, 10);- if (ai != bi) return ai<bi? -1 : ai>bi? 1 : 0;- } else {- if (*pa != *pb) break;- ++pa; ++pb;- }- }- if (*pa == *pb)- return (pa-a) < (pb-b)? -1 : (pa-a) > (pb-b)? 1 : 0;- return *pa<*pb? -1 : *pa>*pb? 1 : 0;-}--#define HEAP_EMPTY 0xffffffffffffffffull--typedef struct {- int i;- uint64_t pos, idx;- bam1_t *b;-} heap1_t;--#define __pos_cmp(a, b) ((a).pos > (b).pos || ((a).pos == (b).pos && ((a).i > (b).i || ((a).i == (b).i && (a).idx > (b).idx))))--static inline int heap_lt(const heap1_t a, const heap1_t b)-{- if (g_is_by_qname) {- int t;- if (a.b == 0 || b.b == 0) return a.b == 0? 1 : 0;- t = strnum_cmp(bam1_qname(a.b), bam1_qname(b.b));- return (t > 0 || (t == 0 && __pos_cmp(a, b)));- } else return __pos_cmp(a, b);-}--KSORT_INIT(heap, heap1_t, heap_lt)--static void swap_header_targets(bam_header_t *h1, bam_header_t *h2)-{- bam_header_t t;- t.n_targets = h1->n_targets, h1->n_targets = h2->n_targets, h2->n_targets = t.n_targets;- t.target_name = h1->target_name, h1->target_name = h2->target_name, h2->target_name = t.target_name;- t.target_len = h1->target_len, h1->target_len = h2->target_len, h2->target_len = t.target_len;-}--static void swap_header_text(bam_header_t *h1, bam_header_t *h2)-{- int tempi;- char *temps;- tempi = h1->l_text, h1->l_text = h2->l_text, h2->l_text = tempi;- temps = h1->text, h1->text = h2->text, h2->text = temps;-}--#define MERGE_RG 1-#define MERGE_UNCOMP 2--/*!- @abstract Merge multiple sorted BAM.- @param is_by_qname whether to sort by query name- @param out output BAM file name- @param headers name of SAM file from which to copy '@' header lines,- or NULL to copy them from the first file to be merged- @param n number of files to be merged- @param fn names of files to be merged-- @discussion Padding information may NOT correctly maintained. This- function is NOT thread safe.- */-int bam_merge_core(int by_qname, const char *out, const char *headers, int n, char * const *fn,- int flag, const char *reg)-{- bamFile fpout, *fp;- heap1_t *heap;- bam_header_t *hout = 0;- bam_header_t *hheaders = NULL;- int i, j, *RG_len = 0;- uint64_t idx = 0;- char **RG = 0;- bam_iter_t *iter = 0;-- if (headers) {- tamFile fpheaders = sam_open(headers);- if (fpheaders == 0) {- const char *message = strerror(errno);- fprintf(stderr, "[bam_merge_core] cannot open '%s': %s\n", headers, message);- return -1;- }- hheaders = sam_header_read(fpheaders);- sam_close(fpheaders);- }-- g_is_by_qname = by_qname;- fp = (bamFile*)calloc(n, sizeof(bamFile));- heap = (heap1_t*)calloc(n, sizeof(heap1_t));- iter = (bam_iter_t*)calloc(n, sizeof(bam_iter_t));- // prepare RG tag- if (flag & MERGE_RG) {- RG = (char**)calloc(n, sizeof(void*));- RG_len = (int*)calloc(n, sizeof(int));- for (i = 0; i != n; ++i) {- int l = strlen(fn[i]);- const char *s = fn[i];- if (l > 4 && strcmp(s + l - 4, ".bam") == 0) l -= 4;- for (j = l - 1; j >= 0; --j) if (s[j] == '/') break;- ++j; l -= j;- RG[i] = calloc(l + 1, 1);- RG_len[i] = l;- strncpy(RG[i], s + j, l);- }- }- // read the first- for (i = 0; i != n; ++i) {- bam_header_t *hin;- fp[i] = bam_open(fn[i], "r");- if (fp[i] == 0) {- int j;- fprintf(stderr, "[bam_merge_core] fail to open file %s\n", fn[i]);- for (j = 0; j < i; ++j) bam_close(fp[j]);- free(fp); free(heap);- // FIXME: possible memory leak- return -1;- }- hin = bam_header_read(fp[i]);- if (i == 0) { // the first BAM- hout = hin;- } else { // validate multiple baf- int min_n_targets = hout->n_targets;- if (hin->n_targets < min_n_targets) min_n_targets = hin->n_targets;-- for (j = 0; j < min_n_targets; ++j)- if (strcmp(hout->target_name[j], hin->target_name[j]) != 0) {- fprintf(stderr, "[bam_merge_core] different target sequence name: '%s' != '%s' in file '%s'\n",- hout->target_name[j], hin->target_name[j], fn[i]);- return -1;- }-- // If this input file has additional target reference sequences,- // add them to the headers to be output- if (hin->n_targets > hout->n_targets) {- swap_header_targets(hout, hin);- // FIXME Possibly we should also create @SQ text headers- // for the newly added reference sequences- }-- bam_header_destroy(hin);- }- }-- if (hheaders) {- // If the text headers to be swapped in include any @SQ headers,- // check that they are consistent with the existing binary list- // of reference information.- if (hheaders->n_targets > 0) {- if (hout->n_targets != hheaders->n_targets) {- fprintf(stderr, "[bam_merge_core] number of @SQ headers in '%s' differs from number of target sequences\n", headers);- if (!reg) return -1;- }- for (j = 0; j < hout->n_targets; ++j)- if (strcmp(hout->target_name[j], hheaders->target_name[j]) != 0) {- fprintf(stderr, "[bam_merge_core] @SQ header '%s' in '%s' differs from target sequence\n", hheaders->target_name[j], headers);- if (!reg) return -1;- }- }-- swap_header_text(hout, hheaders);- bam_header_destroy(hheaders);- }-- if (reg) {- int tid, beg, end;- if (bam_parse_region(hout, reg, &tid, &beg, &end) < 0) {- fprintf(stderr, "[%s] Malformated region string or undefined reference name\n", __func__);- return -1;- }- for (i = 0; i < n; ++i) {- bam_index_t *idx;- idx = bam_index_load(fn[i]);- iter[i] = bam_iter_query(idx, tid, beg, end);- bam_index_destroy(idx);- }- }-- for (i = 0; i < n; ++i) {- heap1_t *h = heap + i;- h->i = i;- h->b = (bam1_t*)calloc(1, sizeof(bam1_t));- if (bam_iter_read(fp[i], iter[i], h->b) >= 0) {- h->pos = ((uint64_t)h->b->core.tid<<32) | (uint32_t)h->b->core.pos<<1 | bam1_strand(h->b);- h->idx = idx++;- }- else h->pos = HEAP_EMPTY;- }- if (flag & MERGE_UNCOMP) {- fpout = strcmp(out, "-")? bam_open(out, "wu") : bam_dopen(fileno(stdout), "wu");- } else {- fpout = strcmp(out, "-")? bam_open(out, "w") : bam_dopen(fileno(stdout), "w");- }- if (fpout == 0) {- fprintf(stderr, "[%s] fail to create the output file.\n", __func__);- return -1;- }- bam_header_write(fpout, hout);- bam_header_destroy(hout);-- ks_heapmake(heap, n, heap);- while (heap->pos != HEAP_EMPTY) {- bam1_t *b = heap->b;- if (flag & MERGE_RG) {- uint8_t *rg = bam_aux_get(b, "RG");- if (rg) bam_aux_del(b, rg);- bam_aux_append(b, "RG", 'Z', RG_len[heap->i] + 1, (uint8_t*)RG[heap->i]);- }- bam_write1_core(fpout, &b->core, b->data_len, b->data);- if ((j = bam_iter_read(fp[heap->i], iter[heap->i], b)) >= 0) {- heap->pos = ((uint64_t)b->core.tid<<32) | (uint32_t)b->core.pos<<1 | bam1_strand(b);- heap->idx = idx++;- } else if (j == -1) {- heap->pos = HEAP_EMPTY;- free(heap->b->data); free(heap->b);- heap->b = 0;- } else fprintf(stderr, "[bam_merge_core] '%s' is truncated. Continue anyway.\n", fn[heap->i]);- ks_heapadjust(heap, 0, n, heap);- }-- if (flag & MERGE_RG) {- for (i = 0; i != n; ++i) free(RG[i]);- free(RG); free(RG_len);- }- for (i = 0; i != n; ++i) {- bam_iter_destroy(iter[i]);- bam_close(fp[i]);- }- bam_close(fpout);- free(fp); free(heap); free(iter);- return 0;-}--int bam_merge(int argc, char *argv[])-{- int c, is_by_qname = 0, flag = 0, ret = 0;- char *fn_headers = NULL, *reg = 0;-- while ((c = getopt(argc, argv, "h:nruR:")) >= 0) {- switch (c) {- case 'r': flag |= MERGE_RG; break;- case 'h': fn_headers = strdup(optarg); break;- case 'n': is_by_qname = 1; break;- case 'u': flag |= MERGE_UNCOMP; break;- case 'R': reg = strdup(optarg); break;- }- }- if (optind + 2 >= argc) {- fprintf(stderr, "\n");- fprintf(stderr, "Usage: samtools merge [-nr] [-h inh.sam] <out.bam> <in1.bam> <in2.bam> [...]\n\n");- fprintf(stderr, "Options: -n sort by read names\n");- fprintf(stderr, " -r attach RG tag (inferred from file names)\n");- fprintf(stderr, " -u uncompressed BAM output\n");- fprintf(stderr, " -R STR merge file in the specified region STR [all]\n");- fprintf(stderr, " -h FILE copy the header in FILE to <out.bam> [in1.bam]\n\n");- fprintf(stderr, "Note: Samtools' merge does not reconstruct the @RG dictionary in the header. Users\n");- fprintf(stderr, " must provide the correct header with -h, or uses Picard which properly maintains\n");- fprintf(stderr, " the header dictionary in merging.\n\n");- return 1;- }- if (bam_merge_core(is_by_qname, argv[optind], fn_headers, argc - optind - 1, argv + optind + 1, flag, reg) < 0) ret = 1;- free(reg);- free(fn_headers);- return ret;-}--typedef bam1_t *bam1_p;--static inline int bam1_lt(const bam1_p a, const bam1_p b)-{- if (g_is_by_qname) {- int t = strnum_cmp(bam1_qname(a), bam1_qname(b));- return (t < 0 || (t == 0 && (((uint64_t)a->core.tid<<32|a->core.pos) < ((uint64_t)b->core.tid<<32|b->core.pos))));- } else return (((uint64_t)a->core.tid<<32|a->core.pos) < ((uint64_t)b->core.tid<<32|b->core.pos));-}-KSORT_INIT(sort, bam1_p, bam1_lt)--static void sort_blocks(int n, int k, bam1_p *buf, const char *prefix, const bam_header_t *h, int is_stdout)-{- char *name;- int i;- bamFile fp;- ks_mergesort(sort, k, buf, 0);- name = (char*)calloc(strlen(prefix) + 20, 1);- if (n >= 0) sprintf(name, "%s.%.4d.bam", prefix, n);- else sprintf(name, "%s.bam", prefix);- fp = is_stdout? bam_dopen(fileno(stdout), "w") : bam_open(name, "w");- if (fp == 0) {- fprintf(stderr, "[sort_blocks] fail to create file %s.\n", name);- free(name);- // FIXME: possible memory leak- return;- }- free(name);- bam_header_write(fp, h);- for (i = 0; i < k; ++i)- bam_write1_core(fp, &buf[i]->core, buf[i]->data_len, buf[i]->data);- bam_close(fp);-}--/*!- @abstract Sort an unsorted BAM file based on the chromosome order- and the leftmost position of an alignment-- @param is_by_qname whether to sort by query name- @param fn name of the file to be sorted- @param prefix prefix of the output and the temporary files; upon- sucessess, prefix.bam will be written.- @param max_mem approxiate maximum memory (very inaccurate)-- @discussion It may create multiple temporary subalignment files- and then merge them by calling bam_merge_core(). This function is- NOT thread safe.- */-void bam_sort_core_ext(int is_by_qname, const char *fn, const char *prefix, size_t max_mem, int is_stdout)-{- int n, ret, k, i;- size_t mem;- bam_header_t *header;- bamFile fp;- bam1_t *b, **buf;-- g_is_by_qname = is_by_qname;- n = k = 0; mem = 0;- fp = strcmp(fn, "-")? bam_open(fn, "r") : bam_dopen(fileno(stdin), "r");- if (fp == 0) {- fprintf(stderr, "[bam_sort_core] fail to open file %s\n", fn);- return;- }- header = bam_header_read(fp);- buf = (bam1_t**)calloc(max_mem / BAM_CORE_SIZE, sizeof(bam1_t*));- // write sub files- for (;;) {- if (buf[k] == 0) buf[k] = (bam1_t*)calloc(1, sizeof(bam1_t));- b = buf[k];- if ((ret = bam_read1(fp, b)) < 0) break;- mem += ret;- ++k;- if (mem >= max_mem) {- sort_blocks(n++, k, buf, prefix, header, 0);- mem = 0; k = 0;- }- }- if (ret != -1)- fprintf(stderr, "[bam_sort_core] truncated file. Continue anyway.\n");- if (n == 0) sort_blocks(-1, k, buf, prefix, header, is_stdout);- else { // then merge- char **fns, *fnout;- fprintf(stderr, "[bam_sort_core] merging from %d files...\n", n+1);- sort_blocks(n++, k, buf, prefix, header, 0);- fnout = (char*)calloc(strlen(prefix) + 20, 1);- if (is_stdout) sprintf(fnout, "-");- else sprintf(fnout, "%s.bam", prefix);- fns = (char**)calloc(n, sizeof(char*));- for (i = 0; i < n; ++i) {- fns[i] = (char*)calloc(strlen(prefix) + 20, 1);- sprintf(fns[i], "%s.%.4d.bam", prefix, i);- }- bam_merge_core(is_by_qname, fnout, 0, n, fns, 0, 0);- free(fnout);- for (i = 0; i < n; ++i) {- unlink(fns[i]);- free(fns[i]);- }- free(fns);- }- for (k = 0; k < max_mem / BAM_CORE_SIZE; ++k) {- if (buf[k]) {- free(buf[k]->data);- free(buf[k]);- }- }- free(buf);- bam_header_destroy(header);- bam_close(fp);-}--void bam_sort_core(int is_by_qname, const char *fn, const char *prefix, size_t max_mem)-{- bam_sort_core_ext(is_by_qname, fn, prefix, max_mem, 0);-}--int bam_sort(int argc, char *argv[])-{- size_t max_mem = 500000000;- int c, is_by_qname = 0, is_stdout = 0;- while ((c = getopt(argc, argv, "nom:")) >= 0) {- switch (c) {- case 'o': is_stdout = 1; break;- case 'n': is_by_qname = 1; break;- case 'm': max_mem = atol(optarg); break;- }- }- if (optind + 2 > argc) {- fprintf(stderr, "Usage: samtools sort [-on] [-m <maxMem>] <in.bam> <out.prefix>\n");- return 1;- }- bam_sort_core_ext(is_by_qname, argv[optind], argv[optind+1], max_mem, is_stdout);- return 0;-}
− samtools-0.1.13/bgzf.c
@@ -1,671 +0,0 @@-/* The MIT License-- Copyright (c) 2008 Broad Institute / Massachusetts Institute of Technology-- 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.-*/--/*- 2009-06-29 by lh3: cache recent uncompressed blocks.- 2009-06-25 by lh3: optionally use my knetfile library to access file on a FTP.- 2009-06-12 by lh3: support a mode string like "wu" where 'u' for uncompressed output */--#include <stdio.h>-#include <stdlib.h>-#include <string.h>-#include <unistd.h>-#include <fcntl.h>-#include <sys/types.h>-#include <sys/stat.h>-#include "bgzf.h"--#include "khash.h"-typedef struct {- int size;- uint8_t *block;- int64_t end_offset;-} cache_t;-KHASH_MAP_INIT_INT64(cache, cache_t)--#if defined(_WIN32) || defined(_MSC_VER)-#define ftello(fp) ftell(fp)-#define fseeko(fp, offset, whence) fseek(fp, offset, whence)-#else-extern off_t ftello(FILE *stream);-extern int fseeko(FILE *stream, off_t offset, int whence);-#endif--typedef int8_t bgzf_byte_t;--static const int DEFAULT_BLOCK_SIZE = 64 * 1024;-static const int MAX_BLOCK_SIZE = 64 * 1024;--static const int BLOCK_HEADER_LENGTH = 18;-static const int BLOCK_FOOTER_LENGTH = 8;--static const int GZIP_ID1 = 31;-static const int GZIP_ID2 = 139;-static const int CM_DEFLATE = 8;-static const int FLG_FEXTRA = 4;-static const int OS_UNKNOWN = 255;-static const int BGZF_ID1 = 66; // 'B'-static const int BGZF_ID2 = 67; // 'C'-static const int BGZF_LEN = 2;-static const int BGZF_XLEN = 6; // BGZF_LEN+4--static const int GZIP_WINDOW_BITS = -15; // no zlib header-static const int Z_DEFAULT_MEM_LEVEL = 8;---inline-void-packInt16(uint8_t* buffer, uint16_t value)-{- buffer[0] = value;- buffer[1] = value >> 8;-}--inline-int-unpackInt16(const uint8_t* buffer)-{- return (buffer[0] | (buffer[1] << 8));-}--inline-void-packInt32(uint8_t* buffer, uint32_t value)-{- buffer[0] = value;- buffer[1] = value >> 8;- buffer[2] = value >> 16;- buffer[3] = value >> 24;-}--static inline-int-bgzf_min(int x, int y)-{- return (x < y) ? x : y;-}--static-void-report_error(BGZF* fp, const char* message) {- fp->error = message;-}--static BGZF *bgzf_read_init()-{- BGZF *fp;- fp = calloc(1, sizeof(BGZF));- fp->uncompressed_block_size = MAX_BLOCK_SIZE;- fp->uncompressed_block = malloc(MAX_BLOCK_SIZE);- fp->compressed_block_size = MAX_BLOCK_SIZE;- fp->compressed_block = malloc(MAX_BLOCK_SIZE);- fp->cache_size = 0;- fp->cache = kh_init(cache);- return fp;-}--static-BGZF*-open_read(int fd)-{-#ifdef _USE_KNETFILE- knetFile *file = knet_dopen(fd, "r");-#else- FILE* file = fdopen(fd, "r");-#endif- BGZF* fp;- if (file == 0) return 0;- fp = bgzf_read_init();- fp->file_descriptor = fd;- fp->open_mode = 'r';-#ifdef _USE_KNETFILE- fp->x.fpr = file;-#else- fp->file = file;-#endif- return fp;-}--static-BGZF*-open_write(int fd, bool is_uncompressed)-{- FILE* file = fdopen(fd, "w");- BGZF* fp;- if (file == 0) return 0;- fp = malloc(sizeof(BGZF));- fp->file_descriptor = fd;- fp->open_mode = 'w';- fp->owned_file = 0; fp->is_uncompressed = is_uncompressed;-#ifdef _USE_KNETFILE- fp->x.fpw = file;-#else- fp->file = file;-#endif- fp->uncompressed_block_size = DEFAULT_BLOCK_SIZE;- fp->uncompressed_block = NULL;- fp->compressed_block_size = MAX_BLOCK_SIZE;- fp->compressed_block = malloc(MAX_BLOCK_SIZE);- fp->block_address = 0;- fp->block_offset = 0;- fp->block_length = 0;- fp->error = NULL;- return fp;-}--BGZF*-bgzf_open(const char* __restrict path, const char* __restrict mode)-{- BGZF* fp = NULL;- if (strchr(mode, 'r') || strchr(mode, 'R')) { /* The reading mode is preferred. */-#ifdef _USE_KNETFILE- knetFile *file = knet_open(path, mode);- if (file == 0) return 0;- fp = bgzf_read_init();- fp->file_descriptor = -1;- fp->open_mode = 'r';- fp->x.fpr = file;-#else- int fd, oflag = O_RDONLY;-#ifdef _WIN32- oflag |= O_BINARY;-#endif- fd = open(path, oflag);- if (fd == -1) return 0;- fp = open_read(fd);-#endif- } else if (strchr(mode, 'w') || strchr(mode, 'W')) {- int fd, oflag = O_WRONLY | O_CREAT | O_TRUNC;-#ifdef _WIN32- oflag |= O_BINARY;-#endif- fd = open(path, oflag, 0666);- if (fd == -1) return 0;- fp = open_write(fd, strchr(mode, 'u')? 1 : 0);- }- if (fp != NULL) fp->owned_file = 1;- return fp;-}--BGZF*-bgzf_fdopen(int fd, const char * __restrict mode)-{- if (fd == -1) return 0;- if (mode[0] == 'r' || mode[0] == 'R') {- return open_read(fd);- } else if (mode[0] == 'w' || mode[0] == 'W') {- return open_write(fd, strstr(mode, "u")? 1 : 0);- } else {- return NULL;- }-}--static-int-deflate_block(BGZF* fp, int block_length)-{- // Deflate the block in fp->uncompressed_block into fp->compressed_block.- // Also adds an extra field that stores the compressed block length.-- bgzf_byte_t* buffer = fp->compressed_block;- int buffer_size = fp->compressed_block_size;-- // Init gzip header- buffer[0] = GZIP_ID1;- buffer[1] = GZIP_ID2;- buffer[2] = CM_DEFLATE;- buffer[3] = FLG_FEXTRA;- buffer[4] = 0; // mtime- buffer[5] = 0;- buffer[6] = 0;- buffer[7] = 0;- buffer[8] = 0;- buffer[9] = OS_UNKNOWN;- buffer[10] = BGZF_XLEN;- buffer[11] = 0;- buffer[12] = BGZF_ID1;- buffer[13] = BGZF_ID2;- buffer[14] = BGZF_LEN;- buffer[15] = 0;- buffer[16] = 0; // placeholder for block length- buffer[17] = 0;-- // loop to retry for blocks that do not compress enough- int input_length = block_length;- int compressed_length = 0;- while (1) {- int compress_level = fp->is_uncompressed? 0 : Z_DEFAULT_COMPRESSION;- z_stream zs;- zs.zalloc = NULL;- zs.zfree = NULL;- zs.next_in = fp->uncompressed_block;- zs.avail_in = input_length;- zs.next_out = (void*)&buffer[BLOCK_HEADER_LENGTH];- zs.avail_out = buffer_size - BLOCK_HEADER_LENGTH - BLOCK_FOOTER_LENGTH;-- int status = deflateInit2(&zs, compress_level, Z_DEFLATED,- GZIP_WINDOW_BITS, Z_DEFAULT_MEM_LEVEL, Z_DEFAULT_STRATEGY);- if (status != Z_OK) {- report_error(fp, "deflate init failed");- return -1;- }- status = deflate(&zs, Z_FINISH);- if (status != Z_STREAM_END) {- deflateEnd(&zs);- if (status == Z_OK) {- // Not enough space in buffer.- // Can happen in the rare case the input doesn't compress enough.- // Reduce the amount of input until it fits.- input_length -= 1024;- if (input_length <= 0) {- // should never happen- report_error(fp, "input reduction failed");- return -1;- }- continue;- }- report_error(fp, "deflate failed");- return -1;- }- status = deflateEnd(&zs);- if (status != Z_OK) {- report_error(fp, "deflate end failed");- return -1;- }- compressed_length = zs.total_out;- compressed_length += BLOCK_HEADER_LENGTH + BLOCK_FOOTER_LENGTH;- if (compressed_length > MAX_BLOCK_SIZE) {- // should never happen- report_error(fp, "deflate overflow");- return -1;- }- break;- }-- packInt16((uint8_t*)&buffer[16], compressed_length-1);- uint32_t crc = crc32(0L, NULL, 0L);- crc = crc32(crc, fp->uncompressed_block, input_length);- packInt32((uint8_t*)&buffer[compressed_length-8], crc);- packInt32((uint8_t*)&buffer[compressed_length-4], input_length);-- int remaining = block_length - input_length;- if (remaining > 0) {- if (remaining > input_length) {- // should never happen (check so we can use memcpy)- report_error(fp, "remainder too large");- return -1;- }- memcpy(fp->uncompressed_block,- fp->uncompressed_block + input_length,- remaining);- }- fp->block_offset = remaining;- return compressed_length;-}--static-int-inflate_block(BGZF* fp, int block_length)-{- // Inflate the block in fp->compressed_block into fp->uncompressed_block-- z_stream zs;- zs.zalloc = NULL;- zs.zfree = NULL;- zs.next_in = fp->compressed_block + 18;- zs.avail_in = block_length - 16;- zs.next_out = fp->uncompressed_block;- zs.avail_out = fp->uncompressed_block_size;-- int status = inflateInit2(&zs, GZIP_WINDOW_BITS);- if (status != Z_OK) {- report_error(fp, "inflate init failed");- return -1;- }- status = inflate(&zs, Z_FINISH);- if (status != Z_STREAM_END) {- inflateEnd(&zs);- report_error(fp, "inflate failed");- return -1;- }- status = inflateEnd(&zs);- if (status != Z_OK) {- report_error(fp, "inflate failed");- return -1;- }- return zs.total_out;-}--static-int-check_header(const bgzf_byte_t* header)-{- return (header[0] == GZIP_ID1 &&- header[1] == (bgzf_byte_t) GZIP_ID2 &&- header[2] == Z_DEFLATED &&- (header[3] & FLG_FEXTRA) != 0 &&- unpackInt16((uint8_t*)&header[10]) == BGZF_XLEN &&- header[12] == BGZF_ID1 &&- header[13] == BGZF_ID2 &&- unpackInt16((uint8_t*)&header[14]) == BGZF_LEN);-}--static void free_cache(BGZF *fp)-{- khint_t k;- khash_t(cache) *h = (khash_t(cache)*)fp->cache;- if (fp->open_mode != 'r') return;- for (k = kh_begin(h); k < kh_end(h); ++k)- if (kh_exist(h, k)) free(kh_val(h, k).block);- kh_destroy(cache, h);-}--static int load_block_from_cache(BGZF *fp, int64_t block_address)-{- khint_t k;- cache_t *p;- khash_t(cache) *h = (khash_t(cache)*)fp->cache;- k = kh_get(cache, h, block_address);- if (k == kh_end(h)) return 0;- p = &kh_val(h, k);- if (fp->block_length != 0) fp->block_offset = 0;- fp->block_address = block_address;- fp->block_length = p->size;- memcpy(fp->uncompressed_block, p->block, MAX_BLOCK_SIZE);-#ifdef _USE_KNETFILE- knet_seek(fp->x.fpr, p->end_offset, SEEK_SET);-#else- fseeko(fp->file, p->end_offset, SEEK_SET);-#endif- return p->size;-}--static void cache_block(BGZF *fp, int size)-{- int ret;- khint_t k;- cache_t *p;- khash_t(cache) *h = (khash_t(cache)*)fp->cache;- if (MAX_BLOCK_SIZE >= fp->cache_size) return;- if ((kh_size(h) + 1) * MAX_BLOCK_SIZE > fp->cache_size) {- /* A better way would be to remove the oldest block in the- * cache, but here we remove a random one for simplicity. This- * should not have a big impact on performance. */- for (k = kh_begin(h); k < kh_end(h); ++k)- if (kh_exist(h, k)) break;- if (k < kh_end(h)) {- free(kh_val(h, k).block);- kh_del(cache, h, k);- }- }- k = kh_put(cache, h, fp->block_address, &ret);- if (ret == 0) return; // if this happens, a bug!- p = &kh_val(h, k);- p->size = fp->block_length;- p->end_offset = fp->block_address + size;- p->block = malloc(MAX_BLOCK_SIZE);- memcpy(kh_val(h, k).block, fp->uncompressed_block, MAX_BLOCK_SIZE);-}--int-bgzf_read_block(BGZF* fp)-{- bgzf_byte_t header[BLOCK_HEADER_LENGTH];- int count, size = 0;-#ifdef _USE_KNETFILE- int64_t block_address = knet_tell(fp->x.fpr);- if (load_block_from_cache(fp, block_address)) return 0;- count = knet_read(fp->x.fpr, header, sizeof(header));-#else- int64_t block_address = ftello(fp->file);- if (load_block_from_cache(fp, block_address)) return 0;- count = fread(header, 1, sizeof(header), fp->file);-#endif- if (count == 0) {- fp->block_length = 0;- return 0;- }- size = count;- if (count != sizeof(header)) {- report_error(fp, "read failed");- return -1;- }- if (!check_header(header)) {- report_error(fp, "invalid block header");- return -1;- }- int block_length = unpackInt16((uint8_t*)&header[16]) + 1;- bgzf_byte_t* compressed_block = (bgzf_byte_t*) fp->compressed_block;- memcpy(compressed_block, header, BLOCK_HEADER_LENGTH);- int remaining = block_length - BLOCK_HEADER_LENGTH;-#ifdef _USE_KNETFILE- count = knet_read(fp->x.fpr, &compressed_block[BLOCK_HEADER_LENGTH], remaining);-#else- count = fread(&compressed_block[BLOCK_HEADER_LENGTH], 1, remaining, fp->file);-#endif- if (count != remaining) {- report_error(fp, "read failed");- return -1;- }- size += count;- count = inflate_block(fp, block_length);- if (count < 0) return -1;- if (fp->block_length != 0) {- // Do not reset offset if this read follows a seek.- fp->block_offset = 0;- }- fp->block_address = block_address;- fp->block_length = count;- cache_block(fp, size);- return 0;-}--int-bgzf_read(BGZF* fp, void* data, int length)-{- if (length <= 0) {- return 0;- }- if (fp->open_mode != 'r') {- report_error(fp, "file not open for reading");- return -1;- }-- int bytes_read = 0;- bgzf_byte_t* output = data;- while (bytes_read < length) {- int available = fp->block_length - fp->block_offset;- if (available <= 0) {- if (bgzf_read_block(fp) != 0) {- return -1;- }- available = fp->block_length - fp->block_offset;- if (available <= 0) {- break;- }- }- int copy_length = bgzf_min(length-bytes_read, available);- bgzf_byte_t* buffer = fp->uncompressed_block;- memcpy(output, buffer + fp->block_offset, copy_length);- fp->block_offset += copy_length;- output += copy_length;- bytes_read += copy_length;- }- if (fp->block_offset == fp->block_length) {-#ifdef _USE_KNETFILE- fp->block_address = knet_tell(fp->x.fpr);-#else- fp->block_address = ftello(fp->file);-#endif- fp->block_offset = 0;- fp->block_length = 0;- }- return bytes_read;-}--int bgzf_flush(BGZF* fp)-{- while (fp->block_offset > 0) {- int count, block_length;- block_length = deflate_block(fp, fp->block_offset);- if (block_length < 0) return -1;-#ifdef _USE_KNETFILE- count = fwrite(fp->compressed_block, 1, block_length, fp->x.fpw);-#else- count = fwrite(fp->compressed_block, 1, block_length, fp->file);-#endif- if (count != block_length) {- report_error(fp, "write failed");- return -1;- }- fp->block_address += block_length;- }- return 0;-}--int bgzf_flush_try(BGZF *fp, int size)-{- if (fp->block_offset + size > fp->uncompressed_block_size)- return bgzf_flush(fp);- return -1;-}--int bgzf_write(BGZF* fp, const void* data, int length)-{- if (fp->open_mode != 'w') {- report_error(fp, "file not open for writing");- return -1;- }-- if (fp->uncompressed_block == NULL)- fp->uncompressed_block = malloc(fp->uncompressed_block_size);-- const bgzf_byte_t* input = data;- int block_length = fp->uncompressed_block_size;- int bytes_written = 0;- while (bytes_written < length) {- int copy_length = bgzf_min(block_length - fp->block_offset, length - bytes_written);- bgzf_byte_t* buffer = fp->uncompressed_block;- memcpy(buffer + fp->block_offset, input, copy_length);- fp->block_offset += copy_length;- input += copy_length;- bytes_written += copy_length;- if (fp->block_offset == block_length) {- if (bgzf_flush(fp) != 0) {- break;- }- }- }- return bytes_written;-}--int bgzf_close(BGZF* fp)-{- if (fp->open_mode == 'w') {- if (bgzf_flush(fp) != 0) return -1;- { // add an empty block- int count, block_length = deflate_block(fp, 0);-#ifdef _USE_KNETFILE- count = fwrite(fp->compressed_block, 1, block_length, fp->x.fpw);-#else- count = fwrite(fp->compressed_block, 1, block_length, fp->file);-#endif- }-#ifdef _USE_KNETFILE- if (fflush(fp->x.fpw) != 0) {-#else- if (fflush(fp->file) != 0) {-#endif- report_error(fp, "flush failed");- return -1;- }- }- if (fp->owned_file) {-#ifdef _USE_KNETFILE- int ret;- if (fp->open_mode == 'w') ret = fclose(fp->x.fpw);- else ret = knet_close(fp->x.fpr);- if (ret != 0) return -1;-#else- if (fclose(fp->file) != 0) return -1;-#endif- }- free(fp->uncompressed_block);- free(fp->compressed_block);- free_cache(fp);- free(fp);- return 0;-}--void bgzf_set_cache_size(BGZF *fp, int cache_size)-{- if (fp) fp->cache_size = cache_size;-}--int bgzf_check_EOF(BGZF *fp)-{- static uint8_t magic[28] = "\037\213\010\4\0\0\0\0\0\377\6\0\102\103\2\0\033\0\3\0\0\0\0\0\0\0\0\0";- uint8_t buf[28];- off_t offset;-#ifdef _USE_KNETFILE- offset = knet_tell(fp->x.fpr);- if (knet_seek(fp->x.fpr, -28, SEEK_END) != 0) return -1;- knet_read(fp->x.fpr, buf, 28);- knet_seek(fp->x.fpr, offset, SEEK_SET);-#else- offset = ftello(fp->file);- if (fseeko(fp->file, -28, SEEK_END) != 0) return -1;- fread(buf, 1, 28, fp->file);- fseeko(fp->file, offset, SEEK_SET);-#endif- return (memcmp(magic, buf, 28) == 0)? 1 : 0;-}--int64_t bgzf_seek(BGZF* fp, int64_t pos, int where)-{- int block_offset;- int64_t block_address;-- if (fp->open_mode != 'r') {- report_error(fp, "file not open for read");- return -1;- }- if (where != SEEK_SET) {- report_error(fp, "unimplemented seek option");- return -1;- }- block_offset = pos & 0xFFFF;- block_address = (pos >> 16) & 0xFFFFFFFFFFFFLL;-#ifdef _USE_KNETFILE- if (knet_seek(fp->x.fpr, block_address, SEEK_SET) != 0) {-#else- if (fseeko(fp->file, block_address, SEEK_SET) != 0) {-#endif- report_error(fp, "seek failed");- return -1;- }- fp->block_length = 0; // indicates current block is not loaded- fp->block_address = block_address;- fp->block_offset = block_offset;- return 0;-}
− samtools-0.1.13/bgzf.h
@@ -1,157 +0,0 @@-/* The MIT License-- Copyright (c) 2008 Broad Institute / Massachusetts Institute of Technology-- 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.-*/--#ifndef __BGZF_H-#define __BGZF_H--#include <stdint.h>-#include <stdio.h>-#include <stdbool.h>-#include <zlib.h>-#ifdef _USE_KNETFILE-#include "knetfile.h"-#endif--//typedef int8_t bool;--typedef struct {- int file_descriptor;- char open_mode; // 'r' or 'w'- bool owned_file, is_uncompressed;-#ifdef _USE_KNETFILE- union {- knetFile *fpr;- FILE *fpw;- } x;-#else- FILE* file;-#endif- int uncompressed_block_size;- int compressed_block_size;- void* uncompressed_block;- void* compressed_block;- int64_t block_address;- int block_length;- int block_offset;- int cache_size;- const char* error;- void *cache; // a pointer to a hash table-} BGZF;--#ifdef __cplusplus-extern "C" {-#endif--/*- * Open an existing file descriptor for reading or writing.- * Mode must be either "r" or "w".- * A subsequent bgzf_close will not close the file descriptor.- * Returns null on error.- */-BGZF* bgzf_fdopen(int fd, const char* __restrict mode);--/*- * Open the specified file for reading or writing.- * Mode must be either "r" or "w".- * Returns null on error.- */-BGZF* bgzf_open(const char* path, const char* __restrict mode);--/*- * Close the BGZ file and free all associated resources.- * Does not close the underlying file descriptor if created with bgzf_fdopen.- * Returns zero on success, -1 on error.- */-int bgzf_close(BGZF* fp);--/*- * Read up to length bytes from the file storing into data.- * Returns the number of bytes actually read.- * Returns zero on end of file.- * Returns -1 on error.- */-int bgzf_read(BGZF* fp, void* data, int length);--/*- * Write length bytes from data to the file.- * Returns the number of bytes written.- * Returns -1 on error.- */-int bgzf_write(BGZF* fp, const void* data, int length);--/*- * Return a virtual file pointer to the current location in the file.- * No interpetation of the value should be made, other than a subsequent- * call to bgzf_seek can be used to position the file at the same point.- * Return value is non-negative on success.- * Returns -1 on error.- */-#define bgzf_tell(fp) ((fp->block_address << 16) | (fp->block_offset & 0xFFFF))--/*- * Set the file to read from the location specified by pos, which must- * be a value previously returned by bgzf_tell for this file (but not- * necessarily one returned by this file handle).- * The where argument must be SEEK_SET.- * Seeking on a file opened for write is not supported.- * Returns zero on success, -1 on error.- */-int64_t bgzf_seek(BGZF* fp, int64_t pos, int where);--/*- * Set the cache size. Zero to disable. By default, caching is- * disabled. The recommended cache size for frequent random access is- * about 8M bytes.- */-void bgzf_set_cache_size(BGZF *fp, int cache_size);--int bgzf_check_EOF(BGZF *fp);-int bgzf_read_block(BGZF* fp);-int bgzf_flush(BGZF* fp);-int bgzf_flush_try(BGZF *fp, int size);--#ifdef __cplusplus-}-#endif--static inline int bgzf_getc(BGZF *fp)-{- int c;- if (fp->block_offset >= fp->block_length) {- if (bgzf_read_block(fp) != 0) return -2; /* error */- if (fp->block_length == 0) return -1; /* end-of-file */- }- c = ((unsigned char*)fp->uncompressed_block)[fp->block_offset++];- if (fp->block_offset == fp->block_length) {-#ifdef _USE_KNETFILE- fp->block_address = knet_tell(fp->x.fpr);-#else- fp->block_address = ftello(fp->file);-#endif- fp->block_offset = 0;- fp->block_length = 0;- }- return c;-}--#endif
− samtools-0.1.13/errmod.c
@@ -1,130 +0,0 @@-#include <math.h>-#include "errmod.h"-#include "ksort.h"-KSORT_INIT_GENERIC(uint16_t)--typedef struct __errmod_coef_t {- double *fk, *beta, *lhet;-} errmod_coef_t;--typedef struct {- double fsum[16], bsum[16];- uint32_t c[16];-} call_aux_t;--static errmod_coef_t *cal_coef(double depcorr, double eta)-{- int k, n, q;- long double sum, sum1;- double *lC;- errmod_coef_t *ec;-- ec = calloc(1, sizeof(errmod_coef_t));- // initialize ->fk- ec->fk = (double*)calloc(256, sizeof(double));- ec->fk[0] = 1.0;- for (n = 1; n != 256; ++n)- ec->fk[n] = pow(1. - depcorr, n) * (1.0 - eta) + eta;- // initialize ->coef- ec->beta = (double*)calloc(256 * 256 * 64, sizeof(double));- lC = (double*)calloc(256 * 256, sizeof(double));- for (n = 1; n != 256; ++n) {- double lgn = lgamma(n+1);- for (k = 1; k <= n; ++k)- lC[n<<8|k] = lgn - lgamma(k+1) - lgamma(n-k+1);- }- for (q = 1; q != 64; ++q) {- double e = pow(10.0, -q/10.0);- double le = log(e);- double le1 = log(1.0 - e);- for (n = 1; n <= 255; ++n) {- double *beta = ec->beta + (q<<16|n<<8);- sum1 = sum = 0.0;- for (k = n; k >= 0; --k, sum1 = sum) {- sum = sum1 + expl(lC[n<<8|k] + k*le + (n-k)*le1);- beta[k] = -10. / M_LN10 * logl(sum1 / sum);- }- }- }- // initialize ->lhet- ec->lhet = (double*)calloc(256 * 256, sizeof(double));- for (n = 0; n < 256; ++n)- for (k = 0; k < 256; ++k)- ec->lhet[n<<8|k] = lC[n<<8|k] - M_LN2 * n;- free(lC);- return ec;-}--errmod_t *errmod_init(float depcorr)-{- errmod_t *em;- em = (errmod_t*)calloc(1, sizeof(errmod_t));- em->depcorr = depcorr;- em->coef = cal_coef(depcorr, 0.03);- return em;-}--void errmod_destroy(errmod_t *em)-{- if (em == 0) return;- free(em->coef->lhet); free(em->coef->fk); free(em->coef->beta);- free(em->coef); free(em);-}-// qual:6, strand:1, base:4-int errmod_cal(const errmod_t *em, int n, int m, uint16_t *bases, float *q)-{- call_aux_t aux;- int i, j, k, w[32];-- if (m > m) return -1;- memset(q, 0, m * m * sizeof(float));- if (n == 0) return 0;- // calculate aux.esum and aux.fsum- if (n > 255) { // then sample 255 bases- ks_shuffle(uint16_t, n, bases);- n = 255;- }- ks_introsort(uint16_t, n, bases);- memset(w, 0, 32 * sizeof(int));- memset(&aux, 0, sizeof(call_aux_t));- for (j = n - 1; j >= 0; --j) { // calculate esum and fsum- uint16_t b = bases[j];- int q = b>>5 < 4? 4 : b>>5;- if (q > 63) q = 63;- k = b&0x1f;- aux.fsum[k&0xf] += em->coef->fk[w[k]];- aux.bsum[k&0xf] += em->coef->fk[w[k]] * em->coef->beta[q<<16|n<<8|aux.c[k&0xf]];- ++aux.c[k&0xf];- ++w[k];- }- // generate likelihood- for (j = 0; j != m; ++j) {- float tmp1, tmp3;- int tmp2, bar_e;- // homozygous- for (k = 0, tmp1 = tmp3 = 0.0, tmp2 = 0; k != m; ++k) {- if (k == j) continue;- tmp1 += aux.bsum[k]; tmp2 += aux.c[k]; tmp3 += aux.fsum[k];- }- if (tmp2) {- bar_e = (int)(tmp1 / tmp3 + 0.499);- if (bar_e > 63) bar_e = 63;- q[j*m+j] = tmp1;- }- // heterozygous- for (k = j + 1; k < m; ++k) {- int cjk = aux.c[j] + aux.c[k];- for (i = 0, tmp2 = 0, tmp1 = tmp3 = 0.0; i < m; ++i) {- if (i == j || i == k) continue;- tmp1 += aux.bsum[i]; tmp2 += aux.c[i]; tmp3 += aux.fsum[i];- }- if (tmp2) {- bar_e = (int)(tmp1 / tmp3 + 0.499);- if (bar_e > 63) bar_e = 63;- q[j*m+k] = q[k*m+j] = -4.343 * em->coef->lhet[cjk<<8|aux.c[k]] + tmp1;- } else q[j*m+k] = q[k*m+j] = -4.343 * em->coef->lhet[cjk<<8|aux.c[k]]; // all the bases are either j or k- }- for (k = 0; k != m; ++k) if (q[j*m+k] < 0.0) q[j*m+k] = 0.0;- }- return 0;-}
− samtools-0.1.13/errmod.h
@@ -1,24 +0,0 @@-#ifndef ERRMOD_H-#define ERRMOD_H--#include <stdint.h>--struct __errmod_coef_t;--typedef struct {- double depcorr;- struct __errmod_coef_t *coef;-} errmod_t;--errmod_t *errmod_init(float depcorr);-void errmod_destroy(errmod_t *em);--/*- n: number of bases- m: maximum base- bases[i]: qual:6, strand:1, base:4- q[i*m+j]: phred-scaled likelihood of (i,j)- */-int errmod_cal(const errmod_t *em, int n, int m, uint16_t *bases, float *q);--#endif
− samtools-0.1.13/faidx.c
@@ -1,423 +0,0 @@-#include <ctype.h>-#include <string.h>-#include <stdlib.h>-#include <stdio.h>-#include <stdint.h>-#include "faidx.h"-#include "khash.h"--typedef struct {- uint64_t len:32, line_len:16, line_blen:16;- uint64_t offset;-} faidx1_t;-KHASH_MAP_INIT_STR(s, faidx1_t)--#ifndef _NO_RAZF-#include "razf.h"-#else-#ifdef _WIN32-#define ftello(fp) ftell(fp)-#define fseeko(fp, offset, whence) fseek(fp, offset, whence)-#else-extern off_t ftello(FILE *stream);-extern int fseeko(FILE *stream, off_t offset, int whence);-#endif-#define RAZF FILE-#define razf_read(fp, buf, size) fread(buf, 1, size, fp)-#define razf_open(fn, mode) fopen(fn, mode)-#define razf_close(fp) fclose(fp)-#define razf_seek(fp, offset, whence) fseeko(fp, offset, whence)-#define razf_tell(fp) ftello(fp)-#endif-#ifdef _USE_KNETFILE-#include "knetfile.h"-#endif--struct __faidx_t {- RAZF *rz;- int n, m;- char **name;- khash_t(s) *hash;-};--#ifndef kroundup32-#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))-#endif--static inline void fai_insert_index(faidx_t *idx, const char *name, int len, int line_len, int line_blen, uint64_t offset)-{- khint_t k;- int ret;- faidx1_t t;- if (idx->n == idx->m) {- idx->m = idx->m? idx->m<<1 : 16;- idx->name = (char**)realloc(idx->name, sizeof(void*) * idx->m);- }- idx->name[idx->n] = strdup(name);- k = kh_put(s, idx->hash, idx->name[idx->n], &ret);- t.len = len; t.line_len = line_len; t.line_blen = line_blen; t.offset = offset;- kh_value(idx->hash, k) = t;- ++idx->n;-}--faidx_t *fai_build_core(RAZF *rz)-{- char c, *name;- int l_name, m_name, ret;- int len, line_len, line_blen, state;- int l1, l2;- faidx_t *idx;- uint64_t offset;-- idx = (faidx_t*)calloc(1, sizeof(faidx_t));- idx->hash = kh_init(s);- name = 0; l_name = m_name = 0;- len = line_len = line_blen = -1; state = 0; l1 = l2 = -1; offset = 0;- while (razf_read(rz, &c, 1)) {- if (c == '\n') { // an empty line- if (state == 1) {- offset = razf_tell(rz);- continue;- } else if ((state == 0 && len < 0) || state == 2) continue;- }- if (c == '>') { // fasta header- if (len >= 0)- fai_insert_index(idx, name, len, line_len, line_blen, offset);- l_name = 0;- while ((ret = razf_read(rz, &c, 1)) != 0 && !isspace(c)) {- if (m_name < l_name + 2) {- m_name = l_name + 2;- kroundup32(m_name);- name = (char*)realloc(name, m_name);- }- name[l_name++] = c;- }- name[l_name] = '\0';- if (ret == 0) {- fprintf(stderr, "[fai_build_core] the last entry has no sequence\n");- free(name); fai_destroy(idx);- return 0;- }- if (c != '\n') while (razf_read(rz, &c, 1) && c != '\n');- state = 1; len = 0;- offset = razf_tell(rz);- } else {- if (state == 3) {- fprintf(stderr, "[fai_build_core] inlined empty line is not allowed in sequence '%s'.\n", name);- free(name); fai_destroy(idx);- return 0;- }- if (state == 2) state = 3;- l1 = l2 = 0;- do {- ++l1;- if (isgraph(c)) ++l2;- } while ((ret = razf_read(rz, &c, 1)) && c != '\n');- if (state == 3 && l2) {- fprintf(stderr, "[fai_build_core] different line length in sequence '%s'.\n", name);- free(name); fai_destroy(idx);- return 0;- }- ++l1; len += l2;- if (l2 >= 0x10000) {- fprintf(stderr, "[fai_build_core] line length exceeds 65535 in sequence '%s'.\n", name);- free(name); fai_destroy(idx);- return 0;- }- if (state == 1) line_len = l1, line_blen = l2, state = 0;- else if (state == 0) {- if (l1 != line_len || l2 != line_blen) state = 2;- }- }- }- fai_insert_index(idx, name, len, line_len, line_blen, offset);- free(name);- return idx;-}--void fai_save(const faidx_t *fai, FILE *fp)-{- khint_t k;- int i;- for (i = 0; i < fai->n; ++i) {- faidx1_t x;- k = kh_get(s, fai->hash, fai->name[i]);- x = kh_value(fai->hash, k);-#ifdef _WIN32- fprintf(fp, "%s\t%d\t%ld\t%d\t%d\n", fai->name[i], (int)x.len, (long)x.offset, (int)x.line_blen, (int)x.line_len);-#else- fprintf(fp, "%s\t%d\t%lld\t%d\t%d\n", fai->name[i], (int)x.len, (long long)x.offset, (int)x.line_blen, (int)x.line_len);-#endif- }-}--faidx_t *fai_read(FILE *fp)-{- faidx_t *fai;- char *buf, *p;- int len, line_len, line_blen;-#ifdef _WIN32- long offset;-#else- long long offset;-#endif- fai = (faidx_t*)calloc(1, sizeof(faidx_t));- fai->hash = kh_init(s);- buf = (char*)calloc(0x10000, 1);- while (!feof(fp) && fgets(buf, 0x10000, fp)) {- for (p = buf; *p && isgraph(*p); ++p);- *p = 0; ++p;-#ifdef _WIN32- sscanf(p, "%d%ld%d%d", &len, &offset, &line_blen, &line_len);-#else- sscanf(p, "%d%lld%d%d", &len, &offset, &line_blen, &line_len);-#endif- fai_insert_index(fai, buf, len, line_len, line_blen, offset);- }- free(buf);- return fai;-}--void fai_destroy(faidx_t *fai)-{- int i;- for (i = 0; i < fai->n; ++i) free(fai->name[i]);- free(fai->name);- kh_destroy(s, fai->hash);- if (fai->rz) razf_close(fai->rz);- free(fai);-}--int fai_build(const char *fn)-{- char *str;- RAZF *rz;- FILE *fp;- faidx_t *fai;- str = (char*)calloc(strlen(fn) + 5, 1);- sprintf(str, "%s.fai", fn);- rz = razf_open(fn, "r");- if (rz == 0) {- fprintf(stderr, "[fai_build] fail to open the FASTA file %s\n",fn);- free(str);- return -1;- }- fai = fai_build_core(rz);- razf_close(rz);- fp = fopen(str, "wb");- if (fp == 0) {- fprintf(stderr, "[fai_build] fail to write FASTA index %s\n",str);- fai_destroy(fai); free(str);- return -1;- }- fai_save(fai, fp);- fclose(fp);- free(str);- fai_destroy(fai);- return 0;-}--#ifdef _USE_KNETFILE-FILE *download_and_open(const char *fn)-{- const int buf_size = 1 * 1024 * 1024;- uint8_t *buf;- FILE *fp;- knetFile *fp_remote;- const char *url = fn;- const char *p;- int l = strlen(fn);- for (p = fn + l - 1; p >= fn; --p)- if (*p == '/') break;- fn = p + 1;-- // First try to open a local copy- fp = fopen(fn, "r");- if (fp)- return fp;-- // If failed, download from remote and open- fp_remote = knet_open(url, "rb");- if (fp_remote == 0) {- fprintf(stderr, "[download_from_remote] fail to open remote file %s\n",url);- return NULL;- }- if ((fp = fopen(fn, "wb")) == 0) {- fprintf(stderr, "[download_from_remote] fail to create file in the working directory %s\n",fn);- knet_close(fp_remote);- return NULL;- }- buf = (uint8_t*)calloc(buf_size, 1);- while ((l = knet_read(fp_remote, buf, buf_size)) != 0)- fwrite(buf, 1, l, fp);- free(buf);- fclose(fp);- knet_close(fp_remote);-- return fopen(fn, "r");-}-#endif--faidx_t *fai_load(const char *fn)-{- char *str;- FILE *fp;- faidx_t *fai;- str = (char*)calloc(strlen(fn) + 5, 1);- sprintf(str, "%s.fai", fn);--#ifdef _USE_KNETFILE- if (strstr(fn, "ftp://") == fn || strstr(fn, "http://") == fn)- {- fp = download_and_open(str);- if ( !fp )- {- fprintf(stderr, "[fai_load] failed to open remote FASTA index %s\n", str);- free(str);- return 0;- }- }- else-#endif- fp = fopen(str, "rb");- if (fp == 0) {- fprintf(stderr, "[fai_load] build FASTA index.\n");- fai_build(fn);- fp = fopen(str, "rb");- if (fp == 0) {- fprintf(stderr, "[fai_load] fail to open FASTA index.\n");- free(str);- return 0;- }- }-- fai = fai_read(fp);- fclose(fp);-- fai->rz = razf_open(fn, "rb");- free(str);- if (fai->rz == 0) {- fprintf(stderr, "[fai_load] fail to open FASTA file.\n");- return 0;- }- return fai;-}--char *fai_fetch(const faidx_t *fai, const char *str, int *len)-{- char *s, *p, c;- int i, l, k;- khiter_t iter;- faidx1_t val;- khash_t(s) *h;- int beg, end;-- beg = end = -1;- h = fai->hash;- l = strlen(str);- p = s = (char*)malloc(l+1);- /* squeeze out "," */- for (i = k = 0; i != l; ++i)- if (str[i] != ',' && !isspace(str[i])) s[k++] = str[i];- s[k] = 0;- for (i = 0; i != k; ++i) if (s[i] == ':') break;- s[i] = 0;- iter = kh_get(s, h, s); /* get the ref_id */- if (iter == kh_end(h)) {- *len = 0;- free(s); return 0;- }- val = kh_value(h, iter);- if (i == k) { /* dump the whole sequence */- beg = 0; end = val.len;- } else {- for (p = s + i + 1; i != k; ++i) if (s[i] == '-') break;- beg = atoi(p);- if (i < k) {- p = s + i + 1;- end = atoi(p);- } else end = val.len;- }- if (beg > 0) --beg;- if (beg >= val.len) beg = val.len;- if (end >= val.len) end = val.len;- if (beg > end) beg = end;- free(s);-- // now retrieve the sequence- l = 0;- s = (char*)malloc(end - beg + 2);- razf_seek(fai->rz, val.offset + beg / val.line_blen * val.line_len + beg % val.line_blen, SEEK_SET);- while (razf_read(fai->rz, &c, 1) == 1 && l < end - beg && !fai->rz->z_err)- if (isgraph(c)) s[l++] = c;- s[l] = '\0';- *len = l;- return s;-}--int faidx_main(int argc, char *argv[])-{- if (argc == 1) {- fprintf(stderr, "Usage: faidx <in.fasta> [<reg> [...]]\n");- return 1;- } else {- if (argc == 2) fai_build(argv[1]);- else {- int i, j, k, l;- char *s;- faidx_t *fai;- fai = fai_load(argv[1]);- if (fai == 0) return 1;- for (i = 2; i != argc; ++i) {- printf(">%s\n", argv[i]);- s = fai_fetch(fai, argv[i], &l);- for (j = 0; j < l; j += 60) {- for (k = 0; k < 60 && k < l - j; ++k)- putchar(s[j + k]);- putchar('\n');- }- free(s);- }- fai_destroy(fai);- }- }- return 0;-}--int faidx_fetch_nseq(const faidx_t *fai) -{- return fai->n;-}--char *faidx_fetch_seq(const faidx_t *fai, char *c_name, int p_beg_i, int p_end_i, int *len)-{- int l;- char c;- khiter_t iter;- faidx1_t val;- char *seq=NULL;-- // Adjust position- iter = kh_get(s, fai->hash, c_name);- if(iter == kh_end(fai->hash)) return 0;- val = kh_value(fai->hash, iter);- if(p_end_i < p_beg_i) p_beg_i = p_end_i;- if(p_beg_i < 0) p_beg_i = 0;- else if(val.len <= p_beg_i) p_beg_i = val.len - 1;- if(p_end_i < 0) p_end_i = 0;- else if(val.len <= p_end_i) p_end_i = val.len - 1;-- // Now retrieve the sequence - l = 0;- seq = (char*)malloc(p_end_i - p_beg_i + 2);- razf_seek(fai->rz, val.offset + p_beg_i / val.line_blen * val.line_len + p_beg_i % val.line_blen, SEEK_SET);- while (razf_read(fai->rz, &c, 1) == 1 && l < p_end_i - p_beg_i + 1)- if (isgraph(c)) seq[l++] = c;- seq[l] = '\0';- *len = l;- return seq;-}--#ifdef FAIDX_MAIN-int main(int argc, char *argv[]) { return faidx_main(argc, argv); }-#endif
− samtools-0.1.13/faidx.h
@@ -1,103 +0,0 @@-/* The MIT License-- Copyright (c) 2008 Genome Research Ltd (GRL).-- 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.-*/--/* Contact: Heng Li <lh3@sanger.ac.uk> */--#ifndef FAIDX_H-#define FAIDX_H--/*!- @header-- Index FASTA files and extract subsequence.-- @copyright The Wellcome Trust Sanger Institute.- */--struct __faidx_t;-typedef struct __faidx_t faidx_t;--#ifdef __cplusplus-extern "C" {-#endif-- /*!- @abstract Build index for a FASTA or razip compressed FASTA file.- @param fn FASTA file name- @return 0 on success; or -1 on failure- @discussion File "fn.fai" will be generated.- */- int fai_build(const char *fn);-- /*!- @abstract Distroy a faidx_t struct.- @param fai Pointer to the struct to be destroyed- */- void fai_destroy(faidx_t *fai);-- /*!- @abstract Load index from "fn.fai".- @param fn File name of the FASTA file- */- faidx_t *fai_load(const char *fn);-- /*!- @abstract Fetch the sequence in a region.- @param fai Pointer to the faidx_t struct- @param reg Region in the format "chr2:20,000-30,000"- @param len Length of the region- @return Pointer to the sequence; null on failure-- @discussion The returned sequence is allocated by malloc family- and should be destroyed by end users by calling free() on it.- */- char *fai_fetch(const faidx_t *fai, const char *reg, int *len);-- /*!- @abstract Fetch the number of sequences. - @param fai Pointer to the faidx_t struct- @return The number of sequences- */- int faidx_fetch_nseq(const faidx_t *fai);-- /*!- @abstract Fetch the sequence in a region.- @param fai Pointer to the faidx_t struct- @param c_name Region name- @param p_beg_i Beginning position number (zero-based)- @param p_end_i End position number (zero-based)- @param len Length of the region- @return Pointer to the sequence; null on failure-- @discussion The returned sequence is allocated by malloc family- and should be destroyed by end users by calling free() on it.- */- char *faidx_fetch_seq(const faidx_t *fai, char *c_name, int p_beg_i, int p_end_i, int *len);--#ifdef __cplusplus-}-#endif--#endif
− samtools-0.1.13/glf.c
@@ -1,236 +0,0 @@-#include <string.h>-#include <stdlib.h>-#include "glf.h"--#ifdef _NO_BGZF-// then alias bgzf_*() functions-#endif--static int glf3_is_BE = 0;--static inline uint32_t bam_swap_endian_4(uint32_t v)-{- v = ((v & 0x0000FFFFU) << 16) | (v >> 16);- return ((v & 0x00FF00FFU) << 8) | ((v & 0xFF00FF00U) >> 8);-}--static inline uint16_t bam_swap_endian_2(uint16_t v)-{- return (uint16_t)(((v & 0x00FF00FFU) << 8) | ((v & 0xFF00FF00U) >> 8));-}--static inline int bam_is_big_endian()-{- long one= 1;- return !(*((char *)(&one)));-}--glf3_header_t *glf3_header_init()-{- glf3_is_BE = bam_is_big_endian();- return (glf3_header_t*)calloc(1, sizeof(glf3_header_t));-}--glf3_header_t *glf3_header_read(glfFile fp)-{- glf3_header_t *h;- char magic[4];- h = glf3_header_init();- bgzf_read(fp, magic, 4);- if (strncmp(magic, "GLF\3", 4)) {- fprintf(stderr, "[glf3_header_read] invalid magic.\n");- glf3_header_destroy(h);- return 0;- }- bgzf_read(fp, &h->l_text, 4);- if (glf3_is_BE) h->l_text = bam_swap_endian_4(h->l_text);- if (h->l_text) {- h->text = (uint8_t*)calloc(h->l_text + 1, 1);- bgzf_read(fp, h->text, h->l_text);- }- return h;-}--void glf3_header_write(glfFile fp, const glf3_header_t *h)-{- int32_t x;- bgzf_write(fp, "GLF\3", 4);- x = glf3_is_BE? bam_swap_endian_4(h->l_text) : h->l_text;- bgzf_write(fp, &x, 4);- if (h->l_text) bgzf_write(fp, h->text, h->l_text);-}--void glf3_header_destroy(glf3_header_t *h)-{- free(h->text);- free(h);-}--char *glf3_ref_read(glfFile fp, int *len)-{- int32_t n, x;- char *str;- *len = 0;- if (bgzf_read(fp, &n, 4) != 4) return 0;- if (glf3_is_BE) n = bam_swap_endian_4(n);- if (n < 0) {- fprintf(stderr, "[glf3_ref_read] invalid reference name length: %d.\n", n);- return 0;- }- str = (char*)calloc(n + 1, 1); // not necesarily n+1 in fact- x = bgzf_read(fp, str, n);- x += bgzf_read(fp, len, 4);- if (x != n + 4) {- free(str); *len = -1; return 0; // truncated- }- if (glf3_is_BE) *len = bam_swap_endian_4(*len);- return str;-}--void glf3_ref_write(glfFile fp, const char *str, int len)-{- int32_t m, n = strlen(str) + 1;- m = glf3_is_BE? bam_swap_endian_4(n) : n;- bgzf_write(fp, &m, 4);- bgzf_write(fp, str, n);- if (glf3_is_BE) len = bam_swap_endian_4(len);- bgzf_write(fp, &len, 4);-}--void glf3_view1(const char *ref_name, const glf3_t *g3, int pos)-{- int j;- if (g3->rtype == GLF3_RTYPE_END) return;- printf("%s\t%d\t%c\t%d\t%d\t%d", ref_name, pos + 1,- g3->rtype == GLF3_RTYPE_INDEL? '*' : "XACMGRSVTWYHKDBN"[g3->ref_base],- g3->depth, g3->rms_mapQ, g3->min_lk);- if (g3->rtype == GLF3_RTYPE_SUB)- for (j = 0; j != 10; ++j) printf("\t%d", g3->lk[j]);- else {- printf("\t%d\t%d\t%d\t%d\t%d\t%s\t%s\t", g3->lk[0], g3->lk[1], g3->lk[2], g3->indel_len[0], g3->indel_len[1],- g3->indel_len[0]? g3->indel_seq[0] : "*", g3->indel_len[1]? g3->indel_seq[1] : "*");- }- printf("\n");-}--int glf3_write1(glfFile fp, const glf3_t *g3)-{- int r;- uint8_t c;- uint32_t y[2];- c = g3->rtype<<4 | g3->ref_base;- r = bgzf_write(fp, &c, 1);- if (g3->rtype == GLF3_RTYPE_END) return r;- y[0] = g3->offset;- y[1] = g3->min_lk<<24 | g3->depth;- if (glf3_is_BE) {- y[0] = bam_swap_endian_4(y[0]);- y[1] = bam_swap_endian_4(y[1]);- }- r += bgzf_write(fp, y, 8);- r += bgzf_write(fp, &g3->rms_mapQ, 1);- if (g3->rtype == GLF3_RTYPE_SUB) r += bgzf_write(fp, g3->lk, 10);- else {- int16_t x[2];- r += bgzf_write(fp, g3->lk, 3);- x[0] = glf3_is_BE? bam_swap_endian_2(g3->indel_len[0]) : g3->indel_len[0];- x[1] = glf3_is_BE? bam_swap_endian_2(g3->indel_len[1]) : g3->indel_len[1];- r += bgzf_write(fp, x, 4);- if (g3->indel_len[0]) r += bgzf_write(fp, g3->indel_seq[0], abs(g3->indel_len[0]));- if (g3->indel_len[1]) r += bgzf_write(fp, g3->indel_seq[1], abs(g3->indel_len[1]));- }- return r;-}--#ifndef kv_roundup32-#define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))-#endif--int glf3_read1(glfFile fp, glf3_t *g3)-{- int r;- uint8_t c;- uint32_t y[2];- r = bgzf_read(fp, &c, 1);- if (r == 0) return 0;- g3->ref_base = c & 0xf;- g3->rtype = c>>4;- if (g3->rtype == GLF3_RTYPE_END) return r;- r += bgzf_read(fp, y, 8);- if (glf3_is_BE) {- y[0] = bam_swap_endian_4(y[0]);- y[1] = bam_swap_endian_4(y[1]);- }- g3->offset = y[0];- g3->min_lk = y[1]>>24;- g3->depth = y[1]<<8>>8;- r += bgzf_read(fp, &g3->rms_mapQ, 1);- if (g3->rtype == GLF3_RTYPE_SUB) r += bgzf_read(fp, g3->lk, 10);- else {- int16_t x[2], max;- r += bgzf_read(fp, g3->lk, 3);- r += bgzf_read(fp, x, 4);- if (glf3_is_BE) {- x[0] = bam_swap_endian_2(x[0]);- x[1] = bam_swap_endian_2(x[1]);- }- g3->indel_len[0] = x[0];- g3->indel_len[1] = x[1];- x[0] = abs(x[0]); x[1] = abs(x[1]);- max = (x[0] > x[1]? x[0] : x[1]) + 1;- if (g3->max_len < max) {- g3->max_len = max;- kv_roundup32(g3->max_len);- g3->indel_seq[0] = (char*)realloc(g3->indel_seq[0], g3->max_len);- g3->indel_seq[1] = (char*)realloc(g3->indel_seq[1], g3->max_len);- }- r += bgzf_read(fp, g3->indel_seq[0], x[0]);- r += bgzf_read(fp, g3->indel_seq[1], x[1]);- g3->indel_seq[0][x[0]] = g3->indel_seq[1][x[1]] = 0;- }- return r;-}--void glf3_view(glfFile fp)-{- glf3_header_t *h;- char *name;- glf3_t *g3;- int len;- h = glf3_header_read(fp);- g3 = glf3_init1();- while ((name = glf3_ref_read(fp, &len)) != 0) {- int pos = 0;- while (glf3_read1(fp, g3) && g3->rtype != GLF3_RTYPE_END) {- pos += g3->offset;- glf3_view1(name, g3, pos);- }- free(name);- }- glf3_header_destroy(h);- glf3_destroy1(g3);-}--int glf3_view_main(int argc, char *argv[])-{- glfFile fp;- if (argc == 1) {- fprintf(stderr, "Usage: glfview <in.glf>\n");- return 1;- }- fp = (strcmp(argv[1], "-") == 0)? bgzf_fdopen(fileno(stdin), "r") : bgzf_open(argv[1], "r");- if (fp == 0) {- fprintf(stderr, "Fail to open file '%s'\n", argv[1]);- return 1;- }- glf3_view(fp);- bgzf_close(fp);- return 0;-}--#ifdef GLFVIEW_MAIN-int main(int argc, char *argv[])-{- return glf3_view_main(argc, argv);-}-#endif
− samtools-0.1.13/glf.h
@@ -1,56 +0,0 @@-#ifndef GLF_H_-#define GLF_H_--typedef struct {- unsigned char ref_base:4, dummy:4; /** "XACMGRSVTWYHKDBN"[ref_base] gives the reference base */- unsigned char max_mapQ; /** maximum mapping quality */- unsigned char lk[10]; /** log likelihood ratio, capped at 255 */- unsigned min_lk:8, depth:24; /** minimum lk capped at 255, and the number of mapped reads */-} glf1_t;--#include <stdint.h>-#include "bgzf.h"-typedef BGZF *glfFile;--#define GLF3_RTYPE_END 0-#define GLF3_RTYPE_SUB 1-#define GLF3_RTYPE_INDEL 2--typedef struct {- uint8_t ref_base:4, rtype:4; /** "XACMGRSVTWYHKDBN"[ref_base] gives the reference base */- uint8_t rms_mapQ; /** RMS mapping quality */- uint8_t lk[10]; /** log likelihood ratio, capped at 255 */- uint32_t min_lk:8, depth:24; /** minimum lk capped at 255, and the number of mapped reads */- int32_t offset; /** the first base in a chromosome has offset zero. */- // for indel (lkHom1, lkHom2 and lkHet are the first three elements in lk[10])- int16_t indel_len[2];- int32_t max_len; // maximum indel len; will be modified by glf3_read1()- char *indel_seq[2];-} glf3_t;--typedef struct {- int32_t l_text;- uint8_t *text;-} glf3_header_t;--#ifdef __cplusplus-extern "C" {-#endif--#define glf3_init1() ((glf3_t*)calloc(1, sizeof(glf3_t)))-#define glf3_destroy1(g3) do { free((g3)->indel_seq[0]); free((g3)->indel_seq[1]); free(g3); } while (0)-- glf3_header_t *glf3_header_init();- glf3_header_t *glf3_header_read(glfFile fp);- void glf3_header_write(glfFile fp, const glf3_header_t *h);- void glf3_header_destroy(glf3_header_t *h);- char *glf3_ref_read(glfFile fp, int *len);- void glf3_ref_write(glfFile fp, const char *name, int len);- int glf3_write1(glfFile fp, const glf3_t *g3);- int glf3_read1(glfFile fp, glf3_t *g3);--#ifdef __cplusplus-}-#endif--#endif
− samtools-0.1.13/kaln.c
@@ -1,486 +0,0 @@-/* The MIT License-- Copyright (c) 2003-2006, 2008, 2009, by Heng Li <lh3lh3@gmail.com>-- 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.-*/--#include <stdlib.h>-#include <stdio.h>-#include <string.h>-#include <stdint.h>-#include <math.h>-#include "kaln.h"--#define FROM_M 0-#define FROM_I 1-#define FROM_D 2--typedef struct {- int i, j;- unsigned char ctype;-} path_t;--int aln_sm_blosum62[] = {-/* A R N D C Q E G H I L K M F P S T W Y V * X */- 4,-1,-2,-2, 0,-1,-1, 0,-2,-1,-1,-1,-1,-2,-1, 1, 0,-3,-2, 0,-4, 0,- -1, 5, 0,-2,-3, 1, 0,-2, 0,-3,-2, 2,-1,-3,-2,-1,-1,-3,-2,-3,-4,-1,- -2, 0, 6, 1,-3, 0, 0, 0, 1,-3,-3, 0,-2,-3,-2, 1, 0,-4,-2,-3,-4,-1,- -2,-2, 1, 6,-3, 0, 2,-1,-1,-3,-4,-1,-3,-3,-1, 0,-1,-4,-3,-3,-4,-1,- 0,-3,-3,-3, 9,-3,-4,-3,-3,-1,-1,-3,-1,-2,-3,-1,-1,-2,-2,-1,-4,-2,- -1, 1, 0, 0,-3, 5, 2,-2, 0,-3,-2, 1, 0,-3,-1, 0,-1,-2,-1,-2,-4,-1,- -1, 0, 0, 2,-4, 2, 5,-2, 0,-3,-3, 1,-2,-3,-1, 0,-1,-3,-2,-2,-4,-1,- 0,-2, 0,-1,-3,-2,-2, 6,-2,-4,-4,-2,-3,-3,-2, 0,-2,-2,-3,-3,-4,-1,- -2, 0, 1,-1,-3, 0, 0,-2, 8,-3,-3,-1,-2,-1,-2,-1,-2,-2, 2,-3,-4,-1,- -1,-3,-3,-3,-1,-3,-3,-4,-3, 4, 2,-3, 1, 0,-3,-2,-1,-3,-1, 3,-4,-1,- -1,-2,-3,-4,-1,-2,-3,-4,-3, 2, 4,-2, 2, 0,-3,-2,-1,-2,-1, 1,-4,-1,- -1, 2, 0,-1,-3, 1, 1,-2,-1,-3,-2, 5,-1,-3,-1, 0,-1,-3,-2,-2,-4,-1,- -1,-1,-2,-3,-1, 0,-2,-3,-2, 1, 2,-1, 5, 0,-2,-1,-1,-1,-1, 1,-4,-1,- -2,-3,-3,-3,-2,-3,-3,-3,-1, 0, 0,-3, 0, 6,-4,-2,-2, 1, 3,-1,-4,-1,- -1,-2,-2,-1,-3,-1,-1,-2,-2,-3,-3,-1,-2,-4, 7,-1,-1,-4,-3,-2,-4,-2,- 1,-1, 1, 0,-1, 0, 0, 0,-1,-2,-2, 0,-1,-2,-1, 4, 1,-3,-2,-2,-4, 0,- 0,-1, 0,-1,-1,-1,-1,-2,-2,-1,-1,-1,-1,-2,-1, 1, 5,-2,-2, 0,-4, 0,- -3,-3,-4,-4,-2,-2,-3,-2,-2,-3,-2,-3,-1, 1,-4,-3,-2,11, 2,-3,-4,-2,- -2,-2,-2,-3,-2,-1,-2,-3, 2,-1,-1,-2,-1, 3,-3,-2,-2, 2, 7,-1,-4,-1,- 0,-3,-3,-3,-1,-2,-2,-3,-3, 3, 1,-2, 1,-1,-2,-2, 0,-3,-1, 4,-4,-1,- -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, 1,-4,- 0,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2, 0, 0,-2,-1,-1,-4,-1-};--int aln_sm_blast[] = {- 1, -3, -3, -3, -2,- -3, 1, -3, -3, -2,- -3, -3, 1, -3, -2,- -3, -3, -3, 1, -2,- -2, -2, -2, -2, -2-};--int aln_sm_qual[] = {- 0, -23, -23, -23, 0,- -23, 0, -23, -23, 0,- -23, -23, 0, -23, 0,- -23, -23, -23, 0, 0,- 0, 0, 0, 0, 0-};--ka_param_t ka_param_blast = { 5, 2, 5, 2, aln_sm_blast, 5, 50 };-ka_param_t ka_param_aa2aa = { 10, 2, 10, 2, aln_sm_blosum62, 22, 50 };--ka_param2_t ka_param2_qual = { 37, 11, 37, 11, 37, 11, 0, 0, aln_sm_qual, 5, 50 };--static uint32_t *ka_path2cigar32(const path_t *path, int path_len, int *n_cigar)-{- int i, n;- uint32_t *cigar;- unsigned char last_type;-- if (path_len == 0 || path == 0) {- *n_cigar = 0;- return 0;- }-- last_type = path->ctype;- for (i = n = 1; i < path_len; ++i) {- if (last_type != path[i].ctype) ++n;- last_type = path[i].ctype;- }- *n_cigar = n;- cigar = (uint32_t*)calloc(*n_cigar, 4);-- cigar[0] = 1u << 4 | path[path_len-1].ctype;- last_type = path[path_len-1].ctype;- for (i = path_len - 2, n = 0; i >= 0; --i) {- if (path[i].ctype == last_type) cigar[n] += 1u << 4;- else {- cigar[++n] = 1u << 4 | path[i].ctype;- last_type = path[i].ctype;- }- }-- return cigar;-}--/***************************/-/* START OF common_align.c */-/***************************/--#define SET_INF(s) (s).M = (s).I = (s).D = MINOR_INF;--#define set_M(MM, cur, p, sc) \-{ \- if ((p)->M >= (p)->I) { \- if ((p)->M >= (p)->D) { \- (MM) = (p)->M + (sc); (cur)->Mt = FROM_M; \- } else { \- (MM) = (p)->D + (sc); (cur)->Mt = FROM_D; \- } \- } else { \- if ((p)->I > (p)->D) { \- (MM) = (p)->I + (sc); (cur)->Mt = FROM_I; \- } else { \- (MM) = (p)->D + (sc); (cur)->Mt = FROM_D; \- } \- } \-}-#define set_I(II, cur, p) \-{ \- if ((p)->M - gap_open > (p)->I) { \- (cur)->It = FROM_M; \- (II) = (p)->M - gap_open - gap_ext; \- } else { \- (cur)->It = FROM_I; \- (II) = (p)->I - gap_ext; \- } \-}-#define set_end_I(II, cur, p) \-{ \- if (gap_end_ext >= 0) { \- if ((p)->M - gap_end_open > (p)->I) { \- (cur)->It = FROM_M; \- (II) = (p)->M - gap_end_open - gap_end_ext; \- } else { \- (cur)->It = FROM_I; \- (II) = (p)->I - gap_end_ext; \- } \- } else set_I(II, cur, p); \-}-#define set_D(DD, cur, p) \-{ \- if ((p)->M - gap_open > (p)->D) { \- (cur)->Dt = FROM_M; \- (DD) = (p)->M - gap_open - gap_ext; \- } else { \- (cur)->Dt = FROM_D; \- (DD) = (p)->D - gap_ext; \- } \-}-#define set_end_D(DD, cur, p) \-{ \- if (gap_end_ext >= 0) { \- if ((p)->M - gap_end_open > (p)->D) { \- (cur)->Dt = FROM_M; \- (DD) = (p)->M - gap_end_open - gap_end_ext; \- } else { \- (cur)->Dt = FROM_D; \- (DD) = (p)->D - gap_end_ext; \- } \- } else set_D(DD, cur, p); \-}--typedef struct {- uint8_t Mt:3, It:2, Dt:3;-} dpcell_t;--typedef struct {- int M, I, D;-} dpscore_t;--/***************************- * banded global alignment *- ***************************/-uint32_t *ka_global_core(uint8_t *seq1, int len1, uint8_t *seq2, int len2, const ka_param_t *ap, int *_score, int *n_cigar)-{- int i, j;- dpcell_t **dpcell, *q;- dpscore_t *curr, *last, *s;- int b1, b2, tmp_end;- int *mat, end, max = 0;- uint8_t type, ctype;- uint32_t *cigar = 0;-- int gap_open, gap_ext, gap_end_open, gap_end_ext, b;- int *score_matrix, N_MATRIX_ROW;-- /* initialize some align-related parameters. just for compatibility */- gap_open = ap->gap_open;- gap_ext = ap->gap_ext;- gap_end_open = ap->gap_end_open;- gap_end_ext = ap->gap_end_ext;- b = ap->band_width;- score_matrix = ap->matrix;- N_MATRIX_ROW = ap->row;-- if (n_cigar) *n_cigar = 0;- if (len1 == 0 || len2 == 0) return 0;-- /* calculate b1 and b2 */- if (len1 > len2) {- b1 = len1 - len2 + b;- b2 = b;- } else {- b1 = b;- b2 = len2 - len1 + b;- }- if (b1 > len1) b1 = len1;- if (b2 > len2) b2 = len2;- --seq1; --seq2;-- /* allocate memory */- end = (b1 + b2 <= len1)? (b1 + b2 + 1) : (len1 + 1);- dpcell = (dpcell_t**)malloc(sizeof(dpcell_t*) * (len2 + 1));- for (j = 0; j <= len2; ++j)- dpcell[j] = (dpcell_t*)malloc(sizeof(dpcell_t) * end);- for (j = b2 + 1; j <= len2; ++j)- dpcell[j] -= j - b2;- curr = (dpscore_t*)malloc(sizeof(dpscore_t) * (len1 + 1));- last = (dpscore_t*)malloc(sizeof(dpscore_t) * (len1 + 1));- - /* set first row */- SET_INF(*curr); curr->M = 0;- for (i = 1, s = curr + 1; i < b1; ++i, ++s) {- SET_INF(*s);- set_end_D(s->D, dpcell[0] + i, s - 1);- }- s = curr; curr = last; last = s;-- /* core dynamic programming, part 1 */- tmp_end = (b2 < len2)? b2 : len2 - 1;- for (j = 1; j <= tmp_end; ++j) {- q = dpcell[j]; s = curr; SET_INF(*s);- set_end_I(s->I, q, last);- end = (j + b1 <= len1 + 1)? (j + b1 - 1) : len1;- mat = score_matrix + seq2[j] * N_MATRIX_ROW;- ++s; ++q;- for (i = 1; i != end; ++i, ++s, ++q) {- set_M(s->M, q, last + i - 1, mat[seq1[i]]); /* this will change s->M ! */- set_I(s->I, q, last + i);- set_D(s->D, q, s - 1);- }- set_M(s->M, q, last + i - 1, mat[seq1[i]]);- set_D(s->D, q, s - 1);- if (j + b1 - 1 > len1) { /* bug fixed, 040227 */- set_end_I(s->I, q, last + i);- } else s->I = MINOR_INF;- s = curr; curr = last; last = s;- }- /* last row for part 1, use set_end_D() instead of set_D() */- if (j == len2 && b2 != len2 - 1) {- q = dpcell[j]; s = curr; SET_INF(*s);- set_end_I(s->I, q, last);- end = (j + b1 <= len1 + 1)? (j + b1 - 1) : len1;- mat = score_matrix + seq2[j] * N_MATRIX_ROW;- ++s; ++q;- for (i = 1; i != end; ++i, ++s, ++q) {- set_M(s->M, q, last + i - 1, mat[seq1[i]]); /* this will change s->M ! */- set_I(s->I, q, last + i);- set_end_D(s->D, q, s - 1);- }- set_M(s->M, q, last + i - 1, mat[seq1[i]]);- set_end_D(s->D, q, s - 1);- if (j + b1 - 1 > len1) { /* bug fixed, 040227 */- set_end_I(s->I, q, last + i);- } else s->I = MINOR_INF;- s = curr; curr = last; last = s;- ++j;- }-- /* core dynamic programming, part 2 */- for (; j <= len2 - b2 + 1; ++j) {- SET_INF(curr[j - b2]);- mat = score_matrix + seq2[j] * N_MATRIX_ROW;- end = j + b1 - 1;- for (i = j - b2 + 1, q = dpcell[j] + i, s = curr + i; i != end; ++i, ++s, ++q) {- set_M(s->M, q, last + i - 1, mat[seq1[i]]);- set_I(s->I, q, last + i);- set_D(s->D, q, s - 1);- }- set_M(s->M, q, last + i - 1, mat[seq1[i]]);- set_D(s->D, q, s - 1);- s->I = MINOR_INF;- s = curr; curr = last; last = s;- }-- /* core dynamic programming, part 3 */- for (; j < len2; ++j) {- SET_INF(curr[j - b2]);- mat = score_matrix + seq2[j] * N_MATRIX_ROW;- for (i = j - b2 + 1, q = dpcell[j] + i, s = curr + i; i < len1; ++i, ++s, ++q) {- set_M(s->M, q, last + i - 1, mat[seq1[i]]);- set_I(s->I, q, last + i);- set_D(s->D, q, s - 1);- }- set_M(s->M, q, last + len1 - 1, mat[seq1[i]]);- set_end_I(s->I, q, last + i);- set_D(s->D, q, s - 1);- s = curr; curr = last; last = s;- }- /* last row */- if (j == len2) {- SET_INF(curr[j - b2]);- mat = score_matrix + seq2[j] * N_MATRIX_ROW;- for (i = j - b2 + 1, q = dpcell[j] + i, s = curr + i; i < len1; ++i, ++s, ++q) {- set_M(s->M, q, last + i - 1, mat[seq1[i]]);- set_I(s->I, q, last + i);- set_end_D(s->D, q, s - 1);- }- set_M(s->M, q, last + len1 - 1, mat[seq1[i]]);- set_end_I(s->I, q, last + i);- set_end_D(s->D, q, s - 1);- s = curr; curr = last; last = s;- }-- *_score = last[len1].M;- if (n_cigar) { /* backtrace */- path_t *p, *path = (path_t*)malloc(sizeof(path_t) * (len1 + len2 + 2));- i = len1; j = len2;- q = dpcell[j] + i;- s = last + len1;- max = s->M; type = q->Mt; ctype = FROM_M;- if (s->I > max) { max = s->I; type = q->It; ctype = FROM_I; }- if (s->D > max) { max = s->D; type = q->Dt; ctype = FROM_D; }-- p = path;- p->ctype = ctype; p->i = i; p->j = j; /* bug fixed 040408 */- ++p;- do {- switch (ctype) {- case FROM_M: --i; --j; break;- case FROM_I: --j; break;- case FROM_D: --i; break;- }- q = dpcell[j] + i;- ctype = type;- switch (type) {- case FROM_M: type = q->Mt; break;- case FROM_I: type = q->It; break;- case FROM_D: type = q->Dt; break;- }- p->ctype = ctype; p->i = i; p->j = j;- ++p;- } while (i || j);- cigar = ka_path2cigar32(path, p - path - 1, n_cigar);- free(path);- }-- /* free memory */- for (j = b2 + 1; j <= len2; ++j)- dpcell[j] += j - b2;- for (j = 0; j <= len2; ++j)- free(dpcell[j]);- free(dpcell);- free(curr); free(last);-- return cigar;-}--typedef struct {- int M, I, D;-} score_aux_t;--#define MINUS_INF -0x40000000--// matrix: len2 rows and len1 columns-int ka_global_score(const uint8_t *_seq1, int len1, const uint8_t *_seq2, int len2, const ka_param2_t *ap)-{- -#define __score_aux(_p, _q0, _sc, _io, _ie, _do, _de) { \- int t1, t2; \- score_aux_t *_q; \- _q = _q0; \- _p->M = _q->M >= _q->I? _q->M : _q->I; \- _p->M = _p->M >= _q->D? _p->M : _q->D; \- _p->M += (_sc); \- ++_q; t1 = _q->M - _io - _ie; t2 = _q->I - _ie; _p->I = t1 >= t2? t1 : t2; \- _q = _p-1; t1 = _q->M - _do - _de; t2 = _q->D - _de; _p->D = t1 >= t2? t1 : t2; \- }-- int i, j, bw, scmat_size = ap->row, *scmat = ap->matrix, ret;- const uint8_t *seq1, *seq2;- score_aux_t *curr, *last, *swap;- bw = abs(len1 - len2) + ap->band_width;- i = len1 > len2? len1 : len2;- if (bw > i + 1) bw = i + 1;- seq1 = _seq1 - 1; seq2 = _seq2 - 1;- curr = calloc(len1 + 2, sizeof(score_aux_t));- last = calloc(len1 + 2, sizeof(score_aux_t));- { // the zero-th row- int x, end = len1;- score_aux_t *p;- j = 0;- x = j + bw; end = len1 < x? len1 : x; // band end- p = curr;- p->M = 0; p->I = p->D = MINUS_INF;- for (i = 1, p = &curr[1]; i <= end; ++i, ++p)- p->M = p->I = MINUS_INF, p->D = -(ap->edo + ap->ede * i);- p->M = p->I = p->D = MINUS_INF;- swap = curr; curr = last; last = swap;- }- for (j = 1; j < len2; ++j) {- int x, beg = 0, end = len1, *scrow, col_end;- score_aux_t *p;- x = j - bw; beg = 0 > x? 0 : x; // band start- x = j + bw; end = len1 < x? len1 : x; // band end- if (beg == 0) { // from zero-th column- p = curr;- p->M = p->D = MINUS_INF; p->I = -(ap->eio + ap->eie * j);- ++beg; // then beg = 1- }- scrow = scmat + seq2[j] * scmat_size;- if (end == len1) col_end = 1, --end;- else col_end = 0;- for (i = beg, p = &curr[beg]; i <= end; ++i, ++p)- __score_aux(p, &last[i-1], scrow[(int)seq1[i]], ap->iio, ap->iie, ap->ido, ap->ide);- if (col_end) {- __score_aux(p, &last[i-1], scrow[(int)seq1[i]], ap->eio, ap->eie, ap->ido, ap->ide);- ++p;- }- p->M = p->I = p->D = MINUS_INF;-// for (i = 0; i <= len1; ++i) printf("(%d,%d,%d) ", curr[i].M, curr[i].I, curr[i].D); putchar('\n');- swap = curr; curr = last; last = swap;- }- { // the last row- int x, beg = 0, *scrow;- score_aux_t *p;- j = len2;- x = j - bw; beg = 0 > x? 0 : x; // band start- if (beg == 0) { // from zero-th column- p = curr;- p->M = p->D = MINUS_INF; p->I = -(ap->eio + ap->eie * j);- ++beg; // then beg = 1- }- scrow = scmat + seq2[j] * scmat_size;- for (i = beg, p = &curr[beg]; i < len1; ++i, ++p)- __score_aux(p, &last[i-1], scrow[(int)seq1[i]], ap->iio, ap->iie, ap->edo, ap->ede);- __score_aux(p, &last[i-1], scrow[(int)seq1[i]], ap->eio, ap->eie, ap->edo, ap->ede);-// for (i = 0; i <= len1; ++i) printf("(%d,%d,%d) ", curr[i].M, curr[i].I, curr[i].D); putchar('\n');- }- ret = curr[len1].M >= curr[len1].I? curr[len1].M : curr[len1].I;- ret = ret >= curr[len1].D? ret : curr[len1].D;- free(curr); free(last);- return ret;-}--#ifdef _MAIN-int main(int argc, char *argv[])-{-// int len1 = 35, len2 = 35;-// uint8_t *seq1 = (uint8_t*)"\0\0\3\3\2\0\0\0\1\0\2\1\2\1\3\2\3\3\3\0\2\3\2\1\1\3\3\3\2\3\3\1\0\0\1";-// uint8_t *seq2 = (uint8_t*)"\0\0\3\3\2\0\0\0\1\0\2\1\2\1\3\2\3\3\3\0\2\3\2\1\1\3\3\3\2\3\3\1\0\1\0";- int len1 = 4, len2 = 4;- uint8_t *seq1 = (uint8_t*)"\1\0\0\1";- uint8_t *seq2 = (uint8_t*)"\1\0\1\0";- int sc;-// ka_global_core(seq1, 2, seq2, 1, &ka_param_qual, &sc, 0);- sc = ka_global_score(seq1, len1, seq2, len2, &ka_param2_qual);- printf("%d\n", sc);- return 0;-}-#endif
− samtools-0.1.13/kaln.h
@@ -1,67 +0,0 @@-/* The MIT License-- Copyright (c) 2003-2006, 2008, 2009 by Heng Li <lh3@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.-*/--#ifndef LH3_KALN_H_-#define LH3_KALN_H_--#include <stdint.h>--#define MINOR_INF -1073741823--typedef struct {- int gap_open;- int gap_ext;- int gap_end_open;- int gap_end_ext;-- int *matrix;- int row;- int band_width;-} ka_param_t;--typedef struct {- int iio, iie, ido, ide;- int eio, eie, edo, ede;- int *matrix;- int row;- int band_width;-} ka_param2_t;--#ifdef __cplusplus-extern "C" {-#endif-- uint32_t *ka_global_core(uint8_t *seq1, int len1, uint8_t *seq2, int len2, const ka_param_t *ap,- int *_score, int *n_cigar);- int ka_global_score(const uint8_t *_seq1, int len1, const uint8_t *_seq2, int len2, const ka_param2_t *ap);-#ifdef __cplusplus-}-#endif--extern ka_param_t ka_param_blast; /* = { 5, 2, 5, 2, aln_sm_blast, 5, 50 }; */-extern ka_param_t ka_param_qual; // only use this for global alignment!!!-extern ka_param2_t ka_param2_qual; // only use this for global alignment!!!--#endif
− samtools-0.1.13/khash.h
@@ -1,528 +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);- if (!ret) kh_del(32, h, k);- 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;-}-*/--/*- 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.-- @copyright Heng Li- */--#define AC_VERSION_KHASH_H "0.2.5"--#include <stdlib.h>-#include <string.h>-#include <limits.h>--/* compipler 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--#ifdef _MSC_VER-#define inline __inline-#endif--typedef khint32_t khint_t;-typedef khint_t khiter_t;--#define __ac_HASH_PRIME_SIZE 32-static const khint32_t __ac_prime_list[__ac_HASH_PRIME_SIZE] =-{- 0ul, 3ul, 11ul, 23ul, 53ul,- 97ul, 193ul, 389ul, 769ul, 1543ul,- 3079ul, 6151ul, 12289ul, 24593ul, 49157ul,- 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul,- 3145739ul, 6291469ul, 12582917ul, 25165843ul, 50331653ul,- 100663319ul, 201326611ul, 402653189ul, 805306457ul, 1610612741ul,- 3221225473ul, 4294967291ul-};--#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))--static const double __ac_HASH_UPPER = 0.77;--#define KHASH_DECLARE(name, khkey_t, khval_t) \- typedef struct { \- khint_t n_buckets, size, n_occupied, upper_bound; \- khint32_t *flags; \- khkey_t *keys; \- khval_t *vals; \- } kh_##name##_t; \- extern kh_##name##_t *kh_init_##name(); \- 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 void 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_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \- typedef struct { \- khint_t n_buckets, size, n_occupied, upper_bound; \- khint32_t *flags; \- khkey_t *keys; \- khval_t *vals; \- } kh_##name##_t; \- SCOPE kh_##name##_t *kh_init_##name() { \- return (kh_##name##_t*)calloc(1, sizeof(kh_##name##_t)); \- } \- SCOPE void kh_destroy_##name(kh_##name##_t *h) \- { \- if (h) { \- free(h->keys); free(h->flags); \- free(h->vals); \- free(h); \- } \- } \- SCOPE void kh_clear_##name(kh_##name##_t *h) \- { \- if (h && h->flags) { \- memset(h->flags, 0xaa, ((h->n_buckets>>4) + 1) * 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 inc, k, i, last; \- k = __hash_func(key); i = k % h->n_buckets; \- inc = 1 + k % (h->n_buckets - 1); last = i; \- while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \- if (i + inc >= h->n_buckets) i = i + inc - h->n_buckets; \- else i += inc; \- if (i == last) return h->n_buckets; \- } \- return __ac_iseither(h->flags, i)? h->n_buckets : i; \- } else return 0; \- } \- SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \- { \- khint32_t *new_flags = 0; \- khint_t j = 1; \- { \- khint_t t = __ac_HASH_PRIME_SIZE - 1; \- while (__ac_prime_list[t] > new_n_buckets) --t; \- new_n_buckets = __ac_prime_list[t+1]; \- if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; \- else { \- new_flags = (khint32_t*)malloc(((new_n_buckets>>4) + 1) * sizeof(khint32_t)); \- memset(new_flags, 0xaa, ((new_n_buckets>>4) + 1) * sizeof(khint32_t)); \- if (h->n_buckets < new_n_buckets) { \- h->keys = (khkey_t*)realloc(h->keys, new_n_buckets * sizeof(khkey_t)); \- if (kh_is_map) \- h->vals = (khval_t*)realloc(h->vals, new_n_buckets * sizeof(khval_t)); \- } \- } \- } \- if (j) { \- for (j = 0; j != h->n_buckets; ++j) { \- if (__ac_iseither(h->flags, j) == 0) { \- khkey_t key = h->keys[j]; \- khval_t val; \- if (kh_is_map) val = h->vals[j]; \- __ac_set_isdel_true(h->flags, j); \- while (1) { \- khint_t inc, k, i; \- k = __hash_func(key); \- i = k % new_n_buckets; \- inc = 1 + k % (new_n_buckets - 1); \- while (!__ac_isempty(new_flags, i)) { \- if (i + inc >= new_n_buckets) i = i + inc - new_n_buckets; \- else i += inc; \- } \- __ac_set_isempty_false(new_flags, i); \- if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { \- { 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); \- } else { \- h->keys[i] = key; \- if (kh_is_map) h->vals[i] = val; \- break; \- } \- } \- } \- } \- if (h->n_buckets > new_n_buckets) { \- h->keys = (khkey_t*)realloc(h->keys, new_n_buckets * sizeof(khkey_t)); \- if (kh_is_map) \- h->vals = (khval_t*)realloc(h->vals, new_n_buckets * sizeof(khval_t)); \- } \- free(h->flags); \- 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); \- } \- } \- 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) { \- if (h->n_buckets > (h->size<<1)) kh_resize_##name(h, h->n_buckets - 1); \- else kh_resize_##name(h, h->n_buckets + 1); \- } \- { \- khint_t inc, k, i, site, last; \- x = site = h->n_buckets; k = __hash_func(key); i = k % h->n_buckets; \- if (__ac_isempty(h->flags, i)) x = i; \- else { \- inc = 1 + k % (h->n_buckets - 1); 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; \- if (i + inc >= h->n_buckets) i = i + inc - h->n_buckets; \- else i += inc; \- 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)) { \- 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)) { \- h->keys[x] = key; \- __ac_set_isboth_false(h->flags, x); \- ++h->size; \- *ret = 2; \- } else *ret = 0; \- 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_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \- KHASH_INIT2(name, static inline, 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 inline khint_t __ac_X31_hash_string(const char *s)-{- khint_t h = *s;- if (h) for (++s ; *s; ++s) h = (h << 5) - h + *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)--/* --- END OF HASH FUNCTIONS --- */--/* Other necessary 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: 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) is 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)--/* 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 */
− samtools-0.1.13/knetfile.c
@@ -1,632 +0,0 @@-/* The MIT License-- Copyright (c) 2008 by Genome Research Ltd (GRL).- 2010 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.-*/--/* Probably I will not do socket programming in the next few years and- therefore I decide to heavily annotate this file, for Linux and- Windows as well. -ac */--#include <time.h>-#include <stdio.h>-#include <ctype.h>-#include <stdlib.h>-#include <string.h>-#include <errno.h>-#include <unistd.h>-#include <sys/types.h>--#ifndef _WIN32-#include <netdb.h>-#include <arpa/inet.h>-#include <sys/socket.h>-#endif--#include "knetfile.h"--/* In winsock.h, the type of a socket is SOCKET, which is: "typedef- * u_int SOCKET". An invalid SOCKET is: "(SOCKET)(~0)", or signed- * integer -1. In knetfile.c, I use "int" for socket type- * throughout. This should be improved to avoid confusion.- *- * In Linux/Mac, recv() and read() do almost the same thing. You can see- * in the header file that netread() is simply an alias of read(). In- * Windows, however, they are different and using recv() is mandatory.- */--/* This function tests if the file handler is ready for reading (or- * writing if is_read==0). */-static int socket_wait(int fd, int is_read)-{- fd_set fds, *fdr = 0, *fdw = 0;- struct timeval tv;- int ret;- tv.tv_sec = 5; tv.tv_usec = 0; // 5 seconds time out- FD_ZERO(&fds);- FD_SET(fd, &fds);- if (is_read) fdr = &fds;- else fdw = &fds;- ret = select(fd+1, fdr, fdw, 0, &tv);-#ifndef _WIN32- if (ret == -1) perror("select");-#else- if (ret == 0)- fprintf(stderr, "select time-out\n");- else if (ret == SOCKET_ERROR)- fprintf(stderr, "select: %d\n", WSAGetLastError());-#endif- return ret;-}--#ifndef _WIN32-/* This function does not work with Windows due to the lack of- * getaddrinfo() in winsock. It is addapted from an example in "Beej's- * Guide to Network Programming" (http://beej.us/guide/bgnet/). */-static int socket_connect(const char *host, const char *port)-{-#define __err_connect(func) do { perror(func); freeaddrinfo(res); return -1; } while (0)-- int on = 1, fd;- struct linger lng = { 0, 0 };- struct addrinfo hints, *res = 0;- memset(&hints, 0, sizeof(struct addrinfo));- hints.ai_family = AF_UNSPEC;- hints.ai_socktype = SOCK_STREAM;- /* In Unix/Mac, getaddrinfo() is the most convenient way to get- * server information. */- if (getaddrinfo(host, port, &hints, &res) != 0) __err_connect("getaddrinfo");- if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) __err_connect("socket");- /* The following two setsockopt() are used by ftplib- * (http://nbpfaus.net/~pfau/ftplib/). I am not sure if they- * necessary. */- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) __err_connect("setsockopt");- if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &lng, sizeof(lng)) == -1) __err_connect("setsockopt");- if (connect(fd, res->ai_addr, res->ai_addrlen) != 0) __err_connect("connect");- freeaddrinfo(res);- return fd;-}-#else-/* MinGW's printf has problem with "%lld" */-char *int64tostr(char *buf, int64_t x)-{- int cnt;- int i = 0;- do {- buf[i++] = '0' + x % 10;- x /= 10;- } while (x);- buf[i] = 0;- for (cnt = i, i = 0; i < cnt/2; ++i) {- int c = buf[i]; buf[i] = buf[cnt-i-1]; buf[cnt-i-1] = c;- }- return buf;-}--int64_t strtoint64(const char *buf)-{- int64_t x;- for (x = 0; *buf != '\0'; ++buf)- x = x * 10 + ((int64_t) *buf - 48);- return x;-}-/* In windows, the first thing is to establish the TCP connection. */-int knet_win32_init()-{- WSADATA wsaData;- return WSAStartup(MAKEWORD(2, 2), &wsaData);-}-void knet_win32_destroy()-{- WSACleanup();-}-/* A slightly modfied version of the following function also works on- * Mac (and presummably Linux). However, this function is not stable on- * my Mac. It sometimes works fine but sometimes does not. Therefore for- * non-Windows OS, I do not use this one. */-static SOCKET socket_connect(const char *host, const char *port)-{-#define __err_connect(func) \- do { \- fprintf(stderr, "%s: %d\n", func, WSAGetLastError()); \- return -1; \- } while (0)-- int on = 1;- SOCKET fd;- struct linger lng = { 0, 0 };- struct sockaddr_in server;- struct hostent *hp = 0;- // open socket- if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) __err_connect("socket");- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)) == -1) __err_connect("setsockopt");- if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&lng, sizeof(lng)) == -1) __err_connect("setsockopt");- // get host info- if (isalpha(host[0])) hp = gethostbyname(host);- else {- struct in_addr addr;- addr.s_addr = inet_addr(host);- hp = gethostbyaddr((char*)&addr, 4, AF_INET);- }- if (hp == 0) __err_connect("gethost");- // connect- server.sin_addr.s_addr = *((unsigned long*)hp->h_addr);- server.sin_family= AF_INET;- server.sin_port = htons(atoi(port));- if (connect(fd, (struct sockaddr*)&server, sizeof(server)) != 0) __err_connect("connect");- // freehostent(hp); // strangely in MSDN, hp is NOT freed (memory leak?!)- return fd;-}-#endif--static off_t my_netread(int fd, void *buf, off_t len)-{- off_t rest = len, curr, l = 0;- /* recv() and read() may not read the required length of data with- * one call. They have to be called repeatedly. */- while (rest) {- if (socket_wait(fd, 1) <= 0) break; // socket is not ready for reading- curr = netread(fd, buf + l, rest);- /* According to the glibc manual, section 13.2, a zero returned- * value indicates end-of-file (EOF), which should mean that- * read() will not return zero if EOF has not been met but data- * are not immediately available. */- if (curr == 0) break;- l += curr; rest -= curr;- }- return l;-}--/*************************- * FTP specific routines *- *************************/--static int kftp_get_response(knetFile *ftp)-{-#ifndef _WIN32- unsigned char c;-#else- char c;-#endif- int n = 0;- char *p;- if (socket_wait(ftp->ctrl_fd, 1) <= 0) return 0;- while (netread(ftp->ctrl_fd, &c, 1)) { // FIXME: this is *VERY BAD* for unbuffered I/O- //fputc(c, stderr);- if (n >= ftp->max_response) {- ftp->max_response = ftp->max_response? ftp->max_response<<1 : 256;- ftp->response = realloc(ftp->response, ftp->max_response);- }- ftp->response[n++] = c;- if (c == '\n') {- if (n >= 4 && isdigit(ftp->response[0]) && isdigit(ftp->response[1]) && isdigit(ftp->response[2])- && ftp->response[3] != '-') break;- n = 0;- continue;- }- }- if (n < 2) return -1;- ftp->response[n-2] = 0;- return strtol(ftp->response, &p, 0);-}--static int kftp_send_cmd(knetFile *ftp, const char *cmd, int is_get)-{- if (socket_wait(ftp->ctrl_fd, 0) <= 0) return -1; // socket is not ready for writing- netwrite(ftp->ctrl_fd, cmd, strlen(cmd));- return is_get? kftp_get_response(ftp) : 0;-}--static int kftp_pasv_prep(knetFile *ftp)-{- char *p;- int v[6];- kftp_send_cmd(ftp, "PASV\r\n", 1);- for (p = ftp->response; *p && *p != '('; ++p);- if (*p != '(') return -1;- ++p;- sscanf(p, "%d,%d,%d,%d,%d,%d", &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);- memcpy(ftp->pasv_ip, v, 4 * sizeof(int));- ftp->pasv_port = (v[4]<<8&0xff00) + v[5];- return 0;-}---static int kftp_pasv_connect(knetFile *ftp)-{- char host[80], port[10];- if (ftp->pasv_port == 0) {- fprintf(stderr, "[kftp_pasv_connect] kftp_pasv_prep() is not called before hand.\n");- return -1;- }- sprintf(host, "%d.%d.%d.%d", ftp->pasv_ip[0], ftp->pasv_ip[1], ftp->pasv_ip[2], ftp->pasv_ip[3]);- sprintf(port, "%d", ftp->pasv_port);- ftp->fd = socket_connect(host, port);- if (ftp->fd == -1) return -1;- return 0;-}--int kftp_connect(knetFile *ftp)-{- ftp->ctrl_fd = socket_connect(ftp->host, ftp->port);- if (ftp->ctrl_fd == -1) return -1;- kftp_get_response(ftp);- kftp_send_cmd(ftp, "USER anonymous\r\n", 1);- kftp_send_cmd(ftp, "PASS kftp@\r\n", 1);- kftp_send_cmd(ftp, "TYPE I\r\n", 1);- return 0;-}--int kftp_reconnect(knetFile *ftp)-{- if (ftp->ctrl_fd != -1) {- netclose(ftp->ctrl_fd);- ftp->ctrl_fd = -1;- }- netclose(ftp->fd);- ftp->fd = -1;- return kftp_connect(ftp);-}--// initialize ->type, ->host, ->retr and ->size-knetFile *kftp_parse_url(const char *fn, const char *mode)-{- knetFile *fp;- char *p;- int l;- if (strstr(fn, "ftp://") != fn) return 0;- for (p = (char*)fn + 6; *p && *p != '/'; ++p);- if (*p != '/') return 0;- l = p - fn - 6;- fp = calloc(1, sizeof(knetFile));- fp->type = KNF_TYPE_FTP;- fp->fd = -1;- /* the Linux/Mac version of socket_connect() also recognizes a port- * like "ftp", but the Windows version does not. */- fp->port = strdup("21");- fp->host = calloc(l + 1, 1);- if (strchr(mode, 'c')) fp->no_reconnect = 1;- strncpy(fp->host, fn + 6, l);- fp->retr = calloc(strlen(p) + 8, 1);- sprintf(fp->retr, "RETR %s\r\n", p);- fp->size_cmd = calloc(strlen(p) + 8, 1);- sprintf(fp->size_cmd, "SIZE %s\r\n", p);- fp->seek_offset = 0;- return fp;-}-// place ->fd at offset off-int kftp_connect_file(knetFile *fp)-{- int ret;- long long file_size;- if (fp->fd != -1) {- netclose(fp->fd);- if (fp->no_reconnect) kftp_get_response(fp);- }- kftp_pasv_prep(fp);- kftp_send_cmd(fp, fp->size_cmd, 1);-#ifndef _WIN32- if ( sscanf(fp->response,"%*d %lld", &file_size) != 1 )- {- fprintf(stderr,"[kftp_connect_file] %s\n", fp->response);- return -1;- }-#else- const char *p = fp->response;- while (*p != ' ') ++p;- while (*p < '0' || *p > '9') ++p;- file_size = strtoint64(p);-#endif- fp->file_size = file_size;- if (fp->offset>=0) {- char tmp[32];-#ifndef _WIN32- sprintf(tmp, "REST %lld\r\n", (long long)fp->offset);-#else- strcpy(tmp, "REST ");- int64tostr(tmp + 5, fp->offset);- strcat(tmp, "\r\n");-#endif- kftp_send_cmd(fp, tmp, 1);- }- kftp_send_cmd(fp, fp->retr, 0);- kftp_pasv_connect(fp);- ret = kftp_get_response(fp);- if (ret != 150) {- fprintf(stderr, "[kftp_connect_file] %s\n", fp->response);- netclose(fp->fd);- fp->fd = -1;- return -1;- }- fp->is_ready = 1;- return 0;-}---/**************************- * HTTP specific routines *- **************************/--knetFile *khttp_parse_url(const char *fn, const char *mode)-{- knetFile *fp;- char *p, *proxy, *q;- int l;- if (strstr(fn, "http://") != fn) return 0;- // set ->http_host- for (p = (char*)fn + 7; *p && *p != '/'; ++p);- l = p - fn - 7;- fp = calloc(1, sizeof(knetFile));- fp->http_host = calloc(l + 1, 1);- strncpy(fp->http_host, fn + 7, l);- fp->http_host[l] = 0;- for (q = fp->http_host; *q && *q != ':'; ++q);- if (*q == ':') *q++ = 0;- // get http_proxy- proxy = getenv("http_proxy");- // set ->host, ->port and ->path- if (proxy == 0) {- fp->host = strdup(fp->http_host); // when there is no proxy, server name is identical to http_host name.- fp->port = strdup(*q? q : "80");- fp->path = strdup(*p? p : "/");- } else {- fp->host = (strstr(proxy, "http://") == proxy)? strdup(proxy + 7) : strdup(proxy);- for (q = fp->host; *q && *q != ':'; ++q);- if (*q == ':') *q++ = 0; - fp->port = strdup(*q? q : "80");- fp->path = strdup(fn);- }- fp->type = KNF_TYPE_HTTP;- fp->ctrl_fd = fp->fd = -1;- fp->seek_offset = 0;- return fp;-}--int khttp_connect_file(knetFile *fp)-{- int ret, l = 0;- char *buf, *p;- if (fp->fd != -1) netclose(fp->fd);- fp->fd = socket_connect(fp->host, fp->port);- buf = calloc(0x10000, 1); // FIXME: I am lazy... But in principle, 64KB should be large enough.- l += sprintf(buf + l, "GET %s HTTP/1.0\r\nHost: %s\r\n", fp->path, fp->http_host);- l += sprintf(buf + l, "Range: bytes=%lld-\r\n", (long long)fp->offset);- l += sprintf(buf + l, "\r\n");- netwrite(fp->fd, buf, l);- l = 0;- while (netread(fp->fd, buf + l, 1)) { // read HTTP header; FIXME: bad efficiency- if (buf[l] == '\n' && l >= 3)- if (strncmp(buf + l - 3, "\r\n\r\n", 4) == 0) break;- ++l;- }- buf[l] = 0;- if (l < 14) { // prematured header- netclose(fp->fd);- fp->fd = -1;- return -1;- }- ret = strtol(buf + 8, &p, 0); // HTTP return code- if (ret == 200 && fp->offset>0) { // 200 (complete result); then skip beginning of the file- off_t rest = fp->offset;- while (rest) {- off_t l = rest < 0x10000? rest : 0x10000;- rest -= my_netread(fp->fd, buf, l);- }- } else if (ret != 206 && ret != 200) {- free(buf);- fprintf(stderr, "[khttp_connect_file] fail to open file (HTTP code: %d).\n", ret);- netclose(fp->fd);- fp->fd = -1;- return -1;- }- free(buf);- fp->is_ready = 1;- return 0;-}--/********************- * Generic routines *- ********************/--knetFile *knet_open(const char *fn, const char *mode)-{- knetFile *fp = 0;- if (mode[0] != 'r') {- fprintf(stderr, "[kftp_open] only mode \"r\" is supported.\n");- return 0;- }- if (strstr(fn, "ftp://") == fn) {- fp = kftp_parse_url(fn, mode);- if (fp == 0) return 0;- if (kftp_connect(fp) == -1) {- knet_close(fp);- return 0;- }- kftp_connect_file(fp);- } else if (strstr(fn, "http://") == fn) {- fp = khttp_parse_url(fn, mode);- if (fp == 0) return 0;- khttp_connect_file(fp);- } else { // local file-#ifdef _WIN32- /* In windows, O_BINARY is necessary. In Linux/Mac, O_BINARY may- * be undefined on some systems, although it is defined on my- * Mac and the Linux I have tested on. */- int fd = open(fn, O_RDONLY | O_BINARY);-#else - int fd = open(fn, O_RDONLY);-#endif- if (fd == -1) {- perror("open");- return 0;- }- fp = (knetFile*)calloc(1, sizeof(knetFile));- fp->type = KNF_TYPE_LOCAL;- fp->fd = fd;- fp->ctrl_fd = -1;- }- if (fp && fp->fd == -1) {- knet_close(fp);- return 0;- }- return fp;-}--knetFile *knet_dopen(int fd, const char *mode)-{- knetFile *fp = (knetFile*)calloc(1, sizeof(knetFile));- fp->type = KNF_TYPE_LOCAL;- fp->fd = fd;- return fp;-}--off_t knet_read(knetFile *fp, void *buf, off_t len)-{- off_t l = 0;- if (fp->fd == -1) return 0;- if (fp->type == KNF_TYPE_FTP) {- if (fp->is_ready == 0) {- if (!fp->no_reconnect) kftp_reconnect(fp);- kftp_connect_file(fp);- }- } else if (fp->type == KNF_TYPE_HTTP) {- if (fp->is_ready == 0)- khttp_connect_file(fp);- }- if (fp->type == KNF_TYPE_LOCAL) { // on Windows, the following block is necessary; not on UNIX- off_t rest = len, curr;- while (rest) {- do {- curr = read(fp->fd, buf + l, rest);- } while (curr < 0 && EINTR == errno);- if (curr < 0) return -1;- if (curr == 0) break;- l += curr; rest -= curr;- }- } else l = my_netread(fp->fd, buf, len);- fp->offset += l;- return l;-}--off_t knet_seek(knetFile *fp, int64_t off, int whence)-{- if (whence == SEEK_SET && off == fp->offset) return 0;- if (fp->type == KNF_TYPE_LOCAL) {- /* Be aware that lseek() returns the offset after seeking,- * while fseek() returns zero on success. */- off_t offset = lseek(fp->fd, off, whence);- if (offset == -1) {- // Be silent, it is OK for knet_seek to fail when the file is streamed- // fprintf(stderr,"[knet_seek] %s\n", strerror(errno));- return -1;- }- fp->offset = offset;- return 0;- }- else if (fp->type == KNF_TYPE_FTP) - {- if (whence==SEEK_CUR)- fp->offset += off;- else if (whence==SEEK_SET)- fp->offset = off;- else if ( whence==SEEK_END)- fp->offset = fp->file_size+off;- fp->is_ready = 0;- return 0;- } - else if (fp->type == KNF_TYPE_HTTP) - {- if (whence == SEEK_END) { // FIXME: can we allow SEEK_END in future?- fprintf(stderr, "[knet_seek] SEEK_END is not supported for HTTP. Offset is unchanged.\n");- errno = ESPIPE;- return -1;- }- if (whence==SEEK_CUR)- fp->offset += off;- else if (whence==SEEK_SET)- fp->offset = off;- fp->is_ready = 0;- return 0;- }- errno = EINVAL;- fprintf(stderr,"[knet_seek] %s\n", strerror(errno));- return -1;-}--int knet_close(knetFile *fp)-{- if (fp == 0) return 0;- if (fp->ctrl_fd != -1) netclose(fp->ctrl_fd); // FTP specific- if (fp->fd != -1) {- /* On Linux/Mac, netclose() is an alias of close(), but on- * Windows, it is an alias of closesocket(). */- if (fp->type == KNF_TYPE_LOCAL) close(fp->fd);- else netclose(fp->fd);- }- free(fp->host); free(fp->port);- free(fp->response); free(fp->retr); // FTP specific- free(fp->path); free(fp->http_host); // HTTP specific- free(fp);- return 0;-}--#ifdef KNETFILE_MAIN-int main(void)-{- char *buf;- knetFile *fp;- int type = 4, l;-#ifdef _WIN32- knet_win32_init();-#endif- buf = calloc(0x100000, 1);- if (type == 0) {- fp = knet_open("knetfile.c", "r");- knet_seek(fp, 1000, SEEK_SET);- } else if (type == 1) { // NCBI FTP, large file- fp = knet_open("ftp://ftp.ncbi.nih.gov/1000genomes/ftp/data/NA12878/alignment/NA12878.chrom6.SLX.SRP000032.2009_06.bam", "r");- knet_seek(fp, 2500000000ll, SEEK_SET);- l = knet_read(fp, buf, 255);- } else if (type == 2) {- fp = knet_open("ftp://ftp.sanger.ac.uk/pub4/treefam/tmp/index.shtml", "r");- knet_seek(fp, 1000, SEEK_SET);- } else if (type == 3) {- fp = knet_open("http://www.sanger.ac.uk/Users/lh3/index.shtml", "r");- knet_seek(fp, 1000, SEEK_SET);- } else if (type == 4) {- fp = knet_open("http://www.sanger.ac.uk/Users/lh3/ex1.bam", "r");- knet_read(fp, buf, 10000);- knet_seek(fp, 20000, SEEK_SET);- knet_seek(fp, 10000, SEEK_SET);- l = knet_read(fp, buf+10000, 10000000) + 10000;- }- if (type != 4 && type != 1) {- knet_read(fp, buf, 255);- buf[255] = 0;- printf("%s\n", buf);- } else write(fileno(stdout), buf, l);- knet_close(fp);- free(buf);- return 0;-}-#endif
− samtools-0.1.13/knetfile.h
@@ -1,75 +0,0 @@-#ifndef KNETFILE_H-#define KNETFILE_H--#include <stdint.h>-#include <fcntl.h>--#ifndef _WIN32-#define netread(fd, ptr, len) read(fd, ptr, len)-#define netwrite(fd, ptr, len) write(fd, ptr, len)-#define netclose(fd) close(fd)-#else-#include <winsock2.h>-#define netread(fd, ptr, len) recv(fd, ptr, len, 0)-#define netwrite(fd, ptr, len) send(fd, ptr, len, 0)-#define netclose(fd) closesocket(fd)-#endif--// FIXME: currently I/O is unbuffered--#define KNF_TYPE_LOCAL 1-#define KNF_TYPE_FTP 2-#define KNF_TYPE_HTTP 3--typedef struct knetFile_s {- int type, fd;- int64_t offset;- char *host, *port;-- // the following are for FTP only- int ctrl_fd, pasv_ip[4], pasv_port, max_response, no_reconnect, is_ready;- char *response, *retr, *size_cmd;- int64_t seek_offset; // for lazy seek- int64_t file_size;-- // the following are for HTTP only- char *path, *http_host;-} knetFile;--#define knet_tell(fp) ((fp)->offset)-#define knet_fileno(fp) ((fp)->fd)--#ifdef __cplusplus-extern "C" {-#endif--#ifdef _WIN32- int knet_win32_init();- void knet_win32_destroy();-#endif-- knetFile *knet_open(const char *fn, const char *mode);-- /* - This only works with local files.- */- knetFile *knet_dopen(int fd, const char *mode);-- /*- If ->is_ready==0, this routine updates ->fd; otherwise, it simply- reads from ->fd.- */- off_t knet_read(knetFile *fp, void *buf, off_t len);-- /*- This routine only sets ->offset and ->is_ready=0. It does not- communicate with the FTP server.- */- off_t knet_seek(knetFile *fp, int64_t off, int whence);- int knet_close(knetFile *fp);--#ifdef __cplusplus-}-#endif--#endif
− samtools-0.1.13/kprobaln.c
@@ -1,278 +0,0 @@-/* The MIT License-- Copyright (c) 2003-2006, 2008-2010, by Heng Li <lh3lh3@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.-*/--#include <stdlib.h>-#include <stdio.h>-#include <string.h>-#include <stdint.h>-#include <math.h>-#include "kprobaln.h"--/*****************************************- * Probabilistic banded glocal alignment *- *****************************************/--#define EI .25-#define EM .33333333333--static float g_qual2prob[256];--#define set_u(u, b, i, k) { int x=(i)-(b); x=x>0?x:0; (u)=((k)-x+1)*3; }--kpa_par_t kpa_par_def = { 0.001, 0.1, 10 };-kpa_par_t kpa_par_alt = { 0.0001, 0.01, 10 };--/*- The topology of the profile HMM:-- /\ /\ /\ /\- I[1] I[k-1] I[k] I[L]- ^ \ \ ^ \ ^ \ \ ^- | \ \ | \ | \ \ |- M[0] M[1] -> ... -> M[k-1] -> M[k] -> ... -> M[L] M[L+1]- \ \/ \/ \/ /- \ /\ /\ /\ /- -> D[k-1] -> D[k] ->-- M[0] points to every {M,I}[k] and every {M,I}[k] points M[L+1].-- On input, _ref is the reference sequence and _query is the query- sequence. Both are sequences of 0/1/2/3/4 where 4 stands for an- ambiguous residue. iqual is the base quality. c sets the gap open- probability, gap extension probability and band width.-- On output, state and q are arrays of length l_query. The higher 30- bits give the reference position the query base is matched to and the- lower two bits can be 0 (an alignment match) or 1 (an- insertion). q[i] gives the phred scaled posterior probability of- state[i] being wrong.- */-int kpa_glocal(const uint8_t *_ref, int l_ref, const uint8_t *_query, int l_query, const uint8_t *iqual,- const kpa_par_t *c, int *state, uint8_t *q)-{- double **f, **b = 0, *s, m[9], sI, sM, bI, bM, pb;- float *qual, *_qual;- const uint8_t *ref, *query;- int bw, bw2, i, k, is_diff = 0, is_backward = 1, Pr;-- /*** initialization ***/- is_backward = state && q? 1 : 0;- ref = _ref - 1; query = _query - 1; // change to 1-based coordinate- bw = l_ref > l_query? l_ref : l_query;- if (bw > c->bw) bw = c->bw;- if (bw < abs(l_ref - l_query)) bw = abs(l_ref - l_query);- bw2 = bw * 2 + 1;- // allocate the forward and backward matrices f[][] and b[][] and the scaling array s[]- f = calloc(l_query+1, sizeof(void*));- if (is_backward) b = calloc(l_query+1, sizeof(void*));- for (i = 0; i <= l_query; ++i) {- f[i] = calloc(bw2 * 3 + 6, sizeof(double)); // FIXME: this is over-allocated for very short seqs- if (is_backward) b[i] = calloc(bw2 * 3 + 6, sizeof(double));- }- s = calloc(l_query+2, sizeof(double)); // s[] is the scaling factor to avoid underflow- // initialize qual- _qual = calloc(l_query, sizeof(float));- if (g_qual2prob[0] == 0)- for (i = 0; i < 256; ++i)- g_qual2prob[i] = pow(10, -i/10.);- for (i = 0; i < l_query; ++i) _qual[i] = g_qual2prob[iqual? iqual[i] : 30];- qual = _qual - 1;- // initialize transition probability- sM = sI = 1. / (2 * l_query + 2); // the value here seems not to affect results; FIXME: need proof- m[0*3+0] = (1 - c->d - c->d) * (1 - sM); m[0*3+1] = m[0*3+2] = c->d * (1 - sM);- m[1*3+0] = (1 - c->e) * (1 - sI); m[1*3+1] = c->e * (1 - sI); m[1*3+2] = 0.;- m[2*3+0] = 1 - c->e; m[2*3+1] = 0.; m[2*3+2] = c->e;- bM = (1 - c->d) / l_ref; bI = c->d / l_ref; // (bM+bI)*l_ref==1- /*** forward ***/- // f[0]- set_u(k, bw, 0, 0);- f[0][k] = s[0] = 1.;- { // f[1]- double *fi = f[1], sum;- int beg = 1, end = l_ref < bw + 1? l_ref : bw + 1, _beg, _end;- for (k = beg, sum = 0.; k <= end; ++k) {- int u;- double e = (ref[k] > 3 || query[1] > 3)? 1. : ref[k] == query[1]? 1. - qual[1] : qual[1] * EM;- set_u(u, bw, 1, k);- fi[u+0] = e * bM; fi[u+1] = EI * bI;- sum += fi[u] + fi[u+1];- }- // rescale- s[1] = sum;- set_u(_beg, bw, 1, beg); set_u(_end, bw, 1, end); _end += 2;- for (k = _beg; k <= _end; ++k) fi[k] /= sum;- }- // f[2..l_query]- for (i = 2; i <= l_query; ++i) {- double *fi = f[i], *fi1 = f[i-1], sum, qli = qual[i];- int beg = 1, end = l_ref, x, _beg, _end;- uint8_t qyi = query[i];- x = i - bw; beg = beg > x? beg : x; // band start- x = i + bw; end = end < x? end : x; // band end- for (k = beg, sum = 0.; k <= end; ++k) {- int u, v11, v01, v10;- double e;- e = (ref[k] > 3 || qyi > 3)? 1. : ref[k] == qyi? 1. - qli : qli * EM;- set_u(u, bw, i, k); set_u(v11, bw, i-1, k-1); set_u(v10, bw, i-1, k); set_u(v01, bw, i, k-1);- fi[u+0] = e * (m[0] * fi1[v11+0] + m[3] * fi1[v11+1] + m[6] * fi1[v11+2]);- fi[u+1] = EI * (m[1] * fi1[v10+0] + m[4] * fi1[v10+1]);- fi[u+2] = m[2] * fi[v01+0] + m[8] * fi[v01+2];- sum += fi[u] + fi[u+1] + fi[u+2];-// fprintf(stderr, "F (%d,%d;%d): %lg,%lg,%lg\n", i, k, u, fi[u], fi[u+1], fi[u+2]); // DEBUG- }- // rescale- s[i] = sum;- set_u(_beg, bw, i, beg); set_u(_end, bw, i, end); _end += 2;- for (k = _beg, sum = 1./sum; k <= _end; ++k) fi[k] *= sum;- }- { // f[l_query+1]- double sum;- for (k = 1, sum = 0.; k <= l_ref; ++k) {- int u;- set_u(u, bw, l_query, k);- if (u < 3 || u >= bw2*3+3) continue;- sum += f[l_query][u+0] * sM + f[l_query][u+1] * sI;- }- s[l_query+1] = sum; // the last scaling factor- }- { // compute likelihood- double p = 1., Pr1 = 0.;- for (i = 0; i <= l_query + 1; ++i) {- p *= s[i];- if (p < 1e-100) Pr += -4.343 * log(p), p = 1.;- }- Pr1 += -4.343 * log(p * l_ref * l_query);- Pr = (int)(Pr1 + .499);- if (!is_backward) { // skip backward and MAP- for (i = 0; i <= l_query; ++i) free(f[i]);- free(f); free(s); free(_qual);- return Pr;- }- }- /*** backward ***/- // b[l_query] (b[l_query+1][0]=1 and thus \tilde{b}[][]=1/s[l_query+1]; this is where s[l_query+1] comes from)- for (k = 1; k <= l_ref; ++k) {- int u;- double *bi = b[l_query];- set_u(u, bw, l_query, k);- if (u < 3 || u >= bw2*3+3) continue;- bi[u+0] = sM / s[l_query] / s[l_query+1]; bi[u+1] = sI / s[l_query] / s[l_query+1];- }- // b[l_query-1..1]- for (i = l_query - 1; i >= 1; --i) {- int beg = 1, end = l_ref, x, _beg, _end;- double *bi = b[i], *bi1 = b[i+1], y = (i > 1), qli1 = qual[i+1];- uint8_t qyi1 = query[i+1];- x = i - bw; beg = beg > x? beg : x;- x = i + bw; end = end < x? end : x;- for (k = end; k >= beg; --k) {- int u, v11, v01, v10;- double e;- set_u(u, bw, i, k); set_u(v11, bw, i+1, k+1); set_u(v10, bw, i+1, k); set_u(v01, bw, i, k+1);- e = (k >= l_ref? 0 : (ref[k+1] > 3 || qyi1 > 3)? 1. : ref[k+1] == qyi1? 1. - qli1 : qli1 * EM) * bi1[v11];- bi[u+0] = e * m[0] + EI * m[1] * bi1[v10+1] + m[2] * bi[v01+2]; // bi1[v11] has been foled into e.- bi[u+1] = e * m[3] + EI * m[4] * bi1[v10+1];- bi[u+2] = (e * m[6] + m[8] * bi[v01+2]) * y;-// fprintf(stderr, "B (%d,%d;%d): %lg,%lg,%lg\n", i, k, u, bi[u], bi[u+1], bi[u+2]); // DEBUG- }- // rescale- set_u(_beg, bw, i, beg); set_u(_end, bw, i, end); _end += 2;- for (k = _beg, y = 1./s[i]; k <= _end; ++k) bi[k] *= y;- }- { // b[0]- int beg = 1, end = l_ref < bw + 1? l_ref : bw + 1;- double sum = 0.;- for (k = end; k >= beg; --k) {- int u;- double e = (ref[k] > 3 || query[1] > 3)? 1. : ref[k] == query[1]? 1. - qual[1] : qual[1] * EM;- set_u(u, bw, 1, k);- if (u < 3 || u >= bw2*3+3) continue;- sum += e * b[1][u+0] * bM + EI * b[1][u+1] * bI;- }- set_u(k, bw, 0, 0);- pb = b[0][k] = sum / s[0]; // if everything works as is expected, pb == 1.0- }- is_diff = fabs(pb - 1.) > 1e-7? 1 : 0;- /*** MAP ***/- for (i = 1; i <= l_query; ++i) {- double sum = 0., *fi = f[i], *bi = b[i], max = 0.;- int beg = 1, end = l_ref, x, max_k = -1;- x = i - bw; beg = beg > x? beg : x;- x = i + bw; end = end < x? end : x;- for (k = beg; k <= end; ++k) {- int u;- double z;- set_u(u, bw, i, k);- z = fi[u+0] * bi[u+0]; if (z > max) max = z, max_k = (k-1)<<2 | 0; sum += z;- z = fi[u+1] * bi[u+1]; if (z > max) max = z, max_k = (k-1)<<2 | 1; sum += z;- }- max /= sum; sum *= s[i]; // if everything works as is expected, sum == 1.0- if (state) state[i-1] = max_k;- if (q) k = (int)(-4.343 * log(1. - max) + .499), q[i-1] = k > 100? 99 : k;-#ifdef _MAIN- fprintf(stderr, "(%.10lg,%.10lg) (%d,%d:%c,%c:%d) %lg\n", pb, sum, i-1, max_k>>2,- "ACGT"[query[i]], "ACGT"[ref[(max_k>>2)+1]], max_k&3, max); // DEBUG-#endif- }- /*** free ***/- for (i = 0; i <= l_query; ++i) {- free(f[i]); free(b[i]);- }- free(f); free(b); free(s); free(_qual);- return Pr;-}--#ifdef _MAIN-#include <unistd.h>-int main(int argc, char *argv[])-{- uint8_t conv[256], *iqual, *ref, *query;- int c, l_ref, l_query, i, q = 30, b = 10, P;- while ((c = getopt(argc, argv, "b:q:")) >= 0) {- switch (c) {- case 'b': b = atoi(optarg); break;- case 'q': q = atoi(optarg); break;- }- }- if (optind + 2 > argc) {- fprintf(stderr, "Usage: %s [-q %d] [-b %d] <ref> <query>\n", argv[0], q, b); // example: acttc attc- return 1;- }- memset(conv, 4, 256);- conv['a'] = conv['A'] = 0; conv['c'] = conv['C'] = 1;- conv['g'] = conv['G'] = 2; conv['t'] = conv['T'] = 3;- ref = (uint8_t*)argv[optind]; query = (uint8_t*)argv[optind+1];- l_ref = strlen((char*)ref); l_query = strlen((char*)query);- for (i = 0; i < l_ref; ++i) ref[i] = conv[ref[i]];- for (i = 0; i < l_query; ++i) query[i] = conv[query[i]];- iqual = malloc(l_query);- memset(iqual, q, l_query);- kpa_par_def.bw = b;- P = kpa_glocal(ref, l_ref, query, l_query, iqual, &kpa_par_alt, 0, 0);- fprintf(stderr, "%d\n", P);- free(iqual);- return 0;-}-#endif
− samtools-0.1.13/kprobaln.h
@@ -1,49 +0,0 @@-/* The MIT License-- Copyright (c) 2003-2006, 2008, 2009 by Heng Li <lh3@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.-*/--#ifndef LH3_KPROBALN_H_-#define LH3_KPROBALN_H_--#include <stdint.h>--typedef struct {- float d, e;- int bw;-} kpa_par_t;--#ifdef __cplusplus-extern "C" {-#endif-- int kpa_glocal(const uint8_t *_ref, int l_ref, const uint8_t *_query, int l_query, const uint8_t *iqual,- const kpa_par_t *c, int *state, uint8_t *q);--#ifdef __cplusplus-}-#endif--extern kpa_par_t kpa_par_def, kpa_par_alt;--#endif
− samtools-0.1.13/kseq.h
@@ -1,227 +0,0 @@-/* The MIT License-- Copyright (c) 2008 Genome Research Ltd (GRL).-- 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.-*/--/* Contact: Heng Li <lh3@sanger.ac.uk> */--/*- 2009-07-16 (lh3): in kstream_t, change "char*" to "unsigned char*"- */--/* Last Modified: 12APR2009 */--#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_MAX 1--#define __KS_TYPE(type_t) \- typedef struct __kstream_t { \- unsigned char *buf; \- int begin, end, is_eof; \- type_t f; \- } 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(type_t, __bufsize) \- static inline kstream_t *ks_init(type_t f) \- { \- kstream_t *ks = (kstream_t*)calloc(1, sizeof(kstream_t)); \- ks->f = f; \- ks->buf = malloc(__bufsize); \- return ks; \- } \- static inline void ks_destroy(kstream_t *ks) \- { \- if (ks) { \- free(ks->buf); \- free(ks); \- } \- }--#define __KS_GETC(__read, __bufsize) \- 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, __bufsize); \- if (ks->end < __bufsize) ks->is_eof = 1; \- if (ks->end == 0) return -1; \- } \- return (int)ks->buf[ks->begin++]; \- }--#ifndef KSTRING_T-#define KSTRING_T kstring_t-typedef struct __kstring_t {- size_t 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(__read, __bufsize) \- static int ks_getuntil(kstream_t *ks, int delimiter, kstring_t *str, int *dret) \- { \- if (dret) *dret = 0; \- 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, __bufsize); \- if (ks->end < __bufsize) ks->is_eof = 1; \- if (ks->end == 0) break; \- } else break; \- } \- 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 < 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->l == 0) { \- str->m = 1; \- str->s = (char*)calloc(1, 1); \- } \- str->s[str->l] = '\0'; \- return str->l; \- }--#define KSTREAM_INIT(type_t, __read, __bufsize) \- __KS_TYPE(type_t) \- __KS_BASIC(type_t, __bufsize) \- __KS_GETC(__read, __bufsize) \- __KS_GETUNTIL(__read, __bufsize)--#define __KSEQ_BASIC(type_t) \- static inline kseq_t *kseq_init(type_t fd) \- { \- kseq_t *s = (kseq_t*)calloc(1, sizeof(kseq_t)); \- s->f = ks_init(fd); \- return s; \- } \- static inline void kseq_rewind(kseq_t *ks) \- { \- ks->last_char = 0; \- ks->f->is_eof = ks->f->begin = ks->f->end = 0; \- } \- static inline 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 \- static 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; \- } /* the first header char has been read */ \- seq->comment.l = seq->seq.l = seq->qual.l = 0; \- if (ks_getuntil(ks, 0, &seq->name, &c) < 0) return -1; \- if (c != '\n') ks_getuntil(ks, '\n', &seq->comment, 0); \- while ((c = ks_getc(ks)) != -1 && c != '>' && c != '+' && c != '@') { \- if (isgraph(c)) { /* printable non-space character */ \- if (seq->seq.l + 1 >= seq->seq.m) { /* double the memory */ \- seq->seq.m = seq->seq.l + 2; \- kroundup32(seq->seq.m); /* rounded to next closest 2^k */ \- seq->seq.s = (char*)realloc(seq->seq.s, seq->seq.m); \- } \- seq->seq.s[seq->seq.l++] = (char)c; \- } \- } \- if (c == '>' || c == '@') seq->last_char = c; /* the first header char has been read */ \- 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 enough memory */ \- 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; /* we should not stop here */ \- while ((c = ks_getc(ks)) != -1 && seq->qual.l < seq->seq.l) \- if (c >= 33 && c <= 127) seq->qual.s[seq->qual.l++] = (unsigned char)c; \- seq->qual.s[seq->qual.l] = 0; /* null terminated string */ \- seq->last_char = 0; /* we have not come to the next header line */ \- if (seq->seq.l != seq->qual.l) return -2; /* qual string is shorter than seq string */ \- 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_INIT(type_t, __read) \- KSTREAM_INIT(type_t, __read, 4096) \- __KSEQ_TYPE(type_t) \- __KSEQ_BASIC(type_t) \- __KSEQ_READ--#endif
− samtools-0.1.13/ksort.h
@@ -1,281 +0,0 @@-/* The MIT License-- Copyright (c) 2008 Genome Research Ltd (GRL).-- 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.-*/--/* Contact: Heng Li <lh3@sanger.ac.uk> */--/*- 2008-11-16 (0.1.4):-- * Fixed a bug in introsort() that happens in rare cases.-- 2008-11-05 (0.1.3):-- * Fixed a bug in introsort() for complex comparisons.-- * Fixed a bug in mergesort(). The previous version is not stable.-- 2008-09-15 (0.1.2):-- * Accelerated introsort. On my Mac (not on another Linux machine),- my implementation is as fast as std::sort on random input.-- * Added combsort and in introsort, switch to combsort if the- recursion is too deep.-- 2008-09-13 (0.1.1):-- * Added k-small algorithm-- 2008-09-05 (0.1.0):-- * Initial version--*/--#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) \- void ks_mergesort_##name(size_t n, type_t array[], type_t temp[]) \- { \- type_t *a2[2], *a, *b; \- int curr, shift; \- \- a2[0] = array; \- a2[1] = temp? temp : (type_t*)malloc(sizeof(type_t) * n); \- for (curr = 0, shift = 0; (1ul<<shift) < n; ++shift) { \- a = a2[curr]; b = a2[1-curr]; \- if (shift == 0) { \- type_t *p = b, *i, *eb = a + n; \- for (i = a; i < eb; i += 2) { \- if (i == eb - 1) *p++ = *i; \- else { \- if (__sort_lt(*(i+1), *i)) { \- *p++ = *(i+1); *p++ = *i; \- } else { \- *p++ = *i; *p++ = *(i+1); \- } \- } \- } \- } else { \- size_t i, step = 1ul<<shift; \- for (i = 0; i < n; i += step<<1) { \- type_t *p, *j, *k, *ea, *eb; \- if (n < i + step) { \- ea = a + n; eb = a; \- } else { \- ea = a + i + step; \- eb = a + (n < i + (step<<1)? n : i + (step<<1)); \- } \- j = a + i; k = a + i + step; p = b + i; \- while (j < ea && k < eb) { \- if (__sort_lt(*k, *j)) *p++ = *k++; \- else *p++ = *j++; \- } \- while (j < ea) *p++ = *j++; \- while (k < eb) *p++ = *k++; \- } \- } \- curr = 1 - curr; \- } \- if (curr == 1) { \- type_t *p = a2[0], *i = a2[1], *eb = array + n; \- for (; p < eb; ++i) *p++ = *i; \- } \- if (temp == 0) free(a2[1]); \- } \- void ks_heapadjust_##name(size_t i, size_t n, type_t l[]) \- { \- size_t k = i; \- type_t tmp = l[i]; \- while ((k = (k << 1) + 1) < n) { \- if (k != n - 1 && __sort_lt(l[k], l[k+1])) ++k; \- if (__sort_lt(l[k], tmp)) break; \- l[i] = l[k]; i = k; \- } \- l[i] = tmp; \- } \- void ks_heapmake_##name(size_t lsize, type_t l[]) \- { \- size_t i; \- for (i = (lsize >> 1) - 1; i != (size_t)(-1); --i) \- ks_heapadjust_##name(i, lsize, l); \- } \- void ks_heapsort_##name(size_t lsize, type_t l[]) \- { \- size_t i; \- for (i = lsize - 1; i > 0; --i) { \- type_t tmp; \- tmp = *l; *l = l[i]; l[i] = tmp; ks_heapadjust_##name(0, i, l); \- } \- } \- inline void __ks_insertsort_##name(type_t *s, type_t *t) \- { \- type_t *i, *j, swap_tmp; \- for (i = s + 1; i < t; ++i) \- for (j = i; j > s && __sort_lt(*j, *(j-1)); --j) { \- swap_tmp = *j; *j = *(j-1); *(j-1) = swap_tmp; \- } \- } \- void ks_combsort_##name(size_t n, type_t a[]) \- { \- const double shrink_factor = 1.2473309501039786540366528676643; \- int do_swap; \- size_t gap = n; \- type_t tmp, *i, *j; \- do { \- if (gap > 2) { \- gap = (size_t)(gap / shrink_factor); \- if (gap == 9 || gap == 10) gap = 11; \- } \- do_swap = 0; \- for (i = a; i < a + n - gap; ++i) { \- j = i + gap; \- if (__sort_lt(*j, *i)) { \- tmp = *i; *i = *j; *j = tmp; \- do_swap = 1; \- } \- } \- } while (do_swap || gap > 2); \- if (gap != 1) __ks_insertsort_##name(a, a + n); \- } \- void ks_introsort_##name(size_t n, type_t a[]) \- { \- int d; \- ks_isort_stack_t *top, *stack; \- type_t rp, swap_tmp; \- type_t *s, *t, *i, *j, *k; \- \- if (n < 1) return; \- else if (n == 2) { \- if (__sort_lt(a[1], a[0])) { swap_tmp = a[0]; a[0] = a[1]; a[1] = swap_tmp; } \- return; \- } \- for (d = 2; 1ul<<d < n; ++d); \- stack = (ks_isort_stack_t*)malloc(sizeof(ks_isort_stack_t) * ((sizeof(size_t)*d)+2)); \- top = stack; s = a; t = a + (n-1); d <<= 1; \- while (1) { \- if (s < t) { \- if (--d == 0) { \- ks_combsort_##name(t - s + 1, s); \- t = s; \- continue; \- } \- i = s; j = t; k = i + ((j-i)>>1) + 1; \- if (__sort_lt(*k, *i)) { \- if (__sort_lt(*k, *j)) k = j; \- } else k = __sort_lt(*j, *i)? i : j; \- rp = *k; \- if (k != t) { swap_tmp = *k; *k = *t; *t = swap_tmp; } \- for (;;) { \- do ++i; while (__sort_lt(*i, rp)); \- do --j; while (i <= j && __sort_lt(rp, *j)); \- if (j <= i) break; \- swap_tmp = *i; *i = *j; *j = swap_tmp; \- } \- swap_tmp = *i; *i = *t; *t = swap_tmp; \- if (i-s > t-i) { \- if (i-s > 16) { top->left = s; top->right = i-1; top->depth = d; ++top; } \- s = t-i > 16? i+1 : t; \- } else { \- if (t-i > 16) { top->left = i+1; top->right = t; top->depth = d; ++top; } \- t = i-s > 16? i-1 : s; \- } \- } else { \- if (top == stack) { \- free(stack); \- __ks_insertsort_##name(a, a+n); \- return; \- } else { --top; s = (type_t*)top->left; t = (type_t*)top->right; d = top->depth; } \- } \- } \- } \- /* This function is adapted from: http://ndevilla.free.fr/median/ */ \- /* 0 <= kk < n */ \- 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; \- } \- } \- void ks_shuffle_##name(size_t n, type_t a[]) \- { \- int i, j; \- for (i = n; i > 1; --i) { \- type_t tmp; \- j = (int)(drand48() * i); \- tmp = a[j]; a[j] = a[i-1]; a[i-1] = tmp; \- } \- }--#define ks_mergesort(name, n, a, t) ks_mergesort_##name(n, a, t)-#define ks_introsort(name, n, a) ks_introsort_##name(n, a)-#define ks_combsort(name, n, a) ks_combsort_##name(n, a)-#define ks_heapsort(name, n, a) ks_heapsort_##name(n, a)-#define ks_heapmake(name, n, a) ks_heapmake_##name(n, a)-#define ks_heapadjust(name, i, n, a) ks_heapadjust_##name(i, n, a)-#define ks_ksmall(name, n, a, k) ks_ksmall_##name(n, a, k)-#define ks_shuffle(name, n, a) ks_shuffle_##name(n, a)--#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)--#endif
− samtools-0.1.13/kstring.c
@@ -1,212 +0,0 @@-#include <stdarg.h>-#include <stdio.h>-#include <ctype.h>-#include <string.h>-#include <stdint.h>-#include "kstring.h"--int ksprintf(kstring_t *s, const char *fmt, ...)-{- va_list ap;- int l;- va_start(ap, fmt);- l = vsnprintf(s->s + s->l, s->m - s->l, fmt, ap); // This line does not work with glibc 2.0. See `man snprintf'.- va_end(ap);- if (l + 1 > s->m - s->l) {- s->m = s->l + l + 2;- kroundup32(s->m);- s->s = (char*)realloc(s->s, s->m);- va_start(ap, fmt);- l = vsnprintf(s->s + s->l, s->m - s->l, fmt, ap);- }- va_end(ap);- s->l += l;- return l;-}--char *kstrtok(const char *str, const char *sep, ks_tokaux_t *aux)-{- const char *p, *start;- if (sep) { // set up the table- if (str == 0 && (aux->tab[0]&1)) return 0; // no need to set up if we have finished- aux->finished = 0;- if (sep[1]) {- aux->sep = -1;- aux->tab[0] = aux->tab[1] = aux->tab[2] = aux->tab[3] = 0;- for (p = sep; *p; ++p) aux->tab[*p>>6] |= 1ull<<(*p&0x3f);- } else aux->sep = sep[0];- }- if (aux->finished) return 0;- else if (str) aux->p = str - 1, aux->finished = 0;- if (aux->sep < 0) {- for (p = start = aux->p + 1; *p; ++p)- if (aux->tab[*p>>6]>>(*p&0x3f)&1) break;- } else {- for (p = start = aux->p + 1; *p; ++p)- if (*p == aux->sep) break;- }- aux->p = p; // end of token- if (*p == 0) aux->finished = 1; // no more tokens- return (char*)start;-}--// s MUST BE a null terminated string; l = strlen(s)-int ksplit_core(char *s, int delimiter, int *_max, int **_offsets)-{- int i, n, max, last_char, last_start, *offsets, l;- n = 0; max = *_max; offsets = *_offsets;- l = strlen(s);- -#define __ksplit_aux do { \- if (_offsets) { \- s[i] = 0; \- if (n == max) { \- max = max? max<<1 : 2; \- offsets = (int*)realloc(offsets, sizeof(int) * max); \- } \- offsets[n++] = last_start; \- } else ++n; \- } while (0)-- for (i = 0, last_char = last_start = 0; i <= l; ++i) {- if (delimiter == 0) {- if (isspace(s[i]) || s[i] == 0) {- if (isgraph(last_char)) __ksplit_aux; // the end of a field- } else {- if (isspace(last_char) || last_char == 0) last_start = i;- }- } else {- if (s[i] == delimiter || s[i] == 0) {- if (last_char != 0 && last_char != delimiter) __ksplit_aux; // the end of a field- } else {- if (last_char == delimiter || last_char == 0) last_start = i;- }- }- last_char = s[i];- }- *_max = max; *_offsets = offsets;- return n;-}--/**********************- * Boyer-Moore search *- **********************/--typedef unsigned char ubyte_t;--// reference: http://www-igm.univ-mlv.fr/~lecroq/string/node14.html-static int *ksBM_prep(const ubyte_t *pat, int m)-{- int i, *suff, *prep, *bmGs, *bmBc;- prep = calloc(m + 256, sizeof(int));- bmGs = prep; bmBc = prep + m;- { // preBmBc()- for (i = 0; i < 256; ++i) bmBc[i] = m;- for (i = 0; i < m - 1; ++i) bmBc[pat[i]] = m - i - 1;- }- suff = calloc(m, sizeof(int));- { // suffixes()- int f = 0, g;- suff[m - 1] = m;- g = m - 1;- for (i = m - 2; i >= 0; --i) {- if (i > g && suff[i + m - 1 - f] < i - g)- suff[i] = suff[i + m - 1 - f];- else {- if (i < g) g = i;- f = i;- while (g >= 0 && pat[g] == pat[g + m - 1 - f]) --g;- suff[i] = f - g;- }- }- }- { // preBmGs()- int j = 0;- for (i = 0; i < m; ++i) bmGs[i] = m;- for (i = m - 1; i >= 0; --i)- if (suff[i] == i + 1)- for (; j < m - 1 - i; ++j)- if (bmGs[j] == m)- bmGs[j] = m - 1 - i;- for (i = 0; i <= m - 2; ++i)- bmGs[m - 1 - suff[i]] = m - 1 - i;- }- free(suff);- return prep;-}--void *kmemmem(const void *_str, int n, const void *_pat, int m, int **_prep)-{- int i, j, *prep = 0, *bmGs, *bmBc;- const ubyte_t *str, *pat;- str = (const ubyte_t*)_str; pat = (const ubyte_t*)_pat;- prep = (_prep == 0 || *_prep == 0)? ksBM_prep(pat, m) : *_prep;- if (_prep && *_prep == 0) *_prep = prep;- bmGs = prep; bmBc = prep + m;- j = 0;- while (j <= n - m) {- for (i = m - 1; i >= 0 && pat[i] == str[i+j]; --i);- if (i >= 0) {- int max = bmBc[str[i+j]] - m + 1 + i;- if (max < bmGs[i]) max = bmGs[i];- j += max;- } else return (void*)(str + j);- }- if (_prep == 0) free(prep);- return 0;-}--char *kstrstr(const char *str, const char *pat, int **_prep)-{- return (char*)kmemmem(str, strlen(str), pat, strlen(pat), _prep);-}--char *kstrnstr(const char *str, const char *pat, int n, int **_prep)-{- return (char*)kmemmem(str, n, pat, strlen(pat), _prep);-}--/***********************- * The main() function *- ***********************/--#ifdef KSTRING_MAIN-#include <stdio.h>-int main()-{- kstring_t *s;- int *fields, n, i;- ks_tokaux_t aux;- char *p;- s = (kstring_t*)calloc(1, sizeof(kstring_t));- // test ksprintf()- ksprintf(s, " abcdefg: %d ", 100);- printf("'%s'\n", s->s);- // test ksplit()- fields = ksplit(s, 0, &n);- for (i = 0; i < n; ++i)- printf("field[%d] = '%s'\n", i, s->s + fields[i]);- // test kstrtok()- s->l = 0;- for (p = kstrtok("ab:cde:fg/hij::k", ":/", &aux); p; p = kstrtok(0, 0, &aux)) {- kputsn(p, aux.p - p, s);- kputc('\n', s);- }- printf("%s", s->s);- // free- free(s->s); free(s); free(fields);-- {- static char *str = "abcdefgcdgcagtcakcdcd";- static char *pat = "cd";- char *ret, *s = str;- int *prep = 0;- while ((ret = kstrstr(s, pat, &prep)) != 0) {- printf("match: %s\n", ret);- s = ret + prep[0];- }- free(prep);- }- return 0;-}-#endif
− samtools-0.1.13/kstring.h
@@ -1,117 +0,0 @@-#ifndef KSTRING_H-#define KSTRING_H--#include <stdlib.h>-#include <string.h>-#include <stdint.h>--#ifndef kroundup32-#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))-#endif--#ifndef KSTRING_T-#define KSTRING_T kstring_t-typedef struct __kstring_t {- size_t l, m;- char *s;-} kstring_t;-#endif--typedef struct {- uint64_t tab[4];- int sep, finished;- const char *p; // end of the current token-} ks_tokaux_t;--#ifdef __cplusplus-extern "C" {-#endif-- int ksprintf(kstring_t *s, const char *fmt, ...);- int ksplit_core(char *s, int delimiter, int *_max, int **_offsets);- char *kstrstr(const char *str, const char *pat, int **_prep);- char *kstrnstr(const char *str, const char *pat, int n, int **_prep);- void *kmemmem(const void *_str, int n, const void *_pat, int m, int **_prep);-- /* kstrtok() is similar to strtok_r() except that str is not- * modified and both str and sep can be NULL. For efficiency, it is- * actually recommended to set both to NULL in the subsequent calls- * if sep is not changed. */- char *kstrtok(const char *str, const char *sep, ks_tokaux_t *aux);--#ifdef __cplusplus-}-#endif- -static inline int kputsn(const char *p, int l, kstring_t *s)-{- if (s->l + l + 1 >= s->m) {- s->m = s->l + l + 2;- kroundup32(s->m);- s->s = (char*)realloc(s->s, s->m);- }- memcpy(s->s + s->l, p, l);- s->l += l;- s->s[s->l] = 0;- return l;-}--static inline int kputs(const char *p, kstring_t *s)-{- return kputsn(p, strlen(p), s);-}--static inline int kputc(int c, kstring_t *s)-{- if (s->l + 1 >= s->m) {- s->m = s->l + 2;- kroundup32(s->m);- s->s = (char*)realloc(s->s, s->m);- }- s->s[s->l++] = c;- s->s[s->l] = 0;- return c;-}--static inline int kputw(int c, kstring_t *s)-{- char buf[16];- int l, x;- if (c == 0) return kputc('0', s);- for (l = 0, x = c < 0? -c : c; x > 0; x /= 10) buf[l++] = x%10 + '0';- if (c < 0) buf[l++] = '-';- if (s->l + l + 1 >= s->m) {- s->m = s->l + l + 2;- kroundup32(s->m);- s->s = (char*)realloc(s->s, s->m);- }- for (x = l - 1; x >= 0; --x) s->s[s->l++] = buf[x];- s->s[s->l] = 0;- return 0;-}--static inline int kputuw(unsigned c, kstring_t *s)-{- char buf[16];- int l, i;- unsigned x;- if (c == 0) return kputc('0', s);- for (l = 0, x = c; x > 0; x /= 10) buf[l++] = x%10 + '0';- if (s->l + l + 1 >= s->m) {- s->m = s->l + l + 2;- kroundup32(s->m);- s->s = (char*)realloc(s->s, s->m);- }- for (i = l - 1; i >= 0; --i) s->s[s->l++] = buf[i];- s->s[s->l] = 0;- return 0;-}--static inline int *ksplit(kstring_t *s, int delimiter, int *n)-{- int max = 0, *offsets = 0;- *n = ksplit_core(s->s, delimiter, &max, &offsets);- return offsets;-}--#endif
− samtools-0.1.13/razf.c
@@ -1,853 +0,0 @@-/*- * RAZF : Random Access compressed(Z) File- * Version: 1.0- * Release Date: 2008-10-27- *- * Copyright 2008, Jue Ruan <ruanjue@gmail.com>, Heng Li <lh3@sanger.ac.uk>- *- * All rights reserved.- *- * Redistribution and use in source and binary forms, with or without- * modification, are permitted provided that the following conditions- * are met:- * 1. Redistributions of source code must retain the above copyright- * notice, this list of conditions and the following disclaimer.- * 2. Redistributions in binary form must reproduce the above copyright- * notice, this list of conditions and the following disclaimer in the- * documentation and/or other materials provided with the distribution.- *- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF- * SUCH DAMAGE.- */--#ifndef _NO_RAZF--#include <fcntl.h>-#include <stdio.h>-#include <stdlib.h>-#include <string.h>-#include <unistd.h>-#include "razf.h"---#if ZLIB_VERNUM < 0x1221-struct _gz_header_s {- int text;- uLong time;- int xflags;- int os;- Bytef *extra;- uInt extra_len;- uInt extra_max;- Bytef *name;- uInt name_max;- Bytef *comment;- uInt comm_max;- int hcrc;- int done;-};-#warning "zlib < 1.2.2.1; RAZF writing is disabled."-#endif--#define DEF_MEM_LEVEL 8--static inline uint32_t byte_swap_4(uint32_t v){- v = ((v & 0x0000FFFFU) << 16) | (v >> 16);- return ((v & 0x00FF00FFU) << 8) | ((v & 0xFF00FF00U) >> 8);-}--static inline uint64_t byte_swap_8(uint64_t v){- v = ((v & 0x00000000FFFFFFFFLLU) << 32) | (v >> 32);- v = ((v & 0x0000FFFF0000FFFFLLU) << 16) | ((v & 0xFFFF0000FFFF0000LLU) >> 16);- return ((v & 0x00FF00FF00FF00FFLLU) << 8) | ((v & 0xFF00FF00FF00FF00LLU) >> 8);-}--static inline int is_big_endian(){- int x = 0x01;- char *c = (char*)&x;- return (c[0] != 0x01);-}--#ifndef _RZ_READONLY-static void add_zindex(RAZF *rz, int64_t in, int64_t out){- if(rz->index->size == rz->index->cap){- rz->index->cap = rz->index->cap * 1.5 + 2;- rz->index->cell_offsets = realloc(rz->index->cell_offsets, sizeof(int) * rz->index->cap);- rz->index->bin_offsets = realloc(rz->index->bin_offsets, sizeof(int64_t) * (rz->index->cap/RZ_BIN_SIZE + 1));- }- if(rz->index->size % RZ_BIN_SIZE == 0) rz->index->bin_offsets[rz->index->size / RZ_BIN_SIZE] = out;- rz->index->cell_offsets[rz->index->size] = out - rz->index->bin_offsets[rz->index->size / RZ_BIN_SIZE];- rz->index->size ++;-}--static void save_zindex(RAZF *rz, int fd){- int32_t i, v32;- int is_be;- is_be = is_big_endian();- if(is_be) write(fd, &rz->index->size, sizeof(int));- else {- v32 = byte_swap_4((uint32_t)rz->index->size);- write(fd, &v32, sizeof(uint32_t));- }- v32 = rz->index->size / RZ_BIN_SIZE + 1;- if(!is_be){- for(i=0;i<v32;i++) rz->index->bin_offsets[i] = byte_swap_8((uint64_t)rz->index->bin_offsets[i]);- for(i=0;i<rz->index->size;i++) rz->index->cell_offsets[i] = byte_swap_4((uint32_t)rz->index->cell_offsets[i]);- }- write(fd, rz->index->bin_offsets, sizeof(int64_t) * v32);- write(fd, rz->index->cell_offsets, sizeof(int32_t) * rz->index->size);-}-#endif--#ifdef _USE_KNETFILE-static void load_zindex(RAZF *rz, knetFile *fp){-#else-static void load_zindex(RAZF *rz, int fd){-#endif- int32_t i, v32;- int is_be;- if(!rz->load_index) return;- if(rz->index == NULL) rz->index = malloc(sizeof(ZBlockIndex));- is_be = is_big_endian();-#ifdef _USE_KNETFILE- knet_read(fp, &rz->index->size, sizeof(int));-#else- read(fd, &rz->index->size, sizeof(int));-#endif- if(!is_be) rz->index->size = byte_swap_4((uint32_t)rz->index->size);- rz->index->cap = rz->index->size;- v32 = rz->index->size / RZ_BIN_SIZE + 1;- rz->index->bin_offsets = malloc(sizeof(int64_t) * v32);-#ifdef _USE_KNETFILE- knet_read(fp, rz->index->bin_offsets, sizeof(int64_t) * v32);-#else- read(fd, rz->index->bin_offsets, sizeof(int64_t) * v32);-#endif- rz->index->cell_offsets = malloc(sizeof(int) * rz->index->size);-#ifdef _USE_KNETFILE- knet_read(fp, rz->index->cell_offsets, sizeof(int) * rz->index->size);-#else- read(fd, rz->index->cell_offsets, sizeof(int) * rz->index->size);-#endif- if(!is_be){- for(i=0;i<v32;i++) rz->index->bin_offsets[i] = byte_swap_8((uint64_t)rz->index->bin_offsets[i]);- for(i=0;i<rz->index->size;i++) rz->index->cell_offsets[i] = byte_swap_4((uint32_t)rz->index->cell_offsets[i]);- }-}--#ifdef _RZ_READONLY-static RAZF* razf_open_w(int fd)-{- fprintf(stderr, "[razf_open_w] Writing is not available with zlib ver < 1.2.2.1\n");- return 0;-}-#else-static RAZF* razf_open_w(int fd){- RAZF *rz;-#ifdef _WIN32- setmode(fd, O_BINARY);-#endif- rz = calloc(1, sizeof(RAZF));- rz->mode = 'w';-#ifdef _USE_KNETFILE- rz->x.fpw = fd;-#else- rz->filedes = fd;-#endif- rz->stream = calloc(sizeof(z_stream), 1);- rz->inbuf = malloc(RZ_BUFFER_SIZE);- rz->outbuf = malloc(RZ_BUFFER_SIZE);- rz->index = calloc(sizeof(ZBlockIndex), 1);- deflateInit2(rz->stream, RZ_COMPRESS_LEVEL, Z_DEFLATED, WINDOW_BITS + 16, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);- rz->stream->avail_out = RZ_BUFFER_SIZE;- rz->stream->next_out = rz->outbuf;- rz->header = calloc(sizeof(gz_header), 1);- rz->header->os = 0x03; //Unix- rz->header->text = 0;- rz->header->time = 0;- rz->header->extra = malloc(7);- strncpy((char*)rz->header->extra, "RAZF", 4);- rz->header->extra[4] = 1; // obsolete field- // block size = RZ_BLOCK_SIZE, Big-Endian- rz->header->extra[5] = RZ_BLOCK_SIZE >> 8;- rz->header->extra[6] = RZ_BLOCK_SIZE & 0xFF;- rz->header->extra_len = 7;- rz->header->name = rz->header->comment = 0;- rz->header->hcrc = 0;- deflateSetHeader(rz->stream, rz->header);- rz->block_pos = rz->block_off = 0;- return rz;-}--static void _razf_write(RAZF* rz, const void *data, int size){- int tout;- rz->stream->avail_in = size;- rz->stream->next_in = (void*)data;- while(1){- tout = rz->stream->avail_out;- deflate(rz->stream, Z_NO_FLUSH);- rz->out += tout - rz->stream->avail_out;- if(rz->stream->avail_out) break;-#ifdef _USE_KNETFILE- write(rz->x.fpw, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);-#else- write(rz->filedes, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);-#endif- rz->stream->avail_out = RZ_BUFFER_SIZE;- rz->stream->next_out = rz->outbuf;- if(rz->stream->avail_in == 0) break;- };- rz->in += size - rz->stream->avail_in;- rz->block_off += size - rz->stream->avail_in;-}--static void razf_flush(RAZF *rz){- uint32_t tout;- if(rz->buf_len){- _razf_write(rz, rz->inbuf, rz->buf_len);- rz->buf_off = rz->buf_len = 0;- }- if(rz->stream->avail_out){-#ifdef _USE_KNETFILE - write(rz->x.fpw, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);-#else - write(rz->filedes, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);-#endif- rz->stream->avail_out = RZ_BUFFER_SIZE;- rz->stream->next_out = rz->outbuf;- }- while(1){- tout = rz->stream->avail_out;- deflate(rz->stream, Z_FULL_FLUSH);- rz->out += tout - rz->stream->avail_out;- if(rz->stream->avail_out == 0){-#ifdef _USE_KNETFILE - write(rz->x.fpw, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);-#else - write(rz->filedes, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);-#endif- rz->stream->avail_out = RZ_BUFFER_SIZE;- rz->stream->next_out = rz->outbuf;- } else break;- }- rz->block_pos = rz->out;- rz->block_off = 0;-}--static void razf_end_flush(RAZF *rz){- uint32_t tout;- if(rz->buf_len){- _razf_write(rz, rz->inbuf, rz->buf_len);- rz->buf_off = rz->buf_len = 0;- }- while(1){- tout = rz->stream->avail_out;- deflate(rz->stream, Z_FINISH);- rz->out += tout - rz->stream->avail_out;- if(rz->stream->avail_out < RZ_BUFFER_SIZE){-#ifdef _USE_KNETFILE - write(rz->x.fpw, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);-#else - write(rz->filedes, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);-#endif- rz->stream->avail_out = RZ_BUFFER_SIZE;- rz->stream->next_out = rz->outbuf;- } else break;- }-}--static void _razf_buffered_write(RAZF *rz, const void *data, int size){- int i, n;- while(1){- if(rz->buf_len == RZ_BUFFER_SIZE){- _razf_write(rz, rz->inbuf, rz->buf_len);- rz->buf_len = 0;- }- if(size + rz->buf_len < RZ_BUFFER_SIZE){- for(i=0;i<size;i++) ((char*)rz->inbuf + rz->buf_len)[i] = ((char*)data)[i];- rz->buf_len += size;- return;- } else {- n = RZ_BUFFER_SIZE - rz->buf_len;- for(i=0;i<n;i++) ((char*)rz->inbuf + rz->buf_len)[i] = ((char*)data)[i];- size -= n;- data += n;- rz->buf_len += n;- }- }-}--int razf_write(RAZF* rz, const void *data, int size){- int ori_size, n;- int64_t next_block;- ori_size = size;- next_block = ((rz->in / RZ_BLOCK_SIZE) + 1) * RZ_BLOCK_SIZE;- while(rz->in + rz->buf_len + size >= next_block){- n = next_block - rz->in - rz->buf_len;- _razf_buffered_write(rz, data, n);- data += n;- size -= n;- razf_flush(rz);- add_zindex(rz, rz->in, rz->out);- next_block = ((rz->in / RZ_BLOCK_SIZE) + 1) * RZ_BLOCK_SIZE;- }- _razf_buffered_write(rz, data, size);- return ori_size;-}-#endif--/* gzip flag byte */-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */-#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */-#define ORIG_NAME 0x08 /* bit 3 set: original file name present */-#define COMMENT 0x10 /* bit 4 set: file comment present */-#define RESERVED 0xE0 /* bits 5..7: reserved */--static int _read_gz_header(unsigned char *data, int size, int *extra_off, int *extra_len){- int method, flags, n, len;- if(size < 2) return 0;- if(data[0] != 0x1f || data[1] != 0x8b) return 0;- if(size < 4) return 0;- method = data[2];- flags = data[3];- if(method != Z_DEFLATED || (flags & RESERVED)) return 0;- n = 4 + 6; // Skip 6 bytes- *extra_off = n + 2;- *extra_len = 0;- if(flags & EXTRA_FIELD){- if(size < n + 2) return 0;- len = ((int)data[n + 1] << 8) | data[n];- n += 2;- *extra_off = n;- while(len){- if(n >= size) return 0;- n ++;- len --;- }- *extra_len = n - (*extra_off);- }- if(flags & ORIG_NAME) while(n < size && data[n++]);- if(flags & COMMENT) while(n < size && data[n++]);- if(flags & HEAD_CRC){- if(n + 2 > size) return 0;- n += 2;- }- return n;-}--#ifdef _USE_KNETFILE-static RAZF* razf_open_r(knetFile *fp, int _load_index){-#else-static RAZF* razf_open_r(int fd, int _load_index){-#endif- RAZF *rz;- int ext_off, ext_len;- int n, is_be, ret;- int64_t end;- unsigned char c[] = "RAZF";- rz = calloc(1, sizeof(RAZF));- rz->mode = 'r';-#ifdef _USE_KNETFILE- rz->x.fpr = fp;-#else-#ifdef _WIN32- setmode(fd, O_BINARY);-#endif- rz->filedes = fd;-#endif- rz->stream = calloc(sizeof(z_stream), 1);- rz->inbuf = malloc(RZ_BUFFER_SIZE);- rz->outbuf = malloc(RZ_BUFFER_SIZE);- rz->end = rz->src_end = 0x7FFFFFFFFFFFFFFFLL;-#ifdef _USE_KNETFILE- n = knet_read(rz->x.fpr, rz->inbuf, RZ_BUFFER_SIZE);-#else- n = read(rz->filedes, rz->inbuf, RZ_BUFFER_SIZE);-#endif- ret = _read_gz_header(rz->inbuf, n, &ext_off, &ext_len);- if(ret == 0){- PLAIN_FILE:- rz->in = n;- rz->file_type = FILE_TYPE_PLAIN;- memcpy(rz->outbuf, rz->inbuf, n);- rz->buf_len = n;- free(rz->stream);- rz->stream = NULL;- return rz;- }- rz->header_size = ret;- ret = inflateInit2(rz->stream, -WINDOW_BITS);- if(ret != Z_OK){ inflateEnd(rz->stream); goto PLAIN_FILE;}- rz->stream->avail_in = n - rz->header_size;- rz->stream->next_in = rz->inbuf + rz->header_size;- rz->stream->avail_out = RZ_BUFFER_SIZE;- rz->stream->next_out = rz->outbuf;- rz->file_type = FILE_TYPE_GZ;- rz->in = rz->header_size;- rz->block_pos = rz->header_size;- rz->next_block_pos = rz->header_size;- rz->block_off = 0;- if(ext_len < 7 || memcmp(rz->inbuf + ext_off, c, 4) != 0) return rz;- if(((((unsigned char*)rz->inbuf)[ext_off + 5] << 8) | ((unsigned char*)rz->inbuf)[ext_off + 6]) != RZ_BLOCK_SIZE){- fprintf(stderr, " -- WARNING: RZ_BLOCK_SIZE is not %d, treat source as gz file. in %s -- %s:%d --\n", RZ_BLOCK_SIZE, __FUNCTION__, __FILE__, __LINE__);- return rz;- }- rz->load_index = _load_index;- rz->file_type = FILE_TYPE_RZ;-#ifdef _USE_KNETFILE- if(knet_seek(fp, -16, SEEK_END) == -1){-#else- if(lseek(fd, -16, SEEK_END) == -1){-#endif- UNSEEKABLE:- rz->seekable = 0;- rz->index = NULL;- rz->src_end = rz->end = 0x7FFFFFFFFFFFFFFFLL;- } else {- is_be = is_big_endian();- rz->seekable = 1;-#ifdef _USE_KNETFILE- knet_read(fp, &end, sizeof(int64_t));-#else- read(fd, &end, sizeof(int64_t));-#endif - if(!is_be) rz->src_end = (int64_t)byte_swap_8((uint64_t)end);- else rz->src_end = end;--#ifdef _USE_KNETFILE- knet_read(fp, &end, sizeof(int64_t));-#else- read(fd, &end, sizeof(int64_t));-#endif - if(!is_be) rz->end = (int64_t)byte_swap_8((uint64_t)end);- else rz->end = end;- if(n > rz->end){- rz->stream->avail_in -= n - rz->end;- n = rz->end;- }- if(rz->end > rz->src_end){-#ifdef _USE_KNETFILE- knet_seek(fp, rz->in, SEEK_SET);-#else- lseek(fd, rz->in, SEEK_SET);-#endif- goto UNSEEKABLE;- }-#ifdef _USE_KNETFILE- knet_seek(fp, rz->end, SEEK_SET);- if(knet_tell(fp) != rz->end){- knet_seek(fp, rz->in, SEEK_SET);-#else- if(lseek(fd, rz->end, SEEK_SET) != rz->end){- lseek(fd, rz->in, SEEK_SET);-#endif- goto UNSEEKABLE;- }-#ifdef _USE_KNETFILE- load_zindex(rz, fp);- knet_seek(fp, n, SEEK_SET);-#else- load_zindex(rz, fd);- lseek(fd, n, SEEK_SET);-#endif- }- return rz;-}--#ifdef _USE_KNETFILE-RAZF* razf_dopen(int fd, const char *mode){- if (strstr(mode, "r")) fprintf(stderr,"[razf_dopen] implement me\n");- else if(strstr(mode, "w")) return razf_open_w(fd);- return NULL;-}--RAZF* razf_dopen2(int fd, const char *mode)-{- fprintf(stderr,"[razf_dopen2] implement me\n");- return NULL;-}-#else-RAZF* razf_dopen(int fd, const char *mode){- if(strstr(mode, "r")) return razf_open_r(fd, 1);- else if(strstr(mode, "w")) return razf_open_w(fd);- else return NULL;-}--RAZF* razf_dopen2(int fd, const char *mode)-{- if(strstr(mode, "r")) return razf_open_r(fd, 0);- else if(strstr(mode, "w")) return razf_open_w(fd);- else return NULL;-}-#endif--static inline RAZF* _razf_open(const char *filename, const char *mode, int _load_index){- int fd;- RAZF *rz;- if(strstr(mode, "r")){-#ifdef _USE_KNETFILE- knetFile *fd = knet_open(filename, "r");- if (fd == 0) {- fprintf(stderr, "[_razf_open] fail to open %s\n", filename);- return NULL;- }-#else-#ifdef _WIN32- fd = open(filename, O_RDONLY | O_BINARY);-#else- fd = open(filename, O_RDONLY);-#endif-#endif- if(fd < 0) return NULL;- rz = razf_open_r(fd, _load_index);- } else if(strstr(mode, "w")){-#ifdef _WIN32- fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);-#else- fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);-#endif- if(fd < 0) return NULL;- rz = razf_open_w(fd);- } else return NULL;- return rz;-}--RAZF* razf_open(const char *filename, const char *mode){- return _razf_open(filename, mode, 1);-}--RAZF* razf_open2(const char *filename, const char *mode){- return _razf_open(filename, mode, 0);-}--int razf_get_data_size(RAZF *rz, int64_t *u_size, int64_t *c_size){- int64_t n;- if(rz->mode != 'r' && rz->mode != 'R') return 0;- switch(rz->file_type){- case FILE_TYPE_PLAIN:- if(rz->end == 0x7fffffffffffffffLL){-#ifdef _USE_KNETFILE- if(knet_seek(rz->x.fpr, 0, SEEK_CUR) == -1) return 0;- n = knet_tell(rz->x.fpr);- knet_seek(rz->x.fpr, 0, SEEK_END);- rz->end = knet_tell(rz->x.fpr);- knet_seek(rz->x.fpr, n, SEEK_SET);-#else- if((n = lseek(rz->filedes, 0, SEEK_CUR)) == -1) return 0;- rz->end = lseek(rz->filedes, 0, SEEK_END);- lseek(rz->filedes, n, SEEK_SET);-#endif - }- *u_size = *c_size = rz->end;- return 1;- case FILE_TYPE_GZ:- return 0;- case FILE_TYPE_RZ:- if(rz->src_end == rz->end) return 0;- *u_size = rz->src_end;- *c_size = rz->end;- return 1;- default:- return 0;- }-}--static int _razf_read(RAZF* rz, void *data, int size){- int ret, tin;- if(rz->z_eof || rz->z_err) return 0;- if (rz->file_type == FILE_TYPE_PLAIN) {-#ifdef _USE_KNETFILE- ret = knet_read(rz->x.fpr, data, size);-#else- ret = read(rz->filedes, data, size);-#endif - if (ret == 0) rz->z_eof = 1;- return ret;- }- rz->stream->avail_out = size;- rz->stream->next_out = data;- while(rz->stream->avail_out){- if(rz->stream->avail_in == 0){- if(rz->in >= rz->end){ rz->z_eof = 1; break; }- if(rz->end - rz->in < RZ_BUFFER_SIZE){-#ifdef _USE_KNETFILE- rz->stream->avail_in = knet_read(rz->x.fpr, rz->inbuf, rz->end -rz->in);-#else- rz->stream->avail_in = read(rz->filedes, rz->inbuf, rz->end -rz->in);-#endif - } else {-#ifdef _USE_KNETFILE- rz->stream->avail_in = knet_read(rz->x.fpr, rz->inbuf, RZ_BUFFER_SIZE);-#else- rz->stream->avail_in = read(rz->filedes, rz->inbuf, RZ_BUFFER_SIZE);-#endif - }- if(rz->stream->avail_in == 0){- rz->z_eof = 1;- break;- }- rz->stream->next_in = rz->inbuf;- }- tin = rz->stream->avail_in;- ret = inflate(rz->stream, Z_BLOCK);- rz->in += tin - rz->stream->avail_in;- if(ret == Z_NEED_DICT || ret == Z_MEM_ERROR || ret == Z_DATA_ERROR){- fprintf(stderr, "[_razf_read] inflate error: %d %s (at %s:%d)\n", ret, rz->stream->msg ? rz->stream->msg : "", __FILE__, __LINE__);- rz->z_err = 1;- break;- }- if(ret == Z_STREAM_END){- rz->z_eof = 1;- break;- }- if ((rz->stream->data_type&128) && !(rz->stream->data_type&64)){- rz->buf_flush = 1;- rz->next_block_pos = rz->in;- break;- }- }- return size - rz->stream->avail_out;-}--int razf_read(RAZF *rz, void *data, int size){- int ori_size, i;- ori_size = size;- while(size > 0){- if(rz->buf_len){- if(size < rz->buf_len){- for(i=0;i<size;i++) ((char*)data)[i] = ((char*)rz->outbuf + rz->buf_off)[i];- rz->buf_off += size;- rz->buf_len -= size;- data += size;- rz->block_off += size;- size = 0;- break;- } else {- for(i=0;i<rz->buf_len;i++) ((char*)data)[i] = ((char*)rz->outbuf + rz->buf_off)[i];- data += rz->buf_len;- size -= rz->buf_len;- rz->block_off += rz->buf_len;- rz->buf_off = 0;- rz->buf_len = 0;- if(rz->buf_flush){- rz->block_pos = rz->next_block_pos;- rz->block_off = 0;- rz->buf_flush = 0;- }- }- } else if(rz->buf_flush){- rz->block_pos = rz->next_block_pos;- rz->block_off = 0;- rz->buf_flush = 0;- }- if(rz->buf_flush) continue;- rz->buf_len = _razf_read(rz, rz->outbuf, RZ_BUFFER_SIZE);- if(rz->z_eof && rz->buf_len == 0) break;- }- rz->out += ori_size - size;- return ori_size - size;-}--int razf_skip(RAZF* rz, int size){- int ori_size;- ori_size = size;- while(size > 0){- if(rz->buf_len){- if(size < rz->buf_len){- rz->buf_off += size;- rz->buf_len -= size;- rz->block_off += size;- size = 0;- break;- } else {- size -= rz->buf_len;- rz->buf_off = 0;- rz->buf_len = 0;- rz->block_off += rz->buf_len;- if(rz->buf_flush){- rz->block_pos = rz->next_block_pos;- rz->block_off = 0;- rz->buf_flush = 0;- }- }- } else if(rz->buf_flush){- rz->block_pos = rz->next_block_pos;- rz->block_off = 0;- rz->buf_flush = 0;- }- if(rz->buf_flush) continue;- rz->buf_len = _razf_read(rz, rz->outbuf, RZ_BUFFER_SIZE);- if(rz->z_eof || rz->z_err) break;- }- rz->out += ori_size - size;- return ori_size - size;-}--static void _razf_reset_read(RAZF *rz, int64_t in, int64_t out){-#ifdef _USE_KNETFILE- knet_seek(rz->x.fpr, in, SEEK_SET);-#else- lseek(rz->filedes, in, SEEK_SET);-#endif- rz->in = in;- rz->out = out;- rz->block_pos = in;- rz->next_block_pos = in;- rz->block_off = 0;- rz->buf_flush = 0;- rz->z_eof = rz->z_err = 0;- inflateReset(rz->stream);- rz->stream->avail_in = 0;- rz->buf_off = rz->buf_len = 0;-}--int64_t razf_jump(RAZF *rz, int64_t block_start, int block_offset){- int64_t pos;- rz->z_eof = 0;- if(rz->file_type == FILE_TYPE_PLAIN){- rz->buf_off = rz->buf_len = 0;- pos = block_start + block_offset;-#ifdef _USE_KNETFILE- knet_seek(rz->x.fpr, pos, SEEK_SET);- pos = knet_tell(rz->x.fpr);-#else- pos = lseek(rz->filedes, pos, SEEK_SET);-#endif- rz->out = rz->in = pos;- return pos;- }- if(block_start == rz->block_pos && block_offset >= rz->block_off) {- block_offset -= rz->block_off;- goto SKIP; // Needn't reset inflate- }- if(block_start == 0) block_start = rz->header_size; // Automaticly revist wrong block_start- _razf_reset_read(rz, block_start, 0);- SKIP:- if(block_offset) razf_skip(rz, block_offset);- return rz->block_off;-}--int64_t razf_seek(RAZF* rz, int64_t pos, int where){- int64_t idx;- int64_t seek_pos, new_out;- rz->z_eof = 0;- if (where == SEEK_CUR) pos += rz->out;- else if (where == SEEK_END) pos += rz->src_end;- if(rz->file_type == FILE_TYPE_PLAIN){-#ifdef _USE_KNETFILE- knet_seek(rz->x.fpr, pos, SEEK_SET);- seek_pos = knet_tell(rz->x.fpr);-#else- seek_pos = lseek(rz->filedes, pos, SEEK_SET);-#endif- rz->buf_off = rz->buf_len = 0;- rz->out = rz->in = seek_pos;- return seek_pos;- } else if(rz->file_type == FILE_TYPE_GZ){- if(pos >= rz->out) goto SKIP;- return rz->out;- }- if(pos == rz->out) return pos;- if(pos > rz->src_end) return rz->out;- if(!rz->seekable || !rz->load_index){- if(pos >= rz->out) goto SKIP;- }- idx = pos / RZ_BLOCK_SIZE - 1;- seek_pos = (idx < 0)? rz->header_size:(rz->index->cell_offsets[idx] + rz->index->bin_offsets[idx / RZ_BIN_SIZE]);- new_out = (idx + 1) * RZ_BLOCK_SIZE;- if(pos > rz->out && new_out <= rz->out) goto SKIP;- _razf_reset_read(rz, seek_pos, new_out);- SKIP:- razf_skip(rz, (int)(pos - rz->out));- return rz->out;-}--uint64_t razf_tell2(RAZF *rz)-{- /*- if (rz->load_index) {- int64_t idx, seek_pos;- idx = rz->out / RZ_BLOCK_SIZE - 1;- seek_pos = (idx < 0)? rz->header_size:(rz->index->cell_offsets[idx] + rz->index->bin_offsets[idx / RZ_BIN_SIZE]);- if (seek_pos != rz->block_pos || rz->out%RZ_BLOCK_SIZE != rz->block_off)- fprintf(stderr, "[razf_tell2] inconsistent block offset: (%lld, %lld) != (%lld, %lld)\n",- (long long)seek_pos, (long long)rz->out%RZ_BLOCK_SIZE, (long long)rz->block_pos, (long long) rz->block_off);- }- */- return (uint64_t)rz->block_pos<<16 | (rz->block_off&0xffff);-}--int64_t razf_seek2(RAZF *rz, uint64_t voffset, int where)-{- if (where != SEEK_SET) return -1;- return razf_jump(rz, voffset>>16, voffset&0xffff);-}--void razf_close(RAZF *rz){- if(rz->mode == 'w'){-#ifndef _RZ_READONLY- razf_end_flush(rz);- deflateEnd(rz->stream);-#ifdef _USE_KNETFILE- save_zindex(rz, rz->x.fpw);- if(is_big_endian()){- write(rz->x.fpw, &rz->in, sizeof(int64_t));- write(rz->x.fpw, &rz->out, sizeof(int64_t));- } else {- uint64_t v64 = byte_swap_8((uint64_t)rz->in);- write(rz->x.fpw, &v64, sizeof(int64_t));- v64 = byte_swap_8((uint64_t)rz->out);- write(rz->x.fpw, &v64, sizeof(int64_t));- }-#else- save_zindex(rz, rz->filedes);- if(is_big_endian()){- write(rz->filedes, &rz->in, sizeof(int64_t));- write(rz->filedes, &rz->out, sizeof(int64_t));- } else {- uint64_t v64 = byte_swap_8((uint64_t)rz->in);- write(rz->filedes, &v64, sizeof(int64_t));- v64 = byte_swap_8((uint64_t)rz->out);- write(rz->filedes, &v64, sizeof(int64_t));- }-#endif-#endif- } else if(rz->mode == 'r'){- if(rz->stream) inflateEnd(rz->stream);- }- if(rz->inbuf) free(rz->inbuf);- if(rz->outbuf) free(rz->outbuf);- if(rz->header){- free(rz->header->extra);- free(rz->header->name);- free(rz->header->comment);- free(rz->header);- }- if(rz->index){- free(rz->index->bin_offsets);- free(rz->index->cell_offsets);- free(rz->index);- }- free(rz->stream);-#ifdef _USE_KNETFILE- if (rz->mode == 'r')- knet_close(rz->x.fpr);- if (rz->mode == 'w')- close(rz->x.fpw);-#else- close(rz->filedes);-#endif- free(rz);-}--#endif
− samtools-0.1.13/razf.h
@@ -1,134 +0,0 @@- /*-- * RAZF : Random Access compressed(Z) File- * Version: 1.0- * Release Date: 2008-10-27- *- * Copyright 2008, Jue Ruan <ruanjue@gmail.com>, Heng Li <lh3@sanger.ac.uk>- *- * All rights reserved.- *- * Redistribution and use in source and binary forms, with or without- * modification, are permitted provided that the following conditions- * are met:- * 1. Redistributions of source code must retain the above copyright- * notice, this list of conditions and the following disclaimer.- * 2. Redistributions in binary form must reproduce the above copyright- * notice, this list of conditions and the following disclaimer in the- * documentation and/or other materials provided with the distribution.- *- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF- * SUCH DAMAGE.- */---#ifndef __RAZF_RJ_H-#define __RAZF_RJ_H--#include <stdint.h>-#include <stdio.h>-#include "zlib.h"--#ifdef _USE_KNETFILE-#include "knetfile.h"-#endif--#if ZLIB_VERNUM < 0x1221-#define _RZ_READONLY-struct _gz_header_s;-typedef struct _gz_header_s _gz_header;-#define gz_header _gz_header-#endif--#define WINDOW_BITS 15--#ifndef RZ_BLOCK_SIZE-#define RZ_BLOCK_SIZE (1<<WINDOW_BITS)-#endif--#ifndef RZ_BUFFER_SIZE-#define RZ_BUFFER_SIZE 4096-#endif--#ifndef RZ_COMPRESS_LEVEL-#define RZ_COMPRESS_LEVEL 6-#endif--#define RZ_BIN_SIZE ((1LLU << 32) / RZ_BLOCK_SIZE)--typedef struct {- uint32_t *cell_offsets; // i- int64_t *bin_offsets; // i / BIN_SIZE- int size;- int cap;-} ZBlockIndex;-/* When storing index, output bytes in Big-Endian everywhere */--#define FILE_TYPE_RZ 1-#define FILE_TYPE_PLAIN 2-#define FILE_TYPE_GZ 3--typedef struct RandomAccessZFile {- char mode; /* 'w' : write mode; 'r' : read mode */- int file_type;- /* plain file or rz file, razf_read support plain file as input too, in this case, razf_read work as buffered fread */-#ifdef _USE_KNETFILE- union {- knetFile *fpr;- int fpw;- } x;-#else- int filedes; /* the file descriptor */-#endif- z_stream *stream;- ZBlockIndex *index;- int64_t in, out, end, src_end;- /* in: n bytes total in; out: n bytes total out; */- /* end: the end of all data blocks, while the start of index; src_end: the true end position in uncompressed file */- int buf_flush; // buffer should be flush, suspend inflate util buffer is empty- int64_t block_pos, block_off, next_block_pos;- /* block_pos: the start postiion of current block in compressed file */- /* block_off: tell how many bytes have been read from current block */- void *inbuf, *outbuf;- int header_size;- gz_header *header;- /* header is used to transfer inflate_state->mode from HEAD to TYPE after call inflateReset */- int buf_off, buf_len;- int z_err, z_eof;- int seekable;- /* Indice where the source is seekable */- int load_index;- /* set has_index to 0 in mode 'w', then index will be discarded */-} RAZF;--#ifdef __cplusplus-extern "C" {-#endif-- RAZF* razf_dopen(int data_fd, const char *mode);- RAZF *razf_open(const char *fn, const char *mode);- int razf_write(RAZF* rz, const void *data, int size);- int razf_read(RAZF* rz, void *data, int size);- int64_t razf_seek(RAZF* rz, int64_t pos, int where);- void razf_close(RAZF* rz);--#define razf_tell(rz) ((rz)->out)-- RAZF* razf_open2(const char *filename, const char *mode);- RAZF* razf_dopen2(int fd, const char *mode);- uint64_t razf_tell2(RAZF *rz);- int64_t razf_seek2(RAZF *rz, uint64_t voffset, int where);--#ifdef __cplusplus-}-#endif--#endif
− samtools-0.1.13/sam.c
@@ -1,175 +0,0 @@-#include <string.h>-#include <unistd.h>-#include "faidx.h"-#include "sam.h"--#define TYPE_BAM 1-#define TYPE_READ 2--bam_header_t *bam_header_dup(const bam_header_t *h0)-{- bam_header_t *h;- int i;- h = bam_header_init();- *h = *h0;- h->hash = h->dict = h->rg2lib = 0;- h->text = (char*)calloc(h->l_text + 1, 1);- memcpy(h->text, h0->text, h->l_text);- h->target_len = (uint32_t*)calloc(h->n_targets, 4);- h->target_name = (char**)calloc(h->n_targets, sizeof(void*));- for (i = 0; i < h->n_targets; ++i) {- h->target_len[i] = h0->target_len[i];- h->target_name[i] = strdup(h0->target_name[i]);- }- return h;-}-static void append_header_text(bam_header_t *header, char* text, int len)-{- int x = header->l_text + 1;- int y = header->l_text + len + 1; // 1 byte null- if (text == 0) return;- kroundup32(x); - kroundup32(y);- if (x < y) header->text = (char*)realloc(header->text, y);- strncpy(header->text + header->l_text, text, len); // we cannot use strcpy() here.- header->l_text += len;- header->text[header->l_text] = 0;-}--samfile_t *samopen(const char *fn, const char *mode, const void *aux)-{- samfile_t *fp;- fp = (samfile_t*)calloc(1, sizeof(samfile_t));- if (mode[0] == 'r') { // read- fp->type |= TYPE_READ;- if (mode[1] == 'b') { // binary- fp->type |= TYPE_BAM;- fp->x.bam = strcmp(fn, "-")? bam_open(fn, "r") : bam_dopen(fileno(stdin), "r");- if (fp->x.bam == 0) goto open_err_ret;- fp->header = bam_header_read(fp->x.bam);- } else { // text- fp->x.tamr = sam_open(fn);- if (fp->x.tamr == 0) goto open_err_ret;- fp->header = sam_header_read(fp->x.tamr);- if (fp->header->n_targets == 0) { // no @SQ fields- if (aux) { // check if aux is present- bam_header_t *textheader = fp->header;- fp->header = sam_header_read2((const char*)aux);- if (fp->header == 0) goto open_err_ret;- append_header_text(fp->header, textheader->text, textheader->l_text);- bam_header_destroy(textheader);- }- if (fp->header->n_targets == 0)- fprintf(stderr, "[samopen] no @SQ lines in the header.\n");- } else fprintf(stderr, "[samopen] SAM header is present: %d sequences.\n", fp->header->n_targets);- }- } else if (mode[0] == 'w') { // write- fp->header = bam_header_dup((const bam_header_t*)aux);- if (mode[1] == 'b') { // binary- char bmode[3];- bmode[0] = 'w'; bmode[1] = strstr(mode, "u")? 'u' : 0; bmode[2] = 0;- fp->type |= TYPE_BAM;- fp->x.bam = strcmp(fn, "-")? bam_open(fn, bmode) : bam_dopen(fileno(stdout), bmode);- if (fp->x.bam == 0) goto open_err_ret;- bam_header_write(fp->x.bam, fp->header);- } else { // text- // open file- fp->x.tamw = strcmp(fn, "-")? fopen(fn, "w") : stdout;- if (fp->x.tamr == 0) goto open_err_ret;- if (strstr(mode, "X")) fp->type |= BAM_OFSTR<<2;- else if (strstr(mode, "x")) fp->type |= BAM_OFHEX<<2;- else fp->type |= BAM_OFDEC<<2;- // write header- if (strstr(mode, "h")) {- int i;- bam_header_t *alt;- // parse the header text - alt = bam_header_init();- alt->l_text = fp->header->l_text; alt->text = fp->header->text;- sam_header_parse(alt);- alt->l_text = 0; alt->text = 0;- // check if there are @SQ lines in the header- fwrite(fp->header->text, 1, fp->header->l_text, fp->x.tamw);- if (alt->n_targets) { // then write the header text without dumping ->target_{name,len}- if (alt->n_targets != fp->header->n_targets)- fprintf(stderr, "[samopen] inconsistent number of target sequences.\n");- } else { // then dump ->target_{name,len}- for (i = 0; i < fp->header->n_targets; ++i)- fprintf(fp->x.tamw, "@SQ\tSN:%s\tLN:%d\n", fp->header->target_name[i], fp->header->target_len[i]);- }- bam_header_destroy(alt);- }- }- }- return fp;--open_err_ret:- free(fp);- return 0;-}--void samclose(samfile_t *fp)-{- if (fp == 0) return;- if (fp->header) bam_header_destroy(fp->header);- if (fp->type & TYPE_BAM) bam_close(fp->x.bam);- else if (fp->type & TYPE_READ) sam_close(fp->x.tamr);- else fclose(fp->x.tamw);- free(fp);-}--int samread(samfile_t *fp, bam1_t *b)-{- if (fp == 0 || !(fp->type & TYPE_READ)) return -1; // not open for reading- if (fp->type & TYPE_BAM) return bam_read1(fp->x.bam, b);- else return sam_read1(fp->x.tamr, fp->header, b);-}--int samwrite(samfile_t *fp, const bam1_t *b)-{- if (fp == 0 || (fp->type & TYPE_READ)) return -1; // not open for writing- if (fp->type & TYPE_BAM) return bam_write1(fp->x.bam, b);- else {- char *s = bam_format1_core(fp->header, b, fp->type>>2&3);- int l = strlen(s);- fputs(s, fp->x.tamw); fputc('\n', fp->x.tamw);- free(s);- return l + 1;- }-}--int sampileup(samfile_t *fp, int mask, bam_pileup_f func, void *func_data)-{- bam_plbuf_t *buf;- int ret;- bam1_t *b;- b = bam_init1();- buf = bam_plbuf_init(func, func_data);- bam_plbuf_set_mask(buf, mask);- while ((ret = samread(fp, b)) >= 0)- bam_plbuf_push(b, buf);- bam_plbuf_push(0, buf);- bam_plbuf_destroy(buf);- bam_destroy1(b);- return 0;-}--char *samfaipath(const char *fn_ref)-{- char *fn_list = 0;- if (fn_ref == 0) return 0;- fn_list = calloc(strlen(fn_ref) + 5, 1);- strcat(strcpy(fn_list, fn_ref), ".fai");- if (access(fn_list, R_OK) == -1) { // fn_list is unreadable- if (access(fn_ref, R_OK) == -1) {- fprintf(stderr, "[samfaipath] fail to read file %s.\n", fn_ref);- } else {- fprintf(stderr, "[samfaipath] build FASTA index...\n");- if (fai_build(fn_ref) == -1) {- fprintf(stderr, "[samfaipath] fail to build FASTA index.\n");- free(fn_list); fn_list = 0;- }- }- }- return fn_list;-}
− samtools-0.1.13/sam.h
@@ -1,98 +0,0 @@-#ifndef BAM_SAM_H-#define BAM_SAM_H--#include "bam.h"--/*!- @header-- This file provides higher level of I/O routines and unifies the APIs- for SAM and BAM formats. These APIs are more convenient and- recommended.-- @copyright Genome Research Ltd.- */--/*! @typedef- @abstract SAM/BAM file handler- @field type type of the handler; bit 1 for BAM, 2 for reading and bit 3-4 for flag format- @field bam BAM file handler; valid if (type&1) == 1- @field tamr SAM file handler for reading; valid if type == 2- @field tamw SAM file handler for writing; valid if type == 0- @field header header struct- */-typedef struct {- int type;- union {- tamFile tamr;- bamFile bam;- FILE *tamw;- } x;- bam_header_t *header;-} samfile_t;--#ifdef __cplusplus-extern "C" {-#endif-- /*!- @abstract Open a SAM/BAM file-- @param fn SAM/BAM file name; "-" is recognized as stdin (for- reading) or stdout (for writing).-- @param mode open mode /[rw](b?)(u?)(h?)([xX]?)/: 'r' for reading,- 'w' for writing, 'b' for BAM I/O, 'u' for uncompressed BAM output,- 'h' for outputing header in SAM, 'x' for HEX flag and 'X' for- string flag. If 'b' present, it must immediately follow 'r' or- 'w'. Valid modes are "r", "w", "wh", "wx", "whx", "wX", "whX",- "rb", "wb" and "wbu" exclusively.-- @param aux auxiliary data; if mode[0]=='w', aux points to- bam_header_t; if strcmp(mode, "rb")!=0 and @SQ header lines in SAM- are absent, aux points the file name of the list of the reference;- aux is not used otherwise. If @SQ header lines are present in SAM,- aux is not used, either.-- @return SAM/BAM file handler- */- samfile_t *samopen(const char *fn, const char *mode, const void *aux);-- /*!- @abstract Close a SAM/BAM handler- @param fp file handler to be closed- */- void samclose(samfile_t *fp);-- /*!- @abstract Read one alignment- @param fp file handler- @param b alignment- @return bytes read- */- int samread(samfile_t *fp, bam1_t *b);-- /*!- @abstract Write one alignment- @param fp file handler- @param b alignment- @return bytes written- */- int samwrite(samfile_t *fp, const bam1_t *b);-- /*!- @abstract Get the pileup for a whole alignment file- @param fp file handler- @param mask mask transferred to bam_plbuf_set_mask()- @param func user defined function called in the pileup process- #param data user provided data for func()- */- int sampileup(samfile_t *fp, int mask, bam_pileup_f func, void *data);-- char *samfaipath(const char *fn_ref);--#ifdef __cplusplus-}-#endif--#endif
− samtools-0.1.13/sam_header.c
@@ -1,735 +0,0 @@-#include "sam_header.h"-#include <stdio.h>-#include <string.h>-#include <ctype.h>-#include <stdlib.h>-#include <stdarg.h>--#include "khash.h"-KHASH_MAP_INIT_STR(str, const char *)--struct _HeaderList-{- struct _HeaderList *last; // Hack: Used and maintained only by list_append_to_end. Maintained in the root node only.- struct _HeaderList *next;- void *data;-};-typedef struct _HeaderList list_t;-typedef list_t HeaderDict;--typedef struct-{- char key[2];- char *value;-}-HeaderTag;--typedef struct-{- char type[2];- list_t *tags;-}-HeaderLine;--const char *o_hd_tags[] = {"SO","GO",NULL};-const char *r_hd_tags[] = {"VN",NULL};--const char *o_sq_tags[] = {"AS","M5","UR","SP",NULL};-const char *r_sq_tags[] = {"SN","LN",NULL};-const char *u_sq_tags[] = {"SN",NULL};--const char *o_rg_tags[] = {"LB","DS","PU","PI","CN","DT","PL",NULL};-const char *r_rg_tags[] = {"ID",NULL};-const char *u_rg_tags[] = {"ID",NULL};--const char *o_pg_tags[] = {"VN","CL",NULL};-const char *r_pg_tags[] = {"ID",NULL};--const char *types[] = {"HD","SQ","RG","PG","CO",NULL};-const char **optional_tags[] = {o_hd_tags,o_sq_tags,o_rg_tags,o_pg_tags,NULL,NULL};-const char **required_tags[] = {r_hd_tags,r_sq_tags,r_rg_tags,r_pg_tags,NULL,NULL};-const char **unique_tags[] = {NULL, u_sq_tags,u_rg_tags,NULL,NULL,NULL};---static void debug(const char *format, ...)-{- va_list ap;- va_start(ap, format);- vfprintf(stderr, format, ap);- va_end(ap);-}--#if 0-// Replaced by list_append_to_end-static list_t *list_prepend(list_t *root, void *data)-{- list_t *l = malloc(sizeof(list_t));- l->next = root;- l->data = data;- return l;-}-#endif--// Relies on the root->last being correct. Do not use with the other list_*-// routines unless they are fixed to modify root->last as well.-static list_t *list_append_to_end(list_t *root, void *data)-{- list_t *l = malloc(sizeof(list_t));- l->last = l;- l->next = NULL;- l->data = data;-- if ( !root )- return l;-- root->last->next = l;- root->last = l;- return root;-}--static list_t *list_append(list_t *root, void *data)-{- list_t *l = root;- while (l && l->next)- l = l->next;- if ( l ) - {- l->next = malloc(sizeof(list_t));- l = l->next;- }- else- {- l = malloc(sizeof(list_t));- root = l;- }- l->data = data;- l->next = NULL;- return root;-}--static void list_free(list_t *root)-{- list_t *l = root;- while (root)- {- l = root;- root = root->next;- free(l);- }-}----// Look for a tag "XY" in a predefined const char *[] array.-static int tag_exists(const char *tag, const char **tags)-{- int itag=0;- if ( !tags ) return -1;- while ( tags[itag] )- {- if ( tags[itag][0]==tag[0] && tags[itag][1]==tag[1] ) return itag; - itag++;- }- return -1;-}----// Mimics the behaviour of getline, except it returns pointer to the next chunk of the text-// or NULL if everything has been read. The lineptr should be freed by the caller. The-// newline character is stripped.-static const char *nextline(char **lineptr, size_t *n, const char *text)-{- int len;- const char *to = text;-- if ( !*to ) return NULL;-- while ( *to && *to!='\n' && *to!='\r' ) to++;- len = to - text + 1;-- if ( *to )- {- // Advance the pointer for the next call- if ( *to=='\n' ) to++;- else if ( *to=='\r' && *(to+1)=='\n' ) to+=2;- }- if ( !len )- return to;-- if ( !*lineptr ) - {- *lineptr = malloc(len);- *n = len;- }- else if ( *n<len ) - {- *lineptr = realloc(*lineptr, len);- *n = len;- }- if ( !*lineptr ) {- debug("[nextline] Insufficient memory!\n");- return 0;- }-- memcpy(*lineptr,text,len);- (*lineptr)[len-1] = 0;-- return to;-}--// name points to "XY", value_from points to the first character of the value string and-// value_to points to the last character of the value string.-static HeaderTag *new_tag(const char *name, const char *value_from, const char *value_to)-{- HeaderTag *tag = malloc(sizeof(HeaderTag));- int len = value_to-value_from+1;-- tag->key[0] = name[0];- tag->key[1] = name[1];- tag->value = malloc(len+1);- memcpy(tag->value,value_from,len+1);- tag->value[len] = 0;- return tag;-}--static HeaderTag *header_line_has_tag(HeaderLine *hline, const char *key)-{- list_t *tags = hline->tags;- while (tags)- {- HeaderTag *tag = tags->data;- if ( tag->key[0]==key[0] && tag->key[1]==key[1] ) return tag;- tags = tags->next;- }- return NULL;-}---// Return codes:-// 0 .. different types or unique tags differ or conflicting tags, cannot be merged-// 1 .. all tags identical -> no need to merge, drop one-// 2 .. the unique tags match and there are some conflicting tags (same tag, different value) -> error, cannot be merged nor duplicated-// 3 .. there are some missing complementary tags and no unique conflict -> can be merged into a single line-static int sam_header_compare_lines(HeaderLine *hline1, HeaderLine *hline2)-{- HeaderTag *t1, *t2;-- if ( hline1->type[0]!=hline2->type[0] || hline1->type[1]!=hline2->type[1] )- return 0;-- int itype = tag_exists(hline1->type,types);- if ( itype==-1 ) {- debug("[sam_header_compare_lines] Unknown type [%c%c]\n", hline1->type[0],hline1->type[1]);- return -1; // FIXME (lh3): error; I do not know how this will be handled in Petr's code- }-- if ( unique_tags[itype] )- {- t1 = header_line_has_tag(hline1,unique_tags[itype][0]);- t2 = header_line_has_tag(hline2,unique_tags[itype][0]);- if ( !t1 || !t2 ) // this should never happen, the unique tags are required- return 2;-- if ( strcmp(t1->value,t2->value) )- return 0; // the unique tags differ, cannot be merged- }- if ( !required_tags[itype] && !optional_tags[itype] )- {- t1 = hline1->tags->data;- t2 = hline2->tags->data;- if ( !strcmp(t1->value,t2->value) ) return 1; // identical comments- return 0;- }-- int missing=0, itag=0;- while ( required_tags[itype] && required_tags[itype][itag] )- {- t1 = header_line_has_tag(hline1,required_tags[itype][itag]);- t2 = header_line_has_tag(hline2,required_tags[itype][itag]);- if ( !t1 && !t2 )- return 2; // this should never happen- else if ( !t1 || !t2 )- missing = 1; // there is some tag missing in one of the hlines- else if ( strcmp(t1->value,t2->value) )- {- if ( unique_tags[itype] )- return 2; // the lines have a matching unique tag but have a conflicting tag- - return 0; // the lines contain conflicting tags, cannot be merged- }- itag++;- }- itag = 0;- while ( optional_tags[itype] && optional_tags[itype][itag] )- {- t1 = header_line_has_tag(hline1,optional_tags[itype][itag]);- t2 = header_line_has_tag(hline2,optional_tags[itype][itag]);- if ( !t1 && !t2 )- {- itag++;- continue;- }- if ( !t1 || !t2 )- missing = 1; // there is some tag missing in one of the hlines- else if ( strcmp(t1->value,t2->value) )- {- if ( unique_tags[itype] )- return 2; // the lines have a matching unique tag but have a conflicting tag-- return 0; // the lines contain conflicting tags, cannot be merged- }- itag++;- }- if ( missing ) return 3; // there are some missing complementary tags with no conflicts, can be merged- return 1;-}---static HeaderLine *sam_header_line_clone(const HeaderLine *hline)-{- list_t *tags;- HeaderLine *out = malloc(sizeof(HeaderLine));- out->type[0] = hline->type[0];- out->type[1] = hline->type[1];- out->tags = NULL;-- tags = hline->tags;- while (tags)- {- HeaderTag *old = tags->data;-- HeaderTag *new = malloc(sizeof(HeaderTag));- new->key[0] = old->key[0];- new->key[1] = old->key[1];- new->value = strdup(old->value);- out->tags = list_append(out->tags, new);-- tags = tags->next;- }- return out;-}--static int sam_header_line_merge_with(HeaderLine *out_hline, const HeaderLine *tmpl_hline)-{- list_t *tmpl_tags;-- if ( out_hline->type[0]!=tmpl_hline->type[0] || out_hline->type[1]!=tmpl_hline->type[1] )- return 0;- - tmpl_tags = tmpl_hline->tags;- while (tmpl_tags)- {- HeaderTag *tmpl_tag = tmpl_tags->data;- HeaderTag *out_tag = header_line_has_tag(out_hline, tmpl_tag->key);- if ( !out_tag )- {- HeaderTag *tag = malloc(sizeof(HeaderTag));- tag->key[0] = tmpl_tag->key[0];- tag->key[1] = tmpl_tag->key[1];- tag->value = strdup(tmpl_tag->value);- out_hline->tags = list_append(out_hline->tags,tag);- }- tmpl_tags = tmpl_tags->next;- }- return 1;-}---static HeaderLine *sam_header_line_parse(const char *headerLine)-{- HeaderLine *hline;- HeaderTag *tag;- const char *from, *to;- from = headerLine;-- if ( *from != '@' ) {- debug("[sam_header_line_parse] expected '@', got [%s]\n", headerLine);- return 0;- }- to = ++from;-- while (*to && *to!='\t') to++;- if ( to-from != 2 ) {- debug("[sam_header_line_parse] expected '@XY', got [%s]\nHint: The header tags must be tab-separated.\n", headerLine);- return 0;- }- - hline = malloc(sizeof(HeaderLine));- hline->type[0] = from[0];- hline->type[1] = from[1];- hline->tags = NULL;-- int itype = tag_exists(hline->type, types);- - from = to;- while (*to && *to=='\t') to++;- if ( to-from != 1 ) {- debug("[sam_header_line_parse] multiple tabs on line [%s] (%d)\n", headerLine,(int)(to-from));- return 0;- }- from = to;- while (*from)- {- while (*to && *to!='\t') to++;-- if ( !required_tags[itype] && !optional_tags[itype] )- {- // CO is a special case, it can contain anything, including tabs- if ( *to ) { to++; continue; }- tag = new_tag(" ",from,to-1);- }- else- tag = new_tag(from,from+3,to-1);-- if ( header_line_has_tag(hline,tag->key) ) - debug("The tag '%c%c' present (at least) twice on line [%s]\n", tag->key[0],tag->key[1], headerLine);- hline->tags = list_append(hline->tags, tag);-- from = to;- while (*to && *to=='\t') to++;- if ( *to && to-from != 1 ) {- debug("[sam_header_line_parse] multiple tabs on line [%s] (%d)\n", headerLine,(int)(to-from));- return 0;- }-- from = to;- }- return hline;-}---// Must be of an existing type, all tags must be recognised and all required tags must be present-static int sam_header_line_validate(HeaderLine *hline)-{- list_t *tags;- HeaderTag *tag;- int itype, itag;- - // Is the type correct?- itype = tag_exists(hline->type, types);- if ( itype==-1 ) - {- debug("The type [%c%c] not recognised.\n", hline->type[0],hline->type[1]);- return 0;- }-- // Has all required tags?- itag = 0;- while ( required_tags[itype] && required_tags[itype][itag] )- {- if ( !header_line_has_tag(hline,required_tags[itype][itag]) )- {- debug("The tag [%c%c] required for [%c%c] not present.\n", required_tags[itype][itag][0],required_tags[itype][itag][1],- hline->type[0],hline->type[1]);- return 0;- }- itag++;- }-- // Are all tags recognised?- tags = hline->tags;- while ( tags )- {- tag = tags->data;- if ( !tag_exists(tag->key,required_tags[itype]) && !tag_exists(tag->key,optional_tags[itype]) )- {- debug("Unknown tag [%c%c] for [%c%c].\n", tag->key[0],tag->key[1], hline->type[0],hline->type[1]);- return 0;- }- tags = tags->next;- }-- return 1;-}---static void print_header_line(FILE *fp, HeaderLine *hline)-{- list_t *tags = hline->tags;- HeaderTag *tag;-- fprintf(fp, "@%c%c", hline->type[0],hline->type[1]);- while (tags)- {- tag = tags->data;-- fprintf(fp, "\t");- if ( tag->key[0]!=' ' || tag->key[1]!=' ' )- fprintf(fp, "%c%c:", tag->key[0],tag->key[1]);- fprintf(fp, "%s", tag->value);-- tags = tags->next;- }- fprintf(fp,"\n");-}---static void sam_header_line_free(HeaderLine *hline)-{- list_t *tags = hline->tags;- while (tags)- {- HeaderTag *tag = tags->data;- free(tag->value);- free(tag);- tags = tags->next;- }- list_free(hline->tags);- free(hline);-}--void sam_header_free(void *_header)-{- HeaderDict *header = (HeaderDict*)_header;- list_t *hlines = header;- while (hlines)- {- sam_header_line_free(hlines->data);- hlines = hlines->next;- }- list_free(header);-}--HeaderDict *sam_header_clone(const HeaderDict *dict)-{- HeaderDict *out = NULL;- while (dict)- {- HeaderLine *hline = dict->data;- out = list_append(out, sam_header_line_clone(hline));- dict = dict->next;- }- return out;-}--// Returns a newly allocated string-char *sam_header_write(const void *_header)-{- const HeaderDict *header = (const HeaderDict*)_header;- char *out = NULL;- int len=0, nout=0;- const list_t *hlines;-- // Calculate the length of the string to allocate- hlines = header;- while (hlines)- {- len += 4; // @XY and \n-- HeaderLine *hline = hlines->data;- list_t *tags = hline->tags;- while (tags)- {- HeaderTag *tag = tags->data;- len += strlen(tag->value) + 1; // \t- if ( tag->key[0]!=' ' || tag->key[1]!=' ' )- len += strlen(tag->value) + 3; // XY:- tags = tags->next;- }- hlines = hlines->next;- }-- nout = 0;- out = malloc(len+1);- hlines = header;- while (hlines)- {- HeaderLine *hline = hlines->data;-- nout += sprintf(out+nout,"@%c%c",hline->type[0],hline->type[1]);-- list_t *tags = hline->tags;- while (tags)- {- HeaderTag *tag = tags->data;- nout += sprintf(out+nout,"\t");- if ( tag->key[0]!=' ' || tag->key[1]!=' ' )- nout += sprintf(out+nout,"%c%c:", tag->key[0],tag->key[1]);- nout += sprintf(out+nout,"%s", tag->value);- tags = tags->next;- }- hlines = hlines->next;- nout += sprintf(out+nout,"\n");- }- out[len] = 0;- return out;-}--void *sam_header_parse2(const char *headerText)-{- list_t *hlines = NULL;- HeaderLine *hline;- const char *text;- char *buf=NULL;- size_t nbuf = 0;-- if ( !headerText )- return 0;-- text = headerText;- while ( (text=nextline(&buf, &nbuf, text)) )- {- hline = sam_header_line_parse(buf);- if ( hline && sam_header_line_validate(hline) )- // With too many (~250,000) reference sequences the header parsing was too slow with list_append.- hlines = list_append_to_end(hlines, hline);- else- {- if (hline) sam_header_line_free(hline);- sam_header_free(hlines);- if ( buf ) free(buf);- return NULL;- }- }- if ( buf ) free(buf);-- return hlines;-}--void *sam_header2tbl(const void *_dict, char type[2], char key_tag[2], char value_tag[2])-{- const HeaderDict *dict = (const HeaderDict*)_dict;- const list_t *l = dict;- khash_t(str) *tbl = kh_init(str);- khiter_t k;- int ret;-- if (_dict == 0) return tbl; // return an empty (not null) hash table- while (l)- {- HeaderLine *hline = l->data;- if ( hline->type[0]!=type[0] || hline->type[1]!=type[1] ) - {- l = l->next;- continue;- }- - HeaderTag *key, *value;- key = header_line_has_tag(hline,key_tag);- value = header_line_has_tag(hline,value_tag); - if ( !key || !value )- {- l = l->next;- continue;- }- - k = kh_get(str, tbl, key->value);- if ( k != kh_end(tbl) )- debug("[sam_header_lookup_table] They key %s not unique.\n", key->value);- k = kh_put(str, tbl, key->value, &ret);- kh_value(tbl, k) = value->value;-- l = l->next;- }- return tbl;-}--char **sam_header2list(const void *_dict, char type[2], char key_tag[2], int *_n)-{- const HeaderDict *dict = (const HeaderDict*)_dict;- const list_t *l = dict;- int max, n;- char **ret;-- ret = 0; *_n = max = n = 0;- while (l)- {- HeaderLine *hline = l->data;- if ( hline->type[0]!=type[0] || hline->type[1]!=type[1] ) - {- l = l->next;- continue;- }- - HeaderTag *key;- key = header_line_has_tag(hline,key_tag);- if ( !key )- {- l = l->next;- continue;- }-- if (n == max) {- max = max? max<<1 : 4;- ret = realloc(ret, max * sizeof(void*));- }- ret[n++] = key->value;-- l = l->next;- }- *_n = n;- return ret;-}--const char *sam_tbl_get(void *h, const char *key)-{- khash_t(str) *tbl = (khash_t(str)*)h;- khint_t k;- k = kh_get(str, tbl, key);- return k == kh_end(tbl)? 0 : kh_val(tbl, k);-}--int sam_tbl_size(void *h)-{- khash_t(str) *tbl = (khash_t(str)*)h;- return h? kh_size(tbl) : 0;-}--void sam_tbl_destroy(void *h)-{- khash_t(str) *tbl = (khash_t(str)*)h;- kh_destroy(str, tbl);-}--void *sam_header_merge(int n, const void **_dicts)-{- const HeaderDict **dicts = (const HeaderDict**)_dicts;- HeaderDict *out_dict;- int idict, status;-- if ( n<2 ) return NULL;-- out_dict = sam_header_clone(dicts[0]);-- for (idict=1; idict<n; idict++)- {- const list_t *tmpl_hlines = dicts[idict];-- while ( tmpl_hlines )- {- list_t *out_hlines = out_dict;- int inserted = 0;- while ( out_hlines )- {- status = sam_header_compare_lines(tmpl_hlines->data, out_hlines->data);- if ( status==0 )- {- out_hlines = out_hlines->next;- continue;- }- - if ( status==2 ) - {- print_header_line(stderr,tmpl_hlines->data);- print_header_line(stderr,out_hlines->data);- debug("Conflicting lines, cannot merge the headers.\n");- return 0;- }- if ( status==3 )- sam_header_line_merge_with(out_hlines->data, tmpl_hlines->data);-- inserted = 1;- break;- }- if ( !inserted )- out_dict = list_append(out_dict, sam_header_line_clone(tmpl_hlines->data));-- tmpl_hlines = tmpl_hlines->next;- }- }-- return out_dict;-}--
− samtools-0.1.13/sam_header.h
@@ -1,24 +0,0 @@-#ifndef __SAM_HEADER_H__-#define __SAM_HEADER_H__--#ifdef __cplusplus-extern "C" {-#endif-- void *sam_header_parse2(const char *headerText);- void *sam_header_merge(int n, const void **dicts);- void sam_header_free(void *header);- char *sam_header_write(const void *headerDict); // returns a newly allocated string-- char **sam_header2list(const void *_dict, char type[2], char key_tag[2], int *_n);-- void *sam_header2tbl(const void *dict, char type[2], char key_tag[2], char value_tag[2]);- const char *sam_tbl_get(void *h, const char *key);- int sam_tbl_size(void *h);- void sam_tbl_destroy(void *h);--#ifdef __cplusplus-}-#endif--#endif
+ samtools-0.1.18/bam.c view
@@ -0,0 +1,362 @@+#include <stdio.h>+#include <ctype.h>+#include <errno.h>+#include <assert.h>+#include "bam.h"+#include "bam_endian.h"+#include "kstring.h"+#include "sam_header.h"++int bam_is_be = 0, bam_verbose = 2;+char *bam_flag2char_table = "pPuUrR12sfd\0\0\0\0\0";++/**************************+ * CIGAR related routines *+ **************************/++uint32_t bam_calend(const bam1_core_t *c, const uint32_t *cigar)+{+ uint32_t k, end;+ end = c->pos;+ for (k = 0; k < c->n_cigar; ++k) {+ int op = cigar[k] & BAM_CIGAR_MASK;+ if (op == BAM_CMATCH || op == BAM_CDEL || op == BAM_CREF_SKIP)+ end += cigar[k] >> BAM_CIGAR_SHIFT;+ }+ return end;+}++int32_t bam_cigar2qlen(const bam1_core_t *c, const uint32_t *cigar)+{+ uint32_t k;+ int32_t l = 0;+ for (k = 0; k < c->n_cigar; ++k) {+ int op = cigar[k] & BAM_CIGAR_MASK;+ if (op == BAM_CMATCH || op == BAM_CINS || op == BAM_CSOFT_CLIP || op == BAM_CEQUAL || op == BAM_CDIFF)+ l += cigar[k] >> BAM_CIGAR_SHIFT;+ }+ return l;+}++/********************+ * BAM I/O routines *+ ********************/++bam_header_t *bam_header_init()+{+ bam_is_be = bam_is_big_endian();+ return (bam_header_t*)calloc(1, sizeof(bam_header_t));+}++void bam_header_destroy(bam_header_t *header)+{+ int32_t i;+ extern void bam_destroy_header_hash(bam_header_t *header);+ if (header == 0) return;+ if (header->target_name) {+ for (i = 0; i < header->n_targets; ++i)+ free(header->target_name[i]);+ free(header->target_name);+ free(header->target_len);+ }+ free(header->text);+ if (header->dict) sam_header_free(header->dict);+ if (header->rg2lib) sam_tbl_destroy(header->rg2lib);+ bam_destroy_header_hash(header);+ free(header);+}++bam_header_t *bam_header_read(bamFile fp)+{+ bam_header_t *header;+ char buf[4];+ int magic_len;+ int32_t i = 1, name_len;+ // check EOF+ i = bgzf_check_EOF(fp);+ if (i < 0) {+ // If the file is a pipe, checking the EOF marker will *always* fail+ // with ESPIPE. Suppress the error message in this case.+ if (errno != ESPIPE) perror("[bam_header_read] bgzf_check_EOF");+ }+ else if (i == 0) fprintf(stderr, "[bam_header_read] EOF marker is absent. The input is probably truncated.\n");+ // read "BAM1"+ magic_len = bam_read(fp, buf, 4);+ if (magic_len != 4 || strncmp(buf, "BAM\001", 4) != 0) {+ fprintf(stderr, "[bam_header_read] invalid BAM binary header (this is not a BAM file).\n");+ return 0;+ }+ header = bam_header_init();+ // read plain text and the number of reference sequences+ bam_read(fp, &header->l_text, 4);+ if (bam_is_be) bam_swap_endian_4p(&header->l_text);+ header->text = (char*)calloc(header->l_text + 1, 1);+ bam_read(fp, header->text, header->l_text);+ bam_read(fp, &header->n_targets, 4);+ if (bam_is_be) bam_swap_endian_4p(&header->n_targets);+ // read reference sequence names and lengths+ header->target_name = (char**)calloc(header->n_targets, sizeof(char*));+ header->target_len = (uint32_t*)calloc(header->n_targets, 4);+ for (i = 0; i != header->n_targets; ++i) {+ bam_read(fp, &name_len, 4);+ if (bam_is_be) bam_swap_endian_4p(&name_len);+ header->target_name[i] = (char*)calloc(name_len, 1);+ bam_read(fp, header->target_name[i], name_len);+ bam_read(fp, &header->target_len[i], 4);+ if (bam_is_be) bam_swap_endian_4p(&header->target_len[i]);+ }+ return header;+}++int bam_header_write(bamFile fp, const bam_header_t *header)+{+ char buf[4];+ int32_t i, name_len, x;+ // write "BAM1"+ strncpy(buf, "BAM\001", 4);+ bam_write(fp, buf, 4);+ // write plain text and the number of reference sequences+ if (bam_is_be) {+ x = bam_swap_endian_4(header->l_text);+ bam_write(fp, &x, 4);+ if (header->l_text) bam_write(fp, header->text, header->l_text);+ x = bam_swap_endian_4(header->n_targets);+ bam_write(fp, &x, 4);+ } else {+ bam_write(fp, &header->l_text, 4);+ if (header->l_text) bam_write(fp, header->text, header->l_text);+ bam_write(fp, &header->n_targets, 4);+ }+ // write sequence names and lengths+ for (i = 0; i != header->n_targets; ++i) {+ char *p = header->target_name[i];+ name_len = strlen(p) + 1;+ if (bam_is_be) {+ x = bam_swap_endian_4(name_len);+ bam_write(fp, &x, 4);+ } else bam_write(fp, &name_len, 4);+ bam_write(fp, p, name_len);+ if (bam_is_be) {+ x = bam_swap_endian_4(header->target_len[i]);+ bam_write(fp, &x, 4);+ } else bam_write(fp, &header->target_len[i], 4);+ }+ bgzf_flush(fp);+ return 0;+}++static void swap_endian_data(const bam1_core_t *c, int data_len, uint8_t *data)+{+ uint8_t *s;+ uint32_t i, *cigar = (uint32_t*)(data + c->l_qname);+ s = data + c->n_cigar*4 + c->l_qname + c->l_qseq + (c->l_qseq + 1)/2;+ for (i = 0; i < c->n_cigar; ++i) bam_swap_endian_4p(&cigar[i]);+ while (s < data + data_len) {+ uint8_t type;+ s += 2; // skip key+ type = toupper(*s); ++s; // skip type+ if (type == 'C' || type == 'A') ++s;+ else if (type == 'S') { bam_swap_endian_2p(s); s += 2; }+ else if (type == 'I' || type == 'F') { bam_swap_endian_4p(s); s += 4; }+ else if (type == 'D') { bam_swap_endian_8p(s); s += 8; }+ else if (type == 'Z' || type == 'H') { while (*s) ++s; ++s; }+ else if (type == 'B') {+ int32_t n, Bsize = bam_aux_type2size(*s);+ memcpy(&n, s + 1, 4);+ if (1 == Bsize) {+ } else if (2 == Bsize) {+ for (i = 0; i < n; i += 2)+ bam_swap_endian_2p(s + 5 + i);+ } else if (4 == Bsize) {+ for (i = 0; i < n; i += 4)+ bam_swap_endian_4p(s + 5 + i);+ }+ bam_swap_endian_4p(s+1); + }+ }+}++int bam_read1(bamFile fp, bam1_t *b)+{+ bam1_core_t *c = &b->core;+ int32_t block_len, ret, i;+ uint32_t x[8];++ assert(BAM_CORE_SIZE == 32);+ if ((ret = bam_read(fp, &block_len, 4)) != 4) {+ if (ret == 0) return -1; // normal end-of-file+ else return -2; // truncated+ }+ if (bam_read(fp, x, BAM_CORE_SIZE) != BAM_CORE_SIZE) return -3;+ if (bam_is_be) {+ bam_swap_endian_4p(&block_len);+ for (i = 0; i < 8; ++i) bam_swap_endian_4p(x + i);+ }+ c->tid = x[0]; c->pos = x[1];+ c->bin = x[2]>>16; c->qual = x[2]>>8&0xff; c->l_qname = x[2]&0xff;+ c->flag = x[3]>>16; c->n_cigar = x[3]&0xffff;+ c->l_qseq = x[4];+ c->mtid = x[5]; c->mpos = x[6]; c->isize = x[7];+ b->data_len = block_len - BAM_CORE_SIZE;+ if (b->m_data < b->data_len) {+ b->m_data = b->data_len;+ kroundup32(b->m_data);+ b->data = (uint8_t*)realloc(b->data, b->m_data);+ }+ if (bam_read(fp, b->data, b->data_len) != b->data_len) return -4;+ b->l_aux = b->data_len - c->n_cigar * 4 - c->l_qname - c->l_qseq - (c->l_qseq+1)/2;+ if (bam_is_be) swap_endian_data(c, b->data_len, b->data);+ return 4 + block_len;+}++inline int bam_write1_core(bamFile fp, const bam1_core_t *c, int data_len, uint8_t *data)+{+ uint32_t x[8], block_len = data_len + BAM_CORE_SIZE, y;+ int i;+ assert(BAM_CORE_SIZE == 32);+ x[0] = c->tid;+ x[1] = c->pos;+ x[2] = (uint32_t)c->bin<<16 | c->qual<<8 | c->l_qname;+ x[3] = (uint32_t)c->flag<<16 | c->n_cigar;+ x[4] = c->l_qseq;+ x[5] = c->mtid;+ x[6] = c->mpos;+ x[7] = c->isize;+ bgzf_flush_try(fp, 4 + block_len);+ if (bam_is_be) {+ for (i = 0; i < 8; ++i) bam_swap_endian_4p(x + i);+ y = block_len;+ bam_write(fp, bam_swap_endian_4p(&y), 4);+ swap_endian_data(c, data_len, data);+ } else bam_write(fp, &block_len, 4);+ bam_write(fp, x, BAM_CORE_SIZE);+ bam_write(fp, data, data_len);+ if (bam_is_be) swap_endian_data(c, data_len, data);+ return 4 + block_len;+}++int bam_write1(bamFile fp, const bam1_t *b)+{+ return bam_write1_core(fp, &b->core, b->data_len, b->data);+}++char *bam_format1_core(const bam_header_t *header, const bam1_t *b, int of)+{+ uint8_t *s = bam1_seq(b), *t = bam1_qual(b);+ int i;+ const bam1_core_t *c = &b->core;+ kstring_t str;+ str.l = str.m = 0; str.s = 0;++ kputsn(bam1_qname(b), c->l_qname-1, &str); kputc('\t', &str);+ if (of == BAM_OFDEC) { kputw(c->flag, &str); kputc('\t', &str); }+ else if (of == BAM_OFHEX) ksprintf(&str, "0x%x\t", c->flag);+ else { // BAM_OFSTR+ for (i = 0; i < 16; ++i)+ if ((c->flag & 1<<i) && bam_flag2char_table[i])+ kputc(bam_flag2char_table[i], &str);+ kputc('\t', &str);+ }+ if (c->tid < 0) kputsn("*\t", 2, &str);+ else {+ if (header) kputs(header->target_name[c->tid] , &str);+ else kputw(c->tid, &str);+ kputc('\t', &str);+ }+ kputw(c->pos + 1, &str); kputc('\t', &str); kputw(c->qual, &str); kputc('\t', &str);+ if (c->n_cigar == 0) kputc('*', &str);+ else {+ for (i = 0; i < c->n_cigar; ++i) {+ kputw(bam1_cigar(b)[i]>>BAM_CIGAR_SHIFT, &str);+ kputc("MIDNSHP=X"[bam1_cigar(b)[i]&BAM_CIGAR_MASK], &str);+ }+ }+ kputc('\t', &str);+ if (c->mtid < 0) kputsn("*\t", 2, &str);+ else if (c->mtid == c->tid) kputsn("=\t", 2, &str);+ else {+ if (header) kputs(header->target_name[c->mtid], &str);+ else kputw(c->mtid, &str);+ kputc('\t', &str);+ }+ kputw(c->mpos + 1, &str); kputc('\t', &str); kputw(c->isize, &str); kputc('\t', &str);+ if (c->l_qseq) {+ for (i = 0; i < c->l_qseq; ++i) kputc(bam_nt16_rev_table[bam1_seqi(s, i)], &str);+ kputc('\t', &str);+ if (t[0] == 0xff) kputc('*', &str);+ else for (i = 0; i < c->l_qseq; ++i) kputc(t[i] + 33, &str);+ } else kputsn("*\t*", 3, &str);+ s = bam1_aux(b);+ while (s < b->data + b->data_len) {+ uint8_t type, key[2];+ key[0] = s[0]; key[1] = s[1];+ s += 2; type = *s; ++s;+ kputc('\t', &str); kputsn((char*)key, 2, &str); kputc(':', &str);+ if (type == 'A') { kputsn("A:", 2, &str); kputc(*s, &str); ++s; }+ else if (type == 'C') { kputsn("i:", 2, &str); kputw(*s, &str); ++s; }+ else if (type == 'c') { kputsn("i:", 2, &str); kputw(*(int8_t*)s, &str); ++s; }+ else if (type == 'S') { kputsn("i:", 2, &str); kputw(*(uint16_t*)s, &str); s += 2; }+ else if (type == 's') { kputsn("i:", 2, &str); kputw(*(int16_t*)s, &str); s += 2; }+ else if (type == 'I') { kputsn("i:", 2, &str); kputuw(*(uint32_t*)s, &str); s += 4; }+ else if (type == 'i') { kputsn("i:", 2, &str); kputw(*(int32_t*)s, &str); s += 4; }+ else if (type == 'f') { ksprintf(&str, "f:%g", *(float*)s); s += 4; }+ else if (type == 'd') { ksprintf(&str, "d:%lg", *(double*)s); s += 8; }+ else if (type == 'Z' || type == 'H') { kputc(type, &str); kputc(':', &str); while (*s) kputc(*s++, &str); ++s; }+ else if (type == 'B') {+ uint8_t sub_type = *(s++);+ int32_t n;+ memcpy(&n, s, 4);+ s += 4; // no point to the start of the array+ kputc(type, &str); kputc(':', &str); kputc(sub_type, &str); // write the typing+ for (i = 0; i < n; ++i) {+ kputc(',', &str);+ if ('c' == sub_type || 'c' == sub_type) { kputw(*(int8_t*)s, &str); ++s; }+ else if ('C' == sub_type) { kputw(*(uint8_t*)s, &str); ++s; }+ else if ('s' == sub_type) { kputw(*(int16_t*)s, &str); s += 2; }+ else if ('S' == sub_type) { kputw(*(uint16_t*)s, &str); s += 2; }+ else if ('i' == sub_type) { kputw(*(int32_t*)s, &str); s += 4; }+ else if ('I' == sub_type) { kputuw(*(uint32_t*)s, &str); s += 4; }+ else if ('f' == sub_type) { ksprintf(&str, "%g", *(float*)s); s += 4; }+ }+ }+ }+ return str.s;+}++char *bam_format1(const bam_header_t *header, const bam1_t *b)+{+ return bam_format1_core(header, b, BAM_OFDEC);+}++void bam_view1(const bam_header_t *header, const bam1_t *b)+{+ char *s = bam_format1(header, b);+ puts(s);+ free(s);+}++int bam_validate1(const bam_header_t *header, const bam1_t *b)+{+ char *s;++ if (b->core.tid < -1 || b->core.mtid < -1) return 0;+ if (header && (b->core.tid >= header->n_targets || b->core.mtid >= header->n_targets)) return 0;++ if (b->data_len < b->core.l_qname) return 0;+ s = memchr(bam1_qname(b), '\0', b->core.l_qname);+ if (s != &bam1_qname(b)[b->core.l_qname-1]) return 0;++ // FIXME: Other fields could also be checked, especially the auxiliary data++ return 1;+}++// FIXME: we should also check the LB tag associated with each alignment+const char *bam_get_library(bam_header_t *h, const bam1_t *b)+{+ const uint8_t *rg;+ if (h->dict == 0) h->dict = sam_header_parse2(h->text);+ if (h->rg2lib == 0) h->rg2lib = sam_header2tbl(h->dict, "RG", "ID", "LB");+ rg = bam_aux_get(b, "RG");+ return (rg == 0)? 0 : sam_tbl_get(h->rg2lib, (const char*)(rg + 1));+}
+ samtools-0.1.18/bam.h view
@@ -0,0 +1,763 @@+/* The MIT License++ Copyright (c) 2008-2010 Genome Research Ltd (GRL).++ 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.+*/++/* Contact: Heng Li <lh3@sanger.ac.uk> */++#ifndef BAM_BAM_H+#define BAM_BAM_H++/*!+ @header++ BAM library provides I/O and various operations on manipulating files+ in the BAM (Binary Alignment/Mapping) or SAM (Sequence Alignment/Map)+ format. It now supports importing from or exporting to SAM, sorting,+ merging, generating pileup, and quickly retrieval of reads overlapped+ with a specified region.++ @copyright Genome Research Ltd.+ */++#define BAM_VERSION "0.1.18 (r982:295)"++#include <stdint.h>+#include <stdlib.h>+#include <string.h>+#include <stdio.h>++#ifndef BAM_LITE+#define BAM_VIRTUAL_OFFSET16+#include "bgzf.h"+/*! @abstract BAM file handler */+typedef BGZF *bamFile;+#define bam_open(fn, mode) bgzf_open(fn, mode)+#define bam_dopen(fd, mode) bgzf_fdopen(fd, mode)+#define bam_close(fp) bgzf_close(fp)+#define bam_read(fp, buf, size) bgzf_read(fp, buf, size)+#define bam_write(fp, buf, size) bgzf_write(fp, buf, size)+#define bam_tell(fp) bgzf_tell(fp)+#define bam_seek(fp, pos, dir) bgzf_seek(fp, pos, dir)+#else+#define BAM_TRUE_OFFSET+#include <zlib.h>+typedef gzFile bamFile;+#define bam_open(fn, mode) gzopen(fn, mode)+#define bam_dopen(fd, mode) gzdopen(fd, mode)+#define bam_close(fp) gzclose(fp)+#define bam_read(fp, buf, size) gzread(fp, buf, size)+/* no bam_write/bam_tell/bam_seek() here */+#endif++/*! @typedef+ @abstract Structure for the alignment header.+ @field n_targets number of reference sequences+ @field target_name names of the reference sequences+ @field target_len lengths of the referene sequences+ @field dict header dictionary+ @field hash hash table for fast name lookup+ @field rg2lib hash table for @RG-ID -> LB lookup+ @field l_text length of the plain text in the header+ @field text plain text++ @discussion Field hash points to null by default. It is a private+ member.+ */+typedef struct {+ int32_t n_targets;+ char **target_name;+ uint32_t *target_len;+ void *dict, *hash, *rg2lib;+ size_t l_text, n_text;+ char *text;+} bam_header_t;++/*! @abstract the read is paired in sequencing, no matter whether it is mapped in a pair */+#define BAM_FPAIRED 1+/*! @abstract the read is mapped in a proper pair */+#define BAM_FPROPER_PAIR 2+/*! @abstract the read itself is unmapped; conflictive with BAM_FPROPER_PAIR */+#define BAM_FUNMAP 4+/*! @abstract the mate is unmapped */+#define BAM_FMUNMAP 8+/*! @abstract the read is mapped to the reverse strand */+#define BAM_FREVERSE 16+/*! @abstract the mate is mapped to the reverse strand */+#define BAM_FMREVERSE 32+/*! @abstract this is read1 */+#define BAM_FREAD1 64+/*! @abstract this is read2 */+#define BAM_FREAD2 128+/*! @abstract not primary alignment */+#define BAM_FSECONDARY 256+/*! @abstract QC failure */+#define BAM_FQCFAIL 512+/*! @abstract optical or PCR duplicate */+#define BAM_FDUP 1024++#define BAM_OFDEC 0+#define BAM_OFHEX 1+#define BAM_OFSTR 2++/*! @abstract defautl mask for pileup */+#define BAM_DEF_MASK (BAM_FUNMAP | BAM_FSECONDARY | BAM_FQCFAIL | BAM_FDUP)++#define BAM_CORE_SIZE sizeof(bam1_core_t)++/**+ * Describing how CIGAR operation/length is packed in a 32-bit integer.+ */+#define BAM_CIGAR_SHIFT 4+#define BAM_CIGAR_MASK ((1 << BAM_CIGAR_SHIFT) - 1)++/*+ CIGAR operations.+ */+/*! @abstract CIGAR: M = match or mismatch*/+#define BAM_CMATCH 0+/*! @abstract CIGAR: I = insertion to the reference */+#define BAM_CINS 1+/*! @abstract CIGAR: D = deletion from the reference */+#define BAM_CDEL 2+/*! @abstract CIGAR: N = skip on the reference (e.g. spliced alignment) */+#define BAM_CREF_SKIP 3+/*! @abstract CIGAR: S = clip on the read with clipped sequence+ present in qseq */+#define BAM_CSOFT_CLIP 4+/*! @abstract CIGAR: H = clip on the read with clipped sequence trimmed off */+#define BAM_CHARD_CLIP 5+/*! @abstract CIGAR: P = padding */+#define BAM_CPAD 6+/*! @abstract CIGAR: equals = match */+#define BAM_CEQUAL 7+/*! @abstract CIGAR: X = mismatch */+#define BAM_CDIFF 8++/*! @typedef+ @abstract Structure for core alignment information.+ @field tid chromosome ID, defined by bam_header_t+ @field pos 0-based leftmost coordinate+ @field strand strand; 0 for forward and 1 otherwise+ @field bin bin calculated by bam_reg2bin()+ @field qual mapping quality+ @field l_qname length of the query name+ @field flag bitwise flag+ @field n_cigar number of CIGAR operations+ @field l_qseq length of the query sequence (read)+ */+typedef struct {+ int32_t tid;+ int32_t pos;+ uint32_t bin:16, qual:8, l_qname:8;+ uint32_t flag:16, n_cigar:16;+ int32_t l_qseq;+ int32_t mtid;+ int32_t mpos;+ int32_t isize;+} bam1_core_t;++/*! @typedef+ @abstract Structure for one alignment.+ @field core core information about the alignment+ @field l_aux length of auxiliary data+ @field data_len current length of bam1_t::data+ @field m_data maximum length of bam1_t::data+ @field data all variable-length data, concatenated; structure: cigar-qname-seq-qual-aux++ @discussion Notes:+ + 1. qname is zero tailing and core.l_qname includes the tailing '\0'.+ 2. l_qseq is calculated from the total length of an alignment block+ on reading or from CIGAR.+ */+typedef struct {+ bam1_core_t core;+ int l_aux, data_len, m_data;+ uint8_t *data;+} bam1_t;++typedef struct __bam_iter_t *bam_iter_t;++#define bam1_strand(b) (((b)->core.flag&BAM_FREVERSE) != 0)+#define bam1_mstrand(b) (((b)->core.flag&BAM_FMREVERSE) != 0)++/*! @function+ @abstract Get the CIGAR array+ @param b pointer to an alignment+ @return pointer to the CIGAR array++ @discussion In the CIGAR array, each element is a 32-bit integer. The+ lower 4 bits gives a CIGAR operation and the higher 28 bits keep the+ length of a CIGAR.+ */+#define bam1_cigar(b) ((uint32_t*)((b)->data + (b)->core.l_qname))++/*! @function+ @abstract Get the name of the query+ @param b pointer to an alignment+ @return pointer to the name string, null terminated+ */+#define bam1_qname(b) ((char*)((b)->data))++/*! @function+ @abstract Get query sequence+ @param b pointer to an alignment+ @return pointer to sequence++ @discussion Each base is encoded in 4 bits: 1 for A, 2 for C, 4 for G,+ 8 for T and 15 for N. Two bases are packed in one byte with the base+ at the higher 4 bits having smaller coordinate on the read. It is+ recommended to use bam1_seqi() macro to get the base.+ */+#define bam1_seq(b) ((b)->data + (b)->core.n_cigar*4 + (b)->core.l_qname)++/*! @function+ @abstract Get query quality+ @param b pointer to an alignment+ @return pointer to quality string+ */+#define bam1_qual(b) ((b)->data + (b)->core.n_cigar*4 + (b)->core.l_qname + (((b)->core.l_qseq + 1)>>1))++/*! @function+ @abstract Get a base on read+ @param s Query sequence returned by bam1_seq()+ @param i The i-th position, 0-based+ @return 4-bit integer representing the base.+ */+#define bam1_seqi(s, i) ((s)[(i)/2] >> 4*(1-(i)%2) & 0xf)++/*! @function+ @abstract Get query sequence and quality+ @param b pointer to an alignment+ @return pointer to the concatenated auxiliary data+ */+#define bam1_aux(b) ((b)->data + (b)->core.n_cigar*4 + (b)->core.l_qname + (b)->core.l_qseq + ((b)->core.l_qseq + 1)/2)++#ifndef kroundup32+/*! @function+ @abstract Round an integer to the next closest power-2 integer.+ @param x integer to be rounded (in place)+ @discussion x will be modified.+ */+#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))+#endif++/*!+ @abstract Whether the machine is big-endian; modified only in+ bam_header_init().+ */+extern int bam_is_be;++/*!+ @abstract Verbose level between 0 and 3; 0 is supposed to disable all+ debugging information, though this may not have been implemented.+ */+extern int bam_verbose;++/*! @abstract Table for converting a nucleotide character to the 4-bit encoding. */+extern unsigned char bam_nt16_table[256];++/*! @abstract Table for converting a 4-bit encoded nucleotide to a letter. */+extern char *bam_nt16_rev_table;++extern char bam_nt16_nt4_table[];++#ifdef __cplusplus+extern "C" {+#endif++ /*********************+ * Low-level SAM I/O *+ *********************/++ /*! @abstract TAM file handler */+ typedef struct __tamFile_t *tamFile;++ /*!+ @abstract Open a SAM file for reading, either uncompressed or compressed by gzip/zlib.+ @param fn SAM file name+ @return SAM file handler+ */+ tamFile sam_open(const char *fn);++ /*!+ @abstract Close a SAM file handler+ @param fp SAM file handler+ */+ void sam_close(tamFile fp);++ /*!+ @abstract Read one alignment from a SAM file handler+ @param fp SAM file handler+ @param header header information (ordered names of chromosomes)+ @param b read alignment; all members in b will be updated+ @return 0 if successful; otherwise negative+ */+ int sam_read1(tamFile fp, bam_header_t *header, bam1_t *b);++ /*!+ @abstract Read header information from a TAB-delimited list file.+ @param fn_list file name for the list+ @return a pointer to the header structure++ @discussion Each line in this file consists of chromosome name and+ the length of chromosome.+ */+ bam_header_t *sam_header_read2(const char *fn_list);++ /*!+ @abstract Read header from a SAM file (if present)+ @param fp SAM file handler+ @return pointer to header struct; 0 if no @SQ lines available+ */+ bam_header_t *sam_header_read(tamFile fp);++ /*!+ @abstract Parse @SQ lines a update a header struct+ @param h pointer to the header struct to be updated+ @return number of target sequences++ @discussion bam_header_t::{n_targets,target_len,target_name} will+ be destroyed in the first place.+ */+ int sam_header_parse(bam_header_t *h);+ int32_t bam_get_tid(const bam_header_t *header, const char *seq_name);++ /*!+ @abstract Parse @RG lines a update a header struct+ @param h pointer to the header struct to be updated+ @return number of @RG lines++ @discussion bam_header_t::rg2lib will be destroyed in the first+ place.+ */+ int sam_header_parse_rg(bam_header_t *h);++#define sam_write1(header, b) bam_view1(header, b)+++ /********************************+ * APIs for string dictionaries *+ ********************************/++ int bam_strmap_put(void *strmap, const char *rg, const char *lib);+ const char *bam_strmap_get(const void *strmap, const char *rg);+ void *bam_strmap_dup(const void*);+ void *bam_strmap_init();+ void bam_strmap_destroy(void *strmap);+++ /*********************+ * Low-level BAM I/O *+ *********************/++ /*!+ @abstract Initialize a header structure.+ @return the pointer to the header structure++ @discussion This function also modifies the global variable+ bam_is_be.+ */+ bam_header_t *bam_header_init();++ /*!+ @abstract Destroy a header structure.+ @param header pointer to the header+ */+ void bam_header_destroy(bam_header_t *header);++ /*!+ @abstract Read a header structure from BAM.+ @param fp BAM file handler, opened by bam_open()+ @return pointer to the header structure++ @discussion The file position indicator must be placed at the+ beginning of the file. Upon success, the position indicator will+ be set at the start of the first alignment.+ */+ bam_header_t *bam_header_read(bamFile fp);++ /*!+ @abstract Write a header structure to BAM.+ @param fp BAM file handler+ @param header pointer to the header structure+ @return always 0 currently+ */+ int bam_header_write(bamFile fp, const bam_header_t *header);++ /*!+ @abstract Read an alignment from BAM.+ @param fp BAM file handler+ @param b read alignment; all members are updated.+ @return number of bytes read from the file++ @discussion The file position indicator must be+ placed right before an alignment. Upon success, this function+ will set the position indicator to the start of the next+ alignment. This function is not affected by the machine+ endianness.+ */+ int bam_read1(bamFile fp, bam1_t *b);++ /*!+ @abstract Write an alignment to BAM.+ @param fp BAM file handler+ @param c pointer to the bam1_core_t structure+ @param data_len total length of variable size data related to+ the alignment+ @param data pointer to the concatenated data+ @return number of bytes written to the file++ @discussion This function is not affected by the machine+ endianness.+ */+ int bam_write1_core(bamFile fp, const bam1_core_t *c, int data_len, uint8_t *data);++ /*!+ @abstract Write an alignment to BAM.+ @param fp BAM file handler+ @param b alignment to write+ @return number of bytes written to the file++ @abstract It is equivalent to:+ bam_write1_core(fp, &b->core, b->data_len, b->data)+ */+ int bam_write1(bamFile fp, const bam1_t *b);++ /*! @function+ @abstract Initiate a pointer to bam1_t struct+ */+#define bam_init1() ((bam1_t*)calloc(1, sizeof(bam1_t)))++ /*! @function+ @abstract Free the memory allocated for an alignment.+ @param b pointer to an alignment+ */+#define bam_destroy1(b) do { \+ if (b) { free((b)->data); free(b); } \+ } while (0)++ /*!+ @abstract Format a BAM record in the SAM format+ @param header pointer to the header structure+ @param b alignment to print+ @return a pointer to the SAM string+ */+ char *bam_format1(const bam_header_t *header, const bam1_t *b);++ char *bam_format1_core(const bam_header_t *header, const bam1_t *b, int of);++ /*!+ @abstract Check whether a BAM record is plausibly valid+ @param header associated header structure, or NULL if unavailable+ @param b alignment to validate+ @return 0 if the alignment is invalid; non-zero otherwise++ @discussion Simple consistency check of some of the fields of the+ alignment record. If the header is provided, several additional checks+ are made. Not all fields are checked, so a non-zero result is not a+ guarantee that the record is valid. However it is usually good enough+ to detect when bam_seek() has been called with a virtual file offset+ that is not the offset of an alignment record.+ */+ int bam_validate1(const bam_header_t *header, const bam1_t *b);++ const char *bam_get_library(bam_header_t *header, const bam1_t *b);+++ /***************+ * pileup APIs *+ ***************/++ /*! @typedef+ @abstract Structure for one alignment covering the pileup position.+ @field b pointer to the alignment+ @field qpos position of the read base at the pileup site, 0-based+ @field indel indel length; 0 for no indel, positive for ins and negative for del+ @field is_del 1 iff the base on the padded read is a deletion+ @field level the level of the read in the "viewer" mode++ @discussion See also bam_plbuf_push() and bam_lplbuf_push(). The+ difference between the two functions is that the former does not+ set bam_pileup1_t::level, while the later does. Level helps the+ implementation of alignment viewers, but calculating this has some+ overhead.+ */+ typedef struct {+ bam1_t *b;+ int32_t qpos;+ int indel, level;+ uint32_t is_del:1, is_head:1, is_tail:1, is_refskip:1, aux:28;+ } bam_pileup1_t;++ typedef int (*bam_plp_auto_f)(void *data, bam1_t *b);++ struct __bam_plp_t;+ typedef struct __bam_plp_t *bam_plp_t;++ bam_plp_t bam_plp_init(bam_plp_auto_f func, void *data);+ int bam_plp_push(bam_plp_t iter, const bam1_t *b);+ const bam_pileup1_t *bam_plp_next(bam_plp_t iter, int *_tid, int *_pos, int *_n_plp);+ const bam_pileup1_t *bam_plp_auto(bam_plp_t iter, int *_tid, int *_pos, int *_n_plp);+ void bam_plp_set_mask(bam_plp_t iter, int mask);+ void bam_plp_set_maxcnt(bam_plp_t iter, int maxcnt);+ void bam_plp_reset(bam_plp_t iter);+ void bam_plp_destroy(bam_plp_t iter);++ struct __bam_mplp_t;+ typedef struct __bam_mplp_t *bam_mplp_t;++ bam_mplp_t bam_mplp_init(int n, bam_plp_auto_f func, void **data);+ void bam_mplp_destroy(bam_mplp_t iter);+ void bam_mplp_set_maxcnt(bam_mplp_t iter, int maxcnt);+ int bam_mplp_auto(bam_mplp_t iter, int *_tid, int *_pos, int *n_plp, const bam_pileup1_t **plp);++ /*! @typedef+ @abstract Type of function to be called by bam_plbuf_push().+ @param tid chromosome ID as is defined in the header+ @param pos start coordinate of the alignment, 0-based+ @param n number of elements in pl array+ @param pl array of alignments+ @param data user provided data+ @discussion See also bam_plbuf_push(), bam_plbuf_init() and bam_pileup1_t.+ */+ typedef int (*bam_pileup_f)(uint32_t tid, uint32_t pos, int n, const bam_pileup1_t *pl, void *data);++ typedef struct {+ bam_plp_t iter;+ bam_pileup_f func;+ void *data;+ } bam_plbuf_t;++ void bam_plbuf_set_mask(bam_plbuf_t *buf, int mask);+ void bam_plbuf_reset(bam_plbuf_t *buf);+ bam_plbuf_t *bam_plbuf_init(bam_pileup_f func, void *data);+ void bam_plbuf_destroy(bam_plbuf_t *buf);+ int bam_plbuf_push(const bam1_t *b, bam_plbuf_t *buf);++ int bam_pileup_file(bamFile fp, int mask, bam_pileup_f func, void *func_data);++ struct __bam_lplbuf_t;+ typedef struct __bam_lplbuf_t bam_lplbuf_t;++ void bam_lplbuf_reset(bam_lplbuf_t *buf);++ /*! @abstract bam_plbuf_init() equivalent with level calculated. */+ bam_lplbuf_t *bam_lplbuf_init(bam_pileup_f func, void *data);++ /*! @abstract bam_plbuf_destroy() equivalent with level calculated. */+ void bam_lplbuf_destroy(bam_lplbuf_t *tv);++ /*! @abstract bam_plbuf_push() equivalent with level calculated. */+ int bam_lplbuf_push(const bam1_t *b, bam_lplbuf_t *buf);+++ /*********************+ * BAM indexing APIs *+ *********************/++ struct __bam_index_t;+ typedef struct __bam_index_t bam_index_t;++ /*!+ @abstract Build index for a BAM file.+ @discussion Index file "fn.bai" will be created.+ @param fn name of the BAM file+ @return always 0 currently+ */+ int bam_index_build(const char *fn);++ /*!+ @abstract Load index from file "fn.bai".+ @param fn name of the BAM file (NOT the index file)+ @return pointer to the index structure+ */+ bam_index_t *bam_index_load(const char *fn);++ /*!+ @abstract Destroy an index structure.+ @param idx pointer to the index structure+ */+ void bam_index_destroy(bam_index_t *idx);++ /*! @typedef+ @abstract Type of function to be called by bam_fetch().+ @param b the alignment+ @param data user provided data+ */+ typedef int (*bam_fetch_f)(const bam1_t *b, void *data);++ /*!+ @abstract Retrieve the alignments that are overlapped with the+ specified region.++ @discussion A user defined function will be called for each+ retrieved alignment ordered by its start position.++ @param fp BAM file handler+ @param idx pointer to the alignment index+ @param tid chromosome ID as is defined in the header+ @param beg start coordinate, 0-based+ @param end end coordinate, 0-based+ @param data user provided data (will be transferred to func)+ @param func user defined function+ */+ int bam_fetch(bamFile fp, const bam_index_t *idx, int tid, int beg, int end, void *data, bam_fetch_f func);++ bam_iter_t bam_iter_query(const bam_index_t *idx, int tid, int beg, int end);+ int bam_iter_read(bamFile fp, bam_iter_t iter, bam1_t *b);+ void bam_iter_destroy(bam_iter_t iter);++ /*!+ @abstract Parse a region in the format: "chr2:100,000-200,000".+ @discussion bam_header_t::hash will be initialized if empty.+ @param header pointer to the header structure+ @param str string to be parsed+ @param ref_id the returned chromosome ID+ @param begin the returned start coordinate+ @param end the returned end coordinate+ @return 0 on success; -1 on failure+ */+ int bam_parse_region(bam_header_t *header, const char *str, int *ref_id, int *begin, int *end);+++ /**************************+ * APIs for optional tags *+ **************************/++ /*!+ @abstract Retrieve data of a tag+ @param b pointer to an alignment struct+ @param tag two-character tag to be retrieved++ @return pointer to the type and data. The first character is the+ type that can be 'iIsScCdfAZH'.++ @discussion Use bam_aux2?() series to convert the returned data to+ the corresponding type.+ */+ uint8_t *bam_aux_get(const bam1_t *b, const char tag[2]);++ int32_t bam_aux2i(const uint8_t *s);+ float bam_aux2f(const uint8_t *s);+ double bam_aux2d(const uint8_t *s);+ char bam_aux2A(const uint8_t *s);+ char *bam_aux2Z(const uint8_t *s);++ int bam_aux_del(bam1_t *b, uint8_t *s);+ void bam_aux_append(bam1_t *b, const char tag[2], char type, int len, uint8_t *data);+ uint8_t *bam_aux_get_core(bam1_t *b, const char tag[2]); // an alias of bam_aux_get()+++ /*****************+ * Miscellaneous *+ *****************/++ /*! + @abstract Calculate the rightmost coordinate of an alignment on the+ reference genome.++ @param c pointer to the bam1_core_t structure+ @param cigar the corresponding CIGAR array (from bam1_t::cigar)+ @return the rightmost coordinate, 0-based+ */+ uint32_t bam_calend(const bam1_core_t *c, const uint32_t *cigar);++ /*!+ @abstract Calculate the length of the query sequence from CIGAR.+ @param c pointer to the bam1_core_t structure+ @param cigar the corresponding CIGAR array (from bam1_t::cigar)+ @return length of the query sequence+ */+ int32_t bam_cigar2qlen(const bam1_core_t *c, const uint32_t *cigar);++#ifdef __cplusplus+}+#endif++/*!+ @abstract Calculate the minimum bin that contains a region [beg,end).+ @param beg start of the region, 0-based+ @param end end of the region, 0-based+ @return bin+ */+static inline int bam_reg2bin(uint32_t beg, uint32_t end)+{+ --end;+ if (beg>>14 == end>>14) return 4681 + (beg>>14);+ if (beg>>17 == end>>17) return 585 + (beg>>17);+ if (beg>>20 == end>>20) return 73 + (beg>>20);+ if (beg>>23 == end>>23) return 9 + (beg>>23);+ if (beg>>26 == end>>26) return 1 + (beg>>26);+ return 0;+}++/*!+ @abstract Copy an alignment+ @param bdst destination alignment struct+ @param bsrc source alignment struct+ @return pointer to the destination alignment struct+ */+static inline bam1_t *bam_copy1(bam1_t *bdst, const bam1_t *bsrc)+{+ uint8_t *data = bdst->data;+ int m_data = bdst->m_data; // backup data and m_data+ if (m_data < bsrc->data_len) { // double the capacity+ m_data = bsrc->data_len; kroundup32(m_data);+ data = (uint8_t*)realloc(data, m_data);+ }+ memcpy(data, bsrc->data, bsrc->data_len); // copy var-len data+ *bdst = *bsrc; // copy the rest+ // restore the backup+ bdst->m_data = m_data;+ bdst->data = data;+ return bdst;+}++/*!+ @abstract Duplicate an alignment+ @param src source alignment struct+ @return pointer to the destination alignment struct+ */+static inline bam1_t *bam_dup1(const bam1_t *src)+{+ bam1_t *b;+ b = bam_init1();+ *b = *src;+ b->m_data = b->data_len;+ b->data = (uint8_t*)calloc(b->data_len, 1);+ memcpy(b->data, src->data, b->data_len);+ return b;+}++static inline int bam_aux_type2size(int x)+{+ if (x == 'C' || x == 'c' || x == 'A') return 1;+ else if (x == 'S' || x == 's') return 2;+ else if (x == 'I' || x == 'i' || x == 'f') return 4;+ else return 0;+}+++#endif
+ samtools-0.1.18/bam_aux.c view
@@ -0,0 +1,213 @@+#include <ctype.h>+#include "bam.h"+#include "khash.h"+typedef char *str_p;+KHASH_MAP_INIT_STR(s, int)+KHASH_MAP_INIT_STR(r2l, str_p)++void bam_aux_append(bam1_t *b, const char tag[2], char type, int len, uint8_t *data)+{+ int ori_len = b->data_len;+ b->data_len += 3 + len;+ b->l_aux += 3 + len;+ if (b->m_data < b->data_len) {+ b->m_data = b->data_len;+ kroundup32(b->m_data);+ b->data = (uint8_t*)realloc(b->data, b->m_data);+ }+ b->data[ori_len] = tag[0]; b->data[ori_len + 1] = tag[1];+ b->data[ori_len + 2] = type;+ memcpy(b->data + ori_len + 3, data, len);+}++uint8_t *bam_aux_get_core(bam1_t *b, const char tag[2])+{+ return bam_aux_get(b, tag);+}++#define __skip_tag(s) do { \+ int type = toupper(*(s)); \+ ++(s); \+ if (type == 'Z' || type == 'H') { while (*(s)) ++(s); ++(s); } \+ else if (type == 'B') (s) += 5 + bam_aux_type2size(*(s)) * (*(int32_t*)((s)+1)); \+ else (s) += bam_aux_type2size(type); \+ } while(0)++uint8_t *bam_aux_get(const bam1_t *b, const char tag[2])+{+ uint8_t *s;+ int y = tag[0]<<8 | tag[1];+ s = bam1_aux(b);+ while (s < b->data + b->data_len) {+ int x = (int)s[0]<<8 | s[1];+ s += 2;+ if (x == y) return s;+ __skip_tag(s);+ }+ return 0;+}+// s MUST BE returned by bam_aux_get()+int bam_aux_del(bam1_t *b, uint8_t *s)+{+ uint8_t *p, *aux;+ aux = bam1_aux(b);+ p = s - 2;+ __skip_tag(s);+ memmove(p, s, b->l_aux - (s - aux));+ b->data_len -= s - p;+ b->l_aux -= s - p;+ return 0;+}++int bam_aux_drop_other(bam1_t *b, uint8_t *s)+{+ if (s) {+ uint8_t *p, *aux;+ aux = bam1_aux(b);+ p = s - 2;+ __skip_tag(s);+ memmove(aux, p, s - p);+ b->data_len -= b->l_aux - (s - p);+ b->l_aux = s - p;+ } else {+ b->data_len -= b->l_aux;+ b->l_aux = 0;+ }+ return 0;+}++void bam_init_header_hash(bam_header_t *header)+{+ if (header->hash == 0) {+ int ret, i;+ khiter_t iter;+ khash_t(s) *h;+ header->hash = h = kh_init(s);+ for (i = 0; i < header->n_targets; ++i) {+ iter = kh_put(s, h, header->target_name[i], &ret);+ kh_value(h, iter) = i;+ }+ }+}++void bam_destroy_header_hash(bam_header_t *header)+{+ if (header->hash)+ kh_destroy(s, (khash_t(s)*)header->hash);+}++int32_t bam_get_tid(const bam_header_t *header, const char *seq_name)+{+ khint_t k;+ khash_t(s) *h = (khash_t(s)*)header->hash;+ k = kh_get(s, h, seq_name);+ return k == kh_end(h)? -1 : kh_value(h, k);+}++int bam_parse_region(bam_header_t *header, const char *str, int *ref_id, int *beg, int *end)+{+ char *s;+ int i, l, k, name_end;+ khiter_t iter;+ khash_t(s) *h;++ bam_init_header_hash(header);+ h = (khash_t(s)*)header->hash;++ *ref_id = *beg = *end = -1;+ name_end = l = strlen(str);+ s = (char*)malloc(l+1);+ // remove space+ for (i = k = 0; i < l; ++i)+ if (!isspace(str[i])) s[k++] = str[i];+ s[k] = 0; l = k;+ // determine the sequence name+ for (i = l - 1; i >= 0; --i) if (s[i] == ':') break; // look for colon from the end+ if (i >= 0) name_end = i;+ if (name_end < l) { // check if this is really the end+ int n_hyphen = 0;+ for (i = name_end + 1; i < l; ++i) {+ if (s[i] == '-') ++n_hyphen;+ else if (!isdigit(s[i]) && s[i] != ',') break;+ }+ if (i < l || n_hyphen > 1) name_end = l; // malformated region string; then take str as the name+ s[name_end] = 0;+ iter = kh_get(s, h, s);+ if (iter == kh_end(h)) { // cannot find the sequence name+ iter = kh_get(s, h, str); // try str as the name+ if (iter == kh_end(h)) {+ if (bam_verbose >= 2) fprintf(stderr, "[%s] fail to determine the sequence name.\n", __func__);+ free(s); return -1;+ } else s[name_end] = ':', name_end = l;+ }+ } else iter = kh_get(s, h, str);+ *ref_id = kh_val(h, iter);+ // parse the interval+ if (name_end < l) {+ for (i = k = name_end + 1; i < l; ++i)+ if (s[i] != ',') s[k++] = s[i];+ s[k] = 0;+ *beg = atoi(s + name_end + 1);+ for (i = name_end + 1; i != k; ++i) if (s[i] == '-') break;+ *end = i < k? atoi(s + i + 1) : 1<<29;+ if (*beg > 0) --*beg;+ } else *beg = 0, *end = 1<<29;+ free(s);+ return *beg <= *end? 0 : -1;+}++int32_t bam_aux2i(const uint8_t *s)+{+ int type;+ if (s == 0) return 0;+ type = *s++;+ if (type == 'c') return (int32_t)*(int8_t*)s;+ else if (type == 'C') return (int32_t)*(uint8_t*)s;+ else if (type == 's') return (int32_t)*(int16_t*)s;+ else if (type == 'S') return (int32_t)*(uint16_t*)s;+ else if (type == 'i' || type == 'I') return *(int32_t*)s;+ else return 0;+}++float bam_aux2f(const uint8_t *s)+{+ int type;+ type = *s++;+ if (s == 0) return 0.0;+ if (type == 'f') return *(float*)s;+ else return 0.0;+}++double bam_aux2d(const uint8_t *s)+{+ int type;+ type = *s++;+ if (s == 0) return 0.0;+ if (type == 'd') return *(double*)s;+ else return 0.0;+}++char bam_aux2A(const uint8_t *s)+{+ int type;+ type = *s++;+ if (s == 0) return 0;+ if (type == 'A') return *(char*)s;+ else return 0;+}++char *bam_aux2Z(const uint8_t *s)+{+ int type;+ type = *s++;+ if (s == 0) return 0;+ if (type == 'Z' || type == 'H') return (char*)s;+ else return 0;+}++#ifdef _WIN32+double drand48()+{+ return (double)rand() / RAND_MAX;+}+#endif
+ samtools-0.1.18/bam_endian.h view
@@ -0,0 +1,42 @@+#ifndef BAM_ENDIAN_H+#define BAM_ENDIAN_H++#include <stdint.h>++static inline int bam_is_big_endian()+{+ long one= 1;+ return !(*((char *)(&one)));+}+static inline uint16_t bam_swap_endian_2(uint16_t v)+{+ return (uint16_t)(((v & 0x00FF00FFU) << 8) | ((v & 0xFF00FF00U) >> 8));+}+static inline void *bam_swap_endian_2p(void *x)+{+ *(uint16_t*)x = bam_swap_endian_2(*(uint16_t*)x);+ return x;+}+static inline uint32_t bam_swap_endian_4(uint32_t v)+{+ v = ((v & 0x0000FFFFU) << 16) | (v >> 16);+ return ((v & 0x00FF00FFU) << 8) | ((v & 0xFF00FF00U) >> 8);+}+static inline void *bam_swap_endian_4p(void *x)+{+ *(uint32_t*)x = bam_swap_endian_4(*(uint32_t*)x);+ return x;+}+static inline uint64_t bam_swap_endian_8(uint64_t v)+{+ v = ((v & 0x00000000FFFFFFFFLLU) << 32) | (v >> 32);+ v = ((v & 0x0000FFFF0000FFFFLLU) << 16) | ((v & 0xFFFF0000FFFF0000LLU) >> 16);+ return ((v & 0x00FF00FF00FF00FFLLU) << 8) | ((v & 0xFF00FF00FF00FF00LLU) >> 8);+}+static inline void *bam_swap_endian_8p(void *x)+{+ *(uint64_t*)x = bam_swap_endian_8(*(uint64_t*)x);+ return x;+}++#endif
+ samtools-0.1.18/bam_import.c view
@@ -0,0 +1,485 @@+#include <zlib.h>+#include <stdio.h>+#include <ctype.h>+#include <string.h>+#include <stdlib.h>+#include <unistd.h>+#include <assert.h>+#ifdef _WIN32+#include <fcntl.h>+#endif+#include "kstring.h"+#include "bam.h"+#include "sam_header.h"+#include "kseq.h"+#include "khash.h"++KSTREAM_INIT(gzFile, gzread, 16384)+KHASH_MAP_INIT_STR(ref, uint64_t)++void bam_init_header_hash(bam_header_t *header);+void bam_destroy_header_hash(bam_header_t *header);+int32_t bam_get_tid(const bam_header_t *header, const char *seq_name);++unsigned char bam_nt16_table[256] = {+ 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,+ 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,+ 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,+ 1, 2, 4, 8, 15,15,15,15, 15,15,15,15, 15, 0 /*=*/,15,15,+ 15, 1,14, 2, 13,15,15, 4, 11,15,15,12, 15, 3,15,15,+ 15,15, 5, 6, 8,15, 7, 9, 15,10,15,15, 15,15,15,15,+ 15, 1,14, 2, 13,15,15, 4, 11,15,15,12, 15, 3,15,15,+ 15,15, 5, 6, 8,15, 7, 9, 15,10,15,15, 15,15,15,15,+ 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,+ 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,+ 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,+ 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,+ 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,+ 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,+ 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,+ 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15+};++unsigned short bam_char2flag_table[256] = {+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,+ 0,BAM_FREAD1,BAM_FREAD2,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,+ BAM_FPROPER_PAIR,0,BAM_FMREVERSE,0, 0,BAM_FMUNMAP,0,0, 0,0,0,0, 0,0,0,0,+ 0,0,0,0, BAM_FDUP,0,BAM_FQCFAIL,0, 0,0,0,0, 0,0,0,0,+ BAM_FPAIRED,0,BAM_FREVERSE,BAM_FSECONDARY, 0,BAM_FUNMAP,0,0, 0,0,0,0, 0,0,0,0,+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0+};++char *bam_nt16_rev_table = "=ACMGRSVTWYHKDBN";++struct __tamFile_t {+ gzFile fp;+ kstream_t *ks;+ kstring_t *str;+ uint64_t n_lines;+ int is_first;+};++char **__bam_get_lines(const char *fn, int *_n) // for bam_plcmd.c only+{+ char **list = 0, *s;+ int n = 0, dret, m = 0;+ gzFile fp = (strcmp(fn, "-") == 0)? gzdopen(fileno(stdin), "r") : gzopen(fn, "r");+ kstream_t *ks;+ kstring_t *str;+ str = (kstring_t*)calloc(1, sizeof(kstring_t));+ ks = ks_init(fp);+ while (ks_getuntil(ks, '\n', str, &dret) > 0) {+ if (n == m) {+ m = m? m << 1 : 16;+ list = (char**)realloc(list, m * sizeof(char*));+ }+ if (str->s[str->l-1] == '\r')+ str->s[--str->l] = '\0';+ s = list[n++] = (char*)calloc(str->l + 1, 1);+ strcpy(s, str->s);+ }+ ks_destroy(ks);+ gzclose(fp);+ free(str->s); free(str);+ *_n = n;+ return list;+}++static bam_header_t *hash2header(const kh_ref_t *hash)+{+ bam_header_t *header;+ khiter_t k;+ header = bam_header_init();+ header->n_targets = kh_size(hash);+ header->target_name = (char**)calloc(kh_size(hash), sizeof(char*));+ header->target_len = (uint32_t*)calloc(kh_size(hash), 4);+ for (k = kh_begin(hash); k != kh_end(hash); ++k) {+ if (kh_exist(hash, k)) {+ int i = (int)kh_value(hash, k);+ header->target_name[i] = (char*)kh_key(hash, k);+ header->target_len[i] = kh_value(hash, k)>>32;+ }+ }+ bam_init_header_hash(header);+ return header;+}+bam_header_t *sam_header_read2(const char *fn)+{+ bam_header_t *header;+ int c, dret, ret, error = 0;+ gzFile fp;+ kstream_t *ks;+ kstring_t *str;+ kh_ref_t *hash;+ khiter_t k;+ if (fn == 0) return 0;+ fp = (strcmp(fn, "-") == 0)? gzdopen(fileno(stdin), "r") : gzopen(fn, "r");+ if (fp == 0) return 0;+ hash = kh_init(ref);+ ks = ks_init(fp);+ str = (kstring_t*)calloc(1, sizeof(kstring_t));+ while (ks_getuntil(ks, 0, str, &dret) > 0) {+ char *s = strdup(str->s);+ int len, i;+ i = kh_size(hash);+ ks_getuntil(ks, 0, str, &dret);+ len = atoi(str->s);+ k = kh_put(ref, hash, s, &ret);+ if (ret == 0) {+ fprintf(stderr, "[sam_header_read2] duplicated sequence name: %s\n", s);+ error = 1;+ }+ kh_value(hash, k) = (uint64_t)len<<32 | i;+ if (dret != '\n')+ while ((c = ks_getc(ks)) != '\n' && c != -1);+ }+ ks_destroy(ks);+ gzclose(fp);+ free(str->s); free(str);+ fprintf(stderr, "[sam_header_read2] %d sequences loaded.\n", kh_size(hash));+ if (error) return 0;+ header = hash2header(hash);+ kh_destroy(ref, hash);+ return header;+}+static inline uint8_t *alloc_data(bam1_t *b, int size)+{+ if (b->m_data < size) {+ b->m_data = size;+ kroundup32(b->m_data);+ b->data = (uint8_t*)realloc(b->data, b->m_data);+ }+ return b->data;+}+static inline void parse_error(int64_t n_lines, const char * __restrict msg)+{+ fprintf(stderr, "Parse error at line %lld: %s\n", (long long)n_lines, msg);+ abort();+}+static inline void append_text(bam_header_t *header, kstring_t *str)+{+ size_t x = header->l_text, y = header->l_text + str->l + 2; // 2 = 1 byte dret + 1 byte null+ kroundup32(x); kroundup32(y);+ if (x < y) + {+ header->n_text = y;+ header->text = (char*)realloc(header->text, y);+ if ( !header->text ) + {+ fprintf(stderr,"realloc failed to alloc %ld bytes\n", y);+ abort();+ }+ }+ // Sanity check+ if ( header->l_text+str->l+1 >= header->n_text )+ {+ fprintf(stderr,"append_text FIXME: %ld>=%ld, x=%ld,y=%ld\n", header->l_text+str->l+1,header->n_text,x,y);+ abort();+ }+ strncpy(header->text + header->l_text, str->s, str->l+1); // we cannot use strcpy() here.+ header->l_text += str->l + 1;+ header->text[header->l_text] = 0;+}++int sam_header_parse(bam_header_t *h)+{+ char **tmp;+ int i;+ free(h->target_len); free(h->target_name);+ h->n_targets = 0; h->target_len = 0; h->target_name = 0;+ if (h->l_text < 3) return 0;+ if (h->dict == 0) h->dict = sam_header_parse2(h->text);+ tmp = sam_header2list(h->dict, "SQ", "SN", &h->n_targets);+ if (h->n_targets == 0) return 0;+ h->target_name = calloc(h->n_targets, sizeof(void*));+ for (i = 0; i < h->n_targets; ++i)+ h->target_name[i] = strdup(tmp[i]);+ free(tmp);+ tmp = sam_header2list(h->dict, "SQ", "LN", &h->n_targets);+ h->target_len = calloc(h->n_targets, 4);+ for (i = 0; i < h->n_targets; ++i)+ h->target_len[i] = atoi(tmp[i]);+ free(tmp);+ return h->n_targets;+}++bam_header_t *sam_header_read(tamFile fp)+{+ int ret, dret;+ bam_header_t *header = bam_header_init();+ kstring_t *str = fp->str;+ while ((ret = ks_getuntil(fp->ks, KS_SEP_TAB, str, &dret)) >= 0 && str->s[0] == '@') { // skip header+ str->s[str->l] = dret; // note that str->s is NOT null terminated!!+ append_text(header, str);+ if (dret != '\n') {+ ret = ks_getuntil(fp->ks, '\n', str, &dret);+ str->s[str->l] = '\n'; // NOT null terminated!!+ append_text(header, str);+ }+ ++fp->n_lines;+ }+ sam_header_parse(header);+ bam_init_header_hash(header);+ fp->is_first = 1;+ return header;+}++int sam_read1(tamFile fp, bam_header_t *header, bam1_t *b)+{+ int ret, doff, doff0, dret, z = 0;+ bam1_core_t *c = &b->core;+ kstring_t *str = fp->str;+ kstream_t *ks = fp->ks;++ if (fp->is_first) {+ fp->is_first = 0;+ ret = str->l;+ } else {+ do { // special consideration for empty lines+ ret = ks_getuntil(fp->ks, KS_SEP_TAB, str, &dret);+ if (ret >= 0) z += str->l + 1;+ } while (ret == 0);+ }+ if (ret < 0) return -1;+ ++fp->n_lines;+ doff = 0;++ { // name+ c->l_qname = strlen(str->s) + 1;+ memcpy(alloc_data(b, doff + c->l_qname) + doff, str->s, c->l_qname);+ doff += c->l_qname;+ }+ { // flag+ long flag;+ char *s;+ ret = ks_getuntil(ks, KS_SEP_TAB, str, &dret); z += str->l + 1;+ flag = strtol((char*)str->s, &s, 0);+ if (*s) { // not the end of the string+ flag = 0;+ for (s = str->s; *s; ++s)+ flag |= bam_char2flag_table[(int)*s];+ }+ c->flag = flag;+ }+ { // tid, pos, qual+ ret = ks_getuntil(ks, KS_SEP_TAB, str, &dret); z += str->l + 1; c->tid = bam_get_tid(header, str->s);+ if (c->tid < 0 && strcmp(str->s, "*")) {+ if (header->n_targets == 0) {+ fprintf(stderr, "[sam_read1] missing header? Abort!\n");+ exit(1);+ } else fprintf(stderr, "[sam_read1] reference '%s' is recognized as '*'.\n", str->s);+ }+ ret = ks_getuntil(ks, KS_SEP_TAB, str, &dret); z += str->l + 1; c->pos = isdigit(str->s[0])? atoi(str->s) - 1 : -1;+ ret = ks_getuntil(ks, KS_SEP_TAB, str, &dret); z += str->l + 1; c->qual = isdigit(str->s[0])? atoi(str->s) : 0;+ if (ret < 0) return -2;+ }+ { // cigar+ char *s, *t;+ int i, op;+ long x;+ c->n_cigar = 0;+ if (ks_getuntil(ks, KS_SEP_TAB, str, &dret) < 0) return -3;+ z += str->l + 1;+ if (str->s[0] != '*') {+ for (s = str->s; *s; ++s) {+ if ((isalpha(*s)) || (*s=='=')) ++c->n_cigar;+ else if (!isdigit(*s)) parse_error(fp->n_lines, "invalid CIGAR character");+ }+ b->data = alloc_data(b, doff + c->n_cigar * 4);+ for (i = 0, s = str->s; i != c->n_cigar; ++i) {+ x = strtol(s, &t, 10);+ op = toupper(*t);+ if (op == 'M') op = BAM_CMATCH;+ else if (op == 'I') op = BAM_CINS;+ else if (op == 'D') op = BAM_CDEL;+ else if (op == 'N') op = BAM_CREF_SKIP;+ else if (op == 'S') op = BAM_CSOFT_CLIP;+ else if (op == 'H') op = BAM_CHARD_CLIP;+ else if (op == 'P') op = BAM_CPAD;+ else if (op == '=') op = BAM_CEQUAL;+ else if (op == 'X') op = BAM_CDIFF;+ else parse_error(fp->n_lines, "invalid CIGAR operation");+ s = t + 1;+ bam1_cigar(b)[i] = x << BAM_CIGAR_SHIFT | op;+ }+ if (*s) parse_error(fp->n_lines, "unmatched CIGAR operation");+ c->bin = bam_reg2bin(c->pos, bam_calend(c, bam1_cigar(b)));+ doff += c->n_cigar * 4;+ } else {+ if (!(c->flag&BAM_FUNMAP)) {+ fprintf(stderr, "Parse warning at line %lld: mapped sequence without CIGAR\n", (long long)fp->n_lines);+ c->flag |= BAM_FUNMAP;+ }+ c->bin = bam_reg2bin(c->pos, c->pos + 1);+ }+ }+ { // mtid, mpos, isize+ ret = ks_getuntil(ks, KS_SEP_TAB, str, &dret); z += str->l + 1;+ c->mtid = strcmp(str->s, "=")? bam_get_tid(header, str->s) : c->tid;+ ret = ks_getuntil(ks, KS_SEP_TAB, str, &dret); z += str->l + 1;+ c->mpos = isdigit(str->s[0])? atoi(str->s) - 1 : -1;+ ret = ks_getuntil(ks, KS_SEP_TAB, str, &dret); z += str->l + 1;+ c->isize = (str->s[0] == '-' || isdigit(str->s[0]))? atoi(str->s) : 0;+ if (ret < 0) return -4;+ }+ { // seq and qual+ int i;+ uint8_t *p = 0;+ if (ks_getuntil(ks, KS_SEP_TAB, str, &dret) < 0) return -5; // seq+ z += str->l + 1;+ if (strcmp(str->s, "*")) {+ c->l_qseq = strlen(str->s);+ if (c->n_cigar && c->l_qseq != (int32_t)bam_cigar2qlen(c, bam1_cigar(b))) {+ fprintf(stderr, "Line %ld, sequence length %i vs %i from CIGAR\n",+ (long)fp->n_lines, c->l_qseq, (int32_t)bam_cigar2qlen(c, bam1_cigar(b)));+ parse_error(fp->n_lines, "CIGAR and sequence length are inconsistent");+ }+ p = (uint8_t*)alloc_data(b, doff + c->l_qseq + (c->l_qseq+1)/2) + doff;+ memset(p, 0, (c->l_qseq+1)/2);+ for (i = 0; i < c->l_qseq; ++i)+ p[i/2] |= bam_nt16_table[(int)str->s[i]] << 4*(1-i%2);+ } else c->l_qseq = 0;+ if (ks_getuntil(ks, KS_SEP_TAB, str, &dret) < 0) return -6; // qual+ z += str->l + 1;+ if (strcmp(str->s, "*") && c->l_qseq != strlen(str->s))+ parse_error(fp->n_lines, "sequence and quality are inconsistent");+ p += (c->l_qseq+1)/2;+ if (strcmp(str->s, "*") == 0) for (i = 0; i < c->l_qseq; ++i) p[i] = 0xff;+ else for (i = 0; i < c->l_qseq; ++i) p[i] = str->s[i] - 33;+ doff += c->l_qseq + (c->l_qseq+1)/2;+ }+ doff0 = doff;+ if (dret != '\n' && dret != '\r') { // aux+ while (ks_getuntil(ks, KS_SEP_TAB, str, &dret) >= 0) {+ uint8_t *s, type, key[2];+ z += str->l + 1;+ if (str->l < 6 || str->s[2] != ':' || str->s[4] != ':')+ parse_error(fp->n_lines, "missing colon in auxiliary data");+ key[0] = str->s[0]; key[1] = str->s[1];+ type = str->s[3];+ s = alloc_data(b, doff + 3) + doff;+ s[0] = key[0]; s[1] = key[1]; s += 2; doff += 2;+ if (type == 'A' || type == 'a' || type == 'c' || type == 'C') { // c and C for backward compatibility+ s = alloc_data(b, doff + 2) + doff;+ *s++ = 'A'; *s = str->s[5];+ doff += 2;+ } else if (type == 'I' || type == 'i') {+ long long x;+ s = alloc_data(b, doff + 5) + doff;+ x = (long long)atoll(str->s + 5);+ if (x < 0) {+ if (x >= -127) {+ *s++ = 'c'; *(int8_t*)s = (int8_t)x;+ s += 1; doff += 2;+ } else if (x >= -32767) {+ *s++ = 's'; *(int16_t*)s = (int16_t)x;+ s += 2; doff += 3;+ } else {+ *s++ = 'i'; *(int32_t*)s = (int32_t)x;+ s += 4; doff += 5;+ if (x < -2147483648ll)+ fprintf(stderr, "Parse warning at line %lld: integer %lld is out of range.",+ (long long)fp->n_lines, x);+ }+ } else {+ if (x <= 255) {+ *s++ = 'C'; *s++ = (uint8_t)x;+ doff += 2;+ } else if (x <= 65535) {+ *s++ = 'S'; *(uint16_t*)s = (uint16_t)x;+ s += 2; doff += 3;+ } else {+ *s++ = 'I'; *(uint32_t*)s = (uint32_t)x;+ s += 4; doff += 5;+ if (x > 4294967295ll)+ fprintf(stderr, "Parse warning at line %lld: integer %lld is out of range.",+ (long long)fp->n_lines, x);+ }+ }+ } else if (type == 'f') {+ s = alloc_data(b, doff + 5) + doff;+ *s++ = 'f';+ *(float*)s = (float)atof(str->s + 5);+ s += 4; doff += 5;+ } else if (type == 'd') {+ s = alloc_data(b, doff + 9) + doff;+ *s++ = 'd';+ *(float*)s = (float)atof(str->s + 9);+ s += 8; doff += 9;+ } else if (type == 'Z' || type == 'H') {+ int size = 1 + (str->l - 5) + 1;+ if (type == 'H') { // check whether the hex string is valid+ int i;+ if ((str->l - 5) % 2 == 1) parse_error(fp->n_lines, "length of the hex string not even");+ for (i = 0; i < str->l - 5; ++i) {+ int c = toupper(str->s[5 + i]);+ if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')))+ parse_error(fp->n_lines, "invalid hex character");+ }+ }+ s = alloc_data(b, doff + size) + doff;+ *s++ = type;+ memcpy(s, str->s + 5, str->l - 5);+ s[str->l - 5] = 0;+ doff += size;+ } else if (type == 'B') {+ int32_t n = 0, Bsize, k = 0, size;+ char *p;+ if (str->l < 8) parse_error(fp->n_lines, "too few values in aux type B");+ Bsize = bam_aux_type2size(str->s[5]); // the size of each element+ for (p = (char*)str->s + 6; *p; ++p) // count the number of elements in the array+ if (*p == ',') ++n;+ p = str->s + 7; // now p points to the first number in the array+ size = 6 + Bsize * n; // total number of bytes allocated to this tag+ s = alloc_data(b, doff + 6 * Bsize * n) + doff; // allocate memory+ *s++ = 'B'; *s++ = str->s[5];+ memcpy(s, &n, 4); s += 4; // write the number of elements+ if (str->s[5] == 'c') while (p < str->s + str->l) ((int8_t*)s)[k++] = (int8_t)strtol(p, &p, 0), ++p;+ else if (str->s[5] == 'C') while (p < str->s + str->l) ((uint8_t*)s)[k++] = (uint8_t)strtol(p, &p, 0), ++p;+ else if (str->s[5] == 's') while (p < str->s + str->l) ((int16_t*)s)[k++] = (int16_t)strtol(p, &p, 0), ++p; // FIXME: avoid unaligned memory+ else if (str->s[5] == 'S') while (p < str->s + str->l) ((uint16_t*)s)[k++] = (uint16_t)strtol(p, &p, 0), ++p;+ else if (str->s[5] == 'i') while (p < str->s + str->l) ((int32_t*)s)[k++] = (int32_t)strtol(p, &p, 0), ++p;+ else if (str->s[5] == 'I') while (p < str->s + str->l) ((uint32_t*)s)[k++] = (uint32_t)strtol(p, &p, 0), ++p;+ else if (str->s[5] == 'f') while (p < str->s + str->l) ((float*)s)[k++] = (float)strtod(p, &p), ++p;+ else parse_error(fp->n_lines, "unrecognized array type");+ s += Bsize * n; doff += size;+ } else parse_error(fp->n_lines, "unrecognized type");+ if (dret == '\n' || dret == '\r') break;+ }+ }+ b->l_aux = doff - doff0;+ b->data_len = doff;+ return z;+}++tamFile sam_open(const char *fn)+{+ tamFile fp;+ gzFile gzfp = (strcmp(fn, "-") == 0)? gzdopen(fileno(stdin), "rb") : gzopen(fn, "rb");+ if (gzfp == 0) return 0;+ fp = (tamFile)calloc(1, sizeof(struct __tamFile_t));+ fp->str = (kstring_t*)calloc(1, sizeof(kstring_t));+ fp->fp = gzfp;+ fp->ks = ks_init(fp->fp);+ return fp;+}++void sam_close(tamFile fp)+{+ if (fp) {+ ks_destroy(fp->ks);+ gzclose(fp->fp);+ free(fp->str->s); free(fp->str);+ free(fp);+ }+}
+ samtools-0.1.18/bam_index.c view
@@ -0,0 +1,719 @@+#include <ctype.h>+#include <assert.h>+#include "bam.h"+#include "khash.h"+#include "ksort.h"+#include "bam_endian.h"+#ifdef _USE_KNETFILE+#include "knetfile.h"+#endif++/*!+ @header++ Alignment indexing. Before indexing, BAM must be sorted based on the+ leftmost coordinate of alignments. In indexing, BAM uses two indices:+ a UCSC binning index and a simple linear index. The binning index is+ efficient for alignments spanning long distance, while the auxiliary+ linear index helps to reduce unnecessary seek calls especially for+ short alignments.++ The UCSC binning scheme was suggested by Richard Durbin and Lincoln+ Stein and is explained by Kent et al. (2002). In this scheme, each bin+ represents a contiguous genomic region which can be fully contained in+ another bin; each alignment is associated with a bin which represents+ the smallest region containing the entire alignment. The binning+ scheme is essentially another representation of R-tree. A distinct bin+ uniquely corresponds to a distinct internal node in a R-tree. Bin A is+ a child of Bin B if region A is contained in B.++ In BAM, each bin may span 2^29, 2^26, 2^23, 2^20, 2^17 or 2^14 bp. Bin+ 0 spans a 512Mbp region, bins 1-8 span 64Mbp, 9-72 8Mbp, 73-584 1Mbp,+ 585-4680 128Kbp and bins 4681-37449 span 16Kbp regions. If we want to+ find the alignments overlapped with a region [rbeg,rend), we need to+ calculate the list of bins that may be overlapped the region and test+ the alignments in the bins to confirm the overlaps. If the specified+ region is short, typically only a few alignments in six bins need to+ be retrieved. The overlapping alignments can be quickly fetched.++ */++#define BAM_MIN_CHUNK_GAP 32768+// 1<<14 is the size of minimum bin.+#define BAM_LIDX_SHIFT 14++#define BAM_MAX_BIN 37450 // =(8^6-1)/7+1++typedef struct {+ uint64_t u, v;+} pair64_t;++#define pair64_lt(a,b) ((a).u < (b).u)+KSORT_INIT(off, pair64_t, pair64_lt)++typedef struct {+ uint32_t m, n;+ pair64_t *list;+} bam_binlist_t;++typedef struct {+ int32_t n, m;+ uint64_t *offset;+} bam_lidx_t;++KHASH_MAP_INIT_INT(i, bam_binlist_t)++struct __bam_index_t {+ int32_t n;+ uint64_t n_no_coor; // unmapped reads without coordinate+ khash_t(i) **index;+ bam_lidx_t *index2;+};++// requirement: len <= LEN_MASK+static inline void insert_offset(khash_t(i) *h, int bin, uint64_t beg, uint64_t end)+{+ khint_t k;+ bam_binlist_t *l;+ int ret;+ k = kh_put(i, h, bin, &ret);+ l = &kh_value(h, k);+ if (ret) { // not present+ l->m = 1; l->n = 0;+ l->list = (pair64_t*)calloc(l->m, 16);+ }+ if (l->n == l->m) {+ l->m <<= 1;+ l->list = (pair64_t*)realloc(l->list, l->m * 16);+ }+ l->list[l->n].u = beg; l->list[l->n++].v = end;+}++static inline void insert_offset2(bam_lidx_t *index2, bam1_t *b, uint64_t offset)+{+ int i, beg, end;+ beg = b->core.pos >> BAM_LIDX_SHIFT;+ end = (bam_calend(&b->core, bam1_cigar(b)) - 1) >> BAM_LIDX_SHIFT;+ if (index2->m < end + 1) {+ int old_m = index2->m;+ index2->m = end + 1;+ kroundup32(index2->m);+ index2->offset = (uint64_t*)realloc(index2->offset, index2->m * 8);+ memset(index2->offset + old_m, 0, 8 * (index2->m - old_m));+ }+ if (beg == end) {+ if (index2->offset[beg] == 0) index2->offset[beg] = offset;+ } else {+ for (i = beg; i <= end; ++i)+ if (index2->offset[i] == 0) index2->offset[i] = offset;+ }+ index2->n = end + 1;+}++static void merge_chunks(bam_index_t *idx)+{+#if defined(BAM_TRUE_OFFSET) || defined(BAM_VIRTUAL_OFFSET16)+ khash_t(i) *index;+ int i, l, m;+ khint_t k;+ for (i = 0; i < idx->n; ++i) {+ index = idx->index[i];+ for (k = kh_begin(index); k != kh_end(index); ++k) {+ bam_binlist_t *p;+ if (!kh_exist(index, k) || kh_key(index, k) == BAM_MAX_BIN) continue;+ p = &kh_value(index, k);+ m = 0;+ for (l = 1; l < p->n; ++l) {+#ifdef BAM_TRUE_OFFSET+ if (p->list[m].v + BAM_MIN_CHUNK_GAP > p->list[l].u) p->list[m].v = p->list[l].v;+#else+ if (p->list[m].v>>16 == p->list[l].u>>16) p->list[m].v = p->list[l].v;+#endif+ else p->list[++m] = p->list[l];+ } // ~for(l)+ p->n = m + 1;+ } // ~for(k)+ } // ~for(i)+#endif // defined(BAM_TRUE_OFFSET) || defined(BAM_BGZF)+}++static void fill_missing(bam_index_t *idx)+{+ int i, j;+ for (i = 0; i < idx->n; ++i) {+ bam_lidx_t *idx2 = &idx->index2[i];+ for (j = 1; j < idx2->n; ++j)+ if (idx2->offset[j] == 0)+ idx2->offset[j] = idx2->offset[j-1];+ }+}++bam_index_t *bam_index_core(bamFile fp)+{+ bam1_t *b;+ bam_header_t *h;+ int i, ret;+ bam_index_t *idx;+ uint32_t last_bin, save_bin;+ int32_t last_coor, last_tid, save_tid;+ bam1_core_t *c;+ uint64_t save_off, last_off, n_mapped, n_unmapped, off_beg, off_end, n_no_coor;++ idx = (bam_index_t*)calloc(1, sizeof(bam_index_t));+ b = (bam1_t*)calloc(1, sizeof(bam1_t));+ h = bam_header_read(fp);+ c = &b->core;++ idx->n = h->n_targets;+ bam_header_destroy(h);+ idx->index = (khash_t(i)**)calloc(idx->n, sizeof(void*));+ for (i = 0; i < idx->n; ++i) idx->index[i] = kh_init(i);+ idx->index2 = (bam_lidx_t*)calloc(idx->n, sizeof(bam_lidx_t));++ save_bin = save_tid = last_tid = last_bin = 0xffffffffu;+ save_off = last_off = bam_tell(fp); last_coor = 0xffffffffu;+ n_mapped = n_unmapped = n_no_coor = off_end = 0;+ off_beg = off_end = bam_tell(fp);+ while ((ret = bam_read1(fp, b)) >= 0) {+ if (c->tid < 0) ++n_no_coor;+ if (last_tid < c->tid || (last_tid >= 0 && c->tid < 0)) { // change of chromosomes+ last_tid = c->tid;+ last_bin = 0xffffffffu;+ } else if ((uint32_t)last_tid > (uint32_t)c->tid) {+ fprintf(stderr, "[bam_index_core] the alignment is not sorted (%s): %d-th chr > %d-th chr\n",+ bam1_qname(b), last_tid+1, c->tid+1);+ return NULL;+ } else if ((int32_t)c->tid >= 0 && last_coor > c->pos) {+ fprintf(stderr, "[bam_index_core] the alignment is not sorted (%s): %u > %u in %d-th chr\n",+ bam1_qname(b), last_coor, c->pos, c->tid+1);+ return NULL;+ }+ if (c->tid >= 0 && !(c->flag & BAM_FUNMAP)) insert_offset2(&idx->index2[b->core.tid], b, last_off);+ if (c->bin != last_bin) { // then possibly write the binning index+ if (save_bin != 0xffffffffu) // save_bin==0xffffffffu only happens to the first record+ insert_offset(idx->index[save_tid], save_bin, save_off, last_off);+ if (last_bin == 0xffffffffu && save_tid != 0xffffffffu) { // write the meta element+ off_end = last_off;+ insert_offset(idx->index[save_tid], BAM_MAX_BIN, off_beg, off_end);+ insert_offset(idx->index[save_tid], BAM_MAX_BIN, n_mapped, n_unmapped);+ n_mapped = n_unmapped = 0;+ off_beg = off_end;+ }+ save_off = last_off;+ save_bin = last_bin = c->bin;+ save_tid = c->tid;+ if (save_tid < 0) break;+ }+ if (bam_tell(fp) <= last_off) {+ fprintf(stderr, "[bam_index_core] bug in BGZF/RAZF: %llx < %llx\n",+ (unsigned long long)bam_tell(fp), (unsigned long long)last_off);+ return NULL;+ }+ if (c->flag & BAM_FUNMAP) ++n_unmapped;+ else ++n_mapped;+ last_off = bam_tell(fp);+ last_coor = b->core.pos;+ }+ if (save_tid >= 0) {+ insert_offset(idx->index[save_tid], save_bin, save_off, bam_tell(fp));+ insert_offset(idx->index[save_tid], BAM_MAX_BIN, off_beg, bam_tell(fp));+ insert_offset(idx->index[save_tid], BAM_MAX_BIN, n_mapped, n_unmapped);+ }+ merge_chunks(idx);+ fill_missing(idx);+ if (ret >= 0) {+ while ((ret = bam_read1(fp, b)) >= 0) {+ ++n_no_coor;+ if (c->tid >= 0 && n_no_coor) {+ fprintf(stderr, "[bam_index_core] the alignment is not sorted: reads without coordinates prior to reads with coordinates.\n");+ return NULL;+ }+ }+ }+ if (ret < -1) fprintf(stderr, "[bam_index_core] truncated file? Continue anyway. (%d)\n", ret);+ free(b->data); free(b);+ idx->n_no_coor = n_no_coor;+ return idx;+}++void bam_index_destroy(bam_index_t *idx)+{+ khint_t k;+ int i;+ if (idx == 0) return;+ for (i = 0; i < idx->n; ++i) {+ khash_t(i) *index = idx->index[i];+ bam_lidx_t *index2 = idx->index2 + i;+ for (k = kh_begin(index); k != kh_end(index); ++k) {+ if (kh_exist(index, k))+ free(kh_value(index, k).list);+ }+ kh_destroy(i, index);+ free(index2->offset);+ }+ free(idx->index); free(idx->index2);+ free(idx);+}++void bam_index_save(const bam_index_t *idx, FILE *fp)+{+ int32_t i, size;+ khint_t k;+ fwrite("BAI\1", 1, 4, fp);+ if (bam_is_be) {+ uint32_t x = idx->n;+ fwrite(bam_swap_endian_4p(&x), 4, 1, fp);+ } else fwrite(&idx->n, 4, 1, fp);+ for (i = 0; i < idx->n; ++i) {+ khash_t(i) *index = idx->index[i];+ bam_lidx_t *index2 = idx->index2 + i;+ // write binning index+ size = kh_size(index);+ if (bam_is_be) { // big endian+ uint32_t x = size;+ fwrite(bam_swap_endian_4p(&x), 4, 1, fp);+ } else fwrite(&size, 4, 1, fp);+ for (k = kh_begin(index); k != kh_end(index); ++k) {+ if (kh_exist(index, k)) {+ bam_binlist_t *p = &kh_value(index, k);+ if (bam_is_be) { // big endian+ uint32_t x;+ x = kh_key(index, k); fwrite(bam_swap_endian_4p(&x), 4, 1, fp);+ x = p->n; fwrite(bam_swap_endian_4p(&x), 4, 1, fp);+ for (x = 0; (int)x < p->n; ++x) {+ bam_swap_endian_8p(&p->list[x].u);+ bam_swap_endian_8p(&p->list[x].v);+ }+ fwrite(p->list, 16, p->n, fp);+ for (x = 0; (int)x < p->n; ++x) {+ bam_swap_endian_8p(&p->list[x].u);+ bam_swap_endian_8p(&p->list[x].v);+ }+ } else {+ fwrite(&kh_key(index, k), 4, 1, fp);+ fwrite(&p->n, 4, 1, fp);+ fwrite(p->list, 16, p->n, fp);+ }+ }+ }+ // write linear index (index2)+ if (bam_is_be) {+ int x = index2->n;+ fwrite(bam_swap_endian_4p(&x), 4, 1, fp);+ } else fwrite(&index2->n, 4, 1, fp);+ if (bam_is_be) { // big endian+ int x;+ for (x = 0; (int)x < index2->n; ++x)+ bam_swap_endian_8p(&index2->offset[x]);+ fwrite(index2->offset, 8, index2->n, fp);+ for (x = 0; (int)x < index2->n; ++x)+ bam_swap_endian_8p(&index2->offset[x]);+ } else fwrite(index2->offset, 8, index2->n, fp);+ }+ { // write the number of reads coor-less records.+ uint64_t x = idx->n_no_coor;+ if (bam_is_be) bam_swap_endian_8p(&x);+ fwrite(&x, 8, 1, fp);+ }+ fflush(fp);+}++static bam_index_t *bam_index_load_core(FILE *fp)+{+ int i;+ char magic[4];+ bam_index_t *idx;+ if (fp == 0) {+ fprintf(stderr, "[bam_index_load_core] fail to load index.\n");+ return 0;+ }+ fread(magic, 1, 4, fp);+ if (strncmp(magic, "BAI\1", 4)) {+ fprintf(stderr, "[bam_index_load] wrong magic number.\n");+ fclose(fp);+ return 0;+ }+ idx = (bam_index_t*)calloc(1, sizeof(bam_index_t)); + fread(&idx->n, 4, 1, fp);+ if (bam_is_be) bam_swap_endian_4p(&idx->n);+ idx->index = (khash_t(i)**)calloc(idx->n, sizeof(void*));+ idx->index2 = (bam_lidx_t*)calloc(idx->n, sizeof(bam_lidx_t));+ for (i = 0; i < idx->n; ++i) {+ khash_t(i) *index;+ bam_lidx_t *index2 = idx->index2 + i;+ uint32_t key, size;+ khint_t k;+ int j, ret;+ bam_binlist_t *p;+ index = idx->index[i] = kh_init(i);+ // load binning index+ fread(&size, 4, 1, fp);+ if (bam_is_be) bam_swap_endian_4p(&size);+ for (j = 0; j < (int)size; ++j) {+ fread(&key, 4, 1, fp);+ if (bam_is_be) bam_swap_endian_4p(&key);+ k = kh_put(i, index, key, &ret);+ p = &kh_value(index, k);+ fread(&p->n, 4, 1, fp);+ if (bam_is_be) bam_swap_endian_4p(&p->n);+ p->m = p->n;+ p->list = (pair64_t*)malloc(p->m * 16);+ fread(p->list, 16, p->n, fp);+ if (bam_is_be) {+ int x;+ for (x = 0; x < p->n; ++x) {+ bam_swap_endian_8p(&p->list[x].u);+ bam_swap_endian_8p(&p->list[x].v);+ }+ }+ }+ // load linear index+ fread(&index2->n, 4, 1, fp);+ if (bam_is_be) bam_swap_endian_4p(&index2->n);+ index2->m = index2->n;+ index2->offset = (uint64_t*)calloc(index2->m, 8);+ fread(index2->offset, index2->n, 8, fp);+ if (bam_is_be)+ for (j = 0; j < index2->n; ++j) bam_swap_endian_8p(&index2->offset[j]);+ }+ if (fread(&idx->n_no_coor, 8, 1, fp) == 0) idx->n_no_coor = 0;+ if (bam_is_be) bam_swap_endian_8p(&idx->n_no_coor);+ return idx;+}++bam_index_t *bam_index_load_local(const char *_fn)+{+ FILE *fp;+ char *fnidx, *fn;++ if (strstr(_fn, "ftp://") == _fn || strstr(_fn, "http://") == _fn) {+ const char *p;+ int l = strlen(_fn);+ for (p = _fn + l - 1; p >= _fn; --p)+ if (*p == '/') break;+ fn = strdup(p + 1);+ } else fn = strdup(_fn);+ fnidx = (char*)calloc(strlen(fn) + 5, 1);+ strcpy(fnidx, fn); strcat(fnidx, ".bai");+ fp = fopen(fnidx, "rb");+ if (fp == 0) { // try "{base}.bai"+ char *s = strstr(fn, "bam");+ if (s == fn + strlen(fn) - 3) {+ strcpy(fnidx, fn);+ fnidx[strlen(fn)-1] = 'i';+ fp = fopen(fnidx, "rb");+ }+ }+ free(fnidx); free(fn);+ if (fp) {+ bam_index_t *idx = bam_index_load_core(fp);+ fclose(fp);+ return idx;+ } else return 0;+}++#ifdef _USE_KNETFILE+static void download_from_remote(const char *url)+{+ const int buf_size = 1 * 1024 * 1024;+ char *fn;+ FILE *fp;+ uint8_t *buf;+ knetFile *fp_remote;+ int l;+ if (strstr(url, "ftp://") != url && strstr(url, "http://") != url) return;+ l = strlen(url);+ for (fn = (char*)url + l - 1; fn >= url; --fn)+ if (*fn == '/') break;+ ++fn; // fn now points to the file name+ fp_remote = knet_open(url, "r");+ if (fp_remote == 0) {+ fprintf(stderr, "[download_from_remote] fail to open remote file.\n");+ return;+ }+ if ((fp = fopen(fn, "wb")) == 0) {+ fprintf(stderr, "[download_from_remote] fail to create file in the working directory.\n");+ knet_close(fp_remote);+ return;+ }+ buf = (uint8_t*)calloc(buf_size, 1);+ while ((l = knet_read(fp_remote, buf, buf_size)) != 0)+ fwrite(buf, 1, l, fp);+ free(buf);+ fclose(fp);+ knet_close(fp_remote);+}+#else+static void download_from_remote(const char *url)+{+ return;+}+#endif++bam_index_t *bam_index_load(const char *fn)+{+ bam_index_t *idx;+ idx = bam_index_load_local(fn);+ if (idx == 0 && (strstr(fn, "ftp://") == fn || strstr(fn, "http://") == fn)) {+ char *fnidx = calloc(strlen(fn) + 5, 1);+ strcat(strcpy(fnidx, fn), ".bai");+ fprintf(stderr, "[bam_index_load] attempting to download the remote index file.\n");+ download_from_remote(fnidx);+ idx = bam_index_load_local(fn);+ }+ if (idx == 0) fprintf(stderr, "[bam_index_load] fail to load BAM index.\n");+ return idx;+}++int bam_index_build2(const char *fn, const char *_fnidx)+{+ char *fnidx;+ FILE *fpidx;+ bamFile fp;+ bam_index_t *idx;+ if ((fp = bam_open(fn, "r")) == 0) {+ fprintf(stderr, "[bam_index_build2] fail to open the BAM file.\n");+ return -1;+ }+ idx = bam_index_core(fp);+ bam_close(fp);+ if(idx == 0) {+ fprintf(stderr, "[bam_index_build2] fail to index the BAM file.\n");+ return -1;+ }+ if (_fnidx == 0) {+ fnidx = (char*)calloc(strlen(fn) + 5, 1);+ strcpy(fnidx, fn); strcat(fnidx, ".bai");+ } else fnidx = strdup(_fnidx);+ fpidx = fopen(fnidx, "wb");+ if (fpidx == 0) {+ fprintf(stderr, "[bam_index_build2] fail to create the index file.\n");+ free(fnidx);+ return -1;+ }+ bam_index_save(idx, fpidx);+ bam_index_destroy(idx);+ fclose(fpidx);+ free(fnidx);+ return 0;+}++int bam_index_build(const char *fn)+{+ return bam_index_build2(fn, 0);+}++int bam_index(int argc, char *argv[])+{+ if (argc < 2) {+ fprintf(stderr, "Usage: samtools index <in.bam> [out.index]\n");+ return 1;+ }+ if (argc >= 3) bam_index_build2(argv[1], argv[2]);+ else bam_index_build(argv[1]);+ return 0;+}++int bam_idxstats(int argc, char *argv[])+{+ bam_index_t *idx;+ bam_header_t *header;+ bamFile fp;+ int i;+ if (argc < 2) {+ fprintf(stderr, "Usage: samtools idxstats <in.bam>\n");+ return 1;+ }+ fp = bam_open(argv[1], "r");+ if (fp == 0) { fprintf(stderr, "[%s] fail to open BAM.\n", __func__); return 1; }+ header = bam_header_read(fp);+ bam_close(fp);+ idx = bam_index_load(argv[1]);+ if (idx == 0) { fprintf(stderr, "[%s] fail to load the index.\n", __func__); return 1; }+ for (i = 0; i < idx->n; ++i) {+ khint_t k;+ khash_t(i) *h = idx->index[i];+ printf("%s\t%d", header->target_name[i], header->target_len[i]);+ k = kh_get(i, h, BAM_MAX_BIN);+ if (k != kh_end(h))+ printf("\t%llu\t%llu", (long long)kh_val(h, k).list[1].u, (long long)kh_val(h, k).list[1].v);+ else printf("\t0\t0");+ putchar('\n');+ }+ printf("*\t0\t0\t%llu\n", (long long)idx->n_no_coor);+ bam_header_destroy(header);+ bam_index_destroy(idx);+ return 0;+}++static inline int reg2bins(uint32_t beg, uint32_t end, uint16_t list[BAM_MAX_BIN])+{+ int i = 0, k;+ if (beg >= end) return 0;+ if (end >= 1u<<29) end = 1u<<29;+ --end;+ list[i++] = 0;+ for (k = 1 + (beg>>26); k <= 1 + (end>>26); ++k) list[i++] = k;+ for (k = 9 + (beg>>23); k <= 9 + (end>>23); ++k) list[i++] = k;+ for (k = 73 + (beg>>20); k <= 73 + (end>>20); ++k) list[i++] = k;+ for (k = 585 + (beg>>17); k <= 585 + (end>>17); ++k) list[i++] = k;+ for (k = 4681 + (beg>>14); k <= 4681 + (end>>14); ++k) list[i++] = k;+ return i;+}++static inline int is_overlap(uint32_t beg, uint32_t end, const bam1_t *b)+{+ uint32_t rbeg = b->core.pos;+ uint32_t rend = b->core.n_cigar? bam_calend(&b->core, bam1_cigar(b)) : b->core.pos + 1;+ return (rend > beg && rbeg < end);+}++struct __bam_iter_t {+ int from_first; // read from the first record; no random access+ int tid, beg, end, n_off, i, finished;+ uint64_t curr_off;+ pair64_t *off;+};++// bam_fetch helper function retrieves +bam_iter_t bam_iter_query(const bam_index_t *idx, int tid, int beg, int end)+{+ uint16_t *bins;+ int i, n_bins, n_off;+ pair64_t *off;+ khint_t k;+ khash_t(i) *index;+ uint64_t min_off;+ bam_iter_t iter = 0;++ if (beg < 0) beg = 0;+ if (end < beg) return 0;+ // initialize iter+ iter = calloc(1, sizeof(struct __bam_iter_t));+ iter->tid = tid, iter->beg = beg, iter->end = end; iter->i = -1;+ //+ bins = (uint16_t*)calloc(BAM_MAX_BIN, 2);+ n_bins = reg2bins(beg, end, bins);+ index = idx->index[tid];+ if (idx->index2[tid].n > 0) {+ min_off = (beg>>BAM_LIDX_SHIFT >= idx->index2[tid].n)? idx->index2[tid].offset[idx->index2[tid].n-1]+ : idx->index2[tid].offset[beg>>BAM_LIDX_SHIFT];+ if (min_off == 0) { // improvement for index files built by tabix prior to 0.1.4+ int n = beg>>BAM_LIDX_SHIFT;+ if (n > idx->index2[tid].n) n = idx->index2[tid].n;+ for (i = n - 1; i >= 0; --i)+ if (idx->index2[tid].offset[i] != 0) break;+ if (i >= 0) min_off = idx->index2[tid].offset[i];+ }+ } else min_off = 0; // tabix 0.1.2 may produce such index files+ for (i = n_off = 0; i < n_bins; ++i) {+ if ((k = kh_get(i, index, bins[i])) != kh_end(index))+ n_off += kh_value(index, k).n;+ }+ if (n_off == 0) {+ free(bins); return iter;+ }+ off = (pair64_t*)calloc(n_off, 16);+ for (i = n_off = 0; i < n_bins; ++i) {+ if ((k = kh_get(i, index, bins[i])) != kh_end(index)) {+ int j;+ bam_binlist_t *p = &kh_value(index, k);+ for (j = 0; j < p->n; ++j)+ if (p->list[j].v > min_off) off[n_off++] = p->list[j];+ }+ }+ free(bins);+ if (n_off == 0) {+ free(off); return iter;+ }+ {+ bam1_t *b = (bam1_t*)calloc(1, sizeof(bam1_t));+ int l;+ ks_introsort(off, n_off, off);+ // resolve completely contained adjacent blocks+ for (i = 1, l = 0; i < n_off; ++i)+ if (off[l].v < off[i].v)+ off[++l] = off[i];+ n_off = l + 1;+ // resolve overlaps between adjacent blocks; this may happen due to the merge in indexing+ for (i = 1; i < n_off; ++i)+ if (off[i-1].v >= off[i].u) off[i-1].v = off[i].u;+ { // merge adjacent blocks+#if defined(BAM_TRUE_OFFSET) || defined(BAM_VIRTUAL_OFFSET16)+ for (i = 1, l = 0; i < n_off; ++i) {+#ifdef BAM_TRUE_OFFSET+ if (off[l].v + BAM_MIN_CHUNK_GAP > off[i].u) off[l].v = off[i].v;+#else+ if (off[l].v>>16 == off[i].u>>16) off[l].v = off[i].v;+#endif+ else off[++l] = off[i];+ }+ n_off = l + 1;+#endif+ }+ bam_destroy1(b);+ }+ iter->n_off = n_off; iter->off = off;+ return iter;+}++pair64_t *get_chunk_coordinates(const bam_index_t *idx, int tid, int beg, int end, int *cnt_off)+{ // for pysam compatibility+ bam_iter_t iter;+ pair64_t *off;+ iter = bam_iter_query(idx, tid, beg, end);+ off = iter->off; *cnt_off = iter->n_off;+ free(iter);+ return off;+}++void bam_iter_destroy(bam_iter_t iter)+{+ if (iter) { free(iter->off); free(iter); }+}++int bam_iter_read(bamFile fp, bam_iter_t iter, bam1_t *b)+{+ int ret;+ if (iter && iter->finished) return -1;+ if (iter == 0 || iter->from_first) {+ ret = bam_read1(fp, b);+ if (ret < 0 && iter) iter->finished = 1;+ return ret;+ }+ if (iter->off == 0) return -1;+ for (;;) {+ if (iter->curr_off == 0 || iter->curr_off >= iter->off[iter->i].v) { // then jump to the next chunk+ if (iter->i == iter->n_off - 1) { ret = -1; break; } // no more chunks+ if (iter->i >= 0) assert(iter->curr_off == iter->off[iter->i].v); // otherwise bug+ if (iter->i < 0 || iter->off[iter->i].v != iter->off[iter->i+1].u) { // not adjacent chunks; then seek+ bam_seek(fp, iter->off[iter->i+1].u, SEEK_SET);+ iter->curr_off = bam_tell(fp);+ }+ ++iter->i;+ }+ if ((ret = bam_read1(fp, b)) >= 0) {+ iter->curr_off = bam_tell(fp);+ if (b->core.tid != iter->tid || b->core.pos >= iter->end) { // no need to proceed+ ret = bam_validate1(NULL, b)? -1 : -5; // determine whether end of region or error+ break;+ }+ else if (is_overlap(iter->beg, iter->end, b)) return ret;+ } else break; // end of file or error+ }+ iter->finished = 1;+ return ret;+}++int bam_fetch(bamFile fp, const bam_index_t *idx, int tid, int beg, int end, void *data, bam_fetch_f func)+{+ int ret;+ bam_iter_t iter;+ bam1_t *b;+ b = bam_init1();+ iter = bam_iter_query(idx, tid, beg, end);+ while ((ret = bam_iter_read(fp, iter, b)) >= 0) func(b, data);+ bam_iter_destroy(iter);+ bam_destroy1(b);+ return (ret == -1)? 0 : ret;+}
+ samtools-0.1.18/bam_lpileup.c view
@@ -0,0 +1,198 @@+#include <stdlib.h>+#include <stdio.h>+#include <assert.h>+#include "bam.h"+#include "ksort.h"++#define TV_GAP 2++typedef struct __freenode_t {+ uint32_t level:28, cnt:4;+ struct __freenode_t *next;+} freenode_t, *freenode_p;++#define freenode_lt(a,b) ((a)->cnt < (b)->cnt || ((a)->cnt == (b)->cnt && (a)->level < (b)->level))+KSORT_INIT(node, freenode_p, freenode_lt)++/* Memory pool, similar to the one in bam_pileup.c */+typedef struct {+ int cnt, n, max;+ freenode_t **buf;+} mempool_t;++static mempool_t *mp_init()+{+ return (mempool_t*)calloc(1, sizeof(mempool_t));+}+static void mp_destroy(mempool_t *mp)+{+ int k;+ for (k = 0; k < mp->n; ++k) free(mp->buf[k]);+ free(mp->buf); free(mp);+}+static inline freenode_t *mp_alloc(mempool_t *mp)+{+ ++mp->cnt;+ if (mp->n == 0) return (freenode_t*)calloc(1, sizeof(freenode_t));+ else return mp->buf[--mp->n];+}+static inline void mp_free(mempool_t *mp, freenode_t *p)+{+ --mp->cnt; p->next = 0; p->cnt = TV_GAP;+ if (mp->n == mp->max) {+ mp->max = mp->max? mp->max<<1 : 256;+ mp->buf = (freenode_t**)realloc(mp->buf, sizeof(freenode_t*) * mp->max);+ }+ mp->buf[mp->n++] = p;+}++/* core part */+struct __bam_lplbuf_t {+ int max, n_cur, n_pre;+ int max_level, *cur_level, *pre_level;+ mempool_t *mp;+ freenode_t **aux, *head, *tail;+ int n_nodes, m_aux;+ bam_pileup_f func;+ void *user_data;+ bam_plbuf_t *plbuf;+};++void bam_lplbuf_reset(bam_lplbuf_t *buf)+{+ freenode_t *p, *q;+ bam_plbuf_reset(buf->plbuf);+ for (p = buf->head; p->next;) {+ q = p->next;+ mp_free(buf->mp, p);+ p = q;+ }+ buf->head = buf->tail;+ buf->max_level = 0;+ buf->n_cur = buf->n_pre = 0;+ buf->n_nodes = 0;+}++static int tview_func(uint32_t tid, uint32_t pos, int n, const bam_pileup1_t *pl, void *data)+{+ bam_lplbuf_t *tv = (bam_lplbuf_t*)data;+ freenode_t *p;+ int i, l, max_level;+ // allocate memory if necessary+ if (tv->max < n) { // enlarge+ tv->max = n;+ kroundup32(tv->max);+ tv->cur_level = (int*)realloc(tv->cur_level, sizeof(int) * tv->max);+ tv->pre_level = (int*)realloc(tv->pre_level, sizeof(int) * tv->max);+ }+ tv->n_cur = n;+ // update cnt+ for (p = tv->head; p->next; p = p->next)+ if (p->cnt > 0) --p->cnt;+ // calculate cur_level[]+ max_level = 0;+ for (i = l = 0; i < n; ++i) {+ const bam_pileup1_t *p = pl + i;+ if (p->is_head) {+ if (tv->head->next && tv->head->cnt == 0) { // then take a free slot+ freenode_t *p = tv->head->next;+ tv->cur_level[i] = tv->head->level;+ mp_free(tv->mp, tv->head);+ tv->head = p;+ --tv->n_nodes;+ } else tv->cur_level[i] = ++tv->max_level;+ } else {+ tv->cur_level[i] = tv->pre_level[l++];+ if (p->is_tail) { // then return a free slot+ tv->tail->level = tv->cur_level[i];+ tv->tail->next = mp_alloc(tv->mp);+ tv->tail = tv->tail->next;+ ++tv->n_nodes;+ }+ }+ if (tv->cur_level[i] > max_level) max_level = tv->cur_level[i];+ ((bam_pileup1_t*)p)->level = tv->cur_level[i];+ }+ assert(l == tv->n_pre);+ tv->func(tid, pos, n, pl, tv->user_data);+ // sort the linked list+ if (tv->n_nodes) {+ freenode_t *q;+ if (tv->n_nodes + 1 > tv->m_aux) { // enlarge+ tv->m_aux = tv->n_nodes + 1;+ kroundup32(tv->m_aux);+ tv->aux = (freenode_t**)realloc(tv->aux, sizeof(void*) * tv->m_aux);+ }+ for (p = tv->head, i = l = 0; p->next;) {+ if (p->level > max_level) { // then discard this entry+ q = p->next;+ mp_free(tv->mp, p);+ p = q;+ } else {+ tv->aux[i++] = p;+ p = p->next;+ }+ }+ tv->aux[i] = tv->tail; // add a proper tail for the loop below+ tv->n_nodes = i;+ if (tv->n_nodes) {+ ks_introsort(node, tv->n_nodes, tv->aux);+ for (i = 0; i < tv->n_nodes; ++i) tv->aux[i]->next = tv->aux[i+1];+ tv->head = tv->aux[0];+ } else tv->head = tv->tail;+ }+ // clean up+ tv->max_level = max_level;+ memcpy(tv->pre_level, tv->cur_level, tv->n_cur * 4);+ // squeeze out terminated levels+ for (i = l = 0; i < n; ++i) {+ const bam_pileup1_t *p = pl + i;+ if (!p->is_tail)+ tv->pre_level[l++] = tv->pre_level[i];+ }+ tv->n_pre = l;+/*+ fprintf(stderr, "%d\t", pos+1);+ for (i = 0; i < n; ++i) {+ const bam_pileup1_t *p = pl + i;+ if (p->is_head) fprintf(stderr, "^");+ if (p->is_tail) fprintf(stderr, "$");+ fprintf(stderr, "%d,", p->level);+ }+ fprintf(stderr, "\n");+*/+ return 0;+}++bam_lplbuf_t *bam_lplbuf_init(bam_pileup_f func, void *data)+{+ bam_lplbuf_t *tv;+ tv = (bam_lplbuf_t*)calloc(1, sizeof(bam_lplbuf_t));+ tv->mp = mp_init();+ tv->head = tv->tail = mp_alloc(tv->mp);+ tv->func = func;+ tv->user_data = data;+ tv->plbuf = bam_plbuf_init(tview_func, tv);+ return (bam_lplbuf_t*)tv;+}++void bam_lplbuf_destroy(bam_lplbuf_t *tv)+{+ freenode_t *p, *q;+ free(tv->cur_level); free(tv->pre_level);+ bam_plbuf_destroy(tv->plbuf);+ free(tv->aux);+ for (p = tv->head; p->next;) {+ q = p->next;+ mp_free(tv->mp, p); p = q;+ }+ mp_free(tv->mp, p);+ assert(tv->mp->cnt == 0);+ mp_destroy(tv->mp);+ free(tv);+}++int bam_lplbuf_push(const bam1_t *b, bam_lplbuf_t *tv)+{+ return bam_plbuf_push(b, tv->plbuf);+}
+ samtools-0.1.18/bam_md.c view
@@ -0,0 +1,384 @@+#include <unistd.h>+#include <assert.h>+#include <string.h>+#include <ctype.h>+#include <math.h>+#include "faidx.h"+#include "sam.h"+#include "kstring.h"+#include "kaln.h"+#include "kprobaln.h"++#define USE_EQUAL 1+#define DROP_TAG 2+#define BIN_QUAL 4+#define UPDATE_NM 8+#define UPDATE_MD 16+#define HASH_QNM 32++char bam_nt16_nt4_table[] = { 4, 0, 1, 4, 2, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4 };++int bam_aux_drop_other(bam1_t *b, uint8_t *s);++void bam_fillmd1_core(bam1_t *b, char *ref, int flag, int max_nm)+{+ uint8_t *seq = bam1_seq(b);+ uint32_t *cigar = bam1_cigar(b);+ bam1_core_t *c = &b->core;+ int i, x, y, u = 0;+ kstring_t *str;+ int32_t old_nm_i = -1, nm = 0;++ str = (kstring_t*)calloc(1, sizeof(kstring_t));+ for (i = y = 0, x = c->pos; i < c->n_cigar; ++i) {+ int j, l = cigar[i]>>4, op = cigar[i]&0xf;+ if (op == BAM_CMATCH || op == BAM_CEQUAL || op == BAM_CDIFF) {+ for (j = 0; j < l; ++j) {+ int z = y + j;+ int c1 = bam1_seqi(seq, z), c2 = bam_nt16_table[(int)ref[x+j]];+ if (ref[x+j] == 0) break; // out of boundary+ if ((c1 == c2 && c1 != 15 && c2 != 15) || c1 == 0) { // a match+ if (flag&USE_EQUAL) seq[z/2] &= (z&1)? 0xf0 : 0x0f;+ ++u;+ } else {+ kputw(u, str); kputc(ref[x+j], str);+ u = 0; ++nm;+ }+ }+ if (j < l) break;+ x += l; y += l;+ } else if (op == BAM_CDEL) {+ kputw(u, str); kputc('^', str);+ for (j = 0; j < l; ++j) {+ if (ref[x+j] == 0) break;+ kputc(ref[x+j], str);+ }+ u = 0;+ if (j < l) break;+ x += l; nm += l;+ } else if (op == BAM_CINS || op == BAM_CSOFT_CLIP) {+ y += l;+ if (op == BAM_CINS) nm += l;+ } else if (op == BAM_CREF_SKIP) {+ x += l;+ }+ }+ kputw(u, str);+ // apply max_nm+ if (max_nm > 0 && nm >= max_nm) {+ for (i = y = 0, x = c->pos; i < c->n_cigar; ++i) {+ int j, l = cigar[i]>>4, op = cigar[i]&0xf;+ if (op == BAM_CMATCH || op == BAM_CEQUAL || op == BAM_CDIFF) {+ for (j = 0; j < l; ++j) {+ int z = y + j;+ int c1 = bam1_seqi(seq, z), c2 = bam_nt16_table[(int)ref[x+j]];+ if (ref[x+j] == 0) break; // out of boundary+ if ((c1 == c2 && c1 != 15 && c2 != 15) || c1 == 0) { // a match+ seq[z/2] |= (z&1)? 0x0f : 0xf0;+ bam1_qual(b)[z] = 0;+ }+ }+ if (j < l) break;+ x += l; y += l;+ } else if (op == BAM_CDEL || op == BAM_CREF_SKIP) x += l;+ else if (op == BAM_CINS || op == BAM_CSOFT_CLIP) y += l;+ }+ }+ // update NM+ if (flag & UPDATE_NM) {+ uint8_t *old_nm = bam_aux_get(b, "NM");+ if (c->flag & BAM_FUNMAP) return;+ if (old_nm) old_nm_i = bam_aux2i(old_nm);+ if (!old_nm) bam_aux_append(b, "NM", 'i', 4, (uint8_t*)&nm);+ else if (nm != old_nm_i) {+ fprintf(stderr, "[bam_fillmd1] different NM for read '%s': %d -> %d\n", bam1_qname(b), old_nm_i, nm);+ bam_aux_del(b, old_nm);+ bam_aux_append(b, "NM", 'i', 4, (uint8_t*)&nm);+ }+ }+ // update MD+ if (flag & UPDATE_MD) {+ uint8_t *old_md = bam_aux_get(b, "MD");+ if (c->flag & BAM_FUNMAP) return;+ if (!old_md) bam_aux_append(b, "MD", 'Z', str->l + 1, (uint8_t*)str->s);+ else {+ int is_diff = 0;+ if (strlen((char*)old_md+1) == str->l) {+ for (i = 0; i < str->l; ++i)+ if (toupper(old_md[i+1]) != toupper(str->s[i]))+ break;+ if (i < str->l) is_diff = 1;+ } else is_diff = 1;+ if (is_diff) {+ fprintf(stderr, "[bam_fillmd1] different MD for read '%s': '%s' -> '%s'\n", bam1_qname(b), old_md+1, str->s);+ bam_aux_del(b, old_md);+ bam_aux_append(b, "MD", 'Z', str->l + 1, (uint8_t*)str->s);+ }+ }+ }+ // drop all tags but RG+ if (flag&DROP_TAG) {+ uint8_t *q = bam_aux_get(b, "RG");+ bam_aux_drop_other(b, q);+ }+ // reduce the resolution of base quality+ if (flag&BIN_QUAL) {+ uint8_t *qual = bam1_qual(b);+ for (i = 0; i < b->core.l_qseq; ++i)+ if (qual[i] >= 3) qual[i] = qual[i]/10*10 + 7;+ }+ free(str->s); free(str);+}++void bam_fillmd1(bam1_t *b, char *ref, int flag)+{+ bam_fillmd1_core(b, ref, flag, 0);+}++int bam_cap_mapQ(bam1_t *b, char *ref, int thres)+{+ uint8_t *seq = bam1_seq(b), *qual = bam1_qual(b);+ uint32_t *cigar = bam1_cigar(b);+ bam1_core_t *c = &b->core;+ int i, x, y, mm, q, len, clip_l, clip_q;+ double t;+ if (thres < 0) thres = 40; // set the default+ mm = q = len = clip_l = clip_q = 0;+ for (i = y = 0, x = c->pos; i < c->n_cigar; ++i) {+ int j, l = cigar[i]>>4, op = cigar[i]&0xf;+ if (op == BAM_CMATCH || op == BAM_CEQUAL || op == BAM_CDIFF) {+ for (j = 0; j < l; ++j) {+ int z = y + j;+ int c1 = bam1_seqi(seq, z), c2 = bam_nt16_table[(int)ref[x+j]];+ if (ref[x+j] == 0) break; // out of boundary+ if (c2 != 15 && c1 != 15 && qual[z] >= 13) { // not ambiguous+ ++len;+ if (c1 && c1 != c2 && qual[z] >= 13) { // mismatch+ ++mm;+ q += qual[z] > 33? 33 : qual[z];+ }+ }+ }+ if (j < l) break;+ x += l; y += l; len += l;+ } else if (op == BAM_CDEL) {+ for (j = 0; j < l; ++j)+ if (ref[x+j] == 0) break;+ if (j < l) break;+ x += l;+ } else if (op == BAM_CSOFT_CLIP) {+ for (j = 0; j < l; ++j) clip_q += qual[y+j];+ clip_l += l;+ y += l;+ } else if (op == BAM_CHARD_CLIP) {+ clip_q += 13 * l;+ clip_l += l;+ } else if (op == BAM_CINS) y += l;+ else if (op == BAM_CREF_SKIP) x += l;+ }+ for (i = 0, t = 1; i < mm; ++i)+ t *= (double)len / (i+1);+ t = q - 4.343 * log(t) + clip_q / 5.;+ if (t > thres) return -1;+ if (t < 0) t = 0;+ t = sqrt((thres - t) / thres) * thres;+// fprintf(stderr, "%s %lf %d\n", bam1_qname(b), t, q);+ return (int)(t + .499);+}++int bam_prob_realn_core(bam1_t *b, const char *ref, int flag)+{+ int k, i, bw, x, y, yb, ye, xb, xe, apply_baq = flag&1, extend_baq = flag>>1&1;+ uint32_t *cigar = bam1_cigar(b);+ bam1_core_t *c = &b->core;+ kpa_par_t conf = kpa_par_def;+ uint8_t *bq = 0, *zq = 0, *qual = bam1_qual(b);+ if ((c->flag & BAM_FUNMAP) || b->core.l_qseq == 0) return -1; // do nothing+ // test if BQ or ZQ is present+ if ((bq = bam_aux_get(b, "BQ")) != 0) ++bq;+ if ((zq = bam_aux_get(b, "ZQ")) != 0 && *zq == 'Z') ++zq;+ if (bq && zq) { // remove the ZQ tag+ bam_aux_del(b, zq-1);+ zq = 0;+ }+ if (bq || zq) {+ if ((apply_baq && zq) || (!apply_baq && bq)) return -3; // in both cases, do nothing+ if (bq && apply_baq) { // then convert BQ to ZQ+ for (i = 0; i < c->l_qseq; ++i)+ qual[i] = qual[i] + 64 < bq[i]? 0 : qual[i] - ((int)bq[i] - 64);+ *(bq - 3) = 'Z';+ } else if (zq && !apply_baq) { // then convert ZQ to BQ+ for (i = 0; i < c->l_qseq; ++i)+ qual[i] += (int)zq[i] - 64;+ *(zq - 3) = 'B';+ }+ return 0;+ }+ // find the start and end of the alignment + x = c->pos, y = 0, yb = ye = xb = xe = -1;+ for (k = 0; k < c->n_cigar; ++k) {+ int op, l;+ op = cigar[k]&0xf; l = cigar[k]>>4;+ if (op == BAM_CMATCH || op == BAM_CEQUAL || op == BAM_CDIFF) {+ if (yb < 0) yb = y;+ if (xb < 0) xb = x;+ ye = y + l; xe = x + l;+ x += l; y += l;+ } else if (op == BAM_CSOFT_CLIP || op == BAM_CINS) y += l;+ else if (op == BAM_CDEL) x += l;+ else if (op == BAM_CREF_SKIP) return -1; // do nothing if there is a reference skip+ }+ // set bandwidth and the start and the end+ bw = 7;+ if (abs((xe - xb) - (ye - yb)) > bw)+ bw = abs((xe - xb) - (ye - yb)) + 3;+ conf.bw = bw;+ xb -= yb + bw/2; if (xb < 0) xb = 0;+ xe += c->l_qseq - ye + bw/2;+ if (xe - xb - c->l_qseq > bw)+ xb += (xe - xb - c->l_qseq - bw) / 2, xe -= (xe - xb - c->l_qseq - bw) / 2;+ { // glocal+ uint8_t *s, *r, *q, *seq = bam1_seq(b), *bq;+ int *state;+ bq = calloc(c->l_qseq + 1, 1);+ memcpy(bq, qual, c->l_qseq);+ s = calloc(c->l_qseq, 1);+ for (i = 0; i < c->l_qseq; ++i) s[i] = bam_nt16_nt4_table[bam1_seqi(seq, i)];+ r = calloc(xe - xb, 1);+ for (i = xb; i < xe; ++i) {+ if (ref[i] == 0) { xe = i; break; }+ r[i-xb] = bam_nt16_nt4_table[bam_nt16_table[(int)ref[i]]];+ }+ state = calloc(c->l_qseq, sizeof(int));+ q = calloc(c->l_qseq, 1);+ kpa_glocal(r, xe-xb, s, c->l_qseq, qual, &conf, state, q);+ if (!extend_baq) { // in this block, bq[] is capped by base quality qual[]+ for (k = 0, x = c->pos, y = 0; k < c->n_cigar; ++k) {+ int op = cigar[k]&0xf, l = cigar[k]>>4;+ if (op == BAM_CMATCH || op == BAM_CEQUAL || op == BAM_CDIFF) {+ for (i = y; i < y + l; ++i) {+ if ((state[i]&3) != 0 || state[i]>>2 != x - xb + (i - y)) bq[i] = 0;+ else bq[i] = bq[i] < q[i]? bq[i] : q[i];+ }+ x += l; y += l;+ } else if (op == BAM_CSOFT_CLIP || op == BAM_CINS) y += l;+ else if (op == BAM_CDEL) x += l;+ }+ for (i = 0; i < c->l_qseq; ++i) bq[i] = qual[i] - bq[i] + 64; // finalize BQ+ } else { // in this block, bq[] is BAQ that can be larger than qual[] (different from the above!)+ uint8_t *left, *rght;+ left = calloc(c->l_qseq, 1); rght = calloc(c->l_qseq, 1);+ for (k = 0, x = c->pos, y = 0; k < c->n_cigar; ++k) {+ int op = cigar[k]&0xf, l = cigar[k]>>4;+ if (op == BAM_CMATCH || op == BAM_CEQUAL || op == BAM_CDIFF) {+ for (i = y; i < y + l; ++i)+ bq[i] = ((state[i]&3) != 0 || state[i]>>2 != x - xb + (i - y))? 0 : q[i];+ for (left[y] = bq[y], i = y + 1; i < y + l; ++i)+ left[i] = bq[i] > left[i-1]? bq[i] : left[i-1];+ for (rght[y+l-1] = bq[y+l-1], i = y + l - 2; i >= y; --i)+ rght[i] = bq[i] > rght[i+1]? bq[i] : rght[i+1];+ for (i = y; i < y + l; ++i)+ bq[i] = left[i] < rght[i]? left[i] : rght[i];+ x += l; y += l;+ } else if (op == BAM_CSOFT_CLIP || op == BAM_CINS) y += l;+ else if (op == BAM_CDEL) x += l;+ }+ for (i = 0; i < c->l_qseq; ++i) bq[i] = 64 + (qual[i] <= bq[i]? 0 : qual[i] - bq[i]); // finalize BQ+ free(left); free(rght);+ }+ if (apply_baq) {+ for (i = 0; i < c->l_qseq; ++i) qual[i] -= bq[i] - 64; // modify qual+ bam_aux_append(b, "ZQ", 'Z', c->l_qseq + 1, bq);+ } else bam_aux_append(b, "BQ", 'Z', c->l_qseq + 1, bq);+ free(bq); free(s); free(r); free(q); free(state);+ }+ return 0;+}++int bam_prob_realn(bam1_t *b, const char *ref)+{+ return bam_prob_realn_core(b, ref, 1);+}++int bam_fillmd(int argc, char *argv[])+{+ int c, flt_flag, tid = -2, ret, len, is_bam_out, is_sam_in, is_uncompressed, max_nm, is_realn, capQ, baq_flag;+ samfile_t *fp, *fpout = 0;+ faidx_t *fai;+ char *ref = 0, mode_w[8], mode_r[8];+ bam1_t *b;++ flt_flag = UPDATE_NM | UPDATE_MD;+ is_bam_out = is_sam_in = is_uncompressed = is_realn = max_nm = capQ = baq_flag = 0;+ mode_w[0] = mode_r[0] = 0;+ strcpy(mode_r, "r"); strcpy(mode_w, "w");+ while ((c = getopt(argc, argv, "EqreuNhbSC:n:Ad")) >= 0) {+ switch (c) {+ case 'r': is_realn = 1; break;+ case 'e': flt_flag |= USE_EQUAL; break;+ case 'd': flt_flag |= DROP_TAG; break;+ case 'q': flt_flag |= BIN_QUAL; break;+ case 'h': flt_flag |= HASH_QNM; break;+ case 'N': flt_flag &= ~(UPDATE_MD|UPDATE_NM); break;+ case 'b': is_bam_out = 1; break;+ case 'u': is_uncompressed = is_bam_out = 1; break;+ case 'S': is_sam_in = 1; break;+ case 'n': max_nm = atoi(optarg); break;+ case 'C': capQ = atoi(optarg); break;+ case 'A': baq_flag |= 1; break;+ case 'E': baq_flag |= 2; break;+ default: fprintf(stderr, "[bam_fillmd] unrecognized option '-%c'\n", c); return 1;+ }+ }+ if (!is_sam_in) strcat(mode_r, "b");+ if (is_bam_out) strcat(mode_w, "b");+ else strcat(mode_w, "h");+ if (is_uncompressed) strcat(mode_w, "u");+ if (optind + 1 >= argc) {+ fprintf(stderr, "\n");+ fprintf(stderr, "Usage: samtools fillmd [-eubrS] <aln.bam> <ref.fasta>\n\n");+ fprintf(stderr, "Options: -e change identical bases to '='\n");+ fprintf(stderr, " -u uncompressed BAM output (for piping)\n");+ fprintf(stderr, " -b compressed BAM output\n");+ fprintf(stderr, " -S the input is SAM with header\n");+ fprintf(stderr, " -A modify the quality string\n");+ fprintf(stderr, " -r compute the BQ tag (without -A) or cap baseQ by BAQ (with -A)\n");+ fprintf(stderr, " -E extended BAQ for better sensitivity but lower specificity\n\n");+ return 1;+ }+ fp = samopen(argv[optind], mode_r, 0);+ if (fp == 0) return 1;+ if (is_sam_in && (fp->header == 0 || fp->header->n_targets == 0)) {+ fprintf(stderr, "[bam_fillmd] input SAM does not have header. Abort!\n");+ return 1;+ }+ fpout = samopen("-", mode_w, fp->header);+ fai = fai_load(argv[optind+1]);++ b = bam_init1();+ while ((ret = samread(fp, b)) >= 0) {+ if (b->core.tid >= 0) {+ if (tid != b->core.tid) {+ free(ref);+ ref = fai_fetch(fai, fp->header->target_name[b->core.tid], &len);+ tid = b->core.tid;+ if (ref == 0)+ fprintf(stderr, "[bam_fillmd] fail to find sequence '%s' in the reference.\n",+ fp->header->target_name[tid]);+ }+ if (is_realn) bam_prob_realn_core(b, ref, baq_flag);+ if (capQ > 10) {+ int q = bam_cap_mapQ(b, ref, capQ);+ if (b->core.qual > q) b->core.qual = q;+ }+ if (ref) bam_fillmd1_core(b, ref, flt_flag, max_nm);+ }+ samwrite(fpout, b);+ }+ bam_destroy1(b);++ free(ref);+ fai_destroy(fai);+ samclose(fp); samclose(fpout);+ return 0;+}
+ samtools-0.1.18/bam_pileup.c view
@@ -0,0 +1,437 @@+#include <stdio.h>+#include <stdlib.h>+#include <ctype.h>+#include <assert.h>+#include "sam.h"++typedef struct {+ int k, x, y, end;+} cstate_t;++static cstate_t g_cstate_null = { -1, 0, 0, 0 };++typedef struct __linkbuf_t {+ bam1_t b;+ uint32_t beg, end;+ cstate_t s;+ struct __linkbuf_t *next;+} lbnode_t;++/* --- BEGIN: Memory pool */++typedef struct {+ int cnt, n, max;+ lbnode_t **buf;+} mempool_t;++static mempool_t *mp_init()+{+ mempool_t *mp;+ mp = (mempool_t*)calloc(1, sizeof(mempool_t));+ return mp;+}+static void mp_destroy(mempool_t *mp)+{+ int k;+ for (k = 0; k < mp->n; ++k) {+ free(mp->buf[k]->b.data);+ free(mp->buf[k]);+ }+ free(mp->buf);+ free(mp);+}+static inline lbnode_t *mp_alloc(mempool_t *mp)+{+ ++mp->cnt;+ if (mp->n == 0) return (lbnode_t*)calloc(1, sizeof(lbnode_t));+ else return mp->buf[--mp->n];+}+static inline void mp_free(mempool_t *mp, lbnode_t *p)+{+ --mp->cnt; p->next = 0; // clear lbnode_t::next here+ if (mp->n == mp->max) {+ mp->max = mp->max? mp->max<<1 : 256;+ mp->buf = (lbnode_t**)realloc(mp->buf, sizeof(lbnode_t*) * mp->max);+ }+ mp->buf[mp->n++] = p;+}++/* --- END: Memory pool */++/* --- BEGIN: Auxiliary functions */++/* s->k: the index of the CIGAR operator that has just been processed.+ s->x: the reference coordinate of the start of s->k+ s->y: the query coordiante of the start of s->k+ */+static inline int resolve_cigar2(bam_pileup1_t *p, uint32_t pos, cstate_t *s)+{+#define _cop(c) ((c)&BAM_CIGAR_MASK)+#define _cln(c) ((c)>>BAM_CIGAR_SHIFT)++ bam1_t *b = p->b;+ bam1_core_t *c = &b->core;+ uint32_t *cigar = bam1_cigar(b);+ int k, is_head = 0;+ // determine the current CIGAR operation+// fprintf(stderr, "%s\tpos=%d\tend=%d\t(%d,%d,%d)\n", bam1_qname(b), pos, s->end, s->k, s->x, s->y);+ if (s->k == -1) { // never processed+ is_head = 1;+ if (c->n_cigar == 1) { // just one operation, save a loop+ if (_cop(cigar[0]) == BAM_CMATCH || _cop(cigar[0]) == BAM_CEQUAL || _cop(cigar[0]) == BAM_CDIFF) s->k = 0, s->x = c->pos, s->y = 0;+ } else { // find the first match or deletion+ for (k = 0, s->x = c->pos, s->y = 0; k < c->n_cigar; ++k) {+ int op = _cop(cigar[k]);+ int l = _cln(cigar[k]);+ if (op == BAM_CMATCH || op == BAM_CDEL || op == BAM_CEQUAL || op == BAM_CDIFF) break;+ else if (op == BAM_CREF_SKIP) s->x += l;+ else if (op == BAM_CINS || op == BAM_CSOFT_CLIP) s->y += l;+ }+ assert(k < c->n_cigar);+ s->k = k;+ }+ } else { // the read has been processed before+ int op, l = _cln(cigar[s->k]);+ if (pos - s->x >= l) { // jump to the next operation+ assert(s->k < c->n_cigar); // otherwise a bug: this function should not be called in this case+ op = _cop(cigar[s->k+1]);+ if (op == BAM_CMATCH || op == BAM_CDEL || op == BAM_CREF_SKIP || op == BAM_CEQUAL || op == BAM_CDIFF) { // jump to the next without a loop+ if (_cop(cigar[s->k]) == BAM_CMATCH|| _cop(cigar[s->k]) == BAM_CEQUAL || _cop(cigar[s->k]) == BAM_CDIFF) s->y += l;+ s->x += l;+ ++s->k;+ } else { // find the next M/D/N/=/X+ if (_cop(cigar[s->k]) == BAM_CMATCH|| _cop(cigar[s->k]) == BAM_CEQUAL || _cop(cigar[s->k]) == BAM_CDIFF) s->y += l;+ s->x += l;+ for (k = s->k + 1; k < c->n_cigar; ++k) {+ op = _cop(cigar[k]), l = _cln(cigar[k]);+ if (op == BAM_CMATCH || op == BAM_CDEL || op == BAM_CREF_SKIP || op == BAM_CEQUAL || op == BAM_CDIFF) break;+ else if (op == BAM_CINS || op == BAM_CSOFT_CLIP) s->y += l;+ }+ s->k = k;+ }+ assert(s->k < c->n_cigar); // otherwise a bug+ } // else, do nothing+ }+ { // collect pileup information+ int op, l;+ op = _cop(cigar[s->k]); l = _cln(cigar[s->k]);+ p->is_del = p->indel = p->is_refskip = 0;+ if (s->x + l - 1 == pos && s->k + 1 < c->n_cigar) { // peek the next operation+ int op2 = _cop(cigar[s->k+1]);+ int l2 = _cln(cigar[s->k+1]);+ if (op2 == BAM_CDEL) p->indel = -(int)l2;+ else if (op2 == BAM_CINS) p->indel = l2;+ else if (op2 == BAM_CPAD && s->k + 2 < c->n_cigar) { // no working for adjacent padding+ int l3 = 0;+ for (k = s->k + 2; k < c->n_cigar; ++k) {+ op2 = _cop(cigar[k]); l2 = _cln(cigar[k]);+ if (op2 == BAM_CINS) l3 += l2;+ else if (op2 == BAM_CDEL || op2 == BAM_CMATCH || op2 == BAM_CREF_SKIP || op2 == BAM_CEQUAL || op2 == BAM_CDIFF) break;+ }+ if (l3 > 0) p->indel = l3;+ }+ }+ if (op == BAM_CMATCH || op == BAM_CEQUAL || op == BAM_CDIFF) {+ p->qpos = s->y + (pos - s->x);+ } else if (op == BAM_CDEL || op == BAM_CREF_SKIP) {+ p->is_del = 1; p->qpos = s->y; // FIXME: distinguish D and N!!!!!+ p->is_refskip = (op == BAM_CREF_SKIP);+ } // cannot be other operations; otherwise a bug+ p->is_head = (pos == c->pos); p->is_tail = (pos == s->end);+ }+ return 1;+}++/* --- END: Auxiliary functions */++/*******************+ * pileup iterator *+ *******************/++struct __bam_plp_t {+ mempool_t *mp;+ lbnode_t *head, *tail, *dummy;+ int32_t tid, pos, max_tid, max_pos;+ int is_eof, flag_mask, max_plp, error, maxcnt;+ bam_pileup1_t *plp;+ // for the "auto" interface only+ bam1_t *b;+ bam_plp_auto_f func;+ void *data;+};++bam_plp_t bam_plp_init(bam_plp_auto_f func, void *data)+{+ bam_plp_t iter;+ iter = calloc(1, sizeof(struct __bam_plp_t));+ iter->mp = mp_init();+ iter->head = iter->tail = mp_alloc(iter->mp);+ iter->dummy = mp_alloc(iter->mp);+ iter->max_tid = iter->max_pos = -1;+ iter->flag_mask = BAM_DEF_MASK;+ iter->maxcnt = 8000;+ if (func) {+ iter->func = func;+ iter->data = data;+ iter->b = bam_init1();+ }+ return iter;+}++void bam_plp_destroy(bam_plp_t iter)+{+ mp_free(iter->mp, iter->dummy);+ mp_free(iter->mp, iter->head);+ if (iter->mp->cnt != 0)+ fprintf(stderr, "[bam_plp_destroy] memory leak: %d. Continue anyway.\n", iter->mp->cnt);+ mp_destroy(iter->mp);+ if (iter->b) bam_destroy1(iter->b);+ free(iter->plp);+ free(iter);+}++const bam_pileup1_t *bam_plp_next(bam_plp_t iter, int *_tid, int *_pos, int *_n_plp)+{+ if (iter->error) { *_n_plp = -1; return 0; }+ *_n_plp = 0;+ if (iter->is_eof && iter->head->next == 0) return 0;+ while (iter->is_eof || iter->max_tid > iter->tid || (iter->max_tid == iter->tid && iter->max_pos > iter->pos)) {+ int n_plp = 0;+ lbnode_t *p, *q;+ // write iter->plp at iter->pos+ iter->dummy->next = iter->head;+ for (p = iter->head, q = iter->dummy; p->next; q = p, p = p->next) {+ if (p->b.core.tid < iter->tid || (p->b.core.tid == iter->tid && p->end <= iter->pos)) { // then remove+ q->next = p->next; mp_free(iter->mp, p); p = q;+ } else if (p->b.core.tid == iter->tid && p->beg <= iter->pos) { // here: p->end > pos; then add to pileup+ if (n_plp == iter->max_plp) { // then double the capacity+ iter->max_plp = iter->max_plp? iter->max_plp<<1 : 256;+ iter->plp = (bam_pileup1_t*)realloc(iter->plp, sizeof(bam_pileup1_t) * iter->max_plp);+ }+ iter->plp[n_plp].b = &p->b;+ if (resolve_cigar2(iter->plp + n_plp, iter->pos, &p->s)) ++n_plp; // actually always true...+ }+ }+ iter->head = iter->dummy->next; // dummy->next may be changed+ *_n_plp = n_plp; *_tid = iter->tid; *_pos = iter->pos;+ // update iter->tid and iter->pos+ if (iter->head->next) {+ if (iter->tid > iter->head->b.core.tid) {+ fprintf(stderr, "[%s] unsorted input. Pileup aborts.\n", __func__);+ iter->error = 1;+ *_n_plp = -1;+ return 0;+ }+ }+ if (iter->tid < iter->head->b.core.tid) { // come to a new reference sequence+ iter->tid = iter->head->b.core.tid; iter->pos = iter->head->beg; // jump to the next reference+ } else if (iter->pos < iter->head->beg) { // here: tid == head->b.core.tid+ iter->pos = iter->head->beg; // jump to the next position+ } else ++iter->pos; // scan contiguously+ // return+ if (n_plp) return iter->plp;+ if (iter->is_eof && iter->head->next == 0) break;+ }+ return 0;+}++int bam_plp_push(bam_plp_t iter, const bam1_t *b)+{+ if (iter->error) return -1;+ if (b) {+ if (b->core.tid < 0) return 0;+ if (b->core.flag & iter->flag_mask) return 0;+ if (iter->tid == b->core.tid && iter->pos == b->core.pos && iter->mp->cnt > iter->maxcnt) return 0;+ bam_copy1(&iter->tail->b, b);+ iter->tail->beg = b->core.pos; iter->tail->end = bam_calend(&b->core, bam1_cigar(b));+ iter->tail->s = g_cstate_null; iter->tail->s.end = iter->tail->end - 1; // initialize cstate_t+ if (b->core.tid < iter->max_tid) {+ fprintf(stderr, "[bam_pileup_core] the input is not sorted (chromosomes out of order)\n");+ iter->error = 1;+ return -1;+ }+ if ((b->core.tid == iter->max_tid) && (iter->tail->beg < iter->max_pos)) {+ fprintf(stderr, "[bam_pileup_core] the input is not sorted (reads out of order)\n");+ iter->error = 1;+ return -1;+ }+ iter->max_tid = b->core.tid; iter->max_pos = iter->tail->beg;+ if (iter->tail->end > iter->pos || iter->tail->b.core.tid > iter->tid) {+ iter->tail->next = mp_alloc(iter->mp);+ iter->tail = iter->tail->next;+ }+ } else iter->is_eof = 1;+ return 0;+}++const bam_pileup1_t *bam_plp_auto(bam_plp_t iter, int *_tid, int *_pos, int *_n_plp)+{+ const bam_pileup1_t *plp;+ if (iter->func == 0 || iter->error) { *_n_plp = -1; return 0; }+ if ((plp = bam_plp_next(iter, _tid, _pos, _n_plp)) != 0) return plp;+ else { // no pileup line can be obtained; read alignments+ *_n_plp = 0;+ if (iter->is_eof) return 0;+ while (iter->func(iter->data, iter->b) >= 0) {+ if (bam_plp_push(iter, iter->b) < 0) {+ *_n_plp = -1;+ return 0;+ }+ if ((plp = bam_plp_next(iter, _tid, _pos, _n_plp)) != 0) return plp;+ // otherwise no pileup line can be returned; read the next alignment.+ }+ bam_plp_push(iter, 0);+ if ((plp = bam_plp_next(iter, _tid, _pos, _n_plp)) != 0) return plp;+ return 0;+ }+}++void bam_plp_reset(bam_plp_t iter)+{+ lbnode_t *p, *q;+ iter->max_tid = iter->max_pos = -1;+ iter->tid = iter->pos = 0;+ iter->is_eof = 0;+ for (p = iter->head; p->next;) {+ q = p->next;+ mp_free(iter->mp, p);+ p = q;+ }+ iter->head = iter->tail;+}++void bam_plp_set_mask(bam_plp_t iter, int mask)+{+ iter->flag_mask = mask < 0? BAM_DEF_MASK : (BAM_FUNMAP | mask);+}++void bam_plp_set_maxcnt(bam_plp_t iter, int maxcnt)+{+ iter->maxcnt = maxcnt;+}++/*****************+ * callback APIs *+ *****************/++int bam_pileup_file(bamFile fp, int mask, bam_pileup_f func, void *func_data)+{+ bam_plbuf_t *buf;+ int ret;+ bam1_t *b;+ b = bam_init1();+ buf = bam_plbuf_init(func, func_data);+ bam_plbuf_set_mask(buf, mask);+ while ((ret = bam_read1(fp, b)) >= 0)+ bam_plbuf_push(b, buf);+ bam_plbuf_push(0, buf);+ bam_plbuf_destroy(buf);+ bam_destroy1(b);+ return 0;+}++void bam_plbuf_set_mask(bam_plbuf_t *buf, int mask)+{+ bam_plp_set_mask(buf->iter, mask);+}++void bam_plbuf_reset(bam_plbuf_t *buf)+{+ bam_plp_reset(buf->iter);+}++bam_plbuf_t *bam_plbuf_init(bam_pileup_f func, void *data)+{+ bam_plbuf_t *buf;+ buf = calloc(1, sizeof(bam_plbuf_t));+ buf->iter = bam_plp_init(0, 0);+ buf->func = func;+ buf->data = data;+ return buf;+}++void bam_plbuf_destroy(bam_plbuf_t *buf)+{+ bam_plp_destroy(buf->iter);+ free(buf);+}++int bam_plbuf_push(const bam1_t *b, bam_plbuf_t *buf)+{+ int ret, n_plp, tid, pos;+ const bam_pileup1_t *plp;+ ret = bam_plp_push(buf->iter, b);+ if (ret < 0) return ret;+ while ((plp = bam_plp_next(buf->iter, &tid, &pos, &n_plp)) != 0)+ buf->func(tid, pos, n_plp, plp, buf->data);+ return 0;+}++/***********+ * mpileup *+ ***********/++struct __bam_mplp_t {+ int n;+ uint64_t min, *pos;+ bam_plp_t *iter;+ int *n_plp;+ const bam_pileup1_t **plp;+};++bam_mplp_t bam_mplp_init(int n, bam_plp_auto_f func, void **data)+{+ int i;+ bam_mplp_t iter;+ iter = calloc(1, sizeof(struct __bam_mplp_t));+ iter->pos = calloc(n, 8);+ iter->n_plp = calloc(n, sizeof(int));+ iter->plp = calloc(n, sizeof(void*));+ iter->iter = calloc(n, sizeof(void*));+ iter->n = n;+ iter->min = (uint64_t)-1;+ for (i = 0; i < n; ++i) {+ iter->iter[i] = bam_plp_init(func, data[i]);+ iter->pos[i] = iter->min;+ }+ return iter;+}++void bam_mplp_set_maxcnt(bam_mplp_t iter, int maxcnt)+{+ int i;+ for (i = 0; i < iter->n; ++i)+ iter->iter[i]->maxcnt = maxcnt;+}++void bam_mplp_destroy(bam_mplp_t iter)+{+ int i;+ for (i = 0; i < iter->n; ++i) bam_plp_destroy(iter->iter[i]);+ free(iter->iter); free(iter->pos); free(iter->n_plp); free(iter->plp);+ free(iter);+}++int bam_mplp_auto(bam_mplp_t iter, int *_tid, int *_pos, int *n_plp, const bam_pileup1_t **plp)+{+ int i, ret = 0;+ uint64_t new_min = (uint64_t)-1;+ for (i = 0; i < iter->n; ++i) {+ if (iter->pos[i] == iter->min) {+ int tid, pos;+ iter->plp[i] = bam_plp_auto(iter->iter[i], &tid, &pos, &iter->n_plp[i]);+ iter->pos[i] = (uint64_t)tid<<32 | pos;+ }+ if (iter->plp[i] && iter->pos[i] < new_min) new_min = iter->pos[i];+ }+ iter->min = new_min;+ if (new_min == (uint64_t)-1) return 0;+ *_tid = new_min>>32; *_pos = (uint32_t)new_min;+ for (i = 0; i < iter->n; ++i) {+ if (iter->pos[i] == iter->min) { // FIXME: valgrind reports "uninitialised value(s) at this line"+ n_plp[i] = iter->n_plp[i], plp[i] = iter->plp[i];+ ++ret;+ } else n_plp[i] = 0, plp[i] = 0;+ }+ return ret;+}
+ samtools-0.1.18/bam_reheader.c view
@@ -0,0 +1,61 @@+#include <stdio.h>+#include <stdlib.h>+#include "bgzf.h"+#include "bam.h"++#define BUF_SIZE 0x10000++int bam_reheader(BGZF *in, const bam_header_t *h, int fd)+{+ BGZF *fp;+ bam_header_t *old;+ int len;+ uint8_t *buf;+ if (in->open_mode != 'r') return -1;+ buf = malloc(BUF_SIZE);+ old = bam_header_read(in);+ fp = bgzf_fdopen(fd, "w");+ bam_header_write(fp, h);+ if (in->block_offset < in->block_length) {+ bgzf_write(fp, in->uncompressed_block + in->block_offset, in->block_length - in->block_offset);+ bgzf_flush(fp);+ }+#ifdef _USE_KNETFILE+ while ((len = knet_read(in->x.fpr, buf, BUF_SIZE)) > 0)+ fwrite(buf, 1, len, fp->x.fpw);+#else+ while (!feof(in->file) && (len = fread(buf, 1, BUF_SIZE, in->file)) > 0)+ fwrite(buf, 1, len, fp->file);+#endif+ free(buf);+ fp->block_offset = in->block_offset = 0;+ bgzf_close(fp);+ return 0;+}++int main_reheader(int argc, char *argv[])+{+ bam_header_t *h;+ BGZF *in;+ if (argc != 3) {+ fprintf(stderr, "Usage: samtools reheader <in.header.sam> <in.bam>\n");+ return 1;+ }+ { // read the header+ tamFile fph = sam_open(argv[1]);+ if (fph == 0) {+ fprintf(stderr, "[%s] fail to read the header from %s.\n", __func__, argv[1]);+ return 1;+ }+ h = sam_header_read(fph);+ sam_close(fph);+ }+ in = strcmp(argv[2], "-")? bam_open(argv[2], "r") : bam_dopen(fileno(stdin), "r");+ if (in == 0) {+ fprintf(stderr, "[%s] fail to open file %s.\n", __func__, argv[2]);+ return 1;+ }+ bam_reheader(in, h, fileno(stdout));+ bgzf_close(in);+ return 0;+}
+ samtools-0.1.18/bam_sort.c view
@@ -0,0 +1,438 @@+#include <stdlib.h>+#include <ctype.h>+#include <assert.h>+#include <errno.h>+#include <stdio.h>+#include <string.h>+#include <unistd.h>+#include "bam.h"+#include "ksort.h"++static int g_is_by_qname = 0;++static inline int strnum_cmp(const char *a, const char *b)+{+ char *pa, *pb;+ pa = (char*)a; pb = (char*)b;+ while (*pa && *pb) {+ if (isdigit(*pa) && isdigit(*pb)) {+ long ai, bi;+ ai = strtol(pa, &pa, 10);+ bi = strtol(pb, &pb, 10);+ if (ai != bi) return ai<bi? -1 : ai>bi? 1 : 0;+ } else {+ if (*pa != *pb) break;+ ++pa; ++pb;+ }+ }+ if (*pa == *pb)+ return (pa-a) < (pb-b)? -1 : (pa-a) > (pb-b)? 1 : 0;+ return *pa<*pb? -1 : *pa>*pb? 1 : 0;+}++#define HEAP_EMPTY 0xffffffffffffffffull++typedef struct {+ int i;+ uint64_t pos, idx;+ bam1_t *b;+} heap1_t;++#define __pos_cmp(a, b) ((a).pos > (b).pos || ((a).pos == (b).pos && ((a).i > (b).i || ((a).i == (b).i && (a).idx > (b).idx))))++static inline int heap_lt(const heap1_t a, const heap1_t b)+{+ if (g_is_by_qname) {+ int t;+ if (a.b == 0 || b.b == 0) return a.b == 0? 1 : 0;+ t = strnum_cmp(bam1_qname(a.b), bam1_qname(b.b));+ return (t > 0 || (t == 0 && __pos_cmp(a, b)));+ } else return __pos_cmp(a, b);+}++KSORT_INIT(heap, heap1_t, heap_lt)++static void swap_header_targets(bam_header_t *h1, bam_header_t *h2)+{+ bam_header_t t;+ t.n_targets = h1->n_targets, h1->n_targets = h2->n_targets, h2->n_targets = t.n_targets;+ t.target_name = h1->target_name, h1->target_name = h2->target_name, h2->target_name = t.target_name;+ t.target_len = h1->target_len, h1->target_len = h2->target_len, h2->target_len = t.target_len;+}++static void swap_header_text(bam_header_t *h1, bam_header_t *h2)+{+ int tempi;+ char *temps;+ tempi = h1->l_text, h1->l_text = h2->l_text, h2->l_text = tempi;+ temps = h1->text, h1->text = h2->text, h2->text = temps;+}++#define MERGE_RG 1+#define MERGE_UNCOMP 2+#define MERGE_LEVEL1 4+#define MERGE_FORCE 8++/*!+ @abstract Merge multiple sorted BAM.+ @param is_by_qname whether to sort by query name+ @param out output BAM file name+ @param headers name of SAM file from which to copy '@' header lines,+ or NULL to copy them from the first file to be merged+ @param n number of files to be merged+ @param fn names of files to be merged++ @discussion Padding information may NOT correctly maintained. This+ function is NOT thread safe.+ */+int bam_merge_core(int by_qname, const char *out, const char *headers, int n, char * const *fn,+ int flag, const char *reg)+{+ bamFile fpout, *fp;+ heap1_t *heap;+ bam_header_t *hout = 0;+ bam_header_t *hheaders = NULL;+ int i, j, *RG_len = 0;+ uint64_t idx = 0;+ char **RG = 0;+ bam_iter_t *iter = 0;++ if (headers) {+ tamFile fpheaders = sam_open(headers);+ if (fpheaders == 0) {+ const char *message = strerror(errno);+ fprintf(stderr, "[bam_merge_core] cannot open '%s': %s\n", headers, message);+ return -1;+ }+ hheaders = sam_header_read(fpheaders);+ sam_close(fpheaders);+ }++ g_is_by_qname = by_qname;+ fp = (bamFile*)calloc(n, sizeof(bamFile));+ heap = (heap1_t*)calloc(n, sizeof(heap1_t));+ iter = (bam_iter_t*)calloc(n, sizeof(bam_iter_t));+ // prepare RG tag+ if (flag & MERGE_RG) {+ RG = (char**)calloc(n, sizeof(void*));+ RG_len = (int*)calloc(n, sizeof(int));+ for (i = 0; i != n; ++i) {+ int l = strlen(fn[i]);+ const char *s = fn[i];+ if (l > 4 && strcmp(s + l - 4, ".bam") == 0) l -= 4;+ for (j = l - 1; j >= 0; --j) if (s[j] == '/') break;+ ++j; l -= j;+ RG[i] = calloc(l + 1, 1);+ RG_len[i] = l;+ strncpy(RG[i], s + j, l);+ }+ }+ // read the first+ for (i = 0; i != n; ++i) {+ bam_header_t *hin;+ fp[i] = bam_open(fn[i], "r");+ if (fp[i] == 0) {+ int j;+ fprintf(stderr, "[bam_merge_core] fail to open file %s\n", fn[i]);+ for (j = 0; j < i; ++j) bam_close(fp[j]);+ free(fp); free(heap);+ // FIXME: possible memory leak+ return -1;+ }+ hin = bam_header_read(fp[i]);+ if (i == 0) { // the first BAM+ hout = hin;+ } else { // validate multiple baf+ int min_n_targets = hout->n_targets;+ if (hin->n_targets < min_n_targets) min_n_targets = hin->n_targets;++ for (j = 0; j < min_n_targets; ++j)+ if (strcmp(hout->target_name[j], hin->target_name[j]) != 0) {+ fprintf(stderr, "[bam_merge_core] different target sequence name: '%s' != '%s' in file '%s'\n",+ hout->target_name[j], hin->target_name[j], fn[i]);+ return -1;+ }++ // If this input file has additional target reference sequences,+ // add them to the headers to be output+ if (hin->n_targets > hout->n_targets) {+ swap_header_targets(hout, hin);+ // FIXME Possibly we should also create @SQ text headers+ // for the newly added reference sequences+ }++ bam_header_destroy(hin);+ }+ }++ if (hheaders) {+ // If the text headers to be swapped in include any @SQ headers,+ // check that they are consistent with the existing binary list+ // of reference information.+ if (hheaders->n_targets > 0) {+ if (hout->n_targets != hheaders->n_targets) {+ fprintf(stderr, "[bam_merge_core] number of @SQ headers in '%s' differs from number of target sequences\n", headers);+ if (!reg) return -1;+ }+ for (j = 0; j < hout->n_targets; ++j)+ if (strcmp(hout->target_name[j], hheaders->target_name[j]) != 0) {+ fprintf(stderr, "[bam_merge_core] @SQ header '%s' in '%s' differs from target sequence\n", hheaders->target_name[j], headers);+ if (!reg) return -1;+ }+ }++ swap_header_text(hout, hheaders);+ bam_header_destroy(hheaders);+ }++ if (reg) {+ int tid, beg, end;+ if (bam_parse_region(hout, reg, &tid, &beg, &end) < 0) {+ fprintf(stderr, "[%s] Malformated region string or undefined reference name\n", __func__);+ return -1;+ }+ for (i = 0; i < n; ++i) {+ bam_index_t *idx;+ idx = bam_index_load(fn[i]);+ iter[i] = bam_iter_query(idx, tid, beg, end);+ bam_index_destroy(idx);+ }+ }++ for (i = 0; i < n; ++i) {+ heap1_t *h = heap + i;+ h->i = i;+ h->b = (bam1_t*)calloc(1, sizeof(bam1_t));+ if (bam_iter_read(fp[i], iter[i], h->b) >= 0) {+ h->pos = ((uint64_t)h->b->core.tid<<32) | (uint32_t)((int32_t)h->b->core.pos+1)<<1 | bam1_strand(h->b);+ h->idx = idx++;+ }+ else h->pos = HEAP_EMPTY;+ }+ if (flag & MERGE_UNCOMP) fpout = strcmp(out, "-")? bam_open(out, "wu") : bam_dopen(fileno(stdout), "wu");+ else if (flag & MERGE_LEVEL1) fpout = strcmp(out, "-")? bam_open(out, "w1") : bam_dopen(fileno(stdout), "w1");+ else fpout = strcmp(out, "-")? bam_open(out, "w") : bam_dopen(fileno(stdout), "w");+ if (fpout == 0) {+ fprintf(stderr, "[%s] fail to create the output file.\n", __func__);+ return -1;+ }+ bam_header_write(fpout, hout);+ bam_header_destroy(hout);++ ks_heapmake(heap, n, heap);+ while (heap->pos != HEAP_EMPTY) {+ bam1_t *b = heap->b;+ if (flag & MERGE_RG) {+ uint8_t *rg = bam_aux_get(b, "RG");+ if (rg) bam_aux_del(b, rg);+ bam_aux_append(b, "RG", 'Z', RG_len[heap->i] + 1, (uint8_t*)RG[heap->i]);+ }+ bam_write1_core(fpout, &b->core, b->data_len, b->data);+ if ((j = bam_iter_read(fp[heap->i], iter[heap->i], b)) >= 0) {+ heap->pos = ((uint64_t)b->core.tid<<32) | (uint32_t)((int)b->core.pos+1)<<1 | bam1_strand(b);+ heap->idx = idx++;+ } else if (j == -1) {+ heap->pos = HEAP_EMPTY;+ free(heap->b->data); free(heap->b);+ heap->b = 0;+ } else fprintf(stderr, "[bam_merge_core] '%s' is truncated. Continue anyway.\n", fn[heap->i]);+ ks_heapadjust(heap, 0, n, heap);+ }++ if (flag & MERGE_RG) {+ for (i = 0; i != n; ++i) free(RG[i]);+ free(RG); free(RG_len);+ }+ for (i = 0; i != n; ++i) {+ bam_iter_destroy(iter[i]);+ bam_close(fp[i]);+ }+ bam_close(fpout);+ free(fp); free(heap); free(iter);+ return 0;+}++int bam_merge(int argc, char *argv[])+{+ int c, is_by_qname = 0, flag = 0, ret = 0;+ char *fn_headers = NULL, *reg = 0;++ while ((c = getopt(argc, argv, "h:nru1R:f")) >= 0) {+ switch (c) {+ case 'r': flag |= MERGE_RG; break;+ case 'f': flag |= MERGE_FORCE; break;+ case 'h': fn_headers = strdup(optarg); break;+ case 'n': is_by_qname = 1; break;+ case '1': flag |= MERGE_LEVEL1; break;+ case 'u': flag |= MERGE_UNCOMP; break;+ case 'R': reg = strdup(optarg); break;+ }+ }+ if (optind + 2 >= argc) {+ fprintf(stderr, "\n");+ fprintf(stderr, "Usage: samtools merge [-nr] [-h inh.sam] <out.bam> <in1.bam> <in2.bam> [...]\n\n");+ fprintf(stderr, "Options: -n sort by read names\n");+ fprintf(stderr, " -r attach RG tag (inferred from file names)\n");+ fprintf(stderr, " -u uncompressed BAM output\n");+ fprintf(stderr, " -f overwrite the output BAM if exist\n");+ fprintf(stderr, " -1 compress level 1\n");+ fprintf(stderr, " -R STR merge file in the specified region STR [all]\n");+ fprintf(stderr, " -h FILE copy the header in FILE to <out.bam> [in1.bam]\n\n");+ fprintf(stderr, "Note: Samtools' merge does not reconstruct the @RG dictionary in the header. Users\n");+ fprintf(stderr, " must provide the correct header with -h, or uses Picard which properly maintains\n");+ fprintf(stderr, " the header dictionary in merging.\n\n");+ return 1;+ }+ if (!(flag & MERGE_FORCE) && strcmp(argv[optind], "-")) {+ FILE *fp = fopen(argv[optind], "rb");+ if (fp != NULL) {+ fclose(fp);+ fprintf(stderr, "[%s] File '%s' exists. Please apply '-f' to overwrite. Abort.\n", __func__, argv[optind]);+ return 1;+ }+ }+ if (bam_merge_core(is_by_qname, argv[optind], fn_headers, argc - optind - 1, argv + optind + 1, flag, reg) < 0) ret = 1;+ free(reg);+ free(fn_headers);+ return ret;+}++typedef bam1_t *bam1_p;++static inline int bam1_lt(const bam1_p a, const bam1_p b)+{+ if (g_is_by_qname) {+ int t = strnum_cmp(bam1_qname(a), bam1_qname(b));+ return (t < 0 || (t == 0 && (((uint64_t)a->core.tid<<32|(a->core.pos+1)) < ((uint64_t)b->core.tid<<32|(b->core.pos+1)))));+ } else return (((uint64_t)a->core.tid<<32|(a->core.pos+1)) < ((uint64_t)b->core.tid<<32|(b->core.pos+1)));+}+KSORT_INIT(sort, bam1_p, bam1_lt)++static void sort_blocks(int n, int k, bam1_p *buf, const char *prefix, const bam_header_t *h, int is_stdout)+{+ char *name, mode[3];+ int i;+ bamFile fp;+ ks_mergesort(sort, k, buf, 0);+ name = (char*)calloc(strlen(prefix) + 20, 1);+ if (n >= 0) {+ sprintf(name, "%s.%.4d.bam", prefix, n);+ strcpy(mode, "w1");+ } else {+ sprintf(name, "%s.bam", prefix);+ strcpy(mode, "w");+ }+ fp = is_stdout? bam_dopen(fileno(stdout), mode) : bam_open(name, mode);+ if (fp == 0) {+ fprintf(stderr, "[sort_blocks] fail to create file %s.\n", name);+ free(name);+ // FIXME: possible memory leak+ return;+ }+ free(name);+ bam_header_write(fp, h);+ for (i = 0; i < k; ++i)+ bam_write1_core(fp, &buf[i]->core, buf[i]->data_len, buf[i]->data);+ bam_close(fp);+}++/*!+ @abstract Sort an unsorted BAM file based on the chromosome order+ and the leftmost position of an alignment++ @param is_by_qname whether to sort by query name+ @param fn name of the file to be sorted+ @param prefix prefix of the output and the temporary files; upon+ sucessess, prefix.bam will be written.+ @param max_mem approxiate maximum memory (very inaccurate)++ @discussion It may create multiple temporary subalignment files+ and then merge them by calling bam_merge_core(). This function is+ NOT thread safe.+ */+void bam_sort_core_ext(int is_by_qname, const char *fn, const char *prefix, size_t max_mem, int is_stdout)+{+ int n, ret, k, i;+ size_t mem;+ bam_header_t *header;+ bamFile fp;+ bam1_t *b, **buf;++ g_is_by_qname = is_by_qname;+ n = k = 0; mem = 0;+ fp = strcmp(fn, "-")? bam_open(fn, "r") : bam_dopen(fileno(stdin), "r");+ if (fp == 0) {+ fprintf(stderr, "[bam_sort_core] fail to open file %s\n", fn);+ return;+ }+ header = bam_header_read(fp);+ buf = (bam1_t**)calloc(max_mem / BAM_CORE_SIZE, sizeof(bam1_t*));+ // write sub files+ for (;;) {+ if (buf[k] == 0) buf[k] = (bam1_t*)calloc(1, sizeof(bam1_t));+ b = buf[k];+ if ((ret = bam_read1(fp, b)) < 0) break;+ mem += ret;+ ++k;+ if (mem >= max_mem) {+ sort_blocks(n++, k, buf, prefix, header, 0);+ mem = 0; k = 0;+ }+ }+ if (ret != -1)+ fprintf(stderr, "[bam_sort_core] truncated file. Continue anyway.\n");+ if (n == 0) sort_blocks(-1, k, buf, prefix, header, is_stdout);+ else { // then merge+ char **fns, *fnout;+ fprintf(stderr, "[bam_sort_core] merging from %d files...\n", n+1);+ sort_blocks(n++, k, buf, prefix, header, 0);+ fnout = (char*)calloc(strlen(prefix) + 20, 1);+ if (is_stdout) sprintf(fnout, "-");+ else sprintf(fnout, "%s.bam", prefix);+ fns = (char**)calloc(n, sizeof(char*));+ for (i = 0; i < n; ++i) {+ fns[i] = (char*)calloc(strlen(prefix) + 20, 1);+ sprintf(fns[i], "%s.%.4d.bam", prefix, i);+ }+ bam_merge_core(is_by_qname, fnout, 0, n, fns, 0, 0);+ free(fnout);+ for (i = 0; i < n; ++i) {+ unlink(fns[i]);+ free(fns[i]);+ }+ free(fns);+ }+ for (k = 0; k < max_mem / BAM_CORE_SIZE; ++k) {+ if (buf[k]) {+ free(buf[k]->data);+ free(buf[k]);+ }+ }+ free(buf);+ bam_header_destroy(header);+ bam_close(fp);+}++void bam_sort_core(int is_by_qname, const char *fn, const char *prefix, size_t max_mem)+{+ bam_sort_core_ext(is_by_qname, fn, prefix, max_mem, 0);+}++int bam_sort(int argc, char *argv[])+{+ size_t max_mem = 500000000;+ int c, is_by_qname = 0, is_stdout = 0;+ while ((c = getopt(argc, argv, "nom:")) >= 0) {+ switch (c) {+ case 'o': is_stdout = 1; break;+ case 'n': is_by_qname = 1; break;+ case 'm': max_mem = atol(optarg); break;+ }+ }+ if (optind + 2 > argc) {+ fprintf(stderr, "Usage: samtools sort [-on] [-m <maxMem>] <in.bam> <out.prefix>\n");+ return 1;+ }+ bam_sort_core_ext(is_by_qname, argv[optind], argv[optind+1], max_mem, is_stdout);+ return 0;+}
+ samtools-0.1.18/bgzf.c view
@@ -0,0 +1,714 @@+/* The MIT License++ Copyright (c) 2008 Broad Institute / Massachusetts Institute of Technology++ 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.+*/++/*+ 2009-06-29 by lh3: cache recent uncompressed blocks.+ 2009-06-25 by lh3: optionally use my knetfile library to access file on a FTP.+ 2009-06-12 by lh3: support a mode string like "wu" where 'u' for uncompressed output */++#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <unistd.h>+#include <fcntl.h>+#include <sys/types.h>+#include <sys/stat.h>+#include "bgzf.h"++#include "khash.h"+typedef struct {+ int size;+ uint8_t *block;+ int64_t end_offset;+} cache_t;+KHASH_MAP_INIT_INT64(cache, cache_t)++#if defined(_WIN32) || defined(_MSC_VER)+#define ftello(fp) ftell(fp)+#define fseeko(fp, offset, whence) fseek(fp, offset, whence)+#else+extern off_t ftello(FILE *stream);+extern int fseeko(FILE *stream, off_t offset, int whence);+#endif++typedef int8_t bgzf_byte_t;++static const int DEFAULT_BLOCK_SIZE = 64 * 1024;+static const int MAX_BLOCK_SIZE = 64 * 1024;++static const int BLOCK_HEADER_LENGTH = 18;+static const int BLOCK_FOOTER_LENGTH = 8;++static const int GZIP_ID1 = 31;+static const int GZIP_ID2 = 139;+static const int CM_DEFLATE = 8;+static const int FLG_FEXTRA = 4;+static const int OS_UNKNOWN = 255;+static const int BGZF_ID1 = 66; // 'B'+static const int BGZF_ID2 = 67; // 'C'+static const int BGZF_LEN = 2;+static const int BGZF_XLEN = 6; // BGZF_LEN+4++static const int GZIP_WINDOW_BITS = -15; // no zlib header+static const int Z_DEFAULT_MEM_LEVEL = 8;+++inline+void+packInt16(uint8_t* buffer, uint16_t value)+{+ buffer[0] = value;+ buffer[1] = value >> 8;+}++inline+int+unpackInt16(const uint8_t* buffer)+{+ return (buffer[0] | (buffer[1] << 8));+}++inline+void+packInt32(uint8_t* buffer, uint32_t value)+{+ buffer[0] = value;+ buffer[1] = value >> 8;+ buffer[2] = value >> 16;+ buffer[3] = value >> 24;+}++static inline+int+bgzf_min(int x, int y)+{+ return (x < y) ? x : y;+}++static+void+report_error(BGZF* fp, const char* message) {+ fp->error = message;+}++int bgzf_check_bgzf(const char *fn)+{+ BGZF *fp;+ uint8_t buf[10],magic[10]="\037\213\010\4\0\0\0\0\0\377";+ int n;++ if ((fp = bgzf_open(fn, "r")) == 0) + {+ fprintf(stderr, "[bgzf_check_bgzf] failed to open the file: %s\n",fn);+ return -1;+ }++#ifdef _USE_KNETFILE+ n = knet_read(fp->x.fpr, buf, 10);+#else+ n = fread(buf, 1, 10, fp->file);+#endif+ bgzf_close(fp);++ if ( n!=10 ) + return -1;++ if ( !memcmp(magic, buf, 10) ) return 1;+ return 0;+}++static BGZF *bgzf_read_init()+{+ BGZF *fp;+ fp = calloc(1, sizeof(BGZF));+ fp->uncompressed_block_size = MAX_BLOCK_SIZE;+ fp->uncompressed_block = malloc(MAX_BLOCK_SIZE);+ fp->compressed_block_size = MAX_BLOCK_SIZE;+ fp->compressed_block = malloc(MAX_BLOCK_SIZE);+ fp->cache_size = 0;+ fp->cache = kh_init(cache);+ return fp;+}++static+BGZF*+open_read(int fd)+{+#ifdef _USE_KNETFILE+ knetFile *file = knet_dopen(fd, "r");+#else+ FILE* file = fdopen(fd, "r");+#endif+ BGZF* fp;+ if (file == 0) return 0;+ fp = bgzf_read_init();+ fp->file_descriptor = fd;+ fp->open_mode = 'r';+#ifdef _USE_KNETFILE+ fp->x.fpr = file;+#else+ fp->file = file;+#endif+ return fp;+}++static+BGZF*+open_write(int fd, int compress_level) // compress_level==-1 for the default level+{+ FILE* file = fdopen(fd, "w");+ BGZF* fp;+ if (file == 0) return 0;+ fp = malloc(sizeof(BGZF));+ fp->file_descriptor = fd;+ fp->open_mode = 'w';+ fp->owned_file = 0;+ fp->compress_level = compress_level < 0? Z_DEFAULT_COMPRESSION : compress_level; // Z_DEFAULT_COMPRESSION==-1+ if (fp->compress_level > 9) fp->compress_level = Z_DEFAULT_COMPRESSION;+#ifdef _USE_KNETFILE+ fp->x.fpw = file;+#else+ fp->file = file;+#endif+ fp->uncompressed_block_size = DEFAULT_BLOCK_SIZE;+ fp->uncompressed_block = NULL;+ fp->compressed_block_size = MAX_BLOCK_SIZE;+ fp->compressed_block = malloc(MAX_BLOCK_SIZE);+ fp->block_address = 0;+ fp->block_offset = 0;+ fp->block_length = 0;+ fp->error = NULL;+ return fp;+}++BGZF*+bgzf_open(const char* __restrict path, const char* __restrict mode)+{+ BGZF* fp = NULL;+ if (strchr(mode, 'r') || strchr(mode, 'R')) { /* The reading mode is preferred. */+#ifdef _USE_KNETFILE+ knetFile *file = knet_open(path, mode);+ if (file == 0) return 0;+ fp = bgzf_read_init();+ fp->file_descriptor = -1;+ fp->open_mode = 'r';+ fp->x.fpr = file;+#else+ int fd, oflag = O_RDONLY;+#ifdef _WIN32+ oflag |= O_BINARY;+#endif+ fd = open(path, oflag);+ if (fd == -1) return 0;+ fp = open_read(fd);+#endif+ } else if (strchr(mode, 'w') || strchr(mode, 'W')) {+ int fd, compress_level = -1, oflag = O_WRONLY | O_CREAT | O_TRUNC;+#ifdef _WIN32+ oflag |= O_BINARY;+#endif+ fd = open(path, oflag, 0666);+ if (fd == -1) return 0;+ { // set compress_level+ int i;+ for (i = 0; mode[i]; ++i)+ if (mode[i] >= '0' && mode[i] <= '9') break;+ if (mode[i]) compress_level = (int)mode[i] - '0';+ if (strchr(mode, 'u')) compress_level = 0;+ }+ fp = open_write(fd, compress_level);+ }+ if (fp != NULL) fp->owned_file = 1;+ return fp;+}++BGZF*+bgzf_fdopen(int fd, const char * __restrict mode)+{+ if (fd == -1) return 0;+ if (mode[0] == 'r' || mode[0] == 'R') {+ return open_read(fd);+ } else if (mode[0] == 'w' || mode[0] == 'W') {+ int i, compress_level = -1;+ for (i = 0; mode[i]; ++i)+ if (mode[i] >= '0' && mode[i] <= '9') break;+ if (mode[i]) compress_level = (int)mode[i] - '0';+ if (strchr(mode, 'u')) compress_level = 0;+ return open_write(fd, compress_level);+ } else {+ return NULL;+ }+}++static+int+deflate_block(BGZF* fp, int block_length)+{+ // Deflate the block in fp->uncompressed_block into fp->compressed_block.+ // Also adds an extra field that stores the compressed block length.++ bgzf_byte_t* buffer = fp->compressed_block;+ int buffer_size = fp->compressed_block_size;++ // Init gzip header+ buffer[0] = GZIP_ID1;+ buffer[1] = GZIP_ID2;+ buffer[2] = CM_DEFLATE;+ buffer[3] = FLG_FEXTRA;+ buffer[4] = 0; // mtime+ buffer[5] = 0;+ buffer[6] = 0;+ buffer[7] = 0;+ buffer[8] = 0;+ buffer[9] = OS_UNKNOWN;+ buffer[10] = BGZF_XLEN;+ buffer[11] = 0;+ buffer[12] = BGZF_ID1;+ buffer[13] = BGZF_ID2;+ buffer[14] = BGZF_LEN;+ buffer[15] = 0;+ buffer[16] = 0; // placeholder for block length+ buffer[17] = 0;++ // loop to retry for blocks that do not compress enough+ int input_length = block_length;+ int compressed_length = 0;+ while (1) {+ z_stream zs;+ zs.zalloc = NULL;+ zs.zfree = NULL;+ zs.next_in = fp->uncompressed_block;+ zs.avail_in = input_length;+ zs.next_out = (void*)&buffer[BLOCK_HEADER_LENGTH];+ zs.avail_out = buffer_size - BLOCK_HEADER_LENGTH - BLOCK_FOOTER_LENGTH;++ int status = deflateInit2(&zs, fp->compress_level, Z_DEFLATED,+ GZIP_WINDOW_BITS, Z_DEFAULT_MEM_LEVEL, Z_DEFAULT_STRATEGY);+ if (status != Z_OK) {+ report_error(fp, "deflate init failed");+ return -1;+ }+ status = deflate(&zs, Z_FINISH);+ if (status != Z_STREAM_END) {+ deflateEnd(&zs);+ if (status == Z_OK) {+ // Not enough space in buffer.+ // Can happen in the rare case the input doesn't compress enough.+ // Reduce the amount of input until it fits.+ input_length -= 1024;+ if (input_length <= 0) {+ // should never happen+ report_error(fp, "input reduction failed");+ return -1;+ }+ continue;+ }+ report_error(fp, "deflate failed");+ return -1;+ }+ status = deflateEnd(&zs);+ if (status != Z_OK) {+ report_error(fp, "deflate end failed");+ return -1;+ }+ compressed_length = zs.total_out;+ compressed_length += BLOCK_HEADER_LENGTH + BLOCK_FOOTER_LENGTH;+ if (compressed_length > MAX_BLOCK_SIZE) {+ // should never happen+ report_error(fp, "deflate overflow");+ return -1;+ }+ break;+ }++ packInt16((uint8_t*)&buffer[16], compressed_length-1);+ uint32_t crc = crc32(0L, NULL, 0L);+ crc = crc32(crc, fp->uncompressed_block, input_length);+ packInt32((uint8_t*)&buffer[compressed_length-8], crc);+ packInt32((uint8_t*)&buffer[compressed_length-4], input_length);++ int remaining = block_length - input_length;+ if (remaining > 0) {+ if (remaining > input_length) {+ // should never happen (check so we can use memcpy)+ report_error(fp, "remainder too large");+ return -1;+ }+ memcpy(fp->uncompressed_block,+ fp->uncompressed_block + input_length,+ remaining);+ }+ fp->block_offset = remaining;+ return compressed_length;+}++static+int+inflate_block(BGZF* fp, int block_length)+{+ // Inflate the block in fp->compressed_block into fp->uncompressed_block++ z_stream zs;+ int status;+ zs.zalloc = NULL;+ zs.zfree = NULL;+ zs.next_in = fp->compressed_block + 18;+ zs.avail_in = block_length - 16;+ zs.next_out = fp->uncompressed_block;+ zs.avail_out = fp->uncompressed_block_size;++ status = inflateInit2(&zs, GZIP_WINDOW_BITS);+ if (status != Z_OK) {+ report_error(fp, "inflate init failed");+ return -1;+ }+ status = inflate(&zs, Z_FINISH);+ if (status != Z_STREAM_END) {+ inflateEnd(&zs);+ report_error(fp, "inflate failed");+ return -1;+ }+ status = inflateEnd(&zs);+ if (status != Z_OK) {+ report_error(fp, "inflate failed");+ return -1;+ }+ return zs.total_out;+}++static+int+check_header(const bgzf_byte_t* header)+{+ return (header[0] == GZIP_ID1 &&+ header[1] == (bgzf_byte_t) GZIP_ID2 &&+ header[2] == Z_DEFLATED &&+ (header[3] & FLG_FEXTRA) != 0 &&+ unpackInt16((uint8_t*)&header[10]) == BGZF_XLEN &&+ header[12] == BGZF_ID1 &&+ header[13] == BGZF_ID2 &&+ unpackInt16((uint8_t*)&header[14]) == BGZF_LEN);+}++static void free_cache(BGZF *fp)+{+ khint_t k;+ khash_t(cache) *h = (khash_t(cache)*)fp->cache;+ if (fp->open_mode != 'r') return;+ for (k = kh_begin(h); k < kh_end(h); ++k)+ if (kh_exist(h, k)) free(kh_val(h, k).block);+ kh_destroy(cache, h);+}++static int load_block_from_cache(BGZF *fp, int64_t block_address)+{+ khint_t k;+ cache_t *p;+ khash_t(cache) *h = (khash_t(cache)*)fp->cache;+ k = kh_get(cache, h, block_address);+ if (k == kh_end(h)) return 0;+ p = &kh_val(h, k);+ if (fp->block_length != 0) fp->block_offset = 0;+ fp->block_address = block_address;+ fp->block_length = p->size;+ memcpy(fp->uncompressed_block, p->block, MAX_BLOCK_SIZE);+#ifdef _USE_KNETFILE+ knet_seek(fp->x.fpr, p->end_offset, SEEK_SET);+#else+ fseeko(fp->file, p->end_offset, SEEK_SET);+#endif+ return p->size;+}++static void cache_block(BGZF *fp, int size)+{+ int ret;+ khint_t k;+ cache_t *p;+ khash_t(cache) *h = (khash_t(cache)*)fp->cache;+ if (MAX_BLOCK_SIZE >= fp->cache_size) return;+ if ((kh_size(h) + 1) * MAX_BLOCK_SIZE > fp->cache_size) {+ /* A better way would be to remove the oldest block in the+ * cache, but here we remove a random one for simplicity. This+ * should not have a big impact on performance. */+ for (k = kh_begin(h); k < kh_end(h); ++k)+ if (kh_exist(h, k)) break;+ if (k < kh_end(h)) {+ free(kh_val(h, k).block);+ kh_del(cache, h, k);+ }+ }+ k = kh_put(cache, h, fp->block_address, &ret);+ if (ret == 0) return; // if this happens, a bug!+ p = &kh_val(h, k);+ p->size = fp->block_length;+ p->end_offset = fp->block_address + size;+ p->block = malloc(MAX_BLOCK_SIZE);+ memcpy(kh_val(h, k).block, fp->uncompressed_block, MAX_BLOCK_SIZE);+}++int+bgzf_read_block(BGZF* fp)+{+ bgzf_byte_t header[BLOCK_HEADER_LENGTH];+ int count, size = 0, block_length, remaining;+#ifdef _USE_KNETFILE+ int64_t block_address = knet_tell(fp->x.fpr);+ if (load_block_from_cache(fp, block_address)) return 0;+ count = knet_read(fp->x.fpr, header, sizeof(header));+#else+ int64_t block_address = ftello(fp->file);+ if (load_block_from_cache(fp, block_address)) return 0;+ count = fread(header, 1, sizeof(header), fp->file);+#endif+ if (count == 0) {+ fp->block_length = 0;+ return 0;+ }+ size = count;+ if (count != sizeof(header)) {+ report_error(fp, "read failed");+ return -1;+ }+ if (!check_header(header)) {+ report_error(fp, "invalid block header");+ return -1;+ }+ block_length = unpackInt16((uint8_t*)&header[16]) + 1;+ bgzf_byte_t* compressed_block = (bgzf_byte_t*) fp->compressed_block;+ memcpy(compressed_block, header, BLOCK_HEADER_LENGTH);+ remaining = block_length - BLOCK_HEADER_LENGTH;+#ifdef _USE_KNETFILE+ count = knet_read(fp->x.fpr, &compressed_block[BLOCK_HEADER_LENGTH], remaining);+#else+ count = fread(&compressed_block[BLOCK_HEADER_LENGTH], 1, remaining, fp->file);+#endif+ if (count != remaining) {+ report_error(fp, "read failed");+ return -1;+ }+ size += count;+ count = inflate_block(fp, block_length);+ if (count < 0) return -1;+ if (fp->block_length != 0) {+ // Do not reset offset if this read follows a seek.+ fp->block_offset = 0;+ }+ fp->block_address = block_address;+ fp->block_length = count;+ cache_block(fp, size);+ return 0;+}++int+bgzf_read(BGZF* fp, void* data, int length)+{+ if (length <= 0) {+ return 0;+ }+ if (fp->open_mode != 'r') {+ report_error(fp, "file not open for reading");+ return -1;+ }++ int bytes_read = 0;+ bgzf_byte_t* output = data;+ while (bytes_read < length) {+ int copy_length, available = fp->block_length - fp->block_offset;+ bgzf_byte_t *buffer;+ if (available <= 0) {+ if (bgzf_read_block(fp) != 0) {+ return -1;+ }+ available = fp->block_length - fp->block_offset;+ if (available <= 0) {+ break;+ }+ }+ copy_length = bgzf_min(length-bytes_read, available);+ buffer = fp->uncompressed_block;+ memcpy(output, buffer + fp->block_offset, copy_length);+ fp->block_offset += copy_length;+ output += copy_length;+ bytes_read += copy_length;+ }+ if (fp->block_offset == fp->block_length) {+#ifdef _USE_KNETFILE+ fp->block_address = knet_tell(fp->x.fpr);+#else+ fp->block_address = ftello(fp->file);+#endif+ fp->block_offset = 0;+ fp->block_length = 0;+ }+ return bytes_read;+}++int bgzf_flush(BGZF* fp)+{+ while (fp->block_offset > 0) {+ int count, block_length;+ block_length = deflate_block(fp, fp->block_offset);+ if (block_length < 0) return -1;+#ifdef _USE_KNETFILE+ count = fwrite(fp->compressed_block, 1, block_length, fp->x.fpw);+#else+ count = fwrite(fp->compressed_block, 1, block_length, fp->file);+#endif+ if (count != block_length) {+ report_error(fp, "write failed");+ return -1;+ }+ fp->block_address += block_length;+ }+ return 0;+}++int bgzf_flush_try(BGZF *fp, int size)+{+ if (fp->block_offset + size > fp->uncompressed_block_size)+ return bgzf_flush(fp);+ return -1;+}++int bgzf_write(BGZF* fp, const void* data, int length)+{+ const bgzf_byte_t *input = data;+ int block_length, bytes_written;+ if (fp->open_mode != 'w') {+ report_error(fp, "file not open for writing");+ return -1;+ }++ if (fp->uncompressed_block == NULL)+ fp->uncompressed_block = malloc(fp->uncompressed_block_size);++ input = data;+ block_length = fp->uncompressed_block_size;+ bytes_written = 0;+ while (bytes_written < length) {+ int copy_length = bgzf_min(block_length - fp->block_offset, length - bytes_written);+ bgzf_byte_t* buffer = fp->uncompressed_block;+ memcpy(buffer + fp->block_offset, input, copy_length);+ fp->block_offset += copy_length;+ input += copy_length;+ bytes_written += copy_length;+ if (fp->block_offset == block_length) {+ if (bgzf_flush(fp) != 0) {+ break;+ }+ }+ }+ return bytes_written;+}++int bgzf_close(BGZF* fp)+{+ if (fp->open_mode == 'w') {+ if (bgzf_flush(fp) != 0) return -1;+ { // add an empty block+ int count, block_length = deflate_block(fp, 0);+#ifdef _USE_KNETFILE+ count = fwrite(fp->compressed_block, 1, block_length, fp->x.fpw);+#else+ count = fwrite(fp->compressed_block, 1, block_length, fp->file);+#endif+ }+#ifdef _USE_KNETFILE+ if (fflush(fp->x.fpw) != 0) {+#else+ if (fflush(fp->file) != 0) {+#endif+ report_error(fp, "flush failed");+ return -1;+ }+ }+ if (fp->owned_file) {+#ifdef _USE_KNETFILE+ int ret;+ if (fp->open_mode == 'w') ret = fclose(fp->x.fpw);+ else ret = knet_close(fp->x.fpr);+ if (ret != 0) return -1;+#else+ if (fclose(fp->file) != 0) return -1;+#endif+ }+ free(fp->uncompressed_block);+ free(fp->compressed_block);+ free_cache(fp);+ free(fp);+ return 0;+}++void bgzf_set_cache_size(BGZF *fp, int cache_size)+{+ if (fp) fp->cache_size = cache_size;+}++int bgzf_check_EOF(BGZF *fp)+{+ static uint8_t magic[28] = "\037\213\010\4\0\0\0\0\0\377\6\0\102\103\2\0\033\0\3\0\0\0\0\0\0\0\0\0";+ uint8_t buf[28];+ off_t offset;+#ifdef _USE_KNETFILE+ offset = knet_tell(fp->x.fpr);+ if (knet_seek(fp->x.fpr, -28, SEEK_END) != 0) return -1;+ knet_read(fp->x.fpr, buf, 28);+ knet_seek(fp->x.fpr, offset, SEEK_SET);+#else+ offset = ftello(fp->file);+ if (fseeko(fp->file, -28, SEEK_END) != 0) return -1;+ fread(buf, 1, 28, fp->file);+ fseeko(fp->file, offset, SEEK_SET);+#endif+ return (memcmp(magic, buf, 28) == 0)? 1 : 0;+}++int64_t bgzf_seek(BGZF* fp, int64_t pos, int where)+{+ int block_offset;+ int64_t block_address;++ if (fp->open_mode != 'r') {+ report_error(fp, "file not open for read");+ return -1;+ }+ if (where != SEEK_SET) {+ report_error(fp, "unimplemented seek option");+ return -1;+ }+ block_offset = pos & 0xFFFF;+ block_address = (pos >> 16) & 0xFFFFFFFFFFFFLL;+#ifdef _USE_KNETFILE+ if (knet_seek(fp->x.fpr, block_address, SEEK_SET) != 0) {+#else+ if (fseeko(fp->file, block_address, SEEK_SET) != 0) {+#endif+ report_error(fp, "seek failed");+ return -1;+ }+ fp->block_length = 0; // indicates current block is not loaded+ fp->block_address = block_address;+ fp->block_offset = block_offset;+ return 0;+}
+ samtools-0.1.18/bgzf.h view
@@ -0,0 +1,157 @@+/* The MIT License++ Copyright (c) 2008 Broad Institute / Massachusetts Institute of Technology++ 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.+*/++#ifndef __BGZF_H+#define __BGZF_H++#include <stdint.h>+#include <stdio.h>+#include <zlib.h>+#ifdef _USE_KNETFILE+#include "knetfile.h"+#endif++//typedef int8_t bool;++typedef struct {+ int file_descriptor;+ char open_mode; // 'r' or 'w'+ int16_t owned_file, compress_level;+#ifdef _USE_KNETFILE+ union {+ knetFile *fpr;+ FILE *fpw;+ } x;+#else+ FILE* file;+#endif+ int uncompressed_block_size;+ int compressed_block_size;+ void* uncompressed_block;+ void* compressed_block;+ int64_t block_address;+ int block_length;+ int block_offset;+ int cache_size;+ const char* error;+ void *cache; // a pointer to a hash table+} BGZF;++#ifdef __cplusplus+extern "C" {+#endif++/*+ * Open an existing file descriptor for reading or writing.+ * Mode must be either "r" or "w".+ * A subsequent bgzf_close will not close the file descriptor.+ * Returns null on error.+ */+BGZF* bgzf_fdopen(int fd, const char* __restrict mode);++/*+ * Open the specified file for reading or writing.+ * Mode must be either "r" or "w".+ * Returns null on error.+ */+BGZF* bgzf_open(const char* path, const char* __restrict mode);++/*+ * Close the BGZ file and free all associated resources.+ * Does not close the underlying file descriptor if created with bgzf_fdopen.+ * Returns zero on success, -1 on error.+ */+int bgzf_close(BGZF* fp);++/*+ * Read up to length bytes from the file storing into data.+ * Returns the number of bytes actually read.+ * Returns zero on end of file.+ * Returns -1 on error.+ */+int bgzf_read(BGZF* fp, void* data, int length);++/*+ * Write length bytes from data to the file.+ * Returns the number of bytes written.+ * Returns -1 on error.+ */+int bgzf_write(BGZF* fp, const void* data, int length);++/*+ * Return a virtual file pointer to the current location in the file.+ * No interpetation of the value should be made, other than a subsequent+ * call to bgzf_seek can be used to position the file at the same point.+ * Return value is non-negative on success.+ * Returns -1 on error.+ */+#define bgzf_tell(fp) ((fp->block_address << 16) | (fp->block_offset & 0xFFFF))++/*+ * Set the file to read from the location specified by pos, which must+ * be a value previously returned by bgzf_tell for this file (but not+ * necessarily one returned by this file handle).+ * The where argument must be SEEK_SET.+ * Seeking on a file opened for write is not supported.+ * Returns zero on success, -1 on error.+ */+int64_t bgzf_seek(BGZF* fp, int64_t pos, int where);++/*+ * Set the cache size. Zero to disable. By default, caching is+ * disabled. The recommended cache size for frequent random access is+ * about 8M bytes.+ */+void bgzf_set_cache_size(BGZF *fp, int cache_size);++int bgzf_check_EOF(BGZF *fp);+int bgzf_read_block(BGZF* fp);+int bgzf_flush(BGZF* fp);+int bgzf_flush_try(BGZF *fp, int size);+int bgzf_check_bgzf(const char *fn);++#ifdef __cplusplus+}+#endif++static inline int bgzf_getc(BGZF *fp)+{+ int c;+ if (fp->block_offset >= fp->block_length) {+ if (bgzf_read_block(fp) != 0) return -2; /* error */+ if (fp->block_length == 0) return -1; /* end-of-file */+ }+ c = ((unsigned char*)fp->uncompressed_block)[fp->block_offset++];+ if (fp->block_offset == fp->block_length) {+#ifdef _USE_KNETFILE+ fp->block_address = knet_tell(fp->x.fpr);+#else+ fp->block_address = ftello(fp->file);+#endif+ fp->block_offset = 0;+ fp->block_length = 0;+ }+ return c;+}++#endif
+ samtools-0.1.18/errmod.c view
@@ -0,0 +1,130 @@+#include <math.h>+#include "errmod.h"+#include "ksort.h"+KSORT_INIT_GENERIC(uint16_t)++typedef struct __errmod_coef_t {+ double *fk, *beta, *lhet;+} errmod_coef_t;++typedef struct {+ double fsum[16], bsum[16];+ uint32_t c[16];+} call_aux_t;++static errmod_coef_t *cal_coef(double depcorr, double eta)+{+ int k, n, q;+ long double sum, sum1;+ double *lC;+ errmod_coef_t *ec;++ ec = calloc(1, sizeof(errmod_coef_t));+ // initialize ->fk+ ec->fk = (double*)calloc(256, sizeof(double));+ ec->fk[0] = 1.0;+ for (n = 1; n != 256; ++n)+ ec->fk[n] = pow(1. - depcorr, n) * (1.0 - eta) + eta;+ // initialize ->coef+ ec->beta = (double*)calloc(256 * 256 * 64, sizeof(double));+ lC = (double*)calloc(256 * 256, sizeof(double));+ for (n = 1; n != 256; ++n) {+ double lgn = lgamma(n+1);+ for (k = 1; k <= n; ++k)+ lC[n<<8|k] = lgn - lgamma(k+1) - lgamma(n-k+1);+ }+ for (q = 1; q != 64; ++q) {+ double e = pow(10.0, -q/10.0);+ double le = log(e);+ double le1 = log(1.0 - e);+ for (n = 1; n <= 255; ++n) {+ double *beta = ec->beta + (q<<16|n<<8);+ sum1 = sum = 0.0;+ for (k = n; k >= 0; --k, sum1 = sum) {+ sum = sum1 + expl(lC[n<<8|k] + k*le + (n-k)*le1);+ beta[k] = -10. / M_LN10 * logl(sum1 / sum);+ }+ }+ }+ // initialize ->lhet+ ec->lhet = (double*)calloc(256 * 256, sizeof(double));+ for (n = 0; n < 256; ++n)+ for (k = 0; k < 256; ++k)+ ec->lhet[n<<8|k] = lC[n<<8|k] - M_LN2 * n;+ free(lC);+ return ec;+}++errmod_t *errmod_init(float depcorr)+{+ errmod_t *em;+ em = (errmod_t*)calloc(1, sizeof(errmod_t));+ em->depcorr = depcorr;+ em->coef = cal_coef(depcorr, 0.03);+ return em;+}++void errmod_destroy(errmod_t *em)+{+ if (em == 0) return;+ free(em->coef->lhet); free(em->coef->fk); free(em->coef->beta);+ free(em->coef); free(em);+}+// qual:6, strand:1, base:4+int errmod_cal(const errmod_t *em, int n, int m, uint16_t *bases, float *q)+{+ call_aux_t aux;+ int i, j, k, w[32];++ if (m > m) return -1;+ memset(q, 0, m * m * sizeof(float));+ if (n == 0) return 0;+ // calculate aux.esum and aux.fsum+ if (n > 255) { // then sample 255 bases+ ks_shuffle(uint16_t, n, bases);+ n = 255;+ }+ ks_introsort(uint16_t, n, bases);+ memset(w, 0, 32 * sizeof(int));+ memset(&aux, 0, sizeof(call_aux_t));+ for (j = n - 1; j >= 0; --j) { // calculate esum and fsum+ uint16_t b = bases[j];+ int q = b>>5 < 4? 4 : b>>5;+ if (q > 63) q = 63;+ k = b&0x1f;+ aux.fsum[k&0xf] += em->coef->fk[w[k]];+ aux.bsum[k&0xf] += em->coef->fk[w[k]] * em->coef->beta[q<<16|n<<8|aux.c[k&0xf]];+ ++aux.c[k&0xf];+ ++w[k];+ }+ // generate likelihood+ for (j = 0; j != m; ++j) {+ float tmp1, tmp3;+ int tmp2, bar_e;+ // homozygous+ for (k = 0, tmp1 = tmp3 = 0.0, tmp2 = 0; k != m; ++k) {+ if (k == j) continue;+ tmp1 += aux.bsum[k]; tmp2 += aux.c[k]; tmp3 += aux.fsum[k];+ }+ if (tmp2) {+ bar_e = (int)(tmp1 / tmp3 + 0.499);+ if (bar_e > 63) bar_e = 63;+ q[j*m+j] = tmp1;+ }+ // heterozygous+ for (k = j + 1; k < m; ++k) {+ int cjk = aux.c[j] + aux.c[k];+ for (i = 0, tmp2 = 0, tmp1 = tmp3 = 0.0; i < m; ++i) {+ if (i == j || i == k) continue;+ tmp1 += aux.bsum[i]; tmp2 += aux.c[i]; tmp3 += aux.fsum[i];+ }+ if (tmp2) {+ bar_e = (int)(tmp1 / tmp3 + 0.499);+ if (bar_e > 63) bar_e = 63;+ q[j*m+k] = q[k*m+j] = -4.343 * em->coef->lhet[cjk<<8|aux.c[k]] + tmp1;+ } else q[j*m+k] = q[k*m+j] = -4.343 * em->coef->lhet[cjk<<8|aux.c[k]]; // all the bases are either j or k+ }+ for (k = 0; k != m; ++k) if (q[j*m+k] < 0.0) q[j*m+k] = 0.0;+ }+ return 0;+}
+ samtools-0.1.18/errmod.h view
@@ -0,0 +1,24 @@+#ifndef ERRMOD_H+#define ERRMOD_H++#include <stdint.h>++struct __errmod_coef_t;++typedef struct {+ double depcorr;+ struct __errmod_coef_t *coef;+} errmod_t;++errmod_t *errmod_init(float depcorr);+void errmod_destroy(errmod_t *em);++/*+ n: number of bases+ m: maximum base+ bases[i]: qual:6, strand:1, base:4+ q[i*m+j]: phred-scaled likelihood of (i,j)+ */+int errmod_cal(const errmod_t *em, int n, int m, uint16_t *bases, float *q);++#endif
+ samtools-0.1.18/faidx.c view
@@ -0,0 +1,432 @@+#include <ctype.h>+#include <string.h>+#include <stdlib.h>+#include <stdio.h>+#include <stdint.h>+#include "faidx.h"+#include "khash.h"++typedef struct {+ int32_t line_len, line_blen;+ int64_t len;+ uint64_t offset;+} faidx1_t;+KHASH_MAP_INIT_STR(s, faidx1_t)++#ifndef _NO_RAZF+#include "razf.h"+#else+#ifdef _WIN32+#define ftello(fp) ftell(fp)+#define fseeko(fp, offset, whence) fseek(fp, offset, whence)+#else+extern off_t ftello(FILE *stream);+extern int fseeko(FILE *stream, off_t offset, int whence);+#endif+#define RAZF FILE+#define razf_read(fp, buf, size) fread(buf, 1, size, fp)+#define razf_open(fn, mode) fopen(fn, mode)+#define razf_close(fp) fclose(fp)+#define razf_seek(fp, offset, whence) fseeko(fp, offset, whence)+#define razf_tell(fp) ftello(fp)+#endif+#ifdef _USE_KNETFILE+#include "knetfile.h"+#endif++struct __faidx_t {+ RAZF *rz;+ int n, m;+ char **name;+ khash_t(s) *hash;+};++#ifndef kroundup32+#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))+#endif++static inline void fai_insert_index(faidx_t *idx, const char *name, int len, int line_len, int line_blen, uint64_t offset)+{+ khint_t k;+ int ret;+ faidx1_t t;+ if (idx->n == idx->m) {+ idx->m = idx->m? idx->m<<1 : 16;+ idx->name = (char**)realloc(idx->name, sizeof(void*) * idx->m);+ }+ idx->name[idx->n] = strdup(name);+ k = kh_put(s, idx->hash, idx->name[idx->n], &ret);+ t.len = len; t.line_len = line_len; t.line_blen = line_blen; t.offset = offset;+ kh_value(idx->hash, k) = t;+ ++idx->n;+}++faidx_t *fai_build_core(RAZF *rz)+{+ char c, *name;+ int l_name, m_name, ret;+ int line_len, line_blen, state;+ int l1, l2;+ faidx_t *idx;+ uint64_t offset;+ int64_t len;++ idx = (faidx_t*)calloc(1, sizeof(faidx_t));+ idx->hash = kh_init(s);+ name = 0; l_name = m_name = 0;+ len = line_len = line_blen = -1; state = 0; l1 = l2 = -1; offset = 0;+ while (razf_read(rz, &c, 1)) {+ if (c == '\n') { // an empty line+ if (state == 1) {+ offset = razf_tell(rz);+ continue;+ } else if ((state == 0 && len < 0) || state == 2) continue;+ }+ if (c == '>') { // fasta header+ if (len >= 0)+ fai_insert_index(idx, name, len, line_len, line_blen, offset);+ l_name = 0;+ while ((ret = razf_read(rz, &c, 1)) != 0 && !isspace(c)) {+ if (m_name < l_name + 2) {+ m_name = l_name + 2;+ kroundup32(m_name);+ name = (char*)realloc(name, m_name);+ }+ name[l_name++] = c;+ }+ name[l_name] = '\0';+ if (ret == 0) {+ fprintf(stderr, "[fai_build_core] the last entry has no sequence\n");+ free(name); fai_destroy(idx);+ return 0;+ }+ if (c != '\n') while (razf_read(rz, &c, 1) && c != '\n');+ state = 1; len = 0;+ offset = razf_tell(rz);+ } else {+ if (state == 3) {+ fprintf(stderr, "[fai_build_core] inlined empty line is not allowed in sequence '%s'.\n", name);+ free(name); fai_destroy(idx);+ return 0;+ }+ if (state == 2) state = 3;+ l1 = l2 = 0;+ do {+ ++l1;+ if (isgraph(c)) ++l2;+ } while ((ret = razf_read(rz, &c, 1)) && c != '\n');+ if (state == 3 && l2) {+ fprintf(stderr, "[fai_build_core] different line length in sequence '%s'.\n", name);+ free(name); fai_destroy(idx);+ return 0;+ }+ ++l1; len += l2;+ if (state == 1) line_len = l1, line_blen = l2, state = 0;+ else if (state == 0) {+ if (l1 != line_len || l2 != line_blen) state = 2;+ }+ }+ }+ fai_insert_index(idx, name, len, line_len, line_blen, offset);+ free(name);+ return idx;+}++void fai_save(const faidx_t *fai, FILE *fp)+{+ khint_t k;+ int i;+ for (i = 0; i < fai->n; ++i) {+ faidx1_t x;+ k = kh_get(s, fai->hash, fai->name[i]);+ x = kh_value(fai->hash, k);+#ifdef _WIN32+ fprintf(fp, "%s\t%d\t%ld\t%d\t%d\n", fai->name[i], (int)x.len, (long)x.offset, (int)x.line_blen, (int)x.line_len);+#else+ fprintf(fp, "%s\t%d\t%lld\t%d\t%d\n", fai->name[i], (int)x.len, (long long)x.offset, (int)x.line_blen, (int)x.line_len);+#endif+ }+}++faidx_t *fai_read(FILE *fp)+{+ faidx_t *fai;+ char *buf, *p;+ int len, line_len, line_blen;+#ifdef _WIN32+ long offset;+#else+ long long offset;+#endif+ fai = (faidx_t*)calloc(1, sizeof(faidx_t));+ fai->hash = kh_init(s);+ buf = (char*)calloc(0x10000, 1);+ while (!feof(fp) && fgets(buf, 0x10000, fp)) {+ for (p = buf; *p && isgraph(*p); ++p);+ *p = 0; ++p;+#ifdef _WIN32+ sscanf(p, "%d%ld%d%d", &len, &offset, &line_blen, &line_len);+#else+ sscanf(p, "%d%lld%d%d", &len, &offset, &line_blen, &line_len);+#endif+ fai_insert_index(fai, buf, len, line_len, line_blen, offset);+ }+ free(buf);+ return fai;+}++void fai_destroy(faidx_t *fai)+{+ int i;+ for (i = 0; i < fai->n; ++i) free(fai->name[i]);+ free(fai->name);+ kh_destroy(s, fai->hash);+ if (fai->rz) razf_close(fai->rz);+ free(fai);+}++int fai_build(const char *fn)+{+ char *str;+ RAZF *rz;+ FILE *fp;+ faidx_t *fai;+ str = (char*)calloc(strlen(fn) + 5, 1);+ sprintf(str, "%s.fai", fn);+ rz = razf_open(fn, "r");+ if (rz == 0) {+ fprintf(stderr, "[fai_build] fail to open the FASTA file %s\n",fn);+ free(str);+ return -1;+ }+ fai = fai_build_core(rz);+ razf_close(rz);+ fp = fopen(str, "wb");+ if (fp == 0) {+ fprintf(stderr, "[fai_build] fail to write FASTA index %s\n",str);+ fai_destroy(fai); free(str);+ return -1;+ }+ fai_save(fai, fp);+ fclose(fp);+ free(str);+ fai_destroy(fai);+ return 0;+}++#ifdef _USE_KNETFILE+FILE *download_and_open(const char *fn)+{+ const int buf_size = 1 * 1024 * 1024;+ uint8_t *buf;+ FILE *fp;+ knetFile *fp_remote;+ const char *url = fn;+ const char *p;+ int l = strlen(fn);+ for (p = fn + l - 1; p >= fn; --p)+ if (*p == '/') break;+ fn = p + 1;++ // First try to open a local copy+ fp = fopen(fn, "r");+ if (fp)+ return fp;++ // If failed, download from remote and open+ fp_remote = knet_open(url, "rb");+ if (fp_remote == 0) {+ fprintf(stderr, "[download_from_remote] fail to open remote file %s\n",url);+ return NULL;+ }+ if ((fp = fopen(fn, "wb")) == 0) {+ fprintf(stderr, "[download_from_remote] fail to create file in the working directory %s\n",fn);+ knet_close(fp_remote);+ return NULL;+ }+ buf = (uint8_t*)calloc(buf_size, 1);+ while ((l = knet_read(fp_remote, buf, buf_size)) != 0)+ fwrite(buf, 1, l, fp);+ free(buf);+ fclose(fp);+ knet_close(fp_remote);++ return fopen(fn, "r");+}+#endif++faidx_t *fai_load(const char *fn)+{+ char *str;+ FILE *fp;+ faidx_t *fai;+ str = (char*)calloc(strlen(fn) + 5, 1);+ sprintf(str, "%s.fai", fn);++#ifdef _USE_KNETFILE+ if (strstr(fn, "ftp://") == fn || strstr(fn, "http://") == fn)+ {+ fp = download_and_open(str);+ if ( !fp )+ {+ fprintf(stderr, "[fai_load] failed to open remote FASTA index %s\n", str);+ free(str);+ return 0;+ }+ }+ else+#endif+ fp = fopen(str, "rb");+ if (fp == 0) {+ fprintf(stderr, "[fai_load] build FASTA index.\n");+ fai_build(fn);+ fp = fopen(str, "rb");+ if (fp == 0) {+ fprintf(stderr, "[fai_load] fail to open FASTA index.\n");+ free(str);+ return 0;+ }+ }++ fai = fai_read(fp);+ fclose(fp);++ fai->rz = razf_open(fn, "rb");+ free(str);+ if (fai->rz == 0) {+ fprintf(stderr, "[fai_load] fail to open FASTA file.\n");+ return 0;+ }+ return fai;+}++char *fai_fetch(const faidx_t *fai, const char *str, int *len)+{+ char *s, c;+ int i, l, k, name_end;+ khiter_t iter;+ faidx1_t val;+ khash_t(s) *h;+ int beg, end;++ beg = end = -1;+ h = fai->hash;+ name_end = l = strlen(str);+ s = (char*)malloc(l+1);+ // remove space+ for (i = k = 0; i < l; ++i)+ if (!isspace(str[i])) s[k++] = str[i];+ s[k] = 0; l = k;+ // determine the sequence name+ for (i = l - 1; i >= 0; --i) if (s[i] == ':') break; // look for colon from the end+ if (i >= 0) name_end = i;+ if (name_end < l) { // check if this is really the end+ int n_hyphen = 0;+ for (i = name_end + 1; i < l; ++i) {+ if (s[i] == '-') ++n_hyphen;+ else if (!isdigit(s[i]) && s[i] != ',') break;+ }+ if (i < l || n_hyphen > 1) name_end = l; // malformated region string; then take str as the name+ s[name_end] = 0;+ iter = kh_get(s, h, s);+ if (iter == kh_end(h)) { // cannot find the sequence name+ iter = kh_get(s, h, str); // try str as the name+ if (iter == kh_end(h)) {+ *len = 0;+ free(s); return 0;+ } else s[name_end] = ':', name_end = l;+ }+ } else iter = kh_get(s, h, str);+ val = kh_value(h, iter);+ // parse the interval+ if (name_end < l) {+ for (i = k = name_end + 1; i < l; ++i)+ if (s[i] != ',') s[k++] = s[i];+ s[k] = 0;+ beg = atoi(s + name_end + 1);+ for (i = name_end + 1; i != k; ++i) if (s[i] == '-') break;+ end = i < k? atoi(s + i + 1) : val.len;+ if (beg > 0) --beg;+ } else beg = 0, end = val.len;+ if (beg >= val.len) beg = val.len;+ if (end >= val.len) end = val.len;+ if (beg > end) beg = end;+ free(s);++ // now retrieve the sequence+ l = 0;+ s = (char*)malloc(end - beg + 2);+ razf_seek(fai->rz, val.offset + beg / val.line_blen * val.line_len + beg % val.line_blen, SEEK_SET);+ while (razf_read(fai->rz, &c, 1) == 1 && l < end - beg && !fai->rz->z_err)+ if (isgraph(c)) s[l++] = c;+ s[l] = '\0';+ *len = l;+ return s;+}++int faidx_main(int argc, char *argv[])+{+ if (argc == 1) {+ fprintf(stderr, "Usage: faidx <in.fasta> [<reg> [...]]\n");+ return 1;+ } else {+ if (argc == 2) fai_build(argv[1]);+ else {+ int i, j, k, l;+ char *s;+ faidx_t *fai;+ fai = fai_load(argv[1]);+ if (fai == 0) return 1;+ for (i = 2; i != argc; ++i) {+ printf(">%s\n", argv[i]);+ s = fai_fetch(fai, argv[i], &l);+ for (j = 0; j < l; j += 60) {+ for (k = 0; k < 60 && k < l - j; ++k)+ putchar(s[j + k]);+ putchar('\n');+ }+ free(s);+ }+ fai_destroy(fai);+ }+ }+ return 0;+}++int faidx_fetch_nseq(const faidx_t *fai) +{+ return fai->n;+}++char *faidx_fetch_seq(const faidx_t *fai, char *c_name, int p_beg_i, int p_end_i, int *len)+{+ int l;+ char c;+ khiter_t iter;+ faidx1_t val;+ char *seq=NULL;++ // Adjust position+ iter = kh_get(s, fai->hash, c_name);+ if(iter == kh_end(fai->hash)) return 0;+ val = kh_value(fai->hash, iter);+ if(p_end_i < p_beg_i) p_beg_i = p_end_i;+ if(p_beg_i < 0) p_beg_i = 0;+ else if(val.len <= p_beg_i) p_beg_i = val.len - 1;+ if(p_end_i < 0) p_end_i = 0;+ else if(val.len <= p_end_i) p_end_i = val.len - 1;++ // Now retrieve the sequence + l = 0;+ seq = (char*)malloc(p_end_i - p_beg_i + 2);+ razf_seek(fai->rz, val.offset + p_beg_i / val.line_blen * val.line_len + p_beg_i % val.line_blen, SEEK_SET);+ while (razf_read(fai->rz, &c, 1) == 1 && l < p_end_i - p_beg_i + 1)+ if (isgraph(c)) seq[l++] = c;+ seq[l] = '\0';+ *len = l;+ return seq;+}++#ifdef FAIDX_MAIN+int main(int argc, char *argv[]) { return faidx_main(argc, argv); }+#endif
+ samtools-0.1.18/faidx.h view
@@ -0,0 +1,103 @@+/* The MIT License++ Copyright (c) 2008 Genome Research Ltd (GRL).++ 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.+*/++/* Contact: Heng Li <lh3@sanger.ac.uk> */++#ifndef FAIDX_H+#define FAIDX_H++/*!+ @header++ Index FASTA files and extract subsequence.++ @copyright The Wellcome Trust Sanger Institute.+ */++struct __faidx_t;+typedef struct __faidx_t faidx_t;++#ifdef __cplusplus+extern "C" {+#endif++ /*!+ @abstract Build index for a FASTA or razip compressed FASTA file.+ @param fn FASTA file name+ @return 0 on success; or -1 on failure+ @discussion File "fn.fai" will be generated.+ */+ int fai_build(const char *fn);++ /*!+ @abstract Distroy a faidx_t struct.+ @param fai Pointer to the struct to be destroyed+ */+ void fai_destroy(faidx_t *fai);++ /*!+ @abstract Load index from "fn.fai".+ @param fn File name of the FASTA file+ */+ faidx_t *fai_load(const char *fn);++ /*!+ @abstract Fetch the sequence in a region.+ @param fai Pointer to the faidx_t struct+ @param reg Region in the format "chr2:20,000-30,000"+ @param len Length of the region+ @return Pointer to the sequence; null on failure++ @discussion The returned sequence is allocated by malloc family+ and should be destroyed by end users by calling free() on it.+ */+ char *fai_fetch(const faidx_t *fai, const char *reg, int *len);++ /*!+ @abstract Fetch the number of sequences. + @param fai Pointer to the faidx_t struct+ @return The number of sequences+ */+ int faidx_fetch_nseq(const faidx_t *fai);++ /*!+ @abstract Fetch the sequence in a region.+ @param fai Pointer to the faidx_t struct+ @param c_name Region name+ @param p_beg_i Beginning position number (zero-based)+ @param p_end_i End position number (zero-based)+ @param len Length of the region+ @return Pointer to the sequence; null on failure++ @discussion The returned sequence is allocated by malloc family+ and should be destroyed by end users by calling free() on it.+ */+ char *faidx_fetch_seq(const faidx_t *fai, char *c_name, int p_beg_i, int p_end_i, int *len);++#ifdef __cplusplus+}+#endif++#endif
+ samtools-0.1.18/kaln.c view
@@ -0,0 +1,486 @@+/* The MIT License++ Copyright (c) 2003-2006, 2008, 2009, by Heng Li <lh3lh3@gmail.com>++ 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.+*/++#include <stdlib.h>+#include <stdio.h>+#include <string.h>+#include <stdint.h>+#include <math.h>+#include "kaln.h"++#define FROM_M 0+#define FROM_I 1+#define FROM_D 2++typedef struct {+ int i, j;+ unsigned char ctype;+} path_t;++int aln_sm_blosum62[] = {+/* A R N D C Q E G H I L K M F P S T W Y V * X */+ 4,-1,-2,-2, 0,-1,-1, 0,-2,-1,-1,-1,-1,-2,-1, 1, 0,-3,-2, 0,-4, 0,+ -1, 5, 0,-2,-3, 1, 0,-2, 0,-3,-2, 2,-1,-3,-2,-1,-1,-3,-2,-3,-4,-1,+ -2, 0, 6, 1,-3, 0, 0, 0, 1,-3,-3, 0,-2,-3,-2, 1, 0,-4,-2,-3,-4,-1,+ -2,-2, 1, 6,-3, 0, 2,-1,-1,-3,-4,-1,-3,-3,-1, 0,-1,-4,-3,-3,-4,-1,+ 0,-3,-3,-3, 9,-3,-4,-3,-3,-1,-1,-3,-1,-2,-3,-1,-1,-2,-2,-1,-4,-2,+ -1, 1, 0, 0,-3, 5, 2,-2, 0,-3,-2, 1, 0,-3,-1, 0,-1,-2,-1,-2,-4,-1,+ -1, 0, 0, 2,-4, 2, 5,-2, 0,-3,-3, 1,-2,-3,-1, 0,-1,-3,-2,-2,-4,-1,+ 0,-2, 0,-1,-3,-2,-2, 6,-2,-4,-4,-2,-3,-3,-2, 0,-2,-2,-3,-3,-4,-1,+ -2, 0, 1,-1,-3, 0, 0,-2, 8,-3,-3,-1,-2,-1,-2,-1,-2,-2, 2,-3,-4,-1,+ -1,-3,-3,-3,-1,-3,-3,-4,-3, 4, 2,-3, 1, 0,-3,-2,-1,-3,-1, 3,-4,-1,+ -1,-2,-3,-4,-1,-2,-3,-4,-3, 2, 4,-2, 2, 0,-3,-2,-1,-2,-1, 1,-4,-1,+ -1, 2, 0,-1,-3, 1, 1,-2,-1,-3,-2, 5,-1,-3,-1, 0,-1,-3,-2,-2,-4,-1,+ -1,-1,-2,-3,-1, 0,-2,-3,-2, 1, 2,-1, 5, 0,-2,-1,-1,-1,-1, 1,-4,-1,+ -2,-3,-3,-3,-2,-3,-3,-3,-1, 0, 0,-3, 0, 6,-4,-2,-2, 1, 3,-1,-4,-1,+ -1,-2,-2,-1,-3,-1,-1,-2,-2,-3,-3,-1,-2,-4, 7,-1,-1,-4,-3,-2,-4,-2,+ 1,-1, 1, 0,-1, 0, 0, 0,-1,-2,-2, 0,-1,-2,-1, 4, 1,-3,-2,-2,-4, 0,+ 0,-1, 0,-1,-1,-1,-1,-2,-2,-1,-1,-1,-1,-2,-1, 1, 5,-2,-2, 0,-4, 0,+ -3,-3,-4,-4,-2,-2,-3,-2,-2,-3,-2,-3,-1, 1,-4,-3,-2,11, 2,-3,-4,-2,+ -2,-2,-2,-3,-2,-1,-2,-3, 2,-1,-1,-2,-1, 3,-3,-2,-2, 2, 7,-1,-4,-1,+ 0,-3,-3,-3,-1,-2,-2,-3,-3, 3, 1,-2, 1,-1,-2,-2, 0,-3,-1, 4,-4,-1,+ -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, 1,-4,+ 0,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2, 0, 0,-2,-1,-1,-4,-1+};++int aln_sm_blast[] = {+ 1, -3, -3, -3, -2,+ -3, 1, -3, -3, -2,+ -3, -3, 1, -3, -2,+ -3, -3, -3, 1, -2,+ -2, -2, -2, -2, -2+};++int aln_sm_qual[] = {+ 0, -23, -23, -23, 0,+ -23, 0, -23, -23, 0,+ -23, -23, 0, -23, 0,+ -23, -23, -23, 0, 0,+ 0, 0, 0, 0, 0+};++ka_param_t ka_param_blast = { 5, 2, 5, 2, aln_sm_blast, 5, 50 };+ka_param_t ka_param_aa2aa = { 10, 2, 10, 2, aln_sm_blosum62, 22, 50 };++ka_param2_t ka_param2_qual = { 37, 11, 37, 11, 37, 11, 0, 0, aln_sm_qual, 5, 50 };++static uint32_t *ka_path2cigar32(const path_t *path, int path_len, int *n_cigar)+{+ int i, n;+ uint32_t *cigar;+ unsigned char last_type;++ if (path_len == 0 || path == 0) {+ *n_cigar = 0;+ return 0;+ }++ last_type = path->ctype;+ for (i = n = 1; i < path_len; ++i) {+ if (last_type != path[i].ctype) ++n;+ last_type = path[i].ctype;+ }+ *n_cigar = n;+ cigar = (uint32_t*)calloc(*n_cigar, 4);++ cigar[0] = 1u << 4 | path[path_len-1].ctype;+ last_type = path[path_len-1].ctype;+ for (i = path_len - 2, n = 0; i >= 0; --i) {+ if (path[i].ctype == last_type) cigar[n] += 1u << 4;+ else {+ cigar[++n] = 1u << 4 | path[i].ctype;+ last_type = path[i].ctype;+ }+ }++ return cigar;+}++/***************************/+/* START OF common_align.c */+/***************************/++#define SET_INF(s) (s).M = (s).I = (s).D = MINOR_INF;++#define set_M(MM, cur, p, sc) \+{ \+ if ((p)->M >= (p)->I) { \+ if ((p)->M >= (p)->D) { \+ (MM) = (p)->M + (sc); (cur)->Mt = FROM_M; \+ } else { \+ (MM) = (p)->D + (sc); (cur)->Mt = FROM_D; \+ } \+ } else { \+ if ((p)->I > (p)->D) { \+ (MM) = (p)->I + (sc); (cur)->Mt = FROM_I; \+ } else { \+ (MM) = (p)->D + (sc); (cur)->Mt = FROM_D; \+ } \+ } \+}+#define set_I(II, cur, p) \+{ \+ if ((p)->M - gap_open > (p)->I) { \+ (cur)->It = FROM_M; \+ (II) = (p)->M - gap_open - gap_ext; \+ } else { \+ (cur)->It = FROM_I; \+ (II) = (p)->I - gap_ext; \+ } \+}+#define set_end_I(II, cur, p) \+{ \+ if (gap_end_ext >= 0) { \+ if ((p)->M - gap_end_open > (p)->I) { \+ (cur)->It = FROM_M; \+ (II) = (p)->M - gap_end_open - gap_end_ext; \+ } else { \+ (cur)->It = FROM_I; \+ (II) = (p)->I - gap_end_ext; \+ } \+ } else set_I(II, cur, p); \+}+#define set_D(DD, cur, p) \+{ \+ if ((p)->M - gap_open > (p)->D) { \+ (cur)->Dt = FROM_M; \+ (DD) = (p)->M - gap_open - gap_ext; \+ } else { \+ (cur)->Dt = FROM_D; \+ (DD) = (p)->D - gap_ext; \+ } \+}+#define set_end_D(DD, cur, p) \+{ \+ if (gap_end_ext >= 0) { \+ if ((p)->M - gap_end_open > (p)->D) { \+ (cur)->Dt = FROM_M; \+ (DD) = (p)->M - gap_end_open - gap_end_ext; \+ } else { \+ (cur)->Dt = FROM_D; \+ (DD) = (p)->D - gap_end_ext; \+ } \+ } else set_D(DD, cur, p); \+}++typedef struct {+ uint8_t Mt:3, It:2, Dt:3;+} dpcell_t;++typedef struct {+ int M, I, D;+} dpscore_t;++/***************************+ * banded global alignment *+ ***************************/+uint32_t *ka_global_core(uint8_t *seq1, int len1, uint8_t *seq2, int len2, const ka_param_t *ap, int *_score, int *n_cigar)+{+ int i, j;+ dpcell_t **dpcell, *q;+ dpscore_t *curr, *last, *s;+ int b1, b2, tmp_end;+ int *mat, end, max = 0;+ uint8_t type, ctype;+ uint32_t *cigar = 0;++ int gap_open, gap_ext, gap_end_open, gap_end_ext, b;+ int *score_matrix, N_MATRIX_ROW;++ /* initialize some align-related parameters. just for compatibility */+ gap_open = ap->gap_open;+ gap_ext = ap->gap_ext;+ gap_end_open = ap->gap_end_open;+ gap_end_ext = ap->gap_end_ext;+ b = ap->band_width;+ score_matrix = ap->matrix;+ N_MATRIX_ROW = ap->row;++ if (n_cigar) *n_cigar = 0;+ if (len1 == 0 || len2 == 0) return 0;++ /* calculate b1 and b2 */+ if (len1 > len2) {+ b1 = len1 - len2 + b;+ b2 = b;+ } else {+ b1 = b;+ b2 = len2 - len1 + b;+ }+ if (b1 > len1) b1 = len1;+ if (b2 > len2) b2 = len2;+ --seq1; --seq2;++ /* allocate memory */+ end = (b1 + b2 <= len1)? (b1 + b2 + 1) : (len1 + 1);+ dpcell = (dpcell_t**)malloc(sizeof(dpcell_t*) * (len2 + 1));+ for (j = 0; j <= len2; ++j)+ dpcell[j] = (dpcell_t*)malloc(sizeof(dpcell_t) * end);+ for (j = b2 + 1; j <= len2; ++j)+ dpcell[j] -= j - b2;+ curr = (dpscore_t*)malloc(sizeof(dpscore_t) * (len1 + 1));+ last = (dpscore_t*)malloc(sizeof(dpscore_t) * (len1 + 1));+ + /* set first row */+ SET_INF(*curr); curr->M = 0;+ for (i = 1, s = curr + 1; i < b1; ++i, ++s) {+ SET_INF(*s);+ set_end_D(s->D, dpcell[0] + i, s - 1);+ }+ s = curr; curr = last; last = s;++ /* core dynamic programming, part 1 */+ tmp_end = (b2 < len2)? b2 : len2 - 1;+ for (j = 1; j <= tmp_end; ++j) {+ q = dpcell[j]; s = curr; SET_INF(*s);+ set_end_I(s->I, q, last);+ end = (j + b1 <= len1 + 1)? (j + b1 - 1) : len1;+ mat = score_matrix + seq2[j] * N_MATRIX_ROW;+ ++s; ++q;+ for (i = 1; i != end; ++i, ++s, ++q) {+ set_M(s->M, q, last + i - 1, mat[seq1[i]]); /* this will change s->M ! */+ set_I(s->I, q, last + i);+ set_D(s->D, q, s - 1);+ }+ set_M(s->M, q, last + i - 1, mat[seq1[i]]);+ set_D(s->D, q, s - 1);+ if (j + b1 - 1 > len1) { /* bug fixed, 040227 */+ set_end_I(s->I, q, last + i);+ } else s->I = MINOR_INF;+ s = curr; curr = last; last = s;+ }+ /* last row for part 1, use set_end_D() instead of set_D() */+ if (j == len2 && b2 != len2 - 1) {+ q = dpcell[j]; s = curr; SET_INF(*s);+ set_end_I(s->I, q, last);+ end = (j + b1 <= len1 + 1)? (j + b1 - 1) : len1;+ mat = score_matrix + seq2[j] * N_MATRIX_ROW;+ ++s; ++q;+ for (i = 1; i != end; ++i, ++s, ++q) {+ set_M(s->M, q, last + i - 1, mat[seq1[i]]); /* this will change s->M ! */+ set_I(s->I, q, last + i);+ set_end_D(s->D, q, s - 1);+ }+ set_M(s->M, q, last + i - 1, mat[seq1[i]]);+ set_end_D(s->D, q, s - 1);+ if (j + b1 - 1 > len1) { /* bug fixed, 040227 */+ set_end_I(s->I, q, last + i);+ } else s->I = MINOR_INF;+ s = curr; curr = last; last = s;+ ++j;+ }++ /* core dynamic programming, part 2 */+ for (; j <= len2 - b2 + 1; ++j) {+ SET_INF(curr[j - b2]);+ mat = score_matrix + seq2[j] * N_MATRIX_ROW;+ end = j + b1 - 1;+ for (i = j - b2 + 1, q = dpcell[j] + i, s = curr + i; i != end; ++i, ++s, ++q) {+ set_M(s->M, q, last + i - 1, mat[seq1[i]]);+ set_I(s->I, q, last + i);+ set_D(s->D, q, s - 1);+ }+ set_M(s->M, q, last + i - 1, mat[seq1[i]]);+ set_D(s->D, q, s - 1);+ s->I = MINOR_INF;+ s = curr; curr = last; last = s;+ }++ /* core dynamic programming, part 3 */+ for (; j < len2; ++j) {+ SET_INF(curr[j - b2]);+ mat = score_matrix + seq2[j] * N_MATRIX_ROW;+ for (i = j - b2 + 1, q = dpcell[j] + i, s = curr + i; i < len1; ++i, ++s, ++q) {+ set_M(s->M, q, last + i - 1, mat[seq1[i]]);+ set_I(s->I, q, last + i);+ set_D(s->D, q, s - 1);+ }+ set_M(s->M, q, last + len1 - 1, mat[seq1[i]]);+ set_end_I(s->I, q, last + i);+ set_D(s->D, q, s - 1);+ s = curr; curr = last; last = s;+ }+ /* last row */+ if (j == len2) {+ SET_INF(curr[j - b2]);+ mat = score_matrix + seq2[j] * N_MATRIX_ROW;+ for (i = j - b2 + 1, q = dpcell[j] + i, s = curr + i; i < len1; ++i, ++s, ++q) {+ set_M(s->M, q, last + i - 1, mat[seq1[i]]);+ set_I(s->I, q, last + i);+ set_end_D(s->D, q, s - 1);+ }+ set_M(s->M, q, last + len1 - 1, mat[seq1[i]]);+ set_end_I(s->I, q, last + i);+ set_end_D(s->D, q, s - 1);+ s = curr; curr = last; last = s;+ }++ *_score = last[len1].M;+ if (n_cigar) { /* backtrace */+ path_t *p, *path = (path_t*)malloc(sizeof(path_t) * (len1 + len2 + 2));+ i = len1; j = len2;+ q = dpcell[j] + i;+ s = last + len1;+ max = s->M; type = q->Mt; ctype = FROM_M;+ if (s->I > max) { max = s->I; type = q->It; ctype = FROM_I; }+ if (s->D > max) { max = s->D; type = q->Dt; ctype = FROM_D; }++ p = path;+ p->ctype = ctype; p->i = i; p->j = j; /* bug fixed 040408 */+ ++p;+ do {+ switch (ctype) {+ case FROM_M: --i; --j; break;+ case FROM_I: --j; break;+ case FROM_D: --i; break;+ }+ q = dpcell[j] + i;+ ctype = type;+ switch (type) {+ case FROM_M: type = q->Mt; break;+ case FROM_I: type = q->It; break;+ case FROM_D: type = q->Dt; break;+ }+ p->ctype = ctype; p->i = i; p->j = j;+ ++p;+ } while (i || j);+ cigar = ka_path2cigar32(path, p - path - 1, n_cigar);+ free(path);+ }++ /* free memory */+ for (j = b2 + 1; j <= len2; ++j)+ dpcell[j] += j - b2;+ for (j = 0; j <= len2; ++j)+ free(dpcell[j]);+ free(dpcell);+ free(curr); free(last);++ return cigar;+}++typedef struct {+ int M, I, D;+} score_aux_t;++#define MINUS_INF -0x40000000++// matrix: len2 rows and len1 columns+int ka_global_score(const uint8_t *_seq1, int len1, const uint8_t *_seq2, int len2, const ka_param2_t *ap)+{+ +#define __score_aux(_p, _q0, _sc, _io, _ie, _do, _de) { \+ int t1, t2; \+ score_aux_t *_q; \+ _q = _q0; \+ _p->M = _q->M >= _q->I? _q->M : _q->I; \+ _p->M = _p->M >= _q->D? _p->M : _q->D; \+ _p->M += (_sc); \+ ++_q; t1 = _q->M - _io - _ie; t2 = _q->I - _ie; _p->I = t1 >= t2? t1 : t2; \+ _q = _p-1; t1 = _q->M - _do - _de; t2 = _q->D - _de; _p->D = t1 >= t2? t1 : t2; \+ }++ int i, j, bw, scmat_size = ap->row, *scmat = ap->matrix, ret;+ const uint8_t *seq1, *seq2;+ score_aux_t *curr, *last, *swap;+ bw = abs(len1 - len2) + ap->band_width;+ i = len1 > len2? len1 : len2;+ if (bw > i + 1) bw = i + 1;+ seq1 = _seq1 - 1; seq2 = _seq2 - 1;+ curr = calloc(len1 + 2, sizeof(score_aux_t));+ last = calloc(len1 + 2, sizeof(score_aux_t));+ { // the zero-th row+ int x, end = len1;+ score_aux_t *p;+ j = 0;+ x = j + bw; end = len1 < x? len1 : x; // band end+ p = curr;+ p->M = 0; p->I = p->D = MINUS_INF;+ for (i = 1, p = &curr[1]; i <= end; ++i, ++p)+ p->M = p->I = MINUS_INF, p->D = -(ap->edo + ap->ede * i);+ p->M = p->I = p->D = MINUS_INF;+ swap = curr; curr = last; last = swap;+ }+ for (j = 1; j < len2; ++j) {+ int x, beg = 0, end = len1, *scrow, col_end;+ score_aux_t *p;+ x = j - bw; beg = 0 > x? 0 : x; // band start+ x = j + bw; end = len1 < x? len1 : x; // band end+ if (beg == 0) { // from zero-th column+ p = curr;+ p->M = p->D = MINUS_INF; p->I = -(ap->eio + ap->eie * j);+ ++beg; // then beg = 1+ }+ scrow = scmat + seq2[j] * scmat_size;+ if (end == len1) col_end = 1, --end;+ else col_end = 0;+ for (i = beg, p = &curr[beg]; i <= end; ++i, ++p)+ __score_aux(p, &last[i-1], scrow[(int)seq1[i]], ap->iio, ap->iie, ap->ido, ap->ide);+ if (col_end) {+ __score_aux(p, &last[i-1], scrow[(int)seq1[i]], ap->eio, ap->eie, ap->ido, ap->ide);+ ++p;+ }+ p->M = p->I = p->D = MINUS_INF;+// for (i = 0; i <= len1; ++i) printf("(%d,%d,%d) ", curr[i].M, curr[i].I, curr[i].D); putchar('\n');+ swap = curr; curr = last; last = swap;+ }+ { // the last row+ int x, beg = 0, *scrow;+ score_aux_t *p;+ j = len2;+ x = j - bw; beg = 0 > x? 0 : x; // band start+ if (beg == 0) { // from zero-th column+ p = curr;+ p->M = p->D = MINUS_INF; p->I = -(ap->eio + ap->eie * j);+ ++beg; // then beg = 1+ }+ scrow = scmat + seq2[j] * scmat_size;+ for (i = beg, p = &curr[beg]; i < len1; ++i, ++p)+ __score_aux(p, &last[i-1], scrow[(int)seq1[i]], ap->iio, ap->iie, ap->edo, ap->ede);+ __score_aux(p, &last[i-1], scrow[(int)seq1[i]], ap->eio, ap->eie, ap->edo, ap->ede);+// for (i = 0; i <= len1; ++i) printf("(%d,%d,%d) ", curr[i].M, curr[i].I, curr[i].D); putchar('\n');+ }+ ret = curr[len1].M >= curr[len1].I? curr[len1].M : curr[len1].I;+ ret = ret >= curr[len1].D? ret : curr[len1].D;+ free(curr); free(last);+ return ret;+}++#ifdef _MAIN+int main(int argc, char *argv[])+{+// int len1 = 35, len2 = 35;+// uint8_t *seq1 = (uint8_t*)"\0\0\3\3\2\0\0\0\1\0\2\1\2\1\3\2\3\3\3\0\2\3\2\1\1\3\3\3\2\3\3\1\0\0\1";+// uint8_t *seq2 = (uint8_t*)"\0\0\3\3\2\0\0\0\1\0\2\1\2\1\3\2\3\3\3\0\2\3\2\1\1\3\3\3\2\3\3\1\0\1\0";+ int len1 = 4, len2 = 4;+ uint8_t *seq1 = (uint8_t*)"\1\0\0\1";+ uint8_t *seq2 = (uint8_t*)"\1\0\1\0";+ int sc;+// ka_global_core(seq1, 2, seq2, 1, &ka_param_qual, &sc, 0);+ sc = ka_global_score(seq1, len1, seq2, len2, &ka_param2_qual);+ printf("%d\n", sc);+ return 0;+}+#endif
+ samtools-0.1.18/kaln.h view
@@ -0,0 +1,67 @@+/* The MIT License++ Copyright (c) 2003-2006, 2008, 2009 by Heng Li <lh3@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.+*/++#ifndef LH3_KALN_H_+#define LH3_KALN_H_++#include <stdint.h>++#define MINOR_INF -1073741823++typedef struct {+ int gap_open;+ int gap_ext;+ int gap_end_open;+ int gap_end_ext;++ int *matrix;+ int row;+ int band_width;+} ka_param_t;++typedef struct {+ int iio, iie, ido, ide;+ int eio, eie, edo, ede;+ int *matrix;+ int row;+ int band_width;+} ka_param2_t;++#ifdef __cplusplus+extern "C" {+#endif++ uint32_t *ka_global_core(uint8_t *seq1, int len1, uint8_t *seq2, int len2, const ka_param_t *ap,+ int *_score, int *n_cigar);+ int ka_global_score(const uint8_t *_seq1, int len1, const uint8_t *_seq2, int len2, const ka_param2_t *ap);+#ifdef __cplusplus+}+#endif++extern ka_param_t ka_param_blast; /* = { 5, 2, 5, 2, aln_sm_blast, 5, 50 }; */+extern ka_param_t ka_param_qual; // only use this for global alignment!!!+extern ka_param2_t ka_param2_qual; // only use this for global alignment!!!++#endif
+ samtools-0.1.18/khash.h view
@@ -0,0 +1,528 @@+/* 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);+ if (!ret) kh_del(32, h, k);+ 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;+}+*/++/*+ 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.++ @copyright Heng Li+ */++#define AC_VERSION_KHASH_H "0.2.5"++#include <stdlib.h>+#include <string.h>+#include <limits.h>++/* compipler 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++#ifdef _MSC_VER+#define inline __inline+#endif++typedef khint32_t khint_t;+typedef khint_t khiter_t;++#define __ac_HASH_PRIME_SIZE 32+static const khint32_t __ac_prime_list[__ac_HASH_PRIME_SIZE] =+{+ 0ul, 3ul, 11ul, 23ul, 53ul,+ 97ul, 193ul, 389ul, 769ul, 1543ul,+ 3079ul, 6151ul, 12289ul, 24593ul, 49157ul,+ 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul,+ 3145739ul, 6291469ul, 12582917ul, 25165843ul, 50331653ul,+ 100663319ul, 201326611ul, 402653189ul, 805306457ul, 1610612741ul,+ 3221225473ul, 4294967291ul+};++#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))++static const double __ac_HASH_UPPER = 0.77;++#define KHASH_DECLARE(name, khkey_t, khval_t) \+ typedef struct { \+ khint_t n_buckets, size, n_occupied, upper_bound; \+ khint32_t *flags; \+ khkey_t *keys; \+ khval_t *vals; \+ } kh_##name##_t; \+ extern kh_##name##_t *kh_init_##name(); \+ 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 void 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_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \+ typedef struct { \+ khint_t n_buckets, size, n_occupied, upper_bound; \+ khint32_t *flags; \+ khkey_t *keys; \+ khval_t *vals; \+ } kh_##name##_t; \+ SCOPE kh_##name##_t *kh_init_##name() { \+ return (kh_##name##_t*)calloc(1, sizeof(kh_##name##_t)); \+ } \+ SCOPE void kh_destroy_##name(kh_##name##_t *h) \+ { \+ if (h) { \+ free(h->keys); free(h->flags); \+ free(h->vals); \+ free(h); \+ } \+ } \+ SCOPE void kh_clear_##name(kh_##name##_t *h) \+ { \+ if (h && h->flags) { \+ memset(h->flags, 0xaa, ((h->n_buckets>>4) + 1) * 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 inc, k, i, last; \+ k = __hash_func(key); i = k % h->n_buckets; \+ inc = 1 + k % (h->n_buckets - 1); last = i; \+ while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \+ if (i + inc >= h->n_buckets) i = i + inc - h->n_buckets; \+ else i += inc; \+ if (i == last) return h->n_buckets; \+ } \+ return __ac_iseither(h->flags, i)? h->n_buckets : i; \+ } else return 0; \+ } \+ SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \+ { \+ khint32_t *new_flags = 0; \+ khint_t j = 1; \+ { \+ khint_t t = __ac_HASH_PRIME_SIZE - 1; \+ while (__ac_prime_list[t] > new_n_buckets) --t; \+ new_n_buckets = __ac_prime_list[t+1]; \+ if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; \+ else { \+ new_flags = (khint32_t*)malloc(((new_n_buckets>>4) + 1) * sizeof(khint32_t)); \+ memset(new_flags, 0xaa, ((new_n_buckets>>4) + 1) * sizeof(khint32_t)); \+ if (h->n_buckets < new_n_buckets) { \+ h->keys = (khkey_t*)realloc(h->keys, new_n_buckets * sizeof(khkey_t)); \+ if (kh_is_map) \+ h->vals = (khval_t*)realloc(h->vals, new_n_buckets * sizeof(khval_t)); \+ } \+ } \+ } \+ if (j) { \+ for (j = 0; j != h->n_buckets; ++j) { \+ if (__ac_iseither(h->flags, j) == 0) { \+ khkey_t key = h->keys[j]; \+ khval_t val; \+ if (kh_is_map) val = h->vals[j]; \+ __ac_set_isdel_true(h->flags, j); \+ while (1) { \+ khint_t inc, k, i; \+ k = __hash_func(key); \+ i = k % new_n_buckets; \+ inc = 1 + k % (new_n_buckets - 1); \+ while (!__ac_isempty(new_flags, i)) { \+ if (i + inc >= new_n_buckets) i = i + inc - new_n_buckets; \+ else i += inc; \+ } \+ __ac_set_isempty_false(new_flags, i); \+ if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { \+ { 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); \+ } else { \+ h->keys[i] = key; \+ if (kh_is_map) h->vals[i] = val; \+ break; \+ } \+ } \+ } \+ } \+ if (h->n_buckets > new_n_buckets) { \+ h->keys = (khkey_t*)realloc(h->keys, new_n_buckets * sizeof(khkey_t)); \+ if (kh_is_map) \+ h->vals = (khval_t*)realloc(h->vals, new_n_buckets * sizeof(khval_t)); \+ } \+ free(h->flags); \+ 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); \+ } \+ } \+ 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) { \+ if (h->n_buckets > (h->size<<1)) kh_resize_##name(h, h->n_buckets - 1); \+ else kh_resize_##name(h, h->n_buckets + 1); \+ } \+ { \+ khint_t inc, k, i, site, last; \+ x = site = h->n_buckets; k = __hash_func(key); i = k % h->n_buckets; \+ if (__ac_isempty(h->flags, i)) x = i; \+ else { \+ inc = 1 + k % (h->n_buckets - 1); 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; \+ if (i + inc >= h->n_buckets) i = i + inc - h->n_buckets; \+ else i += inc; \+ 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)) { \+ 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)) { \+ h->keys[x] = key; \+ __ac_set_isboth_false(h->flags, x); \+ ++h->size; \+ *ret = 2; \+ } else *ret = 0; \+ 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_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \+ KHASH_INIT2(name, static inline, 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 inline khint_t __ac_X31_hash_string(const char *s)+{+ khint_t h = *s;+ if (h) for (++s ; *s; ++s) h = (h << 5) - h + *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)++/* --- END OF HASH FUNCTIONS --- */++/* Other necessary 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: 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) is 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)++/* 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 */
+ samtools-0.1.18/knetfile.c view
@@ -0,0 +1,632 @@+/* The MIT License++ Copyright (c) 2008 by Genome Research Ltd (GRL).+ 2010 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.+*/++/* Probably I will not do socket programming in the next few years and+ therefore I decide to heavily annotate this file, for Linux and+ Windows as well. -ac */++#include <time.h>+#include <stdio.h>+#include <ctype.h>+#include <stdlib.h>+#include <string.h>+#include <errno.h>+#include <unistd.h>+#include <sys/types.h>++#ifndef _WIN32+#include <netdb.h>+#include <arpa/inet.h>+#include <sys/socket.h>+#endif++#include "knetfile.h"++/* In winsock.h, the type of a socket is SOCKET, which is: "typedef+ * u_int SOCKET". An invalid SOCKET is: "(SOCKET)(~0)", or signed+ * integer -1. In knetfile.c, I use "int" for socket type+ * throughout. This should be improved to avoid confusion.+ *+ * In Linux/Mac, recv() and read() do almost the same thing. You can see+ * in the header file that netread() is simply an alias of read(). In+ * Windows, however, they are different and using recv() is mandatory.+ */++/* This function tests if the file handler is ready for reading (or+ * writing if is_read==0). */+static int socket_wait(int fd, int is_read)+{+ fd_set fds, *fdr = 0, *fdw = 0;+ struct timeval tv;+ int ret;+ tv.tv_sec = 5; tv.tv_usec = 0; // 5 seconds time out+ FD_ZERO(&fds);+ FD_SET(fd, &fds);+ if (is_read) fdr = &fds;+ else fdw = &fds;+ ret = select(fd+1, fdr, fdw, 0, &tv);+#ifndef _WIN32+ if (ret == -1) perror("select");+#else+ if (ret == 0)+ fprintf(stderr, "select time-out\n");+ else if (ret == SOCKET_ERROR)+ fprintf(stderr, "select: %d\n", WSAGetLastError());+#endif+ return ret;+}++#ifndef _WIN32+/* This function does not work with Windows due to the lack of+ * getaddrinfo() in winsock. It is addapted from an example in "Beej's+ * Guide to Network Programming" (http://beej.us/guide/bgnet/). */+static int socket_connect(const char *host, const char *port)+{+#define __err_connect(func) do { perror(func); freeaddrinfo(res); return -1; } while (0)++ int on = 1, fd;+ struct linger lng = { 0, 0 };+ struct addrinfo hints, *res = 0;+ memset(&hints, 0, sizeof(struct addrinfo));+ hints.ai_family = AF_UNSPEC;+ hints.ai_socktype = SOCK_STREAM;+ /* In Unix/Mac, getaddrinfo() is the most convenient way to get+ * server information. */+ if (getaddrinfo(host, port, &hints, &res) != 0) __err_connect("getaddrinfo");+ if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) __err_connect("socket");+ /* The following two setsockopt() are used by ftplib+ * (http://nbpfaus.net/~pfau/ftplib/). I am not sure if they+ * necessary. */+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) __err_connect("setsockopt");+ if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &lng, sizeof(lng)) == -1) __err_connect("setsockopt");+ if (connect(fd, res->ai_addr, res->ai_addrlen) != 0) __err_connect("connect");+ freeaddrinfo(res);+ return fd;+}+#else+/* MinGW's printf has problem with "%lld" */+char *int64tostr(char *buf, int64_t x)+{+ int cnt;+ int i = 0;+ do {+ buf[i++] = '0' + x % 10;+ x /= 10;+ } while (x);+ buf[i] = 0;+ for (cnt = i, i = 0; i < cnt/2; ++i) {+ int c = buf[i]; buf[i] = buf[cnt-i-1]; buf[cnt-i-1] = c;+ }+ return buf;+}++int64_t strtoint64(const char *buf)+{+ int64_t x;+ for (x = 0; *buf != '\0'; ++buf)+ x = x * 10 + ((int64_t) *buf - 48);+ return x;+}+/* In windows, the first thing is to establish the TCP connection. */+int knet_win32_init()+{+ WSADATA wsaData;+ return WSAStartup(MAKEWORD(2, 2), &wsaData);+}+void knet_win32_destroy()+{+ WSACleanup();+}+/* A slightly modfied version of the following function also works on+ * Mac (and presummably Linux). However, this function is not stable on+ * my Mac. It sometimes works fine but sometimes does not. Therefore for+ * non-Windows OS, I do not use this one. */+static SOCKET socket_connect(const char *host, const char *port)+{+#define __err_connect(func) \+ do { \+ fprintf(stderr, "%s: %d\n", func, WSAGetLastError()); \+ return -1; \+ } while (0)++ int on = 1;+ SOCKET fd;+ struct linger lng = { 0, 0 };+ struct sockaddr_in server;+ struct hostent *hp = 0;+ // open socket+ if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) __err_connect("socket");+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)) == -1) __err_connect("setsockopt");+ if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&lng, sizeof(lng)) == -1) __err_connect("setsockopt");+ // get host info+ if (isalpha(host[0])) hp = gethostbyname(host);+ else {+ struct in_addr addr;+ addr.s_addr = inet_addr(host);+ hp = gethostbyaddr((char*)&addr, 4, AF_INET);+ }+ if (hp == 0) __err_connect("gethost");+ // connect+ server.sin_addr.s_addr = *((unsigned long*)hp->h_addr);+ server.sin_family= AF_INET;+ server.sin_port = htons(atoi(port));+ if (connect(fd, (struct sockaddr*)&server, sizeof(server)) != 0) __err_connect("connect");+ // freehostent(hp); // strangely in MSDN, hp is NOT freed (memory leak?!)+ return fd;+}+#endif++static off_t my_netread(int fd, void *buf, off_t len)+{+ off_t rest = len, curr, l = 0;+ /* recv() and read() may not read the required length of data with+ * one call. They have to be called repeatedly. */+ while (rest) {+ if (socket_wait(fd, 1) <= 0) break; // socket is not ready for reading+ curr = netread(fd, buf + l, rest);+ /* According to the glibc manual, section 13.2, a zero returned+ * value indicates end-of-file (EOF), which should mean that+ * read() will not return zero if EOF has not been met but data+ * are not immediately available. */+ if (curr == 0) break;+ l += curr; rest -= curr;+ }+ return l;+}++/*************************+ * FTP specific routines *+ *************************/++static int kftp_get_response(knetFile *ftp)+{+#ifndef _WIN32+ unsigned char c;+#else+ char c;+#endif+ int n = 0;+ char *p;+ if (socket_wait(ftp->ctrl_fd, 1) <= 0) return 0;+ while (netread(ftp->ctrl_fd, &c, 1)) { // FIXME: this is *VERY BAD* for unbuffered I/O+ //fputc(c, stderr);+ if (n >= ftp->max_response) {+ ftp->max_response = ftp->max_response? ftp->max_response<<1 : 256;+ ftp->response = realloc(ftp->response, ftp->max_response);+ }+ ftp->response[n++] = c;+ if (c == '\n') {+ if (n >= 4 && isdigit(ftp->response[0]) && isdigit(ftp->response[1]) && isdigit(ftp->response[2])+ && ftp->response[3] != '-') break;+ n = 0;+ continue;+ }+ }+ if (n < 2) return -1;+ ftp->response[n-2] = 0;+ return strtol(ftp->response, &p, 0);+}++static int kftp_send_cmd(knetFile *ftp, const char *cmd, int is_get)+{+ if (socket_wait(ftp->ctrl_fd, 0) <= 0) return -1; // socket is not ready for writing+ netwrite(ftp->ctrl_fd, cmd, strlen(cmd));+ return is_get? kftp_get_response(ftp) : 0;+}++static int kftp_pasv_prep(knetFile *ftp)+{+ char *p;+ int v[6];+ kftp_send_cmd(ftp, "PASV\r\n", 1);+ for (p = ftp->response; *p && *p != '('; ++p);+ if (*p != '(') return -1;+ ++p;+ sscanf(p, "%d,%d,%d,%d,%d,%d", &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);+ memcpy(ftp->pasv_ip, v, 4 * sizeof(int));+ ftp->pasv_port = (v[4]<<8&0xff00) + v[5];+ return 0;+}+++static int kftp_pasv_connect(knetFile *ftp)+{+ char host[80], port[10];+ if (ftp->pasv_port == 0) {+ fprintf(stderr, "[kftp_pasv_connect] kftp_pasv_prep() is not called before hand.\n");+ return -1;+ }+ sprintf(host, "%d.%d.%d.%d", ftp->pasv_ip[0], ftp->pasv_ip[1], ftp->pasv_ip[2], ftp->pasv_ip[3]);+ sprintf(port, "%d", ftp->pasv_port);+ ftp->fd = socket_connect(host, port);+ if (ftp->fd == -1) return -1;+ return 0;+}++int kftp_connect(knetFile *ftp)+{+ ftp->ctrl_fd = socket_connect(ftp->host, ftp->port);+ if (ftp->ctrl_fd == -1) return -1;+ kftp_get_response(ftp);+ kftp_send_cmd(ftp, "USER anonymous\r\n", 1);+ kftp_send_cmd(ftp, "PASS kftp@\r\n", 1);+ kftp_send_cmd(ftp, "TYPE I\r\n", 1);+ return 0;+}++int kftp_reconnect(knetFile *ftp)+{+ if (ftp->ctrl_fd != -1) {+ netclose(ftp->ctrl_fd);+ ftp->ctrl_fd = -1;+ }+ netclose(ftp->fd);+ ftp->fd = -1;+ return kftp_connect(ftp);+}++// initialize ->type, ->host, ->retr and ->size+knetFile *kftp_parse_url(const char *fn, const char *mode)+{+ knetFile *fp;+ char *p;+ int l;+ if (strstr(fn, "ftp://") != fn) return 0;+ for (p = (char*)fn + 6; *p && *p != '/'; ++p);+ if (*p != '/') return 0;+ l = p - fn - 6;+ fp = calloc(1, sizeof(knetFile));+ fp->type = KNF_TYPE_FTP;+ fp->fd = -1;+ /* the Linux/Mac version of socket_connect() also recognizes a port+ * like "ftp", but the Windows version does not. */+ fp->port = strdup("21");+ fp->host = calloc(l + 1, 1);+ if (strchr(mode, 'c')) fp->no_reconnect = 1;+ strncpy(fp->host, fn + 6, l);+ fp->retr = calloc(strlen(p) + 8, 1);+ sprintf(fp->retr, "RETR %s\r\n", p);+ fp->size_cmd = calloc(strlen(p) + 8, 1);+ sprintf(fp->size_cmd, "SIZE %s\r\n", p);+ fp->seek_offset = 0;+ return fp;+}+// place ->fd at offset off+int kftp_connect_file(knetFile *fp)+{+ int ret;+ long long file_size;+ if (fp->fd != -1) {+ netclose(fp->fd);+ if (fp->no_reconnect) kftp_get_response(fp);+ }+ kftp_pasv_prep(fp);+ kftp_send_cmd(fp, fp->size_cmd, 1);+#ifndef _WIN32+ if ( sscanf(fp->response,"%*d %lld", &file_size) != 1 )+ {+ fprintf(stderr,"[kftp_connect_file] %s\n", fp->response);+ return -1;+ }+#else+ const char *p = fp->response;+ while (*p != ' ') ++p;+ while (*p < '0' || *p > '9') ++p;+ file_size = strtoint64(p);+#endif+ fp->file_size = file_size;+ if (fp->offset>=0) {+ char tmp[32];+#ifndef _WIN32+ sprintf(tmp, "REST %lld\r\n", (long long)fp->offset);+#else+ strcpy(tmp, "REST ");+ int64tostr(tmp + 5, fp->offset);+ strcat(tmp, "\r\n");+#endif+ kftp_send_cmd(fp, tmp, 1);+ }+ kftp_send_cmd(fp, fp->retr, 0);+ kftp_pasv_connect(fp);+ ret = kftp_get_response(fp);+ if (ret != 150) {+ fprintf(stderr, "[kftp_connect_file] %s\n", fp->response);+ netclose(fp->fd);+ fp->fd = -1;+ return -1;+ }+ fp->is_ready = 1;+ return 0;+}+++/**************************+ * HTTP specific routines *+ **************************/++knetFile *khttp_parse_url(const char *fn, const char *mode)+{+ knetFile *fp;+ char *p, *proxy, *q;+ int l;+ if (strstr(fn, "http://") != fn) return 0;+ // set ->http_host+ for (p = (char*)fn + 7; *p && *p != '/'; ++p);+ l = p - fn - 7;+ fp = calloc(1, sizeof(knetFile));+ fp->http_host = calloc(l + 1, 1);+ strncpy(fp->http_host, fn + 7, l);+ fp->http_host[l] = 0;+ for (q = fp->http_host; *q && *q != ':'; ++q);+ if (*q == ':') *q++ = 0;+ // get http_proxy+ proxy = getenv("http_proxy");+ // set ->host, ->port and ->path+ if (proxy == 0) {+ fp->host = strdup(fp->http_host); // when there is no proxy, server name is identical to http_host name.+ fp->port = strdup(*q? q : "80");+ fp->path = strdup(*p? p : "/");+ } else {+ fp->host = (strstr(proxy, "http://") == proxy)? strdup(proxy + 7) : strdup(proxy);+ for (q = fp->host; *q && *q != ':'; ++q);+ if (*q == ':') *q++ = 0; + fp->port = strdup(*q? q : "80");+ fp->path = strdup(fn);+ }+ fp->type = KNF_TYPE_HTTP;+ fp->ctrl_fd = fp->fd = -1;+ fp->seek_offset = 0;+ return fp;+}++int khttp_connect_file(knetFile *fp)+{+ int ret, l = 0;+ char *buf, *p;+ if (fp->fd != -1) netclose(fp->fd);+ fp->fd = socket_connect(fp->host, fp->port);+ buf = calloc(0x10000, 1); // FIXME: I am lazy... But in principle, 64KB should be large enough.+ l += sprintf(buf + l, "GET %s HTTP/1.0\r\nHost: %s\r\n", fp->path, fp->http_host);+ l += sprintf(buf + l, "Range: bytes=%lld-\r\n", (long long)fp->offset);+ l += sprintf(buf + l, "\r\n");+ netwrite(fp->fd, buf, l);+ l = 0;+ while (netread(fp->fd, buf + l, 1)) { // read HTTP header; FIXME: bad efficiency+ if (buf[l] == '\n' && l >= 3)+ if (strncmp(buf + l - 3, "\r\n\r\n", 4) == 0) break;+ ++l;+ }+ buf[l] = 0;+ if (l < 14) { // prematured header+ netclose(fp->fd);+ fp->fd = -1;+ return -1;+ }+ ret = strtol(buf + 8, &p, 0); // HTTP return code+ if (ret == 200 && fp->offset>0) { // 200 (complete result); then skip beginning of the file+ off_t rest = fp->offset;+ while (rest) {+ off_t l = rest < 0x10000? rest : 0x10000;+ rest -= my_netread(fp->fd, buf, l);+ }+ } else if (ret != 206 && ret != 200) {+ free(buf);+ fprintf(stderr, "[khttp_connect_file] fail to open file (HTTP code: %d).\n", ret);+ netclose(fp->fd);+ fp->fd = -1;+ return -1;+ }+ free(buf);+ fp->is_ready = 1;+ return 0;+}++/********************+ * Generic routines *+ ********************/++knetFile *knet_open(const char *fn, const char *mode)+{+ knetFile *fp = 0;+ if (mode[0] != 'r') {+ fprintf(stderr, "[kftp_open] only mode \"r\" is supported.\n");+ return 0;+ }+ if (strstr(fn, "ftp://") == fn) {+ fp = kftp_parse_url(fn, mode);+ if (fp == 0) return 0;+ if (kftp_connect(fp) == -1) {+ knet_close(fp);+ return 0;+ }+ kftp_connect_file(fp);+ } else if (strstr(fn, "http://") == fn) {+ fp = khttp_parse_url(fn, mode);+ if (fp == 0) return 0;+ khttp_connect_file(fp);+ } else { // local file+#ifdef _WIN32+ /* In windows, O_BINARY is necessary. In Linux/Mac, O_BINARY may+ * be undefined on some systems, although it is defined on my+ * Mac and the Linux I have tested on. */+ int fd = open(fn, O_RDONLY | O_BINARY);+#else + int fd = open(fn, O_RDONLY);+#endif+ if (fd == -1) {+ perror("open");+ return 0;+ }+ fp = (knetFile*)calloc(1, sizeof(knetFile));+ fp->type = KNF_TYPE_LOCAL;+ fp->fd = fd;+ fp->ctrl_fd = -1;+ }+ if (fp && fp->fd == -1) {+ knet_close(fp);+ return 0;+ }+ return fp;+}++knetFile *knet_dopen(int fd, const char *mode)+{+ knetFile *fp = (knetFile*)calloc(1, sizeof(knetFile));+ fp->type = KNF_TYPE_LOCAL;+ fp->fd = fd;+ return fp;+}++off_t knet_read(knetFile *fp, void *buf, off_t len)+{+ off_t l = 0;+ if (fp->fd == -1) return 0;+ if (fp->type == KNF_TYPE_FTP) {+ if (fp->is_ready == 0) {+ if (!fp->no_reconnect) kftp_reconnect(fp);+ kftp_connect_file(fp);+ }+ } else if (fp->type == KNF_TYPE_HTTP) {+ if (fp->is_ready == 0)+ khttp_connect_file(fp);+ }+ if (fp->type == KNF_TYPE_LOCAL) { // on Windows, the following block is necessary; not on UNIX+ off_t rest = len, curr;+ while (rest) {+ do {+ curr = read(fp->fd, buf + l, rest);+ } while (curr < 0 && EINTR == errno);+ if (curr < 0) return -1;+ if (curr == 0) break;+ l += curr; rest -= curr;+ }+ } else l = my_netread(fp->fd, buf, len);+ fp->offset += l;+ return l;+}++off_t knet_seek(knetFile *fp, int64_t off, int whence)+{+ if (whence == SEEK_SET && off == fp->offset) return 0;+ if (fp->type == KNF_TYPE_LOCAL) {+ /* Be aware that lseek() returns the offset after seeking,+ * while fseek() returns zero on success. */+ off_t offset = lseek(fp->fd, off, whence);+ if (offset == -1) {+ // Be silent, it is OK for knet_seek to fail when the file is streamed+ // fprintf(stderr,"[knet_seek] %s\n", strerror(errno));+ return -1;+ }+ fp->offset = offset;+ return 0;+ }+ else if (fp->type == KNF_TYPE_FTP) + {+ if (whence==SEEK_CUR)+ fp->offset += off;+ else if (whence==SEEK_SET)+ fp->offset = off;+ else if ( whence==SEEK_END)+ fp->offset = fp->file_size+off;+ fp->is_ready = 0;+ return 0;+ } + else if (fp->type == KNF_TYPE_HTTP) + {+ if (whence == SEEK_END) { // FIXME: can we allow SEEK_END in future?+ fprintf(stderr, "[knet_seek] SEEK_END is not supported for HTTP. Offset is unchanged.\n");+ errno = ESPIPE;+ return -1;+ }+ if (whence==SEEK_CUR)+ fp->offset += off;+ else if (whence==SEEK_SET)+ fp->offset = off;+ fp->is_ready = 0;+ return 0;+ }+ errno = EINVAL;+ fprintf(stderr,"[knet_seek] %s\n", strerror(errno));+ return -1;+}++int knet_close(knetFile *fp)+{+ if (fp == 0) return 0;+ if (fp->ctrl_fd != -1) netclose(fp->ctrl_fd); // FTP specific+ if (fp->fd != -1) {+ /* On Linux/Mac, netclose() is an alias of close(), but on+ * Windows, it is an alias of closesocket(). */+ if (fp->type == KNF_TYPE_LOCAL) close(fp->fd);+ else netclose(fp->fd);+ }+ free(fp->host); free(fp->port);+ free(fp->response); free(fp->retr); // FTP specific+ free(fp->path); free(fp->http_host); // HTTP specific+ free(fp);+ return 0;+}++#ifdef KNETFILE_MAIN+int main(void)+{+ char *buf;+ knetFile *fp;+ int type = 4, l;+#ifdef _WIN32+ knet_win32_init();+#endif+ buf = calloc(0x100000, 1);+ if (type == 0) {+ fp = knet_open("knetfile.c", "r");+ knet_seek(fp, 1000, SEEK_SET);+ } else if (type == 1) { // NCBI FTP, large file+ fp = knet_open("ftp://ftp.ncbi.nih.gov/1000genomes/ftp/data/NA12878/alignment/NA12878.chrom6.SLX.SRP000032.2009_06.bam", "r");+ knet_seek(fp, 2500000000ll, SEEK_SET);+ l = knet_read(fp, buf, 255);+ } else if (type == 2) {+ fp = knet_open("ftp://ftp.sanger.ac.uk/pub4/treefam/tmp/index.shtml", "r");+ knet_seek(fp, 1000, SEEK_SET);+ } else if (type == 3) {+ fp = knet_open("http://www.sanger.ac.uk/Users/lh3/index.shtml", "r");+ knet_seek(fp, 1000, SEEK_SET);+ } else if (type == 4) {+ fp = knet_open("http://www.sanger.ac.uk/Users/lh3/ex1.bam", "r");+ knet_read(fp, buf, 10000);+ knet_seek(fp, 20000, SEEK_SET);+ knet_seek(fp, 10000, SEEK_SET);+ l = knet_read(fp, buf+10000, 10000000) + 10000;+ }+ if (type != 4 && type != 1) {+ knet_read(fp, buf, 255);+ buf[255] = 0;+ printf("%s\n", buf);+ } else write(fileno(stdout), buf, l);+ knet_close(fp);+ free(buf);+ return 0;+}+#endif
+ samtools-0.1.18/knetfile.h view
@@ -0,0 +1,75 @@+#ifndef KNETFILE_H+#define KNETFILE_H++#include <stdint.h>+#include <fcntl.h>++#ifndef _WIN32+#define netread(fd, ptr, len) read(fd, ptr, len)+#define netwrite(fd, ptr, len) write(fd, ptr, len)+#define netclose(fd) close(fd)+#else+#include <winsock2.h>+#define netread(fd, ptr, len) recv(fd, ptr, len, 0)+#define netwrite(fd, ptr, len) send(fd, ptr, len, 0)+#define netclose(fd) closesocket(fd)+#endif++// FIXME: currently I/O is unbuffered++#define KNF_TYPE_LOCAL 1+#define KNF_TYPE_FTP 2+#define KNF_TYPE_HTTP 3++typedef struct knetFile_s {+ int type, fd;+ int64_t offset;+ char *host, *port;++ // the following are for FTP only+ int ctrl_fd, pasv_ip[4], pasv_port, max_response, no_reconnect, is_ready;+ char *response, *retr, *size_cmd;+ int64_t seek_offset; // for lazy seek+ int64_t file_size;++ // the following are for HTTP only+ char *path, *http_host;+} knetFile;++#define knet_tell(fp) ((fp)->offset)+#define knet_fileno(fp) ((fp)->fd)++#ifdef __cplusplus+extern "C" {+#endif++#ifdef _WIN32+ int knet_win32_init();+ void knet_win32_destroy();+#endif++ knetFile *knet_open(const char *fn, const char *mode);++ /* + This only works with local files.+ */+ knetFile *knet_dopen(int fd, const char *mode);++ /*+ If ->is_ready==0, this routine updates ->fd; otherwise, it simply+ reads from ->fd.+ */+ off_t knet_read(knetFile *fp, void *buf, off_t len);++ /*+ This routine only sets ->offset and ->is_ready=0. It does not+ communicate with the FTP server.+ */+ off_t knet_seek(knetFile *fp, int64_t off, int whence);+ int knet_close(knetFile *fp);++#ifdef __cplusplus+}+#endif++#endif
+ samtools-0.1.18/kprobaln.c view
@@ -0,0 +1,278 @@+/* The MIT License++ Copyright (c) 2003-2006, 2008-2010, by Heng Li <lh3lh3@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.+*/++#include <stdlib.h>+#include <stdio.h>+#include <string.h>+#include <stdint.h>+#include <math.h>+#include "kprobaln.h"++/*****************************************+ * Probabilistic banded glocal alignment *+ *****************************************/++#define EI .25+#define EM .33333333333++static float g_qual2prob[256];++#define set_u(u, b, i, k) { int x=(i)-(b); x=x>0?x:0; (u)=((k)-x+1)*3; }++kpa_par_t kpa_par_def = { 0.001, 0.1, 10 };+kpa_par_t kpa_par_alt = { 0.0001, 0.01, 10 };++/*+ The topology of the profile HMM:++ /\ /\ /\ /\+ I[1] I[k-1] I[k] I[L]+ ^ \ \ ^ \ ^ \ \ ^+ | \ \ | \ | \ \ |+ M[0] M[1] -> ... -> M[k-1] -> M[k] -> ... -> M[L] M[L+1]+ \ \/ \/ \/ /+ \ /\ /\ /\ /+ -> D[k-1] -> D[k] ->++ M[0] points to every {M,I}[k] and every {M,I}[k] points M[L+1].++ On input, _ref is the reference sequence and _query is the query+ sequence. Both are sequences of 0/1/2/3/4 where 4 stands for an+ ambiguous residue. iqual is the base quality. c sets the gap open+ probability, gap extension probability and band width.++ On output, state and q are arrays of length l_query. The higher 30+ bits give the reference position the query base is matched to and the+ lower two bits can be 0 (an alignment match) or 1 (an+ insertion). q[i] gives the phred scaled posterior probability of+ state[i] being wrong.+ */+int kpa_glocal(const uint8_t *_ref, int l_ref, const uint8_t *_query, int l_query, const uint8_t *iqual,+ const kpa_par_t *c, int *state, uint8_t *q)+{+ double **f, **b = 0, *s, m[9], sI, sM, bI, bM, pb;+ float *qual, *_qual;+ const uint8_t *ref, *query;+ int bw, bw2, i, k, is_diff = 0, is_backward = 1, Pr;++ /*** initialization ***/+ is_backward = state && q? 1 : 0;+ ref = _ref - 1; query = _query - 1; // change to 1-based coordinate+ bw = l_ref > l_query? l_ref : l_query;+ if (bw > c->bw) bw = c->bw;+ if (bw < abs(l_ref - l_query)) bw = abs(l_ref - l_query);+ bw2 = bw * 2 + 1;+ // allocate the forward and backward matrices f[][] and b[][] and the scaling array s[]+ f = calloc(l_query+1, sizeof(void*));+ if (is_backward) b = calloc(l_query+1, sizeof(void*));+ for (i = 0; i <= l_query; ++i) {+ f[i] = calloc(bw2 * 3 + 6, sizeof(double)); // FIXME: this is over-allocated for very short seqs+ if (is_backward) b[i] = calloc(bw2 * 3 + 6, sizeof(double));+ }+ s = calloc(l_query+2, sizeof(double)); // s[] is the scaling factor to avoid underflow+ // initialize qual+ _qual = calloc(l_query, sizeof(float));+ if (g_qual2prob[0] == 0)+ for (i = 0; i < 256; ++i)+ g_qual2prob[i] = pow(10, -i/10.);+ for (i = 0; i < l_query; ++i) _qual[i] = g_qual2prob[iqual? iqual[i] : 30];+ qual = _qual - 1;+ // initialize transition probability+ sM = sI = 1. / (2 * l_query + 2); // the value here seems not to affect results; FIXME: need proof+ m[0*3+0] = (1 - c->d - c->d) * (1 - sM); m[0*3+1] = m[0*3+2] = c->d * (1 - sM);+ m[1*3+0] = (1 - c->e) * (1 - sI); m[1*3+1] = c->e * (1 - sI); m[1*3+2] = 0.;+ m[2*3+0] = 1 - c->e; m[2*3+1] = 0.; m[2*3+2] = c->e;+ bM = (1 - c->d) / l_ref; bI = c->d / l_ref; // (bM+bI)*l_ref==1+ /*** forward ***/+ // f[0]+ set_u(k, bw, 0, 0);+ f[0][k] = s[0] = 1.;+ { // f[1]+ double *fi = f[1], sum;+ int beg = 1, end = l_ref < bw + 1? l_ref : bw + 1, _beg, _end;+ for (k = beg, sum = 0.; k <= end; ++k) {+ int u;+ double e = (ref[k] > 3 || query[1] > 3)? 1. : ref[k] == query[1]? 1. - qual[1] : qual[1] * EM;+ set_u(u, bw, 1, k);+ fi[u+0] = e * bM; fi[u+1] = EI * bI;+ sum += fi[u] + fi[u+1];+ }+ // rescale+ s[1] = sum;+ set_u(_beg, bw, 1, beg); set_u(_end, bw, 1, end); _end += 2;+ for (k = _beg; k <= _end; ++k) fi[k] /= sum;+ }+ // f[2..l_query]+ for (i = 2; i <= l_query; ++i) {+ double *fi = f[i], *fi1 = f[i-1], sum, qli = qual[i];+ int beg = 1, end = l_ref, x, _beg, _end;+ uint8_t qyi = query[i];+ x = i - bw; beg = beg > x? beg : x; // band start+ x = i + bw; end = end < x? end : x; // band end+ for (k = beg, sum = 0.; k <= end; ++k) {+ int u, v11, v01, v10;+ double e;+ e = (ref[k] > 3 || qyi > 3)? 1. : ref[k] == qyi? 1. - qli : qli * EM;+ set_u(u, bw, i, k); set_u(v11, bw, i-1, k-1); set_u(v10, bw, i-1, k); set_u(v01, bw, i, k-1);+ fi[u+0] = e * (m[0] * fi1[v11+0] + m[3] * fi1[v11+1] + m[6] * fi1[v11+2]);+ fi[u+1] = EI * (m[1] * fi1[v10+0] + m[4] * fi1[v10+1]);+ fi[u+2] = m[2] * fi[v01+0] + m[8] * fi[v01+2];+ sum += fi[u] + fi[u+1] + fi[u+2];+// fprintf(stderr, "F (%d,%d;%d): %lg,%lg,%lg\n", i, k, u, fi[u], fi[u+1], fi[u+2]); // DEBUG+ }+ // rescale+ s[i] = sum;+ set_u(_beg, bw, i, beg); set_u(_end, bw, i, end); _end += 2;+ for (k = _beg, sum = 1./sum; k <= _end; ++k) fi[k] *= sum;+ }+ { // f[l_query+1]+ double sum;+ for (k = 1, sum = 0.; k <= l_ref; ++k) {+ int u;+ set_u(u, bw, l_query, k);+ if (u < 3 || u >= bw2*3+3) continue;+ sum += f[l_query][u+0] * sM + f[l_query][u+1] * sI;+ }+ s[l_query+1] = sum; // the last scaling factor+ }+ { // compute likelihood+ double p = 1., Pr1 = 0.;+ for (i = 0; i <= l_query + 1; ++i) {+ p *= s[i];+ if (p < 1e-100) Pr1 += -4.343 * log(p), p = 1.;+ }+ Pr1 += -4.343 * log(p * l_ref * l_query);+ Pr = (int)(Pr1 + .499);+ if (!is_backward) { // skip backward and MAP+ for (i = 0; i <= l_query; ++i) free(f[i]);+ free(f); free(s); free(_qual);+ return Pr;+ }+ }+ /*** backward ***/+ // b[l_query] (b[l_query+1][0]=1 and thus \tilde{b}[][]=1/s[l_query+1]; this is where s[l_query+1] comes from)+ for (k = 1; k <= l_ref; ++k) {+ int u;+ double *bi = b[l_query];+ set_u(u, bw, l_query, k);+ if (u < 3 || u >= bw2*3+3) continue;+ bi[u+0] = sM / s[l_query] / s[l_query+1]; bi[u+1] = sI / s[l_query] / s[l_query+1];+ }+ // b[l_query-1..1]+ for (i = l_query - 1; i >= 1; --i) {+ int beg = 1, end = l_ref, x, _beg, _end;+ double *bi = b[i], *bi1 = b[i+1], y = (i > 1), qli1 = qual[i+1];+ uint8_t qyi1 = query[i+1];+ x = i - bw; beg = beg > x? beg : x;+ x = i + bw; end = end < x? end : x;+ for (k = end; k >= beg; --k) {+ int u, v11, v01, v10;+ double e;+ set_u(u, bw, i, k); set_u(v11, bw, i+1, k+1); set_u(v10, bw, i+1, k); set_u(v01, bw, i, k+1);+ e = (k >= l_ref? 0 : (ref[k+1] > 3 || qyi1 > 3)? 1. : ref[k+1] == qyi1? 1. - qli1 : qli1 * EM) * bi1[v11];+ bi[u+0] = e * m[0] + EI * m[1] * bi1[v10+1] + m[2] * bi[v01+2]; // bi1[v11] has been foled into e.+ bi[u+1] = e * m[3] + EI * m[4] * bi1[v10+1];+ bi[u+2] = (e * m[6] + m[8] * bi[v01+2]) * y;+// fprintf(stderr, "B (%d,%d;%d): %lg,%lg,%lg\n", i, k, u, bi[u], bi[u+1], bi[u+2]); // DEBUG+ }+ // rescale+ set_u(_beg, bw, i, beg); set_u(_end, bw, i, end); _end += 2;+ for (k = _beg, y = 1./s[i]; k <= _end; ++k) bi[k] *= y;+ }+ { // b[0]+ int beg = 1, end = l_ref < bw + 1? l_ref : bw + 1;+ double sum = 0.;+ for (k = end; k >= beg; --k) {+ int u;+ double e = (ref[k] > 3 || query[1] > 3)? 1. : ref[k] == query[1]? 1. - qual[1] : qual[1] * EM;+ set_u(u, bw, 1, k);+ if (u < 3 || u >= bw2*3+3) continue;+ sum += e * b[1][u+0] * bM + EI * b[1][u+1] * bI;+ }+ set_u(k, bw, 0, 0);+ pb = b[0][k] = sum / s[0]; // if everything works as is expected, pb == 1.0+ }+ is_diff = fabs(pb - 1.) > 1e-7? 1 : 0;+ /*** MAP ***/+ for (i = 1; i <= l_query; ++i) {+ double sum = 0., *fi = f[i], *bi = b[i], max = 0.;+ int beg = 1, end = l_ref, x, max_k = -1;+ x = i - bw; beg = beg > x? beg : x;+ x = i + bw; end = end < x? end : x;+ for (k = beg; k <= end; ++k) {+ int u;+ double z;+ set_u(u, bw, i, k);+ z = fi[u+0] * bi[u+0]; if (z > max) max = z, max_k = (k-1)<<2 | 0; sum += z;+ z = fi[u+1] * bi[u+1]; if (z > max) max = z, max_k = (k-1)<<2 | 1; sum += z;+ }+ max /= sum; sum *= s[i]; // if everything works as is expected, sum == 1.0+ if (state) state[i-1] = max_k;+ if (q) k = (int)(-4.343 * log(1. - max) + .499), q[i-1] = k > 100? 99 : k;+#ifdef _MAIN+ fprintf(stderr, "(%.10lg,%.10lg) (%d,%d:%c,%c:%d) %lg\n", pb, sum, i-1, max_k>>2,+ "ACGT"[query[i]], "ACGT"[ref[(max_k>>2)+1]], max_k&3, max); // DEBUG+#endif+ }+ /*** free ***/+ for (i = 0; i <= l_query; ++i) {+ free(f[i]); free(b[i]);+ }+ free(f); free(b); free(s); free(_qual);+ return Pr;+}++#ifdef _MAIN+#include <unistd.h>+int main(int argc, char *argv[])+{+ uint8_t conv[256], *iqual, *ref, *query;+ int c, l_ref, l_query, i, q = 30, b = 10, P;+ while ((c = getopt(argc, argv, "b:q:")) >= 0) {+ switch (c) {+ case 'b': b = atoi(optarg); break;+ case 'q': q = atoi(optarg); break;+ }+ }+ if (optind + 2 > argc) {+ fprintf(stderr, "Usage: %s [-q %d] [-b %d] <ref> <query>\n", argv[0], q, b); // example: acttc attc+ return 1;+ }+ memset(conv, 4, 256);+ conv['a'] = conv['A'] = 0; conv['c'] = conv['C'] = 1;+ conv['g'] = conv['G'] = 2; conv['t'] = conv['T'] = 3;+ ref = (uint8_t*)argv[optind]; query = (uint8_t*)argv[optind+1];+ l_ref = strlen((char*)ref); l_query = strlen((char*)query);+ for (i = 0; i < l_ref; ++i) ref[i] = conv[ref[i]];+ for (i = 0; i < l_query; ++i) query[i] = conv[query[i]];+ iqual = malloc(l_query);+ memset(iqual, q, l_query);+ kpa_par_def.bw = b;+ P = kpa_glocal(ref, l_ref, query, l_query, iqual, &kpa_par_alt, 0, 0);+ fprintf(stderr, "%d\n", P);+ free(iqual);+ return 0;+}+#endif
+ samtools-0.1.18/kprobaln.h view
@@ -0,0 +1,49 @@+/* The MIT License++ Copyright (c) 2003-2006, 2008, 2009 by Heng Li <lh3@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.+*/++#ifndef LH3_KPROBALN_H_+#define LH3_KPROBALN_H_++#include <stdint.h>++typedef struct {+ float d, e;+ int bw;+} kpa_par_t;++#ifdef __cplusplus+extern "C" {+#endif++ int kpa_glocal(const uint8_t *_ref, int l_ref, const uint8_t *_query, int l_query, const uint8_t *iqual,+ const kpa_par_t *c, int *state, uint8_t *q);++#ifdef __cplusplus+}+#endif++extern kpa_par_t kpa_par_def, kpa_par_alt;++#endif
+ samtools-0.1.18/kseq.h view
@@ -0,0 +1,224 @@+/* 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: 18AUG2011 */++#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_MAX 1++#define __KS_TYPE(type_t) \+ typedef struct __kstream_t { \+ unsigned char *buf; \+ int begin, end, is_eof; \+ type_t f; \+ } 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(type_t, __bufsize) \+ static inline kstream_t *ks_init(type_t f) \+ { \+ kstream_t *ks = (kstream_t*)calloc(1, sizeof(kstream_t)); \+ ks->f = f; \+ ks->buf = malloc(__bufsize); \+ return ks; \+ } \+ static inline void ks_destroy(kstream_t *ks) \+ { \+ if (ks) { \+ free(ks->buf); \+ free(ks); \+ } \+ }++#define __KS_GETC(__read, __bufsize) \+ 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, __bufsize); \+ if (ks->end < __bufsize) ks->is_eof = 1; \+ if (ks->end == 0) return -1; \+ } \+ return (int)ks->buf[ks->begin++]; \+ }++#ifndef KSTRING_T+#define KSTRING_T kstring_t+typedef struct __kstring_t {+ size_t 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(__read, __bufsize) \+ static 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, __bufsize); \+ if (ks->end < __bufsize) ks->is_eof = 1; \+ if (ks->end == 0) break; \+ } else break; \+ } \+ 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 < 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); \+ } \+ str->s[str->l] = '\0'; \+ return str->l; \+ } \+ static inline int ks_getuntil(kstream_t *ks, int delimiter, kstring_t *str, int *dret) \+ { return ks_getuntil2(ks, delimiter, str, dret, 0); }++#define KSTREAM_INIT(type_t, __read, __bufsize) \+ __KS_TYPE(type_t) \+ __KS_BASIC(type_t, __bufsize) \+ __KS_GETC(__read, __bufsize) \+ __KS_GETUNTIL(__read, __bufsize)++#define __KSEQ_BASIC(type_t) \+ static inline kseq_t *kseq_init(type_t fd) \+ { \+ kseq_t *s = (kseq_t*)calloc(1, sizeof(kseq_t)); \+ s->f = ks_init(fd); \+ return s; \+ } \+ static inline void kseq_rewind(kseq_t *ks) \+ { \+ ks->last_char = 0; \+ ks->f->is_eof = ks->f->begin = ks->f->end = 0; \+ } \+ static inline 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 \+ static 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, '\n', &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 != '@') { \+ seq->seq.s[seq->seq.l++] = c; /* this is safe: we always have enough space for 1 char */ \+ ks_getuntil2(ks, '\n', &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, '\n', &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_INIT(type_t, __read) \+ KSTREAM_INIT(type_t, __read, 16384) \+ __KSEQ_TYPE(type_t) \+ __KSEQ_BASIC(type_t) \+ __KSEQ_READ++#endif
+ samtools-0.1.18/ksort.h view
@@ -0,0 +1,281 @@+/* The MIT License++ Copyright (c) 2008 Genome Research Ltd (GRL).++ 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.+*/++/* Contact: Heng Li <lh3@sanger.ac.uk> */++/*+ 2008-11-16 (0.1.4):++ * Fixed a bug in introsort() that happens in rare cases.++ 2008-11-05 (0.1.3):++ * Fixed a bug in introsort() for complex comparisons.++ * Fixed a bug in mergesort(). The previous version is not stable.++ 2008-09-15 (0.1.2):++ * Accelerated introsort. On my Mac (not on another Linux machine),+ my implementation is as fast as std::sort on random input.++ * Added combsort and in introsort, switch to combsort if the+ recursion is too deep.++ 2008-09-13 (0.1.1):++ * Added k-small algorithm++ 2008-09-05 (0.1.0):++ * Initial version++*/++#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) \+ void ks_mergesort_##name(size_t n, type_t array[], type_t temp[]) \+ { \+ type_t *a2[2], *a, *b; \+ int curr, shift; \+ \+ a2[0] = array; \+ a2[1] = temp? temp : (type_t*)malloc(sizeof(type_t) * n); \+ for (curr = 0, shift = 0; (1ul<<shift) < n; ++shift) { \+ a = a2[curr]; b = a2[1-curr]; \+ if (shift == 0) { \+ type_t *p = b, *i, *eb = a + n; \+ for (i = a; i < eb; i += 2) { \+ if (i == eb - 1) *p++ = *i; \+ else { \+ if (__sort_lt(*(i+1), *i)) { \+ *p++ = *(i+1); *p++ = *i; \+ } else { \+ *p++ = *i; *p++ = *(i+1); \+ } \+ } \+ } \+ } else { \+ size_t i, step = 1ul<<shift; \+ for (i = 0; i < n; i += step<<1) { \+ type_t *p, *j, *k, *ea, *eb; \+ if (n < i + step) { \+ ea = a + n; eb = a; \+ } else { \+ ea = a + i + step; \+ eb = a + (n < i + (step<<1)? n : i + (step<<1)); \+ } \+ j = a + i; k = a + i + step; p = b + i; \+ while (j < ea && k < eb) { \+ if (__sort_lt(*k, *j)) *p++ = *k++; \+ else *p++ = *j++; \+ } \+ while (j < ea) *p++ = *j++; \+ while (k < eb) *p++ = *k++; \+ } \+ } \+ curr = 1 - curr; \+ } \+ if (curr == 1) { \+ type_t *p = a2[0], *i = a2[1], *eb = array + n; \+ for (; p < eb; ++i) *p++ = *i; \+ } \+ if (temp == 0) free(a2[1]); \+ } \+ void ks_heapadjust_##name(size_t i, size_t n, type_t l[]) \+ { \+ size_t k = i; \+ type_t tmp = l[i]; \+ while ((k = (k << 1) + 1) < n) { \+ if (k != n - 1 && __sort_lt(l[k], l[k+1])) ++k; \+ if (__sort_lt(l[k], tmp)) break; \+ l[i] = l[k]; i = k; \+ } \+ l[i] = tmp; \+ } \+ void ks_heapmake_##name(size_t lsize, type_t l[]) \+ { \+ size_t i; \+ for (i = (lsize >> 1) - 1; i != (size_t)(-1); --i) \+ ks_heapadjust_##name(i, lsize, l); \+ } \+ void ks_heapsort_##name(size_t lsize, type_t l[]) \+ { \+ size_t i; \+ for (i = lsize - 1; i > 0; --i) { \+ type_t tmp; \+ tmp = *l; *l = l[i]; l[i] = tmp; ks_heapadjust_##name(0, i, l); \+ } \+ } \+ inline void __ks_insertsort_##name(type_t *s, type_t *t) \+ { \+ type_t *i, *j, swap_tmp; \+ for (i = s + 1; i < t; ++i) \+ for (j = i; j > s && __sort_lt(*j, *(j-1)); --j) { \+ swap_tmp = *j; *j = *(j-1); *(j-1) = swap_tmp; \+ } \+ } \+ void ks_combsort_##name(size_t n, type_t a[]) \+ { \+ const double shrink_factor = 1.2473309501039786540366528676643; \+ int do_swap; \+ size_t gap = n; \+ type_t tmp, *i, *j; \+ do { \+ if (gap > 2) { \+ gap = (size_t)(gap / shrink_factor); \+ if (gap == 9 || gap == 10) gap = 11; \+ } \+ do_swap = 0; \+ for (i = a; i < a + n - gap; ++i) { \+ j = i + gap; \+ if (__sort_lt(*j, *i)) { \+ tmp = *i; *i = *j; *j = tmp; \+ do_swap = 1; \+ } \+ } \+ } while (do_swap || gap > 2); \+ if (gap != 1) __ks_insertsort_##name(a, a + n); \+ } \+ void ks_introsort_##name(size_t n, type_t a[]) \+ { \+ int d; \+ ks_isort_stack_t *top, *stack; \+ type_t rp, swap_tmp; \+ type_t *s, *t, *i, *j, *k; \+ \+ if (n < 1) return; \+ else if (n == 2) { \+ if (__sort_lt(a[1], a[0])) { swap_tmp = a[0]; a[0] = a[1]; a[1] = swap_tmp; } \+ return; \+ } \+ for (d = 2; 1ul<<d < n; ++d); \+ stack = (ks_isort_stack_t*)malloc(sizeof(ks_isort_stack_t) * ((sizeof(size_t)*d)+2)); \+ top = stack; s = a; t = a + (n-1); d <<= 1; \+ while (1) { \+ if (s < t) { \+ if (--d == 0) { \+ ks_combsort_##name(t - s + 1, s); \+ t = s; \+ continue; \+ } \+ i = s; j = t; k = i + ((j-i)>>1) + 1; \+ if (__sort_lt(*k, *i)) { \+ if (__sort_lt(*k, *j)) k = j; \+ } else k = __sort_lt(*j, *i)? i : j; \+ rp = *k; \+ if (k != t) { swap_tmp = *k; *k = *t; *t = swap_tmp; } \+ for (;;) { \+ do ++i; while (__sort_lt(*i, rp)); \+ do --j; while (i <= j && __sort_lt(rp, *j)); \+ if (j <= i) break; \+ swap_tmp = *i; *i = *j; *j = swap_tmp; \+ } \+ swap_tmp = *i; *i = *t; *t = swap_tmp; \+ if (i-s > t-i) { \+ if (i-s > 16) { top->left = s; top->right = i-1; top->depth = d; ++top; } \+ s = t-i > 16? i+1 : t; \+ } else { \+ if (t-i > 16) { top->left = i+1; top->right = t; top->depth = d; ++top; } \+ t = i-s > 16? i-1 : s; \+ } \+ } else { \+ if (top == stack) { \+ free(stack); \+ __ks_insertsort_##name(a, a+n); \+ return; \+ } else { --top; s = (type_t*)top->left; t = (type_t*)top->right; d = top->depth; } \+ } \+ } \+ } \+ /* This function is adapted from: http://ndevilla.free.fr/median/ */ \+ /* 0 <= kk < n */ \+ 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; \+ } \+ } \+ void ks_shuffle_##name(size_t n, type_t a[]) \+ { \+ int i, j; \+ for (i = n; i > 1; --i) { \+ type_t tmp; \+ j = (int)(drand48() * i); \+ tmp = a[j]; a[j] = a[i-1]; a[i-1] = tmp; \+ } \+ }++#define ks_mergesort(name, n, a, t) ks_mergesort_##name(n, a, t)+#define ks_introsort(name, n, a) ks_introsort_##name(n, a)+#define ks_combsort(name, n, a) ks_combsort_##name(n, a)+#define ks_heapsort(name, n, a) ks_heapsort_##name(n, a)+#define ks_heapmake(name, n, a) ks_heapmake_##name(n, a)+#define ks_heapadjust(name, i, n, a) ks_heapadjust_##name(i, n, a)+#define ks_ksmall(name, n, a, k) ks_ksmall_##name(n, a, k)+#define ks_shuffle(name, n, a) ks_shuffle_##name(n, a)++#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)++#endif
+ samtools-0.1.18/kstring.c view
@@ -0,0 +1,212 @@+#include <stdarg.h>+#include <stdio.h>+#include <ctype.h>+#include <string.h>+#include <stdint.h>+#include "kstring.h"++int ksprintf(kstring_t *s, const char *fmt, ...)+{+ va_list ap;+ int l;+ va_start(ap, fmt);+ l = vsnprintf(s->s + s->l, s->m - s->l, fmt, ap); // This line does not work with glibc 2.0. See `man snprintf'.+ va_end(ap);+ if (l + 1 > s->m - s->l) {+ s->m = s->l + l + 2;+ kroundup32(s->m);+ s->s = (char*)realloc(s->s, s->m);+ va_start(ap, fmt);+ l = vsnprintf(s->s + s->l, s->m - s->l, fmt, ap);+ }+ va_end(ap);+ s->l += l;+ return l;+}++char *kstrtok(const char *str, const char *sep, ks_tokaux_t *aux)+{+ const char *p, *start;+ if (sep) { // set up the table+ if (str == 0 && (aux->tab[0]&1)) return 0; // no need to set up if we have finished+ aux->finished = 0;+ if (sep[1]) {+ aux->sep = -1;+ aux->tab[0] = aux->tab[1] = aux->tab[2] = aux->tab[3] = 0;+ for (p = sep; *p; ++p) aux->tab[*p>>6] |= 1ull<<(*p&0x3f);+ } else aux->sep = sep[0];+ }+ if (aux->finished) return 0;+ else if (str) aux->p = str - 1, aux->finished = 0;+ if (aux->sep < 0) {+ for (p = start = aux->p + 1; *p; ++p)+ if (aux->tab[*p>>6]>>(*p&0x3f)&1) break;+ } else {+ for (p = start = aux->p + 1; *p; ++p)+ if (*p == aux->sep) break;+ }+ aux->p = p; // end of token+ if (*p == 0) aux->finished = 1; // no more tokens+ return (char*)start;+}++// s MUST BE a null terminated string; l = strlen(s)+int ksplit_core(char *s, int delimiter, int *_max, int **_offsets)+{+ int i, n, max, last_char, last_start, *offsets, l;+ n = 0; max = *_max; offsets = *_offsets;+ l = strlen(s);+ +#define __ksplit_aux do { \+ if (_offsets) { \+ s[i] = 0; \+ if (n == max) { \+ max = max? max<<1 : 2; \+ offsets = (int*)realloc(offsets, sizeof(int) * max); \+ } \+ offsets[n++] = last_start; \+ } else ++n; \+ } while (0)++ for (i = 0, last_char = last_start = 0; i <= l; ++i) {+ if (delimiter == 0) {+ if (isspace(s[i]) || s[i] == 0) {+ if (isgraph(last_char)) __ksplit_aux; // the end of a field+ } else {+ if (isspace(last_char) || last_char == 0) last_start = i;+ }+ } else {+ if (s[i] == delimiter || s[i] == 0) {+ if (last_char != 0 && last_char != delimiter) __ksplit_aux; // the end of a field+ } else {+ if (last_char == delimiter || last_char == 0) last_start = i;+ }+ }+ last_char = s[i];+ }+ *_max = max; *_offsets = offsets;+ return n;+}++/**********************+ * Boyer-Moore search *+ **********************/++typedef unsigned char ubyte_t;++// reference: http://www-igm.univ-mlv.fr/~lecroq/string/node14.html+static int *ksBM_prep(const ubyte_t *pat, int m)+{+ int i, *suff, *prep, *bmGs, *bmBc;+ prep = calloc(m + 256, sizeof(int));+ bmGs = prep; bmBc = prep + m;+ { // preBmBc()+ for (i = 0; i < 256; ++i) bmBc[i] = m;+ for (i = 0; i < m - 1; ++i) bmBc[pat[i]] = m - i - 1;+ }+ suff = calloc(m, sizeof(int));+ { // suffixes()+ int f = 0, g;+ suff[m - 1] = m;+ g = m - 1;+ for (i = m - 2; i >= 0; --i) {+ if (i > g && suff[i + m - 1 - f] < i - g)+ suff[i] = suff[i + m - 1 - f];+ else {+ if (i < g) g = i;+ f = i;+ while (g >= 0 && pat[g] == pat[g + m - 1 - f]) --g;+ suff[i] = f - g;+ }+ }+ }+ { // preBmGs()+ int j = 0;+ for (i = 0; i < m; ++i) bmGs[i] = m;+ for (i = m - 1; i >= 0; --i)+ if (suff[i] == i + 1)+ for (; j < m - 1 - i; ++j)+ if (bmGs[j] == m)+ bmGs[j] = m - 1 - i;+ for (i = 0; i <= m - 2; ++i)+ bmGs[m - 1 - suff[i]] = m - 1 - i;+ }+ free(suff);+ return prep;+}++void *kmemmem(const void *_str, int n, const void *_pat, int m, int **_prep)+{+ int i, j, *prep = 0, *bmGs, *bmBc;+ const ubyte_t *str, *pat;+ str = (const ubyte_t*)_str; pat = (const ubyte_t*)_pat;+ prep = (_prep == 0 || *_prep == 0)? ksBM_prep(pat, m) : *_prep;+ if (_prep && *_prep == 0) *_prep = prep;+ bmGs = prep; bmBc = prep + m;+ j = 0;+ while (j <= n - m) {+ for (i = m - 1; i >= 0 && pat[i] == str[i+j]; --i);+ if (i >= 0) {+ int max = bmBc[str[i+j]] - m + 1 + i;+ if (max < bmGs[i]) max = bmGs[i];+ j += max;+ } else return (void*)(str + j);+ }+ if (_prep == 0) free(prep);+ return 0;+}++char *kstrstr(const char *str, const char *pat, int **_prep)+{+ return (char*)kmemmem(str, strlen(str), pat, strlen(pat), _prep);+}++char *kstrnstr(const char *str, const char *pat, int n, int **_prep)+{+ return (char*)kmemmem(str, n, pat, strlen(pat), _prep);+}++/***********************+ * The main() function *+ ***********************/++#ifdef KSTRING_MAIN+#include <stdio.h>+int main()+{+ kstring_t *s;+ int *fields, n, i;+ ks_tokaux_t aux;+ char *p;+ s = (kstring_t*)calloc(1, sizeof(kstring_t));+ // test ksprintf()+ ksprintf(s, " abcdefg: %d ", 100);+ printf("'%s'\n", s->s);+ // test ksplit()+ fields = ksplit(s, 0, &n);+ for (i = 0; i < n; ++i)+ printf("field[%d] = '%s'\n", i, s->s + fields[i]);+ // test kstrtok()+ s->l = 0;+ for (p = kstrtok("ab:cde:fg/hij::k", ":/", &aux); p; p = kstrtok(0, 0, &aux)) {+ kputsn(p, aux.p - p, s);+ kputc('\n', s);+ }+ printf("%s", s->s);+ // free+ free(s->s); free(s); free(fields);++ {+ static char *str = "abcdefgcdgcagtcakcdcd";+ static char *pat = "cd";+ char *ret, *s = str;+ int *prep = 0;+ while ((ret = kstrstr(s, pat, &prep)) != 0) {+ printf("match: %s\n", ret);+ s = ret + prep[0];+ }+ free(prep);+ }+ return 0;+}+#endif
+ samtools-0.1.18/kstring.h view
@@ -0,0 +1,117 @@+#ifndef KSTRING_H+#define KSTRING_H++#include <stdlib.h>+#include <string.h>+#include <stdint.h>++#ifndef kroundup32+#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))+#endif++#ifndef KSTRING_T+#define KSTRING_T kstring_t+typedef struct __kstring_t {+ size_t l, m;+ char *s;+} kstring_t;+#endif++typedef struct {+ uint64_t tab[4];+ int sep, finished;+ const char *p; // end of the current token+} ks_tokaux_t;++#ifdef __cplusplus+extern "C" {+#endif++ int ksprintf(kstring_t *s, const char *fmt, ...);+ int ksplit_core(char *s, int delimiter, int *_max, int **_offsets);+ char *kstrstr(const char *str, const char *pat, int **_prep);+ char *kstrnstr(const char *str, const char *pat, int n, int **_prep);+ void *kmemmem(const void *_str, int n, const void *_pat, int m, int **_prep);++ /* kstrtok() is similar to strtok_r() except that str is not+ * modified and both str and sep can be NULL. For efficiency, it is+ * actually recommended to set both to NULL in the subsequent calls+ * if sep is not changed. */+ char *kstrtok(const char *str, const char *sep, ks_tokaux_t *aux);++#ifdef __cplusplus+}+#endif+ +static inline int kputsn(const char *p, int l, kstring_t *s)+{+ if (s->l + l + 1 >= s->m) {+ s->m = s->l + l + 2;+ kroundup32(s->m);+ s->s = (char*)realloc(s->s, s->m);+ }+ memcpy(s->s + s->l, p, l);+ s->l += l;+ s->s[s->l] = 0;+ return l;+}++static inline int kputs(const char *p, kstring_t *s)+{+ return kputsn(p, strlen(p), s);+}++static inline int kputc(int c, kstring_t *s)+{+ if (s->l + 1 >= s->m) {+ s->m = s->l + 2;+ kroundup32(s->m);+ s->s = (char*)realloc(s->s, s->m);+ }+ s->s[s->l++] = c;+ s->s[s->l] = 0;+ return c;+}++static inline int kputw(int c, kstring_t *s)+{+ char buf[16];+ int l, x;+ if (c == 0) return kputc('0', s);+ for (l = 0, x = c < 0? -c : c; x > 0; x /= 10) buf[l++] = x%10 + '0';+ if (c < 0) buf[l++] = '-';+ if (s->l + l + 1 >= s->m) {+ s->m = s->l + l + 2;+ kroundup32(s->m);+ s->s = (char*)realloc(s->s, s->m);+ }+ for (x = l - 1; x >= 0; --x) s->s[s->l++] = buf[x];+ s->s[s->l] = 0;+ return 0;+}++static inline int kputuw(unsigned c, kstring_t *s)+{+ char buf[16];+ int l, i;+ unsigned x;+ if (c == 0) return kputc('0', s);+ for (l = 0, x = c; x > 0; x /= 10) buf[l++] = x%10 + '0';+ if (s->l + l + 1 >= s->m) {+ s->m = s->l + l + 2;+ kroundup32(s->m);+ s->s = (char*)realloc(s->s, s->m);+ }+ for (i = l - 1; i >= 0; --i) s->s[s->l++] = buf[i];+ s->s[s->l] = 0;+ return 0;+}++static inline int *ksplit(kstring_t *s, int delimiter, int *n)+{+ int max = 0, *offsets = 0;+ *n = ksplit_core(s->s, delimiter, &max, &offsets);+ return offsets;+}++#endif
+ samtools-0.1.18/razf.c view
@@ -0,0 +1,853 @@+/*+ * RAZF : Random Access compressed(Z) File+ * Version: 1.0+ * Release Date: 2008-10-27+ *+ * Copyright 2008, Jue Ruan <ruanjue@gmail.com>, Heng Li <lh3@sanger.ac.uk>+ *+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ * notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ * notice, this list of conditions and the following disclaimer in the+ * documentation and/or other materials provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */++#ifndef _NO_RAZF++#include <fcntl.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <unistd.h>+#include "razf.h"+++#if ZLIB_VERNUM < 0x1221+struct _gz_header_s {+ int text;+ uLong time;+ int xflags;+ int os;+ Bytef *extra;+ uInt extra_len;+ uInt extra_max;+ Bytef *name;+ uInt name_max;+ Bytef *comment;+ uInt comm_max;+ int hcrc;+ int done;+};+#warning "zlib < 1.2.2.1; RAZF writing is disabled."+#endif++#define DEF_MEM_LEVEL 8++static inline uint32_t byte_swap_4(uint32_t v){+ v = ((v & 0x0000FFFFU) << 16) | (v >> 16);+ return ((v & 0x00FF00FFU) << 8) | ((v & 0xFF00FF00U) >> 8);+}++static inline uint64_t byte_swap_8(uint64_t v){+ v = ((v & 0x00000000FFFFFFFFLLU) << 32) | (v >> 32);+ v = ((v & 0x0000FFFF0000FFFFLLU) << 16) | ((v & 0xFFFF0000FFFF0000LLU) >> 16);+ return ((v & 0x00FF00FF00FF00FFLLU) << 8) | ((v & 0xFF00FF00FF00FF00LLU) >> 8);+}++static inline int is_big_endian(){+ int x = 0x01;+ char *c = (char*)&x;+ return (c[0] != 0x01);+}++#ifndef _RZ_READONLY+static void add_zindex(RAZF *rz, int64_t in, int64_t out){+ if(rz->index->size == rz->index->cap){+ rz->index->cap = rz->index->cap * 1.5 + 2;+ rz->index->cell_offsets = realloc(rz->index->cell_offsets, sizeof(int) * rz->index->cap);+ rz->index->bin_offsets = realloc(rz->index->bin_offsets, sizeof(int64_t) * (rz->index->cap/RZ_BIN_SIZE + 1));+ }+ if(rz->index->size % RZ_BIN_SIZE == 0) rz->index->bin_offsets[rz->index->size / RZ_BIN_SIZE] = out;+ rz->index->cell_offsets[rz->index->size] = out - rz->index->bin_offsets[rz->index->size / RZ_BIN_SIZE];+ rz->index->size ++;+}++static void save_zindex(RAZF *rz, int fd){+ int32_t i, v32;+ int is_be;+ is_be = is_big_endian();+ if(is_be) write(fd, &rz->index->size, sizeof(int));+ else {+ v32 = byte_swap_4((uint32_t)rz->index->size);+ write(fd, &v32, sizeof(uint32_t));+ }+ v32 = rz->index->size / RZ_BIN_SIZE + 1;+ if(!is_be){+ for(i=0;i<v32;i++) rz->index->bin_offsets[i] = byte_swap_8((uint64_t)rz->index->bin_offsets[i]);+ for(i=0;i<rz->index->size;i++) rz->index->cell_offsets[i] = byte_swap_4((uint32_t)rz->index->cell_offsets[i]);+ }+ write(fd, rz->index->bin_offsets, sizeof(int64_t) * v32);+ write(fd, rz->index->cell_offsets, sizeof(int32_t) * rz->index->size);+}+#endif++#ifdef _USE_KNETFILE+static void load_zindex(RAZF *rz, knetFile *fp){+#else+static void load_zindex(RAZF *rz, int fd){+#endif+ int32_t i, v32;+ int is_be;+ if(!rz->load_index) return;+ if(rz->index == NULL) rz->index = malloc(sizeof(ZBlockIndex));+ is_be = is_big_endian();+#ifdef _USE_KNETFILE+ knet_read(fp, &rz->index->size, sizeof(int));+#else+ read(fd, &rz->index->size, sizeof(int));+#endif+ if(!is_be) rz->index->size = byte_swap_4((uint32_t)rz->index->size);+ rz->index->cap = rz->index->size;+ v32 = rz->index->size / RZ_BIN_SIZE + 1;+ rz->index->bin_offsets = malloc(sizeof(int64_t) * v32);+#ifdef _USE_KNETFILE+ knet_read(fp, rz->index->bin_offsets, sizeof(int64_t) * v32);+#else+ read(fd, rz->index->bin_offsets, sizeof(int64_t) * v32);+#endif+ rz->index->cell_offsets = malloc(sizeof(int) * rz->index->size);+#ifdef _USE_KNETFILE+ knet_read(fp, rz->index->cell_offsets, sizeof(int) * rz->index->size);+#else+ read(fd, rz->index->cell_offsets, sizeof(int) * rz->index->size);+#endif+ if(!is_be){+ for(i=0;i<v32;i++) rz->index->bin_offsets[i] = byte_swap_8((uint64_t)rz->index->bin_offsets[i]);+ for(i=0;i<rz->index->size;i++) rz->index->cell_offsets[i] = byte_swap_4((uint32_t)rz->index->cell_offsets[i]);+ }+}++#ifdef _RZ_READONLY+static RAZF* razf_open_w(int fd)+{+ fprintf(stderr, "[razf_open_w] Writing is not available with zlib ver < 1.2.2.1\n");+ return 0;+}+#else+static RAZF* razf_open_w(int fd){+ RAZF *rz;+#ifdef _WIN32+ setmode(fd, O_BINARY);+#endif+ rz = calloc(1, sizeof(RAZF));+ rz->mode = 'w';+#ifdef _USE_KNETFILE+ rz->x.fpw = fd;+#else+ rz->filedes = fd;+#endif+ rz->stream = calloc(sizeof(z_stream), 1);+ rz->inbuf = malloc(RZ_BUFFER_SIZE);+ rz->outbuf = malloc(RZ_BUFFER_SIZE);+ rz->index = calloc(sizeof(ZBlockIndex), 1);+ deflateInit2(rz->stream, RZ_COMPRESS_LEVEL, Z_DEFLATED, WINDOW_BITS + 16, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);+ rz->stream->avail_out = RZ_BUFFER_SIZE;+ rz->stream->next_out = rz->outbuf;+ rz->header = calloc(sizeof(gz_header), 1);+ rz->header->os = 0x03; //Unix+ rz->header->text = 0;+ rz->header->time = 0;+ rz->header->extra = malloc(7);+ strncpy((char*)rz->header->extra, "RAZF", 4);+ rz->header->extra[4] = 1; // obsolete field+ // block size = RZ_BLOCK_SIZE, Big-Endian+ rz->header->extra[5] = RZ_BLOCK_SIZE >> 8;+ rz->header->extra[6] = RZ_BLOCK_SIZE & 0xFF;+ rz->header->extra_len = 7;+ rz->header->name = rz->header->comment = 0;+ rz->header->hcrc = 0;+ deflateSetHeader(rz->stream, rz->header);+ rz->block_pos = rz->block_off = 0;+ return rz;+}++static void _razf_write(RAZF* rz, const void *data, int size){+ int tout;+ rz->stream->avail_in = size;+ rz->stream->next_in = (void*)data;+ while(1){+ tout = rz->stream->avail_out;+ deflate(rz->stream, Z_NO_FLUSH);+ rz->out += tout - rz->stream->avail_out;+ if(rz->stream->avail_out) break;+#ifdef _USE_KNETFILE+ write(rz->x.fpw, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);+#else+ write(rz->filedes, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);+#endif+ rz->stream->avail_out = RZ_BUFFER_SIZE;+ rz->stream->next_out = rz->outbuf;+ if(rz->stream->avail_in == 0) break;+ };+ rz->in += size - rz->stream->avail_in;+ rz->block_off += size - rz->stream->avail_in;+}++static void razf_flush(RAZF *rz){+ uint32_t tout;+ if(rz->buf_len){+ _razf_write(rz, rz->inbuf, rz->buf_len);+ rz->buf_off = rz->buf_len = 0;+ }+ if(rz->stream->avail_out){+#ifdef _USE_KNETFILE + write(rz->x.fpw, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);+#else + write(rz->filedes, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);+#endif+ rz->stream->avail_out = RZ_BUFFER_SIZE;+ rz->stream->next_out = rz->outbuf;+ }+ while(1){+ tout = rz->stream->avail_out;+ deflate(rz->stream, Z_FULL_FLUSH);+ rz->out += tout - rz->stream->avail_out;+ if(rz->stream->avail_out == 0){+#ifdef _USE_KNETFILE + write(rz->x.fpw, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);+#else + write(rz->filedes, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);+#endif+ rz->stream->avail_out = RZ_BUFFER_SIZE;+ rz->stream->next_out = rz->outbuf;+ } else break;+ }+ rz->block_pos = rz->out;+ rz->block_off = 0;+}++static void razf_end_flush(RAZF *rz){+ uint32_t tout;+ if(rz->buf_len){+ _razf_write(rz, rz->inbuf, rz->buf_len);+ rz->buf_off = rz->buf_len = 0;+ }+ while(1){+ tout = rz->stream->avail_out;+ deflate(rz->stream, Z_FINISH);+ rz->out += tout - rz->stream->avail_out;+ if(rz->stream->avail_out < RZ_BUFFER_SIZE){+#ifdef _USE_KNETFILE + write(rz->x.fpw, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);+#else + write(rz->filedes, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);+#endif+ rz->stream->avail_out = RZ_BUFFER_SIZE;+ rz->stream->next_out = rz->outbuf;+ } else break;+ }+}++static void _razf_buffered_write(RAZF *rz, const void *data, int size){+ int i, n;+ while(1){+ if(rz->buf_len == RZ_BUFFER_SIZE){+ _razf_write(rz, rz->inbuf, rz->buf_len);+ rz->buf_len = 0;+ }+ if(size + rz->buf_len < RZ_BUFFER_SIZE){+ for(i=0;i<size;i++) ((char*)rz->inbuf + rz->buf_len)[i] = ((char*)data)[i];+ rz->buf_len += size;+ return;+ } else {+ n = RZ_BUFFER_SIZE - rz->buf_len;+ for(i=0;i<n;i++) ((char*)rz->inbuf + rz->buf_len)[i] = ((char*)data)[i];+ size -= n;+ data += n;+ rz->buf_len += n;+ }+ }+}++int razf_write(RAZF* rz, const void *data, int size){+ int ori_size, n;+ int64_t next_block;+ ori_size = size;+ next_block = ((rz->in / RZ_BLOCK_SIZE) + 1) * RZ_BLOCK_SIZE;+ while(rz->in + rz->buf_len + size >= next_block){+ n = next_block - rz->in - rz->buf_len;+ _razf_buffered_write(rz, data, n);+ data += n;+ size -= n;+ razf_flush(rz);+ add_zindex(rz, rz->in, rz->out);+ next_block = ((rz->in / RZ_BLOCK_SIZE) + 1) * RZ_BLOCK_SIZE;+ }+ _razf_buffered_write(rz, data, size);+ return ori_size;+}+#endif++/* gzip flag byte */+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */+#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */+#define COMMENT 0x10 /* bit 4 set: file comment present */+#define RESERVED 0xE0 /* bits 5..7: reserved */++static int _read_gz_header(unsigned char *data, int size, int *extra_off, int *extra_len){+ int method, flags, n, len;+ if(size < 2) return 0;+ if(data[0] != 0x1f || data[1] != 0x8b) return 0;+ if(size < 4) return 0;+ method = data[2];+ flags = data[3];+ if(method != Z_DEFLATED || (flags & RESERVED)) return 0;+ n = 4 + 6; // Skip 6 bytes+ *extra_off = n + 2;+ *extra_len = 0;+ if(flags & EXTRA_FIELD){+ if(size < n + 2) return 0;+ len = ((int)data[n + 1] << 8) | data[n];+ n += 2;+ *extra_off = n;+ while(len){+ if(n >= size) return 0;+ n ++;+ len --;+ }+ *extra_len = n - (*extra_off);+ }+ if(flags & ORIG_NAME) while(n < size && data[n++]);+ if(flags & COMMENT) while(n < size && data[n++]);+ if(flags & HEAD_CRC){+ if(n + 2 > size) return 0;+ n += 2;+ }+ return n;+}++#ifdef _USE_KNETFILE+static RAZF* razf_open_r(knetFile *fp, int _load_index){+#else+static RAZF* razf_open_r(int fd, int _load_index){+#endif+ RAZF *rz;+ int ext_off, ext_len;+ int n, is_be, ret;+ int64_t end;+ unsigned char c[] = "RAZF";+ rz = calloc(1, sizeof(RAZF));+ rz->mode = 'r';+#ifdef _USE_KNETFILE+ rz->x.fpr = fp;+#else+#ifdef _WIN32+ setmode(fd, O_BINARY);+#endif+ rz->filedes = fd;+#endif+ rz->stream = calloc(sizeof(z_stream), 1);+ rz->inbuf = malloc(RZ_BUFFER_SIZE);+ rz->outbuf = malloc(RZ_BUFFER_SIZE);+ rz->end = rz->src_end = 0x7FFFFFFFFFFFFFFFLL;+#ifdef _USE_KNETFILE+ n = knet_read(rz->x.fpr, rz->inbuf, RZ_BUFFER_SIZE);+#else+ n = read(rz->filedes, rz->inbuf, RZ_BUFFER_SIZE);+#endif+ ret = _read_gz_header(rz->inbuf, n, &ext_off, &ext_len);+ if(ret == 0){+ PLAIN_FILE:+ rz->in = n;+ rz->file_type = FILE_TYPE_PLAIN;+ memcpy(rz->outbuf, rz->inbuf, n);+ rz->buf_len = n;+ free(rz->stream);+ rz->stream = NULL;+ return rz;+ }+ rz->header_size = ret;+ ret = inflateInit2(rz->stream, -WINDOW_BITS);+ if(ret != Z_OK){ inflateEnd(rz->stream); goto PLAIN_FILE;}+ rz->stream->avail_in = n - rz->header_size;+ rz->stream->next_in = rz->inbuf + rz->header_size;+ rz->stream->avail_out = RZ_BUFFER_SIZE;+ rz->stream->next_out = rz->outbuf;+ rz->file_type = FILE_TYPE_GZ;+ rz->in = rz->header_size;+ rz->block_pos = rz->header_size;+ rz->next_block_pos = rz->header_size;+ rz->block_off = 0;+ if(ext_len < 7 || memcmp(rz->inbuf + ext_off, c, 4) != 0) return rz;+ if(((((unsigned char*)rz->inbuf)[ext_off + 5] << 8) | ((unsigned char*)rz->inbuf)[ext_off + 6]) != RZ_BLOCK_SIZE){+ fprintf(stderr, " -- WARNING: RZ_BLOCK_SIZE is not %d, treat source as gz file. in %s -- %s:%d --\n", RZ_BLOCK_SIZE, __FUNCTION__, __FILE__, __LINE__);+ return rz;+ }+ rz->load_index = _load_index;+ rz->file_type = FILE_TYPE_RZ;+#ifdef _USE_KNETFILE+ if(knet_seek(fp, -16, SEEK_END) == -1){+#else+ if(lseek(fd, -16, SEEK_END) == -1){+#endif+ UNSEEKABLE:+ rz->seekable = 0;+ rz->index = NULL;+ rz->src_end = rz->end = 0x7FFFFFFFFFFFFFFFLL;+ } else {+ is_be = is_big_endian();+ rz->seekable = 1;+#ifdef _USE_KNETFILE+ knet_read(fp, &end, sizeof(int64_t));+#else+ read(fd, &end, sizeof(int64_t));+#endif + if(!is_be) rz->src_end = (int64_t)byte_swap_8((uint64_t)end);+ else rz->src_end = end;++#ifdef _USE_KNETFILE+ knet_read(fp, &end, sizeof(int64_t));+#else+ read(fd, &end, sizeof(int64_t));+#endif + if(!is_be) rz->end = (int64_t)byte_swap_8((uint64_t)end);+ else rz->end = end;+ if(n > rz->end){+ rz->stream->avail_in -= n - rz->end;+ n = rz->end;+ }+ if(rz->end > rz->src_end){+#ifdef _USE_KNETFILE+ knet_seek(fp, rz->in, SEEK_SET);+#else+ lseek(fd, rz->in, SEEK_SET);+#endif+ goto UNSEEKABLE;+ }+#ifdef _USE_KNETFILE+ knet_seek(fp, rz->end, SEEK_SET);+ if(knet_tell(fp) != rz->end){+ knet_seek(fp, rz->in, SEEK_SET);+#else+ if(lseek(fd, rz->end, SEEK_SET) != rz->end){+ lseek(fd, rz->in, SEEK_SET);+#endif+ goto UNSEEKABLE;+ }+#ifdef _USE_KNETFILE+ load_zindex(rz, fp);+ knet_seek(fp, n, SEEK_SET);+#else+ load_zindex(rz, fd);+ lseek(fd, n, SEEK_SET);+#endif+ }+ return rz;+}++#ifdef _USE_KNETFILE+RAZF* razf_dopen(int fd, const char *mode){+ if (strstr(mode, "r")) fprintf(stderr,"[razf_dopen] implement me\n");+ else if(strstr(mode, "w")) return razf_open_w(fd);+ return NULL;+}++RAZF* razf_dopen2(int fd, const char *mode)+{+ fprintf(stderr,"[razf_dopen2] implement me\n");+ return NULL;+}+#else+RAZF* razf_dopen(int fd, const char *mode){+ if(strstr(mode, "r")) return razf_open_r(fd, 1);+ else if(strstr(mode, "w")) return razf_open_w(fd);+ else return NULL;+}++RAZF* razf_dopen2(int fd, const char *mode)+{+ if(strstr(mode, "r")) return razf_open_r(fd, 0);+ else if(strstr(mode, "w")) return razf_open_w(fd);+ else return NULL;+}+#endif++static inline RAZF* _razf_open(const char *filename, const char *mode, int _load_index){+ int fd;+ RAZF *rz;+ if(strstr(mode, "r")){+#ifdef _USE_KNETFILE+ knetFile *fd = knet_open(filename, "r");+ if (fd == 0) {+ fprintf(stderr, "[_razf_open] fail to open %s\n", filename);+ return NULL;+ }+#else+#ifdef _WIN32+ fd = open(filename, O_RDONLY | O_BINARY);+#else+ fd = open(filename, O_RDONLY);+#endif+#endif+ if(fd < 0) return NULL;+ rz = razf_open_r(fd, _load_index);+ } else if(strstr(mode, "w")){+#ifdef _WIN32+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);+#else+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);+#endif+ if(fd < 0) return NULL;+ rz = razf_open_w(fd);+ } else return NULL;+ return rz;+}++RAZF* razf_open(const char *filename, const char *mode){+ return _razf_open(filename, mode, 1);+}++RAZF* razf_open2(const char *filename, const char *mode){+ return _razf_open(filename, mode, 0);+}++int razf_get_data_size(RAZF *rz, int64_t *u_size, int64_t *c_size){+ int64_t n;+ if(rz->mode != 'r' && rz->mode != 'R') return 0;+ switch(rz->file_type){+ case FILE_TYPE_PLAIN:+ if(rz->end == 0x7fffffffffffffffLL){+#ifdef _USE_KNETFILE+ if(knet_seek(rz->x.fpr, 0, SEEK_CUR) == -1) return 0;+ n = knet_tell(rz->x.fpr);+ knet_seek(rz->x.fpr, 0, SEEK_END);+ rz->end = knet_tell(rz->x.fpr);+ knet_seek(rz->x.fpr, n, SEEK_SET);+#else+ if((n = lseek(rz->filedes, 0, SEEK_CUR)) == -1) return 0;+ rz->end = lseek(rz->filedes, 0, SEEK_END);+ lseek(rz->filedes, n, SEEK_SET);+#endif + }+ *u_size = *c_size = rz->end;+ return 1;+ case FILE_TYPE_GZ:+ return 0;+ case FILE_TYPE_RZ:+ if(rz->src_end == rz->end) return 0;+ *u_size = rz->src_end;+ *c_size = rz->end;+ return 1;+ default:+ return 0;+ }+}++static int _razf_read(RAZF* rz, void *data, int size){+ int ret, tin;+ if(rz->z_eof || rz->z_err) return 0;+ if (rz->file_type == FILE_TYPE_PLAIN) {+#ifdef _USE_KNETFILE+ ret = knet_read(rz->x.fpr, data, size);+#else+ ret = read(rz->filedes, data, size);+#endif + if (ret == 0) rz->z_eof = 1;+ return ret;+ }+ rz->stream->avail_out = size;+ rz->stream->next_out = data;+ while(rz->stream->avail_out){+ if(rz->stream->avail_in == 0){+ if(rz->in >= rz->end){ rz->z_eof = 1; break; }+ if(rz->end - rz->in < RZ_BUFFER_SIZE){+#ifdef _USE_KNETFILE+ rz->stream->avail_in = knet_read(rz->x.fpr, rz->inbuf, rz->end -rz->in);+#else+ rz->stream->avail_in = read(rz->filedes, rz->inbuf, rz->end -rz->in);+#endif + } else {+#ifdef _USE_KNETFILE+ rz->stream->avail_in = knet_read(rz->x.fpr, rz->inbuf, RZ_BUFFER_SIZE);+#else+ rz->stream->avail_in = read(rz->filedes, rz->inbuf, RZ_BUFFER_SIZE);+#endif + }+ if(rz->stream->avail_in == 0){+ rz->z_eof = 1;+ break;+ }+ rz->stream->next_in = rz->inbuf;+ }+ tin = rz->stream->avail_in;+ ret = inflate(rz->stream, Z_BLOCK);+ rz->in += tin - rz->stream->avail_in;+ if(ret == Z_NEED_DICT || ret == Z_MEM_ERROR || ret == Z_DATA_ERROR){+ fprintf(stderr, "[_razf_read] inflate error: %d %s (at %s:%d)\n", ret, rz->stream->msg ? rz->stream->msg : "", __FILE__, __LINE__);+ rz->z_err = 1;+ break;+ }+ if(ret == Z_STREAM_END){+ rz->z_eof = 1;+ break;+ }+ if ((rz->stream->data_type&128) && !(rz->stream->data_type&64)){+ rz->buf_flush = 1;+ rz->next_block_pos = rz->in;+ break;+ }+ }+ return size - rz->stream->avail_out;+}++int razf_read(RAZF *rz, void *data, int size){+ int ori_size, i;+ ori_size = size;+ while(size > 0){+ if(rz->buf_len){+ if(size < rz->buf_len){+ for(i=0;i<size;i++) ((char*)data)[i] = ((char*)rz->outbuf + rz->buf_off)[i];+ rz->buf_off += size;+ rz->buf_len -= size;+ data += size;+ rz->block_off += size;+ size = 0;+ break;+ } else {+ for(i=0;i<rz->buf_len;i++) ((char*)data)[i] = ((char*)rz->outbuf + rz->buf_off)[i];+ data += rz->buf_len;+ size -= rz->buf_len;+ rz->block_off += rz->buf_len;+ rz->buf_off = 0;+ rz->buf_len = 0;+ if(rz->buf_flush){+ rz->block_pos = rz->next_block_pos;+ rz->block_off = 0;+ rz->buf_flush = 0;+ }+ }+ } else if(rz->buf_flush){+ rz->block_pos = rz->next_block_pos;+ rz->block_off = 0;+ rz->buf_flush = 0;+ }+ if(rz->buf_flush) continue;+ rz->buf_len = _razf_read(rz, rz->outbuf, RZ_BUFFER_SIZE);+ if(rz->z_eof && rz->buf_len == 0) break;+ }+ rz->out += ori_size - size;+ return ori_size - size;+}++int razf_skip(RAZF* rz, int size){+ int ori_size;+ ori_size = size;+ while(size > 0){+ if(rz->buf_len){+ if(size < rz->buf_len){+ rz->buf_off += size;+ rz->buf_len -= size;+ rz->block_off += size;+ size = 0;+ break;+ } else {+ size -= rz->buf_len;+ rz->buf_off = 0;+ rz->buf_len = 0;+ rz->block_off += rz->buf_len;+ if(rz->buf_flush){+ rz->block_pos = rz->next_block_pos;+ rz->block_off = 0;+ rz->buf_flush = 0;+ }+ }+ } else if(rz->buf_flush){+ rz->block_pos = rz->next_block_pos;+ rz->block_off = 0;+ rz->buf_flush = 0;+ }+ if(rz->buf_flush) continue;+ rz->buf_len = _razf_read(rz, rz->outbuf, RZ_BUFFER_SIZE);+ if(rz->z_eof || rz->z_err) break;+ }+ rz->out += ori_size - size;+ return ori_size - size;+}++static void _razf_reset_read(RAZF *rz, int64_t in, int64_t out){+#ifdef _USE_KNETFILE+ knet_seek(rz->x.fpr, in, SEEK_SET);+#else+ lseek(rz->filedes, in, SEEK_SET);+#endif+ rz->in = in;+ rz->out = out;+ rz->block_pos = in;+ rz->next_block_pos = in;+ rz->block_off = 0;+ rz->buf_flush = 0;+ rz->z_eof = rz->z_err = 0;+ inflateReset(rz->stream);+ rz->stream->avail_in = 0;+ rz->buf_off = rz->buf_len = 0;+}++int64_t razf_jump(RAZF *rz, int64_t block_start, int block_offset){+ int64_t pos;+ rz->z_eof = 0;+ if(rz->file_type == FILE_TYPE_PLAIN){+ rz->buf_off = rz->buf_len = 0;+ pos = block_start + block_offset;+#ifdef _USE_KNETFILE+ knet_seek(rz->x.fpr, pos, SEEK_SET);+ pos = knet_tell(rz->x.fpr);+#else+ pos = lseek(rz->filedes, pos, SEEK_SET);+#endif+ rz->out = rz->in = pos;+ return pos;+ }+ if(block_start == rz->block_pos && block_offset >= rz->block_off) {+ block_offset -= rz->block_off;+ goto SKIP; // Needn't reset inflate+ }+ if(block_start == 0) block_start = rz->header_size; // Automaticly revist wrong block_start+ _razf_reset_read(rz, block_start, 0);+ SKIP:+ if(block_offset) razf_skip(rz, block_offset);+ return rz->block_off;+}++int64_t razf_seek(RAZF* rz, int64_t pos, int where){+ int64_t idx;+ int64_t seek_pos, new_out;+ rz->z_eof = 0;+ if (where == SEEK_CUR) pos += rz->out;+ else if (where == SEEK_END) pos += rz->src_end;+ if(rz->file_type == FILE_TYPE_PLAIN){+#ifdef _USE_KNETFILE+ knet_seek(rz->x.fpr, pos, SEEK_SET);+ seek_pos = knet_tell(rz->x.fpr);+#else+ seek_pos = lseek(rz->filedes, pos, SEEK_SET);+#endif+ rz->buf_off = rz->buf_len = 0;+ rz->out = rz->in = seek_pos;+ return seek_pos;+ } else if(rz->file_type == FILE_TYPE_GZ){+ if(pos >= rz->out) goto SKIP;+ return rz->out;+ }+ if(pos == rz->out) return pos;+ if(pos > rz->src_end) return rz->out;+ if(!rz->seekable || !rz->load_index){+ if(pos >= rz->out) goto SKIP;+ }+ idx = pos / RZ_BLOCK_SIZE - 1;+ seek_pos = (idx < 0)? rz->header_size:(rz->index->cell_offsets[idx] + rz->index->bin_offsets[idx / RZ_BIN_SIZE]);+ new_out = (idx + 1) * RZ_BLOCK_SIZE;+ if(pos > rz->out && new_out <= rz->out) goto SKIP;+ _razf_reset_read(rz, seek_pos, new_out);+ SKIP:+ razf_skip(rz, (int)(pos - rz->out));+ return rz->out;+}++uint64_t razf_tell2(RAZF *rz)+{+ /*+ if (rz->load_index) {+ int64_t idx, seek_pos;+ idx = rz->out / RZ_BLOCK_SIZE - 1;+ seek_pos = (idx < 0)? rz->header_size:(rz->index->cell_offsets[idx] + rz->index->bin_offsets[idx / RZ_BIN_SIZE]);+ if (seek_pos != rz->block_pos || rz->out%RZ_BLOCK_SIZE != rz->block_off)+ fprintf(stderr, "[razf_tell2] inconsistent block offset: (%lld, %lld) != (%lld, %lld)\n",+ (long long)seek_pos, (long long)rz->out%RZ_BLOCK_SIZE, (long long)rz->block_pos, (long long) rz->block_off);+ }+ */+ return (uint64_t)rz->block_pos<<16 | (rz->block_off&0xffff);+}++int64_t razf_seek2(RAZF *rz, uint64_t voffset, int where)+{+ if (where != SEEK_SET) return -1;+ return razf_jump(rz, voffset>>16, voffset&0xffff);+}++void razf_close(RAZF *rz){+ if(rz->mode == 'w'){+#ifndef _RZ_READONLY+ razf_end_flush(rz);+ deflateEnd(rz->stream);+#ifdef _USE_KNETFILE+ save_zindex(rz, rz->x.fpw);+ if(is_big_endian()){+ write(rz->x.fpw, &rz->in, sizeof(int64_t));+ write(rz->x.fpw, &rz->out, sizeof(int64_t));+ } else {+ uint64_t v64 = byte_swap_8((uint64_t)rz->in);+ write(rz->x.fpw, &v64, sizeof(int64_t));+ v64 = byte_swap_8((uint64_t)rz->out);+ write(rz->x.fpw, &v64, sizeof(int64_t));+ }+#else+ save_zindex(rz, rz->filedes);+ if(is_big_endian()){+ write(rz->filedes, &rz->in, sizeof(int64_t));+ write(rz->filedes, &rz->out, sizeof(int64_t));+ } else {+ uint64_t v64 = byte_swap_8((uint64_t)rz->in);+ write(rz->filedes, &v64, sizeof(int64_t));+ v64 = byte_swap_8((uint64_t)rz->out);+ write(rz->filedes, &v64, sizeof(int64_t));+ }+#endif+#endif+ } else if(rz->mode == 'r'){+ if(rz->stream) inflateEnd(rz->stream);+ }+ if(rz->inbuf) free(rz->inbuf);+ if(rz->outbuf) free(rz->outbuf);+ if(rz->header){+ free(rz->header->extra);+ free(rz->header->name);+ free(rz->header->comment);+ free(rz->header);+ }+ if(rz->index){+ free(rz->index->bin_offsets);+ free(rz->index->cell_offsets);+ free(rz->index);+ }+ free(rz->stream);+#ifdef _USE_KNETFILE+ if (rz->mode == 'r')+ knet_close(rz->x.fpr);+ if (rz->mode == 'w')+ close(rz->x.fpw);+#else+ close(rz->filedes);+#endif+ free(rz);+}++#endif
+ samtools-0.1.18/razf.h view
@@ -0,0 +1,134 @@+ /*-+ * RAZF : Random Access compressed(Z) File+ * Version: 1.0+ * Release Date: 2008-10-27+ *+ * Copyright 2008, Jue Ruan <ruanjue@gmail.com>, Heng Li <lh3@sanger.ac.uk>+ *+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ * notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ * notice, this list of conditions and the following disclaimer in the+ * documentation and/or other materials provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */+++#ifndef __RAZF_RJ_H+#define __RAZF_RJ_H++#include <stdint.h>+#include <stdio.h>+#include "zlib.h"++#ifdef _USE_KNETFILE+#include "knetfile.h"+#endif++#if ZLIB_VERNUM < 0x1221+#define _RZ_READONLY+struct _gz_header_s;+typedef struct _gz_header_s _gz_header;+#define gz_header _gz_header+#endif++#define WINDOW_BITS 15++#ifndef RZ_BLOCK_SIZE+#define RZ_BLOCK_SIZE (1<<WINDOW_BITS)+#endif++#ifndef RZ_BUFFER_SIZE+#define RZ_BUFFER_SIZE 4096+#endif++#ifndef RZ_COMPRESS_LEVEL+#define RZ_COMPRESS_LEVEL 6+#endif++#define RZ_BIN_SIZE ((1LLU << 32) / RZ_BLOCK_SIZE)++typedef struct {+ uint32_t *cell_offsets; // i+ int64_t *bin_offsets; // i / BIN_SIZE+ int size;+ int cap;+} ZBlockIndex;+/* When storing index, output bytes in Big-Endian everywhere */++#define FILE_TYPE_RZ 1+#define FILE_TYPE_PLAIN 2+#define FILE_TYPE_GZ 3++typedef struct RandomAccessZFile {+ char mode; /* 'w' : write mode; 'r' : read mode */+ int file_type;+ /* plain file or rz file, razf_read support plain file as input too, in this case, razf_read work as buffered fread */+#ifdef _USE_KNETFILE+ union {+ knetFile *fpr;+ int fpw;+ } x;+#else+ int filedes; /* the file descriptor */+#endif+ z_stream *stream;+ ZBlockIndex *index;+ int64_t in, out, end, src_end;+ /* in: n bytes total in; out: n bytes total out; */+ /* end: the end of all data blocks, while the start of index; src_end: the true end position in uncompressed file */+ int buf_flush; // buffer should be flush, suspend inflate util buffer is empty+ int64_t block_pos, block_off, next_block_pos;+ /* block_pos: the start postiion of current block in compressed file */+ /* block_off: tell how many bytes have been read from current block */+ void *inbuf, *outbuf;+ int header_size;+ gz_header *header;+ /* header is used to transfer inflate_state->mode from HEAD to TYPE after call inflateReset */+ int buf_off, buf_len;+ int z_err, z_eof;+ int seekable;+ /* Indice where the source is seekable */+ int load_index;+ /* set has_index to 0 in mode 'w', then index will be discarded */+} RAZF;++#ifdef __cplusplus+extern "C" {+#endif++ RAZF* razf_dopen(int data_fd, const char *mode);+ RAZF *razf_open(const char *fn, const char *mode);+ int razf_write(RAZF* rz, const void *data, int size);+ int razf_read(RAZF* rz, void *data, int size);+ int64_t razf_seek(RAZF* rz, int64_t pos, int where);+ void razf_close(RAZF* rz);++#define razf_tell(rz) ((rz)->out)++ RAZF* razf_open2(const char *filename, const char *mode);+ RAZF* razf_dopen2(int fd, const char *mode);+ uint64_t razf_tell2(RAZF *rz);+ int64_t razf_seek2(RAZF *rz, uint64_t voffset, int where);++#ifdef __cplusplus+}+#endif++#endif
+ samtools-0.1.18/sam.c view
@@ -0,0 +1,179 @@+#include <string.h>+#include <unistd.h>+#include "faidx.h"+#include "sam.h"++#define TYPE_BAM 1+#define TYPE_READ 2++bam_header_t *bam_header_dup(const bam_header_t *h0)+{+ bam_header_t *h;+ int i;+ h = bam_header_init();+ *h = *h0;+ h->hash = h->dict = h->rg2lib = 0;+ h->text = (char*)calloc(h->l_text + 1, 1);+ memcpy(h->text, h0->text, h->l_text);+ h->target_len = (uint32_t*)calloc(h->n_targets, 4);+ h->target_name = (char**)calloc(h->n_targets, sizeof(void*));+ for (i = 0; i < h->n_targets; ++i) {+ h->target_len[i] = h0->target_len[i];+ h->target_name[i] = strdup(h0->target_name[i]);+ }+ return h;+}+static void append_header_text(bam_header_t *header, char* text, int len)+{+ int x = header->l_text + 1;+ int y = header->l_text + len + 1; // 1 byte null+ if (text == 0) return;+ kroundup32(x); + kroundup32(y);+ if (x < y) header->text = (char*)realloc(header->text, y);+ strncpy(header->text + header->l_text, text, len); // we cannot use strcpy() here.+ header->l_text += len;+ header->text[header->l_text] = 0;+}++samfile_t *samopen(const char *fn, const char *mode, const void *aux)+{+ samfile_t *fp;+ fp = (samfile_t*)calloc(1, sizeof(samfile_t));+ if (strchr(mode, 'r')) { // read+ fp->type |= TYPE_READ;+ if (strchr(mode, 'b')) { // binary+ fp->type |= TYPE_BAM;+ fp->x.bam = strcmp(fn, "-")? bam_open(fn, "r") : bam_dopen(fileno(stdin), "r");+ if (fp->x.bam == 0) goto open_err_ret;+ fp->header = bam_header_read(fp->x.bam);+ } else { // text+ fp->x.tamr = sam_open(fn);+ if (fp->x.tamr == 0) goto open_err_ret;+ fp->header = sam_header_read(fp->x.tamr);+ if (fp->header->n_targets == 0) { // no @SQ fields+ if (aux) { // check if aux is present+ bam_header_t *textheader = fp->header;+ fp->header = sam_header_read2((const char*)aux);+ if (fp->header == 0) goto open_err_ret;+ append_header_text(fp->header, textheader->text, textheader->l_text);+ bam_header_destroy(textheader);+ }+ if (fp->header->n_targets == 0 && bam_verbose >= 1)+ fprintf(stderr, "[samopen] no @SQ lines in the header.\n");+ } else if (bam_verbose >= 2) fprintf(stderr, "[samopen] SAM header is present: %d sequences.\n", fp->header->n_targets);+ }+ } else if (strchr(mode, 'w')) { // write+ fp->header = bam_header_dup((const bam_header_t*)aux);+ if (strchr(mode, 'b')) { // binary+ char bmode[3];+ int i, compress_level = -1;+ for (i = 0; mode[i]; ++i) if (mode[i] >= '0' && mode[i] <= '9') break;+ if (mode[i]) compress_level = mode[i] - '0';+ if (strchr(mode, 'u')) compress_level = 0;+ bmode[0] = 'w'; bmode[1] = compress_level < 0? 0 : compress_level + '0'; bmode[2] = 0;+ fp->type |= TYPE_BAM;+ fp->x.bam = strcmp(fn, "-")? bam_open(fn, bmode) : bam_dopen(fileno(stdout), bmode);+ if (fp->x.bam == 0) goto open_err_ret;+ bam_header_write(fp->x.bam, fp->header);+ } else { // text+ // open file+ fp->x.tamw = strcmp(fn, "-")? fopen(fn, "w") : stdout;+ if (fp->x.tamr == 0) goto open_err_ret;+ if (strchr(mode, 'X')) fp->type |= BAM_OFSTR<<2;+ else if (strchr(mode, 'x')) fp->type |= BAM_OFHEX<<2;+ else fp->type |= BAM_OFDEC<<2;+ // write header+ if (strchr(mode, 'h')) {+ int i;+ bam_header_t *alt;+ // parse the header text + alt = bam_header_init();+ alt->l_text = fp->header->l_text; alt->text = fp->header->text;+ sam_header_parse(alt);+ alt->l_text = 0; alt->text = 0;+ // check if there are @SQ lines in the header+ fwrite(fp->header->text, 1, fp->header->l_text, fp->x.tamw); // FIXME: better to skip the trailing NULL+ if (alt->n_targets) { // then write the header text without dumping ->target_{name,len}+ if (alt->n_targets != fp->header->n_targets && bam_verbose >= 1)+ fprintf(stderr, "[samopen] inconsistent number of target sequences. Output the text header.\n");+ } else { // then dump ->target_{name,len}+ for (i = 0; i < fp->header->n_targets; ++i)+ fprintf(fp->x.tamw, "@SQ\tSN:%s\tLN:%d\n", fp->header->target_name[i], fp->header->target_len[i]);+ }+ bam_header_destroy(alt);+ }+ }+ }+ return fp;++open_err_ret:+ free(fp);+ return 0;+}++void samclose(samfile_t *fp)+{+ if (fp == 0) return;+ if (fp->header) bam_header_destroy(fp->header);+ if (fp->type & TYPE_BAM) bam_close(fp->x.bam);+ else if (fp->type & TYPE_READ) sam_close(fp->x.tamr);+ else fclose(fp->x.tamw);+ free(fp);+}++int samread(samfile_t *fp, bam1_t *b)+{+ if (fp == 0 || !(fp->type & TYPE_READ)) return -1; // not open for reading+ if (fp->type & TYPE_BAM) return bam_read1(fp->x.bam, b);+ else return sam_read1(fp->x.tamr, fp->header, b);+}++int samwrite(samfile_t *fp, const bam1_t *b)+{+ if (fp == 0 || (fp->type & TYPE_READ)) return -1; // not open for writing+ if (fp->type & TYPE_BAM) return bam_write1(fp->x.bam, b);+ else {+ char *s = bam_format1_core(fp->header, b, fp->type>>2&3);+ int l = strlen(s);+ fputs(s, fp->x.tamw); fputc('\n', fp->x.tamw);+ free(s);+ return l + 1;+ }+}++int sampileup(samfile_t *fp, int mask, bam_pileup_f func, void *func_data)+{+ bam_plbuf_t *buf;+ int ret;+ bam1_t *b;+ b = bam_init1();+ buf = bam_plbuf_init(func, func_data);+ bam_plbuf_set_mask(buf, mask);+ while ((ret = samread(fp, b)) >= 0)+ bam_plbuf_push(b, buf);+ bam_plbuf_push(0, buf);+ bam_plbuf_destroy(buf);+ bam_destroy1(b);+ return 0;+}++char *samfaipath(const char *fn_ref)+{+ char *fn_list = 0;+ if (fn_ref == 0) return 0;+ fn_list = calloc(strlen(fn_ref) + 5, 1);+ strcat(strcpy(fn_list, fn_ref), ".fai");+ if (access(fn_list, R_OK) == -1) { // fn_list is unreadable+ if (access(fn_ref, R_OK) == -1) {+ fprintf(stderr, "[samfaipath] fail to read file %s.\n", fn_ref);+ } else {+ if (bam_verbose >= 3) fprintf(stderr, "[samfaipath] build FASTA index...\n");+ if (fai_build(fn_ref) == -1) {+ fprintf(stderr, "[samfaipath] fail to build FASTA index.\n");+ free(fn_list); fn_list = 0;+ }+ }+ }+ return fn_list;+}
+ samtools-0.1.18/sam.h view
@@ -0,0 +1,98 @@+#ifndef BAM_SAM_H+#define BAM_SAM_H++#include "bam.h"++/*!+ @header++ This file provides higher level of I/O routines and unifies the APIs+ for SAM and BAM formats. These APIs are more convenient and+ recommended.++ @copyright Genome Research Ltd.+ */++/*! @typedef+ @abstract SAM/BAM file handler+ @field type type of the handler; bit 1 for BAM, 2 for reading and bit 3-4 for flag format+ @field bam BAM file handler; valid if (type&1) == 1+ @field tamr SAM file handler for reading; valid if type == 2+ @field tamw SAM file handler for writing; valid if type == 0+ @field header header struct+ */+typedef struct {+ int type;+ union {+ tamFile tamr;+ bamFile bam;+ FILE *tamw;+ } x;+ bam_header_t *header;+} samfile_t;++#ifdef __cplusplus+extern "C" {+#endif++ /*!+ @abstract Open a SAM/BAM file++ @param fn SAM/BAM file name; "-" is recognized as stdin (for+ reading) or stdout (for writing).++ @param mode open mode /[rw](b?)(u?)(h?)([xX]?)/: 'r' for reading,+ 'w' for writing, 'b' for BAM I/O, 'u' for uncompressed BAM output,+ 'h' for outputing header in SAM, 'x' for HEX flag and 'X' for+ string flag. If 'b' present, it must immediately follow 'r' or+ 'w'. Valid modes are "r", "w", "wh", "wx", "whx", "wX", "whX",+ "rb", "wb" and "wbu" exclusively.++ @param aux auxiliary data; if mode[0]=='w', aux points to+ bam_header_t; if strcmp(mode, "rb")!=0 and @SQ header lines in SAM+ are absent, aux points the file name of the list of the reference;+ aux is not used otherwise. If @SQ header lines are present in SAM,+ aux is not used, either.++ @return SAM/BAM file handler+ */+ samfile_t *samopen(const char *fn, const char *mode, const void *aux);++ /*!+ @abstract Close a SAM/BAM handler+ @param fp file handler to be closed+ */+ void samclose(samfile_t *fp);++ /*!+ @abstract Read one alignment+ @param fp file handler+ @param b alignment+ @return bytes read+ */+ int samread(samfile_t *fp, bam1_t *b);++ /*!+ @abstract Write one alignment+ @param fp file handler+ @param b alignment+ @return bytes written+ */+ int samwrite(samfile_t *fp, const bam1_t *b);++ /*!+ @abstract Get the pileup for a whole alignment file+ @param fp file handler+ @param mask mask transferred to bam_plbuf_set_mask()+ @param func user defined function called in the pileup process+ #param data user provided data for func()+ */+ int sampileup(samfile_t *fp, int mask, bam_pileup_f func, void *data);++ char *samfaipath(const char *fn_ref);++#ifdef __cplusplus+}+#endif++#endif
+ samtools-0.1.18/sam_header.c view
@@ -0,0 +1,736 @@+#include "sam_header.h"+#include <stdio.h>+#include <string.h>+#include <ctype.h>+#include <stdlib.h>+#include <stdarg.h>++#include "khash.h"+KHASH_MAP_INIT_STR(str, const char *)++struct _HeaderList+{+ struct _HeaderList *last; // Hack: Used and maintained only by list_append_to_end. Maintained in the root node only.+ struct _HeaderList *next;+ void *data;+};+typedef struct _HeaderList list_t;+typedef list_t HeaderDict;++typedef struct+{+ char key[2];+ char *value;+}+HeaderTag;++typedef struct+{+ char type[2];+ list_t *tags;+}+HeaderLine;++const char *o_hd_tags[] = {"SO","GO",NULL};+const char *r_hd_tags[] = {"VN",NULL};++const char *o_sq_tags[] = {"AS","M5","UR","SP",NULL};+const char *r_sq_tags[] = {"SN","LN",NULL};+const char *u_sq_tags[] = {"SN",NULL};++const char *o_rg_tags[] = {"CN","DS","DT","FO","KS","LB","PG","PI","PL","PU","SM",NULL};+const char *r_rg_tags[] = {"ID",NULL};+const char *u_rg_tags[] = {"ID",NULL};++const char *o_pg_tags[] = {"VN","CL",NULL};+const char *r_pg_tags[] = {"ID",NULL};++const char *types[] = {"HD","SQ","RG","PG","CO",NULL};+const char **optional_tags[] = {o_hd_tags,o_sq_tags,o_rg_tags,o_pg_tags,NULL,NULL};+const char **required_tags[] = {r_hd_tags,r_sq_tags,r_rg_tags,r_pg_tags,NULL,NULL};+const char **unique_tags[] = {NULL, u_sq_tags,u_rg_tags,NULL,NULL,NULL};+++static void debug(const char *format, ...)+{+ va_list ap;+ va_start(ap, format);+ vfprintf(stderr, format, ap);+ va_end(ap);+}++#if 0+// Replaced by list_append_to_end+static list_t *list_prepend(list_t *root, void *data)+{+ list_t *l = malloc(sizeof(list_t));+ l->next = root;+ l->data = data;+ return l;+}+#endif++// Relies on the root->last being correct. Do not use with the other list_*+// routines unless they are fixed to modify root->last as well.+static list_t *list_append_to_end(list_t *root, void *data)+{+ list_t *l = malloc(sizeof(list_t));+ l->last = l;+ l->next = NULL;+ l->data = data;++ if ( !root )+ return l;++ root->last->next = l;+ root->last = l;+ return root;+}++static list_t *list_append(list_t *root, void *data)+{+ list_t *l = root;+ while (l && l->next)+ l = l->next;+ if ( l ) + {+ l->next = malloc(sizeof(list_t));+ l = l->next;+ }+ else+ {+ l = malloc(sizeof(list_t));+ root = l;+ }+ l->data = data;+ l->next = NULL;+ return root;+}++static void list_free(list_t *root)+{+ list_t *l = root;+ while (root)+ {+ l = root;+ root = root->next;+ free(l);+ }+}++++// Look for a tag "XY" in a predefined const char *[] array.+static int tag_exists(const char *tag, const char **tags)+{+ int itag=0;+ if ( !tags ) return -1;+ while ( tags[itag] )+ {+ if ( tags[itag][0]==tag[0] && tags[itag][1]==tag[1] ) return itag; + itag++;+ }+ return -1;+}++++// Mimics the behaviour of getline, except it returns pointer to the next chunk of the text+// or NULL if everything has been read. The lineptr should be freed by the caller. The+// newline character is stripped.+static const char *nextline(char **lineptr, size_t *n, const char *text)+{+ int len;+ const char *to = text;++ if ( !*to ) return NULL;++ while ( *to && *to!='\n' && *to!='\r' ) to++;+ len = to - text + 1;++ if ( *to )+ {+ // Advance the pointer for the next call+ if ( *to=='\n' ) to++;+ else if ( *to=='\r' && *(to+1)=='\n' ) to+=2;+ }+ if ( !len )+ return to;++ if ( !*lineptr ) + {+ *lineptr = malloc(len);+ *n = len;+ }+ else if ( *n<len ) + {+ *lineptr = realloc(*lineptr, len);+ *n = len;+ }+ if ( !*lineptr ) {+ debug("[nextline] Insufficient memory!\n");+ return 0;+ }++ memcpy(*lineptr,text,len);+ (*lineptr)[len-1] = 0;++ return to;+}++// name points to "XY", value_from points to the first character of the value string and+// value_to points to the last character of the value string.+static HeaderTag *new_tag(const char *name, const char *value_from, const char *value_to)+{+ HeaderTag *tag = malloc(sizeof(HeaderTag));+ int len = value_to-value_from+1;++ tag->key[0] = name[0];+ tag->key[1] = name[1];+ tag->value = malloc(len+1);+ memcpy(tag->value,value_from,len+1);+ tag->value[len] = 0;+ return tag;+}++static HeaderTag *header_line_has_tag(HeaderLine *hline, const char *key)+{+ list_t *tags = hline->tags;+ while (tags)+ {+ HeaderTag *tag = tags->data;+ if ( tag->key[0]==key[0] && tag->key[1]==key[1] ) return tag;+ tags = tags->next;+ }+ return NULL;+}+++// Return codes:+// 0 .. different types or unique tags differ or conflicting tags, cannot be merged+// 1 .. all tags identical -> no need to merge, drop one+// 2 .. the unique tags match and there are some conflicting tags (same tag, different value) -> error, cannot be merged nor duplicated+// 3 .. there are some missing complementary tags and no unique conflict -> can be merged into a single line+static int sam_header_compare_lines(HeaderLine *hline1, HeaderLine *hline2)+{+ HeaderTag *t1, *t2;++ if ( hline1->type[0]!=hline2->type[0] || hline1->type[1]!=hline2->type[1] )+ return 0;++ int itype = tag_exists(hline1->type,types);+ if ( itype==-1 ) {+ debug("[sam_header_compare_lines] Unknown type [%c%c]\n", hline1->type[0],hline1->type[1]);+ return -1; // FIXME (lh3): error; I do not know how this will be handled in Petr's code+ }++ if ( unique_tags[itype] )+ {+ t1 = header_line_has_tag(hline1,unique_tags[itype][0]);+ t2 = header_line_has_tag(hline2,unique_tags[itype][0]);+ if ( !t1 || !t2 ) // this should never happen, the unique tags are required+ return 2;++ if ( strcmp(t1->value,t2->value) )+ return 0; // the unique tags differ, cannot be merged+ }+ if ( !required_tags[itype] && !optional_tags[itype] )+ {+ t1 = hline1->tags->data;+ t2 = hline2->tags->data;+ if ( !strcmp(t1->value,t2->value) ) return 1; // identical comments+ return 0;+ }++ int missing=0, itag=0;+ while ( required_tags[itype] && required_tags[itype][itag] )+ {+ t1 = header_line_has_tag(hline1,required_tags[itype][itag]);+ t2 = header_line_has_tag(hline2,required_tags[itype][itag]);+ if ( !t1 && !t2 )+ return 2; // this should never happen+ else if ( !t1 || !t2 )+ missing = 1; // there is some tag missing in one of the hlines+ else if ( strcmp(t1->value,t2->value) )+ {+ if ( unique_tags[itype] )+ return 2; // the lines have a matching unique tag but have a conflicting tag+ + return 0; // the lines contain conflicting tags, cannot be merged+ }+ itag++;+ }+ itag = 0;+ while ( optional_tags[itype] && optional_tags[itype][itag] )+ {+ t1 = header_line_has_tag(hline1,optional_tags[itype][itag]);+ t2 = header_line_has_tag(hline2,optional_tags[itype][itag]);+ if ( !t1 && !t2 )+ {+ itag++;+ continue;+ }+ if ( !t1 || !t2 )+ missing = 1; // there is some tag missing in one of the hlines+ else if ( strcmp(t1->value,t2->value) )+ {+ if ( unique_tags[itype] )+ return 2; // the lines have a matching unique tag but have a conflicting tag++ return 0; // the lines contain conflicting tags, cannot be merged+ }+ itag++;+ }+ if ( missing ) return 3; // there are some missing complementary tags with no conflicts, can be merged+ return 1;+}+++static HeaderLine *sam_header_line_clone(const HeaderLine *hline)+{+ list_t *tags;+ HeaderLine *out = malloc(sizeof(HeaderLine));+ out->type[0] = hline->type[0];+ out->type[1] = hline->type[1];+ out->tags = NULL;++ tags = hline->tags;+ while (tags)+ {+ HeaderTag *old = tags->data;++ HeaderTag *new = malloc(sizeof(HeaderTag));+ new->key[0] = old->key[0];+ new->key[1] = old->key[1];+ new->value = strdup(old->value);+ out->tags = list_append(out->tags, new);++ tags = tags->next;+ }+ return out;+}++static int sam_header_line_merge_with(HeaderLine *out_hline, const HeaderLine *tmpl_hline)+{+ list_t *tmpl_tags;++ if ( out_hline->type[0]!=tmpl_hline->type[0] || out_hline->type[1]!=tmpl_hline->type[1] )+ return 0;+ + tmpl_tags = tmpl_hline->tags;+ while (tmpl_tags)+ {+ HeaderTag *tmpl_tag = tmpl_tags->data;+ HeaderTag *out_tag = header_line_has_tag(out_hline, tmpl_tag->key);+ if ( !out_tag )+ {+ HeaderTag *tag = malloc(sizeof(HeaderTag));+ tag->key[0] = tmpl_tag->key[0];+ tag->key[1] = tmpl_tag->key[1];+ tag->value = strdup(tmpl_tag->value);+ out_hline->tags = list_append(out_hline->tags,tag);+ }+ tmpl_tags = tmpl_tags->next;+ }+ return 1;+}+++static HeaderLine *sam_header_line_parse(const char *headerLine)+{+ HeaderLine *hline;+ HeaderTag *tag;+ const char *from, *to;+ from = headerLine;++ if ( *from != '@' ) {+ debug("[sam_header_line_parse] expected '@', got [%s]\n", headerLine);+ return 0;+ }+ to = ++from;++ while (*to && *to!='\t') to++;+ if ( to-from != 2 ) {+ debug("[sam_header_line_parse] expected '@XY', got [%s]\nHint: The header tags must be tab-separated.\n", headerLine);+ return 0;+ }+ + hline = malloc(sizeof(HeaderLine));+ hline->type[0] = from[0];+ hline->type[1] = from[1];+ hline->tags = NULL;++ int itype = tag_exists(hline->type, types);+ + from = to;+ while (*to && *to=='\t') to++;+ if ( to-from != 1 ) {+ debug("[sam_header_line_parse] multiple tabs on line [%s] (%d)\n", headerLine,(int)(to-from));+ return 0;+ }+ from = to;+ while (*from)+ {+ while (*to && *to!='\t') to++;++ if ( !required_tags[itype] && !optional_tags[itype] )+ {+ // CO is a special case, it can contain anything, including tabs+ if ( *to ) { to++; continue; }+ tag = new_tag(" ",from,to-1);+ }+ else+ tag = new_tag(from,from+3,to-1);++ if ( header_line_has_tag(hline,tag->key) ) + debug("The tag '%c%c' present (at least) twice on line [%s]\n", tag->key[0],tag->key[1], headerLine);+ hline->tags = list_append(hline->tags, tag);++ from = to;+ while (*to && *to=='\t') to++;+ if ( *to && to-from != 1 ) {+ debug("[sam_header_line_parse] multiple tabs on line [%s] (%d)\n", headerLine,(int)(to-from));+ return 0;+ }++ from = to;+ }+ return hline;+}+++// Must be of an existing type, all tags must be recognised and all required tags must be present+static int sam_header_line_validate(HeaderLine *hline)+{+ list_t *tags;+ HeaderTag *tag;+ int itype, itag;+ + // Is the type correct?+ itype = tag_exists(hline->type, types);+ if ( itype==-1 ) + {+ debug("The type [%c%c] not recognised.\n", hline->type[0],hline->type[1]);+ return 0;+ }++ // Has all required tags?+ itag = 0;+ while ( required_tags[itype] && required_tags[itype][itag] )+ {+ if ( !header_line_has_tag(hline,required_tags[itype][itag]) )+ {+ debug("The tag [%c%c] required for [%c%c] not present.\n", required_tags[itype][itag][0],required_tags[itype][itag][1],+ hline->type[0],hline->type[1]);+ return 0;+ }+ itag++;+ }++ // Are all tags recognised?+ tags = hline->tags;+ while ( tags )+ {+ tag = tags->data;+ if ( !tag_exists(tag->key,required_tags[itype]) && !tag_exists(tag->key,optional_tags[itype]) )+ {+ debug("Unknown tag [%c%c] for [%c%c].\n", tag->key[0],tag->key[1], hline->type[0],hline->type[1]);+ return 0;+ }+ tags = tags->next;+ }++ return 1;+}+++static void print_header_line(FILE *fp, HeaderLine *hline)+{+ list_t *tags = hline->tags;+ HeaderTag *tag;++ fprintf(fp, "@%c%c", hline->type[0],hline->type[1]);+ while (tags)+ {+ tag = tags->data;++ fprintf(fp, "\t");+ if ( tag->key[0]!=' ' || tag->key[1]!=' ' )+ fprintf(fp, "%c%c:", tag->key[0],tag->key[1]);+ fprintf(fp, "%s", tag->value);++ tags = tags->next;+ }+ fprintf(fp,"\n");+}+++static void sam_header_line_free(HeaderLine *hline)+{+ list_t *tags = hline->tags;+ while (tags)+ {+ HeaderTag *tag = tags->data;+ free(tag->value);+ free(tag);+ tags = tags->next;+ }+ list_free(hline->tags);+ free(hline);+}++void sam_header_free(void *_header)+{+ HeaderDict *header = (HeaderDict*)_header;+ list_t *hlines = header;+ while (hlines)+ {+ sam_header_line_free(hlines->data);+ hlines = hlines->next;+ }+ list_free(header);+}++HeaderDict *sam_header_clone(const HeaderDict *dict)+{+ HeaderDict *out = NULL;+ while (dict)+ {+ HeaderLine *hline = dict->data;+ out = list_append(out, sam_header_line_clone(hline));+ dict = dict->next;+ }+ return out;+}++// Returns a newly allocated string+char *sam_header_write(const void *_header)+{+ const HeaderDict *header = (const HeaderDict*)_header;+ char *out = NULL;+ int len=0, nout=0;+ const list_t *hlines;++ // Calculate the length of the string to allocate+ hlines = header;+ while (hlines)+ {+ len += 4; // @XY and \n++ HeaderLine *hline = hlines->data;+ list_t *tags = hline->tags;+ while (tags)+ {+ HeaderTag *tag = tags->data;+ len += strlen(tag->value) + 1; // \t+ if ( tag->key[0]!=' ' || tag->key[1]!=' ' )+ len += strlen(tag->value) + 3; // XY:+ tags = tags->next;+ }+ hlines = hlines->next;+ }++ nout = 0;+ out = malloc(len+1);+ hlines = header;+ while (hlines)+ {+ HeaderLine *hline = hlines->data;++ nout += sprintf(out+nout,"@%c%c",hline->type[0],hline->type[1]);++ list_t *tags = hline->tags;+ while (tags)+ {+ HeaderTag *tag = tags->data;+ nout += sprintf(out+nout,"\t");+ if ( tag->key[0]!=' ' || tag->key[1]!=' ' )+ nout += sprintf(out+nout,"%c%c:", tag->key[0],tag->key[1]);+ nout += sprintf(out+nout,"%s", tag->value);+ tags = tags->next;+ }+ hlines = hlines->next;+ nout += sprintf(out+nout,"\n");+ }+ out[len] = 0;+ return out;+}++void *sam_header_parse2(const char *headerText)+{+ list_t *hlines = NULL;+ HeaderLine *hline;+ const char *text;+ char *buf=NULL;+ size_t nbuf = 0;+ int tovalidate = 0;++ if ( !headerText )+ return 0;++ text = headerText;+ while ( (text=nextline(&buf, &nbuf, text)) )+ {+ hline = sam_header_line_parse(buf);+ if ( hline && (!tovalidate || sam_header_line_validate(hline)) )+ // With too many (~250,000) reference sequences the header parsing was too slow with list_append.+ hlines = list_append_to_end(hlines, hline);+ else+ {+ if (hline) sam_header_line_free(hline);+ sam_header_free(hlines);+ if ( buf ) free(buf);+ return NULL;+ }+ }+ if ( buf ) free(buf);++ return hlines;+}++void *sam_header2tbl(const void *_dict, char type[2], char key_tag[2], char value_tag[2])+{+ const HeaderDict *dict = (const HeaderDict*)_dict;+ const list_t *l = dict;+ khash_t(str) *tbl = kh_init(str);+ khiter_t k;+ int ret;++ if (_dict == 0) return tbl; // return an empty (not null) hash table+ while (l)+ {+ HeaderLine *hline = l->data;+ if ( hline->type[0]!=type[0] || hline->type[1]!=type[1] ) + {+ l = l->next;+ continue;+ }+ + HeaderTag *key, *value;+ key = header_line_has_tag(hline,key_tag);+ value = header_line_has_tag(hline,value_tag); + if ( !key || !value )+ {+ l = l->next;+ continue;+ }+ + k = kh_get(str, tbl, key->value);+ if ( k != kh_end(tbl) )+ debug("[sam_header_lookup_table] They key %s not unique.\n", key->value);+ k = kh_put(str, tbl, key->value, &ret);+ kh_value(tbl, k) = value->value;++ l = l->next;+ }+ return tbl;+}++char **sam_header2list(const void *_dict, char type[2], char key_tag[2], int *_n)+{+ const HeaderDict *dict = (const HeaderDict*)_dict;+ const list_t *l = dict;+ int max, n;+ char **ret;++ ret = 0; *_n = max = n = 0;+ while (l)+ {+ HeaderLine *hline = l->data;+ if ( hline->type[0]!=type[0] || hline->type[1]!=type[1] ) + {+ l = l->next;+ continue;+ }+ + HeaderTag *key;+ key = header_line_has_tag(hline,key_tag);+ if ( !key )+ {+ l = l->next;+ continue;+ }++ if (n == max) {+ max = max? max<<1 : 4;+ ret = realloc(ret, max * sizeof(void*));+ }+ ret[n++] = key->value;++ l = l->next;+ }+ *_n = n;+ return ret;+}++const char *sam_tbl_get(void *h, const char *key)+{+ khash_t(str) *tbl = (khash_t(str)*)h;+ khint_t k;+ k = kh_get(str, tbl, key);+ return k == kh_end(tbl)? 0 : kh_val(tbl, k);+}++int sam_tbl_size(void *h)+{+ khash_t(str) *tbl = (khash_t(str)*)h;+ return h? kh_size(tbl) : 0;+}++void sam_tbl_destroy(void *h)+{+ khash_t(str) *tbl = (khash_t(str)*)h;+ kh_destroy(str, tbl);+}++void *sam_header_merge(int n, const void **_dicts)+{+ const HeaderDict **dicts = (const HeaderDict**)_dicts;+ HeaderDict *out_dict;+ int idict, status;++ if ( n<2 ) return NULL;++ out_dict = sam_header_clone(dicts[0]);++ for (idict=1; idict<n; idict++)+ {+ const list_t *tmpl_hlines = dicts[idict];++ while ( tmpl_hlines )+ {+ list_t *out_hlines = out_dict;+ int inserted = 0;+ while ( out_hlines )+ {+ status = sam_header_compare_lines(tmpl_hlines->data, out_hlines->data);+ if ( status==0 )+ {+ out_hlines = out_hlines->next;+ continue;+ }+ + if ( status==2 ) + {+ print_header_line(stderr,tmpl_hlines->data);+ print_header_line(stderr,out_hlines->data);+ debug("Conflicting lines, cannot merge the headers.\n");+ return 0;+ }+ if ( status==3 )+ sam_header_line_merge_with(out_hlines->data, tmpl_hlines->data);++ inserted = 1;+ break;+ }+ if ( !inserted )+ out_dict = list_append(out_dict, sam_header_line_clone(tmpl_hlines->data));++ tmpl_hlines = tmpl_hlines->next;+ }+ }++ return out_dict;+}++
+ samtools-0.1.18/sam_header.h view
@@ -0,0 +1,24 @@+#ifndef __SAM_HEADER_H__+#define __SAM_HEADER_H__++#ifdef __cplusplus+extern "C" {+#endif++ void *sam_header_parse2(const char *headerText);+ void *sam_header_merge(int n, const void **dicts);+ void sam_header_free(void *header);+ char *sam_header_write(const void *headerDict); // returns a newly allocated string++ char **sam_header2list(const void *_dict, char type[2], char key_tag[2], int *_n);++ void *sam_header2tbl(const void *dict, char type[2], char key_tag[2], char value_tag[2]);+ const char *sam_tbl_get(void *h, const char *key);+ int sam_tbl_size(void *h);+ void sam_tbl_destroy(void *h);++#ifdef __cplusplus+}+#endif++#endif
samtools.cabal view
@@ -1,5 +1,5 @@ Name: samtools-Version: 0.1.3+Version: 0.2 Synopsis: Binding to the C samtools library Description: Binding to the C samtools library, which reads and writes SAM format alignments, both binary and tab-@@ -17,13 +17,13 @@ Cabal-version: >=1.4 Extra-source-files: cbits/samtools.c, include/samtools.h,- samtools-0.1.13/bgzf.c, samtools-0.1.13/kstring.c, samtools-0.1.13/bam_aux.c, - samtools-0.1.13/bam.c, samtools-0.1.13/bam_import.c, samtools-0.1.13/sam.c,- samtools-0.1.13/bam_index.c, samtools-0.1.13/bam_pileup.c, samtools-0.1.13/bam_lpileup.c,- samtools-0.1.13/bam_md.c, samtools-0.1.13/glf.c, samtools-0.1.13/razf.c,- samtools-0.1.13/faidx.c, samtools-0.1.13/knetfile.c, samtools-0.1.13/bam_sort.c,- samtools-0.1.13/sam_header.c, samtools-0.1.13/bam_reheader.c, samtools-0.1.13/kprobaln.c,- samtools-0.1.13/bam_maqcns.c, samtools-0.1.13/errmod.c, samtools-0.1.13/kaln.c+ samtools-0.1.18/bgzf.c, samtools-0.1.18/kstring.c, samtools-0.1.18/bam_aux.c, + samtools-0.1.18/bam.c, samtools-0.1.18/bam_import.c, samtools-0.1.18/sam.c,+ samtools-0.1.18/bam_index.c, samtools-0.1.18/bam_pileup.c, samtools-0.1.18/bam_lpileup.c,+ samtools-0.1.18/bam_md.c, samtools-0.1.18/razf.c,+ samtools-0.1.18/faidx.c, samtools-0.1.18/knetfile.c, samtools-0.1.18/bam_sort.c,+ samtools-0.1.18/sam_header.c, samtools-0.1.18/bam_reheader.c, samtools-0.1.18/kprobaln.c,+ samtools-0.1.18/errmod.c, samtools-0.1.18/kaln.c Flag Tests Description: Build test program@@ -33,25 +33,25 @@ Exposed-modules: Bio.SamTools.Bam, Bio.SamTools.Cigar, Bio.SamTools.BamIndex, Bio.SamTools.FaIdx Other-modules: Bio.SamTools.LowLevel, Bio.SamTools.Internal, C2HS- Build-depends: base >= 4.2 && < 5, bytestring, haskell98, vector >= 0.7, seqloc+ Build-depends: base >= 4.2 && < 5, bytestring, haskell98, vector >= 0.7, seqloc >= 0.3.1 Hs-Source-Dirs: src Build-tools: c2hs- Include-dirs: samtools-0.1.13, include+ Include-dirs: samtools-0.1.18, include C-sources: cbits/samtools.c, - samtools-0.1.13/bgzf.c, samtools-0.1.13/kstring.c, samtools-0.1.13/bam_aux.c, - samtools-0.1.13/bam.c, samtools-0.1.13/bam_import.c, samtools-0.1.13/sam.c,- samtools-0.1.13/bam_index.c, samtools-0.1.13/bam_pileup.c, samtools-0.1.13/bam_lpileup.c,- samtools-0.1.13/bam_md.c, samtools-0.1.13/glf.c, samtools-0.1.13/razf.c,- samtools-0.1.13/faidx.c, samtools-0.1.13/knetfile.c, samtools-0.1.13/bam_sort.c,- samtools-0.1.13/sam_header.c, samtools-0.1.13/bam_reheader.c, samtools-0.1.13/kprobaln.c,- samtools-0.1.13/bam_maqcns.c, samtools-0.1.13/errmod.c, samtools-0.1.13/kaln.c+ samtools-0.1.18/bgzf.c, samtools-0.1.18/kstring.c, samtools-0.1.18/bam_aux.c, + samtools-0.1.18/bam.c, samtools-0.1.18/bam_import.c, samtools-0.1.18/sam.c,+ samtools-0.1.18/bam_index.c, samtools-0.1.18/bam_pileup.c, samtools-0.1.18/bam_lpileup.c,+ samtools-0.1.18/bam_md.c, samtools-0.1.18/razf.c,+ samtools-0.1.18/faidx.c, samtools-0.1.18/knetfile.c, samtools-0.1.18/bam_sort.c,+ samtools-0.1.18/sam_header.c, samtools-0.1.18/bam_reheader.c, samtools-0.1.18/kprobaln.c,+ samtools-0.1.18/errmod.c, samtools-0.1.18/kaln.c Install-includes: include/samtools.h,- samtools-0.1.13/bam.h, samtools-0.1.13/bam_endian.h, samtools-0.1.13/faidx.h, - samtools-0.1.13/glf.h, samtools-0.1.13/khash.h,- samtools-0.1.13/kseq.h, samtools-0.1.13/ksort.h, samtools-0.1.13/kstring.h,- samtools-0.1.13/razf.h, samtools-0.1.13/sam.h, samtools-0.1.13/sam_header.h,- samtools-0.1.13/bgzf.h, samtools-0.1.13/knetfile.h, samtools-0.1.13/kaln.h,- samtools-0.1.13/kprobaln.h, samtools-0.1.13/bam_maqcns.h, samtools-0.1.13/errmod.h+ samtools-0.1.18/bam.h, samtools-0.1.18/bam_endian.h, samtools-0.1.18/faidx.h, + samtools-0.1.18/khash.h,+ samtools-0.1.18/kseq.h, samtools-0.1.18/ksort.h, samtools-0.1.18/kstring.h,+ samtools-0.1.18/razf.h, samtools-0.1.18/sam.h, samtools-0.1.18/sam_header.h,+ samtools-0.1.18/bgzf.h, samtools-0.1.18/knetfile.h, samtools-0.1.18/kaln.h,+ samtools-0.1.18/kprobaln.h, samtools-0.1.18/errmod.h CC-options: -g -D_FILE_OFFSET_BITS=64 -D_USE_KNETFILE Extra-libraries: z Ghc-options: -Wall@@ -63,25 +63,25 @@ Other-modules: Bio.SamTools.Bam, Bio.SamTools.Cigar, Bio.SamTools.BamIndex, Bio.SamTools.FaIdx, Bio.SamTools.LowLevel, Bio.SamTools.Internal, C2HS- Build-depends: base >= 4.2 && < 5, bytestring, haskell98, vector >= 0.7, seqloc, process, filepath+ Build-depends: base >= 4.2 && < 5, bytestring, haskell98, vector >= 0.7, seqloc >= 0.3.1, process, filepath Hs-Source-Dirs: src, test Build-tools: c2hs- Include-dirs: samtools-0.1.13, include+ Include-dirs: samtools-0.1.18, include C-sources: cbits/samtools.c, - samtools-0.1.13/bgzf.c, samtools-0.1.13/kstring.c, samtools-0.1.13/bam_aux.c, - samtools-0.1.13/bam.c, samtools-0.1.13/bam_import.c, samtools-0.1.13/sam.c,- samtools-0.1.13/bam_index.c, samtools-0.1.13/bam_pileup.c, samtools-0.1.13/bam_lpileup.c,- samtools-0.1.13/bam_md.c, samtools-0.1.13/glf.c, samtools-0.1.13/razf.c,- samtools-0.1.13/faidx.c, samtools-0.1.13/knetfile.c, samtools-0.1.13/bam_sort.c,- samtools-0.1.13/sam_header.c, samtools-0.1.13/bam_reheader.c, samtools-0.1.13/kprobaln.c,- samtools-0.1.13/bam_maqcns.c, samtools-0.1.13/errmod.c, samtools-0.1.13/kaln.c+ samtools-0.1.18/bgzf.c, samtools-0.1.18/kstring.c, samtools-0.1.18/bam_aux.c, + samtools-0.1.18/bam.c, samtools-0.1.18/bam_import.c, samtools-0.1.18/sam.c,+ samtools-0.1.18/bam_index.c, samtools-0.1.18/bam_pileup.c, samtools-0.1.18/bam_lpileup.c,+ samtools-0.1.18/bam_md.c, samtools-0.1.18/razf.c,+ samtools-0.1.18/faidx.c, samtools-0.1.18/knetfile.c, samtools-0.1.18/bam_sort.c,+ samtools-0.1.18/sam_header.c, samtools-0.1.18/bam_reheader.c, samtools-0.1.18/kprobaln.c,+ samtools-0.1.18/errmod.c, samtools-0.1.18/kaln.c Install-includes: include/samtools.h,- samtools-0.1.13/bam.h, samtools-0.1.13/bam_endian.h, samtools-0.1.13/faidx.h, - samtools-0.1.13/glf.h, samtools-0.1.13/khash.h,- samtools-0.1.13/kseq.h, samtools-0.1.13/ksort.h, samtools-0.1.13/kstring.h,- samtools-0.1.13/razf.h, samtools-0.1.13/sam.h, samtools-0.1.13/sam_header.h,- samtools-0.1.13/bgzf.h, samtools-0.1.13/knetfile.h, samtools-0.1.13/kaln.h,- samtools-0.1.13/kprobaln.h, samtools-0.1.13/bam_maqcns.h, samtools-0.1.13/errmod.h+ samtools-0.1.18/bam.h, samtools-0.1.18/bam_endian.h, samtools-0.1.18/faidx.h, + samtools-0.1.18/khash.h,+ samtools-0.1.18/kseq.h, samtools-0.1.18/ksort.h, samtools-0.1.18/kstring.h,+ samtools-0.1.18/razf.h, samtools-0.1.18/sam.h, samtools-0.1.18/sam_header.h,+ samtools-0.1.18/bgzf.h, samtools-0.1.18/knetfile.h, samtools-0.1.18/kaln.h,+ samtools-0.1.18/kprobaln.h, samtools-0.1.18/errmod.h CC-options: -g -D_FILE_OFFSET_BITS=64 -D_USE_KNETFILE Extra-libraries: z Ghc-options: -Wall
src/Bio/SamTools/Bam.hs view
@@ -261,12 +261,12 @@ refSpLoc :: Bam1 -> Maybe SpLoc.SpliceLoc refSpLoc b | isUnmap b = Nothing | otherwise = liftM (stranded strand) $! liftM2 (cigarToSpLoc) (position b) (Just . cigars $ b)- where strand = if isReverse b then RevCompl else Fwd+ where strand = if isReverse b then Minus else Plus -- | 'Just' the reference sequence location (as per 'refSpLoc') on -- the target reference (as per 'targetName') refSeqLoc :: Bam1 -> Maybe SpliceSeqLoc-refSeqLoc b = liftM2 OnSeq (liftM SeqName $! targetName b) (refSpLoc b)+refSeqLoc b = liftM2 OnSeq (liftM toSeqLabel $! targetName b) (refSpLoc b) -- | Handle for reading SAM/BAM format alignments data InHandle = InHandle { inFilename :: !FilePath
src/Bio/SamTools/Cigar.hs view
@@ -75,7 +75,7 @@ entry start (Cigar SoftClip _len) = (start, Nothing) entry start (Cigar HardClip _len) = (start, Nothing) entry start (Cigar Pad _len) = (start, Nothing)- contig start len = Just $! Loc.fromBoundsStrand (fromIntegral start) (fromIntegral $ start + len - 1) Fwd+ contig start len = Just $! Loc.fromBoundsStrand (fromIntegral start) (fromIntegral $ start + len - 1) Plus mergeAdj :: Loc.ContigLoc -> [Loc.ContigLoc] -> [Loc.ContigLoc] mergeAdj cprev [] = [cprev]@@ -97,4 +97,4 @@ , zip (poses read0 len) (repeat Nothing)) cigarStep (read0, ref0) (Cigar HardClip _len) = ((read0, ref0), []) cigarStep (read0, ref0) (Cigar Pad _len) = ((read0, ref0), [])- poses start len = [ Just $! Pos.Pos (fromIntegral $ start + i) Fwd | i <- [0..(len-1)] ]+ poses start len = [ Just $! Pos.Pos (fromIntegral $ start + i) Plus | i <- [0..(len-1)] ]
src/Bio/SamTools/FaIdx.hs view
@@ -65,8 +65,8 @@ return sout fetchContig :: InHandle -> OnSeq Loc.ContigLoc -> IO (Maybe BS.ByteString)-fetchContig inh (OnSeq (SeqName name) cl) - = liftM result $ fetch inh name intbounds+fetchContig inh (OnSeq name cl) + = liftM result $ fetch inh (unSeqLabel name) intbounds where intbounds = (fromIntegral *** fromIntegral) $ Loc.bounds cl result sequ | BS.null sequ = Nothing | otherwise = return $! stranded (Loc.strand cl) sequ