Pipeline Details#
This document explains how the spatial neural activity analysis pipeline works.
Overview#
Pipeline Flowchart
flowchart TD
subgraph Input
subgraph Neural
A[("traces (.zarr)")]
B[("timestamp (.csv)")]
end
subgraph Behavior
C[("position (.csv)")]
D[("timestamp (.csv)")]
end
end
subgraph load ["ds.load()"]
A --> traces[Calcium Traces]
C --> load_beh("Load Positions<br/>• Compute Speed")
D --> load_beh
load_beh --> traj["Trajectory"]
end
subgraph preprocess ["ds.preprocess_behavior()"]
traj --> PP("• Jump Removal<br/>• Perspective Correction<br/>• Boundary Clipping<br/>• Recompute Speed (mm/s)")
PP --> SF(Speed Filter)
SF --> traj_filt[Filtered Trajectory]
end
subgraph deconv ["ds.deconvolve()"]
traces --> OASIS(OASIS AR2 Deconvolution)
OASIS --> S_list[Event Trains]
OASIS --> event_idx[(event_index)]
end
subgraph match ["ds.match_events()"]
event_idx --> EM("• Timestamp Matching<br/>• Speed Filter")
B --> EM
traj --> EM
EM --> event_place[(event_place)]
end
subgraph occupancy ["ds.compute_occupancy()"]
traj_filt --> OCC(Occupancy Map)
end
event_place --> unit_input["• Events<br/>• Occupancy<br/>• Filtered Trajectory"]
OCC --> unit_input
traj_filt --> unit_input
subgraph analyze ["ds.analyze_units() — per unit"]
unit_input --> RM(Rate Map)
unit_input --> SI("Spatial Information<br/>+ Shuffle Test")
SI --> pval[SI p-value]
unit_input --> RATE_SHUF("Shuffled Rate<br/>Percentile")
RATE_SHUF --> PF("Place Field Detection")
unit_input --> STAB("Split-Half Stability<br/>+ Shuffle Test")
STAB --> stab_p[Stability p-value]
end
subgraph results [Results]
pval --> PC{"Place Cell<br/>Classification"}
stab_p --> PC
PF --> COV(Coverage Analysis)
PC --> browse(Interactive Browser)
COV --> browse
end
Data Files#
Neural inputs (in neural_path directory):
{trace_name}.zarr: calcium traces (frames × units). Name set bytrace_namein config (e.g.C.zarr,C_lp.zarr)A.zarr: spatial footprints for cell contour overlay (optional)max_proj.zarr: max projection image for visualization background (optional)
Behavior inputs:
neural_timestamp.csv: neural frame timestamps (frame, timestamp_first, timestamp_last)behavior_position.csv: animal position per frame (DeepLabCut format with bodypart columns)behavior_timestamp.csv: behavior frame timestamps
Intermediate DataFrames (generated during pipeline):
event_index: deconvolved neural events (frame, unit_id, amplitudes)event_place: events matched to position with speed (unit_id, frame, s, x, y, speed) — only events abovespeed_threshold
Processing Steps#
ds.load()#
Load calcium traces from
{trace_name}.zarrLoad behavior position and timestamps → compute raw speed (px/s)
Load visualization assets (max_proj, footprints, behavior video frame)
ds.preprocess_behavior()#
Saves a copy of the raw trajectory in trajectory_raw, then applies corrections and speed filtering.
When arena_bounds is configured (full pipeline):
Jump removal: interpolate frame-to-frame displacements exceeding
jump_threshold_mmPerspective correction: correct for camera angle using
camera_height_mmandtracking_height_mmBoundary clipping: clip positions to
arena_boundsRecompute speed: recalculate speed in mm/s from corrected positions
Speed filter: apply
speed_threshold→trajectory_filtered
When arena_bounds is not configured (fallback with warnings):
Spatial corrections are skipped (jump removal, perspective correction, boundary clipping)
Speed and position remain in pixels
Speed filter is still applied →
trajectory_filtered
ds.deconvolve()#
Run OASIS AR2 deconvolution on each unit’s calcium trace
Parameters:
g(AR coefficients),baseline,penalty,s_minOutput:
good_unit_ids, spike trains (S_list),event_index
ds.match_events()#
For each neural event, find the closest behavior frame by timestamp
Discard matches where timestamp difference exceeds 0.5 /
behavior_fpsFilter out events where animal speed was below
speed_thresholdOutput:
event_place
ds.compute_occupancy()#
Compute 2D occupancy histogram from
trajectory_filteredSmooth with
occupancy_sigma, mask bins belowmin_occupancyOutput:
occupancy_time,valid_mask, bin edges
ds.analyze_units() — per unit#
Four independent computations from the same inputs (events, filtered trajectory, occupancy):
Rate map: event weights / occupancy time, smoothed with
activity_sigma(for display)Spatial information + shuffle test: Skaggs SI with circular-shift shuffle → SI p-value
Shuffled rate percentile: per-bin percentile of shuffled rate maps → used for place field seed detection
Split-half stability + shuffle test: correlation between first/second half rate maps with circular-shift shuffle → stability p-value
Place cell classification: units with SI p-value < p_value_threshold AND stability p-value < p_value_threshold.
Place field detection (Guo et al. 2023):
Seed detection: bins where rate exceeds the shuffled rate percentile. Only contiguous seed regions with ≥
place_field_min_binsbins are keptExtension: each seed region extends to contiguous bins with rate ≥
place_field_threshold× (seed’s peak rate)
Results#
Coverage map: sum of place field masks across place cells
Coverage curve: cells sorted by field size (largest first), cumulative fraction of environment covered
Interactive browser: max projection overlay, trajectory with events, rate map with place field contour, SI histogram, stability maps, trace view
Key Parameters#
speed_threshold: minimum speed to include data (mm/s)min_occupancy: minimum time per bin to be valid (seconds)bins: spatial resolution (number of bins per axis)occupancy_sigma: Gaussian smoothing sigma for occupancy map (in bins)activity_sigma: Gaussian smoothing sigma for rate map (in bins)n_shuffles: number of circular-shift shuffle iterationsmin_shift_seconds: minimum circular shift for shuffle test (seconds)p_value_threshold: p-value threshold for both SI and stability significancesi_weight_mode:"amplitude"(event amplitudes) or"binary"(event counts)place_field_threshold: fraction of peak rate for place field extensionplace_field_min_bins: minimum contiguous bins for a place field seedplace_field_seed_percentile: percentile of shuffled rates for seed detection
Configuration Reference#
Data Paths Config#
data_paths.yaml
id: data_paths
mio_model: placecell.config.DataPathsConfig
mio_version: 0.8.1
neural_path: path/to/neural
neural_timestamp: path/to/neural_timestamp.csv
behavior_position: path/to/behavior_position.csv
behavior_timestamp: path/to/behavior_timestamp.csv
Analysis Config#
pcell_config.yaml
id: pcell_config
mio_model: pcell.config.AnalysisConfig
mio_version: 0.8.1
neural:
id: neural
fps: 20.0
oasis:
id: oasis
g: [1.60, -0.63] # AR(2) coefficients (required, usually overridden by data config)
baseline: p10
penalty: 0.8 # Sparsity penalty (higher = fewer events). Default 0.
s_min: 0 # Minimum event size threshold. Default 0.
trace_name: C_lp
behavior:
id: behavior
behavior_fps: 20.0
speed_threshold: 10.0 # mm/s
speed_window_frames: 5
bodypart: LED
jump_threshold_mm: 100 # Max plausible frame-to-frame displacement (mm)
spatial_map_2d:
id: spatial_map_2d
bins: 50
min_occupancy: 0.025 # Minimum occupancy (in seconds) to include a bin
occupancy_sigma: 3 # Gaussian smoothing (in bins) for occupancy map
activity_sigma: 3 # Gaussian smoothing (in bins) for rate map
n_shuffles: 1000
random_seed: 1
event_threshold_sigma: 0 # Sigma multiplier for event amplitude threshold
p_value_threshold: 0.05 # P-value threshold for SI and stability
min_shift_seconds: 20 # Minimum circular shift (seconds) for shuffle test
si_weight_mode: amplitude # 'amplitude' or 'binary'
place_field_threshold: 0.35 # Fraction of peak rate for place field boundary
place_field_min_bins: 5 # Minimum contiguous bins for a place field
place_field_seed_percentile: 95 # Percentile of shuffled rates for seed detection
trace_time_window: 600 # Time window (seconds) for trace display