FHIR Chat · Encoding artificial pancreas decision data · implementers

Stream: implementers

Topic: Encoding artificial pancreas decision data


view this post on Zulip Sulka Haro (Jun 14 2019 at 08:25):

I'm looking at how decision data from artificial pancreas systems could be encoded using FHIR. Each one of the systems provides a different set of data regarding the decision that has been made, ranging from the device status at the point of the decision having been made (insulin reservoir status, battery status etc) to calculated insulin on board, the decision that was made (dose more / dose less / do nothing / alarm user) and data regarding the predictive mode estimates for how the blood glucose levels will behave in the near future. Looking at the R4 spec, this looks like a use case that's somewhat outside the scope of the current spec, where it could be argued the system is a Device, but possibly also a Practitioner? Another point of consideration is storing predictions, which is not covered by the current spec. Depending on system used, these status messages are produced 1-2 times / 5 minute interval (1 or 2 updates for each continuous glucose monitor data point), with future systems potentially producing 1 update / minute.

The two use cases for storing the data would be both analysis of the decision data (so structured format is needed), but also potentially clinical use where a healthcare professional might want to access a visualization of the decision data along with separately stored blood glucose, insulin and carbohydrate consumption Observation and MedicationAdministration records. For the latter, it might be the easiest solution to store a textual description of the decision along with a generated image (so expert system visual generator is not needed at the moment of information display).

Here's a sample output from one system, to give you an idea of the amount of information per update:

{
    "device": "<redacted>",
    "openaps": {
        "iob": {
            "iob": 0.88,
            "activity": 0.0042,
            "basaliob": -0.179,
            "bolusiob": 1.059,
            "netbasalinsulin": -0.05,
            "bolusinsulin": 1.2,
            "iobWithZeroTemp": {
                "iob": 0.93,
                "activity": 0.0043,
                "basaliob": -0.129,
                "bolusiob": 1.059,
                "netbasalinsulin": 0,
                "bolusinsulin": 1.2,
                "time": "2019-06-14T07:24:41.000Z"
            },
            "lastBolusTime": 1560494766000,
            "lastTemp": {
                "rate": 0.8,
                "timestamp": "2019-06-14T10:12:13+03:00",
                "started_at": "2019-06-14T10:12:13+03:00",
                "date": 1560496333000,
                "duration": 13.54
            },
            "timestamp": "2019-06-14T07:24:41.000Z"
        },
        "suggested": {
            "temp": "absolute",
            "bg": 142,
            "tick": "+13",
            "eventualBG": 140,
            "insulinReq": 0.13,
            "reservoir": "13.8",
            "deliverAt": "2019-06-14T07:24:50.208Z",
            "sensitivityRatio": 1.04,
            "predBGs": {
                "IOB": [142, 154, 164, 172, 179, 184, 188, 190, 191, 191, 189, 186, 182, 177, 173, 169, 165, 161, 157, 153, 150, 146, 143, 140, 136, 134, 131, 128, 125, 123, 120, 118, 116, 114, 112, 110, 109, 107, 105, 104, 103, 101, 100, 99, 98, 97, 96, 95],
                "ZT": [142, 138, 135, 131, 126, 122, 118, 114, 110, 106, 103, 99, 96, 93, 90, 88, 86, 84, 83, 82, 81, 80, 80, 80, 81, 81, 82, 83, 85, 86, 88, 90, 93],
                "COB": [142, 154, 164, 173, 181, 187, 192, 196, 199, 200, 200, 199, 197, 194, 190, 186, 182, 178, 174, 170, 167, 163, 160, 157, 154, 151, 148, 145, 142, 140, 138, 135, 133, 131, 129, 127, 126, 124, 122, 121, 120, 118, 117, 116, 115, 114, 113, 112],
                "UAM": [142, 154, 165, 175, 183, 190, 197, 202, 207, 210, 213, 214, 215, 215, 214, 212, 209, 206, 202, 198, 195, 191, 188, 185, 181, 178, 176, 173, 170, 168, 165, 163, 161, 159, 157, 155, 154, 152, 150, 149, 147, 146, 145, 144, 143, 142, 141, 140]
            },
            "COB": 12,
            "IOB": 0.88,
            "reason": "COB: 12, Dev: 5.5, BGI: -0.2, ISF: 9.1, CR: 17, Target: 5.2, minPredBG 6.4, minGuardBG 6.8, IOBpredBG 5.3, COBpredBG 6.2, UAMpredBG 7.8;  insulinReq 0.13. temp 0.8 >~ req 0.725U/hr. ",
            "timestamp": "2019-06-14T07:24:50.000Z"
        },
        "enacted": {
            "insulinReq": 0.16,
            "received": true,
            "bg": 101,
            "reservoir": "13.975",
            "temp": "absolute",
            "rate": 0.8,
            "reason": "COB: 17, Dev: 4.7, BGI: -0.1, ISF: 9.1, CR: 17, Target: 5.2, minPredBG 6.7, minGuardBG 6.2, IOBpredBG 2.4, COBpredBG 6.8, UAMpredBG 6.3;  insulinReq 0.16. no temp, setting 0.8U/hr. ",
            "IOB": 0.878,
            "sensitivityRatio": 1.04,
            "COB": 17,
            "eventualBG": 123,
            "timestamp": "2019-06-14T07:12:15.000Z",
            "duration": 30,
            "tick": "+15",
            "deliverAt": "2019-06-14T07:12:09.773Z"
        }
    },
    "pump": {
        "clock": "2019-06-14T10:24:41+03:00",
        "battery": {
            "status": "normal",
            "voltage": 1.39
        },
        "reservoir": 13.8,
        "status": {
            "status": "normal",
            "bolusing": false,
            "suspended": false,
            "timestamp": "2019-06-14T07:24:29.000Z"
        }
    },
    "uploader": {
        "batteryVoltage": 4090,
        "battery": 91
    },
    "created_at": "2019-06-14T07:27:15.699Z",
    "utcOffset": 0
}

