Source code for simpa.core.device_digital_twins.detection_geometries.linear_array

# 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
from simpa.utils import Settings, Tags


[docs]class LinearArrayDetectionGeometry(DetectionGeometryBase): """ This class represents a digital twin of a ultrasound detection device with a linear detection geometry. The origin for this device is the center of the linear array, so approximately the position of the (number_detector_elements/2)th detector element. """ def __init__(self, pitch_mm=0.5, number_detector_elements=100, detector_element_width_mm=0.24, detector_element_length_mm=0.5, center_frequency_hz=3.96e6, bandwidth_percent=55, sampling_frequency_mhz=40, device_position_mm: np.ndarray = None, field_of_view_extent_mm: np.ndarray = None): """ :param pitch_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 device_position_mm: Center of the linear array. """ if field_of_view_extent_mm is None: field_of_view_extent_mm = np.asarray([-number_detector_elements * pitch_mm / 2, number_detector_elements * pitch_mm / 2, 0, 0, 0, 50]) super(LinearArrayDetectionGeometry, 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, field_of_view_extent_mm=field_of_view_extent_mm) self.pitch_mm = pitch_mm self.probe_width_mm = (number_detector_elements - 1) * self.pitch_mm
[docs] def check_settings_prerequisites(self, global_settings: Settings) -> bool: if global_settings[Tags.DIM_VOLUME_X_MM] < self.probe_width_mm + global_settings[Tags.SPACING_MM]: self.logger.error("Volume x dimension is too small to encompass MSOT device in simulation!" "Must be at least {} mm but was {} mm" .format(self.probe_width_mm + global_settings[Tags.SPACING_MM], global_settings[Tags.DIM_VOLUME_X_MM])) return False return True
[docs] def update_settings_for_use_of_model_based_volume_creator(self, global_settings): pass
[docs] def get_detector_element_positions_base_mm(self) -> np.ndarray: detector_positions = np.zeros((self.number_detector_elements, 3)) if self.number_detector_elements > 1: if self.number_detector_elements % 2 == 0: # even number of detector elements det_elements = np.arange(-int(self.number_detector_elements / 2), int(self.number_detector_elements / 2)) * self.pitch_mm + 0.5 * self.pitch_mm else: # odd number of detector elements det_elements = np.arange(-int(self.number_detector_elements / 2), int(self.number_detector_elements / 2) + 1) * self.pitch_mm else: det_elements = 0 detector_positions[:, 0] = det_elements return detector_positions
[docs] def get_detector_element_orientations(self) -> np.ndarray: detector_orientations = np.zeros((self.number_detector_elements, 3)) detector_orientations[:, 2] = -1 return detector_orientations
[docs] def serialize(self) -> dict: serialized_device = self.__dict__ return {"LinearArrayDetectionGeometry": serialized_device}
[docs] @staticmethod def deserialize(dictionary_to_deserialize): deserialized_device = LinearArrayDetectionGeometry() for key, value in dictionary_to_deserialize.items(): deserialized_device.__dict__[key] = value return deserialized_device