Metadata-Version: 2.4
Name: emg-tools
Version: 2.0.0
Summary: Preprocess, analyse and plot EMG signals
Author: Irene Mendez Guerra
License-Expression: MIT
Project-URL: Homepage, https://imendezguerra.github.io/emg-tools/
Project-URL: Documentation, https://imendezguerra.github.io/emg-tools/
Project-URL: Source, https://github.com/imendezguerra/emg-tools
Project-URL: Issues, https://github.com/imendezguerra/emg-tools/issues
Project-URL: Changelog, https://github.com/imendezguerra/emg-tools/releases
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.22
Requires-Dist: scipy>=1.8
Requires-Dist: matplotlib>=3.5
Requires-Dist: seaborn>=0.11
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: pytest-cov>=4; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Requires-Dist: pre-commit>=3; extra == "dev"
Requires-Dist: build>=1; extra == "dev"
Requires-Dist: twine>=5; extra == "dev"
Provides-Extra: docs
Requires-Dist: mkdocs<2,>=1.6; extra == "docs"
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
Requires-Dist: mkdocstrings[python]>=0.26; extra == "docs"
Requires-Dist: markdown-exec>=1.9; extra == "docs"
Dynamic: license-file

# EMG Toolbox

[![PyPI](https://img.shields.io/pypi/v/emg-tools)](https://pypi.org/project/emg-tools/)
[![Python versions](https://img.shields.io/pypi/pyversions/emg-tools)](https://pypi.org/project/emg-tools/)
[![CI](https://github.com/imendezguerra/emg-tools/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/imendezguerra/emg-tools/actions/workflows/ci.yml)
[![Docs](https://github.com/imendezguerra/emg-tools/actions/workflows/docs.yml/badge.svg)](https://imendezguerra.github.io/emg-tools/)

## Overview
<!-- --8<-- [start:overview] -->
EMG Toolbox is a Python package to preprocess, analyse and plot electromyography (EMG) signals, including high-density recordings from electrode grids.

The package is composed of the following modules:

- `tools`: rearrange channels between `(samples, channels)` and grid `(rows, cols, samples)` formats, and replace bad channels with the mean of their neighbours.
- `prepro`: Butterworth bandpass, highpass, lowpass and powerline (bandstop) filters.
- `feats`: amplitude features such as the moving-window root mean square (RMS).
- `freq`: amplitude spectrum and power spectral density (periodogram or Welch).
- `plots`: plot channels over time, PSDs, PSD maps across channels, and spectrograms.
<!-- --8<-- [end:overview] -->

## Table of Contents
- [Installation](#installation)
- [Quick start](#quick-start)
- [Documentation](#documentation)
- [Contributing](#contributing)
- [License](#license)
- [Citation](#citation)
- [Contact](#contact)

## Installation
<!-- --8<-- [start:install] -->
Install the latest release from PyPI (Python 3.10 or newer):

```sh
pip install emg-tools
```

The package is imported as `emg_tools`.
<!-- --8<-- [end:install] -->

To work on the code itself, see the development setup in [CONTRIBUTING.md](https://github.com/imendezguerra/emg-tools/blob/main/CONTRIBUTING.md#development-setup).

## Quick start
<!-- --8<-- [start:quickstart] -->
EMG data is an array of shape `(samples, channels)`. The example below filters a synthetic 16-channel recording and computes its RMS envelope:

```python
import numpy as np

from emg_tools import feats, prepro

fs = 2048                                   # sampling frequency (Hz)
timestamps = np.arange(5 * fs) / fs         # 5 s recording
rng = np.random.default_rng(0)
emg = rng.standard_normal((timestamps.size, 16))                # (samples, channels)
emg += 0.5 * np.sin(2 * np.pi * 50 * timestamps)[:, None]       # powerline noise

emg_filt = prepro.remove_powerline(emg, fs=fs, cutoff=50)
emg_filt = prepro.bandpass_filter(emg_filt, fs=fs, cutoff=[20, 500])

rms, t_win = feats.compute_rms(emg_filt, timestamps, win_len_s=0.25, win_step_s=0.125, fs=fs)
rms.shape                                   # (10240, 16): one RMS value per sample and channel
```
<!-- --8<-- [end:quickstart] -->

## Documentation
The full documentation, with a worked example and the API reference, is at
[imendezguerra.github.io/emg-tools](https://imendezguerra.github.io/emg-tools/).

## Contributing
Contributions are welcome! [CONTRIBUTING.md](https://github.com/imendezguerra/emg-tools/blob/main/CONTRIBUTING.md) explains how to set up a development environment, run the tests, preview the docs, and what the automated checks (pre-commit and CI) do.

## License
This project is licensed under the [MIT License](https://github.com/imendezguerra/emg-tools/blob/main/LICENSE).

## Citation

If you use this code in your research, please cite this repository:

```sh
@software{Mendez_Guerra_EMG_Toolbox,
author = {Mendez Guerra, Irene},
title = {{EMG Toolbox}},
url = {https://github.com/imendezguerra/emg-tools},
version = {2.0.0}
}
```
## Contact

For any questions or inquiries, please contact us at:
```sh
Irene Mendez Guerra
irene.mendez17@imperial.ac.uk
```
