Esempio n. 1
0
 /// <summary>
 /// Save all images and the rt struct to the given folder.
 /// </summary>
 /// <param name="folderPath"></param>
 /// <param name="medicalVolume"></param>
 /// <returns></returns>
 public static async Task SaveMedicalVolumeAsync(
     string folderPath, MedicalVolume medicalVolume)
 {
     await Task.WhenAll(
         SaveDicomImageAsync(folderPath, medicalVolume),
         SaveRtStructAsync(Path.Combine(folderPath, "rtstruct.dcm"), medicalVolume.Struct));
 }
Esempio n. 2
0
 public VolumeLoaderResult(string seriesId, MedicalVolume volume, Exception error, IReadOnlyList <string> warnings)
 {
     SeriesUid = seriesId;
     Volume    = volume;
     Error     = error;
     Warnings  = warnings;
 }
        /// <summary>
        /// Converts a medical volume, scan files and a set of binary masks, into a Dicom representation.
        /// The returned set of Dicom files will have files for all slices of the scan, and an RtStruct
        /// file containing the contours that were derived from the masks. The RtStruct file will be the first
        /// entry in the returned list of Dicom files.
        /// Use with extreme care - many Dicom elements have to be halluzinated here, and there's no
        /// guarantee that the resulting Dicom will be usable beyond what is needed in InnerEye.
        /// </summary>
        /// <param name="medicalVolume">The medical scan.</param>
        /// <param name="scanFiles">The image modality through which the scan was acquired.</param>
        /// <param name="contours">A list of contours for individual anatomical structures, alongside
        /// <returns></returns>
        public static List <DicomFileAndPath> ScanAndContoursToDicom(
            MedicalVolume medicalVolume,
            IReadOnlyList <DicomFileAndPath> scanFiles,
            IReadOnlyList <ContourRenderingInformation> contours)
        {
            var rtFile     = ContoursToDicomRtFile(contours, medicalVolume.Identifiers, medicalVolume.Volume.Transform);
            var dicomFiles = new List <DicomFileAndPath> {
                rtFile
            };

            dicomFiles.AddRange(scanFiles);
            return(dicomFiles);
        }
Esempio n. 4
0
        /// <summary>
        /// Returns a task that saves a copy of the original DICOM files forming a medical volume.
        /// </summary>
        /// <param name="folderPath"></param>
        /// <param name="medicalVolume"></param>
        /// <returns></returns>
        private static async Task SaveDicomImageAsync(string folderPath, MedicalVolume medicalVolume)
        {
            await Task.Run(() =>
                           Parallel.ForEach(
                               medicalVolume.FilePaths,
                               file =>
            {
                if (!File.Exists(file))
                {
                    throw new FileNotFoundException(
                        $"The original dicom directory was modified while using this image. File {file} is missing");
                }

                // ReSharper disable once AssignNullToNotNullAttribute
                var destFile = Path.Combine(folderPath, Path.GetFileName(file));
                File.Copy(file, destFile);
            }));
        }
Esempio n. 5
0
        /// <summary>
        /// Attempt to load a volume from the given SeriesUID for the given DicomFolderContents
        /// </summary>
        /// <param name="dfc">A pre-built description of DICOM contents within a particular folder</param>
        /// <param name="seriesUID">The DICOM seriesUID you wish to construct a volume for</param>
        /// <param name="acceptanceTests">An implementation of IVolumeGeometricAcceptanceTest defining the geometric constraints of your application</param>
        /// <param name="loadStructuresIfExists">True if rt-structures identified in the folder and referencing seriesUID should be loaded</param>
        /// <param name="supportLossyCodecs">If you wish to accept lossy encodings of image pixel data</param>
        /// <returns></returns>
        private static VolumeLoaderResult LoadDicomSeries(
            DicomFolderContents dfc, DicomUID seriesUID, IVolumeGeometricAcceptanceTest acceptanceTests, bool loadStructuresIfExists, bool supportLossyCodecs)
        {
            try
            {
                var dicomSeriesContent = dfc.Series.FirstOrDefault((s) => s.SeriesUID == seriesUID);

                var warnings = new List <string>();
                RadiotherapyStruct rtStruct = null;

                if (dicomSeriesContent != null)
                {
                    var volumeData = DicomSeriesReader.BuildVolume(dicomSeriesContent.Content.Select(x => x.File.Dataset), acceptanceTests, supportLossyCodecs);

                    if (volumeData != null && loadStructuresIfExists)
                    {
                        var rtStructData = dfc.RTStructs.FirstOrDefault(rt => rt.SeriesUID == seriesUID);
                        if (rtStructData != null)
                        {
                            if (rtStructData.Content.Count == 1)
                            {
                                var rtStructAndWarnings = RtStructReader.LoadContours(
                                    rtStructData.Content.First().File.Dataset,
                                    volumeData.Transform.DicomToData,
                                    seriesUID.UID,
                                    null,
                                    false);

                                rtStruct = rtStructAndWarnings.Item1;

                                var warning = rtStructAndWarnings.Item2;

                                if (!string.IsNullOrEmpty(warning))
                                {
                                    warnings.Add(warning);
                                }
                            }
                            else if (rtStructData.Content.Count > 1)
                            {
                                warnings.Add("There is more than 1 RT STRUCT referencing this series - skipping structure set load");
                            }
                        }
                    }
                    var dicomIdentifiers = dicomSeriesContent.Content.Select((v) => DicomIdentifiers.ReadDicomIdentifiers(v.File.Dataset)).ToArray();

                    if (rtStruct == null)
                    {
                        rtStruct = RadiotherapyStruct.CreateDefault(dicomIdentifiers);
                    }

                    var result = new MedicalVolume(
                        volumeData,
                        dicomIdentifiers,
                        dicomSeriesContent.Content.Select((d) => d.Path).ToArray(),
                        rtStruct);

                    return(new VolumeLoaderResult(seriesUID.UID, result, null, warnings));
                }
                throw new Exception("Could not find that series");
            }
            catch (Exception oops)
            {
                return(new VolumeLoaderResult(seriesUID.UID, null, oops, new List <string>()));
            }
        }