1 /* 2 New style BAM reader. This file is part of Sambamba. 3 Copyright (C) 2017 Pjotr Prins <pjotr.prins@thebird.nl> 4 5 Sambamba is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published 7 by the Free Software Foundation; either version 2 of the License, 8 or (at your option) any later version. 9 10 Sambamba is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 18 02111-1307 USA 19 20 */ 21 22 // This is a complete rewrite of Artem Tarasov's original reader. 23 24 module bio2.bam.header; 25 26 /* 27 import std.conv; 28 import core.stdc.stdio: fopen, fread, fclose; 29 import std.typecons; 30 import std.bitmanip; 31 32 import bio.bam.cigar; 33 */ 34 35 import std.exception; 36 import std.file; 37 import std.stdio; 38 import std.string; 39 40 import bio.bam.constants; 41 42 import bio2.bgzf; 43 import bio2.bgzf_writer; 44 import bio2.constants; 45 46 struct RefSequence { 47 size_d length; 48 string name; 49 } 50 51 struct BamHeader { 52 string id; 53 string text; 54 RefSequence[] refs; 55 56 @disable this(this); // disable copy semantics; 57 } 58 59 void fetch_bam_header(ref BamHeader header, ref BgzfStream stream) { 60 // stderr.writeln("Fetching BAM header"); 61 ubyte[4] ubyte4; 62 stream.read(ubyte4); 63 enforce(ubyte4 == BAM_MAGIC,"Invalid file format: expected BAM magic number"); 64 immutable text_size = stream.read!int(); 65 // stderr.writeln("Text size ",text_size.sizeof," ",text_size); 66 immutable text = stream.read!string(text_size); 67 header = BamHeader(BAM_MAGIC,text); 68 immutable n_refs = stream.read!int(); 69 // stderr.writeln("Fetching ",n_refs," references"); 70 foreach(int n_ref; 0..n_refs) { 71 immutable l_name = stream.read!int(); 72 // stderr.writeln("!!",l_name); 73 auto ref_name = stream.read!string(l_name); 74 immutable l_ref = stream.read!int(); // length of reference sequence (bps) 75 // stderr.writeln(l_name," ",ref_name," ",l_ref); 76 header.refs ~= RefSequence(l_ref,ref_name[0..l_name-1]); // drop zero terminator 77 } 78 } 79 80 void write_bam_header(ref BgzfWriter bw, ref BamHeader header) { 81 // stderr.writeln("Writing BAM header"); 82 ubyte[4] magic = cast(ubyte[])BAM_MAGIC; 83 bw.write(magic); 84 // stderr.writeln("Text size ",int.sizeof," ",header.text.length); 85 bw.write!int(cast(int)header.text.length); 86 bw.write(header.text); 87 auto n_refs = cast(int)header.refs.length; 88 bw.write!int(cast(int)header.refs.length); 89 // stderr.writeln("Writing ",n_refs," references"); 90 foreach(int n_ref; 0..n_refs) { 91 immutable refseq = header.refs[n_ref]; 92 bw.write!int(cast(int)(refseq.name.length+1)); // incl. zero terminator 93 // stderr.writeln("!!",refseq.name.length+1); 94 bw.write(refseq.name); 95 bw.write!ubyte(cast(ubyte)'\0'); 96 bw.write!int(cast(int)refseq.length); 97 // stderr.writeln(refseq.name.length+1," ",refseq.name," ",refseq.length); 98 } 99 // stderr.writeln("!!"); 100 bw.flush_block(); 101 }