From b15f22fa6b7e3f9b2924077121586f6794a6922d Mon Sep 17 00:00:00 2001 From: Michael Towsey Date: Mon, 28 Jun 2021 16:52:52 +1000 Subject: [PATCH] Set up new Koala mark3 call recognizer. Issue #500: 1: Set up new Koala mark3 call recognizer and associated test file. 2: Remove previous test file that was no longer needed. 3: Set up new config file for the test recording. 4: The test recording is temporary - just to get started. --- .../Towsey.PhascolarctosCinereusMark3.yml | 79 +++++++++++++++---- .../Recognizers/PhascolarctosCinereusMark3.cs | 34 ++++++-- .../Recognizers/KoalaMark3Tests.cs | 35 ++++---- .../Recognizers/KoalaV3Tests.cs | 78 ------------------ 4 files changed, 109 insertions(+), 117 deletions(-) delete mode 100644 tests/Acoustics.Test/AnalysisPrograms/Recognizers/KoalaV3Tests.cs diff --git a/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.PhascolarctosCinereusMark3.yml b/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.PhascolarctosCinereusMark3.yml index df4156398..25b5c1411 100644 --- a/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.PhascolarctosCinereusMark3.yml +++ b/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.PhascolarctosCinereusMark3.yml @@ -8,46 +8,95 @@ SegmentDuration: 60 # SegmentOverlap: units=seconds; SegmentOverlap: 0 +CommonParameters: &common_parameters + SpeciesName: PhascolarctosCinereus + WindowFunction: HANNING + NoiseReductionType: Standard + BgNoiseThreshold: 0.0 + + # Each of these profiles will be analyzed Profiles: + # This profile detections oscillation in the inhale. KoalaOsc: !OscillationParameters + <<: *common_parameters + ComponentName: Oscillation - SpeciesName: PhascolarctosCinereus FrameSize: 512 FrameStep: 256 - WindowFunction: HANNING - BgNoiseThreshold: 0.0 # min and max of the freq band to search - MinHertz: 250 + MinHertz: 200 MaxHertz: 800 # Min and max durations for the length of a true event (seconds). - MinDuration: 0.5 - MaxDuration: 2.5 + MinDuration: 0.2 + MaxDuration: 3.5 # duration of DCT in seconds # this cannot be too long because the oscillations are not constant. - DctDuration: 0.30 + #DctDuration: 0.30 + DctDuration: 0.2 # minimum acceptable amplitude of a DCT coefficient DctThreshold: 0.5 # OSCILLATIONS PER SECOND: ignore oscillation rates below the min & above the max threshold - MinOcilFreq: 20 - MaxOcilFreq: 55 + MinOscillationFrequency: 20 + MaxOscillationFrequency: 60 # Event threshold - Determines FP / FN trade-off for events. EventThreshold: 0.2 + DecibelThresholds: + - 6.0 + +#################### POST-PROCESSING of EVENTS ################### + +PostProcessing: + PostProcessInDecibelGroups: false + +# # 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. + +# # 1: Combine overlapping events + CombineOverlappingEvents: false + + # 2: Combine possible syllable sequences +# SyllableSequence: +# SyllableStartDifference: 1.2 +# SyllableHertzGap: 2400 + # FilterSyllableSequence: true + # SyllableMaxCount: 3 + # ExpectedPeriod: 0.1 + +# # # 3: Remove events whose duration lies outside 3 SDs of an expected value. +# Duration: +# ExpectedDuration: 2.5 +# DurationStandardDeviation: 0.6 +# # 4: Remove events whose bandwidth lies outside 3 SDs of an expected value. +# # Bandwidth: +# ExpectedBandwidth: 280 +# BandwidthStandardDeviation: 40 + +# # 5: Filter the events for excess activity in their sidebands, i.e. upper and lower buffer zones +# SidebandActivity: +# LowerHertzBuffer: 150 +# UpperHertzBuffer: 400 +# MaxAverageSidebandDecibels: 3.0 + RemoveEnclosedEvents: false ################################################################################ -# Save intermediate file options (case-sensitive): [False/Never | True/Always | WhenEventsDetected] -SaveIntermediateWavFiles: Never -SaveIntermediateCsvFiles: false -# Save spectrogram images: available options (case-sensitive): [False/Never | True/Always | WhenEventsDetected] +# Options to save results files +# 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: Always #SaveSonogramImages: WhenEventsDetected +# Save intermediate file options (case-sensitive): [False/Never | True/Always | WhenEventsDetected] +SaveIntermediateWavFiles: Never +SaveIntermediateCsvFiles: false + # DisplayCsvImage is obsolete - ensure it remains set to: false DisplayCsvImage: false -## End section for AnalyzeLongRecording # Other config files to reference IndexPropertiesConfig: ".\\IndexPropertiesConfig.yml" diff --git a/src/AnalysisPrograms/Recognizers/PhascolarctosCinereusMark3.cs b/src/AnalysisPrograms/Recognizers/PhascolarctosCinereusMark3.cs index 241821214..d7f9b2c38 100644 --- a/src/AnalysisPrograms/Recognizers/PhascolarctosCinereusMark3.cs +++ b/src/AnalysisPrograms/Recognizers/PhascolarctosCinereusMark3.cs @@ -4,18 +4,17 @@ namespace AnalysisPrograms.Recognizers { + using System; + using System.IO; + using System.Linq; + using System.Reflection; + using System.Runtime.CompilerServices; using Acoustics.Shared.ConfigFile; using AnalysisBase; using AnalysisPrograms.Recognizers.Base; using AudioAnalysisTools.Indices; using AudioAnalysisTools.WavTools; using log4net; - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Reflection; - using System.Text; using static AnalysisPrograms.Recognizers.GenericRecognizer; /// @@ -77,14 +76,33 @@ internal class PhascolarctosCinereusMark3 : RecognizerBase public override string Author => "Towsey"; - public override string SpeciesName => "PhascolarctosCinereus"; + public override string SpeciesName => "PhascolarctosCinereusMark3"; - public override string Description => "Detects male Koala bellows. This is Koala Mark 3"; + public override string Description => "Detects male Koala bellows. This is Koala Recognizer, Mark 3"; public override string CommonName => "Koala"; public override Status Status => Status.InDevelopment; + public override AnalyzerConfig ParseConfig(FileInfo file) + { + RuntimeHelpers.RunClassConstructor(typeof(KoalaConfig3).TypeHandle); + var config = ConfigFile.Deserialize(file); + + // validation of configs can be done here + GenericRecognizer.ValidateProfileTagsMatchAlgorithms(config.Profiles, file); + + // This call sets a restriction so that only one generic algorithm is used. + // CHANGE this to accept multiple generic algorithms as required. + //if (result.Profiles.SingleOrDefault() is ForwardTrackParameters) + if (config.Profiles?.Count == 1 && config.Profiles.First().Value is OscillationParameters) + { + return config; + } + + throw new ConfigFileException("Koala Recognizer Mark3 expects one and only one Oscillation algorithm.", file); + } + /// /// This method is called once per segment. Segments are typically one-minute duration. /// diff --git a/tests/Acoustics.Test/AnalysisPrograms/Recognizers/KoalaMark3Tests.cs b/tests/Acoustics.Test/AnalysisPrograms/Recognizers/KoalaMark3Tests.cs index ee3e88cf3..328fdabec 100644 --- a/tests/Acoustics.Test/AnalysisPrograms/Recognizers/KoalaMark3Tests.cs +++ b/tests/Acoustics.Test/AnalysisPrograms/Recognizers/KoalaMark3Tests.cs @@ -1,4 +1,4 @@ -// +// // All code in this file and all associated files are the copyright and property of the QUT Ecoacoustics Research Group (formerly MQUTeR, and formerly QUT Bioacoustics Research Group). // @@ -8,14 +8,17 @@ namespace Acoustics.Test.AnalysisPrograms.Recognizers using System.IO; using Acoustics.Test.TestHelpers; using global::AnalysisPrograms.Recognizers; + using global::AudioAnalysisTools; + using global::AudioAnalysisTools.Events; using global::AudioAnalysisTools.Events.Types; using global::AudioAnalysisTools.WavTools; using Microsoft.VisualStudio.TestTools.UnitTesting; + // [Ignore("Currently failing but also this work has not yet been implemented")] + /// /// Species name = Koala = Botaurus poiciloptilus. /// Recognizer class = Phascolarctos cinereus.cs. - /// [Ignore("Currently failing but also this work has not yet been implemented")] /// [TestClass] public class KoalaMark3Tests : OutputDirectoryTest @@ -26,7 +29,7 @@ public class KoalaMark3Tests : OutputDirectoryTest //private static readonly FileInfo TestAsset = PathHelper.ResolveAsset("Recordings", "koala.wav"); private static readonly FileInfo TestAsset = new FileInfo("C:\\Ecoacoustics\\WavFiles\\KoalaMale\\Jackaroo_20080715-103940.wav"); private static readonly FileInfo ConfigFile = PathHelper.ResolveConfigFile("RecognizerConfigFiles", "Towsey.PhascolarctosCinereusMark3.yml"); - private static readonly PhascolarctosCinereus Recognizer = new PhascolarctosCinereus(); + private static readonly PhascolarctosCinereusMark3 Recognizer = new PhascolarctosCinereusMark3(); //NOTE: If testing recording at its original sample-rate, then use line below. //private static readonly AudioRecording Recording = new AudioRecording(TestAsset); @@ -35,7 +38,7 @@ public class KoalaMark3Tests : OutputDirectoryTest // as in the TestRecognizer() method below. [TestMethod] - public void TestRecognizer() + public void TestKoala3Recognizer() { var config = Recognizer.ParseConfig(ConfigFile); int resampleRate = config.ResampleRate.Value; @@ -45,7 +48,7 @@ public void TestRecognizer() var results = Recognizer.Recognize( audioRecording: recording, - config: config, + configuration: config, segmentStartOffset: TimeSpan.Zero, getSpectralIndexes: null, outputDirectory: this.TestOutputDirectory, @@ -59,21 +62,21 @@ public void TestRecognizer() this.SaveTestOutput( outputDirectory => GenericRecognizer.SaveDebugSpectrogram(results, null, outputDirectory, Recognizer.SpeciesName)); - Assert.AreEqual(1, events.Count); + Assert.AreEqual(12, events.Count); Assert.IsNull(scoreTrack); - Assert.AreEqual(1, plots.Count); - Assert.AreEqual(938, sonogram.FrameCount); + Assert.AreEqual(2, plots.Count); + //Assert.AreEqual(938, sonogram.FrameCount); - Assert.IsInstanceOfType(events[0], typeof(CompositeEvent)); + Assert.IsInstanceOfType(events[0], typeof(OscillationEvent)); - var onlyEvent = (CompositeEvent)events[0]; + var ev = (SpectralEvent)events[0]; - Assert.AreEqual(5.12, onlyEvent.EventStartSeconds); - Assert.AreEqual(12.26, 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(5.12, ev.EventStartSeconds); + Assert.AreEqual(12.26, ev.EventEndSeconds); + Assert.AreEqual(105, ev.LowFrequencyHertz); + Assert.AreEqual(180, ev.HighFrequencyHertz); + Assert.AreEqual(21.7, ev.Score); + Assert.AreEqual(0.95, ev.ScoreNormalized); } } } \ No newline at end of file diff --git a/tests/Acoustics.Test/AnalysisPrograms/Recognizers/KoalaV3Tests.cs b/tests/Acoustics.Test/AnalysisPrograms/Recognizers/KoalaV3Tests.cs deleted file mode 100644 index bfde35615..000000000 --- a/tests/Acoustics.Test/AnalysisPrograms/Recognizers/KoalaV3Tests.cs +++ /dev/null @@ -1,78 +0,0 @@ -// -// All code in this file and all associated files are the copyright and property of the QUT Ecoacoustics Research Group (formerly MQUTeR, and formerly QUT Bioacoustics Research Group). -// - -namespace Acoustics.Test.AnalysisPrograms.Recognizers -{ - using System; - using System.IO; - using Acoustics.Test.TestHelpers; - using global::AnalysisPrograms.Recognizers; - using global::AudioAnalysisTools.Events.Types; - using global::AudioAnalysisTools.WavTools; - using Microsoft.VisualStudio.TestTools.UnitTesting; - - /// - /// Species name = Koala = Botaurus poiciloptilus. - /// Recognizer class = Phascolarctos cinereus.cs. - /// - [TestClass] - [Ignore("Currently failing but also this work has not yet been implemented")] - public class KoalaV3Tests : OutputDirectoryTest - { - /// - /// The canonical recording used for this recognizer is #############################. - /// - private static readonly FileInfo TestAsset = PathHelper.ResolveAsset("Recordings", "koala.wav"); - private static readonly FileInfo ConfigFile = PathHelper.ResolveConfigFile("RecognizerConfigFiles", "Towsey.PhascolarctosCinereus.v3.yml"); - private static readonly PhascolarctosCinereus Recognizer = new PhascolarctosCinereus(); - - //NOTE: If testing recording at its original sample-rate, then use line below. - //private static readonly AudioRecording Recording = new AudioRecording(TestAsset); - - // If needing to resample, then must call AudioRecording.GetAudioRecording(TestAsset, resampleRate, opDir, opFileName); - // as in the TestRecognizer() method below. - - [TestMethod] - public void TestRecognizer() - { - var config = Recognizer.ParseConfig(ConfigFile); - int resampleRate = config.ResampleRate.Value; - string opDir = this.TestOutputDirectory.FullName; - string opFileName = "tempFile"; - var recording = AudioRecording.GetAudioRecording(TestAsset, resampleRate, opDir, opFileName); - - var results = Recognizer.Recognize( - audioRecording: recording, - config: config, - segmentStartOffset: TimeSpan.Zero, - getSpectralIndexes: null, - outputDirectory: this.TestOutputDirectory, - imageWidth: null); - - var events = results.NewEvents; - var scoreTrack = results.ScoreTrack; - var plots = results.Plots; - var sonogram = results.Sonogram; - - this.SaveTestOutput( - outputDirectory => GenericRecognizer.SaveDebugSpectrogram(results, null, outputDirectory, Recognizer.SpeciesName)); - - Assert.AreEqual(1, events.Count); - Assert.IsNull(scoreTrack); - Assert.AreEqual(1, plots.Count); - Assert.AreEqual(938, sonogram.FrameCount); - - Assert.IsInstanceOfType(events[0], typeof(CompositeEvent)); - - var onlyEvent = (CompositeEvent)events[0]; - - Assert.AreEqual(5.12, onlyEvent.EventStartSeconds); - Assert.AreEqual(12.26, onlyEvent.EventEndSeconds); - Assert.AreEqual(105, onlyEvent.LowFrequencyHertz); - Assert.AreEqual(180, onlyEvent.HighFrequencyHertz); - Assert.AreEqual(21.7, onlyEvent.Score); - Assert.AreEqual(0.95, onlyEvent.ScoreNormalized); - } - } -} \ No newline at end of file