Add new Excel report BEA25P077_RP.xlsx with multiple worksheets and styles
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
|
||||
QC_FILE = "BEA25P077_RP.xlsx"
|
||||
PATIENTS_FILE = "patients.xlsx"
|
||||
THRESHOLDS = [0, 0.1, 0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 5.0]
|
||||
|
||||
# Load patient data
|
||||
patients = pd.read_excel(PATIENTS_FILE, usecols=["Number", "Exf"])
|
||||
patients = patients.dropna(subset=["Number"])
|
||||
patients["Number"] = patients["Number"].astype(int)
|
||||
patients["Exf"] = patients["Exf"].astype(int)
|
||||
|
||||
def parse_conc(val):
|
||||
"""Return float concentration, or NaN for 'Too low' / missing."""
|
||||
if isinstance(val, str):
|
||||
return np.nan
|
||||
try:
|
||||
return float(val)
|
||||
except (TypeError, ValueError):
|
||||
return np.nan
|
||||
|
||||
def analyse_sheet(sheet_name, conc_col):
|
||||
df = pd.read_excel(QC_FILE, sheet_name=sheet_name, usecols=["ID", conc_col])
|
||||
df["conc_val"] = df[conc_col].apply(parse_conc)
|
||||
# Extract patient number from ID like "4A_G2" or "4B_G2"
|
||||
extracted = df["ID"].str.extract(r"^(\d+)[AB]")[0]
|
||||
df["Number"] = pd.to_numeric(extracted, errors="coerce")
|
||||
df = df.dropna(subset=["Number"])
|
||||
df["Number"] = df["Number"].astype(int)
|
||||
# Merge with patient diagnosis
|
||||
df = df.merge(patients, on="Number", how="left")
|
||||
return df
|
||||
|
||||
sheets = {
|
||||
"A (Schirmer strips)": ("A-samples", "conc (ng/ul)"),
|
||||
"B (Lens tissues)": ("B-samples", "Conc [ng/ul]"),
|
||||
}
|
||||
|
||||
print(f"{'Threshold':>10} {'Sheet':<22} {'Total':>6} {'Healthy (Exf=0)':>15} {'Diseased (Exf=1)':>16}")
|
||||
print("-" * 80)
|
||||
|
||||
for label, (sheet_name, conc_col) in sheets.items():
|
||||
df = analyse_sheet(sheet_name, conc_col)
|
||||
total_samples = len(df)
|
||||
n_too_low = df["conc_val"].isna().sum()
|
||||
print(f"\n {label} ({total_samples} samples total, {n_too_low} 'Too low')")
|
||||
print(f" {'Threshold':>10} {'Passing':>7} {'Healthy':>8} {'Diseased':>9} {'Unknown dx':>10}")
|
||||
print(f" {'-'*55}")
|
||||
for t in THRESHOLDS:
|
||||
if t == 0:
|
||||
# threshold=0: include all samples (Too low counts as passing)
|
||||
passing = df.copy()
|
||||
else:
|
||||
# Only samples with a numeric conc >= threshold pass
|
||||
passing = df[df["conc_val"] >= t]
|
||||
healthy = (passing["Exf"] == 0).sum()
|
||||
diseased = (passing["Exf"] == 1).sum()
|
||||
unknown = passing["Exf"].isna().sum()
|
||||
print(f" {t:>10.2f} {len(passing):>7} {healthy:>8} {diseased:>9} {unknown:>10}")
|
||||
|
||||
print()
|
||||
Reference in New Issue
Block a user