When we knock out a transcription factor in silico, we score the result as a shift in a marker gene programme: the mean, across that programme's marker genes, of simulated expression minus imputed expression. It is a reasonable readout and it has an obvious problem when the gene you knock out is one of the markers.
It is one of the markers more often than we assumed. The OPC-like programme was specified with seven marker genes, and three of them survived the highly-variable-gene filter on our reference: OLIG1, OLIG2 and PDGFRA. So knocking out OLIG2 sets one of the three genes defining its own readout to zero. A third of the number is the perturbation, by construction.
Storing the atoms
The first two versions of our knockout artefact stored only the mean across each programme's markers. A mean cannot be un-averaged, so any question about what a readout was made of needed a full re-run, which is five hours of compute for a question that should be a subtraction.
The current schema stores the per-marker deltas the programme means are built from, and the schema validator refuses an artefact whose stored means do not reproduce from its own atoms. That single change makes leave-target-out, leave-one-marker-out and re-weighted programme scores all derivable after the fact.
The result
TF readout OPC-like OC-like Other AC-like
OLIG2 all markers -0.2618 -0.1692 -0.0859 -0.0583
leave-out -0.2589 -0.1536 -0.0763 -0.0503
OLIG1 all markers -0.1641 -0.1419 -0.0630 -0.0413
leave-out 0.0000 0.0000 0.0000 0.0000
FOS all markers -0.2314 -0.1206 -0.0770 -0.0502
leave-out -0.2314 -0.1206 -0.0770 -0.0501OLIG2 keeps 99% of its all-marker figure once it is removed from its own average, so the effect is not an artefact of how the readout is scored. FOS is not a marker of this programme, so it has nothing to remove and its row is a formatting check rather than a result.
OLIG1 keeps exactly 0.0000, in all four cell states. Its per-marker atoms are OLIG1 -0.4922, OLIG2 0.0, PDGFRA 0.0. Knocking it out leaves both of the other markers at precisely zero, so the whole of its apparent -0.1641 was its own expression being clamped and then averaged into a programme it is a marker of. Every OLIG1 result on that programme is retracted.
What OLIG2's number is made of
The three atoms behind OLIG2's readout in OPC-like cells are OLIG1 at -0.3672, OLIG2 at -0.2676 and PDGFRA at -0.1506. OLIG2's own row is minus its imputed expression by construction, because the simulation clamps the perturbed gene to zero. The other two rows are downstream regulation. The largest single contribution is the shift in OLIG1, not the clamped row, which is the shape you want: most of the number is the network doing something rather than the perturbation being counted twice.
Two things this does not rescue
Marker coverage, which nothing in this repository recorded until the same batch: the OPC-like programme is 3 genes of 7 intended, AC-like is 2 of 5, OC-like is 4 of 5. The artefact's provenance block had been reporting the intended lists, so every surface quoting it overstated what the numbers were made of. The AC-like programme is two genes.
And zero is the modal outcome on this readout, so no target's zero means anything on its own. Twelve of the 45 targets in the served artefact return exactly zero on the OPC-like programme in every cell state. A gene that scores zero has not been shown to be irrelevant; it has done what most genes do.
What the extra field buys
A leave-target-out readout costs one extra field in a file. The version of this work that does not store the atoms still has both results, still reports them as two independent confirmations of the same biology, and has no way of finding out that one of them is a subtraction.