CaDecon: Automated Deconvolution¶
What is CaDecon?¶
CaDecon is CaLab’s automated deconvolution workflow. Unlike CaTune – where you manually select kernel time constants and sparsity parameters – CaDecon uses the InDeCa (Iterative Non-parametric Deconvolution for Calcium imaging) algorithm to estimate both the calcium kernel shape and per-cell deconvolution parameters directly from your data. You do not need to know tau_rise, tau_decay, or lambda in advance. This is a new approach developed by the CaLab team and should be evaluated on your own data before adopting it for production analyses.
Quick start¶
import calab
import numpy as np
traces = np.load("my_traces.npy") # (n_cells, n_timepoints) or (n_timepoints,)
result = calab.decon(traces, fs=30.0, autorun=True)
if result is not None:
print(result.activity.shape) # (n_cells, n_timepoints)
print(result.fs) # effective sampling rate
print(result.pves) # per-cell proportion of variance explained
print(result.metadata) # estimated tau values, convergence info, etc.
decon() starts a local bridge server, opens the CaDecon web app, and waits for the solver to finish. With autorun=True the solver runs immediately after loading – no manual interaction needed. The estimated kernel parameters and deconvolved activity come back as a CaDeconResult.
decon() reference¶
Full signature¶
calab.decon(
traces: np.ndarray,
fs: float = 30.0,
timeout: float | None = None,
port: int | None = None,
app_url: str | None = None,
open_browser: bool = True,
headless: HeadlessBrowser | bool | None = None,
*,
autorun: bool = False,
upsample_target: int | None = None,
hp_filter_enabled: bool | None = None,
lp_filter_enabled: bool | None = None,
max_iterations: int | None = None,
convergence_tol: float | None = None,
num_subsets: int | None = None,
target_coverage: float | None = None,
aspect_ratio: float | None = None,
seed: int | None = None,
) -> CaDeconResult | None
Parameters¶
Parameter |
Description |
|---|---|
|
Calcium traces. Shape |
|
Sampling rate in Hz. Default: |
|
Seconds to wait for results. |
|
Port to bind the bridge server to. |
|
Override CaDecon URL (useful for local dev). Default: GitHub Pages deployment. |
|
Auto-open the browser. Default: |
|
|
|
Start the solver automatically after traces load. Default: |
|
Target sampling rate (Hz) for upsampling. Must be > 0. |
|
Enable high-pass filter before deconvolution. |
|
Enable low-pass filter before deconvolution. |
|
Maximum solver iterations (1–200). |
|
Convergence tolerance (0–1, exclusive). |
|
Number of random subsets for optimization. Must be > 0. |
|
Fraction of data covered by subsets (0–1]. |
|
Subset aspect ratio (> 0). Greater than 1 = wider, less than 1 = taller. |
|
Random seed for reproducible subset placement. |
Parameters after headless are keyword-only. Any parameter set to None falls through to the browser’s default value.
How it works¶
decon() uses the same bridge mechanism as tune(): Python starts a local HTTP server on 127.0.0.1, opens the CaDecon web app with a ?bridge= URL parameter, and the browser’s WASM solver does the heavy lifting. Results are posted back to the bridge server and returned as a CaDeconResult. The server binds to localhost only and is not network-reachable.
Return value: CaDeconResult¶
Returns a CaDeconResult namedtuple, or None if the session was cancelled or timed out.
Attribute |
Type |
Description |
|---|---|---|
|
|
Deconvolved activity matrix, shape |
|
|
Per-cell scaling factors, shape |
|
|
Per-cell baseline estimates, shape |
|
|
Per-cell proportion of variance explained, shape |
|
|
Slow biexponential kernel waveform, float32 |
|
|
Fast biexponential kernel waveform, float32 (empty if single-component) |
|
|
Effective sampling rate in Hz |
|
|
Estimated tau values, convergence info, version, etc. |
The metadata dict typically contains:
Key |
Description |
|---|---|
|
Estimated slow rise time constant (s) |
|
Estimated slow decay time constant (s) |
|
Slow component amplitude |
|
Fast rise time constant (s), 0 if unused |
|
Fast decay time constant (s), 0 if unused |
|
Fast component amplitude, 0 if unused |
|
InDeCa iterations completed |
|
Whether the algorithm converged |
|
Iteration at which convergence was reached |
|
Final fit residual |
|
Free-form kernel estimate (list of floats) |
Headless mode¶
For scripting, batch processing, or CI pipelines, run CaDecon without a visible browser window using HeadlessBrowser. This is typically combined with autorun=True so the solver runs without user interaction.
Installation¶
pip install calab[headless]
playwright install chromium
Single run¶
with calab.HeadlessBrowser() as browser:
result = calab.decon(traces, fs=30.0, headless=browser, autorun=True)
Shorthand¶
Pass headless=True to create a temporary browser for a single call:
result = calab.decon(traces, fs=30.0, headless=True, autorun=True)
Batch processing¶
Reuse a single browser across multiple datasets to avoid repeated startup costs:
import numpy as np
import calab
datasets = [np.load(f"session_{i}.npy") for i in range(10)]
with calab.HeadlessBrowser() as browser:
results = []
for traces in datasets:
r = calab.decon(traces, fs=30.0, headless=browser, autorun=True)
if r is not None:
results.append(r)
print(f"Cells: {r.activity.shape[0]}, PVE mean: {r.pves.mean():.3f}")
Debugging with a visible window¶
Use visible=True to see the browser while still using the programmatic control flow:
with calab.HeadlessBrowser(visible=True) as browser:
result = calab.decon(traces, fs=30.0, headless=browser, autorun=True)
HeadlessBrowser reference¶
calab.HeadlessBrowser(*, visible: bool = False)
Parameter |
Description |
|---|---|
|
If |
Methods: start(), navigate(url), close(). Properties: page (Playwright Page), is_alive (bool). Supports use as a context manager (with HeadlessBrowser() as hb:).
InDeCa building blocks¶
The InDeCa algorithm iterates between estimating spike trains, estimating a free-form kernel, and fitting a parametric (biexponential) model to that kernel. The decon() function orchestrates the full pipeline in the browser’s WASM solver. Advanced users can call the individual building blocks from Python for custom workflows.
solve_trace()¶
Run the InDeCa deconvolution step on a single trace, given a kernel shape.
calab.solve_trace(
trace: np.ndarray,
tau_rise: float,
tau_decay: float,
fs: float,
*,
upsample_factor: int = 1,
max_iters: int = 500,
tol: float = 1e-4,
hp_enabled: bool = False,
lp_enabled: bool = False,
warm_counts: np.ndarray | None = None,
lambda_: float = 0.0,
) -> SolveTraceResult
Parameter |
Description |
|---|---|
|
1-D calcium trace. |
|
Rise time constant in seconds. |
|
Decay time constant in seconds. |
|
Sampling rate in Hz. |
|
Upsampling multiplier (1 = no upsampling). |
|
Maximum FISTA iterations. |
|
Convergence tolerance. |
|
Enable high-pass filtering. |
|
Enable low-pass filtering. |
|
Spike counts from a previous iteration for warm-start. |
|
L1 sparsity penalty (0 = auto). |
Returns a SolveTraceResult namedtuple with fields: s_counts, alpha, baseline, threshold, pve, iterations, converged.
estimate_kernel()¶
Estimate a free-form kernel from traces and their corresponding spike trains. This is the “kernel step” of the InDeCa iteration.
calab.estimate_kernel(
traces_flat: np.ndarray,
spikes_flat: np.ndarray,
trace_lengths: np.ndarray,
alphas: np.ndarray,
baselines: np.ndarray,
kernel_length: int,
*,
max_iters: int = 200,
tol: float = 1e-4,
warm_kernel: np.ndarray | None = None,
smooth_lambda: float = 0.0,
) -> np.ndarray
Parameter |
Description |
|---|---|
|
Concatenated 1-D traces (all cells flattened end-to-end). |
|
Concatenated 1-D spike trains (matching |
|
Length of each individual trace in the flat arrays. |
|
Per-trace amplitude scaling factors. |
|
Per-trace baseline estimates. |
|
Desired output kernel length in samples. |
|
Maximum FISTA iterations for kernel estimation. |
|
Convergence tolerance. |
|
Kernel from a previous iteration for warm-start. |
|
Total-variation smoothness penalty weight. |
Returns a float32 array of shape (kernel_length,) – the estimated free-form kernel.
fit_biexponential()¶
Fit a parametric biexponential model to a free-form kernel. Optionally refines with a two-component (slow + fast) model.
calab.fit_biexponential(
h_free: np.ndarray,
fs: float,
*,
refine: bool = True,
skip: int = 0,
warm: BiexpFitResult | None = None,
) -> BiexpFitResult
Parameter |
Description |
|---|---|
|
Free-form kernel (1-D). |
|
Sampling rate in Hz. |
|
Whether to refine with a fast (second) component. |
|
Number of leading samples to skip in the fit. |
|
Previous |
Returns a BiexpFitResult namedtuple with fields: tau_rise, tau_decay, beta, residual, tau_rise_fast, tau_decay_fast, beta_fast. Fast-component fields are 0 if a single-component fit was used.
compute_upsample_factor()¶
Compute an integer upsampling multiplier for a given source and target sampling rate.
calab.compute_upsample_factor(fs: float, target_fs: float) -> int
Parameter |
Description |
|---|---|
|
Original sampling rate in Hz. |
|
Target sampling rate in Hz. |
Returns an integer >= 1.
Custom workflow example¶
import numpy as np
import calab
traces = np.load("my_traces.npy") # (n_cells, n_timepoints)
fs = 30.0
# Step 1: Start with an initial guess for the kernel
tau_r, tau_d = 0.1, 0.5
# Step 2: Solve each trace with the current kernel
results = [calab.solve_trace(traces[i], tau_r, tau_d, fs) for i in range(len(traces))]
# Step 3: Estimate a free-form kernel from the spike trains
traces_flat = traces.ravel()
spikes_flat = np.concatenate([r.s_counts for r in results])
trace_lengths = np.array([traces.shape[1]] * len(results))
alphas = np.array([r.alpha for r in results])
baselines = np.array([r.baseline for r in results])
h_free = calab.estimate_kernel(
traces_flat, spikes_flat, trace_lengths,
alphas, baselines, kernel_length=int(5 * tau_d * fs),
)
# Step 4: Fit a parametric model to the kernel
fit = calab.fit_biexponential(h_free, fs)
print(f"Estimated: tau_rise={fit.tau_rise:.4f}, tau_decay={fit.tau_decay:.4f}")
# Could iterate steps 2-4 for refinement (this is what InDeCa does internally)
For full details on all parameters, return types, and edge cases, see the API Reference.
CLI¶
CaDecon is also available from the command line via calab cadecon:
calab cadecon traces.npy --fs 30.0 --output results/session1
This opens CaDecon in the browser, waits for results, and saves:
results/session1_activity.npy– deconvolved activity matrixresults/session1_results.json– alphas, baselines, PVEs, kernel info, and metadata
Flag |
Description |
|---|---|
|
Input |
|
Sampling rate in Hz. Default: |
|
Server port. Default: auto-assign. |
|
Don’t auto-open the browser. |
|
Output path stem. Omit to print results to stdout. |
For additional CLI commands, see the CLI Reference.