From d9e2919d36106ab08dfda0a04ad37c2ce40a75bc Mon Sep 17 00:00:00 2001 From: towsey Date: Thu, 3 Sep 2020 12:34:11 +1000 Subject: [PATCH] Refactored code for the Australasian Bittern Issue #370 --- .../Towsey.BotaurusPoiciloptilus.yml | 26 +++++---- .../Birds/BotaurusPoiciloptilus.cs | 53 +++++++------------ 2 files changed, 35 insertions(+), 44 deletions(-) diff --git a/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.BotaurusPoiciloptilus.yml b/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.BotaurusPoiciloptilus.yml index 85250e3eb..f7a2ac1b2 100644 --- a/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.BotaurusPoiciloptilus.yml +++ b/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.BotaurusPoiciloptilus.yml @@ -26,17 +26,25 @@ Profiles: #################### POST-PROCESSING of EVENTS ################### -# A: First post-processing steps are to combine overlapping/proximal/sequential events -# 1: Combine overlapping events -CombineOverlappingEvents: false +# The first two post-processing steps are to combine overlapping/proximal/sequential events +# 1: Combine overlapping events +CombineOverlappingEvents: true -# 2: Combine each pair of Boobook syllables as one event -# Can also use this to "mop up" events in neighbourhood - these can be removed later. -CombinePossibleSyllableSequence: true -SyllableStartDifference: 3.0 -SyllableHertzGap: 35 +# 2: Combine possible syllable sequences +# Can also use this to "mop up" events in neighbourhood - these can be removed later. +SyllableSequence: + CombinePossibleSyllableSequence: true + SyllableStartDifference: 3.0 + SyllableHertzGap: 35 + FilterSyllableSequence: true + SyllableMaxCount: 6 + ExpectedPeriod: 1.0 -# B: Filter the events for excess activity in their upper and lower buffer zones +# 3: Remove events whose bandwidth lies outside 3 SDs of an expected value. +ExpectedBandwidth: 100 +BandwidthStandardDeviation: 15 + +# 4: Filter the events for excess activity in their upper and lower buffer zones NeighbourhoodLowerHertzBuffer: 150 NeighbourhoodUpperHertzBuffer: 400 NeighbourhoodDbThreshold: 6.0 diff --git a/src/AnalysisPrograms/Recognizers/Birds/BotaurusPoiciloptilus.cs b/src/AnalysisPrograms/Recognizers/Birds/BotaurusPoiciloptilus.cs index 02a868fde..3faaf89c8 100644 --- a/src/AnalysisPrograms/Recognizers/Birds/BotaurusPoiciloptilus.cs +++ b/src/AnalysisPrograms/Recognizers/Birds/BotaurusPoiciloptilus.cs @@ -88,50 +88,33 @@ public override RecognizerResults Recognize( outputDirectory, imageWidth); + var count = combinedResults.NewEvents.Count; + BitternLog.Debug($"Event count before post-processing = {count}."); + if (combinedResults.NewEvents.Count == 0) + { + return combinedResults; + } + // ################### POST-PROCESSING of EVENTS ################### // Following two commented lines are different ways of casting lists. //var newEvents = spectralEvents.Cast().ToList(); //var spectralEvents = events.Select(x => (SpectralEvent)x).ToList(); - if (combinedResults.NewEvents.Count == 0) - { - BitternLog.Debug($"Return zero events."); - return combinedResults; - } + //NOTE: + // The generic recognizer does some post-processing of events prior to returning the list of combined events. + // Its post-processing steps are determined by config settings. + // Generic post processing step 1: Combine overlapping events. + // Generic post processing step 2: Combine possible syllable sequences and filter on excess syllable count. + // Generic post processing step 3: Remove events whose bandwidth is too small or large. + // Generic post processing step 4: Remove events that have excessive noise in their side-bands. - // 1: Filter the events for duration in seconds - var minimumEventDuration = 0.5; - var maximumEventDuration = 2.0; - if (genericConfig.CombinePossibleSyllableSequence) + // Post-processing steps are put here: + + if (combinedResults.NewEvents.Count == 0) { - minimumEventDuration = 2.0; - maximumEventDuration = 10.0; + BitternLog.Debug($"Zero events after post-processing."); } - combinedResults.NewEvents = EventExtentions.FilterOnDuration(combinedResults.NewEvents, minimumEventDuration, maximumEventDuration); - BitternLog.Debug($"Event count after filtering on duration = {combinedResults.NewEvents.Count}"); - - // 2: Filter the events for bandwidth in Hertz - double average = 100; - double sd = 15; - double sigmaThreshold = 3.0; - combinedResults.NewEvents = EventExtentions.FilterOnBandwidth(combinedResults.NewEvents, average, sd, sigmaThreshold); - BitternLog.Debug($"Event count after filtering on bandwidth = {combinedResults.NewEvents.Count}"); - - // 3: Filter on COMPONENT COUNT in Composite events. - int maxComponentCount = 6; - combinedResults.NewEvents = EventExtentions.FilterEventsOnCompositeContent(combinedResults.NewEvents, maxComponentCount); - BitternLog.Debug($"Event count after filtering on component count = {combinedResults.NewEvents.Count}"); - - // Uncomment the next line when want to obtain the event frequency profiles. - // WriteFrequencyProfiles(chirpEvents); - - //foreach (var ev in whistleEvents) - //{ - // // Calculate frequency profile score for event - // SetFrequencyProfileScore((WhistleEvent)ev); - //} - //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);