Metadata-Version: 2.4
Name: mimosa-tool
Version: 1.3.1
Summary: Model-Independent Motif Similarity Assessment tool
Author-email: Anton Tsukanov <tsukanov@bionet.nsc.ru>
License-Expression: MIT
Project-URL: Homepage, https://github.com/ubercomrade/mimosa
Project-URL: Repository, https://github.com/ubercomrade/mimosa
Project-URL: Documentation, https://github.com/ubercomrade/mimosa#readme
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy<2.4,>=2.0
Requires-Dist: scipy>=1.14.1
Requires-Dist: pandas>=2.2.3
Requires-Dist: joblib>=1.5.3
Requires-Dist: numba>=0.65.0
Requires-Dist: tqdm
Dynamic: license-file

# MIMOSA

MIMOSA (`mimosa-tool`) is a Python package and CLI for model-independent motif similarity assessment.
It supports two complementary comparison strategies:

- `profile`: compare score profiles, either from precomputed score tracks or from motif scans on sequences
- `motif`: compare motif representations directly, with optional PFM reconstruction for incompatible representations

The current package version is `1.3.1`.

## Introduction

Transcription factors (TFs) are central regulators of gene expression. They modulate transcription by binding
specific DNA segments in regulatory regions such as promoters and enhancers [1]. The DNA segment recognized by a TF
is called a transcription factor binding site (TFBS). Binding sites for the same TF are similar but not identical, so
they are commonly described as motifs that summarize the variability of recognized sequences [2].

Modern high-throughput assays such as ChIP-seq, HT-SELEX, and DAP-seq have produced large collections of TFBS motifs
[3-5]. Position weight matrices (PWMs) and position frequency matrices (PFMs) remain the most common representation
and are produced by widely used discovery tools such as MEME, STREME, and HOMER [6-8]. At the same time, many motif
models now encode dependencies beyond independent nucleotide columns, including Bayesian Markov models, InMoDe,
DIMONT, SiteGA-style dinucleotide models, and neural network predictors [9-21].

Motif comparison is required to decide whether a discovered pattern represents a known specificity, to cluster
redundant motifs across experiments, and to infer functional relationships between TFs from similar binding
preferences. Existing tools such as Tomtom, STAMP, MACRO-APE, and MoSBAT address this problem with matrix alignment,
correlation, Jaccard-like, or affinity-profile approaches [22-25]. A practical limitation is that many tools assume
PFM/PWM-like matrices, which makes heterogeneous comparisons harder and may lose information when dependency-aware
models must be reduced to simple matrices.

MIMOSA addresses this by separating motif comparison into two workflows. The `profile` workflow compares recognition
profiles, either supplied directly as score tracks or generated by scanning sequences with motif models. This is the
most model-independent workflow and is conceptually close to affinity-profile comparison [25]. The `motif` workflow
aligns motif matrices or tensors directly when representations are compatible; for heterogeneous inputs, it
reconstructs PFMs from sequence hits and then applies the same alignment logic, similar in spirit to Tomtom-style
matrix comparison [22, 26].

## Methodology

### Profile Comparison

`profile` mode converts motif behavior into positional score profiles. If inputs are motif models, MIMOSA scans
the supplied FASTA sequences on both strands. If raw scores must be normalized, they are mapped to empirical
`-log10(FPR)` values using either `--background` sequences or the comparison sequences themselves.
This makes scores from different model families more comparable.

The workflow then selects anchor sites from the first model: either one best-scoring site per sequence, or all sites
above `--min-logfpr`. For each anchor, MIMOSA extracts a site-centered window, evaluates compatible windows from the
second model across the requested shift range and strand orientations, scores the aligned windows, and reports the
best orientation and offset. The offset is `target_start - query_start` in the oriented alignment, so positive values
mean the target starts to the right of the query. The four orientation labels are `++`, `+-`, `-+`, and `--`.

### Motif Matrix/Tensor Comparison

`motif` mode aligns motif representations directly. For compatible model families, the native matrix or tensor is
normalized and aligned without sequence scanning. Reverse-complement candidates are evaluated, and only alignments
with at least half of the shorter motif overlapping are considered.

When model families differ, or when `--pfm-mode` is enabled, MIMOSA reconstructs a PFM for each input model:

1. Each model is scanned on the provided or generated sequences.
2. The best site per sequence is collected across position and strand.
3. Sites are ranked by score and the top `--pfm-top-fraction` fraction is retained.
4. A position count matrix is built from retained sites and converted to a PFM with additive pseudocount smoothing.
5. The reconstructed PFMs are compared with the same alignment and orientation search used for native matrices.

