<htmllang="en"><head><metacharset="UTF-8"/><metaname="viewport"content="width=device-width, initial-scale=1.0"/><title>SAM and BAM · XAM.jl</title><linkhref="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.2.0/normalize.min.css"rel="stylesheet"type="text/css"/><linkhref="https://fonts.googleapis.com/css?family=Lato|Roboto+Mono"rel="stylesheet"type="text/css"/><linkhref="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css"rel="stylesheet"type="text/css"/><linkhref="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css"rel="stylesheet"type="text/css"/><script>documenterBaseURL=".."</script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.min.js"data-main="../assets/documenter.js"></script><scriptsrc="../siteinfo.js"></script><scriptsrc="../../versions.js"></script><linkhref="../assets/documenter.css"rel="stylesheet"type="text/css"/></head><body><navclass="toc"><h1>XAM.jl</h1><selectid="version-selector"onChange="window.location.href=this.value"style="visibility: hidden"></select><formclass="search"id="search-form"action="../search/"><inputid="search-query"name="q"type="text"placeholder="Search docs"/></form><ul><li><aclass="toctext"href="../">Home</a></li><liclass="current"><aclass="toctext"href>SAM and BAM</a><ulclass="internal"><li><aclass="toctext"href="#Introduction-1">Introduction</a></li><li><aclass="toctext"href="#Reading-SAM-and-BAM-files-1">Reading SAM and BAM files</a></li><li><aclass="toctext"href="#SAM-and-BAM-Headers-1">SAM and BAM Headers</a></li><li><aclass="toctext"href="#SAM-and-BAM-Records-1">SAM and BAM Records</a></li><li><aclass="toctext"href="#Accessing-auxiliary-data-1">Accessing auxiliary data</a></li><li><aclass="toctext"href="#Getting-records-in-a-range-1">Getting records in a range</a></li><li><aclass="toctext"href="#Getting-records-overlapping-genomic-features-1">Getting records overlapping genomic features</a></li><li><aclass="toctext"href="#Writing-files-1">Writing files</a></li></ul></li><li><spanclass="toctext">API Reference</span><ul><li><aclass="toctext"href="../api/public/">Public</a></li></ul></li></ul></nav><articleid="docs"><header><nav><ul><li><ahref>SAM and BAM</a></li></ul><aclass="edit-page"href="https://github.com/BioJulia/XAM.jl/blob/develop/docs/src/hts-files.md"><spanclass="fa"></span> Edit on GitHub</a></nav><hr/><divid="topbar"><span>SAM and BAM</span><aclass="fa fa-bars"href="#"></a></div></header><h1><aclass="nav-anchor"id="SAM-and-BAM-1"href="#SAM-and-BAM-1">SAM and BAM</a></h1><h2><aclass="nav-anchor"id="Introduction-1"href="#Introduction-1">Introduction</a></h2><p>High-throughput sequencing (HTS) technologies generate a large amount of data in the form of a large number of nucleotide sequencing reads. One of the most common tasks in bioinformatics is to align these reads against known reference genomes, chromosomes, or contigs. BioAlignments provides several data formats commonly used for this kind of task.</p><p>BioAlignments offers high-performance tools for SAM and BAM file formats, which are the most popular file formats.</p><p>If you have questions about the SAM and BAM formats or any of the terminology used when discussing these formats, see the published [specification][samtools-spec], which is maintained by the [samtools group][samtools].</p><p>A very very simple SAM file looks like the following:</p><pre><codeclass="language-none">@HD VN:1.6 SO:coordinate
r001 147 ref 37 30 9M = 7 -39 CAGCGGCAT * NM:i:1</code></pre><p>Where the first two lines are part of the "header", and the following lines are "records". Each record describes how a read aligns to some reference sequence. Sometimes one record describes one read, but there are other cases like chimeric reads and split alignments, where multiple records apply to one read. In the example above, <code>r003</code> is a chimeric read, and <code>r004</code> is a split alignment, and <code>r001</code> are mate pair reads. Again, we refer you to the official [specification][samtools-spec] for more details.</p><p>A BAM file stores this same information but in a binary and compressible format that does not make for pretty printing here!</p><h2><aclass="nav-anchor"id="Reading-SAM-and-BAM-files-1"href="#Reading-SAM-and-BAM-files-1">Reading SAM and BAM files</a></h2><p>A typical script iterating over all records in a file looks like below:</p><pre><codeclass="language-julia">using BioAlignments
close(reader)</code></pre><p>The size of a BAM file is often extremely large. The iterator interface demonstrated above allocates an object for each record and that may be a bottleneck of reading data from a BAM file. In-place reading reuses a pre-allocated object for every record and less memory allocation happens in reading:</p><pre><codeclass="language-julia">reader = open(BAM.Reader, "data.bam")
record = BAM.Record()
while !eof(reader)
read!(reader, record)
# do something
end</code></pre><h2><aclass="nav-anchor"id="SAM-and-BAM-Headers-1"href="#SAM-and-BAM-Headers-1">SAM and BAM Headers</a></h2><p>Both <code>SAM.Reader</code> and <code>BAM.Reader</code> implement the <code>header</code> function, which returns a <code>SAM.Header</code> object. To extract certain information out of the headers, you can use the <code>find</code> method on the header to extract information according to SAM/BAM tag. Again we refer you to the [specification][samtools-spec] for full details of all the different tags that can occur in headers, and what they mean.</p><p>Below is an example of extracting all the info about the reference sequences from the BAM header. In SAM/BAM, any description of a reference sequence is stored in the header, under a tag denoted <code>SQ</code> (think <code>reference SeQuence</code>!).</p><pre><codeclass="language-jlcon">julia> reader = open(SAM.Reader, "data.sam");
</code></pre><p>In the above we can see there were 7 sequences in the reference: 5 chromosomes, one chloroplast sequence, and one mitochondrial sequence.</p><h2><aclass="nav-anchor"id="SAM-and-BAM-Records-1"href="#SAM-and-BAM-Records-1">SAM and BAM Records</a></h2><p>BioAlignments supports the following accessors for <code>SAM.Record</code> types.</p><sectionclass="docstring"><divclass="docstring-header"><aclass="docstring-binding"id="XAM.SAM.flag"href="#XAM.SAM.flag"><code>XAM.SAM.flag</code></a> — <spanclass="docstring-category">Function</span>.</div><div><div><pre><codeclass="language-julia">flag(record::Record)::UInt16</code></pre><p>Get the bitwise flag of <code>record</code>.</p></div></div><aclass="source-link"target="_blank"href="https://github.com/BioJulia/XAM.jl/blob/647efccb6c9d51705b72a14d0cbad0cbdb33a1f1/src/sam/record.jl#L133-L137">source</a></section><sectionclass="docstring"><divclass="docstring-header"><aclass="docstring-binding"id="XAM.SAM.ismapped"href="#XAM.SAM.ismapped"><code>XAM.SAM.ismapped</code></a> — <spanclass="docstring-category">Function</span>.</div><div><div><pre><codeclass="language-julia">ismapped(record::Record)::Bool</code></pre><p>Test if <code>record</code> is mapped.</p></div></div><aclass="source-link"target="_blank"href="https://github.com/BioJulia/XAM.jl/blob/647efccb6c9d51705b72a14d0cbad0cbdb33a1f1/src/sam/record.jl#L147-L151">source</a></section><sectionclass="docstring"><divclass="docstring-header"><aclass="docstring-binding"id="XAM.SAM.isprimary"href="#XAM.SAM.isprimary"><code>XAM.SAM.isprimary</code></a> — <spanclass="docstring-category">Function</span>.</div><div><div><pre><codeclass="language-julia">isprimary(record::Record)::Bool</code></pre><p>Test if <code>record</code> is a primary line of the read.</p><p>This is equivalent to <code>flag(record) & 0x900 == 0</code>.</p></div></div><aclass="source-link"target="_blank"href="https://github.com/BioJulia/XAM.jl/blob/647efccb6c9d51705b72a14d0cbad0cbdb33a1f1/src/sam/record.jl#L156-L162">source</a></section><sectionclass="docstring"><divclass="docstring-header"><aclass="docstring-binding"id="XAM.SAM.refname"href="#XAM.SAM.refname"><code>XAM.SAM.refname</code></a> — <spanclass="docstring-category">Function</span>.</div><div><div><pre><codeclass="language-julia">refname(record::Record)::String</code></pre><p>Get the reference sequence name of <code>record</code>.</p></div></div><aclass="source-link"target="_blank"href="https://github.com/BioJulia/XAM.jl/blob/647efccb6c9d51705b72a14d0cbad0cbdb33a1f1/src/sam/record.jl#L167-L171">source</a></section><sectionclass="docstring"><divclass="docstring-header"><aclass="docstring-binding"id="XAM.SAM.position"href="#XAM.SAM.position"><code>XAM.SAM.position</code></a> — <spanclass="docstring-category">Function</span>.</div><div><div><pre><codeclass="language-julia">position(record::Record)::Int</code></pre><p>Get the 1-based leftmost mapping position of <code>record</code>.</p></div></div><aclass="source-link"target="_blank"href="https://github.com/BioJulia/XAM.jl/blob/647efccb6c9d51705b72a14d0cbad0cbdb33a1f1/src/sam/record.jl#L184-L188">source</a></section><sectionclass="docstring"><divclass="docstring-header"><aclass="docstring-binding"id="XAM.SAM.rightposition"href="#XAM.SAM.rightposition"><code>XAM.SAM.rightposition</code></a> — <spanclass="docstring-category">Function</span>.</div><div><div><pre><codeclass="language-julia">rightposition(record::Record)::Int</code></pre><p>Get the 1-based rightmost mapping position of <code>record</code>.</p></div></div><aclass="source-link"target="_blank"href="https://github.com/BioJulia/XAM.jl/blob/647efccb6c9d51705b72a14d0cbad0cbdb33a1f1/src/sam/record.jl#L202-L206">source</a></section><sectionclass="docstring"><divclass="docstring-header"><aclass="docstring-binding"id="XAM.SAM.isnextmapped"href="#XAM.SAM.isnextmapped"><code>XAM.SAM.isnextmapped</code></a> — <spanclass="docstring-category">Function</span>.</div><div><div><pre><codeclass="language-julia">isnextmappe
end</code></pre><h2><aclass="nav-anchor"id="Getting-records-in-a-range-1"href="#Getting-records-in-a-range-1">Getting records in a range</a></h2><p>BioAlignments supports the BAI index to fetch records in a specific range from a BAM file. [Samtools][samtools] provides <code>index</code> subcommand to create an index file (.bai) from a sorted BAM file.</p><pre><codeclass="language-console">$ samtools index -b SRR1238088.sort.bam
$ ls SRR1238088.sort.bam*
SRR1238088.sort.bam SRR1238088.sort.bam.bai</code></pre><p><code>eachoverlap(reader, chrom, range)</code> returns an iterator of BAM records overlapping the query interval:</p><pre><codeclass="language-julia">reader = open(BAM.Reader, "SRR1238088.sort.bam", index="SRR1238088.sort.bam.bai")
for record in eachoverlap(reader, "Chr2", 10000:11000)
# `record` is a BAM.Record object
# ...
end
close(reader)</code></pre><h2><aclass="nav-anchor"id="Getting-records-overlapping-genomic-features-1"href="#Getting-records-overlapping-genomic-features-1">Getting records overlapping genomic features</a></h2><p><code>eachoverlap</code> also accepts the <code>Interval</code> type defined in <ahref="https://github.com/BioJulia/GenomicFeatures.jl">GenomicFeatures.jl</a>.</p><p>This allows you to do things like first read in the genomic features from a GFF3 file, and then for each feature, iterate over all the BAM records that overlap with that feature.</p><pre><codeclass="language-julia"># Load GFF3 module.
using GenomicFeatures
using BioAlignments
# Load genomic features from a GFF3 file.
features = open(collect, GFF3.Reader, "TAIR10_GFF3_genes.gff")
# Open a BAM file and iterate over records overlapping mRNA transcripts.
reader = open(BAM.Reader, "SRR1238088.sort.bam", index = "SRR1238088.sort.bam.bai")
for feature in features
for record in eachoverlap(reader, feature)
# `record` overlaps `feature`.
# ...
end
end
close(reader)</code></pre><h2><aclass="nav-anchor"id="Writing-files-1"href="#Writing-files-1">Writing files</a></h2><p>In order to write a BAM or SAM file, you must first create a <code>SAM.Header</code>.</p><p>A <code>SAM.Header</code> is constructed from a vector of <code>SAM.MetaInfo</code> objects.</p><p>For example, to create the following simple header:</p><pre><codeclass="language-none">@HD VN:1.6 SO:coordinate
julia> b = SAM.MetaInfo("SQ", ["SN" =>"ref", "LN" => 45])
SAM.MetaInfo:
tag: SQ
value: SN=ref LN=45
julia> h = SAM.Header([a, b])
SAM.Header(SAM.MetaInfo[SAM.MetaInfo:
tag: HD
value: VN=1.6 SO=coordinate, SAM.MetaInfo:
tag: SQ
value: SN=ref LN=45])
</code></pre><p>Then to create the writer for a SAM file, construct a <code>SAM.Writer</code> using the header and an <code>IO</code> type:</p><pre><codeclass="language-julia">julia> samw = SAM.Writer(open("my-data.sam", "w"), h)
SAM.Writer(IOStream(<file my-data.sam>))
</code></pre><p>To make a BAM Writer is slightly different, as you need to use a specific stream type from the [BGZFStreams][bgzfstreams] package:</p><pre><codeclass="language-julia">julia> using BGZFStreams
</code></pre><p>Once you have a BAM or SAM writer, you can use the <code>write</code> method to write <code>BAM.Record</code>s or <code>SAM.Record</code>s to file:</p><pre><codeclass="language-julia">julia> write(bamw, rec) # Here rec is a `BAM.Record`