User Tools

Site Tools


visual3d:documentation:emg:processing:normalize_emg_to_mvc

Normalize EMG to MVC

Normalize EMG Signal to Maximum Within Gait Cycle

For this example, the goal is as follows:

  • Process the raw EMG signal
    • In this example, a simple linear envelope was done and saved in ANALOG::ENVELOPE
  • Compute the maximum of the EMG signal during each gait cycle
  • Normalize the EMG signal to the maximum during each gait cycle

Sample Files

You can download the sample files here.

The download contains:

  • Sample_Workspace.cmz with -
    • 2 Dynamic Trials
    • Processed EMG signals (ANALOG::ENVELOPE), you should use your own processing, not the example processing used to create this envelope signal
  • EMG_Norm_Gait_Cycle.v3s (Example Pipeline Script)
  • EMG_Norm_Gait_Cycle.v3m (Example Meta-Command)
  • Call_EMG_Norm_Gait_Cycle_Meta.v3s (Example Pipeline Script calling Meta-Command)

Script Explanation

The image on the right corresponds to four steps in the pipeline below. As a general outline, the procedure has the following checkpoints:

* First graph: raw EMG signal with gait events RHS (pink) and RTO (purple). These correspond to the signal within ANALOG::ORIGINAL in the Sample_Workspace.cmz download.
* Second graph: the linear envelope (ANALOG::ENVELOPE) showing the rectified and smoothed signal with maximums A (~0.76) and B (~0.69).
* Third graph: all frames within each gait cycle set to the maximum value, and all other frames are set to zero.
* Fourth graph: the linear envelope signal is divided by the maximum of the corresponding gait cycle. Notice how the peaks of both cycles are now 1, and all values outside the defined event sequence are set to “data not found”.

Example Pipeline Script

Set_Pipeline_Parameter
/PARAMETER_NAME=R_EMG_SIGNAL_LIST
/PARAMETER_VALUE=EMG_A+EMG_B+EMG_C
! /PARAMETER_VALUE_SEARCH_FOR=
! /PARAMETER_VALUE_REPLACE_WITH=
! /PARAMETER_VALUE_PREFIX=
! /PARAMETER_VALUE_APPEND=
! /MULTI_PASS=FALSE
;

Set_Pipeline_Parameter
/PARAMETER_NAME=L_EMG_SIGNAL_LIST
/PARAMETER_VALUE=EMG_A+EMG_B+EMG_C
! /PARAMETER_VALUE_SEARCH_FOR=
! /PARAMETER_VALUE_REPLACE_WITH=
! /PARAMETER_VALUE_PREFIX=
! /PARAMETER_VALUE_APPEND=
! /MULTI_PASS=FALSE
;

Select_Active_File
/FILE_NAME=ALL_FILES
! /QUERY=
;

Event_Define_Event_Sequence
/EVENT_SEQUENCE_NAME=RCYCLE_SEQUENCE
/EVENT_SEQUENCE=RHS+RTO
! /EXCLUDE_EVENTS=
! /INSIDE_OF_SEQUENCE=
! /OFFSET_FROM_START=
! /OFFSET_FROM_END=
! /OFFSET_BY=PERCENT
/EVENT_SEQUENCE_INSTANCE=0
;

Event_Define_Event_Sequence
/EVENT_SEQUENCE_NAME=LCYCLE_SEQUENCE
/EVENT_SEQUENCE=LHS+LTO
! /EXCLUDE_EVENTS=
! /INSIDE_OF_SEQUENCE=
! /OFFSET_FROM_START=
! /OFFSET_FROM_END=
! /OFFSET_BY=PERCENT
/EVENT_SEQUENCE_INSTANCE=0
;

