Skip to content

run.log does not record the UniProt release for -q/--query runs #433

Description

@jcoludar

Summary

For a -q/--query run the dataset is defined by two things: the query string and the UniProt release it was resolved against. run.log records the query and the resulting protein count, but never the release — so the run is not reproducible from its own log.

Why this is not theoretical

The same query returns materially different datasets over time. For family:"beta-lactamase":

when proteins
original bundle 127,115
rebuild, May 2026 152,738
release 2026_02 (10-June-2026) 113,015

A 26% drop between the May rebuild and today, with no change to the query. We hit this while trying to work out which bundle a published figure was built from — the count had moved twice, the derived percentage in the manuscript no longer matched any bundle, and there was no record of the release. It took a full session of archaeology, and the answer turned out not to be recoverable from the repository at all. The release is the one provenance field whose absence actually cost us, and it is the one the run log omits.

The headers are already there

Confirmed against the exact endpoint and parameters query.py uses:

X-UniProt-Release: 2026_02
X-UniProt-Release-Date: 10-June-2026
X-API-Deployment-Date: 29-July-2026

The handling point is query.py, right after response = requests.get(...) / raise_for_status(). Currently the only header read anywhere in the package is content-length.

Two constraints worth knowing before patching

1. The cached-FASTA path skips query_uniprot entirely. --keep-tmp defaults on, so most reruns reuse the cached FASTA and never call the query function. A release captured only in memory would vanish on every resumed run — i.e. on the majority of runs. It needs to be persisted beside the cached FASTA (e.g. uniprot_release.json) and read back on the cached branch.

2. Don't change the return arity. query_uniprot returns a 2-tuple and is unpacked as such by notebooks/ProtSpace_Preparation.ipynb as well as by prepare.py. An optional release_out: dict | None = None out-parameter keeps both working, and still degrades cleanly under --no-keep-tmp where no sidecar can be written.

Suggested output

## Input
query: family:"beta-lactamase"
uniprot_release: 2026_02
uniprot_release_date: 10-June-2026
uniprot_retrieved: 2026-08-11T15:41:00+0000
proteins: 113015

Unrelated but adjacent

query.py reads response.headers.get("content-length", 0) for the download progress bar. UniProt replies Transfer-Encoding: chunked with no Content-Length, so total_size is always 0 and the bar has never had a real total.

Context

Found while preparing datasets for a publication whose Methods section has to state the release per figure. Related: #432, and PRs #430 / #431.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions