Heart Rate Variability Visualization

HeartRateLab provides 18 visualization functions for analysis, model comparison, and normative reference: static Plots.jl figures by default, upgrading to interactive GLMakie figures when GLMakie is loaded.

Analysis Plots

plotibiseries

Time series visualization of inter-beat-intervals with statistical overlays.

using HeartRateLab, GLMakie

ibis = read_txt("data.txt")
fig = plot_ibi_series(ibis; title="IBI Time Series")
display(fig)

Features:

  • Line plot of IBI values
  • Mean line (red dashed)
  • ±1 standard deviation envelope (gray band)
  • Clear axis labels and legend

Use cases:

  • Quick visual inspection of IBI trends
  • Identify periods of high/low variability
  • Detect anomalies or artifacts

plot_poincare

Poincaré scatter plot showing beat-to-beat correlation and variability structure.

fig = plot_poincare(ibis; title="Poincaré Plot")
display(fig)

Features:

  • Scatter plot: IBI[n] vs IBI[n+1]
  • Mean point marked with ⊕
  • Identity line (reference)
  • Symmetric aspect ratio for clarity

Interpretation:

  • Tight cluster → Low HRV (regular beats)
  • Wide distribution → High HRV (variable beats)
  • Horizontal/vertical spread → Different variability types

plot_spectrum

Frequency domain power spectral density with HRV frequency bands.

fig = plot_spectrum(ibis; fs=1.0, title="HRV Power Spectrum")
display(fig)

Features:

  • Welch periodogram with log scales
  • VLF band (0.003–0.04 Hz) - Red shading
  • LF band (0.04-0.15 Hz) - Green shading
  • HF band (0.15-0.4 Hz) - Blue shading

Interpretation:

  • VLF Power - Very low frequency (thermoregulation, long-term variability)
  • LF Power - Low frequency (sympathetic + parasympathetic)
  • HF Power - High frequency (parasympathetic/respiratory)
  • LF/HF Ratio - Sympathovagal balance indicator

Comparison Plots

plot_comparison

Multi-panel comparison of real vs synthetic IBI data across multiple perspectives.

using HeartRateLab, DifferentialEquations, GLMakie

ibis_real = read_txt("data.txt")
lif = LIF()
result = fit(lif, ibis_real; method=:gradient)
ibis_synthetic = simulate(result.model, result.params, length(ibis_real))

fig = plot_comparison(ibis_real, ibis_synthetic; model_name="LIF")
display(fig)

Layout (2×2):

  • Top-left: IBI time series overlay

    • Real data (blue line)
    • Synthetic data (red dashed line)
    • First 200 beats for clarity
  • Top-right: Poincaré plot overlay

    • Real beat pairs (blue scatter)
    • Synthetic beat pairs (red scatter)
    • Identity line (reference)
  • Bottom-left: IBI distribution histograms

    • Real data histogram (blue)
    • Synthetic data histogram (red)
    • Overlaid for comparison
  • Bottom-right: Q-Q plot

    • Real data normalized quantiles
    • Theoretical quantiles
    • Diagonal reference line

plotmodelheatmap

Heatmap showing model reproduction quality across multiple features.

using HeartRateLab, DifferentialEquations

# Fit multiple models
lif_result = fit(LIF(), ibis; method=:gradient)
vdp_result = fit(VanDerPol(), ibis; method=:gradient)
lorenz_result = fit(Lorenz(), ibis; method=:bayesian)

# Compute errors per feature (example)
errors = Dict(
    "LIF" => [5.2, 3.1, 7.8, ...],      # Error for each feature
    "Van der Pol" => [6.1, 2.9, 6.5, ...],
    "Lorenz" => [4.8, 4.2, 8.1, ...]
)

features = ["Mean", "Std", "RMSSD", "pNN50", ...]

fig = plot_model_heatmap(errors, features)
display(fig)

