Skip to content

Commit

Permalink
Finished Generic recognizer and tests
Browse files Browse the repository at this point in the history
- refactored classes according to conventions and added various bits of documentation
- added support for YAML serialization and deserialization of type tags. This allows us to deserialize arrays/maps with variably typed elements.
- added an automatically generated YAML schema for the generic recognizer config
- added a full suite of tests for generic recognizer, including the re-use of algorithms in multiple profiles
- added a hand crafted audio test fixture that made it easy to write said tests

Note: the whistle component and associated test currently fail because @towsey has not completed that algorithm yet.
  • Loading branch information
atruskie committed Jan 28, 2020
1 parent 00086b0 commit 663b9ef
Show file tree
Hide file tree
Showing 22 changed files with 699 additions and 306 deletions.
8 changes: 8 additions & 0 deletions AudioAnalysis.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/ReadSettingsFromFileLevel/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_MEMBERS/@EntryValue">15</s:String>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_BEFORE_SINGLE_LINE_COMMENT/@EntryValue">1</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_ARRAY_INITIALIZER_ELEMENTS_ON_LINE/@EntryValue">1</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_FORMAL_PARAMETERS_ON_LINE/@EntryValue">9999</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_INITIALIZER_ELEMENTS_ON_LINE/@EntryValue">1</s:Int64>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ACCESSORHOLDER_ON_SINGLE_LINE/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/STICK_COMMENT/@EntryValue">False</s:Boolean>


<s:String x:Key="/Default/CodeStyle/CSharpFileLayoutPatterns/Pattern/@EntryValue">&lt;?xml version="1.0" encoding="utf-16"?&gt;&#xD;
&lt;Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"&gt;&#xD;
&lt;TypePattern DisplayName="Non-reorderable types"&gt;&#xD;
Expand Down Expand Up @@ -188,6 +192,7 @@
&lt;/Patterns&gt;</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CSharpUsing/AddImportsToDeepestScope/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CSharpUsing/QualifiedUsingAtNestedScope/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/EditorConfig/EnableStyleCopSupport/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FCONSTANT/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
Expand Down Expand Up @@ -283,11 +288,14 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bioacoustics/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Chromeless/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=dedupe/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=DTMF/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Ecosounds/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ffmpeg/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ffprobe/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=flac/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pteropus/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Redirector/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=resampled/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=spectrograms/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Submatrix/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Anthony/@EntryIndexedValue">True</s:Boolean>
Expand Down
3 changes: 2 additions & 1 deletion src/Acoustics.Shared/Acoustics.Shared.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@
<Compile Include="ConfigFile\ConfigFile.Profiles.cs" />
<Compile Include="ConfigFile\ConfigFileException.cs" />
<Compile Include="ConfigFile\IConfig.cs" />
<Compile Include="ConfigFile\IProfile.cs" />
<Compile Include="ConfigFile\INamedProfiles.cs" />
<Compile Include="ConfigFile\IProfiles.cs" />
<Compile Include="Contracts\Contract.cs" />
<Compile Include="Csv\CsvExtensions.cs" />
<Compile Include="Csv\Csv.cs" />
Expand Down
21 changes: 21 additions & 0 deletions src/Acoustics.Shared/ConfigFile/INamedProfiles.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// <copyright file="INamedProfiles.cs" company="QutEcoacoustics">
// 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).
// </copyright>

namespace Acoustics.Shared.ConfigFile
{
using System.Collections.Generic;

/// <summary>
/// Allows a <see cref="Config"/> class to have profiles.
/// </summary>
/// <typeparam name="T">The type of each expected profile.</typeparam>
public interface INamedProfiles<T>
{
/// <summary>
/// Gets a collection of named profiles that allow for
/// variable and configurable algorithms to be used.
/// </summary>
Dictionary<string, T> Profiles { get; }
}
}
22 changes: 0 additions & 22 deletions src/Acoustics.Shared/ConfigFile/IProfile.cs

This file was deleted.

21 changes: 21 additions & 0 deletions src/Acoustics.Shared/ConfigFile/IProfiles.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// <copyright file="IProfiles.cs" company="QutEcoacoustics">
// 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).
// </copyright>

namespace Acoustics.Shared.ConfigFile
{
using System.Collections.Generic;

/// <summary>
/// Allows a <see cref="Config"/> class to have profiles.
/// </summary>
/// <typeparam name="T">The type of each expected profile.</typeparam>
public interface IProfiles<out T>
{
/// <summary>
/// Gets a collection of unnamed profiles that allow for
/// variable and configurable algorithms to be used.
/// </summary>
IReadOnlyCollection<T> Profiles { get; }
}
}
3 changes: 3 additions & 0 deletions src/Acoustics.Shared/Extensions/FileInfoExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace System
using System;
using Text;
using Acoustics.Shared.Contracts;
using JetBrains.Annotations;
using log4net;

