Coverage for kwave/ksensor.py: 85%
48 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-03-24 12:06 -0700
« prev ^ index » next coverage.py v7.7.1, created at 2025-03-24 12:06 -0700
1from dataclasses import dataclass
3import numpy as np
4from deprecated import deprecated
6from kwave.utils.matrix import expand_matrix
9class kSensor:
10 """
11 Sensor class for k-Wave simulations.
12 """
14 def __init__(self, mask=None, record=None):
15 """
16 Initialize a kSensor object.
18 Args:
19 mask: Binary matrix or a set of Cartesian points where the pressure is recorded at each time-step
20 record: List of parameters to record (e.g., ["p", "p_final"])
21 """
22 self._mask = mask
23 self.record = record
24 # cell array of the acoustic parameters to record in the form Recorder
25 self._record_start_index = 1
27 # Directivity of the individual sensor points
28 self.directivity = None
30 # two element array specifying the center frequency and percentage bandwidth
31 # of a frequency domain Gaussian filter applied to the sensor_data
32 self.frequency_response = None
34 # DEPRECATED: Will be removed in v0.5
35 self._time_reversal_boundary_data = None
37 @property
38 def mask(self):
39 """
40 Binary matrix or a set of Cartesian points where the pressure is recorded at each time-step
41 """
42 return self._mask
44 @mask.setter
45 def mask(self, val):
46 self._mask = val
48 def expand_grid(self, expand_size) -> None:
49 """
50 Enlarge the sensor mask (for Cartesian sensor masks and cuboid corners,
51 this has already been converted to a binary mask for display in inputChecking)
53 Args:
54 expand_size: the number of elements to add in each dimension
56 Returns:
57 None
58 """
59 self.mask = expand_matrix(self.mask, expand_size, 0)
61 @property
62 def record_start_index(self):
63 """
64 Time index to start recording if transducer is used as a sensor
65 """
66 return self._record_start_index
68 @record_start_index.setter
69 def record_start_index(self, val):
70 # force the user index to be an integer
71 self._record_start_index = int(round(val))
73 @property
74 @deprecated(version="0.4.1", reason="Use TimeReversal class instead")
75 def time_reversal_boundary_data(self):
76 return self._time_reversal_boundary_data
78 @time_reversal_boundary_data.setter
79 @deprecated(version="0.4.1", reason="Use TimeReversal class instead")
80 def time_reversal_boundary_data(self, value):
81 self._time_reversal_boundary_data = value
84@dataclass
85class kSensorDirectivity(object):
86 #: matrix of directivity angles (direction of maximum
87 #: response) for each sensor element defined in
88 #: sensor.mask. The angles are in radians where 0 = max
89 #: sensitivity in x direction (up/down) and pi/2 or -pi/2
90 #: = max sensitivity in y direction (left/right)
91 angle: np.ndarray = None
93 #: string defining the directivity pattern, valid inputs
94 #: are 'pressure' (spatial averaging over the sensor
95 #: surface equivalent to a sinc function) and 'gradient'
96 pattern: str = "pressure"
98 #: equivalent element size (the larger the element size the more directional the response)
99 size: float = None
101 #: list of the unique directivity angles
102 unique_angles: np.ndarray = None
104 #: It is precomputed to allow data casting, as kgrid.kx (etc) are computed on the fly.
105 wavenumbers: np.ndarray = None
107 def set_default_size(self, kgrid) -> None:
108 """
109 Set the element size based on the kGrid
111 Args:
112 kgrid: Instance of `~kwave.kgrid.kWaveGrid` class
114 Returns:
115 None
116 """
117 DEFAULT_SIZE = 10
118 self.size = DEFAULT_SIZE * max(kgrid.dx, kgrid.dy)
120 def set_unique_angles(self, sensor_mask) -> None:
121 """
122 Assign unique_angles from sensor_mask
124 Args:
125 sensor_mask:
127 Returns:
128 None
129 """
130 self.unique_angles = np.unique(self.angle[sensor_mask == 1])
132 def set_wavenumbers(self, kgrid) -> None:
133 """
134 Assign the wavenumber vectors
136 Args:
137 kgrid: Instance of `~kwave.kgrid.kWaveGrid` class
139 Returns:
140 None
141 """
142 self.wavenumbers = np.vstack([kgrid.ky.T, kgrid.kx.T])