Skip to content

Commit

Permalink
Fix AustBittern recognizer test
Browse files Browse the repository at this point in the history
Issue #321 THis recognizer with current config has zero errors on this config where db threshold= 6.0. When threshold db = 3.0 get four FPs.
  • Loading branch information
towsey authored and atruskie committed Jun 12, 2020
1 parent ed5579f commit a9d903e
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,51 +9,63 @@ SegmentDuration: 60
SegmentOverlap: 0

# Each of these profiles will be analyzed
# This profile is required for the species-specific recogniser and must have the current name.
Profiles:
AustBittern: !OnebinTrackParameters
BitternSyllable: !OnebinTrackParameters
ComponentName: Whistle
SpeciesName: BotaurusPoiciloptilus
FrameSize: 512
FrameStep: 256
WindowFunction: HANNING
BgNoiseThreshold: 0.0
#BgNoiseThreshold: 0.0
# min and max of the freq band to search
MinHertz: 100
MaxHertz: 200
MinDuration: 0.3
MaxDuration: 1.0
DecibelThreshold: 3.0
DecibelThreshold: 6.0

#Combine each pair of Boobook syllables as one event
#CombineProximalSimilarEvents: false
#################### POST-PROCESSING of EVENTS ###################

# A: First post-processing steps are to combine overlapping/proximal/sequential events
# 1: Combine overlapping events
#CombineOverlappingEvents: false

# 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: 100
SyllableHertzGap: 35

# Common settings
#Standard: &STANDARD
#EventThreshold: 0.2
#BgNoiseThreshold: 3.0
# B: Filter the events for excess activity in their upper and lower buffer zones
LowerHertzBuffer: 150
UpperHertzBuffer: 400

# This notation means the a profile has all of the settings that the Standard profile has,
# however, the DctDuration parameter has been overridden.
# <<: *STANDARD
# DctDuration: 0.3

################################################################################
# Save intermediate file options (case-sensitive): [False/Never | True/Always | WhenEventsDetected]
# C: Options to save results files
# 4: Available options for saving data files (case-sensitive): [False/Never | True/Always | WhenEventsDetected]
SaveIntermediateWavFiles: Never
SaveIntermediateCsvFiles: false

# Save spectrogram images: available options (case-sensitive): [False/Never | True/Always | WhenEventsDetected]
# Available options (case-sensitive): [False/Never | True/Always | WhenEventsDetected]
# "True" is useful when debugging but "WhenEventsDetected" is required for operational use.

# 5: Available options for saving
#SaveSonogramImages: True
SaveSonogramImages: WhenEventsDetected

# DisplayCsvImage is obsolete - ensure it remains set to: false
DisplayCsvImage: false
## End section for AnalyzeLongRecording

# Other config files to reference
HighResolutionIndicesConfig: "../Towsey.Acoustic.HiResIndicesForRecognisers.yml"

################################################################################
# Common settings
#Standard: &STANDARD
#EventThreshold: 0.2
#BgNoiseThreshold: 3.0

# This notation means the a profile has all of the settings that the Standard profile has,
# however, the DctDuration parameter has been overridden.
# <<: *STANDARD
# DctDuration: 0.3
...
85 changes: 71 additions & 14 deletions src/AnalysisPrograms/Recognizers/Birds/BotaurusPoiciloptilus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,9 @@ namespace AnalysisPrograms.Recognizers
using Acoustics.Shared.ConfigFile;
using AnalysisBase;
using AnalysisPrograms.Recognizers.Base;
using AudioAnalysisTools;
using AudioAnalysisTools.DSP;
using AudioAnalysisTools.Events;
using AudioAnalysisTools.Events.Types;
using AudioAnalysisTools.Indices;
using AudioAnalysisTools.StandardSpectrograms;
using AudioAnalysisTools.WavTools;
using log4net;
using SixLabors.ImageSharp;
Expand All @@ -29,7 +26,7 @@ namespace AnalysisPrograms.Recognizers
/// <summary>
/// A recognizer for the Australasian Bittern, Botaurus poiciloptilus, https://en.wikipedia.org/wiki/Australasian_bittern.
/// The Australasian bittern, also known as the brown bittern or matuku hūrepo, is a large bird in the heron family Ardeidae.
/// A secretive bird with a distinctive booming call, it is more often heard than seen.
/// A secretive bird with a distinctive, low frequency booming call, it is more often heard than seen.
/// Australasian bitterns are endangered in both Australia and New Zealand.
/// </summary>
internal class BotaurusPoiciloptilus : RecognizerBase
Expand Down Expand Up @@ -91,42 +88,102 @@ public override RecognizerResults Recognize(
outputDirectory,
imageWidth);

// DO POST-PROCESSING of EVENTS
var events = combinedResults.NewEvents;

// ################### POST-PROCESSING of EVENTS ###################
// Following two commented lines are different ways of casting lists.
//var newEvents = spectralEvents.Cast<EventCommon>().ToList();
//var spectralEvents = events.Select(x => (SpectralEvent)x).ToList();
List<EventCommon> newEvents;

// 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);
//}

if (combinedResults.NewEvents.Count == 0)
{
BitternLog.Debug($"Return zero events.");
return combinedResults;
}

