Пример #1
0
        /// <summary>
        /// Gets the VOI data LUTs for specified frame.
        /// </summary>
        /// <param name="frameNumber"></param>
        /// <returns></returns>
        internal IList <VoiDataLut> GetFrameVoiDataLuts(int frameNumber)
        {
            Platform.CheckPositive(frameNumber, "frameNumber");

            lock (_syncLock)
            {
                var cacheKey = VoiDataLutsCacheKey.RootKey;
                var dataset  = (IDicomAttributeProvider)DataSource;

                // attempt to find the VOI LUT Sequence in a functional group pertaining to the requested frame
                FunctionalGroupDescriptor functionalGroupDescriptor;
                if (_functionalGroups != null && _functionalGroups.TryGetValue(DicomTags.VoiLutSequence, out functionalGroupDescriptor))
                {
                    bool perFrame;
                    var  functionalGroup = MultiFrameFunctionalGroupsModuleIod.GetFunctionalGroup(functionalGroupDescriptor, DataSource, frameNumber, out perFrame);
                    var  item            = functionalGroup != null ? functionalGroup.SingleItem : null;

                    DicomAttribute dicomAttribute;
                    if (item != null && item.TryGetAttribute(DicomTags.VoiLutSequence, out dicomAttribute))
                    {
                        cacheKey = perFrame ? VoiDataLutsCacheKey.GetFrameKey(frameNumber) : VoiDataLutsCacheKey.SharedKey;
                        dataset  = item;
                    }
                }

                IList <VoiDataLut> dataLuts;
                if (!_frameVoiDataLuts.TryGetValue(cacheKey, out dataLuts))
                {
                    _frameVoiDataLuts.Add(cacheKey, dataLuts = CreateVoiDataLuts(dataset));
                }
                return(dataLuts);
            }
        }
        /// <summary>
        /// Directly gets Per Frame ReferencedSegmentNumber without creating the full PerFrameFunctionalGroupsSequence[] collection.
        /// </summary>
        /// <param name="multiFrameFunctionalGroupsModuleIod"><see cref="MultiFrameFunctionalGroupsModuleIod"/> of the segmentation IOD</param>
        /// <param name="frameIndex">frame index (0-based)</param>
        /// <returns>ReferencedSegmentNumber or -1</returns>
        private static int GetPerFrameReferencedSegmentNumber(MultiFrameFunctionalGroupsModuleIod multiFrameFunctionalGroupsModuleIod, int frameIndex)
        {
            var dicomAttribute = multiFrameFunctionalGroupsModuleIod.DicomAttributeProvider[DicomTags.PerFrameFunctionalGroupsSequence];

            if (dicomAttribute.IsNull || dicomAttribute.IsEmpty || frameIndex >= dicomAttribute.Count)
            {
                return(-1);
            }

            var perFrameFunctionalGroupsSequenceItem = ((DicomSequenceItem[])dicomAttribute.Values)[frameIndex];

            if (perFrameFunctionalGroupsSequenceItem != null)
            {
                var dicomAttr1 = perFrameFunctionalGroupsSequenceItem.GetAttribute(DicomTags.SegmentIdentificationSequence);
                if (!dicomAttr1.IsNull && !dicomAttr1.IsEmpty)
                {
                    var segmentIdentificationSequenceItem = ((DicomSequenceItem[])dicomAttr1.Values)[0];
                    var dicomAttr2 = segmentIdentificationSequenceItem.GetAttribute(DicomTags.ReferencedSegmentNumber);
                    if (!dicomAttr2.IsNull && !dicomAttr2.IsEmpty)
                    {
                        return(dicomAttr2.GetInt32(0, -1));
                    }
                }
            }
            return(-1);
        }
        /// <summary>
        /// Directly gets Per Frame <see cref="FunctionalGroupsSequenceItem"/> count without creating the full PerFrameFunctionalGroupsSequence[] collection.
        /// </summary>
        /// <param name="multiFrameFunctionalGroupsModuleIod"><see cref="MultiFrameFunctionalGroupsModuleIod"/> of the segmentation IOD</param>
        /// <returns></returns>
        private static long GetNumberOfPerFrameFinctionalGroupsSequenceItems(MultiFrameFunctionalGroupsModuleIod multiFrameFunctionalGroupsModuleIod)
        {
            var dicomAttribute = multiFrameFunctionalGroupsModuleIod.DicomAttributeProvider[DicomTags.PerFrameFunctionalGroupsSequence];

            if (dicomAttribute.IsNull || dicomAttribute.IsEmpty)
            {
                return(-1);
            }

            return(dicomAttribute.Count);
        }
