OSCR

EEG and IMU Gait Signal Processing: A Comparative Assessment of the "Reza" Exponential Filter and Classical Filters.

Code ↔ Paper

2 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 2 matches
  1. [1] § 2. Materials and Methods › 2.4. Filter Designs › 2.4.2. Butterworth › EEG Configuration ↔ src/reza/__init__.py, lines 1–31 · score 0.52 · SciPy, zero phase, band pass, IIR, magnitude, filter
  2. [2] § 2. Materials and Methods › 2.4. Filter Designs › 2.4.1. Reza Filter Parameters ↔ src/reza/__init__.py, lines 1–31 · score 0.51 · Reza band pass, Reza filter, IIR, exponent, magnitude, FFT

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 · 425 lines · 13 KB · MIT · 2 matches

  1. from __future__ import annotations
  2. """
  3. Reza Filter (minimal, SciPy-like user-facing API)
  4. ------------------------------------------------
  5. Goal: users should only need:
  6. import reza
  7. # SciPy-like (preferred)
  8. y = reza.filter(x, fs=200, Wn=5, btype="low") # low-pass 5 Hz
  9. y = reza.filter(x, fs=200, Wn=10, btype="high") # high-pass 10 Hz
  10. y = reza.filter(x, fs=200, Wn=(5, 10), btype="band") # band-pass 5-10 Hz
  11. # Convenience wrappers
  12. y = reza.low(x, fs=200, fc=5)
  13. y = reza.high(x, fs=200, fc=10)
  14. y = reza.band(x, fs=200, f1=5, f2=10)
  15. Notes
  16. -----
  17. - Reza Filter is applied in the FFT domain as a zero-phase magnitude shaping curve.
  18. - All shaping parameters are internal. The decay exponent d is auto-selected and cached.
  19. - For frequency response, use reza.freqz(...). Unlike IIR filters, Reza's response
  20. depends on the effective FFT length; we choose an internal default automatically
  21. so users do not need to pass n.
  22. """
  23. import math
  24. from functools import lru_cache
  25. import numpy as np
  26. # Package version (must match installed distribution metadata)
  27. try:
  28. from importlib.metadata import version as _pkg_version # py3.8+
  29. __version__ = _pkg_version("reza-filter")
  30. except Exception:
  31. __version__ = "0.0.0"
  32. from . import _fallback
  33. try:
  34. from . import _reza_cpp as _cpp # compiled extension
  35. _HAS_CPP = True
  36. except Exception:
  37. _cpp = None
  38. _HAS_CPP = False
  39. __all__ = [
  40. # Primary (SciPy-like)
  41. "filter",
  42. "freqz",
  43. # Convenience wrappers
  44. "low",
  45. "high",
  46. "band",
  47. # Backward-compatible aliases
  48. "lowpass",
  49. "highpass",
  50. "bandpass",
  51. "lp",
  52. "hp",
  53. "bp",
  54. # Utilities
  55. "has_cpp",
  56. "__version__",
  57. ]
  58. # ---------------------------------------------------------------------
  59. # Internal defaults (NOT part of the public API)
  60. # ---------------------------------------------------------------------
  61. _C_DEFAULT = 0.9
  62. _OFFSET_DEFAULT = 1.0
  63. # Dynamic-decay search parameters (kept internal)
  64. _D_INIT = 10.0
  65. _D_INC = 5.0
  66. _D_THRESHOLD = 1e-4
  67. _D_MAX_ITER = 200
  68. _D_MAX = 1e6
  69. # Freq-response internal defaults (kept internal)
  70. _FREQZ_MIN_N = 4096
  71. _FREQZ_MAX_N = 262144
  72. _FREQZ_MIN_DF_HZ = 0.02 # do not chase absurdly fine grids by default
  73. _FREQZ_FMIN_FRAC = 1.0 / 100 # aim for ~100 points up to the smallest cutoff
  74. def has_cpp() -> bool:
  75. return _HAS_CPP
  76. def _move_axis_to_last(x: np.ndarray, axis: int) -> np.ndarray:
  77. return np.moveaxis(x, axis, -1) if axis != -1 else x
  78. def _move_axis_back(x: np.ndarray, axis: int) -> np.ndarray:
  79. return np.moveaxis(x, -1, axis) if axis != -1 else x
  80. def _apply_gain_rfft(X: np.ndarray, gain: np.ndarray) -> np.ndarray:
  81. if _HAS_CPP:
  82. return _cpp.apply_gain_rfft(X, gain)
  83. return _fallback.apply_gain_rfft(X, gain)
  84. @lru_cache(maxsize=256)
  85. def _auto_d_lowpass(fs: float, n: int, fc: float) -> float:
  86. if _HAS_CPP:
  87. return float(
  88. _cpp.auto_d_lowpass(
  89. float(fs), int(n), float(fc),
  90. float(_C_DEFAULT), float(_OFFSET_DEFAULT),
  91. float(_D_INIT), float(_D_INC), float(_D_THRESHOLD),
  92. int(_D_MAX_ITER), float(_D_MAX),
  93. )
  94. )
  95. return float(
  96. _fallback._auto_d_lowpass(
  97. float(fs), int(n), float(fc),
  98. c=float(_C_DEFAULT), offset=float(_OFFSET_DEFAULT),
  99. initial_d=float(_D_INIT), d_increment=float(_D_INC),
  100. threshold=float(_D_THRESHOLD), max_iter=int(_D_MAX_ITER), max_d=float(_D_MAX),
  101. )
  102. )
  103. @lru_cache(maxsize=256)
  104. def _auto_d_highpass(fs: float, n: int, fc: float) -> float:
  105. if _HAS_CPP:
  106. return float(
  107. _cpp.auto_d_highpass(
  108. float(fs), int(n), float(fc),
  109. float(_C_DEFAULT), float(_OFFSET_DEFAULT),
  110. float(_D_INIT), float(_D_INC), float(_D_THRESHOLD),
  111. int(_D_MAX_ITER), float(_D_MAX),
  112. )
  113. )
  114. return float(
  115. _fallback._auto_d_highpass(
  116. float(fs), int(n), float(fc),
  117. c=float(_C_DEFAULT), offset=float(_OFFSET_DEFAULT),
  118. initial_d=float(_D_INIT), d_increment=float(_D_INC),
  119. threshold=float(_D_THRESHOLD), max_iter=int(_D_MAX_ITER), max_d=float(_D_MAX),
  120. )
  121. )
  122. @lru_cache(maxsize=256)
  123. def _auto_d_bandpass(fs: float, n: int, f1: float, f2: float) -> float:
  124. if _HAS_CPP:
  125. return float(
  126. _cpp.auto_d_bandpass(
  127. float(fs), int(n), float(f1), float(f2),
  128. float(_C_DEFAULT), float(_OFFSET_DEFAULT),
  129. float(_D_INIT), float(_D_INC), float(_D_THRESHOLD),
  130. int(_D_MAX_ITER), float(_D_MAX),
  131. )
  132. )
  133. return float(
  134. _fallback._auto_d_bandpass(
  135. float(fs), int(n), float(f1), float(f2),
  136. c=float(_C_DEFAULT), offset=float(_OFFSET_DEFAULT),
  137. initial_d=float(_D_INIT), d_increment=float(_D_INC),
  138. threshold=float(_D_THRESHOLD), max_iter=int(_D_MAX_ITER), max_d=float(_D_MAX),
  139. )
  140. )
  141. @lru_cache(maxsize=256)
  142. def _gain_lowpass(fs: float, n: int, fc: float) -> np.ndarray:
  143. d = _auto_d_lowpass(fs, n, fc)
  144. if _HAS_CPP:
  145. g = _cpp.gain_lowpass(float(fs), int(n), float(fc),
  146. float(_C_DEFAULT), float(_OFFSET_DEFAULT), float(d))
  147. else:
  148. g = _fallback.calculate_gain_lowpass(float(fs), int(n), float(fc),
  149. c=float(_C_DEFAULT), offset=float(_OFFSET_DEFAULT), d=float(d))
  150. g = np.ascontiguousarray(np.asarray(g, dtype=np.float64))
  151. g.setflags(write=False)
  152. return g
  153. @lru_cache(maxsize=256)
  154. def _gain_highpass(fs: float, n: int, fc: float) -> np.ndarray:
  155. d = _auto_d_highpass(fs, n, fc)
  156. if _HAS_CPP:
  157. g = _cpp.gain_highpass(float(fs), int(n), float(fc),
  158. float(_C_DEFAULT), float(_OFFSET_DEFAULT), float(d))
  159. else:
  160. g = _fallback.calculate_gain_highpass(float(fs), int(n), float(fc),
  161. c=float(_C_DEFAULT), offset=float(_OFFSET_DEFAULT), d=float(d))
  162. g = np.ascontiguousarray(np.asarray(g, dtype=np.float64))
  163. g.setflags(write=False)
  164. return g
  165. @lru_cache(maxsize=256)
  166. def _gain_bandpass(fs: float, n: int, f1: float, f2: float) -> np.ndarray:
  167. d = _auto_d_bandpass(fs, n, f1, f2)
  168. if _HAS_CPP:
  169. g = _cpp.gain_bandpass(float(fs), int(n), float(f1), float(f2),
  170. float(_C_DEFAULT), float(_OFFSET_DEFAULT), float(d))
  171. else:
  172. g = _fallback.calculate_gain_bandpass(float(fs), int(n), float(f1), float(f2),
  173. c=float(_C_DEFAULT), offset=float(_OFFSET_DEFAULT), d=float(d))
  174. g = np.ascontiguousarray(np.asarray(g, dtype=np.float64))
  175. g.setflags(write=False)
  176. return g
  177. # ---------------------------------------------------------------------
  178. # Core filtering (kept stable; used by wrappers)
  179. # ---------------------------------------------------------------------
  180. def lowpass(data, fs: float, fc: float, axis: int = -1):
  181. x = np.asarray(data, dtype=float)
  182. x_m = _move_axis_to_last(x, axis)
  183. n = int(x_m.shape[-1])
  184. gain = _gain_lowpass(float(fs), n, float(fc))
  185. X = np.ascontiguousarray(np.fft.rfft(x_m, axis=-1).astype(np.complex128, copy=False))
  186. Y = _apply_gain_rfft(X, gain)
  187. y = np.fft.irfft(Y, n=n, axis=-1)
  188. return _move_axis_back(y, axis)
  189. def highpass(data, fs: float, fc: float, axis: int = -1):
  190. x = np.asarray(data, dtype=float)
  191. x_m = _move_axis_to_last(x, axis)
  192. n = int(x_m.shape[-1])
  193. gain = _gain_highpass(float(fs), n, float(fc))
  194. X = np.ascontiguousarray(np.fft.rfft(x_m, axis=-1).astype(np.complex128, copy=False))
  195. Y = _apply_gain_rfft(X, gain)
  196. y = np.fft.irfft(Y, n=n, axis=-1)
  197. return _move_axis_back(y, axis)
  198. def bandpass(data, fs: float, f1: float, f2: float, axis: int = -1):
  199. if float(f2) <= float(f1):
  200. raise ValueError("bandpass requires f2 > f1")
  201. x = np.asarray(data, dtype=float)
  202. x_m = _move_axis_to_last(x, axis)
  203. n = int(x_m.shape[-1])
  204. gain = _gain_bandpass(float(fs), n, float(f1), float(f2))
  205. X = np.ascontiguousarray(np.fft.rfft(x_m, axis=-1).astype(np.complex128, copy=False))
  206. Y = _apply_gain_rfft(X, gain)
  207. y = np.fft.irfft(Y, n=n, axis=-1)
  208. return _move_axis_back(y, axis=axis)
  209. # ---------------------------------------------------------------------
  210. # SciPy-like user API (preferred)
  211. # ---------------------------------------------------------------------
  212. def _normalize_btype(btype: str | None) -> str:
  213. if btype is None:
  214. return "low"
  215. b = str(btype).strip().lower()
  216. if b in ("lp", "low", "lowpass", "low-pass"):
  217. return "low"
  218. if b in ("hp", "high", "highpass", "high-pass"):
  219. return "high"
  220. if b in ("bp", "band", "bandpass", "band-pass"):
  221. return "band"
  222. raise ValueError("btype must be one of: 'low', 'high', 'band' (or lowpass/highpass/bandpass aliases)")
  223. def filter(data, fs: float, Wn=None, btype: str = "low", axis: int = -1, *,
  224. lowcut=None, highcut=None):
  225. """
  226. Filter data with a SciPy-like signature.
  227. Preferred:
  228. reza.filter(x, fs, Wn, btype="low|high|band")
  229. Backward compatibility:
  230. reza.filter(x, fs, lowcut=..., highcut=...)
  231. """
  232. # Legacy path (lowcut/highcut)
  233. if Wn is None:
  234. if lowcut is None and highcut is None:
  235. raise ValueError("Provide Wn=... (preferred) or at least one of lowcut/highcut (legacy).")
  236. if lowcut is not None and highcut is not None:
  237. return bandpass(data, fs, lowcut, highcut, axis=axis)
  238. if highcut is not None:
  239. return lowpass(data, fs, highcut, axis=axis)
  240. return highpass(data, fs, lowcut, axis=axis)
  241. bt = _normalize_btype(btype)
  242. if bt in ("low", "high") and isinstance(Wn, (tuple, list, np.ndarray)):
  243. raise ValueError("For btype='low' or 'high', Wn must be a scalar cutoff (Hz).")
  244. if bt == "band" and not isinstance(Wn, (tuple, list, np.ndarray)):
  245. raise ValueError("For btype='band', Wn must be a (low, high) tuple in Hz.")
  246. if bt == "low":
  247. return lowpass(data, fs, float(Wn), axis=axis)
  248. if bt == "high":
  249. return highpass(data, fs, float(Wn), axis=axis)
  250. # band
  251. f1, f2 = float(Wn[0]), float(Wn[1])
  252. return bandpass(data, fs, f1, f2, axis=axis)
  253. # Convenience wrappers
  254. def low(data, fs: float, fc: float, axis: int = -1):
  255. return lowpass(data, fs, fc, axis=axis)
  256. def high(data, fs: float, fc: float, axis: int = -1):
  257. return highpass(data, fs, fc, axis=axis)
  258. def band(data, fs: float, f1: float, f2: float, axis: int = -1):
  259. return bandpass(data, fs, f1, f2, axis=axis)
  260. # Backward-compatible short aliases
  261. def lp(data, fs: float, fc: float, axis: int = -1):
  262. return lowpass(data, fs, fc, axis=axis)
  263. def hp(data, fs: float, fc: float, axis: int = -1):
  264. return highpass(data, fs, fc, axis=axis)
  265. def bp(data, fs: float, f1: float, f2: float, axis: int = -1):
  266. return bandpass(data, fs, f1, f2, axis=axis)
  267. # Optional capitalized aliases (do not advertise; harmless compatibility)
  268. Low = low
  269. High = high
  270. Band = band
  271. # ---------------------------------------------------------------------
  272. # Frequency response (SciPy-like; no user-supplied n)
  273. # ---------------------------------------------------------------------
  274. def _next_pow2(n: int) -> int:
  275. if n <= 1:
  276. return 1
  277. return 1 << int(math.ceil(math.log2(n)))
  278. def _default_n_for_freqz(fs: float, Wn, btype: str) -> int:
  279. fs = float(fs)
  280. # Determine smallest relevant cutoff (Hz)
  281. if btype == "band":
  282. fmin = min(float(Wn[0]), float(Wn[1]))
  283. else:
  284. fmin = float(Wn)
  285. fmin = max(fmin, 1e-6)
  286. # Target frequency resolution
  287. target_df = max(_FREQZ_MIN_DF_HZ, _FREQZ_FMIN_FRAC * fmin)
  288. n = int(math.ceil(fs / target_df))
  289. n = _next_pow2(max(_FREQZ_MIN_N, n))
  290. n = int(min(_FREQZ_MAX_N, n))
  291. return n
  292. def freqz(*args, fs: float, worN: int = 2048, Wn=None, btype: str = "low",
  293. fc: float = None, f1: float = None, f2: float = None):
  294. """
  295. SciPy-like frequency response for Reza filter.
  296. Preferred:
  297. w_hz, H = reza.freqz(fs=200, Wn=5, btype="low", worN=2048)
  298. Backward compatibility:
  299. reza.freqz("lp", fs=..., fc=...)
  300. reza.freqz("hp", fs=..., fc=...)
  301. reza.freqz("bp", fs=..., f1=..., f2=...)
  302. """
  303. # Accept legacy positional "kind"
  304. if len(args) >= 1 and isinstance(args[0], str):
  305. btype = args[0]
  306. bt = _normalize_btype(btype)
  307. # Normalize cutoffs: prefer Wn, but accept legacy fc/f1/f2
  308. if Wn is None:
  309. if bt in ("low", "high"):
  310. if fc is None:
  311. raise ValueError("freqz requires Wn=... (preferred) or fc=... (legacy) for low/high.")
  312. Wn = float(fc)
  313. else:
  314. if f1 is None or f2 is None:
  315. raise ValueError("freqz requires Wn=(f1,f2) (preferred) or f1=... and f2=... (legacy) for band.")
  316. Wn = (float(f1), float(f2))
  317. fs = float(fs)
  318. worN = int(worN)
  319. if worN < 16:
  320. worN = 16
  321. n = _default_n_for_freqz(fs, Wn, bt)
  322. imp = np.zeros(n, dtype=float)
  323. imp[0] = 1.0
  324. if bt == "low":
  325. h = low(imp, fs=fs, fc=float(Wn))
  326. elif bt == "high":
  327. h = high(imp, fs=fs, fc=float(Wn))
  328. else:
  329. h = band(imp, fs=fs, f1=float(Wn[0]), f2=float(Wn[1]))
  330. H_full = np.fft.rfft(h)
  331. f_full = np.fft.rfftfreq(n, d=1.0 / fs)
  332. w = np.linspace(0.0, fs / 2.0, worN, endpoint=True)
  333. Hr = np.interp(w, f_full, H_full.real)
  334. Hi = np.interp(w, f_full, H_full.imag)
  335. return w, Hr + 1j * Hi

