Coverage for kwave/ksensor.py: 85%

48 statements  

« prev     ^ index     » next       coverage.py v7.7.1, created at 2025-03-24 12:06 -0700

1from dataclasses import dataclass 

2 

3import numpy as np 

4from deprecated import deprecated 

5 

6from kwave.utils.matrix import expand_matrix 

7 

8 

9class kSensor: 

10 """ 

11 Sensor class for k-Wave simulations. 

12 """ 

13 

14 def __init__(self, mask=None, record=None): 

15 """ 

16 Initialize a kSensor object. 

17 

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 

26 

27 # Directivity of the individual sensor points 

28 self.directivity = None 

29 

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 

33 

34 # DEPRECATED: Will be removed in v0.5 

35 self._time_reversal_boundary_data = None 

36 

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 

43 

44 @mask.setter 

45 def mask(self, val): 

46 self._mask = val 

47 

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) 

52 

53 Args: 

54 expand_size: the number of elements to add in each dimension 

55 

56 Returns: 

57 None 

58 """ 

59 self.mask = expand_matrix(self.mask, expand_size, 0) 

60 

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 

67 

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)) 

72 

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 

77 

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 

82 

83 

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 

92 

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" 

97 

98 #: equivalent element size (the larger the element size the more directional the response) 

99 size: float = None 

100 

101 #: list of the unique directivity angles 

102 unique_angles: np.ndarray = None 

103 

104 #: It is precomputed to allow data casting, as kgrid.kx (etc) are computed on the fly. 

105 wavenumbers: np.ndarray = None 

106 

107 def set_default_size(self, kgrid) -> None: 

108 """ 

109 Set the element size based on the kGrid 

110 

111 Args: 

112 kgrid: Instance of `~kwave.kgrid.kWaveGrid` class 

113 

114 Returns: 

115 None 

116 """ 

117 DEFAULT_SIZE = 10 

118 self.size = DEFAULT_SIZE * max(kgrid.dx, kgrid.dy) 

119 

120 def set_unique_angles(self, sensor_mask) -> None: 

121 """ 

122 Assign unique_angles from sensor_mask 

123 

124 Args: 

125 sensor_mask: 

126 

127 Returns: 

128 None 

129 """ 

130 self.unique_angles = np.unique(self.angle[sensor_mask == 1]) 

131 

132 def set_wavenumbers(self, kgrid) -> None: 

133 """ 

134 Assign the wavenumber vectors 

135 

136 Args: 

137 kgrid: Instance of `~kwave.kgrid.kWaveGrid` class 

138 

139 Returns: 

140 None 

141 """ 

142 self.wavenumbers = np.vstack([kgrid.ky.T, kgrid.kx.T])