# Transmission Simulator
**Repository Path**: ultcrt/Transmission-Simulator
## Basic Information
- **Project Name**: Transmission Simulator
- **Description**: 本项目的主要目标是基于新冠病毒的传播数据和模型,创建并实现一个用户能够自定义初始数据和传播模型的仿真平台,从而不局限于模拟特定单一的病毒传播,有更高的使用价值。如何设计能够准确模拟病毒传播的数学模型并不是主要目标,合理的数学模型仅仅作为检验仿真平台可靠性的工具。
- **Primary Language**: Python
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-03-22
- **Last Updated**: 2021-11-09
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Transmission Simulator
### 一、概述
本项目的主要目标是基于新冠病毒的传播数据和模型,创建并实现一个用户能够自定义初始数据和传播模型的仿真平台,从而不局限于模拟特定单一的病毒传播,有更高的使用价值。如何设计能够准确模拟病毒传播的数学模型并不是主要目标,合理的数学模型仅仅作为检验仿真平台可靠性的工具。
### 二、输入输出
#### 2.1 格式
为了便于用户输入和对输入数据的读写操作,这里使用Json作为输入数据的数据结构。需要注意的是,为了确保用户能够灵活的替换数学模型,本节涉及到的有关于数学模型的输入参数指的是在用户自定义函数缺省的情况下,使用默认的函数所需的数据(暂定为SEIR模型),在存在用户自定义函数的情况下,数学模型参数由用户决定,本平台只起到将Json中的模型参数(即model_param)整体传递给自定义的模型函数。
其次,考虑到部分用户可能希望获得原始数据和计算结果能够长时间保存的优点,提供将计算结果(即输出数据)用Json文件进行保存的函数。
#### 2.2 数据定义
##### 2.2.1 输入参数
###### 控制参数
| 参数名 | 类型 | 功能 |
|-------------|---------|--------------------------------|
| model\_func | funcion | 用于计算传染的数学模型,可缺省,缺省时使用内置的SEIR函数 |
| type | int | 用于决定覆盖更新(0)还是增量更新(1) |
###### 地区参数
| 参数名 | 类型 | 功能 |
|-------------|---------|--------------------------------|
| name | str | 储存地名 |
| susceptible | int | 储存易感者数量 |
| exposed | int | 储存潜伏者数量 |
| infected | int | 储存感染者数量 |
| recovered | int | 储存治愈者数量 |
| dead | int | 储存死亡者数量 |
| export\_rate | float | 向其他地区的总迁出率,取值范围-1\.00~1\.00,负值表示迁入,正值表示迁出 |
| dest\_pref | dict | 偏好值的取值范围为0\.00~1\.00,即特定地区迁出率占比 \{’region1‘:0\.25,'region2':0\.75\},不允许传入空字典 |
###### 数学模型参数
| 参数名 | 类型 | 功能 |
|-------------|---------|--------------------------------|
| type | string | 识别模型种类 |
| contact_infected | int | 每个感染者接触易感者的人数 |
| contact_exposed | int | 每个潜伏者接触易感者的人数 |
| α | float | 治愈率(I→R),取值范围0\.00~1\.00 |
| β | float | 死亡率(I→D),取值范围0\.00~1\.00 |
| λ_infected | float | 感染者传染率(S→E),取值范围0\.00~1\.00 |
| λ_exposed | float | 潜伏者传染率(S→E),取值范围0\.00~1\.00 |
| σ | float | 发病率(E→I,此概率能够体现潜伏时间),取值范围0\.00~1\.00 |
| μ | float | 治愈后再次易感概率(R→S),取值范围0.00~1.00 |
##### 2.2.2 输出参数
| 参数名 | 类型 | 功能 |
|-------------|-----|---------|
| name | str | 储存地名 |
| susceptible | int | 储存易感者数量 |
| exposed | int | 储存潜伏者数量 |
| infected | int | 储存感染者数量 |
| recovered | int | 储存治愈者数量 |
| dead | int | 储存死亡者数量 |
#### 2.3 文件结构
为了避免多次IO操作,使用单个Json文件储存输入和输出信息。
##### 2.3.1 输入
```
Input
init.json
updates.json
```
##### 2.3.2 输出
```
Output
results.json
```
#### 2.4 Json结构
##### 2.4.1 init.json结构
```json
{
"regions": [{
"name": "region1",
"susceptible": 10,
"exposed": 0,
"infected": 0,
"recovered": 0,
"dead": 0,
"export_rate": 0.05,
"dest_pref": {
"region2": 1.00
},
"model_param": {
"type": "SEIR",
"contact_infected": 10,
"contact_exposed": 10,
"alpha": 0.1,
"beta": 0.1,
"lambda_infected": 0.1,
"lambda_exposed": 0.1,
"sigma": 0.1,
"mu": 0.1
}
},
{
"name": "region2",
"susceptible": 10,
"exposed": 0,
"infected": 0,
"recovered": 0,
"dead": 0,
"export_rate": 0.05,
"dest_pref": {
"region1": 1.00
},
"model_param": {
"type": "SEIR",
"contact_infected": 10,
"contact_exposed": 10,
"alpha": 0.1,
"beta": 0.1,
"lambda_infected": 0.1,
"lambda_exposed": 0.1,
"sigma": 0.1,
"mu": 0.1
}
}
]
}
```
##### 2.4.2 updates.json结构
- 注意:日期小于等于0,则该日更新无效
```json
{
"1": [{
"name": "region1",
"type": 0,
"susceptible": 10,
"exposed": 0,
"infected": 0,
"recovered": 0,
"dead": 0,
"export_rate": 0.05,
"dest_pref": {
"region2": 1.00
},
"model_param": {
"type": "SEIR",
"contact_infected": 10,
"contact_exposed": 10,
"alpha": 0.1,
"beta": 0.1,
"lambda_infected": 0.1,
"lambda_exposed": 0.1,
"sigma": 0.1,
"mu": 0.1
}
}],
"2": [{
"name": "region1",
"type": 0,
"susceptible": 10,
"exposed": 0,
"infected": 0,
"recovered": 0,
"dead": 0,
"export_rate": 0.05,
"dest_pref": {
"region2": 1.00
},
"model_param": {
"type": "SEIR",
"contact_infected": 10,
"contact_exposed": 10,
"alpha": 0.1,
"beta": 0.1,
"lambda_infected": 0.1,
"lambda_exposed": 0.1,
"sigma": 0.1,
"mu": 0.1
}
}]
}
```
##### 2.4.3 results.json结构
```json
{
"0": {
"region1": {
"name": "region1",
"susceptible": 10,
"exposed": 0,
"infected": 0,
"recovered": 0,
"dead": 0,
"export_rate": 0.05,
"dest_pref": {
"region2": 1.00
},
"model_param": {
"type": "SEIR",
"contact_infected": 10,
"contact_exposed": 10,
"alpha": 0.1,
"beta": 0.1,
"lambda_infected": 0.1,
"lambda_exposed": 0.1,
"sigma": 0.1,
"mu": 0.1
}
},
"region2": {
"name": "region2",
"susceptible": 10,
"exposed": 0,
"infected": 0,
"recovered": 0,
"dead": 0,
"export_rate": 0.05,
"dest_pref": {
"region2": 1.00
},
"model_param": {
"type": "SEIR",
"contact_infected": 10,
"contact_exposed": 10,
"alpha": 0.1,
"beta": 0.1,
"lambda_infected": 0.1,
"lambda_exposed": 0.1,
"sigma": 0.1,
"mu": 0.1
}
}
},
"1": {
"region1": {
"name": "region1",
"susceptible": 10,
"exposed": 0,
"infected": 0,
"recovered": 0,
"dead": 0,
"export_rate": 0.05,
"dest_pref": {
"region2": 1.00
},
"model_param": {
"type": "SEIR",
"contact_infected": 10,
"contact_exposed": 10,
"alpha": 0.1,
"beta": 0.1,
"lambda_infected": 0.1,
"lambda_exposed": 0.1,
"sigma": 0.1,
"mu": 0.1
}
},
"region2": {
"name": "region2",
"susceptible": 10,
"exposed": 0,
"infected": 0,
"recovered": 0,
"dead": 0,
"export_rate": 0.05,
"dest_pref": {
"region2": 1.00
},
"model_param": {
"type": "SEIR",
"contact_infected": 10,
"contact_exposed": 10,
"alpha": 0.1,
"beta": 0.1,
"lambda_infected": 0.1,
"lambda_exposed": 0.1,
"sigma": 0.1,
"mu": 0.1
}
}
}
}
```
### 三、框架
#### 3.1 主体流程
1. 从外部获取初始化信息
2. 设置当前日期为0
3. 将初始信息存入结果缓存
4. 当前天数加1
5. 获取更新信息并使用更新信息刷新各地区数据
6. 计算地区内部传染情况并刷新人口组成
7. 计算出各地区迁出人口并刷新人口组成
8. 将本日结果写入结果缓存
9. 返回第四步循环执行
#### 3.2 类定义
##### 3.2.1 Controller类
负责总体控制,本类作为其余四个类的数据交换的枢纽,其他类都只与本类进行直接的数据交换。本类功能包括初始化整个网络、对日期的控制和对区域信息的更新。
###### 数据成员
| 名称 | 类型 | 功能 |
|-------------|----------------|---------------------|
| \_regions | dict | 以地名为引索的字典,值为地区对象 |
| \_loader | InfoLoader | 在Controller初始化时读取init\.json和updates\.json,
分别用于Controller的初始化和每日的区域更新 |
| \_writer | ResultWriter | 将结果写入json中 |
| \_model | InternalModel | 在Controller初始化时获取用户自定义函数,
用于计算人口组成的变化情况。 |
| \_cur\_day | int | 记录当前日期 |
###### 函数成员
| 定义 | 返回值 | 功能 |
|--------------|------------|------------------------|
| \_\_init\_\_\(self, model\_func=None, input\_path=None\) | None | 用于初始化Controller的数据成员,
参数缺省、合法性不在此函数处理。
model\_func为用户自定义传染函数,用于初始化\_model成员,
该函数的具体格式在InternalModel类的说明中给出。
input\_path为输入文件夹的路径,用于初始化\_loader成员,
并使用\_loader的构造函数返回值初始化\_regions。
\_cur\_day初始化为0。 |
| \_hard\_update\(self\) | None | 通过\_loader中的get\_cur\_update方法,
在每日开始时,对区域进行外界强制更新 |
| \_migration\_collect\(self\) | list | 调用每个地区的get\_migration函数,
并把所有的返回值组成list进行返回 |
| \_model\_update\(self\) | None | 通过\_model提供的函数calculate计算出
通过新的人口组成并进行更新 |
| \_migration\_update\(self\) | None | 通过\_migration\_collect的返回值
进行迁出人口的更新 |
| \_write\_cur\_day\(self\) | None | 调用\_writer\.write\_to\_buffer,
将当天结果进行记录 |
| next\_day\(self\) | None | 计算当前日期的结果,具体过程见流程。 |
| set\_model\_func\(self, model\_func\) | None | 使用此函数中途修改传染函数,
如果参数值为None则设置为默认函数 |
| write\(self, path=None\) | None | 调用\_writer\.write\_to\_file,
将目前结果写入文件 |
| get\_results\(self, region\_name=None, day=None\) | dict | 返回名为region\_name的地区日期为day时的数据
(从\_writer\.\_results\_buffer中获取)。
当只有region\_name为空时,返回当日所有地区的数据字典
所构成的dict。当只有day为空时,返回对应
地区的所有天数的信息所组成的dict(key为天数字符串)。
如果两参数都为空,则返回所有\_writer\.\_results\_buffer
中的结果。如果没有能够返回的结果,则返回空 |
| reimport_update\(self\) | bool | 从硬盘重新加载更新数据,返回值代表文件是否存在 |
##### 3.2.2 Region类
储存地区的所有属性,同时提供获取和更新地区属性的函数。
数据成员
###### 数据成员
| 名称 | 类型 | 功能 |
|-----------------|--------|-------------------------------------------------|
| \_name | str | 地名,起到标识作用 |
| \_susceptible | int | 易感者 |
| \_exposed | int | 潜伏者 |
| \_infected | int | 感染者 |
| \_recovered | int | 治愈者 |
| \_dead | int | 死亡者 |
| \_export\_rate | float | 迁出率,-1\.00~1\.00 |
| \_dest\_pref | dict | 以地名为引索的字典,值为迁出偏好,0\.00~1\.00,表示向各地迁出人口的比例 |
| \_model\_param | dict | 传播模型的参数字典,其默认包含的内容如2\.2\.1节的数学模型所述。但实际内容由用户决定。 |
###### 函数成员
| 定义 | 返回值 | 功能 |
|----------|-------|------------------------|
| \_\_init\_\_\(self, info\) | None | info为地区属性的字典。同时,
需要检查除\_model\_param以外的元素取值是否
合法(见2\.2\.1节中的限制,\_model\_param由于是用户传入的,
所以应当交给用户自定义函数进行校验) |
| update\(self, info\) | None | 地区名禁止更新。
使用info更新数据成员,info中的项type=0时,
覆盖更新;type=1时,增量更新(如果缺省type,则默认type=0,字符串元素始终为覆盖更新)。
info为地区属性的字典,且该字典中的所有项都可以缺省
(更新时遍历info即可)。同时,
需要检查除\_model\_param以外的元素取值是否合法 |
| get\_migration\(self\) | list | 通过export\_rate与dest\_pref计算本地向其他地区的迁出人口组成,
返回值数组的每个元素为人口组成字典,且更新模式type=1。
需要注意,name参数为人口迁出的目的地。
当前地点的人口变化也需要包含在返回值数组内(即需要计算当地的人口减少)。 |
| get\_population\(self\) | dict | 返回人口组成字典 |
| get\_param\(self\) | dict | 返回\_model\_param |
| get\_export\_info\(self\) | dict | 返回迁出率与迁出偏好组成的字典 |
##### 3.2.3 InternalModel类
使用用户提供的函数或内置的函数实现地区内部感染情况的相关计算。
###### 数据成员
| 名称 | 类型 | 功能 |
|---------------------|-----------|-------------------------|
| \_customized\_func | function | 储存用户自定义传染函数,该函数的要求如下:
有且只有两个必选参数,且参数1传入人口组成的字典
(2\.2\.2节中除去name的数据所构成的字典),
参数2传入模型所需的参数字典(即Region\.\_model\_param);
且返回值必须为形如参数1的人口组成字典。此外返回的字典可以增加key为type,
值为0或1的项,用于指示Region\.update的覆盖方式(可缺省) |
###### 函数成员
| 定义 | 返回值 | 功能 |
|-----------|-------|--------------|
| \_\_init\_\_\(self, model\_func\) | None | 初始化\_customized\_func,初始化\_customized\_func,如果参数为空则指向内置函数 |
| calculate\(self, population, model\_param\) | dict | 用于调用传染模型,参数、返回值同自定义函数。
当用户自定义函数为空时,使用内置函数。
如果使用内置函数,
需要在内置函数内部检测model\_param中数据取值是否合法 |
| set\_func\(model\_func\) | None | 用于更新模型函数 |
##### 3.2.4 InfoLoader类
负责读取updates.json与init.json文件,为了便于用户实时对地区进行更新,updates.json文件在每日都会重新被读取。该类在读取时同时要实现对于路径合法性的检验(合法性指:初始化路径下必须存在init\.json)。
###### 数据成员
| 名称 | 类型 | 功能 |
|------------|-------|-----------------------------------------------|
|_path | path| 保存输入配置文件夹路径 |
###### 函数成员
| 定义 | 返回值 | 功能 |
| -------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| \_\_init\_\_\(self\, input_path) | None | 初始化_path,当参数为None时(即缺省时),
则指定为当前目录下的input文件夹 |
| get\_init\_info\(\) | dict | 利用_path读取init\.json后,创建以地名为key,
Region对象为值的dict并返回。 |
| get\_cur\_update\(cur\_day\) | list | 参数为当前天数,返回值为updates\.json中的
当前日期的更新数组。当前日期不存在更新信息或文件不存在时返回\[\]
(每次调用此函数都需要重新读取updates.json) |
| reimport_update_json\(self\) | bool | 从硬盘重新加载更新数据,返回值代表文件是否存在 |
##### 3.2.5 ResultsWriter类
负责将结果缓存并提供将结果写入results.json文件文件的函数。
###### 数据成员
| 名称 | 类型 | 功能 |
|--------------------|-------|---------------------|
| \_results\_buffer | dict | 形如results\.json的字典 |
###### 函数成员
| 定义 | 返回值 | 功能 |
|-------------|-------|---------------------|
| \_\_init\_\_\(self\) | None | 初始化\_results\_buffer |
| write\_to\_buffer\(self, results, cur\_day\) | None | 将每次运算的结果暂时储存到\_results\_buffer。
result参数为地名与各地输出参数的字典
所构成的dict。cur\_day为当前日期(将cur_day统一转化为str)。 |
| write\_to\_file\(self, output\_path\) | None | 将\_results\_buffer中的内容写入results\.json中 。
output\_path为输出文件夹位置。
为None时,则指定为当前路径下的名为output的文件夹。
注意对路径合法性的检验。 |
| get\_buffer\(self\) | dict | 返回\_results\_buffer
#### 3.3 详细参数格式
| 名称 | 定义 |
|---------------------------------------------|---------------------------------------------------------------|
| Controller\.\_regions;
InfoLoader\.get_init_info返回值\[2\] |{ "region1": region_object1, "region2": region_object2}
| Region\.\_\_init\_\_参数info | 一个Region对象的所有数据成员构成的dict。
与init\.json中的regions数组的一个元素格式完全相同。 |
| Controller\.get\_results返回值;
ResultsWriter\.\_results\_buffer;
ResultsWriter\.get\_buffer返回值 | 与results\.json结构完全一致 |
| Region\.\_dest\_pref | 与init\.json中的dest\_pref完全相同 |
| Region\.\_model\_param;
Region\.get\_param的返回值;
InternalModel\.calculate中的model\_param参数 | 与init\.json中的model\_param完全相同 |
| Region\.update中info参数 | Region类的任意数据成员与type(标记覆盖模式)所构成的字典。
即updates\.json文件中的单个地区的数据。 |
| Region\.get\_migration的返回值 | { "name": "destination", "type": 1, "susceptible": 10,
"exposed": 0, "infected": 0, "recovered": 0,"dead": 0}
如上结构构成的list |
| Region\.get\_population的返回值;
InternalModel\.calculate中的population参数 |{ "susceptible": 10, "exposed": 0, "infected": 0,
"recovered": 0, "dead": 0}
| Region\.get\_export\_info的返回值 |{ "export_rate": 0.05, "dest_pref": { "region2": 1.00 }} |
| InternalModel\.calculate的返回值 |{ "type": 1, "susceptible": 10, "exposed": 0, "infected": 0,
"recovered": 0, "dead": 0} |
| InfoLoader\.get\_cur\_update | 与updates\.json中单个日期对应的格式一致 |
| ResultsWriter\.write\_to\_butter的results参数 | 与results\.json中单个日期对应的格式一致 |
#### 3.4 包结构
```
transmission_simulator
io
__init__.py
info_loader.py
results_writer.py
structur
__init__.py
internal_model.py
region.py
__init__.py
transmission_simulator.py
```
### 四、开发环境
#### 4.1 依赖
注:只列出需要手动安装的包
1. matplotlib
2. geopandas
3. descartes
4. colour
5. pyqt5
#### 4.2 Python版本
Python3.8.3
Python3.9.0