v1.0.0
A full refactor and modernization of FinaleToolkit. The Python API and numeric
behavior are preserved — the test suite passes (80 passed, 27 skipped; CRAM
tests run where samtools is available). The internals, command line, and
documentation were modernized.
Added
- Single import namespace. Every public feature/class is reachable directly
fromfinaletoolkit(e.g.finaletoolkit.coverage,finaletoolkit.wps,
finaletoolkit.GenomeGaps) via lazy attribute resolution. The subpackage
paths (finaletoolkit.frag,.utils,.genome,.io) still work. Singular
aliasesend_motif/breakpoint_motifare also exposed. - Named return types.
coverage/single_coveragereturnCoverageResult
andfrag_length_intervalsreturnsFragLengthStats—NamedTuples that
index and unpack like plain tuples while adding documented named fields. - Exception hierarchy (
finaletoolkit.exceptions):FinaleToolkitError
withInvalidInputError,UnsupportedFormatError,MissingReferenceError,
MissingIndexError,ContigNotFoundError,ContigMismatchError,
OutOfBoundsError. Each subclasses the built-in it replaces
(ValueError/FileNotFoundError/IndexError), so existingexcepthandlers
still catch them. - Click command line, rendered with rich-click. Every subcommand's
--help
shows panels grouping related options, an example invocation, and uniform
metavars (INPUT,REGIONS,REFERENCE,CHROM_SIZES, ...). Accent colors
are chosen to stay legible on both dark and light terminals. Pass-o -to
write any output to standard output (stdout). - Type hints and NumPy-style docstrings on every public function/class.
- Shared helpers eliminate copy-paste:
frag/_motif_common.py(motif classes,
MDS, drivers),utils/_parallel.py(pool + tqdm),io/writers.py,
cli/_args.py(reusable Click options),cli/_dispatch.py(lazy dispatch).
Changed
-
Command line reimplemented on Click + rich-click (previously argparse).
The flag names were redesigned for consistency — the one intentional break
from the previous CLI. The Python API is unchanged: each flag keeps the
parameter name matching its function argument, so only command-line spellings
changed.Concept Old CLI flag(s) New CLI flag Output path -o/--output-file-o/--output(-= stdout)Optional reference -r/--reference-file-r/--referenceMinimum mapping quality -q/--quality-threshold-q/--min-mapqMin/max fragment length -min/--min-length,-max/--max-length--min-length,--max-lengthDeprecated length aliases -lo/--fraction_low,-hi/--fraction-highremoved Worker processes -w/--workers-t/--threadsVerbosity mixed store_true/count-v/--verbose(counting)k-mer length -k(no long form)-k/--kmer-lengthStrand toggle (motifs) -B/--no-both-strands,-B/--single-strand--strand {both,forward,reverse}coveragescale factor-s/--scale-factor--scale-factorfrag-length-binsshort stat-sf/--short-fraction--short-thresholdfrag-length-binssummary-stats/--summary-stats--summary-statsfrag-length-binshistogram--histogram-path--histogramfrag-length-intervalsshort cutoff-s/--short-reads--short-thresholdcleavage-profileleft/right pad-l/--left,-r/--right--pad-left,--pad-rightwpschrom.sizes-c/--chrom-sizes--chrom-sizesadjust-wpsinterval size-i/--interval_size-i/--interval-sizeadjust-wpssavgol toggle-S/--exclude-savgol--savgol/--no-savgoldelfimerge size-s/--window-size--merge-sizedelfiblacklist-b/--blacklist-file-b/--blacklistfilter-filewhitelist/blacklist-W/--whitelist-file,-B/--blacklist-file-w/--whitelist,-b/--blacklistagg-bwmean-a/--mean--meanThe overloaded short flags were the driver:
-spreviously meant five
different things and-rmeant two; each short flag now has one meaning.
Boolean options use Click's--x/--no-xpairs (e.g.--savgol/--no-savgol)
with the default stated in the help text, and subcommands disable prefix
matching so--savgolis never ambiguous with--savgol-window-size. -
interval-mdsrenamed toregional-mds— the regional Motif Diversity
Score (rMDS), per Bandaru et al., Journal of Clinical Investigation 2026
(196284). The implementing
function is_cli_regional_mds. -
Documentation rebuilt on a custom, compact in-tree Sphinx theme
(Northwestern-purple accents, Inter typography, light/dark). The CLI reference
is generated from the live Click commands (sphinx-click), the API reference
from docstrings (autodoc), and the user guide was restructured. CI
(build-docs.yml,.readthedocs.yaml) installs the package and the docs
toolchain.
Removed
- The deprecated
delfi-gc-correctCLI command. GC correction is performed by
delfiautomatically (delfi --no-gc-correctopts out). The Python function
finaletoolkit.frag.delfi_gc_correctis unchanged and still available.
Performance (identical outputs, lower cost)
- DELFI worker pool is ~80x faster on whole-genome inputs while producing
bit-identical output: the blacklist BED is parsed once and filtered per window
with binary search (instead of being re-read and linearly scanned for every
100kb window), and one alignment handle and one reference handle are opened
per worker via thePoolinitializer and reused for every window. Per-contig
ContigGapsare preloaded into worker globals rather than pickled into every
task. Contributed by D.H.K. (Duco) Gaillard
(@DucoG) in
#172; guarded by new
test_workers_equivalenceandtest_fragfile_inputtests. - DELFI GC content is counted with
str.countinstead of a per-base Python
loop, and short/long fragments are tallied with counters. frag_length_binsbinning is vectorized withnp.add.at.adjust-wpsrunning median/mean usesliding_window_view.- Streaming fragment access and bounded memory are preserved throughout.
Fixed
genome.GenomeGaps.in_tcmere: removed a strayprintthat fired for chr17,
and fixed the telomere-overlap branch (it previously evaluated overlap against
an empty array and was alwaysFalse).frag._delfi_gc_correct.cli_delfi_gc_correctandfrag._delfi.delfistdout
(-) output: rows are stringified before"\t".join(...)(previously joined
raw tuple values and raisedTypeError).frag._delfi_merge_bins.delfi_merge_bins: thegc_correctedargument is
honored, so merging works when GC correction is disabled.MotifsIntervals.from_file:.gzinputs are opened in read mode (previously
opened with"wt", truncating the file). The walrus-operator count check in
MotifFreqs.from_filereports the real count.MotifFreqs.from_file/MotifsIntervals.from_file: a missing/unreadable input
no longer raises a maskingUnboundLocalError; the realFileNotFoundError
propagates.adjust-wps --edge-sizeanddelfi --window-sizedeclaretype=int.
Preserved (compatibility-critical quirks)
genome.ContigGaps.in_tcmere/in_gapkeep theall()-over-telomeres
semantics that the bundled DELFI reference outputs were generated with.- The two hard-coded hg19 no-coverage bin indices (
8779,13664) removed by
DELFI whenremove_nocov=True. multi_wpsreorders intervals into BAM-header contig order before writing
(the 0.12.0 fix for silently-dropped chromosomes) and forwards
fraction_low/fraction_highto workers.
Full refactor merged in #180. Full Changelog: v0.12.0...v1.0.0 · see CHANGELOG.md.