From de629e7f2286e2ed7480d3db074ea712aa7bd706 Mon Sep 17 00:00:00 2001 From: Joe Naegele Date: Fri, 13 Dec 2024 15:05:36 +0000 Subject: [PATCH 1/2] Implement MATLAB generator and analysis tools --- .../+petsird/+binary/AnnulusShapeSerializer.m | 27 ++ matlab/+petsird/+binary/AtomSerializer.m | 25 ++ .../+binary/BedMovementTimeBlockSerializer.m | 25 ++ matlab/+petsird/+binary/BoxShapeSerializer.m | 24 ++ .../+petsird/+binary/BulkMaterialSerializer.m | 28 +++ .../+binary/CoincidenceEventSerializer.m | 26 ++ .../+petsird/+binary/CoordinateSerializer.m | 24 ++ .../+binary/DeadTimeTimeBlockSerializer.m | 26 ++ .../+binary/DetectionEfficienciesSerializer.m | 26 ++ .../+binary/DetectorModuleSerializer.m | 26 ++ .../+binary/DirectionMatrixSerializer.m | 24 ++ matlab/+petsird/+binary/DirectionSerializer.m | 24 ++ .../+binary/EventTimeBlockSerializer.m | 27 ++ .../+binary/ExamInformationSerializer.m | 27 ++ .../ExternalSignalTimeBlockSerializer.m | 26 ++ .../+binary/ExternalSignalTypeSerializer.m | 26 ++ .../GantryMovementTimeBlockSerializer.m | 25 ++ matlab/+petsird/+binary/HeaderSerializer.m | 25 ++ .../+petsird/+binary/InstitutionSerializer.m | 25 ++ .../ModulePairEfficienciesSerializer.m | 25 ++ matlab/+petsird/+binary/PETSIRDReader.m | 33 +++ matlab/+petsird/+binary/PETSIRDWriter.m | 29 +++ .../+binary/ReplicatedObjectSerializer.m | 26 ++ .../+binary/RigidTransformationSerializer.m | 24 ++ .../+binary/ScannerGeometrySerializer.m | 26 ++ .../+binary/ScannerInformationSerializer.m | 34 +++ .../+petsird/+binary/SolidVolumeSerializer.m | 25 ++ matlab/+petsird/+binary/SubjectSerializer.m | 25 ++ .../+binary/TimeFrameInformationSerializer.m | 24 ++ .../+petsird/+binary/TimeIntervalSerializer.m | 25 ++ .../+petsird/+binary/TripleEventSerializer.m | 26 ++ .../+helpers/get_detection_efficiency.m | 37 +++ .../+helpers/get_module_and_element.m | 16 ++ .../+helpers/get_num_detecting_elements.m | 18 ++ matlab/+petsird/AnnulusShape.m | 63 +++++ matlab/+petsird/Atom.m | 52 ++++ matlab/+petsird/BedMovementTimeBlock.m | 50 ++++ matlab/+petsird/BoxShape.m | 51 ++++ matlab/+petsird/BoxSolidVolume.m | 4 + matlab/+petsird/BulkMaterial.m | 75 ++++++ matlab/+petsird/CoincidenceEvent.m | 58 +++++ matlab/+petsird/CoincidencePolicy.m | 35 +++ matlab/+petsird/Coordinate.m | 46 ++++ matlab/+petsird/DeadTimeTimeBlock.m | 76 ++++++ matlab/+petsird/DetectionEfficiencies.m | 82 +++++++ matlab/+petsird/DetectorModule.m | 59 +++++ matlab/+petsird/Direction.m | 46 ++++ matlab/+petsird/DirectionMatrix.m | 47 ++++ matlab/+petsird/EventTimeBlock.m | 64 +++++ matlab/+petsird/ExamInformation.m | 58 +++++ matlab/+petsird/ExternalSignalTimeBlock.m | 56 +++++ matlab/+petsird/ExternalSignalType.m | 53 ++++ matlab/+petsird/ExternalSignalTypeEnum.m | 44 ++++ matlab/+petsird/GantryMovementTimeBlock.m | 50 ++++ matlab/+petsird/GenericSolidVolume.m | 4 + matlab/+petsird/GeometricShape.m | 49 ++++ matlab/+petsird/Header.m | 49 ++++ matlab/+petsird/Institution.m | 49 ++++ matlab/+petsird/ModulePairEfficiencies.m | 56 +++++ matlab/+petsird/PETSIRDReaderBase.m | 93 +++++++ matlab/+petsird/PETSIRDWriterBase.m | 83 +++++++ matlab/+petsird/ReplicatedBoxSolidVolume.m | 5 + matlab/+petsird/ReplicatedDetectorModule.m | 5 + .../+petsird/ReplicatedGenericSolidVolume.m | 5 + matlab/+petsird/ReplicatedObject.m | 67 +++++ matlab/+petsird/RigidTransformation.m | 48 ++++ matlab/+petsird/ScannerGeometry.m | 59 +++++ matlab/+petsird/ScannerInformation.m | 117 +++++++++ matlab/+petsird/SolidVolume.m | 54 ++++ matlab/+petsird/Subject.m | 49 ++++ matlab/+petsird/TimeBlock.m | 65 +++++ matlab/+petsird/TimeFrameInformation.m | 52 ++++ matlab/+petsird/TimeInterval.m | 50 ++++ matlab/+petsird/TripleEvent.m | 59 +++++ matlab/+yardl/+binary/BinaryProtocolReader.m | 40 +++ matlab/+yardl/+binary/BinaryProtocolWriter.m | 37 +++ matlab/+yardl/+binary/BoolSerializer.m | 28 +++ .../+binary/CURRENT_BINARY_FORMAT_VERSION.m | 6 + matlab/+yardl/+binary/CodedInputStream.m | 74 ++++++ matlab/+yardl/+binary/CodedOutputStream.m | 84 +++++++ .../+yardl/+binary/Complexfloat32Serializer.m | 49 ++++ .../+yardl/+binary/Complexfloat64Serializer.m | 49 ++++ matlab/+yardl/+binary/DateSerializer.m | 26 ++ matlab/+yardl/+binary/DatetimeSerializer.m | 26 ++ .../+yardl/+binary/DynamicNDArraySerializer.m | 47 ++++ matlab/+yardl/+binary/EnumSerializer.m | 43 ++++ .../+yardl/+binary/FixedNDArraySerializer.m | 72 ++++++ matlab/+yardl/+binary/FixedVectorSerializer.m | 51 ++++ matlab/+yardl/+binary/Float32Serializer.m | 29 +++ matlab/+yardl/+binary/Float64Serializer.m | 28 +++ matlab/+yardl/+binary/Int16Serializer.m | 22 ++ matlab/+yardl/+binary/Int32Serializer.m | 22 ++ matlab/+yardl/+binary/Int64Serializer.m | 22 ++ matlab/+yardl/+binary/Int8Serializer.m | 27 ++ matlab/+yardl/+binary/MAGIC_BYTES.m | 6 + matlab/+yardl/+binary/MapSerializer.m | 51 ++++ matlab/+yardl/+binary/NDArraySerializer.m | 51 ++++ matlab/+yardl/+binary/NDArraySerializerBase.m | 106 ++++++++ matlab/+yardl/+binary/NoneSerializer.m | 17 ++ matlab/+yardl/+binary/OptionalSerializer.m | 43 ++++ matlab/+yardl/+binary/RecordSerializer.m | 39 +++ matlab/+yardl/+binary/SizeSerializer.m | 5 + matlab/+yardl/+binary/StreamSerializer.m | 79 ++++++ matlab/+yardl/+binary/StringSerializer.m | 26 ++ matlab/+yardl/+binary/TimeSerializer.m | 27 ++ matlab/+yardl/+binary/TypeSerializer.m | 36 +++ matlab/+yardl/+binary/Uint16Serializer.m | 22 ++ matlab/+yardl/+binary/Uint32Serializer.m | 22 ++ matlab/+yardl/+binary/Uint64Serializer.m | 22 ++ matlab/+yardl/+binary/Uint8Serializer.m | 26 ++ matlab/+yardl/+binary/UnionSerializer.m | 81 ++++++ matlab/+yardl/+binary/VectorSerializer.m | 25 ++ matlab/+yardl/+binary/VectorSerializerBase.m | 95 +++++++ matlab/+yardl/Date.m | 70 ++++++ matlab/+yardl/DateTime.m | 81 ++++++ matlab/+yardl/Exception.m | 6 + matlab/+yardl/Map.m | 73 ++++++ matlab/+yardl/None.m | 6 + matlab/+yardl/Optional.m | 83 +++++++ matlab/+yardl/ProtocolError.m | 6 + matlab/+yardl/RuntimeError.m | 6 + matlab/+yardl/Time.m | 90 +++++++ matlab/+yardl/TypeError.m | 6 + matlab/+yardl/Union.m | 41 ++++ matlab/+yardl/ValueError.m | 6 + matlab/+yardl/allocate.m | 11 + matlab/+yardl/dimension_count.m | 9 + matlab/petsird_analysis.m | 80 ++++++ matlab/petsird_generator.m | 232 ++++++++++++++++++ model/_package.yml | 3 + 130 files changed, 5336 insertions(+) create mode 100644 matlab/+petsird/+binary/AnnulusShapeSerializer.m create mode 100644 matlab/+petsird/+binary/AtomSerializer.m create mode 100644 matlab/+petsird/+binary/BedMovementTimeBlockSerializer.m create mode 100644 matlab/+petsird/+binary/BoxShapeSerializer.m create mode 100644 matlab/+petsird/+binary/BulkMaterialSerializer.m create mode 100644 matlab/+petsird/+binary/CoincidenceEventSerializer.m create mode 100644 matlab/+petsird/+binary/CoordinateSerializer.m create mode 100644 matlab/+petsird/+binary/DeadTimeTimeBlockSerializer.m create mode 100644 matlab/+petsird/+binary/DetectionEfficienciesSerializer.m create mode 100644 matlab/+petsird/+binary/DetectorModuleSerializer.m create mode 100644 matlab/+petsird/+binary/DirectionMatrixSerializer.m create mode 100644 matlab/+petsird/+binary/DirectionSerializer.m create mode 100644 matlab/+petsird/+binary/EventTimeBlockSerializer.m create mode 100644 matlab/+petsird/+binary/ExamInformationSerializer.m create mode 100644 matlab/+petsird/+binary/ExternalSignalTimeBlockSerializer.m create mode 100644 matlab/+petsird/+binary/ExternalSignalTypeSerializer.m create mode 100644 matlab/+petsird/+binary/GantryMovementTimeBlockSerializer.m create mode 100644 matlab/+petsird/+binary/HeaderSerializer.m create mode 100644 matlab/+petsird/+binary/InstitutionSerializer.m create mode 100644 matlab/+petsird/+binary/ModulePairEfficienciesSerializer.m create mode 100644 matlab/+petsird/+binary/PETSIRDReader.m create mode 100644 matlab/+petsird/+binary/PETSIRDWriter.m create mode 100644 matlab/+petsird/+binary/ReplicatedObjectSerializer.m create mode 100644 matlab/+petsird/+binary/RigidTransformationSerializer.m create mode 100644 matlab/+petsird/+binary/ScannerGeometrySerializer.m create mode 100644 matlab/+petsird/+binary/ScannerInformationSerializer.m create mode 100644 matlab/+petsird/+binary/SolidVolumeSerializer.m create mode 100644 matlab/+petsird/+binary/SubjectSerializer.m create mode 100644 matlab/+petsird/+binary/TimeFrameInformationSerializer.m create mode 100644 matlab/+petsird/+binary/TimeIntervalSerializer.m create mode 100644 matlab/+petsird/+binary/TripleEventSerializer.m create mode 100644 matlab/+petsird/+helpers/get_detection_efficiency.m create mode 100644 matlab/+petsird/+helpers/get_module_and_element.m create mode 100644 matlab/+petsird/+helpers/get_num_detecting_elements.m create mode 100644 matlab/+petsird/AnnulusShape.m create mode 100644 matlab/+petsird/Atom.m create mode 100644 matlab/+petsird/BedMovementTimeBlock.m create mode 100644 matlab/+petsird/BoxShape.m create mode 100644 matlab/+petsird/BoxSolidVolume.m create mode 100644 matlab/+petsird/BulkMaterial.m create mode 100644 matlab/+petsird/CoincidenceEvent.m create mode 100644 matlab/+petsird/CoincidencePolicy.m create mode 100644 matlab/+petsird/Coordinate.m create mode 100644 matlab/+petsird/DeadTimeTimeBlock.m create mode 100644 matlab/+petsird/DetectionEfficiencies.m create mode 100644 matlab/+petsird/DetectorModule.m create mode 100644 matlab/+petsird/Direction.m create mode 100644 matlab/+petsird/DirectionMatrix.m create mode 100644 matlab/+petsird/EventTimeBlock.m create mode 100644 matlab/+petsird/ExamInformation.m create mode 100644 matlab/+petsird/ExternalSignalTimeBlock.m create mode 100644 matlab/+petsird/ExternalSignalType.m create mode 100644 matlab/+petsird/ExternalSignalTypeEnum.m create mode 100644 matlab/+petsird/GantryMovementTimeBlock.m create mode 100644 matlab/+petsird/GenericSolidVolume.m create mode 100644 matlab/+petsird/GeometricShape.m create mode 100644 matlab/+petsird/Header.m create mode 100644 matlab/+petsird/Institution.m create mode 100644 matlab/+petsird/ModulePairEfficiencies.m create mode 100644 matlab/+petsird/PETSIRDReaderBase.m create mode 100644 matlab/+petsird/PETSIRDWriterBase.m create mode 100644 matlab/+petsird/ReplicatedBoxSolidVolume.m create mode 100644 matlab/+petsird/ReplicatedDetectorModule.m create mode 100644 matlab/+petsird/ReplicatedGenericSolidVolume.m create mode 100644 matlab/+petsird/ReplicatedObject.m create mode 100644 matlab/+petsird/RigidTransformation.m create mode 100644 matlab/+petsird/ScannerGeometry.m create mode 100644 matlab/+petsird/ScannerInformation.m create mode 100644 matlab/+petsird/SolidVolume.m create mode 100644 matlab/+petsird/Subject.m create mode 100644 matlab/+petsird/TimeBlock.m create mode 100644 matlab/+petsird/TimeFrameInformation.m create mode 100644 matlab/+petsird/TimeInterval.m create mode 100644 matlab/+petsird/TripleEvent.m create mode 100644 matlab/+yardl/+binary/BinaryProtocolReader.m create mode 100644 matlab/+yardl/+binary/BinaryProtocolWriter.m create mode 100644 matlab/+yardl/+binary/BoolSerializer.m create mode 100644 matlab/+yardl/+binary/CURRENT_BINARY_FORMAT_VERSION.m create mode 100644 matlab/+yardl/+binary/CodedInputStream.m create mode 100644 matlab/+yardl/+binary/CodedOutputStream.m create mode 100644 matlab/+yardl/+binary/Complexfloat32Serializer.m create mode 100644 matlab/+yardl/+binary/Complexfloat64Serializer.m create mode 100644 matlab/+yardl/+binary/DateSerializer.m create mode 100644 matlab/+yardl/+binary/DatetimeSerializer.m create mode 100644 matlab/+yardl/+binary/DynamicNDArraySerializer.m create mode 100644 matlab/+yardl/+binary/EnumSerializer.m create mode 100644 matlab/+yardl/+binary/FixedNDArraySerializer.m create mode 100644 matlab/+yardl/+binary/FixedVectorSerializer.m create mode 100644 matlab/+yardl/+binary/Float32Serializer.m create mode 100644 matlab/+yardl/+binary/Float64Serializer.m create mode 100644 matlab/+yardl/+binary/Int16Serializer.m create mode 100644 matlab/+yardl/+binary/Int32Serializer.m create mode 100644 matlab/+yardl/+binary/Int64Serializer.m create mode 100644 matlab/+yardl/+binary/Int8Serializer.m create mode 100644 matlab/+yardl/+binary/MAGIC_BYTES.m create mode 100644 matlab/+yardl/+binary/MapSerializer.m create mode 100644 matlab/+yardl/+binary/NDArraySerializer.m create mode 100644 matlab/+yardl/+binary/NDArraySerializerBase.m create mode 100644 matlab/+yardl/+binary/NoneSerializer.m create mode 100644 matlab/+yardl/+binary/OptionalSerializer.m create mode 100644 matlab/+yardl/+binary/RecordSerializer.m create mode 100644 matlab/+yardl/+binary/SizeSerializer.m create mode 100644 matlab/+yardl/+binary/StreamSerializer.m create mode 100644 matlab/+yardl/+binary/StringSerializer.m create mode 100644 matlab/+yardl/+binary/TimeSerializer.m create mode 100644 matlab/+yardl/+binary/TypeSerializer.m create mode 100644 matlab/+yardl/+binary/Uint16Serializer.m create mode 100644 matlab/+yardl/+binary/Uint32Serializer.m create mode 100644 matlab/+yardl/+binary/Uint64Serializer.m create mode 100644 matlab/+yardl/+binary/Uint8Serializer.m create mode 100644 matlab/+yardl/+binary/UnionSerializer.m create mode 100644 matlab/+yardl/+binary/VectorSerializer.m create mode 100644 matlab/+yardl/+binary/VectorSerializerBase.m create mode 100644 matlab/+yardl/Date.m create mode 100644 matlab/+yardl/DateTime.m create mode 100644 matlab/+yardl/Exception.m create mode 100644 matlab/+yardl/Map.m create mode 100644 matlab/+yardl/None.m create mode 100644 matlab/+yardl/Optional.m create mode 100644 matlab/+yardl/ProtocolError.m create mode 100644 matlab/+yardl/RuntimeError.m create mode 100644 matlab/+yardl/Time.m create mode 100644 matlab/+yardl/TypeError.m create mode 100644 matlab/+yardl/Union.m create mode 100644 matlab/+yardl/ValueError.m create mode 100644 matlab/+yardl/allocate.m create mode 100644 matlab/+yardl/dimension_count.m create mode 100644 matlab/petsird_analysis.m create mode 100644 matlab/petsird_generator.m diff --git a/matlab/+petsird/+binary/AnnulusShapeSerializer.m b/matlab/+petsird/+binary/AnnulusShapeSerializer.m new file mode 100644 index 0000000..62d85a3 --- /dev/null +++ b/matlab/+petsird/+binary/AnnulusShapeSerializer.m @@ -0,0 +1,27 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef AnnulusShapeSerializer < yardl.binary.RecordSerializer + methods + function self = AnnulusShapeSerializer() + field_serializers{1} = yardl.binary.Float32Serializer; + field_serializers{2} = yardl.binary.Float32Serializer; + field_serializers{3} = yardl.binary.Float32Serializer; + field_serializers{4} = yardl.binary.FixedVectorSerializer(yardl.binary.Float32Serializer, 2); + self@yardl.binary.RecordSerializer('petsird.AnnulusShape', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.AnnulusShape + end + self.write_(outstream, value.inner_radius, value.outer_radius, value.thickness, value.angular_range); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.AnnulusShape(inner_radius=fields{1}, outer_radius=fields{2}, thickness=fields{3}, angular_range=fields{4}); + end + end +end diff --git a/matlab/+petsird/+binary/AtomSerializer.m b/matlab/+petsird/+binary/AtomSerializer.m new file mode 100644 index 0000000..9d6555d --- /dev/null +++ b/matlab/+petsird/+binary/AtomSerializer.m @@ -0,0 +1,25 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef AtomSerializer < yardl.binary.RecordSerializer + methods + function self = AtomSerializer() + field_serializers{1} = yardl.binary.Uint32Serializer; + field_serializers{2} = yardl.binary.Uint32Serializer; + self@yardl.binary.RecordSerializer('petsird.Atom', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.Atom + end + self.write_(outstream, value.mass_number, value.atomic_number); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.Atom(mass_number=fields{1}, atomic_number=fields{2}); + end + end +end diff --git a/matlab/+petsird/+binary/BedMovementTimeBlockSerializer.m b/matlab/+petsird/+binary/BedMovementTimeBlockSerializer.m new file mode 100644 index 0000000..2c66a2e --- /dev/null +++ b/matlab/+petsird/+binary/BedMovementTimeBlockSerializer.m @@ -0,0 +1,25 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef BedMovementTimeBlockSerializer < yardl.binary.RecordSerializer + methods + function self = BedMovementTimeBlockSerializer() + field_serializers{1} = yardl.binary.Uint32Serializer; + field_serializers{2} = petsird.binary.RigidTransformationSerializer(); + self@yardl.binary.RecordSerializer('petsird.BedMovementTimeBlock', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.BedMovementTimeBlock + end + self.write_(outstream, value.start, value.transform); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.BedMovementTimeBlock(start=fields{1}, transform=fields{2}); + end + end +end diff --git a/matlab/+petsird/+binary/BoxShapeSerializer.m b/matlab/+petsird/+binary/BoxShapeSerializer.m new file mode 100644 index 0000000..beef341 --- /dev/null +++ b/matlab/+petsird/+binary/BoxShapeSerializer.m @@ -0,0 +1,24 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef BoxShapeSerializer < yardl.binary.RecordSerializer + methods + function self = BoxShapeSerializer() + field_serializers{1} = yardl.binary.FixedVectorSerializer(petsird.binary.CoordinateSerializer(), 8); + self@yardl.binary.RecordSerializer('petsird.BoxShape', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.BoxShape + end + self.write_(outstream, value.corners); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.BoxShape(corners=fields{1}); + end + end +end diff --git a/matlab/+petsird/+binary/BulkMaterialSerializer.m b/matlab/+petsird/+binary/BulkMaterialSerializer.m new file mode 100644 index 0000000..a98eedc --- /dev/null +++ b/matlab/+petsird/+binary/BulkMaterialSerializer.m @@ -0,0 +1,28 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef BulkMaterialSerializer < yardl.binary.RecordSerializer + methods + function self = BulkMaterialSerializer() + field_serializers{1} = yardl.binary.Uint32Serializer; + field_serializers{2} = yardl.binary.StringSerializer; + field_serializers{3} = yardl.binary.Float32Serializer; + field_serializers{4} = yardl.binary.VectorSerializer(petsird.binary.AtomSerializer()); + field_serializers{5} = yardl.binary.VectorSerializer(yardl.binary.Float32Serializer); + self@yardl.binary.RecordSerializer('petsird.BulkMaterial', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.BulkMaterial + end + self.write_(outstream, value.id, value.name, value.density, value.atoms, value.mass_fractions); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.BulkMaterial(id=fields{1}, name=fields{2}, density=fields{3}, atoms=fields{4}, mass_fractions=fields{5}); + end + end +end diff --git a/matlab/+petsird/+binary/CoincidenceEventSerializer.m b/matlab/+petsird/+binary/CoincidenceEventSerializer.m new file mode 100644 index 0000000..aab45ad --- /dev/null +++ b/matlab/+petsird/+binary/CoincidenceEventSerializer.m @@ -0,0 +1,26 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef CoincidenceEventSerializer < yardl.binary.RecordSerializer + methods + function self = CoincidenceEventSerializer() + field_serializers{1} = yardl.binary.FixedVectorSerializer(yardl.binary.Uint32Serializer, 2); + field_serializers{2} = yardl.binary.Uint32Serializer; + field_serializers{3} = yardl.binary.FixedVectorSerializer(yardl.binary.Uint32Serializer, 2); + self@yardl.binary.RecordSerializer('petsird.CoincidenceEvent', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.CoincidenceEvent + end + self.write_(outstream, value.detector_ids, value.tof_idx, value.energy_indices); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.CoincidenceEvent(detector_ids=fields{1}, tof_idx=fields{2}, energy_indices=fields{3}); + end + end +end diff --git a/matlab/+petsird/+binary/CoordinateSerializer.m b/matlab/+petsird/+binary/CoordinateSerializer.m new file mode 100644 index 0000000..4219342 --- /dev/null +++ b/matlab/+petsird/+binary/CoordinateSerializer.m @@ -0,0 +1,24 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef CoordinateSerializer < yardl.binary.RecordSerializer + methods + function self = CoordinateSerializer() + field_serializers{1} = yardl.binary.FixedNDArraySerializer(yardl.binary.Float32Serializer, [3]); + self@yardl.binary.RecordSerializer('petsird.Coordinate', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.Coordinate + end + self.write_(outstream, value.c); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.Coordinate(c=fields{1}); + end + end +end diff --git a/matlab/+petsird/+binary/DeadTimeTimeBlockSerializer.m b/matlab/+petsird/+binary/DeadTimeTimeBlockSerializer.m new file mode 100644 index 0000000..f18eb0a --- /dev/null +++ b/matlab/+petsird/+binary/DeadTimeTimeBlockSerializer.m @@ -0,0 +1,26 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef DeadTimeTimeBlockSerializer < yardl.binary.RecordSerializer + methods + function self = DeadTimeTimeBlockSerializer() + field_serializers{1} = petsird.binary.TimeIntervalSerializer(); + field_serializers{2} = yardl.binary.NDArraySerializer(yardl.binary.Float32Serializer, 2); + field_serializers{3} = yardl.binary.NDArraySerializer(yardl.binary.Float32Serializer, 2); + self@yardl.binary.RecordSerializer('petsird.DeadTimeTimeBlock', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.DeadTimeTimeBlock + end + self.write_(outstream, value.time_interval, value.singles_alive_time_fraction, value.module_coincidence_alive_time_fraction); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.DeadTimeTimeBlock(time_interval=fields{1}, singles_alive_time_fraction=fields{2}, module_coincidence_alive_time_fraction=fields{3}); + end + end +end diff --git a/matlab/+petsird/+binary/DetectionEfficienciesSerializer.m b/matlab/+petsird/+binary/DetectionEfficienciesSerializer.m new file mode 100644 index 0000000..19ba038 --- /dev/null +++ b/matlab/+petsird/+binary/DetectionEfficienciesSerializer.m @@ -0,0 +1,26 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef DetectionEfficienciesSerializer < yardl.binary.RecordSerializer + methods + function self = DetectionEfficienciesSerializer() + field_serializers{1} = yardl.binary.OptionalSerializer(yardl.binary.NDArraySerializer(yardl.binary.Float32Serializer, 2)); + field_serializers{2} = yardl.binary.OptionalSerializer(yardl.binary.NDArraySerializer(yardl.binary.Int32Serializer, 2)); + field_serializers{3} = yardl.binary.OptionalSerializer(yardl.binary.VectorSerializer(petsird.binary.ModulePairEfficienciesSerializer())); + self@yardl.binary.RecordSerializer('petsird.DetectionEfficiencies', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.DetectionEfficiencies + end + self.write_(outstream, value.det_el_efficiencies, value.module_pair_sgidlut, value.module_pair_efficiencies_vector); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.DetectionEfficiencies(det_el_efficiencies=fields{1}, module_pair_sgidlut=fields{2}, module_pair_efficiencies_vector=fields{3}); + end + end +end diff --git a/matlab/+petsird/+binary/DetectorModuleSerializer.m b/matlab/+petsird/+binary/DetectorModuleSerializer.m new file mode 100644 index 0000000..5e4a724 --- /dev/null +++ b/matlab/+petsird/+binary/DetectorModuleSerializer.m @@ -0,0 +1,26 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef DetectorModuleSerializer < yardl.binary.RecordSerializer + methods + function self = DetectorModuleSerializer() + field_serializers{1} = yardl.binary.VectorSerializer(petsird.binary.ReplicatedObjectSerializer(petsird.binary.SolidVolumeSerializer(petsird.binary.BoxShapeSerializer()))); + field_serializers{2} = yardl.binary.VectorSerializer(yardl.binary.Uint32Serializer); + field_serializers{3} = yardl.binary.VectorSerializer(petsird.binary.ReplicatedObjectSerializer(petsird.binary.SolidVolumeSerializer(yardl.binary.UnionSerializer('petsird.GeometricShape', {petsird.binary.BoxShapeSerializer(), petsird.binary.AnnulusShapeSerializer()}, {@petsird.GeometricShape.BoxShape, @petsird.GeometricShape.AnnulusShape})))); + self@yardl.binary.RecordSerializer('petsird.DetectorModule', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.DetectorModule + end + self.write_(outstream, value.detecting_elements, value.detecting_element_ids, value.non_detecting_elements); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.DetectorModule(detecting_elements=fields{1}, detecting_element_ids=fields{2}, non_detecting_elements=fields{3}); + end + end +end diff --git a/matlab/+petsird/+binary/DirectionMatrixSerializer.m b/matlab/+petsird/+binary/DirectionMatrixSerializer.m new file mode 100644 index 0000000..179b6b1 --- /dev/null +++ b/matlab/+petsird/+binary/DirectionMatrixSerializer.m @@ -0,0 +1,24 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef DirectionMatrixSerializer < yardl.binary.RecordSerializer + methods + function self = DirectionMatrixSerializer() + field_serializers{1} = yardl.binary.FixedNDArraySerializer(yardl.binary.Float32Serializer, [3, 3]); + self@yardl.binary.RecordSerializer('petsird.DirectionMatrix', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.DirectionMatrix + end + self.write_(outstream, value.matrix); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.DirectionMatrix(matrix=fields{1}); + end + end +end diff --git a/matlab/+petsird/+binary/DirectionSerializer.m b/matlab/+petsird/+binary/DirectionSerializer.m new file mode 100644 index 0000000..77401b4 --- /dev/null +++ b/matlab/+petsird/+binary/DirectionSerializer.m @@ -0,0 +1,24 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef DirectionSerializer < yardl.binary.RecordSerializer + methods + function self = DirectionSerializer() + field_serializers{1} = yardl.binary.FixedNDArraySerializer(yardl.binary.Float32Serializer, [3]); + self@yardl.binary.RecordSerializer('petsird.Direction', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.Direction + end + self.write_(outstream, value.c); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.Direction(c=fields{1}); + end + end +end diff --git a/matlab/+petsird/+binary/EventTimeBlockSerializer.m b/matlab/+petsird/+binary/EventTimeBlockSerializer.m new file mode 100644 index 0000000..b2bfec0 --- /dev/null +++ b/matlab/+petsird/+binary/EventTimeBlockSerializer.m @@ -0,0 +1,27 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef EventTimeBlockSerializer < yardl.binary.RecordSerializer + methods + function self = EventTimeBlockSerializer() + field_serializers{1} = yardl.binary.Uint32Serializer; + field_serializers{2} = yardl.binary.VectorSerializer(petsird.binary.CoincidenceEventSerializer()); + field_serializers{3} = yardl.binary.OptionalSerializer(yardl.binary.VectorSerializer(petsird.binary.CoincidenceEventSerializer())); + field_serializers{4} = yardl.binary.OptionalSerializer(yardl.binary.VectorSerializer(petsird.binary.TripleEventSerializer())); + self@yardl.binary.RecordSerializer('petsird.EventTimeBlock', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.EventTimeBlock + end + self.write_(outstream, value.start, value.prompt_events, value.delayed_events, value.triple_events); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.EventTimeBlock(start=fields{1}, prompt_events=fields{2}, delayed_events=fields{3}, triple_events=fields{4}); + end + end +end diff --git a/matlab/+petsird/+binary/ExamInformationSerializer.m b/matlab/+petsird/+binary/ExamInformationSerializer.m new file mode 100644 index 0000000..317561f --- /dev/null +++ b/matlab/+petsird/+binary/ExamInformationSerializer.m @@ -0,0 +1,27 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ExamInformationSerializer < yardl.binary.RecordSerializer + methods + function self = ExamInformationSerializer() + field_serializers{1} = petsird.binary.SubjectSerializer(); + field_serializers{2} = petsird.binary.InstitutionSerializer(); + field_serializers{3} = yardl.binary.OptionalSerializer(yardl.binary.StringSerializer); + field_serializers{4} = yardl.binary.OptionalSerializer(yardl.binary.DatetimeSerializer); + self@yardl.binary.RecordSerializer('petsird.ExamInformation', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.ExamInformation + end + self.write_(outstream, value.subject, value.institution, value.protocol, value.start_of_acquisition); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.ExamInformation(subject=fields{1}, institution=fields{2}, protocol=fields{3}, start_of_acquisition=fields{4}); + end + end +end diff --git a/matlab/+petsird/+binary/ExternalSignalTimeBlockSerializer.m b/matlab/+petsird/+binary/ExternalSignalTimeBlockSerializer.m new file mode 100644 index 0000000..9e820fe --- /dev/null +++ b/matlab/+petsird/+binary/ExternalSignalTimeBlockSerializer.m @@ -0,0 +1,26 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ExternalSignalTimeBlockSerializer < yardl.binary.RecordSerializer + methods + function self = ExternalSignalTimeBlockSerializer() + field_serializers{1} = yardl.binary.Uint32Serializer; + field_serializers{2} = yardl.binary.Uint32Serializer; + field_serializers{3} = yardl.binary.VectorSerializer(yardl.binary.Float32Serializer); + self@yardl.binary.RecordSerializer('petsird.ExternalSignalTimeBlock', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.ExternalSignalTimeBlock + end + self.write_(outstream, value.start, value.signal_id, value.signal_values); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.ExternalSignalTimeBlock(start=fields{1}, signal_id=fields{2}, signal_values=fields{3}); + end + end +end diff --git a/matlab/+petsird/+binary/ExternalSignalTypeSerializer.m b/matlab/+petsird/+binary/ExternalSignalTypeSerializer.m new file mode 100644 index 0000000..39ca23c --- /dev/null +++ b/matlab/+petsird/+binary/ExternalSignalTypeSerializer.m @@ -0,0 +1,26 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ExternalSignalTypeSerializer < yardl.binary.RecordSerializer + methods + function self = ExternalSignalTypeSerializer() + field_serializers{1} = yardl.binary.EnumSerializer('petsird.ExternalSignalTypeEnum', @petsird.ExternalSignalTypeEnum, yardl.binary.Int32Serializer); + field_serializers{2} = yardl.binary.StringSerializer; + field_serializers{3} = yardl.binary.Uint32Serializer; + self@yardl.binary.RecordSerializer('petsird.ExternalSignalType', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.ExternalSignalType + end + self.write_(outstream, value.type, value.description, value.id); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.ExternalSignalType(type=fields{1}, description=fields{2}, id=fields{3}); + end + end +end diff --git a/matlab/+petsird/+binary/GantryMovementTimeBlockSerializer.m b/matlab/+petsird/+binary/GantryMovementTimeBlockSerializer.m new file mode 100644 index 0000000..7b47a59 --- /dev/null +++ b/matlab/+petsird/+binary/GantryMovementTimeBlockSerializer.m @@ -0,0 +1,25 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef GantryMovementTimeBlockSerializer < yardl.binary.RecordSerializer + methods + function self = GantryMovementTimeBlockSerializer() + field_serializers{1} = yardl.binary.Uint32Serializer; + field_serializers{2} = petsird.binary.RigidTransformationSerializer(); + self@yardl.binary.RecordSerializer('petsird.GantryMovementTimeBlock', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.GantryMovementTimeBlock + end + self.write_(outstream, value.start, value.transform); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.GantryMovementTimeBlock(start=fields{1}, transform=fields{2}); + end + end +end diff --git a/matlab/+petsird/+binary/HeaderSerializer.m b/matlab/+petsird/+binary/HeaderSerializer.m new file mode 100644 index 0000000..8cd8e36 --- /dev/null +++ b/matlab/+petsird/+binary/HeaderSerializer.m @@ -0,0 +1,25 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef HeaderSerializer < yardl.binary.RecordSerializer + methods + function self = HeaderSerializer() + field_serializers{1} = petsird.binary.ScannerInformationSerializer(); + field_serializers{2} = yardl.binary.OptionalSerializer(petsird.binary.ExamInformationSerializer()); + self@yardl.binary.RecordSerializer('petsird.Header', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.Header + end + self.write_(outstream, value.scanner, value.exam); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.Header(scanner=fields{1}, exam=fields{2}); + end + end +end diff --git a/matlab/+petsird/+binary/InstitutionSerializer.m b/matlab/+petsird/+binary/InstitutionSerializer.m new file mode 100644 index 0000000..3d33ba0 --- /dev/null +++ b/matlab/+petsird/+binary/InstitutionSerializer.m @@ -0,0 +1,25 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef InstitutionSerializer < yardl.binary.RecordSerializer + methods + function self = InstitutionSerializer() + field_serializers{1} = yardl.binary.StringSerializer; + field_serializers{2} = yardl.binary.StringSerializer; + self@yardl.binary.RecordSerializer('petsird.Institution', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.Institution + end + self.write_(outstream, value.name, value.address); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.Institution(name=fields{1}, address=fields{2}); + end + end +end diff --git a/matlab/+petsird/+binary/ModulePairEfficienciesSerializer.m b/matlab/+petsird/+binary/ModulePairEfficienciesSerializer.m new file mode 100644 index 0000000..871379d --- /dev/null +++ b/matlab/+petsird/+binary/ModulePairEfficienciesSerializer.m @@ -0,0 +1,25 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ModulePairEfficienciesSerializer < yardl.binary.RecordSerializer + methods + function self = ModulePairEfficienciesSerializer() + field_serializers{1} = yardl.binary.NDArraySerializer(yardl.binary.Float32Serializer, 4); + field_serializers{2} = yardl.binary.Uint32Serializer; + self@yardl.binary.RecordSerializer('petsird.ModulePairEfficiencies', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.ModulePairEfficiencies + end + self.write_(outstream, value.values, value.sgid); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.ModulePairEfficiencies(values=fields{1}, sgid=fields{2}); + end + end +end diff --git a/matlab/+petsird/+binary/PETSIRDReader.m b/matlab/+petsird/+binary/PETSIRDReader.m new file mode 100644 index 0000000..8cf8ef7 --- /dev/null +++ b/matlab/+petsird/+binary/PETSIRDReader.m @@ -0,0 +1,33 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef PETSIRDReader < yardl.binary.BinaryProtocolReader & petsird.PETSIRDReaderBase + % Binary reader for the PETSIRD protocol + % Definition of the stream of data + properties (Access=protected) + header_serializer + time_blocks_serializer + end + + methods + function self = PETSIRDReader(filename) + self@petsird.PETSIRDReaderBase(); + self@yardl.binary.BinaryProtocolReader(filename, petsird.PETSIRDReaderBase.schema); + self.header_serializer = petsird.binary.HeaderSerializer(); + self.time_blocks_serializer = yardl.binary.StreamSerializer(yardl.binary.UnionSerializer('petsird.TimeBlock', {petsird.binary.EventTimeBlockSerializer(), petsird.binary.ExternalSignalTimeBlockSerializer(), petsird.binary.BedMovementTimeBlockSerializer(), petsird.binary.GantryMovementTimeBlockSerializer()}, {@petsird.TimeBlock.EventTimeBlock, @petsird.TimeBlock.ExternalSignalTimeBlock, @petsird.TimeBlock.BedMovementTimeBlock, @petsird.TimeBlock.GantryMovementTimeBlock})); + end + end + + methods (Access=protected) + function value = read_header_(self) + value = self.header_serializer.read(self.stream_); + end + + function more = has_time_blocks_(self) + more = self.time_blocks_serializer.hasnext(self.stream_); + end + + function value = read_time_blocks_(self) + value = self.time_blocks_serializer.read(self.stream_); + end + end +end diff --git a/matlab/+petsird/+binary/PETSIRDWriter.m b/matlab/+petsird/+binary/PETSIRDWriter.m new file mode 100644 index 0000000..3d3ff4f --- /dev/null +++ b/matlab/+petsird/+binary/PETSIRDWriter.m @@ -0,0 +1,29 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef PETSIRDWriter < yardl.binary.BinaryProtocolWriter & petsird.PETSIRDWriterBase + % Binary writer for the PETSIRD protocol + % Definition of the stream of data + properties (Access=protected) + header_serializer + time_blocks_serializer + end + + methods + function self = PETSIRDWriter(filename) + self@petsird.PETSIRDWriterBase(); + self@yardl.binary.BinaryProtocolWriter(filename, petsird.PETSIRDWriterBase.schema); + self.header_serializer = petsird.binary.HeaderSerializer(); + self.time_blocks_serializer = yardl.binary.StreamSerializer(yardl.binary.UnionSerializer('petsird.TimeBlock', {petsird.binary.EventTimeBlockSerializer(), petsird.binary.ExternalSignalTimeBlockSerializer(), petsird.binary.BedMovementTimeBlockSerializer(), petsird.binary.GantryMovementTimeBlockSerializer()}, {@petsird.TimeBlock.EventTimeBlock, @petsird.TimeBlock.ExternalSignalTimeBlock, @petsird.TimeBlock.BedMovementTimeBlock, @petsird.TimeBlock.GantryMovementTimeBlock})); + end + end + + methods (Access=protected) + function write_header_(self, value) + self.header_serializer.write(self.stream_, value); + end + + function write_time_blocks_(self, value) + self.time_blocks_serializer.write(self.stream_, value); + end + end +end diff --git a/matlab/+petsird/+binary/ReplicatedObjectSerializer.m b/matlab/+petsird/+binary/ReplicatedObjectSerializer.m new file mode 100644 index 0000000..e8439ee --- /dev/null +++ b/matlab/+petsird/+binary/ReplicatedObjectSerializer.m @@ -0,0 +1,26 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ReplicatedObjectSerializer < yardl.binary.RecordSerializer + methods + function self = ReplicatedObjectSerializer(t_serializer) + field_serializers{1} = t_serializer; + field_serializers{2} = yardl.binary.VectorSerializer(petsird.binary.RigidTransformationSerializer()); + field_serializers{3} = yardl.binary.VectorSerializer(yardl.binary.Uint32Serializer); + self@yardl.binary.RecordSerializer('petsird.ReplicatedObject', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.ReplicatedObject + end + self.write_(outstream, value.object, value.transforms, value.ids); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.ReplicatedObject(object=fields{1}, transforms=fields{2}, ids=fields{3}); + end + end +end diff --git a/matlab/+petsird/+binary/RigidTransformationSerializer.m b/matlab/+petsird/+binary/RigidTransformationSerializer.m new file mode 100644 index 0000000..d0c7268 --- /dev/null +++ b/matlab/+petsird/+binary/RigidTransformationSerializer.m @@ -0,0 +1,24 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef RigidTransformationSerializer < yardl.binary.RecordSerializer + methods + function self = RigidTransformationSerializer() + field_serializers{1} = yardl.binary.FixedNDArraySerializer(yardl.binary.Float32Serializer, [4, 3]); + self@yardl.binary.RecordSerializer('petsird.RigidTransformation', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.RigidTransformation + end + self.write_(outstream, value.matrix); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.RigidTransformation(matrix=fields{1}); + end + end +end diff --git a/matlab/+petsird/+binary/ScannerGeometrySerializer.m b/matlab/+petsird/+binary/ScannerGeometrySerializer.m new file mode 100644 index 0000000..4c55c69 --- /dev/null +++ b/matlab/+petsird/+binary/ScannerGeometrySerializer.m @@ -0,0 +1,26 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ScannerGeometrySerializer < yardl.binary.RecordSerializer + methods + function self = ScannerGeometrySerializer() + field_serializers{1} = yardl.binary.VectorSerializer(petsird.binary.ReplicatedObjectSerializer(petsird.binary.DetectorModuleSerializer())); + field_serializers{2} = yardl.binary.VectorSerializer(yardl.binary.Uint32Serializer); + field_serializers{3} = yardl.binary.OptionalSerializer(yardl.binary.VectorSerializer(petsird.binary.SolidVolumeSerializer(yardl.binary.UnionSerializer('petsird.GeometricShape', {petsird.binary.BoxShapeSerializer(), petsird.binary.AnnulusShapeSerializer()}, {@petsird.GeometricShape.BoxShape, @petsird.GeometricShape.AnnulusShape})))); + self@yardl.binary.RecordSerializer('petsird.ScannerGeometry', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.ScannerGeometry + end + self.write_(outstream, value.replicated_modules, value.ids, value.non_detecting_volumes); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.ScannerGeometry(replicated_modules=fields{1}, ids=fields{2}, non_detecting_volumes=fields{3}); + end + end +end diff --git a/matlab/+petsird/+binary/ScannerInformationSerializer.m b/matlab/+petsird/+binary/ScannerInformationSerializer.m new file mode 100644 index 0000000..e22a582 --- /dev/null +++ b/matlab/+petsird/+binary/ScannerInformationSerializer.m @@ -0,0 +1,34 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ScannerInformationSerializer < yardl.binary.RecordSerializer + methods + function self = ScannerInformationSerializer() + field_serializers{1} = yardl.binary.StringSerializer; + field_serializers{2} = petsird.binary.ScannerGeometrySerializer(); + field_serializers{3} = yardl.binary.VectorSerializer(petsird.binary.BulkMaterialSerializer()); + field_serializers{4} = yardl.binary.OptionalSerializer(petsird.binary.RigidTransformationSerializer()); + field_serializers{5} = yardl.binary.NDArraySerializer(yardl.binary.Float32Serializer, 1); + field_serializers{6} = yardl.binary.Float32Serializer; + field_serializers{7} = yardl.binary.NDArraySerializer(yardl.binary.Float32Serializer, 1); + field_serializers{8} = yardl.binary.Float32Serializer; + field_serializers{9} = yardl.binary.Uint32Serializer; + field_serializers{10} = yardl.binary.EnumSerializer('petsird.CoincidencePolicy', @petsird.CoincidencePolicy, yardl.binary.Int32Serializer); + field_serializers{11} = petsird.binary.DetectionEfficienciesSerializer(); + self@yardl.binary.RecordSerializer('petsird.ScannerInformation', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.ScannerInformation + end + self.write_(outstream, value.model_name, value.scanner_geometry, value.bulk_materials, value.gantry_alignment, value.tof_bin_edges, value.tof_resolution, value.energy_bin_edges, value.energy_resolution_at_511, value.event_time_block_duration, value.coincidence_policy, value.detection_efficiencies); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.ScannerInformation(model_name=fields{1}, scanner_geometry=fields{2}, bulk_materials=fields{3}, gantry_alignment=fields{4}, tof_bin_edges=fields{5}, tof_resolution=fields{6}, energy_bin_edges=fields{7}, energy_resolution_at_511=fields{8}, event_time_block_duration=fields{9}, coincidence_policy=fields{10}, detection_efficiencies=fields{11}); + end + end +end diff --git a/matlab/+petsird/+binary/SolidVolumeSerializer.m b/matlab/+petsird/+binary/SolidVolumeSerializer.m new file mode 100644 index 0000000..0743e08 --- /dev/null +++ b/matlab/+petsird/+binary/SolidVolumeSerializer.m @@ -0,0 +1,25 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef SolidVolumeSerializer < yardl.binary.RecordSerializer + methods + function self = SolidVolumeSerializer(shape_serializer) + field_serializers{1} = shape_serializer; + field_serializers{2} = yardl.binary.Uint32Serializer; + self@yardl.binary.RecordSerializer('petsird.SolidVolume', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.SolidVolume + end + self.write_(outstream, value.shape, value.material_id); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.SolidVolume(shape=fields{1}, material_id=fields{2}); + end + end +end diff --git a/matlab/+petsird/+binary/SubjectSerializer.m b/matlab/+petsird/+binary/SubjectSerializer.m new file mode 100644 index 0000000..ce7d2e0 --- /dev/null +++ b/matlab/+petsird/+binary/SubjectSerializer.m @@ -0,0 +1,25 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef SubjectSerializer < yardl.binary.RecordSerializer + methods + function self = SubjectSerializer() + field_serializers{1} = yardl.binary.OptionalSerializer(yardl.binary.StringSerializer); + field_serializers{2} = yardl.binary.StringSerializer; + self@yardl.binary.RecordSerializer('petsird.Subject', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.Subject + end + self.write_(outstream, value.name, value.id); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.Subject(name=fields{1}, id=fields{2}); + end + end +end diff --git a/matlab/+petsird/+binary/TimeFrameInformationSerializer.m b/matlab/+petsird/+binary/TimeFrameInformationSerializer.m new file mode 100644 index 0000000..1148122 --- /dev/null +++ b/matlab/+petsird/+binary/TimeFrameInformationSerializer.m @@ -0,0 +1,24 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef TimeFrameInformationSerializer < yardl.binary.RecordSerializer + methods + function self = TimeFrameInformationSerializer() + field_serializers{1} = yardl.binary.VectorSerializer(petsird.binary.TimeIntervalSerializer()); + self@yardl.binary.RecordSerializer('petsird.TimeFrameInformation', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.TimeFrameInformation + end + self.write_(outstream, value.time_frames); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.TimeFrameInformation(time_frames=fields{1}); + end + end +end diff --git a/matlab/+petsird/+binary/TimeIntervalSerializer.m b/matlab/+petsird/+binary/TimeIntervalSerializer.m new file mode 100644 index 0000000..978fbb6 --- /dev/null +++ b/matlab/+petsird/+binary/TimeIntervalSerializer.m @@ -0,0 +1,25 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef TimeIntervalSerializer < yardl.binary.RecordSerializer + methods + function self = TimeIntervalSerializer() + field_serializers{1} = yardl.binary.Uint32Serializer; + field_serializers{2} = yardl.binary.Uint32Serializer; + self@yardl.binary.RecordSerializer('petsird.TimeInterval', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.TimeInterval + end + self.write_(outstream, value.start, value.stop); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.TimeInterval(start=fields{1}, stop=fields{2}); + end + end +end diff --git a/matlab/+petsird/+binary/TripleEventSerializer.m b/matlab/+petsird/+binary/TripleEventSerializer.m new file mode 100644 index 0000000..f5b0dfe --- /dev/null +++ b/matlab/+petsird/+binary/TripleEventSerializer.m @@ -0,0 +1,26 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef TripleEventSerializer < yardl.binary.RecordSerializer + methods + function self = TripleEventSerializer() + field_serializers{1} = yardl.binary.FixedVectorSerializer(yardl.binary.Uint32Serializer, 3); + field_serializers{2} = yardl.binary.FixedVectorSerializer(yardl.binary.Uint32Serializer, 2); + field_serializers{3} = yardl.binary.FixedVectorSerializer(yardl.binary.Uint32Serializer, 3); + self@yardl.binary.RecordSerializer('petsird.TripleEvent', field_serializers); + end + + function write(self, outstream, value) + arguments + self + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) petsird.TripleEvent + end + self.write_(outstream, value.detector_ids, value.tof_indices, value.energy_indices); + end + + function value = read(self, instream) + fields = self.read_(instream); + value = petsird.TripleEvent(detector_ids=fields{1}, tof_indices=fields{2}, energy_indices=fields{3}); + end + end +end diff --git a/matlab/+petsird/+helpers/get_detection_efficiency.m b/matlab/+petsird/+helpers/get_detection_efficiency.m new file mode 100644 index 0000000..7d912d1 --- /dev/null +++ b/matlab/+petsird/+helpers/get_detection_efficiency.m @@ -0,0 +1,37 @@ +function eff = get_detection_efficiency(scanner, event) +% Compute the detection efficiency for a coincidence event + +arguments + scanner (1,1) petsird.ScannerInformation + event (1,1) petsird.CoincidenceEvent +end + +eff = 1; + +% Per det_el efficiencies +det_el_efficiencies = scanner.detection_efficiencies.det_el_efficiencies; +if det_el_efficiencies ~= yardl.None + eff = eff .* (det_el_efficiencies(event.energy_indices(1)+1, event.detector_ids(1)+1) .* ... + det_el_efficiencies(event.energy_indices(2)+1, event.detector_ids(2)+1)); +end + +% Per module-pair efficiencies +module_pair_efficiencies_vector = scanner.detection_efficiencies.module_pair_efficiencies_vector; +if module_pair_efficiencies_vector ~= yardl.None + module_pair_SGID_LUT = scanner.detection_efficiencies.module_pair_sgidlut; + assert(module_pair_SGID_LUT ~= yardl.None); + mod_and_els = petsird.helpers.get_module_and_element(scanner.scanner_geometry, event.detector_ids); + assert(length(scanner.scanner_geometry.replicated_modules) == 1); + SGID = module_pair_SGID_LUT(mod_and_els(1).module+1, mod_and_els(2).module+1); + assert(SGID >= 0); + module_pair_efficiencies = module_pair_efficiencies_vector(SGID+1); + assert(module_pair_efficiencies.sgid == SGID); + eff = eff * module_pair_efficiencies.values( ... + event.energy_indices(2)+1, ... + mod_and_els(2).el+1, ... + event.energy_indices(1)+1, ... + mod_and_els(1).el+1 ... + ); +end + +end diff --git a/matlab/+petsird/+helpers/get_module_and_element.m b/matlab/+petsird/+helpers/get_module_and_element.m new file mode 100644 index 0000000..750be9d --- /dev/null +++ b/matlab/+petsird/+helpers/get_module_and_element.m @@ -0,0 +1,16 @@ +function mod_and_el = get_module_and_element(scanner_geometry, scanner_det_ids) +% Find ModuleAndElement for a list of detector_ids + +arguments + scanner_geometry (1,1) petsird.ScannerGeometry + scanner_det_ids (:,1) uint32 +end + +assert(length(scanner_geometry.replicated_modules) == 1); +rep_module = scanner_geometry.replicated_modules(1); +assert(length(rep_module.object.detecting_elements) == 1); +num_el_per_module = length(rep_module.object.detecting_elements(1).ids); + +mod_and_el = arrayfun(@(id) struct('module', idivide(id, num_el_per_module), 'el', mod(id, num_el_per_module)), scanner_det_ids); + +end diff --git a/matlab/+petsird/+helpers/get_num_detecting_elements.m b/matlab/+petsird/+helpers/get_num_detecting_elements.m new file mode 100644 index 0000000..04e8ce7 --- /dev/null +++ b/matlab/+petsird/+helpers/get_num_detecting_elements.m @@ -0,0 +1,18 @@ +function num_det_els = get_num_detecting_elements(scanner_geometry) +% Compute total number of detecting elements in the scanner + +arguments + scanner_geometry (1,1) petsird.ScannerGeometry +end + +num_det_els = 0; +for rep_mod_idx = 1:length(scanner_geometry.replicated_modules) + rep_module = scanner_geometry.replicated_modules(rep_mod_idx); + det_els = rep_module.object.detecting_elements; + for rep_volume_idx = 1:length(det_els) + rep_volume = det_els(rep_volume_idx); + num_det_els = num_det_els + length(rep_volume.transforms) .* length(rep_module.transforms); + end +end + +end diff --git a/matlab/+petsird/AnnulusShape.m b/matlab/+petsird/AnnulusShape.m new file mode 100644 index 0000000..ef5e784 --- /dev/null +++ b/matlab/+petsird/AnnulusShape.m @@ -0,0 +1,63 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef AnnulusShape < handle + % Annulus of certain thickness centered at [0,0,0] and oriented along the [0,0,1] axis + % in radians. An angle of 0 corresponds to the [1,0,0] axis, Pi/2 corresponds to the [0,1,0] axis. + properties + % inner radius (in mm) + inner_radius + % outer radius (in mm) + outer_radius + % thickness of the annulus, i.e. length along the axis (in mm) + thickness + % start-stop angle (in radians) + angular_range + end + + methods + function self = AnnulusShape(kwargs) + arguments + kwargs.inner_radius = single(0); + kwargs.outer_radius = single(0); + kwargs.thickness = single(0); + kwargs.angular_range = repelem(single(0), 2); + end + self.inner_radius = kwargs.inner_radius; + self.outer_radius = kwargs.outer_radius; + self.thickness = kwargs.thickness; + self.angular_range = kwargs.angular_range; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.AnnulusShape") && ... + isequal({self.inner_radius}, {other.inner_radius}) && ... + isequal({self.outer_radius}, {other.outer_radius}) && ... + isequal({self.thickness}, {other.thickness}) && ... + isequal({self.angular_range}, {other.angular_range}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.AnnulusShape(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/Atom.m b/matlab/+petsird/Atom.m new file mode 100644 index 0000000..502193b --- /dev/null +++ b/matlab/+petsird/Atom.m @@ -0,0 +1,52 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef Atom < handle + % Atom definition in terms of Z and A + properties + % A + mass_number + % Z + atomic_number + end + + methods + function self = Atom(kwargs) + arguments + kwargs.mass_number = uint32(0); + kwargs.atomic_number = uint32(0); + end + self.mass_number = kwargs.mass_number; + self.atomic_number = kwargs.atomic_number; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.Atom") && ... + isequal({self.mass_number}, {other.mass_number}) && ... + isequal({self.atomic_number}, {other.atomic_number}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.Atom(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/BedMovementTimeBlock.m b/matlab/+petsird/BedMovementTimeBlock.m new file mode 100644 index 0000000..4dd7de2 --- /dev/null +++ b/matlab/+petsird/BedMovementTimeBlock.m @@ -0,0 +1,50 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef BedMovementTimeBlock < handle + properties + % start time since ExamInformation.startOfAcquisition in ms + start + transform + end + + methods + function self = BedMovementTimeBlock(kwargs) + arguments + kwargs.start = uint32(0); + kwargs.transform = petsird.RigidTransformation(); + end + self.start = kwargs.start; + self.transform = kwargs.transform; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.BedMovementTimeBlock") && ... + isequal({self.start}, {other.start}) && ... + isequal({self.transform}, {other.transform}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.BedMovementTimeBlock(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/BoxShape.m b/matlab/+petsird/BoxShape.m new file mode 100644 index 0000000..a6e99be --- /dev/null +++ b/matlab/+petsird/BoxShape.m @@ -0,0 +1,51 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef BoxShape < handle + % A box-shape specified by 8 corners (e.g. cuboid, wedge, etc.) + % TODO need to think about a clear definition of planes + % We do not want to have to check about intersection planes + % Potential mechanisms: + % - lexicographical ordering of corner coordinates? + % - first 4 coordinates give first plane, 5th and 6th need to define plane with first 2, etc. + properties + corners + end + + methods + function self = BoxShape(kwargs) + arguments + kwargs.corners = repelem(petsird.Coordinate(), 8); + end + self.corners = kwargs.corners; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.BoxShape") && ... + isequal({self.corners}, {other.corners}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.BoxShape(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/BoxSolidVolume.m b/matlab/+petsird/BoxSolidVolume.m new file mode 100644 index 0000000..2dfb662 --- /dev/null +++ b/matlab/+petsird/BoxSolidVolume.m @@ -0,0 +1,4 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef BoxSolidVolume < petsird.SolidVolume +end diff --git a/matlab/+petsird/BulkMaterial.m b/matlab/+petsird/BulkMaterial.m new file mode 100644 index 0000000..42cee00 --- /dev/null +++ b/matlab/+petsird/BulkMaterial.m @@ -0,0 +1,75 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef BulkMaterial < handle + % Specification of materials used in the scanner. + % TODO agree with vendors if this information can be supplied and to what accuracy + % Ideally this list should be reasonably accurate to be useful for Monte Carlo simulations, but can be approximate. + properties + % unique id that can be used to refer to the material in voxelised maps etc + id + % informative string, not standardised. + % Expected examples: + % detecting: BGO, LSO, LYSO, LaBr, GAGG, plastic + % non-detecting: tungsten, lead + name + % density of the material + % Units: g/cc + density + % List of atoms + atoms + % List of massFractions for the atoms. + % constraint: sum of massFractions should be 1 + % constraint: size(atoms) == size(massFractions) + mass_fractions + end + + methods + function self = BulkMaterial(kwargs) + arguments + kwargs.id = uint32(0); + kwargs.name = ""; + kwargs.density = single(0); + kwargs.atoms = petsird.Atom.empty(); + kwargs.mass_fractions = single.empty(); + end + self.id = kwargs.id; + self.name = kwargs.name; + self.density = kwargs.density; + self.atoms = kwargs.atoms; + self.mass_fractions = kwargs.mass_fractions; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.BulkMaterial") && ... + isequal({self.id}, {other.id}) && ... + isequal({self.name}, {other.name}) && ... + isequal({self.density}, {other.density}) && ... + isequal({self.atoms}, {other.atoms}) && ... + isequal({self.mass_fractions}, {other.mass_fractions}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.BulkMaterial(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/CoincidenceEvent.m b/matlab/+petsird/CoincidenceEvent.m new file mode 100644 index 0000000..b7ed203 --- /dev/null +++ b/matlab/+petsird/CoincidenceEvent.m @@ -0,0 +1,58 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef CoincidenceEvent < handle + % All information about a coincidence event specified as identifiers or indices (i.e. discretized). Indices start from 0. + % TODO: this might take up too much space, so some/all of these could be combined in a single index if necessary. + properties + % the pair of detector elements + detector_ids + % an index into the tofBinEdges field in the ScannerInformation + tof_idx + % a pair of indices into the energyBinEdges field in the ScannerInformation + energy_indices + end + + methods + function self = CoincidenceEvent(kwargs) + arguments + kwargs.detector_ids = repelem(uint32(0), 2); + kwargs.tof_idx = uint32(0); + kwargs.energy_indices = repelem(uint32(0), 2); + end + self.detector_ids = kwargs.detector_ids; + self.tof_idx = kwargs.tof_idx; + self.energy_indices = kwargs.energy_indices; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.CoincidenceEvent") && ... + isequal({self.detector_ids}, {other.detector_ids}) && ... + isequal({self.tof_idx}, {other.tof_idx}) && ... + isequal({self.energy_indices}, {other.energy_indices}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.CoincidenceEvent(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/CoincidencePolicy.m b/matlab/+petsird/CoincidencePolicy.m new file mode 100644 index 0000000..d572dfc --- /dev/null +++ b/matlab/+petsird/CoincidencePolicy.m @@ -0,0 +1,35 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef CoincidencePolicy < uint64 + % Type definition for how to encode how the scanner handles multiple coincidences when recording the prompts. + % Due to various effects (such as high count rate, prompt gammas), it is possible that multiple single + % events are detected within the coincidence window. This type encodes some different ways + % that this multiple events are handled, and recorded in the coincidence stream. + methods (Static) + % multiples will be rejected + function v = REJECT_MULTIPLES + v = petsird.CoincidencePolicy(0); + end + % multiples will be stored as a sequence of pairs, e.g. a triple leads to 3 pairs + function v = STORE_MULTIPLES_AS_PAIRS + v = petsird.CoincidencePolicy(1); + end + % other options, to be listed in the future + function v = OTHER + v = petsird.CoincidencePolicy(2); + end + + function z = zeros(varargin) + elem = petsird.CoincidencePolicy(0); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/Coordinate.m b/matlab/+petsird/Coordinate.m new file mode 100644 index 0000000..978d1ef --- /dev/null +++ b/matlab/+petsird/Coordinate.m @@ -0,0 +1,46 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef Coordinate < handle + % 3D coordinates (in mm) + properties + c + end + + methods + function self = Coordinate(kwargs) + arguments + kwargs.c = repelem(single(0), 3, 1); + end + self.c = kwargs.c; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.Coordinate") && ... + isequal({self.c}, {other.c}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.Coordinate(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/DeadTimeTimeBlock.m b/matlab/+petsird/DeadTimeTimeBlock.m new file mode 100644 index 0000000..5e2fff6 --- /dev/null +++ b/matlab/+petsird/DeadTimeTimeBlock.m @@ -0,0 +1,76 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef DeadTimeTimeBlock < handle + properties + % time interval for this time block + time_interval + % Singles dead-time array for the time interval, stored as fractions of "alive time" + % (1 means no dead-time, 0 means no detected counts) + % If sizeOfEnergyIdxDimension == 1, the fraction is assumed to be the same + % for all energy windows. + % Constraint: sizeOfDetectorIdDimension == number of all possible unique DetectorIds + % Constraint: (sizeOfEnergyIdxDimension == 1) or (sizeOfEnergyIdxDimension == ScannerInformation.numberOfEnergyBins) + singles_alive_time_fraction + % coincidence dead-time array for 2 modules in coincidence, stored as fractions of "alive time" + % (1 means no dead-time, 0 means no detected coincidences) + % If the size of this 2D array is (1,1), it is assumed that the corresponding alive-fraction is the same for all modules. + % Constraint: size(moduleCoincidenceAliveTimeFraction, 0) == 1 or total number of modules of all types + % Constraint: size(moduleCoincidenceAliveTimeFraction, 1) == 1 or total number of modules of all types + module_coincidence_alive_time_fraction + end + + methods + function self = DeadTimeTimeBlock(kwargs) + arguments + kwargs.time_interval = petsird.TimeInterval(); + kwargs.singles_alive_time_fraction = single.empty(); + kwargs.module_coincidence_alive_time_fraction = single.empty(); + end + self.time_interval = kwargs.time_interval; + self.singles_alive_time_fraction = kwargs.singles_alive_time_fraction; + self.module_coincidence_alive_time_fraction = kwargs.module_coincidence_alive_time_fraction; + end + + function res = size_of_detector_id_dimension(self) + res = size(self.singles_alive_time_fraction, ndims(self.singles_alive_time_fraction)-(0)); + return + end + + function res = size_of_energy_idx_dimension(self) + res = size(self.singles_alive_time_fraction, ndims(self.singles_alive_time_fraction)-(1)); + return + end + + + function res = eq(self, other) + res = ... + isa(other, "petsird.DeadTimeTimeBlock") && ... + isequal({self.time_interval}, {other.time_interval}) && ... + isequal({self.singles_alive_time_fraction}, {other.singles_alive_time_fraction}) && ... + isequal({self.module_coincidence_alive_time_fraction}, {other.module_coincidence_alive_time_fraction}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.DeadTimeTimeBlock(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/DetectionEfficiencies.m b/matlab/+petsird/DetectionEfficiencies.m new file mode 100644 index 0000000..c9a7d7c --- /dev/null +++ b/matlab/+petsird/DetectionEfficiencies.m @@ -0,0 +1,82 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef DetectionEfficiencies < handle + % Component-based information on detection efficiencies + % This encodes a simple model for the detection efficiency of (true) coincidences + % consisting of the product of the efficiency of the two detecting elements (det_els) + % and a (geometric) component determined by their location in the two modules. + % The former are stored in detElEfficiencies, and the latter in modulePairEfficienciesVector + % (a list of ModulePairEfficiencies, each entry corresponding to a module pair). + + % Most PET scanners have some kind of geometric symmetry, e.g. rotation over a full + % module, or translation along the axis of the scanner. Module-pairs that are related + % by such a symmetry often have the same geometric detection efficiencies. PETSIRD + % calls this a "symmetry group" (SG). Each SG had an identifier (SGID). To save memory, + % the modulePairEfficienciesVector needs to contain only one of element for each SGID. + % The SGID for a module-pair can be found in modulePairSGIDLUT. + + % Finding the total detection efficiency therefore follows these steps: + % (the following pseudo-code ignores energy bins for simplicity) + % 1. find modules for each det_el + % 2. find det_el indices "inside" each module + % 3. SGID = modulePairSGIDLUT[mod1, mod1] + % 4. if (SGID < 0) return 0 + % 5. module_pair_efficiencies = modulePairEfficienciesVector[SGID] + % 6. return detElEfficiencies[det_el1] * detElEfficiencies[det_el2] * module_pair_efficiencies[det_el_in_mod1, det_el_in_mod2] + + % If either of the components is not present, its value is considered to be 1. + properties + % Detection efficiencies for every detecting element + det_el_efficiencies + % Lookup table for SGIDs. + % Also indicates if coincidences between a module-pair are recorded. + module_pair_sgidlut + % Vector of all modulePairEfficiencies (one for each SGID) + % Constraint: size(modulePairEfficienciesVector) == max(modulePairSGIDLUT) + 1 + module_pair_efficiencies_vector + end + + methods + function self = DetectionEfficiencies(kwargs) + arguments + kwargs.det_el_efficiencies = yardl.None; + kwargs.module_pair_sgidlut = yardl.None; + kwargs.module_pair_efficiencies_vector = yardl.None; + end + self.det_el_efficiencies = kwargs.det_el_efficiencies; + self.module_pair_sgidlut = kwargs.module_pair_sgidlut; + self.module_pair_efficiencies_vector = kwargs.module_pair_efficiencies_vector; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.DetectionEfficiencies") && ... + isequal({self.det_el_efficiencies}, {other.det_el_efficiencies}) && ... + isequal({self.module_pair_sgidlut}, {other.module_pair_sgidlut}) && ... + isequal({self.module_pair_efficiencies_vector}, {other.module_pair_efficiencies_vector}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.DetectionEfficiencies(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/DetectorModule.m b/matlab/+petsird/DetectorModule.m new file mode 100644 index 0000000..8699895 --- /dev/null +++ b/matlab/+petsird/DetectorModule.m @@ -0,0 +1,59 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef DetectorModule < handle + % Top-level detector structure, consisting of one or more lists of detecting elements (or "crystals") + % This allows having different types of detecting elements (e.g. for phoswich detectors) + % TODO this could be made into a hierarchical structure + properties + detecting_elements + % list of unique ids for every replicated solid volume + % constraint: size(detectingElements) == size(detectingElementsIds) + detecting_element_ids + % optional list describing shielding/optical reflectors etc + non_detecting_elements + end + + methods + function self = DetectorModule(kwargs) + arguments + kwargs.detecting_elements = petsird.ReplicatedBoxSolidVolume.empty(); + kwargs.detecting_element_ids = uint32.empty(); + kwargs.non_detecting_elements = petsird.ReplicatedGenericSolidVolume.empty(); + end + self.detecting_elements = kwargs.detecting_elements; + self.detecting_element_ids = kwargs.detecting_element_ids; + self.non_detecting_elements = kwargs.non_detecting_elements; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.DetectorModule") && ... + isequal({self.detecting_elements}, {other.detecting_elements}) && ... + isequal({self.detecting_element_ids}, {other.detecting_element_ids}) && ... + isequal({self.non_detecting_elements}, {other.non_detecting_elements}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.DetectorModule(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/Direction.m b/matlab/+petsird/Direction.m new file mode 100644 index 0000000..0b35e77 --- /dev/null +++ b/matlab/+petsird/Direction.m @@ -0,0 +1,46 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef Direction < handle + % 3D direction vector (normalized to 1) + properties + c + end + + methods + function self = Direction(kwargs) + arguments + kwargs.c = repelem(single(0), 3, 1); + end + self.c = kwargs.c; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.Direction") && ... + isequal({self.c}, {other.c}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.Direction(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/DirectionMatrix.m b/matlab/+petsird/DirectionMatrix.m new file mode 100644 index 0000000..b67e195 --- /dev/null +++ b/matlab/+petsird/DirectionMatrix.m @@ -0,0 +1,47 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef DirectionMatrix < handle + % Orthonormal matrix + % direction_of_first_axis = matrix * [1, 0 ,0] (as a column vector) + properties + matrix + end + + methods + function self = DirectionMatrix(kwargs) + arguments + kwargs.matrix = repelem(single(0), 3, 3); + end + self.matrix = kwargs.matrix; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.DirectionMatrix") && ... + isequal({self.matrix}, {other.matrix}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.DirectionMatrix(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/EventTimeBlock.m b/matlab/+petsird/EventTimeBlock.m new file mode 100644 index 0000000..d389b7a --- /dev/null +++ b/matlab/+petsird/EventTimeBlock.m @@ -0,0 +1,64 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef EventTimeBlock < handle + properties + % start time since ExamInformation.startOfAcquisition in ms + % Note: duration is given by ScannerInformation.eventTimeBlockDuration + start + % TODO encode end time? + % list of prompts in this time block + % TODO might be better to use !array + prompt_events + % optional list of delayed coincidences in this time block + delayed_events + % optional list of triple coincidences in this time block + triple_events + end + + methods + function self = EventTimeBlock(kwargs) + arguments + kwargs.start = uint32(0); + kwargs.prompt_events = petsird.CoincidenceEvent.empty(); + kwargs.delayed_events = yardl.None; + kwargs.triple_events = yardl.None; + end + self.start = kwargs.start; + self.prompt_events = kwargs.prompt_events; + self.delayed_events = kwargs.delayed_events; + self.triple_events = kwargs.triple_events; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.EventTimeBlock") && ... + isequal({self.start}, {other.start}) && ... + isequal({self.prompt_events}, {other.prompt_events}) && ... + isequal({self.delayed_events}, {other.delayed_events}) && ... + isequal({self.triple_events}, {other.triple_events}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.EventTimeBlock(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/ExamInformation.m b/matlab/+petsird/ExamInformation.m new file mode 100644 index 0000000..296ab89 --- /dev/null +++ b/matlab/+petsird/ExamInformation.m @@ -0,0 +1,58 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ExamInformation < handle + % Items describing the exam (incomplete) + properties + subject + institution + protocol + start_of_acquisition + end + + methods + function self = ExamInformation(kwargs) + arguments + kwargs.subject = petsird.Subject(); + kwargs.institution = petsird.Institution(); + kwargs.protocol = yardl.None; + kwargs.start_of_acquisition = yardl.None; + end + self.subject = kwargs.subject; + self.institution = kwargs.institution; + self.protocol = kwargs.protocol; + self.start_of_acquisition = kwargs.start_of_acquisition; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.ExamInformation") && ... + isequal({self.subject}, {other.subject}) && ... + isequal({self.institution}, {other.institution}) && ... + isequal({self.protocol}, {other.protocol}) && ... + isequal({self.start_of_acquisition}, {other.start_of_acquisition}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.ExamInformation(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/ExternalSignalTimeBlock.m b/matlab/+petsird/ExternalSignalTimeBlock.m new file mode 100644 index 0000000..e8eb948 --- /dev/null +++ b/matlab/+petsird/ExternalSignalTimeBlock.m @@ -0,0 +1,56 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ExternalSignalTimeBlock < handle + properties + % start time since ExamInformation.startOfAcquisition in ms + start + % refer to ExternalSignalType.id + signal_id + % Note for triggers, this field is to be ignored + signal_values + end + + methods + function self = ExternalSignalTimeBlock(kwargs) + arguments + kwargs.start = uint32(0); + kwargs.signal_id = uint32(0); + kwargs.signal_values = single.empty(); + end + self.start = kwargs.start; + self.signal_id = kwargs.signal_id; + self.signal_values = kwargs.signal_values; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.ExternalSignalTimeBlock") && ... + isequal({self.start}, {other.start}) && ... + isequal({self.signal_id}, {other.signal_id}) && ... + isequal({self.signal_values}, {other.signal_values}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.ExternalSignalTimeBlock(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/ExternalSignalType.m b/matlab/+petsird/ExternalSignalType.m new file mode 100644 index 0000000..801283a --- /dev/null +++ b/matlab/+petsird/ExternalSignalType.m @@ -0,0 +1,53 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ExternalSignalType < handle + properties + type + description + id + end + + methods + function self = ExternalSignalType(kwargs) + arguments + kwargs.type = petsird.ExternalSignalTypeEnum.ECG_TRACE; + kwargs.description = ""; + kwargs.id = uint32(0); + end + self.type = kwargs.type; + self.description = kwargs.description; + self.id = kwargs.id; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.ExternalSignalType") && ... + isequal({self.type}, {other.type}) && ... + isequal({self.description}, {other.description}) && ... + isequal({self.id}, {other.id}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.ExternalSignalType(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/ExternalSignalTypeEnum.m b/matlab/+petsird/ExternalSignalTypeEnum.m new file mode 100644 index 0000000..f331e5a --- /dev/null +++ b/matlab/+petsird/ExternalSignalTypeEnum.m @@ -0,0 +1,44 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ExternalSignalTypeEnum < uint64 + methods (Static) + function v = ECG_TRACE + v = petsird.ExternalSignalTypeEnum(0); + end + function v = ECG_TRIGGER + v = petsird.ExternalSignalTypeEnum(1); + end + function v = RESP_TRACE + v = petsird.ExternalSignalTypeEnum(2); + end + function v = RESP_TRIGGER + v = petsird.ExternalSignalTypeEnum(3); + end + function v = OTHER_MOTION_SIGNAL + v = petsird.ExternalSignalTypeEnum(4); + end + function v = OTHER_MOTION_TRIGGER + v = petsird.ExternalSignalTypeEnum(5); + end + function v = EXTERNAL_SYNC + v = petsird.ExternalSignalTypeEnum(6); + end + % other options, to be listed in the future + function v = OTHER + v = petsird.ExternalSignalTypeEnum(7); + end + + function z = zeros(varargin) + elem = petsird.ExternalSignalTypeEnum(0); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/GantryMovementTimeBlock.m b/matlab/+petsird/GantryMovementTimeBlock.m new file mode 100644 index 0000000..b453d33 --- /dev/null +++ b/matlab/+petsird/GantryMovementTimeBlock.m @@ -0,0 +1,50 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef GantryMovementTimeBlock < handle + properties + % start time since ExamInformation.startOfAcquisition in ms + start + transform + end + + methods + function self = GantryMovementTimeBlock(kwargs) + arguments + kwargs.start = uint32(0); + kwargs.transform = petsird.RigidTransformation(); + end + self.start = kwargs.start; + self.transform = kwargs.transform; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.GantryMovementTimeBlock") && ... + isequal({self.start}, {other.start}) && ... + isequal({self.transform}, {other.transform}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.GantryMovementTimeBlock(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/GenericSolidVolume.m b/matlab/+petsird/GenericSolidVolume.m new file mode 100644 index 0000000..6532a9d --- /dev/null +++ b/matlab/+petsird/GenericSolidVolume.m @@ -0,0 +1,4 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef GenericSolidVolume < petsird.SolidVolume +end diff --git a/matlab/+petsird/GeometricShape.m b/matlab/+petsird/GeometricShape.m new file mode 100644 index 0000000..ae20a90 --- /dev/null +++ b/matlab/+petsird/GeometricShape.m @@ -0,0 +1,49 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef GeometricShape < yardl.Union + methods (Static) + function res = BoxShape(value) + res = petsird.GeometricShape(1, value); + end + + function res = AnnulusShape(value) + res = petsird.GeometricShape(2, value); + end + + function z = zeros(varargin) + elem = petsird.GeometricShape(0, yardl.None); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end + + methods + function res = isBoxShape(self) + res = self.index == 1; + end + + function res = isAnnulusShape(self) + res = self.index == 2; + end + + function eq = eq(self, other) + eq = isa(other, "petsird.GeometricShape") && all([self.index_] == [other.index_], 'all') && all([self.value] == [other.value], 'all'); + end + + function ne = ne(self, other) + ne = ~self.eq(other); + end + + function t = tag(self) + tags_ = ["BoxShape", "AnnulusShape"]; + t = tags_(self.index_); + end + end +end diff --git a/matlab/+petsird/Header.m b/matlab/+petsird/Header.m new file mode 100644 index 0000000..fca99e7 --- /dev/null +++ b/matlab/+petsird/Header.m @@ -0,0 +1,49 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef Header < handle + properties + scanner + exam + end + + methods + function self = Header(kwargs) + arguments + kwargs.scanner = petsird.ScannerInformation(); + kwargs.exam = yardl.None; + end + self.scanner = kwargs.scanner; + self.exam = kwargs.exam; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.Header") && ... + isequal({self.scanner}, {other.scanner}) && ... + isequal({self.exam}, {other.exam}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.Header(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/Institution.m b/matlab/+petsird/Institution.m new file mode 100644 index 0000000..c81859f --- /dev/null +++ b/matlab/+petsird/Institution.m @@ -0,0 +1,49 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef Institution < handle + properties + name + address + end + + methods + function self = Institution(kwargs) + arguments + kwargs.name = ""; + kwargs.address = ""; + end + self.name = kwargs.name; + self.address = kwargs.address; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.Institution") && ... + isequal({self.name}, {other.name}) && ... + isequal({self.address}, {other.address}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.Institution(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/ModulePairEfficiencies.m b/matlab/+petsird/ModulePairEfficiencies.m new file mode 100644 index 0000000..2dc8aac --- /dev/null +++ b/matlab/+petsird/ModulePairEfficiencies.m @@ -0,0 +1,56 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ModulePairEfficiencies < handle + % Efficiency for two detecting elements (det_els) in a pair of modules. + % This is one component (often called "geometric") of the detection efficiency model. + % If size along energyBinIdx is 1, the effiencies are assumed to be the same for every energy bin. + properties + % Detection efficiency for a pair of detecting elements + % detElIdx1 and detElIdx2 run from 0 to the number of det_els in each module + values + % Symmetry Group Identifier (SGID) + % This should be a number between 0 and numberOfSGIDs-1 + sgid + end + + methods + function self = ModulePairEfficiencies(kwargs) + arguments + kwargs.values = single.empty(); + kwargs.sgid = uint32(0); + end + self.values = kwargs.values; + self.sgid = kwargs.sgid; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.ModulePairEfficiencies") && ... + isequal({self.values}, {other.values}) && ... + isequal({self.sgid}, {other.sgid}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.ModulePairEfficiencies(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/PETSIRDReaderBase.m b/matlab/+petsird/PETSIRDReaderBase.m new file mode 100644 index 0000000..ac4c006 --- /dev/null +++ b/matlab/+petsird/PETSIRDReaderBase.m @@ -0,0 +1,93 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +% Definition of the stream of data +classdef PETSIRDReaderBase < handle + properties (Access=protected) + state_ + end + + methods + function self = PETSIRDReaderBase() + self.state_ = 0; + end + + function close(self) + self.close_(); + if self.state_ ~= 2 + expected_method = self.state_to_method_name_(self.state_); + throw(yardl.ProtocolError("Protocol reader closed before all data was consumed. Expected call to '%s'.", expected_method)); + end + end + + % Ordinal 0 + function value = read_header(self) + if self.state_ ~= 0 + self.raise_unexpected_state_(0); + end + + value = self.read_header_(); + self.state_ = 1; + end + + % Ordinal 1 + function more = has_time_blocks(self) + if self.state_ ~= 1 + self.raise_unexpected_state_(1); + end + + more = self.has_time_blocks_(); + if ~more + self.state_ = 2; + end + end + + function value = read_time_blocks(self) + if self.state_ ~= 1 + self.raise_unexpected_state_(1); + end + + value = self.read_time_blocks_(); + end + + function copy_to(self, writer) + writer.write_header(self.read_header()); + while self.has_time_blocks() + item = self.read_time_blocks(); + writer.write_time_blocks({item}); + end + writer.end_time_blocks(); + end + end + + methods (Static) + function res = schema() + res = petsird.PETSIRDWriterBase.schema; + end + end + + methods (Abstract, Access=protected) + read_header_(self) + has_time_blocks_(self) + read_time_blocks_(self) + + close_(self) + end + + methods (Access=private) + function raise_unexpected_state_(self, actual) + actual_method = self.state_to_method_name_(actual); + expected_method = self.state_to_method_name_(self.state_); + throw(yardl.ProtocolError("Expected call to '%s' but received call to '%s'.", expected_method, actual_method)); + end + + function name = state_to_method_name_(self, state) + if state == 0 + name = "read_header"; + elseif state == 1 + name = "read_time_blocks"; + else + name = ""; + end + end + end +end diff --git a/matlab/+petsird/PETSIRDWriterBase.m b/matlab/+petsird/PETSIRDWriterBase.m new file mode 100644 index 0000000..1782c67 --- /dev/null +++ b/matlab/+petsird/PETSIRDWriterBase.m @@ -0,0 +1,83 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +% Abstract writer for protocol PETSIRD +% Definition of the stream of data +classdef (Abstract) PETSIRDWriterBase < handle + properties (Access=protected) + state_ + end + + methods + function self = PETSIRDWriterBase() + self.state_ = 0; + end + + function close(self) + self.close_(); + if self.state_ ~= 2 + expected_method = self.state_to_method_name_(self.state_); + throw(yardl.ProtocolError("Protocol writer closed before all steps were called. Expected call to '%s'.", expected_method)); + end + end + + % Ordinal 0 + function write_header(self, value) + if self.state_ ~= 0 + self.raise_unexpected_state_(0); + end + + self.write_header_(value); + self.state_ = 1; + end + + % Ordinal 1 + function write_time_blocks(self, value) + if self.state_ ~= 1 + self.raise_unexpected_state_(1); + end + + self.write_time_blocks_(value); + end + + function end_time_blocks(self) + if self.state_ ~= 1 + self.raise_unexpected_state_(1); + end + + self.end_stream_(); + self.state_ = 2; + end + end + + methods (Static) + function res = schema() + res = string('{"protocol":{"name":"PETSIRD","sequence":[{"name":"header","type":"PETSIRD.Header"},{"name":"timeBlocks","type":{"stream":{"items":"PETSIRD.TimeBlock"}}}]},"types":[{"name":"AnnulusShape","fields":[{"name":"innerRadius","type":"float32"},{"name":"outerRadius","type":"float32"},{"name":"thickness","type":"float32"},{"name":"angularRange","type":{"vector":{"items":"float32","length":2}}}]},{"name":"Atom","fields":[{"name":"massNumber","type":"uint32"},{"name":"atomicNumber","type":"uint32"}]},{"name":"BedMovementTimeBlock","fields":[{"name":"start","type":"uint32"},{"name":"transform","type":"PETSIRD.RigidTransformation"}]},{"name":"BoxShape","fields":[{"name":"corners","type":{"vector":{"items":"PETSIRD.Coordinate","length":8}}}]},{"name":"BoxSolidVolume","type":{"name":"PETSIRD.SolidVolume","typeArguments":["PETSIRD.BoxShape"]}},{"name":"BulkMaterial","fields":[{"name":"id","type":"uint32"},{"name":"name","type":"string"},{"name":"density","type":"float32"},{"name":"atoms","type":{"vector":{"items":"PETSIRD.Atom"}}},{"name":"massFractions","type":{"vector":{"items":"float32"}}}]},{"name":"CoincidenceEvent","fields":[{"name":"detectorIds","type":{"vector":{"items":"uint32","length":2}}},{"name":"tofIdx","type":"uint32"},{"name":"energyIndices","type":{"vector":{"items":"uint32","length":2}}}]},{"name":"CoincidencePolicy","values":[{"symbol":"rejectMultiples","value":0},{"symbol":"storeMultiplesAsPairs","value":1},{"symbol":"other","value":2}]},{"name":"Coordinate","fields":[{"name":"c","type":{"array":{"items":"float32","dimensions":[{"length":3}]}}}]},{"name":"DetElEfficiencies","type":{"array":{"items":"float32","dimensions":[{"name":"detElIdx"},{"name":"energyBinIdx"}]}}},{"name":"DetectionEfficiencies","fields":[{"name":"detElEfficiencies","type":[null,"PETSIRD.DetElEfficiencies"]},{"name":"modulePairSGIDLUT","type":[null,"PETSIRD.ModulePairSGIDLUT"]},{"name":"modulePairEfficienciesVector","type":[null,"PETSIRD.ModulePairEfficienciesVector"]}]},{"name":"DetectorModule","fields":[{"name":"detectingElements","type":{"vector":{"items":"PETSIRD.ReplicatedBoxSolidVolume"}}},{"name":"detectingElementIds","type":{"vector":{"items":"uint32"}}},{"name":"nonDetectingElements","type":{"vector":{"items":"PETSIRD.ReplicatedGenericSolidVolume"}}}]},{"name":"EventTimeBlock","fields":[{"name":"start","type":"uint32"},{"name":"promptEvents","type":{"vector":{"items":"PETSIRD.CoincidenceEvent"}}},{"name":"delayedEvents","type":[null,{"vector":{"items":"PETSIRD.CoincidenceEvent"}}]},{"name":"tripleEvents","type":[null,{"vector":{"items":"PETSIRD.TripleEvent"}}]}]},{"name":"ExamInformation","fields":[{"name":"subject","type":"PETSIRD.Subject"},{"name":"institution","type":"PETSIRD.Institution"},{"name":"protocol","type":[null,"string"]},{"name":"startOfAcquisition","type":[null,"datetime"]}]},{"name":"ExternalSignalTimeBlock","fields":[{"name":"start","type":"uint32"},{"name":"signalID","type":"uint32"},{"name":"signalValues","type":{"vector":{"items":"float32"}}}]},{"name":"GantryMovementTimeBlock","fields":[{"name":"start","type":"uint32"},{"name":"transform","type":"PETSIRD.RigidTransformation"}]},{"name":"GenericSolidVolume","type":{"name":"PETSIRD.SolidVolume","typeArguments":["PETSIRD.GeometricShape"]}},{"name":"GeometricShape","type":[{"tag":"BoxShape","type":"PETSIRD.BoxShape"},{"tag":"AnnulusShape","type":"PETSIRD.AnnulusShape"}]},{"name":"Header","fields":[{"name":"scanner","type":"PETSIRD.ScannerInformation"},{"name":"exam","type":[null,"PETSIRD.ExamInformation"]}]},{"name":"Institution","fields":[{"name":"name","type":"string"},{"name":"address","type":"string"}]},{"name":"ModulePairEfficiencies","fields":[{"name":"values","type":{"array":{"items":"float32","dimensions":[{"name":"detElIdx1"},{"name":"energyBinIdx1"},{"name":"detElIdx2"},{"name":"energyBinIdx2"}]}}},{"name":"sgid","type":"uint32"}]},{"name":"ModulePairEfficienciesVector","type":{"vector":{"items":"PETSIRD.ModulePairEfficiencies"}}},{"name":"ModulePairSGIDLUT","type":{"array":{"items":"int32","dimensions":[{"name":"moduleIdx1"},{"name":"moduleIdx2"}]}}},{"name":"ReplicatedBoxSolidVolume","type":{"name":"PETSIRD.ReplicatedObject","typeArguments":["PETSIRD.BoxSolidVolume"]}},{"name":"ReplicatedDetectorModule","type":{"name":"PETSIRD.ReplicatedObject","typeArguments":["PETSIRD.DetectorModule"]}},{"name":"ReplicatedGenericSolidVolume","type":{"name":"PETSIRD.ReplicatedObject","typeArguments":["PETSIRD.GenericSolidVolume"]}},{"name":"ReplicatedObject","typeParameters":["T"],"fields":[{"name":"object","type":"T"},{"name":"transforms","type":{"vector":{"items":"PETSIRD.RigidTransformation"}}},{"name":"ids","type":{"vector":{"items":"uint32"}}}]},{"name":"RigidTransformation","fields":[{"name":"matrix","type":{"array":{"items":"float32","dimensions":[{"length":3},{"length":4}]}}}]},{"name":"ScannerGeometry","fields":[{"name":"replicatedModules","type":{"vector":{"items":"PETSIRD.ReplicatedDetectorModule"}}},{"name":"ids","type":{"vector":{"items":"uint32"}}},{"name":"nonDetectingVolumes","type":[null,{"vector":{"items":"PETSIRD.GenericSolidVolume"}}]}]},{"name":"ScannerInformation","fields":[{"name":"modelName","type":"string"},{"name":"scannerGeometry","type":"PETSIRD.ScannerGeometry"},{"name":"bulkMaterials","type":{"vector":{"items":"PETSIRD.BulkMaterial"}}},{"name":"gantryAlignment","type":[null,"PETSIRD.RigidTransformation"]},{"name":"tofBinEdges","type":{"array":{"items":"float32","dimensions":1}}},{"name":"tofResolution","type":"float32"},{"name":"energyBinEdges","type":{"array":{"items":"float32","dimensions":1}}},{"name":"energyResolutionAt511","type":"float32"},{"name":"eventTimeBlockDuration","type":"uint32"},{"name":"coincidencePolicy","type":"PETSIRD.CoincidencePolicy"},{"name":"detectionEfficiencies","type":"PETSIRD.DetectionEfficiencies"}]},{"name":"SolidVolume","typeParameters":["Shape"],"fields":[{"name":"shape","type":"Shape"},{"name":"materialId","type":"uint32"}]},{"name":"Subject","fields":[{"name":"name","type":[null,"string"]},{"name":"id","type":"string"}]},{"name":"TimeBlock","type":[{"tag":"EventTimeBlock","type":"PETSIRD.EventTimeBlock"},{"tag":"ExternalSignalTimeBlock","type":"PETSIRD.ExternalSignalTimeBlock"},{"tag":"BedMovementTimeBlock","type":"PETSIRD.BedMovementTimeBlock"},{"tag":"GantryMovementTimeBlock","type":"PETSIRD.GantryMovementTimeBlock"}]},{"name":"TripleEvent","fields":[{"name":"detectorIds","type":{"vector":{"items":"uint32","length":3}}},{"name":"tofIndices","type":{"vector":{"items":"uint32","length":2}}},{"name":"energyIndices","type":{"vector":{"items":"uint32","length":3}}}]}]}'); + end + end + + methods (Abstract, Access=protected) + write_header_(self, value) + write_time_blocks_(self, value) + + end_stream_(self) + close_(self) + end + + methods (Access=private) + function raise_unexpected_state_(self, actual) + expected_method = self.state_to_method_name_(self.state_); + actual_method = self.state_to_method_name_(actual); + throw(yardl.ProtocolError("Expected call to '%s' but received call to '%s'", expected_method, actual_method)); + end + + function name = state_to_method_name_(self, state) + if state == 0 + name = "write_header"; + elseif state == 1 + name = "write_time_blocks or end_time_blocks"; + else + name = ''; + end + end + end +end diff --git a/matlab/+petsird/ReplicatedBoxSolidVolume.m b/matlab/+petsird/ReplicatedBoxSolidVolume.m new file mode 100644 index 0000000..285e8e2 --- /dev/null +++ b/matlab/+petsird/ReplicatedBoxSolidVolume.m @@ -0,0 +1,5 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ReplicatedBoxSolidVolume < petsird.ReplicatedObject + % A list of identical SolidVolumes at different locations +end diff --git a/matlab/+petsird/ReplicatedDetectorModule.m b/matlab/+petsird/ReplicatedDetectorModule.m new file mode 100644 index 0000000..cdbff3e --- /dev/null +++ b/matlab/+petsird/ReplicatedDetectorModule.m @@ -0,0 +1,5 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ReplicatedDetectorModule < petsird.ReplicatedObject + % A list of identical modules at different locations +end diff --git a/matlab/+petsird/ReplicatedGenericSolidVolume.m b/matlab/+petsird/ReplicatedGenericSolidVolume.m new file mode 100644 index 0000000..161cd0e --- /dev/null +++ b/matlab/+petsird/ReplicatedGenericSolidVolume.m @@ -0,0 +1,5 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ReplicatedGenericSolidVolume < petsird.ReplicatedObject + % A list of identical SolidVolumes at different locations +end diff --git a/matlab/+petsird/ReplicatedObject.m b/matlab/+petsird/ReplicatedObject.m new file mode 100644 index 0000000..2815d97 --- /dev/null +++ b/matlab/+petsird/ReplicatedObject.m @@ -0,0 +1,67 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ReplicatedObject < handle + % A list of identical objects at different locations + properties + object + % list of transforms + % constraint: length >= 1 + transforms + % list of unique ids for every replicated solid volume + % constraint: size(transforms) == size(ids) + ids + end + + methods + function self = ReplicatedObject(kwargs) + arguments + kwargs.object; + kwargs.transforms = petsird.RigidTransformation.empty(); + kwargs.ids = uint32.empty(); + end + if ~isfield(kwargs, "object") + throw(yardl.TypeError("Missing required keyword argument 'object'")) + end + self.object = kwargs.object; + self.transforms = kwargs.transforms; + self.ids = kwargs.ids; + end + + function res = number_of_objects(self) + res = length(self.transforms); + return + end + + + function res = eq(self, other) + res = ... + isa(other, "petsird.ReplicatedObject") && ... + isequal({self.object}, {other.object}) && ... + isequal({self.transforms}, {other.transforms}) && ... + isequal({self.ids}, {other.ids}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.ReplicatedObject(object=yardl.None); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/RigidTransformation.m b/matlab/+petsird/RigidTransformation.m new file mode 100644 index 0000000..947958c --- /dev/null +++ b/matlab/+petsird/RigidTransformation.m @@ -0,0 +1,48 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef RigidTransformation < handle + % Rigid transformation, encoded via homogenous transformation + % transformed_coord = matrix * [c, 1] (where [c,1] is a column vector) + % with `c` of type `Coordinate` + properties + matrix + end + + methods + function self = RigidTransformation(kwargs) + arguments + kwargs.matrix = repelem(single(0), 4, 3); + end + self.matrix = kwargs.matrix; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.RigidTransformation") && ... + isequal({self.matrix}, {other.matrix}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.RigidTransformation(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/ScannerGeometry.m b/matlab/+petsird/ScannerGeometry.m new file mode 100644 index 0000000..43d20c6 --- /dev/null +++ b/matlab/+petsird/ScannerGeometry.m @@ -0,0 +1,59 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ScannerGeometry < handle + % Full definition of the geometry of the scanner, consisting of + % one of more types of modules replicated in space and (optional) other structures (e.g. side-shielding) + properties + % list of different types of replicated modules + replicated_modules + % list of unique ids for every replicated module + % constraint: size(replicated_modules) == size(ids) + ids + % shielding etc + non_detecting_volumes + end + + methods + function self = ScannerGeometry(kwargs) + arguments + kwargs.replicated_modules = petsird.ReplicatedDetectorModule.empty(); + kwargs.ids = uint32.empty(); + kwargs.non_detecting_volumes = yardl.None; + end + self.replicated_modules = kwargs.replicated_modules; + self.ids = kwargs.ids; + self.non_detecting_volumes = kwargs.non_detecting_volumes; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.ScannerGeometry") && ... + isequal({self.replicated_modules}, {other.replicated_modules}) && ... + isequal({self.ids}, {other.ids}) && ... + isequal({self.non_detecting_volumes}, {other.non_detecting_volumes}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.ScannerGeometry(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/ScannerInformation.m b/matlab/+petsird/ScannerInformation.m new file mode 100644 index 0000000..567bbbb --- /dev/null +++ b/matlab/+petsird/ScannerInformation.m @@ -0,0 +1,117 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef ScannerInformation < handle + properties + model_name + % Geometric information for all detector elements + % All coordinates are in the PET gantry coordinate system. + scanner_geometry + % List of materials present in the scanner geometry. The `material_id`s there will refer to the + % identifiers in this list below. + bulk_materials + % Fixed transformation to reference location for this scanner. + % This field can be used to encode alignment with the CT or MRI gantry for instance. + % The transformation should convert from the PET gantry coordinate system to the reference. + % An empty field implies the identity transformation. + gantry_alignment + % Edge information for TOF bins in mm (given as from first to last edge, so there is one more edge than the number of bins) + % 0 corresponds to the same arrival time. Negative numbers indicate that the first detector detected first. + % For instance, a coincidence event is stored as 2 detectorIds, denoting the arrival time at the first + % detector t1 and the arrival time at the second detector t2, we store (t1-t2)*c/2. + % Note: for non-TOF scanners, this defines the coincidence window + % TODO: this currently assumes equal size for each TOF bin, but some scanners "stretch" TOF bins depending on length of LOR + tof_bin_edges + % TOF resolution (as FWHM) in mm + % Scanner coincidence timing resolution (CTR) without tof-binning + tof_resolution + % Edge information for energy windows in keV (given as from first to last edge, so there is one more edge than the number of bins) + energy_bin_edges + % FWHM of photopeak for incoming gamma of 511 keV, expressed as a ratio w.r.t. 511 + energy_resolution_at_511 + % duration of each event time block in ms + event_time_block_duration + % Encode how the scanner handles multiple coincidences + coincidence_policy + % coincidence detection efficiencies + detection_efficiencies + end + + methods + function self = ScannerInformation(kwargs) + arguments + kwargs.model_name = ""; + kwargs.scanner_geometry = petsird.ScannerGeometry(); + kwargs.bulk_materials = petsird.BulkMaterial.empty(); + kwargs.gantry_alignment = yardl.None; + kwargs.tof_bin_edges = single.empty(); + kwargs.tof_resolution = single(0); + kwargs.energy_bin_edges = single.empty(); + kwargs.energy_resolution_at_511 = single(0); + kwargs.event_time_block_duration = uint32(0); + kwargs.coincidence_policy = petsird.CoincidencePolicy.REJECT_MULTIPLES; + kwargs.detection_efficiencies = petsird.DetectionEfficiencies(); + end + self.model_name = kwargs.model_name; + self.scanner_geometry = kwargs.scanner_geometry; + self.bulk_materials = kwargs.bulk_materials; + self.gantry_alignment = kwargs.gantry_alignment; + self.tof_bin_edges = kwargs.tof_bin_edges; + self.tof_resolution = kwargs.tof_resolution; + self.energy_bin_edges = kwargs.energy_bin_edges; + self.energy_resolution_at_511 = kwargs.energy_resolution_at_511; + self.event_time_block_duration = kwargs.event_time_block_duration; + self.coincidence_policy = kwargs.coincidence_policy; + self.detection_efficiencies = kwargs.detection_efficiencies; + end + + function res = number_of_tof_bins(self) + res = numel(self.tof_bin_edges) - 1; + return + end + + function res = number_of_energy_bins(self) + res = numel(self.energy_bin_edges) - 1; + return + end + + + function res = eq(self, other) + res = ... + isa(other, "petsird.ScannerInformation") && ... + isequal({self.model_name}, {other.model_name}) && ... + isequal({self.scanner_geometry}, {other.scanner_geometry}) && ... + isequal({self.bulk_materials}, {other.bulk_materials}) && ... + isequal({self.gantry_alignment}, {other.gantry_alignment}) && ... + isequal({self.tof_bin_edges}, {other.tof_bin_edges}) && ... + isequal({self.tof_resolution}, {other.tof_resolution}) && ... + isequal({self.energy_bin_edges}, {other.energy_bin_edges}) && ... + isequal({self.energy_resolution_at_511}, {other.energy_resolution_at_511}) && ... + isequal({self.event_time_block_duration}, {other.event_time_block_duration}) && ... + isequal({self.coincidence_policy}, {other.coincidence_policy}) && ... + isequal({self.detection_efficiencies}, {other.detection_efficiencies}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.ScannerInformation(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/SolidVolume.m b/matlab/+petsird/SolidVolume.m new file mode 100644 index 0000000..bbb6179 --- /dev/null +++ b/matlab/+petsird/SolidVolume.m @@ -0,0 +1,54 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef SolidVolume < handle + % A shape filled with a uniform material + properties + shape + % identifier referring to `ScannerInformation.bulkMaterials` list + material_id + end + + methods + function self = SolidVolume(kwargs) + arguments + kwargs.shape; + kwargs.material_id = uint32(0); + end + if ~isfield(kwargs, "shape") + throw(yardl.TypeError("Missing required keyword argument 'shape'")) + end + self.shape = kwargs.shape; + self.material_id = kwargs.material_id; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.SolidVolume") && ... + isequal({self.shape}, {other.shape}) && ... + isequal({self.material_id}, {other.material_id}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.SolidVolume(shape=yardl.None); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/Subject.m b/matlab/+petsird/Subject.m new file mode 100644 index 0000000..07c8271 --- /dev/null +++ b/matlab/+petsird/Subject.m @@ -0,0 +1,49 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef Subject < handle + properties + name + id + end + + methods + function self = Subject(kwargs) + arguments + kwargs.name = yardl.None; + kwargs.id = ""; + end + self.name = kwargs.name; + self.id = kwargs.id; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.Subject") && ... + isequal({self.name}, {other.name}) && ... + isequal({self.id}, {other.id}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.Subject(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/TimeBlock.m b/matlab/+petsird/TimeBlock.m new file mode 100644 index 0000000..e00300f --- /dev/null +++ b/matlab/+petsird/TimeBlock.m @@ -0,0 +1,65 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef TimeBlock < yardl.Union + methods (Static) + function res = EventTimeBlock(value) + res = petsird.TimeBlock(1, value); + end + + function res = ExternalSignalTimeBlock(value) + res = petsird.TimeBlock(2, value); + end + + function res = BedMovementTimeBlock(value) + res = petsird.TimeBlock(3, value); + end + + function res = GantryMovementTimeBlock(value) + res = petsird.TimeBlock(4, value); + end + + function z = zeros(varargin) + elem = petsird.TimeBlock(0, yardl.None); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end + + methods + function res = isEventTimeBlock(self) + res = self.index == 1; + end + + function res = isExternalSignalTimeBlock(self) + res = self.index == 2; + end + + function res = isBedMovementTimeBlock(self) + res = self.index == 3; + end + + function res = isGantryMovementTimeBlock(self) + res = self.index == 4; + end + + function eq = eq(self, other) + eq = isa(other, "petsird.TimeBlock") && all([self.index_] == [other.index_], 'all') && all([self.value] == [other.value], 'all'); + end + + function ne = ne(self, other) + ne = ~self.eq(other); + end + + function t = tag(self) + tags_ = ["EventTimeBlock", "ExternalSignalTimeBlock", "BedMovementTimeBlock", "GantryMovementTimeBlock"]; + t = tags_(self.index_); + end + end +end diff --git a/matlab/+petsird/TimeFrameInformation.m b/matlab/+petsird/TimeFrameInformation.m new file mode 100644 index 0000000..1619b43 --- /dev/null +++ b/matlab/+petsird/TimeFrameInformation.m @@ -0,0 +1,52 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef TimeFrameInformation < handle + % A sequence of time intervals (could be consecutive) + properties + time_frames + end + + methods + function self = TimeFrameInformation(kwargs) + arguments + kwargs.time_frames = petsird.TimeInterval.empty(); + end + self.time_frames = kwargs.time_frames; + end + + function res = number_of_time_frames(self) + res = length(self.time_frames); + return + end + + + function res = eq(self, other) + res = ... + isa(other, "petsird.TimeFrameInformation") && ... + isequal({self.time_frames}, {other.time_frames}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.TimeFrameInformation(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/TimeInterval.m b/matlab/+petsird/TimeInterval.m new file mode 100644 index 0000000..130cfe0 --- /dev/null +++ b/matlab/+petsird/TimeInterval.m @@ -0,0 +1,50 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef TimeInterval < handle + % Time interval in milliseconds since start of acquisition + properties + start + stop + end + + methods + function self = TimeInterval(kwargs) + arguments + kwargs.start = uint32(0); + kwargs.stop = uint32(0); + end + self.start = kwargs.start; + self.stop = kwargs.stop; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.TimeInterval") && ... + isequal({self.start}, {other.start}) && ... + isequal({self.stop}, {other.stop}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.TimeInterval(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+petsird/TripleEvent.m b/matlab/+petsird/TripleEvent.m new file mode 100644 index 0000000..518d24a --- /dev/null +++ b/matlab/+petsird/TripleEvent.m @@ -0,0 +1,59 @@ +% This file was generated by the "yardl" tool. DO NOT EDIT. + +classdef TripleEvent < handle + % All information about a triple event specified as identifiers or indices (i.e. discretized). + properties + detector_ids + % timing differences (converted to mm) w.r.t. first event, stored as + % indices into the tofBinEdges field in the ScannerInformation + % Note: only 2, corresponding to the arrival time differences of the second and third detectorId + % listed w.r.t. the first detectorId + tof_indices + % indices for each single event into the energyBinEdges field in the ScannerInformation + energy_indices + end + + methods + function self = TripleEvent(kwargs) + arguments + kwargs.detector_ids = repelem(uint32(0), 3); + kwargs.tof_indices = repelem(uint32(0), 2); + kwargs.energy_indices = repelem(uint32(0), 3); + end + self.detector_ids = kwargs.detector_ids; + self.tof_indices = kwargs.tof_indices; + self.energy_indices = kwargs.energy_indices; + end + + function res = eq(self, other) + res = ... + isa(other, "petsird.TripleEvent") && ... + isequal({self.detector_ids}, {other.detector_ids}) && ... + isequal({self.tof_indices}, {other.tof_indices}) && ... + isequal({self.energy_indices}, {other.energy_indices}); + end + + function res = ne(self, other) + res = ~self.eq(other); + end + + function res = isequal(self, other) + res = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = petsird.TripleEvent(); + if nargin == 0 + z = elem; + return; + end + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+yardl/+binary/BinaryProtocolReader.m b/matlab/+yardl/+binary/BinaryProtocolReader.m new file mode 100644 index 0000000..1180269 --- /dev/null +++ b/matlab/+yardl/+binary/BinaryProtocolReader.m @@ -0,0 +1,40 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef BinaryProtocolReader < handle + + properties (Access=protected) + stream_ + end + + methods + function self = BinaryProtocolReader(infile, expected_schema) + self.stream_ = yardl.binary.CodedInputStream(infile); + magic_bytes = self.stream_.read_bytes(length(yardl.binary.MAGIC_BYTES)); + if magic_bytes ~= yardl.binary.MAGIC_BYTES + throw(yardl.ProtocolError("Invalid magic bytes")); + end + + version = read_fixed_int32(self.stream_); + if version ~= yardl.binary.CURRENT_BINARY_FORMAT_VERSION + throw(yardl.ProtocolError("Invalid binary format version")); + end + + s = yardl.binary.StringSerializer(); + schema = s.read(self.stream_); + if ~isempty(expected_schema) & schema ~= expected_schema + throw(yardl.ProtocolError("Invalid schema")); + end + end + end + + methods (Access=protected) + function close_(self) + self.stream_.close(); + end + end +end + +function res = read_fixed_int32(stream) + res = typecast(stream.read_bytes(4), "int32"); +end diff --git a/matlab/+yardl/+binary/BinaryProtocolWriter.m b/matlab/+yardl/+binary/BinaryProtocolWriter.m new file mode 100644 index 0000000..4a5378a --- /dev/null +++ b/matlab/+yardl/+binary/BinaryProtocolWriter.m @@ -0,0 +1,37 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef BinaryProtocolWriter < handle + + properties (Access=protected) + stream_ + end + + methods + function self = BinaryProtocolWriter(outfile, schema) + self.stream_ = yardl.binary.CodedOutputStream(outfile); + self.stream_.write_bytes(yardl.binary.MAGIC_BYTES); + write_fixed_int32(self.stream_, yardl.binary.CURRENT_BINARY_FORMAT_VERSION); + s = yardl.binary.StringSerializer(); + s.write(self.stream_, schema); + end + end + + methods (Access=protected) + function end_stream_(self) + self.stream_.write_byte(uint8(0)); + end + + function close_(self) + self.stream_.close(); + end + end +end + +function write_fixed_int32(stream, value) + arguments + stream (1,1) yardl.binary.CodedOutputStream + value (1,1) {mustBeA(value, "int32")} + end + stream.write_bytes(typecast(value, "uint8")); +end diff --git a/matlab/+yardl/+binary/BoolSerializer.m b/matlab/+yardl/+binary/BoolSerializer.m new file mode 100644 index 0000000..8311273 --- /dev/null +++ b/matlab/+yardl/+binary/BoolSerializer.m @@ -0,0 +1,28 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef BoolSerializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + arguments + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) {mustBeInRange(value, 0, 1)} + end + byte = cast(value, "uint8"); + outstream.write_bytes(byte); + end + + function res = read(instream) + byte = instream.read_byte(); + res = cast(byte, "logical"); + end + + function c = get_class() + c = "logical"; + end + + function trivial = is_trivially_serializable() + trivial = true; + end + end +end diff --git a/matlab/+yardl/+binary/CURRENT_BINARY_FORMAT_VERSION.m b/matlab/+yardl/+binary/CURRENT_BINARY_FORMAT_VERSION.m new file mode 100644 index 0000000..2fcacad --- /dev/null +++ b/matlab/+yardl/+binary/CURRENT_BINARY_FORMAT_VERSION.m @@ -0,0 +1,6 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +function res = CURRENT_BINARY_FORMAT_VERSION + res = int32(1); +end diff --git a/matlab/+yardl/+binary/CodedInputStream.m b/matlab/+yardl/+binary/CodedInputStream.m new file mode 100644 index 0000000..34e03ca --- /dev/null +++ b/matlab/+yardl/+binary/CodedInputStream.m @@ -0,0 +1,74 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef CodedInputStream < handle + + properties (Access=private) + fid_ + owns_stream_ + end + + methods + function self = CodedInputStream(infile) + if isa(infile, "string") || isa(infile, "char") + [fileId, errMsg] = fopen(infile, "r"); + if fileId < 0 + throw(yardl.RuntimeError(errMsg)); + end + self.fid_ = fileId; + self.owns_stream_ = true; + else + self.fid_ = infile; + self.owns_stream_ = false; + end + end + + function close(self) + if self.owns_stream_ && self.fid_ > 2 + fclose(self.fid_); + self.fid_ = -1; + end + end + + function res = read_bytes(self, count) + res = fread(self.fid_, count, "*uint8"); + if iscolumn(res) + res = transpose(res); + end + end + + function res = read_byte(self) + res = fread(self.fid_, 1, "*uint8"); + end + + function res = read_values_directly(self, shape, precision) + res = fread(self.fid_, shape, "*"+precision); + if iscolumn(res) + res = transpose(res); + end + end + + function res = read_unsigned_varint(self) + res = uint64(0); + shift = uint8(0); + + while true + byte = self.read_byte(); + res = bitor(res, bitshift(uint64(bitand(byte, 0x7F)), shift)); + if byte < 0x80 + return + end + shift = shift + 7; + end + end + + function res = zigzag_decode(~, value) + value = uint64(value); + res = bitxor(int64(bitshift(value, -1)), -int64(bitand(value, 1))); + end + + function res = read_signed_varint(self) + res = self.zigzag_decode(self.read_unsigned_varint()); + end + end +end diff --git a/matlab/+yardl/+binary/CodedOutputStream.m b/matlab/+yardl/+binary/CodedOutputStream.m new file mode 100644 index 0000000..c2aedf3 --- /dev/null +++ b/matlab/+yardl/+binary/CodedOutputStream.m @@ -0,0 +1,84 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef CodedOutputStream < handle + + properties (Access=private) + fid_ + owns_stream_ + end + + methods + function self = CodedOutputStream(outfile) + if isa(outfile, "string") || isa(outfile, "char") + [fileId, errMsg] = fopen(outfile, "W"); + if fileId < 0 + throw(yardl.RuntimeError(errMsg)); + end + self.fid_ = fileId; + self.owns_stream_ = true; + else + self.fid_ = outfile; + self.owns_stream_ = false; + end + end + + function close(self) + if self.owns_stream_ && self.fid_ > 2 + fclose(self.fid_); + self.fid_ = -1; + end + end + + function write_bytes(self, bytes) + arguments + self + bytes (1,:) {mustBeA(bytes, "uint8")} + end + fwrite(self.fid_, bytes, "uint8"); + end + + function write_byte(self, value) + arguments + self + value (1,1) {mustBeA(value, "uint8")} + end + fwrite(self.fid_, value, "uint8"); + end + + function write_values_directly(self, values, precision) + fwrite(self.fid_, values, precision); + end + + function write_unsigned_varint(self, value) + arguments + self + value (1,1) {mustBeInteger,mustBeNonnegative} + end + + int_val = uint64(value); + while true + if int_val < 0x80 + self.write_byte(uint8(int_val)); + return + end + + self.write_byte(uint8(bitor(bitand(int_val, uint64(0x7F)), uint64(0x80)))); + int_val = bitshift(int_val, -7); + end + end + + function res = zigzag_encode(~, value) + int_val = int64(value); + res = bitxor(bitshift(int_val, 1), bitshift(int_val, -63)); + end + + function write_signed_varint(self, value) + arguments + self + value (1,1) {mustBeInteger} + end + self.write_unsigned_varint(self.zigzag_encode(value)); + end + end +end diff --git a/matlab/+yardl/+binary/Complexfloat32Serializer.m b/matlab/+yardl/+binary/Complexfloat32Serializer.m new file mode 100644 index 0000000..041edb8 --- /dev/null +++ b/matlab/+yardl/+binary/Complexfloat32Serializer.m @@ -0,0 +1,49 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Complexfloat32Serializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + arguments + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) single + end + real_bytes = typecast(single(real(value)), "uint8"); + imag_bytes = typecast(single(imag(value)), "uint8"); + outstream.write_bytes(real_bytes); + outstream.write_bytes(imag_bytes); + end + + function res = read(instream) + real_bytes = instream.read_bytes(4); + imag_bytes = instream.read_bytes(4); + res = complex(typecast(real_bytes, "single"), typecast(imag_bytes, "single")); + end + + function c = get_class() + c = "single"; + end + + function trivial = is_trivially_serializable() + trivial = true; + end + end + + methods + function write_trivially(self, stream, values) + rp = real(values); + ip = imag(values); + parts(1, :) = rp(:); + parts(2, :) = ip(:); + stream.write_values_directly(parts, self.get_class()); + end + + function res = read_trivially(self, stream, shape) + assert(ndims(shape) == 2); + partshape = [2*shape(1) shape(2)]; + res = stream.read_values_directly(partshape, self.get_class()); + res = reshape(res, [2 shape]); + res = squeeze(complex(res(1, :, :), res(2, :, :))); + end + end +end diff --git a/matlab/+yardl/+binary/Complexfloat64Serializer.m b/matlab/+yardl/+binary/Complexfloat64Serializer.m new file mode 100644 index 0000000..5f6fba6 --- /dev/null +++ b/matlab/+yardl/+binary/Complexfloat64Serializer.m @@ -0,0 +1,49 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Complexfloat64Serializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + arguments + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) double + end + real_bytes = typecast(double(real(value)), "uint8"); + imag_bytes = typecast(double(imag(value)), "uint8"); + outstream.write_bytes(real_bytes); + outstream.write_bytes(imag_bytes); + end + + function res = read(instream) + real_bytes = instream.read_bytes(8); + imag_bytes = instream.read_bytes(8); + res = complex(typecast(real_bytes, "double"), typecast(imag_bytes, "double")); + end + + function c = get_class() + c = "double"; + end + + function trivial = is_trivially_serializable() + trivial = true; + end + end + + methods + function write_trivially(self, stream, values) + rp = real(values); + ip = imag(values); + parts(1, :) = rp(:); + parts(2, :) = ip(:); + stream.write_values_directly(parts, self.get_class()); + end + + function res = read_trivially(self, stream, shape) + assert(ndims(shape) == 2); + partshape = [2*shape(1) shape(2)]; + res = stream.read_values_directly(partshape, self.get_class()); + res = reshape(res, [2 shape]); + res = squeeze(complex(res(1, :, :), res(2, :, :))); + end + end +end diff --git a/matlab/+yardl/+binary/DateSerializer.m b/matlab/+yardl/+binary/DateSerializer.m new file mode 100644 index 0000000..20f78c3 --- /dev/null +++ b/matlab/+yardl/+binary/DateSerializer.m @@ -0,0 +1,26 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef DateSerializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + if isa(value, "datetime") + value = yardl.Date.from_datetime(value).value; + elseif isa(value, "yardl.Date") + value = value.value; + else + throw(yardl.TypeError("Expected datetime or yardl.Date, got %s", class(value))); + end + outstream.write_signed_varint(value); + end + + function res = read(instream) + value = instream.read_signed_varint(); + res = yardl.Date(value); + end + + function c = get_class() + c = "yardl.Date"; + end + end +end diff --git a/matlab/+yardl/+binary/DatetimeSerializer.m b/matlab/+yardl/+binary/DatetimeSerializer.m new file mode 100644 index 0000000..07f813b --- /dev/null +++ b/matlab/+yardl/+binary/DatetimeSerializer.m @@ -0,0 +1,26 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef DatetimeSerializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + if isa(value, "datetime") + value = yardl.DateTime.from_datetime(value).value; + elseif isa(value, "yardl.DateTime") + value = value.value; + else + throw(yardl.TypeError("Expected datetime or yardl.DateTime, got %s", class(value))); + end + outstream.write_signed_varint(value); + end + + function res = read(instream) + value = instream.read_signed_varint(); + res = yardl.DateTime(value); + end + + function c = get_class() + c = "yardl.DateTime"; + end + end +end diff --git a/matlab/+yardl/+binary/DynamicNDArraySerializer.m b/matlab/+yardl/+binary/DynamicNDArraySerializer.m new file mode 100644 index 0000000..4f7f8c5 --- /dev/null +++ b/matlab/+yardl/+binary/DynamicNDArraySerializer.m @@ -0,0 +1,47 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef DynamicNDArraySerializer < yardl.binary.NDArraySerializerBase + + methods + function self = DynamicNDArraySerializer(item_serializer) + self@yardl.binary.NDArraySerializerBase(item_serializer); + end + + function write(self, outstream, values) + item_shape = self.item_serializer_.get_shape(); + shape = size(values); + if isempty(item_shape) + % values is an array of variable-length vectors or arrays + values = values(:); + elseif isscalar(item_shape) + % values is an array of scalars + values = values(:); + else + % values is an array of fixed-length vectors or arrays + item_shape = item_shape(item_shape > 1); + outer_shape = shape(length(item_shape) + 1:end); + values = reshape(values, [item_shape prod(outer_shape)]); + shape = outer_shape; + end + + outstream.write_unsigned_varint(length(shape)); + flipped_shape = flip(shape); + for dim = 1:length(flipped_shape) + outstream.write_unsigned_varint(flipped_shape(dim)); + end + + self.write_data_(outstream, values); + end + + function value = read(self, instream) + ndims = instream.read_unsigned_varint(); + flipped_shape = zeros(1, ndims); + for dim = 1:ndims + flipped_shape(dim) = instream.read_unsigned_varint(); + end + shape = flip(flipped_shape); + value = self.read_data_(instream, shape); + end + end +end diff --git a/matlab/+yardl/+binary/EnumSerializer.m b/matlab/+yardl/+binary/EnumSerializer.m new file mode 100644 index 0000000..307eeb9 --- /dev/null +++ b/matlab/+yardl/+binary/EnumSerializer.m @@ -0,0 +1,43 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef EnumSerializer < yardl.binary.TypeSerializer + properties + classname_; + constructor_; + integer_serializer_; + end + + methods + function self = EnumSerializer(classname, classconstructor, integer_serializer) + self.classname_ = classname; + self.constructor_ = classconstructor; + self.integer_serializer_ = integer_serializer; + end + + function write(self, outstream, value) + self.integer_serializer_.write(outstream, value); + end + + function res = read(self, instream) + int_value = self.integer_serializer_.read(instream); + res = self.constructor_(int_value); + end + + function c = get_class(self) + c = self.classname_; + end + + function trivial = is_trivially_serializable(self) + trivial = self.integer_serializer_.is_trivially_serializable(); + end + + function write_trivially(self, outstream, values) + self.integer_serializer_.write_trivially(outstream, values); + end + + function res = read_trivially(self, instream, shape) + res = self.integer_serializer_.read_trivially(instream, shape); + end + end +end diff --git a/matlab/+yardl/+binary/FixedNDArraySerializer.m b/matlab/+yardl/+binary/FixedNDArraySerializer.m new file mode 100644 index 0000000..58871f4 --- /dev/null +++ b/matlab/+yardl/+binary/FixedNDArraySerializer.m @@ -0,0 +1,72 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef FixedNDArraySerializer < yardl.binary.NDArraySerializerBase + + properties + shape_ + end + + methods + function self = FixedNDArraySerializer(item_serializer, shape) + self@yardl.binary.NDArraySerializerBase(item_serializer); + self.shape_ = shape; + end + + function write(self, outstream, values) + if numel(values) == prod(self.shape_) + % This is an NDArray of scalars + self.write_data_(outstream, values(:)); + return; + end + + sz = size(values); + if length(sz) < length(self.shape_) + expected = sprintf("%d ", self.shape_); + actual = sprintf("%d ", sz); + throw(yardl.ValueError("Expected shape [%s], got [%s]", expected, actual)); + end + + fixedSize = sz(end-length(self.shape_)+1:end); + if fixedSize ~= self.shape_ + expected = sprintf("%d ", self.shape_); + actual = sprintf("%d ", fixedSize); + throw(yardl.ValueError("Expected shape [%s], got [%s]", expected, actual)); + end + + inner_shape = sz(1:end-length(self.shape_)); + values = reshape(values, [inner_shape prod(self.shape_)]); + + self.write_data_(outstream, values); + end + + function value = read(self, instream) + value = self.read_data_(instream, self.shape_); + end + + function s = get_shape(self) + item_shape = self.item_serializer_.get_shape(); + if isempty(item_shape) + s = self.shape_; + else + s = [item_shape self.shape_]; + end + + if length(s) > 2 + s = s(s>1); + end + end + + function trivial = is_trivially_serializable(self) + trivial = self.item_serializer_.is_trivially_serializable(); + end + + function write_trivially(self, outstream, values) + self.item_serializer_.write_trivially(outstream, values); + end + + function res = read_trivially(self, instream, shape) + res = self.item_serializer_.read_trivially(instream, shape); + end + end +end diff --git a/matlab/+yardl/+binary/FixedVectorSerializer.m b/matlab/+yardl/+binary/FixedVectorSerializer.m new file mode 100644 index 0000000..35dafc2 --- /dev/null +++ b/matlab/+yardl/+binary/FixedVectorSerializer.m @@ -0,0 +1,51 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef FixedVectorSerializer < yardl.binary.VectorSerializerBase + properties + length_; + end + + methods (Access=protected) + function handle_write_count_(self, ~, count) + if count ~= self.length_ + throw(yardl.ValueError("Expected an array of length %d, got %d", self.length_, count)); + end + end + + function count = get_read_count_(self, ~) + count = self.length_; + end + end + + methods + function self = FixedVectorSerializer(item_serializer, length) + self@yardl.binary.VectorSerializerBase(item_serializer); + self.length_ = length; + end + + function s = get_shape(self) + item_shape = self.item_serializer_.get_shape(); + if isempty(item_shape) + s = [1, self.length_]; + elseif isscalar(item_shape) + s = [item_shape self.length_]; + else + s = [item_shape self.length_]; + s = s(s>1); + end + end + + function trivial = is_trivially_serializable(self) + trivial = self.item_serializer_.is_trivially_serializable(); + end + + function write_trivially(self, outstream, values) + self.item_serializer_.write_trivially(outstream, values); + end + + function res = read_trivially(self, instream, shape) + res = self.item_serializer_.read_trivially(instream, shape); + end + end +end diff --git a/matlab/+yardl/+binary/Float32Serializer.m b/matlab/+yardl/+binary/Float32Serializer.m new file mode 100644 index 0000000..021e623 --- /dev/null +++ b/matlab/+yardl/+binary/Float32Serializer.m @@ -0,0 +1,29 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Float32Serializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + arguments + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) single + end + + bytes = typecast(single(value), "uint8"); + outstream.write_bytes(bytes); + end + + function res = read(instream) + bytes = instream.read_bytes(4); + res = typecast(bytes, "single"); + end + + function c = get_class() + c = "single"; + end + + function trivial = is_trivially_serializable() + trivial = true; + end + end +end diff --git a/matlab/+yardl/+binary/Float64Serializer.m b/matlab/+yardl/+binary/Float64Serializer.m new file mode 100644 index 0000000..4f58367 --- /dev/null +++ b/matlab/+yardl/+binary/Float64Serializer.m @@ -0,0 +1,28 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Float64Serializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + arguments + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) double + end + bytes = typecast(double(value), "uint8"); + outstream.write_bytes(bytes); + end + + function res = read(instream) + bytes = instream.read_bytes(8); + res = typecast(bytes, "double"); + end + + function c = get_class() + c = "double"; + end + + function trivial = is_trivially_serializable() + trivial = true; + end + end +end diff --git a/matlab/+yardl/+binary/Int16Serializer.m b/matlab/+yardl/+binary/Int16Serializer.m new file mode 100644 index 0000000..8f140d8 --- /dev/null +++ b/matlab/+yardl/+binary/Int16Serializer.m @@ -0,0 +1,22 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Int16Serializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + arguments + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) {mustBeInRange(value, -32768, 32767)} + end + outstream.write_signed_varint(value); + end + + function res = read(instream) + res = int16(instream.read_signed_varint()); + end + + function c = get_class() + c = "int16"; + end + end +end diff --git a/matlab/+yardl/+binary/Int32Serializer.m b/matlab/+yardl/+binary/Int32Serializer.m new file mode 100644 index 0000000..20fc3d3 --- /dev/null +++ b/matlab/+yardl/+binary/Int32Serializer.m @@ -0,0 +1,22 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Int32Serializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + arguments + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) {mustBeInRange(value, -2147483648, 2147483647)} + end + outstream.write_signed_varint(value); + end + + function res = read(instream) + res = int32(instream.read_signed_varint()); + end + + function c = get_class() + c = "int32"; + end + end +end diff --git a/matlab/+yardl/+binary/Int64Serializer.m b/matlab/+yardl/+binary/Int64Serializer.m new file mode 100644 index 0000000..2176a93 --- /dev/null +++ b/matlab/+yardl/+binary/Int64Serializer.m @@ -0,0 +1,22 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Int64Serializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + arguments + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) {mustBeInRange(value, -9223372036854775808, 9223372036854775807)} + end + outstream.write_signed_varint(value); + end + + function res = read(instream) + res = int64(instream.read_signed_varint()); + end + + function c = get_class() + c = "int64"; + end + end +end diff --git a/matlab/+yardl/+binary/Int8Serializer.m b/matlab/+yardl/+binary/Int8Serializer.m new file mode 100644 index 0000000..ecf037c --- /dev/null +++ b/matlab/+yardl/+binary/Int8Serializer.m @@ -0,0 +1,27 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Int8Serializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + arguments + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) {mustBeInRange(value, -128, 127)} + end + byte = typecast(int8(value), "uint8"); + outstream.write_byte(byte); + end + + function res = read(instream) + res = typecast(instream.read_byte(), "int8"); + end + + function c = get_class() + c = "int8"; + end + + function trivial = is_trivially_serializable() + trivial = true; + end + end +end diff --git a/matlab/+yardl/+binary/MAGIC_BYTES.m b/matlab/+yardl/+binary/MAGIC_BYTES.m new file mode 100644 index 0000000..4391975 --- /dev/null +++ b/matlab/+yardl/+binary/MAGIC_BYTES.m @@ -0,0 +1,6 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +function res = MAGIC_BYTES + res = unicode2native('yardl'); +end diff --git a/matlab/+yardl/+binary/MapSerializer.m b/matlab/+yardl/+binary/MapSerializer.m new file mode 100644 index 0000000..e8dfcec --- /dev/null +++ b/matlab/+yardl/+binary/MapSerializer.m @@ -0,0 +1,51 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef MapSerializer < yardl.binary.TypeSerializer + properties + key_serializer_; + value_serializer_; + end + + methods + function self = MapSerializer(key_serializer, value_serializer) + self.key_serializer_ = key_serializer; + self.value_serializer_ = value_serializer; + end + + function write(self, outstream, value) + arguments + self (1,1) + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) yardl.Map + end + + count = numEntries(value); + outstream.write_unsigned_varint(count); + if count == 0 + return + end + + ks = keys(value); + vs = values(value); + for i = 1:count + self.key_serializer_.write(outstream, ks(i)); + self.value_serializer_.write(outstream, vs(i)); + end + end + + function res = read(self, instream) + count = instream.read_unsigned_varint(); + res = yardl.Map(); + for i = 1:count + k = self.key_serializer_.read(instream); + v = self.value_serializer_.read(instream); + insert(res, k, v); + end + end + + function c = get_class(~) + c = "yardl.Map"; + end + end +end diff --git a/matlab/+yardl/+binary/NDArraySerializer.m b/matlab/+yardl/+binary/NDArraySerializer.m new file mode 100644 index 0000000..cde6434 --- /dev/null +++ b/matlab/+yardl/+binary/NDArraySerializer.m @@ -0,0 +1,51 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef NDArraySerializer < yardl.binary.NDArraySerializerBase + + properties + ndims_ + end + + methods + function self = NDArraySerializer(item_serializer, ndims) + self@yardl.binary.NDArraySerializerBase(item_serializer); + self.ndims_ = ndims; + end + + function write(self, outstream, values) + sz = size(values); + if ndims(values) < self.ndims_ + sz = [sz ones(1, self.ndims_-ndims(values))]; + end + + flipped_shape = flip(sz); + for dim = 1:self.ndims_ + len = flipped_shape(dim); + outstream.write_unsigned_varint(len); + end + + if length(sz) == self.ndims_ + % This is an NDArray of scalars + self.write_data_(outstream, values(:)); + return + end + + % This is an NDArray of vectors/arrays + inner_shape = sz(1:end-self.ndims_); + outer_shape = sz(end-self.ndims_+1:end); + values = reshape(values, [inner_shape prod(outer_shape)]); + + self.write_data_(outstream, values); + end + + function value = read(self, instream) + flipped_shape = zeros(1, self.ndims_); + for dim = 1:self.ndims_ + flipped_shape(dim) = instream.read_unsigned_varint(); + end + shape = flip(flipped_shape); + value = self.read_data_(instream, shape); + end + end +end diff --git a/matlab/+yardl/+binary/NDArraySerializerBase.m b/matlab/+yardl/+binary/NDArraySerializerBase.m new file mode 100644 index 0000000..12cf775 --- /dev/null +++ b/matlab/+yardl/+binary/NDArraySerializerBase.m @@ -0,0 +1,106 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef NDArraySerializerBase < yardl.binary.TypeSerializer + + properties + item_serializer_ + end + + methods (Abstract) + write(self, outstream, values) + read(self, instream) + end + + methods (Access=protected) + function self = NDArraySerializerBase(item_serializer) + self.item_serializer_ = item_serializer; + end + + function write_data_(self, outstream, values) + % values is an array of shape [A, B, ..., N], where + % N is the "flattened" dimension of the NDArray, and + % A, B, ... are the dimensions of the inner items. + + if ~iscell(values) && self.item_serializer_.is_trivially_serializable() + self.item_serializer_.write_trivially(outstream, values); + return; + end + + sz = size(values); + + if ndims(values) > 2 + count = sz(end); + inner_shape = sz(1:end-1); + r = reshape(values, [], count); + for i = 1:count + val = reshape(r(:, i), inner_shape); + self.item_serializer_.write(outstream, val); + end + elseif isrow(values) || iscolumn(values) + count = prod(sz); + if iscell(values) + for i = 1:count + self.item_serializer_.write(outstream, values{i}); + end + else + for i = 1:count + self.item_serializer_.write(outstream, values(i)); + end + end + else + count = sz(end); + for i = 1:count + self.item_serializer_.write(outstream, values(:, i)); + end + end + end + + function res = read_data_(self, instream, shape) + flat_length = prod(shape); + + item_shape = self.item_serializer_.get_shape(); + + if isempty(item_shape) + res = cell(shape); + for i = 1:flat_length + res{i} = self.item_serializer_.read(instream); + end + return + end + + if self.item_serializer_.is_trivially_serializable() + res = self.item_serializer_.read_trivially(instream, [prod(item_shape), flat_length]); + else + res = yardl.allocate(self.get_class(), [prod(item_shape), flat_length]); + for i = 1:flat_length + item = self.item_serializer_.read(instream); + res(:, i) = item(:); + end + end + + % Tricky reshaping to remove unnecessary singleton dimensions in + % subarrays, arrays of fixed vectors, etc. + item_shape = item_shape(item_shape > 1); + if isempty(item_shape) && isscalar(shape) + item_shape = 1; + end + newshape = [item_shape shape]; + res = reshape(res, newshape); + + if iscolumn(res) + res = transpose(res); + end + end + end + + methods + function c = get_class(self) + c = self.item_serializer_.get_class(); + end + + function s = get_shape(~) + s = []; + end + end +end diff --git a/matlab/+yardl/+binary/NoneSerializer.m b/matlab/+yardl/+binary/NoneSerializer.m new file mode 100644 index 0000000..9986594 --- /dev/null +++ b/matlab/+yardl/+binary/NoneSerializer.m @@ -0,0 +1,17 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef NoneSerializer < yardl.binary.TypeSerializer + methods (Static) + function write(~, ~) + end + + function res = read(~) + res = yardl.None; + end + + function c = get_class() + c = "yardl.Optional"; + end + end +end diff --git a/matlab/+yardl/+binary/OptionalSerializer.m b/matlab/+yardl/+binary/OptionalSerializer.m new file mode 100644 index 0000000..a4f7960 --- /dev/null +++ b/matlab/+yardl/+binary/OptionalSerializer.m @@ -0,0 +1,43 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef OptionalSerializer < yardl.binary.TypeSerializer + properties + item_serializer_; + end + + methods + function self = OptionalSerializer(item_serializer) + self.item_serializer_ = item_serializer; + end + + function write(self, outstream, value) + if isa(value, "yardl.Optional") + if value.has_value() + outstream.write_byte(uint8(1)); + self.item_serializer_.write(outstream, value.value()); + else + outstream.write_byte(uint8(0)); + return + end + else + outstream.write_byte(uint8(1)); + self.item_serializer_.write(outstream, value); + end + end + + function res = read(self, instream) + % Returns either yardl.None or the inner optional value + has_value = instream.read_byte(); + if has_value == 0 + res = yardl.None; + else + res = self.item_serializer_.read(instream); + end + end + + function c = get_class(~) + c = "yardl.Optional"; + end + end +end diff --git a/matlab/+yardl/+binary/RecordSerializer.m b/matlab/+yardl/+binary/RecordSerializer.m new file mode 100644 index 0000000..d6a2fb5 --- /dev/null +++ b/matlab/+yardl/+binary/RecordSerializer.m @@ -0,0 +1,39 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef RecordSerializer < yardl.binary.TypeSerializer + + properties + field_serializers + classname + end + + methods + function self = RecordSerializer(classname, field_serializers) + self.classname = classname; + self.field_serializers = field_serializers; + end + + function c = get_class(self) + c = self.classname; + end + end + + methods (Access=protected) + function write_(self, outstream, varargin) + for i = 1:nargin-2 + fs = self.field_serializers{i}; + field_value = varargin{i}; + fs.write(outstream, field_value); + end + end + + function res = read_(self, instream) + res = cell(size(self.field_serializers)); + for i = 1:length(self.field_serializers) + fs = self.field_serializers{i}; + res{i} = fs.read(instream); + end + end + end +end diff --git a/matlab/+yardl/+binary/SizeSerializer.m b/matlab/+yardl/+binary/SizeSerializer.m new file mode 100644 index 0000000..a613e23 --- /dev/null +++ b/matlab/+yardl/+binary/SizeSerializer.m @@ -0,0 +1,5 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef SizeSerializer < yardl.binary.Uint64Serializer +end diff --git a/matlab/+yardl/+binary/StreamSerializer.m b/matlab/+yardl/+binary/StreamSerializer.m new file mode 100644 index 0000000..233bf2b --- /dev/null +++ b/matlab/+yardl/+binary/StreamSerializer.m @@ -0,0 +1,79 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef StreamSerializer < yardl.binary.TypeSerializer + properties + item_serializer_; + items_remaining_; + end + + methods + function self = StreamSerializer(item_serializer) + self.item_serializer_ = item_serializer; + self.items_remaining_ = 0; + end + + function write(self, outstream, values) + if isempty(values) + return; + end + + if iscolumn(values) + values = transpose(values); + end + s = size(values); + count = s(end); + outstream.write_unsigned_varint(count); + + if iscell(values) + if ~isvector(s) + throw(yardl.ValueError("cell array must be a vector")); + end + for i = 1:count + self.item_serializer_.write(outstream, values{i}); + end + else + if ndims(values) > 2 + r = reshape(values, [], count); + inner_shape = s(1:end-1); + for i = 1:count + val = reshape(r(:, i), inner_shape); + self.item_serializer_.write(outstream, val); + end + else + for i = 1:count + self.item_serializer_.write(outstream, transpose(values(:, i))); + end + end + end + end + + function res = hasnext(self, instream) + if self.items_remaining_ <= 0 + self.items_remaining_ = instream.read_unsigned_varint(); + if self.items_remaining_ <= 0 + res = false; + return; + end + end + res = true; + end + + function res = read(self, instream) + if self.items_remaining_ <= 0 + throw(yardl.RuntimeError("Stream has been exhausted")); + end + + res = self.item_serializer_.read(instream); + self.items_remaining_ = self.items_remaining_ - 1; + end + + function c = get_class(self) + c = self.item_serializer_.get_class(); + end + + function s = get_shape(~) + s = []; + end + end +end diff --git a/matlab/+yardl/+binary/StringSerializer.m b/matlab/+yardl/+binary/StringSerializer.m new file mode 100644 index 0000000..d96ff6c --- /dev/null +++ b/matlab/+yardl/+binary/StringSerializer.m @@ -0,0 +1,26 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef StringSerializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + arguments + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) {mustBeTextScalar} + end + bytes = unicode2native(value, "utf-8"); + outstream.write_unsigned_varint(length(bytes)); + outstream.write_bytes(bytes); + end + + function res = read(instream) + len = instream.read_unsigned_varint(); + bytes = instream.read_bytes(len); + res = convertCharsToStrings(native2unicode(bytes, "utf-8")); + end + + function c = get_class() + c = "string"; + end + end +end diff --git a/matlab/+yardl/+binary/TimeSerializer.m b/matlab/+yardl/+binary/TimeSerializer.m new file mode 100644 index 0000000..e612d9f --- /dev/null +++ b/matlab/+yardl/+binary/TimeSerializer.m @@ -0,0 +1,27 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef TimeSerializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + if isa(value, "datetime") + value = yardl.Time.from_datetime(value).value; + elseif isa(value, "yardl.Time") + value = value.value; + else + throw(yardl.TypeError("Expected datetime or yardl.Time, got %s", class(value))); + end + + outstream.write_signed_varint(value); + end + + function res = read(instream) + value = instream.read_signed_varint(); + res = yardl.Time(value); + end + + function c = get_class() + c = "yardl.Time"; + end + end +end diff --git a/matlab/+yardl/+binary/TypeSerializer.m b/matlab/+yardl/+binary/TypeSerializer.m new file mode 100644 index 0000000..0cbb6f1 --- /dev/null +++ b/matlab/+yardl/+binary/TypeSerializer.m @@ -0,0 +1,36 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef TypeSerializer < handle + methods (Static, Abstract) + write(self, stream, value) + res = read(self, stream) + c = get_class(self) + end + + methods (Static) + function s = get_shape() + s = 1; + end + + function trivial = is_trivially_serializable() + trivial = false; + end + end + + methods + function write_trivially(self, stream, values) + if ~self.is_trivially_serializable() + throw(yardl.TypeError("Not implemented for non-trivially-serializable types")); + end + stream.write_values_directly(values, self.get_class()); + end + + function res = read_trivially(self, stream, shape) + if ~self.is_trivially_serializable() + throw(yardl.TypeError("Not implemented for non-trivially-serializable types")); + end + res = stream.read_values_directly(shape, self.get_class()); + end + end +end diff --git a/matlab/+yardl/+binary/Uint16Serializer.m b/matlab/+yardl/+binary/Uint16Serializer.m new file mode 100644 index 0000000..5e33f7d --- /dev/null +++ b/matlab/+yardl/+binary/Uint16Serializer.m @@ -0,0 +1,22 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Uint16Serializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + arguments + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) {mustBeInRange(value, 0, 65535)} + end + outstream.write_unsigned_varint(value); + end + + function res = read(instream) + res = uint16(instream.read_unsigned_varint()); + end + + function c = get_class() + c = "uint16"; + end + end +end diff --git a/matlab/+yardl/+binary/Uint32Serializer.m b/matlab/+yardl/+binary/Uint32Serializer.m new file mode 100644 index 0000000..5bf4c54 --- /dev/null +++ b/matlab/+yardl/+binary/Uint32Serializer.m @@ -0,0 +1,22 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Uint32Serializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + arguments + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) {mustBeInRange(value, 0, 4294967295)} + end + outstream.write_unsigned_varint(value); + end + + function res = read(instream) + res = uint32(instream.read_unsigned_varint()); + end + + function c = get_class() + c = "uint32"; + end + end +end diff --git a/matlab/+yardl/+binary/Uint64Serializer.m b/matlab/+yardl/+binary/Uint64Serializer.m new file mode 100644 index 0000000..3d51f62 --- /dev/null +++ b/matlab/+yardl/+binary/Uint64Serializer.m @@ -0,0 +1,22 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Uint64Serializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + arguments + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) {mustBeInRange(value, 0, 18446744073709551615)} + end + outstream.write_unsigned_varint(value); + end + + function res = read(instream) + res = uint64(instream.read_unsigned_varint()); + end + + function c = get_class() + c = "uint64"; + end + end +end diff --git a/matlab/+yardl/+binary/Uint8Serializer.m b/matlab/+yardl/+binary/Uint8Serializer.m new file mode 100644 index 0000000..28c873b --- /dev/null +++ b/matlab/+yardl/+binary/Uint8Serializer.m @@ -0,0 +1,26 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Uint8Serializer < yardl.binary.TypeSerializer + methods (Static) + function write(outstream, value) + arguments + outstream (1,1) yardl.binary.CodedOutputStream + value (1,1) {mustBeInRange(value, 0, 255)} + end + outstream.write_byte(uint8(value)); + end + + function res = read(instream) + res = instream.read_byte(); + end + + function c = get_class() + c = "uint8"; + end + + function trivial = is_trivially_serializable() + trivial = true; + end + end +end diff --git a/matlab/+yardl/+binary/UnionSerializer.m b/matlab/+yardl/+binary/UnionSerializer.m new file mode 100644 index 0000000..ba935c9 --- /dev/null +++ b/matlab/+yardl/+binary/UnionSerializer.m @@ -0,0 +1,81 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef UnionSerializer < handle + + properties (Access=protected) + classname_ + case_serializers_ + case_factories_ + offset_ + end + + methods + function self = UnionSerializer(union_class, case_serializers, case_factories) + self.classname_ = union_class; + self.case_serializers_ = case_serializers; + self.case_factories_ = case_factories; + + if isa(case_serializers{1}, "yardl.binary.NoneSerializer") + self.offset_ = 1; + else + self.offset_ = 0; + end + end + + function write(self, outstream, value) + if isa(value, "yardl.Optional") + if ~isa(self.case_serializers_{1}, "yardl.binary.NoneSerializer") + throw(yardl.TypeError("Optional is not valid for this union type")) + end + + if value.has_value() + value = value.value; + else + outstream.write_byte(uint8(0)); + return; + end + end + + if ~isa(value, self.classname_) + throw(yardl.TypeError("Expected union value of type %s, got %s", self.classname_, class(value))) + end + + tag_index = uint8(value.index + self.offset_); + outstream.write_byte(tag_index-1); + + serializer = self.case_serializers_{tag_index}; + serializer.write(outstream, value.value); + end + + function res = read(self, instream) + case_index = instream.read_byte() + 1; + + if case_index == 1 && self.offset_ == 1 + res = yardl.None; + return + end + + serializer = self.case_serializers_{case_index}; + value = serializer.read(instream); + + factory = self.case_factories_{case_index}; + res = factory(value); + end + + function c = get_class(self) + if isa(self.case_serializers_{1}, "yardl.binary.NoneSerializer") + c = "yardl.Optional"; + else + c = self.classname_; + end + end + + end + + methods (Static) + function s = get_shape() + s = 1; + end + end +end diff --git a/matlab/+yardl/+binary/VectorSerializer.m b/matlab/+yardl/+binary/VectorSerializer.m new file mode 100644 index 0000000..04982ef --- /dev/null +++ b/matlab/+yardl/+binary/VectorSerializer.m @@ -0,0 +1,25 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef VectorSerializer < yardl.binary.VectorSerializerBase + + methods (Access=protected) + function handle_write_count_(~, outstream, count) + outstream.write_unsigned_varint(count); + end + + function count = get_read_count_(~, instream) + count = instream.read_unsigned_varint(); + end + end + + methods + function self = VectorSerializer(item_serializer) + self@yardl.binary.VectorSerializerBase(item_serializer); + end + + function s = get_shape(~) + s = []; + end + end +end diff --git a/matlab/+yardl/+binary/VectorSerializerBase.m b/matlab/+yardl/+binary/VectorSerializerBase.m new file mode 100644 index 0000000..dbe1694 --- /dev/null +++ b/matlab/+yardl/+binary/VectorSerializerBase.m @@ -0,0 +1,95 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef VectorSerializerBase < yardl.binary.TypeSerializer + properties + item_serializer_; + end + + methods (Abstract, Access=protected) + handle_write_count_(self, outstream, values) + get_read_count_(self, instream) + end + + methods (Access=protected) + function self = VectorSerializerBase(item_serializer) + self.item_serializer_ = item_serializer; + end + end + + methods + function write(self, outstream, values) + if iscolumn(values) + values = transpose(values); + end + s = size(values); + count = s(end); + + self.handle_write_count_(outstream, count); + + if iscell(values) + % values is a cell array, so must be a vector of shape [1, COUNT] + if ~isvector(s) + throw(yardl.ValueError("cell array must be a vector")); + end + for i = 1:count + self.item_serializer_.write(outstream, values{i}); + end + else + % values is an array, so must have shape [A, B, ..., COUNT] + if self.item_serializer_.is_trivially_serializable() + self.item_serializer_.write_trivially(outstream, values); + return + end + + if ndims(values) > 2 + r = reshape(values, [], count); + for i = 1:count + val = reshape(r(:, i), s(1:end-1)); + self.item_serializer_.write(outstream, val); + end + else + for i = 1:count + self.item_serializer_.write(outstream, transpose(values(:, i))); + end + end + end + end + + function res = read(self, instream) + count = self.get_read_count_(instream); + if count == 0 + res = yardl.allocate(self.get_class(), 0); + return; + end + + item_shape = self.item_serializer_.get_shape(); + if isempty(item_shape) + res = cell(1, count); + for i = 1:count + res{i} = self.item_serializer_.read(instream); + end + return + end + + if self.item_serializer_.is_trivially_serializable() + res = self.item_serializer_.read_trivially(instream, [prod(item_shape), count]); + else + res = yardl.allocate(self.get_class(), [prod(item_shape), count]); + for i = 1:count + item = self.item_serializer_.read(instream); + res(:, i) = item(:); + end + end + + res = squeeze(reshape(res, [item_shape, count])); + if iscolumn(res) + res = transpose(res); + end + end + + function c = get_class(self) + c = self.item_serializer_.get_class(); + end + end +end diff --git a/matlab/+yardl/Date.m b/matlab/+yardl/Date.m new file mode 100644 index 0000000..cbae0f5 --- /dev/null +++ b/matlab/+yardl/Date.m @@ -0,0 +1,70 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Date < handle + + properties (SetAccess=private) + days_since_epoch + end + + methods + function self = Date(days_since_epoch) + if nargin > 0 + self.days_since_epoch = days_since_epoch; + else + self.days_since_epoch = 0; + end + end + + function value = value(self) + value = self.days_since_epoch; + end + + function dt = to_datetime(self) + dt = datetime(0, 'ConvertFrom', 'epochtime') + days(self.days_since_epoch); + end + + function eq = eq(self, other) + if isa(other, 'datetime') + other = yardl.Date.from_datetime(other); + end + + eq = isa(other, 'yardl.Date') && ... + all([self.days_since_epoch] == [other.days_since_epoch]); + end + + function ne = ne(self, other) + ne = ~self.eq(other); + end + + function isequal = isequal(self, other) + isequal = all(eq(self, other)); + end + end + + methods (Static) + function d = from_datetime(value) + dur = value - datetime(0, 'ConvertFrom', 'epochtime'); + d = yardl.Date(days(dur)); + end + + function d = from_components(y, m, d) + d = yardl.Date.from_datetime(datetime(y, m, d)); + end + + function z = zeros(varargin) + elem = yardl.Date(0); + if nargin == 0 + z = elem; + return + end + + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end + +end diff --git a/matlab/+yardl/DateTime.m b/matlab/+yardl/DateTime.m new file mode 100644 index 0000000..af710ec --- /dev/null +++ b/matlab/+yardl/DateTime.m @@ -0,0 +1,81 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef DateTime < handle + % A basic datetime with nanosecond precision, always in UTC. + + properties (SetAccess=private) + nanoseconds_since_epoch + end + + methods + function self = DateTime(nanoseconds_since_epoch) + if nargin > 0 + self.nanoseconds_since_epoch = nanoseconds_since_epoch; + else + self.nanoseconds_since_epoch = 0; + end + end + + function value = value(self) + value = self.nanoseconds_since_epoch; + end + + function dt = to_datetime(self) + dt = datetime(self.nanoseconds_since_epoch, 'ConvertFrom', 'epochtime', 'TicksPerSecond', 1e9); + end + + function eq = eq(self, other) + if isa(other, 'datetime') + other = yardl.DateTime.from_datetime(other); + end + + eq = isa(other, 'yardl.DateTime') && ... + all([self.nanoseconds_since_epoch] == [other.nanoseconds_since_epoch]); + end + + function ne = ne(self, other) + ne = ~self.eq(other); + end + + function isequal = isequal(self, other) + isequal = all(eq(self, other)); + end + end + + methods (Static) + function dt = from_datetime(value) + value.TimeZone = 'UTC'; + nanoseconds_since_epoch = convertTo(value, 'epochtime', 'TicksPerSecond', 1e9); + dt = yardl.DateTime(nanoseconds_since_epoch); + end + + function dt = from_components(year, month, day, hour, minute, second, nanosecond) + if ~(nanosecond >= 0 && nanosecond < 999999999) + throw(yardl.ValueError("nanosecond must be in 0..1e9")); + end + mdt = datetime(year, month, day, hour, minute, second, 'TimeZone', 'UTC'); + seconds_since_epoch = convertTo(mdt, 'epochtime'); + dt = yardl.DateTime(seconds_since_epoch * 1e9 + nanosecond); + end + + function dt = now(~) + dt = yardl.DateTime.from_datetime(datetime('now')); + end + + function z = zeros(varargin) + elem = yardl.DateTime(0); + if nargin == 0 + z = elem; + return + end + + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end + +end diff --git a/matlab/+yardl/Exception.m b/matlab/+yardl/Exception.m new file mode 100644 index 0000000..131fd04 --- /dev/null +++ b/matlab/+yardl/Exception.m @@ -0,0 +1,6 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +function err = Exception(id, varargin) + err = MException(id, varargin{:}); +end diff --git a/matlab/+yardl/Map.m b/matlab/+yardl/Map.m new file mode 100644 index 0000000..5b446cc --- /dev/null +++ b/matlab/+yardl/Map.m @@ -0,0 +1,73 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Map < handle + properties (SetAccess=protected) + dict + end + + methods + + function self = Map(varargin) + self.dict = dictionary(varargin{:}); + end + + function k = keys(self) + k = keys(self.dict); + end + + function v = values(self) + v = values(self.dict); + end + + function l = lookup(self, varargin) + l = lookup(self.dict, varargin{:}); + end + + function insert(self, varargin) + self.dict = insert(self.dict, varargin{:}); + end + + function remove(self, varargin) + self.dict = remove(self.dict, varargin{:}); + end + + function n = numEntries(self) + n = numEntries(self.dict); + end + + function res = eq(a, b) + if isa(b, 'yardl.Map') + res = isequal({a.dict}, {b.dict}); + elseif isa(b, 'dictionary') + res = isequal({a.dict}, {b}); + else + res = false; + end + end + + function ne = ne(a, b) + ne = ~eq(a, b); + end + + function isequal = isequal(self, other) + isequal = all(eq(self, other)); + end + end + + methods (Static) + function z = zeros(varargin) + elem = yardl.Map(); + if nargin == 0 + z = elem; + return + end + + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+yardl/None.m b/matlab/+yardl/None.m new file mode 100644 index 0000000..728123d --- /dev/null +++ b/matlab/+yardl/None.m @@ -0,0 +1,6 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +function n = None() + n = yardl.Optional(); +end diff --git a/matlab/+yardl/Optional.m b/matlab/+yardl/Optional.m new file mode 100644 index 0000000..574bd79 --- /dev/null +++ b/matlab/+yardl/Optional.m @@ -0,0 +1,83 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Optional < handle + properties (SetAccess=protected) + has_value + end + + properties (Access=protected) + value_ + end + + methods + function self = Optional(varargin) + if nargin > 0 + self.value_ = varargin{1}; + self.has_value = true; + else + self.has_value = false; + end + end + + function v = value(self) + if ~self.has_value + throw(yardl.ValueError("Optional type does not have a value")); + end + v = self.value_; + end + + function eq = eq(a, b) + if isa(a, 'yardl.Optional') + if isa(b, 'yardl.Optional') + if all([a.has_value]) && all([b.has_value]) + eq = isequal([a.value_], [b.value_]); + else + eq = [a.has_value] == [b.has_value]; + end + else + if all([a.has_value]) + eq = isequal(b, [a.value_]); + else + eq = false; + end + end + else + % b is the Optional + if all([b.has_value]) + eq = isequal(a, [b.value_]); + else + eq = false; + end + end + end + + function ne = ne(a, b) + ne = ~eq(a, b); + end + + function isequal = isequal(a, varargin) + isequal = all(eq(a, [varargin{:}])); + end + + function isequaln = isequaln(a, varargin) + isequaln = isequal(a, [varargin{:}]); + end + end + + methods (Static) + function z = zeros(varargin) + elem = yardl.None; + if nargin == 0 + z = elem; + return + end + + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end +end diff --git a/matlab/+yardl/ProtocolError.m b/matlab/+yardl/ProtocolError.m new file mode 100644 index 0000000..eac33ad --- /dev/null +++ b/matlab/+yardl/ProtocolError.m @@ -0,0 +1,6 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +function err = ProtocolError(varargin) + err = yardl.Exception("yardl:ProtocolError", varargin{:}); +end diff --git a/matlab/+yardl/RuntimeError.m b/matlab/+yardl/RuntimeError.m new file mode 100644 index 0000000..d2a2d61 --- /dev/null +++ b/matlab/+yardl/RuntimeError.m @@ -0,0 +1,6 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +function err = RuntimeError(varargin) + err = yardl.Exception("yardl:RuntimeError", varargin{:}); +end diff --git a/matlab/+yardl/Time.m b/matlab/+yardl/Time.m new file mode 100644 index 0000000..533d5de --- /dev/null +++ b/matlab/+yardl/Time.m @@ -0,0 +1,90 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Time < handle + % A basic time of day with nanosecond precision. It is not timezone-aware and is + % meant to represent a wall clock time. + + properties (SetAccess=private) + nanoseconds_since_midnight + end + + methods + function self = Time(nanoseconds_since_midnight) + if nargin > 0 + if nanoseconds_since_midnight < 0 || nanoseconds_since_midnight >= 24*60*60*1e9 + throw(yardl.ValuError("Time must be between 00:00:00 and 23:59:59.999999999")); + end + self.nanoseconds_since_midnight = nanoseconds_since_midnight; + else + self.nanoseconds_since_midnight = 0; + end + end + + function value = value(self) + value = self.nanoseconds_since_midnight; + end + + function dt = to_datetime(self) + dt = datetime(self.nanoseconds_since_midnight, 'ConvertFrom', 'epochtime', 'Epoch', datetime('today'), 'TicksPerSecond', 1e9); + end + + function eq = eq(self, other) + if isa(other, 'datetime') + other = yardl.Time.from_datetime(other); + end + + eq = isa(other, 'yardl.Time') && ... + all([self.nanoseconds_since_midnight] == [other.nanoseconds_since_midnight]); + end + + function ne = ne(self, other) + ne = ~self.eq(other); + end + + function isequal = isequal(self, other) + isequal = all(eq(self, other)); + end + end + + methods (Static) + function t = from_datetime(value) + nanoseconds_since_midnight = convertTo(value, 'epochtime', ... + 'Epoch', datetime(value.Year, value.Month, value.Day, 'TimeZone', value.TimeZone), ... + 'TicksPerSecond', 1e9); + t = yardl.Time(nanoseconds_since_midnight); + end + + function t = from_components(hour, minute, second, nanosecond) + if ~(hour >= 0 && hour <= 23) + throw(yardl.ValueError("hour must be between 0 and 23")); + end + if ~(minute >= 0 && minute <= 59) + throw(yardl.ValueError("minute must be between 0 and 59")); + end + if ~(second >= 0 && second <= 59) + throw(yardl.ValueError("second must be between 0 and 59")); + end + if ~(nanosecond >= 0 && nanosecond <= 999999999) + throw(yardl.ValueError("nanosecond must be between 0 and 999999999")); + end + + t = yardl.Time(hour * 60*60*1e9 + minute * 60*1e9 + second * 1e9 + nanosecond); + end + + function z = zeros(varargin) + elem = yardl.Time(0); + if nargin == 0 + z = elem; + return + end + + sz = [varargin{:}]; + if isscalar(sz) + sz = [sz, sz]; + end + z = reshape(repelem(elem, prod(sz)), sz); + end + end + +end diff --git a/matlab/+yardl/TypeError.m b/matlab/+yardl/TypeError.m new file mode 100644 index 0000000..d37b4d6 --- /dev/null +++ b/matlab/+yardl/TypeError.m @@ -0,0 +1,6 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +function err = TypeError(varargin) + err = yardl.Exception("yardl:TypeError", varargin{:}); +end diff --git a/matlab/+yardl/Union.m b/matlab/+yardl/Union.m new file mode 100644 index 0000000..7079c97 --- /dev/null +++ b/matlab/+yardl/Union.m @@ -0,0 +1,41 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +classdef Union < handle & matlab.mixin.CustomDisplay + properties (Access=protected) + index_ + end + + properties (SetAccess=protected) + value + end + + methods + function self = Union(index, value) + self.index_ = index; + self.value = value; + end + + function i = index(self) + i = self.index_; + end + + function isequal = isequal(self, other) + isequal = all(eq(self, other)); + end + end + + methods (Abstract) + t = tag(self) + end + + methods (Access=protected) + function displayScalarObject(obj) + className = matlab.mixin.CustomDisplay.getClassNameForHeader(obj); + header = sprintf('%s.%s\n', className, obj.tag()); + disp(header) + propgroup = getPropertyGroups(obj); + matlab.mixin.CustomDisplay.displayPropertyGroups(obj,propgroup) + end + end +end diff --git a/matlab/+yardl/ValueError.m b/matlab/+yardl/ValueError.m new file mode 100644 index 0000000..3c0bd3f --- /dev/null +++ b/matlab/+yardl/ValueError.m @@ -0,0 +1,6 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +function err = ValueError(varargin) + err = yardl.Exception("yardl:ValueError", varargin{:}); +end diff --git a/matlab/+yardl/allocate.m b/matlab/+yardl/allocate.m new file mode 100644 index 0000000..f99f87f --- /dev/null +++ b/matlab/+yardl/allocate.m @@ -0,0 +1,11 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +function res = allocate(classname, varargin) + % Wrapper around zeros, used to preallocate arrays of yardl objects + if classname == "string" + res = strings(varargin{:}); + else + res = zeros(varargin{:}, classname); + end +end diff --git a/matlab/+yardl/dimension_count.m b/matlab/+yardl/dimension_count.m new file mode 100644 index 0000000..2156767 --- /dev/null +++ b/matlab/+yardl/dimension_count.m @@ -0,0 +1,9 @@ +% Copyright (c) Microsoft Corporation. +% Licensed under the MIT License. + +function c = dimension_count(arr) + % Alternative to Matlab's `ndims` function + % Collapses dimensions of size 1 (making it behave like numpy.array.ndim) + s = size(arr); + c = length(s(s > 1)); +end diff --git a/matlab/petsird_analysis.m b/matlab/petsird_analysis.m new file mode 100644 index 0000000..0e9975a --- /dev/null +++ b/matlab/petsird_analysis.m @@ -0,0 +1,80 @@ +function petsird_generator(input) + +arguments + input (1,1) string +end + +reader = petsird.binary.PETSIRDReader(input); + +header = reader.read_header(); + +if header.exam ~= yardl.None + fprintf("Subject ID: %s\n", header.exam.subject.id); +end + +fprintf("Scanner name: %s\n", header.scanner.model_name); + +fprintf("Types of modules: %d\n", length(header.scanner.scanner_geometry.replicated_modules)); +fprintf("Number of modules of first type: %d\n", ... + length(header.scanner.scanner_geometry.replicated_modules(1).transforms)); +fprintf("Number of types of detecting elements in modules of first type: %d\n", ... + length(header.scanner.scanner_geometry.replicated_modules(1).object.detecting_elements)); +fprintf("Number of elements of first type in modules of first type: %d\n", ... + length(header.scanner.scanner_geometry.replicated_modules(1).object.detecting_elements(1).transforms)); +fprintf("Total number of 'crystals': %d\n", ... + petsird.helpers.get_num_detecting_elements(header.scanner.scanner_geometry)); +fprintf("Number of TOF bins: %d\n", header.scanner.number_of_tof_bins()); +fprintf("Number of energy bins: %d\n", header.scanner.number_of_energy_bins()); + +energy_bin_edges = header.scanner.energy_bin_edges; +fprintf("Energy bin edges: " + join(repelem("%f", length(energy_bin_edges))) + "\n", energy_bin_edges); + +energy_mid_points = (energy_bin_edges(1:end-1) + energy_bin_edges(2:end)) / 2; +fprintf("Energy mid points: " + join(repelem("%f", length(energy_mid_points))) + "\n", energy_mid_points); + +% sgidlut = header.scanner.detection_efficiencies.module_pair_sgidlut; +% fprintf("SGID LUT:\n"); +% disp(sgidlut); + +energy_1 = 0.0; +energy_2 = 0.0; +num_prompts = 0; +num_delayeds = 0; +last_time = 0; +while reader.has_time_blocks() + time_block = reader.read_time_blocks(); + + if time_block.isEventTimeBlock() + last_time = time_block.value.start; + num_prompts = num_prompts + length(time_block.value.prompt_events); + if time_block.value.delayed_events ~= yardl.None + num_delayeds = num_delayeds + length(time_block.value.delayed_events.value); + end + fprintf("===================== Events in time block from %f ==============\n", last_time); + for event_idx = 1:length(time_block.value.prompt_events) + event = time_block.value.prompt_events(event_idx); + energy_1 = energy_1 + energy_mid_points(event.energy_indices(1) + 1); + energy_2 = energy_2 + energy_mid_points(event.energy_indices(2) + 1); + + fprintf("CoincidenceEvent(detectorIds=[%d, %d], tofIdx=%d, energyIndices=[%d, %d])\n", ... + event.detector_ids(1), event.detector_ids(2), event.tof_idx, ... + event.energy_indices(1), event.energy_indices(2)); + mod_and_el = petsird.helpers.get_module_and_element(header.scanner.scanner_geometry, event.detector_ids); + fprintf(" [ModuleAndElement(module=%d, el=%d), ModuleAndElement(module=%d, el=%d)]\n", ... + mod_and_el(1).module, mod_and_el(1).el, mod_and_el(2).module, mod_and_el(2).el); + fprintf(" efficiency: %f\n", petsird.helpers.get_detection_efficiency(header.scanner, event)); + end + end +end + +fprintf("Last time block at %f ms\n", last_time); +fprintf("Number of prompt events: %d\n", num_prompts); +fprintf("Number of delayed events: %d\n", num_delayeds); +if num_prompts > 0 + fprintf("Average energy_1: %f\n", energy_1 / num_prompts) + fprintf("Average energy_2: %f\n", energy_2 / num_prompts) +end + +reader.close(); + +end diff --git a/matlab/petsird_generator.m b/matlab/petsird_generator.m new file mode 100644 index 0000000..ab92524 --- /dev/null +++ b/matlab/petsird_generator.m @@ -0,0 +1,232 @@ +function petsird_generator(output) + +arguments + output (1,1) string +end + +% These are constants for now +config.NUMBER_OF_ENERGY_BINS = 3; +config.NUMBER_OF_TOF_BINS = 300; +config.RADIUS = 400; +config.CRYSTAL_LENGTH = [20, 4, 4]; +config.NUM_CRYSTALS_PER_MODULE = [2, 4, 7]; +config.NUM_MODULES_ALONG_RING = 20; +config.NUM_MODULES_ALONG_AXIS = 2; +config.MODULE_AXIS_SPACING = (config.NUM_CRYSTALS_PER_MODULE(3) + 4) * config.CRYSTAL_LENGTH(3); +config.NUMBER_OF_TIME_BLOCKS = 6; +config.COUNT_RATE = 500; + +writer = petsird.binary.PETSIRDWriter(output); + +header = get_header(config); +writer.write_header(header); + +for t = 0:config.NUMBER_OF_TIME_BLOCKS-1 + start = t * header.scanner.event_time_block_duration; + % TODO: Need Statistics and Machine Learning Toolbox for Poisson distribution functions + % num_prompts_this_block = poissrnd(COUNT_RATE); + num_prompts_this_block = randi(config.COUNT_RATE); + prompts_this_block = get_events(header, num_prompts_this_block, config); + + tb = petsird.TimeBlock.EventTimeBlock(... + petsird.EventTimeBlock(start=start, prompt_events=prompts_this_block) ... + ); + writer.write_time_blocks(tb) +end + +writer.end_time_blocks(); +writer.close(); + +end + +function h = get_header(cfg) + subject = petsird.Subject(id="123456"); + institution = petsird.Institution(name="University of Somewhere", address="Didcot, Oxfordshire, Ox11 0DE, UK"); + h = petsird.Header(); + h.exam = petsird.ExamInformation(subject=subject, institution=institution); + h.scanner = get_scanner_info(cfg); +end + +function scanner = get_scanner_info(cfg) + scanner_geometry = get_scanner_geometry(cfg); + + % TODO scanner_info.bulk_materials + + % TOF info (in mm) + tofBinEdges = single(linspace(-cfg.RADIUS, cfg.RADIUS, cfg.NUMBER_OF_TOF_BINS + 1)); + energyBinEdges = single(linspace(430, 650, cfg.NUMBER_OF_ENERGY_BINS + 1)); + + % We need energy bin info before being able to construct the detection + % efficiencies, so we first construct a scanner without the efficiencies + scanner = petsird.ScannerInformation(... + model_name="PETSIRD_TEST", ... + scanner_geometry=scanner_geometry, ... + tof_bin_edges=tofBinEdges, ... + tof_resolution=9.4, ... % in mm + energy_bin_edges=energyBinEdges, ... + energy_resolution_at_511=0.11, ... % as fraction of 511 + event_time_block_duration=1 ... % ms + ); + + % Now added the efficiencies + scanner.detection_efficiencies = get_detection_efficiencies(scanner, cfg); +end + +function geometry = get_scanner_geometry(cfg) + detector_module = get_detector_module(cfg); + + rep_module = petsird.ReplicatedDetectorModule(object=detector_module); + module_id = 0; + for i = 0:cfg.NUM_MODULES_ALONG_RING-1 + angle = 2 * pi * i / cfg.NUM_MODULES_ALONG_RING; + for ax_mod = 0:cfg.NUM_MODULES_ALONG_AXIS-1 + transform = petsird.RigidTransformation(matrix=... + transpose([... + cos(angle), -sin(angle), 0, 0; ... + sin(angle), cos(angle), 0, 0; ... + 0, 0, 1, cfg.MODULE_AXIS_SPACING * ax_mod; ... + ]) ... + ); + rep_module.transforms = [rep_module.transforms transform]; + rep_module.ids = [rep_module.ids module_id]; + module_id = module_id + 1; + end + end + + geometry = petsird.ScannerGeometry(replicated_modules=[rep_module], ids=[0]); +end + +function detector = get_detector_module(cfg) + % Return a module of NUM_CRYSTALS_PER_MODULE cuboids + crystal = get_crystal(cfg); + rep_volume = petsird.ReplicatedBoxSolidVolume(object=crystal); + N0 = cfg.NUM_CRYSTALS_PER_MODULE(1); + N1 = cfg.NUM_CRYSTALS_PER_MODULE(2); + N2 = cfg.NUM_CRYSTALS_PER_MODULE(3); + id = 0; + for rep0 = 0:N0-1 + for rep1 = 0:N1-1 + for rep2 = 0:N2-1 + transform = petsird.RigidTransformation(matrix=... + transpose([... + 1, 0, 0, cfg.RADIUS + rep0 * cfg.CRYSTAL_LENGTH(1); ... + 0, 1, 0, (rep1 - N1 / 2) * cfg.CRYSTAL_LENGTH(2); ... + 0, 0, 1, (rep2 - N2 / 2) * cfg.CRYSTAL_LENGTH(3); ... + ])); + rep_volume.transforms = [rep_volume.transforms transform]; + rep_volume.ids = [rep_volume.ids id]; + id = id + 1; + end + end + end + detector = petsird.DetectorModule(detecting_elements=[rep_volume], detecting_element_ids=[0]); +end + +function crystal = get_crystal(cfg) + % Return a cuboid shape + crystal_shape = petsird.BoxShape(... + corners = [... + petsird.Coordinate(c=[0, 0, 0]), ... + petsird.Coordinate(c=[0, 0, cfg.CRYSTAL_LENGTH(3)]), ... + petsird.Coordinate(c=[0, cfg.CRYSTAL_LENGTH(2), cfg.CRYSTAL_LENGTH(3)]), ... + petsird.Coordinate(c=[0, cfg.CRYSTAL_LENGTH(2), 0]), ... + petsird.Coordinate(c=[cfg.CRYSTAL_LENGTH(1), 0, 0]), ... + petsird.Coordinate(c=[cfg.CRYSTAL_LENGTH(1), 0, cfg.CRYSTAL_LENGTH(3)]), ... + petsird.Coordinate(c=[cfg.CRYSTAL_LENGTH(1), cfg.CRYSTAL_LENGTH(2), cfg.CRYSTAL_LENGTH(3)]) ... + petsird.Coordinate(c=[cfg.CRYSTAL_LENGTH(1), cfg.CRYSTAL_LENGTH(2), 0]), ... + ]); + crystal = petsird.BoxSolidVolume(shape=crystal_shape, material_id=1); +end + +function efficiencies = get_detection_efficiencies(scanner, cfg) + % Return some (non-physical) detection efficiencies + num_det_els = petsird.helpers.get_num_detecting_elements(scanner.scanner_geometry); + + % det_el_efficiencies = ones(num_det_els, scanner.number_of_energy_bins(), "single"); + det_el_efficiencies = ones(scanner.number_of_energy_bins(), num_det_els, "single"); + + % Only 1 type of module in the current scanner + assert(length(scanner.scanner_geometry.replicated_modules) == 1); + rep_module = scanner.scanner_geometry.replicated_modules(1); + num_modules = int32(length(rep_module.transforms)); + + % We will use rotational symmetries translation along the axis + % We assume all module-pairs are in coincidence, except those + % with the same angle. + % Writing a module number as (z-position, angle): + % eff((z1,a1), (z2, a2)) == eff((z1,0), (z2, abs(a2-a1))) + % or in linear indices + % eff(z1 + NZ * a1, z2 + NZ * a2) == eff(z1, z2 + NZ * abs(a2 - a1)) + % (coincident) SGIDs need to start from 0, so ignoring self-coincident + % angles we get + % SGID = z1 + NZ * (z2 + NZ * abs(a2 - a1) - 1) + num_SGIDs = cfg.NUM_MODULES_ALONG_AXIS * cfg.NUM_MODULES_ALONG_AXIS * (cfg.NUM_MODULES_ALONG_RING - 1); + NZ = cfg.NUM_MODULES_ALONG_AXIS; + module_pair_SGID_LUT = zeros(num_modules, "int32"); + for mod1 = 0:num_modules-1 + for mod2 = 0:num_modules-1 + z1 = mod(mod1, NZ); + a1 = idivide(mod1, NZ); + z2 = mod(mod2, NZ); + a2 = idivide(mod2, NZ); + if a1 == a2 + module_pair_SGID_LUT(mod2+1, mod1+1) = -1; + else + module_pair_SGID_LUT(mod2+1, mod1+1) = z1 + NZ * (z2 + NZ * (abs(a2 - a1) - 1)); + end + end + end + + % fprint("SGID LUT:\n", module_pair_SGID_LUT, file=sys.stderr) + assert(max(module_pair_SGID_LUT(:)) == num_SGIDs - 1); + module_pair_efficiencies_vector = []; + assert(length(rep_module.object.detecting_elements) == 1); + detecting_elements = rep_module.object.detecting_elements(1); + num_det_els_in_module = length(detecting_elements.transforms); + for SGID = 0:num_SGIDs-1 + % Extract first module_pair for this SGID. However, as this + % currently unused, it is commented out + % module_pair = numpy.argwhere(module_pair_SGID_LUT == SGID)[0] + % print(module_pair, file=sys.stderr) + module_pair_efficiencies = ones(... + scanner.number_of_energy_bins(), ... + num_det_els_in_module, ... + scanner.number_of_energy_bins(), ... + num_det_els_in_module ... + ); + % give some (non-physical) value + module_pair_efficiencies = module_pair_efficiencies * SGID; + module_pair_efficiencies_vector = [module_pair_efficiencies_vector ... + petsird.ModulePairEfficiencies(values=module_pair_efficiencies, sgid=SGID)]; + assert(length(module_pair_efficiencies_vector) == SGID + 1); + end + + efficiencies = petsird.DetectionEfficiencies(... + det_el_efficiencies=det_el_efficiencies, ... + module_pair_sgidlut=module_pair_SGID_LUT, ... + module_pair_efficiencies_vector=module_pair_efficiencies_vector ... + ); +end + + +function events = get_events(header, num_events, cfg) + % Generate some random events + detector_count = petsird.helpers.get_num_detecting_elements(header.scanner.scanner_geometry); + events = []; + for i = 1:num_events + while true + detector_ids = int32([randi([0, detector_count-1]), randi([0, detector_count-1])]); + mod_and_els = petsird.helpers.get_module_and_element(header.scanner.scanner_geometry, detector_ids); + if header.scanner.detection_efficiencies.module_pair_sgidlut(mod_and_els(1).module+1, mod_and_els(2).module+1) >= 0 + % in coincidence, we can get out of the loop + break + end + end + + events = [events, petsird.CoincidenceEvent(... + detector_ids = detector_ids, ... + energy_indices = [randi([0, cfg.NUMBER_OF_ENERGY_BINS-1]), randi([0, cfg.NUMBER_OF_ENERGY_BINS-1])], ... + tof_idx=randi([0, cfg.NUMBER_OF_TOF_BINS-1])... + )]; + end +end diff --git a/model/_package.yml b/model/_package.yml index abfc64c..1f8c18e 100644 --- a/model/_package.yml +++ b/model/_package.yml @@ -5,3 +5,6 @@ cpp: python: outputDir: ../python + +matlab: + outputDir: ../matlab From 939345ac6fcd69528d7accda89458cc86d64c3fd Mon Sep 17 00:00:00 2001 From: Joe Naegele Date: Fri, 13 Dec 2024 16:56:58 +0000 Subject: [PATCH 2/2] Add MATLAB toolbox generation script --- .devcontainer/Dockerfile | 2 +- .github/workflows/ci.yml | 2 +- .pre-commit-config.yaml | 1 + .../+petsird/+binary/AnnulusShapeSerializer.m | 27 ---- matlab/+petsird/+binary/AtomSerializer.m | 25 ---- .../+binary/BedMovementTimeBlockSerializer.m | 25 ---- matlab/+petsird/+binary/BoxShapeSerializer.m | 24 ---- .../+petsird/+binary/BulkMaterialSerializer.m | 28 ----- .../+binary/CoincidenceEventSerializer.m | 26 ---- .../+petsird/+binary/CoordinateSerializer.m | 24 ---- .../+binary/DeadTimeTimeBlockSerializer.m | 26 ---- .../+binary/DetectionEfficienciesSerializer.m | 26 ---- .../+binary/DetectorModuleSerializer.m | 26 ---- .../+binary/DirectionMatrixSerializer.m | 24 ---- matlab/+petsird/+binary/DirectionSerializer.m | 24 ---- .../+binary/EventTimeBlockSerializer.m | 27 ---- .../+binary/ExamInformationSerializer.m | 27 ---- .../ExternalSignalTimeBlockSerializer.m | 26 ---- .../+binary/ExternalSignalTypeSerializer.m | 26 ---- .../GantryMovementTimeBlockSerializer.m | 25 ---- matlab/+petsird/+binary/HeaderSerializer.m | 25 ---- .../+petsird/+binary/InstitutionSerializer.m | 25 ---- .../ModulePairEfficienciesSerializer.m | 25 ---- matlab/+petsird/+binary/PETSIRDReader.m | 33 ----- matlab/+petsird/+binary/PETSIRDWriter.m | 29 ----- .../+binary/ReplicatedObjectSerializer.m | 26 ---- .../+binary/RigidTransformationSerializer.m | 24 ---- .../+binary/ScannerGeometrySerializer.m | 26 ---- .../+binary/ScannerInformationSerializer.m | 34 ----- .../+petsird/+binary/SolidVolumeSerializer.m | 25 ---- matlab/+petsird/+binary/SubjectSerializer.m | 25 ---- .../+binary/TimeFrameInformationSerializer.m | 24 ---- .../+petsird/+binary/TimeIntervalSerializer.m | 25 ---- .../+petsird/+binary/TripleEventSerializer.m | 26 ---- matlab/+petsird/AnnulusShape.m | 63 ---------- matlab/+petsird/Atom.m | 52 -------- matlab/+petsird/BedMovementTimeBlock.m | 50 -------- matlab/+petsird/BoxShape.m | 51 -------- matlab/+petsird/BoxSolidVolume.m | 4 - matlab/+petsird/BulkMaterial.m | 75 ----------- matlab/+petsird/CoincidenceEvent.m | 58 --------- matlab/+petsird/CoincidencePolicy.m | 35 ------ matlab/+petsird/Coordinate.m | 46 ------- matlab/+petsird/DeadTimeTimeBlock.m | 76 ------------ matlab/+petsird/DetectionEfficiencies.m | 82 ------------ matlab/+petsird/DetectorModule.m | 59 --------- matlab/+petsird/Direction.m | 46 ------- matlab/+petsird/DirectionMatrix.m | 47 ------- matlab/+petsird/EventTimeBlock.m | 64 ---------- matlab/+petsird/ExamInformation.m | 58 --------- matlab/+petsird/ExternalSignalTimeBlock.m | 56 --------- matlab/+petsird/ExternalSignalType.m | 53 -------- matlab/+petsird/ExternalSignalTypeEnum.m | 44 ------- matlab/+petsird/GantryMovementTimeBlock.m | 50 -------- matlab/+petsird/GenericSolidVolume.m | 4 - matlab/+petsird/GeometricShape.m | 49 -------- matlab/+petsird/Header.m | 49 -------- matlab/+petsird/Institution.m | 49 -------- matlab/+petsird/ModulePairEfficiencies.m | 56 --------- matlab/+petsird/PETSIRDReaderBase.m | 93 -------------- matlab/+petsird/PETSIRDWriterBase.m | 83 ------------- matlab/+petsird/ReplicatedBoxSolidVolume.m | 5 - matlab/+petsird/ReplicatedDetectorModule.m | 5 - .../+petsird/ReplicatedGenericSolidVolume.m | 5 - matlab/+petsird/ReplicatedObject.m | 67 ---------- matlab/+petsird/RigidTransformation.m | 48 ------- matlab/+petsird/ScannerGeometry.m | 59 --------- matlab/+petsird/ScannerInformation.m | 117 ------------------ matlab/+petsird/SolidVolume.m | 54 -------- matlab/+petsird/Subject.m | 49 -------- matlab/+petsird/TimeBlock.m | 65 ---------- matlab/+petsird/TimeFrameInformation.m | 52 -------- matlab/+petsird/TimeInterval.m | 50 -------- matlab/+petsird/TripleEvent.m | 59 --------- matlab/+yardl/+binary/BinaryProtocolReader.m | 40 ------ matlab/+yardl/+binary/BinaryProtocolWriter.m | 37 ------ matlab/+yardl/+binary/BoolSerializer.m | 28 ----- .../+binary/CURRENT_BINARY_FORMAT_VERSION.m | 6 - matlab/+yardl/+binary/CodedInputStream.m | 74 ----------- matlab/+yardl/+binary/CodedOutputStream.m | 84 ------------- .../+yardl/+binary/Complexfloat32Serializer.m | 49 -------- .../+yardl/+binary/Complexfloat64Serializer.m | 49 -------- matlab/+yardl/+binary/DateSerializer.m | 26 ---- matlab/+yardl/+binary/DatetimeSerializer.m | 26 ---- .../+yardl/+binary/DynamicNDArraySerializer.m | 47 ------- matlab/+yardl/+binary/EnumSerializer.m | 43 ------- .../+yardl/+binary/FixedNDArraySerializer.m | 72 ----------- matlab/+yardl/+binary/FixedVectorSerializer.m | 51 -------- matlab/+yardl/+binary/Float32Serializer.m | 29 ----- matlab/+yardl/+binary/Float64Serializer.m | 28 ----- matlab/+yardl/+binary/Int16Serializer.m | 22 ---- matlab/+yardl/+binary/Int32Serializer.m | 22 ---- matlab/+yardl/+binary/Int64Serializer.m | 22 ---- matlab/+yardl/+binary/Int8Serializer.m | 27 ---- matlab/+yardl/+binary/MAGIC_BYTES.m | 6 - matlab/+yardl/+binary/MapSerializer.m | 51 -------- matlab/+yardl/+binary/NDArraySerializer.m | 51 -------- matlab/+yardl/+binary/NDArraySerializerBase.m | 106 ---------------- matlab/+yardl/+binary/NoneSerializer.m | 17 --- matlab/+yardl/+binary/OptionalSerializer.m | 43 ------- matlab/+yardl/+binary/RecordSerializer.m | 39 ------ matlab/+yardl/+binary/SizeSerializer.m | 5 - matlab/+yardl/+binary/StreamSerializer.m | 79 ------------ matlab/+yardl/+binary/StringSerializer.m | 26 ---- matlab/+yardl/+binary/TimeSerializer.m | 27 ---- matlab/+yardl/+binary/TypeSerializer.m | 36 ------ matlab/+yardl/+binary/Uint16Serializer.m | 22 ---- matlab/+yardl/+binary/Uint32Serializer.m | 22 ---- matlab/+yardl/+binary/Uint64Serializer.m | 22 ---- matlab/+yardl/+binary/Uint8Serializer.m | 26 ---- matlab/+yardl/+binary/UnionSerializer.m | 81 ------------ matlab/+yardl/+binary/VectorSerializer.m | 25 ---- matlab/+yardl/+binary/VectorSerializerBase.m | 95 -------------- matlab/+yardl/Date.m | 70 ----------- matlab/+yardl/DateTime.m | 81 ------------ matlab/+yardl/Exception.m | 6 - matlab/+yardl/Map.m | 73 ----------- matlab/+yardl/None.m | 6 - matlab/+yardl/Optional.m | 83 ------------- matlab/+yardl/ProtocolError.m | 6 - matlab/+yardl/RuntimeError.m | 6 - matlab/+yardl/Time.m | 90 -------------- matlab/+yardl/TypeError.m | 6 - matlab/+yardl/Union.m | 41 ------ matlab/+yardl/ValueError.m | 6 - matlab/+yardl/allocate.m | 11 -- matlab/+yardl/dimension_count.m | 9 -- matlab/.gitignore | 1 + matlab/build-toolbox.sh | 3 + matlab/buildfile.m | 41 ++++++ .../+helpers/get_detection_efficiency.m | 0 .../+helpers/get_module_and_element.m | 0 .../+helpers/get_num_detecting_elements.m | 0 matlab/{ => toolbox}/petsird_analysis.m | 0 matlab/{ => toolbox}/petsird_generator.m | 4 +- model/_package.yml | 2 +- 136 files changed, 50 insertions(+), 4956 deletions(-) delete mode 100644 matlab/+petsird/+binary/AnnulusShapeSerializer.m delete mode 100644 matlab/+petsird/+binary/AtomSerializer.m delete mode 100644 matlab/+petsird/+binary/BedMovementTimeBlockSerializer.m delete mode 100644 matlab/+petsird/+binary/BoxShapeSerializer.m delete mode 100644 matlab/+petsird/+binary/BulkMaterialSerializer.m delete mode 100644 matlab/+petsird/+binary/CoincidenceEventSerializer.m delete mode 100644 matlab/+petsird/+binary/CoordinateSerializer.m delete mode 100644 matlab/+petsird/+binary/DeadTimeTimeBlockSerializer.m delete mode 100644 matlab/+petsird/+binary/DetectionEfficienciesSerializer.m delete mode 100644 matlab/+petsird/+binary/DetectorModuleSerializer.m delete mode 100644 matlab/+petsird/+binary/DirectionMatrixSerializer.m delete mode 100644 matlab/+petsird/+binary/DirectionSerializer.m delete mode 100644 matlab/+petsird/+binary/EventTimeBlockSerializer.m delete mode 100644 matlab/+petsird/+binary/ExamInformationSerializer.m delete mode 100644 matlab/+petsird/+binary/ExternalSignalTimeBlockSerializer.m delete mode 100644 matlab/+petsird/+binary/ExternalSignalTypeSerializer.m delete mode 100644 matlab/+petsird/+binary/GantryMovementTimeBlockSerializer.m delete mode 100644 matlab/+petsird/+binary/HeaderSerializer.m delete mode 100644 matlab/+petsird/+binary/InstitutionSerializer.m delete mode 100644 matlab/+petsird/+binary/ModulePairEfficienciesSerializer.m delete mode 100644 matlab/+petsird/+binary/PETSIRDReader.m delete mode 100644 matlab/+petsird/+binary/PETSIRDWriter.m delete mode 100644 matlab/+petsird/+binary/ReplicatedObjectSerializer.m delete mode 100644 matlab/+petsird/+binary/RigidTransformationSerializer.m delete mode 100644 matlab/+petsird/+binary/ScannerGeometrySerializer.m delete mode 100644 matlab/+petsird/+binary/ScannerInformationSerializer.m delete mode 100644 matlab/+petsird/+binary/SolidVolumeSerializer.m delete mode 100644 matlab/+petsird/+binary/SubjectSerializer.m delete mode 100644 matlab/+petsird/+binary/TimeFrameInformationSerializer.m delete mode 100644 matlab/+petsird/+binary/TimeIntervalSerializer.m delete mode 100644 matlab/+petsird/+binary/TripleEventSerializer.m delete mode 100644 matlab/+petsird/AnnulusShape.m delete mode 100644 matlab/+petsird/Atom.m delete mode 100644 matlab/+petsird/BedMovementTimeBlock.m delete mode 100644 matlab/+petsird/BoxShape.m delete mode 100644 matlab/+petsird/BoxSolidVolume.m delete mode 100644 matlab/+petsird/BulkMaterial.m delete mode 100644 matlab/+petsird/CoincidenceEvent.m delete mode 100644 matlab/+petsird/CoincidencePolicy.m delete mode 100644 matlab/+petsird/Coordinate.m delete mode 100644 matlab/+petsird/DeadTimeTimeBlock.m delete mode 100644 matlab/+petsird/DetectionEfficiencies.m delete mode 100644 matlab/+petsird/DetectorModule.m delete mode 100644 matlab/+petsird/Direction.m delete mode 100644 matlab/+petsird/DirectionMatrix.m delete mode 100644 matlab/+petsird/EventTimeBlock.m delete mode 100644 matlab/+petsird/ExamInformation.m delete mode 100644 matlab/+petsird/ExternalSignalTimeBlock.m delete mode 100644 matlab/+petsird/ExternalSignalType.m delete mode 100644 matlab/+petsird/ExternalSignalTypeEnum.m delete mode 100644 matlab/+petsird/GantryMovementTimeBlock.m delete mode 100644 matlab/+petsird/GenericSolidVolume.m delete mode 100644 matlab/+petsird/GeometricShape.m delete mode 100644 matlab/+petsird/Header.m delete mode 100644 matlab/+petsird/Institution.m delete mode 100644 matlab/+petsird/ModulePairEfficiencies.m delete mode 100644 matlab/+petsird/PETSIRDReaderBase.m delete mode 100644 matlab/+petsird/PETSIRDWriterBase.m delete mode 100644 matlab/+petsird/ReplicatedBoxSolidVolume.m delete mode 100644 matlab/+petsird/ReplicatedDetectorModule.m delete mode 100644 matlab/+petsird/ReplicatedGenericSolidVolume.m delete mode 100644 matlab/+petsird/ReplicatedObject.m delete mode 100644 matlab/+petsird/RigidTransformation.m delete mode 100644 matlab/+petsird/ScannerGeometry.m delete mode 100644 matlab/+petsird/ScannerInformation.m delete mode 100644 matlab/+petsird/SolidVolume.m delete mode 100644 matlab/+petsird/Subject.m delete mode 100644 matlab/+petsird/TimeBlock.m delete mode 100644 matlab/+petsird/TimeFrameInformation.m delete mode 100644 matlab/+petsird/TimeInterval.m delete mode 100644 matlab/+petsird/TripleEvent.m delete mode 100644 matlab/+yardl/+binary/BinaryProtocolReader.m delete mode 100644 matlab/+yardl/+binary/BinaryProtocolWriter.m delete mode 100644 matlab/+yardl/+binary/BoolSerializer.m delete mode 100644 matlab/+yardl/+binary/CURRENT_BINARY_FORMAT_VERSION.m delete mode 100644 matlab/+yardl/+binary/CodedInputStream.m delete mode 100644 matlab/+yardl/+binary/CodedOutputStream.m delete mode 100644 matlab/+yardl/+binary/Complexfloat32Serializer.m delete mode 100644 matlab/+yardl/+binary/Complexfloat64Serializer.m delete mode 100644 matlab/+yardl/+binary/DateSerializer.m delete mode 100644 matlab/+yardl/+binary/DatetimeSerializer.m delete mode 100644 matlab/+yardl/+binary/DynamicNDArraySerializer.m delete mode 100644 matlab/+yardl/+binary/EnumSerializer.m delete mode 100644 matlab/+yardl/+binary/FixedNDArraySerializer.m delete mode 100644 matlab/+yardl/+binary/FixedVectorSerializer.m delete mode 100644 matlab/+yardl/+binary/Float32Serializer.m delete mode 100644 matlab/+yardl/+binary/Float64Serializer.m delete mode 100644 matlab/+yardl/+binary/Int16Serializer.m delete mode 100644 matlab/+yardl/+binary/Int32Serializer.m delete mode 100644 matlab/+yardl/+binary/Int64Serializer.m delete mode 100644 matlab/+yardl/+binary/Int8Serializer.m delete mode 100644 matlab/+yardl/+binary/MAGIC_BYTES.m delete mode 100644 matlab/+yardl/+binary/MapSerializer.m delete mode 100644 matlab/+yardl/+binary/NDArraySerializer.m delete mode 100644 matlab/+yardl/+binary/NDArraySerializerBase.m delete mode 100644 matlab/+yardl/+binary/NoneSerializer.m delete mode 100644 matlab/+yardl/+binary/OptionalSerializer.m delete mode 100644 matlab/+yardl/+binary/RecordSerializer.m delete mode 100644 matlab/+yardl/+binary/SizeSerializer.m delete mode 100644 matlab/+yardl/+binary/StreamSerializer.m delete mode 100644 matlab/+yardl/+binary/StringSerializer.m delete mode 100644 matlab/+yardl/+binary/TimeSerializer.m delete mode 100644 matlab/+yardl/+binary/TypeSerializer.m delete mode 100644 matlab/+yardl/+binary/Uint16Serializer.m delete mode 100644 matlab/+yardl/+binary/Uint32Serializer.m delete mode 100644 matlab/+yardl/+binary/Uint64Serializer.m delete mode 100644 matlab/+yardl/+binary/Uint8Serializer.m delete mode 100644 matlab/+yardl/+binary/UnionSerializer.m delete mode 100644 matlab/+yardl/+binary/VectorSerializer.m delete mode 100644 matlab/+yardl/+binary/VectorSerializerBase.m delete mode 100644 matlab/+yardl/Date.m delete mode 100644 matlab/+yardl/DateTime.m delete mode 100644 matlab/+yardl/Exception.m delete mode 100644 matlab/+yardl/Map.m delete mode 100644 matlab/+yardl/None.m delete mode 100644 matlab/+yardl/Optional.m delete mode 100644 matlab/+yardl/ProtocolError.m delete mode 100644 matlab/+yardl/RuntimeError.m delete mode 100644 matlab/+yardl/Time.m delete mode 100644 matlab/+yardl/TypeError.m delete mode 100644 matlab/+yardl/Union.m delete mode 100644 matlab/+yardl/ValueError.m delete mode 100644 matlab/+yardl/allocate.m delete mode 100644 matlab/+yardl/dimension_count.m create mode 100644 matlab/.gitignore create mode 100755 matlab/build-toolbox.sh create mode 100644 matlab/buildfile.m rename matlab/{ => toolbox}/+petsird/+helpers/get_detection_efficiency.m (100%) rename matlab/{ => toolbox}/+petsird/+helpers/get_module_and_element.m (100%) rename matlab/{ => toolbox}/+petsird/+helpers/get_num_detecting_elements.m (100%) rename matlab/{ => toolbox}/petsird_analysis.m (100%) rename matlab/{ => toolbox}/petsird_generator.m (98%) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 8677bde..fe9b550 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -87,7 +87,7 @@ RUN mkdir -p /home/vscode/.local/share/CMakeTools \ && chown vscode:conda /home/vscode/.local/share/CMakeTools/cmake-tools-kits.json # Install the yardl tool -ARG YARDL_VERSION=0.6.2 +ARG YARDL_VERSION=0.6.3 RUN wget --quiet "https://github.com/microsoft/yardl/releases/download/v${YARDL_VERSION}/yardl_${YARDL_VERSION}_linux_x86_64.tar.gz" \ && tar -xzf "yardl_${YARDL_VERSION}_linux_x86_64.tar.gz" \ && mv yardl "/opt/conda/envs/${CONDA_ENVIRONMENT_NAME}/bin/" \ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6d9762e..626339c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ on: pull_request: {branches: [main]} defaults: {run: {shell: 'bash -el {0}'}} # https://github.com/marketplace/actions/setup-miniconda#important env: - YARDL_VERSION: 0.6.2 + YARDL_VERSION: 0.6.3 jobs: validate: strategy: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 76c21b1..b08d90c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,3 +56,4 @@ repos: rev: v14.0.6 hooks: - id: clang-format + types_or: [c++] diff --git a/matlab/+petsird/+binary/AnnulusShapeSerializer.m b/matlab/+petsird/+binary/AnnulusShapeSerializer.m deleted file mode 100644 index 62d85a3..0000000 --- a/matlab/+petsird/+binary/AnnulusShapeSerializer.m +++ /dev/null @@ -1,27 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef AnnulusShapeSerializer < yardl.binary.RecordSerializer - methods - function self = AnnulusShapeSerializer() - field_serializers{1} = yardl.binary.Float32Serializer; - field_serializers{2} = yardl.binary.Float32Serializer; - field_serializers{3} = yardl.binary.Float32Serializer; - field_serializers{4} = yardl.binary.FixedVectorSerializer(yardl.binary.Float32Serializer, 2); - self@yardl.binary.RecordSerializer('petsird.AnnulusShape', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.AnnulusShape - end - self.write_(outstream, value.inner_radius, value.outer_radius, value.thickness, value.angular_range); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.AnnulusShape(inner_radius=fields{1}, outer_radius=fields{2}, thickness=fields{3}, angular_range=fields{4}); - end - end -end diff --git a/matlab/+petsird/+binary/AtomSerializer.m b/matlab/+petsird/+binary/AtomSerializer.m deleted file mode 100644 index 9d6555d..0000000 --- a/matlab/+petsird/+binary/AtomSerializer.m +++ /dev/null @@ -1,25 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef AtomSerializer < yardl.binary.RecordSerializer - methods - function self = AtomSerializer() - field_serializers{1} = yardl.binary.Uint32Serializer; - field_serializers{2} = yardl.binary.Uint32Serializer; - self@yardl.binary.RecordSerializer('petsird.Atom', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.Atom - end - self.write_(outstream, value.mass_number, value.atomic_number); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.Atom(mass_number=fields{1}, atomic_number=fields{2}); - end - end -end diff --git a/matlab/+petsird/+binary/BedMovementTimeBlockSerializer.m b/matlab/+petsird/+binary/BedMovementTimeBlockSerializer.m deleted file mode 100644 index 2c66a2e..0000000 --- a/matlab/+petsird/+binary/BedMovementTimeBlockSerializer.m +++ /dev/null @@ -1,25 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef BedMovementTimeBlockSerializer < yardl.binary.RecordSerializer - methods - function self = BedMovementTimeBlockSerializer() - field_serializers{1} = yardl.binary.Uint32Serializer; - field_serializers{2} = petsird.binary.RigidTransformationSerializer(); - self@yardl.binary.RecordSerializer('petsird.BedMovementTimeBlock', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.BedMovementTimeBlock - end - self.write_(outstream, value.start, value.transform); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.BedMovementTimeBlock(start=fields{1}, transform=fields{2}); - end - end -end diff --git a/matlab/+petsird/+binary/BoxShapeSerializer.m b/matlab/+petsird/+binary/BoxShapeSerializer.m deleted file mode 100644 index beef341..0000000 --- a/matlab/+petsird/+binary/BoxShapeSerializer.m +++ /dev/null @@ -1,24 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef BoxShapeSerializer < yardl.binary.RecordSerializer - methods - function self = BoxShapeSerializer() - field_serializers{1} = yardl.binary.FixedVectorSerializer(petsird.binary.CoordinateSerializer(), 8); - self@yardl.binary.RecordSerializer('petsird.BoxShape', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.BoxShape - end - self.write_(outstream, value.corners); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.BoxShape(corners=fields{1}); - end - end -end diff --git a/matlab/+petsird/+binary/BulkMaterialSerializer.m b/matlab/+petsird/+binary/BulkMaterialSerializer.m deleted file mode 100644 index a98eedc..0000000 --- a/matlab/+petsird/+binary/BulkMaterialSerializer.m +++ /dev/null @@ -1,28 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef BulkMaterialSerializer < yardl.binary.RecordSerializer - methods - function self = BulkMaterialSerializer() - field_serializers{1} = yardl.binary.Uint32Serializer; - field_serializers{2} = yardl.binary.StringSerializer; - field_serializers{3} = yardl.binary.Float32Serializer; - field_serializers{4} = yardl.binary.VectorSerializer(petsird.binary.AtomSerializer()); - field_serializers{5} = yardl.binary.VectorSerializer(yardl.binary.Float32Serializer); - self@yardl.binary.RecordSerializer('petsird.BulkMaterial', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.BulkMaterial - end - self.write_(outstream, value.id, value.name, value.density, value.atoms, value.mass_fractions); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.BulkMaterial(id=fields{1}, name=fields{2}, density=fields{3}, atoms=fields{4}, mass_fractions=fields{5}); - end - end -end diff --git a/matlab/+petsird/+binary/CoincidenceEventSerializer.m b/matlab/+petsird/+binary/CoincidenceEventSerializer.m deleted file mode 100644 index aab45ad..0000000 --- a/matlab/+petsird/+binary/CoincidenceEventSerializer.m +++ /dev/null @@ -1,26 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef CoincidenceEventSerializer < yardl.binary.RecordSerializer - methods - function self = CoincidenceEventSerializer() - field_serializers{1} = yardl.binary.FixedVectorSerializer(yardl.binary.Uint32Serializer, 2); - field_serializers{2} = yardl.binary.Uint32Serializer; - field_serializers{3} = yardl.binary.FixedVectorSerializer(yardl.binary.Uint32Serializer, 2); - self@yardl.binary.RecordSerializer('petsird.CoincidenceEvent', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.CoincidenceEvent - end - self.write_(outstream, value.detector_ids, value.tof_idx, value.energy_indices); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.CoincidenceEvent(detector_ids=fields{1}, tof_idx=fields{2}, energy_indices=fields{3}); - end - end -end diff --git a/matlab/+petsird/+binary/CoordinateSerializer.m b/matlab/+petsird/+binary/CoordinateSerializer.m deleted file mode 100644 index 4219342..0000000 --- a/matlab/+petsird/+binary/CoordinateSerializer.m +++ /dev/null @@ -1,24 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef CoordinateSerializer < yardl.binary.RecordSerializer - methods - function self = CoordinateSerializer() - field_serializers{1} = yardl.binary.FixedNDArraySerializer(yardl.binary.Float32Serializer, [3]); - self@yardl.binary.RecordSerializer('petsird.Coordinate', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.Coordinate - end - self.write_(outstream, value.c); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.Coordinate(c=fields{1}); - end - end -end diff --git a/matlab/+petsird/+binary/DeadTimeTimeBlockSerializer.m b/matlab/+petsird/+binary/DeadTimeTimeBlockSerializer.m deleted file mode 100644 index f18eb0a..0000000 --- a/matlab/+petsird/+binary/DeadTimeTimeBlockSerializer.m +++ /dev/null @@ -1,26 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef DeadTimeTimeBlockSerializer < yardl.binary.RecordSerializer - methods - function self = DeadTimeTimeBlockSerializer() - field_serializers{1} = petsird.binary.TimeIntervalSerializer(); - field_serializers{2} = yardl.binary.NDArraySerializer(yardl.binary.Float32Serializer, 2); - field_serializers{3} = yardl.binary.NDArraySerializer(yardl.binary.Float32Serializer, 2); - self@yardl.binary.RecordSerializer('petsird.DeadTimeTimeBlock', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.DeadTimeTimeBlock - end - self.write_(outstream, value.time_interval, value.singles_alive_time_fraction, value.module_coincidence_alive_time_fraction); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.DeadTimeTimeBlock(time_interval=fields{1}, singles_alive_time_fraction=fields{2}, module_coincidence_alive_time_fraction=fields{3}); - end - end -end diff --git a/matlab/+petsird/+binary/DetectionEfficienciesSerializer.m b/matlab/+petsird/+binary/DetectionEfficienciesSerializer.m deleted file mode 100644 index 19ba038..0000000 --- a/matlab/+petsird/+binary/DetectionEfficienciesSerializer.m +++ /dev/null @@ -1,26 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef DetectionEfficienciesSerializer < yardl.binary.RecordSerializer - methods - function self = DetectionEfficienciesSerializer() - field_serializers{1} = yardl.binary.OptionalSerializer(yardl.binary.NDArraySerializer(yardl.binary.Float32Serializer, 2)); - field_serializers{2} = yardl.binary.OptionalSerializer(yardl.binary.NDArraySerializer(yardl.binary.Int32Serializer, 2)); - field_serializers{3} = yardl.binary.OptionalSerializer(yardl.binary.VectorSerializer(petsird.binary.ModulePairEfficienciesSerializer())); - self@yardl.binary.RecordSerializer('petsird.DetectionEfficiencies', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.DetectionEfficiencies - end - self.write_(outstream, value.det_el_efficiencies, value.module_pair_sgidlut, value.module_pair_efficiencies_vector); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.DetectionEfficiencies(det_el_efficiencies=fields{1}, module_pair_sgidlut=fields{2}, module_pair_efficiencies_vector=fields{3}); - end - end -end diff --git a/matlab/+petsird/+binary/DetectorModuleSerializer.m b/matlab/+petsird/+binary/DetectorModuleSerializer.m deleted file mode 100644 index 5e4a724..0000000 --- a/matlab/+petsird/+binary/DetectorModuleSerializer.m +++ /dev/null @@ -1,26 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef DetectorModuleSerializer < yardl.binary.RecordSerializer - methods - function self = DetectorModuleSerializer() - field_serializers{1} = yardl.binary.VectorSerializer(petsird.binary.ReplicatedObjectSerializer(petsird.binary.SolidVolumeSerializer(petsird.binary.BoxShapeSerializer()))); - field_serializers{2} = yardl.binary.VectorSerializer(yardl.binary.Uint32Serializer); - field_serializers{3} = yardl.binary.VectorSerializer(petsird.binary.ReplicatedObjectSerializer(petsird.binary.SolidVolumeSerializer(yardl.binary.UnionSerializer('petsird.GeometricShape', {petsird.binary.BoxShapeSerializer(), petsird.binary.AnnulusShapeSerializer()}, {@petsird.GeometricShape.BoxShape, @petsird.GeometricShape.AnnulusShape})))); - self@yardl.binary.RecordSerializer('petsird.DetectorModule', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.DetectorModule - end - self.write_(outstream, value.detecting_elements, value.detecting_element_ids, value.non_detecting_elements); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.DetectorModule(detecting_elements=fields{1}, detecting_element_ids=fields{2}, non_detecting_elements=fields{3}); - end - end -end diff --git a/matlab/+petsird/+binary/DirectionMatrixSerializer.m b/matlab/+petsird/+binary/DirectionMatrixSerializer.m deleted file mode 100644 index 179b6b1..0000000 --- a/matlab/+petsird/+binary/DirectionMatrixSerializer.m +++ /dev/null @@ -1,24 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef DirectionMatrixSerializer < yardl.binary.RecordSerializer - methods - function self = DirectionMatrixSerializer() - field_serializers{1} = yardl.binary.FixedNDArraySerializer(yardl.binary.Float32Serializer, [3, 3]); - self@yardl.binary.RecordSerializer('petsird.DirectionMatrix', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.DirectionMatrix - end - self.write_(outstream, value.matrix); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.DirectionMatrix(matrix=fields{1}); - end - end -end diff --git a/matlab/+petsird/+binary/DirectionSerializer.m b/matlab/+petsird/+binary/DirectionSerializer.m deleted file mode 100644 index 77401b4..0000000 --- a/matlab/+petsird/+binary/DirectionSerializer.m +++ /dev/null @@ -1,24 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef DirectionSerializer < yardl.binary.RecordSerializer - methods - function self = DirectionSerializer() - field_serializers{1} = yardl.binary.FixedNDArraySerializer(yardl.binary.Float32Serializer, [3]); - self@yardl.binary.RecordSerializer('petsird.Direction', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.Direction - end - self.write_(outstream, value.c); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.Direction(c=fields{1}); - end - end -end diff --git a/matlab/+petsird/+binary/EventTimeBlockSerializer.m b/matlab/+petsird/+binary/EventTimeBlockSerializer.m deleted file mode 100644 index b2bfec0..0000000 --- a/matlab/+petsird/+binary/EventTimeBlockSerializer.m +++ /dev/null @@ -1,27 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef EventTimeBlockSerializer < yardl.binary.RecordSerializer - methods - function self = EventTimeBlockSerializer() - field_serializers{1} = yardl.binary.Uint32Serializer; - field_serializers{2} = yardl.binary.VectorSerializer(petsird.binary.CoincidenceEventSerializer()); - field_serializers{3} = yardl.binary.OptionalSerializer(yardl.binary.VectorSerializer(petsird.binary.CoincidenceEventSerializer())); - field_serializers{4} = yardl.binary.OptionalSerializer(yardl.binary.VectorSerializer(petsird.binary.TripleEventSerializer())); - self@yardl.binary.RecordSerializer('petsird.EventTimeBlock', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.EventTimeBlock - end - self.write_(outstream, value.start, value.prompt_events, value.delayed_events, value.triple_events); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.EventTimeBlock(start=fields{1}, prompt_events=fields{2}, delayed_events=fields{3}, triple_events=fields{4}); - end - end -end diff --git a/matlab/+petsird/+binary/ExamInformationSerializer.m b/matlab/+petsird/+binary/ExamInformationSerializer.m deleted file mode 100644 index 317561f..0000000 --- a/matlab/+petsird/+binary/ExamInformationSerializer.m +++ /dev/null @@ -1,27 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ExamInformationSerializer < yardl.binary.RecordSerializer - methods - function self = ExamInformationSerializer() - field_serializers{1} = petsird.binary.SubjectSerializer(); - field_serializers{2} = petsird.binary.InstitutionSerializer(); - field_serializers{3} = yardl.binary.OptionalSerializer(yardl.binary.StringSerializer); - field_serializers{4} = yardl.binary.OptionalSerializer(yardl.binary.DatetimeSerializer); - self@yardl.binary.RecordSerializer('petsird.ExamInformation', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.ExamInformation - end - self.write_(outstream, value.subject, value.institution, value.protocol, value.start_of_acquisition); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.ExamInformation(subject=fields{1}, institution=fields{2}, protocol=fields{3}, start_of_acquisition=fields{4}); - end - end -end diff --git a/matlab/+petsird/+binary/ExternalSignalTimeBlockSerializer.m b/matlab/+petsird/+binary/ExternalSignalTimeBlockSerializer.m deleted file mode 100644 index 9e820fe..0000000 --- a/matlab/+petsird/+binary/ExternalSignalTimeBlockSerializer.m +++ /dev/null @@ -1,26 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ExternalSignalTimeBlockSerializer < yardl.binary.RecordSerializer - methods - function self = ExternalSignalTimeBlockSerializer() - field_serializers{1} = yardl.binary.Uint32Serializer; - field_serializers{2} = yardl.binary.Uint32Serializer; - field_serializers{3} = yardl.binary.VectorSerializer(yardl.binary.Float32Serializer); - self@yardl.binary.RecordSerializer('petsird.ExternalSignalTimeBlock', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.ExternalSignalTimeBlock - end - self.write_(outstream, value.start, value.signal_id, value.signal_values); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.ExternalSignalTimeBlock(start=fields{1}, signal_id=fields{2}, signal_values=fields{3}); - end - end -end diff --git a/matlab/+petsird/+binary/ExternalSignalTypeSerializer.m b/matlab/+petsird/+binary/ExternalSignalTypeSerializer.m deleted file mode 100644 index 39ca23c..0000000 --- a/matlab/+petsird/+binary/ExternalSignalTypeSerializer.m +++ /dev/null @@ -1,26 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ExternalSignalTypeSerializer < yardl.binary.RecordSerializer - methods - function self = ExternalSignalTypeSerializer() - field_serializers{1} = yardl.binary.EnumSerializer('petsird.ExternalSignalTypeEnum', @petsird.ExternalSignalTypeEnum, yardl.binary.Int32Serializer); - field_serializers{2} = yardl.binary.StringSerializer; - field_serializers{3} = yardl.binary.Uint32Serializer; - self@yardl.binary.RecordSerializer('petsird.ExternalSignalType', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.ExternalSignalType - end - self.write_(outstream, value.type, value.description, value.id); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.ExternalSignalType(type=fields{1}, description=fields{2}, id=fields{3}); - end - end -end diff --git a/matlab/+petsird/+binary/GantryMovementTimeBlockSerializer.m b/matlab/+petsird/+binary/GantryMovementTimeBlockSerializer.m deleted file mode 100644 index 7b47a59..0000000 --- a/matlab/+petsird/+binary/GantryMovementTimeBlockSerializer.m +++ /dev/null @@ -1,25 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef GantryMovementTimeBlockSerializer < yardl.binary.RecordSerializer - methods - function self = GantryMovementTimeBlockSerializer() - field_serializers{1} = yardl.binary.Uint32Serializer; - field_serializers{2} = petsird.binary.RigidTransformationSerializer(); - self@yardl.binary.RecordSerializer('petsird.GantryMovementTimeBlock', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.GantryMovementTimeBlock - end - self.write_(outstream, value.start, value.transform); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.GantryMovementTimeBlock(start=fields{1}, transform=fields{2}); - end - end -end diff --git a/matlab/+petsird/+binary/HeaderSerializer.m b/matlab/+petsird/+binary/HeaderSerializer.m deleted file mode 100644 index 8cd8e36..0000000 --- a/matlab/+petsird/+binary/HeaderSerializer.m +++ /dev/null @@ -1,25 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef HeaderSerializer < yardl.binary.RecordSerializer - methods - function self = HeaderSerializer() - field_serializers{1} = petsird.binary.ScannerInformationSerializer(); - field_serializers{2} = yardl.binary.OptionalSerializer(petsird.binary.ExamInformationSerializer()); - self@yardl.binary.RecordSerializer('petsird.Header', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.Header - end - self.write_(outstream, value.scanner, value.exam); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.Header(scanner=fields{1}, exam=fields{2}); - end - end -end diff --git a/matlab/+petsird/+binary/InstitutionSerializer.m b/matlab/+petsird/+binary/InstitutionSerializer.m deleted file mode 100644 index 3d33ba0..0000000 --- a/matlab/+petsird/+binary/InstitutionSerializer.m +++ /dev/null @@ -1,25 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef InstitutionSerializer < yardl.binary.RecordSerializer - methods - function self = InstitutionSerializer() - field_serializers{1} = yardl.binary.StringSerializer; - field_serializers{2} = yardl.binary.StringSerializer; - self@yardl.binary.RecordSerializer('petsird.Institution', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.Institution - end - self.write_(outstream, value.name, value.address); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.Institution(name=fields{1}, address=fields{2}); - end - end -end diff --git a/matlab/+petsird/+binary/ModulePairEfficienciesSerializer.m b/matlab/+petsird/+binary/ModulePairEfficienciesSerializer.m deleted file mode 100644 index 871379d..0000000 --- a/matlab/+petsird/+binary/ModulePairEfficienciesSerializer.m +++ /dev/null @@ -1,25 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ModulePairEfficienciesSerializer < yardl.binary.RecordSerializer - methods - function self = ModulePairEfficienciesSerializer() - field_serializers{1} = yardl.binary.NDArraySerializer(yardl.binary.Float32Serializer, 4); - field_serializers{2} = yardl.binary.Uint32Serializer; - self@yardl.binary.RecordSerializer('petsird.ModulePairEfficiencies', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.ModulePairEfficiencies - end - self.write_(outstream, value.values, value.sgid); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.ModulePairEfficiencies(values=fields{1}, sgid=fields{2}); - end - end -end diff --git a/matlab/+petsird/+binary/PETSIRDReader.m b/matlab/+petsird/+binary/PETSIRDReader.m deleted file mode 100644 index 8cf8ef7..0000000 --- a/matlab/+petsird/+binary/PETSIRDReader.m +++ /dev/null @@ -1,33 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef PETSIRDReader < yardl.binary.BinaryProtocolReader & petsird.PETSIRDReaderBase - % Binary reader for the PETSIRD protocol - % Definition of the stream of data - properties (Access=protected) - header_serializer - time_blocks_serializer - end - - methods - function self = PETSIRDReader(filename) - self@petsird.PETSIRDReaderBase(); - self@yardl.binary.BinaryProtocolReader(filename, petsird.PETSIRDReaderBase.schema); - self.header_serializer = petsird.binary.HeaderSerializer(); - self.time_blocks_serializer = yardl.binary.StreamSerializer(yardl.binary.UnionSerializer('petsird.TimeBlock', {petsird.binary.EventTimeBlockSerializer(), petsird.binary.ExternalSignalTimeBlockSerializer(), petsird.binary.BedMovementTimeBlockSerializer(), petsird.binary.GantryMovementTimeBlockSerializer()}, {@petsird.TimeBlock.EventTimeBlock, @petsird.TimeBlock.ExternalSignalTimeBlock, @petsird.TimeBlock.BedMovementTimeBlock, @petsird.TimeBlock.GantryMovementTimeBlock})); - end - end - - methods (Access=protected) - function value = read_header_(self) - value = self.header_serializer.read(self.stream_); - end - - function more = has_time_blocks_(self) - more = self.time_blocks_serializer.hasnext(self.stream_); - end - - function value = read_time_blocks_(self) - value = self.time_blocks_serializer.read(self.stream_); - end - end -end diff --git a/matlab/+petsird/+binary/PETSIRDWriter.m b/matlab/+petsird/+binary/PETSIRDWriter.m deleted file mode 100644 index 3d3ff4f..0000000 --- a/matlab/+petsird/+binary/PETSIRDWriter.m +++ /dev/null @@ -1,29 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef PETSIRDWriter < yardl.binary.BinaryProtocolWriter & petsird.PETSIRDWriterBase - % Binary writer for the PETSIRD protocol - % Definition of the stream of data - properties (Access=protected) - header_serializer - time_blocks_serializer - end - - methods - function self = PETSIRDWriter(filename) - self@petsird.PETSIRDWriterBase(); - self@yardl.binary.BinaryProtocolWriter(filename, petsird.PETSIRDWriterBase.schema); - self.header_serializer = petsird.binary.HeaderSerializer(); - self.time_blocks_serializer = yardl.binary.StreamSerializer(yardl.binary.UnionSerializer('petsird.TimeBlock', {petsird.binary.EventTimeBlockSerializer(), petsird.binary.ExternalSignalTimeBlockSerializer(), petsird.binary.BedMovementTimeBlockSerializer(), petsird.binary.GantryMovementTimeBlockSerializer()}, {@petsird.TimeBlock.EventTimeBlock, @petsird.TimeBlock.ExternalSignalTimeBlock, @petsird.TimeBlock.BedMovementTimeBlock, @petsird.TimeBlock.GantryMovementTimeBlock})); - end - end - - methods (Access=protected) - function write_header_(self, value) - self.header_serializer.write(self.stream_, value); - end - - function write_time_blocks_(self, value) - self.time_blocks_serializer.write(self.stream_, value); - end - end -end diff --git a/matlab/+petsird/+binary/ReplicatedObjectSerializer.m b/matlab/+petsird/+binary/ReplicatedObjectSerializer.m deleted file mode 100644 index e8439ee..0000000 --- a/matlab/+petsird/+binary/ReplicatedObjectSerializer.m +++ /dev/null @@ -1,26 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ReplicatedObjectSerializer < yardl.binary.RecordSerializer - methods - function self = ReplicatedObjectSerializer(t_serializer) - field_serializers{1} = t_serializer; - field_serializers{2} = yardl.binary.VectorSerializer(petsird.binary.RigidTransformationSerializer()); - field_serializers{3} = yardl.binary.VectorSerializer(yardl.binary.Uint32Serializer); - self@yardl.binary.RecordSerializer('petsird.ReplicatedObject', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.ReplicatedObject - end - self.write_(outstream, value.object, value.transforms, value.ids); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.ReplicatedObject(object=fields{1}, transforms=fields{2}, ids=fields{3}); - end - end -end diff --git a/matlab/+petsird/+binary/RigidTransformationSerializer.m b/matlab/+petsird/+binary/RigidTransformationSerializer.m deleted file mode 100644 index d0c7268..0000000 --- a/matlab/+petsird/+binary/RigidTransformationSerializer.m +++ /dev/null @@ -1,24 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef RigidTransformationSerializer < yardl.binary.RecordSerializer - methods - function self = RigidTransformationSerializer() - field_serializers{1} = yardl.binary.FixedNDArraySerializer(yardl.binary.Float32Serializer, [4, 3]); - self@yardl.binary.RecordSerializer('petsird.RigidTransformation', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.RigidTransformation - end - self.write_(outstream, value.matrix); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.RigidTransformation(matrix=fields{1}); - end - end -end diff --git a/matlab/+petsird/+binary/ScannerGeometrySerializer.m b/matlab/+petsird/+binary/ScannerGeometrySerializer.m deleted file mode 100644 index 4c55c69..0000000 --- a/matlab/+petsird/+binary/ScannerGeometrySerializer.m +++ /dev/null @@ -1,26 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ScannerGeometrySerializer < yardl.binary.RecordSerializer - methods - function self = ScannerGeometrySerializer() - field_serializers{1} = yardl.binary.VectorSerializer(petsird.binary.ReplicatedObjectSerializer(petsird.binary.DetectorModuleSerializer())); - field_serializers{2} = yardl.binary.VectorSerializer(yardl.binary.Uint32Serializer); - field_serializers{3} = yardl.binary.OptionalSerializer(yardl.binary.VectorSerializer(petsird.binary.SolidVolumeSerializer(yardl.binary.UnionSerializer('petsird.GeometricShape', {petsird.binary.BoxShapeSerializer(), petsird.binary.AnnulusShapeSerializer()}, {@petsird.GeometricShape.BoxShape, @petsird.GeometricShape.AnnulusShape})))); - self@yardl.binary.RecordSerializer('petsird.ScannerGeometry', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.ScannerGeometry - end - self.write_(outstream, value.replicated_modules, value.ids, value.non_detecting_volumes); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.ScannerGeometry(replicated_modules=fields{1}, ids=fields{2}, non_detecting_volumes=fields{3}); - end - end -end diff --git a/matlab/+petsird/+binary/ScannerInformationSerializer.m b/matlab/+petsird/+binary/ScannerInformationSerializer.m deleted file mode 100644 index e22a582..0000000 --- a/matlab/+petsird/+binary/ScannerInformationSerializer.m +++ /dev/null @@ -1,34 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ScannerInformationSerializer < yardl.binary.RecordSerializer - methods - function self = ScannerInformationSerializer() - field_serializers{1} = yardl.binary.StringSerializer; - field_serializers{2} = petsird.binary.ScannerGeometrySerializer(); - field_serializers{3} = yardl.binary.VectorSerializer(petsird.binary.BulkMaterialSerializer()); - field_serializers{4} = yardl.binary.OptionalSerializer(petsird.binary.RigidTransformationSerializer()); - field_serializers{5} = yardl.binary.NDArraySerializer(yardl.binary.Float32Serializer, 1); - field_serializers{6} = yardl.binary.Float32Serializer; - field_serializers{7} = yardl.binary.NDArraySerializer(yardl.binary.Float32Serializer, 1); - field_serializers{8} = yardl.binary.Float32Serializer; - field_serializers{9} = yardl.binary.Uint32Serializer; - field_serializers{10} = yardl.binary.EnumSerializer('petsird.CoincidencePolicy', @petsird.CoincidencePolicy, yardl.binary.Int32Serializer); - field_serializers{11} = petsird.binary.DetectionEfficienciesSerializer(); - self@yardl.binary.RecordSerializer('petsird.ScannerInformation', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.ScannerInformation - end - self.write_(outstream, value.model_name, value.scanner_geometry, value.bulk_materials, value.gantry_alignment, value.tof_bin_edges, value.tof_resolution, value.energy_bin_edges, value.energy_resolution_at_511, value.event_time_block_duration, value.coincidence_policy, value.detection_efficiencies); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.ScannerInformation(model_name=fields{1}, scanner_geometry=fields{2}, bulk_materials=fields{3}, gantry_alignment=fields{4}, tof_bin_edges=fields{5}, tof_resolution=fields{6}, energy_bin_edges=fields{7}, energy_resolution_at_511=fields{8}, event_time_block_duration=fields{9}, coincidence_policy=fields{10}, detection_efficiencies=fields{11}); - end - end -end diff --git a/matlab/+petsird/+binary/SolidVolumeSerializer.m b/matlab/+petsird/+binary/SolidVolumeSerializer.m deleted file mode 100644 index 0743e08..0000000 --- a/matlab/+petsird/+binary/SolidVolumeSerializer.m +++ /dev/null @@ -1,25 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef SolidVolumeSerializer < yardl.binary.RecordSerializer - methods - function self = SolidVolumeSerializer(shape_serializer) - field_serializers{1} = shape_serializer; - field_serializers{2} = yardl.binary.Uint32Serializer; - self@yardl.binary.RecordSerializer('petsird.SolidVolume', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.SolidVolume - end - self.write_(outstream, value.shape, value.material_id); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.SolidVolume(shape=fields{1}, material_id=fields{2}); - end - end -end diff --git a/matlab/+petsird/+binary/SubjectSerializer.m b/matlab/+petsird/+binary/SubjectSerializer.m deleted file mode 100644 index ce7d2e0..0000000 --- a/matlab/+petsird/+binary/SubjectSerializer.m +++ /dev/null @@ -1,25 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef SubjectSerializer < yardl.binary.RecordSerializer - methods - function self = SubjectSerializer() - field_serializers{1} = yardl.binary.OptionalSerializer(yardl.binary.StringSerializer); - field_serializers{2} = yardl.binary.StringSerializer; - self@yardl.binary.RecordSerializer('petsird.Subject', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.Subject - end - self.write_(outstream, value.name, value.id); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.Subject(name=fields{1}, id=fields{2}); - end - end -end diff --git a/matlab/+petsird/+binary/TimeFrameInformationSerializer.m b/matlab/+petsird/+binary/TimeFrameInformationSerializer.m deleted file mode 100644 index 1148122..0000000 --- a/matlab/+petsird/+binary/TimeFrameInformationSerializer.m +++ /dev/null @@ -1,24 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef TimeFrameInformationSerializer < yardl.binary.RecordSerializer - methods - function self = TimeFrameInformationSerializer() - field_serializers{1} = yardl.binary.VectorSerializer(petsird.binary.TimeIntervalSerializer()); - self@yardl.binary.RecordSerializer('petsird.TimeFrameInformation', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.TimeFrameInformation - end - self.write_(outstream, value.time_frames); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.TimeFrameInformation(time_frames=fields{1}); - end - end -end diff --git a/matlab/+petsird/+binary/TimeIntervalSerializer.m b/matlab/+petsird/+binary/TimeIntervalSerializer.m deleted file mode 100644 index 978fbb6..0000000 --- a/matlab/+petsird/+binary/TimeIntervalSerializer.m +++ /dev/null @@ -1,25 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef TimeIntervalSerializer < yardl.binary.RecordSerializer - methods - function self = TimeIntervalSerializer() - field_serializers{1} = yardl.binary.Uint32Serializer; - field_serializers{2} = yardl.binary.Uint32Serializer; - self@yardl.binary.RecordSerializer('petsird.TimeInterval', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.TimeInterval - end - self.write_(outstream, value.start, value.stop); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.TimeInterval(start=fields{1}, stop=fields{2}); - end - end -end diff --git a/matlab/+petsird/+binary/TripleEventSerializer.m b/matlab/+petsird/+binary/TripleEventSerializer.m deleted file mode 100644 index f5b0dfe..0000000 --- a/matlab/+petsird/+binary/TripleEventSerializer.m +++ /dev/null @@ -1,26 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef TripleEventSerializer < yardl.binary.RecordSerializer - methods - function self = TripleEventSerializer() - field_serializers{1} = yardl.binary.FixedVectorSerializer(yardl.binary.Uint32Serializer, 3); - field_serializers{2} = yardl.binary.FixedVectorSerializer(yardl.binary.Uint32Serializer, 2); - field_serializers{3} = yardl.binary.FixedVectorSerializer(yardl.binary.Uint32Serializer, 3); - self@yardl.binary.RecordSerializer('petsird.TripleEvent', field_serializers); - end - - function write(self, outstream, value) - arguments - self - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) petsird.TripleEvent - end - self.write_(outstream, value.detector_ids, value.tof_indices, value.energy_indices); - end - - function value = read(self, instream) - fields = self.read_(instream); - value = petsird.TripleEvent(detector_ids=fields{1}, tof_indices=fields{2}, energy_indices=fields{3}); - end - end -end diff --git a/matlab/+petsird/AnnulusShape.m b/matlab/+petsird/AnnulusShape.m deleted file mode 100644 index ef5e784..0000000 --- a/matlab/+petsird/AnnulusShape.m +++ /dev/null @@ -1,63 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef AnnulusShape < handle - % Annulus of certain thickness centered at [0,0,0] and oriented along the [0,0,1] axis - % in radians. An angle of 0 corresponds to the [1,0,0] axis, Pi/2 corresponds to the [0,1,0] axis. - properties - % inner radius (in mm) - inner_radius - % outer radius (in mm) - outer_radius - % thickness of the annulus, i.e. length along the axis (in mm) - thickness - % start-stop angle (in radians) - angular_range - end - - methods - function self = AnnulusShape(kwargs) - arguments - kwargs.inner_radius = single(0); - kwargs.outer_radius = single(0); - kwargs.thickness = single(0); - kwargs.angular_range = repelem(single(0), 2); - end - self.inner_radius = kwargs.inner_radius; - self.outer_radius = kwargs.outer_radius; - self.thickness = kwargs.thickness; - self.angular_range = kwargs.angular_range; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.AnnulusShape") && ... - isequal({self.inner_radius}, {other.inner_radius}) && ... - isequal({self.outer_radius}, {other.outer_radius}) && ... - isequal({self.thickness}, {other.thickness}) && ... - isequal({self.angular_range}, {other.angular_range}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.AnnulusShape(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/Atom.m b/matlab/+petsird/Atom.m deleted file mode 100644 index 502193b..0000000 --- a/matlab/+petsird/Atom.m +++ /dev/null @@ -1,52 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef Atom < handle - % Atom definition in terms of Z and A - properties - % A - mass_number - % Z - atomic_number - end - - methods - function self = Atom(kwargs) - arguments - kwargs.mass_number = uint32(0); - kwargs.atomic_number = uint32(0); - end - self.mass_number = kwargs.mass_number; - self.atomic_number = kwargs.atomic_number; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.Atom") && ... - isequal({self.mass_number}, {other.mass_number}) && ... - isequal({self.atomic_number}, {other.atomic_number}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.Atom(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/BedMovementTimeBlock.m b/matlab/+petsird/BedMovementTimeBlock.m deleted file mode 100644 index 4dd7de2..0000000 --- a/matlab/+petsird/BedMovementTimeBlock.m +++ /dev/null @@ -1,50 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef BedMovementTimeBlock < handle - properties - % start time since ExamInformation.startOfAcquisition in ms - start - transform - end - - methods - function self = BedMovementTimeBlock(kwargs) - arguments - kwargs.start = uint32(0); - kwargs.transform = petsird.RigidTransformation(); - end - self.start = kwargs.start; - self.transform = kwargs.transform; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.BedMovementTimeBlock") && ... - isequal({self.start}, {other.start}) && ... - isequal({self.transform}, {other.transform}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.BedMovementTimeBlock(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/BoxShape.m b/matlab/+petsird/BoxShape.m deleted file mode 100644 index a6e99be..0000000 --- a/matlab/+petsird/BoxShape.m +++ /dev/null @@ -1,51 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef BoxShape < handle - % A box-shape specified by 8 corners (e.g. cuboid, wedge, etc.) - % TODO need to think about a clear definition of planes - % We do not want to have to check about intersection planes - % Potential mechanisms: - % - lexicographical ordering of corner coordinates? - % - first 4 coordinates give first plane, 5th and 6th need to define plane with first 2, etc. - properties - corners - end - - methods - function self = BoxShape(kwargs) - arguments - kwargs.corners = repelem(petsird.Coordinate(), 8); - end - self.corners = kwargs.corners; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.BoxShape") && ... - isequal({self.corners}, {other.corners}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.BoxShape(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/BoxSolidVolume.m b/matlab/+petsird/BoxSolidVolume.m deleted file mode 100644 index 2dfb662..0000000 --- a/matlab/+petsird/BoxSolidVolume.m +++ /dev/null @@ -1,4 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef BoxSolidVolume < petsird.SolidVolume -end diff --git a/matlab/+petsird/BulkMaterial.m b/matlab/+petsird/BulkMaterial.m deleted file mode 100644 index 42cee00..0000000 --- a/matlab/+petsird/BulkMaterial.m +++ /dev/null @@ -1,75 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef BulkMaterial < handle - % Specification of materials used in the scanner. - % TODO agree with vendors if this information can be supplied and to what accuracy - % Ideally this list should be reasonably accurate to be useful for Monte Carlo simulations, but can be approximate. - properties - % unique id that can be used to refer to the material in voxelised maps etc - id - % informative string, not standardised. - % Expected examples: - % detecting: BGO, LSO, LYSO, LaBr, GAGG, plastic - % non-detecting: tungsten, lead - name - % density of the material - % Units: g/cc - density - % List of atoms - atoms - % List of massFractions for the atoms. - % constraint: sum of massFractions should be 1 - % constraint: size(atoms) == size(massFractions) - mass_fractions - end - - methods - function self = BulkMaterial(kwargs) - arguments - kwargs.id = uint32(0); - kwargs.name = ""; - kwargs.density = single(0); - kwargs.atoms = petsird.Atom.empty(); - kwargs.mass_fractions = single.empty(); - end - self.id = kwargs.id; - self.name = kwargs.name; - self.density = kwargs.density; - self.atoms = kwargs.atoms; - self.mass_fractions = kwargs.mass_fractions; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.BulkMaterial") && ... - isequal({self.id}, {other.id}) && ... - isequal({self.name}, {other.name}) && ... - isequal({self.density}, {other.density}) && ... - isequal({self.atoms}, {other.atoms}) && ... - isequal({self.mass_fractions}, {other.mass_fractions}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.BulkMaterial(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/CoincidenceEvent.m b/matlab/+petsird/CoincidenceEvent.m deleted file mode 100644 index b7ed203..0000000 --- a/matlab/+petsird/CoincidenceEvent.m +++ /dev/null @@ -1,58 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef CoincidenceEvent < handle - % All information about a coincidence event specified as identifiers or indices (i.e. discretized). Indices start from 0. - % TODO: this might take up too much space, so some/all of these could be combined in a single index if necessary. - properties - % the pair of detector elements - detector_ids - % an index into the tofBinEdges field in the ScannerInformation - tof_idx - % a pair of indices into the energyBinEdges field in the ScannerInformation - energy_indices - end - - methods - function self = CoincidenceEvent(kwargs) - arguments - kwargs.detector_ids = repelem(uint32(0), 2); - kwargs.tof_idx = uint32(0); - kwargs.energy_indices = repelem(uint32(0), 2); - end - self.detector_ids = kwargs.detector_ids; - self.tof_idx = kwargs.tof_idx; - self.energy_indices = kwargs.energy_indices; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.CoincidenceEvent") && ... - isequal({self.detector_ids}, {other.detector_ids}) && ... - isequal({self.tof_idx}, {other.tof_idx}) && ... - isequal({self.energy_indices}, {other.energy_indices}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.CoincidenceEvent(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/CoincidencePolicy.m b/matlab/+petsird/CoincidencePolicy.m deleted file mode 100644 index d572dfc..0000000 --- a/matlab/+petsird/CoincidencePolicy.m +++ /dev/null @@ -1,35 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef CoincidencePolicy < uint64 - % Type definition for how to encode how the scanner handles multiple coincidences when recording the prompts. - % Due to various effects (such as high count rate, prompt gammas), it is possible that multiple single - % events are detected within the coincidence window. This type encodes some different ways - % that this multiple events are handled, and recorded in the coincidence stream. - methods (Static) - % multiples will be rejected - function v = REJECT_MULTIPLES - v = petsird.CoincidencePolicy(0); - end - % multiples will be stored as a sequence of pairs, e.g. a triple leads to 3 pairs - function v = STORE_MULTIPLES_AS_PAIRS - v = petsird.CoincidencePolicy(1); - end - % other options, to be listed in the future - function v = OTHER - v = petsird.CoincidencePolicy(2); - end - - function z = zeros(varargin) - elem = petsird.CoincidencePolicy(0); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/Coordinate.m b/matlab/+petsird/Coordinate.m deleted file mode 100644 index 978d1ef..0000000 --- a/matlab/+petsird/Coordinate.m +++ /dev/null @@ -1,46 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef Coordinate < handle - % 3D coordinates (in mm) - properties - c - end - - methods - function self = Coordinate(kwargs) - arguments - kwargs.c = repelem(single(0), 3, 1); - end - self.c = kwargs.c; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.Coordinate") && ... - isequal({self.c}, {other.c}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.Coordinate(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/DeadTimeTimeBlock.m b/matlab/+petsird/DeadTimeTimeBlock.m deleted file mode 100644 index 5e2fff6..0000000 --- a/matlab/+petsird/DeadTimeTimeBlock.m +++ /dev/null @@ -1,76 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef DeadTimeTimeBlock < handle - properties - % time interval for this time block - time_interval - % Singles dead-time array for the time interval, stored as fractions of "alive time" - % (1 means no dead-time, 0 means no detected counts) - % If sizeOfEnergyIdxDimension == 1, the fraction is assumed to be the same - % for all energy windows. - % Constraint: sizeOfDetectorIdDimension == number of all possible unique DetectorIds - % Constraint: (sizeOfEnergyIdxDimension == 1) or (sizeOfEnergyIdxDimension == ScannerInformation.numberOfEnergyBins) - singles_alive_time_fraction - % coincidence dead-time array for 2 modules in coincidence, stored as fractions of "alive time" - % (1 means no dead-time, 0 means no detected coincidences) - % If the size of this 2D array is (1,1), it is assumed that the corresponding alive-fraction is the same for all modules. - % Constraint: size(moduleCoincidenceAliveTimeFraction, 0) == 1 or total number of modules of all types - % Constraint: size(moduleCoincidenceAliveTimeFraction, 1) == 1 or total number of modules of all types - module_coincidence_alive_time_fraction - end - - methods - function self = DeadTimeTimeBlock(kwargs) - arguments - kwargs.time_interval = petsird.TimeInterval(); - kwargs.singles_alive_time_fraction = single.empty(); - kwargs.module_coincidence_alive_time_fraction = single.empty(); - end - self.time_interval = kwargs.time_interval; - self.singles_alive_time_fraction = kwargs.singles_alive_time_fraction; - self.module_coincidence_alive_time_fraction = kwargs.module_coincidence_alive_time_fraction; - end - - function res = size_of_detector_id_dimension(self) - res = size(self.singles_alive_time_fraction, ndims(self.singles_alive_time_fraction)-(0)); - return - end - - function res = size_of_energy_idx_dimension(self) - res = size(self.singles_alive_time_fraction, ndims(self.singles_alive_time_fraction)-(1)); - return - end - - - function res = eq(self, other) - res = ... - isa(other, "petsird.DeadTimeTimeBlock") && ... - isequal({self.time_interval}, {other.time_interval}) && ... - isequal({self.singles_alive_time_fraction}, {other.singles_alive_time_fraction}) && ... - isequal({self.module_coincidence_alive_time_fraction}, {other.module_coincidence_alive_time_fraction}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.DeadTimeTimeBlock(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/DetectionEfficiencies.m b/matlab/+petsird/DetectionEfficiencies.m deleted file mode 100644 index c9a7d7c..0000000 --- a/matlab/+petsird/DetectionEfficiencies.m +++ /dev/null @@ -1,82 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef DetectionEfficiencies < handle - % Component-based information on detection efficiencies - % This encodes a simple model for the detection efficiency of (true) coincidences - % consisting of the product of the efficiency of the two detecting elements (det_els) - % and a (geometric) component determined by their location in the two modules. - % The former are stored in detElEfficiencies, and the latter in modulePairEfficienciesVector - % (a list of ModulePairEfficiencies, each entry corresponding to a module pair). - - % Most PET scanners have some kind of geometric symmetry, e.g. rotation over a full - % module, or translation along the axis of the scanner. Module-pairs that are related - % by such a symmetry often have the same geometric detection efficiencies. PETSIRD - % calls this a "symmetry group" (SG). Each SG had an identifier (SGID). To save memory, - % the modulePairEfficienciesVector needs to contain only one of element for each SGID. - % The SGID for a module-pair can be found in modulePairSGIDLUT. - - % Finding the total detection efficiency therefore follows these steps: - % (the following pseudo-code ignores energy bins for simplicity) - % 1. find modules for each det_el - % 2. find det_el indices "inside" each module - % 3. SGID = modulePairSGIDLUT[mod1, mod1] - % 4. if (SGID < 0) return 0 - % 5. module_pair_efficiencies = modulePairEfficienciesVector[SGID] - % 6. return detElEfficiencies[det_el1] * detElEfficiencies[det_el2] * module_pair_efficiencies[det_el_in_mod1, det_el_in_mod2] - - % If either of the components is not present, its value is considered to be 1. - properties - % Detection efficiencies for every detecting element - det_el_efficiencies - % Lookup table for SGIDs. - % Also indicates if coincidences between a module-pair are recorded. - module_pair_sgidlut - % Vector of all modulePairEfficiencies (one for each SGID) - % Constraint: size(modulePairEfficienciesVector) == max(modulePairSGIDLUT) + 1 - module_pair_efficiencies_vector - end - - methods - function self = DetectionEfficiencies(kwargs) - arguments - kwargs.det_el_efficiencies = yardl.None; - kwargs.module_pair_sgidlut = yardl.None; - kwargs.module_pair_efficiencies_vector = yardl.None; - end - self.det_el_efficiencies = kwargs.det_el_efficiencies; - self.module_pair_sgidlut = kwargs.module_pair_sgidlut; - self.module_pair_efficiencies_vector = kwargs.module_pair_efficiencies_vector; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.DetectionEfficiencies") && ... - isequal({self.det_el_efficiencies}, {other.det_el_efficiencies}) && ... - isequal({self.module_pair_sgidlut}, {other.module_pair_sgidlut}) && ... - isequal({self.module_pair_efficiencies_vector}, {other.module_pair_efficiencies_vector}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.DetectionEfficiencies(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/DetectorModule.m b/matlab/+petsird/DetectorModule.m deleted file mode 100644 index 8699895..0000000 --- a/matlab/+petsird/DetectorModule.m +++ /dev/null @@ -1,59 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef DetectorModule < handle - % Top-level detector structure, consisting of one or more lists of detecting elements (or "crystals") - % This allows having different types of detecting elements (e.g. for phoswich detectors) - % TODO this could be made into a hierarchical structure - properties - detecting_elements - % list of unique ids for every replicated solid volume - % constraint: size(detectingElements) == size(detectingElementsIds) - detecting_element_ids - % optional list describing shielding/optical reflectors etc - non_detecting_elements - end - - methods - function self = DetectorModule(kwargs) - arguments - kwargs.detecting_elements = petsird.ReplicatedBoxSolidVolume.empty(); - kwargs.detecting_element_ids = uint32.empty(); - kwargs.non_detecting_elements = petsird.ReplicatedGenericSolidVolume.empty(); - end - self.detecting_elements = kwargs.detecting_elements; - self.detecting_element_ids = kwargs.detecting_element_ids; - self.non_detecting_elements = kwargs.non_detecting_elements; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.DetectorModule") && ... - isequal({self.detecting_elements}, {other.detecting_elements}) && ... - isequal({self.detecting_element_ids}, {other.detecting_element_ids}) && ... - isequal({self.non_detecting_elements}, {other.non_detecting_elements}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.DetectorModule(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/Direction.m b/matlab/+petsird/Direction.m deleted file mode 100644 index 0b35e77..0000000 --- a/matlab/+petsird/Direction.m +++ /dev/null @@ -1,46 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef Direction < handle - % 3D direction vector (normalized to 1) - properties - c - end - - methods - function self = Direction(kwargs) - arguments - kwargs.c = repelem(single(0), 3, 1); - end - self.c = kwargs.c; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.Direction") && ... - isequal({self.c}, {other.c}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.Direction(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/DirectionMatrix.m b/matlab/+petsird/DirectionMatrix.m deleted file mode 100644 index b67e195..0000000 --- a/matlab/+petsird/DirectionMatrix.m +++ /dev/null @@ -1,47 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef DirectionMatrix < handle - % Orthonormal matrix - % direction_of_first_axis = matrix * [1, 0 ,0] (as a column vector) - properties - matrix - end - - methods - function self = DirectionMatrix(kwargs) - arguments - kwargs.matrix = repelem(single(0), 3, 3); - end - self.matrix = kwargs.matrix; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.DirectionMatrix") && ... - isequal({self.matrix}, {other.matrix}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.DirectionMatrix(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/EventTimeBlock.m b/matlab/+petsird/EventTimeBlock.m deleted file mode 100644 index d389b7a..0000000 --- a/matlab/+petsird/EventTimeBlock.m +++ /dev/null @@ -1,64 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef EventTimeBlock < handle - properties - % start time since ExamInformation.startOfAcquisition in ms - % Note: duration is given by ScannerInformation.eventTimeBlockDuration - start - % TODO encode end time? - % list of prompts in this time block - % TODO might be better to use !array - prompt_events - % optional list of delayed coincidences in this time block - delayed_events - % optional list of triple coincidences in this time block - triple_events - end - - methods - function self = EventTimeBlock(kwargs) - arguments - kwargs.start = uint32(0); - kwargs.prompt_events = petsird.CoincidenceEvent.empty(); - kwargs.delayed_events = yardl.None; - kwargs.triple_events = yardl.None; - end - self.start = kwargs.start; - self.prompt_events = kwargs.prompt_events; - self.delayed_events = kwargs.delayed_events; - self.triple_events = kwargs.triple_events; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.EventTimeBlock") && ... - isequal({self.start}, {other.start}) && ... - isequal({self.prompt_events}, {other.prompt_events}) && ... - isequal({self.delayed_events}, {other.delayed_events}) && ... - isequal({self.triple_events}, {other.triple_events}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.EventTimeBlock(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/ExamInformation.m b/matlab/+petsird/ExamInformation.m deleted file mode 100644 index 296ab89..0000000 --- a/matlab/+petsird/ExamInformation.m +++ /dev/null @@ -1,58 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ExamInformation < handle - % Items describing the exam (incomplete) - properties - subject - institution - protocol - start_of_acquisition - end - - methods - function self = ExamInformation(kwargs) - arguments - kwargs.subject = petsird.Subject(); - kwargs.institution = petsird.Institution(); - kwargs.protocol = yardl.None; - kwargs.start_of_acquisition = yardl.None; - end - self.subject = kwargs.subject; - self.institution = kwargs.institution; - self.protocol = kwargs.protocol; - self.start_of_acquisition = kwargs.start_of_acquisition; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.ExamInformation") && ... - isequal({self.subject}, {other.subject}) && ... - isequal({self.institution}, {other.institution}) && ... - isequal({self.protocol}, {other.protocol}) && ... - isequal({self.start_of_acquisition}, {other.start_of_acquisition}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.ExamInformation(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/ExternalSignalTimeBlock.m b/matlab/+petsird/ExternalSignalTimeBlock.m deleted file mode 100644 index e8eb948..0000000 --- a/matlab/+petsird/ExternalSignalTimeBlock.m +++ /dev/null @@ -1,56 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ExternalSignalTimeBlock < handle - properties - % start time since ExamInformation.startOfAcquisition in ms - start - % refer to ExternalSignalType.id - signal_id - % Note for triggers, this field is to be ignored - signal_values - end - - methods - function self = ExternalSignalTimeBlock(kwargs) - arguments - kwargs.start = uint32(0); - kwargs.signal_id = uint32(0); - kwargs.signal_values = single.empty(); - end - self.start = kwargs.start; - self.signal_id = kwargs.signal_id; - self.signal_values = kwargs.signal_values; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.ExternalSignalTimeBlock") && ... - isequal({self.start}, {other.start}) && ... - isequal({self.signal_id}, {other.signal_id}) && ... - isequal({self.signal_values}, {other.signal_values}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.ExternalSignalTimeBlock(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/ExternalSignalType.m b/matlab/+petsird/ExternalSignalType.m deleted file mode 100644 index 801283a..0000000 --- a/matlab/+petsird/ExternalSignalType.m +++ /dev/null @@ -1,53 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ExternalSignalType < handle - properties - type - description - id - end - - methods - function self = ExternalSignalType(kwargs) - arguments - kwargs.type = petsird.ExternalSignalTypeEnum.ECG_TRACE; - kwargs.description = ""; - kwargs.id = uint32(0); - end - self.type = kwargs.type; - self.description = kwargs.description; - self.id = kwargs.id; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.ExternalSignalType") && ... - isequal({self.type}, {other.type}) && ... - isequal({self.description}, {other.description}) && ... - isequal({self.id}, {other.id}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.ExternalSignalType(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/ExternalSignalTypeEnum.m b/matlab/+petsird/ExternalSignalTypeEnum.m deleted file mode 100644 index f331e5a..0000000 --- a/matlab/+petsird/ExternalSignalTypeEnum.m +++ /dev/null @@ -1,44 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ExternalSignalTypeEnum < uint64 - methods (Static) - function v = ECG_TRACE - v = petsird.ExternalSignalTypeEnum(0); - end - function v = ECG_TRIGGER - v = petsird.ExternalSignalTypeEnum(1); - end - function v = RESP_TRACE - v = petsird.ExternalSignalTypeEnum(2); - end - function v = RESP_TRIGGER - v = petsird.ExternalSignalTypeEnum(3); - end - function v = OTHER_MOTION_SIGNAL - v = petsird.ExternalSignalTypeEnum(4); - end - function v = OTHER_MOTION_TRIGGER - v = petsird.ExternalSignalTypeEnum(5); - end - function v = EXTERNAL_SYNC - v = petsird.ExternalSignalTypeEnum(6); - end - % other options, to be listed in the future - function v = OTHER - v = petsird.ExternalSignalTypeEnum(7); - end - - function z = zeros(varargin) - elem = petsird.ExternalSignalTypeEnum(0); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/GantryMovementTimeBlock.m b/matlab/+petsird/GantryMovementTimeBlock.m deleted file mode 100644 index b453d33..0000000 --- a/matlab/+petsird/GantryMovementTimeBlock.m +++ /dev/null @@ -1,50 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef GantryMovementTimeBlock < handle - properties - % start time since ExamInformation.startOfAcquisition in ms - start - transform - end - - methods - function self = GantryMovementTimeBlock(kwargs) - arguments - kwargs.start = uint32(0); - kwargs.transform = petsird.RigidTransformation(); - end - self.start = kwargs.start; - self.transform = kwargs.transform; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.GantryMovementTimeBlock") && ... - isequal({self.start}, {other.start}) && ... - isequal({self.transform}, {other.transform}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.GantryMovementTimeBlock(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/GenericSolidVolume.m b/matlab/+petsird/GenericSolidVolume.m deleted file mode 100644 index 6532a9d..0000000 --- a/matlab/+petsird/GenericSolidVolume.m +++ /dev/null @@ -1,4 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef GenericSolidVolume < petsird.SolidVolume -end diff --git a/matlab/+petsird/GeometricShape.m b/matlab/+petsird/GeometricShape.m deleted file mode 100644 index ae20a90..0000000 --- a/matlab/+petsird/GeometricShape.m +++ /dev/null @@ -1,49 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef GeometricShape < yardl.Union - methods (Static) - function res = BoxShape(value) - res = petsird.GeometricShape(1, value); - end - - function res = AnnulusShape(value) - res = petsird.GeometricShape(2, value); - end - - function z = zeros(varargin) - elem = petsird.GeometricShape(0, yardl.None); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end - - methods - function res = isBoxShape(self) - res = self.index == 1; - end - - function res = isAnnulusShape(self) - res = self.index == 2; - end - - function eq = eq(self, other) - eq = isa(other, "petsird.GeometricShape") && all([self.index_] == [other.index_], 'all') && all([self.value] == [other.value], 'all'); - end - - function ne = ne(self, other) - ne = ~self.eq(other); - end - - function t = tag(self) - tags_ = ["BoxShape", "AnnulusShape"]; - t = tags_(self.index_); - end - end -end diff --git a/matlab/+petsird/Header.m b/matlab/+petsird/Header.m deleted file mode 100644 index fca99e7..0000000 --- a/matlab/+petsird/Header.m +++ /dev/null @@ -1,49 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef Header < handle - properties - scanner - exam - end - - methods - function self = Header(kwargs) - arguments - kwargs.scanner = petsird.ScannerInformation(); - kwargs.exam = yardl.None; - end - self.scanner = kwargs.scanner; - self.exam = kwargs.exam; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.Header") && ... - isequal({self.scanner}, {other.scanner}) && ... - isequal({self.exam}, {other.exam}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.Header(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/Institution.m b/matlab/+petsird/Institution.m deleted file mode 100644 index c81859f..0000000 --- a/matlab/+petsird/Institution.m +++ /dev/null @@ -1,49 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef Institution < handle - properties - name - address - end - - methods - function self = Institution(kwargs) - arguments - kwargs.name = ""; - kwargs.address = ""; - end - self.name = kwargs.name; - self.address = kwargs.address; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.Institution") && ... - isequal({self.name}, {other.name}) && ... - isequal({self.address}, {other.address}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.Institution(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/ModulePairEfficiencies.m b/matlab/+petsird/ModulePairEfficiencies.m deleted file mode 100644 index 2dc8aac..0000000 --- a/matlab/+petsird/ModulePairEfficiencies.m +++ /dev/null @@ -1,56 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ModulePairEfficiencies < handle - % Efficiency for two detecting elements (det_els) in a pair of modules. - % This is one component (often called "geometric") of the detection efficiency model. - % If size along energyBinIdx is 1, the effiencies are assumed to be the same for every energy bin. - properties - % Detection efficiency for a pair of detecting elements - % detElIdx1 and detElIdx2 run from 0 to the number of det_els in each module - values - % Symmetry Group Identifier (SGID) - % This should be a number between 0 and numberOfSGIDs-1 - sgid - end - - methods - function self = ModulePairEfficiencies(kwargs) - arguments - kwargs.values = single.empty(); - kwargs.sgid = uint32(0); - end - self.values = kwargs.values; - self.sgid = kwargs.sgid; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.ModulePairEfficiencies") && ... - isequal({self.values}, {other.values}) && ... - isequal({self.sgid}, {other.sgid}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.ModulePairEfficiencies(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/PETSIRDReaderBase.m b/matlab/+petsird/PETSIRDReaderBase.m deleted file mode 100644 index ac4c006..0000000 --- a/matlab/+petsird/PETSIRDReaderBase.m +++ /dev/null @@ -1,93 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -% Definition of the stream of data -classdef PETSIRDReaderBase < handle - properties (Access=protected) - state_ - end - - methods - function self = PETSIRDReaderBase() - self.state_ = 0; - end - - function close(self) - self.close_(); - if self.state_ ~= 2 - expected_method = self.state_to_method_name_(self.state_); - throw(yardl.ProtocolError("Protocol reader closed before all data was consumed. Expected call to '%s'.", expected_method)); - end - end - - % Ordinal 0 - function value = read_header(self) - if self.state_ ~= 0 - self.raise_unexpected_state_(0); - end - - value = self.read_header_(); - self.state_ = 1; - end - - % Ordinal 1 - function more = has_time_blocks(self) - if self.state_ ~= 1 - self.raise_unexpected_state_(1); - end - - more = self.has_time_blocks_(); - if ~more - self.state_ = 2; - end - end - - function value = read_time_blocks(self) - if self.state_ ~= 1 - self.raise_unexpected_state_(1); - end - - value = self.read_time_blocks_(); - end - - function copy_to(self, writer) - writer.write_header(self.read_header()); - while self.has_time_blocks() - item = self.read_time_blocks(); - writer.write_time_blocks({item}); - end - writer.end_time_blocks(); - end - end - - methods (Static) - function res = schema() - res = petsird.PETSIRDWriterBase.schema; - end - end - - methods (Abstract, Access=protected) - read_header_(self) - has_time_blocks_(self) - read_time_blocks_(self) - - close_(self) - end - - methods (Access=private) - function raise_unexpected_state_(self, actual) - actual_method = self.state_to_method_name_(actual); - expected_method = self.state_to_method_name_(self.state_); - throw(yardl.ProtocolError("Expected call to '%s' but received call to '%s'.", expected_method, actual_method)); - end - - function name = state_to_method_name_(self, state) - if state == 0 - name = "read_header"; - elseif state == 1 - name = "read_time_blocks"; - else - name = ""; - end - end - end -end diff --git a/matlab/+petsird/PETSIRDWriterBase.m b/matlab/+petsird/PETSIRDWriterBase.m deleted file mode 100644 index 1782c67..0000000 --- a/matlab/+petsird/PETSIRDWriterBase.m +++ /dev/null @@ -1,83 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -% Abstract writer for protocol PETSIRD -% Definition of the stream of data -classdef (Abstract) PETSIRDWriterBase < handle - properties (Access=protected) - state_ - end - - methods - function self = PETSIRDWriterBase() - self.state_ = 0; - end - - function close(self) - self.close_(); - if self.state_ ~= 2 - expected_method = self.state_to_method_name_(self.state_); - throw(yardl.ProtocolError("Protocol writer closed before all steps were called. Expected call to '%s'.", expected_method)); - end - end - - % Ordinal 0 - function write_header(self, value) - if self.state_ ~= 0 - self.raise_unexpected_state_(0); - end - - self.write_header_(value); - self.state_ = 1; - end - - % Ordinal 1 - function write_time_blocks(self, value) - if self.state_ ~= 1 - self.raise_unexpected_state_(1); - end - - self.write_time_blocks_(value); - end - - function end_time_blocks(self) - if self.state_ ~= 1 - self.raise_unexpected_state_(1); - end - - self.end_stream_(); - self.state_ = 2; - end - end - - methods (Static) - function res = schema() - res = string('{"protocol":{"name":"PETSIRD","sequence":[{"name":"header","type":"PETSIRD.Header"},{"name":"timeBlocks","type":{"stream":{"items":"PETSIRD.TimeBlock"}}}]},"types":[{"name":"AnnulusShape","fields":[{"name":"innerRadius","type":"float32"},{"name":"outerRadius","type":"float32"},{"name":"thickness","type":"float32"},{"name":"angularRange","type":{"vector":{"items":"float32","length":2}}}]},{"name":"Atom","fields":[{"name":"massNumber","type":"uint32"},{"name":"atomicNumber","type":"uint32"}]},{"name":"BedMovementTimeBlock","fields":[{"name":"start","type":"uint32"},{"name":"transform","type":"PETSIRD.RigidTransformation"}]},{"name":"BoxShape","fields":[{"name":"corners","type":{"vector":{"items":"PETSIRD.Coordinate","length":8}}}]},{"name":"BoxSolidVolume","type":{"name":"PETSIRD.SolidVolume","typeArguments":["PETSIRD.BoxShape"]}},{"name":"BulkMaterial","fields":[{"name":"id","type":"uint32"},{"name":"name","type":"string"},{"name":"density","type":"float32"},{"name":"atoms","type":{"vector":{"items":"PETSIRD.Atom"}}},{"name":"massFractions","type":{"vector":{"items":"float32"}}}]},{"name":"CoincidenceEvent","fields":[{"name":"detectorIds","type":{"vector":{"items":"uint32","length":2}}},{"name":"tofIdx","type":"uint32"},{"name":"energyIndices","type":{"vector":{"items":"uint32","length":2}}}]},{"name":"CoincidencePolicy","values":[{"symbol":"rejectMultiples","value":0},{"symbol":"storeMultiplesAsPairs","value":1},{"symbol":"other","value":2}]},{"name":"Coordinate","fields":[{"name":"c","type":{"array":{"items":"float32","dimensions":[{"length":3}]}}}]},{"name":"DetElEfficiencies","type":{"array":{"items":"float32","dimensions":[{"name":"detElIdx"},{"name":"energyBinIdx"}]}}},{"name":"DetectionEfficiencies","fields":[{"name":"detElEfficiencies","type":[null,"PETSIRD.DetElEfficiencies"]},{"name":"modulePairSGIDLUT","type":[null,"PETSIRD.ModulePairSGIDLUT"]},{"name":"modulePairEfficienciesVector","type":[null,"PETSIRD.ModulePairEfficienciesVector"]}]},{"name":"DetectorModule","fields":[{"name":"detectingElements","type":{"vector":{"items":"PETSIRD.ReplicatedBoxSolidVolume"}}},{"name":"detectingElementIds","type":{"vector":{"items":"uint32"}}},{"name":"nonDetectingElements","type":{"vector":{"items":"PETSIRD.ReplicatedGenericSolidVolume"}}}]},{"name":"EventTimeBlock","fields":[{"name":"start","type":"uint32"},{"name":"promptEvents","type":{"vector":{"items":"PETSIRD.CoincidenceEvent"}}},{"name":"delayedEvents","type":[null,{"vector":{"items":"PETSIRD.CoincidenceEvent"}}]},{"name":"tripleEvents","type":[null,{"vector":{"items":"PETSIRD.TripleEvent"}}]}]},{"name":"ExamInformation","fields":[{"name":"subject","type":"PETSIRD.Subject"},{"name":"institution","type":"PETSIRD.Institution"},{"name":"protocol","type":[null,"string"]},{"name":"startOfAcquisition","type":[null,"datetime"]}]},{"name":"ExternalSignalTimeBlock","fields":[{"name":"start","type":"uint32"},{"name":"signalID","type":"uint32"},{"name":"signalValues","type":{"vector":{"items":"float32"}}}]},{"name":"GantryMovementTimeBlock","fields":[{"name":"start","type":"uint32"},{"name":"transform","type":"PETSIRD.RigidTransformation"}]},{"name":"GenericSolidVolume","type":{"name":"PETSIRD.SolidVolume","typeArguments":["PETSIRD.GeometricShape"]}},{"name":"GeometricShape","type":[{"tag":"BoxShape","type":"PETSIRD.BoxShape"},{"tag":"AnnulusShape","type":"PETSIRD.AnnulusShape"}]},{"name":"Header","fields":[{"name":"scanner","type":"PETSIRD.ScannerInformation"},{"name":"exam","type":[null,"PETSIRD.ExamInformation"]}]},{"name":"Institution","fields":[{"name":"name","type":"string"},{"name":"address","type":"string"}]},{"name":"ModulePairEfficiencies","fields":[{"name":"values","type":{"array":{"items":"float32","dimensions":[{"name":"detElIdx1"},{"name":"energyBinIdx1"},{"name":"detElIdx2"},{"name":"energyBinIdx2"}]}}},{"name":"sgid","type":"uint32"}]},{"name":"ModulePairEfficienciesVector","type":{"vector":{"items":"PETSIRD.ModulePairEfficiencies"}}},{"name":"ModulePairSGIDLUT","type":{"array":{"items":"int32","dimensions":[{"name":"moduleIdx1"},{"name":"moduleIdx2"}]}}},{"name":"ReplicatedBoxSolidVolume","type":{"name":"PETSIRD.ReplicatedObject","typeArguments":["PETSIRD.BoxSolidVolume"]}},{"name":"ReplicatedDetectorModule","type":{"name":"PETSIRD.ReplicatedObject","typeArguments":["PETSIRD.DetectorModule"]}},{"name":"ReplicatedGenericSolidVolume","type":{"name":"PETSIRD.ReplicatedObject","typeArguments":["PETSIRD.GenericSolidVolume"]}},{"name":"ReplicatedObject","typeParameters":["T"],"fields":[{"name":"object","type":"T"},{"name":"transforms","type":{"vector":{"items":"PETSIRD.RigidTransformation"}}},{"name":"ids","type":{"vector":{"items":"uint32"}}}]},{"name":"RigidTransformation","fields":[{"name":"matrix","type":{"array":{"items":"float32","dimensions":[{"length":3},{"length":4}]}}}]},{"name":"ScannerGeometry","fields":[{"name":"replicatedModules","type":{"vector":{"items":"PETSIRD.ReplicatedDetectorModule"}}},{"name":"ids","type":{"vector":{"items":"uint32"}}},{"name":"nonDetectingVolumes","type":[null,{"vector":{"items":"PETSIRD.GenericSolidVolume"}}]}]},{"name":"ScannerInformation","fields":[{"name":"modelName","type":"string"},{"name":"scannerGeometry","type":"PETSIRD.ScannerGeometry"},{"name":"bulkMaterials","type":{"vector":{"items":"PETSIRD.BulkMaterial"}}},{"name":"gantryAlignment","type":[null,"PETSIRD.RigidTransformation"]},{"name":"tofBinEdges","type":{"array":{"items":"float32","dimensions":1}}},{"name":"tofResolution","type":"float32"},{"name":"energyBinEdges","type":{"array":{"items":"float32","dimensions":1}}},{"name":"energyResolutionAt511","type":"float32"},{"name":"eventTimeBlockDuration","type":"uint32"},{"name":"coincidencePolicy","type":"PETSIRD.CoincidencePolicy"},{"name":"detectionEfficiencies","type":"PETSIRD.DetectionEfficiencies"}]},{"name":"SolidVolume","typeParameters":["Shape"],"fields":[{"name":"shape","type":"Shape"},{"name":"materialId","type":"uint32"}]},{"name":"Subject","fields":[{"name":"name","type":[null,"string"]},{"name":"id","type":"string"}]},{"name":"TimeBlock","type":[{"tag":"EventTimeBlock","type":"PETSIRD.EventTimeBlock"},{"tag":"ExternalSignalTimeBlock","type":"PETSIRD.ExternalSignalTimeBlock"},{"tag":"BedMovementTimeBlock","type":"PETSIRD.BedMovementTimeBlock"},{"tag":"GantryMovementTimeBlock","type":"PETSIRD.GantryMovementTimeBlock"}]},{"name":"TripleEvent","fields":[{"name":"detectorIds","type":{"vector":{"items":"uint32","length":3}}},{"name":"tofIndices","type":{"vector":{"items":"uint32","length":2}}},{"name":"energyIndices","type":{"vector":{"items":"uint32","length":3}}}]}]}'); - end - end - - methods (Abstract, Access=protected) - write_header_(self, value) - write_time_blocks_(self, value) - - end_stream_(self) - close_(self) - end - - methods (Access=private) - function raise_unexpected_state_(self, actual) - expected_method = self.state_to_method_name_(self.state_); - actual_method = self.state_to_method_name_(actual); - throw(yardl.ProtocolError("Expected call to '%s' but received call to '%s'", expected_method, actual_method)); - end - - function name = state_to_method_name_(self, state) - if state == 0 - name = "write_header"; - elseif state == 1 - name = "write_time_blocks or end_time_blocks"; - else - name = ''; - end - end - end -end diff --git a/matlab/+petsird/ReplicatedBoxSolidVolume.m b/matlab/+petsird/ReplicatedBoxSolidVolume.m deleted file mode 100644 index 285e8e2..0000000 --- a/matlab/+petsird/ReplicatedBoxSolidVolume.m +++ /dev/null @@ -1,5 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ReplicatedBoxSolidVolume < petsird.ReplicatedObject - % A list of identical SolidVolumes at different locations -end diff --git a/matlab/+petsird/ReplicatedDetectorModule.m b/matlab/+petsird/ReplicatedDetectorModule.m deleted file mode 100644 index cdbff3e..0000000 --- a/matlab/+petsird/ReplicatedDetectorModule.m +++ /dev/null @@ -1,5 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ReplicatedDetectorModule < petsird.ReplicatedObject - % A list of identical modules at different locations -end diff --git a/matlab/+petsird/ReplicatedGenericSolidVolume.m b/matlab/+petsird/ReplicatedGenericSolidVolume.m deleted file mode 100644 index 161cd0e..0000000 --- a/matlab/+petsird/ReplicatedGenericSolidVolume.m +++ /dev/null @@ -1,5 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ReplicatedGenericSolidVolume < petsird.ReplicatedObject - % A list of identical SolidVolumes at different locations -end diff --git a/matlab/+petsird/ReplicatedObject.m b/matlab/+petsird/ReplicatedObject.m deleted file mode 100644 index 2815d97..0000000 --- a/matlab/+petsird/ReplicatedObject.m +++ /dev/null @@ -1,67 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ReplicatedObject < handle - % A list of identical objects at different locations - properties - object - % list of transforms - % constraint: length >= 1 - transforms - % list of unique ids for every replicated solid volume - % constraint: size(transforms) == size(ids) - ids - end - - methods - function self = ReplicatedObject(kwargs) - arguments - kwargs.object; - kwargs.transforms = petsird.RigidTransformation.empty(); - kwargs.ids = uint32.empty(); - end - if ~isfield(kwargs, "object") - throw(yardl.TypeError("Missing required keyword argument 'object'")) - end - self.object = kwargs.object; - self.transforms = kwargs.transforms; - self.ids = kwargs.ids; - end - - function res = number_of_objects(self) - res = length(self.transforms); - return - end - - - function res = eq(self, other) - res = ... - isa(other, "petsird.ReplicatedObject") && ... - isequal({self.object}, {other.object}) && ... - isequal({self.transforms}, {other.transforms}) && ... - isequal({self.ids}, {other.ids}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.ReplicatedObject(object=yardl.None); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/RigidTransformation.m b/matlab/+petsird/RigidTransformation.m deleted file mode 100644 index 947958c..0000000 --- a/matlab/+petsird/RigidTransformation.m +++ /dev/null @@ -1,48 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef RigidTransformation < handle - % Rigid transformation, encoded via homogenous transformation - % transformed_coord = matrix * [c, 1] (where [c,1] is a column vector) - % with `c` of type `Coordinate` - properties - matrix - end - - methods - function self = RigidTransformation(kwargs) - arguments - kwargs.matrix = repelem(single(0), 4, 3); - end - self.matrix = kwargs.matrix; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.RigidTransformation") && ... - isequal({self.matrix}, {other.matrix}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.RigidTransformation(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/ScannerGeometry.m b/matlab/+petsird/ScannerGeometry.m deleted file mode 100644 index 43d20c6..0000000 --- a/matlab/+petsird/ScannerGeometry.m +++ /dev/null @@ -1,59 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ScannerGeometry < handle - % Full definition of the geometry of the scanner, consisting of - % one of more types of modules replicated in space and (optional) other structures (e.g. side-shielding) - properties - % list of different types of replicated modules - replicated_modules - % list of unique ids for every replicated module - % constraint: size(replicated_modules) == size(ids) - ids - % shielding etc - non_detecting_volumes - end - - methods - function self = ScannerGeometry(kwargs) - arguments - kwargs.replicated_modules = petsird.ReplicatedDetectorModule.empty(); - kwargs.ids = uint32.empty(); - kwargs.non_detecting_volumes = yardl.None; - end - self.replicated_modules = kwargs.replicated_modules; - self.ids = kwargs.ids; - self.non_detecting_volumes = kwargs.non_detecting_volumes; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.ScannerGeometry") && ... - isequal({self.replicated_modules}, {other.replicated_modules}) && ... - isequal({self.ids}, {other.ids}) && ... - isequal({self.non_detecting_volumes}, {other.non_detecting_volumes}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.ScannerGeometry(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/ScannerInformation.m b/matlab/+petsird/ScannerInformation.m deleted file mode 100644 index 567bbbb..0000000 --- a/matlab/+petsird/ScannerInformation.m +++ /dev/null @@ -1,117 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef ScannerInformation < handle - properties - model_name - % Geometric information for all detector elements - % All coordinates are in the PET gantry coordinate system. - scanner_geometry - % List of materials present in the scanner geometry. The `material_id`s there will refer to the - % identifiers in this list below. - bulk_materials - % Fixed transformation to reference location for this scanner. - % This field can be used to encode alignment with the CT or MRI gantry for instance. - % The transformation should convert from the PET gantry coordinate system to the reference. - % An empty field implies the identity transformation. - gantry_alignment - % Edge information for TOF bins in mm (given as from first to last edge, so there is one more edge than the number of bins) - % 0 corresponds to the same arrival time. Negative numbers indicate that the first detector detected first. - % For instance, a coincidence event is stored as 2 detectorIds, denoting the arrival time at the first - % detector t1 and the arrival time at the second detector t2, we store (t1-t2)*c/2. - % Note: for non-TOF scanners, this defines the coincidence window - % TODO: this currently assumes equal size for each TOF bin, but some scanners "stretch" TOF bins depending on length of LOR - tof_bin_edges - % TOF resolution (as FWHM) in mm - % Scanner coincidence timing resolution (CTR) without tof-binning - tof_resolution - % Edge information for energy windows in keV (given as from first to last edge, so there is one more edge than the number of bins) - energy_bin_edges - % FWHM of photopeak for incoming gamma of 511 keV, expressed as a ratio w.r.t. 511 - energy_resolution_at_511 - % duration of each event time block in ms - event_time_block_duration - % Encode how the scanner handles multiple coincidences - coincidence_policy - % coincidence detection efficiencies - detection_efficiencies - end - - methods - function self = ScannerInformation(kwargs) - arguments - kwargs.model_name = ""; - kwargs.scanner_geometry = petsird.ScannerGeometry(); - kwargs.bulk_materials = petsird.BulkMaterial.empty(); - kwargs.gantry_alignment = yardl.None; - kwargs.tof_bin_edges = single.empty(); - kwargs.tof_resolution = single(0); - kwargs.energy_bin_edges = single.empty(); - kwargs.energy_resolution_at_511 = single(0); - kwargs.event_time_block_duration = uint32(0); - kwargs.coincidence_policy = petsird.CoincidencePolicy.REJECT_MULTIPLES; - kwargs.detection_efficiencies = petsird.DetectionEfficiencies(); - end - self.model_name = kwargs.model_name; - self.scanner_geometry = kwargs.scanner_geometry; - self.bulk_materials = kwargs.bulk_materials; - self.gantry_alignment = kwargs.gantry_alignment; - self.tof_bin_edges = kwargs.tof_bin_edges; - self.tof_resolution = kwargs.tof_resolution; - self.energy_bin_edges = kwargs.energy_bin_edges; - self.energy_resolution_at_511 = kwargs.energy_resolution_at_511; - self.event_time_block_duration = kwargs.event_time_block_duration; - self.coincidence_policy = kwargs.coincidence_policy; - self.detection_efficiencies = kwargs.detection_efficiencies; - end - - function res = number_of_tof_bins(self) - res = numel(self.tof_bin_edges) - 1; - return - end - - function res = number_of_energy_bins(self) - res = numel(self.energy_bin_edges) - 1; - return - end - - - function res = eq(self, other) - res = ... - isa(other, "petsird.ScannerInformation") && ... - isequal({self.model_name}, {other.model_name}) && ... - isequal({self.scanner_geometry}, {other.scanner_geometry}) && ... - isequal({self.bulk_materials}, {other.bulk_materials}) && ... - isequal({self.gantry_alignment}, {other.gantry_alignment}) && ... - isequal({self.tof_bin_edges}, {other.tof_bin_edges}) && ... - isequal({self.tof_resolution}, {other.tof_resolution}) && ... - isequal({self.energy_bin_edges}, {other.energy_bin_edges}) && ... - isequal({self.energy_resolution_at_511}, {other.energy_resolution_at_511}) && ... - isequal({self.event_time_block_duration}, {other.event_time_block_duration}) && ... - isequal({self.coincidence_policy}, {other.coincidence_policy}) && ... - isequal({self.detection_efficiencies}, {other.detection_efficiencies}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.ScannerInformation(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/SolidVolume.m b/matlab/+petsird/SolidVolume.m deleted file mode 100644 index bbb6179..0000000 --- a/matlab/+petsird/SolidVolume.m +++ /dev/null @@ -1,54 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef SolidVolume < handle - % A shape filled with a uniform material - properties - shape - % identifier referring to `ScannerInformation.bulkMaterials` list - material_id - end - - methods - function self = SolidVolume(kwargs) - arguments - kwargs.shape; - kwargs.material_id = uint32(0); - end - if ~isfield(kwargs, "shape") - throw(yardl.TypeError("Missing required keyword argument 'shape'")) - end - self.shape = kwargs.shape; - self.material_id = kwargs.material_id; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.SolidVolume") && ... - isequal({self.shape}, {other.shape}) && ... - isequal({self.material_id}, {other.material_id}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.SolidVolume(shape=yardl.None); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/Subject.m b/matlab/+petsird/Subject.m deleted file mode 100644 index 07c8271..0000000 --- a/matlab/+petsird/Subject.m +++ /dev/null @@ -1,49 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef Subject < handle - properties - name - id - end - - methods - function self = Subject(kwargs) - arguments - kwargs.name = yardl.None; - kwargs.id = ""; - end - self.name = kwargs.name; - self.id = kwargs.id; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.Subject") && ... - isequal({self.name}, {other.name}) && ... - isequal({self.id}, {other.id}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.Subject(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/TimeBlock.m b/matlab/+petsird/TimeBlock.m deleted file mode 100644 index e00300f..0000000 --- a/matlab/+petsird/TimeBlock.m +++ /dev/null @@ -1,65 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef TimeBlock < yardl.Union - methods (Static) - function res = EventTimeBlock(value) - res = petsird.TimeBlock(1, value); - end - - function res = ExternalSignalTimeBlock(value) - res = petsird.TimeBlock(2, value); - end - - function res = BedMovementTimeBlock(value) - res = petsird.TimeBlock(3, value); - end - - function res = GantryMovementTimeBlock(value) - res = petsird.TimeBlock(4, value); - end - - function z = zeros(varargin) - elem = petsird.TimeBlock(0, yardl.None); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end - - methods - function res = isEventTimeBlock(self) - res = self.index == 1; - end - - function res = isExternalSignalTimeBlock(self) - res = self.index == 2; - end - - function res = isBedMovementTimeBlock(self) - res = self.index == 3; - end - - function res = isGantryMovementTimeBlock(self) - res = self.index == 4; - end - - function eq = eq(self, other) - eq = isa(other, "petsird.TimeBlock") && all([self.index_] == [other.index_], 'all') && all([self.value] == [other.value], 'all'); - end - - function ne = ne(self, other) - ne = ~self.eq(other); - end - - function t = tag(self) - tags_ = ["EventTimeBlock", "ExternalSignalTimeBlock", "BedMovementTimeBlock", "GantryMovementTimeBlock"]; - t = tags_(self.index_); - end - end -end diff --git a/matlab/+petsird/TimeFrameInformation.m b/matlab/+petsird/TimeFrameInformation.m deleted file mode 100644 index 1619b43..0000000 --- a/matlab/+petsird/TimeFrameInformation.m +++ /dev/null @@ -1,52 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef TimeFrameInformation < handle - % A sequence of time intervals (could be consecutive) - properties - time_frames - end - - methods - function self = TimeFrameInformation(kwargs) - arguments - kwargs.time_frames = petsird.TimeInterval.empty(); - end - self.time_frames = kwargs.time_frames; - end - - function res = number_of_time_frames(self) - res = length(self.time_frames); - return - end - - - function res = eq(self, other) - res = ... - isa(other, "petsird.TimeFrameInformation") && ... - isequal({self.time_frames}, {other.time_frames}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.TimeFrameInformation(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/TimeInterval.m b/matlab/+petsird/TimeInterval.m deleted file mode 100644 index 130cfe0..0000000 --- a/matlab/+petsird/TimeInterval.m +++ /dev/null @@ -1,50 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef TimeInterval < handle - % Time interval in milliseconds since start of acquisition - properties - start - stop - end - - methods - function self = TimeInterval(kwargs) - arguments - kwargs.start = uint32(0); - kwargs.stop = uint32(0); - end - self.start = kwargs.start; - self.stop = kwargs.stop; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.TimeInterval") && ... - isequal({self.start}, {other.start}) && ... - isequal({self.stop}, {other.stop}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.TimeInterval(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+petsird/TripleEvent.m b/matlab/+petsird/TripleEvent.m deleted file mode 100644 index 518d24a..0000000 --- a/matlab/+petsird/TripleEvent.m +++ /dev/null @@ -1,59 +0,0 @@ -% This file was generated by the "yardl" tool. DO NOT EDIT. - -classdef TripleEvent < handle - % All information about a triple event specified as identifiers or indices (i.e. discretized). - properties - detector_ids - % timing differences (converted to mm) w.r.t. first event, stored as - % indices into the tofBinEdges field in the ScannerInformation - % Note: only 2, corresponding to the arrival time differences of the second and third detectorId - % listed w.r.t. the first detectorId - tof_indices - % indices for each single event into the energyBinEdges field in the ScannerInformation - energy_indices - end - - methods - function self = TripleEvent(kwargs) - arguments - kwargs.detector_ids = repelem(uint32(0), 3); - kwargs.tof_indices = repelem(uint32(0), 2); - kwargs.energy_indices = repelem(uint32(0), 3); - end - self.detector_ids = kwargs.detector_ids; - self.tof_indices = kwargs.tof_indices; - self.energy_indices = kwargs.energy_indices; - end - - function res = eq(self, other) - res = ... - isa(other, "petsird.TripleEvent") && ... - isequal({self.detector_ids}, {other.detector_ids}) && ... - isequal({self.tof_indices}, {other.tof_indices}) && ... - isequal({self.energy_indices}, {other.energy_indices}); - end - - function res = ne(self, other) - res = ~self.eq(other); - end - - function res = isequal(self, other) - res = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = petsird.TripleEvent(); - if nargin == 0 - z = elem; - return; - end - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+yardl/+binary/BinaryProtocolReader.m b/matlab/+yardl/+binary/BinaryProtocolReader.m deleted file mode 100644 index 1180269..0000000 --- a/matlab/+yardl/+binary/BinaryProtocolReader.m +++ /dev/null @@ -1,40 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef BinaryProtocolReader < handle - - properties (Access=protected) - stream_ - end - - methods - function self = BinaryProtocolReader(infile, expected_schema) - self.stream_ = yardl.binary.CodedInputStream(infile); - magic_bytes = self.stream_.read_bytes(length(yardl.binary.MAGIC_BYTES)); - if magic_bytes ~= yardl.binary.MAGIC_BYTES - throw(yardl.ProtocolError("Invalid magic bytes")); - end - - version = read_fixed_int32(self.stream_); - if version ~= yardl.binary.CURRENT_BINARY_FORMAT_VERSION - throw(yardl.ProtocolError("Invalid binary format version")); - end - - s = yardl.binary.StringSerializer(); - schema = s.read(self.stream_); - if ~isempty(expected_schema) & schema ~= expected_schema - throw(yardl.ProtocolError("Invalid schema")); - end - end - end - - methods (Access=protected) - function close_(self) - self.stream_.close(); - end - end -end - -function res = read_fixed_int32(stream) - res = typecast(stream.read_bytes(4), "int32"); -end diff --git a/matlab/+yardl/+binary/BinaryProtocolWriter.m b/matlab/+yardl/+binary/BinaryProtocolWriter.m deleted file mode 100644 index 4a5378a..0000000 --- a/matlab/+yardl/+binary/BinaryProtocolWriter.m +++ /dev/null @@ -1,37 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef BinaryProtocolWriter < handle - - properties (Access=protected) - stream_ - end - - methods - function self = BinaryProtocolWriter(outfile, schema) - self.stream_ = yardl.binary.CodedOutputStream(outfile); - self.stream_.write_bytes(yardl.binary.MAGIC_BYTES); - write_fixed_int32(self.stream_, yardl.binary.CURRENT_BINARY_FORMAT_VERSION); - s = yardl.binary.StringSerializer(); - s.write(self.stream_, schema); - end - end - - methods (Access=protected) - function end_stream_(self) - self.stream_.write_byte(uint8(0)); - end - - function close_(self) - self.stream_.close(); - end - end -end - -function write_fixed_int32(stream, value) - arguments - stream (1,1) yardl.binary.CodedOutputStream - value (1,1) {mustBeA(value, "int32")} - end - stream.write_bytes(typecast(value, "uint8")); -end diff --git a/matlab/+yardl/+binary/BoolSerializer.m b/matlab/+yardl/+binary/BoolSerializer.m deleted file mode 100644 index 8311273..0000000 --- a/matlab/+yardl/+binary/BoolSerializer.m +++ /dev/null @@ -1,28 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef BoolSerializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - arguments - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) {mustBeInRange(value, 0, 1)} - end - byte = cast(value, "uint8"); - outstream.write_bytes(byte); - end - - function res = read(instream) - byte = instream.read_byte(); - res = cast(byte, "logical"); - end - - function c = get_class() - c = "logical"; - end - - function trivial = is_trivially_serializable() - trivial = true; - end - end -end diff --git a/matlab/+yardl/+binary/CURRENT_BINARY_FORMAT_VERSION.m b/matlab/+yardl/+binary/CURRENT_BINARY_FORMAT_VERSION.m deleted file mode 100644 index 2fcacad..0000000 --- a/matlab/+yardl/+binary/CURRENT_BINARY_FORMAT_VERSION.m +++ /dev/null @@ -1,6 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -function res = CURRENT_BINARY_FORMAT_VERSION - res = int32(1); -end diff --git a/matlab/+yardl/+binary/CodedInputStream.m b/matlab/+yardl/+binary/CodedInputStream.m deleted file mode 100644 index 34e03ca..0000000 --- a/matlab/+yardl/+binary/CodedInputStream.m +++ /dev/null @@ -1,74 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef CodedInputStream < handle - - properties (Access=private) - fid_ - owns_stream_ - end - - methods - function self = CodedInputStream(infile) - if isa(infile, "string") || isa(infile, "char") - [fileId, errMsg] = fopen(infile, "r"); - if fileId < 0 - throw(yardl.RuntimeError(errMsg)); - end - self.fid_ = fileId; - self.owns_stream_ = true; - else - self.fid_ = infile; - self.owns_stream_ = false; - end - end - - function close(self) - if self.owns_stream_ && self.fid_ > 2 - fclose(self.fid_); - self.fid_ = -1; - end - end - - function res = read_bytes(self, count) - res = fread(self.fid_, count, "*uint8"); - if iscolumn(res) - res = transpose(res); - end - end - - function res = read_byte(self) - res = fread(self.fid_, 1, "*uint8"); - end - - function res = read_values_directly(self, shape, precision) - res = fread(self.fid_, shape, "*"+precision); - if iscolumn(res) - res = transpose(res); - end - end - - function res = read_unsigned_varint(self) - res = uint64(0); - shift = uint8(0); - - while true - byte = self.read_byte(); - res = bitor(res, bitshift(uint64(bitand(byte, 0x7F)), shift)); - if byte < 0x80 - return - end - shift = shift + 7; - end - end - - function res = zigzag_decode(~, value) - value = uint64(value); - res = bitxor(int64(bitshift(value, -1)), -int64(bitand(value, 1))); - end - - function res = read_signed_varint(self) - res = self.zigzag_decode(self.read_unsigned_varint()); - end - end -end diff --git a/matlab/+yardl/+binary/CodedOutputStream.m b/matlab/+yardl/+binary/CodedOutputStream.m deleted file mode 100644 index c2aedf3..0000000 --- a/matlab/+yardl/+binary/CodedOutputStream.m +++ /dev/null @@ -1,84 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef CodedOutputStream < handle - - properties (Access=private) - fid_ - owns_stream_ - end - - methods - function self = CodedOutputStream(outfile) - if isa(outfile, "string") || isa(outfile, "char") - [fileId, errMsg] = fopen(outfile, "W"); - if fileId < 0 - throw(yardl.RuntimeError(errMsg)); - end - self.fid_ = fileId; - self.owns_stream_ = true; - else - self.fid_ = outfile; - self.owns_stream_ = false; - end - end - - function close(self) - if self.owns_stream_ && self.fid_ > 2 - fclose(self.fid_); - self.fid_ = -1; - end - end - - function write_bytes(self, bytes) - arguments - self - bytes (1,:) {mustBeA(bytes, "uint8")} - end - fwrite(self.fid_, bytes, "uint8"); - end - - function write_byte(self, value) - arguments - self - value (1,1) {mustBeA(value, "uint8")} - end - fwrite(self.fid_, value, "uint8"); - end - - function write_values_directly(self, values, precision) - fwrite(self.fid_, values, precision); - end - - function write_unsigned_varint(self, value) - arguments - self - value (1,1) {mustBeInteger,mustBeNonnegative} - end - - int_val = uint64(value); - while true - if int_val < 0x80 - self.write_byte(uint8(int_val)); - return - end - - self.write_byte(uint8(bitor(bitand(int_val, uint64(0x7F)), uint64(0x80)))); - int_val = bitshift(int_val, -7); - end - end - - function res = zigzag_encode(~, value) - int_val = int64(value); - res = bitxor(bitshift(int_val, 1), bitshift(int_val, -63)); - end - - function write_signed_varint(self, value) - arguments - self - value (1,1) {mustBeInteger} - end - self.write_unsigned_varint(self.zigzag_encode(value)); - end - end -end diff --git a/matlab/+yardl/+binary/Complexfloat32Serializer.m b/matlab/+yardl/+binary/Complexfloat32Serializer.m deleted file mode 100644 index 041edb8..0000000 --- a/matlab/+yardl/+binary/Complexfloat32Serializer.m +++ /dev/null @@ -1,49 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Complexfloat32Serializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - arguments - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) single - end - real_bytes = typecast(single(real(value)), "uint8"); - imag_bytes = typecast(single(imag(value)), "uint8"); - outstream.write_bytes(real_bytes); - outstream.write_bytes(imag_bytes); - end - - function res = read(instream) - real_bytes = instream.read_bytes(4); - imag_bytes = instream.read_bytes(4); - res = complex(typecast(real_bytes, "single"), typecast(imag_bytes, "single")); - end - - function c = get_class() - c = "single"; - end - - function trivial = is_trivially_serializable() - trivial = true; - end - end - - methods - function write_trivially(self, stream, values) - rp = real(values); - ip = imag(values); - parts(1, :) = rp(:); - parts(2, :) = ip(:); - stream.write_values_directly(parts, self.get_class()); - end - - function res = read_trivially(self, stream, shape) - assert(ndims(shape) == 2); - partshape = [2*shape(1) shape(2)]; - res = stream.read_values_directly(partshape, self.get_class()); - res = reshape(res, [2 shape]); - res = squeeze(complex(res(1, :, :), res(2, :, :))); - end - end -end diff --git a/matlab/+yardl/+binary/Complexfloat64Serializer.m b/matlab/+yardl/+binary/Complexfloat64Serializer.m deleted file mode 100644 index 5f6fba6..0000000 --- a/matlab/+yardl/+binary/Complexfloat64Serializer.m +++ /dev/null @@ -1,49 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Complexfloat64Serializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - arguments - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) double - end - real_bytes = typecast(double(real(value)), "uint8"); - imag_bytes = typecast(double(imag(value)), "uint8"); - outstream.write_bytes(real_bytes); - outstream.write_bytes(imag_bytes); - end - - function res = read(instream) - real_bytes = instream.read_bytes(8); - imag_bytes = instream.read_bytes(8); - res = complex(typecast(real_bytes, "double"), typecast(imag_bytes, "double")); - end - - function c = get_class() - c = "double"; - end - - function trivial = is_trivially_serializable() - trivial = true; - end - end - - methods - function write_trivially(self, stream, values) - rp = real(values); - ip = imag(values); - parts(1, :) = rp(:); - parts(2, :) = ip(:); - stream.write_values_directly(parts, self.get_class()); - end - - function res = read_trivially(self, stream, shape) - assert(ndims(shape) == 2); - partshape = [2*shape(1) shape(2)]; - res = stream.read_values_directly(partshape, self.get_class()); - res = reshape(res, [2 shape]); - res = squeeze(complex(res(1, :, :), res(2, :, :))); - end - end -end diff --git a/matlab/+yardl/+binary/DateSerializer.m b/matlab/+yardl/+binary/DateSerializer.m deleted file mode 100644 index 20f78c3..0000000 --- a/matlab/+yardl/+binary/DateSerializer.m +++ /dev/null @@ -1,26 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef DateSerializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - if isa(value, "datetime") - value = yardl.Date.from_datetime(value).value; - elseif isa(value, "yardl.Date") - value = value.value; - else - throw(yardl.TypeError("Expected datetime or yardl.Date, got %s", class(value))); - end - outstream.write_signed_varint(value); - end - - function res = read(instream) - value = instream.read_signed_varint(); - res = yardl.Date(value); - end - - function c = get_class() - c = "yardl.Date"; - end - end -end diff --git a/matlab/+yardl/+binary/DatetimeSerializer.m b/matlab/+yardl/+binary/DatetimeSerializer.m deleted file mode 100644 index 07f813b..0000000 --- a/matlab/+yardl/+binary/DatetimeSerializer.m +++ /dev/null @@ -1,26 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef DatetimeSerializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - if isa(value, "datetime") - value = yardl.DateTime.from_datetime(value).value; - elseif isa(value, "yardl.DateTime") - value = value.value; - else - throw(yardl.TypeError("Expected datetime or yardl.DateTime, got %s", class(value))); - end - outstream.write_signed_varint(value); - end - - function res = read(instream) - value = instream.read_signed_varint(); - res = yardl.DateTime(value); - end - - function c = get_class() - c = "yardl.DateTime"; - end - end -end diff --git a/matlab/+yardl/+binary/DynamicNDArraySerializer.m b/matlab/+yardl/+binary/DynamicNDArraySerializer.m deleted file mode 100644 index 4f7f8c5..0000000 --- a/matlab/+yardl/+binary/DynamicNDArraySerializer.m +++ /dev/null @@ -1,47 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef DynamicNDArraySerializer < yardl.binary.NDArraySerializerBase - - methods - function self = DynamicNDArraySerializer(item_serializer) - self@yardl.binary.NDArraySerializerBase(item_serializer); - end - - function write(self, outstream, values) - item_shape = self.item_serializer_.get_shape(); - shape = size(values); - if isempty(item_shape) - % values is an array of variable-length vectors or arrays - values = values(:); - elseif isscalar(item_shape) - % values is an array of scalars - values = values(:); - else - % values is an array of fixed-length vectors or arrays - item_shape = item_shape(item_shape > 1); - outer_shape = shape(length(item_shape) + 1:end); - values = reshape(values, [item_shape prod(outer_shape)]); - shape = outer_shape; - end - - outstream.write_unsigned_varint(length(shape)); - flipped_shape = flip(shape); - for dim = 1:length(flipped_shape) - outstream.write_unsigned_varint(flipped_shape(dim)); - end - - self.write_data_(outstream, values); - end - - function value = read(self, instream) - ndims = instream.read_unsigned_varint(); - flipped_shape = zeros(1, ndims); - for dim = 1:ndims - flipped_shape(dim) = instream.read_unsigned_varint(); - end - shape = flip(flipped_shape); - value = self.read_data_(instream, shape); - end - end -end diff --git a/matlab/+yardl/+binary/EnumSerializer.m b/matlab/+yardl/+binary/EnumSerializer.m deleted file mode 100644 index 307eeb9..0000000 --- a/matlab/+yardl/+binary/EnumSerializer.m +++ /dev/null @@ -1,43 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef EnumSerializer < yardl.binary.TypeSerializer - properties - classname_; - constructor_; - integer_serializer_; - end - - methods - function self = EnumSerializer(classname, classconstructor, integer_serializer) - self.classname_ = classname; - self.constructor_ = classconstructor; - self.integer_serializer_ = integer_serializer; - end - - function write(self, outstream, value) - self.integer_serializer_.write(outstream, value); - end - - function res = read(self, instream) - int_value = self.integer_serializer_.read(instream); - res = self.constructor_(int_value); - end - - function c = get_class(self) - c = self.classname_; - end - - function trivial = is_trivially_serializable(self) - trivial = self.integer_serializer_.is_trivially_serializable(); - end - - function write_trivially(self, outstream, values) - self.integer_serializer_.write_trivially(outstream, values); - end - - function res = read_trivially(self, instream, shape) - res = self.integer_serializer_.read_trivially(instream, shape); - end - end -end diff --git a/matlab/+yardl/+binary/FixedNDArraySerializer.m b/matlab/+yardl/+binary/FixedNDArraySerializer.m deleted file mode 100644 index 58871f4..0000000 --- a/matlab/+yardl/+binary/FixedNDArraySerializer.m +++ /dev/null @@ -1,72 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef FixedNDArraySerializer < yardl.binary.NDArraySerializerBase - - properties - shape_ - end - - methods - function self = FixedNDArraySerializer(item_serializer, shape) - self@yardl.binary.NDArraySerializerBase(item_serializer); - self.shape_ = shape; - end - - function write(self, outstream, values) - if numel(values) == prod(self.shape_) - % This is an NDArray of scalars - self.write_data_(outstream, values(:)); - return; - end - - sz = size(values); - if length(sz) < length(self.shape_) - expected = sprintf("%d ", self.shape_); - actual = sprintf("%d ", sz); - throw(yardl.ValueError("Expected shape [%s], got [%s]", expected, actual)); - end - - fixedSize = sz(end-length(self.shape_)+1:end); - if fixedSize ~= self.shape_ - expected = sprintf("%d ", self.shape_); - actual = sprintf("%d ", fixedSize); - throw(yardl.ValueError("Expected shape [%s], got [%s]", expected, actual)); - end - - inner_shape = sz(1:end-length(self.shape_)); - values = reshape(values, [inner_shape prod(self.shape_)]); - - self.write_data_(outstream, values); - end - - function value = read(self, instream) - value = self.read_data_(instream, self.shape_); - end - - function s = get_shape(self) - item_shape = self.item_serializer_.get_shape(); - if isempty(item_shape) - s = self.shape_; - else - s = [item_shape self.shape_]; - end - - if length(s) > 2 - s = s(s>1); - end - end - - function trivial = is_trivially_serializable(self) - trivial = self.item_serializer_.is_trivially_serializable(); - end - - function write_trivially(self, outstream, values) - self.item_serializer_.write_trivially(outstream, values); - end - - function res = read_trivially(self, instream, shape) - res = self.item_serializer_.read_trivially(instream, shape); - end - end -end diff --git a/matlab/+yardl/+binary/FixedVectorSerializer.m b/matlab/+yardl/+binary/FixedVectorSerializer.m deleted file mode 100644 index 35dafc2..0000000 --- a/matlab/+yardl/+binary/FixedVectorSerializer.m +++ /dev/null @@ -1,51 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef FixedVectorSerializer < yardl.binary.VectorSerializerBase - properties - length_; - end - - methods (Access=protected) - function handle_write_count_(self, ~, count) - if count ~= self.length_ - throw(yardl.ValueError("Expected an array of length %d, got %d", self.length_, count)); - end - end - - function count = get_read_count_(self, ~) - count = self.length_; - end - end - - methods - function self = FixedVectorSerializer(item_serializer, length) - self@yardl.binary.VectorSerializerBase(item_serializer); - self.length_ = length; - end - - function s = get_shape(self) - item_shape = self.item_serializer_.get_shape(); - if isempty(item_shape) - s = [1, self.length_]; - elseif isscalar(item_shape) - s = [item_shape self.length_]; - else - s = [item_shape self.length_]; - s = s(s>1); - end - end - - function trivial = is_trivially_serializable(self) - trivial = self.item_serializer_.is_trivially_serializable(); - end - - function write_trivially(self, outstream, values) - self.item_serializer_.write_trivially(outstream, values); - end - - function res = read_trivially(self, instream, shape) - res = self.item_serializer_.read_trivially(instream, shape); - end - end -end diff --git a/matlab/+yardl/+binary/Float32Serializer.m b/matlab/+yardl/+binary/Float32Serializer.m deleted file mode 100644 index 021e623..0000000 --- a/matlab/+yardl/+binary/Float32Serializer.m +++ /dev/null @@ -1,29 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Float32Serializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - arguments - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) single - end - - bytes = typecast(single(value), "uint8"); - outstream.write_bytes(bytes); - end - - function res = read(instream) - bytes = instream.read_bytes(4); - res = typecast(bytes, "single"); - end - - function c = get_class() - c = "single"; - end - - function trivial = is_trivially_serializable() - trivial = true; - end - end -end diff --git a/matlab/+yardl/+binary/Float64Serializer.m b/matlab/+yardl/+binary/Float64Serializer.m deleted file mode 100644 index 4f58367..0000000 --- a/matlab/+yardl/+binary/Float64Serializer.m +++ /dev/null @@ -1,28 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Float64Serializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - arguments - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) double - end - bytes = typecast(double(value), "uint8"); - outstream.write_bytes(bytes); - end - - function res = read(instream) - bytes = instream.read_bytes(8); - res = typecast(bytes, "double"); - end - - function c = get_class() - c = "double"; - end - - function trivial = is_trivially_serializable() - trivial = true; - end - end -end diff --git a/matlab/+yardl/+binary/Int16Serializer.m b/matlab/+yardl/+binary/Int16Serializer.m deleted file mode 100644 index 8f140d8..0000000 --- a/matlab/+yardl/+binary/Int16Serializer.m +++ /dev/null @@ -1,22 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Int16Serializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - arguments - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) {mustBeInRange(value, -32768, 32767)} - end - outstream.write_signed_varint(value); - end - - function res = read(instream) - res = int16(instream.read_signed_varint()); - end - - function c = get_class() - c = "int16"; - end - end -end diff --git a/matlab/+yardl/+binary/Int32Serializer.m b/matlab/+yardl/+binary/Int32Serializer.m deleted file mode 100644 index 20fc3d3..0000000 --- a/matlab/+yardl/+binary/Int32Serializer.m +++ /dev/null @@ -1,22 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Int32Serializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - arguments - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) {mustBeInRange(value, -2147483648, 2147483647)} - end - outstream.write_signed_varint(value); - end - - function res = read(instream) - res = int32(instream.read_signed_varint()); - end - - function c = get_class() - c = "int32"; - end - end -end diff --git a/matlab/+yardl/+binary/Int64Serializer.m b/matlab/+yardl/+binary/Int64Serializer.m deleted file mode 100644 index 2176a93..0000000 --- a/matlab/+yardl/+binary/Int64Serializer.m +++ /dev/null @@ -1,22 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Int64Serializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - arguments - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) {mustBeInRange(value, -9223372036854775808, 9223372036854775807)} - end - outstream.write_signed_varint(value); - end - - function res = read(instream) - res = int64(instream.read_signed_varint()); - end - - function c = get_class() - c = "int64"; - end - end -end diff --git a/matlab/+yardl/+binary/Int8Serializer.m b/matlab/+yardl/+binary/Int8Serializer.m deleted file mode 100644 index ecf037c..0000000 --- a/matlab/+yardl/+binary/Int8Serializer.m +++ /dev/null @@ -1,27 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Int8Serializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - arguments - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) {mustBeInRange(value, -128, 127)} - end - byte = typecast(int8(value), "uint8"); - outstream.write_byte(byte); - end - - function res = read(instream) - res = typecast(instream.read_byte(), "int8"); - end - - function c = get_class() - c = "int8"; - end - - function trivial = is_trivially_serializable() - trivial = true; - end - end -end diff --git a/matlab/+yardl/+binary/MAGIC_BYTES.m b/matlab/+yardl/+binary/MAGIC_BYTES.m deleted file mode 100644 index 4391975..0000000 --- a/matlab/+yardl/+binary/MAGIC_BYTES.m +++ /dev/null @@ -1,6 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -function res = MAGIC_BYTES - res = unicode2native('yardl'); -end diff --git a/matlab/+yardl/+binary/MapSerializer.m b/matlab/+yardl/+binary/MapSerializer.m deleted file mode 100644 index e8dfcec..0000000 --- a/matlab/+yardl/+binary/MapSerializer.m +++ /dev/null @@ -1,51 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef MapSerializer < yardl.binary.TypeSerializer - properties - key_serializer_; - value_serializer_; - end - - methods - function self = MapSerializer(key_serializer, value_serializer) - self.key_serializer_ = key_serializer; - self.value_serializer_ = value_serializer; - end - - function write(self, outstream, value) - arguments - self (1,1) - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) yardl.Map - end - - count = numEntries(value); - outstream.write_unsigned_varint(count); - if count == 0 - return - end - - ks = keys(value); - vs = values(value); - for i = 1:count - self.key_serializer_.write(outstream, ks(i)); - self.value_serializer_.write(outstream, vs(i)); - end - end - - function res = read(self, instream) - count = instream.read_unsigned_varint(); - res = yardl.Map(); - for i = 1:count - k = self.key_serializer_.read(instream); - v = self.value_serializer_.read(instream); - insert(res, k, v); - end - end - - function c = get_class(~) - c = "yardl.Map"; - end - end -end diff --git a/matlab/+yardl/+binary/NDArraySerializer.m b/matlab/+yardl/+binary/NDArraySerializer.m deleted file mode 100644 index cde6434..0000000 --- a/matlab/+yardl/+binary/NDArraySerializer.m +++ /dev/null @@ -1,51 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef NDArraySerializer < yardl.binary.NDArraySerializerBase - - properties - ndims_ - end - - methods - function self = NDArraySerializer(item_serializer, ndims) - self@yardl.binary.NDArraySerializerBase(item_serializer); - self.ndims_ = ndims; - end - - function write(self, outstream, values) - sz = size(values); - if ndims(values) < self.ndims_ - sz = [sz ones(1, self.ndims_-ndims(values))]; - end - - flipped_shape = flip(sz); - for dim = 1:self.ndims_ - len = flipped_shape(dim); - outstream.write_unsigned_varint(len); - end - - if length(sz) == self.ndims_ - % This is an NDArray of scalars - self.write_data_(outstream, values(:)); - return - end - - % This is an NDArray of vectors/arrays - inner_shape = sz(1:end-self.ndims_); - outer_shape = sz(end-self.ndims_+1:end); - values = reshape(values, [inner_shape prod(outer_shape)]); - - self.write_data_(outstream, values); - end - - function value = read(self, instream) - flipped_shape = zeros(1, self.ndims_); - for dim = 1:self.ndims_ - flipped_shape(dim) = instream.read_unsigned_varint(); - end - shape = flip(flipped_shape); - value = self.read_data_(instream, shape); - end - end -end diff --git a/matlab/+yardl/+binary/NDArraySerializerBase.m b/matlab/+yardl/+binary/NDArraySerializerBase.m deleted file mode 100644 index 12cf775..0000000 --- a/matlab/+yardl/+binary/NDArraySerializerBase.m +++ /dev/null @@ -1,106 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef NDArraySerializerBase < yardl.binary.TypeSerializer - - properties - item_serializer_ - end - - methods (Abstract) - write(self, outstream, values) - read(self, instream) - end - - methods (Access=protected) - function self = NDArraySerializerBase(item_serializer) - self.item_serializer_ = item_serializer; - end - - function write_data_(self, outstream, values) - % values is an array of shape [A, B, ..., N], where - % N is the "flattened" dimension of the NDArray, and - % A, B, ... are the dimensions of the inner items. - - if ~iscell(values) && self.item_serializer_.is_trivially_serializable() - self.item_serializer_.write_trivially(outstream, values); - return; - end - - sz = size(values); - - if ndims(values) > 2 - count = sz(end); - inner_shape = sz(1:end-1); - r = reshape(values, [], count); - for i = 1:count - val = reshape(r(:, i), inner_shape); - self.item_serializer_.write(outstream, val); - end - elseif isrow(values) || iscolumn(values) - count = prod(sz); - if iscell(values) - for i = 1:count - self.item_serializer_.write(outstream, values{i}); - end - else - for i = 1:count - self.item_serializer_.write(outstream, values(i)); - end - end - else - count = sz(end); - for i = 1:count - self.item_serializer_.write(outstream, values(:, i)); - end - end - end - - function res = read_data_(self, instream, shape) - flat_length = prod(shape); - - item_shape = self.item_serializer_.get_shape(); - - if isempty(item_shape) - res = cell(shape); - for i = 1:flat_length - res{i} = self.item_serializer_.read(instream); - end - return - end - - if self.item_serializer_.is_trivially_serializable() - res = self.item_serializer_.read_trivially(instream, [prod(item_shape), flat_length]); - else - res = yardl.allocate(self.get_class(), [prod(item_shape), flat_length]); - for i = 1:flat_length - item = self.item_serializer_.read(instream); - res(:, i) = item(:); - end - end - - % Tricky reshaping to remove unnecessary singleton dimensions in - % subarrays, arrays of fixed vectors, etc. - item_shape = item_shape(item_shape > 1); - if isempty(item_shape) && isscalar(shape) - item_shape = 1; - end - newshape = [item_shape shape]; - res = reshape(res, newshape); - - if iscolumn(res) - res = transpose(res); - end - end - end - - methods - function c = get_class(self) - c = self.item_serializer_.get_class(); - end - - function s = get_shape(~) - s = []; - end - end -end diff --git a/matlab/+yardl/+binary/NoneSerializer.m b/matlab/+yardl/+binary/NoneSerializer.m deleted file mode 100644 index 9986594..0000000 --- a/matlab/+yardl/+binary/NoneSerializer.m +++ /dev/null @@ -1,17 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef NoneSerializer < yardl.binary.TypeSerializer - methods (Static) - function write(~, ~) - end - - function res = read(~) - res = yardl.None; - end - - function c = get_class() - c = "yardl.Optional"; - end - end -end diff --git a/matlab/+yardl/+binary/OptionalSerializer.m b/matlab/+yardl/+binary/OptionalSerializer.m deleted file mode 100644 index a4f7960..0000000 --- a/matlab/+yardl/+binary/OptionalSerializer.m +++ /dev/null @@ -1,43 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef OptionalSerializer < yardl.binary.TypeSerializer - properties - item_serializer_; - end - - methods - function self = OptionalSerializer(item_serializer) - self.item_serializer_ = item_serializer; - end - - function write(self, outstream, value) - if isa(value, "yardl.Optional") - if value.has_value() - outstream.write_byte(uint8(1)); - self.item_serializer_.write(outstream, value.value()); - else - outstream.write_byte(uint8(0)); - return - end - else - outstream.write_byte(uint8(1)); - self.item_serializer_.write(outstream, value); - end - end - - function res = read(self, instream) - % Returns either yardl.None or the inner optional value - has_value = instream.read_byte(); - if has_value == 0 - res = yardl.None; - else - res = self.item_serializer_.read(instream); - end - end - - function c = get_class(~) - c = "yardl.Optional"; - end - end -end diff --git a/matlab/+yardl/+binary/RecordSerializer.m b/matlab/+yardl/+binary/RecordSerializer.m deleted file mode 100644 index d6a2fb5..0000000 --- a/matlab/+yardl/+binary/RecordSerializer.m +++ /dev/null @@ -1,39 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef RecordSerializer < yardl.binary.TypeSerializer - - properties - field_serializers - classname - end - - methods - function self = RecordSerializer(classname, field_serializers) - self.classname = classname; - self.field_serializers = field_serializers; - end - - function c = get_class(self) - c = self.classname; - end - end - - methods (Access=protected) - function write_(self, outstream, varargin) - for i = 1:nargin-2 - fs = self.field_serializers{i}; - field_value = varargin{i}; - fs.write(outstream, field_value); - end - end - - function res = read_(self, instream) - res = cell(size(self.field_serializers)); - for i = 1:length(self.field_serializers) - fs = self.field_serializers{i}; - res{i} = fs.read(instream); - end - end - end -end diff --git a/matlab/+yardl/+binary/SizeSerializer.m b/matlab/+yardl/+binary/SizeSerializer.m deleted file mode 100644 index a613e23..0000000 --- a/matlab/+yardl/+binary/SizeSerializer.m +++ /dev/null @@ -1,5 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef SizeSerializer < yardl.binary.Uint64Serializer -end diff --git a/matlab/+yardl/+binary/StreamSerializer.m b/matlab/+yardl/+binary/StreamSerializer.m deleted file mode 100644 index 233bf2b..0000000 --- a/matlab/+yardl/+binary/StreamSerializer.m +++ /dev/null @@ -1,79 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef StreamSerializer < yardl.binary.TypeSerializer - properties - item_serializer_; - items_remaining_; - end - - methods - function self = StreamSerializer(item_serializer) - self.item_serializer_ = item_serializer; - self.items_remaining_ = 0; - end - - function write(self, outstream, values) - if isempty(values) - return; - end - - if iscolumn(values) - values = transpose(values); - end - s = size(values); - count = s(end); - outstream.write_unsigned_varint(count); - - if iscell(values) - if ~isvector(s) - throw(yardl.ValueError("cell array must be a vector")); - end - for i = 1:count - self.item_serializer_.write(outstream, values{i}); - end - else - if ndims(values) > 2 - r = reshape(values, [], count); - inner_shape = s(1:end-1); - for i = 1:count - val = reshape(r(:, i), inner_shape); - self.item_serializer_.write(outstream, val); - end - else - for i = 1:count - self.item_serializer_.write(outstream, transpose(values(:, i))); - end - end - end - end - - function res = hasnext(self, instream) - if self.items_remaining_ <= 0 - self.items_remaining_ = instream.read_unsigned_varint(); - if self.items_remaining_ <= 0 - res = false; - return; - end - end - res = true; - end - - function res = read(self, instream) - if self.items_remaining_ <= 0 - throw(yardl.RuntimeError("Stream has been exhausted")); - end - - res = self.item_serializer_.read(instream); - self.items_remaining_ = self.items_remaining_ - 1; - end - - function c = get_class(self) - c = self.item_serializer_.get_class(); - end - - function s = get_shape(~) - s = []; - end - end -end diff --git a/matlab/+yardl/+binary/StringSerializer.m b/matlab/+yardl/+binary/StringSerializer.m deleted file mode 100644 index d96ff6c..0000000 --- a/matlab/+yardl/+binary/StringSerializer.m +++ /dev/null @@ -1,26 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef StringSerializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - arguments - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) {mustBeTextScalar} - end - bytes = unicode2native(value, "utf-8"); - outstream.write_unsigned_varint(length(bytes)); - outstream.write_bytes(bytes); - end - - function res = read(instream) - len = instream.read_unsigned_varint(); - bytes = instream.read_bytes(len); - res = convertCharsToStrings(native2unicode(bytes, "utf-8")); - end - - function c = get_class() - c = "string"; - end - end -end diff --git a/matlab/+yardl/+binary/TimeSerializer.m b/matlab/+yardl/+binary/TimeSerializer.m deleted file mode 100644 index e612d9f..0000000 --- a/matlab/+yardl/+binary/TimeSerializer.m +++ /dev/null @@ -1,27 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef TimeSerializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - if isa(value, "datetime") - value = yardl.Time.from_datetime(value).value; - elseif isa(value, "yardl.Time") - value = value.value; - else - throw(yardl.TypeError("Expected datetime or yardl.Time, got %s", class(value))); - end - - outstream.write_signed_varint(value); - end - - function res = read(instream) - value = instream.read_signed_varint(); - res = yardl.Time(value); - end - - function c = get_class() - c = "yardl.Time"; - end - end -end diff --git a/matlab/+yardl/+binary/TypeSerializer.m b/matlab/+yardl/+binary/TypeSerializer.m deleted file mode 100644 index 0cbb6f1..0000000 --- a/matlab/+yardl/+binary/TypeSerializer.m +++ /dev/null @@ -1,36 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef TypeSerializer < handle - methods (Static, Abstract) - write(self, stream, value) - res = read(self, stream) - c = get_class(self) - end - - methods (Static) - function s = get_shape() - s = 1; - end - - function trivial = is_trivially_serializable() - trivial = false; - end - end - - methods - function write_trivially(self, stream, values) - if ~self.is_trivially_serializable() - throw(yardl.TypeError("Not implemented for non-trivially-serializable types")); - end - stream.write_values_directly(values, self.get_class()); - end - - function res = read_trivially(self, stream, shape) - if ~self.is_trivially_serializable() - throw(yardl.TypeError("Not implemented for non-trivially-serializable types")); - end - res = stream.read_values_directly(shape, self.get_class()); - end - end -end diff --git a/matlab/+yardl/+binary/Uint16Serializer.m b/matlab/+yardl/+binary/Uint16Serializer.m deleted file mode 100644 index 5e33f7d..0000000 --- a/matlab/+yardl/+binary/Uint16Serializer.m +++ /dev/null @@ -1,22 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Uint16Serializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - arguments - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) {mustBeInRange(value, 0, 65535)} - end - outstream.write_unsigned_varint(value); - end - - function res = read(instream) - res = uint16(instream.read_unsigned_varint()); - end - - function c = get_class() - c = "uint16"; - end - end -end diff --git a/matlab/+yardl/+binary/Uint32Serializer.m b/matlab/+yardl/+binary/Uint32Serializer.m deleted file mode 100644 index 5bf4c54..0000000 --- a/matlab/+yardl/+binary/Uint32Serializer.m +++ /dev/null @@ -1,22 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Uint32Serializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - arguments - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) {mustBeInRange(value, 0, 4294967295)} - end - outstream.write_unsigned_varint(value); - end - - function res = read(instream) - res = uint32(instream.read_unsigned_varint()); - end - - function c = get_class() - c = "uint32"; - end - end -end diff --git a/matlab/+yardl/+binary/Uint64Serializer.m b/matlab/+yardl/+binary/Uint64Serializer.m deleted file mode 100644 index 3d51f62..0000000 --- a/matlab/+yardl/+binary/Uint64Serializer.m +++ /dev/null @@ -1,22 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Uint64Serializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - arguments - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) {mustBeInRange(value, 0, 18446744073709551615)} - end - outstream.write_unsigned_varint(value); - end - - function res = read(instream) - res = uint64(instream.read_unsigned_varint()); - end - - function c = get_class() - c = "uint64"; - end - end -end diff --git a/matlab/+yardl/+binary/Uint8Serializer.m b/matlab/+yardl/+binary/Uint8Serializer.m deleted file mode 100644 index 28c873b..0000000 --- a/matlab/+yardl/+binary/Uint8Serializer.m +++ /dev/null @@ -1,26 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Uint8Serializer < yardl.binary.TypeSerializer - methods (Static) - function write(outstream, value) - arguments - outstream (1,1) yardl.binary.CodedOutputStream - value (1,1) {mustBeInRange(value, 0, 255)} - end - outstream.write_byte(uint8(value)); - end - - function res = read(instream) - res = instream.read_byte(); - end - - function c = get_class() - c = "uint8"; - end - - function trivial = is_trivially_serializable() - trivial = true; - end - end -end diff --git a/matlab/+yardl/+binary/UnionSerializer.m b/matlab/+yardl/+binary/UnionSerializer.m deleted file mode 100644 index ba935c9..0000000 --- a/matlab/+yardl/+binary/UnionSerializer.m +++ /dev/null @@ -1,81 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef UnionSerializer < handle - - properties (Access=protected) - classname_ - case_serializers_ - case_factories_ - offset_ - end - - methods - function self = UnionSerializer(union_class, case_serializers, case_factories) - self.classname_ = union_class; - self.case_serializers_ = case_serializers; - self.case_factories_ = case_factories; - - if isa(case_serializers{1}, "yardl.binary.NoneSerializer") - self.offset_ = 1; - else - self.offset_ = 0; - end - end - - function write(self, outstream, value) - if isa(value, "yardl.Optional") - if ~isa(self.case_serializers_{1}, "yardl.binary.NoneSerializer") - throw(yardl.TypeError("Optional is not valid for this union type")) - end - - if value.has_value() - value = value.value; - else - outstream.write_byte(uint8(0)); - return; - end - end - - if ~isa(value, self.classname_) - throw(yardl.TypeError("Expected union value of type %s, got %s", self.classname_, class(value))) - end - - tag_index = uint8(value.index + self.offset_); - outstream.write_byte(tag_index-1); - - serializer = self.case_serializers_{tag_index}; - serializer.write(outstream, value.value); - end - - function res = read(self, instream) - case_index = instream.read_byte() + 1; - - if case_index == 1 && self.offset_ == 1 - res = yardl.None; - return - end - - serializer = self.case_serializers_{case_index}; - value = serializer.read(instream); - - factory = self.case_factories_{case_index}; - res = factory(value); - end - - function c = get_class(self) - if isa(self.case_serializers_{1}, "yardl.binary.NoneSerializer") - c = "yardl.Optional"; - else - c = self.classname_; - end - end - - end - - methods (Static) - function s = get_shape() - s = 1; - end - end -end diff --git a/matlab/+yardl/+binary/VectorSerializer.m b/matlab/+yardl/+binary/VectorSerializer.m deleted file mode 100644 index 04982ef..0000000 --- a/matlab/+yardl/+binary/VectorSerializer.m +++ /dev/null @@ -1,25 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef VectorSerializer < yardl.binary.VectorSerializerBase - - methods (Access=protected) - function handle_write_count_(~, outstream, count) - outstream.write_unsigned_varint(count); - end - - function count = get_read_count_(~, instream) - count = instream.read_unsigned_varint(); - end - end - - methods - function self = VectorSerializer(item_serializer) - self@yardl.binary.VectorSerializerBase(item_serializer); - end - - function s = get_shape(~) - s = []; - end - end -end diff --git a/matlab/+yardl/+binary/VectorSerializerBase.m b/matlab/+yardl/+binary/VectorSerializerBase.m deleted file mode 100644 index dbe1694..0000000 --- a/matlab/+yardl/+binary/VectorSerializerBase.m +++ /dev/null @@ -1,95 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef VectorSerializerBase < yardl.binary.TypeSerializer - properties - item_serializer_; - end - - methods (Abstract, Access=protected) - handle_write_count_(self, outstream, values) - get_read_count_(self, instream) - end - - methods (Access=protected) - function self = VectorSerializerBase(item_serializer) - self.item_serializer_ = item_serializer; - end - end - - methods - function write(self, outstream, values) - if iscolumn(values) - values = transpose(values); - end - s = size(values); - count = s(end); - - self.handle_write_count_(outstream, count); - - if iscell(values) - % values is a cell array, so must be a vector of shape [1, COUNT] - if ~isvector(s) - throw(yardl.ValueError("cell array must be a vector")); - end - for i = 1:count - self.item_serializer_.write(outstream, values{i}); - end - else - % values is an array, so must have shape [A, B, ..., COUNT] - if self.item_serializer_.is_trivially_serializable() - self.item_serializer_.write_trivially(outstream, values); - return - end - - if ndims(values) > 2 - r = reshape(values, [], count); - for i = 1:count - val = reshape(r(:, i), s(1:end-1)); - self.item_serializer_.write(outstream, val); - end - else - for i = 1:count - self.item_serializer_.write(outstream, transpose(values(:, i))); - end - end - end - end - - function res = read(self, instream) - count = self.get_read_count_(instream); - if count == 0 - res = yardl.allocate(self.get_class(), 0); - return; - end - - item_shape = self.item_serializer_.get_shape(); - if isempty(item_shape) - res = cell(1, count); - for i = 1:count - res{i} = self.item_serializer_.read(instream); - end - return - end - - if self.item_serializer_.is_trivially_serializable() - res = self.item_serializer_.read_trivially(instream, [prod(item_shape), count]); - else - res = yardl.allocate(self.get_class(), [prod(item_shape), count]); - for i = 1:count - item = self.item_serializer_.read(instream); - res(:, i) = item(:); - end - end - - res = squeeze(reshape(res, [item_shape, count])); - if iscolumn(res) - res = transpose(res); - end - end - - function c = get_class(self) - c = self.item_serializer_.get_class(); - end - end -end diff --git a/matlab/+yardl/Date.m b/matlab/+yardl/Date.m deleted file mode 100644 index cbae0f5..0000000 --- a/matlab/+yardl/Date.m +++ /dev/null @@ -1,70 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Date < handle - - properties (SetAccess=private) - days_since_epoch - end - - methods - function self = Date(days_since_epoch) - if nargin > 0 - self.days_since_epoch = days_since_epoch; - else - self.days_since_epoch = 0; - end - end - - function value = value(self) - value = self.days_since_epoch; - end - - function dt = to_datetime(self) - dt = datetime(0, 'ConvertFrom', 'epochtime') + days(self.days_since_epoch); - end - - function eq = eq(self, other) - if isa(other, 'datetime') - other = yardl.Date.from_datetime(other); - end - - eq = isa(other, 'yardl.Date') && ... - all([self.days_since_epoch] == [other.days_since_epoch]); - end - - function ne = ne(self, other) - ne = ~self.eq(other); - end - - function isequal = isequal(self, other) - isequal = all(eq(self, other)); - end - end - - methods (Static) - function d = from_datetime(value) - dur = value - datetime(0, 'ConvertFrom', 'epochtime'); - d = yardl.Date(days(dur)); - end - - function d = from_components(y, m, d) - d = yardl.Date.from_datetime(datetime(y, m, d)); - end - - function z = zeros(varargin) - elem = yardl.Date(0); - if nargin == 0 - z = elem; - return - end - - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end - -end diff --git a/matlab/+yardl/DateTime.m b/matlab/+yardl/DateTime.m deleted file mode 100644 index af710ec..0000000 --- a/matlab/+yardl/DateTime.m +++ /dev/null @@ -1,81 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef DateTime < handle - % A basic datetime with nanosecond precision, always in UTC. - - properties (SetAccess=private) - nanoseconds_since_epoch - end - - methods - function self = DateTime(nanoseconds_since_epoch) - if nargin > 0 - self.nanoseconds_since_epoch = nanoseconds_since_epoch; - else - self.nanoseconds_since_epoch = 0; - end - end - - function value = value(self) - value = self.nanoseconds_since_epoch; - end - - function dt = to_datetime(self) - dt = datetime(self.nanoseconds_since_epoch, 'ConvertFrom', 'epochtime', 'TicksPerSecond', 1e9); - end - - function eq = eq(self, other) - if isa(other, 'datetime') - other = yardl.DateTime.from_datetime(other); - end - - eq = isa(other, 'yardl.DateTime') && ... - all([self.nanoseconds_since_epoch] == [other.nanoseconds_since_epoch]); - end - - function ne = ne(self, other) - ne = ~self.eq(other); - end - - function isequal = isequal(self, other) - isequal = all(eq(self, other)); - end - end - - methods (Static) - function dt = from_datetime(value) - value.TimeZone = 'UTC'; - nanoseconds_since_epoch = convertTo(value, 'epochtime', 'TicksPerSecond', 1e9); - dt = yardl.DateTime(nanoseconds_since_epoch); - end - - function dt = from_components(year, month, day, hour, minute, second, nanosecond) - if ~(nanosecond >= 0 && nanosecond < 999999999) - throw(yardl.ValueError("nanosecond must be in 0..1e9")); - end - mdt = datetime(year, month, day, hour, minute, second, 'TimeZone', 'UTC'); - seconds_since_epoch = convertTo(mdt, 'epochtime'); - dt = yardl.DateTime(seconds_since_epoch * 1e9 + nanosecond); - end - - function dt = now(~) - dt = yardl.DateTime.from_datetime(datetime('now')); - end - - function z = zeros(varargin) - elem = yardl.DateTime(0); - if nargin == 0 - z = elem; - return - end - - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end - -end diff --git a/matlab/+yardl/Exception.m b/matlab/+yardl/Exception.m deleted file mode 100644 index 131fd04..0000000 --- a/matlab/+yardl/Exception.m +++ /dev/null @@ -1,6 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -function err = Exception(id, varargin) - err = MException(id, varargin{:}); -end diff --git a/matlab/+yardl/Map.m b/matlab/+yardl/Map.m deleted file mode 100644 index 5b446cc..0000000 --- a/matlab/+yardl/Map.m +++ /dev/null @@ -1,73 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Map < handle - properties (SetAccess=protected) - dict - end - - methods - - function self = Map(varargin) - self.dict = dictionary(varargin{:}); - end - - function k = keys(self) - k = keys(self.dict); - end - - function v = values(self) - v = values(self.dict); - end - - function l = lookup(self, varargin) - l = lookup(self.dict, varargin{:}); - end - - function insert(self, varargin) - self.dict = insert(self.dict, varargin{:}); - end - - function remove(self, varargin) - self.dict = remove(self.dict, varargin{:}); - end - - function n = numEntries(self) - n = numEntries(self.dict); - end - - function res = eq(a, b) - if isa(b, 'yardl.Map') - res = isequal({a.dict}, {b.dict}); - elseif isa(b, 'dictionary') - res = isequal({a.dict}, {b}); - else - res = false; - end - end - - function ne = ne(a, b) - ne = ~eq(a, b); - end - - function isequal = isequal(self, other) - isequal = all(eq(self, other)); - end - end - - methods (Static) - function z = zeros(varargin) - elem = yardl.Map(); - if nargin == 0 - z = elem; - return - end - - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+yardl/None.m b/matlab/+yardl/None.m deleted file mode 100644 index 728123d..0000000 --- a/matlab/+yardl/None.m +++ /dev/null @@ -1,6 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -function n = None() - n = yardl.Optional(); -end diff --git a/matlab/+yardl/Optional.m b/matlab/+yardl/Optional.m deleted file mode 100644 index 574bd79..0000000 --- a/matlab/+yardl/Optional.m +++ /dev/null @@ -1,83 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Optional < handle - properties (SetAccess=protected) - has_value - end - - properties (Access=protected) - value_ - end - - methods - function self = Optional(varargin) - if nargin > 0 - self.value_ = varargin{1}; - self.has_value = true; - else - self.has_value = false; - end - end - - function v = value(self) - if ~self.has_value - throw(yardl.ValueError("Optional type does not have a value")); - end - v = self.value_; - end - - function eq = eq(a, b) - if isa(a, 'yardl.Optional') - if isa(b, 'yardl.Optional') - if all([a.has_value]) && all([b.has_value]) - eq = isequal([a.value_], [b.value_]); - else - eq = [a.has_value] == [b.has_value]; - end - else - if all([a.has_value]) - eq = isequal(b, [a.value_]); - else - eq = false; - end - end - else - % b is the Optional - if all([b.has_value]) - eq = isequal(a, [b.value_]); - else - eq = false; - end - end - end - - function ne = ne(a, b) - ne = ~eq(a, b); - end - - function isequal = isequal(a, varargin) - isequal = all(eq(a, [varargin{:}])); - end - - function isequaln = isequaln(a, varargin) - isequaln = isequal(a, [varargin{:}]); - end - end - - methods (Static) - function z = zeros(varargin) - elem = yardl.None; - if nargin == 0 - z = elem; - return - end - - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end -end diff --git a/matlab/+yardl/ProtocolError.m b/matlab/+yardl/ProtocolError.m deleted file mode 100644 index eac33ad..0000000 --- a/matlab/+yardl/ProtocolError.m +++ /dev/null @@ -1,6 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -function err = ProtocolError(varargin) - err = yardl.Exception("yardl:ProtocolError", varargin{:}); -end diff --git a/matlab/+yardl/RuntimeError.m b/matlab/+yardl/RuntimeError.m deleted file mode 100644 index d2a2d61..0000000 --- a/matlab/+yardl/RuntimeError.m +++ /dev/null @@ -1,6 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -function err = RuntimeError(varargin) - err = yardl.Exception("yardl:RuntimeError", varargin{:}); -end diff --git a/matlab/+yardl/Time.m b/matlab/+yardl/Time.m deleted file mode 100644 index 533d5de..0000000 --- a/matlab/+yardl/Time.m +++ /dev/null @@ -1,90 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Time < handle - % A basic time of day with nanosecond precision. It is not timezone-aware and is - % meant to represent a wall clock time. - - properties (SetAccess=private) - nanoseconds_since_midnight - end - - methods - function self = Time(nanoseconds_since_midnight) - if nargin > 0 - if nanoseconds_since_midnight < 0 || nanoseconds_since_midnight >= 24*60*60*1e9 - throw(yardl.ValuError("Time must be between 00:00:00 and 23:59:59.999999999")); - end - self.nanoseconds_since_midnight = nanoseconds_since_midnight; - else - self.nanoseconds_since_midnight = 0; - end - end - - function value = value(self) - value = self.nanoseconds_since_midnight; - end - - function dt = to_datetime(self) - dt = datetime(self.nanoseconds_since_midnight, 'ConvertFrom', 'epochtime', 'Epoch', datetime('today'), 'TicksPerSecond', 1e9); - end - - function eq = eq(self, other) - if isa(other, 'datetime') - other = yardl.Time.from_datetime(other); - end - - eq = isa(other, 'yardl.Time') && ... - all([self.nanoseconds_since_midnight] == [other.nanoseconds_since_midnight]); - end - - function ne = ne(self, other) - ne = ~self.eq(other); - end - - function isequal = isequal(self, other) - isequal = all(eq(self, other)); - end - end - - methods (Static) - function t = from_datetime(value) - nanoseconds_since_midnight = convertTo(value, 'epochtime', ... - 'Epoch', datetime(value.Year, value.Month, value.Day, 'TimeZone', value.TimeZone), ... - 'TicksPerSecond', 1e9); - t = yardl.Time(nanoseconds_since_midnight); - end - - function t = from_components(hour, minute, second, nanosecond) - if ~(hour >= 0 && hour <= 23) - throw(yardl.ValueError("hour must be between 0 and 23")); - end - if ~(minute >= 0 && minute <= 59) - throw(yardl.ValueError("minute must be between 0 and 59")); - end - if ~(second >= 0 && second <= 59) - throw(yardl.ValueError("second must be between 0 and 59")); - end - if ~(nanosecond >= 0 && nanosecond <= 999999999) - throw(yardl.ValueError("nanosecond must be between 0 and 999999999")); - end - - t = yardl.Time(hour * 60*60*1e9 + minute * 60*1e9 + second * 1e9 + nanosecond); - end - - function z = zeros(varargin) - elem = yardl.Time(0); - if nargin == 0 - z = elem; - return - end - - sz = [varargin{:}]; - if isscalar(sz) - sz = [sz, sz]; - end - z = reshape(repelem(elem, prod(sz)), sz); - end - end - -end diff --git a/matlab/+yardl/TypeError.m b/matlab/+yardl/TypeError.m deleted file mode 100644 index d37b4d6..0000000 --- a/matlab/+yardl/TypeError.m +++ /dev/null @@ -1,6 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -function err = TypeError(varargin) - err = yardl.Exception("yardl:TypeError", varargin{:}); -end diff --git a/matlab/+yardl/Union.m b/matlab/+yardl/Union.m deleted file mode 100644 index 7079c97..0000000 --- a/matlab/+yardl/Union.m +++ /dev/null @@ -1,41 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -classdef Union < handle & matlab.mixin.CustomDisplay - properties (Access=protected) - index_ - end - - properties (SetAccess=protected) - value - end - - methods - function self = Union(index, value) - self.index_ = index; - self.value = value; - end - - function i = index(self) - i = self.index_; - end - - function isequal = isequal(self, other) - isequal = all(eq(self, other)); - end - end - - methods (Abstract) - t = tag(self) - end - - methods (Access=protected) - function displayScalarObject(obj) - className = matlab.mixin.CustomDisplay.getClassNameForHeader(obj); - header = sprintf('%s.%s\n', className, obj.tag()); - disp(header) - propgroup = getPropertyGroups(obj); - matlab.mixin.CustomDisplay.displayPropertyGroups(obj,propgroup) - end - end -end diff --git a/matlab/+yardl/ValueError.m b/matlab/+yardl/ValueError.m deleted file mode 100644 index 3c0bd3f..0000000 --- a/matlab/+yardl/ValueError.m +++ /dev/null @@ -1,6 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -function err = ValueError(varargin) - err = yardl.Exception("yardl:ValueError", varargin{:}); -end diff --git a/matlab/+yardl/allocate.m b/matlab/+yardl/allocate.m deleted file mode 100644 index f99f87f..0000000 --- a/matlab/+yardl/allocate.m +++ /dev/null @@ -1,11 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -function res = allocate(classname, varargin) - % Wrapper around zeros, used to preallocate arrays of yardl objects - if classname == "string" - res = strings(varargin{:}); - else - res = zeros(varargin{:}, classname); - end -end diff --git a/matlab/+yardl/dimension_count.m b/matlab/+yardl/dimension_count.m deleted file mode 100644 index 2156767..0000000 --- a/matlab/+yardl/dimension_count.m +++ /dev/null @@ -1,9 +0,0 @@ -% Copyright (c) Microsoft Corporation. -% Licensed under the MIT License. - -function c = dimension_count(arr) - % Alternative to Matlab's `ndims` function - % Collapses dimensions of size 1 (making it behave like numpy.array.ndim) - s = size(arr); - c = length(s(s > 1)); -end diff --git a/matlab/.gitignore b/matlab/.gitignore new file mode 100644 index 0000000..151080d --- /dev/null +++ b/matlab/.gitignore @@ -0,0 +1 @@ +release/ diff --git a/matlab/build-toolbox.sh b/matlab/build-toolbox.sh new file mode 100755 index 0000000..679e027 --- /dev/null +++ b/matlab/build-toolbox.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +matlab -batch buildtool diff --git a/matlab/buildfile.m b/matlab/buildfile.m new file mode 100644 index 0000000..e81e109 --- /dev/null +++ b/matlab/buildfile.m @@ -0,0 +1,41 @@ +function plan = buildfile + plan = buildplan(localfunctions); + plan.DefaultTasks = ["packageToolbox"]; +end + +function packageToolboxTask(~) + buildToolbox("release"); +end + +function buildToolbox (outdir) + if ~exist(outdir, 'dir') + mkdir(outdir); + end + + uuid = string(java.util.UUID.randomUUID()); + toolboxFolder = "./toolbox/"; + opts = matlab.addons.toolbox.ToolboxOptions(toolboxFolder, uuid); + + toolboxDirs = unique(fileparts(opts.ToolboxFiles)); + if ~all(contains(toolboxDirs, opts.ToolboxFolder)) + error("No symbolic links allowed in toolboxFolder (BUG through at least R2023a)"); + end + + opts.ToolboxName = "PETSIRD"; + + opts.ToolboxVersion = "0.2.0"; + opts.OutputFile = fullfile(outdir, sprintf("petsird-%s.mltbx", opts.ToolboxVersion)); + + opts.Description = "Positron Emission Tomography Standardization Initiative Raw Data (PETSIRD) toolbox for MATLAB"; + % opts.Summary = ""; + % opts.AuthorCompany = ""; + + opts.MinimumMatlabRelease = "R2022b"; + + % Must also specify which folders should be added to MATLAB path upon toolbox installation. + % Must also include at least one *file *in the toolbox folder. + % This seems to be bug on Linux, Matlab R2023a. On Windows, this isn't required. + opts.ToolboxMatlabPath = toolboxFolder; + + matlab.addons.toolbox.packageToolbox(opts); +end diff --git a/matlab/+petsird/+helpers/get_detection_efficiency.m b/matlab/toolbox/+petsird/+helpers/get_detection_efficiency.m similarity index 100% rename from matlab/+petsird/+helpers/get_detection_efficiency.m rename to matlab/toolbox/+petsird/+helpers/get_detection_efficiency.m diff --git a/matlab/+petsird/+helpers/get_module_and_element.m b/matlab/toolbox/+petsird/+helpers/get_module_and_element.m similarity index 100% rename from matlab/+petsird/+helpers/get_module_and_element.m rename to matlab/toolbox/+petsird/+helpers/get_module_and_element.m diff --git a/matlab/+petsird/+helpers/get_num_detecting_elements.m b/matlab/toolbox/+petsird/+helpers/get_num_detecting_elements.m similarity index 100% rename from matlab/+petsird/+helpers/get_num_detecting_elements.m rename to matlab/toolbox/+petsird/+helpers/get_num_detecting_elements.m diff --git a/matlab/petsird_analysis.m b/matlab/toolbox/petsird_analysis.m similarity index 100% rename from matlab/petsird_analysis.m rename to matlab/toolbox/petsird_analysis.m diff --git a/matlab/petsird_generator.m b/matlab/toolbox/petsird_generator.m similarity index 98% rename from matlab/petsird_generator.m rename to matlab/toolbox/petsird_generator.m index ab92524..fa6b97e 100644 --- a/matlab/petsird_generator.m +++ b/matlab/toolbox/petsird_generator.m @@ -23,7 +23,7 @@ function petsird_generator(output) for t = 0:config.NUMBER_OF_TIME_BLOCKS-1 start = t * header.scanner.event_time_block_duration; - % TODO: Need Statistics and Machine Learning Toolbox for Poisson distribution functions + % NOTE: Need Statistics and Machine Learning Toolbox for Poisson distribution functions % num_prompts_this_block = poissrnd(COUNT_RATE); num_prompts_this_block = randi(config.COUNT_RATE); prompts_this_block = get_events(header, num_prompts_this_block, config); @@ -50,8 +50,6 @@ function petsird_generator(output) function scanner = get_scanner_info(cfg) scanner_geometry = get_scanner_geometry(cfg); - % TODO scanner_info.bulk_materials - % TOF info (in mm) tofBinEdges = single(linspace(-cfg.RADIUS, cfg.RADIUS, cfg.NUMBER_OF_TOF_BINS + 1)); energyBinEdges = single(linspace(430, 650, cfg.NUMBER_OF_ENERGY_BINS + 1)); diff --git a/model/_package.yml b/model/_package.yml index 1f8c18e..7ded04c 100644 --- a/model/_package.yml +++ b/model/_package.yml @@ -7,4 +7,4 @@ python: outputDir: ../python matlab: - outputDir: ../matlab + outputDir: ../matlab/toolbox