packages = ["pandas", "matplotlib", "scipy"]
Nociceptor Innervation Suite

Image Quantifier

Drag & Drop folder logic supported via "Load Files".
1. Load -> 2. Draw ROI -> 3. Calc -> 4. Save
No files loaded


--
1. CFA Mice
Left (Inj) 0
Right (Ctrl) 0
2. Carrageenan Mice
Left (Inj) 0
Right (Ctrl) 0
Python Environment Loading...
(Once loaded, upload files on the left and click Generate)

1. Grid Configuration

Include Merge
import pandas as pd import numpy as np import matplotlib.pyplot as plt import matplotlib.patches as mpatches from scipy import stats from js import document, alert from pyodide.ffi import create_proxy import io, base64 STORE = { "CFA_L": [], "CFA_R": [], "Carr_L": [], "Carr_R": [] } NAMES = { "CFA_L": [], "CFA_R": [], "Carr_L": [], "Carr_R": [] } async def add_files(key, input_id, badge_id): inp = document.getElementById(input_id) files = inp.files if files.length == 0: return for i in range(files.length): f = files.item(i) raw_name = f.name text = await f.text() clean = text.replace(',', ' ').replace('\t', ' ') tokens = clean.split() nums = [] for t in tokens: try: nums.append(float(t)) except: pass if nums: STORE[key].append(np.mean(nums)) NAMES[key].append(raw_name) bdg = document.getElementById(badge_id) bdg.innerText = f"{len(STORE[key])}" bdg.classList.add("active") inp.value = "" async def add_cfa_l(e): await add_files("CFA_L", "an_in_CFA_L", "bdg_CFA_L") async def add_cfa_r(e): await add_files("CFA_R", "an_in_CFA_R", "bdg_CFA_R") async def add_carr_l(e): await add_files("Carr_L", "an_in_Carr_L", "bdg_Carr_L") async def add_carr_r(e): await add_files("Carr_R", "an_in_Carr_R", "bdg_Carr_R") def run_analysis(event): if len(STORE["CFA_L"]) == 0: return alert("No Data Loaded") mode = document.getElementById("an-mode").value title = document.getElementById("an-title").value ylabel = document.getElementById("an-ylabel").value fs_title = int(document.getElementById("an-fs-title").value) fs_label = int(document.getElementById("an-fs-label").value) fig = None if mode == "ratio": fig = plot_summary(title, ylabel, fs_title, fs_label) else: fig = plot_raw(title, ylabel, fs_title, fs_label) document.getElementById("an-plot-area").innerHTML = "" display(fig, target="an-plot-area", append=False) # --- SAFE SEM FUNCTION (Handles N=1) --- def safe_sem(data): if len(data) < 2: return 0.0 return stats.sem(data) # --- SAFE T-TEST FUNCTION (Handles N<2 or Identical Data) --- def safe_ttest(g1, g2): if len(g1) < 2 or len(g2) < 2: return 1.0 # Not significant if not enough data if np.allclose(g1, g2): return 1.0 # Identical data = p-value 1.0 try: t, p = stats.ttest_rel(g1, g2) if np.isnan(p): return 1.0 return p except: return 1.0 def plot_summary(title, ylabel, fs_t, fs_l): cfa_r, cfa_l = STORE["CFA_R"], STORE["CFA_L"] carr_r, carr_l = STORE["Carr_R"], STORE["Carr_L"] # Validation for pairs if len(cfa_r) != len(cfa_l): return alert("CFA groups mismatch (L vs R count)") if len(carr_r) != len(carr_l): return alert("Carr groups mismatch (L vs R count)") # Calculate stats using SAFE functions means = [np.mean(cfa_r), np.mean(cfa_l), np.mean(carr_r), np.mean(carr_l)] sems = [safe_sem(cfa_r), safe_sem(cfa_l), safe_sem(carr_r), safe_sem(carr_l)] # Safe T-Tests p_cfa = safe_ttest(cfa_r, cfa_l) p_carr = safe_ttest(carr_r, carr_l) fig, ax = plt.subplots(figsize=(8, 6)) colors = ["#ccc", "#e74c3c", "#ccc", "#3498db"] x_pos = [0,1,2.5,3.5] # Bars ax.bar(x_pos, means, yerr=sems, capsize=5, color=colors, edgecolor='black', width=0.8) # Scatter & Lines # CFA for i in range(len(cfa_r)): ax.plot([0,1], [cfa_r[i], cfa_l[i]], color='black', alpha=0.3, lw=0.5) ax.scatter([0,1], [cfa_r[i], cfa_l[i]], color='black', alpha=0.5, s=20) # Carr for i in range(len(carr_r)): ax.plot([2.5,3.5], [carr_r[i], carr_l[i]], color='black', alpha=0.3, lw=0.5) ax.scatter([2.5,3.5], [carr_r[i], carr_l[i]], color='black', alpha=0.5, s=20) # Brackets Function def draw_bracket(x1, x2, p_val, y_max): h = y_max * 0.05 y_top = y_max + h ax.plot([x1, x1, x2, x2], [y_top-h*0.5, y_top, y_top, y_top-h*0.5], lw=1.5, c='black') star = "ns" if p_val < 0.001: star = "***" elif p_val < 0.01: star = "**" elif p_val < 0.05: star = "*" ax.text((x1+x2)/2, y_top, star, ha='center', va='bottom', fontsize=fs_l, fontweight='bold') return y_top # Calculate Y-Limits y_max_cfa = max(max(cfa_r), max(cfa_l)) if cfa_r else 0 y_max_carr = max(max(carr_r), max(carr_l)) if carr_r else 0 h1 = draw_bracket(0, 1, p_cfa, y_max_cfa) h2 = draw_bracket(2.5, 3.5, p_carr, y_max_carr) ax.set_ylim(bottom=0, top=max(h1, h2)*1.15) ax.set_xticks(x_pos) ax.set_xticklabels(["CFA\nCtrl", "CFA\nInj", "Carr\nCtrl", "Carr\nInj"], fontsize=fs_l) ax.set_title(title, fontsize=fs_t, fontweight='bold') ax.set_ylabel(ylabel, fontsize=fs_l) ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) stats_div = document.getElementById("an-stats-area") stats_div.style.display = "block" stats_div.innerText = f"CFA P-Value: {p_cfa:.5f}\nCarr P-Value: {p_carr:.5f}" plt.tight_layout() return fig def plot_raw(title, ylabel, fs_t, fs_l): fig, ax = plt.subplots(figsize=(10, 5)) labels = [] vals = [] colors = [] # Flatten data for raw plot for i, v in enumerate(STORE["CFA_R"]): labels.append(f"CFA_R_{i+1}"); vals.append(v); colors.append("#ccc") labels.append(f"CFA_L_{i+1}"); vals.append(STORE["CFA_L"][i]); colors.append("#e74c3c") ax.bar(range(len(vals)), vals, color=colors, edgecolor='black') ax.set_xticks(range(len(vals))) ax.set_xticklabels(labels, rotation=45, ha='right', fontsize=fs_l*0.8) ax.set_title(title + " (Raw Data)", fontsize=fs_t) ax.set_ylabel(ylabel, fontsize=fs_l) ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) plt.tight_layout() return fig def main(): document.getElementById("btn_add_CFA_L").addEventListener("click", create_proxy(add_cfa_l)) document.getElementById("btn_add_CFA_R").addEventListener("click", create_proxy(add_cfa_r)) document.getElementById("btn_add_Carr_L").addEventListener("click", create_proxy(add_carr_l)) document.getElementById("btn_add_Carr_R").addEventListener("click", create_proxy(add_carr_r)) document.getElementById("an-btn-run").addEventListener("click", create_proxy(run_analysis)) main()