var newEvents = combinedResults.NewEvents;

// NOTE: If the dB threshold is set low, may get lots of little events.
if (genericConfig.CombinePossibleSyllableSequence)
{
// Convert events to spectral events for combining of possible sequences.
var spectralEvents = events.Cast<SpectralEvent>().ToList();
// Can also use this parameter to combine events that are in the upper or lower neighbourhood.
// Such combinations will increase bandwidth of the event and this property can be used later to weed out unlikely events..
var spectralEvents = newEvents.Cast<SpectralEvent>().ToList();
var startDiff = genericConfig.SyllableStartDifference;
var hertzDiff = genericConfig.SyllableHertzGap;
newEvents = CompositeEvent.CombineProximalEvents(spectralEvents, TimeSpan.FromSeconds(startDiff), (int)hertzDiff);
BitternLog.Debug($"Event count after combining proximals = {combinedResults.NewEvents.Count}");
}

// Get the Bittern syllable config.
const string profileName = "BitternSyllable";
var configuration = (BotaurusPoiciloptilusConfig)genericConfig;
var whistleConfig = (OnebinTrackParameters)configuration.Profiles[profileName];

// 4: Filter events on the amount of acoustic activity in their upper and lower neighbourhoods - their buffer zone.
// The idea is that an unambiguous event should have some acoustic space above and below.
// The filter requires that the average acoustic activity in each frame and bin of the upper and lower buffer zones should not exceed the user specified decibel threshold.
// The bandwidth of these two neighbourhoods is determined by the following parameters.
// ########## These parameters could be specified by user in config.yml file.
var upperHertzBuffer = 400;
var lowerHertzBuffer = 150;

// The decibel threshold is currently set 5/6ths of the user specified threshold.
// THIS IS TO BE WATCHED. IT MAY PROVE TO BE INAPPROPRIATE TO HARD-CODE.
// Want the activity in buffer zones to be "somewhat" less than the user-defined threshold.
var neighbourhoodDbThreshold = whistleConfig.DecibelThreshold.Value * 0.8333;

if (upperHertzBuffer > 0 || lowerHertzBuffer > 0)
{
var spectralEvents2 = combinedResults.NewEvents.Cast<SpectralEvent>().ToList();
combinedResults.NewEvents = EventExtentions.FilterEventsOnNeighbourhood(
spectralEvents2,
combinedResults.Sonogram,
lowerHertzBuffer,
upperHertzBuffer,
segmentStartOffset,
neighbourhoodDbThreshold);

BitternLog.Debug($"Event count after filtering on neighbourhood = {combinedResults.NewEvents.Count}");
}
else

if (combinedResults.NewEvents.Count == 0)
{
newEvents = events;
BitternLog.Debug($"Return zero events.");
return combinedResults;
}

//filter the events for duration in seconds
// 5: 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}");

// 6: Filter the events for duration in seconds
var minimumEventDuration = 0.5;
var maximumEventDuration = 2.0;
if (genericConfig.CombinePossibleSyllableSequence)
{
minimumEventDuration = 2.0;
maximumEventDuration = 10.0;
}

combinedResults.NewEvents = EventExtentions.FilterOnDuration(newEvents, minimumEventDuration, maximumEventDuration);
BitternLog.Debug($"Event count after filtering on duration = {combinedResults.NewEvents.Count}");

double average = 365;
double sd = 22;
// 7: 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}");

//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.
Expand Down
3 changes: 1 addition & 2 deletions src/AnalysisPrograms/Recognizers/Birds/NinoxBoobook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ namespace AnalysisPrograms.Recognizers
using AudioAnalysisTools.Events;
using AudioAnalysisTools.Events.Types;
using AudioAnalysisTools.Indices;
using AudioAnalysisTools.StandardSpectrograms;
using AudioAnalysisTools.WavTools;
using log4net;
using SixLabors.ImageSharp;
Expand Down Expand Up @@ -92,7 +91,7 @@ public override RecognizerResults Recognize(
outputDirectory,
imageWidth);

// ################### DO POST-PROCESSING of EVENTS ###################
// ################### POST-PROCESSING of EVENTS ###################
// Following two commented lines are different ways of casting lists.
//var newEvents = spectralEvents.Cast<EventCommon>().ToList();
//var spectralEvents = events.Select(x => (SpectralEvent)x).ToList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ public void TestRecognizer()
var onlyEvent = (CompositeEvent)events[0];

Assert.AreEqual(5.12, onlyEvent.EventStartSeconds);
Assert.AreEqual(12.26, onlyEvent.EventEndSeconds);
Assert.AreEqual(12.256, onlyEvent.EventEndSeconds);
Assert.AreEqual(105, onlyEvent.LowFrequencyHertz);
Assert.AreEqual(180, onlyEvent.HighFrequencyHertz);
Assert.AreEqual(21.7, onlyEvent.Score);
Assert.AreEqual(0.95, onlyEvent.ScoreNormalized);
Assert.AreEqual(21.72, onlyEvent.Score, 0.01);
Assert.AreEqual(0.947, onlyEvent.ScoreNormalized, 0.01);
}
}
}

0 comments on commit a9d903e

Please sign in to comment.