Ejemplo n.º 1
0
        public void TestDrawRgbColorMatrix()
        {
            // init three matrices
            double[,] redM = new double[5, 5];
            double[,] grnM = new double[5, 5];
            double[,] bluM = new double[5, 5];

            //convert some values to null or NaN
            redM[1, 1] = double.NaN;
            grnM[1, 1] = double.NaN;
            bluM[1, 1] = double.NaN;

            redM[2, 2] = 1.0;
            grnM[2, 2] = 1.0;
            bluM[2, 2] = double.NaN;

            redM[3, 3] = 0.01;
            grnM[3, 3] = 0.01;
            bluM[3, 3] = 0.11;

            var blueEnhanceParameter = 0.0;
            var image = (Bitmap)LDSpectrogramRGB.DrawRgbColorMatrix(redM, grnM, bluM, doReverseColor: true, blueEnhanceParameter);

            Assert.That.PixelIsColor(new Point(1, 1), Color.FromArgb(128, 128, 128), image);
            Assert.That.PixelIsColor(new Point(2, 2), Color.FromArgb(128, 128, 128), image);

            // empty values are rendered as white because of `doReverseColour`
            Assert.That.ImageRegionIsColor(Rectangle.FromLTRB(0, 0, 1, 5), Color.FromArgb(255, 255, 255), image);
            Assert.That.ImageRegionIsColor(Rectangle.FromLTRB(4, 0, 5, 5), Color.FromArgb(255, 255, 255), image);
        }
Ejemplo n.º 2
0
        public static Image <Rgb24> Frame3DSpectrogram(Image <Rgb24> image, string key, int value, int year, string colorMap, TimeSpan xInterval, int nyquistFreq, int unitValue, FileInfo sunriseSetData)
        {
            if (key == KeyDayOfYear)
            {
                var title    = string.Format("SPECTROGRAM (hours x Herz): {0}={1}      (R-G-B={2})", key, value, colorMap, unitValue);
                var titleBar = LDSpectrogramRGB.DrawTitleBarOfFalseColourSpectrogram(title, image.Width);
                return(FrameSliceOf3DSpectrogram_DayOfYear(image, titleBar, year, value, xInterval, unitValue, sunriseSetData, nyquistFreq));
            }
            else
            if (key == KeyFreqBin)
            {
                var title    = string.Format("SPECTROGRAM (hours x months): {0}={1}      (R-G-B={2})", key, value, colorMap, unitValue);
                var titleBar = LDSpectrogramRGB.DrawTitleBarOfFalseColourSpectrogram(title, image.Width);
                return(FrameSliceOf3DSpectrogram_ConstantFreq(image, titleBar, xInterval, unitValue, sunriseSetData, nyquistFreq));
            }
            else
            if (key == KeyMinOfDay)
            {
                var title    = string.Format("SPECTROGRAM (months x Herz): {0}={1}       (R-G-B={2})", key, value, colorMap, unitValue);
                var titleBar = LDSpectrogramRGB.DrawTitleBarOfFalseColourSpectrogram(title, image.Width);
                return(FrameSliceOf3DSpectrogram_ConstantMin((Image <Rgb24>)image, titleBar, nyquistFreq, unitValue, sunriseSetData));
            }

            return(null);
        }
        /// <summary>
        /// This method compares the acoustic indices derived from two different long duration recordings of the same length.
        /// It takes as input six csv files of acoustic indices in spectrogram columns, three csv files for each of the original recordings to be compared.
        /// The method produces one spectrogram image files:
        /// 1) A false-colour difference spectrogram, where the difference is shown as a plus/minus departure from grey.
        /// </summary>
        public static void DrawDifferenceSpectrogram(DirectoryInfo ipdir, FileInfo ipFileName1, FileInfo ipFileName2, DirectoryInfo opdir)
        {
            var cs1 = new LDSpectrogramRGB(minuteOffset, xScale, sampleRate, frameWidth, colorMap)
            {
                FileName         = ipFileName1.Name,
                ColorMode        = colorMap,
                BackgroundFilter = backgroundFilterCoeff,
            };

            string[] keys = colorMap.Split('-');
            cs1.ReadCsvFiles(ipdir, ipFileName1.Name, keys);
            if (cs1.GetCountOfSpectrogramMatrices() == 0)
            {
                LoggedConsole.WriteLine("There are no spectrogram matrices in cs1.dictionary.");
                return;
            }

            var cs2 = new LDSpectrogramRGB(minuteOffset, xScale, sampleRate, frameWidth, colorMap)
            {
                FileName         = ipFileName2.Name,
                ColorMode        = colorMap,
                BackgroundFilter = backgroundFilterCoeff,
            };

            cs2.ReadCsvFiles(ipdir, ipFileName2.Name, keys);
            if (cs2.GetCountOfSpectrogramMatrices() == 0)
            {
                LoggedConsole.WriteLine("There are no spectrogram matrices in cs2.dictionary.");
                return;
            }

            //string title1 = String.Format("DIFFERENCE SPECTROGRAM ({0} - {1})      (scale:hours x kHz)       (colour: R-G-B={2})", ipFileName1, ipFileName2, cs1.ColorMODE);
            //Image deltaSp1 = LDSpectrogramDifference.DrawDifferenceSpectrogram(cs1, cs2, colourGain);
            //Image titleBar1 = LDSpectrogramRGB.DrawTitleBarOfFalseColourSpectrogram(title1, deltaSp1.Width, SpectrogramConstants.HEIGHT_OF_TITLE_BAR);
            //deltaSp1 = LDSpectrogramRGB.FrameSpectrogram(deltaSp1, titleBar1, minuteOffset, cs1.X_interval, cs1.Y_interval);
            //string opFileName1 = ipFileName1 + ".Difference.COLNEG.png";
            //deltaSp1.Save(Path.Combine(opdir.FullName, opFileName1));

            //Draw positive difference spectrograms in one image.
            double colourGain = 2.0;

            Image <Rgb24>[] images = DrawPositiveDifferenceSpectrograms(cs1, cs2, colourGain);

            int    nyquist      = cs1.SampleRate / 2;
            int    herzInterval = 1000;
            string title        =
                $"DIFFERENCE SPECTROGRAM where {ipFileName1} > {ipFileName2}.      (scale:hours x kHz)       (colour: R-G-B={cs1.ColorMode})";
            var titleBar = LDSpectrogramRGB.DrawTitleBarOfFalseColourSpectrogram(title, images[0].Width);

            images[0] = LDSpectrogramRGB.FrameLDSpectrogram(images[0], titleBar, cs1, nyquist, herzInterval);

            title     = string.Format("DIFFERENCE SPECTROGRAM where {1} > {0}      (scale:hours x kHz)       (colour: R-G-B={2})", ipFileName1, ipFileName2, cs1.ColorMode);
            titleBar  = LDSpectrogramRGB.DrawTitleBarOfFalseColourSpectrogram(title, images[1].Width);
            images[1] = LDSpectrogramRGB.FrameLDSpectrogram(images[1], titleBar, cs1, nyquist, herzInterval);
            Image  combinedImage = ImageTools.CombineImagesVertically(images);
            string opFileName    = ipFileName1 + "-" + ipFileName2 + ".Difference.png";

            combinedImage.Save(Path.Combine(opdir.FullName, opFileName));
        }
        public static Image DrawTStatisticSpectrogramsOfSingleIndex(string key, LDSpectrogramRGB cs1, LDSpectrogramRGB cs2, double tStatThreshold)
        {
            var image1 = cs1.DrawGreyscaleSpectrogramOfIndex(key);
            var image2 = cs2.DrawGreyscaleSpectrogramOfIndex(key);

            if (image1 == null || image2 == null)
            {
                Console.WriteLine("WARNING: From method ColourSpectrogram.DrawTStatisticGreyscaleSpectrogramOfIndex()");
                Console.WriteLine("         Null image returned with key: {0}", key);
                return(null);
            }

            //frame image 1
            int nyquist      = cs1.SampleRate / 2;
            int herzInterval = 1000;

            string title    = $"{key} SPECTROGRAM for: {cs1.FileName}.      (scale:hours x kHz)";
            var    titleBar = LDSpectrogramRGB.DrawTitleBarOfGrayScaleSpectrogram(title, image1.Width);

            image1 = LDSpectrogramRGB.FrameLDSpectrogram(image1, titleBar, cs1, nyquist, herzInterval);

            //frame image 2
            title    = $"{key} SPECTROGRAM for: {cs2.FileName}.      (scale:hours x kHz)";
            titleBar = LDSpectrogramRGB.DrawTitleBarOfGrayScaleSpectrogram(title, image2.Width);
            image2   = LDSpectrogramRGB.FrameLDSpectrogram(image2, titleBar, cs1, nyquist, herzInterval);

            //get matrices required to calculate matrix of t-statistics
            double[,] avg1 = cs1.GetSpectrogramMatrix(key);
            if (key.Equals("ENT"))
            {
                avg1 = MatrixTools.SubtractValuesFromOne(avg1);
            }

            double[,] std1 = cs1.GetStandarDeviationMatrix(key);
            double[,] avg2 = cs2.GetSpectrogramMatrix(key);
            if (key.Equals("ENT"))
            {
                avg2 = MatrixTools.SubtractValuesFromOne(avg2);
            }

            double[,] std2 = cs2.GetStandarDeviationMatrix(key);

            //draw a spectrogram of t-statistic values
            //double[,] tStatMatrix = SpectrogramDifference.GetTStatisticMatrix(avg1, std1, cs1.SampleCount, avg2, std2, cs2.SampleCount);
            //Image image3 = SpectrogramDifference.DrawTStatisticSpectrogram(tStatMatrix);
            //titleBar = SpectrogramDifference.DrawTitleBarOfTStatisticSpectrogram(cs1.BaseName, cs2.BaseName, image1.Width, titleHt);
            //image3 = ColourSpectrogram.FrameSpectrogram(image3, titleBar, minOffset, cs2.X_interval, cs2.Y_interval);

            //draw a difference spectrogram derived from by thresholding a t-statistic matrix
            var image4 = DrawDifferenceSpectrogramDerivedFromSingleTStatistic(key, cs1, cs2, tStatThreshold, ColourGain);

            title    = string.Format("{0} DIFFERENCE SPECTROGRAM (thresholded by t-statistic={3}) for: {1} - {2}.      (scale:hours x kHz)", key, cs1.FileName, cs2.FileName, tStatThreshold);
            titleBar = LDSpectrogramRGB.DrawTitleBarOfGrayScaleSpectrogram(title, image2.Width);
            image4   = LDSpectrogramRGB.FrameLDSpectrogram(image4, titleBar, cs2, nyquist, herzInterval);

            var combinedImage = ImageTools.CombineImagesVertically(image1, image2, image4);

            return(combinedImage);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// This is cut down version of the method of same name in LDSpectrogramRGB.cs.
        /// </summary>
        /// <param name="ldSpectrogramConfig">config for ldfc spectrogram.</param>
        /// <param name="outputDirectory">outputDirectory.</param>
        /// <param name="indexGenerationData">indexGenerationData.</param>
        /// <param name="basename">stem name of the original recording.</param>
        /// <param name="indexSpectrograms">Optional spectra to pass in. If specified the spectra will not be loaded from disk!.</param>
        private static string DrawSpectrogramsFromSpectralIndices(
            LdSpectrogramConfig ldSpectrogramConfig,
            DirectoryInfo outputDirectory,
            IndexGenerationData indexGenerationData,
            string basename,
            Dictionary <string, double[, ]> indexSpectrograms = null)
        {
            string colorMap1            = ldSpectrogramConfig.ColorMap1; // SpectrogramConstants.RGBMap_ACI_ENT_EVN;
            string colorMap2            = ldSpectrogramConfig.ColorMap2; // SpectrogramConstants.RGBMap_BGN_PMN_OSC;
            double blueEnhanceParameter = ldSpectrogramConfig.BlueEnhanceParameter.Value;

            var    cs1      = new LDSpectrogramRGB(ldSpectrogramConfig, indexGenerationData, colorMap1);
            string fileStem = basename;

            cs1.FileName = fileStem;

            // calculate start time by combining DatetimeOffset with minute offset.
            cs1.StartOffset = indexGenerationData.AnalysisStartOffset;
            if (indexGenerationData.RecordingStartDate.HasValue)
            {
                DateTimeOffset dto = (DateTimeOffset)indexGenerationData.RecordingStartDate;
                cs1.RecordingStartDate = dto;
                if (dto != null)
                {
                    cs1.StartOffset = dto.TimeOfDay + cs1.StartOffset;
                }
            }

            var indexProperties = IndexCalculateSixOnly.GetIndexProperties();

            cs1.SetSpectralIndexProperties(indexProperties);

            // Load the Index Spectrograms into a Dictionary
            cs1.LoadSpectrogramDictionary(indexSpectrograms);
            if (cs1.GetCountOfSpectrogramMatrices() == 0)
            {
                Log.Error("No spectrogram matrices in the dictionary. Spectrogram files do not exist?");
                throw new InvalidOperationException("Cannot find spectrogram matrix files");
            }

            // draw all available gray scale index spectrograms.
            var keys = indexProperties.Keys.ToArray();

            cs1.DrawGreyScaleSpectrograms(outputDirectory, fileStem, keys);

            // create two false-color spectrogram images
            var   image1NoChrome = cs1.DrawFalseColorSpectrogramChromeless(cs1.ColorMode, colorMap1, blueEnhanceParameter);
            var   image2NoChrome = cs1.DrawFalseColorSpectrogramChromeless(cs1.ColorMode, colorMap2, blueEnhanceParameter);
            var   spacer         = new Image <Rgb24>(image1NoChrome.Width, 10);
            var   imageList      = new[] { image1NoChrome, spacer, image2NoChrome, spacer };
            Image image3         = ImageTools.CombineImagesVertically(imageList);
            var   outputPath     = FilenameHelpers.AnalysisResultPath(outputDirectory, fileStem, "2Maps", "png");

            image3.Save(outputPath);
            return(outputPath);
        }
        // #######################################################################################################################################
        // ### ABOVE METHODS DRAW TIME GRID LINES ON SPECTROGRAMS ####################################################################################
        // #######################################################################################################################################

        public static Image <Rgb24> GetImageFullyAnnotated(Image <Rgb24> image, string title, int[,] gridLineLocations, TimeSpan duration)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            FrequencyScale.DrawFrequencyLinesOnImage((Image <Rgb24>)image, gridLineLocations, includeLabels: true);

            var titleBar       = LDSpectrogramRGB.DrawTitleBarOfGrayScaleSpectrogram(title, image.Width);
            var timeBmp        = ImageTrack.DrawTimeTrack(duration, image.Width);
            var compositeImage = ImageTools.CombineImagesVertically(titleBar, timeBmp, image, timeBmp);

            return(compositeImage);
        }
