forked from georgek/bio-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbambaseatpos.c
155 lines (136 loc) · 3.79 KB
/
bambaseatpos.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
#include <bam/bam.h>
#include <bam/sam.h>
struct pos_data {
uint32_t tid;
uint32_t pos;
char base;
samfile_t *output;
};
/* callback for bam_fetch() */
static int fetch_func(const bam1_t *b, void *data)
{
bam_plbuf_t *buf = data;
bam_plbuf_push(b, buf);
return 0;
}
static int bambasetable[] = {-1, 'a', 'c', -1, 'g', -1, -1, -1, 't'};
/* callback for bam_plbuf_init() */
static int pileup_func_base(uint32_t tid, uint32_t pos, int n,
const bam_pileup1_t *pl, void *data)
{
struct pos_data *p = data;
size_t i;
int posbase;
if (p->tid == tid && p->pos == pos) {
for (i = 0; i < n; ++i) {
posbase = bam1_seqi(bam1_seq(pl[i].b), pl[i].qpos);
if (!pl[i].is_del && p->base == bambasetable[posbase]) {
samwrite(p->output, pl[i].b);
}
}
}
return 0;
}
static int pileup_func_del(uint32_t tid, uint32_t pos, int n,
const bam_pileup1_t *pl, void *data)
{
struct pos_data *p = data;
size_t i;
if (p->tid == tid && p->pos == pos) {
for (i = 0; i < n; ++i) {
if (pl[i].is_del) {
samwrite(p->output, pl[i].b);
}
}
}
return 0;
}
static int pileup_func_ins(uint32_t tid, uint32_t pos, int n,
const bam_pileup1_t *pl, void *data)
{
struct pos_data *p = data;
size_t i;
if (p->tid == tid && p->pos == pos) {
for (i = 0; i < n; ++i) {
if (pl[i].indel > 0) {
samwrite(p->output, pl[i].b);
}
}
}
return 0;
}
int main(int argc, char *argv[])
{
char *progname;
char *bamfilename;
struct pos_data p;
char *outputname;
samfile_t *bamin;
bam_index_t *bamidx;
bam_plbuf_t *buf;
bam_header_t *header;
progname = *argv;
argv++; argc--;
if (argc < 5) {
printf("Usage: %s bam_file chromosome_id position base output\n",
progname);
exit(-1);
}
else {
bamfilename = argv[0];
p.tid = strtoul(argv[1], NULL, 10) - 1;
p.pos = strtoul(argv[2], NULL, 10) - 1;
p.base = tolower(*argv[3]);
outputname = argv[4];
}
/* try to open bam file */
bamin = samopen(bamfilename, "rb", NULL);
if (!bamin) {
fprintf(stderr, "Error opening bamfile %s\n", bamfilename);
exit(-1);
}
/* try to open index */
bamidx = bam_index_load(bamfilename);
if (!bamidx) {
fprintf(stderr, "Error opening index for %s\n"
"(Run samtools index first)\n",
bamfilename);
exit(-1);
}
/* try to open output */
header = bamin->header;
p.output = samopen(outputname, "w", header);
if (!p.output) {
fprintf(stderr, "Error opening output %s\n", outputname);
exit(-1);
}
if (p.output->type == 0) {
fprintf(p.output->x.tamw, "%s", header->text);
}
switch(p.base) {
case 'i':
buf = bam_plbuf_init(&pileup_func_ins, &p);
break;
case 'd':
buf = bam_plbuf_init(&pileup_func_del, &p);
break;
default:
buf = bam_plbuf_init(&pileup_func_base, &p);
break;
}
/* disable maximum pileup depth */
bam_plp_set_maxcnt(buf->iter, INT_MAX);
bam_fetch(bamin->x.bam, bamidx,
p.tid, p.pos, p.pos+1,
buf, &fetch_func);
bam_plbuf_push(0, buf); /* finish pileup */
bam_plbuf_destroy(buf);
bam_index_destroy(bamidx);
samclose(bamin);
samclose(p.output);
return 0;
}