Variability & Risk Metrics
Glucose variability and risk indices.
calculateADRR
Import: @glucoseiq/core/metrics
calculateADRR(readings: GlucoseReading[]): numberCalculates the Average Daily Risk Range (ADRR).
Returns: ADRR value, or NaN if no valid readings
See: https://doi.org/10.2337/dc06-1085
| Parameter | Description |
|---|---|
readings | Array of GlucoseReading objects with timestamps |
calculateActivePercent
Import: @glucoseiq/core/metrics
calculateActivePercent(readings: GlucoseReading[], options?: ActivePercentOptions): ActivePercentResultCalculates a timestamp-slot coverage estimate for CGM readings.
Returns: Slot-coverage result, or a result with NaN if the timestamp span is insufficient
Throws: If expectedIntervalMinutes is invalid or creates an unsafe slot count
Remarks: This estimates data coverage; it does not prove sensor wear or clinical suitability.
See: https://doi.org/10.2337/dc17-1600
| Parameter | Description |
|---|---|
readings | Array of GlucoseReading objects with timestamps |
options | Expected interval configuration |
calculateCONGA
Import: @glucoseiq/core/metrics
calculateCONGA(readings: GlucoseReading[], options?: CONGAOptions): numberCalculates CONGA (Continuous Overall Net Glycemic Action).
Returns: CONGA value in mg/dL, or NaN if insufficient matched pairs
See: https://doi.org/10.1089/dia.2005.7.253
| Parameter | Description |
|---|---|
readings | Array of GlucoseReading objects with timestamps |
options | Time lag (hours) and tolerance configuration |
calculateGRADE
Import: @glucoseiq/core/metrics
calculateGRADE(readings: number[], hypoThreshold: number = 70, hyperThreshold: number = 140, unit: GlucoseUnit = MG_DL): GRADEResultCalculates the GRADE score and its partitioned components.
Returns: GRADE result with overall score and percentage breakdown, or NaN fields if no valid data
See: https://doi.org/10.1111/j.1464-5491.2007.02119.x
| Parameter | Description |
|---|---|
readings | Array of glucose values (mg/dL by default) |
hypoThreshold | Upper bound for hypoglycemia (default: 70 mg/dL, always mg/dL) |
hyperThreshold | Lower bound for hyperglycemia (default: 140 mg/dL, always mg/dL) |
unit | Unit of readings (default 'mg/dL'); 'mmol/L' is converted to mg/dL first |
calculateGRI
Import: @glucoseiq/core/metrics
calculateGRI(input: GRIInput): GRIResultCalculates the Glycemia Risk Index (GRI) from TIR zone percentages.
Returns: GRI result with composite score and risk zone
See: https://doi.org/10.1177/19322968221085273
| Parameter | Description |
|---|---|
input | Percentages for each out-of-range zone |
calculateGVIPGS
Import: @glucoseiq/core/metrics
calculateGVIPGS(readings: GlucoseReading[], options?: GVIPGSOptions): GVIPGSResultCalculates GVI and PGS from glucose readings (Nightscout algorithm).
Returns: GVI, PGS, the mean glucose, and PTIR; NaN when there are no valid steps
| Parameter | Description |
|---|---|
readings | Glucose readings with ISO 8601 timestamps |
options | Target range and maximum gap |
calculateIGC
Import: @glucoseiq/core/metrics
calculateIGC(readings: number[], options?: IGCOptions): IGCResultCalculates Rodbard's hypo/hyper indices and IGC.
Returns: Hypo index, hyper index, and their sum (IGC); NaN fields if no valid readings
See: https://doi.org/10.1089/dia.2008.0132
| Parameter | Description |
|---|---|
readings | Glucose values (mg/dL by default) |
options | Unit, target limits, exponents, and scale factors |
calculateJIndex
Import: @glucoseiq/core/metrics
calculateJIndex(readings: number[], unit: GlucoseUnit = MG_DL): numberCalculates the J-Index for a glucose trace.
The J-Index captures both central tendency and variability in a single score. Higher values indicate worse glycemic control.
Returns: J-Index value, or NaN if fewer than 2 valid readings
See: https://doi.org/10.1055/s-2007-979906
| Parameter | Description |
|---|---|
readings | Array of glucose values (mg/dL by default) |
unit | Unit of readings (default 'mg/dL'); 'mmol/L' is converted to mg/dL first |
calculateMODD
Import: @glucoseiq/core/metrics
calculateMODD(readings: GlucoseReading[], options?: MODDOptions): numberCalculates Mean of Daily Differences (MODD).
Returns: MODD value in mg/dL, or NaN if insufficient matched pairs
See: https://doi.org/10.2337/diacare.3.1.58
| Parameter | Description |
|---|---|
readings | Array of GlucoseReading objects with timestamps |
options | Optional tolerance configuration |
clinicalMAGE
Import: @glucoseiq/core
clinicalMAGE(readings: number[], options: MAGEOptions = {}): numberCalculates Mean Amplitude of Glycemic Excursions (MAGE). Implements Service FJ et al. (1970) methodology.
Returns: MAGE value, or NaN if insufficient data or no valid excursions
See:
import { clinicalMAGE } from '@glucoseiq/core'
const readings: number[] = Array.from(
{ length: 100 },
(_, index) => (index % 2 === 0 ? 90 : 160)
)
const mage = clinicalMAGE(readings)Remarks: - Minimum 24 data points recommended (1 day of hourly readings)
- Best suited for continuous glucose monitoring (CGM) data
- Not recommended for sparse or irregular measurements
- Uses dual moving averages, three-point excursion definition, and prevents double-counting.
| Parameter | Description |
|---|---|
readings | Array of glucose values (mg/dL or mmol/L) |
options | Configuration options for MAGE calculation |
glucoseCoefficientOfVariation
Import: @glucoseiq/core
glucoseCoefficientOfVariation(readings: number[]): numberCalculates the coefficient of variation (CV) for glucose values. CV = (SD / mean) × 100. Used to assess glycemic variability.
Returns: Coefficient of variation as a percentage, or NaN if <2 values or mean is 0
See: ADA 2019: Glycemic Targets
import { glucoseCoefficientOfVariation } from '@glucoseiq/core'
const valuesMgDl: number[] = [100, 120, 140]
const coefficientOfVariation = glucoseCoefficientOfVariation(valuesMgDl)Remarks: - If readings contains <2 values or mean is 0, returns NaN.
- Handles NaN/Infinity values by propagating them in the result.
| Parameter | Description |
|---|---|
readings | Array of glucose values (numbers) |
glucoseGVP
Import: @glucoseiq/core/metrics
glucoseGVP(readings: GlucoseReading[]): numberGlycemic Variability Percentage (GVP): the percentage by which the length of the glucose trace exceeds the length of a flat line over the same time.
GVP = (L / L0 − 1) × 100, where L = Σ √(Δt² + Δglucose²) and L0 = Σ Δt
(Δt in minutes, Δglucose in mg/dL).
Returns: GVP as a percentage, or NaN if < 2 readings or no time span
See: https://doi.org/10.1089/dia.2017.0187
| Parameter | Description |
|---|---|
readings | Glucose readings with ISO 8601 timestamps |
glucoseHBGI
Import: @glucoseiq/core/metrics
glucoseHBGI(readings: number[], unit: GlucoseUnit = MG_DL): numberCalculates the High Blood Glucose Index (HBGI).
Quantifies the risk and extent of hyperglycemia from a glucose trace. Higher values indicate greater hyperglycemia risk.
Risk categories (Kovatchev 2006):
- < 4.5: low risk
- 4.5 - 9.0: moderate risk
- > 9.0: high risk
Returns: HBGI value, or NaN if no valid readings
See: https://doi.org/10.2337/dc06-1085
| Parameter | Description |
|---|---|
readings | Array of glucose values (mg/dL by default) |
unit | Unit of readings (default 'mg/dL'); 'mmol/L' is converted to mg/dL first |
glucoseLBGI
Import: @glucoseiq/core/metrics
glucoseLBGI(readings: number[], unit: GlucoseUnit = MG_DL): numberCalculates the Low Blood Glucose Index (LBGI).
Quantifies the risk and extent of hypoglycemia from a glucose trace. Higher values indicate greater hypoglycemia risk.
Risk categories (Kovatchev 2006):
- < 1.1: low risk
- 1.1 - 2.5: moderate risk
- > 2.5: high risk
Returns: LBGI value, or NaN if no valid readings
See: https://doi.org/10.2337/dc06-1085
| Parameter | Description |
|---|---|
readings | Array of glucose values (mg/dL by default) |
unit | Unit of readings (default 'mg/dL'); 'mmol/L' is converted to mg/dL first |
glucoseMAG
Import: @glucoseiq/core/metrics
glucoseMAG(readings: GlucoseReading[]): numberMean Absolute Glucose change rate (MAG): total absolute glucose change divided by total elapsed time, in mg/dL per hour.
Returns: MAG in mg/dL per hour, or NaN if < 2 readings or no time span
See: https://doi.org/10.1186/cc9002
| Parameter | Description |
|---|---|
readings | Glucose readings with ISO 8601 timestamps |
glucoseMAGE
Import: @glucoseiq/core
glucoseMAGE(readings: number[], options?: MAGEOptions): numberCalculates Mean Amplitude of Glycemic Excursions (MAGE) for glucose values. Implements Service FJ et al. (1970) methodology.
Returns: MAGE value, or NaN if insufficient data or no valid excursions
See:
import { glucoseMAGE } from '@glucoseiq/core'
const valuesMgDl: number[] = Array.from(
{ length: 100 },
(_, index) => (index % 2 === 0 ? 90 : 160)
)
const mage = glucoseMAGE(valuesMgDl, { direction: 'ascending' })Remarks: - Minimum 24 data points recommended (1 day of hourly readings)
- Best suited for continuous glucose monitoring (CGM) data
- Not recommended for sparse or irregular measurements
- Uses dual moving averages, three-point excursion definition, and prevents double-counting.
| Parameter | Description |
|---|---|
readings | Array of glucose values (mg/dL or mmol/L) |
options | Optional configuration for MAGE calculation |
glucoseMValue
Import: @glucoseiq/core/metrics
glucoseMValue(readings: number[], options?: MValueOptions): numberCalculates the Schlichtkrull M-value for a glucose series.
Returns: The M-value, or NaN if there are no valid (finite, > 0) readings
See: https://pubmed.ncbi.nlm.nih.gov/14163158/
| Parameter | Description |
|---|---|
readings | Glucose values (mg/dL by default) |
options | Unit, reference index, and whether to add the W correction |
glucosePercentiles
Import: @glucoseiq/core
glucosePercentiles(readings: number[], percentiles: number[]): Record<number, number>Calculates specified percentiles from an array of glucose values using the nearest-rank method.
Returns: Object mapping percentile to value, or {} if input is empty
Throws: If readings or percentiles is not an array (INVALID_OPTION)
See:
import { glucosePercentiles } from '@glucoseiq/core'
const valuesMgDl: number[] = [100, 120, 140, 160, 180]
const requestedPercentiles: number[] = [10, 50, 90]
const percentiles = glucosePercentiles(valuesMgDl, requestedPercentiles)Remarks: - Returns the value at the nearest-rank for each percentile.
- If readings is empty, returns an empty object.
- Percentiles outside [0, 100] are ignored.
| Parameter | Description |
|---|---|
readings | Array of glucose values (numbers) |
percentiles | Array of percentiles to calculate (e.g., [10, 25, 50, 75, 90]) |
glucoseStandardDeviation
Import: @glucoseiq/core
glucoseStandardDeviation(readings: number[]): numberCalculates the unbiased sample standard deviation (SD) of glucose values. Uses n-1 in the denominator (sample SD), as recommended in research guidelines.
Returns: Standard deviation, or NaN if fewer than 2 values
See:
import { glucoseStandardDeviation } from '@glucoseiq/core'
const valuesMgDl: number[] = [100, 120, 140]
const standardDeviation = glucoseStandardDeviation(valuesMgDl)Remarks: - If readings contains <2 values, returns NaN (not enough data for SD).
- Handles NaN/Infinity values by propagating them in the result.
| Parameter | Description |
|---|---|
readings | Array of glucose values (numbers) |