Batch 2-photon preprocessing script. Runs a configurable source extraction pipeline
from a single JSON configuration file. Optionally runs behavioral synchronization
(via totalsync_2p) after the imaging pipeline when behavior_data is present in
the configuration. The source extraction algorithm is selected via the
source_extraction field; currently supported: suite3d, suite2p.
pip install -e .This registers the batch2p command.
batch2p <data.json> [--working-dir DIR] [--debug] [--sync-only] [--dry-run]
| Argument | Description |
|---|---|
data.json |
Path to the data/run configuration JSON file (required). |
--working-dir DIR |
Local scratch directory for intermediate files (optional). See Working directory. |
--debug |
Skip cleanup of temp/working directories on error, for troubleshooting. |
--sync-only |
Skip source extraction; assume results already exist and only run behavioral synchronization. |
--dry-run |
Check that all input files exist and all output directories are creatable, then exit without running anything. See Dry run. |
| Field | Required | Description |
|---|---|---|
source_extraction |
no | Source extraction algorithm to use. Default: "suite3d". Supported: "suite3d", "suite2p". |
job_id |
yes | Unique string identifier for this run. Used as directory name for job and results output. |
job_root_dir |
yes | Directory in which the algorithm's job folder is created (Suite3D only; Suite2P writes results directly into results_root_dir). |
data |
yes | List of input TIFF files. Entries are relative to root_path if set. See Input files. |
root_path |
no | Base path prepended to all relative entries in data, params_file, and pinsheet_file. |
results_root_dir |
no | Directory under which the results folder (<job_id>/) is created. Defaults to <job_root_dir>/results. |
working_dir |
no | Same as --working-dir; the CLI flag takes precedence if both are provided. |
block_size |
no | Number of planes per volume (default 3). Used for TIFF splitting and synced-output frame-index normalization. |
behavior_data |
no | List of .b64 TotalSync telemetry files, one per entry in data (same order). When present, behavioral synchronization is run after the imaging pipeline. Requires pinsheet_file. |
pinsheet_file |
no (yes if behavior_data set) |
Path to the TotalSync pin mapping JSON file. Relative paths are resolved against root_path. |
fill_tsync_gaps |
no | If true, interpolate timestamp gaps in the behavioral log rather than discarding frames after the first gap (default false). |
ignore_barcode |
no | If true, skip barcode-based alignment and fall back to frame-clock onset matching (default false). |
| Field | Required | Description |
|---|---|---|
params_file |
yes | Path to the Suite3D parameters JSON file. Relative paths are resolved against root_path. |
tiff_trim_size |
no | If > 0, split each input TIFF into chunks of this many frames before running Suite3D. |
add_offset |
no | Boolean passed to split_3d_tiff_into_chunks (default false). Only relevant when tiff_trim_size > 0. |
temp_dir |
no | Parent directory for the TIFF-split temp folder when no working_dir is set. Defaults to the system temp directory. |
| Field | Required | Description |
|---|---|---|
params_file |
yes | Path to the Suite2P parameters JSON file. Relative paths are resolved against root_path. |
temp_dir |
no | Parent directory for the Suite2P fast-disk scratch folder. Overridden by --working-dir if provided. Defaults to the system temp directory. |
Note:
tiff_trim_sizeis ignored by Suite2P. Suite2P processes all input TIFFs in one pass without chunking; settiff_trim_sizeto0(or omit it) when using"source_extraction": "suite2p".
Each entry in data is resolved relative to root_path (if present) and may be:
- A
.tif/.tifffile – added to the list directly. - A directory – all
.tif/.tifffiles inside are added in lexicographic order.
{
"source_extraction": "suite2p",
"root_path": "/data/ofl_2p/20251118",
"params_file": "/home/user/src/ofl_2p_analysis/docs/params_default_suite2p.json",
"data": [
"00001/477116_20251118_00001.tif"
],
"job_root_dir": "/data/ofl_2p/20251118",
"job_id": "00001",
"results_root_dir": "/data/ofl_2p/20251118/preprocessing_results",
"tiff_trim_size": 0,
"block_size": 3,
"temp_dir": "/data/temp/scratch"
}With behavioral synchronization:
{
"source_extraction": "suite2p",
"root_path": "/data/ofl_2p/20251118",
"params_file": "/home/user/src/ofl_2p_analysis/docs/params_default_suite2p.json",
"data": [
"00001/477116_20251118_00001.tif"
],
"behavior_data": [
"20251118-152602_925.b64"
],
"pinsheet_file": "/home/user/src/ofl_2p_analysis/docs/pinSheet_2026.json",
"job_root_dir": "/data/ofl_2p/20251118",
"job_id": "00001",
"results_root_dir": "/data/ofl_2p/20251118/preprocessing_results",
"tiff_trim_size": 0,
"block_size": 3,
"fill_tsync_gaps": true,
"temp_dir": "/data/temp/scratch"
}{
"source_extraction": "suite3d",
"root_path": "/data/ofl_2p/20251118",
"params_file": "params_default_suite3d.json",
"data": [
"00001/477116_20251118_00001.tif"
],
"job_root_dir": "/data/ofl_2p/20251118",
"job_id": "00001split",
"results_root_dir": "/data/ofl_2p/20251118/results",
"tiff_trim_size": 9999,
"block_size": 3,
"add_offset": false,
"temp_dir": "/data/temp"
}With behavioral synchronization:
{
"source_extraction": "suite3d",
"root_path": "/data/ofl_2p/20251118",
"params_file": "params_default_suite3d.json",
"data": [
"00001/477116_20251118_00001.tif"
],
"behavior_data": [
"20251118_171019_550.b64"
],
"pinsheet_file": "/home/user/src/ofl_2p_analysis/docs/pinSheet_2026.json",
"job_root_dir": "/data/ofl_2p/20251118",
"job_id": "00001split",
"results_root_dir": "/data/ofl_2p/20251118/results",
"tiff_trim_size": 9999,
"block_size": 3,
"add_offset": false,
"fill_tsync_gaps": true,
"temp_dir": "/data/temp"
}Suite2P is invoked via suite2p.run_s2p(db, settings) where:
-
settingsis built by loading theparams_fileJSON and merging it into the Suite2P default settings dictionary (suite2p.parameters.default_settings()). The merge respects the two-level nested structure of Suite2P settings: top-level non-dict keys are overwritten directly; top-level dict keys (e.g."registration","detection") are merged at the second level.torch_deviceis auto-detected ("cuda"if a compatible GPU is available, otherwise"cpu") unless explicitly set in the params file. -
dbis constructed from both the data JSON and the params file:data_path— a temporarycollected_input/folder created inside the results directory containing copies of all input TIFFs (deleted after the run).fast_disk— a unique temporary directory used by Suite2P for binary caching (deleted after the run). Parent istemp_dirfromdata.json, or the--working-dirpath if provided.save_folder— the results directory (results_root_dir/<job_id>/).- Acquisition parameters (
fs,tau,nplanes,nchannels, etc.) are mirrored fromsettingsintodb.
Suite2P writes its output under save_folder/:
<results_root_dir>/<job_id>/
combined/ F.npy Fneu.npy spks.npy stat.npy iscell.npy …
plane0/ F.npy Fneu.npy spks.npy …
plane1/ …
plane2/ …
params_used.json
data_used.json
<job_id>.log
When --working-dir DIR (or working_dir in data.json) is provided, the script
isolates all intermediate work in a uniquely-named temporary subdirectory inside
DIR (e.g. DIR/batch2p_<job_id>_<random>/). This allows multiple instances
to run in parallel against the same scratch mount.
Steps performed when a working directory is used:
- Input TIFF files are copied to
<session_tmp>/input_tifs/. - If
behavior_datais present,.b64files are copied to<session_tmp>/input_b64s/. - For Suite3D, if TIFF splitting is requested it runs inside
<session_tmp>/split_tifs/. - The extraction job and results are written inside
<session_tmp>. For Suite2P, the fast-disk scratch directory is also created inside<session_tmp>. - On completion (or on error), the results folder is copied back to
results_root_dir/<job_id>/and the job folder (Suite3D only) is copied back tojob_root_dir/. - If behavioral synchronization ran,
behavior_sync/is copied back toresults_root_dir/behavior_sync/. - The session temp directory (including all input copies and
.b64files) is deleted.
When behavior_data is present in data.json, the script runs totalsync_2p.synchronize()
for each (tif, b64) pair after the extraction pipeline completes. The .b64 files must be
listed in the same order as data, one file per tif entry. Synchronization depends only on
the original TIF file and the .b64 file and is not algorithm-specific.
Outputs are written to results_root_dir/behavior_sync/ and include, per session:
| File | Contents |
|---|---|
<session>_barcode_data.npz |
Raw decoded TotalSync telemetry arrays. |
<session>_frames_time_idx.npz |
Pynapple Tsd mapping scanner time (s) → tif frame index. |
<session>_behavior_sync_stats.pkl |
Synchronization statistics (barcode shift, match table, gap info). |
After synchronization, algorithm-specific synced outputs are created from the
extraction results, selecting F, Fneu, and spks traces at the synchronized
frame indices and saving them as pynapple TsdFrame objects.
Saved in behavior_sync/:
| File | Contents |
|---|---|
F_sync.npz |
Fluorescence traces at synchronized frames. |
Fneu_sync.npz |
Neuropil traces at synchronized frames. |
spks_sync.npz |
Deconvolved spike estimates at synchronized frames. |
When block_size > 1, frame indices are grouped into volumes (block_size consecutive
frames starting at a multiple of block_size). Only complete volumes — those for
which all block_size frames appear in the synchronized frame list — are included.
Truncated volumes (e.g. the last volume if the sync window ends mid-volume) are silently
dropped and a warning is printed. Timestamps are taken from the first frame of each
retained volume.
Suite2P produces both combined (all-plane) and per-plane outputs. Synced versions are created for all of them:
| File | Contents |
|---|---|
behavior_sync/F_sync.npz |
Combined fluorescence traces at synchronized frames. |
behavior_sync/Fneu_sync.npz |
Combined neuropil traces at synchronized frames. |
behavior_sync/spks_sync.npz |
Combined deconvolved spike estimates at synchronized frames. |
behavior_sync/plane0/F_sync.npz |
Plane-0 fluorescence traces at synchronized frames. |
behavior_sync/plane0/Fneu_sync.npz |
Plane-0 neuropil traces. |
behavior_sync/plane0/spks_sync.npz |
Plane-0 spike estimates. |
behavior_sync/plane1/… |
Same for plane 1. |
behavior_sync/plane2/… |
Same for plane 2. |
Frame indices from the behavioral sync (page-level indices in the raw TIFF) are
divided by block_size to convert them to volume-level indices before selecting
columns from the Suite2P arrays.
- With barcode – a cross-correlogram between the tif aux trigger and the
Barcode (Scanner)channel is used to find the time shift, then tif frames are matched one-to-one to scanner frame-clock pulses within a 25 ms tolerance. - Without barcode – the first scanner frame-clock pulse is assumed to correspond to the first tif frame. If timestamp gaps are present in the behavioral log, alignment is restricted to the period before the first gap (or gaps are interpolated if
fill_tsync_gapsistrue).
Set "ignore_barcode": true in data.json to force the without-barcode path even when a Barcode (Scanner) channel is present in the telemetry file.
Pass --dry-run to validate a configuration without executing anything:
batch2p data.json --dry-runThe command checks:
- All entries in
data(TIF files or directories) exist. params_fileandpinsheet_file(when present) exist.- All
.b64files listed inbehavior_dataexist. job_root_dir,results_root_dir,temp_dir, andworking_direither already exist or can be created.
Exits with code 0 on success, 1 if any check fails. All issues are printed to stderr.
- Create
batch2p/extractors/<name>.pyimplementing a subclass ofSourceExtractorfrombatch2p.extractors.base. The subclass must implementrun(),get_job_subdir(), andcreate_synced_outputs(). - Register it in
batch2p/extractors/__init__.pyby adding an entry to_EXTRACTORS. - Set
"source_extraction": "<name>"indata.json.
All stdout and stderr are tee'd to <results_path>/<job_id>.log so that the full
run log is available alongside the results even when the script is run non-interactively.
Before launching the pipeline the script writes two files into the results directory:
data_used.json– the run configuration with all file paths made absolute.params_used.json– the full settings dictionary actually passed to the algorithm (Suite2P: merged two-level dict; Suite3D: params JSON with numpy arrays serialized).params_supplied.json(Suite2P only) – the parameters as read from the user-suppliedparams_file, before merging with Suite2P defaults. Useful for comparing what was explicitly set versus what was inherited from defaults.