/// <summary> /// Starts threads for frontal texture creation. /// </summary> /// <param name="groupState">synchronized Threadstate used to observe progress of one or multiple threads.</param> /// <param name="processed">synchronized queue which will be filled with each image index, that is ready.</param> /// <param name="data">pixel intensity values in a 3D Array mapped to a 1D Array.</param> /// <param name="files">all the DICOM files.</param> /// <param name="target">target jagged array, which the result will be written to.</param> /// <param name="windowWidth">Option to set custom windowWidth, Double.MinValue to not use it</param> /// <param name="windowCenter">Option to set custom windowCenter, Double.MinValue to not use it</param> /// <param name="threadCount">Amount of Threads to use</param> private void StartCreatingFrontTextures(ThreadGroupState groupState, ConcurrentQueue <int> processed, int[] data, IReadOnlyList <DiFile> files, IList <Color32[]> target, double windowWidth, double windowCenter, int threadCount) { int spacing = Height / threadCount; for (var i = 0; i < threadCount; ++i) { groupState.Register(); var startIndex = i * spacing; var endIndex = startIndex + spacing; if (i + 1 == threadCount) { endIndex = Height; } var t = new Thread(() => CreateFrontTextures(groupState, processed, data, Width, Height, files, target, windowWidth, windowCenter, startIndex, endIndex)) { IsBackground = true }; t.Start(); } }
/// <summary> /// Starts threads for volume texture creation. /// </summary> /// <param name="groupState">synchronized Threadstate used to observe progress of one or multiple threads.</param> /// <param name="files">all the DICOM files.</param> /// <param name="data">pixel intensity values in a 3D Array mapped to a 1D Array.</param> /// <param name="target">target jagged array, which the result will be written to.</param> /// <param name="windowWidth">Option to set custom windowWidth, Double.MinValue to not use it</param> /// <param name="windowCenter">Option to set custom windowCenter, Double.MinValue to not use it</param> /// <param name="threadCount">Amount of Threads to use</param> private void StartCreatingVolume(ThreadGroupState groupState, IReadOnlyList <DiFile> files, IReadOnlyList <int> data, IList <Color32> target, double windowWidth, double windowCenter, int threadCount) { #if PRINT_USAGE Debug.Log(Time.time + $" : Started Creating Volume with Window (Center {WindowCenter}, Width {WindowWidth})"); #endif var spacing = files.Count / threadCount; for (var i = 0; i < threadCount; ++i) { groupState.Register(); var startIndex = i * spacing; var endIndex = startIndex + spacing; if (i + 1 == threadCount) { endIndex = files.Count; } var t = new Thread(() => CreateVolume(groupState, data, files, Width, Height, target, windowWidth, windowCenter, startIndex, endIndex)) { IsBackground = true }; t.Start(); } }
/// <summary> /// Unity coroutine for loading the selected folder of files. /// </summary> /// <param name="folderPath">Path of the folder containing the DICOM files</param> /// <param name="threadGroupState">Thread safe thread-state used to observe progress of one or multiple threads.</param> /// <returns>IEnumerator for usage as a coroutine</returns> private IEnumerator InitFiles(string folderPath, ThreadGroupState threadGroupState) { threadGroupState.Register(); //string[] filePaths = Directory.GetFiles(folderPath); //filePaths = Array.FindAll(filePaths, HasNoExtension); var fileNames = GetFiles(folderPath); DicomFiles = new DiFile[fileNames.Count]; threadGroupState.TotalProgress = fileNames.Count; yield return(null); var zeroBased = true; foreach (var path in fileNames) { var diFile = new DiFile(); diFile.InitFromFile(path); if (zeroBased && diFile.GetImageNumber() == DicomFiles.Length) { ShiftLeft(DicomFiles); zeroBased = false; } if (zeroBased) { DicomFiles[diFile.GetImageNumber()] = diFile; } else { DicomFiles[diFile.GetImageNumber() - 1] = diFile; } threadGroupState.IncrementProgress(); yield return(null); } Width = DicomFiles[0].GetImageWidth(); Height = DicomFiles[0].GetImageHeight(); _data = new int[DicomFiles.Length * Width * Height]; VolumeTexture = null; WindowCenterPresets = DicomFiles[0].GetElement(0x0028, 0x1050)?.GetDoubles() ?? new[] { double.MinValue }; WindowWidthPresets = DicomFiles[0].GetElement(0x0028, 0x1051)?.GetDoubles() ?? new[] { double.MinValue }; WindowCenter = WindowCenterPresets[0]; WindowWidth = WindowWidthPresets[0]; MinPixelIntensity = (int)(DicomFiles[0].GetElement(0x0028, 0x1052)?.GetDouble() ?? 0d); MaxPixelIntensity = (int)((DicomFiles[0].GetElement(0x0028, 0x1053)?.GetDouble() ?? 1d) * (Math.Pow(2, DicomFiles[0].GetBitsStored()) - 1) + MinPixelIntensity); threadGroupState.Done(); }
/// <summary> /// Starts one or more Threads for preprocessing. /// </summary> /// <param name="groupState">synchronized Threadstate used to observe progress of one or multiple threads.</param> /// <param name="files">all the DICOM files.</param> /// <param name="target">1D array receiving the 3D data.</param> /// <param name="threadCount">Amount of Threads to use.</param> private void StartPreProcessing(ThreadGroupState groupState, IReadOnlyList <DiFile> files, int[] target, int threadCount) { int spacing = files.Count / threadCount; for (var i = 0; i < threadCount; ++i) { var startIndex = i * spacing; var endIndex = startIndex + spacing; if (i + 1 == threadCount) { endIndex = files.Count; } groupState.Register(); var t = new Thread(() => PreProcess(groupState, files, Width, Height, target, startIndex, endIndex)) { IsBackground = true }; t.Start(); } }