Skip to content

Commit

Permalink
Start work on Template Creation
Browse files Browse the repository at this point in the history
Issue #252 remove old base type and set up new template creation algorithms
  • Loading branch information
towsey committed Sep 21, 2019
1 parent 1ac77f0 commit 1b8e776
Show file tree
Hide file tree
Showing 13 changed files with 205 additions and 269 deletions.
66 changes: 4 additions & 62 deletions src/AnalysisPrograms/Sandpit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,73 +149,15 @@ public static void ContentDescriptionCreateTemplates()

public static void ContentDescriptionApplyTemplates()
{
DirectoryInfo[] directories =
{
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez01\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez02\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez03\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez04\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez05\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez06\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez07\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez08\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez09\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez10\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez11\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez12\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez13\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez14\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez15\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez16\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez17\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez18\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez19\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez20\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez21\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez22\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez23\Towsey.Acoustic"),
new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\Mez24\Towsey.Acoustic"),
};

string[] baseNames =
{
"SM304256_0+1_20151114_001652",
"SM304256_0+1_20151114_011652",
"SM304256_0+1_20151114_021652",
"SM304256_0+1_20151114_031652",
"SM304256_0+1_20151114_041652",
"SM304256_0+1_20151114_051652",
"SM304256_0+1_20151114_061652",
"SM304256_0+1_20151114_071652",
"SM304256_0+1_20151114_081652",
"SM304256_0+1_20151114_091652",
"SM304256_0+1_20151114_101652",
"SM304256_0+1_20151114_111652",
"SM304256_0+1_20151114_121652",
"SM304256_0+1_20151114_131652",
"SM304256_0+1_20151114_141652",
"SM304256_0+1_20151114_151652",
"SM304256_0+1_20151114_161652",
"SM304256_0+1_20151114_171652",
"SM304256_0+1_20151114_181652",
"SM304256_0+1_20151114_191652",
"SM304256_0+1_20151114_201652",
"SM304256_0+1_20151114_211652",
"SM304256_0+1_20151114_221652",
"SM304256_0+1_20151114_231652",
};

var templatesConfig = new FileInfo(@"C:\Work\GitHub\audio-analysis\src\AnalysisConfigFiles\ContentDescriptionTemplates.yml");
var listOfIndexFiles = new FileInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMezIndexFiles.txt");
var contentPlots = ContentDescription.ContentDescriptionOfMultipleRecordingFiles(listOfIndexFiles, templatesConfig);

var contentPlots = ContentDescription.ContentDescriptionOfMultipleRecordingFiles(directories, baseNames, templatesConfig);

// Attach content description plots to LDFC spectrogram
// Attach content description plots to LDFC spectrogram and write to file
var path = Path.Combine(@"C:\Ecoacoustics\Output\Test\Test24HourRecording", "Testing__2Maps.png");
var ldfcSpectrogram = Image.FromFile(path);

//Write image + contentPlots to file.
var image = ContentVisualization.DrawLdfcSpectrogramWithContentScoreTracks(ldfcSpectrogram, contentPlots);
var path1 = Path.Combine(@"C:\Ecoacoustics\Output\ContentDescription", "Testing_2Maps.CONTENTnew01.png");
var path1 = Path.Combine(@"C:\Ecoacoustics\Output\ContentDescription", "Testing_2Maps.CONTENTnew02.png");
image.Save(path1);
}

Expand Down
1 change: 0 additions & 1 deletion src/AudioAnalysisTools/AudioAnalysisTools.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,6 @@
<Compile Include="ChannelIntegrity.cs" />
<Compile Include="ContentDescriptionTools\ContentAlgorithms.cs" />
<Compile Include="ContentDescriptionTools\ContentDescription.cs" />
<Compile Include="ContentDescriptionTools\ContentTypes\BaseContentType.cs" />
<Compile Include="ContentDescriptionTools\ContentTypes\RainLight1.cs" />
<Compile Include="ContentDescriptionTools\ContentTypes\BirdMorningChorus1.cs" />
<Compile Include="ContentDescriptionTools\ContentTypes\SilverEyeMezTasmanIs.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,24 @@ namespace AudioAnalysisTools.ContentDescriptionTools

