From 1f5c47e0ab789f67e001943d46f119b00ada3754 Mon Sep 17 00:00:00 2001 From: Anthony Truskinger Date: Wed, 9 Dec 2020 03:23:54 +1000 Subject: [PATCH] Removed `Tag` from AcousticEvent The Tag property was a poorly implemented method of tagging an acoustic event with a boolean value. Unfortunately we deal with textual tags far more freuqently and the usage is confusing - particularly if the field is detected by automated tooling in output results. It was only used by two methods that calculated accuracy. Neither of those methods are curerntly used. Added to all that, AcousticEvent is on the deprecation path... so this change should be relatively minor --- src/AudioAnalysisTools/AcousticEvent.cs | 241 +----------------------- 1 file changed, 1 insertion(+), 240 deletions(-) diff --git a/src/AudioAnalysisTools/AcousticEvent.cs b/src/AudioAnalysisTools/AcousticEvent.cs index b1da3309c..dc4357b3e 100644 --- a/src/AudioAnalysisTools/AcousticEvent.cs +++ b/src/AudioAnalysisTools/AcousticEvent.cs @@ -45,7 +45,7 @@ public sealed class AcousticEventClassMap : ClassMap nameof(ScoreNormalised), nameof(Score_MaxPossible), nameof(Score_MaxInEvent), nameof(Score_TimeOfMaxInEvent), nameof(Score2Name), nameof(Score2), nameof(Periodicity), nameof(DominantFreq), - nameof(Tag), nameof(Intensity), nameof(Quality), nameof(HitColour), + nameof(Intensity), nameof(Quality), nameof(HitColour), }; public AcousticEventClassMap() @@ -185,12 +185,6 @@ public AcousticEventClassMap() public double DominantFreq { get; set; } // the dominant freq in the event - used for frog calls - /// - /// Gets or sets a value indicating whether gets or sets a value that can be used to filter or tag some members of a list of acoustic events. - /// Was used for constructing data sets. - /// - public bool Tag { get; set; } - /// Gets or sets assigned value when reading in a list of user identified events. Indicates a user assigned assessment of event intensity. public int Intensity { get; set; } @@ -621,239 +615,6 @@ public static List GetTaggedEventsInFile(List labe return events; } - /// - /// Given two lists of AcousticEvents, one being labelled events and the other being predicted events, - /// this method calculates the accuracy of the predictions in terms of tp, fp, fn etc. The events may come from any number of - /// recordings or files. - /// - public static void CalculateAccuracy(List results, List labels, out int tp, out int fp, out int fn, out double precision, out double recall, out double accuracy, out string resultsText) - { - //init values - tp = 0; - fp = 0; - - //header - string space = " "; - int count = 0; - List resultsSourceFiles = new List(); - string header = string.Format("\nScore Category: #{0,12}name{0,3}start{0,6}end{0,2}score1{0,2}score2{0,5}duration{0,6}source file", space); - LoggedConsole.WriteLine(header); - string line = null; - var sb = new StringBuilder(header + "\n"); - string previousSourceFile = " "; - - foreach (AcousticEvent ae in results) - { - count++; - double end = ae.TimeStart + ae.EventDurationSeconds; //calculate end time of the result event - var labelledEvents = GetEventsInFile(labels, ae.FileName); //get all & only those labelled events in same file as result ae - resultsSourceFiles.Add(ae.FileName); //keep list of source files that the detected events come from - AcousticEvent overlapLabelEvent = ae.OverlapsEventInList(labelledEvents); //get overlapped labelled event - if (overlapLabelEvent == null) - { - fp++; - line = - $"False POSITIVE: {count,4} {ae.Name,15} {ae.TimeStart,6:f1} ...{end,6:f1} {ae.Score,7:f1} {ae.Score2,7:f1}\t{ae.EventDurationSeconds,10:f2}"; - } - else - { - tp++; - overlapLabelEvent.Tag = true; //tag because later need to determine fn - line = - $"True POSITIVE: {count,4} {ae.Name,15} {ae.TimeStart,6:f1} ...{end,6:f1} {ae.Score,7:f1} {ae.Score2,7:f1}\t{ae.EventDurationSeconds,10:f2}"; - } - - if (previousSourceFile != ae.FileName) - { - LoggedConsole.WriteLine(line + "\t" + ae.FileName); - sb.Append(line + "\t" + ae.FileName + "\n"); - previousSourceFile = ae.FileName; - } - else - { - LoggedConsole.WriteLine(line + "\t || || || || || ||"); - sb.Append(line + "\t || || || || || ||\n"); - } - } - - //Now calculate the FALSE NEGATIVES. These are the labelled events not tagged in previous search. - LoggedConsole.WriteLine(); - sb.Append("\n"); - fn = 0; - count = 0; - previousSourceFile = " "; //this is just a device to achieve a formatting hwich is easier to interpret - foreach (AcousticEvent ae in labels) - { - count++; - string hitFile = string.Empty; - - //check if this FN event is in a file that score tp of fp hit. - if (resultsSourceFiles.Contains(ae.FileName)) - { - hitFile = "**"; - } - - if (ae.Tag == false) - { - fn++; - line = string.Format( - "False NEGATIVE: {0,4} {5,15} {1,6:f1} ...{2,6:f1} intensity={3} quality={4}", - count, - ae.TimeStart, - ae.TimeEnd, - ae.Intensity, - ae.Quality, - ae.Name); - if (previousSourceFile != ae.FileName) - { - LoggedConsole.WriteLine(line + "\t" + ae.FileName + " " + hitFile); - sb.Append(line + "\t" + ae.FileName + " " + hitFile + "\n"); - previousSourceFile = ae.FileName; - } - else - { - LoggedConsole.WriteLine(line + "\t || || || || || ||"); - sb.Append(line + "\t || || || || || ||\n"); - } - } - } - - if (fn == 0) - { - line = "NO FALSE NEGATIVES."; - } - else - { - line = "** This FN event occured in a recording which also scored a tp or fp hit."; - } - - LoggedConsole.WriteLine(line); - sb.Append(line + "\n"); - - if (tp + fp == 0) - { - precision = 0.0; - } - else - { - precision = tp / (double)(tp + fp); - } - - if (tp + fn == 0) - { - recall = 0.0; - } - else - { - recall = tp / (double)(tp + fn); - } - - accuracy = (precision + recall) / 2; - - resultsText = sb.ToString(); - } - - /// - /// Given two lists of AcousticEvents, one being labelled events and the other being predicted events, - /// this method calculates the accuracy of the predictions in terms of tp, fp, fn etc. - /// This method is similar to the one above except that it is assumed that all the events, both labelled and predicted - /// come from the same recording. - /// - public static void CalculateAccuracyOnOneRecording( - List results, - List labels, - out int tp, - out int fp, - out int fn, - out double precision, - out double recall, - out double accuracy, - out string resultsText) - { - //init values - tp = 0; - fp = 0; - fn = 0; - - //header - string space = " "; - int count = 0; - List resultsSourceFiles = new List(); - string header = string.Format("PREDICTED EVENTS: #{0,12}name{0,3}start{0,6}end{0,2}score1{0,2}score2{0,5}duration{0,6}source file", space); - - //LoggedConsole.WriteLine(header); - string line = null; - var sb = new StringBuilder(header + "\n"); - - foreach (AcousticEvent ae in results) - { - count++; - double end = ae.TimeStart + ae.EventDurationSeconds; //calculate end time of the result event - var labelledEvents = GetEventsInFile(labels, ae.FileName); //get all & only those labelled events in same file as result ae - resultsSourceFiles.Add(ae.FileName); //keep list of source files that the detected events come from - AcousticEvent overlapLabelEvent = ae.OverlapsEventInList(labelledEvents); //get overlapped labelled event - if (overlapLabelEvent == null) - { - fp++; - line = - $"False POSITIVE: {count,4} {ae.Name,15} {ae.TimeStart,6:f1} ...{end,6:f1} {ae.Score,7:f1} {ae.Score2,7:f1}\t{ae.EventDurationSeconds,10:f2}"; - } - else - { - tp++; - overlapLabelEvent.Tag = true; //tag because later need to determine fn - line = - $"True POSITIVE: {count,4} {ae.Name,15} {ae.TimeStart,6:f1} ...{end,6:f1} {ae.Score,7:f1} {ae.Score2,7:f1}\t{ae.EventDurationSeconds,10:f2}"; - } - - sb.Append(line + "\t" + ae.FileName + "\n"); - } - - //Now calculate the FALSE NEGATIVES. These are the labelled events not tagged in previous search. - //LoggedConsole.WriteLine(); - sb.Append("\n"); - count = 0; - foreach (AcousticEvent ae in labels) - { - count++; - if (ae.Tag == false) - { - fn++; - line = string.Format( - "False NEGATIVE: {0,4} {5,15} {1,6:f1} ...{2,6:f1} intensity={3} quality={4}", - count, - ae.TimeStart, - ae.TimeEnd, - ae.Intensity, - ae.Quality, - ae.Name); - sb.Append(line + "\t" + ae.FileName + "\n"); - } - } - - if (tp + fp == 0) - { - precision = 0.0; - } - else - { - precision = tp / (double)(tp + fp); - } - - if (tp + fn == 0) - { - recall = 0.0; - } - else - { - recall = tp / (double)(tp + fn); - } - - accuracy = (precision + recall) / 2; - - resultsText = sb.ToString(); - } - //################################################################################################################# //FOLLOWING TWO METHODS DEAL WITH THE OVERLAP OF EVENTS