For_Each
/ITERATION_PARAMETER_NAME=SIDE
! /ITERATION_PARAMETER_COUNT_NAME=
/ITEMS=R+L
;

 Set_Pipeline_Parameter
 /PARAMETER_NAME=EMG_SIGNAL_LIST
 /PARAMETER_VALUE=:&:&::SIDE&_EMG_SIGNAL_LIST
 ! /PARAMETER_VALUE_SEARCH_FOR=
 ! /PARAMETER_VALUE_REPLACE_WITH=
 ! /PARAMETER_VALUE_PREFIX=
 ! /PARAMETER_VALUE_APPEND=
 /MULTI_PASS=TRUE
 ;

 ! ---------------------------------------------------------------------
 ! Get the maximum number of cycles in a trial the entire CMZ file
 ! ---------------------------------------------------------------------

 ! We're going to loop over every sequence in the trial,
 ! so first calculate the maximum number of sequences in the longest trial

 ! Count the number of cycles in each trial

 Metric_Event_Sequence_Count
 /RESULT_METRIC_FOLDER=EMG_NORM
 /RESULT_METRIC_NAME=&::SIDE&Cycle_Count
 ! /TIME_INTERVAL=
 /EVENT_SEQUENCE=&::SIDE&CYCLE_SEQUENCE
 /EXCLUDE_EVENTS=
 /GENERATE_COUNT_TOTAL_IN_GLOBAL=FALSE
 ;

 ! Calculate the maximum number of cycles across all trials
  
 Metric_Maximum
 /RESULT_METRIC_FOLDER=EMG_NORM
 /RESULT_METRIC_NAME=&::SIDE&Cycle_Count_Global
 ! /APPLY_AS_SUFFIX_TO_SIGNAL_NAME=FALSE
 /SIGNAL_TYPES=METRIC
 /SIGNAL_FOLDER=EMG_NORM
 /SIGNAL_NAMES=&::SIDE&Cycle_Count
 /COMPONENT_SEQUENCE=ALL
 /EVENT_SEQUENCE=
 /EXCLUDE_EVENTS=
 /SEQUENCE_PERCENT_START=
 /SEQUENCE_PERCENT_END=
 /GENERATE_MEAN_AND_STDDEV=FALSE
 ! /APPEND_TO_EXISTING_VALUES=FALSE
 /CREATE_GLOBAL_MAXIMUM=TRUE
 ;
  
 ! Create a list from 1 to the maximum event sequence in steps of 1

 Set_Pipeline_Parameter_From_For_Loop
 /PARAMETER_NAME=SEQUENCE_COUNT
 /PARAMETER_INDEX_START=1
 /PARAMETER_INDEX_END=GLOBAL::METRIC::EMG_NORM::&::SIDE&Cycle_Count_Global_Max
 /PARAMETER_INDEX_STEP=1
 /PARAMETER_INDEX_TYPE=INTEGER
 ;

 ! ---------------------------------------------------------------------
 ! Create Normalize Signal
 ! ---------------------------------------------------------------------

 ! Create a temporary signal which contains zeros at all frames

 Evaluate_Expression
 /EXPRESSION=CURRENT_SIGNAL * 0
 /SIGNAL_TYPES=ANALOG
 /SIGNAL_FOLDER=ENVELOPE
 /SIGNAL_NAMES=::EMG_SIGNAL_LIST
 /RESULT_TYPES=DERIVED
 /RESULT_FOLDERS=EMG_NORM_TEMP
 /RESULT_NAME=
 /APPLY_AS_SUFFIX_TO_SIGNAL_NAME=TRUE
 ;

 ! Loop over every sequence

 For_Each
 /ITERATION_PARAMETER_NAME=SEQUENCE_CURRENT
 ! /ITERATION_PARAMETER_COUNT_NAME=
 /ITEMS=::SEQUENCE_COUNT
 ;

  ! Define the "current" sequence as TEMP_CYCLE

  Event_Define_Event_Sequence
  /EVENT_SEQUENCE_NAME=TEMP_CYCLE
  /EVENT_SEQUENCE=&::SIDE&CYCLE_SEQUENCE
  ! /EXCLUDE_EVENTS=
  ! /INSIDE_OF_SEQUENCE=
  ! /OFFSET_FROM_START=
  ! /OFFSET_FROM_END=
  ! /OFFSET_BY=PERCENT
  /EVENT_SEQUENCE_INSTANCE=::SEQUENCE_CURRENT
  ;
   
  ! Loop over every EMG Signal
   
  For_Each
  /ITERATION_PARAMETER_NAME=EMG_SIGNAL_CURRENT
  ! /ITERATION_PARAMETER_COUNT_NAME=
  /ITEMS=::EMG_SIGNAL_LIST
  ;
    
   ! For all frames during the current cycle, 
   ! set the values to the maximum of the EMG signal
    
   Set_Data_To_New_Values
   /SIGNAL_TYPES=DERIVED
   /SIGNAL_FOLDER=EMG_NORM_TEMP
   /SIGNAL_NAMES=::EMG_SIGNAL_CURRENT
   ! /SIGNAL_COMPONENTS=ALL_COMPONENTS
   /RESULT_TYPES=DERIVED
   /RESULT_FOLDERS=EMG_NORM_TEMP
   /RESULT_SUFFIX=
   /EVENT_SEQUENCE=TEMP_CYCLE
   ! /EXCLUDE_EVENTS=
   ! /START_FRAME=
   ! /END_FRAME=
   ! /USE_POINT_RATE=TRUE
   /REPLACEMENT_VALUES=METRIC_MAXIMUM(ANALOG::ENVELOPE::&::EMG_SIGNAL_CURRENT&,EVENT_LABEL::SEQUENCE::TEMP_CYCLE)
   ! /THRESHOLD_HIGH=NO_DATA
   ! /THRESHOLD_LOW=NO_DATA
   ! /SET_DATA_AT_SINGLE_EVENT=FALSE
   ; 
    
  End_For_Each
  /ITERATION_PARAMETER_NAME=EMG_SIGNAL_CURRENT
  ;

 End_For_Each
 /ITERATION_PARAMETER_NAME=SEQUENCE_CURRENT
 ;

 ! ---------------------------------------------------------------------
 ! Normalize EMG Signal
 ! ---------------------------------------------------------------------

 ! Divide the EMG signals by the temporary signal above

 For_Each
 /ITERATION_PARAMETER_NAME=EMG_SIGNAL_CURRENT
 ! /ITERATION_PARAMETER_COUNT_NAME=
 /ITEMS=::EMG_SIGNAL_LIST
 ;

  Evaluate_Expression
  /EXPRESSION=ANALOG::ENVELOPE::&::EMG_SIGNAL_CURRENT& / DERIVED::EMG_NORM_TEMP::&::EMG_SIGNAL_CURRENT&
  ! /SIGNAL_TYPES=
  ! /SIGNAL_FOLDER=
  ! /SIGNAL_NAMES=
  /RESULT_TYPES=DERIVED
  /RESULT_FOLDERS=EMG_NORM
  /RESULT_NAME=&::EMG_SIGNAL_CURRENT&
  ! /APPLY_AS_SUFFIX_TO_SIGNAL_NAME=FALSE
  ;

 End_For_Each
 /ITERATION_PARAMETER_NAME=EMG_SIGNAL_CURRENT
 ;

