L_DicomChannelSetSamples8

#include "Ltdic.h"

L_UINT32 EXT_FUNCTION L_DicomChannelSetSamples8(hDICOMWaveFormChannel, pSamples, uCount)

HDICOMWAVEFORMCHANNEL hDICOMWaveFormChannel;

/* a DICOM waveform channel handle*/

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

hDICOMWaveFormChannel

A DICOM waveform channel handle

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 L_DicomChannelSetSamples8 function, be sure to call L_DicomWaveGrpSetSampleInterpretation 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 L_DicomWaveGrpGetNumberOfSamplesPerChannel 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 L_DicomWaveGrpGetSampleInterpretation 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:

L_DicomChannelSetSamples16, L_DicomChannelSetSamples32, L_DicomChannelGetSamples, L_DicomChannelGetWaveformGroup, L_DicomWaveGrpGetNumberOfChannels, L_DicomWaveGrpGetChannel, L_DicomWaveGrpAddChannel, L_DicomWaveGrpDeleteChannel

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(HDICOMWAVEFORMCHANNEL  hECGChannel);

BOOL SetChannelAnnotations(HDICOMWAVEFORMCHANNEL  hECGChannel);

BOOL InsertECGCChannel( HDICOMWAVEFORMGROUP hECGWaveformGroup,

                        L_INT16* pSamples,

                        L_UINT32 uSampleCount);

 

// The main function that creates the 

// waveform group and adds to the dataset

BOOL InsertECGCWaveform

(

   HDICOMDS hInputDS, 

   L_INT16* pSamples, 

   L_UINT32 uSampleCount

)

