Skip to content

tools

Description

This module contains the functions that don't properly apply to the plot or analysis category but that are necessary for the usability of the library. The functions contained in this module can be considered as "tools" or shortcuts necessary to operate with the HD-EMG recordings.


showselect(emgfile, how='ref_signal', title='', titlesize=12, nclic=2)

Visually select a part of the recording.

The area can be selected based on the reference signal or based on the mean EMG signal. The selection can be performed with any letter or number in the keyboard, wrong points can be removed by pressing the right mouse button. Once finished, press enter to continue.

PARAMETER DESCRIPTION
emgfile

The dictionary containing the emgfile.

TYPE: dict

how

What to display in the figure used to visually select the area to resize.

ref_signal Visualise the reference signal to select the area to resize.

mean_emg Visualise the mean EMG signal to select the area to resize.

TYPE: str {"ref_signal", "mean_emg"} DEFAULT: "ref_signal"

title

The title of the plot. It is optional but strongly recommended. It should describe the task to do.

TYPE: str DEFAULT: ''

titlesize

The font size of the title.

TYPE: int DEFAULT: 12

nclic

The number of clics to be collected. If nclic < 1, all the clicks are collected.

DEFAULT: 2

RETURNS DESCRIPTION
points

A list containing the selected points sorted in ascending order.

TYPE: list

RAISES DESCRIPTION
ValueError

When the user clicked a wrong number of inputs in the GUI.

Examples:

Load the EMG file and select the points based on the reference signal.

>>> import openhdemg.library as emg
>>> emgfile = emg.askopenfile(filesource="OTB_REFSIG")
>>> points = emg.showselect(
...     emgfile,
...     how="ref_signal",
...     title="Select 2 points",
...     nclic=2,
... )
>>> points
[16115, 40473]

Load the EMG file and select the points based on the mean EMG signal.

>>> import openhdemg.library as emg
>>> emgfile = emg.askopenfile(filesource="OPENHDEMG")
>>> points = emg.showselect(
...     emgfile,
...     how="mean_emg",
...     title="Select 2 points",
...     nclic=2,
... )
>>> points
[135, 26598]


create_binary_firings(emg_length, number_of_mus, mupulses)

Create a binary representation of the MU firing.

Create a binary representation of the MU firing over time based on the times of firing of each MU.

PARAMETER DESCRIPTION
emg_length

Number of samples (length) in the emg file.

TYPE: int

number_of_mus

Number of MUs in the emg file.

TYPE: int

mupulses

Each ndarray should contain the times of firing (in samples) of each MU.

TYPE: list of ndarrays

RETURNS DESCRIPTION
binary_MUs_firing

A pd.DataFrame containing the binary representation of MUs firing.

TYPE: DataFrame


mupulses_from_binary(binarymusfiring)

Extract the MUPULSES from the binary MUs firings.

PARAMETER DESCRIPTION
binarymusfiring

A pd.DataFrame containing the binary representation of MUs firings.

TYPE: DataFrame

RETURNS DESCRIPTION
MUPULSES

A list of ndarrays containing the firing time (in samples) of each MU.

TYPE: list


resize_emgfile(emgfile, area=None, how='ref_signal', accuracy='recalculate', ignore_negative_ipts=False)

Resize all the components in the emgfile.

This function can be useful to compute the various parameters only in the area of interest.

PARAMETER DESCRIPTION
emgfile

The dictionary containing the emgfile to resize.

TYPE: dict

area

The resizing area. If already known, it can be passed in samples, as a list (e.g., [120,2560]). If None, the user can select the area of interest manually.

TYPE: None or list DEFAULT: None

how

If area==None, allow the user to visually select the area to resize based on how.

ref_signal Visualise the reference signal to select the area to resize.

mean_emg Visualise the mean EMG signal to select the area to resize.

TYPE: str {"ref_signal", "mean_emg"} DEFAULT: "ref_signal"

accuracy