### Similarity Metrics

MIMOSA reports higher scores as better matches for all metrics. The profile metrics operate on non-negative
normalized score windows. Let $v_1$ and $v_2$ be two aligned profile vectors.

**Continuous Overlap (`co`)**

The continuous overlap coefficient, also known as the Szymkiewicz-Simpson coefficient, measures how much the smaller
profile is contained in the larger one:

$$
\mathrm{CO}(v_1, v_2) =
\frac{\sum_i \min(v_1^i, v_2^i)}
{\min\left(\sum_i v_1^i, \sum_i v_2^i\right)}
$$

**Continuous Dice (`dice`)**

The Dice coefficient normalizes the shared mass by the total mass of both profiles:

$$
\mathrm{Dice}(v_1, v_2) =
\frac{2 \sum_i \min(v_1^i, v_2^i)}
{\sum_i v_1^i + \sum_i v_2^i}
$$

**Cosine Similarity (`cosine`)**

Cosine similarity compares the angle between two vectors:

$$
\mathrm{Cosine}(v_1, v_2) =
\frac{\sum_i v_1^i v_2^i}
{\sqrt{\sum_i (v_1^i)^2}\sqrt{\sum_i (v_2^i)^2}}
$$

`profile` mode also exposes `co_rowwise` and `dice_rowwise`. These compute one score per selected window and then average finite window scores, instead of pooling all selected windows into one flattened vector. Rowwise variants are useful when many anchors are selected and each anchor should contribute more evenly.

The `motif` metrics operate column-by-column on aligned matrices or flattened tensors. Let $u_t$ and $v_t$ be two aligned columns at position $t$.

**Pearson Correlation (`pcc`)**

$$
\mathrm{PCC}(u_t, v_t) =
\frac{\sum_k (u_{k,t} - \bar{u}_t)(v_{k,t} - \bar{v}_t)}
{\sqrt{\sum_k (u_{k,t} - \bar{u}_t)^2}
\sqrt{\sum_k (v_{k,t} - \bar{v}_t)^2}}
$$

**Euclidean Distance (`ed`)**

$$
\mathrm{ED}(u_t, v_t) = \lVert u_t - v_t \rVert_2
$$

For `ed`, MIMOSA returns the negative mean Euclidean distance across aligned columns so that larger values still
represent more similar motifs.

**Column Cosine (`cosine`)**

For motif matrices, `cosine` is computed column-wise and averaged across the aligned overlap:

$$
\mathrm{Cosine}(u_t, v_t) =
\frac{\sum_k u_{k,t} v_{k,t}}
{\sqrt{\sum_k u_{k,t}^2}\sqrt{\sum_k v_{k,t}^2}}
$$

### Null Hypothesis and Significance

MIMOSA uses a stored pooled null distribution. A null distribution file is built ahead of time from a motif collection split into groups, such as transcription-factor families or classes. The group table defines which motifs are treated as unrelated: for each eligible query motif, null targets are loaded motifs that are present in the group table and have a different group label. Motifs from the same group are not used as null targets for each other.

For PWM/PFM collections, the input collection can also be prepared as a shuffled control set before running MIMOSA, for example by permuting motif positions and nucleotide weights within positions. `mimosa build-null` does not shuffle motifs internally; it treats the supplied shuffled set as the motif collection and still applies the group table to choose unrelated query-target pairs.

MIMOSA compares all eligible query-target pairs selected by these group relations using the selected strategy and metric. Each score is computed after the usual optimization over shifts and orientations. The resulting scores are pooled into one shared null sample:

$$
S_{\text{null}} = \{s(q, t): q \ne t,\; group(q) \ne group(t)\}
$$

For an observed score $S_{\text{obs}}$, significance is computed as an upper-tail survival probability because all
reported metrics are oriented so that larger scores mean stronger similarity:

$$
p = P(S_{\text{null}} \ge S_{\text{obs}})
$$

The pooled distribution is fitted with SciPy's generalized extreme value distribution:

$$
\theta = \operatorname{genextreme.fit}(S_{\text{null}}), \quad
p = \operatorname{genextreme.sf}(S_{\text{obs}}; \theta)
$$

Null distribution files are produced by `mimosa build-null` and stored as trusted `.joblib` files. Each file contains one pooled distribution across all eligible query-target comparisons. For each eligible query motif, MIMOSA compares that query against unrelated target motifs selected from different groups, appends those scores to the shared null sample, and then fits a GEV survival estimator to the pooled scores. The file records:

- comparison strategy and metric
- FASTA and background fingerprints, stored as `none` when sequence-derived scoring is not used
- motif collection fingerprint
- relation input fingerprint
- null-format version
- the GEV estimator parameters
- raw, unsorted null scores in the same order as the stored pairs
- query-target motif-name pairs that contributed scores

At comparison time, `--pvalue` loads either the explicit `--null-distribution` file or the first compatible file found in `--null-search-dir` paths and the user cache (`~/.cache/mimosa/nulls`). Compatibility is checked against the null-format version, strategy, metric, and sequence/background fingerprints. An explicit incompatible file raises an error; a search with no compatible file returns the score-only result and logs a warning.

Annotated results include `p-value`, `adj.p-value`, `E-value`, `null_id`, `null_n`, and `null_estimator`. When more
than one comparison is annotated, `adj.p-value` is computed with SciPy's `stats.false_discovery_control`; for a single
comparison it equals `p-value`. The E-value is `p-value * effective_number_of_targets`; pass
`--effective-number-of-targets` to override the default target count.

## Supported Inputs

| Family | CLI key | Typical inputs |
| :--- | :--- | :--- |
| Precomputed score profiles | `scores` | FASTA-like file with numeric rows |
| PWM / PFM | `pwm` | `.meme`, `.pfm`, or compatible `joblib`-pickled `GenericModel` |
| BaMM | `bamm` | `.ihbcp` or a basename resolvable to `.ihbcp` |
| SiteGA | `sitega` | `.mat` or compatible `joblib`-pickled `GenericModel` |
| DiMotif / Dimont | `dimont` | `.xml` or compatible `joblib`-pickled `GenericModel` |
| Slim | `slim` | `.xml` or compatible `joblib`-pickled `GenericModel` |

Notes:

- `profile` supports all six types above, including direct `scores` vs `scores`
- `motif` supports all motif families except `scores`
- heterogeneous `motif` comparisons automatically switch to sequence-driven PFM reconstruction
- `build-null` accepts directory motif collections for all motif families and multi-motif MEME collections for `pwm`
- BaMM loading uses a uniform background model; a separate background file is not required

### Security note

MIMOSA can load `.pkl` model files and `.joblib` null distribution files. These formats use Python
pickle/joblib serialization and may execute arbitrary code when loaded. Only load such files from trusted sources.

## Installation

MIMOSA requires Python `3.10+`.

Install from PyPI:

```bash
uv pip install mimosa-tool
```

or:

```bash
pip install mimosa-tool
```

Install from source:

```bash
git clone https://github.com/ubercomrade/mimosa.git
cd mimosa
uv sync --group dev
uv pip install -e . --no-build-isolation
```

Main runtime dependencies are declared in [pyproject.toml](pyproject.toml): `numpy`, `scipy`, `pandas`,
`joblib`, `numba`, and `tqdm`.

## Quick Start

Compare two precomputed score profiles:

```bash
mimosa profile examples/scores_1.fasta examples/scores_2.fasta \
  --model1-type scores \
  --model2-type scores \
  --metric cosine
```

Compare two motifs through normalized score profiles:

```bash
mimosa profile examples/gata2.meme examples/gata4.meme \
  --model1-type pwm \
  --model2-type pwm \
  --fasta examples/foreground.fa \
  --background examples/background.fa \
  --metric co \
  --min-logfpr 2 \
  --window-radius 6
```

Compare two motifs directly:

```bash
mimosa motif examples/pif4.meme examples/gata2.meme \
  --model1-type pwm \
  --model2-type pwm \
  --metric pcc
```

Compare motifs from different model families in `motif` mode:

```bash
mimosa motif examples/sitega_stat6.mat examples/pif4.meme \
  --model1-type sitega \
  --model2-type pwm \
  --metric pcc \
  --pfm-mode
```

Build and use a stored null distribution file:

```bash
mimosa build-null motifs.meme \
  --model-type pwm \
  --groups groups.tsv \
  --strategy motif \
  --metric pcc \
  --progress \
  --output motifs-pcc.null.joblib

mimosa motif examples/gata2.meme examples/gata4.meme \
  --model1-type pwm \
  --model2-type pwm \
  --metric pcc \
  --pvalue \
  --null-distribution motifs-pcc.null.joblib
```

Clear cached normalized profiles:

