public void SanitizeDicomLongStringTest() { var testCases = new List <(bool IsValidAlready, string Text, string Expected)> { (false, "12\\34", "12/34"), (true, "abcd/efg", "abcd/efg"), (true, null, null), (false, new string('a', NiiToDicomHelpers.MaxDicomLongStringLength * 2), new string('a', NiiToDicomHelpers.MaxDicomLongStringLength)) }; foreach (var(isValidAlready, text, expected) in testCases) { Assert.AreEqual(isValidAlready, NiiToDicomHelpers.IsValidDicomLongString(text), $"Validity check before conversion on {text}"); var actual = NiiToDicomHelpers.SanitizeDicomLongString(text); Assert.IsTrue(NiiToDicomHelpers.IsValidDicomLongString(actual), $"Should be valid after conversion on {text}"); Assert.AreEqual(expected, actual, "Conversion result does not match expected"); } }
public void MaskToContourCheck(int trueForeground, int renderedForeground, int?maxAbsoluteDifference, double?maxRelativeDifference, bool isAccepted) { if (isAccepted) { NiiToDicomHelpers.CheckContourRendering(trueForeground, renderedForeground, maxAbsoluteDifference, maxRelativeDifference, string.Empty); } else { var messagePrefix = "foo"; var exception = Assert.Throws <InvalidOperationException>(() => NiiToDicomHelpers.CheckContourRendering(trueForeground, renderedForeground, maxAbsoluteDifference, maxRelativeDifference, messagePrefix)); Assert.IsTrue(exception.Message.Contains(messagePrefix)); } }
public void VolumeToDicomAndBack() { var outputFolder = Path.Combine(TestContext.CurrentContext.TestDirectory, "DicomOutput"); if (Directory.Exists(outputFolder)) { Directory.Delete(outputFolder, recursive: true); Thread.Sleep(1000); } Directory.CreateDirectory(outputFolder); var scan = new Volume3D <short>(5, 5, 5); foreach (var index in scan.Array.Indices()) { scan.Array[index] = (short)index; } // Create 3 structures, each with a different color var masks = new List <ContourRenderingInformation>(); var colors = new[] { new RGBColor(255, 0, 0), new RGBColor(0, 255, 0), new RGBColor(0, 0, 255), }; foreach (var index in Enumerable.Range(0, 3)) { var mask = scan.CreateSameSize <byte>(); mask[index + 1, index + 1, index + 1] = 1; masks.Add(new ContourRenderingInformation($"structure_{index}", colors[index], mask)); } var seriesDescription = "description"; var patientId = DicomUID.Generate().UID; var studyId = DicomUID.Generate().UID; var dicomFiles = NiiToDicomHelpers.ScanAndContoursToDicom(scan, ImageModality.CT, masks, seriesDescription, patientId, studyId); // Write to disk, so that we can load it into the App as well var dicomFilesOnDisk = new List <string>(); foreach (var dicomFile in dicomFiles) { dicomFilesOnDisk.Add(dicomFile.SaveToFolder(outputFolder)); } // Test if the first returned Dicom file is really the RTStruct var rtStructFromFile = RtStructReader.LoadContours(dicomFilesOnDisk[0], scan.Transform.DicomToData); Assert.IsNotNull(rtStructFromFile); Assert.AreEqual(masks.Count, rtStructFromFile.Item1.Contours.Count); var fromDisk = NiiToDicomHelpers.MedicalVolumeFromDicomFolder(outputFolder); VolumeAssert.AssertVolumesMatch(scan, fromDisk.Volume, "Loaded scan does not match"); Assert.AreEqual(seriesDescription, fromDisk.Identifiers.First().Series.SeriesDescription); Assert.AreEqual(patientId, fromDisk.Identifiers.First().Patient.Id); Assert.AreEqual(studyId, fromDisk.Identifiers.First().Study.StudyInstanceUid); foreach (var index in Enumerable.Range(0, fromDisk.Struct.Contours.Count)) { var loadedMask = fromDisk.Struct.Contours[index].Contours.ToVolume3D(scan); VolumeAssert.AssertVolumesMatch(masks[index].Contour.ToVolume3D(scan), loadedMask, $"Loaded mask {index}"); Assert.AreEqual(masks[index].Name, fromDisk.Struct.Contours[index].StructureSetRoi.RoiName, $"Loaded mask name {index}"); } // Now test if we can ZIP up all the Dicom files, and read them back in. var zippedDicom = ZippedDicom.DicomFilesToZipArchive(dicomFiles); var dicomFromZip = ZippedDicom.DicomFilesFromZipArchive(zippedDicom); var volumeFromZip = NiiToDicomHelpers.MedicalVolumeFromDicom(dicomFromZip.ToList()); VolumeAssert.AssertVolumesMatch(scan, volumeFromZip.Volume, "Scan from Zip archive does not match"); Assert.AreEqual(masks.Count, volumeFromZip.Struct.Contours.Count, "RtStructs from Zip do not match"); }
/// <summary> /// Common code for planar Nifti to DICOM-RT tests. /// </summary> /// <param name="sourceMaskFilename">Source mask filename.</param> /// <param name="expectedMaskFilename">Optional expected mask filename if not the same as source.</param> /// <param name="fillHoles">Fill holes flag.</param> /// <param name="debugFolderName">Optional folder name for debug images.</param> public static void CommonTestNiftiToDicomFillHoles(string sourceMaskFilename, string expectedMaskFilename, bool?fillHoles, string debugFolderName) { // Create the Nifti file as a NxMx1 volume var sourceMaskVolume2D = ExtractContourTests.LoadMask(sourceMaskFilename); Assert.IsTrue(sourceMaskVolume2D.Array.Any(x => x == 0)); Assert.IsTrue(sourceMaskVolume2D.Array.Any(x => x == 1)); var dimZ = 2; var sourceVolume3D = sourceMaskVolume2D.Extrude(dimZ, 1.0); var niftiFile = TestHelpers.CreateTempNiftiName(NiftiCompression.GZip); MedIO.SaveNifti(sourceVolume3D, niftiFile); // Create the reference DICOM files. var referenceDicomFolder = Path.Combine(TestContext.CurrentContext.TestDirectory, "ReferenceDicom"); if (Directory.Exists(referenceDicomFolder)) { Directory.Delete(referenceDicomFolder, recursive: true); Thread.Sleep(1000); } Directory.CreateDirectory(referenceDicomFolder); var scan = new Volume3D <short>(sourceVolume3D.DimX, sourceVolume3D.DimY, sourceVolume3D.DimZ); foreach (var index in scan.Array.Indices()) { scan.Array[index] = (short)index; } var seriesDescription = "description"; var patientID = DicomUID.Generate().UID; var studyInstanceID = DicomUID.Generate().UID; var dicomFiles = NiiToDicomHelpers.ScanToDicomInMemory(scan, ImageModality.CT, seriesDescription, patientID, studyInstanceID, null); var dicomFilesOnDisk = new List <string>(); foreach (var dicomFile in dicomFiles) { dicomFilesOnDisk.Add(dicomFile.SaveToFolder(referenceDicomFolder)); } // Turn the expected mask into a volume. var expectedNiftiFile = string.Empty; if (!string.IsNullOrEmpty(expectedMaskFilename)) { var expectedMask = ExtractContourTests.LoadMask(expectedMaskFilename); var expectedVolume = expectedMask.Extrude(dimZ, 1.0); expectedNiftiFile = TestHelpers.CreateTempNiftiName(NiftiCompression.GZip); MedIO.SaveNifti(expectedVolume, expectedNiftiFile); } else { // Expected is the same as the source. expectedNiftiFile = niftiFile; } DoTestNiftiToDicom( niftiFile, referenceDicomFolder, new[] { "background", "foreground" }, new RGBColorOption?[] { new RGBColorOption(0xFF, 0x00, 0x00), new RGBColorOption(0x00, 0xFF, 0x00) }, new[] { fillHoles, fillHoles }, new[] { ROIInterpretedType.ORGAN, ROIInterpretedType.CTV }, debugFolderName, true, expectedNiftiFile); }