ROI configuration and output naming for flex-search.
Provides helper functions for directory naming, human-readable labelling,
SimNIBS log parsing, and ROI setup on TesFlexOptimization objects.
Public API
generate_run_dirname
Create a datetime-stamped directory name for a run.
generate_label
Build a human-readable label string for a flex-search run.
parse_optimization_output
Extract the goal-function value from a SimNIBS log line.
configure_roi
Set up ROI(s) on a SimNIBS optimization object.
See Also
tit.opt.flex.flex : Main flex-search orchestrator.
generate_run_dirname
generate_run_dirname(base_path: str) -> str
Generate a datetime-stamped directory name for a flex-search run.
Format is YYYYMMDD_HHMMSS. When a collision exists, _1,
_2, etc. are appended.
Parameters
base_path : str
Parent directory (e.g. flex-search/) to check for
collisions.
Returns
str
Directory name string (not the full path).
Source code in tit/opt/flex/utils.py
| def generate_run_dirname(base_path: str) -> str:
"""Generate a datetime-stamped directory name for a flex-search run.
Format is ``YYYYMMDD_HHMMSS``. When a collision exists, ``_1``,
``_2``, etc. are appended.
Parameters
----------
base_path : str
Parent directory (e.g. ``flex-search/``) to check for
collisions.
Returns
-------
str
Directory name string (not the full path).
"""
from datetime import datetime
name = datetime.now().strftime("%Y%m%d_%H%M%S")
if not os.path.exists(os.path.join(base_path, name)):
return name
suffix = 1
while os.path.exists(os.path.join(base_path, f"{name}_{suffix}")):
suffix += 1
return f"{name}_{suffix}"
|
generate_label
generate_label(config, pareto: bool = False) -> str
Build a human-readable label for a flex-search run.
The label is stored in flex_meta.json for GUI display and is
not used for folder naming or machine parsing.
Parameters
config : FlexConfig
Flex-search configuration instance.
pareto : bool, optional
When True the goal component is replaced by "pareto".
Returns
str
Label string, e.g. "mean_maxTI_sphere(-42,-20,55)r10".
Source code in tit/opt/flex/utils.py
| def generate_label(config, pareto: bool = False) -> str:
"""Build a human-readable label for a flex-search run.
The label is stored in ``flex_meta.json`` for GUI display and is
**not** used for folder naming or machine parsing.
Parameters
----------
config : FlexConfig
Flex-search configuration instance.
pareto : bool, optional
When *True* the goal component is replaced by ``"pareto"``.
Returns
-------
str
Label string, e.g. ``"mean_maxTI_sphere(-42,-20,55)r10"``.
"""
postproc_short = {
"max_TI": "maxTI",
"dir_TI_normal": "normalTI",
"dir_TI_tangential": "tangentialTI",
}
pp = postproc_short.get(
(
config.postproc.value
if hasattr(config.postproc, "value")
else str(config.postproc)
),
str(config.postproc),
)
goal_str = (
"pareto"
if pareto
else (config.goal.value if hasattr(config.goal, "value") else str(config.goal))
)
roi = config.roi
if isinstance(roi, FlexConfig.SphericalROI):
x = int(roi.x) if roi.x == int(roi.x) else roi.x
y = int(roi.y) if roi.y == int(roi.y) else roi.y
z = int(roi.z) if roi.z == int(roi.z) else roi.z
r = int(roi.radius) if roi.radius == int(roi.radius) else roi.radius
roi_str = f"sphere({x},{y},{z})r{r}"
elif isinstance(roi, FlexConfig.AtlasROI):
hemi = roi.hemisphere
atlas = (
os.path.basename(roi.atlas_path).replace(".annot", "").split(".")[-1]
if roi.atlas_path
else "atlas"
)
roi_str = f"{hemi}-{atlas}-{roi.label}"
elif isinstance(roi, FlexConfig.SubcorticalROI):
atlas = os.path.basename(roi.atlas_path) if roi.atlas_path else "volume"
for ext in (".nii.gz", ".nii", ".mgz"):
if atlas.endswith(ext):
atlas = atlas[: -len(ext)]
break
roi_str = f"subcortical-{atlas}-{roi.label}"
else:
roi_str = "unknown"
return f"{goal_str}_{pp}_{roi_str}"
|
parse_optimization_output
parse_optimization_output(line: str) -> float | None
Extract the goal-function value from a SimNIBS log line.
Recognises three patterns:
"Final goal function value: -42.123"
"Goal function value<anything>: -42.123"
- Table row with a
max_TI column (optionally in scientific
notation)
Parameters
line : str
A single line of SimNIBS stdout / stderr.
Returns
float or None
The extracted function value, or None when the line does not
match any known pattern.
Source code in tit/opt/flex/utils.py
| def parse_optimization_output(line: str) -> float | None:
"""Extract the goal-function value from a SimNIBS log line.
Recognises three patterns:
* ``"Final goal function value: -42.123"``
* ``"Goal function value<anything>: -42.123"``
* Table row with a ``max_TI`` column (optionally in scientific
notation)
Parameters
----------
line : str
A single line of SimNIBS stdout / stderr.
Returns
-------
float or None
The extracted function value, or *None* when the line does not
match any known pattern.
"""
import re
# Primary: "Final goal function value: <number>"
m = re.search(
r"Final goal function value:\s*([+-]?[\d.eE+-]+)", line, re.IGNORECASE
)
if m:
return float(m.group(1))
# Secondary: "Goal function value<anything>: <number>"
m = re.search(r"Goal function value[^:]*:\s*([+-]?[\d.eE+-]+)", line, re.IGNORECASE)
if m:
return float(m.group(1))
# Table row: "|max_TI | 0.025" or "max_TI | 0.025e-03"
m = re.search(r"\|?\s*max_TI\s+\|\s*([\d.+-]+)(?:e([+-]?\d+))?", line)
if m:
base = float(m.group(1))
exp = int(m.group(2)) if m.group(2) else 0
val = base * (10**exp)
if val > 0:
return val
return None
|
Configure ROI(s) on a SimNIBS optimization object.
Delegates to the appropriate private helper based on the ROI type
stored in config.roi (spherical, atlas, or subcortical).
opt : simnibs.optimization.TesFlexOptimization
SimNIBS optimization object to configure.
config : FlexConfig
Flex-search configuration containing the ROI specification.
ValueError
If the ROI type is not recognised.
Source code in tit/opt/flex/utils.py
| def configure_roi(opt, config: FlexConfig) -> None:
"""Configure ROI(s) on a SimNIBS optimization object.
Delegates to the appropriate private helper based on the ROI type
stored in ``config.roi`` (spherical, atlas, or subcortical).
Parameters
----------
opt : simnibs.optimization.TesFlexOptimization
SimNIBS optimization object to configure.
config : FlexConfig
Flex-search configuration containing the ROI specification.
Raises
------
ValueError
If the ROI type is not recognised.
"""
if isinstance(config.roi, FlexConfig.SphericalROI):
_configure_spherical_roi(opt, config)
elif isinstance(config.roi, FlexConfig.AtlasROI):
_configure_atlas_roi(opt, config)
elif isinstance(config.roi, FlexConfig.SubcorticalROI):
_configure_subcortical_roi(opt, config)
else:
raise ValueError(f"Unknown ROI type: {type(config.roi)}")
|