-
Notifications
You must be signed in to change notification settings - Fork 13
/
writer.jl
62 lines (51 loc) · 1.61 KB
/
writer.jl
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
# BAM Writer
# ==========
"""
BAM.Writer(output::BGZFStream, header::SAM.Header)
Create a data writer of the BAM file format.
# Arguments
* `output`: data sink
* `header`: SAM header object
"""
mutable struct Writer <: XAMWriter
stream::BGZFStreams.BGZFStream
end
function Writer(stream::BGZFStreams.BGZFStream, header::SAM.Header)
refseqnames = String[]
refseqlens = Int[]
for metainfo in findall(header, "SQ")
push!(refseqnames, metainfo["SN"])
push!(refseqlens, parse(Int, metainfo["LN"]))
end
write_header(stream, header, refseqnames, refseqlens)
return Writer(stream)
end
function BioGenerics.IO.stream(writer::Writer)
return writer.stream
end
function Base.write(writer::Writer, record::Record)
n = 0
n += unsafe_write(writer.stream, pointer_from_objref(record), FIXED_FIELDS_BYTES)
n += unsafe_write(writer.stream, pointer(record.data), data_size(record))
return n
end
function write_header(stream, header, refseqnames, refseqlens)
@assert length(refseqnames) == length(refseqlens) "Lengths of refseq names and lengths must match."
n = 0
# magic bytes
n += write(stream, "BAM\1")
# SAM header
buf = IOBuffer()
l = write(SAM.Writer(buf), header)
n += write(stream, Int32(l))
n += write(stream, take!(buf))
# reference sequences
n += write(stream, Int32(length(refseqnames)))
for (seqname, seqlen) in zip(refseqnames, refseqlens)
namelen = length(seqname)
n += write(stream, Int32(namelen + 1))
n += write(stream, seqname, '\0')
n += write(stream, Int32(seqlen))
end
return n
end