ACE-neuro: Multimodal alignment tutorial¶
Align ephys and miniscope for one line_num (typically TTL-based for Neuralynx + UCLA V3; hardware-clock alignment for some ONIX setups — see MiniscopeDataManager.sync_timestamps), then optional phase-at-calcium-event histograms.
Requires a session whose metadata row points to both modalities under data_path.
Project layout¶
Same as single-modality tutorials:
project_path:experiments.csv,analysis_parameters.csvdata_path: raw trees for both ephys and calcium for this line
Pick line_num only for recordings that actually have both streams populated in experiments.csv.
from pathlib import Path
project_path = Path("/path/to/your/project")
data_path = Path("/path/to/your/raw_data")
line_num = 97
channel_name = "PFCLFPvsCBEEG"
miniscope_filenames = ["0.avi"]
for label, p in ("experiments.csv", project_path / "experiments.csv"), (
"analysis_parameters.csv",
project_path / "analysis_parameters.csv",
):
if not p.is_file():
raise FileNotFoundError(f"Missing {label} at {p}")
from ace_neuro.shared.experiment_data_manager import ExperimentDataManager
edm = ExperimentDataManager(line_num, project_path=project_path, data_path=data_path)
print("ephys dir:", edm.get_ephys_directory())
print("calcium dir:", edm.metadata.get("calcium imaging directory") if edm.metadata else None)
Table of contents¶
- One-shot
MultimodalPipeline.run - Inspect sub-pipelines and alignment outputs on the API object
- Phase histograms (
ca_events=True) - Concept map (what ran internally)
- Troubleshooting
Step 1 — Full multimodal run¶
This runs ephys, then miniscope, then sync_neuralynx_miniscope_timestamps, index finding, and (if ca_events=True) phase histograms. Use headless=True on servers.
from ace_neuro.pipelines.multimodal import MultimodalPipeline
mm = MultimodalPipeline()
mm.run(
line_num=line_num,
project_path=project_path,
data_path=data_path,
channel_name=channel_name,
miniscope_filenames=miniscope_filenames,
ca_events=True,
headless=True,
run_CNMFE=True,
remove_components_with_gui=False,
inspect_motion_correction=False,
)
print("Alignment timestamps shape:", None if mm.t_ca_im is None else getattr(mm.t_ca_im, "shape", len(mm.t_ca_im)))
Step 2 — Outputs on MultimodalPipeline¶
After run(), use mm.ephys_pipeline / mm.miniscope_pipeline for modality-specific state, and the alignment fields below for cross-modal analysis.
print("ephys channel object:", mm.ephys_pipeline.ephys_data_manager.get_channel(channel_name))
print("ephys_idx_all_TTL_events:", mm.ephys_idx_all_TTL_events is not None)
print("ephys_idx_ca_events:", mm.ephys_idx_ca_events is not None)
print("ca_frame_num_of_ephys_idx:", mm.ca_frame_num_of_ephys_idx is not None)
Step 3 — Phase histograms (ephys vs miniscope bands)¶
Populated when ca_events=True and event detection succeeded. Uses mm.phase_hist_ephys / mm.phase_bin_edges_ephys (and miniscope counterparts).
import matplotlib.pyplot as plt
import numpy as np
if mm.phase_hist_ephys is not None and mm.phase_bin_edges_ephys is not None:
centers = (mm.phase_bin_edges_ephys[:-1] + mm.phase_bin_edges_ephys[1:]) / 2.0
plt.figure(figsize=(8, 4))
plt.bar(centers, mm.phase_hist_ephys, width=np.diff(mm.phase_bin_edges_ephys).mean(), alpha=0.7, label="ephys phase @ CA")
plt.xlabel("Phase (rad)")
plt.legend()
plt.title("Calcium events vs ephys phase")
plt.show()
else:
print("No ephys phase histogram (enable ca_events and ensure CNMF-E + events ran).")
if mm.phase_hist_miniscope is not None and mm.phase_bin_edges_miniscope is not None:
centers = (mm.phase_bin_edges_miniscope[:-1] + mm.phase_bin_edges_miniscope[1:]) / 2.0
plt.figure(figsize=(8, 4))
plt.bar(centers, mm.phase_hist_miniscope, width=np.diff(mm.phase_bin_edges_miniscope).mean(), alpha=0.7, color="C1", label="miniscope phase @ CA")
plt.xlabel("Phase (rad)")
plt.legend()
plt.show()
Internals (same as MultimodalPipeline.run)¶
EphysPipeline.run→MiniscopePipeline.runsync_neuralynx_miniscope_timestamps—delete_TTLs,fix_TTL_gaps,only_experiment_eventsfind_ephys_idx_of_TTL_events, optionalfind_ca_movie_frame_num_of_ephys_idxephys_phase_ca_events/miniscope_phase_ca_events→phase_ca_events_histogram
Optional movie export: create_ca_ephys_movie in ace_neuro.multimodal.calcium_ephys_visualizer (resource-heavy).
Troubleshooting¶
- Wrong directory: Same CSV rules as other tutorials — if
project_pathis wrong, both modalities fail metadata lookup. - No histograms: Need
ca_events=True, detectedca_events_idx, and phases computed on the miniscope side. - CNMF-E in multimodal: Turning off
run_CNMFEprevents downstream postprocess-dependent steps.