Example #1
0
        public static void Execute(Arguments arguments)
        {
            MainEntry.WarnIfDeveloperEntryUsed();

            TowseyLibrary.Log.Verbosity = 1;
            string date = "# DATE AND TIME: " + DateTime.Now;

            LoggedConsole.WriteLine("# Running acoustic event detection.");
            LoggedConsole.WriteLine(date);

            FileInfo      recodingFile     = arguments.Source;
            var           recodingBaseName = recodingFile.BaseName();
            DirectoryInfo outputDir        = arguments.Output.Combine(EcosoundsAedIdentifier);

            outputDir.Create();

            Log.Info("# Output folder =" + outputDir);
            Log.Info("# Recording file: " + recodingFile.Name);

            // READ PARAMETER VALUES FROM INI FILE
            AedConfiguration configruation = ConfigFile.Deserialize <AedConfiguration>(arguments.Config);
            var aedConfig = GetAedParametersFromConfigFileOrDefaults(configruation);
            var results   = Detect(recodingFile, aedConfig, TimeSpan.Zero);

            // print image
            // save image of sonograms
            var   outputImagePath = outputDir.CombineFile(recodingBaseName + ".Sonogram.png");
            Image image           = DrawSonogram(results.Item3, results.Item1);

            image.Save(outputImagePath.FullName, ImageFormat.Png);
            Log.Info("Image saved to: " + outputImagePath.FullName);

            // output csv
            var outputCsvPath = outputDir.CombineFile(recodingBaseName + ".Events.csv");

            WriteEventsFileStatic(outputCsvPath, results.Item1);
            Log.Info("CSV file saved to: " + outputCsvPath.FullName);

            TowseyLibrary.Log.WriteLine("Finished");
        }
        public static void Execute(Arguments arguments)
        {
            MainEntry.WarnIfDeveloperEntryUsed();

            if (arguments == null)
            {
                throw new NoDeveloperMethodException();
            }

            // READ PARAMETER VALUES FROM INI FILE
            var config    = ConfigFile.Deserialize(arguments.Config);
            var aedConfig = Aed.GetAedParametersFromConfigFileOrDefaults(config);

            var input = arguments.Source;
            Tuple <BaseSonogram, List <AcousticEvent> > result = Detect(input, aedConfig, Default.eprNormalisedMinScore, TimeSpan.Zero);
            List <AcousticEvent> eprEvents = result.Item2;

            eprEvents.Sort((ae1, ae2) => ae1.TimeStart.CompareTo(ae2.TimeStart));

            LoggedConsole.WriteLine();
            foreach (AcousticEvent ae in eprEvents)
            {
                LoggedConsole.WriteLine(ae.TimeStart + "," + ae.EventDurationSeconds + "," + ae.LowFrequencyHertz + "," + ae.HighFrequencyHertz);
            }

            LoggedConsole.WriteLine();

            string       outputFolder = arguments.Config.ToFileInfo().DirectoryName;
            string       wavFilePath  = input.FullName;
            BaseSonogram sonogram     = result.Item1;
            string       imagePath    = Path.Combine(outputFolder, Path.GetFileNameWithoutExtension(wavFilePath) + ".png");
            var          image        = Aed.DrawSonogram(sonogram, eprEvents);

            image.Save(imagePath);

            //ProcessingTypes.SaveAeCsv(eprEvents, outputFolder, wavFilePath);

            Log.Info("Finished");
        }