Interpretation:

  • Green = Excellent reproduction (quality near 1.0)
  • Yellow = Good reproduction (quality 0.5-0.8)
  • Red = Poor reproduction (quality < 0.5)
  • Diagonal: Model-feature pairs to prioritize

Advanced Plots

plotlorenz3d

Interactive 3D scatter plot of Lorenz coordinates from IBI data.

fig = plot_lorenz_3d(ibis; title="3D Lorenz Plot")
display(fig)

Coordinates:

  • X-axis: IBI[n]
  • Y-axis: IBI[n+1]
  • Z-axis: IBI[n+2]
  • Color: Time progression (blue → red)

Interaction:

  • Rotate with mouse drag
  • Zoom with mouse scroll
  • Hover for coordinates

Use cases:

  • Visualize three-beat patterns
  • Identify nonlinear structure
  • Compare healthy vs pathological patterns

plot_radar

Radar/spider chart for multi-dimensional feature comparison.

using HeartRateLab, GLMakie

# Prepare data (normalized to [0,1])
data = Dict(
    "Subject A" => [0.7, 0.8, 0.6, 0.9, 0.5],
    "Subject B" => [0.5, 0.6, 0.8, 0.7, 0.6],
    "Subject C" => [0.9, 0.7, 0.5, 0.6, 0.8]
)

features = ["HRV", "Complexity", "Chaos", "Stability", "Entropy"]

fig = plot_radar(data; names=features)
display(fig)

Features:

  • Polygon for each dataset
  • Normalized [0,1] scale
  • Color-coded legend
  • Clear radius grid

Use cases:

  • Compare multiple subjects/conditions
  • Visualize HRV profile
  • Identify strengths/weaknesses

plot_correlations

Correlation heatmap showing relationships between HRV features.

using HeartRateLab, GLMakie, DataFrames

# Load data and extract features
ibis = read_txt("data.txt")
features_df = extract_feature_set(ibis) |> DataFrame

# Create correlation heatmap
fig = plot_correlations(features_df; title="HRV Feature Correlations")
display(fig)

Features:

  • Pearson correlation matrix
  • Symmetric heatmap
  • Red = Negative correlation (-1)
  • Blue = Positive correlation (+1)
  • White = No correlation (0)
  • Optional: Correlation values in cells

Use cases:

  • Identify redundant features
  • Understand feature relationships
  • Guide feature selection

Visualization Workflow

using HeartRateLab
using DifferentialEquations
using GLMakie

# Load real data
ibis_real = read_txt("subject.txt")

# 1. Analyze real data
fig1 = plot_ibi_series(ibis_real)
fig2 = plot_poincare(ibis_real)
fig3 = plot_spectrum(ibis_real)

# 2. Fit models
lif = fit(LIF(), ibis_real; method=:gradient)
vdp = fit(VanDerPol(), ibis_real; method=:gradient)
lorenz = fit(Lorenz(), ibis_real; method=:bayesian)

# 3. Generate synthetic data
ibis_lif = simulate(lif.model, lif.params, length(ibis_real))
ibis_vdp = simulate(vdp.model, vdp.params, length(ibis_real))
ibis_lorenz = simulate(lorenz.model, lorenz.params, length(ibis_real))

# 4. Compare models
fig_lif = plot_comparison(ibis_real, ibis_lif; model_name="LIF")
fig_vdp = plot_comparison(ibis_real, ibis_vdp; model_name="Van der Pol")
fig_lorenz = plot_comparison(ibis_real, ibis_lorenz; model_name="Lorenz")

# 5. Advanced analysis
fig_3d = plot_lorenz_3d(ibis_real)
fig_radar = plot_radar(real_features_dict; names=feature_names)

API Reference

GLMakie Tips

Saving Plots:

save("my_plot.png", fig)

Customizing Figure Size:

fig = Figure(size=(1200, 800))

Controlling Display:

# Interactive display
display(fig)

# Save without display
save("my_plot.svg", fig)

Keyboard Shortcuts:

  • q - Quit 3D view
  • s - Screenshot
  • h - Help menu