/// <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="manifest">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(TemplateManifest manifest, Dictionary <string, double[, ]> templateIndices) { // Get the template provenance. Assume array contains only one element. var provenanceArray = manifest.Provenance; var provenance = provenanceArray[0]; var startRowId = provenance.StartOffset; var endRowId = provenance.EndOffset; var dictionaryOfVector = DataProcessing.AverageIndicesOverMinutes(templateIndices, startRowId, endRowId); var reducedIndices = DataProcessing.ReduceIndicesByFactor(dictionaryOfVector, manifest.SpectralReductionFactor); return(reducedIndices); }
public static List <Plot> GetPlots(Dictionary <string, double[]> 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); }
/// <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="oneMinuteOfIndices">Derived from the source recording.</param> /// <param name="template">A previously prepared template.</param> /// <param name="templateIndices">The actual dictionary of template arrays.</param> /// <returns>A similarity score.</returns> public static double GetFullBandContent1(Dictionary <string, double[]> oneMinuteOfIndices, TemplateManifest template, Dictionary <string, double[]> templateIndices) { // copy over the recording indices required by the template. var requiredIndices = DataProcessing.GetRequiredIndices(oneMinuteOfIndices, templateIndices.Keys.ToArray()); //reduce indices and convert to vector. var reducedIndices = DataProcessing.ReduceIndicesByFactor(requiredIndices, template.SpectralReductionFactor); var oneMinuteVector = DataProcessing.ConvertDictionaryToVector(reducedIndices); var templateVector = DataProcessing.ConvertDictionaryToVector(templateIndices); var distance = DataTools.EuclideanDistance(templateVector, oneMinuteVector); // Normalize the distance distance /= Math.Sqrt(templateVector.Length); return(1 - distance); }
/// <summary> /// Cycles through a set of acoustic indices in the order listed and calculates one acoustic signature for each minute of recording. /// WARNING!!!! It is assumed that the indices are listed in temporal order of the original recordings and that the original recordings were continuous. /// When these conditions satisfied, the returned plots contain scores over consecutive minutes. /// Alternatively could read recording minute from its file name. /// </summary> /// <param name="listOfIndexFiles">A text file, each line being the path to the acoustic indices derived from one recording.</param> /// <param name="templatesFile">A json file containing an array of acoustic templates.</param> /// <returns>A list of plots - each plot is the minute by minute scores for a single template.</returns> public static Dictionary <string, double[]> ContentDescriptionOfMultipleRecordingFiles(FileInfo listOfIndexFiles, FileInfo templatesFile) { // TODO: inline this method into AnalysisPrograms.ContentDescription.UseModel.Analyse const int startMinute = 0; // Read in all the prepared templates var templates = Json.Deserialize <FunctionalTemplate[]>(templatesFile); var templatesAsDictionary = DataProcessing.ExtractDictionaryOfTemplateDictionaries(templates); // 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>(); //init a minute index int elapsedMinutes = 0; // cycle through the directories for (int i = 0; i < filePaths.Count; i++) { // read the spectral indices for the current file. //IMPORTANT: This method returns normalised index values 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 = AnalyzeMinutes(templates, templatesAsDictionary, dictionaryOfRecordingIndices, elapsedMinutes); completeListOfResults.AddRange(results); // calculate the elapsed minutes in this recording var matrix = dictionaryOfRecordingIndices.FirstValue(); elapsedMinutes += matrix.GetLength(0); } // convert completeListOfResults to dictionary of score arrays var contentDictionary = DataProcessing.ConvertResultsToDictionaryOfArrays(completeListOfResults, elapsedMinutes, startMinute); return(contentDictionary); }
// ################################################################################### /// <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="manifest">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(TemplateManifest manifest, Dictionary <string, double[, ]> templateIndices) { // Get the template provenance. Assume array contains only one element. var provenanceArray = manifest.Provenance; var provenance = provenanceArray[0]; var startRowId = provenance.StartOffset; var endRowId = provenance.EndOffset; var reductionFactor = manifest.SpectralReductionFactor; 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 = ContentSignatures.FreqBinCount / reductionFactor; int bottomFreq = manifest.BandMinHz; //Hertz int topFreq = manifest.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 /// calculates how much of the match weight is in the correct narrow freq band. /// </summary> /// <param name="oneMinuteOfIndices">Derived from the source recording.</param> /// <param name="template">A previously prepared template.</param> /// <param name="templateIndices">The actual dictionary of template arrays.</param> /// <returns>A similarity score.</returns> public static double GetNarrowBandContent1(Dictionary <string, double[]> oneMinuteOfIndices, TemplateManifest template, Dictionary <string, double[]> templateIndices) { // copy over the recording indices required by the template. var requiredIndices = DataProcessing.GetRequiredIndices(oneMinuteOfIndices, templateIndices.Keys.ToArray()); //reduce indices and convert to vector. var reductionFactor = template.SpectralReductionFactor; var reducedIndices = DataProcessing.ReduceIndicesByFactor(requiredIndices, reductionFactor); // Now pass the template up the full frequency spectrum to get a spectrum of scores. var spectralScores = DataProcessing.ScanSpectrumWithTemplate(templateIndices, reducedIndices); // Now check how much of spectral weight is in the correct freq band ie between 3-4 kHz. int freqBinCount = ContentSignatures.FreqBinCount / reductionFactor; int bottomFreq = template.BandMinHz; //Hertz int topFreq = template.BandMaxHz; //Hertz var freqBinBounds = DataProcessing.GetFreqBinBounds(bottomFreq, topFreq, freqBinCount); double callSum = DataTools.Subarray(spectralScores, freqBinBounds[0], freqBinBounds[1]).Sum(); double totalSum = DataTools.Subarray(spectralScores, 1, spectralScores.Length - 3).Sum(); double score = callSum / totalSum; return(score); }
/// <summary> /// This method calculates new template based on passed manifest. /// </summary> public static Dictionary <string, double[]> CreateTemplateDefinition(TemplateManifest templateManifest) { // Get the template provenance. Assume array contains only one element. var provenanceArray = templateManifest.Provenance; var provenance = provenanceArray[0]; var sourceDirectory = provenance.Directory; var baseName = provenance.Basename; // Read all indices from the complete recording. The path variable is a partial path requiring to be appended. var path = Path.Combine(sourceDirectory, baseName + ContentSignatures.AnalysisString); var dictionaryOfIndices = DataProcessing.ReadIndexMatrices(path); var algorithmType = templateManifest.FeatureExtractionAlgorithm; Dictionary <string, double[]> newTemplateDefinition; switch (algorithmType) { case 1: newTemplateDefinition = ContentAlgorithms.CreateFullBandTemplate1(templateManifest, dictionaryOfIndices); break; case 2: newTemplateDefinition = ContentAlgorithms.CreateBroadbandTemplate1(templateManifest, dictionaryOfIndices); break; case 3: newTemplateDefinition = ContentAlgorithms.CreateNarrowBandTemplate1(templateManifest, dictionaryOfIndices); break; default: //LoggedConsole.WriteWarnLine("Algorithm " + algorithmType + " does not exist."); newTemplateDefinition = null; break; } return(newTemplateDefinition); }