Wednesday, July 20, 2016

Some very short code snippets: Nightscout and the Windows Deskop.

In this post I will provide a few code snippets that could be useful if you want to monitor SGV values stored in a MLAB database. In this case, the Windows desktop.

Just a few words of warnings

  • you'll need a mlab database with current sgv values (either through direct upload or through a full Nighscout install.
  • you'll need a minimal understanding of what a program is, how to install Python on your computer and how to edit source code with your own parameters.
  • the examples given below are absolutely minimal and provide no error checking. I just rewrote them from a bigger, more complex program I wrote and use.
  • I won't have the time to answer python questions. :)
What we need is simply
  • get value(s) from the database
  • create a bitmap we want as a background with the SGV data on it
  • force windows to update our background
And we'll get something like this 



How to connect to mongo and get one recent result


# import the required package to connect to mongodb
from pymongo import MongoClient
# not really needed, but will help if you don't want to display the full length date
import dateutil.parser as dup
# will allow us to get the time
import time
# database connection setup - your own user, password, port and db should be here
# there are other ways to connect to the db, this is just one example
uri = "mongodb://youruser:yourpassword@ds099999.mlab.com:99999/yourdb?authMechanism=SCRAM-SHA-1"
# open the connection to the database
client = MongoClient(uri)
# set the database we want to use (must be your db name)
db = client['yourdb']
# set the collection we need (must be your collection name)
entries = db['entries']
# lets set the time to now - 300 seconds (we want to check if we have a value in the last 5 mins)
# python uses time stamps in seconds, javascript uses time stamps in miliseconds, hence the *1000
starttime = (time.time()-300)*1000
# we query the db for a value after now - 300 seconds
cursor = db.entries.find({"date": {"$gt": starttime}})
# check that we have a result, we don't always
if cursor.count() > 0:
    for i in cursor:
        # check if it is a sgv value, it could be a calibration record, or anything else
        # we could also query a value satisfying both conditions sgv present and time greater 
        # than now minus 300 sec but the query above would be less obvious in a tutorial
        if 'sgv' in i:
            # print the content of the record
            print('SGV', i['sgv'], 'at', dup.parse(i['dateString']).strftime('%H:%M'))
        else:
            print('No SGV data found')
else:
    print("No result found")

How to create bitmaps for backgrounds and activate them


# required for image manipulation
from PIL import Image, ImageDraw, ImageFont
# required for API calls
import ctypes
# my screen resolution is 3440 pixels wide and 1440 pixels high
# it could be different from yours
w = 3440
h = 1440
# these are the coordinates where I want to plot my text
xt = 2500
yt = 1300

# these are for the windows API command for "set wallpaper"
SPI_SETDESKWALLPAPER = 20  
SPI_FORCEUPDATE = 2

# this is my current background, I want to keep a clean copy
bgsource = 'c:/temp/iceflow.jpg'
# this is the background I am planning to display
bgdest = 'c:/temp/mybg.jpg'
# the windows API required string style
APIpath = r'c:\temp\mybg.jpg'
# this is the font I want to use, make sure you download it or 
# use any other font of your computer
font = 'c:/temp/FreeMono.ttf'
fsize = 100
imagemode = 'RGBA'

# I could also generate my own background
# background = bytes([81, 92, 107, 255]*w*h)
# base = Image.frombytes(imagemode, (w, h), background)

# but we use the image above image
base = Image.open(bgsource).convert(imagemode)

# make a blank image for the text, initialized to transparent text color
# we will superpose that image on our normal background
# it works like layers in Photoshop
txt = Image.new(imagemode, base.size, (255,255,255,0))
# get a font
fnt = ImageFont.truetype(font, fsize)
# get a drawing context to the layer we just created
d = ImageDraw.Draw(txt)
# draw some text, half opacity
d.text((xt,yt), "This is a test", font=fnt, fill=(255,255,255,128))
# mix the two images
# it's a merge of layers in Photoshop
out = Image.alpha_composite(base, txt)
# update the background bitmap
out.save(bgdest)
# windows API call on recent systems - this should force a background reset
# to our image
ctypescallresult = ctypes.windll.user32.SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, APIpath, SPI_FORCEUPDATE)

An additional test


The windows API can be capricious, depending on the version you have (64 or 32 bits), the simplest way to test it is to try setting up your background to an image already present on your computer

import ctypes

# see this link for more information
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms724947%28v=vs.85%29.aspx

SPI_SETDESKWALLPAPER = 20  # this is the windows command for set wallpaper
SPI_FORCEUPDATE = 2
# this is our background file
APIpath = r'c:\temp\iceflow.jpg'

ctypescallresult = ctypes.windll.user32.SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, APIpath, SPI_FORCEUPDATE)

The logic


Putting it all together, a minimal program would go like this

get a value, update the background, calculate when to request the next value and, from that point, loop indefinitely, creating the image and updating the background whenever a new value arrives (every five minutes).

That's it - dead easy. Left as an exercise for the reader. 