{

   HDICOMWAVEFORMGROUP  hECGWaveformGroup = NULL;

   L_UINT32             uWaveformGroupCount=0;

   L_UINT32             uIndex=0;

 

   // Sanity check

   if(!pSamples || (uSampleCount == 0) || !hInputDS) 

   {

      return FALSE;   

   }

 

   // Our new waveform group

   hECGWaveformGroup = L_DicomWaveGrpCreate();

   if(hECGWaveformGroup == NULL)

   {

      return FALSE;

   }

   

   // Reset the waveform group, we don't 

   // really need to call this!

   L_DicomWaveGrpReset(hECGWaveformGroup);

   

   

   // Set the number of samples per channel. You can call 

   // L_DicomWaveGrpGetNumberOfSamplesPerChannel to get 

   // the number of samples

          

   if(!L_DicomWaveGrpSetNumberOfSamplesPerChannel(hECGWaveformGroup,uSampleCount))

   {

      L_DicomWaveGrpFree(hECGWaveformGroup);

      return FALSE;

   }

 

   // Set the sampling frequency. You can call 

   // L_DicomWaveGrpGetSamplingFrequency to 

   // get the sampling frequency

   L_DicomWaveGrpSetSamplingFrequency(hECGWaveformGroup,240.00);

   // Set sample interpretation

   if(!L_DicomWaveGrpSetSampleInterpretation(hECGWaveformGroup,DICOM_SAMPLE_INTERPRETATION_SS))

   {

      L_DicomWaveGrpFree(hECGWaveformGroup);

      return FALSE;

   }

   // Just in case!

   if(L_DicomWaveGrpGetSampleInterpretation(hECGWaveformGroup) !=DICOM_SAMPLE_INTERPRETATION_SS)

   {

      L_DicomWaveGrpFree(hECGWaveformGroup);

      return FALSE;

   }

 

   // No Multiplex Group Time Offset

   // You can call L_DicomWaveGrpGetMultiplexGroupTimeOffset 

   // to get the time offset

   if(!L_DicomWaveGrpSetMultiplexGroupTimeOffset(hECGWaveformGroup,FALSE, 0.0))

   {

      L_DicomWaveGrpFree(hECGWaveformGroup);

      return FALSE;

   }

   // No Trigger Time Offset

   // You can call L_DicomWaveGrpGetTriggerTimeOffset 

   // to get the trigger time offset

   if(!L_DicomWaveGrpSetTriggerTimeOffset(hECGWaveformGroup,FALSE, 0.0))

   {

      L_DicomWaveGrpFree(hECGWaveformGroup);

      return FALSE;   

   }   

   // No Trigger Sample Position

   // You can call L_DicomWaveGrpGetTriggerSamplePosition

   // to get the trigger sample position

   if(!L_DicomWaveGrpSetTriggerSamplePosition(hECGWaveformGroup,FALSE, 0))

   {

      L_DicomWaveGrpFree(hECGWaveformGroup);

      return FALSE;

   }

 

   // Waveform originality is original   

   L_DicomWaveGrpSetOriginality(hECGWaveformGroup,DICOM_WAVEFORM_ORIGINALITY_ORIGINAL);

   

   // Just in case

   if(L_DicomWaveGrpGetOriginality(hECGWaveformGroup) != DICOM_WAVEFORM_ORIGINALITY_ORIGINAL)

   {

      L_DicomWaveGrpFree(hECGWaveformGroup);

      return FALSE;   

   }

   

   // Set the multiplex group label

   if(!L_DicomWaveGrpSetMultiplexGroupLabel(hECGWaveformGroup,"SCPECG Waveform"))

   {

      L_DicomWaveGrpFree(hECGWaveformGroup);

      return FALSE;

   }

   if(L_DicomWaveGrpGetMultiplexGroupLabel(hECGWaveformGroup) == NULL)

   {

      L_DicomWaveGrpFree(hECGWaveformGroup);

      return FALSE;

   }

 

   // Set the Waveform padding value

   // You can call L_DicomWaveGrpGetPaddingValue

   // to get the waveform padding value

   if(!L_DicomWaveGrpSetPaddingValue(hECGWaveformGroup,TRUE,32768))

   {

      L_DicomWaveGrpFree(hECGWaveformGroup);

      return FALSE;   

   }

   

   if (!InsertECGCChannel(hECGWaveformGroup, pSamples, uSampleCount))

   {

      L_DicomWaveGrpFree(hECGWaveformGroup);

      return FALSE;

   }

   // Delete any waveform groups that already exist in the dataset

   uWaveformGroupCount = L_DicomGetWaveformGroupCount(hInputDS);

   for(uIndex = 0 ; uIndex < uWaveformGroupCount ; uIndex++)

   {

      L_DicomDeleteWaveformGroup(hInputDS,uIndex,0);

   }

   // Insert the new waveform group into the dataset

   if(L_DicomAddWaveformGroup(hInputDS,hECGWaveformGroup,0, ELEMENT_INDEX_MAX)!= DICOM_SUCCESS)

   {

      L_DicomWaveGrpFree(hECGWaveformGroup);

      return FALSE;   

   }

   L_DicomWaveGrpFree(hECGWaveformGroup);

   return TRUE;

}

 

// Add an ECG channel to the group

BOOL InsertECGCChannel

(  

   HDICOMWAVEFORMGROUP  hECGWaveformGroup,

   L_INT16*             pSamples,

   L_UINT32             uSampleCount

)

