This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
PyTorch Connectomics (PyTC) is a modern deep learning framework for automatic and semi-automatic semantic and instance segmentation in connectomics - reconstructing neural connections from electron microscopy (EM) images. The framework integrates PyTorch Lightning for orchestration and MONAI for medical imaging tools, maintained by Harvard's Visual Computing Group.
Map of common user intents → authoritative source files. Use this
table first; jump straight to the listed paths instead of grepping.
This is the single source of truth for agent navigation; the prompt
files under prompts/ (prompts/INSTALL.md, prompts/ADD_DATASET.md,
prompts/ADD_ARCH.md, prompts/DEBUG_TUTORIAL.md) are thin wrappers
that point back at it.
| Intent | Authoritative source | Concrete example |
|---|---|---|
| Run training | scripts/main.py → connectomics/runtime/dispatch.py |
just train mito_lucchi++ |
| Run inference + decode + evaluate | --mode test → inference/stage.py → decoding/stage.py → evaluation/stage.py |
just test mito_lucchi++ <ckpt> |
| Tune decode params (Optuna) | runtime/tune_runner.py → decoding/tuning/optuna_tuner.py |
python scripts/main.py --config <yaml> --mode tune --checkpoint <ckpt> |
| Add a dataset / new EM volume | tutorials/<new>.yaml (copy closest); data dicts in data/datasets/data_dicts.py; new file format only if needed → connectomics/data/io/io.py |
tutorials/mito_lucchi++.yaml |
| Add a model architecture | connectomics/models/architectures/; register via @register_architecture("name") decorator; add config params to connectomics/config/schema/model.py |
models/architectures/monai_models.py |
| Add a loss function | connectomics/models/losses/losses.py; register in create_loss(); metadata in losses/metadata.py |
models/losses/build.py |
| Add a decoder | connectomics/decoding/decoders/; register via the register_decoder(name, fn, *, overwrite=False) function call in decoding/registry.py (NOT a @register_decoder decorator) |
decoding/decoders/segmentation.py |
| Change augmentation | connectomics/data/augmentation/build.py; profile YAMLs in config/profiles/augmentation_*.yaml |
data/augmentation/transforms.py |
| Change postprocess | connectomics/decoding/postprocess.py; templates in config/templates/decoding_*.yaml |
decoding/streamed_chunked.py |
| Add a tutorial config | tutorials/<name>.yaml; validate with python scripts/validate_tutorial_configs.py --glob 'tutorials/<name>.yaml' (note: --glob is additive over the default tutorials/*.yaml; filter output for the new path before fixing anything) |
tutorials/mito_lucchi++.yaml |
| Debug a failing tutorial | prompts/DEBUG_TUTORIAL.md; reproduce with python scripts/main.py --config <yaml> --fast-dev-run |
python scripts/main.py --config <yaml> --fast-dev-run |
When a new intent class shows up, add a row here rather than scattering pointers across READMEs.
The codebase follows a clean separation of concerns:
- PyTorch Lightning: Orchestration layer (training loop, distributed training, mixed precision, callbacks, logging)
- MONAI: Domain toolkit (medical image models, transforms, losses, metrics)
- Hydra/OmegaConf: Modern configuration management (type-safe, composable configs)
Key Principle: Lightning is the outer shell, MONAI is the inner toolbox. No reimplementation of training loops or domain-specific tools.
The codebase enforces an explicit contract from the v2/v3 refactor:
- One canonical owner per concept. No backward-compatibility shims, no facade re-exports, no duplicate import paths.
- Strict config. Unknown top-level keys raise at load time. Removed fields raise.
getattr(cfg.x, "y", default)ghost reads on undeclared fields are forbidden. - Stages are separate. Pipeline =
train → infer → decode → evaluate → tune. Each stage has its own package and its own entry function. Combined test-mode is a thin wrapper that calls stage APIs in sequence. - Dependency direction:
config → utils → data → models → metrics;training → {config, data, models, metrics};inference → {config, data, models};decoding → {config, data, utils};evaluation → {config, data, metrics};runtime → {config, training, inference, decoding, evaluation}. Static AST tests intests/unit/test_v3_guardrails.pyenforce this. - Public API is explicit and small.
tests/unit/test_public_api_snapshot.pyasserts exact__all__membership.
- Ecosystem-first, no reinvention: Leverage proven frameworks (PyTorch, Lightning, MONAI, nnU-Net) to keep the codebase modern, minimal, and scalable.
- Config-first reproducibility: Use Hydra/OmegaConf YAML composition + CLI overrides so experiments are declarative, reproducible, and easy to customize across datasets/benchmarks.
- Modular + extensible connectomics workflows: Separate concerns cleanly (config, data, training, inference, decoding, evaluation, runtime), expose registry-style extension points, and support large-volume EM workloads (tiling, sliding-window, multi-GPU) for both novices and agentic workflows.
Requires Python 3.8+, PyTorch 1.8+. Install PyTorch separately for your CUDA version, then:
pip install -e . # core
pip install -e .[full] # +tifffile/wandb/jupyter/gputil
# extras: [optim] [wandb] [tiff] [viz] [metrics] [dev] [docs]
pip install git+https://github.com/PytorchConnectomics/MedNeXt.git # optional MedNeXt# Activate your conda/virtual environment
source /projects/weilab/weidf/lib/miniconda3/bin/activate pytc# enable environment
source /projects/weilab/weidf/lib/miniconda3/bin/activate pytc
# Lightning-based training (NEW - Primary)
python scripts/main.py --config tutorials/lucchi.yaml
# Override config from CLI
python scripts/main.py --config tutorials/lucchi.yaml data.dataloader.batch_size=8 optimization.max_epochs=200
# Testing mode
python scripts/main.py --config tutorials/lucchi.yaml --mode test --checkpoint path/to/checkpoint.ckpt
# Fast dev run (1 batch for debugging)
python scripts/main.py --config tutorials/lucchi.yaml --fast-dev-run# Run all tests
python -m pytest tests/
# Run specific test modules
python -m pytest tests/test_models.py
python -m pytest tests/test_augmentations.py
python -m pytest tests/test_loss_functions.pyPost-v3 layout (155 files, ~43K LOC). Many subpackages were renamed in v2/v3:
models/arch → models/architectures, models/loss → models/losses,
training/loss → training/losses, training/optim → training/optimization,
data/dataset → data/datasets, data/augment → data/augmentation,
data/process → data/processing. New top-level packages: runtime/,
evaluation/. Schema split: top-level decoding, evaluation, inference
sections each have their own dataclass module.
connectomics/ # Main Python package (~155 files, ~43K LOC)
├── config/ # Hydra/OmegaConf configuration system (no domain imports)
│ ├── pipeline/
│ │ ├── config_io.py # Config loading, saving, merging, strict-key checks
│ │ ├── profile_engine.py # YAML profile composition engine
│ │ ├── stage_resolver.py # Multi-stage (train/test/tune) config resolution
│ │ └── dict_utils.py # Plain-dict + cfg_get accessors
│ ├── hardware/
│ │ ├── auto_config.py # Auto-configuration planner (GPU-aware)
│ │ ├── gpu_utils.py # GPU memory estimation and batch-size planning
│ │ └── slurm_utils.py # SLURM helpers
│ ├── profiles/ # Section-level profile registries (yaml)
│ ├── templates/ # Decoding templates (yaml)
│ ├── all_profiles.yaml # Master registry index used by tutorials
│ └── schema/ # Dataclass-based config schema definitions
│ ├── root.py # Top-level Config dataclass
│ ├── system.py # System (GPU, CPU, seed)
│ ├── data.py # Data, dataloader, augmentation
│ ├── model.py # Model config (+ model_monai/_mednext/_rsunet/_nnunet)
│ ├── optimization.py # Optimizer, scheduler, training
│ ├── monitor.py # Checkpoint, early stopping, logging
│ ├── inference.py # Inference stage config (raw prediction)
│ ├── decoding.py # Decoding stage config (split out in PR 8)
│ ├── evaluation.py # Evaluation stage config (split out in PR 8)
│ └── stages.py # Multi-stage (test/tune) wrappers
│
├── models/ # Model architectures and loss functions
│ ├── build.py # Model factory (registry-based)
│ ├── architectures/ # Architecture registry + model wrappers
│ │ ├── registry.py # Architecture registration system
│ │ ├── base.py # ConnectomicsModel base interface
│ │ ├── monai_models.py # MONAI wrappers (4 architectures)
│ │ ├── mednext_models.py # MedNeXt wrappers (2 architectures)
│ │ ├── nnunet_models.py # nnU-Net pretrained wrappers (`nnunet`)
│ │ └── rsunet.py # RSUNet models (2 architectures)
│ └── losses/ # Loss function implementations
│ ├── build.py # Loss factory
│ ├── losses.py # Connectomics-specific losses
│ ├── metadata.py # Loss metadata (target types, activation info)
│ └── regularization.py # Regularization losses
│
├── training/ # Training orchestration (no decoding/evaluation internals)
│ ├── lightning/ # PyTorch Lightning integration (PRIMARY)
│ │ ├── model.py # ConnectomicsModule (train/val/test steps, TTA)
│ │ ├── data.py # ConnectomicsDataModule
│ │ ├── data_factory.py # Data dict creation from config
│ │ ├── trainer.py # Trainer creation utilities
│ │ ├── callbacks.py # Custom callbacks (NaN, EMA, …)
│ │ ├── runtime.py # Run directory setup
│ │ ├── path_utils.py # File path expansion utilities
│ │ ├── prediction_crops.py # Prediction-crop helpers (extracted in PR 10)
│ │ ├── test_pipeline.py # Test orchestration; delegates to evaluation/
│ │ ├── visualizer.py # TensorBoard visualization
│ │ └── utils.py # Thin remaining glue (was 771; now ~77)
│ ├── losses/ # Loss orchestration
│ │ ├── orchestrator.py # Multi-loss + deep supervision orchestrator
│ │ ├── plan.py # Loss plan builder from config
│ │ └── balancing.py # Loss weight balancing
│ ├── optimization/ # Optimizers and schedulers
│ │ ├── build.py # Optimizer/scheduler factory
│ │ └── lr_scheduler.py # Custom LR schedulers (WarmupCosine, …)
│ ├── model_weights.py # Weight loading/conversion utilities
│ └── debugging.py # NaN detection and debugging utilities
│
├── data/ # Data loading and preprocessing
│ ├── datasets/ # Dataset classes
│ │ ├── base.py # Base dataset class
│ │ ├── dataset_volume_cached.py
│ │ ├── dataset_volume_h5_lazy.py
│ │ ├── dataset_volume_zarr_lazy.py
│ │ ├── dataset_filename.py # Filename-based datasets (2D images)
│ │ ├── dataset_multi.py # Multi-dataset wrapper
│ │ ├── data_dicts.py # MONAI data dictionary creation
│ │ ├── crop_sampling.py # Random crop sampling
│ │ ├── sampling.py # Sampling strategies
│ │ └── split.py # Train/val/test splitting
│ ├── augmentation/ # MONAI-based augmentations
│ │ ├── build.py # Transform pipeline builder
│ │ ├── transforms.py # Custom MONAI transforms
│ │ ├── augment_ops.py # Augmentation primitive ops
│ │ └── transform_utils.py
│ ├── io/ # Multi-format I/O
│ │ ├── io.py # HDF5, TIFF, PNG, NIfTI, Zarr reading/writing
│ │ ├── transforms.py # LoadVolumed and related MONAI transforms
│ │ ├── tiles.py # Tile I/O utilities
│ │ └── utils.py
│ └── processing/ # Preprocessing and target generation
│ ├── build.py # Transform pipeline builder
│ ├── target.py # Label target generation
│ ├── transforms.py # Processing MONAI transforms
│ ├── distance.py # Distance transform computation
│ ├── flow.py # Optical flow computation
│ ├── weight.py # Sample weight generation
│ ├── segment.py # Segmentation utilities
│ ├── bbox.py / bbox_processor.py
│ ├── affinity.py / iou.py
│ ├── nnunet_preprocess.py # nnU-Net-style preprocessing
│ ├── quantize.py # Label quantization
│ └── misc.py
│
├── inference/ # Stage 2: model prediction → raw artifacts
│ ├── stage.py # `run_prediction_inference` (canonical entry)
│ ├── manager.py # Inference manager
│ ├── sliding.py # Sliding window inference
│ ├── lazy.py / lazy_distributed.py # Lazy-volume sliding window
│ ├── chunked.py # Chunked inference for large volumes
│ ├── chunk_grid.py # Public chunk-grid utilities (per PR-14)
│ ├── tta.py / tta_combinations.py # Test-time augmentation
│ ├── output.py # Output saving utilities
│ └── artifact.py # `PredictionArtifactMetadata`,
│ # `write_prediction_artifact`
│
├── decoding/ # Stage 3: raw arrays → segmentation artifacts
│ ├── stage.py # `run_decoding_stage` entry
│ ├── pipeline.py # Decode-mode normalization + apply pipeline
│ ├── registry.py # Decoder registration (lazy registration via _BUILTINS_REGISTERED)
│ ├── base.py # Decoder dataclass + protocol
│ ├── postprocess.py # Binary/instance post-processing
│ ├── streamed_chunked.py # Chunked decode + CC stitching
│ ├── experiment_log.py # Decode-experiment logging (extracted from training)
│ ├── decoders/ # Concrete decoder implementations
│ │ ├── segmentation.py # CC, distance-watershed, waterz
│ │ ├── segmentation_kernels.py # numba CC kernels
│ │ ├── synapse.py / abiss.py / branch_merge.py / waterz.py
│ ├── tuning/ # Pure tuner (no `connectomics.training` imports)
│ │ └── optuna_tuner.py
│ └── utils.py
│
├── evaluation/ # Stage 4: artifacts + GT → metrics (PR 4)
│ ├── stage.py # `run_evaluation_stage`
│ ├── metrics.py # Test-mode metric instantiation + computation
│ ├── nerl.py # Skeleton-based metrics (NERL/ERL)
│ ├── report.py # Metrics file writing + epoch logging
│ ├── context.py # `EvaluationContext` (decouples from Lightning module)
│ └── curvilinear.py
│
├── runtime/ # CLI / dispatch / orchestration glue (PR 7)
│ ├── cli.py # `parse_args`, `setup_config`
│ ├── dispatch.py # Mode dispatch (train/test/tune/decode-only/cache-hit)
│ ├── output_naming.py # Naming helpers (extracted in PR 2)
│ ├── checkpoint_dispatch.py # Output-base derivation from checkpoint
│ ├── cache_resolver.py # Cached prediction file detection / cache-only test path
│ ├── sharding.py # Independent test sharding
│ ├── tune_runner.py # `run_tuning`, `load_and_apply_best_params` (PR 5)
│ ├── preflight.py # Cross-section validation (moved from config in B5)
│ └── torch_safe_globals.py # `torch.serialization.add_safe_globals` registry
│
├── metrics/ # Metric implementations (no orchestration)
│ ├── metrics_seg.py # TorchMetrics segmentation (Jaccard, Dice, VOI)
│ ├── metrics_skel.py # Skeleton-based metrics
│ └── segmentation_numpy.py # NumPy metrics (Adapted Rand, etc.)
│
└── utils/ # Cross-domain primitives only
├── errors.py # Preflight config validation
├── visualizer.py # TensorBoard visualization
├── download.py # Dataset downloading
├── debug_utils.py / debug_hooks.py
└── label_overlap.py # Vectorized label-overlap helper
scripts/ # Entry points and utilities
├── main.py # Primary entry point — thin: parse → dispatch
├── decode_large.py # Large-volume decode workflow (custom config surface)
├── demo.py # Demo script for quick testing
├── profile_dataloader.py # Data loading profiling tool
├── slurm_launcher.py # SLURM cluster job launcher
├── visualize_neuroglancer.py # Neuroglancer 3D visualization
├── download_data.py # Dataset downloader
├── apply_volume_function.py # Apply functions to volume files
├── images_to_h5.py # Convert image stacks to HDF5
├── downsample_nisb.py # NISB dataset downsampling
├── validate_tutorial_configs.py # Tutorial config validation (CI)
└── tools/ # Additional utility scripts
├── compare_config.py
└── eval_curvilinear.py
tutorials/ # Example configurations (16 canonical YAMLs + custom workflows)
├── mitoEM/, neuron_nisb/, neuron_snemi/ # Multi-config experiment families
├── *.yaml # Dataset-specific configs
│ # mito_lucchi++, mito_mitolab, mito_betaseg(_banis_v0/v1/v2),
│ # neuron_liconn_mit(_x2), nuc_nucmm-z, syn_cremi,
│ # vesicle_xm, fiber_linghu26, minimal, waterz_decoding
└── waterz_decoding_large{,_abiss}.yaml # Custom large-volume workflow YAMLs
# (top-level `large_decode:`/`abiss_large:` keys;
# bypass structured Config; consumed by the
# `waterz_decode_large` console script in lib/waterz/)
tests/ # Test suite
├── unit/ # Unit tests
│ ├── test_v3_guardrails.py # Boundary AST tests, public API snapshots, strict-config raise
│ └── test_v2_boundaries.py # V2 boundary contracts
├── integration/ # Integration tests
├── benchmarks/ # Smoke benchmarks (chunked write throughput, …)
└── e2e/ # End-to-end tests (requires data)
docs/ # Sphinx documentation
notebooks/ # Jupyter notebooks
docker/ # Docker containerization
| Stage | Top-level config | Entry function | Owns |
|---|---|---|---|
| train | optimization, data, model |
trainer.fit(...) |
model fitting + checkpoints |
| infer | inference |
inference.stage.run_prediction_inference |
model → raw prediction artifact |
| decode | decoding |
decoding.stage.run_decoding_stage |
raw prediction → segmentation artifact |
| evaluate | evaluation |
evaluation.stage.run_evaluation_stage |
artifact + GT → metrics |
| tune | decoding.tuning (+ tune stage block) |
runtime.tune_runner.run_tuning |
search over decode/postproc params |
The project uses Hydra/OmegaConf with dataclass-based configs for type safety and composability.
Canonical YAML layout:
connectomics/config/profiles/*.yaml: section-level registries selected by*.profileconnectomics/config/templates/*.yaml: explicit list-item templates, currently for top-leveldecodingtutorials/*.yaml: runnable experiments that_base_the shared registries
Canonical merge semantics:
- Profile payloads are merged into the target section as the base config.
- Explicit keys override profile keys.
- Explicit lists replace profile lists; list overrides are not additive.
- Canonical decoding expansion is explicit
template:inside top-leveldecoding. - Do not introduce
decoding_profileor- profile: decoding_*usages.
Config File Example (tutorials/lucchi.yaml):
system:
num_gpus: 1
num_cpus: 4
seed: 42
model:
architecture: monai_basic_unet3d
in_channels: 1
out_channels: 2
filters: [32, 64, 128, 256, 512, 1024]
dropout: 0.1
loss_functions:
- DiceLoss
- BCEWithLogitsLoss
loss_weights: [1.0, 1.0]
data:
train_image: "datasets/lucchi/train_image.h5"
train_label: "datasets/lucchi/train_label.h5"
patch_size: [128, 128, 128]
batch_size: 2
num_workers: 4
optimizer:
name: AdamW
lr: 1e-4
weight_decay: 1e-4
scheduler:
name: CosineAnnealingLR
warmup_epochs: 5
training:
max_epochs: 100
precision: "16-mixed"
gradient_clip_val: 1.0Key Config Sections (top-level):
system: Hardware (GPUs, CPUs, seed)model: Architecture, loss functions, model parametersdata: Paths, batch size, augmentationoptimization: Optimizer, scheduler, training-loop parametersmonitor: Checkpoint, early stopping, logging configurationinference: Raw prediction stage (sliding window, TTA, chunking, output paths)decoding: Decoding pipeline (decoders, postprocessing, output, tuning)evaluation: Metric selection + thresholds forevaluatestagetest/tune: Stage wrappers that pull from the top-levelinference/decoding/evaluationsections
V3 schema split (PR 8): inference.postprocessing → decoding.postprocessing,
inference.decoding_path → decoding.output_path,
inference.saved_prediction_path → decoding.input_prediction_path. Architecture
nnunet_pretrained was renamed to nnunet. Strict-config raise: any unknown
top-level key fails at load time.
from connectomics.config import load_config, print_config
# Load config
cfg = load_config("tutorials/lucchi.yaml")
# Override from CLI or code
cfg.data.dataloader.batch_size = 8
# Print config
print_config(cfg)The framework uses an extensible architecture registry for managing models:
from connectomics.models.architectures import (
list_architectures,
get_architecture_builder,
register_architecture,
print_available_architectures,
)
# List all available architectures
archs = list_architectures() # 8 total architectures
# Get detailed info with counts
print_available_architectures()MONAI Models (4) - No deep supervision:
monai_basic_unet3d: Simple and fast 3D U-Net (also supports 2D)monai_unet: U-Net with residual units and advanced featuresmonai_unetr: Transformer-based UNETR (Vision Transformer backbone)monai_swin_unetr: Swin Transformer U-Net (SOTA but memory-intensive)
MedNeXt Models (2) - WITH deep supervision:
mednext: MedNeXt with predefined sizes (S/B/M/L) - RECOMMENDED- S: 5.6M params, B: 10.5M, M: 17.6M, L: 61.8M
mednext_custom: MedNeXt with full parameter control for research
RSUNet Models (2) - Pure PyTorch, WITH deep supervision:
rsunet: Residual symmetric U-Net with anisotropic convolutions (EM-optimized)rsunet_iso: RSUNet with isotropic convolutions for uniform voxel spacing
MedNeXt (MICCAI 2023) is a ConvNeXt-based architecture optimized for 3D medical image segmentation:
Predefined Sizes (mednext architecture):
model:
architecture: mednext
mednext_size: S # S (5.6M), B (10.5M), M (17.6M), or L (61.8M)
mednext_kernel_size: 3 # 3, 5, or 7
deep_supervision: true # RECOMMENDED for best performanceCustom Configuration (mednext_custom architecture):
model:
architecture: mednext_custom
mednext_base_channels: 32
mednext_exp_r: [2, 3, 4, 4, 4, 4, 4, 3, 2]
mednext_block_counts: [3, 4, 8, 8, 8, 8, 8, 4, 3]
mednext_kernel_size: 7
deep_supervision: true
mednext_grn: true # Global Response NormalizationKey Features:
- Deep Supervision: Multi-scale outputs (5 scales) for improved training
- UpKern: Weight initialization technique for larger kernels
- Isotropic Spacing: Prefers 1mm isotropic spacing (unlike nnUNet)
- Training: Use AdamW with lr=1e-3, constant LR (no scheduler)
Note: MedNeXt is an optional external dependency - see Installation section for setup
from connectomics.models import build_model
# From config
model = build_model(cfg)
# Model info
print(model.get_model_info()) # Shows parameters, architecture details- Registry-based model building system
- Hydra/OmegaConf configs only
- PyTorch Lightning handles parallelization automatically
- Clean error messages with architecture listing
from connectomics.models.losses import create_loss
# Available losses
loss = create_loss(loss_name='DiceLoss')
loss = create_loss(loss_name='FocalLoss')
loss = create_loss(loss_name='TverskyLoss')
loss = create_loss(loss_name='DiceCELoss')Supported Losses:
DiceLoss: Soft Dice loss for segmentationFocalLoss: Focal loss for class imbalanceTverskyLoss: Tversky loss for handling FP/FN trade-offsDiceCELoss: Combined Dice + Cross-EntropyBCEWithLogitsLoss: Binary cross-entropy with logitsCrossEntropyLoss: Multi-class cross-entropy
Multiple losses can be combined with weights in the config.
Wraps models with automatic training features:
- Distributed training (DDP)
- Mixed precision training (AMP)
- Gradient accumulation
- Learning rate scheduling
- Checkpointing
- Multi-loss support
- Deep supervision: Multi-scale loss computation with automatic target resizing
from connectomics.training.lightning import ConnectomicsModule
# Create Lightning module
lit_model = ConnectomicsModule(cfg)
# Or with pre-built model
lit_model = ConnectomicsModule(cfg, model=custom_model)Handles data loading with MONAI transforms:
- Train/val/test splits
- MONAI CacheDataset for fast loading
- Automatic augmentation pipeline
- Persistent workers for efficiency
from connectomics.training.lightning import ConnectomicsDataModule
datamodule = ConnectomicsDataModule(cfg)Convenience function for creating Lightning Trainer:
from connectomics.training.lightning import create_trainer
trainer = create_trainer(cfg)
trainer.fit(lit_model, datamodule=datamodule)- Support for HDF5, TIFF stacks, Zarr
- 3D volumetric EM data handling
- Multi-scale and multi-task labels
- Efficient caching and preprocessing
Uses MONAI transforms for:
- Intensity transformations
- Spatial transformations (rotation, scaling)
- Elastic deformation
- Random cropping
- Normalization
- Input: (batch, channels, depth, height, width)
- Patch Size: Typically 128x128x128 for 3D
- Normalization: Z-score or min-max per sample
# 1. Load config
from connectomics.config import load_config
cfg = load_config("tutorials/lucchi.yaml")
# 2. Set seed
from pytorch_lightning import seed_everything
seed_everything(cfg.system.seed)
# 3. Create data module
from connectomics.training.lightning import ConnectomicsDataModule
datamodule = ConnectomicsDataModule(cfg)
# 4. Create model
from connectomics.training.lightning import ConnectomicsModule
model = ConnectomicsModule(cfg)
# 5. Create trainer
from connectomics.training.lightning import create_trainer
trainer = create_trainer(cfg)
# 6. Train
trainer.fit(model, datamodule=datamodule)
# 7. Test
trainer.test(model, datamodule=datamodule)python scripts/main.py --config tutorials/lucchi.yamltraining:
precision: "16-mixed" # or "32", "bf16-mixed"system:
num_gpus: 4 # Automatically uses DDPtraining:
accumulate_grad_batches: 4 # Effective batch size = 4xcheckpoint:
monitor: "val/loss"
mode: "min"
save_top_k: 3
save_last: trueearly_stopping:
monitor: "val/loss"
patience: 10
mode: "min"scheduler:
name: CosineAnnealingLR
warmup_epochs: 5
min_lr: 1e-6connectomics/config/schema/root.py: Top-level Config dataclassconnectomics/config/schema/: All dataclass schemas (incl.decoding.py,evaluation.py)connectomics/config/pipeline/config_io.py: Config loading, strict-key check, validationconnectomics/config/pipeline/profile_engine.py: YAML profile composition engineconnectomics/config/pipeline/stage_resolver.py: Multi-stage config resolution
connectomics/models/build.py: Model factoryconnectomics/models/architectures/registry.py: Architecture registration systemconnectomics/models/losses/build.py: Loss factoryconnectomics/training/optimization/build.py: Optimizer/scheduler factory
connectomics/training/lightning/model.py: ConnectomicsModule (train/val/test)connectomics/training/lightning/data.py: ConnectomicsDataModuleconnectomics/training/lightning/trainer.py: Trainer utilitiesconnectomics/training/lightning/test_pipeline.py: Test orchestration; delegates toevaluation/connectomics/training/losses/orchestrator.py: Multi-loss + deep supervisionconnectomics/inference/stage.py:run_prediction_inference(raw artifact)connectomics/decoding/stage.py:run_decoding_stageconnectomics/evaluation/stage.py:run_evaluation_stageconnectomics/runtime/tune_runner.py:run_tuning,load_and_apply_best_params
scripts/main.py: Primary entry — parse → setup config →runtime.dispatchwaterz_decode_large(console script fromlib/waterz/, modulewaterz.cli.decode_large): Custom large-volume decode workflow (consumeslarge_decode:top-level keys intutorials/waterz_decoding_large*.yamlandtutorials/neuron_nisb/*_waterz_large_decode.yaml; these YAMLs intentionally bypass the structuredConfigschema). Install viapip install -e lib/waterz/.
- Add builder function in
connectomics/models/architectures/ - Register with
@register_architecture("name")decorator - Add config parameters to appropriate schema file in
config/schema/ - Create example config in
tutorials/ - Add tests
- Implement in
connectomics/models/losses/losses.py - Register in
create_loss()function - Update documentation
- Add unit tests
- Use MONAI transforms when possible
- Add custom transforms to
connectomics/data/augmentation/ - Register in transform builder
- Implement in
connectomics/decoding/decoders/ - Register with
@register_decoder("name")(lazy registration via_BUILTINS_REGISTERED) - Wire into
decoding/pipeline.pyif it needs orchestration glue - Reference from a tutorial YAML using a
template:entry under top-leveldecoding
- Use Lightning for training: Don't reimplement training loops
- Use MONAI for domain tools: Don't reimplement transforms/losses
- Use Hydra configs: Type-safe, composable, CLI-friendly
- Modular code: One responsibility per module
- Test everything: Unit tests for all components
- Documentation: Update docs when adding features
- ✅ YACS → Hydra/OmegaConf: complete
- ✅ Custom trainer → Lightning: complete
- ✅ Custom models → MONAI/MedNeXt/RSUNet/nnUNet: complete
- ✅ V2 layout refactor (Codex): complete — package boundaries, schema dataclasses, stage scaffolding
- ✅ V3 boundary/contract refactor (PR 0–11): mostly complete
- Total Python files: ~155 (connectomics module)
- Lines of code: ~43,000 (connectomics module)
- Architecture: enforced via static AST tests (
tests/unit/test_v3_guardrails.py) - Type safety: dataclass configs with strict-key check;
getattr(cfg.x, "y", default)ghost reads on undeclared fields are forbidden - Public API: snapshot-tested in
tests/unit/test_public_api_snapshot.py
The architectural skeleton is correct; behavioral cleanup partial.
Landed cleanly:
- Boundary fixes: decoding↛training, inference↛decoding, config↛data execution
- Strict config: unknown top-level keys raise on load
- Schema split:
decoding,evaluationare now top-level config sections - Stage separation:
inference.stage,decoding.stage,evaluation.stage,runtime.tune_runnereach expose a stage entry function - Runtime extraction:
runtime/package owns CLI, dispatch, naming, cache resolution, sharding, preflight, torch-safe-globals - Tutorial migration: 38/40 canonical tutorials load through
Config; the 2 exceptions (tutorials/waterz_decoding_large{,_abiss}.yaml) are custom workflow YAMLs consumed by thewaterz_decode_largeconsole script (fromlib/waterz/) and intentionally bypass the structured schema (validator skips viaCUSTOM_WORKFLOW_ROOTS) - Architecture rename:
nnunet_pretrained→nnunet - Lazy decoder registration via
_BUILTINS_REGISTEREDflag - Public API trim with snapshot tests
Known follow-ups (post-v3):
- Evaluation extraction is a file move;
connectomics.evaluation.*functions still takemoduleas first arg withhasattr(module, "_…")defensive fallbacks (PR-13 /EvaluationContextrewrite) decoding/streamed_chunked.pyimports public chunk-grid utilities frominference/chunk_grid.py(PR-14 done) — verify no remaining underscore-prefixed cross-package importsDecodingConfig.tuning: Optional[Dict[str, Any]]should be a typed dataclass- File splits in PR 10 are partial:
inference/lazy.py(1295), the twodata/{augmentation,processing}/transforms.py(1346 + 979),training/lightning/data_factory.py(1168),callbacks.py(1001),decoders/segmentation.py(815) are untouched and remain the highest-value splits when adjacent behavior changes are needed - A3 product items (
RandMixupd,auto_plan_config,WandbConfig,GANLoss, single-task wrappers,TestConfig.output_path/cache_suffix) deferred pending maintainer sign-off
python -m pytest tests/unit/test_v3_guardrails.py tests/unit/test_v2_boundaries.py \
tests/unit/test_public_api_snapshot.py -q
python scripts/validate_tutorial_configs.pyAuthoritative list lives in setup.py/pyproject.toml. Highlights:
- Core (auto-installed): torch≥1.8, pytorch-lightning≥2.0, monai≥0.9.1, torchmetrics, omegaconf≥2.1, numpy≥1.23, scipy, scikit-image, h5py, opencv-python, einops, cc3d, kimimaro, mahotas, fastremap, tensorboard, tqdm.
- Extras:
[full](tifffile, wandb, jupyter, gputil),[optim](optuna),[wandb],[tiff],[viz](neuroglancer),[metrics](funlib.evaluate, manual:pip install git+https://github.com/funkelab/funlib.evaluate.git),[dev](pytest, pytest-benchmark),[docs](sphinx). - External: MedNeXt (
pip install git+https://github.com/PytorchConnectomics/MedNeXt.git, exposesfrom nnunet_mednext import create_mednext_v1); graceful fallback if missing.
- Config: validate YAML, use
print_config(cfg); unknown top-level keys raise. - GPU OOM: lower
data.dataloader.batch_size/patch_size, useprecision: "16-mixed". - Slow data loading: raise
system.num_workers, setdata.dataloader.persistent_workers: true, enableuse_cachefor small datasets. - Missing module errors: reinstall with the matching extra (e.g.
pip install -e .[full]for tifffile/wandb).
- README.md: Project overview and quick start
- QUICKSTART.md: 5-minute setup guide
- TROUBLESHOOTING.md: Common issues and solutions
- tests/TEST_STATUS.md: Detailed test coverage status
- tests/README.md: Testing guide
- PyTorch Lightning Docs - Training orchestration
- MONAI Docs - Medical imaging toolkit
- Hydra Docs - Configuration management
- Project Documentation - Full docs
- Slack Community - Get help