view this post on Zulip Jason Walonoski (Jun 14 2019 at 13:34):

The system is definitely a Device and not a Practitioner.

A Practitioner is a person (or rarely a service animal).

view this post on Zulip Sulka Haro (Jun 14 2019 at 13:44):

A Practitioner is a person (or rarely a service animal).

Is this the general guideline for all artificial intelligence that makes treatment decisions? ;)

view this post on Zulip Lloyd McKenzie (Jun 14 2019 at 14:47):

Yes. Devices can be software and can absolutely make decisions. (Responsibility tends to cascade up the chain to the organization that made the software or that manages the device.) All of the point-in-time measurements (statuses, blood sugar levels, etc.) would be Observations. The decisions taken could be represented in a few different ways. Alerts would be Communications. Adjustments to dosing would be MedicationAdministrations (if you're actually changing the dose) or MedicationRequest (if you're specifying a target dose that something else will then need to execute). In terms of forecasting, that's a really interesting question. My leaning would be to use Observation - where the code clearly indicates that you're doing a forecast. The alternative would be a modifier extension on Observation that indicates the Observation is a forecast. The effectiveTime would be the date at which the anticipated result would be expected. (And you could use components to capture confidence levels, etc.)

You are correct that this isn't a use-case we've tried to handle before (or at least not one I've seen brought up here), so feel free to push back if things don't seem like they're working quite right.

view this post on Zulip Michael Lawley (Jun 14 2019 at 16:29):

I would expect the effectiveTIme to be the time that the prediction is being made, and then you'd have one of the components carry the time that you're predicting for.
Perhaps there is also a need for LOINC codes to cover predicted BGLs (including the specific algorithm?) @Daniel Vreeman

view this post on Zulip Grahame Grieve (Jun 14 2019 at 21:35):

@Mikael Rinnetmäki I think you've already done all this

view this post on Zulip Mikael Rinnetmäki (Jun 15 2019 at 05:09):

Thanks for the ping @Grahame Grieve. No, I haven't yet done this in that detailed level. In fact, we're doing this together with @Sulka Haro . We have the easy parts, like each measurement from a Continuous Glucose Monitor is an Observation, and each dosing is a MedicationStatement (when we get the data from the pump).

Thanks for input @Lloyd McKenzie. The dosing decision from the APS algorithm should in fact be a MedicationStatement (or a MedicationRequest?), hadn't thought of that. The pump then details in MedicationStatement what was actually delivered. And forecasts being Observations, that's an interesting thought too.

In my view, most of the data in Sulka's example are DeviceMetric stuff.

view this post on Zulip Mikael Rinnetmäki (Jun 15 2019 at 05:12):

it might be the easiest solution to store a textual description of the decision along with a generated image (so expert system visual generator is not needed at the moment of information display).

I would definitely not store an image with each decision (around 288 pieces per day). I'd expect an expert system to be present when a Practitioner is inspecting the data at this level.

view this post on Zulip Jose Costa Teixeira (Jun 15 2019 at 07:45):

DeviceMetric could also hold the forecasts - it is after all something that a device is producing.
Dosing decision should be medicationRequest. Actual administration, if for each administration, should not be a MedicationStatement but a MedicationAdministration.

view this post on Zulip Lloyd McKenzie (Jun 15 2019 at 13:28):

@Michael Lawley the effective Time is when the Observation holds true. There's a different element for when the assertion was made.

view this post on Zulip Lloyd McKenzie (Jun 15 2019 at 13:31):

@Mikael Rinnetmäki MedicationStatement is generally a summary of what's happened. If we were tracking an iv, every adjustment would be a Medication Administration. I don't see why this would be any different.

view this post on Zulip Mikael Rinnetmäki (Jun 15 2019 at 13:49):

My mistake, we do use MedicationAdministration.

view this post on Zulip Mikael Rinnetmäki (Jun 15 2019 at 13:50):

For what the pump did administer.

view this post on Zulip Grahame Grieve (Jun 15 2019 at 19:02):

ok thanks. this is a good and interesting question. I will ask on the OO topic what the intention is for calibration data and device data associated with an observation

view this post on Zulip Grahame Grieve (Jun 15 2019 at 19:06):

https://chat.fhir.org/#narrow/stream/179256-Orders-and.20Observation.20WG/topic/Device.20and.20Calibration.20Data

view this post on Zulip Michael Lawley (Jun 15 2019 at 23:32):

@Lloyd McKenzie Do you mean issued. That didn't seem right to me; it seems to encode time of receipt of the Observation, not time of making the Observation.

I do see this as being when the Observation holds true, but in this case the thing that hold true is *not * an actual BGL but a predicted BGL.

I'm seeing it as there is a point in time T where the algorithm makes multiple predictions, for a series of future time points T+i, about future BGLs. This would result in a set Observations, each with the same effectiveTime but different times in the component. issued would be used for when these predictions arrive in the end system (e.g., Nightscout), which might be delayed as the physical device running the algorithm (e.g., an OpenAPS rig) may be offline while this is happening.

view this post on Zulip Lloyd McKenzie (Jun 17 2019 at 00:46):

Issued is the time the Observation is made. EffectiveTime is when it's deemed to hold true. Typically Observation . issued is the same as or earlier than the EffectiveTime. For example with blood tests the effectiveTime is when the blood is drawn. Issued might be several days later after a culture is done. Observation doesn't track when it's received. (The same instance might be received by different systems at different times.)

view this post on Zulip Lloyd McKenzie (Jun 17 2019 at 00:50):

In this case issued would be when the predictions are made and effectiveTime would be when the value is predicted. We wouldn't track when a given system received the prediction except through lastUpdated, Provenance or AuditEvent. @Michael Lawley

view this post on Zulip Michael Lawley (Jun 17 2019 at 10:49):

Okay, that seems to capture the requirements of representing the two key time points. I was over-interpreting "time this version of the observation was made available to providers" as the receipt time, not the issuance time.

view this post on Zulip Lloyd McKenzie (Jun 17 2019 at 14:44):

@Michael Lawley feel free to submit a change request to better clarify

view this post on Zulip Eric Haas (Jun 17 2019 at 15:17):

I think the definition is simple concise and clear any more words will risk making it murkier

view this post on Zulip Lloyd McKenzie (Jun 17 2019 at 15:53):

@Eric Haas Evidently it's not sufficiently clear or Michael wouldn't have been confused. It doesn't make sense to down-vote the notion of proposing a clarification. If you don't like the proposed clarification, you can challenge that. But certainly there's room here to improve the definition to be clear that we're capturing when the Observation is 'made', not when it happens to be received by a given system.

view this post on Zulip Michael Lawley (Jun 18 2019 at 00:23):

It was the "made available to providers" part that confused me. If it had just said "time this version of the observation was made" then I would (probably) not have been confused. This is simple, concise, and fewer words @Eric Haas but I'm not sure if it actually makes it clearer for all.

view this post on Zulip Lloyd McKenzie (Jun 18 2019 at 02:39):

I think the problem OO is facing is that the determination is made at one point (often by a machine), but the finding is 'released' at a different point - generally when the results are signed off. In some cases, those could be a day or more apart. No action can be taken on the Observation until it's actually released (both because generally no one sees it, but also because it could be totally wrong.) So a proposal for revised wording would need to keep that nuance - while making clear that it's the time released by the observer, not the time received by any arbitrary server (which in some cases could be months or years after the measurement was made).


Last updated: Apr 12 2022 at 19:14 UTC