Пример #4
0
        private DicomAttribute GetFrameAttributeCore(int frameNumber, uint tag)
        {
            FunctionalGroupDescriptor functionalGroupDescriptor;

            if (frameNumber > 0 && _functionalGroups != null && _functionalGroups.TryGetValue(tag, out functionalGroupDescriptor))
            {
                DicomAttribute dicomAttribute;
                var            functionalGroup = MultiFrameFunctionalGroupsModuleIod.GetFunctionalGroup(functionalGroupDescriptor, DataSource, frameNumber);
                var            item            = functionalGroup != null ? functionalGroup.SingleItem : null;
                if (item != null && item.TryGetAttribute(tag, out dicomAttribute))
                {
                    return(dicomAttribute);
                }
            }
            return(null);
        }
Пример #5
0
 public SegmentationDocumentIod(IDicomAttributeProvider dicomAttributeProvider)
 {
     _dicomAttributeProvider     = dicomAttributeProvider;
     _patientModule              = new PatientModuleIod(_dicomAttributeProvider);
     _clinicalTrialSubjectModule = new ClinicalTrialSubjectModuleIod(_dicomAttributeProvider);
     _generalStudyModule         = new GeneralStudyModuleIod(_dicomAttributeProvider);
     _patientStudyModule         = new PatientStudyModuleIod(_dicomAttributeProvider);
     _clinicalTrialStudyModule   = new ClinicalTrialStudyModuleIod(_dicomAttributeProvider);
     _generalSeriesModule        = new GeneralSeriesModuleIod(_dicomAttributeProvider);
     _segmentationSeriesModule   = new SegmentationSeriesModuleIod(_dicomAttributeProvider);
     _clinicalTrialSeriesModule  = new ClinicalTrialSeriesModuleIod(_dicomAttributeProvider);
     _frameOfReferenceModule     = new FrameOfReferenceModuleIod(_dicomAttributeProvider);
     _generalEquipmentModule     = new GeneralEquipmentModuleIod(_dicomAttributeProvider);
     //_enhanceGeneralEquipmentModule = new EnhanceGeneralEquipmentModuleIod(_dicomAttributeProvider);
     _generalImageModule               = new GeneralImageModuleIod(_dicomAttributeProvider);
     _imagePixelModule                 = new ImagePixelMacroIod(_dicomAttributeProvider);
     _segmentationImageModule          = new SegmentationImageModuleIod(_dicomAttributeProvider);
     _multiFrameFunctionalGroupsModule = new MultiFrameFunctionalGroupsModuleIod(_dicomAttributeProvider);
     _multiFrameDimensionModule        = new MultiFrameDimensionModuleIod(_dicomAttributeProvider);
     _specimenModule = new SpecimenModuleIod(_dicomAttributeProvider);
     _commonInstanceReferenceModule = new CommonInstanceReferenceModuleIod(_dicomAttributeProvider);
     _sopCommonModule       = new SopCommonModuleIod(_dicomAttributeProvider);
     _frameExtractionModule = new FrameExtractionModuleIod(_dicomAttributeProvider);
 }
        public void TestSeriesSplittingEnhancedMREcho()
        {
            const int             numberOfSeries     = 2;
            const int             instancesPerSeries = 3;
            const int             framesPerInstance  = 10;
            List <TestDataSource> dataSources        = CreateMRStudyDataSources(numberOfSeries, instancesPerSeries, "1.2.3");

            foreach (var dicomFile in dataSources.Select(d => d.File))
            {
                dicomFile.DataSet[DicomTags.NumberOfFrames].SetInt32(0, framesPerInstance);

                if (dicomFile.DataSet[DicomTags.SeriesNumber].GetInt32(0, 0) != 2)
                {
                    continue;
                }

                var dimUid    = "1.2.3.4.5";
                var mfdModule = new MultiFrameDimensionModuleIod(dicomFile.DataSet);
                mfdModule.DimensionOrganizationSequence = new[] { new DimensionOrganizationSequenceItem {
                                                                      DimensionOrganizationUid = dimUid
                                                                  } };
                mfdModule.DimensionIndexSequence = new[]
                {
                    new DimensionIndexSequenceItem {
                        DimensionIndexPointer = DicomTags.StackId, FunctionalGroupPointer = DicomTags.FrameContentSequence, DimensionOrganizationUid = dimUid
                    },
                    new DimensionIndexSequenceItem {
                        DimensionIndexPointer = DicomTags.InStackPositionNumber, FunctionalGroupPointer = DicomTags.FrameContentSequence, DimensionOrganizationUid = dimUid
                    },
                    new DimensionIndexSequenceItem {
                        DimensionIndexPointer = DicomTags.EffectiveEchoTime, FunctionalGroupPointer = DicomTags.MrEchoSequence, DimensionOrganizationUid = dimUid
                    }
                };
                var mffgModule = new MultiFrameFunctionalGroupsModuleIod(dicomFile.DataSet);
                mffgModule.PerFrameFunctionalGroupsSequence = Enumerable.Range(0, framesPerInstance).Select(i =>
                {
                    var fg = new FunctionalGroupsSequenceItem();
                    ushort inStackPositionNumber = (ushort)(i % 5 + 1);
                    ushort echoNumber            = (ushort)(i / 5 + 1);
                    fg.GetFunctionalGroup <FrameContentFunctionalGroup>().FrameContentSequence = new FrameContentSequenceItem {
                        InStackPositionNumber = inStackPositionNumber, StackId = "1", DimensionIndexValues = new uint[] { 1, inStackPositionNumber, echoNumber }
                    };
                    fg.GetFunctionalGroup <MrEchoFunctionalGroup>().MrEchoSequence = new MrEchoSequenceItem {
                        EffectiveEchoTime = echoNumber + 5 / 1000f
                    };
                    return(fg);
                }).ToArray();
            }

            StudyTree studyTree = CreateStudyTree(ConvertToSops(dataSources));

            MREchoDisplaySetFactory factory = new MREchoDisplaySetFactory();

            factory.SetStudyTree(studyTree);
            List <IDisplaySet> allDisplaySets = new List <IDisplaySet>();

            try
            {
                Patient patient = studyTree.Patients[0];
                Study   study   = patient.Studies[0];

                Assert.AreEqual(numberOfSeries, study.Series.Count, "There should be exactly {0} series", numberOfSeries);

                Series series2 = study.Series[1];

                foreach (Series series in study.Series)
                {
                    Assert.AreEqual(instancesPerSeries, series.Sops.Count, "There should be exactly {0} sops", instancesPerSeries);
                    List <IDisplaySet> displaySets = factory.CreateDisplaySets(series);
                    allDisplaySets.AddRange(displaySets);

                    if (series == series2)
                    {
                        Assert.AreEqual(2, displaySets.Count, "There should be exactly 4 display sets");

                        IDisplaySet displaySet = displaySets[0];
                        Assert.AreEqual(series.Sops.Count * framesPerInstance / 2, displaySet.PresentationImages.Count, "#presentation images should be #Sops/2");
                        Assert.AreNotEqual(series.SeriesInstanceUid, displaySet.Descriptor.Uid, "Series UID and Display Set UID don't match");
                        Assert.AreEqual(typeof(MREchoDisplaySetDescriptor), displaySet.Descriptor.GetType(), "Wrong display set descriptor type");
                        Assert.IsTrue(displaySet.Name.Contains("Echo"), "Display Set name not correct");

                        ValidateMultiframeEchoDisplaySet(displaySets[0], 1);
                        ValidateMultiframeEchoDisplaySet(displaySets[1], 2);
                    }
                    else
                    {
                        //Assert.AreEqual(0, displaySets.Count, "There should be no display sets");
                    }
                }
            }
            finally
            {
                foreach (IDisplaySet displaySet in allDisplaySets)
                {
                    displaySet.Dispose();
                }

                studyTree.Dispose();
            }
        }
 public SegmentationDocumentIod(IDicomAttributeProvider dicomAttributeProvider)
 {
     _dicomAttributeProvider = dicomAttributeProvider;
     _patientModule = new PatientModuleIod(_dicomAttributeProvider);
     _clinicalTrialSubjectModule = new ClinicalTrialSubjectModuleIod(_dicomAttributeProvider);
     _generalStudyModule = new GeneralStudyModuleIod(_dicomAttributeProvider);
     _patientStudyModule = new PatientStudyModuleIod(_dicomAttributeProvider);
     _clinicalTrialStudyModule = new ClinicalTrialStudyModuleIod(_dicomAttributeProvider);
     _generalSeriesModule = new GeneralSeriesModuleIod(_dicomAttributeProvider);
     _segmentationSeriesModule = new SegmentationSeriesModuleIod(_dicomAttributeProvider);
     _clinicalTrialSeriesModule = new ClinicalTrialSeriesModuleIod(_dicomAttributeProvider);
     _frameOfReferenceModule = new FrameOfReferenceModuleIod(_dicomAttributeProvider);
     _generalEquipmentModule = new GeneralEquipmentModuleIod(_dicomAttributeProvider);
     //_enhanceGeneralEquipmentModule = new EnhanceGeneralEquipmentModuleIod(_dicomAttributeProvider);
     _generalImageModule = new GeneralImageModuleIod(_dicomAttributeProvider);
     _imagePixelModule = new ImagePixelMacroIod(_dicomAttributeProvider);
     _segmentationImageModule = new SegmentationImageModuleIod(_dicomAttributeProvider);
     _multiFrameFunctionalGroupsModule = new MultiFrameFunctionalGroupsModuleIod(_dicomAttributeProvider);
     _multiFrameDimensionModule = new MultiFrameDimensionModuleIod(_dicomAttributeProvider);
     _specimenModule = new SpecimenModuleIod(_dicomAttributeProvider);
     _commonInstanceReferenceModule = new CommonInstanceReferenceModuleIod(_dicomAttributeProvider);
     _sopCommonModule = new SopCommonModuleIod(_dicomAttributeProvider);
     _frameExtractionModule = new FrameExtractionModuleIod(_dicomAttributeProvider);
 }
		public void TestSeriesSplittingEnhancedMREcho()
		{
			const int numberOfSeries = 2;
			const int instancesPerSeries = 3;
			const int framesPerInstance = 10;
			List<TestDataSource> dataSources = CreateMRStudyDataSources(numberOfSeries, instancesPerSeries, "1.2.3");

			foreach (var dicomFile in dataSources.Select(d => d.File))
			{
				dicomFile.DataSet[DicomTags.NumberOfFrames].SetInt32(0, framesPerInstance);

				if (dicomFile.DataSet[DicomTags.SeriesNumber].GetInt32(0, 0) != 2) continue;

				var dimUid = "1.2.3.4.5";
				var mfdModule = new MultiFrameDimensionModuleIod(dicomFile.DataSet);
				mfdModule.DimensionOrganizationSequence = new[] {new DimensionOrganizationSequenceItem {DimensionOrganizationUid = dimUid}};
				mfdModule.DimensionIndexSequence = new[]
				                                   	{
				                                   		new DimensionIndexSequenceItem {DimensionIndexPointer = DicomTags.StackId, FunctionalGroupPointer = DicomTags.FrameContentSequence, DimensionOrganizationUid = dimUid},
				                                   		new DimensionIndexSequenceItem {DimensionIndexPointer = DicomTags.InStackPositionNumber, FunctionalGroupPointer = DicomTags.FrameContentSequence, DimensionOrganizationUid = dimUid},
				                                   		new DimensionIndexSequenceItem {DimensionIndexPointer = DicomTags.EffectiveEchoTime, FunctionalGroupPointer = DicomTags.MrEchoSequence, DimensionOrganizationUid = dimUid}
				                                   	};
				var mffgModule = new MultiFrameFunctionalGroupsModuleIod(dicomFile.DataSet);
				mffgModule.PerFrameFunctionalGroupsSequence = Enumerable.Range(0, framesPerInstance).Select(i =>
				                                                                                            	{
				                                                                                            		var fg = new FunctionalGroupsSequenceItem();
				                                                                                            		ushort inStackPositionNumber = (ushort) (i%5 + 1);
				                                                                                            		ushort echoNumber = (ushort) (i/5 + 1);
				                                                                                            		fg.GetFunctionalGroup<FrameContentFunctionalGroup>().FrameContentSequence = new FrameContentSequenceItem {InStackPositionNumber = inStackPositionNumber, StackId = "1", DimensionIndexValues = new uint[] {1, inStackPositionNumber, echoNumber}};
				                                                                                            		fg.GetFunctionalGroup<MrEchoFunctionalGroup>().MrEchoSequence = new MrEchoSequenceItem {EffectiveEchoTime = echoNumber + 5/1000f};
				                                                                                            		return fg;
				                                                                                            	}).ToArray();
			}

			StudyTree studyTree = CreateStudyTree(ConvertToSops(dataSources));

			MREchoDisplaySetFactory factory = new MREchoDisplaySetFactory();
			factory.SetStudyTree(studyTree);
			List<IDisplaySet> allDisplaySets = new List<IDisplaySet>();

			try
			{
				Patient patient = studyTree.Patients[0];
				Study study = patient.Studies[0];

				Assert.AreEqual(numberOfSeries, study.Series.Count, "There should be exactly {0} series", numberOfSeries);

				Series series2 = study.Series[1];

				foreach (Series series in study.Series)
				{
					Assert.AreEqual(instancesPerSeries, series.Sops.Count, "There should be exactly {0} sops", instancesPerSeries);
					List<IDisplaySet> displaySets = factory.CreateDisplaySets(series);
					allDisplaySets.AddRange(displaySets);

					if (series == series2)
					{
						Assert.AreEqual(2, displaySets.Count, "There should be exactly 4 display sets");

						IDisplaySet displaySet = displaySets[0];
						Assert.AreEqual(series.Sops.Count*framesPerInstance/2, displaySet.PresentationImages.Count, "#presentation images should be #Sops/2");
						Assert.AreNotEqual(series.SeriesInstanceUid, displaySet.Descriptor.Uid, "Series UID and Display Set UID don't match");
						Assert.AreEqual(typeof (MREchoDisplaySetDescriptor), displaySet.Descriptor.GetType(), "Wrong display set descriptor type");
						Assert.IsTrue(displaySet.Name.Contains("Echo"), "Display Set name not correct");

						ValidateMultiframeEchoDisplaySet(displaySets[0], 1);
						ValidateMultiframeEchoDisplaySet(displaySets[1], 2);
					}
					else
					{
						//Assert.AreEqual(0, displaySets.Count, "There should be no display sets");
					}
				}
			}
			finally
			{
				foreach (IDisplaySet displaySet in allDisplaySets)
					displaySet.Dispose();

				studyTree.Dispose();
			}
		}
        /// <summary>
        /// Directly gets Per Frame <see cref="FunctionalGroupsSequenceItem"/> without creating the full PerFrameFunctionalGroupsSequence[] collection.
        /// </summary>
        /// <param name="multiFrameFunctionalGroupsModuleIod"><see cref="MultiFrameFunctionalGroupsModuleIod"/> of the segmentation IOD</param>
        /// <param name="frameIndex">frame index (0-based)</param>
        /// <returns>PerFrameFunctionalGroupsSequenceItem for the requested frame</returns>
        private static FunctionalGroupsSequenceItem GetPerFrameFunctionalGroupsSequenceItem(MultiFrameFunctionalGroupsModuleIod multiFrameFunctionalGroupsModuleIod,
                                                                                            int frameIndex)
        {
            var dicomAttribute = multiFrameFunctionalGroupsModuleIod.DicomAttributeProvider[DicomTags.PerFrameFunctionalGroupsSequence];

            if (dicomAttribute.IsNull || dicomAttribute.IsEmpty || frameIndex >= dicomAttribute.Count)
            {
                return(null);
            }

            var item = ((DicomSequenceItem[])dicomAttribute.Values)[frameIndex];

            return(new FunctionalGroupsSequenceItem(item));
        }
        /// <summary>
        /// Gets the functional group sequence item for a particular tag in the data set (i.e. the parent sequence item containing the requested tag).
        /// </summary>
        /// <remarks>
        /// <para>
        /// If the requested tag is the root sequence tag of a functional group (e.g. <see cref="DicomTags.PatientOrientationInFrameSequence"/>),
        /// the returned sequence item will be the functional group sequence item for the frame in which the requested attribute can be found.
        /// </para>
        /// <para>
        /// If the requested tag is a nested tag of a functional group and the root sequence tag allows only one sequence item
        /// (e.g. <see cref="DicomTags.PatientOrientation"/> as a nested tag of <see cref="DicomTags.PatientOrientationInFrameSequence"/>),
        /// the returned sequence item will be the single sequence item in the root sequence attribute.
        /// </para>
        /// <para>
        /// It is not possible to directly access a nested tag of a functional group if the root sequence tag allows multiple sequence items
        /// (e.g. <see cref="DicomTags.RadiopharmaceuticalAgentNumber"/> as a nested tag of <see cref="DicomTags.RadiopharmaceuticalUsageSequence"/>).
        /// To do so, access the <see cref="DicomTags.RadiopharmaceuticalUsageSequence"/> and handle the sequence items individually.
        /// </para>
        /// </remarks>
        /// <param name="frameNumber">DICOM frame number (first frame is 1).</param>
        /// <param name="tag">DICOM tag of the attribute.</param>
        /// <param name="isFrameSpecific">Indicates whether or not the returned functional group is specific to the requested frame.</param>
        /// <returns>The requested functional group sequence item.</returns>
        public DicomSequenceItem GetFrameFunctionalGroupItem(int frameNumber, uint tag, out bool isFrameSpecific)
        {
            FunctionalGroupDescriptor functionalGroupDescriptor;

            if (frameNumber > 0 && _tagMap != null && _tagMap.TryGetValue(tag, out functionalGroupDescriptor))
            {
                FrameFunctionalGroupValue functionalGroupResult;
                var key = new FrameFunctionalGroupKey(functionalGroupDescriptor, frameNumber);
                if (!_cache.TryGetValue(key, out functionalGroupResult))
                {
                    _cache[key] = functionalGroupResult = new FrameFunctionalGroupValue(MultiFrameFunctionalGroupsModuleIod.GetFunctionalGroup(functionalGroupDescriptor, _dataSet, frameNumber, out isFrameSpecific), isFrameSpecific);
                }
                else
                {
                    isFrameSpecific = functionalGroupResult.IsFrameSpecific;
                }

                var functionalGroup = functionalGroupResult.FunctionalGroupMacro;
                if (functionalGroup == null)
                {
                    return(null);
                }

                // if the requested tag is the root sequence tag, return the entire per-frame/shared functional group sequence item as the result
                // otherwise, return the singleton sequence item that contains the requested nested tag (or null if the containing sequence item is not a singleton)
                return(functionalGroup.DefinedTags.Contains(tag) ? functionalGroup.DicomSequenceItem : functionalGroup.SingleItem);
            }
            isFrameSpecific = false;
            return(null);
        }