Skip to content

Health Analytics Service

The Health Analytics Service provides advanced statistical analysis capabilities for health-related data. It's designed to identify patterns, correlations, and insights in health metrics through a high-performance native C++ implementation with a Dart interface.

This service leverages Foreign Function Interface (FFI) to bridge Dart applications with the C++ analytics engine, enabling complex health data analysis with minimal computational overhead in Flutter applications.

Key capabilities include statistical computations, correlation identification, time series analysis, anomaly detection, clustering, and health-specific analyses like medication impact and hormone level monitoring.

Table of Contents

Core Features

The Health Analytics Service provides the following core functionalities:

  • Statistical Analysis: Calculate mean, median, variance, standard deviation, quartiles, skewness, and kurtosis for health metrics.
  • Trend Detection: Identify increasing, decreasing, cyclic, or variable trends in time series data.
  • Correlation Analysis: Find relationships between various health factors and determine their significance.
  • Multivariate Analysis: Explore complex relationships between multiple health variables.
  • Clustering: Group similar health patterns together to identify natural categories.
  • Time Series Forecasting: Predict future values of health metrics based on historical data.
  • Anomaly Detection: Identify unusual patterns or outliers in health data.
  • Factor Impact Analysis: Determine which factors have the strongest influence on target health metrics.
  • Temporal Pattern Analysis: Discover cyclical patterns and date-related trends (e.g., weekly patterns).
  • Medication Impact Analysis: Assess how medications affect various health metrics.
  • Hormone Analysis: Evaluate hormone levels and their impact on health factors.
  • Comprehensive Analysis: Integrate multiple analysis techniques for holistic health insights.

API Reference

Basic Statistics

Calculate fundamental statistics for a health metric:

HealthStatistics stats = analyticsService.calculateStatistics(values);

The HealthStatistics object provides:

  • mean
  • median
  • min/max values
  • standard deviation
  • variance
  • skewness
  • kurtosis
  • quartiles (Q1, Q3)
  • interquartile range (IQR)

Trend Analysis

Detect trends in time series data:

TrendAnalysis trend = analyticsService.detectTrend(values);

This returns a TrendAnalysis with:

  • trend type (increasing, decreasing, cyclic, variable, or none)
  • strength (0-1 scale)
  • description of the detected trend

Correlation Analysis

Find correlations between a target variable and multiple factors:

List<FactorCorrelation> correlations = analyticsService.findCorrelations(
  targetValues,
  factorData,
);

Where:

  • targetValues is a list of double values for the target metric
  • factorData is a map of factor names to lists of double values

Returns a list of FactorCorrelation objects with:

  • factor name
  • correlation coefficient (-1 to 1)
  • p-value
  • confidence level

Multivariate Analysis

Find complex relationships between multiple factors:

List<MultivariateRelationship> relationships = analyticsService.findMultivariateCorrelations(
  factorData,
);

This identifies various relationship types (direct correlation, mediation, network effects) between three or more factors.

Cluster Analysis

Group similar data points based on multiple factors:

List<ClusterPattern> clusters = analyticsService.performClusterAnalysis(
  factorData,
  maxClusters,
);

This identifies natural groupings in the data, returning:

  • cluster ID and name
  • number of points in each cluster
  • significance score
  • key factors defining each cluster
  • detailed description

Time Series Forecasting

Predict future values of a health metric:

TimeSeriesPrediction forecast = analyticsService.predictTimeSeries(
  factorName,
  timeSeriesData,
  stepsAhead,
);

Returns predictions with confidence intervals and seasonality information.

Anomaly Detection

Identify unusual patterns or outliers in health data:

List<AnomalyResult> anomalies = analyticsService.detectAnomalies(
  factorName,
  timeSeriesData,
  dates,
  threshold,
);

Detects statistical outliers, contextual anomalies, and trend changes.

Factor Impact Analysis

Determine which factors have the strongest influence on a target metric:

List<FactorImpact> impacts = analyticsService.rankFactorImpacts(
  factorData,
  targetData,
);

This analyzes both direct and indirect effects of factors, returning:

  • impact score
  • direct effect
  • indirect effect (through other factors)
  • confidence level
  • mechanism description

Date Pattern Analysis

Discover patterns related to specific times (day of week, month, etc.):

List<DatePattern> patterns = analyticsService.analyzeDatePatterns(
  factorName,
  values,
  dates,
);

Identifies weekly, monthly, or custom periodicity patterns.