__init__.py at commit 51b2311, under MIT · at the source

Overview

  1. Ellmer College of Health Sciences, Old Dominion University, Norfolk, VA 23529, USA
  2. School of Exercise Science, Old Dominion University, Norfolk, VA 23529, USA
  3. Department of Exercise and Sport Science, University of North Carolina at Chapel Hill, Chapel Hill, NC 27599, USA
Institutions: Old Dominion University (United States); University of North Carolina at Chapel Hill (United States)
Journal: Sensors (Basel, Switzerland), volume 26, issue 5, article 1719
Dates: received 22 December 2025; accepted 9 February 2026; published online 9 March 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.3390/s26051719 · PMID 41829680 · PMCID PMC12986942 · OpenAlex W7134251995
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: EEG (modality), human (organism)
Methods: Spectral & time-frequency, Statistics, Preprocessing, Evoked potentials
Keywords: EEG filtering, IMU gait analysis, IIR filters (Butterworth, Chebyshev, elliptic), Reza filter, signal-to-noise ratio, power spectral density
MeSH: Electroencephalography*, Gait*, Signal Processing, Computer-Assisted*, Adult, Female, Humans, Male, Signal-To-Noise Ratio (* major topic)
Topic: EEG and Brain-Computer Interfaces (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Citations: not cited yet (Europe PMC); 59 references in the paper

Abstract

Noise degrades both EEG and gait signals, and classical IIR filters (Butterworth, Chebyshev, elliptic) involve trade-offs between passband flatness, ripple, and roll-off. This study compared a novel exponential “Reza” filter with these designs for neural and locomotor data. We analyzed an open-source mobile brain–body imaging dataset with EEG and gait data from 49 healthy adults (EEG: 256-channel, 512 Hz; IMUs: six APDM Opals, 128 Hz). EEG channels were grand-averaged and band-pass filtered at 0.5–50 Hz, while IMU axes were averaged and band-pass filtered at 0.5–5 Hz. The outcomes were signal-to-noise ratio SNR (dB) and band-integrated Welch PSD (EEG:0.5–50 Hz; IMU:0.5–5 Hz). Repeated-measures ANOVAs tested the effect of filter types (Butterworth, Chebyshev I, elliptic, Reza) with Bonferroni-adjusted post hoc tests for the six pairwise filter comparisons (αadj = 0.0083). We reported partial eta-squared (ηp2) as the ANOVA effect size. For EEG, PSD did not differ among filters (p = 0.146), whereas SNR differed strongly (p<0.001): Chebyshev and elliptic yielded the highest mean SNR and did not differ from each other, while both exceeded Butterworth, Reza was the lowest. For IMU, both SNR (p< 0.001) and PSD (p< 0.001) differed: Reza produced the highest mean SNR (significantly exceeding elliptic and Chebyshev), while Butterworth exceeded Chebyshev; meanwhile, IMU PSD showed a clear ordering with Reza retaining the most motion-band power, followed by Butterworth, then Chebyshev, with elliptic retaining the least. These results showed that filter choice materially shapes EEG and gait outcomes. For EEG, Chebyshev maximized SNR, while elliptic and Reza maintained comparable fidelity. For IMU gait signals, Reza matched Butterworth for denoising and preserved more signal power. Therefore, filter choice should be guided by the target outcome (SNR vs. band power) rather than a single default design.

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 2 matches between paragraphs and lines of code.

Rezapousti/Reza-Filter

License: MIT
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: 51b23114db5e227d7d285fd85a09d9a944931865, 26 January 2026
Languages: Python (1066), C++ (1)
Size: 1,278 files, 1,067 scripts
Software Heritage: not archived
Found in: “Supplementary Materials”
Holds: README, license file, environment (pyproject.toml), tests, continuous integration
Not found: CITATION.cff, documentation
Tools: NumPy (6 files)
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
1,069 files

The paper's code and data availability statement is in the Data section.

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;
  • 1,067 scripts, each with its path and the digest of its content;
  • 2 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

Datasets cited

Data Availability Statement

The human subjects data used in this analysis are available via the public dataset published by Hanada, Kalabic, and Ferris (2024) [41]. The full Reza-Filter repository (including high-pass, low-pass, and band-pass implementations, example scripts, and analysis utilities) is available at: https://github.com/Rezapousti/Reza-Filter.git, accessed on 9 March 2026.

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, 30 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 4 authors, 8 keywords, 8 MeSH terms, 48 references.

Cite

This paper

Pousti, R., Russell, D. M., Monroe, D. C., & Rhea, C. K. (2026). EEG and IMU Gait Signal Processing: A Comparative Assessment of the "Reza" Exponential Filter and Classical Filters. Sensors (Basel, Switzerland), 26(5), 1719. https://doi.org/10.3390/s26051719

BibTeX

@article{pousti2026eeg,
author = {Pousti, Reza and Russell, Daniel M and Monroe, Derek C and Rhea, Christopher K},
title = {{EEG and IMU Gait Signal Processing: A Comparative Assessment of the "Reza" Exponential Filter and Classical Filters}},
journal = {Sensors (Basel, Switzerland)},
year = {2026},
month = mar,
volume = {26},
number = {5},
pages = {1719},
publisher = {Multidisciplinary Digital Publishing Institute (MDPI)},
issn = {1424-8220},
doi = {10.3390/s26051719},
url = {https://doi.org/10.3390/s26051719},
pmid = {41829680},
pmcid = {PMC12986942}
}

RIS

TY - JOUR
AU - Pousti, Reza
AU - Russell, Daniel M
AU - Monroe, Derek C
AU - Rhea, Christopher K
TI - EEG and IMU Gait Signal Processing: A Comparative Assessment of the "Reza" Exponential Filter and Classical Filters
T2 - Sensors (Basel, Switzerland)
J2 - Sensors (Basel)
PY - 2026
DA - 2026/03/09
VL - 26
IS - 5
SP - 1719
SN - 1424-8220
PB - Multidisciplinary Digital Publishing Institute (MDPI)
DO - 10.3390/s26051719
UR - https://doi.org/10.3390/s26051719
LA - en
ER -

CSL-JSON

{
"id": "10.3390/s26051719",
"type": "article-journal",
"title": "EEG and IMU Gait Signal Processing: A Comparative Assessment of the \"Reza\" Exponential Filter and Classical Filters",
"container-title": "Sensors (Basel, Switzerland)",
"author": [
{
"family": "Pousti",
"given": "Reza"
},
{
"family": "Russell",
"given": "Daniel M"
},
{
"family": "Monroe",
"given": "Derek C"
},
{
"family": "Rhea",
"given": "Christopher K"
}
],
"container-title-short": "Sensors (Basel)",
"volume": "26",
"issue": "5",
"page": "1719",
"DOI": "10.3390/s26051719",
"PMID": "41829680",
"PMCID": "PMC12986942",
"ISSN": "1424-8220",
"publisher": "Multidisciplinary Digital Publishing Institute (MDPI)",
"URL": "https://doi.org/10.3390/s26051719",
"language": "en",
"issued": {
"date-parts": [
[
2026,
3,
9
]
]
}
}

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.3390/s26082431
Missing Data Gap Imputation Methods in Electroencephalogram (EEG) Signals: A Systematic Scoping Review.
Journal: Sensors (Basel, Switzerland)
In common: EEG, 3 references
[2] doi:10.1038/s41598-026-56070-y [code]
SSDLabeler: realistic semi-synthetic data generation for multi-label artifact classification in EEG.
Journal: Scientific reports
In common: NumPy, EEG, 2 references
[3] doi:10.1016/j.ibneur.2026.05.013 [code]
Anticipatory slow potentials before auditory feedback show posterior predominance but limited condition effects in speech-in-noise.
Journal: IBRO neuroscience reports
In common: NumPy, EEG, 1 reference
[4] doi:10.1038/s41467-026-73553-8 [code]
Universal rhythmic architecture uncovers two modes of neural dynamics.
Journal: Nature communications
In common: NumPy, EEG, 1 reference
[5] doi:10.1111/psyp.70297 [code]
Heartbeat-Evoked Responses in M/EEG: A Systematic Review of Methods With Suggestions for Analysis and Reporting.
Journal: Psychophysiology
In common: NumPy, EEG, 1 reference
[6] doi:10.1111/psyp.70352 [code]
Preprocessing on the Go: Practices in Gait-Related Mobile EEG.
Journal: Psychophysiology
In common: NumPy, EEG, 1 reference
[7] doi:10.1371/journal.pone.0354510 [code]
Personalized adaptive virtual reality experience driven by electroencephalography-based pain recognition.
Journal: PloS one
In common: NumPy, EEG, 1 reference
[8] doi:10.3389/fnins.2026.1907378 [code]
Explainable machine-learning integration of pre-task and preparatory EEG: revealing complementary predictive information for expert action reliability.
Journal: Frontiers in neuroscience
In common: NumPy, EEG, 1 reference
[9] doi:10.1371/journal.pone.0351872 [code]
Decoding visual object recognition from EEG signals.
Journal: PloS one
In common: NumPy, EEG, 1 reference
[10] doi:10.1093/braincomms/fcag351 [code]
Time-resolved aperiodic dynamics in event segmentation in attention-deficit/hyperactivity disorder.
Journal: Brain communications
In common: NumPy, EEG, 1 reference

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.