Inserting a Waveform Group Into a Data Set Example for Visual Basic

'*****************************************************************'
'*  This is a comprehensive sample, which shows how to insert a  *'
'*  waveform group with one ECG channel into a Data Set.         *'
'*  The main function is InsertECGWaveform; the rest of the      *'
'*  functions are helping functions.                             *'
'*****************************************************************'

' The main function that creates the waveform group and adds to the Data Set
Function InsertECGWaveform(objDataSet As LEADDicomDS, Samples() As Integer) As Boolean
   InsertECGWaveform = False
   
   ' Our new waveform group
   Dim objECGWaveformGroup As New DicomWaveformGroup
   
   objECGWaveformGroup.EnableMethodErrors = False
   
   ' Reset the waveform group, we don't really need to call this!
   objECGWaveformGroup.Reset
   
   ' Set the Waveform Sample Interpretation
   objECGWaveformGroup.SampleInterpretation = WAVEFORM_SAMPLE_INTERPRETATION_SS
   
   Dim lNumberOfSamples As Long
   lNumberOfSamples = UBound(Samples) - LBound(Samples) + 1
   
   ' Set the Number of Waveform Samples. You can obtain this number by accessing
   ' the NumberOfSamplesPerChannel property.
   If objECGWaveformGroup.SetNumberOfSamplesPerChannel (lNumberOfSamples) <> DICOM_SUCCESS Then
      Exit Function
   End If

   ' Set the Sampling Frequency
   objECGWaveformGroup.SamplingFrequency = 240#

   ' No Multiplex Group Time Offset. When the value is defined, it can be set using the
   ' MultiplexGroupTimeOffset property.
   objECGWaveformGroup.ValueDefined (MULTIPLEX_GROUP_TIME_OFFSET) = False
   
   ' No Trigger Time Offset. When the value is defined, it can be set using the
   ' TriggerTimeOffset property.
   objECGWaveformGroup.ValueDefined (TRIGGER_TIME_OFFSET) = False
   
   ' No Trigger Sample Position. When the value is defined, it can be set using the
   ' TriggerSamplePosition property.
   objECGWaveformGroup.ValueDefined (TRIGGER_SAMPLE_POSITION) = False

   ' Waveform Originality is ORIGINAL
   objECGWaveformGroup.WaveformOriginality = WAVEFORM_ORIGINALITY_ORIGINAL
   
   ' Set the Multiplex Group Label
   objECGWaveformGroup.ValueDefined (MULTIPLEX_GROUP_LABEL) = True
   objECGWaveformGroup.MultiplexGroupLabel = "SCPECG Waveform"

   ' Set the Waveform Padding Value
   objECGWaveformGroup.ValueDefined (WAVEFORM_PADDING_VALUE) = True
   objECGWaveformGroup.WaveformPaddingValue = 32768
   
   If Not InsertECGChannel(objDataSet, objECGWaveformGroup, Samples) Then
      Exit Function
   End If
   
   ' Delete any waveform groups that already exist in the Data Set
   Do While objDataSet.GetWaveformGroupCount () > 0
      objDataSet.DeleteWaveformGroup 0
   Loop
   
   ' Insert the new waveform group into the Data Set
   If objDataSet.AddWaveformGroup (objECGWaveformGroup) <> DICOM_SUCCESS Then
      Exit Function
   End If
   
   InsertECGWaveform = True
End Function

' Adds an ECG channel to the group
Function InsertECGChannel(objDataSet As LEADDicomDS, _
                          objWaveformGroup As DicomWaveformGroup, _
                          Samples() As Integer) As Boolean
   InsertECGChannel = False
   
   Dim objECGWaveformChannel As DicomWaveformChannel
   
   ' Add a channel to the group
   On Error Resume Next
   Set objECGWaveformChannel = objWaveformGroup.Channels.Add ()
   If Err.Number <> 0 Then
      Exit Function
   End If
   On Error GoTo 0
   
   ' Set the samples of the channel
   If objECGWaveformChannel.SetChannelSamples (Samples) < 0 Then
      Exit Function
   End If
   
   ' Set the Channel Source and Sensitivity
   If Not SetChannelSourceAndSensitivity(objDataSet, objECGWaveformChannel) Then
      Exit Function
   End If
   
   ' Set the Channel Status
   objECGWaveformChannel.ValueDefined (CHANNEL_STATUS) = True
   objECGWaveformChannel.ChannelStatus = CHANNEL_STATUS_OK
   
   ' Set the Channel Time Skew
   objECGWaveformChannel.ValueDefined (CHANNEL_TIME_SKEW) = True
   objECGWaveformChannel.ChannelTimeSkew = 0#

   ' Set the Waveform Channel Number
   objECGWaveformChannel.ValueDefined (WAVEFORM_CHANNEL_NUMBER) = True
   objECGWaveformChannel.WaveformChannelNumber = 0
   
   ' Set the Channel Label
   objECGWaveformChannel.ValueDefined (CHANNEL_LABEL) = True
   objECGWaveformChannel.ChannelLabel = "First Channel"
   
   ' No Channel Offset. When the value is defined, it can be set using the ChannelOffset
   ' property
   objECGWaveformChannel.ValueDefined (CHANNEL_OFFSET) = False
   
   ' Set the Filter Low Frequency
   objECGWaveformChannel.ValueDefined (FILTER_LOW_FREQUENCY) = True
   objECGWaveformChannel.FilterLowFrequency = 0.05
   
   ' Set Filter High Frequency
   objECGWaveformChannel.ValueDefined (FILTER_HIGH_FREQUENCY) = True
   objECGWaveformChannel.FilterHighFrequency = 100#
   
   ' Set the Channel Minimum Value
   objECGWaveformChannel.ValueDefined (CHANNEL_MINIMUM_VALUE) = True
   objECGWaveformChannel.ChannelMinimumValue = -386
   
   ' Set the Channel Maximum Value
   objECGWaveformChannel.ValueDefined (CHANNEL_MAXIMUM_VALUE) = True
   objECGWaveformChannel.ChannelMaximumValue = 1264
   
   ' When the Notch Filter Frequency and Bandwidth are defined, they can be set using the
   ' NotchFilterFrequency and NotchFilterBandwidth properties.
   
   ' Last, but not least, set the channel annotations!
   InsertECGChannel = SetChannelAnnotations(objECGWaveformChannel)
