Skip to content

Commit c84c654

Browse files
committed
Refactor into NeuroAlign package, add pyproject.toml, and update branding
1 parent fa4d844 commit c84c654

7 files changed

Lines changed: 103 additions & 18 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ Thumbs.db
1818
*.zarr
1919
data/
2020
fake_neuropixels.dat
21-
*.dat
21+
*.dat
22+
*.egg-info/

pipeline/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
"""
2+
High Performance Neuro data pipeline
3+
"""
4+
5+
from .base_loader import BaseNeuroLoader
6+
from .ephys_loader import EphysLoader
7+
from .video_loader import VideoLoader
8+
from .nifti_loader import BidsNiftiLoader
9+
from .synchronizer import DataSynchronizer
10+
from .exporter import Hdf5Exporter
11+
12+
__version__ = "0.1.0"

cli.py renamed to pipeline/cli.py

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
11
import argparse
22
import os
3+
import logging
34
import numpy as np
4-
from pipeline.ephys_loader import EphysLoader
5-
from pipeline.video_loader import VideoLoader
6-
from pipeline.synchronizer import DataSynchronizer
7-
from pipeline.nifti_loader import BidsNiftiLoader
5+
6+
logging.basicConfig(
7+
level=logging.INFO,
8+
format="%(asctime)s - [%(levelname)s] - %(name)s: %(message)s",
9+
datefmt="%Y-%m-%d %H:%M:%S",
10+
)
11+
logger = logging.getLogger("ExpAlignCLI")
12+
13+
from .ephys_loader import EphysLoader
14+
from .video_loader import VideoLoader
15+
from .synchronizer import DataSynchronizer
16+
from .nifti_loader import BidsNiftiLoader
17+
from .exporter import Hdf5Exporter
818

919

1020
def main():
1121
parser = argparse.ArgumentParser(
12-
description="ExpAlign: High-Performance Neuro-Data Pipeline"
22+
description="NeuroAlign: High-Performance Neuro-Data Pipeline"
1323
)
14-
1524
parser.add_argument(
1625
"--ephys",
1726
type=str,
@@ -24,7 +33,6 @@ def main():
2433
parser.add_argument(
2534
"--fmri", type=str, required=False, help="Path to the BIDS NIfTI file"
2635
)
27-
2836
parser.add_argument(
2937
"--time", type=float, required=True, help="Timestamp in seconds to align"
3038
)
@@ -37,18 +45,17 @@ def main():
3745

3846
args = parser.parse_args()
3947

40-
print("\n" + "=" * 40)
41-
print(" EXPERANTO MULTIMODAL CLI PIPELINE")
42-
print("=" * 40)
48+
logger.info("Starting NeuroAlign Multimodal Pipeline")
4349

4450
ephys_loader = None
4551
video_loader = None
4652

4753
if args.ephys:
4854
if not os.path.exists(args.ephys):
49-
print(f"Generating dummy ephys data at {args.ephys} for CLI test...")
55+
logger.warning(
56+
f"Generating dummy ephys data at {args.ephys} for CLI test..."
57+
)
5058
np.random.rand(1000).astype(np.float32).tofile(args.ephys)
51-
5259
ephys_loader = EphysLoader(args.ephys, "CLI_Ephys_Dataset", 30000, 384)
5360
ephys_loader.load_data(filter_rule=args.filter)
5461

@@ -57,15 +64,20 @@ def main():
5764
video_loader.load_data()
5865

5966
if args.fmri:
60-
print("\n--- Initializing BIDS fMRI Pipeline ---")
67+
logger.info("Initializing BIDS fMRI Pipeline")
6168
bids_scan = BidsNiftiLoader(args.fmri, "CLI_fMRI_Dataset")
6269
bids_scan.load_data(filter_rule=args.filter)
6370

6471
if ephys_loader and video_loader:
6572
sync_engine = DataSynchronizer(ephys_loader, video_loader)
66-
sync_engine.get_data_at_time(args.time)
73+
ephys_idx, video_frame = sync_engine.get_data_at_time(args.time)
74+
75+
exporter = Hdf5Exporter()
76+
exporter.export_sync_data(
77+
time_sec=args.time, ephys_idx=ephys_idx, video_frame=video_frame
78+
)
6779

68-
print("=" * 40 + "\n")
80+
logger.info("Pipeline Execution Finished Successfully.")
6981

7082

7183
if __name__ == "__main__":

pipeline/ephys_loader.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def __init__(self, file_path, dataset_name, sampling_rate, num_channels):
1515
# COMPOSITION: We plug the FilterEngine into this loader!
1616
self.filter_engine = StringFilterEngine()
1717

18-
def load_data(self, filter_rule=None): # <-- Add a filter_rule argument
18+
def load_data(self, filter_rule=None):
1919
print(f"[{self.dataset_name}] Initializing Zero-Copy Memory Mapping...")
2020

2121
if not os.path.exists(self.file_path):

pipeline/exporter.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import h5py
2+
import os
3+
import logging
4+
5+
6+
class Hdf5Exporter:
7+
"""
8+
Serializes synchronized multimodal data chunks into HDF5 format
9+
for downstream machine learning pipelines (e.g., PyTorch/TensorFlow).
10+
"""
11+
12+
def __init__(self, output_filename="neuro_sync_output.h5"):
13+
self.output_filename = output_filename
14+
self.logger = logging.getLogger("Hdf5Exporter")
15+
16+
def export_sync_data(self, time_sec, ephys_idx, video_frame, fmri_tr=None):
17+
self.logger.info(
18+
f"Exporting synchronized slice at T={time_sec}s to {self.output_filename}"
19+
)
20+
21+
# Open an HDF5 file in write ('w') mode
22+
with h5py.File(self.output_filename, "w") as hf:
23+
# 1. Create a metadata group
24+
meta_group = hf.create_group("metadata")
25+
meta_group.create_dataset("sync_time_seconds", data=time_sec)
26+
27+
# 2. Create the data pointers
28+
hf.create_dataset("ephys_sync_index", data=ephys_idx)
29+
hf.create_dataset("video_sync_frame", data=video_frame)
30+
31+
if fmri_tr is not None:
32+
hf.create_dataset("fmri_sync_volume", data=fmri_tr)
33+
34+
self.logger.info("Export complete. Data is ready for downstream AI ingestion.")

pyproject.toml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[build-system]
2+
requires = ["setuptools>=61.0"]
3+
build-backend = "setuptools.build_meta"
4+
5+
[project]
6+
name = "neuro-align"
7+
version = "0.1.0"
8+
authors = [
9+
{ name="Charan Sai", email="guttulacharansai@gmail.com" },
10+
]
11+
description = "A high-performance, memory-mapped multimodal data pipeline for neuroscience."
12+
readme = "README.md"
13+
requires-python = ">=3.9"
14+
dependencies = [
15+
"numpy",
16+
"h5py",
17+
"nibabel"
18+
]
19+
20+
[project.scripts]
21+
neuro-align = "pipeline.cli:main"
22+
23+
[tool.setuptools.packages.find]
24+
include = ["pipeline*"]

requirements.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
numpy
2-
pytest
2+
pytest
3+
h5py
4+
nibabel

0 commit comments

Comments
 (0)