Skip to main content

Research Helpers

License Python Tests Documentation

Research Helpers is a set of utilities for managing code-intensive research projects and their accompanying papers. Includes shared figure styling, LaTeX table generation and rendering, a build pipeline that keeps a paper's generated tables and figures from drifting out of date, submission packaging for arXiv and Zenodo, structured logging, and a parameter-sweep engine for scheduler job arrays.

Read the documentation

Features

  • Generated Tables and Figures: Build the paper's tables and figures from the repository's own data
  • Drift Detection: Detect when the paper and the data differ
  • Numbers in the Prose: Track every number a sentence states back to the data that supports it, and audit the prose for any untracked values
  • Several Documents: Give a technical note or a supplement its own generated tables, figures, and checks
  • LaTeX Assembly: Compose tables for LaTeX and also display them in Jupyter
  • Shared Figure Styling: Consistent look across LaTeX and Jupyter
  • Submission Packaging: Automatic preparation and pre-checking for arXiv and Zenodo
  • Parameter Sweeps: Plan a grid, run it as a scheduler job array, resume if necessary, and collect the results
  • Campaigns: Put hundreds of sweeps through a few arrays, resume them, and recover from elements that ran twice
  • Aggregation: Combine repeated runs into confidence intervals, with no dependencies on the cluster side
  • Structured Logging: Console and file output at separate levels, with progress bars and colour output

Installation

The core package has no third-party dependencies. Specifically, the code path that runs on a cluster only depends on the standard library. Planning a sweep, running an array task, checking its status, sizing the array and computing a confidence interval all work on a node with nothing but Python on it. Everything that needs a library is a capability, installed as an extra:

pip install research-helpers[figures]   # matplotlib, seaborn
pip install research-helpers[latex]     # LaTeX table assembly and rendering (stdlib only)
pip install research-helpers[log]       # structlog, colorama, tqdm
pip install research-helpers[sweep]     # pandas, pyarrow (planning, running, and intervals need neither)

Requires Python 3.11 or newer.

Quick Start

Wire up the project

A project's wiring—i.e., where the paper lives, how wide it is, where runs are written—goes in the [tool.research-helpers] section of the pyproject.toml file.

[tool.research-helpers.paper]
main = "tex/paper.tex"
tables-dir = "tex/tables"
figures-dir = "tex/figures"
text-width-pt = 468.0 # as reported by \showthe\textwidth

[tool.research-helpers.figures]
profile = "print"
palette = "colorblind"
dpi = 300

research-helpers doctor shows every setting, the value in force, and where it came from.

Keys and values are described in the configuration reference.

Generate a table from data

import json

from research_helpers.build import TABLES, Registry
from research_helpers.latex import half_up, header, table

tables = Registry(TABLES)


@tables.register('tab:scores')
def scores() -> str:
    """Accuracy on the held-out set."""
    data = json.loads(SCORES_PATH.read_text())
    return table(
        spec='lr',
        header_rows=[[header('System'), header('Accuracy')]],
        body_rows=[[name.title(), half_up(v['accuracy'] * 100)] for name, v in data.items()],
        caption='Accuracy on the held-out set.',
        label='tab:scores',
    )


if __name__ == '__main__':
    raise SystemExit(tables.main())

The label names the file, so this is written to scores.tex and the paper reads it with \input{tables/scores}:

$ python -m demo.tables --install
wrote build/tables/scores.tex
installed tex/tables/scores.tex

Check for drift

$ python -m demo.tables --check
OK: all 1 tables in the paper are current

If the data is changed without rebuilding, the check fails:

$ python -m demo.tables --check
stale, the paper is behind the data: tab:scores
to fix: rebuild and install the tables
$ echo $?
1

For a full example, see adding a generated table.

Style a figure for the page

import matplotlib.pyplot as plt

from research_helpers.figures import apply_style, save

apply_style(profile='print')  # \textwidth across, paper font sizes
fig, ax = plt.subplots()  # the profile's size is already in rcParams
ax.plot(iterations, accuracy, marker='o')
save(fig, 'tex/figures/learning-curve.png')

See details in the figures guide.

Run a parameter sweep

from research_helpers.sweep import Sweep

sweep = Sweep()


@sweep.context
def prepare(manifest, run_dir):
    """Loaded once per array task."""
    return load_corpus(manifest.metadata['corpus'])


@sweep.evaluate
def evaluate(params, corpus):
    """One parameter combination."""
    return {'f1': score(corpus, **params)}


if __name__ == '__main__':
    raise SystemExit(sweep.main())
$ python sweep_demo.py plan --config sweep.toml --run-dir runs/demo --tasks 4
planned 12 combinations over 4 array tasks (~3 per task)
manifest: runs/demo/manifest.json

submit with:
  sbatch --array=1-4 <your sbatch script> runs/demo

The manifest is written once and the tasks read it, so re-submitting the two that were killed reproduces exactly their original slices instead of repartitioning the grid. Resumption is per combination, not per task, so a job that hits its wall-time keeps everything it finished. status and run need only the standard library, so nothing needs to be installed to run a progress check from a login node.

Full details are discussed in the sweeps guide.

Package a submission

$ research-helpers arxiv --dry-run
  paper.tex                       43.1 KB
  paper.bbl                       82.1 KB
  tables/scores.tex                0.3 KB
  figures/learning-curve.png      66.3 KB

  4 files, 0.19 MB
  bbl format 3.3 (TeX Live 2025)

ready to upload: select xelatex and TeX Live 2025

(dry run, nothing written)

The target files are keyed by the path they take inside the submission, so what resolves locally will also resolve at the destination. The checks cover filenames arXiv rejects, a .bbl that is missing, stale, or in a format the selected TeX Live will not read, and microtype font expansion under an engine that has none. --tar packs it reproducibly, so re-packing an unchanged submission gives an identical file.

See the submission guide.

Logging

from research_helpers.log import get_logger, setup_logging

setup_logging()
log = get_logger(__name__)

log.info('scoring', corpus='perseus', sentences=18_000)
[INFO    ] 19:41:47 __main__ scoring (corpus=perseus, sentences=18000)

The console and the log file take separate levels. Colour is applied only when the stream is a terminal, so no escape codes are included in a redirected log.

Details in the logging guide.

Documentation

The full documentation includes:

License

The project is licensed under the MIT License, allowing free use, modification, and distribution.

Metadata

Release files for research-helpers 1.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for research-helpers 1.2.1
File Size Uploaded Provenance
research_helpers-1.2.1.tar.gz 117.3 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for research-helpers 1.2.1
File Interpreter ABI Platform
research_helpers-1.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 201.9 kB

Release files / research_helpers-1.2.1.tar.gz

Download URL research_helpers-1.2.1.tar.gz
Size 117.3 kB
Tags Source
SHA-256 checksum
How to use checksums
2e60dc8c783a55514740be7d8d394cb41b0c46f27785ec0fb0e5116ef6541a9e
BLAKE2b-256 checksum
How to use checksums
4bf9cdcd58700cb03670bd2523ae75fbd484643088a8f31fcfea898f86d61317
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / research_helpers-1.2.1-py3-none-any.whl

Download URL research_helpers-1.2.1-py3-none-any.whl
Size 84.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
09a598542bd2e4c9191868efebbf2b90460a5f969c234f3a8acf3082cce904b7
BLAKE2b-256 checksum
How to use checksums
a7cdceac36d6206ce80e696b9678bc48f25556373447dea7787eb7fecc328a4f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Security for research-helpers 1.2.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for research_helpers-1.2.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page