private static (Dictionary <string, double[, ]>, Dictionary <string, IndexProperties>) LoadSpectra(
            AnalysisIoInputDirectory io,
            string analysisTag,
            string fileStem,
            Dictionary <string, IndexProperties> indexProperties)
        {
            indexProperties = InitialiseIndexProperties.FilterIndexPropertiesForSpectralOnly(indexProperties);
            string[] keys = indexProperties.Keys.ToArray();

            Dictionary <string, double[, ]> spectra = IndexMatrices.ReadSpectralIndices(
                io.InputBase,
                fileStem,
                analysisTag,
                keys);

            return(spectra, indexProperties);
        }
Exemplo n.º 2
0
        public static (Dictionary <string, double[, ]>, Dictionary <string, IndexProperties>) LoadSpectra(
            AnalysisIoInputDirectory io,
            string analysisTag,
            string fileStem,
            LdSpectrogramConfig config,
            Dictionary <string, IndexProperties> indexProperties)
        {
            var keys = config.GetKeys().Distinct();

            // add two necessary keys for zooming
            keys = keys.ToList().Append("SUM");
            keys = keys.ToList().Append("DIF");

            //add following matrix for possible subsequent BNG combination matrix.
            string comboIndexID = "RHZ";

            keys = keys.ToList().Append(comboIndexID);

            var relevantIndexProperties = keys.ToDictionary(x => x, x => indexProperties[x]);

            Dictionary <string, double[, ]> spectra = IndexMatrices.ReadSpectralIndices(
                io.InputBase,
                fileStem,
                analysisTag,
                keys.ToArray());

            /*
             * // THE FOLLOWING IDEA TO MAKE A COMBINED MATRIX OF BGN and RHZ was rejected.
             * // Anthony was concerned that the BGN matrix alone was not conveying much information at high resolutions.
             * // The idea was to combine another matrix with the BGN matrix.
             * // I tried three combinations, BGN-RHZ, BGN-OSC and BGN-SPT. None of them appeard to provide additional useful information at high resolution.
             * // The problem is that at high resolution, i.e. approaching 0.1s for an analysis unit, there are not many orthogonal features in a single frequency bin.
             * // Make a BNG COMBINATION Spectral matrix.
             * //var comboMatrix = MatrixTools.MaxOfTwoMatrices(spectra["BNG"], spectra["RHZ"]);
             * var comboMatrix = MatrixTools.AddMatricesWeightedSum(spectra["BGN"], 1.0, spectra[comboIndexID], 10.0);
             * spectra["BGN"] = comboMatrix;
             */

            return(spectra, relevantIndexProperties);
        }
        public static void DrawStackOfZoomedSpectrograms(
            DirectoryInfo inputDirectory,
            DirectoryInfo outputDirectory,
            AnalysisIoInputDirectory io,
            ZoomParameters common,
            string analysisTag,
            TimeSpan focalTime,
            int imageWidth)
        {
            var zoomConfig = common.SpectrogramZoomingConfig;
            LdSpectrogramConfig ldsConfig = common.SpectrogramZoomingConfig.LdSpectrogramConfig;

            //var distributions = common.IndexDistributions;
            string   fileStem        = common.OriginalBasename;
            var      indexGeneration = common.IndexGenerationData;
            TimeSpan dataScale       = indexGeneration.IndexCalculationDuration;

            // ####################### DERIVE ZOOMED OUT SPECTROGRAMS FROM SPECTRAL INDICES
            //var indexGenerationData = common.IndexGenerationData;
            var indexProperties = zoomConfig.IndexProperties;

            var(spectra, filteredIndexProperties) = ZoomCommon.LoadSpectra(io, analysisTag, fileStem, zoomConfig.LdSpectrogramConfig, indexProperties);

            Stopwatch sw = Stopwatch.StartNew();

            // Set the default time-scales in seconds per pixel.
            // These were changed on 3rd April 2019 to better match those in the current zooming config file.
            double[] imageScales = { 60, 30, 15, 7.5, 3.2, 1.6, 0.8, 0.4, 0.2 };
            if (zoomConfig.SpectralIndexScale != null)
            {
                imageScales = zoomConfig.SpectralIndexScale;
            }

            sw = Stopwatch.StartNew();
            int scaleCount = imageScales.Length;
            var imageList  = new List <Image <Rgb24> >();

            for (int i = 0; i < scaleCount; i++)
            {
                var imageScale = TimeSpan.FromSeconds(imageScales[i]);
                var image      = DrawIndexSpectrogramAtScale(ldsConfig, indexGeneration, filteredIndexProperties, focalTime, dataScale, imageScale, imageWidth, spectra, fileStem);
                if (image != null)
                {
                    imageList.Add(image);
                    string name = $"{fileStem}_FocalZoom_min{focalTime.TotalMinutes:f1}_scale{imageScales[i]}.png";
                    image.Save(Path.Combine(outputDirectory.FullName, name));
                }
            }

            sw.Stop();
            LoggedConsole.WriteLine("Finished spectrograms derived from spectral indices. Elapsed time = " + sw.Elapsed.TotalSeconds + " seconds");

            // NOTE: The following code is deprecated. It was originally developed to provide some intermediate steps between the hi-resolution false-colour spectrograms
            // and the standard grey scale spectrograms.
            // ####################### DERIVE ZOOMED IN SPECTROGRAMS FROM STANDARD SPECTRAL FRAMES

            /*
             * int[] compressionFactor = { 8, 4, 2, 1 };
             * int compressionCount = compressionFactor.Length;
             * sw = Stopwatch.StartNew();
             * double frameStepInSeconds = indexGeneration.FrameStep / (double)indexGeneration.SampleRateResampled;
             * TimeSpan frameScale = TimeSpan.FromTicks((long)Math.Round(frameStepInSeconds * 10000000));
             * if (zoomConfig.SpectralFrameScale != null)
             * {
             *  imageScales = zoomConfig.SpectralFrameScale;
             *
             *  // TODO: CONVERT IMAGE scales into Compression factors.
             *  compressionCount = imageScales.Length;
             *  compressionFactor = new int[compressionCount];
             *  compressionFactor[compressionCount - 1] = 1;
             *  double denom = imageScales[compressionCount - 1];
             *
             *  for (int i = 0; i < compressionCount - 1; i++)
             *  {
             *      compressionFactor[i] = (int)Math.Round(imageScales[i] / denom);
             *  }
             * }
             *
             * int maxCompression = compressionFactor[0];
             * TimeSpan maxImageDuration = TimeSpan.FromTicks(maxCompression * imageWidth * frameScale.Ticks);
             *
             * TimeSpan halfMaxImageDuration = TimeSpan.FromMilliseconds(maxImageDuration.TotalMilliseconds / 2);
             * TimeSpan startTimeOfMaxImage = TimeSpan.Zero;
             * if (focalTime != TimeSpan.Zero)
             * {
             *  startTimeOfMaxImage = focalTime - halfMaxImageDuration;
             * }
             *
             * TimeSpan startTimeOfData = TimeSpan.FromMinutes(Math.Floor(startTimeOfMaxImage.TotalMinutes));
             *
             * List<double[]> frameData = ReadFrameData(inputDirectory, fileStem, startTimeOfMaxImage, maxImageDuration, zoomConfig, indexGeneration.MaximumSegmentDuration.Value);
             *
             * // get the index data to add into the
             * // TimeSpan imageScale1 = TimeSpan.FromSeconds(0.1);
             * double[,] indexData = spectra["PMN"];
             *
             * // make the images
             * for (int i = 0; i < compressionCount; i++)
             * {
             *  int factor = compressionFactor[i];
             *  var image = DrawFrameSpectrogramAtScale(ldsConfig, indexGeneration, startTimeOfData, factor, frameData, indexData, focalTime, frameScale, imageWidth);
             *  if (image != null)
             *  {
             *      imageList.Add(image);
             *  }
             * }
             *
             * sw.Stop();
             * LoggedConsole.WriteLine("Finished spectrograms derived from standard frames. Elapsed time = " + sw.Elapsed.TotalSeconds + " seconds");
             */

            // combine the images into a stack
            var    combinedImage = ImageTools.CombineImagesVertically(imageList);
            string fileName      = $"{fileStem}_FocalZOOM_min{focalTime.TotalMinutes:f1}.png";

            combinedImage.Save(Path.Combine(outputDirectory.FullName, fileName));
        }
        /// <summary>
        /// THIS IS ENTRY METHOD FOR TILING SPECTROGRAMS.
        /// </summary>
        public static void DrawTiles(
            AnalysisIoInputDirectory io,
            ZoomParameters common,
            string analysisTag)
        {
            Log.Info("Begin Draw Super Tiles");
            Contract.Requires(common != null, "common can not be null");
            Contract.Requires(common.SpectrogramZoomingConfig != null, "SpectrogramZoomingConfig can not be null");

            var zoomConfig = common.SpectrogramZoomingConfig;
            LdSpectrogramConfig ldsConfig = common.SpectrogramZoomingConfig.LdSpectrogramConfig;
            var distributions             = common.IndexDistributions;
            var indexGenerationData       = common.IndexGenerationData;
            var indexProperties           = zoomConfig.IndexProperties;

            string fileStem = common.OriginalBasename;

            // scales for false color index spectrograms images in seconds per pixel.
            double[] indexScales = zoomConfig.SpectralIndexScale;

            // default scales for standard (FFT) spectrograms in seconds per pixel.
            double[] standardScales = zoomConfig.SpectralFrameScale;

            ValidateScales(indexScales, indexGenerationData.IndexCalculationDuration.TotalSeconds);

            var shouldRenderStandardScale = !standardScales.IsNullOrEmpty();

            if (!shouldRenderStandardScale)
            {
                Log.Warn("Standard spectrograms will not be rendered");
            }

            var allImageScales = indexScales.Concat(standardScales).ToArray();

            Log.Info("Tiling at scales: " + allImageScales.ToCommaSeparatedList());

            // determine what naming format to use for tiles
            var(namingPattern, alignmentPadding) = GetTilingProfile(
                common,
                zoomConfig,
                indexGenerationData,
                indexScales.Max());

            // pad out image so it produces a whole number of tiles
            // this solves the asymmetric right padding of short audio files
            // var paddedWidth = (int)(Math.Ceiling(zoomConfig.TileWidth / xNominalUnitScale) * xNominalUnitScale);

            // create a new tiler
            // pass it scales for x and y-axis
            // also pass it unit scale relations (between unit scale and unit height/width) to use as a reference point
            var tiler = new Tiler(
                new DirectoryInfo(io.OutputBase.FullName),
                namingPattern,
                xScales: new SortedSet <double>(allImageScales),
                xUnitScale: XNominalUnitScale,
                unitWidth: 1440,
                yScales: new SortedSet <double>(allImageScales.Select(x => 1.0)),
                yUnitScale: 1.0,
                unitHeight: namingPattern.TileHeight);

            var(spectra, filteredIndexProperties) = ZoomCommon.LoadSpectra(io, analysisTag, fileStem, zoomConfig.LdSpectrogramConfig, indexProperties);

            // false color index tiles
            GenerateIndexSpectrogramTiles(
                indexScales,
                ldsConfig,
                filteredIndexProperties,
                zoomConfig,
                spectra,
                indexGenerationData,
                fileStem,
                namingPattern,
                tiler,
                alignmentPadding);

            // standard fft frame spectrograms
            if (shouldRenderStandardScale)
            {
                GenerateStandardSpectrogramTiles(
                    spectra,
                    indexGenerationData,
                    ldsConfig,
                    filteredIndexProperties,
                    zoomConfig,
                    standardScales,
                    fileStem,
                    namingPattern,
                    tiler,
                    alignmentPadding);
            }

            Log.Success("Tiling complete");
        }