/// <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);
        }
Beispiel #2
0
        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);
        }
Beispiel #4
0
        /// <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);
        }
Beispiel #7
0
        /// <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);
        }