using System.Collections.ObjectModel; using System.IO; using System.Text.RegularExpressions; using CommunityToolkit.Mvvm.ComponentModel; using DicomViewer.Models; using FellowOakDicom.Imaging; using OxyPlot; using OxyPlot.Series; namespace DicomViewer.ViewModels; public readonly record struct PixelInfo { public string Name { get; init; } public string Value { get; init; } } internal class MainWindowViewModel : ObservableObject { public DicomDataTuple? CurrentImage { get => _currentImage; private set => SetProperty(ref _currentImage, value); } public int CurrentIndex { get => _currentIndex; private set { SetProperty(ref _currentIndex, value); UpdateCurrentImage(); } } public int MaxIndex { get => _maxIndex; private set => SetProperty(ref _maxIndex, value); } public string CurrentImageName { get => _currentImageName; set { SetProperty(ref _currentImageName, value); UpdateCurrentImage(); } } public PlotModel CbfPlotModelModel { get => _cbfPlotModelModel; set => SetProperty(ref _cbfPlotModelModel, value); } public ObservableCollection ImageList { get; } = []; public ObservableCollection PixelInfoList { get; } = []; public string CursorPosition { get => _cursorPosition; set => SetProperty(ref _cursorPosition, value); } private readonly Dictionary> _imageDictionary = new(); private int _currentIndex; private int _maxIndex; private int _pldCount; private string _currentImageName = string.Empty; private string _cursorPosition = string.Empty; private PlotModel _cbfPlotModelModel = new(); private DicomDataTuple? _currentImage; public void LoadData(string path) { CurrentImageName = "corr-cbf"; _imageDictionary.Clear(); ImageList.Clear(); _pldCount = 0; try { //read from each sub folder foreach (string directory in Directory.GetDirectories(Path.Combine(path, "asl"))) { string key = Path.GetFileName(directory); ImageList.Add(key); List imageList = LoadFromDir(directory); _imageDictionary.Add(key, imageList); if (Regex.IsMatch(key, @"cbf\d+")) _pldCount++; } //read java temp string javaTempDir = Path.Combine(path, "java_temp", "reconstructed"); if (Directory.Exists(javaTempDir)) { foreach (string file in Directory.GetFiles(javaTempDir, "*.dcm")) { string key = "j_" + Path.GetFileNameWithoutExtension(file); ImageList.Add(key); List imageList = LoadFromFile(file); _imageDictionary.Add(key, imageList); } } MaxIndex = _imageDictionary.First().Value.Count; CurrentIndex = MaxIndex / 2; } catch (Exception e) { Console.WriteLine(e); throw; } } private static List LoadFromDir(string path) { string[] files = Directory.GetFiles(path); Array.Sort(files); List dataList = files.Select(file => new DicomDataTuple(file)).ToList(); return dataList; } private static List LoadFromFile(string path) { DicomImage image = new(path); List dataList = Enumerable.Range(0, image.NumberOfFrames).Select(index => new DicomDataTuple(path, index)).ToList(); return dataList; } public void UpdateCbfPlot(int x, int y) { try { //draw plot PlotModel model = new() { Title = "CBF Plot" }; LineSeries cbfLine = new() { Title = "CBF", LineJoin = LineJoin.Bevel, MarkerType = MarkerType.Circle }; for (int i = 1; i <= _pldCount; i++) { cbfLine.Points.Add(new DataPoint(i + 1, _imageDictionary[$"cbf{i}"][CurrentIndex - 1].GetPixel(x, y))); } model.Series.Add(cbfLine); //Siemens 5 if (_imageDictionary.ContainsKey("j_PLD1")) { LineSeries pldLine = new() { Title = "PLD", LineJoin = LineJoin.Bevel, MarkerType = MarkerType.Square }; for (int i = 1; i <= _pldCount; i++) { pldLine.Points.Add(new DataPoint(i + 1, _imageDictionary[$"j_PLD{i}"][CurrentIndex - 1].GetPixel(x, y))); } model.Series.Add(pldLine); } CbfPlotModelModel = model; //add all info PixelInfoList.Clear(); foreach (KeyValuePair> pair in _imageDictionary) { string value = string.Empty; try { value = pair.Value[CurrentIndex - 1].GetPixel(x, y).ToString("0.##"); } catch (Exception e) { Console.WriteLine(e); } PixelInfoList.Add(new PixelInfo { Name = pair.Key, Value = value }); } } catch (Exception e) { Console.WriteLine(e); } } private void UpdateCurrentImage() { try { CurrentImage = _imageDictionary[CurrentImageName][CurrentIndex - 1]; } catch (Exception e) { Console.WriteLine(e); } } public void NextImage() { if (CurrentIndex >= MaxIndex) return; CurrentIndex++; } public void PrevImage() { if (CurrentIndex <= 1) return; CurrentIndex--; } }