npm.io
9.3.2 • Published yesterday

@gmod/bbi

Licence
MIT
Version
9.3.2
Deps
3
Size
669 kB
Vulns
0
Weekly
0
Stars
9

bbi-js

NPM version Build Status

Parser for BigWig and BigBed file formats.

Installation

npm install @gmod/bbi

Usage

Local files
import { BigWig } from '@gmod/bbi'

const file = new BigWig({ path: 'volvox.bw' })
const header = await file.getHeader()
const features = await file.getFeatures('chr1', 0, 100, { scale: 1 })
Remote files
import { BigWig } from '@gmod/bbi'

const file = new BigWig({ url: 'https://example.com/file.bw' })
const features = await file.getFeatures('chr1', 0, 100, { scale: 1 })

You can also pass a custom filehandle from generic-filehandle2:

import { RemoteFile } from 'generic-filehandle2'

const file = new BigWig({
  filehandle: new RemoteFile('https://example.com/file.bw'),
})
Browser (CDN)
<script type="module">
  import { BigWig } from 'https://esm.sh/@gmod/bbi'

  const file = new BigWig({ url: 'https://example.com/file.bw' })
  const features = await file.getFeatures('chr1', 0, 100)
  console.log(features)
</script>

See the example folder for a complete working demo.

API

Constructor (BigWig / BigBed)

Pass exactly one of:

Option Description
path Path to a local file
url URL of a remote file
filehandle A GenericFilehandle instance from generic-filehandle2
renameRefSeqs Optional (name: string) => string mapping applied to chromosome names before every query — useful when file-internal names differ from query names (e.g. s => s.replace('chr', ''))
BigWig
getHeader(opts?)

Returns Promise<BigWigHeaderWithRefNames> with chromosome list (refsByName, refsByNumber), zoom levels, summary statistics, and — for BigBed files — the autoSql schema string. The result is cached after the first call.

getFeatures(refName, start, end, opts?)

Returns a Promise<Feature[]> for the given region. Returns an empty array if the refName is not found or the region has no data. Coordinates are 0-based half-open.

Parameter Description
refName Chromosome/sequence name
start 0-based start (inclusive)
end 0-based end (exclusive)
opts.scale Pixels per basepair — selects the zoom level where reductionLevel ≤ 2/scale. Omit for base resolution.
opts.basesPerSpan Inverse of scale (basepairs per pixel)
opts.signal AbortSignal to cancel the request
const features = await bigwig.getFeatures('chr1', 0, 100000)
// [{ start, end, score }, ...]
getFeaturesMulti(regions, opts?)

Fetches features for multiple regions in one call. Returns arrays aligned to input order (result[i] corresponds to regions[i]).

Reads for adjacent on-disk blocks are coalesced across region boundaries, so a whole-genome overview needs far fewer range requests than calling getFeatures per region — useful for rate-limited remote files. Regions may be in any order and may overlap.

const perRegion = await bigwig.getFeaturesMulti([
  { refName: 'chr1', start: 0, end: 1_000_000 },
  { refName: 'chr2', start: 0, end: 1_000_000 },
])
getFeaturesAsArrays(refName, start, end, opts?)

Same parameters as getFeatures, but returns typed arrays instead of an array of objects — more memory-efficient and lower GC pressure for large datasets.

const result = await bigwig.getFeaturesAsArrays('chr1', 0, 100000)
// Base resolution: { starts: Int32Array, ends: Int32Array, scores: Float32Array, isSummary: false }

const summary = await bigwig.getFeaturesAsArrays('chr1', 0, 100000, { scale: 0.01 })
// Zoom level:    { starts, ends, scores, minScores: Float32Array, maxScores: Float32Array, isSummary: true }

The isSummary discriminant lets TypeScript narrow the union type:

if (result.isSummary) {
  // minScores and maxScores are available here
}

Types:

interface BigWigFeatureArrays {
  starts: Int32Array
  ends: Int32Array
  scores: Float32Array
  isSummary: false
}

interface SummaryFeatureArrays {
  starts: Int32Array
  ends: Int32Array
  scores: Float32Array
  minScores: Float32Array
  maxScores: Float32Array
  isSummary: true
}
Understanding zoom levels

scale (pixels per basepair) controls which pre-computed zoom level is served. The file stores zoom levels at increasing reductionLevel values; the library picks the first level where reductionLevel ≤ 2/scale, scanning from the coarsest zoom inward:

