ruby-minibwa

Gem Version Test Lines of Code DOI

Ruby bindings for minibwa, a short-read aligner combining bwa-mem seeding with minimap2 chaining and alignment.

Installation

Requires a C compiler, zlib, and Ruby >= 3.2.

git clone --recursive https://github.com/kojix2/ruby-minibwa
cd ruby-minibwa
bundle install
bundle exec rake compile

The extension builds the vendored minibwa sources, including libsais for index construction. Expect the first build to take a few minutes.

Usage

Build an index:

require "minibwa"

Minibwa::Index.build("ref.fa", "ref", n_thread: 4)

This writes ref.l2b and ref.mbw. Indexes made by the minibwa index command are also usable.

Map reads:

opt = Minibwa::Options.new
opt.preset("sr")  # or "adap", "lr"

idx = Minibwa::Index.load("ref")

hits = idx.map("ACGT...", name: "read1", opt: opt)
hits.each do |h|
  puts [h.ctg, h.ts, h.te, h.strand, h.qs, h.qe, h.mapq, h.cigar_str].join("\t")
end

Map many reads in one call:

seqs  = ["ACGT...", "TGCA..."]
names = ["read1", "read2"]
hits  = idx.map_batch(seqs, names: names, opt: opt)
# => [[Hit, ...], [Hit, ...]]

Use a reusable buffer for repeated mapping:

buf = Minibwa::Buffer.new
idx.map(seq, buf: buf)

Generate SAM output:

puts Minibwa::Sam.header(idx)
hits.each do |h|
  puts Minibwa::Sam.format("read1", 0, h, seq)
end

Note on reverse-strand alignments: For hits where hit.rev is true, the SAM spec requires SEQ to be the reverse complement of the original query and the FLAG to have 0x10 set. Sam.format does not do this automatically — pass the already-oriented sequence and the correct flag. The library does not retain the original query after mapping.

With pe: true, map_batch treats consecutive sequences as read pairs.

CIGAR

Hit#cigar and #cigar_str cover the aligned region only and contain no clipping, which is how minibwa reports alignments. #full_cigar_str takes the query length and adds soft clips derived from qs and qe.

Threads

Options#n_thread affects only Index.build (via libsais + OpenMP). Mapping itself is single-threaded per call, but releases the GVL, so Ruby threads run in parallel. To map from several Ruby threads, give each one its own buffer:

buf = Minibwa::Buffer.new
idx.map(seq, opt: opt, buf: buf)

A Buffer holds mutable scratch state and must not be shared between threads mapping at the same time.

Development

bundle exec rake compile
bundle exec rake test

bin/console gives an IRB session with the extension loaded.

License

MIT. The vendored minibwa is MIT as well; its GPL-licensed files (bwtgen.c, QSufSort.c, providing the low-memory BWT construction option) are neither compiled nor distributed. See ext/minibwa/minibwa/LICENSE.txt.