Skip to content

Commit bd85368

Browse files
committed
New -s, --samples option to include the #CHROM header line with samples.
This option works the same way as `-n, --records` but includes the #CHROM header line with samples. Running with `-s 0` alone outputs the #CHROM header line only
1 parent 983e610 commit bd85368

File tree

7 files changed

+58
-6
lines changed

7 files changed

+58
-6
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ Changes affecting specific commands:
2828
- New `-*, --keep-unseen-allele` option to output the unobserved allele <*>,
2929
intended for gVCF.
3030

31+
* bcftools head
32+
33+
- New `-s, --samples` option to include the #CHROM header line with samples.
34+
3135
* bcftools gtcheck
3236

3337
- Add output options `-o, --output` and `-O, --output-type`

doc/bcftools.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1795,6 +1795,12 @@ present, but it never adds version or command line information itself.
17951795
Also display the first 'INT' variant records.
17961796
By default, no variant records are displayed.
17971797

1798+
*-s, --samples* 'INT'::
1799+
Display the first 'INT' variant records including the last #CHROM header line with samples.
1800+
Running with *-s 0* alone outputs the #CHROM header line only. Note that
1801+
the list of samples, with each sample per line, can be obtained with `bcftools query` using
1802+
the option *-l, --list-samples*.
1803+
17981804

17991805
[[index]]
18001806
=== bcftools index ['OPTIONS'] 'in.bcf'|'in.vcf.gz'

test/head.1.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#CHROM POS ID REF ALT QUAL FILTER INFO FORMAT sample1 sample2

test/head.2.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#CHROM POS ID REF ALT QUAL FILTER INFO FORMAT sample1 sample2
2+
chr1 212740 . A G,<*> 0 . DP=73;I16=0,0,39,4,0,0,2743,192525,0,0,2580,154800,0,0,825,18621;QS=0,2,0;VDB=0.520868;SGB=-1.38232;MQSB=1;MQ0F=0 PL:DP:AD 255,72,0,255,72,255:24:0,24,0 255,57,0,255,57,255:19:0,19,0

test/head.3.out

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
##fileformat=VCFv4.2
2+
##FILTER=<ID=PASS,Description="All filters passed">
3+
#CHROM POS ID REF ALT QUAL FILTER INFO FORMAT sample1 sample2
4+
chr1 212740 . A G,<*> 0 . DP=73;I16=0,0,39,4,0,0,2743,192525,0,0,2580,154800,0,0,825,18621;QS=0,2,0;VDB=0.520868;SGB=-1.38232;MQSB=1;MQ0F=0 PL:DP:AD 255,72,0,255,72,255:24:0,24,0 255,57,0,255,57,255:19:0,19,0
5+
chr1 320055 . A <*> 0 . DP=101;I16=52,9,0,0,4116,300666,0,0,3660,219600,0,0,1281,29849,0,0;QS=2,0;MQSB=1;MQ0F=0 PL:DP:AD 0,87,255:29:29,0 0,96,255:32:32,0

