Skip to content

Commit

Permalink
change name of variable target_range -> interval
Browse files Browse the repository at this point in the history
  • Loading branch information
Deigoodle committed Feb 13, 2024
1 parent 7a0f1ce commit 9813ccb
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 52 deletions.
38 changes: 22 additions & 16 deletions glucopy/classes/Gframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

# Local
from glucopy.utils import (disjoin_days_and_hours,
mgdl_to_mmoll)
mgdl_to_mmoll,
mmoll_to_mgdl)
import glucopy.metrics as metrics

class Gframe:
Expand Down Expand Up @@ -165,7 +166,7 @@ def convert_unit(self,
raise ValueError('The data is already in mmol/L')
else:
if self.unit == 'mmol/L':
self.data['CGM'] = mgdl_to_mmoll(self.data['CGM'], reverse=True)
self.data['CGM'] = mmoll_to_mgdl(self.data['CGM'])
self.unit = new_unit
else:
raise ValueError('The data is already in mg/dL')
Expand Down Expand Up @@ -501,7 +502,7 @@ def modd(self,
# Time in Range
def tir(self,
per_day: bool = False,
target_range:list= [0,70,180],
interval:list= [0,70,180],
percentage: bool = True,
decimals: int = 2):
'''
Expand All @@ -518,7 +519,7 @@ def tir(self,
----------
per_day : bool, default False
If True, returns a pandas Series with the TIR for each day. If False, returns the TIR for all days combined.
target_range : list of int|float, default [0,70,180]
interval : list of int|float, default [0,70,180]
Interval of glucose concentration to calculate :math:`\\tau`. Can be a list of 1 number, in that case the
time will be calculated below and above that number. It will always try to calculate the time below the first
number and above the last number.
Expand Down Expand Up @@ -547,7 +548,7 @@ def tir(self,
.. ipython:: python
gf.tir(target_range=[0,70,150,180,230])
gf.tir(interval=[0,70,150,180,230])
Calculating the TIR for each day and the default range (0,70,180):
Expand All @@ -565,10 +566,10 @@ def tir(self,

# Calculate TIR for each day
for day, day_data in day_groups:
tir[str(day)] = metrics.tir(df=day_data, target_range=target_range, percentage=percentage, decimals=decimals).tolist()
tir[str(day)] = metrics.tir(df=day_data, interval=interval, percentage=percentage, decimals=decimals).tolist()

else: # Calculate TIR for all data
tir = metrics.tir(df=self.data, target_range=target_range, percentage=percentage, decimals=decimals)
tir = metrics.tir(df=self.data, interval=interval, percentage=percentage, decimals=decimals)

return tir

Expand All @@ -577,7 +578,7 @@ def tir(self,
# Frecuency distribution : counts the amount of observations given certain intervals of CGM
def fd(self,
per_day: bool = False,
target_range: list = [0,70,180],
interval: list = [0,70,180],
decimals: int = 2,
count: bool = False):
'''
Expand All @@ -594,7 +595,7 @@ def fd(self,
----------
per_day : bool, default False
If True, returns a pandas Series with the FD for each day. If False, returns the FD for all days combined.
target_range : list of int|float, default [0,70,180]
interval : list of int|float, default [0,70,180]
Interval of glucose concentration to calculate `FD`. Can be a list of 1 number, in that case the time will
be calculated below and above that number. It will always try to calculate the time below the first number
and above the last number.
Expand Down Expand Up @@ -622,7 +623,7 @@ def fd(self,
.. ipython:: python
gf.fd(target_range=[0,70,150,180,230])
gf.fd(interval=[0,70,150,180,230])
Calculating the FD for each day and the default range (0,70,180):
Expand All @@ -638,10 +639,10 @@ def fd(self,
fd.index.name = 'Day'

for day, day_data in day_groups:
fd[str(day)] = metrics.fd(df=day_data, target_range=target_range, decimals=decimals, count=count).values
fd[str(day)] = metrics.fd(df=day_data, interval=interval, decimals=decimals, count=count).values

else:
fd = metrics.fd(df=self.data, target_range=target_range, decimals=decimals, count=count)
fd = metrics.fd(df=self.data, interval=interval, decimals=decimals, count=count)

return fd

Expand Down Expand Up @@ -1060,11 +1061,11 @@ def qscore(self,
'''
# Time in range [70.2,160.2] mg/dL = [3.9,8.9] mmol/L
if self.unit == 'mmol/L':
target_range = [3.9,8.9]
interval = [3.9,8.9]
elif self.unit == 'mg/dL':
target_range = [70.2,160.2]
interval = [70.2,160.2]

tir_per_day = self.tir(per_day=True, target_range=target_range, percentage=False)
tir_per_day = self.tir(per_day=True, interval=interval, percentage=False)

# List with the Timedelta corresponding to the time spent under 3.9 mmol/L for each day
tir_per_day_minus_3_9 = [time[0].total_seconds() for time in tir_per_day]
Expand Down Expand Up @@ -1604,8 +1605,13 @@ def summary(self,
gf = gp.data('prueba_1')
gf.summary()
'''
# Time in range [70,180] mg/dL
tir_interval = np.array([0, 70, 180])
if self.unit == 'mmol/L':
tir_interval = mgdl_to_mmoll(tir_interval)

# Metrics that return Series
tir = self.tir()
tir = self.tir(interval=tir_interval)
grade = self.grade()

# Summary
Expand Down
28 changes: 16 additions & 12 deletions glucopy/metrics/fd.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import numpy as np

def fd(df: pd.DataFrame,
target_range: list = [0,70,180],
interval: list = [0,70,180],
decimals: int = 2,
count: bool = False
):
Expand All @@ -22,7 +22,7 @@ def fd(df: pd.DataFrame,
df : pandas.DataFrame
DataFrame containing the CGM values. The dataframe must contain 'CGM' column present in
:attr:`glucopy.Gframe.data`.
target_range : list of int|float, default [0,70,180]
interval : list of int|float, default [0,70,180]
Target range in CGM unit. It must have at least 2 values, for the "normal"
range, low and high values will be values outside that range.
decimals : int, default 2
Expand All @@ -39,22 +39,26 @@ def fd(df: pd.DataFrame,
-----
This function is meant to be used by :meth:`glucopy.Gframe.fd`
'''
# Check input, Ensure target_range is a list with 0 and the max value of the data
if not isinstance(target_range, list) or not all(isinstance(i, (int, float)) for i in target_range):
raise ValueError("target_range must be a list of numbers")
# Check input, Ensure interval is a list or numpy array of numbers
if not isinstance(interval, (list, np.ndarray)):
raise ValueError("interval must be a list or numpy array of numbers")

# Convert interval to a list if it's a numpy array
if isinstance(interval, np.ndarray):
interval = interval.tolist()

# Add 0 to the target range if it is not present to count the time below the target range
if 0 not in target_range:
target_range = [0] + target_range
if 0 not in interval:
interval = [0] + interval

# Add the max value of the data to the target range if it is not present to count the time above the target range
max_value = max(df['CGM'])
if max_value <= target_range[-1]:
max_value = target_range[-1] + 1
if max_value > target_range[-1]:
target_range = target_range + [max_value]
if max_value <= interval[-1]:
max_value = interval[-1] + 1
if max_value > interval[-1]:
interval = interval + [max_value]

result = pd.cut(df['CGM'], bins=target_range).groupby(pd.cut(df['CGM'], bins=target_range), observed=False).count()
result = pd.cut(df['CGM'], bins=interval).groupby(pd.cut(df['CGM'], bins=interval), observed=False).count()

if not count:
result = result / result.sum()
Expand Down
28 changes: 16 additions & 12 deletions glucopy/metrics/tir.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import numpy as np

def tir(df: pd.DataFrame,
target_range:list= [0,70,180],
interval:list= [0,70,180],
percentage: bool = True,
decimals: int = 2
):
Expand All @@ -21,7 +21,7 @@ def tir(df: pd.DataFrame,
----------
per_day : bool, default False
If True, returns a pandas Series with the TIR for each day. If False, returns the TIR for all days combined.
target_range : list of int|float, default [0,70,180]
interval : list of int|float, default [0,70,180]
Interval of glucose concentration to calculate :math:`\\tau`. Can be a list of 1 number, in that case the
time will be calculated below and above that number. It will always try to calculate the time below the first
number and above the last number.
Expand All @@ -39,26 +39,30 @@ def tir(df: pd.DataFrame,
-----
This function is meant to be used by :meth:`glucopy.Gframe.tir`
'''
# Check input, Ensure target_range is a list with 0 and the max value of the data
if not isinstance(target_range, list) or not all(isinstance(i, (int, float)) for i in target_range):
raise ValueError("target_range must be a list of numbers")
# Check input, Ensure interval is a list or numpy array of numbers
if not isinstance(interval, (list, np.ndarray)):
raise ValueError("interval must be a list or numpy array of numbers")

# Convert interval to a list if it's a numpy array
if isinstance(interval, np.ndarray):
interval = interval.tolist()

# Add 0 to the target range if it is not present to count the time below the target range
if 0 not in target_range:
target_range = [0] + target_range
if 0 not in interval:
interval = [0] + interval

# Add the max value of the data to the target range if it is not present to count the time above the target range
max_value = max(df['CGM'])
if max_value <= target_range[-1]:
max_value = target_range[-1] + 1
if max_value > target_range[-1]:
target_range = target_range + [max_value]
if max_value <= interval[-1]:
max_value = interval[-1] + 1
if max_value > interval[-1]:
interval = interval + [max_value]

data_copy = df.copy()
# Calculate time difference between consecutive timestamps
data_copy['Time_Diff'] = data_copy['Timestamp'].diff().dt.total_seconds()
# Create a column with the range that each CGM value belongs to
data_copy['ranges'] = pd.cut(data_copy['CGM'], bins=target_range)
data_copy['ranges'] = pd.cut(data_copy['CGM'], bins=interval)
# Group data by range and sum the time difference
time_count = data_copy.groupby('ranges', observed=False)['Time_Diff'].sum()

Expand Down
36 changes: 24 additions & 12 deletions glucopy/plot/hist/freq.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# 3rd party
import plotly.graph_objects as go
import numpy as np

# Local
from ...classes import Gframe

def freq(gf: Gframe,
per_day: bool = True,
target_range: list = [0,70,180],
interval: list = [0,70,180],
count: bool = False,
height: float = None,
width: float = None):
Expand All @@ -19,7 +20,7 @@ def freq(gf: Gframe,
Gframe object to plot
per_day : bool, default True
If True, the plot will be separated by days
target_range : list, default [0,70,180]
interval : list, default [0,70,180]
Target range for the glucose
count : bool, default False
If True, the y axis will be the count of the glucose in the target range. If False, the y axis will be the
Expand Down Expand Up @@ -56,7 +57,7 @@ def freq(gf: Gframe,
.. ipython:: python
fig = gp.plot.freq(gf, per_day=False, target_range=[0,100,200,300])
fig = gp.plot.freq(gf, per_day=False, interval=[0,100,200,300])
.. image:: /../img/freq_plot_2.png
:alt: Frequency plot
Expand All @@ -66,17 +67,28 @@ def freq(gf: Gframe,
if not isinstance(gf, Gframe):
raise TypeError('gf must be a Gframe object')

# Check input, Ensure target_range is a list with 0 and the max value of the data
if not isinstance(target_range, list) or not all(isinstance(i, (int, float)) for i in target_range):
raise ValueError("target_range must be a list of numbers")
if 0 not in target_range:
target_range = [0] + target_range
if max(gf.data['CGM']) > target_range[-1]:
target_range = target_range + [max(gf.data['CGM'])]
# Check input, Ensure interval is a list or numpy array of numbers
if not isinstance(interval, (list, np.ndarray)):
raise ValueError("interval must be a list or numpy array of numbers")

# Convert interval to a list if it's a numpy array
if isinstance(interval, np.ndarray):
interval = interval.tolist()

# Add 0 to the target range if it is not present to count the time below the target range
if 0 not in interval:
interval = [0] + interval

# Add the max value of the data to the target range if it is not present to count the time above the target range
max_value = max(gf.data['CGM'])
if max_value <= interval[-1]:
max_value = interval[-1] + 1
if max_value > interval[-1]:
interval = interval + [max_value]

# Get frequencies
frequencies = gf.fd(per_day = per_day, target_range = target_range, count = count)
range_labels = [f'{target_range[i]}-{target_range[i+1]}' for i in range(len(target_range)-1)]
frequencies = gf.fd(per_day = per_day, interval = interval, count = count)
range_labels = [f'{interval[i]}-{interval[i+1]}' for i in range(len(interval)-1)]

fig = go.Figure()
first_day = ''
Expand Down

0 comments on commit 9813ccb

Please sign in to comment.