npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gmod/cram

v8.4.0

Published

read CRAM files with pure Javascript

Readme

@gmod/cram

NPM version Build Status

Read CRAM files with pure JS, works in node or the browser. Supports CRAM 2.x and 3.x, .crai indexes, and all CRAM v3 block codecs (gzip, bzip2, lzma, rANS, arithmetic, fqzcomp, tok3). See docs/CODEC_SUPPORT.md.

Install

npm install @gmod/cram

Usage

import { IndexedCramFile, CraiIndex } from '@gmod/cram'
import { IndexedFasta } from '@gmod/indexedfasta'

const fasta = new IndexedFasta({
  path: '/path/to/reference.fa',
  faiPath: '/path/to/reference.fa.fai',
})

const idToName = []
const nameToId = {}

const indexedFile = new IndexedCramFile({
  cramPath: '/path/to/file.cram',
  // alternatives: cramUrl, cramFilehandle (see generic-filehandle2)
  index: new CraiIndex({
    path: '/path/to/file.cram.crai',
    // alternatives: url, filehandle
  }),
  seqFetch: async (seqId, start, end) => {
    // seqId is numeric; coordinates are 1-based but IndexedFasta is 0-based
    return fasta.getSequence(idToName[seqId], start - 1, end)
  },
  checkSequenceMD5: false,
})

// Build numeric refId <-> name mappings from the SAM header
const samHeader = await indexedFile.cram.getSamHeader()
samHeader
  .filter(l => l.tag === 'SQ')
  .forEach((sqLine, refId) => {
    sqLine.data.forEach(item => {
      if (item.tag === 'SN') {
        nameToId[item.value] = refId
        idToName[refId] = item.value
      }
    })
  })

// Fetch records for a range (1-based, closed coordinates)
const records = await indexedFile.getRecordsForRange(
  nameToId['chr1'],
  10000,
  20000,
)

for (const record of records) {
  console.log(record.readName, record.alignmentStart, record.mappingQuality)

  // Extract variants from read features
  for (const feature of record.readFeatures ?? []) {
    if (feature.code === 'X') {
      // SNP: single base substitution
      console.log(`SNP at ${feature.refPos}: ${feature.ref}->${feature.sub}`)
    } else if (feature.code === 'I') {
      // Insertion: full inserted sequence
      console.log(`Insertion at ${feature.refPos}: ${feature.data}`)
    } else if (feature.code === 'i') {
      // Insertion: padding only (no sequence stored)
      console.log(`Insertion at ${feature.refPos} (no sequence)`)
    } else if (feature.code === 'D') {
      // Deletion: bases deleted from reference
      console.log(`Deletion at ${feature.refPos}: ${feature.data} bases`)
    }
  }
}

See the example directory for browser usage with <script> tag and the bundled cram-bundle.js.

For more complex operations like generating CIGAR strings from read features, see the JBrowse readFeaturesToNumericCIGAR implementation.

API

IndexedCramFile

new IndexedCramFile({
  cramPath, // local path
  cramUrl, // remote URL
  cramFilehandle, // generic-filehandle2 compatible handle
  index, // CraiIndex instance (or any object with getEntriesForRange)
  seqFetch, // async (seqId, start, end) => string
  checkSequenceMD5, // default true; set false to avoid large reference fetches
  cacheSize, // max cached records, default 20000
})
  • getRecordsForRange(seqId, start, end, opts?)Promise<CramRecord[]> — 1-based closed coords. opts: { viewAsPairs, pairAcrossChr, maxInsertSize }
  • hasDataForReferenceSequence(seqId)Promise<boolean>

CraiIndex

Takes { path, url, filehandle } — one of the three is required.

CramRecord

Properties:

  • readName — read name
  • sequenceId — numeric reference ID
  • alignmentStart — 1-based start position
  • qualityScoresUint8Array of per-base quality scores
  • readFeatures — array of read features (see below)
  • tags — auxiliary tags object

Flag methods (all return boolean):

  • isPaired()
  • isProperlyPaired()
  • isSegmentUnmapped()
  • isMateUnmapped()
  • isReverseComplemented()
  • isMateReverseComplemented()
  • isRead1()
  • isRead2()
  • isSecondary()
  • isFailedQc()
  • isDuplicate()
  • isSupplementary()

Methods:

  • getReadBases()string | null | undefined — returns the read sequence string. Requires seqFetch to be configured and is populated automatically by getRecordsForRange.
  • getCigarString()string — returns the CIGAR string describing the read's alignment (e.g. "50M2I48M"), reconstructed from the read features. Substitutions and mismatches are reported as M per the plain CIGAR convention; unmapped reads return "*". Does not require seqFetch.

ReadFeatures

Each entry in record.readFeatures:

  • code — feature type (one of bqBXIDiQNSPH, see CRAM spec §8)
  • pos — read position (1-based)
  • refPos — reference position (1-based)
  • ref / sub — reference and substituted base (code X only)

Error classes

  • CramUnimplementedError — unimplemented spec feature
  • CramMalformedError — malformed file data
  • CramBufferOverrunError — read past end of data

Academic Use

Written with NHGRI funding as part of JBrowse. If you use this in a publication, please cite the most recent JBrowse paper at jbrowse.org.

License

MIT © Robert Buels

Publishing

Trusted publishing via GitHub Actions.

pnpm version patch  # or minor/major