Example #3
0
        public static void Execute(Arguments arguments)
        {
            MainEntry.WarnIfDeveloperEntryUsed();

            string title = "# EVENT PATTERN RECOGNITION.";
            string date  = "# DATE AND TIME: " + DateTime.Now;

            Log.WriteLine(title);
            Log.WriteLine(date);

            Log.Verbosity = 1;

            string targetName = arguments.Target; // prefix of name of created files

            var input = arguments.Source;

            string        recordingFileName  = input.Name;
            string        recordingDirectory = input.DirectoryName;
            DirectoryInfo outputDir          = arguments.Config.ToFileInfo().Directory;
            FileInfo      targetPath         = outputDir.CombineFile(targetName + "_target.txt");
            FileInfo      targetNoNoisePath  = outputDir.CombineFile(targetName + "_targetNoNoise.txt");
            FileInfo      noisePath          = outputDir.CombineFile(targetName + "_noise.txt");
            FileInfo      targetImagePath    = outputDir.CombineFile(targetName + "_target.png");
            FileInfo      paramsPath         = outputDir.CombineFile(targetName + "_params.txt");

            Log.WriteIfVerbose("# Output folder =" + outputDir);

            //i: GET RECORDING
            AudioRecording recording = new AudioRecording(input.FullName);

            //if (recording.SampleRate != 22050) recording.ConvertSampleRate22kHz(); THIS METHOD CALL IS OBSOLETE
            int sr = recording.SampleRate;

            //ii: READ PARAMETER VALUES FROM INI FILE
            var config = new ConfigDictionary(arguments.Config);
            Dictionary <string, string> dict = config.GetTable();

            // framing parameters
            //double frameOverlap      = FeltTemplates_Use.FeltFrameOverlap;   // default = 0.5
            double frameOverlap = double.Parse(dict["FRAME_OVERLAP"]);

            //frequency band
            int minHz = int.Parse(dict["MIN_HZ"]);
            int maxHz = int.Parse(dict["MAX_HZ"]);

            // oscillation OD parameters
            double dctDuration  = double.Parse(dict[OscillationRecogniser.key_DCT_DURATION]);  // 2.0; // seconds
            double dctThreshold = double.Parse(dict[OscillationRecogniser.key_DCT_THRESHOLD]); // 0.5;
            int    minOscilFreq = int.Parse(dict[OscillationRecogniser.key_MIN_OSCIL_FREQ]);   // 4;
            int    maxOscilFreq = int.Parse(dict[OscillationRecogniser.key_MAX_OSCIL_FREQ]);   // 5;
            bool   normaliseDCT = false;

            // iii initialize the sonogram config class.
            SonogramConfig sonoConfig = new SonogramConfig(); //default values config

            sonoConfig.SourceFName = recording.BaseName;

            //sonoConfig.WindowSize = windowSize;
            sonoConfig.WindowOverlap = frameOverlap;

            // iv: generate the sonogram
            BaseSonogram sonogram = new SpectrogramStandard(sonoConfig, recording.WavReader);

            Log.WriteLine("Frames: Size={0}, Count={1}, Duration={2:f1}ms, Overlap={5:f2}%, Offset={3:f1}ms, Frames/s={4:f1}",
                          sonogram.Configuration.WindowSize, sonogram.FrameCount, sonogram.FrameDuration * 1000,
                          sonogram.FrameStep * 1000, sonogram.FramesPerSecond, frameOverlap);
            int binCount = (int)(maxHz / sonogram.FBinWidth) - (int)(minHz / sonogram.FBinWidth) + 1;

            Log.WriteIfVerbose("Freq band: {0} Hz - {1} Hz. (Freq bin count = {2})", minHz, maxHz, binCount);

            // v: extract the subband energy array
            Log.WriteLine("# Start extracting target event.");
            double[] dBArray = SNR.DecibelsInSubband(sonogram.Data, minHz, maxHz, sonogram.FBinWidth);
            for (int i = 0; i < sonogram.FrameCount; i++)
            {
                dBArray[i] /= binCount; // get average dB energy
            }

            double Q  = 0.0;
            double SD = 0.0;

            throw new NotImplementedException("Mike changed the API here, I don't know how to fix it.");
            dBArray = new[] { 0.0 };             // SNR.NoiseSubtractMode(dBArray, out Q, out SD);
            double maxDB       = 6.0;
            double dBThreshold = 2 * SD / maxDB; //set dB threshold to 2xSD above background noise

            dBArray = SNR.NormaliseDecibelArray_ZeroOne(dBArray, maxDB);
            dBArray = DataTools.filterMovingAverage(dBArray, 7);

            //Log.WriteLine("Q ={0}", Q);
            //Log.WriteLine("SD={0}", SD);
            //Log.WriteLine("Th={0}", dBThreshold); //normalised threshhold

            // #############################################################################################################################################
            // vi: look for oscillation at required OR for ground parrots.
            double[] odScores = Oscillations2010.DetectOscillationsInScoreArray(dBArray, dctDuration, sonogram.FramesPerSecond, dctThreshold,
                                                                                normaliseDCT, minOscilFreq, maxOscilFreq);

            //odScores = SNR.NoiseSubtractMode(odScores, out Q, out SD);
            double maxOD = 1.0;

            odScores = SNR.NormaliseDecibelArray_ZeroOne(odScores, maxOD);
            odScores = DataTools.filterMovingAverage(odScores, 5);

            //odScores = DataTools.NormaliseMatrixValues(odScores); //NormaliseMatrixValues 0 - 1
            //double odThreshold = (10 * SD) / maxOD;   //set od threshold to 2xSD above background noise
            //double odThreshold = dctThreshold;
            double odThreshold = 0.4;

            Log.WriteLine("Max={0}", odScores.Max());

            //Log.WriteLine("Q  ={0}", Q);
            //Log.WriteLine("SD ={0}", SD);
            Log.WriteLine("Th ={0}", dctThreshold); //normalised threshhold

            // #############################################################################################################################################
            // vii: LOOK FOR GROUND PARROTS USING TEMPLATE
            var template = GroundParrotRecogniser.ReadGroundParrotTemplateAsList(sonogram);

            double[] gpScores = DetectEPR(template, sonogram, odScores, odThreshold);
            gpScores = DataTools.normalise(gpScores); //NormaliseMatrixValues 0 - 1

            // #############################################################################################################################################

            // iv: SAVE extracted event as matrix of dB intensity values
            //FileTools.WriteMatrix2File(template, targetPath);                  // write template values to file PRIOR to noise removal.
            //FileTools.WriteMatrix2File(templateMinusNoise, targetNoNoisePath); // write template values to file AFTER to noise removal.
            //FileTools.WriteArray2File(noiseSubband, noisePath);

            // v: SAVE image of extracted event in the original sonogram
            string sonogramImagePath = outputDir + Path.GetFileNameWithoutExtension(recordingFileName) + ".png";

            //DrawSonogram(sonogram, sonogramImagePath, dBArray, dBThreshold / maxDB, odScores, dctThreshold, gpScores, template);
        }
        private int Execute(Arguments arguments)
        {
            var errors   = new List <string>();
            var warnings = new List <string>();

            Log.Info("Checking required executables and libraries can be found and loaded");

            // this is an important call used in analyze long recordings.
            // This call effectively check is we can load types and if files are present (I think)
            try
            {
                AnalysisCoordinator.GetAnalyzers <IAnalyser2>(typeof(MainEntry).Assembly);
            }
            catch (ReflectionTypeLoadException rtlex)
            {
                errors.Add(ExceptionLookup.FormatReflectionTypeLoadException(rtlex, true));
            }

            // master audio utility checks for available executables
            try
            {
                var utility = new MasterAudioUtility();
            }
            catch (Exception ex)
            {
                errors.Add(ex.Message);
            }

            if (AppConfigHelper.WvunpackExe == null)
            {
                warnings.Add("Cannot find wvunpack - we'll be unable to process any wavpack files.");
            }

            if (!new SoxAudioUtility(new FileInfo(AppConfigHelper.SoxExe)).SupportsMp3)
            {
                warnings.Add(SoxAudioUtility.Mp3NotSupportedOnOSX);
            }

            if (MainEntry.CheckForDataAnnotations() is string message)
            {
                errors.Add(message);
            }

            Type type = Type.GetType("Mono.Runtime");

            if (type != null)
            {
                errors.Add($"We no longer use Mono with ${Meta.Name}. DO NOT prefix the {Meta.Name} prefix with `mono`.");
            }

            foreach (var warning in warnings)
            {
                Log.Warn(warning);
            }

            // don't have much more to check at the current time
            if (errors.Count == 0)
            {
                Log.Success("Valid environment");

                return(ExceptionLookup.Ok);
            }
            else
            {
                foreach (var error in errors)
                {
                    Log.Error(error);
                }

                // not using exception lookup on purpose - it's static constructor loads more types
                return(ExceptionLookup.UnhandledExceptionErrorCode);
            }
        }
