Skip to content

mesh2nii

tit.tools.mesh2nii

Mesh-to-NIfTI conversion using the SimNIBS Python API.

Wraps simnibs.transformations so that the simulation pipeline can convert .msh meshes to volumetric NIfTI files without shelling out to bash scripts.

Public API

msh_to_nifti Convert a single mesh to subject-space NIfTI. msh_to_mni Convert a single mesh to MNI-space NIfTI. convert_mesh_dir Batch-convert every .msh file in a directory.

See Also

tit.tools.nifti_to_mesh : Inverse operation (NIfTI to surface mesh). tit.tools.field_extract : Extract tissue sub-meshes before conversion.

msh_to_nifti

msh_to_nifti(mesh_path: str, m2m_dir: str, output_path: str, fields: list[str] | None = None) -> None

Convert a mesh file to subject-space NIfTI.

Parameters

mesh_path : str Path to the .msh file. m2m_dir : str Path to the m2m_{subject} directory (used as reference grid). output_path : str Output file prefix. SimNIBS appends the field name (e.g. prefix_magnE.nii.gz). fields : list[str] | None If given, only these fields are written. Otherwise all fields in the mesh are converted.

Source code in tit/tools/mesh2nii.py
def msh_to_nifti(
    mesh_path: str,
    m2m_dir: str,
    output_path: str,
    fields: list[str] | None = None,
) -> None:
    """Convert a mesh file to subject-space NIfTI.

    Parameters
    ----------
    mesh_path : str
        Path to the ``.msh`` file.
    m2m_dir : str
        Path to the ``m2m_{subject}`` directory (used as reference grid).
    output_path : str
        Output file prefix.  SimNIBS appends the field name
        (e.g. ``prefix_magnE.nii.gz``).
    fields : list[str] | None
        If given, only these fields are written.  Otherwise all fields in the
        mesh are converted.
    """
    mesh = mesh_io.read_msh(mesh_path)
    if fields:
        mesh = _filter_mesh_fields(mesh, fields)
    transformations.interpolate_to_volume(mesh, m2m_dir, output_path)

msh_to_mni

msh_to_mni(mesh_path: str, m2m_dir: str, output_path: str, fields: list[str] | None = None) -> None

Convert a mesh file to MNI-space NIfTI.

Parameters

mesh_path : str Path to the .msh file. m2m_dir : str Path to the m2m_{subject} directory. output_path : str Output file prefix. SimNIBS appends the field name (e.g. prefix_magnE.nii.gz). fields : list[str] | None If given, only these fields are written.

Source code in tit/tools/mesh2nii.py
def msh_to_mni(
    mesh_path: str,
    m2m_dir: str,
    output_path: str,
    fields: list[str] | None = None,
) -> None:
    """Convert a mesh file to MNI-space NIfTI.

    Parameters
    ----------
    mesh_path : str
        Path to the ``.msh`` file.
    m2m_dir : str
        Path to the ``m2m_{subject}`` directory.
    output_path : str
        Output file prefix.  SimNIBS appends the field name
        (e.g. ``prefix_magnE.nii.gz``).
    fields : list[str] | None
        If given, only these fields are written.
    """
    if fields:
        mesh = mesh_io.read_msh(mesh_path)
        mesh = _filter_mesh_fields(mesh, fields)
        mesh_path = _write_temp_mesh(mesh)
    transformations.warp_volume(mesh_path, m2m_dir, output_path)

convert_mesh_dir

convert_mesh_dir(mesh_dir: str, output_dir: str, m2m_dir: str, fields: list[str] | None = None, skip_patterns: list[str] | None = None) -> None

Batch-convert every .msh file in mesh_dir to NIfTI.

For each mesh two NIfTI sets are produced:

  • {basename}_subject_{field}.nii.gz – subject space
  • {basename}_MNI_{field}.nii.gz – MNI space
Parameters

mesh_dir : str Directory containing .msh files. output_dir : str Where the NIfTI files are written. m2m_dir : str Path to the m2m_{subject} directory. fields : list[str] | None If given, only these fields are converted. skip_patterns : list[str] | None Basenames containing any of these substrings are skipped. Defaults to ["normal"] (surface-only meshes have no volume elements).

Source code in tit/tools/mesh2nii.py
def convert_mesh_dir(
    mesh_dir: str,
    output_dir: str,
    m2m_dir: str,
    fields: list[str] | None = None,
    skip_patterns: list[str] | None = None,
) -> None:
    """Batch-convert every ``.msh`` file in *mesh_dir* to NIfTI.

    For each mesh two NIfTI sets are produced:

    * ``{basename}_subject_{field}.nii.gz``  – subject space
    * ``{basename}_MNI_{field}.nii.gz``      – MNI space

    Parameters
    ----------
    mesh_dir : str
        Directory containing ``.msh`` files.
    output_dir : str
        Where the NIfTI files are written.
    m2m_dir : str
        Path to the ``m2m_{subject}`` directory.
    fields : list[str] | None
        If given, only these fields are converted.
    skip_patterns : list[str] | None
        Basenames containing any of these substrings are skipped.
        Defaults to ``["normal"]`` (surface-only meshes have no volume
        elements).
    """
    if skip_patterns is None:
        skip_patterns = ["normal"]

    os.makedirs(output_dir, exist_ok=True)

    msh_files = sorted(f for f in os.listdir(mesh_dir) if f.endswith(".msh"))
    if not msh_files:
        logger.warning("No .msh files found in %s", mesh_dir)
        return

    for fname in msh_files:
        base = os.path.splitext(fname)[0]
        if any(p in base for p in skip_patterns):
            logger.debug("Skipping surface mesh: %s", fname)
            continue

        mesh_path = os.path.join(mesh_dir, fname)
        mesh = mesh_io.read_msh(mesh_path)

        # When filtering fields, write a temp mesh for warp_volume
        # (it only accepts file paths, not in-memory mesh objects).
        warp_path = mesh_path
        if fields:
            mesh = _filter_mesh_fields(mesh, fields)
            warp_path = _write_temp_mesh(mesh)

        subject_prefix = os.path.join(output_dir, f"{base}_subject")
        mni_prefix = os.path.join(output_dir, f"{base}_MNI")

        logger.debug("Converting %s → subject space", fname)
        transformations.interpolate_to_volume(mesh, m2m_dir, subject_prefix)

        logger.debug("Converting %s → MNI space", fname)
        transformations.warp_volume(warp_path, m2m_dir, mni_prefix)

        if warp_path != mesh_path:
            os.unlink(warp_path)

    logger.info("NIfTI conversion complete: %s", output_dir)