jxx123 / simglucose

A Type-1 Diabetes simulator implemented in Python for Reinforcement Learning purpose
MIT License
232 stars 111 forks source link

Scenario Simulations #34

Open kasungayan opened 3 years ago

kasungayan commented 3 years ago

Hi,

First of all, thank you very much for your framework, it's quite comprehensive and useful !

Is there any possibility to generate scenarios/simulations where we can enforce not changing the insulin input, while inputting the carbohydrate intake. In other words, scenarios where patient eat, but not taking the required insulin. Also the vice-versa, where the patient's carbohydrate intake is 0 (not eating anything), while the insulin intake is as normal.

If there's possibility to simulate such scenarios, can you kindly give some pointers or guidance ?

Regards, Kasun

jxx123 commented 3 years ago

Hi,

Sorry for the late reply. For now, you can only specify carbohydrate in the CustomScenario.

To have a scenario where the patient takes carb but no insulin, you need to implement a dummy controller yourself, like this (this is also in Rreadme doc). This dummy controller does not inject any insulin.

from simglucose.simulation.user_interface import simulate
from simglucose.controller.base import Controller, Action

class MyController(Controller):
    def __init__(self, init_state):
        self.init_state = init_state
        self.state = init_state

    def policy(self, observation, reward, done, **info):
        '''
        Every controller must have this implementation!
        ----
        Inputs:
        observation - a namedtuple defined in simglucose.simulation.env. For
                      now, it only has one entry: blood glucose level measured
                      by CGM sensor.
        reward      - current reward returned by environment
        done        - True, game over. False, game continues
        info        - additional information as key word arguments,
                      simglucose.simulation.env.T1DSimEnv returns patient_name
                      and sample_time
        ----
        Output:
        action - a namedtuple defined at the beginning of this file. The
                 controller action contains two entries: basal, bolus
        '''
        self.state = observation
        action = Action(basal=0, bolus=0)
        return action

    def reset(self):
        '''
        Reset the controller state to inital state, must be implemented
        '''
        self.state = self.init_state

ctrller = MyController(0)
simulate(controller=ctrller)

Or you might want to keep the basal, but not injecting bolus. You can set bolus to be always 0 here https://github.com/jxx123/simglucose/blob/8f6696a628543a553fd9d5aa55d935be23bd7b38/simglucose/controller/basal_bolus_ctrller.py#L83

For the other way around, it is a bit tricky. Still in the basal_bolus_controller, you can get the meal info here https://github.com/jxx123/simglucose/blob/8f6696a628543a553fd9d5aa55d935be23bd7b38/simglucose/controller/basal_bolus_ctrller.py#L30 you can do something like, when the meal > 0, your bolus is still 0, but you keep a counter, like after 10 time steps (if sample time is 5min, then it is 50 minutes later), you can set bolus > 0 (make sure the patient don't take any meal at this time).

kasungayan commented 3 years ago

Hi @jxx123,

Many thanks for your reply. I have a few things to clarify in your reply:

1) You mentioned that from the CustomScenario controller, I can set the insulin (bolus) to zero, while the carbs (basal) to non-zero (scenario where the patient takes carb but no insulin); which I was able to implement successfully. In the second response, you alternatively mention about the modification that I can do on the _basal_bolusctroller.py file to achieve the same thing ("your answer: Or you might want to keep the basal, but not injecting bolus. You can set bolus to be always 0 here"). What exactly is the difference between your first suggestion and this one ?. I guess it achieves the same result in two different ways right ? (one through a custom controller and other through a direct change in the code, which requires to build the package manually after applying these changes to basal_bolus_ctroller.py). Am I correct ?. If not, can you please elaborate the difference between those two approaches ?

2) For the other scenario, where you inject the insulin (bolus) but not taking any carbs (basal), wouldn't it be possible to just set the basal to 0 in _basal_bolusctrller.py, like:

return Action(basal=0, bolus=bolus)

And I assume it's not possible to write a custom controller for this scenario right ?

Regards, Kasun

jxx123 commented 3 years ago

Hi Kasun,

  1. There is no big difference between using your own custom controller or built-in basal_bolus_controller. I was saying that if you need to keep the basal (so the glucose can stay stay stable), you can just change the built-in basal_bolus_controller by keeping the basal but setting bolus to 0.

  2. I guess you might be confused with the meaning of "basal" and "bolus". They both refer to insulin. Basal is a small amount of insulin that patient always need to inject, and bolus is the big amount of insulin that patients need to take at the meal time to offset the meal effect. If you want to inject insulin but not taking any carbs, you can just set basal and bolus to an amount you like in a custom controller (or basal_bolus_controller), but the tricky part is controller does not know the simulation time. If you want to set insulin to 2U at 7 am, the controller does not know when is 7 am in the simulation. A way to do this is that you can keep a counter in your custom controller to count the time step, and set the bolus (or basal) to an amount you like at the desired time.

Thanks, Jinyu