Skip to content

Commit

Permalink
Merge pull request #57 from Shurikal/list_gym
Browse files Browse the repository at this point in the history
Init gym env with list of patients/meals
  • Loading branch information
jxx123 committed Jul 3, 2023
2 parents a2abc77 + 2fd635f commit 3053386
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 10 deletions.
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,28 @@ simulate(sim_time=my_sim_time,
import gym

# Register gym environment. By specifying kwargs,
# you are able to choose which patient to simulate.
# you are able to choose which patient or patients to simulate.
# patient_name must be 'adolescent#001' to 'adolescent#010',
# or 'adult#001' to 'adult#010', or 'child#001' to 'child#010'
# It can also be a list of patient names
# You can also specify a custom scenario or a list of custom scenarios
# If you chose a list of patient names or a list of custom scenarios,
# every time the environment is reset, a random patient and scenario will be
# chosen from the list

from gym.envs.registration import register
from simglucose.simulation.scenario import CustomScenario
from datetime import datetime

start_time = datetime(2018, 1, 1, 0, 0, 0)
meal_scenario = CustomScenario(start_time=start_time, scenario=[(1,20)])


register(
id='simglucose-adolescent2-v0',
entry_point='simglucose.envs:T1DSimEnv',
kwargs={'patient_name': 'adolescent#002'}
kwargs={'patient_name': 'adolescent#002',
'custom_scenario': meal_scenario}
)

env = gym.make('simglucose-adolescent2-v0')
Expand Down
27 changes: 19 additions & 8 deletions simglucose/envs/simglucose_gym_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@ def __init__(self, patient_name=None, custom_scenario=None, reward_fun=None, see
# have to hard code the patient_name, gym has some interesting
# error when choosing the patient
if patient_name is None:
patient_name = 'adolescent#001'
patient_name = ['adolescent#001']

self.patient_name = patient_name
self.reward_fun = reward_fun
self.np_random, _ = seeding.np_random(seed=seed)
self.custom_scenario = custom_scenario
self.env, _, _, _ = self._create_env_from_random_state(custom_scenario)
self.env, _, _, _ = self._create_env()

def _step(self, action):
# This gym only controls basal insulin
Expand All @@ -47,16 +48,16 @@ def _step(self, action):
return self.env.step(act, reward_fun=self.reward_fun)

def _reset(self):
self.env, _, _, _ = self._create_env_from_random_state(self.custom_scenario)
self.env, _, _, _ = self._create_env()
obs, _, _, _ = self.env.reset()
return obs

def _seed(self, seed=None):
self.np_random, seed1 = seeding.np_random(seed=seed)
self.env, seed2, seed3, seed4 = self._create_env_from_random_state()
self.env, seed2, seed3, seed4 = self._create_env()
return [seed1, seed2, seed3, seed4]

def _create_env_from_random_state(self, custom_scenario=None):
def _create_env(self):
# Derive a random seed. This gets passed as a uint, but gets
# checked as an int elsewhere, so we need to keep it below
# 2**31.
Expand All @@ -65,10 +66,20 @@ def _create_env_from_random_state(self, custom_scenario=None):
seed4 = seeding.hash_seed(seed3 + 1) % 2**31

hour = self.np_random.randint(low=0.0, high=24.0)
start_time = datetime(2018, 1, 1, hour, 0, 0)
patient = T1DPatient.withName(self.patient_name, random_init_bg=True, seed=seed4)
start_time = datetime(2018, 1, 1, hour, 0, 0)

if isinstance(self.patient_name, list):
patient_name = self.np_random.choice(self.patient_name)
patient = T1DPatient.withName(patient_name, random_init_bg=True, seed=seed4)
else:
patient = T1DPatient.withName(self.patient_name, random_init_bg=True, seed=seed4)

if isinstance(self.custom_scenario, list):
scenario = self.np_random.choice(self.custom_scenario)
else:
scenario = RandomScenario(start_time=start_time, seed=seed3) if self.custom_scenario is None else self.custom_scenario

sensor = CGMSensor.withName(self.SENSOR_HARDWARE, seed=seed2)
scenario = RandomScenario(start_time=start_time, seed=seed3) if custom_scenario is None else custom_scenario
pump = InsulinPump.withName(self.INSULIN_PUMP_HARDWARE)
env = _T1DSimEnv(patient, sensor, pump, scenario)
return env, seed2, seed3, seed4
Expand Down
61 changes: 61 additions & 0 deletions tests/test_gym_custom_scenario.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import gym
import unittest
from simglucose.simulation.scenario import CustomScenario
from simglucose.controller.basal_bolus_ctrller import BBController
import datetime as dt


class TestCustomScenario(unittest.TestCase):
def test_custom_scenario(self):
start_time = dt.datetime(2018, 1, 1, 0, 0, 0)

meals = [(1,50),(2,10),(3,20)]
meals_checked = [False for _ in range(len(meals))]

current_pos = 0

custom_meal_scenario = CustomScenario(start_time=start_time, scenario=meals)


gym.envs.register(
id='env-v0',
entry_point='simglucose.envs:T1DSimEnv',
kwargs={'patient_name': 'adult#001',
'custom_scenario': custom_meal_scenario}
)

env = gym.make('env-v0')
ctrller = BBController()

reward = 0
done = False

sample_step = env.env.sensor.sample_time

info = {'sample_time': sample_step,
'patient_name': 'adolescent#002',
'meal': 0}

observation = env.reset()
for t in range(61):
env.render(mode='human')

ctrl_action = ctrller.policy(observation, reward, done, **info)
action = ctrl_action.basal + ctrl_action.bolus
observation, reward, done, info = env.step(action)


if info["meal"] > 0 and t*sample_step == (meals[current_pos][0]*60):
meals_checked[current_pos] = True
current_pos += 1


if done:
print("Episode finished after {} timesteps".format(t + 1))
break

assert(all(meals_checked))


if __name__ == '__main__':
unittest.main()

0 comments on commit 3053386

Please sign in to comment.