Cleanup documentation.
This commit is contained in:
parent
4d77fac610
commit
9f3b597f55
@ -5,17 +5,20 @@ __author__ = 'Timothy Allen'
|
|||||||
__email__ = 'tim@treehouse.org.za'
|
__email__ = 'tim@treehouse.org.za'
|
||||||
__license__ = 'MIT'
|
__license__ = 'MIT'
|
||||||
|
|
||||||
''' Included are the Noto Sans and IcoGluco font sets.
|
''' Included are the OpenSans and IcoGluco font sets.
|
||||||
Noto Sans is licensed under the SIL Open Font License version 1.1
|
IcoGluco contains fonts from Noto Sans, which is licensed under the
|
||||||
|
SIL Open Font License version 1.1
|
||||||
<http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL>,
|
<http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL>,
|
||||||
IcoGluco contains fonts from Noto Sans, as well as
|
as well as a green apple character from
|
||||||
green apple character from Vectors Market <https://www.flaticon.com/authors/vectors-market>,
|
Vectors Market <https://www.flaticon.com/authors/vectors-market>,
|
||||||
licensed under Creative Commons BY 3.0, <http://creativecommons.org/licenses/by/3.0/>, and
|
licensed under Creative Commons BY 3.0, <http://creativecommons.org/licenses/by/3.0/>, and
|
||||||
syringe and pushpin characters from FreePik, <http://www.freepik.com>,
|
syringe and pushpin characters from FreePik, <http://www.freepik.com>,
|
||||||
licensed under Creative Commons BY 3.0, <http://creativecommons.org/licenses/by/3.0/>
|
licensed under Creative Commons BY 3.0, <http://creativecommons.org/licenses/by/3.0/>.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# TODO: weekly graph with each day's figures as a different-coloured line
|
# TODO: weekly graph with each day's figures as a different-coloured line
|
||||||
|
# TODO: Split each type of charts into a separate function and offer a means
|
||||||
|
# of selecting which charts to generate
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import csv
|
import csv
|
||||||
@ -80,6 +83,10 @@ def main():
|
|||||||
for row in rows:
|
for row in rows:
|
||||||
row = parse_entry(row, args.icons)
|
row = parse_entry(row, args.icons)
|
||||||
|
|
||||||
|
''' Fill in gaps that might exist in the data, in order to smooth the curves and fills '''
|
||||||
|
''' We're using 8 minute gaps in order to have more accurate fills '''
|
||||||
|
rows = fill_gaps(rows, interval=dt.timedelta(minutes=10))
|
||||||
|
|
||||||
''' If we're on the default values for units, highs and lows, check that the average
|
''' If we're on the default values for units, highs and lows, check that the average
|
||||||
value is under 35 (assuming that average mmol/L < 35 and average mg/dL > 35) '''
|
value is under 35 (assuming that average mmol/L < 35 and average mg/dL > 35) '''
|
||||||
if args.units == UNIT_MMOLL and (args.high == DEFAULT_HIGH or args.low == DEFAULT_LOW):
|
if args.units == UNIT_MMOLL and (args.high == DEFAULT_HIGH or args.low == DEFAULT_LOW):
|
||||||
@ -92,16 +99,6 @@ def main():
|
|||||||
args.graph_max = GRAPH_MAX_MGDL
|
args.graph_max = GRAPH_MAX_MGDL
|
||||||
args.graph_min = GRAPH_MIN_MGDL
|
args.graph_min = GRAPH_MIN_MGDL
|
||||||
|
|
||||||
''' Fill in gaps that might exist in the data, in order to smooth the curves and fills '''
|
|
||||||
''' We're using 8 minute gaps in order to have more accurate fills '''
|
|
||||||
rows = fill_gaps(rows, interval=dt.timedelta(minutes=10))
|
|
||||||
|
|
||||||
''' Calculate the days and weeks in which we are interested '''
|
|
||||||
''' Note that trim_weeks should be adjusted based on the interval passed to fill_gaps() '''
|
|
||||||
(days, weeks) = list_days_and_weeks(rows, trim_weeks=300)
|
|
||||||
totalweeks = sum([len(weeks[y]) for y in weeks])
|
|
||||||
totaldays = len(days)
|
|
||||||
|
|
||||||
''' Set some defaults '''
|
''' Set some defaults '''
|
||||||
rcParams['font.size'] = 8
|
rcParams['font.size'] = 8
|
||||||
rcParams['axes.titlesize'] = 12
|
rcParams['axes.titlesize'] = 12
|
||||||
@ -116,15 +113,21 @@ def main():
|
|||||||
custom icons on IcoMoon, works around this. '''
|
custom icons on IcoMoon, works around this. '''
|
||||||
if args.icons:
|
if args.icons:
|
||||||
args.customfont = import_font('fonts/icogluco.ttf')
|
args.customfont = import_font('fonts/icogluco.ttf')
|
||||||
#args.customfont = import_font('fonts/OpenSansEmoji.ttf') # Alternate working font
|
#args.customfont = import_font('fonts/OpenSansEmoji.ttf') # Alternate font
|
||||||
|
|
||||||
|
''' Calculate the days and weeks in which we are interested '''
|
||||||
|
''' Note that trim_weeks should be adjusted based on the interval passed to fill_gaps() '''
|
||||||
|
(days, weeks) = list_days_and_weeks(rows, trim_weeks=300)
|
||||||
|
totalweeks = sum([len(weeks[y]) for y in weeks])
|
||||||
|
totaldays = len(days)
|
||||||
|
|
||||||
nrows = args.graphs_per_page
|
nrows = args.graphs_per_page
|
||||||
ncols = 1
|
ncols = 1
|
||||||
plotnum = 1
|
plotnum = 1
|
||||||
with FigurePDF(args.output_file) as pdf:
|
with FigurePDF(args.output_file) as pdf:
|
||||||
|
|
||||||
''' Overall averages for all data by hour '''
|
''' Overall averages for all data by hour of the day '''
|
||||||
title = 'Overall Average Daily Glucose Summary'
|
title = 'Overall Average Glucose Summary'
|
||||||
|
|
||||||
data = {}
|
data = {}
|
||||||
for row in rows:
|
for row in rows:
|
||||||
@ -144,7 +147,7 @@ def main():
|
|||||||
'min' : intervals.get(i).get('min'),
|
'min' : intervals.get(i).get('min'),
|
||||||
}
|
}
|
||||||
|
|
||||||
''' Calculate the mean and median blood glucose levels for the day '''
|
''' Calculate the mean and median blood glucose and HbA1c levels '''
|
||||||
(g_mean, g_median, a_mean, a_median) = calculate_averages(data, args)
|
(g_mean, g_median, a_mean, a_median) = calculate_averages(data, args)
|
||||||
|
|
||||||
figure = Figure(figsize=args.pagesize)
|
figure = Figure(figsize=args.pagesize)
|
||||||
@ -155,9 +158,10 @@ def main():
|
|||||||
figure.set_tight_layout({'pad':3})
|
figure.set_tight_layout({'pad':3})
|
||||||
|
|
||||||
''' Draw the target range '''
|
''' Draw the target range '''
|
||||||
ax.axhspan(args.low, args.high, facecolor='#0072b2', edgecolor='#a8a8a8', alpha=0.2, zorder=5)
|
ax.axhspan(args.low, args.high, facecolor='#0072b2', edgecolor='#a8a8a8', alpha=0.1, zorder=5)
|
||||||
|
|
||||||
''' The maxmined curve of maximum and minimum values '''
|
''' The maxmin curve (maximum and minimum values for each 15 minute
|
||||||
|
period of the data set, by day) '''
|
||||||
generate_plot(intervaldata,
|
generate_plot(intervaldata,
|
||||||
ax=ax,
|
ax=ax,
|
||||||
transforms={'spline':False, 'maxmin':True},
|
transforms={'spline':False, 'maxmin':True},
|
||||||
@ -166,6 +170,8 @@ def main():
|
|||||||
alpha=0.5,
|
alpha=0.5,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
''' The graph with a bezier curve applied, and a boundary transform to change line colour
|
||||||
|
above and below the target values '''
|
||||||
generate_plot(data,
|
generate_plot(data,
|
||||||
ax=ax,
|
ax=ax,
|
||||||
transforms={'bezier':True, 'avga1c':a_median, \
|
transforms={'bezier':True, 'avga1c':a_median, \
|
||||||
@ -178,7 +184,8 @@ def main():
|
|||||||
pdf.savefig(figure)
|
pdf.savefig(figure)
|
||||||
ax.clear()
|
ax.clear()
|
||||||
|
|
||||||
''' Overall averages for a week by hour '''
|
|
||||||
|
''' Overall averages for a week by hour of the dday '''
|
||||||
cnt = 0
|
cnt = 0
|
||||||
for year in reversed(sorted(weeks.keys())):
|
for year in reversed(sorted(weeks.keys())):
|
||||||
for week in reversed(sorted(weeks[year].keys())):
|
for week in reversed(sorted(weeks[year].keys())):
|
||||||
@ -187,7 +194,7 @@ def main():
|
|||||||
monday = time + dt.timedelta(days=-time.weekday(), weeks=week-1)
|
monday = time + dt.timedelta(days=-time.weekday(), weeks=week-1)
|
||||||
sunday = monday + dt.timedelta(days=6)
|
sunday = monday + dt.timedelta(days=6)
|
||||||
period = monday.strftime('%A, %-d %B %Y') + ' to ' + sunday.strftime('%A, %-d %B %Y');
|
period = monday.strftime('%A, %-d %B %Y') + ' to ' + sunday.strftime('%A, %-d %B %Y');
|
||||||
title = 'Average Daily Glucose for ' + period
|
title = 'Average Glucose for ' + period
|
||||||
|
|
||||||
weekrows = []
|
weekrows = []
|
||||||
for row in rows:
|
for row in rows:
|
||||||
@ -204,6 +211,8 @@ def main():
|
|||||||
'comment' : row.get('comment'),
|
'comment' : row.get('comment'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
''' Calculate the maximum and minimum value for each 15-minute period
|
||||||
|
of the day, across the week '''
|
||||||
intervals = calculate_max_min(weekrows)
|
intervals = calculate_max_min(weekrows)
|
||||||
intervaldata = {}
|
intervaldata = {}
|
||||||
for i in intervals:
|
for i in intervals:
|
||||||
@ -213,7 +222,7 @@ def main():
|
|||||||
'min' : intervals.get(i).get('min'),
|
'min' : intervals.get(i).get('min'),
|
||||||
}
|
}
|
||||||
|
|
||||||
''' Calculate the mean and median blood glucose levels for the day '''
|
''' Calculate the mean and median blood glucose levels for the week '''
|
||||||
(g_mean, g_median, a_mean, a_median) = calculate_averages(data, args)
|
(g_mean, g_median, a_mean, a_median) = calculate_averages(data, args)
|
||||||
|
|
||||||
if cnt % nrows == 0:
|
if cnt % nrows == 0:
|
||||||
@ -226,7 +235,7 @@ def main():
|
|||||||
figure.set_tight_layout({'pad':3})
|
figure.set_tight_layout({'pad':3})
|
||||||
|
|
||||||
''' Draw the target range '''
|
''' Draw the target range '''
|
||||||
ax.axhspan(args.low, args.high, facecolor='#0072b2', edgecolor='#a8a8a8', alpha=0.2, zorder=5)
|
ax.axhspan(args.low, args.high, facecolor='#0072b2', edgecolor='#a8a8a8', alpha=0.1, zorder=5)
|
||||||
|
|
||||||
''' The maxmined curve of maximum and minimum values '''
|
''' The maxmined curve of maximum and minimum values '''
|
||||||
generate_plot(intervaldata,
|
generate_plot(intervaldata,
|
||||||
@ -237,6 +246,8 @@ def main():
|
|||||||
alpha=0.5,
|
alpha=0.5,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
''' The graph with a bezier curve applied, and a boundary transform to change line colour
|
||||||
|
above and below the target values '''
|
||||||
generate_plot(data,
|
generate_plot(data,
|
||||||
ax=ax,
|
ax=ax,
|
||||||
transforms={'bezier':True, \
|
transforms={'bezier':True, \
|
||||||
@ -280,19 +291,20 @@ def main():
|
|||||||
''' Draw the target range '''
|
''' Draw the target range '''
|
||||||
ax.axhspan(args.low, args.high, facecolor='#0072b2', edgecolor='#a8a8a8', alpha=0.2, zorder=5)
|
ax.axhspan(args.low, args.high, facecolor='#0072b2', edgecolor='#a8a8a8', alpha=0.2, zorder=5)
|
||||||
|
|
||||||
|
''' Draw graph with a spline tranform and labels '''
|
||||||
generate_plot(data,
|
generate_plot(data,
|
||||||
ax=ax,
|
ax=ax,
|
||||||
transforms={'spline':True, 'label':True, 'avgglucose':g_median, 'avga1c':a_median},
|
transforms={'spline':True, 'label':True, 'avgglucose':g_median, 'avga1c':a_median},
|
||||||
args=args,
|
args=args,
|
||||||
color=BLUE,
|
color=BLUE,
|
||||||
|
)
|
||||||
|
|
||||||
)
|
''' Fill the chart with colour when line is higher or lower than target range '''
|
||||||
''' For max higher than target high '''
|
|
||||||
generate_plot(data,
|
generate_plot(data,
|
||||||
ax=ax,
|
ax=ax,
|
||||||
transforms={'spline':True, 'fill':True},
|
transforms={'spline':True, 'fill':True},
|
||||||
args=args,
|
args=args,
|
||||||
)
|
)
|
||||||
|
|
||||||
''' Save the graph to the output PDF if we're at the end of the page '''
|
''' Save the graph to the output PDF if we're at the end of the page '''
|
||||||
if (cnt + 1) % nrows == 0 or (cnt + 1) == totaldays:
|
if (cnt + 1) % nrows == 0 or (cnt + 1) == totaldays:
|
||||||
@ -367,7 +379,7 @@ def generate_plot(data, ax=None, transforms={}, args=[], **plot_args):
|
|||||||
else:
|
else:
|
||||||
maxmin = False
|
maxmin = False
|
||||||
|
|
||||||
''' Process points to apply smoothing and other fixups '''
|
''' Transform points to apply smoothing and other fixups '''
|
||||||
for transform in transforms:
|
for transform in transforms:
|
||||||
if transform == 'linear' and transforms.get(transform) is True:
|
if transform == 'linear' and transforms.get(transform) is True:
|
||||||
''' Use SciPy's interp1d for linear transforming '''
|
''' Use SciPy's interp1d for linear transforming '''
|
||||||
@ -379,10 +391,11 @@ def generate_plot(data, ax=None, transforms={}, args=[], **plot_args):
|
|||||||
|
|
||||||
elif transform == 'spline' and transforms.get(transform) is True:
|
elif transform == 'spline' and transforms.get(transform) is True:
|
||||||
''' Use SciPy's UnivariateSpline for transforming (s is transforming factor) '''
|
''' Use SciPy's UnivariateSpline for transforming (s is transforming factor) '''
|
||||||
|
''' An s of 8 (mmol/L) or 200 (mg/dL) was chosen by experimentation! '''
|
||||||
if args.units == UNIT_MMOLL:
|
if args.units == UNIT_MMOLL:
|
||||||
s = 8
|
s = 8
|
||||||
else:
|
else:
|
||||||
s = convert_glucose_unit(12, UNIT_MMOLL)
|
s = 200
|
||||||
if not maxmin:
|
if not maxmin:
|
||||||
curve = interpolate.UnivariateSpline(x=x, y=y, k=3, s=s)
|
curve = interpolate.UnivariateSpline(x=x, y=y, k=3, s=s)
|
||||||
y = curve(x)
|
y = curve(x)
|
||||||
@ -399,7 +412,7 @@ def generate_plot(data, ax=None, transforms={}, args=[], **plot_args):
|
|||||||
|
|
||||||
''' The binomial calculation for the bezier curve overflows with arrays of 1020 or more elements,
|
''' The binomial calculation for the bezier curve overflows with arrays of 1020 or more elements,
|
||||||
For large arrays, get a smaller slice of the full array.
|
For large arrays, get a smaller slice of the full array.
|
||||||
Do this by removing every nth element from the array '''
|
Do this by removing every nth element from the array. '''
|
||||||
n = 5
|
n = 5
|
||||||
while len(x) > 1000:
|
while len(x) > 1000:
|
||||||
x = np.delete(x, np.arange(0, len(x), n), axis=0)
|
x = np.delete(x, np.arange(0, len(x), n), axis=0)
|
||||||
@ -409,21 +422,22 @@ def generate_plot(data, ax=None, transforms={}, args=[], **plot_args):
|
|||||||
curve = np.array([c for _, c in bezier(np.array([x,y]).T, 250)])
|
curve = np.array([c for _, c in bezier(np.array([x,y]).T, 250)])
|
||||||
(x, y) = (curve[:,0], curve[:,1])
|
(x, y) = (curve[:,0], curve[:,1])
|
||||||
|
|
||||||
''' Add the mean or median glucose and A1c values '''
|
''' Add the mean or median glucose and A1c values in an annotation box '''
|
||||||
if transform == 'avgglucose' and isinstance(transforms.get(transform), (int, float)):
|
if transform == 'avgglucose' and isinstance(transforms.get(transform), (int, float)):
|
||||||
if args.units == UNIT_MMOLL:
|
if args.units == UNIT_MMOLL:
|
||||||
gmtext = 'Median glucose: %.1f%s' % (round(transforms.get('avgglucose'), 1), args.units)
|
gmtext = 'Median glucose: %.1f%s' % (round(transforms.get('avgglucose'), 1), args.units)
|
||||||
else:
|
else:
|
||||||
gmtext = 'Median glucose: %.0f%s' % (round(transforms.get('avgglucose'), 1), args.units)
|
gmtext = 'Median glucose: %.0f%s' % (round(transforms.get('avgglucose'), 1), args.units)
|
||||||
|
|
||||||
ax.annotate(gmtext, fontsize=9, \
|
ax.annotate(gmtext, fontsize=9, xy=(0.95, 0.85),
|
||||||
xy=(0.95, 0.85), xycoords='axes fraction', verticalalignment='top', horizontalalignment='right', \
|
xycoords='axes fraction', verticalalignment='top', horizontalalignment='right',
|
||||||
zorder=40, bbox=dict(facecolor=GREEN, edgecolor='#009e73', alpha=0.7, pad=8), \
|
zorder=40, bbox=dict(facecolor=GREEN, edgecolor='#009e73', alpha=0.7, pad=8),
|
||||||
)
|
)
|
||||||
if transform == 'avga1c' and isinstance(transforms.get(transform), (int, float)):
|
if transform == 'avga1c' and isinstance(transforms.get(transform), (int, float)):
|
||||||
ax.annotate('Median HbA1c: %.1f%%' % round(transforms.get('avga1c'), 1), fontsize=9, \
|
ax.annotate('Median HbA1c: %.1f%%' % round(transforms.get('avga1c'), 1), fontsize=9,
|
||||||
xy=(0.05, 0.85), xycoords='axes fraction', verticalalignment='top', horizontalalignment='left', \
|
xy=(0.05, 0.85), xycoords='axes fraction',
|
||||||
zorder=40, bbox=dict(facecolor=BOXYELLOW, edgecolor='#e69f00', alpha=0.7, pad=8), \
|
verticalalignment='top', horizontalalignment='left',
|
||||||
|
zorder=40, bbox=dict(facecolor=BOXYELLOW, edgecolor='#e69f00', alpha=0.7, pad=8),
|
||||||
)
|
)
|
||||||
|
|
||||||
if args.units == UNIT_MMOLL:
|
if args.units == UNIT_MMOLL:
|
||||||
@ -434,14 +448,13 @@ def generate_plot(data, ax=None, transforms={}, args=[], **plot_args):
|
|||||||
if transform == 'label' and transforms.get(transform) is True and args.icons is True:
|
if transform == 'label' and transforms.get(transform) is True and args.icons is True:
|
||||||
for x_pos, y_pos, label in zip(x, y, z):
|
for x_pos, y_pos, label in zip(x, y, z):
|
||||||
if isinstance(label, dict) and len(label) > 0:
|
if isinstance(label, dict) and len(label) > 0:
|
||||||
symbol = ''
|
|
||||||
symbol = '$'
|
symbol = '$'
|
||||||
for key in label:
|
for key in label:
|
||||||
''' In the included IcoGluco font use for args.customfont,
|
''' In the included IcoGluco font use for args.customfont,
|
||||||
\N{SYRINGE} is a straight syringe (from FreePik),
|
\N{SYRINGE} is a straight syringe (modified from FreePik) for rotated labels,
|
||||||
\N{PUSHPIN} is a an angled syringe (from FreePik),
|
\N{PUSHPIN} is a an angled syringe (from FreePik) for horizontal labels,
|
||||||
\N{DAGGER} is unused,
|
\N{DAGGER} is unused (reserved a different syringe icon),
|
||||||
\N{GREEN APPLE} is an apple (from Vectors Market. '''
|
\N{GREEN APPLE} is an apple (from Vectors Market). '''
|
||||||
if key == 'Insulin':
|
if key == 'Insulin':
|
||||||
if isinstance(label.get(key), str):
|
if isinstance(label.get(key), str):
|
||||||
symbol += '\N{SYRINGE}^{%s}' % label.get(key)
|
symbol += '\N{SYRINGE}^{%s}' % label.get(key)
|
||||||
@ -452,13 +465,9 @@ def generate_plot(data, ax=None, transforms={}, args=[], **plot_args):
|
|||||||
elif key == 'Food':
|
elif key == 'Food':
|
||||||
symbol += '\N{GREEN APPLE}'
|
symbol += '\N{GREEN APPLE}'
|
||||||
symbol += '$'
|
symbol += '$'
|
||||||
ax.annotate(
|
ax.annotate(symbol, xy=(x_pos, args.graph_max-y_offset),
|
||||||
symbol,
|
rotation=45, zorder=25, fontsize=10,
|
||||||
xy=(x_pos, args.graph_max-y_offset),
|
fontproperties=args.customfont,
|
||||||
rotation=45,
|
|
||||||
zorder=25,
|
|
||||||
fontsize=10,
|
|
||||||
fontproperties=args.customfont,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
''' Create a line coloured according to the list in transforms['color'] '''
|
''' Create a line coloured according to the list in transforms['color'] '''
|
||||||
@ -493,8 +502,8 @@ def generate_plot(data, ax=None, transforms={}, args=[], **plot_args):
|
|||||||
|
|
||||||
def import_font(fontname):
|
def import_font(fontname):
|
||||||
''' Turns a relative font path into a matplotlib font property. '''
|
''' Turns a relative font path into a matplotlib font property. '''
|
||||||
basedir = os.path.dirname(os.path.abspath(__file__))
|
basedir = os.path.dirname(os.path.abspath(__file__))
|
||||||
fontpath = os.path.join(basedir, fontname)
|
fontpath = os.path.join(basedir, fontname)
|
||||||
if not os.path.exists(fontpath):
|
if not os.path.exists(fontpath):
|
||||||
raise UserError("Font %s does not exist" % fontpath)
|
raise UserError("Font %s does not exist" % fontpath)
|
||||||
prop = fm.FontProperties(fname=fontpath)
|
prop = fm.FontProperties(fname=fontpath)
|
||||||
@ -516,13 +525,13 @@ def parse_entry(data, icons, fmt='%Y-%m-%d %H:%M:%S'):
|
|||||||
'''
|
'''
|
||||||
if icons:
|
if icons:
|
||||||
''' Ignore comments that aren't relevant '''
|
''' Ignore comments that aren't relevant '''
|
||||||
rrelevant = re.compile('(Food|Rapid-acting insulin|Long-acting insulin)(?: \((.*?)\))', flags=re.IGNORECASE)
|
rrelevant = re.compile('(Food|Rapid-acting insulin|Long-acting insulin)(?: \((.*?)\))', flags=re.IGNORECASE)
|
||||||
rduplicate = re.compile('^(I\$\^\{\d+\S?)(\}.*)$')
|
rduplicate = re.compile('^(I\$\^\{\d+\S?)(\}.*)$')
|
||||||
commentparts = {}
|
commentparts = {}
|
||||||
for part in data.get('comment').split('; '):
|
for part in data.get('comment').split('; '):
|
||||||
relevant = rrelevant.search(part)
|
relevant = rrelevant.search(part)
|
||||||
if relevant is not None:
|
if relevant is not None:
|
||||||
ctype = relevant.group(1)
|
ctype = relevant.group(1)
|
||||||
cvalue = relevant.group(2)
|
cvalue = relevant.group(2)
|
||||||
|
|
||||||
''' Convert floating point-style strings (2.0) to integer-style strings (2) '''
|
''' Convert floating point-style strings (2.0) to integer-style strings (2) '''
|
||||||
@ -828,6 +837,9 @@ def convert_glucose_unit(value, from_unit, to_unit=None):
|
|||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
exceptions.InvalidGlucoseUnit: If the parameters are incorrect.
|
exceptions.InvalidGlucoseUnit: If the parameters are incorrect.
|
||||||
|
Note that this is defined by the main glucometerutils package, from which
|
||||||
|
this function is duplicated, and is not a valid exception for this script.
|
||||||
|
So let's hope it doesn't get triggered!
|
||||||
"""
|
"""
|
||||||
if from_unit not in VALID_UNITS:
|
if from_unit not in VALID_UNITS:
|
||||||
raise exceptions.InvalidGlucoseUnit(from_unit)
|
raise exceptions.InvalidGlucoseUnit(from_unit)
|
||||||
|
Loading…
Reference in New Issue
Block a user