Skip to content

Instantly share code, notes, and snippets.

@JSH32
Last active December 3, 2023 05:05
Show Gist options
  • Save JSH32/0470b722376c0ab2563153c731779e06 to your computer and use it in GitHub Desktop.
Save JSH32/0470b722376c0ab2563153c731779e06 to your computer and use it in GitHub Desktop.
EKG R-Peak detection algorithm (Pan–Tompkins algorithm)
We can make this file beautiful and searchable if this error is corrected: No commas found in this CSV file in line 0.
hart
530
518
506
494
483
472
462
454
446
440
434
430
428
430
430
432
436
439
444
450
454
459
465
470
475
481
487
490
494
497
500
502
504
505
507
506
504
504
503
502
500
499
498
496
495
493
491
488
488
487
490
491
500
515
538
567
603
640
677
714
745
772
788
795
795
783
765
740
712
677
641
605
568
535
503
474
450
430
414
401
393
388
385
385
388
393
401
412
426
440
455
473
491
509
523
537
549
558
564
565
565
561
556
548
540
531
519
508
497
486
475
465
457
450
444
438
435
432
431
431
432
434
438
441
445
450
454
460
466
471
477
483
487
491
493
496
500
501
502
504
505
504
503
502
501
499
498
496
495
492
492
490
490
490
497
510
530
559
593
630
667
703
735
759
774
782
781
771
753
728
700
668
632
597
562
528
497
470
446
426
411
399
389
385
382
383
386
391
398
407
420
433
450
469
487
504
521
537
550
560
569
573
571
569
563
556
544
533
521
509
496
485
475
466
456
449
442
436
433
430
428
429
428
431
436
441
447
452
457
462
466
471
478
483
487
491
494
497
499
501
503
504
505
504
504
503
501
500
498
497
496
498
502
512
530
554
585
618
651
684
715
739
756
767
768
762
749
728
704
673
641
608
574
540
509
480
455
433
416
403
391
385
379
378
378
382
390
399
413
428
446
464
482
501
521
537
550
562
569
574
574
572
567
559
548
537
523
510
496
485
474
463
452
445
438
433
431
428
429
428
430
433
436
440
445
450
455
462
468
474
481
486
490
496
500
504
506
508
508
508
508
509
507
505
503
499
498
497
501
508
520
542
570
605
642
679
714
745
768
785
794
793
783
766
744
715
683
647
613
578
544
513
485
460
441
425
413
403
399
396
395
397
402
409
419
428
441
455
470
484
500
513
527
536
544
549
550
551
548
543
537
529
521
511
501
489
481
471
463
455
448
444
439
437
435
432
433
433
436
439
443
448
452
457
462
467
473
477
482
487
491
494
497
498
499
500
500
499
500
498
498
497
495
494
492
491
490
489
492
500
515
538
569
604
643
681
716
747
770
785
790
788
777
758
734
704
671
636
601
567
533
503
476
453
435
419
409
401
397
395
395
397
402
409
418
429
443
458
473
489
504
519
532
543
549
554
556
553
550
544
537
527
517
506
496
485
475
467
458
451
445
440
437
436
435
436
437
438
441
444
447
452
457
462
467
471
477
482
485
489
493
497
500
501
502
503
502
502
501
500
499
498
497
496
494
493
491
488
487
484
483
482
481
486
493
509
532
565
602
641
682
720
753
777
794
802
800
789
770
745
714
680
643
607
572
537
505
477
454
433
417
407
399
393
392
391
394
398
405
416
428
442
458
475
492
507
521
536
545
552
557
561
560
556
549
541
532
520
510
498
487
477
467
458
450
443
438
435
433
432
431
432
433
437
441
446
450
455
462
467
472
479
483
488
492
496
498
499
500
500
500
500
498
498
497
496
495
493
494
493
491
492
491
490
490
488
486
482
480
479
477
479
482
491
506
532
565
605
645
687
726
759
786
803
810
809
797
777
751
720
682
645
605
567
531
498
471
446
426
411
400
390
386
383
385
387
393
401
413
426
440
457
475
491
509
523
539
550
557
562
563
560
556
550
542
531
519
507
496
484
473
464
456
448
441
436
433
430
429
429
429
431
434
439
444
449
455
461
467
473
479
486
490
492
496
498
499
501
502
502
501
501
500
499
497
495
494
491
491
489
492
498
509
529
555
589
627
664
701
733
759
778
787
788
781
764
743
713
679
644
607
570
535
502
473
446
425
407
394
384
377
374
373
376
381
387
397
410
426
444
461
480
499
517
532
544
555
562
565
566
565
562
554
544
533
521
507
493
482
470
459
449
443
435
429
424
423
423
421
425
427
431
435
441
447
452
460
467
472
479
484
487
491
495
498
500
503
503
505
506
507
509
515
526
543
568
597
631
665
698
727
750
767
773
773
764
747
724
695
662
627
591
556
523
491
463
439
418
401
389
379
372
366
366
370
375
384
396
411
429
449
469
492
513
533
550
564
574
581
584
583
579
572
561
548
535
519
505
491
476
464
454
446
436
430
426
421
419
420
421
424
427
432
440
445
451
458
465
471
477
483
488
492
496
499
500
502
503
506
507
508
516
529
551
578
612
650
688
725
760
789
809
819
822
815
799
776
748
714
677
637
599
562
524
493
464
442
422
408
399
391
387
385
386
390
396
404
415
430
444
460
478
495
510
524
537
547
552
558
559
557
553
547
539
530
518
505
495
483
472
462
453
444
437
431
428
424
424
425
426
429
431
436
440
444
450
457
464
471
476
484
487
491
494
497
499
500
500
500
498
497
496
496
493
494
495
499
511
532
560
597
637
679
719
756
788
811
827
831
826
810
789
759
725
687
648
607
570
535
503
476
452
434
419
410
401
397
394
393
395
400
407
416
429
442
458
475
491
507
522
533
543
549
551
550
547
542
534
523
514
502
491
481
470
461
453
445
441
437
433
430
429
429
428
428
430
432
436
440
445
450
456
462
469
473
477
481
487
489
492
494
496
496
496
496
497
494
493
492
490
488
488
486
484
483
480
478
477
476
474
473
472
471
474
479
489
507
535
570
613
656
702
745
783
813
833
843
843
831
812
784
750
711
671
629
586
549
513
482
455
433
417
404
395
389
385
385
388
394
400
412
426
441
459
476
492
510
526
538
548
556
559
560
556
552
543
535
523
512
501
488
476
466
455
447
438
433
428
424
423
422
423
425
427
430
433
437
443
449
456
460
465
471
474
478
484
488
491
493
496
496
496
497
496
496
495
493
492
490
486
485
484
482
480
478
476
475
473
473
473
471
469
470
469
468
470
471
472
474
479
486
496
514
542
577
619
664
711
754
793
822
844
854
851
839
817
789
753
712
668
626
583
541
504
471
442
419
402
388
380
372
371
371
375
382
391
404
418
435
454
473
493
512
530
545
556
565
569
571
567
562
555
546
534
522
509
496
483
471
460
450
440
433
426
421
419
418
418
419
421
426
430
434
441
446
452
457
463
468
474
478
482
487
490
494
496
499
500
500
500
500
499
496
495
493
491
488
486
485
483
481
479
478
476
475
473
473
472
470
469
469
471
472
479
491
511
538
574
614
656
697
736
768
793
806
812
807
791
770
741
707
670
631
592
553
518
485
455
429
408
392
378
368
362
359
359
362
370
382
395
413
433
455
478
500
521
541
557
569
578
583
585
582
575
566
556
542
531
517
501
487
473
460
448
440
432
426
422
418
417
417
419
422
427
430
436
442
449
455
463
470
477
482
486
490
493
496
500
502
504
505
504
505
505
503
501
499
497
494
491
488
485
482
481
480
483
490
504
527
556
590
626
666
702
734
760
777
786
786
779
763
740
711
680
644
608
572
539
507
478
453
433
418
404
395
389
383
383
384
387
394
404
417
433
449
468
487
505
522
536
547
556
561
564
562
559
552
543
534
524
512
499
488
474
463
453
445
436
431
426
426
424
424
425
427
427
431
436
442
448
453
461
467
471
476
482
486
489
492
495
498
499
500
500
500
500
498
498
497
495
494
493
490
488
487
485
483
483
483
485
493
506
527
557
591
631
671
710
746
773
793
803
804
797
783
760
731
698
663
625
590
554
522
493
468
448
432
419
408
403
399
397
398
402
407
415
425
437
451
465
481
496
510
522
533
541
547
550
551
549
544
538
531
522
511
500
491
481
470
461
453
447
441
436
433
432
433
432
435
437
438
442
445
449
454
457
463
467
471
474
479
482
486
488
490
492
493
494
495
495
495
495
496
496
494
495
495
493
492
490
489
488
486
485
484
484
488
498
516
539
572
607
647
684
719
750
773
787
792
790
777
757
732
700
666
629
594
557
525
494
467
445
427
412
402
397
394
393
395
399
404
412
422
434
448
465
483
499
515
529
540
549
557
562
563
562
558
553
544
534
523
511
500
487
476
466
457
448
440
435
431
426
425
425
427
429
432
436
441
444
451
456
462
468
474
479
482
485
489
493
494
496
497
499
500
499
499
498
497
498
496
496
494
492
489
486
484
481
479
478
478
481
489
505
528
558
594
630
668
701
730
752
767
772
768
757
736
712
683
650
615
581
546
514
484
457
434
414
398
387
379
373
371
370
372
377
386
399
415
434
454
477
498
518
536
553
565
573
579
581
578
574
566
557
544
531
518
505
490
478
467
455
447
438
434
429
426
424
425
427
429
431
434
440
443
448
455
462
468
473
479
483
486
491
494
496
500
505
507
508
508
508
506
504
504
506
512
525
545
573
604
638
675
709
739
762
779
787
785
776
759
736
707
675
641
606
572
540
510
482
457
436
420
408
398
391
387
385
386
389
396
406
419
433
451
470
487
506
525
539
552
561
565
568
567
564
559
551
541
530
518
506
493
480
468
459
450
444
438
433
428
426
424
425
427
428
432
435
441
446
452
457
463
468
474
478
484
489
493
496
500
501
502
501
501
498
496
495
494
492
491
494
501
515
538
569
606
646
686
725
761
790
810
822
823
815
798
774
743
708
671
631
595
557
523
494
467
446
429
418
410
404
402
401
402
405
411
419
429
442
455
471
485
500
514
526
537
544
548
551
551
548
544
539
530
521
512
503
494
483
474
465
456
448
442
436
433
430
428
427
427
428
430
434
438
441
446
451
456
461
467
471
475
481
485
487
489
493
493
493
494
494
493
494
494
493
493
491
489
487
485
482
480
479
480
484
497
515
542
576
616
658
699
740
774
801
820
828
825
815
794
769
737
702
664
625
586
548
513
482
458
437
421
407
399
394
389
387
389
393
398
408
421
434
450
467
485
502
517
530
540
549
553
556
555
552
546
539
530
520
509
498
486
476
464
456
447
440
434
430
426
424
423
424
425
429
432
438
443
447
451
456
461
465
469
473
477
480
483
486
489
490
492
495
495
495
494
492
491
488
489
488
487
485
484
483
481
481
480
476
475
473
474
475
478
488
503
526
558
596
637
678
716
752
779
798
807
807
798
779
755
725
689
652
614
576
538
504
473
447
425
407
393
384
377
373
372
374
379
388
400
415
433
453
474
495
515
532
548
560
569
574
575
574
569
561
553
542
530
516
503
490
478
465
455
444
436
430
426
422
420
421
423
424
428
432
436
442
448
454
460
464
471
476
482
486
492
494
498
500
501
503
503
502
502
501
499
498
496
493
491
488
488
486
486
487
495
508
528
555
586
623
659
693
726
753
772
784
786
780
765
744
719
687
654
619
584
550
516
488
463
440
421
406
397
390
386
384
385
387
393
402
415
431
448
467
488
507
524
541
553
562
568
571
570
565
560
551
542
530
516
502
488
476
465
455
447
438
431
426
423
422
421
422
423
426
431
436
441
448
453
459
465
472
479
484
488
493
498
502
503
504
506
506
505
503
501
499
498
496
494
490
490
493
500
515
536
566
603
641
681
721
758
786
809
822
824
815
799
777
748
715
679
642
603
566
532
503
477
454
437
425
415
409
404
404
402
406
410
417
426
438
452
466
479
494
508
521
529
538
544
547
548
546
543
536
529
519
509
500
490
481
472
464
456
449
443
437
433
430
428
427
425
427
429
431
435
440
444
448
452
459
464
469
474
479
482
485
489
491
492
493
494
import matplotlib.pyplot as plt
import pandas as pd
from scipy.signal import butter, lfilter
def bandpass_filter(signal, lowcut, highcut, fs, order=5):
# Bandpass filter to filter out noise outside of range.
nyq = 0.5 * fs
low = lowcut / nyq
high = highcut / nyq
b, a = butter(order, [low, high], btype='band')
filtered_signal = lfilter(b, a, signal)
return filtered_signal
def integration(data, N):
# Average over the squared data of N points.
# This is done to smooth the data.
integrated = []
for i in range(len(data) - N):
integrated.append(sum(data[i:i+N]))
return integrated
def peak_finding(integrated, limit):
# If points on both sides have lower values then this point is a peak.
peaks = []
for i in range(1, len(integrated) - 1):
if integrated[i] > limit and integrated[i-1] < integrated[i] > integrated[i+1]:
peaks.append(i)
return peaks
def R_correction(signal, peaks):
peaks_corrected = []
for peak in peaks:
cnt = peak
if cnt - 1 < 0 or cnt + 1 >= len(signal):
continue
# If the signal at the current peak index is less than the signal at the previous index,
# iterate backwards until the current signal is greater than the signal at the previous index
while signal[cnt] < signal[cnt - 1] and cnt > 0:
cnt -= 1
# If the signal at the current peak index is less than the signal at the next index,
# iterate forward until the current signal is greater than the signal at the next index
while signal[cnt] < signal[cnt + 1] and cnt < len(signal) - 1:
cnt += 1
peaks_corrected.append(cnt)
return peaks_corrected
signal = pd.read_csv('data.csv')['hart'].values
# Filter outside of EKG frequency range of 0.05Hz-100Hz
filtered_data = bandpass_filter(signal, .6, 50, 1000)
derivative_data = [filtered_data[i+1] - filtered_data[i] for i in range(len(filtered_data)-1)]
# Make values positive and changes larger for emphasis.
squared_data = [i ** 2 for i in derivative_data]
# Moving window integration
integrated_data = integration(squared_data, 30)
# Set limit of 50% of the highest value for peak finding
limit = 0.5 * max(integrated_data)
peak_indices = peak_finding(integrated_data, limit)
corrected_peaks = R_correction(signal, peak_indices)
plt.plot(signal, label='EKG Signal')
plt.scatter(corrected_peaks, [signal[i] for i in corrected_peaks], color='red', label='R-peaks')
plt.xlabel('Time')
plt.ylabel('Amplitude')
plt.legend()
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment