def update_equiv_src(self, new_src: Source): """"If the new source is within the margin of an old source, add its audio to the old source and analyze with ML""" logging.debug(f"Updating equivalent source...") for src in self.sources: if src.position.within_margin(resonant.SOURCE_MARGIN, new_src.position): logging.debug( f"New source ({new_src}) within margin of old source ({src})... updating" ) src.update_audio(new_src.audio[:resonant.LOCALIZING_WINDOW]) src.position = new_src.position # It only runs ml if it has enough samples to analyze """if src.can_ml_analyze: # self.ml.analyze(src) # This means the ML was conclusive and it keeps it alive if src.name is not None: src.reset_cycles() """ return # If there are no equivalent sources, add it to the tracked sources new_src.track() self.sources.append(new_src) logging.debug( f"No matching source to new source ({new_src}). Adding to tracked sources." )
def test_src_filter(sources: List[Source]): resonant.CYCLES_TO_LIVE = 3 sources = [ Source(60, np.array([1, 1, 1, 1, 1, 1, 1])), Source(21, np.array([1, 1, 1, 1, 1, 1, 1])), ] sources[0].cycles_lived = 2 sources[1].cycles_lived = 0
def test_ml_max_samples(self): resonant.MIN_ML_SAMPLES = 6 resonant.MAX_ML_SAMPLES = 10 src = Source(33, np.zeros(7)) assert src.can_ml_analyze is True src.audio = np.zeros(11) with pytest.raises(AssertionError) as exc_info: src.can_ml_analyze
def test_ml_min_samples(self): resonant.MIN_ML_SAMPLES = 6 resonant.MAX_ML_SAMPLES = 10 src = Source(33, np.zeros(5)) assert src.can_ml_analyze is False src.audio = np.zeros(6) assert src.can_ml_analyze is True
def sources(): empty_audio = np.zeros(5) resonant.SOURCE_MARGIN = SphericalPt.angle_only(5) resonant.MAX_ML_SAMPLES = 8 resonant.MIN_ML_SAMPLES = 6 sources = [ Source(30, empty_audio), Source(88, empty_audio), ] return sources
def test_updates(count_nan): resonant.MIN_ML_SAMPLES = 3 resonant.MAX_ML_SAMPLES = 8 src = Source(30, np.array([])) assert src.can_ml_analyze is False assert count_nan(src.audio) == resonant.MAX_ML_SAMPLES additional = np.array([2, 2, 2, 2]) src.update_audio(additional) expected = np.array([2, 2, 2, 2, np.nan, np.nan, np.nan, np.nan]) assert np.array_equal(src.audio, expected, equal_nan=True) is True assert src.can_ml_analyze is True assert count_nan(src.audio) == 4
def run_algorithm(cls, microphones: List[Mic]): def get_ratio(m1, m2): index_delay = fft_crosscorr( m1.signal, m2.signal).argmax() - len(m1.signal) / 2 confidence = np.real(fft_crosscorr(m1.signal, m2.signal).max()) ratio = resonant.V_SOUND * index_delay / \ (resonant.AUDIO_SAMPLING_RATE * resonant.MIC_SPACING * math.sqrt(2)) ratio = np.clip(ratio, -1, 1) return ratio, confidence def ave_angle(a1, a2): if (a1 < 90 and a2 > 270): a1 -= 360 if (a2 < 90 and a1 > 270): a2 -= 360 ave = (a1 + a2) / 2 if (ave < 0): ave += 360 return ave r1, c1 = get_ratio(microphones[0], microphones[2]) r2, c2 = get_ratio(microphones[1], microphones[3]) confidence = c1 * c2 logging.debug(f"Localization confidence: {confidence/resonant.LOCALIZATION_CORRELATION_THRESHOLD}") if (r1 >= 0 and r2 >= 0): angle1 = -math.acos(r1) * (180/math.pi) + 225 angle2 = math.acos(r2) * (180/math.pi) + 135 elif (r1 <= 0 and r2 <= 0): angle1 = math.acos(r1) * (180/math.pi) - 135 angle2 = -math.acos(r2) * (180/math.pi) + 135 elif (r1 > 0 and r2 < 0): angle1 = math.acos(r1) * (180/math.pi) - 135 angle2 = math.acos(r2) * (180/math.pi) + 135 elif (r1 < 0 and r2 > 0): angle1 = -math.acos(r1) * (180/math.pi) + 225 angle2 = -math.acos(r2) * (180/math.pi) + 135 if (angle1 < 0): angle1 += 360 if (angle2 < 0): angle2 += 360 ave_angle = ave_angle(angle1, angle2) source = Source((ave_angle + resonant.ANGLE_OFFSET) % 360, microphones[0].signal) logging.debug(f"Calculated source: {source}") print(f"Calculated source: {source} Localization confidence: {confidence}") if confidence >= resonant.LOCALIZATION_CORRELATION_THRESHOLD: return source else: print('Source ignored') return None
def test_cycles_reset(sources: List[Source]): ml = MLStub() ml.analyze_name = "dog" scheduler = SourceScheduler(ml) scheduler.sources = sources new_src = Source(33, np.array([1, 1, 1, 1, 1, 1])) source = sources[0] source.cycles_lived = 2 scheduler.update_equiv_src(new_src) assert source.cycles_lived == 0
def test_equiv_src_new(sources): # This has the sources not machine learning ready ml = MLStub() scheduler = SourceScheduler(ml) scheduler.sources = sources new_src = Source(38.1, np.array([1, 1, 1, 1])) scheduler.update_equiv_src(new_src) assert ml.analyzed is False assert new_src.id != -1 assert new_src in scheduler.sources
def test_equiv_src_existing(sources): # This has the sources not machine learning ready resonant.MIN_ML_SAMPLES = 10 ml = MLStub() scheduler = SourceScheduler(ml) scheduler.sources = sources new_src = Source(33, np.array([1, 1, 1, 1])) scheduler.update_equiv_src(new_src) assert ml.analyzed is False assert new_src.id == None assert new_src not in scheduler.sources
def analyze(self, src: Source): self.analyzed = True src.name = self.analyze_name