From 01961567859811c98c7463b4ac5be47348833c00 Mon Sep 17 00:00:00 2001 From: Sinan Shi Date: Sun, 13 Nov 2016 16:27:14 +0000 Subject: [PATCH 01/14] update infotb in deltaTime() --- R/deltaTime.R | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/R/deltaTime.R b/R/deltaTime.R index ee58a27..c6b2efe 100644 --- a/R/deltaTime.R +++ b/R/deltaTime.R @@ -69,7 +69,11 @@ deltaTime <- function(record, pseudotime=FALSE, units="hours", tdiff=FALSE) { } return(data) }) - return(new.episode(eps)) + newep <- new.episode(eps) + newep@parse_file <- ep@parse_file + newep@parse_time <- ep@parse_time + newep + } } @@ -81,8 +85,10 @@ deltaTime <- function(record, pseudotime=FALSE, units="hours", tdiff=FALSE) { record@episodes[[e]]@t_admission <- admdsct[[e]]$admt record@episodes[[e]]@t_discharge <- admdsct[[e]]$dsct } + record <- index.record(record) } + if (nep != record@nepisodes) { if (pseudotime) warning(nep - record@nepisodes, From 074a66e2a7d0374944bd0e72c0eaee18e48c36bc Mon Sep 17 00:00:00 2001 From: Sinan Shi Date: Sun, 13 Nov 2016 17:18:17 +0000 Subject: [PATCH 02/14] adding unique patient ids in infotb --- DESCRIPTION | 8 ++++++-- NAMESPACE | 2 ++ R/ccRecord.R | 23 ++++++++++++++++++++++- R/deltaTime.R | 1 - 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 6143b17..d1d0176 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -5,13 +5,16 @@ Version: 0.1 Date: 2016-11-10 Author: Steve Harris, Sinan Shi, David Perez-Suarez Maintainer: Sinan Shi -Description: The package contains essential tools and utility functions to facilitate the data processing pipeline, data cleaning and data analysing of clinical data from Critical Care - Health Informatics Collaborative (CC-HIC). +Description: The package contains essential tools and utility functions to + facilitate the data processing pipeline, data cleaning and data analysing of + clinical data from Critical Care - Health Informatics Collaborative (CC-HIC). Depends: R (>= 3.1.0) License: GPL-3 LinkingTo: Rcpp Suggests: - testthat + testthat, + knitr Imports: data.table, XML, @@ -24,6 +27,7 @@ Collate: 'ccRecord.R' 'ccTable.R' 'create2dclean.R' + 'data.quality.report.R' 'deltaTime.R' 'filter.categorical.R' 'filter.missingness.R' diff --git a/NAMESPACE b/NAMESPACE index 58e6025..8a686b2 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -13,6 +13,7 @@ export(ccRecord) export(code2stname) export(create.cctable) export(create2dclean) +export(data.quality.report) export(deltaTime) export(extractInfo) export(extract_file_origin) @@ -49,6 +50,7 @@ exportMethods("[[") import(Rcpp) import(XML) import(data.table) +import(knitr) import(methods) import(parallel) import(yaml) diff --git a/R/ccRecord.R b/R/ccRecord.R index b8f243c..c26186a 100644 --- a/R/ccRecord.R +++ b/R/ccRecord.R @@ -128,6 +128,26 @@ setMethod('+', c("ccRecord", "NULL"), function(e1, e2) return(e1)) +patient.index <- function(tb) { + if (all(is.na(tb$nhs_number))) { + warning("No patient identity can be found.") + } + else { + tb$t_discharge <- suppressWarnings(as.POSIXct(as.numeric(unclass(tb$t_discharge)), + origin="1970-01-01")) + tb$t_admission <- suppressWarnings(as.POSIXct(as.numeric(unclass(tb$t_admission)), + origin="1970-01-01")) + + tb[, id:= nhs_number] + tb$id[tb$id == "NULL"] <- tb$pas_number[tb$id == "NULL"] + + tb[, pid:=.GRP, by="id"] + tb[, index:=seq(nrow(tb))] + } + return(tb) +} + + index.record <- function(rec) { retrieve_all <- function(x) { .simple.data.frame(list(site_id = x@site_id, @@ -141,7 +161,8 @@ index.record <- function(rec) { } rec@nepisodes <- length(rec@episodes) - rec@infotb <- rbindlist(for_each_episode(rec, retrieve_all)) + infotb <- rbindlist(for_each_episode(rec, retrieve_all)) + rec@infotb <- patient.index(infotb) rec } diff --git a/R/deltaTime.R b/R/deltaTime.R index c6b2efe..a2641f2 100644 --- a/R/deltaTime.R +++ b/R/deltaTime.R @@ -73,7 +73,6 @@ deltaTime <- function(record, pseudotime=FALSE, units="hours", tdiff=FALSE) { newep@parse_file <- ep@parse_file newep@parse_time <- ep@parse_time newep - } } From bedff141036ed4aceea6dee667e5464a310843b9 Mon Sep 17 00:00:00 2001 From: Sinan Shi Date: Sun, 13 Nov 2016 17:19:02 +0000 Subject: [PATCH 03/14] adding initial report template --- R/data.quality.report.R | 37 +++++ inst/report/Makefile | 4 + inst/report/ccd_color.png | Bin 0 -> 18195 bytes inst/report/ccd_gray.png | Bin 0 -> 17730 bytes inst/report/data_quality_report.Rmd | 9 + inst/report/dqr.Rmd | 82 ++++++++++ inst/report/listings-setup.tex | 58 +++++++ inst/report/report.latex | 246 ++++++++++++++++++++++++++++ man/data.quality.report.Rd | 12 ++ 9 files changed, 448 insertions(+) create mode 100644 R/data.quality.report.R create mode 100644 inst/report/Makefile create mode 100644 inst/report/ccd_color.png create mode 100644 inst/report/ccd_gray.png create mode 100644 inst/report/data_quality_report.Rmd create mode 100644 inst/report/dqr.Rmd create mode 100644 inst/report/listings-setup.tex create mode 100644 inst/report/report.latex create mode 100644 man/data.quality.report.Rd diff --git a/R/data.quality.report.R b/R/data.quality.report.R new file mode 100644 index 0000000..d4676d4 --- /dev/null +++ b/R/data.quality.report.R @@ -0,0 +1,37 @@ +#' Create the data quality report +#' +#' @export data.quality.report +#' @import knitr +data.quality.report <- function(ccd, pdf=T) { + + if (!dir.exists(".temp")) { + unlink(".temp", recursive=T) + dir.create(".temp") + } + wd <- getwd() + rptpath <- paste(path.package('ccdata'), "report", sep="/") + file.copy(rptpath, ".temp", recursive=T) + + setwd('.temp/report') + dqpath <- "data_quality_report.Rmd" + headerpath <- "listings-setup.tex" + tpltpath <- "report.latex" + + knit(dqpath, "data_quality_report.md") + if (pdf) { + pandoc.cmd <- + paste("pandoc -s -N --toc --listings -H ", headerpath, + " --template=", tpltpath, + " -V --number-section -V papersize:a4paper -V geometry:margin=1.3in ", + "data_quality_report.md -o data_quality_report.pdf", sep="") + tryCatch(system(pandoc.cmd), + error = function(e) { + cat(e) + setwd(wd) + }, + finally = { + setwd(wd) + }) + setwd(wd) + } +} diff --git a/inst/report/Makefile b/inst/report/Makefile new file mode 100644 index 0000000..c980490 --- /dev/null +++ b/inst/report/Makefile @@ -0,0 +1,4 @@ +SOURCE:=data_quality_report.md +TARGET:=data_quality_report.pdf +all: + pandoc -s -N --toc --listings -H listings-setup.tex --template=report.latex -V --number-section -V papersize:a4paper -V geometry:margin=1.3in ${SOURCE} -o ${TARGET} diff --git a/inst/report/ccd_color.png b/inst/report/ccd_color.png new file mode 100644 index 0000000000000000000000000000000000000000..2914e3419bdec30aadd12641cd8758e5760d5454 GIT binary patch literal 18195 zcmd4&^4U)2ScPcI2CEZ9a4T92*bax|-pmZ;d2uL@w#J%`= zUElY=aPJTBnCCfXdQQ$ns;S66$0WxD007VB<)kzK0F+Pw07(sqhWN4*P{V@wN9HE| z&P~(F(#_N4g9Sj`+{x5}M&7~1%0k1!#N6BEyTuy-K&DY%N?glp=^#t_18i_QV#vvY z`au)Q;*%Pg^}r#}}MN*o%xhz5^EDCA=rL8zd(QNxTgDfvsJ zAMYVSJEf*fiA;XjK4|wDM|)gPy!`*oFSoek_Mw;02=vK;(TW%o_{O` zgWih~N;qrXr4r`E%>Da>3jS8Z7`9H4j{F3ILIHi7hvA&4Pk4Gx~fQ}Ywq1fj|9 zNFCZ||H06$^fkKwkBzR}S;>8w2W~y=r*;Io`@G0uUrE=0LI;C#MR`kKq)!?=H6n!G z#T|OyB|OE(`~*MsX3~VVR}AE+zx(GIhz}y`4$<8v|0i@%#lRW}{69g(Mt14X9r_Jr z_Wy^T#z7CO{fiy$KTsS9NIaR_bdsm|$16haUUTBWQMAh^S_tBDcq@v|lyXY{jE4{( z`Gfu6YcngeXNqjLZdFh@&8X(eCUs!5E%|EdakjCchwP<95YvPf&oZbI0(6Gf( zQAGg3{~Lhcr)}<3I4Sc40ua;>tSu&fY=H6pv$$O7kJHnI+!s&H2uUN?+dxV(N&n$` zZh$4AA@e^$K*H5sk2cF;K`e0@lWk7}5d1?kSZlZbW1ezyR_2WG%fJ2zTE8eg-3;dN z{zInYhVoZkHiCNpR_bZ+6E~seRMa_)|M5z@U9+`C2mFs5(-0N)V*>p@BOv;kdo3|= z7JU7$mD))JLv`x^jK{d7ymy+;ejMF6S@D_7z7+f z&U7s-E&GQJ;pia3d?i}8VACs9tcYz4YNK%I3V#KrJ0_-AiNKP1% zC(5w>PXGXwS$jZ@?XkGN`v03ENCnm=P(fItcW3&oV~!Qn8!)t93thhl1Gv-Qih#$z zL(;==9|YyJkUp(Q(N>NOGsT$?UlRP2J-GDhBYz#z@ws*Xuo-vK%>HY;!iSJ>{*@{< z%?OwL;0=Xpv9EE=GafxEgq{LI*QB!Geb12=2L8@H3la#{NU+#Y2X-{x!5zlRq@Itn z#R>O7x)z2M9L)0a)eq>Xtw}yNby4O{+wd`9xmDb7d+dJU0IZXwq5gQ2wV(JK4HX>Z zYt>FU%LdGCLZZcR(6Bb@up$kIlo$z4&Y{S7^IaE7m_^i1f(=DjL;REq|DjnP z-_%!sF~8uJ%piePQ0zVddXCmhd=oT4P@%Upffzc@gA~<%GkxdtiGkLn`-k7`w9qgV zCW$SM(Y{PVl^ws)(?@O(m@cItquTTgWblu5u`TtK5jC7#e1>obU8YXPFOBzPB?sVh zTyjg5R22>JlP>R@ppgKwORo#NUkqWaDWp|-=`K%Cbx7^3>O&<-f*ID%o%o*Fahn-u zT0*Z}jFzVr4ki0HGS%NtnBTU}%uKgp_6yn(AS@^j^e6tfxu7~bNqv1nyq!HZ`H{gEbohW~p80%2nbzus^ zDT6_`w5W;=2Q!^MOQ9wXyBxkixC3%p1)rm zroN6iu{cn3xiO;0g;F8|#8_*>L4Sn)TJRQDPiFHakF7X--m2b)i|S{a?U0Mg+7TMV zgb?Z(Vpge*C(&WXwt8MLVq%P00lo;kuv1t@>3>aM8xBIlpqTD6lI^}RD6MJjS$xDb zBNEGbZQB;<5Nh98Ef!XkgjUYiW+73ffc}B zHV4eQI6bG;n-ga(-an5QF?%Hs3S5hTk_$X8G`%NAJXnaXpwJ+YQY4!;J;pTfYQG$xzwK#SBPpc$Iaw8DoBrZ9)ZZ-% zdVp?d44uZ+HYnrFoI*@Hh-ve!gtLa<$c38qxUDPQhpg|-L~8L=fyPyTFPoT)?5@Op zN<{k?*K}%$#cuNo6Cl%Z`_4^COVHpNm4lRAwg{^y%lQQ|JdFV7?~)Ahe}Ki+KxN~L~* zHY+#YEu0+_3-_;2;&8nyf|^phe2~OsI@r*dCpJYa%?N!y3f$Ix?*NKp4!KDhowonD z%7tNe&aAsckQ&(6;>m-%Hq>RtXF9ZK2R0%ch8O5Q%keyk2ntoJLQg8eCBkYih`tPI z9av-k6D6L->ZOr~WJ8l^RVtxSOT937-eL@un2LFF5CLbdn*#yzGAR$`&tCOJ>kiY> z{B+Un{pY*4<#Wv zLJjee@sX%f8*hKuLcQnx^tp%&?+)<7o{U7bbG}R-I@-6YpeBgGNXC z%${n*Vxy1^FNDJ(FJCy>Kbh~7UX)=}{z>ORSH{?6qlcOQ)!N=TL^}EZVLHeoRT@yo z+mXb~{(%+YPWFdZ3-#Ah_~wm#`c8ZJSm0+A_}tml@3=#=Q2%#}L!X;AY9TPKCU1~> z3-ghgV=k8vQ~mP6R@;LLBtpo9Q-<)L^GQVY?9`oO2*B|d(};4~t1|tVN{s|wSJKM) zC^w&}yLed|@!77;R*h~R6KBl7KPZrok2~A~VZ5kpH7sxlK{260v=h z1eqwV{g5gEAV<-ZB^T367Q47eqVB3CP+08`6=(ZJn^S7GW1RU1r8NaJPlxDxy)wy9 zLqYQ}|K(J#X$onrtS?uIQKS_$xOjE4`Ui9`r<#gmKCKRHXf*qJSMqTw?w(11gVcD7 zJk2Cicp*Dg1M!lw#-ZzzUk*vzHtn~H?S@2+UGGTj@;#G&oN2|!9Z1@5z3~7qq&&2k zP=muZ6kyH#4jDB9$=|8)wyO#7!~ILNo+Az!$ z(UX`+bI6!BoFT&wJYR;tlyJQOse;p^UIY6qg7_d3*fI>*Da_c9Rz@1JW;-pUqmEu5 zo(?$Bx7c5#%}pgJ)m$zl1%*>69s}ntF`Bg;f7ny`!0O<()ZBg4noB7Sv*MGMZzcDN znXzASyB+Q&V>y^b1^2UHe+?W>A0wm<-w9*PJezr%9zYD62k~^RU%q-r%4LS@p%m>K z^3esS$?W@?bp}i%3dC6$mM(-!X{bs#QsccNjRHbAAB)I5U!lc^FAZW~_Hmnf&D0t$ zd?+B&dNMw+Hg~_*lnGx$#{cZwJb3??jDBdM6ZdF$U_(Q^8Nqm)cy0Xr!N+S>OpT-kY>QYE8xk%^_l`YE)Q^Ab&I>L9K9>qCmS~+!sm;(X*csd`CoX2J z5SH!aXhLmKW{qtiWlqh7(TAA(i9XD-&uifyhH()(c~n!(C|W=B)>&*`sTVY-n*f=-NAMTnwqB?J~~`$-4_=?Cv}E3O6K%WtOs4j{%d7NqWWv z?3>>FE1xlIc-_j2C%v1;qn=8#^(C6IPH`mpf*^Y$#dD%os5-59hj+@=f+Ehb>NuYA zBQWwJi#w$JK-3JkILrRlcEG)Y?-uu12i0U|Ikkpopk8jCX;!&hh=Y1+y$yl%QIuIcfqkt|-5Kj@nI@ScYBOPE ziXG08tamYJvhkWHimx-qEynBfyEU?Mpr6%d`tI!~6K#Vn4gcDqyyD^R{Ntf8N6v@P zdSk&FKgSb>>UO2)6UvzmWxnhUOYb$|)=N0h9xwQ4VGF{rPmos4EL#kgBMk{SF; z0GjxPx*?l-TxE_5b@7u4X+Wl}~wjlR0Re~@bQ(aDY>t@CF7ehF6uh}{GU-#Dl zu)wUR?1(QHL{^md?6m7<8UHmZuD|SHWZh$7n}f38T-JV@BVKrY&l|}f0xvLk)TCre zbZe}$)P9OQmT%<9e{Ono7dTmz*&~;gsfk~`g72koQFnY|#Oo~?>@p)zeZ3I^AvT}5 zR@@to^R-prE;1;-y@P_fKxUz8_j!s0s_E@^h2z+!reXfTE!r9TlQ$o%x|MBz%USuh z)3|chG`j>#R@x=ZL}ImB@s|KP`0QDbjN=JDb^ZE4J=zqb} z$fFcdY3si`Ot9d*z#a z(RUi8{Kp_{L$DKz{37QA?e-M59jyfw8UM?vhr)qkQ0RJG&}0uGA5k-r#4#lp}hln$;v$#dv zb_tmF-y8!cimio%IdR62Gtb+cug+5`q_LP6a3EFFnf6(E+R+~d!TBN0Vg5h%(gBl^ zz5Cx%PT9ZmX6JVg9=4)heXOqME5(3kRLTuk{Qlb_Y8{nGN90ple_W9i>(H8 ztk2~b5ywBoxo3=GX{i4u9*5oh+|7qUEII$AY)@b_)qD>BPvNFj(rSP;xMjwABee){ zD9SwtB3h1b7?=E$#0>0xfM&NLHfFocxD$lLZ#i62c$S*>Wa1NH5%N6{09xF|WWwI^ zi@4%ZwlxjyHx_hj1Lg|E|NquZJ|<&k1(u!nKG@A&v0=6MVlY8)pT zLFDZvnA?o6Xq?_tZ$G^2Iy9>tXhjYJPTbc>5r#A0xKZx6k-1xnuK#F~$=*jFyz7Y) zPm5tFTh0F9VDjNGf(AR<$;wzm+KGTPVUVgJHkvWd0o|BynRKDqpS4UQa+a&5P)Sfs zD_@P?QKFIon@d;wdIg;LoYvrKIQ8+POQ4#mbJ=}_m7^#GQrIN&ESQtEi)5#`j=dsU zC0Vef@M`YtIHL+Kh~+>nH0r)52SN$bS7#*f`zy9;49{HLN%P(cR1U}y)EOfF$cfD* z(BLoF{@bX$o)%~#jJPYvh{jA;Zc#SDLh?U#dlfpyT0J^9>1F?(nqd5j3sxaie%%2{ z-LOXLmo1r@lxKwz?Ye^&cXtKL8O`sGt4TY!B9FPqxu&(Gz`>l9P9oWgnPK}{LaGrQ z?iubJX(8u3&%5@0uR2E{?EF%D;1yyTcHZar>=Sz-vKV+FP>Gs9qO>|=Hj!h}CKr42 zz+UGYgDvN4__$~lzD)}I^h<}i&IQaH11xb~yusD}b;~@kGLcBNGbVrrqVA=A_wMRW zq)8bY0!HiPlpws)z*e!ra5A%)c|rxSZY$v^0O5VekZ8BYfeUE#r0Hfi%ePq*fArV- zDiGt02FQQaPk!oB!ezq74TMUFVHbUSX^FT^!44UBn@r9RflS2@Dqp{w8gXxucpX0j zvCO!tl}+6O0;GmT1Mh_RO)!6WsZzXBCR7LN-0xs=k!lgjv=)KHNzsgL_?V>8dA6#f zET$Rr4&5s;t=QrxAlVGqeAyu#2TmS-kIz>~X!Im1h_2K5qDW(82lTG)5SqPGUc+jHUd>=BOd0dcg6A~NNK#F<6AeS7P_ zBRDV*(v44qznj~l1>SFsrUm3oh`oO9Y%A!LrRxAoJN|k^K%C*PC5^{U*DeFF9;#41 zew|g3e)g{5Rhb;RADd82_gBV=Oh%3B?hU~k$!3C+fj5bki_MmmitKg*Dos3V-YD>s zwl256jS=z=PDWM~5WnZ(vE}r*{?y(1Q1#e6$DadlTfCC5arc2$ohZcZSNVqJmLhXp z9;Q?2e(g+0CX->$gR~zLUDgF^N54SoCm!fT-@*@U*)kMwe|RnhYJ6v8q-&7{_HL}( zITxoYi4>AbG!-M49P&iF+^^@;X0?2GrE$QbF@4D*p6NR7?{3=0WSt~|N9MgY=H8KW zj33aRord{cS@!KJmeXu0wd~Q%NWD-lx(pqfW}1?&?c?8t8d|u|qi#jy_p^slr5ee5 zvU3620i5b6c#8xG2gNw?b9^MW&NR@-*~(IpuzD{b4Aze@f%<2aLkoK7H5v+Hoi)~(un5$5}mtSarTmh4}>jd zm~=+uliREEM})X|l2j*Oko?)nlzvlWKs=w;Of=9`6FzbNe(&_vXJjipgTB+aPkT*! z`O)D#1L6mgVaJRb`e;GCt0*c%s6?VWiA|LPY1PrE_l1gF?_S|VkC$e`Zj2f9Qd}|P z2f*w~nRwe4r>zqYu76kt-uZDcwP^dj3}!1$^DZ1egv|Izpyn|I+-x@|7LT>cfep2c zN!clZBw0Rf+t+D3cIV)_FGPF!4p+KTAY`c+Aw9_2vnpw^m{(_3c5w&X>-C0J7=5G+ zL5r(29f3qJ^QahUeE-i6t}yz_C6mX*$j@{{;iJP#Huir=ZX`kUQ5@((s)Zs3Qs~>; zek%iw)-w}VX|pOTm+zcQMj%UtgDEBJWkhx6`kRkU&Zl+b^B=~KDJh+J6ufr-3dW!; z%G#Nbj9QifYKYcwRDQ3M)=Kd!SY0uPp;y`!zKp$?xltxk+0ez2#*R~Zlf<-X*AeGU zYfgaE+AtdYOlIsgXe9A1Hwm@uz%;i^xHNLb8jSyu&7~Y;}^Y2$vFVbtr8NtC5)M*i}Z|Em* z*rUE{u>m|1`GjVHMThlzjf`Ip=;=(<-$Gi~U_4ov|MVOP?c4k&Wc z$I%^&7dmEi<0*_foP{#9lU1uq68l;s<1KXe>-N2hU-$0ox>ly#xBk9l(v0|ai$qcp z;}{u<(m7+GkgTZQar)(3?nrzU(gI;K@|(M2fB&XLsKjX&UZ_YONw9M?ozZ1G|LgAg zaG0S=Im*YaP2JZY5=4%~-wpJhW!D3O*Cl6P@8@>@1REXf@&q2;G&}g)l1&Gg1AK42 z4l8_4hEXT;82k!tOb}eV|H-U26Lw}9f zuci9Eok_lc1=M1`fAl8E1JxMDg}+pL*{c@wYMy@CN7;L>*-gGUGzw=-bFpCBSpL+T+awrg$nYx132ni<%?KqWqq;z9wV7}iJpa6#LILy}qv^1B zN@k!o)teForZk)Gk*cS_>hrALT(Rt1&cz6i4Ud)9?Dp$jXD4quHw)QnJRSLAL(b{p>6l&qR|f)P@W`2LOwbGBBM zSAW=?>B2gB06WaYR#VZob@8I)DCtT@sf#=#=Mml$HIxFrwY+A1C?YivF6{^f+0aNL$mgprFhPBLvTuF z1;cL5fG6$D!tYDt;%0^l%A0Fm)V#x6Y&LO`#Vu#Ys#Chp72O@pclyS&Gdjd^;qfF} zUgO`I>h>f*k*)Vkj_l%q3cPp-2j#zt*5j@Y7E0!B6Mg6+Q>7_=sHYquCQwHGfVfh& zX=_yF6yJRxq^I5COd*&~WQWWD_y{Act42IH%F=)3wBpLC@d-+FW>Icw4Htp$6?Ha&UY>8`o%c^5%Zw~4JBF)Zpj>`;tKp$;Bp7C z8Z_rs(XJ(U6@UA%Vesd+rOHY)$vHF-u^IS&Ec)28YkiixPvR#NFVi8;;#aK4L3=QM z%oUP#{9TtTV9l%Pvq}ot1?Aekl}yqxm2sSA-~+Jtg}T6Fs!GvyFPgA%>wESciNM0YXocldq+*>+q@BcOD^<)`@zNaEALZ9Mi22K%Y^rmsLdVi#r7lrox z)xX2gLZk~iAF%TVyGQ)lE{kL!_4)*#+1_8j3c8qfRh~TjW3QxE2u*NJAQekN zspp5olXu>QLv^*d`bgUc7TW3?P0v}O5#TMjznT?gw5>AT9oAl>Jm;A;?nMq#EI&{p z@P^zP*XBc%RLA4&J(6#4KS&W{Lsu|O=f>u`bnGlK3;Ud4hfIvBW`$N^1X@Gql`goyzq>rFb zysfQmUQ?qSd{Ztg-h?b?kFRfAKltv`$S}1(l(x>d|M`^Um0!CgYkLb03o7^KfwfzJgzI^wio@ z_X&V;B9=Us6ycE=oyqxdcHa2#TtnY}O(bXuv-jB~CMhQ^nm>u-U%7geizp`>WK^)* z=<-(UnDtR-gFMAg;g0M#`0$!o&=OP#VW5T`?r(y7u7LYsA;JfLYSfK{lMWU8GsF(g zqT$w~0pEhaivIY66H6nmaT3~=gSt5hkx*le^mI2F*%dXaHEidlkieDSQW4(YuR~Yw zqoaRQPN4$&P{c{Y5woYeysNPP3rK(X_(i#)dhhbtLRxXRi~kCs6rYx*&?Zpdr-Lt_ za)Lnzk&aW;nvr;mN*K(E4VjifY;D{B?!+5gJV(-QuU^*lOgKHw_BWGPC(mz=y;rR@92d$Ph z`YP7=4DZ_vcSc7f$!*9t!4$SktsDYAXoh7HCY=;-#Ujc*x;QWq2zm>8wLI<+d;IG~ z^-yumV$+w2tAHV84aST1CKTH^rak~wvnzq6O!v?JS%&!eYqWhavFn(xs%t^N9s50j z5+|3mjT_nYYjH(nV^@BMwL@1f^{pIvO_7JA#gQQ{2kU}}3oUC?wOfZ0)`a%q4D^rF zF){RFpepf?c}SPks3tVL4l~8m9O}6&dI1dZ{3h4x%!{Parc z#;|*c|CQ!<4N^1OMsR)@{Rzf{1($_^|Q~{$VsuobL8QT-; zT2p7r-DRH9L&Fd8^FB(+C>t>}{p_GIVDCcf>jzD1!~_4ZDg01N8e<2{{_8p?F!OIi zJlm|be+6BG|K6`uHtaBobtM#Gnx+BsF9LP~4HJ}xZJX0p<`NcXpR_z3N?aKHt$(K`VvAFu6xv-eNMX04kuI^0JvJ`arAPS^je!_Nkjg4KY+c!2{uMcBoz@0kqw=>f)CUv zu%VHgXnYSm@N!DF{eDSU2>=TufelHm$&hY`;(Q6S@Ut?c@hLlG=FuWij$JT$6R|J0^ZEJrymqav2MUl^V~tB(N1= z5F*i>C87K5f>77LdXYw0v%Q(7IFgM47$6mL` zXR`c|(oNqqRP|ol#N`Z6zFh)Gr>d7U62=Y?2DDS!1qp9c1 zU%dtPLQg24Ne~{1Ge`gF3T4l{cdwlt*?S9bIdR^Ppn_I8T-)tuvS}EKmRz0IO!Ao> zMhH}@=>%rVI5T-x!P9gcacVtxMN|&!9kM9$LzoCmB`kit?Csu?TXO`8ljbmXa6epI zOAxksUNI1jJy;5>>Msoa2qDmR|Jk%d>7?7uGkh7M-=Ev)FIG)?l_8gj<4x_}n7QE} z1SjjzEH~qd^Y7h7Rfb}GcCEyQ{Cb!k{Z5E#l9`G2hCjbXpQ~kc?3%5-!-MJ-r2`}| z>t}OTNvb_|8J(H&%dOhtE0Y;W)vkJon}8H>@Kc=I(gvg=uPIuP+Uw75r^#9m1jJl$ z(5F^#;GeA|4w4y0Y(!HtYT#w^vVpV`lOv1cKf3ME_GzB^AL%d1&Od|t*^6%Uf=3DJ zx=i^6lE3@o+LOjJk?Y^Ou#HRJ*Qyc<&>WhVU?wNaRXn zV-&n7%dv-sJW|%gdm2&R3eH7$q(&%3O3IP6G@Z1 zw(0b@{d3_g^Io{$2kVf8&)mI}M#BEUorrfYG_wpyH69~P_7Mxv#DoK56^-nd8>c($xtDkWOb2_Sf*=@>264Xiv z-r33;^AUQ!F6TIew>k=wT!G`X-ZIf8VGjNDLGo=SHOwN=_Z=aqi+7bB4-HsQm6fC& z;)=X)#cTu%GX|7Q6sO*`({_2Z&f)Baq9FB=vT~(z71GjeiLshBR(7!Wi z$USZyL=$ZI=ybFGNt(UulEO%#S}~sc2xNgV*LQZY&+`e|c5mSvnknEat;ushsFnPl zLB0$In(!F=Ryb}IRcAON@@48A$;4A%cp{D8+Z+26h4~nVKr85gbVHK1?={)oMW){y zvy)#Yk{l?@#u+#icbmaW@Ew|X5+f)?VchWxkV1uh^y!rtKixcH_0*~)aMH7!pNdz~ z_L(Qtd-t0*6HB$z~nplbX%-zq7lpRj$Wc!BaIZn4a%++{jV;bGyhqd#1}z zYQL%8oZAweOLcUq3r3?8cj#kqBCsz=!=QL|5X(4&9VZ?sj%wmVnIHlDa8!A zRwpeh;6Uj^CvbESUvWS;sAiya(rKI_sXr97=XW=J7Gr8(AD=Mxwg9tneWf+Qg{$9O zgMgSm?kh&#JbnOKLE)`+6r4~-uXgSk8~j+HtI8cc}RO)TbNIks8iuCXtR-2KSM585bFIh#WiQDFe+}b2^N94L@H;D zv7m2`t6x`%qPyhj6HU;2)^O{MF z6gMp?{O0=2cT$>HPAQtc7QMw?_f|h*{q>`uEOTxB&B{syvG_((ZfxA*r-Z(V*^MQ) zZo|hMs3z(8&X${U&lh$wqa-hM=LH7Z9E)PmMxrk`&g;-vf2Ra>9IPGI#*I-bY}^r1kqft-{S@m>uVWojUcb{fN%L3C)kbDqAbd7I zOBC9(W;#^Kb}Ou!qR%_aNaY?e+#W|a!>-BU3sC|nvV8uER<6`<43E_h;PN^R@d7vm zjq$7|vYT3(KTI907`EP`%Viiw#Fg2KcJkWj^s~0kL7nZlG`R20GbSRnekC()H0No~ zyzX4`#1oj`Tq_Ni1kqwj3RiDpj}RkA_eL6e%*cF2@hssOm+w8C9bWV_r$$eYYJ;SP zGwX4(p!H}DT_G}?qx(XsSnar=G!^#IiA#eN_i1GSgB@CP>B;`AC3h3A9pT<30`S5+ z(4WqTbf}U#VL1N8B&H;lW}Gtl-W^cFdV3;(^Incbw^Wm*_eAync&A6=dI>g*M&Q1z zuyd$?uloRT*As^0AaXxkR$;LpU(ZPOzvZy>zZx}ksJEn+p<+6q!;#%oq>hIs?p@2Q zjxlJX{h6tPo%o*DISkbmc#!T3Km530X{;=z!EW^szLigox{7)|@{n^{a^uIk{EJ z-~1cjrV=(9?9U&3}^(ABVywN>*2~pZPlw9qEo7m zM*H>q_wI)4lx62agy>B+p`87`#dREMz_~;|>v}DIT@Luj*3$7=!NNxP2=n1R&UW@q= zFaASIu$se$t5k5S63G}{<(z&~TF3b@7eDF-yByge8O{_67{~IARk#jUH^+PNMAc%B zt=fys@&)Wy?WSi0N+Yf}F+*fgWU%ok7O48h4J%f$P8kc2I?}OzM|WGk5()97cHAg8 zeTu$$vOAu^Wk|>N+E3mUqHYi<6ooL1n`UK#9NL2kZ(%+#vq}F+YDpA4vF{Vd7Cpvu zfRc;vBEz9U60$$$yfKqaPD>RMC@S+3*xVW4#(Z`?lK+@lRauF0gUMHPT+Nt#k*i5y z{7iJ=XDO~#w?IUPRy_HFtoF+>tEeAEq$?GaLWEU#A!?e~FD|9As{|W)h)_Az+*VdI zzgQ1M?p*UBvYPSL7iRV%zTsp-c#N+S%l&7(#g+a*8*oY$NPePOQh%cLk$(G8L@p2l z^;S;$N+Tdmh?6axo~ym4yFq{)?A(G_rh@0QvplUgz8%8sY9-+bB>i1v^NBha%YLn_ zB8IlwunwvO|6y~a`pp{L+Qfp;kxdv>;ueu(p&X|g!ib6r=JmXNJ0Ob|WT!_bNGZXL@cUqX8n} zQe42^#A|>C^xOh-U7GbXt^3Me4-SJJ4DHhJ{4?nt;+S8Dv@mq;qrn{6`{K**SIl0* zg&9WCZZwz?EVh;nsQC!nOpNW3?C5F8$v0y}ya@>*)db9I$dzY~GUNU3BP++xazcMk zEg)QjOD2i4^rhf9k+HBEI|&Q*`MY;`lB-C7*_YNyZ7d=&UQ+pkMyDFekg zs)mgLCp8>bCbWi%n3JdWEacBWuEbTwsH2B(gCs+g=c%9)u??C%MB+eTAN6R;-fIpm z7THI4YJR*mjng{C9)0(Nt^N!boh5W4sl2#KLY1Z2iFr&uH~YoF=FZL)`r99+Li<&0 zPR|D{mu>=znc@Y35+!c8^HZpJ;g{$kFtE^Vde_{*Jv+bV*3;84qKGK71!T^Gu@E6Z zRQI``X)o{anZ&8d;|khXg-pbQ%HK3P%&bNW$5gG-QHh~_-4XteG@ao$R=@S8vpvM}))|5ET>A1$mCICO?|79M_;o^^UnT@k>X|NrCT&#P$CaV#0jw zciOBALVj*~GMzmi$NvND+eE})^%FBTr{_N|sz=N;zc8cjNcmt{4h3U`I8y4n%;6aMKPGhyvD+kC>Dan9i}=y5vQ6hjZ( z=_b?@Zc{;*A6F@1<-N688w-$lO%nfR;Zlg+n`2r3RXU#_ZGCoa^XPE~3EwvpMF|ks z;xzP5WO1NF*v9z*)Q{KpX0Fiqz>Io;4rdljvv0&b0yDp?=zQUD)ko(PXfwwyR97|Vq* z%e;spJeu(huZ=9u+uKbk)VVES9Hg|&zQk}#}{uRr)be+uH)a{np}c%kbWq*V=D!?Lsy zX*eAb7}(#UHBdhtSWv!=_8y>_X@3Z+`* z!aL284>Bm|14{Bs_!^QbJd)9&B0?eqnTy{p@dXi-mUMM@TrJGz%b#^ca55#*F18iL zjFZdzI?xsPQJE0rp=L?=28LCd`yHzfQW2k13Nq(5?dBxJ=yzPAg-711do#c?YL)Vj^_ z9ZCkU*W#9#q{Q0_n@VC~_Fjy&`WsOj3p9~1V`}PB=akb457AR#^_}Tzim!AjTX0Lz z>kKkCXhO+9%^9Cyo`)@{PqvKzHMYs401D>%Jx+__;JB_72EYCJ^G|L3?Rbq}B5vY` z{9NsE@aS4KD#NcYnoQp37t{C)#`o zepf_GA!+*oa~zf$$RO4Y%b zn3^#CuW}br&nTBuWQWAmgY&<}>;(S1hfMmX>cFQuKv8SGcj1>I2ndnZ4%o#|)|7Eg z|3?KuR7C8Wz+jdre&G6T1Nl=I1m#=F6-E;kO+=3Qzfwfw8AFnr#3Dpl0|3~^&x-_b zlQQySzxMxbx`rq;*=0hc^1(`OxE9YFXP=(SPP~*qi0GdFbsTN{-gw7!ESj-j=6XDE zdLBMRNg_Jv+ttJx*KU7GnQ2g92K#=|hFg9x*g@Dm>QG%P@V04(C3=&RWoXFF@%o9` zD4`G{Q$!(g8OZ7(Z&3Kxa7arkaZWvXFta{f7*FRodfY)%Ty1AHddrw(sMFS2sWrks zsbPL#r)rPM=5LUF7X#N)WJV$vj^K-~ zn>%fTYyVircS$?RMAY6Y)V5JQ?g~ART9jKMG8%?!aODGBAVSB6pY$Ju5q5I|3ot=c znRjKrL{OA^`A#KkrYw8Xy!WF)J`jJlFnp#Px!_|BUMLsPF%fY0?;hY9M@$KvS{@E+ z-BX852=(XVg)nm(L^nr9(WDF!aapjHA=4rsxMs)|FV{zT%uCo6O2Ai7U7UncK~ILq zKfw1B{E2V_#9dnz>Rbtmda9Iy>2q~q2U;{?{KI`EVNe)uZImY}7~nRTjhP?cfY7uQ zE!q%ObdR#SfCsBlQKV=v94)aI9yhS=)1ECHa7B$M!{n4|itH6sMj%c+=?Nhpf7u9@ec3PD$B3tTPZixbg;R7NSPB9%(|0_{ITM#+Tam=xp zzab~eFt9UsP+ifDw27Pq7MdWVkShNfuvuhcw@(LXP*zkwGzkM&X zno%2k4ZD)k+Bl!<&?2tvtCjlIbbzr?_@^9ru^)B+_@T2(DMvFa5`cG{c1V9kA;;^s z=M(a`2~idvRHbW=7l}~4_#~qtRbnkG1YN&>og^xd1pFa))1^9SpGG0oz2Vq|rLZ$f zl`OBkT@bE2;QGl*i@%IM|K4=o@`U*)?#I!lr*QT6Pj%@wgwmD>4Nfqnlj{jeB4Qhq z+WflPQv(XMP{w;nyESwAHv_a%bZLiN5y$vu^{icJQ$9bqK7GEy_JcANwAq@upB9Mp z4SgTkx#w0K0Dy)H_3pLV*yhOKpOYK^6l$y9<*S_M>nJ~+O)PTbBN`iZC@uFzoDY9i zd!AP0FEqSB_#@<|K^jqd2|&%0aI-g?J0o--P$iiaH(O~i(y-l^`bF>i(Cy&+HWG0p z8zr9q6}6r*hp6O65T#9cnnpkIzWqzFzJ810aZWE{I z>^R{H+o$LLZy1&=3LnDzRmEEx-pFQo8fEONtst{;IqE%@eoxuQd^H-C73kqs?S9Cx zTXgvp^qGMVH|}5ao%0?Ml|2c_Id3uxl+Aa?W^&$lazLE$?XHhmpShCsc2?3<=)Y%N z_&4Yz4A>jbi*U)8p}62#kNk`NnRqcOhPk6aM`&5q_co!LD)r3SJD&t(9t4S#unMXl zHVAKohU)n~)5|VUaVys@E2tV0-fJJOY7d{T;~Z_KT0579?ZnWa20^$U5wBN>U<81$ z+$k^QVTTl2xij+U4xP#Q8`%-H39~n2b=-IZxy4&fYHz+Cmx<>=ZF+#!CXl;n-2 zTfdC?lx1g*=kY$Z7QiBfUb$2%{~=V?)q(yJnrwA(i7Q9wx;a7d=-cmKr1Sr8V32^9 z@wxA{d$Z^S;dDg$kh_LG+f}j@QAk~-L>6D>{M`!QDa66qP~&4`+(M2WMZ1^I+vi7! zcd{p{6X5#vHG;_#-DxaO4D7$x#p%6PrF+>b6UqH0a|BT!t;tso+*NpMt)McDlns@S7-mf&6&2*W_i8@sKR1UaJ;pQqfRhc=&NR*qGru>(|>L*_nbfe zy|c$f?7D1~p!Iv7&4<*^1+#bmo@u^AK3pcxrrrEjSn}mPUaxc9Lj!lN-*r3PW66iP zT_^gb&wp4exBT6|{+-LJcGdVLl?z?0HF*1NA+T%#S=DsG=|@Mi{pJ7rLJh;i_oN)F zyT7aT^os{=H+Et6RB8V>=%B4vV+(X*ycIZ@g0d#3BH zJD0@P-(HgP>i!_YG)U3xRckly|N`c#d6R8W%2i1BhaMO z=b!WK+vNSac0!T63sfEy*ZOU5oEMzOv4)OQ1uWf$I0@8j2xan$*c2=jd zD97?$whm!6d}mLqeO3M&8N@ZmJ$ZkA?A+>nm6|0TzJ>fsdB=JCGr!8%teZaNd8O+7 zM|Mwlo|q>6w65dkFzB;PFc(h&BL#5e5LDX#%lOcQykm zI8pzexXbIi>o{4tdzraf0%YDfnOoAobTqTJ)V4Hx=i~CrQUU;g{Cx?L(e<9)%ed8B z>mQ5oJDj9We(Lj#@d`_Pt{rRCZnk zD#6|22%BRn|Gx6@x@{^hiA6&x|NqTJ$p&A#Z^$QmFsME0egqTn@}!6~T<7aQD?woZ zrd-mH#FM@s{+2Zl&I8Z`(R$@sFr~&wAE+RDOiGHZx-fH;L! zgM1%Yq(SKTSyypOBrKT!*P>li0rX!{?<4~6<+SCilVph=o&scme1NLB`+qj0tW-+> zsU^)Vg7NU^!D#xK;6TOyHMZHRB#ywOLjwQx8r4*~3hR(T7Wlvolnp`~W4?YduKewR z{73UUU4nB_8TB7oxQ3E7wtso^dLC{(D5jo;wZsciJWvlkkxSdjdGhLKHSfFa=n zJ1Ri7;|9|n^M3zlD*zUzK^~|w%l7aTrJR_x`tl7yA@&1_$sirIWe_qhZBG0^qS}H! zHm)ye)UrK(piu##=Qm1cNg0iKpdL&kq%e>BpIu6kn}>n0k8TMEKC1Tr=XQGTjW}?` z|BNH<(tGEWJF4)|{z2WIjpfMDiX!8G{rVA@x&~kSUpSdVc4hgVsQpV0lxKvTxtEom z{PWX8TU0Pv#);kMh1;(ueN zKZ^19nI!Z^_u|<tF*u=D| z5qcm|O;^_vpRK(7pH~@~sHQz09-*QQi15CjPizf%zYj$BCr1^5anad=zv03ie9(tV&32O1^`$nH?4^xGnYhe< zcTtuzPAmLLDEYQ#`(xWPXV^f-vG$26sznj;0Q0+nTwY84rdew`e8iIxyQ zZ>hMPe}XuUhqe?t{?HRDqxrU;A60Wc3G8F3{;8jB(IaIML3@P`2uP4`9~!UCw0Vz; zUV~Rvaj<{>FqC}j6^B-Wqi9fL6d)DzB$FCEci1v}jFcfw8U@;sPlGwc7wY0`XO*%L zXva9Kc4+3UmL+L;*sT;vs9yW7P<#dWIv-i@=m!dH(**GhXQW@$yRK{%(ccZ8Sf~&B z8SG!)w8bpAkUwi>GW+^TL}MEK?Pu%b=OKmYw+RV9$kL**M1P}w+)HuSL9Eyt()3~x z$vU&6OO@nFsa=-nZb!Xd_u?3O<9-kwF5=GMeS&dsrBlHwi0HBHwV|VU%57LAV#JRd z^HtU4^;3hlMbbulE4kRAZDnK8qd-oSzXx**OO`@=)RguO4`PkeuufO z5iGApiZpb3142YX5p+oL9bMvMB>iu|+;&+6|ay5drJst@4)s3jzSlgC)a8CVrLY zGRVau+;dzH4tA&mV?W+jwDc}Y2E-xQ0xCSz&%qlU>Xq>?-s)1auHRHgj8Ki0v%3(2 zrc%0TWhq&xRSB_aZcjW)J2%L!?@d(o0JkHB+ro83RmpOXICNoHCBjXXbcEA=Z7B}Z zeW5%cfG#YN)AKm_jKNqJH8fDY_$+%gFs)Zb9lB=HSGm5q@p#Fa6Bu6^zi2>@ztY~> zVKR-Hx>0$?kisTjtZJ1+hx~g9ZBD7JNx<9dGNfE2CPF7CK*d@HSQ#nv(#5}b)Jg5_ zc#&j`5cMDII+1)Zl+;aZ@Y4xkg&dr%n25U4(w>@a<2H;wTpya|}G zf7g*~%Rr3%eb4FXY#$S1<@1!T4AG3C5SnQ+-@AB*2QzYB@OwKhj@>&eHS19PI;{F&vCA$FYG@hnK zmOqBL<6^@DaPXWN9Z4-=Zpey3;dne-gmM3!jst2Z0SX(@$A3iz5j5;#_mJhDp511*{`c(!4^Ms0Y0IH;GhRr2WeQclX1BC=#5nxz z)1w+i{4%fU{!kwkqVNWTlzQcFA~zLyPy9qW|5+Ss#HmKG&r z%;o(m2hEmGCn8JIq9Qtyhx(%xK58-OOo;Ay-8ZVqQsuPMomL7s{L0frV=(^=%lZRH zZjty6*I7IG{qt+ox)4N9T}1g#O8>s41hd%DY3`tLAIgBG$bj4Csw7Hnnxm(b`moT- zh%oYtDB}C(@q9`)2-p}b`x(G}IVO#7PS>@JrUk_I-aj?mdsvucM4b8A;uyX_ZWE?% zhCT0>2N3zn4Biox5K?r9NZDadOh8b^jWP+o0zQFDn-WV?)XDi~@WtKx#bHO1s#Yfl zMHbCDsIi9ROrK_tDHZba_l;^|#^WE{5Yn&4eNljvEI$nm>UXF#L}e5sNoX}1tfN-! zB5)_LZ7yr7(oujcl1`7g$&kThzafb;IF!=giSFcjF%LTA&&5oSyHx2wzhQj(=C}UG zlWIj$)D#lp{MY=5-wch7sB%8s%|y|dR71Y~nM$xe#jk1)wj~-@DRX}P!Yu+zx-YTc zlFXBH*>22T4y@=bc62Fl{?6Q&Nkx!qDf~xLkU1ZjqI^0byLXi9o4zIIbS`+X0p6v-Csfvy-n&mISSe2Ni0xj9%I%`&}*a7$(|V&Tpczzwiw) zwoF?3lqcgSEMl%2n@2yI%hl|K=jmRfLUV@Er_QV(>eIKk7hRY@wn+%?UhWMj54W(^ zNZ(<);(0Dx%JT^|EO#8TjAmHtSr^X~i1e(#K)>yTDT`TMiOrbNF(lMUT6{ih)6eev z>93il&+3k3G^G=5L2ZR(fZMPRys6c`oIGCHqi(lg*lB528O=}su45A?*rKDrpo*ku z6=7v;^mO=gP?$7rB%l8%f<|?Y^*ssWfD|(`euQSx(}xkC2MQIiT~hFTvkH4#oR{VI zKECMc2~L{bQq}SL*u$#xRA;{tjwQ$pPpR8+EH(uM+sM{R`bb}5>M=@p4pJ-bsv4RZmw8= zRsFD~M=c83oOP9?I7PW&pJn7nsB0okXa5V-MoP+Hwr{?>+DUV74a0i*r(Vv4&>A>5 zyj(uM5I^;s@n0%WqP0`M-@@7bD6>L9t3;tXBz>(F#Wp>*%<5a4G;LW(_jm3r3kYA% z=-t;vx%|#g5}@78fU@6jbo=$1=QUrt^LdVXkv4MjA1Go0f@oK$I~yX+O!UnbwE=m~ zMndLd3&(Ihj_tAW{b_~wc!QtYDEIP|iGFXFiD%rm)V!IIL)h$T`xP;ZaW#Kz4b+|e z0P8C0fA6HVIQ1g;He;jkmx7d2vrWSv{`2sk9eiVVf_ijLW3H|K{8ALtxOF=8z=#QU z$mP3Wr@Yw$Qk{uS&Epi#_>iONlS4N=WJ=mmQMbL0jt`k##yy3{oqRVhXraQ4YU;aj zfAy{1DhEDGQJ$#Q{m(V${L{0;oo*`vDZlYwU#7B75?ugT%r{ooVt?)gJ>~<8A0-tO z)2)=#19f)UR!PIuXNa^so+JupCm!aIF^PsSo(kE{s^4kg%qhl1KVlcTw_ZO@6t-_V ztmY$<-^zK>>`W%_`SQ!BfB}+g>%EMU)2}|h>Lfp3)va%Bhz0%yLX`T;7xtud2$M4$ zk#=JD?-6txuhuEP(htOqvqUZH;`cUa6gedKePDE8LC#2sVAUxG-_%EEN745<`~nNx zBMnlzkW!(r_r~5nXYP$8)U#W?ftjPo*6Wv>nUvA{x&#L=GLUbvF7f^2UXE&m=S+zG z-s_MBXQ@fx8PAb!lqPkJPwV_83On|o-xh+4AZsxOX_0&#K0#ihetn>$1KuUzzc<9Ov<-xGz|;>c#qK`^Z% zpSx6!1}ad9GFu9PWyR3=#gUFo<^riE2ydx64C6RxOn|G2-Srg4KK`3Jmx3ZSeqEx> zuk}6UyF|c_@L?MEte(rJww4>7)%gH+6R&TG(1=#1HOOS3wq#xY(_J2SlZ#}2GFK*9 z%GVLZ2}E{eT!znd-Qf3jSJv9!_uC{1{Oh!u{v;6XS&XRLtY2c6Gb@Mjam=Npc^Bi* zJ+7n=9p?SQBu-Pv{wu{bap#mt_EI5+NcKFUOx4KtfF}Vg7!^)7%n%c;S<+F`pK;4m zluF`JgQR!ktMGCOk=v*GJQ1nVWbKrAQ&Mdu@(O)%?!!0UMv1;EP7;!(QA(b4gH)z> zE{C4&<|BpGcXEh=VhlplIWN|xrK`T6p6pSV6=fv67G7OO6t=c+6fI5iNd#G`7%(h( zzrfH!_o7m3asEYk&euZ1zWb;AKye2Pnn*Sye0kM=Z^PE^gjj~_r?Qlb1T&T4i%9r6 zFlQZC;Iwp+P@eYTJ~ z|Cb&%FQwAsroZv%QobE&&X&I~BG)b(Y9QAZPH>T9+=me{Z@8*f)de_AQAZ$k2#la{$G166Y@QDtUpgjWSzf{cCxFX z%?7^v!NB27X`9tIL7@i<>mrg=OSm;1rK4Nc2R0gw)~UVljhY9m;v&%aT))MCP~D7c zT`d%|t}^*pXzKQE82XCg@ful(p6+ebADb6EJByvnkAy<_917B&-XouAi$?c<2YqcS z#9e1&p?4Bwqq?_!`oe>~^cx9UcPP0pu@+_V^0>qwsNl{}Ku_v^jKoxV%vIjGiY0$$ zp|4l*&+uQhbRm3Ptr^glWIt6PY|ZbfD70kf2;SC^uC?x47$+jM&NECFcdvVIwIVyh5ps&Wg*$^sIr_3b2^gM)s%K zXM=4{&4-&3HP9`NsV_`2_<;BFIb28UOsQ=IqSfV`r@i-?Hw=QW`^ba&2>3z{lk=L zGJ0H%f)}w9Vly+Vqhx#USFZEwS&s!3n5+__*dU+}Yl(gKk=4$L%A4CR+VwLRpF|r1 z7FU0^zFykhTeDO7Ogrv~wkkV5a)@CJ_Wlgwhp}On+%cK2ha_zolPY8d#M0wOz$FPT z48!OjU8^S6%v_jrE}tgBO;;*^FOfYR(;ba|ih6}uB?+Hek2haFo#x@cjG;X1#MBZ| z;%~@iX^H)!Rbavd>~imH?88xo^cyqoGh&PjX?LU=yscMjvLO$KPJ9#%_^C~ALW$C3xSDp;F723h1h!OXcI7C9A3 zD1{OH!IOx+e%|AIZ>oY!@wJPv{M`tnz}^$gqrm8nc%W@c(*yPsU}2DZn!`uBeL-YEq+Qlx5`EXdz3C$?eoYhOi7=XS5&R;HWXuFfK^sV zkCw^lER%(%E+p*^>+psvQ_tV1+ud6-WJIb}`C{|=XqLVxq4RI~#4l=!L<@Rh2(5{9 z@dld{XfiscE!utTR-&s#z=Hm(NV~3(U}aN zC5K@Z%Ll0pdZhiZn=A9D;0|x(MHWUg8p(Uc14d%kKW;oX{$Y5epT|;+l0ZSzyY!0G zMuW6ys_lfjC5kR9?u;YBO0>qhRHN*vh#dKUw_oOxk-#O*gbtz)qKC&Z-mcgbq8R4ot82 zo{;0&%-0Pn>54XV9^2iHt-JPm9bt$<^q2&v%ttw=$0`^3JuLv1H6(>3MisA1)-JV2 z(W)l-A$dYwpK7Lo4?G#?A}#HsdSh3sj(mpscSA_yA!qRqJV6zoFZ(V<0mDAs76W=d zSw63|9Ps>rl7vaL&x%Mz;+JVR{FL+O@}tY%l#yar5|XthDmgv@jHO_w$Kh}U@Gv^Q zaS@REyoR*RGOtjlPAV5{tUGSgs9~odrHz&|N)cfikiTl0xO3a!?9un5hm!p{+mB28jboe3e!>? z+%#G?#O&5*3~XHKCr8V2tYpBqFam6NhaTPOIYhGykiR_ByM`MpN$F9%QrD#IkZWj7XRK`zzdZ&RUDM-g5X*jx z7)xo$rD818kj3ku={ypW?ei>#gE~QTtun`x;O?ZTlFp;h$itz7Xpo{7YWw;Om}Tw+ z^muBt2XCG-vY-1L`cmzegMIKH0Yd+$onT#<=Sz+LEtLGzg?f;)kd%@9#0TO@5!~AH zf*vEccdN=wKV5630j1aQ@W^MOin&3PvI8pJx0{AY4OKGNpV7XUIa2=Xn435?;nBaq zOZ}27= z4z}2xt|>j+$?M!wQEN(!HMVlM4=T(^m-vpHj0vY4R((_Ocj&$3>36X@{!4T>+#zq4 zzm3Cb{j?p4VR2F=*Xp%}#42Bm%2#P+M7W|LSX>mHUbQokv1xi4ZXU`IN_B3jl2WD> z3y_I8xd-YCI7kYd7gmRt#SeLr^p)}Y(+J zHu)%4plskf+Op%%(&7zltUC2*)AF-hvP>y;@SX2+?3Q%f$-AXE-H5N>V$i!a5@2#^ zsYeFbDzPBuc&pHK2tBS~F6!lSk(UE28Dm>&PzjP#zd6uxrg{T@b`xG1AEpm@`<39#O&?e<@a8LrR}5rtNJxb#BfLm zT`N_fZHh2ls76kllD}az*<_%VGxvz!IWW;WZJf;Sv^2l>_bY0uw!QAD)DW<|*-YI@ z7DK$2Pb~2@XcpD043D#rkR1SA)L{%gH82zu zCQg0av;=jyY~`8XcQd2`Qd7V=oMy@xXmV=Ty@t_&A>|$yKSB{a5#B!w;5Ut%OP=RN zjQOYi0D`mQX;DJ&{f?-Pr&^bknxq4Q;5>1$i$T_4Bz(q7EdniC)^<}<&y7V{XYvMdoFi6KU{NFPvZ~@I zB5X!J1!e+fAhQ{|BV*1j)b1s}gbSueSp8~)7axej zd_o+X>uR)IxRPkGA;7+gvx<=k{#!(moD}o*lcjWt$Ijc$2?b_Zk6i7nGbun3!<(82 z!9Vg6+`Z4h8;;qVlIk)I7HygfhXLhR#xZ`&*;Mjrzut&DyuT?A+MvOHN$2^M?(zkd z%;o5~w{#XQ9eCX7B7gMj!ghUl&ZVX@L8(N18vhGl(}KDww!VH~rL-8L=d+#EN&x_D zRgT9o{K!m=C@~+s>;MYLU;7KC%dYlRqj(IZox7mT@JxQ^{%9*ft|!8%V9Apm{F!j* z3Es*`WCMcwiFZsG#R?nyK&_2N9(EZ z0_yjELUB(oi|@2&9fk0t5P`CT-P94=y0q?ftKm_G-Sjx@Iz8|CXKU5{l#U1vanIB{#|LgogFWE z+=uu`7hh9Tzsha7PfwORMhCVCKzZJRq`fb{OSus&{>hcg-bc;ZEE@DhcRDfaut;Ha z(IEQtTFKdGDfI4q(my9u8%n8vfBhLTcYpr|V-#nF=uL$IPU9&X@U(x<)pvPmDhX=( z$C}E9Lo6B`$lQAqep zU%~h(^;Rp*_w)morm0N)cQ!v9s9#8ibiTHRDz}toaXD^HpEdKogCQibJjv{QWLsis zm!Q{~tmPTcSd?wv*nU0spN2+kEeGW6y#Wn_!ZNXcVGS!&6|iCMqPYuEs0YOlH=zXe zv|50(GjBs(BI}z%*mNgiKno=lbCOq{Hg0iLq9Ph#@0P`y@|yYtXXGF?#wIS1uH&h|BEaZwE$=T)PlPkqA(0|MYH%sj1Q#t!I^%2S(BSP1^eGN z2Klq7^(8(cQw#~TOKA6eff1vduosk(4K`J5XQQW%rQQOuvo0Uyv-8tmCwI6S3G;I1y!Gxt z-(U7G?#3-nXrPyePZ`>{C*CTlh4%L|wmhSry}aBo00n&e)r=Di@I-su`viV#y<_-> z9(W5AFeyq)b!l0x%ahjNENGJn&fKqNNA|x?hPUjv&?^PYg^VDAuGeVyXJ0KtWm!lx$IBv(d+({^8H)~9GbZ=z~_#4viku{P9MO(Oyo2FkXPST12K zJ0++K`NW1Eq*-c&jOdX;==2uB!VM9HtQ?B#wN4^2O*(1T;tn?2Yx7k#dv!s>6a}=GH8eo zk~q5)X-{SavEj546+bg1#_&ZxO0EbBbl=T+PSZ+Z-mVEwCN)+!W*x6yU6OB3T@l8Q zQh})huug8zv}}j<#6HDO^b{!sUZ(?$2({}XUJK@Q*o@vC=zxT0H1^$AK7Brd^$k+S zLtX;1@Hm!i4~}DA06T*{xUi-dY`zt4tq2+))fZTayrZkb__}*mGZY$%%ct85rduAV z%RBOyL=g2Z6c}hmdbRvA3ZxHl_NL*?E4px9JE}fWk{av!o_wfjzG26FQd(Ugm&a%mMb9@;e3UhPm`0W_y>J zgytlqq}^MJ6V2wzZt;uO-+zO`);jYnzK+iNWrd0W2d7!pjZ+`D!Y6v5B0m`W?_`3) zHbQ|+s$9UH$02+}^HKEFeU}mRF_d(P<6+P+Y!{bdGrG}dyu&KCbf=l&pG#g2BHX5> zfFkjCHe&C+)3Vr7<6&3;OtYB3nPsP``HQ>Eq`d)726TSo{x~Ue2`}biNB>w>dT3dE zQVPU?C1_-pPw6UYDlxym%g1R4G3@zK*W}AgdSjY(UlvOX6%-Mg`(et{tvb>~LZ@+y zhB_o?0~9*$WGF>jH_hOr`Mjs;xJ5xk2{C`r!as4}Ob#v92G8mb_Hu(B}<#rOZw&K~IIvbbY_kw z=`dGPj#@Mv$d|c_Co=n*z6&N^_|$!opQyqcH`aPbK_=ErDm>=?;!T?6J$(!@H~I5( z|Cu_Xt4<3)=WcnwI9v3f<6wIHE{gc6rrgF1Fd?0Jm-Y2zE1TK-tC`e-HW%m;poo}} z^P6KJr^F(a76BzOFKzkr?~QW_*XX1neE8sT1=KzjDSCa`W{LNVg)RlU7tJ^qwZwxx zF;}Kuj*MAGhwQ~DNfGe>35;wofPoluBmS0LO1z!Y+@?PyFdM8!J6@hQnua#m))(^0K)OCijs&8Po+AM+ zkF+|w=AV0O92^JucrjXt8;JsdwTwGH8fq^E; zhnv-k_In{}i70H@p0Rc%m~|;uVLb_Z5g}xXY*-+7nq{p^)S$w)I9L`%eSUH<*SvNt z{!%CHcBjzE&R4pAsDW68yBX5g9llznFN?=*Zm zGd{1W$@&PjXo;$U<6N+0C~23pvQ_aw(m$)Kgw8pqa|p!Sj%}&LAw`c9KWJ?a{gHXR zY=a&K>0TBZsZCDmYyL}n=%M}@VZn+G%u?3`{CywkBMV|&(;+{CuR(H*--RQR(Z z?`df~G^{RBJ#MB`f26pbfd({ZF7RmhDFL_p2@WnC%!J1g(YGc8nIZ~X5wAZK+>Cj8 zfRW+S&>&uOmB&?J*99Lk_Uc#)7k9bq=+NOWv{(I={L@RPvG|A057%h;V z#$OSKLg?x(7LmL>sJBBc$UaKPMP+;{>dai_+h(xSFKg1qGGNSpqnQB)_SByz24;0d`(uD#2D+NIVpX!Vj^HN-Sh1W&$UKGi}8+!~@dH*;amFk9xH9 zF;uc>OtuRn!t@Zws#0OVp5xs3@7L!Z+YOS1@G(j# z27|&MXGYK>mpf;cNZ(|n2h_%^5SrXJV2{@BB4@>{cXcla-|ykfIiwXKfC~23bdFn<0PK@!*eke8#EF7O*5**%T3|;SHmY(Fil5y0;c$z+KR&tA1)7 z*qlK@vuCm05n0@9J!h}(1yN9J40Mj5tf?cUoS<~2iX3M+)iRlT(u#Qr&hxVK;Oec^ zn0w8on)2vNbR`ldXRIm%>iuQVZqI~^BnwU3zZt01e5^vsG*t;e)S?+r3Y2G*h9yQr5% z_Sk;dzo%$_sa1)Lh9KuU4whS)X>mJ=@6P{7hLV@~kuQ!vA%tyKttL9jyh3&$r`|*T znn!v9RYKVJxNKAzA3@m&`wh;Vxe&TMmSa4H6Gh5wzX4b2wPIceOwu0m&*%%AE4H%J z=`?C(+$RO|NHw|rcpe*AG2;g8^cMFu>&#GV_@#$kDWG7j{_5P3QPgdGbs8-LcHod{ zxgncUBrjSyR6J?I-gtzj2A}}y<;Fc!rDk_we8m>gX7S0Rp_q3cnP)3r!Zi7Mp#R5) zuRZqu^EqdAhkbU9elQQUB+2y(AI;-P>ON+~Yq8dtjv^ZWZx)I@_J!78$9~%>Ux+Pp z`_o*ff6Mhc!c#{ZTjMM^4W;v>V zwt+8%MeW*r;t`eE*!hRwR1o2jHgnbExJ@wCqLJ}PsMK~=M*z+s*NKh7O!W%=yfBsM6XT! zYT~gWW@8pGF7g{brx}V$mmNQ+_sc&u$wGH^U>(EzNh}-Bl$Y2+;Xh#=Jjgquu#q>` z6q^@3xo?WKr^@>3>NT0Z!Fx5n)L}39dG>={$Ke6vO~21I2psxSf)D5>3M+XP?}Kr_ z{fea<&!oU}Xmn3_x=0l1+O4VN$Pao$^@;L~+p`LDj?Mjdq)cQds@@CJ%rIB8IIfJT zxs+4z(;E9b`8NOCk;6T=paz@Ovt$H=?4-xUk9dq7Yq1g3cd=*jLtudgPVe0rFgYny zxl43OU-he^ZyM)9J*{0Fr|R@Xy_%MHEM?5V{V_LCie*|sg+y3cgi@>U33VQED6sQP zgx_WF+5Ed=lC5|KTse<3OVdlc&V6nh-@TyS+pzKd;v_Ntxwl;i&8g%dtr%kj(b$!p zUJiN794sc9fjn`xLfFMY4fr$pD2rd2d{ui-C*jo(k6?}F6c)o#(GLS>FS9I4FC+)h zRe_yhBT({Z35$!_VL1wzoQhJ>%Spu+*jCtkT^>ZasN(B7qE8Y643yDO&0wL-V~bq& zb4E-H&Zjz?Hd(#S`2~wzQ0DzAzDRj-#!~%V*U`>rn>g1n6%q}^keqTfhnUqIE!_ut z%yJrV(wBMG&Lgq!dcrgyo{31L-Rhj;2!yn$E*?x!Sik;88mV6hl~Ayu(-|+5w=8*ZsEo*`)VVz|S6ocTnX_r_ZCE{V0`x{a~A!*@0}g zqWO$r0w&-cO3}z4hpIKsOVv-Tbbpey@nt;Qhe@Q=yb^jlk(vyIbLd8WB2Z2h8+J?l z6IEO@XWMnij*)Rb;OX_q>>jJTt{!sx%gbs;tDabeFbk^WPutJ@HYzCP)xQu2P>9JJ zkC#9xg59|9GVDY!8FKk*PC16NsTnE`>_Zlum*YH6(pl!;mZn1$5iT_}@*`1S8D?D! z76(%;kf`#>9+ysnq*_V{=uce_#BnX}4pnXW-t|dUuFb0Yem-Bz1&tXE4CKHKJa3LL zgsEzgejpwh#g(Jc*cmCj{E5b)(3zaR8-G-nUG8dbn{XS9u_q!xVIGOSy9xA6bwt+Yd;nc}dHe&a z=94OuCHaGiS9mH_iptly4w3!8-~3T202d|1q+X>qsY_jn9)=Nzo%qM=QIbd2OvOe@ zaVp;c*_U-3**{sQ&p{SF(Bxaaz8njF-=+QlT#+8Z`THlPMVWZ`?k&~!(@DR2C#O7) z`_5hPo{+D>y+bok3}U?QH$5OC@Ri)`rs&;cRdii^SI$I!#&$ zY)YBF2X;a~3W!NyRH_k%iELRuH`$j%Sih~k(J}BCv}f%avPhGdygBgxhG2lN3XKYB z9jUlJ;`xEC;j-!VN|fwNLNUQ(y`#|E^ebn?kWZb!O1M*Ry zuFcla$2(y=zXBXF_?10`fgac=2{aM}Lgc=ndq0WBC_t*mBSZ|E2?`I>yv#M@6)2ma zEeFrOe`2G~9+3}i=7(;_Dq-h3x8z#ARH4U3lL0PZp}CZ?gnxEVbM6-uiQ<3cZ1Jhk zjb|5fmS>O4e3s3Uh!NDp%{dq@F3=G&rycEz84 ziu-HY&!T=K)A#jFj~G6Fh3V{J^a>@V$8yQLFL}%7q#pACH9clx*_g-T=);HzF{_$x zf+HvJCYA4uWl`&>s1i!cv@*e{d?n`&L^KqtR;V#AIRQb*@pR zd(`F3)xoe)kt{!TmFeH-AI|JC8G<0815*j=`65(^{$-8`SRiHR9j%LWt+wOByW^jI zDpUJ(60}j!6s3z#vhJpwzxz0z=L3gRDPAQtD)VG9k z5)l8sfbZZ(P7Bs>5~p5EOFCW9BZu$FE>Wjm&2w|cx$yMj>Vw&nVNHkp=tHlhlax^U zu-RY_CN+@Rv_D@1Ro-d-wmsB;$z1&T!GAz2LN1$`dCbe8Ro(Q$Qc@wsO`n)kuQwvq zPid~j*RA8&-2WssnrVG!x2GvjW)H-{WT+wfAi{c1VoOHULS2cfy}TacS_wx__Y>(> zrio6hq-7cHl3;b4CSo)@6cJBhl&8x5c(>Mz{kiV1cl<*CpX|K-RWJ4vPB`&Xf(n76 zw^AsSkk*~Vi>{KB=_J|k)$9Z;uK~=T6HUR1ALj@^wj^6yXWvr=yO47=byv z?euYjRn*j09Qg8>stQ8E1KF41lSr?>k|Ks4j?~C^HQnGK`B0lpUV{mv)#=taolv+< z!jFs-AF1ur%n^(qvsIc2+~6$W{v*8TpKX!Ueh`-bq5HaL(dyi7ZC zmpUm%9$iTvGhl5RR@lq+!~(n(vN72nZk7|bXZH<$U2CI$^`mX8dUy-%k0ZyZ=gSwZ zl)-$YbY4g7w?J8E$t|99k9^LGRNU@q>}3xYbc4ovJGs{(e08VToJjA^q6nOxE(L1x4~*vI zHBmqLgrx8Y^IIwyPun1$4ts?UnScx_(z*%y`*?|2ZH_R=T*tf8xUcR9QYH6&2D@Kc z%HgB#@7UY5LwBWfe_d%+jF-liJ%~&nqxE?ss#xeJMTi2L@nGL6Vq@G9tv&`Y(r#L9Y~FdBOvb-dBY0-@*TCt$ z2M!~#4q2EVIZd2o-KL?5M(+yxz(*9EC}=SFZgx6Dku9O+e(V$AV|JqW$7}g zT=Oqc4){gC*d?4S0(gS%S}n}zEdEjK7Fv7^ z1^-}mC>-2Ju;T@~b_mV?J;Y#ey1FA%dq4o9Fn2*_BXt${NNiM9HmbxMzz3SmkJ%9V zrv+s@R#4`%%Q0Pvq{G0R$%pn2EYx2WaNNE=z!x4gcja!kwmS)tp(ts}fbTef>}Mw@ z9v)k21FBBWk#T;BepfmhQfWxLlZCnAjCE`E zLAr4aCqFMt-L6g0hL}-N-uQuU4<+@ zIzXCcbx2A$MNVA;7A=1z=0smu728H)cK+Re!DISa;8AmOR-jJ6fk!m_^P#g%0wUkv z*vp%s`M_nI?ql*hg3{|^D$Tb}sL}zW){V!DJco@O_X-E{aji{K|M5toK)ZQ*Bn9GL>G)obOTc+ z>rg2nSV*mpy1~__&9mAZ%K2}^H}G|9|4F6d-NOJXB!(;qT{`P;(mg7O%Wr_g15?$w zO_A$;YPv0w_5(#Kw7wudFbEA*SL9%R^#kG{=?U8N7}BHUF$!Ed5#)Uc#VZ7j=Ap+S z3hg9K!e5BqRqLHr1a!S>WX%5|uO|%&y4@n){(Sf&ccFIVYvD+M^G##DBo`2cjH1Uu z;IyW1paFt_J*Fn;_G6)Js*Eg^!G*>(M4^(A2sLs^SZAMpk2op`eAlGU%bppcFrth^ zq2rl7%XMt&V&uHh-EkDi!n7? z5Rsxo{Kh|G8*POL{kJtg%~Vll>VY2wgx+3Qs6qwx`h&u^NdtA?)wo<+-hE>JRH~+kN_fqe-P!yve%6VIU0&I4y!Rbj4ak-p0f)=RN zi`h(U4jrG*ffjPksnCB!vZWth8j~C|Yjs$5`T5$qX-LBAZ8*A7XyJD3G<4_RcQODJ zoSC(AJKxbROM&mgJNmNGp zS9l7UqLA8`q+#Lf&%X}&80X5V;nj3|+uU9VJH6-l%*E+>H#6?#XeT8@Sc*cNOCN4U zW#domLiO5E^Ncn*FU>ablcpEHDfCezt*?9b)=Q;hKEnBs1DHlmiR<|vB@7`)RKHQ| zI4g2W9>#2v&wn#%o}zf++**?_3{2>L_>m?*UZVZhj{jg1gCDlr1Ad<|XVf4#Y08Fp zVdwKs;gc5yauhRa7tV&{R#&B)hyF9?qD(+EQ>7ng)QqV3Q`)R%!<%TAveCc46tmeZ zCFO=o#DxFo@QWgF{A@6~SmZ_WL|%g&MHSj}Qc?DJvvIQ{VmO=9JZZq>55` z?sIpxO>o-F2~yTc|wVg^wU8{Xzj9W%z*t^c6FP2C+xCB(b+=G-CBKoW*j@oO=y z0_OKMFB5aw#MPanBu zkiLnQWYOx$rY;%z_W1SVzohT~kL!#OpGFi~)G#`(r4|)Q3y5%Ha}B^jJ#h zr*l^O$H2h%Z2q`v7w#eX%nG$xnqk>dJhq9pT~f_U#|vMh3M1qaWQq3IRWNsQcO?xN z;YF}@(c1x$f0A&(+#KmhMWz_TQG?yuuJA z8V}MBjG7RACCt6q$(#-Huz3yrLg4?~ly865a~-_%aPzKU#`@%4qL)^(yz Setups +#load data +FILE <- '../data/delta_num.RData' +FILE <- paste(getwd(), FILE, sep="/") +library(ccdata) +if (!exists("ccd_delta_num")) + load(FILE) +ccd <- ccd_delta_num +siteinfol <- site.info() +siteinfot <- as.data.frame(siteinfol, stringsAsFactors=FALSE) +row.names(siteinfot) <- c("Hospital", "Unit", "Location", "Notes") +siteinfot <- siteinfot[1:3, ] # remove notes +info <- extract.info(ccd) + +suppressWarnings(library(pander)) +panderOptions("digits", 2) +panderOptions("table.split.table", Inf) + +ctime <- file.info(FILE)$ctime +hostname <- system('hostname') +``` + +\newpage + +# Data Summary +This is the data summary of file ``r FILE`` which sits on the machine +``r Sys.info()['nodename']``, created at ``r ctime``. + +## Site Code Information +```{r, echo=FALSE} +panderOptions("table.style", "multiline") +pander(t(siteinfot), split.table = Inf) +``` +## XML files +```{r, echo=FALSE} +pander(file.summary.table(info)) +``` + +## Data Summary of Sites +```{r pander, echo=FALSE} +pander(summary.table2(info)) +``` + + +# Identification Issues +## Non-identifiable Episodes +```{r, echo=FALSE} +allmiss = info[nhs_number=="NULL" & pas_number=="NULL"] +numallmiss = nrow(allmiss) +``` +Patient identity is based on NHS number or PAS number. In this data extract, +there are **`r mdred(numallmiss)`** episodes missing both NHS number and PAS +number. The non-identifiable episodes are distributed as following, + +```{r, echo=FALSE} +pander(allmiss[,list("Number of Non-identifiable Episodes"=.N), by="Site"]) +``` +## Identification Missingness +```{r, echo=FALSE} +pander(id.missingness(info)) +``` + +# Entire Field Missingness +\footnotesize +```{r, echo=FALSE} +pander(miss.fields(ccd)) +``` diff --git a/inst/report/listings-setup.tex b/inst/report/listings-setup.tex new file mode 100644 index 0000000..34e46d6 --- /dev/null +++ b/inst/report/listings-setup.tex @@ -0,0 +1,58 @@ +\usepackage{xcolor} + +\usepackage{listings} +\usepackage{color} + +\definecolor{mygreen}{rgb}{0,0.6,0} +\definecolor{mygray}{rgb}{0.5,0.5,0.5} +\definecolor{mymauve}{rgb}{0.58,0,0.82} +\definecolor{mygray}{gray}{.9} + +\lstset{ % + backgroundcolor=\color{mygray}, % choose the background color; you must add \usepackage{color} or \usepackage{xcolor} + basicstyle=\fontfamily{cmtt}\footnotesize, % the size of the fonts that are used for the code + breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace + breaklines=true, % sets automatic line breaking + captionpos=b, % sets the caption-position to bottom + commentstyle=\color{mygreen}, % comment style + deletekeywords={...}, % if you want to delete keywords from the given language +% escapeinside={\%*}{*)}, % if you want to add LaTeX within your code + extendedchars=true, % lets you use non-ASCII characters; for 8-bits encodings only, does not work with UTF-8 + frame=single, % adds a frame around the code + keepspaces=true, % keeps spaces in text, useful for keeping indentation of code (possibly needs columns=flexible) + keywordstyle=\color{blue}, % keyword style +% language=Octave, % the language of the code + otherkeywords={*,...}, % if you want to add more keywords to the set +% numbers=left, % where to put the line-numbers; possible values are (none, left, right) +% numbersep=5pt, % how far the line-numbers are from the code +% numberstyle=\tiny\color{mygray}, % the style that is used for the line-numbers + rulecolor=\color{black}, % if not set, the frame-color may be changed on line-breaks within not-black text (e.g. comments (green here)) + showspaces=false, % show spaces everywhere adding particular underscores; it overrides 'showstringspaces' + showstringspaces=false, % underline spaces within strings only + showtabs=false, % show tabs within strings adding particular underscores + stepnumber=2, % the step between two line-numbers. If it's 1, each line will be numbered + stringstyle=\color{mymauve}, % string literal style + tabsize=2, % sets default tabsize to 2 spaces + title=\lstname % show the filename of files included with \lstinputlisting; also try caption instead of title +} + +%\lstset{ +% basicstyle=\ttfamily, +%% numbers=left, +%% numberstyle=\footnotesize, +%% stepnumber=2, +%% numbersep=5pt, +% backgroundcolor=\color{black!10}, +% showspaces=false, +% showstringspaces=false, +% showtabs=false, +% tabsize=2, +% captionpos=b, +% breaklines=true, +% breakatwhitespace=true, +% breakautoindent=true, +% linewidth=80 +%} + + + diff --git a/inst/report/report.latex b/inst/report/report.latex new file mode 100644 index 0000000..50186a7 --- /dev/null +++ b/inst/report/report.latex @@ -0,0 +1,246 @@ +\documentclass[$if(fontsize)$$fontsize$,$endif$$if(lang)$$lang$,$endif$$if(papersize)$$papersize$,$endif$]{$documentclass$} + + + + +\usepackage[T1]{fontenc} +\usepackage{lmodern} +\usepackage{amssymb,amsmath} +\usepackage{ifxetex,ifluatex} +\usepackage[svgnames]{xcolor} % Enabling colors by their 'svgnames' +\usepackage{fixltx2e} % provides \textsubscript +% use microtype if available +\IfFileExists{microtype.sty}{\usepackage{microtype}}{} +% use upquote if available, for straight quotes in verbatim environments +\IfFileExists{upquote.sty}{\usepackage{upquote}}{} +\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex + \usepackage[utf8]{inputenc} +$if(euro)$ + \usepackage{eurosym} +$endif$ +\else % if luatex or xelatex + \usepackage{fontspec} + \ifxetex + \usepackage{xltxtra,xunicode} + \fi + \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} + \newcommand{\euro}{€} +$if(mainfont)$ + \setmainfont{$mainfont$} +$endif$ +$if(sansfont)$ + \setsansfont{$sansfont$} +$endif$ +$if(monofont)$ + \setmonofont{$monofont$} +$endif$ +$if(mathfont)$ + \setmathfont{$mathfont$} +$endif$ +\fi +$if(geometry)$ +\usepackage[$for(geometry)$$geometry$$sep$,$endfor$]{geometry} +$endif$ +$if(natbib)$ +\usepackage{natbib} +\bibliographystyle{plainnat} +$endif$ +$if(biblatex)$ +\usepackage{biblatex} +$if(biblio-files)$ +\bibliography{$biblio-files$} +$endif$ +$endif$ +$if(listings)$ +\usepackage{listings} +$endif$ +$if(lhs)$ +\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{} +$endif$ +$if(highlighting-macros)$ +$highlighting-macros$ +$endif$ +$if(verbatim-in-note)$ +\usepackage{fancyvrb} +$endif$ +$if(tables)$ +\usepackage{longtable} +\let\oldlongtable\longtable + +\def\longtable{\tiny \oldlongtable} + +$endif$ +\usepackage{libertine} +\usepackage{framed} +\let\oldquote\quote +\let\endoldquote\endquote +\newcommand*\openquote{\makebox(25,-22){\scalebox{5}{\color{DarkGreen}``}}} +\newcommand*\closequote{\makebox(25,-22){\scalebox{5}{\color{DarkGreen}''}}} +\definecolor{verypalegreen}{RGB}{252,255,250} +\colorlet{shadecolor}{verypalegreen} +%\setlength{\textwidth}{6in} +\makeatletter +\def\shadequote{\begin{snugshade}\begin{oldquote}\openquote} +\def\endshadequote{% + \closequote\end{oldquote}\end{snugshade}} +\makeatother + +\renewenvironment{quote}{\begin{shadequote}}{\end{shadequote}} +\usepackage{graphicx} +% We will generate all images so they have a width \maxwidth. This means +% that they will get their normal width if they fit onto the page, but +% are scaled down if they would overflow the margins. +\makeatletter +\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth +\else\Gin@nat@width\fi} +\makeatother +\let\Oldincludegraphics\includegraphics +\renewcommand{\includegraphics}[1]{\Oldincludegraphics[width=\maxwidth]{#1}} +\ifxetex + \usepackage[setpagesize=false, % page size defined by xetex + unicode=false, % unicode breaks when used with xetex + xetex]{hyperref} +\else + \usepackage[unicode=true]{hyperref} +\fi +\hypersetup{breaklinks=true, + bookmarks=true, + pdfauthor={$author-meta$}, + pdftitle={$title-meta$}, + colorlinks=true, + urlcolor=$if(urlcolor)$$urlcolor$$else$blue$endif$, + linkcolor=$if(linkcolor)$$linkcolor$$else$magenta$endif$, + pdfborder={0 0 0}} +\urlstyle{same} % don't use monospace font for urls +$if(links-as-notes)$ +% Make links footnotes instead of hotlinks: +\renewcommand{\href}[2]{#2\footnote{\url{#1}}} +$endif$ +$if(strikeout)$ +\usepackage[normalem]{ulem} +% avoid problems with \sout in headers with hyperref: +\pdfstringdefDisableCommands{\renewcommand{\sout}{}} +$endif$ +\setlength{\parindent}{0pt} +\setlength{\parskip}{6pt plus 2pt minus 1pt} +\setlength{\emergencystretch}{3em} % prevent overfull lines +$if(numbersections)$ +$else$ +\setcounter{secnumdepth}{0} +$endif$ +$if(verbatim-in-note)$ +\VerbatimFootnotes % allows verbatim text in footnotes +$endif$ +$if(lang)$ +\ifxetex + \usepackage{polyglossia} + \setmainlanguage{$mainlang$} +\else + \usepackage[$lang$]{babel} +\fi +$endif$ +$for(header-includes)$ +$header-includes$ +$endfor$ + +\usepackage{lettrine} % Package to accentuate the first letter of the text +\usepackage{fix-cm} % Custom font sizes - used for the initial letter in the document + +\definecolor{uclmidgreen}{RGB}{130,141,55} + +\newcommand{\initial}[1]{ % Defines the command and style for the first letter +\lettrine[lines=3,lhang=0.3,nindent=0em]{ +\color{DarkGreen} +{\textsf{#1}}}{}} + +\definecolor{ccdblue}{RGB}{0, 54, 73} +\usepackage{sectsty} % Enables custom section titles +\sectionfont{\color{ccdblue}\fontsize{20}{20}\usefont{OT1}{phv}{b}{n}} % Change the font of all section commands +\subsectionfont{\color{ccdblue}\fontsize{16}{16}\usefont{OT1}{phv}{b}{n}} % Change the font of all section commands + + +\usepackage{titling} % Allows custom title configuration +\newcommand{\HorRule}{\color{DarkSeaGreen} \rule{\linewidth}{1pt}} % Defines the gold horizontal rule around the title +\usepackage{pagecolor}% With option pagecolor={somecolor or none} +\pretitle{ + \vspace*{\fill} + \Oldincludegraphics[scale=0.15]{ccd_color} + \par + \fontsize{35}{35} + \usefont{OT1}{phv}{b}{n} + \color{ccdblue} + \selectfont +} +\posttitle{\vspace*{\fill}} +$if(title)$ +\title{$title$} +$endif$ + +\author{$for(author)$$author$$sep$ \and $endfor$} +\date{$date$} + +%\postauthor{\footnotesize \usefont{OT1}{phv}{m}{sl} \color{Black} % Configuration for the institution name +% +% +%University College London% Your institution +% +%\par\end{flushleft}\HorRule} % Horizontal rule after the title + + +\usepackage{picture} +\usepackage{eso-pic} + +\renewcommand{\rmdefault}{phv} + +\usepackage{fancyhdr} + +\begin{document} +%\pagecolor{seafoam} +$if(title)$ +\maketitle +$endif$ +\newpage +\pagecolor{white} +\pagestyle{fancy} +\fancyhf{} +\rhead{\Oldincludegraphics[scale=0.1]{ccd_gray}} +\lhead{\leftmark} +\rfoot{Page \thepage} + +$for(include-before)$ +$include-before$ +$endfor$ + +\par \par + +$if(toc)$ +{ + \hypersetup{linkcolor=black} +\setcounter{tocdepth}{$toc-depth$} +\tableofcontents +} +$endif$ +$body$ + +$if(natbib)$ +$if(biblio-files)$ +$if(biblio-title)$ +$if(book-class)$ +\renewcommand\bibname{$biblio-title$} +$else$ +\renewcommand\refname{$biblio-title$} +$endif$ +$endif$ +\bibliography{$biblio-files$} + +$endif$ +$endif$ +$if(biblatex)$ +\printbibliography$if(biblio-title)$[title=$biblio-title$]$endif$ + +$endif$ +$for(include-after)$ +$include-after$ + +$endfor$ +\end{document} diff --git a/man/data.quality.report.Rd b/man/data.quality.report.Rd new file mode 100644 index 0000000..c32cd41 --- /dev/null +++ b/man/data.quality.report.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/data.quality.report.R +\name{data.quality.report} +\alias{data.quality.report} +\title{Create the data quality report} +\usage{ +data.quality.report(ccd, pdf = T) +} +\description{ +Create the data quality report +} + From a0d4abfa96c35ec662fcb270156fa8011e39c8cb Mon Sep 17 00:00:00 2001 From: Sinan Shi Date: Wed, 23 Nov 2016 18:35:36 +0000 Subject: [PATCH 04/14] DQ report: file list --- R/data.quality.report.R | 10 +++++----- inst/report/bar.png | Bin 0 -> 4087 bytes inst/report/data_quality_report.Rmd | 20 +++++++++++++++++--- inst/report/report.latex | 24 +++++++++++++++++------- 4 files changed, 39 insertions(+), 15 deletions(-) create mode 100644 inst/report/bar.png diff --git a/R/data.quality.report.R b/R/data.quality.report.R index d4676d4..fd519d4 100644 --- a/R/data.quality.report.R +++ b/R/data.quality.report.R @@ -4,15 +4,15 @@ #' @import knitr data.quality.report <- function(ccd, pdf=T) { - if (!dir.exists(".temp")) { - unlink(".temp", recursive=T) - dir.create(".temp") + if (!dir.exists(".report")) { + unlink(".report", recursive=T) + dir.create(".report") } wd <- getwd() rptpath <- paste(path.package('ccdata'), "report", sep="/") - file.copy(rptpath, ".temp", recursive=T) + file.copy(rptpath, ".report", recursive=T) - setwd('.temp/report') + setwd('.report/report') dqpath <- "data_quality_report.Rmd" headerpath <- "listings-setup.tex" tpltpath <- "report.latex" diff --git a/inst/report/bar.png b/inst/report/bar.png new file mode 100644 index 0000000000000000000000000000000000000000..9e3d0478c892a88cdc4b4af0631d9217eac860bf GIT binary patch literal 4087 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 Date: Sat, 26 Nov 2016 17:26:07 +0000 Subject: [PATCH 05/14] Adding total data point counts; ethnicity table 1. --- NAMESPACE | 4 ++ R/data.quality.report.R | 90 ++++++++++++++++++++++++++++- data/ITEM_REF.yaml | 32 ++++++++++ inst/report/data_quality_report.Rmd | 29 +++++++--- 4 files changed, 144 insertions(+), 11 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 15836a1..30ba382 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -18,6 +18,7 @@ export(deltaTime) export(demographic.patient.spell) export(extractInfo) export(extract_file_origin) +export(file.summary) export(find.episode.time) export(for_each_episode) export(getEpisodePeriod) @@ -36,9 +37,12 @@ export(selectTable) export(short2longname) export(sql.demographic.table) export(stname2code) +export(table1.row) +export(total.data.point) export(unique.spell) export(update.database) export(which.classification) +export(xml.file.duration.plot) export(xml2Data) export(xmlEpisodeToList) export(xmlLoad) diff --git a/R/data.quality.report.R b/R/data.quality.report.R index fd519d4..b8fb9a7 100644 --- a/R/data.quality.report.R +++ b/R/data.quality.report.R @@ -4,10 +4,11 @@ #' @import knitr data.quality.report <- function(ccd, pdf=T) { - if (!dir.exists(".report")) { + if (dir.exists(".report")) { unlink(".report", recursive=T) - dir.create(".report") } + + dir.create(".report") wd <- getwd() rptpath <- paste(path.package('ccdata'), "report", sep="/") file.copy(rptpath, ".report", recursive=T) @@ -35,3 +36,88 @@ data.quality.report <- function(ccd, pdf=T) { setwd(wd) } } + + +#' @export file.summary +file.summary <- function(ccd) { + infotb <- ccd@infotb + file.summary <- infotb[, list("Number of Episode"=.N, + "Upload time"=max(parse_time), + "Sites"=paste(unique(site_id), collapse=", ")), by=parse_file] + file.summary[, "File":=parse_file] + file.summary[, parse_file:=NULL] + return(file.summary) +} + +#' @export xml.file.duration.plot +xml.file.duration.plot <- function(ccd) { + tb <- copy(ccd@infotb) + tb <- tb[, list(minadm=min(t_admission, na.rm=T), + maxadm=max(t_admission, na.rm=T), + mindis=min(t_discharge, na.rm=T), + maxdis=max(t_discharge, na.rm=T)), by=parse_file] + ggplot(tb, aes(x=minadm, y=parse_file)) + + geom_segment(aes(xend=maxdis, yend=parse_file), color="gray", size=7) + + annotate("text", x=tb$minadm+(tb$maxdis-tb$minadm)/2, + y=tb$parse_file, label=tb$parse_file, size=3) + + scale_x_datetime(date_breaks="3 month")+ + theme(axis.text.y=element_blank()) + + ggtitle("The Duration of XML Files") + + xlab("") + ylab("") +} + + +ethnicity.plot <- function(demg) { + ggplot(demg, aes(x=ETHNIC, fill=ETHNIC)) + + scale_fill_discrete(h=c(50,250)) + + geom_bar(aes(y=(..count..)/sum(..count..) * 100)) + + geom_text(aes(y = ((..count..)/sum(..count..))*100, + label = scales::percent((..count..)/sum(..count..))), + stat = "count", vjust = -0.25) +} + + + +#demographic.data.completeness <- function(ccd) { +# demographic +#} + +#' +#' @export total.data.point +total.data.point <- function(ccd) { + dp.physio <- + sum(unlist(for_each_episode(ccd, + function(x) + Reduce(sum, sapply(x@data, nrow))))) + dp.demg <- + sum(unlist(for_each_episode(ccd, + function(x) + Reduce(sum, sapply(x@data, nrow))))) + return(sum(dp.physio, dp.demg)) +} + +#' @export table1.row +table1.row <- function(demg, name) { + ref <- ccdata:::ITEM_REF[[stname2code(name)]] + if (ref$Datatype %in% c("text", "list")) { + stopifnot(!is.null(ref$category)) + nmref <- sapply(ref$category$levels, function(x) x) + r <- demg[, .N, by=name] + level.name <- nmref[r[[name]]] + r[, nm:=level.name] + r[, percent:=N/nrow(demg)*100] + + txt <- paste("
  • ", + r$nm, ":\t\t\t\t", + r$N, "[", + round(r$percent),"%]", + "
  • ", + sep="", + collapse="") + txt <- paste("