livia-test/DicomViewer/ViewModels/MainWindowViewModel.cs
2025-03-28 14:31:53 +08:00

190 lines
5.9 KiB
C#

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<string> ImageList { get; } = [];
public ObservableCollection<PixelInfo> PixelInfoList { get; } = [];
public string CursorPosition { get => _cursorPosition; set => SetProperty(ref _cursorPosition, value); }
private readonly Dictionary<string, List<DicomDataTuple>> _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<DicomDataTuple> 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<DicomDataTuple> 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<DicomDataTuple> LoadFromDir(string path)
{
string[] files = Directory.GetFiles(path);
Array.Sort(files);
List<DicomDataTuple> dataList = files.Select(file => new DicomDataTuple(file)).ToList();
return dataList;
}
private static List<DicomDataTuple> LoadFromFile(string path)
{
DicomImage image = new(path);
List<DicomDataTuple> 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<string, List<DicomDataTuple>> 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--;
}
}