用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的循环体中使用else语句的方法
Mar 30 Python
用Python编写简单的定时器的方法
May 02 Python
TensorFlow的权值更新方法
Jun 14 Python
numpy给array增加维度np.newaxis的实例
Nov 01 Python
python 实现敏感词过滤的方法
Jan 21 Python
python调用自定义函数的实例操作
Jun 26 Python
Python collections中的双向队列deque简单介绍详解
Nov 04 Python
Python for i in range ()用法详解
Sep 18 Python
python爬虫学习笔记之Beautifulsoup模块用法详解
Apr 09 Python
文件上传服务器-jupyter 中python解压及压缩方式
Apr 22 Python
Django项目配置Memcached和Redis, 缓存选择哪个更有优势
Apr 06 Python
利用python做表格数据处理
Apr 13 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 stream_context_create()作用和用法分析
2011/03/29 PHP
PHP接收json 并将接收数据插入数据库的实现代码
2015/12/01 PHP
CheckBox 如何实现全选?
2006/06/23 Javascript
[原创]静态页面也可以实现预览 列表不同的显示方式
2006/10/14 Javascript
TopList标签和JavaScript结合两例
2007/08/12 Javascript
JQUERY实现左侧TIPS滑进滑出效果示例
2013/06/27 Javascript
使用phantomjs进行网页抓取的实现代码
2014/09/29 Javascript
全面解析Bootstrap中nav、collapse的使用方法
2016/05/22 Javascript
Vue 2.0+Vue-router构建一个简单的单页应用(附源码)
2017/03/14 Javascript
nodejs制作爬虫实现批量下载图片
2017/05/19 NodeJs
详解node单线程实现高并发原理与node异步I/O
2017/09/21 Javascript
vue实现前进刷新后退不刷新效果
2018/01/26 Javascript
NodeJS父进程与子进程资源共享原理与实现方法
2018/03/16 NodeJs
JavaScript对象拷贝与Object.assign用法实例分析
2018/06/20 Javascript
jQuery选择器之基本选择器用法实例分析
2019/02/19 jQuery
vue响应式更新机制及不使用框架实现简单的数据双向绑定问题
2019/06/27 Javascript
在Python中使用SimpleParse模块进行解析的教程
2015/04/11 Python
python 捕获shell脚本的输出结果实例
2017/01/04 Python
python多进程和多线程究竟谁更快(详解)
2017/05/29 Python
Python实现的文本编辑器功能示例
2017/06/30 Python
Python3中正则模块re.compile、re.match及re.search函数用法详解
2018/06/11 Python
Python对切片命名的实现方法
2018/10/16 Python
Flask框架模板继承实现方法分析
2019/07/31 Python
python kafka 多线程消费者&amp;手动提交实例
2019/12/21 Python
使用Pycharm(Python工具)新建项目及创建Python文件的教程
2020/04/26 Python
video结合canvas实现视频在线截图功能
2018/06/25 HTML / CSS
英国领先的在线高尔夫商店:Gamola Golf
2019/11/16 全球购物
Quiksilver美国官网:始于1969年的优质冲浪服和滑雪板外套
2020/04/20 全球购物
数学与统计学院学生个人职业生涯规划书
2014/02/10 职场文书
《放小鸟》教学反思
2014/04/20 职场文书
乡镇党员干部四风对照检查材料思想汇报
2014/09/27 职场文书
2014年帮扶工作总结
2014/11/26 职场文书
大学生考试作弊被抓检讨书
2014/12/27 职场文书
安全守法证明
2015/06/23 职场文书
在人间读书笔记
2015/06/30 职场文书
驾驶员安全责任协议书
2016/03/22 职场文书