Skip to content

The .snipesig format

snipe computes alignment-free QC metrics — coverage, depth, error and mutation rates, contamination, ploidy signals — from a sketch of the sequencing data rather than from an alignment. .snipesig is the native format that stores that sketch: a full-fidelity edgemer signature, including every hash, abundance, and metadata field, so a signature written now reloads with the same contents later. The same input produces the same signature (same checksum).

.snipesig is the single signature format snipe writes. Internally it is Parquet-encoded: the edgemer data lives in columnar Parquet, and the whole thing carries a self-describing header. There is no separate .parquet extension — Parquet is the encoding of .snipesig, not a different file type. The extension changed nothing about what a signature is; it changed how the bytes are laid out on disk.

Two pieces make up the file:

  • Edgemer columns, stored in compressed (zstd) Parquet row-groups. This is the K1/K2 hash and abundance payload — the edgemers themselves.
  • A snipe_signature_header blob — the full signature header serialized as JSON and stored in the Parquet footer’s key-value metadata. It carries the ksize parameters, counts, checksums, and the rest of the signature’s identity alongside the columnar data.

Because the header travels with the columns, a .snipesig file is self-describing: everything needed to reconstruct the signature is inside it, including data that plainer formats would drop — for example, a signature sketched with --keep-acgt round-trips with full fidelity.

Every signature carries a k1_checksum in its header — an md5 computed over the signature’s sorted, distinct K1 hash set. The same K1 content produces the same checksum whether the signature is an edgemer signature or a K1-only one, and it is stable across a save/load round-trip.

The checksum is abundance-independent: two signatures with the same K1 hashes but different counts share a checksum, so it answers “are these the same k-mer set?” without regard to depth. snipe info reports it directly:

K1 checksum (md5): 85e65cc582d48cbf2fa1b2b7c9b552c7

The checksum is an md5 over the signature’s sorted, distinct K1 hashes.

Writes are always Parquet, always single-signature

Section titled “Writes are always Parquet, always single-signature”

There is only one thing snipe writes: a single Parquet-encoded signature per file. JSON writing was removed entirely — there is no environment hatch to force legacy output, and no multi-signature file on the write path. Commands that emit a signature, including downscale and export, produce one signature; they operate on a single signature and reject legacy multi-signature input.

Before Parquet, .snipesig was a JSON-gzip encoding. snipe still reads those older files — that path is preserved as read-only backward compatibility — but it never writes them.

The loader auto-detects the encoding by the file’s leading magic bytes, so you never pass a flag to say which kind you have:

  • PAR1 → Parquet-encoded .snipesig (the current format)
  • 1f 8b (gzip) or [ → legacy JSON-gzip .snipesig

Both resolve through the same load path, so old and new signatures behave identically once in memory. Only the writer has moved on.