private static FrameContentSequenceItem GetFrameContentSequenceItem(FunctionalGroupsSequenceItem functionalGroupsSequenceItem)
        {
            // NOTE: only PerFrameFunctionalGroup will have this item
            var frameContentFunctionalGroup = functionalGroupsSequenceItem.GetFunctionalGroup <FrameContentFunctionalGroup>();

            return(frameContentFunctionalGroup.HasValues() ? frameContentFunctionalGroup.FrameContentSequence : null);
        }
        private static ImageSopInstanceReferenceMacro[] GetSourceImageSequence(FunctionalGroupsSequenceItem functionalGroupsSequenceItem)
        {
            var sharedDerivationSequenceFunctionalGroup = functionalGroupsSequenceItem.GetFunctionalGroup <DerivationImageFunctionalGroup>();

            return(sharedDerivationSequenceFunctionalGroup.HasValues()
                                                ? (sharedDerivationSequenceFunctionalGroup.DerivationImageSequence.Length > 0
                                                          ? sharedDerivationSequenceFunctionalGroup.DerivationImageSequence[0].SourceImageSequence
                                                          : null)
                                                : null);
        }
        /// <summary>
        /// Creates the SharedFunctionalGroupsSequence in the underlying collection. Type 2.
        /// </summary>
        public FunctionalGroupsSequenceItem CreateSharedFunctionalGroupsSequence()
        {
            var dicomAttribute = DicomAttributeProvider[DicomTags.SharedFunctionalGroupsSequence];

            if (dicomAttribute.IsNull || dicomAttribute.IsEmpty)
            {
                var dicomSequenceItem = new DicomSequenceItem();
                dicomAttribute.Values = new[] { dicomSequenceItem };
                var sequenceType = new FunctionalGroupsSequenceItem(dicomSequenceItem);
                return(sequenceType);
            }
            return(new FunctionalGroupsSequenceItem(((DicomSequenceItem[])dicomAttribute.Values)[0]));
        }
        private static void InitializeSegmentationFunctionalGroup(FunctionalGroupsSequenceItem functionalGroupsSequenceItem, int segmentNumber)
        {
            var segmentationFunctionalGroup = functionalGroupsSequenceItem.GetFunctionalGroup<SegmentationFunctionalGroup>();
            var segmentationIdentificationSequenceItem = segmentationFunctionalGroup.CreateSegmentIdentificationSequence();
            segmentationIdentificationSequenceItem.ReferencedSegmentNumber = segmentNumber;

            segmentationFunctionalGroup.SegmentIdentificationSequence = segmentationIdentificationSequenceItem;
        }
        private static void InitializePlanePositionPatientFunctionalGroup(FunctionalGroupsSequenceItem functionalGroupsSequenceItem,
																		  ImagePositionPatient imagePositionPatient)
        {
            if (imagePositionPatient.IsNull)
                return;

            var planePositionPatientFunctionalGroup = functionalGroupsSequenceItem.GetFunctionalGroup<PlanePositionPatientFunctionalGroup>();
            var planePositionSequence = planePositionPatientFunctionalGroup.CreatePlanePositionSequence();
            planePositionSequence.ImagePositionPatient = new[] { imagePositionPatient.X, imagePositionPatient.Y, imagePositionPatient.Z };

            planePositionPatientFunctionalGroup.PlanePositionSequence = planePositionSequence;
        }
        private static void InitializePlaneOrientationPatientFunctionalGroup(FunctionalGroupsSequenceItem functionalGroupsSequenceItem,
																			 ImageOrientationPatient imageOrientationPatient)
        {
            if (imageOrientationPatient.IsNull)
                return;

            var planeOrientationPatientFunctionalGroup = functionalGroupsSequenceItem.GetFunctionalGroup<PlaneOrientationPatientFunctionalGroup>();
            var planeOrientationPatientSequence = planeOrientationPatientFunctionalGroup.CreatePlaneOrientationSequence();
            planeOrientationPatientSequence.ImageOrientationPatient = new[]
                {
                    imageOrientationPatient.RowX, imageOrientationPatient.RowY, imageOrientationPatient.RowZ, imageOrientationPatient.ColumnX,
                    imageOrientationPatient.ColumnY, imageOrientationPatient.ColumnZ
                };

            planeOrientationPatientFunctionalGroup.PlaneOrientationSequence = planeOrientationPatientSequence;
        }
        /// <summary>
        /// Initializes Pixel Measures Functional Group
        /// </summary>
        /// <param name="functionalGroupsSequenceItem">Functional Group Sequence Item that the newly initialized Pixel Measures Functional Group will belong</param>
        /// <param name="imageFrame"><see cref="Frame"/> that is a source of group's values</param>
        private static void InitializePixelMeasureFunctionalGroup(FunctionalGroupsSequenceItem functionalGroupsSequenceItem, Frame imageFrame)
        {
            var pixelSpacing = imageFrame.PixelSpacing;
            if (pixelSpacing.IsNull)
                return;

            var pixelMeasureFunctionalGroup = functionalGroupsSequenceItem.GetFunctionalGroup<PixelMeasuresFunctionalGroup>();
            var pixelMeasureSequence = pixelMeasureFunctionalGroup.CreatePixelMeasuresSequence();
            pixelMeasureSequence.PixelSpacing = new[] {pixelSpacing.Row, pixelSpacing.Column};
            pixelMeasureSequence.SliceThickness = imageFrame.SliceThickness;

            pixelMeasureFunctionalGroup.PixelMeasuresSequence = pixelMeasureSequence;
        }
        private static void InitializeFrameContentFunctionalGroup(FunctionalGroupsSequenceItem functionalGroupsSequenceItem, int stackId, int inStackPositionNumber)
        {
            var frameContentFunctionalGroup = functionalGroupsSequenceItem.GetFunctionalGroup<FrameContentFunctionalGroup>();
            var frameContentSequenceItem = frameContentFunctionalGroup.CreateFrameContentSequence();
            frameContentSequenceItem.DimensionIndexValues = new[] {(uint)stackId, (uint)inStackPositionNumber};
            frameContentSequenceItem.StackId = string.Format("Stack ID {0}", stackId);
            frameContentSequenceItem.InStackPositionNumber = inStackPositionNumber;

            frameContentFunctionalGroup.FrameContentSequence = frameContentSequenceItem;
        }
        private static void InitializeDerivationImageFunctionalGroup(FunctionalGroupsSequenceItem functionalGroupsSequenceItem, ImageSop imageSop, int frameNumber)
        {
            var derivationImageFunctionalGroup = functionalGroupsSequenceItem.GetFunctionalGroup<DerivationImageFunctionalGroup>();
            var derivationImageSequenceItem = derivationImageFunctionalGroup.CreateDerivationImageSequenceItem();
            var derivationCodeSequence = derivationImageSequenceItem.CreateDerivationCodeSequence();
            derivationCodeSequence.CodeValue = "113076";
            derivationCodeSequence.CodeMeaning = "Segmentation";
            derivationCodeSequence.CodingSchemeDesignator = "DCM";
            derivationImageSequenceItem.DerivationCodeSequence = derivationCodeSequence;
            var sourceImageSequenceItem = derivationImageSequenceItem.CreateSourceImageSequenceItem();
            sourceImageSequenceItem.ReferencedSopClassUid = imageSop.SopClassUid;
            sourceImageSequenceItem.ReferencedSopInstanceUid = imageSop.SopInstanceUid;
            if (frameNumber != 1)
                sourceImageSequenceItem.ReferencedFrameNumber2 = new[] {frameNumber};
            // TODO: FIXME: replace with stock implementation when available
            var purposeOfReferenceCodeSequence = new Func<CodeSequenceMacro>(() =>
                {
                    var dicomAttribute = sourceImageSequenceItem.DicomAttributeProvider[DicomTags.PurposeOfReferenceCodeSequence];
                    if (dicomAttribute.IsNull || dicomAttribute.IsEmpty)
                    {
                        var dicomSequenceItem = new DicomSequenceItem();
                        dicomAttribute.Values = new[] {dicomSequenceItem};
                        return new CodeSequenceMacro(dicomSequenceItem);
                    }
                    return new CodeSequenceMacro(((DicomSequenceItem[]) dicomAttribute.Values)[0]);
                }).Invoke();
            purposeOfReferenceCodeSequence.CodeValue = "121322";
            purposeOfReferenceCodeSequence.CodeMeaning = "Source image for image processing operation";
            purposeOfReferenceCodeSequence.CodingSchemeDesignator = "DCM";
            derivationImageSequenceItem.SourceImageSequence = new[] {sourceImageSequenceItem};

            derivationImageFunctionalGroup.DerivationImageSequence = new[] {derivationImageSequenceItem};
        }
        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>
        /// Creates a single instance of a PerFrameFunctionalGroupsSequence item. Does not modify the PerFrameFunctionalGroupsSequence in the underlying collection.
        /// </summary>
        public FunctionalGroupsSequenceItem CreatePerFrameFunctionalGroupsSequence()
        {
            var iodBase = new FunctionalGroupsSequenceItem(new DicomSequenceItem());

            return(iodBase);
        }
        private static SegmentIdentificationSequenceItem GetSegmentIdentificationSequenceItem(FunctionalGroupsSequenceItem functionalGroupsSequenceItem)
        {
            var sharedSegmentationFunctionalGroup = functionalGroupsSequenceItem.GetFunctionalGroup <SegmentationFunctionalGroup>();

            return(sharedSegmentationFunctionalGroup.HasValues() ? sharedSegmentationFunctionalGroup.SegmentIdentificationSequence : null);
        }
        private static PixelMeasuresSequenceItem GetPixelMeasuresSequenceItem(FunctionalGroupsSequenceItem functionalGroupsSequenceItem)
        {
            var sharedPixelMeasureFucntionalGroup = functionalGroupsSequenceItem.GetFunctionalGroup <PixelMeasuresFunctionalGroup>();

            return(sharedPixelMeasureFucntionalGroup.HasValues() ? sharedPixelMeasureFucntionalGroup.PixelMeasuresSequence : null);
        }
        private static PlaneOrientationSequenceItem GetPlaneOrientationSequenceItem(FunctionalGroupsSequenceItem functionalGroupsSequenceItem)
        {
            var sharedPlaneOrientationFunctionalGroup = functionalGroupsSequenceItem.GetFunctionalGroup <PlaneOrientationPatientFunctionalGroup>();

            return(sharedPlaneOrientationFunctionalGroup.HasValues() ? sharedPlaneOrientationFunctionalGroup.PlaneOrientationSequence : null);
        }