public static void Execute(Arguments arguments)
        {
            if (arguments == null)
            {
                arguments = Dev();
            }

            string   opFName       = ANALYSIS_NAME + ".txt";
            FileInfo opPath        = arguments.Output.CombineFile(opFName);
            string   audioFileName = arguments.Source.Name;

            Log.Verbosity = 1;

            string title = "# FOR DETECTION OF ACOUSTIC EVENTS HAVING A GRID OR GRATING STRUCTURE";
            string date  = "# DATE AND TIME: " + DateTime.Now;

            LoggedConsole.WriteLine(title);
            LoggedConsole.WriteLine(date);
            LoggedConsole.WriteLine("# Output folder:  " + arguments.Output);
            LoggedConsole.WriteLine("# Recording file: " + arguments.Source.Name);
            FileTools.WriteTextFile(opPath.FullName, date + "\n# Recording file: " + audioFileName);

            //READ PARAMETER VALUES FROM INI FILE
            var configuration = new ConfigDictionary(arguments.Config);
            Dictionary <string, string> configDict = configuration.GetTable();

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

            int startMinute           = 5; //dummy value
            var fiSegmentOfSourceFile = arguments.Source;
            var diOutputDir           = arguments.Output;

            //#############################################################################################################################################
            DataTable dt = AnalysisReturnsDataTable(startMinute, fiSegmentOfSourceFile, configDict, diOutputDir);

            //#############################################################################################################################################
            if (dt == null)
            {
                Log.WriteLine("\n\n\n##############################\n WARNING! No events returned.");
            }
            else
            {
                //LoggedConsole.WriteLine("\tRecording Duration: {0:f2}seconds", recordingTimeSpan.TotalSeconds);
                LoggedConsole.WriteLine("# Event count for minute {0} = {1}", startMinute, dt.Rows.Count);
                DataTableTools.WriteTable2Console(dt);
            }

            LoggedConsole.WriteLine("# Finished recording:- " + arguments.Source.FullName);
        }
