/// <summary>
		/// Gets the Dimension Index Value of a specific dimension for the specified frame.
		/// </summary>
		/// <remarks>
		/// The Dimension Index Value is a number associated with a specific frame in a multi-frame image
		/// that identifies its sequential order relative to the other frames in a particular dimension.
		/// The dimension is identified by the DICOM tag which has the value of the frame in this dimension,
		/// and the DICOM tag of the parent functional group sequence.
		/// </remarks>
		/// <param name="frameNumber">The number of the frame for which the index value is to be retrieved (1-based index).</param>
		/// <param name="dimensionIndexTag">The DICOM tag of the dimension to retrieve (i.e. the Dimension Index Pointer).</param>
		/// <param name="functionalGroupTag">The DICOM tag of the parent functional group sequence (i.e. the Functional Group Pointer).</param>
		/// <returns>The index value of the frame in the specified dimension, or NULL if the image is not a multi-frame or does not contain the specified dimension.</returns>
		public int? GetFrameDimensionIndexValue(int frameNumber, uint dimensionIndexTag, uint functionalGroupTag)
		{
			if (frameNumber > 0 && IsMultiframe)
			{
				DimensionIndexSequenceItem dimension;
				var dimensionIndex = new MultiFrameDimensionModuleIod(DataSource).FindDimensionIndexSequenceItemByTag(dimensionIndexTag, functionalGroupTag, out dimension);
				if (dimensionIndex >= 0)
				{
					int dimensionIndexValue;
					var dicomAttribute = GetFrameAttributeCore(frameNumber, DicomTags.DimensionIndexValues);
					if (dicomAttribute != null && dicomAttribute.TryGetInt32(dimensionIndex, out dimensionIndexValue))
						return dimensionIndexValue;
				}
			}
			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();
			}
		}
		private void ValidateMultiframeEchoDisplaySet(IDisplaySet displaySet, int echoNumber)
		{
			string seriesInstanceUid = null;
			foreach (IPresentationImage presentationImage in displaySet.PresentationImages)
			{
				var sopProvider = ((IImageSopProvider) presentationImage);
				var mfdModule = new MultiFrameDimensionModuleIod(sopProvider.ImageSop.DataSource);
				var echoDim = mfdModule.FindDimensionIndexSequenceItemByTag(DicomTags.EffectiveEchoTime, DicomTags.MrEchoSequence);
				Assert.IsTrue(echoDim >= 0, "MR Echo dimension was not found");

				seriesInstanceUid = sopProvider.ImageSop.SeriesInstanceUid;
				Assert.AreEqual(echoNumber, sopProvider.Frame[DicomTags.DimensionIndexValues].GetInt32(echoDim, -1), "Echo number must be {0} for each image in the display set", echoNumber);
			}

			Assert.IsNotNull(seriesInstanceUid);
			Assert.AreEqual(String.Format("{0}:Echo{1}", seriesInstanceUid, echoNumber), displaySet.Uid);
		}
		/// <summary>
		/// Gets the Dimension Organization UID of a specific dimension for the specified frame.
		/// </summary>
		/// <remarks>
		/// The Dimension Organization UID identifies when the same dimension index values are valid
		/// across multiple SOP instances.
		/// </remarks>
		/// <param name="frameNumber">The number of the frame for which the dimension is to be retrieved (1-based index).</param>
		/// <param name="dimensionIndexTag">The DICOM tag of the dimension to retrieve (i.e. the Dimension Index Pointer).</param>
		/// <param name="functionalGroupTag">The DICOM tag of the parent functional group sequence (i.e. the Functional Group Pointer).</param>
		/// <returns>The Dimension Organization UID of the specified dimension, or empty if the image is not a multi-frame or does not contain the specified dimension.</returns>
		public string GetFrameDimensionOrganizationUid(int frameNumber, uint dimensionIndexTag, uint functionalGroupTag)
		{
			if (frameNumber > 0 && IsMultiframe)
			{
				DimensionIndexSequenceItem dimension;
				var dimensionIndex = new MultiFrameDimensionModuleIod(DataSource).FindDimensionIndexSequenceItemByTag(dimensionIndexTag, functionalGroupTag, out dimension);
				if (dimensionIndex >= 0) return dimension.DimensionOrganizationUid;
			}
			return string.Empty;
		}