# 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_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
@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_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
@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>"