Cycle Analysis

Analyze cyclical patterns in health data:

CycleAnalysis cycles = analyticsService.analyzeCycles(
  factorName,
  values,
  dates,
);

Returns information about:

  • cycle length
  • amplitude
  • phase shift
  • confidence level
  • variance in cycle length

Medication Impact Analysis

Assess how medications affect health metrics:

MedicationImpactResult impact = analyticsService.analyzeMedicationImpact(
  medicationName,
  factorName,
  beforeData,
  afterData,
);

Compares health metrics before and after medication, providing:

  • mean values before and after
  • magnitude and significance of changes
  • overall impact score
  • estimated days to effect

Hormone Analysis

Evaluate hormone levels and their impact on health factors:

HormoneImpactResult hormoneImpact = analyticsService.analyzeHormoneImpact(
  hormoneName,
  hormoneLevels,
  factorData,
  minOptimalLevel,
  maxOptimalLevel,
);

Provides information about:

  • current vs. optimal hormone levels
  • deviation from optimal range
  • impact on mood and energy
  • correlations with other health factors

Comprehensive Analysis

Generate a holistic analysis combining multiple techniques:

ComprehensiveHealthAnalysis analysis = await analyticsService.generateComprehensiveAnalysis(
  moodEntries: moodEntries,
  medications: medications,
  takenMedications: takenMedications,
  bloodworkEntries: bloodworkEntries,
  timeframe: "3 months",
);

This integrates all analysis methods to provide a complete health overview.

Data Models

The service uses the following core data models:

Health Statistics

class HealthStatistics {
  final double mean;
  final double median;
  final double min;
  final double max;
  final double stdDev;
  final double variance;
  final double skewness;
  final double kurtosis;
  final double q1;
  final double q3;
  final double iqr;
}

Trend Analysis

class TrendAnalysis {
  final TrendType type; // enum: none, increasing, decreasing, cyclic, variable
  final double strength;
  final String description;
}

Factor Correlation

class FactorCorrelation {
  final String factorName;
  final double correlation;
  final double pValue;
  final double confidence;
}

Multivariate Relationship

class MultivariateRelationship {
  final List<String> factorNames;
  final double correlationStrength;
  final String description;
  final double confidence;
  final List<double> factorWeights;
  final RelationshipType relationshipType;
}

Cluster Pattern

class ClusterPattern {
  final int id;
  final String name;
  final String description;
  final int pointCount;
  final double significance;
  final List<String> keyFactors;
  final List<double> factorImportance;
}

Time Series Prediction

class TimeSeriesPrediction {
  final String factorName;
  final List<double> predictions;
  final List<List<double>> confidenceIntervals;
  final double confidence;
  final int seasonalityPeriod;
  final TimeUnit timeUnit;
}

Anomaly Result

class AnomalyResult {
  final String factorName;
  final int dataPointIndex;
  final double anomalyScore;
  final String description;
  final double originalValue;
  final double expectedValue;
  final DateTime? date;
  final double confidence;
  final AnomalyType anomalyType;
}

Factor Impact

class FactorImpact {
  final String factorName;
  final double impactScore;
  final double directEffect;
  final double indirectEffect;
  final double confidence;
  final String mechanism;
}

Date Pattern

class DatePattern {
  final PatternType type;
  final int periodicity;
  final double strength;
  final String description;
  final List<double> peakValues;
  final int peakDayOfWeek;
  final int peakDayOfMonth;
  final int peakMonth;
}

Cycle Analysis

class CycleAnalysis {
  final double cycleLength;
  final double cycleLengthVariance;
  final double amplitude;
  final double phaseShift;
  final double confidence;
  final String description;
}

Medication Impact Result

class MedicationImpactResult {
  final String medicationName;
  final String factorName;
  final double beforeMean;
  final double afterMean;
  final double changeMagnitude;
  final double changeSignificance;
  final double overallImpact;
  final int daysToEffect;
  final String description;
}

Hormone Impact Result

class HormoneImpactResult {
  final String hormoneName;
  final double currentLevel;
  final double optimalLevel;
  final double optimalRangeLower;
  final double optimalRangeUpper;
  final double deviation;
  final double impactOnMood;
  final double impactOnEnergy;
  final Map<String, double> factorImpacts;
  final String description;
}

Comprehensive Health Analysis