End_For_Each
/ITERATION_PARAMETER_NAME=SIDE
;

Calling Example Meta-Command

Once the example Meta-Command from the download is placed in your Meta-Command folder, you can call the command using the following syntax:

EMG_Norm_Gait_Cycle
/EMG_INPUT_FOLDER=ENVELOPE
/EMG_OUTPUT_FOLDER=EMG_NORM
/R_EMG_SIGNAL_LIST=EMG_A+EMG_B+EMG_C
/R_EVENT_SEQUENCE=RHS+RTO
/L_EMG_SIGNAL_LIST=EMG_A_L+EMG_B_L+EMG_C_L
/L_EVENT_SEQUENCE=LHS+LTO
;
  • EMG_INPUT_FOLDER should be the EMG signals you want to normalized
  • EMG_OUTPUT_FOLDER should be the resulting EMG folder for the normalized signals
  • R_EMG_SIGNAL_LIST the list of right side EMG signals to normalize to the right gait cycle
  • R_EVENT_SEQUENCE events which indicate the right gait cycle (this example normalizes to stance, but you probably want to normalize to the entire gait cycle)
  • L_EMG_SIGNAL_LIST the list of left side EMG signals to normalize to the left gait cycle
  • R_EVENT_SEQUENCE events which indicate the left gait cycle (this example normalizes to stance, but you probably want to normalize to the entire gait cycle)
visual3d/documentation/emg/processing/normalize_emg_to_mvc.txt · Last modified: 2024/07/17 11:45 by sgranger