public ImagePlaneAnnotationItemProvider()
			: base("AnnotationItemProviders.Dicom.ImagePlane", new AnnotationResourceResolver(typeof(ImagePlaneAnnotationItemProvider).Assembly))
		{
			_annotationItems = new List<IAnnotationItem>();

			AnnotationResourceResolver resolver = new AnnotationResourceResolver(this);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.ImagePlane.SliceThickness",
						resolver,
						delegate(Frame frame)
						{
							double thickness = frame.SliceThickness;

							if (double.IsNaN(thickness) || thickness == 0)
								return "";

							return String.Format(SR.FormatMillimeters, frame.SliceThickness.ToString("F1"));
						},
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add(new SliceLocationAnnotationItem());
		}
		public ContrastBolusAnnotationItemProvider()
			: base("AnnotationItemProviders.Dicom.ContrastBolus", new AnnotationResourceResolver(typeof (ContrastBolusAnnotationItemProvider).Assembly))
		{
			_annotationItems = new List<IAnnotationItem>();

			AnnotationResourceResolver resolver = new AnnotationResourceResolver(this);

			_annotationItems.Add
				(
					new CodeSequenceAnnotationItem
						(
						"Dicom.ContrastBolus.Agent",
						resolver,
						DicomTags.ContrastBolusAgentSequence,
						DicomTags.ContrastBolusAgent
						)
				);

			// N.B.: The contrast/bolus items defined here are only for those that are defined as part of (enhanced) contrast/bolus module C.7.6.4 and C.7.6.4b
			// Annotation items for contrast/bolus tags in the X-Ray 3D Shared Acquisition macro should be defined separately in the DX or another X-Ray specific provider
		}
		public MRImageAnnotationItemProvider()
			: base("AnnotationItemProviders.Dicom.MRImage", new AnnotationResourceResolver(typeof(MRImageAnnotationItemProvider).Assembly))
		{
			_annotationItems = new List<IAnnotationItem>();

			AnnotationResourceResolver resolver = new AnnotationResourceResolver(this);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.MRImage.EchoTime",
						resolver,
						delegate(Frame frame)
						{
							double value;
							bool tagExists = frame.ParentImageSop[DicomTags.EchoTime].TryGetFloat64(0, out value);
							if (tagExists)
								return String.Format(SR.FormatMilliseconds, value.ToString("F2"));

							return "";
						},
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.MRImage.MagneticFieldStrength",
						resolver,
						delegate(Frame frame)
						{
							double value;
							bool tagExists = frame.ParentImageSop[DicomTags.MagneticFieldStrength].TryGetFloat64(0, out value);
							if (tagExists)
								return String.Format(SR.FormatTeslas, value.ToString("F1"));

							return "";
						},
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.MRImage.AcquisitionMatrix",
						resolver,
						delegate(Frame frame)
						{
							//TODO (CR Mar 2010): check for the 2 that aren't zero.
							string phaseDirection = frame.ParentImageSop[DicomTags.InPlanePhaseEncodingDirection].ToString().ToUpperInvariant();

							DicomAttribute acqAttrib = frame.ParentImageSop[DicomTags.AcquisitionMatrix];
							if (!acqAttrib.IsEmpty && acqAttrib.Count > 3)
							{
								ushort frequencyRows = acqAttrib.GetUInt16(0, 0);
								ushort frequencyColumns = acqAttrib.GetUInt16(1, 0);
								ushort phaseRows = acqAttrib.GetUInt16(2, 0);
								ushort phaseColumns = acqAttrib.GetUInt16(3, 0);

								switch (phaseDirection)
								{
									case "COL":
										return String.Format(SR.Format2Dimensions, phaseColumns, frequencyRows);
									case "ROW":
									default:
										return String.Format(SR.Format2Dimensions, frequencyColumns, phaseRows);
								}
							}

							return "";
						},
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.MRImage.ReceiveCoilName",
						resolver,
						delegate(Frame frame)
						{
							string value;
							value = frame.ParentImageSop[DicomTags.ReceiveCoilName].GetString(0, null);
							return value;
						},
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.MRImage.RepetitionTime",
						resolver,
						delegate(Frame frame)
						{
							double value;
							bool tagExists = frame.ParentImageSop[DicomTags.RepetitionTime].TryGetFloat64(0, out value);
							if (tagExists)
								return String.Format(SR.FormatMilliseconds, value.ToString("F2"));

							return "";
						},
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.MRImage.EchoTrainLength",
						resolver,
						delegate(Frame frame)
						{
							int value;
							bool tagExists = frame.ParentImageSop[DicomTags.EchoTrainLength].TryGetInt32(0, out value);
							if (tagExists)
								return String.Format("{0}", value);

							return "";
						},
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.MRImage.InversionTime",
						resolver,
						delegate(Frame frame)
						{
							double value;
							var tagExists = frame.ParentImageSop[DicomTags.InversionTime].TryGetFloat64(0, out value);
							return tagExists ? string.Format(SR.FormatMilliseconds, value.ToString("F2")) : string.Empty;
						},
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.MRImage.TriggerTime",
						resolver,
						delegate(Frame frame)
						{
							double value;
							var tagExists = frame.ParentImageSop[DicomTags.TriggerTime].TryGetFloat64(0, out value);
							return tagExists ? string.Format(SR.FormatMilliseconds, value.ToString("F2")) : string.Empty;
						},
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.MRImage.NumberOfAverages",
						resolver,
						delegate(Frame frame)
						{
							double value;
							var tagExists = frame.ParentImageSop[DicomTags.NumberOfAverages].TryGetFloat64(0, out value);
							return tagExists ? string.Format("{0}", value) : string.Empty;
						},
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.MRImage.PixelBandwidth",
						resolver,
						delegate(Frame frame)
						{
							double value;
							var tagExists = frame.ParentImageSop[DicomTags.PixelBandwidth].TryGetFloat64(0, out value);
							return tagExists ? string.Format(SR.FormatHertzPerPixel, value.ToString("F2")) : string.Empty;
						},
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.MRImage.FlipAngle",
						resolver,
						delegate(Frame frame)
						{
							double value;
							var tagExists = frame.ParentImageSop[DicomTags.FlipAngle].TryGetFloat64(0, out value);
							return tagExists ? string.Format(SR.FormatDegrees, value.ToString("F2")) : string.Empty;
						},
						DicomDataFormatHelper.RawStringFormat
					)
				);
		}
		public CTImageAnnotationItemProvider()
			: base("AnnotationItemProviders.Dicom.CTImage", new AnnotationResourceResolver(typeof (CTImageAnnotationItemProvider).Assembly))
		{
			_annotationItems = new List<IAnnotationItem>();

			AnnotationResourceResolver resolver = new AnnotationResourceResolver(this);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.CTImage.KVP",
						resolver,
						delegate(Frame frame)
							{
								double value;
								bool tagExists = frame[DicomTags.Kvp].TryGetFloat64(0, out value);
								if (tagExists)
									return String.Format(SR.FormatKilovolts, value);

								return "";
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.CTImage.XRayTubeCurrent",
						resolver,
						f => DXImageAnnotationItemProvider.GetXRayTubeCurrentInMa(f, SR.FormatMilliamps),
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.CTImage.GantryDetectorTilt",
						resolver,
						delegate(Frame frame)
							{
								double value;
								bool tagExists = frame[DicomTags.GantryDetectorTilt].TryGetFloat64(0, out value);
								if (tagExists)
									return String.Format(SR.FormatDegrees, value);

								return "";
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.CTImage.Exposure",
						resolver,
						f => DXImageAnnotationItemProvider.GetExposureInMas(f, SR.FormatMilliampSeconds),
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.CTImage.ExposureTime",
						resolver,
						f => DXImageAnnotationItemProvider.GetExposureTimeInMs(f, SR.FormatMilliseconds),
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.CTImage.ConvolutionKernel",
						resolver,
						frame => frame[DicomTags.ConvolutionKernel].GetString(0, null),
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.CTImage.TableSpeed",
						resolver,
						GetTableSpeed,
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.CTImage.TablePosition",
						resolver,
						GetTablePosition,
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.CTImage.Composite.TablePositionSpeed",
						resolver,
						delegate(Frame frame)
							{
								var position = GetTablePosition(frame);
								var speed = GetTableSpeed(frame);
								if (string.IsNullOrEmpty(position))
									return speed;
								if (string.IsNullOrEmpty(speed))
									return position;
								return string.Format(SR.FormatTablePositionSpeed, position, speed);
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);
		}
		public DXImageAnnotationItemProvider()
			: base("AnnotationItemProviders.Dicom.DXImage", new AnnotationResourceResolver(typeof (DXImageAnnotationItemProvider).Assembly))
		{
			_annotationItems = new List<IAnnotationItem>();

			AnnotationResourceResolver resolver = new AnnotationResourceResolver(this);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// this is actually DX Positioning module
					"Dicom.DXImage.DetectorPrimaryAngle",
					resolver,
					f => FormatFloat64(f, DicomTags.DetectorPrimaryAngle, SR.FormatDegrees),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// this is actually DX Positioning module
					"Dicom.DXImage.PositionerPrimaryAngle",
					resolver,
					f => FormatFloat64(f, DicomTags.PositionerPrimaryAngle, SR.FormatDegrees),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// this is actually DX Positioning module
					"Dicom.DXImage.PositionerSecondaryAngle",
					resolver,
					f => FormatFloat64(f, DicomTags.PositionerSecondaryAngle, SR.FormatDegrees),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// this is actually DX Positioning module
					"Dicom.DXImage.BodyPartThickness",
					resolver,
					f => string.Format(SR.FormatMillimeters, FormatFloat64(f, DicomTags.BodyPartThickness, "{0:F1}")),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// this is actually DX Positioning module
					"Dicom.DXImage.CompressionForce",
					resolver,
					f => FormatInt32(f, DicomTags.CompressionForce, SR.FormatNewtons),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// this is actually DX Series module
					"Dicom.DXImage.PresentationIntentType",
					resolver,
					f => f.ParentImageSop[DicomTags.PresentationIntentType].ToString(),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// whoa, this is actually DX Image module
					"Dicom.DXImage.AcquisitionDeviceProcessingDescription",
					resolver,
					f => f.ParentImageSop[DicomTags.AcquisitionDeviceProcessingDescription].ToString(),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// this is actually DX Detector module
					"Dicom.DXImage.CassetteId",
					resolver,
					f => f.ParentImageSop[DicomTags.CassetteId].ToString(),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// this is actually DX Detector module
					"Dicom.DXImage.PlateId",
					resolver,
					f => f.ParentImageSop[DicomTags.PlateId].ToString(),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// this isn't even a DX module, but other X-Ray related modules
					"Dicom.DXImage.KVP",
					resolver,
					f => FormatFloat64(f, DicomTags.Kvp, SR.FormatKilovolts),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// this isn't even a DX module, but other X-Ray related modules
					"Dicom.DXImage.AveragePulseWidth",
					resolver,
					f => FormatFloat64(f, DicomTags.AveragePulseWidth, SR.FormatMilliseconds),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// this isn't even a DX module, but other X-Ray related modules
					"Dicom.DXImage.ImageAndFluoroscopyAreaDoseProduct",
					resolver,
					f => FormatFloat64(f, DicomTags.ImageAndFluoroscopyAreaDoseProduct, SR.FormatDecigraySquareCentimeters),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// legacy item (new layouts should use Exposure) so that current annotation layouts don't break - can be removed in a future release
					"Dicom.DXImage.ExposureInMas",
					resolver,
					f => GetExposureInMas(f, SR.FormatMilliampSeconds),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// this isn't defined in a DX module, but rather in other X-Ray related modules
					"Dicom.DXImage.Exposure",
					resolver,
					f => GetExposureInMas(f, SR.FormatMilliampSeconds),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// this isn't defined in a DX module, but rather in other X-Ray related modules
					"Dicom.DXImage.ExposureTime",
					resolver,
					f => GetExposureTimeInMs(f, SR.FormatMilliseconds),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// this isn't defined in a DX module, but rather in other X-Ray related modules
					"Dicom.DXImage.XRayTubeCurrent",
					resolver,
					f => GetXRayTubeCurrentInMa(f, SR.FormatMilliamps),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					// this isn't even a DX module, but other X-Ray related modules
					"Dicom.DXImage.FilterMaterial",
					resolver,
					f => f.ParentImageSop[DicomTags.FilterMaterial].ToString(),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new CodeSequenceAnnotationItem
					(
					// this isn't even a DX module, but other X-Ray related modules
					"Dicom.DXImage.ContrastBolusAgent",
					resolver,
					DicomTags.ContrastBolusAgentSequence,
					DicomTags.ContrastBolusAgent
					)
				);
		}
		public DXImageAnnotationItemProvider()
			: base("AnnotationItemProviders.Dicom.DXImage", new AnnotationResourceResolver(typeof (DXImageAnnotationItemProvider).Assembly))
		{
			_annotationItems = new List<IAnnotationItem>();
			_frameContext = new AnnotationDataSourceContext<Frame>();
			_frameContext.DataSourceChanged += OnFrameContextDataSourceChanged;

			AnnotationResourceResolver resolver = new AnnotationResourceResolver(this);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// this is actually DX Positioning module
						"Dicom.DXImage.DetectorPrimaryAngle",
						resolver,
						f => FormatFloat64(f, DicomTags.DetectorPrimaryAngle, SR.FormatDegrees),
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// this is actually DX Positioning module
						"Dicom.DXImage.PositionerPrimaryAngle",
						resolver,
						f => FormatFloat64(f, DicomTags.PositionerPrimaryAngle, SR.FormatDegrees),
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// this is actually DX Positioning module
						"Dicom.DXImage.PositionerSecondaryAngle",
						resolver,
						f => FormatFloat64(f, DicomTags.PositionerSecondaryAngle, SR.FormatDegrees),
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// this is actually DX Positioning or X-Ray 3D Acquisition module
						"Dicom.DXImage.BodyPartThickness",
						resolver,
						f =>
							{
								var acquisitions = _frameContext.GetData<IXRay3DAcquisitionSequenceItem[]>(f, _keyAcquisitionSequence);
								var dataset = acquisitions != null ? (IEnumerable<IDicomAttributeProvider>) acquisitions.Select(a => a.DicomSequenceItem) : new IDicomAttributeProvider[] {f};
								return string.Format(SR.FormatMillimeters, FormatMultiValues(dataset, FormatFloat64, DicomTags.BodyPartThickness, "{0:F1}"));
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// this is actually DX Positioning module
						"Dicom.DXImage.CompressionForce",
						resolver,
						f =>
							{
								var acquisitions = _frameContext.GetData<IXRay3DAcquisitionSequenceItem[]>(f, _keyAcquisitionSequence);
								var dataset = acquisitions != null ? (IEnumerable<IDicomAttributeProvider>) acquisitions.Select(a => a.DicomSequenceItem) : new IDicomAttributeProvider[] {f};
								return FormatMultiValues(dataset, FormatInt32, DicomTags.CompressionForce, SR.FormatNewtons);
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// this is actually DX Series module
						"Dicom.DXImage.PresentationIntentType",
						resolver,
						f => f[DicomTags.PresentationIntentType].ToString(),
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// whoa, this is actually DX Image module
						"Dicom.DXImage.AcquisitionDeviceProcessingDescription",
						resolver,
						f => f[DicomTags.AcquisitionDeviceProcessingDescription].ToString(),
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// this is actually DX Detector module
						"Dicom.DXImage.CassetteId",
						resolver,
						f => f[DicomTags.CassetteId].ToString(),
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// this is actually DX Detector module
						"Dicom.DXImage.PlateId",
						resolver,
						f => f[DicomTags.PlateId].ToString(),
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// this isn't even a DX module, but other X-Ray related modules
						"Dicom.DXImage.KVP",
						resolver,
						f =>
							{
								var acquisitions = _frameContext.GetData<IXRay3DAcquisitionSequenceItem[]>(f, _keyAcquisitionSequence);
								var dataset = acquisitions != null ? (IEnumerable<IDicomAttributeProvider>) acquisitions.Select(a => a.DicomSequenceItem) : new IDicomAttributeProvider[] {f};
								return FormatMultiValues(dataset, FormatFloat64, DicomTags.Kvp, SR.FormatKilovolts);
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// this isn't even a DX module, but other X-Ray related modules
						"Dicom.DXImage.AveragePulseWidth",
						resolver,
						f => FormatFloat64(f, DicomTags.AveragePulseWidth, SR.FormatMilliseconds),
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// this isn't even a DX module, but other X-Ray related modules
						"Dicom.DXImage.ImageAndFluoroscopyAreaDoseProduct",
						resolver,
						f => FormatFloat64(f, DicomTags.ImageAndFluoroscopyAreaDoseProduct, SR.FormatDecigraySquareCentimeters),
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// legacy item (new layouts should use Exposure) so that current annotation layouts don't break - can be removed in a future release
						"Dicom.DXImage.ExposureInMas",
						resolver,
						f =>
							{
								var acquisitions = _frameContext.GetData<IXRay3DAcquisitionSequenceItem[]>(f, _keyAcquisitionSequence);
								var dataset = acquisitions != null ? (IEnumerable<IDicomAttributeProvider>) acquisitions.Select(a => a.DicomSequenceItem) : new IDicomAttributeProvider[] {f};
								return FormatMultiValues(dataset, GetExposureInMas, SR.FormatMilliampSeconds);
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// this isn't defined in a DX module, but rather in other X-Ray related modules
						"Dicom.DXImage.Exposure",
						resolver,
						f =>
							{
								var acquisitions = _frameContext.GetData<IXRay3DAcquisitionSequenceItem[]>(f, _keyAcquisitionSequence);
								var dataset = acquisitions != null ? (IEnumerable<IDicomAttributeProvider>) acquisitions.Select(a => a.DicomSequenceItem) : new IDicomAttributeProvider[] {f};
								return FormatMultiValues(dataset, GetExposureInMas, SR.FormatMilliampSeconds);
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// this isn't defined in a DX module, but rather in other X-Ray related modules
						"Dicom.DXImage.ExposureTime",
						resolver,
						f =>
							{
								var acquisitions = _frameContext.GetData<IXRay3DAcquisitionSequenceItem[]>(f, _keyAcquisitionSequence);
								var dataset = acquisitions != null ? (IEnumerable<IDicomAttributeProvider>) acquisitions.Select(a => a.DicomSequenceItem) : new IDicomAttributeProvider[] {f};
								return FormatMultiValues(dataset, GetExposureTimeInMs, SR.FormatMilliseconds);
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// this isn't defined in a DX module, but rather in other X-Ray related modules
						"Dicom.DXImage.XRayTubeCurrent",
						resolver,
						f =>
							{
								var acquisitions = _frameContext.GetData<IXRay3DAcquisitionSequenceItem[]>(f, _keyAcquisitionSequence);
								var dataset = acquisitions != null ? (IEnumerable<IDicomAttributeProvider>) acquisitions.Select(a => a.DicomSequenceItem) : new IDicomAttributeProvider[] {f};
								return FormatMultiValues(dataset, GetXRayTubeCurrentInMa, SR.FormatMilliamps);
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						// this isn't even a DX module, but other X-Ray related modules
						"Dicom.DXImage.FilterMaterial",
						resolver,
						f =>
							{
								var acquisitions = _frameContext.GetData<IXRay3DAcquisitionSequenceItem[]>(f, _keyAcquisitionSequence);
								var dataset = acquisitions != null ? (IEnumerable<IDicomAttributeProvider>) acquisitions.Select(a => a.DicomSequenceItem) : new IDicomAttributeProvider[] {f};
								return FormatMultiValues(dataset, FormatString, DicomTags.FilterMaterial, null);
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new CodeSequenceAnnotationItem
						(
						// definition of the contrast/bolus agent item takes into account the X-Ray 3D Acquisition sequence, and is thus separate from the normal contast/bolus modules
						"Dicom.DXImage.ContrastBolusAgent",
						resolver,
						DicomTags.ContrastBolusAgentSequence,
						DicomTags.ContrastBolusAgent,
						f =>
							{
								var acquisitions = _frameContext.GetData<IXRay3DAcquisitionSequenceItem[]>(f, _keyAcquisitionSequence);
								return acquisitions != null ? (IDicomAttributeProvider) acquisitions.Select(d => d.DicomSequenceItem).FirstOrDefault() : f;
							}
						)
				);
		}
		public PatientAnnotationItemProvider()
			: base("AnnotationItemProviders.Dicom.Patient", new AnnotationResourceResolver(typeof(PatientAnnotationItemProvider).Assembly))
		{
			_annotationItems = new List<IAnnotationItem>();

			AnnotationResourceResolver resolver = new AnnotationResourceResolver(this);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.Patient.EthnicGroup",
						resolver,
						FrameDataRetrieverFactory.GetStringRetriever(DicomTags.EthnicGroup),
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.Patient.PatientComments",
						resolver,
						FrameDataRetrieverFactory.GetStringRetriever(DicomTags.PatientComments),
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.Patient.PatientId",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.PatientId; },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.Patient.PatientsBirthDate",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.PatientsBirthDate; },
						DicomDataFormatHelper.DateFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.Patient.PatientsBirthTime",
						resolver,
						FrameDataRetrieverFactory.GetStringRetriever(DicomTags.PatientsBirthTime),
						DicomDataFormatHelper.TimeFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<PersonName>
					(
						"Dicom.Patient.PatientsName",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.PatientsName; },
						DicomDataFormatHelper.PersonNameFormatter
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.Patient.PatientsSex",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.PatientsSex; },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<PersonName>
					(
						"Dicom.Patient.ResponsiblePerson",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.ResponsiblePerson; },
						DicomDataFormatHelper.PersonNameFormatter
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.Patient.ResponsibleOrganization",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.ResponsibleOrganization; },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new CodeSequenceAnnotationItem
					(
						"Dicom.Patient.PatientSpecies",
						resolver,
						DicomTags.PatientSpeciesCodeSequence,
						DicomTags.PatientSpeciesDescription
					)
				);

			_annotationItems.Add
				(
					new CodeSequenceAnnotationItem
					(
						"Dicom.Patient.PatientBreed",
						resolver,
						DicomTags.PatientBreedCodeSequence,
						DicomTags.PatientBreedDescription
					)
				);
		}
		public GeneralStudyAnnotationItemProvider()
			: base("AnnotationItemProviders.Dicom.GeneralStudy", new AnnotationResourceResolver(typeof(GeneralStudyAnnotationItemProvider).Assembly))
		{
			_annotationItems = new List<IAnnotationItem>();

			AnnotationResourceResolver resolver = new AnnotationResourceResolver(this);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralStudy.AccessionNumber",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.AccessionNumber; },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<PersonName>
					(
						"Dicom.GeneralStudy.ReferringPhysiciansName",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.ReferringPhysiciansName; },
						DicomDataFormatHelper.PersonNameFormatter
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralStudy.StudyDate",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.StudyDate; },
						DicomDataFormatHelper.DateFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralStudy.StudyTime",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.StudyTime; },
						DicomDataFormatHelper.TimeFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralStudy.StudyDescription",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.StudyDescription; },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralStudy.StudyId",
						resolver,
						FrameDataRetrieverFactory.GetStringRetriever(DicomTags.StudyId),
						DicomDataFormatHelper.RawStringFormat
					)
				);
		}
		public GeneralImageAnnotationItemProvider()
			: base("AnnotationItemProviders.Dicom.GeneralImage", new AnnotationResourceResolver(typeof(GeneralImageAnnotationItemProvider).Assembly))
		{
			_annotationItems = new List<IAnnotationItem>();

			AnnotationResourceResolver resolver = new AnnotationResourceResolver(this);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralImage.AcquisitionDate",
						resolver,
						delegate(Frame frame) { return frame.AcquisitionDate; },
						DicomDataFormatHelper.DateFormat
					)
				);


			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralImage.AcquisitionTime",
						resolver,
						delegate(Frame frame) { return frame.AcquisitionTime; },
						delegate (string input)
							{
								if (String.IsNullOrEmpty(input))
									return String.Empty;

								DateTime time;
								if (!TimeParser.Parse(input, out time))
									return input;

								return time.ToString("HH:mm:ss.FFFFFF");
							}
					)
				);


			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralImage.AcquisitionDateTime",
						resolver,
						delegate(Frame frame) { return frame.AcquisitionDateTime; },
						delegate(string input)
							{
								if (String.IsNullOrEmpty(input))
									return String.Empty;

								DateTime dateTime;
								if (!DateTimeParser.Parse(input, out dateTime))
									return input;

								return String.Format("{0} {1}", 
									dateTime.Date.ToString(Format.DateFormat),
									dateTime.ToString("HH:mm:ss.FFFFFF"));
							}
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralImage.AcquisitionNumber",
						resolver,
						delegate(Frame frame) { return frame.AcquisitionNumber.ToString(); },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
						"Dicom.GeneralImage.ContentDate",
						resolver,
						FrameDataRetrieverFactory.GetStringRetriever(DicomTags.ContentDate),
						DicomDataFormatHelper.DateFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralImage.ContentTime",
						resolver,
						FrameDataRetrieverFactory.GetStringRetriever(DicomTags.ContentTime),
						DicomDataFormatHelper.TimeFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralImage.DerivationDescription",
						resolver,
						FrameDataRetrieverFactory.GetStringRetriever(DicomTags.DerivationDescription),
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralImage.ImageComments",
						resolver,
						delegate(Frame frame) { return frame.ImageComments; },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralImage.ImagesInAcquisition",
						resolver,
						delegate(Frame frame) { return frame.ImagesInAcquisition.ToString(); },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralImage.ImageType",
						resolver,
						delegate(Frame frame) { return frame.ImageType; },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add(new InstanceNumberAnnotationItem());

			_annotationItems.Add
				(
					new LossyImagePresentationAnnotationItem
					(
						"Dicom.GeneralImage.LossyImageCompression",
						resolver
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralImage.QualityControlImage",
						resolver,
						FrameDataRetrieverFactory.GetStringRetriever(DicomTags.QualityControlImage),
						DicomDataFormatHelper.BooleanFormatter
					)
				);

			_annotationItems.Add
				(
					new LateralityViewPositionAnnotationItem
					(
						"Dicom.GeneralImage.ViewPosition",
						false, true
					)
				);

			_annotationItems.Add
				(
					new LateralityViewPositionAnnotationItem
					(
						"Dicom.GeneralImage.ImageLaterality",
						true, false
					)
				);
			
			_annotationItems.Add
				(
					new LateralityViewPositionAnnotationItem
					(
						"Dicom.GeneralImage.Composite.LateralityViewPosition",
						true, true
					)
				);
		}
		public GeneralSeriesAnnotationItemProvider()
			: base("AnnotationItemProviders.Dicom.GeneralSeries", new AnnotationResourceResolver(typeof(GeneralSeriesAnnotationItemProvider).Assembly))
		{
			_annotationItems = new List<IAnnotationItem>();

			AnnotationResourceResolver resolver = new AnnotationResourceResolver(this);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralSeries.BodyPartExamined",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.BodyPartExamined; },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralSeries.Laterality",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.Laterality; },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralSeries.Modality",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.Modality; },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<PersonName[]>
					(
						"Dicom.GeneralSeries.OperatorsName",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.OperatorsName; },
						DicomDataFormatHelper.PersonNameListFormatter
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralSeries.PerformedProcedureStepDescription",
						resolver,
						FrameDataRetrieverFactory.GetStringRetriever(DicomTags.PerformedProcedureStepDescription),
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<PersonName[]>
					(
						"Dicom.GeneralSeries.PerformingPhysiciansName",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.PerformingPhysiciansName; },
						DicomDataFormatHelper.PersonNameListFormatter
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralSeries.ProtocolName",
						resolver,
						FrameDataRetrieverFactory.GetStringRetriever(DicomTags.ProtocolName),
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralSeries.SeriesDate",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.SeriesDate; },
						DicomDataFormatHelper.DateFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralSeries.SeriesTime",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.SeriesTime; },
						DicomDataFormatHelper.TimeFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralSeries.SeriesDescription",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.SeriesDescription; },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.GeneralSeries.SeriesNumber",
						resolver,
						delegate(Frame frame)
						{
							if (frame.ParentImageSop.ParentSeries != null)
							{
								return String.Format(SR.FormatSeriesNumberAndCount, frame.ParentImageSop.SeriesNumber, 
									frame.ParentImageSop.ParentSeries.ParentStudy.Series.Count);
							}
							else
							{
								return frame.ParentImageSop.SeriesNumber.ToString();
							}
						},
						DicomDataFormatHelper.RawStringFormat
					)
				);
		}
		public GeneralEquipmentAnnotationItemProvider()
			: base("AnnotationItemProviders.Dicom.GeneralEquipment", new AnnotationResourceResolver(typeof (GeneralEquipmentAnnotationItemProvider).Assembly))
		{
			_annotationItems = new List<IAnnotationItem>();

			AnnotationResourceResolver resolver = new AnnotationResourceResolver(this);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					"Dicom.GeneralEquipment.DateOfLastCalibration",
					resolver,
					FrameDataRetrieverFactory.GetStringRetriever(DicomTags.DateOfLastCalibration),
					DicomDataFormatHelper.DateFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					"Dicom.GeneralEquipment.TimeOfLastCalibration",
					resolver,
					FrameDataRetrieverFactory.GetStringRetriever(DicomTags.TimeOfLastCalibration),
					DicomDataFormatHelper.TimeFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					"Dicom.GeneralEquipment.DeviceSerialNumber",
					resolver,
					FrameDataRetrieverFactory.GetStringRetriever(DicomTags.DeviceSerialNumber),
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					"Dicom.GeneralEquipment.InstitutionAddress",
					resolver,
					FrameDataRetrieverFactory.GetStringRetriever(DicomTags.InstitutionAddress),
					SingleLineStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					"Dicom.GeneralEquipment.InstitutionalDepartmentName",
					resolver,
					delegate(Frame frame) { return frame.ParentImageSop.InstitutionalDepartmentName; },
					SingleLineStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					"Dicom.GeneralEquipment.InstitutionName",
					resolver,
					delegate(Frame frame) { return frame.ParentImageSop.InstitutionName; },
					SingleLineStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					"Dicom.GeneralEquipment.Manufacturer",
					resolver,
					delegate(Frame frame) { return frame.ParentImageSop.Manufacturer; },
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					"Dicom.GeneralEquipment.ManufacturersModelName",
					resolver,
					delegate(Frame frame) { return frame.ParentImageSop.ManufacturersModelName; },
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string>
					(
					"Dicom.GeneralEquipment.StationName",
					resolver,
					delegate(Frame frame) { return frame.ParentImageSop.StationName; },
					DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
				new DicomAnnotationItem<string[]>
					(
					"Dicom.GeneralEquipment.SoftwareVersions",
					resolver,
					FrameDataRetrieverFactory.GetStringArrayRetriever(DicomTags.SoftwareVersions),
					DicomDataFormatHelper.StringListFormat
					)
				);
		}
		public PatientAnnotationItemProvider()
			: base("AnnotationItemProviders.Dicom.Patient", new AnnotationResourceResolver(typeof(PatientAnnotationItemProvider).Assembly))
		{
			_annotationItems = new List<IAnnotationItem>();

			AnnotationResourceResolver resolver = new AnnotationResourceResolver(this);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.Patient.EthnicGroup",
						resolver,
						FrameDataRetrieverFactory.GetStringRetriever(DicomTags.EthnicGroup),
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.Patient.PatientComments",
						resolver,
						FrameDataRetrieverFactory.GetStringRetriever(DicomTags.PatientComments),
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.Patient.PatientId",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.PatientId; },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.Patient.OtherPatientIds",
						resolver,
						delegate(Frame frame)
							{
								var patientIds = new List<string>();
								DicomAttribute attribute;
								if (frame.ParentImageSop.TryGetAttribute(DicomTags.OtherPatientIds, out attribute))
									patientIds.AddRange(DicomStringHelper.GetStringArray(attribute));

								if (frame.ParentImageSop.TryGetAttribute(DicomTags.OtherPatientIdsSequence, out attribute) && !attribute.IsEmpty && !attribute.IsNull)
								{
									var sqAttr = (DicomAttributeSQ)attribute;
									for (var i = 0; i < sqAttr.Count; i++)
									{
										var attr = sqAttr[i][DicomTags.PatientId];
										if (attr != null && !string.IsNullOrEmpty(attr))
											patientIds.Add(attr);
									}
								}

								return DicomStringHelper.GetDicomStringArray(patientIds.Distinct());
							},
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.Patient.PatientsBirthDate",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.PatientsBirthDate; },
						DicomDataFormatHelper.DateFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.Patient.PatientsBirthTime",
						resolver,
						FrameDataRetrieverFactory.GetStringRetriever(DicomTags.PatientsBirthTime),
						DicomDataFormatHelper.TimeFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<PersonName>
					(
						"Dicom.Patient.PatientsName",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.PatientsName; },
						DicomDataFormatHelper.PersonNameFormatter
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.Patient.PatientsSex",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.PatientsSex; },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<PersonName>
					(
						"Dicom.Patient.ResponsiblePerson",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.ResponsiblePerson; },
						DicomDataFormatHelper.PersonNameFormatter
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.Patient.ResponsibleOrganization",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.ResponsibleOrganization; },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new CodeSequenceAnnotationItem
					(
						"Dicom.Patient.PatientSpecies",
						resolver,
						DicomTags.PatientSpeciesCodeSequence,
						DicomTags.PatientSpeciesDescription
					)
				);

			_annotationItems.Add
				(
					new CodeSequenceAnnotationItem
					(
						"Dicom.Patient.PatientBreed",
						resolver,
						DicomTags.PatientBreedCodeSequence,
						DicomTags.PatientBreedDescription
					)
				);
		}
		public PatientStudyAnnotationItemProvider()
			: base("AnnotationItemProviders.Dicom.PatientStudy", new AnnotationResourceResolver(typeof(PatientStudyAnnotationItemProvider).Assembly))
		{
			_annotationItems = new List<IAnnotationItem>();

			AnnotationResourceResolver resolver = new AnnotationResourceResolver(this);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.PatientStudy.AdditionalPatientsHistory",
						resolver,
						delegate(Frame frame) { return frame.ParentImageSop.AdditionalPatientsHistory; },
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.PatientStudy.Occupation",
						resolver,
						FrameDataRetrieverFactory.GetStringRetriever(DicomTags.Occupation),
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.PatientStudy.PatientsAge",
						resolver,
						FrameDataRetrieverFactory.GetStringRetriever(DicomTags.PatientsAge),
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<double>
					(
						"Dicom.PatientStudy.PatientsSize",
						resolver,
						FrameDataRetrieverFactory.GetDoubleRetriever(DicomTags.PatientsSize),
						delegate(double input)
						{
							if (double.IsNaN(input) || input == 0)
								return "";

							return String.Format(SR.FormatMeters, input.ToString("F2"));
						}
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<double>
					(
						"Dicom.PatientStudy.PatientsWeight",
						resolver,
						FrameDataRetrieverFactory.GetDoubleRetriever(DicomTags.PatientsWeight),
						delegate(double input)
						{
							if (double.IsNaN(input) || input == 0)
								return "";

							return String.Format(SR.FormatKilograms, input.ToString("F2"));
						}
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.PatientStudy.Composite.PatientsAgeSex",
						resolver,
						delegate(Frame frame)
						{
						    var components = new List<string>();
						    if (!string.IsNullOrEmpty(frame.ParentImageSop.PatientsAge)) components.Add(frame.ParentImageSop.PatientsAge);
						    if (!string.IsNullOrEmpty(frame.ParentImageSop.PatientsSex)) components.Add(frame.ParentImageSop.PatientsSex);
						    return string.Join(SR.SeparatorAgeSexBirthDate, components.ToArray());
						},
						DicomDataFormatHelper.RawStringFormat
					)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
					(
						"Dicom.PatientStudy.Composite.PatientsAgeSexBirthDate",
						resolver,
						delegate(Frame frame)
						{
						    var components = new List<string>();
						    if (!string.IsNullOrEmpty(frame.ParentImageSop.PatientsAge)) components.Add(frame.ParentImageSop.PatientsAge);
						    if (!string.IsNullOrEmpty(frame.ParentImageSop.PatientsSex)) components.Add(frame.ParentImageSop.PatientsSex);
						    if (!string.IsNullOrEmpty(frame.ParentImageSop.PatientsBirthDate)) components.Add(DicomDataFormatHelper.DateFormat(frame.ParentImageSop.PatientsBirthDate));
						    return string.Join(SR.SeparatorAgeSexBirthDate, components.ToArray());
						},
						DicomDataFormatHelper.RawStringFormat
					)
				);
		}
		public MRImageAnnotationItemProvider()
			: base("AnnotationItemProviders.Dicom.MRImage", new AnnotationResourceResolver(typeof (MRImageAnnotationItemProvider).Assembly))
		{
			_annotationItems = new List<IAnnotationItem>();

			AnnotationResourceResolver resolver = new AnnotationResourceResolver(this);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.MRImage.EchoTime",
						resolver,
						delegate(Frame frame)
							{
								double value;
								bool tagExists = frame[DicomTags.EffectiveEchoTime].TryGetFloat64(0, out value) || frame[DicomTags.EchoTime].TryGetFloat64(0, out value);
								if (tagExists)
									return String.Format(SR.FormatMilliseconds, value.ToString("F2"));

								return "";
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.MRImage.MagneticFieldStrength",
						resolver,
						delegate(Frame frame)
							{
								double value;
								bool tagExists = frame[DicomTags.MagneticFieldStrength].TryGetFloat64(0, out value);
								if (tagExists)
									return String.Format(SR.FormatTeslas, value.ToString("F1"));

								return "";
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.MRImage.AcquisitionMatrix",
						resolver,
						delegate(Frame frame)
							{
								// the acquisition matrix of an MR image refers to the dimensions of the raw data as acquired by the modality
								// which is encoded in frequency domain, so the two axes are phase and frequency
								// it seems that we simply want the width x height of the raw data here
								// which is basically figuring out whether phase is rows or cols, and formatting the numbers appropriately
								string phaseDirection = frame[DicomTags.InPlanePhaseEncodingDirection].ToString().ToUpperInvariant();

								var acqAttrib = frame[DicomTags.AcquisitionMatrix];
								if (!acqAttrib.IsEmpty && acqAttrib.Count >= 4)
								{
									// the order of the values in this attribute is: freq-rows \ freq-cols \ phase-rows \ phase-cols
									// the acquisition matrix tag is used by MR Image module, which uses the code string COL and ROW
									switch (phaseDirection)
									{
										case "COL":
											const int phaseColumns = 3;
											const int frequencyRows = 0;
											return String.Format(SR.Format2Dimensions, acqAttrib.GetUInt16(phaseColumns, 0), acqAttrib.GetUInt16(frequencyRows, 0));
										case "ROW":
										default:
											const int frequencyColumns = 1;
											const int phaseRows = 2;
											return String.Format(SR.Format2Dimensions, acqAttrib.GetUInt16(frequencyColumns, 0), acqAttrib.GetUInt16(phaseRows, 0));
									}
								}
								else
								{
									int phaseSteps, frequencySteps;
									if (frame[DicomTags.MrAcquisitionFrequencyEncodingSteps].TryGetInt32(0, out frequencySteps)
									    && frame[DicomTags.MrAcquisitionPhaseEncodingStepsInPlane].TryGetInt32(0, out phaseSteps))
									{
										// in the MR FOV/Geometry functional group, the code strings are COLUMN, ROW and OTHER
										switch (phaseDirection)
										{
											case "COLUMN":
												return string.Format(SR.Format2Dimensions, phaseSteps, frequencySteps);
											case "ROW":
												return string.Format(SR.Format2Dimensions, frequencySteps, phaseSteps);
										}
									}
								}

								return string.Empty;
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.MRImage.ReceiveCoilName",
						resolver,
						delegate(Frame frame)
							{
								string value;
								value = frame[DicomTags.ReceiveCoilName].GetString(0, null);
								return value;
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.MRImage.RepetitionTime",
						resolver,
						delegate(Frame frame)
							{
								double value;
								bool tagExists = frame[DicomTags.RepetitionTime].TryGetFloat64(0, out value);
								if (tagExists)
									return String.Format(SR.FormatMilliseconds, value.ToString("F2"));

								return "";
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.MRImage.EchoTrainLength",
						resolver,
						delegate(Frame frame)
							{
								int value;
								bool tagExists = frame[DicomTags.EchoTrainLength].TryGetInt32(0, out value);
								if (tagExists)
									return String.Format("{0}", value);

								return "";
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.MRImage.InversionTime",
						resolver,
						delegate(Frame frame)
							{
								double value;
								var tagExists = frame[DicomTags.InversionTime].TryGetFloat64(0, out value);
								if (tagExists) return string.Format(SR.FormatMilliseconds, value.ToString("F2"));

								DicomAttribute dicomAttribute;
								if (((IDicomAttributeProvider) frame).TryGetAttribute(DicomTags.InversionTimes, out dicomAttribute) && !dicomAttribute.IsEmpty && !dicomAttribute.IsNull)
								{
									var values = dicomAttribute.Values as double[];
									if (values != null) return string.Format(SR.FormatMilliseconds, DicomStringHelper.GetDicomStringArray(values, "F2"));
								}
								return string.Empty;
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.MRImage.TriggerTime",
						resolver,
						delegate(Frame frame)
							{
								double value;
								var tagExists = frame[DicomTags.TriggerTime].TryGetFloat64(0, out value);
								if (tagExists) return string.Format(SR.FormatMilliseconds, value.ToString("F2"));

								DicomAttribute dicomAttribute;
								if (((IDicomAttributeProvider) frame).TryGetAttribute(DicomTags.NominalCardiacTriggerDelayTime, out dicomAttribute) && !dicomAttribute.IsEmpty && !dicomAttribute.IsNull)
								{
									tagExists = dicomAttribute.TryGetFloat64(0, out value);
									if (tagExists) return string.Format(SR.FormatMilliseconds, value.ToString("F2"));
								}
								return string.Empty;
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.MRImage.NumberOfAverages",
						resolver,
						delegate(Frame frame)
							{
								double value;
								var tagExists = frame[DicomTags.NumberOfAverages].TryGetFloat64(0, out value);
								return tagExists ? string.Format("{0}", value) : string.Empty;
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.MRImage.PixelBandwidth",
						resolver,
						delegate(Frame frame)
							{
								double value;
								var tagExists = frame[DicomTags.PixelBandwidth].TryGetFloat64(0, out value);
								return tagExists ? string.Format(SR.FormatHertzPerPixel, value.ToString("F2")) : string.Empty;
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);

			_annotationItems.Add
				(
					new DicomAnnotationItem<string>
						(
						"Dicom.MRImage.FlipAngle",
						resolver,
						delegate(Frame frame)
							{
								double value;
								var tagExists = frame[DicomTags.FlipAngle].TryGetFloat64(0, out value);
								return tagExists ? string.Format(SR.FormatDegrees, value.ToString("F2")) : string.Empty;
							},
						DicomDataFormatHelper.RawStringFormat
						)
				);
		}