Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ result_float = iglu.cv_glu(glucose_list) # list of glucose values
```

## IGLU-R Compatibility Test Status
The current version of IGLU-PYTHON is test-compatible with IGLU-R v4.2.2
The current version of IGLU-PYTHON is test-compatible with IGLU-R v4.3.0 (2025-07-12)

Unless noted, IGLU-R test compatability is considered successful if it achieves precision of 0.001

Expand Down Expand Up @@ -73,7 +73,7 @@ Unless noted, IGLU-R test compatability is considered successful if it achieves
| lbgi | Low Blood Glucose Index| βœ… |βœ… returns float |
| m_value | M-value of Schlichtkrull et al | βœ… |βœ… returns float |
| mad_glu | Median Absolute Deviation | βœ… |βœ… returns float |
| mag | Mean Absolute Glucose| βœ… | βœ… only Series(DatetimeIndex) returns float ||| IMHO, Original R implementation has an error |
| mag | Mean Absolute Glucose| βœ… | βœ… only Series(DatetimeIndex) returns float ||| IMHO, Original R bug fixed in v4.3.0 |
| mage | Mean Amplitude of Glycemic Excursions| βœ… |βœ… only Series(DatetimeIndex) returns float || See algorithm at [MAGE](https://irinagain.github.io/iglu/articles/MAGE.html) |
| mean_glu | Mean glucose value | βœ… | βœ… returns float|
| median_glu |Median glucose value| βœ… |βœ… returns float |
Expand Down
50 changes: 22 additions & 28 deletions iglu_python/mag.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import numpy as np
import pandas as pd

from .utils import CGMS2DayByDay, check_data_columns, is_iglu_r_compatible
from .utils import CGMS2DayByDay, check_data_columns


def mag(
data: Union[pd.DataFrame, pd.Series],
n: int = 60,
n: int | None = None, # to match a new IGLU-R behavior
dt0: Optional[int] = None,
inter_gap: int = 45,
tz: str = "",
Expand All @@ -26,9 +26,10 @@ def mag(
----------
data : Union[pd.DataFrame, pd.Series]
DataFrame with columns 'id', 'time', and 'gl', or a Series of glucose values
n : int, default=60
n : int|None, default=None
Integer giving the desired interval in minutes over which to calculate
the change in glucose. Default is 60 for hourly intervals.
the change in glucose. Default is None - will be automatically set to dt0
(from data collection frequency).
dt0 : Optional[int], default=None
Time interval between measurements in minutes. If None, it will be automatically
determined from the data.
Expand Down Expand Up @@ -85,14 +86,20 @@ def mag(
return out


def mag_single(gl: pd.Series, n: int = 60, dt0: Optional[int] = None, inter_gap: int = 45, tz: str = "") -> float:
def mag_single(
gl: pd.Series,
n: int | None = None, # to match a new IGLU-R behavior
dt0: Optional[int] = None,
inter_gap: int = 45,
tz: str = "",
) -> float:
"""Calculate MAG for a single subject"""
# Convert data to day-by-day format
data_ip = CGMS2DayByDay(gl, dt0=dt0, inter_gap=inter_gap, tz=tz)
dt0_actual = data_ip[2] # Time between measurements in minutes

# Ensure n is not less than data collection frequency
if n < dt0_actual:
if n is None or n < dt0_actual:
n = dt0_actual

# Calculate number of readings per interval
Expand All @@ -108,27 +115,14 @@ def mag_single(gl: pd.Series, n: int = 60, dt0: Optional[int] = None, inter_gap:
# Calculate absolute differences between readings n minutes apart
lag = readings_per_interval

if is_iglu_r_compatible():
idx = np.arange(0, len(gl_values), lag)
gl_values_idx = gl_values[idx]
diffs = gl_values_idx[1:] - gl_values_idx[:-1]
diffs = np.abs(diffs)
diffs = diffs[~np.isnan(diffs)]
# to be IGLU-R test compatible, imho they made error.
# has to be total_time_hours = ((len(diffs)) * n) / 60
total_time_hours = ((len(gl_values_idx[~np.isnan(gl_values_idx)])) * n) / 60
if total_time_hours == 0:
return 0.0
mag = float(np.sum(diffs) / total_time_hours)
else:
diffs = gl_values[lag:] - gl_values[:-lag]
diffs = np.abs(diffs)
diffs = diffs[~np.isnan(diffs)]

# Calculate MAG: sum of absolute differences divided by total time in hours
total_time_hours = ((len(diffs)) * n) / 60
if total_time_hours == 0:
return 0.0
mag = float(np.sum(diffs) / total_time_hours)
diffs = gl_values[lag:] - gl_values[:-lag]
diffs = np.abs(diffs)
diffs = diffs[~np.isnan(diffs)]

# Calculate MAG: sum of absolute differences divided by total time in hours
total_time_hours = ((len(diffs)) * n) / 60
if total_time_hours == 0:
return 0.0
mag = float(np.sum(diffs) / total_time_hours)

return mag
40 changes: 20 additions & 20 deletions iglu_r_discrepancies.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 28,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -25,7 +25,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 29,
"metadata": {},
"outputs": [
{
Expand All @@ -35,7 +35,7 @@
"Python version: 3.11.10 (main, Oct 3 2024, 02:26:51) [Clang 14.0.6 ]\n",
"R version: [1] \"R version 4.4.3 (2025-02-28)\"\n",
"\n",
"iglu version: [1] β€˜4.2.2’\n",
"iglu version: [1] β€˜4.3.0’\n",
"\n",
"iglu_py version: 1.1.1\n",
"rpy2 version: 3.6.0\n"
Expand All @@ -61,7 +61,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 30,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -93,7 +93,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 31,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -190,7 +190,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 32,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -244,7 +244,7 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 33,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -287,7 +287,7 @@
"1 subject1 102.222222"
]
},
"execution_count": 7,
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
Expand Down Expand Up @@ -315,7 +315,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 34,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -361,7 +361,7 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 35,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -451,7 +451,7 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 36,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -504,7 +504,7 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": 37,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -626,7 +626,7 @@
},
{
"cell_type": "code",
"execution_count": 22,
"execution_count": 38,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -677,7 +677,7 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 39,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -799,7 +799,7 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": 40,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -847,7 +847,7 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 41,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -858,7 +858,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 42,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -1026,7 +1026,7 @@
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": 43,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -1196,7 +1196,7 @@
},
{
"cell_type": "code",
"execution_count": 16,
"execution_count": 44,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -1366,7 +1366,7 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 45,
"metadata": {},
"outputs": [
{
Expand Down
24 changes: 12 additions & 12 deletions notebooks/auc_evaluation.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -51,7 +51,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 11,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -153,7 +153,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -167,7 +167,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 13,
"metadata": {},
"outputs": [
{
Expand All @@ -177,7 +177,7 @@
"Python version: 3.11.10 (main, Oct 3 2024, 02:26:51) [Clang 14.0.6 ]\n",
"R version: [1] \"R version 4.4.3 (2025-02-28)\"\n",
"\n",
"iglu version: [1] β€˜4.2.2’\n",
"iglu version: [1] β€˜4.3.0’\n",
"\n",
"iglu_py version: 1.1.1\n",
"rpy2 version: 3.6.0\n"
Expand Down Expand Up @@ -209,7 +209,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 14,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -252,7 +252,7 @@
"1 subject1 102.222222"
]
},
"execution_count": 5,
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
Expand Down Expand Up @@ -294,7 +294,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 15,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -410,7 +410,7 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -433,7 +433,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 17,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -476,7 +476,7 @@
"0 subject1 100.0"
]
},
"execution_count": 8,
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
Expand All @@ -502,7 +502,7 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 18,
"metadata": {},
"outputs": [
{
Expand Down
Loading
Loading