recalculate The Silhouette score is computed in the new resized file. This can be done only if IPTS is present.

maintain The original accuracy measure already contained in the emgfile is returned without any computation.

TYPE: str {"recalculate", "maintain"} DEFAULT: "recalculate"

ignore_negative_ipts

This parameter determines the silhouette score estimation. If True, only positive ipts values are used during peak and noise clustering. This is particularly important for compensating sources with large negative components. This parameter is considered only if accuracy=="recalculate".

TYPE: bool DEFAULT: False

RETURNS DESCRIPTION
rs_emgfile

the new (resized) emgfile.

TYPE: dict

start_, end_ : int

the start and end of the selection (can be used for code automation).

Notes

Suggested names for the returned objects: rs_emgfile, start_, end_.

Examples:

Manually select the area to resize the emgfile based on mean EMG signal and recalculate the silhouette score in the new portion of the signal.

>>> emgfile = emg.askopenfile(filesource="DEMUSE", ignore_negative_ipts=True)
>>> rs_emgfile, start_, end_ = emg.resize_emgfile(
...     emgfile,
...     how="mean_emg",
...     accuracy="recalculate",
... )

Automatically resize the emgfile in the pre-specified area. Do not recalculate the silhouette score in the new portion of the signal.

>>> emgfile = emg.askopenfile(filesource="CUSTOMCSV")
>>> rs_emgfile, start_, end_ = emg.resize_emgfile(
...     emgfile,
...     area=[120, 25680],
...     accuracy="maintain",
... )


compute_idr(emgfile)

Compute the IDR.

This function computes the instantaneous discharge rate (IDR) from the MUPULSES. The IDR is very useful for plotting and visualisation of the MUs behaviour.

PARAMETER DESCRIPTION
emgfile

The dictionary containing the emgfile.

TYPE: dict

RETURNS DESCRIPTION
idr

A dict containing a pd.DataFrame for each MU (keys are integers). Accessing the key, we have a pd.DataFrame containing:

  • mupulses: firing sample.
  • diff_mupulses: delta between consecutive firing samples.
  • timesec: delta between consecutive firing samples in seconds.
  • idr: instantaneous discharge rate.

TYPE: dict

Examples:

Load the EMG file, compute IDR and access the results for the first MU.

>>> import openhdemg.library as emg
>>> emgfile = emg.askopenfile(filesource="OTB", otb_ext_factor=8)
>>> idr = emg.compute_idr(emgfile=emgfile)
>>> munumber = 0
>>> idr[munumber]
    mupulses  diff_mupulses    timesec       idr
0        9221            NaN   4.502441       NaN
1        9580          359.0   4.677734  5.704735
2        9973          393.0   4.869629  5.211196
3       10304          331.0   5.031250  6.187311
4       10617          313.0   5.184082  6.543131
..        ...            ...        ...       ...
149     54521          395.0  26.621582  5.184810
150     54838          317.0  26.776367  6.460568
151     55417          579.0  27.059082  3.537133
152     55830          413.0  27.260742  4.958838
153     56203          373.0  27.442871  5.490617


delete_mus(emgfile, munumber, if_single_mu='ignore', delete_delsys_muaps=True)

Delete unwanted MUs.

PARAMETER DESCRIPTION
emgfile

The dictionary containing the emgfile.

TYPE: dict

munumber

The MUs to remove. If a single MU has to be removed, this should be an int (number of the MU). If multiple MUs have to be removed, a list of int should be passed. An unpacked (*) range can also be passed as munumber=[*range(0, 5)]. munumber is expected to be with base 0 (i.e., the first MU in the file is the number 0).

TYPE: int, list of int

if_single_mu

A string indicating how to behave in case of a file with a single MU.

ignore Ignore the process and return the original emgfile. (Default)

remove Remove the MU and return the emgfile without the MU. This should allow full compatibility with the use of this file in following processing (i.e., save/load and analyse).

TYPE: str {"ignore", "remove"} DEFAULT: "ignore"

