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); }
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"); }