Ejemplo n.º 7
0
        public void TestChromelessImage()
        {
            var indexPropertiesFile = ConfigFile.Default <IndexPropertiesCollection>();
            var indexProperties     = ConfigFile.Deserialize <IndexPropertiesCollection>(indexPropertiesFile);

            var indexSpectrograms = new Dictionary <string, double[, ]>(6);
            var indexStatistics   = new Dictionary <string, IndexDistributions.SpectralStats>();
            var keys = (LDSpectrogramRGB.DefaultColorMap1 + "-" + LDSpectrogramRGB.DefaultColorMap2).Split('-');

            foreach (var key in keys)
            {
                var matrix = new double[256, 60].Fill(indexProperties[key].DefaultValue);
                indexSpectrograms.Add(key, matrix);
                double[] array = DataTools.Matrix2Array(matrix);
                indexStatistics.Add(key, IndexDistributions.GetModeAndOneTailedStandardDeviation(array, 300, IndexDistributions.UpperPercentileDefault));
            }

            var images = LDSpectrogramRGB.DrawSpectrogramsFromSpectralIndices(
                inputDirectory: null,
                outputDirectory: this.outputDirectory,
                ldSpectrogramConfig: new LdSpectrogramConfig(),
                indexPropertiesConfigPath: indexPropertiesFile,
                indexGenerationData: new IndexGenerationData()
            {
                AnalysisStartOffset      = 0.Seconds(),
                FrameLength              = 512,
                IndexCalculationDuration = 60.0.Seconds(),
                RecordingBasename        = "RGB_TEST",
                RecordingDuration        = 60.0.Seconds(),
                SampleRateResampled      = 22050,
            },
                basename: "RGB_TEST",
                analysisType: AcousticIndices.AnalysisName,
                indexSpectrograms: indexSpectrograms,
                summaryIndices: Enumerable
                .Range(0, 60)
                .Select((x) => new SummaryIndexValues(60.0.Seconds(), indexProperties))
                .Cast <SummaryIndexBase>()
                .ToArray(),
                indexStatistics: indexStatistics,
                imageChrome: ImageChrome.Without);

            foreach (var(image, key) in images)
            {
                Assert.That.ImageIsSize(60, 256, image);
                Assert.That.ImageRegionIsColor(Rectangle.FromLTRB(0, 0, 60, 256), Color.Black, (Bitmap)image);
            }
        }
