Source code for blissoda.tomo.nxtomo.multiturn

from __future__ import annotations

from typing import Any

SEQUENCES = frozenset({"tomo:multitomo", "tomo:pcotomo"})


[docs] def matches(processor: Any, entry: Any) -> bool: return processor._sequence_name(entry) in SEQUENCES
def _proj(entry: Any) -> dict[str, Any]: return entry.get("technique", {}).get("proj", {}) def _require_proj(entry: Any) -> dict[str, Any]: proj_info = _proj(entry) missing = [name for name in ("proj_n", "nb_turns") if name not in proj_info] if missing: missing_fields = ", ".join(f"technique.proj.{name}" for name in missing) raise ValueError(f"Missing multiturn NXtomo metadata: {missing_fields}") return proj_info def _turns(entry: Any) -> int: proj_info = _require_proj(entry) return max(int(proj_info["nb_turns"]), 1) def _proj_n(entry: Any) -> int: proj_info = _require_proj(entry) return max(int(proj_info["proj_n"]), 1)
[docs] def expanded_subscan_plan(processor: Any, entry: Any) -> list[tuple[str | None, int]]: plan = processor._subscan_plan(entry) turns = _turns(entry) expanded = [] for kind, count in plan: actual_count = int(count) if processor._is_projection_kind(kind): actual_count = _proj_n(entry) * turns expanded.append((kind, actual_count)) return expanded
[docs] def synthetic_translation(processor: Any, entry: Any, alias_name: str): return processor._position_array(entry, alias_name)
[docs] def segment_specs(processor: Any, entry: Any, records: list[dict[str, Any]]): turns = _turns(entry) if turns <= 1: return [{"label": None, "pieces": records}] specs = [] for turn_index in range(turns): pieces = [] for record in records: if not processor._is_projection_kind(record["kind"]): pieces.append(record) continue frames_per_turn = _proj_n(entry) start = record["frame_start"] + turn_index * frames_per_turn stop = start + frames_per_turn pieces.append(processor._slice_record(record, start, stop)) specs.append({"label": f"turn_{turn_index + 1:03d}", "pieces": pieces}) return specs