Why I built a CFU plotter
Look — at some point, if you work with E. coli for a living, you have to do something with CFUs or you quietly lose your credibility. So this is partly me keeping mine. That is the honest, slightly-embarrassing origin of this tool, and I would rather say it out loud than pretend it began with a grand vision.
The more serious version is this. A colony-forming-unit assay is one of the simplest things you do at the bench: you dilute, you plate, you incubate, you count. That part is honest, satisfying work. The trouble starts the moment you want to show the data to anyone else.
Because a single CFU experiment is never one number. It is a few strains or vectors, a couple of treatments, an early and a late timepoint, three replicate plates each, and counts that live across five or six orders of magnitude. By the time you want to present it, you have stopped being a microbiologist and become a person shuttling numbers between a spreadsheet, a stats function, and a plotting tool — praying you did not transpose a column somewhere along the way.
I ran a lot of these assays. And every single time, the counting was the easy part; turning the counts into a figure I actually trusted — one I could reproduce a year later — was the part that reliably ate an afternoon.
The counting is easy. Making a figure you trust, and could rebuild a year later, is the part that costs you.
The actual problem
To be fair, none of the individual tools is the villain. Spreadsheets store counts fine. ggplot2 plots beautifully. The problem is the loop you run to assemble the figure by hand, and how fragile it is: copy the counts, compute means, reshape the table, decide between raw and log scale and toggle it twice, run a t-test off to one side, hand-nudge the significance stars, export, discover the DPI is wrong, fix it, re-export — then do it all again for the next panel.
CFU data has one extra trap. Because the counts are log-distributed, the statistics really ought to run on log10(CFU), not the raw numbers — and that is easy to get subtly wrong when the test lives in a different window from the plot. The number under the figure and the bars in the figure should never be able to disagree. By hand, they can.
So I built the loop into one app
I wanted a way to quantify and present this data in the cleanest, most insightful, most story-telling way I could manage — and to have it stay reproducible. So CFU Plot Studio does the whole loop in one place: you map your columns, it plots the bars with the replicate points on top, runs the statistics on log10(CFU) with the correction you choose, places the annotations, checks the figure for the boring submission-killers, and exports — including the exact R script that made it. The graph, the numbers, and the recipe stay attached to each other. That last part is the whole point.
One honest footnote: I build these tools with an AI partner. I am a microbiologist, not a career software engineer — the decisions about what a trustworthy CFU figure is are mine, and Claude did a lot of the implementation heavy-lifting. That collaboration is a big part of why a single frustrated afternoon could turn into something I can actually share.