DDLBlacklist

Script: ddlblacklist.sh Package: ddl Class: DDLBlacklistMaker.java

Builds a DDL kmer blacklist from pre-built DDL sketch files. Reads sketches with kmer arrays (built with kmers=t in ddlwriter.sh), promotes each TaxID to genus level, counts distinct genera per kmer across all input files, and outputs overrepresented kmers as FASTA with multi-level taxonomic counts in the header. These blacklists are autoloaded by DDLCompare and applied during sketching by DDLWriter to reduce noise from widely-shared kmers, improving signal quality in taxonomic distance calculations.

Basic Usage

ddlblacklist.sh in=sketches.tsv out=blacklist.fa [mincount=20] [k=19]

Input sketch files must have been built with kmers=t in ddlwriter.sh. Multiple input files may be specified as a comma-delimited list; files are processed sequentially and sketch data is discarded after kmer extraction to minimize memory usage.

Two Operating Modes

DDLBlacklist operates in one of two modes:

Sketch Requirements

Input sketches must have been built with kmers=t in ddlwriter.sh to store the raw kmer values alongside sketch scores. Sketches built without kmers=t cannot be used for blacklist generation (DDLBlacklist will print an error). The k and exponent parameters must match those used during sketch construction.

Memory Note

The tool autodetects memory and defaults to 4GB (-Xmx4g). For large datasets spanning many RefSeq clades, the kmer-to-genera map may require substantially more memory. Processing 12 RefSeq clades containing 304 million distinct kmers from 200,000 records requires significantly more than the default 4GB allocation.

Output Header Format

Each blacklisted kmer is written as a FASTA entry. The header encodes taxonomic breadth and sequence complexity:

>kmer_7f3a9c1e2b raw=312 g=312 f=89 o=34 c=15 p=7 k=3 sk=2 e=0.847
raw
Distinct genus-level TaxIDs containing this kmer. This is the primary count used for filtering.
g / f / o / c / p / k / sk
Distinct taxa at genus / family / order / class / phylum / kingdom / superkingdom level, promoted from the genus TaxIDs. These allow post-hoc filtering at any taxonomic resolution using simple awk commands on the FASTA headers.
e
Shannon entropy of the kmer's trimer distribution (0 to 1). Low-entropy kmers are repetitive or low-complexity sequences (e.g., homopolymers or simple repeats). Entropy is calculated using sub-kmers of length entropyk.

The FASTA sequence line contains the decoded kmer nucleotide sequence.

Parameters

Input/Output parameters

in=<file>
Input DDL sketch file(s). Accepts comma-delimited list of multiple files (e.g., in=archaea.tsv.gz,bacteria.tsv.gz,viral.tsv.gz). Files are processed sequentially. All input sketches must have been built with kmers=t.
out=<file>
Output FASTA file of overrepresented kmers. Supports gzip compression (use .fa.gz extension). Required unless running in condense or validate-only mode.
blacklist=<file>
(bl) FASTA blacklist file for condense mode. When condense=t, this blacklist is loaded and used to prefer non-blacklisted kmers when reducing sketch bucket counts. Not used in standard blacklist generation mode.

Filtering parameters

mincount=20
(mintaxcount, mintaxa) Minimum number of distinct genus-level TaxIDs that must contain a kmer for it to be included in the blacklist output. Lower values produce larger, more aggressive blacklists. Default is 20 in the Java source; the shell script usage examples show 5 for whole-genome blacklists and 80-200 for ribosomal blacklists depending on taxonomic level.
minentropy=0
(entropy) Minimum Shannon entropy threshold. Kmers with trimer entropy below this value are included in the blacklist regardless of their genus count. Set to a value between 0 and 1 to blacklist low-complexity kmers (e.g., minentropy=0.5). Disabled (0) by default.
entropyk=3
(ek) Sub-kmer length for entropy calculation. Entropy is computed over the distribution of overlapping sub-kmers of this length within the full k-mer. Default value of 3 uses trimer (3-mer) distribution.

Sketch compatibility parameters

k=19
K-mer length. Must exactly match the k-mer length used when building the input sketches with ddlwriter.sh. Common values: 19 for SSU/ITS ribosomal blacklists, 31 for whole-genome blacklists.
exponent=<int>
(ebits) Exponent bits parameter for DynamicDemiLog. Must match the exponent value used when building the input sketches. Common values: 4 for ribosomal sketches, 5 for whole-genome sketches.

Condense mode parameters

condense=f
Enable condense mode. When set to true, reduces double-sized sketches (e.g., 4096-bucket) to half size (2048-bucket) while preferring non-blacklisted kmers at each bucket position. Useful for approximating the effect of a blacklist without re-reading raw genome data. Requires blacklist= to be set for meaningful results.
validate=f
Validate shared keys at each taxonomic distance. In blacklist generation mode with a single input file, reloads the file after processing and runs the validation step. In condense mode, runs validation on the condensed sketches. Produces a table of average shared keys by common ancestor level (species through superkingdom), enabling quantitative measurement of blacklist effectiveness.
samples=100000
(validatesamples) Number of random pairs to sample during validation. Higher values give more stable estimates. The shell script documentation shows 200,000 as a typical value for production blacklist validation.

Java Parameters

-Xmx
Set Java's memory usage, overriding autodetection. Default is 4GB (-Xmx4g). For large multi-clade datasets, increase to match available RAM (e.g., -Xmx64g for full RefSeq processing).
-eoom
Exit if an out-of-memory exception occurs. Requires Java 8u92+.
-da
Disable assertions.

Examples

Build a Ribosomal Kmer Blacklist (16S)

