Skip to content

flex_search

Flex-search optimization report generator for TI-Toolbox.

This module provides a report generator for electrode placement optimization results from the flex-search algorithm.

FlexSearchReportGenerator

FlexSearchReportGenerator(project_dir: str | Path, subject_id: str, session_id: str | None = None)

Bases: BaseReportGenerator

Report generator for flex-search optimization results.

Creates comprehensive HTML reports including: - Optimization configuration - Target ROI specification - Search results and rankings - Best solution details - Visualization of optimal electrode placement

Initialize the flex-search report generator.

Parameters:

Name Type Description Default
project_dir str | Path

Path to the project directory

required
subject_id str

BIDS subject ID

required
session_id str | None

Optional session identifier

None
Source code in tit/reporting/generators/flex_search.py
def __init__(
    self,
    project_dir: str | Path,
    subject_id: str,
    session_id: str | None = None,
):
    """
    Initialize the flex-search report generator.

    Args:
        project_dir: Path to the project directory
        subject_id: BIDS subject ID
        session_id: Optional session identifier
    """
    super().__init__(
        project_dir=project_dir,
        subject_id=subject_id,
        session_id=session_id,
        report_type="flex-search",
    )

    # Flex-search specific data
    self.config: dict[str, Any] = {}
    self.roi_info: dict[str, Any] = {}
    self.search_results: list[dict[str, Any]] = []
    self.best_solution: dict[str, Any] | None = None
    self.optimization_metrics: dict[str, Any] = {}

set_configuration

set_configuration(electrode_net: str | None = None, optimization_target: str | None = None, n_candidates: int = 100, selection_method: str = 'best', intensity_ch1: float = 1.0, intensity_ch2: float = 1.0, **kwargs) -> None

Set the optimization configuration.

Parameters:

Name Type Description Default
electrode_net str | None

EEG net used

None
optimization_target str | None

Target metric to optimize

None
n_candidates int

Number of candidate solutions evaluated

100
selection_method str

Method for selecting best solution

'best'
intensity_ch1 float

Channel 1 intensity

1.0
intensity_ch2 float

Channel 2 intensity

1.0
**kwargs

Additional configuration

{}
Source code in tit/reporting/generators/flex_search.py
def set_configuration(
    self,
    electrode_net: str | None = None,
    optimization_target: str | None = None,
    n_candidates: int = 100,
    selection_method: str = "best",
    intensity_ch1: float = 1.0,
    intensity_ch2: float = 1.0,
    **kwargs,
) -> None:
    """
    Set the optimization configuration.

    Args:
        electrode_net: EEG net used
        optimization_target: Target metric to optimize
        n_candidates: Number of candidate solutions evaluated
        selection_method: Method for selecting best solution
        intensity_ch1: Channel 1 intensity
        intensity_ch2: Channel 2 intensity
        **kwargs: Additional configuration
    """
    self.config = {
        "electrode_net": electrode_net,
        "optimization_target": optimization_target,
        "n_candidates": n_candidates,
        "selection_method": selection_method,
        "intensity_ch1": intensity_ch1,
        "intensity_ch2": intensity_ch2,
        **kwargs,
    }

set_roi_info

set_roi_info(roi_name: str, roi_type: str = 'mask', coordinates: list[float] | None = None, radius: float | None = None, volume_mm3: float | None = None, n_voxels: int | None = None, **kwargs) -> None

Set the target ROI information.

Parameters:

Name Type Description Default
roi_name str

Name of the target ROI

required
roi_type str

Type of ROI (mask, sphere, coordinates)

'mask'
coordinates list[float] | None

Center coordinates (if applicable)

None
radius float | None

Radius in mm (if sphere)

None
volume_mm3 float | None

ROI volume in mm³

None
n_voxels int | None

Number of voxels in ROI

None
**kwargs

Additional ROI info

{}
Source code in tit/reporting/generators/flex_search.py
def set_roi_info(
    self,
    roi_name: str,
    roi_type: str = "mask",
    coordinates: list[float] | None = None,
    radius: float | None = None,
    volume_mm3: float | None = None,
    n_voxels: int | None = None,
    **kwargs,
) -> None:
    """
    Set the target ROI information.

    Args:
        roi_name: Name of the target ROI
        roi_type: Type of ROI (mask, sphere, coordinates)
        coordinates: Center coordinates (if applicable)
        radius: Radius in mm (if sphere)
        volume_mm3: ROI volume in mm³
        n_voxels: Number of voxels in ROI
        **kwargs: Additional ROI info
    """
    self.roi_info = {
        "name": roi_name,
        "type": roi_type,
        "coordinates": coordinates,
        "radius": radius,
        "volume_mm3": volume_mm3,
        "n_voxels": n_voxels,
        **kwargs,
    }

add_search_result

add_search_result(rank: int, electrode_1a: str, electrode_1b: str, electrode_2a: str, electrode_2b: str, score: float, mean_field_roi: float | None = None, max_field_roi: float | None = None, focality: float | None = None, **metrics) -> None

Add a search result entry.

Parameters:

Name Type Description Default
rank int

Ranking of this solution

required
electrode_1a str

First electrode of pair 1

required
electrode_1b str

Second electrode of pair 1

required
electrode_2a str

First electrode of pair 2

required
electrode_2b str

Second electrode of pair 2

required
score float

Optimization score

required
mean_field_roi float | None

Mean field in ROI (V/m)

None
max_field_roi float | None

Max field in ROI (V/m)

None
focality float | None

Focality metric

None
**metrics

Additional metrics

