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

# pyright: reportUnusedClass=false
# pyright: reportUnusedImport=false
# pyright: reportUnknownArgumentType=false
# pyright: reportUnknownMemberType=false
# pyright: reportUnknownVariableType=false

import collections.abc
import io
import typing

import numpy as np
import numpy.typing as npt

from .types import *

from .protocols import *
from . import _ndjson
from . import yardl_types as yardl

class ModulePairEfficienciesConverter(_ndjson.JsonConverter[ModulePairEfficiencies, np.void]):
    def __init__(self) -> None:
        self._values_converter = _ndjson.NDArrayConverter(_ndjson.float32_converter, 2)
        self._sgid_converter = _ndjson.uint32_converter
        super().__init__(np.dtype([
            ("values", self._values_converter.overall_dtype()),
            ("sgid", self._sgid_converter.overall_dtype()),
        ]))

    def to_json(self, value: ModulePairEfficiencies) -> object:
        if not isinstance(value, ModulePairEfficiencies): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'ModulePairEfficiencies' instance")
        json_object = {}

        json_object["values"] = self._values_converter.to_json(value.values)
        json_object["sgid"] = self._sgid_converter.to_json(value.sgid)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["values"] = self._values_converter.numpy_to_json(value["values"])
        json_object["sgid"] = self._sgid_converter.numpy_to_json(value["sgid"])
        return json_object

    def from_json(self, json_object: object) -> ModulePairEfficiencies:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return ModulePairEfficiencies(
            values=self._values_converter.from_json(json_object["values"],),
            sgid=self._sgid_converter.from_json(json_object["sgid"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._values_converter.from_json_to_numpy(json_object["values"]),
            self._sgid_converter.from_json_to_numpy(json_object["sgid"]),
        ) # type:ignore 


class DetectionEfficienciesConverter(_ndjson.JsonConverter[DetectionEfficiencies, np.void]):
    def __init__(self) -> None:
        self._method_description_converter = _ndjson.string_converter
        self._calibration_factor_converter = _ndjson.float32_converter
        self._detection_bin_efficiencies_converter = _ndjson.OptionalConverter(_ndjson.VectorConverter(_ndjson.NDArrayConverter(_ndjson.float32_converter, 1)))
        self._module_pair_sgidlut_converter = _ndjson.OptionalConverter(_ndjson.VectorConverter(_ndjson.VectorConverter(_ndjson.NDArrayConverter(_ndjson.int32_converter, 2))))
        self._module_pair_efficiencies_vectors_converter = _ndjson.OptionalConverter(_ndjson.VectorConverter(_ndjson.VectorConverter(_ndjson.VectorConverter(ModulePairEfficienciesConverter()))))
        super().__init__(np.dtype([
            ("method_description", self._method_description_converter.overall_dtype()),
            ("calibration_factor", self._calibration_factor_converter.overall_dtype()),
            ("detection_bin_efficiencies", self._detection_bin_efficiencies_converter.overall_dtype()),
            ("module_pair_sgidlut", self._module_pair_sgidlut_converter.overall_dtype()),
            ("module_pair_efficiencies_vectors", self._module_pair_efficiencies_vectors_converter.overall_dtype()),
        ]))

    def to_json(self, value: DetectionEfficiencies) -> object:
        if not isinstance(value, DetectionEfficiencies): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'DetectionEfficiencies' instance")
        json_object = {}

        json_object["methodDescription"] = self._method_description_converter.to_json(value.method_description)
        json_object["calibrationFactor"] = self._calibration_factor_converter.to_json(value.calibration_factor)
        if value.detection_bin_efficiencies is not None:
            json_object["detectionBinEfficiencies"] = self._detection_bin_efficiencies_converter.to_json(value.detection_bin_efficiencies)
        if value.module_pair_sgidlut is not None:
            json_object["modulePairSGIDLUT"] = self._module_pair_sgidlut_converter.to_json(value.module_pair_sgidlut)
        if value.module_pair_efficiencies_vectors is not None:
            json_object["modulePairEfficienciesVectors"] = self._module_pair_efficiencies_vectors_converter.to_json(value.module_pair_efficiencies_vectors)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["methodDescription"] = self._method_description_converter.numpy_to_json(value["method_description"])
        json_object["calibrationFactor"] = self._calibration_factor_converter.numpy_to_json(value["calibration_factor"])
        if (field_val := value["detection_bin_efficiencies"]) is not None:
            json_object["detectionBinEfficiencies"] = self._detection_bin_efficiencies_converter.numpy_to_json(field_val)
        if (field_val := value["module_pair_sgidlut"]) is not None:
            json_object["modulePairSGIDLUT"] = self._module_pair_sgidlut_converter.numpy_to_json(field_val)
        if (field_val := value["module_pair_efficiencies_vectors"]) is not None:
            json_object["modulePairEfficienciesVectors"] = self._module_pair_efficiencies_vectors_converter.numpy_to_json(field_val)
        return json_object

    def from_json(self, json_object: object) -> DetectionEfficiencies:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return DetectionEfficiencies(
            method_description=self._method_description_converter.from_json(json_object["methodDescription"],),
            calibration_factor=self._calibration_factor_converter.from_json(json_object["calibrationFactor"],),
            detection_bin_efficiencies=self._detection_bin_efficiencies_converter.from_json(json_object.get("detectionBinEfficiencies")),
            module_pair_sgidlut=self._module_pair_sgidlut_converter.from_json(json_object.get("modulePairSGIDLUT")),
            module_pair_efficiencies_vectors=self._module_pair_efficiencies_vectors_converter.from_json(json_object.get("modulePairEfficienciesVectors")),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._method_description_converter.from_json_to_numpy(json_object["methodDescription"]),
            self._calibration_factor_converter.from_json_to_numpy(json_object["calibrationFactor"]),
            self._detection_bin_efficiencies_converter.from_json_to_numpy(json_object.get("detectionBinEfficiencies")),
            self._module_pair_sgidlut_converter.from_json_to_numpy(json_object.get("modulePairSGIDLUT")),
            self._module_pair_efficiencies_vectors_converter.from_json_to_numpy(json_object.get("modulePairEfficienciesVectors")),
        ) # type:ignore 


class AliveTimeFractionsConverter(_ndjson.JsonConverter[AliveTimeFractions, np.void]):
    def __init__(self) -> None:
        self._singles_alive_time_fractions_converter = _ndjson.VectorConverter(_ndjson.NDArrayConverter(_ndjson.float32_converter, 1))
        self._module_coincidence_alive_time_fractions_converter = _ndjson.OptionalConverter(_ndjson.VectorConverter(_ndjson.VectorConverter(_ndjson.NDArrayConverter(_ndjson.float32_converter, 2))))
        super().__init__(np.dtype([
            ("singles_alive_time_fractions", self._singles_alive_time_fractions_converter.overall_dtype()),
            ("module_coincidence_alive_time_fractions", self._module_coincidence_alive_time_fractions_converter.overall_dtype()),
        ]))

    def to_json(self, value: AliveTimeFractions) -> object:
        if not isinstance(value, AliveTimeFractions): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'AliveTimeFractions' instance")
        json_object = {}

        json_object["singlesAliveTimeFractions"] = self._singles_alive_time_fractions_converter.to_json(value.singles_alive_time_fractions)
        if value.module_coincidence_alive_time_fractions is not None:
            json_object["moduleCoincidenceAliveTimeFractions"] = self._module_coincidence_alive_time_fractions_converter.to_json(value.module_coincidence_alive_time_fractions)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["singlesAliveTimeFractions"] = self._singles_alive_time_fractions_converter.numpy_to_json(value["singles_alive_time_fractions"])
        if (field_val := value["module_coincidence_alive_time_fractions"]) is not None:
            json_object["moduleCoincidenceAliveTimeFractions"] = self._module_coincidence_alive_time_fractions_converter.numpy_to_json(field_val)
        return json_object

    def from_json(self, json_object: object) -> AliveTimeFractions:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return AliveTimeFractions(
            singles_alive_time_fractions=self._singles_alive_time_fractions_converter.from_json(json_object["singlesAliveTimeFractions"],),
            module_coincidence_alive_time_fractions=self._module_coincidence_alive_time_fractions_converter.from_json(json_object.get("moduleCoincidenceAliveTimeFractions")),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._singles_alive_time_fractions_converter.from_json_to_numpy(json_object["singlesAliveTimeFractions"]),
            self._module_coincidence_alive_time_fractions_converter.from_json_to_numpy(json_object.get("moduleCoincidenceAliveTimeFractions")),
        ) # type:ignore 


class SolidVolumeConverter(typing.Generic[Shape, Shape_NP], _ndjson.JsonConverter[SolidVolume[Shape], np.void]):
    def __init__(self, shape_converter: _ndjson.JsonConverter[Shape, Shape_NP]) -> None:
        self._shape_converter = shape_converter
        self._shape_supports_none = self._shape_converter.supports_none()
        self._material_id_converter = _ndjson.uint32_converter
        super().__init__(np.dtype([
            ("shape", self._shape_converter.overall_dtype()),
            ("material_id", self._material_id_converter.overall_dtype()),
        ]))

    def to_json(self, value: SolidVolume[Shape]) -> object:
        if not isinstance(value, SolidVolume): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'SolidVolume[Shape]' instance")
        json_object = {}

        if not self._shape_supports_none or value.shape is not None:
            json_object["shape"] = self._shape_converter.to_json(value.shape)
        json_object["materialId"] = self._material_id_converter.to_json(value.material_id)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        if not self._shape_supports_none or value["shape"] is not None:
            json_object["shape"] = self._shape_converter.numpy_to_json(value["shape"])
        json_object["materialId"] = self._material_id_converter.numpy_to_json(value["material_id"])
        return json_object

    def from_json(self, json_object: object) -> SolidVolume[Shape]:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return SolidVolume[Shape](
            shape=self._shape_converter.from_json(json_object.get("shape") if self._shape_supports_none else json_object["shape"]),
            material_id=self._material_id_converter.from_json(json_object["materialId"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._shape_converter.from_json_to_numpy(json_object.get("shape") if self._shape_supports_none else json_object["shape"]),
            self._material_id_converter.from_json_to_numpy(json_object["materialId"]),
        ) # type:ignore 


class CoordinateConverter(_ndjson.JsonConverter[Coordinate, np.void]):
    def __init__(self) -> None:
        self._c_converter = _ndjson.FixedNDArrayConverter(_ndjson.float32_converter, (3,))
        super().__init__(np.dtype([
            ("c", self._c_converter.overall_dtype()),
        ]))

    def to_json(self, value: Coordinate) -> object:
        if not isinstance(value, Coordinate): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'Coordinate' instance")
        json_object = {}

        json_object["c"] = self._c_converter.to_json(value.c)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["c"] = self._c_converter.numpy_to_json(value["c"])
        return json_object

    def from_json(self, json_object: object) -> Coordinate:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return Coordinate(
            c=self._c_converter.from_json(json_object["c"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._c_converter.from_json_to_numpy(json_object["c"]),
        ) # type:ignore 


class BoxShapeConverter(_ndjson.JsonConverter[BoxShape, np.void]):
    def __init__(self) -> None:
        self._corners_converter = _ndjson.FixedVectorConverter(CoordinateConverter(), 8)
        super().__init__(np.dtype([
            ("corners", self._corners_converter.overall_dtype()),
        ]))

    def to_json(self, value: BoxShape) -> object:
        if not isinstance(value, BoxShape): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'BoxShape' instance")
        json_object = {}

        json_object["corners"] = self._corners_converter.to_json(value.corners)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["corners"] = self._corners_converter.numpy_to_json(value["corners"])
        return json_object

    def from_json(self, json_object: object) -> BoxShape:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return BoxShape(
            corners=self._corners_converter.from_json(json_object["corners"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._corners_converter.from_json_to_numpy(json_object["corners"]),
        ) # type:ignore 


class AnnulusShapeConverter(_ndjson.JsonConverter[AnnulusShape, np.void]):
    def __init__(self) -> None:
        self._inner_radius_converter = _ndjson.float32_converter
        self._outer_radius_converter = _ndjson.float32_converter
        self._thickness_converter = _ndjson.float32_converter
        self._angular_range_converter = _ndjson.FixedVectorConverter(_ndjson.float32_converter, 2)
        super().__init__(np.dtype([
            ("inner_radius", self._inner_radius_converter.overall_dtype()),
            ("outer_radius", self._outer_radius_converter.overall_dtype()),
            ("thickness", self._thickness_converter.overall_dtype()),
            ("angular_range", self._angular_range_converter.overall_dtype()),
        ]))

    def to_json(self, value: AnnulusShape) -> object:
        if not isinstance(value, AnnulusShape): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'AnnulusShape' instance")
        json_object = {}

        json_object["innerRadius"] = self._inner_radius_converter.to_json(value.inner_radius)
        json_object["outerRadius"] = self._outer_radius_converter.to_json(value.outer_radius)
        json_object["thickness"] = self._thickness_converter.to_json(value.thickness)
        json_object["angularRange"] = self._angular_range_converter.to_json(value.angular_range)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["innerRadius"] = self._inner_radius_converter.numpy_to_json(value["inner_radius"])
        json_object["outerRadius"] = self._outer_radius_converter.numpy_to_json(value["outer_radius"])
        json_object["thickness"] = self._thickness_converter.numpy_to_json(value["thickness"])
        json_object["angularRange"] = self._angular_range_converter.numpy_to_json(value["angular_range"])
        return json_object

    def from_json(self, json_object: object) -> AnnulusShape:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return AnnulusShape(
            inner_radius=self._inner_radius_converter.from_json(json_object["innerRadius"],),
            outer_radius=self._outer_radius_converter.from_json(json_object["outerRadius"],),
            thickness=self._thickness_converter.from_json(json_object["thickness"],),
            angular_range=self._angular_range_converter.from_json(json_object["angularRange"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._inner_radius_converter.from_json_to_numpy(json_object["innerRadius"]),
            self._outer_radius_converter.from_json_to_numpy(json_object["outerRadius"]),
            self._thickness_converter.from_json_to_numpy(json_object["thickness"]),
            self._angular_range_converter.from_json_to_numpy(json_object["angularRange"]),
        ) # type:ignore 


class RigidTransformationConverter(_ndjson.JsonConverter[RigidTransformation, np.void]):
    def __init__(self) -> None:
        self._matrix_converter = _ndjson.FixedNDArrayConverter(_ndjson.float32_converter, (3, 4,))
        super().__init__(np.dtype([
            ("matrix", self._matrix_converter.overall_dtype()),
        ]))

    def to_json(self, value: RigidTransformation) -> object:
        if not isinstance(value, RigidTransformation): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'RigidTransformation' instance")
        json_object = {}

        json_object["matrix"] = self._matrix_converter.to_json(value.matrix)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["matrix"] = self._matrix_converter.numpy_to_json(value["matrix"])
        return json_object

    def from_json(self, json_object: object) -> RigidTransformation:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return RigidTransformation(
            matrix=self._matrix_converter.from_json(json_object["matrix"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._matrix_converter.from_json_to_numpy(json_object["matrix"]),
        ) # type:ignore 


class ReplicatedObjectConverter(typing.Generic[T, T_NP], _ndjson.JsonConverter[ReplicatedObject[T], np.void]):
    def __init__(self, t_converter: _ndjson.JsonConverter[T, T_NP]) -> None:
        self._object_converter = t_converter
        self._object_supports_none = self._object_converter.supports_none()
        self._transforms_converter = _ndjson.VectorConverter(RigidTransformationConverter())
        super().__init__(np.dtype([
            ("object", self._object_converter.overall_dtype()),
            ("transforms", self._transforms_converter.overall_dtype()),
        ]))

    def to_json(self, value: ReplicatedObject[T]) -> object:
        if not isinstance(value, ReplicatedObject): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'ReplicatedObject[T]' instance")
        json_object = {}

        if not self._object_supports_none or value.object is not None:
            json_object["object"] = self._object_converter.to_json(value.object)
        json_object["transforms"] = self._transforms_converter.to_json(value.transforms)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        if not self._object_supports_none or value["object"] is not None:
            json_object["object"] = self._object_converter.numpy_to_json(value["object"])
        json_object["transforms"] = self._transforms_converter.numpy_to_json(value["transforms"])
        return json_object

    def from_json(self, json_object: object) -> ReplicatedObject[T]:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return ReplicatedObject[T](
            object=self._object_converter.from_json(json_object.get("object") if self._object_supports_none else json_object["object"]),
            transforms=self._transforms_converter.from_json(json_object["transforms"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._object_converter.from_json_to_numpy(json_object.get("object") if self._object_supports_none else json_object["object"]),
            self._transforms_converter.from_json_to_numpy(json_object["transforms"]),
        ) # type:ignore 


class DetectorModuleConverter(_ndjson.JsonConverter[DetectorModule, np.void]):
    def __init__(self) -> None:
        self._detecting_elements_converter = ReplicatedObjectConverter(SolidVolumeConverter(BoxShapeConverter()))
        self._non_detecting_elements_converter = _ndjson.VectorConverter(ReplicatedObjectConverter(SolidVolumeConverter(_ndjson.UnionConverter(GeometricShape, [(GeometricShape.BoxShape, BoxShapeConverter(), [dict]), (GeometricShape.AnnulusShape, AnnulusShapeConverter(), [dict])], False))))
        super().__init__(np.dtype([
            ("detecting_elements", self._detecting_elements_converter.overall_dtype()),
            ("non_detecting_elements", self._non_detecting_elements_converter.overall_dtype()),
        ]))

    def to_json(self, value: DetectorModule) -> object:
        if not isinstance(value, DetectorModule): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'DetectorModule' instance")
        json_object = {}

        json_object["detectingElements"] = self._detecting_elements_converter.to_json(value.detecting_elements)
        json_object["nonDetectingElements"] = self._non_detecting_elements_converter.to_json(value.non_detecting_elements)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["detectingElements"] = self._detecting_elements_converter.numpy_to_json(value["detecting_elements"])
        json_object["nonDetectingElements"] = self._non_detecting_elements_converter.numpy_to_json(value["non_detecting_elements"])
        return json_object

    def from_json(self, json_object: object) -> DetectorModule:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return DetectorModule(
            detecting_elements=self._detecting_elements_converter.from_json(json_object["detectingElements"],),
            non_detecting_elements=self._non_detecting_elements_converter.from_json(json_object["nonDetectingElements"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._detecting_elements_converter.from_json_to_numpy(json_object["detectingElements"]),
            self._non_detecting_elements_converter.from_json_to_numpy(json_object["nonDetectingElements"]),
        ) # type:ignore 


class ScannerGeometryConverter(_ndjson.JsonConverter[ScannerGeometry, np.void]):
    def __init__(self) -> None:
        self._replicated_modules_converter = _ndjson.VectorConverter(ReplicatedObjectConverter(DetectorModuleConverter()))
        self._non_detecting_volumes_converter = _ndjson.OptionalConverter(_ndjson.VectorConverter(SolidVolumeConverter(_ndjson.UnionConverter(GeometricShape, [(GeometricShape.BoxShape, BoxShapeConverter(), [dict]), (GeometricShape.AnnulusShape, AnnulusShapeConverter(), [dict])], False))))
        super().__init__(np.dtype([
            ("replicated_modules", self._replicated_modules_converter.overall_dtype()),
            ("non_detecting_volumes", self._non_detecting_volumes_converter.overall_dtype()),
        ]))

    def to_json(self, value: ScannerGeometry) -> object:
        if not isinstance(value, ScannerGeometry): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'ScannerGeometry' instance")
        json_object = {}

        json_object["replicatedModules"] = self._replicated_modules_converter.to_json(value.replicated_modules)
        if value.non_detecting_volumes is not None:
            json_object["nonDetectingVolumes"] = self._non_detecting_volumes_converter.to_json(value.non_detecting_volumes)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["replicatedModules"] = self._replicated_modules_converter.numpy_to_json(value["replicated_modules"])
        if (field_val := value["non_detecting_volumes"]) is not None:
            json_object["nonDetectingVolumes"] = self._non_detecting_volumes_converter.numpy_to_json(field_val)
        return json_object

    def from_json(self, json_object: object) -> ScannerGeometry:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return ScannerGeometry(
            replicated_modules=self._replicated_modules_converter.from_json(json_object["replicatedModules"],),
            non_detecting_volumes=self._non_detecting_volumes_converter.from_json(json_object.get("nonDetectingVolumes")),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._replicated_modules_converter.from_json_to_numpy(json_object["replicatedModules"]),
            self._non_detecting_volumes_converter.from_json_to_numpy(json_object.get("nonDetectingVolumes")),
        ) # type:ignore 


class ExpandedDetectionBinConverter(_ndjson.JsonConverter[ExpandedDetectionBin, np.void]):
    def __init__(self) -> None:
        self._module_index_converter = _ndjson.uint32_converter
        self._element_index_converter = _ndjson.uint32_converter
        self._energy_index_converter = _ndjson.uint32_converter
        super().__init__(np.dtype([
            ("module_index", self._module_index_converter.overall_dtype()),
            ("element_index", self._element_index_converter.overall_dtype()),
            ("energy_index", self._energy_index_converter.overall_dtype()),
        ]))

    def to_json(self, value: ExpandedDetectionBin) -> object:
        if not isinstance(value, ExpandedDetectionBin): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'ExpandedDetectionBin' instance")
        json_object = {}

        json_object["moduleIndex"] = self._module_index_converter.to_json(value.module_index)
        json_object["elementIndex"] = self._element_index_converter.to_json(value.element_index)
        json_object["energyIndex"] = self._energy_index_converter.to_json(value.energy_index)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["moduleIndex"] = self._module_index_converter.numpy_to_json(value["module_index"])
        json_object["elementIndex"] = self._element_index_converter.numpy_to_json(value["element_index"])
        json_object["energyIndex"] = self._energy_index_converter.numpy_to_json(value["energy_index"])
        return json_object

    def from_json(self, json_object: object) -> ExpandedDetectionBin:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return ExpandedDetectionBin(
            module_index=self._module_index_converter.from_json(json_object["moduleIndex"],),
            element_index=self._element_index_converter.from_json(json_object["elementIndex"],),
            energy_index=self._energy_index_converter.from_json(json_object["energyIndex"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._module_index_converter.from_json_to_numpy(json_object["moduleIndex"]),
            self._element_index_converter.from_json_to_numpy(json_object["elementIndex"]),
            self._energy_index_converter.from_json_to_numpy(json_object["energyIndex"]),
        ) # type:ignore 


class SingleEventConverter(_ndjson.JsonConverter[SingleEvent, np.void]):
    def __init__(self) -> None:
        self._detection_bin_converter = _ndjson.uint32_converter
        self._time_offset_in_time_block_converter = _ndjson.uint32_converter
        super().__init__(np.dtype([
            ("detection_bin", self._detection_bin_converter.overall_dtype()),
            ("time_offset_in_time_block", self._time_offset_in_time_block_converter.overall_dtype()),
        ]))

    def to_json(self, value: SingleEvent) -> object:
        if not isinstance(value, SingleEvent): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'SingleEvent' instance")
        json_object = {}

        json_object["detectionBin"] = self._detection_bin_converter.to_json(value.detection_bin)
        json_object["timeOffsetInTimeBlock"] = self._time_offset_in_time_block_converter.to_json(value.time_offset_in_time_block)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["detectionBin"] = self._detection_bin_converter.numpy_to_json(value["detection_bin"])
        json_object["timeOffsetInTimeBlock"] = self._time_offset_in_time_block_converter.numpy_to_json(value["time_offset_in_time_block"])
        return json_object

    def from_json(self, json_object: object) -> SingleEvent:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return SingleEvent(
            detection_bin=self._detection_bin_converter.from_json(json_object["detectionBin"],),
            time_offset_in_time_block=self._time_offset_in_time_block_converter.from_json(json_object["timeOffsetInTimeBlock"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._detection_bin_converter.from_json_to_numpy(json_object["detectionBin"]),
            self._time_offset_in_time_block_converter.from_json_to_numpy(json_object["timeOffsetInTimeBlock"]),
        ) # type:ignore 


class CoincidenceEventConverter(_ndjson.JsonConverter[CoincidenceEvent, np.void]):
    def __init__(self) -> None:
        self._detection_bins_converter = _ndjson.FixedVectorConverter(_ndjson.uint32_converter, 2)
        self._tof_idx_converter = _ndjson.uint32_converter
        super().__init__(np.dtype([
            ("detection_bins", self._detection_bins_converter.overall_dtype()),
            ("tof_idx", self._tof_idx_converter.overall_dtype()),
        ]))

    def to_json(self, value: CoincidenceEvent) -> object:
        if not isinstance(value, CoincidenceEvent): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'CoincidenceEvent' instance")
        json_object = {}

        json_object["detectionBins"] = self._detection_bins_converter.to_json(value.detection_bins)
        json_object["tofIdx"] = self._tof_idx_converter.to_json(value.tof_idx)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["detectionBins"] = self._detection_bins_converter.numpy_to_json(value["detection_bins"])
        json_object["tofIdx"] = self._tof_idx_converter.numpy_to_json(value["tof_idx"])
        return json_object

    def from_json(self, json_object: object) -> CoincidenceEvent:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return CoincidenceEvent(
            detection_bins=self._detection_bins_converter.from_json(json_object["detectionBins"],),
            tof_idx=self._tof_idx_converter.from_json(json_object["tofIdx"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._detection_bins_converter.from_json_to_numpy(json_object["detectionBins"]),
            self._tof_idx_converter.from_json_to_numpy(json_object["tofIdx"]),
        ) # type:ignore 


class TripleEventConverter(_ndjson.JsonConverter[TripleEvent, np.void]):
    def __init__(self) -> None:
        self._detection_bins_converter = _ndjson.FixedVectorConverter(_ndjson.uint32_converter, 3)
        self._tof_indices_converter = _ndjson.FixedVectorConverter(_ndjson.uint32_converter, 2)
        super().__init__(np.dtype([
            ("detection_bins", self._detection_bins_converter.overall_dtype()),
            ("tof_indices", self._tof_indices_converter.overall_dtype()),
        ]))

    def to_json(self, value: TripleEvent) -> object:
        if not isinstance(value, TripleEvent): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'TripleEvent' instance")
        json_object = {}

        json_object["detectionBins"] = self._detection_bins_converter.to_json(value.detection_bins)
        json_object["tofIndices"] = self._tof_indices_converter.to_json(value.tof_indices)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["detectionBins"] = self._detection_bins_converter.numpy_to_json(value["detection_bins"])
        json_object["tofIndices"] = self._tof_indices_converter.numpy_to_json(value["tof_indices"])
        return json_object

    def from_json(self, json_object: object) -> TripleEvent:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return TripleEvent(
            detection_bins=self._detection_bins_converter.from_json(json_object["detectionBins"],),
            tof_indices=self._tof_indices_converter.from_json(json_object["tofIndices"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._detection_bins_converter.from_json_to_numpy(json_object["detectionBins"]),
            self._tof_indices_converter.from_json_to_numpy(json_object["tofIndices"]),
        ) # type:ignore 


class QuadrupleEventConverter(_ndjson.JsonConverter[QuadrupleEvent, np.void]):
    def __init__(self) -> None:
        self._detection_bins_converter = _ndjson.FixedVectorConverter(_ndjson.uint32_converter, 4)
        self._tof_indices_converter = _ndjson.FixedVectorConverter(_ndjson.uint32_converter, 3)
        super().__init__(np.dtype([
            ("detection_bins", self._detection_bins_converter.overall_dtype()),
            ("tof_indices", self._tof_indices_converter.overall_dtype()),
        ]))

    def to_json(self, value: QuadrupleEvent) -> object:
        if not isinstance(value, QuadrupleEvent): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'QuadrupleEvent' instance")
        json_object = {}

        json_object["detectionBins"] = self._detection_bins_converter.to_json(value.detection_bins)
        json_object["tofIndices"] = self._tof_indices_converter.to_json(value.tof_indices)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["detectionBins"] = self._detection_bins_converter.numpy_to_json(value["detection_bins"])
        json_object["tofIndices"] = self._tof_indices_converter.numpy_to_json(value["tof_indices"])
        return json_object

    def from_json(self, json_object: object) -> QuadrupleEvent:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return QuadrupleEvent(
            detection_bins=self._detection_bins_converter.from_json(json_object["detectionBins"],),
            tof_indices=self._tof_indices_converter.from_json(json_object["tofIndices"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._detection_bins_converter.from_json_to_numpy(json_object["detectionBins"]),
            self._tof_indices_converter.from_json_to_numpy(json_object["tofIndices"]),
        ) # type:ignore 


class SubjectConverter(_ndjson.JsonConverter[Subject, np.void]):
    def __init__(self) -> None:
        self._name_converter = _ndjson.OptionalConverter(_ndjson.string_converter)
        self._id_converter = _ndjson.string_converter
        super().__init__(np.dtype([
            ("name", self._name_converter.overall_dtype()),
            ("id", self._id_converter.overall_dtype()),
        ]))

    def to_json(self, value: Subject) -> object:
        if not isinstance(value, Subject): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'Subject' instance")
        json_object = {}

        if value.name is not None:
            json_object["name"] = self._name_converter.to_json(value.name)
        json_object["id"] = self._id_converter.to_json(value.id)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        if (field_val := value["name"]) is not None:
            json_object["name"] = self._name_converter.numpy_to_json(field_val)
        json_object["id"] = self._id_converter.numpy_to_json(value["id"])
        return json_object

    def from_json(self, json_object: object) -> Subject:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return Subject(
            name=self._name_converter.from_json(json_object.get("name")),
            id=self._id_converter.from_json(json_object["id"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._name_converter.from_json_to_numpy(json_object.get("name")),
            self._id_converter.from_json_to_numpy(json_object["id"]),
        ) # type:ignore 


class InstitutionConverter(_ndjson.JsonConverter[Institution, np.void]):
    def __init__(self) -> None:
        self._name_converter = _ndjson.string_converter
        self._address_converter = _ndjson.string_converter
        super().__init__(np.dtype([
            ("name", self._name_converter.overall_dtype()),
            ("address", self._address_converter.overall_dtype()),
        ]))

    def to_json(self, value: Institution) -> object:
        if not isinstance(value, Institution): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'Institution' instance")
        json_object = {}

        json_object["name"] = self._name_converter.to_json(value.name)
        json_object["address"] = self._address_converter.to_json(value.address)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["name"] = self._name_converter.numpy_to_json(value["name"])
        json_object["address"] = self._address_converter.numpy_to_json(value["address"])
        return json_object

    def from_json(self, json_object: object) -> Institution:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return Institution(
            name=self._name_converter.from_json(json_object["name"],),
            address=self._address_converter.from_json(json_object["address"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._name_converter.from_json_to_numpy(json_object["name"]),
            self._address_converter.from_json_to_numpy(json_object["address"]),
        ) # type:ignore 


external_signal_type_enum_name_to_value_map = {
    "ecgTrace": ExternalSignalTypeEnum.ECG_TRACE,
    "ecgTrigger": ExternalSignalTypeEnum.ECG_TRIGGER,
    "respTrace": ExternalSignalTypeEnum.RESP_TRACE,
    "respTrigger": ExternalSignalTypeEnum.RESP_TRIGGER,
    "otherMotionSignal": ExternalSignalTypeEnum.OTHER_MOTION_SIGNAL,
    "otherMotionTrigger": ExternalSignalTypeEnum.OTHER_MOTION_TRIGGER,
    "externalSync": ExternalSignalTypeEnum.EXTERNAL_SYNC,
    "mrPulseStart": ExternalSignalTypeEnum.MR_PULSE_START,
    "other": ExternalSignalTypeEnum.OTHER,
}
external_signal_type_enum_value_to_name_map = {v: n for n, v in external_signal_type_enum_name_to_value_map.items()}

class ExternalSignalConverter(_ndjson.JsonConverter[ExternalSignal, np.void]):
    def __init__(self) -> None:
        self._type_converter = _ndjson.EnumConverter(ExternalSignalTypeEnum, np.int32, external_signal_type_enum_name_to_value_map, external_signal_type_enum_value_to_name_map)
        self._description_converter = _ndjson.string_converter
        self._id_converter = _ndjson.uint32_converter
        super().__init__(np.dtype([
            ("type", self._type_converter.overall_dtype()),
            ("description", self._description_converter.overall_dtype()),
            ("id", self._id_converter.overall_dtype()),
        ]))

    def to_json(self, value: ExternalSignal) -> object:
        if not isinstance(value, ExternalSignal): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'ExternalSignal' instance")
        json_object = {}

        json_object["type"] = self._type_converter.to_json(value.type)
        json_object["description"] = self._description_converter.to_json(value.description)
        json_object["id"] = self._id_converter.to_json(value.id)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["type"] = self._type_converter.numpy_to_json(value["type"])
        json_object["description"] = self._description_converter.numpy_to_json(value["description"])
        json_object["id"] = self._id_converter.numpy_to_json(value["id"])
        return json_object

    def from_json(self, json_object: object) -> ExternalSignal:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return ExternalSignal(
            type=self._type_converter.from_json(json_object["type"],),
            description=self._description_converter.from_json(json_object["description"],),
            id=self._id_converter.from_json(json_object["id"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._type_converter.from_json_to_numpy(json_object["type"]),
            self._description_converter.from_json_to_numpy(json_object["description"]),
            self._id_converter.from_json_to_numpy(json_object["id"]),
        ) # type:ignore 


class ExamInformationConverter(_ndjson.JsonConverter[ExamInformation, np.void]):
    def __init__(self) -> None:
        self._subject_converter = SubjectConverter()
        self._institution_converter = InstitutionConverter()
        self._protocol_converter = _ndjson.OptionalConverter(_ndjson.string_converter)
        self._start_of_acquisition_converter = _ndjson.OptionalConverter(_ndjson.datetime_converter)
        self._external_signals_converter = _ndjson.VectorConverter(ExternalSignalConverter())
        super().__init__(np.dtype([
            ("subject", self._subject_converter.overall_dtype()),
            ("institution", self._institution_converter.overall_dtype()),
            ("protocol", self._protocol_converter.overall_dtype()),
            ("start_of_acquisition", self._start_of_acquisition_converter.overall_dtype()),
            ("external_signals", self._external_signals_converter.overall_dtype()),
        ]))

    def to_json(self, value: ExamInformation) -> object:
        if not isinstance(value, ExamInformation): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'ExamInformation' instance")
        json_object = {}

        json_object["subject"] = self._subject_converter.to_json(value.subject)
        json_object["institution"] = self._institution_converter.to_json(value.institution)
        if value.protocol is not None:
            json_object["protocol"] = self._protocol_converter.to_json(value.protocol)
        if value.start_of_acquisition is not None:
            json_object["startOfAcquisition"] = self._start_of_acquisition_converter.to_json(value.start_of_acquisition)
        json_object["externalSignals"] = self._external_signals_converter.to_json(value.external_signals)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["subject"] = self._subject_converter.numpy_to_json(value["subject"])
        json_object["institution"] = self._institution_converter.numpy_to_json(value["institution"])
        if (field_val := value["protocol"]) is not None:
            json_object["protocol"] = self._protocol_converter.numpy_to_json(field_val)
        if (field_val := value["start_of_acquisition"]) is not None:
            json_object["startOfAcquisition"] = self._start_of_acquisition_converter.numpy_to_json(field_val)
        json_object["externalSignals"] = self._external_signals_converter.numpy_to_json(value["external_signals"])
        return json_object

    def from_json(self, json_object: object) -> ExamInformation:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return ExamInformation(
            subject=self._subject_converter.from_json(json_object["subject"],),
            institution=self._institution_converter.from_json(json_object["institution"],),
            protocol=self._protocol_converter.from_json(json_object.get("protocol")),
            start_of_acquisition=self._start_of_acquisition_converter.from_json(json_object.get("startOfAcquisition")),
            external_signals=self._external_signals_converter.from_json(json_object["externalSignals"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._subject_converter.from_json_to_numpy(json_object["subject"]),
            self._institution_converter.from_json_to_numpy(json_object["institution"]),
            self._protocol_converter.from_json_to_numpy(json_object.get("protocol")),
            self._start_of_acquisition_converter.from_json_to_numpy(json_object.get("startOfAcquisition")),
            self._external_signals_converter.from_json_to_numpy(json_object["externalSignals"]),
        ) # type:ignore 


class DirectionConverter(_ndjson.JsonConverter[Direction, np.void]):
    def __init__(self) -> None:
        self._c_converter = _ndjson.FixedNDArrayConverter(_ndjson.float32_converter, (3,))
        super().__init__(np.dtype([
            ("c", self._c_converter.overall_dtype()),
        ]))

    def to_json(self, value: Direction) -> object:
        if not isinstance(value, Direction): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'Direction' instance")
        json_object = {}

        json_object["c"] = self._c_converter.to_json(value.c)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["c"] = self._c_converter.numpy_to_json(value["c"])
        return json_object

    def from_json(self, json_object: object) -> Direction:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return Direction(
            c=self._c_converter.from_json(json_object["c"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._c_converter.from_json_to_numpy(json_object["c"]),
        ) # type:ignore 


class DirectionMatrixConverter(_ndjson.JsonConverter[DirectionMatrix, np.void]):
    def __init__(self) -> None:
        self._matrix_converter = _ndjson.FixedNDArrayConverter(_ndjson.float32_converter, (3, 3,))
        super().__init__(np.dtype([
            ("matrix", self._matrix_converter.overall_dtype()),
        ]))

    def to_json(self, value: DirectionMatrix) -> object:
        if not isinstance(value, DirectionMatrix): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'DirectionMatrix' instance")
        json_object = {}

        json_object["matrix"] = self._matrix_converter.to_json(value.matrix)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["matrix"] = self._matrix_converter.numpy_to_json(value["matrix"])
        return json_object

    def from_json(self, json_object: object) -> DirectionMatrix:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return DirectionMatrix(
            matrix=self._matrix_converter.from_json(json_object["matrix"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._matrix_converter.from_json_to_numpy(json_object["matrix"]),
        ) # type:ignore 


class AtomConverter(_ndjson.JsonConverter[Atom, np.void]):
    def __init__(self) -> None:
        self._mass_number_converter = _ndjson.uint32_converter
        self._atomic_number_converter = _ndjson.uint32_converter
        super().__init__(np.dtype([
            ("mass_number", self._mass_number_converter.overall_dtype()),
            ("atomic_number", self._atomic_number_converter.overall_dtype()),
        ]))

    def to_json(self, value: Atom) -> object:
        if not isinstance(value, Atom): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'Atom' instance")
        json_object = {}

        json_object["massNumber"] = self._mass_number_converter.to_json(value.mass_number)
        json_object["atomicNumber"] = self._atomic_number_converter.to_json(value.atomic_number)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["massNumber"] = self._mass_number_converter.numpy_to_json(value["mass_number"])
        json_object["atomicNumber"] = self._atomic_number_converter.numpy_to_json(value["atomic_number"])
        return json_object

    def from_json(self, json_object: object) -> Atom:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return Atom(
            mass_number=self._mass_number_converter.from_json(json_object["massNumber"],),
            atomic_number=self._atomic_number_converter.from_json(json_object["atomicNumber"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._mass_number_converter.from_json_to_numpy(json_object["massNumber"]),
            self._atomic_number_converter.from_json_to_numpy(json_object["atomicNumber"]),
        ) # type:ignore 


class BulkMaterialConverter(_ndjson.JsonConverter[BulkMaterial, np.void]):
    def __init__(self) -> None:
        self._id_converter = _ndjson.uint32_converter
        self._name_converter = _ndjson.string_converter
        self._density_converter = _ndjson.float32_converter
        self._atoms_converter = _ndjson.VectorConverter(AtomConverter())
        self._mass_fractions_converter = _ndjson.VectorConverter(_ndjson.float32_converter)
        super().__init__(np.dtype([
            ("id", self._id_converter.overall_dtype()),
            ("name", self._name_converter.overall_dtype()),
            ("density", self._density_converter.overall_dtype()),
            ("atoms", self._atoms_converter.overall_dtype()),
            ("mass_fractions", self._mass_fractions_converter.overall_dtype()),
        ]))

    def to_json(self, value: BulkMaterial) -> object:
        if not isinstance(value, BulkMaterial): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'BulkMaterial' instance")
        json_object = {}

        json_object["id"] = self._id_converter.to_json(value.id)
        json_object["name"] = self._name_converter.to_json(value.name)
        json_object["density"] = self._density_converter.to_json(value.density)
        json_object["atoms"] = self._atoms_converter.to_json(value.atoms)
        json_object["massFractions"] = self._mass_fractions_converter.to_json(value.mass_fractions)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["id"] = self._id_converter.numpy_to_json(value["id"])
        json_object["name"] = self._name_converter.numpy_to_json(value["name"])
        json_object["density"] = self._density_converter.numpy_to_json(value["density"])
        json_object["atoms"] = self._atoms_converter.numpy_to_json(value["atoms"])
        json_object["massFractions"] = self._mass_fractions_converter.numpy_to_json(value["mass_fractions"])
        return json_object

    def from_json(self, json_object: object) -> BulkMaterial:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return BulkMaterial(
            id=self._id_converter.from_json(json_object["id"],),
            name=self._name_converter.from_json(json_object["name"],),
            density=self._density_converter.from_json(json_object["density"],),
            atoms=self._atoms_converter.from_json(json_object["atoms"],),
            mass_fractions=self._mass_fractions_converter.from_json(json_object["massFractions"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._id_converter.from_json_to_numpy(json_object["id"]),
            self._name_converter.from_json_to_numpy(json_object["name"]),
            self._density_converter.from_json_to_numpy(json_object["density"]),
            self._atoms_converter.from_json_to_numpy(json_object["atoms"]),
            self._mass_fractions_converter.from_json_to_numpy(json_object["massFractions"]),
        ) # type:ignore 


class BinEdgesConverter(_ndjson.JsonConverter[BinEdges, np.void]):
    def __init__(self) -> None:
        self._edges_converter = _ndjson.NDArrayConverter(_ndjson.float32_converter, 1)
        super().__init__(np.dtype([
            ("edges", self._edges_converter.overall_dtype()),
        ]))

    def to_json(self, value: BinEdges) -> object:
        if not isinstance(value, BinEdges): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'BinEdges' instance")
        json_object = {}

        json_object["edges"] = self._edges_converter.to_json(value.edges)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["edges"] = self._edges_converter.numpy_to_json(value["edges"])
        return json_object

    def from_json(self, json_object: object) -> BinEdges:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return BinEdges(
            edges=self._edges_converter.from_json(json_object["edges"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._edges_converter.from_json_to_numpy(json_object["edges"]),
        ) # type:ignore 


singles_histogram_level_type_name_to_value_map = {
    "none": SinglesHistogramLevelType.NONE,
    "module": SinglesHistogramLevelType.MODULE,
    "all": SinglesHistogramLevelType.ALL,
}
singles_histogram_level_type_value_to_name_map = {v: n for n, v in singles_histogram_level_type_name_to_value_map.items()}

single_event_policy_name_to_value_map = {
    "all": SingleEventPolicy.ALL,
    "rejectIfNotInCoincidence": SingleEventPolicy.REJECT_IF_NOT_IN_COINCIDENCE,
    "other": SingleEventPolicy.OTHER,
}
single_event_policy_value_to_name_map = {v: n for n, v in single_event_policy_name_to_value_map.items()}

coincidence_policy_name_to_value_map = {
    "rejectHigherMultiples": CoincidencePolicy.REJECT_HIGHER_MULTIPLES,
    "multiplesAsAllCoincidences": CoincidencePolicy.MULTIPLES_AS_ALL_COINCIDENCES,
    "multiplesAsSequentialCoincidences": CoincidencePolicy.MULTIPLES_AS_SEQUENTIAL_COINCIDENCES,
    "other": CoincidencePolicy.OTHER,
}
coincidence_policy_value_to_name_map = {v: n for n, v in coincidence_policy_name_to_value_map.items()}

triple_event_policy_name_to_value_map = {
    "rejectHigherMultiples": TripleEventPolicy.REJECT_HIGHER_MULTIPLES,
    "other": TripleEventPolicy.OTHER,
}
triple_event_policy_value_to_name_map = {v: n for n, v in triple_event_policy_name_to_value_map.items()}

quadruple_event_policy_name_to_value_map = {
    "rejectHigherMultiples": QuadrupleEventPolicy.REJECT_HIGHER_MULTIPLES,
    "other": QuadrupleEventPolicy.OTHER,
}
quadruple_event_policy_value_to_name_map = {v: n for n, v in quadruple_event_policy_name_to_value_map.items()}

class ScannerInformationConverter(_ndjson.JsonConverter[ScannerInformation, np.void]):
    def __init__(self) -> None:
        self._model_name_converter = _ndjson.string_converter
        self._scanner_geometry_converter = ScannerGeometryConverter()
        self._bulk_materials_converter = _ndjson.VectorConverter(BulkMaterialConverter())
        self._gantry_alignment_converter = _ndjson.OptionalConverter(RigidTransformationConverter())
        self._tof_bin_edges_converter = _ndjson.VectorConverter(_ndjson.VectorConverter(BinEdgesConverter()))
        self._tof_resolution_converter = _ndjson.VectorConverter(_ndjson.VectorConverter(_ndjson.float32_converter))
        self._event_energy_bin_edges_converter = _ndjson.VectorConverter(BinEdgesConverter())
        self._energy_resolution_at_511_converter = _ndjson.VectorConverter(_ndjson.float32_converter)
        self._singles_histogram_level_converter = _ndjson.EnumConverter(SinglesHistogramLevelType, np.int32, singles_histogram_level_type_name_to_value_map, singles_histogram_level_type_value_to_name_map)
        self._singles_histogram_energy_bin_edges_converter = _ndjson.VectorConverter(BinEdgesConverter())
        self._single_event_policy_converter = _ndjson.EnumConverter(SingleEventPolicy, np.int32, single_event_policy_name_to_value_map, single_event_policy_value_to_name_map)
        self._prompt_event_policy_converter = _ndjson.EnumConverter(CoincidencePolicy, np.int32, coincidence_policy_name_to_value_map, coincidence_policy_value_to_name_map)
        self._delayed_event_policy_converter = _ndjson.EnumConverter(CoincidencePolicy, np.int32, coincidence_policy_name_to_value_map, coincidence_policy_value_to_name_map)
        self._triple_event_policy_converter = _ndjson.EnumConverter(TripleEventPolicy, np.int32, triple_event_policy_name_to_value_map, triple_event_policy_value_to_name_map)
        self._quadruple_event_policy_converter = _ndjson.EnumConverter(QuadrupleEventPolicy, np.int32, quadruple_event_policy_name_to_value_map, quadruple_event_policy_value_to_name_map)
        self._single_events_are_stored_converter = _ndjson.bool_converter
        self._prompt_events_are_stored_converter = _ndjson.bool_converter
        self._delayed_events_are_stored_converter = _ndjson.bool_converter
        self._triple_events_are_stored_converter = _ndjson.bool_converter
        self._quadruple_events_are_stored_converter = _ndjson.bool_converter
        self._detection_efficiencies_converter = DetectionEfficienciesConverter()
        super().__init__(np.dtype([
            ("model_name", self._model_name_converter.overall_dtype()),
            ("scanner_geometry", self._scanner_geometry_converter.overall_dtype()),
            ("bulk_materials", self._bulk_materials_converter.overall_dtype()),
            ("gantry_alignment", self._gantry_alignment_converter.overall_dtype()),
            ("tof_bin_edges", self._tof_bin_edges_converter.overall_dtype()),
            ("tof_resolution", self._tof_resolution_converter.overall_dtype()),
            ("event_energy_bin_edges", self._event_energy_bin_edges_converter.overall_dtype()),
            ("energy_resolution_at_511", self._energy_resolution_at_511_converter.overall_dtype()),
            ("singles_histogram_level", self._singles_histogram_level_converter.overall_dtype()),
            ("singles_histogram_energy_bin_edges", self._singles_histogram_energy_bin_edges_converter.overall_dtype()),
            ("single_event_policy", self._single_event_policy_converter.overall_dtype()),
            ("prompt_event_policy", self._prompt_event_policy_converter.overall_dtype()),
            ("delayed_event_policy", self._delayed_event_policy_converter.overall_dtype()),
            ("triple_event_policy", self._triple_event_policy_converter.overall_dtype()),
            ("quadruple_event_policy", self._quadruple_event_policy_converter.overall_dtype()),
            ("single_events_are_stored", self._single_events_are_stored_converter.overall_dtype()),
            ("prompt_events_are_stored", self._prompt_events_are_stored_converter.overall_dtype()),
            ("delayed_events_are_stored", self._delayed_events_are_stored_converter.overall_dtype()),
            ("triple_events_are_stored", self._triple_events_are_stored_converter.overall_dtype()),
            ("quadruple_events_are_stored", self._quadruple_events_are_stored_converter.overall_dtype()),
            ("detection_efficiencies", self._detection_efficiencies_converter.overall_dtype()),
        ]))

    def to_json(self, value: ScannerInformation) -> object:
        if not isinstance(value, ScannerInformation): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'ScannerInformation' instance")
        json_object = {}

        json_object["modelName"] = self._model_name_converter.to_json(value.model_name)
        json_object["scannerGeometry"] = self._scanner_geometry_converter.to_json(value.scanner_geometry)
        json_object["bulkMaterials"] = self._bulk_materials_converter.to_json(value.bulk_materials)
        if value.gantry_alignment is not None:
            json_object["gantryAlignment"] = self._gantry_alignment_converter.to_json(value.gantry_alignment)
        json_object["tofBinEdges"] = self._tof_bin_edges_converter.to_json(value.tof_bin_edges)
        json_object["tofResolution"] = self._tof_resolution_converter.to_json(value.tof_resolution)
        json_object["eventEnergyBinEdges"] = self._event_energy_bin_edges_converter.to_json(value.event_energy_bin_edges)
        json_object["energyResolutionAt511"] = self._energy_resolution_at_511_converter.to_json(value.energy_resolution_at_511)
        json_object["singlesHistogramLevel"] = self._singles_histogram_level_converter.to_json(value.singles_histogram_level)
        json_object["singlesHistogramEnergyBinEdges"] = self._singles_histogram_energy_bin_edges_converter.to_json(value.singles_histogram_energy_bin_edges)
        json_object["singleEventPolicy"] = self._single_event_policy_converter.to_json(value.single_event_policy)
        json_object["promptEventPolicy"] = self._prompt_event_policy_converter.to_json(value.prompt_event_policy)
        json_object["delayedEventPolicy"] = self._delayed_event_policy_converter.to_json(value.delayed_event_policy)
        json_object["tripleEventPolicy"] = self._triple_event_policy_converter.to_json(value.triple_event_policy)
        json_object["quadrupleEventPolicy"] = self._quadruple_event_policy_converter.to_json(value.quadruple_event_policy)
        json_object["singleEventsAreStored"] = self._single_events_are_stored_converter.to_json(value.single_events_are_stored)
        json_object["promptEventsAreStored"] = self._prompt_events_are_stored_converter.to_json(value.prompt_events_are_stored)
        json_object["delayedEventsAreStored"] = self._delayed_events_are_stored_converter.to_json(value.delayed_events_are_stored)
        json_object["tripleEventsAreStored"] = self._triple_events_are_stored_converter.to_json(value.triple_events_are_stored)
        json_object["quadrupleEventsAreStored"] = self._quadruple_events_are_stored_converter.to_json(value.quadruple_events_are_stored)
        json_object["detectionEfficiencies"] = self._detection_efficiencies_converter.to_json(value.detection_efficiencies)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["modelName"] = self._model_name_converter.numpy_to_json(value["model_name"])
        json_object["scannerGeometry"] = self._scanner_geometry_converter.numpy_to_json(value["scanner_geometry"])
        json_object["bulkMaterials"] = self._bulk_materials_converter.numpy_to_json(value["bulk_materials"])
        if (field_val := value["gantry_alignment"]) is not None:
            json_object["gantryAlignment"] = self._gantry_alignment_converter.numpy_to_json(field_val)
        json_object["tofBinEdges"] = self._tof_bin_edges_converter.numpy_to_json(value["tof_bin_edges"])
        json_object["tofResolution"] = self._tof_resolution_converter.numpy_to_json(value["tof_resolution"])
        json_object["eventEnergyBinEdges"] = self._event_energy_bin_edges_converter.numpy_to_json(value["event_energy_bin_edges"])
        json_object["energyResolutionAt511"] = self._energy_resolution_at_511_converter.numpy_to_json(value["energy_resolution_at_511"])
        json_object["singlesHistogramLevel"] = self._singles_histogram_level_converter.numpy_to_json(value["singles_histogram_level"])
        json_object["singlesHistogramEnergyBinEdges"] = self._singles_histogram_energy_bin_edges_converter.numpy_to_json(value["singles_histogram_energy_bin_edges"])
        json_object["singleEventPolicy"] = self._single_event_policy_converter.numpy_to_json(value["single_event_policy"])
        json_object["promptEventPolicy"] = self._prompt_event_policy_converter.numpy_to_json(value["prompt_event_policy"])
        json_object["delayedEventPolicy"] = self._delayed_event_policy_converter.numpy_to_json(value["delayed_event_policy"])
        json_object["tripleEventPolicy"] = self._triple_event_policy_converter.numpy_to_json(value["triple_event_policy"])
        json_object["quadrupleEventPolicy"] = self._quadruple_event_policy_converter.numpy_to_json(value["quadruple_event_policy"])
        json_object["singleEventsAreStored"] = self._single_events_are_stored_converter.numpy_to_json(value["single_events_are_stored"])
        json_object["promptEventsAreStored"] = self._prompt_events_are_stored_converter.numpy_to_json(value["prompt_events_are_stored"])
        json_object["delayedEventsAreStored"] = self._delayed_events_are_stored_converter.numpy_to_json(value["delayed_events_are_stored"])
        json_object["tripleEventsAreStored"] = self._triple_events_are_stored_converter.numpy_to_json(value["triple_events_are_stored"])
        json_object["quadrupleEventsAreStored"] = self._quadruple_events_are_stored_converter.numpy_to_json(value["quadruple_events_are_stored"])
        json_object["detectionEfficiencies"] = self._detection_efficiencies_converter.numpy_to_json(value["detection_efficiencies"])
        return json_object

    def from_json(self, json_object: object) -> ScannerInformation:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return ScannerInformation(
            model_name=self._model_name_converter.from_json(json_object["modelName"],),
            scanner_geometry=self._scanner_geometry_converter.from_json(json_object["scannerGeometry"],),
            bulk_materials=self._bulk_materials_converter.from_json(json_object["bulkMaterials"],),
            gantry_alignment=self._gantry_alignment_converter.from_json(json_object.get("gantryAlignment")),
            tof_bin_edges=self._tof_bin_edges_converter.from_json(json_object["tofBinEdges"],),
            tof_resolution=self._tof_resolution_converter.from_json(json_object["tofResolution"],),
            event_energy_bin_edges=self._event_energy_bin_edges_converter.from_json(json_object["eventEnergyBinEdges"],),
            energy_resolution_at_511=self._energy_resolution_at_511_converter.from_json(json_object["energyResolutionAt511"],),
            singles_histogram_level=self._singles_histogram_level_converter.from_json(json_object["singlesHistogramLevel"],),
            singles_histogram_energy_bin_edges=self._singles_histogram_energy_bin_edges_converter.from_json(json_object["singlesHistogramEnergyBinEdges"],),
            single_event_policy=self._single_event_policy_converter.from_json(json_object["singleEventPolicy"],),
            prompt_event_policy=self._prompt_event_policy_converter.from_json(json_object["promptEventPolicy"],),
            delayed_event_policy=self._delayed_event_policy_converter.from_json(json_object["delayedEventPolicy"],),
            triple_event_policy=self._triple_event_policy_converter.from_json(json_object["tripleEventPolicy"],),
            quadruple_event_policy=self._quadruple_event_policy_converter.from_json(json_object["quadrupleEventPolicy"],),
            single_events_are_stored=self._single_events_are_stored_converter.from_json(json_object["singleEventsAreStored"],),
            prompt_events_are_stored=self._prompt_events_are_stored_converter.from_json(json_object["promptEventsAreStored"],),
            delayed_events_are_stored=self._delayed_events_are_stored_converter.from_json(json_object["delayedEventsAreStored"],),
            triple_events_are_stored=self._triple_events_are_stored_converter.from_json(json_object["tripleEventsAreStored"],),
            quadruple_events_are_stored=self._quadruple_events_are_stored_converter.from_json(json_object["quadrupleEventsAreStored"],),
            detection_efficiencies=self._detection_efficiencies_converter.from_json(json_object["detectionEfficiencies"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._model_name_converter.from_json_to_numpy(json_object["modelName"]),
            self._scanner_geometry_converter.from_json_to_numpy(json_object["scannerGeometry"]),
            self._bulk_materials_converter.from_json_to_numpy(json_object["bulkMaterials"]),
            self._gantry_alignment_converter.from_json_to_numpy(json_object.get("gantryAlignment")),
            self._tof_bin_edges_converter.from_json_to_numpy(json_object["tofBinEdges"]),
            self._tof_resolution_converter.from_json_to_numpy(json_object["tofResolution"]),
            self._event_energy_bin_edges_converter.from_json_to_numpy(json_object["eventEnergyBinEdges"]),
            self._energy_resolution_at_511_converter.from_json_to_numpy(json_object["energyResolutionAt511"]),
            self._singles_histogram_level_converter.from_json_to_numpy(json_object["singlesHistogramLevel"]),
            self._singles_histogram_energy_bin_edges_converter.from_json_to_numpy(json_object["singlesHistogramEnergyBinEdges"]),
            self._single_event_policy_converter.from_json_to_numpy(json_object["singleEventPolicy"]),
            self._prompt_event_policy_converter.from_json_to_numpy(json_object["promptEventPolicy"]),
            self._delayed_event_policy_converter.from_json_to_numpy(json_object["delayedEventPolicy"]),
            self._triple_event_policy_converter.from_json_to_numpy(json_object["tripleEventPolicy"]),
            self._quadruple_event_policy_converter.from_json_to_numpy(json_object["quadrupleEventPolicy"]),
            self._single_events_are_stored_converter.from_json_to_numpy(json_object["singleEventsAreStored"]),
            self._prompt_events_are_stored_converter.from_json_to_numpy(json_object["promptEventsAreStored"]),
            self._delayed_events_are_stored_converter.from_json_to_numpy(json_object["delayedEventsAreStored"]),
            self._triple_events_are_stored_converter.from_json_to_numpy(json_object["tripleEventsAreStored"]),
            self._quadruple_events_are_stored_converter.from_json_to_numpy(json_object["quadrupleEventsAreStored"]),
            self._detection_efficiencies_converter.from_json_to_numpy(json_object["detectionEfficiencies"]),
        ) # type:ignore 


class HeaderConverter(_ndjson.JsonConverter[Header, np.void]):
    def __init__(self) -> None:
        self._scanner_converter = ScannerInformationConverter()
        self._exam_converter = _ndjson.OptionalConverter(ExamInformationConverter())
        super().__init__(np.dtype([
            ("scanner", self._scanner_converter.overall_dtype()),
            ("exam", self._exam_converter.overall_dtype()),
        ]))

    def to_json(self, value: Header) -> object:
        if not isinstance(value, Header): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'Header' instance")
        json_object = {}

        json_object["scanner"] = self._scanner_converter.to_json(value.scanner)
        if value.exam is not None:
            json_object["exam"] = self._exam_converter.to_json(value.exam)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["scanner"] = self._scanner_converter.numpy_to_json(value["scanner"])
        if (field_val := value["exam"]) is not None:
            json_object["exam"] = self._exam_converter.numpy_to_json(field_val)
        return json_object

    def from_json(self, json_object: object) -> Header:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return Header(
            scanner=self._scanner_converter.from_json(json_object["scanner"],),
            exam=self._exam_converter.from_json(json_object.get("exam")),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._scanner_converter.from_json_to_numpy(json_object["scanner"]),
            self._exam_converter.from_json_to_numpy(json_object.get("exam")),
        ) # type:ignore 


class TimeIntervalConverter(_ndjson.JsonConverter[TimeInterval, np.void]):
    def __init__(self) -> None:
        self._start_converter = _ndjson.uint32_converter
        self._stop_converter = _ndjson.uint32_converter
        super().__init__(np.dtype([
            ("start", self._start_converter.overall_dtype()),
            ("stop", self._stop_converter.overall_dtype()),
        ]))

    def to_json(self, value: TimeInterval) -> object:
        if not isinstance(value, TimeInterval): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'TimeInterval' instance")
        json_object = {}

        json_object["start"] = self._start_converter.to_json(value.start)
        json_object["stop"] = self._stop_converter.to_json(value.stop)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["start"] = self._start_converter.numpy_to_json(value["start"])
        json_object["stop"] = self._stop_converter.numpy_to_json(value["stop"])
        return json_object

    def from_json(self, json_object: object) -> TimeInterval:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return TimeInterval(
            start=self._start_converter.from_json(json_object["start"],),
            stop=self._stop_converter.from_json(json_object["stop"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._start_converter.from_json_to_numpy(json_object["start"]),
            self._stop_converter.from_json_to_numpy(json_object["stop"]),
        ) # type:ignore 


class EventTimeBlockConverter(_ndjson.JsonConverter[EventTimeBlock, np.void]):
    def __init__(self) -> None:
        self._time_interval_converter = TimeIntervalConverter()
        self._single_events_converter = _ndjson.VectorConverter(_ndjson.VectorConverter(SingleEventConverter()))
        self._prompt_events_converter = _ndjson.VectorConverter(_ndjson.VectorConverter(_ndjson.VectorConverter(CoincidenceEventConverter())))
        self._delayed_events_converter = _ndjson.VectorConverter(_ndjson.VectorConverter(_ndjson.VectorConverter(CoincidenceEventConverter())))
        self._triple_events_converter = _ndjson.VectorConverter(_ndjson.VectorConverter(_ndjson.VectorConverter(_ndjson.VectorConverter(TripleEventConverter()))))
        self._quadruple_events_converter = _ndjson.VectorConverter(_ndjson.VectorConverter(_ndjson.VectorConverter(_ndjson.VectorConverter(_ndjson.VectorConverter(TripleEventConverter())))))
        super().__init__(np.dtype([
            ("time_interval", self._time_interval_converter.overall_dtype()),
            ("single_events", self._single_events_converter.overall_dtype()),
            ("prompt_events", self._prompt_events_converter.overall_dtype()),
            ("delayed_events", self._delayed_events_converter.overall_dtype()),
            ("triple_events", self._triple_events_converter.overall_dtype()),
            ("quadruple_events", self._quadruple_events_converter.overall_dtype()),
        ]))

    def to_json(self, value: EventTimeBlock) -> object:
        if not isinstance(value, EventTimeBlock): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'EventTimeBlock' instance")
        json_object = {}

        json_object["timeInterval"] = self._time_interval_converter.to_json(value.time_interval)
        json_object["singleEvents"] = self._single_events_converter.to_json(value.single_events)
        json_object["promptEvents"] = self._prompt_events_converter.to_json(value.prompt_events)
        json_object["delayedEvents"] = self._delayed_events_converter.to_json(value.delayed_events)
        json_object["tripleEvents"] = self._triple_events_converter.to_json(value.triple_events)
        json_object["quadrupleEvents"] = self._quadruple_events_converter.to_json(value.quadruple_events)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["timeInterval"] = self._time_interval_converter.numpy_to_json(value["time_interval"])
        json_object["singleEvents"] = self._single_events_converter.numpy_to_json(value["single_events"])
        json_object["promptEvents"] = self._prompt_events_converter.numpy_to_json(value["prompt_events"])
        json_object["delayedEvents"] = self._delayed_events_converter.numpy_to_json(value["delayed_events"])
        json_object["tripleEvents"] = self._triple_events_converter.numpy_to_json(value["triple_events"])
        json_object["quadrupleEvents"] = self._quadruple_events_converter.numpy_to_json(value["quadruple_events"])
        return json_object

    def from_json(self, json_object: object) -> EventTimeBlock:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return EventTimeBlock(
            time_interval=self._time_interval_converter.from_json(json_object["timeInterval"],),
            single_events=self._single_events_converter.from_json(json_object["singleEvents"],),
            prompt_events=self._prompt_events_converter.from_json(json_object["promptEvents"],),
            delayed_events=self._delayed_events_converter.from_json(json_object["delayedEvents"],),
            triple_events=self._triple_events_converter.from_json(json_object["tripleEvents"],),
            quadruple_events=self._quadruple_events_converter.from_json(json_object["quadrupleEvents"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._time_interval_converter.from_json_to_numpy(json_object["timeInterval"]),
            self._single_events_converter.from_json_to_numpy(json_object["singleEvents"]),
            self._prompt_events_converter.from_json_to_numpy(json_object["promptEvents"]),
            self._delayed_events_converter.from_json_to_numpy(json_object["delayedEvents"]),
            self._triple_events_converter.from_json_to_numpy(json_object["tripleEvents"]),
            self._quadruple_events_converter.from_json_to_numpy(json_object["quadrupleEvents"]),
        ) # type:ignore 


class ExternalSignalTimeBlockConverter(_ndjson.JsonConverter[ExternalSignalTimeBlock, np.void]):
    def __init__(self) -> None:
        self._time_interval_converter = TimeIntervalConverter()
        self._signal_id_converter = _ndjson.uint32_converter
        self._signal_values_converter = _ndjson.VectorConverter(_ndjson.float32_converter)
        super().__init__(np.dtype([
            ("time_interval", self._time_interval_converter.overall_dtype()),
            ("signal_id", self._signal_id_converter.overall_dtype()),
            ("signal_values", self._signal_values_converter.overall_dtype()),
        ]))

    def to_json(self, value: ExternalSignalTimeBlock) -> object:
        if not isinstance(value, ExternalSignalTimeBlock): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'ExternalSignalTimeBlock' instance")
        json_object = {}

        json_object["timeInterval"] = self._time_interval_converter.to_json(value.time_interval)
        json_object["signalID"] = self._signal_id_converter.to_json(value.signal_id)
        json_object["signalValues"] = self._signal_values_converter.to_json(value.signal_values)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["timeInterval"] = self._time_interval_converter.numpy_to_json(value["time_interval"])
        json_object["signalID"] = self._signal_id_converter.numpy_to_json(value["signal_id"])
        json_object["signalValues"] = self._signal_values_converter.numpy_to_json(value["signal_values"])
        return json_object

    def from_json(self, json_object: object) -> ExternalSignalTimeBlock:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return ExternalSignalTimeBlock(
            time_interval=self._time_interval_converter.from_json(json_object["timeInterval"],),
            signal_id=self._signal_id_converter.from_json(json_object["signalID"],),
            signal_values=self._signal_values_converter.from_json(json_object["signalValues"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._time_interval_converter.from_json_to_numpy(json_object["timeInterval"]),
            self._signal_id_converter.from_json_to_numpy(json_object["signalID"]),
            self._signal_values_converter.from_json_to_numpy(json_object["signalValues"]),
        ) # type:ignore 


class BedMovementTimeBlockConverter(_ndjson.JsonConverter[BedMovementTimeBlock, np.void]):
    def __init__(self) -> None:
        self._time_interval_converter = TimeIntervalConverter()
        self._transform_converter = RigidTransformationConverter()
        super().__init__(np.dtype([
            ("time_interval", self._time_interval_converter.overall_dtype()),
            ("transform", self._transform_converter.overall_dtype()),
        ]))

    def to_json(self, value: BedMovementTimeBlock) -> object:
        if not isinstance(value, BedMovementTimeBlock): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'BedMovementTimeBlock' instance")
        json_object = {}

        json_object["timeInterval"] = self._time_interval_converter.to_json(value.time_interval)
        json_object["transform"] = self._transform_converter.to_json(value.transform)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["timeInterval"] = self._time_interval_converter.numpy_to_json(value["time_interval"])
        json_object["transform"] = self._transform_converter.numpy_to_json(value["transform"])
        return json_object

    def from_json(self, json_object: object) -> BedMovementTimeBlock:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return BedMovementTimeBlock(
            time_interval=self._time_interval_converter.from_json(json_object["timeInterval"],),
            transform=self._transform_converter.from_json(json_object["transform"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._time_interval_converter.from_json_to_numpy(json_object["timeInterval"]),
            self._transform_converter.from_json_to_numpy(json_object["transform"]),
        ) # type:ignore 


class GantryMovementTimeBlockConverter(_ndjson.JsonConverter[GantryMovementTimeBlock, np.void]):
    def __init__(self) -> None:
        self._time_interval_converter = TimeIntervalConverter()
        self._transform_converter = RigidTransformationConverter()
        super().__init__(np.dtype([
            ("time_interval", self._time_interval_converter.overall_dtype()),
            ("transform", self._transform_converter.overall_dtype()),
        ]))

    def to_json(self, value: GantryMovementTimeBlock) -> object:
        if not isinstance(value, GantryMovementTimeBlock): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'GantryMovementTimeBlock' instance")
        json_object = {}

        json_object["timeInterval"] = self._time_interval_converter.to_json(value.time_interval)
        json_object["transform"] = self._transform_converter.to_json(value.transform)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["timeInterval"] = self._time_interval_converter.numpy_to_json(value["time_interval"])
        json_object["transform"] = self._transform_converter.numpy_to_json(value["transform"])
        return json_object

    def from_json(self, json_object: object) -> GantryMovementTimeBlock:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return GantryMovementTimeBlock(
            time_interval=self._time_interval_converter.from_json(json_object["timeInterval"],),
            transform=self._transform_converter.from_json(json_object["transform"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._time_interval_converter.from_json_to_numpy(json_object["timeInterval"]),
            self._transform_converter.from_json_to_numpy(json_object["transform"]),
        ) # type:ignore 


class DeadTimeTimeBlockConverter(_ndjson.JsonConverter[DeadTimeTimeBlock, np.void]):
    def __init__(self) -> None:
        self._time_interval_converter = TimeIntervalConverter()
        self._alive_time_fractions_converter = AliveTimeFractionsConverter()
        super().__init__(np.dtype([
            ("time_interval", self._time_interval_converter.overall_dtype()),
            ("alive_time_fractions", self._alive_time_fractions_converter.overall_dtype()),
        ]))

    def to_json(self, value: DeadTimeTimeBlock) -> object:
        if not isinstance(value, DeadTimeTimeBlock): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'DeadTimeTimeBlock' instance")
        json_object = {}

        json_object["timeInterval"] = self._time_interval_converter.to_json(value.time_interval)
        json_object["aliveTimeFractions"] = self._alive_time_fractions_converter.to_json(value.alive_time_fractions)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["timeInterval"] = self._time_interval_converter.numpy_to_json(value["time_interval"])
        json_object["aliveTimeFractions"] = self._alive_time_fractions_converter.numpy_to_json(value["alive_time_fractions"])
        return json_object

    def from_json(self, json_object: object) -> DeadTimeTimeBlock:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return DeadTimeTimeBlock(
            time_interval=self._time_interval_converter.from_json(json_object["timeInterval"],),
            alive_time_fractions=self._alive_time_fractions_converter.from_json(json_object["aliveTimeFractions"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._time_interval_converter.from_json_to_numpy(json_object["timeInterval"]),
            self._alive_time_fractions_converter.from_json_to_numpy(json_object["aliveTimeFractions"]),
        ) # type:ignore 


class SinglesHistogramTimeBlockConverter(_ndjson.JsonConverter[SinglesHistogramTimeBlock, np.void]):
    def __init__(self) -> None:
        self._time_interval_converter = TimeIntervalConverter()
        self._singles_histograms_converter = _ndjson.VectorConverter(_ndjson.NDArrayConverter(_ndjson.uint64_converter, 1))
        super().__init__(np.dtype([
            ("time_interval", self._time_interval_converter.overall_dtype()),
            ("singles_histograms", self._singles_histograms_converter.overall_dtype()),
        ]))

    def to_json(self, value: SinglesHistogramTimeBlock) -> object:
        if not isinstance(value, SinglesHistogramTimeBlock): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'SinglesHistogramTimeBlock' instance")
        json_object = {}

        json_object["timeInterval"] = self._time_interval_converter.to_json(value.time_interval)
        json_object["singlesHistograms"] = self._singles_histograms_converter.to_json(value.singles_histograms)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["timeInterval"] = self._time_interval_converter.numpy_to_json(value["time_interval"])
        json_object["singlesHistograms"] = self._singles_histograms_converter.numpy_to_json(value["singles_histograms"])
        return json_object

    def from_json(self, json_object: object) -> SinglesHistogramTimeBlock:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return SinglesHistogramTimeBlock(
            time_interval=self._time_interval_converter.from_json(json_object["timeInterval"],),
            singles_histograms=self._singles_histograms_converter.from_json(json_object["singlesHistograms"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._time_interval_converter.from_json_to_numpy(json_object["timeInterval"]),
            self._singles_histograms_converter.from_json_to_numpy(json_object["singlesHistograms"]),
        ) # type:ignore 


class TimeFrameInformationConverter(_ndjson.JsonConverter[TimeFrameInformation, np.void]):
    def __init__(self) -> None:
        self._time_frames_converter = _ndjson.VectorConverter(TimeIntervalConverter())
        super().__init__(np.dtype([
            ("time_frames", self._time_frames_converter.overall_dtype()),
        ]))

    def to_json(self, value: TimeFrameInformation) -> object:
        if not isinstance(value, TimeFrameInformation): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'TimeFrameInformation' instance")
        json_object = {}

        json_object["timeFrames"] = self._time_frames_converter.to_json(value.time_frames)
        return json_object

    def numpy_to_json(self, value: np.void) -> object:
        if not isinstance(value, np.void): # pyright: ignore [reportUnnecessaryIsInstance]
            raise TypeError("Expected 'np.void' instance")
        json_object = {}

        json_object["timeFrames"] = self._time_frames_converter.numpy_to_json(value["time_frames"])
        return json_object

    def from_json(self, json_object: object) -> TimeFrameInformation:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return TimeFrameInformation(
            time_frames=self._time_frames_converter.from_json(json_object["timeFrames"],),
        )

    def from_json_to_numpy(self, json_object: object) -> np.void:
        if not isinstance(json_object, dict):
            raise TypeError("Expected 'dict' instance")
        return (
            self._time_frames_converter.from_json_to_numpy(json_object["timeFrames"]),
        ) # type:ignore 


class NDJsonPETSIRDWriter(_ndjson.NDJsonProtocolWriter, PETSIRDWriterBase):
    """NDJson writer for the PETSIRD protocol.

    Definition of the stream of data
    """


    def __init__(self, stream: typing.Union[typing.TextIO, str]) -> None:
        PETSIRDWriterBase.__init__(self)
        _ndjson.NDJsonProtocolWriter.__init__(self, stream, PETSIRDWriterBase.schema)

    def _write_header(self, value: Header) -> None:
        converter = HeaderConverter()
        json_value = converter.to_json(value)
        self._write_json_line({"header": json_value})

    def _write_time_blocks(self, value: collections.abc.Iterable[TimeBlock]) -> None:
        converter = _ndjson.UnionConverter(TimeBlock, [(TimeBlock.EventTimeBlock, EventTimeBlockConverter(), [dict]), (TimeBlock.ExternalSignalTimeBlock, ExternalSignalTimeBlockConverter(), [dict]), (TimeBlock.BedMovementTimeBlock, BedMovementTimeBlockConverter(), [dict]), (TimeBlock.GantryMovementTimeBlock, GantryMovementTimeBlockConverter(), [dict]), (TimeBlock.DeadTimeTimeBlock, DeadTimeTimeBlockConverter(), [dict]), (TimeBlock.SinglesHistogramTimeBlock, SinglesHistogramTimeBlockConverter(), [dict])], False)
        for item in value:
            json_item = converter.to_json(item)
            self._write_json_line({"timeBlocks": json_item})


class NDJsonPETSIRDReader(_ndjson.NDJsonProtocolReader, PETSIRDReaderBase):
    """NDJson writer for the PETSIRD protocol.

    Definition of the stream of data
    """


    def __init__(self, stream: typing.Union[io.BufferedReader, typing.TextIO, str]) -> None:
        PETSIRDReaderBase.__init__(self)
        _ndjson.NDJsonProtocolReader.__init__(self, stream, PETSIRDReaderBase.schema)

    def _read_header(self) -> Header:
        json_object = self._read_json_line("header", True)
        converter = HeaderConverter()
        return converter.from_json(json_object)

    def _read_time_blocks(self) -> collections.abc.Iterable[TimeBlock]:
        converter = _ndjson.UnionConverter(TimeBlock, [(TimeBlock.EventTimeBlock, EventTimeBlockConverter(), [dict]), (TimeBlock.ExternalSignalTimeBlock, ExternalSignalTimeBlockConverter(), [dict]), (TimeBlock.BedMovementTimeBlock, BedMovementTimeBlockConverter(), [dict]), (TimeBlock.GantryMovementTimeBlock, GantryMovementTimeBlockConverter(), [dict]), (TimeBlock.DeadTimeTimeBlock, DeadTimeTimeBlockConverter(), [dict]), (TimeBlock.SinglesHistogramTimeBlock, SinglesHistogramTimeBlockConverter(), [dict])], False)
        while (json_object := self._read_json_line("timeBlocks", False)) is not _ndjson.MISSING_SENTINEL:
            yield converter.from_json(json_object)

