PacBio BAM index file (bam.pbi) format

PacBio’s previous alignment file format (cmp.h5) contained a data table called the alignment index that recorded auxiliary identifying information and precomputed summary statistics per aligned read. This table served several purposes:

  1. it enabled fast random access to aligned reads satisfying fairly complex predicates, for example, reads from a specific list of ZMWs which had unambiguous mapping (MapQV==254), or a read with a given readname.
  2. it allowed summary reports (readlength, mapped identity/accuracy, etc.) to be constructed by quick operations over the alignment index instead of loading all of the sequence reads for each analysis.

In order to provide backwards-compatibility with the APIs enabled for accessing the cmp.h5, we have devised a new BAM companion file, the PacBio BAM index, which supports the two use cases above.

Version

This is version 4.0.0 of the bam.pbi specification.

Changelog

[4.0.0] - 2020-10-08
  • Added nInsOps, nDelOps fields to mapped data section.
[3.0.2] - 2018-09-13
  • qStart,qLen for CCS records now stored as (0,qLen) instead of (-1,-1)
[3.0.1] - 2015-09-23
  • Local context flags moved into the always-present “basic” data section.
[3.0.0] - 2015-07-12
  • Initial publishing of specification.

Format

The format mimics the HDF5 column-based approach without requiring the additional library dependency. Most sections are laid out as a series of 1-dimensional arrays, a la HDF5 datasets. Calculating an average or maximum mapQV, for example, would simply involve a block read of the array and the relevant computation.

It enables the 2 major use cases listed above

  1. Random-access queries, including:
    • by reference or genomic region
    • by read group
    • by query name
    • by ZMW
    • by barcode index
    • etc.
  2. Obtain information without processing entire BAM file
    • Calculate summary statistics
    • Reverse-lookup - get information for a record, given its index
Like the associated BAM & BAI formats, PBI is compressed in the BGZF format.
See SAM/BAM spec for details.

All multi-byte numbers in PBI are stored little-endian.

All optional columns in PBI are either present for all rows or for none of them,
and always present in the order described in this document. This is important for correctly accessing specific values by column index.

File sections follow each other immediately in the file and are described below.

PBI Header

Field Size Definition Value
magic char[4] PBI magic string PBI\1
version uint32_t PBI format version (xx.yy.zz) 0x00xxyyzz
pbi_flags uint16_t bitflag describing file contents 1
n_reads uint32_t number of reads in the BAM file
reserved char[18] reserved space for future expansion fill(0x00)

1 pbi_flags:

Flag Value Description
Basic 0x0000 PbiHeader & BasicData only
Mapped 0x0001 MappedData section present
Coordinate Sorted 0x0002 CoordinateSortedData section present
Barcode 0x0004 BarcodeData section present

(0x0008 - 0x8000) are available to mark future data modifiers, add’l sections, etc.

Basic Data

This section contains data that apply to all PacBio BAM reads.

Each index field is laid out as a column (array), consisting of one value per BAM record. Thus for N records, this section will contain N rgId values, followed by N qStart values, then N qEnd values, and so on.

Field Size Definition
rgId int32_t Integral value of @RG::ID 1
qStart int32_t Start of query in polymerase read (0 for CCS reads)
qEnd int32_t End of query in polymerase read (qLen for CCS reads)
holeNumber int32_t The holenumber of the ZMW producing the read
readQual float Expected accuracy (‘rq’ tag) [0-1]
ctxt_flag uint8_t Local context of subread (‘cx’ tag) 2
fileOffset int64_t Virtual offset of record (bgzf_tell)

1 Read group identifiers for PacBio data are calculated as follows:

RGID_STRING := md5(movieName + "//" + readType)) [:8]
RGID_INT    := int32.Parse(RGID_STRING)

RGID_STRING is used in the @RG header and in the `RG` tag of BAM
records.  RGID_INT is used here in the PBI index.

Note that RGID_INT may be negative.
2
Local context flags are only valid for Subread / Insert records. For all other record-types, or if the CX tag is not present in the record, this value should be 0

Mapped Data

This section contains data that apply to all mapped PacBio BAM reads.

Each index field is laid out as a column (array), consisting of one value per BAM record. Thus for N records, this section will contain N tId values, followed by N tStart values, then N tEnd values, and so on.

Field Size Definition
tId int32_t BAM tid indication aligned reference
tStart uint32_t (0-based) Start of alignment in reference
tEnd uint32_t End of alignment in reference (endpos)
aStart uint32_t Start of aligned query in polymerase read
aEnd uint32_t End of aligned query in polymerase read
revStrand uint8_t 1 if reverse strand alignment, else 0
nM uint32_t Number of base matches in alignment
nMM uint32_t Number of base mismatches in alignment
mapQV uint8_t The mapping quality [valid ranges 0-254]
nInsOps uint32_t Number of insertion operations (not bases)
nDelOps uint32_t Number of deletion operations (not bases)

Note

Inserted and deleted base counts are not included in the index. These values are readily computed as:

nInsertedBases = aEnd - aStart - nM - nMM
nDeletedBases = tEnd - tStart - nM - nMM

Alignment length can be computed using:

aEnd - aStart + tEnd - tStart - nM - nMM

Coordinate-Sorted Data

In a coordinate-sorted BAM file, the records that are mapped to each reference form contiguous blocks. The data in this section provide a mapping between each tId and its start/end rows 2.

The lookup table is prefixed with the number of reference entries.

Field Size Definition
n_tids uint32_t Number of reference sequences

The lookup table is laid out as a column (array) of tuples, one per reference.

Field Size Definition
tId uint32_t reference sequence ID 1
beginRow uint32_t index of first record mapped on tId 2
endRow uint32_t index of last record mapped on tId 2
1
This dataset should be sorted in ascending order of the uint32 cast of tId (thus a tId of -1 will follow all other tId values)
2
Data fields beginRow and endRow. If tId[i]==t, then [beginRow, endRow) represents range of reads (by 0-based ordinal position in the BAM file) mapped to the reference contig with tId of t. If no BAM records are aligned to t, then we should have beginRow, endRow = -1.

Barcode Data

This section contains data that apply to all barcoded PacBio BAM reads.

Each index field is laid out as a column (array), consisting of one value per BAM record. Thus for N records, this section will contain N bc_forward values, followed by N bc_reverse values, then N bc_qual values.

Field Size Definition
bc_forward int16_t B_F from ‘bc’ tag (index to barcode FASTA), or -1 if not present
bc_reverse int16_t B_R from ‘bc’ tag (index to barcode FASTA), or -1 if not present
bc_qual int8_t barcode call confidence (‘bq’ tag), or -1 if not present

Note

If the Barcode flag is set in the header, these values must be present in all rows, otherwise it should be present for none of them.

If one Barcode field is set to -1 / non-existant, then all barcode-related fields should be set as such.