0
|
1 /* test/test_view.c -- simple view tool, purely for use in a test harness.
|
|
2
|
|
3 Copyright (C) 2012 Broad Institute.
|
|
4 Copyright (C) 2013-2014 Genome Research Ltd.
|
|
5
|
|
6 Author: Heng Li <lh3@sanger.ac.uk>
|
|
7
|
|
8 Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9 of this software and associated documentation files (the "Software"), to deal
|
|
10 in the Software without restriction, including without limitation the rights
|
|
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12 copies of the Software, and to permit persons to whom the Software is
|
|
13 furnished to do so, subject to the following conditions:
|
|
14
|
|
15 The above copyright notice and this permission notice shall be included in
|
|
16 all copies or substantial portions of the Software.
|
|
17
|
|
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
21 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
23 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
24 DEALINGS IN THE SOFTWARE. */
|
|
25
|
|
26 #include <stdio.h>
|
|
27 #include <unistd.h>
|
|
28 #include <stdlib.h>
|
|
29 #include <string.h>
|
|
30
|
|
31 #include "cram/cram.h"
|
|
32
|
|
33 #include "htslib/sam.h"
|
|
34
|
|
35 typedef struct hts_opt {
|
|
36 enum cram_option opt;
|
|
37 union {
|
|
38 int i;
|
|
39 char *s;
|
|
40 } val;
|
|
41 struct hts_opt *next;
|
|
42 } hts_opt;
|
|
43
|
|
44 /*
|
|
45 * Parses arg and appends it to the option list.
|
|
46 * Returns 0 on success;
|
|
47 * -1 on failure.
|
|
48 */
|
|
49 int add_option(hts_opt **opts, char *arg) {
|
|
50 hts_opt *o, *t;
|
|
51 char *cp;
|
|
52
|
|
53 if (!(cp = strchr(arg, '=')))
|
|
54 cp = "1"; // assume boolean
|
|
55 else
|
|
56 *cp++ = 0;
|
|
57
|
|
58 if (!(o = malloc(sizeof(*o))))
|
|
59 return -1;
|
|
60
|
|
61 if (strcmp(arg, "DECODE_MD") == 0)
|
|
62 o->opt = CRAM_OPT_DECODE_MD, o->val.i = atoi(cp);
|
|
63 else if (strcmp(arg, "VERBOSITY") == 0)
|
|
64 o->opt = CRAM_OPT_VERBOSITY, o->val.i = atoi(cp);
|
|
65 else if (strcmp(arg, "SEQS_PER_SLICE") == 0)
|
|
66 o->opt = CRAM_OPT_SEQS_PER_SLICE, o->val.i = atoi(cp);
|
|
67 else if (strcmp(arg, "SLICES_PER_CONTAINER") == 0)
|
|
68 o->opt = CRAM_OPT_SLICES_PER_CONTAINER, o->val.i = atoi(cp);
|
|
69 else if (strcmp(arg, "EMBED_REF") == 0)
|
|
70 o->opt = CRAM_OPT_EMBED_REF, o->val.i = atoi(cp);
|
|
71 else if (strcmp(arg, "NO_REF") == 0)
|
|
72 o->opt = CRAM_OPT_NO_REF, o->val.i = atoi(cp);
|
|
73 else if (strcmp(arg, "IGNORE_MD5") == 0)
|
|
74 o->opt = CRAM_OPT_IGNORE_MD5, o->val.i = atoi(cp);
|
|
75 else if (strcmp(arg, "USE_BZIP2") == 0)
|
|
76 o->opt = CRAM_OPT_USE_BZIP2, o->val.i = atoi(cp);
|
|
77 else if (strcmp(arg, "USE_RANS") == 0)
|
|
78 o->opt = CRAM_OPT_USE_RANS, o->val.i = atoi(cp);
|
|
79 else if (strcmp(arg, "USE_LZMA") == 0)
|
|
80 o->opt = CRAM_OPT_USE_LZMA, o->val.i = atoi(cp);
|
|
81 else if (strcmp(arg, "REFERENCE") == 0)
|
|
82 o->opt = CRAM_OPT_REFERENCE, o->val.s = cp;
|
|
83 else if (strcmp(arg, "VERSION") == 0)
|
|
84 o->opt = CRAM_OPT_VERSION, o->val.s =cp;
|
|
85 else if (strcmp(arg, "MULTI_SEQ_PER_SLICE") == 0)
|
|
86 o->opt = CRAM_OPT_MULTI_SEQ_PER_SLICE, o->val.i = atoi(cp);
|
|
87 else if (strcmp(arg, "NTHREADS") == 0)
|
|
88 o->opt = CRAM_OPT_NTHREADS, o->val.i = atoi(cp);
|
|
89 else if (strcmp(arg, "REQUIRED_FIELDS") == 0)
|
|
90 o->opt = CRAM_OPT_REQUIRED_FIELDS, o->val.i = strtol(cp, NULL, 0);
|
|
91 else {
|
|
92 fprintf(stderr, "Unknown option '%s'\n", arg);
|
|
93 free(o);
|
|
94 return -1;
|
|
95 }
|
|
96
|
|
97 o->next = NULL;
|
|
98
|
|
99 if (*opts) {
|
|
100 t = *opts;
|
|
101 while (t->next)
|
|
102 t = t->next;
|
|
103 t->next = o;
|
|
104 } else {
|
|
105 *opts = o;
|
|
106 }
|
|
107
|
|
108 return 0;
|
|
109 }
|
|
110
|
|
111 int main(int argc, char *argv[])
|
|
112 {
|
|
113 samFile *in;
|
|
114 char *fn_ref = 0;
|
|
115 int flag = 0, c, clevel = -1, ignore_sam_err = 0;
|
|
116 char moder[8];
|
|
117 bam_hdr_t *h;
|
|
118 bam1_t *b;
|
|
119 htsFile *out;
|
|
120 char modew[8];
|
|
121 int r = 0, exit_code = 0;
|
|
122 hts_opt *in_opts = NULL, *out_opts = NULL, *last = NULL;
|
|
123
|
|
124 while ((c = getopt(argc, argv, "IbDCSl:t:i:o:")) >= 0) {
|
|
125 switch (c) {
|
|
126 case 'S': flag |= 1; break;
|
|
127 case 'b': flag |= 2; break;
|
|
128 case 'D': flag |= 4; break;
|
|
129 case 'C': flag |= 8; break;
|
|
130 case 'l': clevel = atoi(optarg); flag |= 2; break;
|
|
131 case 't': fn_ref = optarg; break;
|
|
132 case 'I': ignore_sam_err = 1; break;
|
|
133 case 'i': if (add_option(&in_opts, optarg)) return 1; break;
|
|
134 case 'o': if (add_option(&out_opts, optarg)) return 1; break;
|
|
135 }
|
|
136 }
|
|
137 if (argc == optind) {
|
|
138 fprintf(stderr, "Usage: samview [-bSCSI] [-l level] [-o option=value] <in.bam>|<in.sam>|<in.cram> [region]\n");
|
|
139 return 1;
|
|
140 }
|
|
141 strcpy(moder, "r");
|
|
142 if (flag&4) strcat(moder, "c");
|
|
143 else if ((flag&1) == 0) strcat(moder, "b");
|
|
144
|
|
145 in = sam_open(argv[optind], moder);
|
|
146 if (in == NULL) {
|
|
147 fprintf(stderr, "Error opening \"%s\"\n", argv[optind]);
|
|
148 return EXIT_FAILURE;
|
|
149 }
|
|
150 h = sam_hdr_read(in);
|
|
151 h->ignore_sam_err = ignore_sam_err;
|
|
152 b = bam_init1();
|
|
153
|
|
154 strcpy(modew, "w");
|
|
155 if (clevel >= 0 && clevel <= 9) sprintf(modew + 1, "%d", clevel);
|
|
156 if (flag&8) strcat(modew, "c");
|
|
157 else if (flag&2) strcat(modew, "b");
|
|
158 out = hts_open("-", modew);
|
|
159 if (out == NULL) {
|
|
160 fprintf(stderr, "Error opening standard output\n");
|
|
161 return EXIT_FAILURE;
|
|
162 }
|
|
163
|
|
164 /* CRAM output */
|
|
165 if (flag & 8) {
|
|
166 // Parse input header and use for CRAM output
|
|
167 out->fp.cram->header = sam_hdr_parse_(h->text, h->l_text);
|
|
168
|
|
169 // Create CRAM references arrays
|
|
170 if (fn_ref)
|
|
171 cram_set_option(out->fp.cram, CRAM_OPT_REFERENCE, fn_ref);
|
|
172 else
|
|
173 // Attempt to fill out a cram->refs[] array from @SQ headers
|
|
174 cram_set_option(out->fp.cram, CRAM_OPT_REFERENCE, NULL);
|
|
175 }
|
|
176
|
|
177 // Process any options; currently cram only.
|
|
178 for (; in_opts; in_opts = (last=in_opts)->next, free(last)) {
|
|
179 hts_set_opt(in, in_opts->opt, in_opts->val);
|
|
180 if (in_opts->opt == CRAM_OPT_REFERENCE)
|
|
181 hts_set_opt(out, in_opts->opt, in_opts->val);
|
|
182 }
|
|
183 for (; out_opts; out_opts = (last=out_opts)->next, free(last))
|
|
184 hts_set_opt(out, out_opts->opt, out_opts->val);
|
|
185
|
|
186 sam_hdr_write(out, h);
|
|
187 if (optind + 1 < argc && !(flag&1)) { // BAM input and has a region
|
|
188 int i;
|
|
189 hts_idx_t *idx;
|
|
190 if ((idx = bam_index_load(argv[optind])) == 0) {
|
|
191 fprintf(stderr, "[E::%s] fail to load the BAM index\n", __func__);
|
|
192 return 1;
|
|
193 }
|
|
194 for (i = optind + 1; i < argc; ++i) {
|
|
195 hts_itr_t *iter;
|
|
196 if ((iter = bam_itr_querys(idx, h, argv[i])) == 0) {
|
|
197 fprintf(stderr, "[E::%s] fail to parse region '%s'\n", __func__, argv[i]);
|
|
198 continue;
|
|
199 }
|
|
200 while ((r = bam_itr_next(in, iter, b)) >= 0) {
|
|
201 if (sam_write1(out, h, b) < 0) {
|
|
202 fprintf(stderr, "Error writing output.\n");
|
|
203 exit_code = 1;
|
|
204 break;
|
|
205 }
|
|
206 }
|
|
207 hts_itr_destroy(iter);
|
|
208 }
|
|
209 hts_idx_destroy(idx);
|
|
210 } else while ((r = sam_read1(in, h, b)) >= 0) {
|
|
211 if (sam_write1(out, h, b) < 0) {
|
|
212 fprintf(stderr, "Error writing output.\n");
|
|
213 exit_code = 1;
|
|
214 break;
|
|
215 }
|
|
216 }
|
|
217
|
|
218 if (r < -1) {
|
|
219 fprintf(stderr, "Error parsing input.\n");
|
|
220 exit_code = 1;
|
|
221 }
|
|
222
|
|
223 r = sam_close(out);
|
|
224 if (r < 0) {
|
|
225 fprintf(stderr, "Error closing output.\n");
|
|
226 exit_code = 1;
|
|
227 }
|
|
228
|
|
229 bam_destroy1(b);
|
|
230 bam_hdr_destroy(h);
|
|
231
|
|
232 r = sam_close(in);
|
|
233 if (r < 0) {
|
|
234 fprintf(stderr, "Error closing input.\n");
|
|
235 exit_code = 1;
|
|
236 }
|
|
237
|
|
238 return exit_code;
|
|
239 }
|