OSCR

Leednet: a lightweight network for event detection in EEG signals.

Code ↔ Paper

7 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 7 matches
  1. [1] § Results and discussion › Feature extraction using signal decomposition techniques ↔ ablation_study/preprocess_data.py, lines 59–87 · score 0.74 · Frequency Domain Features, peak frequency, bandwidth, kurtosis, sum, centroid
  2. [2] § Methodology › Training protocol ↔ ablation_study/src/train_eval.py, lines 200–250 · score 0.69 · AdamW, ReduceLROnPlateau, weight decay, scheduler, optimizer, epochs
  3. [3] § Results and discussion › Feature extraction using signal decomposition techniques ↔ ablation_study/notebooks/exp25_vmd_handcrafted_features.ipynb, lines 1–50 · score 0.68 · spectral centroid, peak frequency, VMD, Frequency Domain, skewness, bandwidth
  4. [4] § Methodology › Training protocol ↔ experiments/LEEDNet_Parameters.ipynb, lines 32–73 · score 0.68 · AdamW, ReduceLROnPlateau, weight decay, scheduler, optimizer, loss
  5. [5] § Methodology › Dataset and segment annotation ↔ Dataset_Creation/config.py, lines 75–105 · score 0.64 · delta slow wave, Sharp Waves, duration, validation, Spike, abnormal
  6. [6] § Methodology › Dataset and segment annotation ↔ Dataset_Creation/abnormality_extraction.ipynb, lines 70–113 · score 0.62 · delta slow wave, Sharp Waves, polyspikes, abnormal, activity
  7. [7] § Methodology › Model architecture › Single-branch LEEDNet ↔ ablation_study/src/models/LEEDNetModel.py, lines 116–202 · score 0.50 · fusion gate, head, single branch, module, classification, EEG

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Python · 208 lines · 8.3 KB · no license · 1 match

  1. import os
  2. import sys
  3. import numpy as np
  4. import pandas as pd
  5. import torch
  6. import pywt
  7. from scipy.signal import lfilter, bessel
  8. from tqdm import tqdm
  9. from vmdpy import VMD
  10. from scipy.stats import kurtosis, skew, entropy
  11. # --- Pre-processing Functions ---
  12. def bessel_bandpass(data, lowcut=0.01, highcut=15, fs=200, order=4):
  13. b, a = bessel(order, [lowcut, highcut], btype='band', fs=fs)
  14. return lfilter(b, a, data)
  15. # MSPCA (copied from notebooks for consistency)
  16. def _hankel_avg(matrix, orig_len):
  17. K, L = matrix.shape
  18. result = np.zeros(orig_len); counts = np.zeros(orig_len)
  19. for i in range(K):
  20. result[i:i+L] += matrix[i]
  21. counts[i:i+L] += 1
  22. return result / counts
  23. def mspca_denoise(signal, wavelet='db4', level=5, device=None):
  24. if device is None:
  25. device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
  26. sig = np.array(signal, dtype=np.float64).flatten()
  27. n = len(sig)
  28. coeffs = pywt.wavedec(sig, wavelet, level=level)
  29. rec = np.zeros(n)
  30. for i, c in enumerate(coeffs):
  31. L = len(c)
  32. K = n - L + 1
  33. if K <= 0:
  34. temp_coeffs = [np.zeros_like(cc) for cc in coeffs]
  35. temp_coeffs[i] = c
  36. rec += pywt.waverec(temp_coeffs, wavelet)[:n]
  37. continue
  38. H = np.zeros((K, L))
  39. for j in range(K): H[j] = sig[j:j+L]
  40. H_t = torch.tensor(H, dtype=torch.float32).to(device)
  41. U, S, V = torch.svd(H_t)
  42. S_np = S.cpu().numpy(); s_sq = S_np**2; var = np.cumsum(s_sq) / np.sum(s_sq)
  43. rank = np.searchsorted(var, 0.95) + 1
  44. S_th = torch.zeros_like(S); S_th[:rank] = S[:rank]
  45. H_rec = torch.mm(U, torch.mm(torch.diag(S_th), V.t())).cpu().numpy()
  46. rec += _hankel_avg(H_rec, n)
  47. return rec / len(coeffs)
  48. def vmd_decompose(signal, n_modes=5):
  49. # n_modes Intrinsic Mode Functions (IMFs)
  50. # alpha=2000, tau=0, K=n_modes, DC=0, init=1, tol=1e-7
  51. u, u_hat, omega = VMD(signal, 2000, 0, n_modes, 0, 1, 1e-7)
  52. return u # [n_modes, T]
  53. def extract_vmd_features(imfs, fs=200):
  54. all_feats = []
  55. for imf in imfs:
  56. # Energy features
  57. energy = np.sum(imf**2)
  58. # Statistical features
  59. m = np.mean(imf)
  60. v = np.var(imf)
  61. s = np.std(imf)
  62. k = kurtosis(imf)
  63. sk = skew(imf)
  64. # Entropy features
  65. p = np.abs(imf) + 1e-12
  66. p /= np.sum(p)
  67. h = entropy(p)
  68. # Frequency-domain features
  69. fft = np.fft.rfft(imf)
  70. mags = np.abs(fft)
  71. freqs = np.fft.rfftfreq(len(imf), d=1/fs)
  72. sum_mags = np.sum(mags) + 1e-12
  73. centroid = np.sum(freqs * mags) / sum_mags
  74. bandwidth = np.sqrt(np.sum(((freqs - centroid)**2) * mags) / sum_mags)
  75. peak_freq = freqs[np.argmax(mags)]
  76. all_feats.extend([energy, m, v, s, k, sk, h, centroid, bandwidth, peak_freq])
  77. return np.array(all_feats, dtype=np.float32)
  78. # --- Main Script ---
  79. def preprocess_experiment(exp_id, csv_files, base_save_dir, device):
  80. print(f"\n>>> Processing Experiment {exp_id}...")
  81. num_skipped = 0
  82. num_processed = 0
  83. for csv_path in csv_files:
  84. df = pd.read_csv(csv_path)
  85. new_data = []
  86. save_dir = os.path.join(base_save_dir, f"exp{exp_id}", os.path.basename(csv_path).replace('.csv', ''))
  87. os.makedirs(save_dir, exist_ok=True)
  88. desc = f"Exp{exp_id} - {os.path.basename(csv_path)}"
  89. for idx, row in tqdm(df.iterrows(), total=len(df), desc=desc):
  90. file_path = row['file_name']
  91. # Save Path Check
  92. save_name = os.path.basename(file_path).replace('.npz', '.npy')
  93. save_path = os.path.join(save_dir, save_name)
  94. if os.path.exists(save_path):
  95. num_skipped += 1
  96. new_row = row.copy()
  97. new_row['file_name'] = save_path
  98. new_data.append(new_row)
  99. continue
  100. try:
  101. raw_data = np.load(file_path)['data'][0] # Channel 0
  102. except Exception as e:
  103. print(f"Error loading {file_path}: {e}")
  104. continue
  105. # Apply Pre-processing
  106. if exp_id == 1: # Symlet DWT
  107. filtered = bessel_bandpass(raw_data)
  108. coeffs = pywt.wavedec(filtered, 'sym5', level=4)
  109. feat = np.concatenate(coeffs).astype(np.float32)
  110. elif exp_id == 2: # Daubechies DWT
  111. filtered = bessel_bandpass(raw_data)
  112. coeffs = pywt.wavedec(filtered, 'db4', level=4)
  113. feat = np.concatenate(coeffs).astype(np.float32)
  114. elif exp_id == 3: # MSPCA
  115. feat = mspca_denoise(raw_data, device=device).astype(np.float32)
  116. elif exp_id == 4: # VMD
  117. filtered = bessel_bandpass(raw_data)
  118. feat = vmd_decompose(filtered, n_modes=5).astype(np.float32)
  119. elif exp_id == 5: # Baseline (t-SNE)
  120. feat = bessel_bandpass(raw_data).astype(np.float32)
  121. elif exp_id == 6: # Mexican Hat CWT (mexh)
  122. filtered = bessel_bandpass(raw_data)
  123. coeffs, _ = pywt.cwt(filtered, np.arange(1, 31), 'mexh', sampling_period=1/200)
  124. feat = coeffs.astype(np.float32)
  125. elif exp_id == 7: # Real Morlet CWT (morl)
  126. filtered = bessel_bandpass(raw_data)
  127. coeffs, _ = pywt.cwt(filtered, np.arange(1, 31), 'morl', sampling_period=1/200)
  128. feat = coeffs.astype(np.float32)
  129. elif exp_id == 8: # Gaussian Derivative CWT (gaus5)
  130. filtered = bessel_bandpass(raw_data)
  131. coeffs, _ = pywt.cwt(filtered, np.arange(1, 31), 'gaus5', sampling_period=1/200)
  132. feat = coeffs.astype(np.float32)
  133. elif exp_id == 9: # STFT / FFT Branch
  134. from scipy.signal import stft
  135. filtered = bessel_bandpass(raw_data)
  136. # raw_data is 1D, so filtered is 1D
  137. spec = np.abs(stft(filtered, fs=200, nperseg=64, noverlap=32)[2])**2
  138. feat = spec.astype(np.float32)
  139. elif exp_id == 24: # Sequential VMD -> CWT
  140. filtered = bessel_bandpass(raw_data)
  141. imfs = vmd_decompose(filtered, n_modes=5)
  142. cwt_results = []
  143. for i in range(imfs.shape[0]):
  144. coeffs, _ = pywt.cwt(imfs[i], np.arange(1, 31), 'cmor1.5-1.0', sampling_period=1/200)
  145. cwt_results.append(np.abs(coeffs))
  146. feat = np.mean(np.stack(cwt_results, axis=0), axis=0).astype(np.float32)
  147. elif exp_id == 25: # VMD Hand-crafted Features
  148. filtered = bessel_bandpass(raw_data)
  149. imfs = vmd_decompose(filtered, n_modes=5)
  150. feat = extract_vmd_features(imfs).astype(np.float32) # [50]
  151. # Save
  152. np.save(save_path, feat)
  153. num_processed += 1
  154. # Record
  155. new_row = row.copy()
  156. new_row['file_name'] = save_path
  157. new_data.append(new_row)
  158. # Save new CSV
  159. new_df = pd.DataFrame(new_data)
  160. # Special case mapping to match old suffix conventions
  161. suffix_str = f'_exp{exp_id}'
  162. if exp_id == 9:
  163. suffix_str = '_fft'
  164. new_csv_path = csv_path.replace('.csv', f'{suffix_str}.csv')
  165. new_df.to_csv(new_csv_path, index=False)
  166. print(f"Saved new catalog to {new_csv_path}")
  167. print(f"Experiment {exp_id} finished: Processed {num_processed}, Skipped {num_skipped}")
  168. if __name__ == "__main__":
  169. csv_files = [
  170. '/media/hira/SSD 4TB/code/LEEDNet_EEG_Event_Detection/ablation_study/dataset/train.csv',
  171. '/media/hira/SSD 4TB/code/LEEDNet_EEG_Event_Detection/ablation_study/dataset/eval.csv',
  172. '/media/hira/SSD 4TB/code/LEEDNet_EEG_Event_Detection/ablation_study/dataset/test.csv'
  173. ]
  174. base_save_dir = '/media/hira/SSD 4TB/code/LEEDNet_EEG_Event_Detection/ablation_study/dataset/preprocessed'
  175. device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
  176. print(f"Using device: {device}")
  177. # Run pre-processing for all experiments (1 through 9)
  178. preprocess_experiment(25, csv_files, base_save_dir, device)
  179. # for i in range(1, 10):
  180. # preprocess_experiment(i, csv_files, base_save_dir, device)
  181. print("\\nAll pre-processing complete!")

