From 9f7ea74058833c01953823e609f92aaf106fb277 Mon Sep 17 00:00:00 2001 From: Niklas Holzwarth Date: Wed, 28 Sep 2022 15:40:46 +0200 Subject: [PATCH] includes cup array PType307 --- .../detection_geometries/cup_array.py | 88 ++++++++++++++++++ .../cup_positions_PType307 | Bin 0 -> 14617 bytes 2 files changed, 88 insertions(+) create mode 100644 simpa/core/device_digital_twins/detection_geometries/cup_array.py create mode 100644 simpa/core/device_digital_twins/detection_geometries/cup_positions_PType307 diff --git a/simpa/core/device_digital_twins/detection_geometries/cup_array.py b/simpa/core/device_digital_twins/detection_geometries/cup_array.py new file mode 100644 index 00000000..567c86a7 --- /dev/null +++ b/simpa/core/device_digital_twins/detection_geometries/cup_array.py @@ -0,0 +1,88 @@ +# SPDX-FileCopyrightText: 2021 Division of Intelligent Medical Systems, DKFZ +# SPDX-FileCopyrightText: 2021 Janek Groehl +# SPDX-License-Identifier: MIT +import numpy as np + +from simpa.core.device_digital_twins import DetectionGeometryBase +import os + + +class CupArrayDetectionGeometry(DetectionGeometryBase): + """ + This class represents a digital twin of a ultrasound detection device + with a cup detection geometry. The origin for this device is the center (focus) of the cup array. + """ + + def __init__(self, radius_mm=30, + pitch_mm=None, + number_detector_elements=384, + detector_element_width_mm=None, + detector_element_length_mm=None, + center_frequency_hz=8e6, + bandwidth_percent=50, + sampling_frequency_mhz=40, + angular_origin_offset=None, + device_position_mm=None, + field_of_view_extent_mm=None): + """ + :param pitch_mm: In-plane distance between the beginning of one detector element to the next detector element. + :param radius_mm: + :param number_detector_elements: + :param detector_element_width_mm: + :param detector_element_length_mm: + :param center_frequency_hz: + :param bandwidth_percent: + :param sampling_frequency_mhz: + :param angular_origin_offset: + :param device_position_mm: Center (focus) of the curved array. + """ + + super(CupArrayDetectionGeometry, self).__init__( + number_detector_elements=number_detector_elements, + detector_element_width_mm=detector_element_width_mm, + detector_element_length_mm=detector_element_length_mm, + center_frequency_hz=center_frequency_hz, + bandwidth_percent=bandwidth_percent, + sampling_frequency_mhz=sampling_frequency_mhz, + device_position_mm=device_position_mm) + + self.pitch_mm = pitch_mm + self.radius_mm = radius_mm + self.angular_origin_offset = angular_origin_offset + + if field_of_view_extent_mm is None: + self.logger.warning("Set field_of_view_extend_mm, while looping over first or second dimension - otherwise " + "memory issues could arise. Default FOV is 4mm*4mm*8.5mm, hence very small.") + self.field_of_view_extent_mm = np.asarray([-2., 2., -2., 2., -6.5, 2.]) # -6.5 mm is level of membrane + else: + self.field_of_view_extent_mm = field_of_view_extent_mm + + def check_settings_prerequisites(self, global_settings) -> bool: + pass + + def update_settings_for_use_of_model_based_volume_creator(self, global_settings): + pass + + def get_detector_element_positions_base_mm(self) -> np.ndarray: + py_file_path = os.path.dirname(os.path.realpath(__file__)).replace("\\", "/") + detector_positions = np.load(f'{py_file_path}/cup_positions_PType307', allow_pickle=True) * 1000 # m -> mm + return detector_positions + + def get_detector_element_orientations(self) -> np.ndarray: + detector_positions = self.get_detector_element_positions_base_mm() + detector_orientations = np.subtract(0, detector_positions) + norm = np.linalg.norm(detector_orientations, axis=-1) + for dim in range(3): + detector_orientations[:, dim] = detector_orientations[:, dim] / norm + return detector_orientations + + def serialize(self) -> dict: + serialized_device = self.__dict__ + return {"CupArrayDetectionGeometry": serialized_device} + + @staticmethod + def deserialize(dictionary_to_deserialize): + deserialized_device = CupArrayDetectionGeometry() + for key, value in dictionary_to_deserialize.items(): + deserialized_device.__dict__[key] = value + return deserialized_device diff --git a/simpa/core/device_digital_twins/detection_geometries/cup_positions_PType307 b/simpa/core/device_digital_twins/detection_geometries/cup_positions_PType307 new file mode 100644 index 0000000000000000000000000000000000000000..b9665b20105a30c929b056c24befc03c102628bc GIT binary patch literal 14617 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 R|D$4PtnaNX-@?STe+R6>P455z literal 0 HcmV?d00001