Ejemplo n.º 8
0
        public static Image DrawFalseColorSpectrograms(Arguments args, string fileStem, Dictionary <string, IndexProperties> indexProperties, Dictionary <string, double[, ]> spectra = null)
        {
            // note: the spectra are oriented as per visual orientation, i.e. xAxis = time framesDictionary<string, Int16>.KeyCollection keys = AuthorList.Keys
            // string[] keys = spectra.Keys.ToCommaSeparatedList().Split(',');
            // int frameCount = spectra[keys[0]].GetLength(1);

            int    sampleRate       = 22050;
            int    frameWidth       = 512;
            double backgroundFilter = 0.75;  // 0.75 means small values are accentuated.
            var    minuteOffset     = TimeSpan.Zero;
            var    dataScale        = args.TemporalScale;
            string colorMap         = args.ColourMap1 ?? LDSpectrogramRGB.DefaultColorMap1;
            var    cs1 = new LDSpectrogramRGB(minuteOffset, dataScale, sampleRate, frameWidth, colorMap)
            {
                FileName                 = fileStem,
                BackgroundFilter         = backgroundFilter,
                IndexCalculationDuration = dataScale,
            };

            // set the relevant dictionary of index properties
            cs1.SetSpectralIndexProperties(indexProperties);
            cs1.SpectrogramMatrices = spectra;

            // get parameter from the config file.
            var configFile           = args.FalseColourSpectrogramConfig.ToFileInfo();
            var config               = LdSpectrogramConfig.ReadYamlToConfig(configFile);
            var blueEnhanceParameter = config.BlueEnhanceParameter ?? 0.0;

            var image1       = cs1.DrawFalseColorSpectrogramChromeless("NEGATIVE", colorMap, blueEnhanceParameter);
            var fullDuration = TimeSpan.FromSeconds(image1.Width * dataScale.TotalSeconds);

            string title       = fileStem;
            var    titleImage  = LDSpectrogramRGB.DrawTitleBarOfFalseColourSpectrogram(title, image1.Width);
            int    trackHeight = 20;
            var    timeScale   = ImageTrack.DrawTimeRelativeTrack(fullDuration, image1.Width, trackHeight);

            colorMap = args.ColourMap2 ?? LDSpectrogramRGB.DefaultColorMap2;
            var image2 = cs1.DrawFalseColorSpectrogramChromeless("NEGATIVE", colorMap, blueEnhanceParameter);
            var list   = new List <Image> {
                titleImage, image1, timeScale, image2
            };
            var combinedImage = ImageTools.CombineImagesVertically(list.ToArray());

            return(combinedImage);
        }
        public Image GetImageFullyAnnotated(Image image, string title, int[,] gridLineLocations)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            FrequencyScale.DrawFrequencyLinesOnImage((Bitmap)image, gridLineLocations, includeLabels: true);

            var titleBar = LDSpectrogramRGB.DrawTitleBarOfGrayScaleSpectrogram(title, image.Width);
            var timeBmp  = ImageTrack.DrawTimeTrack(this.Duration, image.Width);
            var list     = new List <Image> {
                titleBar, timeBmp, image, timeBmp
            };
            var compositeImage = ImageTools.CombineImagesVertically(list);

            return(compositeImage);
        }
        public static Image DrawDifferenceSpectrogram(LDSpectrogramRGB target, LDSpectrogramRGB reference, double colourGain)
        {
            string[] keys = target.ColorMap.Split('-');
            double[,] tgtRedM = target.GetNormalisedSpectrogramMatrix(keys[0]);
            double[,] tgtGrnM = target.GetNormalisedSpectrogramMatrix(keys[1]);
            double[,] tgtBluM = target.GetNormalisedSpectrogramMatrix(keys[2]);

            double[,] refRedM = reference.GetNormalisedSpectrogramMatrix(keys[0]);
            double[,] refGrnM = reference.GetNormalisedSpectrogramMatrix(keys[1]);
            double[,] refBluM = reference.GetNormalisedSpectrogramMatrix(keys[2]);

            // assume all matricies are normalised and of the same dimensions
            int rows = tgtRedM.GetLength(0); //number of rows
            int cols = tgtRedM.GetLength(1); //number

            Image <Rgb24> bmp = new Image <Rgb24>(cols, rows);

            int maxRGBValue = 255;

            for (int row = 0; row < rows; row++)
            {
                for (int column = 0; column < cols; column++)
                {
                    var d1 = (tgtRedM[row, column] - refRedM[row, column]) * colourGain;
                    var d2 = (tgtGrnM[row, column] - refGrnM[row, column]) * colourGain;
                    var d3 = (tgtBluM[row, column] - refBluM[row, column]) * colourGain;

                    var i1 = 127 + Convert.ToInt32(d1 * maxRGBValue);
                    i1 = Math.Max(0, i1);
                    i1 = Math.Min(maxRGBValue, i1);
                    var i2 = 127 + Convert.ToInt32(d2 * maxRGBValue);
                    i2 = Math.Max(0, i2);
                    i2 = Math.Min(maxRGBValue, i2);
                    var i3 = 127 + Convert.ToInt32(d3 * maxRGBValue);
                    i3 = Math.Max(0, i3);
                    i3 = Math.Min(maxRGBValue, i3);

                    //Color colour = Color.FromRgb(i1, i2, i3);
                    bmp[column, row] = Color.FromRgb((byte)i1, (byte)i2, (byte)i3);
                }
            }

            return(bmp);
        }
        /// <summary>
        /// ONLY Use this concatenation method when you want to concatenate the files for a fixed single day.
        /// The files to be concatenated must be somewhere in the subdirectory structure of the passed list of data directories
        /// Read them into a dictionary
        /// MOST RECENT METHOD TO CONCATENATE Spectral INDEX.CSV FILES - Early September 2015.
        /// It is designed to deal with Yvonne's case where want to concatenate files distributed over arbitrary directories.
        /// It only merges files for the passed fixed date. i.e only 24 hours
        /// </summary>
        public static void DrawSpectralIndexFiles(
            Dictionary <string, double[, ]> dictionary,
            LdSpectrogramConfig sgConfig,
            IndexGenerationData indexGenerationData,
            FileInfo indexPropertiesConfigFileInfo,
            DirectoryInfo opDir,
            SiteDescription siteDescription,
            FileInfo sunriseDataFile          = null,
            List <GapsAndJoins> segmentErrors = null)
        {
            // derive new indices such as sqrt(PMN), NCDI etc -- main reason for this is to view what their distributions look like.
            dictionary = IndexMatrices.AddDerivedIndices(dictionary);

            // Calculate the index distribution statistics and write to a json file. Also save as png image
            if (indexGenerationData.RecordingStartDate != null)
            {
                DateTimeOffset dto        = (DateTimeOffset)indexGenerationData.RecordingStartDate;
                string         dateString = $"{dto.Year}{dto.Month:D2}{dto.Day:D2}";
                string         opFileStem = $"{siteDescription.SiteName}_{dateString}";

                var indexDistributions = IndexDistributions.WriteSpectralIndexDistributionStatistics(dictionary, opDir, opFileStem);

                //SummaryIndexBase[] summaryIndices = null;
                string analysisType = "Towsey.Acoustic";

                Tuple <Image, string>[] tuple = LDSpectrogramRGB.DrawSpectrogramsFromSpectralIndices(
                    opDir, // topLevelDirectories[0], // this should not be required but it is - because things have gotten complicated !
                    opDir,
                    sgConfig,
                    indexPropertiesConfigFileInfo,
                    indexGenerationData,
                    opFileStem,
                    analysisType,
                    dictionary,
                    null, //summaryIndices,
                    indexDistributions,
                    siteDescription,
                    sunriseDataFile,
                    segmentErrors,
                    ImageChrome.With);
            }
        }
        public static double[,] GetTStatisticMatrix(string key, LDSpectrogramRGB cs1, LDSpectrogramRGB cs2)
        {
            double[,] avg1 = cs1.GetSpectrogramMatrix(key);
            if (key.Equals("TEN"))
            {
                avg1 = MatrixTools.SubtractValuesFromOne(avg1);
            }

            double[,] std1 = cs1.GetStandarDeviationMatrix(key);

            double[,] avg2 = cs2.GetSpectrogramMatrix(key);
            if (key.Equals("TEN"))
            {
                avg2 = MatrixTools.SubtractValuesFromOne(avg2);
            }

            double[,] std2 = cs2.GetStandarDeviationMatrix(key);

            double[,] tStatMatrix = GetTStatisticMatrix(avg1, std1, cs1.SampleCount, avg2, std2, cs2.SampleCount);
            return(tStatMatrix);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// This method draws a spectrogram with other useful information attached.
        /// </summary>
        /// <param name="sonogram">of BaseSonogram class.</param>
        /// <param name="events">a list of acoustic events.</param>
        /// <param name="plots">a list of plots relevant to the spectrogram scores.</param>
        /// <param name="hits">not often used - can be null.</param>
        public static Image <Rgb24> GetSonogramPlusCharts(
            BaseSonogram sonogram,
            List <EventCommon> events,
            List <Plot> plots,
            double[,] hits)
        {
            var spectrogram = sonogram.GetImage(doHighlightSubband: false, add1KHzLines: true, doMelScale: false);

            Contract.RequiresNotNull(spectrogram, nameof(spectrogram));

            var height    = spectrogram.Height;
            var width     = spectrogram.Width;
            var frameSize = sonogram.Configuration.WindowSize;
            //var segmentDuration = sonogram.Duration;
            var spectrogramDuration = width * sonogram.FrameStep;

            // init with linear frequency scale and draw freq grid lines on image
            int hertzInterval = 1000;

            if (height < 200)
            {
                hertzInterval = 2000;
            }

            var nyquist   = sonogram.NyquistFrequency;
            var freqScale = new FrequencyScale(nyquist, frameSize, hertzInterval);

            FrequencyScale.DrawFrequencyLinesOnImage(spectrogram, freqScale.GridLineLocations, includeLabels: true);

            // draw event outlines onto spectrogram.
            if (events != null && events.Count > 0)
            {
                foreach (SpectralEvent ev in events)
                {
                    var options = new EventRenderingOptions(new UnitConverters(ev.SegmentStartSeconds, spectrogramDuration, nyquist, width, height));
                    spectrogram.Mutate(x => ev.Draw(x, options));
                }
            }

            // now add in hits to the spectrogram image.
            if (hits != null)
            {
                spectrogram = Image_MultiTrack.OverlayScoresAsRedTransparency(spectrogram, hits);
            }

            int pixelWidth = spectrogram.Width;
            var titleBar   = LDSpectrogramRGB.DrawTitleBarOfGrayScaleSpectrogram("TITLE", pixelWidth);
            var timeTrack  = ImageTrack.DrawTimeTrack(sonogram.Duration, pixelWidth);

            var imageList = new List <Image <Rgb24> >
            {
                titleBar,
                timeTrack,
                spectrogram,
                timeTrack,
            };

            if (plots != null)
            {
                foreach (var plot in plots)
                {
                    // Next line assumes plot data normalised in 0,1
                    var plotImage = plot.DrawAnnotatedPlot(ImageTrack.DefaultHeight);

                    // the following draws same plot without the title.
                    //var plotImage = ImageTrack.DrawScoreArrayTrack(plot.data, plot.threshold, pixelWidth);
                    imageList.Add(plotImage);
                }
            }

            var compositeImage = ImageTools.CombineImagesVertically(imageList);

            return(compositeImage);
        }
Ejemplo n.º 14
0
        public static Image DrawIndexSpectrogramCommon(
            LdSpectrogramConfig config,
            IndexGenerationData indexGenerationData,
            Dictionary <string, IndexProperties> indexProperties,
            TimeSpan startTime,
            TimeSpan endTime,
            TimeSpan dataScale,
            TimeSpan imageScale,
            int imageWidth,
            Dictionary <string, double[, ]> spectra,
            string basename)
        {
            double scalingFactor = Math.Round(imageScale.TotalMilliseconds / dataScale.TotalMilliseconds);

            Contract.Requires(scalingFactor >= 1.0, $"Compression scale `{scalingFactor}`is invalid");

            // calculate data duration from column count of abitrary matrix
            //TimeSpan dataDuration = TimeSpan.FromSeconds(matrix.GetLength(1) * dataScale.TotalSeconds);
            int columnCount = spectra.FirstValue().GetLength(1);

            var startIndex = (int)(startTime.Ticks / dataScale.Ticks);
            var endIndex   = (int)(endTime.Ticks / dataScale.Ticks);

            Contract.Ensures(endIndex <= columnCount);

            // extract subset of target data
            var spectralSelection = new Dictionary <string, double[, ]>();

            foreach (string key in spectra.Keys)
            {
                var matrix   = spectra[key];
                int rowCount = matrix.GetLength(0);

                spectralSelection[key] = MatrixTools.Submatrix(matrix, 0, startIndex, rowCount - 1, endIndex - 1);
                Contract.Ensures(
                    spectralSelection[key].GetLength(1) == (endTime - startTime).Ticks / dataScale.Ticks,
                    "The expected number of frames should be extracted.");
            }

            // compress spectrograms to correct scale
            if (scalingFactor > 1)
            {
                // we add rounding to the compression so that fractional pixels get rendered
                spectralSelection = IndexMatrices.CompressIndexSpectrograms(
                    spectralSelection,
                    imageScale,
                    dataScale,
                    d => Math.Round(d, MidpointRounding.AwayFromZero));
            }
            else
            {
                // this else is unnecessary - completely defensive code
                Contract.Ensures(scalingFactor == 1);
            }

            // check that have not compressed matrices to zero length
            if (spectralSelection.FirstValue().GetLength(0) == 0 || spectralSelection.FirstValue().GetLength(1) == 0)
            {
                throw new InvalidOperationException("Spectral matrices compressed to zero size");
            }

            // DEFINE the DEFAULT colour maps for the false-colour spectrograms
            // Then obtain values from spectrogramDrawingConfig. NOTE: WE REQUIRE LENGTH = 11 chars.
            string colorMap1 = "ACI-ENT-EVN";

            if (config.ColorMap1 != null && config.ColorMap1.Length == 11)
            {
                colorMap1 = config.ColorMap1;
            }

            string colorMap2 = "BGN-PMN-EVN";

            if (config.ColorMap2 != null && config.ColorMap2.Length == 11)
            {
                colorMap2 = config.ColorMap2;
            }

            double backgroundFilterCoeff = indexGenerationData.BackgroundFilterCoeff;

            // double  colourGain = (double?)configuration.ColourGain ?? SpectrogramConstants.COLOUR_GAIN;  // determines colour saturation
            var cs1 = new LDSpectrogramRGB(config, indexGenerationData, colorMap1)
            {
                FileName         = basename,
                BackgroundFilter = backgroundFilterCoeff,
            };

            cs1.SetSpectralIndexProperties(indexProperties); // set the relevant dictionary of index properties
            cs1.LoadSpectrogramDictionary(spectralSelection);

            // set up piecewise linear function to determine colour weights
            var    logResolution   = Math.Log(imageScale.TotalMilliseconds, 2);
            double upperResolution = Math.Log(32768, 2);
            double lowerResolution = Math.Log(256, 2);
            double range           = upperResolution - lowerResolution;
            double blendWeight1;

            if (logResolution >= upperResolution)
            {
                blendWeight1 = 1.0;
            }
            else if (logResolution <= lowerResolution)
            {
                blendWeight1 = 0.0;
            }
            else
            {
                blendWeight1 = (logResolution - lowerResolution) / range;
            }

            double blendWeight2 = 1 - blendWeight1;

            //else if (imageScaleInMsPerPixel > 2000)
            //{
            //    blendWeight1 = 0.7;
            //    blendWeight2 = 0.3;
            //}
            //else if (imageScaleInMsPerPixel > 1000)
            //{
            //    blendWeight1 = 0.3;
            //    blendWeight2 = 0.7;
            //}
            //else if (imageScaleInMsPerPixel > 500)
            //{
            //    // > 0.5 seconds
            //    blendWeight1 = 0.2;
            //    blendWeight2 = 0.8;
            //}
            //else if (imageScaleInMsPerPixel > 300)
            //{
            //    // > 0.5 seconds
            //    blendWeight1 = 0.1;
            //    blendWeight2 = 0.9;
            //}

            var ldfcSpectrogram = cs1.DrawBlendedFalseColourSpectrogram(colorMap1, colorMap2, blendWeight1, blendWeight2);

            if (ldfcSpectrogram == null)
            {
                throw new InvalidOperationException("Null Image returned from DrawBlendedFalseColourSpectrogram");
            }

            return(ldfcSpectrogram);
        }
        /// <summary>
        /// This method compares the acoustic indices derived from two different long duration recordings of the same length.
        /// It takes as input six csv files of acoustic indices in spectrogram columns, three csv files for each of the original recordings to be compared.
        /// The method produces four spectrogram image files:
        /// 1) A triple image. Top:    The spectrogram for index 1, recording 1.
        ///                    Middle: The spectrogram for index 1, recording 2.
        ///                    Bottom: A t-statistic thresholded difference spectrogram for INDEX 1 (derived from recordings 1 and 2).
        /// 2) A triple image. Top:    The spectrogram for index 2, recording 1.
        ///                    Middle: The spectrogram for index 2, recording 2.
        ///                    Bottom: A t-statistic thresholded difference spectrogram for INDEX 2 (derived from recordings 1 and 2).
        /// 3) A triple image. Top:    The spectrogram for index 3, recording 1.
        ///                    Middle: The spectrogram for index 3, recording 2.
        ///                    Bottom: A t-statistic thresholded difference spectrogram for INDEX 3 (derived from recordings 1 and 2).
        /// 4) A double image. Top:    A t-statistic thresholded difference spectrogram (t-statistic is positive).
        ///                    Bottom: A t-statistic thresholded difference spectrogram (t-statistic is negative).
        /// </summary>
        public static void DrawTStatisticThresholdedDifferenceSpectrograms(DirectoryInfo ipdir, FileInfo ipFileName1, FileInfo ipSdFileName1,
                                                                           FileInfo ipFileName2, FileInfo ipSdFileName2,
                                                                           DirectoryInfo opdir)
        {
            string opFileName1 = ipFileName1.Name;
            var    cs1         = new LDSpectrogramRGB(minuteOffset, xScale, sampleRate, frameWidth, colorMap)
            {
                FileName         = opFileName1,
                ColorMode        = colorMap,
                BackgroundFilter = backgroundFilterCoeff,
            };

            string[] keys = colorMap.Split('-');
            cs1.ReadCsvFiles(ipdir, ipFileName1.Name, keys);

            // string imagePath = Path.Combine(opdir.FullName, opFileName1 + ".COLNEG.png");

            string opFileName2 = ipFileName2.Name;
            var    cs2         = new LDSpectrogramRGB(minuteOffset, xScale, sampleRate, frameWidth, colorMap)
            {
                FileName         = opFileName2,
                ColorMode        = colorMap,
                BackgroundFilter = backgroundFilterCoeff,
            };

            cs2.ReadCsvFiles(ipdir, ipFileName2.Name, keys);

            bool allOk       = true;
            int  sampleCount = 30;

            allOk = cs1.ReadStandardDeviationSpectrogramCsvs(ipdir, ipSdFileName1.Name);
            if (!allOk)
            {
                Console.WriteLine("Cannot do t-test comparison because error reading standard deviation file: {0}", ipSdFileName1.Name);
                return;
            }

            cs1.SampleCount = sampleCount;
            allOk           = cs2.ReadStandardDeviationSpectrogramCsvs(ipdir, ipSdFileName2.Name);
            if (!allOk)
            {
                Console.WriteLine("Cannot do t-test comparison because error reading standard deviation file: {0}", ipSdFileName2.Name);
                return;
            }

            cs2.SampleCount = sampleCount;

            string key             = "ACI";
            var    tStatIndexImage = DrawTStatisticSpectrogramsOfSingleIndex(key, cs1, cs2, tStatThreshold);
            string opFileName3     = ipFileName1 + ".tTest." + key + ".png";

            tStatIndexImage.Save(Path.Combine(opdir.FullName, opFileName3));

            key             = "TEN";
            tStatIndexImage = DrawTStatisticSpectrogramsOfSingleIndex(key, cs1, cs2, tStatThreshold);
            opFileName3     = ipFileName1 + ".tTest." + key + ".png";
            tStatIndexImage.Save(Path.Combine(opdir.FullName, opFileName3));

            key             = "CVR";
            tStatIndexImage = DrawTStatisticSpectrogramsOfSingleIndex(key, cs1, cs2, tStatThreshold);
            opFileName3     = ipFileName1 + ".tTest." + key + ".png";
            tStatIndexImage.Save(Path.Combine(opdir.FullName, opFileName3));

            tStatIndexImage = DrawTStatisticSpectrogramsOfMultipleIndices(cs1, cs2, tStatThreshold, ColourGain);
            opFileName3     = ipFileName1 + "-" + ipFileName2 + ".Difference.tTestThreshold.png";
            tStatIndexImage.Save(Path.Combine(opdir.FullName, opFileName3));
        }
        public static Image DrawTStatisticSpectrogramsOfMultipleIndices(LDSpectrogramRGB cs1, LDSpectrogramRGB cs2, double tStatThreshold, double colourGain)
        {
            string[] keys = cs1.ColorMap.Split('-'); //assume both spectorgrams have the same acoustic indices in same order

            double[,] m1 = GetDifferenceSpectrogramDerivedFromSingleTStatistic(keys[0], cs1, cs2, tStatThreshold);
            double[,] m2 = GetDifferenceSpectrogramDerivedFromSingleTStatistic(keys[1], cs1, cs2, tStatThreshold);
            double[,] m3 = GetDifferenceSpectrogramDerivedFromSingleTStatistic(keys[2], cs1, cs2, tStatThreshold);

            int rows = m1.GetLength(0); //number of rows
            int cols = m1.GetLength(1); //number

            var spg1Image   = new Image <Rgb24>(cols, rows);
            var spg2Image   = new Image <Rgb24>(cols, rows);
            int maxRgbValue = 255;

            for (int row = 0; row < rows; row++)
            {
                for (int column = 0; column < cols; column++)
                {
                    var dR = m1[row, column] * colourGain;
                    var dG = m2[row, column] * colourGain;
                    var dB = m3[row, column] * colourGain;

                    byte iR1 = 0;
                    byte iR2 = 0;
                    byte iG1 = 0;
                    byte iG2 = 0;
                    byte iB1 = 0;
                    byte iB2 = 0;

                    var value = Convert.ToByte(Math.Abs(dR) * maxRgbValue);
                    value = (byte)Math.Min(maxRgbValue, value);
                    if (dR > 0.0)
                    {
                        iR1 = value;
                    }
                    else
                    {
                        iR2 = value;
                    }

                    value = Convert.ToByte(Math.Abs(dG) * maxRgbValue);
                    value = (byte)Math.Min(maxRgbValue, value);
                    if (dG > 0.0)
                    {
                        iG1 = value;
                    }
                    else
                    {
                        iG2 = value;
                    }

                    value = Convert.ToByte(Math.Abs(dB) * maxRgbValue);
                    value = (byte)Math.Min(maxRgbValue, value);
                    if (dB > 0.0)
                    {
                        iB1 = value;
                    }
                    else
                    {
                        iB2 = value;
                    }

                    var colour1 = Color.FromRgb(iR1, iG1, iB1);
                    var colour2 = Color.FromRgb(iR2, iG2, iB2);
                    spg1Image[column, row] = colour1;
                    spg2Image[column, row] = colour2;
                }
            }

            var images       = new Image <Rgb24> [2];
            int nyquist      = cs1.SampleRate / 2;
            int herzInterval = 1000;

            string title    = string.Format("DIFFERENCE SPECTROGRAM (thresholded by t-Statistic={2}) where {0} > {1}      (scale:hours x kHz)       (colour: R-G-B={2})", cs1.FileName, cs2.FileName, tStatThreshold);
            var    titleBar = LDSpectrogramRGB.DrawTitleBarOfFalseColourSpectrogram(title, spg1Image.Width);

            images[0] = LDSpectrogramRGB.FrameLDSpectrogram(spg1Image, titleBar, cs1, nyquist, herzInterval);
            title     = string.Format("DIFFERENCE SPECTROGRAM (thresholded by t-Statistic={2}) where {1} > {0}      (scale:hours x kHz)       (colour: R-G-B={2})", cs1.FileName, cs2.FileName, tStatThreshold);
            titleBar  = LDSpectrogramRGB.DrawTitleBarOfFalseColourSpectrogram(title, spg2Image.Width);
            images[1] = LDSpectrogramRGB.FrameLDSpectrogram(spg2Image, titleBar, cs1, nyquist, herzInterval);

            var compositeImage = ImageTools.CombineImagesVertically(images);

            return(compositeImage);
        }
Ejemplo n.º 17
0
        public static void Execute(Arguments arguments)
        {
            if (arguments == null)
            {
                throw new NoDeveloperMethodException();
            }

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

            LoggedConsole.WriteLine("# DRAW LONG DURATION SPECTROGRAMS DERIVED FROM CSV FILES OF SPECTRAL INDICES OBTAINED FROM AN AUDIO RECORDING");
            LoggedConsole.WriteLine(date);
            LoggedConsole.WriteLine("# Spectrogram Config      file: " + arguments.FalseColourSpectrogramConfig);
            LoggedConsole.WriteLine("# Index Properties Config file: " + arguments.IndexPropertiesConfig);
            LoggedConsole.WriteLine();

            (FileInfo indexGenerationDataFile, FileInfo indexDistributionsFile) =
                ZoomParameters.CheckNeededFilesExist(arguments.InputDataDirectory.ToDirectoryInfo());

            var indexGenerationData = Json.Deserialize <IndexGenerationData>(indexGenerationDataFile);

            // spectral distribution statistics is required only when calcualting difference spectrograms.
            Dictionary <string, IndexDistributions.SpectralStats> indexDistributionsData = null;

            if (indexDistributionsFile != null && indexDistributionsFile.Exists)
            {
                indexDistributionsData = IndexDistributions.Deserialize(indexDistributionsFile);
            }

            // this config can be found in IndexGenerationData. If config argument not specified, simply take it from icd file
            LdSpectrogramConfig config;

            if (arguments.FalseColourSpectrogramConfig == null)
            {
                config = indexGenerationData.LongDurationSpectrogramConfig;
            }
            else
            {
                config = LdSpectrogramConfig.ReadYamlToConfig(arguments.FalseColourSpectrogramConfig.ToFileInfo());
            }

            FilenameHelpers.ParseAnalysisFileName(indexGenerationDataFile, out var originalBaseName, out var _, out var _);

            // CHECK FOR ERROR SEGMENTS - get zero signal array
            var input   = arguments.InputDataDirectory.ToDirectoryInfo();
            var csvFile = new FileInfo(Path.Combine(input.FullName, originalBaseName + "__Towsey.Acoustic.Indices.csv"));

            //Dictionary<string, double[]> summaryIndices = CsvTools.ReadCSVFile2Dictionary(csvFile.FullName);
            //var summaryIndices = Csv.ReadFromCsv<Dictionary<string, double[]>>(csvFile);
            var summaryIndices = Csv.ReadFromCsv <SummaryIndexValues>(csvFile);

            var indexErrors = GapsAndJoins.DataIntegrityCheckForZeroSignal(summaryIndices);

            //config.IndexCalculationDuration = TimeSpan.FromSeconds(1.0);
            //config.XAxisTicInterval = TimeSpan.FromSeconds(60.0);
            //config.IndexCalculationDuration = TimeSpan.FromSeconds(60.0);
            //config.XAxisTicInterval = TimeSpan.FromSeconds(3600.0);
            LDSpectrogramRGB.DrawSpectrogramsFromSpectralIndices(
                inputDirectory: input,
                outputDirectory: arguments.OutputDirectory.ToDirectoryInfo(),
                ldSpectrogramConfig: config,
                indexPropertiesConfigPath: arguments.IndexPropertiesConfig.ToFileInfo(),
                indexGenerationData: indexGenerationData,
                basename: originalBaseName,
                analysisType: AcousticIndices.TowseyAcoustic,
                indexSpectrograms: null,
                indexStatistics: indexDistributionsData,
                segmentErrors: indexErrors,
                imageChrome: false.ToImageChrome());

            Log.Success("Draw Long Duration Spectrograms complete!");
        }
Ejemplo n.º 18
0
        } // method DrawRidgeSpectrograms()

        public static Image DrawRidgeSpectrograms(DirectoryInfo inputDirectory, FileInfo ipConfig, string fileStem, double scale, Dictionary <string, double[, ]> spectra = null)
        {
            string analysisType = AcousticIndices.TowseyAcoustic;

            //double backgroundFilter = 0.0; // 0.0 means small values are removed.
            double backgroundFilter = 0.75;  // 0.75 means small values are accentuated.
            var    dataScale        = TimeSpan.FromSeconds(scale);

            Dictionary <string, IndexProperties> indexProperties = IndexProperties.GetIndexProperties(ipConfig);

            string[] keys = SpectralPeakTracks.GetDefaultRidgeKeys();

            // read the csv files of the indices in keys array
            if (spectra == null)
            {
                //C:\SensorNetworks\Output\BIRD50\Training\ID0001\Towsey.Acoustic\ID0001__Towsey.Acoustic.ACI
                spectra = IndexMatrices.ReadSpectralIndices(inputDirectory, fileStem, analysisType, keys);
            }

            var cs1 = new LDSpectrogramRGB(minuteOffset: TimeSpan.Zero, xScale: dataScale, sampleRate: 22050, frameWidth: 512, colorMap: null)
            {
                FileName                 = fileStem,
                BackgroundFilter         = backgroundFilter,
                IndexCalculationDuration = dataScale,
            };

            // set the relevant dictionary of index properties
            cs1.SetSpectralIndexProperties(indexProperties);
            cs1.SpectrogramMatrices = spectra;
            if (cs1.GetCountOfSpectrogramMatrices() == 0)
            {
                LoggedConsole.WriteLine("WARNING:  " + fileStem + ":   No spectrogram matrices in the dictionary. Spectrogram files do not exist?");
                return(null);
            }
            else if (cs1.GetCountOfSpectrogramMatrices() < keys.Length)
            {
                LoggedConsole.WriteLine("WARNING:  " + fileStem + ":   Missing indices in the dictionary. Some files do not exist?");
                return(null);
            }

            var stringFont = Drawing.Tahoma8;

            // constants for labels
            Color[]       color       = { Color.Blue, Color.Green, Color.Red, Color.Orange, Color.Purple };
            int           labelYvalue = 3;
            int           labelIndex  = 0;
            Image <Rgb24> ridges      = null;

            foreach (string key in keys)
            {
                Image <Rgb24> greyScaleImage = (Image <Rgb24>)cs1.DrawGreyscaleSpectrogramOfIndex(key);
                var           pixelWidth     = greyScaleImage.Width;

                int height = greyScaleImage.Height;
                ridges.Mutate(g2 =>
                {
                    if (ridges == null)
                    {
                        ridges = new Image <Rgb24>(pixelWidth, height);
                        g2.Clear(Color.White);
                    }

                    g2.DrawText(key, stringFont, color[labelIndex], new PointF(0, labelYvalue));
                });
                labelYvalue += 10;

                //g1.DrawLine(new Pen(Color.Black, 1), 0, 0, width, 0);//draw upper boundary
                //g1.DrawLine(new Pen(Color.Black, 1), 0, 1, width, 1);//draw upper boundary

                // transfer greyscale image to colour image
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < pixelWidth; x++)
                    {
                        var col = greyScaleImage[x, y];
                        if (col.G < 150)
                        {
                            ridges[x, y] = color[labelIndex];
                        }
                    }
                }

                labelIndex += 1;
            } //foreach key

            return(ridges);
        } // method DrawRidgeSpectrograms()