public static class ContentAlgorithms
{
/// <summary>
/// This algorithm is used for full band width events such as a rain and wind.
/// It calculates a content score based on a template match to what is in the full spectrum.
/// </summary>
/// <param name="templateManifest">A description of the template which is to be created.</param>
/// <param name="templateIndices">The actual dictionary of template arrays.</param>
/// <returns>A new template.</returns>
public static Dictionary<string, double[]> CreateFullBandTemplate1(ContentTemplate templateManifest, Dictionary<string, double[,]> templateIndices)
{
var reductionFactor = templateManifest.SpectralReductionFactor;
var startRowId = templateManifest.StartRowId;
var endRowId = templateManifest.EndRowId;
var dictionaryOfVector = DataProcessing.AverageIndicesOverMinutes(templateIndices, startRowId, endRowId);
var reducedIndices = DataProcessing.ReduceIndicesByFactor(dictionaryOfVector, reductionFactor);

return reducedIndices;
}

/// <summary>
/// This algorithm is used for full band width events such as a rain and wind.
/// It calculates a content score based on a template match to what is in the full spectrum.
Expand All @@ -33,6 +51,31 @@ public static double GetFullBandContent1(Dictionary<string, double[]> oneMinuteO
return 1 - distance;
}

// ###################################################################################

/// <summary>
/// This algorithm is used for broad band events such as a bird chorus.
/// It selects acoustic content over a band of several kHz and calculates a content score based on a template match to what is in the band.
/// </summary>
/// <param name="templateManifest">A previously prepared template.</param>
/// <param name="templateIndices">The actual dictionary of template arrays.</param>
/// <returns>A similarity score.</returns>
public static Dictionary<string, double[]> CreateBroadbandTemplate1(ContentTemplate templateManifest, Dictionary<string, double[,]> templateIndices)
{
var reductionFactor = templateManifest.SpectralReductionFactor;
var startRowId = templateManifest.StartRowId;
var endRowId = templateManifest.EndRowId;
var dictionaryOfVector = DataProcessing.AverageIndicesOverMinutes(templateIndices, startRowId, endRowId);
// remove first two freq bins and last four freq bins, i.e. bottomBin = 2 and topBin = 11;
int freqBinCount = ContentDescription.FreqBinCount / reductionFactor;
int bottomFreq = templateManifest.BandMinHz; //Hertz
int topFreq = templateManifest.BandMaxHz; //Hertz
var freqBinBounds = DataProcessing.GetFreqBinBounds(bottomFreq, topFreq, freqBinCount);
var reducedIndices = DataProcessing.ReduceIndicesByFactor(dictionaryOfVector, reductionFactor);
reducedIndices = DataProcessing.ApplyBandPass(reducedIndices, freqBinBounds[0], freqBinBounds[1]);
return reducedIndices;
}

/// <summary>
/// This algorithm is used for broad band events such as a bird chorus.
/// It selects acoustic content over a band of several kHz and calculates a content score based on a template match to what is in the band.
Expand All @@ -43,13 +86,14 @@ public static double GetFullBandContent1(Dictionary<string, double[]> oneMinuteO
/// <returns>A similarity score.</returns>
public static double GetBroadbandContent1(Dictionary<string, double[]> oneMinuteOfIndices, ContentTemplate template, Dictionary<string, double[]> templateIndices)
{
// remove first two freq bins and last four freq bins, i.e. bottomBin = 2 and topBin = 11;
var reductionFactor = template.SpectralReductionFactor;
int freqBinCount = ContentDescription.FreqBinCount / reductionFactor;
int bottomFreq = template.BandMinHz; //Hertz
int topFreq = template.BandMaxHz; //Hertz
var freqBinBounds = DataProcessing.GetFreqBinBounds(bottomFreq, topFreq, freqBinCount);
var reducedIndices = DataProcessing.ReduceIndicesByFactor(oneMinuteOfIndices, reductionFactor);

// remove top freq bins and bottom freq bins;
reducedIndices = DataProcessing.ApplyBandPass(reducedIndices, freqBinBounds[0], freqBinBounds[1]);
var oneMinuteVector = DataProcessing.ConvertDictionaryToVector(reducedIndices);
var templateVector = DataProcessing.ConvertDictionaryToVector(templateIndices);
Expand All @@ -62,6 +106,32 @@ public static double GetBroadbandContent1(Dictionary<string, double[]> oneMinute
return 1 - distance;
}

// ###################################################################################

/// <summary>
/// This algorithm is used for narrow band events such as an insect bird chorus or content due to narrow band calls of a single bird species.
/// It searches the full spectrum for a match to the template and then
/// calculates how much of the match weight is in the correct narrow freq band.
/// </summary>
/// <param name="templateManifest">A previously prepared template.</param>
/// <param name="templateIndices">The actual dictionary of template arrays.</param>
/// <returns>A similarity score.</returns>
public static Dictionary<string, double[]> CreateNarrowBandTemplate1(ContentTemplate templateManifest, Dictionary<string, double[,]> templateIndices)
{
var reductionFactor = templateManifest.SpectralReductionFactor;
var startRowId = templateManifest.StartRowId;
var endRowId = templateManifest.EndRowId;
var dictionaryOfVector = DataProcessing.AverageIndicesOverMinutes(templateIndices, startRowId, endRowId);
// remove first two freq bins and last four freq bins, i.e. bottomBin = 2 and topBin = 11;
int freqBinCount = ContentDescription.FreqBinCount / reductionFactor;
int bottomFreq = templateManifest.BandMinHz; //Hertz
int topFreq = templateManifest.BandMaxHz; //Hertz
var freqBinBounds = DataProcessing.GetFreqBinBounds(bottomFreq, topFreq, freqBinCount);
var reducedIndices = DataProcessing.ReduceIndicesByFactor(dictionaryOfVector, reductionFactor);
reducedIndices = DataProcessing.ApplyBandPass(reducedIndices, freqBinBounds[0], freqBinBounds[1]);
return reducedIndices;
}

/// <summary>
/// This algorithm is used for narrow band events such as an insect bird chorus or content due to narrow band calls of a single bird species.
/// It searches the full spectrum for a match to the template and then
Expand Down Expand Up @@ -89,5 +159,7 @@ public static double GetNarrowBandContent1(Dictionary<string, double[]> oneMinut
double score = callSum / totalSum;
return score;
}

// ###################################################################################
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@

namespace AudioAnalysisTools.ContentDescriptionTools
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Acoustics.Shared.ConfigFile;
using AudioAnalysisTools.ContentDescriptionTools.ContentTypes;
using TowseyLibrary;

public class ContentDescription
Expand All @@ -32,28 +29,31 @@ public class ContentDescription

public static string[] IndexNames { get; } = { "ACI", "ENT", "EVN", "BGN", "PMN" };

public static List<Plot> ContentDescriptionOfMultipleRecordingFiles(DirectoryInfo[] directories, string[] baseNames, FileInfo templatesConfig)
public static List<Plot> ContentDescriptionOfMultipleRecordingFiles(FileInfo listOfIndexFiles, FileInfo templatesConfig)
{
// Read in all content templates
var templateCollection = ConfigFile.Deserialize<TemplateCollection>(templatesConfig);
var templatesAsDictionary = DataProcessing.ExtractDictionaryOfTemplateDictionaries(templateCollection);

// Read in list of paths to index files
var filePaths = FileTools.ReadTextFile(listOfIndexFiles.FullName);

// init a list to collect description results
var completeListOfResults = new List<DescriptionResult>();

// cycle through the directories
// WARNING: Assume one-hour duration for each recording
for (int i = 0; i < directories.Length; i++)
for (int i = 0; i < filePaths.Count; i++)
{
// read the spectral indices for the current file
var dictionaryOfRecordingIndices = DataProcessing.ReadIndexMatrices(directories[i], baseNames[i]);
var dictionaryOfRecordingIndices = DataProcessing.ReadIndexMatrices(filePaths[i]);

// Draw the index matrices for check/debug purposes
// var dir1 = new DirectoryInfo(@"C:\Ecoacoustics\Output\ContentDescription");
// ContentDescription.DrawNormalisedIndexMatrices(dir1, baseName, dictionary);

// get the rows and do something with them one by one.
var results = AnalyseMinutes(templateCollection, templatesAsDictionary, dictionaryOfRecordingIndices, i * 60); // WARNING: HACK: ASSUME ONE HOUR FILES
var results = AnalyzeMinutes(templateCollection, templatesAsDictionary, dictionaryOfRecordingIndices, i * 60); // WARNING: HACK: ASSUME ONE HOUR FILES
completeListOfResults.AddRange(results);
}

Expand All @@ -66,7 +66,7 @@ public static List<Plot> ContentDescriptionOfMultipleRecordingFiles(DirectoryInf
return contentPlots;
}

public static List<DescriptionResult> AnalyseMinutes(
public static List<DescriptionResult> AnalyzeMinutes(
TemplateCollection templateCollection,
Dictionary<string, Dictionary<string, double[]>> templatesAsDictionary,
Dictionary<string, double[,]> dictionaryOfRecordingIndices,
Expand Down Expand Up @@ -94,7 +94,7 @@ public static List<DescriptionResult> AnalyseMinutes(
var template = kvp.Value;
var algorithmType = template.FeatureExtractionAlgorithm;
var templateIndices = templatesAsDictionary[key];
double score = 0.0;
double score;

switch (algorithmType)
{
Expand Down
Loading

0 comments on commit 1b8e776

Please sign in to comment.