Exemple #2
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);
        }
        } //AddContext2Table()

        public Tuple <DataTable, DataTable> ProcessCsvFile(FileInfo fiCsvFile, FileInfo fiConfigFile)
        {
            DataTable dt = CsvTools.ReadCSVToTable(fiCsvFile.FullName, true); //get original data table

            if ((dt == null) || (dt.Rows.Count == 0))
            {
                return(null);
            }
            //get its column headers
            var dtHeaders = new List <string>();
            var dtTypes   = new List <Type>();

            foreach (DataColumn col in dt.Columns)
            {
                dtHeaders.Add(col.ColumnName);
                dtTypes.Add(col.DataType);
            }

            List <string> displayHeaders = null;

            //check if config file contains list of display headers
            if (fiConfigFile != null)
            {
                var configuration = new ConfigDictionary(fiConfigFile.FullName);
                Dictionary <string, string> configDict = configuration.GetTable();
                if (configDict.ContainsKey(Keys.DISPLAY_COLUMNS))
                {
                    displayHeaders = configDict[Keys.DISPLAY_COLUMNS].Split(',').ToList();
                }
            }
            //if config file does not exist or does not contain display headers then use the original headers
            if (displayHeaders == null)
            {
                displayHeaders = dtHeaders;                         //use existing headers if user supplies none.
            }
            //now determine how to display tracks in display datatable
            Type[] displayTypes = new Type[displayHeaders.Count];
            bool[] canDisplay   = new bool[displayHeaders.Count];
            for (int i = 0; i < displayTypes.Length; i++)
            {
                displayTypes[i] = typeof(double);
                canDisplay[i]   = false;
                if (dtHeaders.Contains(displayHeaders[i]))
                {
                    canDisplay[i] = true;
                }
            }

            DataTable table2Display = DataTableTools.CreateTable(displayHeaders.ToArray(), displayTypes);

            foreach (DataRow row in dt.Rows)
            {
                DataRow newRow = table2Display.NewRow();
                for (int i = 0; i < canDisplay.Length; i++)
                {
                    if (canDisplay[i])
                    {
                        newRow[displayHeaders[i]] = row[displayHeaders[i]];
                    }
                    else
                    {
                        newRow[displayHeaders[i]] = 0.0;
                    }
                }
                table2Display.Rows.Add(newRow);
            }

            //order the table if possible
            if (dt.Columns.Contains(AudioAnalysisTools.Keys.EVENT_START_ABS))
            {
                dt = DataTableTools.SortTable(dt, AudioAnalysisTools.Keys.EVENT_START_ABS + " ASC");
            }
            else if (dt.Columns.Contains(AudioAnalysisTools.Keys.EVENT_COUNT))
            {
                dt = DataTableTools.SortTable(dt, AudioAnalysisTools.Keys.EVENT_COUNT + " ASC");
            }
            else if (dt.Columns.Contains(AudioAnalysisTools.Keys.INDICES_COUNT))
            {
                dt = DataTableTools.SortTable(dt, AudioAnalysisTools.Keys.INDICES_COUNT + " ASC");
            }
            else if (dt.Columns.Contains(AudioAnalysisTools.Keys.START_MIN))
            {
                dt = DataTableTools.SortTable(dt, AudioAnalysisTools.Keys.START_MIN + " ASC");
            }

            table2Display = NormaliseColumnsOfDataTable(table2Display);
            return(System.Tuple.Create(dt, table2Display));
        } // ProcessCsvFile()
        /// <summary>
        /// A WRAPPER AROUND THE analyser.Analyse(analysisSettings) METHOD
        /// To be called as an executable with command line arguments.
        /// </summary>
        /// <param name="sourcePath"></param>
        /// <param name="configPath"></param>
        /// <param name="outputPath"></param>
        public static int Execute(string[] args)
        {
            int status = 0;

            if (args.Length < 4)
            {
                Console.WriteLine("Require at least 4 command line arguments.");
                status = 1;
                return(status);
            }
            //GET FIRST THREE OBLIGATORY COMMAND LINE ARGUMENTS
            string   recordingPath = args[0];
            string   configPath    = args[1];
            string   outputDir     = args[2];
            FileInfo fiSource      = new FileInfo(recordingPath);

            if (!fiSource.Exists)
            {
                Console.WriteLine("Source file does not exist: " + recordingPath);
                status = 2;
                return(status);
            }
            FileInfo fiConfig = new FileInfo(configPath);

            if (!fiConfig.Exists)
            {
                Console.WriteLine("Config file does not exist: " + configPath);
                status = 2;
                return(status);
            }
            DirectoryInfo diOP = new DirectoryInfo(outputDir);

            if (!diOP.Exists)
            {
                Console.WriteLine("Output directory does not exist: " + outputDir);
                status = 2;
                return(status);
            }

            //INIT SETTINGS
            AnalysisSettings analysisSettings = new AnalysisSettings();

            analysisSettings.ConfigFile           = fiConfig;
            analysisSettings.AnalysisRunDirectory = diOP;
            analysisSettings.AudioFile            = null;
            analysisSettings.EventsFile           = null;
            analysisSettings.IndicesFile          = null;
            analysisSettings.ImageFile            = null;
            TimeSpan tsStart       = new TimeSpan(0, 0, 0);
            TimeSpan tsDuration    = new TimeSpan(0, 0, 0);
            var      configuration = new ConfigDictionary(analysisSettings.ConfigFile.FullName);

            analysisSettings.ConfigDict = configuration.GetTable();


            //PROCESS REMAINDER OF THE OPTIONAL COMMAND LINE ARGUMENTS
            for (int i = 3; i < args.Length; i++)
            {
                string[] parts = args[i].Split(':');
                if (parts[0].StartsWith("-tmpwav"))
                {
                    var outputWavPath = Path.Combine(outputDir, parts[1]);
                    analysisSettings.AudioFile = new FileInfo(outputWavPath);
                }
                else
                if (parts[0].StartsWith("-events"))
                {
                    string eventsPath = Path.Combine(outputDir, parts[1]);
                    analysisSettings.EventsFile = new FileInfo(eventsPath);
                }
                else
                if (parts[0].StartsWith("-indices"))
                {
                    string indicesPath = Path.Combine(outputDir, parts[1]);
                    analysisSettings.IndicesFile = new FileInfo(indicesPath);
                }
                else
                if (parts[0].StartsWith("-sgram"))
                {
                    string sonoImagePath = Path.Combine(outputDir, parts[1]);
                    analysisSettings.ImageFile = new FileInfo(sonoImagePath);
                }
                else
                if (parts[0].StartsWith("-start"))
                {
                    int s = Int32.Parse(parts[1]);
                    tsStart = new TimeSpan(0, 0, s);
                }
                else
                if (parts[0].StartsWith("-duration"))
                {
                    int s = Int32.Parse(parts[1]);
                    tsDuration = new TimeSpan(0, 0, s);
                    if (tsDuration.TotalMinutes > 10)
                    {
                        Console.WriteLine("Segment duration cannot exceed 10 minutes.");
                        status = 3;
                        return(status);
                    }
                }
            }

            //EXTRACT THE REQUIRED RECORDING SEGMENT
            FileInfo tempF = analysisSettings.AudioFile;

            if (tsDuration.TotalSeconds == 0)   //Process entire file
            {
                AudioFilePreparer.PrepareFile(fiSource, tempF, new AudioUtilityRequest {
                    SampleRate = LSKiwiHelper.RESAMPLE_RATE
                });
                //var fiSegment = AudioFilePreparer.PrepareFile(diOutputDir, fiSourceFile, , Human2.RESAMPLE_RATE);
            }
            else
            {
                AudioFilePreparer.PrepareFile(fiSource, tempF, new AudioUtilityRequest {
                    SampleRate = LSKiwiHelper.RESAMPLE_RATE, OffsetStart = tsStart, OffsetEnd = tsStart.Add(tsDuration)
                });
                //var fiSegmentOfSourceFile = AudioFilePreparer.PrepareFile(diOutputDir, new FileInfo(recordingPath), MediaTypes.MediaTypeWav, TimeSpan.FromMinutes(2), TimeSpan.FromMinutes(3), RESAMPLE_RATE);
            }

            //DO THE ANALYSIS
            //#############################################################################################################################################
            IAnalyser      analyser = new LSKiwi2();
            AnalysisResult result   = analyser.Analyse(analysisSettings);
            DataTable      dt       = result.Data;

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

            //ADD IN ADDITIONAL INFO TO RESULTS TABLE
            if (dt != null)
            {
                AddContext2Table(dt, tsStart, result.AudioDuration);
                CsvTools.DataTable2CSV(dt, analysisSettings.EventsFile.FullName);
                //DataTableTools.WriteTable(augmentedTable);
            }
            else
            {
                return(-993);  //error!!
            }

            return(status);
        }
Exemple #5
0
        public static void Execute(Arguments arguments)
        {
            string date = "# DATE AND TIME: " + DateTime.Now;

            Log.WriteLine("# DETECTING LOW FREQUENCY AMPLITUDE OSCILLATIONS");
            Log.WriteLine(date);

            Log.Verbosity = 1;

            FileInfo      recordingFile = arguments.Source;
            FileInfo      iniPath       = arguments.Config.ToFileInfo();
            DirectoryInfo outputDir     = arguments.Output;
            string        opFName       = "OcillationReconiserResults.cav";
            string        opPath        = outputDir + 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;

            bool   doSegmentation = bool.Parse(dict[key_DO_SEGMENTATION]);
            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 dctDuration    = double.Parse(dict[key_DCT_DURATION]);    //duration of DCT in seconds
            double dctThreshold   = double.Parse(dict[key_DCT_THRESHOLD]);   //minimum acceptable value of a DCT coefficient
            int    minOscilFreq   = int.Parse(dict[key_MIN_OSCIL_FREQ]);     //ignore oscillations below this threshold freq
            int    maxOscilFreq   = int.Parse(dict[key_MAX_OSCIL_FREQ]);     //ignore oscillations above this threshold freq
            double minDuration    = double.Parse(dict[key_MIN_DURATION]);    //min duration of event in seconds
            double maxDuration    = double.Parse(dict[key_MAX_DURATION]);    //max duration of event in seconds
            double eventThreshold = double.Parse(dict[key_EVENT_THRESHOLD]); //min score for an acceptable event
            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("Oscill bounds: " + minOscilFreq + " - " + maxOscilFreq + " Hz");
            Log.WriteIfVerbose("minAmplitude = " + dctThreshold);
            Log.WriteIfVerbose("Duration bounds: " + minDuration + " - " + maxDuration + " seconds");

//#############################################################################################################################################
            var results = Execute_ODDetect(recordingFile, doSegmentation, minHz, maxHz, frameOverlap, dctDuration, dctThreshold,
                                           minOscilFreq, maxOscilFreq, eventThreshold, minDuration, maxDuration);

            Log.WriteLine("# Finished detecting oscillation events.");

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

            var sonogram         = results.Item1;
            var hits             = results.Item2;
            var scores           = results.Item3;
            var predictedEvents  = results.Item4;
            var intensity        = results.Item5;
            var analysisDuration = results.Item6;

            Log.WriteLine("# Event Count = " + predictedEvents.Count());
            int pcHIF = 100;

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

            //write event count to results file.
            double sigDuration = sonogram.Duration.TotalSeconds;
            string fname       = recordingFile.BaseName();
            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);
            string        str = string.Format("{0}\t{1}\t{2}\t{3}\t{4}", fname, sigDuration, count, analysisDuration.TotalMilliseconds, pcHIF);
            StringBuilder sb  = AcousticEvent.WriteEvents(predictedEvents, str);

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

            //draw images of sonograms
            string imagePath = outputDir + fname + ".png";

            if (DRAW_SONOGRAMS == 2)
            {
                DrawSonogram(sonogram, imagePath, hits, scores, predictedEvents, eventThreshold, intensity);
            }
            else
            if (DRAW_SONOGRAMS == 1 && predictedEvents.Count > 0)
            {
                DrawSonogram(sonogram, imagePath, hits, scores, predictedEvents, eventThreshold, intensity);
            }

            Log.WriteLine("# Finished recording:- " + recordingFile.Name);
        }
