diff --git a/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.NinoxStrenua.yml b/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.NinoxStrenua.yml index 6165a1fc7..317bf9c7d 100644 --- a/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.NinoxStrenua.yml +++ b/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.NinoxStrenua.yml @@ -22,36 +22,41 @@ Profiles: MaxHertz: 600 MinDuration: 0.3 MaxDuration: 1.5 - DecibelThreshold: 12.0 + DecibelThreshold: 18.0 #################### POST-PROCESSING of EVENTS ################### -# A: First post-processing steps are to combine overlapping/proximal/sequential events -# 1: Combine overlapping events +# 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: false +# 2: Combine syllable sequences as one event +CombinePossibleSyllableSequence: true SyllableStartDifference: 1.5 SyllableHertzGap: 300 +SyllableMaxCount: 6 -# 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: 150 +BandwidthStandardDeviation: 15 + +# 4: Filter the events for excess activity in their sidebands, i.e. upper and lower buffer zones NeighbourhoodLowerHertzBuffer: 100 -NeighbourhoodUpperHertzBuffer: 300 -NeighbourhoodDbThreshold: 12.0 +NeighbourhoodUpperHertzBuffer: 600 +#NeighbourhoodDecibelBuffer: 18.0 # use this value if not combining sequences +NeighbourhoodDecibelBuffer: 9.0 # use this value when combining sequences -# C: Options to save results files -# 4: Available options for saving spectrograms (case-sensitive): [False/Never | True/Always | WhenEventsDetected] +# Options to save results files +# 5: 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] +# 6: 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 +# 7: DisplayCsvImage is obsolete - ensure it remains set to: false DisplayCsvImage: false ## End section for AnalyzeLongRecording diff --git a/src/AnalysisPrograms/Recognizers/Birds/NinoxStrenua.cs b/src/AnalysisPrograms/Recognizers/Birds/NinoxStrenua.cs index 3fc0c6e3e..68b1ce83e 100644 --- a/src/AnalysisPrograms/Recognizers/Birds/NinoxStrenua.cs +++ b/src/AnalysisPrograms/Recognizers/Birds/NinoxStrenua.cs @@ -93,6 +93,18 @@ public override RecognizerResults Recognize( //var newEvents = spectralEvents.Cast().ToList(); //var spectralEvents = events.Select(x => (SpectralEvent)x).ToList(); + //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. + + // The following post processing steps are specific for this species recognizer: + // 1: remove events that have wrong length. This is necssary if events have been combined in post-processing steps 1 and 2 above. + // 2: filter chirp events based on their frequency profiles. + if (combinedResults.NewEvents.Count == 0) { PowerfulOwlLog.Debug($"Return zero events."); @@ -102,32 +114,20 @@ public override RecognizerResults Recognize( // 1: Filter the events for duration in seconds // Get the PowerfulOwl Syllable config. const string profileName = "StrenuaSyllable"; - var configuration = (NinoxStrenuaConfig)genericConfig; - var chirpConfig = (ForwardTrackParameters)configuration.Profiles[profileName]; + var chirpConfig = (ForwardTrackParameters)genericConfig.Profiles[profileName]; var minimumEventDuration = chirpConfig.MinDuration; var maximumEventDuration = chirpConfig.MaxDuration; if (genericConfig.CombinePossibleSyllableSequence) { + int maxComponentCount = genericConfig.SyllableMaxCount; minimumEventDuration *= 2.0; - maximumEventDuration *= 1.5; + maximumEventDuration *= maxComponentCount; } combinedResults.NewEvents = EventExtentions.FilterOnDuration(combinedResults.NewEvents, minimumEventDuration.Value, maximumEventDuration.Value); PowerfulOwlLog.Debug($"Event count after filtering on duration = {combinedResults.NewEvents.Count}"); - // 2: Filter the events for bandwidth in Hertz - double average = 400; - double sd = 50; - double sigmaThreshold = 3.0; - //combinedResults.NewEvents = EventExtentions.FilterOnBandwidth(combinedResults.NewEvents, average, sd, sigmaThreshold); - PowerfulOwlLog.Debug($"Event count after filtering on bandwidth = {combinedResults.NewEvents.Count}"); - - // 3: Filter on COMPONENT COUNT in Composite events. - int maxComponentCount = 5; - combinedResults.NewEvents = EventExtentions.FilterEventsOnCompositeContent(combinedResults.NewEvents, maxComponentCount); - PowerfulOwlLog.Debug($"Event count after filtering on component count = {combinedResults.NewEvents.Count}"); - - // 4: Pull out the chirp events and calculate their frequency profiles. + // 2: Pull out the chirp events and calculate their frequency profiles. var (chirpEvents, others) = combinedResults.NewEvents.FilterForEventType(); // Uncomment the next line when want to obtain the event frequency profiles.