Single-Cell & Perturbation Bioinformatics · Machine Learning
CRISPRi perturbation screens, cell foundation models, and out-of-core pipelines for single-cell data that will not fit in memory. Two years at the bench before moving to computation, so I know how the data was made — and I measure a dataset before I model it.
MSc Bioinformatics, University of Edinburgh · based in Edinburgh, UK, open to relocating · UK Graduate visa, valid to December 2027 · available immediately
Four shipped, two in progress
Zero-shot generalisation under distribution shift. Before building a model I established what a good answer could even look like.
The task
Unperturbed cells from three anonymised human cell lines. None appears in any training data.
How each of 300 CRISPRi gene knockdowns changes the transcriptome, in every context.
cells × 18,533 genes, as raw integer counts. Scored on six metrics.
The model has to answer for cell types it has never seen, using only what it learned from other lines — zero-shot generalisation under distribution shift.
Where a score can land
Nobody can reach 1.0. I measured the ceiling at roughly 0.30 by running the organisers' own scorer sideways on control cells, scoring them against each other. The experiment cannot repeat itself more precisely than that. Everything real happens in the band between 0 and 0.30 — which is why knowing where 0.30 sat mattered more than any single submission.
What truncation cost
Same model, same data. The only change is how many genes each predicted cell is allowed to express. Keeping the top 2,000 of 18,533 zeroes 89% of the transcriptome — and nmae went from its floor of −6 to −0.0117 when that stopped.
46 non-targeting guides, 400 cells each — cells where nothing was perturbed. Comparing each guide's mean profile against the other 45 runs exactly the comparison the challenge scores, on a group with no signal in it. MAE 0.0132. Replicated across all three contexts at 0.0132 / 0.0121 / 0.0131, within 9%. Below that number, a difference is sampling noise.
Per-gene detection rates with np.bincount, then log2 fold change with a pseudocount — chosen over plain difference, which rewards abundance rather than specificity. A: immature T-lymphoid, TRBC1 in 100.0% of cells, IKZF1 and LEF1 as master regulators, RAG1 and CD1E present. B: RPE1-like, CLU / FOLR1 / HTRA1, CDKN2A intact. C: basal squamous, TP63 and KRT5.
Exactly 400 cells per guide, standard deviation 0.0. Real experiments are never that even, so the release had been subsampled before publication. Guide identifiers run to 99 while only 46 exist — an identifier is a name, not a count. Separately, median depth of 20,109 counts per cell matched the organisers' documentation exactly, and all three contexts were depth-matched, which means differences between them are biological rather than technical.
Two early submissions scored about −1.0. Five of six metrics sat at ~0, exactly as the scale defines for a no-change prediction — but nmae was pinned at its floor of −6. The cause was truncation: keeping only the strongest genes per cell sends every other gene to zero. Predicting at full density moved the score to −0.0317 and the rank from 455 to 274, and nmae from −6 to −0.0117. The lesson was about the objective rather than the model — normalised error is dominated by what you predict as zero, so a representation choice made before any learning happens can cost more than the model can recover.
The official packaging tool was killed three times by the memory limit. Instead of retrying with smaller inputs, I read its source: every stored entry is held three times over — once on load, once in an unconditional type conversion, once in the integrality check. Instrumenting a run confirmed it: ~30 bytes per entry, peak 31.6 GB. That converts an unknown into a formula — available memory ÷ 30 is the ceiling.
The submission format turned out to be tar(zstd(h5ad)) with a single entry, and every step of that streams. I built the container by hand: it scored −0.03174760868365253, identical to the official tool's output to fifteen decimal places. The ceiling was a choice the validator made, not a property of the format.
Arc's STATE transformer with ESM2 perturbation embeddings and an optimal-transport loss over cell sets. Converting its log-space output back to raw integer counts needed care: each predicted cell is scaled to the library size of the control cell that seeded it, then Poisson-sampled rather than rounded — at ~20,000 counts across 18,533 genes, rounding sends everything below 0.5 to zero, which is the same truncation that scored −6. Result: median 20,007 counts per cell against a raw median of 19,940.
The training set had been cut to fit a memory limit, dropping competition_train and leaving four reference Perturb-seq datasets — about 80,000 cells, none of them from the distribution being evaluated. The model was learning entirely out of domain and then being asked to generalise into it. Restored, competition_train is 221,273 cells: three quarters of the training set, and the only part drawn from the competition's own experiment. A larger handicap than the training budget was. I also vectorised a quadratic loop in the inference path that assigned rows one at a time into a DataFrame across 120,000 iterations.
30 GPU-hours per week, a 12-hour ceiling per session, and no disk that survives between sessions. I measured throughput instead of estimating it — 0.29 it/s, which turned an eleven-hour guess into a five-hour plan — checkpointed every 500 steps so a lost session costs 500 steps rather than all of them, and moved the trained model into a versioned artefact so it never needs retraining. The analysis that preceded it ran on an 8 GB laptop, streaming sparse chunks rather than loading matrices, on data that is 17 GB dense.
Breast cancer relapse classification, built to measure how much a common methodological shortcut exaggerates reported performance.
Cross-validated AUC — same data, same models
SVM tops the leaky ranking and comes third when done properly. The shortcut does not only inflate the score — it picks the wrong model.
With 22,215 features and 286 samples, p >> n and the univariate filter is doing most of the work — so where it sits decides the reported score. Rank probes once on the full dataset and every fold's held-out samples have already helped choose the features; the fold is not held out at all. Put scaling and selection inside a Pipeline and both refit per fold. Both are implemented, so the gap is measured rather than asserted.
Four models compared under both protocols. SVM looks like the best model under leakage and is third without it. Run the comparison the wrong way and the ranking changes, not only the magnitude — which is the part that actually costs you.
Test AUC 0.61–0.64 against a 24% base rate: weak but non-zero, and consistent with the literature on single-cohort microarray classifiers. The PCA shows why — relapse status is not separable along the dominant axes of variation. The README also records that the endpoint is bone relapse rather than the paper's distant-metastasis-free survival, because that clinical table was never deposited in GEO.
How dietary fibre changes a fermenting microbial community, in composition and in function. Four taxonomic profilers run against the same samples and compared for agreement rather than picking one and trusting it.
One fermentation, two sequencing layers
Where the profilers disagree is itself a result. Establish how much of an answer is method before attributing any of it to biology — the same instinct as measuring a noise floor.
Built for people at the bench. A tool that runs a statistical test without telling you the test was inappropriate is worse than no tool at all — so this one checks first.
A complete standard workflow on a public 10x dataset, containerised and documented.
Why this one. I have worked with single-cell data through h5py and CSR directly, which taught me the structure but skipped the standard toolchain. This closes that gap, on a dataset anyone can download and check.
The perturbation pipeline rebuilt so anyone can run it, not just me.
Why this one. Everything I built for the Challenge runs on my machine and nowhere else. I have the runtime figures already — but until someone else can reproduce them, they are my numbers rather than evidence.
Where each of these is evidenced above
What I can do today, and what I am closing next
AnnData / h5adCSR sparse matricesout-of-core HDF5 (h5py)CRISPRi Perturb-seqdifferential expression (Wilcoxon, BH)marker-gene annotation
scikit-learnRandom Forest / SVM / XGBoostleakage-safe cross-validationfeature selection under p >> nROC-AUC, PR-AUC, confusion matricesarc-state (STATE) fine-tuningzero-shot inferenceESM2 embeddingsWeights & Biases
DNA/RNA extractionPCR / qPCRcloning and plasmid workcell culture
I know how the data I analyse was generated, and can design the experiment that produces it.
GLMs (Poisson, binomial, overdispersion)multiple-testing correction and FDRnonparametric and rank-based testslinear models and ANOVA
RNA-seq end to endFastQC / MultiQCSTAR / HISAT2DESeq2 / edgeRTPM / TMM / VST normalisationGO / KEGG enrichment
PythonRBashnumpy / pandas / scipy.sparseNextflow DSL2 (modules, profiles)DockerSlurm / HPCGitLinux
Scanpy, Seurat and Cell Ranger — the standard single-cell stack, and the clearest distance between what I have built and the roles I want. AWS (S3, Batch, IAM, cost control), to run the Nextflow pipelines I already write somewhere other than one machine. PyTorch from first principles rather than through a framework. scVI and trajectory inference.
Both peer-reviewed, with DOIs
Biofilm formation and para-cresol production by Clostridioides difficile under the influence of phytonutrients from Rhus chinensis
Sruthi K, Gurubasavaiah KM, Khade OS, Vanitha T, Bhatt P · 10.1007/s00284-026-05076-w
Holistic Approach Environ · 15(2), 57–68 · 2025Early release of methane and quicker degradation of bioplastics using activated sludge
Mukunda CK, Gurubasavaiah KM, Banu SH · 10.33765/thate.15.2.2
Two years at the bench, then computation
Bioinformatics Domain Expert · Mercor
AI evaluation across single-cell genomics, metagenomics and microbiology — judging whether a model’s biological reasoning holds. 1,000+ tasks, each in a pinned container.computational
Bioinformatics Consultant · KreatBio
End-to-end metagenomic analysis for client sample sets, from raw sequencing through to interpreted results.computational
MSc Bioinformatics · University of Edinburgh
Where the work moved from the bench to computation.the move
Project Associate, gut health & prebiotics · CSIR–CFTRI
Ran the molecular workstream — extraction, PCR, microbiome assays — then analysed the sequencing it produced. Mentored MSc students at the bench.bench and computational
Junior Research Fellow · University of Hyderabad
Drug-resistance mechanisms in Leishmania donovani — PCR, cloning, protein expression, western blotting.bench
Academic Intern, Biochemistry · JSS College
Led a KSCST-funded project on methane from biodegradable plastics. It became my first publication.bench
MSc Biochemistry · JSS College
BSc Chemistry, Botany & Biotechnology · University of Mysore