annotate pyPRADA_1.2/tools/samtools-0.1.16/bam_lpileup.c @ 0:acc2ca1a3ba4

Uploaded
author siyuan
date Thu, 20 Feb 2014 00:44:58 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
1 #include <stdlib.h>
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
2 #include <stdio.h>
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
3 #include <assert.h>
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
4 #include "bam.h"
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
5 #include "ksort.h"
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
6
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
7 #define TV_GAP 2
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
8
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
9 typedef struct __freenode_t {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
10 uint32_t level:28, cnt:4;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
11 struct __freenode_t *next;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
12 } freenode_t, *freenode_p;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
13
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
14 #define freenode_lt(a,b) ((a)->cnt < (b)->cnt || ((a)->cnt == (b)->cnt && (a)->level < (b)->level))
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
15 KSORT_INIT(node, freenode_p, freenode_lt)
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
16
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
17 /* Memory pool, similar to the one in bam_pileup.c */
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
18 typedef struct {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
19 int cnt, n, max;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
20 freenode_t **buf;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
21 } mempool_t;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
22
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
23 static mempool_t *mp_init()
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
24 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
25 return (mempool_t*)calloc(1, sizeof(mempool_t));
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
26 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
27 static void mp_destroy(mempool_t *mp)
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
28 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
29 int k;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
30 for (k = 0; k < mp->n; ++k) free(mp->buf[k]);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
31 free(mp->buf); free(mp);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
32 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
33 static inline freenode_t *mp_alloc(mempool_t *mp)
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
34 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
35 ++mp->cnt;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
36 if (mp->n == 0) return (freenode_t*)calloc(1, sizeof(freenode_t));
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
37 else return mp->buf[--mp->n];
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
38 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
39 static inline void mp_free(mempool_t *mp, freenode_t *p)
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
40 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
41 --mp->cnt; p->next = 0; p->cnt = TV_GAP;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
42 if (mp->n == mp->max) {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
43 mp->max = mp->max? mp->max<<1 : 256;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
44 mp->buf = (freenode_t**)realloc(mp->buf, sizeof(freenode_t*) * mp->max);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
45 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
46 mp->buf[mp->n++] = p;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
47 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
48
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
49 /* core part */
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
50 struct __bam_lplbuf_t {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
51 int max, n_cur, n_pre;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
52 int max_level, *cur_level, *pre_level;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
53 mempool_t *mp;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
54 freenode_t **aux, *head, *tail;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
55 int n_nodes, m_aux;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
56 bam_pileup_f func;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
57 void *user_data;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
58 bam_plbuf_t *plbuf;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
59 };
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
60
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
61 void bam_lplbuf_reset(bam_lplbuf_t *buf)
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
62 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
63 freenode_t *p, *q;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
64 bam_plbuf_reset(buf->plbuf);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
65 for (p = buf->head; p->next;) {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
66 q = p->next;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
67 mp_free(buf->mp, p);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
68 p = q;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
69 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
70 buf->head = buf->tail;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
71 buf->max_level = 0;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
72 buf->n_cur = buf->n_pre = 0;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
73 buf->n_nodes = 0;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
74 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
75
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
76 static int tview_func(uint32_t tid, uint32_t pos, int n, const bam_pileup1_t *pl, void *data)
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
77 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
78 bam_lplbuf_t *tv = (bam_lplbuf_t*)data;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
79 freenode_t *p;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
80 int i, l, max_level;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
81 // allocate memory if necessary
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
82 if (tv->max < n) { // enlarge
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
83 tv->max = n;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
84 kroundup32(tv->max);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
85 tv->cur_level = (int*)realloc(tv->cur_level, sizeof(int) * tv->max);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
86 tv->pre_level = (int*)realloc(tv->pre_level, sizeof(int) * tv->max);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
87 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
88 tv->n_cur = n;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
89 // update cnt
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
90 for (p = tv->head; p->next; p = p->next)
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
91 if (p->cnt > 0) --p->cnt;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
92 // calculate cur_level[]
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
93 max_level = 0;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
94 for (i = l = 0; i < n; ++i) {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
95 const bam_pileup1_t *p = pl + i;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
96 if (p->is_head) {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
97 if (tv->head->next && tv->head->cnt == 0) { // then take a free slot
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
98 freenode_t *p = tv->head->next;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
99 tv->cur_level[i] = tv->head->level;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
100 mp_free(tv->mp, tv->head);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
101 tv->head = p;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
102 --tv->n_nodes;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
103 } else tv->cur_level[i] = ++tv->max_level;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
104 } else {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
105 tv->cur_level[i] = tv->pre_level[l++];
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
106 if (p->is_tail) { // then return a free slot
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
107 tv->tail->level = tv->cur_level[i];
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
108 tv->tail->next = mp_alloc(tv->mp);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
109 tv->tail = tv->tail->next;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
110 ++tv->n_nodes;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
111 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
112 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
113 if (tv->cur_level[i] > max_level) max_level = tv->cur_level[i];
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
114 ((bam_pileup1_t*)p)->level = tv->cur_level[i];
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
115 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
116 assert(l == tv->n_pre);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
117 tv->func(tid, pos, n, pl, tv->user_data);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
118 // sort the linked list
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
119 if (tv->n_nodes) {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
120 freenode_t *q;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
121 if (tv->n_nodes + 1 > tv->m_aux) { // enlarge
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
122 tv->m_aux = tv->n_nodes + 1;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
123 kroundup32(tv->m_aux);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
124 tv->aux = (freenode_t**)realloc(tv->aux, sizeof(void*) * tv->m_aux);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
125 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
126 for (p = tv->head, i = l = 0; p->next;) {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
127 if (p->level > max_level) { // then discard this entry
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
128 q = p->next;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
129 mp_free(tv->mp, p);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
130 p = q;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
131 } else {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
132 tv->aux[i++] = p;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
133 p = p->next;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
134 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
135 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
136 tv->aux[i] = tv->tail; // add a proper tail for the loop below
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
137 tv->n_nodes = i;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
138 if (tv->n_nodes) {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
139 ks_introsort(node, tv->n_nodes, tv->aux);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
140 for (i = 0; i < tv->n_nodes; ++i) tv->aux[i]->next = tv->aux[i+1];
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
141 tv->head = tv->aux[0];
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
142 } else tv->head = tv->tail;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
143 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
144 // clean up
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
145 tv->max_level = max_level;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
146 memcpy(tv->pre_level, tv->cur_level, tv->n_cur * 4);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
147 // squeeze out terminated levels
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
148 for (i = l = 0; i < n; ++i) {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
149 const bam_pileup1_t *p = pl + i;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
150 if (!p->is_tail)
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
151 tv->pre_level[l++] = tv->pre_level[i];
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
152 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
153 tv->n_pre = l;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
154 /*
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
155 fprintf(stderr, "%d\t", pos+1);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
156 for (i = 0; i < n; ++i) {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
157 const bam_pileup1_t *p = pl + i;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
158 if (p->is_head) fprintf(stderr, "^");
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
159 if (p->is_tail) fprintf(stderr, "$");
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
160 fprintf(stderr, "%d,", p->level);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
161 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
162 fprintf(stderr, "\n");
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
163 */
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
164 return 0;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
165 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
166
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
167 bam_lplbuf_t *bam_lplbuf_init(bam_pileup_f func, void *data)
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
168 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
169 bam_lplbuf_t *tv;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
170 tv = (bam_lplbuf_t*)calloc(1, sizeof(bam_lplbuf_t));
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
171 tv->mp = mp_init();
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
172 tv->head = tv->tail = mp_alloc(tv->mp);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
173 tv->func = func;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
174 tv->user_data = data;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
175 tv->plbuf = bam_plbuf_init(tview_func, tv);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
176 return (bam_lplbuf_t*)tv;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
177 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
178
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
179 void bam_lplbuf_destroy(bam_lplbuf_t *tv)
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
180 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
181 freenode_t *p, *q;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
182 free(tv->cur_level); free(tv->pre_level);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
183 bam_plbuf_destroy(tv->plbuf);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
184 free(tv->aux);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
185 for (p = tv->head; p->next;) {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
186 q = p->next;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
187 mp_free(tv->mp, p); p = q;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
188 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
189 mp_free(tv->mp, p);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
190 assert(tv->mp->cnt == 0);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
191 mp_destroy(tv->mp);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
192 free(tv);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
193 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
194
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
195 int bam_lplbuf_push(const bam1_t *b, bam_lplbuf_t *tv)
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
196 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
197 return bam_plbuf_push(b, tv->plbuf);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
198 }