Exemple #6
0
        /// <summary>
        /// Wraps up the resources into a template.ZIP file
        /// and then runs a test on the source recording.
        /// </summary>
        public static void Execute(Arguments arguments)
        {
            if (arguments == null)
            {
                arguments = Dev();
            }

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

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

            //ZIP THE OUTPUT FILES
            const bool ZipOutput = true;

            FileInfo iniPath = arguments.Config;

            string[] nameComponents = (Path.GetFileNameWithoutExtension(iniPath.Name)).Split('_');
            string   targetName     = nameComponents[0] + "_" + nameComponents[1];

            //i: Set up the file names
            DirectoryInfo outputDir       = iniPath.Directory;
            FileInfo      targetImagePath = outputDir.CombineFile(targetName + "_target.png"); // input image file
            FileInfo      binaryOpPath    = outputDir.CombineFile(targetName + "_binary.bmp");
            FileInfo      trinaryOpPath   = outputDir.CombineFile(targetName + "_trinary.bmp");
            FileInfo      sprOpPath       = outputDir.CombineFile(targetName + "_spr.txt");    // syntactic pattern recognition file
            //additional files to be zipped up with template
            FileInfo targetPath        = outputDir.CombineFile(targetName + "_target.txt");
            FileInfo targetNoNoisePath = outputDir.CombineFile(targetName + "_targetNoNoise.txt");
            FileInfo noisePath         = outputDir.CombineFile(targetName + "_noise.txt");

            //ii: READ PARAMETER VALUES FROM INI FILE
            var config = new ConfigDictionary(iniPath);
            Dictionary <string, string> dict = config.GetTable();
            string sourceFile           = dict[FeltTemplate_Create.key_SOURCE_RECORDING];
            string sourceDir            = dict[FeltTemplate_Create.key_SOURCE_DIRECTORY];
            double dB_Threshold         = double.Parse(dict[FeltTemplate_Create.key_DECIBEL_THRESHOLD]);
            double maxTemplateIntensity = double.Parse(dict[FeltTemplate_Create.key_TEMPLATE_MAX_INTENSITY]);
            int    neighbourhood        = int.Parse(dict[FeltTemplate_Create.key_DONT_CARE_NH]);   //the do not care neighbourhood
            int    lineLength           = int.Parse(dict[FeltTemplate_Create.key_LINE_LENGTH]);
            double templateThreshold    = dB_Threshold / maxTemplateIntensity;
            int    bitmapThreshold      = (int)(255 - (templateThreshold * 255));

            Log.WriteLine("#################################### WRITE THE BINARY TEMPLATE ##################################");
            Bitmap bitmap    = ImageTools.ReadImage2Bitmap(targetImagePath.FullName);
            var    binaryBmp = Image2BinaryBitmap(bitmap, bitmapThreshold);

            binaryBmp.Save(binaryOpPath.FullName);

            Log.WriteLine("#################################### WRITE THE TRINARY TEMPLATE ##################################");
            var trinaryBmp = Image2TrinaryBitmap(binaryBmp, neighbourhood);

            trinaryBmp.Save(trinaryOpPath.FullName);

            Log.WriteLine("#################################### WRITE THE SPR TEMPLATE ##################################");
            double[,] matrix = ImageTools.GreyScaleImage2Matrix(bitmap);
            matrix           = DataTools.MatrixRotate90Clockwise(matrix); //rows=time  cols=freq.
            //ImageTools.DrawMatrix(matrix, @"C:\SensorNetworks\Output\FELT_LewinsRail1\SPR_output1.bmp");
            //int smallLengthThreshold = 10;
            //var tuple = SPT.doSPT(matrix, templateThreshold, smallLengthThreshold);
            //matrix = tuple.Item1;
            //ImageTools.DrawMatrix(matrix, @"C:\SensorNetworks\Output\FELT_LewinsRail1\SPR_output2.bmp");
            char[,] spr = SprTools.Target2SymbolicTracks(matrix, templateThreshold, lineLength);
            FileTools.WriteMatrix2File(spr, sprOpPath.FullName);
            var    tuple1   = FindMatchingEvents.Execute_One_Spr_Match(spr, matrix, templateThreshold);
            double sprScore = tuple1.Item1;
            double dBScore  = sprScore * maxTemplateIntensity;

            Log.WriteLine("#################################### WRITE THE OSCILATION TEMPLATE ##################################");
            double[,] target = FileTools.ReadDoubles2Matrix(targetPath.FullName);
            // oscillations in time
            double[,] rotatedtarget = DataTools.MatrixRotate90Clockwise(target);
            var colSums = DataTools.GetColumnsAverages(rotatedtarget);

            double[] periods = Oscillations2010.PeriodicityAnalysis(colSums); // frame periodicity
            LoggedConsole.WriteLine("Periodicity (sec) = {0:f3},  {1:f3},  {2:f3}",
                                    periods[0] * FeltTemplates_Use.FeltFrameOffset, periods[1] * FeltTemplates_Use.FeltFrameOffset, periods[2] * FeltTemplates_Use.FeltFrameOffset);
            //double oscilFreq = indexOfMaxValue / dctDuration * 0.5; //Times 0.5 because index = Pi and not 2Pi

            // oscillations in freq i.e. harmonics
            colSums = DataTools.GetColumnsAverages(target);
            periods = Oscillations2010.PeriodicityAnalysis(colSums);
            LoggedConsole.WriteLine("Periodicity (Hz) = {0:f0},  {1:f0},  {2:f0}.",
                                    periods[0] * FeltTemplates_Use.FeltFreqBinWidth, periods[1] * FeltTemplates_Use.FeltFreqBinWidth, periods[2] * FeltTemplates_Use.FeltFreqBinWidth);
            //double oscilFreq = indexOfMaxValue / dctDuration * 0.5; //Times 0.5 because index = Pi and not 2Pi

            //FileTools.WriteMatrix2File(spr, sprOpPath);

            // ZIP THE OUTPUT
            Log.WriteLine("#################################### ZIP THE TEMPLATES ##################################");
            if (ZipOutput == true)
            {
                var filenames = new[]
                { iniPath, targetImagePath, binaryOpPath, targetPath, targetNoNoisePath, noisePath };
                string biOutZipFile = outputDir + targetName + "_binaryTemplate.zip";
                //FileTools.ZipFiles(filenames, biOutZipFile);

                filenames = new[]
                { iniPath, targetImagePath, trinaryOpPath, targetPath, targetNoNoisePath, noisePath };

                string triOutZipFile = outputDir + targetName + "_trinaryTemplate.zip";
                //FileTools.ZipFiles(filenames, triOutZipFile);

                filenames = new[]
                { iniPath, targetImagePath, sprOpPath, targetPath, targetNoNoisePath, noisePath };

                string sprOutZipFile = outputDir + targetName + "_syntacticTemplate.zip";
                //FileTools.ZipFiles(filenames, sprOutZipFile);

                // Zipping files can be done by using standard .NET 4.6 System.IO.Compression
                // however, this code hasn't been used in years and I've opted to just comment out the lines above
                throw new NotImplementedException("Zipping template files intentionally broken");
            }

            Log.WriteLine("\n\n#################################### TEST THE EXTRACTED EVENT ON SOURCE FILE ##################################");
            //vi: TEST THE EVENT ON ANOTHER FILE
            //felt  "C:\SensorNetworks\WavFiles\Canetoad\DM420010_128m_00s__130m_00s - Toads.mp3" C:\SensorNetworks\Output\FELT_CaneToad\FELT_CaneToad_Params.txt events.txt
            //string testRecording = @"C:\SensorNetworks\WavFiles\Gecko\Suburban_March2010\geckos_suburban_104.mp3";
            //string testRecording = @"C:\SensorNetworks\WavFiles\Gecko\Suburban_March2010\geckos_suburban_18.mp3";
            //string testRecording = @"C:\SensorNetworks\WavFiles\Currawongs\Currawong_JasonTagged\West_Knoll_Bees_20091102-170000.mp3";
            //string testRecording = @"C:\SensorNetworks\WavFiles\Curlew\Curlew2\Top_Knoll_-_St_Bees_20090517-210000.wav";

            string listOpDir        = "C:\\SensorNetworks\\Output\\FELT_templateList\\";
            string templateListPath = listOpDir + "templateTestList.txt";
            var    list             = new List <string>();

            list.Add("#" + outputDir + targetName + "_binaryTemplate.zip");
            list.Add("#" + outputDir + targetName + "_trinaryTemplate.zip");
            list.Add("#" + outputDir + targetName + "_syntacticTemplate.zip");
            FileTools.Append2TextFile(templateListPath, list);      //write the template.ZIP file

            //TEST THE TEMPLATE ON SOURCE FILE
            //string[] arguments = new string[3];

            /*
             * var args = new FeltTemplates_Use.Arguments()
             *         {
             *             Source = "",
             * arguments[0] = sourceDir + "\\" + sourceFile;
             * arguments[1] = templateListPath;
             * arguments[2] = listOpDir;
             *
             *         }*/
            //FeltTemplates_Use.Dev(arguments);

            Log.WriteLine("# Finished everything!");
        }
