LDicomWaveformChannel::SetChannelSamples8

#include "Ltdic.h"

L_UINT32 LDicomWaveformChannel::SetChannelSamples8(pSamples, uCount)

L_CHAR* pSamples;

/* pointer to the input buffer */

L_UINT32 uCount;

/* size of the input buffer */

Sets 8-bit data for a channel.

Parameter

Description

pSamples

Pointer to the buffer that holds the new channel samples.

uCount

Size of the buffer pointed to by pSamples.

Returns

The actual number of samples set for the channel.

Comments

This function sets the new samples for a channel. Before calling the LDicomWaveformChannel::SetChannelSamples8 function, be sure to call LDicomWaveformGroup::SetSampleInterpretation to set the waveform sample interpretation.

The number of samples actually set will be less than or equal to the "Number of samples per channel" (003A, 0010) in the multiplex group that represents the parent of this channel. To get that number, call the LDicomWaveformGroup::GetNumberOfSamplesPerChannel function.

This function is intended to be used for setting the data of 8-bit channels where the "Waveform Sample Interpretation" (5400,1006) is signed 8-bit linear (DICOM_SAMPLE_INTERPRETATION_SB), unsigned 8-bit linear (DICOM_SAMPLE_INTERPRETATION_UB), 8-bit mu-law (DICOM_SAMPLE_INTERPRETATION_MB) or 8-bit A-law (DICOM_SAMPLE_INTERPRETATION_AB). To get the waveform sample interpretation, use the LDicomWaveformGroup::GetSampleInterpretation function.

Required DLLs and Libraries

LTDIC

For a listing of the exact DLLs and Libraries needed, based on the toolkit version, refer to Files To Be Included With Your Application

See Also

Functions:

Class Members, LDicomWaveformChannel::SetChannelSamples16, LDicomWaveformChannel::SetChannelSamples32, LDicomWaveformChannel::GetChannelSamples, LDicomWaveformChannel::GetWaveformGroup, LDicomWaveformGroup::GetNumberOfChannels, LDicomWaveformGroup::GetChannel, LDicomWaveformGroup::AddChannel, LDicomWaveformGroup::DeleteChannel

Topics:

Working with DICOM Waveforms

Example

/******************************************************************/
/*   This is a comprehensive sample, which shows how to insert a  */
/*   waveform group with one ECG channel into a dataset.          */
/*   The main function is InsertECGCWaveform ,and the rest of the */
/*   functions are helping functions.                             */
/******************************************************************/

// Function prototypes
BOOL SetChannelSourceAndSensitivity(LDicomWaveformChannel*  pECGChannel); 
BOOL SetChannelAnnotations(LDicomWaveformChannel*  pECGChannel); 
BOOL InsertECGCChannel( LDicomWaveformGroup* pECGWaveformGroup, 
                        L_INT16* pSamples, 
                        L_UINT32 uSampleCount); 

