Skip to content

Commit

Permalink
Changes to the use of parameters in the config files
Browse files Browse the repository at this point in the history
Issue #451 Final changes to the use of post-processing parameters in config files.
  • Loading branch information
towsey committed Feb 25, 2021
1 parent cabcefb commit dcc9559
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 87 deletions.
6 changes: 2 additions & 4 deletions src/AnalysisPrograms/Recognizers/Base/RecognizerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,7 @@ public override void WriteEventsFile(FileInfo destination, IEnumerable<EventBase
.Where(x => x is AcousticEvent)
.Select(x => (AcousticEvent)x));

// HACK: improve filename creation
/*var destinationBetaCsv = destination
var destinationBetaCsv = destination
.FullName
.Replace(".csv", ".beta.csv")
.ToFileInfo();
Expand All @@ -315,8 +314,7 @@ public override void WriteEventsFile(FileInfo destination, IEnumerable<EventBase
results
.Where(x => x is EventCommon)
.Select(x => (EventCommon)x));
*/
// HACK: improve filename creation

var destinationJson = destination
.FullName
.Replace(".csv", ".beta.json")
Expand Down
43 changes: 17 additions & 26 deletions src/AnalysisPrograms/Recognizers/GenericRecognizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,35 +139,31 @@ public override RecognizerResults Recognize(
var postprocessingConfig = configuration.PostProcessing;
var postEvents = new List<EventCommon>();

// count number of events detected at each decibel threshold.
for (int i = 1; i <= 39; i++)
{
var dbEvents = EventFilters.FilterOnDecibelDetectionThreshold(results.NewEvents, (double)i);
var groups = results.NewEvents.GroupBy(x => x.DecibelDetectionThreshold);

if (dbEvents.Count > 0)
{
//Log.Debug($"Profiles detected {dbEvents.Count} events at threshold {i} dB.");
var ppEvents = EventPostProcessing.PostProcessingOfSpectralEvents(
dbEvents,
postprocessingConfig,
(double)i,
results.Sonogram,
segmentStartOffset);

postEvents.AddRange(ppEvents);
}
foreach (var group in groups)
{
var key = group.Key;
List<EventCommon> events = group.ToList<EventCommon>();
Log.Debug($"Profiles detected {events.Count} events at threshold {key} dB.");

var ppEvents = EventPostProcessing.PostProcessingOfSpectralEvents(
events,
postprocessingConfig,
key.Value,
results.Sonogram,
segmentStartOffset);

postEvents.AddRange(ppEvents);
}

// Running profiles with multiple dB thresholds produces nested (Russian doll) events.
// Remove all but the outermost event.
// Add a spacer for easier reading of the debug output.
Log.Debug($" ");
Log.Debug($"Event count BEFORE removing enclosed events = {postEvents.Count}.");
Log.Debug($"## Event count BEFORE removing enclosed events = {postEvents.Count}.");
results.NewEvents = CompositeEvent.RemoveEnclosedEvents(postEvents);
Log.Debug($"Event count AFTER removing enclosed events = {postEvents.Count}.");
Log.Debug($"## Event count AFTER removing enclosed events = {postEvents.Count}.");

// Write out the events to log.
//Log.Debug($"FINAL event count = {postEvents.Count}.");
if (postEvents.Count > 0)
{
int counter = 0;
Expand All @@ -179,11 +175,6 @@ public override RecognizerResults Recognize(
}
}

//results.NewEvents = EventPostProcessing.PostProcessingOfSpectralEvents(
// results.NewEvents,
// postprocessingConfig,
// results.Sonogram,
// segmentStartOffset);
return results;
}

Expand Down
2 changes: 1 addition & 1 deletion src/AudioAnalysisTools/Events/EventCommon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public abstract class EventCommon : EventBase, IDrawableEvent
/// Gets or sets the Decibel threshold at which the event was detected.
/// This is used during post-processing to group events according to the threshold of their detection..
/// </summary>
public double DecibelDetectionThreshold { get; set; }
public double? DecibelDetectionThreshold { get; set; }

/// <summary>
/// Gets the component name for this event.
Expand Down
53 changes: 24 additions & 29 deletions src/AudioAnalysisTools/Events/EventFilters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,14 @@ public static List<EventCommon> FilterOnBandwidth(List<EventCommon> events, doub

public static List<EventCommon> FilterOnBandwidth(List<EventCommon> events, double minBandwidth, double maxBandwidth)
{
// The following line does it all BUT it does not allow for feedback to the user.
//var outputEvents = events.Where(ev => ((SpectralEvent)ev).BandWidthHertz >= minBandwidth && ((SpectralEvent)ev).BandWidthHertz <= maxBandwidth).ToList();
//var filteredEvents = events.Where(ev => ((SpectralEvent)ev).BandWidthHertz >= minBandwidth && ((SpectralEvent)ev).BandWidthHertz <= maxBandwidth).ToList();

/*
* ABC.where(x => {
Log.debug("ABC")
return x == somevalue;
});
*/

var filteredEvents = new List<EventCommon>();

Expand All @@ -98,7 +104,7 @@ public static List<EventCommon> FilterOnBandwidth(List<EventCommon> events, doub
}

/// <summary>
/// Removes short events from a list of events.
/// Filters list of events to remove short events.
/// </summary>
public static List<SpectralEvent> FilterShortEvents(List<SpectralEvent> events, double minimumDurationSeconds)
{
Expand All @@ -107,7 +113,7 @@ public static List<SpectralEvent> FilterShortEvents(List<SpectralEvent> events,
}

/// <summary>
/// Removes long events from a list of events.
/// Filters list of events to remove long events.
/// </summary>
public static List<SpectralEvent> FilterLongEvents(List<SpectralEvent> events, double maximumDurationSeconds)
{
Expand All @@ -116,16 +122,16 @@ public static List<SpectralEvent> FilterLongEvents(List<SpectralEvent> events, d
}

/// <summary>
/// Filters lists of spectral events based on their DecibelDetectionThreshold.
/// Filters lists of events based on their DecibelDetectionThreshold.
/// </summary>
/// <param name="events">The list of events.</param>
/// <param name="threshold">The Decibel Detection Threshold.</param>
/// <returns>The filtered list of events.</returns>
public static List<EventCommon> FilterOnDecibelDetectionThreshold(List<EventCommon> events, double threshold)
{
if (threshold <= 0.0)
if (threshold < 0.0)
{
throw new Exception("Invalid Decibel Detection Threshold passed to method EventExtentions.FilterOnDecibelDetectionThreshold(). Minimum threshold <= 0 seconds");
throw new Exception("Invalid Decibel Detection Threshold passed to EventExtentions.FilterOnDecibelDetectionThreshold(). Minimum accepted threshold = 0 dB");
}

// The following line does it all BUT it does not allow for feedback to the user.
Expand All @@ -134,7 +140,7 @@ public static List<EventCommon> FilterOnDecibelDetectionThreshold(List<EventComm
}

/// <summary>
/// Filters lists of spectral events based on their duration.
/// Filters lists of events based on their duration.
/// Note: The typical sigma threshold would be 2 to 3 sds.
/// </summary>
/// <param name="events">The list of events.</param>
Expand Down Expand Up @@ -250,10 +256,11 @@ public static List<EventCommon> FilterEventsOnSyllableCountAndPeriodicity(List<E
}
}

string strArray = DataTools.Array2String(actualPeriodSeconds.ToArray());
Log.Debug($" Event{count} actual periods: {strArray}");
//string strArray = DataTools.Array2String(actualPeriodSeconds.ToArray());
//Log.Debug($" Event{count} actual periods: {strArray}");
Log.Debug($" Event{count} actual periods: {actualPeriodSeconds.Join(",")}");

// reject composite events whose total syllable count exceeds the user defined max.
// reject composite events whose total syllable count exceeds the user defined max.
if (syllableCount > maxSyllableCount)
{
Log.Debug($" Event{count} rejected: Actual syllable count > max: {syllableCount} > {maxSyllableCount}");
Expand Down Expand Up @@ -362,9 +369,7 @@ public static (int Count, double AveragePeriod, double SdPeriod) GetPeriodicity(
/// <param name="spectrogram">A matrix of the spectrogram in which event occurs.</param>
/// <param name="lowerHertzBuffer">The band width of the required lower buffer. 100-200Hz is often appropriate.</param>
/// <param name="upperHertzBuffer">The band width of the required upper buffer. 300-500Hz is often appropriate.</param>
/// <param name="filterEventsOnSidebandBackground">A boolean that determines if event is to be filtered on sideband background.</param>
/// <param name="thresholdForBackgroundDecibels">The max allowed value for the average decibels value (over all spectrogram cells) in an event's sideband.</param>
/// <param name="filterEventsOnSidebandActivity">A boolean that determines if event is to be filtered on its sideband activity.</param>
/// <param name="thresholdForMaxSidebandActivity">The max allowed value for the decibels value in a sideband timeframe or freq bin.</param>
/// <param name="segmentStartOffset">Start time of the current recording segment.</param>
/// <returns>A list of filtered events.</returns>
Expand All @@ -373,10 +378,8 @@ public static List<EventCommon> FilterEventsOnSidebandActivity(
BaseSonogram spectrogram,
int lowerHertzBuffer,
int upperHertzBuffer,
bool filterEventsOnSidebandBackground,
double thresholdForBackgroundDecibels,
bool filterEventsOnSidebandActivity,
double thresholdForMaxSidebandActivity,
double? thresholdForBackgroundDecibels,
double? thresholdForMaxSidebandActivity,
TimeSpan segmentStartOffset)
{
// allow bin gaps below the event.
Expand Down Expand Up @@ -404,9 +407,7 @@ public static List<EventCommon> FilterEventsOnSidebandActivity(
lowerSidebandAccepted = IsSidebandActivityBelowThreshold(
lowerSidebandMatrix,
"Lower",
filterEventsOnSidebandBackground,
thresholdForBackgroundDecibels,
filterEventsOnSidebandActivity,
thresholdForMaxSidebandActivity);

if (!lowerSidebandAccepted)
Expand All @@ -422,9 +423,7 @@ public static List<EventCommon> FilterEventsOnSidebandActivity(
upperSidebandAccepted = IsSidebandActivityBelowThreshold(
upperSidebandMatrix,
"Upper",
filterEventsOnSidebandBackground,
thresholdForBackgroundDecibels,
filterEventsOnSidebandActivity,
thresholdForMaxSidebandActivity);

if (!upperSidebandAccepted)
Expand Down Expand Up @@ -458,18 +457,14 @@ public static List<EventCommon> FilterEventsOnSidebandActivity(
/// Therefore, also require that there be at most one sideband bin or frame containing acoustic activity greater than the supplied decibel threshold.
/// </summary>
/// <param name="sidebandMatrix">A matrix that represents a portion of spectrogram which is actually the sideband of an acoustic event.</param>
/// <param name="filterEventsOnSidebandBackground">A boolean that determines if the background test is done.</param>
/// <param name="thresholdForBackgroundDecibels">Decibel threshold for the background test.</param>
/// <param name="filterEventsOnSidebandActivity">A boolean that determines if the activity test is done.</param>
/// <param name="thresholdForActivityDecibels">Decibel threshold for the activity test.</param>
/// <returns>A boolean determining whether the sideband is accepoted or rejected.</returns>
public static bool IsSidebandActivityBelowThreshold(
double[,] sidebandMatrix,
string side,
bool filterEventsOnSidebandBackground,
double thresholdForBackgroundDecibels,
bool filterEventsOnSidebandActivity,
double thresholdForActivityDecibels)
double? thresholdForBackgroundDecibels,
double? thresholdForActivityDecibels)
{
//calculate the row averages and column averages. These are averages of decibel values.
var averageRowDecibels = MatrixTools.GetRowAverages(sidebandMatrix);
Expand All @@ -478,7 +473,7 @@ public static bool IsSidebandActivityBelowThreshold(
var averageMatrixDecibels = averageColDecibels.Average();

//perform the background acoustic test if filterEventsOnSidebandBackground = true.
if (filterEventsOnSidebandBackground)
if (thresholdForBackgroundDecibels != null)
{
// Is the background acoustic activity in the sideband below the user set threshold?
if (averageMatrixDecibels <= thresholdForBackgroundDecibels)
Expand All @@ -498,7 +493,7 @@ public static bool IsSidebandActivityBelowThreshold(

// The sideband is accepted based on Test 1. Now do test 2.
// Also need to cover possibility that there is much acoustic activity concentrated in one freq bin or time frame.
if (!filterEventsOnSidebandActivity)
if (thresholdForActivityDecibels == null)
{
Log.Debug($" {side}Sideband accepted without test 2 for concentrated acoustic activity.");
return true;
Expand Down
32 changes: 5 additions & 27 deletions src/AudioAnalysisTools/Events/Types/EventPostProcessing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public static List<EventCommon> PostProcessingOfSpectralEvents(
}

// 3: Filter the events for time duration (seconds)
if ((postprocessingConfig.Duration != null) && postprocessingConfig.Duration.FilterOnDuration && (newEvents.Count > 0))
if ((postprocessingConfig.Duration != null) && (newEvents.Count > 0))
{
Log.Debug($"FILTER ON EVENT DURATION");
var expectedEventDuration = postprocessingConfig.Duration.ExpectedDuration;
Expand All @@ -99,7 +99,7 @@ public static List<EventCommon> PostProcessingOfSpectralEvents(
}

// 4: Filter the events for bandwidth in Hertz
if ((postprocessingConfig.Bandwidth != null) && postprocessingConfig.Bandwidth.FilterOnBandwidth && (newEvents.Count > 0))
if ((postprocessingConfig.Bandwidth != null) && (newEvents.Count > 0))
{
Log.Debug($"FILTER ON EVENT BANDWIDTH");
var expectedEventBandwidth = postprocessingConfig.Bandwidth.ExpectedBandwidth;
Expand Down Expand Up @@ -128,9 +128,7 @@ public static List<EventCommon> PostProcessingOfSpectralEvents(
spectrogram,
sidebandActivity.LowerSidebandWidth,
sidebandActivity.UpperSidebandWidth,
sidebandActivity.FilterEventsOnSidebandBackground,
sidebandActivity.MaxBackgroundDecibels,
sidebandActivity.FilterEventsOnSidebandActivity,
sidebandActivity.MaxActivityDecibels,
segmentStartOffset);
Log.Debug($" Event count after filtering on sideband activity = {newEvents.Count}");
Expand Down Expand Up @@ -180,11 +178,6 @@ public class PostProcessingConfig
/// </summary>
public class DurationConfig
{
/// <summary>
/// Gets or sets a value indicating Whether or not to filter events on their duration.
/// </summary>
public bool FilterOnDuration { get; set; }

/// <summary>
/// Gets or sets a value indicating the Expected duration of an event.
/// </summary>
Expand All @@ -201,11 +194,6 @@ public class DurationConfig
/// </summary>
public class BandwidthConfig
{
/// <summary>
/// Gets or sets a value indicating Whether or not to filter events on their band-width.
/// </summary>
public bool FilterOnBandwidth { get; set; }

/// <summary>
/// Gets or sets a value indicating the Expected bandwidth of an event.
/// </summary>
Expand Down Expand Up @@ -234,29 +222,19 @@ public class SidebandConfig
/// </summary>
public int LowerSidebandWidth { get; set; }

/// <summary>
/// Gets or sets a value indicating Whether or not to filter events based on background noise in the sidebands.
/// </summary>
public bool FilterEventsOnSidebandBackground { get; set; }

/// <summary>
/// Gets or sets a value indicating the maximum permissible value of background acoustic activity in the upper and lower sidebands of an event.
/// The background is claculated as the average decibel value over all spectrogram cells in each sideband.
/// This value is used only if LowerHertzBuffer > 0 OR UpperHertzBuffer > 0.
/// </summary>
public double MaxBackgroundDecibels { get; set; }

/// <summary>
/// Gets or sets a value indicating Whether or not to filter events based on the presence of acoustic "events" in the sidebands.
/// </summary>
public bool FilterEventsOnSidebandActivity { get; set; }
public double? MaxBackgroundDecibels { get; set; }

/// <summary>
/// Gets or sets a value indicating the maximum decibel value in a sideband frequency bin or timeframe.
/// The decibel value is an average over all spectrogram cells in any frame or bin.
/// This value is used only if LowerHertzBuffer > 0 OR UpperHertzBuffer > 0.
/// </summary>
public double MaxActivityDecibels { get; set; }
public double? MaxActivityDecibels { get; set; }
}

/// <summary>
Expand Down Expand Up @@ -287,7 +265,7 @@ public class SyllableSequenceConfig
/// </summary>
public double SyllableHertzGap { get; set; }

// ################ The next four properties concern the filtering/removal of sequences that do not satisfy expected properties.
// ################ The next four properties concern the filtering or removal of sequences that do not satisfy expected properties.

/// <summary>
/// Gets or sets a value indicating Whether or not to remove/filter sequences having incorrect properties.
Expand Down

0 comments on commit dcc9559

Please sign in to comment.