Monday, July 4, 2016

Global screening - take 2 - doubling down.

Since my previous post triggered some poor responses (especially by mail) and I am a guy that's always willing to be on the receiving end of a good beating, let's take another angle.The purpose of widespread finger pricking is to avoid late diagnosis and save lives. Definitely a commendable goal. The question here is essentially

"how do we improve the initial diagnosis so we can avoid death by DKA at or near diagnosis time"


That is a valid question, and everyone would like to diminish the mortality/morbidity toll, even if it is not very large.

A few additional numbers


There were roughly 208.000 practicing primary care physicians in the US in 2009-2010 (reference U.S. Department of Health & Human Services)


There were 18.436 under twenty diagnosed with Type 1 diabetes in 2008-2009 (reference Center for Disease Control), roughly 30.000 if one includes adults.


Assuming all diagnosis are made by primary case physicians, which would be a wildly optimistic view and precisely the issue promoters of the "blood test for everyone" idea would like to address, that means that our hypothetical average primary care physician is confronted with a diagnosis situation once every 11.28 years in an under twenty kid and once every 6.93 years for the whole population. If the diagnosis is missed in 50% of the cases, double those numbers.

On average, this means that what was, for you, one of the single most important event of your life is an extremely rare occurrence for the physician you encountered. A GP will probably remember forever the 3 or 4 initial T1D diagnosis he made over his career.


Would additional training help dealing with such a rare event? To be honest, I am not sure.



Assume I am a genius

I've already talked about how hard it would be to diagnose T1D based on a single BG Meter reading. Let's however assume that I am a genius, Theranos style, and that I invent a method that, with a single cheap finger prick is almost perfect at diagnosing Type 1 Diabetes before the patient falls in DKA. I can already imagine how my TED talk would go: a summary of the issue, a couple of dramatic images of immensely cute kids killed or handicapped by severe DKA, the description of how my almost perfect method works, simultaneously dosing all antibodies, blood sugar and eventual other markers of Beta cells demise. I'll conclude my speech with the image of a cute healthy kid walking an open path, symbolizing his bright future, in a nice postcard landscape. Then, I will enjoy the standing ovation.

My perfect test would be the perfect solution to the problem, right?


Wrong!

But things aren't as bright as they seem.

Imagine my test is essentially perfect at finding all Type 1 Diabetics (in other word 100% sensitive) and almost perfect at detecting Type 1 Diabetics in a general population. We'll say that it is 99.9% specific, which means that it will only flag 0.1% of the healthy population as having Type 1 Diabetes.

100% sensitivity and 99.9% specificity are unheard of in the area of biological testing, but hey, I told you we are assuming I am a genius...

Let's now apply this test to the 320.000.000 yearly primary care under twenty visits in the US that we estimated earlier. We can drop the visits by identified type 1 diabetics, they wouldn't do the test anyway and assume that we score 100% detection on the 18.436 unidentified Type 1 Diabetics.

Let's again be generous with numbers and assume that out of these 320.000.000 visits, 20.000.000 are by known T1Ds and that, again 150.000.000 of the remaining visits are clear enough that they don't require any kid of testing (but of course, the GP could be wrong here as well)

My "almost perfect" test would still flag 0.1% of those healthy visits as definitely Type 1 Diabetics (for example because of the presence of similar molecules).

The scoreboard would now look like this.

  • 18.436 T1Ds correctly and immediately diagnosed.
  • 150.000 non T1D patients wrongly identified as T1Ds
One other way of looking at my perfect test would be to say that it is wrong 89% of the time and correct 11% of the time.
If a BG meter was correct 99% of the time, it would miss 184 real Type 1 Diabetics and flag no less than 1.500.000 visits as probable Type 1 Diabetics.

Of course in real life, things don't work that way, and fortunately so. Your MD is not a total idiot. He would put results in context, retest any suspicious results. But that would not prevent a lot of useless double checks and additional procedures carried out on non T1D people.

So much for that bright idea... I am not a genius and, even if I was, it wouldn't work too well.

The narrative "We did a BG meter test, found 450 mg/dL, double checked and saved the life of the kid" is extremely seductive but quite unlikely in practice. The odds are slightly higher than winning a significant payout at a lottery, but not high. And it will come at the cost of a lot of false positives which will also cause worries and distress to the falsely suspect kid, put his family under stress and trigger automatic additional tests (maybe a day off at work?) or investigations that carry their own risks.


Back of the envelopes computations certainly aren't the final word. They certainly do not prove that the system can not be improved. But they can definitely prove that something like a car will not fly to the moon...

Sunday, July 3, 2016

Would a finger prick with each pediatric visit make sense?

The Internet and social networks are huge amplifiers. T1D communities, once you get to know them, are among the worst offenders... When they aren't busy lynching restaurant owners for signs asking diabetic patients no to inject themselves in public or attacking some minor public person who confused T2D with T1D, they busy themselves with a "fingerpricks for every kid" crusade.