Example #5
0
        public static void Execute(Arguments arguments)
        {
            MainEntry.WarnIfDevleoperEntryUsed();

            string date = "# DATE AND TIME: " + DateTime.Now;

            Log.WriteLine("# SEGMENTING A RECORDING");
            Log.WriteLine(date);

            Log.Verbosity = 1;

            FileInfo      recordingPath = arguments.Source;
            FileInfo      iniPath       = arguments.Config.ToFileInfo();
            DirectoryInfo outputDir     = arguments.Output;
            string        opFName       = "segment-output.txt";
            FileInfo      opPath        = outputDir.CombineFile(opFName);

            Log.WriteIfVerbose("# Output folder =" + outputDir);

            //READ PARAMETER VALUES FROM INI FILE
            var config = new ConfigDictionary(iniPath);
            Dictionary <string, string> dict = config.GetTable();

            Dictionary <string, string> .KeyCollection keys = dict.Keys;

            int    minHz          = int.Parse(dict[key_MIN_HZ]);
            int    maxHz          = int.Parse(dict[key_MAX_HZ]);
            double frameOverlap   = double.Parse(dict[key_FRAME_OVERLAP]);
            double smoothWindow   = double.Parse(dict[key_SMOOTH_WINDOW]); //smoothing window (seconds) before segmentation
            double thresholdSD    = double.Parse(dict[key_THRESHOLD]);     //segmentation threshold in noise SD
            double minDuration    = double.Parse(dict[key_MIN_DURATION]);  //min duration of segment & width of smoothing window in seconds
            double maxDuration    = double.Parse(dict[key_MAX_DURATION]);  //max duration of segment in seconds
            int    DRAW_SONOGRAMS = int.Parse(dict[key_DRAW_SONOGRAMS]);   //options to draw sonogram

            Log.WriteIfVerbose("# Freq band: {0} Hz - {1} Hz.)", minHz, maxHz);
            Log.WriteIfVerbose("# Smoothing Window: {0}s.", smoothWindow);
            Log.WriteIfVerbose("# Duration bounds: " + minDuration + " - " + maxDuration + " seconds");

            //#############################################################################################################################################
            var results = Execute_Segmentation(recordingPath, minHz, maxHz, frameOverlap, smoothWindow, thresholdSD, minDuration, maxDuration);

            Log.WriteLine("# Finished detecting segments.");

            //#############################################################################################################################################

            var sonogram        = results.Item1;
            var predictedEvents = results.Item2; //contain the segments detected
            var Q           = results.Item3;
            var oneSD_dB    = results.Item4;
            var dBThreshold = results.Item5;
            var intensity   = results.Item6;

            Log.WriteLine("# Signal:  Duration={0}, Sample Rate={1}", sonogram.Duration, sonogram.SampleRate);
            Log.WriteLine("# Frames:  Size={0}, Count={1}, Duration={2:f1}ms, Overlap={5:f0}%, Offset={3:f1}ms, Frames/s={4:f1}",
                          sonogram.Configuration.WindowSize, sonogram.FrameCount, sonogram.FrameDuration * 1000,
                          sonogram.FrameStep * 1000, sonogram.FramesPerSecond, frameOverlap);
            int binCount = (int)(maxHz / sonogram.FBinWidth) - (int)(minHz / sonogram.FBinWidth) + 1;

            Log.WriteLine("# FreqBand: {0} Hz - {1} Hz. (Freq bin count = {2})", minHz, maxHz, binCount);
            Log.WriteLine("# Intensity array - noise removal: Q={0:f1}dB. 1SD={1:f3}dB. Threshold={2:f3}dB.", Q, oneSD_dB, dBThreshold);
            Log.WriteLine("# Events:  Count={0}", predictedEvents.Count());
            int pcHIF = 100;

            if (intensity != null)
            {
                int hifCount = intensity.Count(p => p > dBThreshold); //count of high intensity frames
                pcHIF = 100 * hifCount / sonogram.FrameCount;
            }

            //write event count to results file.
            double sigDuration = sonogram.Duration.TotalSeconds;
            string fname       = recordingPath.Name;
            int    count       = predictedEvents.Count;

            //string str = String.Format("#RecordingName\tDuration(sec)\t#Ev\tCompT(ms)\t%hiFrames\n{0}\t{1}\t{2}\t{3}\t{4}\n", fname, sigDuration, count, analysisDuration.TotalMilliseconds, pcHIF);
            //StringBuilder sb = new StringBuilder(str);
            //StringBuilder sb = new StringBuilder();
            string        str = string.Format("{0}\t{1}\t{2}\t{3}", fname, sigDuration, count, pcHIF);
            StringBuilder sb  = AcousticEvent.WriteEvents(predictedEvents, str);

            FileTools.WriteTextFile(opPath.FullName, sb.ToString());

            //draw images of sonograms
            string imagePath = outputDir + Path.GetFileNameWithoutExtension(recordingPath.Name) + ".png";
            double min, max;

            DataTools.MinMax(intensity, out min, out max);
            double threshold_norm = dBThreshold / max; //min = 0.0;

            intensity = DataTools.normalise(intensity);
            if (DRAW_SONOGRAMS == 2)
            {
                DrawSonogram(sonogram, imagePath, predictedEvents, threshold_norm, intensity);
            }
            else
            if (DRAW_SONOGRAMS == 1 && predictedEvents.Count > 0)
            {
                DrawSonogram(sonogram, imagePath, predictedEvents, threshold_norm, intensity);
            }

            Log.WriteLine("# Finished recording:- " + recordingPath.Name);
        }
