|
什么是传染病动力学?numpy和matplotlib用python实现传染病模型SI模型SIS模型SIR模型SEIR模型 什么是传染病动力学?最近,在报道疫情的众多新闻中,相信大家也看到过一些来预测新型冠状病毒会导致感染肺炎的人数。你一定好奇,这个人数要怎么预测呢?预测人数又有什么用呢? 事实上,从学科方向来说,这类研究属于传染病动力学,就是用数学模型去描述传染病在人群中传播的规律,从而预测患病人数,进而指导政府制定措施和政策去控制传染病的传播。
7 ]% A/ T! k0 H) M# G% v这类研究最早可追溯到18世纪Daniel Bernoulli对天花的研究,而我们今天所要介绍的SIR模型是1927年Kermack与McKendrick在为了研究伦敦黑死病而提出的,是传染病动力学中最基础的模型。 介绍了传染病模型的背景信息,不知道现在你对传染病模型更有兴趣,还是执着地对python更有兴趣呢?不论哪种,这篇文章会满足你所有的好奇心。 numpy和matplotlib首先,安装一下这节课我们需要使用的两个python包,numpy和matplotlib。- m: t I$ q# [3 k
numpy-是python进行科学和矩阵运算最常用的包。 用numpy建立一维数组,存储和计算每天传染病人数的数据。
4 C8 X: B5 _; y% \' {import numpy as np import matplotlib.pyplot as plt 用matplotlib绘制传染病人数随天数变化的曲线,给出模型预测人数变化的直观认识。 好啦,下面开始用python实现传染病模型吧。 用python实现传染病模型为了让大家能够更好地理解,我们先不直接说SIR模型,我们从最简单的开始。 SI模型首先想象这样一个场景,一个城市有 个人,假设没有人出生和死亡,忽然有一天有 个人感染了病毒成为了患者,如果每天每个患者能够有效传染 个人,那么第二天患病人数是多少呢?最简单的答案是: ,也就是说每天都会新增 个患者。那这样以来,在无限远的将来会有无穷多的人被感染,显然这是不合理的,那错在哪里?仔细思考,你一定发现了,已经患病的人就不能再被传染了,所以我们有必要把人群分为两类,易感者(S-susceptiable)和感染者(I-infective)(你猜的没错,这就是SIR中S和I的含义,R的含义之后介绍再讲)。为了之后方便计算我们记易感者和感染者在人群中的比例为 ,那么 。我们重新考虑上面的问题,顺便来个示意图: Image Name这样的话,每天新增的患者数为 ,也就是总传染人数乘以易感者所占的人群比例。. ^: Z; T* x& A5 i: a
那么每天的感染者比例的增加量就是 。我们假设城市有一千万(N=10的7次方)人,每个患者每天接触感染每天0.8人(lamda=0.8),初始感染人数为45人(i0 = 45/N),我们来模拟70天(T=70)的情况。 # population
! F0 @ s6 y6 ~& w2 O: rN = 1e73 I* R# l8 a* a. ~6 i; x: T" }6 R, V& \
# simuation Time / Day P6 ?8 F: ?! S) ~) P+ P" X
T = 70
1 Z) c1 Z7 v7 `, F( P# susceptiable ratio; Z) l$ E- u+ n, {3 A w
s = np.zeros([T])1 _5 B% x: ~% k4 R# J; ~
# infective ratio, n9 u9 X! a" L& O5 L, w
i = np.zeros([T])8 y1 ~9 v8 G: w; D
# contact rate
% U, y" x" Y& I' s+ e/ g1 Olamda = 0.8
6 v+ f8 T! N/ r3 F+ s7 i5 u( M- W" ~' F/ g! L$ O, `
# initial infective people# W* i8 ~! b6 i+ O3 h
i[0] = 45.0 / N
) I6 Q6 |1 v; h4 _5 X; i" t0 b- V4 O
for t in range(T-1):5 u" x5 E3 A: M
i[t + 1] = i[t] + i[t] * lamda * (1.0 - i[t])
5 L# H; n8 Y8 N
, A' U7 d( x. J0 x# G& o
5 p- x% l M1 t, h% K4 z% M) K# L3 s, ?/ l
相信其他语句大家都明白,新知识是这两行:
+ Q+ l8 T9 n0 {1 c8 q& i4 U6 F4 c5 l* K9 G/ W' X) G
3 P" H5 N+ X4 P9 L8 W1 l
s = np.zeros([T])
% i1 x: t4 a# z, h/ P7 v5 I! Bi = np.zeros([T])
4 t2 Z, V" K4 I! \# M2 z0 ^. _$ y' M' G( H. Z. I4 O3 k
这两句话的意思是一样的,就是利用numpy(已被我们重新命名为np)的函数(zeros())来建立一个所有元素都是零的数组,而给的参数决定了这个数组的维度。比如:
2 q; W5 t" |4 M1 y$ p) e, c2 H: Z8 ^$ s' B5 @2 P3 Q. X% i
a = np.zeros([2,3])' L: K8 E0 n- y3 S" f
a3 r, l+ |! \2 j5 @
E! @0 r Z# x9 karray([[0., 0., 0.],) k8 N0 M6 A$ k* c
[0., 0., 0.]])2 e6 k7 a$ b! n6 H! R, M
5 v% m' G& i1 h& ]( p1 \
! i" H4 f D# Y2 Farray([0., 0., 0., 0., 0.])
2 X: w: B0 M5 t. K" y) X R4 D$ Z
/ ~: @0 `. N( B8 A& n- A( Q2 f, r9 G
类似的还有产生元素全部是1的数组的函数np.ones():
( u/ r/ O: F$ W: M [" c, i1 F0 K: ?% P! V8 @
a = np.ones([5])
$ f0 J0 ?- L/ q- F# }9 ?3 e0 ha
5 ^; t0 |3 ^; y( w; \
' T% ?! Q3 W9 D4 Warray([1., 1., 1., 1., 1.]) U* [# h2 }- \8 `
2 c; x( j% [* m5 o) t7 [3 L2 y* ]% o% a
a = np.ones([2,3])0 y* f- q! x, T3 f" F
a- F8 H3 O3 p7 j" S
( I$ p! F. C3 S
+ g- A1 O) C% |; S
array([[1., 1., 1.],
* ~- o( @+ C4 A8 F( S% X/ s [1., 1., 1.]])% c t/ j* D- e9 M) q% T: w
. X" `3 I( X& o E' t7 z
, D8 p, X2 s% t" O. L4 ^/ |3 o* bplt.plot(i)9 S) G+ t# B( `5 ]1 }" h9 K
. M, n) c6 C$ q1 s1 m+ ^' i
% V: M* ?& o1 U. a5 {$ O[<matplotlib.lines.Line2D at 0x7f0c2768d6d8>]$ o; p" @7 m/ z9 D, E0 Q
* f' i3 K) R5 ?8 t) q8 W! X: N: p6 s6 P2 Y
" h5 m3 @; n9 [% A
0 S2 n9 [* h" h+ q% A8 C
2 R- d; E' J3 M$ @实现SI模型的核心代码是第三个cell的第11,12行:& @( F' d( A1 a5 e9 |
; T( J" ~5 ^3 s' K, B* d7 R( x/ Yfor t in range(T-1):
( X0 O% N0 ?3 N) I( Y+ z5 y4 n0 _( ]( f i[t + 1] = i[t] + i[t] * lamda * (1.0 - i[t])
3 c- ]- S, A7 I% G$ o) e
, _) Z4 N" z7 v% u3 S就是我们建立的数学模型,利用python的for循环语句累加迭代的方式把每天的增加量叠加到感染者比例上。 运行代码完成计算,我们利用matplotlib的pyplot来画出感染者的随天数的变化曲线: 1 U' ^1 K# m0 `' }# v. U
fig, ax = plt.subplots(figsize=(8,4))
7 o% _* G1 {" Z: Z0 Aax.plot(i, c='r', lw=2)3 o v$ Y# F: j( h5 M; m$ }* B
ax.set_xlabel('Day',fontsize=20)* z% h+ ?( S/ i1 S% I
ax.set_ylabel('Infective Ratio', fontsize=20)
" z' q& }1 Q6 aax.grid(1): G3 f. X" G7 D1 a
plt.xticks(fontsize=20)# B& `: w$ ^6 ^1 T! E |) a4 f
plt.yticks(fontsize=20);# c" q4 i+ Y: |) i! W' U+ _4 M
: g6 O2 p; o; N! w* U3 V
7 \0 Y% k& H! c4 H9 {" l1 Z, g. x
# _' [5 j; Y2 T$ l0 s; {$ F
9 U1 z' N) G) v2 \" ^& G
从这个结果看到,大约在25天左右,全部人群都会变成感染者,感染率 。- x9 `2 V* W: u: F- x2 R5 O# ^
在程序中我们假设每天每个患者传染0.8个人,你可以改变lamda的值,观察全部人群感染的天数的变化。0 R8 m3 O( W# _4 r: H) _3 |
认真思考你会知道,lamda的现实意义就是该城市的卫生水平,衡量的是消毒,隔离这些措施执行得怎么样。回到传染病模型,按照SI模型计算的结果,我们全人类都会患病,这好可怕!原因是我们忽略了一个很重要的因素,那就是我们有奋斗在一线的医护人员,我们会被治愈!所以SI模型只适合研究具有高传染风险又不能被治愈的病(比如HIV)。 但是对于其他病,我们是可以靠医疗和自身免疫系统康复的,那么紧接着的一个问题就是,被治愈后还会再被传染上嘛?根据这个问题的回答不同,我们有了两个不同的模型,SIR 和 SIS。现在可以揭晓,SIR的R的含义了,就是移出者(Removed),现实含义就是指被治愈后不会再被感染的人。而SIS表示治愈后仍然还是易感者。下面我们用python来分别实现这两个模型。 SIS模型为了实现这个模型,我们需要引入新的一个参数,治愈率 。好啦,先上我们的新示意图: Image Name和SI模型做比较,区别就是计算感染者的增加数时要减去被治愈的人数。
) X6 p/ ?% P, h+ l所以这时候每天的增加的感染者为: ,
) m- r1 J1 P3 N6 n增加的感染率为: 。, l; V+ R9 }" e+ ~1 B- K: d) U9 d
模型完成啦,修改python代码:5 r; r/ y3 Q: g( Q+ d
# susceptiable ratio) Q/ U+ x+ c/ ]* s9 L( {
s = np.zeros([T])
0 V3 [( C( T5 e) A3 h- _# infective ratio4 O3 ]+ L1 v U. m7 n9 c
i = np.zeros([T])2 p: J% L& b* S
- j% {1 I5 [$ e0 H' j
# contact rate
( ~. u' M; ~- B. W9 V9 Alamda = 1.0
+ k+ D! W: Z6 T& K9 G9 c) D# recover rate5 P0 u4 t! |8 Y& W3 e, r4 w* q
gamma = 0.5 . ]; J1 p* {% {, V0 W7 ]
. V* @$ k; X8 o, z7 ^) a8 S! d
# initial infective people
, n% _& x$ U! k li[0] = 45.0 / N
+ H0 V* y' h1 S! {6 }1 }8 d) r n( u# v+ g
for t in range(T-1):) O Z2 V R' S! h' V, v
i[t + 1] = i[t] + i[t] * lamda * (1.0 - i[t]) - gamma*i[t]* S2 n! P. d9 K$ w: V% Z( D+ a) z9 k
8 c, ^2 b% X% s- b+ s A; U( D; V
: V) E; p, C9 F- y
运行代码,我们画出曲线(代码和SI模型的画图完全一样):
7 y; ?7 B% f& ?0 E9 x5 ?& q2 `( h0 M8 v3 \# I K" \4 K* }$ d$ i2 S
fig, ax = plt.subplots(figsize=(8,4))7 Y0 ^$ w$ [$ m% d
ax.plot(i, c='r', lw=2)' b1 Z: L4 v9 e. a& K3 K7 R, t
ax.set_xlabel('Day',fontsize=20)- u! Y- o/ z' j4 p, L
ax.set_ylabel('Infective Ratio', fontsize=20)% f; C/ i8 m3 O1 f2 k5 x5 t
ax.grid(1)
6 @0 l) d( |& q) s$ b2 S, lplt.xticks(fontsize=20)+ O" _' y2 x2 c; M' s3 _" |& Y
plt.yticks(fontsize=20);2 n. c& k7 b% c# D
5 N1 I1 r2 K3 h
![]()
0 M: h2 H Q8 f y" V# s2 A' `4 D- d# ]6 V! {8 x
# |; }! i0 y Q& v4 G @% V行代码,我们画出曲线(代码和SI模型的画图完全一样)
; S& x2 e' `8 U. t* T& F可以看到,达到最大感染率的时间退后10天左右,最后感染和治愈达到动态平衡,人群中有始终有一半的人感染着。所以,SIS模型适合研究具有传染性和反复性的流行病,比如常见流感。同样的,感兴趣的话,改变lamda和gamma的值,观察曲线的变化。和lamda不同的是,gamma的现实意义就是对这种疾病的治疗水平。 SIR模型加入了移出者,被治愈的病人不会再被传染,先上我们的新示意图: Image NameSIR 模型0 e# o- P# X, V8 ?
注意到这里,人群被分成了三类,不再只有I和S,所以相比于之前的模型,我们需要找到新的约束关系。现在我们需要分别计算三种人每天的增加量了:
9 z5 O7 [$ L# K$ Y& A' t2 V- 易感者:每天都在被传染,所以一直在减少,减少量为被传染的人数:
- 感染者:增加了被感染的人,减少了治愈的人:
- 移出者:增加了治愈的人: 5 f/ P) h/ Z! r6 C! P+ }4 _8 j
建模完成,修改python代码,并且假设人群普遍易感,新型疾病,初始没有移出者。 + R. L' I% |5 J# u' R
# population% ~4 A% H: z# }' c
N = 1e7 + 10 + 5 A4 k) i% \1 L* Q9 M
# simuation Time / Day
1 l+ U3 a- N" p" ]/ pT = 170
4 M) o% d4 R3 j5 o" l2 V0 H# susceptiable ratio, T/ x( K; Q7 a/ u
s = np.zeros([T])" O5 m$ I0 Y( E
# infective ratio
& x/ Z2 C: |' e& Pi = np.zeros([T]): B8 O( O! @" R; [
# remove ratio, r5 Q7 e/ i. w( P8 \; P
r = np.zeros([T])
' A( f* m+ G4 o! ?: s0 q& R0 ~
! e6 v" r$ M0 S! h# contact rate1 Q( D4 W+ G/ g. L( F) ?: J
lamda = 0.2586
( G1 G* |) g4 J! B& ]" O0 B5 U2 s# recover rate' `' x9 r: S* G X( S- R
gamma = 0.0821* c: M& w) b1 g% R
( A5 A y+ ]2 _) Z" s; x2 P# initial infective people
) i; s$ O& S, B5 t6 M; Ri[0] = 10.0 / N: F* C6 a8 ?# v6 }* \. T/ {
s[0] = 1e7 / N
: l+ e6 R m, Y' @. y/ S0 afor t in range(T-1):8 `! i' f/ `7 T) p& H% o/ b6 u
i[t + 1] = i[t] + i[t] * lamda * s[t] - gamma*i[t] N7 s" \: m0 ]" d1 ~ x9 |" R, `
s[t + 1] = s[t] - lamda * s[t] * i[t]6 u$ a5 y" Y3 u, ]& r
r[t + 1] = r[t] + gamma*i[t]
" V: r0 t: T- l9 ^/ E' D9 _ L( A: N4 e; Y
fig, ax = plt.subplots(figsize=(10,6))& ` y% j, X8 F9 p6 L' h3 S& A3 G
ax.plot(s, c='b', lw=2, label='S'); j1 L# N) A, h+ z; M3 E% j5 V2 j
ax.plot(i, c='r', lw=2, label='I'), C5 e0 F4 e ~7 K V
ax.plot(r, c='g', lw=2, label='R')
! I; r0 c! V% t" J! P3 r* y" Rax.set_xlabel('Day',fontsize=20)
+ I3 ~' R! t, [" I! a0 N" u5 oax.set_ylabel('Infective Ratio', fontsize=20)+ H$ R5 s9 \0 T1 p3 ~) V4 a* m
ax.grid(1)
; ~' [, b8 z' `5 V' mplt.xticks(fontsize=20)
) {* l2 i! n5 _plt.yticks(fontsize=20)6 o6 v2 P0 K. v' k
plt.legend();
) }* ?; y, o; ^% K& ~: C0 v) E6 t9 S4 P; F1 B1 @/ J
6 ?) \6 {% f+ C( x/ L. Q0 o
@ D0 y l0 t* M8 ?# S2 B
# N7 n6 U6 m( Z U3 \+ x
感染人数峰值发生在一个月左右,最大感染人数不到人群的20%, 但是最终人群的80%都会得此病(就是最终的移出者的比例)。SIR模型适合研究没有潜伏期的急性传染病,治疗后能够痊愈并具有抗病性。 到这里,虽然不准确,我们也可以先用SIR模型来分析一下此次疫情,武汉新型冠状病毒的传染病动力学! 模型有了,其实就是确定参数的问题。一开始就有人做了这个工作: Image Name于教授给的参数是参考了非典的, ,初始易感人数为一千万, 初始感染10人,初始移出者5人,那么我们的城市总人数 , 带入我们的模型得到结果:重现于教授的模型! E I- B' L6 P1 R- {
高峰和尾声日期的推测基本相符。
6 z! u' `$ Y' l _# Q# susceptiable ratio
" E4 D$ Z/ d% ns = np.zeros([T])
/ e+ s3 a" }* ~: e; X9 a# infective ratio
4 j& g2 h8 E1 u4 }3 bi = np.zeros([T])
, k/ N0 ]3 U* T+ [) o9 R# removed ratio
& f3 p1 r( p( i8 Z; J4 Br = np.zeros([T])
* _9 l- g5 V7 C$ p! m) J8 \3 B: L! z8 m _
# birth ratio' N4 Y8 g @% A! Q8 a2 Y
b = 20.0 / N& O( o- o) o X7 X2 }
# death ratio7 ^8 V2 k5 K6 Y0 Y- m; \
d = 10.0 / N
: D8 A! S" O0 C1 t' k8 [. H/ U' U% E1 a0 [! A3 d
# contact rate
1 g* b% V- r, F& W7 ]: Ty = 1.51 q$ f' |# `) d! W. W
# recover rate: W$ ~; i6 t% H' a: B' v0 a' [
u = 0.8 # 1 / infective_period& q: D! s( O; V2 ?& i2 r- E! n% e
% H! Q% r5 b- ?+ V6 z# a8 a# sigma = y / u2 ?8 l- Y( k- ~1 A# g4 G- M- q
. n% F( b( U. @5 N" ]- R
# initial infective people
/ n7 H) `7 M! ` _% h; ^# Zi[0] = 45.0 / N
! j( U1 d7 P5 g# Zs[0] = 1 - i[0]
4 }2 w% C" L. L7 g) Efor t in range(T-1):, D' k6 c/ O: Z7 u8 H0 |
i[t+1] = i[t] + i[t] * y * s[t] - u*i[t] - d*i[t]
' U7 n, g1 s) A9 P, J/ h+ S0 ] s[t+1] = s[t] - y * s[t] * i[t] + b - d*s[t]
1 h# \- C6 A8 S* c& w k5 P r[t+1] = r[t] + u*i[t] - d*r[t]
, M' h% _2 h+ ~! O0 o
) z8 G4 X% S! \plt.plot(i)5 @( y- E W0 b. k# Y* W
plt.plot(s): y$ c4 n# {. \0 {
plt.plot(r)2 P& _% O2 ^8 F* G% s
plt.plot(np.diff(i),ls='--')) A) E1 Z) h* c
% m9 f0 `3 Q& |) r3 f( g2 |
# I3 @4 L# W. G+ L& S8 O9 Y% D[<matplotlib.lines.Line2D at 0x7f77796e8518>]
. A2 ?: U6 m O4 J$ f6 Y' L+ M0 @6 r C& ^
![]()
& h1 B' [4 ^# p/ R
8 p$ I3 R' r2 sSEIR模型但是,SIR模型和实际情况的出入会比较大,因为忽略了太多因素了,比如说潜伏期,比如说政策调控,药物,出生死亡等等。下面我们可以和前面一样,把潜伏期考虑进去,新增一个人群,叫潜伏者E(exposed): Image NameSEIR模型( c; X) H; U' G5 @: F( j, F, K$ w
同样的我们需要计算各人群每天的增加量: S:每天减少: 5 r) U% [% Y( u. u* d' |
E:每天增加传染,减少发病: 4 d. x0 }3 F& A; }
I:每天增加发病,减少治愈:
B* y) { R9 v/ cR:每天增加治愈: 6 S% D2 ^( n; n
建模完成,修改我们的python程序,这里的 可以理解为潜伏期的倒数。给的4天。新型冠状病毒给目前临床的潜伏期是3-14天。" t8 J8 g, J( y/ [" K- i- L
# population
4 s9 t0 \9 M" _N = 1e7 + 10 + 56 L* d; Z" x" ~) @
# simuation Time / Day
1 H9 F8 n9 `6 gT = 170
: _ S$ ~7 t! W! W# susceptiable ratio
. c0 l. K2 P- y* Z$ W" O! |s = np.zeros([T])
( |% o1 ]& O% U3 A8 w! X# exposed ratio
) k$ v' B' o% Z ke = np.zeros([T]); K. [6 ?. Y" h f$ d+ v
# infective ratio
: \6 K- s0 K/ ~) m- Y# [% S) w" Zi = np.zeros([T])
8 i5 m ~ P( E7 h2 x# remove ratio# }: ?; [% }7 u7 {3 t: ?
r = np.zeros([T])
. k$ V/ W! | P" ^: n5 L0 O4 x; K% I, N! _0 D1 T' V% x% R g
# contact rate" O& Y+ H& R1 p. u# Z
lamda = 0.5- b6 h0 ^1 F' X* P1 r# ?: ~
# recover rate
9 ]/ b1 y' U! I( igamma = 0.0821' z8 a( A$ w. M( M. B' R+ U
# exposed period5 h& N0 D% `: h+ \
sigma = 1 / 4
) r/ p- i2 k8 [2 V7 q" i; n) _6 M4 A2 y9 n0 S1 _/ b% _3 Z
# initial infective people. f/ H! c" e+ ]: n5 p3 w! g
i[0] = 10.0 / N
& \: N$ K4 y2 A4 t5 a1 ?s[0] = 1e7 / N
: b' d) g# T; k( \1 M/ Ie[0] = 40.0 / N4 n5 u5 t" O, O
for t in range(T-1):. [1 ?: h- L0 E3 V; J
s[t + 1] = s[t] - lamda * s[t] * i[t]
% q& [9 P. a# {9 _. L/ U( I e[t + 1] = e[t] + lamda * s[t] * i[t] - sigma * e[t]
! }% l5 E& B R1 T5 Q% s5 G) k: x i[t + 1] = i[t] + sigma * e[t] - gamma * i[t]8 z1 `, J. N7 G2 [) M$ K# F) i$ h3 `
r[t + 1] = r[t] + gamma * i[t]
6 e3 H, g# h9 n) G4 R
e0 \0 Z' E. l
' E: b$ g6 n7 S6 e- ^fig, ax = plt.subplots(figsize=(10,6))
$ M# R# B! Z$ S3 q, Z7 i: g( |ax.plot(s, c='b', lw=2, label='S')" U6 o+ E- X ]* _, t1 i6 T
ax.plot(e, c='orange', lw=2, label='E') j# ?8 O& N1 }+ \; v
ax.plot(i, c='r', lw=2, label='I')
m8 H0 U0 k. a( Y" v& qax.plot(r, c='g', lw=2, label='R')
! d- @+ S& U% A+ i3 _ax.set_xlabel('Day',fontsize=20)) }/ m5 ^$ m( |( p( q- w$ M+ n
ax.set_ylabel('Infective Ratio', fontsize=20)/ `; C' M% N9 {! d. X( l
ax.grid(1)6 @% X3 N# r( J9 g. g: J
plt.xticks(fontsize=20)4 w9 C3 k) K# }( ?
plt.yticks(fontsize=20)% |) e( G1 t1 x+ Z# e* N5 h
plt.legend();
+ o' r* m$ L$ m( A5 n4 m* O' J/ H8 |) {& W. P
* f. h; L+ k% t6 z' B , q# D3 {# l9 {: N
; ~: ]2 p$ w3 ?% E+ [1 p% x, ~按照模型的结果,此次疫情可能真的要持续到 三四月份。这个接触率 真的非常影响表现,模型给的是个常数,但是由于政府措施的原因,这应该是个变化的值。
! w8 \" k% q% T4 b6 k, H1 Z还有治愈率 也是。没有完美的模型,但是随着考虑因素的增多,就会越来越接近实际情况,从而指导政府的疫情方针政策的制定。9 B: `5 K! h( V: V2 K
' s, I" u: G% L
5 Z- g6 ~0 U' S1 X9 g3 |" r- `
0 n2 o# C" r& {' ^: t
R4 {" m$ i& X. U- c6 _
|