```bash
mimosa cache clear --cache-dir .mimosa-cache
```

## Python API

Use the top-level `mimosa` package for library integration. The stable public API includes model loading,
scanning, comparison, and model-handler registration:

```python
from mimosa import compare_one_to_one, read_model, scan_model

query = read_model("query.meme", "pwm")
target = read_model("target.xml", "dimont")

scores = scan_model(query, sequences, strand="best")
result = compare_one_to_one(query, target, strategy="profile", sequences=sequences)
```

MIMOSA accepts either paths plus model-type keys or preloaded `GenericModel` instances:

```python
from mimosa import GenericModel, compare_one_to_many

query = GenericModel("pwm", "query", representation, length, {"kmer": 1, "_source_pfm": pfm})
results = compare_one_to_many(query, targets, strategy="profile", sequences=sequences)
```

For long one-vs-many runs, pass `progress=True` to render a `tqdm` progress bar on `stderr` without changing the
returned results:

```python
results = compare_one_to_many(query, targets, strategy="profile", sequences=sequences, progress=True)
```

External model families should be integrated through `register_model_handler`. A handler is an adapter bundle with
`scan`, optional `scan_both`, `load`, `write`, and `score_bounds` callables. Functions in `mimosa.handlers` whose
names start with `_` are internal implementation details and should not be imported by downstream projects.

```python
from mimosa import GenericModel, register_model_handler


def load_custom(path: str, kwargs: dict) -> GenericModel:
    return GenericModel("custom", "custom_name", representation, length, {"kmer": 1})


register_model_handler(
    "custom",
    scan=scan_custom,
    scan_both=None,
    load=load_custom,
    write=write_custom,
    score_bounds=custom_score_bounds,
)
```

## CLI Overview

The CLI exposes four top-level commands:

- `mimosa profile`
- `mimosa motif`
- `mimosa build-null`
- `mimosa cache clear`

Comparison, null-building, and cache maintenance commands print one JSON object to `stdout`. Logs and progress bars
are written to `stderr`, so JSON output remains safe to pipe into tools such as `jq`.

Progress bars are controlled by `--progress` and `--no-progress`. The default is automatic: progress is shown only
when `stderr` is an interactive terminal. Use `--progress` to force bars for long local runs, or `--no-progress` for
CI and log files. `-v/--verbose` enables additional logging; when progress is active, log lines are emitted through
`tqdm.write(...)` so they do not corrupt the active bar.

Typical `profile` result:

```json
{
  "query": "model_or_profile_1",
  "target": "model_or_profile_2",
  "score": 0.0,
  "offset": 0,
  "orientation": "++",
  "metric": "co",
  "n_sites": 0
}
```

Typical `motif` result:

```json
{
  "query": "model_1",
  "target": "model_2",
  "score": 0.0,
  "offset": 0,
  "orientation": "++",
  "metric": "pcc"
}
```

If `--pvalue` is used with a compatible null distribution file, the result may also include:

- `p-value`
- `adj.p-value`
- `E-value`
- `null_id`
- `null_n`
- `null_estimator`

`orientation` is one of `++`, `+-`, `-+`, `--`.
`offset` is `target_start - query_start` in the selected oriented alignment for both `profile` and `motif` modes.

## `profile` Mode

`profile` is the general-purpose workflow for comparing positional score signals.

It supports:

- direct `scores` vs `scores` comparisons
- motif-vs-motif comparisons through sequence scanning
- empirical score normalization with background calibration
- optional on-disk caching of normalized profile bundles
- p-value annotation from compatible stored null distribution files

If motif scanning is required and `--fasta` is omitted, MIMOSA generates random A/C/G/T sequences with:

- `--num-sequences` default `1000`
- `--seq-length` default `200`

If `--background` is provided, normalization is fitted on those sequences and applied to the comparison set.
If omitted, normalization is fitted on the same sequence set used for comparison. The hidden legacy alias
`--promoters` is still accepted for compatibility, but `--background` is the documented name.

Supported metrics:

- `co`
- `co_rowwise`
- `dice`
- `dice_rowwise`
- `cosine`

Important arguments:

| Flag | Meaning |
| :--- | :--- |
| `--model1-type`, `--model2-type` | `scores`, `pwm`, `bamm`, `sitega`, `dimont`, `slim` |
| `--fasta` | FASTA sequences used to scan motif inputs |
| `--background` | FASTA used to calibrate empirical profile normalization |
| `--num-sequences` | number of random sequences when `--fasta` is omitted |
| `--seq-length` | random sequence length when `--fasta` is omitted |
| `--metric` | `co`, `co_rowwise`, `dice`, `dice_rowwise`, or `cosine` |
| `--search-range` | maximum motif shift explored, default `10` |
| `--window-radius` | site-centered half-window size, default `10` |
| `--realign-window` | local target-anchor realignment half-width, default `3` |
| `--min-logfpr` | empirical log-tail threshold for anchors; omitted or `0` uses one best anchor per sequence |
| `--cache` | `off` or `on` |
| `--cache-dir` | cache directory, default `.mimosa-cache` |
| `--pvalue` | annotate using a compatible stored null distribution file |
| `--null-distribution` | explicit trusted null distribution file path from `mimosa build-null` |
| `--null-search-dir` | repeatable additional null distribution file search directory |
| `--effective-number-of-targets` | override E-value target count |
| `--seed` | random seed, default `127` |
| `--jobs` | number of parallel jobs, default `-1` |
| `--progress`, `--no-progress` | show or suppress progress bars on `stderr`; default auto-detects terminals |
| `-v`, `--verbose` | verbose logging |

Example with two motif models:

```bash
mimosa profile examples/myog.ihbcp examples/pif4.meme \
  --model1-type bamm \
  --model2-type pwm \
  --metric co
```

## `motif` Mode

`motif` compares motif representations directly.

Supported metrics:

- `pcc`
- `ed`
- `cosine`

Execution rules:

- if model types match and `--pfm-mode` is not enabled, MIMOSA aligns native matrices or tensors directly
- if model types differ, MIMOSA reconstructs PFMs from sequences automatically
- `--pfm-mode` forces PFM reconstruction even when both inputs use the same model family

If PFM reconstruction is required and `--fasta` is omitted, MIMOSA generates random A/C/G/T sequences with:

- `--num-sequences` default `20000`
- `--seq-length` default `100`

Important arguments:

| Flag | Meaning |
| :--- | :--- |
| `--model1-type`, `--model2-type` | `pwm`, `bamm`, `sitega`, `dimont`, `slim` |
| `--fasta` | optional FASTA for PFM reconstruction |
| `--num-sequences` | number of random sequences when `--fasta` is omitted |
| `--seq-length` | random sequence length when `--fasta` is omitted |
| `--metric` | `pcc`, `ed`, or `cosine` |
| `--pfm-mode` | force sequence-driven PFM reconstruction |
| `--pfm-top-fraction` | top fraction of reconstructed hits used for PFM building, default `0.05` |
| `--pvalue` | annotate using a compatible stored null distribution file |
| `--null-distribution` | explicit trusted null distribution file path from `mimosa build-null` |
| `--null-search-dir` | repeatable additional null distribution file search directory |
| `--effective-number-of-targets` | override E-value target count |
| `--seed` | random seed, default `127` |
| `--jobs` | number of parallel jobs, default `-1` |
| `--progress`, `--no-progress` | show or suppress progress bars on `stderr`; default auto-detects terminals |
| `-v`, `--verbose` | verbose logging |

Example:

```bash
mimosa motif examples/sitega_gata2.mat examples/pif4.meme \
  --model1-type sitega \
  --model2-type pwm \
  --metric ed \
  --pfm-mode
```

## `build-null` Mode

`mimosa build-null` creates a trusted joblib null distribution file with one pooled null distribution from a motif
collection and a relation input. Directory collections are loaded deterministically for any motif type when
`--model-type` is provided; multi-motif MEME collections are supported for `--model-type pwm`. Motif names must be
unique.

A group relation table is required. `--groups` must point to a table with motif-name and group columns; targets from
different groups are used as null targets.

For `--strategy profile`, `build-null` uses FASTA sequences or generates random sequences with the `profile` defaults
(`--num-sequences 1000`, `--seq-length 200`). For `--strategy motif`, direct same-family matrix/tensor comparison does
not need sequences. If `--pfm-mode` is enabled, sequence-driven PFM reconstruction uses the same `--fasta` or random
sequence options.

Important arguments:

