def candidate_detail(pm, subject: str, kind: str, run: str, candidate_id: str) -> dict:
"""Resolve a saved candidate into the standard editable simulation config."""
from tit.config_io import serialize_config
from tit.sim.config import Montage, SimulationConfig
root = Path(pm.project_dir)
directory = run_directory(pm, subject, kind, run)
rows = _rows(root, directory, subject, kind)
row = next((r for r in rows if r["id"] == candidate_id), None)
if row is None:
raise FileNotFoundError("Candidate not found.")
name = (
"candidate_"
+ hashlib.sha256(f"{kind}/{run}/{candidate_id}".encode()).hexdigest()[:16]
)
provenance = {
"kind": kind,
"run": run,
"candidate_id": candidate_id,
"metrics": "optimization estimates",
}
config = row["_manifest"].get("config", {})
geometry = None
if kind == "flex":
identity = row["_manifest"].get("head_mesh_identity")
if identity is None:
row["replay_note"] = (
"Head mesh identity was not recorded; unchanged mesh physics cannot be verified for this history."
)
provenance["head_mesh_identity"] = "unavailable in legacy history"
else:
from tit.mesh_identity import verify_subject_mesh
if not isinstance(identity, dict) or not isinstance(
identity.get("path"), str
):
raise ValueError("Candidate head mesh identity is malformed.")
verify_subject_mesh(pm, subject, identity.get("sha256"))
provenance["head_mesh_sha256"] = identity["sha256"]
provenance["head_mesh_source_path"] = identity["path"]
geometry = _geometries(root, [row])[candidate_id]
electrodes = []
currents = []
for channel in geometry["electrodes"]:
if len(channel) != 2:
raise ValueError(
"Simulation replay currently requires two electrodes per carrier."
)
ordered = sorted(channel, key=lambda e: -e["current_A"])
positive, negative = (float(e["current_A"]) for e in ordered)
if not (
math.isfinite(positive)
and math.isfinite(negative)
and positive > 0 > negative
and abs(positive + negative) < 1e-10
):
raise ValueError(
"Candidate carrier currents are invalid or unbalanced."
)
currents.append(positive * 1000)
electrodes.extend(ordered)
if len(currents) != 2:
raise ValueError("Flex replay requires exactly two carriers.")
spec = electrodes[0]
if any(
any(cell[key] != spec[key] for key in ("shape", "dimensions", "thickness"))
for cell in electrodes
):
raise ValueError(
"Mixed electrode geometries cannot be replayed in the standard Simulator."
)
poses = [cell["posmat"] for cell in electrodes]
positions = [[pose[i][3] for i in range(3)] for pose in poses]
montage = Montage(
name,
Montage.Mode.FLEX_FREE,
[positions[i : i + 2] for i in range(0, len(positions), 2)],
electrode_poses=poses,
provenance=provenance,
)
simulation = SimulationConfig(
subject,
[montage],
conductivity=config.get("anisotropy_type", "scalar"),
intensities=currents,
electrode_shape=spec["shape"],
electrode_dimensions=spec["dimensions"],
gel_thickness=spec["thickness"][0],
rubber_thickness=spec["thickness"][1],
aniso_maxratio=config.get("aniso_maxratio", 10),
aniso_maxcond=config.get("aniso_maxcond", 2),
)
else:
if not all(value is not None and value > 0 for value in row["currents_mA"]):
raise ValueError("Saved montage does not contain usable carrier currents.")
montage = Montage(
name,
Montage.Mode.NET,
row["pairs"],
eeg_net=row["eeg_net"],
provenance=provenance,
)
provenance["geometry"] = "Simulator defaults; not recorded in Ex history"
simulation = SimulationConfig(
subject, [montage], intensities=row["currents_mA"]
)
return {
"candidate": _public(row, geometry),
"simulation_config": serialize_config(simulation),
}