delete_delsys_muaps

If true, deletes also the associated MUAPs computed by the Delsys software stored in emgfile["EXTRAS"].

TYPE: Bool DEFAULT: True

RETURNS DESCRIPTION
emgfile

The dictionary containing the emgfile without the unwanted MUs.

TYPE: dict

Examples:

Delete MUs 1,4,5 from the emgfile.

>>> import openhdemg.library as emg
>>> emgfile = emg.askopenfile(filesource="OTB", otb_ext_factor=8)
>>> emgfile = emg.delete_mus(emgfile=emgfile, munumber=[1,4,5])


delete_empty_mus(emgfile)

Delete all the MUs without firings.

PARAMETER DESCRIPTION
emgfile

The dictionary containing the emgfile.

TYPE: dict

RETURNS DESCRIPTION
emgfile

The dictionary containing the emgfile without the empty MUs.

TYPE: dict


sort_mus(emgfile)

Sort the MUs in order of recruitment.

PARAMETER DESCRIPTION
emgfile

The dictionary containing the emgfile.

TYPE: dict

RETURNS DESCRIPTION
sorted_emgfile

The dictionary containing the sorted emgfile.

TYPE: dict


compute_covsteady(emgfile, start_steady=-1, end_steady=-1)

Calculates the covsteady.

This function calculates the coefficient of variation of the steady-state phase (covsteady of the REF_SIGNAL).

PARAMETER DESCRIPTION
emgfile

The dictionary containing the emgfile.

TYPE: dict

start_steady

The start and end point (in samples) of the steady-state phase. If < 0 (default), the user will need to manually select the start and end of the steady-state phase.

TYPE: int DEFAULT: -1

end_steady

The start and end point (in samples) of the steady-state phase. If < 0 (default), the user will need to manually select the start and end of the steady-state phase.

TYPE: int DEFAULT: -1

RETURNS DESCRIPTION
covsteady

The coefficient of variation of the steady-state phase in %.

TYPE: float

See also
  • compute_idr : computes the instantaneous discharge rate.

Examples:

Load the EMG file, compute covsteady and access the result from GUI.

>>> import openhdemg.library as emg
>>> emgfile = emg.askopenfile(filesource="OTB", otb_ext_factor=8)
>>> covsteady = emg.compute_covsteady(emgfile=emgfile)
>>> covsteady
1.452806

The process can be automated by bypassing the GUI.

>>> import openhdemg.library as emg
>>> emgfile = emg.askopenfile(filesource="OTB", otb_ext_factor=8)
>>> covsteady = emg.compute_covsteady(
...     emgfile=emgfile,
...     start_steady=3580,
...     end_steady=15820,
... )
>>> covsteady
35.611263


filter_rawemg(emgfile, order=2, lowcut=20, highcut=500)

Band-pass filter the RAW_SIGNAL.

The filter is a Zero-lag band-pass Butterworth.

PARAMETER DESCRIPTION
emgfile

The dictionary containing the emgfile.

TYPE: dict

order

The filter order.

TYPE: int DEFAULT: 2

lowcut

The lower cut-off frequency in Hz.

TYPE: int DEFAULT: 20

highcut

The higher cut-off frequency in Hz.

TYPE: int DEFAULT: 500

RETURNS DESCRIPTION
filteredrawsig

The dictionary containing the emgfile with a filtered RAW_SIGNAL. Currently, the returned filteredrawsig cannot be accurately compressed when using the functions save_json_emgfile() and asksavefile(). We therefore suggest you to save the unfiltered emgfile if you want to obtain maximum compression.

TYPE: dict

See also
  • filter_refsig : low-pass filter the REF_SIGNAL.


filter_refsig(emgfile, order=4, cutoff=15)

Low-pass filter the REF_SIGNAL.

This function is used to low-pass filter the REF_SIGNAL and remove noise. The filter is a Zero-lag low-pass Butterworth.