Exemple #7
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);
        }
Exemple #8
0
        public Tuple <DataTable, DataTable> ProcessCsvFile(FileInfo fiCsvFile, FileInfo fiConfigFile)
        {
            DataTable dt = CsvTools.ReadCSVToTable(fiCsvFile.FullName, true); //get original data table

            if ((dt == null) || (dt.Rows.Count == 0))
            {
                return(null);
            }
            //get its column headers
            var dtHeaders = new List <string>();
            var dtTypes   = new List <Type>();

            foreach (DataColumn col in dt.Columns)
            {
                dtHeaders.Add(col.ColumnName);
                dtTypes.Add(col.DataType);
            }

            List <string> displayHeaders = null;

            //check if config file contains list of display headers
            if (fiConfigFile != null)
            {
                var configuration = new ConfigDictionary(fiConfigFile.FullName);
                Dictionary <string, string> configDict = configuration.GetTable();
                if (configDict.ContainsKey(AnalysisKeys.DisplayColumns))
                {
                    displayHeaders = configDict[AnalysisKeys.DisplayColumns].Split(',').ToList();
                }
            }
            //if config file does not exist or does not contain display headers then use the original headers
            if (displayHeaders == null)
            {
                displayHeaders = dtHeaders;                         //use existing headers if user supplies none.
            }
            //now determine how to display tracks in display datatable
            Type[] displayTypes = new Type[displayHeaders.Count];
            bool[] canDisplay   = new bool[displayHeaders.Count];
            for (int i = 0; i < displayTypes.Length; i++)
            {
                displayTypes[i] = typeof(double);
                canDisplay[i]   = false;
                if (dtHeaders.Contains(displayHeaders[i]))
                {
                    canDisplay[i] = true;
                }
            }

            DataTable table2Display = DataTableTools.CreateTable(displayHeaders.ToArray(), displayTypes);

            foreach (DataRow row in dt.Rows)
            {
                DataRow newRow = table2Display.NewRow();
                for (int i = 0; i < canDisplay.Length; i++)
                {
                    if (canDisplay[i])
                    {
                        newRow[displayHeaders[i]] = row[displayHeaders[i]];
                    }
                    else
                    {
                        newRow[displayHeaders[i]] = 0.0;
                    }
                }
                table2Display.Rows.Add(newRow);
            }

            //order the table if possible
            if (dt.Columns.Contains(AnalysisKeys.EventStartAbs))
            {
                dt = DataTableTools.SortTable(dt, AnalysisKeys.EventStartAbs + " ASC");
            }
            else if (dt.Columns.Contains(AnalysisKeys.EventCount))
            {
                dt = DataTableTools.SortTable(dt, AnalysisKeys.EventCount + " ASC");
            }
            else if (dt.Columns.Contains(AnalysisKeys.KeyRankOrder))
            {
                dt = DataTableTools.SortTable(dt, AnalysisKeys.KeyRankOrder + " ASC");
            }
            else if (dt.Columns.Contains(AnalysisKeys.KeyStartMinute))
            {
                dt = DataTableTools.SortTable(dt, AnalysisKeys.KeyStartMinute + " ASC");
            }

            //this depracted now that use class indexProperties to do normalisation
            //table2Display = NormaliseColumnsOfDataTable(table2Display);

            //add in column of weighted indices
            //bool addColumnOfweightedIndices = true;
            //if (addColumnOfweightedIndices)
            //{
            //    double[] comboWts = IndexCalculate.CalculateComboWeights();
            //    double[] weightedIndices = IndexCalculate.GetArrayOfWeightedAcousticIndices(dt, comboWts);
            //    string colName = "WeightedIndex";
            //    DataTableTools.AddColumnOfDoubles2Table(table2Display, colName, weightedIndices);
            //}
            return(Tuple.Create(dt, table2Display));
        } // ProcessCsvFile()
