Skip to content

HemiSpec API Design

This document defines the first stable Python API layer for the Hemisphere Reconstruction Structural Specificity Toolkit.

The API is intentionally the foundation layer. CLI, PyPI packaging, and GUI deployment should call this layer instead of duplicating workflow logic.

Public package name

Keep the current import name for compatibility:

import hemispec

The product name can be presented as HemiSpec while the package remains hemispec-toolkit / hemispec until release naming is finalized.

Workflow order

The target product workflow is:

preprocessed GM -> DGN inference -> reconstructed GM -> ANS/RNS -> reliability/specificity validation

The preprocessing contract is documented by:

from hemispec import get_preprocessing_spec

spec = get_preprocessing_spec()
print(spec.script_path)
print(spec.sample_input_dir)

The expected preprocessing script is:

src/hemispec/resources/preprocess/process_single_subject_GM_v2_reorient.sh

It produces *_GM_masked.nii.gz files. Example inputs are in:

examples/input_sample/

Metric API

Use MetricComputeConfig and compute_metrics to compute ANS/RNS maps:

from pathlib import Path
from hemispec import MetricComputeConfig, compute_metrics

result = compute_metrics(
    MetricComputeConfig(
        actual_glob="/data/gm/*_GM_masked.nii.gz",
        reconstructed_glob="/data/recon/*_PRED_LR_full.nii.gz",
        out_dir=Path("/data/hemispec/metrics"),
        gm_thresh=0.15,
        save_subject_maps=True,
    )
)

print(result.n_pairs)
print(result.out_dir)

This writes:

ANS_group_masked_mean.nii.gz
RNS_group_masked_mean.nii.gz
validN.nii.gz
coverage.nii.gz
subject_maps/<subject>_ANS.nii.gz
subject_maps/<subject>_RNS.nii.gz

Validation API

Use ValidationConfig and either validate_specificity or validate_reliability:

from pathlib import Path
from hemispec import ValidationConfig, validate_specificity

run = validate_specificity(
    ValidationConfig(
        maps_dir=Path("/data/hemispec/metrics/subject_maps"),
        out_dir=Path("/data/hemispec/specificity"),
        hemis=("L", "R"),
        session_a="run-01",
        session_b="run-02",
        write_plots=True,
    )
)

df = run.to_dataframe()

Both functions use the same matrix engine:

within similarity   = diagonal scan-A vs scan-B similarity
between similarity  = off-diagonal similarity
specificity index   = mean(within) - mean(between)
top-1 match rate    = percent of rows whose best match is the same subject

validate_reliability is an interpretation alias for the same computation when the inputs are repeat scans.

DGN inference API

The public contract is already defined:

from pathlib import Path
from hemispec import (
    DGNInferenceConfig,
    discover_local_dgn_bundles,
    run_dgn_inference,
)

bundles = discover_local_dgn_bundles()
config = DGNInferenceConfig(
    model=bundles["L_to_R"],
    input_glob="/data/gm/*_GM_masked.nii.gz",
    out_dir=Path("/data/recon"),
    device="cuda",
)

run_dgn_inference(config)

For the common end-to-end workflow, use PipelineRunConfig and run_pipeline:

from pathlib import Path
from hemispec import PipelineRunConfig, run_pipeline

run = run_pipeline(
    PipelineRunConfig(
        inference=config,
        metrics_out_dir=Path("/data/hemispec/ANS_RNS_thr0p15"),
        save_subject_maps=True,
    )
)

print(run.reconstructed_paths)
print(run.metrics.subject_maps_dir)

The local bundle discovery follows the confirmed product-level mapping:

outputs_bi_stable_L = R_to_L = right hemisphere -> generated left hemisphere
outputs_bi_stable_R = L_to_R = left hemisphere  -> generated right hemisphere

See docs/dgn_model_bundle.md for checkpoint locations, crop conventions, and current adapter status.

The API now has a package-owned runtime adapter for trained PyTorch Generator checkpoints. Install the model extra before running real DGN inference:

python -m pip install -e .[model]

train_code/ remains reference-only. Runtime inference uses package-owned modules and trained checkpoints, not training scripts. The public model bundle contract intentionally exposes deployed inference assets rather than training code paths.

Bilateral workflow API

For the release workflow, use BilateralWorkflowConfig and run_bilateral_workflow. This is the API entry point behind the compact GUI standard workflow and the CLI hemispec workflow command.

from pathlib import Path
from hemispec import BilateralWorkflowConfig, run_bilateral_workflow

run = run_bilateral_workflow(
    BilateralWorkflowConfig(
        input_glob="/data/gm/*_GM_masked.nii.gz",
        out_dir=Path("/data/hemispec/full_workflow"),
        device="auto",
        run_classifier=False,  # opt in only when ROI table/classifier validation is needed
        run_trt=False,
    )
)

print(run.hemi_maps_dir)          # <out-dir>/voxel_maps
print(run.subject_summary_csv)    # <out-dir>/tables/subject_metric_summary.csv
print(run.roi_csv)                # optional: present when ROI atlas export is enabled and available
print(run.roi_wide_csv)           # optional: present when ROI atlas export is enabled and available
print(run.combined_maps_dir)      # intermediate path; removed unless keep_intermediate=True

The workflow runs both deployed DGN directions:

L_to_R = left hemisphere -> generated right hemisphere
R_to_L = right hemisphere -> generated left hemisphere

It writes the final user-facing voxel maps directly as hemisphere-specific ANS/RNS maps:

voxel_maps/<subject>_ANS.L.nii.gz
voxel_maps/<subject>_ANS.R.nii.gz
voxel_maps/<subject>_RNS.L.nii.gz
voxel_maps/<subject>_RNS.R.nii.gz

Intermediate DGN reconstructions, one-direction metrics, and merged bilateral maps are stored under intermediate/ only when keep_intermediate=True / --keep-intermediate is used.

When ROI atlas export is enabled and an atlas is available, ROI outputs include both a long table for the saved classifier adapter and a wide table for direct downstream use. If no atlas is provided, voxel-wise ANS/RNS maps remain the primary output and users can extract ROI features with their own downstream methods:

tables/roi_features_bilateral.csv
tables/roi_features_bilateral_wide.csv

The wide table has one row per subject with explicit feature names such as:

ANS.L_roi_1
ANS.R_roi_1
RNS.L_roi_1
RNS.R_roi_1

The subject summary table reports hemisphere means and ANS/RNS finite-voxel whole-brain means:

ANS.L_mean
ANS.R_mean
RNS.L_mean
RNS.R_mean
ANS.whole_brain_mean
RNS.whole_brain_mean

CLI and GUI rule

CLI args -> config dataclass -> API function
GUI fields -> config dataclass -> API function

The CLI follows this rule for models, infer, run, workflow, compute, trt, specificity, and hemi-classify.

The compact GUI now follows the same rule through a single standard workflow surface:

Input GM maps -> Output workspace -> Optional ROI table -> Optional validation -> Run HemiSpec

The GUI intentionally exposes only normal-user decisions. Model roots, devices, thresholds, suffix rules, classifier bundle paths, and TRT regexes remain encapsulated in documented defaults or available through CLI/API for advanced users. New workflow logic should be added to the API first, then exposed through CLI and GUI.