public static class FileInfoExtensions
Expand Down Expand Up @@ -177,6 +178,8 @@ public static string FormatList(this IEnumerable<FileSystemInfo> infos)
{
return infos.Select(x => x.FullName).FormatList();
}

public static string[] ReadAllLines([NotNull] this FileInfo file) => File.ReadAllLines(file.FullName);
}

public class FileInfoNameComparer : IComparer<FileInfo>, IEqualityComparer<FileInfo>
Expand Down
58 changes: 52 additions & 6 deletions src/Acoustics.Shared/Yaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,47 @@
namespace Acoustics.Shared
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using JetBrains.Annotations;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.RepresentationModel;
using YamlDotNet.Serialization;

using Zio;

public class Yaml
public static class Yaml
{
internal static IDeserializer Deserializer => new DeserializerBuilder().IgnoreUnmatchedProperties().Build();
private static readonly Dictionary<string, Type> TagMappings = new Dictionary<string, Type>();

internal static IDeserializer Deserializer => new DeserializerBuilder()
.IgnoreUnmatchedProperties()
.WithTagMappings(TagMappings)
.Build();

/// <summary>
/// Registers a type and a tag name that will be emitted in a YAML document when
/// serializing, and will allow for unambiguous parsing when deserializing.
/// </summary>
/// <typeparam name="T">The type to register.</typeparam>
/// <param name="name">The tag name to use.</param>
public static void AddTagMapping<T>(string name = null)
{
// yml type tags must be prefixed with an "!" character.
if (name == null)
{
name = "!" + typeof(T).Name;
}
else
{
if (name[0] != '!')
{
name = "!" + name;
}
}

TagMappings.Add(name, typeof(T));
}

public static T Deserialize<T>(FileInfo file)
{
Expand All @@ -44,11 +74,14 @@ public static T Deserialize<T>(TextReader stream)
return deserializer.Deserialize<T>(parser);
}

public static void Serialize<T>(FileInfo file, T obj)
public static void Serialize<T>([NotNull] FileInfo file, [CanBeNull] T obj)
{
using (var stream = file.CreateText())
{
var serializer = new SerializerBuilder().EmitDefaults().Build();
var serializer = new SerializerBuilder()
.EmitDefaults()
.WithTagMappings(TagMappings)
.Build();

serializer.Serialize(stream, obj);
}
Expand All @@ -73,5 +106,18 @@ internal static (object, T) LoadAndDeserialize<T>(string path)
return (generic, obj);
}
}

/// <summary>
/// A helper extension method that registers multiple tag mappings with
/// the <see cref="SerializerBuilder"/> or the <see cref="DeserializerBuilder"/>.
/// </summary>
private static T WithTagMappings<T>(
this T builder,
Dictionary<string, Type> mappings)
where T : BuilderSkeleton<T>
{
return mappings
.Aggregate(builder, (b, kvp) => b.WithTagMapping(kvp.Key, kvp.Value));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
Profiles:
TestAed: !AedParameters
IntensityThreshold: 0
SmallAreaThreshold: 0
BandpassMinimum:
BandpassMaximum:
NoiseReductionType: None
BgNoiseThreshold: 0
ResampleRate: 0
IncludeHitElementsInOutput: false
ConfigPath:
GenericConfig:
TestOscillation: !OscillationParameters
DctDuration: 1
DctThreshold: 0.5
MinOscillationFrequency: 6
MaxOscillationFrequency: 4
EventThreshold: 0.29999999999999999
ComponentName:
SpeciesName:
FrameSize:
FrameStep:
BgNoiseThreshold:
MinHertz: 0
MaxHertz: 0
BottomHertzBuffer: 0
TopHertzBuffer:
MinDuration: 1
MaxDuration: 10
DecibelThreshold: 6
TestBlob: !BlobParameters
ComponentName:
SpeciesName:
FrameSize:
FrameStep:
BgNoiseThreshold:
MinHertz: 800
MaxHertz: 8000
BottomHertzBuffer: 0
TopHertzBuffer:
MinDuration: 1
MaxDuration: 10
DecibelThreshold: 6
TestWhistle: !WhistleParameters
ComponentName:
SpeciesName:
FrameSize:
FrameStep:
BgNoiseThreshold:
MinHertz: 0
MaxHertz: 0
BottomHertzBuffer: 0
TopHertzBuffer:
MinDuration: 1
MaxDuration: 10
DecibelThreshold: 6
HighResolutionIndicesConfig:
EventThreshold: 0.2
SegmentDuration: 60
SegmentOverlap: 0
ResampleRate: 22050
SaveIntermediateWavFiles: False
SaveIntermediateCsvFiles: false
SaveSonogramImages: False
RequireDateInFilename: false
Loading

0 comments on commit 663b9ef

Please sign in to comment.