Skip to main content

memewrap

Python wrappers for the MEME-suite command-line tools: STREME, TOMTOM and FIMO.

Extracted from wrapper code that had been copied across four scripts in two active research repos, each with MEME_BIN = os.path.expanduser("~/miniconda3/envs/meme-suite/bin") hardcoded at module scope.

Why this exists (and where it doesn't)

Checked against PyPI rather than assumed:

STREME TOMTOM FIMO
gimmemotifs 0.18.4 ✗ — wraps 22 tools including dreme.py, the tool STREME deprecated and replaced, but ships no streme.py ✗ — has its own motif-similarity code
pymemesuite 0.1.0a4 real Cython bindings
memewrap ✓ (CLI, chunked)

STREME and TOMTOM are the actual gap. The ecosystem wrapped the previous generation of discriminative motif discovery and never followed it forward.

FIMO is only partly a gap — and if you can install pymemesuite, prefer it. It binds FIMO natively: no subprocess, no temp files. memewrap.fimo drives the CLI instead, which is what a bioconda MEME environment gives you without a compiler, and parallelises across sequence chunks.

Install

pip install memewrap

pip gives you the wrappers and none of the binaries — the MEME suite is a C toolchain, not a Python package:

conda create -n meme-suite -c bioconda -c conda-forge meme
export MEME_BIN=~/miniconda3/envs/meme-suite/bin   # or just put them on PATH

Resolution order is meme_bin= argument → $MEME_BINPATH. Every wrapper raises MemeToolNotFound naming where it looked, so a missing suite fails at setup rather than several minutes into a scan.

Use

from memewrap import run_streme, match_count, run_fimo_parallel, build_feature_matrix

# Discriminative discovery: what is enriched in `primary` relative to `control`?
motifs = run_streme("primary.fa", "control.fa", "out/streme", nmotifs=5, minw=6, maxw=12)

# How many of my motifs match a reference set? (the shape a permutation test needs)
n = match_count(motifs, "jaspar_plants.meme", q_thresh=0.05)

# Scan, then build a (gene x motif) design matrix of max FIMO scores.
tsv = run_fimo_parallel("promoters.fa", "jaspar_plants.meme", "out/fimo", n_chunks=8)
X = build_feature_matrix(tsv, gene_ids, motif_ids)

What each wrapper fixes

These are measured against the source they came from, not stylistic preferences.

run_streme refuses nmotifs and thresh together. STREME's own help says --nmotifs overrides --thresh when positive. One source call site passed both, so it read as "significant motifs, up to N" and meant "exactly N motifs, significant or not" — STREME will emit its Nth motif at p=0.9. Nothing in the output says which rule applied.

Related, and worth stating because it looked like a bug and wasn't: the two source call sites appeared to diverge, one passing --order 2 --thresh 0.05 and one passing neither. Against STREME 5.5.9 those are both the defaults, so the divergence was cosmetic.

run_fimo_parallel no longer loses the header. The source kept the header from chunk 0 and stripped line 0 of every later chunk. fimo --text writes a header only when it writes output, so an empty chunk 0 — routine, since chunks are dealt round-robin — meant chunk 1's header got stripped as a duplicate. Downstream, pd.read_csv promotes the first data row to column names: one hit silently lost, every column mislabelled, no exception. The header is now taken from the first chunk that has one.

match_count applies its threshold where it can be observed. The source passed q_thresh as TOMTOM's -thresh and re-filtered at the same value, so the second filter could never drop a row. TOMTOM now runs permissively and the filtering happens here — which also leaves the written tomtom.tsv complete, so a stricter threshold doesn't require re-running every comparison.

verify_tools checks executability, not existence. os.path.exists is true for a directory named streme and for a non-executable HTML error page saved under that name. Both reported the tool present and then failed inside a subprocess.

verify_meme_db checks the MEME version header, and takes expect_min. Counting ^MOTIF alone validates any file that mentions motifs at line start. And ok cannot express "I expected JASPAR plants CORE and got nine motifs" — a truncated download parses cleanly, finds fewer hits, and reads as a result.

Tests

pip install -e '.[dev]'
pytest

57 tests. The MEME-dependent ones run by default and skip individually, with a reason, only when the binaries are absent — a wrapper verified against a mocked subprocess.run proves the mock matches the wrapper, which is the one relationship that cannot break in production.

The end-to-end control plants a known motif in 90% of the primary sequences and none of the controls, and asserts STREME recovers it; FIMO is then really run, really chunked and really merged over sequences whose hits are known.

tests/test_fimo.py reproduces the source's merge loop verbatim and asserts it fails — the "never trust a test you haven't seen fail" control made permanent, so a regression turns two tests red rather than one.

A 15-mutant pass kills 15/15, including every source behaviour listed above. Two guards were deleted rather than kept after mutation showed them unreachable: an empty-chunk check already guaranteed by a min() bound, and a dropna already handled by pandas' comment and blank-line defaults.

Licence

MIT.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

memewrap-0.1.0.tar.gz (30.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

memewrap-0.1.0-py3-none-any.whl (19.4 kB view details)

Uploaded Python 3

File details

Details for the file memewrap-0.1.0.tar.gz.

File metadata

  • Download URL: memewrap-0.1.0.tar.gz
  • Upload date:
  • Size: 30.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for memewrap-0.1.0.tar.gz
Algorithm Hash digest
SHA256 01f38596f43af16ab464ab3aa474d2497e32ff45be482d682e39c9180277dc89
MD5 22eb1e223304b4b166b056bb34b20036
BLAKE2b-256 a20a5a68bb30a6f554c07cde6c333e4dc144a44977320729bd1a5355f9c41cec

See more details on using hashes here.

File details

Details for the file memewrap-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: memewrap-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 19.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for memewrap-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 46c7e087ede28d4feb1a4269af02231b3f3abdbaa3f97bcfc7feedb904a92a13
MD5 4a3bbdcd8a08ac82bc60f641c7037373
BLAKE2b-256 191e3d7d96d30ae97f85db75e30d5c4a75d19d11acc3a776b4ffd940839ce085

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page