{

   HDICOMWAVEFORMCHANNEL  hECGChannel  =  NULL;

   L_UINT32 uNumberOfSamples           =  0;

   L_INT32  nChannelNumber             =  -1;

   L_INT32  nMinValue                  =  0;

   L_INT32  nMaxValue                  =  0;

   

   if(hECGWaveformGroup == NULL)

   {

      return FALSE;   

   }

 

   // Add a channel to the group

   // If you want to create a channel which is not part of a waveform group, then you need to 

   // call the L_DicomChannelCreate function to create it, and then call L_DicomChannelFree to free

   // it when you are 

  // finished with the channel. This is not recommended, however.

  // When creating a channel, it is best to call L_DicomWaveGrpAddChannel which creates a channel

   // as part of a waveform group.

   hECGChannel = L_DicomWaveGrpAddChannel(hECGWaveformGroup,ELEMENT_INDEX_MAX);

   if(hECGChannel == NULL)

   {

      return FALSE;

   }

   // If we want to update a channel, we can first call 

   // L_DicomWaveGrpDeleteChannel and then call 

   // L_DicomWaveGrpAddChannel with the same 

   // index we passed to L_DicomWaveGrpDeleteChannel

 

   // 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(   (L_DicomWaveGrpGetNumberOfChannels(hECGWaveformGroup) !=1)||

         (L_DicomWaveGrpGetChannel(hECGWaveformGroup,0) ==NULL) )

   {

      return FALSE;   

   }   

   // Sanity checks!

   if((L_DicomChannelGetWaveformGroup(hECGChannel) != hECGWaveformGroup)||

      (L_DicomChannelGetIndex(hECGChannel) != 0))

   {

      return FALSE;   

   }   

   /*

         Set the channel samples

         The data we are setting in here is 16 bit data. 

         We would call L_DicomChannelSetSamples8 if the data were 8 bit. 

         We can also call L_DicomChannelSetSamples32, which will set the data 

         as either 8-bit or 16-bit depending on the sample interpretation   

   */

   if(L_DicomChannelSetSamples16(hECGChannel,pSamples, uSampleCount)!=uSampleCount)

   {

      return FALSE;

   }

   // Just in case

   if((!L_DicomChannelGetSamples(hECGChannel,&uNumberOfSamples))||

      (uNumberOfSamples == 0))

   {

      return FALSE;   

   }

   // Set the channel source and sensitivity

   if(!SetChannelSourceAndSensitivity(hECGChannel))

   {

      return FALSE;

   }

   // Set the channel status

   L_DicomChannelSetStatus(hECGChannel,DICOM_CHANNEL_STATUS_OK);

   if(L_DicomChannelGetStatus(hECGChannel)!=DICOM_CHANNEL_STATUS_OK)

   {

      return FALSE;   

   }

   // Set the channel time skew. You can call 

   // L_DicomChannelGetTimeSkew to get the time skew

   // You can also call L_DicomChannelSetSampleSkew

   // And L_DicomChannelGetSampleSkew to set and get 

   // the channel samples skew

   L_DicomChannelSetTimeSkew(hECGChannel,0.000000);

 

   // Set the waveform channel number

   if(!L_DicomChannelSetNumber(hECGChannel,TRUE, 0))

   {

      return FALSE;   

   }

   if((!L_DicomChannelGetNumber(hECGChannel,&nChannelNumber))||

      (nChannelNumber !=0))

   {

      return FALSE;   

   }

   // Set the channel label   

   if(!L_DicomChannelSetLabel(hECGChannel,"First Channel"))

   {

      return FALSE;   

   }

   if(!L_DicomChannelGetLabel(hECGChannel))

   {

      return FALSE;   

   }

   // No channel offset

   // You can also call L_DicomChannelGetOffset

   // To get the channel offset

   if(!L_DicomChannelSetOffset(hECGChannel,FALSE, 0.0))

   {

      return FALSE;      

   }

   // Set filter low frequency

   // You can also call L_DicomChannelGetFilterLowFrequency

   // To get the filter low frequency   

   if(!L_DicomChannelSetFilterLowFrequency(hECGChannel,TRUE, 0.050))

   {

      return FALSE;      

   }   

   // Set filter high frequency

   // You can also call L_DicomChannelGetFilterHighFrequency

   // To get the filter high frequency   

   if(!L_DicomChannelSetFilterHighFrequency(hECGChannel,TRUE, 100.00))

   {

      return FALSE;      

   }   

   // These are hard-coded values!

   // Set the channel minimum value 

   if(!L_DicomChannelSetMinimumValue(hECGChannel,TRUE, -386))

   {

      return FALSE;      

   }   

   // Set the channel maximum value

   if(!L_DicomChannelSetMaximumValue(hECGChannel,TRUE, 1264))

   {

      return FALSE;      

   }

   // Just in case

   if((!L_DicomChannelGetMinimumValue(hECGChannel,&nMinValue))||

      (nMinValue !=-386))

   {

      return FALSE;      

   }

   // Just in case

   if((!L_DicomChannelGetMaximumValue(hECGChannel,&nMaxValue))||

      (nMaxValue !=1264))

   {

      return FALSE;      

   }          

   /*

      You can also call the following functions to set and get the notch 

      filter frequency and bandwidth

      L_DicomChannelSetNotchFilterFrequency

      L_DicomChannelGetNotchFilterFrequency

      L_DicomChannelSetNotchFilterBandwidth

      L_DicomChannelGetNotchFilterBandwidth   

   */ 

 

   // Last, but not least, set the channel annotations!

   return SetChannelAnnotations(hECGChannel);

}

 

