0
|
1 /* htsfile.c -- file identifier and minimal viewer.
|
|
2
|
|
3 Copyright (C) 2014-2015 Genome Research Ltd.
|
|
4
|
|
5 Author: John Marshall <jm18@sanger.ac.uk>
|
|
6
|
|
7 Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8 of this software and associated documentation files (the "Software"), to deal
|
|
9 in the Software without restriction, including without limitation the rights
|
|
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11 copies of the Software, and to permit persons to whom the Software is
|
|
12 furnished to do so, subject to the following conditions:
|
|
13
|
|
14 The above copyright notice and this permission notice shall be included in
|
|
15 all copies or substantial portions of the Software.
|
|
16
|
|
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
20 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
23 DEALINGS IN THE SOFTWARE. */
|
|
24
|
|
25 #include <errno.h>
|
|
26 #include <stdio.h>
|
|
27 #include <stdlib.h>
|
|
28 #include <getopt.h>
|
|
29 #include <unistd.h>
|
|
30
|
|
31 #include "htslib/hfile.h"
|
|
32 #include "htslib/hts.h"
|
|
33 #include "htslib/sam.h"
|
|
34 #include "htslib/vcf.h"
|
|
35
|
|
36 enum { identify, view_headers, view_all } mode = identify;
|
|
37 int show_headers = 1;
|
|
38
|
|
39 static htsFile *dup_stdout(const char *mode)
|
|
40 {
|
|
41 int fd = dup(STDOUT_FILENO);
|
|
42 hFILE *hfp = (fd >= 0)? hdopen(fd, mode) : NULL;
|
|
43 return hfp? hts_hopen(hfp, "-", mode) : NULL;
|
|
44 }
|
|
45
|
|
46 static int view_sam(hFILE *hfp, const char *filename)
|
|
47 {
|
|
48 samFile *in = hts_hopen(hfp, filename, "r");
|
|
49 if (in == NULL) return 0;
|
|
50 samFile *out = dup_stdout("w");
|
|
51 bam_hdr_t *hdr = sam_hdr_read(in);
|
|
52
|
|
53 if (show_headers) sam_hdr_write(out, hdr);
|
|
54 if (mode == view_all) {
|
|
55 bam1_t *b = bam_init1();
|
|
56 while (sam_read1(in, hdr, b) >= 0)
|
|
57 sam_write1(out, hdr, b);
|
|
58 bam_destroy1(b);
|
|
59 }
|
|
60
|
|
61 bam_hdr_destroy(hdr);
|
|
62 hts_close(out);
|
|
63 hts_close(in);
|
|
64 return 1;
|
|
65 }
|
|
66
|
|
67 static int view_vcf(hFILE *hfp, const char *filename)
|
|
68 {
|
|
69 vcfFile *in = hts_hopen(hfp, filename, "r");
|
|
70 if (in == NULL) return 0;
|
|
71 vcfFile *out = dup_stdout("w");
|
|
72 bcf_hdr_t *hdr = bcf_hdr_read(in);
|
|
73
|
|
74 if (show_headers) bcf_hdr_write(out, hdr);
|
|
75 if (mode == view_all) {
|
|
76 bcf1_t *rec = bcf_init();
|
|
77 while (bcf_read(in, hdr, rec) >= 0)
|
|
78 bcf_write(out, hdr, rec);
|
|
79 bcf_destroy(rec);
|
|
80 }
|
|
81
|
|
82 bcf_hdr_destroy(hdr);
|
|
83 hts_close(out);
|
|
84 hts_close(in);
|
|
85 return 1;
|
|
86 }
|
|
87
|
|
88 static void usage(FILE *fp, int status)
|
|
89 {
|
|
90 fprintf(fp,
|
|
91 "Usage: htsfile [-chH] FILE...\n"
|
|
92 "Options:\n"
|
|
93 " -c, --view Write textual form of FILEs to standard output\n"
|
|
94 " -h, --header-only Display only headers in view mode, not records\n"
|
|
95 " -H, --no-header Suppress header display in view mode\n");
|
|
96 exit(status);
|
|
97 }
|
|
98
|
|
99 int main(int argc, char **argv)
|
|
100 {
|
|
101 static const struct option options[] = {
|
|
102 { "header-only", no_argument, NULL, 'h' },
|
|
103 { "no-header", no_argument, NULL, 'H' },
|
|
104 { "view", no_argument, NULL, 'c' },
|
|
105 { "help", no_argument, NULL, '?' },
|
|
106 { "version", no_argument, NULL, 1 },
|
|
107 { NULL, 0, NULL, 0 }
|
|
108 };
|
|
109
|
|
110 int status = EXIT_SUCCESS;
|
|
111 int c, i;
|
|
112 while ((c = getopt_long(argc, argv, "chH?", options, NULL)) >= 0)
|
|
113 switch (c) {
|
|
114 case 'c': mode = view_all; break;
|
|
115 case 'h': mode = view_headers; show_headers = 1; break;
|
|
116 case 'H': show_headers = 0; break;
|
|
117 case 1:
|
|
118 printf(
|
|
119 "htsfile (htslib) %s\n"
|
|
120 "Copyright (C) 2015 Genome Research Ltd.\n",
|
|
121 hts_version());
|
|
122 exit(EXIT_SUCCESS);
|
|
123 break;
|
|
124 case '?': usage(stdout, EXIT_SUCCESS); break;
|
|
125 default: usage(stderr, EXIT_FAILURE); break;
|
|
126 }
|
|
127
|
|
128 if (optind == argc) usage(stderr, EXIT_FAILURE);
|
|
129
|
|
130 for (i = optind; i < argc; i++) {
|
|
131 htsFormat fmt;
|
|
132 hFILE *fp = hopen(argv[i], "r");
|
|
133 if (fp == NULL) {
|
|
134 fprintf(stderr, "htsfile: can't open \"%s\": %s\n", argv[i], strerror(errno));
|
|
135 status = EXIT_FAILURE;
|
|
136 continue;
|
|
137 }
|
|
138
|
|
139 if (hts_detect_format(fp, &fmt) < 0) {
|
|
140 fprintf(stderr, "htsfile: detecting \"%s\" format failed: %s\n", argv[i], strerror(errno));
|
|
141 hclose_abruptly(fp);
|
|
142 status = EXIT_FAILURE;
|
|
143 continue;
|
|
144 }
|
|
145
|
|
146 if (mode == identify) {
|
|
147 char *description = hts_format_description(&fmt);
|
|
148 printf("%s:\t%s\n", argv[i], description);
|
|
149 free(description);
|
|
150 }
|
|
151 else
|
|
152 switch (fmt.category) {
|
|
153 case sequence_data: if (view_sam(fp, argv[i])) fp = NULL; break;
|
|
154 case variant_data: if (view_vcf(fp, argv[i])) fp = NULL; break;
|
|
155 default:
|
|
156 fprintf(stderr, "htsfile: can't view %s: unknown format\n", argv[i]);
|
|
157 status = EXIT_FAILURE;
|
|
158 break;
|
|
159 }
|
|
160
|
|
161 if (fp && hclose(fp) < 0) {
|
|
162 fprintf(stderr, "htsfile: closing %s failed\n", argv[i]);
|
|
163 status = EXIT_FAILURE;
|
|
164 }
|
|
165 }
|
|
166
|
|
167 return status;
|
|
168 }
|