# Step 1: Build double-sized sketches with kmer storage from 16S database
ddlwriter.sh in=16S.fa.gz out=16S_sketches.tsv k=19 buckets=256 exponent=4 \
    mode=pertid kmers=t lineage=t

# Step 2: Generate blacklist at family level
ddlblacklist.sh in=16S_sketches.tsv out=bl_16S_family.fa k=19 exponent=4 \
    mincount=160 validate=t samples=200000

# Step 3: Inspect output headers to verify counts
grep "^>" bl_16S_family.fa | head -5

The double-sized sketch (buckets=256 instead of the standard 128) is required so condense mode can later reduce back to the normal size while preferring non-blacklisted kmers. The validate step reports average shared keys at each taxonomic distance, letting you confirm the blacklist reduces noise without harming within-genus signal.

Build a Whole-Genome Blacklist from Multiple RefSeq Clades

# Step 1: Build double-sized sketches per clade (run separately for each)
ddlwriter.sh in=refseq.bacteria.fna.gz out=bacteria.tsv.gz k=31 buckets=4096 \
    exponent=5 mode=pertid kmers=t lineage=t tossjunk t=32
ddlwriter.sh in=refseq.archaea.fna.gz out=archaea.tsv.gz k=31 buckets=4096 \
    exponent=5 mode=pertid kmers=t lineage=t tossjunk t=32

# Step 2: Generate combined kmer dump across all clades
ddlblacklist.sh in=archaea.tsv.gz,bacteria.tsv.gz,fungi.tsv.gz,viral.tsv.gz \
    out=combined_dump.fa.gz k=31 exponent=5 mincount=5

# Step 3: Filter combined dump at chosen thresholds using awk
# (genus/250, family/50, order/20, class/10, phylum/5)
zcat combined_dump.fa.gz | awk '/^>/{keep=0; \
    if ($2~/g=/ && ...) keep=1} keep{print}' > filtered_blacklist.fa

Files are processed sequentially and each clade's sketch data is discarded after kmer extraction, so total memory is determined by the kmer map size rather than all sketches simultaneously. Using a low mincount=5 in the dump step captures all potentially useful kmers; thresholding is done in post-processing after inspecting the cumulative distribution of genus counts.

Validate Blacklist Effectiveness via Condense Mode

# Condense double-sized sketches to normal size while preferring non-blacklisted kmers,
# then validate shared-key statistics across taxonomic distances
ddlblacklist.sh in=archaea.tsv.gz,bacteria.tsv.gz,viral.tsv.gz \
    condense=t validate=t blacklist=genomeDDLBlacklist.fa \
    k=31 exponent=5 samples=200000

This approximates the effect of the blacklist on real comparisons without re-reading and re-sketching terabytes of genome data. The output table shows average shared keys at species, genus, family, order, class, phylum, kingdom, and superkingdom levels. A good blacklist reduces class-and-above noise substantially while preserving genus-level signal near its original value.

Algorithm Details

Genus Promotion

Each sketch record carries a TaxID. Before counting, DDLBlacklist walks the NCBI taxonomy tree upward from the record's TaxID to find the enclosing genus node. All kmers from that record are credited to the genus TaxID, not the original species or strain TaxID. This ensures that a genus with hundreds of sequenced strains does not artificially inflate kmer counts relative to a poorly-sequenced genus.

Multi-Level Header Generation

After collecting the genus-to-kmer mapping, the tool promotes each genus set further up the tree (family, order, class, phylum, kingdom, superkingdom) using distinct-count tracking. The resulting header fields allow post-hoc filtering at any taxonomic level using simple awk commands on the output FASTA, without re-running the tool.

Entropy Filtering

Shannon entropy of the kmer's sub-kmer distribution is computed and written to each header. Entropy is calculated using overlapping sub-kmers of length entropyk (default 3, i.e., trimers) within the full k-mer sequence. The resulting value is normalized to [0, 1] where 0 means perfectly repetitive and 1 means maximally uniform. Setting minentropy > 0 captures low-complexity kmers that should be blacklisted regardless of their taxonomic breadth.

Condense Mode Details

Double-sized sketches have 2N buckets where a normal sketch has N. Condense mode pairs up bucket i with bucket i+N and selects the winner for the condensed bucket. The selection logic is:

This approximates what would happen if the blacklist were active during original sketching: blacklisted kmers would not compete for bucket slots, and the next-best kmer at each bucket would be used instead.

Validation Statistics

The validate mode samples random pairs of records and computes shared key counts, WKID (Weighted Kmer Identity), and estimated ANI (Average Nucleotide Identity) for each pair, then bins results by the level of the pair's common ancestor in the taxonomy tree. The noise floor metric (average shared keys at class+ distance) is the primary quality indicator: a well-tuned blacklist reduces this substantially while keeping within-genus shared keys near their original value.

Known Blacklist Performance (from shell script documentation)

Workflow Integration

DDL Tool Suite

DDLBlacklist fits into the DDL (Deterministic Locality-sensitive hashing for Lineage) workflow:

Blacklist Generation Workflow Summary

  1. Build double-sized sketches with kmers=t using ddlwriter.sh.
  2. Run ddlblacklist.sh with a low mincount to produce a comprehensive kmer dump.
  3. Filter the dump at chosen per-level thresholds using awk on FASTA headers.
  4. Merge filtered blacklists using ddlmerger.sh.
  5. Validate effectiveness using condense mode (condense=t validate=t).
  6. Optionally iterate: re-sketch with the blacklist active to expose second-tier masked kmers, then re-run ddlblacklist.sh on the new sketches and merge.

Applying a Blacklist

Once generated, a blacklist FASTA is applied in two ways:

Support

For questions and support: