|
7 | 7 | from birdnet.acoustic.inference.core.encoding.encoding_tensor import ( |
8 | 8 | AcousticEncodingTensor, |
9 | 9 | ) |
10 | | -from birdnet.acoustic.inference.core.result_base import AcousticResultBase |
11 | | -from birdnet.utils.helper import get_uint_dtype |
| 10 | +from birdnet.acoustic.inference.core.result_base import ( |
| 11 | + VAR_END_TIME, |
| 12 | + VAR_INPUT, |
| 13 | + VAR_START_TIME, |
| 14 | + AcousticResultBase, |
| 15 | +) |
| 16 | +from birdnet.utils.helper import ( |
| 17 | + apply_speed_to_duration, |
| 18 | + get_hop_duration_s, |
| 19 | + get_uint_dtype, |
| 20 | +) |
| 21 | + |
| 22 | +VAR_EMBEDDING = "embedding" |
12 | 23 |
|
13 | 24 | NP_EMB_KEY = "embeddings" |
14 | 25 | NP_EMB_MASKED_KEY = "embeddings_masked" |
@@ -78,6 +89,65 @@ def emd_dim(self) -> int: |
78 | 89 | def max_n_segments(self) -> int: |
79 | 90 | return self._embeddings.shape[1] |
80 | 91 |
|
| 92 | + def test() -> None: |
| 93 | + pass |
| 94 | + |
| 95 | + def to_structured_array(self) -> np.ndarray: |
| 96 | + valid_mask_per_segment = ~(self._embeddings_masked).all(axis=2) |
| 97 | + valid_file_idx, valid_seg_idx = np.where(valid_mask_per_segment) |
| 98 | + n_embeddings = len(valid_file_idx) |
| 99 | + |
| 100 | + embeddings_selected = self.embeddings[valid_file_idx, valid_seg_idx] |
| 101 | + |
| 102 | + dtype = [ |
| 103 | + (VAR_INPUT, self._input_dtype), |
| 104 | + (VAR_START_TIME, self._input_durations.dtype), |
| 105 | + (VAR_END_TIME, self._input_durations.dtype), |
| 106 | + (VAR_EMBEDDING, self._embeddings.dtype, self.emd_dim), |
| 107 | + ] |
| 108 | + |
| 109 | + structured_array = np.empty(n_embeddings, dtype=dtype) |
| 110 | + del dtype |
| 111 | + |
| 112 | + if n_embeddings == 0: |
| 113 | + return structured_array |
| 114 | + del n_embeddings |
| 115 | + |
| 116 | + sort_keys = ( |
| 117 | + valid_seg_idx, |
| 118 | + valid_file_idx, |
| 119 | + ) |
| 120 | + sort_indices = np.lexsort(sort_keys) |
| 121 | + del sort_keys |
| 122 | + |
| 123 | + file_idx_flat = valid_file_idx[sort_indices] |
| 124 | + chunk_idx_flat = valid_seg_idx[sort_indices] |
| 125 | + emb_flat = embeddings_selected[sort_indices] |
| 126 | + del embeddings_selected |
| 127 | + del sort_indices |
| 128 | + |
| 129 | + hop_duration_s = get_hop_duration_s( |
| 130 | + self._segment_duration_s[0], self._overlap_duration_s[0], self._speed[0] |
| 131 | + ) |
| 132 | + start_times = chunk_idx_flat.astype(self._input_durations.dtype) * hop_duration_s |
| 133 | + del hop_duration_s |
| 134 | + del chunk_idx_flat |
| 135 | + |
| 136 | + structured_array[VAR_START_TIME] = start_times |
| 137 | + structured_array[VAR_END_TIME] = np.minimum( |
| 138 | + start_times |
| 139 | + + apply_speed_to_duration(self._segment_duration_s[0], self._speed[0]), |
| 140 | + self._input_durations[file_idx_flat], |
| 141 | + ) |
| 142 | + del start_times |
| 143 | + structured_array[VAR_INPUT] = self._inputs[file_idx_flat] |
| 144 | + del file_idx_flat |
| 145 | + |
| 146 | + structured_array[VAR_EMBEDDING] = emb_flat |
| 147 | + del emb_flat |
| 148 | + |
| 149 | + return structured_array |
| 150 | + |
81 | 151 | def unprocessable_inputs(self) -> np.ndarray: |
82 | 152 | return self._unprocessable_inputs |
83 | 153 |
|
|
0 commit comments