{}
Source code in tit/reporting/generators/flex_search.py
def add_search_result(
    self,
    rank: int,
    electrode_1a: str,
    electrode_1b: str,
    electrode_2a: str,
    electrode_2b: str,
    score: float,
    mean_field_roi: float | None = None,
    max_field_roi: float | None = None,
    focality: float | None = None,
    **metrics,
) -> None:
    """
    Add a search result entry.

    Args:
        rank: Ranking of this solution
        electrode_1a: First electrode of pair 1
        electrode_1b: Second electrode of pair 1
        electrode_2a: First electrode of pair 2
        electrode_2b: Second electrode of pair 2
        score: Optimization score
        mean_field_roi: Mean field in ROI (V/m)
        max_field_roi: Max field in ROI (V/m)
        focality: Focality metric
        **metrics: Additional metrics
    """
    self.search_results.append(
        {
            "rank": rank,
            "electrode_1a": electrode_1a,
            "electrode_1b": electrode_1b,
            "electrode_2a": electrode_2a,
            "electrode_2b": electrode_2b,
            "pair_1": f"{electrode_1a}-{electrode_1b}",
            "pair_2": f"{electrode_2a}-{electrode_2b}",
            "score": score,
            "mean_field_roi": mean_field_roi,
            "max_field_roi": max_field_roi,
            "focality": focality,
            **metrics,
        }
    )

set_best_solution

set_best_solution(electrode_pairs: list[dict[str, str]], score: float, metrics: dict[str, Any], montage_image_base64: str | None = None, field_map_base64: str | None = None, electrode_coordinates: list[list[float]] | None = None, channel_array_indices: list[list[int]] | None = None) -> None

Set the best (selected) solution.

Parameters:

Name Type Description Default
electrode_pairs list[dict[str, str]]

List of electrode pair specs

required
score float

Final optimization score

required
metrics dict[str, Any]

Solution metrics

required
montage_image_base64 str | None

Base64 montage visualization

None
field_map_base64 str | None

Base64 field map visualization

None
Source code in tit/reporting/generators/flex_search.py
def set_best_solution(
    self,
    electrode_pairs: list[dict[str, str]],
    score: float,
    metrics: dict[str, Any],
    montage_image_base64: str | None = None,
    field_map_base64: str | None = None,
    electrode_coordinates: list[list[float]] | None = None,
    channel_array_indices: list[list[int]] | None = None,
) -> None:
    """
    Set the best (selected) solution.

    Args:
        electrode_pairs: List of electrode pair specs
        score: Final optimization score
        metrics: Solution metrics
        montage_image_base64: Base64 montage visualization
        field_map_base64: Base64 field map visualization
    """
    self.best_solution = {
        "electrode_pairs": electrode_pairs,
        "score": score,
        "metrics": metrics,
        "montage_image_base64": montage_image_base64,
        "field_map_base64": field_map_base64,
        "electrode_coordinates": electrode_coordinates,
        "channel_array_indices": channel_array_indices,
    }

populate_from_data

populate_from_data(data: dict[str, Any]) -> None

Populate the report from a data dictionary.

Parameters:

Name Type Description Default
data dict[str, Any]

Dictionary containing all optimization data

required
Source code in tit/reporting/generators/flex_search.py
def populate_from_data(self, data: dict[str, Any]) -> None:
    """
    Populate the report from a data dictionary.

    Args:
        data: Dictionary containing all optimization data
    """
    # Configuration
    if "config" in data:
        self.config = data["config"]

    # ROI info
    if "roi" in data:
        self.roi_info = data["roi"]

    # Search results
    if "results" in data:
        for i, result in enumerate(data["results"]):
            self.add_search_result(rank=i + 1, **result)

    # Best solution
    if "best_solution" in data:
        self.best_solution = data["best_solution"]

    # Optimization metrics
    if "metrics" in data:
        self.optimization_metrics = data["metrics"]

load_from_output_dir

load_from_output_dir(output_dir: str | Path) -> None

Load optimization data from an output directory.

Parameters:

Name Type Description Default
output_dir str | Path

Path to the flex-search output directory

required
Source code in tit/reporting/generators/flex_search.py
def load_from_output_dir(self, output_dir: str | Path) -> None:
    """
    Load optimization data from an output directory.

    Args:
        output_dir: Path to the flex-search output directory
    """
    output_dir = Path(output_dir)

    # Try to load results JSON
    results_file = output_dir / "optimization_results.json"
    if results_file.exists():
        with open(results_file) as f:
            data = json.load(f)
            self.populate_from_data(data)

    # Try to load configuration
    config_file = output_dir / "config.json"
    if config_file.exists():
        with open(config_file) as f:
            self.config = json.load(f)

create_flex_search_report

create_flex_search_report(project_dir: str | Path, subject_id: str, data: dict[str, Any], output_path: str | Path | None = None) -> Path

Convenience function to create a flex-search report.

Parameters:

Name Type Description Default
project_dir str | Path

Path to project directory

required
subject_id str

BIDS subject ID

required
data dict[str, Any]

Dictionary containing optimization data

required
output_path str | Path | None

Optional custom output path

None

Returns:

Type Description
Path

Path to the generated report

Source code in tit/reporting/generators/flex_search.py
def create_flex_search_report(
    project_dir: str | Path,
    subject_id: str,
    data: dict[str, Any],
    output_path: str | Path | None = None,
) -> Path:
    """
    Convenience function to create a flex-search report.

    Args:
        project_dir: Path to project directory
        subject_id: BIDS subject ID
        data: Dictionary containing optimization data
        output_path: Optional custom output path

    Returns:
        Path to the generated report
    """
    generator = FlexSearchReportGenerator(
        project_dir=project_dir,
        subject_id=subject_id,
    )
    generator.populate_from_data(data)
    return generator.generate(output_path)