End Function

' Sets the Channel Source and Sensitivity
Function SetChannelSourceAndSensitivity(objDataSet As LEADDicomDS, _
                                        objWaveformChannel As DicomWaveformChannel) _
                                        As Boolean
   SetChannelSourceAndSensitivity = False
   
   ' We will use the Context Group Table

   ' -------------------- Channel Source --------------------
   
   Const CID_3001 = "CID 3001"
   
   ' Load the ECG Leads Context Group
   objDataSet.LoadContextGroup CID_3001
   If Not objDataSet.FindContextGroup(CID_3001) Then
      Exit Function
   End If
   
   ' 5.6.3-9-1 is Lead I (Einthoven)
   If Not objDataSet.FindCodedConcept("SCPECG", "5.6.3-9-1") Then
      Exit Function
   End If
   
   ' Set the Channel Source
   With objWaveformChannel.ChannelSource
      .CodingSchemeDesignator = objDataSet.CurrentCodedConcept.CodingSchemeDesignator
      .CodingSchemeVersion = objDataSet.CurrentCodedConcept.CodingSchemeVersion
      .CodeValue = objDataSet.CurrentCodedConcept.CodeValue
      .CodeMeaning = objDataSet.CurrentCodedConcept.CodeMeaning
   End With

   ' -------------------- Channel Sensitivity --------------------
   
   objWaveformChannel.ValueDefined (CHANNEL_SENSITIVITY) = True
   
   ' The Channel Sensitivity
   objWaveformChannel.ChannelSensitivity = 0.00122
   
   Const CID_3082 = "CID 3082"
   
   ' Load the Cardiology Units of Measurement Context Group
   objDataSet.LoadContextGroup CID_3082
   If Not objDataSet.FindContextGroup(CID_3082) Then
      Exit Function
   End If
   
   If Not objDataSet.FindCodedConcept("UCUM", "mV") Then
      Exit Function
   End If
   
   ' The Channel Sensitivity Units
   With objWaveformChannel.ChannelSensitivityUnits
      .CodingSchemeDesignator = objDataSet.CurrentCodedConcept.CodingSchemeDesignator
      .CodingSchemeVersion = objDataSet.CurrentCodedConcept.CodingSchemeVersion
      .CodeValue = objDataSet.CurrentCodedConcept.CodeValue
      .CodeMeaning = objDataSet.CurrentCodedConcept.CodeMeaning
   End With
   
   ' The Channel Sensitivity Correction Factor
   objWaveformChannel.ChannelSensitivityCF = 1#
   
   ' The Channel Baseline
   objWaveformChannel.ChannelBaseline = 0#
   
   SetChannelSourceAndSensitivity = True
End Function

' Adds annotations for the channel
Function SetChannelAnnotations(objWaveformChannel As DicomWaveformChannel) As Boolean
   SetChannelAnnotations = False

   ' Delete any existing channel annotations
   Do While objWaveformChannel.Annotations.Count > 0
      objWaveformChannel.Annotations.Remove 0
   Loop

   Dim objECGWaveformAnnotation As DicomWaveformAnnotation
   
   ' Add an annotation object
   On Error Resume Next
   Set objECGWaveformAnnotation = objWaveformChannel.Annotations.Add ()
   If Err.Number <> 0 Then
      Exit Function
   End If
   On Error GoTo 0
   
   ' Our annotation is defined by a Coded Name/Numeric Measurement pair
   objECGWaveformAnnotation.ValueType = TYPE_CODED_NAME_AND_NUMERIC_VALUE
   
   ' The Coded Name. Note: Instead of setting these values directly, you can also use
   ' the Context Group Table; the Context Groups defined by the DICOM Content Mapping
   ' Resource (DCMR) can be loaded into this table. Take a look at the function
   ' SetChannelSourceAndSensitivity above for an example.
   With objECGWaveformAnnotation.CodedName
      .CodingSchemeDesignator = "LN"
      .CodingSchemeVersion = "19971101"
      .CodeValue = "8867-4"
      .CodeMeaning = "Heart rate"
   End With
   
   ' The Numeric Value
   On Error Resume Next
   objECGWaveformAnnotation.NumericValueCount = 1
   If Err.Number <> 0 Then
      Exit Function
   End If
   On Error GoTo 0
   objECGWaveformAnnotation.NumericValue(0) = 69#
   
   ' The Measurement Units. Refer to the note given when the Coded Name was set.
   objECGWaveformAnnotation.ValueDefined (MEASUREMENT_UNITS) = True
   With objECGWaveformAnnotation.MeasurementUnits
      .CodingSchemeDesignator = "UCUM"
      .CodingSchemeVersion = "1.4"
      .CodeValue = "{H.B.}/min"
      .CodeMeaning = "Heart beat per minute"
   End With
   
   SetChannelAnnotations = True
End Function