# This file was generated by the "yardl" tool. DO NOT EDIT.
# pyright: reportUnusedImport=false
# pyright: reportUnknownArgumentType=false
# pyright: reportUnknownMemberType=false
# pyright: reportUnknownVariableType=false
import datetime
import enum
import types
import typing
import numpy as np
import numpy.typing as npt
from . import yardl_types as yardl
from . import _dtypes
[docs]class CoincidenceEvent:
"""All information about a coincidence event specified as identifiers or indices (i.e. discretized).
TODO: this might take up too much space, so some/all of these could be combined in a single index if necessary.
"""
[docs] detector_1_id: yardl.UInt32
[docs] detector_2_id: yardl.UInt32
[docs] energy_1_idx: yardl.UInt32
[docs] energy_2_idx: yardl.UInt32
def __init__(self, *,
detector_1_id: yardl.UInt32 = 0,
detector_2_id: yardl.UInt32 = 0,
tof_idx: yardl.UInt32 = 0,
energy_1_idx: yardl.UInt32 = 0,
energy_2_idx: yardl.UInt32 = 0,
):
self.detector_1_id = detector_1_id
self.detector_2_id = detector_2_id
self.tof_idx = tof_idx
self.energy_1_idx = energy_1_idx
self.energy_2_idx = energy_2_idx
[docs] def __eq__(self, other: object) -> bool:
return (
isinstance(other, CoincidenceEvent)
and self.detector_1_id == other.detector_1_id
and self.detector_2_id == other.detector_2_id
and self.tof_idx == other.tof_idx
and self.energy_1_idx == other.energy_1_idx
and self.energy_2_idx == other.energy_2_idx
)
[docs] def __str__(self) -> str:
return f"CoincidenceEvent(detector1Id={self.detector_1_id}, detector2Id={self.detector_2_id}, tofIdx={self.tof_idx}, energy1Idx={self.energy_1_idx}, energy2Idx={self.energy_2_idx})"
[docs] def __repr__(self) -> str:
return f"CoincidenceEvent(detector1Id={repr(self.detector_1_id)}, detector2Id={repr(self.detector_2_id)}, tofIdx={repr(self.tof_idx)}, energy1Idx={repr(self.energy_1_idx)}, energy2Idx={repr(self.energy_2_idx)})"
[docs]class Subject:
[docs] name: typing.Optional[str]
def __init__(self, *,
name: typing.Optional[str] = None,
id: str = "",
):
self.name = name
self.id = id
[docs] def __eq__(self, other: object) -> bool:
return (
isinstance(other, Subject)
and self.name == other.name
and self.id == other.id
)
[docs] def __str__(self) -> str:
return f"Subject(name={self.name}, id={self.id})"
[docs] def __repr__(self) -> str:
return f"Subject(name={repr(self.name)}, id={repr(self.id)})"
[docs]class Institution:
def __init__(self, *,
name: str = "",
address: str = "",
):
self.name = name
self.address = address
[docs] def __eq__(self, other: object) -> bool:
return (
isinstance(other, Institution)
and self.name == other.name
and self.address == other.address
)
[docs] def __str__(self) -> str:
return f"Institution(name={self.name}, address={self.address})"
[docs] def __repr__(self) -> str:
return f"Institution(name={repr(self.name)}, address={repr(self.address)})"
[docs]class Detector:
"""Detector ID and location. Units are in mm
TODO: this is currently just a sample implementation with "point" detectors.
We plan to have full shape information here.
"""
def __init__(self, *,
id: yardl.UInt32 = 0,
x: yardl.Float32 = 0.0,
y: yardl.Float32 = 0.0,
z: yardl.Float32 = 0.0,
):
self.id = id
self.x = x
self.y = y
self.z = z
[docs] def __eq__(self, other: object) -> bool:
return (
isinstance(other, Detector)
and self.id == other.id
and self.x == other.x
and self.y == other.y
and self.z == other.z
)
[docs] def __str__(self) -> str:
return f"Detector(id={self.id}, x={self.x}, y={self.y}, z={self.z})"
[docs] def __repr__(self) -> str:
return f"Detector(id={repr(self.id)}, x={repr(self.x)}, y={repr(self.y)}, z={repr(self.z)})"
[docs]class TimeBlock:
"""number of the block. Multiply with listmodeTimeBlockDuration to get time since startOfAcquisition"""
[docs] prompt_events: list[CoincidenceEvent]
"""list of prompts in this time block
TODO might be better to use !array
"""
[docs] delayed_events: typing.Optional[list[CoincidenceEvent]]
"""list of delayed coincidences in this time block"""
def __init__(self, *,
id: yardl.UInt32 = 0,
prompt_events: typing.Optional[list[CoincidenceEvent]] = None,
delayed_events: typing.Optional[list[CoincidenceEvent]] = None,
):
self.id = id
self.prompt_events = prompt_events if prompt_events is not None else []
self.delayed_events = delayed_events
[docs] def __eq__(self, other: object) -> bool:
return (
isinstance(other, TimeBlock)
and self.id == other.id
and self.prompt_events == other.prompt_events
and self.delayed_events == other.delayed_events
)
[docs] def __str__(self) -> str:
return f"TimeBlock(id={self.id}, promptEvents={self.prompt_events}, delayedEvents={self.delayed_events})"
[docs] def __repr__(self) -> str:
return f"TimeBlock(id={repr(self.id)}, promptEvents={repr(self.prompt_events)}, delayedEvents={repr(self.delayed_events)})"
[docs]class TimeInterval:
"""Time interval in milliseconds since start of acquisition"""
def __init__(self, *,
start: yardl.UInt32 = 0,
stop: yardl.UInt32 = 0,
):
self.start = start
self.stop = stop
[docs] def __eq__(self, other: object) -> bool:
return (
isinstance(other, TimeInterval)
and self.start == other.start
and self.stop == other.stop
)
[docs] def __str__(self) -> str:
return f"TimeInterval(start={self.start}, stop={self.stop})"
[docs] def __repr__(self) -> str:
return f"TimeInterval(start={repr(self.start)}, stop={repr(self.stop)})"
[docs]def _mk_get_dtype():
dtype_map: dict[typing.Union[type, types.GenericAlias], typing.Union[np.dtype[typing.Any], typing.Callable[[tuple[type, ...]], np.dtype[typing.Any]]]] = {}
get_dtype = _dtypes.make_get_dtype_func(dtype_map)
dtype_map.setdefault(CoincidenceEvent, np.dtype([('detector_1_id', np.dtype(np.uint32)), ('detector_2_id', np.dtype(np.uint32)), ('tof_idx', np.dtype(np.uint32)), ('energy_1_idx', np.dtype(np.uint32)), ('energy_2_idx', np.dtype(np.uint32))], align=True))
dtype_map.setdefault(Subject, np.dtype([('name', np.dtype([('has_value', np.dtype(np.bool_)), ('value', np.dtype(np.object_))], align=True)), ('id', np.dtype(np.object_))], align=True))
dtype_map.setdefault(Institution, np.dtype([('name', np.dtype(np.object_)), ('address', np.dtype(np.object_))], align=True))
dtype_map.setdefault(ExamInformation, np.dtype([('subject', get_dtype(Subject)), ('institution', get_dtype(Institution)), ('protocol', np.dtype([('has_value', np.dtype(np.bool_)), ('value', np.dtype(np.object_))], align=True)), ('start_of_acquisition', np.dtype([('has_value', np.dtype(np.bool_)), ('value', np.dtype(np.datetime64))], align=True))], align=True))
dtype_map.setdefault(Detector, np.dtype([('id', np.dtype(np.uint32)), ('x', np.dtype(np.float32)), ('y', np.dtype(np.float32)), ('z', np.dtype(np.float32))], align=True))
dtype_map.setdefault(ScannerInformation, np.dtype([('model_name', np.dtype([('has_value', np.dtype(np.bool_)), ('value', np.dtype(np.object_))], align=True)), ('detectors', np.dtype(np.object_)), ('tof_bin_edges', np.dtype(np.object_)), ('tof_resolution', np.dtype(np.float32)), ('energy_bin_edges', np.dtype(np.object_)), ('energy_resolution_at_511', np.dtype(np.float32)), ('listmode_time_block_duration', np.dtype(np.uint32))], align=True))
dtype_map.setdefault(Header, np.dtype([('scanner', get_dtype(ScannerInformation)), ('exam', np.dtype([('has_value', np.dtype(np.bool_)), ('value', get_dtype(ExamInformation))], align=True))], align=True))
dtype_map.setdefault(TimeBlock, np.dtype([('id', np.dtype(np.uint32)), ('prompt_events', np.dtype(np.object_)), ('delayed_events', np.dtype([('has_value', np.dtype(np.bool_)), ('value', np.dtype(np.object_))], align=True))], align=True))
dtype_map.setdefault(TimeInterval, np.dtype([('start', np.dtype(np.uint32)), ('stop', np.dtype(np.uint32))], align=True))
dtype_map.setdefault(TimeFrameInformation, np.dtype([('time_frames', np.dtype(np.object_))], align=True))
return get_dtype
[docs]get_dtype = _mk_get_dtype()