Ejemplo n.º 19
0
        /// <summary>
        /// This method compares the acoustic indices derived from two different long duration recordings of the same length.
        ///     It takes as input any number of csv files of acoustic indices in spectrogram columns.
        ///     Typically there will be at least three indices csv files for each of the original recordings to be compared.
        ///     The method produces four spectrogram image files:
        ///     1) A negative false-color spectrogram derived from the indices of recording 1.
        ///     2) A negative false-color spectrogram derived from the indices of recording 2.
        ///     3) A spectrogram of euclidean distances between the two input files.
        ///     4) The above three spectrograms combined in one image.
        /// </summary>
        public static void DrawDistanceSpectrogram(
            DirectoryInfo inputDirectory,
            FileInfo inputFileName1,
            FileInfo inputFileName2,
            DirectoryInfo outputDirectory)
        {
            // PARAMETERS
            string outputFileName1 = inputFileName1.Name;
            var    cs1             = new LDSpectrogramRGB(minuteOffset, xScale, sampleRate, frameWidth, colorMap);

            cs1.ColorMode        = colorMap;
            cs1.BackgroundFilter = backgroundFilterCoeff;
            string[] keys = colorMap.Split('-');
            cs1.ReadCsvFiles(inputDirectory, inputFileName1.Name, keys);
            double blueEnhanceParameter = 0.0;

            cs1.DrawNegativeFalseColorSpectrogram(outputDirectory, outputFileName1, blueEnhanceParameter);
            string imagePath = Path.Combine(outputDirectory.FullName, outputFileName1 + ".COLNEG.png");
            var    spg1Image = Image.Load <Rgb24>(imagePath);

            if (spg1Image == null)
            {
                LoggedConsole.WriteLine("SPECTROGRAM IMAGE DOES NOT EXIST: {0}", imagePath);
                return;
            }

            int nyquist       = cs1.SampleRate / 2;
            int hertzInterval = 1000;

            string title =
                $"FALSE COLOUR SPECTROGRAM: {inputFileName1}.      (scale:hours x kHz)       (colour: R-G-B={cs1.ColorMode})";
            var titleBar = LDSpectrogramRGB.DrawTitleBarOfFalseColourSpectrogram(title, spg1Image.Width);

            spg1Image = LDSpectrogramRGB.FrameLDSpectrogram(
                spg1Image,
                titleBar,
                cs1,
                nyquist,
                hertzInterval);

            string outputFileName2 = inputFileName2.Name;
            var    cs2             = new LDSpectrogramRGB(minuteOffset, xScale, sampleRate, frameWidth, colorMap)
            {
                ColorMode        = colorMap,
                BackgroundFilter = backgroundFilterCoeff,
            };

            cs2.ReadCsvFiles(inputDirectory, inputFileName2.Name, keys);

            // cs2.DrawGreyScaleSpectrograms(opdir, opFileName2);
            cs2.DrawNegativeFalseColorSpectrogram(outputDirectory, outputFileName2, blueEnhanceParameter);
            imagePath = Path.Combine(outputDirectory.FullName, outputFileName2 + ".COLNEG.png");
            var spg2Image = Image.Load <Rgb24>(imagePath);

            if (spg2Image == null)
            {
                LoggedConsole.WriteLine("SPECTROGRAM IMAGE DOES NOT EXIST: {0}", imagePath);
                return;
            }

            title =
                $"FALSE COLOUR SPECTROGRAM: {inputFileName2}.      (scale:hours x kHz)       (colour: R-G-B={cs2.ColorMode})";
            titleBar  = LDSpectrogramRGB.DrawTitleBarOfFalseColourSpectrogram(title, spg2Image.Width);
            spg2Image = LDSpectrogramRGB.FrameLDSpectrogram(
                spg2Image,
                titleBar,
                cs1,
                nyquist,
                hertzInterval);

            string outputFileName4 = inputFileName1 + ".EuclideanDistance.png";
            var    deltaSp         = DrawDistanceSpectrogram(cs1, cs2);

            Color[] colorArray = LDSpectrogramRGB.ColourChart2Array(GetDifferenceColourChart());
            titleBar = DrawTitleBarOfEuclidianDistanceSpectrogram(
                inputFileName1.Name,
                inputFileName2.Name,
                colorArray,
                deltaSp.Width,
                SpectrogramConstants.HEIGHT_OF_TITLE_BAR);
            deltaSp = LDSpectrogramRGB.FrameLDSpectrogram(deltaSp, titleBar, cs2, nyquist, hertzInterval);
            deltaSp.Save(Path.Combine(outputDirectory.FullName, outputFileName4));

            string outputFileName5 = inputFileName1 + ".2SpectrogramsAndDistance.png";

            var combinedImage = ImageTools.CombineImagesVertically(spg1Image, spg2Image, deltaSp);

            combinedImage.Save(Path.Combine(outputDirectory.FullName, outputFileName5));
        }
        public static Image <Rgb24>[] DrawPositiveDifferenceSpectrograms(LDSpectrogramRGB target, LDSpectrogramRGB reference, double colourGain)
        {
            string[] keys = target.ColorMap.Split('-');

            double[,] tgtRedM = target.GetNormalisedSpectrogramMatrix(keys[0]);
            double[,] tgtGrnM = target.GetNormalisedSpectrogramMatrix(keys[1]);
            double[,] tgtBluM = target.GetNormalisedSpectrogramMatrix(keys[2]);

            double[,] refRedM = reference.GetNormalisedSpectrogramMatrix(keys[0]);
            double[,] refGrnM = reference.GetNormalisedSpectrogramMatrix(keys[1]);
            double[,] refBluM = reference.GetNormalisedSpectrogramMatrix(keys[2]);

            // assume all matricies are normalised and of the same dimensions
            int rows = tgtRedM.GetLength(0); //number of rows
            int cols = tgtRedM.GetLength(1); //number

            var spg1Image   = new Image <Rgb24>(cols, rows);
            var spg2Image   = new Image <Rgb24>(cols, rows);
            int maxRgbValue = 255;

            for (int row = 0; row < rows; row++)
            {
                for (int column = 0; column < cols; column++)
                {
                    var dR = (tgtRedM[row, column] - refRedM[row, column]) * colourGain;
                    var dG = (tgtGrnM[row, column] - refGrnM[row, column]) * colourGain;
                    var dB = (tgtBluM[row, column] - refBluM[row, column]) * colourGain;

                    var iR1 = 0;
                    var iR2 = 0;
                    var iG1 = 0;
                    var iG2 = 0;
                    var iB1 = 0;
                    var iB2 = 0;

                    var value = Convert.ToInt32(Math.Abs(dR) * maxRgbValue);
                    value = Math.Min(maxRgbValue, value);
                    if (dR > 0.0)
                    {
                        iR1 = value;
                    }
                    else
                    {
                        iR2 = value;
                    }

                    value = Convert.ToInt32(Math.Abs(dG) * maxRgbValue);
                    value = Math.Min(maxRgbValue, value);
                    if (dG > 0.0)
                    {
                        iG1 = value;
                    }
                    else
                    {
                        iG2 = value;
                    }

                    value = Convert.ToInt32(Math.Abs(dB) * maxRgbValue);
                    value = Math.Min(maxRgbValue, value);
                    if (dB > 0.0)
                    {
                        iB1 = value;
                    }
                    else
                    {
                        iB2 = value;
                    }

                    var colour1 = Color.FromRgb((byte)iR1, (byte)iG1, (byte)iB1);
                    var colour2 = Color.FromRgb((byte)iR2, (byte)iG2, (byte)iB2);
                    spg1Image[column, row] = colour1;
                    spg2Image[column, row] = colour2;
                }
            }

            return(new[] { spg1Image, spg2Image });
        }
