AniAnn's: ANI Inferred ANNotation of Tandem Repeats
AniAnn's is an a priori satellite array detection and annotation software package. AniAnn's uses a matrix of Average Nucleotide Identity (ANI) values similar to ModDotPlot in order to infer the location and orientation of satellite arrays. It introduces new downstream analysis to accurately annotate its contents and boundaries.
You can download the current release from GitHub by using:
git clone https://github.com/marbl/anianns.git
cd anianns
Although optional, we recommend setting up a virtual environment:
python -m venv venv
source venv/bin/activate
Once the virtual environment is activated, you can install the required dependencies:
python -m pip install .
By default, AniAnn's installs without ModDotPlot as a dependency. If you would like to include ModDotPlot into the same venv for plotting, you can install using the following command:
python -m pip install .[moddotplot]
AniAnn's is also available to install using PyPI:
pip install anianns
Once installed, confirm AniAnn's was installed correctly by running python -m anianns -h, or simply with the shortcut anianns -h:
__ __
_ _ _ .' `'._.'` '.
/ \ _ __ (_) / \ _ __ _ __ ' ___ | .--; ;--. |
/ _ \ | '_ \| | / _ \ | '_ \| '_ \ / __| | ( / \ ) |
/ ___ \| | | | | / ___ \| | | | | | | \__ | \ ;` /^\ `; /
/_/ \_\_| |_|_|/_/ \_\_| |_|_| |_| |___/ :` .'._.'. `;
'-`'.___.'`-'
usage: anianns [-h] {annotate,build_db,ntrprism} ...
Ani Ann's: ANI Inferred ANNotation of Tandem Repeats
positional arguments:
{annotate,build_db,ntrprism} Choose mode: annotate, build_db, ntrprism
annotate Takes an input fasta and outputs an annotated bedfile of satellite arrays.
build_db Takes an input fasta, a bedfile of satellite coordinates, and an optional config file and outputs a db of satellite k-mers.
ntrprism Takes an input fasta, and a bedfile or region. Outputs k-mer histogram.
options:
-h, --help show this help message and exit
Note that AniAnn's might take a while to run during your first usage. This is because the Python interpreter is compiling source code into the pycache directory. Subsequent runs will use the pre-compiled code and load much faster!
AniAnn's must be run either in annotate mode, or build_db mode.
anianns annotate -f <FASTA_FILENAME(S)> <ARGS>
AniAnn's requires at least one FASTA file as input. It generates one output annotation file (default BED) per sequence contained in the input FASTA file(s). Output annotation files are named based on the sequence identifier from the FASTA header.
Annotation of arrays into known satellite classes must be done through the use of a satellite k-mer database, using the command --classify <directory>. See creating an annotation database for more information.
-f / --fasta <FILENAME(S)>
Fasta file(s) to input. Multifasta files are accepted.
-s / --seq_id <STR>
Sequence ID to extract (multiple if using multifasta file). Will ignore if not found. Default: None.
-d / --directory <DIR>
Name of output directory. Default: current working directory.
-o / --output-format <STR>
Output annotation file format. Options are BED, GTF, GFF, CSV, TSV, JSON. Default: BED.
GTF and GFF output uses 1-based inclusive coordinates, tandem_repeat features,
and includes the AniAnn's repeat name and inferred monomer length in the attributes.
-m / --mask <ALL>
Name or repeat length of satellite arrays to mask. Replaces deteced satellites with N's. See Repeat Masking for more info. Default: None.
--soft <BOOL>
Softmask flag. Instead of N's, will force bases lower-case in detected satellite arrays. Must be used with --mask. Default: None.
-c / --classify <DIR>
Directory containing .db or .msh k-mer db files. Required for annotation into known satellites. Default: None.
-t / --threshold <INT>
Confidence threshold. This relates to the minimum percentage of k-mers in a satellite array required to be within that are contained within the selected. A lower number will be more sensitive, at the risk Default: 50.
-k / --kmer <INT>
K-mer size to use. This should be large enough to distinguish unique k-mers with enough specificity, but not too large that sensitivity is removed. Default: 21.
-i / --identity <INT>
Minimum sequence identity cutoff threshold when running ModDotPlot. While it is possible to go as low as 50% sequence identity, anything below 80% is not recommended. Default: 86.
-w / --window <INT>
The central dotplot window size. AniAnn's automatically scans half, the supplied
value, and double the supplied value. For example, -w 5000 scans windows of
2500, 5000, and 10000 bp. AniAnn's hashes each sequence band once, scans the
additional resolutions without dense matrices, reconciles overlapping calls,
and boundary-refines only the winning call at each locus. If the initial
right-boundary range has no supported transition, refinement searches back to
the left using k-mers observed at least three times in the candidate core. This
prevents an unresolved call from defaulting to a matrix-band endpoint.
Boundary refinement runs NTRPrism at both k=6 and the user-selected k-mer
length. A significant k=6 result supplies the monomer estimate; the
user-selected k-mer result is used only when k=6 rejects. If both reject,
AniAnn's removes the candidate even when its matrix or distal signal is strong,
so final annotations never use a monomer score below 3 bp as a fallback.
Periodic rescues target long arrays whose repeat unit produces
several regularly spaced lines parallel to the main diagonal rather than one
solid diagonal block. AniAnn's scans a bounded set of diagonal lags without
materializing a full matrix, requires at least three high-contrast harmonics
with consistent row coverage, and independently confirms the inferred period
with NTRPrism before adding the candidate. Broad dense blocks, isolated
off-diagonal matches, and single parallel lines do not pass this rescue path.
Comparable spans favor the finer resolution; a coarser call wins when it
recovers materially more supported array sequence.
Default: 2000 (scans 1000, 2000, and 4000).
--band <FLOAT>
AniAnn's streams the sequence in bands of this many megabases. Normal
annotation scans outward from the diagonal without materializing a full band
matrix; --plot or --distal creates the primary-resolution matrix needed for
visualization or distal-link detection. Default: 2.
--cache-dir <DIR>
Opt in to reusable canonical k-mer hashing. When the directory contains a
matching cache for the FASTA sequence and k-mer size, AniAnn's loads it;
otherwise AniAnn's creates the cache during the run. Without --cache-dir,
hashes are streamed in memory and no disk cache is read or created.
Default: caching disabled.
-j / --threads <INT>
Maximum total compute concurrency used by AniAnn's. By default, AniAnn's uses
all threads available to its Numba runtime. During an uncached multi-band run,
one worker is reserved for streaming k-mer hashes while the remaining workers
run the matrix kernels. With --threads 1, hashing and matrix processing run
synchronously so the limit is preserved. Default: all available threads.
Distal annotation runs also write satellite_dsu.tsv and a human-readable
satellite_dsu.txt; non-distal runs do not create either file. Each
boundary-refined satellite is a DSU node, including unlinked singletons.
Validated distal links union their two satellite nodes, so chains of distal
relationships share one stable component_id; the table also reports
component size and direct-link count. BED itemRgb values are shared only by
satellites that have both the same DSU component and the same retained
NTRPrism signature (monomer, periodicity, and HOR status). Missing NTRPrism
monomers are not grouped by color.
--identifier <STR>
Name of identifier. Used when no matches to a k-mer db are found, or if --classify is not provided. bed file to output to. Default: None.
-p / --plot <bool>
Save two PNGs for every --band length matrix under
<output directory>/matrix_plots; plots are not displayed interactively. The
standard filename is a hollow, edge-only view: cyan intensity shows the
normalized Sobel gradient response and green outlines show detected diagonal
satellites. With --distal, distal link rectangles are also highlighted in
red. The companion _identity.png file is a higher-resolution, inverted
11-level Spectral ANI heatmap with an identity colorbar; values below the ANI
cutoff are white, and it has no Sobel, satellite, distal, or annotation legend.
Adjacent matrix pairs receive the same two views. Sobel
is visualization-only and does not affect satellite or distal-link prediction.
Default: disabled.
--distal
Detect distal-satellite links independently of whether plots are requested.
Detected off-diagonal blocks are written to
<sequence>_distal_links.bedpe, and used to link satellites in the DSU. A
compact candidate-neighborhood matrix retaining two neighboring windows on
either side of each candidate is used in memory and is not written to disk. An
unmatched distal axis must pass NTR Prism and boundary refinement before it is
added to BED/CSV or linked in the DSU. Strong distal support cannot rescue an
endpoint rejected at both k values.
Neighboring bands are bridged with bounded candidate-to-all comparisons in both
directions plus a 50-window seam scan. With both --distal --plot, links are
outlined in red. When the bridge finds evidence, a sparse
two-band heatmap is saved under matrix_pairs/; adjacent pairs are then skipped
by the final global comparison to avoid duplicate work.
Default: disabled.
--verbose
Show stage timings, the number of potential candidates, concise acceptance or removal reasons for each boundary-refined candidate, and resolved boundary histograms. Per-matrix timing comparisons and unresolved extension histograms are omitted. Each candidate begins with a labeled separator, and every boundary histogram line is capped at 80 characters, including searches that resolve after extending the initial boundary range. Default: disabled.
--log
Write the verbose output to a timestamped file in the selected output directory
while continuing to show it in the terminal. The filename records the local run
date and time, for example
anianns_annotation_log_2026-08-04_14-37-52.txt. This option implies
--verbose and cannot be combined with --quiet. A distal run also writes a
per-sequence <sequence>_distal_summary.txt containing the score, density, row
coverage, column coverage, and hit count for every accepted distal satellite
pair.
Default: disabled.
--quiet
Suppress all stdout and stderr output, including the AniAnn's banner, sequence status, progress bars, warnings, and completion messages. Output files are still written normally. Default: disabled.
anianns -f sample_sequences/sample_hap1_.fa
Upon running the above command, you should see the following output in sample_hap1.bed:
#chrom start end name score strand thickStart thickEnd itemRgb
sample_hap1 67178 407613 147 . 67178 407613 31,119,180
sample_hap1 458676 466557 64 . 458676 466557 174,199,232
sample_hap1 634665 668075 5 . 634665 668075 255,127,14
sample_hap1 670071 1148691 68 . 670071 1148691 255,187,120
sample_hap1 1148878 1472729 5 . 1148878 1472729 44,160,44
sample_hap1 1472878 2702615 42 . 1472878 2702615 152,223,138
sample_hap1 2729748 2834698 5 . 2729748 2834698 214,39,40
sample_hap1 3044478 3208742 147 . 3044478 3208742 255,152,150
sample_hap1 3225278 3297085 48 . 3225278 3297085 148,103,189
This is a BED file containing inferred satellite intervals. The value in the score column indicates the periodicity of the satellite array. Since no k-mer database was used, AniAnn's does not attempt to classify each array.
To classify each line of the BED file into a known satellite array, a database of k-mers must be used. See creating an annotation database for more information. We will use the following provided k-mer db for our sample run:
anianns -f sample_sequences/sample_hap1.fa --classify sample_sequences/sample_kmer_db
#chrom start end name score strand thickStart thickEnd itemRgb
sample_hap1 67178 407613 ACRO 147 . 67178 407613 31,119,180
sample_hap1 458676 466557 Walusat 64 . 458676 466557 174,199,232
sample_hap1 634665 668075 HSat3 5 . 634665 668075 255,127,14
sample_hap1 670071 1148691 bSat 68 . 670071 1148691 255,187,120
sample_hap1 1148878 1472729 HSat3 5 . 1148878 1472729 255,127,14
sample_hap1 1472878 2702615 HSat1A 42 . 1472878 2702615 152,223,138
sample_hap1 2729748 2834698 HSat3 5 . 2729748 2834698 255,127,14
sample_hap1 3044478 3208742 ACRO 147 . 3044478 3208742 31,119,180
sample_hap1 3225278 3297085 CER 48 . 3225278 3297085 148,103,189
Note that you must use the default k-mer value as the classification database. The default k = 21. AniAnn's will label arrays it determines to be related as the same color in itemRgb.
For a more thorough analysis of the region, run anianns -f sample_sequences/sample_hap1_.fa --distal
To visualize the matrix evidence behind the annotations, add --plot:
anianns annotate -f sample_sequences/sample_hap1.fa -d sample_hap1_plots --plot
This saves an annotated Sobel view and a high-resolution spectral identity view
for each sequence band under sample_hap1_plots/matrix_plots. Satellite
intervals and Sobel edges are labeled on the annotated view, with its legend
placed outside the matrix. Combining --plot with --distal also outlines
supported distal matches and saves any adjacent-band views under
matrix_pairs.
anianns annotate -f <FASTA_FILENAME(S)> --mask <ARGS>
Use of AniAnn's as a tool to mask satellite arrays from a given sequence is done through the -m/--mask argument. AniAnn's will output each sequence into its own masked fasta file in the --directory ouptut folder. By default, running --mask with no parameters will mask everything deemed a satellite array.
- If string parameter(s) are provided (e.g.,
hSat1 hSat2), AniAnn's will mask arrays that match the provided class. Note this must be used in conjunction with--classifyin order to match names. Matches are case-insensitive. - If integer parameter(s) are provided (e.g.,
6 7 42), AniAnn's will mask arrays whose predominant monomer length is equal to that provided.
anianns build_db -f <FASTA_FILENAME(S)> -b <BED_FILENAME(S)> <ARGS>
Building a database of satellite k-mers is how AniAnn's can match a detected satellite array into a known repeat class. AniAnn's will extract and compress k-mers at the coordinates provided by a bed file. Running this will create a directory at --directory.
-f / --fasta <FILENAME(S)>
Fasta file(s) to input. Multifasta files are accepted.
-b / --bed <FILENAME(S)>
Bed file(s) to input. Must contain at least 4 columns: 1 chrom, 2 start, 3 end, 4 name.
-c / --config <FILENAME>
Name of config file to use. See Sample database for more infoDefault: None.
-k / --kmer <INT>
K-mer size. Note that k-mers must be the same length when running anianns annotate in order for classification to work. Default: 21.
-d / --directory <DIR>
Specifies the output directory where results will be saved. If not provided, AniAnn's automatically creates an output folder in the current working directory:
- If the BED file contains a track header, the folder name will be derived from that header.
- If no header is present, the folder name will default to the k-mer length (e.g., k_21). Default: current working directory.
-v / --verbose <BOOL>
Verbose logging output. Will output a log file into --directory. Default: False.
-q / --quiet <BOOL>
Suppress all logging output. Default: False.
Here, we will create a db of known satellite arrays using the HG002 human genome CenSat annotation track (credit: Hailey Loucks):
wget https://raw.githubusercontent.com/hloucks/CenSatData/refs/heads/main/HG002/v1.1/hg002v1.1.cenSatv2.0.bed
We want to remove any centromere transition regions ct from this BED file:
awk 'NR==1 || $4!="ct"' hg002v1.1.cenSatv2.0.bed > hg002v1.1.cenSatv2.0.ctRemoved.bed
Finally, we want to group related satellite arrays into the same class. This is done using a --config file. For this example, we will use the file provided in config folder of this repo:
head config/sample_config.json
{
"gSat": [
"gSat(GSAT,GSATX)",
"gSat(GSAT)",
"gSat(GSATII,GSATX)",
"gSat(GSATII,TAR1)",
"gSat(GSATII)",
"gSat(GSATX)",
"gSat(TAR1)"
],
This merges the k-mers of all variations of gSat into the same class. Anything not in the config file is not included in the k-mer db. The config file must be in standard JSON format. If a config file is not provided, each unique value in column 4 of the input bed file will become its own unique class.
Creating a k-mer db for HG002 using the provided config file takes around 3 minutes. This results in 16.9 million unique k-mers, compressed down into a 53mb directory. Note that increasing the k-mer size will increase the directory size, as a more specific k-mer threshold will increase the total number of unique k-mers.
NTRPrism reports the most common distances between consecutive occurrences of the same forward k-mer in one FASTA region. Nearby spacing values are combined before ranking and plotting, so values such as 170 and 171 bp contribute to the same peak by default.
anianns ntrprism \
-f assembly.fa.gz \
-s chr1_MATERNAL \
-r 120000000 121000000 \
-k 6The region uses 0-based, half-open coordinates. By default, the command prints
the ten strongest merged spacing peaks, each peak's count as a percentage of
the requested interval, and a horizontal ASCII histogram. It does not create
files unless --save is supplied:
anianns ntrprism \
-f assembly.fa.gz \
-s chr1_MATERNAL \
-r 120000000 121000000 \
-k 11 \
--save \
-d chr1_ntrprismWith --save, AniAnn's also writes a top-ten text report and a PNG histogram.
The -k / --kmer option controls the k-mer length and defaults to 21, matching
the annotation pipeline. The
default nearby-value merge distance is 1 bp; use --merge-distance to change
it. Use --quiet --save for files without the terminal report. Missing or
unreadable FASTA files, unknown sequence IDs, invalid ranges, and regions
shorter than the selected k-mer size produce an error and a nonzero exit status.
For bug reports or general usage questions, please raise a GitHub issue, or email alex dot sweeten at nih dot gov