[
  { "reductionLevel": 40 },
  { "reductionLevel": 160 },
  { "reductionLevel": 640 },
  { "reductionLevel": 2560 },
  { "reductionLevel": 10240 },
  { "reductionLevel": 40960 },
  { "reductionLevel": 163840 }
]

If no zoom level matches (e.g. scale: 1), base-resolution data is returned.

Feature type

Both BigWig and BigBed return Feature objects. Fields vary by file type and zoom level:

Field Present on Description
start always 0-based half-open start
end always 0-based half-open end
score always Signal value (BigWig) or BED score (BigBed)
rest BigBed Raw tab-delimited BED columns 4+
uniqueId BigBed Stable ID from file offset; deduplicates exact copies
field BigBed (searchExtraIndex) Which extra-index column matched
minScore zoom data Minimum score across the summary interval
maxScore zoom data Maximum score across the summary interval
summary zoom data true when the feature comes from a zoom level
BigBed
getFeatures(refName, start, end, opts?)

Returns a Promise<Feature[]>. No zoom levels — always base resolution.

Parameter Description
refName Chromosome/sequence name
start 0-based start (inclusive)
end 0-based end (exclusive)
opts.signal AbortSignal to cancel the request
searchExtraIndex(name, opts?)

Searches the BigBed extra indexes (created with -extraIndex in bedToBigBed) for a string match. Returns a Promise<Feature[]> with an additional field property indicating which index matched.

Parsing BigBed features with @gmod/bed

Raw BigBed features contain a rest field with tab-delimited columns 4+. Use @gmod/bed together with the autoSql from the file header to parse them into named fields:

import { BigBed } from '@gmod/bbi'
import BED from '@gmod/bed'

const file = new BigBed({ path: './data/hg18.bb' })
const { autoSql } = await file.getHeader()
const feats = await file.getFeatures('chr7', 0, 100000)
const parser = new BED({ autoSql })
const lines = feats.map(({ start, end, rest, uniqueId }) =>
  parser.parseLine(`chr7\t${start}\t${end}\t${rest}`, { uniqueId }),
)

Raw feature:

{
  "chromId": 0,
  "start": 64068,
  "end": 64107,
  "rest": "uc003sil.1\t0\t-\t64068\t64068\t255,0,0\t.\tDQ584609",
  "uniqueId": "bb-171"
}

Parsed feature:

{
  "uniqueId": "bb-0",
  "chrom": "chr7",
  "chromStart": 54028,
  "chromEnd": 73584,
  "name": "uc003sii.2",
  "score": 0,
  "strand": -1,
  "thickStart": 54028,
  "thickEnd": 54028,
  "reserved": "255,0,0",
  "spID": "AL137655"
}

The uniqueId is derived from the file offset and helps deduplicate exact feature copies.

parseBigWig(bigwig, opts?)

Reads all features from every chromosome at base resolution, skipping chromosomes with no data.

import { BigWig, parseBigWig } from '@gmod/bbi'

const file = new BigWig({ path: 'volvox.bw' })
const results = await parseBigWig(file)
for (const { starts, ends, scores } of results) {
  for (let i = 0; i < starts.length; i++) {
    console.log(starts[i], ends[i], scores[i])
  }
}

Returns Promise<BigWigFeatureArrays[]>, one entry per chromosome with data.

ArrayFeatureView / BigWigFeature

ArrayFeatureView wraps a BigWigFeatureArrays or SummaryFeatureArrays result and exposes a JBrowse-compatible Feature-style interface. BigWigFeature is a single-feature view into an ArrayFeatureView.

import { BigWig, ArrayFeatureView } from '@gmod/bbi'

const file = new BigWig({ path: 'volvox.bw' })
const arrays = await file.getFeaturesAsArrays('chr1', 0, 100000)
const view = new ArrayFeatureView(arrays, 'mySource', 'chr1')

for (let i = 0; i < view.length; i++) {
  console.log(view.start(i), view.end(i), view.score(i))
}

BigWigFeature exposes get(i, key) and toJSON(). Valid keys: start, end, score, refName, source, summary, minScore, maxScore.

Publishing

Trusted publishing via GitHub Actions.

pnpm version patch  # or minor/major

Academic Use

This package was written with funding from the NHGRI as part of the JBrowse project. If you use it in an academic project that you publish, please cite the most recent JBrowse paper, which will be linked from jbrowse.org.

License

MIT Colin Diesh

Keywords