diff --git a/src/AnalysisPrograms/Sandpit.cs b/src/AnalysisPrograms/Sandpit.cs index 768367241..8f6003d01 100644 --- a/src/AnalysisPrograms/Sandpit.cs +++ b/src/AnalysisPrograms/Sandpit.cs @@ -64,11 +64,11 @@ public override Task Execute(CommandLineApplication app) Log.WriteLine("# Start Time = " + tStart.ToString(CultureInfo.InvariantCulture)); // CONTENT DESCRIPTION - //ContentDescriptionCreateTemplates(); - //ContentDescriptionApplyTemplates(); + ContentDescriptionCreateTemplates(); + ContentDescriptionApplyTemplates(); //AnalyseFrogDataSet(); - Audio2CsvOverOneFile(); + //Audio2CsvOverOneFile(); //Audio2CsvOverMultipleFiles(); // used to get files from availae for Black rail and Least Bittern papers. @@ -123,7 +123,7 @@ public override Task Execute(CommandLineApplication app) public static void ContentDescriptionCreateTemplates() { var templateManifests = new FileInfo(@"C:\Ecoacoustics\ContentDescription\ContentDescriptionTemplateManifests.yml"); - var templateDefinitions = new FileInfo(@"C:\Ecoacoustics\ContentDescription\TemplateDefinitions.json"); + var templateDefinitions = new FileInfo(@"C:\Ecoacoustics\ContentDescription\Towsey.TemplateDefinitions.json"); TemplateManifest.CreateNewFileOfTemplateDefinitions(templateManifests, templateDefinitions); Console.WriteLine("# Finished creation of new manifest"); } @@ -132,20 +132,29 @@ public static void ContentDescriptionApplyTemplates() { Console.WriteLine("# Start scanning with content description templates"); - var templatesFile = new FileInfo(@"C:\Ecoacoustics\ContentDescription\TemplateDefinitions.json"); - var listOfIndexFiles = new FileInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMezIndexFiles.txt"); - var contentPlots = AudioAnalysisTools.ContentDescriptionTools.ContentSignatures.ContentDescriptionOfMultipleRecordingFiles(listOfIndexFiles, templatesFile); + var templatesFile = new FileInfo(@"C:\Ecoacoustics\ContentDescription\Towsey.TemplateDefinitions.json"); + var listOfIndexFiles = new FileInfo(Path.Combine(@"C:\Ecoacoustics\Output\Test\Test24HourRecording", "TasmanIslandMezIndexFiles.txt")); + var dataDirectory = @"C:\Ecoacoustics\Output\Test\Test24HourRecording"; + var outputDirectory = @"C:\Ecoacoustics\ContentDescription"; + var contentDictionary = ContentSignatures.ContentDescriptionOfMultipleRecordingFiles(listOfIndexFiles, templatesFile); + + // Write the results to a csv file + var filePath = Path.Combine(outputDirectory, "AcousticSignatures.csv"); + FileTools.WriteDictionaryAsCsvFile(contentDictionary, filePath); + + // get content description plots and use to examine score distributions. + var contentPlots = ContentSignatures.GetPlots(contentDictionary); var images = GraphsAndCharts.DrawPlotDistributions(contentPlots); var plotsImage = ImageTools.CombineImagesVertically(images); - var path1 = Path.Combine(@"C:\Ecoacoustics\ContentDescription", "ScoreDistributions.png"); + var path1 = Path.Combine(outputDirectory, "ScoreDistributions.png"); plotsImage.Save(path1); - // Attach content description plots to LDFC spectrogram and write to file - var path = Path.Combine(@"C:\Ecoacoustics\Output\Test\Test24HourRecording", "Testing__2Maps.png"); + // Attach plots to LDFC spectrogram and write to file + var path = Path.Combine(dataDirectory, "Testing__2Maps.png"); var ldfcSpectrogram = Image.FromFile(path); var image = ContentVisualization.DrawLdfcSpectrogramWithContentScoreTracks(ldfcSpectrogram, contentPlots); - var path2 = Path.Combine(@"C:\Ecoacoustics\ContentDescription", "Testing_2Maps.CONTENTnew07.png"); + var path2 = Path.Combine(outputDirectory, "Testing_2Maps.CONTENTnew07.png"); image.Save(path2); Console.WriteLine("# Finished scanning recording with content description templates"); } diff --git a/src/AudioAnalysisTools/ContentDescriptionTools/ContentSignatures.cs b/src/AudioAnalysisTools/ContentDescriptionTools/ContentSignatures.cs index 098a84f88..1faa79319 100644 --- a/src/AudioAnalysisTools/ContentDescriptionTools/ContentSignatures.cs +++ b/src/AudioAnalysisTools/ContentDescriptionTools/ContentSignatures.cs @@ -47,10 +47,9 @@ public class ContentSignatures /// A text file, each line being the path to the acoustic indices derived from one recording. /// A json file containing an array of acoustic templates. /// A list of plots - each plot is the minute by minute scores for a single template. - public static List ContentDescriptionOfMultipleRecordingFiles(FileInfo listOfIndexFiles, FileInfo templatesFile) + public static Dictionary ContentDescriptionOfMultipleRecordingFiles(FileInfo listOfIndexFiles, FileInfo templatesFile) { - // total length in minutes of all the recordings - const int totalMinutesDurationOverAllRecordings = 1440; + // ASSUMPTION: const int startMinute = 0; // Read in all the prepared templates @@ -86,18 +85,9 @@ public static List ContentDescriptionOfMultipleRecordingFiles(FileInfo lis elapsedMinutes += matrix.GetLength(0); } - var plotDict = DataProcessing.ConvertResultsToPlots(completeListOfResults, totalMinutesDurationOverAllRecordings, startMinute); - var contentPlots = DataProcessing.ConvertPlotDictionaryToPlotList(plotDict); - - // convert scores to z-scores - //contentPlots = DataProcessing.SubtractMeanPlusSd(contentPlots); - - //the following did not work as well. - //contentPlots = DataProcessing.SubtractModeAndSd(contentPlots); - - // Use percentile thresholding followed by normalize in 0,1. - contentPlots = DataProcessing.PercentileThresholding(contentPlots, 90); - return contentPlots; + // convert completeListOfResults to dictionary of score arrays + var contentDictionary = DataProcessing.ConvertResultsToDictionaryOfArrays(completeListOfResults, elapsedMinutes, startMinute); + return contentDictionary; } public static List AnalyzeMinutes( @@ -131,7 +121,7 @@ public static List AnalyzeMinutes( /// IMPORTANT: The indices passed in the dictionary "oneMinuteOfIndices" must be normalised. /// /// The templates read from json file. - /// The numerical pasrt of each template. + /// The numerical part of each template. /// The normalised values of the indices derived from one minute of recording. /// The minute ID, i.e. its temporal position. /// A single instance of a DescriptionResult. @@ -182,5 +172,22 @@ public static DescriptionResult AnalyzeOneMinute( return descriptionResult; } + + public static List GetPlots(Dictionary contentDictionary) + { + double threshold = 0.25; + var plotDict = DataProcessing.ConvertArraysToPlots(contentDictionary, threshold); + var contentPlots = DataProcessing.ConvertPlotDictionaryToPlotList(plotDict); + + // convert scores to z-scores + //contentPlots = DataProcessing.SubtractMeanPlusSd(contentPlots); + + //the following did not work as well. + //contentPlots = DataProcessing.SubtractModeAndSd(contentPlots); + + // Use percentile thresholding followed by normalize in 0,1. + contentPlots = DataProcessing.PercentileThresholding(contentPlots, 90); + return contentPlots; + } } } diff --git a/src/AudioAnalysisTools/ContentDescriptionTools/TemplateManifest.cs b/src/AudioAnalysisTools/ContentDescriptionTools/TemplateManifest.cs index 86f6f9882..6d463fcd5 100644 --- a/src/AudioAnalysisTools/ContentDescriptionTools/TemplateManifest.cs +++ b/src/AudioAnalysisTools/ContentDescriptionTools/TemplateManifest.cs @@ -79,10 +79,11 @@ public static void CreateNewFileOfTemplateDefinitions(FileInfo manifestFile, Fil } } - var templatesFilePath = Path.Combine(manifestFile.DirectoryName ?? throw new InvalidOperationException(), "TemplateDefinitions.json"); + var templatesFileName = templateDefinitionsFile.Name; + var templatesFilePath = Path.Combine(manifestFile.DirectoryName ?? throw new InvalidOperationException(), templatesFileName); // Save the previous templates file - string backupTemplatesFilePath = Path.Combine(manifestFile.DirectoryName, "TemplateDefinitions.Backup.json"); + string backupTemplatesFilePath = Path.Combine(manifestFile.DirectoryName, templatesFileName + ".Backup.json"); if (File.Exists(backupTemplatesFilePath)) { File.Delete(backupTemplatesFilePath);