# Vital_sqi: Signal quality control of physiological signals
<!-- [![Build Status](https://travis-ci.com/meta00/vital_sqi.svg?token=CDjcmJqzLe7opuWagsPJ&branch=main)](https://travis-ci.com/meta00/vital_sqi)
[![codecov](https://codecov.io/gh/meta00/vital_sqi/branch/main/graph/badge.svg?token=6RV5BUK340)](https://codecov.io/gh/meta00/vital_sqi)
[![Documentation Status](https://readthedocs.org/projects/vitalsqi/badge/?version=latest)](https://vitalsqi.readthedocs.io/en/latest/?badge=latest)
[![PyPI version](https://badge.fury.io/py/vital-sqi.svg)](https://badge.fury.io/py/vital-sqi)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -->
![GitHub stars](https://img.shields.io/github/stars/Oucru-Innovations/vital-sqi?style=social)
![PyPI - Downloads](https://img.shields.io/pypi/dm/vitalSQI-toolkit)
![PyPI](https://img.shields.io/pypi/v/vitalSQI-toolkit)
![Build Status](https://github.com/Oucru-Innovations/vital-sqi/actions/workflows/ci.yml/badge.svg)
[![Coverage Status](https://coveralls.io/repos/github/Oucru-Innovations/vital-sqi/badge.svg?branch=main)](https://coveralls.io/github/Oucru-Innovations/vital-sqi?branch=main)
![GitHub License](https://img.shields.io/github/license/Oucru-Innovations/vital-sqi)
![Python Versions](https://img.shields.io/badge/python-3.7%2B-blue)
[![Documentation Status](https://readthedocs.org/projects/vital-sqi/badge/?version=latest)](https://vital-sqi.readthedocs.io/en/latest/?badge=latest)
<!-- ![PyPI Downloads](https://img.shields.io/pypi/dm/vitalsqi)
[![PyPI version](https://badge.fury.io/py/vitalsqi.svg)](https://badge.fury.io/py/vitalsqi)
[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Oucru-Innovations/vital-sqi/blob/main/docs/source/notebooks/synthesize_data.ipynb) -->
---
# Overview
**Vital_sqi** is an open-source Python package for **signal quality index (SQI)** extraction and **quality classification** of ECG and PPG signals. The package enables streamlined signal quality control, essential for reliable health monitoring and clinical research.
## Key Features:
1. Support for **PPG and ECG signals** in various formats, including wearable device data.
2. Implementation of **state-of-the-art SQI extraction methods** (e.g., statistical, HRV, waveform-based).
3. Rule-based **quality classification** using user-defined thresholds.
4. **Pipelines** for end-to-end processing, from data ingestion to SQI classification.
5. A **GUI tool** for defining rules and visualizing results interactively.
---
# Prerequisites and Installation
The package supports Python `3.7` and `3.8`. Install Vital_sqi using pip:
```bash
pip install vitalSQI-toolkit
```
### Optional Dependencies:
- **Dash** for GUI applications.
- **Plotly** for visualization.
- **Matplotlib** for advanced plotting options.
For detailed dependencies, refer to the [documentation](https://vital-sqi.readthedocs.io/en/latest/).
---
# Getting Started
The core of the package is built around three main classes:
### **1. SignalSQI Class**
This class handles the main signal data and SQI extraction workflow.
Attributes:
- `signal`: Waveform data (as a pandas DataFrame).
- `sampling_rate`: Sampling rate of the signal (user-defined or auto-inferred).
- `sqis`: SQI values calculated for signal segments.
- `rules` and `ruleset`: Lists of applied rules and the ruleset used for classification.
### **2. Rule Class**
Defines individual SQI-based rules for classification.
Example rule structure in JSON:
```json
{
"test_sqi": {
"name": "test_sqi",
"def": [
{"op": ">", "value": "10", "label": "reject"},
{"op": ">=", "value": "3", "label": "accept"},
{"op": "<", "value": "3", "label": "reject"}
],
"desc": "",
"ref": ""
}
}
```
### **3. Ruleset Class**
Groups rules and defines the sequence for applying them to signal segments. The ruleset is defined in JSON format and can be customized to fit specific needs.`ruleset` object of class `Ruleset` contains a set of selected `rules` (selected from the list of rules in `signal_obj.rule`) and the order to apply them in quality
assignment (see schema below). Notice that this is not a tree-based classification.
![Example of a rule set](images/resize_sample_rule_chart.png "Example of a rule set")
# Pipelines
The package includes predefined pipelines for processing ECG and PPG signals.
### Example: Extracting SQIs from ECG
```python
from vital_sqi.pipeline.pipeline_highlevel import *
from vital_sqi.data.signal_sqi_class import SignalSQI
import os
file_in = os.path.abspath('tests/test_data/example.edf')
sqi_dict = os.path.abspath('tests/test_data/sqi_dict.json')
segments, signal_sqi_obj = get_ecg_sqis(file_in, sqi_dict, 'edf')
```
### Example: Quality Classification for ECG
```python
from vital_sqi.pipeline.pipeline_highlevel import *
import os
import tempfile
file_in = os.path.abspath('tests/test_data/example.edf')
sqi_dict = os.path.abspath('tests/test_data/sqi_dict.json')
rule_dict_filename = os.path.abspath('tests/test_data/rule_dict_test.json')
ruleset_order = {3: 'skewness_1', 2: 'entropy', 1: 'perfusion'}
output_dir = tempfile.gettempdir()
signal_obj = get_qualified_ecg(
file_name=file_in,
sqi_dict_filename=sqi_dict,
file_type='edf',
duration=30,
rule_dict_filename=rule_dict_filename,
ruleset_order=ruleset_order,
output_dir=output_dir
)
```
---
# GUI for Rules and Execution
Vital_sqi provides a GUI for creating rules, defining rulesets, and executing them interactively. The GUI helps users:
- Configure rules visually.
- Test and validate signal quality thresholds.
- Export results for further analysis.
[Click here for the GUI guide](https://vital-sqi.readthedocs.io/en/latest/docstring/vital_sqi.app.html#module-vital_sqi.app.app).
# Workflow Overview
### **1. Reading and Writing Signals**
Supported formats:
- ECG: `EDF`, `MIT`, `CSV`.
- PPG: `CSV`.
### **2. Preprocessing and Segmentation**
Available preprocessing steps:
- Trimming, tapering, and smoothing.
- Bandpass filtering.
- Segmentation by duration or by beat.
### **3. SQI Extraction**
Four types of SQIs:
1. **Statistical SQIs**: Kurtosis, skewness, entropy, etc.
2. **HRV-based SQIs**: SDNN, SDSD, RMSSD, etc.
3. **RR Interval-based SQIs**: Ectopic, correlogram, etc.
4. **Waveform-based SQIs**: DTW, QRS energy, etc.
The function `vital_sqi.pipeline_function.extract_sqi` is used to extract a number of SQIs from segments. The requested SQIs
are defined in a json file called SQI dictionary. We provide a dictionary template for all implemented SQIs, with default
parameters, in `vital_sqi/resource/sqi_dict.json`.
### **4. Signal Quality Classification**
- Rule-based classification using user-defined thresholds.
- Optimized rule application for performance.
Templates for rules and rulesets are available in the `vital_sqi/resource` directory.
The package allows making rule set from SQIs and user-defined thresholds for quality classification. A segment assigned
as `accept` pass all rules in the set, otherwise `reject`. Rules in the set have ordered, which might help to
improve speed.
We ran brute force threshold searching for an in-house PPG dataset (generated with Smartcare, doubly annotated
by domain experts) to obtain a set of recommended thresholds, as found in `resource/rule_dict.json`.
---
# Documentation
Find detailed tutorials, examples, and API references at:
🔗 [Vital_sqi Documentation](https://vital-sqi.readthedocs.io/en/latest/)
---
# Contributions
We welcome contributions from the community! Please refer to our [CONTRIBUTING.md](https://github.com/Oucru-Innovations/vital-sqi/blob/main/CONTRIBUTING.md) for guidelines.
---
# References
- [Optimal Signal Quality Index for Photoplethysmogram Signals](https://doi.org/10.xxxx)
- [Other relevant papers and research articles]
---
# License
Vital_sqi is licensed under the MIT License. See the [LICENSE](https://github.com/Oucru-Innovations/vital-sqi/blob/main/LICENSE) file for details.
---
Thank you for supporting Vital_sqi! For questions or issues, feel free to [open an issue](https://github.com/Oucru-Innovations/vital-sqi/issues) on GitHub.
Raw data
{
"_id": null,
"home_page": "https://github.com/Oucru-Innovations/vital-sqi",
"name": "vitalsqi-toolkit",
"maintainer": "Hai Ho, Khoa Le",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "haihb@oucru.org, khoaldv@oucru.org",
"keywords": "signal quality, ECG, PPG, toolkit",
"author": "Khoa Le, Hai Ho, Stefan Karolcik, Heloise Greeff",
"author_email": "Khoa Le <khoaldv@oucru.org>, Hai Ho <haihb@oucru.org>, Stefan Karolcik <s.karolcik@imperial.ac.uk>, Heloise Greeff <heloise.greeff@eng.ox.ac.uk>",
"download_url": "https://files.pythonhosted.org/packages/28/89/3ae973c1d3f9dd3797ca8c4357ab8fc519bccd6583e4d29a39c52b06b668/vitalsqi_toolkit-1.0.2.tar.gz",
"platform": null,
"description": "# Vital_sqi: Signal quality control of physiological signals\r\n\r\n<!-- [![Build Status](https://travis-ci.com/meta00/vital_sqi.svg?token=CDjcmJqzLe7opuWagsPJ&branch=main)](https://travis-ci.com/meta00/vital_sqi)\r\n[![codecov](https://codecov.io/gh/meta00/vital_sqi/branch/main/graph/badge.svg?token=6RV5BUK340)](https://codecov.io/gh/meta00/vital_sqi)\r\n[![Documentation Status](https://readthedocs.org/projects/vitalsqi/badge/?version=latest)](https://vitalsqi.readthedocs.io/en/latest/?badge=latest)\r\n[![PyPI version](https://badge.fury.io/py/vital-sqi.svg)](https://badge.fury.io/py/vital-sqi)\r\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -->\r\n\r\n![GitHub stars](https://img.shields.io/github/stars/Oucru-Innovations/vital-sqi?style=social)\r\n![PyPI - Downloads](https://img.shields.io/pypi/dm/vitalSQI-toolkit)\r\n![PyPI](https://img.shields.io/pypi/v/vitalSQI-toolkit)\r\n![Build Status](https://github.com/Oucru-Innovations/vital-sqi/actions/workflows/ci.yml/badge.svg)\r\n[![Coverage Status](https://coveralls.io/repos/github/Oucru-Innovations/vital-sqi/badge.svg?branch=main)](https://coveralls.io/github/Oucru-Innovations/vital-sqi?branch=main)\r\n![GitHub License](https://img.shields.io/github/license/Oucru-Innovations/vital-sqi)\r\n![Python Versions](https://img.shields.io/badge/python-3.7%2B-blue)\r\n[![Documentation Status](https://readthedocs.org/projects/vital-sqi/badge/?version=latest)](https://vital-sqi.readthedocs.io/en/latest/?badge=latest)\r\n<!-- ![PyPI Downloads](https://img.shields.io/pypi/dm/vitalsqi)\r\n[![PyPI version](https://badge.fury.io/py/vitalsqi.svg)](https://badge.fury.io/py/vitalsqi)\r\n[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Oucru-Innovations/vital-sqi/blob/main/docs/source/notebooks/synthesize_data.ipynb) -->\r\n\r\n---\r\n\r\n# Overview\r\n\r\n**Vital_sqi** is an open-source Python package for **signal quality index (SQI)** extraction and **quality classification** of ECG and PPG signals. The package enables streamlined signal quality control, essential for reliable health monitoring and clinical research.\r\n\r\n## Key Features:\r\n1. Support for **PPG and ECG signals** in various formats, including wearable device data.\r\n2. Implementation of **state-of-the-art SQI extraction methods** (e.g., statistical, HRV, waveform-based).\r\n3. Rule-based **quality classification** using user-defined thresholds.\r\n4. **Pipelines** for end-to-end processing, from data ingestion to SQI classification.\r\n5. A **GUI tool** for defining rules and visualizing results interactively.\r\n\r\n---\r\n\r\n# Prerequisites and Installation\r\n\r\nThe package supports Python `3.7` and `3.8`. Install Vital_sqi using pip:\r\n\r\n```bash\r\npip install vitalSQI-toolkit\r\n```\r\n\r\n### Optional Dependencies:\r\n- **Dash** for GUI applications.\r\n- **Plotly** for visualization.\r\n- **Matplotlib** for advanced plotting options.\r\n\r\nFor detailed dependencies, refer to the [documentation](https://vital-sqi.readthedocs.io/en/latest/).\r\n\r\n---\r\n\r\n# Getting Started\r\n\r\nThe core of the package is built around three main classes:\r\n\r\n### **1. SignalSQI Class**\r\nThis class handles the main signal data and SQI extraction workflow.\r\nAttributes:\r\n- `signal`: Waveform data (as a pandas DataFrame).\r\n- `sampling_rate`: Sampling rate of the signal (user-defined or auto-inferred).\r\n- `sqis`: SQI values calculated for signal segments.\r\n- `rules` and `ruleset`: Lists of applied rules and the ruleset used for classification.\r\n\r\n### **2. Rule Class**\r\nDefines individual SQI-based rules for classification.\r\nExample rule structure in JSON:\r\n```json\r\n{\r\n \"test_sqi\": {\r\n \"name\": \"test_sqi\",\r\n \"def\": [\r\n {\"op\": \">\", \"value\": \"10\", \"label\": \"reject\"},\r\n {\"op\": \">=\", \"value\": \"3\", \"label\": \"accept\"},\r\n {\"op\": \"<\", \"value\": \"3\", \"label\": \"reject\"}\r\n ],\r\n \"desc\": \"\",\r\n \"ref\": \"\"\r\n }\r\n}\r\n```\r\n\r\n### **3. Ruleset Class**\r\nGroups rules and defines the sequence for applying them to signal segments. The ruleset is defined in JSON format and can be customized to fit specific needs.`ruleset` object of class `Ruleset` contains a set of selected `rules` (selected from the list of rules in `signal_obj.rule`) and the order to apply them in quality \r\nassignment (see schema below). Notice that this is not a tree-based classification.\r\n \r\n![Example of a rule set](images/resize_sample_rule_chart.png \"Example of a rule set\")\r\n\r\n# Pipelines\r\n\r\nThe package includes predefined pipelines for processing ECG and PPG signals. \r\n\r\n### Example: Extracting SQIs from ECG\r\n```python\r\nfrom vital_sqi.pipeline.pipeline_highlevel import *\r\nfrom vital_sqi.data.signal_sqi_class import SignalSQI\r\nimport os\r\n\r\nfile_in = os.path.abspath('tests/test_data/example.edf')\r\nsqi_dict = os.path.abspath('tests/test_data/sqi_dict.json')\r\nsegments, signal_sqi_obj = get_ecg_sqis(file_in, sqi_dict, 'edf')\r\n```\r\n\r\n### Example: Quality Classification for ECG\r\n```python\r\nfrom vital_sqi.pipeline.pipeline_highlevel import *\r\nimport os\r\nimport tempfile\r\n\r\nfile_in = os.path.abspath('tests/test_data/example.edf')\r\nsqi_dict = os.path.abspath('tests/test_data/sqi_dict.json')\r\nrule_dict_filename = os.path.abspath('tests/test_data/rule_dict_test.json')\r\nruleset_order = {3: 'skewness_1', 2: 'entropy', 1: 'perfusion'}\r\noutput_dir = tempfile.gettempdir()\r\n\r\nsignal_obj = get_qualified_ecg(\r\n file_name=file_in,\r\n sqi_dict_filename=sqi_dict,\r\n file_type='edf',\r\n duration=30,\r\n rule_dict_filename=rule_dict_filename,\r\n ruleset_order=ruleset_order,\r\n output_dir=output_dir\r\n)\r\n```\r\n\r\n---\r\n\r\n# GUI for Rules and Execution\r\n\r\nVital_sqi provides a GUI for creating rules, defining rulesets, and executing them interactively. The GUI helps users:\r\n- Configure rules visually.\r\n- Test and validate signal quality thresholds.\r\n- Export results for further analysis.\r\n\r\n[Click here for the GUI guide](https://vital-sqi.readthedocs.io/en/latest/docstring/vital_sqi.app.html#module-vital_sqi.app.app).\r\n\r\n\r\n# Workflow Overview\r\n\r\n### **1. Reading and Writing Signals**\r\nSupported formats:\r\n- ECG: `EDF`, `MIT`, `CSV`.\r\n- PPG: `CSV`.\r\n\r\n### **2. Preprocessing and Segmentation**\r\nAvailable preprocessing steps:\r\n- Trimming, tapering, and smoothing.\r\n- Bandpass filtering.\r\n- Segmentation by duration or by beat.\r\n\r\n### **3. SQI Extraction**\r\nFour types of SQIs:\r\n1. **Statistical SQIs**: Kurtosis, skewness, entropy, etc.\r\n2. **HRV-based SQIs**: SDNN, SDSD, RMSSD, etc.\r\n3. **RR Interval-based SQIs**: Ectopic, correlogram, etc.\r\n4. **Waveform-based SQIs**: DTW, QRS energy, etc.\r\n\r\nThe function `vital_sqi.pipeline_function.extract_sqi` is used to extract a number of SQIs from segments. The requested SQIs\r\nare defined in a json file called SQI dictionary. We provide a dictionary template for all implemented SQIs, with default \r\nparameters, in `vital_sqi/resource/sqi_dict.json`.\r\n\r\n### **4. Signal Quality Classification**\r\n- Rule-based classification using user-defined thresholds.\r\n- Optimized rule application for performance.\r\n\r\nTemplates for rules and rulesets are available in the `vital_sqi/resource` directory.\r\n\r\nThe package allows making rule set from SQIs and user-defined thresholds for quality classification. A segment assigned \r\nas `accept` pass all rules in the set, otherwise `reject`. Rules in the set have ordered, which might help to \r\nimprove speed.\r\n\r\nWe ran brute force threshold searching for an in-house PPG dataset (generated with Smartcare, doubly annotated \r\nby domain experts) to obtain a set of recommended thresholds, as found in `resource/rule_dict.json`.\r\n\r\n---\r\n\r\n# Documentation\r\n\r\nFind detailed tutorials, examples, and API references at:\r\n\ud83d\udd17 [Vital_sqi Documentation](https://vital-sqi.readthedocs.io/en/latest/)\r\n\r\n---\r\n\r\n# Contributions\r\n\r\nWe welcome contributions from the community! Please refer to our [CONTRIBUTING.md](https://github.com/Oucru-Innovations/vital-sqi/blob/main/CONTRIBUTING.md) for guidelines.\r\n\r\n---\r\n\r\n# References\r\n\r\n- [Optimal Signal Quality Index for Photoplethysmogram Signals](https://doi.org/10.xxxx)\r\n- [Other relevant papers and research articles]\r\n\r\n---\r\n\r\n# License\r\n\r\nVital_sqi is licensed under the MIT License. See the [LICENSE](https://github.com/Oucru-Innovations/vital-sqi/blob/main/LICENSE) file for details.\r\n\r\n---\r\n\r\nThank you for supporting Vital_sqi! For questions or issues, feel free to [open an issue](https://github.com/Oucru-Innovations/vital-sqi/issues) on GitHub.\r\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A toolkit for signal quality analysis of ECG and PPG signals",
"version": "1.0.2",
"project_urls": {
"Documentation": "https://pypi.org/project/vitalsqi_toolkit/",
"Homepage": "https://github.com/Oucru-Innovations/vital-sqi",
"Source": "https://github.com/Oucru-Innovations/vital-sqi",
"Tracker": "https://github.com/Oucru-Innovations/vital-sqi/issues"
},
"split_keywords": [
"signal quality",
" ecg",
" ppg",
" toolkit"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "ac3386010365658aa34735597cbe09a8335f09e6a756ebb3b6b1ed2d2e150205",
"md5": "4bf07bbbb3b872d4d4471bfd5d31fddd",
"sha256": "8a2c15175917808067f150a23883369ae7e0ba780099640559d5fa0a75ed67ae"
},
"downloads": -1,
"filename": "vitalsqi_toolkit-1.0.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "4bf07bbbb3b872d4d4471bfd5d31fddd",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 143945,
"upload_time": "2024-11-28T08:35:50",
"upload_time_iso_8601": "2024-11-28T08:35:50.605898Z",
"url": "https://files.pythonhosted.org/packages/ac/33/86010365658aa34735597cbe09a8335f09e6a756ebb3b6b1ed2d2e150205/vitalsqi_toolkit-1.0.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "28893ae973c1d3f9dd3797ca8c4357ab8fc519bccd6583e4d29a39c52b06b668",
"md5": "c3c8022dbe8d8d7b733ae9cb6fb32ad9",
"sha256": "e9adcbdad4340a30dd733cd3c2365ca83abdda4d47face5de489a7edec640786"
},
"downloads": -1,
"filename": "vitalsqi_toolkit-1.0.2.tar.gz",
"has_sig": false,
"md5_digest": "c3c8022dbe8d8d7b733ae9cb6fb32ad9",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 67598,
"upload_time": "2024-11-28T08:35:52",
"upload_time_iso_8601": "2024-11-28T08:35:52.725396Z",
"url": "https://files.pythonhosted.org/packages/28/89/3ae973c1d3f9dd3797ca8c4357ab8fc519bccd6583e4d29a39c52b06b668/vitalsqi_toolkit-1.0.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-28 08:35:52",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Oucru-Innovations",
"github_project": "vital-sqi",
"travis_ci": true,
"coveralls": true,
"github_actions": true,
"requirements": [
{
"name": "vitalDSP",
"specs": []
},
{
"name": "openpyxl",
"specs": []
},
{
"name": "matplotlib",
"specs": []
},
{
"name": "numpy",
"specs": [
[
">=",
"1.20.2"
]
]
},
{
"name": "pandas",
"specs": [
[
">=",
"1.1.5"
]
]
},
{
"name": "plotly",
"specs": [
[
">=",
"4.14.3"
]
]
},
{
"name": "scikit-learn",
"specs": [
[
">=",
"0.24.1"
]
]
},
{
"name": "scipy",
"specs": [
[
">=",
"1.6.0"
]
]
},
{
"name": "tqdm",
"specs": [
[
">=",
"4.56.0"
]
]
},
{
"name": "pmdarima",
"specs": [
[
">=",
"1.8.0"
]
]
},
{
"name": "pyEDFlib",
"specs": [
[
">=",
"0.1.20"
]
]
},
{
"name": "pycwt",
"specs": [
[
">=",
"0.3.0a22"
]
]
},
{
"name": "statsmodels",
"specs": [
[
">=",
"0.12.2"
]
]
},
{
"name": "wfdb",
"specs": [
[
">=",
"3.3.0"
]
]
},
{
"name": "datetimerange",
"specs": [
[
">=",
"1.0.0"
]
]
},
{
"name": "dateparser",
"specs": [
[
">=",
"1.0.0"
]
]
},
{
"name": "pyflowchart",
"specs": [
[
">=",
"0.1.3"
]
]
},
{
"name": "pytest",
"specs": [
[
"~=",
"6.2.3"
]
]
},
{
"name": "setuptools",
"specs": [
[
"~=",
"52.0.0"
]
]
},
{
"name": "dash",
"specs": [
[
">=",
"1.20.0"
]
]
}
],
"tox": true,
"lcname": "vitalsqi-toolkit"
}