public static Image <Rgb24> DrawOneScaledIndexSpectrogramTile( LdSpectrogramConfig config, IndexGenerationData indexGenerationData, Dictionary <string, IndexProperties> indexProperties, TimeSpan startTime, TimeSpan dataScale, TimeSpan imageScale, int superTileImageWidth, Dictionary <string, double[, ]> spectra, string basename, ImageChrome chromeOption) { Contract.Requires(!spectra.IsNullOrEmpty()); // calculate data duration from column count of abitrary matrix var matrix = spectra.First().Value; int columnCount = matrix.GetLength(1); TimeSpan dataDuration = TimeSpan.FromSeconds(columnCount * dataScale.TotalSeconds); var analysisStartTime = indexGenerationData.RecordingStartDate.Value.TimeOfDay.Add(indexGenerationData.AnalysisStartOffset); TimeSpan offsetTime = TimeSpan.Zero; TimeSpan imageDuration = TimeSpan.FromTicks(superTileImageWidth * imageScale.Ticks); TimeSpan halfImageDuration = TimeSpan.FromTicks(superTileImageWidth * imageScale.Ticks / 2); if (startTime < TimeSpan.Zero) { offsetTime = TimeSpan.Zero - startTime; startTime = TimeSpan.Zero; } TimeSpan endTime = startTime + imageDuration; if (endTime > dataDuration) { endTime = dataDuration; } // get the plain unchromed spectrogram var ldSpectrogram = ZoomCommon.DrawIndexSpectrogramCommon( config, indexGenerationData, indexProperties, startTime, endTime, dataScale, imageScale, superTileImageWidth, spectra, basename); if (chromeOption == ImageChrome.Without) { return(ldSpectrogram); } int nyquist = 22050 / 2; if (indexGenerationData.SampleRateResampled > 0) { nyquist = indexGenerationData.SampleRateResampled / 2; } int hertzInterval = 1000; if (config != null) { hertzInterval = config.YAxisTicInterval; } string title = $"ZOOM SCALE={imageScale.TotalSeconds}s/pixel"; var titleBar = ZoomFocusedSpectrograms.DrawTitleBarOfZoomSpectrogram(title, ldSpectrogram.Width); startTime += analysisStartTime; ldSpectrogram = ZoomFocusedSpectrograms.FrameZoomSpectrogram( ldSpectrogram, titleBar, startTime, imageScale, config.XAxisTicInterval, nyquist, hertzInterval); // create the base image var image = Drawing.NewImage(ldSpectrogram.Width, ldSpectrogram.Height, Color.DarkGray); var xOffset = (int)(offsetTime.Ticks / imageScale.Ticks); image.Mutate(g1 => { g1.DrawImage(ldSpectrogram, new Point(xOffset, 0), 1); }); return(image); }
/// <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"); }