The assay layer¶
Screening before downloading. GSE109816 is 880 runs of Smart-seq2 that the
reprocessing pipeline fetched in full — terabytes — before rejecting them at the
chemistry step. The metadata that would have said so was already in hand: the
ENA filereport this project fetches for every run carries
library_construction_protocol, and the difference between the two assays is
plain in it.
fetch screen GSE109816 # exits 2; nothing here is 10x
fetch screen GSE111360 --explain # every run, with the phrases each call rests on
run assay library_type chemistry
SRR6798781 10x VDJ|GEX 10x_5p_v1_v2
What it is not¶
Not a replacement for reading the reads. fetch inspect reads a run's first
reads and names the kit from them, and rename10xrun in the reprocessing pipeline does the
same from the FASTQs and fails closed, which is right for the thing that decides how
reads are parsed. This layer is a cheap prior computed before anything is downloaded. Where
it and the reads disagree, the reads win, and the disagreement is a finding about the
submission. Over the reprocessing pipeline's own record, metadata and reads named different
kits for 20 samples, and the pipeline sided with the reads in all 20
(the comparison).
Measured¶
Recall: 90.9%, on a random 2,000-run draw from reprocessed-srr — a corpus
in which every run is 10x by construction, since it is what the 10x pipeline
has already reprocessed successfully. Surveyed 2026-09-15.
| Runs | Recall | |
|---|---|---|
ENA library_construction_protocol and friends |
1,757 / 1,986 | 88.5% |
| …plus GEO's own metadata for the 62 that are GEO submissions | 1,806 / 1,986 | 90.9% |
Of the 229 runs ENA's metadata could not classify:
- 167 are not GEO submissions at all — deposited directly to SRA or ENA, so there is no second description to consult.
- 49 of the remaining 62 were recovered from GEO (79%), almost all from
!Sample_data_processingnaming CellRanger or 10x. GSM5659253 is typical: its ENA protocol describes the tissue dissociation in detail and never names a platform, while GEO saysSequenced reads were mapped … with CellRanger (v6.0.0). - 13 remain unrecognised even with both archives' text.
Every run in the sample had some protocol text, so none of the misses is an empty field. They are protocols that genuinely never name the platform.
What is not measured, and why¶
The false-positive rate. There is no labelled non-10x corpus of comparable scale to measure it against, so this page reports recall and does not report precision. That asymmetry is stated rather than papered over — per the governing rule, an unmeasured number is not evidence, and claiming one here would be exactly the kind of invented default this project exists to avoid.
What can be said is narrower and checkable: the phrases are platform names
(10x, Chromium, CellRanger, GemCode, Next GEM), not descriptions of
single-cell work in general. scRNA-seq deliberately is not among them — it
appears in Smart-seq, Drop-seq and inDrop submissions too, and adding it would
buy recall by manufacturing false positives.
Matching, and what a call means¶
Recognition is pattern matching over submitter free text, and cannot be anything else. Two consequences are handled explicitly.
A call carries its grounds. Every match records the phrase and the field it came from, so a classification can be argued with rather than only believed:
10x [GEX]: 'CellRanger' in sample_data_processing
An absent field is unknown, not negative. A run with no protocol text is reported as such and is never screened out. Screening on absence would discard every submission that left the field blank.
Library type is study-level, and says so¶
ENA's library_construction_protocol is per-experiment in the schema and
per-study in practice: submitters paste the whole methods section into every
run of a study. GSE111360's protocol names both a Chromium 5' gene expression
kit and TCR V(D)J, so every one of its runs matches two families.
Choosing between them by declaration order would attach a confident label to a coin flip. An ambiguous run therefore has no library type, and the candidates stay visible:
run assay library_type
SRR6798781 10x VDJ|GEX
2 of 2 runs recognised as 10x; 2 name more than one library type
Where the text names exactly one family, the type is asserted. The families are checked specific-first — ATAC, VDJ, CRISPR, HTO, ADT, then GEX — because almost every protocol says "gene expression" somewhere, so ordering decides presentation while the ambiguity rule decides truth.
Chemistry: what metadata settles that the reads may not¶
rename10xrun's infer_10x_chemistry.py decides chemistry from the FASTQ files: barcode
length, UMI length, and which whitelist the barcodes hit. It says itself where that runs
out, in a warning it emits:
737K-august-2016cannot distinguish 3prime v2 from 5prime v1/v2 by FASTQ geometry alone
Both use a 16 bp barcode, a 10 bp UMI and the same whitelist, so geometry is blind there.
fetch inspect looks past geometry: it reads the strand of the cDNA read
(3' is sense, 5' antisense) and what follows the UMI. That settles most such runs. It does
not settle all of them. Under classifier 0.4.0, 94 of the 979 samples read from the
pipeline's record are left ambiguous between the two. A 26-base barcode read cannot show the
TSO, and the strand signals did not agree.
Metadata settles some of those. A protocol naming a "Chromium Next GEM Single Cell 5' Library & Gel Bead Kit" settles it before anything is downloaded. It did so for 9 of the 94, and all 9 the way the pipeline mapped them. When that may be used is its own decision.
Measured¶
2,000 runs from reprocessed-srr, 2026-09-16:
| Runs | ||
|---|---|---|
| Metadata names exactly one chemistry | 648 | 32.4% |
| …of which finer than FASTQ geometry can reach | 292 | 14.6% |
| Names more than one (a study that ran both kits) | 12 | 0.6% |
| Names none | 1,340 | 67.0% |
| Chemistry | Runs |
|---|---|
10x_3p_v3_family |
299 |
10x_5p_v1_v2 |
183 |
10x_3p_v2 |
109 |
10x_multiome_arc_gex |
42 |
10x_atac_v1_v1.1_v2 |
11 |
10x_5p_v3_gemx, 10x_3p_v4_gemx, 10x_3p_v1 |
4 |
The two bolded rows are the payoff: 292 runs where the metadata distinguishes 3' v2 from 5' v1/v2 and the whitelist cannot. For the other 67% the metadata is silent, and silence is the answer it gives.
Measured against the reads and the pipeline¶
Measured on 2026-10-23 over the reprocessing pipeline's own record: 5,762 samples it mapped,
979 of them read by fetch inspect
(the comparison). Over the 964 samples whose
metadata names exactly one kit:
| Samples | |
|---|---|
| the kit's list is the pipeline's whitelist | 900 |
| it is another list | 64 |
| the kit's strand is the pipeline's | 946 of 948 |
| read, and the reads name the same kit | 147 |
| read, and the reads name another: the pipeline sides with the reads | 20 of 20 |
The metadata is wrong about the list for one sample in fifteen. Every mistake is a field written once for a study and applied to every sample:
- "3' v2" for a v3 study, or the reverse (33);
- an ATAC or Multiome kit named for the gene-expression samples (29);
- a GEM-X 3' v4 kit for v2 samples (2).
The two strand mistakes are the same kind: GSE121380's protocol names a 5' kit for all its samples, and the pipeline mapped two of them as 3'.
This replaces a 240-run table on this page that counted 26 runs whose reads could not choose between 3' v2 and 5'. That figure could not be regenerated from the benchmark's committed calls, which give 19, as the benchmark says. The table above regenerates from committed CSVs. The benchmark's own finding stands: 26 of its 240 metadata labels were disputed by the reads and an instrument together.
The ids are rename10xrun's verbatim — 10x_3p_v3_family, 10x_5p_v1_v2,
10x_multiome_arc_gex — so the two answers compare without translation, and a
test asserts the vocabularies have not drifted apart.
A study that ran two kits names both¶
The protocol field describes a study, not a library. GSE111360's names a
Chromium 3' kit and a 5' kit because the study used both, in one field shared
by every run, so those runs report 10x_3p_v3_family|10x_5p_v1_v2 and assert
nothing — the same rule the library type
follows.
A GEM-X 3' kit is not ambiguous with the plain 3' family it implies, nor Multiome with ATAC: that is one library described at two levels, and reporting it as a conflict would manufacture an ambiguity that is not there.
It is an interface, and that is tested¶
An interface proven against a single implementation is not proven. Smart-seq is implemented alongside 10x, and it has no feature-barcode family at all — one library per cell — which exercises the parts of the interface 10x makes look mandatory. Adding a third assay is a data change:
PARSE = Assay(name="parse-seq", phrases=("Parse Biosciences", "Evercode"))
tests/test_assays.py::TestTheInterfaceIsAnInterface asserts that a new assay
needs no change to the core, and that an assay declaring no library types is
valid.