Usage Guide

Quick Start

Use SimindPythonConnector when you want direct Python control of SIMIND inputs/outputs without any reconstruction-package dependency.

The Python package does not bundle SIMIND. Before calling run(), make sure the SIMIND executable is available as simind on PATH; see Installation.

import numpy as np
from simind_python_connector import SimindPythonConnector
from simind_python_connector.configs import get

source = np.zeros((32, 32, 32), dtype=np.float32)  # z, y, x
source[12:20, 12:20, 12:20] = 1.0
mu_map = np.zeros_like(source)
mu_map[source > 0] = 0.15

connector = SimindPythonConnector(
    config_source=get("Example.yaml"),
    output_dir="output/basic",
    output_prefix="case01",
    quantization_scale=0.05,
)

connector.configure_voxel_phantom(
    source=source,
    mu_map=mu_map,
    voxel_size_mm=4.0,
)
connector.set_energy_windows([126], [154], [0])
connector.add_runtime_switch("FI", "tc99m")
connector.add_runtime_switch("CC", "ma-lehr")
connector.add_runtime_switch("NN", 1)
connector.add_runtime_switch("RR", 12345)

outputs = connector.run()
total = outputs["tot_w1"].projection
print(total.shape)

Adaptor Workflows

Use adaptors when you want connector-managed SIMIND execution plus native objects for a target reconstruction package.

STIR adaptor

from simind_python_connector import StirSimindAdaptor
from simind_python_connector.configs import get

adaptor = StirSimindAdaptor(
    config_source=get("Example.yaml"),
    output_dir="output/stir_adaptor",
    output_prefix="stir_case01",
)
adaptor.set_source(stir_source)
adaptor.set_mu_map(stir_mu_map)
adaptor.set_energy_windows([75], [225], [0])
adaptor.add_runtime_switch("FI", "y90_tissue")
adaptor.add_runtime_switch("CC", "ma-megp")
adaptor.add_runtime_switch("RR", 12345)

outputs = adaptor.run()
stir_total = outputs["tot_w1"]

SIRF adaptor

from simind_python_connector import SirfSimindAdaptor
from simind_python_connector.configs import get

adaptor = SirfSimindAdaptor(
    config_source=get("Example.yaml"),
    output_dir="output/sirf_adaptor",
    output_prefix="sirf_case01",
)
adaptor.set_source(sirf_source)
adaptor.set_mu_map(sirf_mu_map)
adaptor.set_energy_windows([75], [225], [0])
adaptor.add_runtime_switch("FI", "y90_tissue")
adaptor.add_runtime_switch("CC", "ma-megp")
adaptor.add_runtime_switch("RR", 12345)

outputs = adaptor.run()
sirf_total = outputs["tot_w1"]

PyTomography adaptor

The adaptor returns PyTomography-compatible tensors and output headers. Build the system matrix directly with PyTomography APIs.

import torch
from pytomography.io.SPECT import simind as pytomo_simind
from pytomography.projectors.SPECT import SPECTSystemMatrix

from simind_python_connector import PyTomographySimindAdaptor
from simind_python_connector.configs import get

adaptor = PyTomographySimindAdaptor(
    config_source=get("Example.yaml"),
    output_dir="output/pytomo_adaptor",
    output_prefix="pytomo_case01",
)
adaptor.set_source(source_tensor_xyz)
adaptor.set_mu_map(mu_tensor_xyz)
adaptor.set_energy_windows([75], [225], [0])
adaptor.add_runtime_switch("FI", "y90_tissue")
adaptor.add_runtime_switch("CC", "ma-megp")
adaptor.add_runtime_switch("RR", 12345)
adaptor.run()

projections = adaptor.get_total_output(window=1).to(dtype=torch.float32)
header = adaptor.get_output_header_path("tot_w1")
object_meta, proj_meta = pytomo_simind.get_metadata(str(header))

system_matrix = SPECTSystemMatrix(
    obj2obj_transforms=[],
    proj2proj_transforms=[],
    object_meta=object_meta,
    proj_meta=proj_meta,
)

Density Conversion

The package includes HU-to-density conversion utilities, including the Schneider2000 model.

import numpy as np
from simind_python_connector.converters.attenuation import hu_to_density_schneider

hu_image = np.array([[-1000, 0, 500], [800, 1200, 2000]])
density_map = hu_to_density_schneider(hu_image)