static void ShowSequenceImporter() { string dir = EditorUtility.OpenFolderPanel("Select a folder to load", "", ""); if (Directory.Exists(dir)) { ImageSequenceImporter importer = new ImageSequenceImporter(dir); VolumeDataset dataset = importer.Import(); if (dataset != null) { if (EditorPrefs.GetBool("DownscaleDatasetPrompt")) { if (EditorUtility.DisplayDialog("Optional DownScaling", $"Do you want to downscale the dataset? The dataset's dimension is: {dataset.dimX} x {dataset.dimY} x {dataset.dimZ}", "Yes", "No")) { dataset.DownScaleData(); } } VolumeObjectFactory.CreateObject(dataset); } } else { Debug.LogError("Directory doesn't exist: " + dir); } }
private void OnOpenRAWDatasetResult(RuntimeFileBrowser.DialogResult result) { if (!result.cancelled) { // We'll only allow one dataset at a time in the runtime GUI (for simplicity) DespawnAllDatasets(); // Did the user try to import an .ini-file? Open the corresponding .raw file instead string filePath = result.path; if (System.IO.Path.GetExtension(filePath) == ".ini") { filePath = filePath.Replace(".ini", ".raw"); } // Parse .ini file DatasetIniData initData = DatasetIniReader.ParseIniFile(filePath + ".ini"); if (initData != null) { // Import the dataset RawDatasetImporter importer = new RawDatasetImporter(filePath, initData.dimX, initData.dimY, initData.dimZ, initData.format, initData.endianness, initData.bytesToSkip); VolumeDataset dataset = importer.Import(); // Spawn the object if (dataset != null) { VolumeObjectFactory.CreateObject(dataset); } } } }
public static void ImportDataset(string filePath) { DatasetType datasetType = DatasetImporterUtility.GetDatasetType(filePath); switch (datasetType) { case DatasetType.Raw: { RAWDatasetImporterEditorWindow wnd = (RAWDatasetImporterEditorWindow)EditorWindow.GetWindow(typeof(RAWDatasetImporterEditorWindow)); if (wnd != null) { wnd.Close(); } wnd = new RAWDatasetImporterEditorWindow(filePath); wnd.Show(); break; } case DatasetType.DICOM: { DatasetImporterBase importer = new DICOMImporter(new FileInfo(filePath).Directory.FullName, false); VolumeDataset dataset = importer.Import(); if (dataset != null) { VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); } break; } } }
/// <summary> /// Generates a histogram where: /// X-axis = the data sample (density) value /// Y-axis = the sample count (number of data samples with the specified density) /// </summary> /// <param name="dataset"></param> /// <returns></returns> public static Texture2D GenerateHistogramTexture(VolumeDataset dataset) { int minValue = dataset.GetMinDataValue(); int maxValue = dataset.GetMaxDataValue(); int numValues = maxValue - minValue + 1; float valRangeRecip = 1.0f / (maxValue - minValue); int numSamples = System.Math.Min(numValues, 1024); int[] values = new int[numSamples]; Color[] cols = new Color[numSamples]; Texture2D texture = new Texture2D(numSamples, 1, TextureFormat.RGBAFloat, false); int maxFreq = 0; for (int iData = 0; iData < dataset.data.Length; iData++) { int dataValue = dataset.data[iData]; float tValue = (dataValue - minValue) * valRangeRecip; int valueIndex = Mathf.RoundToInt((numSamples - 1) * tValue); values[valueIndex] += 1; maxFreq = System.Math.Max(values[valueIndex], maxFreq); } for (int iSample = 0; iSample < numSamples; iSample++) { cols[iSample] = new Color(Mathf.Log10((float)values[iSample]) / Mathf.Log10((float)maxFreq), 0.0f, 0.0f, 1.0f); } texture.SetPixels(cols); texture.Apply(); return(texture); }
private void OnOpenDICOMDatasetResult(RuntimeFileBrowser.DialogResult result) { if (!result.cancelled) { // We'll only allow one dataset at a time in the runtime GUI (for simplicity) DespawnAllDatasets(); bool recursive = true; // Read all files IEnumerable <string> fileCandidates = Directory.EnumerateFiles(result.path, "*.*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly) .Where(p => p.EndsWith(".dcm", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicom", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicm", StringComparison.InvariantCultureIgnoreCase)); // Import the dataset DICOMImporter importer = new DICOMImporter(fileCandidates, Path.GetFileName(result.path)); List <DICOMImporter.DICOMSeries> seriesList = importer.LoadDICOMSeries(); float numVolumesCreated = 0; foreach (DICOMImporter.DICOMSeries series in seriesList) { VolumeDataset dataset = importer.ImportDICOMSeries(series); // Spawn the object if (dataset != null) { VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); obj.transform.position = new Vector3(numVolumesCreated, 0, 0); numVolumesCreated++; } } } }
public static Texture2D GenerateHistogramTexture(VolumeDataset dataset) { int minValue = dataset.GetMinDataValue(); int maxValue = dataset.GetMaxDataValue(); int numSamples = maxValue - minValue + 1; int[] values = new int[numSamples]; Color[] cols = new Color[numSamples]; Texture2D texture = new Texture2D(numSamples, 1, TextureFormat.RGBAFloat, false); int maxFreq = 0; for (int iData = 0; iData < dataset.data.Length; iData++) { int dataValue = dataset.data[iData] - minValue; values[dataValue] += 1; maxFreq = System.Math.Max(values[dataValue], maxFreq); } for (int iSample = 0; iSample < numSamples; iSample++) { cols[iSample] = new Color(Mathf.Log10((float)values[iSample]) / Mathf.Log10((float)maxFreq), 0.0f, 0.0f, 1.0f); } texture.SetPixels(cols); texture.Apply(); return(texture); }
static void ShowDICOMImporter() { string dir = EditorUtility.OpenFolderPanel("Select a folder to load", "", ""); if (Directory.Exists(dir)) { bool recursive = true; // Read all files IEnumerable <string> fileCandidates = Directory.EnumerateFiles(dir, "*.*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly) .Where(p => p.EndsWith(".dcm", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicom", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicm", StringComparison.InvariantCultureIgnoreCase)); if (!fileCandidates.Any()) { #if UNITY_EDITOR if (UnityEditor.EditorUtility.DisplayDialog("Could not find any DICOM files", $"Failed to find any files with DICOM file extension.{Environment.NewLine}Do you want to include files without DICOM file extension?", "Yes", "No")) { fileCandidates = Directory.EnumerateFiles(dir, "*.*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); } #endif } if (fileCandidates.Any()) { DICOMImporter importer = new DICOMImporter(fileCandidates, Path.GetFileName(dir)); List <DICOMImporter.DICOMSeries> seriesList = importer.LoadDICOMSeries(); float numVolumesCreated = 0; foreach (DICOMImporter.DICOMSeries series in seriesList) { VolumeDataset dataset = importer.ImportDICOMSeries(series); if (dataset != null) { if (EditorPrefs.GetBool("DownscaleDatasetPrompt")) { if (EditorUtility.DisplayDialog("Optional DownScaling", $"Do you want to downscale the dataset? The dataset's dimension is: {dataset.dimX} x {dataset.dimY} x {dataset.dimZ}", "Yes", "No")) { dataset.DownScaleData(); } } VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); obj.transform.position = new Vector3(numVolumesCreated, 0, 0); numVolumesCreated++; } } } else { Debug.LogError("Could not find any DICOM files to import."); } } else { Debug.LogError("Directory doesn't exist: " + dir); } }
/// <summary> /// Creates a histogram texture for 2D transfer functions. /// X-axis = data sample (density) value /// Y-axis = gradient magnitude /// colour = white (if there is a data sample with the specified value and gradient magnitude) or black (if not) /// </summary> /// <param name="dataset"></param> /// <returns></returns> public static Texture2D Generate2DHistogramTexture(VolumeDataset dataset) { float minValue = dataset.GetMinDataValue(); float maxValue = dataset.GetMaxDataValue(); // Value range of the density values. float densityValRange = maxValue - minValue + 1.0f; float densityRangeRecip = 1.0f / (maxValue - minValue); // reciprocal // Clamp density value samples. int numDensitySamples = System.Math.Min((int)densityValRange, 512); int numGradientSamples = 256; Color[] cols = new Color[numDensitySamples * numGradientSamples]; Texture2D texture = new Texture2D(numDensitySamples, numGradientSamples, TextureFormat.RGBAFloat, false); // Zero-initialise colours. for (int iCol = 0; iCol < cols.Length; iCol++) { cols[iCol] = new Color(0.0f, 0.0f, 0.0f, 0.0f); } float maxRange = dataset.GetMaxDataValue() - dataset.GetMinDataValue(); const float maxNormalisedMagnitude = 1.75f; // sqrt(1^2 + 1^2 + 1^2) = swrt(3) = a bit less than 1.75 for (int x = 1; x < dataset.dimX - 1; x++) { for (int y = 1; y < dataset.dimY - 1; y++) { for (int z = 1; z < dataset.dimZ - 1; z++) { int iData = x + y * dataset.dimX + z * (dataset.dimX * dataset.dimY); int density = Mathf.RoundToInt(dataset.data[iData]); // FIXME float x1 = dataset.data[(x + 1) + y * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; float x2 = dataset.data[(x - 1) + y * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; float y1 = dataset.data[x + (y + 1) * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; float y2 = dataset.data[x + (y - 1) * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; float z1 = dataset.data[x + y * dataset.dimX + (z + 1) * (dataset.dimX * dataset.dimY)]; float z2 = dataset.data[x + y * dataset.dimX + (z - 1) * (dataset.dimX * dataset.dimY)]; // Calculate gradient Vector3 grad = new Vector3((x2 - x1) / (float)maxRange, (y2 - y1) / (float)maxRange, (z2 - z1) / (float)maxRange); // Calculate density and gradient value indices (in flattened 2D array) float tDensity = (density - minValue) * densityRangeRecip; int iDensity = Mathf.RoundToInt((numDensitySamples - 1) * tDensity); int iGrad = (int)(grad.magnitude * numGradientSamples / maxNormalisedMagnitude); // Assign a white colour to all samples (in a histogram where x = density and y = gradient magnitude). cols[iDensity + iGrad * numDensitySamples] = Color.white; } } } texture.SetPixels(cols); texture.Apply(); return(texture); }
public override VolumeDataset Import() { VolumeDataset dataset = new VolumeDataset(); dataset.dimX = dimX; dataset.dimY = dimY; dataset.dimZ = dimZ; FileStream fs = new FileStream(filePath, FileMode.Open); BinaryReader reader = new BinaryReader(fs); if (skipBytes > 0) { reader.ReadBytes(skipBytes); } int uDimension = dimX * dimY * dimZ; dataset.data = new int[uDimension]; int val = 0; for (int i = 0; i < uDimension; i++) { switch (contentFormat) { case DataContentFormat.Int8: val = (int)reader.ReadSByte(); break; case DataContentFormat.Int16: val = (int)reader.ReadInt16(); break; case DataContentFormat.Int32: val = (int)reader.ReadInt32(); break; case DataContentFormat.Uint8: val = (int)reader.ReadByte(); break; case DataContentFormat.Uint16: val = (int)reader.ReadUInt16(); break; case DataContentFormat.Uint32: val = (int)reader.ReadUInt32(); break; } dataset.data[i] = val; } Debug.Log("Loaded dataset in range: " + dataset.GetMinDataValue() + " - " + dataset.GetMaxDataValue()); return(dataset); }
public VolumeDataset Import() { // Check that the file exists if (!File.Exists(filePath)) { Debug.LogError("The file does not exist: " + filePath); return(null); } FileStream fs = new FileStream(filePath, FileMode.Open); BinaryReader reader = new BinaryReader(fs); // Check that the dimension does not exceed the file size long expectedFileSize = (long)(dimX * dimY * dimZ) * GetSampleFormatSize(contentFormat) + skipBytes; if (fs.Length < expectedFileSize) { Debug.LogError($"The dimension({dimX}, {dimY}, {dimZ}) exceeds the file size. Expected file size is {expectedFileSize} bytes, while the actual file size is {fs.Length} bytes"); reader.Close(); fs.Close(); return(null); } VolumeDataset dataset = new VolumeDataset(); dataset.datasetName = Path.GetFileName(filePath); dataset.filePath = filePath; dataset.dimX = dimX; dataset.dimY = dimY; dataset.dimZ = dimZ; // Skip header (if any) if (skipBytes > 0) { reader.ReadBytes(skipBytes); } int uDimension = dimX * dimY * dimZ; dataset.data = new float[uDimension]; // Read the data/sample values for (int i = 0; i < uDimension; i++) { dataset.data[i] = (float)ReadDataValue(reader); } Debug.Log("Loaded dataset in range: " + dataset.GetMinDataValue() + " - " + dataset.GetMaxDataValue()); reader.Close(); fs.Close(); dataset.FixDimensions(); return(dataset); }
public static Material CreateMaterialDVR(VolumeDataset dataset) { Shader shader = Shader.Find("VolumeRendering/DirectVolumeRenderingShader"); Material material = new Material(shader); const int noiseDimX = 512; const int noiseDimY = 512; Texture2D noiseTexture = NoiseTextureGenerator.GenerateNoiseTexture(noiseDimX, noiseDimY); material.SetTexture("_NoiseTex", noiseTexture); material.SetTexture("_DataTex", dataset.GetDataTexture()); return(material); }
private void OnOpenPARDatasetResult(RuntimeFileBrowser.DialogResult result) { if (!result.cancelled) { DespawnAllDatasets(); string filePath = result.path; ParDatasetImporter parimporter = new ParDatasetImporter(filePath); VolumeDataset dataset = parimporter.Import(); //overriden somewhere if (dataset != null) { VolumeObjectFactory.CreateObject(dataset); } } }
public static VolumeRenderedObject CreateObject(VolumeDataset dataset) { GameObject outerObject = new GameObject("VolumeRenderedObject_" + dataset.datasetName); VolumeRenderedObject volObj = outerObject.AddComponent <VolumeRenderedObject>(); GameObject meshContainer = GameObject.Instantiate((GameObject)Resources.Load("VolumeContainer")); meshContainer.transform.parent = outerObject.transform; meshContainer.transform.localScale = Vector3.one; meshContainer.transform.localPosition = Vector3.zero; meshContainer.transform.parent = outerObject.transform; outerObject.transform.localRotation = Quaternion.Euler(90.0f, 0.0f, 0.0f); MeshRenderer meshRenderer = meshContainer.GetComponent <MeshRenderer>(); meshRenderer.sharedMaterial = new Material(meshRenderer.sharedMaterial); volObj.meshRenderer = meshRenderer; volObj.dataset = dataset; const int noiseDimX = 512; const int noiseDimY = 512; Texture2D noiseTexture = NoiseTextureGenerator.GenerateNoiseTexture(noiseDimX, noiseDimY); TransferFunction tf = TransferFunctionDatabase.CreateTransferFunction(); Texture2D tfTexture = tf.GetTexture(); volObj.transferFunction = tf; TransferFunction2D tf2D = TransferFunctionDatabase.CreateTransferFunction2D(); volObj.transferFunction2D = tf2D; meshRenderer.sharedMaterial.SetTexture("_DataTex", dataset.GetDataTexture()); meshRenderer.sharedMaterial.SetTexture("_GradientTex", null); meshRenderer.sharedMaterial.SetTexture("_NoiseTex", noiseTexture); meshRenderer.sharedMaterial.SetTexture("_TFTex", tfTexture); meshRenderer.sharedMaterial.EnableKeyword("MODE_DVR"); meshRenderer.sharedMaterial.DisableKeyword("MODE_MIP"); meshRenderer.sharedMaterial.DisableKeyword("MODE_SURF"); if (dataset.scaleX != 0.0f && dataset.scaleY != 0.0f && dataset.scaleZ != 0.0f) { float maxScale = Mathf.Max(dataset.scaleX, dataset.scaleY, dataset.scaleZ); volObj.transform.localScale = new Vector3(dataset.scaleX / maxScale, dataset.scaleY / maxScale, dataset.scaleZ / maxScale); } return(volObj); }
private void ImportDataset() { DatasetImporterBase importer = new RawDatasetImporter(fileToImport, dimX, dimY, dimZ, dataFormat, endianness, bytesToSkip); VolumeDataset dataset = importer.Import(); if (dataset != null) { VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); } else { Debug.LogError("Failed to import datset"); } this.Close(); }
private void OnOpenDICOMDatasetResult(RuntimeFileBrowser.DialogResult result) { if (!result.cancelled) { // We'll only allow one dataset at a time in the runtime GUI (for simplicity) DespawnAllDatasets(); // Import the dataset DICOMImporter importer = new DICOMImporter(result.path, true); VolumeDataset dataset = importer.Import(); // Spawn the object if (dataset != null) { VolumeObjectFactory.CreateObject(dataset); } } }
/// <summary> /// Generates a histogram (but computaion is done on GPU) where: /// X-axis = the data sample (density) value /// Y-axis = the sample count (number of data samples with the specified density) /// </summary> /// <param name="dataset"></param> /// <returns></returns> public static Texture2D GenerateHistogramTextureOnGPU(VolumeDataset dataset) { double actualBound = dataset.GetMaxDataValue() - dataset.GetMinDataValue() + 1; int numValues = System.Convert.ToInt32(dataset.GetMaxDataValue() - dataset.GetMinDataValue() + 1); // removed +1 int sampleCount = System.Math.Min(numValues, 256); ComputeShader computeHistogram = Resources.Load("ComputeHistogram") as ComputeShader; int handleInitialize = computeHistogram.FindKernel("HistogramInitialize"); int handleMain = computeHistogram.FindKernel("HistogramMain"); ComputeBuffer histogramBuffer = new ComputeBuffer(sampleCount, sizeof(uint) * 1); uint[] histogramData = new uint[sampleCount]; Color32[] histogramCols = new Color32[sampleCount]; Texture3D dataTexture = dataset.GetDataTexture(); if (handleInitialize < 0 || handleMain < 0) { Debug.LogError("Histogram compute shader initialization failed."); } computeHistogram.SetFloat("ValueRange", (float)(numValues - 1)); computeHistogram.SetTexture(handleMain, "VolumeTexture", dataTexture); computeHistogram.SetBuffer(handleMain, "HistogramBuffer", histogramBuffer); computeHistogram.SetBuffer(handleInitialize, "HistogramBuffer", histogramBuffer); computeHistogram.Dispatch(handleInitialize, sampleCount / 8, 1, 1); computeHistogram.Dispatch(handleMain, (dataTexture.width + 7) / 8, (dataTexture.height + 7) / 8, (dataTexture.depth + 7) / 8); histogramBuffer.GetData(histogramData); int maxValue = (int)histogramData.Max(); Texture2D texture = new Texture2D(sampleCount, 1, TextureFormat.RGBA32, false); for (int iSample = 0; iSample < sampleCount; iSample++) { histogramCols[iSample] = new Color(Mathf.Log10((float)histogramData[iSample]) / Mathf.Log10((float)maxValue), 0.0f, 0.0f, 1.0f); } texture.SetPixels32(histogramCols); texture.Apply(); return(texture); }
static void ShowDICOMImporter() { string dir = EditorUtility.OpenFolderPanel("Select a folder to load", "", ""); if (Directory.Exists(dir)) { DICOMImporter importer = new DICOMImporter(dir, true); VolumeDataset dataset = importer.Import(); if (dataset != null) { VolumeObjectFactory.CreateObject(dataset); } } else { Debug.LogError("Directory doesn't exist: " + dir); } }
public VolumeDataset Import() { if (!Directory.Exists(directoryPath)) { throw new NullReferenceException("No directory found: " + directoryPath); } List <string> imagePaths = GetSortedImagePaths(); Vector3Int dimensions = GetVolumeDimensions(imagePaths); int[] data = FillSequentialData(dimensions, imagePaths); VolumeDataset dataset = FillVolumeDataset(data, dimensions); dataset.FixDimensions(); return(dataset); }
/// <summary> /// Wraps volume data into a VolumeDataset. /// </summary> /// <param name="data">Sequential value data for a volume.</param> /// <param name="dimensions">The XYZ dimensions of the volume.</param> /// <returns>The wrapped volume data.</returns> private VolumeDataset FillVolumeDataset(int[] data, Vector3Int dimensions) { string name = Path.GetFileName(directoryPath); VolumeDataset dataset = new VolumeDataset() { name = name, datasetName = name, data = Array.ConvertAll(data, new Converter <int, float>((int val) => { return(Convert.ToSingle(val)); })), dimX = dimensions.x, dimY = dimensions.y, dimZ = dimensions.z, scaleX = 1f, // Scale arbitrarily normalised around the x-axis scaleY = (float)dimensions.y / (float)dimensions.x, scaleZ = (float)dimensions.z / (float)dimensions.x }; return(dataset); }
/// <summary> /// Wraps volume data into a VolumeDataset. /// </summary> /// <param name="data">Sequential value data for a volume.</param> /// <param name="dimensions">The XYZ dimensions of the volume.</param> /// <returns>The wrapped volume data.</returns> private VolumeDataset FillVolumeDataset(int[] data, Vector3Int dimensions) { string name = Path.GetFileName(directoryPath); VolumeDataset dataset = new VolumeDataset() { name = name, datasetName = name, data = data, dimX = dimensions.x, dimY = dimensions.y, dimZ = dimensions.z, scaleX = 1f, // Scale arbitrarily normalised around the x-axis scaleY = (float)dimensions.y / (float)dimensions.x, scaleZ = (float)dimensions.z / (float)dimensions.x }; return(dataset); }
public static Texture2D Generate2DHistogramTexture(VolumeDataset dataset) { int numSamples = dataset.GetMaxDataValue() + 1; int numGradientSamples = 256; Color[] cols = new Color[numSamples * numGradientSamples]; Texture2D texture = new Texture2D(numSamples, numGradientSamples, TextureFormat.RGBAFloat, false); for (int iCol = 0; iCol < cols.Length; iCol++) { cols[iCol] = new Color(0.0f, 0.0f, 0.0f, 0.0f); } int maxRange = dataset.GetMaxDataValue() - dataset.GetMinDataValue(); const float maxNormalisedMagnitude = 1.75f; // sqrt(1^2 + 1^2 + 1^2) = swrt(3) = a bit less than 1.75 for (int x = 1; x < dataset.dimX - 1; x++) { for (int y = 1; y < dataset.dimY - 1; y++) { for (int z = 1; z < dataset.dimZ - 1; z++) { int iData = x + y * dataset.dimX + z * (dataset.dimX * dataset.dimY); int density = dataset.data[iData]; int x1 = dataset.data[(x + 1) + y * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; int x2 = dataset.data[(x - 1) + y * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; int y1 = dataset.data[x + (y + 1) * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; int y2 = dataset.data[x + (y - 1) * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; int z1 = dataset.data[x + y * dataset.dimX + (z + 1) * (dataset.dimX * dataset.dimY)]; int z2 = dataset.data[x + y * dataset.dimX + (z - 1) * (dataset.dimX * dataset.dimY)]; Vector3 grad = new Vector3((x2 - x1) / (float)maxRange, (y2 - y1) / (float)maxRange, (z2 - z1) / (float)maxRange); cols[density + (int)(grad.magnitude * numGradientSamples / maxNormalisedMagnitude) * numSamples] = Color.white; } } } texture.SetPixels(cols); texture.Apply(); return(texture); }
static void ShowDICOMImporter() { string dir = EditorUtility.OpenFolderPanel("Select a folder to load", "", ""); if (Directory.Exists(dir)) { bool recursive = true; // Read all files IEnumerable <string> fileCandidates = Directory.EnumerateFiles(dir, "*.*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly) .Where(p => p.EndsWith(".dcm", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicom", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicm", StringComparison.InvariantCultureIgnoreCase)); if (!fileCandidates.Any()) { #if UNITY_EDITOR if (UnityEditor.EditorUtility.DisplayDialog("Could not find any DICOM files", $"Failed to find any files with DICOM file extension.{Environment.NewLine}Do you want to include files without DICOM file extension?", "Yes", "No")) { fileCandidates = Directory.EnumerateFiles(dir, "*.*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); } #endif } if (fileCandidates.Any()) { DICOMImporter importer = new DICOMImporter(fileCandidates, Path.GetFileName(dir)); VolumeDataset dataset = importer.Import(); if (dataset != null) { VolumeObjectFactory.CreateObject(dataset); } } else { Debug.LogError("Could not find any DICOM files to import."); } } else { Debug.LogError("Directory doesn't exist: " + dir); } }
public override VolumeDataset Import() { if (!Directory.Exists(directoryPath)) { throw new NullReferenceException("No directory found: " + directoryPath); } List <string> imagePaths = GetSortedImagePaths(); if (!ImageSetHasUniformDimensions(imagePaths)) { throw new IndexOutOfRangeException("Image sequence has non-uniform dimensions"); } Vector3Int dimensions = GetVolumeDimensions(imagePaths); int[] data = FillSequentialData(dimensions, imagePaths); VolumeDataset dataset = FillVolumeDataset(data, dimensions); return(dataset); }
public static void ImportDataset(string filePath) { DatasetType datasetType = DatasetImporterUtility.GetDatasetType(filePath); switch (datasetType) { case DatasetType.Raw: { RAWDatasetImporterEditorWindow wnd = (RAWDatasetImporterEditorWindow)EditorWindow.GetWindow(typeof(RAWDatasetImporterEditorWindow)); if (wnd != null) { wnd.Close(); } wnd = new RAWDatasetImporterEditorWindow(filePath); wnd.Show(); break; } case DatasetType.DICOM: { string directoryPath = new FileInfo(filePath).Directory.FullName; // Find all DICOM files in directory IEnumerable <string> fileCandidates = Directory.EnumerateFiles(directoryPath, "*.*", SearchOption.TopDirectoryOnly) .Where(p => p.EndsWith(".dcm", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicom", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicm", StringComparison.InvariantCultureIgnoreCase)); DatasetImporterBase importer = new DICOMImporter(fileCandidates, Path.GetFileName(directoryPath)); VolumeDataset dataset = importer.Import(); if (dataset != null) { VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); } break; } } }
private void OnOpenDICOMDatasetResult(RuntimeFileBrowser.DialogResult result) { if (!result.cancelled) { // We'll only allow one dataset at a time in the runtime GUI (for simplicity) DespawnAllDatasets(); bool recursive = true; // Read all files IEnumerable <string> fileCandidates = Directory.EnumerateFiles(result.path, "*.*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly) .Where(p => p.EndsWith(".dcm", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicom", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicm", StringComparison.InvariantCultureIgnoreCase)); // Import the dataset DICOMImporter importer = new DICOMImporter(fileCandidates, Path.GetFileName(result.path)); VolumeDataset dataset = importer.Import(); // Spawn the object if (dataset != null) { VolumeObjectFactory.CreateObject(dataset); } } }
private void ImportDataset() { DatasetImporterBase importer = null; switch (datasetType) { case DatasetType.Raw: { importer = new RawDatasetImporter(fileToImport, dimX, dimY, dimZ, dataFormat, bytesToSkip); break; } case DatasetType.DICOM: { importer = new DICOMImporter(new FileInfo(fileToImport).Directory.FullName, false); break; } } VolumeDataset dataset = null; if (importer != null) { dataset = importer.Import(); } if (dataset != null) { VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); } else { Debug.LogError("Failed to import datset"); } this.Close(); }
/// <summary> /// Generates a histogram where: /// X-axis = the data sample (density) value /// Y-axis = the sample count (number of data samples with the specified density) /// </summary> /// <param name="dataset"></param> /// <returns></returns> public static Texture2D GenerateHistogramTexture(VolumeDataset dataset) { float minValue = dataset.GetMinDataValue(); float maxValue = dataset.GetMaxDataValue(); float valueRange = maxValue - minValue; int numFrequencies = Mathf.Min((int)valueRange, 1024); int[] frequencies = new int[numFrequencies]; int maxFreq = 0; float valRangeRecip = 1.0f / (maxValue - minValue); for (int iData = 0; iData < dataset.data.Length; iData++) { float dataValue = dataset.data[iData]; float tValue = (dataValue - minValue) * valRangeRecip; int freqIndex = (int)(tValue * (numFrequencies - 1)); frequencies[freqIndex] += 1; maxFreq = System.Math.Max(frequencies[freqIndex], maxFreq); } Color[] cols = new Color[numFrequencies]; Texture2D texture = new Texture2D(numFrequencies, 1, TextureFormat.RGBAFloat, false); for (int iSample = 0; iSample < numFrequencies; iSample++) { cols[iSample] = new Color(Mathf.Log10((float)frequencies[iSample]) / Mathf.Log10((float)maxFreq), 0.0f, 0.0f, 1.0f); } texture.SetPixels(cols); //texture.filterMode = FilterMode.Point; texture.Apply(); return(texture); }
public static VolumeRenderedObject CreateObject(VolumeDataset dataset) { GameObject obj = GameObject.Instantiate((GameObject)Resources.Load("VolumeRenderedObject")); VolumeRenderedObject volObj = obj.GetComponent <VolumeRenderedObject>(); MeshRenderer meshRenderer = obj.GetComponent <MeshRenderer>(); meshRenderer.material = new Material(meshRenderer.sharedMaterial); volObj.dataset = dataset; const int noiseDimX = 512; const int noiseDimY = 512; Texture2D noiseTexture = NoiseTextureGenerator.GenerateNoiseTexture(noiseDimX, noiseDimY); TransferFunction tf = TransferFunctionDatabase.CreateTransferFunction(); Texture2D tfTexture = tf.GetTexture(); volObj.transferFunction = tf; tf.histogramTexture = HistogramTextureGenerator.GenerateHistogramTexture(dataset); TransferFunction2D tf2D = TransferFunctionDatabase.CreateTransferFunction2D(); volObj.transferFunction2D = tf2D; meshRenderer.sharedMaterial.SetTexture("_DataTex", dataset.GetDataTexture()); meshRenderer.sharedMaterial.SetTexture("_GradientTex", null); meshRenderer.sharedMaterial.SetTexture("_NoiseTex", noiseTexture); meshRenderer.sharedMaterial.SetTexture("_TFTex", tfTexture); meshRenderer.sharedMaterial.EnableKeyword("MODE_DVR"); meshRenderer.sharedMaterial.DisableKeyword("MODE_MIP"); meshRenderer.sharedMaterial.DisableKeyword("MODE_SURF"); return(volObj); }
private void ImportDataset() { RawDatasetImporter importer = new RawDatasetImporter(fileToImport, dimX, dimY, dimZ, dataFormat, endianness, bytesToSkip); VolumeDataset dataset = importer.Import(); if (dataset != null) { if (EditorPrefs.GetBool("DownscaleDatasetPrompt")) { if (EditorUtility.DisplayDialog("Optional DownScaling", $"Do you want to downscale the dataset? The dataset's dimension is: {dataset.dimX} x {dataset.dimY} x {dataset.dimZ}", "Yes", "No")) { dataset.DownScaleData(); } } VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); } else { Debug.LogError("Failed to import datset"); } this.Close(); }
private void ImportDataset() { DatasetImporterBase importer = null; switch (datasetType) { case DatasetType.Raw: { importer = new RawDatasetImporter(fileToImport, dimX, dimY, dimZ, dataFormat, bytesToSkip); break; } case DatasetType.DICOM: { throw new System.NotImplementedException("TODO: implement support for DICOM files"); } } VolumeDataset dataset = null; if (importer != null) { dataset = importer.Import(); } if (dataset != null) { VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); } else { Debug.LogError("Failed to import datset"); } this.Close(); }