| Flag | Meaning |
| :--- | :--- |
| `motifs` | directory collection or multi-motif MEME file |
| `--model-type` | `pwm`, `bamm`, `sitega`, `dimont`, or `slim` |
| `--pattern` | optional glob for directory collections |
| `--groups` | TSV/CSV motif-to-group table |
| `--name-column`, `--group-column` | column names for `--groups`, defaults `motif` and `group` |
| `--ignore-missing-relations` | ignore relation names absent from the loaded collection |
| `--strategy` | `profile` or `motif` |
| `--metric` | defaults to `co` for `profile` and `pcc` for `motif` |
| `--fasta`, `--background` | sequence inputs for profile scoring or `--pfm-mode` reconstruction |
| `--search-range`, `--window-radius`, `--realign-window`, `--min-logfpr` | profile comparator options |
| `--pfm-mode`, `--pfm-top-fraction` | PFM reconstruction options for motif nulls |
| `--cache`, `--cache-dir` | profile cache options during null building |
| `--output` | output `.joblib` null distribution file path |
| `--install-cache` | also copy the null distribution file into `~/.cache/mimosa/nulls` |
| `--strict` | fail when a query has too few null targets |
| `--min-null-targets` | minimum number of null targets per query, default `1` |
| `--seed`, `--jobs` | random seed and parallelism |
| `--progress`, `--no-progress` | show or suppress query and target progress bars on `stderr`; default auto-detects terminals |

Group-table example:

```bash
mimosa build-null H14CORE_meme_format.meme \
  --model-type pwm \
  --groups H14CORE_annotation.tsv \
  --name-column motif \
  --group-column family \
  --strategy motif \
  --metric pcc \
  --progress \
  --output hocomoco-pwm-motif-pcc.null.joblib
```

Using the null distribution file:

```bash
mimosa motif examples/gata2.meme examples/gata4.meme \
  --model1-type pwm \
  --model2-type pwm \
  --metric pcc \
  --pvalue \
  --null-distribution hocomoco-pwm-motif-pcc.null.joblib
```

If `--install-cache` was used while building the null distribution file, later comparisons can omit
`--null-distribution` and search the user cache automatically when `--pvalue` is enabled. Use `--null-search-dir` for
additional project-local file directories.

The build command prints a JSON summary with the null distribution file path, optional cache path, number of motifs
loaded, number of queries used in the pooled distribution, skipped queries, and total comparisons run.

## `cache` Command

`mimosa cache clear` removes derived profile artifacts created by `mimosa profile --cache on`.

```bash
mimosa cache clear --cache-dir .mimosa-cache
```

The command prints:

```json
{
  "cache_dir": ".mimosa-cache",
  "removed": 0
}
```

## Python API

The public API is exported from [src/mimosa/__init__.py](src/mimosa/__init__.py).

High-level comparison helpers:

- `compare_one_to_one(...)`
- `compare_one_to_many(...)`
- `create_one_to_one_config(...)`
- `create_one_to_many_config(...)`
- `run_one_to_one(...)`
- `run_one_to_many(...)`
- `create_comparator_config(...)`
- `compare(...)`
- `validate_metric(...)`

Model and scanning helpers:

- `read_model(...)`
- `scan_model(...)`
- `get_scores(...)`
- `get_frequencies(...)`
- `get_sites(...)`
- `get_pfm(...)`
- `register_model_handler(...)`

Strand-aware scanning and site helpers accept `strand="best"`, `"+"`, `"-"`, or `"both"`.
`"best"` collapses the two strands by taking the best score per position, while `"both"` keeps `+` and `-`
predictions as separate observations for threshold calibration and site extraction. Threshold-table calibration and
site/PFM reconstruction use `"both"` by default.

Types and utility exports:

- `GenericModel`
- `StrandMode`
- `ComparisonResult`
- `OneToOneConfig`
- `OneToManyConfig`
- `ComparatorConfig`
- `clear_cache(...)`
- `read_models(...)`
- `build_null_distributions(...)`
- `load_null_distribution_file(...)`
- `save_null_distribution_file(...)`
- relation parser: `parse_group_relations(...)`

Single comparison example:

```python
from mimosa import compare_one_to_one

result = compare_one_to_one(
    "examples/gata2.meme",
    "examples/gata4.meme",
    query_type="pwm",
    target_type="pwm",
    strategy="profile",
    sequences="examples/foreground.fa",
    background="examples/background.fa",
    metric="co",
    min_logfpr=2.0,
)
```

One-vs-many example:

```python
from mimosa import compare_one_to_many

results = compare_one_to_many(
    "examples/pif4.meme",
    [
        "examples/gata2.meme",
        "examples/foxa2.meme",
    ],
    query_type="pwm",
    target_type="pwm",
    strategy="motif",
    metric="pcc",
    progress=True,
)
```

`progress=True` is a runtime-only API option. It does not become part of `ComparatorConfig`, cache keys, or null
distribution compatibility signatures.

