Example #1
0
        /// <summary>
        /// Converts a multi-label map to a set of binary volumes. If a voxel has value v in the
        /// input image, v >= 1, then the (v-1)th result volume will have set that voxel to 1.
        /// Put another way: The i.th result volume will have voxels non-zero wherever the input
        /// volume had value (i+1).
        /// </summary>
        /// <param name="image">A multi-label input volume.</param>
        /// <param name="numOutputMasks">The number of result volumes that will be generated.
        /// This value must be at least equal to the maximum voxel value in the input volume.</param>
        /// <returns></returns>
        public static Volume3D <byte>[] MultiLabelMapping(Volume3D <byte> image, int numOutputMasks)
        {
            var result = new Volume3D <byte> [numOutputMasks];

            for (var i = 0; i < numOutputMasks; i++)
            {
                result[i] = image.CreateSameSize <byte>();
            }

            for (var i = 0; i < image.Length; ++i)
            {
                if (image[i] != 0 && image[i] <= numOutputMasks)
                {
                    result[image[i] - 1][i] = 1;
                }
            }

            return(result);
        }
        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");
        }