Skip to content

skin_visualization

tit.opt.flex.skin_visualization

Valid-skin-region visualization for flex-search outputs.

create_valid_skin_region_visualization

create_valid_skin_region_visualization(config: FlexConfig, output_folder: str, logger) -> None

Write the valid-skin-region PNG for a flex-search run.

Source code in tit/opt/flex/skin_visualization.py
def create_valid_skin_region_visualization(
    config: FlexConfig,
    output_folder: str,
    logger,
) -> None:
    """Write the valid-skin-region PNG for a flex-search run."""
    try:
        from simnibs.mesh_tools import mesh_io
        from simnibs.utils.file_finder import Templates
        from simnibs.utils.transformations import (
            create_new_connectivity_list_point_mask,
            subject2mni_coords,
        )
        from tit.paths import get_path_manager
    except ImportError as exc:
        logger.warning(f"Could not import SimNIBS skin visualization dependencies: {exc}")
        return

    pm = get_path_manager()
    m2m = Path(pm.m2m(config.subject_id))
    mesh_path = m2m / f"{m2m.name.removeprefix('m2m_')}.msh"
    if not mesh_path.exists():
        candidates = list(m2m.glob("*.msh"))
        if not candidates:
            logger.warning(f"Could not create skin visualization: no .msh under {m2m}")
            return
        mesh_path = candidates[0]

    try:
        mesh = mesh_io.read_msh(str(mesh_path))
        mesh.fn = str(mesh_path)
        mesh_relabel = mesh.relabel_internal_air()
        skin_surface = mesh_relabel.crop_mesh(tags=1005)
        points = skin_surface.nodes.node_coord.copy()
        con = skin_surface.elm.node_number_list[:, :3] - 1

        raw_mask = _skin_mask_from_mni_volume(
            skin_surface,
            mesh_relabel,
            Templates().mni_volume_upper_head_mask,
            subject2mni_coords,
        )
        mask = _largest_component_mask(
            points,
            con,
            raw_mask,
            create_new_connectivity_list_point_mask,
        )
        if config.skin_region_margin_mm:
            mask = _apply_margin(
                points,
                con,
                mask,
                float(config.skin_region_margin_mm),
                create_new_connectivity_list_point_mask,
            )

        guard_mask = None
        guard_boundary_mask = None
        plot_points = points
        fiducial_frame = None
        if config.avoid_landmark_regions and config.skin_region_margin_mm > 0:
            fiducials = _read_fiducials(m2m)
            fiducial_frame = _make_fiducial_frame(fiducials)
            guard_mask = _landmark_guard_mask(points, fiducials, fiducial_frame)
            mask = _largest_component_mask(
                points,
                con,
                mask & ~guard_mask,
                create_new_connectivity_list_point_mask,
            )
            guard_boundary_mask = np.zeros(points.shape[0], dtype=bool)
            guard_boundary_mask[_boundary_nodes(con, guard_mask, side=True)] = True
            plot_points = _local_coords(points, *fiducial_frame)

        electrodes = _load_electrodes(
            config.skin_visualization_net,
            points,
            plot_points,
            mask,
            fiducial_frame,
            logger,
        )

        output_path = Path(output_folder)
        output_path.mkdir(parents=True, exist_ok=True)
        png_path = output_path / "valid_skin_region.png"
        _plot_skin_region(
            plot_points=plot_points,
            mask=mask,
            out_png=png_path,
            guard_mask=guard_mask,
            guard_boundary_mask=guard_boundary_mask,
            electrodes=electrodes,
        )
        logger.info(f"Valid skin region visualization saved to: {png_path}")
    except Exception as exc:
        logger.warning(f"Could not create valid skin region visualization: {exc}")