// The main function that creates the 
// waveform group and adds to the dataset
BOOL InsertECGCWaveform
 (
   LDicomDS &InputDS, 
   L_INT16* pSamples, 
   L_UINT32 uSampleCount

{
   // Sanity check
   if(!pSamples || (uSampleCount == 0) ) 
   {
      return FALSE;   
   }

   // Our new waveform group
   LDicomWaveformGroup  ECGWaveformGroup; 
   
   // Reset the waveform group, we don't 
   // really need to call this! 
   ECGWaveformGroup.Reset();
   
   // Set the number of samples per channel. You can call 
   // LDicomWaveformGroup::GetNumberOfSamplesPerChannel to get 
   // the number of samples
   if(!ECGWaveformGroup.SetNumberOfSamplesPerChannel(uSampleCount)) 
   {
      return FALSE; 
   }

   // Set the sampling frequency. You can call 
   // LDicomWaveformGroup::GetSamplingFrequency to 
   // get the sampling frequency
   ECGWaveformGroup.SetSamplingFrequency(240.00); 
   // Set sample interpretation
   if(!ECGWaveformGroup.SetSampleInterpretation(DICOM_SAMPLE_INTERPRETATION_SS)) 
   {
      return FALSE; 
   }
   // Just in case! 
   if(ECGWaveformGroup.GetSampleInterpretation() !=DICOM_SAMPLE_INTERPRETATION_SS) 
   {
      return FALSE; 
   }

   // No Multiplex Group Time Offset
   // You can call LDicomWaveformGroup::GetMultiplexGroupTimeOffset 
   // to get the time offset
   if(!ECGWaveformGroup.SetMultiplexGroupTimeOffset(FALSE, 0.0)) 
   {
      return FALSE; 
   }
   // No Trigger Time Offset
   // You can call LDicomWaveformGroup::GetTriggerTimeOffset 
   // to get the trigger time offset
   if(!ECGWaveformGroup.SetTriggerTimeOffset(FALSE, 0.0)) 
   {
      return FALSE;   
   }   
   // No Trigger Sample Position
   // You can call LDicomWaveformGroup::GetTriggerSamplePosition
   // to get the trigger sample position
   if(!ECGWaveformGroup.SetTriggerSamplePosition(FALSE, 0)) 
   {
      return FALSE; 
   }

   // Waveform originality is original   
   ECGWaveformGroup.SetWaveformOriginality(DICOM_WAVEFORM_ORIGINALITY_ORIGINAL); 
   
   // Just in case
   if(ECGWaveformGroup.GetWaveformOriginality() != DICOM_WAVEFORM_ORIGINALITY_ORIGINAL) 
   {
      return FALSE;   
   }
   
   // Set the multiplex group label
   if(!ECGWaveformGroup.SetMultiplexGroupLabel("SCPECG Waveform"))
   {
      return FALSE; 
   }
   if(ECGWaveformGroup.GetMultiplexGroupLabel() == NULL) 
   {
      return FALSE; 
   }

   // Set the Waveform padding value
   // You can call LDicomWaveformGroup::GetWaveformPaddingValue
   // to get the waveform padding value
   if(!ECGWaveformGroup.SetWaveformPaddingValue(TRUE,32768)) 
   {
      return FALSE;   
   }
   
   if (!InsertECGCChannel(&ECGWaveformGroup , pSamples, uSampleCount)) 
   {
      return FALSE; 
   }
   // Delete any waveform groups that already exist in the dataset
   L_UINT32 uWaveformGroupCount = InputDS.GetWaveformGroupCount();
   for(L_UINT32 uIndex = 0 ; uIndex < uWaveformGroupCount ; uIndex++)
   {
      InputDS.DeleteWaveformGroup(uIndex,0); 
   }
   // Insert the new waveform group into the dataset
   if(InputDS.AddWaveformGroup(&ECGWaveformGroup, 0, ELEMENT_INDEX_MAX)!= DICOM_SUCCESS) 
   {
      return FALSE;   
   }
   return TRUE; 
}

// Add an ECG channel to the group
BOOL InsertECGCChannel
 (  
   LDicomWaveformGroup* pECGWaveformGroup, 
   L_INT16*             pSamples, 
   L_UINT32             uSampleCount

{
   LDicomWaveformChannel*  pECGChannel= NULL; 
   L_UINT32 uNumberOfSamples  =0; 
   L_INT32  nChannelNumber =  -1; 
   L_INT32  nMinValue      =  0; 
   L_INT32  nMaxValue      =  0; 
   
   if(pECGWaveformGroup == NULL) 
   {
      return FALSE;   
   }

   // Add a channel to the group
   pECGChannel = pECGWaveformGroup->AddChannel(/*ELEMENT_INDEX_MAX*/);
   if(pECGChannel == NULL) 
   {
      return FALSE; 
   }
   // If we want to update a channel, we can first call 
   // LDicomWaveformGroup::DeleteChannel and then call 
   // LDicomWaveformGroup::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(   (pECGWaveformGroup->GetNumberOfChannels() !=1)|| 
         (pECGWaveformGroup->GetChannel(0) ==NULL) ) 
   {
      return FALSE;   
   }   
   // Sanity checks! 
   if((pECGChannel->GetWaveformGroup() != pECGWaveformGroup)|| 
      (pECGChannel->GetIndex() != 0)) 
   {
      return FALSE;   
   }   
   /*
         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(pECGChannel->SetChannelSamples16(pSamples, uSampleCount)!=uSampleCount) 
   {
      return FALSE; 
   }
   // Just in case
   if((!pECGChannel->GetChannelSamples(&uNumberOfSamples))|| 
      (uNumberOfSamples == 0)) 
   {
      return FALSE;   
   }
   // Set the channel source and sensitivity
   if(!SetChannelSourceAndSensitivity(pECGChannel)) 
   {
      return FALSE; 
   }
   // Set the channel status
   pECGChannel->SetChannelStatus(DICOM_CHANNEL_STATUS_OK); 
   if(pECGChannel->GetChannelStatus()!=DICOM_CHANNEL_STATUS_OK) 
   {
      return FALSE;   
   }
   // Set the channel time skew. You can call 
   // LDicomWaveformChannel::GetChannelTimeSkew to get the time skew
   // You can also call LDicomWaveformChannel::SetChannelSampleSkew
   // And LDicomWaveformChannel::GetChannelSampleSkew to set and get 
   // the channel samples skew
   pECGChannel->SetChannelTimeSkew(0.000000); 


   // Set the waveform channel number
   if(!pECGChannel->SetWaveformChannelNumber(TRUE, 0)) 
   {
      return FALSE;   
   }
   if((!pECGChannel->GetWaveformChannelNumber(&nChannelNumber))|| 
      (nChannelNumber !=0)) 
   {
      return FALSE;   
   }
   // Set the channel label   
   if(!pECGChannel->SetChannelLabel("First Channel"))
   {
      return FALSE;   
   }
   if(!pECGChannel->GetChannelLabel())
   {
      return FALSE;   
   }
   // No channel offset
   // You can also call LDicomWaveformChannel::GetChannelOffset
   // To get the channel offset
   if(!pECGChannel->SetChannelOffset(FALSE, 0.0)) 
   {
      return FALSE;      
   }
   // Set filter low frequency
   // You can also call LDicomWaveformChannel::GetFilterLowFrequency
   // To get the filter low frequency   
   if(!pECGChannel->SetFilterLowFrequency(TRUE, 0.050)) 
   {
      return FALSE;      
   }   
   // Set filter high frequency
   // You can also call LDicomWaveformChannel::GetFilterHighFrequency
   // To get the filter high frequency   
   if(!pECGChannel->SetFilterHighFrequency(TRUE, 100.00)) 
   {
      return FALSE;      
   }   
   // Set the channel minimum value
   if(!pECGChannel->SetChannelMinimumValue(TRUE, -386)) 
   {
      return FALSE;      
   }   
   // Set the channel maximum value
   if(!pECGChannel->SetChannelMaximumValue(TRUE, 1264)) 
   {
      return FALSE;      
   }
   // Just in case
   if((!pECGChannel->GetChannelMinimumValue(&nMinValue))|| 
      (nMinValue !=-386)) 
   {
      return FALSE;      
   }
   // Just in case
   if((!pECGChannel->GetChannelMaximumValue(&nMaxValue))|| 
      (nMaxValue !=1264)) 
   {
      return FALSE;      
   }          
   /*
      You can also call the following functions to set and get the notch 
      filter frequency and bandwidth
      LDicomWaveformChannel::SetNotchFilterFrequency
      LDicomWaveformChannel::GetNotchFilterFrequency
      LDicomWaveformChannel::SetNotchFilterBandwidth
      LDicomWaveformChannel::GetNotchFilterBandwidth   
   */ 

   // Last, but not least, set the channel annotations! 
   return SetChannelAnnotations(pECGChannel); 
}

//Set the channel source and sensitivity
BOOL SetChannelSourceAndSensitivity(LDicomWaveformChannel*  pECGChannel) 
{
      
   // Let's use the DICOM context group tables! 

   ///////////////////////Channel Source/////////////////////////   
   // Load the ECG Leads table 
   LDicomContextGroup::Load(CID_3001);   
   pDICOMCONTEXTGROUP pECGLeadsGroup = LDicomContextGroup::Find(CID_3001); 
   if(pECGLeadsGroup) 
   {
      // 5.6.3-9-1 is Lead I (Einthoven) 
      pDICOMCODEDCONCEPT pCodedConcept = LDicomContextGroup::FindCodedConcept(pECGLeadsGroup, 
                                                                              "SCPECG",
                                                                              "5.6.3-9-1");
      if(pCodedConcept) 
      {
         DICOMCODESEQUENCEITEM   DicomSourceSequenceItem; 
         L_UINT16                uRet; 

         memset(&DicomSourceSequenceItem , 0 , sizeof(DICOMCODESEQUENCEITEM)); 
         DicomSourceSequenceItem.uStructSize = sizeof(DICOMCODESEQUENCEITEM);         
        
         DicomSourceSequenceItem.pszCodeValue              = pCodedConcept->pszCodeValue                 ; 
         DicomSourceSequenceItem.pszCodingSchemeDesignator = pCodedConcept->pszCodingSchemeDesignator    ; 
         DicomSourceSequenceItem.pszCodingSchemeVersion    = pCodedConcept->pszCodingSchemeVersion       ; 
         DicomSourceSequenceItem.pszCodeMeaning            = pCodedConcept->pszCodeMeaning               ; 

         // Set the channel source         
         uRet = pECGChannel->SetChannelSource(&DicomSourceSequenceItem); 
         if(uRet!= DICOM_SUCCESS) 
         {
            return FALSE; 
         }
         // You can call LDicomWaveformChannel::GetChannelSource ()
         // to get the channel source
      }
      else
      {
         return FALSE; 
      }
   }
   else
   {
      return FALSE; 
   }

   ///////////////////////Channel Sensitivity////////////////////////
   
   // Cardiology Units of Measurement
   LDicomContextGroup::Load(CID_3082);   
   pDICOMCONTEXTGROUP pCardiologyUnitsGroup = LDicomContextGroup::Find(CID_3082); 
   if(pCardiologyUnitsGroup) 
   {
      pDICOMCODEDCONCEPT pCodedConcept = LDicomContextGroup::FindCodedConcept(pCardiologyUnitsGroup, 
                                                                              "UCUM",
                                                                              "mV");
      if(pCodedConcept) 
      {
         DICOMCODESEQUENCEITEM   DicomSourceSequenceItem; 
         L_UINT16                uRet; 

         memset(&DicomSourceSequenceItem , 0 , sizeof(DICOMCODESEQUENCEITEM)); 
         DicomSourceSequenceItem.uStructSize = sizeof(DICOMCODESEQUENCEITEM);         
        
         DicomSourceSequenceItem.pszCodeValue              = pCodedConcept->pszCodeValue                 ; 
         DicomSourceSequenceItem.pszCodingSchemeDesignator = pCodedConcept->pszCodingSchemeDesignator    ; 
         DicomSourceSequenceItem.pszCodingSchemeVersion    = pCodedConcept->pszCodingSchemeVersion       ; 
         DicomSourceSequenceItem.pszCodeMeaning            = pCodedConcept->pszCodeMeaning               ; 

         // Set the channel sensitivity
         uRet = pECGChannel->SetChannelSensitivity(  TRUE, 
                                                            0.001220, 
                                                            &DicomSourceSequenceItem); 
         if(uRet  != DICOM_SUCCESS) 
         {
            return FALSE; 
         }         
         // You can call LDicomWaveformChannel::GetChannelSensitivity()
         // to get the channel sensitivity
      }
      else
      {
         return FALSE; 
      }
   }
   else
   {
      return FALSE; 
   }

   return TRUE; 
}

// Add annotations for the channel
BOOL SetChannelAnnotations(LDicomWaveformChannel*  pECGChannel) 
{

   // Delete any existing channel annotations
   for(L_UINT32 uIndex = 0 ; uIndex <
pECGChannel->GetAnnotationCount();uIndex++)
   {
      if(pECGChannel->GetAnnotation(uIndex)) 
      {
         pECGChannel->DeleteAnnotation(uIndex); 
      }
   }

   DICOMWAVEFORMANNOTATION ECGWaveformAnnotation; 

   memset(&ECGWaveformAnnotation,0, sizeof(DICOMWAVEFORMANNOTATION)); 
   ECGWaveformAnnotation.uStructSize = sizeof(DICOMWAVEFORMANNOTATION); 

   // Over here we are populating the DICOMCODESEQUENCEITEM structure
   // directly. What we can also do is fill it with values from
   // the LDicomContextGroup table which lists all the context
   // group tables defined by the DICOM standard.  You can look at
   // the SetChannelSourceAndSensitivity above for an Example on
   // how to do that

   //
   DICOMCODESEQUENCEITEM CodedName; 
   memset(&CodedName,0, sizeof(DICOMCODESEQUENCEITEM)); 
   CodedName.uStructSize               = sizeof(DICOMCODESEQUENCEITEM); 
   CodedName.pszCodeValue              = "8867-4";
   CodedName.pszCodeMeaning            = "Heart rate";
   CodedName.pszCodingSchemeDesignator = "LN";
   CodedName.pszCodingSchemeVersion    = "19971101";

   ECGWaveformAnnotation.pCodedName = &CodedName; 

   DICOMCODESEQUENCEITEM MeasurementUnits; 
   memset(&MeasurementUnits,0, sizeof(DICOMCODESEQUENCEITEM)); 
   MeasurementUnits.uStructSize               =
sizeof(DICOMCODESEQUENCEITEM); 
   MeasurementUnits.pszCodeValue              = "{H.B.}/min";
   MeasurementUnits.pszCodeMeaning            = "Heart beat per minute";
   MeasurementUnits.pszCodingSchemeDesignator = "UCUM";
   MeasurementUnits.pszCodingSchemeVersion    = "1.4";

   ECGWaveformAnnotation.pMeasurementUnits = &MeasurementUnits; 

   L_DOUBLE dNumericValue = 69.00; 
   ECGWaveformAnnotation.pNumericValue = &dNumericValue ; 
   ECGWaveformAnnotation.uNumericValueCount = 1; 

   if(pECGChannel->AddAnnotation(&ECGWaveformAnnotation) != DICOM_SUCCESS) 
   {
      return FALSE; 
   }

   return TRUE; 
}