Site extraction and PFM reconstruction example:

```python
from mimosa import get_pfm, get_sites, read_model
from mimosa.io import read_fasta

model = read_model("examples/pif4.meme", "pwm")
sequences = read_fasta("examples/foreground.fa")

sites = get_sites(model, sequences, mode="best", strand="both")
pfm = get_pfm(model, sequences, mode="best", strand="both", top_fraction=0.05)
```

## Extension Hooks

Custom model families can be registered at runtime through `register_model_handler(...)`.
A handler bundle provides:

- `load`
- `scan`
- optional `scan_both`
- `write`
- `score_bounds`

This makes it possible to integrate new motif representations without changing the public comparison API.

## Development

Common local commands:

```bash
uv sync --group dev
uv run pytest
uv run ruff check .
uv run ruff format --check .
```

Focused test commands:

```bash
uv run pytest tests/test_unit.py
uv run pytest tests/test_integration.py
```

## Bibliography

1. Lambert, S. A., Jolma, A., Campitelli, L. F., Das, P. K., Yin, Y., Albu, M., Chen, X., Taipale, J.,
   Hughes, T. R., & Weirauch, M. T. (2018). The human transcription factors. _Cell_, 172(4), 650-665.
   https://doi.org/10.1016/j.cell.2018.01.029

2. Wasserman, W. W., & Sandelin, A. (2004). Applied bioinformatics for the identification of regulatory elements.
   _Nature Reviews Genetics_, 5(4), 276-287. https://doi.org/10.1038/nrg1315

3. Park, P. J. (2009). ChIP-seq: advantages and challenges of a maturing technology.
   _Nature Reviews Genetics_, 10(10), 669-680. https://doi.org/10.1038/nrg2641

4. Jolma, A., Kivioja, T., Toivonen, J., Cheng, L., Wei, G., Enge, M., Taipale, M., Vaquerizas, J. M.,
   Yan, J., Sillanpaa, M. J., Bonke, M., Palin, K., Talukder, S., Hughes, T. R., Luscombe, N. M.,
   Ukkonen, E., & Taipale, J. (2010). Multiplexed massively parallel SELEX for characterization of human
   transcription factor binding specificities. _Genome Research_, 20(6), 861-873.
   https://doi.org/10.1101/gr.100552.109

5. O'Malley, R. C., Huang, S. C., Song, L., Lewsey, M. G., Bartlett, A., Nery, J. R., Galli, M.,
   Gallavotti, A., & Ecker, J. R. (2016). Cistrome and epicistrome features shape the regulatory DNA landscape.
   _Cell_, 165(5), 1280-1292. https://doi.org/10.1016/j.cell.2016.04.038

6. Bailey, T. L., & Elkan, C. (1994). Fitting a mixture model by expectation maximization to discover motifs
   in biopolymers. _Proceedings of the International Conference on Intelligent Systems for Molecular Biology_,
   2, 28-36.

7. Bailey, T. L. (2021). STREME: accurate and versatile sequence motif discovery. _Bioinformatics_, 37(18),
   2834-2840. https://doi.org/10.1093/bioinformatics/btab203

8. Heinz, S., Benner, C., Spann, N., Bertolino, E., Lin, Y. C., Laslo, P., Cheng, J. X., Murre, C.,
   Singh, H., & Glass, C. K. (2010). Simple combinations of lineage-determining transcription factors prime
   cis-regulatory elements required for macrophage and B cell identities. _Molecular Cell_, 38(4), 576-589.
   https://doi.org/10.1016/j.molcel.2010.05.004

9. Grau, J., Posch, S., Grosse, I., & Keilwagen, J. (2013). A general approach for discriminative de novo motif
   discovery from high-throughput data. _Nucleic Acids Research_, 41(21), e197.
   https://doi.org/10.1093/nar/gkt831

10. Eggeling, R., Grosse, I., & Grau, J. (2017). InMoDe: tools for learning and visualizing intra-motif
    dependencies of DNA binding sites. _Bioinformatics_, 33(4), 580-582.
    https://doi.org/10.1093/bioinformatics/btw689

11. Siebert, M., & Soding, J. (2016). Bayesian Markov models consistently outperform PWMs at predicting motifs
    in nucleotide sequences. _Nucleic Acids Research_, 44(13), 6055-6069.
    https://doi.org/10.1093/nar/gkw521

