/// <summary> /// Convert from Nifti format to DICOM-RT format. /// </summary> /// <param name="niftiFilename">Nifti input filename.</param> /// <param name="referenceSeries">Path to folder of reference DICOM files.</param> /// <param name="structureNames">Names for each structure.</param> /// <param name="structureColors">Colors for each structure, defaults to red if this array smaller than list of structures.</param> /// <param name="fillHoles">Flags to enable fill holes for each structure, defaults to false this array smaller than list of structures..</param> /// <param name="dcmFilename">Target output file.</param> public static void ConvertNiftiToDicom( string niftiFilename, string referenceSeries, string[] structureNames, RGBColorOption?[] structureColors, bool?[] fillHoles, ROIInterpretedType[] roiInterpretedTypes, string dcmFilename, string modelNameAndVersion, string manufacturer, string interpreter) { var sourceVolume = MedIO.LoadNiftiAsByte(niftiFilename); Trace.TraceInformation($"Loaded NIFTI from {niftiFilename}"); var labels = VolumeMetadataMapper.MultiLabelMapping(sourceVolume, structureNames.Length); var volumesWithMetadata = VolumeMetadataMapper.MapVolumeMetadata(labels, structureNames, structureColors, fillHoles, roiInterpretedTypes); var referenceVolume = DicomSeriesHelpers.LoadVolume( DicomFolderContents.Build( Directory.EnumerateFiles(referenceSeries).Select(x => DicomFileAndPath.SafeCreate(x)).ToList() )); var outputEncoder = new DicomRTStructOutputEncoder(); var outputStructureBytes = outputEncoder.EncodeStructures( volumesWithMetadata, new Dictionary <string, MedicalVolume>() { { "", referenceVolume } }, modelNameAndVersion, manufacturer, interpreter); File.WriteAllBytes(dcmFilename, outputStructureBytes.Array); }
public void RtStructOutputEncoder_SuccessWithValidInputs() { var labels = VolumeMetadataMapper.MultiLabelMapping(sourceVolume, NumValidLabels); var volumesWithMetadata = VolumeMetadataMapper.MapVolumeMetadata(labels, StructureNames, StructureColors, FillHoles, ROIInterpretedTypes); var referenceVolume = DicomSeriesHelpers.LoadVolume(DicomFolderContents.Build( Directory.EnumerateFiles(TestDicomVolumeLocation).Select(x => DicomFileAndPath.SafeCreate(x)).ToList() )); var outputEncoder = new DicomRTStructOutputEncoder(); var outputStructureBytes = outputEncoder.EncodeStructures( volumesWithMetadata, new Dictionary <string, MedicalVolume>() { { "", referenceVolume } }, "modelX:1", "manufacturer", "interpreter"); var dcm = DicomFile.Open(new MemoryStream(outputStructureBytes.Array)); // Check the output format (should be RT struct) Assert.AreEqual(DicomUID.RTStructureSetStorage, dcm.FileMetaInfo.MediaStorageSOPClassUID); // Check stuff in StructureSet ROI sequence var structSetRois = dcm.Dataset.GetSequence(DicomTag.StructureSetROISequence).Items; var iter = StructureNames.GetEnumerator(); iter.MoveNext(); var origReferencedFrameOfReference = referenceVolume.Identifiers.First().FrameOfReference.FrameOfReferenceUid; foreach (var roi in structSetRois) { // Verify that names in the generated DICOM Rt structure are the ones we've supplied Assert.AreEqual(iter.Current, roi.GetString(DicomTag.ROIName)); iter.MoveNext(); // Verify that this roi references the same frame of reference as the original image Assert.AreEqual(roi.GetString(DicomTag.ReferencedFrameOfReferenceUID), origReferencedFrameOfReference); } // Check stuff in ROI Contour sequence var roiContours = dcm.Dataset.GetSequence(DicomTag.ROIContourSequence).Items; var iterColors = 0; var sopInstanceUIDs = referenceVolume.Identifiers.Select(x => x.Image.SopCommon.SopInstanceUid); foreach (var contourSequence in roiContours) { // Verify that colors in the generated contour sequence are the ones we've supplied var currentColor = StructureColors[iterColors].Value; var currentColorString = string.Format("{0}\\{1}\\{2}", currentColor.R, currentColor.G, currentColor.B); Assert.AreEqual(contourSequence.GetString(DicomTag.ROIDisplayColor), currentColorString); iterColors++; // Verify that all contour types are closed planar Assert.IsTrue(contourSequence.GetSequence(DicomTag.ContourSequence).Items.All( x => x.GetString(DicomTag.ContourGeometricType) == "CLOSED_PLANAR")); // Verify that for all contours there exists a SOP Instance UID in the original series Assert.IsTrue(contourSequence.GetSequence(DicomTag.ContourSequence).Items.All( x => sopInstanceUIDs.Contains(x.GetSequence(DicomTag.ContourImageSequence).Items[0].GetString(DicomTag.ReferencedSOPInstanceUID)))); } }