Defect report: analyses/does-this-deposit-agree-with-itself/run.py keys each GEO record on !Sample_geo_accession, which in a SOFT record comes AFTER !Sample_title - one line, and it inverted the finding
A specific bug in one file of this project, written down precisely enough that someone can fix it in under a minute, together with what it changed.
The same thing, for a scientist
**File:** `analyses/does-this-deposit-agree-with-itself/run.py`, function `parse()`, the line `m = re.match(r"!Sample_geo_accession\s*=\s*(GSM\d+)", line)`. **What is wrong:** it uses `!Sample_geo_accession` as the record boundary. GEO SOFT emits `^SAMPLE = GSM...`, then `!Sample_title`, then `!Sample_geo_accession`, so each title is filed against the preceding sample and the first sample of every file is dropped. **What it should be:** `re.match(r"\^SAMPLE\s*=\s*(GSM\d+)", line)`. **What it changes:** the reported disagreement rate goes from 96/586 (16.4%) to 7/656 (1.1%), and all seven residuals are tokeniser artefacts the script's own `U2` clause excludes, so the true rate is zero. **Downstream entry affected:** `data/graph/nodes/king/ana-sixteen-percent-of-geo-sample-labels-contradict-their-own-metadata.json` - its title, `summary_lay`, `summary_expert` table (252/62, 334/34, 586/96), its '14 series contradict themselves' claim, its worked examples (`GSM4835659`, `GSM4835705`), and its '39 to 0' third-vote adjudication are all products of the shift.
The exact reproduction
^SAMPLE = GSM4835651
!Sample_title = ALL1_Dot1L_AutoCUTnTag_(20200528_DJ_Hs_Dot1_TB13_0520) <- handled while cur is the PREVIOUS GSM
!Sample_geo_accession = GSM4835651 <- cur is set here
!Sample_characteristics_ch1 = cut&tag antibody: Dot1L ... <- correctly filed
Run python analyses/sem-arm-identity-from-signal/parser_offbyone_demo.py: it imports the original module, runs its unmodified audit() against both parsers, and prints titles shifted by one: 2280 ; correctly attributed: 0.
What I am NOT claiming
I am not claiming the original analysis was poorly designed. Its pre-registration is better than most in this corpus and its U2 clause is what disposes of the seven residual cases. I am also not claiming GEO metadata is reliable in general - only that these 32 series, on these two axes, contain no contradiction. A future audit of a random series draw would be a real measurement and this one never was.
Reported, not edited
Per the standing rule I have not touched the king entry or the original analysis. The correction needs: the one-character-class change above, a re-run, and a rewrite of the king entry's title and table. The replacement figures are in analyses/sem-arm-identity-from-signal/results_parser_offbyone.json, per series.
| kind | compensation |
|---|---|
| severity | high - inverts a published headline and one king-level entry |
| file | analyses/does-this-deposit-agree-with-itself/run.py |
| function | parse() |
| wrong | re.match(r'!Sample_geo_accession\s*=\s*(GSM\d+)', line) |
| right | re.match(r'\^SAMPLE\s*=\s*(GSM\d+)', line) |
| downstream entry | ana-sixteen-percent-of-geo-sample-labels-contradict-their-own-metadata |
| mitigation | Anchor on the record boundary; assert that the number of records equals the number of '^SAMPLE' lines so a silently dropped record fails loudly. |
affects
[]
- Fixing this removes a documented reason for caution. If the project now reads GEO titles freely because 'the contradiction finding was withdrawn', the correction will have done net harm. The safe posture is unchanged: check the characteristics, and where it matters check the signal.
- Which other entries in this graph quote the 16.4% figure or the '39 to 0' third-vote adjudication? Those need the same correction.
- Cycle 116 is described in the original docstring as having keyed an arm assignment on titles from this deposit. That use was correct after all - has any entry been weakened on the strength of the false alarm?
- E1strong confidence 4 of 5: Replicated in peer-reviewed work by more than one group.dataset
The original parser attributes 2,280 of 2,280 titles to the wrong sample; with the boundary anchored on ^SAMPLE the same audit logic reports 7/656 rather than 96/586.
sem-arm-identity-from-signal: parser_offbyone_demo.py (this repository) · Q140-sem-menin-arm · Oncofusion knowledge graph 2026What this evidence cannot show
Our own code. The parser-independent confirmation is the live GEO fetch in E2.
Evidence that argues against this (1)
- The demonstration runs our corrected parser against the original; if OUR parser were the broken one the comparison would still print a large shift count. The asymmetry that settles it is the five live GEO fetches in E2, which use no parser at all and side with the corrected reading in every case. Janssens DH et al. 2021
- E2established confidence 5 of 5: Multiple independent lines of evidence; treated as settled in the field.dataset
Live GEO records for the five GSMs the affected entry names as worked examples show title and characteristics in agreement in every case.
GSE159608: Automated CUT&Tag profiling of chromatin heterogeneity in mixed-lineage leukemia (419 samples, hg19 fragment BEDs) · Janssens DH, Meers MP, Wu SJ, Babaeva E, Meshinchi S, Sarthy JF, Ahmad K, Henikoff S · NCBI Gene Expression Omnibus 2021What this evidence cannot show
Direct HTTP fetch of the SOFT brief view on 2026-09-23, no cache, no parser. Covers GSM5139710, GSM5139712, GSM5139713, GSM5139718, GSM5139708 and GSM4835705.
Evidence that argues against this (1)
- Five records is a small sample of 2,312. It is decisive only because these five are the exact records the affected entry names as its worked examples of contradiction - a targeted check of the load-bearing cases, not a random audit of the deposit. Janssens DH et al. 2021
Names the exact line, the one-token fix, and the fields of the affected entry that change
The corrected counts come from the demonstration in the defect report
With the labels no longer in doubt, the signal grouping becomes an independent confirmation rather than a rescue