cardio_rs/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(feature = "std"), no_std)]
3
4pub mod metrics;
5pub use metrics::{frequency_domain, geometric_domain, non_linear, time_domain};
6
7pub mod utils;
8#[cfg(feature = "std")]
9pub use utils::io_utils;
10pub use utils::processing_utils;
11
12pub mod analysis;
13pub use analysis::{live_analysis, windows_analysis};
14
15/// A struct that contains the Heart Rate Variability (HRV) metrics,
16/// divided into time-domain, frequency-domain, and geometric-domain metrics.
17#[derive(Debug, PartialEq, Clone, Copy, Default)]
18pub struct HrvMetrics<T> {
19    /// Time-domain HRV metrics (`TimeMetrics<T>`).
20    pub time: crate::time_domain::TimeMetrics<T>,
21    /// Frequency-domain HRV metrics (`FrequencyMetrics<T>`).
22    pub frequency: crate::frequency_domain::FrequencyMetrics<T>,
23    /// Geometric-domain HRV metrics (`GeometricMetrics<T>`).
24    pub geometric: crate::geometric_domain::GeometricMetrics<T>,
25    /// Non-linear HRV metrics (`NonLinearMetrics<T>`).
26    pub non_linear: crate::non_linear::NonLinearMetrics<T>,
27}
28
29/// A macro that performs a standard HRV analysis on a given input, returning the HRV metrics
30/// in time-domain, frequency-domain, and geometric-domain categories.
31///
32/// This macro computes HRV metrics using a series of transformations:
33/// 1. It processes RR intervals by detecting ectopic beats and outliers.
34/// 2. Computes time-domain metrics, frequency-domain metrics, and geometric-domain metrics.
35///
36/// The macro accepts two forms:
37///
38/// - **Form 1**: Takes a reference to an object containing RR intervals (e.g., `RRIntervals`).
39///
40/// ```rust
41/// use cardio_rs::standard_analysis;
42/// use cardio_rs::HrvMetrics;
43///
44/// let rr_intervals = vec![800., 810., 780., 850., 900.];
45/// let hrv_metrics = standard_analysis!(rr_intervals);
46/// ```
47///
48/// - **Form 2**: Takes a file path, signal, and sample rate to build a `Data` object and then runs the analysis on that data.
49///
50/// ```rust
51/// #[cfg(feature = "std")]
52/// {
53/// use cardio_rs::standard_analysis;
54/// use cardio_rs::HrvMetrics;
55///
56/// let path = "tests/ecg.csv";
57/// let signal = "ECG_Raw";
58/// let rate = 1000.;
59/// let hrv_metrics = cardio_rs::standard_analysis!(path, signal, rate);
60/// }
61/// ```
62/// Where `path` is the file path to the data, `signal` is the name of the signal, and `rate`
63/// is the sample rate of the signal.
64///
65/// The macro relies on the following modules automatically imported for computing HRV metrics:
66/// - `cardio_rs::frequency_domain::FrequencyMetrics`
67/// - `cardio_rs::geometric_domain::GeometricMetrics`
68/// - `cardio_rs::time_domain::TimeMetrics`
69/// - `cardio_rs::processing_utils::{DetectOutliers, EctopicMethod, RRIntervals}`
70/// - `cardio_rs::io_utils::{Data, DataBuilder}`
71#[macro_export]
72macro_rules! standard_analysis {
73    ( $x:expr ) => {{
74        use cardio_rs::{
75            frequency_domain::FrequencyMetrics,
76            geometric_domain::GeometricMetrics,
77            non_linear::NonLinearMetrics,
78            processing_utils::{DetectOutliers, EctopicMethod, RRIntervals},
79            time_domain::TimeMetrics,
80        };
81        let mut rr_intervals = RRIntervals::new($x);
82        rr_intervals.detect_ectopics(EctopicMethod::Karlsson);
83        rr_intervals.detect_outliers(&300., &2_000.);
84        rr_intervals.remove_outliers_ectopics();
85
86        let time = TimeMetrics::compute(rr_intervals.as_slice());
87        let frequency = FrequencyMetrics::compute(rr_intervals.as_slice(), 4.);
88        let geometric = GeometricMetrics::compute(rr_intervals.as_slice());
89        let non_linear = NonLinearMetrics::compute_default(rr_intervals.as_slice());
90
91        HrvMetrics {
92            time,
93            frequency,
94            geometric,
95            non_linear,
96        }
97    }};
98    ( $path:expr, $signal:expr, $rate:expr ) => {{
99        #[cfg(feature = "std")]
100        {
101            use cardio_rs::io_utils::{Data, DataBuilder};
102            let data = DataBuilder::new($path.into(), $signal.into())
103                .with_rate($rate)
104                .build()
105                .unwrap();
106            standard_analysis!(data.get_rr())
107        }
108    }};
109}