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");
        }
Esempio n. 4
0
        /// <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);
        }