preprocess_data.py at commit 84143e0, no license · at the source

Overview

Authors: Mohammad Ali Alqarni1, Hira Masood2,3, Hassan Aqeel Khan4, Awais Mehmood Kamboh2, Saima Shafait5, Tooba Jaffarey6, Faisal Shafait2,7
  1. College of Computer Science and Engineering, University of Jeddah, Jeddah, Saudi Arabia
  2. School of Electrical Engineering and Computer Science, National University of Sciences and Technology, Islamabad, Pakistan
  3. Deep Learning Laboratory, National Center of Artificial Intelligence, Islamabad, Pakistan
  4. Department of Applied Artificial Intelligence and Robotics, Aston University Birmingham, Birmingham, B4 7ET United Kingdom
  5. Pak-Emirates Military Hospital, Rawalpindi, Pakistan
  6. AI Lounge Private Limited, Islamabad, Pakistan
  7. Guangdong CAS Cogniser Information Technology Co., Ltd., Guangzhou, China
Journal: Journal on advances in signal processing, volume 2026, issue 1, article 64
Dates: received 6 November 2025; accepted 27 April 2026; published online 26 May 2026; in print 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1186/s13634-026-01330-2 · PMID 42598465 · PMCID PMC13471070 · OpenAlex W7162443700
Open access: hybrid, a free copy (OpenAlex)
Status: code verified
Categories: EEG (modality)
Methods: Spectral & time-frequency, Connectivity, Smoothing, state filtering, decompositions, Preprocessing, Machine learning, Physiology & signal measures
Keywords: Automated EEG analysis, Computer-aided diagnosis, Computational neurology, Convolutional neural networks, Deep learning
Topic: EEG and Brain-Computer Interfaces (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Funding: Engineering and Physical Sciences Research Council (EP/Y002865/1); University of Jeddah (UJ-21-DR-105)
Citations: not cited yet (Europe PMC); 46 references in the paper

Abstract

Detection of diagnostically relevant events within an EEG recording requires making classification decisions about small event windows of a few seconds duration each. For long-duration EEG recordings, this can translate into thousands of decisions leading to a high computational load, which must be reduced for field deployments of EEG triage and decision support systems, especially in resource-constrained healthcare systems. In this work, we explore three avenues for enhancing computational efficiency: (1) purpose-built architectures; (2) length of the decision window/segment; and (3) lightweight preprocessing and feature extraction. For the architecture, we present LEEDNet (Lightweight EEG Event Detection Network), a lightweight convolutional architecture that is purpose-built for prompt classification of short EEG events into three categories (Normal, Slow Waves, or Spike and Sharp Waves). LEEDNet is evaluated on the expert-annotated NMT-Events dataset with subject-wise splits. Compared to four state-of-the-art baselines, LEEDNet delivers the best performance, on three out of four, performance evaluation metrics while being much more deployment friendly (requiring only 0.25 M parameters and 37 MFLOPs per segment, enabling inference in < 5 ms on a standard CPU). For the segment length, ablation results show a length of 2 s to be the best performing, with longer segments degrading due to label dilution and background dominance. We also examine the impact of different feature engineering configurations and whether the increased computational overhead associated with extraction of complex features leads to substantial performance gains. In particular, we examine three input modalities—raw signals, FFT-based spectra, and wavelets—both independently (single-branch) and in a modular, multi-branch fusion model. Our results indicate that the single-branch LEEDNet, based on Raw EEG data, achieves the best overall performance, with 81.2% accuracy and 77.5% macro-F1. No consistent gains were observed after the introduction of modalities based on Fourier and Wavelet features indicating that, for our architecture, a data-driven approach (based on raw EEG waveforms) is better suited compared to a handcrafted feature engineering approach. This is welcomed from a computation overhead perspective since complex feature engineering can be eliminated in favor of raw samples as input features without sacrificing performance.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repository

Its files are read in the Code ↔ Paper reader above, with 7 matches between paragraphs and lines of code.

dll-ncai/LEEDNet_EEG_Event_Detection

License: none: the authors keep all their rights
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Commit: 84143e0dd284e3b391f88f5c35a6ded123d48c26, 3 April 2026
Languages: Jupyter (43), Python (13)
Size: 91 files, 56 scripts
Software Heritage: not archived
Found in: the text, “Footnotes”
Holds: README, 43 notebooks
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: PyTorch (41 files), NumPy (11 files), pandas (8 files), Matplotlib (5 files), scikit-learn (5 files), PyWavelets (3 files), SciPy (3 files), seaborn (3 files), MNE-Python (1 file)
Availability: 1 check, the latest on 28 September 2026: the link answers
  • 28 September 2026: the link answers
46 files

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 45 scripts, each with its path and the digest of its content;
  • 7 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Data availability

This study used the publicly available NMT-Events Dataset. The dataset can be accessed at https://dll.seecs.nust.edu.pk/downloads/. No new data were generated in this work; only analyses of the existing dataset were performed.

Reproduced under the paper's license (CC BY), from the paper cited above.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 28 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 7 authors, 5 keywords, 2 funders, 23 references.

Cite

This paper

Alqarni, M. A., Masood, H., Khan, H. A., Kamboh, A. M., Shafait, S., Jaffarey, T., & Shafait, F. (2026). Leednet: a lightweight network for event detection in EEG signals. Journal on advances in signal processing, 2026(1), 64. https://doi.org/10.1186/s13634-026-01330-2

BibTeX

@article{alqarni2026leednet,
author = {Alqarni, Mohammad Ali and Masood, Hira and Khan, Hassan Aqeel and Kamboh, Awais Mehmood and Shafait, Saima and Jaffarey, Tooba and Shafait, Faisal},
title = {{Leednet: a lightweight network for event detection in EEG signals}},
journal = {Journal on advances in signal processing},
year = {2026},
month = may,
volume = {2026},
number = {1},
pages = {64},
issn = {3091-4507},
doi = {10.1186/s13634-026-01330-2},
url = {https://doi.org/10.1186/s13634-026-01330-2},
pmid = {42598465},
pmcid = {PMC13471070}
}

RIS

TY - JOUR
AU - Alqarni, Mohammad Ali
AU - Masood, Hira
AU - Khan, Hassan Aqeel
AU - Kamboh, Awais Mehmood
AU - Shafait, Saima
AU - Jaffarey, Tooba
AU - Shafait, Faisal
TI - Leednet: a lightweight network for event detection in EEG signals
T2 - Journal on advances in signal processing
J2 - J Adv Signal Process
PY - 2026
DA - 2026/05/26
VL - 2026
IS - 1
SP - 64
SN - 3091-4507
DO - 10.1186/s13634-026-01330-2
UR - https://doi.org/10.1186/s13634-026-01330-2
LA - en
ER -

CSL-JSON

{
"id": "10.1186/s13634-026-01330-2",
"type": "article-journal",
"title": "Leednet: a lightweight network for event detection in EEG signals",
"container-title": "Journal on advances in signal processing",
"author": [
{
"family": "Alqarni",
"given": "Mohammad Ali"
},
{
"family": "Masood",
"given": "Hira"
},
{
"family": "Khan",
"given": "Hassan Aqeel"
},
{
"family": "Kamboh",
"given": "Awais Mehmood"
},
{
"family": "Shafait",
"given": "Saima"
},
{
"family": "Jaffarey",
"given": "Tooba"
},
{
"family": "Shafait",
"given": "Faisal"
}
],
"container-title-short": "J Adv Signal Process",
"volume": "2026",
"issue": "1",
"page": "64",
"DOI": "10.1186/s13634-026-01330-2",
"PMID": "42598465",
"PMCID": "PMC13471070",
"ISSN": "3091-4507",
"URL": "https://doi.org/10.1186/s13634-026-01330-2",
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
26
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1038/s41598-026-68186-2 [code]
NeuroStream: spectral-spatio-temporal deep learning for visual stimulus classification from EEG.
Journal: Scientific reports
In common: PyWavelets, PyTorch, seaborn, 5 other tools, EEG, 2 references
[2] doi:10.1371/journal.pone.0347671 [code]
RMETNet: A cross-subject motor imagery EEG signal classification model based on TSLANet and riemannian geometry features.
Journal: PloS one
In common: MNE-Python, PyTorch, seaborn, 5 other tools, EEG, 2 references
[3] doi:10.3390/bios16080437 [code]
Deep Learning for Ear-EEG-Based Brain-Computer Interface: A Systematic Comparison and Design Insights.
Journal: Biosensors
In common: MNE-Python, PyTorch, scikit-learn, 3 other tools, EEG, 3 references
[4] doi:10.3390/brainsci16070680 [code]
ION-Sim: A Novel Open-Source Simulation Framework for Intraoperative Neurophysiological Monitoring.
Journal: Brain sciences
In common: PyWavelets, MNE-Python, PyTorch, 5 other tools, EEG
[5] doi:10.1002/hbm.70628 [code]
EEG Biomarkers for Affective Disorders Diagnosis: An Evaluation and Validation Study.
Journal: Human brain mapping
In common: PyWavelets, MNE-Python, PyTorch, 5 other tools, EEG
[6] doi:10.1371/journal.pone.0354510 [code]
Personalized adaptive virtual reality experience driven by electroencephalography-based pain recognition.
Journal: PloS one
In common: PyWavelets, MNE-Python, seaborn, 4 other tools, EEG, 1 reference
[7] doi:10.1038/s41746-026-02778-0 [code]
Trust-gated synthetic EEG augmentation reduces performance drops when generalizing to new patients.
Journal: NPJ digital medicine
In common: MNE-Python, PyTorch, scikit-learn, 4 other tools, EEG, 2 references
[8] doi:10.1002/hbm.70528 [code]
Explainable AI Insights Into EEG Classification and Its Alignment to Neural Correlates.
Journal: Human brain mapping
In common: MNE-Python, PyTorch, seaborn, 5 other tools, EEG, 1 reference
[9] doi:10.1117/1.nph.13.2.025001 [code]
Surface-based image reconstruction optimization for high-density functional near-infrared spectroscopy.
Journal: Neurophotonics
In common: PyWavelets, MNE-Python, seaborn, 5 other tools
[10] doi:10.1126/sciadv.aee9425 [code]
Probabilistic inference of homonymous and heteronymous recurrent inhibition in human muscles from large-scale motor neuron recordings.
Journal: Science advances
In common: PyWavelets, PyTorch, seaborn, 5 other tools

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.