Does that idea even remotely make sense? Here is some food for thought...

Using 2009 figures, around 30.000 persons were diagnosed with diabetes in the USA. A ballpark estimate is that out of those 30.000 patients, 2/3rd are under the age of 20. This matches the official tally that was, for that period

"During 2008–2009, an estimated 18,436 people younger than 20 years in the United States were newly diagnosed with type 1 diabetes annually..."

Severe DKA is generally present, on average, in 25% of those patients. The percentage can go as high as 50% for kids in the 0-4 yo range, is a bit lower in girls than in boys and, of course, varies with care accessibility, insurance coverage, education level, etc...

Let's say that 4750 of the 18436 patients above were in severe DKA (as opposed to mild, safely correctable DKA which is probably present in another 25%)

The approximate rate of death and extremely severe complications from DKA is between 5 and 2% depending again on socio economic and access issues. If we take a value of 3%, we end up with around 150 tragic deaths per year.

Yes, the rate of T1D diagnosis has increased, US is closer to 40.000 yearly diagnosis now. But, on the other hand, death by DKA has been on the decrease since a long time. Yes, improvements are also made there;

"from 1985 to 2002, age-adjusted death rates for hyperglycemic crisis decreased from 42.4 to 23.8 per 100,000 people with diabetes, a 4.4% decrease per year"

Total yearly deaths by DKA (all ages, all causes) seem to hover in the 2500 range. Going back to our earlier estimate, we'd end up with 150 yearly deaths around diagnosis and 2350 yearly DKA deaths during the rest of the life or a T1D (pump failures, not caring, no access, etc...)

Keep in mind that out of those 150 deaths, we have parents who simply "prayed" their kid would get better, parents who weren't covered by social security and were reluctant to see a doctor, kids who fell into DKA and were correctly and immediately diagnosed and some - which could be seen as the "misdiagnosed" and "problematic" ones. It is hard to say how many, but it is nonetheless a subset of 150.

I'll be very generous and use the following split: 50 did not see a doctor soon enough, 50 did and were immediately diagnosed, 50 did and some mistake occurred. Let's say that the doctor flipped a coin in all cases. I think we can assume this as a worst case scenario.

Would a finger prick avoid any of those 50 deaths?


How quickly does DKA develop? In our case, Max was playing a game of tennis against as stronger adult player on day minus one. He lost 6-4 6-4, hardly a severe beating. He wasn't looking his best, but still spent time chatting and drinking a coke with his opponent after the game. The following day, he was on the edge of consciousness...

The clinical presentation of DKA usually develops rapidly, over a period of  less than 24 hours.<24 hours="" i="">


Ah, that's a bit annoying... It could be that a finger prick done a week before would have shown elevated by not critical blood sugar values, that would have been hard to interpret if not done after a night of fast. Type 1? Type 2? Post meal?

There's a reason why diagnosis criteria for T2D require at least a couple of venous blood values in the fasting state...

Now, people who complain about finger prick tests not being systematically done with every pediatric visit are often people who complain about their BG meter being inaccurate. Logically, a single test shouldn't be taken at face value. Anyway, maybe they just like to complain...

How many finger pricks?


The under twenty population of the USA is around 80.000.000. The average American, all ages groups, sees a doctor 3 times a year (900.000.000 yearly visits). That's low compared to countries such as Japan (13 times a year) or France (6-7 times a year) and has been linked to the cost of care in the US.

We can also assume that kids in the 0-20 range see their doctors more than the average. I will be very conservative here and estimate that they have 4 visits per year on average. We "only" have 320.000.000 of visits to deal with. Assuming 1/2 of those visits are for the typical gastro-intestinal/infection/flu/etc... pediatric visit, we are talking about 160.000.000 visits and probably a bit more than 200.000.000$ in finger prick strips.

That 200.000.000$ would eventually buy us a few hours, possibly a day for the 50 kids who would have been misdiagnosed at the first visit, possibly - let's again be generous here - saving 25 kids.

Cost per kid saved: roughly 8 million dollars.

But the story does not end here...


Let's say that those 25 kids in the 250-500 mg/dl - something is definitely wrong here - ranges are "saved". What about the vast majority of the others, in the 100 mg/dl to 250 mg/dl range? Those would of course end up being investigated further. Hard to tell if they were fasting, just had a large ice cream, are pre T2D or T2D. More visits. More tests.

And what about false positives? A decent BG meter will perform, on average, within a +/-5% to +/-7% MARD but will have occasional outliers (because of strip issues, procedural issues or just bad luck). Let's assume that we only have one outlier out of 50 measurements, one half way too low and on half way too high: we'll have 3.2 millions outliers and 1.6 millions of false positive values.

So let's summarize


  • around 25 lives saved, at most.
  • 8 millions of $ per life saved, for a total of 200 millions of dollars
  • 1.6 millions of false positive deserving at least a couple of additional tests/visits or, because mistakes will also happen there, extensive additional exploration.

Worth it?