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