# Data-generating model shared by make_data.py and simulation.py. Python 3.13, NumPy.
# Bacterial burden: each mouse's spleen is homogenised in 1 mL, 10-fold dilutions are made, and 100 uL of each is
# plated. The plate read is the most dilute one with at least 30 colonies (or the undiluted plate if none has 30);
# CFU per organ = colonies x 10^dilution x 10 (per mL) x 1 mL. Zero colonies on the undiluted plate means fewer than
# 10 CFU per organ (log10 = 1, the limit of detection). True log10 burden per mouse is normal.
import numpy as np
MICE = 8

def mouse(rng, mean, sd=1.2):
    true_cfu = 10 ** rng.normal(mean, sd)                              # CFU in the organ (1 mL homogenate)
    for d in range(5, -1, -1):                                         # most dilute plate first
        col = rng.poisson(true_cfu * 0.1 / 10 ** d)                    # 100 uL of the 10^-d dilution
        if col >= 30 or d == 0: return d, int(min(col, 300 if d > 0 else col))

def study(rng, mean_ctrl=3.0, mean_trt=3.0):
    return [(g, f"{g[0].upper()}{m + 1}", *mouse(rng, mu)) for g, mu in (("control", mean_ctrl), ("treated", mean_trt)) for m in range(MICE)]