Example #6
0
        private int Execute(Arguments arguments)
        {
            var errors = new List <string>();

            Log.Info("Checking required executables and libraries can be found and loaded");

            // this is an important call used in analyze long recordings.
            // This call effectively check is we can load types and if files are present (I think)
            try
            {
                AnalysisCoordinator.GetAnalyzers <IAnalyser2>(typeof(MainEntry).Assembly);
            }
            catch (ReflectionTypeLoadException rtlex)
            {
                errors.Add(ExceptionLookup.FormatReflectionTypeLoadException(rtlex, true));
            }

            // master audio utility checks for available executables
            try
            {
                var utility = new MasterAudioUtility();
            }
            catch (Exception ex)
            {
                errors.Add(ex.Message);
            }

            if (MainEntry.CheckForDataAnnotations() is string message)
            {
                errors.Add(message);
            }

            if (AppConfigHelper.IsMono)
            {
                Type type = Type.GetType("Mono.Runtime");
                if (type != null)
                {
                    MethodInfo displayName = type.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);

                    if (displayName?.Invoke(null, null) is string name)
                    {
                        var version = Regex.Match(name, @".*(\d+\.\d+\.\d+\.\d+).*").Groups[1].Value;
                        Console.WriteLine(version);
                        if (new Version(version) > new Version(5, 5))
                        {
                            Log.Success($"Your mono version {name} is greater than our required Mono version 5.5");
                        }
                        else
                        {
                            errors.Add($"Mono version is {name}, we require at least Mono 5.5");
                        }
                    }
                    else
                    {
                        errors.Add("Could not get Mono display name");
                    }
                }
            }

            // don't have much more to check at the current time
            if (errors.Count == 0)
            {
                Log.Success("Valid environment");

                return(ExceptionLookup.Ok);
            }
            else
            {
                foreach (var error in errors)
                {
                    Log.Error(error);
                }

                // not using exception lookup on purpose - it's static constructor loads more types
                return(ExceptionLookup.UnhandledExceptionErrorCode);
            }
        }