diff --git a/src/AnalysisBase/ResultBases/SpectralIndexBase.cs b/src/AnalysisBase/ResultBases/SpectralIndexBase.cs
index 50d568d5d..5f2f87161 100644
--- a/src/AnalysisBase/ResultBases/SpectralIndexBase.cs
+++ b/src/AnalysisBase/ResultBases/SpectralIndexBase.cs
@@ -1,4 +1,4 @@
-// --------------------------------------------------------------------------------------------------------------------
+// --------------------------------------------------------------------------------------------------------------------
//
// 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).
//
@@ -11,15 +11,44 @@ namespace AnalysisBase.ResultBases
{
using System;
using System.Collections.Generic;
- using System.IO;
using System.Linq;
- using System.Reflection;
public abstract class SpectralIndexBase : ResultBase
{
public abstract Dictionary> GetSelectors();
- }
+ protected static (Dictionary> CachedSelectors, Dictionary> CachedSetters, string[] Keys) MakeSelectors()
+ where T : SpectralIndexBase
+ {
+ var getters = ReflectionExtensions.GetGetters();
+
+ var cachedSelectors = new Dictionary>(getters.Count);
+ foreach (var keyValuePair in getters)
+ {
+ // var key = keyValuePair.Key;
+ var selector = keyValuePair.Value;
+
+ cachedSelectors.Add(
+ keyValuePair.Key,
+ spectrumBase => selector((T)spectrumBase));
+ }
+ var keys = cachedSelectors.Keys.ToArray();
+ var setters = ReflectionExtensions.GetSetters();
+
+ var cachedSetters = new Dictionary>(getters.Count);
+ foreach (var keyValuePair in setters)
+ {
+ // var key = keyValuePair.Key;
+ var setter = keyValuePair.Value;
+
+ cachedSetters.Add(
+ keyValuePair.Key,
+ (spectrumBase, value) => setter(spectrumBase, value));
+ }
+
+ return (cachedSelectors, cachedSetters, keys);
+ }
+ }
}
\ No newline at end of file
diff --git a/src/AnalysisPrograms/ContentDescription/UseModel.cs b/src/AnalysisPrograms/ContentDescription/UseModel.cs
index 55ab2ecc3..b89d35949 100644
--- a/src/AnalysisPrograms/ContentDescription/UseModel.cs
+++ b/src/AnalysisPrograms/ContentDescription/UseModel.cs
@@ -26,9 +26,9 @@ namespace AnalysisPrograms.ContentDescription
/// This class is derived from AbstractStrongAnalyser.
/// It is equivalent to AnalyseLongRecording.cs or a species recognizer.
/// To call this class, the first argument on the commandline must be 'audio2csv'.
- /// Given a one-minute recording segment, the ContentDescription.Analyze() method calls AudioAnalysisTools.Indices.IndexCalculateSixOnly.Analysis().
+ /// Given a one-minute recording segment, the UseModel.Analyze() method calls AudioAnalysisTools.Indices.IndexCalculateSixOnly.Analysis().
/// This calculates six spectral indices, ACI, ENT, EVN, BGN, PMN, OSC. This set of 6x256 acoustic features is used for content description.
- /// The content description methods are called from UseModel.SummariseResults() method.
+ /// The content description methods are called from UseModel.Analyze() method.
///
public class UseModel : AbstractStrongAnalyser
{
@@ -41,6 +41,10 @@ public class UseModel : AbstractStrongAnalyser
private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private FunctionalTemplate[] functionalTemplates;
+
+ private Dictionary> templatesAsDictionary;
+
public override string DisplayName => "Content Description";
public override string Identifier => TowseyContentDescription;
@@ -52,10 +56,6 @@ public class UseModel : AbstractStrongAnalyser
AnalysisTargetSampleRate = ContentSignatures.SampleRate,
};
- private FunctionalTemplate[] functionalTemplates;
-
- private Dictionary> templatesAsDictionary;
-
public override void BeforeAnalyze(AnalysisSettings analysisSettings)
{
// Read in the functional templates file. These doe the content description.
@@ -107,11 +107,10 @@ public override AnalysisResult2 Analyze(AnalysisSettings analysisSettings, Se
segmentSettings.SegmentStartOffset,
segmentSettings.Segment.SourceMetadata.SampleRate);
- segmentResults.SpectralIndexValues.FileName = segmentSettings.Segment.SourceMetadata.Identifier;
-
// DO THE CONTENT DESCRIPTION FOR ONE MINUTE HERE
// First get acoustic indices for one minute, convert to Dictionary and normalize the values.
- var indicesDictionary = IndexCalculateSixOnly.ConvertIndicesToDictionary(segmentResults.SpectralIndexValues);
+ var indicesDictionary = segmentResults.AsArray().ToTwoDimensionalArray(SpectralIndexValuesForContentDescription.CachedSelectors);
+ //var indicesDictionary = IndexCalculateSixOnly.ConvertIndicesToDictionary(segmentResults);
foreach (string key in ContentSignatures.IndexNames)
{
var indexBounds = ContentSignatures.IndexValueBounds[key];
@@ -124,7 +123,7 @@ public override AnalysisResult2 Analyze(AnalysisSettings analysisSettings, Se
var descriptionResultForOneMinute = ContentSignatures.AnalyzeOneMinute(
this.functionalTemplates,
this.templatesAsDictionary,
- indicesDictionary,
+ indicesDictionary.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.GetRow(0)), // this line converts dictionary of one-row matrices to dictionary of arrays.
startMinuteId);
// set up the analysis results to return
@@ -135,7 +134,7 @@ public override AnalysisResult2 Analyze(AnalysisSettings analysisSettings, Se
{
// Transfer the spectral index results to AnalysisResults
// TODO: consider not returning this value if it is not needed in summarize
- segmentResults.SpectralIndexValues,
+ segmentResults,
},
MiscellaneousResults =
{
@@ -254,10 +253,10 @@ public override void SummariseResults(
// Write the results to a csv file
var filePath = Path.Combine(resultsDirectory.FullName, "AcousticSignatures.csv");
- FileTools.WriteDictionaryAsCsvFile(contentDictionary, filePath);
// TODO: fix this so it writes header and a column of content description values.
//Csv.WriteToCsv(new FileInfo(filePath), contentDictionary);
+ FileTools.WriteDictionaryAsCsvFile(contentDictionary, filePath);
// prepare graphical plots of the acoustic signatures.
var contentPlots = GetPlots(contentDictionary);
@@ -272,61 +271,6 @@ public override void SummariseResults(
image.Save(path3);
}
- /*
- ///
- /// NOTE: THIS METHOD SHOULD EVENTUALLY BE DELETED. NO LONGER CALLED.
- /// Calculate the content description for each minute.
- ///
- /// set of spectral indices for each minute.
- /// json file containing description of templates.
- /// Offset into the recording where recording begun (may not be a whole or round minute).
- private static Dictionary GetContentDescription(
- SpectralIndexBase[] spectralIndices,
- FileInfo templatesFile,
- TimeSpan elapsedTimeAtStartOfRecording)
- {
- // Read in the content description templates
- var templates = Json.Deserialize(templatesFile);
- var templatesAsDictionary = DataProcessing.ExtractDictionaryOfTemplateDictionaries(templates);
- var startMinuteId = (int)Math.Round(elapsedTimeAtStartOfRecording.TotalMinutes);
-
- // create dictionary of index vectors
- var results = new List();
-
- int length = spectralIndices.Length;
-
- //loop over all minutes in the recording
- for (int i = 0; i < length; i++)
- {
- var oneMinuteOfIndices = spectralIndices[i];
-
- // Transfer acoustic indices to dictionary
- var indicesDictionary = IndexCalculateSixOnly.ConvertIndicesToDictionary(oneMinuteOfIndices);
-
- // normalize the index values
- foreach (string key in ContentSignatures.IndexNames)
- {
- var indexBounds = ContentSignatures.IndexValueBounds[key];
- var indexArray = indicesDictionary[key];
- var normalisedVector = DataTools.NormaliseInZeroOne(indexArray, indexBounds[0], indexBounds[1]);
- indicesDictionary[key] = normalisedVector;
- }
-
- // scan templates over one minute of indices
- var resultsForOneMinute = ContentSignatures.AnalyzeOneMinute(
- templates,
- templatesAsDictionary,
- indicesDictionary,
- startMinuteId + i);
- results.Add(resultsForOneMinute);
- }
-
- // convert results to dictionary of score arrays
- var dictionaryOfScores = DataProcessing.ConvertResultsToDictionaryOfArrays(results, length, startMinuteId);
- return dictionaryOfScores;
- }
- */
-
///
/// Produce plots for graphical display.
/// NOTE: The threshold can be changed later.
diff --git a/src/AudioAnalysisTools/AudioAnalysisTools.csproj b/src/AudioAnalysisTools/AudioAnalysisTools.csproj
index ed84a9e47..cd015acdd 100644
--- a/src/AudioAnalysisTools/AudioAnalysisTools.csproj
+++ b/src/AudioAnalysisTools/AudioAnalysisTools.csproj
@@ -246,7 +246,7 @@
-
+
diff --git a/src/AudioAnalysisTools/ContentDescriptionTools/ContentSignatures.cs b/src/AudioAnalysisTools/ContentDescriptionTools/ContentSignatures.cs
index 0da6a212e..669b36141 100644
--- a/src/AudioAnalysisTools/ContentDescriptionTools/ContentSignatures.cs
+++ b/src/AudioAnalysisTools/ContentDescriptionTools/ContentSignatures.cs
@@ -7,14 +7,14 @@ namespace AudioAnalysisTools.ContentDescriptionTools
using System;
using System.Collections.Generic;
using System.IO;
- using System.Linq;
using Acoustics.Shared;
+ using AudioAnalysisTools.Indices;
using TowseyLibrary;
///
/// This class contains methods which use functional templates to scan one or multiple files to obtain a content description.
/// For consistency between recordings many parameters such as sample rate, frame size etc, must be declared as constants.
- /// In addition, the absolute values in the template description dictionary must be normalised using the fixed set of normalisation bounds in IndexValueBounds.
+ /// In addition, the absolute values in the template description dictionary must be normalised using the fixed set of normalization bounds in IndexValueBounds.
/// Note that each functional template uses one of a small number of algorithms to calculate a similarity value.
///
public class ContentSignatures
@@ -43,12 +43,13 @@ public class ContentSignatures
///
/// Gets an array of six spectral indices that are calculated.
///
- public static string[] IndexNames { get; } = { "ACI", "ENT", "EVN", "BGN", "PMN", "OSC" };
+ public static string[] IndexNames { get; } = SpectralIndexValuesForContentDescription.Keys;
///
/// Gets an array containing names of spectral indices that are not wanted. They are used to remove unwanted selectors.
/// This is a temporary arrangement to utilize existing code.
/// TODO Eventually separate out template results so do not have to use the AnalysisResult2 class.
+ /// ToDO: this should now be deleteable
///
public static string[] UnusedIndexNames { get; } = { "CVR", "DIF", "RHZ", "RVT", "RPS", "RNG", "R3D", "SPT", "SUM" };
diff --git a/src/AudioAnalysisTools/ContentDescriptionTools/SpectralIndexValuesforContentDescription.cs b/src/AudioAnalysisTools/ContentDescriptionTools/SpectralIndexValuesforContentDescription.cs
index dd99e5e7d..3961bd113 100644
--- a/src/AudioAnalysisTools/ContentDescriptionTools/SpectralIndexValuesforContentDescription.cs
+++ b/src/AudioAnalysisTools/ContentDescriptionTools/SpectralIndexValuesforContentDescription.cs
@@ -1,4 +1,4 @@
-//
+//
// 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).
//
@@ -19,110 +19,26 @@ namespace AudioAnalysisTools.Indices
/// Purpose of this class is to avoid using the class IndexCalculateResult for returning results from IndexCalculateSixOnly.Analysis();
/// This class is stripped down to just the required six spectral indices.
///
- public class SpectralIndexValuesforContentDescription : ResultBase
+ public class SpectralIndexValuesForContentDescription : SpectralIndexBase
{
- //static SpectralIndexValuesforContentDescription()
- //{
- // var getters = ReflectionExtensions.GetGetters();
-
- // CachedSelectors = new Dictionary>(getters.Count);
- // foreach (var keyValuePair in getters)
- // {
- // // var key = keyValuePair.Key;
- // var selector = keyValuePair.Value;
-
- // CachedSelectors.Add(
- // keyValuePair.Key,
- // spectrumBase => selector((SpectralIndexValues)spectrumBase));
- // }
-
- // Keys = CachedSelectors.Keys.ToArray();
-
- // var setters = ReflectionExtensions.GetSetters();
-
- // CachedSetters = new Dictionary>(getters.Count);
- // foreach (var keyValuePair in setters)
- // {
- // // var key = keyValuePair.Key;
- // var setter = keyValuePair.Value;
-
- // CachedSetters.Add(
- // keyValuePair.Key,
- // (spectrumBase, value) => setter(spectrumBase, value));
- // }
- //}
-
- public SpectralIndexValuesforContentDescription()
+ // Static constructors are called implicitly when the type is first used.
+ // Do NOT delete even if it has 0 references.
+ static SpectralIndexValuesForContentDescription()
{
- // empty constructor important!
- }
-
- //public SpectralIndexValuesforContentDescription(int spectrumLength, Dictionary indexProperties, IndexCalculateConfig configuration)
- //{
- // foreach (var cachedSetter in CachedSetters)
- // {
- // var defaultValue = 0.0;
-
- // if (indexProperties.ContainsKey(cachedSetter.Key))
- // {
- // var indexProperty = indexProperties[cachedSetter.Key];
- // if (indexProperty.IsSpectralIndex)
- // {
- // defaultValue = indexProperty.DefaultValue;
- // }
- // }
-
- // double[] initArray = new double[spectrumLength].FastFill(defaultValue);
-
- // // WARNING: Potential throw site
- // // No need to give following warning because should call CheckExistenceOfSpectralIndexValues() method before entering loop.
- // // This prevents multiple warnings through loop.
- // //this.SetPropertyValue(cachedSetter.Key, initArray);
-
- // cachedSetter.Value(this, initArray);
- // }
-
- // this.Configuration = configuration;
- //}
-
- ///
- /// Imports a dictionary of spectra.
- /// Assumes `CheckExistenceOfSpectralIndexValues` has already been called.
- /// Assumes frequency component is in fist index (i.e. frequency is rows) and time in second index (time is columns).
- ///
- ///
- /// The dictionary to convert to spectral index base
- ///
- public static SpectralIndexValues[] ImportFromDictionary(Dictionary dictionaryOfSpectra)
- {
- return dictionaryOfSpectra.FromTwoDimensionalArray(CachedSetters, TwoDimensionalArray.Rotate90AntiClockWise);
+ var result = MakeSelectors();
+ CachedSelectors = result.CachedSelectors;
+ CachedSetters = result.CachedSetters;
+ Keys = result.Keys;
}
- ///
- /// Used to check that the keys in the indexProperties dictionary correspond to Properties in the SpectralIndexValues class.
- /// Call this method before entering a loop because do not want the error message at every iteration through loop.
- ///
- public static void CheckExistenceOfSpectralIndexValues(Dictionary indexProperties)
+ public SpectralIndexValuesForContentDescription()
{
- foreach (var kvp in indexProperties)
- {
- if (!kvp.Value.IsSpectralIndex)
- {
- continue;
- }
-
- var success = CachedSelectors.ContainsKey(kvp.Key);
- if (!success)
- {
- LoggedConsole.WriteWarnLine(
- "### WARNING: The PROPERTY <" + kvp.Key + "> does not exist in the SpectralIndexValues class!");
- }
- }
+ // empty constructor important!
}
public static Dictionary> CachedSelectors { get; }
- public static Dictionary> CachedSetters { get; }
+ public static Dictionary> CachedSetters { get; }
public static string[] Keys { get; }
@@ -141,15 +57,7 @@ public static Image CreateImageOfSpectralIndices(SpectralIndexValues spectralInd
var combinedImage = ImageTools.CombineImagesVertically(images.ToArray());
return combinedImage;
}
-
- ///
- /// Gets the configuration used to generate these results.
- ///
- ///
- /// This property was added when we started generating lots of results that used
- /// different parameters - we needed a way to disambiguate them.
- ///
- public IndexCalculateConfig Configuration { get; }
+
// 1:
public double[] ACI { get; set; }
@@ -175,9 +83,6 @@ public static Image CreateImageOfSpectralIndices(SpectralIndexValues spectralInd
///
public double[] PMN { get; set; }
- //public override Dictionary> GetSelectors()
- //{
- // return CachedSelectors;
- //}
+ public override Dictionary> GetSelectors() => CachedSelectors;
}
}
\ No newline at end of file
diff --git a/src/AudioAnalysisTools/Indices/IndexCalculateSixOnly.cs b/src/AudioAnalysisTools/Indices/IndexCalculateSixOnly.cs
index 89c14646c..0f6c1373e 100644
--- a/src/AudioAnalysisTools/Indices/IndexCalculateSixOnly.cs
+++ b/src/AudioAnalysisTools/Indices/IndexCalculateSixOnly.cs
@@ -41,7 +41,8 @@ public class IndexCalculateSixOnly
/// boolean with default value = false.
/// An IndexCalculateResult.
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Reviewed. Suppression is OK here.")]
- public static IndexCalculateResult Analysis(
+ //////public static IndexCalculateResult Analysis(
+ public static SpectralIndexValuesForContentDescription Analysis(
AudioRecording recording,
TimeSpan segmentOffsetTimeSpan,
int sampleRateOfOriginalAudioFile,
@@ -66,16 +67,16 @@ public static IndexCalculateResult Analysis(
var config = new IndexCalculateConfig(); // sets some default values
int freqBinCount = frameSize / 2;
var indexProperties = GetIndexProperties();
- var result = new IndexCalculateResult(freqBinCount, indexProperties, indexCalculationDuration, segmentOffsetTimeSpan, config);
- //var result = new SpectralIndexValuesforContentDescription();
+ ////////var result = new IndexCalculateResult(freqBinCount, indexProperties, indexCalculationDuration, segmentOffsetTimeSpan, config);
+ var spectralIndices = new SpectralIndexValuesForContentDescription();
- //result.SummaryIndexValues = null;
- SpectralIndexValues spectralIndices = result.SpectralIndexValues;
+ ///////result.SummaryIndexValues = null;
+ ///////SpectralIndexValues spectralIndices = result.SpectralIndexValues;
// set up default spectrogram to return
- result.Sg = returnSonogramInfo ? GetSonogram(recording, windowSize: 1024) : null;
- result.Hits = null;
- result.TrackScores = new List();
+ ///////result.Sg = returnSonogramInfo ? GetSonogram(recording, windowSize: 1024) : null;
+ ///////result.Hits = null;
+ ///////result.TrackScores = new List();
// ################################## FINISHED SET-UP
// ################################## NOW GET THE AMPLITUDE SPECTROGRAM
@@ -154,8 +155,9 @@ public static IndexCalculateResult Analysis(
//spectralIndices.CVR = spActivity.CoverSpectrum;
spectralIndices.EVN = spActivity.EventSpectrum;
- result.TrackScores = null;
- return result;
+ ///////result.TrackScores = null;
+ ///////return result;
+ return spectralIndices;
} // end calculation of Six Spectral Indices
public static Dictionary GetIndexProperties()
@@ -183,7 +185,7 @@ public static Dictionary GetIndexProperties()
/// Transfers the required six indices from SpectralIndexBase to a dictionary.
/// IMPORTANT NOTE: THis method needs to be updated if there is a change to the indices used for content description.
///
- public static Dictionary ConvertIndicesToDictionary(SpectralIndexBase indexSet)
+ /*public static Dictionary ConvertIndicesToDictionary(SpectralIndexBase indexSet)
{
var dictionary = new Dictionary();
var aciArray = (double[])indexSet.GetPropertyValue("ACI");
@@ -199,7 +201,7 @@ public static Dictionary ConvertIndicesToDictionary(SpectralIn
var oscArray = (double[])indexSet.GetPropertyValue("OSC");
dictionary.Add("OSC", oscArray);
return dictionary;
- }
+ }*/
private static SpectrogramStandard GetSonogram(AudioRecording recording, int windowSize)
{
diff --git a/src/AudioAnalysisTools/Indices/SpectralIndexValues.cs b/src/AudioAnalysisTools/Indices/SpectralIndexValues.cs
index e11c0d057..f440eb85e 100644
--- a/src/AudioAnalysisTools/Indices/SpectralIndexValues.cs
+++ b/src/AudioAnalysisTools/Indices/SpectralIndexValues.cs
@@ -15,35 +15,14 @@ namespace AudioAnalysisTools.Indices
public class SpectralIndexValues : SpectralIndexBase
{
+ // Static constructors are called implicitly when the type is first used.
+ // Do NOT delete even if it has 0 references.
static SpectralIndexValues()
{
- var getters = ReflectionExtensions.GetGetters();
-
- CachedSelectors = new Dictionary>(getters.Count);
- foreach (var keyValuePair in getters)
- {
- // var key = keyValuePair.Key;
- var selector = keyValuePair.Value;
-
- CachedSelectors.Add(
- keyValuePair.Key,
- spectrumBase => selector((SpectralIndexValues)spectrumBase));
- }
-
- Keys = CachedSelectors.Keys.ToArray();
-
- var setters = ReflectionExtensions.GetSetters();
-
- CachedSetters = new Dictionary>(getters.Count);
- foreach (var keyValuePair in setters)
- {
- // var key = keyValuePair.Key;
- var setter = keyValuePair.Value;
-
- CachedSetters.Add(
- keyValuePair.Key,
- (spectrumBase, value) => setter(spectrumBase, value));
- }
+ var result = MakeSelectors();
+ CachedSelectors = result.CachedSelectors;
+ CachedSetters = result.CachedSetters;
+ Keys = result.Keys;
}
public SpectralIndexValues()
@@ -196,9 +175,6 @@ public static Image CreateImageOfSpectralIndices(SpectralIndexValues spectralInd
public double[] SUM { get; set; }
- public override Dictionary> GetSelectors()
- {
- return CachedSelectors;
- }
+ public override Dictionary> GetSelectors() => CachedSelectors;
}
}
\ No newline at end of file