PARAMETER DESCRIPTION
emgfile

The dictionary containing the emgfile.

TYPE: dict

order

The filter order.

TYPE: int DEFAULT: 4

cutoff

The cut-off frequency in Hz.

TYPE: int DEFAULT: 15

RETURNS DESCRIPTION
filteredrefsig

The dictionary containing the emgfile with a filtered REF_SIGNAL.

TYPE: dict

See also
  • remove_offset : remove the offset from the REF_SIGNAL.
  • filter_rawemg : band-pass filter the RAW_SIGNAL.


remove_offset(emgfile, offsetval=0, auto=0)

Remove the offset from the REF_SIGNAL.

PARAMETER DESCRIPTION
emgfile

The dictionary containing the emgfile.

TYPE: dict

offsetval

Value of the offset. If offsetval is 0 (default), the user will be asked to manually select an aerea to compute the offset value. Otherwise, the value passed to offsetval will be used. Negative offsetval can be passed.

TYPE: float DEFAULT: 0

auto

If auto > 0, the script automatically removes the offset based on the number of samples passed in input.

TYPE: int DEFAULT: 0

RETURNS DESCRIPTION
offs_emgfile

The dictionary containing the emgfile with a corrected offset of the REF_SIGNAL.

TYPE: dict

See also
  • filter_refsig : low-pass filter REF_SIGNAL.


get_mvc(emgfile, how='showselect', conversion_val=0)

Measure the maximum voluntary contraction (MVC).

PARAMETER DESCRIPTION
emgfile

The dictionary containing the emgfile with the reference signal.

TYPE: dict

how

showselect Ask the user to select the area where to calculate the MVC with a GUI.

all Calculate the MVC on the entire file.

TYPE: str {"showselect", "all"} DEFAULT: "showselect"

conversion_val

The conversion value to multiply the original reference signal. I.e., if the original reference signal is in kilogram (kg) and conversion_val=9.81, the output will be in Newton (N). If conversion_val=0 (default), the results will simply be in the original measure unit. conversion_val can be any custom int or float.

TYPE: float or int DEFAULT: 0

RETURNS DESCRIPTION
mvc

The MVC value in the original (or converted) unit of measurement.

TYPE: float

See also
  • compute_rfd : calculate the RFD.
  • remove_offset : remove the offset from the REF_SIGNAL.
  • filter_refsig : low-pass filter REF_SIGNAL.

Examples:

Load the EMG file, remove reference signal offset and get MVC value.

>>> import openhdemg.library as emg
>>> emg_refsig = emg.askopenfile(filesource="OTB_REFSIG")
>>> offs_refsig = emg.remove_offset(emgfile=emg_refsig)
>>> mvc = emg.get_mvc(emgfile=offs_refsig )
>>> mvc
50.72

The process can be automated by bypassing the GUI and calculating the MVC of the entire file.

>>> import openhdemg.library as emg
>>> emg_refsig = emg.askopenfile(filesource="OTB_REFSIG")
>>> mvc = emg.get_mvc(emgfile=emg_refsig, how="all")
>>> print(mvc)
50.86


compute_rfd(emgfile, ms=[50, 100, 150, 200], startpoint=None, conversion_val=0)

Calculate the RFD.

Rate of force development (RFD) is reported as X/Sec where "X" is the unit of measurement based on conversion_val.

PARAMETER DESCRIPTION
emgfile

The dictionary containing the emgfile with the reference signal.

TYPE: dict

ms

Milliseconds (ms). A list containing the ranges in ms to calculate the RFD.

TYPE: list DEFAULT: [50, 100, 150, 200]

startpoint

The starting point to calculate the RFD in samples, If None, the user will be requested to manually select the starting point.

TYPE: None or int DEFAULT: None

conversion_val

The conversion value to multiply the original reference signal. I.e., if the original reference signal is in kilogram (kg) and conversion_val=9.81, the output will be in Newton/Sec (N/Sec). If conversion_val=0 (default), the results will simply be Original measure unit/Sec. conversion_val can be any custom int or float.

