SKESA (Strategic K-mer Extension for Scrupulous Assemblies) compiled to WebAssembly using Emscripten. Runs genome assembly entirely in the browser or Node.js with no server required.
Serve the repository and open demo/index.html:
python3 -m http.server 8000
# Visit http://localhost:8000/demo/Upload paired FASTQ files (or gzipped FASTQ) and click "Assemble".
import { readFileSync } from 'fs';
import { gunzipSync } from 'zlib';
const { default: createSKESA } = await import('./build/skesa.js');
const stdout = [];
const stderr = [];
const skesa = await createSKESA({
wasmBinary: readFileSync('./build/skesa.wasm'),
noInitialRun: true,
print: (t) => stdout.push(t),
printErr: (t) => stderr.push(t),
});
// Write reads to virtual filesystem
const r1 = gunzipSync(readFileSync('reads_R1.fastq.gz'));
const r2 = gunzipSync(readFileSync('reads_R2.fastq.gz'));
skesa.FS.writeFile('/r1.fastq', r1);
skesa.FS.writeFile('/r2.fastq', r2);
// Run assembly
skesa.callMain([
'--reads', '/r1.fastq,/r2.fastq',
'--cores', '1',
'--min_contig', '200',
]);
// Output is in stdout array (FASTA format)
const fasta = stdout.join('\n');Requires Docker with the Emscripten SDK image:
./compile-docker.shOutputs build/skesa.js and build/skesa.wasm.
node test/test.mjsAssembles T7 phage reads and verifies the output (1 contig, ~40kb genome).
The SKESA source code required several fixes for correct operation on wasm32 (where size_t is 32-bit vs 64-bit on x86-64):
-
Read storage bit-packing (
common_util.hpp): Cast touint64_tbefore left-shifting nucleotide values by >= 32 bits. Without this, half of all nucleotides in the read storage were corrupted due toptrdiff_tbeing 32-bit on wasm32. -
Kmer count packing (
KmerInit.hpp,counter.hpp): Changed count storage fromsize_ttouint64_t. SKESA packs strand info and branching data into the upper 32 bits of kmer counts using shifts (<< 48,<< 32), which overflow on 32-bitsize_t. -
Thread forcing (
skesa.cpp): Forces single-threaded operation (ncores=1) on Emscripten builds.
SKESA is a United States Government Work and is in the public domain. See src/LICENSE.