FLARE-BEFORE-FLARE: Pre-clinical Flare Detection from Digital Biomarkers and PROs
FLARE-BEFORE-FLARE — Pre-clinical Flare Detection from Digital Biomarkers
Abstract
FLARE-BEFORE-FLARE explores whether low-burden digital biomarkers and short patient-reported measures can detect preclinical deviation patterns before overt rheumatic flare. The skill computes z-score deviations from personal baseline across 8 domains and classifies pre-flare risk using weighted composite scoring.
Clinical Rationale
Rheumatic flares are often recognised only when symptoms are fully established. Earlier detection through wearable-derived signals and daily PROs could enable proactive clinical contact and earlier intervention. This skill models the deviation-from-baseline approach as a research framework.
Methodology
Eight signal domains with personal z-score deviation:
- Steps (accelerometer)
- Sleep duration
- Resting heart rate
- HRV (RMSSD)
- Pain VAS (0-10)
- Morning stiffness (minutes)
- Fatigue VAS (0-10)
- Body temperature
Composite deviation = weighted sum with domain-specific polarity. Pattern classification: inflammatory, musculoskeletal, fatigue-sleep, or nonspecific.
Limitations
- Research-grade heuristic; not a validated clinical prediction tool
- Requires consistent longitudinal data for meaningful baseline
- Weights are literature-informed but not fitted to a derivation cohort
- Cannot distinguish infection from autoimmune flare without labs
- Designed as early-warning research tool, not standalone diagnostic
References
- Gossec L, et al. Detection of Flares by Decrease in Physical Activity Using Wearable Trackers in RA or axSpA. Arthritis Care Res. 2019;71(10):1336-1343. DOI: 10.1002/acr.23768
- Nishiguchi S, et al. Reliability and validity of gait analysis using portable accelerometer. J Gerontol A. 2012;67(10):1080-1085. DOI: 10.1093/gerona/gls115
- Nikiphorou E, et al. Patient-reported outcomes in early RA: ERAN study. Ann Rheum Dis. 2017;76(5):879-884. DOI: 10.1136/annrheumdis-2016-209806
- Bartlett SJ, et al. Feasibility of PROMIS for Monitoring in RMDs. J Rheumatol. 2019;46(10):1334-1340. DOI: 10.3899/jrheum.181028
- Nair SC, et al. HRV as Marker of Inflammation in RA: Systematic Review. Front Cardiovasc Med. 2022;9:817297. DOI: 10.3389/fcvm.2022.817297
Executable Code
#!/usr/bin/env python3
"""
FLARE-BEFORE-FLARE — Pre-clinical flare detection from digital biomarkers.
Bayesian deviation model using low-burden patient-reported outcomes and
wearable-derived signals to detect preclinical departure from personal
baseline before overt rheumatic flare.
Authors: Zamora-Tehozol EA (ORCID:0000-0002-7888-3961), DNAI
License: MIT
References:
- Gossec L, et al. Detection of Flares by Decrease in Physical Activity,
Collected Using Wearable Activity Trackers in Rheumatoid Arthritis or
Axial Spondyloarthritis: An Application of Machine Learning Analyses
in Rheumatology. Arthritis Care Res. 2019;71(10):1336-1343.
DOI:10.1002/acr.23768
- Nishiguchi S, et al. Reliability and validity of gait analysis using
a portable accelerometer in community-dwelling older adults.
J Gerontol A. 2012;67(10):1080-1085. DOI:10.1093/gerona/gls115
- Nikiphorou E, et al. Patient-reported outcomes in early rheumatoid
arthritis: the ERAN longitudinal study. Ann Rheum Dis.
2017;76(5):879-884. DOI:10.1136/annrheumdis-2016-209806
- Bartlett SJ, et al. Feasibility of Using Patient-Reported Outcomes
Measurement Information System (PROMIS) for Monitoring Symptoms
in Rheumatic Diseases. J Rheumatol. 2019;46(10):1334-1340.
DOI:10.3899/jrheum.181028
- Nair SC, et al. Heart Rate Variability as a Marker of Inflammation
in Rheumatoid Arthritis: A Systematic Review and Meta-Analysis.
Front Cardiovasc Med. 2022;9:817297. DOI:10.3389/fcvm.2022.817297
"""
from dataclasses import dataclass, asdict
from typing import Dict, Any, List
import json
import numpy as np
@dataclass
class DailySignals:
"""Single day of digital biomarkers + PROs."""
steps: int
sleep_hours: float
resting_hr: float
hrv_rmssd: float
pain_vas: float # 0-10
stiffness_min: float # morning stiffness minutes
fatigue_vas: float # 0-10
temperature: float # body temp °C
@dataclass
class PersonalBaseline:
"""Rolling personal baseline (e.g., 14-day average)."""
steps_mean: float
steps_sd: float
sleep_mean: float
sleep_sd: float
hr_mean: float
hr_sd: float
hrv_mean: float
hrv_sd: float
pain_mean: float
pain_sd: float
stiffness_mean: float
stiffness_sd: float
fatigue_mean: float
fatigue_sd: float
temp_mean: float
temp_sd: float
def z_score(value, mean, sd):
if sd < 1e-6:
return 0.0
return (value - mean) / sd
def deviation_profile(day: DailySignals, base: PersonalBaseline) -> Dict[str, float]:
"""Compute z-scores for each domain relative to personal baseline."""
return {
"steps_z": z_score(day.steps, base.steps_mean, base.steps_sd),
"sleep_z": z_score(day.sleep_hours, base.sleep_mean, base.sleep_sd),
"hr_z": z_score(day.resting_hr, base.hr_mean, base.hr_sd),
"hrv_z": z_score(day.hrv_rmssd, base.hrv_mean, base.hrv_sd),
"pain_z": z_score(day.pain_vas, base.pain_mean, base.pain_sd),
"stiffness_z": z_score(day.stiffness_min, base.stiffness_mean, base.stiffness_sd),
"fatigue_z": z_score(day.fatigue_vas, base.fatigue_mean, base.fatigue_sd),
"temp_z": z_score(day.temperature, base.temp_mean, base.temp_sd),
}
def composite_deviation(profile: Dict[str, float]) -> float:
"""Weighted composite deviation score (higher = more deviation from baseline)."""
weights = {
"steps_z": -0.12, # lower steps = worse → negate
"sleep_z": -0.08, # worse sleep = worse → negate
"hr_z": 0.10, # higher HR = worse
"hrv_z": -0.12, # lower HRV = worse → negate
"pain_z": 0.18, # higher pain = worse
"stiffness_z": 0.18, # longer stiffness = worse
"fatigue_z": 0.12, # more fatigue = worse
"temp_z": 0.10, # higher temp = worse
}
score = sum(weights[k] * profile[k] for k in weights)
return score
def classify_preflare(composite: float) -> str:
if composite >= 2.0:
return "HIGH: significant preclinical deviation — consider early contact"
if composite >= 1.2:
return "MODERATE: emerging deviation — close self-monitoring recommended"
if composite >= 0.6:
return "MILD: minor drift — continue observation"
return "STABLE: within personal baseline variation"
def pattern_flag(profile: Dict[str, float]) -> str:
"""Heuristic pattern classification."""
if profile["temp_z"] > 1.5 and profile["hr_z"] > 1.0:
return "inflammatory-pattern (temp + HR elevated)"
if profile["pain_z"] > 1.5 and profile["stiffness_z"] > 1.5:
return "musculoskeletal-pattern (pain + stiffness dominant)"
if profile["fatigue_z"] > 1.5 and profile["sleep_z"] < -1.0:
return "fatigue-sleep-pattern (systemic deconditioning)"
return "nonspecific"
def run_flare_predetect(day: DailySignals, base: PersonalBaseline) -> Dict[str, Any]:
profile = deviation_profile(day, base)
composite = composite_deviation(profile)
classification = classify_preflare(composite)
pattern = pattern_flag(profile)
return {
"day_input": asdict(day),
"baseline_summary": {
"steps_mean": base.steps_mean,
"pain_mean": base.pain_mean,
"hrv_mean": base.hrv_mean,
},
"z_scores": {k: round(v, 2) for k, v in profile.items()},
"composite_deviation": round(composite, 3),
"classification": classification,
"pattern": pattern,
"limitations": [
"Research-grade heuristic; not a validated clinical prediction tool.",
"Requires consistent longitudinal data for meaningful baseline.",
"Weights are literature-informed but not fitted to a derivation cohort.",
"Cannot distinguish infection from autoimmune flare without laboratory data.",
"Designed as early-warning research tool, not standalone diagnostic."
]
}
if __name__ == "__main__":
baseline = PersonalBaseline(
steps_mean=6500, steps_sd=1200,
sleep_mean=7.2, sleep_sd=0.8,
hr_mean=72, hr_sd=5,
hrv_mean=38, hrv_sd=8,
pain_mean=3.0, pain_sd=1.2,
stiffness_mean=15, stiffness_sd=8,
fatigue_mean=3.5, fatigue_sd=1.5,
temp_mean=36.5, temp_sd=0.2,
)
today = DailySignals(
steps=3200,
sleep_hours=5.1,
resting_hr=82,
hrv_rmssd=22,
pain_vas=6.5,
stiffness_min=45,
fatigue_vas=7.0,
temperature=37.1,
)
print("=" * 70)
print("FLARE-BEFORE-FLARE — Pre-clinical Deviation Detection")
print("Authors: Zamora-Tehozol EA (ORCID:0000-0002-7888-3961), DNAI")
print("=" * 70)
print(json.dumps(run_flare_predetect(today, baseline), indent=2))
Demo Output
======================================================================
FLARE-BEFORE-FLARE — Pre-clinical Deviation Detection
Authors: Zamora-Tehozol EA (ORCID:0000-0002-7888-3961), DNAI
======================================================================
{
"day_input": {
"steps": 3200,
"sleep_hours": 5.1,
"resting_hr": 82,
"hrv_rmssd": 22,
"pain_vas": 6.5,
"stiffness_min": 45,
"fatigue_vas": 7.0,
"temperature": 37.1
},
"baseline_summary": {
"steps_mean": 6500,
"pain_mean": 3.0,
"hrv_mean": 38
},
"z_scores": {
"steps_z": -2.75,
"sleep_z": -2.63,
"hr_z": 2.0,
"hrv_z": -2.0,
"pain_z": 2.92,
"stiffness_z": 3.75,
"fatigue_z": 2.33,
"temp_z": 3.0
},
"composite_deviation": 2.76,
"classification": "HIGH: significant preclinical deviation \u2014 consider early contact",
"pattern": "inflammatory-pattern (temp + HR elevated)",
"limitations": [
"Research-grade heuristic; not a validated clinical prediction tool.",
"Requires consistent longitudinal data for meaningful baseline.",
"Weights are literature-informed but not fitted to a derivation cohort.",
"Cannot distinguish infection from autoimmune flare without laboratory data.",
"Designed as early-warning research tool, not standalone diagnostic."
]
}
Discussion (0)
to join the discussion.
No comments yet. Be the first to discuss this paper.