Source code for pytomography.io.PET.prd.protocols

# This file was generated by the "yardl" tool. DO NOT EDIT.

# pyright: reportUnusedImport=false

import abc
import collections.abc
import datetime
import typing

import numpy as np
import numpy.typing as npt

from .types import *
from .yardl_types import ProtocolError
from . import yardl_types as yardl

[docs]class PrdExperimentWriterBase(abc.ABC): """Abstract writer for the PrdExperiment protocol.""" def __init__(self) -> None: self._state = 0
[docs] schema = r"""{"protocol":{"name":"PrdExperiment","sequence":[{"name":"header","type":"Prd.Header"},{"name":"timeBlocks","type":{"stream":{"items":"Prd.TimeBlock"}}}]},"types":[{"name":"CoincidenceEvent","fields":[{"name":"detector1Id","type":"uint32"},{"name":"detector2Id","type":"uint32"},{"name":"tofIdx","type":"uint32"},{"name":"energy1Idx","type":"uint32"},{"name":"energy2Idx","type":"uint32"}]},{"name":"Detector","fields":[{"name":"id","type":"uint32"},{"name":"x","type":"float32"},{"name":"y","type":"float32"},{"name":"z","type":"float32"}]},{"name":"ExamInformation","fields":[{"name":"subject","type":"Prd.Subject"},{"name":"institution","type":"Prd.Institution"},{"name":"protocol","type":[null,"string"]},{"name":"startOfAcquisition","type":[null,"datetime"]}]},{"name":"Header","fields":[{"name":"scanner","type":"Prd.ScannerInformation"},{"name":"exam","type":[null,"Prd.ExamInformation"]}]},{"name":"Institution","fields":[{"name":"name","type":"string"},{"name":"address","type":"string"}]},{"name":"ScannerInformation","fields":[{"name":"modelName","type":[null,"string"]},{"name":"detectors","type":{"vector":{"items":"Prd.Detector"}}},{"name":"tofBinEdges","type":{"array":{"items":"float32","dimensions":1}}},{"name":"tofResolution","type":"float32"},{"name":"energyBinEdges","type":{"array":{"items":"float32","dimensions":1}}},{"name":"energyResolutionAt511","type":"float32"},{"name":"listmodeTimeBlockDuration","type":"uint32"}]},{"name":"Subject","fields":[{"name":"name","type":[null,"string"]},{"name":"id","type":"string"}]},{"name":"TimeBlock","fields":[{"name":"id","type":"uint32"},{"name":"promptEvents","type":{"vector":{"items":"Prd.CoincidenceEvent"}}},{"name":"delayedEvents","type":[null,{"vector":{"items":"Prd.CoincidenceEvent"}}]}]}]}"""
[docs] def __enter__(self): return self
[docs] def __exit__(self, exc_type: typing.Optional[type[BaseException]], exc: typing.Optional[BaseException], traceback: object) -> None: if exc is None and self._state == 3: try: self._end_stream() return finally: self.close() self.close() if exc is None and self._state != 4: expected_method = self._state_to_method_name((self._state + 1) & ~1) raise ProtocolError(f"Protocol writer closed before all steps were called. Expected to call to '{expected_method}'.")
[docs] def write_header(self, value: Header) -> None: """Ordinal 0""" if self._state != 0: self._raise_unexpected_state(0) self._write_header(value) self._state = 2
[docs] def write_time_blocks(self, value: collections.abc.Iterable[TimeBlock]) -> None: """Ordinal 1""" if self._state & ~1 != 2: self._raise_unexpected_state(2) self._write_time_blocks(value) self._state = 3
@abc.abstractmethod
[docs] def _write_header(self, value: Header) -> None: raise NotImplementedError()
@abc.abstractmethod
[docs] def _write_time_blocks(self, value: collections.abc.Iterable[TimeBlock]) -> None: raise NotImplementedError()
@abc.abstractmethod
[docs] def close(self) -> None: pass
@abc.abstractmethod
[docs] def _end_stream(self) -> None: pass
[docs] def _raise_unexpected_state(self, actual: int) -> None: expected_method = self._state_to_method_name(self._state) actual_method = self._state_to_method_name(actual) raise ProtocolError(f"Expected to call to '{expected_method}' but received call to '{actual_method}'.")
[docs] def _state_to_method_name(self, state: int) -> str: if state == 0: return 'write_header' if state == 2: return 'write_time_blocks' return "<unknown>"
[docs]class PrdExperimentReaderBase(abc.ABC): """Abstract reader for the PrdExperiment protocol.""" def __init__(self) -> None: self._state = 0
[docs] schema = PrdExperimentWriterBase.schema
[docs] def __enter__(self): return self
[docs] def __exit__(self, exc_type: typing.Optional[type[BaseException]], exc: typing.Optional[BaseException], traceback: object) -> None: self.close() if exc is None and self._state != 4: if self._state % 2 == 1: previous_method = self._state_to_method_name(self._state - 1) raise ProtocolError(f"Protocol reader closed before all data was consumed. The iterable returned by '{previous_method}' was not fully consumed.") else: expected_method = self._state_to_method_name(self._state) raise ProtocolError(f"Protocol reader closed before all data was consumed. Expected call to '{expected_method}'.")
@abc.abstractmethod
[docs] def close(self) -> None: raise NotImplementedError()
[docs] def read_header(self) -> Header: """Ordinal 0""" if self._state != 0: self._raise_unexpected_state(0) value = self._read_header() self._state = 2 return value
[docs] def read_time_blocks(self) -> collections.abc.Iterable[TimeBlock]: """Ordinal 1""" if self._state != 2: self._raise_unexpected_state(2) value = self._read_time_blocks() self._state = 3 return self._wrap_iterable(value, 4)
[docs] def copy_to(self, writer: PrdExperimentWriterBase) -> None: writer.write_header(self.read_header()) writer.write_time_blocks(self.read_time_blocks())
@abc.abstractmethod
[docs] def _read_header(self) -> Header: raise NotImplementedError()
@abc.abstractmethod
[docs] def _read_time_blocks(self) -> collections.abc.Iterable[TimeBlock]: raise NotImplementedError()
[docs] T = typing.TypeVar('T')
[docs] def _wrap_iterable(self, iterable: collections.abc.Iterable[T], final_state: int) -> collections.abc.Iterable[T]: yield from iterable self._state = final_state
[docs] def _raise_unexpected_state(self, actual: int) -> None: actual_method = self._state_to_method_name(actual) if self._state % 2 == 1: previous_method = self._state_to_method_name(self._state - 1) raise ProtocolError(f"Received call to '{actual_method}' but the iterable returned by '{previous_method}' was not fully consumed.") else: expected_method = self._state_to_method_name(self._state) raise ProtocolError(f"Expected to call to '{expected_method}' but received call to '{actual_method}'.")
[docs] def _state_to_method_name(self, state: int) -> str: if state == 0: return 'read_header' if state == 2: return 'read_time_blocks' return "<unknown>"