Ejemplo n.º 21
0
        public static Image <Rgb24> DrawDistanceSpectrogram(LDSpectrogramRGB cs1, LDSpectrogramRGB cs2)
        {
            string[] keys = cs1.ColorMap.Split('-');

            string key = keys[0];

            double[,] m1Red = cs1.GetNormalisedSpectrogramMatrix(key);
            IndexDistributions.SpectralStats stats = IndexDistributions.GetModeAndOneTailedStandardDeviation(m1Red);
            cs1.IndexStats.Add(key, stats);
            m1Red = MatrixTools.Matrix2ZScores(m1Red, stats.Mode, stats.StandardDeviation);

            ////LoggedConsole.WriteLine("1.{0}: Min={1:f2}   Max={2:f2}    Mode={3:f2}+/-{4:f3} (SD=One-tailed)", key, dict["min"], dict["max"], dict["mode"], dict["sd"]);
            key             = keys[1];
            double[,] m1Grn = cs1.GetNormalisedSpectrogramMatrix(key);
            stats           = IndexDistributions.GetModeAndOneTailedStandardDeviation(m1Grn);
            cs1.IndexStats.Add(key, stats);
            m1Grn = MatrixTools.Matrix2ZScores(m1Grn, stats.Mode, stats.StandardDeviation);

            ////LoggedConsole.WriteLine("1.{0}: Min={1:f2}   Max={2:f2}    Mode={3:f2}+/-{4:f3} (SD=One-tailed)", key, dict["min"], dict["max"], dict["mode"], dict["sd"]);
            key             = keys[2];
            double[,] m1Blu = cs1.GetNormalisedSpectrogramMatrix(key);
            stats           = IndexDistributions.GetModeAndOneTailedStandardDeviation(m1Blu);
            cs1.IndexStats.Add(key, stats);
            m1Blu = MatrixTools.Matrix2ZScores(m1Blu, stats.Mode, stats.StandardDeviation);

            ////LoggedConsole.WriteLine("1.{0}: Min={1:f2}   Max={2:f2}    Mode={3:f2}+/-{4:f3} (SD=One-tailed)", key, dict["min"], dict["max"], dict["mode"], dict["sd"]);
            key             = keys[0];
            double[,] m2Red = cs2.GetNormalisedSpectrogramMatrix(key);
            stats           = IndexDistributions.GetModeAndOneTailedStandardDeviation(m2Red);
            cs2.IndexStats.Add(key, stats);
            m2Red = MatrixTools.Matrix2ZScores(m2Red, stats.Mode, stats.StandardDeviation);

            ////LoggedConsole.WriteLine("2.{0}: Min={1:f2}   Max={2:f2}    Mode={3:f2}+/-{4:f3} (SD=One-tailed)", key, dict["min"], dict["max"], dict["mode"], dict["sd"]);
            key             = keys[1];
            double[,] m2Grn = cs2.GetNormalisedSpectrogramMatrix(key);
            stats           = IndexDistributions.GetModeAndOneTailedStandardDeviation(m2Grn);
            cs2.IndexStats.Add(key, stats);
            m2Grn = MatrixTools.Matrix2ZScores(m2Grn, stats.Mode, stats.StandardDeviation);

            ////LoggedConsole.WriteLine("2.{0}: Min={1:f2}   Max={2:f2}    Mode={3:f2}+/-{4:f3} (SD=One-tailed)", key, dict["min"], dict["max"], dict["mode"], dict["sd"]);
            key             = keys[2];
            double[,] m2Blu = cs2.GetNormalisedSpectrogramMatrix(key);
            stats           = IndexDistributions.GetModeAndOneTailedStandardDeviation(m2Blu);
            cs2.IndexStats.Add(key, stats);
            m2Blu = MatrixTools.Matrix2ZScores(m2Blu, stats.Mode, stats.StandardDeviation);

            ////LoggedConsole.WriteLine("2.{0}: Min={1:f2}   Max={2:f2}    Mode={3:f2}+/-{4:f3} (SD=One-tailed)", key, dict["min"], dict["max"], dict["mode"], dict["sd"]);
            var v1 = new double[3];

            double[] mode1 =
            {
                cs1.IndexStats[keys[0]].Mode, cs1.IndexStats[keys[1]].Mode,
                cs1.IndexStats[keys[2]].Mode,
            };
            double[] stDv1 =
            {
                cs1.IndexStats[keys[0]].StandardDeviation, cs1.IndexStats[keys[1]].StandardDeviation,
                cs1.IndexStats[keys[2]].StandardDeviation,
            };
            LoggedConsole.WriteLine(
                "1: avACI={0:f3}+/-{1:f3};   avTEN={2:f3}+/-{3:f3};   avCVR={4:f3}+/-{5:f3}",
                mode1[0],
                stDv1[0],
                mode1[1],
                stDv1[1],
                mode1[2],
                stDv1[2]);

            var v2 = new double[3];

            double[] mode2 =
            {
                cs2.IndexStats[keys[0]].Mode, cs2.IndexStats[keys[1]].Mode,
                cs2.IndexStats[keys[2]].Mode,
            };
            double[] stDv2 =
            {
                cs2.IndexStats[keys[0]].StandardDeviation, cs2.IndexStats[keys[1]].StandardDeviation,
                cs2.IndexStats[keys[2]].StandardDeviation,
            };
            LoggedConsole.WriteLine(
                "2: avACI={0:f3}+/-{1:f3};   avTEN={2:f3}+/-{3:f3};   avCVR={4:f3}+/-{5:f3}",
                mode2[0],
                stDv2[0],
                mode2[1],
                stDv2[1],
                mode2[2],
                stDv2[2]);

            // assume all matrices are normalised and of the same dimensions
            int rows      = m1Red.GetLength(0); // number of rows
            int cols      = m1Red.GetLength(1); // number
            var d12Matrix = new double[rows, cols];
            var d11Matrix = new double[rows, cols];
            var d22Matrix = new double[rows, cols];

            for (int row = 0; row < rows; row++)
            {
                for (int col = 0; col < cols; col++)
                {
                    v1[0] = m1Red[row, col];
                    v1[1] = m1Grn[row, col];
                    v1[2] = m1Blu[row, col];

                    v2[0] = m2Red[row, col];
                    v2[1] = m2Grn[row, col];
                    v2[2] = m2Blu[row, col];

                    d12Matrix[row, col] = DataTools.EuclideanDistance(v1, v2);
                    d11Matrix[row, col] = (v1[0] + v1[1] + v1[2]) / 3; // get average of the normalised values
                    d22Matrix[row, col] = (v2[0] + v2[1] + v2[2]) / 3;

                    // following lines are for debugging purposes
                    // if ((row == 150) && (col == 1100))
                    // {
                    // LoggedConsole.WriteLine("V1={0:f3}, {1:f3}, {2:f3}", v1[0], v1[1], v1[2]);
                    // LoggedConsole.WriteLine("V2={0:f3}, {1:f3}, {2:f3}", v2[0], v2[1], v2[2]);
                    // LoggedConsole.WriteLine("EDist12={0:f4};   ED11={1:f4};   ED22={2:f4}", d12Matrix[row, col], d11Matrix[row, col], d22Matrix[row, col]);
                    // }
                }
            }

            double[] array = DataTools.Matrix2Array(d12Matrix);
            NormalDist.AverageAndSD(array, out var avDist, out var sdDist);
            for (int row = 0; row < rows; row++)
            {
                for (int col = 0; col < cols; col++)
                {
                    d12Matrix[row, col] = (d12Matrix[row, col] - avDist) / sdDist;
                }
            }

            double zScore;
            Dictionary <string, Color> colourChart = GetDifferenceColourChart();
            Color colour;

            var bmp = new Image <Rgb24>(cols, rows);

            for (int row = 0; row < rows; row++)
            {
                for (int col = 0; col < cols; col++)
                {
                    zScore = d12Matrix[row, col];

                    if (d11Matrix[row, col] >= d22Matrix[row, col])
                    {
                        if (zScore > 3.08)
                        {
                            colour = colourChart["+99.9%"];
                        }

                        // 99.9% conf
                        else
                        {
                            if (zScore > 2.33)
                            {
                                colour = colourChart["+99.0%"];
                            }

                            // 99.0% conf
                            else
                            {
                                if (zScore > 1.65)
                                {
                                    colour = colourChart["+95.0%"];
                                }

                                // 95% conf
                                else
                                {
                                    if (zScore < 0.0)
                                    {
                                        colour = colourChart["NoValue"];
                                    }
                                    else
                                    {
                                        // v = Convert.ToInt32(zScore * MaxRGBValue);
                                        // colour = Color.FromRgb(v, 0, v);
                                        colour = colourChart["+NotSig"];
                                    }
                                }
                            }
                        }

                        // if() else
                        bmp[col, row] = colour;
                    }
                    else
                    {
                        if (zScore > 3.08)
                        {
                            colour = colourChart["-99.9%"];
                        }

                        // 99.9% conf
                        else
                        {
                            if (zScore > 2.33)
                            {
                                colour = colourChart["-99.0%"];
                            }

                            // 99.0% conf
                            else
                            {
                                if (zScore > 1.65)
                                {
                                    colour = colourChart["-95.0%"];
                                }

                                // 95% conf
                                else
                                {
                                    if (zScore < 0.0)
                                    {
                                        colour = colourChart["NoValue"];
                                    }
                                    else
                                    {
                                        // v = Convert.ToInt32(zScore * MaxRGBValue);
                                        // if()
                                        // colour = Color.FromRgb(0, v, v);
                                        colour = colourChart["-NotSig"];
                                    }
                                }
                            }
                        }

                        // if() else
                        bmp[col, row] = colour;
                    }
                }

                // all rows
            }

            // all rows

            return(bmp);
        }
