/// <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); }
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); }
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 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); }