用Python制作在地图上模拟瘟疫扩散的Gif图


Posted in Python onMarch 31, 2015

受杰森的《Almost Looks Like Work》启发,我来展示一些病毒传播模型。需要注意的是这个模型并不反映现实情况,因此不要误以为是西非可怕的传染病。相反,它更应该被看做是某种虚构的僵尸爆发现象。那么,让我们进入主题。

用Python制作在地图上模拟瘟疫扩散的Gif图

这就是SIR模型,其中字母S、I和R反映的是在僵尸疫情中,个体可能处于的不同状态。

  •     S 代表易感群体,即健康个体中潜在的可能转变的数量。
  •     I 代表染病群体,即僵尸数量。
  •     R 代表移除量,即因死亡而退出游戏的僵尸数量,或者感染后又转回人类的数量。但对与僵尸不存在治愈者,所以我们就不要自我愚弄了(如果要把SIR模型应用到流感传染中,还是有治愈者的)。
  • 至于β(beta)和γ(gamma):
  •     β(beta)表示疾病的传染性程度,只要被咬就会感染。
  •     γ(gamma)表示从僵尸走向死亡的速率,取决于僵尸猎人的平均工作速率,当然,这不是一个完美的模型,请对我保持耐心。
  • S′=?βIS告诉我们健康者变成僵尸的速率,S′是对时间的导数。
  • I′=βIS?γI告诉我们感染者是如何增加的,以及行尸进入移除态速率(双关语)。
  • R′=γI只是加上(gamma I),这一项在前面的等式中是负的。

上面的模型没有考虑S/I/R的空间分布,下面来修正一下!

一种方法是把瑞典和北欧国家分割成网格,每个单元可以感染邻近单元,描述如下:

其中对于单元,和是它周围的四个单元。(不要因为对角单元而脑疲劳,我们需要我们的大脑不被吃掉)。

初始化一些东东。
 

import numpy as np
import math
import matplotlib.pyplot as plt  
%matplotlib inline
from matplotlib import rcParams
import matplotlib.image as mpimg
rcParams['font.family'] = 'serif'
rcParams['font.size'] = 16
rcParams['figure.figsize'] = 12, 8
from PIL import Image

适当的beta和gamma值就能够摧毁大半江山
 

beta = 0.010
gamma = 1

还记得导数的定义么?当导数已知,假设Δt很小的情况下,经过重新整理,它可以用来近似预测函数的下一个取值,我们已经声明过u′(t)。

用Python制作在地图上模拟瘟疫扩散的Gif图

初始化一些东东。
 

import numpy as np
import math
import matplotlib.pyplot as plt  
%matplotlib inline
from matplotlib import rcParams
import matplotlib.image as mpimg
rcParams['font.family'] = 'serif'
rcParams['font.size'] = 16
rcParams['figure.figsize'] = 12, 8
from PIL import Image

适当的beta和gamma值就能够摧毁大半江山
 

beta = 0.010
gamma = 1

还记得导数的定义么?当导数已知,假设Δt很小的情况下,经过重新整理,它可以用来近似预测函数的下一个取值,我们已经声明过u′(t)。

用Python制作在地图上模拟瘟疫扩散的Gif图

这种方法叫做欧拉法,代码如下:
 

def euler_step(u, f, dt):
  return u + dt * f(u)

我们需要函数f(u)。友好的numpy提供了简洁的数组操作。我可能会在另一篇文章中回顾它,因为它们太强大了,需要更多的解释,但现在这样就能达到效果:

def f(u):
  S = u[0]
  I = u[1]
  R = u[2]
 
  new = np.array([-beta*(S[1:-1, 1:-1]*I[1:-1, 1:-1] +
              S[0:-2, 1:-1]*I[0:-2, 1:-1] +
              S[2:, 1:-1]*I[2:, 1:-1] +
              S[1:-1, 0:-2]*I[1:-1, 0:-2] +
              S[1:-1, 2:]*I[1:-1, 2:]),
           beta*(S[1:-1, 1:-1]*I[1:-1, 1:-1] +
              S[0:-2, 1:-1]*I[0:-2, 1:-1] +
              S[2:, 1:-1]*I[2:, 1:-1] +
              S[1:-1, 0:-2]*I[1:-1, 0:-2] +
              S[1:-1, 2:]*I[1:-1, 2:]) - gamma*I[1:-1, 1:-1],
           gamma*I[1:-1, 1:-1]
          ])
 
  padding = np.zeros_like(u)
  padding[:,1:-1,1:-1] = new
  padding[0][padding[0] < 0] = 0
  padding[0][padding[0] > 255] = 255
  padding[1][padding[1] < 0] = 0
  padding[1][padding[1] > 255] = 255
  padding[2][padding[2] < 0] = 0
  padding[2][padding[2] > 255] = 255
 
  return padding

导入北欧国家的人口密度图并进行下采样,以便较快地得到结果
 

from PIL import Image
img = Image.open('popdens2.png')
img = img.resize((img.size[0]/2,img.size[1]/2))
img = 255 - np.asarray(img)
imgplot = plt.imshow(img)
imgplot.set_interpolation('nearest')

用Python制作在地图上模拟瘟疫扩散的Gif图

北欧国家的人口密度图(未包含丹麦)

S矩阵,也就是易感个体,应该近似于人口密度。感染者初始值是0,我们把斯德哥尔摩作为第一感染源。
 

S_0 = img[:,:,1]
I_0 = np.zeros_like(S_0)
I_0[309,170] = 1 # patient zero

因为还没人死亡,所以把矩阵也置为0.
 

R_0 = np.zeros_like(S_0)

接着初始化模拟时长等。
 