12. Ge, W., Meier, M., Roth, C., & Soding, J. (2021). Bayesian Markov models improve the prediction of binding
    motifs beyond first order. _NAR Genomics and Bioinformatics_, 3(2), lqab026.
    https://doi.org/10.1093/nargab/lqab026

13. Toivonen, J., Das, P. K., Taipale, J., & Ukkonen, E. (2020). MODER2: first-order Markov modeling and
    discovery of monomeric and dimeric binding motifs. _Bioinformatics_, 36(9), 2690-2696.
    https://doi.org/10.1093/bioinformatics/btaa045

14. Mathelier, A., & Wasserman, W. W. (2013). The next generation of transcription factor binding site prediction.
    _PLoS Computational Biology_, 9(9), e1003214. https://doi.org/10.1371/journal.pcbi.1003214

15. Levitsky, V. G., Ignatieva, E. V., Ananko, E. A., Turnaev, I. I., Merkulova, T. I., Kolchanov, N. A.,
    & Hodgman, T. C. (2007). Effective transcription factor binding site prediction using a combination of
    optimization, a genetic algorithm and discriminant analysis to capture distant interactions.
    _BMC Bioinformatics_, 8, 481. https://doi.org/10.1186/1471-2105-8-481

16. Tsukanov, A. V., Mironova, V. V., & Levitsky, V. G. (2022). Motif models proposing independent and
    interdependent impacts of nucleotides are related to high and low affinity transcription factor binding sites
    in Arabidopsis. _Frontiers in Plant Science_, 13, 938545. https://doi.org/10.3389/fpls.2022.938545

17. Alipanahi, B., Delong, A., Weirauch, M. T., & Frey, B. J. (2015). Predicting the sequence specificities of
    DNA- and RNA-binding proteins by deep learning. _Nature Biotechnology_, 33(8), 831-838.
    https://doi.org/10.1038/nbt.3300

18. Hassanzadeh, H. R., & Wang, M. D. (2016). DeeperBind: enhancing prediction of sequence specificities of DNA
    binding proteins. _Proceedings of the IEEE International Conference on Bioinformatics and Biomedicine_, 2016,
    178-183. https://doi.org/10.1109/BIBM.2016.7822515

19. Chen, C., Hou, J., Shi, X., Yang, H., Birchler, J. A., & Cheng, J. (2021). DeepGRN: prediction of transcription
    factor binding site across cell-types using attention-based deep neural networks. _BMC Bioinformatics_, 22, 38.
    https://doi.org/10.1186/s12859-020-03952-1

20. Wang, K., Zeng, X., Zhou, J., Liu, F., Luan, X., & Wang, X. (2024). BERT-TFBS: a novel BERT-based model for
    predicting transcription factor binding sites by transfer learning. _Briefings in Bioinformatics_, 25(3),
    bbae195. https://doi.org/10.1093/bib/bbae195

21. Jing Zhang, F., Zhang, S. W., & Zhang, S. (2022). Prediction of transcription factor binding sites with an
    attention augmented convolutional neural network. _IEEE/ACM Transactions on Computational Biology and
    Bioinformatics_, 19(6), 3614-3623. https://doi.org/10.1109/TCBB.2021.3126623

22. Gupta, S., Stamatoyannopoulos, J. A., Bailey, T. L., & Noble, W. S. (2007). Quantifying similarity between
    motifs. _Genome Biology_, 8(2), R24. https://doi.org/10.1186/gb-2007-8-2-r24

23. Mahony, S., & Benos, P. V. (2007). STAMP: a web tool for exploring DNA-binding motif similarities.
    _Nucleic Acids Research_, 35(Web Server issue), W253-W258. https://doi.org/10.1093/nar/gkm272

24. Vorontsov, I. E., Kulakovskiy, I. V., & Makeev, V. J. (2013). Jaccard index based similarity measure to
    compare transcription factor binding site models. _Algorithms for Molecular Biology_, 8, 23.
    https://doi.org/10.1186/1748-7188-8-23

25. Lambert, S. A., Albu, M., Hughes, T. R., & Najafabadi, H. S. (2016). Motif comparison based on similarity of
    binding affinity profiles. _Bioinformatics_, 32(22), 3504-3506.
    https://doi.org/10.1093/bioinformatics/btw489

26. van Dongen, S., & Enright, A. J. (2012). Metric distances derived from cosine similarity and Pearson and
    Spearman correlations. _arXiv preprint_, arXiv:1208.3145. https://doi.org/10.48550/arXiv.1208.3145

## License

MIT. See [LICENSE](LICENSE).