TYPE: float or int DEFAULT: 0

RETURNS DESCRIPTION
rfd

A pd.DataFrame containing the RFD at the different times.

TYPE: DataFrame

See also
  • get_mvif : measure the MViF.
  • remove_offset : remove the offset from the REF_SIGNAL.
  • filter_refsig : low-pass filter REF_SIGNAL.

Examples:

Load the EMG file, low-pass filter the reference signal and compute RFD.

>>> import openhdemg.library as emg
>>> emg_refsig = emg.askopenfile(filesource="OTB_REFSIG")
>>> filteredrefsig  = emg.filter_refsig(
...     emgfile=emg_refsig,
...     order=4,
...     cutoff=15,
... )
>>> rfd = emg.compute_rfd(
...     emgfile=filteredrefsig,
...     ms=[50, 100, 200],
...     conversion_val=9.81,
...     )
>>> rfd
        50         100        200
0  68.34342  79.296188  41.308215

The process can be automated by bypassing the GUI.

>>> import openhdemg.library as emg
>>> emg_refsig = emg.askopenfile(filesource="OTB_REFSIG")
>>> filteredrefsig  = emg.filter_refsig(
...     emgfile=emg_refsig,
...     order=4,
...     cutoff=15,
...     )
>>> rfd = emg.compute_rfd(
...     emgfile=filteredrefsig,
...     ms=[50, 100, 200],
...     startpoint=3568,
...     )
>>> rfd
        50         100        200
0  68.34342  79.296188  41.308215


compute_svr(emgfile, gammain=1 / 1.6, regparam=1 / 0.37, endpointweights_numpulses=5, endpointweights_magnitude=5, discontfiring_dur=1.0)

Fit MU discharge rates with Support Vector Regression, nonlinear regression.

Provides smooth and continous estimates of discharge rate useful for quantification and visualisation. Suggested hyperparameters and framework from Beauchamp et. al., 2022 https://doi.org/10.1088/1741-2552/ac4594

Author: James (Drew) Beauchamp

PARAMETER DESCRIPTION
emgfile

The dictionary containing the emgfile.

TYPE: dict

gammain

The kernel coefficient.

TYPE: float DEFAULT: 1/1.6

regparam

The regularization parameter, must be positive.

TYPE: float DEFAULT: 1/0.370

endpointweights_numpulses

Number of discharge instances at the start and end of MU firing to apply a weighting coefficient.

TYPE: int DEFAULT: 5

endpointweights_magnitude

The scaling factor applied to the number of pulses provided by endpointweights_numpulses. The scaling is applied to the regularization parameter, per sample. Larger values force the classifier to put more emphasis on the number of discharge instances at the start and end of firing provided by endpointweights_numpulses.

TYPE: int DEFAULT: 5

discontfiring_dur

Duration of time in seconds that defines an instnance of discontinuous firing. SVR fits will not be returned at points of discontinuity.

TYPE: int DEFAULT: 1

RETURNS DESCRIPTION
svrfits

A pd.DataFrame containing the smooth/continous MU discharge rates and corresponding time vectors.

TYPE: DataFrame

See also
  • compute_deltaf : quantify delta F via paired motor unit analysis.

Examples:

Quantify svr fits.

>>> import openhdemg.library as emg
>>> import pandas as pd
>>> emgfile = emg.emg_from_samplefile()
>>> emgfile = emg.sort_mus(emgfile=emgfile)
>>> svrfits = emg.compute_svr(emgfile)

Quick plot showing the results.

>>> smoothfits = pd.DataFrame(svrfits["gensvr"]).transpose()
>>> emg.plot_smoothed_dr(
>>>     emgfile,
>>>     smoothfits=smoothfits,
>>>     munumber="all",
>>>     addidr=False,
>>>     stack=True,
>>>     addrefsig=True,
>>> )