T = 900             # final time
dt = 1             # time increment
N = int(T/dt) + 1        # number of time-steps
t = np.linspace(0.0, T, N)   # time discretization
 
# initialize the array containing the solution for each time-step
u = np.empty((N, 3, S_0.shape[0], S_0.shape[1]))
u[0][0] = S_0
u[0][1] = I_0
u[0][2] = R_0

我们需要自定义一个颜色表,这样才能将感染矩阵显示在地图上。
 

import matplotlib.cm as cm
theCM = cm.get_cmap("Reds")
theCM._init()
alphas = np.abs(np.linspace(0, 1, theCM.N))
theCM._lut[:-3,-1] = alphas

下面坐下来欣赏吧…

for n in range(N-1):
  u[n+1] = euler_step(u[n], f, dt)

让我们再做一下图像渲染,把它做成gif,每个人都喜欢gifs!
 

from images2gif import writeGif
 
keyFrames = []
frames = 60.0
 
for i in range(0, N-1, int(N/frames)):
  imgplot = plt.imshow(img, vmin=0, vmax=255)
  imgplot.set_interpolation("nearest")
  imgplot = plt.imshow(u[i][1], vmin=0, cmap=theCM)
  imgplot.set_interpolation("nearest")
  filename = "outbreak" + str(i) + ".png"
  plt.savefig(filename)
  keyFrames.append(filename)
 
images = [Image.open(fn) for fn in keyFrames]
gifFilename = "outbreak.gif"
writeGif(gifFilename, images, duration=0.3)
plt.clf()
Python 相关文章推荐
你眼中的Python大牛 应该都有这份书单
Oct 31 Python
python xlsxwriter创建excel图表的方法
Jun 11 Python
Python实现的knn算法示例
Jun 14 Python
用python3教你任意Html主内容提取功能
Nov 05 Python
Python button选取本地图片并显示的实例
Jun 13 Python
PyQt5根据控件Id获取控件对象的方法
Jun 25 Python
Python安装selenium包详细过程
Jul 23 Python
python 模拟贷款卡号生成规则过程解析
Aug 30 Python
python-sys.stdout作为默认函数参数的实现
Feb 21 Python
使用Django xadmin 实现修改时间选择器为不可输入状态
Mar 30 Python
Python 私有属性和私有方法应用场景分析
Jun 19 Python
python中scipy.stats产生随机数实例讲解
Feb 19 Python
以一段代码为实例快速入门Python2.7
Mar 31 #Python
11个并不被常用但对开发非常有帮助的Python库
Mar 31 #Python
Python的Flask框架中@app.route的用法教程
Mar 31 #Python
使用Python的Flask框架实现视频的流媒体传输
Mar 31 #Python
在Python3中初学者应会的一些基本的提升效率的小技巧
Mar 31 #Python
使用IronPython把Python脚本集成到.NET程序中的教程
Mar 31 #Python
提升Python程序运行效率的6个方法
Mar 31 #Python
You might like
php eval函数一句话木马代码
2015/05/21 PHP
学习php设计模式 php实现合成模式(composite)
2015/12/08 PHP
windows环境下使用Composer安装ThinkPHP5
2018/05/18 PHP
Laravel路由研究之domain解决多域名问题的方法示例
2019/04/04 PHP
详解将数据从Laravel传送到vue的四种方式
2019/10/16 PHP
jquery跟js初始化加载的多种方法及区别介绍
2014/04/02 Javascript
node.js开发中使用Node Supervisor实现监测文件修改并自动重启应用
2014/11/04 Javascript
Bootstrap+jfinal实现省市级联下拉菜单
2016/05/30 Javascript
JS本地刷新返回上一页代码
2016/07/25 Javascript
AngularJS实现动态编译添加到dom中的方法
2016/11/04 Javascript
微信小程序 video详解及简单实例
2017/01/16 Javascript
JS实现AES加密并与PHP互通的方法分析
2017/04/19 Javascript
angularjs 获取默认选中的单选按钮的value方法
2018/02/28 Javascript
vue中v-for加载本地静态图片方法
2018/03/03 Javascript
vue 实现复制内容到粘贴板clipboard的方法
2018/03/17 Javascript
vue-devtools的安装步骤
2018/04/23 Javascript
Javascript实现秒表倒计时功能
2018/11/17 Javascript
vue element动态渲染、移除表单并添加验证的实现
2019/01/16 Javascript
Layer+Echarts构建弹出层折线图的方法
2019/09/25 Javascript
OpenLayer学习之自定义测量控件
2020/09/28 Javascript
详解Vue的异步更新实现原理
2020/12/22 Vue.js
java直接调用python脚本的例子
2014/02/16 Python
python中实现指定时间调用函数示例代码
2017/09/08 Python
使用Python横向合并excel文件的实例
2018/12/11 Python
对Python中创建进程的两种方式以及进程池详解
2019/01/14 Python
Python+threading模块对单个接口进行并发测试
2019/06/25 Python
python tkinter的消息框模块(messagebox,simpledialog)
2020/11/07 Python
一款纯css3实现的竖形二级导航的实例教程
2014/12/11 HTML / CSS
Ray-Ban雷朋美国官网:全球领先的太阳眼镜品牌
2016/07/20 全球购物
蛋白质世界:Protein World
2017/11/23 全球购物
Perfume’s Club澳大利亚官网:西班牙领先的在线美容店
2021/02/01 全球购物
毕业生实习鉴定
2013/12/11 职场文书
大学生推广普通话演讲稿
2014/09/21 职场文书
农村环境卫生倡议书
2015/04/29 职场文书
golang 生成对应的数据表struct定义操作
2021/04/28 Golang
Win11 Dev 预览版25174.1000发布 (附更新修复内容汇总)
2022/08/05 数码科技