Ejemplo n.º 22
0
        public void TestAnalyzeSr64000Recording()
        {
            int    sampleRate = 64000;
            double duration   = 420; // signal duration in seconds = 7 minutes

            int[]  harmonics     = { 500, 1000, 2000, 4000, 8000 };
            var    recording     = DspFilters.GenerateTestRecording(sampleRate, duration, harmonics, WaveType.Cosine);
            string recordingName = "TemporaryRecording2";
            var    recordingPath = this.outputDirectory.CombineFile(recordingName + ".wav");

            WavWriter.WriteWavFileViaFfmpeg(recordingPath, recording.WavReader);

            var fst       = FreqScaleType.Linear125Octaves7Tones28Nyquist32000;
            var freqScale = new FrequencyScale(fst);

            /*
             * // draw the signal as spectrogram just for debugging purposes
             * // but can only draw a two minute spectrogram when sr=64000 - change duration above.
             * duration = 120; // if drawing sonogram, then set signal duration = 2 minutes
             * var sonogram = OctaveFreqScale.ConvertRecordingToOctaveScaleSonogram(recording, fst);
             * var sonogramImage = sonogram.GetImageFullyAnnotated(sonogram.GetImage(), "SPECTROGRAM", freqScale.GridLineLocations);
             * var outputImagePath = this.outputDirectory.CombineFile("SignalSpectrogram_OctaveFreqScale.png");
             * sonogramImage.Save(outputImagePath.FullName);
             */

            // Now need to rewrite the config file with new parameter settings
            var configPath = PathHelper.ResolveConfigFile("Towsey.Acoustic.yml");

            // Convert the Config config to IndexCalculateConfig class and merge in the unnecesary parameters.
            //Config configuration = Yaml.Deserialise(configPath);
            //IndexCalculateConfig config = IndexCalculateConfig.GetConfig(configuration, false);

            // because of difficulties in dealing with Config config files, just edit the text file!!!!!
            var configLines = File.ReadAllLines(configPath.FullName);

            configLines[configLines.IndexOf(x => x.StartsWith("IndexCalculationDuration: "))] = "IndexCalculationDuration: 15.0";

            //configLines[configLines.IndexOf(x => x.StartsWith("BgNoiseBuffer: "))] = "BgNoiseBuffer: 5.0";
            configLines[configLines.IndexOf(x => x.StartsWith("FrequencyScale: Linear"))] = "FrequencyScale: " + fst;

            // the is the only octave scale currently functioning for IndexCalculate class
            configLines[configLines.IndexOf(x => x.StartsWith("FrameLength"))]    = $"FrameLength: {freqScale.WindowSize}";
            configLines[configLines.IndexOf(x => x.StartsWith("ResampleRate: "))] = "ResampleRate: 64000";

            // write the edited Config file to temporary output directory
            var newConfigPath = this.outputDirectory.CombineFile("Towsey.Acoustic.yml");

            File.WriteAllLines(newConfigPath.FullName, configLines);

            PathHelper.ResolveConfigFile("IndexPropertiesConfig.yml").CopyTo(this.outputDirectory.CombineFile("IndexPropertiesConfig.yml").FullName);

            var arguments = new AnalyseLongRecording.Arguments
            {
                Source        = recordingPath,
                Config        = newConfigPath.FullName,
                Output        = this.outputDirectory,
                MixDownToMono = true,
                Parallel      = !Debugger.IsAttached,
            };

            AnalyseLongRecording.Execute(arguments);

            var resultsDirectory = this.outputDirectory.Combine("Towsey.Acoustic");
            var listOfFiles      = resultsDirectory.EnumerateFiles().ToArray();

            Assert.AreEqual(19, listOfFiles.Length);

            var csvCount = listOfFiles.Count(f => f.Name.EndsWith(".csv"));

            Assert.AreEqual(15, csvCount);

            var jsonCount = listOfFiles.Count(f => f.Name.EndsWith(".json"));

            Assert.AreEqual(2, jsonCount);

            var pngCount = listOfFiles.Count(f => f.Name.EndsWith(".png"));

            Assert.AreEqual(2, pngCount);

            var bgnFile = resultsDirectory.CombineFile(recordingName + "__Towsey.Acoustic.BGN.csv");

            double[,] actualBgn = Csv.ReadMatrixFromCsv <double>(bgnFile, TwoDimensionalArray.None);

            var expectedSpectrumFile = PathHelper.ResolveAsset("LongDuration", "BgnMatrix.OctaveScale.csv");

            // uncomment the following line when first produce the array
            // bgnFile.CopyTo(expectedSpectrumFile.FullName);

            // compare actual BGN file with expected file.
            var expectedBgn = Csv.ReadMatrixFromCsv <double>(expectedSpectrumFile, TwoDimensionalArray.None);

            CollectionAssert.That.AreEqual(expectedBgn, actualBgn, 0.000_000_001);

            var array = MatrixTools.GetRow(actualBgn, 0);

            Assert.AreEqual(28, actualBgn.RowLength());
            Assert.AreEqual(256, array.Length);

            // draw array just to check peaks are in correct places - just for debugging purposes
            var ldsBgnSpectrumFile = this.outputDirectory.CombineFile("Spectrum2.png");

            GraphsAndCharts.DrawGraph(array, "LD BGN SPECTRUM Octave", ldsBgnSpectrumFile);

            // ##########################################
            // SECOND part of test is to create the LD spectrograms because they are not created when IndexCalcDuration < 60 seconds
            // first read in the index generation data
            var icdPath         = resultsDirectory.CombineFile(recordingName + "__IndexGenerationData.json");
            var indexConfigData = Json.Deserialize <IndexGenerationData>(icdPath);

            var indexPropertiesConfig = PathHelper.ResolveConfigFile("IndexPropertiesConfig.yml");

            var ldSpectrogramConfigFile = PathHelper.ResolveConfigFile("SpectrogramFalseColourConfig.yml");
            var ldSpectrogramConfig     = LdSpectrogramConfig.ReadYamlToConfig(ldSpectrogramConfigFile);

            ldSpectrogramConfig.FreqScale = fst.ToString();

            // finally read in the dictionary of spectra
            string analysisType        = "Towsey.Acoustic";
            var    keys                = LDSpectrogramRGB.GetArrayOfAvailableKeys();
            var    dictionaryOfSpectra = IndexMatrices.ReadSpectralIndices(resultsDirectory, recordingName, analysisType, keys);

            LDSpectrogramRGB.DrawSpectrogramsFromSpectralIndices(
                inputDirectory: resultsDirectory,
                outputDirectory: resultsDirectory,
                ldSpectrogramConfig: ldSpectrogramConfig,
                indexPropertiesConfigPath: indexPropertiesConfig,
                indexGenerationData: indexConfigData,
                basename: recordingName,
                analysisType: analysisType,
                indexSpectrograms: dictionaryOfSpectra);

            // test number of images - should now be 23
            listOfFiles = resultsDirectory.EnumerateFiles().ToArray();
            pngCount    = listOfFiles.Count(f => f.Name.EndsWith(".png"));
            Assert.AreEqual(22, pngCount);

            var twoMapsImagePath = resultsDirectory.CombineFile(recordingName + "__2Maps.png");
            var twoMapsImage     = Image.Load <Rgb24>(twoMapsImagePath.FullName);

            // image is (7*4) * 652
            Assert.AreEqual(28, twoMapsImage.Width);
            Assert.AreEqual(652, twoMapsImage.Height);
        }
