Code files related to HD-sEMG signal processing. Equipment used : OT Bioelectronica (2 units) + Muscle Dynamometer (for torque)
This documentation explains what happens in each of the codes and how to use them to process your files :
- Data Collection, Naming :
First, after collecting the emg data from OT Bioelectronica, convert the data from otb+ format to csv file using the OT Bioelectronica's software (runs only on Windows). Then rename the file as per the naming structure given below,
Naming structure - Every file has “PXX””L/R””type”
PXX - the participants number L/R - “Left” or “Right” type - “60”, ”90”, ”120” for Isokinetic exercises, “Flexion”, “Extension” for MVCs, “Push”, “Pull” for functional tasks
Examples of files following the naming structure : P07_Left_Flexion.csv, P10_Right_Pull.csv, P15_Left_90.csv, etc. Note that the code is case sensitive, hence P07_left_flexion.csv won't work since left is not detected as "Left" and flexion isn't detected as "Flexion"
Do the same for all the collected HD-sEMG data, convert the otb+ files to csv files, rename them as per the naming structure and then put all the renamed csv data in a folder called "Raw_EMG_Data". The naming is a critical step since this is how the code recognises which files are related to which exercise type.
- After you have all the data in "Raw_EMG_Data", then run it through the code "1_MicroVolts_Conversion.ipynb"
Sometimes OT Bioelectronica's Sessantoquattro system gives out emg data in milli Volts and sometimes it gives out emg data in Volts, it is a software bug from OT Bioelectronica's side. To fix this, this code runs through all the csv files inside the "Raw_EMG_Data" folder, converts all the units to microvolts and saves all the modified csv files to the "Processed_Raw_EMG_Data". This is required so that all the mean and max values of RMS/MDF/ARV values in the end are comparable.
Code Logic : Look at the columns of every csv file, if the column average is less than 3, then multiply it by 1000 to convert Volts reading to Milli-Volts reading, then convert all Milli-volts to Micro-volts
- Now, run the code "2_Dead_Ch_Rectification.ipynb" and make sure that you have generated "Processed_Raw_EMG_Data" folder from the previous code before running this code This code first detects the dead channels; even if a channel has been dead for one second, the channel is considered as a dead channel, then the code runs an averaging algorithm on all the dead channels, replaces the dead channels values with an average of the emg values of the surrounding channels After making all the changes, the emg data is saved to the folder "Rectified_EMG_Data"
To check the working of this code, look at the heatmap generated by the file using Ashirbad's code before processing (the file in Processed_Raw_EMG_Data) and the file with the same file name in "Rectified_EMG_Data" after processing (running the code)
Code Logic : In a csv file, in every column, look for a sequence of zeros, if you find a sequence of zeros greater than 2000 (which is the number of samples per second) Then mark that column as a dead channel. Do this for every column, and find out all the dead channels. Make a score board, a score board is a representation of how many channels around the dead channel are usable (not dead). From the score board, we determine which of the deda channels has the highest number of channels around it and then rectify that dead channel first. Next we remove it from the dead channel list, calculate the score board again and see which dead channel scores the highest (has the most usable active emg channels) now, and rectify it. We do this iteratively till all the dead channels are fixed (averaged).
- Run "3_EMG_Processing_RMS_MDF_ARV.ipynb" file after the running the dead channel rectification code, this step is likely to take a LOT of time since it generates RMS and ARV versions of the emg data. This code creates three folders, "EMG_RMS_Data" and "EMG_ARV_Data". These folders contain rms and arv versions of the raw emg data (which has been processed to remove dead channels at this stage)
Code Logic : There isn't any big logic to it, it simply takes in each of the csv files, calculates rms and arv version of the file for the set window size Saves it in three different folders called "EMG_RMS_Data" and "EMG_ARV_Data"
- Now run the "4_Extract_Normalization_Values.ipynb" file, this file looks at all the files in the "EMG_RMS_Data" folder (generated in the previous step) which have "Flexion" / "Extension" in it's name, identifies the plateau in the torque line (which is the last column in any csv), picks a midpoint or a point on a plateau, then extracts G1, G2 normalization values. G1 is the normalization value for grid 1 (the one placed on bicep) and G2 is the normalization value for grid 2 (the one placed on tricep). All the normalization values are found and stored in a file called "MVC_Data.csv"
Code Logic : It reads the data on the last column, which is the torque data, run's an algorithm on it to detect a plateau, then picks the midpoint of that plateau, From the midpoint of the plateau, you get the MVC index which will be used to get G1, G2 values and store it in MVC_Data.csv file.
- Now, you can generate a file by running "5_NF_Index_File_Generation.ipynb" which has all the non-functional task (60, 90, 120) filenames in a column and also have two other columns which are meant to contain Flexion and Extension indices. After you generate this file, you will need to manually fill up the indexes in this csv file. You can use excel, open up the csv file, plot the last column click on the points related to Flexion or Extension and note it down in the generated csv file. The indexes are used by the next program to generate features.
Code Logic : It looks at all the files in "EMG_RMS_Data" folder, picks out the names of the files which have 60, 90 and 120 in them, and puts them in a column, it also creates two other empty columns named "Flexion" and "Extension", where indexes related to the flexion and extension peaks need to be put.
- Run "6_EMG_Feature_Extraction_F.ipynb" to calculate features for functional (Push, Pull) tasks. It automatically picks up the indexes based on the highest peak it detects in an emg rms file for channel 14 (chose this channel since it is near the middle of the electrode grid). It then calculates 'Entropy', 'CoV', 'Intensity', 'Differential Intensity', 'Mean_RMS', 'Max_RMS', 'Mean_MDF', 'Max_MDF','Mean_ARV', 'Max_ARV','Xcg', 'Ycg' and puts it in "Data_Functional.csv" file.
- Run "6_EMG_Feature_Extraction_NF.ipynb" to calculate features for non-functional (60,90,120) tasks. It picks up the indexes based on the indexes we manually put in "Non_Functional_Indexes.csv". It then calculates 'Entropy', 'CoV', 'Intensity', 'Differential Intensity', 'Mean_RMS', 'Max_RMS', 'Mean_MDF', 'Max_MDF','Mean_ARV', 'Max_ARV','Xcg', 'Ycg' for each of the grids and puts it in "Data_Non_Functional.csv" file.