This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
TimeCellScore: detects "time cells" in 2-photon calcium imaging data. Time cells fire reliably at a specific latency during a trial. The compute-heavy scoring is in C++, exposed to Python via pybind11.
Three scoring methods are implemented:
- R2B (
r2bScore.cpp): Ridge-to-Background ratio. Splits trials into odd/even sets; finds the peak frame on even trials, computes ridge/background ratio on odd trials. Significance via circular shuffling bootstrap. - TI (
tiScore.cpp): Temporal Information (Mau et al. 2018). Finds transients per trial, computes temporal information bits, tests against shuffled percentile. - PEQ (
peqScore.cpp): Parametric Equation score Q = fracFired × exp(−α·noise + β·widthCV + imprecision/frames). Lower Q is better; threshold is ~0.002.
make # builds tc.so (the pybind11 module)
make clean # removes .so filesRequires pybind11 headers at ../extern/pybind11/include. The output is tc<python-extension-suffix>.so (e.g. tc.cpython-310-x86_64-linux-gnu.so), imported as import tc.
- Python:
DATA[cell, trial, frame] - C++ internal: flat 1D array logically
data[frame][trial][cell]with cell varying fastest
The Python wrappers in pyBindMat.py perform np.swapaxes(DATA, 0, 2).reshape(-1) before passing to C++. The analysis window is circShuffleFrames = 2*circPad + usOnsetFrame - csOnsetFrame frames wide, centred between CS and US onset.
| File | Role |
|---|---|
tcHeader.h |
Structs: AnalysisParams, TiAnalysisParams, PeqAnalysisParams, CellScore |
tcDefaults.cpp |
Default-value constructors for all param structs |
r2bScore.cpp |
R2B scoring: trialAve, shuffleTrialAve, r2b, r2bScore |
tiScore.cpp |
TI scoring: reorderData, findTransients, findTemporalInformation, tuningCurve, cellTIscore, tiScore |
peqScore.cpp |
PEQ scoring: findEventWidthStats, findHitRatioAndImprecision, cellPeqScore, peqScore |
tcBind.cpp |
pybind11 module definition; exposes all three score functions and all param/result classes |
| File | Role |
|---|---|
pyBindMat.py |
runR2Banalysis, runTIanalysis, runPEQanalysis: handle axis transposition, pack params, call tc.*Score, return list-of-lists (10 fields including allPkIndices/Scores/Pvalues) |
tcMultiTestMAT.py |
Test/report script for .mat files; extracts timing from nested ops struct, prints 0/1/2/3+ peak counts and per-cell table |
tcMultiTestNPZ.py |
Batch analysis for .npz files; no dual-stim split; saves CSV with per-cell multi-peak columns; prints 2+-peak table |
tcpy_looped3.py |
Batch loop over multiple mice and dates, loads .mat files, runs R2B + TI, saves consolidated_TC.h5 / .csv |
run_batch_analysis.py |
Validation against synthetic datasets with ground truth; produces ti.csv, r2b.csv, peq.csv, groundTruth.csv |
| Field | R2B | TI | PEQ |
|---|---|---|---|
meanScore |
Shuffled mean R2B | Peak of mean trace | Mean signal across frames/trials |
baseScore |
Raw R2B ratio | Raw TI bits | Q value |
percentileScore |
Bootstrap percentile | Shuffled-percentile TI | unused |
sdev |
— | — | Sdev across all frames/trials |
sigMean |
baseScore > thresh×meanScore | numOK > 99th pct | — |
sigBootstrap |
percentile > r2bPercentile | baseScore > percentileScore AND fracFired > thresh | — |
fracTrialsFired |
— | Fraction of trials with ≥1 transient | Hit-trial ratio |
meanTrace |
Mean over odd trials | Mean binned trace | Mean trace |
meanPkIdx |
Frame of peak (even trials) | Frame of peak in binned trace | Frame of peak |
All three scoring methods now use peeling with an availability mask to detect multiple significant peaks per cell, separated by at least minPeakSep seconds (default 0.4 s). CellScore carries allPkIndices, allPkScores, and allPkPvalues for every accepted peak. convScoreToList in pyBindMat.py returns a 10-element list; indices 7/8/9 are these three lists.