class ComprehensiveHealthAnalysis {
  final TrendAnalysis moodTrend;
  final List<MultivariateRelationship> factorCorrelations;
  final List<ClusterPattern> clusters;
  final List<AnomalyResult> anomalies;
  final List<FactorImpact> factorImpacts;
  final List<TimeSeriesPrediction> predictions;
  final List<DatePattern> datePatterns;
  final List<CycleAnalysis> cycleAnalyses;
  final List<HormoneImpactResult> hormoneImpacts;
  final List<MedicationImpactResult> medicationImpacts;
  final DateTime analysisDate;
  final String timeframe;
}

Example Usage

import 'package:nokken/src/features/health_analytics/health_analytics_service.dart';
import 'package:nokken/src/features/mood_tracker/models/mood_entry.dart';
import 'package:nokken/src/features/medication_tracker/models/medication.dart';
import 'package:nokken/src/features/bloodwork_tracker/models/bloodwork.dart';

Future<void> generateHealthInsights(
  List<MoodEntry> moodEntries,
  List<Medication> medications,
  List<Bloodwork> bloodworkEntries,
) async {
  final analyticsService = HealthAnalyticsService();
  await analyticsService.initialize();

  if (!analyticsService.isInitialized) {
    print('Failed to initialize analytics service');
    return;
  }

  // Determine which medications the user is currently taking
  final takenMedications = medications
      .where((med) => med.isActive)
      .map((med) => med.id)
      .toSet();

  // Generate comprehensive analysis
  final analysis = await analyticsService.generateComprehensiveAnalysis(
    moodEntries: moodEntries,
    medications: medications,
    takenMedications: takenMedications,
    bloodworkEntries: bloodworkEntries,
    timeframe: '3 months',
  );

  // Present key insights
  print('=== HEALTH INSIGHTS ===');
  print('Analysis date: ${analysis.analysisDate}');
  print('Timeframe: ${analysis.timeframe}');

  // Mood trend
  print('\n== Mood Trend ==');
  print(analysis.moodTrend.description);

  // Key correlations
  print('\n== Key Correlations ==');
  for (final correlation in analysis.factorCorrelations.take(3)) {
    print(correlation.description);
  }

  // Anomalies
  print('\n== Anomalies Detected ==');
  for (final anomaly in analysis.anomalies.take(5)) {
    print('${anomaly.factorName}: ${anomaly.description}');
    if (anomaly.date != null) {
      print('Date: ${anomaly.date}');
    }
  }

  // Medication impacts
  print('\n== Medication Impacts ==');
  for (final impact in analysis.medicationImpacts) {
    print('${impact.medicationName}${impact.factorName}: ${impact.description}');
  }

  // Predictions
  print('\n== Predictions ==');
  for (final prediction in analysis.predictions.take(3)) {
    print('${prediction.factorName} next week: ${prediction.predictions.first.toStringAsFixed(1)} (confidence: ${(prediction.confidence * 100).toStringAsFixed(1)}%)');
  }
}

Performance Considerations

The Health Analytics Service uses a high-performance C++ implementation for computation-intensive operations, but there are still important considerations for optimal usage:

  1. Data Volume: The service performs well with typical health tracking data volumes (hundreds to thousands of data points), but very large datasets may require batching or sampling.

  2. Memory Management: The service handles memory allocation and deallocation for native resources, but be mindful of large data structures in Dart code.

  3. Initialization Cost: The first call to initialize() has a one-time overhead for loading the native library.

  4. Operation Complexity: Operations like cluster analysis and multivariate correlation have higher computational complexity.

  5. Platform Differences: Performance may vary across platforms. iOS and Android have different native code optimization levels.

Troubleshooting

Common Issues

Native Library Loading Failures

If you encounter issues loading the native library:

  1. Verify the native libraries are correctly placed in platform-specific directories
  2. Check that library names match expected platform conventions:
Platform Library
Android libhealth_analytics.so
iOS Framework or dynamic library
Linux libhealth_analytics.so
  1. For Android, ensure the correct ABIs are supported in your build.gradle:
android {
    defaultConfig {
        ndk {
            abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
        }
    }
}

Insufficient Data Errors

Many analysis methods require minimum data points:

  • Basic statistics: at least 1 data point
  • Trend analysis: at least 3 data points
  • Correlation analysis: at least 3 matched pairs
  • Cycle analysis: at least 20 data points
  • Cluster analysis: at least 5 data points

Always check data volumes before calling analysis methods and provide appropriate fallbacks or messages when data is insufficient.