C#
Objective-C
C++/CLI
public DicomCodeSequenceItem SensitivityUnits { get; }
@property (nonatomic, strong, readonly, nullable) LTDicomCodeSequenceItem *sensitivityUnits;
public:
property DicomCodeSequenceItem^ SensitivityUnits {
DicomCodeSequenceItem^ get();
}
Value indicating the channel sensitivity units.
For more information, refer to the "Channel Sensitivity Units Sequence" (003A,0211) element in the DICOM standard.
using Leadtools;
using Leadtools.Dicom;
public void InsertECGCWaveform(DicomDataSet inputDS, short[] samples, int count)
{
// Our new waveform group
DicomWaveformGroup ECGWaveformGroup = new DicomWaveformGroup();
// Reset the waveform group, we don't
// really need to call this!
ECGWaveformGroup.Reset();
// Set the number of samples per channel. You can call
// DicomWaveformGroup.GetNumberOfSamplesPerChannel to get
// the number of samples
ECGWaveformGroup.SetNumberOfSamplesPerChannel(count);
// Set the sampling frequency. You can call
// DicomWaveformGroup.GetSamplingFrequency to
// get the sampling frequency
ECGWaveformGroup.SetSamplingFrequency(240.00);
// Set sample interpretation
ECGWaveformGroup.SetSampleInterpretation(DicomWaveformSampleInterpretationType.Signed16BitLinear);
// Just in case!
Debug.Assert(ECGWaveformGroup.GetSampleInterpretation() == DicomWaveformSampleInterpretationType.Signed16BitLinear);
// No Multiplex Group Time Offset
// You can call DicomWaveformGroup.GetMultiplexGroupTimeOffset
// to get the time offset
ECGWaveformGroup.SetMultiplexGroupTimeOffset(false, 0.0);
// No Trigger Time Offset
// You can call DicomWaveformGroup.GetTriggerTimeOffset
// to get the trigger time offset
ECGWaveformGroup.SetTriggerTimeOffset(false, 0.0);
// No Trigger Sample Position
// You can call DicomWaveformGroup.GetTriggerSamplePosition
// to get the trigger sample position
ECGWaveformGroup.SetTriggerSamplePosition(false, 0);
// Waveform originality is original
ECGWaveformGroup.SetWaveformOriginality(DicomWaveformOriginalityType.Original);
// Just in case!
Debug.Assert(ECGWaveformGroup.GetWaveformOriginality() == DicomWaveformOriginalityType.Original);
// Set the multiplex group label
ECGWaveformGroup.SetMultiplexGroupLabel("SCPECG Waveform");
Debug.Assert(ECGWaveformGroup.GetMultiplexGroupLabel() == "SCPECG Waveform");
// Set the Waveform padding value
// You can call DicomWaveformGroup.GetWaveformPaddingValue
// to get the waveform padding value
ECGWaveformGroup.SetWaveformPaddingValue(true, 32768);
InsertECGCChannel(ECGWaveformGroup, samples, count);
// Delete any waveform groups that already exist in the dataset
for (int index = 0; index < inputDS.WaveformGroupCount; index++)
{
inputDS.DeleteWaveformGroup(index);
}
// Insert the new waveform group into the dataset
inputDS.AddWaveformGroup(ECGWaveformGroup, 0);
// Populate sensitivity information of waveform group channels
PopulateChannelsSensitivityInformation(ECGWaveformGroup);
}
// Add an ECG channel to the group
void InsertECGCChannel(DicomWaveformGroup ECGWaveformGroup, short[] samples, int count)
{
// Add a channel to the group
DicomWaveformChannel ECGChannel = ECGWaveformGroup.AddChannel(1);
if (ECGChannel == null)
{
return;
}
// If we want to update a channel, we can first call
// DicomWaveformGroup.DeleteChannel and then call
// DicomWaveformGroup.AddChannel with the same
// index we passed to DeleteChannel
// Make sure that the channel really got added
// This is for the purposes of this sample only, because
// the check we did in the previous statement is enough
if ((ECGWaveformGroup.ChannelCount != 1) ||
(ECGWaveformGroup.GetChannel(0) == null))
{
return;
}
// We can call DicomWaveformChannel.GetWaveformGroup to access the waveform
// group that the channel belongs to
if (ECGChannel.Index != 0)
{
return;
}
/*
Set the channel samples
The data we are setting in here is 16 bit data.
We would call SetChannelSamples8 if the data were 8 bit.
We can also call SetChannelSamples32, which will set the data
as either 8-bit or 16-bit depending on the sample interpretation
*/
if (ECGChannel.SetChannelSamples16(samples, count) != count)
{
return;
}
if ((ECGChannel.GetChannelSamples() == null) || (ECGChannel.GetChannelSamplesCount() == 0))
return;
// Set the channel source and sensitivity
SetChannelSourceAndSensitivity(ECGChannel);
// Set the channel status
ECGChannel.SetChannelStatus(DicomChannelStatusType.OK);
if (ECGChannel.GetChannelStatus() != DicomChannelStatusType.OK)
{
return;
}
// Set the channel time skew. You can call
// LDicomWaveformChannel::GetChannelTimeSkew to get the time skew
// You can also call DicomWaveformChannel.SetChannelSampleSkew
// And DicomWaveformChannel.GetChannelSampleSkew to set and get
// the channel samples skew
ECGChannel.SetChannelTimeSkew(0.000000);
// Set the waveform channel number
ECGChannel.SetWaveformChannelNumber(true, 0);
if (ECGChannel.GetWaveformChannelNumber() != 0)
return;
// Set the channel label
ECGChannel.SetChannelLabel("First Channel");
if (ECGChannel.GetChannelLabel() != "First Channel")
return;
// No channel offset
// You can also call DicomWaveformChannel.GetChannelOffset
// To get the channel offset
ECGChannel.SetChannelOffset(false, 0.0);
// Set filter low frequency
// You can also call DicomWaveformChannel.GetFilterLowFrequency
// To get the filter low frequency
ECGChannel.SetFilterLowFrequency(true, 0.050);
// Set filter high frequency
// You can also call DicomWaveformChannel.GetFilterHighFrequency
// To get the filter high frequency
ECGChannel.SetFilterHighFrequency(true, 100.00);
// Set the channel minimum value
ECGChannel.SetChannelMinimumValue(true, -386);
// Set the channel maximum value
ECGChannel.SetChannelMaximumValue(true, 1264);
if (ECGChannel.GetChannelMinimumValue() != -386)
return;
if (ECGChannel.GetChannelMaximumValue() != 1264)
return;
/*
You can also call the following functions to set and get the notch
filter frequency and bandwidth
DicomWaveformChannel.SetNotchFilterFrequency
DicomWaveformChannel.GetNotchFilterFrequency
DicomWaveformChannel.SetNotchFilterBandwidth
DicomWaveformChannel.GetNotchFilterBandwidth
*/
// Last, but not least, set the channel annotations!
SetChannelAnnotations(ECGChannel);
}
//Set the channel source and sensitivity
void SetChannelSourceAndSensitivity(DicomWaveformChannel channel)
{
// Let's use the DICOM context group tables!
///////////////////////Channel Source/////////////////////////
// Load the ECG Leads table
DicomContextGroupTable.Instance.Load(DicomContextIdentifierType.CID3001);
DicomContextGroup ECGLeadsGroup = DicomContextGroupTable.Instance.Find(DicomContextIdentifierType.CID3001);
Assert.IsNotNull(ECGLeadsGroup);
DicomContextIdentifierType type = ECGLeadsGroup.ContextIdentifier;
DicomCodedConcept codedConcept = DicomContextGroupTable.Instance.FindCodedConcept(ECGLeadsGroup, "MDC", "2:1");
Assert.IsNotNull(codedConcept);
using (DicomCodeSequenceItem codeSequenceItem = new DicomCodeSequenceItem())
{
codeSequenceItem.CodeValue = codedConcept.CodeValue;
codeSequenceItem.CodingSchemeDesignator = codedConcept.CodingSchemeDesignator;
codeSequenceItem.CodingSchemeVersion = codedConcept.CodingSchemeVersion;
codeSequenceItem.CodeMeaning = codedConcept.CodeMeaning;
// Set the channel source
channel.SetChannelSource(codeSequenceItem);
}
///////////////////////Channel Sensitivity////////////////////////
using (DicomCodeSequenceItem sourceSequenceItem = new DicomCodeSequenceItem())
{
sourceSequenceItem.CodeValue = "mV";
sourceSequenceItem.CodingSchemeDesignator = "UCUM";
sourceSequenceItem.CodingSchemeVersion = string.Empty;
sourceSequenceItem.CodeMeaning = "millivolt";
// Set the channel sensitivity
channel.SetChannelSensitivity(true, 0.001220, sourceSequenceItem, 1.0, 0.0);
}
}
// Add annotations for the channel
void SetChannelAnnotations(DicomWaveformChannel channel)
{
// Delete any existing channel annotations
for (int index = 0; index < channel.GetAnnotationCount(); index++)
{
if (channel.GetAnnotation(index) != null)
{
channel.DeleteAnnotation(index);
}
}
DicomWaveformAnnotation waveformAnnotation = new DicomWaveformAnnotation();
DicomCodeSequenceItem codedName = new DicomCodeSequenceItem();
codedName.CodeValue = "8867-4";
codedName.CodeMeaning = "Heart rate";
codedName.CodingSchemeDesignator = "LN";
codedName.CodingSchemeVersion = "19971101";
waveformAnnotation.CodedName = codedName;
//Over here we can access other properties such as
// waveformAnnotation.CodedValue and waveformAnnotation.UnformattedTextValue
DicomCodeSequenceItem measurementUnits = new DicomCodeSequenceItem();
measurementUnits.CodeValue = "{H.B.}/min";
measurementUnits.CodeMeaning = "Heart beat per minute";
measurementUnits.CodingSchemeDesignator = "UCUM";
measurementUnits.CodingSchemeVersion = "1.4";
waveformAnnotation.MeasurementUnits = measurementUnits;
waveformAnnotation.SetNumericValue(new double[] { 69.00 }, 1);
channel.AddAnnotation(waveformAnnotation);
}
// Reports a channel's sensitivity information within the waveform group.
void PopulateChannelsSensitivityInformation(DicomWaveformGroup ECGWaveformGroup)
{
string strItemText;
DicomWaveformChannel channel = null;
for (int nIndex = 0; nIndex < ECGWaveformGroup.ChannelCount; nIndex++)
{
channel = ECGWaveformGroup.GetChannel(nIndex);
if (channel == null)
continue;
DicomChannelSensitivity channelSensitivity = channel.GetChannelSensitivity();
if (channelSensitivity == null)
continue;
if (channelSensitivity.SensitivityUnits.CodeMeaning == null)
continue;
if (string.IsNullOrEmpty(channelSensitivity.SensitivityUnits.CodeMeaning))
continue;
strItemText = string.Format("Channel sensitivity is included: {0}", channelSensitivity.Include.ToString());
strItemText += string.Format("\nSensitivity value is: {0:g}", channelSensitivity.Sensitivity);
strItemText += string.Format("\nSensitivity units value is: {0}", channelSensitivity.SensitivityUnits.CodeMeaning);
strItemText += string.Format("\nBaseline value is: {0:g}", channelSensitivity.Baseline);
strItemText += string.Format("\nSensitivity correction factor value is: {0:g}", channelSensitivity.SensitivityCF);
Console.WriteLine(strItemText);
}
}