Ejemplo n.º 23
0
        } // method DrawAggregatedSpectrograms()

        public static Image <Rgb24> DrawGrayScaleSpectrograms(Arguments arguments, string fileStem, TimeSpan dataScale, Dictionary <string, double[, ]> spectra = null)
        {
            // default values
            int sampleRate = 22050;
            int frameWidth = 512;

            //double backgroundFilter = 0.0; // 0.0 means small values are removed.
            double backgroundFilter = 0.75;  // 0.75 means small values are accentuated.
            string analysisType     = AcousticIndices.TowseyAcoustic;

            string[] keys           = LDSpectrogramRGB.GetArrayOfAvailableKeys();
            var      inputDirectory = arguments.InputDataDirectory;
            Dictionary <string, IndexProperties> indexProperties = IndexProperties.GetIndexProperties(arguments.IndexPropertiesConfig.ToFileInfo());

            if (spectra == null)
            {
                spectra = IndexMatrices.ReadSpectralIndices(inputDirectory.ToDirectoryInfo(), fileStem, analysisType, keys);
            }

            // note: the spectra are oriented as per visual orientation, i.e. xAxis = time frames
            //int frameCount = spectra[keys[0]].GetLength(1);
            var cs1 = new LDSpectrogramRGB(minuteOffset: TimeSpan.Zero, xScale: dataScale, sampleRate: sampleRate, frameWidth: frameWidth, colorMap: null)
            {
                FileName                 = fileStem,
                BackgroundFilter         = backgroundFilter,
                IndexCalculationDuration = dataScale,
            };

            cs1.SetSpectralIndexProperties(indexProperties); // set the relevant dictionary of index properties
            cs1.SpectrogramMatrices = spectra;
            if (cs1.GetCountOfSpectrogramMatrices() == 0)
            {
                LoggedConsole.WriteLine("WARNING:  " + fileStem + ":   No spectrogram matrices in the dictionary. Spectrogram files do not exist?");
                return(null);
            }

            var list       = new List <Image <Rgb24> >();
            var stringFont = Drawing.Arial14;

            foreach (string key in keys)
            {
                var image = cs1.DrawGreyscaleSpectrogramOfIndex(key);

                int width  = 70;
                int height = image.Height;
                var label  = new Image <Rgb24>(width, height);
                label.Mutate(g1 =>
                {
                    g1.Clear(Color.Gray);
                    g1.DrawText(key, stringFont, Color.Black, new PointF(4, 30));
                    g1.DrawLine(new Pen(Color.Black, 1), 0, 0, width, 0); //draw upper boundary
                    g1.DrawLine(new Pen(Color.Black, 1), 0, 1, width, 1); //draw upper boundary
                });
                var imagearray    = new[] { label, image };
                var labelledImage = ImageTools.CombineImagesInLine(imagearray);
                list.Add(labelledImage);
            } //foreach key

            var combinedImage = ImageTools.CombineImagesVertically(list);

            return(combinedImage);
        } // method DrawGrayScaleSpectrograms()
