Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored to version 2.0.0 #3

Merged
merged 1 commit into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# .github/workflows/run_mocha_tests.yml
name: Test

on: [push, workflow_dispatch]

jobs:
build:
name: Test

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '16.x'
- run: npm install
- run: npm run build --if-present
- run: npm test
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
node_modules
coverage
dist
examples/headlessComparativeStudyResults.json
examples/headlessComparativeStudy.png
examples/**.json
examples/**.png
package-lock.json
11 changes: 11 additions & 0 deletions .mocharc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extension": ["ts", "js", "mjs"],
"spec": "test/**/*.test.*",
"node-option": [
"experimental-specifier-resolution=node",
"loader=ts-node/esm"
],
"package": "./package.json",
"bail": false,
"recursive": true
}
6 changes: 6 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"recommendations": [
"vue.vscode-typescript-vue-plugin",
"vue.volar"
]
}
74 changes: 74 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Serve",
"command": "npm run serve",
"request": "launch",
"type": "node-terminal"
},
{
"name": "Build",
"command": "npm run build",
"request": "launch",
"type": "node-terminal"
},
{
"name": "Run unit tests",
"command": "npm run test",
"request": "launch",
"type": "node-terminal"
},
{
"name": "Launch Chrome (debug)",
"type": "chrome",
"request": "launch",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}",
"sourceMaps": true
},
{
"name": "Launch Edge (debug)",
"type": "msedge",
"request": "launch",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}",
"sourceMaps": true
},
{
"name": "Run minimal demo (JS)",
"command": "node --loader ts-node/esm ./MinimalDemoJS.js",
"request": "launch",
"cwd": "${workspaceRoot}/examples/MinimalDemo/",
"type": "node-terminal"
},
{
"name": "Run minimal demo (TS)",
"command": "node --loader ts-node/esm ./MinimalDemoTS.ts",
"request": "launch",
"cwd": "${workspaceRoot}/examples/MinimalDemo/",
"type": "node-terminal"
},
{
"name": "Run controller study demo",
"command": "node --loader ts-node/esm ./ControllerStudyDemo.ts",
"request": "launch",
"cwd": "${workspaceRoot}/examples/ControllerStudyDemo",
"type": "node-terminal"
},
{
"name": "Omnipod in silico study",
"command": "node --loader ts-node/esm ./OmnipodInSilicoStudy.ts",
"request": "launch",
"cwd": "${workspaceRoot}/examples/OmnipodStudy/",
"type": "node-terminal",
},
{
"name": "Exercise models comparison",
"command": "node --loader ts-node/esm ./ExerciseModelsComparison.ts",
"request": "launch",
"cwd": "${workspaceRoot}/examples/ExerciseModelsComparison/",
"type": "node-terminal",
},
]
}
5 changes: 5 additions & 0 deletions @types/oref0.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare module 'oref0/lib/determine-basal/determine-basal.js'
declare module 'oref0/lib/basal-set-temp.js'
declare module 'oref0/lib/iob/index.js'
declare module 'oref0/lib/meal/total.js'
declare module 'oref0/lib/glucose-get-last.js'
6 changes: 6 additions & 0 deletions @types/shims-vue.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
declare module '*.vue' {
import { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

2 changes: 2 additions & 0 deletions @types/vue-i18n.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

declare module 'vue-i18n'
6 changes: 6 additions & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Heiko Peuscher
Hariolf Betz
Simone Hohm
Isabell Seidler
Lorenzo Sandini
Tom Wetterich
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2021 Heiko Peuscher
Copyright (c) 2021-present, Heiko Peuscher et al.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
<p align="center">
<p align="left">
<a href="https://lt1.org/" target="_blank">
<img alt="LoopInsighT1" src="./src/assets/images/loopinsight1.png" width="240">
<img alt="LoopInsighT1" src="./src/frontend/assets/images/LT1_logo.png" width="200">
</a>
</p>

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/)
[![PR's welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://LT1.org/contribute)
![test](https://github.com/hpeuscher/lt1-private/actions/workflows/test.yml/badge.svg)

<hr/>

This software is intended for closed-loop simulation of automatic insulin delivery systems for type 1 diabetic persons.

# Demo and further information
For a live demo, visit the [project website](https://lt1.org/simulator)
For a live demo, visit the project website [https://LT1.org](https://lt1.org/simulator).

# Installation / Quick start
Follow these instructions to use the simulator locally and modify its source code.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
127 changes: 127 additions & 0 deletions examples/ControllerStudyDemo/ControllerStudyDemo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/**
* This file is part of LoopInsighT1, an open source tool to
* simulate closed-loop glycemic control in type 1 diabetes.
* Distributed under the MIT software license.
* See https://lt1.org for further information.
*/

/**
* This file performs two simulations with identical scenarios but
* different controller algorithms. The results are stored to a
* JSON file, from which they can be imported and postprocessed
* in other tools like Matlab(R)
*
* Usage: cd ./examples/ControllerStudyDemo
* node --loader ts-node/esm ./ControllerStudyDemo.ts
*
* Or run the "Run controller study demo (JS)" configuration in VS Code
* (which will support debugging).
*/

import * as fs from 'fs'
import Simulator from '../../src/core/Simulator.js'
import VirtualPatientUvaPadova from '../../src/core/models/UvaPadova_T1DMS.js'
import Controller from '../../src/types/Controller.js'
import ControllerBasalBolus from '../../src/core/controllers/BasalBolus.js'
import ControllerOref0 from '../../src/core/controllers/Oref0.js'
import Meal from '../../src/types/Meal.js'
import IdealCGM from '../../src/core/sensors/IdealCGM.js'
import StaticInsulinPump from '../../src/core/actuators/StaticInsulinPump.js'
import ControllerUnion from '../../src/core/ControllerUnion.js'
import MealBolus from '../../src/core/controllers/MealBolus.js'


// define a patient object
const patient = new VirtualPatientUvaPadova()

// define a set of meals
const meals: Meal[] = [
{
start: new Date("2022-05-01T08:00:00Z"),
duration: 15,
carbs: 20,
announcement: {
start: new Date("2022-05-01T08:00:00Z"),
carbs: 20,
time: new Date("2022-05-01T07:00:00Z"),
},
},
{
start: new Date("2022-05-01T17:00:00Z"),
duration: 15,
carbs: 40,
announcement: {
start: new Date("2022-05-01T17:00:00Z"),
carbs: 40,
time: new Date("2022-05-01T16:00:00Z"),
},
},
{
start: new Date("2022-05-02T08:00:00Z"),
duration: 15,
carbs: 30,
},
]

// function for easy call of simulation
function performSimulationWithController(id: string, controller: Controller) {
controller.autoConfigure?.(patient.getPatientProfile())
// prepare the simulator
const sim = new Simulator()
// prepare simulation
sim.setPatient(patient)
sim.setSensor(new IdealCGM())
sim.setActuator(new StaticInsulinPump())
sim.setController(controller)
sim.setMeals(meals)
sim.setOptions({
"t0": new Date("2022-05-01T00:00:00Z"), // start at 0am
"tmax": new Date("2022-05-03T00:00:00Z"), // two days later
})
// run simulation
sim.runSimulation()
const results = sim.getSimulationResults()
return { id, meals, results } // TODO: patient, controller,
}

/** first controller */
const controller1 = new ControllerBasalBolus({
premealTime: 30, carbFactor: 0.8 // meal bolus
})

/** second controller: oref0 with meal bolus */
const controller2 = new ControllerUnion([
new ControllerOref0({
max_iob: 3.5,
dia: 6,
max_daily_basal: 1.3,
max_basal: 3.5,
max_bg: 100,
min_bg: 100,
sens: 40,
carb_ratio: 10 / 0.8,
maxCOB: 120,
}),
// meal bolus
new MealBolus({
premealTime: 30,
carbFactor: 0.8,
})
])

// run simulations
const results = [
performSimulationWithController("Basal+Bolus", controller1),
performSimulationWithController("oref0", controller2),
]

// store simulation input and results to JSON file
fs.writeFile("./ControllerStudyResults.json",
JSON.stringify(results),
function (err: NodeJS.ErrnoException | null) {
if (err) {
throw err
}
console.log("Done! Now run ControllerStudyPostprocess.m in Matlab(R)")
}
)
50 changes: 50 additions & 0 deletions examples/ControllerStudyDemo/ControllerStudyPostprocess.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
% This file is part of LoopInsighT1, an open source tool to
% simulate closed-loop glycemic control in type 1 diabetes.
% Distributed under the MIT software license.
% See https://lt1.org for further information.

clearvars;

% add util path which contains importJsonData
addpath('../util/')
% import JSON file
simDataJson = fileread('ControllerStudyResults.json');
% decode JSON file
simData = jsondecode(simDataJson);

%% prepare figure
clf(); set(gcf, 'Color', 'w', 'Position', [100 100 750 500]);
tiledlayout(2,1);
ax1 = nexttile(); set(ax1, 'NextPlot', 'add');
ax2 = nexttile(); set(ax2, 'NextPlot', 'add');


%% process data
for i=1:length(simData)
data = simData(i);

% import data
[t, y, s, c, u, x] = importJsonData(data.results);

% hide zero boluses in diagram
c.ibolus(c.ibolus==0) = NaN;

% plot blood glucose and insulin infusion rate
h = plot(ax1, t, y.Gp, 'DisplayName', data.id);
stairs(ax2, t(~isnan(c.iir)), c.iir(~isnan(c.iir)), 'Color', h.Color);
plot(ax2, t, c.ibolus, '^', ...
'MarkerEdgeColor', 'k', 'MarkerFaceColor', h.Color);
end

%% format graphs
axes(ax1);
title('glucose concentration in mg/dl');
hold on; box on; grid on;
legend('show', 'Location', 'northwest')

axes(ax2);
title('insulin infusion: basal rate in U/h and bolus in U');
hold on; box on; grid on;

%% store as file
print('ControllerStudyDemo.png', '-dpng', '-r300');
Loading