|
什么是传染病动力学?numpy和matplotlib用python实现传染病模型SI模型SIS模型SIR模型SEIR模型 什么是传染病动力学?最近,在报道疫情的众多新闻中,相信大家也看到过一些来预测新型冠状病毒会导致感染肺炎的人数。你一定好奇,这个人数要怎么预测呢?预测人数又有什么用呢? 事实上,从学科方向来说,这类研究属于传染病动力学,就是用数学模型去描述传染病在人群中传播的规律,从而预测患病人数,进而指导政府制定措施和政策去控制传染病的传播。
% v, U* B4 ^2 H+ K/ Q这类研究最早可追溯到18世纪Daniel Bernoulli对天花的研究,而我们今天所要介绍的SIR模型是1927年Kermack与McKendrick在为了研究伦敦黑死病而提出的,是传染病动力学中最基础的模型。 介绍了传染病模型的背景信息,不知道现在你对传染病模型更有兴趣,还是执着地对python更有兴趣呢?不论哪种,这篇文章会满足你所有的好奇心。 numpy和matplotlib首先,安装一下这节课我们需要使用的两个python包,numpy和matplotlib。' I W# c# A1 `! ?
numpy-是python进行科学和矩阵运算最常用的包。 用numpy建立一维数组,存储和计算每天传染病人数的数据。
5 o/ T5 Y& N2 Fimport numpy as np import matplotlib.pyplot as plt 用matplotlib绘制传染病人数随天数变化的曲线,给出模型预测人数变化的直观认识。 好啦,下面开始用python实现传染病模型吧。 用python实现传染病模型为了让大家能够更好地理解,我们先不直接说SIR模型,我们从最简单的开始。 SI模型首先想象这样一个场景,一个城市有 个人,假设没有人出生和死亡,忽然有一天有 个人感染了病毒成为了患者,如果每天每个患者能够有效传染 个人,那么第二天患病人数是多少呢?最简单的答案是: ,也就是说每天都会新增 个患者。那这样以来,在无限远的将来会有无穷多的人被感染,显然这是不合理的,那错在哪里?仔细思考,你一定发现了,已经患病的人就不能再被传染了,所以我们有必要把人群分为两类,易感者(S-susceptiable)和感染者(I-infective)(你猜的没错,这就是SIR中S和I的含义,R的含义之后介绍再讲)。为了之后方便计算我们记易感者和感染者在人群中的比例为 ,那么 。我们重新考虑上面的问题,顺便来个示意图: Image Name这样的话,每天新增的患者数为 ,也就是总传染人数乘以易感者所占的人群比例。
' V5 T7 E$ h6 T4 t \那么每天的感染者比例的增加量就是 。我们假设城市有一千万(N=10的7次方)人,每个患者每天接触感染每天0.8人(lamda=0.8),初始感染人数为45人(i0 = 45/N),我们来模拟70天(T=70)的情况。 # population7 A$ T& M5 B2 D. O' c
N = 1e72 m1 I- \, c8 F$ V; D9 s" p: m
# simuation Time / Day" c9 R/ t1 U$ o
T = 70- ^) i3 w+ s) T- W5 }
# susceptiable ratio
8 j# {; O6 r6 ]. D- j$ t/ ?s = np.zeros([T])
3 Q! T' I* d6 b# g7 A# infective ratio
9 u- b5 L, C0 I3 Di = np.zeros([T])7 I. a+ O- x( s1 ^. u2 S
# contact rate, \; E1 u+ s, l4 X' p6 y
lamda = 0.8
2 V1 @, a& b3 _ u, w! r; U9 U5 {+ ?+ t, W" n' {- t
# initial infective people
' y r: u, x& S. l( a3 @% \" zi[0] = 45.0 / N/ i# K. ^) }8 n2 u4 X: I9 T, ?3 V
& C) L! X( s, afor t in range(T-1):8 N" s9 K% y$ \) A6 Z
i[t + 1] = i[t] + i[t] * lamda * (1.0 - i[t])- [3 l! ]* c$ ?. q8 K! X3 \
6 i0 M& Z o: Z
8 t( {) `. D' j. [; v' T& |# W
8 n' H) Y1 w3 S0 `9 j* T: T相信其他语句大家都明白,新知识是这两行:, M9 r7 O, m3 R5 g. ^' k" k( Z
% g/ j6 E) q7 @) r, `" u
7 j+ K' K( i- ls = np.zeros([T])
* D7 E/ r9 {6 u: M/ fi = np.zeros([T])
4 `* E, M' K6 P+ G8 I) o: K4 k
这两句话的意思是一样的,就是利用numpy(已被我们重新命名为np)的函数(zeros())来建立一个所有元素都是零的数组,而给的参数决定了这个数组的维度。比如:
! { h K) h( m) t9 Z+ H
! ?- h9 X1 b; Fa = np.zeros([2,3])/ g r' Q. e( Q
a7 w' b8 b/ b8 l Y8 Z7 c
* I$ H _; w7 {3 O. M. harray([[0., 0., 0.],
3 [' Q- J9 a7 } | [0., 0., 0.]])! g) I, O: s8 H$ u1 D4 e
7 f9 {8 g4 s, S; y, |: x9 w+ ~$ J2 p/ H/ {
array([0., 0., 0., 0., 0.])
5 ~$ x: W5 B/ F# ~: n8 Q9 k6 O4 P' A2 R* E2 X) I
' ~0 O7 r/ H8 G$ V( ?* b
类似的还有产生元素全部是1的数组的函数np.ones():
9 ?4 t. T' |+ Y5 c$ n- i2 a3 l9 t& G8 G( F" x
a = np.ones([5])
1 F' C% Q! b/ R7 Ka5 X, _& l% m2 S) k+ n# T5 j
+ |8 [; z' g3 T- t3 { Varray([1., 1., 1., 1., 1.])
; a) Q2 F& w9 d, Q. j* Q* I
& w2 c9 w/ G( O2 H" }. D; U6 j" V) D/ X" F5 i) g0 _
a = np.ones([2,3])" Y: L+ z- r( h
a
2 c3 z# x8 I0 Q" u) _/ r: C0 D* o
g5 R) j) F; u
array([[1., 1., 1.],4 l+ ^* x. ^) U0 r8 \( |* |
[1., 1., 1.]])- A- M4 u7 p; C- J: A' V
2 ~+ S$ h" a, u! d4 h# a
2 W5 \. {2 M0 j, O4 o
plt.plot(i)
2 \# v$ h+ g! G
`: G% }3 g8 _$ @0 z
2 k2 l- h% n0 D" g; P[<matplotlib.lines.Line2D at 0x7f0c2768d6d8>]
' ]( {, V- p) R
, o# S" K5 p4 z: E9 \& I- E5 O0 S2 u$ Q& k- l
" w$ a: | R) q! n4 \
/ F8 [, W1 @, A# k& x, G- S) h6 v3 I1 L
实现SI模型的核心代码是第三个cell的第11,12行:
% B# W0 X8 a4 m1 x! Y
|" l- G H2 M8 Zfor t in range(T-1):% d9 z' j/ z R$ v X$ S
i[t + 1] = i[t] + i[t] * lamda * (1.0 - i[t])6 S, s" c% L- p7 x3 Q2 r
# |- e* t7 c8 W1 F. h( K
就是我们建立的数学模型,利用python的for循环语句累加迭代的方式把每天的增加量叠加到感染者比例上。 运行代码完成计算,我们利用matplotlib的pyplot来画出感染者的随天数的变化曲线: # [2 i8 o4 {: |/ J
fig, ax = plt.subplots(figsize=(8,4))
3 V) v: N+ ~' r* w! rax.plot(i, c='r', lw=2)
! L: M6 D4 g. v" d* t, yax.set_xlabel('Day',fontsize=20)
1 V% E3 D0 Y% l. x2 b+ Max.set_ylabel('Infective Ratio', fontsize=20)4 {$ z4 i4 s' Y9 J& e2 E, Z/ d
ax.grid(1)1 T6 \9 t& N, R# r$ N' \
plt.xticks(fontsize=20)9 t, a, a6 n! m S+ I' @( H2 V% {0 E% J1 [
plt.yticks(fontsize=20);
2 B& w5 J% b6 j$ D6 v' o
: l+ m7 {9 G+ t" y! f$ U
! P2 }2 V( D# o$ p1 p![]()
: {4 @) ~3 `2 e" J% D6 g0 I
1 k9 t# O$ M% i1 F" y; r从这个结果看到,大约在25天左右,全部人群都会变成感染者,感染率 。! o3 \6 y/ i7 b% H; z2 b
在程序中我们假设每天每个患者传染0.8个人,你可以改变lamda的值,观察全部人群感染的天数的变化。
3 A0 l4 k2 O) U: T& ]. @认真思考你会知道,lamda的现实意义就是该城市的卫生水平,衡量的是消毒,隔离这些措施执行得怎么样。回到传染病模型,按照SI模型计算的结果,我们全人类都会患病,这好可怕!原因是我们忽略了一个很重要的因素,那就是我们有奋斗在一线的医护人员,我们会被治愈!所以SI模型只适合研究具有高传染风险又不能被治愈的病(比如HIV)。 但是对于其他病,我们是可以靠医疗和自身免疫系统康复的,那么紧接着的一个问题就是,被治愈后还会再被传染上嘛?根据这个问题的回答不同,我们有了两个不同的模型,SIR 和 SIS。现在可以揭晓,SIR的R的含义了,就是移出者(Removed),现实含义就是指被治愈后不会再被感染的人。而SIS表示治愈后仍然还是易感者。下面我们用python来分别实现这两个模型。 SIS模型为了实现这个模型,我们需要引入新的一个参数,治愈率 。好啦,先上我们的新示意图: Image Name和SI模型做比较,区别就是计算感染者的增加数时要减去被治愈的人数。5 }2 p0 Z, j# A! \' N# z" K) W& G
所以这时候每天的增加的感染者为: ,: s/ X: C% C9 o8 Z. q" D
增加的感染率为: 。7 M5 b+ G0 L* r/ z) N0 D
模型完成啦,修改python代码:' E/ T6 ]5 H8 W
# susceptiable ratio' y9 O/ r7 f O5 \- c( Q% U1 y3 s4 E
s = np.zeros([T])5 O6 p# `0 S' E7 y
# infective ratio
7 X& f$ d+ x! m. B- A* ui = np.zeros([T])- F8 {( Q/ J3 d6 B3 E1 R
2 V# ?& @7 Q+ j+ q# contact rate
( q6 ~% ]6 X( i/ O1 Vlamda = 1.0
& G) d J; w% C+ n# recover rate
# S/ k# O7 E/ `8 M3 w/ Xgamma = 0.5 % p/ L% ~6 a% I: ~1 Z& @, \7 k" d/ Z
; ?) Z8 U5 K, u3 X, r
# initial infective people
/ v* L4 }. k4 P7 h- y7 O8 W7 Oi[0] = 45.0 / N
( _/ P) H6 _2 X( a( l, W
' s6 Y, B' ]) Q) r6 R2 J7 j, Cfor t in range(T-1):
% q2 ^# Y8 |0 J7 \) F i[t + 1] = i[t] + i[t] * lamda * (1.0 - i[t]) - gamma*i[t]
1 X2 A" v' s' q
% O! P; @# i& P K8 H
1 N7 O/ p& `& o7 W: F( d2 i- z' L
1 Y# d( c+ N: C- N, L y运行代码,我们画出曲线(代码和SI模型的画图完全一样):8 D% \ } D" R7 G7 U
' N2 A& \/ W/ i: N$ [3 e7 E3 O
fig, ax = plt.subplots(figsize=(8,4))+ d5 ~) w g+ H1 _2 ~, g
ax.plot(i, c='r', lw=2)
1 E0 Z. }2 C6 D7 max.set_xlabel('Day',fontsize=20)
. ^( q- h( z" Zax.set_ylabel('Infective Ratio', fontsize=20)
6 W# X/ g! l, R+ q& v, Sax.grid(1)0 a: f B8 w0 E: D A2 p
plt.xticks(fontsize=20)5 p4 w( x5 k( O& F5 X
plt.yticks(fontsize=20);2 c7 W. G% |3 `. L/ o& O, B; w0 b
, Y# ^4 k2 B/ P: v+ F, i6 ^' q$ \![]()
A9 w. V W) U2 [
+ l0 }- F4 U0 b1 R/ D u( t; I7 p. z. [' ]2 l! Q2 i+ r# N
行代码,我们画出曲线(代码和SI模型的画图完全一样)2 J# f) M8 `$ h, E% q
可以看到,达到最大感染率的时间退后10天左右,最后感染和治愈达到动态平衡,人群中有始终有一半的人感染着。所以,SIS模型适合研究具有传染性和反复性的流行病,比如常见流感。同样的,感兴趣的话,改变lamda和gamma的值,观察曲线的变化。和lamda不同的是,gamma的现实意义就是对这种疾病的治疗水平。 SIR模型加入了移出者,被治愈的病人不会再被传染,先上我们的新示意图: Image NameSIR 模型4 O% t& d) H: k3 L- y
注意到这里,人群被分成了三类,不再只有I和S,所以相比于之前的模型,我们需要找到新的约束关系。现在我们需要分别计算三种人每天的增加量了: t; U3 P4 x3 b5 I7 x
- 易感者:每天都在被传染,所以一直在减少,减少量为被传染的人数:
- 感染者:增加了被感染的人,减少了治愈的人:
- 移出者:增加了治愈的人: . v* o) j( P, q" P0 d# `
建模完成,修改python代码,并且假设人群普遍易感,新型疾病,初始没有移出者。
& H' s+ a7 ?3 R& [# population
' [8 J5 F* f8 U2 q) VN = 1e7 + 10 + 5
, k2 C, c1 S6 }# simuation Time / Day. T5 L6 A% t- K# H9 W$ L6 ^
T = 170% i- Z; [% q& I0 n- h, ^
# susceptiable ratio
1 \# O) N }9 S+ v: ds = np.zeros([T])- `: D% s- F" r6 k
# infective ratio, u* w& O$ C3 v* t# P
i = np.zeros([T])( g) b# C m' V5 a
# remove ratio
# H1 ]8 l5 X) Z( O+ Jr = np.zeros([T])( ^/ J/ ?9 k6 L' a
+ ]% \# m, p8 \1 ?- M3 U. P
# contact rate
# |6 j7 S; T4 \! m/ {' Xlamda = 0.2586 ^ U0 y0 |% d, K
# recover rate
2 [/ i/ N S0 d# Rgamma = 0.0821% J& r3 i1 T( t# i4 T- y2 p
6 u. j- |. f+ b) l1 `$ o+ L
# initial infective people
5 G) F/ Q7 B4 [, Y! C1 Li[0] = 10.0 / N
4 ~* d9 l5 ~! W: }s[0] = 1e7 / N
/ Q/ x4 P: a" M" s6 vfor t in range(T-1):
6 W' I4 |, \9 c3 f$ i% a5 c i[t + 1] = i[t] + i[t] * lamda * s[t] - gamma*i[t]
+ Y1 r6 L8 F V b s[t + 1] = s[t] - lamda * s[t] * i[t]5 O, O; \% m6 U2 n
r[t + 1] = r[t] + gamma*i[t]* c: ?6 I; S, p+ p" b: ^* o
% g4 @% ~) _3 Y
fig, ax = plt.subplots(figsize=(10,6))
z9 J0 k2 o6 t* Q0 Dax.plot(s, c='b', lw=2, label='S')
& r% r c0 F" v: ^ax.plot(i, c='r', lw=2, label='I'), I6 P: X: p$ D9 F7 ~8 \* Q/ r' _
ax.plot(r, c='g', lw=2, label='R')
) V+ r# B6 _8 N6 _! i3 T7 Wax.set_xlabel('Day',fontsize=20)+ d s( A' c) `/ J
ax.set_ylabel('Infective Ratio', fontsize=20)
; j0 f8 W& u" S7 ~9 gax.grid(1)
2 O' N1 z6 S/ C; t, aplt.xticks(fontsize=20)
6 \- Z5 t& m6 t' ^# S) ]0 aplt.yticks(fontsize=20)
, ?9 H, R/ u; e1 N& u+ Aplt.legend();7 E, j' _0 e) I+ z! v; g
9 Q5 x! z! g7 M3 d
0 T" j# k! t3 `0 b! M' Z$ m, G& p! d r3 T 3 o) v; Y) G+ H3 Q2 E* {: j, n
$ {) }' q# y( D. \
感染人数峰值发生在一个月左右,最大感染人数不到人群的20%, 但是最终人群的80%都会得此病(就是最终的移出者的比例)。SIR模型适合研究没有潜伏期的急性传染病,治疗后能够痊愈并具有抗病性。 到这里,虽然不准确,我们也可以先用SIR模型来分析一下此次疫情,武汉新型冠状病毒的传染病动力学! 模型有了,其实就是确定参数的问题。一开始就有人做了这个工作: Image Name于教授给的参数是参考了非典的, ,初始易感人数为一千万, 初始感染10人,初始移出者5人,那么我们的城市总人数 , 带入我们的模型得到结果:重现于教授的模型' s/ F5 f& t: z$ n' j- c
高峰和尾声日期的推测基本相符。 - i% A, U/ L3 f0 t! Q/ A; K
# susceptiable ratio
9 p; _! o! |& L7 h. Ks = np.zeros([T])
+ \1 @2 w1 I: _8 _; T: I) q# infective ratio1 B1 [4 B3 i7 \4 E
i = np.zeros([T])7 j3 e1 u1 H) @& W: s5 V* l5 \
# removed ratio
8 V4 e, q$ ?% h8 [; m; A3 Xr = np.zeros([T])8 u D8 t- T) l4 U+ X
0 I- |) \ f* H2 A6 S) M) \# birth ratio
. {4 f+ o% F% C& P! jb = 20.0 / N/ r% f2 Z5 d3 B( g8 I: U& {
# death ratio4 y4 X& y- J* l7 ~! P9 R
d = 10.0 / N. |1 P) V: L- e3 m$ [& Z, D
( _& ^4 J- O! b2 L" k# contact rate" ^ E& U4 {" I% H' e# e8 h6 ?
y = 1.5( @: g2 y0 T4 }2 m! Y+ V
# recover rate
9 o- D8 v# g8 B6 gu = 0.8 # 1 / infective_period! ^* Q" l* @% t) j% b6 M
& \5 x, d, k( E: w6 t" E- T9 b
# sigma = y / u
0 U* H# I3 L/ X! t: u
) x' h3 A6 q3 W( ]7 d) G; _# initial infective people* ~9 k, p" X! r# V0 r
i[0] = 45.0 / N$ r, B$ m8 k* _% m; `
s[0] = 1 - i[0]
. l* r- t; K) zfor t in range(T-1):: v1 R/ H5 ^% O K4 _+ ], p2 v
i[t+1] = i[t] + i[t] * y * s[t] - u*i[t] - d*i[t]
, k n6 c& S/ S4 z# F4 {9 P s[t+1] = s[t] - y * s[t] * i[t] + b - d*s[t]
x8 i/ d7 ?, j0 Y7 | H. W2 z r[t+1] = r[t] + u*i[t] - d*r[t]; B* s R0 Y0 W4 l
+ e7 U' d+ T4 u+ l: }1 Y. Q
plt.plot(i)6 S+ q' x4 h. ^1 R+ L
plt.plot(s)
) [' n L3 E" x6 g6 Pplt.plot(r), n/ g$ j% J4 y; e ]
plt.plot(np.diff(i),ls='--')+ F4 t3 S1 d6 }" ~$ Y
s) y7 [& L4 p2 Z: E
) {6 W6 z* G2 _+ L/ y F
[<matplotlib.lines.Line2D at 0x7f77796e8518>]
) L, O+ d2 s% j3 K, }
) V1 U! J% w! k8 O: y6 f $ `2 b5 l& E$ i
9 n& M6 i: P pSEIR模型但是,SIR模型和实际情况的出入会比较大,因为忽略了太多因素了,比如说潜伏期,比如说政策调控,药物,出生死亡等等。下面我们可以和前面一样,把潜伏期考虑进去,新增一个人群,叫潜伏者E(exposed): Image NameSEIR模型# k/ H( V" j' r
同样的我们需要计算各人群每天的增加量: S:每天减少: $ j: `( Z! ~7 a# S! j! x1 m3 C7 D, d
E:每天增加传染,减少发病: 5 W& b6 |9 ^# i6 r4 V- F
I:每天增加发病,减少治愈: " q1 n; S' I! E
R:每天增加治愈: . ?" i6 E; g, G) ]+ C& t5 ?- Y; R
建模完成,修改我们的python程序,这里的 可以理解为潜伏期的倒数。给的4天。新型冠状病毒给目前临床的潜伏期是3-14天。
6 M8 L- J# S, J. X5 y. p# population. v# x8 k0 F3 }8 f# u: m
N = 1e7 + 10 + 5
5 O w8 i( M' j1 G3 f" k# simuation Time / Day
* W1 N; ^5 y& J6 j7 y" _8 N) zT = 170- I' n! ~& n4 j1 T! C1 R, l
# susceptiable ratio
: H1 c: A5 K: ^. U' x$ Ds = np.zeros([T]). x% c! k4 z4 d
# exposed ratio
0 n8 O' I6 a( Ye = np.zeros([T])
5 \ S' k O0 S( C$ g$ I' J# infective ratio
1 {. V8 K+ j/ \9 E7 p1 R! F5 si = np.zeros([T])
0 z- c' I- o# G. ^# remove ratio
" V z4 @2 A1 }7 [ v9 Y' n7 M7 Fr = np.zeros([T])6 y- P( S9 R- R) m6 [
) }# f: }# ^- { f3 f; K* R6 u# contact rate- p9 z0 Q: ^% E1 V, Y# [
lamda = 0.5
7 r. T0 c/ {; Z. \# recover rate; o8 F1 \. G) e d( C- i! E* X
gamma = 0.0821
/ b6 P5 G1 t! j P; n/ Z# exposed period# V4 y' i- y% N7 R1 \
sigma = 1 / 4: x6 Y) \7 B: q; r% M1 F
7 K( \- m6 u: X1 F) _+ M. C- B. a3 D4 u
# initial infective people4 \. y: k! E- z1 G J* r! O
i[0] = 10.0 / N
- Y u& F) y+ c1 R, ?4 ^" ?5 zs[0] = 1e7 / N/ p2 g, H4 P6 S7 c$ n4 Y1 Y6 f
e[0] = 40.0 / N
8 c* \+ Q3 g; h9 ^for t in range(T-1):0 f7 S }" P* d- [ Y. }$ {
s[t + 1] = s[t] - lamda * s[t] * i[t]1 r2 }/ E! ^5 G
e[t + 1] = e[t] + lamda * s[t] * i[t] - sigma * e[t]' A$ k) q0 N- y3 R; A8 F7 Y
i[t + 1] = i[t] + sigma * e[t] - gamma * i[t]7 M7 Z" X6 Y' L z
r[t + 1] = r[t] + gamma * i[t] t# [9 u9 H9 w) U( p
% e* B8 Z r) ]* S
) W3 B; h, `0 H% v- w" b7 T
fig, ax = plt.subplots(figsize=(10,6))/ o* B, I, J) r0 k& V2 Y( U; o
ax.plot(s, c='b', lw=2, label='S')
( e* s# @" }% r5 y3 sax.plot(e, c='orange', lw=2, label='E')
) c* k. a0 q$ y; C+ b1 j) R' g% vax.plot(i, c='r', lw=2, label='I'). D0 s9 n6 R3 w' s' h, [ w
ax.plot(r, c='g', lw=2, label='R')0 \) g# T& z: t9 k P$ a! l% j4 j
ax.set_xlabel('Day',fontsize=20)- q0 q% F9 U; ~' d1 a4 C
ax.set_ylabel('Infective Ratio', fontsize=20); \4 Q; `/ M, I; F- S
ax.grid(1)6 t, ^: l7 R) ?8 A
plt.xticks(fontsize=20)
. q) i/ F9 [3 s p- oplt.yticks(fontsize=20)
+ k0 G$ Z0 P: c& h& ^4 U6 |plt.legend();9 p. y" V5 s: N2 P9 t' x
# J4 e, {& C. H. _# E' o
I! ^& s8 B8 N% I
3 E4 l0 P& f- _' M& y8 b7 g
: M7 y$ |# z& H
按照模型的结果,此次疫情可能真的要持续到 三四月份。这个接触率 真的非常影响表现,模型给的是个常数,但是由于政府措施的原因,这应该是个变化的值。
8 e) a2 K% R1 P. y- E$ ~( y# }( I还有治愈率 也是。没有完美的模型,但是随着考虑因素的增多,就会越来越接近实际情况,从而指导政府的疫情方针政策的制定。
# S( Y" _: b4 P7 T7 k% Q& _
/ g) `: [: M3 ^6 ]0 } I M
. v: h5 H; l1 H. i; a9 k6 U
; D. j. G) m. u5 n* L
$ i3 \8 i6 `) c: J" B4 n! H4 z: b |