Ejemplo n.º 24
0
        } // method DrawAggregatedSpectrograms()

        public static Image DrawGrayScaleSpectrograms(Arguments arguments, string fileStem, TimeSpan dataScale, Dictionary <string, double[, ]> spectra = null)
        {
            int sampleRate = 22050;
            int frameWidth = 512;

            //double backgroundFilter = 0.0; // 0.0 means small values are removed.
            double backgroundFilter = 0.75;  // 0.75 means small values are accentuated.
            string analysisType     = AcousticIndices.TowseyAcoustic;

            string[] keys = LDSpectrogramRGB.GetArrayOfAvailableKeys();

            //LoggedConsole.WriteLine("# Spectrogram Config      file: " + arguments.SpectrogramConfigPath);
            //LoggedConsole.WriteLine("# Index Properties Config file: " + arguments.IndexPropertiesConfig);
            var inputDirectory = arguments.InputDataDirectory;
            Dictionary <string, IndexProperties> indexProperties = IndexProperties.GetIndexProperties(arguments.IndexPropertiesConfig.ToFileInfo());

            if (spectra == null)
            {
                //C:\SensorNetworks\Output\BIRD50\Training\ID0001\Towsey.Acoustic\ID0001__Towsey.Acoustic.ACI
                spectra = IndexMatrices.ReadSpectralIndices(inputDirectory.ToDirectoryInfo(), fileStem, analysisType, keys);
            }

            // note: the spectra are oriented as per visual orientation, i.e. xAxis = time frames
            //int frameCount = spectra[keys[0]].GetLength(1);
            var cs1 = new LDSpectrogramRGB(minuteOffset: TimeSpan.Zero, xScale: dataScale, sampleRate: sampleRate, frameWidth: frameWidth, colourMap: null)
            {
                FileName                 = fileStem,
                BackgroundFilter         = backgroundFilter,
                IndexCalculationDuration = dataScale,
            };

            cs1.SetSpectralIndexProperties(indexProperties); // set the relevant dictionary of index properties
            cs1.SpectrogramMatrices = spectra;
            if (cs1.GetCountOfSpectrogramMatrices() == 0)
            {
                LoggedConsole.WriteLine("WARNING:  " + fileStem + ":   No spectrogram matrices in the dictionary. Spectrogram files do not exist?");
                return(null);
            }

            List <Image> list       = new List <Image>();
            Font         stringFont = new Font("Arial", 14);

            foreach (string key in keys)
            {
                var image = cs1.DrawGreyscaleSpectrogramOfIndex(key);

                int width  = 70;
                int height = image.Height;
                var label  = new Bitmap(width, height);
                var g1     = Graphics.FromImage(label);
                g1.Clear(Color.Gray);
                g1.DrawString(key, stringFont, Brushes.Black, new PointF(4, 30));
                g1.DrawLine(new Pen(Color.Black), 0, 0, width, 0); //draw upper boundary
                g1.DrawLine(new Pen(Color.Black), 0, 1, width, 1); //draw upper boundary

                Image[] imagearray    = { label, image };
                var     labelledImage = ImageTools.CombineImagesInLine(imagearray);
                list.Add(labelledImage);
            } //foreach key

            var combinedImage = ImageTools.CombineImagesVertically(list.ToArray());

            return(combinedImage);
        } // method DrawGrayScaleSpectrograms()
        /// <summary>
        /// This method draws a spectrogram with other useful information attached.
        /// </summary>
        /// <param name="sonogram">of BaseSonogram class.</param>
        /// <param name="events">a list of acoustic events.</param>
        /// <param name="plots">a list of plots relevant to the spectrogram scores.</param>
        /// <param name="hits">not often used - can be null.</param>
        public static Image <Rgb24> GetSonogramPlusCharts(
            BaseSonogram sonogram,
            List <AcousticEvent> events,
            List <Plot> plots,
            double[,] hits)
        {
            var spectrogram = sonogram.GetImage(doHighlightSubband: false, add1KHzLines: true, doMelScale: false);

            Contract.RequiresNotNull(spectrogram, nameof(spectrogram));

            var height    = spectrogram.Height;
            var frameSize = sonogram.Configuration.WindowSize;

            // init with linear frequency scale and draw freq grid lines on image
            int hertzInterval = 1000;

            if (height < 200)
            {
                hertzInterval = 2000;
            }

            var freqScale = new FrequencyScale(sonogram.NyquistFrequency, frameSize, hertzInterval);

            FrequencyScale.DrawFrequencyLinesOnImage(spectrogram, freqScale.GridLineLocations, includeLabels: true);

            // draw event outlines onto spectrogram.
            if (events != null && events.Count > 0)
            {
                // set colour for the events
                foreach (AcousticEvent ev in events)
                {
                    ev.BorderColour = AcousticEvent.DefaultBorderColor;
                    ev.ScoreColour  = AcousticEvent.DefaultScoreColor;
                    ev.DrawEvent(spectrogram, sonogram.FramesPerSecond, sonogram.FBinWidth, height);
                }
            }

            // now add in hits to the spectrogram image.
            if (hits != null)
            {
                spectrogram = Image_MultiTrack.OverlayScoresAsRedTransparency(spectrogram, hits);

                // following line needs to be reworked if want to call OverlayRainbowTransparency(hits);
                //image.OverlayRainbowTransparency(hits);
            }

            int pixelWidth = spectrogram.Width;
            var titleBar   = LDSpectrogramRGB.DrawTitleBarOfGrayScaleSpectrogram("TITLE", pixelWidth);
            var timeTrack  = ImageTrack.DrawTimeTrack(sonogram.Duration, pixelWidth);

            var imageList = new List <Image <Rgb24> >
            {
                titleBar,
                timeTrack,
                spectrogram,
                timeTrack,
            };

            if (plots != null)
            {
                foreach (var plot in plots)
                {
                    // Next line assumes plot data normalised in 0,1
                    var plotImage = plot.DrawAnnotatedPlot(ImageTrack.DefaultHeight);

                    // the following draws same plot without the title.
                    //var plotImage = ImageTrack.DrawScoreArrayTrack(plot.data, plot.threshold, pixelWidth);
                    imageList.Add(plotImage);
                }
            }

            var compositeImage = ImageTools.CombineImagesVertically(imageList);

            return(compositeImage);
        }
 public static Image <Rgb24> DrawDifferenceSpectrogramDerivedFromSingleTStatistic(string key, LDSpectrogramRGB cs1, LDSpectrogramRGB cs2, double tStatThreshold, double colourGain)
 {
     double[,] m1     = cs1.GetNormalisedSpectrogramMatrix(key); //the TEN matrix is subtracted from 1.
     double[,] m2     = cs2.GetNormalisedSpectrogramMatrix(key);
     double[,] tStatM = GetTStatisticMatrix(key, cs1, cs2);
     return(DrawDifferenceSpectrogramDerivedFromSingleTStatistic(key, m1, m2, tStatM, tStatThreshold, colourGain));
 }
Ejemplo n.º 27
0
        public void SummariseResults(AnalysisSettings settings, FileSegment inputFileSegment, EventBase[] events, SummaryIndexBase[] indices, SpectralIndexBase[] spectralIndices, AnalysisResult2[] results)
        {
            var acousticIndicesConfig = (AcousticIndicesConfig)settings.AnalysisAnalyzerSpecificConfiguration;

            var  sourceAudio      = inputFileSegment.Source;
            var  resultsDirectory = AnalysisCoordinator.GetNamedDirectory(settings.AnalysisOutputDirectory, this);
            bool tileOutput       = acousticIndicesConfig.TileOutput;

            var frameWidth = acousticIndicesConfig.FrameLength;
            int sampleRate = AppConfigHelper.DefaultTargetSampleRate;

            sampleRate = acousticIndicesConfig.ResampleRate ?? sampleRate;

            // Gather settings for rendering false color spectrograms
            var ldSpectrogramConfig = acousticIndicesConfig.LdSpectrogramConfig;

            string basename = Path.GetFileNameWithoutExtension(sourceAudio.Name);

            // output to disk (so other analyzers can use the data,
            // only data - configuration settings that generated these indices
            // this data can then be used by post-process analyses

            /* NOTE: The value for FrameStep is used only when calculating a standard spectrogram
             * FrameStep is NOT used when calculating Summary and Spectral indices.
             */
            var indexConfigData = new IndexGenerationData()
            {
                RecordingExtension            = inputFileSegment.Source.Extension,
                RecordingBasename             = basename,
                RecordingStartDate            = inputFileSegment.TargetFileStartDate,
                RecordingDuration             = inputFileSegment.TargetFileDuration.Value,
                SampleRateOriginal            = inputFileSegment.TargetFileSampleRate.Value,
                SampleRateResampled           = sampleRate,
                FrameLength                   = frameWidth,
                FrameStep                     = settings.Configuration.GetIntOrNull(AnalysisKeys.FrameStep) ?? frameWidth,
                IndexCalculationDuration      = acousticIndicesConfig.IndexCalculationDurationTimeSpan,
                BgNoiseNeighbourhood          = acousticIndicesConfig.BgNoiseBuffer,
                AnalysisStartOffset           = inputFileSegment.SegmentStartOffset ?? TimeSpan.Zero,
                MaximumSegmentDuration        = settings.AnalysisMaxSegmentDuration,
                BackgroundFilterCoeff         = SpectrogramConstants.BACKGROUND_FILTER_COEFF,
                LongDurationSpectrogramConfig = ldSpectrogramConfig,
            };
            var icdPath = FilenameHelpers.AnalysisResultPath(
                resultsDirectory,
                basename,
                IndexGenerationData.FileNameFragment,
                "json");

            Json.Serialise(icdPath.ToFileInfo(), indexConfigData);

            // gather spectra to form spectrograms.  Assume same spectra in all analyzer results
            // this is the most efficient way to do this
            // gather up numbers and strings store in memory, write to disk one time
            // this method also AUTOMATICALLY SORTS because it uses array indexing
            var dictionaryOfSpectra = spectralIndices.ToTwoDimensionalArray(SpectralIndexValues.CachedSelectors, TwoDimensionalArray.Rotate90ClockWise);

            // Calculate the index distribution statistics and write to a json file. Also save as png image
            var indexDistributions = IndexDistributions.WriteSpectralIndexDistributionStatistics(dictionaryOfSpectra, resultsDirectory, basename);

            // HACK: do not render false color spectrograms unless IndexCalculationDuration = 60.0 (the normal resolution)
            if (acousticIndicesConfig.IndexCalculationDurationTimeSpan != 60.0.Seconds())
            {
                Log.Warn("False color spectrograms were not rendered");
            }
            else
            {
                FileInfo indicesPropertiesConfig = acousticIndicesConfig.IndexPropertiesConfig.ToFileInfo();

                // Actually draw false color / long duration spectrograms
                Tuple <Image <Rgb24>, string>[] images =
                    LDSpectrogramRGB.DrawSpectrogramsFromSpectralIndices(
                        inputDirectory: resultsDirectory,
                        outputDirectory: resultsDirectory,
                        ldSpectrogramConfig: ldSpectrogramConfig,
                        indexPropertiesConfigPath: indicesPropertiesConfig,
                        indexGenerationData: indexConfigData,
                        basename: basename,
                        analysisType: this.Identifier,
                        indexSpectrograms: dictionaryOfSpectra,
                        indexStatistics: indexDistributions,
                        imageChrome: (!tileOutput).ToImageChrome());

                if (tileOutput)
                {
                    Debug.Assert(images.Length == 2);

                    Log.Info("Tiling output at scale: " + acousticIndicesConfig.IndexCalculationDuration);

                    foreach (var image in images)
                    {
                        TileOutput(resultsDirectory, Path.GetFileNameWithoutExtension(sourceAudio.Name), image.Item2 + ".Tile", inputFileSegment, image.Item1);
                    }
                }
            }
        }
        public static double[,] GetDifferenceSpectrogramDerivedFromSingleTStatistic(string key, LDSpectrogramRGB cs1, LDSpectrogramRGB cs2, double tStatThreshold)
        {
            double[,] m1     = cs1.GetNormalisedSpectrogramMatrix(key); //the TEN matrix is subtracted from 1.
            double[,] m2     = cs2.GetNormalisedSpectrogramMatrix(key);
            double[,] tStatM = GetTStatisticMatrix(key, cs1, cs2);
            int rows = m1.GetLength(0); //number of rows
            int cols = m2.GetLength(1); //number

            var differenceM = new double[rows, cols];

            for (int row = 0; row < rows; row++)
            {
                for (int column = 0; column < cols; column++)
                {
                    if (Math.Abs(tStatM[row, column]) >= tStatThreshold)
                    {
                        differenceM[row, column] = m1[row, column] - m2[row, column];
                    }
                }
            }

            return(differenceM);
        }