using System.Collections.Concurrent; using System.Collections.ObjectModel; using System.IO; using System.Windows; using System.Windows.Media.Imaging; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Messaging; using Livia.Models; using Livia.Models.Data; using Livia.Utility; using Livia.Utility.DependencyInjection; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace Livia.ViewModels; public class MosaicImageGroupControlViewModel : ObservableObject, IRecipient, ILiviaModuleViewModel { public ObservableCollection MosaicImageCollection { get; } = []; public ImageRotationViewerGroupControlViewModel AxialOverviewViewModel { get; } public bool AxialOverviewVisible { get => _axialOverviewVisibleVisible; set { SetProperty(ref _axialOverviewVisibleVisible, value); if (!value) return; RoiLegendVisible = true; ColorBarVisible = false; AdditionalInfoJson additionalInfo = _dataBlockLoader.GetSharedData("additionalInfo"); string defaultMaskToLoad = additionalInfo.AtlasInfoListDict.Keys.First(k => k.Contains("cbf", StringComparison.CurrentCultureIgnoreCase)); ImageRotationViewerControlViewModel.LoadAtlasName = defaultMaskToLoad; PerfusionDataGridControlViewModel.LoadAtlasName = defaultMaskToLoad; WeakReferenceMessenger.Default.Send(new MaskChangedMessage()); } } public bool RoiLegendVisible { get => _roiLegendVisible; private set => SetProperty(ref _roiLegendVisible, value); } public bool ColorBarVisible { get => _colorBarVisible; private set => SetProperty(ref _colorBarVisible, value); } public ColorBarControlViewModel ColorBarControlViewModel { get; } public IRoiLegendManager RoiLegendManager { get; } public MosaicImageControlViewModel CurrentMosaicImageControlViewModel { get; } public static bool RoiEnabled { get; set; } = true; public int LastTabIndex; private bool _axialOverviewVisibleVisible; private bool _roiLegendVisible; private bool _colorBarVisible; private string _currentMosaicImageKey = string.Empty; private int _currentTabIndex; private readonly IDataBlockLoader _dataBlockLoader; private readonly ILogger _logger; private readonly Dictionary<(string MosaicImageKey, int TabIndex), ObservableCollection> _roiCollectionDictionary = new(); private readonly ObservableCollection _emptyCollection = []; public MosaicImageGroupControlViewModel(IRoiLegendManager roiLegendManager, IDataBlockLoader dataBlockLoader, ILogger logger) { RoiLegendManager = roiLegendManager; _dataBlockLoader = dataBlockLoader; _logger = logger; AxialOverviewViewModel = ActivatorUtilities.CreateInstance(ServiceProviderFactory.ServiceProvider); ColorBarControlViewModel = ActivatorUtilities.CreateInstance(ServiceProviderFactory.ServiceProvider); CurrentMosaicImageControlViewModel = ActivatorUtilities.CreateInstance(ServiceProviderFactory.ServiceProvider); WeakReferenceMessenger.Default.RegisterAll(this); } public async Task LoadData(DataBlock dataBlock) { MosaicImageCollection.Clear(); AdditionalInfoJson additionalInfo = _dataBlockLoader.GetSharedData("additionalInfo"); CurrentMosaicImageControlViewModel.RoiCollection = _emptyCollection; foreach (MosaicImageInfo info in additionalInfo.MosaicImageInfoList) { //roi disabled, and it is a roi image. if (!RoiEnabled && info.Range == null) continue; string displayName = info.ImgId; BitmapImage image = await LiviaUtility.LoadBitmapAsync(Path.Combine(dataBlock.ResultPath, info.FilePath)); MosaicImageData data = new(image, displayName, info) { ShowJumpToDataGridButton = additionalInfo.AtlasInfoListDict.ContainsKey(info.ImgId), ShowMosaicRoiOverlayTip = additionalInfo.MosaicRoiOverlayInfoList.Exists(n => n.ImgId.Equals(info.ImgId)) }; MosaicImageCollection.Add(data); } await AxialOverviewViewModel.LoadData(dataBlock); AxialOverviewVisible = true; //update roi collection _roiCollectionDictionary.Clear(); if (RoiSummaryControlViewModel.RoiTabIdToTabIndexDictionary != null) { Dictionary> roiDictionary = _dataBlockLoader.GetSharedData>>("roiCollection"); foreach (RoiOverlayInfo overlayInfo in additionalInfo.MosaicRoiOverlayInfoList) { ObservableCollection roiCollection = []; if (roiDictionary.TryGetValue(overlayInfo.RoiTabId, out ConcurrentBag? bag)) roiCollection.AddRange(bag.OrderBy(item => item.ZIndex)); if (!RoiSummaryControlViewModel.RoiTabIdToTabIndexDictionary.TryGetValue(overlayInfo.RoiTabId, out int tabIndex)) continue; if (!_roiCollectionDictionary.TryAdd((overlayInfo.ImgId, tabIndex), roiCollection)) { _logger.LogWarning("Mosaic roi key pair already exists: {imageId}, {tabIndex}", overlayInfo.ImgId, tabIndex); } } } } public void Init() { } public void SetSelectedMosaicImage(MosaicImageData data) { ColorBarVisible = data.UseColorBar; RoiLegendVisible = !ColorBarVisible; AxialOverviewVisible = false; CurrentMosaicImageControlViewModel.CurrentMosaicImage = data.Image; _currentMosaicImageKey = data.MosaicImageInfo.ImgId; CurrentMosaicImageControlViewModel.RoiCollection = _emptyCollection; UpdateRoi(); if (data.MosaicImageInfo.Range == null) return; ColorBarControlViewModel.ColorBarRangeMin = data.MosaicImageInfo.Range[0]; ColorBarControlViewModel.ColorBarRangeMax = data.MosaicImageInfo.Range[1]; ColorBarControlViewModel.ColorBarUnit = data.MosaicImageInfo.Unit; ColorBarControlViewModel.ImagePath = data.MosaicImageInfo.IsGray ? ColorBarControlViewModel.BlackWhiteColorBarImage : ColorBarControlViewModel.PerfusionColorBarImage; AdditionalInfoJson additionalInfo = _dataBlockLoader.GetSharedData("additionalInfo"); string maskToLoad = additionalInfo.AtlasInfoListDict.ContainsKey(data.DisplayName) ? data.DisplayName : additionalInfo.AtlasInfoListDict.Keys.First(k => k.Contains("cbf", StringComparison.CurrentCultureIgnoreCase)); ImageRotationViewerControlViewModel.LoadAtlasName = maskToLoad; WeakReferenceMessenger.Default.Send(new MaskChangedMessage()); if (data.ShowJumpToDataGridButton) WeakReferenceMessenger.Default.Send(new PerfusionDataGridChangeParameterMessage(maskToLoad)); } private void UpdateRoi() { if (_roiCollectionDictionary.TryGetValue((_currentMosaicImageKey, _currentTabIndex), out ObservableCollection? roiCollection)) { CurrentMosaicImageControlViewModel.RoiCollection = roiCollection; LastTabIndex = _currentTabIndex; } else { if (_roiCollectionDictionary.TryGetValue((_currentMosaicImageKey, LastTabIndex), out ObservableCollection? lastRoiCollection)) CurrentMosaicImageControlViewModel.RoiCollection = lastRoiCollection; } //update display name foreach (MosaicImageData mosaicImageData in MosaicImageCollection) { if (_roiCollectionDictionary.ContainsKey((mosaicImageData.MosaicImageInfo.ImgId, _currentTabIndex))) { mosaicImageData.DisplayName = (string)(Application.Current.TryFindResource($"RoiTabHeader{_currentTabIndex}") ?? ""); } } } public void Receive(RoiTabChangedMessage message) { _currentTabIndex = message.Value; UpdateRoi(); } }