From 28c2eda0cdf3c3a46b77a8b8961bd2d346a90137 Mon Sep 17 00:00:00 2001 From: towsey Date: Tue, 13 Oct 2020 15:32:20 +1100 Subject: [PATCH] Fix unit test for Cisticola Issue #370 Incorporate all latest event combiners and filters into this recognizer --- .../Towsey.CisticolaExilis.yml | 57 +++++++++++++------ .../Recognizers/Birds/CisticolaExilis.cs | 29 +--------- .../Recognizers/CisticolaTests.cs | 22 +++---- 3 files changed, 52 insertions(+), 56 deletions(-) diff --git a/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.CisticolaExilis.yml b/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.CisticolaExilis.yml index 36dc72890..f8b14061e 100644 --- a/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.CisticolaExilis.yml +++ b/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.CisticolaExilis.yml @@ -22,36 +22,59 @@ Profiles: MaxHertz: 3300 MinBandwidthHertz: 200 MaxBandwidthHertz: 900 - DecibelThreshold: 6.0 + DecibelThresholds: + - 6.0 + - 9.0 + - 12.0 #################### POST-PROCESSING of EVENTS ################### -# A: First post-processing steps are to combine overlapping/proximal/sequential events -# 1: Combine overlapping events -CombineOverlappingEvents: true +PostProcessing: +# The following generic post-processing steps are determined by config settings. +# Step 1: Combine overlapping events - events derived from all profiles. +# Step 2: Combine possible syllable sequences and filter on excess syllable count. +# Step 3: Remove events whose bandwidth is too small or large. +# Step 4: Remove events that have excessive noise in their side-bands. -# 2: Combine syllables that possibly belong to the same strophe. -# Can also use this to "mop up" events in neighbourhood - these can be removed later. -CombinePossibleSyllableSequence: true -SyllableStartDifference: 0.15 -SyllableHertzGap: 500 + # 1: Combine overlapping events + CombineOverlappingEvents: true -# B: Filter the events for excess activity in their upper and lower buffer zones -NeighbourhoodLowerHertzBuffer: 0 -NeighbourhoodUpperHertzBuffer: 200 -NeighbourhoodDbThreshold: 4.0 + # 2: Combine possible syllable sequences + SyllableSequence: + CombinePossibleSyllableSequence: true + SyllableStartDifference: 0.11 + SyllableHertzGap: 300 + FilterSyllableSequence: true + SyllableMaxCount: 2 + ExpectedPeriod: 0.08 -# C: Options to save results files -# 4: Available options for saving spectrograms (case-sensitive): [False/Never | True/Always | WhenEventsDetected] + # 3: Remove events whose duration lies outside 3 SDs of an expected value. + Duration: + ExpectedDuration: 0.14 + DurationStandardDeviation: 0.01 + + # 4: Remove events whose bandwidth lies outside 3 SDs of an expected value. + # Bandwidth: + ExpectedBandwidth: 600 + BandwidthStandardDeviation: 150 + + # 4: Filter the events for excess activity in their sidebands, i.e. upper and lower buffer zones + SidebandActivity: + LowerHertzBuffer: 0 + UpperHertzBuffer: 0 #200 + DecibelBuffer: 2.0 + +# Options to save results files +# 1: Available options for saving spectrograms (case-sensitive): [False/Never | True/Always | WhenEventsDetected] # "True" is useful when debugging but "WhenEventsDetected" is required for operational use. #SaveSonogramImages: True SaveSonogramImages: WhenEventsDetected -# 5: Available options for saving data files (case-sensitive): [False/Never | True/Always | WhenEventsDetected] +# 2: Available options for saving data files (case-sensitive): [False/Never | True/Always | WhenEventsDetected] SaveIntermediateWavFiles: Never SaveIntermediateCsvFiles: false -# 6: DisplayCsvImage is obsolete - ensure it remains set to: false +# 3: DisplayCsvImage is obsolete - ensure it remains set to: false DisplayCsvImage: false ## End section for AnalyzeLongRecording diff --git a/src/AnalysisPrograms/Recognizers/Birds/CisticolaExilis.cs b/src/AnalysisPrograms/Recognizers/Birds/CisticolaExilis.cs index c85f422a0..eb5ab8bfd 100644 --- a/src/AnalysisPrograms/Recognizers/Birds/CisticolaExilis.cs +++ b/src/AnalysisPrograms/Recognizers/Birds/CisticolaExilis.cs @@ -81,35 +81,8 @@ public override RecognizerResults Recognize( imageWidth); // ################### POST-PROCESSING of EVENTS ################### - if (combinedResults.NewEvents.Count == 0) - { - CisticolaLog.Debug($"Return zero events."); - return combinedResults; - } - - // 1: Filter the events for duration in seconds - var minimumEventDuration = 0.1; - var maximumEventDuration = 0.25; - combinedResults.NewEvents = EventFilters.FilterOnDuration(combinedResults.NewEvents, minimumEventDuration, maximumEventDuration); - CisticolaLog.Debug($"Event count after filtering on duration = {combinedResults.NewEvents.Count}"); - - // 2: Filter the events for bandwidth in Hertz - double average = 600; - double sd = 150; - double sigmaThreshold = 3.0; - combinedResults.NewEvents = EventFilters.FilterOnBandwidth(combinedResults.NewEvents, average, sd, sigmaThreshold); - CisticolaLog.Debug($"Event count after filtering on bandwidth = {combinedResults.NewEvents.Count}"); - - // 3: Filter on COMPONENT COUNT in Composite events. - //int maxComponentCount = 2; - //combinedResults.NewEvents = EventExtentions.FilterEventsOnCompositeContent(combinedResults.NewEvents, maxComponentCount); - //CisticolaLog.Debug($"Event count after filtering on component count = {combinedResults.NewEvents.Count}"); - - //combinedResults.NewEvents = FilterEventsOnFrequencyProfile(combinedResults.NewEvents); + // Additional post-processing steps can be coded here. - //UNCOMMENT following line if you want special debug spectrogram, i.e. with special plots. - // NOTE: Standard spectrograms are produced by setting SaveSonogramImages: "True" or "WhenEventsDetected" in UserName.SpeciesName.yml config file. - //GenericRecognizer.SaveDebugSpectrogram(territorialResults, genericConfig, outputDirectory, audioRecording.BaseName); return combinedResults; } diff --git a/tests/Acoustics.Test/AnalysisPrograms/Recognizers/CisticolaTests.cs b/tests/Acoustics.Test/AnalysisPrograms/Recognizers/CisticolaTests.cs index 6a958229c..bb20d768f 100644 --- a/tests/Acoustics.Test/AnalysisPrograms/Recognizers/CisticolaTests.cs +++ b/tests/Acoustics.Test/AnalysisPrograms/Recognizers/CisticolaTests.cs @@ -51,21 +51,21 @@ public void TestRecognizer() this.SaveTestOutput( outputDirectory => GenericRecognizer.SaveDebugSpectrogram(results, null, outputDirectory, Recognizer.SpeciesName)); - // this test returns 17 events with one false-negative and possibly one false-positive. - Assert.AreEqual(17, events.Count); + // this test returns 20 events with one false-positive. + Assert.AreEqual(20, events.Count); Assert.IsNull(scoreTrack); - Assert.AreEqual(1, plots.Count); + Assert.AreEqual(3, plots.Count); Assert.AreEqual(3747, sonogram.FrameCount); - Assert.IsInstanceOfType(events[3], typeof(CompositeEvent)); - var fourthEvent = (CompositeEvent)events[3]; + Assert.IsInstanceOfType(events[6], typeof(CompositeEvent)); + var ev = (CompositeEvent)events[6]; - Assert.AreEqual(7.28, fourthEvent.EventStartSeconds); - Assert.AreEqual(7.432, fourthEvent.EventEndSeconds); - Assert.AreEqual(2542, fourthEvent.LowFrequencyHertz); - Assert.AreEqual(3100, fourthEvent.HighFrequencyHertz); - Assert.AreEqual(17.91649081319, fourthEvent.Score, TestHelper.AllowedDelta); - Assert.AreEqual(0.07765486486, fourthEvent.ScoreNormalized, TestHelper.AllowedDelta); + Assert.AreEqual(7.28, ev.EventStartSeconds); + Assert.AreEqual(7.432, ev.EventEndSeconds); + Assert.AreEqual(2542, ev.LowFrequencyHertz); + Assert.AreEqual(3100, ev.HighFrequencyHertz); + Assert.AreEqual(19.577394545704326, ev.Score, TestHelper.AllowedDelta); + Assert.AreEqual(0.00013717318483754581, ev.ScoreNormalized, TestHelper.AllowedDelta); } } } \ No newline at end of file