|
2 | 2 |
|
3 | 3 | This Swift module uses LoopAlgorithm to create C functions for generating predictions and prediction dates from JSON data. |
4 | 4 |
|
5 | | -How? |
6 | | -I create a foreign function interface (FFI) in Swift by using the unofficial @_cdecl Swift function. This interfaces the Swift code with C. Then we can create a dynamic library, import it into a Python (or other) repositories, and use for example ctypes to compile the C code. |
| 5 | +This is achieved by creating a foreign function interface (FFI) in Swift by using the unofficial @_cdecl Swift function. This interfaces the Swift code with C. Then we can create a dynamic library, import it into a Python (or other) repositories, and use for example ctypes to compile the C code. |
7 | 6 |
|
8 | 7 |
|
9 | | -## Installation |
10 | 8 |
|
11 | | -1. Clone the repository |
12 | | -2. Build the dynamic library: |
| 9 | +## Repository Overview |
13 | 10 |
|
14 | | -``` |
15 | | -swift package clean |
16 | | -swift build --configuration release |
17 | | -``` |
18 | | -Check if the dynamic library got properly generated and print the path: |
19 | | -``` |
20 | | -find .build -name "libLoopAlgorithmToPython.dylib" |
21 | | -``` |
22 | | -Output should be something like: /release/libLoopAlgorithmToPython.dylib |
| 11 | +### Exposed functions |
23 | 12 |
|
24 | | -Copy that file into your repository. |
| 13 | +You can find the C-exposed functions in the file `Sources/LoopAlgorithmToPython/LoopAlgorithmToPython.swift`. |
25 | 14 |
|
| 15 | +### Python API |
26 | 16 |
|
27 | | -## Exposed functions |
| 17 | +Python API functions are located in `loop_to_python_api/api.py`. |
28 | 18 |
|
29 | | -You can find the C-exposed functions in the file `LoopAlgorithmToPython.swift`. |
| 19 | +### Tests and test data |
30 | 20 |
|
| 21 | +`python_tests/` contains examples of executing all the functions as well as example files providing templates on how to structure the input files. |
31 | 22 |
|
32 | 23 |
|
33 | | -## Usage in Python |
34 | 24 |
|
35 | | -Here's how you can use the dynamic library (`libLoopAlgorithmToPython.dylib`) in Python to call the exposed functions: |
36 | 25 |
|
37 | | -``` |
38 | | -import ctypes |
39 | | -import json |
| 26 | +## Python API Functions |
40 | 27 |
|
41 | | -json_file_path = 'some_file.json' |
| 28 | +------------------------- |
42 | 29 |
|
43 | | -# Load the shared library |
44 | | -swift_lib = ctypes.CDLL('./libLoopAlgorithmToPython.dylib') |
| 30 | +### Initialize Exception Handlers |
45 | 31 |
|
46 | | -# Specify the argument types and return type of the Swift function |
47 | | -swift_lib.generatePrediction.argtypes = [ctypes.c_char_p] |
48 | | -swift_lib.generatePrediction.restype = ctypes.POINTER(ctypes.c_double) |
| 32 | +`initialize_exception_handlers()` |
49 | 33 |
|
50 | | -swift_lib.getPredictionDates.argtypes = [ctypes.c_char_p] |
51 | | -swift_lib.getPredictionDates.restype = ctypes.c_char_p |
| 34 | +Initializes the exception and signal handlers in the Swift library to provide more informative error messages. |
52 | 35 |
|
53 | | -swift_lib.getActiveCarbs.argtypes = [ctypes.c_char_p] |
54 | | -swift_lib.getActiveCarbs.restype = ctypes.c_double |
| 36 | +------------------------- |
55 | 37 |
|
56 | | -swift_lib.getActiveInsulin.argtypes = [ctypes.c_char_p] |
57 | | -swift_lib.getActiveInsulin.restype = ctypes.c_double |
| 38 | +### Generate Prediction |
58 | 39 |
|
59 | | -# Read JSON file |
60 | | -def read_json_file(file_path): |
61 | | - with open(file_path, 'r') as f: |
62 | | - data = json.load(f) |
63 | | - return data |
| 40 | +`generate_prediction(json_file, len=72)` |
64 | 41 |
|
65 | | -json_data = read_json_file(json_file_path) # Read JSON file |
66 | | -json_str = json.dumps(json_data) # Convert JSON data to JSON string |
67 | | -json_bytes = json_str.encode('utf-8') # Convert JSON string to bytes |
| 42 | +Generates a prediction based on the provided JSON input. |
68 | 43 |
|
69 | | -# Prepare a variable to receive the length of the predicted values |
70 | | -length = 82 |
| 44 | +- **Parameters**: |
| 45 | + - `json_file`: The JSON data input. See python tests and test files for example inputs. |
| 46 | + - `len` (optional): The number of prediction values to generate. Defaults to 72. |
| 47 | +- **Returns**: A list of prediction values. |
71 | 48 |
|
72 | | -# Call the Swift functions |
73 | | -result_prediction_values = swift_lib.generatePrediction(json_bytes) |
74 | | -result_prediction_dates = swift_lib.getPredictionDates(json_bytes).decode('utf-8') |
75 | | -result_active_carbs = swift_lib.getActiveCarbs(json_bytes) |
76 | | -result_active_insulin = swift_lib.getActiveInsulin(json_bytes) |
| 49 | +------------------------- |
77 | 50 |
|
78 | | -# Read the generated predictions |
79 | | -array = [result_prediction_values[i] for i in range(length)] |
80 | | -print(array[0]) |
81 | | -print(f"The result from generatePrediction is: {array}") |
| 51 | +### Get Prediction Dates |
82 | 52 |
|
83 | | -# Read the dates |
84 | | -date_list = result.split(',')[:-1] |
85 | | -print(f"The result from getPredictionDates is: {date_list}") |
| 53 | +`get_prediction_dates(json_file)` |
86 | 54 |
|
87 | | -# Read the active carbohydrates |
88 | | -print(f"The result from getActiveCarbs is: {result_active_carbs}") |
| 55 | +Fetches prediction dates based on the provided JSON input. |
89 | 56 |
|
90 | | -# Read the active insulin |
91 | | -print(f"The result from getActiveInsulin is: {result_active_insulin}") |
92 | | -``` |
| 57 | +- **Parameters**: |
| 58 | + - `json_file`: The JSON data input. See python tests and test files for example inputs. |
| 59 | +- **Returns**: A list of prediction dates as strings. |
93 | 60 |
|
94 | | -Adjust the paths, function names, and details as per your specific project setup and requirements. |
| 61 | +------------------------- |
95 | 62 |
|
| 63 | +### Get Prediction Values and Dates |
96 | 64 |
|
| 65 | +`get_prediction_values_and_dates(json_file)` |
97 | 66 |
|
| 67 | +Combines the `generate_prediction` and `get_prediction_dates` functions to return both prediction values and dates. |
98 | 68 |
|
| 69 | +- **Parameters**: |
| 70 | + - `json_file`: The JSON data input. See python tests and test files for example inputs. |
| 71 | +- **Returns**: A tuple containing a list of prediction values and a list of prediction dates. |
99 | 72 |
|
| 73 | +------------------------- |
| 74 | + |
| 75 | +### Get Glucose Effect Velocity |
| 76 | + |
| 77 | +`get_glucose_effect_velocity(json_file, len=72)` |
| 78 | + |
| 79 | +Fetches the glucose effect velocity, which is equivalent to Insulin Counteraction Effect (ICE). |
| 80 | + |
| 81 | +- **Parameters**: |
| 82 | + - `json_file`: The JSON data input. See python tests and test files for example inputs. |
| 83 | + - `len` (optional): The number of values to fetch. Defaults to 72. |
| 84 | +- **Returns**: A list of glucose effect velocity values. |
| 85 | + |
| 86 | +------------------------- |
| 87 | + |
| 88 | +### Get Glucose Effect Velocity Dates |
| 89 | + |
| 90 | +`get_glucose_effect_velocity_dates(json_file)` |
| 91 | + |
| 92 | +Fetches the dates associated with the glucose effect velocity. |
| 93 | + |
| 94 | +- **Parameters**: |
| 95 | + - `json_file`: The JSON data input. See python tests and test files for example inputs. |
| 96 | +- **Returns**: A list of dates as strings. |
| 97 | + |
| 98 | + |
| 99 | +------------------------- |
| 100 | + |
| 101 | +### Get Glucose Velocity Values and Dates |
| 102 | + |
| 103 | +`get_glucose_velocity_values_and_dates(json_file)` |
| 104 | + |
| 105 | +Combines the `get_glucose_effect_velocity` and `get_glucose_effect_velocity_dates` functions to return both glucose effect velocity values and dates. |
| 106 | + |
| 107 | +- **Parameters**: |
| 108 | + - `json_file`: The JSON data input. See python tests and test files for example inputs. |
| 109 | +- **Returns**: A tuple containing a list of glucose effect velocity values and a list of dates. |
| 110 | + |
| 111 | +------------------------- |
| 112 | + |
| 113 | +### Get Active Carbs |
| 114 | + |
| 115 | +`get_active_carbs(json_file)` |
| 116 | + |
| 117 | +Fetches the active carbohydrates based on the provided JSON input. |
| 118 | + |
| 119 | +- **Parameters**: |
| 120 | + - `json_file`: The JSON data input. See python tests and test files for example inputs. |
| 121 | +- **Returns**: The active carbohydrates as a double. |
| 122 | + |
| 123 | + |
| 124 | +------------------------- |
| 125 | + |
| 126 | +### Get Active Insulin |
| 127 | + |
| 128 | +`get_active_insulin(json_file)` |
| 129 | + |
| 130 | +Fetches the active insulin based on the provided JSON input. |
| 131 | + |
| 132 | +- **Parameters**: |
| 133 | + - `json_file`: The JSON data input. See python tests and test files for example inputs. |
| 134 | +- **Returns**: The active insulin as a double. |
| 135 | + |
| 136 | +------------------------- |
| 137 | + |
| 138 | +### Percent Absorption at Percent Time |
| 139 | + |
| 140 | +`percent_absorption_at_percent_time(percent_time)` |
| 141 | + |
| 142 | +Calculates the percentage of carbohydrate absorption at a given percent time using a piecewise linear model. |
| 143 | + |
| 144 | +- **Parameters**: |
| 145 | + - `percent_time`: The time as a fraction (e.g., 0.2 for 20%). |
| 146 | +- **Returns**: The percentage of absorption as a double. |
| 147 | + |
| 148 | +------------------------- |
| 149 | + |
| 150 | +### Piecewise Linear Percent Rate at Percent Time |
| 151 | + |
| 152 | +`piecewise_linear_percent_rate_at_percent_time(percent_time)` |
| 153 | + |
| 154 | +Calculates the percentage rate of carbohydrate absorption at a given percent time using a piecewise linear model. |
| 155 | + |
| 156 | +- **Parameters**: |
| 157 | + - `percent_time`: The time as a fraction (e.g., 0.2 for 20%). |
| 158 | +- **Returns**: The percentage rate of absorption as a double. |
| 159 | + |
| 160 | +------------------------- |
| 161 | + |
| 162 | +### Linear Percent Rate at Percent Time |
| 163 | + |
| 164 | +`linear_percent_rate_at_percent_time(percent_time)` |
| 165 | + |
| 166 | +Calculates the percentage rate of carbohydrate absorption at a given percent time using a linear model. |
| 167 | + |
| 168 | +- **Parameters**: |
| 169 | + - `percent_time`: The time as a fraction (e.g., 0.2 for 20%). |
| 170 | +- **Returns**: The percentage rate of absorption as a double. |
| 171 | + |
| 172 | +------------------------- |
| 173 | + |
| 174 | +### Get Dynamic Carbs on Board |
| 175 | + |
| 176 | +`get_dynamic_carbs_on_board(json_file)` |
| 177 | +Fetches the dynamic carbohydrates on board based on the provided JSON input. |
| 178 | + |
| 179 | +- **Parameters**: |
| 180 | + - `json_file`: The JSON data input. See python tests and test files for example inputs. |
| 181 | +- **Returns**: The dynamic carbohydrates on board as a double. |
| 182 | + |
| 183 | +------------------------- |
| 184 | + |
| 185 | + |
| 186 | + |
| 187 | + |
| 188 | +## Build Dynamic Library |
| 189 | + |
| 190 | +The file `python_api/libLoopAlgorithmToPython.dylib` contains the dynamic library that is containing the C-embedded Swift functions. |
| 191 | + |
| 192 | +After making changes in the Swift code, rebuild the dynamic library by running `chmod +x build.sh` followed by `./build.sh`. |
| 193 | + |
| 194 | + |
| 195 | + |
| 196 | +## Run Tests |
| 197 | + |
| 198 | +Run command `pytest`. |
100 | 199 |
|
101 | 200 |
|
102 | 201 |
|
|
0 commit comments