//Set the channel source and sensitivity

BOOL SetChannelSourceAndSensitivity(HDICOMWAVEFORMCHANNEL  hECGChannel)

{

      

   pDICOMCONTEXTGROUP pCardiologyUnitsGroup;

   pDICOMCONTEXTGROUP pECGLeadsGroup;

 

   // Let's use the DICOM context group tables!

 

   ///////////////////////Channel Source/////////////////////////   

   // Load the ECG Leads table 

   L_DicomLoadContextGroup(CID_3001);   

   pECGLeadsGroup = L_DicomFindContextGroup(CID_3001);

   if(pECGLeadsGroup)

   {

      // 5.6.3-9-1 is Lead I (Einthoven)

      pDICOMCODEDCONCEPT pCodedConcept = L_DicomFindCodedConcept( 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 = L_DicomChannelSetSource(hECGChannel,&DicomSourceSequenceItem);

         if(uRet!= DICOM_SUCCESS)

         {

            return FALSE;

         }

         // You can call L_DicomChannelGetSource() 

         // to get the channel source

      }

      else

      {

         return FALSE;

      }

   }

   else

   {

      return FALSE;

   }

 

   ///////////////////////Channel Sensitivity////////////////////////

   

   // Cardiology Units of Measurement

   L_DicomLoadContextGroup(CID_3082);   

   pCardiologyUnitsGroup = L_DicomFindContextGroup(CID_3082);

   if(pCardiologyUnitsGroup)

   {

      pDICOMCODEDCONCEPT pCodedConcept = L_DicomFindCodedConcept( 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 = L_DicomChannelSetSensitivity(   hECGChannel,

                                                TRUE,

                                                0.001220,

                                                &DicomSourceSequenceItem,

                                                1.0,

                                                0.0);

         if(uRet  != DICOM_SUCCESS)

         {

            return FALSE;

         }         

         // You can call L_DicomChannelGetSensitivity() 

         // to get the channel sensitivity

      }

      else

      {

         return FALSE;

      }

   }

   else

   {

      return FALSE;

   }

 

   return TRUE;

}

 

// Add annotations for the channel

BOOL SetChannelAnnotations(HDICOMWAVEFORMCHANNEL  hECGChannel)

{

 

   L_UINT32 uIndex = 0 ;

   DICOMWAVEFORMANNOTATION ECGWaveformAnnotation;

   DICOMCODESEQUENCEITEM CodedName;

   L_DOUBLE dNumericValue = 69.00;

   DICOMCODESEQUENCEITEM MeasurementUnits;

 

   // Delete any existing channel annotations

   for(uIndex = 0 ; uIndex <L_DicomChannelGetAnnotationCount(hECGChannel);uIndex++)

   {

      if(L_DicomChannelGetAnnotation(hECGChannel,uIndex))

      {

         L_DicomChannelDeleteAnnotation(hECGChannel,uIndex);

      }

   }

   

   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

 

   //

   

   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;

   

   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;   

   ECGWaveformAnnotation.pNumericValue = &dNumericValue ;

   ECGWaveformAnnotation.uNumericValueCount = 1;

 

   if(L_DicomChannelAddAnnotation(hECGChannel,&ECGWaveformAnnotation) != DICOM_SUCCESS)

   {

      return FALSE;

   }

 

   return TRUE;

}