Giter Club home page Giter Club logo

two_moving_average_qrs_detector's Introduction

A two moving average qrs detector with optional temporal correction

  • References

    • Elgendi, Mohamed; Eskofier, Björn; Dokos, Socrates; Abbott, Derek; Amaral, Luís A. Nunes. (2014): Revisiting QRS Detection Methodologies for Portable, Wearable, Battery-Operated, and Wireless ECG Systems. In PLoS ONE 9 (1), e84018. DOI: 10.1371/journal.pone.0084018.
    • Elgendi, Mohamed; Jonkman, Mirjam; Boer, Friso de (2009): Improved QRS Detection Algorithm using Dynamic Thresholds. In International Journal of Hybrid Information Technology 2, pp. 65–80.
    • Elgendi, Mohamed; Jonkman, Mirjam; DeBoer, Friso (Eds.) (2010): Frequency Bands Effects on QRS Detection. International Conference on Bio-inspired Systems and Signal Processing.
    • Elgendi, Mohamed; Talkachova, Alena (2013): Fast QRS Detection with an Optimized Knowledge-Based Method. Evaluation on 11 Standard ECG Databases. In PLoS ONE 8 (9), e73557. DOI: 10.1371/journal.pone.0073557.
    • Gradl, Stefan; Leutheuser, Heike; Elgendi, Mohamed; Lang, Nadine; Eskofier, Bjoern M. (2015): Temporal correction of detected R-peaks in ECG signals. A crucial step to improve QRS detection algorithms. In Annual International Conference of the IEEE Engineering in Medicine and Biology Society. IEEE Engineering in Medicine and Biology Society. Annual International Conference 2015, pp. 522–525. DOI: 10.1109/embc.2015.7318414.
    • Porr, Bernd; Howell, Luis (2019): R-peak detector stress test with a new noisy ECG database reveals significant performance differences amongst popular detectors: Cold Spring Harbor Laboratory.

Implementation details

  • qrs_detector_2ma.r and qrs_detector_2ma_mod.r both return a data table containing the input signal, all intermediate calculations including filtered and squared signal, windows and blocks along with detected qrs (loc).
  • One additional column (loc_sr) is reported if the user needs slackness reduction.
  • The modified version (qrs_detector_2ma_mod.r) attempts to detect the very first and very last beats which are missed by design in the original version. The implementation of slackness reduction for these marginal peaks was found effective in most cases but though I am not saying it is 100% safe.
  • Two dependencies only: packages gsignal (butter() & filtfilt()) and data.table (fread(), data.table(), fifelse(), rleid(), frollingmeans() & foverlaps() + faster computation times) are required.
  • No for-loops are being used.

Validation against the Glasgow University Database (GUDB)

High precision ECG Database with annotated R peaks, recorded and filmed under realistic conditions (https://researchdata.gla.ac.uk/716/ and https://github.com/berndporr/ECG-GUDB) Howell, L. and Porr, B. (2018) High precision ECG Database with annotated R peaks, recorded and filmed under realistic conditions. University of Glascow Datacite DOI: 10.5525/gla.researchdata.716

  • All recordings with annotations were tested: 123 for the chest strap and 106 for the loose cable setup.

  • Without slackness correction

    • With zero tolerance
task channel TPR F1
hand_bike cable 0.3458 0.3454
hand_bike cheststrap 0.3253 0.3236
jogging cable 0.2661 0.2692
jogging cheststrap 0.2797 0.2822
maths cable 0.3487 0.3484
maths cheststrap 0.4023 0.4022
sitting cable 0.3394 0.3393
sitting cheststrap 0.3922 0.3924
walking cable 0.2908 0.2905
walking cheststrap 0.3505 0.3504
  • Using a 40 ms tolerance window

According to Porr & Howell, the default tolerance is a tenth of the sampling rate as may be read in the Physionet comparison algorithms. For a 250 Hz sampling rate, a tolerance of 40 ms corresponds to (40e-3) * 250 = 10 samples. The detection is said to be right shifted (Porr & Howell 2019) but our sample plots show some cases of left-shifted detection. So, we used a tolerance interval which is symmetrical around the reference annotation. The WFBD application guide (WAG.pdf) says that the match window specifies the maximum absolute difference in annotation times that is permitted for matching annotations. Its default value used by the bxb function is 0.15 seconds which is way too large.

task channel TPR F1
hand_bike cable 0.9949 0.9933
hand_bike cheststrap 0.9846 0.9788
jogging cable 0.9433 0.9519
jogging cheststrap 0.9569 0.9628
maths cable 0.9996 0.9988
maths cheststrap 0.9665 0.9664
sitting cable 1 0.9995
sitting cheststrap 0.9678 0.9679
walking cable 0.9869 0.9852
walking cheststrap 0.9686 0.9681
  • Using slackness correction

    • With zero tolerance
task channel TPR F1
hand_bike cable 0.9926 0.9911
hand_bike cheststrap 0.9832 0.9774
jogging cable 0.9381 0.9466
jogging cheststrap 0.9529 0.9587
maths cable 0.9994 0.9986
maths cheststrap 0.9665 0.9664
sitting cable 1 0.9995
sitting cheststrap 0.9668 0.9669
walking cable 0.9851 0.9835
walking cheststrap 0.9678 0.9673
  • Using a 40 ms tolerance window
task channel TPR F1
hand_bike cable 0.9949 0.9933
hand_bike cheststrap 0.9846 0.9788
jogging cable 0.9433 0.9519
jogging cheststrap 0.9569 0.9628
maths cable 0.9996 0.9988
maths cheststrap 0.9665 0.9664
sitting cable 1 0.9995
sitting cheststrap 0.9678 0.9679
walking cable 0.9869 0.9852
walking cheststrap 0.9686 0.9681
  • Compare with the detect_rpeaks() function from the rsleep package

    • With zero tolerance
task channel TPR F1
hand_bike cable 0.1519 0.1516
hand_bike cheststrap 0.2479 0.2444
jogging cable 0.06779 0.07407
jogging cheststrap 0.1936 0.1999
maths cable 0.1692 0.1691
maths cheststrap 0.3334 0.3272
sitting cable 0.1922 0.1923
sitting cheststrap 0.371 0.3538
walking cable 0.07615 0.07591
walking cheststrap 0.3008 0.2974
  • Using a 40 ms tolerance window
task channel TPR F1
hand_bike cable 0.9903 0.9905
hand_bike cheststrap 0.9787 0.9552
jogging cable 0.8355 0.8799
jogging cheststrap 0.8662 0.9047
maths cable 0.9989 0.9985
maths cheststrap 0.9852 0.9662
sitting cable 0.9981 0.9985
sitting cheststrap 0.9952 0.9539
walking cable 0.9897 0.99
walking cheststrap 0.9933 0.9715
> library(rbenchmark)
> benchmark(
>     dtbr <- apply(sample_list, 1, valid_fn, freq_sampling = 250L,  slred = TRUE)
> )
> test replications  elapsed  relative  user.self  sys.self  user.child  sys.child
>             100   776.02         1     299.06     27.72          NA         NA

plot1 rightend

plot2 detail

two_moving_average_qrs_detector's People

Contributors

liegepr avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.