/// <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"); }
private static (TilingProfile Profile, TimeSpan padding) GetTilingProfile( ZoomParameters common, SpectrogramZoomingConfig zoomConfig, IndexGenerationData indexGeneration, double maxScale) { TilingProfile namingPattern; TimeSpan padding; switch (zoomConfig.TilingProfile) { case nameof(PanoJsTilingProfile): namingPattern = new PanoJsTilingProfile(); padding = TimeSpan.Zero; if (zoomConfig.TileWidth != namingPattern.TileWidth) { throw new ConfigFileException( "TileWidth must match the default PanoJS TileWidth of " + namingPattern.TileWidth); } break; case nameof(AbsoluteDateTilingProfile): // Zooming spectrograms use multiple color profiles at different levels // therefore unable to set a useful tag (like ACI-ENT-EVN). if (indexGeneration.RecordingStartDate != null) { var recordingStartDate = (DateTimeOffset)indexGeneration.RecordingStartDate; var tilingStartDate = GetPreviousTileBoundary( zoomConfig.TileWidth, maxScale, recordingStartDate); padding = recordingStartDate - tilingStartDate; // if we're not writing tiles to disk, omit the basename because whatever the container format is // it will have the base name attached namingPattern = new AbsoluteDateTilingProfile( common.OmitBasename ? string.Empty : common.OriginalBasename, "BLENDED.Tile", tilingStartDate, indexGeneration.FrameLength / 2, zoomConfig.TileWidth); } else { throw new ArgumentNullException( nameof(zoomConfig.TilingProfile), "`RecordingStateDate` from the `IndexGenerationData.json` cannot be null when `AbsoluteDateTilingProfile` specified"); } break; default: throw new ConfigFileException( $"The {nameof(zoomConfig.TilingProfile)} configuration property was set to an unsupported value - no profile known by that name"); } Log.Info($"Tiling had a left padding duration of {padding} to align tiles"); Log.Info( $"Tiling using {namingPattern.GetType().Name}, Tile Width: {namingPattern.TileWidth}, Height: {namingPattern.TileHeight}"); return(namingPattern, padding); }