diff --git a/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.AnthusNovaeseelandiae.yml b/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.AnthusNovaeseelandiae.yml
index e557d3e22..c6e29a67a 100644
--- a/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.AnthusNovaeseelandiae.yml
+++ b/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.AnthusNovaeseelandiae.yml
@@ -21,37 +21,55 @@ Profiles:
MinHertz: 2000
MaxHertz: 7000
MinBandwidthHertz: 500
- MaxBandwidthHertz: 5000
- DecibelThreshold: 9.0
+ MaxBandwidthHertz: 6000
+ 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.25
-SyllableHertzGap: 3000
+ # 1: Combine overlapping events
+ CombineOverlappingEvents: true
-# B: Filter the events for excess activity in their upper and lower buffer zones
-NeighbourhoodLowerHertzBuffer: 200
-NeighbourhoodUpperHertzBuffer: 0
-NeighbourhoodDbThreshold: 9.0
+ # 2: Combine possible syllable sequences
+ SyllableSequence:
+ CombinePossibleSyllableSequence: false
+ SyllableStartDifference: 0.25
+ SyllableHertzGap: 3000
+ FilterSyllableSequence: false
+ SyllableMaxCount: 0
+ ExpectedPeriod: 0
-# C: Options to save results files
-# 4: Available options for saving spectrograms (case-sensitive): [False/Never | True/Always | WhenEventsDetected]
+ # 3: Remove events whose bandwidth lies outside 3 SDs of an expected value.
+ Bandwidth:
+ ExpectedBandwidth: 4000
+ BandwidthStandardDeviation: 400
+
+ # 4: Filter the events for excess activity in their sidebands, i.e. upper and lower buffer zones
+ SidebandActivity:
+ LowerHertzBuffer: 0 #200
+ UpperHertzBuffer: 0
+ DecibelBuffer: 0.0 #9.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/AnthusNovaeseelandiae.cs b/src/AnalysisPrograms/Recognizers/Birds/AnthusNovaeseelandiae.cs
index 6ef6a49eb..b0b558134 100644
--- a/src/AnalysisPrograms/Recognizers/Birds/AnthusNovaeseelandiae.cs
+++ b/src/AnalysisPrograms/Recognizers/Birds/AnthusNovaeseelandiae.cs
@@ -92,97 +92,11 @@ public override RecognizerResults Recognize(
outputDirectory,
imageWidth);
- // ################### POST-PROCESSING of EVENTS ###################
-
- if (combinedResults.NewEvents.Count == 0)
- {
- PipitLog.Debug($"Return zero events.");
- return combinedResults;
- }
-
- // 1: Filter the events for duration in seconds
- var minimumEventDuration = 0.1;
- var maximumEventDuration = 0.4;
- combinedResults.NewEvents = EventFilters.FilterOnDuration(combinedResults.NewEvents, minimumEventDuration, maximumEventDuration);
- PipitLog.Debug($"Event count after filtering on duration = {combinedResults.NewEvents.Count}");
-
- // 2: Filter the events for bandwidth in Hertz
- double average = 3500;
- double sd = 600;
- double sigmaThreshold = 3.0;
- combinedResults.NewEvents = EventFilters.FilterOnBandwidth(combinedResults.NewEvents, average, sd, sigmaThreshold);
- PipitLog.Debug($"Event count after filtering on bandwidth = {combinedResults.NewEvents.Count}");
-
- combinedResults.NewEvents = FilterEventsOnFrequencyProfile(combinedResults.NewEvents);
+ // ################### YOU CAN PUT ADDITIONAL POST-PROCESSING CODE HERE ###################
return combinedResults;
}
- ///
- /// This method assumes that the only events of interest are composite events.
- ///
- /// THe current list of events.
- /// A list of composite events.
- public static List FilterEventsOnFrequencyProfile(List events)
- {
- if (events.Count == 0)
- {
- return events;
- }
-
- // select only the composite events.
- //var compositeEvents = events.Select(x => (CompositeEvent)x).ToList();
- var (compositeEvents, others) = events.FilterForEventType();
-
- if (compositeEvents == null || compositeEvents.Count == 0)
- {
- return events;
- }
-
- // get the composite track for each composite event.
- var returnEvents = new List();
- foreach (var ev in compositeEvents)
- {
- var componentEvents = ev.ComponentEvents.Cast();
- var points = EventExtentions.GetCompositeTrack(componentEvents).ToArray();
-
- // Uncomment this line when want to see the composite track profile.
- //WriteFrequencyProfile(points);
-
- // For Pipit require minimum of four frames duration.
- var length = points.Length;
- if (length < 4)
- {
- continue;
- }
-
- // Only select events having strong downward slope in spectrogram.
- var avFirstTwoEvents = (points[0].Hertz.Minimum + points[0].Hertz.Minimum) / 2;
- var avLastTwoEvents = (points[length - 1].Hertz.Minimum + points[length - 2].Hertz.Minimum) / 2;
- if (avFirstTwoEvents - avLastTwoEvents > 500)
- {
- returnEvents.Add(ev);
- }
- }
-
- return returnEvents;
- }
-
- public static void WriteFrequencyProfile(ISpectralPoint[] points)
- {
- if (points != null)
- {
- var str = $"Track({points[0].Seconds.Minimum:F2}):";
-
- foreach (var point in points)
- {
- str += $" {point.Hertz.Minimum},";
- }
-
- Console.WriteLine(str);
- }
- }
-
/*
///
/// Summarize your results. This method is invoked exactly once per original file.
diff --git a/tests/Acoustics.Test/AnalysisPrograms/Recognizers/AustralPipitTests.cs b/tests/Acoustics.Test/AnalysisPrograms/Recognizers/AustralPipitTests.cs
index dfb6bddc0..d7427911a 100644
--- a/tests/Acoustics.Test/AnalysisPrograms/Recognizers/AustralPipitTests.cs
+++ b/tests/Acoustics.Test/AnalysisPrograms/Recognizers/AustralPipitTests.cs
@@ -58,30 +58,28 @@ public void TestRecognizer()
this.SaveTestOutput(
outputDirectory => GenericRecognizer.SaveDebugSpectrogram(results, null, outputDirectory, Recognizer.SpeciesName));
- //this test returns two false-positives with the current component parameters.
- Assert.AreEqual(7, events.Count);
+ Assert.AreEqual(5, events.Count);
Assert.IsNull(scoreTrack);
- Assert.AreEqual(1, plots.Count);
+ Assert.AreEqual(3, plots.Count);
Assert.AreEqual(1874, sonogram.FrameCount);
- Assert.IsInstanceOfType(events[2], typeof(CompositeEvent));
- var ev = (CompositeEvent)events[2];
-
// events[2] should be a composite event.
- Assert.AreEqual(16.656, ev.EventStartSeconds);
- Assert.AreEqual(17.008, ev.EventEndSeconds);
- Assert.AreEqual(3596, ev.BandWidthHertz);
+ var ev = (CompositeEvent)events[2];
+ Assert.IsInstanceOfType(events[2], typeof(CompositeEvent));
+ Assert.AreEqual(22.0000000000000, ev.EventStartSeconds, TestHelper.AllowedDelta);
+ Assert.AreEqual(22.3680000000000, ev.EventEndSeconds, TestHelper.AllowedDelta);
+ Assert.AreEqual(4743, ev.BandWidthHertz);
- // This event should contain 5 component events
+ // This event should contain 13 component events
var componentEvents = ev.ComponentEvents;
- Assert.AreEqual(5, componentEvents.Count);
+ Assert.AreEqual(13, componentEvents.Count);
// This tests that the component tracks are correctly combined.
//This can also be tested somewhere else, starting with just the comosite event in json file.
var points = EventExtentions.GetCompositeTrack(componentEvents.Cast()).ToArray();
- Assert.AreEqual(16.672, points[1].Seconds.Minimum);
- Assert.AreEqual(5425, points[1].Hertz.Minimum);
- Assert.AreEqual(23.712453258003087, points[1].Value, TestHelper.AllowedDelta);
+ Assert.AreEqual(22.0160000000000, points[1].Seconds.Minimum, TestHelper.AllowedDelta);
+ Assert.AreEqual(5456, points[1].Hertz.Minimum);
+ Assert.AreEqual(23.13758005922, points[1].Value, TestHelper.AllowedDelta);
}
}
}