diff --git a/Acoustics/Acoustics.Shared/FileNameHelpers.cs b/Acoustics/Acoustics.Shared/FileNameHelpers.cs index b86ccaab2..d855f49be 100644 --- a/Acoustics/Acoustics.Shared/FileNameHelpers.cs +++ b/Acoustics/Acoustics.Shared/FileNameHelpers.cs @@ -1,10 +1,12 @@ -namespace Acoustics.Shared +// +// 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). +// + +namespace Acoustics.Shared { using System; - using System.Collections.Generic; using System.IO; using System.Linq; - using System.Text; using System.Text.RegularExpressions; /// @@ -21,12 +23,6 @@ public static class FilenameHelpers /// /// Return an absolute path for a result file. /// - /// - /// - /// - /// - /// - /// public static string AnalysisResultPath( DirectoryInfo outputDirectory, FileInfo orignalFile, @@ -42,12 +38,6 @@ public static string AnalysisResultPath( /// /// Return an absolute path for a result file. /// - /// - /// - /// - /// - /// - /// public static string AnalysisResultPath( DirectoryInfo outputDirectory, string baseName, @@ -63,11 +53,6 @@ public static string AnalysisResultPath( /// /// Return a relative file name only (no directory) for a result file. /// - /// - /// - /// - /// - /// public static string AnalysisResultName(string baseName, string analysisTag, string newExtension, params string[] otherSegments) { if (string.IsNullOrWhiteSpace(baseName)) @@ -100,7 +85,6 @@ public static string AnalysisResultName(string baseName, string analysisTag, str return filename; } - public static void ParseAnalysisFileName( FileInfo file, out string originalBaseName, @@ -159,9 +143,6 @@ public static bool TryParseAnalysisFileName( /// Matches a very specific format: /// e.g. "4c77b524-1857-4550-afaa-c0ebe5e3960a_20101013_003000+1000_Towsey.Acoustic.ACI.csv" /// - /// - /// - /// public static bool TryParseOldStyleCsvFileName(string filename, out string analysisTag) { analysisTag = string.Empty; @@ -181,7 +162,6 @@ public static bool TryParseOldStyleCsvFileName(string filename, out string analy { return false; } - } } } diff --git a/AudioAnalysis/AnalysisConfigFiles/IndexPropertiesConfigForZooming.yml b/AudioAnalysis/AnalysisConfigFiles/IndexPropertiesConfigForZooming.yml new file mode 100644 index 000000000..97877b833 --- /dev/null +++ b/AudioAnalysis/AnalysisConfigFiles/IndexPropertiesConfigForZooming.yml @@ -0,0 +1,766 @@ +--- +# WARNING!!! The keys used below MUST BE EXACTLY the SAME as those declared in the class InitialiseIndexProperties (starting at line 30). + +# the root object name maps to the Key property on the IndexProperties class + +RankOrder: # AKA IndexCount + Name: Rank order of audio segment + Comment: "Rank of minute segment in temporal order from start of recording." + DataType: int + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 100.0 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: false + ComboWeight: 0.0 +StartOffset: + Name: Segment start time + Comment: "Exact time span (total minutes) from start of recording to start of this segment." + DataType: double + DefaultValue: 0.0 + DoDisplay: false + NormMin: 0.0 + NormMax: 200.0 + ProjectID: Acoustic Indices + Units: "min" + IncludeInComboIndex: false + ComboWeight: 0.0 +StartOffsetMinute: + Name: Segment start minute + Comment: "Total minutes from start of recording to start of this segment." + DataType: int + DefaultValue: 0.0 + DoDisplay: false + NormMin: 0.0 + NormMax: 200.0 + ProjectID: Acoustic Indices + Units: "min" + IncludeInComboIndex: false + ComboWeight: 0.0 +StartOffsetSecond: + Name: Segment start second + Comment: "Total seconds from start of recording to start of this segment." + DataType: int + DefaultValue: 0.0 + DoDisplay: false + NormMin: 0.0 + NormMax: 200.0 + ProjectID: Acoustic Indices + Units: "sec" + IncludeInComboIndex: false + ComboWeight: 0.0 +SegmentDuration: + Name: Time duration of audio segment + Comment: "Exact time span (total minutes) of this audio segment - typically 1.0 minutes." + DataType: TimeSpan + DefaultValue: 0.0 + DoDisplay: false + NormMin: 0.0 + NormMax: 1.0 + ProjectID: Acoustic Indices + Units: "min" + IncludeInComboIndex: false + ComboWeight: 0.0 +HighAmplitudeIndex: + Name: High Amplitude Index + Comment: "Av number of samples/sec where abs. amplitude is within 10*epislon of the max signal value." + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 1.0 + ProjectID: Acoustic Indices + Units: "av/s" + IncludeInComboIndex: false + ComboWeight: 0.0 +ZeroSignal: + Name: Zero Signal Index + Comment: "Indicates if signal segment is flat or zero." + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 1.0 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: false + ComboWeight: 0.0 +ClippingIndex: + Name: Clipping Index + Comment: "Av number of clipped samples/sec i.e. where the abs. amplitude of two conscutive samples is within 4*epislon of the max signal value." + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 1.0 + ProjectID: Acoustic Indices + Units: "avClips/s" + IncludeInComboIndex: false + ComboWeight: 0.0 +AvgSignalAmplitude: + Name: av Signal Ampl + Comment: "Av amplitude of the signal envelope in dB." + DataType: double + DefaultValue: -80 + DoDisplay: true + # SNR.MINIMUM_dB_BOUND_FOR_ZERO_SIGNAL = -80 dB + # -50 dB is typical level for environmental BGN + NormMin: -50.0 + NormMax: -10.0 + ProjectID: Acoustic Indices + Units: "dB" + IncludeInComboIndex: false + ComboWeight: 0.0 +BackgroundNoise: + Name: Background Noise + Comment: "Av amplitude of the noise removed from the audio segment using the method of Lamel et al." + DataType: double + DefaultValue: -80 + DoDisplay: true + # SNR.MINIMUM_dB_BOUND_FOR_ZERO_SIGNAL + 10 + NormMin: -50.0 + NormMax: -10.0 + ProjectID: Acoustic Indices + Units: "dB" + IncludeInComboIndex: false + ComboWeight: 0.0 +Snr: + Name: Maximum SNR + Comment: "Max amplitude of signal envelope after noise removal." + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 50.0 + ProjectID: Acoustic Indices + Units: "dB" + IncludeInComboIndex: false + ComboWeight: 0.0 +AvgSnrOfActiveFrames: + Name: av SNR (Active frames) + Comment: "Av amplitude of active frames in signal envelope after noise removal. Active frames are those with amplitude > threshold 3 dB." + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 30.0 + ProjectID: Acoustic Indices + Units: "dB" + IncludeInComboIndex: false + ComboWeight: 0.0 +Activity: + Name: Activity + Comment: "% of active frames i.e. where SNR exceeds threshold = 3 dB." + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 1.0 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: false + ComboWeight: 0.0 +EventsPerSecond: + Name: Events per sec + Comment: "Av number of events per second. An event is any consecutive sequence of active frames having duration > threshold = 100 ms." + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 5.0 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: false + ComboWeight: 0.0 +AvgEventDuration: + Name: Av Event Duration + Comment: "Av duration in ms of the events in an audio segment." + DataType: TimeSpan + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 1000 + ProjectID: Acoustic Indices + Units: "ms" + IncludeInComboIndex: false + ComboWeight: 0.0 +HighFreqCover: + Name: hf Cover + Comment: "% hf Cover 4000 Hz to 8800 Hz" + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0 + NormMax: 0.5 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: false + ComboWeight: 0.0 +MidFreqCover: + Name: mf Cover + Comment: "% mf Cover. 500 Hz to 4000 Hz" + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 0.50 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: false + ComboWeight: 0.0 +LowFreqCover: + Name: lf Cover + Comment: "% lf Cover. 0 - 500 Hz" + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 0.50 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: false + ComboWeight: 0.0 +AcousticComplexity: + Name: ACI + Comment: "ACI" + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.4 + NormMax: 0.7 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: true + ComboWeight: 0.2 +TemporalEntropy: + Name: 1-H[t] + Comment: "1-Ht is a measure of concentration of acoustic energy instead of energy dispersal." + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 0.5 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: true + ComboWeight: 0.3 +SqrtTempEntropy: + Name: Sqrt(1-H[t]) + Comment: "Sqrt(1-Ht) is an attempt to obtain more even distribution of Ht values. NormMax = sqrt(0.5)" + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 0.7 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: false + ComboWeight: 0.0 +LogTempEntropy: + Name: Log(1-H[t]) + Comment: "Log(1-Ht) is an attempt to obtain more even distribution of Ht values. NormMax = log(1 + 0.5)" + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 0.176 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: false + ComboWeight: 0.0 +EntropyOfAverageSpectrum: + Name: 1-H[avg spectrum] + Comment: "1-H[spectral avg] is a measure of concentration of acoustic energy in the average spectrum over one minute." + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 1.0 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: false + ComboWeight: 0.0 +EntropyOfVarianceSpectrum: + Name: 1-H[var spectrum] + Comment: "1-H[spectral var] is a measure of concentration of acoustic energy in the variance spectrum over one minute." + DataType: double + DefaultValue: 0.0 + DoDisplay: false + NormMin: 0.0 + NormMax: 1.0 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: false + ComboWeight: 0.0 +EntropyOfPeaksSpectrum: + Name: 1-H[peak freq spectrum] + Comment: "1-H[peak freq] is a measure of concentration of peak frequencies over one minute." + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 1.0 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: false + ComboWeight: 0.0 +EntropyOfCoVSpectrum: + Name: 1-H[CoV spectrum] + Comment: "1-H[CoV sp] is a measure of concentration of energy in the Coeff of Variance Spectrum." + DataType: double + DefaultValue: 0.0 + DoDisplay: false + NormMin: 0.0 + NormMax: 1.0 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: false + ComboWeight: 0.0 +ClusterCount: + Name: Cluster Count + Comment: "Number of spectral clusters in one minute audio segment as determined by a clustering algorithm." + DataType: int + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0 + NormMax: 50 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: true + ComboWeight: 0.3 +#AvgClusterDuration: +# Name: av Cluster Duration +# Comment: "Average duration in ms of the spectrum cluster sequences." +# DataType: TimeSpan +# DefaultValue: 0.0 +# DoDisplay: true +# NormMin: 0 +# NormMax: 250 +# ProjectID: Acoustic Indices +# Units: "ms" +# IncludeInComboIndex: false +# ComboWeight: 0.0 +ThreeGramCount: + Name: 3-gram Count + Comment: "Number of different tri-gram spectral cluster sequences." + DataType: int + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0 + NormMax: 1500 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: false + ComboWeight: 0.0 +SptDensity: + Name: SPT density + Comment: "Average number of spectral peaks tracks traversing a frame." + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 10.0 + ProjectID: Acoustic Indices + Units: "" + IncludeInComboIndex: false + ComboWeight: 0.0 +#SptPerSecond: +# Name: av Tracks/Sec +# Comment: "Average number of spectral tracks per second." +# DataType: double +# DefaultValue: 0.0 +# DoDisplay: true +# NormMin: 0 +# NormMax: 50 +# ProjectID: Acoustic Indices +# Units: "" +# IncludeInComboIndex: false +# ComboWeight: 0.0 +#AvgSptDuration: +# Name: av Track Duration +# Comment: "Average duration of a spectral track." +# DataType: TimeSpan +# DefaultValue: 0.0 +# DoDisplay: true +# NormMin: 0.25 +# NormMax: 2.0 +# ProjectID: Acoustic Indices +# Units: "s" +# IncludeInComboIndex: false +# ComboWeight: 0.0 +#RainIndex: +# Name: Rain Index +# Comment: "OBSOLETE! DEPRACATED! Rain score calculated every 10 sec and 6 values averaged over the minute." +# DataType: double +# DefaultValue: 0.0 +# DoDisplay: false +# NormMin: 0 +# NormMax: 1.0 +# ProjectID: Acoustic Indices +# Units: "" +# IncludeInComboIndex: false +# ComboWeight: 0.0 +#CicadaIndex: +# Name: Cicada Index +# Comment: "OBSOLETE! DEPRACATED! Cicada score calculated every 10 sec and 6 values averaged over the minute." +# DataType: double +# DefaultValue: 0.0 +# DoDisplay: false +# NormMin: 0 +# NormMax: 1.0 +# ProjectID: Acoustic Indices +# Units: "" +# IncludeInComboIndex: false +# ComboWeight: 0.0 +NDSI: + Name: NDSI + Comment: "Normalised Difference Soundscape Index) calculated from PSD - originated from Stuart Gage." + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: -1.0 + NormMax: 1.0 + ProjectID: Acoustic Indices + Units: "" +NDSI-LM: + Name: NDSI-LM + Comment: "Normalised Difference Soundscape Index) ratio of Mid/Low freq bands." + DataType: double + DefaultValue: 0.0 + DoDisplay: false + NormMin: -1.0 + NormMax: 1.0 + ProjectID: Acoustic Indices + Units: "" +NDSI-MH: + Name: NDSI-MH + Comment: "Normalised Difference Soundscape Index) ratio of High/Mid freq bands." + DataType: double + DefaultValue: 0.0 + DoDisplay: false + NormMin: -1.0 + NormMax: 1.0 + ProjectID: Acoustic Indices + Units: "" +EventsTotal: + Name: Event Count + Comment: "The total count of acoustic events per minute of recording." + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0 + NormMax: 15.0 + ProjectID: Acoustic Indices + Units: "" +EventsTotalThresholded: + Name: Event Count + Comment: "Count of acoustic events (wide range)" + DataType: double + DefaultValue: 0.0 + DoDisplay: false + NormMin: 5 + NormMax: 25 + ProjectID: Acoustic Indices + Units: "" +ZeroCrossingFractionLeft: + Name: Zero Crossing Fraction Left + Comment: "" + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 1.0 + ProjectID: Channel Integrity + Units: "" +ZeroCrossingFractionRight: + Name: Zero Crossing Fraction Right + Comment: "" + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 1.0 + ProjectID: Channel Integrity + Units: "" +ChannelSimilarity: + Name: Channel Similarity + Comment: "similarityIndex = (min*min)/(max*max), where min=min of two channels and max = max of the two. Summed over all freq bins" + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 1.0 + ProjectID: Channel Integrity + Units: "" +ChannelDiffDecibels: + Name: Channel Difference in decibels + Comment: "decibelIndex = dBmax-dBmin, where dBmin=min of two channels and dBmax = max of the two. Summed over all freq bins" + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: -8.0 + NormMax: 8.0 + ProjectID: Channel Integrity + Units: "decibels" +AverageDecibelBias: + Name: Average Channel Bias in decibels + Comment: "avDecibelBias += (dbLeft-dbRight). Summed over all freq bins" + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: -8.0 + NormMax: 8.0 + ProjectID: Channel Integrity + Units: "decibels" +MedianDecibelBias: + Name: Median Channel Bias in decibels + Comment: "medianDecibelBias += (medianOfLeftSpectrum-medianOfRightSpectrum). Summed over all freq bins" + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: -0.2 + NormMax: 0.2 + ProjectID: Channel Integrity + Units: "decibels" +LowFreqDecibelBias: + Name: Low Freq Channel dB Bias + Comment: "lowFreqDbBias += (dbLeft-dbRight). Summed over low freq bins, 0-2kHz" + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: -10.0 + NormMax: 10.0 + ProjectID: Channel Integrity + Units: "decibels" +MidFreqDecibelBias: + Name: Mid-Freq Channel dB Bias + Comment: "midFreqDbBias += (dbLeft-dbRight). Summed over mid freq bins, 2-7kHz" + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: -10.0 + NormMax: 10.0 + ProjectID: Channel Integrity + Units: "decibels" +HighFreqDecibelBias: + Name: High Freq Channel dB Bias + Comment: "highFreqDbBias += (dbLeft-dbRight). Summed over high freq bins, 7khz-nyquist" + DataType: double + DefaultValue: 0.0 + DoDisplay: true + NormMin: -5.0 + NormMax: 5.0 + ProjectID: Channel Integrity + Units: "decibels" +FileName: + Name: File Name + Comment: "FILLER TO STOP WARNING MESSAGE! File Name" + DataType: int + DefaultValue: 0.0 + DoDisplay: false + ProjectID: Acoustic Indices + Units: "" +# ADD THE SUMMARY INDICES ABOVE HERE +# ==================================================================================================================================== +# ==================================================================================================================================== +# ADD THE SPECTRAL INDICES BELOW HERE + +# IMPORTANT: SPECTRAL INDCIES MUST BE OF TYPE Double[] +ACI: + Name: spectralACI + Comment: "Spectrum of ACI values, one value for each frequency bin." + DataType: double[] + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.4 + NormMax: 0.7 + CalculateNormMin: true + CalculateNormMax: true + ProjectID: Acoustic Indices + Units: "" +BGN: + Name: spectralBGN + Comment: "Spectrum of dB value of the background 'noise' removed each frequency bin." + DataType: double[] + DefaultValue: -100.0 + DoDisplay: true + # min = SNR.MINIMUM_dB_BOUND_FOR_ZERO_SIGNAL - 20 = -80-20 = -100, + # Usual value is -30. However -20 adds more contrast into BGN spectrogram + NormMin: -100.0 + NormMax: -30.0 + CalculateNormMin: true + CalculateNormMax: true + ProjectID: Acoustic Indices + Units: "dB" +CLS: + Name: spectralCLS + Comment: "Cluster count: number of distinct spectral clusters in each freq bin of the mid-band." + DataType: double[] + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 4.0 + CalculateNormMin: true + CalculateNormMax: false + ProjectID: Acoustic Indices + Units: "" +CVR: + Name: spectralCVR + Comment: "Freq bin COVER: Spectrum of the fraction of active elements in each freq bin where amplitude > threshold = 3 dB." + # IMPORTANT - sometimes this is expressed as a percentage rather than fraction. NEED TO CHECK!! + DataType: double[] + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 0.7 + CalculateNormMin: true + CalculateNormMax: false + ProjectID: Acoustic Indices + Units: "" +# ComboWeight: 0.0 +DIF: + Name: spectralDIF + Comment: "Spectrum of summed DIFFERENCES between consecutive FFT coeff's in the ampl spgram. This spgram not displayed. It is used as intermediate for subsequent calculation of ACI." + DataType: double[] + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 10.0 + CalculateNormMin: false + CalculateNormMax: false + ProjectID: Acoustic Indices + Units: "" +ENT: + Name: spectralENT + Comment: "1 - Temporal Entropy. Default value = 0.0 because index = 1-Ht = a measure of concentration of acoustic energy instead of energy dispersal." + DataType: double[] + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 0.6 + CalculateNormMin: true + CalculateNormMax: false + ProjectID: Acoustic Indices + Units: "" +EVN: + Name: spectralEVN + Comment: "Spectrum of acoustic events per second (as defined above) in each frequency band." + DataType: double[] + DefaultValue: 0.0 + DoDisplay: true + NormMin: 2.0 + NormMax: 6.0 + CalculateNormMin: false + CalculateNormMax: true + ProjectID: Acoustic Indices + Units: "events/s" +SUM: + Name: spectralSUM + Comment: "Spectrum of summed FFT coefficients derived from the ampl spgram. This spgram not displayed. It is used for intermediate calculations only." + DataType: double[] + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 10.0 + CalculateNormMin: false + CalculateNormMax: false + ProjectID: Acoustic Indices + Units: "" +PMN: + Name: spectralPMN + Comment: "Spectrum of average dB power in each frequency bin after noise removal." + DataType: double[] + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 5.5 + CalculateNormMin: true + CalculateNormMax: false + ProjectID: Acoustic Indices + Units: "dB" +POW: + Name: spectralPOW + Comment: "DEPRACATED: Spectrum of average dB power in each frequency bin after noise removal." + DataType: double[] + DefaultValue: 0.0 + DoDisplay: true + NormMin: 3.0 + NormMax: 15.0 + CalculateNormMin: false + CalculateNormMax: false + ProjectID: Acoustic Indices + Units: "dB" +RHZ: + Name: spectralRHZ + Comment: "Spectrum of average number of horizontal spectral ridges per sec." + DataType: double[] + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.1 + NormMax: 1.5 + CalculateNormMin: false + CalculateNormMax: false + ProjectID: Acoustic Indices + Units: "tracks/s" +RVT: + Name: spectralRVT + Comment: "Spectrum of average number of vertical spectral ridges per sec." + DataType: double[] + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.1 + NormMax: 0.4 + CalculateNormMin: false + CalculateNormMax: false + ProjectID: Acoustic Indices + Units: "tracks/s" +RPS: + Name: spectralRPS + Comment: "Spectrum of average number of positive slope ridges per sec." + DataType: double[] + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 0.4 + CalculateNormMin: false + CalculateNormMax: false + ProjectID: Acoustic Indices + Units: "tracks/s" +RNG: + Name: spectralRNG + Comment: "Spectrum of average number of negative slope ridges per sec." + DataType: double[] + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.0 + NormMax: 0.4 + CalculateNormMin: false + CalculateNormMax: false + ProjectID: Acoustic Indices + Units: "tracks/s" +R3D: + Name: spectralR3D + Comment: "Spectrum of max value of horizontal, positive and negative slope ridges per sec." + DataType: double[] + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.15 + NormMax: 1.0 + CalculateNormMin: false + CalculateNormMax: false + ProjectID: Acoustic Indices + Units: "tracks/s" +SPT: + Name: spectralSPT + Comment: "Spectrum of average number of spectral Peak Tracks per second within each freq bin." + DataType: double[] + DefaultValue: 0.0 + DoDisplay: true + NormMin: 0.05 + NormMax: 0.5 + CalculateNormMin: false + CalculateNormMax: false + ProjectID: Acoustic Indices + Units: "tracks/s" \ No newline at end of file diff --git a/AudioAnalysis/AnalysisConfigFiles/SpectrogramZoomingConfig.yml b/AudioAnalysis/AnalysisConfigFiles/SpectrogramZoomingConfig.yml index ccb4f297e..3ab3654a5 100644 --- a/AudioAnalysis/AnalysisConfigFiles/SpectrogramZoomingConfig.yml +++ b/AudioAnalysis/AnalysisConfigFiles/SpectrogramZoomingConfig.yml @@ -31,5 +31,5 @@ LdSpectrogramConfig: XAxisTicIntervalSeconds: 3600 # Hertz YAxisTicInterval: 1000 -IndexPropertiesConfig: './IndexPropertiesConfig.yml' +IndexPropertiesConfig: './IndexPropertiesConfigForZooming.yml' ... \ No newline at end of file diff --git a/AudioAnalysis/AnalysisPrograms/Draw/Zooming/DrawZoomingSpectrograms.Dev.cs b/AudioAnalysis/AnalysisPrograms/Draw/Zooming/DrawZoomingSpectrograms.Dev.cs index fb29014ae..325d721f9 100644 --- a/AudioAnalysis/AnalysisPrograms/Draw/Zooming/DrawZoomingSpectrograms.Dev.cs +++ b/AudioAnalysis/AnalysisPrograms/Draw/Zooming/DrawZoomingSpectrograms.Dev.cs @@ -1,7 +1,10 @@ +// +// 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). +// + namespace AnalysisPrograms.Draw.Zooming { using System; - using System.IO; public static partial class DrawZoomingSpectrograms { @@ -62,12 +65,12 @@ public static Arguments Dev() //string opdir = @"C:\SensorNetworks\Output\BAC\HiResRidge"; // BIRD50 - string ipdir = @"C:\SensorNetworks\Output\BIRD50\Towsey.Acoustic"; - string opdir = @"C:\SensorNetworks\Output\BIRD50"; + //string ipdir = @"C:\SensorNetworks\Output\BIRD50\Towsey.Acoustic"; + //string opdir = @"C:\SensorNetworks\Output\BIRD50"; // ECLIPSE FARMSTAY - //string ipdir = @"C:\SensorNetworks\Output\FalseColourSpectrograms\Eclipse\EclipseFarmstay.200ms\Towsey.Acoustic"; - //string opdir = @"C:\SensorNetworks\Output\FalseColourSpectrograms\SpectrogramFocalZoom\FocalZoomImage"; + string ipdir = @"C:\SensorNetworks\Output\FalseColourSpectrograms\Eclipse\EclipseFarmstay.200ms\Towsey.Acoustic"; + string opdir = @"C:\SensorNetworks\Output\FalseColourSpectrograms\SpectrogramFocalZoom\FocalZoomImage"; //BRISTLE BIRD //string ipdir = @"C:\SensorNetworks\Output\BristleBird\Towsey.Acoustic"; @@ -85,12 +88,9 @@ public static Arguments Dev() //csp.TestImage(Path.Combine(opdir, "testImageCyanScale1.png")); // ################ TEST a colour scheme for the high resolution frame spectrograms. - var opDir = new DirectoryInfo(opdir); - //string config = @"C:\Work\GitHub\audio-analysis\AudioAnalysis\AnalysisConfigFiles\SpectrogramScalingConfig.json"; - //string config = @"C:\Work\GitHub\audio-analysis\AudioAnalysis\AnalysisConfigFiles\SpectrogramZoomingConfig.yml"; - string config = - @"C:\Work\GitHub\audio-analysis\AudioAnalysis\AnalysisConfigFiles\SpectrogramHiResConfig.yml"; + string config = @"C:\Work\GitHub\audio-analysis\AudioAnalysis\AnalysisConfigFiles\SpectrogramZoomingConfig.yml"; + //string config = @"C:\Work\GitHub\audio-analysis\AudioAnalysis\AnalysisConfigFiles\SpectrogramHiResConfig.yml"; return new Arguments { @@ -102,8 +102,9 @@ public static Arguments Dev() // draw a focused multi-resolution pyramid of images //ZoomAction = Arguments.ZoomActionType.Tile, ZoomAction = Arguments.ZoomActionType.Focused, - FocusMinute = 1, - //FocusMinute = 61, + + //FocusMinute = 1, + FocusMinute = 60, }; } } diff --git a/AudioAnalysis/AnalysisPrograms/Draw/Zooming/DrawZoomingSpectrograms.cs b/AudioAnalysis/AnalysisPrograms/Draw/Zooming/DrawZoomingSpectrograms.cs index 08d774f21..d2065537c 100644 --- a/AudioAnalysis/AnalysisPrograms/Draw/Zooming/DrawZoomingSpectrograms.cs +++ b/AudioAnalysis/AnalysisPrograms/Draw/Zooming/DrawZoomingSpectrograms.cs @@ -46,9 +46,10 @@ public static void Execute(Arguments arguments) LoggedConsole.WriteLine("# Input Directory : " + arguments.SourceDirectory); LoggedConsole.WriteLine("# Output Directory : " + arguments.Output); - var common = new ZoomArguments(); - - common.SpectrogramZoomingConfig = Yaml.Deserialise(arguments.SpectrogramTilingConfig); + var common = new ZoomArguments() + { + SpectrogramZoomingConfig = Yaml.Deserialise(arguments.SpectrogramTilingConfig), + }; // search for index properties config var indexPropertiesPath = IndexProperties.Find(common.SpectrogramZoomingConfig, arguments.SpectrogramTilingConfig); diff --git a/AudioAnalysis/AudioAnalysisTools/Indices/IndexGenerationData.cs b/AudioAnalysis/AudioAnalysisTools/Indices/IndexGenerationData.cs index fd553096a..e40a674a4 100644 --- a/AudioAnalysis/AudioAnalysisTools/Indices/IndexGenerationData.cs +++ b/AudioAnalysis/AudioAnalysisTools/Indices/IndexGenerationData.cs @@ -88,8 +88,8 @@ public static IndexGenerationData GetIndexGenerationData(DirectoryInfo directory public static FileInfo FindFile(DirectoryInfo directory) { - const string Pattern = "*" + FileNameFragment + "*"; - return directory.GetFiles(Pattern).Single(); + const string pattern = "*" + FileNameFragment + "*"; + return directory.GetFiles(pattern).Single(); } } } diff --git a/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/LDSpectrogramRGB.cs b/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/LDSpectrogramRGB.cs index d5c2b3d5d..6e006d69a 100644 --- a/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/LDSpectrogramRGB.cs +++ b/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/LDSpectrogramRGB.cs @@ -635,7 +635,7 @@ public Image DrawFalseColourSpectrogramChromeless(string colorMode, string color return bmp; } - public Image DrawBlendedFalseColourSpectrogram(string colorMode, string colorMap1, string colorMap2, double blendWt1, double blendWt2) + public Image DrawBlendedFalseColourSpectrogram(string colorMap1, string colorMap2, double blendWt1, double blendWt2) { if (!this.ContainsMatrixForKeys(colorMap1) || !this.ContainsMatrixForKeys(colorMap2)) { @@ -660,11 +660,7 @@ public Image DrawBlendedFalseColourSpectrogram(string colorMode, string colorMap matrix2 = this.GetNormalisedSpectrogramMatrix(rgbMap2[2]); var bluMatrix = MatrixTools.AddMatricesWeightedSum(matrix1, blendWt1, matrix2, blendWt2); - bool doReverseColour = colorMode.StartsWith("POS"); - - Image bmp = DrawRgbColourMatrix(redMatrix, grnMatrix, bluMatrix, doReverseColour); - - //bmp.Save(@"C:\SensorNetworks\Output\FalseColourSpectrograms\SpectrogramZoom\TiledImages\TESTIMAGE.png"); + var bmp = DrawRgbColourMatrix(redMatrix, grnMatrix, bluMatrix, false); return bmp; } @@ -1001,14 +997,16 @@ public double[] GetSummaryIndicesWeightedAtDistance(double[,] normalisedIndex1, double[] indices1 = MatrixTools.GetColumn(normalisedIndex1, minuteInDay); indices1 = DataTools.reverseArray(indices1); indices1 = CalculateDecayedSpectralIndices(indices1, distanceInMeters, decayConstant); - double[] indices2 = MatrixTools.GetColumn(normalisedIndex2, minuteInDay); - indices2 = DataTools.reverseArray(indices2); - indices2 = CalculateDecayedSpectralIndices(indices2, distanceInMeters, decayConstant); - double[] indices3 = MatrixTools.GetColumn(normalisedIndex3, minuteInDay); - indices3 = DataTools.reverseArray(indices3); - indices3 = CalculateDecayedSpectralIndices(indices3, distanceInMeters, decayConstant); - - return indices1; + + //double[] indices2 = MatrixTools.GetColumn(normalisedIndex2, minuteInDay); + //indices2 = DataTools.reverseArray(indices2); + //indices2 = CalculateDecayedSpectralIndices(indices2, distanceInMeters, decayConstant); + + //double[] indices3 = MatrixTools.GetColumn(normalisedIndex3, minuteInDay); + //indices3 = DataTools.reverseArray(indices3); + //indices3 = CalculateDecayedSpectralIndices(indices3, distanceInMeters, decayConstant); + + return indices1; // or indices2 or indices 3 } public static double[] CalculateDecayedSpectralIndices(double[] spectralIndices, int distanceInMeters, double halfLife) diff --git a/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/SpectrogramZoomingConfig.cs b/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/SpectrogramZoomingConfig.cs index 033b5ec92..4815ee7b5 100644 --- a/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/SpectrogramZoomingConfig.cs +++ b/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/SpectrogramZoomingConfig.cs @@ -43,6 +43,8 @@ public SpectrogramZoomingConfig() public double SpectralFrameDuration { get; set; } + public string ScaleUnits { get; set; } + /// /// Get or sets the number of zoom levels to render for standard FFT spectrogram images. /// Should contain about 1-3 steps following an inverse base-2 power distribution diff --git a/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/ZoomArguments.cs b/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/ZoomArguments.cs index c3da40142..a4db7b604 100644 --- a/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/ZoomArguments.cs +++ b/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/ZoomArguments.cs @@ -1,11 +1,12 @@ -namespace AudioAnalysisTools.LongDurationSpectrograms +// +// 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). +// + +namespace AudioAnalysisTools.LongDurationSpectrograms { - using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; - using System.Linq; - using System.Text; using Acoustics.Shared; using Acoustics.Shared.Contracts; using Indices; @@ -27,11 +28,10 @@ public class ZoomArguments /// We expect a valid indices output directory (the input directory in this action) /// to contain a SpectralIndexStatistics.json and a IndexGenerationData.json file /// - public static (FileInfo indexGenerationDataFile, FileInfo indexDistributionsFile) CheckNeededFilesExist( - DirectoryInfo indicesDirectory) + public static (FileInfo indexGenerationDataFile, FileInfo indexDistributionsFile) CheckNeededFilesExist(DirectoryInfo indicesDirectory) { - // NOTE: This file should not be compulsory requirement for this activity. At the most a warning could be - // written to say that file not found. + // NOTE: This file should not be compulsory requirement for this activity. + // At the most, a warning could be written to say that file not found. //indicesDirectory.GetFiles("*" + IndexDistributions.SpectralIndexStatisticsFilenameFragment + "*").Single(); return ( indexGenerationDataFile: IndexGenerationData.FindFile(indicesDirectory), @@ -45,11 +45,11 @@ public void GuessOriginalBasename() string[] otherSegments; FilenameHelpers.ParseAnalysisFileName(this.IndexGenerationDataFile, out originalBaseName, out analysisTag, out otherSegments); #if DEBUG - string originalBaseName2; - string analysisTag2; - string[] otherSegments2; - FilenameHelpers.ParseAnalysisFileName(this.IndexDistributionsFile, out originalBaseName2, out analysisTag2, out otherSegments2); - Debug.Assert(originalBaseName == originalBaseName2); + //string originalBaseName2; + //string analysisTag2; + //string[] otherSegments2; + //FilenameHelpers.ParseAnalysisFileName(this.IndexDistributionsFile, out originalBaseName2, out analysisTag2, out otherSegments2); + //Debug.Assert(originalBaseName == originalBaseName2); #endif this.OriginalBasename = originalBaseName; } @@ -67,7 +67,6 @@ public void CheckForNeededFiles(DirectoryInfo indicesDirectory) // this also means we can parse out other information from these files this.GuessOriginalBasename(); - } } } diff --git a/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/ZoomCommon.cs b/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/ZoomCommon.cs index 7c5a35687..8c0fd0c81 100644 --- a/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/ZoomCommon.cs +++ b/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/ZoomCommon.cs @@ -93,11 +93,12 @@ public static Image DrawIndexSpectrogramCommon( cs1.LoadSpectrogramDictionary(spectralSelection); var imageScaleInMsPerPixel = (int)imageScale.TotalMilliseconds; - double blendWt1 = 0.1; - double blendWt2 = 0.9; + double blendWt1 = 0.0; + double blendWt2 = 1.0; if (imageScaleInMsPerPixel > 15000) { + // > 15 seconds blendWt1 = 1.0; blendWt2 = 0.0; } @@ -108,33 +109,28 @@ public static Image DrawIndexSpectrogramCommon( } else if (imageScaleInMsPerPixel > 5000) { - blendWt1 = 0.8; - blendWt2 = 0.2; + blendWt1 = 0.7; + blendWt2 = 0.3; } else if (imageScaleInMsPerPixel > 1000) { - blendWt1 = 0.6; - blendWt2 = 0.4; + blendWt1 = 0.2; + blendWt2 = 0.8; } else if (imageScaleInMsPerPixel > 500) { - blendWt1 = 0.3; - blendWt2 = 0.7; + // > 0.5 seconds + blendWt1 = 0.1; + blendWt2 = 0.9; } - Image LdSpectrogram = cs1.DrawBlendedFalseColourSpectrogram( - "NEGATIVE", - colorMap1, - colorMap2, - blendWt1, - blendWt2); - - if (LdSpectrogram == null) + var ldfcSpectrogram = cs1.DrawBlendedFalseColourSpectrogram(colorMap1, colorMap2, blendWt1, blendWt2); + if (ldfcSpectrogram == null) { - throw new NullReferenceException("Null Image of DrawBlendedFalseColourSpectrogram"); + throw new NullReferenceException("Null Image returned from DrawBlendedFalseColourSpectrogram()"); } - return LdSpectrogram; + return ldfcSpectrogram; } } } \ No newline at end of file diff --git a/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/ZoomFocusedSpectrograms.cs b/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/ZoomFocusedSpectrograms.cs index f40542493..5cf49c776 100644 --- a/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/ZoomFocusedSpectrograms.cs +++ b/AudioAnalysis/AudioAnalysisTools/LongDurationSpectrograms/Zooming/ZoomFocusedSpectrograms.cs @@ -1,4 +1,8 @@ -/* +// +// 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). +// + +/* Action code for this analysis = ZoomingSpectrograms Activity Codes for other tasks to do with spectrograms and audio files: @@ -14,6 +18,7 @@ audiocutter - Cuts audio into segments of desired length and format createfoursonograms */ + namespace AudioAnalysisTools.LongDurationSpectrograms { using System; @@ -23,7 +28,6 @@ namespace AudioAnalysisTools.LongDurationSpectrograms using System.IO; using System.Linq; using Acoustics.Shared; - using Acoustics.Shared.Contracts; using DSP; using Indices; using StandardSpectrograms; @@ -32,54 +36,59 @@ namespace AudioAnalysisTools.LongDurationSpectrograms public static class ZoomFocusedSpectrograms { - public static void DrawStackOfZoomedSpectrograms(DirectoryInfo inputDirectory, DirectoryInfo outputDirectory, ZoomArguments common, - TimeSpan focalTime, int imageWidth) + public static void DrawStackOfZoomedSpectrograms( + DirectoryInfo inputDirectory, + DirectoryInfo outputDirectory, + ZoomArguments common, + TimeSpan focalTime, + int imageWidth) { var zoomConfig = common.SpectrogramZoomingConfig; LdSpectrogramConfig ldsConfig = common.SpectrogramZoomingConfig.LdSpectrogramConfig; - var distributions = IndexDistributions.Deserialize(common.IndexDistributionsFile); + + // var distributions = IndexDistributions.Deserialize(common.IndexDistributionsFile); var indexGeneration = Json.Deserialise(common.IndexGenerationDataFile); var indexProperties = common.IndexProperties; - string fileStem = common.OriginalBasename; + string fileStem = common.OriginalBasename; string analysisType = "Towsey.Acoustic"; - TimeSpan dataScale = indexGeneration.IndexCalculationDuration; + var dataScale = indexGeneration.IndexCalculationDuration; // ####################### DERIVE ZOOMED OUT SPECTROGRAMS FROM SPECTRAL INDICES var sw = Stopwatch.StartNew(); - string[] keys = { "ACI", "POW", "BGN", "CVR", "DIF", "ENT", "EVN", "RHZ", "RVT", "RPS", "RNG", "SUM", "SPT" }; + string[] keys = { "ACI", "BGN", "CVR", "DIF", "ENT", "EVN", "PMN", "POW", "RHZ", "RVT", "RPS", "RNG", "SUM", "SPT" }; Dictionary spectra = IndexMatrices.ReadCsvFiles(inputDirectory, fileStem + "__" + analysisType, keys); sw.Stop(); LoggedConsole.WriteLine("Time to read spectral index files = " + sw.Elapsed.TotalSeconds + " seconds"); - - sw = Stopwatch.StartNew(); // standard scales in seconds per pixel. - double[] imageScales = {60, 24, 12, 6, 2, 1, 0.6, 0.2}; + double[] imageScales = { 60, 24, 12, 6, 2, 1, 0.6, 0.2 }; if (zoomConfig.SpectralIndexScale != null) { imageScales = zoomConfig.SpectralIndexScale; } + sw = Stopwatch.StartNew(); int scaleCount = imageScales.Length; var imageList = new List(); - Image image = null; for (int i = 0; i < scaleCount; i++) { - TimeSpan imageScale = TimeSpan.FromSeconds(imageScales[i]); - image = DrawIndexSpectrogramAtScale(ldsConfig, indexGeneration, indexProperties, focalTime, dataScale, imageScale, imageWidth, spectra, fileStem); + var imageScale = TimeSpan.FromSeconds(imageScales[i]); + var image = DrawIndexSpectrogramAtScale(ldsConfig, indexGeneration, indexProperties, focalTime, dataScale, imageScale, imageWidth, spectra, fileStem); if (image != null) { imageList.Add(image); - string name = string.Format("{0}_FocalZoom_min{1:f1}_scale{2}.png", fileStem, focalTime.TotalMinutes, imageScales[i]); + string name = $"{fileStem}_FocalZoom_min{focalTime.TotalMinutes:f1}_scale{imageScales[i]}.png"; image.Save(Path.Combine(outputDirectory.FullName, name)); } - } + sw.Stop(); LoggedConsole.WriteLine("Finished spectrograms derived from spectral indices. Elapsed time = " + sw.Elapsed.TotalSeconds + " seconds"); - + /* + * // NOTE: COMMENTED OUT THIS SECTION OF CODE ON 16th NOVEMBER 2017 when trying to revive the ZOOMING code. + * No longer needed. // ####################### DERIVE ZOOMED IN SPECTROGRAMS FROM STANDARD SPECTRAL FRAMES int[] compressionFactor = { 8, 4, 2, 1 }; int compressionCount = compressionFactor.Length; @@ -89,28 +98,34 @@ public static void DrawStackOfZoomedSpectrograms(DirectoryInfo inputDirectory, D if (zoomConfig.SpectralFrameScale != null) { imageScales = zoomConfig.SpectralFrameScale; + // TODO: CONVERT IMAGE scales into Compression factors. compressionCount = imageScales.Length; compressionFactor = new int[compressionCount]; - compressionFactor[compressionCount-1] = 1; + compressionFactor[compressionCount - 1] = 1; double denom = imageScales[compressionCount - 1]; - for (int i = 0; i < compressionCount-1; i++) + for (int i = 0; i < compressionCount - 1; i++) + { compressionFactor[i] = (int)Math.Round(imageScales[i] / denom); + } } - int maxCompression = compressionFactor[0]; + int maxCompression = compressionFactor[0]; TimeSpan maxImageDuration = TimeSpan.FromTicks(maxCompression * imageWidth * frameScale.Ticks); TimeSpan halfMaxImageDuration = TimeSpan.FromMilliseconds(maxImageDuration.TotalMilliseconds / 2); TimeSpan startTimeOfMaxImage = TimeSpan.Zero; if (focalTime != TimeSpan.Zero) + { startTimeOfMaxImage = focalTime - halfMaxImageDuration; + } + TimeSpan startTimeOfData = TimeSpan.FromMinutes(Math.Floor(startTimeOfMaxImage.TotalMinutes)); List frameData = ReadFrameData(inputDirectory, fileStem, startTimeOfMaxImage, maxImageDuration, zoomConfig, indexGeneration.MaximumSegmentDuration.Value); // get the index data to add into the - TimeSpan imageScale1 = TimeSpan.FromSeconds(0.1); + // TimeSpan imageScale1 = TimeSpan.FromSeconds(0.1); double[,] indexData = spectra["POW"]; // make the images @@ -118,35 +133,27 @@ public static void DrawStackOfZoomedSpectrograms(DirectoryInfo inputDirectory, D { int factor = compressionFactor[i]; image = DrawFrameSpectrogramAtScale(ldsConfig, indexGeneration, startTimeOfData, factor, frameData, indexData, focalTime, frameScale, imageWidth); - if (image != null) imageList.Add(image); + if (image != null) + { + imageList.Add(image); + } } sw.Stop(); LoggedConsole.WriteLine("Finished spectrograms derived from standard frames. Elapsed time = " + sw.Elapsed.TotalSeconds + " seconds"); - + // ####################### FINSIHED ZOOMED-IN SPECTROGRAMS DERIVED FROM STANDARD SPECTRAL FRAMES + */ // combine the images into a stack Image combinedImage = ImageTools.CombineImagesVertically(imageList); - string fileName = string.Format("{0}_FocalZOOM_min{1:f1}.png", fileStem, focalTime.TotalMinutes); + string fileName = $"{fileStem}_FocalZOOM_min{focalTime.TotalMinutes:f1}.png"; combinedImage.Save(Path.Combine(outputDirectory.FullName, fileName)); } - - /// /// This method can add in absolute time if you want. /// Currently commented out - see below. /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// public static Image DrawIndexSpectrogramAtScale( LdSpectrogramConfig config, IndexGenerationData indexGenerationData, @@ -155,7 +162,8 @@ public static Image DrawIndexSpectrogramAtScale( TimeSpan dataScale, TimeSpan imageScale, int imageWidth, - Dictionary spectra, string basename) + Dictionary spectra, + string basename) { if (spectra == null) { @@ -171,8 +179,8 @@ public static Image DrawIndexSpectrogramAtScale( return null; } - Dictionary dictIP = indexProperties; - dictIP = InitialiseIndexProperties.FilterIndexPropertiesForSpectralOnly(dictIP); + Dictionary dictIp = indexProperties; + dictIp = InitialiseIndexProperties.FilterIndexPropertiesForSpectralOnly(dictIp); // calculate start time by combining DatetimeOffset with minute offset. TimeSpan sourceMinuteOffset = indexGenerationData.MinuteOffset; @@ -185,47 +193,63 @@ public static Image DrawIndexSpectrogramAtScale( // calculate data duration from column count of abitrary matrix var kvp = spectra.First(); var matrix = kvp.Value; + //var matrix = spectra["ACI"]; // assume this key will always be present!! TimeSpan dataDuration = TimeSpan.FromSeconds(matrix.GetLength(1) * dataScale.TotalSeconds); - TimeSpan recordingStartTime = TimeSpan.Zero; // default = zero minute of day i.e. midnight + var recordingStartTime = TimeSpan.Zero; // default = zero minute of day i.e. midnight recordingStartTime = TimeTools.DateTimePlusTimeSpan(indexGenerationData.RecordingStartDate, indexGenerationData.MinuteOffset); TimeSpan offsetTime = TimeSpan.Zero; - TimeSpan ImageDuration = TimeSpan.FromTicks(imageWidth * imageScale.Ticks); + TimeSpan imageDuration = TimeSpan.FromTicks(imageWidth * imageScale.Ticks); TimeSpan halfImageDuration = TimeSpan.FromTicks(imageWidth * imageScale.Ticks / 2); TimeSpan startTime = TimeSpan.Zero; - if (focalTime != TimeSpan.Zero) startTime = focalTime - halfImageDuration; + if (focalTime != TimeSpan.Zero) + { + startTime = focalTime - halfImageDuration; + } + if (startTime < TimeSpan.Zero) { offsetTime = TimeSpan.Zero - startTime; - startTime = TimeSpan.Zero; + startTime = TimeSpan.Zero; + } + + var endTime = imageDuration; + if (focalTime != TimeSpan.Zero) + { + endTime = focalTime + halfImageDuration; } - TimeSpan endTime = ImageDuration; - if (focalTime != TimeSpan.Zero) endTime = focalTime + halfImageDuration; - if (endTime > dataDuration) endTime = dataDuration; + + if (endTime > dataDuration) + { + endTime = dataDuration; + } + TimeSpan spectrogramDuration = endTime - startTime; int spectrogramWidth = (int)(spectrogramDuration.Ticks / imageScale.Ticks); // get the plain unchromed spectrogram - Image LDSpectrogram = ZoomCommon.DrawIndexSpectrogramCommon( + Image ldfcSpectrogram = ZoomCommon.DrawIndexSpectrogramCommon( config, indexGenerationData, indexProperties, - startTime, endTime, - dataScale, imageScale, imageWidth, + startTime, + endTime, + dataScale, + imageScale, + imageWidth, spectra, basename); - if (LDSpectrogram == null) + if (ldfcSpectrogram == null) { - LoggedConsole.WriteLine("WARNING: NO SPECTROGRAM AT SCALE "+ imageScale); + LoggedConsole.WriteLine("WARNING: NO SPECTROGRAM AT SCALE " + imageScale); return null; } - // now chrome spectrogram - Graphics g2 = Graphics.FromImage(LDSpectrogram); + Graphics g2 = Graphics.FromImage(ldfcSpectrogram); // draw red line at focus time if (focalTime != TimeSpan.Zero) @@ -233,13 +257,16 @@ public static Image DrawIndexSpectrogramAtScale( Pen pen = new Pen(Color.Red); TimeSpan focalOffset = focalTime - startTime; int x1 = (int)(focalOffset.Ticks / imageScale.Ticks); - g2.DrawLine(pen, x1, 0, x1, LDSpectrogram.Height); + g2.DrawLine(pen, x1, 0, x1, ldfcSpectrogram.Height); } // draw the title bar int nyquist = 22050 / 2; // default if (indexGenerationData.SampleRateResampled > 0) + { nyquist = indexGenerationData.SampleRateResampled / 2; + } + int herzInterval = 1000; if (config != null) { @@ -251,9 +278,9 @@ public static Image DrawIndexSpectrogramAtScale( //add chrome // NEXT LINE USED ONLY IF WANT ABSOLUTE TIME //startTime += recordingStartTime; - Image titleBar = DrawTitleBarOfZoomSpectrogram(title, LDSpectrogram.Width); - LDSpectrogram = FrameZoomSpectrogram( - LDSpectrogram, + Image titleBar = DrawTitleBarOfZoomSpectrogram(title, ldfcSpectrogram.Width); + ldfcSpectrogram = FrameZoomSpectrogram( + ldfcSpectrogram, titleBar, startTime, imageScale, @@ -262,17 +289,15 @@ public static Image DrawIndexSpectrogramAtScale( herzInterval); // create the base canvas image on which to centre the focal image - Image image = new Bitmap(imageWidth, LDSpectrogram.Height); + Image image = new Bitmap(imageWidth, ldfcSpectrogram.Height); Graphics g1 = Graphics.FromImage(image); g1.Clear(Color.DarkGray); - int Xoffset = (int)(offsetTime.Ticks / imageScale.Ticks); - g1.DrawImage(LDSpectrogram, Xoffset, 0); - + int xOffset = (int)(offsetTime.Ticks / imageScale.Ticks); + g1.DrawImage(ldfcSpectrogram, xOffset, 0); return image; } - /// /// This method can add in the absolute recording start time. However currently disabled. /// @@ -325,7 +350,7 @@ public static Image DrawFrameSpectrogramAtScale( spectralSelection = TemporalMatrix.CompressFrameSpectrograms(spectralSelection, compressionFactor); } - Image spectrogramImage = DrawStandardSpectrogramInFalseColour(spectralSelection); + Image spectrogramImage = DrawStandardSpectrogramInFalseColour(spectralSelection); Graphics g2 = Graphics.FromImage(spectrogramImage); @@ -345,7 +370,7 @@ public static Image DrawFrameSpectrogramAtScale( } int herzInterval = config.YAxisTicInterval; - string title = string.Format("ZOOM SCALE={0}ms/pixel Image duration={1} ", imageScale.TotalMilliseconds, imageDuration); + string title = $"ZOOM SCALE={imageScale.TotalMilliseconds}ms/pixel Image duration={imageDuration} "; Image titleBar = DrawTitleBarOfZoomSpectrogram(title, spectrogramImage.Width); // add the recording start time ONLY IF WANT ABSOLUTE TIME SCALE - obtained from info in file name @@ -372,13 +397,11 @@ public static Image DrawFrameSpectrogramAtScale( return image; } - - public static List ReadFrameData(DirectoryInfo dataDir, string fileStem, TimeSpan startTime, TimeSpan maxDuration, SpectrogramZoomingConfig zoomingConfig, TimeSpan indexGenerationSegmentDuration) { TimeSpan endTime = startTime + maxDuration; int startMinute = (int)Math.Floor(startTime.TotalMinutes); - int endMinute = (int)Math.Ceiling(endTime.TotalMinutes); + int endMinute = (int)Math.Ceiling(endTime.TotalMinutes); int expectedDataDurationInSeconds = (int)indexGenerationSegmentDuration.TotalSeconds; int expectedFrameCount = (int)Math.Round(expectedDataDurationInSeconds / zoomingConfig.SpectralFrameDuration); @@ -400,11 +423,10 @@ public static List ReadFrameData(DirectoryInfo dataDir, string fileSte frameData.AddRange(data); } + return frameData; } - - public static Dictionary CompressFrameSpectrogram(Dictionary spectra, TimeSpan imageScale, TimeSpan defaultTimeScale) { int scalingFactor = (int)Math.Round(imageScale.TotalMilliseconds / defaultTimeScale.TotalMilliseconds); @@ -415,27 +437,31 @@ public static Dictionary CompressFrameSpectrogram(Dictionary< double[,] matrix = spectra[key]; int rowCount = matrix.GetLength(0); int colCount = matrix.GetLength(1); - int compressedLength = (colCount / scalingFactor); + int compressedLength = colCount / scalingFactor; var newMatrix = new double[rowCount, compressedLength]; double[] tempArray = new double[scalingFactor]; // take the MAX for (int r = 0; r < rowCount; r++) { - int colIndex = 0; for (int c = 0; c < colCount - scalingFactor; c += step) { - colIndex = c / scalingFactor; - for (int i = 0; i < scalingFactor; i++) tempArray[i] = matrix[r, c + i]; + var colIndex = c / scalingFactor; + for (int i = 0; i < scalingFactor; i++) + { + tempArray[i] = matrix[r, c + i]; + } + newMatrix[r, colIndex] = tempArray.Max(); } } + compressedSpectra[key] = newMatrix; } + return compressedSpectra; } - private static Dictionary GetConfigurationForConvCNN(FileInfo configFile) { dynamic configuration = Yaml.Deserialise(configFile); @@ -452,16 +478,11 @@ private static Dictionary GetConfigurationForConvCNN(FileInfo co return configDict; } - - - /// /// A FALSE-COLOUR VERSION OF DECIBEL SPECTROGRAM /// Taken and adapted from Spectrogram Image 5 in the method of CLASS Audio2InputForConvCNN.cs: /// /// the sonogram data (NOT noise reduced) - /// - /// public static Image DrawStandardSpectrogramInFalseColour(double[,] dbSpectrogramData) { // Do NOISE REDUCTION @@ -471,7 +492,6 @@ public static Image DrawStandardSpectrogramInFalseColour(double[,] dbSpectrogram double ridgeThreshold = 2.5; double[,] matrix = dbSpectrogramData; - //double[,] matrix = ImageTools.WienerFilter(dbSpectrogramData, 3); byte[,] hits = RidgeDetection.Sobel5X5RidgeDetectionExperiment(matrix, ridgeThreshold); // ################### RESEARCH QUESTION: @@ -486,7 +506,6 @@ public static Image DrawStandardSpectrogramInFalseColour(double[,] dbSpectrogram //range = max - min; // ULTIMATELY THE BEST APPROACH APPEARED TO BE FIXED NORMALISATION BOUNDS - double truncateMin = -95.0; double truncateMax = -30.0; double filterCoefficient = 0.75; @@ -494,20 +513,18 @@ public static Image DrawStandardSpectrogramInFalseColour(double[,] dbSpectrogram truncateMin = 0; truncateMax = 50; + + // nr = noise reduced double[,] nrSpectrogramNorm = SpectrogramTools.NormaliseSpectrogramMatrix(nrSpectrogramData, truncateMin, truncateMax, filterCoefficient); - //nrSpectrogramNorm = DataTools.NormaliseMatrixValues(nrSpectrogramNorm); nrSpectrogramNorm = MatrixTools.BoundMatrix(nrSpectrogramNorm, 0.0, 0.9); nrSpectrogramNorm = MatrixTools.SquareRootOfValues(nrSpectrogramNorm); nrSpectrogramNorm = DataTools.normalise(nrSpectrogramNorm); // create image from normalised data - Image image = SpectrogramTools.CreateFalseColourDecibelSpectrogramForZooming(dbSpectrogramNorm, nrSpectrogramNorm, hits); - //image.Save(@"C:\SensorNetworks\Output\Sonograms\TEST3.png", ImageFormat.Png); - + var image = SpectrogramTools.CreateFalseColourDecibelSpectrogramForZooming(dbSpectrogramNorm, nrSpectrogramNorm, hits); return image; } - public static Image DrawTitleBarOfZoomSpectrogram(string title, int width) { //Image colourChart = LDSpectrogramRGB.DrawColourScale(width, SpectrogramConstants.HEIGHT_OF_TITLE_BAR - 2); @@ -515,29 +532,28 @@ public static Image DrawTitleBarOfZoomSpectrogram(string title, int width) Bitmap bmp = new Bitmap(width, height); Graphics g = Graphics.FromImage(bmp); g.Clear(Color.Black); - Pen pen = new Pen(Color.White); Font stringFont = new Font("Arial", 9); - //Font stringFont = new Font("Tahoma", 9); - SizeF stringSize = new SizeF(); + int x1 = 4; + g.DrawString(title, stringFont, Brushes.Wheat, new PointF(x1, 3)); - int X = 4; - g.DrawString(title, stringFont, Brushes.Wheat, new PointF(X, 3)); + SizeF stringSize = g.MeasureString(title, stringFont); + x1 += stringSize.ToSize().Width + 70; - stringSize = g.MeasureString(title, stringFont); - X += (stringSize.ToSize().Width + 70); //g.DrawString(text, stringFont, Brushes.Wheat, new PointF(X, 3)); - //stringSize = g.MeasureString(text, stringFont); //X += (stringSize.ToSize().Width + 1); //g.DrawImage(colourChart, X, 1); string text = Meta.OrganizationTag; stringSize = g.MeasureString(text, stringFont); - int X2 = width - stringSize.ToSize().Width - 2; - if (X2 > X) g.DrawString(text, stringFont, Brushes.Wheat, new PointF(X2, 3)); + int x2 = width - stringSize.ToSize().Width - 2; + if (x2 > x1) + { + g.DrawString(text, stringFont, Brushes.Wheat, new PointF(x2, 3)); + } - g.DrawLine(new Pen(Color.LightGray), 0, 0, width, 0);//draw upper boundary - g.DrawLine(new Pen(Color.LightGray), 0, 1, width, 1);//draw upper boundary + g.DrawLine(new Pen(Color.LightGray), 0, 0, width, 0); //draw upper boundary + g.DrawLine(new Pen(Color.LightGray), 0, 1, width, 1); //draw upper boundary g.DrawLine(new Pen(Color.LightGray), 0, height - 1, width, height - 1); //draw lower boundary g.DrawLine(new Pen(Color.Red), 0, 2, 0, height - 1); //draw start boundary g.DrawLine(new Pen(Color.Pink), width - 1, 2, width - 1, height - 1); //draw end boundary @@ -549,16 +565,16 @@ public static Image FrameZoomSpectrogram(Image bmp1, Image titleBar, TimeSpan st TimeSpan fullDuration = TimeSpan.FromTicks(xAxisPixelDuration.Ticks * bmp1.Width); // init frequency scale - int frameSize = bmp1.Height; + int frameSize = bmp1.Height * 2; // THIS MIGHT BECOME A BUG ONE DAY!!!!! var freqScale = new FrequencyScale(nyquist, frameSize, herzInterval); SpectrogramTools.DrawGridLinesOnImage((Bitmap)bmp1, startOffset, fullDuration, xAxisTicInterval, freqScale); int trackHeight = 20; // put start offset into a datetime object. - DateTimeOffset dto = new DateTimeOffset(); + var dto = default(DateTimeOffset); dto = dto + startOffset; - Bitmap timeBmp = Image_Track.DrawTimeTrack(fullDuration, dto, bmp1.Width, trackHeight); - int imageHt = bmp1.Height + titleBar.Height + trackHeight +1; + var timeBmp = Image_Track.DrawTimeTrack(fullDuration, dto, bmp1.Width, trackHeight); + int imageHt = bmp1.Height + titleBar.Height + trackHeight + 1; Bitmap compositeBmp = new Bitmap(bmp1.Width, imageHt); //get canvas for entire image Graphics gr = Graphics.FromImage(compositeBmp); @@ -571,8 +587,5 @@ public static Image FrameZoomSpectrogram(Image bmp1, Image titleBar, TimeSpan st gr.DrawImage(timeBmp, 0, offset); //draw return compositeBmp; } - - - } }