test/test.pl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,9 @@
361361
run_test(\&test_vcf_view,$opts,in=>'view.sites',out=>'view.sites.1.out',args=>'',tgts=>'view.sites.txt');
362362
run_test(\&test_vcf_view,$opts,in=>'view.sites',out=>'view.sites.1.out',args=>'',tgts=>'view.sites.txt.gz');
363363
run_test(\&test_vcf_head,$opts,in=>'mpileup.2.vcf',in_nheaders=>22);
364+
run_test(\&test_vcf_head2,$opts,in=>'mpileup.2',out=>'head.1.out',args=>'-s0');
365+
run_test(\&test_vcf_head2,$opts,in=>'mpileup.2',out=>'head.2.out',args=>'-s1');
366+
run_test(\&test_vcf_head2,$opts,in=>'mpileup.2',out=>'head.3.out',args=>'-s2 -h2');
364367
run_test(\&test_vcf_call,$opts,in=>'mpileup',out=>'mpileup.1.out',args=>'-mv');
365368
run_test(\&test_vcf_call,$opts,in=>'mpileup',out=>'mpileup.2.out',args=>'-mg0');
366369
run_test(\&test_vcf_call,$opts,in=>'mpileup',out=>'mpileup.3.out',args=>'-mv -S {PATH}/mpileup.3.samples');
@@ -1516,6 +1519,13 @@ sub test_vcf_head
15161519
test_cmd($opts, %args, gen_head_output(5, 5, "fiveboth", $infile),
15171520
cmd => "$$opts{bin}/bcftools head -h 5 -n 5 < $infile");
15181521
}
1522+
sub test_vcf_head2
1523+
{
1524+
my ($opts,%args) = @_;
1525+
bgzip_tabix_vcf($opts,$args{in});
1526+
test_cmd($opts,%args,cmd=>"$$opts{bin}/bcftools head $args{args} $$opts{tmp}/$args{in}.vcf.gz");
1527+
test_cmd($opts,%args,cmd=>"$$opts{bin}/bcftools view --no-version -Ob $$opts{tmp}/$args{in}.vcf.gz | $$opts{bin}/bcftools head $args{args}");
1528+
}
15191529
sub test_vcf_call
15201530
{
15211531
my ($opts,%args) = @_;

vcfhead.c

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* vcfhead.c -- view VCF/BCF file headers.
22
33
Copyright (C) 2021 University of Glasgow.
4+
Copyright (C) 2023 Genome Research Ltd.
45
56
Author: John Marshall <[email protected]>
67
@@ -41,30 +42,36 @@ int main_vcfhead(int argc, char *argv[])
4142
"Usage: bcftools head [OPTION]... [FILE]\n"
4243
"\n"
4344
"Options:\n"
44-
" -h, --headers INT Display INT header lines [all]\n"
45-
" -n, --records INT Display INT variant record lines [none]\n"
45+
" -h, --headers INT Display INT header lines [all]\n"
46+
" -n, --records INT Display INT variant record lines [none]\n"
47+
" -s, --samples INT Display INT records starting with the #CHROM header line [none]\n"
4648
"\n";
4749

4850
static const struct option loptions[] = {
4951
{ "headers", required_argument, NULL, 'h' },
5052
{ "records", required_argument, NULL, 'n' },
53+
{ "samples", required_argument, NULL, 's' },
5154
{ NULL, 0, NULL, 0 }
5255
};
5356

5457
int all_headers = 1;
58+
int samples = 0;
5559
uint64_t nheaders = 0;
5660
uint64_t nrecords = 0;
5761

5862
int c, nargs;
59-
while ((c = getopt_long(argc, argv, "h:n:", loptions, NULL)) >= 0)
63+
while ((c = getopt_long(argc, argv, "h:n:s:", loptions, NULL)) >= 0)
6064
switch (c) {
6165
case 'h': all_headers = 0; nheaders = strtoull(optarg, NULL, 0); break;
6266
case 'n': nrecords = strtoull(optarg, NULL, 0); break;
67+
case 's': nrecords = strtoull(optarg, NULL, 0); samples = 1; break;
6368
default:
6469
fputs(usage, stderr);
6570
return EXIT_FAILURE;
6671
}
6772

73+
if ( samples && all_headers ) all_headers = 0;
74+
6875
nargs = argc - optind;
6976
if (nargs == 0 && isatty(STDIN_FILENO)) {
7077
fputs(usage, stdout);
@@ -99,17 +106,34 @@ int main_vcfhead(int argc, char *argv[])
99106
bcf_hdr_format(hdr, 0, &str);
100107
fputs(ks_str(&str), stdout);
101108
}
102-
else if (nheaders > 0) {
109+
else if (nheaders > 0 || samples ) {
103110
bcf_hdr_format(hdr, 0, &str);
104111
char *lim = str.s;
105112
uint64_t n;
113+
int samples_printed = 0;
106114
for (n = 0; n < nheaders; n++) {
115+
if ( samples && !strncmp(lim,"#CHROM\t",7) ) samples_printed = 1;
107116
lim = strchr(lim, '\n');
108117
if (lim) lim++;
109118
else break;
110119
}
111-
if (lim) *lim = '\0';
112-
fputs(ks_str(&str), stdout);
120+
if ( nheaders )
121+
{
122+
char tmp;
123+
if (lim) { tmp = *lim; *lim = '\0'; }
124+
fputs(ks_str(&str), stdout);
125+
if (lim) *lim = tmp;
126+
}
127+
if ( lim && samples && !samples_printed )
128+
{
129+
while ( lim && *lim )
130+
{
131+
if ( !strncmp(lim,"#CHROM\t",7) ) { fputs(lim, stdout); break; }
132+
lim = strchr(lim, '\n');
133+
if (lim) lim++;
134+
else break;
135+
}
136+
}
113137
}
114138

115139
if (nrecords > 0) {

0 commit comments

Comments
 (0)