Exemple #9
0
        public static void Execute(Arguments arguments)
        {
            if (arguments == null)
            {
                arguments = Dev();
            }

            const string Title = "# EXTRACT AND SAVE ACOUSTIC EVENT.";
            string       date  = "# DATE AND TIME: " + DateTime.Now;

            Log.WriteLine(Title);
            Log.WriteLine(date);

            FileInfo recordingPath = arguments.Source;
            FileInfo iniPath       = arguments.Config; // path of the ini or params file
            string   targetName    = arguments.Target; // prefix of name of created files

            DirectoryInfo outputDir         = iniPath.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");
            FileInfo      sonogramImagePath = outputDir.CombineFile(Path.GetFileNameWithoutExtension(recordingPath.Name) + ".png");

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

            //i: GET RECORDING
            AudioRecording recording = new AudioRecording(recordingPath.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(iniPath);
            Dictionary <string, string> dict = config.GetTable();
            //Dictionary<string, string>.KeyCollection keys = dict.Keys;

            double frameOverlap   = FeltTemplates_Use.FeltFrameOverlap; // Double.Parse(dict[key_FRAME_OVERLAP]);
            double eventStart     = double.Parse(dict[key_EVENT_START]);
            double eventEnd       = double.Parse(dict[key_EVENT_END]);
            int    minHz          = int.Parse(dict[key_MIN_HZ]);
            int    maxHz          = int.Parse(dict[key_MAX_HZ]);
            double dBThreshold    = double.Parse(dict[key_DECIBEL_THRESHOLD]); //threshold to set MIN DECIBEL BOUND
            int    DRAW_SONOGRAMS = int.Parse(dict[key_DRAW_SONOGRAMS]);       //options to draw sonogram

            // iii: Extract the event as TEMPLATE
            // #############################################################################################################################################
            Log.WriteLine("# Start extracting target event.");
            var results            = Execute_Extraction(recording, eventStart, eventEnd, minHz, maxHz, frameOverlap, dBThreshold, TimeSpan.Zero);
            var sonogram           = results.Item1;
            var extractedEvent     = results.Item2;
            var template           = results.Item3; // event's matrix of target values before noise removal
            var noiseSubband       = results.Item4; // event's array  of noise  values
            var templateMinusNoise = results.Item5; // event's matrix of target values after noise removal

            Log.WriteLine("# Finished extracting target event.");
            // #############################################################################################################################################

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

            // v: SAVE image of extracted event in the original sonogram

            DrawSonogram(sonogram, sonogramImagePath.FullName, extractedEvent);

            // vi: SAVE extracted event as noise reduced image
            // alter matrix dynamic range so user can determine correct dynamic range from image
            // matrix = SNR.SetDynamicRange(matrix, 0.0, dynamicRange);       // set event's dynamic range
            var results1    = BaseSonogram.Data2ImageData(templateMinusNoise);
            var targetImage = results1.Item1;
            var min         = results1.Item2;
            var max         = results1.Item3;

            ImageTools.DrawMatrix(targetImage, 1, 1, targetImagePath.FullName);

            // vii: SAVE parameters file
            dict.Add(key_SOURCE_DIRECTORY, arguments.Source.DirectoryName);
            dict.Add(key_SOURCE_RECORDING, arguments.Source.Name);
            dict.Add(key_TEMPLATE_MIN_INTENSITY, min.ToString());
            dict.Add(key_TEMPLATE_MAX_INTENSITY, max.ToString());
            WriteParamsFile(paramsPath.FullName, dict);

            Log.WriteLine("# Finished everything!");
        }
Exemple #10
0
        public static void Execute(Arguments arguments)
        {
            if (arguments == null)
            {
                arguments = Dev();
            }

            LoggedConsole.WriteLine("DATE AND TIME:" + DateTime.Now);
            LoggedConsole.WriteLine("Syntactic Pattern Recognition\n");
            //StringBuilder sb = new StringBuilder("DATE AND TIME:" + DateTime.Now + "\n");
            //sb.Append("SCAN ALL RECORDINGS IN A DIRECTORY USING HTK-RECOGNISER\n");

            Log.Verbosity = 1;

            FileInfo      recordingPath = arguments.Source;
            FileInfo      iniPath       = arguments.Config;
            DirectoryInfo outputDir     = arguments.Output;
            string        opFName       = "SPR-output.txt";
            string        opPath        = outputDir + opFName;

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

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

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

            string callName     = dict[key_CALL_NAME];
            double frameOverlap = Convert.ToDouble(dict[key_FRAME_OVERLAP]);
            //SPT PARAMETERS
            double intensityThreshold   = Convert.ToDouble(dict[key_SPT_INTENSITY_THRESHOLD]);
            int    smallLengthThreshold = Convert.ToInt32(dict[key_SPT_SMALL_LENGTH_THRESHOLD]);
            //WHIPBIRD PARAMETERS
            int    whistle_MinHz          = int.Parse(dict[key_WHISTLE_MIN_HZ]);
            int    whistle_MaxHz          = int.Parse(dict[key_WHISTLE_MAX_HZ]);
            double optimumWhistleDuration = double.Parse(dict[key_WHISTLE_DURATION]);   //optimum duration of whistle in seconds
            int    whip_MinHz             = (dict.ContainsKey(key_WHIP_MIN_HZ)) ? int.Parse(dict[key_WHIP_MIN_HZ]) : 0;
            int    whip_MaxHz             = (dict.ContainsKey(key_WHIP_MAX_HZ)) ? int.Parse(dict[key_WHIP_MAX_HZ]) : 0;
            double whipDuration           = (dict.ContainsKey(key_WHIP_DURATION)) ? double.Parse(dict[key_WHIP_DURATION]) : 0.0; //duration of whip in seconds
            //CURLEW PARAMETERS
            double minDuration = (dict.ContainsKey(key_MIN_DURATION)) ? double.Parse(dict[key_MIN_DURATION]) : 0.0;              //min duration of call in seconds
            double maxDuration = (dict.ContainsKey(key_MAX_DURATION)) ? double.Parse(dict[key_MAX_DURATION]) : 0.0;              //duration of call in seconds

            double eventThreshold = double.Parse(dict[key_EVENT_THRESHOLD]);                                                     //min score for an acceptable event
            int    DRAW_SONOGRAMS = Convert.ToInt16(dict[key_DRAW_SONOGRAMS]);

            // B: CHECK to see if conversion from .MP3 to .WAV is necessary
            var destinationAudioFile = recordingPath;

            //LOAD RECORDING AND MAKE SONOGRAM
            BaseSonogram sonogram = null;

            using (var recording = new AudioRecording(destinationAudioFile.FullName))
            {
                // if (recording.SampleRate != 22050) recording.ConvertSampleRate22kHz(); // THIS METHOD CALL IS OBSOLETE

                var sonoConfig = new SonogramConfig
                {
                    NoiseReductionType = NoiseReductionType.None,
                    //NoiseReductionType = NoiseReductionType.STANDARD,
                    WindowOverlap = frameOverlap,
                };
                sonogram = new SpectrogramStandard(sonoConfig, recording.WavReader);
            }

            List <AcousticEvent> predictedEvents = null;

            double[,] hits = null;
            double[] scores = null;

            var audioFileName = Path.GetFileNameWithoutExtension(destinationAudioFile.FullName);

            if (callName.Equals("WHIPBIRD"))
            {
                //SPT
                var result1 = SPT.doSPT(sonogram, intensityThreshold, smallLengthThreshold);
                //SPR
                Log.WriteLine("SPR start: intensity threshold = " + intensityThreshold);
                int    slope       = 0;   //degrees of the circle. i.e. 90 = vertical line.
                double sensitivity = 0.7; //lower value = more sensitive
                var    mHori       = MarkLine(result1.Item1, slope, smallLengthThreshold, intensityThreshold, sensitivity);
                slope       = 87;         //84
                sensitivity = 0.8;        //lower value = more sensitive
                var mVert = MarkLine(result1.Item1, slope, smallLengthThreshold - 4, intensityThreshold + 1, sensitivity);
                Log.WriteLine("SPR finished");
                Log.WriteLine("Extract Whipbird calls - start");

                int minBound_Whistle = (int)(whistle_MinHz / sonogram.FBinWidth);
                int maxBound_Whistle = (int)(whistle_MaxHz / sonogram.FBinWidth);
                int whistleFrames    = (int)(sonogram.FramesPerSecond * optimumWhistleDuration); //86 = frames/sec.
                int minBound_Whip    = (int)(whip_MinHz / sonogram.FBinWidth);
                int maxBound_Whip    = (int)(whip_MaxHz / sonogram.FBinWidth);
                int whipFrames       = (int)(sonogram.FramesPerSecond * whipDuration); //86 = frames/sec.
                var result3          = DetectWhipBird(mHori, mVert, minBound_Whistle, maxBound_Whistle, whistleFrames, minBound_Whip, maxBound_Whip, whipFrames, smallLengthThreshold);
                scores = result3.Item1;
                hits   = DataTools.AddMatrices(mHori, mVert);

                predictedEvents = AcousticEvent.ConvertScoreArray2Events(
                    scores,
                    whip_MinHz,
                    whip_MaxHz,
                    sonogram.FramesPerSecond,
                    sonogram.FBinWidth,
                    eventThreshold,
                    minDuration,
                    maxDuration,
                    TimeSpan.Zero);
                foreach (AcousticEvent ev in predictedEvents)
                {
                    ev.FileName = audioFileName;
                    ev.Name     = callName;
                }

                sonogram.Data = result1.Item1;
                Log.WriteLine("Extract Whipbird calls - finished");
            }
            else if (callName.Equals("CURLEW"))
            {
                //SPT
                double backgroundThreshold = 4.0;
                var    result1             = SNR.NoiseReduce(sonogram.Data, NoiseReductionType.Standard, backgroundThreshold);
                //var result1 = SPT.doSPT(sonogram, intensityThreshold, smallLengthThreshold);
                //var result1 = doNoiseRemoval(sonogram, intensityThreshold, smallLengthThreshold);

                //SPR
                Log.WriteLine("SPR start: intensity threshold = " + intensityThreshold);
                int    slope       = 20;  //degrees of the circle. i.e. 90 = vertical line.
                double sensitivity = 0.8; //lower value = more sensitive
                var    mHori       = MarkLine(result1.Item1, slope, smallLengthThreshold, intensityThreshold, sensitivity);
                slope       = 160;
                sensitivity = 0.8;        //lower value = more sensitive
                var mVert = MarkLine(result1.Item1, slope, smallLengthThreshold - 3, intensityThreshold + 1, sensitivity);
                Log.WriteLine("SPR finished");

                //detect curlew calls
                int minBound_Whistle = (int)(whistle_MinHz / sonogram.FBinWidth);
                int maxBound_Whistle = (int)(whistle_MaxHz / sonogram.FBinWidth);
                int whistleFrames    = (int)(sonogram.FramesPerSecond * optimumWhistleDuration);
                var result3          = DetectCurlew(mHori, mVert, minBound_Whistle, maxBound_Whistle, whistleFrames, smallLengthThreshold);

                //process curlew scores - look for curlew characteristic periodicity
                double minPeriod        = 1.2;
                double maxPeriod        = 1.8;
                int    minPeriod_frames = (int)Math.Round(sonogram.FramesPerSecond * minPeriod);
                int    maxPeriod_frames = (int)Math.Round(sonogram.FramesPerSecond * maxPeriod);
                scores = DataTools.filterMovingAverage(result3.Item1, 21);
                scores = DataTools.PeriodicityDetection(scores, minPeriod_frames, maxPeriod_frames);

                //extract events
                predictedEvents = AcousticEvent.ConvertScoreArray2Events(
                    scores,
                    whistle_MinHz,
                    whistle_MaxHz,
                    sonogram.FramesPerSecond,
                    sonogram.FBinWidth,
                    eventThreshold,
                    minDuration,
                    maxDuration,
                    TimeSpan.Zero);
                foreach (AcousticEvent ev in predictedEvents)
                {
                    ev.FileName = audioFileName;
                    ev.Name     = callName;
                }

                hits          = DataTools.AddMatrices(mHori, mVert);
                sonogram.Data = result1.Item1;
                Log.WriteLine("Extract Curlew calls - finished");
            }
            else if (callName.Equals("CURRAWONG"))
            {
                //SPT
                var result1 = SPT.doSPT(sonogram, intensityThreshold, smallLengthThreshold);
                //SPR
                Log.WriteLine("SPR start: intensity threshold = " + intensityThreshold);
                int slope = 70;           //degrees of the circle. i.e. 90 = vertical line.
                //slope = 210;
                double sensitivity = 0.7; //lower value = more sensitive
                var    mHori       = MarkLine(result1.Item1, slope, smallLengthThreshold, intensityThreshold, sensitivity);
                slope = 110;
                //slope = 340;
                sensitivity = 0.7;        //lower value = more sensitive
                var mVert = MarkLine(result1.Item1, slope, smallLengthThreshold - 3, intensityThreshold + 1, sensitivity);
                Log.WriteLine("SPR finished");

                int minBound_Whistle = (int)(whistle_MinHz / sonogram.FBinWidth);
                int maxBound_Whistle = (int)(whistle_MaxHz / sonogram.FBinWidth);
                int whistleFrames    = (int)(sonogram.FramesPerSecond * optimumWhistleDuration); //86 = frames/sec.
                var result3          = DetectCurlew(mHori, mVert, minBound_Whistle, maxBound_Whistle, whistleFrames + 10, smallLengthThreshold);
                scores = result3.Item1;
                hits   = DataTools.AddMatrices(mHori, mVert);

                predictedEvents = AcousticEvent.ConvertIntensityArray2Events(
                    scores,
                    TimeSpan.Zero,
                    whistle_MinHz,
                    whistle_MaxHz,
                    sonogram.FramesPerSecond,
                    sonogram.FBinWidth,
                    eventThreshold,
                    0.5,
                    maxDuration);
                foreach (AcousticEvent ev in predictedEvents)
                {
                    ev.FileName = audioFileName;
                    //ev.Name = callName;
                }
            }

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

            Log.WriteIfVerbose("Number of Events: " + count);
            string str = string.Format("{0}\t{1}\t{2}", callName, sigDuration, count);

            FileTools.WriteTextFile(opPath, AcousticEvent.WriteEvents(predictedEvents, str).ToString());

            // SAVE IMAGE
            string imageName = outputDir + audioFileName;
            string imagePath = imageName + ".png";

            if (File.Exists(imagePath))
            {
                int suffix = 1;
                while (File.Exists(imageName + "." + suffix.ToString() + ".png"))
                {
                    suffix++;
                }
                //{
                //    suffix = (suffix == string.Empty) ? "1" : (int.Parse(suffix) + 1).ToString();
                //}
                //File.Delete(outputDir + audioFileName + "." + suffix.ToString() + ".png");
                File.Move(imagePath, imageName + "." + suffix.ToString() + ".png");
            }
            //string newPath = imagePath + suffix + ".png";
            if (DRAW_SONOGRAMS == 2)
            {
                DrawSonogram(sonogram, imagePath, hits, scores, predictedEvents, eventThreshold);
            }
            else
            if ((DRAW_SONOGRAMS == 1) && (predictedEvents.Count > 0))
            {
                DrawSonogram(sonogram, imagePath, hits, scores, predictedEvents, eventThreshold);
            }

            Log.WriteIfVerbose("Image saved to: " + imagePath);
            //string savePath = outputDir + Path.GetFileNameWithoutExtension(recordingPath);
            //string suffix = string.Empty;
            //Image im = sonogram.GetImage(false, false);
            //string newPath = savePath + suffix + ".jpg";
            //im.Save(newPath);

            LoggedConsole.WriteLine("\nFINISHED RECORDING!");
            Console.ReadLine();
        }
        public static void Execute(Arguments arguments)
        {
            if (arguments == null)
            {
                arguments = Dev();
            }

            string title = "# FIND OTHER ACOUSTIC EVENTS LIKE THIS";
            string date  = "# DATE AND TIME: " + DateTime.Now;

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

            Log.Verbosity = 1;
            Log.WriteIfVerbose("# Recording     =" + arguments.Source); //the recording to be scanned
            Log.WriteIfVerbose("# Template list =" + arguments.Config); //the path to a file containing the paths to template locations, one template per line
            Log.WriteIfVerbose("# Output folder =" + arguments.Output); //name of output dir

            var allEvents     = new List <AcousticEvent>();
            var scoresList    = new List <double[]>();
            var thresholdList = new List <double>();

            //i: GET RECORDING
            AudioRecording recording = new AudioRecording(arguments.Source.FullName);
            //if (recording.SampleRate != 22050) recording.ConvertSampleRate22kHz(); // THIS METHOD CALL IS OBSOLETE
            int sr = recording.SampleRate;

            //ii: MAKE SONOGRAM
            Log.WriteLine("Start sonogram.");
            SonogramConfig sonoConfig = new SonogramConfig(); //default values config

            sonoConfig.SourceFName        = recording.BaseName;
            sonoConfig.WindowOverlap      = FeltFrameOverlap; // set default value
            sonoConfig.DoMelScale         = false;
            sonoConfig.NoiseReductionType = NoiseReductionType.Standard;
            AmplitudeSonogram   basegram = new AmplitudeSonogram(sonoConfig, recording.WavReader);
            SpectrogramStandard sonogram = new SpectrogramStandard(basegram);  //spectrogram has dim[N,257]

            Log.WriteLine("Signal: Duration={0}, Sample Rate={1}", sonogram.Duration, sr);
            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, FeltFrameOverlap * 100);

            //iii: Get zip paths and the results Tuple
            List <string> zipList = FileTools.ReadTextFile(arguments.Config.FullName);
            Tuple <SpectrogramStandard, List <AcousticEvent>, double[]> results = null; //set up the results Tuple

            foreach (string zipPath in zipList)
            {
                if (zipPath.StartsWith("#"))
                {
                    continue;                           // commented line
                }
                if (zipPath.Length < 2)
                {
                    continue;                           // empty line
                }
                //i: get params file
                ZipFile.ExtractToDirectory(arguments.Output.FullName, zipPath);
                string   zipName    = Path.GetFileNameWithoutExtension(zipPath);
                string[] parts      = zipName.Split('_');
                string   paramsPath = Path.Combine(arguments.Output.FullName, parts[0] + "_" + parts[1] + "_Params.txt");

                string id = parts[0] + "_" + parts[1];
                Log.WriteIfVerbose("################################################### " + id + " ########################################################");

                //ii: READ PARAMETER VALUES FROM INI FILE
                var config = new ConfigDictionary(paramsPath);
                Dictionary <string, string> dict = config.GetTable();
                //Dictionary<string, string>.KeyCollection keys = dict.Keys;
                //int DRAW_SONOGRAMS = Int32.Parse(dict[FeltTemplate_Create.key_DRAW_SONOGRAMS]);          //options to draw sonogram
                dict[FeltTemplate_Create.key_DECIBEL_THRESHOLD] = "4.0";
                dict[FeltTemplate_Create.key_MIN_DURATION]      = "0.02";

                if (zipName.EndsWith("binaryTemplate"))
                {
                    string templatePath = Path.Combine(arguments.Output.FullName, id + "_binary.bmp");
                    double[,] templateMatrix = FindMatchingEvents.ReadImage2BinaryMatrixDouble(templatePath);
                    results = FELTWithBinaryTemplate(sonogram, dict, templateMatrix, TimeSpan.Zero);
                }
                else
                if (zipName.EndsWith("trinaryTemplate"))
                {
                    string templatePath = Path.Combine(arguments.Output.FullName, id + "_trinary.bmp");
                    double[,] templateMatrix = FindMatchingEvents.ReadImage2TrinaryMatrix(templatePath);
                    results = FELTWithBinaryTemplate(sonogram, dict, templateMatrix, TimeSpan.Zero);
                }
                else
                if (zipName.EndsWith("syntacticTemplate"))
                {
                    string templatePath = Path.Combine(arguments.Output.FullName, id + "_spr.txt");
                    char[,] templateMatrix = FindMatchingEvents.ReadTextFile2CharMatrix(templatePath);
                    results = FELTWithSprTemplate(sonogram, dict, templateMatrix, TimeSpan.Zero);
                }
                else
                {
                    Log.WriteLine("ERROR! UNKNOWN TEMPLATE: Zip file has unrecognised suffix:" + zipName);
                    continue;
                }

                //get results
                sonogram = results.Item1;
                var matchingEvents = results.Item2;
                var scores         = results.Item3;

                double matchThreshold = double.Parse(dict[FeltTemplate_Create.key_DECIBEL_THRESHOLD]);
                Log.WriteLine("# Finished detecting events like target: " + id);
                Log.WriteLine("# Matching Event Count = " + matchingEvents.Count);
                Log.WriteLine("           @ threshold = {0:f2}", matchThreshold);

                // accumulate results
                allEvents.AddRange(matchingEvents);
                scoresList.Add(scores);
                thresholdList.Add(matchThreshold);

                //v: write events count to results info file.
                double        sigDuration = sonogram.Duration.TotalSeconds;
                string        fname       = arguments.Source.Name;
                string        str         = string.Format("{0}\t{1}\t{2}", fname, sigDuration, matchingEvents.Count);
                StringBuilder sb          = AcousticEvent.WriteEvents(matchingEvents, str);
                FileTools.WriteTextFile("opPath", sb.ToString());
            } // foreach (string zipPath in zipList)

            Log.WriteLine("\n\n\n##########################################################");
            Log.WriteLine("# Finished detecting events");
            Log.WriteLine("# Event Count = " + allEvents.Count);
            foreach (AcousticEvent ae in allEvents)
            {
                Log.WriteLine("# Event name = {0}  ############################", ae.Name);
                Log.WriteLine("# Event time = {0:f2} to {1:f2} (frames {2}-{3}).", ae.TimeStart, ae.TimeEnd, ae.Oblong.RowTop, ae.Oblong.RowBottom);
                Log.WriteLine("# Event score= {0:f2}.", ae.Score);
            }

            int percentOverlap = 50;

            allEvents = PruneOverlappingEvents(allEvents, percentOverlap);
            Log.WriteLine("\n##########################################################");
            Log.WriteLine("# Finished pruning events");
            Log.WriteLine("# Event Count = " + allEvents.Count);
            WriteEventNames(allEvents);

            //WriteScoreAverages2Console(scoresList);

            //draw images of sonograms
            int      DRAW_SONOGRAMS = 2;
            FileInfo opImagePath    = arguments.Output.CombineFile(Path.GetFileNameWithoutExtension(arguments.Source.Name) + "_matchingEvents.png");

            if (DRAW_SONOGRAMS == 2)
            {
                DrawSonogram(sonogram, opImagePath, allEvents, thresholdList, scoresList);
            }
            else
            if ((DRAW_SONOGRAMS == 1) && (allEvents.Count > 0))
            {
                DrawSonogram(sonogram, opImagePath, allEvents, thresholdList, scoresList);
            }

            Log.WriteLine("# FINISHED passing all templates over recording:- " + arguments.Source.Name);
        }