{"id":24598337,"url":"https://github.com/rosnavigator/ecg_compressedsensing","last_synced_at":"2026-04-15T18:01:46.462Z","repository":{"id":252076241,"uuid":"839353260","full_name":"RosNaviGator/Ecg_CompressedSensing","owner":"RosNaviGator","description":"The project involves developing a Python library for ECG compressed sensing. The software will include modules for data reading, visualization, compressed-sensing, reconstruction, and evaluation.","archived":false,"fork":false,"pushed_at":"2024-09-27T18:39:56.000Z","size":179085,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-18T05:33:01.398Z","etag":null,"topics":["compressed-sensing","dictionary-learning","ecg","ecg-signal","heart","numerical-analysis","python","signal-processing"],"latest_commit_sha":null,"homepage":"https://rosnavigator.github.io/NAML_ECG_compressor/","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RosNaviGator.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-07T12:45:28.000Z","updated_at":"2025-02-24T16:49:30.000Z","dependencies_parsed_at":"2024-09-16T00:14:54.314Z","dependency_job_id":"83e8bdd6-5b01-47fc-9a40-7a07df02bfcf","html_url":"https://github.com/RosNaviGator/Ecg_CompressedSensing","commit_stats":null,"previous_names":["rosnavigator/naml_ecg_compressor","rosnavigator/ecg_compressedsensing"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/RosNaviGator/Ecg_CompressedSensing","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RosNaviGator%2FEcg_CompressedSensing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RosNaviGator%2FEcg_CompressedSensing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RosNaviGator%2FEcg_CompressedSensing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RosNaviGator%2FEcg_CompressedSensing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RosNaviGator","download_url":"https://codeload.github.com/RosNaviGator/Ecg_CompressedSensing/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RosNaviGator%2FEcg_CompressedSensing/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268331176,"owners_count":24233198,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compressed-sensing","dictionary-learning","ecg","ecg-signal","heart","numerical-analysis","python","signal-processing"],"created_at":"2025-01-24T12:15:53.141Z","updated_at":"2026-04-15T18:01:46.456Z","avatar_url":"https://github.com/RosNaviGator.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ECG Compressed Sensing with Kronecker Technique \u0026 Adaptive Dictionary Learning\n\n__Date:__ September 2024\n\n__Author:__ Francesco Rosnati, HPC Engineering Master's student at Politecnico di Milano\n\n__Course:__ Numerical Analysis for Machine Learning at Politecnico di Milano -- Professor Edie Miglio\n\n\u003cdiv style=\"text-align: center;\"\u003e\n    \u003cimg src=\"./.img/ECG_wave.jpg\" alt=\"ECG graph\" width=\"600\"\u003e\n\u003c/div\u003e\n\n\n## Overview\n\nThis project explores the application of **Compressed Sensing (CS)** techniques to electrocardiogram (ECG) signal processing, specifically leveraging adaptive dictionary learning methods and the Kronecker technique for sparse signal recovery. In particular the goal is to explore soultions that would fit on _portable remote_ Ecg machines which have low computational power and limited storage capacity.\n\n### Refer to the [Report](./Others/Report/NAML_report.pdf) for a thorough review of the present study and it's results.\n\n### Goal\nThe goal of this project is to apply compressed sensing to ECG data and investigate the performance of adaptive dictionary learning (MOD and K-SVD) compared to fixed dictionaries (DCT), with and without the Kronecker technique. We aim to determine whether adaptive methods can outperform fixed dictionaries in terms of signal reconstruction quality. In particular it will be tested trying to simulate what would be possible to achieve with a _remote portable_ Ecg machine, such apparatus limits the computational power in measurement phase and has linited torage capabilites. (Recovery is not limited because it doesn't have to happen on-chip, it can be done on more powerful machines in a second moment)\n\nThe present project is mainly ispired by the work \"A compressed-sensing-based compressor for ECG.\" by Izadi V, Shahri PK, Ahani H. \u003ca href=\"#ref1\"\u003e[1]\u003c/a\u003e\n\n### Compressed Sensing\n\nCompressed Sensing is a method that exploits the sparsity of signals to enable recovery from fewer measurements than what classical Nyquist sampling theory requires. In essence, CS leverages the fact that many real-world signals ($`x`$) are sparse when represented in certain domains (e.g., frequency domain). Sparsity means that in such domain the signal can be represented with only a few non-zero coefficients, the _dictionary_ $`\\Psi`$ can be seen as the tranformation that maps the real signal to it's sparse counterpart: $`x = \\Psi s`$, where $`s`$ is the sparse version.\n\nGiven a sparse signal $`x`$, we can acquire compressed measurements $`y`$ by multiplying $`x`$ with a measurement matrix: $`y = \\Phi x`$\n\nCompressed sensing aims to recover $`x`$ from the compressed measurements $`y`$. The goal is to find the __sparsest__ vector $`s`$ that is consistent with:\n\n$$\ny = \\Phi x = \\Phi \\Psi s\n$$\n\n- $`x \\in \\mathbb{R}^n`$ _real_ signal coming from sensors\n- $`y \\in \\mathbb{R}^m`$ _compressed measurement_\n- $`\\Psi \\in \\mathbb{R}^{n \\times n}`$ is the _dictionary_ (same as explained in previous section)\n- $`\\Phi \\in \\mathbb{R}^{m \\times n}`$ with $m \\ll n$ is the _measurement matrix_.\n- $`s \\in \\mathbb{R}^n`$ is the _sparse representation_ of $x$ in $\\Psi$\n\nSuch system of equations is __under-determined__ since there are infinitely many consistent solution $`s`$. The __sparsest solution__ is the one that satisfies:\n\n$$\n\\hat{s} = \\arg_{s} \\min \\|s\\|_0 \\text{ subject to } y = \\Phi \\Psi \\alpha\n$$\n\nwhere $`\\min \\|s\\|_0`$ denotes the $`\\ell_0`$-pseudo-norm, given by the _non-zero entries_, also referred as the _cardinality_ of $`s`$.\n\nThe optimization is non-convex, and in general, the solution can only be found with a brute-force search that is combinatorial in $`n`$ and $`K`$. In particular, all possible $`K`$-sparse vectors in $`\\mathbb{R}^n`$ must be checked; if the exact level of sparsity $`K`$ is unknown, the search is even broader. Because this search is combinatorial, solving such minimization is intractable for even moderately large $`n`$ and $`K`$, and the prospect of solving larger problems does not improve with Moore’s law of exponentially increasing computational power. \u003ca href=\"#ref7\"\u003e[7]\u003c/a\u003e\n\n### Measurement matrix\nIn the present project different _measurement matrices_ are explored: deterministic _DBBD_ (deterministic binary block diagonal) and _randomic_ gaussian or binary (binary both normalized and not). The idea is to test which dictionaries work best on a given the given measurement matrices.\n\n### Dictionaries\nThe success of CS hinges on the sparsity of the signal. Sparsity refers to how efficiently a signal can be represented using only a few non-zero coefficients in a dictionary. A **dictionary** is a set of basis functions used to represent the signal in a sparse form. \n\nThere are two types of dictionaries:\n- **Fixed Dictionaries**: Predefined, like the **Discrete Cosine Transform (DCT)**, used as a baseline in this project.\n- **Adaptive Dictionary Learning**: Methods that adapt the dictionary to the data, aiming for better representation. \u003ca href=\"#ref2\"\u003e[2]\u003c/a\u003e Two key adaptive methods explored here are:\n  - **MOD (Method of Optimal Directions)** \u003ca href=\"#ref3\"\u003e[3]\u003c/a\u003e\n  - **K-SVD (K-Singular Value Decomposition)** \u003ca href=\"#ref4\"\u003e[4]\u003c/a\u003e\n\nThese adaptive methods aim to outperform fixed dictionaries by tailoring the dictionary to the specific signal.\n\n### Solve the minimization problem: SL0 Algorithm\nThe **Smoothed L0 (SL0)** algorithm is employed to solve the sparse recovery problem. SL0 approximates the L0 norm, which counts the number of non-zero coefficients, with a smooth function. It minimizes this approximation while maintaining accuracy in signal recovery. \u003ca href=\"#ref6\"\u003e[6]\u003c/a\u003e\n\n### Kronecker Technique\nThe **Kronecker technique** is used in this project to exploit the sparsity structure of the signal. It involves constructing a Kronecker product of smaller measurement matrices, which leads to computational efficiency and better recovery performance in certain scenarios. The project evaluates the performance of the Kronecker technique in conjunction with fixed and adaptive dictionaries. \u003ca href=\"#ref5\"\u003e[5]\u003c/a\u003e\n\n\n## Code Overview\n\n### Refer to the [Official Documentation Website](https://rosnavigator.github.io/Ecg_CompressedSensing/) for more in depth description.\n\n### [CompSensePack](./CompSensePack/)\n\nThe **CompSensePack** package is designed to handle the core tasks of compressed sensing and dictionary learning. It provides modular tools and high-level abstractions for applying compressive sensing techniques to various signals, with a focus on electrocardiogram (ECG) data in this project. The package is divided into two major components: the main package, which handles signal processing, sparse recovery, and general utilities, and the dictionaries subpackage, which is focused on dictionary learning techniques.\n\nThe main package offers a range of modules to perform the following tasks:\n\n- **SL0 Algorithm**\n- **Measurement Matrix Generation**\n- **Utilities**\n- **Evaluation and Plotting**\n- **Compressed Sensing Class**\n\n### Dictionaries Subpackage\n\nThe **Dictionaries Subpackage** is a specialized part of the library (it's contained in the _CompSensePack_), dedicated to the generation and learning of dictionaries. Dictionaries are the set of basis functions in which the signal is sparsely represented, and they are central to the performance of compressed sensing. The subpackage offers both fixed dictionaries and adaptive dictionary learning algorithms, enabling flexibility in how the signal is represented and reconstructed.\n\n- **KSVD Dictionary Learning**\n- **MOD Dictionary Learning**\n- **OMP Algorithm**\n- **DCT Dictionary**\n- **Dictionary Utilities**\n\n### [Scripts](./Scripts/)\n\nThe **Scripts** directory contains Python scripts to run the experiments and test the package functionality:\n\n#### ecgStudy\nMain experiments runned\n  - `study_100m_signal.py`: Applies the compressed sensing techniques (DCT, MOD, K-SVD) to a specific ECG signal from the MIT-BIH Arrhythmia Database (Record 100), comparing the performance of the different methods.\n  - `visualize_wfdb_signals.py`: Allows users to visualize the compressed sensing results on a signal from the MIT-BIH database using different dictionaries and measurement matrices.\n\n#### functionalityTesting\n_Debug_ scripts to test single modules\n  - `testDictionaries.py`: Tests dictionary learning methods like DCT, MOD, and K-SVD.\n  - `testEval.py`: Tests evaluation methods for comparing reconstructed signals.\n  - `testMeasurementMatrix.py`: Tests different measurement matrices used in compressed sensing.\n  - `testSL0.py`: Verifies the implementation and performance of the SL0 algorithm.\n  - `testUtils.py`: Tests utility functions within the package.\n\n## How to Use\n\n- Instruction to [run in local environment](#run-in-local-environment)\n- The notebook used during construction of the program is still available [here](Others/.additionalMaterials/buildingProgram.ipynb).\n\n### Run in local environment\n\n#### Python3 required\n\n### 1. Set Up a Virtual Environment (optional)\n#### Linux or MacOs (Unix-based)\n```bash\nif [[ \"$VIRTUAL_ENV\" != \"\" ]]; then\n    # Deactivate any active virtual environment if one exists\n    deactivate\n    # Remove any previous instance of .venvCsp\nrm -r .venvCsp\nfi\n# Create and activate a new virtual environment, ensure 'python' refers to python3\npython -m venv .venvCsp\nsource .venvCsp/bin/activate\n```\n#### Windows (only Git bash supported for now)\n```bash\n# Deactivate any active virtual environment if one exists (Git Bash syntax)\nif [[ \"$VIRTUAL_ENV\" != \"\" ]]; then\n    deactivate\n    rm -r .venvCsp\nfi\n# Create and activate a new virtual environment, ensure 'python' is python3\npython -m venv .venvCsp\nsource .venvCsp/Scripts/activate\n```\n\n### 2. Install CompSensePack (it also installs requirements)\n```bash\npip install .\n```\n\n### 3. Run the Scripts\n__Run from the _root_ directory of the project!__\n\n#### Methods efficiency comparison\n- Test the various _measurement matrices_, _dictionaries_, _Kronecker technique_, and so on.\n- [Change the parameters at the bottom of the script](./Scripts/ecgStudy/study_100m_signal.py) in the `__main__`, feel free to experiment. It works with a single _record_, which is contained in [data](./data/) directory.\n```bash\npython Scripts/ecgStudy/study_100m_signal.py\n``` \n#### Visualize recontructed signal\n- This script will process the signals and plot reconstructed version over the original. It's possible to download any record of the [MIT-BIH Arrhythmia Database](https://physionet.org/content/mitdb/1.0.0/) available through the [wfdb](https://wfdb.readthedocs.io/en/latest/) library.\n- [Feel free to change parameters](./Scripts/ecgStudy/visualize_wfdb_signals.py).\n```bash\npython Scripts/ecgStudy/visualize_wfdb_signals.py\n```\n\n## Contributing\n\nIf you'd like to contribute to this project, feel free to open issues and submit pull requests. Any improvements or additional features are welcome.\n\n\n## References\n\n1. \u003ca id=\"ref1\"\u003e\u003c/a\u003e Izadi V, Shahri PK, Ahani H. \"[A compressed-sensing-based compressor for ECG](./Others/Papers/ECG-compressedSensing/CS-based_ECGcompressor.pdf).\" *Biomed Eng Lett.* 2020 Feb 6;10(2):299-307. doi: [10.1007/s13534-020-00148-7](https://doi.org/10.1007/s13534-020-00148-7). PMID: 32431956; PMCID: PMC7235110.\n\n2. \u003ca id=\"ref2\"\u003e\u003c/a\u003e Olshausen, B., Field, D. \"[Emergence of simple-cell receptive field properties by learning a sparse code for natural images](./Others/Papers/AdaptiveDictionaryLearning/adaptiveDictOriginalArticle.pdf).\" *Nature* 381, 607–609 (1996). doi: [10.1038/381607a0](https://doi.org/10.1038/381607a0).\n\n3. \u003ca id=\"ref3\"\u003e\u003c/a\u003e Engan, K., Aase, S., Husoy, J. \"[Method of Optimal Directions for frame design](./Others/Papers/AdaptiveDictionaryLearning/mod.pdf).\" *ICASSP, IEEE International Conference on Acoustics, Speech and Signal Processing* - Proceedings. 5. 2443 - 2446 vol.5. 1999. doi: [10.1109/ICASSP.1999.760624](https://doi.org/10.1109/ICASSP.1999.760624).\n\n4. \u003ca id=\"ref4\"\u003e\u003c/a\u003e M. Aharon, M. Elad and A. Bruckstein. \"[K-SVD: An algorithm for designing overcomplete dictionaries for sparse representation](./Others/Papers/AdaptiveDictionaryLearning/ksvd.pdf).\" *IEEE Transactions on Signal Processing,* vol. 54, no. 11, pp. 4311-4322, Nov. 2006. doi: [10.1109/TSP.2006.881199](https://doi.org/10.1109/TSP.2006.881199).\n\n5. \u003ca id=\"ref5\"\u003e\u003c/a\u003e Zanddizari H, Rajan S, Zarrabi H. \"[Increasing the quality of reconstructed signal in compressive sensing utilizing Kronecker technique](./Others/Papers/Kronecker%20Technique/kronecker.pdf).\" *Biomed Eng Lett.* 2018 Jan 31;8(2):239-247. doi: [10.1007/s13534-018-0057-4](https://doi.org/10.1007/s13534-018-0057-4). PMID: 30603207; PMCID: PMC6208527.\n\n6. \u003ca id=\"ref6\"\u003e\u003c/a\u003e H. Mohimani, M. Babaie-Zadeh and C. Jutten. \"[A Fast Approach for Overcomplete Sparse Decomposition Based on Smoothed  ℓ0  Norm](./Others/Papers/ReconstructionMethods/Smooth-L0/smooth-L0.pdf).\" *IEEE Transactions on Signal Processing,* vol. 57, no. 1, pp. 289-301, Jan. 2009. doi: [10.1109/TSP.2008.2007606](https://doi.org/10.1109/TSP.2008.2007606).\n\n7. \u003ca id=\"ref7\"\u003e\u003c/a\u003e Brunton, S. L., Kutz, J. N. \"Data-Driven Science and Engineering: Machine Learning, Dynamical Systems, and Control.\" *Cambridge University Press,* 2019. ISBN: 9781108422093. Available at [Cambridge University Press](https://www.cambridge.org/highereducation/books/data-driven-science-and-engineering/44AE36BB7D4FD41E241ADBE6118E64BB).\n\n\n\n## Bugs \u0026 Possible Future developements\n\n- The possibility of \"mantaining one or more of the initial atoms\" in the Dictionary in the KSVD implementation is not working properly, it's is not a particularly relevant feature in Ecg Signal processing\n- The record \"100m.mat\" is **weird**... It's the one which I performed the main study of best methods, but after the study I realized that the SNR values and the whole record do not match with the actual record from `wfdb`: in the future it would be advisable to repeat the study with an actual record from `wfdb`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frosnavigator%2Fecg_compressedsensing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frosnavigator%2Fecg_compressedsensing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frosnavigator%2Fecg_compressedsensing/lists"}