From 257ac748f58154879e4db1b6b866de1a207b5e49 Mon Sep 17 00:00:00 2001 From: jwallib Date: Wed, 7 Jul 2021 15:07:43 +0000 Subject: [PATCH 1/2] Patch fix for long formula names --- R/coxph.R | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/R/coxph.R b/R/coxph.R index 796221af..c485c80b 100644 --- a/R/coxph.R +++ b/R/coxph.R @@ -33,7 +33,10 @@ coxph <- function(formula, data, weights, subset, na.action, terms(formula[[1]], specials=ss, data=data) else Terms <- if (missing(data)) terms(formula, specials=ss) else terms(formula, specials=ss, data=data) - + attr(Terms,'term.labels') = gsub('\n',' ', attr(Terms,'term.labels')) + colnames(attr(Terms,'factors')) = gsub('\n',' ', colnames(attr(Terms,'factors'))) + rownames(attr(Terms,'factors')) = gsub('\n',' ', rownames(attr(Terms,'factors'))) + tcl <- attr(Terms, 'specials')$cluster if (length(tcl) > 1) stop("a formula cannot have multiple cluster terms") @@ -127,7 +130,10 @@ coxph <- function(formula, data, weights, subset, na.action, # okay, now evaluate the formula mf <- eval(tform, parent.frame()) Terms <- terms(mf) - + attr(Terms,'term.labels') = gsub('\n',' ', attr(Terms,'term.labels')) + colnames(attr(Terms,'factors')) = gsub('\n',' ', colnames(attr(Terms,'factors'))) + rownames(attr(Terms,'factors')) = gsub('\n',' ', rownames(attr(Terms,'factors'))) + # Grab the response variable, and deal with Surv2 objects n <- nrow(mf) Y <- model.response(mf) From 667d64783ab23bc567aaf79413063dd3ec184eae Mon Sep 17 00:00:00 2001 From: jwallib Date: Thu, 8 Jul 2021 08:34:30 +0000 Subject: [PATCH 2/2] Move patch to noweb and make all --- noweb/balance.pdf | Bin 0 -> 4351 bytes noweb/code.aux | 35 + noweb/code.log | 947 +++ noweb/code.nw | 17011 +++++++++++++++++++++++++++++++++++++++ noweb/code.out | 12 + noweb/code.pdf | Bin 0 -> 408326 bytes noweb/code.tex | 17262 ++++++++++++++++++++++++++++++++++++++++ noweb/code.toc | 0 noweb/coxph.Rnw | 10 +- noweb/noweb.sty | 25 + src/agexact.o | Bin 0 -> 29688 bytes src/agfit4.o | Bin 0 -> 49064 bytes src/agfit5.o | Bin 0 -> 48296 bytes src/agmart.o | Bin 0 -> 12784 bytes src/agmart3.o | Bin 0 -> 19984 bytes src/agscore2.o | Bin 0 -> 19848 bytes src/agsurv3.o | Bin 0 -> 29984 bytes src/agsurv4.o | Bin 0 -> 12248 bytes src/agsurv5.o | Bin 0 -> 11312 bytes src/cdecomp.o | Bin 0 -> 17160 bytes src/chinv2.o | Bin 0 -> 10728 bytes src/chinv3.o | Bin 0 -> 12704 bytes src/cholesky2.o | Bin 0 -> 5848 bytes src/cholesky3.o | Bin 0 -> 12800 bytes src/cholesky5.o | Bin 0 -> 7376 bytes src/chsolve2.o | Bin 0 -> 10016 bytes src/chsolve3.o | Bin 0 -> 10672 bytes src/chsolve5.o | Bin 0 -> 5728 bytes src/collapse.o | Bin 0 -> 15016 bytes src/concordance1.o | Bin 0 -> 25824 bytes src/concordance3.o | Bin 0 -> 44288 bytes src/concordance5.o | Bin 0 -> 29800 bytes src/cox_Rcallback.o | Bin 0 -> 21672 bytes src/coxcount1.o | Bin 0 -> 32512 bytes src/coxdetail.o | Bin 0 -> 18960 bytes src/coxexact.o | Bin 0 -> 45176 bytes src/coxfit5.o | Bin 0 -> 49896 bytes src/coxfit6.o | Bin 0 -> 41696 bytes src/coxmart.o | Bin 0 -> 13600 bytes src/coxmart2.o | Bin 0 -> 11416 bytes src/coxph_wtest.o | Bin 0 -> 12152 bytes src/coxsafe.o | Bin 0 -> 3264 bytes src/coxscho.o | Bin 0 -> 13656 bytes src/coxscore2.o | Bin 0 -> 18656 bytes src/coxsurv1.o | Bin 0 -> 24752 bytes src/coxsurv2.o | Bin 0 -> 26272 bytes src/dmatrix.o | Bin 0 -> 10904 bytes src/doloop.o | Bin 0 -> 11048 bytes src/finegray.o | Bin 0 -> 19064 bytes src/gchol.o | Bin 0 -> 16208 bytes src/init.o | Bin 0 -> 17736 bytes src/multicheck.o | Bin 0 -> 15800 bytes src/norisk.o | Bin 0 -> 12208 bytes src/pyears1.o | Bin 0 -> 21320 bytes src/pyears2.o | Bin 0 -> 16392 bytes src/pyears3b.o | Bin 0 -> 24000 bytes src/pystep.o | Bin 0 -> 12528 bytes src/survConcordance.o | Bin 0 -> 12928 bytes src/survdiff2.o | Bin 0 -> 14464 bytes src/survfit4.o | Bin 0 -> 10648 bytes src/survfitci.o | Bin 0 -> 30736 bytes src/survfitkm.o | Bin 0 -> 52672 bytes src/survfitresid.o | Bin 0 -> 30432 bytes src/survival.so | Bin 0 -> 715760 bytes src/survpenal.o | Bin 0 -> 18616 bytes src/survreg6.o | Bin 0 -> 33904 bytes src/survreg7.o | Bin 0 -> 45656 bytes src/survregc1.o | Bin 0 -> 30088 bytes src/survregc2.o | Bin 0 -> 24800 bytes src/survsplit.o | Bin 0 -> 16960 bytes src/tmerge.o | Bin 0 -> 20216 bytes src/zph1.o | Bin 0 -> 29392 bytes src/zph2.o | Bin 0 -> 36264 bytes 73 files changed, 35300 insertions(+), 2 deletions(-) create mode 100644 noweb/balance.pdf create mode 100644 noweb/code.aux create mode 100644 noweb/code.log create mode 100644 noweb/code.nw create mode 100644 noweb/code.out create mode 100644 noweb/code.pdf create mode 100644 noweb/code.tex create mode 100644 noweb/code.toc create mode 100644 noweb/noweb.sty create mode 100644 src/agexact.o create mode 100644 src/agfit4.o create mode 100644 src/agfit5.o create mode 100644 src/agmart.o create mode 100644 src/agmart3.o create mode 100644 src/agscore2.o create mode 100644 src/agsurv3.o create mode 100644 src/agsurv4.o create mode 100644 src/agsurv5.o create mode 100644 src/cdecomp.o create mode 100644 src/chinv2.o create mode 100644 src/chinv3.o create mode 100644 src/cholesky2.o create mode 100644 src/cholesky3.o create mode 100644 src/cholesky5.o create mode 100644 src/chsolve2.o create mode 100644 src/chsolve3.o create mode 100644 src/chsolve5.o create mode 100644 src/collapse.o create mode 100644 src/concordance1.o create mode 100644 src/concordance3.o create mode 100644 src/concordance5.o create mode 100644 src/cox_Rcallback.o create mode 100644 src/coxcount1.o create mode 100644 src/coxdetail.o create mode 100644 src/coxexact.o create mode 100644 src/coxfit5.o create mode 100644 src/coxfit6.o create mode 100644 src/coxmart.o create mode 100644 src/coxmart2.o create mode 100644 src/coxph_wtest.o create mode 100644 src/coxsafe.o create mode 100644 src/coxscho.o create mode 100644 src/coxscore2.o create mode 100644 src/coxsurv1.o create mode 100644 src/coxsurv2.o create mode 100644 src/dmatrix.o create mode 100644 src/doloop.o create mode 100644 src/finegray.o create mode 100644 src/gchol.o create mode 100644 src/init.o create mode 100644 src/multicheck.o create mode 100644 src/norisk.o create mode 100644 src/pyears1.o create mode 100644 src/pyears2.o create mode 100644 src/pyears3b.o create mode 100644 src/pystep.o create mode 100644 src/survConcordance.o create mode 100644 src/survdiff2.o create mode 100644 src/survfit4.o create mode 100644 src/survfitci.o create mode 100644 src/survfitkm.o create mode 100644 src/survfitresid.o create mode 100644 src/survival.so create mode 100644 src/survpenal.o create mode 100644 src/survreg6.o create mode 100644 src/survreg7.o create mode 100644 src/survregc1.o create mode 100644 src/survregc2.o create mode 100644 src/survsplit.o create mode 100644 src/tmerge.o create mode 100644 src/zph1.o create mode 100644 src/zph2.o diff --git a/noweb/balance.pdf b/noweb/balance.pdf new file mode 100644 index 0000000000000000000000000000000000000000..06b0d72df609dff6eb7efd09ba9800d2d7aa9785 GIT binary patch literal 4351 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 +Babel <3.18> and hyphenation patterns for 3 language(s) loaded. +(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls +Document Class: article 2014/09/29 v1.4h Standard LaTeX document class +(/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo +File: size10.clo 2014/09/29 v1.4h Standard LaTeX file (size option) +) +\c@part=\count79 +\c@section=\count80 +\c@subsection=\count81 +\c@subsubsection=\count82 +\c@paragraph=\count83 +\c@subparagraph=\count84 +\c@figure=\count85 +\c@table=\count86 +\abovecaptionskip=\skip41 +\belowcaptionskip=\skip42 +\bibindent=\dimen102 +) (./noweb.sty +(/usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty +Package: fancyvrb 2008/02/07 + +Style option: `fancyvrb' v2.7a, with DG/SPQR fixes, and firstline=lastline fix +<2008/02/07> (tvz) (/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +Package: keyval 2014/10/28 v1.15 key=value parser (DPC) +\KV@toks@=\toks14 +) +\FV@CodeLineNo=\count87 +\FV@InFile=\read1 +\FV@TabBox=\box26 +\c@FancyVerbLine=\count88 +\FV@StepNumber=\count89 +\FV@OutFile=\write3 +) (/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +Package: hyperref 2018/02/06 v6.86b Hypertext links for LaTeX + +(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-hyperref.sty +Package: hobsub-hyperref 2016/05/16 v1.14 Bundle oberdiek, subset hyperref (HO) + + +(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-generic.sty +Package: hobsub-generic 2016/05/16 v1.14 Bundle oberdiek, subset generic (HO) +Package: hobsub 2016/05/16 v1.14 Construct package bundles (HO) +Package: infwarerr 2016/05/16 v1.4 Providing info/warning/error messages (HO) +Package: ltxcmds 2016/05/16 v1.23 LaTeX kernel commands for general use (HO) +Package: ifluatex 2016/05/16 v1.4 Provides the ifluatex switch (HO) +Package ifluatex Info: LuaTeX not detected. +Package: ifvtex 2016/05/16 v1.6 Detect VTeX and its facilities (HO) +Package ifvtex Info: VTeX not detected. +Package: intcalc 2016/05/16 v1.2 Expandable calculations with integers (HO) +Package: ifpdf 2017/03/15 v3.2 Provides the ifpdf switch +Package: etexcmds 2016/05/16 v1.6 Avoid name clashes with e-TeX commands (HO) +Package etexcmds Info: Could not find \expanded. +(etexcmds) That can mean that you are not using pdfTeX 1.50 or +(etexcmds) that some package has redefined \expanded. +(etexcmds) In the latter case, load this package earlier. +Package: kvsetkeys 2016/05/16 v1.17 Key value parser (HO) +Package: kvdefinekeys 2016/05/16 v1.4 Define keys (HO) +Package: pdftexcmds 2018/01/21 v0.26 Utility functions of pdfTeX for LuaTeX (HO +) +Package pdftexcmds Info: LuaTeX not detected. +Package pdftexcmds Info: \pdf@primitive is available. +Package pdftexcmds Info: \pdf@ifprimitive is available. +Package pdftexcmds Info: \pdfdraftmode found. +Package: pdfescape 2016/05/16 v1.14 Implements pdfTeX's escape features (HO) +Package: bigintcalc 2016/05/16 v1.4 Expandable calculations on big integers (HO +) +Package: bitset 2016/05/16 v1.2 Handle bit-vector datatype (HO) +Package: uniquecounter 2016/05/16 v1.3 Provide unlimited unique counter (HO) +) +Package hobsub Info: Skipping package `hobsub' (already loaded). +Package: letltxmacro 2016/05/16 v1.5 Let assignment for LaTeX macros (HO) +Package: hopatch 2016/05/16 v1.3 Wrapper for package hooks (HO) +Package: xcolor-patch 2016/05/16 xcolor patch +Package: atveryend 2016/05/16 v1.9 Hooks at the very end of document (HO) +Package atveryend Info: \enddocument detected (standard20110627). +Package: atbegshi 2016/06/09 v1.18 At begin shipout hook (HO) +Package: refcount 2016/05/16 v3.5 Data extraction from label references (HO) +Package: hycolor 2016/05/16 v1.8 Color options for hyperref/bookmark (HO) +) +(/usr/share/texlive/texmf-dist/tex/generic/ifxetex/ifxetex.sty +Package: ifxetex 2010/09/12 v0.6 Provides ifxetex conditional +) +(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/auxhook.sty +Package: auxhook 2016/05/16 v1.4 Hooks for auxiliary files (HO) +) +(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/kvoptions.sty +Package: kvoptions 2016/05/16 v3.12 Key value format for package options (HO) +) +\@linkdim=\dimen103 +\Hy@linkcounter=\count90 +\Hy@pagecounter=\count91 + +(/usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def +File: pd1enc.def 2018/02/06 v6.86b Hyperref: PDFDocEncoding definition (HO) +) +\Hy@SavedSpaceFactor=\count92 + +(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/hyperref.cfg +File: hyperref.cfg 2002/06/06 v1.2 hyperref configuration of TeXLive +) +Package hyperref Info: Hyper figures OFF on input line 4509. +Package hyperref Info: Link nesting OFF on input line 4514. +Package hyperref Info: Hyper index ON on input line 4517. +Package hyperref Info: Plain pages OFF on input line 4524. +Package hyperref Info: Backreferencing OFF on input line 4529. +Package hyperref Info: Implicit mode ON; LaTeX internals redefined. +Package hyperref Info: Bookmarks ON on input line 4762. +\c@Hy@tempcnt=\count93 + +(/usr/share/texlive/texmf-dist/tex/latex/url/url.sty +\Urlmuskip=\muskip10 +Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc. +) +LaTeX Info: Redefining \url on input line 5115. +\XeTeXLinkMargin=\dimen104 +\Fld@menulength=\count94 +\Field@Width=\dimen105 +\Fld@charsize=\dimen106 +Package hyperref Info: Hyper figures OFF on input line 6369. +Package hyperref Info: Link nesting OFF on input line 6374. +Package hyperref Info: Hyper index ON on input line 6377. +Package hyperref Info: backreferencing OFF on input line 6384. +Package hyperref Info: Link coloring OFF on input line 6389. +Package hyperref Info: Link coloring with OCG OFF on input line 6394. +Package hyperref Info: PDF/A mode OFF on input line 6399. +LaTeX Info: Redefining \ref on input line 6439. +LaTeX Info: Redefining \pageref on input line 6443. +\Hy@abspage=\count95 +\c@Item=\count96 +\c@Hfootnote=\count97 +) +Package hyperref Info: Driver (autodetected): hpdftex. + +(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def +File: hpdftex.def 2018/02/06 v6.86b Hyperref driver for pdfTeX +\Fld@listcount=\count98 +\c@bookmark@seq@number=\count99 + +(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/rerunfilecheck.sty +Package: rerunfilecheck 2016/05/16 v1.8 Rerun checks for auxiliary files (HO) +Package uniquecounter Info: New unique counter `rerunfilecheck' on input line 2 +82. +) +\Hy@SectionHShift=\skip43 +)) +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty +Package: amsmath 2017/09/02 v2.17a AMS math features +\@mathmargin=\skip44 + +For additional information on amsmath, use the `?' option. +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +Package: amstext 2000/06/29 v2.01 AMS text + +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty +File: amsgen.sty 1999/11/30 v2.0 generic functions +\@emptytoks=\toks15 +\ex@=\dimen107 +)) +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty +Package: amsbsy 1999/11/29 v1.2d Bold Symbols +\pmbraise@=\dimen108 +) +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty +Package: amsopn 2016/03/08 v2.02 operator names +) +\inf@bad=\count100 +LaTeX Info: Redefining \frac on input line 213. +\uproot@=\count101 +\leftroot@=\count102 +LaTeX Info: Redefining \overline on input line 375. +\classnum@=\count103 +\DOTSCASE@=\count104 +LaTeX Info: Redefining \ldots on input line 472. +LaTeX Info: Redefining \dots on input line 475. +LaTeX Info: Redefining \cdots on input line 596. +\Mathstrutbox@=\box27 +\strutbox@=\box28 +\big@size=\dimen109 +LaTeX Font Info: Redeclaring font encoding OML on input line 712. +LaTeX Font Info: Redeclaring font encoding OMS on input line 713. +\macc@depth=\count105 +\c@MaxMatrixCols=\count106 +\dotsspace@=\muskip11 +\c@parentequation=\count107 +\dspbrk@lvl=\count108 +\tag@help=\toks16 +\row@=\count109 +\column@=\count110 +\maxfields@=\count111 +\andhelp@=\toks17 +\eqnshift@=\dimen110 +\alignsep@=\dimen111 +\tagshift@=\dimen112 +\tagwidth@=\dimen113 +\totwidth@=\dimen114 +\lineht@=\dimen115 +\@envbody=\toks18 +\multlinegap=\skip45 +\multlinetaggap=\skip46 +\mathdisplay@stack=\toks19 +LaTeX Info: Redefining \[ on input line 2817. +LaTeX Info: Redefining \] on input line 2818. +) +(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty +Package: graphicx 2017/06/01 v1.1a Enhanced LaTeX Graphics (DPC,SPQR) + +(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty +Package: graphics 2017/06/25 v1.2c Standard LaTeX Graphics (DPC,SPQR) + +(/usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty +Package: trig 2016/01/03 v1.10 sin cos tan (DPC) +) +(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration +) +Package graphics Info: Driver file: pdftex.def on input line 99. + +(/usr/share/texlive/texmf-dist/tex/latex/graphics-def/pdftex.def +File: pdftex.def 2018/01/08 v1.0l Graphics/color driver for pdftex +)) +\Gin@req@height=\dimen116 +\Gin@req@width=\dimen117 +) +No file code.aux. +\openout1 = `code.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 19. +LaTeX Font Info: ... okay on input line 19. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 19. +LaTeX Font Info: ... okay on input line 19. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 19. +LaTeX Font Info: ... okay on input line 19. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 19. +LaTeX Font Info: ... okay on input line 19. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 19. +LaTeX Font Info: ... okay on input line 19. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 19. +LaTeX Font Info: ... okay on input line 19. +LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 19. +LaTeX Font Info: ... okay on input line 19. +\AtBeginShipoutBox=\box29 +Package hyperref Info: Link coloring OFF on input line 19. +(/usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty +Package: nameref 2016/05/21 v2.44 Cross-referencing by name of section + +(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/gettitlestring.sty +Package: gettitlestring 2016/05/16 v1.5 Cleanup title references (HO) +) +\c@section@level=\count112 +) +LaTeX Info: Redefining \ref on input line 19. +LaTeX Info: Redefining \pageref on input line 19. +LaTeX Info: Redefining \nameref on input line 19. +\@outlinefile=\write4 +\openout4 = `code.out'. + + +(/usr/share/texlive/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +\scratchcounter=\count113 +\scratchdimen=\dimen118 +\scratchbox=\box30 +\nofMPsegments=\count114 +\nofMParguments=\count115 +\everyMPshowfont=\toks20 +\MPscratchCnt=\count116 +\MPscratchDim=\dimen119 +\MPnumerator=\count117 +\makeMPintoPDFobject=\count118 +\everyMPtoPDFconversion=\toks21 +) (/usr/share/texlive/texmf-dist/tex/latex/oberdiek/epstopdf-base.sty +Package: epstopdf-base 2016/05/15 v2.6 Base part for package epstopdf + +(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/grfext.sty +Package: grfext 2016/05/16 v1.2 Manage graphics extensions (HO) +) +Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 4 +38. +Package grfext Info: Graphics extension search list: +(grfext) [.pdf,.png,.jpg,.mps,.jpeg,.jbig2,.jb2,.PDF,.PNG,.JPG,.JPE +G,.JBIG2,.JB2,.eps] +(grfext) \AppendGraphicsExtensions on input line 456. + +(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv +e +)) +\tf@toc=\write5 +\openout5 = `code.toc'. + + +[1 + +{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] +LaTeX Font Info: Try loading font information for OMS+cmr on input line 83. + +(/usr/share/texlive/texmf-dist/tex/latex/base/omscmr.fd +File: omscmr.fd 2014/09/29 v2.5h Standard LaTeX font definitions +) +LaTeX Font Info: Font shape `OMS/cmr/m/n' in size <10> not available +(Font) Font shape `OMS/cmsy/m/n' tried instead on input line 83. +LaTeX Font Info: Try loading font information for OMS+cmtt on input line 101 +. + +(/usr/share/texmf/tex/latex/R/tex/latex/omscmtt.fd +File: omscmtt.fd +) +LaTeX Font Info: Font shape `OMS/cmtt/m/n' in size <10> not available +(Font) Font shape `OMS/cmsy/m/n' tried instead on input line 101. + [2] [3] [4] [5] [6] +[7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] +[22] [23] [24] [25] [26] [27] + +LaTeX Warning: Citation `Gail81' on page 28 undefined on input line 1424. + +[28] [29] [30] [31] [32] [33] [34] [35] [36] [37] [38] [39] [40] [41] [42] +[43] [44] [45] [46] [47] [48] [49] [50] [51] [52] [53] [54] [55] [56] [57] +[58] [59] [60] [61] [62] [63] [64] [65] [66] [67] [68] +Overfull \hbox (6.082pt too wide) in paragraph at lines 3521--3530 +[]\OT1/cmr/m/n/10 Finally, the last (some-what bor-ing) part of the code. First +, if given the ar-gu-ment \OT1/cmtt/m/n/10 censor=FALSE + [] + +[69] [70] [71] [72] [73] [74] [75] [76] [77] [78] [79] [80] [81] [82] [83] +[84] [85] [86] [87] [88] [89] [90] [91] [92] [93] [94] [95] [96] [97] [98] +[99] [100] [101] [102] [103] [104] [105] [106] [107] [108] [109] [110] [111] +[112] [113] [114] [115] [116] [117] [118] + +LaTeX Warning: File `figures/balance.pdf' not found on input line 6110. + + +! Package pdftex.def Error: File `figures/balance.pdf' not found: using draft s +etting. + +See the pdftex.def package documentation for explanation. +Type H for immediate help. + ... + +l.6110 \myfig{balance} + +? X + +Here is how much of TeX's memory you used: + 6457 strings out of 494923 + 118551 string characters out of 6180743 + 173289 words of memory out of 5000000 + 9303 multiletter control sequences out of 15000+600000 + 9705 words of font info for 36 fonts, out of 8000000 for 9000 + 14 hyphenation exceptions out of 8191 + 35i,10n,28p,265b,470s stack positions out of 5000i,500n,10000p,200000b,80000s +pdfTeX warning (dest): name{btree2} has been referenced but does not exist, rep +laced by a fixed one + +pdfTeX warning (dest): name{pcoxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}finish1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{pcoxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}terms1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{pcoxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}simple1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{pcoxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}expected21} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{pcoxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}expected22} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{pcoxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}expected1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{pcoxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}getdata3} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{pcoxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}getdata1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{pcoxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}init1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{pcoxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}finish2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{pcoxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}terms2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{pcoxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}simple2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{pcoxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}expected2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{pcoxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}getdata2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{pcoxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}init2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{finegray\\unhbox\040\\voidb@x\040\\kern\040\\z@\040 +\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{ +}{}build1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{finegray\\unhbox\040\\voidb@x\040\\kern\040\\z@\040 +\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{ +}{}censor3} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{finegray\\unhbox\040\\voidb@x\040\\kern\040\\z@\040 +\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{ +}{}censor1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{finegray\\unhbox\040\\voidb@x\040\\kern\040\\z@\040 +\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{ +}{}build2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{finegray\\unhbox\040\\voidb@x\040\\kern\040\\z@\040 +\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{ +}{}censor2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{survfit.coxphms\\unhbox\040\\voidb@x\040\\kern\040\ +\z@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphencha +r\040}{}{}result1} has been referenced but does not exist, replaced by a fixed +one + +pdfTeX warning (dest): name{survfit.coxphms\\unhbox\040\\voidb@x\040\\kern\040\ +\z@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphencha +r\040}{}{}setup3b1} has been referenced but does not exist, replaced by a fixed + one + +pdfTeX warning (dest): name{survfit.coxphms\\unhbox\040\\voidb@x\040\\kern\040\ +\z@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphencha +r\040}{}{}setupa1} has been referenced but does not exist, replaced by a fixed +one + +pdfTeX warning (dest): name{survfit.coxphms\\unhbox\040\\voidb@x\040\\kern\040\ +\z@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphencha +r\040}{}{}result2} has been referenced but does not exist, replaced by a fixed +one + +pdfTeX warning (dest): name{survfit.coxphms\\unhbox\040\\voidb@x\040\\kern\040\ +\z@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphencha +r\040}{}{}setup3b2} has been referenced but does not exist, replaced by a fixed + one + +pdfTeX warning (dest): name{survfit.coxphms\\unhbox\040\\voidb@x\040\\kern\040\ +\z@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphencha +r\040}{}{}setupa2} has been referenced but does not exist, replaced by a fixed +one + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}compute3} has been referenced but does not exist, replaced by a fixed o +ne + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}compute1} has been referenced but does not exist, replaced by a fixed o +ne + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}unlist1} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}unlist2} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}compute2} has been referenced but does not exist, replaced by a fixed o +ne + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}finish1} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{newstrata\\unhbox\040\\voidb@x\040\\kern\040\\z@\04 +0\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040} +{}{}fixup1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{newstrata\\unhbox\040\\voidb@x\040\\kern\040\\z@\04 +0\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040} +{}{}fixup2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}result1} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup34} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}newdata23} has been referenced but does not exist, replaced by a fixed +one + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}newdata21} has been referenced but does not exist, replaced by a fixed +one + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}newdata22} has been referenced but does not exist, replaced by a fixed +one + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup33} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup31} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup2c3} has been referenced but does not exist, replaced by a fixed o +ne + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup2c1} has been referenced but does not exist, replaced by a fixed o +ne + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup2b1} has been referenced but does not exist, replaced by a fixed o +ne + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup23} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup21} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup15} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup14} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup13} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup11} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}finish2} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}result2} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup32} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup2c2} has been referenced but does not exist, replaced by a fixed o +ne + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup2b2} has been referenced but does not exist, replaced by a fixed o +ne + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup22} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{survfit.coxph\\unhbox\040\\voidb@x\040\\kern\040\\z +@\040\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\ +040}{}{}setup12} has been referenced but does not exist, replaced by a fixed on +e + +pdfTeX warning (dest): name{agfit4\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}finish1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{agfit4\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}addup3} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{agfit4\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}addup1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{agfit4\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}iter1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{agreg\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +remove1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{breslow\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\ +\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{} +{}efron1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{breslow\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\ +\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{} +{}efron2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{agreg\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +remove2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{agfit4\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}addup2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{agfit4\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}finish2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{agfit4\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\ +char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{ +}iter2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{agreg\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +finish1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{agreg\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +fixup1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{agreg\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +finish2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{agreg\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +fixup2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +finish4} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +finish3} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +finish1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +iter1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +finish2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +addup3} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +addup1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +iter01} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +addup2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +strata1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +setup1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +iter2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +iter02} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +strata2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +setup2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +recur3} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +recur1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{excox\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +recur2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +finish3} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +finish1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +compute1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +penal1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +zeroevent1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +zeroevent2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +setup1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +make\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\char\040`\\protect\040\\discre +tionary\040{\\char\040\\defaulthyphenchar\040}{}{}X3} has been referenced but d +oes not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +make\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\char\040`\\protect\040\\discre +tionary\040{\\char\040\\defaulthyphenchar\040}{}{}X1} has been referenced but d +oes not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxcount\\unhbox\040\\voidb@x\040\\kern\040\\z@\040 +\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{ +}{}list\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\char\040`\\protect\040\\dis +cretionary\040{\\char\040\\defaulthyphenchar\040}{}{}return3} has been referenc +ed but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxcount\\unhbox\040\\voidb@x\040\\kern\040\\z@\040 +\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{ +}{}list\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\char\040`\\protect\040\\dis +cretionary\040{\\char\040\\defaulthyphenchar\040}{}{}return1} has been referenc +ed but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxcount\\unhbox\040\\voidb@x\040\\kern\040\\z@\040 +\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{ +}{}alloc\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\char\040`\\protect\040\\di +scretionary\040{\\char\040\\defaulthyphenchar\040}{}{}memory3} has been referen +ced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxcount\\unhbox\040\\voidb@x\040\\kern\040\\z@\040 +\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{ +}{}alloc\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\char\040`\\protect\040\\di +scretionary\040{\\char\040\\defaulthyphenchar\040}{}{}memory1} has been referen +ced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxcount\\unhbox\040\\voidb@x\040\\kern\040\\z@\040 +\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{ +}{}list\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\char\040`\\protect\040\\dis +cretionary\040{\\char\040\\defaulthyphenchar\040}{}{}return2} has been referenc +ed but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxcount\\unhbox\040\\voidb@x\040\\kern\040\\z@\040 +\\char\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{ +}{}alloc\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\char\040`\\protect\040\\di +scretionary\040{\\char\040\\defaulthyphenchar\040}{}{}memory2} has been referen +ced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +transform4} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +transform3} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +transform1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +bothsides1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +multi\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\char\040`\\protect\040\\discr +etionary\040{\\char\040\\defaulthyphenchar\040}{}{}X4} has been referenced but +does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +multi\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\char\040`\\protect\040\\discr +etionary\040{\\char\040\\defaulthyphenchar\040}{}{}X3} has been referenced but +does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +multi\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\char\040`\\protect\040\\discr +etionary\040{\\char\040\\defaulthyphenchar\040}{}{}X1} has been referenced but +does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +missing1} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +missing2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +multiform21} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +multiform11} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +finish2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +compute2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +penal2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +multi\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\char\040`\\protect\040\\discr +etionary\040{\\char\040\\defaulthyphenchar\040}{}{}X2} has been referenced but +does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +setup2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +make\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\char\040`\\protect\040\\discre +tionary\040{\\char\040\\defaulthyphenchar\040}{}{}X2} has been referenced but d +oes not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +multiform22} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +transform2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +bothsides2} has been referenced but does not exist, replaced by a fixed one + +pdfTeX warning (dest): name{coxph\\unhbox\040\\voidb@x\040\\kern\040\\z@\040\\c +har\040`\\protect\040\\discretionary\040{\\char\040\\defaulthyphenchar\040}{}{} +multiform12} has been referenced but does not exist, replaced by a fixed one + +< +/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb> +Output written on code.pdf (118 pages, 408326 bytes). +PDF statistics: + 1148 PDF objects out of 1200 (max. 8388607) + 1001 compressed objects within 11 object streams + 431 named destinations out of 1000 (max. 500000) + 1 words of extra memory for PDF output out of 10000 (max. 10000000) + diff --git a/noweb/code.nw b/noweb/code.nw new file mode 100644 index 00000000..3e82fe31 --- /dev/null +++ b/noweb/code.nw @@ -0,0 +1,17011 @@ +\documentclass{article} +\usepackage{noweb} +\usepackage{amsmath} +\usepackage{fancyvrb} +\usepackage{graphicx} +\addtolength{\textwidth}{1in} +\addtolength{\oddsidemargin}{-.5in} +\setlength{\evensidemargin}{\oddsidemargin} + +\newcommand{\myfig}[1]{\includegraphics[width=\textwidth]{figures/#1.pdf}} +\newcommand{\code}[1]{\texttt{#1}} +\newcommand{\xbar}{\overline{x}} +\newcommand{\sign}{{\rm sign}} + +\noweboptions{breakcode} +\title{Survival Package Functions} +\author{Terry Therneau} + +\begin{document} +\maketitle +\tableofcontents + +\section{Introduction} + +\begin{quotation} +Let us change or traditional attitude to the construction of programs. +Instead of imagining that our main task is to instruct a \emph{computer} +what to do, let us concentrate rather on explaining to \emph{humans} +what we want the computer to do. (Donald E. Knuth, 1984). +\end{quotation} + +This is the definition of a coding style called +\emph{literate programming}. +I first made use of it in the \emph{coxme} library and have become a full +convert. For the survival library only selected objects are documented in +this way; as I make updates and changes I am slowly converting the source +code. +The first motivation for this is to make the code easier for me, both to +create and to maintain. As to maintinance, I have found that whenver I +need to update code I spend a lot of time in the ``what was I doing in these +x lines?'' stage. The code never has enough documentation, even for the +author. (The survival library is already better than the majority of packages +in R, whose comment level is abysmal. +In the pre-noweb source code about 1 line in 6 +has a comment, for the noweb document the documentation/code ratio is 2:1.) +I also find it helps in creating new code to have the real documentation of +intent --- formulas with integrals and such --- closely integrated. +The second motivation is to leave code that is well enough explained that +someone else can take it over. + +The source code is structured using \emph{noweb}, one of the simpler literate +programming environments. +The source code files look remakably like Sweave, and the .Rnw mode of +emacs works perfectly for them. This is not too surprising since Sweave +was also based on noweb. Sweave is not sufficient to process the files, +however, since it has a different intention: it is designed to +\emph{execute} the code and make the results into a report, while noweb +is designed to \emph{explain} the code. We do this using the \code{noweb} +library in R, which contains the \code{noweave} and \code{notangle} functions. +(It would in theory be fairly simple to extend \code{knitr} to do this task, +which is a topic for further exploration one day. A downside to noweb is +that like Sweave it depends on latex, which has an admittedly steep learning +curve, and markdown is thus attractive.) + + +\section{Cox Models} +\subsection{Coxph} +The [[coxph]] routine is the underlying basis for all the models. +The source was converted to noweb when adding time-transform terms. + +The call starts out with the basic building of a model frame +and proceeds from there. +The aeqSurv function is used to adjucate near ties in the time +variable, numerical precision issues that occur when users base +caculations on days/365.25 instead of days. + +A cluster term in the model is an exception. The variable mentioned is +never part of the formal model, and so it is not kept as part of the saved +terms structure. + +The analysis for multi-state data is a bit more complex. +\begin{itemize} + \item If the formula statement is a list, we preprocess this to find out + any potential extra variables, and create a new global formula which + will be used to create the data frame. + \item In the above case missing value processing needs + to be deferred, since some covariates may apply only to select + transitions. + \item After the data frame is constructed, the transitions matrix can be + used to check that all the state names actually exist, construct the + cmap matrix, and do missing value removal. +\end{itemize} + +<>= +#tt <- function(x) x +coxph <- function(formula, data, weights, subset, na.action, + init, control, ties= c("efron", "breslow", "exact"), + singular.ok =TRUE, robust, + model=FALSE, x=FALSE, y=TRUE, tt, method=ties, + id, cluster, istate, statedata, nocenter=c(-1, 0, 1), ...) { + + ties <- match.arg(ties) + Call <- match.call() + ## We want to pass any ... args to coxph.control, but not pass things + ## like "dats=mydata" where someone just made a typo. The use of ... + ## is simply to allow things like "eps=1e6" with easier typing + extraArgs <- list(...) + if (length(extraArgs)) { + controlargs <- names(formals(coxph.control)) #legal arg names + indx <- pmatch(names(extraArgs), controlargs, nomatch=0L) + if (any(indx==0L)) + stop(gettextf("Argument %s not matched", + names(extraArgs)[indx==0L]), domain = NA) + } + if (missing(control)) control <- coxph.control(...) + + # Move any cluster() term out of the formula, and make it an argument + # instead. This makes everything easier. But, I can only do that with + # a local copy, doing otherwise messes up future use of update() on + # the model object for a user stuck in "+ cluster()" mode. + if (missing(formula)) stop("a formula argument is required") + + ss <- c("cluster", "offset") + if (is.list(formula)) + Terms <- if (missing(data)) terms(formula[[1]], specials=ss) else + terms(formula[[1]], specials=ss, data=data) + else Terms <- if (missing(data)) terms(formula, specials=ss) else + terms(formula, specials=ss, data=data) + attr(Terms,'term.labels') = gsub('\n',' ', attr(Terms,'term.labels')) + colnames(attr(Terms,'factors')) = gsub('\n',' ', colnames(attr(Terms,'factors'))) + rownames(attr(Terms,'factors')) = gsub('\n',' ', rownames(attr(Terms,'factors'))) + + tcl <- attr(Terms, 'specials')$cluster + if (length(tcl) > 1) stop("a formula cannot have multiple cluster terms") + + if (length(tcl) > 0) { # there is one + # subscripting of formulas is broken at least through R 3.5, if the + # formula contains an offset. Adding offset to the "specials" above + # is just a sneaky way to find out if one is present, then call + # reformulate ourselves. tt is a correct index into the row labels + # of the factors attribute, tt+1 to the variables attribute (which is + # a list, so you have to skip the "list" call). The term.labels attr + # contains neither the response nor the offset, but does contain the + # interactions, which we need. + factors <- attr(Terms, 'factors') + if (any(factors[tcl,] >1)) stop("cluster() cannot be in an interaction") + if (attr(Terms, "response") ==0) + stop("formula must have a Surv response") + # reformulate with the response option puts ` ` around Surv, which messes + # up evaluation, hence the fancy dance to replace a piece rather + # than recreate + temp <- attr(Terms, "term.labels") + oo <- attr(Terms, 'specials')$offset + if (!is.null(oo)) { + # add the offset to the set of labels + ooterm <- rownames(factors)[oo] + if (oo < tcl) temp <- c(ooterm, temp) + else temp <- c(temp, ooterm) + } + if (is.null(Call$cluster)) + Call$cluster <- attr(Terms, "variables")[[1+tcl]][[2]] + else warning("cluster appears both in a formula and as an argument, formula term ignored") + if (is.list(formula)) + formula[[1]][[3]] <- reformulate(temp[1-tcl])[[2]] + else formula[[3]] <- reformulate(temp[1-tcl])[[2]] + + Call$formula <- formula + + } + + # create a call to model.frame() that contains the formula (required) + # and any other of the relevant optional arguments + # but don't evaluate it just yet + indx <- match(c("formula", "data", "weights", "subset", "na.action", + "cluster", "id", "istate"), + names(Call), nomatch=0) + if (indx[1] ==0) stop("A formula argument is required") + tform <- Call[c(1,indx)] # only keep the arguments we wanted + tform[[1L]] <- quote(stats::model.frame) # change the function called + + # if the formula is a list, do the first level of processing on it. + if (is.list(formula)) { + <> + } + else { + multiform <- FALSE # formula is not a list of expressions + covlist <- NULL + dformula <- formula + } + + # add specials to the formula + special <- c("strata", "tt", "frailty", "ridge", "pspline") + tform$formula <- if(missing(data)) terms(formula, special) else + terms(formula, special, data=data) + + # Make "tt" visible for coxph formulas, without making it visible elsewhere + if (!is.null(attr(tform$formula, "specials")$tt)) { + coxenv <- new.env(parent= environment(formula)) + assign("tt", function(x) x, envir=coxenv) + environment(tform$formula) <- coxenv + } + + # okay, now evaluate the formula + mf <- eval(tform, parent.frame()) + Terms <- terms(mf) + attr(Terms,'term.labels') = gsub('\n',' ', attr(Terms,'term.labels')) + colnames(attr(Terms,'factors')) = gsub('\n',' ', colnames(attr(Terms,'factors'))) + rownames(attr(Terms,'factors')) = gsub('\n',' ', rownames(attr(Terms,'factors'))) + + # Grab the response variable, and deal with Surv2 objects + n <- nrow(mf) + Y <- model.response(mf) + isSurv2 <- inherits(Y, "Surv2") + if (isSurv2) { + # this is Surv2 style data + # if there were any obs removed due to missing, remake the model frame + if (length(attr(mf, "na.action"))) { + tform$na.action <- na.pass + mf <- eval.parent(tform) + } + if (!is.null(attr(Terms, "specials")$cluster)) + stop("cluster() cannot appear in the model statement") + new <- surv2data(mf) + mf <- new$mf + istate <- new$istate + id <- new$id + Y <- new$y + n <- nrow(mf) + } + else { + if (!is.Surv(Y)) stop("Response must be a survival object") + id <- model.extract(mf, "id") + istate <- model.extract(mf, "istate") + } + if (n==0) stop("No (non-missing) observations") + + type <- attr(Y, "type") + multi <- FALSE + if (type=="mright" || type == "mcounting") multi <- TRUE + else if (type!='right' && type!='counting') + stop(paste("Cox model doesn't support \"", type, + "\" survival data", sep='')) + data.n <- nrow(Y) #remember this before any time transforms + + if (!multi && multiform) + stop("formula is a list but the response is not multi-state") + if (multi && length(attr(Terms, "specials")$frailty) >0) + stop("multi-state models do not currently support frailty terms") + if (multi && length(attr(Terms, "specials")$pspline) >0) + stop("multi-state models do not currently support pspline terms") + if (multi && length(attr(Terms, "specials")$ridge) >0) + stop("multi-state models do not currently support ridge penalties") + + if (control$timefix) Y <- aeqSurv(Y) + <> + + # The time transform will expand the data frame mf. To do this + # it needs Y and the strata. Everything else (cluster, offset, weights) + # should be extracted after the transform + # + strats <- attr(Terms, "specials")$strata + hasinteractions <- FALSE + dropterms <- NULL + if (length(strats)) { + stemp <- untangle.specials(Terms, 'strata', 1) + if (length(stemp$vars)==1) strata.keep <- mf[[stemp$vars]] + else strata.keep <- strata(mf[,stemp$vars], shortlabel=TRUE) + istrat <- as.integer(strata.keep) + + for (i in stemp$vars) { #multiple strata terms are allowed + # The factors attr has one row for each variable in the frame, one + # col for each term in the model. Pick rows for each strata + # var, and find if it participates in any interactions. + if (any(attr(Terms, 'order')[attr(Terms, "factors")[i,] >0] >1)) + hasinteractions <- TRUE + } + if (!hasinteractions) dropterms <- stemp$terms + } else istrat <- NULL + + if (hasinteractions && multi) + stop("multi-state coxph does not support strata*covariate interactions") + + + timetrans <- attr(Terms, "specials")$tt + if (missing(tt)) tt <- NULL + if (length(timetrans)) { + if (multi || isSurv2) stop("the tt() transform is not implemented for multi-state or Surv2 models") + <> + } + + xlevels <- .getXlevels(Terms, mf) + + # grab the cluster, if present. Using cluster() in a formula is no + # longer encouraged + cluster <- model.extract(mf, "cluster") + weights <- model.weights(mf) + # The user can call with cluster, id, robust, or any combination + # Default for robust: if cluster or any id with > 1 event or + # any weights that are not 0 or 1, then TRUE + # If only id, treat it as the cluster too + has.cluster <- !(missing(cluster) || length(cluster)==0) + has.id <- !(missing(id) || length(id)==0) + has.rwt<- (!is.null(weights) && any(weights != floor(weights))) + #has.rwt<- FALSE # we are rethinking this + has.robust <- (!missing(robust) && !is.null(robust)) # arg present + if (has.id) id <- as.factor(id) + + if (missing(robust) || is.null(robust)) { + if (has.cluster || has.rwt || + (has.id && (multi || anyDuplicated(id[Y[,ncol(Y)]==1])))) + robust <- TRUE else robust <- FALSE + } + if (!is.logical(robust)) stop("robust must be TRUE/FALSE") + + if (has.cluster) { + if (!robust) { + warning("cluster specified with robust=FALSE, cluster ignored") + ncluster <- 0 + clname <- NULL + } + else { + if (is.factor(cluster)) { + clname <- levels(cluster) + cluster <- as.integer(cluster) + } else { + clname <- sort(unique(cluster)) + cluster <- match(cluster, clname) + } + ncluster <- length(clname) + } + } else { + if (robust && has.id) { + # treat the id as both identifier and clustering + clname <- levels(id) + cluster <- as.integer(id) + ncluster <- length(clname) + } + else { + ncluster <- 0 # has neither + } + } + + # if the user said "robust", (time1,time2) data, and no cluster or + # id, complain about it + if (robust && is.null(cluster)) { + if (ncol(Y) ==2 || !has.robust) cluster <- seq.int(1, nrow(mf)) + else stop("one of cluster or id is needed") + } + + contrast.arg <- NULL #due to shared code with model.matrix.coxph + attr(Terms, "intercept") <- 1 # always have a baseline hazard + + if (multi) { + <> + } + + <> + <> + if (multi) { + <> + } + + # infinite covariates are not screened out by the na.omit routines + # But this needs to be done after the multi-X part + if (!all(is.finite(X))) + stop("data contains an infinite predictor") + + + # init is checked after the final X matrix has been made + if (missing(init)) init <- NULL + else { + if (length(init) != ncol(X)) stop("wrong length for init argument") + temp <- X %*% init - sum(colMeans(X) * init) + offset + # it's okay to have a few underflows, but if all of them are too + # small we get all zeros + if (any(exp(temp) > .Machine$double.xmax) || all(exp(temp)==0)) + stop("initial values lead to overflow or underflow of the exp function") + } + + <> + <> + <> + } +@ + + +Multi-state models have a multi-state response, optionally they have a +formula that is a list. +If the formula is a list then the first element is the default formula +with a survival response and covariates on the right. +Further elements are of the form from/to ~ covariates / options and +specify other covariates for all from:to transitions. +Steps in processing such a formula are +\begin{enumerate} + \item Gather all the variables that appear on a right-hand side, and + create a master formula y ~ all of them. This is used to create the + model.frame. We also need to defer missing value processing, since + some covariates might appear for only some transitions. + \item Get the data. The response, id, and statedata variables can now + be checked for consistency with the formulas. + \item After X has been formed, expand it. +\end{enumerate} +Here is code for the first step. + +<>= +multiform <- TRUE +dformula <- formula[[1]] # the default formula for transitions +if (missing(statedata)) covlist <- parsecovar1(formula[-1]) +else { + if (!inherits(statedata, "data.frame")) + stop("statedata must be a data frame") + if (is.null(statedata$state)) + stop("statedata data frame must contain a 'state' variable") + covlist <- parsecovar1(formula[-1], names(statedata)) +} + +# create the master formula, used for model.frame +# the term.labels + reformulate + environment trio is used in [.terms; +# if it's good enough for base R it's good enough for me +tlab <- unlist(lapply(covlist$rhs, function(x) + attr(terms.formula(x$formula), "term.labels"))) +tlab <- c(attr(terms.formula(dformula), "term.labels"), tlab) +newform <- reformulate(tlab, dformula[[2]]) +environment(newform) <- environment(dformula) +formula <- newform +tform$na.action <- na.pass # defer any missing value work to later +@ + +<>= +# check for consistency of the states, and create a transition +# matrix +if (length(id)==0) + stop("an id statement is required for multi-state models") + +mcheck <- survcheck2(Y, id, istate) +# error messages here +if (mcheck$flag["overlap"] > 0) + stop("data set has overlapping intervals for one or more subjects") + +transitions <- mcheck$transitions +istate <- mcheck$istate +states <- mcheck$states + +# build tmap, which has one row per term, one column per transition +if (missing(statedata)) + covlist2 <- parsecovar2(covlist, NULL, dformula= dformula, + Terms, transitions, states) +else covlist2 <- parsecovar2(covlist, statedata, dformula= dformula, + Terms, transitions, states) +tmap <- covlist2$tmap +if (!is.null(covlist)) { + <> +} +@ + +For multi-state models we can't tell what observations should be removed until +any extra formulas have been processed. +There may be rows that are missing \emph{some} of the covariates but +are okay for \emph{some} transitions. Others could be useless. +Those rows can be removed from the model frame before creating the X matrix. +Also identify partially used rows, ones where the necessary covariates are +present for some of the possible transitions but not all. +Those obs are dealt with later by the stacker function. +<>= +# first vector will be true if there is at least 1 transition for which all +# covariates are present, second if there is at least 1 for which some are not +good.tran <- bad.tran <- rep(FALSE, nrow(Y)) +# We don't need to check interaction terms +termname <- rownames(attr(Terms, 'factors')) +trow <- (!is.na(match(rownames(tmap), termname))) + +# create a missing indicator for each term +termiss <- matrix(0L, nrow(mf), ncol(mf)) +for (i in 1:ncol(mf)) { + xx <- is.na(mf[[i]]) + if (is.matrix(xx)) termiss[,i] <- apply(xx, 1, any) + else termiss[,i] <- xx +} + +for (i in levels(istate)) { + rindex <- which(istate ==i) + j <- which(covlist2$mapid[,1] == match(i, states)) #possible transitions + for (jcol in j) { + k <- which(trow & tmap[,jcol] > 0) # the terms involved in that + bad.tran[rindex] <- (bad.tran[rindex] | + apply(termiss[rindex, k, drop=FALSE], 1, any)) + good.tran[rindex] <- (good.tran[rindex] | + apply(!termiss[rindex, k, drop=FALSE], 1, all)) + } +} +n.partially.used <- sum(good.tran & bad.tran & !is.na(Y)) +omit <- (!good.tran & bad.tran) | is.na(Y) +if (all(omit)) stop("all observations deleted due to missing values") +temp <- setNames(seq(omit)[omit], attr(mf, "row.names")[omit]) +attr(temp, "class") <- "omit" +mf <- mf[!omit,, drop=FALSE] +attr(mf, "na.action") <- temp +Y <- Y[!omit] +id <- id[!omit] +if (length(istate)) istate <- istate[!omit] # istate can be NULL +@ + +For a multi-state model, create the expanded X matrix. Sometimes it is +much expanded. +The first step is to create the cmap matrix from tmap by expanding terms; +factors turn into multiple columns for instance. +If tmap has rows (terms) for strata, then we have to deal with the complication +that a strata might be applied to some transitions and not to others. +<>= +if (length(strats) >0) { + stratum_map <- tmap[c(1L, strats),] # strats includes Y, + tmap has an extra row + stratum_map[-1,] <- ifelse(stratum_map[-1,] >0, 1L, 0L) + if (nrow(stratum_map) > 2) { + temp <- stratum_map[-1,] + if (!all(apply(temp, 2, function(x) all(x==0) || all(x==1)))) { + # the hard case: some transitions use one strata variable, some + # transitions use another. We need to keep them separate + strata.keep <- mf[,strats] # this will be a data frame + istrat <- sapply(strata.keep, as.numeric) + } + } +} +else stratum_map <- tmap[1,,drop=FALSE] +@ + +Also create the initial values vector. + +The stacker function will create a separate block of observations for every +unique value in \code{stratum\_map}. +Now say that two transitions A:B and A:C share the same baseline hazard. +Then either a B or a C outcome will be an ``event'' in that stratum; they +would only be distinguished by perhaps having different covariates. +The first thing we do with the result is to rebuild the transitions matrix: +the working version was created before removing missings and can +seriously overstate the number of transitions available. +Then set up the data. + +<>= +cmap <- parsecovar3(tmap, colnames(X), attr(X, "assign"), covlist2$phbaseline) +xstack <- stacker(cmap, stratum_map, as.integer(istate), X, Y, strata=istrat, + states=states) + +rkeep <- unique(xstack$rindex) +transitions <- survcheck2(Y[rkeep,], id[rkeep], istate[rkeep])$transitions + +X <- xstack$X +Y <- xstack$Y +istrat <- xstack$strata +if (length(offset)) offset <- offset[xstack$rindex] +if (length(weights)) weights <- weights[xstack$rindex] +if (length(cluster)) cluster <- cluster[xstack$rindex] +@ + +The next step for multi X is to remake the assign attribute. +It is a list with one element per term, and needs to be expanded in the +same way as \code{tmap}, which has one row per term (+ an intercept row). +For \code{predict, type='terms'} to work, no label can be repeated in the +final assign object. +If a variable `fred' were common across all the states we would want to +use that as the label, but if it appears twice, as separate terms for +two different transitions, then we label it as fred\_x:y where x:y is the +transition. +<>= +t2 <- tmap[-c(1, strats),,drop=FALSE] # remove the intercept row and strata rows +r2 <- row(t2)[!duplicated(as.vector(t2)) & t2 !=0] +c2 <- col(t2)[!duplicated(as.vector(t2)) & t2 !=0] +a2 <- lapply(seq(along.with=r2), function(i) {cmap[assign[[r2[i]]], c2[i]]}) +# which elements are unique? +tab <- table(r2) +count <- tab[r2] +names(a2) <- ifelse(count==1, row.names(t2)[r2], + paste(row.names(t2)[r2], colnames(cmap)[c2], sep="_")) +assign <- a2 +@ + +An increasingly common error is for users to put the time variable on +both sides of the formula, in the mistaken idea that this will +deal with a failure of proportional hazards. +Add a test for such models, but don't bail out. There will be cases where +someone has the the stop variable in an expression on the right hand side, +to create current age say. +The \code{variables} attribute of the Terms object is the expression form +of a list that contains the response variable followed by the predictors. +Subscripting this, element 1 is the call to ``list'' itself so we always +retain it. My \code{terms.inner} function works only with formula +objects. +<>= +if (length(attr(Terms, 'variables')) > 2) { # a ~1 formula has length 2 + ytemp <- terms.inner(formula[1:2]) + suppressWarnings(z <- as.numeric(ytemp)) # are any of the elements numeric? + ytemp <- ytemp[is.na(z)] # toss numerics, e.g. Surv(t, 1-s) + xtemp <- terms.inner(formula[-2]) + if (any(!is.na(match(xtemp, ytemp)))) + warning("a variable appears on both the left and right sides of the formula") +} +@ + +At this point we deal with any time transforms. +The model frame is expanded to a ``fake'' data set that has a +separate stratum for each unique event-time/strata combination, +and any tt() terms in the formula are processed. +The first step is to create the index vector [[tindex]] and +new strata [[.strata.]]. This last is included in a model.frame call +(for others to use), internally the code simply replaces the \code{istrat} +variable. +A (modestly) fast C-routine first counts up and indexes the observations. +We start out with error checks; since the computation can be slow we want +to complain early. +<>= +timetrans <- untangle.specials(Terms, 'tt') +ntrans <- length(timetrans$terms) + +if (is.null(tt)) { + tt <- function(x, time, riskset, weights){ #default to O'Brien's logit rank + obrien <- function(x) { + r <- rank(x) + (r-.5)/(.5+length(r)-r) + } + unlist(tapply(x, riskset, obrien)) + } +} +if (is.function(tt)) tt <- list(tt) #single function becomes a list + +if (is.list(tt)) { + if (any(!sapply(tt, is.function))) + stop("The tt argument must contain function or list of functions") + if (length(tt) != ntrans) { + if (length(tt) ==1) { + temp <- vector("list", ntrans) + for (i in 1:ntrans) temp[[i]] <- tt[[1]] + tt <- temp + } + else stop("Wrong length for tt argument") + } +} +else stop("The tt argument must contain a function or list of functions") + +if (ncol(Y)==2) { + if (length(strats)==0) { + sorted <- order(-Y[,1], Y[,2]) + newstrat <- rep.int(0L, nrow(Y)) + newstrat[1] <- 1L + } + else { + sorted <- order(istrat, -Y[,1], Y[,2]) + #newstrat marks the first obs of each strata + newstrat <- as.integer(c(1, 1*(diff(istrat[sorted])!=0))) + } + if (storage.mode(Y) != "double") storage.mode(Y) <- "double" + counts <- .Call(Ccoxcount1, Y[sorted,], + as.integer(newstrat)) + tindex <- sorted[counts$index] +} +else { + if (length(strats)==0) { + sort.end <- order(-Y[,2], Y[,3]) + sort.start<- order(-Y[,1]) + newstrat <- c(1L, rep(0, nrow(Y) -1)) + } + else { + sort.end <- order(istrat, -Y[,2], Y[,3]) + sort.start<- order(istrat, -Y[,1]) + newstrat <- c(1L, as.integer(diff(istrat[sort.end])!=0)) + } + if (storage.mode(Y) != "double") storage.mode(Y) <- "double" + counts <- .Call(Ccoxcount2, Y, + as.integer(sort.start -1L), + as.integer(sort.end -1L), + as.integer(newstrat)) + tindex <- counts$index +} +@ + +The C routine has returned a list with 4 elements +\begin{description} + \item[nrisk] a vector containing the number at risk at each event time + \item[time] the vector of event times + \item[status] a vector of status values + \item[index] a vector containing the set of subjects at risk for event time + 1, followed by those at risk at event time 2, those at risk at event time 3, + etc. +\end{description} + +The new data frame is then a simple creation. +The subtle part below is a desire to retain transformation information +so that a downstream call to \code{termplot} will work. +The tt function supplied by the user often finishes with a call to +\code{pspline} or \code{ns}. If the returned value of the \code{tt} +call has a class for which a \code{makepredictcall} method exists then +we need to do 2 things: +\begin{enumerate} + \item Construct a fake call, e.g., ``pspline(age)'', then feed it and + the result of tt as arguments to \code{makepredictcall} + \item Replace that componenent in the predvars attribute of the terms. +\end{enumerate} +The \code{timetrans\$terms} value is a count of the right hand side of +the formula. Some objects in the terms structure are unevaluated calls +that include y, this adds 2 to the count (the call to ``list'' and +the response). + +<>= +Y <- Surv(rep(counts$time, counts$nrisk), counts$status) +type <- 'right' # new Y is right censored, even if the old was (start, stop] + +mf <- mf[tindex,] +istrat <- rep(1:length(counts$nrisk), counts$nrisk) +weights <- model.weights(mf) +if (!is.null(weights) && any(!is.finite(weights))) + stop("weights must be finite") + +tcall <- attr(Terms, 'variables')[timetrans$terms+2] +pvars <- attr(Terms, 'predvars') +pmethod <- sub("makepredictcall.", "", as.vector(methods("makepredictcall"))) +for (i in 1:ntrans) { + newtt <- (tt[[i]])(mf[[timetrans$var[i]]], Y[,1], istrat, weights) + mf[[timetrans$var[i]]] <- newtt + nclass <- class(newtt) + if (any(nclass %in% pmethod)) { # It has a makepredictcall method + dummy <- as.call(list(as.name(class(newtt)[1]), tcall[[i]][[2]])) + ptemp <- makepredictcall(newtt, dummy) + pvars[[timetrans$terms[i]+2]] <- ptemp + } +} +attr(Terms, "predvars") <- pvars +@ + +This is the C code for time-transformation. +For the first case it expects y to contain time and status sorted from +longest time to shortest, and strata=1 for the first observation of +each strata. +<>= +#include "survS.h" +/* +** Count up risk sets and identify who is in each +*/ +SEXP coxcount1(SEXP y2, SEXP strat2) { + int ntime, nrow; + int i, j, n; + int stratastart=0; /* start row for this strata */ + int nrisk=0; /* number at risk (=0 to stop -Wall complaint)*/ + double *time, *status; + int *strata; + double dtime; + SEXP rlist, rlistnames, rtime, rn, rindex, rstatus; + int *rrindex, *rrstatus; + + n = nrows(y2); + time = REAL(y2); + status = time +n; + strata = INTEGER(strat2); + + /* + ** First pass: count the total number of death times (risk sets) + ** and the total number of rows in the new data set. + */ + ntime=0; nrow=0; + for (i=0; i> + + /* + ** Pass 2, fill them in + */ + ntime=0; + for (i=0; i> +} +@ + +The start-stop case is a bit more work. +The set of subjects still at risk is an arbitrary set so we have to +keep an index vector [[atrisk]]. +At each new death time we write out the set of those at risk, with the +deaths last. +I toyed with the idea of a binary tree then realized it was not useful: +at each death we need to list out all the subjects at risk into the index +vector which is an $O(n)$ process, tree or not. +<>= +#include "survS.h" +/* count up risk sets and identify who is in each, (start,stop] version */ +SEXP coxcount2(SEXP y2, SEXP isort1, SEXP isort2, SEXP strat2) { + int ntime, nrow; + int i, j, istart, n; + int nrisk=0, *atrisk; + double *time1, *time2, *status; + int *strata; + double dtime; + int iptr, jptr; + + SEXP rlist, rlistnames, rtime, rn, rindex, rstatus; + int *rrindex, *rrstatus; + int *sort1, *sort2; + + n = nrows(y2); + time1 = REAL(y2); + time2 = time1+n; + status = time2 +n; + strata = INTEGER(strat2); + sort1 = INTEGER(isort1); + sort2 = INTEGER(isort2); + + /* + ** First pass: count the total number of death times (risk sets) + ** and the total number of rows in the new data set + */ + ntime=0; nrow=0; + istart =0; /* walks along the sort1 vector (start times) */ + for (i=0; i= dtime; istart++) + nrisk--; + for(j= i+1; j> + atrisk = (int *)R_alloc(n, sizeof(int)); /* marks who is at risk */ + + /* + ** Pass 2, fill them in + */ + ntime=0; nrisk=0; + j=0; /* pointer to time1 */; + istart=0; + for (i=0; i=dtime; istart++) { + atrisk[sort1[istart]]=0; + nrisk--; + } + for (j=1; j> +} +@ + +<>= +/* +** Allocate memory +*/ +PROTECT(rtime = allocVector(REALSXP, ntime)); +PROTECT(rn = allocVector(INTSXP, ntime)); +PROTECT(rindex=allocVector(INTSXP, nrow)); +PROTECT(rstatus=allocVector(INTSXP,nrow)); +rrindex = INTEGER(rindex); +rrstatus= INTEGER(rstatus); +@ + +<>= +/* return the list */ +PROTECT(rlist = allocVector(VECSXP, 4)); +SET_VECTOR_ELT(rlist, 0, rn); +SET_VECTOR_ELT(rlist, 1, rtime); +SET_VECTOR_ELT(rlist, 2, rindex); +SET_VECTOR_ELT(rlist, 3, rstatus); +PROTECT(rlistnames = allocVector(STRSXP, 4)); +SET_STRING_ELT(rlistnames, 0, mkChar("nrisk")); +SET_STRING_ELT(rlistnames, 1, mkChar("time")); +SET_STRING_ELT(rlistnames, 2, mkChar("index")); +SET_STRING_ELT(rlistnames, 3, mkChar("status")); +setAttrib(rlist, R_NamesSymbol, rlistnames); + +unprotect(6); +return(rlist); +@ + +We now return to the original thread of the program, though perhaps +with new data, and build the $X$ matrix. +Creation of the $X$ matrix for a Cox model requires just a bit of +trickery. +The baseline hazard for a Cox model plays the role of an intercept, +but does not appear in the $X$ matrix. +However, to create the columns of $X$ for factor variables correctly, +we need to call the model.matrix routine in such a way that it \emph{thinks} +there is an intercept, and so we set the intercept attribute to 1 in +the terms object before calling model.matrix, ignoring any -1 term the +user may have added. +One simple way to handle all this is to call model.matrix on the original +formula and then remove the terms we don't need. +However, +\begin{enumerate} + \item The cluster() term, if any, could lead to thousands of extraneous + ``intercept'' columns which are never needed. + \item Likewise, nested case-control models can have thousands of strata, + again leading many intercepts we never need. They never have strata by + covariate interactions, however. + \item If there are strata by covariate interactions in the model, + the dummy intercepts-per-strata columns are necessary information for the + model.matrix routine to correctly compute other columns of $X$. +\end{enumerate} + +On later reflection \code{cluster} should never have been in the model +statement in the first place, something that became painfully apparent +with addition of multi-state models. +In the future we will discourage it. +For reason 2 above the usual plan is to also remove strata +terms from the ``Terms'' object \emph{before} calling model.matrix, +unless there are strata by covariate interactions in which case we remove +them after. +If anything is pre-dropped, for documentation purposes we want the +returned assign attribute to match the Terms structure that we will +hand back. (Do we ever use it?) +In particular, the numbers therein correspond to the column names in +\code{attr(Terms, 'factors')} +The requires a shift. The cluster and strata terms are seen as main +effects, so appear early in that list. +We have found a case where terms get relabeled: +<>= + t1 <- terms( ~(x1 + x2):x3 + strata(x4)) + t2 <- terms( ~(x1 + x2):x3) + t3 <- t1[-1] + colnames(attr(t1, "factors")) + colnames(attr(t2, "factors")) + colnames(attr(t3, "factors")) +@ +In t1 the strata term appears first, as it is the only thing that looks like +a main effect, and the column labels are strata(x4), x1:x3, x2:x3. +In t3 the column labels are x1:x3 and x3:x2 --- note left-right swap of +the second. This means that using match() on the labels is not a reliable +approach. +We instead assume that nothing is reordered and do a shift. + +<>= + +if (length(dropterms)) { + Terms2 <- Terms[ -dropterms] + X <- model.matrix(Terms2, mf, constrasts.arg=contrast.arg) + # we want to number the terms wrt the original model matrix + temp <- attr(X, "assign") + shift <- sort(dropterms) + for (i in seq(along.with=shift)) + temp <- temp + 1*(shift[i] <= temp) + attr(X, "assign") <- temp +} +else X <- model.matrix(Terms, mf, contrasts.arg=contrast.arg) + +# drop the intercept after the fact, and also drop strata if necessary +Xatt <- attributes(X) +if (hasinteractions) adrop <- c(0, untangle.specials(Terms, "strata")$terms) +else adrop <- 0 +xdrop <- Xatt$assign %in% adrop #columns to drop (always the intercept) +X <- X[, !xdrop, drop=FALSE] +attr(X, "assign") <- Xatt$assign[!xdrop] +attr(X, "contrasts") <- Xatt$contrasts +@ + +Finish the setup. If someone includes an init statement or offset, make sure +that it does not lead to instant code failure due to overflow/underflow. +<>= +offset <- model.offset(mf) +if (is.null(offset) | all(offset==0)) offset <- rep(0., nrow(mf)) +else if (any(!is.finite(offset) | !is.finite(exp(offset)))) + stop("offsets must lead to a finite risk score") + +weights <- model.weights(mf) +if (!is.null(weights) && any(!is.finite(weights))) + stop("weights must be finite") + +assign <- attrassign(X, Terms) +contr.save <- attr(X, "contrasts") +<> +@ + +Check for a rare edge case: a data set with no events. In this case the +return structure is simple. +The coefficients will all be NA, since they can't be estimated. +The variance matrix is all zeros, in line with the usual rule to zero out +any row and col corresponding to an NA coef. +The loglik is the sum of zero terms, which we set to zero like the usual +R result for sum(numeric(0)). +An overall idea is to return something that won't blow up later code. + +<>= +if (sum(Y[, ncol(Y)]) == 0) { + # No events in the data! + ncoef <- ncol(X) + ctemp <- rep(NA, ncoef) + names(ctemp) <- colnames(X) + concordance= c(concordant=0, discordant=0, tied.x=0, tied.y=0, tied.xy=0, + concordance=NA, std=NA, timefix=FALSE) + rval <- list(coefficients= ctemp, + var = matrix(0.0, ncoef, ncoef), + loglik=c(0,0), + score =0, + iter =0, + linear.predictors = offset, + residuals = rep(0.0, data.n), + means = colMeans(X), method=method, + n = data.n, nevent=0, terms=Terms, assign=assign, + concordance=concordance, wald.test=0.0, + y = Y, call=Call) + class(rval) <- "coxph" + return(rval) +} +@ + +Check for penalized terms in the model, and set up infrastructure for +the fitting routines to deal with them. +<>= +pterms <- sapply(mf, inherits, 'coxph.penalty') +if (any(pterms)) { + pattr <- lapply(mf[pterms], attributes) + pname <- names(pterms)[pterms] + # + # Check the order of any penalty terms + ord <- attr(Terms, "order")[match(pname, attr(Terms, 'term.labels'))] + if (any(ord>1)) stop ('Penalty terms cannot be in an interaction') + pcols <- assign[match(pname, names(assign))] + + fit <- coxpenal.fit(X, Y, istrat, offset, init=init, + control, + weights=weights, method=method, + row.names(mf), pcols, pattr, assign, + nocenter= nocenter) +} +@ + +<>= +else { + rname <- row.names(mf) + if (multi) rname <- rname[xstack$rindex] + if( method=="breslow" || method =="efron") { + if (grepl('right', type)) + fit <- coxph.fit(X, Y, istrat, offset, init, control, + weights=weights, method=method, + rname, nocenter=nocenter) + else fit <- agreg.fit(X, Y, istrat, offset, init, control, + weights=weights, method=method, + rname, nocenter=nocenter) + } + else if (method=='exact') { + if (type== "right") + fit <- coxexact.fit(X, Y, istrat, offset, init, control, + weights=weights, method=method, + rname, nocenter=nocenter) + else fit <- agexact.fit(X, Y, istrat, offset, init, control, + weights=weights, method=method, + rname, nocenter=nocenter) + } + else stop(paste ("Unknown method", method)) +} +@ + +<>= +if (is.character(fit)) { + fit <- list(fail=fit) + class(fit) <- 'coxph' +} +else { + if (!is.null(fit$coefficients) && any(is.na(fit$coefficients))) { + vars <- (1:length(fit$coefficients))[is.na(fit$coefficients)] + msg <-paste("X matrix deemed to be singular; variable", + paste(vars, collapse=" ")) + if (!singular.ok) stop(msg) + # else warning(msg) # stop being chatty + } + fit$n <- data.n + fit$nevent <- sum(Y[,ncol(Y)]) + fit$terms <- Terms + fit$assign <- assign + class(fit) <- fit$class + fit$class <- NULL + + # don't compute a robust variance if there are no coefficients + if (robust && !is.null(fit$coefficients) && !all(is.na(fit$coefficients))) { + fit$naive.var <- fit$var + # a little sneaky here: by calling resid before adding the + # na.action method, I avoid having missings re-inserted + # I also make sure that it doesn't have to reconstruct X and Y + fit2 <- c(fit, list(x=X, y=Y, weights=weights)) + if (length(istrat)) fit2$strata <- istrat + if (length(cluster)) { + temp <- residuals.coxph(fit2, type='dfbeta', collapse=cluster, + weighted=TRUE) + # get score for null model + if (is.null(init)) + fit2$linear.predictors <- 0*fit$linear.predictors + else fit2$linear.predictors <- c(X %*% init) + temp0 <- residuals.coxph(fit2, type='score', collapse=cluster, + weighted=TRUE) + } + else { + temp <- residuals.coxph(fit2, type='dfbeta', weighted=TRUE) + fit2$linear.predictors <- 0*fit$linear.predictors + temp0 <- residuals.coxph(fit2, type='score', weighted=TRUE) + } + fit$var <- t(temp) %*% temp + u <- apply(as.matrix(temp0), 2, sum) + fit$rscore <- coxph.wtest(t(temp0)%*%temp0, u, control$toler.chol)$test + } + + #Wald test + if (length(fit$coefficients) && is.null(fit$wald.test)) { + #not for intercept only models, or if test is already done + nabeta <- !is.na(fit$coefficients) + # The init vector might be longer than the betas, for a sparse term + if (is.null(init)) temp <- fit$coefficients[nabeta] + else temp <- (fit$coefficients - + init[1:length(fit$coefficients)])[nabeta] + fit$wald.test <- coxph.wtest(fit$var[nabeta,nabeta], temp, + control$toler.chol)$test + } + + # Concordance. Done here so that we can use cluster if it is present + # The returned value is a subset of the full result, partly because it + # is all we need, but more for backward compatability with survConcordance.fit + if (length(cluster)) + temp <- concordancefit(Y, fit$linear.predictors, istrat, weights, + cluster=cluster, reverse=TRUE, + timefix= FALSE) + else temp <- concordancefit(Y, fit$linear.predictors, istrat, weights, + reverse=TRUE, timefix= FALSE) + if (is.matrix(temp$count)) + fit$concordance <- c(colSums(temp$count), concordance=temp$concordance, + std=sqrt(temp$var)) + else fit$concordance <- c(temp$count, concordance=temp$concordance, + std=sqrt(temp$var)) + + na.action <- attr(mf, "na.action") + if (length(na.action)) fit$na.action <- na.action + if (model) { + if (length(timetrans)) { + stop("'model=TRUE' not supported for models with tt terms") + } + fit$model <- mf + } + if (x) { + fit$x <- X + if (length(timetrans)) fit$strata <- istrat + else if (length(strats)) fit$strata <- strata.keep + } + if (y) fit$y <- Y + fit$timefix <- control$timefix # remember this option +} +@ +If any of the weights were not 1, save the results. +Add names to the means component, which are occassionally +useful to survfit.coxph. +Other objects below are used when we need to recreate a +model frame. + +<>= +if (!is.null(weights) && any(weights!=1)) fit$weights <- weights +if (multi) { + fit$transitions <- transitions + fit$states <- states + fit$cmap <- cmap + fit$stratum_map <- stratum_map # why not 'stratamap'? Confusion with fit$strata + fit$resid <- rowsum(fit$resid, xstack$rindex) + # add a suffix to each coefficent name. Those that map to multiple transitions + # get the first transition they map to + single <- apply(cmap, 1, function(x) all(x %in% c(0, max(x)))) #only 1 coef + cindx <- col(cmap)[match(1:length(fit$coefficients), cmap)] + rindx <- row(cmap)[match(1:length(fit$coefficients), cmap)] + suffix <- ifelse(single[rindx], "", paste0("_", colnames(cmap)[cindx])) + names(fit$coefficients) <- paste0(names(fit$coefficients), suffix) + if (x) fit$strata <- istrat # save the expanded strata + class(fit) <- c("coxphms", class(fit)) +} +names(fit$means) <- names(fit$coefficients) + +fit$formula <- formula(Terms) +if (length(xlevels) >0) fit$xlevels <- xlevels +fit$contrasts <- contr.save +if (any(offset !=0)) fit$offset <- offset + +fit$call <- Call +fit +@ + +The model.matrix and model.frame routines are called after a Cox model to +reconstruct those portions. +Much of their code is shared with the coxph routine. + +<>= +# In internal use "data" will often be an already derived model frame. +# We detect this via it having a terms attribute. +model.matrix.coxph <- function(object, data=NULL, + contrast.arg=object$contrasts, ...) { + # + # If the object has an "x" component, return it, unless a new + # data set is given + if (is.null(data) && !is.null(object[['x']])) + return(object[['x']]) #don't match "xlevels" + + Terms <- delete.response(object$terms) + if (is.null(data)) mf <- stats::model.frame(object) + else { + if (is.null(attr(data, "terms"))) + mf <- stats::model.frame(Terms, data, xlev=object$xlevels) + else mf <- data #assume "data" is already a model frame + } + + cluster <- attr(Terms, "specials")$cluster + if (length(cluster)) { + temp <- untangle.specials(Terms, "cluster") + dropterms <- temp$terms + } + else dropterms <- NULL + + strats <- attr(Terms, "specials")$strata + hasinteractions <- FALSE + if (length(strats)) { + stemp <- untangle.specials(Terms, 'strata', 1) + if (length(stemp$vars)==1) strata.keep <- mf[[stemp$vars]] + else strata.keep <- strata(mf[,stemp$vars], shortlabel=TRUE) + istrat <- as.integer(strata.keep) + + for (i in stemp$vars) { #multiple strata terms are allowed + # The factors attr has one row for each variable in the frame, one + # col for each term in the model. Pick rows for each strata + # var, and find if it participates in any interactions. + if (any(attr(Terms, 'order')[attr(Terms, "factors")[i,] >0] >1)) + hasinteractions <- TRUE + } + if (!hasinteractions) dropterms <- c(dropterms, stemp$terms) + } else istrat <- NULL + + <> + X +} +@ + +In parallel is the model.frame routine, which reconstructs the model frame. +This routine currently doesn't do all that we want. To wit, the following code +fails: +\begin{verbatim} +> tfun <- function(formula, ndata) { + fit <- coxph(formula, data=ndata) + model.frame(fit) + } +> tfun(Surv(time, status) ~ age, lung) +Error: ndata not found +\end{verbatim} +The genesis of this problem is hard to unearth, but has to do with non standard +evaluation rules used by model.frame.default. In essence it pays attention to +the environment of the formula, but the enclos argument of eval appears to be +ignored. I've not yet found a solution. + +<>= +model.frame.coxph <- function(formula, ...) { + dots <- list(...) + nargs <- dots[match(c("data", "na.action", "subset", "weights", + "id", "cluster", "istate"), + names(dots), 0)] + # If nothing has changed and the coxph object had a model component, + # simply return it. + if (length(nargs) ==0 && !is.null(formula$model)) return(formula$model) + else { + # Rebuild the original call to model.frame + Terms <- terms(formula) + fcall <- formula$call + indx <- match(c("formula", "data", "weights", "subset", "na.action", + "cluster", "id", "istate"), + names(fcall), nomatch=0) + if (indx[1] ==0) stop("The coxph call is missing a formula!") + + temp <- fcall[c(1,indx)] # only keep the arguments we wanted + temp[[1]] <- quote(stats::model.frame) # change the function called + temp$xlev <- formula$xlevels # this will turn strings to factors + temp$formula <- Terms #keep the predvars attribute + # Now, any arguments that were on this call overtake the ones that + # were in the original call. + if (length(nargs) >0) + temp[names(nargs)] <- nargs + + # Make "tt" visible for coxph formulas, + if (!is.null(attr(temp$formula, "specials")$tt)) { + coxenv <- new.env(parent= environment(temp$formula)) + assign("tt", function(x) x, envir=coxenv) + environment(temp$formula) <- coxenv + } + + # The documentation for model.frame implies that the environment arg + # to eval will be ignored, but if we omit it there is a problem. + if (is.null(environment(formula$terms))) + mf <- eval(temp, parent.frame()) + else mf <- eval(temp, environment(formula$terms), parent.frame()) + + if (!is.null(attr(formula$terms, "dataClasses"))) + .checkMFClasses(attr(formula$terms, "dataClasses"), mf) + + if (is.null(attr(Terms, "specials")$tt)) return(mf) + else { + # Do time transform + tt <- eval(formula$call$tt) + Y <- aeqSurv(model.response(mf)) + strats <- attr(Terms, "specials")$strata + if (length(strats)) { + stemp <- untangle.specials(Terms, 'strata', 1) + if (length(stemp$vars)==1) strata.keep <- mf[[stemp$vars]] + else strata.keep <- strata(mf[,stemp$vars], shortlabel=TRUE) + istrat <- as.numeric(strata.keep) + } + + <> + mf[[".strata."]] <- istrat + return(mf) + } + } +} +@ + +\subsection{Exact partial likelihood} +Let $r_i = \exp(X_i\beta)$ be the risk score for observation $i$. +For one of the time points assume that there that there are $d$ +tied deaths among $n$ subjects at risk. +For convenience we will index them as $i= 1,\ldots,d$ in the $n$ at risk. +Then for the exact parial likelihood, the contribution at this time point +is +\begin{align*} + L &= \sum_{i=1}^d \log(r_i) - \log(D) \\ + \frac{\partial L}{\partial \beta_j} &= x_{ij} - (1/D) + \frac{\partial D}{\partial \beta_j} \\ + \frac{\partial^2 L}{\partial \beta_j \partial \beta_k} &= + (1/D^2)\left[D\frac{\partial^2D}{\partial \beta_j \partial \beta_k} - + \frac{\partial D}{\partial \beta_j}\frac{\partial D}{\partial \beta_k} + \right] +\end{align*} +The hard part of this computation is $D$, which is a sum +\begin{equation*} + D = \sum_{S(d,n)} r_{s_1}r_{s_2} \ldots r_{s_d} +\end{equation*} +where $S(d,n)$ is the set of all possible subsets of size $d$ from $n$ +objects, and $s_1, s_2, \ldots$ indexes the current selection. +So if $n=6$ and $d=2$ we would have the 15 pairs 12, 13, .... 56; +for $n=5$ and $d=3$ there would be 10 triples 123, 124, 125, \ldots, 345. + +The brute force computation of all subsets can take a very long time. +Gail et al \cite{Gail81} show simple recursion formulas that speed +this up considerably. Let $D(d,n)$ be the denominator with $d$ +deaths and $n$ subjects. Then +\begin{align} + D(d,n) &= r_nD(d-1, n-1) + D(d, n-1) \label{d0}\\ + \frac{\partial D(d,n)}{\partial \beta_j} &= + \frac{\partial D(d, n-1)}{\partial \beta_j} + + r_n \frac{\partial D(d-1, n-1)}{\partial \beta_j} + + x_{nj}r_n D(d-1, n-1) \label{d1}\\ + \frac{\partial^2D(d,n}{\partial \beta_j \partial \beta_k} &= + \frac{\partial^2D(d,n-1)}{\partial \beta_j \partial \beta_k} + + r_n\frac{\partial^2D(d-1,n-1)}{\partial \beta_j \partial \beta_k} + + x_{nj}r_n\frac{\partial D(d-1, n-1)}{\partial \beta_k} + \nonumber \\ + & x_{nk}r_n\frac{\partial D(d-1, n-1)}{\partial \beta_j} + + x_{nj}x_{nk}r_n D(d-1, n-1) \label{d2} +\end{align} + +The above recursion is captured in the three routines below. +The first calculates $D$. +It is called with $d$, $n$, an array that will contain all the +values of $D(d,n)$ computed so far, and the the first dimension of the array. +The intial condition $D(0,n)=1$ is important to all three routines. + +<>= +double coxd0(int d, int n, double *score, double *dmat, + int dmax) { + double *dn; + + if (d==0) return(1.0); + dn = dmat + (n-1)*dmax + d -1; /* pointer to dmat[d,n] */ + + if (*dn ==0) { /* still to be computed */ + *dn = score[n-1]* coxd0(d-1, n-1, score, dmat, dmax); + if (d>= +double coxd1(int d, int n, double *score, double *dmat, double *d1, + double *covar, int dmax) { + int indx; + + indx = (n-1)*dmax + d -1; /*index to the current array member d1[d.n]*/ + if (d1[indx] ==0) { /* still to be computed */ + d1[indx] = score[n-1]* covar[n-1]* coxd0(d-1, n-1, score, dmat, dmax); + if (d1) d1[indx] += score[n-1]* + coxd1(d-1, n-1, score, dmat, d1, covar, dmax); + } + return(d1[indx]); +} + +double coxd2(int d, int n, double *score, double *dmat, double *d1j, + double *d1k, double *d2, double *covarj, double *covark, + int dmax) { + int indx; + + indx = (n-1)*dmax + d -1; /*index to the current array member d1[d,n]*/ + if (d2[indx] ==0) { /*still to be computed */ + d2[indx] = coxd0(d-1, n-1, score, dmat, dmax)*score[n-1] * + covarj[n-1]* covark[n-1]; + if (d1) d2[indx] += score[n-1] * ( + coxd2(d-1, n-1, score, dmat, d1j, d1k, d2, covarj, covark, dmax) + + covarj[n-1] * coxd1(d-1, n-1, score, dmat, d1k, covark, dmax) + + covark[n-1] * coxd1(d-1, n-1, score, dmat, d1j, covarj, dmax)); + } + return(d2[indx]); +} +@ + +Now for the main body. Start with the dull part of the code: +declarations. +I use [[maxiter2]] for the +S structure and [[maxiter]] for the variable within it, and +etc for the other input arguments. +All the input arguments except strata are read-only. +The output beta vector starts as a copy of ibeta. +<>= +#include +#include "survS.h" +#include "survproto.h" +#include + +<> + +SEXP coxexact(SEXP maxiter2, SEXP y2, + SEXP covar2, SEXP offset2, SEXP strata2, + SEXP ibeta, SEXP eps2, SEXP toler2) { + int i,j,k; + int iter; + + double **covar, **imat; /*ragged arrays */ + double *time, *status; /* input data */ + double *offset; + int *strata; + int sstart; /* starting obs of current strata */ + double *score; + double *oldbeta; + double zbeta; + double newlk=0; + double temp; + int halving; /*are we doing step halving at the moment? */ + int nrisk =0; /* number of subjects in the current risk set */ + int dsize, /* memory needed for one coxc0, coxc1, or coxd2 array */ + dmemtot, /* amount needed for all arrays */ + ndeath; /* number of deaths at the current time point */ + double maxdeath; /* max tied deaths within a strata */ + + double dtime; /* time value under current examiniation */ + double *dmem0, **dmem1, *dmem2; /* pointers to memory */ + double *dtemp; /* used for zeroing the memory */ + double *d1; /* current first derivatives from coxd1 */ + double d0; /* global sum from coxc0 */ + + /* copies of scalar input arguments */ + int nused, nvar, maxiter; + double eps, toler; + + /* returned objects */ + SEXP imat2, beta2, u2, loglik2; + double *beta, *u, *loglik; + SEXP rlist, rlistnames; + int nprotect; /* number of protect calls I have issued */ + + <> + <> + <> + <> + } +@ + +Setup is ordinary. Grab S objects and assign others. +I use \verb!R_alloc! for temporary ones since it is released automatically on +return. +<>= +nused = LENGTH(offset2); +nvar = ncols(covar2); +maxiter = asInteger(maxiter2); +eps = asReal(eps2); /* convergence criteria */ +toler = asReal(toler2); /* tolerance for cholesky */ + +/* +** Set up the ragged array pointer to the X matrix, +** and pointers to time and status +*/ +covar= dmatrix(REAL(covar2), nused, nvar); +time = REAL(y2); +status = time +nused; +strata = INTEGER(PROTECT(duplicate(strata2))); +offset = REAL(offset2); + +/* temporary vectors */ +score = (double *) R_alloc(nused+nvar, sizeof(double)); +oldbeta = score + nused; + +/* +** create output variables +*/ +PROTECT(beta2 = duplicate(ibeta)); +beta = REAL(beta2); +PROTECT(u2 = allocVector(REALSXP, nvar)); +u = REAL(u2); +PROTECT(imat2 = allocVector(REALSXP, nvar*nvar)); +imat = dmatrix(REAL(imat2), nvar, nvar); +PROTECT(loglik2 = allocVector(REALSXP, 5)); /* loglik, sctest, flag,maxiter*/ +loglik = REAL(loglik2); +nprotect = 5; +@ + +The data passed to us has been sorted by strata, and +reverse time within strata (longest subject first). +The variable [[strata]] will be 1 at the start of each new strata. +Separate strata are completely separate computations: time 10 in +one strata and time 10 in another are not comingled. +Compute the largest product (size of strata)* +(max tied deaths in strata) for allocating scratch space. +When computing $D$ it is advantageous to create all the intermediate +values of $D(d,n)$ in an array since they will be used in the +derivative calculation. Likewise, the first derivatives are used +in calculating the second. +Even more importantly, say we have a large data set. It will +be sorted with the longest times first. +If there is a death with 30 at risk and another with 40 at +risk, the intermediate sums we computed for the n=30 case +are part of the computation for n=40. To make this +work we need to index our matrices, within any strata, +by the maximum number of tied deaths in the strata. +We save this in the strata variable: first obs of a new +strata has the number of events. +And what if a strata had 0 events? We mark it with a 1. + +Note that the maxdeath variable is floating point. I had someone call this +routine with a data set that gives an integer overflow in that situation. +We now keep track of this further below and fail with a message. +Such a run would take longer than forever to complete even if integer +subscripts did not overflow. +<>= +strata[0] =1; /* in case the parent forgot (e.g., no strata case)*/ +temp = 0; /* temp variable for dsize */ + +maxdeath =0; +j=0; /* start of the strata */ +for (i=0; i0) { + /* assign data for the prior stratum, just finished */ + /* If maxdeath <2 leave the strata alone at it's current value of 1 */ + if (maxdeath >1) strata[j] = maxdeath; + j = i; + if (maxdeath*nrisk > temp) temp = maxdeath*nrisk; + } + maxdeath =0; /* max tied deaths at any time in this strata */ + nrisk=0; + ndeath =0; + } + dtime = time[i]; + ndeath =0; /*number tied here */ + while (time[i] ==dtime) { + nrisk++; + ndeath += status[i]; + i++; + if (i>=nused || strata[i] >0) break; /*tied deaths don't cross strata */ + } + if (ndeath > maxdeath) maxdeath = ndeath; +} +/* data for the final stratum */ +if (maxdeath*nrisk > temp) temp = maxdeath*nrisk; +if (maxdeath >1) strata[j] = maxdeath; + +/* Now allocate memory for the scratch arrays + Each per-variable slice is of size dsize +*/ +dsize = temp; +temp = temp * ((nvar*(nvar+1))/2 + nvar + 1); +dmemtot = dsize * ((nvar*(nvar+1))/2 + nvar + 1); +if (temp != dmemtot) { /* the subscripts will overflow */ + error("(number at risk) * (number tied deaths) is too large"); +} +dmem0 = (double *) R_alloc(dmemtot, sizeof(double)); /*pointer to memory */ +dmem1 = (double **) R_alloc(nvar, sizeof(double*)); +dmem1[0] = dmem0 + dsize; /*points to the first derivative memory */ +for (i=1; i>= +sstart =0; /* a line to make gcc stop complaining */ +for (i=0; i0) { /* first obs of a new strata */ + maxdeath= strata[i]; + dtemp = dmem0; + for (j=0; j=nused || strata[i] >0) break; + } + + /* We have added up over the death time, now process it */ + if (ndeath >0) { /* Add to the loglik */ + d0 = coxd0(ndeath, nrisk, score+sstart, dmem0, maxdeath); + R_CheckUserInterrupt(); + newlk -= log(d0); + dmem2 = dmem0 + (nvar+1)*dsize; /*start for the second deriv memory */ + for (j=0; j 3) R_CheckUserInterrupt(); + u[j] -= d1[j]; + for (k=0; k<= j; k++) { /* second derivative*/ + temp = coxd2(ndeath, nrisk, score+sstart, dmem0, dmem1[j], + dmem1[k], dmem2, covar[j] + sstart, + covar[k] + sstart, maxdeath); + if (ndeath > 5) R_CheckUserInterrupt(); + imat[k][j] += temp/d0 - d1[j]*d1[k]; + dmem2 += dsize; + } + } + } + } +@ + +Do the first iteration of the solution. The first iteration is +different in 3 ways: it is used to set the initial log-likelihood, +to compute the score test, and +we pay no attention to convergence criteria or diagnositics. +(I expect it not to converge in one iteration). + +<>= +/* +** do the initial iteration step +*/ +newlk =0; +for (i=0; i> + +loglik[0] = newlk; /* save the loglik for iteration zero */ +loglik[1] = newlk; /* and it is our current best guess */ +/* +** update the betas and compute the score test +*/ +for (i=0; i> + } + +/* +** Never, never complain about convergence on the first step. That way, +** if someone has to they can force one iter at a time. +*/ +for (i=0; i>= +halving =0 ; /* =1 when in the midst of "step halving" */ +for (iter=1; iter<=maxiter; iter++) { + newlk =0; + for (i=0; i> + + /* am I done? + ** update the betas and test for convergence + */ + loglik[3] = cholesky2(imat, nvar, toler); + + if (fabs(1-(loglik[1]/newlk))<= eps && halving==0) { /* all done */ + loglik[1] = newlk; + <> + } + + if (iter==maxiter) break; /*skip the step halving and etc */ + + if (newlk < loglik[1]) { /*it is not converging ! */ + halving =1; + for (i=0; i> +@ + +The common code for finishing. Invert the information matrix, copy it +to be symmetric, and put together the output structure. + +<>= +loglik[4] = iter; +chinv2(imat, nvar); +for (i=1; i>= +agreg.fit <- function(x, y, strata, offset, init, control, + weights, method, rownames, resid=TRUE, nocenter=NULL) + { + nvar <- ncol(x) + event <- y[,3] + if (all(event==0)) stop("Can't fit a Cox model with 0 failures") + + if (missing(offset) || is.null(offset)) offset <- rep(0.0, nrow(y)) + if (missing(weights)|| is.null(weights))weights<- rep(1.0, nrow(y)) + else if (any(weights<=0)) stop("Invalid weights, must be >0") + else weights <- as.vector(weights) + + # Find rows to be ignored. We have to match within strata: a + # value that spans a death in another stratum, but not it its + # own, should be removed. Hence the per stratum delta + if (length(strata) ==0) {y1 <- y[,1]; y2 <- y[,2]} + else { + if (is.numeric(strata)) strata <- as.integer(strata) + else strata <- as.integer(as.factor(strata)) + delta <- strata* (1+ max(y[,2]) - min(y[,1])) + y1 <- y[,1] + delta + y2 <- y[,2] + delta + } + event <- y[,3] > 0 + dtime <- sort(unique(y2[event])) + indx1 <- findInterval(y1, dtime) + indx2 <- findInterval(y2, dtime) + # indx1 != indx2 for any obs that spans an event time + ignore <- (indx1 == indx2) + nused <- sum(!ignore) + + # Sort the data (or rather, get a list of sorted indices) + # For both stop and start times, the indices go from last to first + if (length(strata)==0) { + sort.end <- order(ignore, -y[,2]) -1L #indices start at 0 for C code + sort.start<- order(ignore, -y[,1]) -1L + strata <- rep(0L, nrow(y)) + } + else { + sort.end <- order(ignore, strata, -y[,2]) -1L + sort.start<- order(ignore, strata, -y[,1]) -1L + } + + if (is.null(nvar) || nvar==0) { + # A special case: Null model. Just return obvious stuff + # To keep the C code to a small set, we call the usual routines, but + # with a dummy X matrix and 0 iterations + nvar <- 1 + x <- matrix(as.double(1:nrow(y)), ncol=1) #keep the .C call happy + maxiter <- 0 + nullmodel <- TRUE + if (length(init) !=0) stop("Wrong length for inital values") + init <- 0.0 #dummy value to keep a .C call happy (doesn't like 0 length) + } + else { + nullmodel <- FALSE + maxiter <- control$iter.max + + if (is.null(init)) init <- rep(0., nvar) + if (length(init) != nvar) stop("Wrong length for inital values") + } + + # 2021 change: pass in per covariate centering. This gives + # us more freedom to experiment. Default is to leave 0/1 variables alone + if (is.null(nocenter)) zero.one <- rep(FALSE, ncol(x)) + zero.one <- apply(x, 2, function(z) all(z %in% nocenter)) + + # the returned value of agfit$coef starts as a copy of init, so make sure + # is is a vector and not a matrix; as.double suffices. + # Solidify the storage mode of other arguments + storage.mode(y) <- storage.mode(x) <- "double" + storage.mode(offset) <- storage.mode(weights) <- "double" + agfit <- .Call(Cagfit4, nused, + y, x, strata, weights, + offset, + as.double(init), + sort.start, sort.end, + as.integer(method=="efron"), + as.integer(maxiter), + as.double(control$eps), + as.double(control$toler.chol), + ifelse(zero.one, 0L, 1L)) + # agfit4 centers variables within strata, so does not return a vector + # of means. Use a fill in consistent with other coxph routines + agmeans <- ifelse(zero.one, 0, colMeans(x)) + + <> + <> + rval +} +@ + +Upon return we need to clean up three simple things. +The first is the rare case that the agfit routine failed. +These cases are rare, usually involve an overflow or underflow, and +we encourage users to let us have a copy of the data when it occurs. +(They end up in the \code{fail} directory of the library.) +The second is that if any of the covariates were redudant then this +will be marked by zeros on the diagonal of the variance matrix. +Replace these coefficients and their variances with NA. +The last is to post a warning message about possible infinite coefficients. +The algorithm for determining this is unreliable, unfortunately. +Sometimes coefficients are marked as infinite when the solution is not tending +to infinity (usually associated with a very skewed covariate), and sometimes +one that is tending to infinity is not marked. Que sera sera. +Don't complain if the user asked for only one iteration; they will already +know that it has not converged. +<>= +vmat <- agfit$imat +coef <- agfit$coef +if (agfit$flag[1] < nvar) which.sing <- diag(vmat)==0 +else which.sing <- rep(FALSE,nvar) + +if (maxiter >1) { + infs <- abs(agfit$u %*% vmat) + if (any(!is.finite(coef)) || any(!is.finite(vmat))) + stop("routine failed due to numeric overflow.", + "This should never happen. Please contact the author.") + if (agfit$flag[4] > 0) + warning("Ran out of iterations and did not converge") + else { + infs <- (!is.finite(agfit$u) | + infs > control$toler.inf*(1+ abs(coef))) + if (any(infs)) + warning(paste("Loglik converged before variable ", + paste((1:nvar)[infs],collapse=","), + "; beta may be infinite. ")) + } +} +@ + +The last of the code is very standard. Compute residuals and package +up the results. +One design decision is that we return all $n$ residuals and predicted +values, even though the model fit ignored useless observations. +(All those obs have a residual of 0). +<>= +lp <- as.vector(x %*% coef + offset - sum(coef * agmeans)) +if (resid) { + if (any(lp > log(.Machine$double.xmax))) { + # prevent a failure message due to overflow + # this occurs with near-infinite coefficients + temp <- lp + log(.Machine$double.xmax) - (1 + max(lp)) + score <- exp(temp) + } else score <- exp(lp) + + residuals <- .Call(Cagmart3, nused, + y, score, weights, + strata, + sort.start, sort.end, + as.integer(method=='efron')) + names(residuals) <- rownames +} + +# The if-then-else below is a real pain in the butt, but the tccox +# package's test suite assumes that the ORDER of elements in a coxph +# object will never change. +# +if (nullmodel) { + rval <- list(loglik=agfit$loglik[2], + linear.predictors = offset, + method= method, + class = c("coxph.null", 'coxph') ) + if (resid) rval$residuals <- residuals +} +else { + names(coef) <- dimnames(x)[[2]] + if (maxiter > 0) coef[which.sing] <- NA # always leave iter=0 alone + flag <- agfit$flag + names(flag) <- c("rank", "rescale", "step halving", "convergence") + + if (resid) { + rval <- list(coefficients = coef, + var = vmat, + loglik = agfit$loglik, + score = agfit$sctest, + iter = agfit$iter, + linear.predictors = as.vector(lp), + residuals = residuals, + means = agmeans, + first = agfit$u, + info = flag, + method= method, + class = "coxph") + } else { + rval <- list(coefficients = coef, + var = vmat, + loglik = agfit$loglik, + score = agfit$sctest, + iter = agfit$iter, + linear.predictors = as.vector(lp), + means = agmeans, + first = agfit$u, + info = flag, + method = method, + class = "coxph") + } + rval +} +@ + +The details of the C code contain the more challenging part of the +computations. +It starts with the usual dull stuff. +My standard coding style for a variable zed to to use +[[zed2]] as the variable name for the R object, and [[zed]] for +the pointer to the contents of the object, i.e., what the +C code will manipulate. +For the matrix objects I make use of ragged arrays, this +allows for reference to the i,j element as \code{cmat[i][j]} +and makes for more readable code. + +<>= +#include +#include "survS.h" +#include "survproto.h" + +SEXP agfit4(SEXP nused2, SEXP surv2, SEXP covar2, SEXP strata2, + SEXP weights2, SEXP offset2, SEXP ibeta2, + SEXP sort12, SEXP sort22, SEXP method2, + SEXP maxiter2, SEXP eps2, SEXP tolerance2, + SEXP doscale2) { + + int i,j,k, person; + int indx1, istrat, p, p1; + int nrisk, nr; + int nused, nvar; + int rank=0, rank2, fail; /* =0 to keep -Wall happy */ + + double **covar, **cmat, **imat; /*ragged array versions*/ + double *a, *oldbeta; + double *scale; + double *a2, **cmat2; + double *eta; + double denom, zbeta, risk; + double dtime =0; /* initial value to stop a -Wall message */ + double temp, temp2; + double newlk =0; + int halving; /*are we doing step halving at the moment? */ + double tol_chol, eps; + double meanwt; + int deaths; + double denom2, etasum; + double recenter; + + /* inputs */ + double *start, *tstop, *event; + double *weights, *offset; + int *sort1, *sort2, maxiter; + int *strata; + double method; /* saving this as double forces some double arithmetic */ + int *doscale; + + /* returned objects */ + SEXP imat2, beta2, u2, loglik2; + double *beta, *u, *loglik; + SEXP sctest2, flag2, iter2; + double *sctest; + int *flag, *iter; + SEXP rlist; + static const char *outnames[]={"coef", "u", "imat", "loglik", + "sctest", "flag", "iter", ""}; + int nprotect; /* number of protect calls I have issued */ + + /* get sizes and constants */ + nused = asInteger(nused2); + nvar = ncols(covar2); + nr = nrows(covar2); /*nr = number of rows, nused = how many we use */ + method= asInteger(method2); + eps = asReal(eps2); + tol_chol = asReal(tolerance2); + maxiter = asInteger(maxiter2); + doscale = INTEGER(doscale2); + + /* input arguments */ + start = REAL(surv2); + tstop = start + nr; + event = tstop + nr; + weights = REAL(weights2); + offset = REAL(offset2); + sort1 = INTEGER(sort12); + sort2 = INTEGER(sort22); + strata = INTEGER(strata2); + + /* + ** scratch space + ** nvar: a, a2, oldbeta, scale + ** nvar*nvar: cmat, cmat2 + ** nr: eta + */ + eta = (double *) R_alloc(nr + 4*nvar + 2*nvar*nvar, sizeof(double)); + a = eta + nr; + a2= a + nvar; + scale = a2 + nvar; + oldbeta = scale + nvar; + + /* + ** Set up the ragged arrays + ** covar2 might not need to be duplicated, even though + ** we are going to modify it, due to the way this routine was + ** was called. But check + */ + PROTECT(imat2 = allocMatrix(REALSXP, nvar, nvar)); + nprotect =1; + if (MAYBE_REFERENCED(covar2)) { + PROTECT(covar2 = duplicate(covar2)); + nprotect++; + } + covar= dmatrix(REAL(covar2), nr, nvar); + imat = dmatrix(REAL(imat2), nvar, nvar); + cmat = dmatrix(oldbeta+ nvar, nvar, nvar); + cmat2= dmatrix(oldbeta+ nvar + nvar*nvar, nvar, nvar); + + /* + ** create the output structures + */ + PROTECT(rlist = mkNamed(VECSXP, outnames)); + nprotect++; + beta2 = SET_VECTOR_ELT(rlist, 0, duplicate(ibeta2)); + beta = REAL(beta2); + u2 = SET_VECTOR_ELT(rlist, 1, allocVector(REALSXP, nvar)); + u = REAL(u2); + + SET_VECTOR_ELT(rlist, 2, imat2); + loglik2 = SET_VECTOR_ELT(rlist, 3, allocVector(REALSXP, 2)); + loglik = REAL(loglik2); + + sctest2 = SET_VECTOR_ELT(rlist, 4, allocVector(REALSXP, 1)); + sctest = REAL(sctest2); + flag2 = SET_VECTOR_ELT(rlist, 5, allocVector(INTSXP, 4)); + flag = INTEGER(flag2); + for (i=0; i<4; i++) flag[i]=0; + + iter2 = SET_VECTOR_ELT(rlist, 6, allocVector(INTSXP, 1)); + iter = INTEGER(iter2); + + /* + ** Subtract the mean from each covar, as this makes the variance + ** computation more stable. The mean is taken per stratum, + ** the scaling is overall. + */ + for (i=0; i0) temp = temp2/temp; /* 1/scale */ + else temp = 1.0; /* rare case of a constant covariate */ + scale[i] = temp; + for (person=0; person> + <> +} +@ + +As we walk through the risk sets observations are both added and +removed from a set of running totals. +We have 6 running totals: +\begin{itemize} + \item sum of the weights, denom = $\sum w_i r_i$ + \item totals for each covariate a[j] = $\sum w_ir_i x_{ij}$ + \item totals for each covariate pair cmat[j,k]= $\sum w_ir_i x_{ij} x_{ik}$ + \item the same three quantities, but only for times that are exactly + tied with the current death time, named denom2, a2, cmat2. + This allows for easy compuatation of the Efron approximation for ties. +\end{itemize} + + +At one point I spent a lot of time worrying about $r_i$ values that are too +large, but it turns out that the overall scale of the weights does not +really matter since they always appear as a ratio. +(Assuming we avoid exponential overflow and underflow, of course.) +What does get the code in trouble is when there are large and small +weights and we get an update of (large + small) - large. +For example suppose a data set has a time dependent covariate which grows +with time and the data has values like below: + +\begin{center} + \begin{tabular}{ccccc} + time1 & time2 & status & x \\ \hline + 0 & 90 & 1 & 1 \\ + 0 & 105 & 0 & 2 \\ + 100 & 120 & 1 & 50 \\ + 100 & 124 & 0 & 51 + \end{tabular} +\end{center} +The code moves from large times to small, so the first risk set has +subjects 3 and 4, the second has 1 and 2. +The original code would do removals only when necessary, i.e., at the +event times of 120 and 90, and additions as they came along. +This leads to adding in subjects 1 and 2 before the update at time 90 +when observations 3 and 4 are removed; +for a coefficient greater than about .6 this leads to a loss of all of +the significant digits. +The defense is to remove subjects from the risk set as early +as possible, and defer additions for as long as possible. +Every time we hit a new (unique) death time, and only then, +update the totals: first remove any +old observations no longer in the risk set and then add any new ones. + +One interesting edge case is observations that are not part of any risk +set. (A call to survSplit with too fine a partition can create these, or +using a subset of data that excluded some of the deaths.) +Observations that are not part of any risk set add unnecessary noise since +they will be added and then subtracted from all the totals, but the +intermediate values are never used. If said observation had a large risk +score this could be exceptionally bad. +The parent routine has already dealt with such observations: their indices +never appear in the sort1 or sort2 vector. + +The three primary quantities for the Cox model are the log-likelihood $L$, +the score vector $U$ and the Hessian matrix $H$. +\begin{align*} + L &= \sum_i w_i \delta_i \left[\eta_i - \log(d(t)) \right] \\ + d(t) &= \sum_j w_j r_j Y_j(t) \\ + U_k &= \sum_i w_i \delta_i \left[ (X_{ik} - \mu_k(t_i)) \right] \\ + \mu_k(t) &= \frac{\sum_j w_j r_j Y_j(t) X_{jk}} {d(t)} \\ + H_{kl} &= \sum_i w_i \delta_i V_{kl}(t_i) \\ + V_{kl}(t) &= \frac{\sum_j w_j r_j Y_j(t) [X_{jk} - \mu_k(t)] + [X_{jl}- \mu_l(t)]} {d(t)} \\ + &= \frac{\sum_j w_j r_j Y_j(t) X_{jk}X_{jl}} {d(t)} + - d(t) \mu_k(t) \mu_l(t) +\end{align*} +In the above $\delta_i =1$ for an event and 0 otherwise, $w_i$ is the per +subject weight, $\eta_i$ is the current linear predictor $X\beta$ for the +subject, $r_i = \exp(\eta_i)$ is the risk score +and $Y_i(t)$ is 1 if observation $i$ is at risk at time $t$. +The vector $\mu(t)$ is the weighted mean of the covariates at time $t$ +using a weight of $w r Y(t)$ for each subject, and $V(t)$ is the weighted +variance matrix of $X$ at time $t$. + +Tied deaths and the Efron approximation add a small complication to the +formula. Say there are three tied deaths at some particular time $t$. +When calculating the denominator $d(t)$, mean $\mu(t)$ and variance +$V(t)$ at that time the inclusion value $Y_i(t)$ is 0 or 1 for all other +subjects, as usual, but for the three tied deaths Y(t) is taken to +be 1 for the first death, 2/3 for the second, and 1/3 for the third. +The idea is that if the tied death times were randomly broken by adding +a small random amount then each of these three would be in the first risk set, +have 2/3 chance of being in the second, and 1/3 chance of being in the risk +set for the third death. +In the code this means that at a death time we add the \code{denom2}, +\code{a2} and \code{c2} portions in a little at at time: +for three tied death the code will add in 1/3, update totals, +add in another 1/3, update totals, then the last 1/3, and update totals. + +The variance formula is stable if $\mu$ is small relative to +the total variance. This is guarranteed by having a working estimate $m$ +of the mean along with the formula: +\begin{align*} + (1/n) \sum w_ir_i(x_i- \mu)^2 &= (1/n)\sum w_ir_i(x-m)^2 - + (\mu -m)^2 \\ + \mu &= (1/n) \sum w_ir_i (x_i -m)\\ + n &= \sum w_ir_i +\end{align*} +A refinement of this is to scale the covariates, since the Cholesky +decomposition can lose precision when variables are on vastly different +scales. We do this centering and scaling once at the beginning of the +calculation. +Centering is done per strata --- what if someone had two strata and +a covariate with mean 0 in the first but mean one million in the second? +(Users do amazing things). Scaling is required to be a single +value for each covariate, however. For a univariate model scaling +does not add any precision. + +Weighted sums can still be unstable if the weights get out of hand. +Because of the exponential $r_i = exp(\eta_i)$ +the original centering of the $X$ matrix may not be enough. +A particular example was a data set on hospital adverse events with +``number of nurse shift changes to date'' as a time dependent covariate. +At any particular time point the covariate varied only by $\pm 3$ between +subjects (weekends often use 12 hour nurse shifts instead of 8 hour). The +regression coefficient was around 1 and the data duration was 11 weeks +(about 200 shifts) so that $eta$ values could be over 100 even after +centering. We keep a time dependent average of $\eta$ and use it to update +a recentering constant as necessary. +A case like this should be rare, but it is not as unusual as one might +think. + +The last numerical problem is when one or more coefficients gets too +large, leading to a huge weight exp(eta). +This usually happens when a coefficient is tending to infinity, but can +also be due to a bad step in the intermediate Newton-Raphson path. +In the infinite coefficient case the +log-likelihood trends to an asymptote and there is a race between three +conditions: convergence of the loglik, singularity of the variance matrix, +or an invalid log-likelihood. The first of these wins the race most of +the time, especially if the data set is small, and is the simplest case. +The last occurs when the denominator becomes $<0$ due to +round off so that log(denom) is undefined, the second when extreme weights +cause the second derivative to lose precision. +In all 3 we revert to step halving, since a bad Newton-Raphson step can +cause the same issues to arise. + +The next section of code adds up the totals for a given iteration. +This is the workhorse. +For a given death time all of the events tied at +that time must be handled together, hence the main loop below proceeds in +batches: +\begin{enumerate} + \item Find the time of the next death. Whenever crossing a stratum + boundary, zero cetain intermediate sums. + \item Remove all observations in the stratum with time1 $>$ dtime. + When survSplit was used to create a data set, this will often remove all. + If so we can rezero temporaries and regain precision. + \item Add new observations to the risk set and to the death counts. +\end{enumerate} + + +<>= +for (person=0; person> + + /* + ** add any new subjects who are at risk + ** denom2, a2, cmat2, meanwt and deaths count only the deaths + */ + denom2= 0; + meanwt =0; + deaths=0; + for (i=0; i> + risk = exp(eta[p] - recenter) * weights[p]; + + if (event[p] ==1 ){ + deaths++; + denom2 += risk; + meanwt += weights[p]; + newlk += weights[p]* (eta[p] - recenter); + for (i=0; i> +} /* end of accumulation loop */ +@ + +The last step in the above loop adds terms to the loglik, score and +information matrices. Assume that there were 3 tied deaths. +The difference between the Efron and Breslow approximations is that for the +Efron the three tied subjects are given a weight of 1/3 for the first, 2/3 for +the second, and 3/3 for the third death; for the Breslow they get 3/3 for +all of them. +Note that \code{imat} is symmetric, and that the cholesky routine will +utilize the upper triangle of the matrix as input, using the lower part for +its own purposes. The inverse from \code{chinv} is also in the upper +triangle. +<>= +/* +** Add results into u and imat for all events at this time point +*/ +if (method==0 || deaths ==1) { /*Breslow */ + denom += denom2; + newlk -= meanwt*log(denom); /* sum of death weights*/ + for (i=0; i>= +/* +** subtract out the subjects whose start time is to the right +** If everyone is removed reset the totals to zero. (This happens when +** the survSplit function is used, so it is worth checking). +*/ +for (; indx1>= +/* +** We must avoid overflow in the exp function (~709 on Intel) +** and want to act well before that, but not take action very often. +** One of the case-cohort papers suggests an offset of -100 meaning +** that etas of 50-100 can occur in "ok" data, so make it larger +** than this. +** If the range of eta is more then log(1e16) = 37 then the data is +** hopeless: some observations will have effectively 0 weight. Keeping +** the mean sensible has sufficed to keep the max in check. +*/ +if (fabs(etasum/nrisk - recenter) > 200) { + flag[1]++; /* a count, for debugging/profiling purposes */ + temp = etasum/nrisk - recenter; + recenter = etasum/nrisk; + + if (denom > 0) { + /* we can skip this if there is no one at risk */ + if (fabs(temp) > 709) error("exp overflow due to covariates\n"); + + temp = exp(-temp); /* the change in scale, for all the weights */ + denom *= temp; + for (i=0; i>= +/* main loop */ +halving =0 ; /* =1 when in the midst of "step halving" */ +fail =0; +for (*iter=0; *iter<= maxiter; (*iter)++) { + R_CheckUserInterrupt(); /* be polite -- did the user hit cntrl-C? */ + <> + + if (*iter==0) { + loglik[0] = newlk; + loglik[1] = newlk; + /* compute the score test, but don't corrupt u */ + for (i=0; i0) break; + + for (i=0; i1 && ((newlk -loglik[1])/ fabs(loglik[1])) < -eps) { + /* + ** "Once more unto the breach, dear friends, once more; ..." + **The last iteration above was worse than one of the earlier ones, + ** by more than roundoff error. + ** We need to use beta and imat at the last good value, not the + ** last attempted value. We have tossed the old imat away, so + ** recompute it. + ** It will happen very rarely that we run out of iterations, and + ** even less often that it is right in the middle of halving. + */ + for (i=0; i> + rank2 = cholesky2(imat, nvar, tol_chol); + } + break; + } + + if (fail >0 || newlk < loglik[1]) { + /* + ** The routine has not made progress past the last good value. + */ + halving++; flag[2]++; + for (i=0; i>= + +flag[0] = rank; +loglik[1] = newlk; +chinv2(imat, nvar); +for (i=0; i>= +survfit.coxph <- + function(formula, newdata, se.fit=TRUE, conf.int=.95, individual=FALSE, + stype=2, ctype, + conf.type=c("log", "log-log", "plain", "none", "logit", "arcsin"), + censor=TRUE, start.time, id, influence=FALSE, + na.action=na.pass, type, ...) { + + Call <- match.call() + Call[[1]] <- as.name("survfit") #nicer output for the user + object <- formula #'formula' because it has to match survfit + + <> + <> + <> + <> + <> + if (missing(newdata)) { + if (inherits(formula, "coxphms")) + stop ("newdata is required for multi-state models") + risk2 <- 1 + } + else { + if (length(object$means)) + risk2 <- exp(c(x2 %*% beta) + offset2 - xcenter) + else risk2 <- exp(offset2 - xcenter) + } + <> + <> + } +@ +The third line \code{as.name('survfit')} causes the printout to say +`survfit' instead of `survfit.coxph'. %' + +The setup for the has three main phases, first of course to sort out the +options the user has given us, second to rebuild the +data frame, X matrix, etc from the original Cox model, and third to +create variables from the new data set. +In the code below x2, y2, strata2, id2, etc. are variables from the +new data, X, Y, strata etc from the old. One exception to the pattern +is id= argument, oldid = id from original data, id2 = id from new. + +If the newdata argument is missing we use \code{object\$means} as the +default value. This choice has lots of statistical shortcomings, +particularly in a stratified model, but is common in other +packages and a historic option here. +If stype is missing we use the standard approach of exp(cumulative hazard), +and ctype is pulled from the Cox model. +That is, the \code{coxph} computation used for \code{ties='breslow'} is +the same as the Nelson-Aalen hazard estimate, and +the Efron approximation the tie-corrected hazard. + +One particular special case (that gave me fits for a while) is when there +are non-heirarchical models, for example \code{~ age + age:sex}. +The fit of such a model will \emph{not} be the same using the variable +\code{age2 <- age-50}; I originally thought it was a flaw induced by my +subtraction. +The routine simply cannot give a sensible curve for a model like this. +The issue continued to surprise me each time I rediscovered it, +leading to an error message for my own protection. I'm +not convinced at this time that there is a sensible survival curve +that \emph{could} be calculated for such a model. +A model with \code{age + age:strata(sex)} will be ok, because the +coxph routine treats this last term as though it had a * in it, i.e., +fits a stratified model. + +<>= +Terms <- terms(object) +robust <- !is.null(object$naive.var) # did the coxph model use robust var? + +if (!is.null(attr(object$terms, "specials")$tt)) + stop("The survfit function can not process coxph models with a tt term") + +if (!missing(type)) { # old style argument + if (!missing(stype) || !missing(ctype)) + warning("type argument ignored") + else { + temp1 <- c("kalbfleisch-prentice", "aalen", "efron", + "kaplan-meier", "breslow", "fleming-harrington", + "greenwood", "tsiatis", "exact") + + survtype <- match(match.arg(type, temp1), temp1) + stype <- c(1,2,2,1,2,2,2,2,2)[survtype] + if (stype!=1) ctype <-c(1,1,2,1,1,2,1,1,1)[survtype] + } +} +if (missing(ctype)) { + # Use the appropriate one from the model + temp1 <- match(object$method, c("exact", "breslow", "efron")) + ctype <- c(1,1,2)[temp1] +} +else if (!(ctype %in% 1:2)) stop ("ctype must be 1 or 2") +if (!(stype %in% 1:2)) stop("stype must be 1 or 2") + +if (!se.fit) conf.type <- "none" +else conf.type <- match.arg(conf.type) + +tfac <- attr(Terms, 'factors') +temp <- attr(Terms, 'specials')$strata +has.strata <- !is.null(temp) +if (has.strata) { + stangle = untangle.specials(Terms, "strata") #used multiple times, later + # Toss out strata terms in tfac before doing the test 1 line below, as + # strata end up in the model with age:strat(grp) terms or *strata() terms + # (There might be more than one strata term) + for (i in temp) tfac <- tfac[,tfac[i,] ==0] # toss out strata terms +} +if (any(tfac >1)) + stop("not able to create a curve for models that contain an interaction without the lower order effect") + +Terms <- object$terms +n <- object$n[1] +if (!has.strata) strata <- NULL +else strata <- object$strata + +if (!missing(individual)) warning("the `id' option supersedes `individual'") +missid <- missing(id) # I need this later, and setting id below makes + # "missing(id)" always false + +if (!missid) individual <- TRUE +else if (missid && individual) id <- rep(0L,n) #dummy value +else id <- NULL + +if (individual & missing(newdata)) { + stop("the id option only makes sense with new data") +} +@ + +In two places below we need to know if there are strata by covariate +interactions, which requires looking at attributes of the terms +object. +The factors attribute will have a row for the strata variable, or +maybe more than one (multiple strata terms are legal). If it has +a 1 in a column that corresponds to something of order 2 or +greater, that is a strata by covariate interaction. +<>= +if (has.strata) { + temp <- attr(Terms, "specials")$strata + factors <- attr(Terms, "factors")[temp,] + strata.interaction <- any(t(factors)*attr(Terms, "order") >1) +} +@ + + +I need to retrieve a copy of the original data. +We always need the $X$ matrix and $y$, both of which might be found in +the data object. +If the fit was a multistate model, +the original call included either strata, offset, weights, or id, +or if either $x$ or $y$ are missing from the \code{coxph} object, +then the model frame will need to be reconstructed. +We have to use \code{object['x'}] instead of \texttt{object\$x} since +the latter will +pick off the \code{xlevels} component if the \code{x} component is missing +(which is the default). +<>= +coxms <- inherits(object, "coxphms") +if (coxms || is.null(object$y) || is.null(object[['x']]) || + !is.null(object$call$weights) || !is.null(object$call$id) || + (has.strata && is.null(object$strata)) || + !is.null(attr(object$terms, 'offset'))) { + + mf <- stats::model.frame(object) + } +else mf <- NULL #useful for if statements later +@ + +For a single state model we can grab +the X matrix off the model frame, for multistate some more work +needs to be done. +We have to repeat some lines from coxph, but to do that we need some +further material. +We prefer \code{object\$y} to model.response, since the former will have been +passed through aeqSurv with the options the user specified. +For a multi-state model, however, we do have to recreate since the +saved y has been expanded. +In that case observe the saved status of timefix. Old saved objects +might not have that element, if missing assume TRUE. + +<>= +position <- NULL +Y <- object[['y']] +if (is.null(mf)) { + weights <- object$weights # let offsets/weights be NULL until needed + offset <- NULL + X <- object[['x']] +} +else { + weights <- model.weights(mf) + offset <- model.offset(mf) + X <- model.matrix.coxph(object, data=mf) + if (is.null(Y) || coxms) { + Y <- model.response(mf) + if (is.null(object$timefix) || object$timefix) Y <- aeqSurv(Y) + } + oldid <- model.extract(mf, "id") + if (length(oldid) && ncol(Y)==3) position <- survflag(Y, oldid) + else position <- NULL + if (!coxms && (nrow(Y) != object$n[1])) + stop("Failed to reconstruct the original data set") + if (has.strata) { + if (length(strata)==0) { + if (length(stangle$vars) ==1) strata <- mf[[stangle$vars]] + else strata <- strata(mf[, stangle$vars], shortlabel=TRUE) + } + } + +} +@ + +If a model frame was created, then it is trivial to grab \code{y} +from the new frame and compare it to \code{object\$y} from the +original one. This is to avoid nonsense results that arise +when someone changes the data set under our feet. +We can only check the size: with the addition of aeqSurv other packages +were being flagged for tiny discrepancies. +Later note: this check does not work for multi-state models, and we don't +\emph{have} to have it. Removed by using if (FALSE) so as to preserve +the code for future consideration. +<>= +if (FALSE) { +if (!is.null(mf)){ + y2 <- object[['y']] + if (!is.null(y2)) { + if (ncol(y2) != ncol(Y) || length(y2) != length(Y)) + stop("Could not reconstruct the y vector") + } +} +} +type <- attr(Y, 'type') +if (!type %in% c("right", "counting", "mright", "mcounting")) + stop("Cannot handle \"", type, "\" type survival data") + +if (!missing(start.time)) { + if (!is.numeric(start.time) || length(start.time) > 1) + stop("start.time must be a single numeric value") + # Start the curves after start.time + # To do so, remove any rows of the data with an endpoint before that + # time. + if (ncol(Y)==3) { + keep <- Y[,2] > start.time + Y[keep,1] <- pmax(Y[keep,1], start.time) + } + else keep <- Y[,1] > start.time + if (!any(Y[keep, ncol(Y)]==1)) + stop("start.time argument has removed all endpoints") + Y <- Y[keep,,drop=FALSE] + X <- X[keep,,drop=FALSE] + if (!is.null(offset)) offset <- offset[keep] + if (!is.null(weights)) weights <- weights[keep] + if (!is.null(strata)) strata <- strata[keep] + if (length(id) >0 ) id <- id[keep] + if (length(position) >0) position <- position[keep] + n <- nrow(Y) +} +@ + +In the above code we see id twice. The first, kept as \code{oldid} is the +identifier variable for subjects in the original data set, and is needed +whenever it contained subjects with more than one row. +The second is the user variable of this call, and is used to define multiple +rows for a new subject. The latter usage should be rare but we need to +allow for it. + +If a variable is deemed redundant the \code{coxph} routine will have set its +coefficient to NA as a marker. +We want to ignore that coefficient: treating it as a zero has the +desired effect. +Another special case is a null model, having either ~1 or only an offset +on the right hand side. In that case we create a dummy covariate to +allow the rest of the code to work without special if/else. +The last special case is a model with a sparse frailty term. We treat +the frailty coefficients as 0 variance (in essence as an offset). +The frailty is removed from the model variables but kept in the risk score. +This isn't statistically very defensible, but it is backwards compatatble. %' +A non-sparse frailty does not need special code and works out like any +other variable. + +Center the risk scores by subtracting $ \overline x \hat\beta$ from each. +The reason for this is to avoid huge values when calculating $\exp(X\beta)$; +this would happen if someone had a variable with a mean of 1000 and a +variance of 1. +Any constant can be subtracted, mathematically the results are identical as long +as the same values are subtracted from the old and new $X$ data. +The mean is used because it is handy, we just need to get $X\beta$ in the +neighborhood of zero. + +<>= +if (length(object$means) ==0) { # a model with only an offset term + # Give it a dummy X so the rest of the code goes through + # (This case is really rare) + # se.fit <- FALSE + X <- matrix(0., nrow=n, ncol=1) + if (is.null(offset)) offset <- rep(0, n) + xcenter <- mean(offset) + coef <- 0.0 + varmat <- matrix(0.0, 1, 1) + risk <- rep(exp(offset- mean(offset)), length=n) +} +else { + varmat <- object$var + beta <- ifelse(is.na(object$coefficients), 0, object$coefficients) + if (is.null(offset)) xcenter <- sum(object$means * beta) + else xcenter <- sum(object$means * beta)+ mean(offset) + if (!is.null(object$frail)) { + keep <- !grepl("frailty(", dimnames(X)[[2]], fixed=TRUE) + X <- X[,keep, drop=F] + } + + if (is.null(offset)) risk <- c(exp(X%*% beta - xcenter)) + else risk <- c(exp(X%*% beta + offset - xcenter)) +} +@ + +The \code{risk} vector and \code{x} matrix come from the original data, and are +the raw data for the survival curve and its variance. +We also need the risk score $\exp(X\beta)$ for the target subject(s). +\begin{itemize} + \item For predictions with time-dependent covariates the user will have + either included an \code{id} statement (newer style) or specified the + \code{individual=TRUE} option. If the latter, then \code{newdata} is + presumed to contain only a single indivual represented by multiple + rows. If the former then the \code{id} variable marks separate individuals. + In either case we need to retrieve + the covariates, strata, and repsonse from the new data set. + \item For ordinary predictions only the covariates are needed. + \item If newdata is not present we assume that this is the ordinary case, and + use the value of \code{object\$means} as the default covariate set. This is + not ideal statistically since many users view this as an + ``average'' survival curve, which it is not. +\end{itemize} + +When grabbing [newdata] we want to use model.frame processing, both to +handle missing values correctly and, perhaps more importantly, to correctly +map any factor variables between the original fit and the new data. (The +new data will often have only one of the original levels represented.) +Also, we want to correctly handle data-dependent nonlinear terms such as +ns and pspline. +However, the simple call found in predict.lm, say, +\code{model.frame(Terms, data=newdata, ..} isn't used here +for a few reasons. +The first is a decision on our part that the user should not have +to include unused terms in the newdata: sometimes we don't need the +response and sometimes we do. +Second, if there are strata, the user may or may not +have included strata variables in their data set and we need to +act accordingly. +The third is that we might have an \code{id} statement in this +call, which is another variable to be fetched. +At one time we dealt with cluster() terms in the formula, but the coxph +routine has already removed those for us. +Finally, note that there is no ability to use sparse frailties and newdata together; +it is a hard case and so rare as to not be worth it. + +First, remove unnecessary terms from the orginal model formula. +If \code{individual} is false then the repsonse variable can go. + +The dataClasses and predvars attributes, if present, have elements +in the same order as the first dimension of the ``factors'' attribute +of the terms. +Subscripting the terms argument does not preserve dataClasses or +predvars, however. Use the pre and post subscripting factors attribute +to determine what elements of them to keep. +The predvars component is a call objects with one element for each +term in the formula, so y ~ age + ns(height) would lead to a predvars +of length 4, element 1 is the call itself, 2 would be y, etc. +The dataClasses object is a simple list. + +<>= +if (missing(newdata)) { + # If the model has interactions, print out a long warning message. + # People may hate it, but I don't see another way to stamp out these + # bad curves without backwards-incompatability. + # I probably should complain about factors too (but never in a strata + # or cluster term). + if (any(attr(Terms, "order") > 1) ) + warning("the model contains interactions; the default curve based on columm means of the X matrix is almost certainly not useful. Consider adding a newdata argument.") + + if (length(object$means)) { + mf2 <- as.list(object$means) #create a dummy newdata + names(mf2) <- names(object$coefficients) + mf2 <- as.data.frame(mf2) + x2 <- matrix(object$means, 1) + } + else { # nothing but an offset + mf2 <- data.frame(X=0) + x2 <- 0 + } + offset2 <- 0 + found.strata <- FALSE +} +else { + if (!is.null(object$frail)) + stop("Newdata cannot be used when a model has frailty terms") + + Terms2 <- Terms + if (!individual) Terms2 <- delete.response(Terms) + <> +} +@ + +For backwards compatability, I allow someone to give an ordinary vector +instead of a data frame (when only one curve is required). In this case +I also need to verify that the elements have a name. +Then turn it into a data frame, like it should have been from the beginning. +(Documentation of this ability has been suppressed, however. I'm hoping +people forget it ever existed.) +<>= +if (is.vector(newdata, "numeric")) { + if (individual) stop("newdata must be a data frame") + if (is.null(names(newdata))) { + stop("Newdata argument must be a data frame") + } + newdata <- data.frame(as.list(newdata), stringsAsFactors=FALSE) +} +@ + +Finally get my new model frame mf2. +We allow the +user to leave out any strata() variables if they so desire, +\emph{if} there are no strata by covariate interactions. + +How does one check if the strata variables are or are not available in +the call? +My first attempt at this was to wrap the call in a try() construct and +see if it failed. This doesn't work. +\begin{itemize} + \item What if there is no strata variable in newdata, but they do have, + by bad luck, a variable of the same name in their main directory? + \item It would seem like changing the environment to NULL would be wise, + so that we don't find variables anywhere but in the data argument, + a sort of sandboxing. Not wise: you then won't find functions like ``log''. + \item We don't dare modify the environment of the formula at all. + It is needed for the sneaky caller who uses his own function + inside the formula, 'mycosine' say, and that function can only be + found if we retain the environment. +\end{itemize} +One way out of this is to evaluate each of the strata terms +(there can be more than one) one at a time, in an environment that knows +nothing except "list" and a fake definition of "strata", and newdata. +Variables that are part of the global environment won't be found. +I even watch out for the case of either "strata" or "list" is the name of +the stratification variable, which causes my fake strata function to +return a function when said variable is not in newdata. The +variable found.strata is true if ALL the strata are found, set it to +false if any are missing. + +<>= +if (has.strata) { + found.strata <- TRUE + tempenv <- new.env(, parent=emptyenv()) + assign("strata", function(..., na.group, shortlabel, sep) + list(...), envir=tempenv) + assign("list", list, envir=tempenv) + for (svar in stangle$vars) { + temp <- try(eval(parse(text=svar), newdata, tempenv), + silent=TRUE) + if (!is.list(temp) || + any(unlist(lapply(temp, class))== "function")) + found.strata <- FALSE + } + + if (!found.strata) { + ss <- untangle.specials(Terms2, "strata") + Terms2 <- Terms2[-ss$terms] + } +} + +tcall <- Call[c(1, match(c('id', "na.action"), + names(Call), nomatch=0))] +tcall$data <- newdata +tcall$formula <- Terms2 +tcall$xlev <- object$xlevels[match(attr(Terms2,'term.labels'), + names(object$xlevels), nomatch=0)] +tcall[[1L]] <- quote(stats::model.frame) +mf2 <- eval(tcall) +@ + +Now, finally, extract the \code{x2} matrix from the just-created frame. +<>= +if (has.strata && found.strata) { #pull them off + temp <- untangle.specials(Terms2, 'strata') + strata2 <- strata(mf2[temp$vars], shortlabel=TRUE) + strata2 <- factor(strata2, levels=levels(strata)) + if (any(is.na(strata2))) + stop("New data set has strata levels not found in the original") + # An expression like age:strata(sex) will have temp$vars= "strata(sex)" + # and temp$terms = integer(0). This does not work as a subscript + if (length(temp$terms) >0) Terms2 <- Terms2[-temp$terms] +} +else strata2 <- factor(rep(0, nrow(mf2))) + +if (!robust) cluster <- NULL +if (individual) { + if (missing(newdata)) + stop("The newdata argument must be present when individual=TRUE") + if (!missid) { #grab the id variable + id2 <- model.extract(mf2, "id") + if (is.null(id2)) stop("id=NULL is an invalid argument") + } + else id2 <- rep(1, nrow(mf2)) + + x2 <- model.matrix(Terms2, mf2)[,-1, drop=FALSE] #no intercept + if (length(x2)==0) stop("Individual survival but no variables") + + offset2 <- model.offset(mf2) + if (length(offset2) ==0) offset2 <- 0 + + y2 <- model.extract(mf2, 'response') + if (attr(y2,'type') != type) + stop("Survival type of newdata does not match the fitted model") + if (attr(y2, "type") != "counting") + stop("Individual=TRUE is only valid for counting process data") + y2 <- y2[,1:2, drop=F] #throw away status, it's never used +} +else if (missing(newdata)) { + if (has.strata && strata.interaction) + stop ("Models with strata by covariate interaction terms require newdata") + offset2 <- 0 + if (length(object$means)) { + x2 <- matrix(object$means, nrow=1, ncol=ncol(X)) + } else { + # model with only an offset and no new data: very rare case + x2 <- matrix(0.0, nrow=1, ncol=1) # make a dummy x2 + } +} else { + offset2 <- model.offset(mf2) + if (length(offset2) >0) offset2 <- offset2 + else offset2 <- 0 + x2 <- model.matrix(Terms2, mf2)[,-1, drop=FALSE] #no intercept +} +@ + +<>= +if (individual) { + result <- coxsurv.fit(ctype, stype, se.fit, varmat, cluster, + Y, X, weights, risk, position, strata, oldid, + y2, x2, risk2, strata2, id2) +} +else { + result <- coxsurv.fit(ctype, stype, se.fit, varmat, cluster, + Y, X, weights, risk, position, strata, oldid, + y2, x2, risk2) + if (has.strata && found.strata) { + if (is.matrix(result$surv)) { + <> + } + } +} +@ + +The final bit of work. If the newdata arg contained strata then the +user should not get a matrix of survival curves containing +every newdata obs * strata combination, but rather a vector +of curves, each one with the appropriate strata. +It was faster to compute them all, however, than to use the individual=T +logic. So now pick off the bits we want. +The names of the curves will be the rownames of the newdata arg, +if they exist. +<>= +nr <- nrow(result$surv) #a vector if newdata had only 1 row +indx1 <- split(1:nr, rep(1:length(result$strata), result$strata)) +rows <- indx1[as.numeric(strata2)] #the rows for each curve + +indx2 <- unlist(rows) #index for time, n.risk, n.event, n.censor +indx3 <- as.integer(strata2) #index for n and strata + +for(i in 2:length(rows)) rows[[i]] <- rows[[i]]+ (i-1)*nr #linear subscript +indx4 <- unlist(rows) #index for surv and std.err +temp <- result$strata[indx3] +names(temp) <- row.names(mf2) +new <- list(n = result$n[indx3], + time= result$time[indx2], + n.risk= result$n.risk[indx2], + n.event=result$n.event[indx2], + n.censor=result$n.censor[indx2], + strata = temp, + surv= result$surv[indx4], + cumhaz = result$cumhaz[indx4]) +if (se.fit) new$std.err <- result$std.err[indx4] +result <- new +@ + +Finally, the last (somewhat boring) part of the code. +First, if given the argument \code{censor=FALSE} we need to +remove all the time points from the output at which there +was only censoring activity. This action is mostly for +backwards compatability with older releases that never +returned censoring times. +Second, add +in the variance and the confidence intervals to the result. +The code is nearly identical to that in survfitKM. +<>= +if (!censor) { + kfun <- function(x, keep){ if (is.matrix(x)) x[keep,,drop=F] + else if (length(x)==length(keep)) x[keep] + else x} + keep <- (result$n.event > 0) + if (!is.null(result$strata)) { + temp <- factor(rep(names(result$strata), result$strata), + levels=names(result$strata)) + result$strata <- c(table(temp[keep])) + } + result <- lapply(result, kfun, keep) + } +result$logse = TRUE # this will migrate further in + +if (se.fit && conf.type != "none") { + ci <- survfit_confint(result$surv, result$std.err, logse=result$logse, + conf.type, conf.int) + result <- c(result, list(lower=ci$lower, upper=ci$upper, + conf.type=conf.type, conf.int=conf.int)) +} + +if (!missing(start.time)) result$start.time <- start.time + +result$call <- Call +class(result) <- c('survfitcox', 'survfit') +result +@ +% +% Second part of coxsurv.Rnw, broken in two to make it easier for me +% to work with emacs. +Now, we're ready to do the main compuation. %' +The code has gone through multiple iteration as options and complexity +increased. + +Computations are separate for each strata, and each strata will +have a different number of time points in the result. +Thus we can't preallocate a matrix. Instead we generate an empty list, %' +one per strata, and then populate it with the survival curves. +At the end we unlist the individual components one by one. +This is memory efficient, the number +of curves is usually small enough that the "for" loop is no great +cost, and it's easier to see what's going on than C code. +The computational exception is a model with thousands of strata, e.g., a matched +logistic, but in that case survival curves are useless. +(That won't stop some users from trying it though.) + +First, compute the baseline survival curves for each strata. If the strata +was a factor produce output curves in that order, otherwise in sorted order. +This fitting routine was set out as a separate function for the sake of the rms +package. They want to utilize the computation, but have a diffferent +process to create the x and y data. +<>= +coxsurv.fit <- function(ctype, stype, se.fit, varmat, cluster, + y, x, wt, risk, position, strata, oldid, + y2, x2, risk2, strata2, id2, unlist=TRUE) { + + if (missing(strata) || length(strata)==0) strata <- rep(0L, nrow(y)) + + if (is.factor(strata)) ustrata <- levels(strata) + else ustrata <- sort(unique(strata)) + nstrata <- length(ustrata) + survlist <- vector('list', nstrata) + names(survlist) <- ustrata + survtype <- if (stype==1) 1 else ctype+1 + vartype <- survtype + if (is.null(wt)) wt <- rep(1.0, nrow(y)) + if (is.null(strata)) strata <- rep(1L, nrow(y)) + for (i in 1:nstrata) { + indx <- which(strata== ustrata[i]) + survlist[[i]] <- agsurv(y[indx,,drop=F], x[indx,,drop=F], + wt[indx], risk[indx], + survtype, vartype) + } + <> + + if (unlist) { + if (length(result)==1) { # the no strata case + if (se.fit) + result[[1]][c("n", "time", "n.risk", "n.event", "n.censor", + "surv", "cumhaz", "std.err")] + else result[[1]][c("n", "time", "n.risk", "n.event", "n.censor", + "surv", "cumhaz")] + } + else { + <> + } + } + else { + names(result) <- ustrata + result + } +} +@ + +In an ordinary survival curve object with multiple strata, as produced by +\code{survfitKM}, the time, survival and etc components are each a +single vector that contains the results for strata 1, followed by +strata 2, \ldots. The strata compontent is a vector of integers, one +per strata, that gives the number of elements belonging to each stratum. +The reason is that each strata will have a different number of observations, +so that a matrix form was not viable, and the underlying C routines were +not capable of handling lists (the code predates the .Call function by +a decade). +The underlying computation of \code{survfitcoxph.fit} naturally creates the list +form, we unlist it to \code{survfit} form as our last action unless the +caller requests otherwise. + +<>= +temp <-list(n = unlist(lapply(result, function(x) x$n), + use.names=FALSE), + time= unlist(lapply(result, function(x) x$time), + use.names=FALSE), + n.risk= unlist(lapply(result, function(x) x$n.risk), + use.names=FALSE), + n.event= unlist(lapply(result, function(x) x$n.event), + use.names=FALSE), + n.censor=unlist(lapply(result, function(x) x$n.censor), + use.names=FALSE), + strata = sapply(result, function(x) length(x$time))) +names(temp$strata) <- names(result) + +if ((missing(id2) || is.null(id2)) && nrow(x2)>1) { + temp$surv <- t(matrix(unlist(lapply(result, + function(x) t(x$surv)), use.names=FALSE), + nrow= nrow(x2))) + dimnames(temp$surv) <- list(NULL, row.names(x2)) + temp$cumhaz <- t(matrix(unlist(lapply(result, + function(x) t(x$cumhaz)), use.names=FALSE), + nrow= nrow(x2))) + if (se.fit) + temp$std.err <- t(matrix(unlist(lapply(result, + function(x) t(x$std.err)), use.names=FALSE), + nrow= nrow(x2))) + } +else { + temp$surv <- unlist(lapply(result, function(x) x$surv), + use.names=FALSE) + temp$cumhaz <- unlist(lapply(result, function(x) x$cumhaz), + use.names=FALSE) + if (se.fit) + temp$std.err <- unlist(lapply(result, + function(x) x$std.err), use.names=FALSE) + } +temp +@ + +For \code{individual=FALSE} we have a second dimension, namely each of the +target covariate sets (if there are multiples). Each of these generates +a unique set of survival and variance(survival) values, but all of the +same size since each uses all the strata. The final output structure in +this case has single vectors for the time, number of events, number censored, +and number at risk values since they are common to all the curves, and a +matrix of +survival and variance estimates, one column for each of the +distinct target values. +If $\Lambda_0$ is the baseline cumulative hazard from the +above calculation, then $r_i \Lambda_0$ is the cumulative +hazard for the $i$th new risk score $r_i$. +The variance has two parts, the first of which is $r_i^2 H_1$ where +$H_1$ is returned from the \code{agsurv} routine, and the second is +\begin{align*} + H_2(t) =& d'(t) V d(t) \\ %' + d(t) = \int_0^t [z- \overline x(s)] d\Lambda(s) +\end{align*} +$V$ is the variance matrix for $\beta$ from the fitted Cox +model, and $d(t)$ is the distance between the +target covariate $z$ and the mean of the original data, +summed up over the interval from 0 to $t$. +Essentially the variance in $\hat \beta$ has a larger influence +when prediction is far from the mean. +The function below takes the basic curve from the list and multiplies +it out to matrix form. +<>= +expand <- function(fit, x2, varmat, se.fit) { + if (survtype==1) + surv <- cumprod(fit$surv) + else surv <- exp(-fit$cumhaz) + + if (is.matrix(x2) && nrow(x2) >1) { #more than 1 row in newdata + fit$surv <- outer(surv, risk2, '^') + dimnames(fit$surv) <- list(NULL, row.names(x2)) + if (se.fit) { + varh <- matrix(0., nrow=length(fit$varhaz), ncol=nrow(x2)) + for (i in 1:nrow(x2)) { + dt <- outer(fit$cumhaz, x2[i,], '*') - fit$xbar + varh[,i] <- (cumsum(fit$varhaz) + rowSums((dt %*% varmat)* dt))* + risk2[i]^2 + } + fit$std.err <- sqrt(varh) + } + fit$cumhaz <- outer(fit$cumhaz, risk2, '*') + } + else { + fit$surv <- surv^risk2 + if (se.fit) { + dt <- outer(fit$cumhaz, c(x2)) - fit$xbar + varh <- (cumsum(fit$varhaz) + rowSums((dt %*% varmat)* dt)) * + risk2^2 + fit$std.err <- sqrt(varh) + } + fit$cumhaz <- fit$cumhaz * risk2 + } + fit + } +@ +In the lines just above: I have a matrix \code{dt} with one row per death +time and one column per variable. For each row $d_i$ separately we +want the quadratic form $d_i V d_i'$. The first matrix product can %' +be done for all rows at once: found in the inner parenthesis. +Ordinary (not matrix) multiplication followed by rowsums does the rest +in one fell swoop. + +Now, if \code{id2} is missing we can simply apply the \code{expand} function +to each strata. +For the case with \code{id2} not missing, we create a single survival +curve for each unique id (subject). +A subject will spend blocks of time with different covariate sets, +sometimes even jumping between strata. Retrieve each one and save it into +a list, and then sew them together end to end. +The \code{n} component is the number of observations in the strata --- but this +subject might visit several. We report the first one they were in for +printout. +The \code{time} component will be cumulative on this subject's scale. %' +Counting this is a bit trickier than I first thought. Say that the +subject's first interval goes from 1 to 10, with observed time points in +that interval at 2, 5, and 7, and a second interval from 12 to 20 with +observed time points in the data of 15 and 18. On the subject's time +scale things happen at days 1, 4, 6, 12 and 15. The deltas saved below +are 2-1, 5-2, 7-5, 3+ 14-12, 17-14. Note the 3+ part, kept +in the \code{timeforward} variable. +Why all this ``adding up'' nuisance? If the subject spent time in two +strata, the second one might be on an internal time scale of `time since +entering the strata'. The two intervals in newdata could be 0--10 followed +by 0--20. Time for the subject can't go backwards though: the change %` +between internal/external time scales is a bit like following someone who +was stepping back and forth over the international date line. + +In the code the \code{indx} variable points to the set of times that the +subject was present, for this row of the new data. Note the $>$ on +one end and $\le$ on the other. If someone's interval 1 was 0--10 and +interval 2 was 10--20, and there happened to be a jump in the baseline +survival curve at exactly time 10 (someone else died), +that jump is counted only in the first interval. +<>= +if (missing(id2) || is.null(id2)) + result <- lapply(survlist, expand, x2, varmat, se.fit) +else { + onecurve <- function(slist, x2, y2, strata2, risk2, se.fit) { + ntarget <- nrow(x2) #number of different time intervals + surv <- vector('list', ntarget) + n.event <- n.risk <- n.censor <- varh1 <- varh2 <- time <- surv + hazard <- vector('list', ntarget) + stemp <- as.integer(strata2) + timeforward <- 0 + for (i in 1:ntarget) { + slist <- survlist[[stemp[i]]] + indx <- which(slist$time > y2[i,1] & slist$time <= y2[i,2]) + if (length(indx)==0) { + timeforward <- timeforward + y2[i,2] - y2[i,1] + # No deaths or censors in user interval. Possible + # user error, but not uncommon at the tail of the curve. + } + else { + time[[i]] <- diff(c(y2[i,1], slist$time[indx])) #time increments + time[[i]][1] <- time[[i]][1] + timeforward + timeforward <- y2[i,2] - max(slist$time[indx]) + + hazard[[i]] <- slist$hazard[indx]*risk2[i] + if (survtype==1) surv[[i]] <- slist$surv[indx]^risk2[i] + + n.event[[i]] <- slist$n.event[indx] + n.risk[[i]] <- slist$n.risk[indx] + n.censor[[i]]<- slist$n.censor[indx] + dt <- outer(slist$cumhaz[indx], x2[i,]) - slist$xbar[indx,,drop=F] + varh1[[i]] <- slist$varhaz[indx] *risk2[i]^2 + varh2[[i]] <- rowSums((dt %*% varmat)* dt) * risk2[i]^2 + } + } + + cumhaz <- cumsum(unlist(hazard)) + if (survtype==1) surv <- cumprod(unlist(surv)) #increments (K-M) + else surv <- exp(-cumhaz) + + if (se.fit) + list(n=as.vector(table(strata)[stemp[1]]), + time=cumsum(unlist(time)), + n.risk = unlist(n.risk), + n.event= unlist(n.event), + n.censor= unlist(n.censor), + surv = surv, + cumhaz= cumhaz, + std.err = sqrt(cumsum(unlist(varh1)) + unlist(varh2))) + else list(n=as.vector(table(strata)[stemp[1]]), + time=cumsum(unlist(time)), + n.risk = unlist(n.risk), + n.event= unlist(n.event), + n.censor= unlist(n.censor), + surv = surv, + cumhaz= cumhaz) + } + + if (all(id2 ==id2[1])) { + result <- list(onecurve(survlist, x2, y2, strata2, risk2, se.fit)) + } + else { + uid <- unique(id2) + result <- vector('list', length=length(uid)) + for (i in 1:length(uid)) { + indx <- which(id2==uid[i]) + result[[i]] <- onecurve(survlist, x2[indx,,drop=FALSE], + y2[indx,,drop=FALSE], + strata2[indx], risk2[indx], se.fit) + } + names(result) <- uid + } +} +@ + +Next is the code for the \code{agsurv} function, which actually does the work. +The estimates of survival are the Kalbfleisch-Prentice (KP), Breslow, and +Efron. Each has an increment at each unique death time. +First a bit of notation: +$Y_i(t)$ is 1 if bservation $i$ is ``at risk'' at time $t$ and 0 otherwise. +For a simple surivival (\code{ncol(y)==2}) a subject is at risk until the +time of censoring or death (first column of \code{y}). +For (start, stop] data (\code{ncol(y)==3}) a subject becomes a +part of the risk set at start+0 and stays through stop. +$dN_i(t)$ will be 1 if subject $i$ had an event at time $t$. +The risk score for each subject is $r_i = \exp(X_i \beta)$. + +The Breslow increment at time $t$ is $\sum w_i dN_i(t) / \sum w_i r_i Y_i(t)$, +the number of events at time $t$ over the number at risk at time $t$. +The final survival is \code{exp(-cumsum(increment))}. + +The Kalbfleish-Prentice increment is a multiplicative term $z$ +which is the solution to the equation +$$ +\sum w_i r_i Y_i(t) = \sum dN_i(t) w_i \frac{r_i}{1- z(t)^{r_i}} +$$ +The left hand side is the weighted number at risk at time $t$, the +right hand side is a sum over the tied events at that time. +If there is only one event the equation has a closed form solution. +If not, and knowing the solution must lie between 0 and 1, we do +35 steps of bisection to get a solution within 1e-8. +An alternative is to use the -log of the Breslow estimate as a starting +estimate, which is faster but requires a more sophisticated iteration logic. +The final curve is $\prod_t z(t)^{r_c}$ where $r_c$ is the risk score +for the target subject. + +The Efron estimate can be viewed as a modified Breslow estimate under the +assumption that tied deaths are not really tied -- we just don't know the %' +order. So if there are 3 subjects who die at some time $t$ we will have +three psuedo-terms for $t$, $t+\epsilon$, and $t+ 2\epsilon$. All 3 subjects +are present for the denominator of the first term, 2/3 of each for the second, +and 1/3 for the third terms denominator. All contribute 1/3 of the weight +to each numerator (1/3 chance they were the one to die there). The formulas +will require $\sum w_i dN_i(t)$, $\sum w_ir_i dN_i(t)$, and $\sum w_i X_i +dN_i(t)$, i.e., the sums only over the deaths. + +For simple survival data the risk sum $\sum w_i r_i Y_i(t)$ for all +the unique death times $t$ is fast to compute as a cumulative sum, starting +at the longest followup time and summing towards the shortest. +There are two algorithms for (start, stop] data. +\begin{itemize} + \item Do a separate sum at each death time. The problem is for very large + data sets. For each death time the selection \code{(start=t)} + is $O(n)$ and can take more time then all the remaining calculations + together. + \item Use the difference of two cumulative sums, one ordered by start time + and one ordered by stop time. This is $O(2n)$ for the intial sums. The + problem here is potential round off error if the sums get large. + This issue is mostly precluded by subtracting means first, and avoiding + intervals that don't overlap an event time. +\end{itemize} +We compute the extended number still at risk --- all whose stop time +is $\ge$ each unique death time --- in the vector \code{xin}. From +this we have to subtract all those who haven't actually entered yet %' +found in \code{xout}. Remember that (3,20] enters at time 3+. +The total at risk at any time is the difference between them. +Output is only for the +stop times; a call to approx is used to reconcile the two time sets. +The \code{irisk} vector is for the printout, it is a sum of weighted counts +rather than weighted risk scores. +<>= +agsurv <- function(y, x, wt, risk, survtype, vartype) { + nvar <- ncol(as.matrix(x)) + status <- y[,ncol(y)] + dtime <- y[,ncol(y) -1] + death <- (status==1) + + time <- sort(unique(dtime)) + nevent <- as.vector(rowsum(wt*death, dtime)) + ncens <- as.vector(rowsum(wt*(!death), dtime)) + wrisk <- wt*risk + rcumsum <- function(x) rev(cumsum(rev(x))) # sum from last to first + nrisk <- rcumsum(rowsum(wrisk, dtime)) + irisk <- rcumsum(rowsum(wt, dtime)) + if (ncol(y) ==2) { + temp2 <- rowsum(wrisk*x, dtime) + xsum <- apply(temp2, 2, rcumsum) + } + else { + delta <- min(diff(time))/2 + etime <- c(sort(unique(y[,1])), max(y[,1])+delta) #unique entry times + indx <- approx(etime, 1:length(etime), time, method='constant', + rule=2, f=1)$y + esum <- rcumsum(rowsum(wrisk, y[,1])) #not yet entered + nrisk <- nrisk - c(esum,0)[indx] + irisk <- irisk - c(rcumsum(rowsum(wt, y[,1])),0)[indx] + xout <- apply(rowsum(wrisk*x, y[,1]), 2, rcumsum) #not yet entered + xin <- apply(rowsum(wrisk*x, dtime), 2, rcumsum) # dtime or alive + xsum <- xin - (rbind(xout,0))[indx,,drop=F] + } + + ndeath <- rowsum(status, dtime) #unweighted death count +@ + +The KP estimate requires a short C routine to do the iteration +efficiently, and the Efron estimate needs a second C routine to +efficiently compute the partial sums. +<>= + ntime <- length(time) + if (survtype ==1) { #Kalbfleisch-Prentice + indx <- (which(status==1))[order(dtime[status==1])] #deaths + km <- .C(Cagsurv4, + as.integer(ndeath), + as.double(risk[indx]), + as.double(wt[indx]), + as.integer(ntime), + as.double(nrisk), + inc = double(ntime)) + } + + if (survtype==3 || vartype==3) { # Efron approx + xsum2 <- rowsum((wrisk*death) *x, dtime) + erisk <- rowsum(wrisk*death, dtime) #risk score sums at each death + tsum <- .C(Cagsurv5, + as.integer(length(nevent)), + as.integer(nvar), + as.integer(ndeath), + as.double(nrisk), + as.double(erisk), + as.double(xsum), + as.double(xsum2), + sum1 = double(length(nevent)), + sum2 = double(length(nevent)), + xbar = matrix(0., length(nevent), nvar)) + } + haz <- switch(survtype, + nevent/nrisk, + nevent/nrisk, + nevent* tsum$sum1) + varhaz <- switch(vartype, + nevent/(nrisk * + ifelse(nevent>=nrisk, nrisk, nrisk-nevent)), + nevent/nrisk^2, + nevent* tsum$sum2) + xbar <- switch(vartype, + (xsum/nrisk)*haz, + (xsum/nrisk)*haz, + nevent * tsum$xbar) + + result <- list(n= nrow(y), time=time, n.event=nevent, n.risk=irisk, + n.censor=ncens, hazard=haz, + cumhaz=cumsum(haz), varhaz=varhaz, ndeath=ndeath, + xbar=apply(matrix(xbar, ncol=nvar),2, cumsum)) + if (survtype==1) result$surv <- km$inc + result +} +@ + +The arguments to this function are the number of unique times n, which is +the length of the vectors ndeath (number at each time), denom, and the +returned vector km. The risk and wt vectors contain individual values for +the subjects with an event. Their length will be equal to sum(ndeath). +<>= +#include "survS.h" +#include "survproto.h" + +void agsurv4(Sint *ndeath, double *risk, double *wt, + Sint *sn, double *denom, double *km) +{ + int i,j,k, l; + int n; /* number of unique death times */ + double sumt, guess, inc; + + n = *sn; + j =0; + for (i=0; i>= +#include "survS.h" +void agsurv5(Sint *n2, Sint *nvar2, Sint *dd, double *x1, + double *x2, double *xsum, double *xsum2, + double *sum1, double *sum2, double *xbar) { + double temp; + int i,j, k, kk; + double d; + int n, nvar; + + n = n2[0]; + nvar = nvar2[0]; + + for (i=0; i< n; i++) { + d = dd[i]; + if (d==1){ + temp = 1/x1[i]; + sum1[i] = temp; + sum2[i] = temp*temp; + for (k=0; k< nvar; k++) + xbar[i+ n*k] = xsum[i + n*k] * temp*temp; + } + else { + temp = 1/x1[i]; + for (j=0; j>= +survfit.coxphms <- +function(formula, newdata, se.fit=TRUE, conf.int=.95, individual=FALSE, + stype=2, ctype, + conf.type=c("log", "log-log", "plain", "none", "logit", "arcsin"), + censor=TRUE, start.time, id, influence=FALSE, + na.action=na.pass, type, p0=NULL, ...) { + + Call <- match.call() + Call[[1]] <- as.name("survfit") #nicer output for the user + object <- formula #'formula' because it has to match survfit + se.fit <- FALSE #still to do + if (missing(newdata)) + stop("multi-state survival requires a newdata argument") + if (!missing(id)) + stop("using a covariate path is not supported for multi-state") + temp <- object$stratum_map["(Baseline)",] + baselinecoef <- rbind(temp, coef= 1.0) + if (any(duplicated(temp))) { + # We have shared hazards + # Find rows of cmap with "ph(a:b)" type labels to find out which + # ones have proportionality + rname <- rownames(object$cmap) + phbase <- grepl("ph(", rname, fixed=TRUE) + for (i in which(phbase)) { + ctemp <- object$cmap[i,] + index <- which(ctemp >0) + baselinecoef[2, index] <- exp(object$coef[ctemp[index]]) + } + } else phbase <- rep(FALSE, nrow(object$cmap)) + + # process options, set up Y and the model frame, deal with start.time + <> + <> + istate <- model.extract(mf, "istate") + if (!missing(start.time)) { + if (!is.numeric(start.time) || length(start.time) !=1 + || !is.finite(start.time)) + stop("start.time must be a single numeric value") + toss <- which(Y[,ncol(Y)-1] <= start.time) + if (length(toss)) { + n <- nrow(Y) + if (length(toss)==n) stop("start.time has removed all observations") + Y <- Y[-toss,,drop=FALSE] + X <- X[-toss,,drop=FALSE] + weights <- weights[-toss] + oldid <- oldid[-toss] + istate <- istate[-toss] + } + } + + # expansion of the X matrix with stacker, set up shared hazards + <> + + # risk scores, mf2, and x2 + <> + <> + + <> + <> + + cifit$call <- Call + class(cifit) <- c("survfitms", "survfit") + cifit +} +@ +The third line \code{as.name('survfit')} causes the printout to say +`survfit' instead of `survfit.coxph'. %' + +Notice that setup is almost completely shared with survival for single state +models. The major change is that we use survfitCI (non-Cox) to do all the +legwork wrt the tabulation values (number at risk, etc.), +while for the computation proper it is easier to make use of the same +expanded data set that coxph used for a multi-state fit. + +<>= +# Rebuild istate using the survcheck routine +mcheck <- survcheck2(Y, oldid, istate) +transitions <- mcheck$transitions +if (is.null(istate)) istate <- mcheck$istate +if (!identical(object$states, mcheck$states)) + stop("failed to rebuild the data set") + +# Let the survfitCI routine do the work of creating the +# overall counts (n.risk, etc). The rest of this code then +# replaces the surv and hazard components. +if (missing(start.time)) start.time <- min(Y[,2], 0) +# If the data has absorbing states (ones with no transitions out), then +# remove those rows first since they won't be in the final output. +t2 <- transitions[, is.na(match(colnames(transitions), "(censored)")), drop=FALSE] +absorb <- row.names(t2)[rowSums(t2)==0] + +if (is.null(weights)) weights <- rep(1.0, nrow(Y)) +if (is.null(strata)) tempstrat <- rep(1L, nrow(Y)) +else tempstrat <- strata + +if (length(absorb)) droprow <- istate %in% absorb else droprow <- FALSE + +# Let survfitCI fill in the n, number at risk, number of events, etc. portions +# We will replace the pstate and cumhaz estimate with correct ones. +if (any(droprow)) { + j <- which(!droprow) + cifit <- survfitCI(as.factor(tempstrat[j]), Y[j,], weights[j], + id =oldid[j], istate= istate[j], + se.fit=FALSE, start.time=start.time, p0=p0) + } +else cifit <- survfitCI(as.factor(tempstrat), Y, weights, + id= oldid, istate = istate, se.fit=FALSE, + start.time=start.time, p0=p0) + +# For computing the actual estimates it is easier to work with an +# expanded data set. +# Replicate actions found in the coxph-multi-X chunk, +cluster <- model.extract(mf, "cluster") +xstack <- stacker(object$cmap, object$stratum_map, as.integer(istate), X, Y, + as.integer(strata), + states= object$states) +if (length(position) >0) + position <- position[xstack$rindex] # id was required by coxph +X <- xstack$X +Y <- xstack$Y +strata <- strata[xstack$rindex] # strat in the model, other than transitions +transition <- xstack$transition +istrat <- xstack$strata +if (length(offset)) offset <- offset[xstack$rindex] +if (length(weights)) weights <- weights[xstack$rindex] +if (length(cluster)) cluster <- cluster[xstack$rindex] +oldid <- oldid[xstack$rindex] +if (robust & length(cluster)==0) cluster <- oldid +@ + +The survfit.coxph-setup3 chunk, shared with single state Cox models, has created +an mf2 model frame and an x2 matrix. +For multi-state, we ignore any strata variables in mf2. +Create a matrix of risk scores, number of subjects by number of transitions. +Different transitions often have different coefficients, so there is a risk +score vector per transition. + +<>= +if (has.strata && !is.null(mf2[[stangle$vars]])){ + mf2 <- mf2[is.na(match(names(mf2), stangle$vars))] + mf2 <- unique(mf2) + x2 <- unique(x2) +} +temp <- coef(object, matrix=TRUE)[!phbase,,drop=FALSE] # ignore missing coefs +risk2 <- exp(x2 %*% ifelse(is.na(temp), 0, temp) - xcenter) +@ + +At this point we have several parts to keep straight. The data set has been +expanded into a new X and Y. +\begin{itemize} + \item \code{strata} contains any strata that were specified by the user + in the original fit. We do completely separate computations for each + stratum: the time scale starts over, nrisk, etc. Each has a separate + call to the multihaz function. + \item \code{transtion} contains the transition to which each observation + applies + \item \code{istrat} comes from the xstack routine, and marks each + strata * basline hazard combination. + \item \code{baselinecoef} maps from baseline hazards to transitions. It + has one column per transition, which hazard it points to, and a + multiplier. Most multipliers will be 1. + \item \code{hfill} is constructed below. It contains the row/column to which + each column of baselinecoef is mapped, within the H matrix used to compute + P(state). +\end{itemize} +The coxph routine fits all strata and transitions at once, since the loglik is +a sum over strata. This routine does each stratum separately. + +<>= +# make the expansion map. +# The H matrices we will need are nstate by nstate, at each time, with +# elements that are non-zero only for observed transtions. +states <- object$states +nstate <- length(states) +notcens <- (colnames(object$transitions) != "(censored)") +trmat <- object$transitions[, notcens, drop=FALSE] +from <- row(trmat)[trmat>0] +from <- match(rownames(trmat), states)[from] # actual row of H +to <- col(trmat)[trmat>0] +to <- match(colnames(trmat), states)[to] # actual col of H +hfill <- cbind(from, to) + +if (individual) { + stop("time dependent survival curves are not supported for multistate") +} +ny <- ncol(Y) +if (is.null(strata)) { + fit <- multihaz(Y, X, position, weights, risk, istrat, ctype, stype, + baselinecoef, hfill, x2, risk2, varmat, nstate, se.fit, + cifit$p0, cifit$time) + cifit$pstate <- fit$pstate + cifit$cumhaz <- fit$cumhaz +} +else { + if (is.factor(strata)) ustrata <- levels(strata) + else ustrata <- sort(unique(strata)) + nstrata <- length(cifit$strata) + itemp <- rep(1:nstrata, cifit$strata) + timelist <- split(cifit$time, itemp) + ustrata <- names(cifit$strata) + tfit <- vector("list", nstrata) + for (i in 1:nstrata) { + indx <- which(strata== ustrata[i]) # divides the data + tfit[[i]] <- multihaz(Y[indx,,drop=F], X[indx,,drop=F], + position[indx], weights[indx], risk[indx], + istrat[indx], ctype, stype, baselinecoef, hfill, + x2, risk2, varmat, nstate, se.fit, + cifit$p0[i,], timelist[[i]]) + } + + # do.call(rbind) doesn't work for arrays, it loses a dimension + ntime <- length(cifit$time) + cifit$pstate <- array(0., dim=c(ntime, dim(tfit[[1]]$pstate)[2:3])) + cifit$cumhaz <- array(0., dim=c(ntime, dim(tfit[[1]]$cumhaz)[2:3])) + rtemp <- split(seq(along=cifit$time), itemp) + for (i in 1:nstrata) { + cifit$pstate[rtemp[[i]],,] <- tfit[[i]]$pstate + cifit$cumhaz[rtemp[[i]],,] <- tfit[[i]]$cumhaz + } +} +cifit$newdata <- mf2 +@ + +Finally, a routine that does all the actual work. +\begin{itemize} + \item The first 5 variables are for the data set that the Cox model was built + on: y, x, position, risk score, istrat. + Position is a flag for each obs. Is it the first of a connected string + such as (10, 12) (12,19) (19,21), the last of such a string, both, + or neither. 1*first + 2*last. This affects whether an obs is labeled + as censored or not, nothing else. + \item x2 and risk2 are the covariates and risk scores for the predicted + values. These do not involve any ph(a:b) coefficients. + \item baselinecoef and hfill control mapping from fittes hazards to + transitions and probabilities + \item p0 will be NULL if the user did not specifiy it. + \item vmat is only needed for standard errors + \item utime is the set of time points desired +\end{itemize} + + +<>= +# Compute the hazard and survival functions +multihaz <- function(y, x, position, weight, risk, istrat, ctype, stype, + bcoef, hfill, x2, risk2, vmat, nstate, se.fit, p0, utime) { + if (ncol(y) ==2) { + sort1 <- seq.int(0, nrow(y)-1L) # sort order for a constant + y <- cbind(-1.0, y) # add a start.time column, -1 in case + # there is an event at time 0 + } + else sort1 <- order(istrat, y[,1]) -1L + sort2 <- order(istrat, y[,2]) -1L + ntime <- length(utime) + + # this returns all of the counts we might desire. + storage.mode(weight) <- "double" #failsafe + # for Surv(time, status), position is 2 (last) for all obs + if (length(position)==0) position <- rep(2L, nrow(y)) + + fit <- .Call(Ccoxsurv2, utime, y, weight, sort1, sort2, position, + istrat, x, risk) + cn <- fit$count # 1-3 = at risk, 4-6 = events, 7-8 = censored events + # 9-10 = censored, 11-12 = Efron, 13-15 = entry + + if (ctype ==1) { + denom1 <- ifelse(cn[,4]==0, 1, cn[,3]) + denom2 <- ifelse(cn[,4]==0, 1, cn[,3]^2) + } else { + denom1 <- ifelse(cn[,4]==0, 1, cn[,11]) + denom2 <- ifelse(cn[,4]==0, 1, cn[,12]) + } + + temp <- matrix(cn[,5] / denom1, ncol = fit$ntrans) + hazard <- temp[,bcoef[1,]] * rep(bcoef[2,], each=nrow(temp)) + if (se.fit) { + temp <- matrix(cn[,5] / denom2, ncol = fit$ntrans) + varhaz <- temp[,bcoef[1,]] * rep(bcoef[2,]^2, each=nrow(temp)) + } + + # Expand the result, one "hazard set" for each row of x2 + nx2 <- nrow(x2) + h2 <- array(0, dim=c(nrow(hazard), nx2, ncol(hazard))) + if (se.fit) v2 <- h2 + S <- double(nstate) # survival at the current time + S2 <- array(0, dim=c(nrow(hazard), nx2, nstate)) + + H <- matrix(0, nstate, nstate) + if (stype==2) { + H[hfill] <- colMeans(hazard) + diag(H) <- diag(H) -rowSums(H) + esetup <- survexpmsetup(H) + } + + for (i in 1:nx2) { + h2[,i,] <- apply(hazard %*% diag(risk2[i,]), 2, cumsum) + if (se.fit) { + d1 <- fit$xbar - rep(x[i,], each=nrow(fit$xbar)) + d2 <- apply(d1*hazard, 2, cumsum) + d3 <- rowSums((d2%*% vmat) * d2) +# v2[jj,] <- (apply(varhaz[jj,],2, cumsum) + d3) * (risk2[i])^2 + } + + S <- p0 + for (j in 1:ntime) { + H[,] <- 0.0 + H[hfill] <- hazard[j,] *risk2[i,] + if (stype==1) { + diag(H) <- pmax(0, 1.0 - rowSums(H)) + S <- as.vector(S %*% H) # don't keep any names + } + else { + diag(H) <- 0.0 - rowSums(H) + #S <- as.vector(S %*% expm(H)) # dgeMatrix issue + S <- as.vector(S %*% survexpm(H, 1, esetup)) + } + S2[j,i,] <- S + } + } + rval <- list(time=utime, xgrp=rep(1:nx2, each=nrow(hazard)), + pstate=S2, cumhaz=h2) + if (se.fit) rval$varhaz <- v2 + rval +} +@ + + +\section{The Fine-Gray model} +For competing risks with ending states 1, 2, \ldots $k$, +the Fine-Gray approach turns these into a set of simple 2-state +Cox models: +\begin{itemize} + \item (not yet in state 1) $\longrightarrow$ state 1 + \item (not yet in state 2) $\longrightarrow$ state 2 + \item \ldots +\end{itemize} +Each of these is now a simple Cox model, assuming that we are willing +to make a proportional hazards assumption. +There is one added complication: +when estimating the first model, one wants to use the data set that +would have occured if the subjects being followed for state 1 had +not had an artificial censoring, that is, had continued to be followed +for event 1 even after event 2 occured. +Sometimes this can be filled in directly, e.g., if we knew the enrollment +dates for each subject along with the date that follow-up for the +study was terminated, and there was no lost to follow-up (only administrative +censoring.) +An example is the mgus2 data set, where follow-up for death continued +after the occurence of plasma cell malignancy. +In practice what is done is to estimate the overall censoring distribution and +give subjects artificial follow-up. + +The function below creates a data set that can then be used with coxph. +<>= +finegray <- function(formula, data, weights, subset, na.action= na.pass, + etype, prefix="fg", count="", id, timefix=TRUE) { + Call <- match.call() + indx <- match(c("formula", "data", "weights", "subset", "id"), + names(Call), nomatch=0) + if (indx[1] ==0) stop("A formula argument is required") + temp <- Call[c(1,indx)] # only keep the arguments we wanted + temp$na.action <- na.action + temp[[1L]] <- quote(stats::model.frame) # change the function called + + special <- c("strata", "cluster") + temp$formula <- if(missing(data)) terms(formula, special) + else terms(formula, special, data=data) + + mf <- eval(temp, parent.frame()) + if (nrow(mf) ==0) stop("No (non-missing) observations") + Terms <- terms(mf) + + Y <- model.extract(mf, "response") + if (!inherits(Y, "Surv")) stop("Response must be a survival object") + type <- attr(Y, "type") + if (type!='mright' && type!='mcounting') + stop("Fine-Gray model requires a multi-state survival") + nY <- ncol(Y) + states <- attr(Y, "states") + if (timefix) Y <- aeqSurv(Y) + + strats <- attr(Terms, "specials")$strata + if (length(strats)) { + stemp <- untangle.specials(Terms, 'strata', 1) + if (length(stemp$vars)==1) strata <- mf[[stemp$vars]] + else strata <- survival::strata(mf[,stemp$vars], shortlabel=TRUE) + istrat <- as.numeric(strata) + mf[stemp$vars] <- NULL + } + else istrat <- rep(1, nrow(mf)) + + id <- model.extract(mf, "id") + if (!is.null(id)) mf["(id)"] <- NULL # don't leave it in result + user.weights <- model.weights(mf) + if (is.null(user.weights)) user.weights <- rep(1.0, nrow(mf)) + + cluster<- attr(Terms, "specials")$cluster + if (length(cluster)) { + stop("a cluster() term is not valid") + } + + # If there is start-stop data, then there needs to be an id + # also check that this is indeed a competing risks form of data. + # Mark the first and last obs of each subject, as we need it later. + # Observations may not be in time order within a subject + delay <- FALSE # is there delayed entry? + if (type=="mcounting") { + if (is.null(id)) stop("(start, stop] data requires a subject id") + else { + index <- order(id, Y[,2]) # by time within id + sorty <- Y[index,] + first <- which(!duplicated(id[index])) + last <- c(first[-1] -1, length(id)) + if (any(sorty[-last, 3] != 0)) + stop("a subject has a transition before their last time point") + delta <- c(sorty[-1,1], 0) - sorty[,2] + if (any(delta[-last] !=0)) + stop("a subject has gaps in time") + if (any(Y[first,1] > min(Y[,2]))) delay <- TRUE + temp1 <- temp2 <- rep(FALSE, nrow(mf)) + temp1[index[first]] <- TRUE + temp2[index[last]] <- TRUE + first <- temp1 #used later + last <- temp2 + } + } else last <- rep(TRUE, nrow(mf)) + + if (missing(etype)) enum <- 1 #generate a data set for which endpoint? + else { + index <- match(etype, states) + if (any(is.na(index))) + stop ("etype argument has a state that is not in the data") + enum <- index[1] + if (length(index) > 1) warning("only the first endpoint was used") + } + + # make sure count, if present is syntactically valid + if (!missing(count)) count <- make.names(count) else count <- NULL + oname <- paste0(prefix, c("start", "stop", "status", "wt")) + + <> + <> +} +@ + +The censoring and truncation distributions are +\begin{align*} + G(t) &= \prod_{s \le t} \left(1 - \frac{c(s)}{r_c(s)} \right ) \\ + H(t) &= \prod_{s > t} \left(1 - \frac{e(s)}{r_e(s)} \right ) +\end{align*} +where $c(t)$ is the number of subjects censored at time $t$, $e(t)$ is the +number who enter at time $t$, and $r$ is the size of the relevant risk set. +These are equations 5 and 6 of Geskus (Biometrics 2011). +Note that both $G$ and $H$ are right continuous functions. +For tied times the assumption is that event $<$ censor $<$ entry. +For $G$ we use a modified Kapan-Meier where any events at censoring time $t$ are +removed from the risk set just before time $t$. +To avoid issues with times that are nearly identical (but not quite) we first +convert to an integer time scale, and then move events backwards by .2. +Since this is a competing risks data set any non-censored observation for a +subject is their last, so this time shift does not goof up the alignment +of start, stop data. +For the truncation distribution it is the subjects with times +at or before time $t$ that +are in the risk set $r_e(t)$ for truncation at (or before) $t$. +$H$ can be calculated using an ordinary KM on the reverse time scale. + +When there is (start,stop) data and hence multiple observations per subject, +calculation of $G$ needs use a status that is 1 only for the \emph{last} row +row of a censored subject. + +<>= +if (ncol(Y) ==2) { + temp <- min(Y[,1], na.rm=TRUE) + if (temp >0) zero <- 0 + else zero <- 2*temp -1 # a value less than any observed y + Y <- cbind(zero, Y) # add a start column +} + +utime <- sort(unique(c(Y[,1:2]))) # all the unique times +newtime <- matrix(findInterval(Y[,1:2], utime), ncol=2) +status <- Y[,3] + +newtime[status !=0, 2] <- newtime[status !=0,2] - .2 +Gsurv <- survfit(Surv(newtime[,1], newtime[,2], last & status==0) ~ istrat, + se.fit=FALSE) +@ + +The calculation for $H$ is also done on the integer scale. +Otherwise we will someday be clobbered by times that differ only in +round off error. The only nuisance is the status variable, which is +1 for the first row of each subject, since the data set may not +be in sorted order. The offset of .2 used above is not needed, but due +to the underlying integer scale it doesn't harm anything either. +Reversal of the time scale leads to a left continuous function which +we fix up later. +<>= +if (delay) + Hsurv <- survfit(Surv(-newtime[,2], -newtime[,1], first) ~ istrat, + se.fit =FALSE) +@ + +Consider the following data set: +\begin{itemize} + \item Events of type 1 at times 1, 4, 5, 10 + \item Events of type 2 at times 2, 5, 8 + \item Censors at times 3, 4, 4, 6, 8, 9, 12 +\end{itemize} +The censoring distribution will have the following shape: +\begin{center} + \begin{tabular}{rcccccc} + interval& (0,3]& (3,4] & (4,6] & (6,8] & (8,12] & 12+\\ + C(t) & 1 &11/12 & (11/12)(8/10) & (11/15)(5/6)& (11/15)(5/6)(3/4)& + 0 \\ + & 1.0000 & .9167 & .7333 & .6111 & .4583 + \end{tabular} + \end{center} +Notice that the event at time 4 is not counted in the risk set at time 4, +so the jump is 8/10 rather than 8/11. +Likewise at time 8 the risk set has 4 instead of 5: censors occur after deaths. + +When creating the data set for event type 1, subjects who have an event of +type 2 get extended out using this censoring distribution. The event at +time 2, for instance, appears as a censored observation with time dependent +weights of $G(t)$. The type 2 event at time 5 has weight 1 up through time 5, +then weights of $G(t)/C(5)$ for the remainder. +This means a weight of 1 over (5,6], 5/6 over (6,8], (5/6)(3/4) over (9,12] +and etc. + +Though there are 6 unique censoring intervals, +in the created data set for event type 1 we only need to know case +weights at times 1, 4, 5, and 10; the information from the (4,6] and (6,8] +intervals will never be used. +To create a minimal sized data set we can leave those intervals out. +$G(t)$ only drops to zero if the largest time(s) are censored observations, so +by definition no events lie in an interval with $G(t)=0$. + +If there is delayed entry, then the set of intervals is larger due to a merge +with the jumps in Hsurv. +The truncation distribution Hsurv ($H$) will become 0 at the first entry time; +it is a left continuous function whereas Gsurv ($G$) is right continuous. +We can slide $H$ one point to the left and merge them at the jump points. + +<>= +status <- Y[, 3] + +# Do computations separately for each stratum +stratfun <- function(i) { + keep <- (istrat ==i) + times <- sort(unique(Y[keep & status == enum, 2])) #unique event times + if (length(times)==0) return(NULL) #no events in this stratum + tdata <- mf[keep, -1, drop=FALSE] + maxtime <- max(Y[keep, 2]) + + Gtemp <- Gsurv[i] + if (delay) { + Htemp <- Hsurv[i] + dtime <- rev(-Htemp$time[Htemp$n.event > 0]) + dprob <- c(rev(Htemp$surv[Htemp$n.event > 0])[-1], 1) + ctime <- Gtemp$time[Gtemp$n.event > 0] + cprob <- c(1, Gtemp$surv[Gtemp$n.event > 0]) + temp <- sort(unique(c(dtime, ctime))) # these will all be integers + index1 <- findInterval(temp, dtime) + index2 <- findInterval(temp, ctime) + ctime <- utime[temp] + cprob <- dprob[index1] * cprob[index2+1] # G(t)H(t), eq 11 Geskus + } + else { + ctime <- utime[Gtemp$time[Gtemp$n.event > 0]] + cprob <- Gtemp$surv[Gtemp$n.event > 0] + } + + ct2 <- c(ctime, maxtime) + cp2 <- c(1.0, cprob) + index <- findInterval(times, ct2, left.open=TRUE) + index <- sort(unique(index)) # the intervals that were actually seen + # times before the first ctime get index 0, those between 1 and 2 get 1 + ckeep <- rep(FALSE, length(ct2)) + ckeep[index] <- TRUE + expand <- (Y[keep, 3] !=0 & Y[keep,3] != enum & last[keep]) #which rows to expand + split <- .Call(Cfinegray, Y[keep,1], Y[keep,2], ct2, cp2, expand, + c(TRUE, ckeep)) + tdata <- tdata[split$row,,drop=FALSE] + tstat <- ifelse((status[keep])[split$row]== enum, 1, 0) + + + tdata[[oname[1]]] <- split$start + tdata[[oname[2]]] <- split$end + tdata[[oname[3]]] <- tstat + tdata[[oname[4]]] <- split$wt * user.weights[split$row] + if (!is.null(count)) tdata[[count]] <- split$add + tdata +} + +if (max(istrat) ==1) result <- stratfun(1) +else { + tlist <- lapply(1:max(istrat), stratfun) + result <- do.call("rbind", tlist) +} + +rownames(result) <- NULL #remove all the odd labels that R adds +attr(result, "event") <- states[enum] +result +@ +\subsection{The predict method} +The \code{predict.coxph} function +produces various types of predicted values from a Cox model. +The arguments are +\begin{description} + \item [object] The result of a call to \code{coxph}. + \item [newdata] Optionally, a new data set for which prediction is + desired. If this is absent predictions are for the observations used + fit the model. + \item[type] The type of prediction + \begin{itemize} + \item lp = the linear predictor for each observation + \item risk = the risk score $exp(lp)$ for each observation + \item expected = the expected number of events + \item survival = predicted survival = exp(-expected) + \item terms = a matrix with one row per subject and one column for + each term in the model. + \end{itemize} + \item[se.fit] Whether or not to return standard errors of the predictions. + \item[na.action] What to do with missing values \emph{if} there is new + data. + \item[terms] The terms that are desired. This option is almost never used, + so rarely in fact that it's hard to justify keeping it. + \item[collapse] An optional vector of subject identifiers, over which to + sum or `collapse' the results + \item[reference] the reference context for centering the results + \item[\ldots] All predict methods need to have a \ldots argument; we make + no use of it however. +\end{description} + +%\subsection{Setup} +The first task of the routine is to reconsruct necessary data elements +that were not saved as a part of the \code{coxph} fit. +We will need the following components: +\begin{itemize} + \item for type=`expected' residuals we need the orignal survival y. This %'` + is saved in coxph objects by default so will only need to be fetched in + the highly unusual case that a user specfied + \code{y=FALSE} in the orignal call. + \item for any call with either newdata, standard errors, or type='terms' + the original $X$ matrix, weights, strata, and offset. + When checking for the existence of a saved $X$ matrix we can't %' + use \code{object\$x} + since that will also match the \code{xlevels} component. + \item the new data matrix, if any +\end{itemize} + +<>= +predict.coxph <- function(object, newdata, + type=c("lp", "risk", "expected", "terms", "survival"), + se.fit=FALSE, na.action=na.pass, + terms=names(object$assign), collapse, + reference=c("strata", "sample", "zero"), ...) { + <> + <> + if (type=="expected") { + <> + } + else { + <> + <> + } + <> + } +@ + +We start of course with basic argument checking. +Then retrieve the model parameters: does it have a strata +statement, offset, etc. +The \code{Terms2} object is a model statement without the strata or cluster terms, +appropriate for recreating the matrix of covariates $X$. +For type=expected the response variable needs to be kept, if not we remove +it as well since the user's newdata might not contain one. %' +The type= survival is treated the same as type expected. +<>= +if (!inherits(object, 'coxph')) + stop("Primary argument much be a coxph object") + +Call <- match.call() +type <-match.arg(type) +if (type=="survival") { + survival <- TRUE + type <- "expected" #this is to stop lots of "or" statements +} +else survival <- FALSE + +n <- object$n +Terms <- object$terms + +if (!missing(terms)) { + if (is.numeric(terms)) { + if (any(terms != floor(terms) | + terms > length(object$assign) | + terms <1)) stop("Invalid terms argument") + } + else if (any(is.na(match(terms, names(object$assign))))) + stop("a name given in the terms argument not found in the model") + } + +# I will never need the cluster argument, if present delete it. +# Terms2 are terms I need for the newdata (if present), y is only +# needed there if type == 'expected' +if (length(attr(Terms, 'specials')$cluster)) { + temp <- untangle.specials(Terms, 'cluster', 1) + Terms <- object$terms[-temp$terms] + } +else Terms <- object$terms + +if (type != 'expected') Terms2 <- delete.response(Terms) +else Terms2 <- Terms + +has.strata <- !is.null(attr(Terms, 'specials')$strata) +has.offset <- !is.null(attr(Terms, 'offset')) +has.weights <- any(names(object$call) == 'weights') +na.action.used <- object$na.action +n <- length(object$residuals) + +if (missing(reference) && type=="terms") reference <- "sample" +else reference <- match.arg(reference) +@ + +The next task of the routine is to reconsruct necessary data elements +that were not saved as a part of the \code{coxph} fit. +We will need the following components: +\begin{itemize} + \item for type=`expected' residuals we need the orignal survival y. This %'` + is saved in coxph objects by default so will only need to be fetched in + the highly unusual case that a user specfied \code{y=FALSE} in the orignal + call. We also need the strata in this case. Grabbing it is the same + amount of work as grabbing X, so gets lumped with that case in the + code. + \item for any call with either standard errors, reference strata, + or type=`terms' + the original $X$ matrix, weights, strata, and offset. + When checking for the existence of a saved $X$ matrix we can't %' + use \code{object\$x} + since that will also match the \code{xlevels} component. + \item the new data matrix, if present, along with offset and strata. +\end{itemize} +For the case that none of the above are needed, we can use the +\code{linear.predictors} component of the fit. The variable \code{use.x} signals +this case, which takes up almost none of the code but is common in usage. + +The check below that nrow(mf)==n is to avoid data sets that change under our +feet. A fit was based on data set ``x'', and when we reconstruct the data +frame it is a different size! This means someone changed the data between +the model fit and the extraction of residuals. +One other non-obvious case is that coxph treats the model \code{age:strata(grp)} +as though it were \code{age:strata(grp) + strata(grp)}. +The untangle.specials function will return +\code{vars= strata(grp), terms=integer(0)}; the first shows a strata to extract +and the second that there is nothing to remove from the terms structure. + +<>= +have.mf <- FALSE +if (type == "expected") { + y <- object[['y']] + if (is.null(y)) { # very rare case + mf <- stats::model.frame(object) + y <- model.extract(mf, 'response') + have.mf <- TRUE #for the logic a few lines below, avoid double work + } + } + +# This will be needed if there are strata, and is cheap to compute +strat.term <- untangle.specials(Terms, "strata") +if (se.fit || type=='terms' || (!missing(newdata) && type=="expected") || + (has.strata && (reference=="strata") || type=="expected")) { + use.x <- TRUE + if (is.null(object[['x']]) || has.weights || has.offset || + (has.strata && is.null(object$strata))) { + # I need the original model frame + if (!have.mf) mf <- stats::model.frame(object) + if (nrow(mf) != n) + stop("Data is not the same size as it was in the original fit") + x <- model.matrix(object, data=mf) + if (has.strata) { + if (!is.null(object$strata)) oldstrat <- object$strata + else { + if (length(strat.term$vars)==1) oldstrat <- mf[[strat.term$vars]] + else oldstrat <- strata(mf[,strat.term$vars], shortlabel=TRUE) + } + } + else oldstrat <- rep(0L, n) + + weights <- model.weights(mf) + if (is.null(weights)) weights <- rep(1.0, n) + offset <- model.offset(mf) + if (is.null(offset)) offset <- 0 + } + else { + x <- object[['x']] + if (has.strata) oldstrat <- object$strata + else oldstrat <- rep(0L, n) + weights <- rep(1.,n) + offset <- 0 + } +} +else { + # I won't need strata in this case either + if (has.strata) { + stemp <- untangle.specials(Terms, 'strata', 1) + Terms2 <- Terms2[-stemp$terms] + has.strata <- FALSE #remaining routine never needs to look + } + oldstrat <- rep(0L, n) + offset <- 0 + use.x <- FALSE +} +@ + +Now grab data from the new data set. We want to use model.frame +processing, in order to correctly expand factors and such. +We don't need weights, however, and don't want to make the user +include them in their new dataset. Thus we build the call up +the way it is done in coxph itself, but only keeping the newdata +argument. Note that terms2 may have fewer variables than the +original model: no cluster and if type!= expected no response. +If the original model had a strata, but newdata does not, we need to +remove the strata from xlev to stop a spurious warning message. + +<>= +if (!missing(newdata)) { + use.x <- TRUE #we do use an X matrix later + tcall <- Call[c(1, match(c("newdata", "collapse"), names(Call), nomatch=0))] + names(tcall)[2] <- 'data' #rename newdata to data + tcall$formula <- Terms2 #version with no response + tcall$na.action <- na.action #always present, since there is a default + tcall[[1L]] <- quote(stats::model.frame) # change the function called + + if (!is.null(attr(Terms, "specials")$strata) && !has.strata) { + temp.lev <- object$xlevels + temp.lev[[strat.term$vars]] <- NULL + tcall$xlev <- temp.lev + } + else tcall$xlev <- object$xlevels + mf2 <- eval(tcall, parent.frame()) + + collapse <- model.extract(mf2, "collapse") + n2 <- nrow(mf2) + + if (has.strata) { + if (length(strat.term$vars)==1) newstrat <- mf2[[strat.term$vars]] + else newstrat <- strata(mf2[,strat.term$vars], shortlabel=TRUE) + if (any(is.na(match(newstrat, oldstrat)))) + stop("New data has a strata not found in the original model") + else newstrat <- factor(newstrat, levels=levels(oldstrat)) #give it all + if (length(strat.term$terms)) + newx <- model.matrix(Terms2[-strat.term$terms], mf2, + contr=object$contrasts)[,-1,drop=FALSE] + else newx <- model.matrix(Terms2, mf2, + contr=object$contrasts)[,-1,drop=FALSE] + } + else { + newx <- model.matrix(Terms2, mf2, + contr=object$contrasts)[,-1,drop=FALSE] + newstrat <- rep(0L, nrow(mf2)) + } + + newoffset <- model.offset(mf2) + if (is.null(newoffset)) newoffset <- 0 + if (type== 'expected') { + newy <- model.response(mf2) + if (attr(newy, 'type') != attr(y, 'type')) + stop("New data has a different survival type than the model") + } + na.action.used <- attr(mf2, 'na.action') + } +else n2 <- n +@ + +%\subsection{Expected hazard} +When we do not need standard errors the computation of expected +hazard is very simple since +the martingale residual is defined as status - expected. The 0/1 +status is saved as the last column of $y$. +<>= +if (missing(newdata)) + pred <- y[,ncol(y)] - object$residuals +if (!missing(newdata) || se.fit) { + <> + } +if (survival) { #it actually was type= survival, do one more step + if (se.fit) se <- se * exp(-pred) + pred <- exp(-pred) # probablility of being in state 0 +} +@ + +The more general case makes use of the [agsurv] routine to calculate +a survival curve for each strata. The routine is defined in the +section on individual Cox survival curves. The code here closely matches +that. The routine only returns values at the death times, so we need +approx to get a complete index. + +One non-obvious, but careful choice is to use the residuals for the predicted +value instead of the compuation below, whenever operating on the original +data set. This is a consequence of the Efron approx. When someone in +a new data set has exactly the same time as one of the death times in the +original data set, the code below implicitly makes them the ``last'' death +in the set of tied times. +The Efron approx puts a tie somewhere in the middle of the pack. This is +way too hard to work out in the code below, but thankfully the original +Cox model already did it. However, it does mean that a different answer will +arise if you set newdata = the original coxph data set. +Standard errors have the same issue, but 1. they are hardly used and 2. the +original coxph doesn't do that calculation. So we do what's easiest. + +<>= +ustrata <- unique(oldstrat) +risk <- exp(object$linear.predictors) +x <- x - rep(object$means, each=nrow(x)) #subtract from each column +if (missing(newdata)) #se.fit must be true + se <- double(n) +else { + pred <- se <- double(nrow(mf2)) + newx <- newx - rep(object$means, each=nrow(newx)) + newrisk <- c(exp(newx %*% object$coef) + newoffset) + } + +survtype<- ifelse(object$method=='efron', 3,2) +for (i in ustrata) { + indx <- which(oldstrat == i) + afit <- agsurv(y[indx,,drop=F], x[indx,,drop=F], + weights[indx], risk[indx], + survtype, survtype) + afit.n <- length(afit$time) + if (missing(newdata)) { + # In this case we need se.fit, nothing else + j1 <- approx(afit$time, 1:afit.n, y[indx,1], method='constant', + f=0, yleft=0, yright=afit.n)$y + chaz <- c(0, afit$cumhaz)[j1 +1] + varh <- c(0, cumsum(afit$varhaz))[j1 +1] + xbar <- rbind(0, afit$xbar)[j1+1,,drop=F] + if (ncol(y)==2) { + dt <- (chaz * x[indx,]) - xbar + se[indx] <- sqrt(varh + rowSums((dt %*% object$var) *dt)) * + risk[indx] + } + else { + j2 <- approx(afit$time, 1:afit.n, y[indx,2], method='constant', + f=0, yleft=0, yright=afit.n)$y + chaz2 <- c(0, afit$cumhaz)[j2 +1] + varh2 <- c(0, cumsum(afit$varhaz))[j2 +1] + xbar2 <- rbind(0, afit$xbar)[j2+1,,drop=F] + dt <- (chaz * x[indx,]) - xbar + v1 <- varh + rowSums((dt %*% object$var) *dt) + dt2 <- (chaz2 * x[indx,]) - xbar2 + v2 <- varh2 + rowSums((dt2 %*% object$var) *dt2) + se[indx] <- sqrt(v2-v1)* risk[indx] + } + } + + else { + #there is new data + use.x <- TRUE + indx2 <- which(newstrat == i) + j1 <- approx(afit$time, 1:afit.n, newy[indx2,1], + method='constant', f=0, yleft=0, yright=afit.n)$y + chaz <-c(0, afit$cumhaz)[j1+1] + pred[indx2] <- chaz * newrisk[indx2] + if (se.fit) { + varh <- c(0, cumsum(afit$varhaz))[j1+1] + xbar <- rbind(0, afit$xbar)[j1+1,,drop=F] + } + if (ncol(y)==2) { + if (se.fit) { + dt <- (chaz * newx[indx2,]) - xbar + se[indx2] <- sqrt(varh + rowSums((dt %*% object$var) *dt)) * + newrisk[indx2] + } + } + else { + j2 <- approx(afit$time, 1:afit.n, newy[indx2,2], + method='constant', f=0, yleft=0, yright=afit.n)$y + chaz2 <- approx(-afit$time, afit$cumhaz, -newy[indx2,2], + method="constant", rule=2, f=0)$y + chaz2 <-c(0, afit$cumhaz)[j2+1] + pred[indx2] <- (chaz2 - chaz) * newrisk[indx2] + + if (se.fit) { + varh2 <- c(0, cumsum(afit$varhaz))[j1+1] + xbar2 <- rbind(0, afit$xbar)[j1+1,,drop=F] + dt <- (chaz * newx[indx2,]) - xbar + dt2 <- (chaz2 * newx[indx2,]) - xbar2 + + v2 <- varh2 + rowSums((dt2 %*% object$var) *dt2) + v1 <- varh + rowSums((dt %*% object$var) *dt) + se[indx2] <- sqrt(v2-v1)* risk[indx2] + } + } + } + } +@ + +%\subsection{Linear predictor, risk, and terms} +For these three options what is returned is a \emph{relative} prediction +which compares each observation to the average for the data set. +Partly this is practical. Say for instance that a treatment covariate +was coded as 0=control and 1=treatment. +If the model were refit using a new coding of 3=control 4=treatment, the +results of the Cox model would be exactly the same with respect to +coefficients, variance, tests, etc. +The raw linear predictor $X\beta$ however would change, increasing by +a value of $3\beta$. +The relative predictor +\begin{equation} + \eta_i = X_i\beta - (1/n)\sum_j X_j\beta + \label{eq:eta} +\end{equation} +will stay the same. +The second reason for doing this is that the Cox model is a +relative risks model rather than an absolute risks model, +and thus relative predictions are almost certainly what the +user was thinking of. + +When the fit was for a stratified Cox model more care is needed. +For instance assume that we had a fit that was stratified by sex with +covaritate $x$, and a second data set were created where for the +females $x$ is replaced +by $x+3$. The Cox model results will be unchanged for the two +models, but the `normalized' linear predictors $(x - \overline x)'\beta$ %` +will not be the same. +This reflects a more fundamental issue that the for a stratified +Cox model relative risks are well defined only \emph{within} a +stratum, i.e. for subject pairs that share a common baseline +hazard. +The example above is artificial, but the problem arises naturally +whenever the model includes a strata by covariate interaction. +So for a stratified Cox model the predictions should be forced to +sum to zero within each stratum, or equivalently be made relative +to the weighted mean of the stratum. +Unfortunately, this important issue was not realized until late in 2009 +when a puzzling query was sent to the author involving the results +from such an interaction. +Note that this issue did not arise with type='expected', which +has a natural scaling. + +An offset variable, if specified, is treated like any other covariate +with respect to centering. +The logic for this choice is not as compelling, but it seemed the +best that I could do. +Note that offsets play no role whatever in predicted terms, only in +the lp and risk. + +Start with the simple ones +<>= +if (is.null(object$coefficients)) + coef<-numeric(0) +else { + # Replace any NA coefs with 0, to stop NA in the linear predictor + coef <- ifelse(is.na(object$coefficients), 0, object$coefficients) + } + +if (missing(newdata)) { + offset <- offset - mean(offset) + if (has.strata && reference=="strata") { + # We can't use as.integer(oldstrat) as an index, if oldstrat is + # a factor variable with unrepresented levels as.integer could + # give 1,2,5 for instance. + xmeans <- rowsum(x*weights, oldstrat)/c(rowsum(weights, oldstrat)) + newx <- x - xmeans[match(oldstrat,row.names(xmeans)),] + } + else if (use.x) { + if (reference == "zero") newx <- x + else newx <- x - rep(object$means, each=nrow(x)) + } +} +else { + offset <- newoffset - mean(offset) + if (has.strata && reference=="strata") { + xmeans <- rowsum(x*weights, oldstrat)/c(rowsum(weights, oldstrat)) + newx <- newx - xmeans[match(newstrat, row.names(xmeans)),] + } + else if (reference!= "zero") + newx <- newx - rep(object$means, each=nrow(newx)) + } + +if (type=='lp' || type=='risk') { + if (use.x) pred <- drop(newx %*% coef) + offset + else pred <- object$linear.predictors + if (se.fit) se <- sqrt(rowSums((newx %*% object$var) *newx)) + + if (type=='risk') { + pred <- exp(pred) + if (se.fit) se <- se * sqrt(pred) # standard Taylor series approx + } + } +@ + +The type=terms residuals are a bit more work. +In Splus this code used the Build.terms function, which was essentially +the code from predict.lm extracted out as a separate function. +As of March 2010 (today) a check of the Splus function and the R code +for predict.lm revealed no important differences. +A lot of the bookkeeping in both is to work around any possible NA +coefficients resulting from a singularity. +The basic formula is to +\begin{enumerate} + \item If the model has an intercept, then sweep the column means + out of the X matrix. We've already done this. + \item For each term separately, get the list of coefficients that + belong to that term; call this list \code{tt}. + \item Restrict $X$, $\beta$ and $V$ (the variance matrix) to that + subset, then the linear predictor is $X\beta$ with variance + matrix $X V X'$. The standard errors are the square root of + the diagonal of this latter matrix. This can be computed, + as colSums((X %*% V) * X)). +\end{enumerate} +Note that the \code{assign} component of a coxph object is the same +as that found in Splus models (a list), most R models retain a numeric vector +which contains the same information but it is not as easily used. The first +first part of predict.lm in R rebuilds the list form as its \code{asgn} variable. +I can skip this part since it is already done. +<>= +else if (type=='terms') { + asgn <- object$assign + nterms<-length(asgn) + pred<-matrix(ncol=nterms,nrow=NROW(newx)) + dimnames(pred) <- list(rownames(newx), names(asgn)) + if (se.fit) se <- pred + + for (i in 1:nterms) { + tt <- asgn[[i]] + tt <- tt[!is.na(object$coefficients[tt])] + xtt <- newx[,tt, drop=F] + pred[,i] <- xtt %*% object$coefficient[tt] + if (se.fit) + se[,i] <- sqrt(rowSums((xtt %*% object$var[tt,tt]) *xtt)) + } + pred <- pred[,terms, drop=F] + if (se.fit) se <- se[,terms, drop=F] + + attr(pred, 'constant') <- sum(object$coefficients*object$means, na.rm=T) + } +@ + +To finish up we need to first expand out any missings in the result +based on the na.action, and optionally collapse the results within +a subject. +What should we do about the standard errors when collapse is specified? +We assume that the individual pieces are +independent and thus var(sum) = sum(variances). +The statistical justification of this is quite solid for the linear predictor, +risk and terms type of prediction due to independent increments in a martingale. +For expecteds the individual terms are positively correlated so the se will +be too small. One solution would be to refuse to return an se in this +case, but the the bias should usually be small, +and besides it would be unkind to the user. + +Prediction of type='terms' is expected to always return a matrix, or +the R termplot() function gets unhappy. +<>= +if (type != 'terms') { + pred <- drop(pred) + if (se.fit) se <- drop(se) + } + +if (!is.null(na.action.used)) { + pred <- napredict(na.action.used, pred) + if (is.matrix(pred)) n <- nrow(pred) + else n <- length(pred) + if(se.fit) se <- napredict(na.action.used, se) + } + +if (!missing(collapse) && !is.null(collapse)) { + if (length(collapse) != n2) stop("Collapse vector is the wrong length") + pred <- rowsum(pred, collapse) # in R, rowsum is a matrix, always + if (se.fit) se <- sqrt(rowsum(se^2, collapse)) + if (type != 'terms') { + pred <- drop(pred) + if (se.fit) se <- drop(se) + } + } + +if (se.fit) list(fit=pred, se.fit=se) +else pred +@ +\section{Concordance} +\subsection{Main routine} + The concordance statistic is the most used measure of goodness-of-fit +in survival models. +In general let $y_i$ and $x_i$ be observed and predicted data values. +A pair of obervations $i$, $j$ is considered condordant if either +$y_i > y_j, x_i > x_j$ or $y_i < y_j, x_i < x_j$. +The concordance is the fraction of concordant pairs. +For a Cox model remember that the predicted survival $\hat y$ is longer if +the risk score $X\beta$ is lower, so we have to flip the definition and +count ``discordant'' pairs, this is done at the end of the routine. + +One wrinkle is what to do with ties in either $y$ or $x$. Such pairs +can be ignored in the count (treated as incomparable), treated as discordant, +or given a score of 1/2. +\begin{itemize} + \item Kendall's $\tau$-a scores ties as 0. + \item Kendall's $\tau$-b and the Goodman-Kruskal $\gamma$ ignore ties in + either $y$ or $x$. + \item Somers' $d$ treats ties in $y$ as incomparable, pairs that are tied + in $x$ (but not $y$) score as 1/2. The AUC from logistic regression is + equal to Somers' $d$. +\end{itemize} +All three of the above range from -1 to 1, the concordance is +$(d +1)/2$. +For survival data any pairs which cannot be ranked with certainty are +considered incomparable. +For instance $y_i$ is censored at time 10 and $y_j$ is an event (or censor) +at time 20. Subject $i$ may or may not survive longer than subject $j$. +Note that if $y_i$ is censored at time +10 and $y_j$ is an event at time 10 then $y_i > y_j$. +Observations that are in different strata are also incomparable, +since the Cox model only compares within strata. + +The program creates 4 variables, which are the number of concordant pairs, +discordant, tied on time, and tied on $x$ but not on time. +The default concordance is based on the Somers'/AUC definition, +but all 4 values are reported back so that a user +can recreate Kendall's or Goodmans values if desired. + +Here is the main routine. +<>= +concordance <- function(object, ...) + UseMethod("concordance") + +concordance.formula <- function(object, data, + weights, subset, na.action, cluster, + ymin, ymax, + timewt=c("n", "S", "S/G", "n/G", "n/G2", "I"), + influence=0, ranks=FALSE, reverse=FALSE, + timefix=TRUE, keepstrata=10, ...) { + Call <- match.call() # save a copy of of the call, as documentation + timewt <- match.arg(timewt) + if (missing(ymin)) ymin <- NULL + if (missing(ymax)) ymax <- NULL + + index <- match(c("data", "weights", "subset", "na.action", + "cluster"), + names(Call), nomatch=0) + temp <- Call[c(1, index)] + temp[[1L]] <- quote(stats::model.frame) + special <- c("strata", "cluster") + temp$formula <- if(missing(data)) terms(object, special) + else terms(object, special, data=data) + mf <- eval(temp, parent.frame()) # model frame + if (nrow(mf) ==0) stop("No (non-missing) observations") + Terms <- terms(mf) + + Y <- model.response(mf) + if (inherits(Y, "Surv")) { + if (timefix) Y <- aeqSurv(Y) + } else { + if (is.factor(Y) && (is.ordered(Y) || length(levels(Y))==2)) + Y <- Surv(as.numeric(Y)) + else if (is.numeric(Y) && is.vector(Y)) Y <- Surv(Y) + else stop("left hand side of the formula must be a numeric vector, + survival object, or an orderable factor") + if (timefix) Y <- aeqSurv(Y) + } + n <- nrow(Y) + + wt <- model.weights(mf) + offset<- attr(Terms, "offset") + if (length(offset)>0) stop("Offset terms not allowed") + + stemp <- untangle.specials(Terms, "strata") + if (length(stemp$vars)) { + if (length(stemp$vars)==1) strat <- mf[[stemp$vars]] + else strat <- strata(mf[,stemp$vars], shortlabel=TRUE) + Terms <- Terms[-stemp$terms] + } + else strat <- NULL + + # if "cluster" was an argument, use it, otherwise grab it from the model + group <- model.extract(mf, "cluster") + cluster<- attr(Terms, "specials")$cluster + if (length(cluster)) { + tempc <- untangle.specials(Terms, 'cluster', 1:10) + ord <- attr(Terms, 'order')[tempc$terms] + if (any(ord>1)) stop ("Cluster can not be used in an interaction") + cluster <- strata(mf[,tempc$vars], shortlabel=TRUE) #allow multiples + Terms <- Terms[-tempc$terms] # toss it away + } + if (length(group)) cluster <- group + + x <- model.matrix(Terms, mf)[,-1, drop=FALSE] #remove the intercept + if (ncol(x) > 1) stop("Only one predictor variable allowed") + + if (!is.null(ymin) & (length(ymin)> 1 || !is.numeric(ymin))) + stop("ymin must be a single number") + if (!is.null(ymax) & (length(ymax)> 1 || !is.numeric(ymax))) + stop("ymax must be a single number") + if (!is.logical(reverse)) + stop ("the reverse argument must be TRUE/FALSE") + + fit <- concordancefit(Y, x, strat, wt, ymin, ymax, timewt, cluster, + influence, ranks, reverse, keepstrata=keepstrata) + na.action <- attr(mf, "na.action") + if (length(na.action)) fit$na.action <- na.action + fit$call <- Call + + class(fit) <- 'concordance' + fit +} + +print.concordance <- function(x, digits= max(1L, getOption("digits") - 3L), + ...) { + if(!is.null(cl <- x$call)) { + cat("Call:\n") + dput(cl) + cat("\n") + } + omit <- x$na.action + if(length(omit)) + cat("n=", x$n, " (", naprint(omit), ")\n", sep = "") + else cat("n=", x$n, "\n") + + if (length(x$concordance) > 1) { + # result of a call with multiple fits + tmat <- cbind(concordance= x$concordance, se=sqrt(diag(x$var))) + print(round(tmat, digits=digits), ...) + cat("\n") + } + else cat("Concordance= ", format(x$concordance, digits=digits), " se= ", + format(sqrt(x$var), digits=digits), '\n', sep='') + + if (!is.matrix(x$count) || nrow(x$count < 11)) + print(round(x$count,2)) + invisible(x) + } + +<> + +<> +@ + +The concordancefit function is broken out separately, since it is called +by all of the methods. It is also called directly by the the \code{coxph} +routine. +If $y$ is not a survival quantity, then all of the options for the +\code{timewt} parameter lead to the same result. + +<>= +concordancefit <- function(y, x, strata, weights, ymin=NULL, ymax=NULL, + timewt=c("n", "S", "S/G", "n/G", "n/G2", "I"), + cluster, influence=0, ranks=FALSE, reverse=FALSE, + timefix=TRUE, keepstrata=10, robustse =TRUE) { + # The coxph program may occassionally fail, and this will kill the C + # routine further below. So check for it. + if (any(is.na(x)) || any(is.na(y))) return(NULL) + timewt <- match.arg(timewt) + + if (!robustse) {ranks <- FALSE; influence =0;} + + # these should only occur if something other package calls this routine + if (!is.Surv(y)) { + if (is.factor(y) && (is.ordered(y) || length(levels(y))==2)) + y <- Surv(as.numeric(y)) + else if (is.numeric(y) && is.vector(y)) y <- Surv(y) + else stop("left hand side of the formula must be a numeric vector, + survival object, or an orderable factor") + if (timefix) y <- aeqSurv(y) + } + n <- length(y) + if (length(x) != n) stop("x and y are not the same length") + if (missing(strata) || length(strata)==0) strata <- rep(1L, n) + if (length(strata) != n) + stop("y and strata are not the same length") + if (missing(weights) || length(weights)==0) weights <- rep(1.0, n) + else if (length(weights) != n) stop("y and weights are not the same length") + + type <- attr(y, "type") + if (type %in% c("left", "interval")) + stop("left or interval censored data is not supported") + if (type %in% c("mright", "mcounting")) + stop("multiple state survival is not supported") + + nstrat <- length(unique(strata)) + if (!is.logical(keepstrata)) { + if (!is.numeric(keepstrata)) + stop("keepstrat argument must be logical or numeric") + else keepstrata <- (nstrat <= keepstrata) + } + + if (timewt %in% c("n", "I") && nstrat > 10 && !keepstrata) { + # Special trickery for matched case-control data, where the + # number of strata is huge, n per strata is small, and compute + # time becomes excessive. Make the data all one strata, but over + # disjoint time intervals + stemp <- as.numeric(as.factor(strata)) -1 + if (ncol(y) ==3) { + delta <- 2+ max(y[,2]) - min(y[,1]) + y[,1] <- y[,1] + stemp*delta + y[,2] <- y[,2] + stemp*delta + } + else { + delta <- max(y[,1]) +2 + m1 <- rep(-1L, nrow(y)) + y <- Surv(m1 + stemp*delta, y[,1] + stemp*delta, y[,2]) + } + strata <- rep(1L, n) + nstrat <- 1 + } + + # This routine is called once per stratum + docount <- function(y, risk, wts, timeopt= 'n', timefix) { + n <- length(risk) + # this next line is mostly invoked in stratified logistic, where + # only 1 event per stratum occurs. All time weightings are the same + # don't waste time even if the user asked for something different + if (sum(y[,ncol(y)]) <2) timeopt <- 'n' + + sfit <- survfit(y~1, weights=wts, se.fit=FALSE, timefix=timefix) + etime <- sfit$time[sfit$n.event > 0] + esurv <- sfit$surv[sfit$n.event > 0] + + if (length(etime)==0) { + # the special case of a stratum with no events (it happens) + # No need to do any more work + return(list(count= rep(0.0, 6), influence=matrix(0.0, n, 5), + resid=NULL)) + } + + if (timeopt %in% c("S/G", "n/G", "n/G2")) { + temp <- y + temp[,ncol(temp)] <- 1- temp[,ncol(temp)] # switch event/censor + gfit <- survfit(temp~1, weights=wts, se.fit=FALSE, timefix=timefix) + # G has the exact same time values as S + gsurv <- c(1, gfit$surv) # We want G(t-) + gsurv <- gsurv[which(sfit$n.event > 0)] + } + + npair <- (sfit$n.risk- sfit$n.event)[sfit$n.event>0] + temp <- ifelse(esurv==0, 0, esurv/npair) # avoid 0/0 + timewt <- switch(timeopt, + "S" = sum(wts)*temp, + "S/G" = sum(wts)* temp/ gsurv, + "n" = rep(1.0, length(npair)), + "n/G" = 1/gsurv, + "n/G2"= 1/gsurv^2, + "I" = rep(1.0, length(esurv)) + ) + if (!is.null(ymin)) timewt[etime < ymin] <- 0 + if (!is.null(ymax)) timewt[etime > ymax] <- 0 + timewt <- ifelse(is.finite(timewt), timewt, 0) # 0 at risk case + + # order the data: reverse time, censors before deaths + if (ncol(y)==2) { + sort.stop <- order(-y[,1], y[,2], risk) -1L + } else { + sort.stop <- order(-y[,2], y[,3], risk) -1L #order by endpoint + sort.start <- order(-y[,1]) -1L + } + + # match each prediction score to the unique set of scores + # (to deal with ties) + utemp <- match(risk, sort(unique(risk))) + bindex <- btree(max(utemp))[utemp] + + storage.mode(y) <- "double" # just in case y is integer + storage.mode(wts) <- "double" + if (robustse) { + if (ncol(y) ==2) + fit <- .Call(Cconcordance3, y, bindex, wts, rev(timewt), + sort.stop, ranks) + else fit <- .Call(Cconcordance4, y, bindex, wts, rev(timewt), + sort.start, sort.stop, ranks) + + # The C routine gives back an influence matrix which has columns for + # concordant, discordant, tied on x but not y, tied on y, and tied + # on both x and y. + dimnames(fit$influence) <- list(NULL, + c("concordant", "discordant", "tied.x", "tied.y", "tied.xy")) + if (ranks) { + if (ncol(y)==2) dtime <- y[y[,2]==1, 1] + else dtime <- y[y[,3]==1, 2] + temp <- data.frame(time= sort(dtime), fit$resid) + names(temp) <- c("time", "rank", "timewt", "casewt", "variance") + fit$resid <- temp[temp[,3] > 0,] # don't return zeros + } + } + else { + if (ncol(y) ==2) + fit <- .Call(Cconcordance5, y, bindex, wts, rev(timewt), + sort.stop) + else fit <- .Call(Cconcordance6, y, bindex, wts, rev(timewt), + sort.start, sort.stop) + } + fit + } + + if (nstrat < 2) { + fit <- docount(y, x, weights, timewt, timefix=timefix) + count2 <- fit$count[1:5] + vcox <- fit$count[6] + fit$count <- fit$count[1:5] + if (robustse) imat <- fit$influence + if (ranks) resid <- fit$resid + } else { + strata <- as.factor(strata) + ustrat <- levels(strata)[table(strata) >0] #some strata may have 0 obs + tfit <- lapply(ustrat, function(i) { + keep <- which(strata== i) + docount(y[keep,,drop=F], x[keep], weights[keep], timewt, + timefix=timefix) + }) + temp <- t(sapply(tfit, function(x) x$count)) + fit <- list(count = temp[,1:5]) + count2 <- colSums(fit$count) + if (!keepstrata) fit$count <- count2 + vcox <- sum(temp[,6]) + if (robustse) { + imat <- do.call("rbind", lapply(tfit, function(x) x$influence)) + # put it back into data order + index <- match(1:n, (1:n)[order(strata)]) + imat <- imat[index,] + if (ranks) { + nr <- lapply(tfit, function(x) nrow(x$resid)) + resid <- do.call("rbind", lapply(tfit, function(x) x$resid)) + resid$strata <- rep(ustrat, nr) + } + } + } + + npair <- sum(count2[1:3]) + if (!keepstrata && is.matrix(fit$count)) fit$count <- colSums(fit$count) + somer <- (count2[1] - count2[2])/npair + if (robustse) { + dfbeta <- weights*((imat[,1]- imat[,2])/npair - + (somer/npair)* rowSums(imat[,1:3])) + if (!missing(cluster) && length(cluster)>0) { + dfbeta <- tapply(dfbeta, cluster, sum) + dfbeta <- ifelse(is.na(dfbeta),0, dfbeta) # if cluster is a factor + } + var.somer <- sum(dfbeta^2) + rval <- list(concordance = (somer+1)/2, count=fit$count, n=n, + var = var.somer/4, cvar=vcox/(4*npair^2)) + } + else rval <- list(concordance = (somer+1)/2, count=fit$count, n=n, + cvar=vcox/(4*npair^2)) + if (is.matrix(rval$count)) + colnames(rval$count) <- c("concordant", "discordant", "tied.x", + "tied.y", "tied.xy") + else names(rval$count) <- c("concordant", "discordant", "tied.x", "tied.y", + "tied.xy") + + if (influence == 1 || influence==3) rval$dfbeta <- dfbeta/2 + if (influence >=2) rval$influence <- imat + + if (ranks) rval$ranks <- resid + if (reverse) { + # flip concordant/discordant values but not the labels + rval$concordance <- 1- rval$concordance + if (!is.null(rval$dfbeta)) rval$dfbeta <- -rval$dfbeta + if (!is.null(rval$influence)) { + rval$influence <- rval$influence[,c(2,1,3,4,5)] + colnames(rval$influence) <- colnames(rval$influence)[c(2,1,3,4,5)] + } + if (is.matrix(rval$count)) { + rval$count <- rval$count[, c(2,1,3,4,5)] + colnames(rval$count) <- colnames(rval$count)[c(2,1,3,4,5)] + } + else { + rval$count <- rval$count[c(2,1,3,4,5)] + names(rval$count) <- names(rval$count)[c(2,1,3,4,5)] + } + if (ranks) rval$ranks$rank <- -rval$ranks$rank + } + + rval +} +@ + +\subsection{Methods} + +Methods are defined for lm, survfit, and coxph objects. Detection of +strata, weights, or clustering is the main nuisance, since those are +not passed back as part of coxph or survreg objects. Glm and lm objects +have the model frame by default, but that can be turned off by a user. +This routine gets the X, Y, and other portions from the result of a +particular fit object. + +<>= +cord.getdata <- function(object, newdata=NULL, cluster=NULL, need.wt, timefix=TRUE) { + # For coxph object, don't reconstruct the model frame unless we must. + # This will occur if weights, strata, or cluster are needed, or if + # there is a newdata argument. Of course, if the model frame is + # already present, then use it! + Terms <- terms(object) + specials <- attr(Terms, "specials") + if (!is.null(specials$tt)) + stop("cannot yet handle models with tt terms") + + if (!is.null(newdata)) { + mf <- model.frame(object, data=newdata) + y <- model.response(mf) + if (!is.Surv(y)) { + if (is.numeric(y) && is.vector(y)) y <- Surv(y) + else stop("left hand side of the formula must be a numeric vector or a survival object") + } + if (timefix) y <- aeqSurv(y) + rval <- list(y= y, x= predict(object, newdata)) + # the type of prediction does not matter, as long as it is a + # monotone transform of the linear predictor + } + else { + mf <- object$model + y <- object$y + if (is.null(y)) { + if (is.null(mf)) mf <- model.frame(object) + y <- model.response(mf) + } + if (!is.Surv(y)) { + y <- Surv(y) + if (timefix) y <- aeqSurv(y) + } # survival models will have already called timefix + + x <- object$linear.predictors # used by most + if (is.null(x)) x <- object$fitted.values # used by lm + if (is.null(x)) {object$na.action <- NULL; x <- predict(object)} + rval <- list(y = y, x= x) + } + + if (need.wt) { + if (is.null(mf)) mf <- model.frame(object) + rval$weights <- model.weights(mf) + } + + if (!is.null(specials$strata)) { + if (is.null(mf)) mf <- model.frame(object) + stemp <- untangle.specials(Terms, 'strata', 1) + if (length(stemp$vars)==1) rval$strata <- mf[[stemp$vars]] + else rval$strata <- strata(mf[,stemp$vars], shortlabel=TRUE) + } + + if (is.null(cluster)) { + if (!is.null(specials$cluster)) { + if (is.null(mf)) mf <- model.frame(object) + tempc <- untangle.specials(Terms, 'cluster', 1:10) + ord <- attr(Terms, 'order')[tempc$terms] + rval$cluster <- strata(mf[,tempc$vars], shortlabel=TRUE) + } + else if (!is.null(object$call$cluster)) { + if (is.null(mf)) mf <- model.frame(object) + rval$cluster <- model.extract(mf, "cluster") + } + } + else rval$cluster <- cluster + rval +} +@ + +The methods themselves, which are near clones of each other. +There is one portion of these that is not very clear. +I use the trick from nearly all calls to model.frame to deal with +arguments that might be there or might not, such as newdata. +Construct a call by hand by first subsetting this call as Call[...], +then replace the first element with the name of what I really want +to call -- quote(cord.work) --, add any other args I want, and finally +execute it with eval(). +The problem is that this doesn't work; the routine can't find cord.work +since it is not an exported function. A simple call to cord.work is +okay, since function calls inherit from the survival namespace, but +cfun isn't a function call, it is an expression. +There are 3 possible solutions +\begin{itemize} + \item bad: change eval(cfun, parent.frame()) to eval(cfun, evironment(coxph)), + or any other function from the survival library which has + namespace::survival as its environment. If the user calls concordance + with ymax=zed, say, we might not be able to find 'zed'. Especially if they + had called concordance from within a function. We need the call chain. + \item okay: use cfun[[1]] <- cord.work, which makes a copy of the entire + cord.work function and stuffs it in. The function isn't too long, so this + is okay. If cord.work fails, the label on its error message won't be as + nice since it won't have ``cord.work'' in it. + \item speculative: make a function and invoke it. + This creates a new function in the survival namespace, but evaluates it + in the current context. Using parent.frame() is important so that I + don't accidentally pick up 'nfit' say, if the user had used a variable of + that name as one of their arguments. \\ + temp <- function(){} \\ + body(temp, environment(coxph)) <- cfun\\ + rval <- eval(temp(), parent.frame()) +\end{itemize} + +<>= +concordance.lm <- function(object, ..., newdata, cluster, ymin, ymax, + influence=0, ranks=FALSE, timefix=TRUE, + keepstrata=10) { + Call <- match.call() + fits <- list(object, ...) + nfit <- length(fits) + fname <- as.character(Call) # like deparse(substitute()) but works for ... + fname <- fname[1 + 1:nfit] + notok <- sapply(fits, function(x) !inherits(x, "lm")) + if (any(notok)) { + # a common error is to mistype an arg, "ramk=TRUE" for instance, + # and it ends up in the ... list + # try for a nice message in this case: the name of the arg if it + # has one other than "object", fname otherwise + indx <- which(notok) + id2 <- names(Call)[indx+1] + temp <- ifelse(id2 %in% c("","object"), fname, id2) + stop(temp, " argument is not an appropriate fit object") + } + + cargs <- c("ymin", "ymax","influence", "ranks", "keepstrata") + cfun <- Call[c(1, match(cargs, names(Call), nomatch=0))] + cfun[[1]] <- cord.work # or quote(survival:::cord.work) + cfun$fname <- fname + + if (missing(newdata)) newdata <- NULL + if (missing(cluster)) cluster <- NULL + need.wt <- any(sapply(fits, function(x) !is.null(x$call$weights))) + + cfun$data <- lapply(fits, cord.getdata, newdata=newdata, cluster=cluster, + need.wt=need.wt, timefix=timefix) + rval <- eval(cfun, parent.frame()) + rval$call <- Call + rval +} + +concordance.survreg <- function(object, ..., newdata, cluster, ymin, ymax, + timewt=c("n", "S", "S/G", "n/G", "n/G2", "I"), + influence=0, ranks=FALSE, timefix=FALSE, + keepstrata=10) { + Call <- match.call() + fits <- list(object, ...) + nfit <- length(fits) + fname <- as.character(Call) # like deparse(substitute()) but works for ... + fname <- fname[1 + 1:nfit] + notok <- sapply(fits, function(x) !inherits(x, "survreg")) + if (any(notok)) { + # a common error is to mistype an arg, "ramk=TRUE" for instance, + # and it ends up in the ... list + # try for a nice message in this case: the name of the arg if it + # has one other than "object", fname otherwise + indx <- which(notok) + id2 <- names(Call)[indx+1] + temp <- ifelse(id2 %in% c("","object"), fname, id2) + stop(temp, " argument is not an appropriate fit object") + } + + cargs <- c("ymin", "ymax","influence", "ranks", "timewt", "keepstrata") + cfun <- Call[c(1, match(cargs, names(Call), nomatch=0))] + cfun[[1]] <- cord.work + cfun$fname <- fname + + if (missing(newdata)) newdata <- NULL + if (missing(cluster)) cluster <- NULL + need.wt <- any(sapply(fits, function(x) !is.null(x$call$weights))) + + cfun$data <- lapply(fits, cord.getdata, newdata=newdata, cluster=cluster, + need.wt=need.wt, timefix=timefix) + rval <- eval(cfun, parent.frame()) + rval$call <- Call + rval +} + +concordance.coxph <- function(object, ..., newdata, cluster, ymin, ymax, + timewt=c("n", "S", "S/G", "n/G", "n/G2", "I"), + influence=0, ranks=FALSE, timefix=FALSE, + keepstrata=10) { + Call <- match.call() + fits <- list(object, ...) + nfit <- length(fits) + fname <- as.character(Call) # like deparse(substitute()) but works for ... + fname <- fname[1 + 1:nfit] + notok <- sapply(fits, function(x) !inherits(x, "coxph")) + if (any(notok)) { + # a common error is to mistype an arg, "ramk=TRUE" for instance, + # and it ends up in the ... list + # try for a nice message in this case: the name of the arg if it + # has one other than "object", fname otherwise + indx <- which(notok) + id2 <- names(Call)[indx+1] + temp <- ifelse(id2 %in% c("","object"), fname, id2) + stop(temp, " argument is not an appropriate fit object") + } + + # the cargs trick is a nice one, but it only copies over arguments that + # are present. If 'ranks' was not specified, the default of FALSE is + # not set. We keep it in the arg list only to match the documentation. + cargs <- c("ymin", "ymax","influence", "ranks", "timewt", "keepstrata") + cfun <- Call[c(1, match(cargs, names(Call), nomatch=0))] + cfun[[1]] <- cord.work # a copy of the function + cfun$fname <- fname + cfun$reverse <- TRUE + + if (missing(newdata)) newdata <- NULL + if (missing(cluster)) cluster <- NULL + need.wt <- any(sapply(fits, function(x) !is.null(x$call$weights))) + + cfun$data <- lapply(fits, cord.getdata, newdata=newdata, cluster=cluster, + need.wt=need.wt, timefix=timefix) + rval <- eval(cfun, parent.frame()) + rval$call <- Call + rval +} +@ + +The next routine does all of the actual work for a set of models. +Note that because of the call-through trick (fargs) exactly and only those +arguments that are passed in are passed through to concordancefit. +Default argument values for that function are found there. The default +value for inflence found below is used in this routine, so it is important +that they match. + +<>= +cord.work <- function(data, timewt, ymin, ymax, influence=0, ranks=FALSE, + reverse, fname, keepstrata) { + Call <- match.call() + fargs <- c("timewt", "ymin", "ymax", "influence", "ranks", "reverse", + "keepstrata") + fcall <- Call[c(1, match(fargs, names(Call), nomatch=0))] + fcall[[1L]] <- concordancefit + + nfit <- length(data) + if (nfit==1) { + dd <- data[[1]] + fcall$y <- dd$y + fcall$x <- dd$x + fcall$strata <- dd$strata + fcall$weights <- dd$weights + fcall$cluster <- dd$cluster + rval <- eval(fcall, parent.frame()) + } + else { + # Check that all of the models used the same data set, in the same + # order, to the best of our abilities + n <- length(data[[1]]$x) + for (i in 2:nfit) { + if (length(data[[i]]$x) != n) + stop("all models must have the same sample size") + + if (!identical(data[[1]]$y, data[[i]]$y)) + warning("models do not have the same response vector") + + if (!identical(data[[1]]$weights, data[[i]]$weights)) + stop("all models must have the same weight vector") + } + + if (influence==2) fcall$influence <-3 else fcall$influence <- 1 + flist <- lapply(data, function(d) { + temp <- fcall + temp$y <- d$y + temp$x <- d$x + temp$strata <- d$strata + temp$weights <- d$weights + temp$cluster <- d$cluster + eval(temp, parent.frame()) + }) + + for (i in 2:nfit) { + if (length(flist[[1]]$dfbeta) != length(flist[[i]]$dfbeta)) + stop("models must have identical clustering") + } + count = do.call(rbind, lapply(flist, function(x) { + if (is.matrix(x$count)) colSums(x$count) else x$count})) + + concordance <- sapply(flist, function(x) x$concordance) + dfbeta <- sapply(flist, function(x) x$dfbeta) + + names(concordance) <- fname + rownames(count) <- fname + + wt <- data[[1]]$weights + if (is.null(wt)) vmat <- crossprod(dfbeta) + else vmat <- t(wt * dfbeta) %*% dfbeta + rval <- list(concordance=concordance, count=count, + n=flist[[1]]$n, var=vmat, + cvar= sapply(flist, function(x) x$cvar)) + + if (influence==1) rval$dfbeta <- dfbeta + else if (influence ==2) { + temp <- unlist(lapply(flist, function(x) x$influence)) + rval$influence <- array(temp, + dim=c(dim(flist[[1]]$influence), nfit)) + } + + if (ranks) { + temp <- lapply(flist, function(x) x$ranks) + rdat <- data.frame(fit= rep(fname, sapply(temp, nrow)), + do.call(rbind, temp)) + row.names(rdat) <- NULL + rval$ranks <- rdat + } + } + + class(rval) <- "concordance" + rval +} +@ + +Last, a few miscellaneous methods +<>= +coef.concordance <- function(object, ...) object$concordance +vcov.concordance <- function(object, ...) object$var +@ + +The C routine returns an influence matrix with one row per subject $i$, +and columns giving the partial with respect to $w_i$ for the number of +concordant, discordant, tied on $x$ and ties on $y$ pairs. +Somers' $d$ is $(C-D)/m$ where $m= C + D + T$ is the total number of %' +comparable pairs, which does not count the tied-on-y column. +For any given subject or cluster $k$ (for grouped jackknife) the +IJ estimate of the variance is +\begin{align*} + V &\ \sum_k \left(\frac{\partial d}{\partial w_k}\right)^2 \\ + \frac{\partial d}{\partial w_k} &= + \frac{1}{m} \left[\frac{\partial{C-D}}{\partial w_k} - + d \frac{\partial C+D+T}{\partial w_k} \right] \\ +\end{align*} + +The C code looks a lot like a Cox model: walk forward through time, keep +track of the risk sets, and add something to the totals at each death. +What needs to be summed is the rank of the event subject's $x$ value, as +compared to the value for all others at risk at this time point. +For notational simplicity let $Y_j(t_i)$ be an indicator that subject $j$ +is at risk at event time $t_i$, and $Y^*_j(t_i)$ the more restrictive one that +subject $j$ is both at risk and not a tied event time. +The values we want at time $t_i$ are +\begin{align} + C_i &= v_i \delta_i w_i \sum_j w_j Y^*_j(t_i) \left[I(x_i < x_j) \right] + \label{C} \\ + D_i &= v_i \delta_i w_i \sum_j w_j Y^*_j(t_i) \left[I(x_i > x_j)\right] + \label{D} \\ + T_i &= v_i \delta_i w_i \sum_j w_j Y^*_j(t_i) \left[I(x_i = x_j) \right] + \label{T} \\ +\end{align} + +In the above $v$ is an optional time weight, which we will discuss later. +The normal concordance definition has $v=1$. +$C$, $D$, and $T$ are the number of concordant, discordant, and tied +pairs, respectively, +and $m= C+D+T$ will be the total number of concordant pairs. +Somers' $d$ is $(C-D)/m$ and the concordance is $(d+1)/2 = (C + T/2)/m$. + +The primary compuational question is how to do this efficiently, i.e., better +than a naive algorithm that loops across all $n(n-1)/2$ +possible pairs. +There are two key ideas. +\begin{enumerate} +\item Rearrange the counting so that we do it by death times. + For each death we count the number of other subjects in the risk set whose + score is higher, lower, or tied and add it into the totals. + This neatly solves the question of time-dependent covariates. +\item Counting the number with higher, lower, and tied $x$ can be done in + $O(\log_2 n)$ time if the $x$ data is kept in a binary tree. +\end{enumerate} + +\begin{figure} + \myfig{balance} + \caption{A balanced tree of 13 nodes.} + \label{treefig} +\end{figure} + +Figure \ref{treefig} shows a balanced binary tree containing +13 risk scores. For each node the left child and all its descendants +have a smaller value than the parent, the right child and all its +descendents have a larger value. +Each node in figure \ref{treefig} is also annotated with the total weight +of observations in that node and the weight for itself plus all its children +(not shown on graph). +Assume that the tree shown represents all of the subjects still alive at the +time a particular subject ``Smith'' expires, and that Smith has the risk score +of 19 in the tree. +The concordant pairs are those with a risk score $>19$, i.e., both $\hat y=x$ +and $y$ are larger, discordant are $<19$, and we have no ties. +The totals can be found by +\begin{enumerate} + \item Initialize the counts for discordant, concordant and tied to the + values from the left children, right children, and ties at this node, + respectively, which will be $(C,D,T) = (1,1,0)$. + \item Walk up the tree, and at each step add the (parent + left child) or + (parent + right child) to either D or C, depending on what part of the + tree has not yet been totaled. + At the next node (8) $D= D+4$, and at the top node $C=C + 6$. +\end{enumerate} + +There are 5 concordant and 7 discordant pairs. +This takes a little less than $\log_2(n)$ steps on average, as compared to an +average of $n/2$ for the naive method. The difference can matter when $n$ is +large since this traversal must be done for each event. + +The classic way to store trees is as a linked list. There are several +algorithms for adding and subtracting nodes from a tree while maintaining +the balance (red-black trees, AA trees, etc) but we take a different +approach. Since we need to deal with case weights in the model and we +know all the risk score at the outset, the full set of risk scores is +organised into a tree at the beginning, updating the sums of weights at +each node as observations are added or removed from the risk set. + +If we internally index the nodes of the tree as 1 for the top, +2--3 for the next +horizontal row, 4--7 for the next, \ldots then the parent-child +traversal becomes particularly easy. +The parent of node $i$ is $i/2$ (integer arithmetic) and the children of +node $i$ are $2i$ and $2i +1$. In C code the indices start at 0 of course. +The following bit of code arranges data into such a tree. +<>= +btree <- function(n) { + tfun <- function(n, id, power) { + if (n==1L) id + else if (n==2L) c(2L *id + 1L, id) + else if (n==3L) c(2L*id + 1L, id, 2L*id +2L) + else { + nleft <- if (n== power*2L) power else min(power-1L, n-power%/%2L) + c(tfun(nleft, 2L *id + 1L, power%/%2), id, + tfun(n-(nleft+1L), 2L*id +2L, power%/%2)) + } + } + tfun(as.integer(n), 0L, as.integer(2^(floor(logb(n-1,2))))) +} +@ + +Referring again to figure \ref{treefig}, \code{btree(13)} yields the vector +\code{7 3 8 1 9 4 10 0 11 5 12 2 6} +meaning that the smallest element +will be in position 8 of the tree, the next smallest in position 4, etc, +and using indexing that starts at 0 since the results will be passed to a C +routine. +The code just above takes care to do all arithmetic as integer. +This actually made almost no difference in the compute time, but it was an +interesting exercise to find that out. + +The next question is how to compute a variance for the result. +One approach is to compute an infinitesimal jackknife (IJ) estimate, +for which we need derivatives with respect to the weights. +Looking back at equation \eqref{C} we have +\begin{align} + C &= \sum_i w_i \delta_i \sum_j Y^*_j(t_i) w_j I(x_i < x_j) + \nonumber\\ +% \frac{\partial C}{\partial w_k} &= +% (v_k/m_k)\delta_k \sum_j Y^*_{j}(t_k) I(x_k < x_j) + +% \sum_i (v_i/m_i) w_i Y^*_k(t_i) I(x_i < x_k) \label{partialC} +\end{align} +A given subject's weight appears multiple times, once when they are an +event ($w_i \delta_i)$, and then as part of the risk set for other's +events. I avoided this for some time because it looked like an $O(nd)$ +process to separately update each subject's influence for each risk set +they inhabit, but David Watson pointed out a path forward. +The solution is to keep two trees. +Tree 1 contains all of the subjects at risk. We traverse it when each subject +is added in, updating the tree, +and traverse it again at each death, pulling off values to update our sums. +The second tree holds only the deaths and is updated at each death; +it is read out twice per subject, +once just after they enter the risk set and once when they leave. + +The basic algorithm is to move through an outer and inner loop. The +outer loop moves across unique times, the inner for all obs that +share a death time. We progress from largest to smallest time. +Dealing with tied deaths is a bit subtle. +\begin{itemize} + \item All of the tied deaths need to be added to the event tree before + subtracting the tree values from the ``initial'' influence matrix, since + none of the tied subjects are in the comparison set for each other. + \item Changes to the overall concordance/discordance counts need to be done + for all the ties before adding them into the main tree, for the same reason. + \item The Cox model variance just below has to be added up sequentially, + one terms after each addition to the main tree. +\end{itemize} +Thus the inner loop must be repeated at least twice. + +A second variance computation treats the data as a Cox model. +Create zero-centered scores for all subjects in the risk set: +\begin{align} + z_i(t) &= \sum_{j \in R(t)} w_j \sign(x_i - x_j) \nonumber \\ + D-C &= \sum_i \delta_i z_i(t_i) \label{zcord} +\end{align} +At any event time $\sum w_i z_i =0$. +Equation \eqref{zcord} is the score equation +for a Cox model with time-dependent covariate $z$. +When two subjects have an event at the same time, this formulation treats +each of them as being in the other's risk set whereas the concordance +treats them as incomparable --- how can they be the same? +The trick is that $D-C$ does not change: the tied pairs add equally to +$D$ and $C$. +Under the null hypothesis that the risk score is not related to outcome, +each term in \eqref{zcord} is a random selection from the $z$ scores in +the risk set, and the variance of the addition is the variance of $z$, +the sum of these over deaths is the Cox model information matrix, +which is also the variance of the score statistic. +The mean of $z$ is always zero, so we need to keep track of +$\sum w_i z^2$. + +How can we do this efficiently? First note that $z_i$ can be written +as sum(weights for smaller x) - sum(weights for larger x), and in fact the +weighted mean for any slice of $x$, $a < x < b$, is exactly the +same: mean = sum(weights for x values below the range) - + sum(weights above the range). +The second trick is to use an ANOVA decomposition of the variance of $z$ into +within-slice and between-slice sums of squares, where the 3 slices are the +$z$ scores at a given $x$ value (node of the tree), weights for score below that +cutpoint, and above. +Assume that a new observation $k$ has just been added to the tree. +This will add $w_k$ to all the $z$ values above, and to the weighted mean of +all those above, $-w_k$ to the values and means below, and 0 to the values and +means of any tied observations. Thus none of the current `within' +SS change. +Let $s_a$, $s_b$ and $s_0$ be the current sum of weights above, below, and +at the node of the tree. The mean for the above group was $(s_b + s_0)$ with +between SS contribution of $s_a (s_b + s_0)^2$. The below mean was +$-(s_a + s_0)$ with between SS contribution of $s_b(s_a + s_0)^2$. +The change to the between SS from adding the new subject is +$$ +s_a\left( (s_b+s_0 + w_k)^2 - (s_b + s_0)^2 \right) = +s_a (2w_k (s_b + s_0) + w_k^2) +$$ +while the change in between SS for the below group +is $s_b(2w_k(s_a + s_0) + w_k^2)$, and there is no change for the +prior observations in the middle group. +Last we add $w_kz_k^2 = w_k(s_b- s_a)^2$ to the sum for the new observation. +Putting all this together the change is +$$ + w_k \left(s_a (w_k + (s_b + s_c)) + s_b(w_k + (s_a + s_c)) + (s_a-s_b)^2 \right) +$$ + +We can now define the C-routine that does the bulk of the work. +First we give the outline shell of the code and then discuss the +parts one by one. This routine is for ordinary survival data, and +will be called once per stratum. +Input variables are +\begin{description} + \item[n] the number of observations + \item[y] matrix containing the time and status, data is sorted by descending + time, with censorings precedint deaths. + \item[x] the tree node at which this observation's risk score resides %' + \item[wt] case weight for the observation +\end{description} +The routine will return list with three components: +\begin{itemize} + \item count, a vector containing the weighted number of concordant, + discordant, tied on $x$ but not $y$, and tied on y pairs. + The weight for a pair is $w_iw_j$. + \item resid, a three column matrix with one row per event, containing the + score residual at that event, its variance, and the sum of weights. + The score residual is + a rescaled $z_i$ so as to lie between 0 and 1: $(1+ z/\sum(w))/2$. + The concordance is then a weighted sum of the residuals. + \item influence, a matrix with one row per observation and 4 columns, giving + that observation's first derivative with respect to the count vector. +\end{itemize} + +<>= +#include "survS.h" +#include "survproto.h" + +<> + +SEXP concordance3(SEXP y, SEXP x2, SEXP wt2, SEXP timewt2, + SEXP sortstop, SEXP doresid2) { + int i, j, k, ii, jj, kk, j2; + int n, ntree, nevent; + double *time, *status; + int xsave; + + /* sum of weights for a node (nwt), sum of weights for the node and + ** all of its children (twt), then the same again for the subset of + ** deaths + */ + double *nwt, *twt, *dnwt, *dtwt; + double z2; /* sum of z^2 values */ + + int ndeath; /* total number of deaths at this point */ + int utime; /* number of unique event times seen so far */ + double dwt, dwt2; /* sum of weights for deaths and deaths tied on x */ + double wsum[3]; /* the sum of weights that are > current, <, or equal */ + double temp, adjtimewt; /* the second accounts for npair and timewt*/ + + SEXP rlist, count2, imat2, resid2; + double *count, *imat[5], *resid[4]; + double *wt, *timewt; + int *x, *sort2; + int doresid; + static const char *outnames1[]={"count", "influence", "resid", ""}, + *outnames2[]={"count", "influence", ""}; + + n = nrows(y); + doresid = asLogical(doresid2); + x = INTEGER(x2); + wt = REAL(wt2); + timewt = REAL(timewt2); + sort2 = INTEGER(sortstop); + time = REAL(y); + status = time + n; + + /* if there are tied predictors, the total size of the tree will be < n */ + ntree =0; nevent =0; + for (i=0; i= ntree) ntree = x[i] +1; + nevent += status[i]; + } + + nwt = (double *) R_alloc(4*ntree, sizeof(double)); + twt = nwt + ntree; + dnwt = twt + ntree; + dtwt = dnwt + ntree; + + for (i=0; i< 4*ntree; i++) nwt[i] =0.0; + + if (doresid) PROTECT(rlist = mkNamed(VECSXP, outnames1)); + else PROTECT(rlist = mkNamed(VECSXP, outnames2)); + count2 = SET_VECTOR_ELT(rlist, 0, allocVector(REALSXP, 6)); + count = REAL(count2); + for (i=0; i<6; i++) count[i]=0.0; + imat2 = SET_VECTOR_ELT(rlist, 1, allocMatrix(REALSXP, n, 5)); + for (i=0; i<5; i++) { + imat[i] = REAL(imat2) + i*n; + for (j=0; j> + + UNPROTECT(1); + return(rlist); +} +@ + +The key part of our computation is to update the vectors of weights. +We don't actually pass the risk score values $r$ into the routine, %' +it is enough for each observation to point to the appropriate tree +node. +The tree contains the weights for everyone whose survival is larger +than the time currently under review, so starts with all weights +equal to zero. +For any pair of observations $i,j$ we need to add $w_iw_j$ +to the appropriate count, $w_j$ to subject $i$'s row of the leverage +matrix and $w_i$ to subject $j$'s row. We use two trees to do this +efficiently, one with all the observations to date, one with the events to +date. +Starting at the largest time (which is sorted last), walk through the tree. +\begin{itemize} + \item If the current observation is a censoring time, in order: + \begin{itemize} + \item Subtract event tree information from the influence matrix + \item Update the Cox variance + \item Add them into the main tree + \end{itemize} + \item If the current observation is a death, care for all deaths tied + at this time point. Each pass covers all the deaths. + \begin{itemize} + \item Pass 1: In any order + \begin{itemize} + \item Add up the total number of deaths + \item Update the tied.y count and tied.xy count \\ + tied.xy subtotals reset each time x changes + \item Count concordant, discordant, tied.x counts, both total + and for the observation's influence + \item Add the subject to the event tree + \item Compute the first 3 columns of the residuals. + \end{itemize} + \item Finish up the tied.xy influence, for the last unique x in this set. + \item Pass 2: + \begin{itemize} + \item Subtract the event tree information from the influence matrix + \item Add the tied.y part of the influence for each obs + \item Increment the Cox variance + \item Add the subject into the main tree + \end{itemize} + \end{itemize} + + \item When all the subjects have been added to the tree, then add the final + death tree's data for to the influence matrix. +\end{itemize} + +For concordant, discordant, and tied.x there are three +readouts: the total tree before any additions, the death tree after the +addition of the tied events, and the death tree at the very end. +Increments to the Cox variance occur just before each addition to the total +tree, and are saved out after each batch of events. + +The above discussion counts up all pairs that are not tied on the response $y$. +Though not used in the concordance the routine counts up tied.y pairs as well, +with a separate count for those that are tied on both $x$ and $y$. +The algorithm for this part is simpler since the data is sorted by $y$. +Say that there were 5 obs tied at some time point with weights of $w_1$ to +$w_5$. +The total count for ties involves all 5-choose-2 pairs and can be written as +$$ + w_1 w_2 + (w_1 + w_2)w_3 + (w_1 + w_2 + w_3)w_4 + (w_1 + w_2 + w_3 + w_4)w_5 +$$ +which immediately suggests a simple summation algorithm as we go through the +loop. In the below \code{dwt} contains the running sum 0, $w_1$, $w_1 + w_2$, +etc and we add \code{w[i]*dwt} to the total just before incrementing the sum. +The influence for observation 1 is $w_2 + w_3 + w_4 + w_5$, which can be done +at the end as \code{dwt - wt[i]}. +The temporary accumulator \code{dwt} is reset to 0 with each new $y$ +value. +To compute ties on both $x$ and $y$ the data set is sorted by $x$ within $y$, +and we use the same algorithm, but reset \code{dwt2} to zero whenever +either $x$ or $y$ changes. + +<>= +z2 =0; utime=0; +for (i=0; i>= +void walkup(double *nwt, double* twt, int index, double sums[3], int ntree) { + int i, j, parent; + + for (i=0; i<3; i++) sums[i] = 0.0; + sums[2] = nwt[index]; /* tied on x */ + + j = 2*index +2; /* right child */ + if (j < ntree) sums[0] += twt[j]; + if (j <=ntree) sums[1]+= twt[j-1]; /*left child */ + + while(index > 0) { /* for as long as I have a parent... */ + parent = (index-1)/2; + if (index%2 == 1) sums[0] += twt[parent] - twt[index]; /* left child */ + else sums[1] += twt[parent] - twt[index]; /* I am a right child */ + index = parent; + } +} + +void addin(double *nwt, double *twt, int index, double wt) { + nwt[index] += wt; + while (index >0) { + twt[index] += wt; + index = (index-1)/2; + } + twt[0] += wt; +} +@ + +The code for [start, stop) data is almost identical, the primary call +simply has one more index. +As in the agreg routines there are two sort indices, the first indexes +the data by stop time, longest to earliest, and the second by start time. +The [[y]] variable now has three columns. +<>= + SEXP concordance4(SEXP y, SEXP x2, SEXP wt2, SEXP timewt2, + SEXP sortstart, SEXP sortstop, SEXP doresid2) { + int i, j, k, ii, jj, kk, i2, j2; + int n, ntree, nevent; + double *time1, *time2, *status; + int xsave; + + /* sum of weights for a node (nwt), sum of weights for the node and + ** all of its children (twt), then the same again for the subset of + ** deaths + */ + double *nwt, *twt, *dnwt, *dtwt; + double z2; /* sum of z^2 values */ + + int ndeath; /* total number of deaths at this point */ + int utime; /* number of unique event times seen so far */ + double dwt; /* weighted number of deaths at this point */ + double dwt2; /* tied on both x and y */ + double wsum[3]; /* the sum of weights that are > current, <, or equal */ + double temp, adjtimewt; /* the second accounts for npair and timewt*/ + + SEXP rlist, count2, imat2, resid2; + double *count, *imat[5], *resid[4]; + double *wt, *timewt; + int *x, *sort2, *sort1; + int doresid; + static const char *outnames1[]={"count", "influence", "resid", ""}, + *outnames2[]={"count", "influence", ""}; + + n = nrows(y); + doresid = asLogical(doresid2); + x = INTEGER(x2); + wt = REAL(wt2); + timewt = REAL(timewt2); + sort2 = INTEGER(sortstop); + sort1 = INTEGER(sortstart); + time1 = REAL(y); + time2 = time1 + n; + status = time2 + n; + + /* if there are tied predictors, the total size of the tree will be < n */ + ntree =0; nevent =0; + for (i=0; i= ntree) ntree = x[i] +1; + nevent += status[i]; + } + + /* + ** nwt and twt are the node weight and total =node + all children for the + ** tree holding all subjects. dnwt and dtwt are the same for the tree + ** holding all the events + */ + nwt = (double *) R_alloc(4*ntree, sizeof(double)); + twt = nwt + ntree; + dnwt = twt + ntree; + dtwt = dnwt + ntree; + + for (i=0; i< 4*ntree; i++) nwt[i] =0.0; + + if (doresid) PROTECT(rlist = mkNamed(VECSXP, outnames1)); + else PROTECT(rlist = mkNamed(VECSXP, outnames2)); + count2 = SET_VECTOR_ELT(rlist, 0, allocVector(REALSXP, 6)); + count = REAL(count2); + for (i=0; i<6; i++) count[i]=0.0; + imat2 = SET_VECTOR_ELT(rlist, 1, allocMatrix(REALSXP, n, 5)); + for (i=0; i<5; i++) { + imat[i] = REAL(imat2) + i*n; + for (j=0; j> + + UNPROTECT(1); + return(rlist); +} +@ + + As we move from the longest time to the shortest observations are added + into the tree of weights whenever we encounter their stop time. + This is just as before. Weights now also need to be removed from the + tree whenever we encounter an observation's start time. %' + It is convenient ``catch up'' on this second task whenever we encounter + a death. + +<>= +z2 =0; utime=0; i2 =0; /* i2 tracks the start times */ +for (i=0; i= time2[ii]); i2++) { + jj = sort1[i2]; + /* influence */ + walkup(dnwt, dtwt, x[jj], wsum, ntree); + imat[0][jj] += wsum[1]; + imat[1][jj] += wsum[0]; + imat[2][jj] += wsum[2]; + + addin(nwt, twt, x[jj], -wt[jj]); /*remove from main tree */ + + /* Cox variance */ + walkup(nwt, twt, x[jj], wsum, ntree); + z2 -= wt[jj]*(wsum[0]*(wt[jj] + 2*(wsum[1] + wsum[2])) + + wsum[1]*(wt[jj] + 2*(wsum[0] + wsum[2])) + + (wsum[0]-wsum[1])*(wsum[0]-wsum[1])); + } + + ndeath=0; dwt=0; + dwt2 =0; xsave=x[ii]; j2= i; + adjtimewt = timewt[utime++]; + + /* pass 1 */ + for (j=i; j>= +survexp <- function(formula, data, + weights, subset, na.action, rmap, times, + method=c("ederer", "hakulinen", "conditional", "individual.h", + "individual.s"), + cohort=TRUE, conditional=FALSE, + ratetable=survival::survexp.us, scale=1, se.fit, + model=FALSE, x=FALSE, y=FALSE) { + <> + <> + <> + <> +} +@ + + +The first few lines are standard. Keep a copy of the call, then manufacture +a call to [[model.frame]] that contains only the arguments relevant to that +function. +<>= +Call <- match.call() + +# keep the first element (the call), and the following selected arguments +indx <- match(c('formula', 'data', 'weights', 'subset', 'na.action'), + names(Call), nomatch=0) +if (indx[1] ==0) stop("A formula argument is required") +tform <- Call[c(1,indx)] # only keep the arguments we wanted +tform[[1L]] <- quote(stats::model.frame) # change the function called + +Terms <- if(missing(data)) terms(formula, 'ratetable') + else terms(formula, 'ratetable',data=data) +@ + +The function works with two data sets, the user's data on an actual set of %' +subjects and the reference ratetable. +This leads to a particular nuisance, that the variable names in the data +set may not match those in the ratetable. +For instance the United States overall death rate table [[survexp.us]] expects +3 variables, as shown by [[summary(survexp.us)]] +\begin{itemize} + \item age = age in days for each subject at the start of follow-up + \item sex = sex of the subject, ``male'' or ``female'' (the routine accepts + any unique abbreviation and is case insensitive) + \item year = date of the start of follow-up + \end{itemize} + +Up until the most recent revision, the +formula contained any necessary mapping between the variables in the data +set and +the ratetable. For instance +\begin{verbatim} + survexp( ~ sex + ratetable(age=age*365.25, sex=sex, + year=entry.dt), + data=mydata, ratetable=survexp.us) +\end{verbatim} +In this case the user's data set has a variable `age' containing age in years, +along with sex and an entry date. +This had to be changed for two reasons. The primary one is that the data +in a [[ratetable]] call had to be converted into a matrix in order to ``pass +through'' the model.frame logic. With the recent updates to coxph so that it +remembers factor codings correctly in new data sets, it is advantageous to +keep factors as factors. +The second is that a coxph model with a large number of covariates induces a +very long ratetable clause; at about 40 variable it caused one of the +R internal +routines to fail due to a long expression. +A third reason, perhaps the most pressing in reality, is that I've always %' +felt that the prior code was confusing since it used the same term 'ratetable' +for two different tasks. + +The new process adds the [[rmap]] argument, an example would be +[[rmap=list(age =age*365.25, year=entry.dt)]]. +Any variables in the ratetable that are not found in [[rmap]] are assumed to +not need a mapping, this would be [[sex]] in the above example. +For backwards compatability we allow the old style argument, converting it +into the new style. + +The [[rmap]] argument needs to be examined without evaluating it; we then add +the appropriate extra variables into a temporary formula so that the model +frame has all that is required. The ratetable variables then can be +retrieved from the model frame. +The [[pyears]] routine uses the same rmap argument; this segment of the +code is given its own name so that it can be included there as well. +<>= +rate <- attr(Terms, "specials")$ratetable +if(length(rate) > 1) + stop("Can have only 1 ratetable() call in a formula") +<> + +mf <- eval(tform, parent.frame()) +@ +<>= +if(length(rate) == 1) { + if (!missing(rmap)) + stop("The ratetable() call in a formula is depreciated") + + stemp <- untangle.specials(Terms, 'ratetable') + rcall <- as.call(parse(text=stemp$var)[[1]]) # as a call object + rcall[[1]] <- as.name('list') # make it a call to list(.. + Terms <- Terms[-stemp$terms] # remove from the formula + } +else if (!missing(rmap)) { + rcall <- substitute(rmap) + if (!is.call(rcall) || rcall[[1]] != as.name('list')) + stop ("Invalid rcall argument") + } +else rcall <- NULL # A ratetable, but no rcall argument + +# Check that there are no illegal names in rcall, then expand it +# to include all the names in the ratetable +if (is.ratetable(ratetable)) { + varlist <- names(dimnames(ratetable)) + if (is.null(varlist)) varlist <- attr(ratetable, "dimid") # older style +} +else if(inherits(ratetable, "coxph") && !inherits(ratetable, "coxphms")) { + ## Remove "log" and such things, to get just the list of + # variable names + varlist <- all.vars(delete.response(ratetable$terms)) + } +else stop("Invalid rate table") + +temp <- match(names(rcall)[-1], varlist) # 2,3,... are the argument names +if (any(is.na(temp))) + stop("Variable not found in the ratetable:", (names(rcall))[is.na(temp)]) + +if (any(!(varlist %in% names(rcall)))) { + to.add <- varlist[!(varlist %in% names(rcall))] + temp1 <- paste(text=paste(to.add, to.add, sep='='), collapse=',') + if (is.null(rcall)) rcall <- parse(text=paste("list(", temp1, ")"))[[1]] + else { + temp2 <- deparse(rcall) + rcall <- parse(text=paste("c(", temp2, ",list(", temp1, "))"))[[1]] + } + } +@ + +The formula below is used only in the call to [[model.frame]] to ensure +that the frame has both the formula and the ratetable variables. +We don't want to modify the original formula, since we use it to create +the $X$ matrix and the response variable. +The non-obvious bit of code is the addition of an environment to the +formula. The [[model.matrix]] routine has a non-standard evaluation - it +uses the frame of the formula, rather than the parent.frame() argument +below, along with the [[data]] to look up variables. +If a formula is long enough deparse() will give two lines, hence the +extra paste call to re-collapse it into one. +<>= +# Create a temporary formula, used only in the call to model.frame +newvar <- all.vars(rcall) +if (length(newvar) > 0) { + temp <- paste(paste(deparse(Terms), collapse=""), + paste(newvar, collapse='+'), sep='+') + tform$formula <- as.formula(temp, environment(Terms)) + } +@ + +If the user data has 0 rows, e.g. from a mistaken [[subset]] statement +that eliminated all subjects, we need to stop early. Otherwise the +.C code fails in a nasty way. +<>= +n <- nrow(mf) +if (n==0) stop("Data set has 0 rows") +if (!missing(se.fit) && se.fit) + warning("se.fit value ignored") + +weights <- model.extract(mf, 'weights') +if (length(weights) ==0) weights <- rep(1.0, n) +if (class(ratetable)=='ratetable' && any(weights !=1)) + warning("weights ignored") + +if (any(attr(Terms, 'order') >1)) + stop("Survexp cannot have interaction terms") +if (!missing(times)) { + if (any(times<0)) stop("Invalid time point requested") + if (length(times) >1 ) + if (any(diff(times)<0)) stop("Times must be in increasing order") + } +@ + +If a response variable was given, we only need the times and not the +status. To be correct, +computations need to be done for each of the times given in +the [[times]] argument as well as for each of the unique y values. +This ends up as the vector [[newtime]]. If a [[times]] argument was +given we will subset down to only those values at the end. +For a population rate table and the Ederer method the times argument is +required. +<>= +Y <- model.extract(mf, 'response') +no.Y <- is.null(Y) +if (no.Y) { + if (missing(times)) { + if (is.ratetable(ratetable)) + stop("either a times argument or a response is needed") + } + else newtime <- times + } +else { + if (is.matrix(Y)) { + if (is.Surv(Y) && attr(Y, 'type')=='right') Y <- Y[,1] + else stop("Illegal response value") + } + if (any(Y<0)) stop ("Negative follow up time") +# if (missing(npoints)) temp <- unique(Y) +# else temp <- seq(min(Y), max(Y), length=npoints) + temp <- unique(Y) + if (missing(times)) newtime <- sort(temp) + else newtime <- sort(unique(c(times, temp[temp>= +ovars <- attr(Terms, 'term.labels') +# rdata contains the variables matching the ratetable +rdata <- data.frame(eval(rcall, mf), stringsAsFactors=TRUE) +if (is.ratetable(ratetable)) { + israte <- TRUE + if (no.Y) { + Y <- rep(max(times), n) + } + rtemp <- match.ratetable(rdata, ratetable) + R <- rtemp$R + } +else if (inherits(ratetable, 'coxph')) { + israte <- FALSE + Terms <- ratetable$terms +# if (!is.null(attr(Terms, 'offset'))) +# stop("Cannot deal with models that contain an offset") +# strats <- attr(Terms, "specials")$strata +# if (length(strats)) +# stop("survexp cannot handle stratified Cox models") +# + if (any(names(mf[,rate]) != attr(ratetable$terms, 'term.labels'))) + stop("Unable to match new data to old formula") + } +else stop("Invalid ratetable") +@ + +Now for some calculation. If cohort is false, then any covariates on the +right hand side (other than the rate table) are irrelevant, the function +returns a vector of expected values rather than survival curves. +<>= +if (substring(method, 1, 10) == "individual") { #individual survival + if (no.Y) stop("for individual survival an observation time must be given") + if (israte) + temp <- survexp.fit (1:n, R, Y, max(Y), TRUE, ratetable) + else { + rmatch <- match(names(data), names(rdata)) + if (any(is.na(rmatch))) rdata <- cbind(rdata, data[,is.na(rmatch)]) + temp <- survexp.cfit(1:n, rdata, Y, 'individual', ratetable) + } + if (method == "individual.s") xx <- temp$surv + else xx <- -log(temp$surv) + names(xx) <- row.names(mf) + na.action <- attr(mf, "na.action") + if (length(na.action)) return(naresid(na.action, xx)) + else return(xx) + } +@ + +Now for the more commonly used case: returning a survival curve. +First see if there are any grouping variables. +The results of the [[tcut]] function are often used in person-years +analysis, which is somewhat related to expected survival. However +tcut results aren't relevant here and we put in a check for the %' +confused user. +The strata command creates a single factor incorporating all the +variables. +<>= +if (length(ovars)==0) X <- rep(1,n) #no categories +else { + odim <- length(ovars) + for (i in 1:odim) { + temp <- mf[[ovars[i]]] + ctemp <- class(temp) + if (!is.null(ctemp) && ctemp=='tcut') + stop("Can't use tcut variables in expected survival") + } + X <- strata(mf[ovars]) + } + +#do the work +if (israte) + temp <- survexp.fit(as.numeric(X), R, Y, newtime, + method=="conditional", ratetable) +else { + temp <- survexp.cfit(as.numeric(X), rdata, Y, method, ratetable, weights) + newtime <- temp$time + } +@ + +Now we need to package up the curves properly +All the results can +be returned as a single matrix of survivals with a common vector of times. +If there was a times argument we need to subset to selected rows of the +computation. +<>= +if (missing(times)) { + n.risk <- temp$n + surv <- temp$surv + } +else { + if (israte) keep <- match(times, newtime) + else { + # The result is from a Cox model, and it's list of + # times won't match the list requested in the user's call + # Interpolate the step function, giving survival of 1 + # for requested points that precede the Cox fit's + # first downward step. The code is like summary.survfit. + n <- length(temp$time) + keep <- approx(temp$time, 1:n, xout=times, yleft=0, + method='constant', f=0, rule=2)$y + } + + if (is.matrix(temp$surv)) { + surv <- (rbind(1,temp$surv))[keep+1,,drop=FALSE] + n.risk <- temp$n[pmax(1,keep),,drop=FALSE] + } + else { + surv <- (c(1,temp$surv))[keep+1] + n.risk <- temp$n[pmax(1,keep)] + } + newtime <- times + } +newtime <- newtime/scale +if (is.matrix(surv)) { + dimnames(surv) <- list(NULL, levels(X)) + out <- list(call=Call, surv= drop(surv), n.risk=drop(n.risk), + time=newtime) + } +else { + out <- list(call=Call, surv=c(surv), n.risk=c(n.risk), + time=newtime) + } +@ + +Last do the standard things: add the model, x, or y components to the output +if the user asked for them. (For this particular routine I can't think of %' +a reason they every would.) Copy across summary information from the +rate table computation if present, and add the method and class to the +output. +<>= +if (model) out$model <- mf +else { + if (x) out$x <- X + if (y) out$y <- Y + } +if (israte && !is.null(rtemp$summ)) out$summ <- rtemp$summ +if (no.Y) out$method <- 'Ederer' +else if (conditional) out$method <- 'conditional' +else out$method <- 'cohort' +class(out) <- c('survexp', 'survfit') +out +@ + +\subsection{Parsing the covariates list} +For a multi-state Cox model we allow a list of formulas to take the place +of the \code{formula} argument. +The first element of the list is the default formula, later elements +are of the form \code{transitions ~ formula/options}, where the left hand side +denotes one or more transitions, and the right hand side is used to augment +the basic formula wrt those transitions. + +Step 1 is to break the formula into parts. There will be a list of left sides, +a list of right sides, and a list of options. +From this we can create a single ``pseudo formula'' that is used to drive +the model.frame process, which ensures that all of the variables we need +will be found in the model frame. +Further processing has to wait until after the model frame has been constructed, +i.e., if a left side referred to state ``deathh'' that might be a real state +or a typing mistake, we can't know until the data is in hand. + +Should we walk the parse tree of the formula, or convert it to character and use +string manipulations? The latter looks promising until you see a fragment +like this: +\code{entry:death ~ age/sex + ns(weight/height, df=4) / common} +Walking the parse tree is a bit more subtle, but we then can take advantage of +all the knowledge built into the R parser. +A formula is a 3 element list of ``~'', leftside, rightside, or 2 elements if +it has only a right hand side. Legal ones for coxph have both left and right. + +<>= +parsecovar1 <- function(flist, statedata) { + if (any(sapply(flist, function(x) !inherits(x, "formula")))) + stop("an element of the formula list is not a formula") + if (any(sapply(flist, length) != 3)) + stop("all formulas must have a left and right side") + + # split the formulas into a right hand and left hand side + lhs <- lapply(flist, function(x) x[-3]) # keep the ~ + rhs <- lapply(flist, function(x) x[[3]]) # don't keep the ~ + + rhs <- parse_rightside(rhs) + <> + list(rhs = rhs, lhs= lterm) +} +@ + +\begin{figure} + \includegraphics{figures/fig1.pdf} + \caption{The parse tree for the formula + \code{1:3 +2:3 ~ strata(sex)/(age + trt) + ns(weight/ht, df=4) / common + shared}} + \label{figparse} +\end{figure} + +Figure \ref{figparse} shows the parse tree for a complex formula. +The following function splits the formula at the rightmost slash, ignoring the +inside of any function or parenthesised phrase. +Recursive functions like this are almost impossible to read, but luckily +it is short. +The formula recurrs on the left and right side of +*: and \%in\%, and on +binary - (but not on unary -). +<>= +rightslash <- function(x) { + if (class(x) != 'call') return(x) + else { + if (x[[1]] == as.name('/')) return(list(x[[2]], x[[3]])) + else if (x[[1]]==as.name('+') || (x[[1]]==as.name('-') && length(x)==3)|| + x[[1]]==as.name('*') || x[[1]]==as.name(':') || + x[[1]]==as.name('%in%')) { + temp <- rightslash(x[[3]]) + if (is.list(temp)) { + x[[3]] <- temp[[1]] + return(list(x, temp[[2]])) + } else { + temp <- rightslash(x[[2]]) + if (is.list(temp)) { + x[[2]] <- temp[[2]] + return(list(temp[[1]], x)) + } else return(x) + } + } + else return(x) + } +} +@ + +There are 4 possble options of common, shared, and init. +The first 2 appear just as words, the last should have a set of +values attached which become the \code{ival} vector. +There will, of course, one day be a user with a variable named \code{common} +who wants a nested term \code{x/common}. Since we don't look inside +parenthesis they will be able to use \code{1:3 ~ (x/common)}. + +<>= +parse_rightside <- function(rhs) { + parts <- lapply(rhs, rightslash) + new <- lapply(parts, function(opt) { + tform <- ~ x # a skeleton, "x" will be replaced + if (!is.list(opt)) { # no options for this line + tform[[2]] <- opt + list(formula = tform, ival = NULL, common = FALSE, + shared = FALSE) + } + else{ + # treat the option list as though it were a formula + temp <- ~ x + temp[[2]] <- opt[[2]] + optterms <- terms(temp) + ff <- rownames(attr(optterms, "factors")) + index <- match(ff, c("common", "shared", "init")) + if (any(is.na(index))) + stop("option not recognized in a covariates formula: ", + paste(ff[is.na(index)], collapse=", ")) + common <- any(index==1) + shared <- any(index==2) + if (any(index==3)) { + optatt <- attributes(optterms) + j <- optatt$variables[1 + which(index==3)] + j[[1]] <- as.name("list") + ival <- unlist(eval(j, parent.frame())) + } + else ival <- NULL + tform[[2]] <- opt[[1]] + list(formula= tform, ival= ival, common= common, shared=shared) + } + }) + new +} +@ + +The left hand side of each formula specifies the set of transitions to which +the covariates apply, and is more complex. +Say instance that we had 7 states and the following statedata +data set. +\begin{center} + \begin{tabular}{cccc} + state & A& N& death \\ \hline + A-N- & 0& 0 & 0\\ + A+N- & 1& 0 & 0\\ + A-N1 & 0& 1 & 0\\ + A+N1 & 1& 1 & 0\\ + A-N2 & 0& 2 & 0\\ + A+N2 & 1& 2 & 0\\ + Death& NA & NA& 1 +\end{tabular} +\end{center} + + Here are some valid transitions +\begin{enumerate} + \item 0:state('A+N+'), any transition to the A+N+ state + \item state('A-N-'):death(0), a transition from A-N-, but not to death + \item A(0):A(1), any of the 4 changes that start with A=0 and end with A=1 + \item N(0):N(1,2) + N(1):N(2), an upward change of N + \item 'A-N-':c('A-N+','A+N-'); if there is no variable then the + overall state is assumed + \item 1:3 + 2:3; we can refer to states by number, and we can have multiples +\end{enumerate} + +<>= +# deal with the left hand side of the formula +# the next routine cuts at '+' signs +pcut <- function(form) { + if (length(form)==3) { + if (form[[1]] == '+') + c(pcut(form[[2]]), pcut(form[[3]])) + else if (form[[1]] == '~') pcut(form[[2]]) + else list(form) + } + else list(form) +} +lcut <- lapply(lhs, function(x) pcut(x[[2]])) +@ +We now have one list per formula, each list is either a single term +or a list of terms (case 4 above). +To make evaluation easier, create functions that append their +name to a list of values. +I have not yet found a way to do this without eval(parse()), which +always seems clumsy. +A use for the labels without an argument will arise later, hence the +double environments. + +Repeating the list above, this is what we want to end with +\begin{itemize} + \item a list with one element per formula in the covariates list + \item each element is a list, with one element per term: multiple + a:b terms are allowed separated by + signs + \item each of these level 3 elements is a list with two elements + ``left'' and ``right'', for the two sides of the : operator + \item left and right will be one of 3 forms: a simple vector, + a one element list containing the stateid, or a two element list + containing the stateid and the values. + Any word that doesn't match one of the + column names of statedata ends up as a vector. +\end{itemize} + +<>= +env1 <- new.env(parent= parent.frame(2)) +env2 <- new.env(parent= env1) +if (missing(statedata)) { + assign("state", function(...) list(stateid= "state", + values=c(...)), env1) + assign("state", list(stateid="state")) +} +else { + for (i in statedata) { + assign(i, eval(list(stateid=i)), env2) + tfun <- eval(parse(text=paste0("function(...) list(stateid='" + , i, "', values=c(...))"))) + assign(i, tfun, env1) + } +} +lterm <- lapply(lcut, function(x) { + lapply(x, function(z) { + if (length(z)==1) { + temp <- eval(z, envir= env2) + if (is.list(temp) && names(temp)[[1]] =="stateid") temp + else temp + } + else if (length(z) ==3 && z[[1]]==':') + list(left=eval(z[[2]], envir=env2), right=eval(z[[3]], envir=env2)) + else stop("invalid term: ", deparse(z)) + }) +}) +@ + + +The second call, which builds tmap, the terms map. +Arguments are the results from the first pass, the statedata data frame, +the default formula, the terms structure from the full formula, +and the transitions count. + +One nuisance is that the terms function sometimes inverts things. For +example in the formula +\code{terms(~ x1 + x1:iage + x2 + x2:iage)} the label for the second +of these becomes \code{iage:x2}. +I'm guessing it is because the variable first appear in the order x1, iage, x2 +and labels make use of that order. +But when we look at the formula fragment \code{~ x2 + x2:iage} the terms +will be in the other order. +A way out of this is to use the simple \code{termmatch} function below, +which keys off of the factors attribute instead of the names. + +<>= +termmatch <- function(f1, f2) { + # look for f1 in f2, each the factors attribute of a terms object + if (length(f1)==0) return(NULL) # a formula with only ~1 + irow <- match(rownames(f1), rownames(f2)) + if (any(is.na(irow))) stop ("termmatch failure 1") + hashfun <- function(j) sum(ifelse(j==0, 0, 2^(seq(along.with=j)))) + hash1 <- apply(f1, 2, hashfun) + hash2 <- apply(f2[irow,,drop=FALSE], 2, hashfun) + index <- match(hash1, hash2) + if (any(is.na(index))) stop("termmatch failure 2") + index +} + +parsecovar2 <- function(covar1, statedata, dformula, Terms, transitions,states) { + if (is.null(statedata)) + statedata <- data.frame(state = states, stringsAsFactors=FALSE) + else { + if (is.null(statedata$state)) + stop("the statedata data set must contain a variable 'state'") + indx1 <- match(states, statedata$state, nomatch=0) + if (any(indx1==0)) + stop("statedata does not contain all the possible states: ", + states[indx1==0]) + statedata <- statedata[indx1,] # put it in order + } + + # Statedata might have rows for states that are not in the data set, + # for instance if the coxph call had used a subset argument. Any of + # those were eliminated above. + # Likewise, the formula list might have rules for transitions that are + # not present. Don't worry about it at this stage. + allterm <- attr(Terms, 'factors') + nterm <- ncol(allterm) + + # create a map for every transition, even ones that are not used. + # at the end we will thin it out + # It has an extra first row for intercept (baseline) + # Fill it in with the default formula + nstate <- length(states) + tmap <- array(0, dim=c(nterm+1, nstate, nstate)) + dmap <- array(seq_len(length(tmap)), dim=c(nterm+1, nstate, nstate)) #unique values + dterm <- termmatch(attr(terms(dformula), "factors"), allterm) + dterm <- c(1L, 1L+ dterm) # add intercept + tmap[dterm,,] <- dmap[dterm,,] + inits <- NULL + + if (!is.null(covar1)) { + <> + } + <> +} +@ + +Now go through the formulas one by one. The left hand side tells us which +state:state transitions to fill in, the right hand side tells the variables. +The code block below goes through lhs element(s) for a single formula. +That element is itself a list which has an entry for each term, and that +entry can have left and right portions. +<>= +state1 <- state2 <- NULL +for (x in lhs) { + # x is one term + if (!is.list(x) || is.null(x$left)) stop("term found without a ':' ", x) + # left of the colon + if (!is.list(x$left) && length(x$left) ==1 && x$left==0) + temp1 <- 1:nrow(statedata) + else if (is.numeric(x$left)) { + temp1 <- as.integer(x$left) + if (any(temp1 != x$left)) stop("non-integer state number") + if (any(temp1 <1 | temp1> nstate)) + stop("numeric state is out of range") + } + else if (is.list(x$left) && names(x$left)[1] == "stateid"){ + if (is.null(x$left$value)) + stop("state variable with no list of values: ",x$left$stateid) + else { + if (any(k= is.na(match(x$left$stateid, names(statedata))))) + stop(x$left$stateid[k], ": state variable not found") + zz <- statedata[[x$left$stateid]] + if (any(k= is.na(match(x$left$value, zz)))) + stop(x$left$value[k], ": state value not found") + temp1 <- which(zz %in% x$left$value) + } + } + else { + k <- match(x$left, statedata$state) + if (any(is.na(k))) stop(x$left[is.na(k)], ": state not found") + temp1 <- which(statedata$state %in% x$left) + } + + # right of colon + if (!is.list(x$right) && length(x$right) ==1 && x$right ==0) + temp2 <- 1:nrow(statedata) + else if (is.numeric(x$right)) { + temp2 <- as.integer(x$right) + if (any(temp2 != x$right)) stop("non-integer state number") + if (any(temp2 <1 | temp2> nstate)) + stop("numeric state is out of range") + } + else if (is.list(x$right) && names(x$right)[1] == "stateid") { + if (is.null(x$right$value)) + stop("state variable with no list of values: ",x$right$stateid) + else { + if (any(k= is.na(match(x$right$stateid, names(statedata))))) + stop(x$right$stateid[k], ": state variable not found") + zz <- statedata[[x$right$stateid]] + if (any(k= is.na(match(x$right$value, zz)))) + stop(x$right$value[k], ": state value not found") + temp2 <- which(zz %in% x$right$value) + } + } + else { + k <- match(x$right, statedata$state) + if (any(is.na(k))) stop(x$right[k], ": state not found") + temp2 <- which(statedata$state %in% x$right) + } + + + state1 <- c(state1, rep(temp1, length(temp2))) + state2 <- c(state2, rep(temp2, each=length(temp1))) +} +@ +At the end it has created to vectors state1 and state2 listing all +the pairs of states that are indicated. + +The init clause (initial values) are gathered but not checked: +we don't yet know how many columns a term will expand into. +tmap is a 3 way array: term, state1, state2 containing coefficient numbers and +zeros. + +<>= +for (i in 1:length(covar1$rhs)) { + rhs <- covar1$rhs[[i]] + lhs <- covar1$lhs[[i]] # one rhs and one lhs per formula + + <> + npair <- length(state1) # number of state:state pairs for this line + + # update tmap for this set of transitions + # first, what variables are mentioned, and check for errors + rterm <- terms(rhs$formula) + rindex <- 1L + termmatch(attr(rterm, "factors"), allterm) + + # the update.formula function is good at identifying changes + # formulas that start with "- x" have to be pasted on carefully + temp <- substring(deparse(rhs$formula, width.cutoff=500), 2) + if (substring(temp, 1,1) == '-') dummy <- formula(paste("~ .", temp)) + else dummy <- formula(paste("~. +", temp)) + + rindex1 <- termmatch(attr(terms(dformula), "factors"), allterm) + rindex2 <- termmatch(attr(terms(update(dformula, dummy)), "factors"), + allterm) + dropped <- 1L + rindex1[is.na(match(rindex1, rindex2))] # remember the intercept + if (length(dropped) >0) { + for (k in 1:npair) tmap[dropped, state1[k], state2[k]] <- 0 + } + + # grab initial values + if (length(rhs$ival)) + inits <- c(inits, list(term=rindex, state1=state1, + state2= state2, init= rhs$ival)) + + # adding -1 to the front is a trick, to check if there is a "+1" term + dummy <- ~ -1 + x + dummy[[2]][[3]] <- rhs$formula + if (attr(terms(dummy), "intercept") ==1) rindex <- c(1L, rindex) + + # an update of "- sex" won't generate anything to add + # dmap is simply an indexed set of unique values to pull from, so that + # no number is used twice + if (length(rindex) > 0) { # rindex = things to add + if (rhs$common) { + j <- dmap[rindex, state1[1], state2[1]] + for(k in 1:npair) tmap[rindex, state1[k], state2[k]] <- j + } + else { + for (k in 1:npair) + tmap[rindex, state1[k], state2[k]] <- dmap[rindex, state1[k], state2[k]] + } + } + + # Deal with the shared argument, using - for a separate coef + if (rhs$shared && npair>1) { + j <- dmap[1, state1[1], state2[1]] + for (k in 2:npair) + tmap[1, state1[k], state2[k]] <- -j + } +} +@ + + +Fold the 3-dimensional tmap into a matrix with terms as rows +and one column for each transition that actually occured. + +<>= +i <- match("(censored)", colnames(transitions), nomatch=0) +if (i==0) t2 <- transitions +else t2 <- transitions[,-i, drop=FALSE] # transitions to 'censor' don't count +indx1 <- match(rownames(t2), states) +indx2 <- match(colnames(t2), states) +tmap2 <- matrix(0L, nrow= 1+nterm, ncol= sum(t2>0)) + +trow <- row(t2)[t2>0] +tcol <- col(t2)[t2>0] +for (i in 1:nrow(tmap2)) { + for (j in 1:ncol(tmap2)) + tmap2[i,j] <- tmap[i, indx1[trow[j]], indx2[tcol[j]]] +} + +# Remember which hazards had ph +# tmap2[1,] is the 'intercept' row +# If the hazard for colum 6 is proportional to the hazard for column 2, +# the tmap2[1,2] = tmap[1,6], and phbaseline[6] =2 +temp <- tmap2[1,] +tmap2[1,] <- match(abs(tmap2[1,]), unique(abs(temp))) +phbaseline <- ifelse(temp<0, tmap2[1,], 0) + +if (nrow(tmap2) > 1) + tmap2[-1,] <- match(tmap2[-1,], unique(c(0L, tmap2[-1,]))) -1L + +dimnames(tmap2) <- list(c("(Baseline)", colnames(allterm)), + paste(indx1[trow], indx2[tcol], sep=':')) +# mapid gives the from,to for each realized state +list(tmap = tmap2, inits=inits, mapid= cbind(from=indx1[trow], to=indx2[tcol]), + phbaseline = phbaseline) +@ + + +Last is a helper routine that converts tmap, which has one row per term, +into cmap, which has one row per coefficient. Both have one column per +transition. +It uses the assign attribute of the X matrix along with the column names. + +Consider the model \code{~ x1 + strata(x2) + factor(x3)} where x3 has 4 levels. +The Xassign vector will be 1, 3, 3, 3, since it refers to terms and there are 3 +columns of X for term number 3. +If there were an intercept the first column of X +would be a 1 and Xassign would be 0, 1, 3, 3, 3. + +Let's say that there were 3 transitions and tmap looks like this: +\begin{tabular}{rccc} + & 1:2 & 1:3 & 2:3 \\ +(Baseline) & 1 & 2 & 3 \\ + x1 & 1 & 4 & 4 \\ + strata(x2) & 2 & 5 & 6 \\ + factor(x3) & 3 & 3 & 7 +\end{tabular} +The cmap matrix will ignore rows 1 and 3 since they do not correspond to +coefficients in the model. + +<>= +parsecovar3 <- function(tmap, Xcol, Xassign, phbaseline=NULL) { + # sometime X will have an intercept, sometimes not; cmap never does + hasintercept <- (Xassign[1] ==0) + + ptemp <- phbaseline[phbaseline >0] + nph.coef <- length(ptemp) + nph.row <- length(unique(ptemp)) + cmap <- matrix(0L, length(Xcol) + nph.row - hasintercept, ncol(tmap)) + uterm <- unique(Xassign[Xassign != 0]) # terms that will have coefficients + + xcount <- table(factor(Xassign, levels=1:max(Xassign))) + mult <- 1+ max(xcount) # temporary scaling + + ii <- 0 + for (i in uterm) { + k <- seq_len(xcount[i]) + for (j in 1:ncol(tmap)) + cmap[ii+k, j] <- if(tmap[i+1,j]==0) 0 else tmap[i+1,j]*mult +k + ii <- ii + max(k) + } + + if (nph.row > 0) { + i <- length(Xcol)- hasintercept # non-ph rows in cmap + j <- cbind(i+ match(ptemp, unique(ptemp)), which(phbaseline>0)) + cmap[j] <- max(cmap) + seq(along.with =ptemp) + newname <- paste0("ph(",colnames(tmap)[unique(ptemp)], ")") + } else newname <- NULL + + # renumber coefs as 1, 2, 3, ... + cmap[,] <- match(cmap, sort(unique(c(0L, cmap)))) -1L + + colnames(cmap) <- colnames(tmap) + if (hasintercept) rownames(cmap) <- c(Xcol[-1], newname) + else rownames(cmap) <- c(Xcol, newname) + + cmap +} +@ +\section{Person years} +The person years routine and the expected survival code are the +two parts of the survival package that make use of external +rate tables, of which the United States mortality tables \code{survexp.us} +and \code{survexp.usr} are examples contained in the package. +The arguments for pyears are +\begin{description} + \item[formula] The model formula. The right hand side consists of grouping + variables and is essentially identical to [[survfit]], the result of the + model will be a table of results with dimensions determined from the + right hand variables. The formula can include an optional [[ratetable]] + directive; but this style has been superseded by the [[rmap]] argument. + \item [data, weights, subset, na.action] as usual + \item[rmap] an optional mapping for rate table variables, see more below. + \item[ratetable] the population rate table to use as a reference. This can + either be a ratetable object or a previously fitted Cox model + \item[scale] Scale the resulting output times, e.g., 365.25 to turn days into + years. + \item[expect] Should the output table include the expected number of + events, or the expected number of person-years of observation? + \item[model, x, y] as usual + \item[data.frame] if true the result is returned as a data frame, if false + as a set of tables. +\end{description} + +<>= +pyears <- function(formula, data, + weights, subset, na.action, rmap, + ratetable, scale=365.25, expect=c('event', 'pyears'), + model=FALSE, x=FALSE, y=FALSE, data.frame=FALSE) { + + <> + <> + <> + } +@ + +Start out with the standard model processing, which involves making a copy +of the input call, but keeping only the arguments we want. +We then process the special argument [[rmap]]. This is discussed in the +section on the [[survexp]] function so we need not repeat the +explantation here. +<>= +expect <- match.arg(expect) +Call <- match.call() + +# create a call to model.frame() that contains the formula (required) +# and any other of the relevant optional arguments +# then evaluate it in the proper frame +indx <- match(c("formula", "data", "weights", "subset", "na.action"), + names(Call), nomatch=0) +if (indx[1] ==0) stop("A formula argument is required") +tform <- Call[c(1,indx)] # only keep the arguments we wanted +tform[[1L]] <- quote(stats::model.frame) # change the function called + +Terms <- if(missing(data)) terms(formula, 'ratetable') + else terms(formula, 'ratetable',data=data) +if (any(attr(Terms, 'order') >1)) + stop("Pyears cannot have interaction terms") + +rate <- attr(Terms, "specials")$ratetable +if (length(rate) >0 || !missing(rmap) || !missing(ratetable)) { + has.ratetable <- TRUE + if(length(rate) > 1) + stop("Can have only 1 ratetable() call in a formula") + if (missing(ratetable)) stop("No rate table specified") + + <> + } +else has.ratetable <- FALSE + +mf <- eval(tform, parent.frame()) + +Y <- model.extract(mf, 'response') +if (is.null(Y)) stop ("Follow-up time must appear in the formula") +if (!is.Surv(Y)){ + if (any(Y <0)) stop ("Negative follow up time") + Y <- as.matrix(Y) + if (ncol(Y) >2) stop("Y has too many columns") + } +else { + stype <- attr(Y, 'type') + if (stype == 'right') { + if (any(Y[,1] <0)) stop("Negative survival time") + nzero <- sum(Y[,1]==0 & Y[,2] ==1) + if (nzero >0) + warning(paste(nzero, + "observations with an event and 0 follow-up time,", + "any rate calculations are statistically questionable")) + } + else if (stype != 'counting') + stop("Only right-censored and counting process survival types are supported") + } + +n <- nrow(Y) +if (is.null(n) || n==0) stop("Data set has 0 observations") + +weights <- model.extract(mf, 'weights') +if (is.null(weights)) weights <- rep(1.0, n) +@ + +The next step is to check out the ratetable. +For a population rate table a set of consistency checks is done by the +[[match.ratetable]] function, giving a set of sanitized indices [[R]]. +This function wants characters turned to factors. +For a Cox model [[R]] will be a model matix whose covariates are coded +in exactly the same way that variables were coded in the original +Cox model. We call the model.matrix.coxph function so as not to have to +repeat the steps found there (remove cluster statements, etc). +<>= +# rdata contains the variables matching the ratetable +if (has.ratetable) { + rdata <- data.frame(eval(rcall, mf), stringsAsFactors=TRUE) + if (is.ratetable(ratetable)) { + israte <- TRUE + rtemp <- match.ratetable(rdata, ratetable) + R <- rtemp$R + } + else if (inherits(ratetable, 'coxph') && !inherits(ratetable, "coxphms")) { + israte <- FALSE + Terms <- ratetable$terms + if (!is.null(attr(Terms, 'offset'))) + stop("Cannot deal with models that contain an offset") + strats <- attr(Terms, "specials")$strata + if (length(strats)) + stop("pyears cannot handle stratified Cox models") + + if (any(names(mf[,rate]) != attr(ratetable$terms, 'term.labels'))) + stop("Unable to match new data to old formula") + R <- model.matrix.coxph(ratetable, data=rdata) + } + else stop("Invalid ratetable") + } +@ + +Now we process the non-ratetable variables. +Those of class [[tcut]] set up time-dependent classes. For +these the cutpoints attribute sets the intervals, if there +were 4 cutpoints of 1, 5,6, and 10 the 3 intervals will be 1-5, +5-6 and 6-10, and odims will be 3. +All other variables are treated as factors. +<>= +ovars <- attr(Terms, 'term.labels') +if (length(ovars)==0) { + # no categories! + X <- rep(1,n) + ofac <- odim <- odims <- ocut <- 1 + } +else { + odim <- length(ovars) + ocut <- NULL + odims <- ofac <- double(odim) + X <- matrix(0, n, odim) + outdname <- vector("list", odim) + names(outdname) <- attr(Terms, 'term.labels') + for (i in 1:odim) { + temp <- mf[[ovars[i]]] + if (inherits(temp, 'tcut')) { + X[,i] <- temp + temp2 <- attr(temp, 'cutpoints') + odims[i] <- length(temp2) -1 + ocut <- c(ocut, temp2) + ofac[i] <- 0 + outdname[[i]] <- attr(temp, 'labels') + } + else { + temp2 <- as.factor(temp) + X[,i] <- temp2 + temp3 <- levels(temp2) + odims[i] <- length(temp3) + ofac[i] <- 1 + outdname[[i]] <- temp3 + } + } +} +@ + +Now do the computations. +The code above has separated out the variables into 3 groups: +\begin{itemize} + \item The variables in the rate table. These determine where we + \emph{start} in the rate table with respect to retrieving the relevant + death rates. For the US table [[survexp.us]] this will be the date of + study entry, age (in days) at study entry, and sex of each subject. + \item The variables on the right hand side of the model. These are + interpreted almost identically to a call to [[table]], with special + treatment for those of class \emph{tcut}. + \item The response variable, which tells the number of days of follow-up + and optionally the status at the end of follow-up. +\end{itemize} + +Start with the rate table variables. +There is an oddity about US rate tables: the entry for age (year=1970, +age=55) contains the daily rate for anyone who turns 55 in that year, +from their birthday forward for 365 days. So if your birthday is on +Oct 2, the 1970 table applies from 2Oct 1970 to 1Oct 1971. The +underlying C code wants to make the 1970 rate table apply from 1Jan +1970 to 31Dec 1970. The easiest way to finess this is to fudge +everyone's enter-the-study date. If you were born in March but +entered in April, make it look like you entered in Febuary; that way +you get the first 11 months at the entry year's rates, etc. The birth +date is entry date - age in days (based on 1/1/1970). + +The other aspect of the rate tables is that ``older style'' tables, those that +have the factor attribute, contained only decennial data which the C code would +interpolate on the fly. The value of [[atts$factor]] was 10 indicating that +there are 10 years in the interpolation interval. The newer tables do not +do this and the C code is passed a 0/1 for continuous (age and year) versus +discrete (sex, race). +<>= +ocut <-c(ocut,0) #just in case it were of length 0 +osize <- prod(odims) +if (has.ratetable) { #include expected + atts <- attributes(ratetable) + datecheck <- function(x) + inherits(x, c("Date", "POSIXt", "date", "chron")) + cuts <- lapply(attr(ratetable, "cutpoints"), function(x) + if (!is.null(x) & datecheck(x)) ratetableDate(x) else x) + + if (is.null(atts$type)) { + #old stlye table + rfac <- atts$factor + us.special <- (rfac >1) + } + else { + rfac <- 1*(atts$type ==1) + us.special <- (atts$type==4) + } + if (any(us.special)) { #special handling for US pop tables + if (sum(us.special) > 1) stop("more than one type=4 in a rate table") + # Someone born in June of 1945, say, gets the 1945 US rate until their + # next birthday. But the underlying logic of the code would change + # them to the 1946 rate on 1/1/1946, which is the cutpoint in the + # rate table. We fudge by faking their enrollment date back to their + # birth date. + # + # The cutpoint for year has been converted to days since 1/1/1970 by + # the ratetableDate function. (Date objects in R didn't exist when + # rate tables were conceived.) + if (is.null(atts$dimid)) dimid <- names(atts$dimnames) + else dimid <- atts$dimid + cols <- match(c("age", "year"), dimid) + if (any(is.na(cols))) + stop("ratetable does not have expected shape") + + # The format command works for Dates, use it to get an offset + bdate <- as.Date("1970-01-01") + (R[,cols[2]] - R[,cols[1]]) + byear <- format(bdate, "%Y") + offset <- as.numeric(bdate - as.Date(paste0(byear, "-01-01"))) + R[,cols[2]] <- R[,cols[2]] - offset + + # Doctor up "cutpoints" - only needed for (very) old style rate tables + # for which the C code does interpolation on the fly + if (any(rfac >1)) { + temp <- which(us.special) + nyear <- length(cuts[[temp]]) + nint <- rfac[temp] #intervals to interpolate over + cuts[[temp]] <- round(approx(nint*(1:nyear), cuts[[temp]], + nint:(nint*nyear))$y - .0001) + } + } + docount <- is.Surv(Y) + temp <- .C(Cpyears1, + as.integer(n), + as.integer(ncol(Y)), + as.integer(is.Surv(Y)), + as.double(Y), + as.double(weights), + as.integer(length(atts$dim)), + as.integer(rfac), + as.integer(atts$dim), + as.double(unlist(cuts)), + as.double(ratetable), + as.double(R), + as.integer(odim), + as.integer(ofac), + as.integer(odims), + as.double(ocut), + as.integer(expect=='event'), + as.double(X), + pyears=double(osize), + pn =double(osize), + pcount=double(if(docount) osize else 1), + pexpect=double(osize), + offtable=double(1))[18:22] + } +else { #no expected + docount <- as.integer(ncol(Y) >1) + temp <- .C(Cpyears2, + as.integer(n), + as.integer(ncol(Y)), + as.integer(docount), + as.double(Y), + as.double(weights), + as.integer(odim), + as.integer(ofac), + as.integer(odims), + as.double(ocut), + as.double(X), + pyears=double(osize), + pn =double(osize), + pcount=double(if (docount) osize else 1), + offtable=double(1)) [11:14] + } +@ + +Create the output object. +<>= +has.tcut <- any(sapply(mf, function(x) inherits(x, 'tcut'))) +if (data.frame) { + # Create a data frame as the output, rather than a set of + # rate tables + if (length(ovars) ==0) { # no variables on the right hand side + keep <- TRUE + df <- data.frame(pyears= temp$pyears/scale, + n = temp$n) + } + else { + keep <- (temp$pyears >0) # what rows to keep in the output + # grab prototype rows from the model frame, this preserves class + # (unless it is a tcut variable, then we know what to do) + tdata <- lapply(1:length(ovars), function(i) { + temp <- mf[[ovars[i]]] + if (inherits(temp, "tcut")) { #if levels are numeric, return numeric + if (is.numeric(outdname[[i]])) outdname[[i]] + else factor(outdname[[i]], outdname[[i]]) # else factor + } + else temp[match(outdname[[i]], temp)] + }) + tdata$stringsAsFactors <- FALSE # argument for expand.grid + df <- do.call("expand.grid", tdata)[keep,,drop=FALSE] + names(df) <- ovars + df$pyears <- temp$pyears[keep]/scale + df$n <- temp$pn[keep] + } + row.names(df) <- NULL # toss useless 'creation history' + if (has.ratetable) df$expected <- temp$pexpect[keep] + if (expect=='pyears') df$expected <- df$expected/scale + if (docount) df$event <- temp$pcount[keep] + # if any of the predictors were factors, make them factors in the output + for (i in 1:length(ovars)){ + if (is.factor( mf[[ovars[i]]])) + df[[ovars[i]]] <- factor(df[[ovars[i]]], levels( mf[[ovars[i]]])) + } + + out <- list(call=Call, + data= df, offtable=temp$offtable/scale, + tcut=has.tcut) + if (has.ratetable && !is.null(rtemp$summ)) + out$summary <- rtemp$summ +} + +else if (prod(odims) ==1) { #don't make it an array + out <- list(call=Call, pyears=temp$pyears/scale, n=temp$pn, + offtable=temp$offtable/scale, tcut = has.tcut) + if (has.ratetable) { + out$expected <- temp$pexpect + if (expect=='pyears') out$expected <- out$expected/scale + if (!is.null(rtemp$summ)) out$summary <- rtemp$summ + } + if (docount) out$event <- temp$pcount +} +else { + out <- list(call = Call, + pyears= array(temp$pyears/scale, dim=odims, dimnames=outdname), + n = array(temp$pn, dim=odims, dimnames=outdname), + offtable = temp$offtable/scale, tcut=has.tcut) + if (has.ratetable) { + out$expected <- array(temp$pexpect, dim=odims, dimnames=outdname) + if (expect=='pyears') out$expected <- out$expected/scale + if (!is.null(rtemp$summ)) out$summary <- rtemp$summ + } + if (docount) + out$event <- array(temp$pcount, dim=odims, dimnames=outdname) +} +out$observations <- nrow(mf) +out$terms <- Terms +na.action <- attr(mf, "na.action") +if (length(na.action)) out$na.action <- na.action +if (model) out$model <- mf +else { + if (x) out$x <- X + if (y) out$y <- Y +} +class(out) <- 'pyears' +out +@ +\subsection{Print and summary} +The print function for pyear gives a very abbreviated +printout: just a few lines. +It works with pyears objects with or without a data component. + +<>= +print.pyears <- function(x, ...) { + if (!is.null(cl<- x$call)) { + cat("Call:\n") + dput(cl) + cat("\n") + } + + if (is.null(x$data)) { + if (!is.null(x$event)) + cat("Total number of events:", format(sum(x$event)), "\n") + cat ( "Total number of person-years tabulated:", + format(sum(x$pyears)), + "\nTotal number of person-years off table:", + format(x$offtable), "\n") + } + else { + if (!is.null(x$data$event)) + cat("Total number of events:", format(sum(x$data$event)), "\n") + cat ( "Total number of person-years tabulated:", + format(sum(x$data$pyears)), + "\nTotal number of person-years off table:", + format(x$offtable), "\n") + } + if (!is.null(x$summary)) { + cat("Matches to the chosen rate table:\n ", + x$summary) + } + cat("Observations in the data set:", x$observations, "\n") + if (!is.null(x$na.action)) + cat(" (", naprint(x$na.action), ")\n", sep='') + cat("\n") + invisible(x) +} +@ + +The summary function attempts to create output that looks like a +pandoc table, which in turn makes it mesh nicely with Rstudio. +Pandoc has 4 types of tables: with and without vertical bars and +with single or multiple rows per cell. +If the pyears object has only a single dimension then our output will +be a simple table with a row or column for each of the output +types (see the vertical argument). +The result will be a simple table or a ``pipe'' table depending on the +vline argument. +For two or more dimensions the output follows the usual R strategy for printing +an array, but with each ``cell'' containing all of the summaries for that +combination of predictors, thus giving +either a ``multiline'' or ``grid'' table. +The default values of no vertical lines makes the tables +appropriate for non-pandoc output such as a terminal session. + +<>= +summary.pyears <- function(object, header=TRUE, call=header, + n= TRUE, event=TRUE, pyears=TRUE, + expected = TRUE, rate = FALSE, rr = expected, + ci.r = FALSE, ci.rr = FALSE, totals=FALSE, + legend=TRUE, vline = FALSE, vertical = TRUE, + nastring=".", conf.level=0.95, + scale= 1, ...) { + # Usual checks + if (!inherits(object, "pyears")) + stop("input must be a pyears object") + temp <- c(is.logical(header), is.logical(call), is.logical(n), + is.logical(event) , is.logical(pyears), is.logical(expected), + is.logical(rate), is.logical(ci.r), is.logical(rr), + is.logical(ci.rr), is.logical(vline), is.logical(vertical), + is.logical(legend), is.logical(totals)) + tname <- c("header", "call", "n", "event", "pyears", "expected", + "rate", "ci.r", "rr", "ci.rr", "vline", "vertical", + "legend", "totals") + if (any(!temp) || length(temp) != 14 || any(is.na(temp))) { + stop("the ", paste(tname[!temp], collapse=", "), + "argument(s) must be single logical values") + } + if (!is.numeric(conf.level) || conf.level <=0 || conf.level >=1 | + length(conf.level) > 1 || is.na(conf.level) > 1) + stop("conf.level must be a single numeric between 0 and 1") + if (is.na(scale) || !is.numeric(scale) || length(scale) !=1 || scale <=0) + stop("scale must be a value > 0") + + vname <- attr(terms(object), "term.labels") #variable names + + if (!is.null(object$data)) { + # Extra work: restore the tables which had been unpacked into a df + # All of the categories are factors in this case + tdata <- object$data[vname] # the conditioning variables + dname <- lapply(tdata, function(x) { + if (is.factor(x)) levels(x) else sort(unique(x))}) # dimnames + dd <- sapply(dname, length) # dim of arrays + index <- tapply(tdata[,1], tdata) + restore <- c('n', 'event', 'pyears', 'expected') #do these, if present + restore <- restore[restore %in% names(object$data)] + new <- lapply(object$data[restore], + function(x) { + temp <- array(0L, dim=dd, dimnames=dname) + temp[index] <- x + temp} ) + object <- c(object, new) + } + + if (is.null(object$expected)) { + expected <- FALSE + rr <- FALSE + ci.rr <- FALSE + } + if (is.null(object$event)) { + event <- FALSE + rate <- FALSE + ci.r <- FALSE + rr <- FALSE + ci.rr <- FALSE + } + + # print out the front matter + if (call && !is.null(object$call)) { + cat("Call: ") + dput(object$call) + cat("\n") + } + if (header) { + cat("number of observations =", object$observations) + if (length(object$omit)) + cat(" (", naprint(object$omit), ")\n", sep="") + else cat("\n") + if (object$offtable > 0) + cat(" Total time lost (off table)", format(object$offtable), "\n") + cat("\n") + } + + # Add in totals if requested + if (totals) { + # if the pyear object was based on any time dependent cuts, then + # the "n" component cannot be totaled up. + tcut <- if (is.null(object$tcut)) TRUE else object$tcut + object$n <- pytot(object$n, na=tcut) + object$pyears <- pytot(object$pyears) + if (event) object$event <- pytot(object$event) + if (expected) object$expected <- pytot(object$expected) + } + + dd <- dim(object$n) + vname <- attr(terms(object), "term.labels") #variable names + <> + if (length(dd) ==1) { + # 1 dimensional table + <> + } else { + # more than 1 dimension + <> + } + invisible(object) +} + +<> +@ + +<>= +# Put the elements to be printed onto a list +pname <- (tname[3:6])[c(n, event, pyears, expected)] +plist <- object[pname] + +if (rate) { + pname <- c(pname, "rate") + plist$r <- scale* object$event/object$pyears +} +if (ci.r) { + pname <- c(pname, "ci.r") + plist$ci.r <- cipoisson(object$event, object$pyears, p=conf.level) *scale +} +if (rr) { + pname <- c(pname, "rr") + plist$rr <- object$event/object$expected +} +if (ci.rr) { + pname <- c(pname, "ci.rr") + plist$ci.rr <- cipoisson(object$event, object$expected, p=conf.level) +} + +rname <- c(n = "N", event="Events", + pyears= "Time", expected= "Expected events", + rate = "Event rate", ci.r = "CI (rate)", + rr= "Obs/Exp", ci.rr= "CI (O/E)") +rname <- rname[pname] +@ + +If there is only one dimension to the table we can forgo the top legend +and use the object names as one of the margins. +If \code{vertical=TRUE} the output types are vertical, otherwise they +are horizontal. Format each element of the output separately. + + +<>= +cname <- names(object$n) #category names + +if (vertical) { + # The person-years objects list across the top, categories up and down + # This makes columns line up in a standard "R" way + # The first column label is the variable name, content is the categories + plist <- lapply(plist, pformat, nastring, ...) # make it character + pcol <- sapply(plist, function(x) nchar(x[1])) #width of each one + colwidth <- pmax(pcol, nchar(rname)) +2 + for (i in 1:length(plist)) + plist[[i]] <- strpad(plist[[i]], colwidth[i]) + + colwidth <- c(max(nchar(vname), nchar(cname)) +2, colwidth) + leftcol <- list(strpad(cname, colwidth[1])) + header <- strpad(c(vname, rname), colwidth) +} +else { + # in this case each column will have different types of objects in it + # alignment is the nuisance + newmat <- pybox(plist, length(plist[[1]]), nastring, ...) + colwidth <- pmax(nchar(cname), apply(nchar(newmat), 1, max)) +2 + # turn the list sideways + plist <- split(newmat, row(newmat)) + for (i in 1:length(plist)) + plist[[i]] <- strpad(plist[[i]], colwidth[i]) + + colwidth <- c(max(nchar(vname), nchar(rname)) +2, colwidth) + leftcol <- list(strpad(rname, colwidth[1])) + header <- strpad(c(vname, cname), colwidth) + } + +# Now print it +if (vline) { # use a pipe table + cat(paste(header, collapse = "|"), "\n") + cat(paste(strpad("-", colwidth, "-"), collapse="|"), "\n") + + temp <- do.call("paste", c(leftcol, plist, list(sep ="|"))) + cat(temp, sep= '\n') +} +else { + cat(paste(header, collapse = " "), "\n") + cat(paste(strpad("-", colwidth, "-"), collapse=" "), "\n") + temp <- do.call("paste", c(leftcol, plist, list(sep =" "))) + cat(temp, sep='\n') +} +@ + +When there are more than one category in the pyears object then +we use a special layout. Each 'cell' of the printed table has +all of the values in it. + +<>= +if (header) { + # the header is itself a table + width <- max(nchar(rname)) + if (vline) { + cat('+', strpad('-', width, '-'), "+\n", sep="") + cat(paste0('|',strpad(rname, width), '|'), sep='\n') + cat('+', strpad('-', width, '-'), "+\n\n", sep="") + } else { + cat(strpad('-', width, '-'), "\n") + cat(strpad(rname, width), sep='\n') + cat(strpad('-', width, '-'), "\n\n") + } +} +tname <- vname[1:2] #names for the row and col +rowname <- dimnames(object$n)[[1]] +colname <- dimnames(object$n)[[2]] +if (length(dd) > 2) + newmat <- pybox(plist, c(dd[1],dd[2], prod(dd[-(1:2)])), + nastring, ...) +else newmat <- pybox(plist, dd, nastring, ...) + +if (length(dd) > 2) { + newmat <- pybox(plist, c(dd[1],dd[2], prod(dd[-(1:2)])), + nastring, ...) + outer.label <- do.call("expand.grid", dimnames(object$n)[-(1:2)]) + temp <- names(outer.label) + for (i in 1:nrow(outer.label)) { + # first the caption, then data + cat(paste(":", paste(temp, outer.label[i,], sep="=")), '\n') + pyshow(newmat[,,i,], tname, rowname, colname, vline) + } +} +else { + newmat <- pybox(plist, dd, nastring, ...) + pyshow(newmat, tname, rowname, colname, vline) +} +@ + + +Here are some character manipulation functions. The stringi package has +more elegant versions of the pad function, but we don't need the speed. +No one is going to print out thousands of lines. + +<>= +strpad <- function(x, width, pad=' ') { + # x = the string(s) to be padded out + # width = width of desired string. + nc <- nchar(x) + added <- width - nc + + left <- pmax(0, floor(added/2)) # can't add negative space + right <- pmax(0, width - (nc + left)) # right will be >= left + + if (all(right <=0)) { + if (length(x) >= length(width)) x # nothing needs to be done + else rep(x, length=length(width)) + } + else { + # Each pad could be a different length. + # Make a long string from which we can take a portion + longpad <- paste(rep(pad, max(right)), collapse='') + paste0(substring(longpad, 1, left), x, substring(longpad,1, right)) + } +} + +pformat <- function(x, nastring, ...) { + # This is only called for single index tables, in vertical mode + # Any matrix will be a confidence interval + if (is.matrix(x)) + ret <- paste(ifelse(is.na(x[,1]), nastring, + format(x[,1], ...)), "-", + ifelse(is.na(x[,2]), nastring, + format(x[,2], ...))) + else ret <- ifelse(is.na(x), nastring, format(x, ...)) +} +@ + +Create formatted boxes. We want all the decimal points to line up, +so the format calls are in 3 parts: integer, real, and confidence interval. +If there are confidence intervals, format their values and then paste +together the left-right ends. +The intermediag form \code{final} is a matrix with one column per statistic. +At the end, reformat it as an array whose last dimension is the components. + +<>= +pybox <- function(plist, dd, nastring, ...) { + ci <- (substring(names(plist), 1,3) == "ci.") # the CI components + int <- sapply(plist, function(x) all(x == floor(x) | is.na(x))) + int <- (!ci & int) + real<- (!ci & !int) + nc <- prod(dd) + final <- matrix("", nrow=nc, ncol=length(ci)) + + if (any(int)) { # integers + if (any(sapply(plist[int], length) != nc)) + stop("programming length error, notify package author") + temp <- unlist(plist[int]) + final[,int] <- ifelse(is.na(temp), nastring, format(temp)) + } + if (any(real)) { # floating point + if (any(sapply(plist[real], length) != nc)) + stop("programming length error, notify package author") + temp <- unlist(plist[real]) + final[,real] <- ifelse(is.na(temp), nastring, + format(temp, ...)) + } + + if (any(ci)) { + if (any(sapply(plist[ci], length) != nc*2)) + stop("programming length error, notify package author") + temp <- unlist(plist[ci]) + temp <- array(ifelse(is.na(temp), nastring, + format(temp, ...)), + dim=c(nc, 2, sum(ci))) + final[,ci] <- paste(temp[,1,], temp[,2,], sep='-') + } + array(final, dim=c(dd, length(ci))) +} +@ + +This function prints out a box table. Each cell contains the full set of +statistics that were requested. Most of the work is the creation of +the appropriate spacing and special characters to create a valid +pandoc table. +<>= +pyshow <- function(dmat, labels, rowname, colname, vline) { + # Every column is the same width, except the first + colwidth <- c(max(nchar(rowname), nchar(labels[1])), + rep(max(nchar(dmat[1,1,]), nchar(colname)), length(colname))) + colwidth[2] <- max(colwidth[2], nchar(labels[2])) + ncol <- length(colwidth) + + dd <- dim(dmat) # vector of length 3, third dim is the statistics + rline <- ceiling(dd[3]/2) #which line to put the row label on. + if (vline) { # use a grid table + cat("+", paste(strpad('-', colwidth, pad='-'), collapse='+'), "+\n", + sep='') + temp <- rep(' ', ncol); temp[2] <- labels[2] + cat("|", paste(strpad(temp, colwidth), collapse="|"), "|\n", + sep='') + cat("|", paste(strpad(c(labels[1], colname), colwidth), collapse="|"), + "|\n", sep='') + cat("+", paste(strpad('=', colwidth, pad='='), collapse="+"), "+\n", + sep='') + for (i in 1:dd[1]) { + for (j in 1:dd[3]) { #one printout line per stat + if (j==rline) temp <- c(rowname[i], dmat[i,,j]) + else temp <- c("", dmat[i,,j]) + cat("|", paste(strpad(temp, colwidth), collapse='|'), "|\n", + sep='') + } + cat("+", paste(strpad('-', colwidth, '-'), collapse='+'), "+\n", + sep='') + } + } + else { # use a multiline table + cat(paste(strpad('-', colwidth, '-'), collapse='-'), "\n") + temp <- rep(' ', ncol); temp[2] <- labels[2] + cat(paste(strpad(temp, colwidth), collapse=" "), "\n") + cat(paste(strpad(c(labels[1], colname), colwidth), collapse=" "), + "\n") + cat(paste(strpad('-', colwidth, pad='-'), collapse=" "), "\n") + for (i in 1:dd[1]) { + for (j in 1:dd[3]) { #one printout line per stat + if (j==rline) temp <- c(rowname[i], dmat[i,,j]) + else temp <- c("", dmat[i,,j]) + cat(paste(strpad(temp, colwidth), collapse=' '), "\n") + } + if (i< dd[1]) cat(" \n") #blank line + } + cat(paste(strpad('-', colwidth, '-'), collapse='-'), "\n") + } +} +@ + +This function adds a totals row to the data, for either the first +or first and second dimensions. +The ``n'' component can't be totaled, so we turn that into NA. +<>= +pytot <- function(x, na=FALSE) { + dd <- dim(x) + if (length(dd) ==1) { + if (na) array(c(x, NA), dim= length(x) +1, + dimnames=list(c(dimnames(x)[[1]], "Total"))) + else array(c(x, sum(x)), dim= length(x) +1, + dimnames=list(c(dimnames(x)[[1]], "Total"))) + } + else if (length(dd) ==2) { + if (na) new <- rbind(cbind(x, NA), NA) + else { + new <- rbind(x, colSums(x)) + new <- cbind(new, rowSums(new)) + } + array(new, dim=dim(x) + c(1,1), + dimnames=list(c(dimnames(x)[[1]], "Total"), + c(dimnames(x)[[2]], "Total"))) + } + else { + # The general case + index <- 1:length(dd) + if (na) sum1 <- sum2 <- sum3 <- NA + else { + sum1 <- apply(x, index[-1], sum) # row sums + sum2 <- apply(x, index[-2], sum) # col sums + sum3 <- apply(x, index[-(1:2)], sum) # total sums + } + + # create a new matrix and then fill it in + d2 <- dd + d2[1:2] <- dd[1:2] +1 + dname <- dimnames(x) + dname[[1]] <- c(dname[[1]], "Total") + dname[[2]] <- c(dname[[2]], "Total") + new <- array(x[1], dim=d2, dimnames=dname) + + # say dim(x) =(5,8,4); we want new[6,-9,] <- sum1; new[-6,9,] <- sum2 + # and new[6,9,] <- sum3 + # if dim is longer, we need to add more commas + commas <- rep(',', length(dd) -2) + eval(parse(text=paste("new[1:dd[1], 1:dd[2]", commas, "] <- x"))) + eval(parse(text=paste("new[ d2[1],-d2[2]", commas, "] <- sum1"))) + eval(parse(text=paste("new[-d2[1], d2[2]", commas, "] <- sum2"))) + eval(parse(text=paste("new[ d2[1], d2[2]", commas, "] <- sum3"))) + new + } +} +@ +\section{Residuals for survival curves} +\subsection{R-code} +For all the more complex cases, the variance of a survival curve is based on +the infinitesimal jackknife: +$$ +D_i(t) = \frac{\partial S(t)}{\partial w_i} +$$ +evaluated at the the observed vector of weights. The variance at a given +time is then $D'WD'$ where $D$ is a diagonal matrix of the case weights. +When there are multiple states $S$ is replaced by the vector $p(t)$, with +one element per state, and the formula gets a bit more complex. +The predicted curve from a Cox model is the most complex case. + +Realizing that we need to return the matrix $D$ to the user, in order to compute +the variance of derived quantities like the restricted mean time in state, +the code has been changed from a primarily internal focus (compute within the +survfit routine) to an external one. + +The underlying C code is very similar to that in survfitkm.c +One major difference in the routines is that this code is designed to return +values at a fixed set of time points; it is an error if the user does not +provide them. This allows the result to be presented as a matrix or array. +Computational differences will be discussed later. + +The method argument is for debugging. For multi-state it uses either C code +or the optimized R method. +The double call below is because we want residuals to return a simple matrix, +but the pseudo function needs to get back a little bit more. + +\section{Residuals for survival curves} +\subsection{R-code} +For all the more complex cases, the variance of a survival curve is based on +the infinitesimal jackknife: +$$ +D_i(t) = \frac{\partial S(t)}{\partial w_i} +$$ +evaluated at the the observed vector of weights. The variance at a given +time is then $D'WD'$ where $D$ is a diagonal matrix of the case weights. +When there are multiple states $S$ is replaced by the vector $p(t)$, with +one element per state, and the formula gets a bit more complex. +The predicted curve from a Cox model is the most complex case. + +Realizing that we need to return the matrix $D$ to the user, in order to compute +the variance of derived quantities like the restricted mean time in state, +the code has been changed from a primarily internal focus (compute within the +survfit routine) to an external one. + +The underlying C code is very similar to that in survfitkm.c +One major difference in the routines is that this code is designed to return +values at a fixed set of time points; it is an error if the user does not +provide them. This allows the result to be presented as a matrix or array. +Computational differences will be discussed later. + +The method argument is for debugging. For multi-state it uses either C code +or the optimized R method. +The double call below is because we want residuals to return a simple matrix, +but the pseudo function needs to get back a little bit more. + +<>= +# residuals for a survfit object +residuals.survfit <- function(object, times, + type= "pstate", + collapse, weighted=FALSE, method=1, ...){ + + if (!inherits(object, "survfit")) + stop("argument must be a survfit object") + if (missing(times)) stop("the times argument is required") + # allow a set of alias + temp <- c("pstate", "cumhaz", "sojourn", "survival", + "chaz", "rmst", "rmts", "auc") + type <- match.arg(casefold(type), temp) + itemp <- c(1,2,3,1,2,3,3,3)[match(type, temp)] + type <- c("pstate", "cumhaz", "auc")[itemp] + + if (missing(collapse)) + fit <- survresid.fit(object, times, type, weighted=weighted, + method= method) + else fit <- survresid.fit(object, times, type, collapse= collapse, + weighted= weighted, method= method) + + fit$residuals +} + +survresid.fit <- function(object, times, + type= "pstate", + collapse, weighted=FALSE, method=1) { + + survfitms <- inherits(object, "survfitms") + coxsurv <- inherits(object, "survfitcox") + timefix <- (is.null(object$timefix) || object$timefix) + + start.time <- object$start.time + if (is.null(start.time)) start.time <- min(c(0, object$time)) + + # check input arguments + if (missing(times)) + stop ("the times argument is required") + else { + if (!is.numeric(times)) stop("times must be a numeric vector") + times <- sort(unique(times)) + if (timefix) times <- aeqSurv(Surv(times))[,1] + } + + # get the data + <> + + if (missing(collapse)) collapse <- (!(is.null(id)) && any(duplicated(id))) + if (collapse && is.null(id)) stop("collapse argument requires an id or cluster argument in the survfit call") + + ny <- ncol(newY) + if (collapse && any(X != X[1])) { + # If the same id shows up in multiple curves, we just can't deal + # with it. + temp <- unlist(lapply(split(id, X), unique)) + if (any(duplicated(temp))) + stop("same id appears in multiple curves, cannot collapse") + } + + timelab <- signif(times, 3) # used for dimnames + # What type of survival curve? + if (!coxsurv) { + stype <- Call$stype + if (is.null(stype)) stype <- 1 + ctype <- Call$ctype + if (is.null(ctype)) ctype <- 1 + if (!survfitms) { + resid <- rsurvpart1(newY, X, casewt, times, + type, stype, ctype, object) + if (collapse) { + resid <- rowsum(resid, id, reorder=FALSE) + dimnames(resid) <- list(id= unique(id), times=timelab) + curve <- (as.integer(X))[!duplicated(id)] #which curve for each + } + else { + if (length(id) >0) dimnames(resid) <- list(id=id, times=timelab) + curve <- as.integer(X) + } + } + else { # multi-state + if (!collapse) { + if (length(id >0)) d1name <- id else d1name <- NULL + cluster <- d1name + curve <- as.integer(X) + } + else { + d1name <- unique(id) + cluster <- match(id, d1name) + curve <- (as.integer(X))[!duplicated(id)] + } + resid <- rsurvpart2(newY, X, casewt, istate, times, cluster, + type, object, method=method, collapse=collapse) + + if (type == "cumhaz") { + ntemp <- colnames(object$cumhaz) + if (length(dim(resid)) ==3) + dimnames(resid) <- list(id=d1name, times=timelab, + cumhaz= ntemp) + else dimnames(resid) <- list(id=d1name, cumhaz=ntemp) + } + else { + ntemp <- object$states + if (length(dim(resid)) ==3) + dimnames(resid) <- list(id=d1name, times=timelab, + state= ntemp) + else dimnames(resid) <- list(id=d1name, state= ntemp) + } + } + } + else stop("coxph survival curves not yet available") + + if (weighted && any(casewt !=1)) resid <- resid*casewt + + list(residuals= resid, curve= curve, id= id, idname=idname) +} +@ + +The first part of the work is retrieve the data set. This is done in multiple +places in the survival code, all essentially the same. +If I gave up (like lm) and forced the model frame to be saved this would be +easier of course. + +<>= +Call <- object$call + +# remember the name of the id variable, if present. +# but we don't try to parse it: id= mydata$clinic becomes NULL +idname <- Call$id +if (is.name(idname)) idname <- as.character(idname) +else idname <- NULL +# I always need the model frame +if (coxsurv) { + mf <- model.frame(object) + if (is.null(object$y)) Y <- model.response(mf) + else Y <- object$y +} +else { + formula <- formula(object) + + # the chunk below is shared with survfit.formula + na.action <- getOption("na.action") + if (is.character(na.action)) + na.action <- get(na.action) # this is a temporary hack + <> + # end of shared code +} + +xlev <- levels(X) + +# Deal with ties +if (is.null(Call$timefix) || Call$timefix) newY <- aeqSurv(Y) else newY <- Y +@ + +This code has 3 primary sections: single state survival, multi-state survival, +and post-Cox survival. +A motivating idea in all of them is to avoid an $O(nd)$ calculation that +involves the increment to each subject's leverage at each of the $d$ +event times. Since $d$ often grows with $n$ this can get very slow. This +routine is designed for the case where the number of time points in the +output matrix is modest, so we aim for $O(n)$ processes that repeat for +each output time. + +\subsection{Simple survival} +The Nelson-Aalen estimate of cumulative hazard is a simple sum +\begin{align} + H(t) &= H(t-) + h(t) \nonumber \\ + \frac{\partial H(t)}{\partial w_i} &= \frac{\partial H(t-)}{\partial w_i} + + [dN_i(t) - Y_i(t)h(t)]/r(t) \nonumber \\ + &= \sum_{d_j \le t} dN_i(d_j)/r(d_j) - Y_i(d_j)h(d_j)/r(d_j) + \label{NAderiv} +\end{align} +where $H$ the cumulative hazard, +$h$ is the increment to the cumulative hazard, $Y_i$ is 1 when a +subject is at risk, and $dN_i$ marks an event for the subject. +Our basic strategy for the NA estimate is to use a two stage estimate. +First, compute three vectors, each with one element per event time. +\begin{itemize} + \item term1 = $1/r(d_j)$ is the increment to the derivative for any + observation with an event at event time $d_j$ + \item term2 = $-h(d_j)/r(d_j)$ is the increment for any observation that is at + risk at time $d_j$ + \item term3 = cumulative sum of term2 +\end{itemize} + +For any given observation $i$ whose follow-up interval is $(s_i, t_i)$, their +derivative at time $z$ is the sum of +\begin{itemize} + \item term3(min($z$, $t_i$)) - term3(min($z$, $s_i$)) + \item term1($t_i$) if $t_i \le z$ and observation $i$ is an event +\end{itemize} + +The Fleming-Harrington estimate of survival is +\begin{align*} + S(t) &= e^{-H(t)} \\ + \partial{S(t)}{\partial w_i} &= -S(t)\partial{H(t)}{\partial w_i} +\end{align*} +So has exactly the same computation, with a multiplication at the end. + +<>= +rsurvpart1 <- function(Y, X, casewt, times, + type, stype, ctype, fit) { + + ntime <- length(times) + etime <- (fit$n.event >0) + ny <- ncol(Y) + event <- (Y[,ny] >0) + status <- Y[,ny] + + # + # Create a list whose first element contains the location of + # the death times in curve 1, second element the death times for curve 2, + # + if (is.null(fit$strata)) { + fitrow <- list(which(etime)) + } + else { + temp1 <- cumsum(fit$strata) + temp2 <- c(1, temp1+1) + fitrow <- lapply(1:length(fit$strata), function(i) { + indx <- seq(temp2[i], temp1[i]) + indx[etime[indx]] # keep the death times + }) + } + ff <- unlist(fitrow) + + # for each time x, the index of the last death time which is <=x. + # 0 if x is before the first death time in the fit object. + # The result is an index to the survival curve + matchfun <- function(x, fit, index) { + dtime <- fit$time[index] # subset to this curve + i2 <- findInterval(x, dtime, left.open=FALSE) + c(0, index)[i2 +1] + } + + # output matrix D will have one row per observation, one col for each + # reporting time. tindex and yindex have the same dimension as D. + # tindex points to the last death time in fit which + # is <= the reporting time. (If there is only 1 curve, each col of + # tindex will be a repeat of the same value.) + tindex <- matrix(0L, nrow(Y), length(times)) + for (i in 1:length(fitrow)) { + yrow <- which(as.integer(X) ==i) + temp <- matchfun(times, fit, fitrow[[i]]) + tindex[yrow, ] <- rep(temp, each= length(yrow)) + } + tindex[,] <- match(tindex, c(0,ff)) -1L # the [,] preserves dimensions + + # repeat the indexing for Y onto fit$time. Each row of yindex points + # to the last row of fit with death time <= Y[,ny] + ny <- ncol(Y) + yindex <- matrix(0L, nrow(Y), length(times)) + event <- (Y[,ny] >0) + if (ny==3) startindex <- yindex + for (i in 1:length(fitrow)) { + yrow <- (as.integer(X) ==i) # rows of Y for this curve + temp <- matchfun(Y[yrow,ny-1], fit, fitrow[[i]]) + yindex[yrow,] <- rep(temp, ncol(yindex)) + if (ny==3) { + temp <- matchfun(Y[yrow,1], fit, fitrow[[i]]) + startindex[yrow,] <- rep(temp, ncol(yindex)) + } + } + yindex[,] <- match(yindex, c(0,ff)) -1L + if (ny==3) { + startindex[,] <- match(startindex, c(0,ff)) -1L + # no subtractions for report times before subject's entry + startindex <- pmin(startindex, tindex) + } + + # Now do the work + if (type=="cumhaz" || stype==2) { # result based on hazards + if (ctype==1) { + <> + } else { + <> + } + } else { # not hazard based + <> + } + D +} +@ + +The Nelson-Aalen is the simplest case. +We don't have to worry about case weights of the data, since that has +already been accounted for by the survfit function. + +<>= +death <- (yindex <= tindex & rep(event, ntime)) # an event occured at <= t + +term1 <- 1/fit$n.risk[ff] +term2 <- lapply(fitrow, function(i) fit$n.event[i]/fit$n.risk[i]^2) +term3 <- unlist(lapply(term2, cumsum)) + +sum1 <- c(0, term1)[ifelse(death, 1+yindex, 1)] +sum2 <- c(0, term3)[1 + pmin(yindex, tindex)] +if (ny==3) sum3 <- c(0, term3)[1 + pmin(startindex, tindex)] + +if (ny==2) D <- matrix(sum1 - sum2, ncol=ntime) +else D <- matrix(sum1 + sum3 - sum2, ncol=ntime) + +# survival is exp(-H) so the derivative is a simple transform of D +if (type== "pstate") D <- -D* c(1,fit$surv[ff])[1+ tindex] +else if (type == "auc") { + <> +} +@ + +The sojourn time is the area under the survival curve. Let $x_j$ be the +widths of the rectangles under the curve from event time $d_j$ to +$min(d_{j+1}, t)$, zero if $t \le d_j$, or $t-d_m$ if $t$ is after the last +event time. +\begin{align*} + A(0,t) &= \sum_{j=1}^m x_j S(d_j) \\ + \frac{\partial A(0,t)}{\partial w_i} &= + \sum_{j=1}^m -x_j S(d_j) \frac{\partial H(d_j)}{\partial w_i} \\ + &= \sum_{j=1}^m -x_jS(d_j) \sum_{k \le j} \frac{\partial h(d_k)}{\partial w_i} \\ + &= \sum_{k=1}^m \frac{\partial h(d_k)}{\partial w_i} + \left(\sum_{j\ge k} -x_j S(d_j) \right) \\ + &= \sum_{k=1}^m -A(d_k, t) \frac{\partial h(d_k)}{\partial w_i} +\end{align*} + +For an observation at risk over the interval $(a,b)$ we have exactly the same +calculus as the cumulative hazard with respect to which $h(d_k)$ terms +are counted for the observation, but now they are weighted sums. The weights +are different for each output time, so we set them up as a matrix. +We need the AUC at each event time $d_k$, and the AUC at the output times. + +Matrix subscripts are a little used feature of R. If y is a matrix of +values and x is a 2 colum matrix containing m (row, col) pairs, the +result will be a vector of length m that plucks out the [x[1,1], x[1,2]] +value of y, then the [x[2,1], x[2,2]] value of y, etc. +They are rarely useful, but very handy in the few cases where they apply. + +<>= +auc1 <- lapply(fitrow, function(i) { + if (length(i) <=1) 0 + else c(0, cumsum(diff(fit$time[i]) * (fit$surv[i])[-length(i)])) + }) # AUC at each event time +auc2 <- lapply(fitrow, function(i) { + if (length(i) <=1) 0 + else { + xx <- sort(unique(c(fit$time[i], times))) # all the times + yy <- (fit$surv[i])[findInterval(xx, fit$time[i])] + auc <- cumsum(c(diff(xx),0) * yy) + c(0, auc)[match(times, xx)] + }}) # AUC at the output times + +# Most often this function is called with a single curve, so make that case +# faster. (Or I presume so: mapply and do.call may be more efficient than +# I think for lists of length 1). +if (length(fitrow)==1) { # simple case, most common to ask for auc + wtmat <- pmin(outer(auc1[[1]], -auc2[[1]], '+'),0) + term1 <- term1 * wtmat + term2 <- unlist(term2) * wtmat + term3 <- apply(term2, 2, cumsum) +} +else { #more than one curve, compute weighted cumsum per curve + wtmat <- mapply(function(x, y) pmin(outer(x, -y, "+"), 0), auc1, auc2) + term1 <- term1 * do.call(rbind, wtmat) + temp <- mapply(function(x, y) apply(x*y, 2, cumsum), term2, wtmat) + term3 <- do.call(rbind, temp) +} + +sum1 <- sum2 <- matrix(0, nrow(yindex), ntime) +if (ny ==3) sum3 <- sum1 +for (i in 1:ntime) { + sum1[,i] <- c(0, term1[,i])[ifelse(death[,i], 1 + yindex[,i], 1)] + sum2[,i] <- c(0, term3[,i])[1 + pmin(yindex[,i], tindex[,i])] + if (ny==3) sum3[,i] <- c(0, term3[,i])[1 + pmin(startindex[,i], tindex[,i])] +} +# Perhaps a bit faster(?), but harder to read. And for AUC people usually only +# ask for one time point +#sum1 <- rbind(0, term1)[cbind(c(ifelse(death, 1+yindex, 1)), c(col(yindex)))] +#sum2 <- rbind(0, term3)[cbind(c(1 + pmin(yindex, tindex)), c(col(yindex)))] +#if (ny==3) sum3 <- +# rbind(0, term3)[c(cbind(1 + pmin(startindex, tindex)), +# c(col(yindex)))] +if (ny==2) D <- matrix(sum1 - sum2, ncol=ntime) +else D <- matrix(sum1 + sum3 - sum2, ncol=ntime) +@ + +\paragraph{Fleming-Harrington} +For the Fleming-Harrington estimator the calculation at a tied time differs +slightly. +If there were 10 at risk and 3 tied events, the Nelson-Aalen has an increment +of 3/10, while the FH has an increment of (1/10 + 1/9 + 1/8). The underlying +idea is that the true time values are continuous and we observe ties due to +coarsening of the data. The derivative will have 3 terms as well. In this +case the needed value cannot be pulled directly from the survfit object. +Computationally, the number of distinct times at which a tie occurs is normally +quite small and the for loop below will not be too expensive. + +<>= +stop("residuals function still imcomplete, for FH estimate") +if (any(casewt != casewt[1])) { + # Have to reconstruct the number of obs with an event, the curve only + # contains the weighted sum + nevent <- unlist(lapply(seq(along.with=levels(X)), function(i) { + keep <- which(as.numeric(X) ==i) + counts <- table(Y[keep, ny-1], status) + as.vector(counts[, ncol(counts)]) + })) +} else nevent <- fit$n.event + +n2 <- fit$n.risk +risk2 <- 1/fit$n.risk +ltemp <- risk2^2 +for (i in which(nevent>1)) { # assume not too many ties + denom <- fit$n.risk[i] - fit$n.event[i]*(0:(nevent[i]-1))/nevent[i] + risk2[i] <- mean(1/denom) # multiplier for the event + ltemp[i] <- mean(1/denom^2) + n2[i] <- mean(denom) +} + +death <- (yindex <= tindex & rep(event, ntime)) +term1 <- risk2[ff] +term2 <- lapply(fitrow, function(i) event[i]*ltemp[i]) +term3 <- unlist(lapply(term2, cumsum)) + +sum1 <- c(0, term1)[ifelse(death, 1+yindex, 1)] +sum2 <- c(0, term3)[1 + pmin(yindex, tindex)] +if (ny==3) sum3 <- c(0, term3)[1 + pmin(startindex, tindex)] + +if (ny==2) D <- matrix(sum1 - sum2, ncol=ntime) +else D <- matrix(sum1 + sum3 - sum2, ncol=ntime) + +if (type=="pstate") D <- -D* c(0,fit$surv[ff])[1+ tindex] +else if (type=="auc") { + <> +} +@ + +\paragraph{Kaplan-Meier} +For the Kaplan-Meier (a special case of the Aalen-Johansen) the underlying +algorithm is multiplicative, but we can turn it into an additive +algoritm with a slight of hand. + +\begin{align*} + S(t) &= \prod_{d_j\le t} (1- h(d_j)) \\ + &= \exp \left(\sum_{d_j\le t} \log(1- h(d_j)) \right) \\ + &= \exp \left(\sum_{d_j\le t} \log(r(d_j) - dN(d_j)) - log(r(d_j)) \right) \\ + \frac{\partial S(t)}{\partial w_i} &= + S(t) \sum_{d_j\le t} \frac{Y_i(d_j) - dN_i(d_j)}{r(d_j) - dN(d_j)} - + \frac{Y_i(d_j)}{ r(d_j)} +\end{align*} + +The addend for term2 is now $1/n(n-e)$ where $e$ is the number of events, i.e., +the same term as in the Greenwood variance, and term1 is $-1/n(n-e)$. +The jumps in the KM curve are just a big larger than jumps in a FH estimate, +so it makes sense that these are just a bit larger. + +<>= +death <- (yindex <= tindex & rep(event, ntime)) +# dtemp avoids 1/0. (When this occurs the influence is 0, since +# the curve has dropped to zero; and this avoids Inf in term1 and term2). +dtemp <- ifelse(fit$n.risk==fit$n.event, 0, 1/(fit$n.risk- fit$n.event)) +term1 <- dtemp[ff] +term2 <- lapply(fitrow, function(i) dtemp[i]*fit$n.event[i]/fit$n.risk[i]) +term3 <- unlist(lapply(term2, cumsum)) + +add1 <- c(0, term1)[ifelse(death, 1+yindex, 1)] +add2 <- c(0, term3)[1 + pmin(yindex, tindex)] +if (ny==3) add3 <- c(0, term3)[1 + pmin(startindex, tindex)] + +if (ny==2) D <- matrix(add1 - add2, ncol=ntime) +else D <- matrix(add1 + add3 - add2, ncol=ntime) + +# survival is exp(-H) so the derivative is a simple transform of D +if (type== "pstate") D <- -D* c(1,fit$surv[ff])[1+ tindex] +else if (type == "auc") { + <> +} +@ + +\subsection{Multi-state Aalen-Johansen estimate} +For multi-state models a correction for ties of similar spirit to the +Efron approximation in a Cox model (the ctype=2 argument for \code{survfit}) +is difficult: the 'right' answer depends on the study. +Thus the ctype argument is not present. +Both stype 1 and 2 are feasible, but currently only \code{stype=1} is +supported. +This makes the code somewhat simpler, but this is more than offset by the +multi-state nature. +With multiple states we also need to account for influence on the starting +state $p(0)$. + +One thing that can make this code slow is data that has been divided into a +very large number of intervals, giving a large number of observations for +each cluster. We first deal with that by collapsing adjacent observations. + +<>= +rsurvpart2 <- function(Y, X, casewt, istate, times, cluster, type, fit, + method, collapse) { + ny <- ncol(Y) + ntime <- length(times) + nstate <- length(fit$states) + + # ensure that Y, istate, and fit all use the same set of states + states <- fit$states + if (!identical(attr(Y, "states"), fit$states)) { + map <- match(attr(Y, "states"), fit$states) + Y[,ny] <- c(0, map)[1+ Y[,ny]] # 0 = censored + attr(Y, "states") <- fit$states + } + if (is.null(istate)) istate <- rep(1L, nrow(Y)) #everyone starts in s0 + else { + if (is.character(istate)) istate <- factor(istate) + if (is.factor(istate)) { + if (!identical(levels(istate), fit$states)) { + map <- match(levels(istate), fit$states) + if (any(is.na(map))) stop ("invalid levels in istate") + istate <- map[istate] + } + } # istate is numeric, we take what we get and hope it is right + } + + # collapse redundant rows in Y, for efficiency + # a redundant row is a censored obs in the middle of a chain of times + # if the user wants individial obs, however, we would just have to + # expand it again + if (ny==3 && collapse & any(duplicated(cluster))) { + ord <- order(cluster, X, istate, Y[,1]) + cfit <- .Call(Ccollapse, Y, X, istate, cluster, casewt, ord -1L) + if (nrow(cfit) < .8*length(X)) { + # shrinking the data by 20 percent is worth it + temp <- Y[ord,] + Y <- cbind(temp[cfit[,1], 1], temp[cfit[2], 2:3]) + X <- X[cfit[,1]] + istate <- istate[cfit[1,]] + cluster <- cluster[cfit[1,]] + } + } + + # Compute the initial leverage + inf0 <- NULL + if (is.null(fit$call$p0) && any(istate != istate[1])) { + #p0 was not supplied by the user, and the intitial states vary + inf0 <- matrix(0., nrow=nrow(Y), ncol=nstate) + i0fun <- function(i, fit, inf0) { + # reprise algorithm in survfitCI + p0 <- fit$p0 + t0 <- fit$time[1] + if (ny==2) at.zero <- which(as.numeric(X) ==i) + else + at.zero <- which(as.numeric(X) ==i & + (Y[,1] < t0 & Y[,2] >= t0)) + for (j in 1:nstate) { + inf0[at.zero, j] <- (ifelse(istate[at.zero]==states[j], 1, 0) - + p0[j])/sum(casewt[at.zero]) + } + inf0 + } + + if (is.null(fit$strata)) inf0 <- i0fun(1, fit, inf0) + else for (i in 1:length(levels(X))) + inf0 <- i0fun(i, fit[i], inf0) # each iteration fills in some rows + } + + p0 <- fit$p0 # needed for method==1, type != cumhaz + fit <- survfit0(fit) # package the initial state into the picture + start.time <- fit$time[1] + + # This next block is identical to the one in rsurvpart1, more comments are + # there + etime <- (rowSums(fit$n.event) >0) + event <- (Y[,ny] >0) + # + # Create a list whose first element contains the location of + # the death times in curve 1, second element for curve 2, etc. + # + if (is.null(fit$strata)) fitrow <- list(which(etime)) + else { + temp1 <- cumsum(fit$strata) + temp2 <- c(1, temp1+1) + fitrow <- lapply(1:length(fit$strata), function(i) { + indx <- seq(temp2[i], temp1[i]) + indx[etime[indx]] # keep the death times + }) + } + ff <- unlist(fitrow) + + # for each time x, the index of the last death time which is <=x. + # 0 if x is before the first death time + matchfun <- function(x, fit, index) { + dtime <- fit$time[index] # subset to this curve + i2 <- findInterval(x, dtime, left.open=FALSE) + c(0, index)[i2 +1] + } + + + if (type== "cumhaz") { + <> + } else { + <> + } + + # since we may have done a partial collapse (removing redundant rows), the + # parent routine can't collapse the data + if (collapse & any(duplicated(cluster))) { + if (length(dim(D)) ==2) + D <- rowsum(D, cluster, reorder=FALSE) + else { #rowsums has to be fooled + dd <- dim(D) + temp <- rowsum(matrix(D, nrow=dd[1]), cluster) + D <- array(temp, dim=c(nrow(temp), dd[2:3])) + } + } + D +} +@ + +\paragraph{Nelson-Aalen} +The multi-state Nelson-Aalen estimate of the cumulative hazard at time $t$ +is a vector with one element for each observed transition pair. If there +were $k$ states there are potentially $k(k-1)$ transition pairs, though +normally only a small number will occur in a given fit. +We ignore transitions from state $j$ to state $j$. +Let $r(t)$ be the weighted number at risk at time $t$, in each state. +When some subject makes a $j:k$ transition, the $j:k$ transition will +have an increment of $w_i/r_j(t)$. +This is precisely the same increment as the ordinary Nelson estimate. +The only change then is that we loop over the set of possible transitions, +creating a large output object. + +<>= +# output matrix D will have one row per observation, one col for each +# reporting time. tindex and yindex have the same dimension as D. +# tindex points to the last death time in fit which +# is <= the reporting time. (If there is only 1 curve, each col of +# tindex will be a repeat of the same value.) +tindex <- matrix(0L, nrow(Y), length(times)) +for (i in 1:length(fitrow)) { + yrow <- which(as.integer(X) ==i) + temp <- matchfun(times, fit, fitrow[[i]]) + tindex[yrow, ] <- rep(temp, each= length(yrow)) +} +tindex[,] <- match(tindex, c(0,ff)) -1L # the [,] preserves dimensions + +# repeat the indexing for Y onto fit$time. Each row of yindex points +# to the last row of fit with death time <= Y[,ny] +ny <- ncol(Y) +yindex <- matrix(0L, nrow(Y), length(times)) +event <- (Y[,ny] >0) +if (ny==3) startindex <- yindex +for (i in 1:length(fitrow)) { + yrow <- (as.integer(X) ==i) # rows of Y for this curve + temp <- matchfun(Y[yrow,ny-1], fit, fitrow[[i]]) + yindex[yrow,] <- rep(temp, ncol(yindex)) + if (ny==3) { + temp <- matchfun(Y[yrow,1], fit, fitrow[[i]]) + startindex[yrow,] <- rep(temp, ncol(yindex)) + } +} +yindex[,] <- match(yindex, c(0,ff)) -1L +if (ny==3) { + startindex[,] <- match(startindex, c(0, ff)) -1L + # no subtractions for report times before subject's entry + startindex <- pmin(startindex, tindex) +} + +dstate <- Y[,ncol(Y)] +istate <- as.integer(istate) +ntrans <- ncol(fit$cumhaz) # the number of possible transitions +D <- array(0, dim=c(nrow(Y), ntime, ntrans)) + +scount <- table(istate[dstate!=0], dstate[dstate!=0]) # observed transitions +state1 <- row(scount)[scount>0] +state2 <- col(scount)[scount>0] +temp <- paste(rownames(scount)[state1], + colnames(scount)[state2], sep='.') +if (!identical(temp, colnames(fit$cumhaz))) stop("setup error") + +for (k in length(state1)) { + e2 <- Y[,ny] == state2[k] + add1 <- (yindex <= tindex & rep(e2, ntime)) + lsum <- unlist(lapply(fitrow, function(i) + cumsum(fit$n.event[i,k]/fit$n.risk[i,k]^2))) + + term1 <- c(0, 1/fit$n.risk[ff,k])[ifelse(add1, 1+yindex, 1)] + term2 <- c(0, lsum)[1+pmin(yindex, tindex)] + if (ny==3) term3 <- c(0, lsum)[1 + startindex] + + if (ny==2) D[,,k] <- matrix(term1 - term2, ncol=ntime) + else D[,,k] <- matrix(term1 + term3 - term2, ncol=ntime) +} +@ + +\paragraph{Aalen-Johansen} +The multi-state AJ estimate is more complex. Let $p(t)$ be the vector +of probability in state at time $t$. +Then +\begin{align} + p(t) &= p(t-) [I+ A(t)]\nonumber\\ + \frac{\partial p(t)}{\partial w_i} &= \frac{\partial p(t-)}{\partial w_i} + [I+ A(t)] + + p(t-) \frac{\partial A(t)}{\partial w_i} \nonumber\\ + &= U_i(t-) [I+ A(t)] + p(t-) \frac{\partial A(t)}{\partial w_i} + \label{ajresidx}\\ +\end{align} + +When we expand the left hand portion of \eqref{ajresidx} to include all +observations it becomes simple matrix multiplication, not so with +the right hand portion. +Each individual subject $i$ has a subject-specific +nstate * nstate derivative matrix $dA$, which will be non-zero only for the +state (row) $j$ that the subject occupies at time $t-$. +The $j$th row of $p(t-) dH$ is added to each subject's derivative. + +The $A$ matrix at time $t$ has off diagonal elements and derivative +\begin{align} +A(t)_{jk} &= \frac{\sum_i w_i Y_{ij}(t) dN{ik}(t)} + {\sum_i w_iY_{ij}(t)} \\ + &= \lambda_{jk}(t) \\ +\frac{\partial A(t)}{\partial w_i} &= \frac{dN_{ik}(t) - \lambda_{jk}(t)} + {\sum_i w_iY_{ij}(t)} \label{Aderiv} +\end{align} + +This is the standard counting process notation: $Y_{ij}(t)$ is 1 if subject $i$ +is in state $j$ and at risk at time $t-$, and $dN_{ik}(t)$ is a transition to +state $k$ at time $t$. +Each observation at risk appears in at most 1 row of $A(t)$, since they can +only be in one state. +The diagonal element of $A$ are set so that each row sums to 0. +If there are no transitions out of state $j$ at some time point, then that +row of $A$ is zero. +Since the row sums are constant, the sum of the derivatives for each row +must be zero. + +If we evaluate equation \label{ajresidx} directly there will be +$O(nk^2)$ operations at each death time for the matrix product, and another +$O(nk)$ to add in the new increment. For a large data set $d$ is often +of the same order as $n$, which makes this an expensive calculation. +But, this is what the C-code version currently does, because I have code that +actually works. + + +<>= +if (method==1) { + # Compute the result using the direct method, in C code + # the routine is called separately for each curve, data in sorted order + # + is1 <- as.integer(istate) -1L # 0 based subscripts for C + if (is.null(inf0)) inf0 <- matrix(0, nrow=nrow(Y), ncol=nstate) + if (all(as.integer(X) ==1)) { # only one curve + if (ny==2) asort1 <- 0L else asort1 <- order(Y[,1], Y[,2]) -1L + asort2 <- order(Y[,ny-1]) -1L + tfit <- .Call(Csurvfitresid, Y, asort1, asort2, is1, + casewt, p0, inf0, times, start.time, + type== "auc") + + if (ntime==1) { + if (type=="auc") D <- tfit[[2]] else D <- tfit[[1]] + } + else { + if (type=="auc") D <- array(tfit[[2]], dim=c(nrow(Y), nstate, ntime)) + else D <- array(tfit[[1]], dim=c(nrow(Y), nstate, ntime)) + } + } + else { # one curve at a time + ix <- as.numeric(X) # 1, 2, etc + if (ntime==1) D <- matrix(0, nrow(Y), nstate) + else D <- array(0, dim=c(nrow(Y), nstate, ntime)) + for (curve in 1:max(ix)) { + j <- which(ix==curve) + ytemp <- Y[j,,drop=FALSE] + if (ny==2) asort1 <- 0L + else asort1 <- order(ytemp[,1], ytemp[,2]) -1L + asort2 <- order(ytemp[,ny-1]) -1L + + # call with a subset of the data + j <- which(ix== curve) + tfit <- .Call(Csurvfitresid, ytemp, asort1, asort2, is1[j], + casewt[j], p0[curve,], inf0[j,], times, + start.time, type=="auc") + if (ntime==1) { + if (type=="auc") D[j,] <- tfit[[2]] else D[j,] <- tfit[[1]] + } else { + if (type=="auc") D[j,,] <- tfit[[2]] else D[j,,] <- tfit[[1]] + } + } + } + # the C code makes time the last dimension, we want it to be second + if (ntime > 1) D <- aperm(D, c(1,3,2)) +} +else { + # method 2 + <> +} +@ + +Can we speed this up? +An alternate is to look at the direct expansion. +\begin{align} + p(t) &= p(0) \prod_{d_j \le t} [I+ A(d_j)] \nonumber \\ + \frac{\partial p(t)}{\partial w_i} &= + \frac{\partial p(0)}{\partial w_i} \prod_{d_j \le t} [I+ A(d_j)] \\ + & + p(0)\sum_{d_j \le t} \left( \prod_{kk$. +Let $D(x)$ be the diagonal matrix. +\begin{align} +T_{01} &= D(p'(0))[I+ A(d_1)] & T_{02} &= T_{01}[I + A(d_2)] & + T_{03} &= T_{02} [I + A(d_3)] & \ldots \\ +T_{11} &= D(p(d_1)) B(d_1) & T_{12} &= T_{11}[I + A(d_2)] & + T_{13} &= T_{12}[I + A(d_3)] & \ldots \\ +T_{21} &= 0 & T_{22} &= D(p(d_2)) B(d_2) & T_{23} &= T_{22}[I+ A(d_2)] & \ldots \\ +T_{31} &= 0 & T_{32}&=0 & T_{33} &= D(p(d_3)) B(d_3) &\ldots +\end{align} +(According to the latex guide the above should be nicely spaced, but I get +equations that are touching. Why?) + +If $p(0)$ is a fixed value specified by the user then $p'(0)$ =0. +Otherwise $p(0)$ is the emprical distribution of the initial states, just +before the first death time $d_1$. Let $n_0$ be the (weighted) count of +subjects who are at risk at that time. +The $j$th row of $p'(0)$ is defined as the deviative wrt $w_i$ for a subject +who starts in state $j$. +If no one starts in state $j$ that row of the matrix will be 0, otherwise +it contains $(1-p_j(0)$ in the $jth$ element and $p_j(0)/n_0$ elsewhere. + +Define the matrix $W_{jk} = \sum_{l=1}^j T_{lk}$, with $W_{j0}=0$. +Then for someone who enters at time $s$ such that $d_a < s \le d_{a+1}$, +is censored or has an event at time $t$ such that $d_b \le t >= +Yold <- Y +utime <- fit$time[fit$time <= max(times) & etime] # unique death times +ndeath <- length(utime) # number of unique event times +delta <- diff(c(start.time, utime)) + +# Expand Y +if (ny==2) split <- .Call(Csurvsplit, rep(0., nrow(Y)), Y[,1], times) +else split <- .Call(Csurvsplit, Y[,1], Y[,2], times) +X <- X[split$row] +casewt <- casewt[split$row] +istate <- istate[split$row] +Y <- cbind(split$start, split$end, + ifelse(split$censor, 0, Y[split$row,ny])) +ny <- 3 + +# Create a vector containing the index of each end time into the fit object +yindex <- ystart <- double(nrow(Y)) +for (i in 1:length(fitrow)) { + yrow <- (as.integer(X) ==i) # rows of Y for this curve + yindex[yrow] <- matchfun(Y[yrow, 2], fit, fitrow[[i]]) + ystart[yrow] <- matchfun(Y[yrow, 1], fit, fitrow[[i]]) +} +# And one indexing the reporting times into fit +tindex <- matrix(0L, nrow=length(fitrow), ncol=ntime) +for (i in 1:length(fitrow)) { + tindex[i,] <- matchfun(times, fit, fitrow[[i]]) +} +yindex[,] <- match(yindex, c(0,ff)) -1L +tindex[,] <- match(tindex, c(0,ff)) -1L +ystart[,] <- pmin(match(ystart, c(0,ff)) -1L, tindex) + +# Create the array of C matrices +cmat <- array(0, dim=c(nstate, nstate, ndeath)) # max(i2) = ndeath, by design +Hmat <- cmat + +# We only care about observations that had a transition; any transitions +# after the last reporting time are not relevant +transition <- (Y[,ny] !=0 & Y[,ny] != istate & + Y[,ny-1] <= max(times)) # obs that had a transition +i2 <- match(yindex, sort(unique(yindex))) # which C matrix this obs goes to +i2 <- i2[transition] +from <- as.numeric(istate[transition]) # from this state +to <- Y[transition, ny] # to this state +nrisk <- fit$n.risk[cbind(yindex[transition], from)] # number at risk +wt <- casewt[transition] +for (i in seq(along.with =from)) { + j <- c(from[i], to[i]) + haz <- wt[i]/nrisk[i] + cmat[from[i], j, i2[i]] <- cmat[from[i], j, i2[i]] + c(-haz, haz) +} +for (i in 1:ndeath) Hmat[,,i] <- cmat[,,i] + diag(nstate) + +# The transformation matrix H(t) at time t is cmat[,,t] + I +# Create the set of W and V matrices. +# +dindex <- which(etime & fit$time <= max(times)) +Wmat <- Vmat <- array(0, dim=c(nstate, nstate, ndeath)) +for (i in ndeath:1) { + j <- match(dindex[i], tindex, nomatch=0) + if (j > 0) { + # this death matches one of the reporting times + Wmat[,,i] <- diag(nstate) + Vmat[,,i] <- matrix(0, nstate, nstate) + } + else { + Wmat[,,i] <- Hmat[,,i+1] %*% Wmat[,,i+1] + Vmat[,,i] <- delta[i] + Hmat[,,i+1] %*% Wmat[,,i+1] + } +} +@ + +The above code has created the Wmat array for all reporting times and +for all the curves (if more than one). +Each of them reaches forward to the next reporting time. +Now work forward in time. + +<>= +iterm <- array(0, dim=c(nstate, nstate, ndeath)) # term in equation +itemp <- vtemp <- matrix(0, nstate, nstate) # cumulative sum, temporary +isum <- isum2 <- iterm # cumulative sum +vsum <- vsum2 <- vterm <- iterm +for (i in 1:ndeath) { + j <- dindex[i] + n0 <- ifelse(fit$n.risk[j,] ==0, 1, fit$n.risk[j,]) # avoid 0/0 + iterm[,,i] <- ((fit$pstate[j-1,]/n0) * cmat[,,i]) %*% Wmat[,,i] + vterm[,,i] <- ((fit$pstate[j-1,]/n0) * cmat[,,i]) %*% Vmat[,,i] + itemp <- itemp + iterm[,,i] + vtemp <- vtemp + vterm[,,i] + isum[,,i] <- itemp + vsum[,,i] <- vtemp + j <- match(dindex[i], tindex, nomatch=0) + if (j>0) itemp <- vtemp <- matrix(0, nstate, nstate) # reset + isum2[,,i] <- itemp + vsum2[,,i] <- vtemp +} + +# We want to add isum[state,, entry time] - isum[state,, exit time] for +# each subject, and for those with an a:b transition there will be an +# additional vector with -1, 1 in the a and b position. +i1 <- match(ystart, sort(unique(yindex)), nomatch=0) # start at 0 gives 0 +i2 <- match(yindex, sort(unique(yindex))) +D <- matrix(0., nrow(Y), nstate) +keep <- (Y[,2] <= max(times)) # any intervals after the last reporting time + # will have 0 influence +for (i in which(keep)) { + if (Y[i,3] !=0 && istate[i] != Y[i,3]) { + z <- fit$pstate[yindex[i]-1, istate[i]]/fit$n.risk[yindex[i], istate[i]] + temp <- double(nstate) + temp[istate[i]] = -z + temp[Y[i,3]] = z + temp <- temp %*% Wmat[,,i2[i]] - isum[istate[i],,i2[i]] + if (i1[i] >0) temp <- temp + isum2[istate[i],, i1[i]] + D[i,] <- temp + } + else { + if (i1[i] >0) D[i,] = isum2[istate[i],,i1[i]] - isum[istate[i],, i2[i]] + else D[i,] = -isum[istate[i],, i2[i]] + } +} +@ + +By design, each row of $Y$, and hence each row of $D$, corresponds to a unique +curve, and also to a unique period in the reporting intervals. +(Any Y intervals after the last reporting time will have D=0 for the row.) +If there are multiple reporting intervals, create an array with one +n by nstate slice for each. +If a row lies in the first interval, $D$ currently contains its influence +on that interval. It's influence on the second interval is the vector times +$\prod H(d_k)$ where $k$ is the set of event times $>$ the first reporting time +and $\le$ the second one. + +<>= +Dsave <- D +if (!is.null(inf0)) { + # add in the initial influence, to the first row of each obs + # (inf0 was created on unsplit data) + j <- which(!duplicated(split$row)) + D[j,] <- D[j,] + (inf0%*% Hmat[,,1] %*% Wmat[,,1]) +} +if (ntime > 1) { + interval <- findInterval(yindex, tindex, left.open=TRUE) + D2 <- array(0., dim=c(dim(D), ntime)) + D2[interval==0,,1] <- D[interval==0,] + for (i in 1:(ntime-1)) { + D2[interval==i,,i+1] = D[interval==i,] + j <- tindex[i] + D2[,,i+1] = D2[,,i+1] + D2[,,i] %*% (Hmat[,,j] %*% Wmat[,,j]) + } + D <- D2 +} + +# undo any artificial split +if (any(duplicated(split$row))) { + if (ntime==1) D <- rowsum(D, split$row) + else { + # rowsums has to be fooled + temp <- rowsum(matrix(D, ncol=(nstate*ntime)), split$row) + # then undo it + D <- array(temp, dim=c(nrow(temp), nstate, ntime)) + } +} +@ +\section{Accelerated Failure Time models} +The [[surveg]] function fits parametric failure time models. +This includes accerated failure time models, the Weibull, log-normal, +and log-logistic models. +It also fits as well as censored linear regression; with left censoring +this is referred to in economics \emph{Tobit} regression. + +\subsection{Residuals} +The residuals for a [[survreg]] model are one of several types +\begin{description} + \item[response] residual [[y]] value on the scale of the original data + \item[deviance] an approximate deviance residual. A very bad idea + statistically, retained for the sake of backwards compatability. + \item[dfbeta] a matrix with one row per observation and one column per + parameter showing the approximate influence of each observation on + the final parameter value + \item[dfbetas] the dfbeta residuals scaled by the standard error of + each coefficient + \item[working] residuals on the scale of the linear predictor + \item[ldcase] likelihood displacement wrt case weights + \item[ldresp] likelihood displacement wrt response changes + \item[ldshape] likelihood displacement wrt changes in shape + \item[matrix] matrix of derivatives of the log-likelihood wrt paramters +\end{description} + +The other parameters are +\begin{description} + \item[rsigma] whether the scale parameters should be included in the + result for dfbeta results. I can think of no reason why one would not + want them --- unless of course the scale was fixed by the user, in + which case there is no parameter. + \item[collapse] optional vector of subject identifiers. This is for the + case where a subject has multiple observations in a data set, and one + wants to have residuals per subject rather than residuals per observation. + \item[weighted] whether the residuals should be multiplied by the case + weights. The sum of weighted residuals will be zero. +\end{description} + +The routine starts with standard stuff, checking arguments for +validity and etc. +The two cases of response or working residuals require +a lot less computation. and are the most common calls, so they are +taken care of first. + +<>= +# +# Residuals for survreg objects +residuals.survreg <- function(object, type=c('response', 'deviance', + 'dfbeta', 'dfbetas', 'working', 'ldcase', + 'ldresp', 'ldshape', 'matrix'), + rsigma =TRUE, collapse=FALSE, weighted=FALSE, ...) { + type <-match.arg(type) + n <- length(object$linear.predictors) + Terms <- object$terms + if(!inherits(Terms, "terms")) + stop("invalid terms component of object") + + # If the variance wasn't estimated then it has no error + if (nrow(object$var) == length(object$coefficients)) rsigma <- FALSE + + # If there was a cluster directive in the model statment then remove + # it. It does not correspond to a coefficient, and would just confuse + # things later in the code. + cluster <- untangle.specials(Terms,"cluster")$terms + if (length(cluster) >0 ) + Terms <- Terms[-cluster] + + strata <- attr(Terms, 'specials')$strata + intercept <- attr(Terms, "intercept") + response <- attr(Terms, "response") + weights <- object$weights + if (is.null(weights)) weighted <- FALSE + + <> + <> + <> + <> + } +@ + +First retrieve the distribution, which is used multiple times. +The common case is a character string pointing to some element of +[[survreg.distributions]], but the other is a user supplied +list of the form contained there. +Some distributions are defined as the transform of another in which +case we need to set [[itrans]] and [[dtrans]] and follow the link, +otherwise the transformation and its inverse are the identity. +<>= +if (is.character(object$dist)) + dd <- survreg.distributions[[object$dist]] +else dd <- object$dist +ytype <- attr(y, "type") +if (is.null(dd$itrans)) { + itrans <- dtrans <-function(x)x + # reprise the work done in survreg to create a transformed y + if (ytype=='left') y[,2] <- 2- y[,2] + else if (type=='interval' && all(y[,3]<3)) y <- y[,c(1,3)] +} +else { + itrans <- dd$itrans + dtrans <- dd$dtrans + + # reprise the work done in survreg to create a transformed y + tranfun <- dd$trans + exactsurv <- y[,ncol(y)] ==1 + if (any(exactsurv)) logcorrect <-sum(log(dd$dtrans(y[exactsurv,1]))) + + if (ytype=='interval') { + if (any(y[,3]==3)) + y <- cbind(tranfun(y[,1:2]), y[,3]) + else y <- cbind(tranfun(y[,1]), y[,3]) + } + else if (ytype=='left') + y <- cbind(tranfun(y[,1]), 2-y[,2]) + else y <- cbind(tranfun(y[,1]), y[,2]) +} + +if (!is.null(dd$dist)) dd <- survreg.distributions[[dd$dist]] +deviance <- dd$deviance +dens <- dd$density +@ + +The next task is to decide what data we need. The response +is always needed, but is normally saved as a part of the +model. If it is a transformed distribution such as the +Weibull (a transform of the extreme value) the saved object +[[y]] is the transformed data, so we need to replicate that +part of the survreg() code. +(Why did I even allow for y=F in survreg? Because I was +mimicing the lm function --- oh the long, long consequences of +a design decision.) + +The covariate matrix [[x]] will be needed for all but +response, deviance, and working residuals. +If the model +included a strata() term then there will be multiple scales, +and the strata variable needs to be recovered. +The variable [[sigma]] is set to a scalar if there are no +strata, but otherwise to a vector with [[n]] elements containing +the appropriate scale for each subject. + +The leverage type residuals all need the second derivative +matrix. If there was a [[cluster]] statement in the model this +will be found in [[naive.var]], otherwise in the [[var]] +component. +<>= +if (is.null(object$naive.var)) vv <- object$var +else vv <- object$naive.var + +need.x <- is.na(match(type, c('response', 'deviance', 'working'))) +if (is.null(object$y) || !is.null(strata) || (need.x & is.null(object[['x']]))) + mf <- stats::model.frame(object) + +if (is.null(object$y)) y <- model.response(mf) +else y <- object$y + +if (!is.null(strata)) { + temp <- untangle.specials(Terms, 'strata', 1) + Terms2 <- Terms[-temp$terms] + if (length(temp$vars)==1) strata.keep <- mf[[temp$vars]] + else strata.keep <- strata(mf[,temp$vars], shortlabel=TRUE) + strata <- as.numeric(strata.keep) + nstrata <- max(strata) + sigma <- object$scale[strata] + } +else { + Terms2 <- Terms + nstrata <- 1 + sigma <- object$scale + } + +if (need.x) { + x <- object[['x']] #don't grab xlevels component + if (is.null(x)) + x <- model.matrix(Terms2, mf, contrasts.arg=object$contrasts) + } +@ + + + +The most common residual is type response, which requires almost +no more work, for the others we need to create the matrix of +derivatives before proceeding. +We use the [[center]] component from the deviance function for the +distribution, which returns the data point [[y]] itself for an +exact, left, or right censored observation, and an appropriate +midpoint for interval censored ones. +<>= +if (type=='response') { + yhat0 <- deviance(y, sigma, object$parms) + rr <- itrans(yhat0$center) - itrans(object$linear.predictor) + } +else { + <> + <> + } +@ + +The matrix of derviatives is used in all of the other cases. +The starting point is the [[density]] function of the distribtion +which return a matrix with columns of +$F(x)$, $1-F(x)$, $f(x)$, $f'(x)/f(x)$ and $f''(x)/f(x)$. %' +The matrix type residual contains columns for each of +$$ + L_i \quad \frac{\partial L_i}{\partial \eta_i} + \quad \frac{\partial^2 L_i}{\partial \eta_i^2} + \quad \frac{\partial L_i}{\partial \log(\sigma)} + \quad \frac{\partial L_i}{\partial \log(\sigma)^2} + \quad \frac{\partial^2 L_i}{\partial \eta \partial\log(\sigma)} +$$ +where $L_i$ is the contribution to the log-likelihood from each +individual. +Note that if there are multiple scales, i.e. a strata() term in the +model, then terms 3--6 are the derivatives for that subject with +respect to their \emph{particular} scale factor; derivatives with +respect to all the other scales are zero for that subject. + +The log-likelihood can be written as +\begin{align*} +L &= \sum_{exact}\left[ \log(f(z_i)) -\log(\sigma_i) \right] + + \sum_{censored} \log \left( \int_{z_i^l}^{z_i^u} f(u)du \right) \\ + &\equiv \sum_{exact}\left[g_1(z_i) -\log(\sigma_i) \right] + + \sum_{censored} \log(g_2(z_i^l, z_i^u)) \\ + z_i &= (y_i - \eta_i)/ \sigma_i + \end{align*} +For the interval censored observations we have a $z$ defined at both the +lower and upper endpoints. +The linear predictor is $\eta = X\beta$. + +The derivatives are shown below. +Note that $f(-\infty) = f(\infty) = F(-\infty)=0$, +$F(\infty)=1$, $z^u = \infty$ for a right censored observation +and $z^l = -\infty$ for a left censored one. +\begin{align*} +\frac{\partial g_1}{\partial \eta} &= - \frac{1}{\sigma} + \left[\frac{f'(z)}{f(z)} \right] \\ %' +\frac{\partial g_2}{\partial \eta} &= - \frac{1}{\sigma} \left[ + \frac{f(z^u) - f(z^l)}{F(z^u) - F(z^l)} \right] \\ +\frac{\partial^2 g_1}{\partial \eta^2} &= \frac{1}{\sigma^2} + \left[ \frac{f''(z)}{f(z)} \right] + - (\partial g_1 / \partial \eta)^2 \\ +\frac{\partial^2 g_2}{\partial \eta^2} &= \frac{1}{\sigma^2} \left[ + \frac{f'(z^u) - f'(z^l)}{F(z^u) - F(z^l)} \right] + - (\partial g_2 / \partial \eta)^2 \\ +\frac{\partial g_1}{\partial \log\sigma} && - \left[ + \frac{zf'(z)}{f(z)} \right] \\ +\frac{\partial g_2}{\partial \log\sigma} &= - \left[ + \frac{z^uf(z^u) - z^lf(z^l)}{F(z^u) - F(z^l)} \right] \\ +\frac{\partial^2 g_1}{\partial (\log\sigma)^2} &=& \left[ + \frac{z^2 f''(z) + zf'(z)}{f(z)} \right] + - (\partial g_1 / \partial \log\sigma)^2 \\ +\frac{\partial^2 g_2}{\partial (\log\sigma)^2} &= \left[ + \frac{(z^u)^2 f'(z^u) - (z^l)^2f'(z_l) } + {F(z^u) - F(z^l)} \right] + - \partial g_1 /\partial \log\sigma(1+\partial g_1 / \partial \log\sigma) \\ +\frac{\partial^2 g_1}{\partial \eta \partial \log\sigma} &= + \frac{zf''(z)}{\sigma f(z)} + -\partial g_1/\partial \eta (1 + \partial g_1/\partial \log\sigma) \\ +\frac{\partial^2 g_2}{\partial \eta \partial \log\sigma} &= + \frac{z^uf'(z^u) - z^lf'(z^l)}{\sigma [F(z^u) - F(z^l)]} + -\partial g_2/\partial \eta (1 + \partial g_2/\partial \log\sigma) \\ +\end{align*} + +In the code [[z]] is the relevant point for exact, left, or right +censored data, and [[z2]] the upper endpoint for an interval censored one. +The variable [[tdenom]] contains the denominator for each subject (which +is the same for all derivatives for that subject). +For an interval censored observation we try to avoid numeric cancellation +by using the appropriate tail of the distribution. +For instance with $(z^l, z^u) = (12,15)$ the value of $F(x)$ will be very +near 1 and it is better to subtract two upper tail values $(1-F)$ than +two lower tail ones $F$. +<>= +status <- y[,ncol(y)] +eta <- object$linear.predictors +z <- (y[,1] - eta)/sigma +dmat <- dens(z, object$parms) +dtemp<- dmat[,3] * dmat[,4] #f' +if (any(status==3)) { + z2 <- (y[,2] - eta)/sigma + dmat2 <- dens(z2, object$parms) + } +else { + dmat2 <- dmat #dummy values + z2 <- 0 + } + +tdenom <- ((status==0) * dmat[,2]) + #right censored + ((status==1) * 1 ) + #exact + ((status==2) * dmat[,1]) + #left + ((status==3) * ifelse(z>0, dmat[,2]-dmat2[,2], + dmat2[,1] - dmat[,1])) #interval +g <- log(ifelse(status==1, dmat[,3]/sigma, tdenom)) #loglik +tdenom <- 1/tdenom +dg <- -(tdenom/sigma) *(((status==0) * (0-dmat[,3])) + #dg/ eta + ((status==1) * dmat[,4]) + + ((status==2) * dmat[,3]) + + ((status==3) * (dmat2[,3]- dmat[,3]))) + +ddg <- (tdenom/sigma^2) *(((status==0) * (0- dtemp)) + #ddg/eta^2 + ((status==1) * dmat[,5]) + + ((status==2) * dtemp) + + ((status==3) * (dmat2[,3]*dmat2[,4] - dtemp))) + +ds <- ifelse(status<3, dg * sigma * z, + tdenom*(z2*dmat2[,3] - z*dmat[,3])) +dds <- ifelse(status<3, ddg* (sigma*z)^2, + tdenom*(z2*z2*dmat2[,3]*dmat2[,4] - + z * z*dmat[,3] * dmat[,4])) +dsg <- ifelse(status<3, ddg* sigma*z, + tdenom *(z2*dmat2[,3]*dmat2[,4] - z*dtemp)) +deriv <- cbind(g, dg, ddg=ddg- dg^2, + ds = ifelse(status==1, ds-1, ds), + dds=dds - ds*(1+ds), + dsg=dsg - dg*(1+ds)) +@ + +Now, we can calcultate the actual residuals case by case. +For the dfbetas there will be one column per coefficient, +so if there are strata column 4 of the deriv matrix needs +to be \emph{un}collapsed into a matrix with nstrata columns. +The same manipulation is needed for the ld residuals. +<>= +if (type=='deviance') { + yhat0 <- deviance(y, sigma, object$parms) + rr <- (-1)*deriv[,2]/deriv[,3] #working residuals + rr <- sign(rr)* sqrt(2*(yhat0$loglik - deriv[,1])) + } + +else if (type=='working') rr <- (-1)*deriv[,2]/deriv[,3] + +else if (type=='dfbeta' || type== 'dfbetas' || type=='ldcase') { + score <- deriv[,2] * x # score residuals + if (rsigma) { + if (nstrata > 1) { + d4 <- matrix(0., nrow=n, ncol=nstrata) + d4[cbind(1:n, strata)] <- deriv[,4] + score <- cbind(score, d4) + } + else score <- cbind(score, deriv[,4]) + } + rr <- score %*% vv + # cause column names to be retained + # old: if (type=='dfbetas') rr[] <- rr %*% diag(1/sqrt(diag(vv))) + if (type=='dfbetas') rr <- rr * rep(1/sqrt(diag(vv)), each=nrow(rr)) + if (type=='ldcase') rr<- rowSums(rr*score) + } + +else if (type=='ldresp') { + rscore <- deriv[,3] * (x * sigma) + if (rsigma) { + if (nstrata >1) { + d6 <- matrix(0., nrow=n, ncol=nstrata) + d6[cbind(1:n, strata)] <- deriv[,6]*sigma + rscore <- cbind(rscore, d6) + } + else rscore <- cbind(rscore, deriv[,6] * sigma) + } + temp <- rscore %*% vv + rr <- rowSums(rscore * temp) + } + +else if (type=='ldshape') { + sscore <- deriv[,6] *x + if (rsigma) { + if (nstrata >1) { + d5 <- matrix(0., nrow=n, ncol=nstrata) + d5[cbind(1:n, strata)] <- deriv[,5] + sscore <- cbind(sscore, d5) + } + else sscore <- cbind(sscore, deriv[,5]) + } + temp <- sscore %*% vv + rr <- rowSums(sscore * temp) + } + +else { #type = matrix + rr <- deriv + } +@ + +Finally the two optional steps of adding case weights and +collapsing over subject id. +<>= +#case weights +if (weighted) rr <- rr * weights + +#Expand out the missing values in the result +if (!is.null(object$na.action)) { + rr <- naresid(object$na.action, rr) + if (is.matrix(rr)) n <- nrow(rr) + else n <- length(rr) + } + +# Collapse if desired +if (!missing(collapse)) { + if (length(collapse) !=n) stop("Wrong length for 'collapse'") + rr <- drop(rowsum(rr, collapse)) + } + +rr +@ + + + + + + + + +\section{Survival curves} +The survfit function was set up as a method so that we could apply the +function to both formulas (to compute the Kaplan-Meier) and to coxph +objects. +The downside to this is that the manual pages get a little odd, but from +a programming perspective it was a good idea. +At one time, long long ago, we allowed the function to be called with +``Surv(time, status)'' as the formula, i.e., without a tilde. That was +a bad idea, now abandoned. + +A note on times: one of the things that drove me nuts was the problem of +``tied but not quite tied'' times. +As an example consider two values of 24173 = 23805 + 368. These are values from +an actual study with times in days. +However, the user chose to use age in years, and saved those values out +in a CSV file, resulting in values for the above of 66.18206708000000 +and 66.18206708000001. +The R phrase \code{unique(x)} sees these two values as distinct but +\code{table(x)} and \code{tapply} see it as a single value since they +first apply \code{factor} to the values, and that in turn uses +\code{as.character}. +A transition through CSV is not necessary to create the problem: +<>= +tfun <- function(start, gap) { + as.numeric(start)/365.25 - as.numeric(start + gap)/365.25 +} + +test <- logical(200) +for (i in 1:200) { + test[i] <- tfun(as.Date("2010/01/01"), 29) == + tfun(as.Date("2010/01/01") + i, 29) +} +table(test) +@ +The number of FALSE entries in the table depends on machine, compiler, +and a host of other issues. +There is discussion of this general issue in the R FAQ: ``why doesn't R +think these numbers are equal''. +The Kaplan-Meier and Cox model both pay careful attention to ties, and +so both now use the \code{aeqSurv} routine to first preprocess +the time data. It uses the same rules as \code{all.equal} to +adjudicate ties and near ties. + + +<>= +survfit <- function(formula, ...) { + UseMethod("survfit") +} + +<> +<> +<> +@ + +The result of a survival curve will have a \code{surv} or \code{pstate} +component that is a vector or a matrix, and an optional strata component. +From a user's point of view this is an object with [strata, newdata, state] +as dimensions, where only 1, 2 or all three of these may appear. +The first is always present, and is essentially the number of distinct +curves created by the right-hand side of the equation (or by the strata in +a coxph model). +The newdata portion appears for survival curves from a Cox model, when curves +for multiple covariate patterns were requested; +the state portion only from a multi-state model; or both for a multi-state +Cox model. +The \code{surv} component contains the time points for the first stratum, +the second, third, etc stacked one above the other. +As with R matrices, if only 1 subscript is given for an array or matrix of +curves, we treat the collection of curves as a vector of curves. +We need to make sure that the new object has the same order of elements as +the old -- users count on this. + +<>= +dim.survfit <- function(x) { + d1name <- "strata" + d2name <- "data" + d3name <- "states" + if (is.null(x$strata)) {d1 <- d1name <- NULL} else d1 <- length(x$strata) + if (is.null(x$newdata)) {d2 <- d2name <- NULL} else d2 <- nrow(x$newdata) + if (is.null(x$states)) {d3 <- d3name <- NULL} else d3 <- length(x$states) + + if (inherits(x, "survfitcox") && is.null(d2) && is.null(d3) && + is.matrix(x$surv)) { + # older style survfit.coxph object, before I added newdata to the output + d2name <- "data" + d2 <- ncol(x$surv) + } + + dd <- c(d1, d2, d3) + names(dd) <- c(d1name, d2name, d3name) + dd +} + +# there is a separate function for survfitms objects +"[.survfit" <- function(x, ... , drop=TRUE) { + nmatch <- function(indx, target) { + # This function lets R worry about character, negative, or + # logical subscripts. + # It always returns a set of positive integer indices + temp <- 1:length(target) + names(temp) <- target + temp[indx] + } + + if (!inherits(x, "survfit")) stop("[.survfit called on non-survfit object") + ndots <- ...length() # the simplest, but not avail in R 3.4 + # ndots <- length(list(...))# fails if any are missing, e.g. fit[,2] + # ndots <- if (missing(drop)) nargs()-1 else nargs()-2 # a workaround + + dd <- dim(x) + # for dd=NULL, an object with only one curve, x[1] is always legal + if (is.null(dd)) dd <- c(strata=1L) # survfit object with only one curve + dtype <- match(names(dd), c("strata", "data", "states")) + + if (ndots >0 && !missing(..1)) i <- ..1 else i <- NULL + if (ndots> 1 && !missing(..2)) j <- ..2 else j <- NULL + + if (ndots > length(dd)) + stop("incorrect number of dimensions") + if (length(dtype) > 2) stop("invalid survfit object") # should never happen + if (is.null(i) && is.null(j)) { + # called with no subscripts given -- return x untouched + return(x) + } + + # Code below is easier if "i" is always the strata + if (dtype[1] !=1) { + dtype <- c(1, dtype) + j <- i; i <- NULL + dd <- c(1, dd) + ndots <- ndots +1 + } + + # We need to make a new one + newx <- vector("list", length(x)) + names(newx) <- names(x) + for (k in c("logse", "version", "conf.int", "conf.type", "type", "call")) + if (!is.null(x[[k]])) newx[[k]] <- x[[k]] + class(newx) <- class(x) + + if (ndots== 1 && length(dd)==2) { + # one subscript given for a two dimensional object + # If one of the dimensions is 1, it is easier for me to fill in i and j + if (dd[1]==1) {j <- i; i<- 1} + else if (dd[2]==1) j <- 1 + else { + # the user has a mix of rows/cols + index <- 1:prod(dd) + itemp <- matrix(index, nrow=dd[1]) + keep <- itemp[i] # illegal subscripts will generate an error + if (length(keep) == length(index) && all(keep==index)) return(x) + + ii <- row(itemp)[keep] + jj <- col(itemp)[keep] + # at this point we have a matrix subscript of (ii, jj) + # expand into a long pair of rows and cols + temp <- split(seq(along.with=x$time), + rep(1:length(x$strata), x$strata)) + indx1 <- unlist(temp[ii]) # rows of the surv object + indx2 <- rep(jj, x$strata[ii]) + + # return with each curve as a separate strata + newx$n <- x$n[ii] + for (k in c("time", "n.risk", "n.event", "n.censor", "n.enter")) + if (!is.null(x[[k]])) newx[[k]] <- (x[[k]])[indx1] + k <- cbind(indx1, indx2) + for (j in c("surv", "std.err", "upper", "lower", "cumhaz", + "std.chaz", "influence.surv", "influence.chaz")) + if (!is.null(x[[j]])) newx[[j]] <- (x[[j]])[k] + temp <- x$strata[ii] + names(temp) <- 1:length(ii) + newx$strata <- temp + return(newx) + } + } + + # irow will be the rows that need to be taken + # j the columns (of present) + if (is.null(x$strata)) { + if (is.null(i) || all(i==1)) irow <- seq(along.with=x$time) + else stop("subscript out of bounds") + newx$n <- x$n + } + else { + if (is.null(i)) indx <- seq(along.with= x$strata) + else indx <- nmatch(i, names(x$strata)) #strata to keep + if (any(is.na(indx))) + stop(paste("strata", + paste(i[is.na(indx)], collapse=' '), + 'not matched')) + # Now, indx may not be in order: some can use curve[3:2] to reorder + # The list/unlist construct will reorder the data + temp <- split(seq(along.with =x$time), + rep(1:length(x$strata), x$strata)) + irow <- unlist(temp[indx]) + + if (length(indx) <=1 && drop) newx$strata <- NULL + else newx$strata <- x$strata[i] + + newx$n <- x$n[indx] + if (length(indx) ==1 & drop) x$strata <- NULL + else newx$strata <- x$strata[indx] + } + + if (length(dd)==1) { # no j dimension + for (k in c("time", "n.risk", "n.event", "n.censor", "n.enter", + "surv", "std.err", "cumhaz", "std.chaz", "upper", "lower", + "influence.surv", "influence.chaz")) + if (!is.null(x[[k]])) newx[[k]] <- (x[[k]])[irow] + } + + else { # 2 dimensional object + if (is.null(j)) j <- seq.int(ncol(x$surv)) + # If the curve has been selected by strata and keep has only + # one row, we don't want to lose the second subscript too + if (length(irow)==1) drop <- FALSE + + for (k in c("time", "n.risk", "n.event", "n.censor", "n.enter")) + if (!is.null(x[[k]])) newx[[k]] <- (x[[k]])[irow] + for (k in c("surv", "std.err", "cumhaz", "std.chaz", "upper", "lower", + "influence.surv", "influence.chaz")) + if (!is.null(x[[k]])) newx[[k]] <- (x[[k]])[irow, j, drop=drop] + } + newx +} +@ + +\subsection{Kaplan-Meier} +The most common use of the survfit function is with a formula as the first +argument, and the most common outcome of such a call is a Kaplan-Meier +curve. + +The id argument is from an older version of the competing risks code; most +people will use [[cluster(id)]] in the formula instead. +The istate argument only applies to competing risks, but don't print +an error message if it is accidentally there. + +<>= +survfit.formula <- function(formula, data, weights, subset, + na.action, stype=1, ctype=1, + id, cluster, robust, istate, + timefix=TRUE, etype, error, ...) { + + Call <- match.call() + Call[[1]] <- as.name('survfit') #make nicer printout for the user + <> + + # Deal with the near-ties problem + if (!is.logical(timefix) || length(timefix) > 1) + stop("invalid value for timefix option") + if (timefix) newY <- aeqSurv(Y) else newY <- Y + + if (missing(robust)) robust <- NULL + # Call the appropriate helper function + if (attr(Y, 'type') == 'left' || attr(Y, 'type') == 'interval') + temp <- survfitTurnbull(X, newY, casewt, ...) + else if (attr(Y, 'type') == "right" || attr(Y, 'type')== "counting") + temp <- survfitKM(X, newY, casewt, stype=stype, ctype=ctype, id=id, + cluster=cluster, robust=robust, ...) + else if (attr(Y, 'type') == "mright" || attr(Y, "type")== "mcounting") + temp <- survfitCI(X, newY, weights=casewt, stype=stype, ctype=ctype, + id=id, cluster=cluster, robust=robust, + istate=istate, ...) + else { + # This should never happen + stop("unrecognized survival type") + } + + # If a stratum had no one beyond start.time, the length 0 gives downstream + # failure, e.g., there is no sensible printout for summary(fit, time= 100) + # for such a curve + temp$strata <- temp$strata[temp$strata >0] + if (is.null(temp$states)) class(temp) <- 'survfit' + else class(temp) <- c("survfitms", "survfit") + + if (!is.null(attr(mf, 'na.action'))) + temp$na.action <- attr(mf, 'na.action') + + temp$call <- Call + temp + } +@ + +This chunk of code is shared with resid.survfit +<>= +# create a copy of the call that has only the arguments we want, +# and use it to call model.frame() +indx <- match(c('formula', 'data', 'weights', 'subset','na.action', + 'istate', 'id', 'cluster', "etype"), names(Call), nomatch=0) +#It's very hard to get the next error message other than malice +# eg survfit(wt=Surv(time, status) ~1) +if (indx[1]==0) stop("a formula argument is required") +temp <- Call[c(1, indx)] +temp[[1L]] <- quote(stats::model.frame) +mf <- eval.parent(temp) + +Terms <- terms(formula, c("strata", "cluster")) +ord <- attr(Terms, 'order') +if (length(ord) & any(ord !=1)) + stop("Interaction terms are not valid for this function") + +n <- nrow(mf) +Y <- model.response(mf) +if (inherits(Y, "Surv2")) { + # this is Surv2 style data + # if there are any obs removed due to missing, remake the model frame + if (length(attr(mf, "na.action"))) { + temp$na.action <- na.pass + mf <- eval.parent(temp) + } + if (!is.null(attr(Terms, "specials")$cluster)) + stop("cluster() cannot appear in the model statement") + new <- surv2data(mf) + mf <- new$mf + istate <- new$istate + id <- new$id + Y <- new$y + if (anyNA(mf[-1])) { #ignore the response variable still found there + if (missing(na.action)) temp <- get(getOption("na.action"))(mf[-1]) + else temp <- na.action(mf[-1]) + omit <- attr(temp, "na.action") + mf <- mf[-omit,] + Y <- Y[-omit] + id <- id[-omit] + istate <- istate[-omit] + } + n <- nrow(mf) +} +else { + if (!is.Surv(Y)) stop("Response must be a survival object") + id <- model.extract(mf, "id") + istate <- model.extract(mf, "istate") +} +if (n==0) stop("data set has no non-missing observations") + +casewt <- model.extract(mf, "weights") +if (is.null(casewt)) casewt <- rep(1.0, n) +else { + if (!is.numeric(casewt)) stop("weights must be numeric") + if (any(!is.finite(casewt))) stop("weights must be finite") + if (any(casewt <0)) stop("weights must be non-negative") + casewt <- as.numeric(casewt) # transform integer to numeric +} + +if (!is.null(attr(Terms, 'offset'))) warning("Offset term ignored") + +cluster <- model.extract(mf, "cluster") +temp <- untangle.specials(Terms, "cluster") +if (length(temp$vars)>0) { + if (length(cluster) >0) stop("cluster appears as both an argument and a model term") + if (length(temp$vars) > 1) stop("can not have two cluster terms") + cluster <- mf[[temp$vars]] + Terms <- Terms[-temp$terms] +} + +ll <- attr(Terms, 'term.labels') +if (length(ll) == 0) X <- factor(rep(1,n)) # ~1 on the right +else X <- strata(mf[ll]) + +# Backwards support for the now-depreciated etype argument +etype <- model.extract(mf, "etype") +if (!is.null(etype)) { + if (attr(Y, "type") == "mcounting" || + attr(Y, "type") == "mright") + stop("cannot use both the etype argument and mstate survival type") + if (length(istate)) + stop("cannot use both the etype and istate arguments") + status <- Y[,ncol(Y)] + etype <- as.factor(etype) + temp <- table(etype, status==0) + + if (all(rowSums(temp==0) ==1)) { + # The user had a unique level of etype for the censors + newlev <- levels(etype)[order(-temp[,2])] #censors first + } + else newlev <- c(" ", levels(etype)[temp[,1] >0]) + status <- factor(ifelse(status==0,0, as.numeric(etype)), + labels=newlev) + + if (attr(Y, 'type') == "right") + Y <- Surv(Y[,1], status, type="mstate") + else if (attr(Y, "type") == "counting") + Y <- Surv(Y[,1], Y[,2], status, type="mstate") + else stop("etype argument incompatable with survival type") +} +@ + +Once upon a time I allowed survfit to be called without the +`\textasciitilde 1' portion of the formula. +This was a mistake for multiple reasons, but the biggest problem is timing. +If the subject has a data statement but the first argument is not a formula, +R needs to evaluate Surv(t,s) to know that it is a survival object, +but it also needs to know that this is a survival object before evaluation +in order to dispatch the correct method. +The method below helps give a useful error message in some cases. +<>= +survfit.Surv <- function(formula, ...) + stop("the survfit function requires a formula as its first argument") +@ + + +The last peice in this file is the function to create confidence +intervals. It is called from multiple different places so it is well to +have one copy. +If $p$ is the survival probability and $s(p)$ its standard error, +we can do confidence intervals on the simple scale of +$ p \pm 1.96 s(p)$, but that does not have very good properties. +Instead use a transformation $y = f(p)$ for which the standard error is +$s(p) f'(p)$, leading to the confidence interval +\begin{equation*} + f^{-1}\left(f(p) +- 1.96 s(p)f'(p) \right) + \end{equation*} +Here are the supported transformations. +\begin{center} + \begin{tabular}{rccc} + &$f$& $f'$ & $f^{-1}$ \\ \hline +log & $\log(p)$ & $1/p$ & $ \exp(y)$ \\ +log-log & $\log(-\log(p))$ & $1/\left[ p \log(p) \right]$ & + $\exp(-\exp(y)) $ \\ +logit & $\log(p/1-p)$ & $1/[p (1-p)]$ & $1- 1/\left[1+ \exp(y)\right]$ \\ +arcsin & $\arcsin(\sqrt{p})$ & $1/(2 \sqrt{p(1-p)})$ &$\sin^2(y)$ \\ + +\end{tabular} \end{center} +Plain intervals can give limits outside of (0,1), we truncate them when this +happens. The log intervals can give an upper limit greater than 1, but the +lower limit is always valid, and the log-log and logit. The arcsin require +truncation in the middle of the formula. +In all cases we return NA as the CI for survival=0: it makes the graphs look +better. + +Some of the underlying routines compute the standard error of $p$ and some +the standard error of $\log(p)$. The \code{selow} argument is used for the +modified lower limits of Dory and Korn. When this is used for cumulative +hazards the ulimit arg will be FALSE: no upper limit of 1. + +<>= +survfit_confint <- function(p, se, logse=TRUE, conf.type, conf.int, + selow, ulimit=TRUE) { + zval <- qnorm(1- (1-conf.int)/2, 0,1) + if (missing(selow)) scale <- 1.0 + else scale <- ifelse(selow==0, 1.0, selow/se) # avoid 0/0 at the origin + if (!logse) se <- ifelse(se==0, 0, se/p) # se of log(survival) = log(p) + + if (conf.type=='plain') { + se2 <- se* p * zval # matches equation 4.3.1 in Klein & Moeschberger + if (ulimit) list(lower= pmax(p -se2*scale, 0), upper = pmin(p + se2, 1)) + else list(lower= pmax(p -se2*scale, 0), upper = p + se2) + } + else if (conf.type=='log') { + #avoid some "log(0)" messages + xx <- ifelse(p==0, NA, p) + se2 <- zval* se + temp1 <- exp(log(xx) - se2*scale) + temp2 <- exp(log(xx) + se2) + if (ulimit) list(lower= temp1, upper= pmin(temp2, 1)) + else list(lower= temp1, upper= temp2) + } + else if (conf.type=='log-log') { + xx <- ifelse(p==0 | p==1, NA, p) + se2 <- zval * se/log(xx) + temp1 <- exp(-exp(log(-log(xx)) - se2*scale)) + temp2 <- exp(-exp(log(-log(xx)) + se2)) + list(lower = temp1 , upper = temp2) + } + else if (conf.type=='logit') { + xx <- ifelse(p==0, NA, p) # avoid log(0) messages + se2 <- zval * se *(1 + xx/(1-xx)) + + temp1 <- 1- 1/(1+exp(log(p/(1-p)) - se2*scale)) + temp2 <- 1- 1/(1+exp(log(p/(1-p)) + se2)) + list(lower = temp1, upper=temp2) + } + else if (conf.type=="arcsin") { + xx <- ifelse(p==0, NA, p) + se2 <- .5 *zval*se * sqrt(xx/(1-xx)) + list(lower= (sin(pmax(0, asin(sqrt(xx)) - se2*scale)))^2, + upper= (sin(pmin(pi/2, asin(sqrt(xx)) + se2)))^2) + } + else stop("invalid conf.int type") +} +@ +\subsection{Kaplan-Meier} +This routine has been rewritten more times than any other in the package, +as we trade off simplicty of the code with execution speed. +This version does all of the oranizational work in S and calls a C +routine for each separate curve. +The first code did everything in C but was too hard to maintain and the most +recent prior function did nearly everything in S. +Introduction of robust variance +prompted a movement of more of the code into C since that calculation +is computationally intensive. + +<>= +survfitKM <- function(x, y, weights=rep(1.0,length(x)), + stype=1, ctype=1, + se.fit=TRUE, + conf.int= .95, + conf.type=c('log', 'log-log', 'plain', 'none', + 'logit', "arcsin"), + conf.lower=c('usual', 'peto', 'modified'), + start.time, id, cluster, robust, influence=FALSE, + type) { + + if (!missing(type)) { + if (!is.character(type)) stop("type argument must be character") + # older style argument is allowed + temp <- charmatch(type, c("kaplan-meier", "fleming-harrington", "fh2")) + if (is.na(temp)) stop("invalid value for 'type'") + type <- c(1,3,4)[temp] + } + else { + if (!(ctype %in% 1:2)) stop("ctype must be 1 or 2") + if (!(stype %in% 1:2)) stop("stype must be 1 or 2") + type <- as.integer(2*stype + ctype -2) + } + + conf.type <- match.arg(conf.type) + conf.lower<- match.arg(conf.lower) + if (is.logical(conf.int)) { + # A common error is for users to use "conf.int = FALSE" + # it's not correct, but allow it + if (!conf.int) conf.type <- "none" + conf.int <- .95 + } + + if (!is.Surv(y)) stop("y must be a Surv object") + if (attr(y, 'type') != 'right' && attr(y, 'type') != 'counting') + stop("Can only handle right censored or counting data") + ny <- ncol(y) # Will be 2 for right censored, 3 for counting + # The calling routine has used 'strata' on x, so it is a factor with + # no unused levels. But just in case a user called this... + if (!is.factor(x)) stop("x must be a factor") + xlev <- levels(x) # Will supply names for the curves + x <- as.integer(x) # keep the integer index + + if (missing(start.time)) time0 <- min(0, y[,ny-1]) + else time0 <- start.time + + # The user can call with cluster, id, robust, or any combination + # Default for robust: if cluster or any id with > 1 event or + # any weights that are not 0 or 1, then TRUE + # If only id, treat it as the cluster too + has.cluster <- !(missing(cluster) || length(cluster)==0) + has.id <- !(missing(id) || length(id)==0) + has.rwt<- (!missing(weights) && any(weights != floor(weights))) + #has.rwt <- FALSE # we are rethinking this + has.robust <- !missing(robust) && !is.null(robust) + if (has.id) id <- as.factor(id) + + if (missing(robust) || is.null(robust)) { + if (influence) { + robust <- TRUE + if (!(has.cluster || has.id)) { + cluster <- seq(along=x) + has.cluster <- TRUE + } + } + else if (has.cluster || has.rwt || + (has.id && anyDuplicated(id[y[,ncol(y)]==1]))) + robust <- TRUE + else robust <- FALSE + } + if (!is.logical(robust)) stop("robust must be TRUE/FALSE") + + if (has.cluster) { + if (!robust) { + warning("cluster specified with robust=FALSE, cluster ignored") + ncluster <- 0 + clname <- NULL + } + else { + if (is.factor(cluster)) { + clname <- levels(cluster) + cluster <- as.integer(cluster) + } else { + clname <- sort(unique(cluster)) + cluster <- match(cluster, clname) + } + ncluster <- length(clname) + } + } else if (robust) { + if (has.id) { + # treat the id as both identifier and clustering + clname <- levels(id) + cluster <- as.integer(id) + ncluster <- length(clname) + } + else if (ncol(y)==2 || !has.robust) { + # create our own clustering + n <- nrow(y) + cluster <- 1:n + ncluster <- n + clname <- 1:n + } + else stop("id or cluster option required") + } else ncluster <- 0 + + if (is.logical(influence)) { + # TRUE/FALSE is treated as all or nothing + if (!influence) influence <- 0L + else influence <- 3L + } + else if (!is.numeric(influence)) + stop("influence argument must be numeric or logical") + if (!(influence %in% 0:3)) stop("influence argument must be 0, 1, 2, or 3") + else influence <- as.integer(influence) + if (!robust && influence >0) { + warning("robust=FALSE implies influence=FALSE") + influence <- 0L + } + + if (!se.fit) { + # if the user asked for no standard error, skip any robust computation + ncluster <- 0L + influence <- 0L + } + + # if start.time was set, delete obs if necessary + keep <- y[,ny-1] >= time0 + if (!all(keep)) { + y <- y[keep,] + if (length(id) >0) id <- id[keep] + if (length(cluster) >0) cluster <- cluster[keep] + x <- x[keep] + weights <- weights[keep] + } + + + <> + <> +} +@ + +At each event time we have +\begin{itemize} + \item n(t) = number at risk = sum of weigths for those at risk + \item d(t) = number of events = sum of weights for the deaths + \item e(t) = unweighted number of events +\end{itemize} +From this we can calculate the Kapan-Meier and Nelson-Aalen estimates. +The Fleming-Harrington estimate is the analog of the Efron approximation +in a Cox model. +When there are no case weights the FH idea is quite simple. +Assume that the real data is not tied, but we saw a coarsened version. +If we see 3 events out of 10 subjects at risk the NA increment is 3/10 but the +FH is 1/10 + 1/9 + 1/8, it is what we would have seen with the +uncoarsened data. +If there are case weights we give each of the 3 terms a 1/3 chance of being +the first, second, or third event +\begin{align*} + KM(t) &= KM(t-) (1- d(t)/n(t) \\ + NA(t) &= NA(t-) + d(t)/n(t) \\ + FH(t) &= FH(t-) + \sum_{i=1}^{3} \frac{(d(t)/3}{n(t)- d(t)(i-1)/3} +\end{align*} + +When one of these 3 subjects has an event but continues, which can happen with +start/stop data, then this gets trickier: the second $d$ in the last equation +above should include only the other 2. The idea is that each of those will +certainly be present for the first event, has 2/3 chance of being present +for the second, and 1/3 for the third. +If we think of the size of the denominator as a random variable $Z$, an +exact solution would use $E(1/Z)$, the FH uses $1/E(Z)$ and the NA uses +$1/\max(Z)$ as the denominator for each of the 3 deaths. + +One problem with survival is near ties in Y: table, unique, ==, etc. can +do different things in this case. Luckily, the parent survfit routine +has dealt with that by using the \code{aeqSurv} function. + +The underlying C code allows the sort1/sort2 vectors to be a different +length than y, weights, and cluster. +When there is only one curve we use that to our advantage to avoid creating +a new copy of the last 3, passing in the original data. +When there are multiple curves I had an internal debate about efficiency. +Is is better to make a subset of y for each curve = more memory, or keep the +original y and address a different subset in each C call = worse memory +cache performance? I don't know the answer. +In either case the cluster vector needs to be re-done for each group. +Say that curve 1 uses subjects 1-10 and curve 2 uses 11-n: we don't want +the first curve to compute or keep the zero influence values for all the +subjects who are not in it. +Especially when returning the influence matrix, which can get too large +for memory. + +If ny==3 and has.id is true, then do some extra setup work, which is to +create a position vector of 1=first obs for the subject, 2 = last, 3=both, +0= other, for each set of back to back times. +This is used to prevent counting a subject with data of (0,10], (10,15] in +both the censored at 10 and entered at 10 totals. +We assume the data has been vetted to prevent overlapping intervals, so that +it suffices to sort by ending time. If a subject has holes in their timeline +they will have more than one first and last indicator. + +<>= +if (ny==3 & has.id) position <- survflag(y, id) +else position <- integer(0) + +if (length(xlev) ==1) {# only one group + if (ny==2) { + sort1 <- NULL + sort2 <- order(y[,1]) + } + else { + sort2 <- order(y[,2]) + sort1 <- order(y[,1]) + } + toss <- (y[sort2, ny-1] < time0) + if (any(toss)) { + # Some obs were removed by the start.time argument + sort2 <- sort2[!toss] + if (ny ==3) { + index <- match(which(toss), sort1) + sort1 <- sort1[-index] + } + } + n.used <- length(sort2) + if (ncluster > 0) + cfit <- .Call(Csurvfitkm, y, weights, sort1-1L, sort2-1L, type, + cluster-1L, ncluster, position, influence) + else cfit <- .Call(Csurvfitkm, y, weights, sort1-1L, sort2-1L, type, + 0L, 0L, position, influence) +} else { + # multiple groups + ngroup <- length(xlev) + cfit <- vector("list", ngroup) + n.used <- integer(ngroup) + if (influence) clusterid <- cfit # empty list of group id values + for (i in 1:ngroup) { + keep <- which(x==i & y[,ny-1] >= time0) + if (length(keep) ==0) next; # rare case where all are < start.time + ytemp <- y[keep,] + n.used[i] <- nrow(ytemp) + if (ny==2) { + sort1 <- NULL + sort2 <- order(ytemp[,1]) + } + else { + sort2 <- order(ytemp[,2]) + sort1 <- order(ytemp[,1]) + } + + # Cluster is a nuisance: every curve might have a different set + # We need to relabel them from 1 to "number of unique clusters in this + # curve for the C routine + if (ncluster > 0) { + c2 <- cluster[keep] + c.unique <- sort(unique(c2)) + nc <- length(c.unique) + c2 <- match(c2, c.unique) # renumber them + if (influence >0) { + clusterid[[i]] <-c.unique + } + } + + if (ncluster > 0) + cfit[[i]] <- .Call(Csurvfitkm, ytemp, weights[keep], sort1 -1L, + sort2 -1L, type, + c2 -1L, length(c.unique), position, influence) + else cfit[[i]] <- .Call(Csurvfitkm, ytemp, weights[keep], sort1 -1L, + sort2 -1L, type, + 0L, 0L, position, influence) + } +} +@ + +<>= +# create the survfit object +if (length(n.used) == 1) { + rval <- list(n= length(x), + time= cfit$time, + n.risk = cfit$n[,4], + n.event= cfit$n[,5], + n.censor=cfit$n[,6], + surv = cfit$estimate[,1], + std.err = cfit$std[,1], + cumhaz = cfit$estimate[,2], + std.chaz = cfit$std[,2]) + } else { + strata <- sapply(cfit, function(x) if (is.null(x$n)) 0L else nrow(x$n)) + names(strata) <- xlev + # we need to collapse the curves + rval <- list(n= as.vector(table(x)), + time = unlist(lapply(cfit, function(x) x$time)), + n.risk= unlist(lapply(cfit, function(x) x$n[,4])), + n.event= unlist(lapply(cfit, function(x) x$n[,5])), + n.censor=unlist(lapply(cfit, function(x) x$n[,6])), + surv = unlist(lapply(cfit, function(x) x$estimate[,1])), + std.err =unlist(lapply(cfit, function(x) x$std[,1])), + cumhaz =unlist(lapply(cfit, function(x) x$estimate[,2])), + std.chaz=unlist(lapply(cfit, function(x) x$std[,2])), + strata=strata) + if (ny==3) rval$n.enter <- unlist(lapply(cfit, function(x) x$n[,8])) +} + +if (ny ==3) { + rval$n.enter <- cfit$n[,8] + rval$type <- "counting" +} +else rval$type <- "right" + +if (se.fit) { + rval$logse = (ncluster==0 || (type==2 || type==4)) # se(log S) or se(S) + rval$conf.int = conf.int + rval$conf.type= conf.type + if (conf.lower != "usual") rval$conf.lower = conf.lower + + if (conf.lower == "modified") { + nstrat = length(n.used) + events <- rval$n.event >0 + if (nstrat ==1) events[1] <- TRUE + else events[1 + cumsum(c(0, rval$strata[-nstrat]))] <- TRUE + zz <- 1:length(events) + n.lag <- rep(rval$n.risk[events], diff(c(zz[events], 1+max(zz)))) + # + # n.lag = the # at risk the last time there was an event (or + # the first time of a strata) + # + } + std.low <- switch(conf.lower, + 'usual' = rval$std.err, + 'peto' = sqrt((1-rval$surv)/ rval$n.risk), + 'modified' = rval$std.err * sqrt(n.lag/rval$n.risk)) + + if (conf.type != "none") { + ci <- survfit_confint(rval$surv, rval$std.err, logse=rval$logse, + conf.type, conf.int, std.low) + rval <- c(rval, list(lower=ci$lower, upper=ci$upper)) + } +} else { + # for consistency don't return the se if std.err=FALSE + rval$std.err <- NULL + rval$std.chaz <- NULL +} + +# Add the influence, if requested by the user +# remember, if type= 3 or 4, the survival influence has to be constructed. +if (influence > 0) { + if (type==1 | type==2) { + if (influence==1 || influence ==3) { + if (length(xlev)==1) { + rval$influence.surv <- cfit$influence1 + row.names(rval$influence.surv) <- clname + } + else { + temp <- vector("list", ngroup) + for (i in 1:ngroup) { + temp[[i]] <- cfit[[i]]$influence1 + row.names(temp[[i]]) <- clname[clusterid[[i]]] + } + rval$influence.surv <- temp + } + } + if (influence==2 || influence==3) { + if (length(xlev)==1) { + rval$influence.chaz <- cfit$influence2 + row.names(rval$influence.chaz) <- clname + } + else { + temp <- vector("list", ngroup) + for (i in 1:ngroup) { + temp[[i]] <- cfit[[i]]$influence2 + row.names(temp[[i]]) <- clname[clusterid[[i]]] + } + rval$influence.chaz <- temp + } + } + } + else { + # everything is derived from the influence of the cumulative hazard + if (length(xlev) ==1) { + temp <- cfit$influence2 + row.names(temp) <- clname + } else { + temp <- vector("list", ngroup) + for (i in 1:ngroup) { + temp[[i]] <- cfit[[i]]$influence2 + row.names(temp[[i]]) <- clname[clusterid[[i]]] + } + } + + if (influence==2 || influence ==3) + rval$influence.chaz <- temp + + if (influence==1 || influence==3) { + # if an obs moves the cumulative hazard up, then it moves S down + if (length(xlev) ==1) + rval$influence.surv <- -temp * rep(rval$surv, each=nrow(temp)) + else { + for (i in 1:ngroup) + temp[[i]] <- -temp[[i]] * rep(cfit[[i]]$estimate[,1], + each=nrow(temp[[i]])) + rval$influence.surv <- temp + } + } + } +} + +if (!missing(start.time)) rval$start.time <- start.time +rval +@ + +Now for the real work using C routines. +My standard for a variable named ``zed'' is to use zed2 for the S object +and zed for the data part of the object; the latter is what the C code +works with. +<>= +#include +#include "survS.h" +#include "survproto.h" + +SEXP survfitkm(SEXP y2, SEXP weight2, SEXP sort12, SEXP sort22, + SEXP type2, SEXP id2, SEXP nid2, SEXP position2, + SEXP influence2) { + + int i, i1, i2, j, k, person1, person2; + int nused, nid, type, influence; + int ny, ntime; + double *tstart=0, *stime, *status, *wt; + double v1, v2, dtemp, haz; + double temp, dtemp2, dtemp3, frac, btemp; + int *sort1=0, *sort2, *id=0; + static const char *outnames[]={"time", "n", "estimate", "std.err", + "influence1", "influence2", ""}; + SEXP rlist; + double *gwt=0, *inf1=0, *inf2=0; /* =0 to silence -Wall */ + int *gcount=0; + int n1, n2, n3, n4; + int *position=0, hasid; + double wt1, wt2, wt3, wt4; + + /* output variables */ + double *n[10], *dtime, + *kvec, *nvec, *std[2], *imat1=0, *imat2=0; /* =0 to silence -Wall*/ + double km, nelson; /* current estimates */ + + /* map the input data */ + ny = ncols(y2); /* 2= ordinary survival 3= start,stop data */ + nused = nrows(y2); + if (ny==3) { + tstart = REAL(y2); + stime = tstart + nused; + sort1 = INTEGER(sort12); + } + else stime = REAL(y2); + status= stime +nused; + wt = REAL(weight2); + sort2 = INTEGER(sort22); + nused = LENGTH(sort22); + + type = asInteger(type2); + nid = asInteger(nid2); + if (LENGTH(position2) > 0) { + hasid =1; + position = INTEGER(position2); + } else hasid=0; + influence = asInteger(influence2); + + /* nused was used for two things just above. The first was the length of + the input data y, only needed for a moment to set up tstart, stime, and + status. The second is the number of these observations we will actually + use, which is the length of sort2. This routine can be called multiple + times with sort1/sort2 pointing to different subsets of the data while + y, wt, id and position can remain unchanged + */ + + if (length(id2)==0) nid =0; /* no robust variance */ + else id = INTEGER(id2); + + /* pass 1, get the number of unique times, needed for memory allocation + Number of xval groups (unique id values) has been supplied + Data is sorted by time + */ + ntime =1; + temp = stime[sort2[0]]; + for (i=1; i>= + /* Allocate memory for the output + n has 6 columns for number at risk, events, censor, then the + 3 weighted versions of the same, then optionally two more for + number added to the risk set (when ny=3) + */ + PROTECT(rlist = mkNamed(VECSXP, outnames)); + + dtime = REAL(SET_VECTOR_ELT(rlist, 0, allocVector(REALSXP, ntime))); + if (ny==2) j=7; else j=9; + n[0] = REAL(SET_VECTOR_ELT(rlist, 1, allocMatrix(REALSXP, ntime, j))); + for (i=1; i0 ) { /* robust variance */ + gcount = (int *) R_alloc(nid, sizeof(int)); + if (type <3) { /* working vectors for the influence */ + gwt = (double *) R_alloc(3*nid, sizeof(double)); + inf1 = gwt + nid; + inf2 = inf1 + nid; + for (i=0; i< nid; i++) { + gwt[i] =0.0; + gcount[i] = 0; + inf1[i] =0; + inf2[i] =0; + } + } + else { + gwt = (double *) R_alloc(2*nid, sizeof(double)); + inf2 = gwt + nid; + for (i=0; i< nid; i++) { + gwt[i] =0.0; + gcount[i] = 0; + inf2[i] =0; + } + } + + /* these are not accumulated, so do not need to be zeroed */ + if (type <3) { + if (influence==1 || influence ==3) + imat1 = REAL(SET_VECTOR_ELT(rlist, 4, + allocMatrix(REALSXP, nid, ntime))); + if (influence==2 || influence==3) + imat2 = REAL(SET_VECTOR_ELT(rlist, 5, + allocMatrix(REALSXP, nid, ntime))); + } + else if (influence !=0) + imat2 = REAL(SET_VECTOR_ELT(rlist, 5, + allocMatrix(REALSXP, nid, ntime))); + } + + <> + <> + + UNPROTECT(1); + return(rlist); +} +@ + +Pass 2 goes from the last time to the first and fills in the \code{n} matrix. +<>= +R_CheckUserInterrupt(); /*check for control-C */ +/* +** person1, person2 track through sort1 and sort2, respectively +** likewise with i1 and i2 +*/ +person1 = nused-1; person2 = nused-1; +n1=0; wt1=0; +for (k=ntime-1; k>=0; k--) { + dtime[k] = stime[sort2[person2]]; /* current time point */ + n2=0; n3=0; wt2=0; wt3=0; + for (; person2 >=0; person2--) { + i2= sort2[person2]; + if (stime[i2] != dtime[k]) break; + + n1++; /* number at risk */ + wt1 += wt[i2]; /* weighted number at risk */ + if (status[i2] ==1) { + n2++; /* events */ + wt2 += wt[i2]; + } else if (hasid==0 || (position[i2]& 2)) { + /* if there are no repeated obs for a subject (hasid=0) + ** or this is the last of a string (a,b](b,c](c,d].. for + ** a subject (position[i2]=2 or 3), then it is a 'real' censor + */ + n3++; + wt3 += wt[i2]; + } + } + + if (ny==3) { /* remove any with start time >=dtime*/ + n4 =0; wt4 =0; + for (; person1 >=0; person1--) { + i1 = sort1[person1]; + if (tstart[i1] < dtime[k]) break; + n1--; + wt1 -= wt[i1]; + if (hasid==0 || (position[i1] & 1)) { + /* if there are no repeated id (hasid=0) or this is the + ** first of a string of (a,b](b,c](c,d] for a subject, then + ** this is a 'real' entry */ + n4++; + wt4 += wt[i1]; + } + } + if (n4>0) { + n[6][k+1] = n4; + n[7][k+1] = wt4; + } + } + + n[0][k] = n1; n[1][k]=n2; n[2][k]=n3; + n[3][k] = wt1; n[4][k]=wt2; n[5][k]=wt3; +} + +if (ny ==3) { /* fill in number entered for the initial interval */ + n4=0; wt4=0; + for (; person1>=0; person1--) { + i1 = sort1[person1]; + if (hasid==0 || (position[i1] & 1)) { + n4++; + wt4 += wt[i1]; + } + } + n[6][0] = n4; + n[7][0] = wt4; +} +@ + +The rest of the code is identical for simple survival or start-stop data. +The cumulative hazard estimates are the Nelson-Aalen-Breslow (same estimate, +three different papers) or the Fleming-Harrington. +\begin{align*} + \Lambda_A(t) &\ \sum{u_j \le t} d_j/r_j \\ + \Lambda_{FH}(t) &= \sum{u_j \le t} \frac{d_j} + {f_j \sum_{k=0}^{f_j-1} (r_j - kd_j/f_j)} +\end{align*} +To understand the Fleming-Harrington estimate, suppose that at some time +point we had three deaths out of 10 at risk. The Aalen estimate gives a +hazard estimate of 3/10. +The FH estimate assumes that the deaths didn't actually all happen at once, +even though rounding in the data collection process makes it appear that +way, so the better estimate is 1/10 + 1/9 + 1/8. The third person to die, +whoever that was, would have had only 8 at risk when their event happened. + +The estimate of survival is either the Kaplan-Meier or the exponential +of the hazard. +\begin{equation*} + KM(t) = \prod_{u_j \le t} \frac{r_j - d_j}{r_j} +\end{equation*} + +The third pass goes from smallest time to largest. 99 times out of 100 the +user will choose type=1, so we try to avoid testing those +expression n times. +<>= +R_CheckUserInterrupt(); /*check for control-C */ +nelson =0.0; km=1.0; +v1=0; v2=0; +if (nid==0) { /* simple variance */ + if (type==1 || type==3) { /* Nelson-Aalen hazard */ + for (i=0; i0 && n[4][i]>0) { /* at least one event with wt>0*/ + nelson += n[4][i]/n[3][i]; + v2 += n[4][i]/(n[3][i]*n[3][i]); + } + + nvec[i] = nelson; + std[0][i] = sqrt(v2); + std[1][i] = sqrt(v2); + } + } else { /* Fleming hazard */ + for (i=0; i0 && n[4][i]>0) { /* at least one event */ + km *= (n[3][i]-n[4][i])/n[3][i]; + v1 += n[4][i]/(n[3][i] * (n[3][i] - n[4][i])); /* Greenwood */ + } + kvec[i] = km; + std[0][i] = sqrt(v1); + } + } else { /* exp survival */ + for (i=0; i< ntime; i++) { + kvec[i] = exp(-nvec[i]); + std[0][i] = std[1][i]; + } + } +} + +else { /* infinitesimal jackknife variance */ + <> +} +@ + +The robust variance is based on an infinitesimal jackknife (IJ). +Let $S_{-i}(t)$ be the survival curve without subject $i$ and +$J_i(t) = S_i(t) - S_{-i}(t)$ be the change in the +survival curve from adding subject $i$ back in. +Then the jackknife estimate of variance is +$$ + \sigma^2_J(t) = \sum \left( J_i(t) - \overline J(t) \right)^2 +$$ +The IJ estimate instead uses the linear approximation to the +jackknife, since it is normally less work to compute the derivative than a +whole new estimate. +Notice that if all the weights were doubled the expression below will stay +the same since the derivative will drop by 1/2. +\begin{align*} + \sigma^2_{IJ}(t_k) & = \sum_i w_i U_{ik}^2 \\ + U_{ik} & = \frac{\partial S(t_k)}{\partial w_i} +\end{align*} + +The big problem with the IJ estimate is that a first derivative matrix $U$ +will have one row per subject and one column per event time. +Since the number of unique event times tends to grow with $n$, this +matrix very rapidly becomes too large to manage. +Instead use a grouped jackknife with $g$ groups, +$g$ will often be on the order of 20--50. +The 0/1 design matrix $B$ has $n$ rows and $g$ columns, one column per group, +marking which subject is in each group. +The grouped jackknife can be written as +\begin{align*} + U'WBB'W U &= V'V +\end{align*} +Our goal is to accumulate and use $V$ instead of $U$. +The working vectors \code{inf1} and \code{inf2} contain the current +estimate for the survival S and cumulative hazard H, at a given time. +They are saved into the \code{imat} array for users, if desired. + +First work this out for the cumulative hazard, which is simpler, and a single +subject $k$. +\begin{align} + H(t) &= \sum_{s\le t} \frac{\sum w_i dN_i(s)}{\sum w_i Y_i(s)} \nonumber\\ + &= \sum _{s\le t} h(s) \nonumber \\ + U_k(t) &= U_k(t-) + \frac{\partial h(t)}{\partial w_k} \nonumber \\ + &= U_k(t-) + \frac{1}{\sum w_i Y_i(t)} \left(dN_k(t) - Y_k(t)h(t) \right) + \label{Una} \\ + \sum_k w_k U_k(t) &= 0 \nonumber +\end{align} +using the counting process notation of $N(t)$ for events and $Y(t)$ for at risk. +The weighted sum of the first derivatives is zero, so we don't need a mean +when computing the variance estimate. (This is true for all IJ estimators.) +$V$ involves the weighted sum of this over groups, +for the increment to each row of $V$ the rightmost term of \eqref{Una} is +replaced by the weighted sum over each group. Since $h$ is the same for +every subject at risk, we only need accumulate the sum of +subjects in and sum of events in each group. The first can be kept as +a running sum with $O(n)$ effort. + +When using the FH2 estimate tied deaths are different. Say that subject $i$ +dies at some time $t$ where there are 2 other tied deaths. +Let $w_i$ for $i=1,2,3$ be the weight of those who die and $s$ the sum of +weights for all the others. +The contribution to the cumulative hazard and derivative at this time point is +\begin{align*} + h &= \frac{w_1+w_2+w_3}{3} \frac{1}{s+w_1+w_2+w_3} + + \frac{w_1+w_2+w_3}{3} \frac{1}{s+ 2(w_1+w_2+w_3)/3} + + \frac{w_1+w_2+w_3}{3} \frac{1}{s+ (w_1 + w_2 + w_3)/3} \\ + &\equiv a(b_1 + b_2 + b_3) + \frac{\partial h}{\partial w_i} &= + &= \left\{ \begin{array}{cl} + \frac{b_1 + b_2 + b_3}{3} - a b_1^2 - (2/3)a b_2^2 - (1/3)a b_3^2 & i\le 3 \\ + -a(b_1^2 + b_2^2 + b_3^2) & i> 3 \end{array} \right . +\end{align*} +The idea is that if the data had been gathered with more precision, then there +would not be ties. The first death has 1/3 chance of being subject 1,2, or 3 +and all are in the denominator. The second also has 1/3 chance of being 1--3, +and each of these has 2/3 chance of still being in the denominator, etc. +The standard variance will be $ab_1^2 + ab_2^2 + ab_3^2$. + +For the Kaplan-Meier we have +\begin{align} + KM(t) &= KM(t-) [1 - h(t)] \nonumber\\ + U_k(t) &= \frac{\partial KM(t)}{\partial w_k} \nonumber\\ + &= U_k(t-) [1- h(t)] - + KM(t-)\frac{\partial h(t)}{\partial w_k} \label{Ukm} +\end{align} +The $V$ matrix is again a weighted sum. The first term of \eqref{Ukm} does +not change, it multiplies the current value times $1-h$. +The second term involves the same summation as the cumulative hazard. + +When using $\exp(-H)$ as the survival estimate then +\begin{align*} + \frac{partial S(t)}{\partial w_k} &= \frac{\partial e^{-H(t)}}{\partial w_k}\\ + &= e^{-H(t)} \partial{H(t)}{\partial w_k} +\end{align*} +so in this case only the robust variance for the cumulative hazard $H$ is +needed, and the parent R routine can fill in the rest. + +The variance for a given survival time is $\sum V^2$, which is always returned. +The code keeps the current $V$ vector for the hazard $H$ in \code{inf2}, and if +necessary that for the KM in \code{inf1}. +A last step is to add up the squares of all of these, so the algorithm is +$O(gp)$ where $p$ is the number of unique event times and $g$ is the number +of groups. +The sum of weights for each group is kept in a vector \code{gwt}, which is +updated as subjects enter and leave. + +Say that a study had n= 10 million subjects in g=100 groups with +d = 1 million deaths. +At each death we update the 'hazard' part of the influence for all 100 +groups, which is O(gd). +The deaths at that time point have a second increment, to whichever +group each is in, but since time is sorted that adds O(n) for indexing and +O(d) for the work. The most important thing is to avoid doing anything +that would be O(ng) or O(nd). +For method=3 the hazard part of the increment is also +different for a death, the solution is to do an ordinary increment for everyone +in the O(gd) step, then correct it when doing the O(d) update. + +<>= +v1=0; v2 =0; km=1; nelson =0; +person2=0; +if (ny==3) { + person1 =0; +} else { + /* at the start, everyone is at risk */ + for (i=0; i< nused; i++) { + i2 = id[i]; + gcount[i2]++; + gwt[i2] += wt[i]; + } +} + +if (type==1) { + for (i=0; i< ntime; i++) { + if (ny==3) { + /* add in new subjects */ + for (; person1 < nused; person1++) { + /* add in those whose start time is < dtime */ + i1 = sort1[person1]; + if (tstart[i1] >= dtime[i]) break; + gcount[id[i1]]++; + gwt[id[i1]] += wt[i1]; + } + } + + if (n[1][i] > 0 && n[4][i]>0) { /* need to update the sums */ + haz = n[4][i]/n[3][i]; + for (k=0; k< nid; k++) { + inf1[k] = inf1[k] *(1.0 -haz) + gwt[k]*km*haz/n[3][i]; + inf2[k] -= gwt[k] * haz/n[3][i]; + } + for (; person2 dtime[i]) break; /* those at this time */ + if (status[i2]==1) { + inf1[id[i2]] -= km* wt[i2]/n[3][i]; + inf2[id[i2]] += wt[i2]/n[3][i]; + } + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + } + km *= (1-haz); + nelson += haz; + + v1=0; v2=0; + for (k=0; k dtime[i]) break; + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + } + } + + kvec[i] = km; + nvec[i] = nelson; + std[0][i] = sqrt(v1); + std[1][i] = sqrt(v2); + if (influence==1 || influence ==3) + for (k=0; k= dtime[i]) break; + gcount[id[i1]]++; + gwt[id[i1]] += wt[i1]; + } + } + + if (n[1][i] > 0 && n[4][i] >0) { /* need to update the sums */ + dtemp =0; /* the working denominator */ + dtemp2=0; /* sum of squares */ + dtemp3=0; + temp = n[3][i] - n[4][i]; /* sum of weights for the non-deaths */ + for (k=n[1][i]; k>0; k--) { + frac = k/n[1][i]; + btemp = 1/(temp + frac*n[4][i]); /* "b" in the math */ + dtemp += btemp; + dtemp2 += btemp*btemp*frac; + dtemp3 += btemp*btemp; /* non-death deriv */ + } + + dtemp /= n[1][i]; /* average denominator */ + if (n[4][i] != n[1][i]) { /* case weights */ + dtemp2 *= n[4][i]/ n[1][i]; + dtemp3 *= n[4][i]/ n[1][i]; + } + nelson += n[4][i]*dtemp; + + haz = n[4][i]/n[3][i]; + for (k=0; k< nid; k++) { + inf1[k] = inf1[k] *(1.0 -haz) + gwt[k]*km*haz/n[3][i]; + if (gcount[k]>0) inf2[k] -= gwt[k] * dtemp3; + } + for (; person2 dtime[i]) break; + if (status[i2]==1) { + inf1[id[i2]] -= km* wt[i2]/n[3][i]; + inf2[id[i2]] += wt[i2] *(dtemp + dtemp3 - dtemp2); + } + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + } + km *= (1-haz); + + v1=0; v2=0; + for (k=0; k dtime[i]) break; + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + } + } + + kvec[i] = km; + nvec[i] = nelson; + std[0][i] = sqrt(v1); + std[1][i] = sqrt(v2); + if (influence==1 || influence ==3) + for (k=0; k= dtime[i]) break; + + gcount[id[i1]]++; + gwt[id[i1]] += wt[i1]; + } + } + + if (n[1][i] > 0 && n[4][i]>0) { /* need to update the sums */ + haz = n[4][i]/n[3][i]; + for (k=0; k< nid; k++) { + inf2[k] -= gwt[k] * haz/n[3][i]; + } + for (; person2 dtime[i]) break; + if (status[i2]==1) { + inf2[id[i2]] += wt[i2]/n[3][i]; + } + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + } + nelson += haz; + + v2=0; + for (k=0; k dtime[i]) break; + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + } + } + + kvec[i] = exp(-nelson); + nvec[i] = nelson; + std[1][i] = sqrt(v2); + std[0][i] = sqrt(v2); + + if (influence>0) + for (k=0; k= dtime[i]) break; + gcount[id[i1]]++; + gwt[id[i1]] += wt[i1]; + } + } + if (n[1][i] > 0 && n[4][i] >0) { /* need to update the sums */ + dtemp =0; /* the working denominator */ + dtemp2=0; /* sum of squares */ + dtemp3=0; + temp = n[3][i] - n[4][i]; /* sum of weights for the non-deaths */ + for (k=n[1][i]; k>0; k--) { + frac = k/n[1][i]; + btemp = 1/(temp + frac*n[4][i]); /* "b" in the math */ + dtemp += btemp; + dtemp2 += btemp*btemp*frac; + dtemp3 += btemp*btemp; /* non-death deriv */ + } + + dtemp /= n[1][i]; /* average denominator */ + if (n[4][i] != n[1][i]) { /* case weights */ + dtemp2 *= n[4][i]/ n[1][i]; + dtemp3 *= n[4][i]/ n[1][i]; + } + nelson += n[4][i]*dtemp; + + for (k=0; k< nid; k++) { + if (gcount[k]>0) inf2[k] -= gwt[k] * dtemp3; + } + for (; person2 dtime[i]) break; + if (status[i2]==1) { + inf2[id[i2]] += wt[i2] *(dtemp + dtemp3 - dtemp2); + } + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + } + + v2=0; + for (k=0; k dtime[i]) break; + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + } + } + + kvec[i] = exp(-nelson); + nvec[i] = nelson; + std[1][i] = sqrt(v2); + std[0][i] = sqrt(v2); + + if (influence>0) + for (k=0; k>= +<> +survfitCI <- function(X, Y, weights, id, cluster, robust, istate, + stype=1, ctype=1, + se.fit=TRUE, + conf.int= .95, + conf.type=c('log', 'log-log', 'plain', 'none', + 'logit', "arcsin"), + conf.lower=c('usual', 'peto', 'modified'), + influence = FALSE, start.time, p0, type){ + + if (!missing(type)) { + if (!missing(ctype) || !missing(stype)) + stop("cannot have both an old-style 'type' argument and the stype/ctype arguments that replaced it") + if (!is.character(type)) stop("type argument must be character") + # older style argument is allowed + temp <- charmatch(type, c("kaplan-meier", "fleming-harrington", "fh2")) + if (is.na(temp)) stop("invalid value for 'type'") + type <- c(1,3,4)[temp] + } + else { + if (!(ctype %in% 1:2)) stop("ctype must be 1 or 2") + if (!(stype %in% 1:2)) stop("stype must be 1 or 2") + type <- as.integer(2*stype + ctype -2) + } + if (type != 1) warning("only stype=1, ctype=1 currently implimented for multi-state data") + + conf.type <- match.arg(conf.type) + conf.lower<- match.arg(conf.lower) + if (conf.lower != "usual") + warning("conf.lower is ignored for multi-state data") + if (is.logical(conf.int)) { + # A common error is for users to use "conf.int = FALSE" + # it's illegal per documentation, but be kind + if (!conf.int) conf.type <- "none" + conf.int <- .95 + } + + + if (is.logical(influence)) { + # TRUE/FALSE is treated as all or nothing + if (!influence) influence <- 0L + else influence <- 3L + } + else if (!is.numeric(influence)) + stop("influence argument must be numeric or logical") + if (!(influence %in% 0:3)) stop("influence argument must be 0, 1, 2, or 3") + else influence <- as.integer(influence) + + if (!se.fit) { + # if the user asked for no standard error, skip any robust computation + ncluster <- 0L + influence <- 0L + } + + type <- attr(Y, "type") + # This line should be unreachable, unless they call "surfitCI" directly + if (type !='mright' && type!='mcounting') + stop(paste("multi-state computation doesn't support \"", type, + "\" survival data", sep='')) + + # If there is a start.time directive, start by removing any prior events + if (!missing(start.time)) { + if (!is.numeric(start.time) || length(start.time) !=1 + || !is.finite(start.time)) + stop("start.time must be a single numeric value") + toss <- which(Y[,ncol(Y)-1] <= start.time) + if (length(toss)) { + n <- nrow(Y) + if (length(toss)==n) stop("start.time has removed all observations") + Y <- Y[-toss,,drop=FALSE] + X <- X[-toss] + weights <- weights[-toss] + if (length(id) ==n) id <- id[-toss] + if (!missing(istate) && length(istate)==n) istate <- istate[-toss] + } + } + n <- nrow(Y) + status <- Y[,ncol(Y)] + ncurve <- length(levels(X)) + + # The user can call with cluster, id, robust or any combination. + # If only id, treat it as the cluster too + if (missing(robust) || length(robust)==0) robust <- TRUE + if (!robust) stop("multi-state survfit supports only a robust variance") + + has.cluster <- !(missing(cluster) || length(cluster)==0) + has.id <- !(missing(id) || length(id)==0) + if (has.id) id <- as.factor(id) + else { + if (ncol(Y) ==3) stop("an id statement is required for start,stop data") + id <- 1:n # older default, which could lead to invalid curves + } + if (influence && !(has.cluster || has.id)) { + cluster <- seq(along.with=X) + has.cluster <- TRUE + } + + if (has.cluster) { + if (is.factor(cluster)) { + clname <- levels(cluster) + cluster <- as.integer(cluster) + } else { + clname <- sort(unique(cluster)) + cluster <- match(cluster, clname) + } + ncluster <- length(clname) + } else { + if (has.id) { + # treat the id as both identifier and clustering + clname <- levels(id) + cluster <- as.integer(id) + ncluster <- length(clname) + } + else { + ncluster <- 0 # has neither + clname <- NULL + } + } + + if (missing(istate) || is.null(istate)) + mcheck <- survcheck2(Y, id) + else mcheck <- survcheck2(Y, id, istate) + if (any(mcheck$flag > 0)) stop("one or more flags are >0 in survcheck") + states <- mcheck$states + istate <- mcheck$istate + nstate <- length(states) + smap <- c(0, match(attr(Y, "states"), states)) + Y[,ncol(Y)] <- smap[Y[,ncol(Y)] +1] # new states may be a superset + status <- Y[,ncol(Y)] + + if (mcheck$flag["overlap"] > 0) + stop("a subject has overlapping time intervals") +# if (mcheck$flag["gap"] > 0 || mcheck$flag["jump"] > 0) +# warning("subject(s) with time gaps, results may be questionable") + + # The states of the status variable are the first columns in the output + # any extra initial states are later in the list. + # Now that we know the names, verify that p0 is correct (if present) + if (!missing(p0) && !is.null(p0)) { + if (length(p0) != nstate) stop("wrong length for p0") + if (!is.numeric(p0) || abs(1-sum(p0)) > sqrt(.Machine$double.eps)) + stop("p0 must be a numeric vector that adds to 1") + } else p0 <- NULL +@ + +The status vector will have values of 0 for censored. +<>= + curves <- vector("list", ncurve) + names(curves) <- levels(X) + + if (ncol(Y)==2) { # 1 transition per subject + # dummy entry time that is < any event time + t0 <- min(0, Y[,1]) + entry <- rep(t0-1, nrow(Y)) + for (i in levels(X)) { + indx <- which(X==i) + curves[[i]] <- docurve2(entry[indx], Y[indx,1], status[indx], + istate[indx], weights[indx], + states, + id[indx], se.fit, influence, p0) + } + } + else { + <> + <> + } + + <> +} +@ + +In the multi-state case we can calculate the current P(state) +vector $p(t)$ using the product-limit form, while the cumulative hazard +$c(t)$ is a sum. +\begin{align*} + p(t) &= p(0)\prod_{s<=t} [I + dA(s)] \\ + &= p(0) \prod_{s<=t} H(s) \\ + c(t) &= \sum_{s<=t} dA(s) +\end{align*} +Where $p$ is a row vector and $H$ is the multi-state hazard matrix. +$H(t)$ is a simple transition matrix. +Row $j$ of $H$ describes the outcome of everyone who was in state $j$ at +time $t-0$; and is the fraction of them who are in states $1, 2, \ldots$ +at time $t+0$. +Let $Y_{ij}(t)$ be the indicator function which is 1 if subject $i$ +is in state $j$ at time $t-0$, then +\begin{equation} + H_{jk}(t) = \frac{\sum_i w_i Y_{ij}(t) Y_{ik}(t+)} + {\sum_i w_i Y_{ij}(t)} \label{H} +\end{equation} +Each row of $H$ sums to 1: everyone has to go somewhere. +This formula collapses to the Kaplan-Meier in the simple case where $p(t)$ is a +vector of length 2 with state 1 = alive and state 2 = dead. + +The variance is based on per-subject influence. Since $p(t)$ is a vector +the influence can be written as a matrix with one row per subject and +one column per state. +$$ U_{ij}(t) \equiv \frac{\partial p_j(t)}{\partial w_i}. $$ +This can be calculate using a recursive formula. +First, the derivative of a matrix product $AB$ is $d(A)B + Ad(B)$ where +$d(A)$ is the elementwise derivative of $A$ and similarly for $B$. +(Write out each element of the matrix product.) +Since $p(t) = p(t-)H(t)$, the $i$th row of U satisfies +\begin{align} + U_i(t) &= \frac{\partial p(t)}{\partial w_i} \nonumber \\ + &= \frac{\partial p(t-)}{\partial w_i} H(t) + + p(t-) \frac{\partial H(t)}{\partial w_i} \nonumber \\ + &= U_i(t-) H(t) + p(t-) \frac{\partial H(t)}{\partial w_i} + \label{ci} +\end{align} +The first term of \ref{ci} collapses to ordinary matrix multiplication. +The second term does not: each at risk subject has a unique matrix derivative +$\partial H$; $n$ vectors of length $p$ can be arranged into a matrix, making +the code simple, but $n$ +$p$ by $p$ matrices are not so neat. +However, note that +\begin{enumerate} +\item $\partial H$ is zero for anyone not in the risk set, since their + weight does not appear in $H$. +\item Each subject who is at risk will be in one (and only one) of the + states at the event time, their weight only appears in that row of $H$. + Thus for each at risk subject $\partial H$ has only one non-zero row. +\end{enumerate} +Say that the subject enters the given event time in state $j$ and ends it +in state $k$. +(For most subjects at most time poinnts $k=j$: if there are 100 at risk at +time $t$ and 1 changes state, the other 99 stay put.) +Let $n_j(t)= \sum_i Y_{ij}(t)w_i$ be the weighted number of subjects +in state $j$, these are the contributers to row $j$ of $H$. +Using equation \ref{H}, the derivative of row $j$ +with respect to the subject is $(1_k - H_j)/n_j$ +where $1_k$ is a vector with 1 in position $k$. +The product of $p(t)$ with this matrix is the vector +$p_j(t)(1_k - H_j)/n_j$. +The second term thus turns out to be fairly simple to compute, but I have +not seen a way to write it in a compact matrix form + +The weighted sum of each column of $U$ will be zero (if computed correctly) +and the weighted sum of squares for each column will be the infinitesimal +jackknife estimate of variance for the elements of $p$. +The entire variance-covariance matrix for the states is $U'W^2U$ where +$W$ is a diagonal +matrix of weights, but we currently don't report that back. +Note that this is for sampling weights. +If one has real case weights, where an integer weight of 2 means 2 observations +that were collapsed in to one row of data to save space, then the +variance is $U'WU$. +Case weights were somewhat common in my youth due to small computer memory, +but I haven't seen such data in 20 years. + +The residuals for the cumulative hazard are an easier computation, since each +hazard function stands alone. In a multistate model with $k$ states there +are potentially $k(k-1)$ hazard functions arranged in a $k$ by $k$ matrix, +i.e., as used for the NA update; in the code both the hazard, the IJ scores +and the standard errors are kept as matrices with a column for each combination +that does occur. At each event time only the rows of U2 that correspond to +the risk set will be updated. + +Below is the function for a single curve. +For the status variable a value if 0 is ``no event''. +One nuisance in the function is that we need to ensure the +tapply command gives totals for all states, not just the ones present in the +data --- a call using the \code{subset} argument might not have all the states +--- which leads to using factor commands. +Another more confusing one is for multiple rows per subject data, where the +cstate and U objects have only one row per subject; +any given subject is only in one state at a time. +This leads to indices of [[atrisk]] for the set of rows in the risk set but +[[aindx]] for the subjects in the risk set, [[death]] for the rows that have +an event this time and [[dindx]] for the corresponding subjects. + +The setup for (start, stop] data is a bit more work. +We want to ensure that a given subject remains in the same group and that +they have a continuous period of observation. + +If the input data was the result of a tmerge call, say, it might have a +lot of extra 'censored' rows. For instance a subject whose state pattern +is (0, 5, 1), (5,10, 2), i.e., a transition to state 1 at day 5 and state 2 +on day 10 might input as (0,2,0), (2,5,1), (5,6,0), (6,8,0), (8,10,2) +instead. +These extra censors cause an +unnecessary row of output on days 2, 6, and 8. +Remove these before going further. + +<>= +# extra censors +indx <- order(id, Y[,2]) # in stop order +extra <- (survflag(Y[indx,], id[indx]) ==0 & (Y[indx,3] ==0)) +# If a subject had obs of (a, b)(b,c)(c,d), and c was a censoring +# time, that is an "extra" censoring/entry at c that we don't want +# to count. Deal with it by changing that subject +# to (a,b)(b,d). Won't change S(t), only the n.censored/n.enter count. +if (any(extra)) { + e2 <- indx[extra] + Y <- cbind(Y[-(1+e2),1], Y[-e2,-1]) + status <- status[-e2] + X <- X[-e2] + id <- id[-e2] + istate <- istate[-e2] + weights <- weights[-e2] + indx <- order(id, Y[,2]) +} +@ + +<>= +# Now to work +for (i in levels(X)) { + indx <- which(X==i) +# temp <- docurve1(Y[indx,1], Y[indx,2], status[indx], +# istate[indx], weights[indx], states, id[indx]) + curves[[i]] <- docurve2(Y[indx,1], Y[indx,2], status[indx], + istate[indx], + weights[indx], states, id[indx], se.fit, + influence, p0) +} +@ + +<>= +# Turn the result into a survfit type object +grabit <- function(clist, element) { + temp <-(clist[[1]][[element]]) + if (is.matrix(temp)) { + do.call("rbind", lapply(clist, function(x) x[[element]])) + } + else { + xx <- as.vector(unlist(lapply(clist, function(x) x[element]))) + if (inherits(temp, "table")) matrix(xx, byrow=T, ncol=length(temp)) + else xx + } +} + +# we want to rearrange the cumulative hazard to be in time order +# with one column for each observed transtion. +nstate <- length(states) +temp <- matrix(0, nstate, nstate) +indx1 <- match(rownames(mcheck$transitions), states) +indx2 <- match(colnames(mcheck$transitions), states, nomatch=0) #ignore censor +temp[indx1, indx2[indx2>0]] <- mcheck$transitions[,indx2>0] +ckeep <- which(temp>0) +names(ckeep) <- outer(1:nstate, 1:nstate, paste, sep='.')[ckeep] +#browser() + +if (length(curves) ==1) { + keep <- c("n", "time", "n.risk", "n.event", "n.censor", "pstate", + "p0", "cumhaz", "influence.pstate") + if (se.fit) keep <- c(keep, "std.err", "sp0") + kfit <- (curves[[1]])[match(keep, names(curves[[1]]), nomatch=0)] + names(kfit$p0) <- states + if (se.fit) kfit$logse <- FALSE + kfit$cumhaz <- t(kfit$cumhaz[ckeep,,drop=FALSE]) + colnames(kfit$cumhaz) <- names(ckeep) +} +else { + kfit <- list(n = as.vector(table(X)), #give it labels + time = grabit(curves, "time"), + n.risk= grabit(curves, "n.risk"), + n.event= grabit(curves, "n.event"), + n.censor=grabit(curves, "n.censor"), + pstate = grabit(curves, "pstate"), + p0 = grabit(curves, "p0"), + strata= unlist(lapply(curves, function(x) + if (is.null(x$time)) 0L else length(x$time)))) + kfit$p0 <- matrix(kfit$p0, ncol=nstate, byrow=TRUE, + dimnames=list(names(curves), states)) + if (se.fit) { + kfit$std.err <- grabit(curves, "std.err") + kfit$sp0<- matrix(grabit(curves, "sp0"), + ncol=nstate, byrow=TRUE) + kfit$logse <- FALSE + } + + # rearrange the cumulative hazard to be in time order, with columns + # for each transition + kfit$cumhaz <- do.call(rbind, lapply(curves, function(x) + t(x$cumhaz[ckeep,,drop=FALSE]))) + colnames(kfit$cumhaz) <- names(ckeep) + + if (influence) kfit$influence.pstate <- + lapply(curves, function(x) x$influence.pstate) +} + +if (!missing(start.time)) kfit$start.time <- start.time +kfit$transitions <- mcheck$transitions + +@ + +<>= +# +# Last bit: add in the confidence bands: +# +if (se.fit && conf.type != "none") { + ci <- survfit_confint(kfit$pstate, kfit$std.err, logse=FALSE, + conf.type, conf.int) + kfit <- c(kfit, ci, conf.type=conf.type, conf.int=conf.int) +} +kfit$states <- states +kfit$type <- attr(Y, "type") +kfit +@ + +The updated docurve function is here. +One issue that was not recognized originally is delayed entry. If most +of the subjects start at time 0, say, but one of them starts at day 100 +then that last subject is not a part of $p_0$. +We will define $p_0$ as the distribution of states just before the first +event. +The code above has already ensured that each subject has a unique +value for istate, so we don't have to search for the right one. +The initial vector and leverage are +\begin{align*} + p_0 &= (\sum I{s_i=1}w_i, \sum I{s_i=2}w_i, \ldots)/ \sum w_i \\ + \frac{\partial p_0}{\partial w_k} &= + [(I{s_k=1}, I{s_k=2}, ...)- p_0]/\sum w_i +\end{align*} + +The input data set is not necessarily sorted by time or subject. +The data has been checked so that subjects don't have gaps, however. +The cstate variable for each subject contains their first istate +value. Only those intervals that overlap the first event time contribute +to $p_0$. +Now: what to report as the ``time'' for the initial row. The values for +it come from (first event time -0), i.e. all who are at risk at the +smallest \code{etime} with status $>0$. +But for normal plotting the smallest start time seems to be a good +default. +In the usual (start, stop] data +a large chunk of the subjects have a common start time. +However, if the first event doesn't happen for a while +and subjects are dribbling in, then the best point to start a plot +is open to debate. Que sera sera. +<>= +docurve2 <- function(entry, etime, status, istate, wt, states, id, + se.fit, influence=FALSE, p0) { + timeset <- sort(unique(etime)) + nstate <- length(states) + uid <- sort(unique(id)) + index <- match(id, uid) + # Either/both of id and cstate might be factors. Data may not be in + # order. Get the initial state for each subject + temp1 <- order(id, entry) + temp2 <- match(uid, id[temp1]) + cstate <- (as.numeric(istate)[temp1])[temp2] # initial state for each + + # The influence matrix can be huge, make sure we have enough memory + if (influence) { + needed <- max(nstate * length(uid), 1 + length(timeset)) + if (needed > .Machine$integer.max) + stop("number of rows for the influence matrix is > the maximum integer") + } + storage.mode(wt) <- "double" # just in case someone had integer weights + + # Compute p0 (unless given by the user) + if (is.null(p0)) { + if (all(status==0)) t0 <- max(etime) #failsafe + else t0 <- min(etime[status!=0]) # first transition event + at.zero <- (entry < t0 & etime >= t0) + wtsum <- sum(wt[at.zero]) # weights for a subject may change + p0 <- tapply(wt[at.zero], istate[at.zero], sum) / wtsum + p0 <- ifelse(is.na(p0), 0, p0) #for a state not in at.zero, tapply =NA + } + # initial leverage matrix + nid <- length(uid) + i0 <- matrix(0., nid, nstate) + if (all(p0 <1)) { #actually have to compute it + who <- index[at.zero] # this will have no duplicates + for (j in 1:nstate) + i0[who,j] <- (ifelse(istate[at.zero]==states[j], 1, 0) - p0[j])/wtsum + } + + storage.mode(cstate) <- "integer" + storage.mode(status) <- "integer" + # C code has 0 based subscripts + if (influence) se.fit <- TRUE # se.fit is free in this case + + fit <- .Call(Csurvfitci, c(entry, etime), + order(entry) - 1L, + order(etime) - 1L, + length(timeset), + status, + as.integer(cstate) - 1L, + wt, + index -1L, + p0, i0, + as.integer(se.fit) + 2L*as.integer(influence)) + + if (se.fit) + out <- list(n=length(etime), time= timeset, p0 = p0, + sp0= sqrt(colSums(i0^2)), + pstate = fit$p, std.err=fit$std, + n.risk = fit$nrisk, + n.event= fit$nevent, + n.censor=fit$ncensor, + cumhaz = fit$cumhaz) + else out <- list(n=length(etime), time= timeset, p0=p0, + pstate = fit$p, + n.risk = fit$nrisk, + n.event = fit$nevent, + n.censor= fit$ncensor, + cumhaz= fit$cumhaz) + if (influence) { + temp <- array(fit$influence, + dim=c(length(uid), nstate, 1+ length(timeset)), + dimnames=list(uid, NULL, NULL)) + out$influence.pstate <- aperm(temp, c(1,3,2)) + } + out +} +@ +\subsubsection{C-code} +(This is set up as a separate file in the source code directory since +it is easier to make emacs stay in C-mode if the file has a .nw +extension.) + +<>= +#include "survS.h" +#include "survproto.h" +#include + +SEXP survfitci(SEXP ftime2, SEXP sort12, SEXP sort22, SEXP ntime2, + SEXP status2, SEXP cstate2, SEXP wt2, SEXP id2, + SEXP p2, SEXP i02, SEXP sefit2) { + <> + <> + <> +} +@ +Arguments to the routine are the following. +For an R object ``zed'' I use the convention of [[zed2]] to refer to the +object and [[zed]] to the contents of the object. +\begin{description} + \item[ftime] A two column matrix containing the entry and exit times + for each subject. + \item[sort1] Order vector for the entry times. The first element of sort1 + points to the first entry time, etc. + \item[sort2] Order vector for the event times. + \item[ntime] Number of unique event time values. This fixes the size of + the output arrays. + \item[status] Status for each observation. 0= censored + \item[cstate] The initial state for each subject, which will be + updated during computation to always be the current state. + \item[wt] Case weight for each observation. + \item[id] The subject id for each observation. + \item[p] The initial distribution of states. This will be updated during + computation to be the current distribution. + \item[i0] The initial influence matrix, number of subjects by number of states + \item[sefit] If 1 then do the se compuatation, if 2 also return the full + influence matrix upon which it is based, if 0 the se is not needed. +\end{description} + +Note that code is called with id and not cluster: there is a basic premise that +each id is a single subject and thus has a unique "current state" at any +given time point. The history of this is that before the survcheck routine, +we did not have a good way for a user to normalize the 'current state' variable +for a subject, so this routine takes care of that tracking process. +When multi-state Cox models were added we became more formal about this, and +users can now have data sets with quite odd patterns of transitions and current +state, ones that survcheck calls a teleport. At some point this routine should +be updated as well. Cumulative hazard estimates make at least some sense +when a subject has a hole, though P(state |t) curves do not. + +Declare all of the variables. +<>= +int i, j, k, kk; /* generic loop indices */ +int ck, itime, eptr; /*specific indices */ +double ctime; /*current time of interest, in the main loop */ +int oldstate, newstate; /*when changing state */ + +double temp, *temp2; /* scratch double, and vector of length nstate */ +double *dptr; /* reused in multiple contexts */ +double *p; /* current prevalence vector */ +double **hmat; /* hazard matrix at this time point */ +double **umat=0; /* per subject leverage at this time point */ +int *atrisk; /* 1 if the subject is currently at risk */ +int *ns; /* number curently in each state */ +int *nev; /* number of events at this time, by state */ +double *ws; /* weighted count of number state */ +double *wtp; /* case weights indexed by subject */ +double wevent; /* weighted number of events at current time */ +int nstate; /* number of states */ +int n, nperson; /*number of obs, subjects*/ +double **chaz; /* cumulative hazard matrix */ + +/* pointers to the R variables */ +int *sort1, *sort2; /*sort index for entry time, event time */ +double *entry,* etime; /*entry time, event time */ +int ntime; /* number of unique event time values */ +int *status; /*0=censored, 1,2,... new states */ +int *cstate; /* current state for each subject */ +int *dstate; /* the next state, =cstate if not an event time */ +double *wt; /* weight for each observation */ +double *i0; /* initial influence */ +int *id; /* for each obs, which subject is it */ +int sefit; + +/* returned objects */ +SEXP rlist; /* the returned list and variable names of same */ +const char *rnames[]= {"nrisk","nevent","ncensor", "p", + "cumhaz", "std", "influence.pstate", ""}; +SEXP setemp; +double **pmat, **vmat=0, *cumhaz, *usave=0; /* =0 to silence -Wall warning */ +int *ncensor, **nrisk, **nevent; +@ + +Now set up pointers for all of the R objects sent to us. +The two that will be updated need to be replaced by duplicates. +<>= +ntime= asInteger(ntime2); +nperson = LENGTH(cstate2); /* number of unique subjects */ +n = LENGTH(sort12); /* number of observations in the data */ +PROTECT(cstate2 = duplicate(cstate2)); +cstate = INTEGER(cstate2); +entry= REAL(ftime2); +etime= entry + n; +sort1= INTEGER(sort12); +sort2= INTEGER(sort22); +status= INTEGER(status2); +wt = REAL(wt2); +id = INTEGER(id2); +PROTECT(p2 = duplicate(p2)); /*copy of initial prevalence */ +p = REAL(p2); +nstate = LENGTH(p2); /* number of states */ +i0 = REAL(i02); +sefit = asInteger(sefit2); + +/* allocate space for the output objects +** Ones that are put into a list do not need to be protected +*/ +PROTECT(rlist=mkNamed(VECSXP, rnames)); +setemp = SET_VECTOR_ELT(rlist, 0, allocMatrix(INTSXP, ntime, nstate)); +nrisk = imatrix(INTEGER(setemp), ntime, nstate); /* time by state */ +setemp = SET_VECTOR_ELT(rlist, 1, allocMatrix(INTSXP, ntime, nstate)); +nevent = imatrix(INTEGER(setemp), ntime, nstate); /* time by state */ +setemp = SET_VECTOR_ELT(rlist, 2, allocVector(INTSXP, ntime)); +ncensor = INTEGER(setemp); /* total at each time */ +setemp = SET_VECTOR_ELT(rlist, 3, allocMatrix(REALSXP, ntime, nstate)); +pmat = dmatrix(REAL(setemp), ntime, nstate); +setemp = SET_VECTOR_ELT(rlist, 4, allocMatrix(REALSXP, nstate*nstate, ntime)); +cumhaz = REAL(setemp); + +if (sefit >0) { + setemp = SET_VECTOR_ELT(rlist, 5, allocMatrix(REALSXP, ntime, nstate)); + vmat= dmatrix(REAL(setemp), ntime, nstate); +} +if (sefit >1) { + /* the max space is larger for a matrix than a vector + ** This is pure sneakiness: if I allocate a vector then n*nstate*(ntime+1) + ** may overflow, as it is an integer argument. Using the rows and cols of + ** a matrix neither overflows. But once allocated, I can treat setemp + ** like a vector since usave is a pointer to double, which is bigger than + ** integer and won't overflow. */ + setemp = SET_VECTOR_ELT(rlist, 6, allocMatrix(REALSXP, n*nstate, ntime+1)); + usave = REAL(setemp); +} + +/* allocate space for scratch vectors */ +ws = (double *) R_alloc(2*nstate, sizeof(double)); /*weighted number in state */ +temp2 = ws + nstate; +ns = (int *) R_alloc(2*nstate, sizeof(int)); +nev = ns + nstate; +atrisk = (int *) R_alloc(2*nperson, sizeof(int)); +dstate = atrisk + nperson; +wtp = (double *) R_alloc(nperson, sizeof(double)); +hmat = (double**) dmatrix((double *)R_alloc(nstate*nstate, sizeof(double)), + nstate, nstate); +chaz = (double**) dmatrix((double *)R_alloc(nstate*nstate, sizeof(double)), + nstate, nstate); +if (sefit >0) + umat = (double**) dmatrix((double *)R_alloc(nperson*nstate, sizeof(double)), + nstate, nperson); + +/* R_alloc does not zero allocated memory */ +for (i=0; i>= +if (sefit ==1) { + dptr = i0; + for (j=0; j1) { + /* copy influence, and save it */ + dptr = i0; + for (j=0; j>= +itime =0; /*current time index, for output arrays */ +eptr = 0; /*index to sort1, the entry times */ +for (i=0; i> + <> + + /* Take the current events and censors out of the risk set */ + for (; i0) cstate[id[j]] = status[j]-1; /*new state */ + atrisk[id[j]] =0; + } + else break; + } + itime++; +} +@ + +The key variables for the computation are the matrix $H$ and the +current prevalence vector $P$. +$H$ is created anew at each unique time point. +Row $j$ of $H$ concerns everyone in state $j$ just before the time point, +and contains the transitions at that time point. +So the $jk$ element is the (weighted) fraction who change from state $j$ +to state $k$, and the $jj$ element the fraction who stay put. +Each row of $H$ by definition sums to 1. +If no one is in the state then the $jj$ element is set to 1. +A second version which we call H2 has 1 subtracted from each diagonal giving +row sums are 0, we go back and +forth depending on which is needed at the moment. +If there are no events at this time point $P$ and $U$ do not update. +<>= +for (j=0; j0) { + newstate = status[k] -1; /* 0 based subscripts */ + oldstate = cstate[id[k]]; + if (oldstate != newstate) { + /* A "move" to the same state does not count */ + dstate[id[k]] = newstate; + nev[newstate]++; + wevent += wt[k]; + hmat[oldstate][newstate] += wt[k]; + } + } + else ncensor[itime]++; + } + else break; + } + +if (wevent > 0) { /* there was at least one move with weight > 0 */ + /* finish computing H */ + for (j=0; j0) { + temp =0; + for (k=0; k0) { + <> + } + <> +} +@ + +The most complicated part of the code is the update of the +per subject influence matrix $U$. +The influence for a subject is the derivative of the current +estimates wrt the case weight of that subject. Since $p$ is a +vector the influence $U$ is easily represented as a matrix with one row +per subject and one column per state. +Refer to equation \eqref{ci} for the derivation. + +Let $m$ and $n$ be the old and new states for subject $i$, and +$n_m$ the sum of weights for all subjects at risk in state $m$. +Then +\begin{equation*} + U_{ij}(t) = \sum_k \left[ U_{ik}(t-)H_{kj}\right] + p_m(t-)(I_{n=j} - H_{mj})/ n_m +\end{equation*} +\begin{enumerate} + \item The first term above is simple matrix multiplication. + \item The second adds a vector with mean zero. +\end{enumerate} +If standard errors are not needed we can skip this calculation. + +<>= +/* Update U, part 1 U = U %*% H -- matrix multiplication */ +for (j=0; j>= +/* Finally, update chaz and p. */ +for (j=0; j>= +/* store into the matrices that will be passed back */ +for (j=0; j0) { + temp =0; + for (k=0; k 1) + for (k=0; k>= +/* return a list */ +UNPROTECT(3); +return(rlist); +@ +\subsubsection{Printing and plotting} +The \code{survfitms} class differs from a \code{survfit}, but many of the +same methods nearly apply. +<>= +# Methods for survfitms objects +<> +<> +@ + +The subscript method is a near copy of that for survfit +objects, but with a slightly different set of components. +The object could have strata and will almost always have multiple +columns. Following convention, if there is only one subscript we treat +the object as though it were a vector. +The \code{nmatch} function allow the user to use either names +or integer indices. + +<>= +"[.survfitms" <- function(x, ..., drop=FALSE) { + nmatch <- function(i, target) { + # This function lets R worry about character, negative, + # or logical subscripts + # It always returns a set of positive integer indices + temp <- seq(along.with=target) + names(temp) <- target + temp[i] + } + if (!is.null(x$influence.pstate) || !is.null(x$influence.cumhaz)) + x <- survfit0(x, x$start.time) # make influence and pstate align + ndots <- ...length() # the simplest, but not avail in R 3.4 + # ndots <- length(list(...))# fails if any are missing, e.g. fit[,2] + # ndots <- if (missing(drop)) nargs()-1 else nargs()-2 # a workaround + + dd <- dim(x) + dmatch <- match(c("strata", "data", "states"), names(dd), nomatch=0) + if (is.null(x$states)) stop("survfitms object has no states component") + if (dmatch[3]==0) stop ("survfitms object has no states dimension") + dtype <- match(names(dd), c("strata", "data", "states")) + + if (ndots==0) return(x) # no subscript given + if (ndots >0 && !missing(..1)) i <- ..1 else i <- NULL + if (ndots> 1 && !missing(..2)) j <- ..2 else j <- NULL + if (ndots> 2 && !missing(..3)) k <- ..3 else k <- NULL + if (is.null(i) & is.null(j) & is.null(k)) return(x) # only one curve + + # Make a new object + newx <- vector("list", length(x)) + names(newx) <- names(x) + for (kk in c("logse", "version", "conf.int", "conf.type", "type", + "start.time", "call")) + if (!is.null(x[[kk]])) newx[[kk]] <- x[[kk]] + newx$transitions <- NULL # may no longer be accurate, and not needed + class(newx) <- class(x) + + # Like a matrix, let the user use a single subscript if they desire + if (ndots==1 && length(dd) > 1) { + # the 'treat it as a vector' case + if (!is.numeric(i)) + stop("single subscript must be numeric") + if (any(dmatch==2)) stop("single index subscripts are not supported for a survfit objet with both data and state dimesions") + + # when subscripting a mix, these don't endure + newx$cumhaz <- newx$std.chaz <- newx$influence.chaz <- NULL + newx$transitions <- newx$states <- newx$newdata <- NULL + + # what strata and columns do I need? + itemp <- matrix(1:prod(dd), nrow=dd[1]) + jj <- (col(itemp))[i] # columns + ii <- (row(itemp))[i] # this is now the strata id + + if (dtype[1]!=1 || dd[1]==1) # no strata or only 1 + irow <- rep(seq(along.with= x$time), length(ii)) + else { + itemp2 <- split(1:sum(x$strata), rep(1:length(x$strata), x$strata)) + irow <- unlist(itemp2[ii]) # rows of the pstate object + } + inum <- x$strata[ii] # number of rows in each ii + indx <- cbind(irow, rep(jj,ii)) # matrix index for pstate + + # The n.risk, n.event, .. matrices dont have a newdata dimension. + if (all(dtype!=2) || dd["data"]==1) kk <- jj + else { # both data and states + itemp <- matrix(1:(dd["data"]*dd["states"]), nrow=dd[2]) + kk <- (col(itemp))[jj] # the state of each selected one + indx2 <- cbind(irow, rep(k, irow)) + } + newx$n <- x$n[ii] + newx$time <- x$time[irow] + for (z in c("n.risk", "n.event", "n.censor", "n.enter")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[indx2] + for (z in c("pstate", "std.err", "upper", "lower")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[indx] + + newx$strata <- x$strata[ii] + names(newx$strata) <- seq(along.with=ii) + + return(newx) + } + + # not a single subscript, i.e., the usual case + # Backwards compatability: If x$strata=NULL, it is a semantic argument + # of whether there is still "1 stratum". I have used the second + # form at times, e.g. x[1,,2] for an object with only data and state + # dimensions. + # If there are no strata, 1 too many subscripts, and the first is 1, + # assume this case and toss the first + if (ndots == (length(dd)+1)) { + if (is.null(x$strata) && (is.null(i) || (length(i)==1 && i==1))) { + i <-j; j <-k; k <- NULL + } else stop("incorrect number of dimensions") + } else if (ndots != length(dd)) stop("incorrect number of dimensions") + + # create irow, which selects for the time dimension of x + if (dtype[1]!=1 || is.null(i)) { + irow <- seq(along.with= x$time) + } + else { + i <- nmatch(i, names(x$strata)) + itemp <- split(1:sum(x$strata), rep(1:length(x$strata), x$strata)) + irow <- unlist(itemp[i]) # rows of the pstate object + } + + # Select the n, strata, and time components of the output. Make j,k + # point to the subscripts other than strata (makes later code a touch + # simpler.) + newx$time <- x$time[irow] + if (dtype[1] !=1) { # there are no strata + newx$n <- x$n + k <- j; j <- i; + dd <- c(0, dd) + dtype <- c(1, dtype) + } + else { # there are strata + if (is.null(i)) i <-seq(along.with=x$strata) + if ((drop && length(i)>1) || !drop) newx$strata <- x$strata[i] + newx$n <- x$n[i] + } + + # The n.censor and n.enter values do not repeat with multiple X values + for (z in c("n.censor", "n.enter")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[irow, drop=FALSE] + + # two cases: with newx or without newx (pstate is always present) + nstate <- length(x$states) + if (dtype[2] !=2) { # j indexes the states, there is no data dimension + if (is.null(j)) j <- seq.int(nstate) + else j <- nmatch(j, x$states) + + # keep these as start points for plotting, even though they won't make + # true sense if states are subset, since rows won't sum to 1 + if (!is.null(x$p0)) { + if (is.matrix(x$p0)) newx$p0 <- x$p0[i,j, drop=FALSE] + else newx$p0 <- x$p0[j] + } + if (!is.null(x$sp0)) { + if (is.matrix(x$sp0)) newx$sp0 <- x$sp0[i,j, drop=FALSE] + else newx$sp0 <- x$sp0[j] + } + + # in the rare case of a single strata with 1 obs, don't drop dims + if (length(irow)==1 && length(j) > 1) drop2 <- FALSE + else drop2 <- drop + + for (z in c("n.risk", "n.event")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[irow,j, drop=drop2] + for (z in c("pstate", "std.err", "upper", "lower")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[irow,j, drop=drop2] + if (!is.null(x$influence.pstate)) { + if (is.list(x$influence.pstate)) { + if (length(i)==1) newx$influence.pstate <- x$influence.pstate[[i]] + else newx$influence.pstate <- lapply(x$influence.pstate[i], + function(x) x[,,j, drop= drop]) + } + else newx$influence.pstate <- x$influence.pstate[,,j, drop=drop] + } + + if (length(j)== nstate && all(j == seq.int(nstate))) { + # user kept all the states, in original order + newx$states <- x$states + for (z in c("cumhaz", "std.chaz")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[irow,, drop=drop2] + if (!is.null(x$influence.chaz)) { + if (is.list(x$influence.chaz)) { + newx$influence.chaz <- x$influence.chaz[i] + if (length(i)==1 && drop) + newx$influence.chaz <- x$influence.chaz[[i]] + } + else newx$influence.chaz <- x$influence.chaz + } + } + else { + # Some states were dropped, leaving no consistent way to + # subscript cumhaz, or not one I have yet seen clearly + # So remove it from the object + newx$cumhaz <- newx$std.chaz <- newx$influence.chaz <- NULL + if (length(j)==1 & drop) { + newx$states <- NULL + temp <- class(newx) + class(newx) <- temp[temp!="survfitms"] + } + else newx$states <- x$states[j] + } + } + else { # j points at newdata, k points at states + if (is.null(j)) j <- seq.int(dd[2]) + else j <- nmatch(j, seq.int(dd[2])) + + if (is.null(k)) k <- seq.int(nstate) + else k <- nmatch(k, x$states) + + # keep these as start points for plotting, even though they won't make + # true sense is states are subset, since rows won't sum to 1 + # (all data= sets have the same p0) + if (!is.null(x$p0)) { + if (is.matrix(x$p0)) newx$p0 <- x$p0[i,k] else newx$p0 <- x$p0[k] + } + if (!is.null(x$sp0)) { + if (is.matrix(x$sp0)) newx$sp0 <- x$p0[i,k] else newx$sp0 <- x$sp0[k] + } + + if (length(irow)==1) { + if (length(j) > 1) drop2 <- FALSE else drop2<- drop + if (length(k) > 1) drop3 <- FALSE else drop3 <- drop + } + else drop2 <- drop3 <- drop + + for (z in c("n.risk", "n.event")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[irow, k, drop=drop3] + for (z in c("pstate", "std.err", "upper", "lower")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[irow,j,k, drop=drop2] + + if (!is.null(x$influence.pstate)) { + if (is.list(x$influence.pstate)) { + if (length(i)==1) + newx$influence.pstate <- (x$influence.pstate[[i]])[,,j,k, drop=drop] + else newx$influence.pstate <- lapply(x$influence.pstate[i], + function(x) x[,,j,k, drop= drop]) + } + else newx$influence.pstate <- x$influence.pstate[,,j,k, drop=drop] + } + + if (length(k)== nstate && all(k == seq.int(nstate))) { + # user kept all the states + newx$states <- x$states + for (z in c("cumhaz", "std.chaz")) + if (!is.null(x[[z]])) + newx[[z]] <- (x[[z]])[irow,j,, drop=drop2] + if (!is.null(x$influence.chaz)) { + if (is.list(x$influence.chaz)) { + newx$influence.chaz <- (x$influence.chaz[i])[,j,] + if (length(i)==1 && drop) + newx$influence.chaz <- x$influence.chaz[[i]] + } + else newx$influence.chaz <- x$influence.chaz[,j,] + } + } + else { + # never drop the states component. Otherwise downstream code + # will start looking for x$surv instead of x$pstate + newx$states <- x$states[k] + newx$cumhaz <- newx$std.chaz <- newx$influence.chaz <- NULL + x$transitions <- NULL + } + + if (length(j)==1 && drop) newx$newdata <- NULL + else newx$newdata <- x$newdata[j,,drop=FALSE] #newdata is a data frame + + } + newx +} +@ + +The summary.survfit and summary.survfitms functions share a significant +amount of code. +One part of the code that once was subtle is dealing with +intermediate time points; the findInterval function in base R has +made that much easier. +Since the result does not involve interpolation, one should be able +to create a special index vector i and return \code{time[i]}, +\code{surv[i,]}, etc, to subscript all the curves in a survfit object +at once. But that approach, though efficient in theory, runs into +two problems. First is the extrapolated value for the curves at +time points before the first event, which is allowed to be different +for different curves in survfitms objects. +The second is that there is interpolation of a sort: the n.event and n.censor +components are summed over intervals when the selected time points are +sparse, and that process is very tricky for multiple curves at once. +At one point the code took that approach, but it became too complex to maintain. +The current approach is slower but more transparent: do the individual +curves one by one, then paste together the results. + +<>= +summary.survfit <- function(object, times, censored=FALSE, + scale=1, extend=FALSE, + rmean=getOption('survfit.rmean'), + ...) { + fit <- object #save typing + if (!inherits(fit, 'survfit')) + stop("summary.survfit can only be used for survfit objects") + if (is.null(fit$logse)) fit$logse <- TRUE #older style + + # The print.rmean option is depreciated, it is still listened + # to in print.survfit, but ignored here + if (is.null(rmean)) rmean <- "common" + if (is.numeric(rmean)) { + if (is.null(fit$start.time)) { + if (rmean < min(fit$time)) + stop("Truncation point for the mean time in state is < smallest survival") + } + else if (rmean < fit$start.time) + stop("Truncation point for the mean time in state is < smallest survival") + } + else { + rmean <- match.arg(rmean, c('none', 'common', 'individual')) + if (length(rmean)==0) stop("Invalid value for rmean option") + } + + # adding time 0 makes the mean and median easier + fit0 <- survfit0(fit, fit$start.time) #add time 0 + temp <- survmean(fit0, scale=scale, rmean) + table <- temp$matrix #for inclusion in the output list + rmean.endtime <- temp$end.time + + if (!is.null(fit$strata)) { + nstrat <- length(fit$strata) + } + delta <- function(x, indx) { # sums between chosen times + if (is.logical(indx)) indx <- which(indx) + if (!is.null(x) && length(indx) >0) { + fx <- function(x, indx) diff(c(0, c(0, cumsum(x))[indx+1])) + if (is.matrix(x)) { + temp <- apply(x, 2, fx, indx=indx) + # don't return a vector when only 1 time point is given + if (is.matrix(temp)) temp else matrix(temp, nrow=1) + } + else fx(x, indx) + } + else NULL + } + + if (missing(times)) { + <> + } + else { + fit <- fit0 + <> + times <- sort(times) #in case the user forgot + if (is.null(fit$strata)) fit <- findrow(fit, times, extend) + else { + ltemp <- vector("list", nstrat) + for (i in 1:nstrat) + ltemp[[i]] <- findrow(fit[i], times, extend) + fit <- unpacksurv(fit, ltemp) + } + } + + # finish off the output structure + fit$table <- table + if (length(rmean.endtime)>0 && !any(is.na(rmean.endtime[1]))) + fit$rmean.endtime <- rmean.endtime + + # A survfit object may contain std(log S) or std(S), summary always std(S) + if (!is.null(fit$std.err) && fit$logse) fit$std.err <- fit$std.err * fit$surv + + # Expand the strata + if (!is.null(fit$strata)) + fit$strata <- factor(rep(1:nstrat, fit$strata), 1:nstrat, + labels= names(fit$strata)) + if (scale != 1) { + # fix scale in the output + fit$time <- fit$time/scale + } + + class(fit) <- "summary.survfit" + fit +} +@ + +The simple case of no times argument. +<>= +if (!censored) { + index <- (rowSums(as.matrix(fit$n.event)) >0) + for (i in c("time","n.risk", "n.event", "surv", "pstate", "std.err", + "upper", "lower", "cumhaz", "std.chaz")) { + if (!is.null(fit[[i]])) { # not all components in all objects + temp <- fit[[i]] + if (is.matrix(temp)) temp <- temp[index,,drop=FALSE] + else if (!is.array(temp)) temp <- temp[index] #simple vector + else temp <- temp[index,,, drop=FALSE] # 3 way + fit[[i]] <- temp + } + } + + # The n.enter and n.censor values are accumualated + # both of these are simple vectors + if (is.null(fit$strata)) { + for (i in c("n.enter", "n.censor")) + if (!is.null(fit[[i]])) + fit[[i]] <- delta(fit[[i]], index) + } + else { + sindx <- rep(1:nstrat, fit$strata) + for (i in c("n.enter", "n.censor")) { + if (!is.null(fit[[i]])) + fit[[i]] <- unlist(sapply(1:nstrat, function(j) + delta(fit[[i]][sindx==j], index[sindx==j]))) + } + # the "factor" is needed for the case that a strata has no + # events at all, and hence 0 lines of output + fit$strata[] <- as.vector(table(factor(sindx[index], 1:nstrat))) + } +} +#if missing(times) and censored=TRUE, the fit object is ok as it is +@ + +To deal with selected times we first define a subscripting function. +For indices of 0, which are requested times that are before the first event, +it fills in the initial value. + +<>= +ssub<- function(x, indx) { #select an object and index + if (!is.null(x) && length(indx)>0) { + if (is.matrix(x)) x[pmax(1,indx),,drop=FALSE] + else if (is.array(x)) x[pmax(1,indx),,,drop=FALSE] + else x[pmax(1, indx)] + } + else NULL +} +@ + +This function does the real work, for any single curve. +The default value for init is correct for survival curves. + +Say that the data has values at time 5, 10, 15, 20 \ldots, and a user asks +for \code{times=c(7, 15, 20, 30)}. +In the input object \code{n.risk} refers to the number at risk just before +time 5, 10, \ldots; it is a left-continuous function. +The survival is a right-continuous function. So at time 7 we want to +take the survival from time 5 and number at risk from time 10; +\code{indx1} will be the right-continuous index and \code{indx2} the +left continuous one. The value of n.risk at time 30 has to be computed. +For counts of events, censoring, and entry we want to know the total +number that happened during the intervals of 0-7, 7-15, 15-20 and 20-30. +Technically censorings at time 15 happen just after time 15 so would +go into the third line of the report. +However, this would lead to terrible confusion for the user since +using \code{times=c(5, 10, 15, 20)} would lead to different counts than +a call that did not contain the times argument, so all 3 of the intermediates +are computed using indx1. +A report at time 30 is made only if extend=TRUE, in which case we need +to compute a tail value for n.risk. +<>= +findrow <- function(fit, times, extend) { + if (FALSE) { + if (is.null(fit$start.time)) mintime <- min(fit$time, 0) + else mintime <- fit$start.time + ptimes <- times[times >= mintime] + } else ptimes <- times[is.finite(times)] + + if (!extend) { + maxtime <- max(fit$time) + ptimes <- ptimes[ptimes <= maxtime] + } + ntime <- length(fit$time) + + index1 <- findInterval(ptimes, fit$time) + index2 <- 1 + findInterval(ptimes, fit$time, left.open=TRUE) + if (length(index1) ==0) + stop("no points selected for one or more curves, consider using the extend argument") + # The pmax() above encodes the assumption that n.risk for any + # times before the first observation = n.risk at the first obs + fit$time <- ptimes + + for (i in c("surv", "pstate", "upper", "lower", "std.err", "cumhaz", + "std.chaz")) { + if (!is.null(fit[[i]])) fit[[i]] <- ssub(fit[[i]], index1) + } + + if (is.matrix(fit$n.risk)) { + # Every observation in the data has to end with a censor or event. + # So by definition the number at risk after the last observed time + # value must be 0. + fit$n.risk <- rbind(fit$n.risk,0)[index2,,drop=FALSE] + } + else fit$n.risk <- c(fit$n.risk, 0)[index2] + + for (i in c("n.event", "n.censor", "n.enter")) + fit[[i]] <- delta(fit[[i]], index1) + fit +} + +# For a single component, turn it from a list into a single vector, matrix +# or array +unlistsurv <- function(x, name) { + temp <- lapply(x, function(x) x[[name]]) + if (is.vector(temp[[1]])) unlist(temp) + else if (is.matrix(temp[[1]])) do.call("rbind", temp) + else { + # the cumulative hazard is the only component that is an array + # it's third dimension is n + xx <- unlist(temp) + dd <- dim(temp[[1]]) + dd[3] <- length(xx)/prod(dd[1:2]) + array(xx, dim=dd) + } +} + +# unlist all the components built by a set of calls to findrow +# and remake the strata +unpacksurv <- function(fit, ltemp) { + keep <- c("time", "surv", "pstate", "upper", "lower", "std.err", + "cumhaz", "n.risk", "n.event", "n.censor", "n.enter", + "std.chaz") + for (i in keep) + if (!is.null(fit[[i]])) fit[[i]] <- unlistsurv(ltemp, i) + fit$strata[] <- sapply(ltemp, function(x) length(x$time)) + fit +} +@ + +Repeat the code for survfitms objects. The only real difference is +the preservation of \code{pstate} and \code{cumhaz} instead of \code{surv}, +and the use of survmean2. + +<>= +summary.survfitms <- function(object, times, censored=FALSE, + scale=1, extend=FALSE, + rmean= getOption("survfit.rmean"), + ...) { + + fit <- object # save typing + if (!inherits(fit, 'survfitms')) + stop("summary.survfitms can only be used for survfitms objects") + if (is.null(fit$logse)) fit$logse <- FALSE # older style + + # The print.rmean option is depreciated, it is still listened + # to in print.survfit, but ignored here + if (is.null(rmean)) rmean <- "common" + if (is.numeric(rmean)) { + if (is.null(fit$start.time)) { + if (rmean < min(fit$time)) + stop("Truncation point for the mean is < smallest survival") + } + else if (rmean < fit$start.time) + stop("Truncation point for the mean is < smallest survival") + } + else { + rmean <- match.arg(rmean, c('none', 'common', 'individual')) + if (length(rmean)==0) stop("Invalid value for rmean option") + } + + fit0 <- survfit0(fit, fit$start.time) # add time 0 + temp <- survmean2(fit0, scale=scale, rmean) + table <- temp$matrix #for inclusion in the output list + rmean.endtime <- temp$end.time + + if (!missing(times)) { + if (!is.numeric(times)) stop ("times must be numeric") + times <- sort(times) + } + + if (!is.null(fit$strata)) { + nstrat <- length(fit$strata) + sindx <- rep(1:nstrat, fit$strata) + } + delta <- function(x, indx) { # sums between chosen times + if (is.logical(indx)) indx <- which(indx) + if (!is.null(x) && length(indx) >0) { + fx <- function(x, indx) diff(c(0, c(0, cumsum(x))[indx+1])) + if (is.matrix(x)) { + temp <- apply(x, 2, fx, indx=indx) + if (is.matrix(temp)) temp else matrix(temp, nrow=1) + } + else fx(x, indx) + } + else NULL + } + + if (missing(times)) { + <> + } + else { + fit <-fit0 # easier to work with + <> + times <- sort(times) + if (is.null(fit$strata)) fit <- findrow(fit, times, extend) + else { + ltemp <- vector("list", nstrat) + for (i in 1:nstrat) + ltemp[[i]] <- findrow(fit[i,], times, extend) + fit <- unpacksurv(fit, ltemp) + } + } + + # finish off the output structure + fit$table <- table + if (length(rmean.endtime)>0 && !any(is.na(rmean.endtime))) + fit$rmean.endtime <- rmean.endtime + + if (!is.null(fit$strata)) + fit$strata <- factor(rep(names(fit$strata), fit$strata)) + + # A survfit object may contain std(log S) or std(S), summary always std(S) + if (!is.null(fit$std.err) && fit$logse) fit$std.err <- fit$std.err * fit$surv + if (scale != 1) { + # fix scale in the output + fit$time <- fit$time/scale + } + class(fit) <- "summary.survfitms" + fit +} + +<> +<> +@ + +Printing for a survfitms object is different than for a survfit one. +The big difference is that I don't have an estimate of the median, or +any other quantile for that matter. Mean time in state makes sense, but +I don't have a standard error for it at the moment. +The other is that there is usually a mismatch between the n.event matrix +and the n.risk matrix. +The latter has all the states that were possible whereas the former only +has states with an arrow pointing in. We need to manufacture the 0 events +for the other states. + +<>= +print.survfitms <- function(x, scale=1, + rmean = getOption("survfit.rmean"), ...) { + if (!is.null(cl<- x$call)) { + cat("Call: ") + dput(cl) + cat("\n") + } + omit <- x$na.action + if (length(omit)) cat(" ", naprint(omit), "\n") + + x <- survfit0(x, x$start.time) + if (is.null(rmean)) rmean <- "common" + if (is.numeric(rmean)) { + if (is.null(x$start.time)) { + if (rmean < min(x$time)) + stop("Truncation point for the mean is < smallest survival") + } + else if (rmean < x$start.time) + stop("Truncation point for the mean is < smallest survival") + } + else { + rmean <- match.arg(rmean, c('none', 'common', 'individual')) + if (length(rmean)==0) stop("Invalid value for rmean option") + } + + temp <- survmean2(x, scale=scale, rmean) + if (is.null(temp$end.time)) print(temp$matrix, ...) + else { + etime <- temp$end.time + dd <- dimnames(temp$matrix) + cname <- dd[[2]] + cname[length(cname)] <- paste0(cname[length(cname)], '*') + dd[[2]] <- cname + dimnames(temp$matrix) <- dd + print(temp$matrix, ...) + if (length(etime) ==1) + cat(" *mean time in state, restricted (max time =", + format(etime, ...), ")\n") + else cat(" *mean time in state, restricted (per curve cutoff)\n") + } + invisible(x) +} +@ + +This part of the computation is set out separately since it is called +by both print and summary. +<>= +survmean2 <- function(x, scale=1, rmean) { + nstate <- length(x$states) #there will always be at least 1 state + ngrp <- max(1, length(x$strata)) + if (is.null(x$newdata)) ndata <- 0 else ndata <- nrow(x$newdata) + if (ngrp >1) { + igrp <- rep(1:ngrp, x$strata) + rname <- names(x$strata) + } + else { + igrp <- rep(1, length(x$time)) + rname <- NULL + } + + # The n.event matrix may not have nstate columms. Its + # colnames are the first elements of states, however + if (is.matrix(x$n.event)) { + nc <- ncol(x$n.event) + nevent <- tapply(x$n.event, list(rep(igrp, nc), col(x$n.event)), sum) + dimnames(nevent) <- list(rname, x$states[1:nc]) + } + else { + nevent <- tapply(x$n.event, igrp, sum) + names(nevent) <- rname + } + + if (ndata< 2) { + outmat <- matrix(0., nrow=nstate*ngrp , ncol=2) + outmat[,1] <- rep(x$n, nstate) + outmat[1:length(nevent), 2] <- c(nevent) + + if (ngrp >1) + rowname <- c(outer(rname, x$states, paste, sep=", ")) + else rowname <- x$states + } + else { + outmat <- matrix(0., nrow=nstate*ndata*ngrp, ncol=2) + outmat[,1] <- rep(x$n, nstate*ndata) + outmat[, 2] <- rep(c(nevent), each=ndata) + + temp <- outer(1:ndata, x$states, paste, sep=", ") + if (ngrp >1) + rowname <- c(outer(rname, temp, paste, sep=", ")) + else rowname <- temp + nstate <- nstate * ndata + } + + # Caculate the mean time in each state + if (rmean != "none") { + if (is.numeric(rmean)) maxtime <- rep(rmean, ngrp) + else if (rmean=="common") maxtime <- rep(max(x$time), ngrp) + else maxtime <- tapply(x$time, igrp, max) + + meantime <- matrix(0., ngrp, nstate) + if (!is.null(x$influence)) stdtime <- meantime + for (i in 1:ngrp) { + # a 2 dimensional matrix is an "array", but a 3-dim array is + # not a "matrix", so check for matrix first. + if (is.matrix(x$pstate)) + temp <- x$pstate[igrp==i,, drop=FALSE] + else if (is.array(x$pstate)) + temp <- matrix(x$pstate[igrp==i,,,drop=FALSE], + ncol= nstate) + else temp <- matrix(x$pstate[igrp==i], ncol=1) + + tt <- x$time[igrp==i] + + # Now cut it off at maxtime + delta <- diff(c(tt[tt nrow(temp)) delta <- delta[1:nrow(temp)] + if (length(delta) < nrow(temp)) + delta <- c(delta, rep(0, nrow(temp) - length(delta))) + meantime[i,] <- colSums(delta*temp) + + if (!is.null(x$influence)) { + # calculate the variance + if (is.list(x$influence)) + itemp <- apply(x$influence[[i]], 1, + function(x) colSums(x*delta)) + else itemp <- apply(x$influence, 1, + function(x) colSums(x*delta)) + stdtime[i,] <- sqrt(rowSums(itemp^2)) + } + } + outmat <- cbind(outmat, c(meantime)/scale) + cname <- c("n", "nevent", "rmean") + if (!is.null(x$influence)) { + outmat <- cbind(outmat, c(stdtime)/scale) + cname <- c(cname, "std(rmean)") + } + # report back a single time, if there is only one + if (all(maxtime == maxtime[1])) maxtime <- maxtime[1] + } + else cname <- c("n", "nevent") + dimnames(outmat) <- list(rowname, cname) + + if (rmean=='none') list(matrix=outmat) + else list(matrix=outmat, end.time=maxtime/scale) +} +@ +\section{Matrix exponentials and transition matrices} +For multi-state models, we need to compute the exponential of the transition +matrix, sometimes many times. +The matrix exponential is formally defined as +\begin{equation*} + \exp(R) = I + \sum_{j=1}^\infty R^i/i! + \end{equation*} +The computation is nicely solved by the expm package +\emph{if} we didn't need derivatives and/or high speed. +We want both. + +For the package there are three cases: +\begin{enumerate} + \item If there is only one departure state, then there is a fast closed + form solution, shown below. This case occurs whenever an event time + is unique, i.e., no other event times are tied with this one. This always + holds for competing risk models. + \item If the rate matrix $R$ is upper triangular and the (non-zero) diagonal + elements are distinct, there is a fast matrix decomposition algorithm. + If the transition matrix is acylic then it can be rearranged to be in upper + triangular form. The decomposition also gives a simple expression for + the derivative. + \item In the general case we use a Pade-Laplace algorithm: the same found + in the matexp package. +\end{enumerate} + +For a rate matrix $R$, $R_{jk}$ is the rate of transition from state $j$ to +state $k$, and is itself an exponential $R_{jk} = \exp(\eta_{jk})$. +Thus all non-diagonal values must be $/ge 0$. Transitions that do not occur +have rate 0. +The diagonal element is determined by the constraint that row sums are 0. +Let $A= \exp(R)$. +Also be aware that $\exp(A)\exp(B) \ne \exp(A+B)$ for the case of matrices. + +If there is only one non-zero diagonal element, $R_{jj}$ say, then +\begin{align*} + A_{jj} &= e^{R_{jj}} \\ + A_{jk} &= \left(1- e^{R_{jj}}\right) \frac{R_{jk}}/{\sum_{l\ne j} R_{jl}} \\ + A_{kk} &= 1; k\ne j +\end{align*} +and all other elements of $A$ are zero. +The derivative of $A$ with respect to $\eta_{jk}$ will be 0 for all rows +except row $j$. +\begin{align*} + \frac{\partial A_{jj}}{\partial \eta_{jk}} &= + \frac{\partial \exp(-\sum_{k!=j} \eta_{jk})}{\partial \eta_{jk}} \\ + &= -\eta_{jk} A_{jj} \\ + \frac{\partial A_{jk}}{\partial \eta_{jk}} &= eta_{jk}A_{jj} + \;\mbox{single event type} \\ + \frac{\partial A_{jk}}{\partial \eta_{jm}}&= + A_{jj} eta_{jm}\frac{R_{jm}}{\sum_{l\ne j} R_{jl}} + + (A_{jj} -1) \frac{\eta_{jm} (1- \sum_{l\ne j} R_{jl})}{(\sum_{l\ne j} R_{jl})^2} +\end{align*} +If time is continuous then most events will be at a unique event time, and this +fast computation will be the most common case. + +If the state space is acylic, the case for many survival problems, then +we can reorder the states so that R is upper triangular. +In that case, the diagonal elements of R are the eigenvalues. If these +are unique (ignoring the zeros), then an algorithm of Kalbfleisch and Lawless +gives both A and the derivatives of A in terms of a matrix decomposition. +For the remaining cases use the Pade' approximation as found in the +matexp package. +The overall stategy is the following: +\begin{enumerate} + \item Call \code{survexpmsetup} once, which will decide if the matrix is + acyclic, and return a reorder vector if so or a flag if it is not. + This determination is based on the possible transitions, e.g., on the + transitions matrix from survcheck. + \item Call \code{survexpm} for each individual transition matrix. + In that routine + \begin{itemize} + \item First check for the simple case, otherwise + \item Do not need derivatives: call survexpm + \item Do need derivatives + \begin{itemize} + \item If upper triangular and no tied values, use the deriv routine + \item Otherwise use the Pade routine + \end{itemize} + \end{itemize} +\end{enumerate} + +<>= +survexpmsetup <- function(rmat) { + # check the validity of the transition matrix, and determine if it + # is acyclic, i.e., can be reordered into an upper triangular matrix. + if (!is.matrix(rmat) || nrow(rmat) != ncol(rmat) || any(diag(rmat) > 0) || + any(rmat[row(rmat) != col(rmat)] < 0)) + stop ("input is not a transition matrix") + if (!is.logical(all.equal(rowSums(rmat), rep(0, ncol(rmat))))) + stop("input is not a transition matrix") + nc <- ncol(rmat) + lower <- row(rmat) > col(rmat) + if (all(rmat[lower] ==0)) return(0) # already in order + + # score each state by (number of states it follows) - (number it precedes) + temp <- 1*(rmat >0) # 0/1 matrix + indx <- order(colSums(temp) - rowSums(temp)) + temp <- rmat[indx, indx] # try that ordering + if (all(temp[lower]== 0)) indx # it worked! + else -1 # there is a loop in the states +} +@ + +\subsection{Decompostion} +Based on Kalbfleisch and Lawless, ``The analysis of panel data under a +Markov assumption'' (J Am Stat Assoc, 1985:863-871), the +rate matrix $R$ can be written as $ADA^{-1}$ for some matrix $A$, where +$D$ is a diagonal matrix of eigenvalues, provided all of the eigenvalues +are distinct. Then $R^k = A D^k A^{-1}$, and using the definition of +a matrix exponential we see that +$\exp(R) = A \exp(D) A^{-1}$. The exponential of a diagonal +matrix is simply a diagonal matrix of the exponentials. +The matrix $Rt$ for a scalar $t$ has decomposition $A\exp(Dt)A^{-1}$; a +single decompostion suffices for all values of $t$. + +A particular example is +\begin{equation} + R = + \begin{pmatrix} + r_{11} & r_{12} & r_{13} & 0 & 0 & r_{15}\\ + 0 & r_{22} & 0 & r_{24} & 0 & r_{25}\\ + 0 & 0 & r_{33} & r_{34} & r_{35} & r_{35}\\ + 0 & 0 & 0 & r_{44} & r_{45} & r_{45} \\ + 0 & 0 & 0 & 0 & r_{55} & r_{55} \\ + 0 & 0 & 0 & 0 & 0 & 0 + \end{pmatrix}. +\end{equation} +Since this is a transition matrix the diagonal elements are constrained so that +row sums are zero: $r_{ii} = -\sum_{j\ne i} r_{ij}$. +Since R is an upper triangular matrix it's eigenvalues lie on the diagonal. +If none of the the eigenvalues are +repeated, then the Prentice result applies. + +The decompostion is quite simple since $R$ is triangular. +We want the eigenvectors, i.e. solutions to +\begin{align*} + R v_i &= r_{ii} v_i \\ +% R v_2 &= r_{22} v_2 \\ +% R v_3 &= r_{33} v_3 \\ +% R v_4 &= r_{44} v_4 \\ +% R v_5 &= r_{55} v_5 \\ +% R v_6 &= r_{66} v_6 +\end{align*} +for $i= 1, \dots, 6$, where $v_i$ are the colums of $V$. + +It turns out that the set of eigenvectors is +also upper triangular; we can solve for them one by one +using back substitution. +For the first eigenvector we have +$v_1 = (1, 0,0,0,0,0)$. +For the second we have the equations +\begin{align*} + r_{11} x + r_{12}y &= r_{22} x \\ + r_{22}y &= r_{22} y +\end{align*} +which has the solution $(r_{12}/(r_{22}- r_{11}), 1, 0,0,0,0)$, +and the process recurs for other rows. +Since $V$ is triangular the inverse of $V$ is upper triangular +and also easy to compute. + +This approach fails if there are tied eigenvalues. +Kalbfleice and Lawless comment that this case is rare, +but one can then use a decomposition to Jordan canonical form re +Cox and Miller, the Theory of Stochastic Processes, 1965. +Although this leads to some nice theorems it does not give a +simple comutational form, however, +and it is easier to fall back on the pade routine. +At this time, the pade routine is as fast as the triangluar code, +at least for small matrices without deriviatives. + +<>= +survexpm <- function(rmat, time=1.0, setup, eps=1e-6) { + # rmat is a transition matrix, so the diagonal elements are 0 or negative + if (length(rmat)==1) exp(rmat[1]*time) #failsafe -- should never be called + else { + nonzero <- (diag(rmat) != 0) + if (sum(nonzero ==0)) diag(nrow(rmat)) # expm(0 matrix) = identity + if (sum(nonzero) ==1) { + j <- which(nonzero) + emat <- diag(nrow(rmat)) + temp <- exp(rmat[j,j] * time) + emat[j,j] <- temp + emat[j, -j] <- (1-temp)* rmat[j, -j]/sum(rmat[j,-j]) + emat + } + else if (missing(setup) || setup[1] < 0 || + any(diff(sort(diag(rmat)))< eps)) pade(rmat*time) + else { + if (setup[1]==0) .Call(Ccdecomp, rmat, time)$P + else { + temp <- rmat + temp[setup, setup] <- .Call(Ccdecomp, rmat[setup, setup], time) + temp$P + } + } + } +} +@ + +The routine below is modeled after the cholesky routines in the survival +library. +To help with notation, the return values are labeled as in the +Kalbfleisch and Lawless paper, +except that their Q = our rmat. Q = A diag(d) Ainv and P= exp(Qt) + +<>= +/* +** Compute the eigenvectors for the upper triangular matrix R +*/ +#include +#include "R.h" +#include "Rinternals.h" + +SEXP cdecomp(SEXP R2, SEXP time2) { + int i,j,k; + int nc, ii; + + static const char *outnames[]= {"d", "A", "Ainv", + "P", ""}; + SEXP rval, stemp; + double *R, *A, *Ainv, *P; + double *dd, temp, *ediag; + double time; + + nc = ncols(R2); /* number of columns */ + R = REAL(R2); + time = asReal(time2); + + /* Make the output matrices as copies of R, so as to inherit + ** the dimnames and etc + */ + + PROTECT(rval = mkNamed(VECSXP, outnames)); + stemp= SET_VECTOR_ELT(rval, 0, allocVector(REALSXP, nc)); + dd = REAL(stemp); + stemp = SET_VECTOR_ELT(rval, 1, allocMatrix(REALSXP, nc, nc)); + A = REAL(stemp); + for (i =0; i< nc*nc; i++) A[i] =0; /* R does not zero memory */ + stemp = SET_VECTOR_ELT(rval, 2, duplicate(stemp)); + Ainv = REAL(stemp); + stemp = SET_VECTOR_ELT(rval, 3, duplicate(stemp)); + P = REAL(stemp); + + ediag = (double *) R_alloc(nc, sizeof(double)); + + /* + ** Compute the eigenvectors + ** For each column of R, find x such that Rx = kx + ** The eigenvalue k is R[i,i], x is a column of A + ** Remember that R is in column order, so the i,j element is in + ** location i + j*nc + */ + ii =0; /* contains i * nc */ + for (i=0; i=0; j--) { /* fill in the rest */ + temp =0; + for (k=j; k<=i; k++) temp += R[j + k*nc]* A[k +ii]; + A[j +ii] = temp/(dd[i]- R[j + j*nc]); + } + ii += nc; + } + + /* + ** Solve for A-inverse, which is also upper triangular. The diagonal + ** of A and the diagonal of A-inverse are both 1. At the same time + ** solve for P = A D Ainverse, where D is a diagonal matrix + ** with exp(eigenvalues) on the diagonal. + ** P will also be upper triangular, and we can solve for it using + ** nearly the same code as above. The prior block had RA = x with A the + ** unknown and x successive colums of the identity matrix. + ** We have PA = AD, so x is successively columns of AD. + ** Imagine P and A are 4x4 and we are solving for the second row + ** of P. Remember that P[2,1]= A[2,3] = A[2,4] =0; the equations for + ** this row of P are: + ** + ** 0*A[1,2] + P[2,2]A[2,2] + P[2,3] 0 + P[2,4] 0 = A[2,2] D[2] + ** 0*A[1,3] + P[2,2]A[2,3] + P[2,3]A[3,3] + P[2,4] 0 = A[2,3] D[3] + ** 0*A[1,4] + P[2,2]A[2,4] + P[2,3]A[3,4] + P[2,4]A[4,4] = A[2,4] D[4] + ** + ** For A-inverse the equations are (use U= A-inverse for a moment) + ** 0*A[1,2] + U[2,2]A[2,2] + U[2,3] 0 + U[2,4] 0 = 1 + ** 0*A[1,3] + U[2,2]A[2,3] + U[2,3]A[3,3] + U[2,4] 0 = 0 + ** 0*A[1,4] + U[2,2]A[2,4] + U[2,3]A[3,4] + U[2,4]A[4,4] = 0 + */ + + ii =0; /* contains i * nc */ + for (i=0; i=0; j--) { /* fill in the rest of the column*/ + temp =0; + for (k=j+1; k<=i; k++) temp += A[j + k*nc]* Ainv[k +ii]; + Ainv[j +ii] = -temp; + } + + /* column i of P */ + P[i + ii] = ediag[i]; + for (j=0; j>= +derivative <- function(rmat, time, dR, setup, eps=1e-8) { + if (missing(setup) || setup[1] <0 || any(diff(sort(diag(rmat)))< eps)) + return (pade(rmat*time, dR*time)) + + if (setup==0) dlist <- .Call(Ccdecomp, rmat, time) + else dlist <- .Call(Ccdecomp, rmat[setup, setup], time) + ncoef <- dim(dR)[3] + nstate <- nrow(rmat) + + dmat <- array(0.0, dim=c(nstate, nstate, ncoef)) + vtemp <- outer(dlist$d, dlist$d, + function(a, b) { + ifelse(abs(a-b)< eps, time* exp(time* (a+b)/2), + (exp(a*time) - exp(b*time))/(a-b))}) + + # two transitions can share a coef, but only for the same X variable + for (i in 1:ncoef) { + G <- dlist$Ainv %*% dR[,,i] %*% dlist$A + V <- G*vtemp + dmat[,,i] <- dlist$A %*% V %*% dlist$Ainv + } + dlist$dmat <- dmat + + # undo the reordering, if needed + if (setup[1] >0) { + indx <- order(setup) + dlist <- list(P = dlist$P[indx, indx], + dmat = apply(dmat,1:2, function(x) x[indx, indx])) + } + + dlist +} +@ + +The Pade approximation is found in the file pade.R. There is a good discussion +of the problem at www.maths.manchester.ac.uk/~higham/talks/exp09.pdf. +The pade function copied code from the matexp package, which in turn is based +on Higham 2005. Let B be a matrix and define +\begin{eqnarray*} + r_m(B) &= p(B)/q(B) \\ + p(B) &= \sum_{j=0^m} \frac{((2m-j)! m!}{(2m)!(m-j)! j!} B^j \\ + q(B) &= p(-B) +\end{eqnarray*} + +The algorithm for calculating $\exp(A)$ is based on the following table +\begin{center} +\begin{tabular}{c|ccccc} + $||A||_1$ & 0.15 & .25 & .95 & 2.1 & 3.4 \\ + m & 3 & 5 & 7 & 9 & 13 +\end{tabular} \end{center} +The 1 norm of a matrix is \code{max(colSums(A))}. If the norm is $\le 3.4$ +the $\exp(A) = r_m(A)$ using the table. +Otherwise, find $s$ such that $B = A/2^s$ has norm $<=3.4$ and use the table +method to find $\exp(B)$, then $\exp(A) \approx B^(2^s)$, the latter involves +repeated squaring of the matrix. + +The expm code has a lot of extra steps whose job is to make sure that elements +of $A$ are not too disparate in size. Transition matrices are nice and we can +skip all of that. This makes the pade function conserably faster than the +expm function from the Matrix library. In fact, if there aren't any +tied event times, most elements of the rate matrix will be zero, and +others are on the order of 1/(number at risk), so that $m=3$ is the most common +outcome. +\section{Plotting survival curves} +This version of the curves uses the newer form of the survfit object, which +fixes an original design decision that I now consider to have been a mistake. +That is, an ordinary survival curve did not store the intial (time=0, S=1) +point in the survfit object, leaving it up to plotting and/or printing routines +to glue it back on. +Later additions of delayed starting time and multi-state curves meant that I +had to store those values anyway, sticking them into appended objects. +The version3 survfit object puts the intial time back where it belongs, and +makes this routine easier to write. + +The plot, lines, and points routines use several common code blocks in order to +maintain consistency. + +The xmax argument has been a long term issue. Using xmax on a plot call, we +would like that xmax to persist in a subsequent lines.survfit call. +But, the problem with this is that lines might not be called after plot.survfit: +someone might have other data and then want to add a survfit line to it (rare +case I know). If we save the xlimits in some global object, there is no way +to erase that object every time a high level call is made. + +<>= +plot.survfit<- function(x, conf.int, mark.time=FALSE, + pch=3, col=1,lty=1, lwd=1, + cex=1, log=FALSE, + xscale=1, yscale=1, + xlim, ylim, xmax, + fun, xlab="", ylab="", xaxs='r', + conf.times, conf.cap=.005, conf.offset=.012, + conf.type=c('log', 'log-log', 'plain', + 'logit', "arcsin"), + mark, noplot="(s0)", cumhaz=FALSE, + firstx, ymin, ...) { + + dotnames <- names(list(...)) + if (any(dotnames =='type')) + stop("The graphical argument 'type' is not allowed") + x <- survfit0(x, x$start.time) # align data at 0 for plotting + + <> + <> + <> + <> + <> + <> + <> + type <- 's' + <> + invisible(lastx) +} + +lines.survfit <- function(x, type='s', + pch=3, col=1, lty=1, lwd=1, + cex=1, + mark.time=FALSE, xmax, + fun, conf.int=FALSE, + conf.times, conf.cap=.005, conf.offset=.012, + conf.type=c('log', 'log-log', 'plain', + 'logit', "arcsin"), + mark, noplot="(s0)", cumhaz=FALSE, ...) { + x <- survfit0(x, x$start.time) + + xlog <- par("xlog") + <> + <> + <> + <> + + # remember a prior xmax + if (missing(xmax)) xmax <- getOption("plot.survfit")$xmax + <> + <> + invisible(lastx) +} + +points.survfit <- function(x, fun, censor=FALSE, + col=1, pch, noplot="(s0)", cumhaz=FALSE, ...) { + + conf.int <- conf.times <- FALSE # never draw these with 'points' + x <- survfit0(x, x$start.time) + + <> + <> + + if (ncurve==1 || (length(col)==1 && missing(pch))) { + if (censor) points(stime, ssurv, ...) + else points(stime[x$n.event>0], ssurv[x$n.event>0], ...) + } + else { + c2 <- 1 #cycles through the colors and characters + col <- rep(col, length=ncurve) + if (!missing(pch)) { + if (length(pch)==1) + pch2 <- rep(strsplit(pch, '')[[1]], length=ncurve) + else pch2 <- rep(pch, length=ncurve) + } + for (j in 1:ncol(ssurv)) { + for (i in unique(stemp)) { + if (censor) who <- which(stemp==i) + else who <- which(stemp==i & x$n.event >0) + if (missing(pch)) + points(stime[who], ssurv[who,j], col=col[c2], ...) + else + points(stime[who], ssurv[who,j], col=col[c2], + pch=pch2[c2], ...) + c2 <- c2+1 + } + } + } +} +@ + +<>= +# decide on logarithmic axes, yes or no +if (is.logical(log)) { + ylog <- log + xlog <- FALSE + if (ylog) logax <- 'y' + else logax <- "" +} +else { + ylog <- (log=='y' || log=='xy') + xlog <- (log=='x' || log=='xy') + logax <- log +} + +if (!missing(fun)) { + if (is.character(fun)) { + if (fun=='log'|| fun=='logpct') ylog <- TRUE + if (fun=='cloglog') { + xlog <- TRUE + if (ylog) logax <- 'xy' + else logax <- 'x' + } + if (fun=="cumhaz" && missing(cumhaz)) cumhaz <- TRUE + } +} +@ + +<>= +# The default for plot and lines is to add confidence limits +# if there is only one curve +if (missing(conf.int) && missing(conf.times)) + conf.int <- (!is.null(x$std.err) && prod(dim(x) ==1)) + +if (missing(conf.times)) conf.times <- NULL +else { + if (!is.numeric(conf.times)) stop('conf.times must be numeric') + if (missing(conf.int)) conf.int <- TRUE +} + +if (!missing(conf.int)) { + if (is.numeric(conf.int)) { + conf.level <- conf.int + if (conf.level<0 || conf.level > 1) + stop("invalid value for conf.int") + if (conf.level ==0) conf.int <- FALSE + else if (conf.level != x$conf.int) { + x$upper <- x$lower <- NULL # force recomputation + } + conf.int <- TRUE + } + else conf.level = 0.95 +} + +# Organize data into stime, ssurv, supper, slower +stime <- x$time +std <- NULL +yzero <- FALSE # a marker that we have an "ordinary survival curve" with min 0 +smat <- function(x) { + # the rest of the routine is simpler if everything is a matrix + dd <- dim(x) + if (is.null(dd)) as.matrix(x) + else if (length(dd) ==2) x + else matrix(x, nrow=dd[1]) +} + +if (cumhaz) { # plot the cumulative hazard instead + if (is.null(x$cumhaz)) + stop("survfit object does not contain a cumulative hazard") + + if (is.numeric(cumhaz)) { + dd <- dim(x$cumhaz) + if (is.null(dd)) nhazard <- 1 + else nhazard <- prod(dd[-1]) + + if (cumhaz != floor(cumhaz)) stop("cumhaz argument is not integer") + if (any(cumhaz < 1 | cumhaz > nhazard)) stop("subscript out of range") + ssurv <- smat(x$cumhaz)[,cumhaz, drop=FALSE] + if (!is.null(x$std.chaz)) std <- smat(x$std.chaz)[,cumhaz, drop=FALSE] + } + else if (is.logical(cumhaz)) { + ssurv <- smat(x$cumhaz) + if (!is.null(x$std.chaz)) std <- smat(x$std.chaz) + } + else stop("invalid cumhaz argument") +} +else if (inherits(x, "survfitms")) { + i <- !(x$states %in% noplot) + if (all(i) || !any(i)) { + # the !any is a failsafe, in case none are kept we ignore noplot + ssurv <- smat(x$pstate) + if (!is.null(x$std.err)) std <- smat(x$std.err) + if (!is.null(x$lower)) { + slower <- smat(x$lower) + supper <- smat(x$upper) + } + } + else { + i <- which(i) # the states to keep + # we have to be careful about subscripting + if (length(dim(x$pstate)) ==3) { + ssurv <- smat(x$pstate[,,i, drop=FALSE]) + if (!is.null(x$std.err)) + std <- smat(x$std.err[,,i, drop=FALSE]) + if (!is.null(x$lower)) { + slower <- smat(x$lower[,,i, drop=FALSE]) + supper <- smat(x$upper[,,i, drop=FALSE]) + } + } + else { + ssurv <- x$pstate[,i, drop=FALSE] + if (!is.null(x$std.err)) std <- x$std.err[,i, drop=FALSE] + if (!is.null(x$lower)) { + slower <- smat(x$lower[,i, drop=FALSE]) + supper <- smat(x$upper[,i, drop=FALSE]) + } + } + } +} +else { + yzero <- TRUE + ssurv <- as.matrix(x$surv) # x$surv will have one column + if (!is.null(x$std.err)) std <- as.matrix(x$std.err) + # The fun argument usually applies to single state survfit objects + # First deal with the special case of fun='cumhaz', which is here for + # backwards compatability; people should use the cumhaz argument + if (!missing(fun) && is.character(fun) && fun=="cumhaz") { + cumhaz <- TRUE + if (!is.null(x$cumhaz)) { + ssurv <- as.matrix(x$cumhaz) + if (!is.null(x$std.chaz)) std <- as.matrix(x$std.chaz) + } + else { + ssurv <- as.matrix(-log(x$surv)) + if (!is.null(x$std.err)) { + if (x$logse) std <- as.matrix(x$std.err) + else std <- as.matrix(x$std.err/x$surv) + } + } + } +} + +# set up strata +if (is.null(x$strata)) { + nstrat <- 1 + stemp <- rep(1, length(x$time)) # same length as stime +} +else { + nstrat <- length(x$strata) + stemp <- rep(1:nstrat, x$strata) # same length as stime +} +ncurve <- nstrat * ncol(ssurv) +@ + +If confidence limits are to be plotted, and they were not part of the +data that is passed in, create them. Confidence limits for the +cumulative hazard must always be created, and they don't use transforms. +<>= +conf.type <- match.arg(conf.type) +if (conf.type=="none") conf.int <- FALSE +if (conf.int== "none") conf.int <- FALSE +if (conf.int=="only") { + plot.surv <- FALSE + conf.int <- TRUE + } +else plot.surv <- TRUE + +if (conf.int) { + if (is.null(std)) stop("object does not have standard errors, CI not possible") + if (cumhaz) { + if (missing(conf.type)) conf.type="plain" + temp <- survfit_confint(ssurv, std, logse=FALSE, + conf.type, conf.level, ulimit=FALSE) + supper <- as.matrix(temp$upper) + slower <- as.matrix(temp$lower) + } + else if (is.null(x$upper)) { + if (missing(conf.type) && !is.null(x$conf.type)) + conf.type <- x$conf.type + temp <- survfit_confint(ssurv, std, logse= x$logse, + conf.type, conf.level, ulimit=FALSE) + supper <- as.matrix(temp$upper) + slower <- as.matrix(temp$lower) + } + else if (!inherits(x, "survfitms")) { + supper <- as.matrix(x$upper) + slower <- as.matrix(x$lower) + } +} else supper <- slower <- NULL +@ + +The functional form of the fun argument can be whatever the user wants. +For the character form we try to thin out the obvious mistakes. +If fun=='cumhaz', the code above has already replaced ssurv with the +cumulative hazard, so this part of the code should plug in an identity +function. + +<>= +if (!missing(fun)){ + if (is.character(fun)) { + if (cumhaz) { + tfun <- switch(tolower(fun), + 'log' = function(x) x, + 'cumhaz'=function(x) x, + 'identity'= function(x) x, + stop("Invalid function argument") + ) + } else if (inherits(x, "survfitms")) { + tfun <-switch(tolower(fun), + 'log' = function(x) log(x), + 'event'=function(x) x, + 'cloglog'=function(x) log(-log(1-x)), + 'cumhaz' = function(x) x, + 'pct' = function(x) x*100, + 'identity'= function(x) x, + stop("Invalid function argument") + ) + } else { + yzero <- FALSE + tfun <- switch(tolower(fun), + 'log' = function(x) x, + 'event'=function(x) 1-x, + 'cumhaz'=function(x) x, + 'cloglog'=function(x) log(-log(x)), + 'pct' = function(x) x*100, + 'logpct'= function(x) 100*x, #special case further below + 'identity'= function(x) x, + 'f' = function(x) 1-x, + 's' = function(x) x, + 'surv' = function(x) x, + stop("Unrecognized function argument") + ) + } + } + else if (is.function(fun)) tfun <- fun + else stop("Invalid 'fun' argument") + + ssurv <- tfun(ssurv ) + if (!is.null(supper)) { + supper <- tfun(supper) + slower <- tfun(slower) + } +} +@ + +The \code{mark} argument is a holdover from S, when pch could not have +numeric values; mark has since disappeared from the manual page for +\code{par}. We honor it for backwards compatability. +To be consistent with matplot and others, we allow pch to be a character +string or a vector of characters. + +<>= +if (missing(mark.time) & !missing(mark)) mark.time <- TRUE +if (missing(pch) && !missing(mark)) pch <- mark +if (length(pch)==1 && is.character(pch)) pch <- strsplit(pch, "")[[1]] + +# Marks are not placed on confidence bands +pch <- rep(pch, length.out=ncurve) +mcol <- rep(col, length.out=ncurve) +if (is.numeric(mark.time)) mark.time <- sort(mark.time) + +# The actual number of curves is ncurve*3 if there are confidence bands, +# unless conf.times has been given. Colors and line types in the latter +# match the curves +# If the number of line types is 1 and lty is an integer, then use lty +# for the curve and lty+1 for the CI +# If the length(lty) <= length(ncurve), use the same color for curve and CI +# otherwise assume the user knows what they are about and has given a full +# vector of line types. +# Colors and line widths work like line types, excluding the +1 rule. +if (conf.int & is.null(conf.times)) { + if (length(lty)==1 && is.numeric(lty)) + lty <- rep(c(lty, lty+1, lty+1), ncurve) + else if (length(lty) <= ncurve) + lty <- rep(rep(lty, each=3), length.out=(ncurve*3)) + else lty <- rep(lty, length.out= ncurve*3) + + if (length(col) <= ncurve) col <- rep(rep(col, each=3), length.out=3*ncurve) + else col <- rep(col, length.out=3*ncurve) + + if (length(lwd) <= ncurve) lwd <- rep(rep(lwd, each=3), length.out=3*ncurve) + else lwd <- rep(lwd, length.out=3*ncurve) +} +else { + col <- rep(col, length.out=ncurve) + lty <- rep(lty, length.out=ncurve) + lwd <- rep(lwd, length.out=ncurve) +} +@ + + +Create the frame for the plot. +We draw an empty figure, letting R figure out the limits. + +<>= +# check consistency +if (!missing(xlim)) { + if (!missing(xmax)) warning("cannot have both xlim and xmax arguments, xmax ignored") + if (!missing(firstx)) stop("cannot have both xlim and firstx arguments") +} +if (!missing(ylim)) { + if (!missing(ymin)) stop("cannot have both ylim and ymin arguments") +} + +# Do axis range computations +if (!missing(xlim) && !is.null(xlim)) { + tempx <- xlim + xmax <- xlim[2] + if (xaxs == 'S') tempx[2] <- tempx[1] + diff(tempx)*1.04 +} +else { + temp <- stime[is.finite(stime)] + if (!missing(xmax) && missing(xlim)) temp <- pmin(temp, xmax) + else xmax <- NULL + + if (xaxs=='S') { + rtemp <- range(temp) + delta <- diff(rtemp) + #special x- axis style for survival curves + if (xlog) tempx <- c(min(rtemp[rtemp>0]), min(rtemp)+ delta*1.04) + else tempx <- c(min(rtemp), min(rtemp)+ delta*1.04) + } + else if (xlog) tempx <- range(temp[temp > 0]) + else tempx <- range(temp) +} +if (!missing(xlim) || !missing(xmax)) + options(plot.survfit = list(xmax=tempx[2])) +else options(plot.survfit = NULL) + +if (!missing(ylim) && !is.null(ylim)) tempy <- ylim +else { + skeep <- is.finite(stime) & stime >= tempx[1] & stime <= tempx[2] + + if (ylog) { + if (!is.null(supper)) + tempy <- range(c(slower[is.finite(slower) & slower>0 & skeep], + supper[is.finite(supper) & skeep])) + else tempy <- range(ssurv[is.finite(ssurv)& ssurv>0 & skeep]) + if (tempy[2]==1) tempy[2] <- .99 # makes for a prettier axis + if (any(c(ssurv, slower)[skeep] ==0)) { + tempy[1] <- tempy[1]*.8 + ssurv[ssurv==0] <- tempy[1] + if (!is.null(slower)) slower[slower==0] <- tempy[1] + } + } + else { + if (!is.null(supper)) + tempy <- range(c(supper[skeep], slower[skeep]), finite=TRUE, na.rm=TRUE) + else tempy <- range(ssurv[skeep], finite=TRUE, na.rm= TRUE) + if (yzero) tempy <- range(c(0, tempy)) + } +} + +if (!missing(ymin)) tempy[1] <- ymin + +# +# Draw the basic box +# +temp <- if (xaxs=='S') 'i' else xaxs +plot(range(tempx, finite=TRUE, na.rm=TRUE)/xscale, + range(tempy, finite=TRUE, na.rm=TRUE)*yscale, + type='n', log=logax, xlab=xlab, ylab=ylab, xaxs=temp,...) +if(yscale != 1) { + if (ylog) par(usr =par("usr") -c(0, 0, log10(yscale), log10(yscale))) + else par(usr =par("usr")/c(1, 1, yscale, yscale)) +} +if (xscale !=1) { + if (xlog) par(usr =par("usr") -c(log10(xscale), log10(xscale), 0,0)) + else par(usr =par("usr")*c(xscale, xscale, 1, 1)) +} +@ +The use of [[par(usr)]] just above is a bit sneaky. I want the +lines and points routines to be able to add to the plot, \emph{without} +passing them a global parameter that determines the y-scale or forcing +the user to repeat it. + +The next functions do the actual drawing. +<>= +# Create a step function, removing redundancies that sometimes occur in +# curves with lots of censoring. +dostep <- function(x,y) { + keep <- is.finite(x) & is.finite(y) + if (!any(keep)) return() #all points were infinite or NA + if (!all(keep)) { + # these won't plot anyway, so simplify (CI values are often NA) + x <- x[keep] + y <- y[keep] + } + n <- length(x) + if (n==1) list(x=x, y=y) + else if (n==2) list(x=x[c(1,2,2)], y=y[c(1,1,2)]) + else { + # replace verbose horizonal sequences like + # (1, .2), (1.4, .2), (1.8, .2), (2.3, .2), (2.9, .2), (3, .1) + # with (1, .2), (.3, .2),(3, .1). + # They are slow, and can smear the looks of the line type. + temp <- rle(y)$lengths + drops <- 1 + cumsum(temp[-length(temp)]) # points where the curve drops + + #create a step function + if (n %in% drops) { #the last point is a drop + xrep <- c(x[1], rep(x[drops], each=2)) + yrep <- rep(y[c(1,drops)], c(rep(2, length(drops)), 1)) + } + else { + xrep <- c(x[1], rep(x[drops], each=2), x[n]) + yrep <- c(rep(y[c(1,drops)], each=2)) + } + list(x=xrep, y=yrep) + } +} + +drawmark <- function(x, y, mark.time, censor, cex, ...) { + if (!is.numeric(mark.time)) { + xx <- x[censor>0] + yy <- y[censor>0] + if (any(censor >1)) { # tied death and censor, put it on the midpoint + j <- pmax(1, which(censor>1) -1) + i <- censor[censor>0] + yy[i>1] <- (yy[i>1] + y[j])/2 + } + } + else { #interpolate + xx <- mark.time + yy <- approx(x, y, xx, method="constant", f=0)$y + } + points(xx, yy, cex=cex, ...) +} +@ + +The code to draw the lines and confidence bands. +<>= +c1 <- 1 # keeps track of the curve number +c2 <- 1 # keeps track of the lty, col, etc +xend <- yend <- double(ncurve) +if (length(conf.offset) ==1) + temp.offset <- (1:ncurve - (ncurve+1)/2)* conf.offset* diff(par("usr")[1:2]) +else temp.offset <- rep(conf.offset, length=ncurve) * diff(par("usr")[1:2]) +temp.cap <- conf.cap * diff(par("usr")[1:2]) + +for (j in 1:ncol(ssurv)) { + for (i in unique(stemp)) { #for each strata + who <- which(stemp==i) + + # if n.censor is missing, then assume any line that does not have an + # event would not be present but for censoring, so there must have + # been censoring then + # otherwise categorize is 0= no censor, 1=censor, 2=censor and death + if (is.null(x$n.censor)) censor <- ifelse(x$n.event[who]==0, 1, 0) + else censor <- ifelse(x$n.censor[who]==0, 0, 1 + (x$n.event[who] > 0)) + xx <- stime[who] + yy <- ssurv[who,j] + if (conf.int) { + ylower <- (slower[who,j]) + yupper <- (supper[who,j]) + } + if (!is.null(xmax) && max(xx) > xmax) { # truncate on the right + xn <- min(which(xx > xmax)) + xx <- xx[1:xn] + yy <- yy[1:xn] + xx[xn] <- xmax + yy[xn] <- yy[xn-1] + if (conf.int) { + ylower <- ylower[1:xn] + yupper <- yupper[1:xn] + ylower[xn] <- ylower[xn-1] + yupper[xn] <- yupper[xn-1] + } + } + + + if (plot.surv) { + if (type=='s') + lines(dostep(xx, yy), lty=lty[c2], col=col[c2], lwd=lwd[c2]) + else lines(xx, yy, type=type, lty=lty[c2], col=col[c2], lwd=lwd[c2]) + if (is.numeric(mark.time) || mark.time) + drawmark(xx, yy, mark.time, censor, pch=pch[c1], col=mcol[c1], + cex=cex) + } + xend[c1] <- max(xx) + yend[c1] <- yy[length(yy)] + + if (conf.int && !is.null(conf.times)) { + # add vertical bars at the specified times + x2 <- conf.times + temp.offset[c1] + templow <- approx(xx, ylower, x2, + method='constant', f=1)$y + temphigh<- approx(xx, yupper, x2, + method='constant', f=1)$y + segments(x2, templow, x2, temphigh, + lty=lty[c2], col=col[c2], lwd=lwd[c2]) + if (conf.cap>0) { + segments(x2-temp.cap, templow, x2+temp.cap, templow, + lty=lty[c2], col=col[c2], lwd=lwd[c2] ) + segments(x2-temp.cap, temphigh, x2+temp.cap, temphigh, + lty=lty[c2], col=col[c2], lwd=lwd[c2]) + } + + } + c1 <- c1 +1 + c2 <- c2 +1 + + if (conf.int && is.null(conf.times)) { + if (type == 's') { + lines(dostep(xx, ylower), lty=lty[c2], + col=col[c2],lwd=lwd[c2]) + c2 <- c2 +1 + lines(dostep(xx, yupper), lty=lty[c2], + col=col[c2], lwd= lwd[c2]) + c2 <- c2 + 1 + } + else { + lines(xx, ylower, lty=lty[c2], + col=col[c2],lwd=lwd[c2], type=type) + c2 <- c2 +1 + lines(xx, yupper, lty=lty[c2], + col=col[c2], lwd= lwd[c2], type= type) + c2 <- c2 + 1 + } + } + + } +} +lastx <- list(x=xend, y=yend) +@ + + + + +\section{State space figures} +The statefig function was written to do ``good enough'' state space figures +quickly and easily. There are certainly figures it can't draw and +many figures that can be drawn better, but it accomplishes its purpose. +The key argument \code{layout}, the first, is a vector of numbers. +The value (1,3,4,2) for instance has a single state, then a column with 3 +states, then a column with 4, then a column with 2. +If \code{layout} is instead a 1 column matrix then do the same from top +down. If it is a 2 column matrix then they provided their own spacing. + +<>= +statefig <- function(layout, connect, margin=.03, box=TRUE, + cex=1, col=1, lwd=1, lty=1, bcol= col, + acol=col, alwd = lwd, alty= lty, offset=0) { + # set up an empty canvas + frame(); # new environment + par(usr=c(0,1,0,1)) + if (!is.numeric(layout)) + stop("layout must be a numeric vector or matrix") + if (!is.matrix(connect) || nrow(connect) != ncol(connect)) + stop("connect must be a square matrix") + nstate <- nrow(connect) + dd <- dimnames(connect) + if (!is.null(dd[[1]])) statenames <- dd[[1]] + else if (is.null(dd[[2]])) + stop("connect must have the state names as dimnames") + else statenames <- dd[[2]] + + # expand out all of the graphical parameters. This lets users + # use a vector of colors, line types, etc + narrow <- sum(connect!=0) + acol <- rep(acol, length=narrow) + alwd <- rep(alwd, length=narrow) + alty <- rep(alty, length=narrow) + + bcol <- rep(bcol, length=nstate) + lty <- rep(lty, length=nstate) + lwd <- rep(lwd, length=nstate) + + col <- rep(col, length=nstate) # text colors + + <> + <> + <> + + dimnames(cbox) <- list(statenames, c("x", "y")) + invisible(cbox) +} +<> +@ + +The drawing region is always (0,1) by (0,1). +A user can enter their own matrix of coordinates. +Otherwise the free space is divided with one portion +on each end and 2 portions between boxes. If there were 3 columns for +instance they will have x coordinates of 1/6, 1/6 + 1/3, 1/6 + 2/3. Ditto +for dividing up the y coordinate. The primary nuisance is that we want to +count down from the top instead of up from the bottom. A 1 by 1 matrix is +treated as a column matrix. + +<>= +if (is.matrix(layout) && ncol(layout)==2 && nrow(layout) > 1) { + # the user provided their own + if (any(layout <0) || any(layout >1)) + stop("layout coordinates must be between 0 and 1") + if (nrow(layout) != nstate) + stop("layout matrix should have one row per state") + cbox <- layout +} +else { + if (any(layout <=0 | layout != floor(layout))) + stop("non-integer number of states in layout argument") + space <- function(n) (1:n -.5)/n # centers of the boxes + if (sum(layout) != nstate) stop("number of boxes != number of states") + cbox <- matrix(0, ncol=2, nrow=nstate) #coordinates will be here + n <- length(layout) + + ix <- rep(seq(along=layout), layout) + if (is.vector(layout) || ncol(layout)> 1) { #left to right + cbox[,1] <- space(n)[ix] + for (i in 1:n) cbox[ix==i,2] <- 1 -space(layout[i]) + } else { # top to bottom + cbox[,2] <- 1- space(n)[ix] + for (i in 1:n) cbox[ix==i,1] <- space(layout[i]) + } +} +@ + +Write the text out. Compute the width and height of each box. +Then compute the margin. The only tricky thing here is that we want +the area around the text to \emph{look} the same left-right and up-down, +which depends on the geometry of the plotting region. + +<>= +text(cbox[,1], cbox[,2], statenames, cex=cex, col=col) # write the labels +textwd <- strwidth(statenames, cex=cex) +textht <- strheight(statenames, cex=cex) +temp <- par("pin") #plot region in inches +dx <- margin * temp[2]/mean(temp) # extra to add in the x dimension +dy <- margin * temp[1]/mean(temp) # extra to add in y + +if (box) { + drawbox <- function(x, y, dx, dy, lwd, lty, col) { + lines(x+ c(-dx, dx, dx, -dx, -dx), + y+ c(-dy, -dy, dy, dy, -dy), lwd=lwd, lty=lty, col=col) + } + for (i in 1:nstate) + drawbox(cbox[i,1], cbox[i,2], textwd[i]/2 + dx, textht[i]/2 + dy, + col=bcol[i], lwd=lwd[i], lty=lty[i]) + dx <- 2*dx; dy <- 2*dy # move arrows out from the box + } +@ + +Now for the hard part, which is drawing the arrows. +The entries in the connection matrix are 0= no connection or $1+d$ for +$-1 < d < 1$. The connection is an arc that passes from the center of +box 1 to the center of box 2, and through a point that is $dz$ units above +the midpoint of the line from box 1 to box 2, where $2z$ is the length +of that line. +For $d=1$ we get a half circle to the right (with respect to traversing the +line from A to B) and for $d= -1$ we get a half circle to the left. +If $d=0$ it is a straight line. + +If A and B are the starting and ending points then AB is the chord of a +circle. Draw radii from the center to A, B, and through the midpoint $c$ of +AB. This last has length $dz$ above the chord and $r- dz$ below where $r$ +is the radius. Then we have +\begin{align*} + r^2 & = z^2 + (r-dz)^2 \\ + 2rdz &= z^2 + (dz)^2 \\ + r &= \left[z (1+ d^2) \right ]/ 2d +\end{align*} +Be careful with negative $d$, which is used to denote left-hand arcs. + +The angle $\theta$ from A to B is the arctan of $B-A$, +and the center of the circle is at +$C = (A+B)/2 + (r - dz)(\sin \theta, -\cos \theta)$. +We then need to draw the arc $C + r(\cos \phi, \sin \phi)$ for some range +of angles $\phi$. +The angles to the centers of the boxes are $\arctan(A-C)$ and $\arctan(B-C)$, +but we want to start and end outside the box. +It turned out that this is more subtle than I thought. +The solution below uses two helper functions \code{statefigx} and +\code{statefigy}. +The first accepts $C$, $r$, the range of $\phi$ values, and a target +$y$ value. It returns the angles, within the range, such that the +endpoint of the arc has horizontal coordinate $x$, or an empty +vector if none such exists. For an arc there are sometimes two +solutions. +First calculate the angles for which the arc will strike the horizontal +line. If the arc is too short to reach the line then there is no +intersection. +The return legal angles. +<>= +statefigx <- function(x, C, r, a1, a2) { + temp <-(x - C[1])/r + if (abs(temp) >1) return(NULL) # no intersection of the arc and x + phi <- acos(temp) # this will be from 0 to pi + pi <- 3.1415926545898 # in case someone has a variable "pi" + if (x > C[1]) phi <- c(phi, pi - phi) + else phi <- -c(phi, pi - phi) + # Add reflection about the X axis, in both forms + phi <- c(phi, -phi, 2*pi - phi) + amax <- max(a1, a2) + amin <- min(a1, a2) + phi[phi amin] +} +statefigy <- function(y, C, r, a1, a2) { + pi <- 3.1415926545898 # in case someone has a variable named "pi" + amax <- max(a1, a2) + amin <- min(a1, a2) + temp <-(y - C[2])/r + if (abs(temp) >1) return(NULL) # no intersection of the arc and y + phi <- asin(temp) # will be from -pi/2 to pi/2 + phi <- c(phi, sign(phi)*pi -phi) # reflect about the vertical + phi <- c(phi, phi + 2*pi) + phi[phi amin] +} +@ + +<>= +phi <- function(x1, y1, x2, y2, d, delta1, delta2) { + # d = height above the line + theta <- atan2(y2-y1, x2-x1) # angle from center to center + if (abs(d) < .001) d=.001 # a really small arc looks like a line + + z <- sqrt((x2-x1)^2 + (y2 - y1)^2) /2 # half length of chord + ab <- c((x1 + x2)/2, (y1 + y2)/2) # center of chord + r <- abs(z*(1 + d^2)/ (2*d)) + if (d >0) C <- ab + (r - d*z)* c(-sin(theta), cos(theta)) # center of arc + else C <- ab + (r + d*z)* c( sin(theta), -cos(theta)) + + a1 <- atan2(y1-C[2], x1-C[1]) # starting angle + a2 <- atan2(y2-C[2], x2-C[1]) # ending angle + if (abs(a2-a1) > pi) { + # a1= 3 and a2=-3, we don't want to include 0 + # nor for a1=-3 and a2=3 + if (a1>0) a2 <- a2 + 2 *pi + else a1 <- a1 + 2*pi + } + if (d > 0) { #counterclockwise + phi1 <- min(statefigx(x1 + delta1[1], C, r, a1, a2), + statefigx(x1 - delta1[1], C, r, a1, a2), + statefigy(y1 + delta1[2], C, r, a1, a2), + statefigy(y1 - delta1[2], C, r, a1, a2), na.rm=TRUE) + phi2 <- max(statefigx(x2 + delta2[1], C, r, a1, a2), + statefigx(x2 - delta2[1], C, r, a1, a2), + statefigy(y2 + delta2[2], C, r, a1, a2), + statefigy(y2 - delta2[2], C, r, a1, a2), na.rm=TRUE) + } + else { # clockwise + phi1 <- max(statefigx(x1 + delta1[1], C, r, a1, a2), + statefigx(x1 - delta1[1], C, r, a1, a2), + statefigy(y1 + delta1[2], C, r, a1, a2), + statefigy(y1 - delta1[2], C, r, a1, a2), na.rm=TRUE) + phi2 <- min(statefigx(x2 + delta2[1], C, r, a1, a2), + statefigx(x2 - delta2[1], C, r, a1, a2), + statefigy(y2 + delta2[2], C, r, a1, a2), + statefigy(y2 - delta2[2], C, r, a1, a2), na.rm=TRUE) + } + + list(center=C, angle=c(phi1, phi2), r=r) +} +@ + +Now draw the arrows, one at a time. I arbitrarily declare that 20 +segments is enough for a smooth curve. +<>= +arrow2 <- function(...) arrows(..., angle=20, length=.1) +doline <- function(x1, x2, d, delta1, delta2, lwd, lty, col) { + if (d==0 && x1[1] ==x2[1]) { # vertical line + if (x1[2] > x2[2]) # downhill + arrow2(x1[1], x1[2]- delta1[2], x2[1], x2[2] + delta2[2], + lwd=lwd, lty=lty, col=col) + else arrow2(x1[1], x1[2]+ delta1[2], x2[1], x2[2] - delta2[2], + lwd=lwd, lty=lty, col=col) + } + else if (d==0 && x1[2] == x2[2]) { # horizontal line + if (x1[1] > x2[1]) # right to left + arrow2(x1[1]-delta1[1], x1[2], x2[1] + delta2[1], x2[2], + lwd=lwd, lty=lty, col=col) + else arrow2(x1[1]+delta1[1], x1[2], x2[1] - delta2[1], x2[2], + lwd=lwd, lty=lty, col=col) + } + else { + temp <- phi(x1[1], x1[2], x2[1], x2[2], d, delta1, delta2) + if (d==0) { + arrow2(temp$center[1] + temp$r*cos(temp$angle[1]), + temp$center[2] + temp$r*sin(temp$angle[1]), + temp$center[1] + temp$r*cos(temp$angle[2]), + temp$center[2] + temp$r*sin(temp$angle[2]), + lwd=lwd, lty=lty, col=col) + } + else { + # approx the curve with 21 segments + # arrowhead on the last one + phi <- seq(temp$angle[1], temp$angle[2], length=21) + lines(temp$center[1] + temp$r*cos(phi), + temp$center[2] + temp$r*sin(phi), lwd=lwd, lty=lty, col=col) + arrow2(temp$center[1] + temp$r*cos(phi[20]), + temp$center[2] + temp$r*sin(phi[20]), + temp$center[1] + temp$r*cos(phi[21]), + temp$center[2] + temp$r*sin(phi[21]), + lwd=lwd, lty=lty, col=col) + } + } +} +@ +The last arrow bit is the offset. If offset $\ne 0$ and there is a +bidirectional +arrow between two boxes, and the arc for both of them is identical, +then move each arrow just a bit, orthagonal to a segment connecting the middle +of the two boxes. +If the line goes from (x1, y1) to (x2, y2), then the normal to the line at +(x1, x2) is (y2-y1, x1-x2), normalized to length 1. +The -1 below (\code{-offset}) makes the shift obey a left-hand rule: looking +down a line segement towards the arrow head, we shift to the left. +This makes two horizontal arrows stack in the normal typographical order +for chemical reactions, the right facing one above the left facing. +A user can use a negative value for offset to reverse this if they wish. + +<>= +k <- 1 +for (j in 1:nstate) { + for (i in 1:nstate) { + if (i != j && connect[i,j] !=0) { + if (connect[i,j] == 2-connect[j,i] && offset!=0) { + #add an offset + toff <- c(cbox[j,2] - cbox[i,2], cbox[i,1] - cbox[j,1]) + toff <- -offset *toff/sqrt(sum(toff^2)) + doline(cbox[i,]+toff, cbox[j,]+toff, connect[i,j]-1, + delta1 = c(textwd[i]/2 + dx, textht[i]/2 + dy), + delta2 = c(textwd[j]/2 + dx, textht[j]/2 + dy), + lty=alty[k], lwd=alwd[k], col=acol[k]) + } + else doline(cbox[i,], cbox[j,], connect[i,j]-1, + delta1 = c(textwd[i]/2 + dx, textht[i]/2 + dy), + delta2 = c(textwd[j]/2 + dx, textht[j]/2 + dy), + lty=alty[k], lwd=alwd[k], col=acol[k]) + k <- k +1 + } + } +} +@ +\section{tmerge} +The tmerge function was designed around a set of specific problems. +The idea is to build up a time dependent data set one endpoint at at time. +The primary arguments are +\begin{itemize} + \item data1: the base data set that will be added onto + \item data2: the source for new information + \item id: the subject identifier in the new data + \item \ldots: additional arguments that add variables to the data set + \item tstart, tstop: used to set the time range for each subject + \item options +\end{itemize} +The created data set has three new variables (at least), which are +\code{id}, \code{tstart} and \code{tstop}. + +The key part of the call are the ``\ldots'' arguments +which each can be one of four types: +tdc() and cumtdc() add a time dependent variable, event() and cumevent() +add a new endpoint. +In the survival routines time intervals are open on the left and +closed on the right, i.e., (tstart, tstop]. +Time dependent covariates apply from the start of an interval and events +occur at the end of an interval. +If a data set already had intervals of (0,10] and (10, 14] a new time +dependent covariate or event at time 8 would lead to three intervals of +(0,8], (8,10], and (10,14]; +the new time-dependent covariate value would be added to the second interval, +a new event would be added to the first one. + +A typical call would be +<>= + newdata <- tmerge(newdata, old, id=clinic, diabetes=tdc(diab.time)) +@ +which would add a new time dependent covariate \code{diabetes} to the +data set. + +<>= +tmerge <- function(data1, data2, id, ..., tstart, tstop, options) { + Call <- match.call() + # The function wants to recognize special keywords in the + # arguments, so define a set of functions which will be used to + # mark objects + new <- new.env(parent=parent.frame()) + assign("tdc", function(time, value=NULL, init=NULL) { + x <- list(time=time, value=value, default= init); + class(x) <- "tdc"; x}, + envir=new) + assign("cumtdc", function(time, value=NULL, init=NULL) { + x <- list(time=time, value=value, default= init); + class(x) <-"cumtdc"; x}, + envir=new) + assign("event", function(time, value=NULL, censor=NULL) { + x <- list(time=time, value=value, censor=censor); + class(x) <-"event"; x}, + envir=new) + assign("cumevent", function(time, value=NULL, censor=NULL) { + x <- list(time=time, value=value, censor=censor); + class(x) <-"cumevent"; x}, + envir=new) + + if (missing(data1) || missing(data2) || missing(id)) + stop("the data1, data2, and id arguments are required") + if (!inherits(data1, "data.frame")) stop("data1 must be a data frame") + <> + <> + <> +} +<> +@ + +The program can't use formulas because the \ldots arguments need to be +named. This results in a bit of evaluation magic to correctly assess +arguments. +The routine below could have been set out as a separate top-level routine, +the argument is where we want to document it: within the tmerge page or +on a separate one. +I decided on the former. +<>= +tmerge.control <- function(idname="id", tstartname="tstart", tstopname="tstop", + delay =0, na.rm=TRUE, tdcstart=NA_real_, ...) { + extras <- list(...) + if (length(extras) > 0) + stop("unrecognized option(s):", paste(names(extras), collapse=', ')) + if (length(idname) != 1 || make.names(idname) != idname) + stop("idname option must be a valid variable name") + if (!is.null(tstartname) && + (length(tstartname) !=1 || make.names(tstartname) != tstartname)) + stop("tstart option must be NULL or a valid variable name") + if (length(tstopname) != 1 || make.names(tstopname) != tstopname) + stop("tstop option must be a valid variable name") + if (length(delay) !=1 || !is.numeric(delay) || delay < 0) + stop("delay option must be a number >= 0") + if (length(na.rm) !=1 || ! is.logical(na.rm)) + stop("na.rm option must be TRUE or FALSE") + if (length(tdcstart) !=1) stop("tdcstart must be a single value") + list(idname=idname, tstartname=tstartname, tstopname=tstopname, + delay=delay, na.rm=na.rm, tdcstart=tdcstart) +} + +if (!inherits(data1, "tmerge") && !is.null(attr(data1, "tname"))) { + # old style object that someone saved! + tm.retain <- list(tname = attr(data1, "tname"), + tevent= list(name=attr(data1, "tevent"), + censor= attr(data1, "tcensor")), + tdcvar = attr(data1, "tdcvar"), + n = nrow(data1)) + attr(data1, "tname") <- attr(data1, "tevent") <- NULL + attr(data1, "tcensor") <- attr(data1, "tdcvar") <- NULL + attr(data1, "tm.retain") <- tm.retain + class(data1) <- c("tmerge", class(data1)) +} + +if (inherits(data1, "tmerge")) { + tm.retain <- attr(data1, "tm.retain") + firstcall <- FALSE + # check out whether the object looks legit: + # has someone tinkered with it? This won't catch everything + tname <- tm.retain$tname + tevent <- tm.retain$tevent + tdcvar <- tm.retain$tdcvar + if (nrow(data1) != tm.retain$n) + stop("tmerge object has been modified, size") + if (any(is.null(match(unlist(tname), names(data1)))) || + any(is.null(match(tm.retain$tcdname, names(data1)))) || + any(is.null(match(tevent$name, names(data1))))) + stop("tmerge object has been modified, missing variables") + for (i in seq(along=tevent$name)) { + ename <- tevent$name[i] + if (is.numeric(data1[[ename]])) { + if (!is.numeric(tevent$censor[[i]])) + stop("event variable ", ename, + " no longer matches it's original class") + } + else if (is.character(data1[[ename]])) { + if (!is.character(tevent$censor[[i]])) + stop("event variable ", ename, + " no longer matches it's original class") + } + else if (is.logical(data1[[ename]])) { + if (!is.logical(tevent$censor[[i]])) + stop("event variable ", ename, + " no longer matches it's original class") + } + else if (is.factor(data1[[ename]])) { + if (levels(data1[[ename]])[1] != tevent$censor[[i]]) + stop("event variable ", ename, + " has a new first level") + } + else stop("event variable ", ename, " is of an invalid class") + } +} else { + firstcall <- TRUE + tname <- tevent <- tdcvar <- NULL + if (is.name(Call[["id"]])) { + idx <- as.character(Call[["id"]]) + if (missing(options)) options <-list(idname= idx) + else if (is.null(options$idname)) options$idname <- idx + } +} + +if (!missing(options)) { + if (!is.list(options)) stop("options must be a list") + if (!is.null(tname)) { + # If an option name matches one already in tname, don't confuse + # the tmerge.control routine with duplicate arguments + temp <- match(names(options), names(tname), nomatch=0) + topt <- do.call(tmerge.control, c(options, tname[temp==0])) + if (any(temp >0)) { + # A variable name is changing midstream, update the + # variable names in data1 + varname <- tname[c("idname", "tstartname", "tstopname")] + temp2 <- match(varname, names(data1)) + names(data1)[temp2] <- varname + } + } + else topt <- do.call(tmerge.control, options) +} +else if (length(tname)) topt <- do.call(tmerge.control, tname) +else topt <- tmerge.control() + +# id, tstart, tstop are found in data2 +if (missing(id)) stop("the id argument is required") +if (missing(data1) || missing(data2)) + stop("two data sets are required") +id <- eval(Call[["id"]], data2, enclos=emptyenv()) #don't find it elsewhere +if (is.null(id)) stop("id variable not found in data2") +if (any(is.na(id))) stop("id variable cannot have missing values") + +if (firstcall) { + if (!missing(tstop)) { + tstop <- eval(Call[["tstop"]], data2) + if (length(tstop) != length(id)) + stop("tstop and id must be the same length") + # The neardate routine will check for legal tstop data type + } + if (!missing(tstart)) { + tstart <- eval(Call[["tstart"]], data2) + if (length(tstart)==1) tstart <- rep(tstart, length(id)) + if (length(tstart) != length(id)) + stop("tstart and id must be the same length") + if (any(tstart >= tstop)) + stop("tstart must be < tstop") + } +} +else { + if (!missing(tstart) || !missing(tstop)) + stop("tstart and tstop arguments only apply to the first call") +} +@ + +Get the \ldots arguments. They are evaluated in a special frame, +set up earlier, so that the definitions of the functions tdc, +cumtdc, event, and cumevent are local to tmerge. +Check that they are all legal: each argument is named, and is one of the four +allowed types. +<>= +# grab the... arguments +notdot <- c("data1", "data2", "id", "tstart", "tstop", "options") +dotarg <- Call[is.na(match(names(Call), notdot))] +dotarg[[1]] <- as.name("list") # The as-yet dotarg arguments +if (missing(data2)) args <- eval(dotarg, envir=new) +else args <- eval(dotarg, data2, enclos=new) + +argclass <- sapply(args, function(x) (class(x))[1]) +argname <- names(args) +if (any(argname== "")) stop("all additional argments must have a name") + +check <- match(argclass, c("tdc", "cumtdc", "event", "cumevent")) +if (any(is.na(check))) + stop(paste("argument(s)", argname[is.na(check)], + "not a recognized type")) +@ + +The tcount matrix keeps track of what we have done, and is added to +the final object at the end. +This is useful to the user for debugging what may have gone right or +wrong in their usage. + +<>= +# The tcount matrix is useful for debugging +tcount <- matrix(0L, length(argname), 9) +dimnames(tcount) <- list(argname, c("early","late", "gap", "within", + "boundary", "leading", "trailing", + "tied", "missid")) +tcens <- tevent$censor +tevent <- tevent$name +if (is.null(tcens)) tcens <- vector('list', 0) +@ + +The very first call to the routine is special, since this is when the +range of legal times is set. We also apply an initial sort to the data +if necessary so that times are in order. +There are 2 cases: +\begin{enumerate} + \item Adding a time range: tstop comes from data2, optional tstart, and the + id can be simply matched, by which we mean no duplicates in data1. + \item The more common case: there is no tstop, one observation per subject, + and the first optional argument is an + event or cumevent. We then use its time as the range. +\end{enumerate} +One thing we could add, but didn't, was to warn if any of the three new +variables will stomp on ones already in data1. + +Note that in case 2 we cannot wait for the later code to deal with duplicate +id/time pairs, since that later code requires a valid starting point. That +code will work out which of a duplicate should be retained, however. + +<>= +newdata <- data1 #make a copy +if (firstcall) { + # We don't look for topt$id. What if the user had id=clinic, but their + # starting data set also had a variable named "id". We want clinic for + # this first call. + idname <- Call[["id"]] + if (!is.name(idname)) + stop("on the first call 'id' must be a single variable name") + + # The line below finds tstop and tstart variables in data1 + indx <- match(c(topt$idname, topt$tstartname, topt$tstopname), names(data1), + nomatch=0) + if (any(indx[1:2]>0) && FALSE) { # warning currently turned off. Be chatty? + overwrite <- c(topt$tstartname, topt$tstopname)[indx[2:3]] + warning("overwriting data1 variables", paste(overwrite, collapse=' ')) + } + + temp <- as.character(idname) + if (!is.na(match(temp, names(data1)))) { + data1[[topt$idname]] <- data1[[temp]] + baseid <- data1[[temp]] + } + else stop("id variable not found in data1") + + if (any(duplicated(baseid))) + stop("for the first call (that establishes the time range) data1 must have no duplicate identifiers") + + if (missing(tstop)) { + if (length(argclass)==0 || argclass[1] != "event") + stop("neither a tstop argument nor an initial event argument was found") + # this is case 2 -- the first time value for each obs sets the range + last <- !duplicated(id) + indx2 <- match(unique(id[last]), baseid) + if (any(is.na(indx2))) + stop("setting the range, and data2 has id values not in data1") + if (any(is.na(match(baseid, id)))) + stop("setting the range, and data1 has id values not in data2") + newdata <- data1[indx2,] + tstop <- (args[[1]]$time)[last] + } + else { + if (length(baseid)== length(id) && all(baseid == id)) newdata <- data1 + else { # Note: 'id' is the idlist for data 2 + indx2 <- match(id, baseid) + if (any(is.na(indx2))) + stop("setting the range, and data2 has id values not in data1") + if (any(is.na(match(baseid, id)))) + stop("setting the range, and data1 has id values not in data2") + newdata <- data1[indx2,] + } + } + + if (any(is.na(tstop))) + stop("missing time value, when that variable defines the span") + if (missing(tstart)) { + indx <- which(tstop <=0) + if (length(indx) >0) stop("found an ending time of ", tstop[indx[1]], + ", the default starting time of 0 is invalid") + tstart <- rep(0, length(tstop)) + } + if (any(tstart >= tstop)) + stop("tstart must be < tstop") + newdata[[topt$tstartname]] <- tstart + newdata[[topt$tstopname]] <- tstop + n <- nrow(newdata) + if (any(duplicated(id))) { + # sort by time within id + indx1 <- match(id, unique(id)) + newdata <- newdata[order(indx1, tstop),] + } + temp <- newdata[[topt$idname]] + if (any(tstart >= tstop)) stop("tstart must be < tstop") + if (any(newdata$tstop[-n] > newdata$tstart[-1] & + temp[-n] == temp[-1])) + stop("first call has created overlapping or duplicated time intervals") + idmiss <- 0 # the tcount table should have a zero +} +else { #not a first call + idmatch <- match(id, data1[[topt$idname]], nomatch=0) + if (any(idmatch==0)) idmiss <- sum(idmatch==0) + else idmiss <- 0 +} +@ + +Now for the real work. For each additional argument we first match the +id/time pairs of the new data to the current data set, and categorize +each into a type. If the time value in data2 is NA, then that +addition is skipped. Ditto if the value is NA and options narm=TRUE. +This is a convenience for the user, who will often +be merging in a variable like ``day of first diabetes diagnosis'' which +is missing for those who never had that outcome occur. +<>= +saveid <- id +for (ii in seq(along.with=args)) { + argi <- args[[ii]] + baseid <- newdata[[topt$idname]] + dstart <- newdata[[topt$tstartname]] + dstop <- newdata[[topt$tstopname]] + argcen <- argi$censor + + # if an event time is missing then skip that obs. Also toss obs that + # whose id does not match anyone in data1 + etime <- argi$time + if (idmiss ==0) keep <- rep(TRUE, length(etime)) + else keep <- (idmatch > 0) + if (length(etime) != length(saveid)) + stop("argument ", argname[ii], " is not the same length as id") + if (!is.null(argi$value)) { + if (length(argi$value) != length(saveid)) + stop("argument ", argname[ii], " is not the same length as id") + if (topt$na.rm) keep <- keep & !(is.na(etime) | is.na(argi$value)) + else keep <- keep & !is.na(etime) + if (!all(keep)) { + etime <- etime[keep] + argi$value <- argi$value[keep] + } + } + else { + keep <- keep & !is.na(etime) + etime <- etime[keep] + } + id <- saveid[keep] + + # Later steps become easier if we sort the new data by id and time + # The match() is critical when baseid is not in sorted order. The + # etime part of the sort will change from one ii value to the next. + indx <- order(match(id, baseid), etime) + id <- id[indx] + etime <- etime[indx] + if (!is.null(argi$value)) + yinc <- argi$value[indx] + else yinc <- NULL + + # indx1 points to the closest start time in the baseline data (data1) + # that is <= etime. indx2 to the closest end time that is >=etime. + # If etime falls into a (tstart, tstop) interval, indx1 and indx2 + # will match + # If the "delay" argument is set and this event is of type tdc, then + # move any etime that is after the entry time for a subject. + if (topt$delay >0 && argclass[ii] %in% c("tdc", "cumtdc")) { + mintime <- tapply(dstart, baseid, min) + index <- match(id, names(mintime)) + etime <- ifelse(etime <= mintime[index], etime, etime+ topt$delay) + } + + indx1 <- neardate(id, baseid, etime, dstart, best="prior") + indx2 <- neardate(id, baseid, etime, dstop, best="after") + + # The event times fall into one of 5 categories + # 1. Before the first interval + # 2. After the last interval + # 3. Outside any interval but with time span, i.e, it falls into + # a gap in follow-up + # 4. Strictly inside an interval (does't touch either end) + # 5. Inside an interval, but touching. + itype <- ifelse(is.na(indx1), 1, + ifelse(is.na(indx2), 2, + ifelse(indx2 > indx1, 3, + ifelse(etime== dstart[indx1] | + etime== dstop[indx2], 5, 4)))) + + # Subdivide the events that touch on a boundary + # 1: intervals of (a,b] (b,d], new count at b "tied edge" + # 2: intervals of (a,b] (c,d] with c>b, new count at c, "front edge" + # 3: intervals of (a,b] (c,d] with c>b, new count at b, "back edge" + # + subtype <- ifelse(itype!=5, 0, + ifelse(indx1 == indx2+1, 1, + ifelse(etime==dstart[indx1], 2, 3))) + tcount[ii,1:7] <- table(factor(itype+subtype, levels=c(1:4, 6:8))) + + # count ties. id and etime are not necessarily sorted + tcount[ii,8] <- sum(tapply(etime, id, function(x) sum(duplicated(x)))) + tcount[ii,9] <- idmiss + <> +} +@ + +A \code{tdc} or \code{cumtdc} operator defines a new time-dependent +variable which applies to all future times. +Say that we had the following scenario for one subject +\begin{center} + \begin{tabular}{rr|rr} + \multicolumn{2}{c}{current} & \multicolumn{2}{c}{addition} \\ + tstart & tstop & time & x \\ + 2 & 5 & 1 & 20.2 \\ + 6 & 7 & 7 & 11 \\ + 7 & 15 & 8 & 17.3 \\ + 15 & 30 \\ + \end{tabular} + \end{center} +The resulting data set will have intervals of (2,5), (6,7), (7,8) and (8,15) +with covariate values of 20.2, 20.2, 11, and 17.3. +Only a covariate change that occurs within an interval causes a new data +row. Covariate changes that happen after the last interval are ignored, +i.e. at change at time $\ge 30$ in the above example. + +If instead this had been events at times 1, 7, and 8, the first event would +be ignored since it happens outside of any interval, so would an event +at exactly time 2. The event at time +7 would be recorded in the (6,7) interval and the one at time 8 in the +(7,8) interval: events happen at the ends of intervals. +In both cases new rows are only generated for new time values that fall +strictly within one of the old intervals. + +When a subject has two increments on the same day the later one wins. +This is correct behavior for cumtdc, a bit odd for cumevent, and the +user's problem for tdc and event. +We report back the number of ties so that the user can deal with it. + +Where are we now with the variables? +\begin{center} + \begin{tabular}{cccc} + itype& class & indx1 & indx2 \\ \hline + 1 & before & NA & next interval \\ + 2 & after & prior interval & NA \\ + 3 & in a gap & prior interval & next interval \\ + 4 & within interval & containing interval & containing interval \\ + 5-1 & on a join & next interval & prior interval \\ + 5-2 & front edge & containing & containing \\ + 5-3 & back edge & containing & containing \\ + \end{tabular} +\end{center} +If there are any itype 4, start by expanding the data set to add +new cut points, which will turn all the 4's into 5-1 types. +When expanding, all the event type variables turn into ``censor'' at the +newly added times and other variables stay the same. +A subject could have more than one new cutpoint added within an interval +so we have to count each. +In newdata all the rows for a given subject are contiguous and in time +order, though the data set may not be in subject order. +<>= +indx4 <- which(itype==4) +n4 <- length(indx4) +if (n4 > 0) { + # we need to eliminate duplicate times within the same id, but + # do so without changing the class of etime: it might + # be a Date, an integer, a double, ... + # Using unique on a data.frame does the trick + icount <- data.frame(irow= indx1[indx4], etime=etime[indx4]) + icount <- unique(icount) + # the icount data frame will be sorted by second column within first + # so rle is faster than table + n.add <- rle(icount$irow)$length # number of rows to add for each id + + # expand the data + irep <- rep.int(1L, nrow(newdata)) + erow <- unique(indx1[indx4]) # which rows in newdata to be expanded + irep[erow] <- 1+ n.add # number of rows in new data + jrep <- rep(1:nrow(newdata), irep) #stutter the duplicated rows + newdata <- newdata[jrep,] #expand it out + dstart <- dstart[jrep] + dstop <- dstop[jrep] + + #fix up times + nfix <- length(erow) + temp <- vector("list", nfix) + iend <- (cumsum(irep))[irep >1] #end row of each duplication set + for (j in 1:nfix) temp[[j]] <- -(seq(n.add[j] -1, 0)) + iend[j] + newrows <- unlist(temp) + + dstart[newrows] <- dstop[newrows-1] <- icount$etime + newdata[[topt$tstartname]] <- dstart + newdata[[topt$tstopname]] <- dstop + for (ename in tevent) newdata[newrows-1, ename] <- tcens[[ename]] + + # refresh indices + baseid <- newdata[[topt$idname]] + indx1 <- neardate(id, baseid, etime, dstart, best="prior") + indx2 <- neardate(id, baseid, etime, dstop, best="after") + subtype[itype==4] <- 1 #all the "insides" are now on a tied edge + itype[itype==4] <- 5 +} +@ + +Now we can add the new variable. +The most common is a tdc, so start with it. +The C routine returns a set of indices: 0,1,1,2,3,0,4,... would mean that +row 1 of the new data happens before the tdc variable, 2 and 3 take values from +the first element of yinc, etc. +By returning an index, the yinc variable can be of any data type. Using +is.na() on the left side below causes the \emph{right} kind of NA to be inserted +(this trick was stolen from the merge routine). + +If this is a first call, don't allow the new variable to overwrite a variable +already existing in the data set, we found it leads to problems. (Usually it +is a user mistake.) However, tdc calls themselves can stack. + +<>= +# add a tdc variable +newvar <- newdata[[argname[ii]]] # prior value (for sequential tmerge calls) +if (argclass[ii] %in% c("tdc", "cumtdc")){ + if (argname[[ii]] %in% tevent) + stop("attempt to turn event variable", argname[[ii]], "into a tdc") + if (!(argname[[ii]] %in% tdcvar)){ + tdcvar <- c(tdcvar, argname[[ii]]) + if (!is.null(newvar) && argclass[ii] == "tdc") { + warning(paste0("replacement of variable '", argname[ii], "'")) + newvar <- NULL + } + } +} +if (argclass[ii] == "tdc") { + default <- argi$default # default value + if (is.null(default)) default <- topt$tdcstart + else if (length(default) !=1) + stop("initial tdc value must be of length 1") + + # id can be any data type; feed integers to the C routine + storage.mode(dstart) <- storage.mode(etime) <- "double" #if time is integer + uid <- unique(baseid) + index <- .Call(Ctmerge2, match(baseid, uid), dstart, + match(id, uid), etime) + + if (!is.null(yinc)) newvar <- NULL # a tdc can't be updated, other than 0/1 + if (is.null(newvar)) { + if (is.null(yinc)) newvar <- ifelse(index==0, 0L, 1L) #add a 0/1 variable + else { + newvar <- yinc[pmax(1L, index)] + if (any(index==0)) { + if (is.na(default)) is.na(newvar) <- (index==0L) + else { + if (is.numeric(newvar)) newvar[index==0L] <- as.numeric(default) + else { + if (is.factor(newvar)) { + # special case: if default isn't in the set of levels, + # add it to the levels + if (is.na(match(default, levels(newvar)))) + levels(newvar) <- c(levels(newvar), default) + } + newvar[index== 0L] <- default + } + } + } + } + } else { + # update a 0/1 variable + if (is.integer(newvar) && all(newvar==0L | newvar==1L)) + newvar[index!=0L] <- 1L + else stop("tdc update does not match prior variable type: ", argname[ii]) + } + tdcvar <- unique(c(tdcvar, argname[[ii]])) +} +@ + +Events and cumevents are easy because +each affects only one interval. +<>= +# add events +if (argclass[ii] %in% c("cumtdc", "cumevent")) { + if (is.null(yinc)) yinc <- rep(1L, length(id)) + else if (is.logical(yinc)) yinc <- as.numeric(yinc) # allow cumulative T/F + if (!is.numeric(yinc)) stop("invalid increment for cumtdc or cumevent") +} +if (argclass[ii] == "cumevent"){ + ykeep <- (yinc !=0) # ignore the addition of a censoring event + yinc <- unlist(tapply(yinc, match(id, baseid), cumsum)) +} + +if (argclass[ii] %in% c("event", "cumevent")) { + if (!is.null(newvar)) { + if (!argname[ii] %in% tevent) { + #warning(paste0("non-event variable '", argname[ii], "' replaced by an event variable")) + newvar <- NULL + } + else if (!is.null(yinc)) { + if (class(newvar) != class(yinc)) + stop("attempt to update an event variable with a different type") + if (is.factor(newvar) && !all(levels(yinc) %in% levels(newvar))) + stop("attemp to update an event variable and levels do not match") + } + } + + if (is.null(yinc)) yinc <- rep(1L, length(id)) + if (is.null(newvar)) { + if (is.numeric(yinc)) newvar <- rep(0L, nrow(newdata)) + else if (is.factor(yinc)) + newvar <- factor(rep(levels(yinc)[1], nrow(newdata)), + levels(yinc)) + else if (is.character(yinc)) newvar <- rep('', nrow(newdata)) + else if (is.logical(yinc)) newvar <- rep(FALSE, nrow(newdata)) + else stop("invalid value for a status variable") + } + + keep <- (subtype==1 | subtype==3) # all other events are thrown away + if (argclass[ii] == "cumevent") keep <- (keep & ykeep) + newvar[indx2[keep]] <- yinc[keep] + + # add this into our list of 'this is an event type variable' + if (!(argname[ii] %in% tevent)) { + tevent <- c(tevent, argname[[ii]]) + if (is.factor(yinc)) tcens <- c(tcens, list(levels(yinc)[1])) + else if (is.logical(yinc)) tcens <- c(tcens, list(FALSE)) + else if (is.character(yinc)) tcens <- c(tcens, list("")) + else if (is.integer(yinc)) tcens <- c(tcens, list(0L)) + else tcens <- c(tcens, list(0)) + names(tcens) <- tevent + } +} + +else if (argclass[ii] == "cumtdc") { # process a cumtdc variable + # I don't have a good way to catch the reverse of this user error + if (argname[[ii]] %in% tevent) + stop("attempt to turn event variable", argname[[ii]], "into a cumtdc") + + keep <- itype != 2 # changes after the last interval are ignored + indx <- ifelse(subtype==1, indx1, + ifelse(subtype==3, indx2+1L, indx2)) + + # we want to pass the right kind of NA to the C code + default <- argi$default + if (is.null(default)) default <- as.numeric(topt$tdcstart) + else { + if (length(default) != 1) stop("tdc initial value must be of length 1") + if (!is.numeric(default)) stop("cumtdc initial value must be numeric") + } + if (is.null(newvar)) { # not overwriting a prior value + if (is.null(argi$value)) newvar <- rep(0.0, nrow(newdata)) + else newvar <- rep(default, nrow(newdata)) + } + + # the increment must be numeric + if (!is.numeric(newvar)) + stop("data and starting value do not agree on data type") + # id can be any data type; feed integers to the C routine + storage.mode(yinc) <- storage.mode(dstart) <- "double" + storage.mode(newvar) <- storage.mode(etime) <- "double" + newvar <- .Call(Ctmerge, match(baseid, baseid), dstart, newvar, + match(id, baseid)[keep], etime[keep], + yinc[keep], indx[keep]) +} + +newdata[[argname[ii]]] <- newvar +@ + +Finish up by adding the attributes and the class +<>= +tm.retain <- list(tname = topt[c("idname", "tstartname", "tstopname")], + n= nrow(newdata)) +if (length(tevent)) + tm.retain$tevent <- list(name = tevent, censor=tcens) +if (length(tdcvar)>0) tm.retain$tdcvar <- tdcvar +attr(newdata, "tm.retain") <- tm.retain +attr(newdata, "tcount") <- rbind(attr(data1, "tcount"), tcount) +attr(newdata, "call") <- Call + +row.names(newdata) <- NULL #These are a mess; kill them off. +# Not that it works: R just assigns new row names. +class(newdata) <- c("tmerge", "data.frame") +newdata +@ + +The summary routine is for checking: it simply prints out the attributes. +<>= +summary.tmerge <- function(object, ...) { + if (!is.null(cl <- attr(object, "call"))) { + cat("Call:\n") + dput(cl) + cat("\n") + } + + print(attr(object, "tcount")) +} + +# This could be smarter: if you only drop variables that are not known +# to tmerge then it would be okay. But I currently like the "touch it +# and it dies" philosophy +"[.tmerge" <- function(x, ..., drop=TRUE){ + class(x) <- "data.frame" + attr(x, "tm.retain") <- NULL + attr(x, "tcount") <- NULL + attr(x, "call") <- NULL + NextMethod(x) + } +@ +\section{Linear models and contrasts} +The primary contrast function is \code{yates}. +This function does both simple and population contrasts; the name is a nod +to the ``Yates weighted means'' method, the first population contrast that +I know of. +A second reason for the name is that +the word ``contrast'' is already overused in the S/R lexicon. +Both \code{yates} and \code{cmatrix} can be used with any model that returns +the necessary +portions, e.g., lm, coxph, or glm. +They were written because I became embroiled in the ``type III'' controversy, +and made it a goal to figure out what exactly it is that SAS does. +If I had known that that quest would take multiple years would +perhaps have never started. + +Population contrasts can result in some head scratching. +It is easy to create the predicted value for any hypothethical +subject from a model. +A population prediction holds some data values constant and lets the +others range over a population, giving a mean predicted value or +population average. +Population predictions for two treatments are the familiar g-estimates +of causal models. +We can take sums or differences of these predictions as well, e.g. to +ask if they are significantly different. +What can't be done is to work backwards from one of these contrasts to the +populations, at least for continuous variables. +If someone asks for an x contrast of 15-5 is this a sum of two population +estimates at 15 and -5, or a difference? +It's always hard to guess the mind of a user. +Therefore what is needed is a fitted model, the term (covariate) of interest, +levels of that covariate, a desired comparison, and a population. + +First is cmatrix routine. This is called by users to create a contrast +matrix for a model, users can also construct their own contrast matrices. +The result has two parts: the definition of a set of predicted values and +a set of contrasts between those values. +The routine requires a fit and a formula. The formula is simply a way to +get a set of variable names: all those variables are the fixed ones in +the population contrast, and all others form the ``population''. +The result will be a matrix or list that has a label +attribute containing the name of the term; this is used in printouts in the +obvious way. +Suppose that our model was \code{coxph(Surv(time, status) ~ age*sex + ph.ecog)}. +Someone might want the population matrix for age, sex, ph.ecog, or age+ sex. +For the last it doesn't matter if they say age+sex, age*sex, or age:sex. + +<>= +cmatrix <- function(fit, term, + test =c("global", "trend", "pairwise", "mean"), + levels, assign) { + # Make sure that "fit" is present and isn't missing any parts. + if (missing(fit)) stop("a fit argument is required") + Terms <- try(terms(fit), silent=TRUE) + + if (inherits(Terms, "try-error")) + stop("the fit does not have a terms structure") + else Terms <- delete.response(Terms) # y is not needed + Tatt <- attributes(Terms) + # a flaw in delete.response: it doesn't subset dataClasses + Tatt$dataClasses <- Tatt$dataClasses[row.names(Tatt$factors)] + test <- match.arg(test) + + if (missing(term)) stop("a term argument is required") + if (is.character(term)) term <- formula(paste("~", term)) + else if (is.numeric(term)) { + if (all(term == floor(term) & term >0 & term < length(Tatt$term.labels))) + term <- formula(paste("~", + paste(Tatt$term.labels[term], collapse='+'))) + else stop("a numeric term must be an integer between 1 and max terms in the fit") + } + else if (!inherits(term, "formula")) + stop("the term must be a formula or integer") + fterm <- delete.response(terms(term)) + fatt <- attributes(fterm) + user.name <- fatt$term.labels # what the user called it + termname <- all.vars(fatt$variables) + indx <- match(termname, all.vars(Tatt$variables)) + if (any(is.na(indx))) + stop("variable ", termname[is.na(indx)], " not found in the formula") + + # What kind of term is being tested? It can be categorical, continuous, + # an interaction of only categorical terms, interaction of only continuous + # terms, or a mixed interaction. + # Key is a trick to get "zed" from ns(zed, df= dfvar) + key <- sapply(Tatt$variables[-1], function(x) all.vars(x)[1]) + parts <- names(Tatt$dataClasses)[match(termname, key)] + types <- Tatt$dataClasses[parts] + iscat <- as.integer(types=="factor" | types=="character") + if (length(iscat)==1) termtype <- iscat + else termtype <- 2 + any(iscat) + all(iscat) + + # Were levels specified? If so we either simply accept them (continuous), + # or double check them (categorical) + if (missing(levels)) { + temp <- fit$xlevels[match(parts, names(fit$xlevels), nomatch=0)] + if (length(temp) < length(parts)) + stop("continuous variables require the levels argument") + levels <- do.call(expand.grid, c(temp, stringsAsFactors=FALSE)) + } + else { #user supplied + if (is.list(levels)) { + if (is.null(names(levels))) { + if (length(termname)==1) names(levels)== termname + else stop("levels list requires named elements") + } + } + if (is.data.frame(levels) || is.list(levels)) { + index1 <- match(termname, names(levels), nomatch=0) + # Grab the cols from levels that are needed (we allow it to have + # extra, unused columns) + levels <- as.list(levels[index1]) + # now, levels = the set of ones that the user supplied (which might + # be none, if names were wrong) + if (length(levels) < length(termname)) { + # add on the ones we don't have, using fit$xlevels as defaults + temp <- fit$xlevels[parts[index1==0]] + if (length(temp) > 0) { + names(temp) <- termname[index1 ==0] + levels <- c(levels, temp) + } + } + index2 <- match(termname, names(levels), nomatch=0) + if (any(index2==0)) + stop("levels information not found for: ", termname[index2==0]) + levels <- expand.grid(levels[index2], stringsAsFactors=FALSE) + if (any(duplicated(levels))) stop("levels data frame has duplicates") + } + else if (is.matrix(levels)) { + if (ncol(levels) != length(parts)) + stop("levels matrix has the wrong number of columns") + if (!is.null(dimnames(levels)[[2]])) { + index <- match(termname, dimnames(levels)[[2]], nomatch=0) + if (index==0) + stop("matrix column names do no match the variable list") + else levels <- levels[,index, drop=FALSE] + } else if (ncol(levels) > 1) + stop("multicolumn levels matrix requires column names") + if (any(duplicated(levels))) + stop("levels matrix has duplicated rows") + levels <- data.frame(levels, stringsAsFactors=FALSE) + names(levels) <- termname + } + else if (length(parts) > 1) + stop("levels should be a data frame or matrix") + else { + levels <- data.frame(x=unique(levels), stringsAsFactors=FALSE) + names(levels) <- termname + } + } + + # check that any categorical levels are legal + for (i in which(iscat==1)) { + xlev <- fit$xlevels[[parts[i]]] + if (is.null(xlev)) + stop("xlevels attribute not found for", termname[i]) + temp <- match(levels[[i]], xlev) + if (any(is.na(temp))) + stop("invalid level for term", termname[i]) + } + + rval <- list(levels=levels, termname=termname) + # Now add the contrast matrix between the levels, if needed + if (test=="global") { + <> + } + else if (test=="pairwise") { + <> + } + else if (test=="mean") { + <> + } + else { + <> + } + # the user can say "age" when the model has "ns(age)", but we need + # the more formal label going forward + rval <- list(levels=levels, termname=parts, cmat=cmat, iscat=iscat) + class(rval) <- "cmatrix" + rval +} +@ + +The default contrast matrix is a simple test of equality if there is only +one term. +If the term is the interaction of multiple categorical variables +then we do an anova type decomposition. +In other cases we currently fail. +<>= +if (TRUE) { +#if (length(parts) ==1) { + cmat <- diag(nrow(levels)) + cmat[, nrow(cmat)] <- -1 # all equal to the last + cmat <- cmat[-nrow(cmat),, drop=FALSE] +} +else if (termtype== 4) { # anova type + stop("not yet done 1") +} +else stop("not yet done 2") +@ + + +The \code{pairwise} option creates a set of contrast matrices for all pairs +of a factor. + +<>= +nlev <- nrow(levels) # this is the number of groups being compared +if (nlev < 2) stop("pairwise tests need at least 2 groups") +npair <- nlev*(nlev-1)/2 +if (npair==1) cmat <- matrix(c(1, -1), nrow=1) +else { + cmat <- vector("list", npair) + k <- 1 + cname <- rep("", npair) + for (i in 1:(nlev-1)) { + temp <- double(nlev) + temp[i] <- 1 + for (j in (i+1):nlev) { + temp[j] <- -1 + cmat[[k]] <- matrix(temp, nrow=1) + temp[j] <- 0 + cname[k] <- paste(i, "vs", j) + k <- k+1 + } + } + names(cmat) <- cname +} +@ + +The mean option compares each to the overall mean. +<>= +ntest <- nrow(levels) +cmat <- vector("list", ntest) +for (k in 1:ntest) { + temp <- rep(-1/ntest, ntest) + temp[k] <- (ntest-1)/ntest + cmat[[k]] <- matrix(temp, nrow=1) +} +names(cmat) <- paste(1:ntest, "vs mean") +@ + +The \code{linear} option is of interest for terms that have more than one +column; the two most common cases are a factor variable or a spline. +It forms a pair of tests, one for the linear and one +for the nonlinear part. For non-linear functions such as splines we need +some notion of the range of the data, since we want to be linear over the +entire range. + +<>= +cmat <- vector("list", 2) +cmat[[1]] <- matrix(1:ntest, 1, ntest) +cmat[[2]] <- diag(ntest) +attr(cmat, "nested") <- TRUE +if (is.null(levels[[1]])) { + # a continuous variable, and the user didn't give levels for the test + # look up the call and use the knots + tcall <- Tatt$predvars[[indx + 1]] # skip the 'call' + if (tcall[[1]] == as.name("pspline")) { + bb <- tcall[["Boundary.knots"]] + levels[[1]] <- seq(bb[1], bb[2], length=ntest) + } + else if (tcall[[1]] %in% c("ns", "bs")) { + bb <- c(tcall[["Boundary.knots"]], tcall[["knots"]]) + levels[[1]] <- sort(bb) + } + else stop("don't know how to do a linear contrast for this term") +} +@ + + +Here are some helper routines. +Formulas are from chapter 5 of Searle. The sums of squares only makes +sense within a linear model. +<>= +gsolve <- function(mat, y, eps=sqrt(.Machine$double.eps)) { + # solve using a generalized inverse + # this is very similar to the ginv function of MASS + temp <- svd(mat, nv=0) + dpos <- (temp$d > max(temp$d[1]*eps, 0)) + dd <- ifelse(dpos, 1/temp$d, 0) + # all the parentheses save a tiny bit of time if y is a vector + if (all(dpos)) x <- drop(temp$u %*% (dd*(t(temp$u) %*% y))) + else if (!any(dpos)) x <- drop(temp$y %*% (0*y)) # extremely rare + else x <-drop(temp$u[,dpos] %*%(dd[dpos] * (t(temp$u[,dpos, drop=FALSE]) %*% y))) + attr(x, "df") <- sum(dpos) + x +} + +qform <- function(var, beta) { # quadratic form b' (V-inverse) b + temp <- gsolve(var, beta) + list(test= sum(beta * temp), df=attr(temp, "df")) +} +@ + +The next functions do the work. Some bookkeeping is needed for +a missing value in beta: we leave that coefficient out of the linear +predictor. +If there are missing coefs then the variance matrix will not have those +columns in any case. +The nafun function asks if a linear combination is NA. It treats +0*NA as 0. + +<>= +estfun <- function(cmat, beta, varmat) { + nabeta <- is.na(beta) + if (any(nabeta)) { + k <- which(!nabeta) #columns to keep + estimate <- drop(cmat[,k] %*% beta[k]) # vector of predictions + evar <- cmat[,k] %*% varmat %*% t(cmat[,k, drop=FALSE]) + list(estimate = estimate, var=evar) + } + else { + list(estimate = drop(cmat %*% beta), + var = cmat %*% varmat %*% t(cmat)) + } +} + +testfun <- function(cmat, beta, varmat, sigma2) { + nabeta <- is.na(beta) + if (any(nabeta)) { + k <- which(!nabeta) #columns to keep + estimate <- drop(cmat[,k] %*% beta[k]) # vector of predictions + temp <- qform(cmat[,k] %*% varmat %*% t(cmat[,k,drop=FALSE]), estimate) + rval <- c(chisq=temp$test, df=temp$df) + } + else { + estimate <- drop(cmat %*% beta) + temp <- qform(cmat %*% varmat %*% t(cmat), estimate) + rval <- c(chisq=temp$test, df=temp$df) + } + if (!is.null(sigma2)) rval <- c(rval, ss= unname(rval[1]) * sigma2) + rval +} + +nafun <- function(cmat, est) { + used <- apply(cmat, 2, function(x) any(x != 0)) + any(used & is.na(est)) + } +@ +Now for the primary function. +The user may have a list of tests, or a single term. +The first part of the function does the usual of grabbing arguments +and then checking them. +The fit object has to have the standard stuff: terms, assign, xlevels +and contrasts. +Attributes of the terms are used often enough that we copy them +to \code{Tatt} to save typing. +We will almost certainly need the model frame and/or model matrix as +well. + +In the discussion below I use x1 to refer to the covariates/terms that are +the target, e.g. \code{test='Mask'} to get the mean population values for +each level of the Mask variable in the solder data set, and x2 to refer to +all the other terms in the model, the ones that we average over. +These are also referred to as U and V in the vignette. + +<>= +yates <- function(fit, term, population=c("data", "factorial", "sas"), + levels, test =c("global", "trend", "pairwise"), + predict="linear", options, nsim=200, + method=c("direct", "sgtt")) { + Call <- match.call() + if (missing(fit)) stop("a fit argument is required") + Terms <- try(terms(fit), silent=TRUE) + if (inherits(Terms, "try-error")) + stop("the fit does not have a terms structure") + else Terms <- delete.response(Terms) # y is not needed + Tatt <- attributes(Terms) + # a flaw in delete.response: it doesn't subset dataClasses + Tatt$dataClasses <- Tatt$dataClasses[row.names(Tatt$factors)] + + if (inherits(fit, "coxphms")) stop("multi-state coxph not yet supported") + if (is.list(predict) || is.function(predict)) { + # someone supplied their own + stop("user written prediction functions are not yet supported") + } + else { # call the method + indx <- match(c("fit", "predict", "options"), names(Call), nomatch=0) + temp <- Call[c(1, indx)] + temp[[1]] <- quote(yates_setup) + mfun <- eval(temp, parent.frame()) + } + if (is.null(mfun)) predict <- "linear" + + # we will need the original model frame and X matrix + mframe <- fit$model + if (is.null(mframe)) mframe <- model.frame(fit) + Xold <- model.matrix(fit) + if (is.null(fit$assign)) { # glm models don't save assign + xassign <- attr(Xold, "assign") + } + else xassign <- fit$assign + + + nvar <- length(xassign) + nterm <- length(Tatt$term.names) + termname <- rownames(Tatt$factors) + iscat <- sapply(Tatt$dataClasses, + function(x) x %in% c("character", "factor")) + + method <- match.arg(casefold(method), c("direct", "sgtt")) #allow SGTT + if (method=="sgtt" && missing(population)) population <- "sas" + + if (inherits(population, "data.frame")) popframe <- TRUE + else if (is.character(population)) { + popframe <- FALSE + population <- match.arg(tolower(population[1]), + c("data", "factorial", "sas", + "empirical", "yates")) + if (population=="empirical") population <- "data" + if (population=="yates") population <- "factorial" + } + else stop("the population argument must be a data frame or character") + test <- match.arg(test) + + if (popframe || population != "data") weight <- NULL + else { + weight <- model.extract(mframe, "weights") + if (is.null(weight)) { + id <- model.extract(mframe, "id") + if (!is.null(id)) { # each id gets the same weight + count <- c(table(id)) + weight <- 1/count[match(id, names(count))] + } + } + } + + if (method=="sgtt" && (population !="sas" || predict != "linear")) + stop("sgtt method only applies if population = sas and predict = linear") + + beta <- coef(fit, complete=TRUE) + nabeta <- is.na(beta) # undetermined coefficients + vmat <- vcov(fit, complete=FALSE) + if (nrow(vmat) > sum(!nabeta)) { + # a vcov method that does not obey the complete argument + vmat <- vmat[!nabeta, !nabeta] + } + + # grab the dispersion, needed for the writing an SS in linear models + if (class(fit)[1] =="lm") sigma <- summary(fit)$sigma + else sigma <- NULL # don't compute an SS column + + # process the term argument and check its legality + if (missing(levels)) + contr <- cmatrix(fit, term, test, assign= xassign) + else contr <- cmatrix(fit, term, test, assign= xassign, levels = levels) + x1data <- as.data.frame(contr$levels) # labels for the PMM values + + # Make the list of X matrices that drive everything: xmatlist + # (Over 1/2 the work of the whole routine) + xmatlist <- yates_xmat(Terms, Tatt, contr, population, mframe, fit, + iscat) + + # check rows of xmat for estimability + <> + + # Drop missing coefficients, and use xmatlist to compute the results + beta <- beta[!nabeta] + if (predict == "linear" || is.null(mfun)) { + # population averages of the simple linear predictor + <> + } + else { + <> + } + result$call <- Call + class(result) <- "yates" + result +} +@ + +Models with factor variables may often lead to population predictions that +involve non-estimable functions, particularly if there are interactions +and the user specifies a factorial population. +If there are any missing coefficients we have to do formal checking for +this: any given row of the new $X$ matrix, for prediction, must be in the +row space of the original $X$ matrix. +If this is true then a regression of a new row on the old $X$ will have +residuals of zero. +It is not possible to derive this from the pattern of NA coefficients alone. +Set up a function that returns a true/false vector of whether each row of +a matrix is estimable. This test isn't relevant if population=none. + + +<>= +if (any(is.na(beta)) && (popframe || population != "none")) { + Xu <- unique(Xold) # we only need unique rows, saves time to do so + if (inherits(fit, "coxph")) X.qr <- qr(t(cbind(1.0,Xu))) + else X.qr <- qr(t(Xu)) # QR decomposition of the row space + estimcheck <- function(x, eps= sqrt(.Machine$double.eps)) { + temp <- abs(qr.resid(X.qr, t(x))) + # apply(abs(temp), 1, function(x) all(x < eps)) # each row estimable + all(temp < eps) + } + estimable <- sapply(xmatlist, estimcheck) +} else estimable <- rep(TRUE, length(xmatlist)) +@ + +When the prediction target is $X\beta$ there is a four step +process: build the reference population, create the list of X matrices +(one prediction matrix for each for x1 value), +column means of each X form each row of the +contrast matrix Cmat, and then use Cmat to get the pmm values and +tests of the pmm values. + +<>= +temp <- match(contr$termname, colnames(Tatt$factors)) +if (any(is.na(temp))) + stop("term '", contr$termname[is.na(temp)], "' not found in the model") + +meanfun <- if (is.null(weight)) colMeans else function(x) { + colSums(x*weight)/ sum(weight)} +Cmat <- t(sapply(xmatlist, meanfun))[,!nabeta] + +# coxph model: the X matrix is built as though an intercept were there (the +# baseline hazard plays that role), but then drop it from the coefficients +# before computing estimates and tests. +if (inherits(fit, "coxph")) { + Cmat <- Cmat[,-1, drop=FALSE] + offset <- -sum(fit$means[!nabeta] * beta) # recenter the predictions too + } +else offset <- 0 + +# Get the PMM estimates, but only for estimable ones +estimate <- cbind(x1data, pmm=NA, std=NA) +if (any(estimable)) { + etemp <- estfun(Cmat[estimable,,drop=FALSE], beta, vmat) + estimate$pmm[estimable] <- etemp$estimate + offset + estimate$std[estimable] <- sqrt(diag(etemp$var)) +} + +# Now do tests on the PMM estimates, one by one +if (method=="sgtt") { + <> +} +else { + if (is.list(contr$cmat)) { + test <- t(sapply(contr$cmat, function(x) + testfun(x %*% Cmat, beta, vmat, sigma^2))) + natest <- sapply(contr$cmat, nafun, estimate$pmm) + } + else { + test <- testfun(contr$cmat %*% Cmat, beta, vmat, sigma^2) + test <- matrix(test, nrow=1, + dimnames=list("global", names(test))) + natest <- nafun(contr$cmat, estimate$pmm) + } + if (any(natest)) test[natest,] <- NA +} +if (any(estimable)){ +# Cmat[!estimable,] <- NA + result <- list(estimate=estimate, test=test, mvar=etemp$var, cmat=Cmat) + } +else result <- list(estimate=estimate, test=test, mvar=NA) +if (method=="sgtt") result$SAS <- Smat +@ + +In the non-linear case the mfun object is either a single function +or a list containing two functions \code{predict} and \code{summary}. +The predict function is handed a vector $\eta = X\beta$ along with +the $X$ matrix, though most methods don't use $X$. +The result of predict can be a vector or a matrix. +For coxph models we add on an ``intercept coef'' that will center the +predictions. + +<>= +xall <- do.call(rbind, xmatlist)[,!nabeta, drop=FALSE] +if (inherits(fit, "coxph")) { + xall <- xall[,-1, drop=FALSE] # remove the intercept + eta <- xall %*% beta -sum(fit$means[!nabeta]* beta) +} +else eta <- xall %*% beta +n1 <- nrow(xmatlist[[1]]) # all of them are the same size +index <- rep(1:length(xmatlist), each = n1) +if (is.function(mfun)) predfun <- mfun +else { # double check the object + if (!is.list(mfun) || + any(is.na(match(c("predict", "summary"), names(mfun)))) || + !is.function(mfun$predic) || !is.function(mfun$summary)) + stop("the prediction should be a function, or a list with two functions") + predfun <- mfun$predict + sumfun <- mfun$summary +} +pmm <- predfun(eta, xall) +n2 <- length(eta) +if (!(is.numeric(pmm)) || !(length(pmm)==n2 || nrow(pmm)==n2)) + stop("prediction function should return a vector or matrix") +pmm <- rowsum(pmm, index, reorder=FALSE)/n1 +pmm[!estimable,] <- NA + +# get a sample of coefficients, in order to create a variance +# this is lifted from the mvtnorm code (can't include a non-recommended +# package in the dependencies) +tol <- sqrt(.Machine$double.eps) +if (!isSymmetric(vmat, tol=tol, check.attributes=FALSE)) + stop("variance matrix of the coefficients is not symmetric") +ev <- eigen(vmat, symmetric=TRUE) +if (!all(ev$values >= -tol* abs(ev$values[1]))) + warning("variance matrix is numerically not positive definite") +Rmat <- t(ev$vectors %*% (t(ev$vectors) * sqrt(ev$values))) +bmat <- matrix(rnorm(nsim*ncol(vmat)), nrow=nsim) %*% Rmat +bmat <- bmat + rep(beta, each=nsim) # add the mean + +# Now use this matrix of noisy coefficients to get a set of predictions +# and use those to create a variance matrix +# Since if Cox we need to recenter each run +sims <- array(0., dim=c(nsim, nrow(pmm), ncol(pmm))) +if (inherits(fit, 'coxph')) offset <- bmat %*% fit$means[!nabeta] +else offset <- rep(0., nsim) + +for (i in 1:nsim) + sims[i,,] <- rowsum(predfun(xall %*% bmat[i,] - offset[i]), index, + reorder=FALSE)/n1 +mvar <- var(sims[,,1]) # this will be used for the tests +estimate <- cbind(x1data, pmm=unname(pmm[,1]), std= sqrt(diag(mvar))) + +# Now do the tests, on the first column of pmm only +if (is.list(contr$cmat)) { + test <- t(sapply(contr$cmat, function(x) + testfun(x, pmm[,1], mvar[estimable, estimable], NULL))) + natest <- sapply(contr$cmat, nafun, pmm[,1]) +} +else { + test <- testfun(contr$cmat, pmm[,1], mvar[estimable, estimable], NULL) + test <- matrix(test, nrow=1, + dimnames=list(contr$termname, names(test))) + natest <- nafun(contr$cmat, pmm[,1]) +} +if (any(natest)) test[natest,] <- NA +if (any(estimable)) + result <- list(estimate=estimate,test=test, mvar=mvar) +else result <- list(estimate=estimate, test=test, mvar=NA) + +# If there were multiple columns from predfun, compute the matrix of +# results and variances +if (ncol(pmm) > 1 && any(estimable)){ + pmm <- apply(sims, 2:3, mean) + mvar2 <- apply(sims, 2:3, var) + # Call the summary function, if present + if (is.list(mfun)) result$summary <- sumfun(pmm, mvar2) + else { + result$pmm <- pmm + result$mvar2 <- mvar2 + } +} +@ + + +Build the population data set. +If the user provided a data set as the population then the task is +fairly straightforward: we manipulate the data set and then call +model.frame followed by model.matrix in the usual way. +The primary task in that +case is to verify that the data has all the needed variables. + +Otherwise we have to be subtle. +\begin{enumerate} + \item We have ready access to a model frame, but not to the data. + Consider a spline term for instance --- it's not always possible + to go backwards and get the data. + \item We need to manipulate this model frame, e.g., make everyone + treatment=A, then repeat with everyone treatment B. + \item We need to do it in a way that makes the frame still look + like a correct model frame to R. This requires care. +\end{enumerate} + +For population= factorial we create a population data set that has all +the combinations. If there are three adjusters z1, z2 and z3 with +2, 3, and 5 levels, respectively, the new data set will have 30 +rows. +If the primary model didn't have any z1*z2*z3 terms in it we +likely could get by with less, but it's not worth the programming effort +to figure that out: predicted values are normally fairly cheap. +For population=sas we need a mixture: categoricals are factorial and others +are data. Say there were categoricals with 3 and 5 levels, so the factorial +data set has 15 obs, while the overall n is 50. We need a data set of 15*50 +observations to ensure all combinations of the two categoricals with each +continuous line. + +An issue with data vs model is names. Suppose the original model was +\code{lm(y \textasciitilde ns(age,4) + factor(ph.ecog))}. +In the data set the variable name is ph.ecog, in the model frame, +the xlevels list, and terms structure it is factor(ph.ecog). +The data frame has individual columns for the four variables, the model frame +is a list with 3 elements, one of which is named ``ns(age, 4)'': notice the +extra space before the 4 compared to what was typed. + +<>= +yates_xmat <- function(Terms, Tatt, contr, population, mframe, fit, + iscat, weight) { + # which variables(s) are in x1 (variables of interest) + x1indx <- apply(Tatt$factors[,contr$termname,drop=FALSE] >0, 1, any) + x2indx <- !x1indx # adjusters + if (inherits(population, "data.frame")) pdata <- population #user data + else if (population=="data") pdata <- mframe #easy case + else if (population=="factorial") + pdata <- yates_factorial_pop(mframe, Terms, x2indx, fit$xlevels) + else if (population=="sas") { + if (all(iscat[x2indx])) + pdata <- yates_factorial_pop(mframe, Terms, x2indx, fit$xlevels) + else if (!any(iscat[x2indx])) pdata <- mframe # no categoricals + else { # mixed population + pdata <- yates_factorial_pop(mframe, Terms, x2indx & iscat, + fit$xlevels) + n2 <- nrow(pdata) + pdata <- pdata[rep(1:nrow(pdata), each=nrow(mframe)), ] + row.names(pdata) <- 1:nrow(pdata) + # fill in the continuous + k <- rep(1:nrow(mframe), n2) + for (i in which(x2indx & !iscat)) { + j <- names(x1indx)[i] + if (is.matrix(mframe[[j]])) + pdata[[j]] <- mframe[[j]][k,, drop=FALSE] + else pdata[[j]] <- (mframe[[j]])[k] + attributes(pdata[[j]]) <- attributes(mframe[[j]]) + } + } + } + else stop("unknown population") # this should have been caught earlier + + # Now create the x1 data set, the unique rows we want to test + <> + + xmatlist +} +@ + +Build a factorial data set from a model frame. +<>= +yates_factorial_pop <- function(mframe, terms, x2indx, xlevels) { + x2name <- names(x2indx)[x2indx] + dclass <- attr(terms, "dataClasses")[x2name] + if (!all(dclass %in% c("character", "factor"))) + stop("population=factorial only applies if all the adjusting terms are categorical") + + nvar <- length(x2name) + n2 <- sapply(xlevels[x2name], length) # number of levels for each + n <- prod(n2) # total number of rows needed + pdata <- mframe[rep(1, n), -1] # toss the response + row.names(pdata) <- NULL # throw away funny names + n1 <- 1 + for (i in 1:nvar) { + j <- rep(rep(1:n2[i], each=n1), length=n) + xx <- xlevels[[x2name[i]]] + if (dclass[i] == "factor") + pdata[[x2name[i]]] <- factor(j, 1:n2[i], labels= xx) + else pdata[[x2name[i]]] <- xx[j] + n1 <- n1 * n2[i] + } + attr(pdata, "terms") <- terms + pdata +} +@ + +The next section builds a set of X matrices, one for each level of the +x1 combination. +The following was learned by reading the source code for +model.matrix: +\begin{itemize} +\item If pdata has no terms attribute then model.matrix will call model.frame + first, otherwise not. The xlev argument is passed forward to model.frame + but is otherwise unused. +\item If necessary, it will reorder the columns of pdata to match the terms, + though I try to avoid that. +\item Toss out the response variable, if present. +\item Any character variables are turned into factors. The dataClass attribute + of the terms object is not consulted. +\item For each column that is a factor + \begin{itemize} + \item if it alreay has a contrasts attribute, it is left alone. + \item otherwise a contrasts attribute is added using a matching + element from contrasts.arg, if present, otherwise the global default + \item contrasts.arg must be a list, but it does not have to contain all + factors + \end{itemize} + \item Then call the internal C code +\end{itemize} + +If pdata already is a model frame we want to leave it as one, so as to +avoid recreating the raw data. +If x1data comes from the user though, so we need to do that portion of +model.frame processing ourselves, in order to get it into the right +form. Always turn characters into factors, since individual elements +of \code{xmatlist} will have only a subset of the x1 variables. +One nuisance is name matching. Say the model had +\code{factor(ph.ecog)} as a term; then \code{fit\$xlevels} will have +`factor(ph.ecog)' as a name but the user will likely have created a +data set using `ph.ecog' as the name. + +<>= +if (is.null(contr$levels)) stop("levels are missing for this contrast") +x1data <- as.data.frame(contr$levels) # in case it is a list +x1name <- names(x1indx)[x1indx] +for (i in 1:ncol(x1data)) { + if (is.character(x1data[[i]])) { + if (is.null(fit$xlevels[[x1name[i]]])) + x1data[[i]] <- factor(x1data[[i]]) + else x1data[[i]] <- factor(x1data[[i]], fit$xlevels[[x1name[i]]]) + } +} + +xmatlist <- vector("list", nrow(x1data)) +if (is.null(attr(pdata, "terms"))) { + np <- nrow(pdata) + k <- match(x1name, names(pdata), nomatch=0) + if (any(k>0)) pdata <- pdata[, -k, drop=FALSE] # toss out yates var + for (i in 1:nrow(x1data)) { + j <- rep(i, np) + tdata <- cbind(pdata, x1data[j,,drop=FALSE]) # new data set + xmatlist[[i]] <- model.matrix(Terms, tdata, xlev=fit$xlevels, + contrast.arg= fit$contrasts) + } +} else { + # pdata is a model frame, convert x1data + # if the name and the class agree we go forward simply + index <- match(names(x1data), names(pdata), nomatch=0) + + if (all(index >0) && + identical(lapply(x1data, class), lapply(pdata, class)[index]) & + identical(sapply(x1data, ncol) , sapply(pdata, ncol)[index])) + { # everything agrees + for (i in 1:nrow(x1data)) { + j <- rep(i, nrow(pdata)) + tdata <- pdata + tdata[,names(x1data)] <- x1data[j,] + xmatlist[[i]] <- model.matrix(Terms, tdata, + contrasts.arg= fit$contrasts) + } + } + else { + # create a subset of the terms structure, for x1 only + # for instance the user had age=c(75, 75, 85) and the term was ns(age) + # then call model.frame to fix it up + x1term <- Terms[which(x1indx)] + x1name <- names(x1indx)[x1indx] + attr(x1term, "dataClasses") <- Tatt$dataClasses[x1name] # R bug + x1frame <- model.frame(x1term, x1data, xlev=fit$xlevels[x1name]) + for (i in 1:nrow(x1data)) { + j <- rep(i, nrow(pdata)) + tdata <- pdata + tdata[,names(x1frame)] <- x1frame[j,] + xmatlist[[i]] <- model.matrix(Terms, tdata, xlev=fit$xlevels, + contrast.arg= fit$contrasts) + } + } +} +@ + +The decompostion based algorithm for SAS type 3 tests. +Ignore the set of contrasts cmat since the algorithm can only +do a global test. +We mostly mimic the SAS GLM algorithm. + +For the generalized Cholesky decomposition $LDL' = X'X$, where $L$ is +lower triangular with $L_{ii}=1$ and $D$ is diagonal, the set of contrasts +$L'\beta$ gives the type I sequential sums of squares, partitioning the +rows of $L$ into those for term 1, term 2, etc. +If $X$ is the design matrix for a balanced factorial design then it is +also true that $L_{ij}=0$ unless term $j$ includes term $i$, e.g., x1:x2 +includes x1. These blocks of zeros mean that changing the order of the terms +in the model simply rearranges $L$, and individual tests are unchanged. + +This is precisely the definition of a type III contrast in SAS. +With a bit of reading between the lines the ``four types of estimable +functions'' document suggests the following algorithm: +\begin{enumerate} + \item Start with an $X$ matrix in standard order of intercept, main effects, + first order interactions, etc. Code any categorical variable with $k$ levels + as $k$ 0/1 columns. An interaction of two categoricals with $k$ and $l$ + levels will have $kl$ columns, etc. + \item Create the dependency matrix $D = (X'X)^-(X'X)$. If column $i$ of $X$ + can be written as a linear combination of prior columns, then column $i$ of + $D$ contains that combination. Other columns of $D$ match the identity + matrix. + \item Intitialize $L = D$. + \item For any row $i$ and $j$ such that $i$ is contained in $j$, make $L_i$ + orthagonal to $L_j$. +\end{enumerate} +The algorithm appears to work in almost all cases, an exception is when the +type 3 test has fewer degrees of freedom that we would expect. + +Continuous variables are not orthagonalized in the SAS type III approach, +nor any interaction that contains a continuous variable as one of its parts. +To find the nested terms first note which rows of \code{factors} refer +to categorical variables (the \code{iscat} variable); +columns of \code{factors} that are non-zero only +in categorical rows are the ``categorical'' columns. +A term represented by one column in \code{factors} ``contains'' the term +represented in some other column iff it's non-zero elements are a superset. + +We have to build a new X matrix that is the expanded SAS coding, and are only +able to do that for models that have an intercept, and use contr.treatement +or contr.SAS coding. +<>= +# It would be simplest to have the contrasts.arg to be a list of function names. +# However, model.matrix plays games with the calling sequence, and any function +# defined at this level will not be seen. Instead create a list of contrast +# matrices. +temp <- sapply(fit$contrasts, function(x) (is.character(x) && + x %in% c("contr.SAS", "contr.treatment"))) +if (!all(temp)) + stop("yates sgtt method can only handle contr.SAS or contr.treatment") +temp <- vector("list", length(fit$xlevels)) +names(temp) <- names(fit$xlevels) +for (i in 1:length(fit$xlevels)) { + cmat <- diag(length(fit$xlevels[[i]])) + dimnames(cmat) <- list(fit$xlevels[[i]], fit$xlevels[[i]]) + if (i>1 || Tatt$intercept==1) { + if (fit$contrasts[[i]] == "contr.treatment") + cmat <- cmat[, c(2:ncol(cmat), 1)] + } + temp[[i]] <- cmat +} +sasX <- model.matrix(formula(fit), data=mframe, xlev=fit$xlevels, + contrasts.arg=temp) +sas.assign <- attr(sasX, "assign") + +# create the dependency matrix D. The lm routine is unhappy if it thinks +# the right hand and left hand sides are the same, fool it with I(). +# We do this using the entire X matrix even though only categoricals will +# eventually be used; if a continuous variable made it NA we need to know. +D <- coef(lm(sasX ~ I(sasX) -1)) +dimnames(D)[[1]] <- dimnames(D)[[2]] #get rid if the I() names +zero <- is.na(D[,1]) # zero rows, we'll get rid of these later +D <- ifelse(is.na(D), 0, D) + +# make each row orthagonal to rows for other terms that contain it +# Containing blocks, if any, will always be below +# this is easiest to do with the transposed matrix +# Only do this if both row i and j are for a categorical variable +if (!all(iscat)) { + # iscat marks variables in the model frame as categorical + # tcat marks terms as categorical. For x1 + x2 + x1:x2 iscat has + # 2 entries and tcat has 3. + tcat <- (colSums(Tatt$factors[!iscat,,drop=FALSE]) == 0) +} +else tcat <- rep(TRUE, max(sas.assign)) # all vars are categorical + +B <- t(D) +dimnames(B)[[2]] <- paste0("L", 1:ncol(B)) # for the user +if (ncol(Tatt$factors) > 1) { + share <- t(Tatt$factors) %*% Tatt$factors + nc <- ncol(share) + for (i in which(tcat[-nc])) { + j <- which(share[i,] > 0 & tcat) + k <- j[j>i] # terms that I need to regress out + if (length(k)) { + indx1 <- which(sas.assign ==i) + indx2 <- which(sas.assign %in% k) + B[,indx1] <- resid(lm(B[,indx1] ~ B[,indx2])) + } + } +} + +# Cut B back down to the non-missing coefs of the original fit +Smat <- t(B)[!zero, !zero] +Sassign <- xassign[!nabeta] +@ + +Although the SGTT does test for all terms, we only want to print out the +ones that were asked for. +<>= +keep <- match(contr$termname, colnames(Tatt$factors)) +if (length(keep) > 1) { # more than 1 term in the model + test <- t(sapply(keep, function(i) + testfun(Smat[Sassign==i,,drop=FALSE], beta, vmat, sigma^2))) + rownames(test) <- contr$termname +} else { + test <- testfun(Smat[Sassign==keep,, drop=FALSE], beta, vmat, sigma^2) + test <- matrix(test, nrow=1, + dimnames=list(contr$termname, names(test))) +} +@ + + +The print routine places the population predicted values (PPV) alongside the +tests on those values. Defaults are copied from printCoefmat. + +<>= +print.yates <- function(x, digits = max(3, getOption("digits") -2), + dig.tst = max(1, min(5, digits-1)), + eps=1e-8, ...) { + temp1 <- x$estimate + temp1$pmm <- format(temp1$pmm, digits=digits) + temp1$std <- format(temp1$std, digits=digits) + + # the spaces help separate the two parts of the printout + temp2 <- cbind(test= paste(" ", rownames(x$test)), + data.frame(x$test), stringsAsFactors=FALSE) + row.names(temp2) <- NULL + + temp2$Pr <- format.pval(pchisq(temp2$chisq, temp2$df, lower.tail=FALSE), + eps=eps, digits=dig.tst) + temp2$chisq <- format(temp2$chisq, digits= dig.tst) + temp2$df <- format(temp2$df) + if (!is.null(temp2$ss)) temp2$ss <- format(temp2$ss, digits=digits) + + if (nrow(temp1) > nrow(temp2)) { + dummy <- temp2[1,] + dummy[1,] <- "" + temp2 <- rbind(temp2, dummy[rep(1, nrow(temp1)-nrow(temp2)),]) + } + if (nrow(temp2) > nrow(temp1)) { + # get rid of any factors before padding + for (i in which(sapply(temp1, is.factor))) + temp1[[i]] <- as.character(temp1[[i]]) + + dummy <- temp1[1,] + dummy[1,] <- "" + temp1 <- rbind(temp1, dummy[rep(1, nrow(temp2)- nrow(temp1)),]) + } + print(cbind(temp1, temp2), row.names=FALSE) + invisible(x) +} +@ + + +Routines to allow yates to interact with other models. +Each is called with the fitted model and the type of prediction. +It should return NULL when the type is a linear predictor, since the +parent routine has a very efficient approach in that case. +Otherwise it returns a function that will be applied to each value +$\eta$, from each row of a prediction matrix. + +<>= +yates_setup <- function(fit, ...) + UseMethod("yates_setup", fit) + +yates_setup.default <- function(fit, type, ...) { + if (!missing(type) && !(type %in% c("linear", "link"))) + warning("no yates_setup method exists for a model of class ", + class(fit)[1], " and estimate type ", type, + ", linear predictor estimate used by default") + NULL +} + +yates_setup.glm <- function(fit, predict = c("link", "response", "terms", + "linear"), ...) { + type <- match.arg(predict) + if (type == "link" || type== "linear") NULL # same as linear + else if (type == "response") { + finv <- family(fit)$linkinv + function(eta, X) finv(eta) + } + else if (type == "terms") + stop("type terms not yet supported") +} +@ + +For the coxph routine, we are making use of the R environment by first +defining the baseline hazard and then defining the predict and summary +functions. This means that those functions have access to the baseline. + +<>= +yates_setup.coxph <- function(fit, predict = c("lp", "risk", "expected", + "terms", "survival", "linear"), + options, ...) { + type <- match.arg(predict) + if (type=="lp" || type == "linear") NULL + else if (type=="risk") function(eta, X) exp(eta) + else if (type == "survival") { + # If there are strata we need to do extra work + # if there is an interaction we want to suppress a spurious warning + suppressWarnings(baseline <- survfit(fit, censor=FALSE)) + if (missing(options) || is.null(options$rmean)) + rmean <- max(baseline$time) # max death time + else rmean <- options$rmean + + if (!is.null(baseline$strata)) + stop("stratified models not yet supported") + cumhaz <- c(0, baseline$cumhaz) + tt <- c(diff(c(0, pmin(rmean, baseline$time))), 0) + + predict <- function(eta, ...) { + c2 <- outer(exp(drop(eta)), cumhaz) # matrix of values + surv <- exp(-c2) + meansurv <- apply(rep(tt, each=nrow(c2)) * surv, 1, sum) + cbind(meansurv, surv) + } + summary <- function(surv, var) { + bsurv <- t(surv[,-1]) + std <- t(sqrt(var[,-1])) + chaz <- -log(bsurv) + zstat <- -qnorm((1-baseline$conf.int)/2) + baseline$lower <- exp(-(chaz + zstat*std)) + baseline$upper <- exp(-(chaz - zstat*std)) + baseline$surv <- bsurv + baseline$std.err <- std/bsurv + baselinecumhaz <- chaz + baseline + } + list(predict=predict, summary=summary) + } + else stop("type expected is not supported") +} + +@ +\section{The cox.zph function} +The simplest test of proportional hazards is to use a time dependent +coefficient $\beta(t) = a + bt$. +Then $\beta(t) x = ax + b*(tx)$, and the extended coefficients $a$ and $b$ +can be obtained from a Cox model with an extra 'fake' covariate $tx$. +More generally, replace $t$ with some function $g(t)$, which gives rise to +an entire family of tests. +An efficient assessment of this extended model can be done using a score +test. +\begin{itemize} + \item Augment the original variables $x_1, \ldots x_k$ with $k$ new ones +$g(t)x_1, \ldots, g(t)x_k$ + \item Compute the first and second derivatives $U$ and $H$ of the Cox model +at the starting estimate of $(\hat\beta, 0)$; prior covariates at their +prior values, and the new covariates at 0. No iteration is done. +This can be done efficiently with a modified version of the primary C routines +for coxph. + \item By design, the first $k$ elements of $U$ will be zero. Thus the +first iteration of the new coefficients, and the score tests for them, are +particularly easy. +\end{itemize} + +The information or Hessian matrix for a Cox model is +$$ \sum_{j \in deaths} V(t_j) = \sum_jV_j$$ +where $V_j$ is the variance matrix of the weighted covariate values, over +all subjects at risk at time $t_j$. +Then the expanded information matrix for the score test is +\begin{align*} + H &= \left(\begin{array}{cc} H_1 & H_2 \\ H_2' & H_3 \end{array} \right) \\ + H_1 &= \sum V(t_j) \\ + H_2 &= \sum V(t_j) g(t_j) \\ + H_3 &= \sum V(t_j) g^2(t_j) +\end{align*} +The inverse of the matrix will be more numerically stable if $g(t)$ is centered +at zero, and this does not change the test statistic. +In the usual case $V(t)$ is close to constant in time --- the variance of +$X$ does not change rapidly --- and then $H_2$ is approximately zero. +The original cox.zph used an approximation, which is to assume that +$V(t)$ is exactly constant. +In that case $H_2=0$ and $H_3= \sum V(t_j) \sum g^2(t_j)$ and the test +is particularly easy to compute. +This assumption of identical components can fail badly for models with a +covariate by strata interaction, and for some models with covariate +dependent censoring. +Multi-state models finally forced a change. + +The newer version of the routine has two separate tracks: for the formal test +and another for the residuals. + +<>= +cox.zph <- function(fit, transform='km', terms=TRUE, singledf =FALSE, + global=TRUE) { + Call <- match.call() + if (!inherits(fit, "coxph") && !inherits(fit, "coxme")) + stop ("argument must be the result of Cox model fit") + if (inherits(fit, "coxph.null")) + stop("there are no score residuals for a Null model") + if (!is.null(attr(terms(fit), "specials")[["tt"]])) + stop("function not defined for models with tt() terms") + + if (inherits(fit, "coxme")) { + # drop all mention of the random effects, before getdata + fit$formula <- fit$formula$fixed + fit$call$formula <- fit$formula + } + + cget <- coxph.getdata(fit, y=TRUE, x=TRUE, stratax=TRUE, weights=TRUE) + y <- cget$y + ny <- ncol(y) + event <- (y[,ny] ==1) + if (length(cget$strata)) + istrat <- as.integer(cget$strata) - 1L # number from 0 for C + else istrat <- rep(0L, nrow(y)) + + # if terms==FALSE the singledf argument is moot, but setting a value + # leads to a simpler path through the code + if (!terms) singledf <- FALSE + + <> + <> + <> + <> + + rval$transform <- tname + rval$call <- Call + class(rval) <- "cox.zph" + return(rval) +} + +print.cox.zph <- function(x, digits = max(options()$digits - 4, 3), + signif.stars=FALSE, ...) { + invisible(printCoefmat(x$table, digits=digits, signif.stars=signif.stars, + P.values=TRUE, has.Pvalue=TRUE, ...)) +} +@ + +The user can use $t$ or $g(t)$ as the multiplier of the covariates. +The default is to use the KM, only because that seems to be best at +avoiding edge cases. + +<>= +times <- y[,ny-1] +if (is.character(transform)) { + tname <- transform + ttimes <- switch(transform, + 'identity'= times, + 'rank' = rank(times), + 'log' = log(times), + 'km' = { + temp <- survfitKM(factor(rep(1L, nrow(y))), + y, se.fit=FALSE) + # A nuisance to do left continuous KM + indx <- findInterval(times, temp$time, left.open=TRUE) + 1.0 - c(1, temp$surv)[indx+1] + }, + stop("Unrecognized transform")) + } + else { + tname <- deparse(substitute(transform)) + if (length(tname) >1) tname <- 'user' + ttimes <- transform(times) + } + gtime <- ttimes - mean(ttimes[event]) + + # Now get the U, information, and residuals + if (ny==2) { + ord <- order(istrat, y[,1]) -1L + resid <- .Call(Czph1, gtime, y, X, eta, + cget$weights, istrat, fit$method=="efron", ord) + } + else { + ord1 <- order(-istrat, -y[,1]) -1L # reverse time for zph2 + ord <- order(-istrat, -y[,2]) -1L + resid <- .Call(Czph2, gtime, y, X, eta, + cget$weights, istrat, fit$method=="efron", + ord1, ord) + } +@ + +The result has a score vector of length $2p$ where $p$ is the number of +variables and an information matrix that is $2p$ by $2p$. +This is done with C code that +is a simple variation on iteration 1 for a coxph model. + +If \code{singledf} is TRUE then treat each term as a single degree of +freedom test, otherwise as a multi-degree of freedom. +If terms=FALSE test each covariate individually. +If all the variables are univariate this is a moot point. +The survival routines return Splus style assign components, that is a list +with one element per term, each element an integer vector of coefficient +indices. + +The asgn vector is our main workhorse: loop over asgn to process term by +term. +\begin{itemize} + \item if term=FALSE, set make a new asgn with one coef per term + \item if a coefficient is NA, remove it from the relevant asgn vector + \item frailties and penalized coxme coefficients are ignored: remove + their element from the asgn list +\end{itemize} + +For random effects models, including both frailty and coxme results, the +random effect is included in the linear.predictors component of the +fit. This allows us to do score tests for the other terms while effectively +holding the random effect fixed. + +If there are any NA coefficients these are redundant variables. It's +easiest to simply get rid of them at the start by fixing up X, varnames, +asgn, and nvar. +<>= +eta <- fit$linear.predictors +X <- cget$x +varnames <- names(fit$coefficients) +nvar <- length(varnames) + +if (!terms) { + # create a fake asgn that has one value per coefficient + asgn <- as.list(1:nvar) + names(asgn) <- names(fit$coefficients) +} +else if (inherits(fit, "coxme")) { + asgn <- attrassign(cget$x, terms(fit)) + # allow for a spelling inconsistency in coxme, later fixed + if (is.null(fit$linear.predictors)) + eta <- fit$linear.predictor + fit$df <- NULL # don't confuse later code +} +else asgn <- fit$assign + +if (!is.list(asgn)) stop ("unexpected assign component") + +frail <- grepl("frailty(", names(asgn), fixed=TRUE) +if (any(frail)) { + dcol <- unlist(asgn[frail]) # remove these columns from X + X <- X[, -dcol, drop=FALSE] + asgn <- asgn[!frail] + # frailties don't appear in the varnames, so no change there +} +nterm <- length(asgn) +termname <- names(asgn) + +if (any(is.na(fit$coefficients))) { + keep <- !is.na(fit$coefficients) + varnames <- varnames[keep] + X <- X[,keep] + + # fix up assign + new <- unname(unlist(asgn))[keep] # the ones to keep + asgn <- sapply(asgn, function(x) { + i <- match(x, new, nomatch=0) + i[i>0]}) + asgn <- asgn[sapply(asgn, length)>0] # drop any that were lost + termname <- names(asgn) + nterm <- length(asgn) # asgn will be a list + nvar <- length(new) +} +@ + +The zph1 and zph2 functions do not consider penalties, so we need to add +those back in after the call. +Nothing needs to be done wrt the first derivative: we already ignore the +first ncoef elements of the returned first derivative (u) vector, which would +have had a penalty. The second portion of u is for beta=0, and all of the +penalties that currently are implemented have first derivative 0 at 0. +For the second derivative, the current penalties (frailty, rigde, pspline) have +a second derivative penalty that is independent of beta-hat. +The coxph result contains the numeric value of the penalty at the solution, +and we use a score test that would penalize the new time*pspline() term in +the same way as the pspline term was penalized. + +If no coefficients were missing then allvar will be 1:n, otherwise it +will have holes. + +<>= +test <- double(nterm+1) +df <- rep(1L, nterm+1) +u0 <- rep(0, nvar) +if (!is.null(fit$coxlist2)) { # there are penalized terms + pmat <- matrix(0., 2*nvar, 2*nvar) # second derivative penalty + pmat[1:nvar, 1:nvar] <- fit$coxlist2$second + pmat[1:nvar + nvar, 1:nvar + nvar] <- fit$coxlist2$second + imatr <- resid$imat + pmat +} +else imatr <- resid$imat + +for (ii in 1:nterm) { + jj <- asgn[[ii]] + kk <- c(1:nvar, jj+nvar) + imat <- imatr[kk, kk] + u <- c(u0, resid$u[jj+nvar]) + if (singledf && length(jj) >1) { + vv <- solve(imat)[-(1:nvar), -(1:nvar)] + t1 <- sum(fit$coef[jj] * resid$u[jj+nvar]) + test[ii] <- t1^2 * (fit$coef[jj] %*% vv %*% fit$coef[jj]) + df[ii] <- 1 + } + else { + test[ii] <- drop(solve(imat,u) %*% u) + if (is.null(fit$df)) df[ii] <- length(jj) + else df[ii] <- fit$df[ii] + } +} + +#Global test +if (global) { + u <- c(u0, resid$u[-(1:nvar)]) + test[nterm+1] <- solve(imatr, u) %*% u + if (is.null(fit$df)) df[nterm+1] <- nvar + else df[nterm+1] <- sum(fit$df) + + tbl <- cbind(test, df, pchisq(test, df, lower.tail=FALSE)) + dimnames(tbl) <- list(c(termname, "GLOBAL"), c("chisq", "df", "p")) +} +else { + tbl <- cbind(test, df, pchisq(test, df, lower.tail=FALSE))[1:nterm,, drop=FALSE] + dimnames(tbl) <- list(termname, c("chisq", "df", "p")) +} + +# The x, y, residuals part is sorted by time within strata; this is +# what the C routine zph1 and zph2 return +indx <- if (ny==2) ord +1 else rev(ord) +1 # return to 1 based subscripts +indx <- indx[event[indx]] # only keep the death times +rval <- list(table=tbl, x=unname(ttimes[indx]), time=unname(y[indx, ny-1])) +if (length(cget$strata)) rval$strata <- cget$strata[indx] +@ + +The matrix of scaled Schoenfeld residuals is created one stratum at a +time. +The ideal for the residual $r(t_i)$, contributed by an event for subject +$i$ at time $t_i$ is to use $r_iV^{-1}(t_i)$, the inverse of the variance +matrix of $X$ at that time and for the relevant stratum. +What is returned as \code{resid\$imat} is $\sum_i V(t_i)$. +One option would have been to return all the individual $\hat V_i$ matrices, +but that falls over when the number at risk is too small and it cannot +be inverted. +Option 2 would be to use a per stratum averge of the $V_i$, but that falls +flat for models with a large number of strata, a nested case-control model +for instance. +We take a different average that may not be the best, but seems to be +good enough and doesn't seem to fail. +\begin{enumerate} + \item The \code{resid\$used} matrix contains the number of deaths for + each strata (row) that contributed to the sum for each variable (column). + The value is either 0 or the number of events in the stratum, zero for those + variables that are constant within the stratum. From this we can get the + number of events that contributed to each element of the \code{imat} total. + Dividing by this gives a per-element average \code{vmean}. + \item For a given stratum, some of the covariates may have been unused. For + any of those set the scaled Schoenfeld residual to NA, and use the other + rows/columns of the \code{vmean} matrix to scale the rest. +\end{enumerate} +Now if some variable $x_1$ has a large variance at some time points and a +small variance at others, or a large variance in one stratum and a small +variance in another, the above smoothing won't catch that subtlety. +However we expect such an issue to be rare. +The common problem of strata*covariate interactions is the target of the +above manipulations. + +<>= +# Watch out for a particular edge case: there is a factor, and one of the +# strata happens to not use one of its levels. The element of resid$used will +# be zero, but it really should not. +used <-resid$used +for (i in asgn) { + if (length(i) > 1 && any(used[,i] ==0)) + used[,i] <- apply(used[,i,drop=FALSE], 1, max) +} + +# Make the weight matrix +wtmat <- matrix(0, nvar, nvar) +for (i in 1:nrow(used)) + wtmat <- wtmat + outer(used[i,], used[i,], pmin) +# with strata*covariate interactions (multi-state models for instance) the +# imatr matrix will be block diagonal. Don't divide these off diagonal zeros +# by a wtmat value of zero. +vmean <- imatr[1:nvar, 1:nvar, drop=FALSE]/ifelse(wtmat==0, 1, wtmat) + +sresid <- resid$schoen +if (terms && any(sapply(asgn, length) > 1)) { # collase multi-column terms + temp <- matrix(0, ncol(sresid), nterm) + for (i in 1:nterm) { + j <- asgn[[i]] + if (length(j) ==1) temp[j, i] <- 1 + else temp[j, i] <- fit$coefficients[j] + } + + sresid <- sresid %*% temp + vmean <- t(temp) %*% vmean %*% temp + used <- used[, sapply(asgn, function(x) x[1]), drop=FALSE] +} + +dimnames(sresid) <- list(signif(rval$time, 4), termname) + +# for each stratum, rescale the Schoenfeld residuals in that stratum +sgrp <- rep(1:nrow(used), apply(used, 1, max)) +for (i in 1:nrow(used)) { + k <- which(used[i,] > 0) + if (length(k) >0) { # there might be no deaths in the stratum + j <- which(sgrp==i) + if (length(k) ==1) sresid[j,k] <- sresid[j,k]/vmean[k,k] + else sresid[j, k] <- t(solve(vmean[k, k], t(sresid[j, k, drop=FALSE]))) + sresid[j, -k] <- NA + } +} + +# Add in beta-hat. For a term with multiple columns we are testing zph for +# the linear predictor X\beta, which always has a coefficient of 1 +for (i in 1:nterm) { + j <- asgn[[i]] + if (length(j) ==1) sresid[,i] <- sresid[,i] + fit$coefficients[j] + else sresid[,i] <- sresid[,i] +1 +} + +rval$y <- sresid +rval$var <- solve(vmean) +@ + +<>= +"[.cox.zph" <- function(x, ..., drop=FALSE) { + i <- ..1 + if (!is.null(x$strata)) { + y2 <- x$y[,i,drop=FALSE] + ymiss <- apply(is.na(y2), 1, all) + if (any(ymiss)) { + # some deaths played no role in these coefficients + # due to a strata * covariate interaction, drop unneeded rows + z<- list(table=x$table[i,,drop=FALSE], x=x$x[!ymiss], + time= x$time[!ymiss], + strata = x$strata[!ymiss], + y = y2[!ymiss,,drop=FALSE], + var=x$var[i,i, drop=FALSE], + transform=x$transform, call=x$call) + } + else z<- list(table=x$table[i,,drop=FALSE], x=x$x, time= x$time, + strata = x$strata, + y = y2, var=x$var[i,i, drop=FALSE], + transform=x$transform, call=x$call) + } + else + z<- list(table=x$table[i,,drop=FALSE], x=x$x, time= x$time, + y = x$y[,i,drop=FALSE], + var=x$var[i,i, drop=FALSE], + transform=x$transform, call=x$call) + class(z) <- class(x) + z +} +@ +\bibliographystyle{plain} +\bibliography{refer} +\end{document} diff --git a/noweb/code.out b/noweb/code.out new file mode 100644 index 00000000..6f832217 --- /dev/null +++ b/noweb/code.out @@ -0,0 +1,12 @@ +\BOOKMARK [1][-]{section.1}{Introduction}{}% 1 +\BOOKMARK [1][-]{section.2}{Cox Models}{}% 2 +\BOOKMARK [2][-]{subsection.2.1}{Coxph}{section.2}% 3 +\BOOKMARK [2][-]{subsection.2.2}{Exact partial likelihood}{section.2}% 4 +\BOOKMARK [2][-]{subsection.2.3}{Andersen-Gill fits}{section.2}% 5 +\BOOKMARK [2][-]{subsection.2.4}{Predicted survival}{section.2}% 6 +\BOOKMARK [3][-]{subsubsection.2.4.1}{Multi-state models}{subsection.2.4}% 7 +\BOOKMARK [1][-]{section.3}{The Fine-Gray model}{}% 8 +\BOOKMARK [2][-]{subsection.3.1}{The predict method}{section.3}% 9 +\BOOKMARK [1][-]{section.4}{Concordance}{}% 10 +\BOOKMARK [2][-]{subsection.4.1}{Main routine}{section.4}% 11 +\BOOKMARK [2][-]{subsection.4.2}{Methods}{section.4}% 12 diff --git a/noweb/code.pdf b/noweb/code.pdf new file mode 100644 index 0000000000000000000000000000000000000000..36fa98de4596ff636586b72615f6bacbde8b177d GIT binary patch literal 408326 zcmb5UQ*>@y7j_xjwr$(C?d;gLy<^+9?d;gtvCTKOQ>Xr_yK`Eruh!MNTQ_s{r;j-v zawRbddS(W881nh0ku?~0A|@h-U)C^ud@zi1X7(1YmP9OUEKEfI=Ye6Au(EYEb0%Vx zur+oy6Eib$Fg1e_5P)%Ubv84$gYn!5(~^!q>_G2(sb_Ld3Tl%md7dE7AX^ktbcQmA zJ4%=hB5$;nw_+Bntb)iO%x_mt)01&#t{ju>3nSb;5X=|!dl4^%OpVYfo!I~MotFud zR>osV4R@+UJbk~d-%I!MwKIsXM3D308%ad?c3RRlqWSdWE^{(sNW<*Idmzd9u(l50 z!T<65h6Xc*IQB-zKr5C*C`~@mkwHyl8dAQbH8Ebl(!~4`-iAzENJL+tcQHCUiTiJOg z8}`d!^C1rcDqsp!E^D@AvqiU@2<=98d<|gV2FBU>A-0VdU7H@kJzO&X zmeOIXgXQko+`HS|0Ww(CTs|yd$v$Ehx>=XJY=Qu@R0e`{nj8Fj$k?Yq%o^8QdYR&W zk|=9~SLUNT2h&eJeZi^R5S-W1b!WuaCaFCjbQZ)5Jk&hd4r2dO&8`EvIv!bZW}>A% zt!S-Jj7qQ*zah(Eb}>>G-0vDC07(Vz@J*PNy@*YK&2h_QOKq(OaIpw@z4qrS#~CaT zyurD2IyF%qQ>Y-O!8uP)J0hlXig6C+H_>B$IOJed5qxpBR{HEx+C+1+ZU~NXVL8#x zYX$2Ccp>e&cXs3V&N_aKm@!VN2X4N^P!O`-+A3csj_X==0R*+;kvc3Ca_~OXTTEl2 zogdJ_K;tDoWhA^|oH)rH)l(1!e9rJ!%AtS~#|4}pEvtpDuDnJIu23c$tUq{?m;mc! zHtHdVL!G&pnu`VYldD3>cq5kr7+=oaCQ-vDGAIifnfBYHsD%L%Ag%udS0bc7*)j<_H2l1a zzYB-HmocaLLn&F@e#isjur5_F!H_&s{M=7;5f^HTN=N+i3BBeRLU}6FVY-|+r&s^# z9V3HE@^NKFHl?>Tp;?A+N}HnhVVT7_7C4s+`RAIa(ml6i+DX7rGFU zI%?Ei3vUe@b1j~gFo>fOj;Ej?&H(B z&o6iUt?Li$cVCZCr0AN&bU{Vgi6>7cZzZb zMPNBieF9o6_i(3?{pg5LpeGJu5~KOP{T+#rDg>Z7xI%3gi0v754#>`$bH?@y$Wnw% zgGXjl0^xnS*`Ru)Dqb@7A<6;uA~kFSW=_%$z||ou(755E-l0jqoO(8%DY_?ov8d_p zK7_xnHoxT=Cdp{Z6A~(74&?eu6m>dv41!g4DXuohY@pci$kXT%L^f{t0>^kuX6X%( zRCaLSYN<;0t(QdHc6cb1O~n~FU9uavYpj8*5<=YN9%=L%8fuXvl<69Q-&r8hfw@sn zl63x(x0Zk$s~vbnN$qw(Nbf}G9U!wxvS++q!Qs)c?%71Lah)Eluf*%(tI>$|e|+1@ zGBd?>8WpZ05-#$O{lOF_4KFfFh2{da)5)^UwI#;ed2o5N#8&E<1!B0+J4tkrhHl+e z5x0l^%NEkd_%Na)*z*VQrnF#1)&B68RXPRVJ90HgOU6(n@V2bGRlrv@mbS9`DDHav z7#fXN_I>a9r1j6Y`I(~1NxFE2@bzdr!SothS?L^!(kFc!b(@*!A8?r|WwxMDDKBTw z{ker-=RpPDML5vhLeb{bLxH!jLni9YMTnDnlaU~>7@eRQ5rQvxjQg;{-O6F4d`A_t zYDGx+0x^vCh%%fC6o;%!MJ0xnrT5g-G9DSNu4p+6`4wQq1!$(Aii&T9nIrZF;lmKq z?Tt>pkOM%h_k=b6Y#G|u;zE^v!y)U*PGD>qf4j*Vt3Bm-s>W0odVTH&?xsd3(_AAu zv-e?|t2!a?)uxgqNy+B5PcsIkLmH44nk)5>2cDStcRCKp`exbCw%%->P*XXUyEg{PkT1tA6Sy zmDZ{__z9a}nJ)e`Im|xEc?7mp>-xj#IcFjLnNkOrjr7vLr1VOeWKeBv;GvW#wpS&N z-1C)NJjvAUagIbT7hv@=JJ_#`IhFqAark;hIbd z^ex%eplO&|$Z2E2YEa^qS+Sv~#dyMKURET;0sX}`;$Rdlh5hm1rt^Eh`#cvc;gNKQ zF|#-QfA#C1xBpw+n7RM$aLnB7tpBUS)oRJcA9A4d&DC2z8UbTt(WaSdV>Af3216%^ zQ$)x!J|`Rr$=d2-OD{#KwSV2HGES79{u?aV}y~ zR84B`)E$%Vh(|$2mT)27&Q!d*xo6rP;pIlX8Zym)$Q)}n&m+rX66f9l?ip6i5SP9a zm~QX1xR}|i(x_j#6M&(KKBRE8(8k(Od3kEJR^$_;0eI!f&Dm7dWnw9^8~NuXzU^E0 zg5NJVXtO?s%`;Ye5>ibi54LdmjS_D2>PN{9nbU45O^Ob-w7FP6sLQBFVzoZ78s!YCR_a3@uG=%iMm2%YuCjW%he z7iwv_469puY)M`;j@Yvd_0%J?DD;%dv+|BgC*BPdoC_{m`~ibEt*2ifJ*lA96jF9y zxRt-QKRfA!G(tNv|F9Ji5FP%QhDl72g$b(;*D6wNHYL@R0)q;$?w579!YZHEZ(Xrc zhdEu0Wd)smVLb(2o(m}=*z=r2mE$N|lkI#_5tst`)xbw%yp%5DQNbeSnLd(}(E+Tm z?NuH{C2t^Z9(N$GQ(fBNxgku!8s_fhw8~mFzt6F&T@wO!*h~pP;)z=Jh1zOQ_na1zBQ!myVU&=~1iamqVCR zywl2_cp<8lxvi$`Rag<4k}Q}ZRAN0b;J)5B1wI|bL1!P-n&TI23|)VsGmfFdGuWJz zcj=d2hDLWzCm=}J^~TYDzLLl@3T9WGP!70&=>5yC_Y31?)ty6))vkn#!iWwMv~NM4 zxBbX@j)@XPVG$7+w6GLunu{151PP?)@EdQb0eMja%M?I$bdIR0#6g-VQzF?^hY7L3 zq@4VaW<3_a9`=h|G-LMj8i$4$Y?comNJmKWfv(@aNO{cjXphVVh{;BUf@Ab_#vun; z-!PPmf=-!fmTku>VAKMv#Gx0f9Sg`a`A-M*VJ(=#hN5MfL(Ke}xh(&MoK8;Ihu=|W zRhR+hh%Nt65MjM3DutK8%ef?^f^=c$_i2{o?%QXdG$-b3q~}``8j{A%_Tg`-K#6=$ z$VK^aO#R&1*~w`H$?9A=9dsI$fr5_M!7q+HL0xrSFMFsOfIL0xWg9|M(95okCFrKl zdavN~#>$CV4ghw`HJ*Y2gh>Lo~Mp z=Uuz5YubD@ljzjWs)aZEK2U-#s#eBV^ink+eE9U#Z`0GQl-+&4iMWu5KDT-^ zk>>flOP?&|4!}hMWzlIc$`U$% zOy3Lgm;k&9|HKq0I`ImzZtZ3=FDd)vkjYJnYbaIDO@HR17XgJfhoYP`_>+XLcR1fk zW!AX%bIc^t$CysO8h_cg*l1C%omZyesxto``QZp_^XcvHi?~1`O2q8^pE%V*3CDpC zL}ybz2!iRuS9DXJ#r>dUcZ5eT5+sP+J=qn^1HsGc3t~T4uepqLa$~&y_dXqtJI?xL zLevmhCd7VX=sK_0r;d2O{F<{4vCxyidLl@OM4t`=@R58) z1zN;U&DZr{#HyaRl6{1qqOZwVXE&$*nL_|OWqS~g-FaE1CXO)1_CeQGW?cz=xNrGK z6|b$(&}M_H!iQXVfBAmU22n_+y3;>QSDR&glLZd(1pyI|E;oYyCPyE)Z+An6QXfTI z{|&i@E}RwnlUHSlM&=HiPv(E8>K6PswwB$Anc!^xy_W$c!@AJ$7^gRogCK7}~8 z$VdV{6cJS&FlMhu2n6Ls1$zYN(N5o!?ECh`&H(gg?;z);M_Bfb$`lUoETrCU1W#E< zVtv?A)d5O7QDOHGOaVcO=tU6YO1Uwa^ z7l0g4s6vgV(hMQCBg8HKn_*pQy;!XOo!6ar=(a~+b z!=gC|x4-!lmY$Bjb@BB~ysk!Yp5)?1hbV=!Z7H>@26&*h276?p+yVPN+<`7}v}ALz z9&J#zqV_2e9%xyZpp{A7xr|#>-fdwTIMtv(rG=d9Ymld11@V~?p%qEJEcPrK2itgd zWZ_OBXX1>!2KGxkjVLdV7yRw8ZjFxVL5wcdD6)?j)oJvf2I7R1`wAdpwV`LV@29+?YQUry9LQQ~KQ2 z%j=YF0ut*e0?0a^wYgwe7E!<3s>0Y#qs8wC{f_%>W|@3=JyBMt@Ikk}TBbh$22tHP z=BhgXtT1Iif=l#CPurzkOvWXzrFM)%SwCH-p=*<%dv?OX!`lcws|M}?8t5e)nW+kO zC9pbyFlr}PSGweh=(?rm#`2vpQDCM*EM@EUZpvho^NcX9(ZiVJ*BzvH=qa{Sohe1A zElZL+EL6NRfV6}CIH&C&a>WTYL`@I5#isIteVXx`yEgobrTNr$SK&8K=ZH^4mQxm9 zm}EfurR8bFqV=F1eBsEGMT%1rw+Hi~WnmAnm^#ewYfT&Bq&xU+YSYtB(o?87Mh$Cd z@`!jU#>BtSDrEQ+uQA$E_x9%dC(P^+XxuWk5$M<)9#~bAmmnC8oY2HpNyf)DdD|d_ zQGm|t7A<3@a;mS}P%!zr2>lJ{_hjF5QnL|FR+-Ia9gCCSM_bRnPDdFGAgeD!J1rts z8?v&XV1|Os^d=phN>!g0KIQzGAoNt#D=DL^Fm3K^MAnLCr+0FX$YDl*FR@{MJ#cUn zNpC}N>zoPEdBb|Hq9(xxIgEUHtk(;0rkp*oB3D>B^bvOgH1tc`e5nIc7-A2fHsTMB zS*-coL}CV_TTQIQ#e)*h$#Jcvswgh|=IFwMl`K@)b`2@`BeE_h-J3ey1;#$l%2PT4 zVffjbyYwpnqBvgeZKP)D)K*UQ*`+wU&vnx7JB!*<6(rB3X@QFUbGLQ>IjHnHLTR@? zUvh1R)-Iu|?hg~U7e>E)^_zc#mX+l{K+DX|^*@7Fb1LbO0&ROvlWSJ3Q`KxyBF)r_ z#z0PGu~NpZ3EN`%96T*yrUedXApZL!5J-C5SujZ+V-X_!L*Uflaq4~OY8xa@C1F&U zPY06}E1U>=p9+B#iLBU7z`NrOJ@t4j`0lGvOmL=%sO!zk+<$xj@cm_z7t8%|I+$Au zw89^gC`@8*W$WQ`rWaQbrxkll>Q{3c2J3N%wzRqb3*8tw71zdL|LKC>SIF}qf;8=L zg;*$zN1R_hAU5sz^&`kJXO$-(Ol4bLJ zkM+yK)`cZ6>j(c-sx2FpVlx+Q#sH54WXfC?Stv73A=h$q0%TbFl9y>#=9u&(7HML$ zG=Zk5akfvnU=Y$6&JSJtl80n3jOkCF?Hx}~M5<#OH z!9CPeJvV+1RLM!axf8Q)8iMZ-_EBrBRO5isFydB;l0c!ARp)U*W7|1!;qR|Y=))?= zS`2}wXVZ8^7(1^1i=iRVo&euR{x^T4rjz)(px4I<3-m|7N%!COPWkeXI+*>(R)9hB zR_QwwY<-2RHns5#9+<~tD31(HwxLqR!Kh|9SmCo3vqfYGxWC1)2*54+y)Av`VjTz1 z8+f6}8Do)uH38Ic-+z$?9M2COEV2!k5)A@PvANe{a;vxH)|16H@te}bh(cq58ugS- zp^f6{GLv&8jy#9B!V!N6zAmR!^P(e4%_1Ey60XD`>Ei>r^bPe8g^19q6a^~ zM^2*v!7My$EUfOfW;suSKVAKVT{%CS+AFoE*%8>2SMx~dvrsf)f};$-nf4k|AHUfB zbftE#mYS|6qlQXS=4SGeeWSDW$*Yo-KAjhF2;NKP(_Tu-(hV-O7aWJd!rlyAvDlti z=677M@cta5kVO}q4n^zenJA5F&Vo)smDezY8^#LGquRTeX-JZcm)TD35g*~RQ@))7Tb zR(Gh{>kq0g^{t&asblE14Y~Pp4eT8MKX$Oey7N5P|*Dn`Xkv?{>pcT@UFG zM`yyh>&Wp*FX2P46n4aV^2~7OSm#nUfLTH$efi>2apU*e^nHsMbB-DHA5{CV`ywXJ z|5+bLH2=hHav=5IXi`m*>;TzFq|obv9Dvw0`cOp?pqw^H`4rGkn$slGNZ)J-3G|hS zO%}=V_K|UW&ZI^RaSm}hNc7V??C>iXB?Q@G%mtev4|sw!ab=LZASospWkTlPI zb9MR%+V|6@9ilkWSxbO_^U4%eDFy6r2BZamDKmv5nMSV543FUl#OXtZ+A~wCoYgA6 zTs1c|!p^-@>#+8Yytb6x5bU>L4%i|z*;YMsenhPdLOb#0hFA(XA$o4Vr|XiyNj+>2 zF&-5TU$ID{ygA}d+PP;9qAbR4U7#l=wQE{329pG?Br$F1g@1Xnz%N4oHoqHD8`6ebqM(#) zGV1BNigW5LBv_S#GPJKAWFMKUP#eWltt7SF$_wI&BOSR|duqP}>J#eL6a(s_o$_Bv z%g`L8P+0PmSEA19*{++)O~`n8zC7;o|wwt36+LznZ22D_3@Slbb!F)4sPJcIhIVuYTs`A_g84EpcOcQfBrp zII;?dR?zTPCog?#i}J&hv9n57lSRsZCprQoosa!wU){q+9NVWPo&h6~G9;ie54zZd zv`bQ!d?iDWv{q{{QiD^@GUZAMQKVI5p_SXtnL~TIE@jy5_7#v%NZ7ZG+`2eIQp2@w zYqlov^S(?a7Gc%MgjL19sa#nE8^7-rXW;+(xMxEKznIHm!Q7)0g9BCke3#8B33Wl~ zb1}XwdbTRM3~tJ*7uw(a6*+ng2g{R`w&FI^@z`2H2mWCCYbxHmf(2ZAW7z_0hmd%; z{V#Me9GTTc5gdQSInVcsbOY~%W}=P{JxCB>#PX;mo;hY2`(Zk)h%<!4s~_Uh--kOzUx-*fp5> zH@$SZH81y>|JH(FcOxJNKB|$H-k=63Y)xL`fxI#K6<=(NT(XgmGgYbFp`8Olo z1LU7t550Jy<3IEeyl~b~6uLMUh%x;bZqiiWnRmEQf|ULW_cQ1VbA7sx@Ic8>a*58- zes}rQr|iW^&G#C#!otsELJ-NAgFoDdk&@VuwKg`x%;%YMLOeG+8!NVk4r8+5Rb~dJ^;OTt*dH4r7bkD z9Mb&|}NIeKmrO4Hg;gIFRHV_)B^hlYK zfs5zMB@gXqX0l>_HSvGAvPLAcYcU=kn`SE-@j(JSo8&Zz@+gz9{G9{dzO5mO$-2l6 ztkZ@k%wq5I0LQ!Ukjp;3NRTy{dQ409Gpr18!7!{Fwsy`m2} zCdS`<#wvJV=_WO@ zXES%ETyg6AwtHjm@IgTA1-L|64dbdvZ4=*bzW#Cr#nfjIgKdb>P|+XH$TUt zTQoZ()5G^OE!QdNqGE3FhsJj=)OR)h9xVKgm`P&zdHY+-WY)a6-XroA{t!qdb$7S@ zg@EAQz{ZQGLV}PANoBvKcwUR7azZT9y<^Mvr>C2srFsDsDH?Pn7K9a(A-14e?3gx` zLL{YihuB-%I=UH9)Mq&aCN||tx1sW@@ptX;$Aub2hA3X z%_@=fqUL%HSUU&5OD0;%9mmw8Oj%4NS}U^Y1lOD+AT0iF+ZJ`>rmQyi#_Tr(zkR_lJuqW`k}5g%epf z@?-R_<%Amdisl5`}6nPjSK@y|4&P*Y7`$f2t6hBu%ZVE*U_+&w7%?x(_-VhJe{uPrM;u_L*QHWfCU{s-TFVit@lF**aalTKmI@V*bh&`1c&x6Y{s^dBxW{Cjmxo85~4^-DiaV& z`x`Ubby>Z?!uc(kT&+!Tj|X5Q@q|M@xv&(;@Ef_MG+_Z%;r^@+4X`c$2MWiL=9*n; z-~PPl_^`a%PkINER-uZ}N=A3-0#KP+$D&u8kNv@g`tzcn(CZR!<4oy!?Y+lw-ESM? zABC>$yWle6P+?B^xXrRUnC`zv-6Ry@(94P;IpG404y<_!GpC-0O`8|T^ATeuPk0Ly z4L>50-svs6xDpH`i|AC(cmd6lHlYjEeDd zMEq^vw=orbP7v@rgnuT>c{k@H##<_HQUhFDG_S7D9G!^2ZjUB3l%#;Se-Wg*>n_Qp z$x%^OdBUr3PjGgm$y{H0`#dwI#~Y3Rn~UuKF>rEm{lD`j(f@ZHt5;LkVS@?H|E6B5 zQVkt?Ywbv+}tUTcaE{73b$rgCLx;r`yNf^@n@_)Yp7} zmy#xKO`cUHBKe7|NB~Ng((VZ7N`K7KRSe<53Zxp zDlj&}wJIV|FYNAM5ARj6croG?eSKj;iPT4wK#{nH+F7*7w3(t@1fVG~t|^JUliCb$ z`+uLs%6)yPMPYyKjgjIuVbJi>yA7z%M%Hqa_6uqPa;8<{Si`mshYka0qj=6Bu>p&w zAo*DX@<3os$brNy{A*_Mz6$-@yA`Oj+Cx$iIlt}&+J=CFof=Rt27??SgUFa4ei4hf zIjcr78`K;-@GrJ6KR?E7TGrWU`uMPgW_C`w5^&`jx3 zdlf=)pV%8VNxfhHtJHAZ)AC;5k)wvoT?SjH&t<)&4&pG4%0sSr`^d)~Ua;<${bm*u zAQ=P|>%XK=Bn@PQv@U$19-7W|JfjnO^+aOU^@1rMO`5r;VfsLujhv+&t5By!*;d_# zaTRtPYv%cS>`^rR1IUUv32K#L$R<;!gGfa3Cw$+`E@|7ob(hVFvWqa?NRYZg?G>JK zQqaIcIHI(EiKjb0H;Pbiag13ga&@bKg@>KU;!vwu@sg>~c+*qMIypM)x~dX3!4)vJ zjLbDbBeVh&1`CcW9n}$CeliWdgn#b&8v855tvz%bU4v7JWF2U!ZF@1}d42g=C~WB? zOjprIeRBP%B_C@07RhSz<~5{;l|4RsA3ti@jkfCCn8MqgnfC?ko?3|X@Bf&C?LYj6 zo$LR{h$S2U&xqA`s>ziNk-Esfx-{j!fMyw3W|{b?f(bwWIFNdliWJF0W=$yU?`y#& zx~XDnx=G;OAdL|5@OmPAvHU!-43L`T_>~-fZrhzb!Gx0Sm_|X1EHPo5J@*aQG`gnY zrcv>1-X}Fk_G&MDSl{38#cDWi)&!S#+)GhpXL$*;e35gao&0dEZv~sREL1I4Ypc5x zUDLUX`Ox3iKb_VbmhvmP!P(62g8D$cLIb zdYl<06oOvQkmW~yG7>{!^+aLDEQilg-*~Dzfw+mf6<@eH%sD?>D@(Jyk5fY5?Lo0v z&7vzBMSLkFC9Ui8pD|+?u=z5YEEbd{GQac-zM_p+yR$k&pely$IyO!OTBh^B+3|5< zi+rTYY6V48j|>>-OkW+zLl*fxk;K!h>Xy#NkxH+Ymq+q)wH39HHD`?vqMg>*{mn=* z<}`U;cVzp^i_4ean-skfK&EBX>)Quke@$ z_K>|da(JUY)Ux#DcNbd;UHeC%T70d`6=U*5yumVYyb{C0us%ioa9@TdqS5q-wTDt^U z{N7!ac!|%Br;ZEo>E>KPVwBEpZZy<;9m-QR-jLo;(r%B{d4s=LEv-P@oeI2@*PECz zEf~s1)W&cOj(#pFc5Q5F;=7E>>z5=iCbGPDb-&hd9nm9AA8y!;Rj;Fd?m70m-Tk6? zFC%1+bfb^6a0higXx%jS@sTF5^6DPMI}rB1Hi&^?oe%)JpC%aMxa>)zW4hZ{xq+ju z?H(IvGZ=W|7603Neu(Fsm#LMB2AL%oy2R z1a1BK#8$;jMI|E>O29}tT3BAtzpnOwW8?exr#Jy#+)4`{is*P#T#e?Q6oBl=(CDTJ8AaUF5i3->%<6llERq4mh% zP)1`jB~?)VrXgzS`J@U40};$lJE^lHWzBk~&kBcq{bbcYUjhYk$^q-w?!B>WW@Ee7 zt%{QCPKQ9&AABkx65R$zMz40<*LU(v-1*BY5iU}vv8PSr3oSFBO_%;hG3raYx3+SQ zpa9P|1h$A21ryY)?YDk$z&zT{GVll;BUlm}Y5|>PH-Wm^a zS_-=p6@oeP*x&+fPov<*$VPBN%g!^3XCEXlCJ`=BdOLwqmllena2o>jfag87ve;2y z(@{UZhr$mR!g3lZ3wPuio7YF}$UP}dX7*|pgnF3MUp&HYM%lav;Y+o5`{&6w?fTOl z&j^amz^lk{TEMmfvv~6LT*pU zN;-CHAo~|QrcDR34OVU*yFLG#)5noR@vpyP{|=ykobg}1er9H-|G5*^s`>u}&`rG( zKB!G`8p&iDp=Emn2y`&X8L=Zm*dZwW0tRlRv$U1R!;Nf|D8J=Kw{8LCPzo0#LjRlj z*;w*2XSA)Tb zN&~Xgk(2; zwJh;{=i?$99|7AUP?kfuxb?Tv}?NYz%2u zXNyV2d5}&EOq{uiVcgOM$y?qe7rWRbV74NRs3l}+xKnXHD@WeUBqlL~rn5A2`szCy zP=PLFIn4^};aHCWko#+?!E(}%c>WEfX!xd%{s`=Rj zLjDp29Zt|piXq#rbxyvdH=RIA6B3v#78ikU%<>+j>pc>&or7qvC>cmf$uqyFWUPaEjHgm9S%-h_|N3s~Z_T46AZ+WNTGZLV+XhaQ=r%+_TY>#E!Au1F zwi2?68m^pqqr#V8T+4GYgp(rUd%RCpPq$N+99i!I(k8_!N8X2q&7RL~NF_Vz(R`0hD|IO4rF=*| za_UUTtLs6}D5=ZxI?Cdnv-998!ofQ5$i>bbH$j6?0*BGX@%UbAJh~n~>gdV@H5SsN zL+an0HE24H!}=#C9C_~qwGLx_l*&n-NvWml?WHR9uR0AUOmV33lfkQ_aclQ}oeO~0 zd*c`mINw2lG2S%4x%;IJ+QcAM`NflXe}l!kQZBS0i4|IB=D3#$N%0;}%;`=V&c`IB z3>=UKU{yavdCtvO4yuiK0ABE(psj|P2Av(r`~AIC`8IwuQ_X7teYq;~G=($gNd}F` zs%T(E^EN7Xm09XHqA#b9r~MZe0H$Sv=%k0bAOm9Bo6)Ukkch(Rs5|p7kgCz}B3C%s zCXg_QG+rPsC0S&V=EA77<%>|MwK5fskW4bsy+7z4{GcqUQGXE_&m{{Cqt721s*u0G z3!(Hf5PQ{%d1@h3=3YwNnv%;7`;J5`xXdoYfwGmPYLQX z=LzGoQdR&$Hr3h?=f&_CteL`D@Vo~Eyh3#V#AyAY&_AW%TK=s{>>9Kqyq?xOg-JXt zcon@2u@#zj^g`d2;xjWKBqPn}Vs_dK&s`CgM0xPVxVOEH;i)_4 z7cuF%wEx(+pRhbN$G%rQOPR}z3&vGHY_bvfs z6XdI{gDIClmad;%kcPAhSjn!52J~?ZdxPR@Kz8fWVQOO+Th{yA`c9Q9h71+$g06dO z=-J1^hT5w1Be8^=t_!(mRn<7p-TFSs-I{@(sb_|PtM)SedgFvKdJ`mlS$$+g4@ag& z0bNL5tGRug6~y3E&ipP-D0ZIqivOG1JPpgyv6Zcdt~e$Jj_ znr74arKZSv^CkQ;&q|i!s_m2yTWr1_<#mP2w?Q`8Y;L_|lXFvXlJWcx)JQD6GL7v0phv@ zKA%eZ1;4Xr>ymjzSM4=1ld3CE!Z)y0e!ScJx726$#xh#Y*ViWg#?j4Q`4$}KMP|zu z%4+0(rb{rrRp;V@eRLx_N5W2_@cvQjMBW-$r?fumIOj0Dw`pDIU!Iepfm4B8fY<55 zZc;g>Y!>bNr*J@dy443!1Y1}phUf{(q*et{!`HP*z#h8%cH=0RTTKX91kxG!RoME4 zZSVVVw?8AOvW+tO@2FvB`mc327YED#x@(%z(stOCK=Oa7SBis#NyTE2jx17zYzV=! zGzOzODB?gXE*MYkU_uOwpvQc>%U#D-K@;zu&?U6Jo}HbYo}Im`WvEl!(dYSfl>NPx z7hktZYP?={^HKaZ&1z@C(G@2lD=L0?KAnf%uW(*nbX?7+zP$Z<{r-~3o&{t4-W={F zFK1YrnL2K(I>M!5hOUMp0rI02Q}!fgqeJRXV^n>2lEDwhf>V=m`!-ii+j6pfT;zhY z`xpv(0z6{=z%T|oHXePqgbqtO5bsc8;$yrdU0PNng8Fc`^c*8aflAbohK$jqU-L^E z<;Wh_G%@D4ujnva1xzdJnCe_p45JqfZR%u_mYO(U)#U}kU4UGQL`h{YFM8d1_jO@> zy>u_Q0*1Y^1{*bPXDKptdkjsvgH6|R7Q!%_k$Y46D1b!K%cZ+d1dwMbw^C_4B-bQ0 z^>S7a)`&3p55tz-5*wMZ?IBemf=i!1Ie@G2=2!>$Di>=?CU6)h?@ow7?I~c%UtLdT zVs=-=C{Pnw5jrKV{hrgN|-$Hu~;Hd*Wf z7N~R(wOF3~Q0-roYBiL~0{~ip6`Ghnv)>%QtDzI0N9C@6-RX9O_Wei92K*}nf{_gx2|8}=PM z-u_nVaq)0Bzlz-Lf58-AyxHjUxC9z=m-jL5KLZ+bmb38pM2Vx-H>1*tsyL4=J0^hUW3AYK922pihDgjCyU6UZzX5`89kAiVoQ%f_PHb5 zX&0Z;q|*rxW2-k8=52J{&TgDgmySBwM&MuZYh;DLii|rH(f6{#ZJ-OvThboHaOzsz z09ORRdd*GP%G`|x7F_@pNcFeyG8n` zrlG)gZ%oY^>#6j_Olc7A5}<>-5)MR+Q$B+)#v+5Nl`fl`9=HLx)`z@ zL*K8tos3$5XghiUQB4Kz7n;!HScZ`P3YwbCbPQAoboBQY1`Vbry7+t~RhFT$Xi6Lp zVVUQGT+>k6M@ePoNB9of7)#S9ja!6f$ql#A;Qze!em>_Kq>>47i4Lz z69Lg|5OWGU;{T@MP! zB^20aqdux60_j`|42W~U*4@w^{)6GycgtS%6ayK%>qJ29DZ-9T$(*v?e)Oh*8*9I}q81Gn4G;lhmM{OMCmL#^3>acw>yH&lG=%s}) zfdFykhhW8yfVun?4LAcg1WX$CX!Rg3rp1qrgMh1)j1K{92Dt&R3I|zU;~k!gcvoAC zSk)cD;3{0bx+xSI)@a^tffOB*Jmsf{VP60eM`p+G7gVw3q{0aK(t5fQzLpZUkRYyx zQsPJv`z_GGOBhC6sucO!JhQxB`d={zdh&j_i>n|GP0k?;0w|6(#-5)!&>($mf+v=W z=TbPAK-M@3&w&9y?43+(G_>K1l~{<&t@`S!dA7WMggtxCbpQhFxGWLuRr_W~rI;jB zX0dAoJfJULHHfS=$`t>a%B8pDBOt zY%z=9PRkC`K8-8d#8&)EzF5~Usy%Fyq|@j6QL>@IO<12Vv=Q#+PTOdkp|xsayX4DD z8g+yFi$aWT>8Xu2qx{XSdN&K59}5ZNA5(;ngw0em#}36~r2y4v8|8{WhF$sS`F zaS++Y=lHDndG<`TOi^}vW`Kx_h|YXRF8`3u_9vvR#E1$j zbeGTJrAcRij=fLw|Harj@aVdBTe?=+wz0~#ZQHhO+pBEbwr$(CZTC8-Pj@=`cGCOJ z^9$Z&a?EkvOF1xYqHw9 z1hOud-j0(ZKG`5hp_)25(ps)~3z+MBErYZy*=y5#ChUP?tN`S(?!M^4=(k}Q$ zU}N5@AbY+ojlJ3b=!m36bHfS@)+i-=IIxOCPRk(~%HP!48TAF%%Lid6E#_r(bH ziP+YBrJz##7O}B#=tX;TPyUlqWu@CbUik zPCV0|U?hN-nwW$Szf(6EJv;Gl^22gM9hjP$D!1*}fV=s5zWWHhD3Yij{D?@yKWLm0 zF|sODWLDfI%yt>UiTFq`*2c-`m!`I5J;suzcPtQA+rY?g_!MQ9xlHy z#6XdlW4vY$03XxO)v-rY0Bt(t>0w`!SJn-EOzTMEjBXJ9i5bYd9uC9id3`n8+Muo% zxF%=`V5i2BY3I9p&}m_9AvqB@yRmUM*z5jfUhIZUWhY2kivPTT&-qIhQx2c}dwFqA zyo8@i0F$OfAN;N*<)<@qGofyM)5Fk&dlQ!J6obnTyfFWu_8Hfo7{9Qb+_S)XiEF7w zjQ}$rUwr#tD9AH z;73GaBSu%?jz4t%>iD*r8u}pHo&%{r_OTch&2915L}sI1E_|a&{fV4oiK*xADWh!q zZfa$V$-9USmuc3KU}eDEK>l}3`QcGgz#paZVb0d9Ee(cYV6{oGP@2@#iSS*&c5IG3 zt=5Wi7gS}j_|0G2@_q+%J7G79OwYoIpYF&UCkgJv5X0BJ{w7i>hX**(E8+q#9nKhA zGQTd7=Ls1xT?^&zahiyGdL54r#$FXWx}>8(0s`EFW!6&)eFW;9JW!KWzm{=?oeJKu z+%+$AOH&ygGvvot4dc?5tg%}A-EI*rYzlx<$>v~a+*ELo(HC^lTwPQy5GsH-BVb2M zeqWD}EGR0G*<3>Ti+N>aZ!Xz;i9JkoH2+j!KPd!=yHeM@eLuv8sxD$R9?DN@m$NZP z3He}});Of0Sm%LC5_jq=D{*gih1t7Kb21Po5EUs`{75R(&DS@}J{?)lGEQa*1Gh$( zIqGbt3smjF2r!Vy3_ghRDAVt%xlHtQ!XCl{8=Mh5Xhlnb0PkH+fXB#Gz6LT0?lt*A z@SC@9TNHc^yK?5}*uUmp7r1*2;&w`q7b@RS(y%S44F<`?I-Rs7&j?l(VuQ1>6{JuO)&V{f z+xB58&Ds^v;<-CO6XosYJmYo`8guNcK~QvWS9FWjE(+ZE(<=a>atB&-K~;%!wti&! z{T#UK>^O<@>b=m4EyR=18TEMTGFt2f#jHSFQVGBk%0Oh*atSXSJ1`b(z)1oG#qTORs{+}_!NqHypN!D$jv;6JsuN3-dPf2wEKI9gLWyoDC)|FE zAGH*4reXQODNok|pDsSSJb{)fZ2m?FM7j?1@T7oTf`{7a0n6~B1FK0Wx6S^IbIpi& z0SB0DDww#?jpG<*+;212HDX=} zF{f}nt=aK$rV1fZEkamc+^839fBbMoa4SR%X$Wdl>m*|#VM>nKq0eU_*r|l(9yf!; zgOPOWebv`Yam6{)bq&Fx6NV(gB}|0f8Bz|y5IqDgArgAAeS}0Eh%aLA_B@5`MJ-kA z#Au}qk?@mKL9E^Q6pQV-ZYH%0&_A8`1%Sl&pxOwy%gA85F@WF^1!t7zf^)zWF|HVM ze7niCi_G?cOqCJTLZ5R0bQX*^*nhN?Ex(ZAk<5NA2A9; zSL)W!!Q)V@JUyHX!1X$N!qtV5hEtZB(y6CP%*lT5K-R!$#p)ugIb2ZLh_;i6FsrX{ z7Ec=L&gYbF(7z_V!)1xxGnuBi3pCs37%WuMCWbdNLx>nFkgqH#!5mtzTx;xo+^P>f zFSQUl>XPhN6MwZ!g(et>!+DU=$)6vUt^YjqM#hPH#)_^*Xj3+>EqG!5i#K)^$p8Ky zy4Zhmh_N&NPZRqu4)&&0C2cp@{_D_(Ovb;sgPuqMPBQX+KA)Qk@^Yv*-_Bd^w*&!U z0;o9aS&weFQDk)?7o2A;bwoj$tx2~nnXg8cwr`YPY#^7gd2KlmI$`XId+aa-pL%V1 zz!Py9?<7*9);D-UEI8kbbp>sa(vF-jkClqAu5YmYjBK($HVMBO_u_JYB$F%}g#z{@ z0kC_#njpD#X^i8C=8ZWyL;=V4KvEa!7;1;4%wSgUeAP9*xlIu|e~=#ZK3jGGu%I9Q zITa0s7TU)$LHy+R_ro_5X=*o`%UXR18w8=Hqllegsvq4H ziDcRcz;GE}%tsy*2kjpRvnxf*8rC=L-yT02w0!rbk>*6UQ_Jzy4|nUD{i_@z!+*O7@R)%#gwoGIsFEc<0tft8mJ43)znLr-_&82WVi=_P~NoXz^E# zfotceA5WBS4Lb(sDjQvPs>B8L_)euxe_qCoZx*|=QgLRX{|*XAad+AmkJE4S-wI_$ zOe}hOiGExYq>-E9Z)tZa6LrJ=e=C1$Ds;Lq{uH9_6{4*xkFoE*0)x$Zz9f4Gro@{P zp|h&DpvVa53i_++jrxW$ic=R!Miid<_!DM%2GF;xv$0;!)@NUp9Wa;Nz3#Nx0lKlr zUh5*U$N1u!<%#?|W+N?<+?@rEGtrqV;6i*_OW@7AOPi1((3pdR13p2m*g=VyFj@AR zqi-AZNKk%6^u1{G9JWy8&{(B`*8aFD!2t@3M4GRzZeNsQM7u~v-9pm7XW;#z+%P9! zDaOuTi;P|779J#9@n6{6eAEqs57sERmlk@U6LS!jTY|(dsaYf9r3pje9C}nBrLQeYf`eK!qoCdgjV(ms64DtEU2DE-C2SV-&1Ab z^Y_%XbrV}e_7?0cwkqBAnr@E8uwCK6zGUTBKGGki3}q|dh5a>q)BU_^<1InKCW^Ie ziM@@$nc%OE+cqP(VE|kX%SeYJjjAm7k;I47l)qNcl0SO~QL~V|uVPk>O(1X6=vLXx ztvPgAqJw~VC=);WlfR@WMQ{4VLp{>}uoxDMxgpl?Iv8o;#+iEWiUZcmCE*<5Pi*qa zqMHvi&{j130O-keO8isg|I=ETmHA(j6Pwf|9sl=j-@71kjMP=7JN zwupW;H=ow_G1V5CDw!-B#jb4$R;Mi8mJ93CV3}u_?!yxp@22yx9U9+dYsdb-(kYR- z1*N@J_l?cB*N-?TQJ>}v3a4y!vqFUSXaHWAU49-XvAl8#>Z*HOY#!KPNU7Rx1596U zT4%L+lbkaTW23p_Qa*i=J&qD#F&S-}5HCV-Ba(5| z5|I7OL_V8jThlQHLJe>Gk09H4z$0H-md*Mjf4E>m1qQN?Z{bfx=h+RVv$M`yiuAHU zhxyo&`ocgHpb`5Q!L<1rUt z=4v4tv})d4vm(<>A-xhHgoz``Lss&abg2Z6Qr9ygSb!*g+;^FI zH?LUhRZb*g%+SNot%+DJh>|FdT;V7~0;ih>lXXa2_wr6N+>RLDxSkHWjKtIOpeB~0)4(7<`% z1*`K}5))5<2`A6;_?bk{*b;_I5#6A0CSd@E{`6ZL#Jz5;7n<(}brj^0qNcO`sSC1) zk2u65;L~v|dqI1ws-VtmSIVM0q>0KFu@;C%QshMS*?c~c*|FVz!j^k=K*s06lcxu> z3VmmthrhW`pFmTVp~$7%3BwAD09HWqZa(EFD{)eqPBW(}fuz(K2wEt!xW%Ch6L7jj*b6pd33L25Kcm_L*1HIcd0&k@el_TTgs79zMMDqPt zscQVH)P-cn<5$?EEN1_H8tb(@jTvX~k*0cTe|8_bgohqeSHa?Io?Cku~?^<^{m2`S!!>NDxT7lUB=Hr6=uH}1Pvr1UO+X3O+QE?V7c zjnT4>1Q6}^csTgrpyJ0yZJ}F03IPxFPQQmqnT{RcJAhGFn8ua|Q?dM4o5AUm_d>tS zyl3`8Rq`g6pgd3Uap8l!lk#r{X5Z$qskoof_ht=qWtyK`vsZ~5fTgTlIqz{`AfCJ@ zD9dmjo9d5?*YVLv5Xd@X3}FlEr^|UxtY(D)q3<5)?bA=V?%iAs+itt-9(Ivr z=iQ?eP^~pv&vqdOCwftUN}9#{1VEybgpEyQO4M2h0Tkg<$5T_UF}U_x8Nzx*S09IvHl{;rezqoO|#LhBv6uFFna^&V#r(wis!R$>JVRUkbnFDLe&k z$8fy|{DhnlLy!i;rgCHKUI-GqL4aUKq+}Zp)8f`l$SiVmvt+V9JPd8LdoQ^PgP(hcf(;I#7np?RVK?TmMoSCn<&Qx zK_>?_4Pp=(p?`d=b+O|0PA`G_?XS6CK33nXU7S662eXii=)*Z1oWVkYi_F)z~%Ry|)blc+pbXV0@df=}X6l#(%OeBw0D z)2Tcn*YL7x8GF%-7m7vWE(1`I&x;Bn#g|1TQaIK!2Y~)vqIRnx4gJ5j(&j;?Wqv}B8D-I zGm3?f$rxBNfbz?@DzF?Z4;N+5tQqKM!9+fFsvsswd^zY3{FwR#Zlxe*uWLQ!rYKLs=;;0}=ur8qncpooZb9zrjRauX%I@y3bIoiF)Nsi^>{vk8dTGS} zf{>TcAomD*%<^8M(4Z8tAGf^AsC1GAfj=Ga0ASII+`P)FJo%`uyg5Jge zr75nyg3n0KVa3|l=HHru3-m0LW2R!4RS_mg*)3uXvcX<^j*$V>VQ#*_$Baw#4=B9g zz+O_CxSmCp{}u-vGFndSY9g*o-{n4voMa+qC)F~{cVeEF-G zKXRmv07{^ag|~DQZ!ne(&i?SguEdwEG4G=%w1*66vo0znVGtT)b2#Whrj@KaninN5 z04Cn^Crd4%#F9fA^$eP;-I}va&2Ol>MqemhYWDgLxUZ&d+~~G#*#TRMSyxrFxr$Ax zeAkB)rND8w_q3@;If}2MM!Ry@iw-*GFLucK2?a6F!P+}KIp(tduV!fkmOj6SrV zQ2LX3aOo6AC_sao=q9zOzdlasIJVm^SS7C$v6c0bXg@zG@qNKW6DinI7Ds;cyHnAy zJYdPWo_49ZDrmKD-_A6)ZGuU!cRgpxkg7euB;>W(Ew`vczR9u%iVmVmdCv-RgD9{j zw84@*q9iIG%5k)jt4>)rysG_4UDq=F3dmARMg@=X33AC_74!Al!87T-u(Pb{$^PuL zyV707p+(P2Sa)-v;*%PSLjlFfU&md0_Kn=!~bTHaaG{pS6&S14pN@6M>1{YpjO z)|E1S>=Rwq`ErvaG^=CHEOb%~`}C?Q**P!$kL#=w8o|XDf$uojVbe{PrXaV8mbUC^ zXpWCKHq$EDwaUuM&xK^ZPlEhqSlxRxKDh+qM^-2iwJUR$_7@lkSQFKM=D7b?$Wn5* zGsdTtHLy^0vWBFU!KbIA`!Cm?gQF8Z8zcSyMXb}a|7Cdn_wWDj>ATY0u)$)5_g+!G zt@F-f!`AV~ABC}jYUGPOB&f2^t?vpCUeyqchbrO!=`wAsh$N=mCcAJ$LYHnpWah-q zZcBhBFHoZ|%N>o6hzL+NN@Ruw8gI|dtp7{3jc^=pbx1=N<93|UI3n8qL$T|MrSv=Y zcM|w-9b#U?ER0WvRt|;9h*dwd)rOHx(3wk*KNwno?5%H?i34u;>U${Tpf~*Wmvq+z zfT?UD(D&Q|BBK{{T@NbyqwSZTI>2JE3IbGNVP#f9e}3&4K92{=4omWoH3!`wC}L58 zqJb+4S0WXH_JioBRYJ6PB+`f10jlT7L7XxDr0f|piw!GI}?jMk~^yTU+0Cpsn)BGZcHR@9yWn~Sn$ zvAd5CUU2-mHgsjg4Q`s9sDhpL#Pj1smjVn&U#wRGXnF2vZEX*=pN$Bbz@oC^7csO- zMrwwffkOaCwfwdIoP^(cpoJn#?5fC@ya3Qrj{g(3z+7pDZ-|XaEJW#7%EA4sGrjVM z-_ua`c@KGYu?78Bl$)Xs7&c2A(tcvPfKSx@L+Xyud433j4Zj1H2~?&Z9pRn<_T02L zj1Noof$5jc>)I@M&yhk)mHA(|dP)#kbMtQ&-TK1sg}GAT9Pcq}!jW~Sh8)kYl@!s1 zwU?dH0=Ta41_v*NKc;`qYJV($TD~8=R`NIzYp_x3s*ykwqD=SC$G zbBF0If)Vr7NDn1X)K8pa+P2t|L3aZ3tOjADJ1`(aRbYmIvl12+)g{9N>jjCv5=e1U zIV?y;j~<;ExX4McOy=3Ds}=G+W)<|=UZEvAJR1?wSQOefrX;X;gxTsa^h|VukXYog zQaCM07Vh+z;_T{eNTykt6O<*8txEM~rw0%0DLg6E;dC0g|iS{xsTQ@W$vBjYS-m1DUbuoSu3X3XGlfsmjDb7kENroQp^M#SAyk^+f zdhN~9@&!7o5c)cyYDG7UQ$F{g?R7XNVd^%D288J`Gn+6G0-sUIev2cD!46xwdZg|9hZCDmMW-aaosV~I&{ck@!b*Qx zCe_PC`p*??#`4$1Engp1t;`*(IIN!QuT_H?nLGqd4sK;i%ft&Kvx`+{cl(5Jj@t9& zO2!Fpx2+8o!tgqUX>tytCQuSY)@#|PUf_dT%MWm$?xNz@UCgbJuzTnxd!RPepShI1 z99ShT+SJbSUxC7Lv4co_V zI<8Y+sDOnxY^W?TF3otMsk4sD4A$q|lb=57o$kKs{| zWu|x_H92(`(@K)7uQMkkoyir&c8D&Pj>ew25lg~t~q)2{!8G_G`YqzMeYM=3a z=JG7NQm!k&a+Ue%2$M=^7l(75i%ojff^}%`&Yo_grJU69-I6x&^IIKv;6JNAJ@Y?J zHVprs!ddm#tG~g5>@!nC$B`R*5Qh3!B432ViABZo~A1zD|SN#MYtEI)3h~#gWZ_k>V?bf z>FTxA$ZkFZ@?5M@p`_Y2_>!|<<{I$4artijc0Qic`Xi6%M_g2=ruH(dGv91E-5FMs z{E`a0FO4XaFP5r6(yU>a7>6|!28nmTrtusvJ6IRzxvNTh9~@>}iDPkf)U?cANL-k0 z(rJVFVBF2VZf4VH#UNe5O07j}?Qdo2Q#oogg!-z&d&8ro;r8PLzk6-pggI#QoSW!? zmUCUIGLCbaj7Nz5dO+q9IV2t`y``1Gfu(G7vJZj12v$|621B)@!EyPHEAfd$t4jdT z7CZv;X7Qj3Ko{VzAFv;Wd1&<1Qh8mzEIm;_y_xb^bZnb!R$Gf1#J!seV}}kF7J=d5 z9e}twFo?L!>~}J=2rvv5W~Ht!U>o@fqNk{CO=VrH1dxN?k5HYeG=I#iBodIUIsZZi z*){QiiiAA8SG1OG0^dc7KcTs5%sY*OrWQab)iZzy{N{6;liJHu9jNqPXDos_y~upR z5j>QCGj!ixPU)IZVm+ru4!F+sin>481p9ycHpRgPZ5G{V;1mi%$Zjl}; zvjznfm?CDu_Q(=nk9w3z+byYP;id1>v+4aQO)_pAHop{@UOO^3Lg7Qn!t>MJ{o(W? ztX^8o6Do!p8^S3N8zn@GZNLjKyo8LY-Za+p)WpcKDl(m&luVB53Vz=+?=Y6WeB{1y zH!dMbKxi~M-jCD=jUMCD}jP!-zCI*A-PeRJab96F?_HqxiT4#1J9VL$|b%e%}MdJgo4-X7r69LMc7{! zaVKnM6aF&Jss)r=L3v?wvq_1Ko@}BP8qK|2YNnD534x5cK$xQ*0{}UBg92S5`H_ND zrUj2PPoM_%fTv>8w$!>_e^@fIK-f+10aAriN)gM-B$uq@b4*<&JUO>mPFX}a z#}YOtvz3!{_tkigbwXM|1cmn@a^NAT2!S8P3Qbvm)VS6kN~2l-SPCw<1+L&OB|zie z_F6I;?*6zsPpY_(T;vyc2p42%XD1NGSo!tgPJ$Q$iSSMw>>DQEOdux2MC5dD@lqB_ z!S(WKYhbc)Fp^q*3I3#jR*@#(BZqeb(us^?lTEAhROku~z6qI8AlwYX)!jrr>lPBs zg4G9FZD-M96^S6_5J(XqiPPR8A`aBR zq6Ev_oLjoz(UO!`$^Ib=veNyh(UkT7T=D%20W?WP(>CM3i6y&b7UBfWNZ^&m^CU$J z#pdblTvFrrd|2}Wii-XV6FoV!BYnj(={!RuC-+%5UMIaPYjd{_L0wEzhKQaGNudZ3 z3rtV@W{C0fhf~ShpNBJ#H#ZCTgmYukUk-}4WJEu5LG2?ohf+B0qQ;u6&>eU^O*ZNY z6S=QW^dIz{gN8s0VTJlZb)m@VNep#*U_^;Q^5-Dvq2|D~lH*EFNR-1UV-r8Ozb|FY)j3 zU7uS_k_c~E>v-w~6DK28^ccb9*O7VZjuz8@7^mI1BVFQ)(~|ySj~PYO+>xeNQ_8-@73l)$dg*4h*-Oa~=WL zPe~d$XPGP1yF+koaH}IlvMx|YyGPfwM~LVscf%iXw714Q;MMd4^OjYt9%*rOMWZKwD(*QEgN7$)-+ zk(?a$ORtPm$xkA;OfqaHfl+RsQU72;!-i3bc+uoi17H=}Ax9U$4~=d2FW85T)Cm%B z){e6FZNL-&u)jnuwK+Zvl}@7-y>s(i@9(uO&SpIunI2)owfLPh~GHrxat15?*Eut`^5B$ zBtYHmUB9I2#Wh%k^a`MBVrfxvvUhFU@=DkBEHphPz(SykH5wOh{Lz4u|GodAb|zo?}pn4p%*AL)~R7oL6dxYJw{A1P12e?N2%;# z-5cV67P(IOl#RbhEUQK63FgX}IedUednxkza!#2*t7b7c`a$<*LCd{>#_mHBb8Dh( zTJwWFyp{ra#Y`E;QK@zD>PfL((sqy|V4Mn-_(ZSn$x!}`rP59kBbg0P>SM63%q7X4 zcp<216N5z2C8oj_$jF;RqOE8x73sgc&sR-?#poGF-Qqz9<~N_xpFP(%ofm{B91feN z@-2mwhBnqwV%yhbyx&65R7bH#SxG*BM-+*r59y@K6hc)vL}DnN6ryH|pN}qVBqDFR z0*#8#wnHhRRycF?bAaC~fgo|Y@EHb8ZSJBQQz@aW#+?wm?ZP>M)CwsTB^^^pT9(^{ zTrzh?#!?IM%YGjfcLI$2{ zt_QOpbDB>ca?n}Yox5U(&&(zvJ;*R-t%6*?+FS*3ZA^G=S%%bznrPZGrij+y{0nLz zQ5hD~naq>UfNKimj|3isZzc`PCluIbh&-y)k3Vo*-=mQ}51{WXRhj#7(aa3jno`;2 zp3Y2DRerh_M(=GcM(X)2jwO;_DNoupk_dvHV@}~uNAZ~>^OfwNDrWsyx02KkS^Vp_ z@_Pq$O?GBn_|y58srm4 z(KY5Pmvbl(FtDsd&3EF{pLWhH;s?uhTa_8nM98aUxF=?4rPZt|7E|9}sITMw{}42P z5j+3MJz!@0*Q$Jxs`cNd9R7P-SO0P1&`Cw83rd*R$-l#yY@Lw49q>YK7SXUQj!ZT_ z!>z~1l}n-Ci1chCwD<7t^>%M-fb*zjDd9mCH-p#(v3<|VncGlbPc)AeDsa@LORss{ z#8-2u!F1;2r}CT2cjyynC-`DD{9+pQ&zg9yH|uF>%4!+0snsL|dNigVH)ph$of53M zcgiy78ufVo6>8L}OB5G>2z%a@d)%5bJj^kDhIZ(5;j}!?T;lM<_3|dm@ zxruKCOeR{8AxnZ-49%Osf^qlNU|;I>+ge#`R@M~SBn0*aF~eR~DlH&uEvU#BsCP@l zgCgAx?M_uPT7|6NqLXluyv}S)`yp7Ii*q1s%0!B7HBa|X5-M?fVA|f!!$|FsU~kP% zwGVPjY+9@59lnm@jt`^O#+}W|cHj${f}oR#YH-)YPD%>U+QC-dT9qvCwiwjc^cg3Y zlEZD6#CNhO3J=Ml9)%HU^8r4(E__g>O);F}0nJLhASRQCR%zgkIk&f(4)og#p48fs z!xP4)>J1Gq?GE&*M@@k*)>|OJBmlbn4?u_|-F4gytG^ql5n)joc!_>;C*qZ0UAKm| zk8EY%*VD$1DD)CSf}biY8oTPNtg&JvtE?|-Dh`mLgb(Hl_pq}0ySd&CdaA+;odaci ziuMZfMHv7MZ;$X}g?Cf6BvHusEJF6h8iZj`OTtF+HU35z+P3c7V#4(dSEF-b!k;F-tqr$LlcTTGq4 zDDP1Jwry(%hqY-myG%2OZtJm^=F`V?S z0g5wEmtBuyDIYFaSjVf?@F>9{f^b)sLvoX4kj)xOi$5ZTHEuWTYVKdJo^XVN7wvgO zY*VyK0*?mD6>i4)zjH)BJ18-!U|ZjfLy0j&J#N}l1zXKG8Eqnv5p0hsZapWvsthrO zUD&>owaR|K$2A>SkwKN2vj4=eVnl`4%O>jc$c2oBF-*1)k1TmhE=>2bI+KG7(}O^z zJZg$<&W4kqXnKk3^x`kQo9yQ7LBtj111PGydi=OZLTN1wn2BL#Pj4LZZzZ(k%{>D` z@TdEprUdGLN%RTVi|6Oa=oOI>JpC4UVChv$>5yn<@~_B|Qv?isk0~?P6FviIw2X!c znEv2^6NqF5(M=J+OYR?`>@)zEAhJt!AujD}VX|z8XpQw#Bt z>g-NnyMEB?9(@JUw@ZvEShiF$k-e`LC|+oRa90h-W&v>ei)mIOknIgV$L*e-rGH3_ z9aXi;FjT;v2odg^L1Rd*t^Jk^=(0+qe#w$dIqwOC0|aAPNt+)Y6S_fV6y~b(bPKx7 z-?I$@yDm;{BMMCw`lZpgFGLUwm(*jf8s&VB-i^qESH^+)&0-%IHQSgl5bZED?kPGV z(y&RmiMnZk?XI>IxwO{EBvbBBV`{~u|JWzyOXCYWvACUF5f1BNy711f%qE;3JHF$qtlSQp0_!tZR1DBK_VsBJ&~asQkCTyz)DsiAP&Y3%LmUOe zD4Ya9qAfngMl=?Zcu3WReQ8jK9PhBOi0WMLq#$5~<^4dWVP_e7t3I@{ zMQ9ZYn&i@nePLlZ`0T8v7YuX`orVR>@9Xvu$zKypKZ9I9eD`im)Ts9*ja4;j+`QlM~QPHVPd31_-Ov2pKH<4Gr=WVB#^xYNZ;5w-_{BzI{Y=U2nkk66daS*i% zndw7dg((C5G??`06C2|x^Dw;&h6Y7E4fJkXf?H=rr4Kc{2B5@Upl$rkcV;^oW^S_4 z|D2CN(2FlbH0BD`{DvReMu+q2+>3gSAg*W9$ykBLQmnGxQdhEkfVCiQ#Cz52k1-Fn zEW~>HigO6c!4XFn43@fNV_BEByBc$NI`mEQ1dRQM;=}$A8zBZdmVd2v7pYmt95f?* z`}7!eh{LyWljoC-E$2n%^E>iI0DjGawD)fN?EZcBG+PH-zWwQ!u#e}lbiI)!ZRm5t z>7Jd*sQWR-JnweT+uqkP2~<6kgzdE}D@Blf=4Rm-N0^g?V^5d+qf_mD0^Os}c9j=S zv5sqP)zIELBbONWN>ec-m6wh%)(zvtg9%Dimu$svkga~Fe4RzIYb(q9YBLK~2{16L zG7A-+)%EpzYVbsk8LN--^j3_kqvuujAMlA~+)|1fZSt8Bf1y{WpBF3?5KHd^N))5; zOM2V!?tZp>rekg4zmLbVv`nWxGfqT$tTZO|g{cGZs@HM)VW~U8asX^Kv(?#bJZj5p ze$O#~PSMwc8d_0DbtrfpNjqP1%G=(Kl0V)i)iy2bGzcc)ZBsIjnIVEgB4XBm16fKb zW`pF(gueM@zM6wZ8rXqY#I?SYUb9DbA;z!X*EZn^B&kUdU@a@IV1YAjLKi>OyW-p! z;QCDm0B44$b253i8Gkf=1+kmBhKHJ3q05jNXPI(XSrWGkbOR%639YFavb?rj;D19d z>MOUjl056F+Fx+!*ilK_?A*7JWr1=?p0L|V8+QoG->CXX?K0y;#}hPeDkX!60)d}P zO3_=SA0WiC2n9gWf&he{G;ajhhd7KXN4t8j z09BTtOR#^Vu}`TL!Sku#n`yRoo@q9uq~!}9q&;ufuwW8M&M#w%^7pgt$G8^**%pTj zuxHW0daPjC1DaAsLXm1jsgY|lw)(*Yq{&j!m?y$m2~t{Vj_qr2C`l?4R_1lWNsPQy zNMGJz9&P1wJz|Dopr7*s828z;4cTM<7H0u?bWiHdGdMbU!JM8WSrwWK^H59%hH>IG zK+sN!#li=t@TmOR55h(h@VP(~3kAX|Q-M*cAo;Hk3o_+ae(F>Of!n6oX~IlJJeSqN zMvvss+ zbvkvX2)22#TILSJG{I&!lJWHY9*j9$bmx&NNuaM#{e&0F(HsOZp2=p$BFvvk4^L9+5eyb}}a!AF-zo2VF&3G8+joI=F zsjzMEqYZC%g7{GJCKH9^>n%OjAwBenv<}JK5Vrdc$CmYcY==ZGC5g<)uAZ~BIQJtP zrD@>6#;h2wKKe|!b)-fKA5SeMJ&;b_4i^l55t^Av-QeKW$^<;_N34*COyqcf&kw^( zemtTV%w zJoE^aO0l4jVN!JB(hN&ZmG+-L?H3`u)?oVm9{q3|HToHR6&H<#gJ0Y{vSsesl&LYXBqHPee6E;H)_~3e0y#Ki3K8) zF)Wwhyk%OP>{b>#vPN)*uWRJH+aAf*O04!IKHI-XH4hsGzOgKoOT&(vX)%@lFFJ`1 zM)-Ctq1OSA#f-bAlPD3CmZu0p>1K+wB`^W1t)V}N2xVf!42!kBtodl^f$lg~RDtFogGWxI;zXctK&P$O zscY|(ophUC-q5nY?*G!}>;`?_EdOor^YLP+M=U%(0^u{J740JL6M#qd(_*ryq!}G#~6%89qii=(Q^1#BYi`z*4 zZb$yNjfpb9-!|)kZ@6Lrd&Yr)CwA2-cYn!qv}|?2D}rPzKS5%71nj4D|o7X{BeT``33QQU4d|cWV==1iJjE zG?WY^{Ue_b*g7k!tOp1S}AlofekYhw?uqUSp2@XUAG>6~BxpnXymWbEyHNugpJUCIc24R8{p1Yd4x{m`-xC>gkq z&9X?$5%~c}`v9HK3VwkecV}!=i{`XJ%-B2&OlEt!&G5vi*VSTiD?@Ehz|E{1u4aP* z&xcWh0}fPu1PdgL3Ms-`kkBu+AZ%uz449uNc1gBls(-UDsEO{Eq7Nx$6}^uE)hVz_ zVj;1q{N#vuc_d)wAB4s#M|p;I{#9$Jz~Qu@QlNbJk>>Zz+K63B;S< z4H7FNS0RsyQ`Qxi7!cWPf=+3lvwYFkfQ9cOj7dvTt!Lac94Xl|h|^<7{G%h%C+1!m zE*B>?4<2?oqQ)7;sx?-FitIRIKVI=7d3Xtr_#y0VPF@r7A)+IpqQ`|#1isb64azC; zdZh_vPPEg~T|)f}wzx2~x;_tmuT#Eg($vrS^GK+MDR*pK?k|E4x^#qN==kwb!!(C$J66EMdE(?;h^D{FFnsNUw?b>l*|#e^B1_#l<+=wR_Xh9N1o8q;h#dJEg79wcmBi+Tk>gt}OU zH?!A%#d@WQLz6nd>$JMY8izB&VT32+ily`Lbhj0S2OyfR;E$VHvRC;mAZZAgw*^O} z4cg!*NR6nD|XTOJ}!6~RCXV&u;SfX?O8VH+_@MW3)2F%hpmbYS^0j}uZgl}k%% zSgz00q`!j@X%uv|FEt81-L6?Irj`JC7b?pTs$2hEDKiUPO_p6yq%0lGc8YTQg+g2& zlJf_f6Sazu4MtL4j3^MYZOs-F)t>l+EZLYVpfRm8=0fuvyajNk;=#IYiUmHvK;Zu6 z`2?Xh(AZO-`=FJss%`dzir6LIY`LBV{e2G_0>ezwGAbKUIDAvjVa-OEh*7bHYPM+Gc$WIx=;mG!7s_X`Cy4Y*^0IF9i8h7G6C#Jlbqf$+g=!bYi(92; zDMI80(Dp%ZECBzk6AfvPx)rT{HgcrzQ^19H-NQ!4Rx-UYcnkoFbhKnevDU9tn4X4v zi~oAYBH1_`8uMz)=)$OVavdHG$~Va-_zdPx-op>_ZVy_UZ=M|>|Dl*8OW!fVe}&eEN@fO^{s;p?YYZ&aX6)_5N*qK zo0cj{opz(omN!&b=__af0keQEVH(79^4kJkLXXVG4~N&Xzc z!f66($KpJ0wX_CVbT{1Kmobj%T=dHA`5cnSC2}ug;-C<6{@HBaEv$iI)`gd#B%?wP znUKh`=C8ZXhePqfiTO> z{4dVpi7NUzVDqmGN(EcJu2Aas&}@%eKYN+xDEXZQHhe#nVtjrRrJ{%kcUP zedkfqrVW!v5ZP#&qms`wMuhH@1BevI-Hnv2vNkZH*$D)QpFVXIJA{x;f9e{PG6Z2D z^%}uMm%H)@ER|OKxLPbI%k6CSRzF1ZQfdfnC^{dzl+O!M^4v9ns8k8I8J(EaEEQKK zQN(iQFrP+~&hBH7yeful0@+}Tl1q?wn=2BmGelVe9H@?TGrdV2-G39Cv!!|t%xA=W zjV0Pf<-1uu+)kX*U&1F-alpZADl;bm*}*U3@0QrgGts08VnZ)6ND1H4PpkJQLEaPx z`(Kx_$Bg&Lil~wcBW;*&n^PDSP_-YR*8Ky7} z2dCUv%nbIhesN(GrIT}H9vLLwS@z#GU5pbos_o93S33u%y7Max%qT{EjrYZwBX|+% zd|G&YFTo>K6)Ic5^PbeT&=RReWPh%fv9CTUoQfK~8)t>5s9|G|GSS2apSm7fbS*2R zeAX?%SL#g6oCdT_lPDThjxSFnpk*3dRZU~elv$5XE6;aLPrjoi0)P_#`d~k|LG8T) zoQP-}l?!0AnTlG0oope|Ps6c{8sAT~g-1{4po_tV?dMOrBWUg;d3Pg*Id z=2a>1`o)l`D^I+uGiY5?gN^3eR z-4+?ht?c98l8kmz^>U_=yQQgoao(I{Dm5fwzdV0H$^@`UVzkI?*?{JIqsZ11KG0uT zP3=`yiDOgjOI~IKQhF0)NY{Fg)C;w3B~FQa_wEbdsEkQspTYNAZBmVDa3pMZutAV? z)6qsmaWzE9__U`e*1nY5EWnTsAcd5U5%U0`-GF<>SYj=EEis0$(a6k>eMUF=h|AT< z`Q(!rtda^p-6|%y_Xc)7rB|-RKI~I}^NNi@{X0vM&v17J&f7HYA)1HY$8_K@8!-vp zC)5rV{H{{1@u#GcBb3%T_{#LTZ>93bJYa5$`)%i}o%~VX9HMHFec3Zed?<70ne7MQ zYxYR&AE1NjpDro%>>U5rw*0q2`oEIRW#w9}B9jpbPnIjGpql!T1);&v#G}u>;!QNd zDIoEV`@Vk$QmNM)tmqoRg;01tkDsROA5T8d57h9uASM5@$zy2n&R>!VgOGs`9zMI1 zOefzuJ??yvUAtR+w!6nL#Z>cgNeiM~bdGTF)IK-9Q-8caBTBv5XGC<7xN3kj$q}Uv zh$Z6iM5aNEl0Y`KDBTpb^U5M*wRG>qg{&c>t>2Xfq)7E}nv8u(X!*hxyH2Hus>xuK z?%zIDuWKT2AI?~2D|D2kYd%Qw;FWncbZNJMTJTn?)$x(RgLe1CLmA-(JD6KtDMRYn zE!H+tO&J~fR1=e&9G-_WljuLi%FuUV zNcdX-0XVL|qwaZeDFd_f8wA)W<|qIY1{TW%M%f396W|rmZ}FF0Ay?@@vt3`?NkY_W zOOoP52KV}-HEkd4Xxrk(hc3s_y-+XxMsG!u&>}Fvg>@TW%w0~$wwx1J=zxdT; zs={#`qJPnG#5pF+lX0GJ(lxTdxC9iUGYcD~>42o8~)8n_x#CfPhOXZT+j3%CH7&8hU|FQu0@;B~8JHgj(XZWZz6p z4c7Smr1D0=xnjIYHiWTx7;PRNI3jT*ew*5Zq>{7DTgABZ%$ro94P~LR2rKR_r&&Qc zz0nvk9i|O?Q{TZg)?k22NjNW7tCkT@sA;~&Fsuy4MHm#TeCGlybG77fChHPm>v6=q z=?-qW?2N2hg@u#R&d*GvR(E6e*4YyBR4Uc9>AMBX0W$NBj-uaI+!lt>>3;MfZ#}G1 z|4CpeC`w{hatxe=ZGhp=V;suJEUjQBYgUcb2CGCL8e_y^UZK$G8T*}$jM;(p9X|)= zjh@N6vUH_;yfy33$4Tmz4I6nSMN3fz2=&!DAf-?%sX1AOyNYP!j!4sr z-~IeA&TIo>@CmI|Hcy!xC z9E@rOCi&Kl{r5U_mu*zY3<#~Rb|n=TfhR9E03OHYU+fp zr{PL26!y@+s*cU)Z*?n@{|yC}_pcj_ER2Z{V0_FnWiZ?+V|2>aCFJ>7ArIA+iT z)bx(ket?=~FcSU=k^VtmXJBAu{kMoz{oiD!O``4s0BvP)fih#DMaB<}$3>?pk{MjH zfY5+M0hMCo?d3>`)nv>eLYF!mXWHxGo&DRv`{`^hun}W0AA5Rv4W{E)*p|jAc(2aX z^4X<@&jT6d0vDNmAjd$`7Ei5jHjNov5I!6biK4OP&y7hPwZm7x<6R2sB`X2@L_|?9 zOQ9DmWjj3HVq;$3_4qu*O&bBeHG~Akl#RD%&^IDKn`<9s31r9bk6s&0^vT2^`kW@`7n`RyH6ZG;1wOF&qfM^uKfju5x zbP8)(@hba{s+~%&f+}biZ@Q+y(y9PP$9ECo6SrxI8K~SDCUoJtLs7*ja1Az$zLS^S z?Z*Sl2el8i@^l()WdQsv{tBnuXwO)m>`F^hgGlvq`)ma|_zc=S42&Rxka?zr_>`vN zHlyM`8Zif=e@JTy3;5N3FF6p^OmpR_Ns*O%k;siu<+Kl>i{LuS5+vAqa;}K?#1u~J zdvroiUDF9ycVe34h4g+xLm>>jX9b3{@`B;`0G}$*0Gv6)#X6Q%$a+D;K;ZQvMknl0 z$wH&Rn^~7`H0OG4l%wJQ4(Hbf>n{M;Q0kO#t7ldZ%ewvNhb;1K*)5KBJN`}(SF|%XzzC| zFHOq2Lg>@)f(`j~{|V$DZ6G*Gttlw=L?@f;SONM9c=pA7a28{AAD{pIE;r%Xokc*? z1osGpP`h8=)gAo_@Zwlz#JU5h;z-F%1i%kTC2k`m6cxTOLAg*?^SkdNkz?0d=;h>+ zOAW-d|JmRTmdKGfBW)}I0wl-RmH0srLGT6%Pk8R3r~E9P0KqZE@nA_K(gCK69OpQi zxqtXc>@4Q8IhGT_l(R@@Auc5yx|qy_1sU!wwSGWbxRz{}GeH^rlGOnmUP~dP*-6zT zk#+ZoRWzY4xA#V)RG{2FVHP% z^;|vX$L;W%lNLSjUG9)>Q-tpE#0$r{@U8M4-%}yRKzH=xd|GE}NQ5HC&=b9r%Rw+E zV_)jI+#Rts8ok{qV(?ov2d7M_5$7n;YFFf8#-c(c4@!xoFU(~ySM3v$L()cTQr8Vm zZ7OtIGhklT%_BbSMjKw{Q_f-#94gi=;(7IHXnASi{ag<%jpQGkl#I;(M7Wsg|24cd zt4aLbj6(U(X4EtzBfY8gSVMK*0uU?~zR0?+_9Hze2v&H*swIQC%ld^@J-^wv8aIeegZ&+-cix^}3mRZSNg_3gpQ=ux8Hs0 zVT5k%QphbRUWSpVq9zNMqHHmo%1L;Rs~VcbrowDhCv(70qi!HmAke5<+BSYTwWd;% z63CrfwWtH}ZzX@XC!xN3UzzN-gh`d~kZE3TiFI6qN?Q4|;WZzofC?_xgBZ8M`p?l5 zvuJy#-$hJ#32vFnEGz7$aab0nHf^P4QnP6_6nx+EatG?a=f9Ys*62D)RFsfEJ`f#* zYD>5mrR-g4ec-9dbw8xCDK|P>W2)8OO(OZIultH+g<0%`Hc+6jolo1rs-S^gRX2uf z(FMY;HK}dl6SWlyYfIGR!HL;E!INq)G$;ztL=DEd3J_8p9K`L&)1IT(TaMS72?hdV z*$UmD4m0{Tz^hbW4kYhI`#+qM?FRFE;+<1kIiKXisClFkPWX%w^%2X3_JqAFuoh3t zPuSbY$s$A^=B@;&QE;_SMmHB6I7C<)br~d@d<3`s#Ri{| z>ioixjrh?}B3X~(<#qW&-FO~M>)u@202s4ifPpSFh}P$tatDmv48?_OgaKk<7a$XpUId`-_no`5p!~2&-KW^Hha0ZF ziX`O=8kqt&g-e<;G+HPiECpucbG`CV-f#5|7*2jwVxbD1CRAuosBp2)q%eLnrl@vX z8oL;rTS613!w0K_e&!EE9sY3?I+4lkqSK#4UsB zQs@qvHUq#L&IsgU=>}V}I4F&|2_;xx>{U1FYQ5cq4N(D055eUumq^Y{|1sUm-a$I& z$s;{5S5_XZVT;9ByRvO3Q$TZsmcN`XQZrkwy*e_8*;=cuDVshZqbSu_26%Moupif6 zydhur1N4~Uk_u*+;VWo?@+{JW{w~UeBz)26T`P5lZ0o2iP_oN3)WZU&GpUrO?-ZJ^ zjk_GDn$&3q_xH;Qiw93ZyP5>~y<3vsj@RN(uWpJ(k&gI*?u3ORrODr4&wC+=PQr_-MBVs`WM`{ZP1MU-aiH7EvZ0TvZ0 zav&P@8Vt6AAV@py$hnp1R^*xc@P!CTkuzrB1mT?m`-=J^C9)8w#K|Y4lSBR21yl%+ zCrz4VP$jOIbwz*#hq%ztFS>jg*s}%Kg%+kck~e^2C2yTWzIl)Xb2|Iy>;4) zFV`dC^3FXeYj5aTUO(H*Jr*O=#%j@DEP}1r4NrRqNKm$|8yX)zWte)O4Ze4DWzLx< z|G-vR{z-acV*J4ll>0#6`2#sh>9VjItM*|i^4Tl%rGj&%%@?Nn z;pK8sr&;&3^__aN6KCIhK0+J*nOvF__-&dOS0Kg zYeih1g!6|Z*}0H|miQpL%}>YBm)z*+cV0f9s13|Hyw(?Lf~14Xk~2r;R=`3C!Rs$T z*mwTf(hMGLw-?_A=^jC>OCHFLX$d7b1+`K~M3-(7{0R?<;8W}YH-B*SjGCbD`3$BE zUsmYAP$(-!3!Vel>bb$nP|Ta(y-dRF;qev7^1{jUukb_cN#H&1+oDx74BSszxEF<;b-c%O9%hIh}d<>)Jj`vaK!eKdX zVkqZ^d&$p}w|{&Ih;sdQ=bD)A8 zO*2imcp9`{OfQKP5~6f&6`8K3oC^JjZ`#<^qD%5XnCF^9;@x78LtFp~HOeXK+6rD& zB`#n+68yV8o&L6Pvdc#bcaDyAcq%|)b>R!hF*0fTR5rwtWe*WCCoqCM~O&*;38q z>i$}99Gr~w_Y#60M9RGQAaF>ee|_)aGkS7E?mIziq(^3aqHZwDG{CLM4i?0jDRb9Q z+i&OPNIqy+nQBJj$}MSt8Lo>=5>;m2h2Atq*ObtBIa9aAevh}|o75l9$1Wi|wzM@L z496Z!JpZ|kKH$W>ExwN7xA!jCZjQJx8@;6uV|dAb*j<28dkq+0FkX(GAZazYD2ET8E#o zz96=ryc&_Ty>uz@kA%Zw-S(_n59FPwYJ6T$Jc&;OU3wemqgVi=3m0eeuZ+%<1Pa711Rp%p_ z_HUNf=iD!#dQ?k^+i`su#hX?TSDDQWG#DM) zl+WJ4m!Fjs#EPi|9W{-X#iIyH>J&AKQ7K##cU6&pvaL8Cm~p zP5J*{ypXIemAL=EN2c`G%3+oLm*K7TsSe|mODvU|If~k3j`5>l##a-J#$X<93S03; z2aXwAv|_(IK0Y)JeYSjG@7vO?`&gsr$9QwCSM;-ONi7<{6tbkBN5&SSa_77-NA6(a ztMa6KYEA2SSx5*U%$W{6la4(>bdDuB1A|-oD>CSYh(WAMXtK^dz-?AUy$G8`#pv~F zR4dn7b7`HpS~3tVxw|NcR+h6^56!(!!3#wO7)bQLyM7KPjM~lzQKeH9AX@e`L!FnE zgoCbbvI1$7UoMo*hLf3t3pZjr2BV#ZvxCnA$hT!9U4EE!`$aZ9Yb zq^{Hn4{tDrC#=m#eNAHjt!es(OTaI6SwpeU7Xtw3$MEbGaRBIF<(T0)O;M-=RWPql zbHt-C^L_y})$X`vPlUXpB@BQMRB_BDi|@OnUNOC&d4%A|!a7v~0#r8OfVP5zad>%) zxILRpe@*!{Ko97@YdUj-g17ZpWsV`%{DD?RAf^PVaZ?8aTqij|aF4_QDZ9Vqv~#10?Kjv(E>gbNvix`pKi;Net9BY% z5UQh~nuOnv-opqXZO|ZV3X`gGSE9BU#>O&tlLoxQXl)p0L5{%Tpu(u4q+-v~wgGDB zX7JbMR7Hcw09-^70Y`&}qTF7lQwHcx_STyhK!BI4gg`pi=`1Te17(LqNbng92TL2W zR?5O_0AyooV6bf*>S(c2@d&t8*nwl8Bc(((pNRqMcE6my&^8v0b+;6TQ~QMqY?BU) z^YvTPs`yYvQ!Qftg%s?J6j%I8RByzs2rU$UTbM{uY0s@mv@F5|z0C`fDJ*b_UB-kn zCy1AZMXQ5BmMS@}Tg=2}yPiTP9Mh>IxLeaJ%k=_%X#W#pDn4x7Ql7W{A+bWZEpFHO zV>W<+x@gey9yH&QU(_jYefz_5vNq0sj*mMi4kJexD(8d$+lE{WDTEsGNb&VBe~65dofw~C?fp}Uvr}d7$Lt8809^OZx=$};86a|15g~Pr4#1<{Cyy6~wa*GX_q&!cK z@9PGJBd>}b+O$0(f1FlZVw>|Bv=`ZyYX=f4+FTv5_HFfin1KL_CqDaYS*Dr%q$2$F zs+~W^Ly%z$MY-<&c=7)B5T2m@xR9eea8W*3v#Au?)vuJI5B`SK^W5<(W^ir4=QD2uE9) z+M(Bh8Ea@ZwNwVNVm;$Y9)D^WjkUayGmopdECRN3wjC=ob7+^ou5N;FiOAozJ65ng zX**ggc7$6E#9u=1CNUfQE~6S!Z(>d7eq8J7FgvD>#Hn-SpLO61zijNa>~x-g#1KgL z-Ruy`xwcIUzr?IKZU$~X;C}#po=w>Q2}J)vm0)CI`PZK2W(_^NgEmCpnNs=|=q#A3 z_D{O=7JtFJZ#nI4BqelYu$?Dh|_Y#f?7o|5a5@QL{T#&Av@KPCA(=cW}OgOSW z8oFMel&jPP;m4jWU6~9N;qlfbD$;H8jYpoYxF#ZrQ+6r7AFs({fHW&X6ugBor_%~i zZ8RwK=`mRe$uC&Ac_BTcW-lo5{~ zgx-H7Blo>G`jMb*erDX=GQND8Yw_ayS~Sf-%NtGAl4VTQuHz;sWMRwJSdm?Av<{|C zRP8e1ZLf41CsaK&nQ!72es|K~GAzaz_?)of2NF`0Mf$*mtRD)8@rj5M{3w0Ajg(BvOT{c5l-n18;0 zf3LeaCMBKEn2MAMnfPlV~hIZxOd^+;@DN@%85Lpq((=e+WtXuu(m!+}4o| zME=&amqeN#j=JHp(2fgYXl?u3M;W*kkf!e1qpLF0Ic11Ki);{rWU4Hd3tmqEsWPUH z+w{)0KXVUP#miaWD%i{GvV47UkHAG1J0mp0XOwXP1hT0Vu;fzT8C$`NnMzlUaxbB^CBSgsjlArC%zTDkZyDdaj8?q7?B2TnQ z8WC=KwyIi6tHBYD*utvG&abj%D6(y7Ij2~(tP_#Fs>IZb%l1a2V@p5?9-*cT6eJ5| zLFlabaVGunF+eH|HOOf7uvpTJ^q5=Zvg(6VGn^*uecRVVG~i#zlOal_QjjGD&&qoc zru1AV*bqn8T%G_P9`NRvViPi^pz`Qi*~DC9+V2AtMSPiGaR`lg9it|EX)3H>%k~_S zrf?hGd>fp9wl?saJGpSzWwzbv6ebx>72Db&kPVRx+DHqzPld<@I8vhZ`IpT$<0O)p z!S#NT@sxyxVCoAB-eZF;7m1pIl~AWkPBcI^YAk{!o|(XG|bmqm5A z@5>e!bbv#QoeJB66AvqPIhVg~(#{Z%(Kb&AZ1eV%u^jpx#%)l*3M#xXJd$4Vh0bFw zq7`-?ra=NkAa$MA%g$$SeOoRh4h;>Z9u3`~r*)i0P30l@5%=PMvxf^TEIsePhfFWu zB1)nYA~F4LDAJ0I!x*SZ)6w}n*hlw*ixz(ABHv~-C4aMLixB{4jX9W8`Ji#O?h+(8 zabg<28Fja}TqX-X@uQdbJ%6_YEG2z~!hZWs(i`eUWj=%!iaJ;6fMHL9EGYBoD~uS_ zHq2+bKRPke>(3Skk^h3wd+ypkmO{Qi0?9?$|8>EsU!^|sO3p#I)6b<_AH*hpe^5mT3Csf~YzLbeD!+9m;!W4{DN*!7&u&U9eZpjE}YJ31S60!|I0#is#8m8~Eyme&jcQ z9`dFL0Rt27#TF%h1gJvZVJ>(GFA#t7_|q%@$qJK>5HehA)CRSNAROw<4hA1MkrkWm zKq*7f#zrvG)1O3FS{}2q5rz53d@_yv73RL2l`b3H*a-JF;{m{Ms{O#Zss|h!exx2u z6v*5j4zT7!U1_Agb2l8HbPk~>%KRKv-PTK`L*k;jQly?~clnYDQB-SvJ>9!id1LF> zHhuN)@|@Hv8&C=l%F~K3Sp#TGq z{!-M3vU^eopg+Z`rOjNTp_zZmqPcE$2*xR*W86p?K_urH?p_h`i4RLTQOWFoMxmZzMo z|LFyWH=@@2yMHFCfX7eYp$i|3Fs|8ZIDkF8_>7~!uU8_IxPyj!_lutB+eSk(_2FKLD8WT1c;m1CAN8bsmD^ z(pZ53|K1kz7T6|{;ZYW?bL6umI>o3I_``ixQ^Ra#t#_vdmw?&a2%g1Utm@e%`w169 z6cAOUr9a4)OM|ncV$;(H-7AivU)gI|0xXC5F7Hp!P&w}j1|WlH%ME(qy;pxcS4`;N z#PEZqUe#8qOhk3|NDP3gHVy!ZlC44NvCBa!djPoZo%AcDzwb1@q;Efo(T619>OS<( zt+iLN#3Dx`b&$U?^BGZgT~r!9+Sb%nN48D-P>tk`NA3Xv@|wj&v( z;+b#*EiW*+*r|<78(^g+R7?6TJM9iC$ud3D=Z`I~z?}=fruY7A@|Ob@$9oCoo_E$# zGjumh0%R^azodjOYiQU!FxuGo;-cl;yB=2-YP{saGF z`-h`9BNNlVmJzQs|JIC;BKBOU~9UVI#gl3P~bUkt*aB@r20*DWiE z#3Z6jDH>V7mPJO|164JK)Sq;A!s-JS&8#kh!6g*1iL_{+S|49xN}LdB&U{AA`3~vG zOh7;=(;6v{b+29l{-mLg4EYOFo3r`Am~J@y`193t0OdG(%Hxx^j!xe%!r&gBzfbu+ zD9wgAiKO?>lu6|ui5Ul=+PN~8?s^>s(v7^KNC0m4RBUdjir&0u4Z-)>HfN?G{vm*+G81-Y7@cm`z53P?!iZjL`crl?2 zfvh{D>LaoVBLXdqAwEN*`y0+IAqk8rCShBjMBlD4K2G2e@>`+Ir_Ly%(joVY(742S zg3@OmF#{*ZE(Ba(SsHsM8M`tvcOhSfvO24kq7w6^dp)bA$FEFee z`yQDA7^z|^?Tdk^ykwD=!z1YkJrRloj4z@otN#?rTxZ%Fj&|tVe1&f0ADd*=pW68d z=qr@NkMXP_xdhJZl-{L*5gBPxA7*)A(7~2gN_a~m7HXCZm*@9CS|G3z0{kXOZ4rSY z2yxQzph$@bmb)~`7zO1XD)(FUP{16biMm+XdO+og@yuT_^Y5l#p1*WkTRC$95I{rm z9qKrhV4250aRB`7Wl{O0#?-{%MOzNB)$VslXSW6KO>0Xtxc%kP&M5Rl(w7~;d$RE|u2?X$OWIYyW+XbO_x213Sh_zDF|(r;fETvK4(O{ z*cs5~OKNN{Vw}D7s+3X{)P_ zl~isyN8FF0Pnu$>Zh9#L^g&x?$Zc|`w8RtiCwq4AGH+0Nc674t?E_yMc?izSOW}EA z?3Q~pVOS%Y(L^Ru1KfMS^d-)vyDk!R`)HT8&MsBui|H%uA+Gz4Gq5R5bd$7y@QebMa4|x1?q`p8ig=Jq0 z!eVN-V@vV+Aic2#&yeFg`TF8UyC%#UT*AU3O14iXOL_I$TPQV-!ef_xw-Udlr$B7m+-}?P) zW(0{im*cbw$OezFWRi5XSs?oJf%WH%iU2TjYEXRG@OpI?CdD zM+Mg<#rA>AX_@!PYyAYP9*c>2p1NsvF(k*~Qi{yxxN7S z$6Kyjp4a1X%>$;4>boY>)aC|;pLiy88NG6zbHYVCkM#p`lfeLJp%5rt#ft#qtkg~3NW^LksVI|2VA-bxSj?< zptn0xj(I6@sPvNDz%U~SX9GcT*romKcAAWFL*8h653JM2M}ZYJNe0ynSDPlf&qoZ& zKD%LvTJzY)B$anBV{biHV?o9B39R!0RW>xC=%He8(5g~8z!)^uty~T65E2p0tU-C4 z-UU&5q>_{F?)q27Qbpef`Lglhp$&A-&7<9fws5@Bwqe zkHg92IJ(vKW!WU)VELQ|5YV~~=oyHspq3_3mbCC$?DgLRh^l}t)oyqx&ZqXMa5dXZ z(RL=uf1F787;+H(QR0L)VpGWBgbl&#aC*sFUApx5;I|wSy>t9HmAB{)w0Cyk3<{TH}6i>%YTWqe3Yi*8aAoM4JI$Mm9 zK2yp4g|Wdl9R$jL@!4p#1DS;4U|qug!V3CT?`wW3ZsJ)^efZb(0=h!Zrm;=aV-WaU zDIoGfsCAFzH=70wosN%W3~zRdv0L7H2e@VKde+i_4#Enf>;ipBLB}w%P9W8L^>mg$ zUTuR{mu^ZEX~r6^TRz- zgLsMevkz8nQSM&LcvagpPF`LHjg8&d1=jr$8M#5%#uR$rJ-Y^xRCzdppEV% z@ByGBQ%QQAF0P5%%#uryI*m8%ZQ6+=9k~o>SEaajSE+;-Mt)bL;BKDbBqfQoMeuY+ zlC16=3T%O*Ri07l;7zI2zMqq$nMdJsZdCip+_i~UCqCZcd${tP9zumdc|S7nbN$Z^ z-JIu}>L2I<1B>i`;9MO4v(Z`F#MaE&9G`)a;a_WB)oL35NlpBx*|CMLVWmLi+;;!3 z@fm%U7e(X%2y{L#j)YUyS_(|WB-?jqFQ2Jt#p1)*lRfKq59U`_hlZEK9kHkbf54a} zQ(sOfA-o(ApYY%lS*7*8{!wQ674pve#9j6!atK}(1g6huIH|9(TI>gGMow@#kBv%bX>54ZlhpEDGzsL06RJ9D<$lp2*Yp$3Dw0@4(oLmBVp1J z=!&exiKgJ3`^Ilp?4WYrx!5(onA{UaB7v~|RctJt{Y^|z1Z0(xgSX2m*)yErwg(lm zSp@A|{FS@iVy}7z;iVX(!;n49IYOt_=zE{Xp=ULls>3$GVa#n=ETx?rF5)*~g9OM=tAj=jkBIXN2bf zsr-I8!Zc=_NR6R~FQ3!?4w}({`eWsf>gcBYXdX9|^LP&(9k zOrbDxu4pD)+Dl@Q;w{#0?4XyL(|k;Ze2tClwI}u^R-qNqqF9{{*!qh?_6S(pE9p}( zuR!p=m)Ue}(G$|%s|)CSTf^I5O+AEA-A&Qlww$xGc-@2W+OKX*CNFwbt6zGm+?hZN z>JA>SaX0XI2TA9!9QQc{=rE7M-UxyOuKrYlJ~)&$dJ`1kRdz}nPefKqj1CZ}su2SO zW6&#jZe+xFj59`PYcK~T$-FSgZlF*TFN+g zDsv+mIfJ>yE%ix6OoME}->%hvw4P{T2JkII{S>jw*da{ll<<`6xZ{yE<%NYsz(BNU zE8>OYnFY5Mb1DYFF0Zp@?WEW(U_AgI1Qn2V$|y;!i1x#k^trq}&U1NunqT3nffbhkD8hW}K>)RP|C=R{HC!+9157 z7ndSu1(j&6l%YZc<|Pv)sT6z{?#a{inkSa8wGTtDv}a_FpcB?x;0Nng!wVJ++?`=lk@+;OR zc-DQ|5}rmSb#;e)UOsjn2hn|dOB5}XwukHgtYk+TUGON&c{E@K<4!f%4aXt9D3V|G zil|cyC|2%w{(PR;(L7F2LrPzj!D>%FJ+E$cAvJ>om?JQ1j(jK@5QnXR*yoASv1LZw zn-;h_FQE>$xwvV+VM!`Mz=Fk|)iajuAN|5%Z}bc}n_d1MV!@3AL?pwap}orC_074l zo$(0}Ipt zNRa(M+U+?QIR3lc{x4Mi>s0cUmd$_e1K-zreX&>Q8BD~X#C7bO*ex`(K%pC7_BIXt z-7zhYto1-69L6`ZKig);YYqkMs$G%?zySbgB(UXsleg*Uj3{I5LImjuFhka(zqJDm z=041YZ#g3fLb2zuDPIv82PG+^L?!bC2AHDB_lKc9#rt{#2$0VZB(q!~x+JHfzjsM5 z{`TCg8APGLjudnYr}M82njf+kz_cg=>6K&99yV9rZTqt)-i@6hv-VlMP^T#hyhOE& z#OiVs#y_es2w)7RNg#|70qKYb)drTvId@aqH8_!y0%pcYPri2C z<2FL&5i{Qo)L=LW6S*P~fKCD=CIP^$kwBm}7!VSHG8%iSN64ZpNygw}0Y)DquMrb+ z19pZ-Joh8tJcN~}p*%ry7Qyh)CyoswAc-aNfb>$6f~#f(iO#F79g4pP&G{u@7K|bF zg@8LiVPJ9}fyCE=JA}-$vnNK9%P475nJ6U$ zG6#qem4(cWzA_GcOG567O-*>*_C`0eB&f!BhskI;QW3 zEd}U=q_aL>WW+BC&xzPz5e@V{+03I�Rj#KoL67Y8U45%iT+EsH`f57kK-(lZ&F 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ν1*_SzjWVD^;Qgmy_tPMG;GY39c$a)M4#FqlmUJ@2P-Tyl@6 z1E==`LaCZQy8j@AEdQzVW@rDu5#s;%G;C_3ud_8k^}3Ne@bE@DV0 zj0U}#px|p@&Nf`LXMbcHu4~>ONyUCSI?2xhM0&_j#S-IRC}st!bA9}AOB!WOEYqje z7HPF3#M-k<#)LzZn6*u~IPvaN zZMDeqMHSWQy=d=#+>!>sTux1*5wa!!0c`L10iT`0oCP4JJHMj}LMuZDR7z#4jV@^m&?Br`B;-BV*LICcN93gI1IM z7V5o#vU_r~DZ)sz?e?1x^JsHA2);Q9LK@=3r&@NEZ0w60eOQz9l3Z+7i20oM4rx@RV5&(}1rhd&v<6;4TNmD;TU4O! zt4%RU!C&b47|-iu;dX2Eo=r2@^h z3{^WXi*mqZ)}nn+kBRgwAXU-UAG|-^h02hl#Ra8ci3~l_f6rvze`PES7}<}_^j_8n zB28-_2*Yq@=iHa&z)Lt&08;5DVBME!thRV<-bRn$5Y%g+Ro>-3V$Qdq>OSY>e^AkE zYUZW#IPC_3<_EU3bLr-pSh*yJNEL{ja1f|YNu)9ty zBFFx_00Ki>2?Ss6bRj2b$k%=g;(80;emd6TUR;aPAwUyc*bijve-yV8s$mX1VEC!D z(R^qwEVxgSucSr$n>_kUgBqF)Jr3PWfx**Hs?u8XAlR@zs>RNE0Ip-Ud^I}cU6#4% zl0SFi)`WiMhmK%})beY2MB$K<{Cjz%yu6c!Qx8R|dG^M26+z2-s%E)*4 z^xpY-4F7CXJhS6C@I`RsW?;iIC2+2>k9b*Kw$Qm8Y2+3uJbUt!7Nf7bRDsGx{eJ(= z&v0fvJ(?*9d)rc?&+^UAJ;9@|m+P8yv+2WIQ7eto66wv0E&OiPIhS3R+ImikpGSEV z8aUpG6fe`4;!E*tM^WXXYy}dKjf`1JBFV33iDof9z22U7S-QO!5w*$@JE`rw)p@Ky zL+C~|yyc11`E;>vUUQ|i0KDL#Z&!s(oT#Eb1f^&8n8>Mjix5;c^}J zmsOzq5wf6O?UQPiy6TrPKDEDO7H8{&TwgA{r@czg-6zr1AMPa8h(lNvzt05u-&&AzOy<^1MXiwu5s`i8GC$X?!G7_I8oo?_KS z;r9d_W~58@5tnwkalmOTnnFb4Q>(z(fn&UJ&Qf zKy%HECXP>~#?~7I>;f8ehpJr&cgtLxQDtSd8B6?WN8+s&--$cJijdWt*L*!Q)+tZn z$T6jlUJ#>L27$YLF^_7_82)Wk!GprB;f7pJ@$&kBLE0iz$y_}-wcm!_#nmB8{HD&~z}hXPL` zEjT&^$|Z*g^96UkJM_BCN}=^qJquE>=yVM%6(Ba_L?G<;49&sV1+~f=y|Z|AVnDDI z9LuYE1Z=hj7DpW>^}vzI=y=~bJs#-)mLvK3A4HAqKZqJLGxLA#H_y?~jz4ck@e}AV ziuVpGvR#h)+c8HURV*2h9R6eq-z0e_DAP1Wuqmi?zDXj$&yt-;yS^4&s$noRk?_HJ zKNb3Qb-KAMaNr)QUu@|0+|)zEEFg2=!8-QAD1DV%(UI4A{7&{*JnN)hx$B1;n%Khe z+<*R$>|4|?egZfXjg{7V4VYSaUk3m2nbi}_#wcZLI>BJOyqN0W6T9F0E-@i;RuYnS z;{^}zvV0d6XLg+0)ufh@#_hFZ|LE~OF(2>Vx2XoxBl+Sshc_$^cs9J!9K;&(V6@X$ zx<(N|aYv~Hk1`S`bfK}v$-BA`6|v$?+IgIVVLRkuBzcPF>=u2nL=v{#*~QJ(J>+JMIuwOQ^HO|6ScTWtjp~E&k z)GsCM&l_jE^Id->&qTGI!gil@C3K~XIV2vZ+i;pLI2=|ljw3QCHUdlxfc23E_B5^A zX$^v^+#gZ2>KBe>fMWiN^kV0TT~lWYXfKM~vYy>C==UVfke6m*4nL1A9xyzK@x}zc zjJ&_Em;YoKtVH_EwafLxjb%I^N(^~04v&*vW8)6sF8DLna?8^U#7+L$9MmMhnp2^` z79@=Ir^s0!N!KY^R(Qe%!&S;$&VtOha{|QS%Fb85Ze`wUG3QvH*>|X}kZ?W}d^g>6 zih8djLg0Q2;ki~l9v6Hwo`%gw^*{;30@pf>N^&&bDEVa*J^>s?UusKC{2a{M?ciR6 z_i22KN<5eV+L-3wRaCJelBfBq)`pu1QBm(9p)jkOzkusWxB%Xpd4sJrD>h!g4Q#fB z&C`9l1O#D6epnv4zTsjt3xtNKE&jkhueQ`mIlLKANrsfDCXhWb0)BZenj@kNew5ExH zr^;5xCqzo)LbG^tK<@SZ7a@}3W9o}ONtTJo75UdnmW2dXckVMSVr|P5Whlf-H+ku> z=fp4$JE1m-l33R1u6TO5#51)kw4u~OyrbdXZ(8tY@&y;V1 z-&sOkRfDIK3{e?|>0*r#c%rkO@@OkDR0;h+#yR}Il&AYd<}ev=l)B3Z%o;&4JDIDp zv(1ey0ixaiKE9J*hykUBsHshCcCSa;hdlZ;F+)l_t=tkX-*f0F<{G?|z5nX;+d4&G z)P$HH*7Vss3kGrGbL5Bd_*=T{9uZ`~rU$1JfjFqGWq*mD(>OX?lym;;Aj-pFgDsoz zXbHMT;>q-oM5aB)rQwE9;jh{G-h4|Oo?z5%LCXB92^ib+%Oq4OzQpRho4uRWYAPI4$JWR)W)q_w!DSRZ7Ae_VaffV38)|mj6mh8XsZ? zi(8Y^Nbt3&OX#oONe%C8)~|8~{|I)L#9PTTUoiq+A+JQLi_|q)HRwT+1IyxnOw|qO z=qI?|SFO(tDcl%f9_(0`$Bi3xGsNbYQ>*o{Mv_k#G?o}TqBgx(wTTv?FtdrtZ{W3b zK0epMe3DTgEqLVpJHr;9^4XU#Ji{dEeDva#UW$8^^rs@Au--u*5)0vhEa3tfL>8g1 zbWiF01(j5F(>-*%#~dW|U3}@tHhJVn6vYsx`E1vx0}i@u8nuo^Niurw?0QjHBGS^z znXtza=KnXsqba54*8p`?2#~1TNOMndCifyFCdqBbi3{BiM{h`!0=jrz3o$LZf%)Su zfp^3(dW+IcdM3M!JoY;=k0tvCkh8_nefL_Y^(zach$^c5aoILb(_E6!7Vg z1=i2@^V6o(1bh0EH>-%b!M(Qndc5T_|6(ON)m98dA-`M`JB*n<3G*CiiBe+9Lyil{95uT%; zT-%UzvC5l;z3CQo>{3?<=Ev2RbO%tMsNB4P%LNr;pEc{jP(>Ap`w{G9)lnc^L!3K} z;{K!9M`0zVp8zL{>L;bUK8RFQIaOul<#@_gGVr3g)ZtrA1R!kb0*z=_$%-sM)#r6q z*iDA?ionWcm2y!{AJFrqTemH0V!r?77eD38iQuoYLQukV1GrC9kL%{bDp~uzta`7^ zWATx?hj0Q}(He?DsVFldio~^U*v`}0I8M5?&E~^6Gq?~Qd6m!L=c@m(oR8Q7&3PCV zj{J4f^FHvyFBAE*p?NVW&u;xWeouD7$rG87cmrkL-_d*Ur@va8n@3hy_|Gui&yaeE zPxA2B&)lA=0@TrY8BsitFRr0uuDFhH)`hkjI47pUL#R(ECt}$|zaa>k8s>S^FD0Y~ zzsI@<(!D+HV#?(<7=mT7vn)K+N!;-BXU&Hnjdb7$kj17d*>V!b`lnAcR+0AouTXfN z9bcUejT#G+u+Af-oe(t2A7NRzVpR#JpBGTyXc*x}FFi_~sS{9#B5}GNhRau<+RnCG z`RisSnRLtoLxfB_u6fQ%Y3NkXSMO#2j`h50Ww-xB2lVd>$!c2_V!#1aQ!Fb(;BF(ao!)g)~a%FWY|xu;-F&%zqPM-m+ys z`-ptD`#in*4obi`OAfd+>BM^=Hw+p5i@oB4FEVMO6?aEdVmIQJ={IRmUd%k*&rR!@ zbl5ob0+@Psz2cDtmNCKecj*a<0>g0tSL`)?Ux_Qw|bk_i208Fp1JiY&xA6sSmZo?QwWCRO#Ny5+A9zNsE{%% zFaZz;RnLpC4kjftH=tfwl_M4#ZRyO;Xss@atC-k#5S|=}Ua1gEXA=}}B?ZL3tTup_ z*;yfc0eMyTU&h0EvF3b5WN>S$9ky1+rqp<3a?Gw2?VXjix!e(S{i?N=10uW)V6>}(o2s&YYUb>5l!LJIXsvhtz+XaeIQvX zi`2`VJwD8t=$L?sntr(bSs^MLcalt1)7XS;;XmqUxPRrE>f?jK*&+3%Jh zF6Kh+y#C)0xBKL?Wy4OV7?yJ*7je~ms%{OI2nj0>HE^#~(d-Pq82PpL?IcO{?vL9I zt;CM+zcn)57_7jP3LRB)kEdR=Vl{t837KE~Rn1l@$b1bDA;-fzueRa7Id_;YP$zAA zvN#ph6m{`^iSEU6&aETL(HFhC%}_Q@`b}_0I;MY&jGJYa`{(gf_1Jxq$FuS}_K+}d z%a;eK-KOKq=hbPnjnsDMUTb9>k$+2VvsAsQV-tm%;J)Ff0+q6k!Y&OLXVcrECY;Ki zqGG*{C$_^qE6m(YmIAol78EamVCe`;-s*IaonB=HuiNj?h6*ROJgq#X)VD@|US7y8 zDWuLu#Lb{7Pm{k~`>d_TtcJ)pBP^$V<__3ua0%Usa5Wwy$hQ%c zC+L;@<#0ZhX{jVwBJ!;1qkESI7nO>6SE7R(wJe%{`l}qUr;s{NaKpJqWjo?geDY z@{@xxPKX|C&hl7RSldM}>N*DU{0&Xd5$JQUK#rT#U^U^E5We^EK)Prshmjt&aIh{3 z61eJBnjt8|er}3vA0iIv*yB>~*&jOk5UwXXN@nl=DJ2wi<8Bh#E9Zv)eBF^31R`2L zf8@~M;f|UD(4aOzI}G7TtRyb37=I`Q6dn$D^W}q!MpuzavrGO#v%dqK)O{-yPwD1I z(9&U=0lxZ}VMgKE(P|8eyeW}LN^_H;OdNf=moh070~Tyby02PT<{Q>N#fssTF~rI{ z$Qg)q<1cZ4RTCL!%zm92--LhrlzboiJ74$>3@d!tzwP-Xkt%70x#tgEev*e#Mdfrc z^4WWl4TNieji_Uqu65$&XiMKnira>&8tLUZ05ggAhA~`28c|Au-Z~y&o_AO z+TDin`{+5Ke8@eIF5RY?A~mqyHUx56WHqqf)j@jAu@sOQQcEe&OtED=*4(=w(~8#< zE>QhwYzy}1NEv9CD*kcIWa(BiX4}yzAcJI*4D+OP^Q46BcAF$VxOSLe>o&1>eqwN) z?tpa8Hs`GI*#sYb!v@fYf?(AZ4*cdd1dPjd^!Ky@_xfpd>S!l`SF8bz=GSR6U*Hz$ zw`%`Eayb5zB%-U(2#z7n|5Fs6>6z{>8S!gS3a6a zL9_gjyre2bqnN^ZQxF3*>Bes6-8-w>%pR`?$GDSM1Y|Pk%)D^7AS75|Grb_!Ok(if zq_b%UtQAxSg9=Z)_SgH6>(NEQJ;26@9z5hNDHX&&Y1VMa1cItO|N4L$hO1^|HKa32 z(Mio038v8;u)>rnQ3SJQ*Y_we|6oJ%@U}!Vv>{Z@kEFbPiq&N~#IbWU>+p?G(-)(? zu0>idLv*r*al_tnF z6!%JhF)wz8fX)&~N@cz}sHBd>S|mhL-+NuuTuC@D%dBbzZz0%G&DOWX z%s1S&yft2W=RE2rrKV-p3sx6b_0V2H-}`IXEjAD1VM^LUJHrMDnqtr4awC4K%4!eP z8=A-KK-iB6@o?^ad3T>`H9VxB@$Obvh?+Mo^ro#04@V&%A5LGDpgVjlkKi1?ujF&H zH=Rvva>i^p5Y6?>B*^+}$jTXUH$pgrEv+(o&($pwOG14Pibj1_I9uOZGl!0P&~CaK zc0i?S!(!6B_;bgk$kGyn-JBQ!TTHWfzu3ZrEX(~m3eJn=w{4sHMa%{1z|wq!LNH9M zXadlf-0%Hm7aW}dhTSiqJNwFMO~LWu*GO4cb0Koc0ya!_ZO-8S@UFIxPEiXddIJ7& zAj&S~pkDoSs2-`g7Gn5MWpG(V5twC171Y`GIJKrZIZ{@B6e*N3ZXRITRSPNe(3bsb zI4eBy+XmB^fmp~UEVm*%u(BMkfM(0EU_YiyTLnv?DL1vSK(3#t6liW4={BBQg_%TaOZaZr`EifA?C%*74Ycwa4bLtR%P3d5qpCCP=NR%~D7!70t}xs_||G5Y}3j z)}q-$Bs?TSwf*08UVu4Pludd?_sJEptcKRrHgPU+XnGhiX*i};t!-IIkL|!_#gYi) zth2XKDG$jAdeHz4cygR?tzwfbI_01)P#jr{^GJT+t!06AFfy&d=K%XJG}Bi5wP6OY zEaji-jtdq?i*OrHoc5sB9`Y9|^uZ%;IKdzmD(RwTD^YaE`BC#selut!7Ep*lZ94Ao zrbV5oCsmQjap}1)EF>DP_OtvuXPfG?rPyIH%L%z2`Wt8`TlJF(cYmVSk!N$kBwMBl zz!#5X!?$@tQ*|Z+ynzvpoapI&dX)&1LV!`Oh+Oclelg~e7f8;i6GNQqOt_ir!Ur2- zrt(b%Ptj`ybXh{CWMAyjWyF9q!ZCA=Tgl{u;&2#m&hX&5>GX%oa0c|{Bxz3!XsA1Z zXF6KCF&Mw+FD8bzRa18Vz+_m?M^2US=aQ>}a~G%Ar?T?s5VpT2@&>+Oqb^*1z>f6X zJcYidpbvA@rM(+emx1V-CXfiI&B@FfiU#Oo%DCx?8qOlm=+Xkm($(FC80TY&%#)1O z_q{e77yay5)m)RYl+8Vm>j({V!S`PiNtk@2PD(Z8VuY*DZh+b}=9;%r`ahjz=~w<0 zD95u}o3rB&Rg}!-&`;kr1&Gxid>-n}QTu+H>hDEOK3#Z2jh!t7Vfe0hpsS-+(KcHf z;+pg>2*{i}m;vBqIaTiUHS%n2sS(`T=B6pnkR`fgCWKjIHdt#*0+chZzSEsM88!AS z+s=APkX^-xbG+(+{04j|O!BZBue+{4QZYBgu8&xY!DTN_Tpnmh`t!PHWzWw8mA3mx z;+I2#h6F+J1)&h2mb=u+dR;x&#*C;|0isWneo3zsT^u) z+vB$V^jogoF@6`mP2deDL#BN~ZKVT(^-&;g#{O9N<49}s3p**BTlb;onWrd`*0b2G zDh3%=ECykStJC*mIy4*&9NXOJW;lA}H-dK`3wBzNIlD0Ej6q0pBvX0{X|9b^|NDvD ztp#QyG3Er3IFl$CtXo*2IXVpF7?p>JEb>tRm@#@>*r4G{x?;o{+$Wj%NYGIR0IJqW zDmX&EoNNIG`x=fS81@~ckIKl0HocT=AKMyu%X$pAO(9xV%M7O>BnuiEq-ro5=z5qTD~VWS&dLy_Bo6Kr0%j$po(N2GA{dO3=c|h@ z8OE|^fWr_{EUT=HDS?9jK4nB8GFGxsVO)mqO|!U`GXFaY9EdS>d z802UQ3^oEOxpnv$*)cH!1v!`;R({z|ih>Pl8LOgEAa8oB0!8xEMdMh3g}{&rC{9eE zGbknY{?BX1`d+F4`}W$QO2$!5VPIyAup2ny5IQ-ovAozWG+F7%9;XFpj1jOFrgZ?N zU)o45ihD#0tVQQW%ZQHJ;{P!APQjUWQP*xdNhj&pwr$(#SRLE8ZQHhO+qUz>w#}W| zwd=24^}SX9cOS3&WF5>k=UQW2V_X9*42)X6yiU=bb1rX=s4XADKqHi2J#iMwt#^1_ z`_6Sh_h+ab6=5mZ!hVPb6PG-h=|Bgs(S`}W=G|5?ei?A(PJ;`!!K*%cyzYq}?tuyB zlPP9fdguzMo*%lI8R&ubajywKrv)3xsW@+QlU1t>5Vb{?EH@9b{MDV>K$3$09N_ji z4!xben?rg{YW%YPv3oagX^J~DgE#D=k}%?cw)y&6GInxw_I@;Cv*g%G{`vksbpLi` zUtZ*snX@fR<^bJQ+JiAwU9#lKjG-gLXR&lGTkoo|sm<$|x$V{6Q!zYo_WcpM~+-4Au&7Buih)?ie;~sZ(m8i5j|Y6wh0DXGxZLEV|!%6^zlyD)p9ZBEhSBo^+y|i;-n0R1ciB8q1RrdCa12B1gCy(mscgI37|AEqx7TkBQ3KW`rSa^w{5rneqlcjNY9lQ@yRc%F5(<|27G|t@Iwk}0iz({N&H|FF9=H4lbBW<}Y&V@pwNR7%jCs3JfRBJ<7h zRn<8d?q62$t;$PX#PY&{FM<(10|UJmtX{6i5LIfaa%ejdhYG5q-DrR@mqStm zPdOE+=N~B#NMU1xd!|8&Y-@nD4lPzko(qgBb4(yHSz2?7dqk`n2FWt?YQ~_vQxLs2 zyiK3xV{q3&b;ua{U_`B{%D#tMa!b+D@T6Y}4fzd>;W z?P<13wvPI@#HGx_PVv z6Ws*5c3E`*cq{!wY&+=bO+y5L$ zl)-V1O{Otshb1`4|i$>?2FU9)FX=;K2k2?7sgk4^19(zXa zKwyHN|C5MF0rq2Crz~>1!wh85(S`#sd7w$Q;Pr1#^$wUhB~PNz2o6ty)d5-*Bk9Ji z_mp->a*aYX4AMrJKD_=V`k>??!u19HQyhsL6BN+n^j-);*7qTfe>TK|{_#f%66vQ( z;wtLZ5emlC9Os|uFv8o67t0WSLMwW!djFln9bQAL*&N;1A zwRZc{sB8=pJQ~=RW(XSZ-YAW2E5#+oVa&i z$h80_FH57JqtEn_s_M9ejU&63WFb`27{c7KdBSw7Mh;?K^dr2R)_Qlx0Fz`vqEzC8 zn>3T{CzRr#Tyhd2Gh(dP=_+G~T4zl)65?E^)bFHOZLhk4ukd5WhYHTJD^=Nyy)oY| z$2p=!$+patP7dH^;LZJ+FG1k6WTH}3eN?GlI)lyTqMk`&lN9AFf)wBYhD8mmL_LPfA4jq zjxSUGXIH|){vWYu3@nWQ9}V&Ut`bX9-Ts;F;k~bQc8zfeK^UmcT7unrS($r-d7E&T z@gG5GLpZ(Gi?v zSm|^sIbU!1WIM0!kH_yC7mq;H*jPi+Od7h8`rAOOlp;)lbg&$>;dV9$pH_=ZxCQVX zKhKFD?4Umz_}UMn6~V7~^V%O)nRs-Q^+!SOgm*e?mJr30*grnK*xtaZ~8Q-MI ztSQ@M$$zTONtc*y8+*9L-x6rs*L&n%?qtfc*V(h(A7V&*G1|l*O;-lkS4JGKPo8wM zd6g$3v8-<@f(KzS7FC$scBXZisy9!N(;uz?!sX@V2rqr{T2$Bl3q#aM&L9zob~QOE z9pO<)fmz4Z+Oo*j2*m?5gR|NN+@Ux@cNwuM`0zPqL{cU%{M{9aaHDYPCDOU@IfaF;pK1pQ8 zy@$Jt-DP_Y4FPCw3t2>zX*dVIS_o?98>LV&R21ZHRz?)ThXjE}ZZ$cDgjzSwU zzJx&vF)NHOEsrYx3A&%gF zqI-iBL>}3iU75qko{-DBzOIQ`Ie%2Gmh$7`MC%=5?CjbhY@HQ}-iNa=-&RSx$;ONA z(GmniZ)OE|`-HHT95!!BOLIqUJ* zJBFANs2?9%TKpVJ5Gy?HzWdUTftWGnQ7nt`;M}lLSP`t*-e{>#8g~*4Nf$Le+c%IE9LZ2gqH>j1M7}Ak1klp{n{$f0bPbR^^?mYJDsQal z<}MVDGFP63Y75cQ$q%C=#T(|W4>)O)qAS%MQyfvmU@LxvVy4?TO8A|s%$&6L5EYkd z5~NSeMi{VgfHQ`*Uf{AbE&K?V`=-XhHL)dZozyO2s*=_nlbRwCVL^-#)rG=_Ww{={ z-8huL6N2hv1{t^$GYmH~&0n~A{-@fJ9!_1o*kgJ;8pZ8o-kGzEY*ufqs%W<0nDQgH zo;Kxbad$r--~H&u?f~ib;>Io4k&jx;<(X~T9i9T|Uq)3&hYG9pjk~F_POJ^4Gnc1> z^~IhLVo!T*Hf~3OML(VTg6h`T%L$F)L8}H`%FChCJ$GK{>bNCEhlKhg(IU1z@eemn zS^6;H*4d@oJL;1Z#j|H|rRZ^0*&Ac}?QXKtq?(9(;y|mGXqZ^JSVuSDJv!M;r>6e< z?-GVG3=aD4Yyd*{mdG<&*lliu^IK113J1HAN%B*9{iYfEAIT72)i?Eb5AD+y=Vm>h9-Xt`2aW0}Z&a^Ppb0_1H^)vi}O?9_3O|2RW9{^Nd_k%^7@f9vrp z!Z1tN7kzyHfCT?bKxR>;-s1aOo9A3sNM4RF#IR^wdKS0dT+bO9&2e|`rUHnk2_f-B ze^z{6ICsHIx4E+3@`hNXbZA(OQE>qz-GQ*(tJo#Bdc#*;g)fPfsM!$m*?-mUHl3~? z<8_X{lYNvv4s5#E@RiyM>hF8-3s$j8w5bs@J4dF<+%U4q|I+P?rc>SSSJF%69N41I z#aqGRb6RKl;NFe7IHtKoyL;j0ID`3>rij`~I$isOblf%>)v-lvcDA9m$LC6U@wN-Y zO%iq=W{M5g)@l-LGJY#GD}h+Uebih9*}5-S-Roe0qE=YXhg3!_6`%q`vSq`$<)tnb zSJ0urr)+T;3aSAlAb05K3PsL(zlmJQxM0cWADzGYI(GoFfg)@xGC;K%#t%s9sGmdO zLvf#lFv_J$dwbBzo(W!zQ~*H(u)F2r)IvbEieV{@JsTL+r#7QBF; zx;85U2q83s=S;!{Lj=DW*1nGHthX5{*F}boA4K?&aq+)nhlS>@xwHdvi5CWn6TSfs zo#DP`ZGh(gQ;EMo>DWM@nQ^SKsDHtgjwa948oA^MeLY|>qpK$+y#j1)5?)8aJOX5s zw@X_fJw#y$VFW^9qXYXsVR}yxC7dR5wr)p0#?JrLR!JHBmf}L_Wz*EVTL#Sb&m_IvX(X+PXn^t<@0=N*){|jU9Hkrm_p<$p zZR86L#a z+{HSc-5J?B2)2z3yGi>WlD8N@Eu2{x{)d>%prW9ThoO07 z_-VCsRCj1b0Z73J;Vt0mq5~k4vZU(-h86p0&J1;66q+`Rz-@0|%y?1L)qzgZwXsQe zs1FAxOWGf5VNaODv3e;d{Tp=QSrk?Q_9v-n)*atjwAcN@NIBq?BSyhY?^4R@9ZSwa zuMUu&*N2#Dk)Rr7Wrd`WdHai%_9dfjv@Def@D=hzy9in zGkoALL@B;RRVJO+f0+I%qU4jy%wB(}^)yfhClTcl5R=aerf;WY531X#47qI1K_19J zbNR8`o;&*Kdo9Em-S)`Y{x7P!y*}@tg+$cb*%t~6)3ZgEvhgPtWt@?G9ln!I(yIP+42l% z@Jny%5mOkKZt#8eZlfLxtH_0Xv%WBiyr)Y;EFNSXhw&;+Bcr~kpbev#f$3UYc7cUL zUeA3ep2p2^FV%DrbHdm(I1@`%$51A9%bJP8sZOP~TlyQQ*;?fGtGV=VBo~p$=KTgS z?|B=?L;0LK2$z931~3sGRaw8Qp*C!+Bz*uixxnimXgoQVQUF3g00RK@Y|bUw(+VLNe!&C8gX@+lk^FIWt&M`^sLpNMOiV;L>GwtXVIohGDeJ=DTJK)b?C%YIh=)XM8@`8=n4z$4B1en7O zdAg8NeDsyen81I$$Fbizq6U;mm^u1=fk9CkZ@TE$(~9nF)7S0CQT2Mq@RrMqtPfj} zB*ufIv{!(od4lE2+CVfdKl9=d7Dn~^j^n=vc7!Xd4kGUr&}TnvPyhMB>0!Q;m9#&Q z@P`UU`0nFBxrX6z`ZBJi}_72-w`*0^Y#xkE2T?mcw>*k<;D$7`J+6QFTD?t+UlbTtMH zDEc$);N|2vsKX>MCAq0U6o7An7T8)sM*VuSXx*|nM-&N@C(T)R?qQOX8u*nnPBtLN zF=;)RtXaB!Ki?wgN@ru+GxeN}b7(~{TRnt-B$UeL@?P`>nkt{GsKDT&ARNePv{%)_ zW=|$UPyD;${I~mHon4DE^*hhiKnI`CxA$q*I|r^|U$v(|F!%G+sp6KE0p4A6yAm4o zU<$9|lQjqvHV4caxDIFAIsRz#3aw$m;-NGXgM|b zmXFtB;kx&J7qvUHoxXpQeLkABeG2M&GoYl}5f8ZmT=vn^vN-;H! znEhrH@0l8ODJWslk#Ot8A}|ennEI2aGE>sOzLvPA5zR|WL-<8$Sw7ni1;l_K$@UxZ z-Ho$r^>*IZ*T)jubwmgw^*ynVD=+V$9pcsA0f9;fz4+3A!{d#`jVEiycJ}w{)H}1b zl=L1wg$o?QOkLCaU_vs0gfh~e@6ad#*^dLdYtyoU9nMju%CaKAR!X7g=>9X?DD|ia z&*oA0e5N%A64uMY^|;_tqZr17;IWx^Da$%l^HhLOfXRq9w75ztiG{Kjlf&DHl2-37 zj;=QY!~+h1ZkRWYjA^Gz8JCWADfwA1Zws24UaV#d1UUxOL6H;r;BG6myVktC*%xRl zTI`?0CNd1gxH|I4UB^_shsqEUPzXfWCS((2%B#aGN~upUtg=p(Z(G7hH=@G|&_eKx z+`G`;se|0NpC`OPyXPPV=N54VGH&Ea6KF+$&Y;me=F7D^=-cg=V;@5W*d!3b6457E zK@SSQ8tiSRUrl({M?Gf{!gMldRhFF%$USEn^jq*`isU$1G$*xLHj}?sGvZMGIHH7N zaNs)$`{0JPFa&TTr&W6l7HrRuil@Mh$ zos~WnR0^!Oc)s6D@UGNo=jkU(PCtJ){W8`pCw{Tbgv%E#22VU^RJHIZYX7kny`c&Ml^ql!d^CiAG2FXi)hw0^}MTe(eDO53Q8C|(_7YS zhyuAZoT_++Nge77XTK)V7X7U{9;IF7Cue;G)D}whEb~SzU|fqmRLUlN_`D?Ma9-=9Q|GV#>W`>m6kkr zpt&f3MyStc8*qX9c(D(M*i~Lvh4Y5lY=9n3AO}0o@jmsDLI)KUQvELXaX9B&K z@c?aen-xOqLFg?<&M)uC1If63s< zjc}N+$z3SI?Xj~@Tz{%(ZmlN?3EZF2pQURg3uxHbaB^rkuy=p|4(Gv)sCocYF*$Yoa z_WR2*;5fnYJal?0a2~-(2!Ja;sE_oBscpe zrBA_*$CWgh(^COe$(&SNlI0L*^m-7kO13_^lWBhsRv)41Y|=oh;7j2qI|!(CTv>!e zGl&L;YXJQn%^)gU$WMjG@r*W&S*;Z%;sq)@T#GK(AXIz=DS*8+-Qj@{nb!E{n}Jhk zeI>m;cW22j-9N*h7NcRTFJIi|z{i>-jL|*E(*OASRLQY`ubWc2CW(58DRf7qh92QN zU#N;Q)iKsg_|oG~i|ngOo>s?g-%^HM-QEY~P4lV&IejRzBY`-AZm##H(=tCq5gJ&6 z4tH5j#+~__57YMmou`2s_N*Y+NuHFsh?CA_G{s1Nh5e#}8E9L-WRU>sFCif#w=C$i zt^wlp;B>xY04`pWa{)lELL#|QFca3lK<-~bLWMr04~ZZssW@|%9b>b|utYwz9DeJ> z$AF*id>GSjQH>p0LYizf4K;Nx+4*{BH(`yOXcc>k@7Mx526!e8}t)>u%;s=RxjyrSUItotB} zkoF3#jryQDX9t{!x@GAga3OattEGUThx`ik923amh|~5tbW;E7!>taxM{73arIYx9 z^1yOyf@wW zDQsKHAOv9F5(JQ5P}@bObD7Y%X3Eq@u6}mIbM~v0PLwFPO8H%dF(wZDyIu5_Z3>ie zoVp&d*AnT?sI~(PX?tZECY5bsGs<~ZMgUXG1U^$?DFGP?wwHlcCCoMXvjcQ242(lqI2q=vDVKXNiRLIb)MwhZ2My(N+R z%t^NR5Ne{<3N(`pQ^@^>T=u6@TVQp&r3bwPq0{I^v459|8@g5h;x7YX{n9(~4aG-v zf~GoxMfN($(={=do*Nvo%5B;|(A<6nG{LFxM zCq}Z2b*KWYJD&G^sLQ4T$zO8_O|t+|X;6`~y<`OCeO6p&{b&v~t%v)CPY^UnNxx2} zeX%>#CQ>Xjvx9iyHpl2efO_u6DqP1Hz?Efqq?5X_o8jZgitG3{I}jnd2*TgY8)Qt1 zJr;+>$66Efdmr1akYQ7N{(j1c$*t-ph15b+(DPH1p{Kddl%kkx0XxT)J5DU-cSQ?@ zKsmwJ5+gQwhjG58n-(!!FaGiN&0nwZMKT|s4=5NHub|+ly?QdMgGbB%eDQ&k>AiI-{BTv(2+Ee4Ii8WA7L}^_{VoKV5V{;}xWr{ZbMIz4WzU<6A6 zncdG~-m#czRCJb{L$wcknzwKZS+6`#PbbdoNIGwk5a0!4jYHaa zynR(vEkW}TgeWJ`_*;OK>aNzop(l^ghyGIJE>G->#n~FP_Em3A>+ogIChz7valtIN zTftP;8^RZbw%}(at|7j@8_(e@duY(E)9r)H@gj`#t0>-BVe4&XT#9eL@oQH6k0`!d zsoSHk*d4g53_f0c)z-`X^g}_b$ewcL$!7qTLymSiS(CfS{5{Z`*fE>caP#AE<>%FB z75L}gWr|M|5;&s@8_l8i`n2l7+<68+Gb_*=-U#Wz^mDJhmfPHUdHRO9$0Otu875IY zfoEpG&|{7n3M#@VBOpkmKY#KR?n#A@+vic|$)&FCKSqZi#{B;@nXvuu*%4J}0PBOn zJFgx>GW^{*=SYC{Har!m|H*;r8k#>pFm9%u$8hCk_QIwNqmQhT%Gx+gSD&u%s4ef?@X+ea}S-(GG+2l0CG!AA1hB7+qK@l0tN1oQOckf8mHMrB?|39B_N z4^@_{P0LkdTb3f}C4DAb1(YSJnY@py&t$;hkE$xwf-wA9OnO2~R0qg@|MXiExwq># zvXrG4uGCrBxzfDG?4-RCaaqAyX+)~Hz1v*@D$|X!Dak#>6UW>=QA7|$y3-hTTQx7= zf~{wj>UwA<;QT6j*BE3pB^KhOVTk&wX403C%F)K1%eg)DeGJb*6Wp~`H zu+5FM)4z$q72#bH%)3kXN{wAvKd>+6If30@MSdIsTKGP1=*}J#76&7iQUr@~?$uF0 zeAKaE4OVF4;WoCNC*ph57uGm`d^#)Ftry%AS}gpcwyd^A(aKApJh+Rt%3WR6N@6>C z^`Ne|(H83z3xIRAxHXT}VSKbMQkTCD2sAMo6B!PGkajQA^SZOv2_X9<9MiH)$f$ZT z9@U(T?2EMd&RDmd+Cr#!VrqMip{eMjJTtA<1=*2-f(jbVdicL~l|L2&O9>yjSN9+qnA5gC=K=o#5uhkwm zyA>n`zmJ3j#>V`9`8jj9M`6KI*L(mWtPGOqp|t^d+t)e6m8eM{i5qlydl>SVp`oB*sY|h>*;JpP4f}=rZiBX$8q_>32+( zJc}sTh9y(&r*p2@><2Yp4Ruc^iSUw|^lWY|(9JkQFlbschqNUno5196#%k~&zv(K{ zyS)AmHG{MQ#hZWy=*CH?QeZ}mSZikJrs$qQ4Z1Dk1G$)+=>UicZm3y}OAovhk{Ie* za2{utU1P6QN~kL~jeph(c?|6)MzE716i>Mk5Mby;yXi&fo!3odn^6g}lq=?wIo$b$ zzH~!`V+1_(Dme35C*y2rps1X?bI~J2$Slm{Qb)iL93gR`mJB-+%+dh>I`^ZZ81Eed zPh#h{RSH4o^$Wcnw^paZs6Epf82Cp}s+jTtG)!>>W3?xHB5}UDxC4`@1AW^}r&2ae z<9ukOxNJbJWf{FRuIKHZ-{C#30}ua=R7Z!mSq3%YD)N3x%NR9m-agOvGF=Df-mw`A zb%_$+dW4#im#WZ_*A$UX|g{geaMOYRTb9H)Pzs3?NI}VYt#t26$^7r! z9Cz^ETr8maK%*g*j&0Q&|Ko@f8+}tG#Nu5#b_|RT>@YK7E4W{(q0j})UR+MgQwT+3 z%SD)|>H;dre2?3-Qv3Pxq) zWq*1vD2qlSct;hP(SB0FMl+F#*tqNSdz^^mLRErc0aujPGe0RdD#E14Ji_2q?f+sh zV-+)c@mJ%?&uDam%Z6HU-!tS{Hs_@QCe)!iW0Wig{TQNC5Km9gH)ALv&ZqYB6765g zj5G5_wJyd@b7hXlR$_I`I3QRTdJ^b8R|3LRXG$D?S1-(LX!rE_#+)G^qouup|KxyAfX7Wvn< zs?`gJsG8_(Snm8N?KU9$!@6@y*TlOd4VhX=r>{1!>QNY0tzqyr2WSI3cc)fS{?GWD zgigyozgKcJUjNY_5kju6o?=|;J8T6YcU#S15&76m>Y)x5zKyOosKD*_rs{Gt5c>McB$PrXUx8ezh1giUbxeBDgg z^T~~O*6xTL*s#a9Q(|YwQxz?EYiE|1HT(Fy0A!QM-`@TH4eSyh_>t4BuWL=uZe#JU zQ%5T;cnjH-(fti1WgkqkLb8)+di|Z9aZFJIMJe~okmttT5DIj35n_lZSy~A8uuv{W zfYJ2fbkubHLN#WqsB^6$@!l%Z8cLt;(EP!7Lz1HW8e~GWSH1Vq+<1Q*%&9wmi8E3lBH%%&280(5C36DRnl+koouFmK&2x~i-DTlX@x@6Z-)unbZC4bAxD-D?57-k~?W$t&G+Q z!m_^q6b8Qibf%q6gy#FJKO7CKilbx|X5P6EhJG+6-i8GtcRi$hwEB3g5W;JuG9Xns zk$BiX8LmcjF(6l@-$d%ZsiOkuhMH+};hti~R0uzma*l#DfM+S#1>?ai8@Zd6*mSOz zI)c7rrR=bkmoA1aUI(^;)pBgCmK((Ii|MKz~BLlaW&WEcpQ&zFieP! z=|?q7{b0tw&h0;33Z0W?!qO7c@q@%b-9S22wHeWW)vJJQ4B~;r9tW~$5oVKoZ1H?0 zKcFraoqa(W3hSR$RG4cwn(p2-{^Uo4(pCD;F4umhNA?Q#Q5ijExtW^WyxJL7(W215 zESE&s+m;D3{}LWh2saj^wC%uE66BL6bV)0(?xK>oG?^OkZmH#fB86r`eIMhrdzY|C zje@Sp>?gTp0m+9|W1eIXMf)AMJC38m3JCtp#?1`&&cywoA)VG5yon7}nOQ=ReK!-> zp2G9-N;OoJzYgleq7)MKgwHQQBmUKlprGSl@7+js(su7HWr{7)lvKJz#NW8z8!g#= ztxr*N}3_7qON`4Ie5yfe^%3)>J}4qF|54-j(v~dgB zBPT#I$wPztK*G5qnPl~g>s-W5uOFL#Dp@rNg%H@zY4Q@8^u6^v?_W0+YPO&YU-eJn zthA=5jAr(8oWHDm@z&wt#9BVB^e5z$($1l`RLfj)6Q`NK;gl|Ad)ql9Vje%I^6mV8fUiLRn^EURk-u!@hFLj8zf;M0@6 z_i|qlA`#`@+VDn5V};6BSP3b#tpebJ8msbd!&j$2)&r-^GQ!Ff8kxTT^VhToE8fdq zSy{O_J2F0b>d`8IQTnB4{&=Oed60h>ff~&lG}Dgmw=kE@aj>d2@O>T_G>|f2^WdPn zO?@N}2WNJqG@>K&A?B++_HcWBNnyCg_?Yl;W9%$wi)3kg!Q1)(y@vev7^MD^d3`aOBhUv8u z5Nc?%wffvYfjzbd`Zu0OEFPLx%6az1Zkq$x4|JtjDZKyD?qY<&+z=CU`4aFv_EgBHv5?Bd}TlI_3qcebKs3s?{9svD$k$?W!C33Tby5VJ@WKvWFGjrF9P&`A8wDV4B-)ZFbBiG zR4>cwlTgYQT;SsogJYPJv+X58j-VR%H)m%qL?zaB?`6%S|50liXHbb?8GlSsa9A*H znl9zVSRjm8j5jIhsbKmjaJ3J*=}ml`g3pV#4TjXSW^*W z?jfp0KAb4B%Rp1XMT)biP1-El1h=8#fCj1CNSmx}^PWXp`DOY3%~9>g>O$aWr8+NmdqIztUuV*<6Cc6_~HW23H+=Co^D=X-I$< z)+A_|IwRVbyzBp=73Vh=io$B3P)sw|E9`ct(>&^_i7q`^M==Fx>|55poWJjQwzR?Dv zJHV8})J6@flr&YkGm9fWWGs(01*&oo$j=Q-tY1O4Ljll8L?V&$E%WzY+&?bKgsoK7 z7vP_?`wuuRDJs5i{Vfh(e=e#5Wz5d1C@tlpJsCegTWrfwwwu!h=O^x9#LGTE>VaZ%*qO+=x)@l@FXtfm>RqiR!9+{)FTDDB#n~D$U(^UFmSjrmR zFjP$o*6%D6t6|!5va_|-zS;>`pzJQcc~Sq@X`F+@nffNsIobrY%SH;WpSggF+7|l! z%>bsk1;nK?KmiK-AnUA2KI!oBN{>E>43!RY5dt^03z~RA94;=EZo(i()%2AZJ2|yF zwlWfMcc+V}qX0hw!}{+zt*<_v0^_R$zjE_%256r-A=5;?{R1oH!z)}qIcI!u@b}k; z6sfRDOP363^t!~7Tsj*Yr;=P#RV=CB2N~QqyB=T&C$d8~ZhUAE-IxpF!+l1*j4j9q>4UgE~2%LF%x zy<4^)@akE;=*r}Fb7p7vNH?yfW&U3kjr~6=8q@z?wto13`fPMlgwfM*hO&^ud=FDU z>e&32ms$M|@G9XS?487{!R2Mmb)+$|WO(P_8J;kv%n>%Y_=4@H>mT)weG^iLTu{ZQ z9!V0JvpEWwMqa0GldMY2v`Ez^|Ltmy!y4~qF!i_M>Scs*7vqN3XIOG&Y2P&KEtrC^O+t8LoA2ccc?g>l(w z1D^K2Qc*sA>Dfb?7DM|BlznL7Tw}Yf_Q((IwKFD>6Wqxnnw08*sMwYB-iMY*I_J5& zte0UYH;40mA!hqFB#l#Pnr;W|F=>8IAMs-wpXwYGbI-$E8@#eHa0O zuMJcQXWho7zH`*xU_Y z;Ld})abrkld{|ibfBqrFS_uL0Q}t?FjbZLmm_?c#$vf0XVL5YutnEj70Iq$R4^zi73_J6`n0Uv37Z`YQCfL@RH* zWxRenm4@qXtxaYtYDniOXrLSiQFZ1pzuLLwF$vuR_W%oJ$BynL=5S~9%uC#LC}*ZX z{@!$sQzUmvTkxRuX;%8CJd0;uEJ!(CX@0}_5*bO1j>!2Jivb~O4i zDGMQDVjNvni?Nrs`&e_(*a{eOYx2W7U88@4AFv#()$m(5oaE6`*0RfRL!3`ciWtaz zni>q5g4PN4m;#{xo@f-VQCOHkMy_B7~nPXT^czfg%VHWutyDE3Uy* zN!agp7oOfPaC1-J!(Qc!3Wjf4c%Nl^gyZN8U_f$u*Cb2I%PDY!(#bX;+{0D3Cp*&a`Xcb#`)7pTDrC1Pvms7RNLaf&N+BYATvj67E&08UOx=a>Dn7 zM(xe2Upey(zeG_{HUf#x>0(lLL}L-sqpG^;8ayc469CurtrT?9;yCQUOf=|7HzBxN zB9C9va7CvfyRL}(-H>RquD5x<$c;-`bQ}ROY+wWRJ;JRNj4yKv)JamenB_2V)kX zm|>gJsx&OZ=FvT}TK^=ird|kSi6e&E)hhRNuD3rwIACogdM5KPj=X)4z~Xe052cfj zypc=To~NeJWUtu(%o1IE{>=2_+ZIp_v3gnVZ>E;}6?(e8IW63<*jZ$36wNGTeYCjt>S>(aJb`+ zid=ja|I*T({M+8`eE50V!jhEI?FNroI06|}iSyl7&CWx3Xy?nK(%?B+X2=JTUB|`9 zv%zAyag?hnk7SJ0r)Y=YqF{XpG#<$V$(d{#JL)EFN}vZp^VP+!1Z$ia?|s)=Y6WW& ztnqV|+?%XO55DaaqA$Kc0Oht;SjBZ*S^_R>KY}c|>frOIH}lOEoX6p?kfahuZmIYc zS_DrfI{i$zFMsoL7N1JME>PuW(axe9&Td>X_(!!AbCd$Y;=uT%-5f*M4vTEMFm&J0XYJ#O=o7N}&BrJ}}y?Mm>|P2`pRVV}@G9cMWb*WY08 zL&DgwrI8bov_|*1LTqV_=ot+c*yQv24#3Udo4L8#%%naH8=FmPrLvI{?5*61!8$zv z)vcUW&AckaS#$!rWxAbPAv0b%ZtwDVrn6J3r~UFL)u*recS57_Gw0YCFJS1_Qkxax zP2mD_OaROVMVg-mHki%Q`OsgfMa)k}bT=jNOj~==5GR2Y- z?yVb|Vm9%dVqWH-Z@CjXu?_Y93vTkyyWvSE0Rd6QbSf zsLRY>Lvr52fxsi4rN_b z0fwp=$Jy;gf*hhA|E8d>ZFv&irRmNKb}}hxBN@vzMj&(CE@TyGMCf#MCtFOVn=sKgMc-u)_+GO>PJVHQ=WNy8-%_;=qFN*$;CqR~JmgyUbaePJdO z3dF4tsR*3JD4LUV8=f8gOEl8Nn-&o{EL~Lb_TFXahw@ptK-rKaQ*ls^E9UHwHbZ&I z4m_ft8R^f(;!R&uakUJoMQ;bFKelK_;in=ULBT{%{9$R^WYxi2c5;xp%4K2FmWWWh z%F~43)T4r@w$)0C*R~Ca5=aP(GecLC&fvqkkRdc(ZDM!u#n9M^!gtfL+oO@52*Oks zB#Qc6GIvvM|>2FD;r1gg@>UDq9D?lv_S2Jy5S1GdQ6Dc~axlugJ- zDQVs1RXf!uJ&Wxp2X_;1U)?{0T?qX9k8pAI^>U+oFJEdYHMz^qXm!7u7RC_uZZ%NG znp588Y5Pq(CMXujh#Y_OIC?#*Psyfi;pxyB#p%wx>I2WzTf*L&=^}pOE65*ljmR;y zJ8aq}Cq{$PJc{BGCmIhKJ{uzf86j;Eif=1=H=rbq&9U*K&`AgHsx|m41$;yvBK9_J z1jl4e(!4vsS9pvEzb)^l#jc?4hQRFy_urkUCihRH6R|HDA&nWHgi$<*{?-&wZ6_xgx!A41wN{|{yF5FH8^tP94rZQIUCa$?)I zZQHhO+qP}nwv#@uv3l_SwfgpaPpfuSeL}W;M~6z0gH>z5qa*8%3y_a#L~cMrLOn+T zMf48xOa3mPP%Et(>UQnj>HWm7ntRpwkJ*Ej{Xh0TrvD#ta_EyWn{0PEwG3N=MoR`l z3QL7$^q>v=n@P$#eqqYaV;N2;vMyN zK9&gV`x9n97@*sF`NrpmR&j=VMiI(Js_V9VuPcz^{L$&Z-O*n-dL5|A6jQ|klY+(T z7KBXls{rQ5b8qUTeN1305&8b~b$159=%$jH)G<*k_;_|}jqUNYB9z4{Z2a>py#;bf zLsG;o5bEy=?92Al$$=Qq@_Cf%O6KPKh}Ct1YE3Km>OmNTg4pV8V|VwM`a83Ks2KQBK8T|Dj(?SfaF%O z2`lHo>{;bFe_#kUJ8*&|vTi&`B`?R_CtDsGWJVT_UBr_7$2Ts@+f!i5*nmuGReX(4BY2}^VcArR@;WPGDf zYbUys**cW{4L04Jp_8iahPGVK6`8?91;i<$$iLqviX-6~Eyzzbu6M_b@YxuzNcBun;4ZtpR z@eGRXz%F&hjrm6)mIzQ{yi9caB02TP1eHBUW%n{OgHcdF%vM#x z429h(GVDh^*tL*&hywEbnx-wKPGU*AChzA^^S%sLWZ?);w2IM5vH^n+p!5ZM(M0N< ztCLAb(D+Wet&yaimevc9F8{&-zpP$k|Jfrsoqf^30@%3XNJk3}lu3Vu`{G8SY=;v$ z_y$E0LO=uoR>UPML#&NwEaN-Iw;ji_S)ibzL}ZP%3|&!3jALraQvO>e06uL8`HSd` z!+!x`pTXg1cI>f+?&@t-2!fd@jNn^!DY5@|;;$I8DQGl8@jL+}D|rNB$(2UrL+8>MHwAa=jD8N0EWjGhlz!K&7P%VJ#jVbqv41IW?6T)RL%eFvw zs(UtRGB*Cbc?6Em5mX7e43a{*kMG!3s8B|zgUK^y@Q#vE?KoP^K+(Ky-I{-bfS z{Lf?YhSmNb+u%0@5GFZhqUSsiBj_f97den_Cr=BHIgKW1r4%iNha0r_`|N$WhN@+< z8Jjsg7gmygz;s~j{VaR!j*e+$)^WKQI(w!tUAk1GaE2IJfswr;-4DbY{G@V{P=85z zg$bpRT`P)uot{Ug{afY43A37xu$0g zYg8On(ik%;=)7x3Mc4+aS+D`eDKi-7M1X=X zlzY(>B_abS2W>Xz-DX^g|}`fP!V|YX^j5e`~Y!IHKd~tH_lz&jR-7b>w4- z>bf11L*bZ?w(6u+wI$@k+#x~mb(t*RMI$KPu%>b+d zuc5fW0VE@(!eFIBNUvY4O67pMcwN#Iau00hj)_NfS}eihBPb>Hd~#v=m9jKOj`c`H zhLC9_rix79nZ_fa{cTCe@OZ$neo+NE)%2}nsv0;f+4ST%GhEvBT$AT|v z?C^?c!shhFra&$wFA)RNgHgtEil)uWR6Hrj@gTPZl9Y5!Xw)iqzl{5zC zY{M0=7sqLGljCz)*|vhp%!SvwevyI2sY4Uz?>%En^2^t#>TZxsrKgZ)=Z|^S%GTJ9 z&qzu|2c9BTy>jyb@R{FaYRMI?*E7;^!7IP<>q>o!G&w@RfE|`#E{B#t_6zSe!n^*F zelS$~EeME{`%U?WdV*JD;l7^Mv|AWr7YbQRK0i{r*6Q2J%Vyt0k0;UW)*0NVNt(a* zcBT#t;Yp1_@TX5(#vpRYXvOD;if61jKBst{9eL;=3c3}jFhY3Dc$1F*)Uf5nDEZ?% zhPi9x&>}%J=w1mNVUx>RVKa_1?gM|_d~?TBJov^t!5#4ecaC*^f8XW>K_smZc-Of- zxrz$=YC6Ab-cI@8XfeNg1GslU^pNS61^UvF9G_QHq%a=~IL4!f7pY&UNySv?VU=jq zDGDD+bWzIAKZmwQk&8ChVKbR>q!bFNDotK{4Zjy&Wb**K&2IUA4bEQUeO-eXB?aG? zHS>Lmr|tOK!*gQqo48NpN@fM#n-fk`Q@(^*b99srO^?5w%x9NPa~j1aBrhDVw$9c( zxA2an9?rhReY&Ui2yIU^;KmI&ml|p$y_bwtm4ZA<%q7$lPI-NIKf-vpo(~6MTCUn5 zsx;Wwjt@|_!0s~qAq;LoZZ)G2TD02OKDG%;eNcv)gVfYbxIxgsS@2M`cc-vZ(cgHC9CVk zUGvVfn$^4Z2ixOPeP#3wycKu*=|wYBJ{<0C+O(Ld54KxJhwhl+?_Tb#1<#Uu$7i%MmfM>|o&?K;tR%rb+Hj0NUIan@3`*^2i?Z z?NRH+jo|rNnhA+OR|5nE;^+E~6G#pV*xzPi5%_&YO&?Z;r)|wrC~a5iO7@T#QTJ|t z&`Bak9QdLWelDCbPszEIZF)k(QM&*|Gp-@v6ulW+m*iHPO0$ZJ^6gWw+;HgFVppZn z6)aD{cJ@1kety!@(MCwi+xV3m zHLU=OFeo*!3rK-1=PYqLzG_wydb;S{-&?2Gi8t5ib3z5JeyJk-u6_dJ31_u2!=4hL z7EjZ!;}Y>Sh?FIW=#=?&TFgkMGNKmaCF>zV2CVs%oxuia7VYCC-QXzLq*2*uRHM8; zxBZb}7?t02ze%mwrvWYHQN1fXDnVpcH*Da#{K>&`fs9T5O`pO&^f8_Yb4y^pjCkeM zgi+Eo`aB`5fo&Kg)x`P8xkDpU<)Racu@FRROwVF#y>$lYZmOhS=h{sc44rlFhBR3j z*V^6x38hqEs<0G#?u zD2jmy@g*esTZBT=k;7?WHGdyyB0Zeen1O2Ru|vC9kEP^{wWBiC3N~w6O&M?P9^F+x z24ZVlDClvaFUE@3$EPkp2B^afWK{9&rZbRoNGh8H2#lF`r-A@$)v7t-)9ZxzvL*sK zO1C^XTZFEbCLzN~HKomRT)8lma}qf2SF+6=|iUa=z6;JH1`IE%WB>C;S*MAoxQ`o7;OF;Bkge^)y79lyH z0Gh#wmRqfrMWRMUE~G1U&+hgGO%tfm#A!SXvL7Ywmc1z2lP~)a^2d^<9P$l@1(2ec zSyd)IpZpkI)eLRD{2Nj~52meub;K9^0(PPB1b~MTnQNF1gzd!6+g?J=0S^>%JSe~w z3Uq3YC+Gq6NvcugTKC+;&Rj{eqY4YR}2 z{4?3_M=n)iLKIfri;A6Cf>O4jnSDfwA?L!=u~H1}8?;klk&$a$*$^x>dS`b-24&K> z>@N_D(T9lK(y8BJLqarH4u_-Sz_A(D)t}Ly4u914s_P&aTWpMcMi!`y zX+vf6(K9!@($SkvayBzkxP?U=zE&oh`!GauMfySgyP81o^xi6_s`I zUW!xYxe7+UL;_*3IvG*ujdq(*A+-!RZU(VkIo8_YRB}4c>wULVcqubd2W_-jmiIY~ zba<#Evp=G zG62SpZqleGK%bxt<_xjrP&UG0G@67bk~AlAS@~<9dU2n&aUTuxcK=v!O26_o0{;t1 z*|f^S>=h00AM_X*5RkjQM`tx$fn>HrVbUNb*Mk{+>5Dudg&e+9dTk&^qj-B5uofPT z)%CT`b>8Hm@BL2CwkMZFN^^a)yfI1`GQ7O&gbH;WY}(atA5KmL3b-zC`efKLEO%BD z=Rj1L;=Rh|aD^!fvGLBsp}Knogim$F-;w5JHEyG<TqZL5PCtuvXIzR5eR!D<+&kIEP}4Qp z8=9PT$Np+Z?|QV;{4*1rj}r%I-B*rIJB$zJ^#$T27VN8YUTf2nk;1^^V#v%a1RXs=7`I6k3#2G8a(RPyNj^h;uzVfs~PCs^e9DgUd;4v&bH~NjWw^X zvfK4(`>eiXtLO#n8WsTgvYgSH5(MocUOtcwKN5j?vh>@g0HP4;AEnBpP4n>TxN!2D z%k=Vnay4zmW79~6^Fa^j`y9O2yVaYn$H(v_VNRxW2Am&h59>DYU5ok)xYK|P_8)T# z$A1||ajQlACI)>L$eE zPRB$1U3d9d?QG;G-IS%ctXCM*Hs7B2lVfaL?PDt0fTIf&-{L|sFK0#V z?#G)NzOAq8<4ievwi_VbWB;BF^XdmRwwp`;)*8EyOX&bwO+v|}7~r+k3LY5u-OU#d z^kaW^92nV*4py|%{8#%XVBpBjOYJ!KZPu@?!&rCcZpp+x&&kWszbXo{b0|DGk@>aw z>?DirwFfldE#c7?ZAYr3R8j`5hxvGLQH_?tBD;kB;6EIQp(Ura6DT&Ha`?Ei*3AP5 z9>%LtqiEuV6^3%UO)7^`tW$;v3^H8>wUL`6WtZAWA3K?sG!IM&hp6tQlq-sOaMcy*@+v8<&9^k9o#CTMtLDvLaz zs02oO5bHSPe6hlyqZbK$uiCy_2VBw0N94cAtJFgIP|h7jpSpR+1ZfN*&{14UfH-i< z1;ZpiVA^&+LZCh`MI~uQc?Viwc+==dJJZiHf!!?Bl=nNITo?O`L|RKMpLff2Fopw7 zE=YAO9pbDhZbP$ONKY_{TZe6oFx6wX2wmi{fO7LJFo>r0U&;_UHMEQi1q^<~#2xfC zE3~x@-w<N0&B|^Z_dZvZ9kd^_UEkgK|Lo{U)VKi56YglDaS)f+V4lm% zCGXjS)x({Q) zQ!n*oRz||BW65E7v(QV;BMNMc`bgw_@HnVW?t|XX7aR?f!I0@c>uJ}ag4z!4XSj!k z0qV8GZdZ^~DLM+g}n6A=KvARar~*xvmND1-%M5n&>W|LvfWo;Mjq4AaNRrOhQ{k@e~LgQSpOSkB~e7{7CI z4hkx60)k2)hXyC8Ofp;IVKDl|G^}l7zFh?8pG&a=H<1HvS%qw+k6jo4njoOfcu(Gp zfq|Km1A{Ui1LJT8_7@4yi%KN7I(7p<8+qc`R-dm&GrAq~6nB#1u>sB?-$Do4jP_eQ z7^VK1@{E1n*6-i-wzf>ysMptJ$zpaT*^_|g(>5hsr;#Q^j~wD965B=vM()6%lpkbc zUI!R%C_w?l#*;Z+N&;Y!Q(I0ZZOQ<2DRPykrA&yX!91f4OCh*3%y)@4O?7_Nt+ znMG&xo0Pv{Wf(nbpv*~mN;{&OC~)>bf%fZEu&=8daGYeZQkT=lD2;zbZ>tGMgd1W> zpDE25RD`fJqTQNb&Em3f$V17_g@RP`ob(IEL@;EJI1awxgLVae+&3>=Tdir|5d&uS zr*XEol+&q-;Gksfa%*jy-FMt|#VA!jF$a^=8YuIg`s{IWhv!FvPfMj*pIZNyJuXUU zjY;~h$QItDSFL-0qykKcIXMOihPD8zC+N`?K(U&F`wZm~iSSolBkSBxv?Ed<#tW}l zcfPSni(Gh7+piJYJeb6md#om6;V(%mqQOPyE_`6dh5%hW58#9e#p7&}#@Og!%%#*^Dw z9Ahz%h*3s90*lMMiV92uhfPtdfmL@FtP8)J;DOsHT)g{vj5g8pfNgyTJTLCG69Gf^ zOX252eF(Xyu$(Vy$hBbaC>>y+L)z%!B=~dV6x!*gWMCgvM$iJ zJWI32sW*Au>teq!*W4jpK*!sLL?Mv$kJf(s-ip4G5^5<)S?uWIt=j;*nlNFk)S?A3yo%S%xQJ%xMOF5rKYaX3+pd9x$M* zmX;krh9jr-QN5ZfYeG}$nKh-uH|2|$_$p6vUBLY=unMhEf=XQxc=BC=x{2VHXt&?( z0SaS+(d@iXcpFP~Bv_fhK%cuzy;S4@UW(=;0phJ8CkGpBYMiTzC24zRJg?Uc_Gg`<(3KX2BZPEqPdAJ4s23(emIa$$TY_@YzPCOj5IlCALvMal8x?dpROQxE2)NY4)I~oUa`XsK+GO z-Z4}xukVDNsPDn<3`61zHDD3$#3=)ggB5~TVj`&HROCV{X;=_zw|X*#LrWs!nP}T) z4$jbf@*BWwk9&L3`%cs2Uu_`^1Zacu%BNxaq~|BVXdIraSJ+gJMh{Rcxp$}*z zUpp3d=!JG*>f|G-4=i*@2h+@KuJ)XjHZq2p*j5RVm!RUdfu|%rMoLC($SP;$mRID~ zCWNhvA9B+6cd<68i3fschi}1|vsnIvP|!}GymrgaKci(ZnZBw-Ck(`TQJc1Q`iwkK z)Vg0v2>fy+j$VBbzEz+Upn)i_iiL0_UI36sPb&y?jwx;W?GsP@1$9`kgW@9wyt2JW zDTV8|Ugya~{J?mo*n;7s&7rC>jUVle*6)<45TzzZs$Fsjh@Sq*fjculC1pttN_KC&9;Q8!kwq4tP& z#XW+Ds;rG<>A6=sMF)F2U22eB?#vc&#!mfnb}t_*F3fpD*1tdX^8|@dr7u_Kde$zh z^5!jT@Z`aDSqqL1T<@zCFt%rUH|Tz*X&w61I6zg%l!c#|v;^>C4cS3crh=E`sIK(G zV>G{>M8~tN+^9E4yId4JUE!mS6B#ktE8M+yvpOS;#gF~)bZ_bd^{GpY9pxu`751gs zLbF6MGbL(&w}s>EFCIDT#p31twEkvCsobmT0iOM9%4!L@l}R{WhoE=x-k53k9iWT# z@;Ba)4>YqNixK-m>%DitI?hxg_kI&j*w=IhW#?rZxZ#81g+wK%`S2dC^FS>}*{TXT@oI7|j;%Gs_N@Bj0>Znrc~-qnf$K z=Ci3#Mst*(H;(VB0ACOXVEHPwT6-`hQj zJ_{$}r`&9OHt*eMB;=f}Y{;SF^gRO5LbF^*Fq zRFeuPRIv7k?7rRaC%wn)>`DJMh5rYanw|6imMjwdf2%{LRWxlg8U9zi7ym^?3uRk9 zBuLRcleza=Q|U2nArfqf@L>X0V#(+8BdBAfwt1$~H6fta%zKaHV?CesjLq%d1eCxT z@$QBZ+7oZxi}vK}3P5{Kvv~FO@}YCryMyQHK>Wdi0|7|>YWZG4zk(%Ds22e5P*Si$ zNxwbM2ym$$3;n%I=IDL%A>r*sA#tvGjxk@#j>G7$&OBSIzLliB;t}jO!PNs5?}!xe zLvB)zqrca5C2l`yjoF}gy68Nz?S9m!k^?hDLq-<~2`eGhJ&4>}ELW9HwNwlbi#7uk zb~{0koBBhr4= zQ5nFWx+-k>BrSmRtSSJ}+bhDyClLNI*=uj(-a%zWWPb+sYax+`B)C7&Hyy=kFwGmy zq?0X8w_Fcnm)P)}SqymiNaH4(l;yAU*(uL)apY!G7^ze;?K|l2c1aiaeL{sG$u}ey~rg>oM_mgFIA>p{!d0mYyx_vF7a9_CDgMabagH5fVlylzC zw7~U-r+%FN#E=UppnS!bmOauL)K*y?)}-wMt+(;(-<@>R!uWUU$np}mnL~4BYf zht_$B(snVYuzMEEC3;8Lq>?Qaha7o+;z6KUuM;7J2;gt1R@J({dOW#eAMO`A`Hx!r zFRNr`mjAgD>l*9-+;}^EhYRpEa2=>4iONOesN?e3=8D8{hd?zre)2Ytx2aYnu*EMM zH~DrkXXI*+cM6^HKtJ|n21gx22Hg{NyM121icuqpZF35}PsV}N}>7;+O?C#IiZw-jhk$gE;*TF2A9vMBGOAJ znyjr7O$DBc($HL zXTdh{ybJ#*}G^ZWsDJ5 ze$#a@Dq@XA8Z1-Cf1$*tC5PkU}HOFB^zqo4)Ic$W7q#(V`MhRGf zat1hkg#Io=19hB9u^yds(sK!`r^v|D{c4-8OmLR*y;>?CE-Y;`t8gzd!kPii4vCw3 zOSZNc7$~exDlcFk{bzM%Pap9|mav1%3FjS>6-w?2pPNLJ!~jn+rp&y41|j0D-&h7<=Z;Rzm%)ub&Nq779U63aa-iUn zCJO3zY3nwf{T9vi%d&>HvNVB)vdTPY=&eQaxDq_Xg9BYMV{yfiydjbRwNVAYJ_23fR3r03vnPl24C;2f!{@em z>1^TLx!F>4gy|A)yF!HZJs2A3_@aj ziwW*0I;Aa6gsD^CE-`OUBtihFT9mBr3`)_J(FeE+6~#fp`|SH&A%>m6y9Zu~3qs^* z8PB3#g3{Xw9mH%8dt^WazWu!s$f}3r6X=SoMdn1A5X}=qdkF!`qiKc74Tc(W%MbA* z4Q`uop)rK-kC7^KJRl(903*GP4^1z{mN7>wGqHz)lPyjl>wee|7X$=v&ynhUWMBn_ z$NMCTW0q2mZA9)BVR`JsQZ0>=8W0*ziN8O@!1Q$x`IDy)Pm?T_`XLN7MV@Zsv`BOa z0HQQdF>W9GF{pzioicZXpbw;}rci2AA^Xww$2cFa&IVTl-*P?KZ|! zGepmFd3F+iU222yiQ8TjX**zo_eM+rBd{Ic4PEAUZuBazU1SdxfDK-X6JAL}Cdwp2 zWYNXBNl9S3o7caB9$vZK|7ws^CuKr73SlioQo=P%#c!3<=i*IkeyqDUMle;8>l9qp`6m(R;0bCc7&MAe*% zSauCcN>`GO^~>x|SG0;I#+L`E1+ZpEqv9)da4_f6xW)5#<86+2u<;Hi@RmY61nH-a zZZ+ad8aZ(x5q=}BQ>^n`3gA3>%7h}`0v6-ftZCGYf2TVc$+Wmb9Mc{gjjPNA0W?r# zYTiVDJ!vBj;j)0S%^Z6%V(FL}`U%56W$ zOHetUM;~&*{;T_-+NnMYX>77v6dseReREqHmqmv)X&bGCP2IkW%3X@T$0pz7YnIcf zJ`(K!5S>|pD7#h!52Qp05V1!PV8bw~{(3rju@g6$v zMth^772dMO0EWUGAv}&+r{U)iGF)!v z%9cw#ZPr#0#BvLqjHQn9LFK)2<+}~g?=y8-B<+-WuY9c++RU8*m0>3ioW5`YkwIE^m%(`I*;C~S%6NGu)_J?Mu zrhCrG&}#yagnihpX>-64L$QD(E z8z~goHak^8juBUCw(`aZSGdN);5tYASp2}kv&%%z8pVdAfH{*YQ``aPBQO9AtsqSy zwzqSmu)Xi--Zxq6fN!D=b!~czzx@Fo4D*Wkko=1_;J%Lf+44x^d!Hd9*6B+!xiU=9 zP^8`^r=yu|o2-8Vo0>!T4lBc8x`%Q+XO4!=u}to}Q#mbYx?{V-v@tRAwEN+Boef=7 ztM^y(xihRAZ$hm#!q3d^z&4~Wr-6kigkIhdj-A3ml(e=rcaR-0ey2o%jrP__vQW>@ ziKwDRuntH+t2{2JBl|OW_+#+K)kihJ>tm^41x!9bD(-;DV*}{7{l!zFi`9lz9?GT= z1pU(JZ7$&R>J0srsoA(U(s8@K7@ZsG`?Wjc&q1Mep`>jp>jL`N#qJ$Be}{|Q{)i4o z6x^>5mXx=40R%HK2(~55j0cJpZhxSFL)NJ*=8bl#BTrH;B=Q@nvO>SlKQvPj! z(#AQ`%kWVa;XM~Qm+IF1HMymt7grIL*9`-(z1Wk^<6+zJ9$(`6T1U;@10kBK`POnzW zQei~)I!*ift+_DmtRysz06_I_D5b#m2Z zHzf*YxD0R(nbXJ}1|-X`{9Ey5O|h#Jktfs*6SBuigwpzlJjh zAIZj}u+3(@ew&2^zkYU=j6hcKB>~}#fkOY({qFq1?KuQJ6AfI`W2+t{9@+z?qi@n zM>wC(v#AXpv3cO{@nER1MbS_k$Io)9qIw2T@rvT-g)sRniTXG=XC&D z@|=vCYT`&fXMRCr!~jd`PMUha(rsh|nKY324$AUKg}q{DfRv*pgVzh>eTLCv`QI;g z&0(c>NkSs3G_kOG%BN65kDCl|L-E#pI7`ch{uMboxbHJf>ktx7ct2zGW=Lo&^N(il z))Btz_iU{rj&iMx;H0R^ek@G_2T5z4fzOO?&OCQSnfV0}>eQDRRbd~2Nd-^&XApsZ z7OU!M(e1B=B(UX88aCs`mSJ||wp`ZH%RNq;u7fIWGkVN*`qUvdfh<;&rqZ@(lFieI z?U8zc;I{4%_h3ES!Fp6njH-l+*EXL&usZal0ROek{m12mk)8Q}%)9!3NwsZa{$t_Q zXWwR*l7UzGyiF7^PjOfNmh&wL;SMAg*1-Qbwcy5*EmzX>g7iq@u%;pSrhnj`FCUga zLyZzP%#VZ04s5!^yQHlV_Ggz$GY? zLk-)CR}>G-is+pF`oTTmtNQNdrKjufah77 zRFvB-S)GX({y5VvrhwC;0s|QwS!otTm!49K4?|_|G%Tnb z>uMUZBm${O+`ajjed_RRF&su@#+}|xp!RZJX*Fg#6cf^oL+@U<$A190FSOhHjj!f} zxFmICLx5H0YQVSAIxD-hP{`yrlN)aBL^x7lv`6e}r#ZydyATq=tQ3K_fVj4CT}DhR za4gv!NVGD%kMXX9mLHAfbjnzSnsW_Zic!h=BdcFlfFe^J>a@NA@)PReWvTdCgnP^s5c@)Y5G?Z@g%u{ULgwrx<#CHt6f^Rgv{=Nz2&KO?gwvFvtSo7u>=}fYO*m)^o1~vBa82?D zkdjRrntT>w_M_!8=YbA?J;6UGIA2~Z!`J?zKG+>%|79|3_fn;wQ-gA9_AqJ`?xcIQ z#9xw4dMPiK+q`48U<7Z|iX%_Aa`L;$>E7vpLGSo)&6;YCEj{8Zmx&p`>C0ZLw z`xN|YZ}8em7tFIT*d{YS<*-z}^epTVZ(VpnDQ4Izsgct=b zdk1kfcUh@KrW>H$Y59E z=0p%6_KwVT#5!Fpow!OG*BxO5ZNK{$yYnv$6z~l^_9##Lo=w!VPC=2Vgd6XX@$UX* z-s4R9f`bQB0*XkHn0p$WMTt~Rz@=vSH^ZzGnns(y zmj11Ptp|;L-MR=*Myfcqx(AEE*;6duof@+MVvi^J2M)EwMcRC>N_Fz#z1!g=rm8AE z7!1HMToEWF?}rsGk>|-Ae@wE>V_)17bg(GUhNR(8o1(j!C1II_$g^hUKj?N8hzQ)}V9c@~jx)!H zwaCsVQ@+_y&5J^3DX!OF5E%E18J~62^#wud$D|t4Cljcb=3;t! z?;3B=c{hgjs5z#EerJ(VKL_rZdZxnP8%Fgra`UWJSbN(0w~2$<6#Us$rqzH2fY9@n z?BJV^9np`*h3-d|LZ(o_CJWy0r{DKJ73}7^9{d%nO_xl3VB!D*RM%Up=L1}Y-J3J7sig4%)4qH&rDg5R-0q^w8SJ)yb*CBZyPd5i>R-f{F*$lF`3zOB zYOm8~;5)Z}30c932Cr%Maj53+O@0iix5woIKDyE3nfd%!GlB`gN%He7v8?Dz3yYRo zQF22r-bZhZ`R&dAlncalNQd@ZOl*powzd}D;r|@S?_((AVTN<{%9y-*k%VjT3QtYt zaZtqTMM))ND|{(jHJM0aC|(?p^HzobT^lr1DB{QWRZ1Jg^C)j|lt!&yuX-Ad4Jqxs z*UMAw37z;PpA|+`%9BO!MKl2{$w-oy7F43I_bGSAygrwBhsUE%FS!t9W^|80%-S5` zvW>fCpU3&w_RTNgh2Gx_z?F-cNyp2|c!r3(U3I9;EknOjvqNrT<1yCOMUutf^R5Y| z1rr6lmzM0Tv_P1JfN!hp=h4@Nd_$}iZWbkUkv%-h%#L`G4Y-t42ufMuquR02G1Ss1 zR_CZx1T2KXieWc zrmGCuH!@dWKGu`oh~(|+edz!_;SB68VJQpgLrHK!j%#c(ETtsnjBwXM3plQ`P{uST zL1II*>)Mt#ej$FwZvo$sWD z`TDaiSd#e%*Ut5|!a}Qmy^ch7llpCe(QgH`>Qrv-*W-@zA^eMofDkHxAM*1LgwED1 z{SVLzIw9GAmEnJlri|=t|5IvRwyLD#0muI;L%BwDWPY`WP9!=_ZpCKLt^Jhg{(dl! zkr_SitJz%}=SaOe=FE0I@$Z|Tj(8v4o#|e2-=r`SrG2w@JaN@<5^)iI1ju91LSr@$ z2e!l0W8FvFdr(~>qVs4IBpDP(+SYfs6UtTb*vyx>R6|s5>1fdfb1EWMP3=XC?UYIp z)ne3fT0t2kkuKi7+etUD-uHNp3Rdq;gF4ZoRgG-4XJ^(pK{Ef?+mluE`1BDRt9A;l zaR_=F{udc$dpLT<>ig{`1TG800;O42Tr<9Px`+lf<3Wb|k`wKTaV!VePhwwP!^ ze7mUjYtNtT+BFeufegT?9J+HmuJzvw=mzkYm-QAE&@RW}LJrf^*@)z#{^##Ck^t2( z1%2(MO49C`%GZ+p6}O0L{BjGCIjMzXZxNUpep_gU~HJHTDI2t8kQB zk8ORVv((7*U9%I$Q+{h9+8g|d%UvNvd`=VN&otp(de6@5*dsCRTRIiy`bETOEKKp^ zqYE`;iT+$-tLXXI>in;vC8J^x%ONuZd(cdlu4eqY0mq>sp zuki~Y-v4F4^Qk{Hdx>q^m7baAmm}P;D`L>-7V}wKSbz`4-}+i^NKFKtl>oTQ0qpY4 zL2kl4Ol^$DoXaI-nEg0;V<#e??)szJMy>FcK01p3))z-Nqcba=g{nhbIcN#3x=eQL z3Kn;+tar25###&Xwjvx{O8$pde0;aeNaB)dmKo<%tQ5MYDHbx%M;pI7_zCq!qwGr8 zn;~Q$>(Vp+(exdvrwP{4IY%te7S0Pz{$Vg@(_HWO&K3!Ti|3ao<0DrgNAwnN*0my) zi*JDykGJL=#S{3^bXVPO=n&F)8g&FNDqf1@%X}c|;g0Jvew#vMV|(>@+jrg|wdy|_ z9pis+h#46fIsT`OZdz5^@n3*>_ou2^0`zeN!@YPzjuzJma_2kSKq?E;!bxC5nv z{NrWk9uNwlKzx?Ci3cL3Ui;_EwWi(sdRQbyHN%DA1DXx#GH0;LKObPR@c`{DoObN9#%?z%0@!`GvFVNk;8u&=!W8*jVj>R!|h3a<9G? z6ItxZEa84_VfuYJv`|RLfFMPp5QFN-mU&NAbOMU#jlZiURL_s{cc2QZ)e$PU9$jX3 z2~p4Bs4DXH7Zn70LHmzjIY3MINpm#Ngf4*l?blOu%ay+Ljo|z9<>BUEP!M6LL%I5f1V=hxW1B>eZc|2jY5Z zE=P?y{bTs=KR zh(@SNkT7t+>MOsc)qup-f)ZF}?JjG5w*7dj>gBA)#TF6`3=}J8MO{DK`_(0s*g)8c zT<+V6A`HHG5cpmXK3T;<^%cAY<<~SL60(oy#3FX;1C73tP{jdm$6TPI#Ep7-KgVg) zq+2l#jc4cX$J%FkpGuNUFMM#1bl$=$`3NGKtwUNYuG9f5f1T!(k2x`NzGO(^vX%Q# zm+tGY)ffX3r0ymoFdeVF+;D&aB-z;ctuSMt<~mCh;cwr$(CZQHhO?5^A0H{wRTC!$Z!4{Oa|keMUr$Y*p>Jor3K z7e8??(!YRGgnlCunIpvQwZ5QFgG#P#VpmzB({Uz{iz8nITF@wnV0o`pqVBB6WBl8L z`Bi?pEXy4i;-@P&HaytO5q~K&kWNU5MZ^@h?OYNwibNW1=1URT=w5|)*5F3##L%A$ zGGLW67S=5)%cQSjba#F?AdD$K##~saHd1Rw3?Fu}FRLnw@XQpd)0a^3fa`-(9q`Lk z`3u+hJ#0;|Pf){tORRE7B<^F8vhW?Y4)-ml z1eETBW9D6L)L4yj{jOcQDa>8e?AwPEA-&swmcoEq9QQ+CVZCyhczy7eaGtD``JhRU z)6><|&m8`8?V*u)olxk{^1G1%>h-m7YNj2`*! zlxP}$^=py)+n`8&>Ys$+qXI|iFEMqx7I~AVS)xC@rJAW0vRd4{ytKwaeRwR(IwX}5 zrErm{Lxx$BoEd&f6UGJb?qtY+Miwz0-*gHjWA2_pc#ou*L=|f5;=}AnF~&`jhOloN zpimBlb^b(=v*eOsoCSA2#}?v6;k0U`ng;g7~F$01ps{_f{#H6!*-F9*SEwG z6&?dTa$5Ssgf9vS`77W~#FyFM*~>1mGi-uC#r!Bi0MZI?=Ut1Wp+M@C)h=OIt(YzZ zU;*fG9MG4A95q2U3D0p?7-}Xqy+ROEwj)-8Nm?Q7*b7w$X(BcGX%1-eW?t<9$XPeI z=~|`XSYk4zgQ)yrE2XC=CJ{0i4dHxloBIafg8@d`4o%Ix>XnFPsVr z;KFH1F4_R(3|0a26@}OVC?V0u;Q(d*M0HzUzr3nJs8y?0) zbfH(ipAqC$wdSn-0f19n*e^rGXz&E~b9!c=n!^D^q0wY7pG6IpyEc<#HC?vZ$N_Pe zL_7zH@du9CFQXWmY)zRt_~(CoGw9)l8l9dfCVc z;PA2$eeT=KOESXic4x%u{r>wW{hqyX{Vyw4uZFMsa_>K;>~AJ4Uv52Zl}I-@!pq%Q zUyOeoKR4N<@UK2BKjj_T>2Ce?!H0h4X3SSGeCk6G0c#Bc7ub&n!I-^_hqtG8r>0*E zUl#4UUoQ?F4XKZtnU|4~&sQIVUoSv69c^zmeBB>+&o86&%Z4qK-=CM$j}M*=a|`_R zbhc=Zs2{ssy%}`$=*yN|xw2@v&&#)N4R4y>SylYiHT=8UYK_~M|Gr{;CoP+MAn#{S zDr?2wYG>Rnc8aUeevC(c^Huqy>Zbj`zijsx);|_YUq?k4%~Mzh^g9MQ+>l~~(DJ<~ zzAX8)mTkR2l_E2xYMpUBUV#yB7jJ<5J6vxW0hCkcm)@QYecnq32-5E_Q){Q*Y+O2- zK6Tj+e>@+YSh0LV@haCXAwQ}rFVE;sFNaNwm{x!zrUtSosbmQ5fr4ptLE zF9LMkiPeNH!gZ6oRZ_ilUV<}XK#4d!%!F}${V<3Cm&|~J8~ZlEeSe*(u3%b!oI`Vu zh_jGl_fIk8u-YQ-*kQr&A!*;jE@5+(E(`vA+%W+0YGtdtG8F95gu0_Kbny7iBSYc@ zRW}~Z;P<0Pre9WV%@^38%k4jas*=488DU-HtAtvAFVz{IZW@q!4?<}O;;JgiA*d3D zMK{G(2<(7Ko&pqd7%SK`7F4shNX~O|9{Na}XOtUB;D+4@K~+*~{qmc#&TvH3n4`dC zo!450q}0s6e}951BIzL5X9b0+6`Ir&0}|H_&m|2ZD_J6jOP;poSt@^AST$sYFzDJ^ zWRQhhL|0j~D#8^}lFbfc1~8Lc*Lw%YDGyB2YCbBnXdfMa5=5Wd5~I9ULBny)*M4$!mw1UEAd@1xx6q*sP}k8 zk*I3YX9DUyC6a*O4B_PtxnFu!;VIv+Z`Mr7Mqz@u8o6=U1z#9t@(kqZ2AYZ^4|FMv=($hWq*DZM`y3^jBDz)XfaV8-#$DLaY zG#BXX@sxef7mE(<;LrG^HYXBR(N^iVvAi7#_%U0`?$4J4#ta|Nn%~4vu96xlCzwWc;KSZTXA@)#depK8g^w*ATm2wSB~6+sca<> z+-=#rA_MYw9`z5D&|)p$D>&)daopJ_sY5|^Mo8YkHUMmH+s2QmQW|>43vEs-3FaI+i zMYI6YdmXlsnBq2V^;5Y{C3}$Jo1l><(`wlgWtdV2C;vi=%K({ z`iO$>;lBx)wf1@^ao1o4FdhD9MopZkiDA|9X@iC8-Ktqi^*i1k3mIQkB#r@z@o_eA z(TRx5q>uP#a}%FMpJMa=<~5?olH2$A6F2O8#AtdoJg$oK0;h?PB%P`;W$eD6q8U5H zK6u!7>&Yz|Tbos-cL#yu-~2;2iwYys_IdL|8?niMYkep3)UA8}oex*7Th-D|!a zoA>}wzD{Fv5V|_`Z^89V3t0rPfRPmvNs3BEDmjPO-j@wu# zY>?vJKk?6~j~=|s&yTq0N;e5U;e5B?BR;6YJ1RcRFZ+V{N-v^z$5*at5&&dxbHd%D zD22r?j1Q+y%rCB1$``PL)qdP1cCCRdq#rdi3Fo7K zUPXL~ioM&fhf>Kqqyj;Bq3^+&5q0?*)Z;JVz=hFz+E@F)Ar(+A$3UhLNJ1R;IDK2% z_iTyF^o>?yP308(Q#mkY3Lem58zSTIhbQJ=TXr75IUsN|0+acjl;WZ!kLtv3yhCe1 zDwh#e5`^%u1qI(g=QxsiIL&DV0J#P7zn5e@C@VBKi+)AVV^*@2Zq047v$$3NB3r4; z&o3Ek8iRX7)1aD@_D{&wHnD z%I9jf1gqD-y_1ymv7HT6>+MwNqqx<@$Pp=5j9=%e+iHf6nST#KChtb z{*49RXeq?oDnL1UPa9ynTC{2(oSH4Bv6U5pUV0X+yH?%^z!04ZkN+w01yrGStyZ`^ z^cA#D(`PG2ucbjXRhX8?ctvo<=ezh8clj7lg4%J`YB~?Ge2KiEvD#J+-uzg+ zT(cFs{eXT4bqd>t*ja6S%~Dy-$p*FabF*q+8YGoA_4UU+E!uDqrJK3!$K&1o16yFq zucgbJO~Xp2K6&AyRj1T?KJ5|>-1f}d_WcboUDty{Bu};TS7+-BI?e)T|3B0b=KmB@ z#qeuQ|G%IAZ;jEcrW0GphT@&87ccwCKn+UI<}a|Ud?CdQzs%QM-l514(TB zS+aqzhrJ1jFec;H3g5|*;>|z9`-(UFxxC#e4lhT907{Wo<%%4}gOD$|M-TAuHBOao zeRFUA0!`!}O})f(gyT1D+8nfQDrqH%AQS><{loxjm%2=m3hh3^I9AH2^%XZq2LA$u6}=9S=jV(>J)&><@gOQ`N<~9*H9ba zmK~JYVuzf4+VLpNewp)GI(3^d2N{d37!lCocP~|h9r>!NG(!{<(3vuKybfJd4)X4Y zhQf^_D$7Cq_(w1o8wLwcei}2GjQ~Kw0#R8cI#~ zGVkjjG(8@4nlJRX12KXpG@YKI!t0{FwYmM4_+sMHn`);j+DQKB7m3bWHgnU(6xG}g z)A4faR0&)=9P6k3QbeAoBLSV#&-?rad;pk8{Gi4wBboYE4e=IS~W=?GcR zzloaLQUHP`soF;C)H;@V4_e|p2y`cCl)7r6xTplCrA#iyT`rsw8tec$MTPC6uoSRV zcb7T^Y8_n{3Hbo##4_6n>~}zp2^GlDDrbMq5ONlBVzv>&TEO%w>>C%o5rXNRxt{#7 zgV?*2;3BxlQKM^dFO72fGv{R^x+O;Cx;0vMpv$;5t3Z!s;Jm2D+!MURX6&NTn5Vh@ zv489&Paz8grlwLPW&d&f-nx1Ic_ItcZ&|MyS@&e7He8u{Z)Q3W;LcC^-tmy_rnjfc zWxv3g2FwCypX|B=5PGbsEyxVP6}qfk3s@a$(MC(vj9noa-jeIj!o4B}HcMYdma71^ z4Ougnuj+KDWsiw4V3RKDpwF!5q7cFFT;=O|*odF=ruraV&DiP*4gO9mXGTDH9^Lle()U?N}qu zjfWM<01$Z=JWtmTjb^XlKs~{qE@G&PSlRME!zVZM;VJYlR;<9CffnLxPm{!(A=ei; z{^_Tau2ucnWcjg0SPl`04(d}beu)d+o7Bvh^%y_3_C#ilYad)-hC03JFK1{z9~#@^ z<&A;MEB#3i9Ls+wN-Y0rxM5}duUQb;>brKo!;R0a-o7bq0RY>t;~N+FaZt5MAkq-N z(m!7UI4b2VEZj%1=)lzX`(`XrhRSjCnv^JZwDZu-4gdVB$Ls#&n<&eA%@nnotaFeg z3e6f>R&_E>bTv_js~r-_Bkn_G;PJ~6P2Az`a>{47;K=pWfhl)tAkO9>?a8TTY1M;= z9oqom;}c1{Q^DpDVlucRP1AwAoq>Dgs(@45{gF?bi}3euGYIEn!cFylV>ytxU&9Qs zEZDh4hwL{^pbN^Gtaczz@|q^KxDJfRUbW5%PgvWOUajgVxNlKg=_*y{s^@e%q8dPX zBlS)da=D%L=P=LK*aKAuyu*@}R>f7+A&FmOfA{R{l1KYOx|2$}7__vmG7vSVNnL6G z#?Hlc9HykvzFoi4eZTNoyx0UNo(3I3aD+8x#UH7ox>|vX`oKex(#AwmWvP9R$d~9j zik+z0O1zvoL5Skv9;)D=JsGEBgo;vQ=Qv=AWfeuhAG{Y%DW2MuRcq8LkrXP&CPkY6 zB|!MQD!{9$10q#00DQ*XgZv6dc(j&xl_)BZ*m91lXaLT0Y{#b#Xv#_>xv|x6kL%6! zat)*6ioLkj0_M`+`uN}`EVJUIA1Wpqugtv1&Z)*kWrLG&NywnBxVORV_Y!T%#^3i9 zjKH5^z(J;CKxIzinL!ldP~a@cpwF}eDkhzUBd`G!AB+qMM;}W|Ha{=VwqnDHU>wjj ztUkw{tNBP-%k`4m?om0f;SW@!?db*xHTh{QgzO-9zv;xGbTknL{$VcNYT(q zNmw9V1<0*wJ_`Z7X`5i>M02KW#D1D>6e4}f+h;5c)KJ`{zh;#eQsGcIS1=aU($q5~ z76Wb&Rm*N=n~zh7-rRki(z^U$5H>L5IsRjq=_J>1cY>!GS+aD{Au`(}6wC!jKTnb@ z0i4^$&n)aH#DfB-Ii~S*8!_boz2J&U-h|8LJNM9b`%X!+it!k`Wk$FCl6dpD-?GpN zvT5_A9oLmlzBMXxun&?p`YF}wU$KlRr1MyGq@^!C()aI5^3QBm^7GF8)tYRPvq~oR zZC^e#rPdlV8LTbTr}p{=dmHpA-xWPqSD|n%3ZFqN&m=nvSwniJomDRu1wQPb^duxC zNn$^wEh;QYXb$*&W5H*Nj319UWt;M4$k_x$#(aP<$k;*i!y4#3M5#}}zThgZ!1A*} zie7Ya;)^VDp=bdE@jiOjxO-psMAw(d4l2Uai0?8ssPejIdx&*Amc<5)rCmwBGC_@u zmG*S8R*;b|?N$XPew>*V(UJ4GzqJ*nyW|rqN0j;;=+jrxQH2eYKXv5!B4-P4oORG+ zUZq;)bcxIHQ@F;9q^JVYa-4rJeuufDXI|O?>@og(!4#g`!a%Qx=mzN{qwB1zl2UT_ zs&o{`-{5o?&EvPf%=9W|fq{L&ipZn{G)hT&&gEpmD7F*VpSyhCK5pD-DbvyTSbc+X zw(+uq*m2&r(Bci-Gru(0)xq0^J;kw38R}j*Nsc=@7}Q{EIdY2rR!ZsE5uX@u)Vz}S z@yc>2+K3IBDDIypy{`dagbDpd9=ny0J;7(5Bkd%&jiN2Gp;1UDi2gU%ZRw+C8okbL zG4SU8>}LH6Lz+L06uSD)b4s&X%>q&B-7URh$TyRBk5JSP46FI8#?;wdr;0 z)Pt|ePQs72Fk|rkWjI6LNirKi5oujid&62s!@?p*L0esL33a32y3+rE8ng}8{D=O*%K9I~F~|R({&D%g`p3VW z-hoSKN5o3cO}rF9om2qq7J8i!Qi(wSl=HAiUDWcSYrS6Xo$(YLPOH~pqS&Kucema` z-wyYe7oI0_X}5Hc@gqa#`|ds+y3|CHh;4nwc6IrhZ1hD9oS_+y98Qgf3iSrUkig&aH;%bTxygQqfAPL6$z-D$~NO)%InN=FuN=3Rpw5G zrl~R$8xJ?eGO8J^8_r}u425=z)h0I+)fNJ0;tcs~S#uLkJO6OXe*E-=zFIcIo@~cv z5{v_*Dwg?~Sm_sqmZst$!Wdwmn&I zmQB%bKJ5iIj1n1Cbe~#qAnmZTbnXC}rDtWFxv>=!HlNa@K93cdJtv7nRpc831FbLC z^5+rC*{~@9Fi<`T2sh$*=i#=WmksfXI;NxWCJYV~5Rh{dl6XkNr3V!j%)Jc`)Yg=b zFX_76egqcSI||EH3F1#`&zUP;&&yx&D-wkWZmxfAO%l>>H=%LrJ=mYp3BLY-*r54^ znR|wv93@Mw z!-*ce4&)Mn=AcaDs4_fE)bZ>oZAh{-7CmIJI(?B9Z0?BNFhzycZqjAV41mrS!-NhP z{2woE1*|sxPW&pOH#+v3$J}O0Bj*J5M{tK((zwkzfs$H${K8oW-2~R{;YJE5X@s^@ zR2q>(p>x9()wJ#ReXs^C3x}x08Cp-JR*aGBux_i5jS!=?1*nxWMwUZ*q8Hp)8ahhy zpgUMVc&nIf{ClY{38PYeG`4|oQG{9MMKoQ&`r4Xu+z339NLKBGHfv?f6a0NJ9D z;g{$Z5`IW;fm0*S`X;dN*5AQZo?7Q0c~5d83)^}t9|3Tjy%yfLq7&MsyiT#n`4fw( zttZT7WZTPfp;_dl!)5 zV)qP49awa4VB_yd*qMII^7hbREfUB&!32AC2vzRpT3Gc?Pz3Wtq8eB2i8EN}RGk!tHAUO7<9}l9iy%$(W+mCMzA(;-;X#OVOE0GfIV{Cx`O82>K z4GufJdW0*A7>z0>`YbcBIl^@U|1A=0O)dg$T6I z*Bm5Jw-(Fn*%%2o?$=Nc00>OkCRkwf^a~I>0vynKj)RHyz&lqy+MWv=Vd%8P&x8e1 z2O)@hA2qU2a;wV7z77^9FkY)Mhl3L9@5U4WS?4S~z{9l|58&mSX1)(jVY5lc6Yjta zh5}pW3Gd}Aqw#UIOEb_O&cUWDyzgt6i(DBO#=z5jj4MY8q%JJSaWB;rd{f|V;itUd zQd5dePxBMH&$9Un8QL#hI~;<{k9&rpsl$g6sF(eN%F@v45BwP+Abn%Lqx=>dA7l<; zDCbUsUeInt=B4GZLW&o&I|n{T2#&_$FO3GvEcpvGTe=d2!tH*ba87*xcLzRzBqf&R zag|KsD(t)3ic%ovwHLES$#5~V7{zib>wf#fZ7u#?{1|!O^0-oA6sPK;mBdoxHhmoj z{f)?Mv<>DGAY`59s5ck5l8d1fk-0>OcTT4y4;R5kPQ}aT7=#y0xUQ}pp1n(LgK2_g&iPbkv|b5Mhkq`;W`Pd|L_ zGE+bDN?>n6-1Erd=9A5rIRd-J0gFhG({-y{Edi`lCP5C95z#LuE3*nxEtu>uqng_| zyZ7Wly;O}%m7h6v%4G@qh=1~@5dt1&7WZSL^vE{MXsL{0x4;A(Z?-ssA^)yV#&#D(?&8DG9LHiW^Iu|LuPDNab9KGI72B?s~6{5sDp+X z2;;E>HU5C57zzzi6WiA=NK0IRk>D)ejRqrs5GtIeSH#0`!ktM+w+C3xBRzA(839`r zz6^%}qdP?r&&YW`2C2}Bql)?*P*^>glD?OX#MTZr7pI_LX{6w@sHBaOgL(>?glHS+CxG{Oqst|9o^cYwWOh;b7aoK{|{RBhHG&_}uT5!!@+S z5UrgT&SNj;%>eHFCb~Nt#4&+PIL@1h#)^G*vKO@ugSUwcyhQ;i-TRR5n7{JDFnbPz z_xA(mx~szXjj+NO?9=i@82^k>6$OV9E`&ny6@}rqQO;*u_?{4!)e~<50ul3^TT1SU zN$$eDrj(qB++~ERE=nD;ZuAc8=B|mEoZzv69P}!|}(ST16sw8iBueOla=M?KD zB_z|oQ!Lh%bFO72k$ip|#>X)k8HI^7wrE$-ya;fU)_OmNaphai@uw)2sOO`Nfz4HI zWO?ZCAT5`ozm*ER)Z*>_aVRPjm8L!U8Y3lapNN~w<})V$yCs~t9~~U8RK{F8aF6Q- zB4C87B}ZaOE_(>=x;HVPd**`rSzGv0P`B02CUCN#;?WK;iBgnj!rNX`b|ra4ZsRjl za4APL3PlkcZspQHggLjjO)TGQJcU*A^Wcu2#eVEtMAqLL_V}W$zIyePt-K&2yedD* zCxgG$zBl24X*7!O5X#JWb1Po8Rab3zakrD&ie^I|dx$HxJOB!_3U*~(+cX7xph>rk zZEl5i=8PJRjMRbmg@o;4qFJT97K43l4(pYtQD-dDycZu*j99t)He6#>|9Q{rK9~ZQ zUk-j6hvOfB{b7ZTE;H1!xw%qSbr%EQd zCqGOU)bxT#&e@p!=_hm63$pcLb9PtQ_HEiMk6{yCMHTPP3pDQ1w8($wPK*biH!sh4 zzn;!*)Ng?i=9fo8Dqy@zzVp#x0-fJV=biX7k^EhKytBhZd(;}vH`3bXk>jzB|1#XVY9QB?W7b1)da%WU1tClvP^K-|kojsxv_o*pS%2!_cNB zNHm+Ocmc@s#G+Sb6-o+GP9dwuaA$yLf=ANDZ-Ar>E{9n8ND8q?ng8f=6|gtbAfX!8 zdBFmeOrk4P_vsPvPIQ{DW^F}-TMv4NiX92T7z2?G>!ykEI&BG+2Y8v75jYa-%#rt# zt`?p#quL#yVdJIoXtVq`i(XCR!rww|rRlQIYlwBcdu2gE6N|zmvb^oGC_tPC$bq`t&-Ok zOjzp+H=gcHy`luM7!ftnl53qocsut25LlKXoRtt}jm$u#7L*g6Pb89|7vMOO;%FjJ z4Gexc*wu8mo*(?h-BGUP;r^KRz3+-pbBz}TzkU@0vWUA*2B}E*?T2K=@D{xQwOhO- z%CRvu5lYAe+K3^}wH!b)@XPuo&0y65kG1KS-A~L~{6{CQu0Tv$OL>H1pEc;N3__kU zUo3sNZc{6Dum7Rql+DinQCWzNa-D)Y5#8+A2t=?cpw3(%K?P~;&V@mSKS;xlut@m~ zE450&{dvd+Xnk)Lq?s^EfCwZGjU^Su2ZB7p<#s9}Kl=o61!kJP&XbU8&E$eGD0N&a z#9wiDwtS}E3c$5U*a|!1;4q~SnMTi11w^Yl-i0!_+u(^>(?iQ#QCO0$93(tDF*?vN z)P1P9{KZ*#Yj1x8))4RX^dZ}ei${e+5 zuC~-1+rCGlbb5uC%l++g_tHu(ZhLre(W;+QVcb#z@S{YFNJ(nxT|&S@cV6%n+>>;4 zN=0^Ba1lbW{i-+=LX=5gih<+QY__SxAnyckTeCb1y5ejb=j^aI{u0tTqa1YDD=G&9$iNjkdnw z9LMfs<#pX4;~P_96mR0duECIBgtHfGaT*w;|#I55|8UM``YVg*&l8q?)hk_e~ejdI$s(j7-#At^B*9Q)#f3@ z-6*d?+CCPT^!a1HZ2Hj5nFFo(FoZ)Ryerx7D$y8kqo`tr%i#$W`ZqgMYx3^z z5!F6qexKwYh^(_tk$MZi>Db>m`KdI&Hgs4koja}uxRMFsv{4_VVftJf4ACXcsE{7} zwB|NkO8La2HjSWGqa(l75+t;7QF;>e@3gH(U)+yLe7Ltu5}4VGgmrFWw}B^}LmFMD zXT{FQ1eJ;&#tl?>yw|#ryIcURif_r~=!*#MeSGC$B~WEgG1P1zJL=^@fajFM{q35# zW;)kI|YRa2&exzisH;W%kAVP^RBD)<#=|jZ^<;cfM z3*R5>_1hyBKxKKnoX^Kuv%BvzoHw!SCOXz}glHF38p!Y6$%o96cxuUCil(BV+`AY0ImwdA z#!DP}Q$BKe#{jbrQd7t!$lFz#923UWEg$Zra<1*sNmKTQj0MM0RLlQ_6pMKVDMK=9%g4k0j!1d0{G zL&%0T!LCjQB$BDxAa`&HXrgKfMn6mxLgyPhQ?}eoh%K{`Kir{ENzvQoEzXDF1B42; z6wwU9$?}$50b_>cc;>Yq1~EHCNv;(Q#H)E z5LjuWN*4OHK{I+$f(eF#h!oN+qs%0xhvO_d%1}^$p`+K|#0jTi!z+rVIGNKF4ML~i zk(??FQ8A${u=dYeN=06!(>nrh?WZl;nkIuVBoX6yLcHZX7Kq_M0FAB;dccI9xx=xy z>9h0%4thPIq4A69HKgdWbCxjOEJsjin`BquB`9)!mRH6nDCd&UYt)0&&YI0WRKeH> zhP)NX(l0MXW3!~>RqjA)qqtATmSsgHKC>JkPow}$Uzhi>Z6jQ2#UNO5x1RTF!tT7v z?V^}H3vZyIX{xpn4QRKnKd=io^q22gx*0@V6c8v+H;@nKEy9~vgEvhoiL104ots*q z!A-#qYZ7O@Zl60>5x=tuoF&IZ`q?~l-CX}|mRWGl4>YZK6BWsDYs0vzf%G}*w0)IY z1AVn0H~!jLzI5d0)laA!s_+txob+RP@6cJ0>up6DE4x-o!{UA)e5Wc2WKs8}4&O*fx`b2};@!eq3)eD=L${eFeu`OD7^ zua0D83EI2QjzRT&F(>UpAx1njd?#f8%BH)NIJz?JBC>%c+KFMU&UU*@qov+Ozg%Km z^UwIzdeRWp@#kqNmeZ{+kiNsLa}vXE=jVqidjp(<>%hF(Ar?%C8>MxX+oaa|bVWhA z3B{93f>1YG{0S|j@8vsZCtwC_6&Q}%mJCV|VeDUq|LAMB_N?3wV9R$g^na=g|LNl} z2jhReaA?MuOxR?*%Bi(yzgC{9LXBSLJPeROwiO|R#8NK~IXptx@jGj&_P+VS%8{r2ez zb3giS$YZ?=eE;m^H|w|VPwS2F9M~2+eFwdl`=P$P`Y{?k60M#F?p>|R-OFbed8P{k zTFiQ}>^22pF7oym9Pn=lzvGPc`@Jt9jELv#8%G!9NQtv(7rn8g-HfmJ6vDfwXe;3b z=BC}7xxBF7L@VjtrgXI!x=yQR`6-mjtQd*Bxhh5HN8DS|w?E<~S5{5tX9wY>(u9Zir~YOcQNO2 zzHxy@{$q(6eS9NJjNROGomON6sJ6FW6(^#;gZbTj9^A?rEVSaJ?rj&)Ttt1ZPz%Xn&0B+(=wR)tJ-Qv973322I9u zql%vtjjU;?K887Hyf1hKK3-9Y1)ocW^X@(Ds*P>M6?Q2Lo-AJ!y>)vjRT8$2sJOUN zoG;vFj^f{u^*CfjZ2Q79Wx=m;b6vsWH-{ zPCIKIs2>ymvH#~iFJI!LfsethL5LCT(GOvFm*M9d=1`A~=Eri7EC=8SU4&m^M9$M` zW`iN$IIvk-1E4v-xyiyc57yKcBi9K@;glt4niKZ^UcfGKZWzk5E2Y~Sf{P26hR~8}B-qD_M7rsZFF?+2m6?7lk~dj{0Hz z^mg#RdlT;G21>U%W)o*yK#dMm!&qH8)|S6C%jHzED#A3@=P}%B0M%@0$yx11sO{>T z#VT+%I@4oR56FkvwBvnfE9*dhM7c`Qjl zFSX*nc}-UI zs#Sc69oRusr8-ZNElOl8tsPKOE$>NNzssoluTum}2{21mur8!twGnqqTjhlfAqISD z&t-5)myNg9l+`;*Bf|_gvE&F;V0c)QgjX?OVo0l1|3Jy93+c-Er6;f<0myZe3%GIS zI@8IwiOUX&Z^pdtk-%&`rcpTpC(Kny6f0OZ=>3vnyK zENpO0IA9_hD%j5bn`*xI3BfM&S*2{Zm~2AEb0uxB)F^VO-a3k63ZHR-Uy^QLAMM85 zzktY33Y-x|WNX1xY(@A^6cJ=WxN`eB(r3;R(W%~SpY1Rgp!hOz{J8}oyS1T}M}`pw zEOg>mJr9Q$IYMy-vC0S&dV^_8YxTk`l&_wteG?$OjATo_0fzTJ?F(Gk)G?~*w7Y>H z>7n{y9!gE=@7TRHK*_(AK&$#HmZ1B&>Eln{y7sPS`)KRgu&(Wxov5JAd{${)P6w_- zCOF^T{nzDTsC-AaojnjkKkh~(t5i*D3b37C;jOIqt zB1k0fuhbd|HkjP`@*@xJe|Ou@?@lkS4qZ@S&~^;bX22?~5vI&^F~kDboo|BYo$I8) zFQo&Z_Ikg{|DjJfy~B*)lP%hNN}BtNH0XR>Tn%nt-1_sp5bsLY`_(i<^}bEV1BjibfGHgOnxEdV5rg)Pkuj%k7T zi}kt1=_hsGOs>JU>r3S2mj@ao+_nR}SmM!T1!+2Q{CR^SLz7d1?JHP$QL+pjAVGGWBL?{+|ST0E3V~HG34L6W$D|0 zfg(?X6T_NP^&p58xS$)--UgkD9)hN7tg^KWSf`b1R} zdqzOW^e{awhIW1fS@Y?vwD-cX;P*xfM)=Pk#5Fm|AZew)TIj8dp?}2on&u>j3G4we zeQFYSfP(fERYnlW%*@NjmjcUazMxWVeWS00;G0?jP6XHtD?@7?7q9MOSNls(L@#_F zOnk9ge0CG`LH|-BPMhIftF@XpY!YW+#sDHW0guWsc799*!?YXX(4Uq`0fIoMOi^ zGxm$5&@Zg?&b#(En;*YVr)9-GwIJAZ&aW@(xtMhFFt4604YB6hF+9PT<>YgwICw1r zvW-wX9Ty)RE@BKYD-68(uAovH{fd&JV8(Ig`W;&%aq7F;vov(dw97>DbX;_ZY`A65H5~1 zlke&*Y#nDQBpR=uM-N!}Usxy9*g67RR$OYSR=2=tzdmdj7#7s6er~rVkcoSO5U^GR zw6H-DM{}cpxs~jhT$Jf_5PHmTUQh9T+y9q_&mJRozV4uKu{jeLWrdN?2 zJp(B1{u8{)?|w5fZ6y_nI>lKhZs+d610dDnuAlt2uokcUJPlQ5vDQ0%m@vzkG2Hra zEw`Kkd00nEq?tUbU*M-6jV@_o*7k4Jjav zN)qil5S!K&(0D#XM_-K>L>Jc_nvD~+VvWS|b1yxANCU;9B>I^olIYA-rpIH5FP+^E zzwA5(bR&zL_~bRj@FGK`xCImZp#_sBTH&v!{S!b`()o2YBk=?qt;zI@PvYRHW`O*0 zz|uf>Wr&B8SzeG@y*x93<>Xmnc*nNyq<{0-*O>U`@px2`1quPG5o8O!sL9p`dg}2! z_S6@Tu)=K*K?uof!B5;f4&@|}VLprR?P{@l{l2z|Ob-0vj-iIlWfH`svtC=|V(yci z#c2U0*r6q^q$#|5{lJ)MtihfuSMOESV{D^gsW$kb&^z5a>?3a_`7;c9D{TB-9PX^n zZ;SQFN*a5h8C~)D zq379RER|2vd>=Y{H5voq(4^QX?WpHlYr}s3hX3Z=w05AAc0*W_T|I6<#0utEM~CM{ zs%pvtNz)74Mg3C)6aosBKtLC%1^H93dzXO3lzbWx)CH9yR^J+G#SVXp*^x%d)07db zXfk19G>+HxoEU40L#5jG(^G4+CxKQhKT#HHYXH}BVkq6tA6a_ixyht9k*hD9j3W2R zUXX~;wp%>mjNGZzJAKQA^HXJgV;{H|rORrscJ!@bp(tH_<_qpaD*YXr_OK#I93$1& z*XOBNH15K0tJ;#%H5IFX(8?wFsj-BwqS^8j%c$97kr7NHrx#JplMiE1P$%#2oWd%A zhbJaOM*f^5^;hxL`HAPJCiF+z_;@iE7zN~_wZaIl@*2hQaqYfwGBU7BM1_gloKPSW z#aXQyAwZ@-)&_)5LuEnMBxQ+iIF=2aFN78Ks#9tYu0c_JxD(4hj{}E)TrtH{&{76% z6Ug7U=R?yqiPXoEfdPn)kxf}y$l!nQ?J9+sm*~g+=UsC22h!afo0wLwaowh?st+Ig z=$g2h%PKTmlQM4A7fUAcGtC$iGFLAvCLXf6`Ru`s?7zMT@f1%Su7eQ3!4Xz!`9KCQ z8%qm=SwNBHvQ=9R-RGxgRS?>_Z8ccb9)!wmSLbst+`0iGzOl+bYIvC*K88ScL0yPR zXiMzcAGd_xOWQA+a@Dj9jF%yCU}WIW{j-abAr;g;1^?OO0k#$i~V z@gkkYyX4*J+$-o)j5N`x@m~1qOoizATARqJJmimxvk)VsCxZYCe2S3J9EGkdNpPQdu5x$K|<;J4ST zAM-7-Kje=YIu4(zAoOWDNjc+QOij*Y?P5K3eVbBgE-8n!e;<;-?cZVLjkVOD>_wSWlsDatQl|X#88FNK_q?NV!C-qQgiSniZKA zC=Z{bO3mE4qz(@2CqN{IIzDG;gGFMEvR5-M!6C6D3OQRdWL(rRp*L zXVQn+*G0&c&#i9YE9|D=dID#n5Y6>Dz144u$xw*z0uIUU6~VnGBO+GPJAxbV3jY1C zciTYDyztl14tO{caE*9z-2-Dvl+Y}rRy$|*tr5&fUgn{HY%_c7g%DdqUrS_$_I@3NO@%h5K?Tv zd1!T-hBI|YjpE!~<+d)c;a+qP}nwr$(CZQI6Pwr%z98*#fk z;y=;%RMdMtR7B3q9CLhQQH`%F10N}!&c#IM$KBS5{Y{(XGGM;5(r->{iU7zcfTaA; zb0_#XeJDtvmM?eeIsMZTCY8ph0|<`v{^4rPJPG zu9~b3p8zmQ=MPZlhSxn%)mAEWr6VJr78#8HZ9crK54?yWO5|X5Q1bx!aKg(azKw@-u9llY=lA*}aoPU7AqEi4_^TjhGAmHu zEZ@=0Nmiras~7+Y;N~fN57c-fNe*0fEXW&zV@0fnka4g#dG_#pFE^@H(s=3l;90!7 z+MtO)!a)W8Uab`zJCZRQ?3@Q@VE+=t)6hB`$bo&k70*f-Vjyw?`$?PJh@rfN^}%yV zlPxEOn3#QctBOEABsJy?_FPX*e@%pg*{5tNWr(CQ8MV^vJT_dg!Eca+(ut0b*kh&s zxAImuDSRltIV(on@x)jIrlc(9-FZzYtN7A$^r?1+1|1hDEKSq=T}3vZtv09tNODou zbH7+bgB~PodV4pW$EkM2&8ne=pjehv_RP6(UEL!M&@NZ*W9^;(a7U3xG5z4M>36AR zE6G5p&q%uOv_n4?E-!nZ{Q_rUz~$?TZN9}qVgVBkBM^Tt zLA#VT03M&T*@CC88r#f(m|UA^d;fX7+pq}aW2#$WeBr!ET!L?IHX0q#9giOdfjG+z*vSZ|&K>mP82yL}%LqHj~YI=$A z_?3(t7?9?&wV=BIUzx}@?Fi_wc9A?Z!NF!_9&lIBAcm|$5r_t`q0{4^k<3PBsLcP(Ro&sTF05wiGu>Kc?;g&d~lYDg{^&W z`(mb<+2Bq5QpD!??EvASg+(0TED?2rwv+ecNZbL?fC#Jk72oB6;X8RA|GaFxwE*QP zF{nO?B|SdNH-NO^!Og7K5Y0%O+H*#l z$G0zMF3+GBg>-fz9pD5zaswEE^@fG5qPPY<#x+CLyl&F}LxD{aia!M!<{RSBX6I`{^R9r*f@@DZJy-EAP0 z6X`LQQ5lEbD2IoY;J$m*5UT>!W(aJNBeYA#+p9=41d{;7o^rQXqx%P~^m426bVjKt z_7Re1!^RxWB*9590H8LleJ0e~Xj%fHqh`zMw_a=nk{4BBH`YlH2J3Q4+2{<0zl#~x zUN(~6Nrfs}hl^FZN<@0|n6nr*(Q3`ro+`=s>+v)Yl!sl_NA~%TV$Q5te{zk1ERCYt z@!C2CX!NtIUPr8*oD66S=Ol@9l@Hvp7qCAzmbyRg(%o_od8e2!apesPBdf;iUoKoO z!s99O%PxKZobJ}UAT25$Dv}z~f&&8h)3XGqtb#&e49$XUXy8}Zz*94*L-#QR?9CW? z02Jn_cMJPfNv?J#o!zG{h-5hvz%?dF&Vq!3k?}X7sl!}AqSnEFQ=hRo_AynwKjNx4 zS>C#@!sitgS6O^a#(8dGBQ!?8=;zibn(Au0LIY>vYPI26(6A(bU~b)%R<3f{5PhHI z{y}lb^~8)EB&`YRX&(cj)L-2Jjc(Mm)1dwLs!003t4MriVh~#8;K=C3x`0*v3hB;D zfjLJ)3!zXv!ol<=e`c$?3acNx?446J5Jx~?EZH~i;Hoq3_?EtbO5^#m{!S_6rbG#dA#q{+M-rfR#o*Q zn0CFPciVM-JUZs26Tb~*ifM1Wzm(BK^noFcxt!x_`8ngMow$x@pOS3TU3+iuS!I^} z9u2VB=rmUyU(f8Ku2yQ7MYXI_$_)pOQp}HbuigGU?SHlr1FhHXYy>=8;e<+Np@(aq zQy;eNDw`a()#}z3kwb3w2ob`%uI$Ux#K7SCc+AbUifGZV03^X~+Np=df=LcGJmm@I z=x7EigH#Vcyf9Tdko?$Tt?FJ6V{3bRs@En2r7=4p*Vy}mVRhD}4gt{E40RWNYb3jw+7|GS$nM3P>BY0i;MD zJwvWS3^!>UeDq)!A0~!?oG((!0Zn(`r|b-=m_f=EtwJwV0P3{ItW!)UHK?@6tfiK1 zqA#w{u?YJ6*2vmN^vtQqDl-c42AV-)Cxd)EV6m*W*WJQO7=JP@wpiypejA-j_WgK7 z`Hd21p`_MeuPHCN&>Jq8VsgJOTO;@e+$w$v;6NNSQ(&JG@R)YV4op|6Y&D#xY!(oS zgmu4Prix*8b|;hfcUPrmw|`<}vme2*n1MvfHl3>5`5?gDnDS(Rjr}6OI@n0b#j#v# zpPcN#YS-Ja(qS%q4SCA}gnH%ZI<~kWMCdi-$ZR@@E^8HKi(!;_w|*7|=#GAlDlliJ6iF&d zXA7&xr9Md1;Y|>BEUEs@;C8-E1J~M8zhrs{;}a4b^oPCaz(Rdfg$3zUX!b0giQ6ha zkJusus(@ob9%JFkwjzitx_-~BO#ogbcFbpF7y`%o*HJ-M#esVOu`@&(M~IFV1NUaY z5OS|0r;DzJstwzKvz!wmuhsysU$g6$=<&)STo~ss(u2vy!g9`XrGb_4f%M4g3(MKo6lMwqR*og|;A%87z#8?r$EFlUg5-lWKClvf z%)+TXaWk3|0+fEkzJVuxy>hdX8Zr0P$c$AIX3BAbJD16dQ6GLJ;@ROm&)xdXWhF3Z zE&sSpfC0m+cvw|v_kQ5@VLc39< zivy5do9o!1(A5e^1wwY2UHb7^q~iF&pdM@d5i6-m#>^Eh+^a_R=2>Jx|8Ni3? z73FnlGEbID*iY$VFi2NYLQ=GKEZpWXa;3;8ZoB)@WsyX zbGgh2m4gUHs}wLCZvVQtS=L!u3{?0E+pm5TVEdDUmyRp(yfxxokWH7bNJw&6t|d7o z>0Y0FlWlt6xR&hz*0F{gd8!Il{md=HkavMe*eu8O23rI4B&pB1(W2rR>B#ng$J7wk1>6D zF|1yTsm_%P&cNS?FD9_+wvSITpmt|(*V+BE_pNF=hP$au9WPg1#p%9v1aP%St7-zx?mBkXji z#b%`rzL($UXg!}1vOqCcsYvW}UF*I3U8I3t{}v4k8PQZ#fDq*Bml&!I31}i)AOq-w zy(27g2!BdqyGkWdDLS)Dl_`JBYN!IFr10=}Y-l#^rk6H%)h&n5+6=@rUS@FoqrWIz_ibizh4)Sd*&anh5=L4{tYt=F8H52crnJR^yUh)q>rk zm5<{q7`u{)#W+G+MlUZ}_Btik#yL!P#W`R$henalm;3U~<~FeDw61PMz{CxCH%se$ z_L%qEWtS9b*Gw(aq}sREW-F)7(f-({t1OGxSgc}gZC}Ivdb5^v*Z1`m4)2H;)^y;q z5z`#m>R-hAE?u{MHVvDt&?~mvQOr*n2n~oU>laf0wYHiob?;r;nYi-(@zqYksb~U~ z{95PXQ8ok(-^W%OcDqa1!Ffi#6l03;y;>1$XRfkX(uJGF%x9f?Q_o-T>$g*k#3!r| zj?f837@(s#?%=jZzUnh#1y&Gc0QqKB+fgS&@8_43l|F!Ms3?#B&?_;p{?COS$3IQr zzg^hXsA*_jI zdc^PKH(KKQ9&@U4UZbkqUXjkE2blQ-n#6I=JoZ+D{#|qgV7|{0IS8&xicFqjBf@*H z`^Bwrcs9C4KCmPziAgP(4RbB$x!=X)2{1SsX438SL2O(0U;lKZtX?{D3&Or#) zzp%2QO0{v&+tMD4e75%$3_`gEcRO<}AbEescwlvRD2|hr8VnBX9LKeyHdWLkT(``;afv$thXynw~SrX9J&R5M4?i8hgvv{{5%PrcRCd_Eaj6N`R zG-C}34UA|J-3+)%&Zg=Ti)pB=QJMqOR&uEy4Z{}Hb7ePk7oh?Yvw!2*6WM4GsFXcP zw#)DB&{`KM=t!oGa%cW%z}TL0RQN|Zp?fRRTZJV$mPWyu7kPg3PXwqJ16I`p6^nU+ zs}@^!;m*s^Lpmb`ri*RRH>s9Q^ThGaaMvYJrhseN&*)uRlchNS`b=INOF|O|s_Gz#?&nwu~~~_E;b|lLqRj40av# zk)RkQ{T;G{)z)2Q3kgf>xQ9C%69XE@;ZCRBM4YeHZdI$uNcCeIoCZ2`rmD_ri5-+%m+v9=Vo*{dy7(KQW<)5jZjLWhO3G>Go0NJr7pbUj1+mR zA>B5yF1bo}0PZg^^mhWe3;zhcwUu8QjBl6yu&@4QDTOnw#UNDM+_e*lY_nEN$A7?r zp1cePmL!QuRq{{+r7qouP9NLCz3%NFtsg zaF|3jaW_w_-T^v!jY%$GmgJe^&VtQKfNi_iL$zT154RZ@>Hqu5szzNa?y?oZm#=S-9lV~g-c(Tz)(g`>)+3}I6Jd&DY`A{xQhlHQ{D8|%J7{zdJ00$;==v2o2{~E1E01moSH-S>@z_bC_k*$yG<+^ z*{{}{Vb?U$1|-*}DnogD$jtgk($UL%58iX!TRDDS2}O0s$%#5<^@v95vz@!XIdx3@V92g{+ROGX!LmHOr5!H61amCHQ*jKdnIsNM9&X<=W!*c)Y|w zj913EQOMZb)=WSH1t z37~Z{U1B_J%qB!hOa0v}(t=s2t@G}Cn0|bV7t8HFuX=nKty?TSLMN*FrpMDcTux0i z)M~1`vz);5SQ9JZ;oG?|o&-0)$WzXR1iKOwYmg5u{+%k2nzY_Fa$CY0ePMh!^o9hs zIAc*LyMC&g&CSN0u2|!Qk$Gl+{E?_F55;$ms$e98os$03Nyn%?y#|$8enr4u83zjAd zriNDLakY_)1g;$i_EPJBE!y5qUi107I8ET%>2oHDqbY6oprdBW~$<>H13t!tpk zLl&J-s;+zM0A9;CzX(1DIEqgxeXXvQ3`MQoZdt}f`&2Ui@b~pRROigFSI<;Gm)*j^ z*}Lp`E)~nilq;~aj4tir?|yx4)f}n(h!Qm{6!K@RkC#4(NE4bg(1)T>j^8Imf1~r> z*QVk8`NCf&(EgDqPJ`nXzy){{l-j~}bf);>b40$^ro*2b%4+bEOnplH25yq*5AfQ} zTNnDmM5+6(YA3MHy`wyGW$`~(Ht+*%`QamZJjw3T3+5t6^ew9x$99G)z9Wj$* z!-m?&N|+*^i+cDw8ioqE-rOwA6gkm*cwXKdv>iR)bKXev52muTW6ITpIVwROK0t;; zqyAKsHG7=_sw>n$LXf*?>5hO29(xQeZ75x)%!m^u8-(P_e_DWKScpS!3jb zaaj9`z68^(s#g7umHCe}Pwx_|3ut=**R_kbRAoSq8Wu89-&hJ^thA5AGce5x_7@@$ zQ;+Dob+>2tMQf@4ZdMARik@X{rAu$~h@8C2H{ce*wPldip=#~|HI3L>LI{4%#Mws2 zZv;NTvYYB;o*;aQJigiS)}5O^@`U3FoIh0)~LFVFMSX{g>{ar#EF zxgh?@L?jsH3===&SSIFm_LO8U$I=mav9-rUO@jOv@Juz)5FfBkr|U9O0Od@XwL~Bc zBNa9CwbRo56w|&5)7sZ+FY9JbT}Dyn9A;Kaf=HOWjVB)n_mkxMYna^b_v7v^SS2TP z(#VUAU&TZ;gJP}yLyVB%a*tWmy*AF4o$x9Ee-8;{}IkLqjz9}Ee6&g1C%Ye zK7Vd~c)q%k0K1@id>d%*sn>H(2%Vd7ZgD7}qzw`5I(V~#znxM?@UI`xxO4=y25%HX zYhT$>68}Xxa=-_1!U8~~Oth|}M3EQgfUKF+yBV$DVu~mk zwy&VO)y%)NiUVOX3gF7BH%M^2pqiwswh%eRb11oHx)8|rn$NBXmBQrs5ftn!8S>jn zLGq5bxx3(j?-?xs856;i^F@qSYMTQ?$N;%ZO4ef9+NA#Ku;9QBJ<|SKZQhz5mk$xQ z6R8B3tmdGE;>BfOr|(U9O-WFrpJf%f#K{jl72lgdo$)^&_eGe=| zcjs$FnQDddQ39L(nhAd$_X4~SxcrW+@a~u983R7d`oO87SY4=@DotEo5&F>ohC#wM_m8<23SXf+ z%^U+q&$ciOM7S&jtX{f-IMbNkVqi)pEu#3>}q;B zb7d#@K$F%@`&RjOB=*y-!l?HC<=PM(IG)w^{v&^H`$m^GgZ)&VgCBghaFF*rcY9;L z&W8FyJXx3#XWFW1(rOINoT%SgoNS!nQZRhIx8T7=WP#W@6IS@{NuE}SYB{KwoPdAh z{0B1Fmy|*x$l6@p8i59;o)hQIlI2tnu3O%lsSgOR z1mXVB8AJ~i5tDQ-iV{=gm|7NH%13a?JXjwy5O`HNnyRb9A2`n#5a(mKDpk&bkdzrx zltH9l7+s0bfPegIi<*M=^*XsAK6vBLtK#56LIDn~Ou)0YrftBl z&3mEw(!^KE_tSvqo>dR>Q_W6ZRI-P6gE8~7W{OmZVbh4+0=9`&8eRycLg$>8LVo(x zw!_?|NW7=3Rl#xM5ZQe%bvfAujt2G6{Oc+SIVR3T3i6kL)#i|jMTk$6`ruQj8awY1 zi>bVQ2EeGeXvUJ|O@ZR@j+sArc9E_@4l0dr zjTbCjnW~I?j1ni`%mOTQZjXFIA~V5HcufpQ_Rug@r4bbQrNC7N7r;Q%`0K-v04o?p zKdz&fM?K9%^p}#m-+*%rviS@t_byCnw2TkiW zm&L^eZe<)-*@~Of=lcAIROP|rse%|!tY&ie2@gn##n#{vM>IEfmP6mfOTJ^Hx1W=< z%h`6C$SOg*Ud)j}bfGR_G6bm#kF@DFF@pOJ4y!5Nb_)x&2if(W9$Ra5l-Mmmxeiu6 z&4Ufc52Y?UJeh7Y&@YB+gmTW)KlJL(;SA#PH8WM(%j^rwf3^S4*W;EBBD9yU;vNU_ zds8kiLa$OuHU-&T_2&TEfR0uCJ-6s0%OY1E>@Fd-!(vnbcR`-tz4nPXb}{oowZ3as4XgBZzyvvSg#kXihN-6KRoofDrof*TDL6_velNSe*}Z3*7A+3mM*i z&8tXq#=hsIw-e~BZWc{arRYl2NGONR@us=nwW@;EsL?L{V)QG57dkEv`t2r6&-a#) z)uPR#F3eLrrR^D+{ltK)3X8egca6nmOzv-3k9mPT0Y|fM-tVFHCx*nv(uS-OJ=2BO z=ZmnEWjnbd@?0Z$|Ip_nb06bi;t^-c*vShrXj z`o+<)COu1u&@AdaCT@Z&V#Ix30Enbm_5y)Y=icLE0{QhYa9f+;dYwm4t-nzlo9a62 zn5UD;Yi~gB3uQVmT^_LMZElYMFy8$mxi(GRdywsg{83f{pU%=++^K7N5^%GSPVyeF z8m&d7^!;@V4RkA1tC-&4tHV{wIThHAi;lEgQ5f&@50?Wb>QQN}tlYnNxR?2OBHUcP zfRvs-wi}f8jw=a^)OhvXKmbeC%)%1t<;XhTYQ1l`$%}xP|4`;x{zI8(Wc){*`(Mxh zS)@zR*tR=tNATP2Bh133WyE|G_PNyL(+=1I5((gC?#HR`;YTW-^f~7-}jRQY0|eo z9D>=ojyRW1#IazB2{BRv@x->Gq(W)6QXQPw=Hr~y2hOH$OP45A-B65U^(?So9Ou9d zTH|)%h~nUff@j-LTkQv)XZA<;@V3R5%V;^3LzhO8pn~W_q5_-hl5O?Ca(4xg?m0PX zNphROg`61blfy{srP`fj9UCoul1$;04r}K^531;v(V8Yt=N*ljPK7tg^|`2qW{aBY z`cAp7&Vyfdjd@t6k1;uNKVth6Bux_Kl{FnI&?>ejcXSQYH9cC6Q(C%E`n9Y8MUmNIi^vKg z8=LJLd-Eq%tZmf~>%};}MLI&emQFYF9zMA^Dq57zwhMdfr|-{kPosN*=M`OYrlQ2D zHp4{Ql5rF02dM;7?7=dg@hB67=8u*#g}N&?Oc$-MnV=n}4BNBIR6fh8FC4iG$ixw7 z6}c)+9f4=?=9bCq@MZ^fF;nsSAX_v9@HSth5y)<8LVbGOhS&*Jf^Up9d`SD4!e&iD z3+g&4B3tCK0R;?gJThY#`T5K(#bi{%2yejJ&b7mzRX+uaMD7=9J;978!-n8O?5|ex z1OBA1v`!22F;y-R4>`7VSDB>(2s)RpczI+TqZI=Tu**)=93b8nzB%P(6WB3DMO{(& zCk#1Ei)r2BNf@=LdtzcaYFHN71;tMzdwrNK zxy;)y7%`s2_QkMZb#I(BX zm@I!XLlaC*p}u!TGhpV>moT`O4jHp>35Fx~4>|hQR3hxf)`8`&JqQHLN0Z5v%J5^L zC?2YxNWXlo4i=lV^D$x>l=^rbGdnc_C`3x)E6iLN{4|;A|F8!U8JR1C;D#C8ZS8;o z0jCH;6b!rY?SjMAM`~v|q6kI$))Y{Y?iPDL4b&BG++R7cXE1P4ge2c{nNEot8=PQ_ zYma(@{=}>O+_9w1ukk*CaFwGunW>RJIE^}~J$hCNB|>J9g61~dC%+Oc{jZyq1+P(_5SW*#ciwh#rymXh*ybb zm%gNt!2{$O9T;omjoZP>sUzv-CnkDHFFA%3lY@8fRdGstlPPsRYQ)Pn z|4l&@D{6O988*p?KHOTSK*Hn{oJ+2J=hr6JJqyjq8G;zFW|h)wid>C2vE%CAFsb9k|BHQ?Fo_~vt$83Q*5QKVlUHS|W*06D5hlHw(;@!26%6>U+`=WZ zE7UdM1f9`20B=*J;}X^l=j+k6?IvG9yR?s;L=o`0pxMDiw7B3QZkXbK;D{!nXPn)= z!)M5(r$|WjY*M!sAueOodHUqMAi#>IoP8fyV8pyW$!<8KJ*##%gPnyL1%^9zgD5Pl z^(*F=-DRP4n2juAZ_gsw@@3H#&oS`XkY@hmqx+>5K3_sBf#62sounJ?XSw$Fe#(cO8aiP3cg7ibQ6 zk`CM12&PY>!_--&t!Jm>beaAOSLqj|gwfbt%;aXzx?cD&Y@6$>Tm3^>`Zx+EwxLyI z9-nDG1MabZ# zv_t&i?4#mABWmd7!N;omNLMZ4Jx%ww-2GP1^LE$WF-?JTvE2Q2LMIf0`C4tmE7QyW z>+600>F)XRchTwL#MAS17jXXCbfoJSCSDzH^t6(19(HcC-f@)0pWQL!kyN1n(*i;w zOh;ZJKAuse7p{-j=Z)?OBlzKe_D5|0;=TXhV4DBGP&<0&|0mRrk)G|p_U)`_YT03R zp!lxU?HPRv-ed2;2Ix1W;oAhDsuO#dTVa*cC8?{|8H+y|)HUH;T%VHW{f0 z8bFKSI*!NT&Do?=V3{$B2))fILyuWAavkDaWJJT^K2Nv{^q3(P=kul`W6YUD7Udv) zpye9Rh6)afQ-?OL70?$u1@_L;Lvg(lcR$rK^-g-n=z;4$B0q!MNu%dUYuu7DG7G^Syzw<-}|HGdMRg{l3bW?gXL<~Gu{5V6BNz6}$Hl8qB zPYz69$*x1JOYqznB{p!G_=NH{SIF`)RAoQt=ZrL<8ZmYQjsOXuh5Z9O3J(xTVTEK# zSc*@X29#NUT-c55PvXKNPFA=*AWIQTioSvj76=aU7Ty8QiF{n(KOu6DAdieapq*R@ z+bslv?V=zCC^Sx?f54M|1rP(^o?NW&&VvKO8mX46w5l2{SnbnbnVh(4fc((OIsK=k z{Lq48j~W6!l&Q1|W|QcgG4KVx`*5Xd;_3TzYf{>e_g7t}l#k}*(y~_<&|?75hbyDE zMm4JI*rcUW&PeAu?!wab=kOqj!=YS!xHHcT3A#a8Z#*RCFWlohkWkL@DK^WA^~1KC zR$cWL*^-+Z+U3XVuGym==@K5=RF$O$oQ&C0pX@K|_j&N$P|mqA?b=E3u*OKPQ=@)3 zfdp#+0JWi#Wc=qqx2H+z?er5})GHK|kIheWr`FGlL2GMTlw8|dU+vo*sFH>0<7W1e zCSDKAlHbqeZmGUHcI8#!pNJDTHa0W4$P>+Frv`lsJcZFCh$J84Ptf``CEp+u7JZpr z05R-v84V2h^7jCr?z%AAs{PexX+K?B+FccY@Xz;;n2g>!-WoTB-EH$*F05;dGf_4t zg+DzWr6(C#Wz2Jp9-eHJ4Cyul$bo28nYfh8m9r2F8{$tchS|A0Gj(*Rd9n_ba&mrJ z)3vm{cD`SVG^bgMeto;#baiuSnjdrL=hu!6qtL9+YE3K0jhb_)kB`S@H6Pyss5L8L zk6l^M&!=0LmOHAyw{BlGmCxHWAvUJ5AYg~y-2M%Kr|A9qxNy+w3RnhO<;Yn2K^%J! zO=H5W?SI8Ay1DUBxp}$B0nyXIoYyYU{o!&Od0 z&|RT^K*#h~jtTXwC(qeuqx#%oVFVW{>$WZ9K?{P!j5TWJ=kLAu^j@C5TSYEah|D1Z zYJ!IT%B^!<68p)lAL0{w4tWGyZCU9{Zg37`e+L^i+xvOV0Qt6}a2LUK`YJ;flI!rD$VXE7oUA1QDEV6b_V`@S*}sca4!f!C|+GObkqdz>E$| zyv^+Qmm}~;4B{L=D1u*d%qvtu#Vc;1A6XHZ6T*Q-x?i6pJ+DIJk7sfv+GHVHM z)H#JFk~)MjPr#7Mc)*G%<);`RX)Y4uYpcf&%et{Am9v?(irk{eOx&sF7ETk{UX{&( zCsXK59{DCuG)rY9=L*f?qdRB%TRlgQf+&8-mv-s>`)9^;7-1R9*!xnLq1c>Qsqa~= z)>a7{uY-qJsqF3=I(QUi15+1vzfNpe=;&SDmq)%hKr>jk5}=AWHL9f@E(oXaAmYsD}A6E=H zOs8RN%4f}!N`&OW#pL@?ZT&g4iD_?4+0=5>wLZ3jZ5CJwMT?8`Y&|Ciy}=E)(V|60 zI%Wl^7@zV}PX4`7f)jHFzxUMd13zG708Q8*0YwN+`7>=TUc{MpR$_s};Slqoh?&fk z^tv=8%)c664(IwS2qjOdJX?h|T$tHHZ~WiEEEcGXNxCyixKX|fE;bt&vL)YuZtXK| zJgREzJ@sNPJmqZzomGd#XEg!5ol@a$&S|-$bV#?Ml*u#4*&m$>-^Od)N{`bsO$mpLH{V&o zJ%&j@*-qcY>f%UNq#|}s>vouSdOt|#*1TGLLgtC>>OIjbp`meR!a2k=j(#Z_?PI3%J`~HdUke| z3I_U9^4$!PBruy2)Yfi6lLdqIwW(aMK)?B^!6s4kdJACbRoZ@YFNJDWNhR*}^!+N? zHMJg3>=!?>x>%Zi`?5O$=uxqC7hZmW9>kl)#){#oC3)n^<-5<8T#W?k0a!`e4FR5z zV^=nRlY}Vd9yUWg%^EIqMh12?%)4vvu=QAO z>n>Z~!|AlwxUk)frlC<#v$1&q2r{kXi2x6H1)lxrEGFgtXCK1O`X3y99REAl>c7B; z)u>7R-~Qm2=Og6rdyH%p!6kh;IWgR==;X+G5Rpx2gBj1fER&XhAq^@_Wz5AE5;HA%tvhf zc(U15(~gtRF?8f(?oTx%&tLy-P&=I9ETEU+28FY|+#1-+6#=tI!RVO*w!O7fz|QOu zhlnL^CCN2p{>E}gjvyOF+F(PC#Knf@WPqM38WJw}le-AAuAX9_Bec%=VvWTUzdXrA zTf@lV*jn_65ZDWC93*`=Yx(G~LQT&6V-OL9q?7M8y8f5$qNa=z8mOwC5|LUYQV=ON z&zwc?8flc&NMO5NR+s2=0fS^`o?1C_6-*_);pR~qgz-H)s%0;X806z~Nh{lr^`Ksx z4&%ZkDJ3p`-SRVvYB8U8ATdq)*T`leIT_}Pm$(X3ppsAaS}OO3de~J*kE_5F{4(pN zlmqu5v4s4_nUc8r)9&mkB4V}^Wr-C4omd<~Fgdx0V|}!a+O1KbKQ9%vC9+F<7+dwp z{0k^JP@Z8o9;c3Pn48KnM^;Y@r6J6R9Tqt)F_#$aN)+UZo9CzuyA~7oyDG?&w(*V| z1p?+~Gm+oaT2R@vQOtF`#bgr7DmrZb5>S{&req;791sZ@T+3JdQVSxyz_)YuDrDRI zn17Uxz#g-MAE$tq5#sz-q-L`g+{fnqUE5w*28|X#9+4 z)vPg`>zxd-dek20^f~im z3;xYakP#8HPz)}ZOzJ`-1An=pgV{Ppc-HH~X(bEDE=#?F{WB9#(tB8mkeOVNFAcX> z=Y-{fwks;QXzaGHZHs}A+I>) zZ#>^vUtXiJt@U|-AvPd&>{(Bw=Z(k;t8&>OvqhO;kM6)pX{MO}LLcC_cNU+5=Au)2 zJ$NdZGk9>MBV9G$-Htix`F4L?GkLH_8e@RMLtypY3TotyoA^!=#)DF{l2+I`BGmRA z8e)t@w5ffix^mgFUqg~u{T<2W04HQQU{48*_r6OA*}08+o^%Qv6G`{%7Jv#R7fqxE zj|FFe_wPYU(IeO8vaAZvhN_t|g-aKOc$^GvSG*3!d?Ij`YJF&0v4rNQO+oCaz~xs# z^*rc3o{4?=GZ&+biI>hM?~+zj1r~0M!Vpb7C@ybGmIW7Dj7gCFg-{~W!M6^;^3Ps> zy9Y0_lk=^Tio}h{xnOz>8Xg}Azpwe&cfA!0xi?1!L6|TMAgk-bHB2WV-+4393{>Kr z=cr6fbv0?hT88I4RS_w!&8a6R{_?QrMK?^&%q8$kn*fDlHJm0&7lw)uq<#Qlhp&)Q$aieHwG9cVc znfqa=PR~5heS!3rQKCx}0Y_F1gVR1m`ZxK{zoZ1HG67u1Tbi>Cc(}yf%1}@En-<*) z#7y_bfY_iI(_^1&mDx88Gu@cY5*CmUDa3zYf9UYH89Pc#pSpn_a`|%S-N$T92oyV` zmcu05DIl#@an&@FoPZ4e%Tw9@+L%lzhnj#pqf8Htkmy78wGk)Hh_$w)qOrVo^BWP z3F;5sG|K#_V#fB0u?Q0SGq$?b*&KuVdLwV|`^`58>Os{6JoG)wh4V`QgOVBtapybOR zSd!Z{K8N$lou)FPMKg;K=36@yy+|IjDSN(1xdp;w%jQ&L?Y`9+X1H}{dUXuuye||N zff$1mxhkwj^QMn2?vpt^>Zc&C;)ar^f5VBb(T*gUwn*SjJyQ@@*0*+siZ%4eig`1{ zjHCRdN_ynh&G`T(14mN-_xODg}fB;Y63 z+_Ep~_n|zspJ~9fMZiDE(R}e;gw;&Zc|r`@417J-;ol}UYHC@r?7OtF1k=s{sRred zr`n0)F+pXsbP=eD{2p}mdTZh1wYSM+MstTu?eU2Q z9R_t3Q@Gf~-u2q5b(tEM^l%VM#WV7~^;%VR`gr^kaXwIxkwp{rO`O%Y(ff}r2LI9I zJ$eRp-)UGAW&ah~ez+pveZ#B;OJW&X3@N*H5>N8&le{^hPC-)A4kqptgxP;(4V)>| zoZ-Gs?%~Xt>u|uVq&HLVazu9dHUc6g$S0$k1ho|rBgyRLluw9F0+adIdfn(i$Sdo; zHceDCT9D2-EKPVzHcP_Ft9t=P<1O8E zio;D8IGwlB6sQbwYd-Lc0?}6ZYO1UEooj`CNKe3zb>NER$HV*6f;#rqX+#_?y1*`M z>sZ+(kET^s!6)%UxbelBk#6;YrMT+{;mO36|BJ z-w$_(U2ue04WyUqM-zr3(pm@U;94j6!qlmP!z#0boG$JiIwumi-!>AvtIL%UTIZhM z50{jBJmtMD6F79X1|W%OCKzglJSi;P@iMSp>Z|$8}N8G$~`aLJyILEzc z_m@_kGhIf(Cb#mI16WrVB`~jxO*Xm<+q71yVry)}el+-|LQUPV<6Ik|h*%i=x2Rlo zWuHEX3fLN2qmM@|mPUe9o|kV1NO{2~D9K*3euW^TF?dGh?ManrI1v?MiIp7)6xa1e zJyhm@^jsmUQzIBT|B{*%+iQ!o5NMiV!y)S;imgu6rt-`w?`G{Ru4m!6*-3ZdWe;C2 zMs6^^PW`w>l<9vVS&;oYA(m>)KiVkz9}(e|Z}}8~hYO>sX|T5VuWWcqzV&$LoM=wJ~uLZf}7Ru zL`=o(lT$5p&RHKsHT{iE?souI=a!gv0k}3bAIP`JEEJ#!9=%VfIRufobWZ2JQFQ%XQ)CSzx&}R_jih?jVa}N|5^tyjpiqT>T@a zjHyMm_ncCNYLQL6(N>w`?@2D}@Y!?ne=+t>-Jx(zxMghHwr$(CZQHhO+qP}n+1at} zWT$g_oQoc#-;3{0)T&kW)SO%Z9#C|a9VfU#i+8PVT9gq+olkQ{I><=-p{RWs9#ZUAMEvJ~l4JxcYkyLGe&U zabaE1?8$PmTPd4FZ&Yddb?R}5bRK`Cr&zNYDId=yU8}@XL?6Vo$l4#O#a*PA2Oq># zup#LrK4|h6%=II7vH=Bh(sKy^im_!E-n$DmkyMGw-~tFQ9<+0Uh!0;8%;n22*PdJE zCt;8L-DRJGVrxed;M0c&dne+(OhJPTKmyI{65@Tqv5^hCMhpoS;TbnPW z82riyL-isgYXH(Qb3s2U=oSEM)T<`30HxmJC;*prU!a{;OBmA#g-kB{!+Jgea)w4C z@N?8qc6`t!z^#u?R#x1*aok;a>w$mCk$`jM7sRutP7V1yThF;mbz9A?)fCoO_&UJY zilw)NC&a5k`pn3X%qKsksF?CL>GQfsQ62$drbgelMtjop)!eV6Bv`&oJ6lY@v<0(v z*&c<*SccJkhXit@G^ujgo@9GrF6?(>PXLE`$RwZadsOsRKgwRYv2A0pJ|g73cQCz zs>5Rz5R29_Rs7{dIWT{%>)Xfx=XoUYPsnhfzcoR!SD@G5LvCn3LB35Yt?>!d%CtTg z9GU}AvTlk$<~KtJ@r~E6GLH$Q?-L~)#;VFR6gPHB3hyMlhFq>R(cw4?*w;d1UJ!J} z4qOpd`nf;V63jNd`%OTnCA|u$wd}z3dvK(G@?IFP#AyRnH5tnQ7&%bFl0m{bd$1G+ zl|0rHDXP<4gd)?goVRv^J|As_pTgjS=7SELVx;VlIAEAY*G z#m(437P)_H1`~~=_U%6EV;+OC(}P)3f?cB4D&6%ZZ>W9s%1qtB@`xVcx9cN#h#qd9 zNcMQ5urg$=B(UQSL^q!R2xtn{3N<=CZtD0G*zhna&YmhV16;&vL+*A}A}A6?YKPX@ z=?riQvr6P^3wg@kg2V-TblqMM48TvpcUgL>*YS7^BVy6%@EnUVBP2SZf$eG|kMk@{ zFfcG^3dpx1^obYQJ~u~9I6Va#bW9e@mxa;K4+^6Xb46x{jo~O=Z1i#ffDPy2plrcH zKNiP<5J0EF{t+vh%yTp5VUaEAL-}=9TXNoW3!@wpL*#YNz1Q^-8EJvoyRyechCz{Z zLyHx*4)L?z*=CF9XPoNf$qzYr1k|#pX{5AhX`<`DTN^*c59j;J{~JV~o(X31{w|>T zOXd4qfKxG_{jx7yUMOS;ZI`vhoP$q)Sf`;P+A}9$q%>+e>FcOUbeR1LZ~qVag>ww% zKe_=9mjBOI?EhL>I9dNMv-*FSMzyL-J7+WepJ|i_**S@<5$GhCaJdfG@=VM48gD75 z0YcbH0CmXq)4IA4HL~G*qM6qO#-J7c{!M%LI}2}jH~xWO08qR~uqD?3oS+~A43B%z z#00KP^58J)^ril7IGtlXAKWVaE{#7|o$_p+#SA@~rzCM$S`3-z47FOc{oD89)8zmr z45L^ebQD_|8plxNVmcQzR_ZgYM)Y4A8qLhsvm8-I^(M;dsGBse zsA^H=6t?gO6-kLvQN49f&h&UvU2?>DE@`Eco-&HrL7BysJC@>$^yaWOvWQ@yAX#o! zR$}=ov$lfTN?JAHZPBg@?OOL&k1rzG5#fzdqAWEERU|Q@@VW{7vxk(7nfUWDz;=LZ zB2sM>nm5P-FV5?|9=h6xJw)klQ;g|sh3MP^_x0Nq;EfpSEH}%Z%@55|OW97g4dD)R zKf7QJ@|YNf0K!FB?fX;GRlJkRnF2t7`6?0^`pSxx2c!aw-K5+BLTk&>F05HW>qV6zG{USLiex>xbxk~TTbSsQ)(X9FLXT#8^TjkeEoGK;07=z( z_@%jP+o38`j~@sQn-BX^wJR?qec|Vn2`LU+tG_kdN2WL;TTVHRu$ zTG<3hYeq^R<4{0dm&YF?-yFMknyiimfUF$ALkV#RZ8gqeE*vn`O=XFb_N!Drk{Llg zUogSq)|v<^@8xFDgeqhvI_U9K`)s9*Xg-ZE3Afa(eRfcWq^vv@9QF*xvtg(qPQzIs zM_rU{6cLrC?ge)hy0A4zWOi-J7_=YOrU3i0drapT57(hEH}DJGXI>r1r9+?H88!HzLniDW<-b(& zDz-trXU0O6`rQIE7RmLOPKZvoo!hiL60; z!m3UxRwenLQgKeHK5#W95u1GTqi8*Uv-#B5&I~1KE?!^Zl?D6zc5A(6uY);6( zAnK9_<-5nbSumzzb!Ka>D9Nm;!tYq7YOh3Jii;{nPgB0P>uH*&;_z0jEW5Jl?9|B| zYM77R;8tFIX1$t+pRGISn9f!sV|q92gyLBH_9x_CENTDh)ge=~ zEU}o8#E@&Z?IlZ?Dn4|Ss=4sSy<;y|6cc`PiS|uf zxKv@=^lwj)n|f#7ma2Nfaby<7TLVir?K7`zU7c7HcatA88eX)dl*U3M{JyG+^*3LE zc+D|9K&Ar{siI~9t(wupyga%T55GbmVwxEQg(v1U`PYA6I-0L;tG5lJn3QV8V%e?l z>c&up>xB6}l$YP?7SJgN^{`jp6~+xM`PZy*WUcL7I_%fgsVkRKv~N|sqkkr0-|eng$bjT~_x@aoV_3YrEubFh5<1A%bkCS-k{x2wrcRTy3t55 zQkAjZ4%AK)^b+f@$uNCp9oL5w>zDMvL#<#pwKgDjgVZ`VE1=r58qw&iPy~krq`PKd zF^m*Zu53eK<&0J`hg||uMGd?0%p9;ar@QpL6Y7;8&lpHY(%6@@F-x`C(S4%yOV_J zuh+^Pkr{YwBKB!xUhS6V!A`xe(!ARBI?h{DKVmQNs;)i)+)uK64yn87XD<*2)~;!M zVhd@-C3cGgGDJns1MSUjG&+7mE5g%nq{Ugm8ks=SBq9!x5;Z!Yibb}s*SjXVYE}eNCvd>@azl;R}luP-1ZscxJBhW_|JtQmE5bIuFGV~ zYM>}fZ4umiic)d^n)KSoA>fRDZ_s*`?N-&$)7~Yd5&_0|df3LC1IZm+BuYn}k7KRJ z?Una|~hX562L1RZJwt2Y|@BdN$}_Ok?0C)F?8}-o_`F-0%L>)0HP`8iYLJ>;xLgz$|gCof^k4i2tFml z?hn3!d`BW=3S~W{gr;)gTqFA54BjjTk^U~TZ-f?yJG&?L))cxGS_+C|$lX9tVL*Ejn4RBDQCJ5J{Cf&n=)sL`Wd zKFB;?Yg4v&G0JURs^|hUH<=(*IWeu8MzDY;VK* zq;_THE8h%B!Ja_E-<{7r?SE|7zxwNfR>vav;Way+CKVApbAhtEwSduL>6qeum*sh# zZCl~6JZcrXc_KA~1So%2Db3W90r{kipyGmu?#>~>)LY&6~evYIJYE!Wnu)RG&ouRr8p14tvLmuBes$g>#2 z(NyC%BoMWU+5B7kzI}t1pj3@O5B|6%)f{MjllQ6$dp>_yHBuWP(}!UmZCn~_-h);x z->&!V+4&7GvkRG`rj7XEv-Sf#8RQzz4yi95SZ3t8cd+n_U87d>|fRr&!!@@)q`;PV-jE{ZR_*A;x$OYkrCrim* zupA}Is?Rbw3gy_c>8|KWX29@OfK6FNSkl)|h4_~ydihqjraLFKFx;DDG631IN#MJb z-17#lu%)k+rMg3ALK`we)9(Omas@JSzd%-(CLR!1jhPcNYWwv#4*k?8PbvAXZijXl z+Q;~35svo6=%MHvgicnS;Sy9k@H@O6u;E6dBiPe2^;l4^1PY~b`?qs<)#p)z= z<-Sro`#;sStseBG*`7Oz;nHY@sF$mD=HO(jU!`~7#en`W#0BEPW(=}~0HR~ao+uK~ z@Z3H(f>;vagUK`pwp2oj1Quxx&WZ!Ah?oW?4Z2Yi#JQ}fwrW;?hRX<}V1jZ+H$9Op zqaZ%-k4u~E!ASh@UE6v7$t7C=C6~KR{Y4+;cAWrhbKF2gQx2+% zxU=tWJCPO(2PrYeN$5%dQYiAX1ivoX%CcQ$tf`|u7od^tG{Jq&L5QxW1>k61Hn0Tu z%P#jGTHE#ZJu(I4@a#W9ADEN57&^e^1v@(j;n$Hk8)l0I0~MZ<$^#mjq7-^v=3kMfDLAMqKSUX__y8g zgTA!vuYe4eA#5}f+7Wpe*N`r?FXm`RU?vxXC~Uar{M)RCN~aB;35)<#l{EnBGJ#rGf-QqrKS|446kG%_bSL{>XB(ZMVTT*^4Ph|EIgj z=>EB*IDVC9*(g2#B0bf{a#B!awSjDZM$Owc{I#DS45JCB8_fo9lmjnsRN5)V?9I31 za8sK_t8<&z@ako!mwE@geK~vA@@%2~-QMDF zcXgR0z&BFpeHKX*!VFq;!#8T+QiWOXHnS^SD(`)kV84~z)+(x6DmBDC_cPZs>SxF6 zg<-qD$}+lN&`2tXj#m2w6D_J}C2rp%*N;r7V`a+$<{0)is;vs^@&Fssv$|Y{zo@ti z@y8MOh*q8Pnuz70@76XBAw0&bZyX$5?|@9KUbnAdK=ai?{rT@ey)Ogl`N&tUQ)(JU z2Ed2$_t|kwBFXmoR;;L9PndNF$|ILr@9N@Xr`MW(y63P`s;-oJ^tr}RXE2B!1cVd( zdH}43ER*|e54n0`tfp`YclW1HxP8W3xjS8_Js}@?vM+LbV3PT&5?88mq&=zb zZm=A?-EXnbuA9^2u_tZeJN*k?=}?58haWxYpL9x|A8+xILVPF)s|aNUiHit8-|7SLo7 zY{E$(^|JNeRFaV7=57&xA9GG3&E}S^!cMTP)9-@pHRkPmwfR;r+$lAh2Qq1O)sD1S z!X#0L)R8KPK~L9K9luvOFAmVY*hz-h%SPw zVjMXroKT{)WP~zfcet3o9v^-7Dahv`JQk*%toP>^BAH226hmr(ySQt+OK%Jk;;1uU z`TA=unw$a7MqbapXIs+!uL zKFY4GHffi#E8th|W!y{*JB+ioeB0BU%0BOX{2XF_A{gg8(M{r3^m4s`ny*m8d?pP% z$cFLc7b#&x5b_r;_4Gb>w!v6RYkzI&9zRC)EeStj!{hH{cWzbNRMWV+6=BWoz!=u9 z(oQQZ?R|gKBoC&Xrc7>W#5c?s0AYl`y4Qi<6lr?xa7?#_n)U_@>A7v;X>2uivu*06 z^r^1kKJtqnTP`e|D`}Fugq2%+QO{(v%D1wje_mxb+g;kWvB}g|ZpLWwLnF4B_`QGW z2@3`5^`+)hwFG@RD@;h9D6^$|&#H@=T|p%%?*kKiC==6uy^zf)?^3+0OG53nbq>wU zRW$er8H=SI+=kHU+}ijSV~eCyz_|;r36IfmonzNsw-!R{CKaSQZC#2A*ernHY@@(#~YsCJ-G@`(`D|Q{Z$)t*a17?C71L(^YZR8cV z7QCu(0`3ObPewWOE5O#!-dM12pqdL+AfmJrI)I}Lay-ri;5D=(k<4&I%J$ZNkERl+ zwV>@$rboR+#HPE8BamPnBeVc@ktpB$dt6{H##PvT)kHpGmoG4OmRD9=csZE`Q)|7- z&{qiI@GXNr?X{hBtk?a%tt3>xss{l{!wt~;IffyH%V{`_lEJx?AP713hC#THtZU|Gcs5{W?fZSJ=56c(ANt}FPM z!w=}L#J^Am&o@T{;AWDpYdgflf=Az7b3*d`}$kT9++l5uYWSZ-~h<9|(YgpOLp1d50uILXY+ZDp+SCImHK->fXYXLy2K zA`%R5;sO5xeQ^QDPvX+bbpP;A03`};Gf+7to5fogBbPNw=*S0zopkgw(_xlzMkULP zNQQH0cd*9)F4f)t0nK5C1e2OVyi6`LIP(NmKDeMpi9D44<8=QM#OdOUOyW``;}i#M z7k7%v+okz5wa8drKK8>N>|8G87v14-_3@MH{ z1HJ|lUoJh?6(S9Ng*K0+H?dtFz`wXOHT~CxyvJP{EiM%{0SDZOV8md7LThv!<``lM zpo2x`^e-lXew@ecjN*d(zd#_3G)(KWGEH0A$p|*~vct3s82PY}aou4`cmTO4jz=9l z);J@?`c}ycJIyusDr$ci@k%VBu#C)@{q}PbqzN96inV5vPRds3B;h5ge0~R4-iZGG z-Iw^jjF1GQ;G4_zWPTveB)rd(4S$!SM;Y&Pd=WV0^z5W`cU^8gVIy;V>&VCLztXcC zmp)KS=A?-n1MQX4?f1XGE|-Q^&ReyeG4`+G@b8r8I0OG=PegDk9G5pB@-=+@c$hl; zo~DYUunpb$1hBwtr>4^W2vd2?uN~|2z?&Mc1|8X1nX{AG%%>qqA8pA&~|` zgV|`{xiS?tFM!tsV?e@fPNhsQ`TMkg8z;W$WJ8V{1>}w3!Gm}EDL1Zg?e^ ze)qh+4uVr1f|dKXBFzODwvkDXD%{IkiZ5Dv4t}zh2hE-zyN8AO`la5^7IEaZM(uSd zfGznC5tkSAO2=hrf49*&0mU+~?n%isE+U>tJj7<>I-DvQKbPg&i)VShBjP3<{<{$0 zWE#2SWJI;Y9D%qBDT2OAZJV5hdn0;-@lNgh(bjf=wsfI)qt=L-Zzsp$toREkKbkQ6 z5NAGW15g~eKmC{}QtPkGihcl{W_7C0L0xP&tYMpRo>;OW?aYP8HJE#hOK2)Qc7YYQ zMOOfd_eAt5l+D_-cF8@>A_ZWv z{P$*-uO3=;`rF#(PLDh#3fOyR;VJUfNMr!QQDHC#H%e zwkopQX4XF-%s7YQ7L*emXZ2KTSQN*hhY5;L$U>0IAW_!AzHX2Ob!i8>!k(y@*B%Mi zfpuMiyHN;h{4|_lqEC+nNz)^)0-Jc~sD&o9F+s~Hu_EbYp00=5gN3RE)`A7$JWfqu zZauOT!5$gP;DNRTkqD?4!pwQXk;I}}Rk(^t4K%}8BGpwaV(fzk;6Hn9fryZjKJjC& z)ma3GX)y3Ew5VDHdcx1%)f!LXH=G4MZGfWOw@b)_+i|{)MvCO7XuCH-K-jm=8nHTV zFA%3(#gJ%**On?9;Xc3>L1OHKYz)zMzROSL4~P!cA_cdfFhjZ56^+jy$Gv`gX7evL ztYF?XRgDA5AWA@^e6$TsR)V$p~ov7NwEBHOjQ_^MXK+C3lgt$qx*t z^z=S$ItY+lkdkmradAE|2NEoLx(AscPWXY0FC;{T*wzOzUI68HH3KtbY<#5wXTBT3 zPqNEh3=a%kI!1YCR_T=F{+#Yhn|qSfjhhSc@KqFikHdIh5$c9_lVBv0I!BlYO5~MW z;j>mLHr?-mEM=KUB3#8B_27zbX7XkdSfA83r5I$o{s7DQfrMGD6ZYGnTmf26{(ldZlDWAt^U%NVbO#ze^z4jx}F ztb&0n#t*tm5WXcJz6|$*)N<3^Kg_BP$RBC%gLth!ENDsnxkHxnm#y@DMdSX_Z{Jv+ z|3to3Pb+7X|D&H8^i4y^#U`EbFlrx-{sV-z+HC$`55RwU4_JQ#l>Z}AWmQw#etQD- z*ENc;6JDxlJ#;X07c>T4GHBMli><&d5LgCkVP(RYCP6Q`dEbBA31h!B;n+nH)hBVJ zGym;#dN;pbuh*~clo&}9_jmN!i*Q)NM6)eImWap{ZM}MwKgh|qk0lY3FO1BlRwEsk zM-p#4jkYh8!NYTZV-*zsv1xj3Y06*k#}$z-O(|-ogZa9xwFkxhAZq=#*oLrGfh#T{ zr4$hA$fz=a2=|fB7cP7t&)rpZWtOTQircPq*^+t(l`>K4*bVah;tyD>-x=dA1Iv1?9pw% z1N1rT$NuusGzILdyUJ#p?(+G;n4)z%o@F`q^Q6#+gWWN~{*&7SSwcC79=SFczbdmO zcgN1w6niVBY;etOrY*;6Pa;ta(WV4e-cGb5LNu)cMcpE?3~UaSYk7_#ZZsV#b86H? zRWWF5$C?OeK&!JhFNRBrOlIL95BT{3z3l}R7@Q$*R{U7XZjs- z#9E-oI~r(qh{ofR?Z|Z4JYnn1rLWpB*2Pq}l}}E&fh_l_#w$ZXs9Nw2J&#xkajHiD z?))u427^^k;5UxSHDi#S=Z%Zus9k3x>@$t9uWqtJQ4%-4uzkOuW-t{Sj#F96K=z(g z>5StQJ}(uchUoK%AjWeu}B89mtPLmDuc{<>#2VDcbxA%u0zBlE&q&t5pF$hn&)TYc1B7U?^=UqT@1mbqp-G*JR@{LkeX zw4+N24$ceBCAYEPD5XHFjE@CTG~RZwz~J+reqetIzkbW$LMcqz+Y@nE3GawtP&%Kmy3$A? zUS#6fxJJcTfQ%V;dZF7(wVXF82rlLGqa3FHCZ)Ji|5XZ}DHVf6ty1~y+vrwLm3y0I z|9xq*28nQu=KBWJb3oA~ptg$Ig$a5o5mLI64gA zpB2TlC&Wm)@`UL0(+cUba`~TX^NAoING~rj@B%UBMqA{)t6f>uYia;hDyCGPVe*wj zt}GmiOr6uYks#x$c)+!NZc7WmsY)7=$rzpb_Qx(2aeyDM8@)<$7n zD~W`ccHcf%J&nf&%fpBiFnRerMtI=TlFUq+kq-<3w!v)43D53P?PLU%bqy1eldObr z8vdgU10)FWyT=7$cno_d0QsKrd+1>4bGLOKVNIgRv1Kz0RP_WH1EAH5L$*jjQr>Y} zqQ8SBKM*As90|VFClt}qi#_zd8r;(0{lLBSv5LqO&?<8W6mbr{u{lQ|`FUP5xp>BQ zr!-tbK0soCLpyiWCeAFTUU<;{9)Ohlu%`Ss#7{!nHp_GikueGNI!biSeC=#8HUWlr0@X zJyBcW*PbWQ`Uc3BL84O5GT~q-tYoUYcQC<_hCn9I3rgN3n=LjRdV|g8!U#FZ3|Yc= z>&&#MVi|)%3IKl)c27`t6Do!!_?BN60Yr)^pJEUHq<1wB^WyRg3cC4t;Xu+J-`>0m zF2S0ovRPu$C@Px5DGv=) zfrOM1aKSxHHNfvVu!M)&f!pjV?dDc$g7glUi9~ha=YZjaKWeTGTWIjMi5jGA5kaZk!Jp>mh^|$FJOgOxnks=Tn7D#W?wQt`I+y>pQ&1I->avL)A z4nJx2e9#<2{kOGM{eW1lM7%3sL81=849D*E`5_M0!tUtRvSIGO=p0nnF2{l9 zMMpN(C3$4#3C@f#r2(EE&K}1s6yI#`XOn)`Kcha{LKy8B_PcIVgdz^0N&S+!V*cW5 zeKudSJwv(Y$zC3(y=hyXJieCZ0bzhJ3^aYsIP0y#V`+qLjcQwD{ z1^+9BiD&iQz>-Fa@Bl{9@`gbmrt@vfT>OdqJE2nD-9yb*6yS)0b*K(0KZu{x_W*95 zIfoPV@h>v};`uB8D=BTjG7h|^ep2khsJ~fN-14*K!l&hUmX?*;a*!fHGnyAr50yZp zBC}N(hN)z2qx!Z^{~Oz_5Y+KM+Dj((|JX7xu>H@(zESmQyKN4X-BW59b_=8eGttSU zFg66qy3u(NS^eJ_Q!6cCI8XmKJ>Pmi0+i1&^juOHHY zV$KY4KNc-B;xllAoA@FJurC4}+GRzjY;*VI1$g_P7oqwY&iP5T-hbLBB7B7(n82*Y zdweo8kC*Y`;oYkb^NH+P0uUz$&IxCg(2;o`gs7Sph>}sCj2EtdX1_Pa5 zujheLH4YpCLHhgYEu)|l7$rMSRtEoi_e?4tATiw^2elIat~K$iFJqb>6bR7i=DAD@ znNHI}LFim%&Oh*b5MN}Z>-ZSq1W??EBBA4M$(jYa_#uqMFU~|=`y`Wst(Y(2$ zEIpTH}gMAM~)}bNg0K#~AjdlOH_h`u3feglp10X~wH&`tmm% zcEpv6c>I9MZ3m%w7@*CO){RZaL>7B80XidqH)b!rOcK#Mrtz~jUU-Du$&U&nUmh^t z^HSCMY2g_LDn8I53zP!{L3u{JU%5jVJ z`(>I3PO4eN(%vaL)y}TiH{NYWVxB{|V7LNliXu7+z?IItj0v*9dO(i1v?{`f`=gJ! zDq-O?B8R9+zc_ebRj-B#@4A4_g=B6KCT)%Kw3@9bp>lH{Oc+u=FZa}5H|aLeWd;`7 z^YaUW5S?|q&X8VzX-KvayQXOBD8-uAEp}CGoIO~S3<$#e+o!t-?RUDVRK0nSNvI{t z{Y@g-lpbs#TBJ#458Wasbh)ylm*U|wVKCIKl-Ha-BH@PKr%c%$_>bK z;JQgP@bio1KnR>@8yN7rf6K&wiT=mM|0KCCKJu18^+^cv{f4QU_lp{Su6Ekbj0Uv< zSNK?vbW0aiA7Rgb_mEfTQSp-J2K^YI&PSCJ=02CiK0`M~cs zS*UFGZmrE>ud7*mo%-leKIv++rUcyhpR~1>}eXl zuffIc26J1uUhPeDJ@FoTw{s>x5j!NoLRcPg*p_Vw0HkS*tlxz_eggBpshXyqpRWD` zI7_tiAE|#%=Kq>(GXBaa{>P8)=x^5dknR7Z{yX*x8E_qQb z;bKI%N2F4u79)YL;^`@qkSM1em(b1#31nf-PqN3yC+#nrr?Ua%loH1Lcr@+F7+?gE zh9q%l1Mx+YUHLk@39|Fi67hAv&PDNx=$$Gx{vk%mewO#K^;CIxo~t%mbC_L_2&>py zjIN#lR=ckM(YcO5V=M}Zx}-QPDOz5e`uCw+;n>x{rphpr|q@RlR|dy8vQ0c3aO#jkRv&?b4=j z*7?`Lu9XTL8|JZK2O845# zip8onXYc}?AXK4px7*1y^$;i}g1IUELwkp-=~xV_Gn>AEZ$eYG-p;T0+i4dx_@K#a zY4S9FW6Cwmnh(te8-2D)sO}SQR=gF4sk(foM##)#s;9t+Zw&#-z<5o%MW5L(xUx7*@G$ zwqQ5`4ysT)Sb4+i7mI$brsD%eyOl3eEwUG(_Nz^#-TE=ND0XZSZ6(FD0%ZOQ(G330 zy^99uI$nNm@wcHaQ1YMjo0Lqq8H?exSveX@j69jDMeZ4J7Ga|8mw@}9k?qXW>aBd5 zHz%ep+a@9&myF~_ltp`9LZkG(Su#UAQOhvOurR#=uG zS6M3Xwlp(!J=uu*WO{R_k2sc|1%U^iF1egB6PHclQKsPBMB1xyVQr7S8r1%FjDA1e z+R30=w1iixhP69RtgE9)+vD&929V(bXZXe#m_R2`p%A;HHMj!CzFGD;|hddUbl^Jl?v;?iVyjhFODM42hp=|R!Zz8oIuuq+@K*8XCrweG<%7w4iF!w zuvM6R?;B1(>;yv)An4GABYxRN6|U0GkAK_0A!on8r!*+}z-Cxbecsb-6ftV_+({VF zrfKsm_NFmf0;wT3SZVQcz*dG;qmR04s{CnqCyW5S1BarMF@EBzK+NYwDG_wcU&RM8 z>JP`j$;I&ejxf8bJd?<2H^RO}xUiUw3)| zW;F}l*q=e_F9C}^HXV4!RYxiRwPUx{uhA`%V-Qpgdb0-J#c13UQV=1^d;q;Shvb6n$%xX^t(Wf;dr6(3|3A7V z=Ks1+U}5{8YgVa-wDb0F&H7ZQkV;N8Bg*(AeN@8LlG|}8R~D|t$;vx`LQz--019Gj zNygs?4dfG0ghS4IPzdVwx^0gx{oU2q)dzV;B5HXx{#&93{Q{Kyk-`xlk|({G-@V5k z-iaQHH_hoE^cs<_Ba^Nw)W`Fg6dgg8ZAAL~Sc%jBR+1aA`Lh9!Y4!0v&VR&5-UjmV zXd3(?0+_JilUCckkmT&W(0dr+J%Q>y|JKZ2Z?V z=L8qIa0*Q@2XR^i$UMkS!X9GIWnwP0!V15(lwzyQ0uTVUD!qzxJxM8XlsD-Vk_|-% z-{hxX4pw~60(gGRzmw=P2_i2s={^%V94Hyfc5MqFsqd z=?pw6FM=crt=uC?M(=X=WQ~bKd9T1TeUup{B~({q`USSU8GhSr*~DxG7W3;PXr5v# z@?&U!j;)kQz({}{M%O{l>J-pCMQ|cYDMPaw?F_rjk_;+&vsG+B=i+(!^9ac3WFm!t zN2Uu12cFw$!6zkDa0?<38TA-t7X1)I#_kDQ%(wM0h#^EDuLD;3z|s0>6tpXlAy^is{Ys+)eJSMwJBT5xP8z z?Hd(K^>W_BYJPs-uZ_CN#ky8Zju=IZvN}vMj%u0etcOZo&fZJ2_5OC}o4Ic{NA6Y8 z^$N_D&6*0Sh^kZ*9(pP$zIvW+Vn}}qb@qOrp3jA=1#v3rt*htT817~9t7dIZ!_d}@yV%T%T)7vn5t(w!Ya?#u*slFC1n_JIk>*N%*iw?5 zBr`{O==+eGjogN^TZLYAb6F)L5Y>i-$AzJ((h}V3RI32`H?{% zuI^Vad|NNI=L&cL5@+emFyXTk8|>2>cJO(eH&z!Go{Sp4!`%0I_w{OM*LKygmyUN} zn&Ocy6RWo6$ePQMu5GgVM(cTlpW~NGws=>kNDavvwLN{aUfZGKOIxrzF8p7g0$5vr ziCoW{TS0GG0P5`z;0ZbY6>`TF+XCkUHH9@(yvfnw*Lpnq@=q|H=}3Ns-OoY zNh_9}W;$EE^H*6dJUAiBt}j?6eRoS5H)gHT_xlv)&i;b$>>Hj3MqkNP+~WOzyaO!%Ay{N&7N%V2_VSe+_@(Zq@~aM-q*g@H&fr|cRM(8#t32l zoSJ4x9U6g_fMf;@Ab&iWwd~2m_?YDfdHTD$Xs*+anZUMCSY?{Zf4kpH^H9%?z$ zBou2o?3scQMgrR~%rDw_zTub?mTBdZb?9CpQpvIaZB z(*%9==qsUB4qS9@O9BVim4@*4u5n3OE8B$d7ORWQKCU&z1-&cLT9yPA$et2kb%zz_ zS`y~u*b$Zp$OWqZy(7|WOKg9%0VjCLF>NR~=@b;NeF7%KU(^OZXX(hVK76Pj8#lkb zDSF#$el>du%=13n6oEU_0}(BqHVww75x{tF-sw?#P$)*pYIH=5;;GhKrDjr~Ldv^a z6yr)`WR<4eMO|oP8|Jt@b_l1!q3#oszYnX?qD)Lo@DtPKo0XY$Ph>Ieu4oG8q2~Dg))!XFnmV;B2RNIji6P7CN>sK#}pO2R1-N^>C`lnoU~vYRGfX>5^E)- zu(Q0b>1x#;6Gvi*6zL8&M_|$k;?V2*V5dG;ulKWfd@Nh|<-WQ1NUr&pkfA z^=|>-zQ2X!4B^AeyrZFrbv!I`rp#inv(QOOiDjhHmC@uUtgMBM7rZH}1V>rb3o8(+ zx%V7AN0u9{m~`FuJ#0tg6Vne9G6i28-~+vDTS+EZZw1)fMj?4DR`jgb@Wo9`gnn!P z3uGdQDX$;Ph;N}+5EU6(D#x&y9-Lsz@uFplSvLTQST7xztL1Q2vPXqyxuq_{QdM7; z{Q_$O@!(qSXe2E&vvz+*Ln)^9x@=w1saTeSYzAf{7s#?mjPO#jF0+x-kXG$FVo+or zwIjK9Ex1``fOw~OAyGruV$R7cc~oEj>qeKnFdLf)Jr>P+$Qbh`H@P3tsCn@oK4&YU zNj3cp2GG&U_4WDRL3Z|GwO(ERf_J!awQ|IVpdCM(J%|Qp0lC<%r9xVZn?Tx*Uo=g& zhD}emkX21;U5(n_#{a|EI|XUBb=#t8tI|fLZQEw0ZQHggZQHhO+h(P0e|c-)efB*& z;$LxNz08;q^Lez{N9zr-FmV2E`|_l^Ky6Us=W`^*yoD2Qi+DJR0ZJT(JkY(oM2GBGc6Yl@I@dIs5{ud zSN1D2_f|D7K96%AXkEI~2x~s72TN+5z20CV*i@AB2eP|vuG4@z@51X>v{dV?!vxjl zLY@^y-5a!(dNJ= zY?&3g+SJ39L4TPh*rbz0rEMa{0t#w%U8RB$hme#FA zVPyHAxmE6$2`X@GPCvn6w_3_NxHL~FHkcUny75= z+vj9DS{HX|sajzDkSz$qzA>Q%K`El8Tb1!#f{^-*?s!-InP!BAySqTkFhlwY>yijy zTM}gI?=T=|>t19FsZc+i;PHzlCzK_Asf6F-M}nC!rS89KA~vD!6!izqJY+`pUTB+; zqz7tjjCofv8EsYO#a3CrE2(Jv8{lg*;8H6giOKflrBAh-avu+lU_1EQVb|n7Ka0J^ z6cNq1624@uqOZ7|Gm{Z#TR?RgrjW#3jo6 ziw#;JYluC}I;xKZK}U9r34)@M4x-vw<*!8j;fJ=l{3~91C)5V#HvZ>3+2_dDEv%0} zA=5}CiQCl=M*klj-C`nyaEi5I2*+G>KPQLtc16K?UQ~(x=Fa6!8tVPvOXX@Prya9& zWgh#c&A7odmAkucc#um>-|QIyAIB<}ik|V%%Bt!pdn_UOW?8eQ+eo%FVO*%;>uGJ7 ztf>B|)IwB?1wmZeI>V1@s~A{I>E$&YicJV}-1BwYlZ|1$yeF z>)_!MpUjCMLw)hfWX*d2>Unzq-O(MYTL+~j1ZglMd3R>{+@)Fud64ApBMRX=b>0F> zAM+(YW|^Q{H!2sI+CvaTfdU{aBbY!Uh5z_V(EY{4^@aZKrHAF8km;YIDH;B~LbCY( z@`%?U+u+7E61+drT>cUc!u6-c|CME%a+(%Sg8lPo?c+i^VkxMhXlN}`@{W-?>+Lx6 zjvzCvb{1cIh!8=sZ4DQl0j|&Jlvaozh(gnPVfguBR!zwpi2dVRlB1WPLc%!~^D*Y~ht#QL|I{BYkK*-y(G6}UBQ+<7*`fJ` z4XL)k`VY!!*en!4E~;bR!LJLhcA%%>T~*I13XJo$-EZHIh?KI4`gjPk-*~|>8blq#(9cZ zfq%$93?slH!jvG?)+@nkpCHUk@J2P$8+M^o_vxWaEiNttV$dn1)@k{i|0K_`1yf;m zyC46lhV>2f_VOE~{>GDchcXnDq(JT~Q@9^o)klr6y?+BTnMFJ>dnixnNr7EgXs`4gku@gGI7l zH;-x9qtP~Idj%mlw}--9ZU z9(JE_l%^&Ganx(;%#Bzjdsq6a=IZ21^|w=2lX2Y26HpR zzJb3__xb(_aQ;D&$H>6M`EN&|ZZ+xHOfJ-&+1k9bvU8dKezG_PRvl$ajBU2gE$!d_ z>4L(9AZGYVe%@bjEkJgP0ApEd7 z@&WGnObNT+C?iClYp;PMe)Eu9j*3xpi7^vqO?V%UQl$+t`%w)?QeW8*Vw~oe4afOv z1t+_ELW7|~$l|b`nY&crVF9{Gq=W(Sls#uMPUn~IReEVmN~$8BS~(e6%Ct`G-pB8p z?PnY0avj(9dT5t>12-aN`*0;C1>hd4t1^96o4>$J0lAqB#at`OdXZ~s=+3WWL)owC zwcgnM>;gm*KUhq59YPMEq6yk=O?A~68H6JqSTVdIl>BSPN=QAlzB%yTBO~dw-k<$x#hvM01D(;Q z%EP_bFfhARk*{(_YDb9`wZwq(-5aP3!3yjREGZ^d^UMDd|4=9~D^fda;y%&!)pLUTVS==g%3+$BsAzoK zILMxC2(frBz!^ngq5vXXNIoO4LWHNdglST8GujpMQOl*Kk;fFzJ}JD)#o)Zxys4Sj zw0XIwGAI1q(vd5*fo$|ZpSK8N^(EkB0rySwsCss}Dq}xmhP#AaBakI}+Pbg=r(m{b z3PXy5w3^`I*<)sj&ekIX)@~%DD&HJL%uLT@K9%vyYOG4N$%4EDuXn!{qmAwy-1^b% zIA%F79SIZ+3wUCCmLPfgN!>I2GUwO9fxieEPZ3Y zP8y+rT?fd>-RG{%if<1EB84r5PP;aPjjFdd6SvS((i1e|ZxUun&98^j4L;IUPds=& z2Yww{nYrV!W>Hy+?=G`-Q z+M1xEu9popF%=Rja#La23O2tB2x)gKzoBHQ^~QKrrB8B957iU9drq-oz%b1T&$MfU zZ{Tqh$?E}@?fTbxg_6jp5pdh!0v%F#=Fvqt9xYEEyu<|W z@x8Z3fZp+=DN%7|+%|Pta`#qZ?C(MYK-kr0sP>}@%3bn|zktLfs{o~XwQ3-|5Z(Ft z#ql|Y6a>iaKcLEA$;JPz2KqlCXpGGNzB+MOZPWJeI@D)Y&3#dy8nk7lLt5ZL$@y2_ zT8qF1xTf(-Kzx~cXToWMGV=G|;>08y%7#RAig&{YCMOOj4vh1Ur{T`bzDyHa^p87h zotZ8U$3%{_Va0=YK^85HMlEr^x_2rJoywERvDmDelt(}HUY$89fCXChXGkj)`u@+r z-!C2jkFP~*RxQt*Oi^?O43|ml8ijYDz=J_hxykJujX5ykHN(oN&CH* zF#%m_KH!tl8jLqW>);9KEEBLM_-syeB0I%~~7@O8z_C<#9;VdDj_D>WoNE zAU+%RBEoC``LVYFr|PXYrbng|$QlFH-zlgfk_l4MCFvnvB1pR1cDH)eof}&5tJw?M zs#jmiJgR##NMtcP_Sh@}F@qH;rnEw?$%ZyF!0h3D=`bVR2@0;}V+`0rhlDOIPJN2u zC2?3=okpAoK7S3Zr?iQx;N64C#G3XIIeYvI6mQ+hcn--UGqEnrD&=sS`K^H;eSWdZ zMklbCWAl6hgaPn_P6WrkfjDi3=7QM}H+%t=H5R&3V~Ppw!f$xdu(}O3BVGugYiG`g zgDhu9RaeanDKs6|#+zD3(P&5vz*jr@D$hV-(%A>dT``Gk8g^8yM=hw?HJV+?g!b2* z@0eiu-RA1=MuOjdbmoI|!LT4AB=D^x5=4wZXtc>nEW{+^Xs_1E((h&@L2g<{I@2_H z;~>-)cEEIV*%FRbV0+PKjjl$KqRu49Z5GH+$vhY~bjASzTmk4NHHftH6RIf5ko^O? zdmBg{QM~Mu-445nA+XNqaejkb>aNw}%2l}s2wx3&%}22mK3|ighy?Fs(vlusOOCp2 zvE4B>*t)9ns~5X`J?t*8?eYe3?Qzg%S{hKKG>?h-u)A|V*wfUO3S=wx?e*P=HtcK$ z6LDWd3KoxC`?dKHunimskOVjb25YL@l~{Z)N&8LQsFbRC$>JmnD`<Nh-tdds}}KnI=q4RLo&JiZeS5vNAl< zh-L&o9!sJear3!yNWIBu&Nf`)RK6k4hWIz5vU3m&_2 z^IGQ~C(lCk5vDReu^&`Az<#S})5FvMe7j8WU8&Yn)Zn32r;L~lM=j&jBXyV$6eyfXL zrR=!{HNz4k2GnKl)wtIvVPKsFm5IG$A%g%HD)DMY!1ujfTIbe7HJ`1c$nMpCu70=u zfJjFVvjtQ^+l8<{jU313U6%i6_%8tNW=k$P@w z?Ug{|1JZtwYQ(m9S;PZT2I6C%{J9KBp^&B}wUL~N_1n#t@F1_p7f=J~DghZ|s=E?0MwKR1Zt_k(a$MAZ;+C7jo>wC02!&>p7u7;xrD+F)DgUf&uM~wa zB{{gt@$$Po_9PnRQ%aT@nV7 zA3Xy4{sm>Ea|ALqCl=vRw&qOq<{3A+=6t}!k2hxS^d?aBaVMNMp8V#JAaf722H68p z+dD^7QKrVyvK&#r64Ee@1~6rvH~-8RakIx9$H019+I{$HYSR8nNlmhU9J5FmZ8+Fl z?{C>2QH@0R^)Ww0xkoO>gTMJe#z*)$U0ehWf?#Q>#D9^C#(M)u-qCAN<3$Z=V`a!s z0gG2ZR#}(-^J1sh^U0D{VDS6~!3#ZlXWbMYa|c&$cFpy}(YsZihhM7HW!!Q8l{sn~ zN28bhE*;>jJoQ>}wG*$_3PKuUc|Bud$#%Pj{{mtRc}i=qiwyg4`k3b#y(uoC$@9FrT1;{js<>oYrjU|^ zF#z?HJ@cAF*0l39CwA=v1l#5j!Ms~>RCos?8euR&68W|oGc!WqCc}h{V;o|BNfo*RLhrnLO41Z zKqJBB4!TrRI6Farvl&iuET_>5wP~~p2kSQYyI0Y`eZe!4@4*1K9w_Y4>wNTg4TYjm zK@Jm(J$TEgH32OjIcK&Wvf^T{VDK zxOUpv0$d+BM5KNs%WSVH6>lg6&v`0)7j}2zt{W4vQZ+n|%o8m&b6(><76}>87 zTs&%U>fa0x&Z&KpC25YJ7izE2)E;=5!y;v&?23*DgGH5{6~8#A-Kij35gEWW!YLDo@>-JL-n!tmmy)ay+Qa(> z2RGSIZ(ay|0bM;C!I>&u9UZ$mHunsA)wQY`_#=|8F1_8JP+L1|Z?Xx-g835(Y7vB$ zd&C0x1NQjf`-g#owzbq^mM*_4gdQOJya6s)#kAT$Fp7Jx3aRfvtq0AJUD&Mz+mnG( zc)>#5C`H}KkMuc2;Z6yI9$Ao<5{t_xnxBk*UEib2_vd601F~f2fD?7@FPC)M$d2vM zT8TVcJs_n1VitIS0PmtoUW=AC$q)&mTvxf^PRb9J4{NN~5MU8$k)J;)@{j~8m4EW) zowMuUW*;*j{^7#`Cw$-J0VPkOAd^C$v0LDQy&hNfUvGLsNpqIsy+4AXnH|v@-suI} z3=9$Au&J~fMQZq2_N}&dyn_W~cTvckYzh)`ek&PGTMPLttX4Ry_ZrBmLKGYYwJ%y` znO{W3H)jVAtsS>_D(tS4Ay@O{#(PVF*^aDA>LI zrDjL@YoRaaC}xSb-IZb1OE1x2@(dx8yoRSs5!bTrAQ*26&0hz!)(U2e;?tJlB(k7Q`qgEUSWCZ~h{m6cxcva##%OtyKuJ`zYC9X30S-IGYRA*7r z#~+7I&+N=;P^14W@$2ldzo2=b0Nm#k9h60w9;BD1c;fCBiI?yGZ@3@`eu{vza!Y)l zmeC&3gkX2v35{KH@0tYuUW_NBw}zs+L|MA3{H?)Uo~{XWb6@^uk-54X*f7d@UV4+j zYeM@&w4KX(9A=KRLoohnTl%uM!pbu9llB-Nu;gx`*5}m}#T|7QgWm0{Hrk&W8H? zUtig7%Dtl#oQsxZpk7rE0kMo5Cg=6aGj*6qmFu3%;Mi$ik`AE+*6s`~S}=_S8>Q_r|;&?K@=BU}VDNHi2Woke`~3$P`JE&ZO~&hs(C)+U%D` z)i@s=G7R63os3tYm>fmKLTjg#C-XR3Z1};5^NzE9g`*odV0|I!`5*R+At;7;8->|< z%ZV(;0-#xq$$|xgAuMsBNImmD&_dRwT8A{z6~TeBLajz%Z(`sJ_0-fGwpnjzQpsrI zVMh)taNj`MA9WxFlyab(OyUfIa2i<`2=@GQK_=zy%e=^F7{$rXrF0~3A5n*kVi~`k#pe4 z(^|fYIQ#Hpex<2mn{cq`dj4H(W!I2V3Bmo^WeTIeja`}Yn+?B>xcrf5pKaDd2*-W> z!qO;<`7%5RReu_#e*WWn42->!Vrq4M{dDUAdJ>czIRms;_-0xDdj*_t>Xr~rSVJ&+ zjjGgGElK>snYweaUwK=pn^q#6B6@&hBTJTOxrWCQY2TI-LsO-Dt#h{b^PyE9#Njy4 z?fB{%u)51nTcZ75;9{f$yRaoX3EMNaYLMZ=wj;X+5A(t`)o7fBL0}<(wQ-!MU61Hs z??K<<#$u0flRVNv>7`qsa8*YVLveb(ZqP;_|1LU{bv_t55jw2fTmgi!{}fBZV=M#K zxd%zV7rC`*8SX5-ZxbuOg5~CHCJ!xA=ok~Jb{b!Bh2Yg<{!Cs>JQp9w&I(^ zB6UMh4@a@C!eSzked^!?)Au3-5XmD>+Yj!hif=k7!dDxkp7I0nrYwRZ9`lCen+sa) zV!0EzHDb^^Il37|k3zEY-M;TS(kea7-ePEtV^UE<$UGaHu@c$4Y(tm3Oocv)uaTKN zeS(VyDAD36C>T-}J(%`-Wmy%huVutpB(M9rdsp-e{JPRw#3^S_f|LI<8p{I* zbz-55<X9_#Oust^p|4!MU$b-?69O=-#$o^hWH~!4ORnbE zg8S$gpV#}W`MWOQA9u)F9w4#G#ifYdM+G#q-WBg)R{*HvGri>2*4FLhogagc@=2uz zSwm{Se{M~;g z{2MfJhBjgewClP{VQdoUw1M~?JBb&d#ER%vzmX*@uRcE#78KA;C_8!4C_JGg<_F*0 zA525vOuU@FSzgGjnh?J18)V6H_{FXKkRhc1%m$6KAD6dATc4|2XapuhHS%Qu?Z z#5`~Al3g2@+;~Lu$Y$(*JA<;93MshGX^F`(rl{NSeyxu6g3JoAb`{bpj}I6 zBnIcO*R}M_Lb%-4ax`|6pBKr+!5}E7q@j>04xqU_%KON?!&o8NR3p9{i)iQW@_R%g z6q@x^VqOJUuZ`hj3r4=P{Voi&$YP9yLPq}t_DUEl2t%!F)Hed_)pD9# zq305@?;}sA=HR7@=@pYLgyJ6ek)Ax5xP6yzGke{%67+ImAD`)K)RR<(!#E!XvW#9* zu*viD`}tlf0?$A+;X+e}{K*K(u~OQY9Ci#rm)fzhB>|O8djo(}Z}-Wq4x&Lj(iEav zIAWs1zZFH6s3|Cq+_3{E`%ng zCDd<)LPN?uDA$V(H-yUxB2&nn7c@_Jwa5A9QN1;z&>pR4ykky$lA%sGI9Pwt`JqdH zZk2-_=$C*tdY|-g?P@|AGzc|+8j{K`w{44`w}-Q5dV!3@wl##+1)e=vBW4lNN$~KV zfC@J6o`Mt|s(CqoL03tvsg1my zaNc445`D2krQv9$pyoy8mNPHBlGOupsxf=Ss9CmbdCF*|NZlakD4&mv7V?gx?!^jz z_aGG#N!^WA3!#RRW3A~MN-sp9RpP$%49v_J-`^Y9S4+LJP|jjz<0 zB{yd$ha5+47wA(jR!3`G`vvr33*OTUeX?Wb`m!*ZUrTHbJ{TK2vs-sxey$?&Zy%3d ze|FYB-u8Y-eSgRMmS3p6><%9ZedV4~C#{$_YqGNO(9b2X$8Ki!0>>{bQ~VQR{KM^q zk%{GB7k@RY$vSOtVE#4z)RAN-P;#t+;c!hFuqQfqB%T>an;}{wM9>DI6MK=g_x0-e zbRnlOTD;VeOW%J~pM1^TOjdT5O0H!>K5#^MO?F|3CFIkUr=}0Nn#7?lW^agtb|X~35O|(g@of% zSZFmu%_D-Ec$9H=!@Ek#2}!@ac<@qdzxR~kreg`A^hNLZghBf0Xf5d&g0>yR%d`px z6+Tc#6bWV7Lq|s71YO<=B>CBJJx1Z93heQR#=Gf1 z_ThlJNfu=D;_?R!mz!-Se(&+=3AUYf)JY?kq0T4xpJ`er!I6GNA=1&7nuqy_4Fx#| zVM>ugpne1~@^#^bII_33K-dP*526|3QY-29Itq%=);+B-P&KS#!)>Kn!|oiDI_0>G z9Bpy=G=ZcOOp$+W<>!)=HN}qd=G<$%j6n*oN8e! z+KE)G!!1oV63FCXof;*PW)IjI$rI^*m-djgA%K-@UAvO9T1}9xJZqHk(kK-W%t@6m{(GyT7WuSrGRtM zGj65zgw3(~$7{gB4SWiLFYN^X!eNt3|l1QpPq^L96Gpzj9fY!%Ou)RWEgE0_HWLaf2 zRF>bm?{1cD?*iRa$)aSMLu{ei?g~qvR5`R7`)sOsc;3`iv~GCCEs_EU@fzrvjOzzz zGTNYa1Gqf^tL{seedz^=b_s#L)?Ugnu+d<0AMT`#E;v`H1Dtzxx9*&TfIAWZGG3we zLBvUoM7aw4d4%{_d@Sc1$H;$F_Vz~awk#D8LFg$*N1Th};%F^@XHDmE2zI!+}jv99}9_oAfTJ%sT z$IXH&I-jl7sT<9^3kaZMWY0!~c1BN{Jr=P$1?o8o3JmP{;o+jeln3$ENljReQ$p)Q}Oot~lkzhvC zXJxL&1cu+E4%OV`2tfR8r$Tnd;@9QjWsfcBgm{Wbj3{lIqm7_z&IOv**tErA zNAg)!yRG-pa0vYq2Z||ZE1{JK9!Q30V*{%4N0x>p9!`TU3*ze~XMR}M>&m@b38+6V zRT^QuJ*z!VOUZsG8C3_)Jx}9SK|G=)?l9q2S6lxPwv1;dM8^;ZBUO5cxpTln0ZiI> zgq~w~>!gGh`l-XuZfN2q&6RCpRvJl9kp5vm7o|2$N`5 zE0(B3#!#dFlX*B`pC-%%u@g6S43uhklLjf0afA>(O*0@gOE#SW^mz!0A;pDLXC5dH z)gMgkzK=!Ad>vE)A`x$lW*!XH3X=`aetd-z;>ACCasjd~HGnB|Ec70^8nQ93x4*w% z|8)Tm{dAyncl$P$|9c=oWu#)g6h=Km*ZbX>$Nm0~oYK8AbXPKo8ota9p)YGD-By19 zP7erk-G}1}b;NCgOJ^S%`}T2kCdL}BX9HUbc2Caih~0SzxAWjCyP`03l_0v>jBoJDqQ{j_;Z z`y4aSmiaK>MFHK6-upe9YOx@BxlQTAbYm0UaVyGS64sFU!uUrWM zDcet!7zar^RqOx(};an{=L{`&0w$cQ($M)R9bhj+BJu)P_;$HkR7 zi@xTu?8n4OFncj<%!W7JtG>Ewr5UwyBaV@aUaB`EcX3wo(Odiap+GMu7Ww1boXjFk z+tAFF6sb1JKHnhxoaEXu+D%8T$>&u!A#V65b!Gi4>AGtgUb zrL?IpYE^G%PRl6D3P4O$@J8dcF>qQsL%nI>m-5slhw0K6?@eB5f`_=u?tAHffkbpY&%6!Lo`h0k^;aRU173bL|nU-ESH3H9cBZ9{ghs~Pi znis42$=f#ou@KdPVs@@mJe+yE!zNDEtZ$vluA^UtYS+JJ8|;dBsBqgwcNkRQ`{ad# zzAImn_^^l`Rn8rCh5!ei6~y_+X5sQ#Vjf+I;zbl@oGxBSlDZQ_HaHO>?^MIt z8G}b?DT%aD&+=kbb6~P#gV-f(%sz4g9;A}JFC}P{NqyqnlYvokLhyas=c?Xr5JG&u z$fPFi3@>pI3^!8kU5+;6W9_*=-M$rE5}j2F z$ZFB70Bl!JvWPkNr^M5|%~#JVR<@~b1wJ~IH?kh7o5SvMJ~|dY7qykK0iAp&)M{8} zVbpr}^$7#9Ts>DqsWq7E9KYDb4s6UO7S_`k0_PbqtF zJf$kfD4Xcz6gT7)mF(*A*&e><4YO|k^9RcLPlYs$jQ?I2T&*UZc<^^=J6o&2&YMOx z_p>(}Cd|0eX>CKRZQ5~ejY&1So4m4!xUGwWY<$H_Y$0r5@T0)3j z`|?2)Ie;Px!vG0*6&C%&`tG2pjE23c%)*OC6^H#1Pc_l`Xk;dH1F!+HiMu=+N}u<0 zpIS=8;}?#yiKQU5upzij9ba|q6|~v`-%8rAp{abaY{fyu{Gcb5A|`({@(33~#^bG1 zueEP=YYZGHL1c3;OdT7ZQ*O#?B~7z3sk>U*M=W(4Z+ch20H>vN2}8DHd?9733KCbD zwFB{UK%&!Ild4s5tH6;>GLsOs6YPrd28>=fDYboc^O#TmY@@F0oOApuQaXT z(DuT!`oDYNw#V2_%G zuWUze0J-S~{z7`qK5>j>XRGN27etN`^*t=+XVVI<11cbe8jNnE;})hBbPi%PqPmqn z$|+v)qQqrc%d=`d%UV(_N_@|D98r3UY_05j8110A@l6y3ic>npd-w8RZp zQL|!U7gtZkoNhz6+@6r+>Wcv=}KFZ00s|^Ru5OIsVtyBXvfBQLJaCA`c;HUmy|^1 zY0>Mm1)q)BV8cdTKvio;Q78VKVj4>`UU6}s-%utxlerqZyK^sT-g71|cC!#?K3gRN zklXS_@1QhL6)MY}fGBwBMQ|?Rlz+7=!`&(`z3ke_{L3rHwy4!niR({t7gg@ddn`1F8Ejs+DF@$xo=p1q0cHNLM5XTT-Py<(Qu20W*@p z4uG%80luUp^q~ihO`Yn%%a#dlTw323ua5^Y;CNxo!-ecpy`YSc;>Tbm!H~#y=pOJ_ zK8Gg!ybs*ExU8>Rz~Y|*ShbxA?bL^tQ$7WsI=!}hzHY%GQYL8cfko#wg`g-HsdAh1 zjJSbVLUU@tAxw7Ig#5+wm4kpoJeg~8u0ok~PDh1K(Y`3}3$$)SAb=p|^@(#G3~>zn zksP{d?<3n2B2R24yNerKgEhO>jY^X?py020LA(_=p9{AuBXI@0l*zA~U` zlU)2kIef}kd>kR{{sgn-ErURG1FczM*N>(xR02xjlS!C~9vDF{ugqLioXeXj$(0DQ9Q{$g1UdE6Uj8^=|LDvf(XZer*&;=(NaLGqTB+iA>4p^H8<+ zin<<`7yl^=!iT-y8Ss^YM!g#iOpQw9C4_jjgfVJZGlcsBmniGg!osmMmD5a<%dJLd zgtrLpc|82LC+TD_%{YeR+?!8c>6ql##BvUs%O-vX*RO-s@HIvq$8$~D((1F+mytV3 zevcPGb~hvJriD3BkfG?G;Lst@9k^mbBDwc(*;@7}pyI@HDhH)Jk2n>nn+=D@d-Gd&|gL^ACd@ z+}n~;Ye+DI2?=dY=(HtO`!`uwWj;6Q%2F5M`uih?_WoK_z9LfD8}?tFhlNH=-e1;|3NgX3xZq^f;H{5uaARF3*yG-6JG8cmAIEFhd{0yLYNj?SJe!$*gzFv%0Wux1Px1$))c&- zam$C@g8*r#EpS&-r`jYDkpdx$@_;*7EBG_0Ca~wav3~=j_FBdNCnj)m{BJ+P|1VR( z_Wv;j9Dn_s|JJW?r6OyG%MSM!GWP1br^1UQr2Kyn{@!mAfCZ~Zw7~GPXAc@MuS2O? z6?nh-;Anm@DS{4cA;eQmIj9QmH$&zu|~ND)h{04_6vmD32dvV%;QV09cTQ6bjM_ogi+$;T5;Y zc|xELA%p-p6hk4tU?mV1XfHL_4N0?it= zPAds^!T?{#M{IVP6ZT%b)hBti5B|`zaYuJnf)!$S?k|Qf4&H5J&vjEpZs$cGIEfol zv7`}EvC(CxYa>|Ur9&5y6Bb@AI`j;=v(D{?-GFDu-pr>D-05B=NZZ-)nd@_VVU4?H zm$fjLtb%f1>itPQ-{MQ8RFa5j`#Hez)5X<^Q2TA#%TD?z%bj@t&DZ@52Eit{eC`tW z=ZwW zWchztzyJQoO!$`o{2$hjm5J@Y%}4*m30gawI1Is&bfRnpb_(0OL0?~Aqh}#)(R&fBbAEfN zyr8SxMnBItb`lXQDU_hF0Am3U3$(~N%REMH0U2lz!IOyr5fj7m5)(7iV5LWdB(mP} zJE}9W<^>gkkEMJd!Wuy4CngkH9P`Q#?j9GNRh!bKDpL6Fui`vIpNO*k}{$KLczd*yxP4662!?13aQVh z6r{MHl85e($%#vKx}aJbaHHF0O0}M ztOHLZFaddR=Uw$inE*@#U|-#wfMgzJzTsc&ZhAp9)&N)5=GJfx^~_B!t#z!RX`1Sw z!1snsk8-whO+dn0iM?>})p&w8fKa+n^p#Mt8wkHtTPP$HWiZSh=1+EhaU)1rZgO!? zaoCGq4yI4EE#7P0|C9GtxBMB+=mr{C%vK+(G&*E6>_qsAG zsO)#h?(S~?0DRu`E1$0n&`7T@;G_71&wz|j%j(5%>f6^4!ofj>Q4u=B?-!s}NdoE* z#BGt05#$_WBO^#!+L{J1?hV1tH;#D!+`+EP=RUQC6%2^|SLN0V-&d(|s^2WoQ7=X? z%x&-AP@S7ZSTF?u^C?%9b=1gBZyJC<_G6ds`@7_`mg2iM2;fJJ?9|c%(2{?n5BetP z&W{dh{^+IMAzxiT^MN%Myy?{c@RMB*_}0`RifbPKUY6v->bVKbt4@FN+ce*&Fx`h> zQLM9PV*6fg`;@MEUoFtkS_457h(Y(uMhC(}AwK+`@3u>=U;cQr_s$*fRq1;}`p9`wD@_!-d;6*d=(ws|V&u-&vgpJAHmZ1;sqI5tO^3^LKOH0s0jOdZ|Z0 z(GRR2_a*(ve&8t{`b{VY6g1Bt4%?^ysrRT>4M*lDKn4VQOE5Ndk6yg7|MkkazNz&a02%Z{aW9&TanlmoC>EBgFSo zx62#lo!HpJUE$lK zUa!tC;N7#fZ}@Msxu|SB+@0C0-O{};lkcGKo-2VooHlle2e8!xbEF+Ugd9EKIXtTNk1p+-Ht_+$AmlGu29@6 zFX(mfV0G8jc*+b@L%ry-^COj_m+t5@h$mSmvPQ{59Sa7-O2od7LRs9LxFa)o-^3`; zq(Luyu!ogS%bSOBzZh=nb!!GL*FuCN3PYm5_aR)YGq!%6GDyN$%{RV!{UO^mL>E_| znwwbdY4fmP#Wf@Vw+^c%b@o2;cBYfmrmm0LsFy3fCIHh!<;=NDj1!jg-e z6d=n8w27-48#kJXqCWAAq=M%bTgGs=eCa(}@arvX{M7${7<;E?VYDE+cH`T&ZQHhO z+qP}nwr$(CZQEAPy;Z4HDtX9nSP#9bXOA&44qtXAM9qS_;AUfxqzn!x#0!4ue-E!q z>YuVc>Rp9cK4C=nksE!%)Xr~{k)Eieyott6)HEebsR@Rg8l`6mDw1VJJ)E(|<|^SY zl_KLvG0TMW%Dz4j%=8$!W+gw=Q05fmH0Jyz5fByZJDU!kD_na&m5%a0n7-fG=bG9D z#I|KB+h;)tA2c^vD?FivLSdS$z7$?&ah2p(0rvB9bXsQF+7LH$dXKT9%^yT%RbcR-~9E%qEej z0n^dRjQ4+p3w=X*Vs;1%+J_Vw1^hudXsG&15)>FZ~Jo}cjU}=+Or=thPf9?_~ z#WMmfSn&x1GPw*<;4W{s1L_i!wT-r^{_U++nzZL-_DP=VJXv+63hduTV+_Sx{V{g}?@-)piY-sjer6j1Nsk@+JXZLA)Bvg>dHAC=Cuvr;m zzAiC-<1&Q@q0fb3Azy~YJpFemXu-~`X)?kie0pc&A$M|&JkpB7&I#Jm8Hu0=+yRH+ zwyNd1UgKbm5z`)M_e6(Y5e#5g68yysq9XMK@4MZ=#rU|CqUCWeo7^D120^NLUL)Z z?HsKF*{Fk3m^4tcn;?H@1pYef9TOYeH`hR#`D-&_uKhy=`izvxpn;YMN5Z)PS)Dvp zNJNYSoO)&p>qT#Q5_}}g9eKT`obKf)(y80!pNDL4d{EJN+=Bf=PD3ss ztC=N-=YoCj)3c6f5|z0Teg#y{RTFXRD zxR+}TXNK6t@VcFmB!~GaiC4QSer)Mk7HF+V0;A=?ltDc;QGY63;snpH){(Oqa^$EBICt zb9}ja^CFR+)^-&gqqgR?64;{@RyDNQ$twX}-+qq=UdDs8^XMvJ$`};#cldWBzQT#x zuFvDMy+Wg<(G<&Q@~1eOV_V)+utH%BHW;9;?`qsU)ZfxXA~0-biJt3@&)Ct|8t|r# zZ;hS|5Lle#Iiw(}UhQkC?0-?ZnvUSg@TtqcnHo!eikOsmt#OQOJct5(MLu0^c_A0r z{jdp%L&{EMhXz6S=AMuS+TD$JB0y`7ihB{pIJOvPu(T%Lo(J9ND#gs3J!&3nc~taq zCNi<+Ze;yBPxJZ7VzDE>CecY9 zP{7wtTp{k5(WBBIlJ5xeKWD7ZE=ArVDtjEHK7M~=iET~9Nz|& z+Jkywl6wTvH`(SR>K5N&O3_P=`$bjBt=f;lQ#y>0*B0ibf(y`Hn2qkm?HuzpNgHL4 z@vOVRgX3#;wN^6OixX*FO<&r`iWhnKo^O|Jv zN`bH_#CPnx9+%Q8=Jwo?^k%tk?q1Sn70;&Ykgw8=W=I`Zq!Had%9_m-b}bIfT8Lit z{t&?s)>QyN&m6rgM#dAFMQ%q$GsE80}>-ov}nT>MaS#v(&Dm0+a7NsOr zq|LzXR*ho7aW)<`%VL~OkIkI~IsuB(N^bV*Is}Cl4faU+R2nshIK3;wp@Qj6LGYPG zHUTUvaAD*3%Jy@en^S`j5*w>zrwoA8tfADA>(1HC{%%6ee%Bw>OE?efn~M2%2p^nZ zbC)uO-2!~j+*I;+&_m#oITY3_o|KIX<&-v(^NYd-PFSH!>HD3gC5QarK?-L2x1ErB zlmGm+_j;T-Kvbr`VhKr#->d)%USB7{b!*wxo={6fT;e%Pgc~t=FnJy9`)*K~U8USq zp;3zpQ_bO*FEHoWs?}*m<#e0Z1Hg+7O|QIkZL}e0oCAKz2%v0P0Vl02iGdJ4$rd+F zaRV~w&hHizrE6m^1;i)75f zp92tnRnX6xikRWe=4GSa3?;C|o4A!}ZBRn;$3sz483-}dEjd1^F}*E{1zlp5Lz0EC zQMBJm242i}PAY7-qL8CR3HB9fL=4B7PRJw13jd-PLMMXWe|!TJ}}0B5qL(=h@Vj)!Wl#6HcfTJd>WCWe=+GZAH*Ne z^)F*`?zKrg03hj1`BCpe*9G-Bz{XhKj#(=P`tyS6BvzxQE_j8~<9a+nJgXbEU$oQM zApJr(CXNnX%K!RDW_I(bG4jwrrm!MVIJf>JjWhrOUJvR8XMRh25Yp*6LPRR50Z1Lu8X7vx-KY1j4)sU~^ zYlwv-H?2rD6&iBi@;dorB9o?Dln6JwyT7^Mjy}d6@1EWG1DDa1y&gNP%o@ucxHKNC zOiCw1gDoB{s8bp}dRD}{xuO!6H=_adq!GKfIw~oMVSNJRHJ*UvknTyjnQH_O-=EAW zNX&2x2X_dsi0|3GYqHcJpWfeN5Lq_$>x5|$D~0$@6Vc*E6zX0S85{rKcCTkUo%)3zJ4vfNLYzD* ziWVO!caJwBpF}z|!RG9o=9b+rC%s(6F`s5X6PybViM)I_*j4YwGyfP3t#weKkq#O` zb#S+l{X6u*S^4k<0she>4t#M~?;vqOV;bl8T1cf6htH8@ETIRi^IenzD%PDMyhN!$ zXj+4YbaavTREnTpj$UN*`W5q`vjUb;-fhC8EQvLq2{#kpz~!KO;hLTd#>oi5VmB{g zYDze5dM_Z`BqgnIghdq6VB5z-SW6f0_u{WHk)V-LM^6mK9L<1qlj1dyk@o*4G9TIl z^zsb(sis38x_)nhP)>b++*5;Q0PqO~_r!loBk##>#Bii-o;j|^I?oF-G4{ym?ylt; z@mBqYK*CeiqXC&j>E_kiG5l;ijq1q-Xr>VBq`@N1)%>|tzOdU=sJIle($|5?o$ zTuisyXq?N&K;%yapB*7!dx%;dI?K|Pb7LPy!^+Ub=+LRinR{L;f`Y8h%MU5O6_shmYMj?B?w!m}d-Vk)0`(+c++2xSmOTSPKo(r_#%<~zI zBXzFmZFEE+tXYZmut4ZOz&N_?GMe<+<%YQ)uv>r52n$w16r%yBMocdV(ib36WMJdL zLuS7{LX;4NFibYjj8SQux>r$d9iV6`2gk}2DS44row)1@_v@n+o0ob^GfnbxSPyHT zjq2N{F5xpxu&oG@nL2T$?$O+uuHRz15(oXVB@t__4Ty2eMTHN8L~oRT8940^m~z0D zbXZ34&E7ISB;U}BuYJo$JsH^bM#mTvWdKOvK+K1sdPqt#Fzj$M3Q4srC!4CIQS*XI zi{^umjWf-3!A(t1T!OuzrqR~6dAOv1&iSlawK_IXzHb@}Af5AS8+p-V`*zGlv-TZ1 z+FNbTnbbg1n58u%)gkAZiI{FPyI2hI-@BpE&QMgy?&NL?l}mMrlC1cUHFt8^M1JHC z&gJwLa`wlM1j>!gdtC0in8^mKod79~F2PM1({wEN<0F-*%Zdof{7J57S7hT}rz|G@ zZ%=K~5LVJdrcq2gPBrh{o;9mB<2$7n;%W>UiYO78&q%227?^oAM}9^=VQlo zt6zHe2o6Z)1VD*gV~IQdlu%rmMrydwo^AgV00~A~9Lk`$P6f* zKi0*9J6{k)i#UxceNhTvlpumB`lMO6qXUMTysopxZkT`JAjwq1-Jz7lK&<_YQfHrx zM+Lm^K{MY%6NVW5rMs+C3}s*+s!FxZ%nT}yPb?sSjbOi^(`H5fv}He{ILfs>#60;g zC%{HN+5cFGYp8H0Zn#V+w)1#GrHZQ)LsiX;XYz#+?Y0c-vo7_mh(auxf6s{K zX&x3@#$-qR!ZfdQZTrEEt@z1;q4&jqej}L#Uc9&|p}u+I0Bx!Pt~TcDz{wup@9DlY zs~Miq@49AZ8v|aul)dm{nqvR9w%q%WJJ2zKzT)5^)5NKH`mog<$CN+@S>@myn*qfP zQK4=6%%4WPXu!{82REI)^t8(Mu(x-TG~~I)_H*9yCiubl6IZsQWk%aWr_+QkvJwM$ zF|Ob4p#hnVx?!Mm!+h%jP4}gW>>Z-5*sKSTgMZ`J#TT|0m79*FRncjv`g{njHnFS1 z0pKxnsGULq-|d$$^eUBx@Bk7{QHpS1oc~?{lQd?Jy7R0^yV~d8;ZaPrUQ^b%vKKvN z&>`K|sGfHDrsC;@c$$k@NJ5_ecw7<&8` zv*ULrIbDXI9*FdAe{mf52VMK^$tLU*s3p@II>0()X%eXBk&em7+-D~gdo=%k(unf` zA?Cv?u2Trpp^p7rTj_@#Oh@5ieMLs-YbDye$xeio{;3nDvGv1lVxBg6g|G$sWsQna z)P%fO3?Yh?3vEggg}dtT;`=*PvB#29e5>x(Gpq{5PR8_ul~>CGv_*3|A#6*jKo=oi zDc37dadaY5@(twvwUsm(OS}r>wxTb~R)Fvbl(Ix|kO6P4mROKG8G5Z2%?2CgKZqM%lX7g0fmwh=a??Zg&GaWpM8WPH zJzz;4A~aqgXSn1w+>=EVs;`oZH7!iP+%3wI!};5>N_!ntAaJVWqCEhGUFPX@ecr zB`%4Ok z#oE+y;;C+@(~2&a{Axq66do~;2F4oKR1n9cyhYk4i)t$i4*Sr>!Btk5tF zJcxQAz7&5EH*}HJ9t|@S)>Tdr>cD^-l5Ee7D7q_j66;v#T8JLk{gr(HW;MKYMZ+j= zxmy}|3cJ~M731aXh$?Aik_wswIml|FBETI;TrFRz#2_Wr{nBIx0fYaQPV$NwBWJ?7 zfrmVH-dJ+WLi7)*xn8y2V=7vN%yRKx=CRC!|Nk+=lfpa0!ymgl3}nOqZVx zTWk;Sc}Sy?%nrmypW_D3yRMPLiOg3+=u}Y1sk3+!#4hQ7N7K@-7wD}DRq#+3aDw4qOOVRLt%e9h2d< zY%pEA5|E+dm2F!15e<-@fJ?gW!7Vi4Fm{dnIZS6Fyl-ARJ{}!AhIA0)+u&xwS(oC? zZcw33`oM12-3^|*SFe2@2)gOFf##hn-ksq2^A#wyV|t^IU=ZBsKi1lJ4q1wk%bT>P zc+#}~lA#QXuCY7XZHt!6HJ}>NKi7g|uc)2q&&lbvU|kz=#Y9e#(JCX21B4k6yp5)w zW&k=?n5)5A56>>-8tZWTIrw`c@4WsGxw129)T3?RPIov=!tdXZj z33sL8^fkcCOr(qaMy5vkXmlBofpeB|GtwQ(`LGgT!SD=n721oa&5aFvQ{);!!p%66 zq4DdQjBBoHOZ3`aPWd~9tA1cYQtuVzztL3JW0yYqphY#1_7uBEhH^o27Hklu^s%D9EVTbmzP7T-owt=Ow-!B6LZeeS(C8sv=A zKAF#s3wO1GO`W^3}$y$FV}UG-|1)7w@NVA4xW$&r;`b1GuHvvPeWyFHMcouL<=CaMy+1 z_hPaf38l+=pf2rug=twh85&@*6<*Xt;2FAV(3Nu-!VL24Y^}uoNaf179vh4v4N_FO zP8yUD4Tf?nX7^LQ-_ywUrg+_Omuwu!6|eIxls1x2{K$#z4UPLs+mOkpoZbgDB;PS$bArb`e$zbK9bhw-<=B|PF3AU zDeF<5M@DD1qVrroaI@ZiOd_rB-cP3?zXM)_97^zEvL@K-(Z3%Zz>g#ge(Yc?3I-Ek zZ$Yuz^EvAMXxrjYgZ@BX_9hZ5!W^QT=?Yvav$n*uH$j*_h{Q_a?aaKL7aHGMruh*y zgE#A!GK6B-gF<%Q@MB$G1=fTfS+zq_(s3Szc&6#*L=$HRnPmvqF4xV=r%1KE@+lIx zC!iYR*1utp^>EVFW2OlRZ79iFK z`e2Y;0o7?RFUeKPDP}v(tQY%;Aj^e!4Nl9sX ze_#yJoEBXlfh>yD$%2G{1>GfPuaJF~Dj3HFtPHrRQ|eOjVa`|L_)RV%Mjo%5QUqi~ ztfx7-A5^zzueJoE&HKSirZPj6B!xp2E&dP$TaYTx;P$G=d)8V&B_NDa(1S{WEE;pW ziM~P=^;|2j5ogQ#ajS-&U_n-TYt-DqJk>AEWmvhE*bhhvIu1guLN+Hw<5 zX_+lpi_2Je{z%4kk)X2as_xYxdl~9c_r-XT|GU#xWlEQ*?%&;aM2w+=W+HoAX-}SR zlV)u2uHg<4j@T88(#q3rFJ%0CY8m(lcG&j61rJ=BczCHzP0&bjtpP9{W2-UOVyQHG z#KY2?=iz~I-#b2e>@BM@&enqws{N1xT`u=edKv5<8_*hi%Z`(p^>oZ#^U`?&zzts6 zNiB2AXN}%zaaB{E3h_3+)>0_fvl_s0?4I5;9|aY9*49%AJ2R87mR}P}v5Z0I{kZJu zoTF=u1;+0&Vj){G9gX~6tjBrzj*awl3s zH6#i2JADcX7$v!nLBBlT);6Hp?Qm>pbqw&|`O4W$Aa0zd_}9nkD?gi^c#L6;OD=|~ z6llu1{hkZD)F($`cZ>Nm)>9Cgd;vAtS7|DpobD3RuH7J63Fj zendUxJiugZ`t2k{)d|NJ+g~BlBp8RdG zX3U#!*xJfd+_`oHK0K(fC;2SPT}JqQ31KpGQ2~L7gHI|a&N)3r$zjheZ`uaI)bd*i1_iUe$`mN9<}!6wr|Gw}>*J2g_6gd8`+Vx{tY)j)7lq4* z1b!I9_4xB3JTcCBc^L%08`Y>+kRV6KmPh9lIEgCSsgk}<1VcbXexBEUyK*Yl^rC*A zd;9dFFQUA%LYFV<@=e>d2tKujNogP+`oet`>zBvN#gi+eq5Dc=`6$_$|s+ zXc93aOWR(?9#rip0bPV3E0w77LvefM8#gR>X*)p+7A)X7ZTi>047~S;lJqdeY2D^<&|g_g^_<$=TR8oNXz! znPBqT-kRvdX;xVc;emx%7b35BD_@#<5PA4Iv@7E|RcKZ!ln&n6xZK4!n!WrAnQ3aH zS)-@lJIDSjz80%q=*_bCzpE`H7Z|;$;&bze1AXfDmp8<3~JtainS( zAgCeN9!YLk*Ub56vVU;OKDJ4*(7w!@5f~CFXQp;bV-md+V}jbbA1b5;M$9lkBED7L zGRPLfJ1_R@w5+IV@HEeKeCG!mRfP5%=es$4}HC4=^o8d9blfJpU zl?M-;Bsd#_vnB5gJa;;x(uD_Z75_4p3FT`ostn<-S6?{o@ozeSx4_43IRVl(;apTm z14CJWHE|qU2)U`y7zpWEtKy$+wM8YlNp-nO-P`|b(*%8@V~r^5%t!p&m6WW$u|LdPpKpG0q)cp_7slcg z1R_xPv4)|0Sl)x@wz@XJm?JBKMDQX;*Y5hpu=TEe?uhSV_^^tC!Bw@Nf5tL_wbNol z3zg(NwAM(irq^Y`b*h&*bSZSrJ}At7;<={|gevnciF_59Jaw7>Rx~ZzZdix;WPFTT zuhBe#gE-jJJBVtATrVfKQ%(oe)kZYqV;y^M%Ca(0|GK3=aH3tueifu;VF} zhh=HML7kQUuChJPchOP~ykU__B4BVSe>m04f!=y{iHmXTcLmYA!IbRy9 zhXt~@hsMK3NNycJZez5?2K1HoI?WQ#>O^8?IsvJV`&a*F`fo~4gihzfI}kx_{GO`% z{`TwCSm_44U$5*WPk{&;hSvu=WuHLOQl|psXJGI0Ou%=|2Gnir!!3dHwasjxx z4@jSOg1f|Q4OtPq=FtmdZdKEh)laJ+`286l3p1;V3`ZTA!`-dO!UReNeQ&H113;*ZdWfbkKo#@N76yE+&)i-or|m6>j`AwYK{)qU4$O%w9=3JLEhOOg4=e z9;m{!LEXQs^-_VsoeHM+EcM+wg>Y_9heE8}-*cFX;vqEZ0vH~p6*+?g5*u9WT0#-I z8TLUVCeic;W9M0wa@D_`*R4ev90+N6S(w!eYa%o&8`Q2SiM6#1ScN52VdE(DnFEZv zGbgwP`CN(&O|GengyF=&D%Ba9S0%Xa338mUP1iz3M%Ls%8n2MtO+`Oamd;vO@*UBA zdm%Sbj#E3y&T)-`i5o6sECodpIm+Tyis7$epcbVp1LM)TxK}-iKHMz^KGE`wylkUe z0e7h%3Jj(*)zNT9ypKh(e;Hg%+M$g@*3?*nkHAYH^Ck2AY&~&kfBZJJIdXG!NK}tb z_+C-nB!DSTC%?MH;ufw(;#GF(tNZkS%A&0aF&{)Xy(+1YCk0sYE{L64un7U`hl^R> zIuweCHAxM(9>ZY!`1D%WoV+a>@dbsz(H5YExelb z#|gYkM+-ftWG+)iw%u3;;4!~C!7+Tab_RpY;5jf)Fu0~=kk2Q}rN%NinsU9-q7qz0 z-1nF!wX?4OMr=MLmI>e6JVeF@>L3~71ub*HDrNUYs&r{62a3n|FLGp2G5k*E>WYIY z)a-D#POa^QuhQu(;(pjOLZ8T=rvwyVn1#r!tl6FH8P4|F`jP4d!ip5su$MWu$8dplqUUr#g_(9%9mW7BV#@#%OHGrN;L8O^odmT6h;v1aZdoRG}}D$6=^v6k(Hj{t%3Uynyjq~UZq zb73}4PzyX=(*zoXElG2wfHuBo4tPNcErRPSWFh2D&Mh!toK`}erqpYgT7U7cX>>D< zNx@J{qU8*`79dJ6$bv;uv#LO!qmx09Kc26Y8H8ERvU7^_(fd^qPJIZ~>hI+rjWut# zQWJF&qJ^61M*+%FgdS7%lMBDAGz(vsFseFWPi8JPHGP4%q)DFN)VvmOete7ozncCm zW{C*7!0e~JBDtMpDU}gFn+?Ep87Zne%rZTMjbpXmd+Ag-PGTy1hTPgWxzR7HUsHhQ z6Ebc$Ok*6L@K)1#;ew9)9C#$n-$EhjHMVC5%> zRbZsd_J>rzFS;kYz!4bUjc{=lX|PuKH(JD8vHu?MW zA>B|ckTYa-A%M~9Il*{+1h8V67T-w8J@;N7Ugt95Q%%G5w$4nQnaTj*V}5}6?kj8Q zT{IGmvlVS5$dYBK1;3y78hh>Lb1soTRbuxRl|eyFMQ3$?u4bF_|3+7%Cia?yjtViv3g z>aG$XFOXW~Ev?dBHuSWt(U1$uE_7_nn?OV*>;2&RJ>EXUNRdC5WL*R^Ijft6sTPtJ zz-i=)QR$37KmAw8Yx%Za^};FrSu5J^qlwKvWH@N9Y+D^KW#pG49>oi>ETk^9rCbLW z?HtdAse|&~uRljexPaBEN-+9f=_B^NoyOZ3`MPr5f`&0%$C^*D0`&INZQX^=xgE8J zh$e#PdfK3@WjwvUby*7K3-v4fa5YM$3m>OV+#>n!Cbn)4*wX9V_eQoLs`{jHjY(Zx zRt?OkLj5!}#txD@STS;XZQ$n=) z#Rqf+#>A{bc6Bcp!m>}fRKzQ}rnvK8mG6I600nbgtvk-VBEJFoPM_am>4wD4wEAuu zs?Y39lu|tY_-5fg;cL9=JbNRt~Zd&6TG$;M9+NnhfTONSv9+_*!QrlNu<% z8#stPoHo`tyTMVqji6w{_-{yhqnxU@BHFbl&-NQ`-WMAn=t`LkDIG<|dexcJmAg`U z`}nkT=gSe)?71^98a)fY2(xTSJu8&(#$#SE52U zq!|a_5cSu844UFez@f^u1SH)o|MMnTthP>nT8CZ_kUa}T9Y$bpzVxJ9TYT?Vn zZf=(?+Tc$>vN+#7 zVf3?RG+!wUC4rKE!j0{J^ma8Q?#W&}3%?bypNzwds>RZMKSIhKc^Q(^bdCjA16>7* zdPOC{TNByF{!hsX2kL7Df?J3(o^T>K3*vB?Yl*vzhvZ2&iU_cHfOUzjS{o&&;y5q@ zL|lZBqP?~+cU@h@g*BNf7`8kTw004gsMkVH&22G(XJd?1>a=?H6x+>SsezfGKrH1p zDaadoc=fzvJGd^95vnUwaZ1OQV+1|JOPu3}l-SkUopTL?GE8j-DXD1cD^L6hpV>9P zvZg<_y`ZUWX!=j-OoQ_(;w`Z@ZC$1C=Y5W=$ZL0DcDh3EUMZlvA{t)@)enGxGKH-*cSF?kQ`&7RAYid zdOi@*)#dKwhg*c);MU&9*T4&*lq@Z7GYb&WOKZ*&YSQ$DS(BIb)_g?-s#0pfxO#|R z{HuD0`ccQu*NeU(<%zr!UZ++GF^3W#RQ09qH;FCfKy74Qc)Jp_Nv}C z2y_L=D^JH(D!>Hu4N4;vId)B_xMnffgaZAC+2=PBAxU3lE?kDYxuG zINkaIx5uhDQ#{?m-A7a#?y%%|ACth^v-bepE6lqa*~S)xi5+khJ?kTt5SKj%F*66Q zJP}qnj`z8ifqX$EIFz4lQoD;`&!N0qYT-qg2zOD{(lp5wL-&p_3Lg=I7EEmi1B`Rh zgM@mPUGUPSG5FV}QkNR0nhbPs!pv?8Ht@bI3Ia%i;Kw&;p%zkDmpr5ix>f1(Zk_oj znvRqtLG{zi*y9YBr~8Fe4%PZ%+}^NxrL+>O6F!*n08luxiFg9nu$;BME9$9(gQRAQ zm0RN%K`o);PmaoE3JUcvU-YZrOgT=EiIYMhId6nYU|hKA{O6Q-8bxUyGL!?2zIV(R z7)%xq(T(nV_4@N>BgxtmOi5ye9 zos(zhqRtrm)>5-t0?j7gnu&sGPX8@gQ)IzM>v}2sZOYX55AQfWkny!(t0Er^qt*=> zR)1Vk(N4o5Eml8US8PF1(0(Fp`w94#hzqn2>C)Ue>As%^>Co&R3uw(9H#^;e`EqxX zVN!^i=EYyO_EJ{`^oKfrnw8yht&f7Em9(e0s!v}+NmDk3PJdgp5{`R?8TkT59mb?m zIrQt6<72ZLJ2Ir@>Lxz!NUq*&!K+aUaQeOXMVpc_nx1aD0f&45xr+Ph@R(>y2;(~A zAjMSs)2+ejqE;j!)2Z>jo&ijT-21dZZ-Vl@K5oT8MHH}SuIqbL%EbkH1)2esX=ICiqXmj^N_IVjO$L6LhQ=7&T?&ULM1yHWQ9FM zpmGo&R74rvXM24({-J+}TrF5J{M(RgGmlfF7$LyHAUJ{QP3CdL-MgpSG?S)!Hu5I8 zs#(NtG|bp#)BJ{Lnu??Rm*Ye4`)i{UY#{7NE(MJVRmp)3CR4b~fCU+6hyn+fyK51* zebyoufGSwThVGe4HcLqHLInJ&A)4?gtZY4QI1*PfDD0FDs)DRlKx9&{Q!v6!i*ju3 z@_VE6pd$bZ3-hMBbqgL^FwFPlPI&@AQbwE%)Io@=R%X9q_7^!u3epxLI; z^GX;|@DL(wIu|i%8Ud2x!_uAPsj(xU9*YqXjWE`Ag(WT+v3n>7@>cr|{tDS~q3>KN z=dj5J3b&3!S(a^nJ#Z~=!~Z|)|NnpoH-pGyucOjL{v+eJFKgImzD4A2?_!dvBrQ8$( zbgXR!aFqq%iUZ)P1Hi)a4~mKT;}iBG1N0{zhcSeeHwGEs5E_^*Z$^BD#g&DZqDnjC z{QH2)XEOq*e|mai{6m0+Zvy5LnC6%FCmbJvw0_fGfHsDbZ(|Gc*Wv!90_llQiHZsW zfIq*zorP?4GHr2dL^jX|Z5Pt62C&pOt53pO$G-P6_D39t{a!P#E^h{ap$dP>gLUzO zLUW5pLch1J4@nOwn4Kf2m3OK~+V9}x*HHz`zXk~Xl~8?8>W6;6vIn@XzV<8oqWW|r z1b>dxkI%^H$pHqx1PsswqQ-C4_itZJP4$6xwh{ap_g}sVv~Ox;baZk6=8pro z?`EpnzX!t1jot6ZzTuaZXLkSKSnmd)&K(E%8ldi<=O^EjEnutfAC*M4K6bSi`zKm{ zeGT9g{@)EUvNc3N;cwE<26XE?65n1Q(lHKy-i?OuH9+fLUf&-EFV*xmuI1GO+)o@8 zsHFK+c}1Ver`2&^&f($f9e^(Nb~XSitgR~m7Z(|ye_9sI{?nd^GJkyEr~Vh2DypRc z-2PwF&Y9Dv+?1`Kh5v6IhylR28!gF~*-0Sa^B?$*e@xcQ^+(jtpT@0U@b_QEw_EC8 z)%;%@k%gMp7T@=?AL1{cZ#>TM>Ji;&lcSDKZX5r?uLoNGpVSKIUq|QRYwPLXRgw!J z&s`w;^5W~AQ82rd&~Ctt3O=o=s^8>^T-WKHNK**^0Ojj!{GJ??e@ITuji2}2mWk=p zw>LYV)gv6*yNAbbS26PP^zQdts)PL#0Kcp(KAdu^8HIzr6L9x>-r558_bnU>uz$6@ zSK1kT|C2p00F)Qm@*dmd5DY-%59?2ad!ETN+#wi1$**X)H9-C|UpNjx@&}j$kbmP} z{uyc6DxElOOsV>v-S36CLYcpf|vOAp5?Po$DX}>)Gya%B4q1!0R8f z*C{XG=bs~=+u40w))@v5)!wh(Py?UaSKaAGo|e-uns==IhuP|xA+4(Hz8@ra6!7_> z?O&b$nTGZsNS>L)*V+Ql(%ugg@7dEk@NZhz{_}-+&+Yss24zJ;vo> zcTa|X{Y%;YYZfL0qFd^X!@++t-y3F7)H;ze*flQbV&l-u>VB3os)pkN-Rct>iq9!F zDdafaFq#)}gPMp+o3~xKQ3y+=Et_(vq<3H>Jh+id-lT%~M)U5C2VdvsRml1PyMUX- zq8S(GlOg$uu?~m3G!M16j_WP+^Y7M6S(Z5NO`#2Dsc6$?0saSSn_P=mYyy-*C@2g@ zqSpzo>5Zu>jO*+OGRTg9q{?}C4A~*No>$lnZBDsVD45u@JHpJup25cVY3oHwbv?sx zipSu+o+-#96Ct7~8u1u2Y!S}-f!H0E6kVtxlcJ=oqTp{az{HdEZKZ-o)5>fXBVn&L zD^8pc4Nh0?QDt}=F;Mb3DqL=O4?IPbW=+|F!eG|gvC8a&i(k82iC}t*QG~9yAvY!7 zCmQ&Zc<SxR{k5E$f-U_VeWJ46UE66lKr zmh<#oC?>J^g%b;4Hv<8b*JM}->WPc#6zm>X3!5w*v~tm9yd`j9rUHdhqJms)cJl|T zeVmroU7&R7X%|6dhD_BU$Da9gqQ`ec6&%Y?R?kVWd}dKuhEcJq33O_kn2(litv)44jc z6*=njI0KxV9=jxCk#kQimZ{R@GC|@F=U^&9;`K-bJPIL-`)J*86z5q2%Nc|+o~t}+ zsvkly(iWM0+f{k8ZSr`R7KeRrGPao3=2Q)m$ct7oSlCoI*YT&W&#X?pgZ$|zNIXp} zqmH)}D$ptxowPz%(J%G#Z{!>4cZ@oIEURXN|4nOnF8h*34s^Yu<4fkbeEe%m6-+KP zb{=w$-t@K2B1S9|mr3X_X;Jm(enFo$GyqeN&`{P5GbA3;c60o(&CtMI62S9siQ(9v3Iq6|7B7 z*hs0n@vZ59=yw)jMffe_L~Q1#!1N0;TrJ~`H`Bxl5qa1154c(YJ%Oha_g5XVztMi8 zmUJ-Sm|@A-Ba)Mpji=7OT^1|>40L;#@)oO4+=WVoc$^-jFY!2BnfV{^ZoC=cE$#} zUM6Q5_FnW%JJ$73WaK4RiR{T~-eW|RVJm&&OZZZCRU+}JuZs_e*-8m)h@41TlO8+* z5111&j=|&LZ6mC85elFp==)x37%B0BSCA`SeL{LJr|tvu@I^?&K-SpPEeu(q8B&f) zd3I@m8=bgvXJC(%v$Q{t4x7StKjs!x79!RedSy^})Vq4zg)O=2izi2vMJ3qfs3Zgz zY5Wqh>Qj{48eo6?#k|WGWiSzW_#7T+132Eg<$o(-)i4CH*kDbzAv$A)NeyF=JGND< zJ`XwWoBtiKrRw0^cn0|)Tfy!xX#hT zy551>m7b55pUs1-9ZCKNW9JMd4AX?!@yt86ZQHhO+qP}nwr$(CZQI;0`On#4gAF_A zu=`Y1_q~tm&JriN>|KZQuzliojda)d?yjR?v3DRa)-watjjy{dS=GVLeEbY||CQ8< zqsKw;GnacMV2j-wgSz}CkR<gX_4iw9tPaQglh@UpfkzV z-T2k}+H>5u#mkh`B)>|^+I{0(B}I$hDq%J3X77d9s2HGsA}4}W2~XJ=U+Ga9L)(eg zhqmb?90N!kq`+Lu4v>l*gH$BFA>5pqHe@ z-CHJS$efUsKt&7fVLUP!7PmC6tuEo9J^)LjBwZ){C({pwUCwXD=Cpd38GJ|U(1lP$Y}>($K53{!=Ttz1MWe=WmO-TI1&rP(mSrHO zl;l!|#SLuJWG?t;7>*(zv54;Cs{$Rr+UqO!((mTLk5D+0#Ul7M6bNpY1VNZ#oaN3A zKZ)?vK$DP1K>r$LDRbC}HU`Rd%ZW_!bG?>)$Y3%h4$5BWULIy30w-x?)D6B8Xz zX>N(9mWYuKP_GM$+kn$Ket1oarR&(=Or#K-Yv#&%M2JyeExWCs@mQ)vD9_##;Dxd7 z_X#ZW)&C@O{%!^%ETzA+Ta!jYq#G830NLEs8DCZlv2uOGZ-se)cWHaS-ChKV7CrUM zr94Xr8)kW!_O5_*=cfRjGW9B`Cd@@?`E9QKLE|E5`)Yj$4UeB7YfV)==t4yf7}DWw zCS08oSiKDI2NHElhYT4Rh|@u%KSWP@29qqZ-9}JafPqlt(!8NVfkGl@$1}?)L=|Fn z%Qv1|=9KyofNB2AP3#U~1V5Ej=|AQ4*R^QXW$Mi=!Tnx7I8H8J0FM#g zKP+`RyKvNC%+hH~E;+!gpDNk%(-FpG?ASl=dcQ&tfW!14)wm=|J zrr@ZP8QaY>_;gu}1gFsu$@3{9_?hf>piOK-67{z2qs!|Qeqr@0#56)>LYvo~WuT2! zDdZTHB2$yvbKe$yC2_i}UX0ceaV7CR%3NVpb3tA86wh4cEEE2ZnffuyDx(;aSE*_J zt0YXy@m8{*>PLeztu(pnAWg*gk!lucd@vSRT>Y|5@OVy)Iy*-|PVKG-{W`*Mv>V>1He<{-%k?nZBv+ z@nC{N`wEZYX4>Oq#2bF+e_9)r2^q~z5zS*J6e{X!*T+ zxYDoZ%^^^W{_ zE<89)kImUcPUiZy%C(!Uglm~tO9p@9QEdN?`hq|EL$oRX7;i-&kZj@0MDHL|T4kGo zd9Ql1ng5?G+}X$~_HdpHp0ceeOzlKb4sUEgnYNXgcM4= zj_Md(0l`w?(7K1z>n(D}vFyEmkYR>YgPr7Aj2VhQu7`)YwA1IL=GQ@G)Xf6kyQ*_5 z>jG%px9ID(8T_TlV-!jIZrp(!wdUzQ)2AO}&TQUCS05X?=8L_U^saN<1j_TC=`nHn$-vJz1n$))T!Yi}THN zFi-9sng^Ty_I~z<0sjw@z$-2W(|E}+Fp!oPC(Gq?RY>cvbY{}|0Adw=nLW#;OK;)a zU|XWVEVe|J096ut5H^{bQ$mZb}WzktCYLJRHYqW6Bcf@Eu&fGZxgNN5Xk_ar3AmU zL+B&~94E|CIb5TCHXFLC|J-p$1p33uqXXqHwmF@1&vir{^m5GCZXIYe8s3 zT}lQ*;ZVZKN&{~tXb&fQ-aBgTm#a+{&%zcw6rSq>O*gGPK_UpjhsXktE&z=v#gHuj_cbAm%0BWApm|WOq{zk zR8_y7*w8O6acfxsqhtbLT6c2krYx^{@ik5)H3=D9wDT4KMruz} z_*BNbS+~>Iwc;);(!F$d0~vkNs#2&2{ac887ww&Axhzq@~g)dDTpfsp3cdf2AW({`VW zw@S^?Zk8nprnce6wrOH5YnRCWiH8U@SLoBFF?I4&2gV#IghW$>X|dJR7U{*E!1J9+ zg5;R()I~^qS=KgZ6G+s}R|K{iAjLE%Nd2&f-C0lXM)riv5jte$G!Ol@+)zJ60i^!= z@0gAb-2;nDLKKZlYHeB-L}T1hT9w7)p@hY15RbpcH}lUeJjlfS^93QO6;_^+Glj-2B)Maf zDeRH^#MYDSvCR}~bL*y!z7i+O8?njSsoj(D%V?!mX+S~Dd+F58O-z|F$tx(N$DKMn zcC>xXX2W1ub%o3Yd2YNSt@|)u$%zl@v{CQ(GH%Q*AaR@^)UF%$tR_+2|cdgmTSOMSF3$m*>v-Hkj8wGxG+%HL;G0O@@=USyd1p zhgHYwnsKKaTUBjA4m(3YFw{fDzSq?(r_D`wV*L?-`(2wXMWp$yq%2JMVn2|SSI$#A zwW^pj5Aen^05Bcqov;9_aF?)2s&+GAw2ZymRy1u1@unC))gi#YEi;SL5n=+c34O9{ zm|eRa2UDr>FPX2in5ww3xhZg(R2*Im(tU6h!MK7N(&GsQ`4CKwaaV;d^5?yihWcr9 zH))+J$le1AeOVji2B+r*1`Hn=6X=W^v7wmuI#n_NJJaEQWv~!iX@c7Eq8V1~@up{V z`cz+HM@M}b!L|GLaCvrGXeiWAc%5lzxp3b+9+tc{p*`^*GiUBaG;TQyxYx~wC zpIj@5V7d6GeS+xn+AS?!|2BYAlc+kQg%Yk9H!5eX*q|sjh_|QVXyq|IPwl@v@R))` zi?jBGj;TYIGamceqDBnXVHiqpTK?~)I>&}p5eKS%5bra#Y!AP$wi`~zdY)e*Pyt`z zurBEV#S|#U&HvHgO;2d+{7NBDzH2|sEI0dosydSl%x#<%Dj#R5+5E9raEj<|kyVF> zUvjyu(iFryXjpAE)=P$|4GR-M=I-Xi!{|tNz zlcd9K@I?5Tr@`Uo<=Y#7<->|#G$Mg zVAMpuz9m+CfqAiA)Y>)QD{nE}Gfv+VD5#-8ADsPJ7A)Xm{8!BlYP=+O;UqX<3~z

OGgu1u$O1Vk8p2Eg8x78RfDYfwT=M$($)F1qr4Adei^t`c(DNG}KC(isc`G~V^~-1e7b0By%n5sD_*JB;A2=rBNjrv^yVP#tOhc+mZc zP2R6m7RId}l1FWwP|6w0BJ@NoI%_7SWq}PvhlqK6hn}}^%SFH}xF{Rnfd;}yZE7FV zi06*ath%n%@sDzfI zS*y9fbp}h9U!(2p1nW=T9%+0qnn`U1tk&F!kn@x`e52hoe=;@gT|M0d(1O=I<5w4< zphPPkxoR%nQ+UdOTLKJ~H)_3Nf{7>nRrNS=kd|3Lfs-l-oR9tqHvJsx1m`P94uONZ zqVm#*qBq#8sS}AMeMQE&!5qis>m_G=E$9z4k)4g&9X1o1z)CEEvRD+t1ny}HY7;k^ z5bmI}m`A!vFdal`YG6`MkJpP#k-4@AuMUGpAP?cDs=m-OCPHBj@WbhYsl1N^S~x^Q z7uIz?%s|qKII62&n#?Le+Cf$yXQA9)z-g)qA7b3d;htMjfNLirt`Gu095OVJMlto34kl=Lu@#nReaaBr+@kC+G#%Sn>ZS{of12_t$sC8@wZ$Z}p^eCOw?z2wcs`aEWDlEQjfd=Y=4v>dwG}(y0!Js8eq&w)n zLfcZO%n2z})du?ohj$z+dq+-?|r!w|bjo%F)R)QPyX-AZQeE-cIE8Yfs0 z43m(8xoUSIguaEOEFnavOWC~30lyOUTn=@?GH@x$h1*y1Ov~?0r zshn4_`NGDu>ZLm-2fSG|8eA{}FPkKe_1KX~w)3&n3EPT%Qn;Qz@xq|}Og0o&n4m)y zD7^8;MF`LKR-}o3AyX)@HyL&{r!RZBqiRoDld}V_$J?pwF;f5Y`A-bIU{OAWhYm;P zAjb{XXW$gNBahE1vgHtpveb;F(y6N}5*TzC+mm_)-#02)LHybHCtt+%`K0d%+N!Q( z`lui11(hi?{USaOR-=&!!Xk6zJ|M23DWs4LSO9OOb+N+LC-XvP-qj+k8E+&jn7X}=65o3n%fZm{T9AkBoKeR6^$p^R&tK zAKZ%tQI)7_>inrCAx05g=yRmXVoMd@_a!v61{>vb_N4R82!x^HVPcbLpuin} zAr44|!N52!6|T78g*!(f$*yhiPCJxh=W@9|cHf?9SVG>O_Y*7^UA}tRNzi-Nh?`T- zB(52)iYWF%qN9gT;x-2alZO;%%`F}Kn6zNFurBUXtD^ETjpl+h9^scQxWm zkCrNerYMcdN3?Of!jzQ2gP(+yFXi^@6k-;N5;Q!;fdWm#BSR!-->9E4IKhY!RHy*S zEd?|2PNoq6V z9&7rifGP$c>sS?&ewF@fSiRsH{?LXmD|en%NoH59<9If9W@)_(3dtgh=B%bwV}!ou zFG1v9VSERyV@3l+J0&39-)4s)Ng7)VTqK$iChyJjj75xxFx$R*4S0NJ=~4}L$ew?9Ak^y*=F8lko(NvWBfafQ`11bx-T4n=QyQd%eS7 zuxh6t<$C(ApM@?Ug{3u@Vos`>e0B;Q%a_x|cDg;~+-;psNW&L&O49V7os8mScn@!s zK#IB{H3p!Dq!9?a#mQR#;exfOKPhCxq1BvnG@!qj@TJp*1}9c0LM1LTopOsN@%F$n zo8MQ;YC&4>sPf3D#m^hiET^b?On$qD}Ur==?%k!p%R#S6L|=~ z;J}$%CPhm5aHkr{z7{q}Rr<)t`+8<}abz_Qs;5d(mxm0uh)4uuOA9O(J;SWHxqh6F zp>ZcjM<6`}T2b;kjRqp#a+6@8&Jo}&e|9fpQYEA2cDy}Fab?t)mN^$IHCE;l-}ht{ zUYx4{NI8(*#X{h)$qzkbkyxuKvJ>V5*Ys|nPYbPgMPxVG`xzDraD{dIPO0!0X<2nu$niK~kB=ktc9@x5vffpdv&e0s@Ua8 zr?Djz#WW-g+YdQm_zHQ8<2$_-Xk2u5M}^!eTa+7GR1qg%*;aVS#XH0K*q zYOI8mZ?2i&F9O|J9O|Ua=y;SwL6L(iv*||fu8Km=dU#ys%5cPRxc^+g;) z_Jd-*OHmiUOPiP``h}N@yEqH?g7_| z?>qDf>v$(UP8Hr_)w4MfBOCiQygC)ocVG+~q-S1tp88gti*_7D8ibT%~_ETP&e(S9f?vnk=^ z-R8@RG`4<4JyRxUZ!Se}lzV02*?Mj7qaC4?c758E-y&$olUPPK!UtIUu*PREmN$X- z5=&WDK;TT!=%IToOzR7QH8~)7$keek)-5nx-8GeoMoNj3P8E}xnmtvW?F&?vz4WkP z`eWcYrJv05+7K1G=(jcS(ACzc_9?E|yPf(R_2jq3;#Hy?1`hjdl70yc$Lso++pND}R zqc#+M=W5x{QGGi3UQd}F%4G9W*2Y|rl+K!zy?PE{OXEegnX(CoEvA8;VS!!{Dj`-- zs!TSv#T*)0wO(@4mu^yg;rlHf4T$xC&P8}F@2G8bQkRk2Xk3}1sg9)X>H8==OfD0=7=+Cw5P@VF z?kef;!EsxSUme|$2-*qb58!PREEz{+Wt#O--g*l1t%uGQLtNb@Ph(EM?8v*sN?amUSeY*|c_yHP&68g$ z81zmrPR=ZvmkaGvlJt2zSC6i_wgswTIzrP3j)FUkksG-+s9R3P>2xd7YLn2%lP5vYgN zmSGy$kY(!7-s+EL`n56~@g+LH4%$n< z^x#sevIP29fte${5MD#O<^c-OPRj;Bv;&s+^i>~{A)uSStCrC-?8pcg@_ZMssk?O- zp9c}Aj6b>Oz@!Q2IoWndU3HwS|7H8_vOiNKxJ@(%QgfS9c{-Mm zbo`1_Z`|3@5DQBn_1PBozOjWuHgI-Uy#U{S19=)!&}<%%?%f|*au)7P>*U5FLM{1? z36nr>>-aJNgLX)yb?si05=?j>F>t-t?}A8M2K=Dpgpf$sN&jxj{;0_qg7TL5S{ghP zjc)Ug7Nr!+LW8${UXcZ8*45jVd0r?-00#i2qiEo zB%rxjE#MF3hNBOS1L&a#9zd3BNRagejjINZ?~d{tlHiEEmbFzQc1ljlOr{6fDzMuM zB6>2yZ+H{dmfh(l*$ZCA6gFLiHH9xttsroL%2#oqyZ{lcOH>{nqIu>TpO95Ei>$hK zVWvr($+e1#cMtLaA_ODW1w#3Q7$&yqH{Ld*yz(E&#M553sVK<9{%&2o&tY62+)?q6 z5yPK8QX;OZ2Yy=>%GF#W-5ywp^^u0|jLD|ubCLY+2cCj02jw!1&0gtz zHLPlF9^Y_6;z@9NPB=>nlV2Kojo07tb=JjK2F;!ahV**-3qBC-dF50u1pO5hN8I4Y+FC! zn?2m=u;Rd&GxHQR2$$Ki{l`F5b|TzxXP#~6X!DTY@`$#Il!4AO#hHq5qy%iV!Zd>5~rId-o(8WbF|2XniE` zT#I>=kXd!>B6Vk6Yy}xte&IO#(qnU^YVN=7jLMIJ4AXhM6vwN%S9miJgMm~pyF6N= zadWQ5+@>0knX}p(PW6~!wY&`9JF-H8wA?G2o$dvu(0_prtoct9BnXt&COwQ1ZyV3o zeTbK>W;RscbU4g`+v#;#)(U2!8laB2p$lN3(DWLx*vMA2-<(~QCEsg8G<|ZYq^rG( zPc)f+rIks6gKs*%AzdW$wN4O!6za;L?ZEq@303Xt$qh0N>{tC_1X(^^3B;5eAD2=t zqaKVfn)b9G4Tm+xA!-n5Pi{;#FoHBR7akFfAg-k3Mt&mQ2^eg^icVx!veWsZr2R8ZDK=Z=p9bH(0W^WJ|JV+7QJ^_(o9>(()BtpSZv( zGw?j`}w3UGUJPsvilnW&z4i;FBXuyj$@~DNuA|bL#Fk-N^80zvsSDIj)3xPkTuQ33mK^ zAQ^{%=swg5a{@x++S$E!LXg~($^7rxhsO+Cw%Due97eC+7i2AFXpb$y6)erWDvWpm z>P~1V13?%~md~yjr4X@L75E}91)-)4HV z-!V+>@w3)0vuw`>KnT{gx_0gp-=;`W$)Um?m$NPsKBGPUP|wi&@B;>Gj<_f>!WCmzUZ5ksi}xK=t>sZ2$ZA|jL{xuWIdtvv?7`VM;n7-*bvnS zqK#wUk%t(3|1gTy$Zuj=o{T))oilR&kkk|47d?OVtr zlq3tMMzLNqPfW8OrvYpu1`&wIp89jvOwD;@!iuKSMfNe(LG;omub+xqTkv-L#t|Me zEF|44?+}3<;bRMMH0DLWaI(tywX$e)B%}dNiG7yT9rr);Z}mJEMV}S{a;cFjWK`HB zt)U*zUDJBkOTw)ji&obTwSWc(m3d6DZy9;I?>wCi21QVjrua*=`Z){+jfpYXx^8>b zFdhbRMxoJ55)H-ap<&f&X0rmUEWTB2SQQu+K6LhCsSJUzA``{CuSBBi9o@lag){3( z^mOCzm{b5y&X%+BR=S-3NLMe6KoWce#EFF17fjiGsJfF(AOKpeMQP@k> zChJydoG-7e%rt)CKT)kERbre#TP{Im6czp5|U< zVARa?wJw5Uzk4lf}WHGoqSY{1bW53;pXx0AU&tzUxH)#ZzL4 zFaLkyJpb`I_;!Ytklft=BX<77d01Ik{w5GV-SPF{g3Afc6M@rq3MUAp@m>~bQBjU$Y~11r6?ePfC3W{7k5623js7-Jc#h&{KLZHqQb(^;xaVg z0`0;6Ova2@0fu%6=*!RfxQ!3=;SXm?!3DQDDu?m`P~gk};^6?0kwGCN9`6C%J=}$V z9fJo%03Gq=!fE((pz?u&0(TzLO$=&z?ZbP34{h`Mcmbt5H1_ASd zUBQQV23q~~NPwC7Y4`c0js}gu&N=wE{{Wl~Tp{S-v7y_U*oCb7<=?m>!Ix2?!MAT< z=T%gJ%{v1N{Mf604*CJ#pX>qt+q-x0Yy1ZZ67WkJWNocaTZ>-~2Vx0VAH*I6mQP=pJv{;nEz*AUGbslP1irPM(*^gIH{%jG*quM#r|Jq{Ub9ojXw9SD@lpWK z23Oy>oyY4&+WohFJpkbk5C>5gpN|i44F=$~#cuz%$v-!S@{I-Z%ec3)ALks>0d##k z3GgL!-S0-nUCcF(1kK;i)Bii}2lS_V02lzE6%GTW57QdP|L}|SGYj4NW#qHw$3Bdu zKj}oqhwp#3_Vkwakuzv*Aa9oU*ZybA&{kX88e2{Kl}GXiGdbSh4JakB|u7mg1H zFizJG2ak9N`u@iij|%Z zUy(BtE+B4J7vBD##$6x9A792_bU$xW;&LS!rcO{}^ zpS=H?hbylOdkc=2V%4A8op0#CocSyTF6DHnZSLTIEs^81-JZxjS6+HPf5;3Sg*}=? z<(_w!E9hq3zS$b~8|+R6F1H{rLewB+II~ELJa&Z-M@e+WA9;2d%845f-))B54gmk9#p!05AiL>l%Ff$P3!z{gS=FIy|uo6iyAW};u> zrE^n2Xz>7R)E|Ka?~s8{p&mAb-le^yhMIy8-#wiuMDV=Kku#^Lk1G8oZd0K5+;w}+ zNPZAPNQ(mtrOWdtVlIpaNuyo|Dc&>eMxMw7OGI&Vbv1ZE988uF%wFTjjHq7fT*o&~ zDxpiHywFa^t}faxQoqQW9eYM1GiDAth!sho%GcZeeGrF4u3M}?32adTx}s5j8)OYC zor%vWgT53MHuX2*+2NXkEB_8lZ`@BlR(~(>;d%%GT5oq>Y$%Hg47e#UICjQe1t;+H zHtbRX6vt0R#bp-VGT|@>cW}~a)Z5-gDnxsPQ1h~MuQF#6jM9`j!!XVQ1snL3JyTx) zb&|h8?~opmL@|z>yIzWbTO`b7?RV<7a!|pY7$ROYD_DE2qcXiRF#C`sM0`YM%E(le zW~MP-*0^Mxptg8`E&CgNA0|h$HqR_LXA54uxc3OOdqx(u*k8n(?kfWvt_z!zM7>zU zG^$&s4Q*g2v_D(YP?~~IAn3wvqcrce=dsQO;Hm;s2 zh%OMZlll$?S z(3@tHMJlOP?AOan5Pr!vvrnp-u!e#7RbSVHOP4D7UN0Bl@@CR=2`r&8O7M@t3%vF9 zpSOto6KySo@)yaF_1O|UMdeCQxV9=|XxW~8(P0zbdxKd0hn)EfjA-H$udjxgRNn2W zp%cqobFuXKeWyi@m&gG~wf6)@iB_CI8e0tBD1grI#{`^)uT_`)3ZNV(xWU3RAt6^^xD|et$mH9^V;wb*0h@{mQ8#m4fLwXt^kZQrm|kw zVqs7w`^9R2vC_nG|5Je0Uvxj6Am-kNCkMiqH3=%p<771|6UAkz@RNT-Yg?A5>q+TN z77iSkkJ(xRDAU{iaAQ*U3eIR4E1$8K)F*?K7u7}8{OpZtZN)4Pc!7#1*Q+Pv>k_K# z-5~RX6g1Uc2vXZq#q8!^b(s5gjSLU46gNA^nmMf8XQr#D=11Vcat$_n$rKB_#&GWX z&>bS~&5xl3I=oWFvP+ zbM~zQ$jqgSc#&2S>@f60dh!&0niS+eYcjRXdUqAs#i}$CT0lWgJ^R8i6{?U!R0hUA zQqqHHSp}C1geaeKovlhkwiCHT4(~w0tkr;{Q9OK7WqCSqcz!sxWZ@+q8;|c4x*Bh1 z+dX9)ldtYWbZ1n9nG!;`Lbhm6}+T?I^Sv`+DTx1%Y){aa2-MYbm-3XAch}FPS7Z0$^Ax3J3Am4k-{VpqF%L(-aoWb{wM-*<}fj|pf@dT+A{$viEF2xtqN_&w@vS@ z==F}p%OYe)&+~(Y`sw?onc~XPxP5F&TB`_pG`0A)wA+pJMlh7gtD-fsuH^h{!n$ZH zi*zV`g%5c^c`shNxSK)s*z2$f*Vmuu^?i_u{4V|`n znpb?}q0MWHHxlZ-mC^<@R^AR1gHsqE#;x{a>1C`Fucy=x26#(QtGkjOv@8(z4I@u6 z0PDogWeH^J;cNdCppE-ZO`j+u5gqfjZn^-Sbp4jbbMsWso*v`x1@WSJ5f=NS5*sYm zUw&Kym;S!{aHu})KKXq0ls71RObWky7Js1^AYB-b4!@*!s>^fo7~5!Etb1Hk$DV;2 zp`%mzD58%$cReoY8j-pT6#-vi858g^x&{-)lS$K6cbZ=8@Gs3{9+NMF{ugPSKD?X> zm)zVe8uGcKz5wT)N?aB#;(kk2jp88#Gvu-HDSD1xctO^Y#*sG9!gB>O?mz6^4Lp4uN$f1B3e<>n{XWkG;%x9_7s z^Q2xPo1BNy3oZN-0rsTZPl{szy6AY_@Zy|{^G$KXh)r|6034qqyV&%b8@0A~Z&(lc z#3>Bm{+5o8xXX$+AeIfo7DTSKhw(VCuNwurqIv3WnEZ2 z68Db#6hd0t5$vd2EEgLz@Xo=53iBGp1Leu$CWZjP&P3aNSkT~Cp~s(eS8xV2sbq^=}CHdoyjXTCtDX4&5RIG%?;2mBC>i z;I%V}tRdPkvFxe#s31^_ga^3Pien#LYhP-%V`qHDC>cRy z6qHup*kS0*JzAPD)Y`@k>0aEaLxKd%25Bv-E<}HOG+bY72tZn13(ll|q6HWhQgoDV zd~)ch2$h;;$y;v_&UAAufKT}dbd8gk`GU;@G;P*gq+2sETlX-*xk#u&1S73Xz8Py- z7v0AALfu;=z1+Ry`7d84GoX69cD~!qy4pj$U3Ej4M4ODm^VuO(+(@Fx{k@?~NvOC@ z*pBiE?O7Pme3uq@ANaZHC7jSTL9&cqOKN- zv1sA(K2A;>K$XIv7@$(%7jRCu!YrXcW0x^Rrai}n8|h6deVJ?5K5h((LAvwSi;e@V z8@upd_VxO)0Qt%sDK^X$^xJf0OQ12yzR63R_a1wRePaXv#V0xIcB`0i&w!a(se&3E z5Qrp3eRSIVYS!uk)zcEdPFg)Zmbug^jn|aK=kcbBGvzy8h$475Cxr*O`>hxTN4+u=-y&C%s&(du~kbMvdUXz z%V0)R#L0dEVd=SR9a~D&!O3mUf-BeNo>ZJN>U-iVI@=}HNDHDNyHuaQEM9-KCU?H0 zIrTM02dcP0RO`-waGf;vRiqbbWD}7(JZo8_W(LqSlUtY@bR>w9C6uqn=|9AQ+Sbt_ z6V2g`{s=GiZ;a)tZ2Yi}wDkIgNBB0=59UKK@jMVbRZE>J&aT*)$X%ill-gsj+Q~PW z#94Zqo+WH@s&69g7wV{+iS6Cgw%74m^9;5Y7)^Jr6DiybSz*z{KCn8cmx|<(+u#+! zclU6(xXecrViUX^Um#74o~Vo-4HMVW}TOe91q;BSz%<=^h8v@>M<%wB1} z1cT-L;%zqs7h~zTi=~RW{Z}M!?ffV3 zL^?zcjP;p>6r>lJh158vkrlsu_!WuOebQJMyV02%zkiEGZOE=FqAs0BEQbpzm1rnG zeVl18_7%LW>TfJ|<<(;VWjB97VGzymLu?}vU_BcQ*XD(~W+AFMZDf_Y=Fi!@k5DH4 zouZ%>^|?z30wAo9Eo$$5x39?Fvdp=R`bZx0z$Ls&Ll?5$7;=;oIRlJgX&{cWT(!~m zuK8*UFkqcxOP}8Bo}ua$jWSSHb9u=>x>IPW@o&vybnzy9{MVc1jg%99=PD~}&es6J z8|M2$LTZeC9IAIQ*2ACW-Y_(`dX@h{DuSc6(`pvp?!iKGZ;I%LH14wo_v_?Pg^8_tOPKJHj9%}!}5y(@P-iK5`L4iUGI=SD`nOV zVN^dr#5VelfmVwlw*C4uSQ`B7KDrlEt^>ftN3>IYL74NBGY3Lsa`*xjg}0P-UTtY2 z^X3oay%d|9&?^SZVAPCsMR;YWSY@QjgbN{)n1MZonWtY+JG=(Y;c|VDf2RJi2X=EvAtCtU$Zj zS{OOx40~1C*vY9_AZ}NbPs~2)J3mfpTwGfu(;N&&x`>xy8oK?jYO~A6MgJ9?3?^XUi>4kD=xxf1wX*$2d(&s7`o5|_JQO?b} z&sKtkZ2cjd4om0w4Z(EBatD7Rq%p3(ZH zz>eD<6r%7UoI=4b0p2)szA9?0o9L~*#xWTB3!Cl7Qd_3S6^`Z+Q~aY0Xcm1bY%_pg z$Qt8Jx@<@a&|@W?Xjc$IE|;yED{6*5gDgID#ZLD-ZMa=J83WssdnD-WhL*tT1S{UM z0~F+O`D0;Y%hbm^hYpX@a-9#*Fwpl~kjZGx%^_?RL9wZ|3nZgxKm_kd-^;7C?ROHA z+W2V!R2slHMcSIGbub>Gq8jdSMDD6&X7ZstbUoP}(*q5&b7F!(Z5Oj<7oHeZF-(l! zO=Nhmx?z;lTo=$hcA4n92j!EEj+(}?Gs>^^U^)Ubw$8mGp7L9Z(*}sp5rn41d&{;M zee*Ky?bOGt%#NkY+H%CztapN`T%-pss~aZ8A{wGypCz@{;aTRUZ%wz2eVwhF%7Y_b zWc={)|A7s76vkKnPk=Q>jf30!T=fQq+}2cKZQ;hku`d5f(6h3z3&PDH#7%67*B@!d z)p&-=Gotmb2t7v32GOO+9Fp@@QMv5iQH0CoNmX$URfd_`td|t}M9Fe=vpA6&S(uAN z4Ux79;SjYdNBki37F+u9y<;B`?MxAe4OH@iQFnwAF$fe5TUVZcQ8p}Je;k?vPt_gf z`VD4*Q(ZVf4ZW-!%rfE9GMlT~b%A>gBji-t^w2f-V?f}4-LuWBoo9FCr1S>dk(`#! z3hq7r4`b&Lq)8WO+p=xjwr$(&ve9L`x@@z{w*8fD+qR9{lXv3{{=uDO#F^wQBQnlj zd#{V7dGAHhf|bA$IMHs~m*fM%2{NYwX~7l+q473%r)rbwNo)x>fF#Y)^xG{2Qmevc zvbyhe=3XYByS%kShdBS++F9jq1U?M72C*wx*QZ*6b#oCSF<|-tNTFZp8 zi^l<2np3s#=nj%{y^|^iyQ=@S#S5gWhpbS4wh+;Df+F%;@O;m zy=j!93N0_mJY5J%5pYl}>p|qv*n5Or6-`F@nAf+OfvjWX>OUi^{Z3?HhN>XRV!-i) zLdR=;S^cM)iF1^hu(q(n2e-SaXd~o5Y z0TGrNlrV|=*xaE|_4f5>@K04vzxQ+0zU&)r;I&cbOG=$|;q3)3iTD+(ENy!>d{y#{ zCC*KpeSp%vE+`ZCPJkoh_<_~cw6AbuKx#PO+7J1j{CxNpvn5LbMiqg7b`*mYyfGc5JJQ2=#6D$Kt}~SXh_hXyP5I&`X&@2@BHh&E z2RhG;Z5-#3YAy>q;|hhb{x0C1RoT)Vr?gp*G21czw7)xUCu`c^@J|69*NLr+lyki) zymJ8fSKUrx=1KvXv#u$+OMN#N#_qhobxn}C(&f#4T^(c8J@^x878ykq^JMqSc{|&QMrIvJw&jPVVuF4($uH1cDqJ2 zd&m8i+>J^p{QEu`D#mcrkVRs(p+fEVF<_Aj#;u%BJErB=3_^aDBI5q4-ES%h<1*u@^?jvo8|{S^Lf#Lbw<$wf zuBoq%gME2z0oeL7JT1#R0XvEQ;KW7}A!g zw<~X1S=Ex*3Ofa1HB|d`BYJLcafFj{oKy+WgonNYyr%<;$>-mfm!m_*_+Orehq<#_ zTCHkI^_fTGW105m-;L@t0%k^naf+Xq11Boer!T3Slsuq4j4K?nyXf~lXXGPg8sjor z&V}Y`(eTBNRBd&=S>aQc*g)fSXn5*AmbV{jDqqh}mn?Vv%%x5cVaBsFll+MpSgV7{ z=RVz(n5cX6_0Pw;8?A+Jq*$4_ddanFA-oWX1DvuQXw(+N0?LzFP;PadPkOkvCiqF_ zquD$koKj8&O{b^y2yG7HefAj~XgETkq|NJSz4%3N*N+P<2&|b*rfq$HX>rD??4LEZkJTrQ1mC2Yr4AJor zvBJ3H&1Sd`nmMm%i&Ov0KzJ;7(Nux>26TmjVay1Zz)^5@MZ;liy1m8~Xf`RY?~1*Y z3)U&zVC=PKZu0aX6P;NoCN|IO=^=28%Lu??ue|e|Ac=Dl-}H!lke(UL5mO#>@=2Ls z=BAY8I+1kSKo1WiPoi)yE8z>IM?OV86H6sNNtup)dKlRCrtN#0Xu>oF)xur4g?Jx=0#aF1DUTHyVI>I?>(ZAO<(Rua5FCB1uq3$qJA4+v`8c(gY}UN^LeO3#;&xdQ;_}|A z$PH0klo{ih#6!t*IEkurKwzz>zzNhPH@4-!)i_1k*w72}y(Z3S_)uq_YOmBQcUwmc zY3K)t?^m^`4%J&lB|lc^$CwB>p#G8BQF{!IxlrgSL~`-O$=yGp*3C-UCNyI+_GnH0 zl0L+92~K`9IoRnsTX5jCkm~U*ZNT0F?R`&7PHts5qb(>V&a8qbg3(;~d3;{eus)o8 z8+j)XhC-@C;juZ@FsZOZ!Z*l*%w{`qEnxq5j7B-KzyjwQPaD6GT8J zje}GWBhy(->7EvWqVM1%s#A1BciFlar|-Mw`Jr+31MFj&?*5jCpu z>k-iF(2)2)!U6QY1_`mOnjLPoMS@F2F9F@IS|5mM69Y#0^@|d`Gno`*kD_nnJl;l|J#$vMDXhv0rZAn!6*uvzuFeeqY4Hej3dEyaT7C`vqRhbudH*ZLM=6u&2X__EOp(B)C& zAA;G1Wzh3Kw}($59iMoKHx@XD+_VFiXnQp^NLc--Cl>xPN{Hd~_q$)O-|dDLSeuZ? zKa5Rb{g;>i2*xKz!xmt{9p1u=Dc=;t@>~Er1SBvbIFLXw@gd-FUZA^X*TWC({@EG$ z`-!oih3IUO*&X<6h*eU^KroRj;!#38e?=PysDRtsAh7qJvscFcy%WgGycVclh<%{Y zz0c`bHqpzUeko`VAzxr;B$dEVpwp9+9e)g|gta~+20y?Vz&_(9H=(2=mSIJZ_2)ue zDc}R-d$fWNBq%5#Je-S&gaHKXn=>Yt{qct5J6tVnZ2>E+Ac*h%Ll5!{&V&06<;(vwjPL*=UwU z?d+fxd2}O*XusG*J;UR1)@2Ya=D*J|P$#ppqKrh}?1@_mYQ5#<9el@!s- z7zY&)BkNp0ixU8o5`vu5;4s0bef;@?gxID?P>+HFhnZ_Uq=YDnMQr}7#ke@s05Ok4dY`{Qh<9uUK$g+2-Jwc++of!_|8;BZ4rppUvg zJ)ern&#s{&7uY^*{ZK|$;D(HVQ-$xMp9a0+!N7y7T%F|L>EUpc0Tg8)xLGLXQw&0} zGjxp7b-k8MY~prZp>wz zk353&(z|3UMh>*E_eD4CaRoVTQ#48G-UP>n-A)U0n~UoXEH)RjH}utx3s$`SLrf#y z4r>PCcN8qu;2asE(z-G>y_lNeF=q~V*3IGS1zvP~GK~e+ZkX5pKGlQ@uJCn!T$}|I z<%sDyhCtX61o?J_!{82o~-9ve!PL*ZsX^_br< zz!?~QgViRkV?Q%pp#UC-f{zWrsMSydUkK;@C5kg4y57*gstJ>sMD(k4#9P^Tr4SR9 zDN1wi59WEOH+dL{D|~j}7uKMi%fJT3M?<X8hiK+eN09qK1WZG2S+x7!!UmE=cp=qo$|`9FW<`5v#tI#Lc$6Dl=Q#w zAp6Br0`3@Gw(`VP>bQX%@3Mnz>ouCZdaA}Ssw(Xe#Wxvh%K!M^_DY<{5&C2?zefnh z-CL!Ml%m_X3xnJ+YFWjo48iC4TY;|p4euf+nG+oQOHZwoh+V$sR1ODADP;JBnJ6Sj z@r<})UX|rEBrw)SKOv{bM;p))NjwYAOU`qAr5VY1HOD|Z+8>F*%b8pJ3Fa;fw{BC#WK)>r-)1Ci@?iFly`*qsZ@bPdBw?S zb&g_+vTtX%FtEuUo`fp+Oh(3Ntu(DFL$6>gD_UhtJ~#GAx3agJ7;ks6t1=s@s7NHS z7N_P!#?CoG~Rk(P$KrK zL_Ra$qS>3%$`;i=DFjD}d{A?YHRRyeG-wcYBf&Y&;X2#)yCi~NOn$^Y#%ZY0{HS-( zc}0^&MwE5f4mcuTJ632q^gQBzeW*`6hylR()(*mnx~8x)3WUSA<9v&_En8P!fkoaw zs3bpn{xh$`P82Qd>xR=nYpA!Ks7m;ph!Cezktnr&WAhwln#7JBhH+L6c|wIsc}}0h z6*9%%R*C?ZDt2mm<3ioCIw6hit#3~(4v&*mwa?yY$alh)!Kfl`#u#!5JJI|`n{|ucfcD{X zrcwCr?S`)xt%j98vLI!a`3lJ+n|N=_7ggIj-AAY>stz@K9051MGSB*oy<+(=r&-8} zqdGOj;?duPqc)}#A7$0WM94CQv*lygr3lZ=5#LQgNF&_lFCoo(xk7{;PBfvmh;Kga zQEK?At0Xq3{Hj>!x*mXyUQTVh44v6gjWQaxE-_!Ce(wqooP%y@VM5m#-Y(ea7CL&$ zWAwsJi2cnmeUNKWoK(1*-CyZ&1Kn7sw)NMnY&oE(EMcpg5PFQv(fIa=WuRrz^3d?9 zMl!z0<%t)XX$JqsQ5@0WX7Igzr0w0@Z`<7gpW)cigpy?Yc?1(48lSiQIDHvscuHq$ zBt2#1M?+WQwjw;W#>Xe;TQ!;ip(m9x>PM5Iu|u&EHze+n^>v4lO1hOJ;@@JLB=jv^ zf?vYTIim-oY+2lQ&2<~0BKvxmnq+S$*$2zM$N6=9V*!x!f$RZ3{Tk~$=(qETquZXs z@1Yv@h;i1x(kj)zYslM0b@ymwzFXThcBjjJQKLmEO93+{%QSx$Yqw+R6UAvIA#>=R z-!@)gjCq@{>?vj=S1f@{S}mW2JrOAU9^2baewgDOR-X30*G7l4rq3%Pq{1G~G-fXy zQ5o0r^i9)yXjjV034h^U+mFG*%=EgvQBAuzxDJmt zDqobxzLZzz1PK^rWGeI5?zqd3&nmO>VfQX7n7$L$Smr33id2@enq?W1WDIo&{XK*l zGYD}#TQ2;BSI5EKp{bmW8m}kP6b4m;POSg(zyibhhQzvLZ5%a!Jd|DTzxvL=N z`g4J}`XL?i-9R5S4t?~(fRNwrMzjeV1Lg8}W<^gtPHWSkA+B~&%I-kO_XIAlH$FFg_DqZ~7K@3zI)F``!LjEF8C;ipD zkDgr8cWGrk7=yV|xEx}w>uUYtkJRTK!kUPu@SQ}bFRHp0>%7_^r=2)y=NsX2O$%Ww z%)wBmIcHgO>y)-$K(PJ|HNvVz`oM`D)%GIjNXeF7MTV%ZCKql*RifwovYoywUs}#u z2~=dKB)z43C-A}emu!#b`~kvgTlSwJ4N<137($mTMt7W$!{LjooU_D%v9XM0_uj^+ zW66-kemv2AZR94M4vKX@G87iAT#6x-91;zS`a^EH8gx&^4~&}z<-C`&m?873?(rTS zbRH>nFGyU%!du~laxz*(#R}c>v~5J@X9^+=(q(dk6R7D}KbXXQ4$(X_yXeTe(_NTU zr?z4l__ghnD{?ngIeH@o#iFd}Bj1$qk_a2USownpLv9s4nfHo74tZ!PN4mRzzzUXS z+C~GnM_Q*Q!cGX{OxHaIl&8b+E028wSH_csG~pb^(v1q)`FEEF?u>&a74RzuXZvz&*unABf}*S;*fH7fbl0oz{J6!k39 z@IRR`c0Q4v*CQseO$*bLqp+9i^R!F|1KXSi6V6L{Prz|VahvA;JGjkLB_V|85)OP- z{qLvSIs#lTGZ&7j_MV18G?lJ?ja}7HehNB{MZkraIZ)sggqzaHy6M+;U9~jf)H0N< z@?&={VmhNzs_Va>|B+`uL#xyLI-jYy*>#TPo$@skVuoQj-s!YEZ59Nww&;}Z7t%hO z)zV$bF@2cQ>WO2nO@dY1l|TbEjnaaGV|iHyhRKG=-$IPMEX>mbO{DtlZNp z&p>g`6Qaa7`1;{3Q+;4VeU~ZRsLSaol9$T*xw@Zg{KE#NCf-a6F&TFiMZvvnKC;X> z{0>6`)#FBNEQi&uJ-9In^xb^RD)$7rSl#Q=EU3cpJ&ps3*}xIwk+UKuJ+&;DSau`{ zt28IzSd_Vp2I~-uuT#3qIJuvIhr8 z3f)MT9ppNXs3WALuVU)>{sxD)h4x#qAJv!zv=X)=FF-nUtccGc=OfB>P+S6T zr7Zr=cW0+9m6m4l@o_Qj0KGZ9RkEK%9=s^SPu0Vbk-J=#`nP3)ZGidaCyGcnab_m1 zjbe<+iJyS+;`Hp}Bs8~kIkr!e)!N)bmJ#ZBv25|knk?BPia7f*z-2jtF}{z1)%n{n z&G&oQ#F&)FFJGpmt4qY~{}O!qOnkyOqonjj?3>r6jFI;bY{XNrvidtW1oYl*VR6?` zyvNj4acAN zI6S!4Z#5>YtOB!wAecT|p*l{ip5Tq%pTz4Yx0gz%SJz_I6aubD&p1mtU5OdF9iBkZ ze+|aE9#`H3d_w>*;tXOwe<=ot&gb%WCspWC>t9MN$vuD5>D<$5u2$0JvWvi9PzC zO)Ulb5@_7@`3JRL(^5r7vT=jd%4MyQ{`I-Epw+s-xdB{hfXED&9~mv9&pkHB$+Qy| zwh<27me^3uhaHj5zK5Yo^AQI%LHhPt&;FgvQn8Xfy7V#*O3d3=Zwj;Txm^9Keh5V_ zoCLP-BT~a7`n?_dYp7n==NiX=5j#VPTabXqc)VBh<#n^yWx9av;+(-eMf+X(apL6W z1%A*29e}mhbD-^8QcrDlvL?JbvG4B0f0=fMVog$B+l%!|9QmlPuKG3kBFjiykav;! zjw#_;{wl_LVV`Mg559m0tMbB$Dvdx0EqOS&+)a$YXEOYK*o^_QZCuzBS_!d^3LGX( zXmwtWD&fwwgw1(WA)aD$wF}LHvQ;wzj^W4mSJ`w)0=uCA|E>hp>|lN^q4907^sWcO zOH1{Hu2B;3;rgrghv)wHW&Rl3Kdk2DprtPPL<5}vb4Vk<47)a~SzR92DKT-RBD*#~ z&dG1Xvx+N*bljaWNQ_MP1araatb6K_RzP=MJ5GR1X(G2#5`R`NeQ(j>!u#8HMTA@E zXv+79V-YIRoA6lgs>?BrgvEJj`OaM1#FS0-cu{a6UqT+9|HJfm6%NLR#+E`c>@{PJ z7qhkFX}5dsmQR{~WBIx40;FN#c}y#ACaj9Oaf%VFGDMUaNyRCnb5Ep`UM=3pmT6-v zx@F=Y#fyp)1VU0(*~;Y*nro(Ml3<*G^)$)&f|C#K3&ecqA9mjj zJU>`#8!ugQo~a908I1SFd6kvzj$&o;-w>pfXlYqFMNuj#6s?3*oJHV|HIC(nI5HO7pPvyY1I0RcmVD=LMh>9=RkfiA*T4GEjU zmD0X_A4OtC0P5P?t+_>W++HR=?K&MaV;~-SkTGv1XfrCR;z5T3WvluJ6fgd(|EmmBv z?YQF^9^95S`H?ita-Ggp1i)oAwgs6aX*7X-U*ANkWVGBUBYQl>CJJsQ8nS~hD_*hf zv78dSf+g+3NcEqXNkxlw`^wI}PXV(VbG!HrnXhYQUso+*>+A{9IYvnxObf`)YzNo) zeirQm%UtcfRSnfD#1E7Y)d+UI#ZmQ#V;mTPjx7k}i5$HUsV3Jz-Vnyaww2;$bRrrL zp&B+QGQ?})p4K4f7r0#w+e#)n4F$%XQUPh^nENPXA zj~97Y-q#s_N}92G1<`-27m?nU5>yoDRGySmbVRpdHu;&#en0SptFU*V1vhE-ytF|I zIl6)uuY_V;v0I@c?nc)sOO@I-M{7GpxKPIX)grUSwOF87D2vcew=O{HDesvCq_xE1dNCs`ca7pXx|l?Bt=T z!=ef1UpW;T5-=6Z1Gksq+)KsD3r73CU%RPVBICi{;jF)@RXywGflK(idfVw;^hbAG zy3^cEPwS1Wv|(m0M+2N?N{t~kI+|U+=V}@DrE##qI8w8VYSGorvz&X}-cAK}hd-1M zm_=}R*}Y&&Kr+I-eyfCG!>#Qmd^>0ht6RZe?@J(D-0{qeT^ITER|Gvf>Xusl?h{pp z!fYpgW|x4(6fNi_Y!lC0B=`2XJnY}Lgpm#i&{(39AUfwwb#aV4{N}E)U4{M-slO1m z^Wh>1h?N})>O%}vzq{zOu*bNoWPwZE7=k1T7YvPaGdh+-@Jp|@)r#K_%%WXYl?Ww5 zTY?>1r6-ljb5gE@_(c-8Z|DaL z`Db73Jxme(koqEATBX`ji^NHriG-T>&7ehnP`z_`-eX>|rmd%e9x)Fa8eVrKJh_ER z;><+wbyg>;BoK|NY!AE8CK6dH>r9rb3g>$bx#n%PKaROvA^qD%u|GcOs!10*@qTXp z3+;984abWblN)ue^aRzI^{NNHRYVKAVn^SI+I&mvXLVa6+jyAR7_F7JNI@T0y z?d~>=(`04w0Y6SnLCGfmDwJt1+;3Gmw4y`*3E@WTZFP)b76zTM-zSr{$ltDl#`X~$ zUG2eg1=k2dIFIUo?;Q8(=TQDwdU3`VKPD>28pTrUxcga$x`*nC_dFzf(J5m=nwKOgd+HZ5df$zNImRvxp&|+L> zEqsQxoXqiB1#MiVMx|?0Aj9}Vl3icE<(k~Ix!B7WvB-SYP0I}qM|m$Kj=SW$nBYwS zFh2&(xMOHoEt@`RwkfB_rhxT*qJ$yPIcposHsRqpe@zk3_*CR9iHM}rUz>bjm8;|- zVf)OrHu!0o2z{$s0%=e#}L>aTBoJmJlDsI3}I)7U#DNKiE2g87>^rKK4WC(ojUZQdR zOE<8H?08yuc`+%?B=2XC}U%Pf%94y@zB?qbk&rH0bVJR{vn>wOZKuC!%ma%}p6Q2W=sS zacoEM`A-m{B@A$5Vz-Yv^{vJ=pb52P({f~D_3NbYelwuaHwi7tyV+G~y9i6P=X#h6 zwe-m(rp$cl%TTWAf@U*v6xOv#ZrZd$U^ZI-D6>(@DOi+jfIi-ZzX)5QlQ|T1u3)Et`$3e&^ zwAqkDsc{GjnyB~|XUNg2YIo^V9OCPWbgG&-fBz!Si8Zud-bDJ)XqQM=mr*cB6(~Bq z`4vBvSO~cz4*BprRB!U|M$gyEY&Ek#PG@Z*2yXs>5+;T_{%1hX`5ys23llrb|BK}R z=~CI)IsW(f{|_uMvvaYs{$F*eFW^eq7xUmS2iHhMr@PlEn_F8!@Jwz0T&eEvVL-yc zov1`ebZwpB?wzJLz6#H8-+=S&0vPk=DhpS^ts7pYc&c(1sH|1&K(b5Q9BeJD3{Rkf z`}=viNg#7`4heH}4KNrOc32CWS^rBYG#nyHN?2aqTz~O!o}hqf2M*@E2i?4`9D1SS zB=&$%_}>1pf&0L)4D8T?B22b8OEK7K$X4V!U?#>@XaQ46Ljg9<> zs7aNTw4}4c5p&aXasht`cCGhp5tM+r1M&2QC<1oKLD2#@^895?#PWd3GIY7VuKvBj z)eW2{2*?4#2G%6LdO>%bQWrIzboa_7prQ#+XpX@2!@X{E2lz3-KNIwqk?9-bmf#v7 zg3k6w1_B3nV{H}GZj0V_3aA8QnJAzj1h23$iXm=xOVN&SR4NivNLRYi)=Cau0^e}|!#bwB??%(uK($UxI zn`^lry_%HjoXYAG|M>FI>WH%&7CC`6*76Ma+n1umEBRVFTV?X8Z-uy5-X&a;lp@ z{@wy=(xr8Eg{76Fum2|gT%aM>JA-<#)YXGvX>q3m(@kFL1t2;QcKxJDLR;R&#rhw~ zY-Fwj`z3uXe=L{%Sh~GgK$ZQhA>s7?BvP+-$1p$%eOb)AW^kv+?D*Ax`scm?RK9;= z-W*bYR-}Ibkz@kex<5yy-@Lm&BmXvN>fC-P_w8H+xdGLIU0WM0tKU0H^0Pagw1_PA zucibFSPPQ}z{s&f=le})V@n-4^%}SK zr{7?g88hn-;m$@Xwr)4SME17%g9GO5ncY$LPsivE)?Po?PQ^6K>A%X7VxBS=7O ztdM(1>x9239*|;cD?2-I`xpBb5QT&;?@23KukO?~kSeca$PVVz8*ne#`^F>ZJ_u99 z7pCtoU?%Br;VK}Ca=~!aUa}X+?j!0?;Y}clp&t?k4xprS!a?9)DnG&7T5R8WoEX)D zr!nFmfbb7_%3DDAk$e>L=v!Ri2mR_RApC&S%iH#ocCUI#j>4bl0~bV__lI}4T5Fc@ zl>*iD=b5RY(d^B{XW{lnbjJWz&b-&3aNw_oRRyDCuO_y@*=cKj`_ic`X37vS1m?)J5E)jj6& zf$4ML{DbMEdUc2S`B$3r`|$L&1;(GhV0(F2@U=D#0qPKfMMCS<%3>1NR2y^APm?tI zX1tDd8qzn@t#oLd$)E`FgpWwTtS%uhGpCtKm!W=kh9uu%t(a)vF|Cou{j6PI@pCEX z>rbGT@lNzA)%D2*{Ht8S2|e(c;-Yz-&lDOmNv_HWFcW#dRFl1jFlr;PI*b})MMuw@ zn5Ik>O9UcI-xW;G7Q30Y(<;~|&PW!`G`+-tH7}lKn_7DoM}45Ka>rgd40ch2PtFSz zbj_0Gg(&I3#OYTEf5JBl12C_}A@TI-e%An)@nzi-&ICA>VtX-zBsNyAL}I##Bn2qC z4I8z)D-7oG2BxGJ*`o9o;Us*LT%lGh|26d7Ra(8+Jl+G0JE>f%lSl+{)*mnwha9%| zdHNzRO@J+m&R7VoEZ4EA(Cnt{LpeE2dEaU zkKu*juj1W?M%56fxqO~^4jj^PlWxB?+Cr+Iz2wld4b6kcbt+{<&8!&QTI*JL{&r&A zPU9O!f-4R@$_wXHW@R@%p#AKbFnwg>?bX)_DhIf4g*8%WlZ>z0U^qe9=~ ztAd;}(Yyo0{}`;iJ9>vOHsRyJV0jKb3tM2@3_}p+ZbSieU$an?H`v{R1Pn*q1~C}8 zur3BOvuKd=hPVZ{k=1)85EIgk2Sp+Bj!jrv9Ice13X{G@8OF}Aq!_GbsH=8nH?`pa zvMEVdJ_uNhP^Mo@)Cmm+7$D$v&v zz$)4+$Le3Zj;1FBeRUCI^wZDeYWc282;}o=6~GkWFm;{(+p*oD(y4u0+!6^MrJ|-Z z^!8RJLUFn2m+d}5VFb3!3>vg@jJC6JR(MSFc;QMMi_9q31D0JNC`l|tBW`%FExxgc z37sH9tYBUCygWmJVsIgW4aZ`A?COSD1i!g@h^Si!baeW(^pcddyy+EqE`rO0I!3J`xZQ9M13SIx$(nrs#bwDLOBla@XkQto{(&+(X|xxU?*u0=SE739PyC<82&jZU45fr8)|t)42Aw zFLinczt!usNSonD2t*MoWs0&Rw7@eEfiBm-@p+J#8(()t*h9QjjEkP`%9TWQDUZQB zp~23x9cRJroWs|qDDv`9n8_96O&Sfn2oQ#;3z`}ers7}EF})gWk@iJePnXNPu8M&f zmL*-|=Q9NyZZ^D=2WTnVZ_lz^6yCYVtCt|iSjctnHOAx?B1A{DsL6h#qIsba&qd!I zN}9n$+5Cy%xQxO%fKj0+CgRh(1k2NN9B8M+$Ed2iz8YYV{*>N@R!a6x>2DGpkjZ0* zLd0uvKUmY}bf&|z^8>J66aWvv7QsvdpMzlYlH$`yz-~-hF|||E1pe%WJwAI8BKE$> zeQ&yt!p|>|_6SCjxXNo7qc;Zkc|!ABwf`pe%#Pt&cIo)NiC?7ww%MRV^I?6jCLP}6 zUNY47u?hYQnE`J*`eB{g=xxuMay}rg)1)a~z`tB~A~m z2d^{}-_7@9XVtd*yfYA>N{D9wIzh(`jkC-DK=Q=XoK3R45(ryI}7KZP* z8nS}(6Xc+Vw*6YE_i@U`t0iqo2+g>4tWA-Fs@V&CGGzjJ@BDuHQ{0r)E~Q2gH6^C;q&0&T1ADv zex(U*WVb%s!2<)Y!2s*-$18oGIE)|kP?~YmF0wIgSB(5WND>tGP}}*^R<{Gt&~aq< zi3);Go)p?pQWxB+3Y=k2d?Ft1Av~Hl>p;}hC0;s_VdRCTm4oM$S32&zt%NbD>Hw83 zmTua;EV7kt1&!DC_JE&U&v&e`Cy1>B?0><8SaTz5`??y$_88QnsK5V`- zh{SP$QylW5bAI3LF!XczT@}g+I32QS!eM0R{L0e_a)d!>@PUQ*@_L~8EF<#ywKz2i z*_=teTw&Tg-vQ489K z;(?}Uk9`pvb@)X&&K&F9vMf_Qw)LVlUsCr`R<%)hi4+mx%?b74$CzEg;_YGvpoU9D#W0yxGvo8m}%9uj&8)LyJ z)5xkKe&HM1tD*h}G;+GOr+6JVub#r`no=7(AyxGm9@Y1@tX4m(4ww4AnCM#!OweWR zHOg*Bbyu6@@g#QrG50)%KOiXK2!8PMS{I&5BfXRs0nN0{d7QuoMatxgtYCGj?_eIebDx9H9|h_JMrb1D6rnAArBE$+XZq;pwuo2w(qPmUZe&#Y4LQ85^PMROD&wBq!5(kCVruBl7zGuVB)Fi zUlKymkM#eX1k!%nbn%I4Ak;d(nM-Iuz0d-W@oEzgH=t9ArGo53Lv9^epbPSae{JWH zJfn>G%gR1|ACaUzGd4>|yhroz*ML2t10##yy*l}QSFY$f19+>VyPDjBX{f^E;JjWw zwQQWiN!)TNPb%Hoy+*gxwF4J4HdhZE%z>5k8Tnq;#l5L}=2Ux0n~NlR*{R@`H7%xY zr2okPBU!o>gz?O+1Ce3UR7AVWWCv z_RI~rpq*T;qlP|~Jafp#KLy0I7zHUYll|PR+ejbW4U6RBol`7^Xrw549WkGQG|1rw zWJh|Ni;?$DU*s|>)AMQlIXw_zQEMPEqjr#~bisR^-p_Qdaw%@8+{V^nxC5ODjp34M zcsT}~d}7(FvRHe#e*}%9GRN_Y&4#N|+;%o)+J=S~BV+k+63t$NY^LCh&uMo}X}vRaMw(u6l;hGHgcRYe@8|6t);j9lBX!v zAmyD~5bD+XVl;->xmjB(W?#Us{oIt#9nVaPK#pMvcgGBJ+ z$l}6sA3G7D<8ke5jnU5{w zQfknRwXA6|P~|rI%H!G+5{Pkb)%xESo)^Uv0DvRr&mhjIM zzH+TJ$lgDXN7qLom7i)RXtWuHKx-o7VVFUi|Vh%DIGUs*SfbSlJo&CL%NMu$AJq^-|FRlf&h&9oDE#v3MEIL z;1+}hE7zuNhlcBAQagreK{PEKjjFV~6DTFw(`O0$FLL}_kHoQ#`<_U+b}lrUuOr7@ zQXhGme%qkCQi~T1S9JeM*U`3C2Qqlly;t;|uTGJmuJz_*^LsWPh%!Vz4N62iK7AhJ zceHFP=aFgF=(*m(d7F`26eM_$oN99oY?emEHE3!XS=@Z`@oU9}9n!7p?8Uu6Q5f1| z70pmCU)Jj4JOjTbLQLI660_nE1(Uisp=AE2a%j%=4r9{2A2PpkpZH`LNnf(z5nTuE z1;P2px)!2t=b7^majn_5XR6O7Ix&{J&Y*LpkUOG_N!5#NQV5gL@#Qe>IV@l0gszy; zFC4mW^pQ5{fn?Y!I-4-Y#VRja{WBP%PusOGvSY7)lfHRs@6_ZCXR)u-CRns8_tQTz z0u{A`pAEFNLHjSA4X+s)$xkk6d!ex%hgG+SgeL{*n||w!u0i;A)|DrkJYXW6vm#i> z+#muwFr?jTDC7pN&>Jf1bQ_@ftu79D*hY@rv zA1SOi()iQUmXu)0DtG%g!pEgsFi*~0@W-Yz1~E8?h2$o$DlZSxdIX>tQ?Ob1K2nRs z3-{eRG98g1*KQzYn8(^I4J05|Xege(ncM?CvHIKkN=w0YOR%hHi{2Ii=_9}}-j1uA z`ff)TQDBUJpKY$=b}9b~)J8>?u)kuvOwzJbjMSWXuKH&&Axu}_!5?!y$c9Qf3T*r%^r>X`S3=BUU>CtcO>_lk#5{6B_K`?C zg-wR4WPcY$2_i3ggyk}x-({XO8Sg+T)v*ZLediK-D}suPEX37SxNxg@@DQp` zbh{I#tj=jr^Bf&Bkt|arSWk&Z`+S}(ZcU-zStAfgcR;WLK3p`*zfFW9+kt+O*Ti@M{T`qv@acyrQVCQ zDsyfX`KJG2>>PqD0k#BMwr$%s`jyQt+qP}nwryKowr$(4{=J!)S^UK;Ga?rmxw(jY z&dnxJD*mUjkgaCB7QEtWuadckN49Ave$Zn!?g$3(OUmhcteUrdJuu1TbyVi+=QsFs zwaveEi0M$LB{Y^;V7z00jW}fIRbaG4C5j47YiZy9Ygzl%{7wnY9<+h<-;?&n@Gjsw3)l~09RLPWP-!IB< zYZHu7KZJa0a^bfXlAQB|v-AWp3)-t;!qJW!8#4Zy5`Gx3pr zem(0YaK#H48kt0Yrbvl5Kj@8!`zKOW2YzG#*Lx&fJDxF!wM&BOWM%j9qn>D&=&fGm!iOqBvmomiu zGOVS%|7+oPtXPQc&cR_hzzSBhF6RcELZh|2^ZcX?KjCuQlq6iPX;S6^RCaiqV3ZH4f8!Blak>pbghoz@>D6LyWr~Y%byd$zmhxYZWZJ7(&~p;Q zr!ON!gje~w!KNNoU5!s(k}M(7zA<_C;AlLSKt`Gm5$}{uMu)2L3{I{;%W8BNqVe)P z;Zjmy?EE0+uyXz6{%r}c@kr)>X)ruWrWv;hv`q$t7?TM4L*!7W=H#~B_Y-e z?cOc6*9ju;f1~m}fk^$$%~BLm4Phx}w)~)nkvIc6zd} zp-x+QApcNx*Yuo6i$WM14<+4`_?OG{lgtkUQkxU$H~6<}WjxqM%nk_`LpW9-27>ia zU^OH16$oa?Ydj0ID-yOfZj!1}JG3mKFbQ?oBb{)?;N0tsE?tgOhcV?X?66PdlFiPu zLqq#xVPjlRlo`G1iR`NNh=)jx6FxN&0C@4Um!3W9gkEE}N@f{EtGRsU>5SoTMz;U{ zFxe6QTMTKEl_f#ipO~m8{M3Q8vbQt2MXnTG6#JBu$cnuzIwof(%|+U79Pq}-rIG;vb9$>yPO^szyO+oFrn0F*Kt zG^l`A_jML&8n!EH6QE7doKlUNk2zClqTZ7MR7m$JZ8UL2Wp9D4^@C6fq7mnoRCg!_ zWu&+6s{{_k?_n8Tu8_H2z$OVgx#*sj+eZ0$(symMA?1c+-EUg_N<`xGDn#PO`pigl zgMMM2elb<&tIkB+oyhm$@jU=Puk;;Sg(E5I+$miz!L^R58`Z`6VNsFxc`2a*$8sMuWZ>%rvmaa!>uN94O{^=-z^0H?{Ev!d;As95 zKC~rg`(7Vt8M(Z&kBM)3tO_L)B~x<6O4e*{dhRDq`o&+WBi?VAAx35_I2&wg`OEe= zjj!S*6xJ5*q*~Z$%VQ;ri-y3jQC4!LGH8fy@Q{#3aQU7KY`B?UgGuGn20E*lIvh-J z*t@@H%jXUy>yt{mqW&98qTV={3e(|LX@&iW{H(tMW|bc1ao)}yhjqTVlc!>GqQnDr zw7uPu$Q-p-=_`=)!PaG6azL8*=ftq4T)oEZi4HabjifF8prIsP_o&175>Sn3zqlVW zhFQ3fi8nT~IX{z6eD5Ky?^*s%^~LLTrZi7(2XTa5NQOQ4v2$AxAzzhPJ&1g&cE&E* zDR;f6`9itAHDY~zuAHY}ztBx`2~FIl9YA!O#Z8wK%y8EV!*gAcO2gm8-`|vZjJ6rP zH(eFnV&Cr=RAcGLYCIAJjfz~DGNQa1s@M=BQoGZf-eV_j6*j-{Q>L-zz!9RY?&4(g z6JwXM_%Aec7(_=9fm%+_oV=bez*dHdqJs%q_foJQW=-|Td##!2#j1>BB8C7gXm}O` zY7Q{~xeAbYEC>k6m&L@CwBR;&C;zOC^y>eGL*@aUWv+#+RpKJEkjZ(i@a$4Fu%p%x3$sdls%n z6?W)GB@5N8t1i!(v3KO83!}_<#cjE}_vH0N{fpF?ZFgx=ecyYxi;h=!{odT$^)1A< zSC<5%w|d(!(tF@ZJjB!Of=o7EmF2VWt6F@q)C8cqt7V@X^{Z#Jzf4w5=TkB$r)o*< zZ&&_oNolAdxDVaIgQlwxzfIElC}sx=kud0xG0uqFf7yGaii2`k{%nh}H&#^xc7=$Y zr>|C2Zq(7eXadXPWNa)fG~s?udgX}AJWiyTr*lqwB}{qCKn8aTL$*Kjwol7F7@tUD zKS(N5>yHaM>4(=R)4Ct}(Amd01P*qgVWk;&%ugi^i&de)qbb4aujo4TgY~6{r+?!F zpcEiB+VhAGO8CW9g8);{82(*GZ)v1-Yn=!4y(ERf)8A}Rq<`r+X3PsT*Ao6^$ zIX!9a;3!HfH!NkOkOZBV?AY&~mXk)v~N!~IJw6xhYEF+x}$(?EC2ywt1T$-@M)@LPZHznE^1^G4Tt7oWzRe7B0POFlYv1$N@|8XHC*K)?0$psID!mQ3g52|E{l; zd$&A3%FG@No!mP!=$`|sbG%<=&sj|%f`pO=haNGgLUaxnTw5LVsL+GP@0J3i*GX+I zXird|8ytxbDC%>(y?)9(fzOUQE)MEiz36=)xwSadJuob#_rC<+0kMUH|Bh69Mc!6J z(v_j(8A>7!YAcsZfvpxo^xMX(av9El@7gZB=7)9S*WC?8eWGOpMSIm5bVHUCSScRG z@X9c#8zk@fdxegt;sXhrF8j!^7iy=bS+K=ntB*-%fd-6rg(BhdlnfPnK)$yeL7Fs1 zkKuR4Gvcv4*m8%&11Oqxkix9vI}c6cY7!o)e?`3xHwb5#;~_ReBD+OwwsYj{mDg~} z|5$S!Fjl&ipX1hDIu&*|WBX7jokXGhQ)nyD$Bp43HPuzA`b2t9i#{1QgtL22(8h{2 zs|vl3D;DhGlPP7c#CV$tvOR&mThJS8Onq^?LT-pAl~)> z&C+>u#I-(%o(*%)$2|04ddukC(&zU2;~bDtFbdHY8OQ}JR)Xfdw^AR#xM*J=7N)K< zh~a6a9fsZ8wl&!>ab2e2M3JIyl$5Di9HaB+2IvH7;)LU7UGmZkqocPYh(^M`tGH4q zyxkmj!8|7C_(rCG^&+;#ow9W%q3IuMJA;*&eFl`fFymCVg6_Av!JC7LwJ}Gk$ETM^ zn?rNzwjrSO!7`T7d=N0*p~6I>t$zV_3@~4sR8C>gH|ZuoWVFa79-63ol6$cVq&Z7- z%YJJu5bl+5Z11~C>C5Ul>_t{d#ES!aQ&Ye~S8(0bIMSEuP&V++426(qfPz;Qr;p(( zx@WEyq*zwdZMSWel77w}5{3!7dLMaV@Mn&$m5euOBh$tt=0rEN0)UC-%MpK-uE|=k zoK`XEMxNf0%T(kZ`=*TwP;*OFMCBM9rC$)#*?k6+D>_=1^;ON254|>+Bbhu2!-oo_mwT($qNTghvS?NE|%_`5c9{Brs zEHrlV!T%u8jF`XOzhSGsn@F`I++(WqLlwn`$D6M{Ot)z=u>zJoUQ9L}eJkn` zleSq|e)Cv?QBJ;o2MId4!3bpb*BGyP9SfOyRm0$8G=@UZu9XOO=_EOgZw7%?rP+EB#W00%ef{< zDo7<9l#{mB?6Y59YW+0@Q^TWFuP}A%R;>8bY&G#0xoV6FG95NVA~dD5gZRmUkyWGc z`*}0wL-nTilAWOe^V00+Z1~0F{`a|j^G+^;Gj|I}S!kKPV#dRT!)%zq6P&8)mUI}r zF1^+ChxF1l#hoKBAKkv#>@7mv)d2#t(qIC{XXk_H?f`)a^|Js9ZWTd|^C)6(S~a$M zHpuPRax*4Ge^F8T>tOTr+KdIJbkLp0+Bp-tlKp}*G43-Sp+{BpsU*q}zK65IBbrXE zF9Kq%cyf*qInVtBd{Kk^q|=e=laW32+ZpUQeQhk$Wn7l{q`W9T_li9mu;2?2FMu)@cDK%v z_Pd8~8&p?>0E5Hkq^R63J=puaJTP0AVM?%|%K-@_whBe*TGXBsu+R2kF_>!!5L-xnYw`SCOnMtGMRi_ty3(@Y|UvJadgzV zo(>nhljb9UM~EMqbpW^D%ck34?$x#RU<(H2<0c7J6)2XKf;RK&7>JwPuJtA((F(0M^GB_1Z>_-Z?UZ~+4ORg{$dZw1(bXm+UNZ+ z0N{C{n82s|1R|<( z5C&;QPFo0k)7KsrX&i~9!xcu&*#D*yyr-U_*mCKxMSR(8lGEg$-`+rN85#|H%9!N# zBe~Ore$S}Sz>0Pag|LFHYvwAY&7SWgQI=LS33QKKXSxpM^e8QD0hxn|T42CY(2c}l zD&aE z>n4+QybR|Q!yEW+KX&ssglpVqy4#lt{Q?Gr1TQ*;f1s8%>))p$*j$=`w0NGDHsNz~ z8*VIcMYD7n5j(S<8UQ1hq+PCfPI+UDeI3GMKNk@#Ja0w3f4xqfBDDHow$3G+;Y+|` ztp~U2&fU&!EDaX(Mi6j?zC5PHtlGJb*&VES&YXYGwW{Dp9!Bn+=`S zNVP!y=dzhJsSh*vNV>y?e^`X6hVrOh2N_QGt{wA><6bU^oyY*H{Ee@DN?Kx?{9bvs zOzsxR5n~=Ju6hN$TG`#lWX_h=D1!_A88`OQtJP0Fxq0}|uU5Hd#bft=A)aR&1DT)o zqSV_#X%&nB(w2n-O<8a&((Ic&lnyE>4OnJ7AE)$uPH=`B$rt#g{Px6`pd;gM2?o0S zRE2&pLLS=Be$yA1UK8kEGr_>4+yNFig2~0Bj7j%`KgF`U2wnO>7G8_Iii_>Z-?T&g zDiPr-A?>|3@DVni70ScA1+Y!6H5PgTk z!%7EUJ{#DF^`ZpsL}ggZ9*{UrW~Spb6e@nV18_kCqbPdF@OF2yjtLPvfteI3I4jqk z7SB^~D_P@`t~!r=m+J$!MjTnVU zYD8#gd9Y(?)qJi1DEJRk?*0Al!JW;Id5hZEF{uucBvg_1+^9}ZgJ+f8SPdj@7-tJ} z$0Lo5n~4JrES~k#SbxVlT#Jd8SA`9n8Fo<(O{_92gtiqaW9qiMBu~?{rdn8|O>^`* zLaU52H%~XL7W0_uoNB^@7MC<2W2y;i1M-5Zmc|}`a>i@1U@nVf(7cGx5X=zDN?3GS zbC|p>`kyQgi1Q9Tlj*em3>19It@u}`fYxz<;2O0x^9WJsEDhz$UT*B5HW#)3dzAp+C`UP; zkE@*NnYeHA8Fq{P{j#k*x3Btu+PZ5egK5&(Albrs;alxsYGUopyeKi*;D=Kqooj7i zZ1s7HiqtU!#DMZ?+}Z3`qFSC{weU{PjhF-1K^c<}U69sQ5gVr$U8LSSww;-EZsgXY zHTIonD7f}&wmm>dVF!P4* zUfDfnm7rnWc;BaJONg*B^bEu0Xf+4vd>eXdW(n>~9>>LPRVqUGTkjRyDG;i35?8l` zLSuGkbPjYE+N&5ZKp5@7`KY9kSp7AgfP?S+AwJF<;6ckdsnz9R%f63BE(-KxAi09Q z5Ov0F{l@qU=F?YHpv3L*=5`J^1%ztUMoq{Np3;J1nG8;9a_xaCOHi3RI1<5ff9p?lTyYNrfZa%6}+oz5d%oFqJPx>sN5KAChwqLsM3DO zRi6#>fgve}_xQpR4o6Y7;~-u-@If3B%09YRpfwf8q6qhTT;ljcYFEMCVeq_dP#)=R zM`&IXtA+|~QSRR{;Jn+wwenGw-u(vM5>*oH;!2NGm|i$cO>es><}7ZS?aSB<6msAWdLK=i?o@-ZE369tPmBa;xe9qjeuzXS9gw z-4fqCu-nlaMBHEh3t0RjmULafA@Y2L z&n0r5%4kG019ppx4Ojp$K?x5;K*&del(^6T!1Y-j%VXkc1l;4KO*n{7fMMI8QqGm< zW<9grM&wsHtQUn0w6+JoTv}A}VM`>MD>Y&?KVkG;L6x=aS%Y>Jz&g7Cz^Ny(L?>syv*F%uS zXOr>^BwvOx%G4ySC`xF^utp`W?u6N@XhdWMCKRWz7hj%@qSe4KE$0oAf7TfyxC%RN zxCJS$@I1`n-bdHPt<>?1IR&cf4gMy0YHN~*==BT`gkW_KT@inl;m^8QKhDp~Hqos5 zI^-iS*a@# zm<-E4CbXqmT<9ju%K2(^In0cwv3E^0r4eq5mm=iqm=cUe{H4ME(&wXyj-JS(sfY%r zEidcnI&&1|Z8-O+zy8-&X&N><75skfb;*YkcHvnQ8DC5tLMvGA+1b#)^EV+~Oc^+$ z7eH!)oc0sWir3CzW%SrEYDuVDCr^a^yF>zB$@V$Ocjy--U8alDC*&QT(l7F@I=2UE zhegNi#?R8>W(JN3`6tujZ&`_v+vd%x5Hcz+{Ixq8D*hCfV%L!qb7n9pf@0Rl-VZ2= zr>X1KoTCZlKdzmk;rb!rHBP1e{imaHOt@xGEZl30D&vA5IHJjfuf-n(Jdy$?XLi^R z9+xA2H;h>H(bz~2XGDKGiXymjzneuR6E!HxXhb^twUn*L%P>ZGEPwMblP`%QRj_Dj z8e^vlhKwhg%(VoQt3SmueJNDfmtBCfhuSLivl8J`M)Ir3zi{kw*QIJhf`^tY>@M+3 zb9H0*p)tm=HUhr|t!Ami|ShD&tVXHwh=EFN2d%ejV zaSD<3M!o0J(hoCHm1_h^cK_xvdvtL?5F4tPKr)7qE>&jFvXYj#68hbv&;3A)#u^k> zJV-%Za7rT@bV&zMT#ZdBf#dzf9xz=A39e`6milrvVzgsazS}0wg)p0l8g;lw^lo zF;xWP;~8r4{*T82)NtA~86Z8S=Qn!@6L%;^uneFu_IJuCqtxeshOOGECAYYR=765) zF7$KO?%MP9)bJu$G@cus5}2~k2(CtwN3&D$zu+Pv`>K+nmubLxk6JkajQc^2dq*)3 z1QQ29`MQh_$c4szUiO?Fz?S?8xxbZ2mJU?Hm~5+?i`$EndV2QT57Zc2MeiO%(r`#C zOc%c0y9}Pq3aUEtrE}Ka<(ay~2a5_UaxkQ2qBLp>Q@^;9UX~hZ z;6-!ttX(j7RkkII5uX%ifxD(A$)X5an=;(16MNowBZ640*;E0H&CwXQ%t;rgnx2m? zr5Lj0-JA8thq*mai+J8hx58cGRY+#@DLJV=1r-im(vEnG{KeYdp`we_qkrs79S_Pv@>NN)~JP8Y3!L5g{FbuM=L zN2I1&wj@N*@`**^n5vYTbtNGgs#pB10Y635#Ev86{yQ;WprHSOpHGw*J&#t;}tB@`$@U4m11RY~!)DN6D zV8chxcMi?dp$*aTW2`B&M#@sxQ9`8QjABZ;?ZUDle-D5(mwWo`&YPoamRY7q0!+ZucNum{+ zmV1qxZCw;?ag6Gc3KV@}r@PZNb%Jl)IBYlSQ<~eGbs7AQ?$H!%Uc!o*lHP!;GmiO6 zh5vE@4ff0bZpy9Dvn6w{FYw^ZhrtVzD6zKwv=&XipM*{J`AOujmr7Y78VYmGP-w;v zBlV+yw)nGcf~4GKr-PfMyLL$RiNPo#=W)lTTH`Lf&A%_|iy?~{1C&;dAq%xgrv^_R zHNC^_uShp0j!RxBxkU%;`1Ev5C@k-)6|m3oh3tATV*KGl4S+`dri3Z*=rkWJ5z|es zuz!N(*{kP_TQp!=M)6LzA|hbV>-(r94Y*C#LJOXPl!CE*NR8ixf-~FbQ_v{(y#js~ zw!~&rjC1nE8K*tgRPj8oeE-@`Ln3Bhe}Qcb%BwDs4tG+&K8Z3V&d0!InnF@+K&YY>az7Q)`pifmdA3; z-@P+mlW)84A^Rlkv;rRyk)6gx6C3>5^ts*1ZnX1 zaQJN>HD!KOJO)!eFdDaxi`oRYI?~k6cB#QP7uHgmHU~1f!$v$L>FNRhaF=Z!yF~!o zLy>H(VR4|k@_X0vP60HDwKzN&2fH>XK~Ye?DB zYRfAp-SKH6~KsCUvYz$}^3ur6?Qh z%DFD+nb_q_c3~j81-oeE-1UuJinv~?VPr$>W{KVz5Fo+irfVcsCc(QXOCi1!3>u%HPGA;&OA4$85q>ZKJikDyMK5m4R~^n`vo5wG zAr%v2l78#JNeaGKc1emyG=0-PIIvkNL*fJtg)S+>ipOe{-IEbAaqsJ{yXvu13z+Y+V#?BIdRM`nU4R)y0=Z|!R|Hlwgd{pZ*o7T zR;h4bdKPV15kW8UH(_Gd@Pt&nITYiR__U4(Fxup_<^;MiEhsFeR>mi&$`Q%b;)B98 zwSh+ZZ=d%YlFH;V-?6O-aftzI9*Ol*pns@>;v|lt?LYnkZR%aS|5v1(`@bON%xuhT z|BIA!uyb(#&*}dX<(%xS|9|JZ8~E?6%>|ATok#+m>p)pD4030f$M>paQqs891wpxI~d&SyEwEev=`Tw zXmr@<p82at-3nN#7r14ExKA#nzg_zn6dbyG;+# z6!sOQBLEmG40RX>&PCkV{g+L@Ezs}@5Wfn%e=9832X6H}Za?&!69ZN**8OJ1774SRw~crB{4|_TaFR$)1KE-k(a9A;c>iWi@Kf2pJ)j18^k(Ss z(-gmeiLrc_a0mmWrQw@9I3^4>4jAp=0$5e$4HVE`|Mz7*U>^vOAI{VVg#_dZ?%z{$ z?ctlc`sx7u7v|x|nUn(R&MBY+$QoJLAC#z7e;Bbfk9Q0e&cDmUAN1>o^-dl(D-Ba0 zv>_CScEs*|z@L4%gw`7Rk<^8fk!E7wGPv_?^}XtjAhkfikaezwahZTy0rm zQ6lT`b@*@W`1n9Ku24H?)_eR{0^56$|DV-Ub>ZT@Dl^nF7JmYjeE1iI+o#OKXoh+rVS=`jcQR^ubjBD#Sw z`i1?vfod4=(>avKjgDUw{8R|m9J2Pkh?Q4>0&;W$eb*NF=Lelv@fGI5U zTklIogzyTgX)vQOSUD&_ST3N)OlkbBt8F!eVh(wZDgV|U`bf{TuM=4$pO*C0s5@KP zrdyuTvA(kBynLP>P?UGI;d89&~Tq=VTcw83<8~SM-}( zvw@_IfeinjMr2lffx}hDQwHpZZW(`ZTz87>HaU2CP_tRUx7PbrGbmbf$^P}z$h}CV z?k95(8eICt?er}^MZKwr z0v(Kr2JY1H-mWo<&y9uPLxUQ1@@maFg|4wg_qP@PW*xz8`eIX;Yi~u_+3*(qoPwNZ zY69wN9vN%0`a9{obt4-{=dXil-Y-cUo^YwZE>D`jvdwi+-!p0vq*VqGs9$Ova zvYQes4t*M4Lmv-e&lC#^9G(X@CfurLKt=Ac>MVEePt}fc1V|(0oZ!Wy2%>;)ZEcbb zI;T^k>$vc7Bx|v_oh2!bq45IKX9;Zk>S2y(JvHWh?#Vlgiw=XVBXQBSb`$TOTmF_u zWhAtB_q`}#&%HwG&s1q*7U5X=KHN*MAQcUHTl98Jq@<5YNOWNQMK)-DwD5bP+Ub<@ zOKrIFQdDX3N$y`N-UN#*GpC9+8;Y5&ZFq>)vu8a_cK#jcM!nD_!XxoBIL2%7LvfgXW?85);>ocab0<=-rvJy z$DaKl&j<>`_RwG`;oH1P(M|s)y06OC;>_?KF9V>QFkScDwObC^BoNgxJZ32z|BQjm z%j=CIChs+fZrGw4H-#Qmw*| z7F#Xx5*lbWKqlz)oM9*v;z6FOr(@8!lI^J2j7>P^6sn8bLn~T_@9T5Dfej)o-CWHr zxGyncYK&}1(P(aplYRhl(vdoJ()ahthv zq6)FcVUIC2#!(8|9?Ouc?z?82VPYU0RKEgm&lR{kVlOaxMzU-x2++yKW?fyhTW(Kf zy|6O69IL?j>uHTy*mT4S%i_G}v__IeOYLlV{lNxJX<;a|J7}>+_CpLYT4bodfvDA0 zrQ$;qy-x~+Ot1OrauhrBm0pJ>_W#nvp$gzTn&IQC%D+(Le_6^$KL*$=t3>qM*i(Q? zzVRY&MOvW2DsAc%b3~sncWaWqCUefVB!#-V>^ftt*t!8H$X&{IWgN*47a_F4#^I23 z2hI&~?MiVK9j7*U=&!wlO`bpRmB^S8b(9uFUMJqB^er&(XDp!~w@%3!YZAnp#v&N{ zwp4T7j|?i8V2i46P7JR(1QhmV+Wk^mb!UpT_>hoc0n=SCW@1WXOo}v4^ z^N+y$)ASnMBjz=TY36pxo-58dL? zwteH<(1BtwpDz8=$y!|IRUsY@lcXZ{D`gHSmo@@JO;{fbILfe2zAO#;Jc>mHL4J@; zj7JBUhDD#%C#>Q)7knkiL(+obk4cT@J!I+(I_^X;uW-G#d0c!H{7Eh(c8*m+}9=T{~4l?kvkr76S?m z#8h*0gCHsY*6_*h+PDLS!A>bHr)GY0*^?8;2{s)a$jhO8${TSG%nsKK4_XZpUOdbn ziM0=S-`{RFcHK7zaUzmityU&!I|0`o&-RMM&9g2!FT~#vjQnWf7q)K}@;Tp>;wg2i z9m)g5*OG;|4Ao$|^%|-kB~`qod`@ZA_|NY8>0H7jyV~RfD%KgPS$_n7xVK~>Q7G-PJ}e4@+SjQlZSO&b%QENIvQG|P7ya%a6I zt#|n9cu_pTl!kF#r&+LvvRaA{3T+#u5LI+06)X+bckys)W%>d^+0+#gk^*l#g_ViC z9f7+siCs1(j!kMnD<_UAZPYYW!$4)gSax^Rg?pk+j?j%plCvIVQ;ZSNU{Y1m*6;JK z$}T0Vm)=Ct$uJsl4`$?>ZG|Nah8NnC79>qF*V-z?RAv_^)i`a)m2oy4aN z6VN|KRTKQ>FS1%J>!16@DT^j7^QRbU38sGYPj~IMIr!qGhEjB#D!hwpJ(MXjdwR(n~qt_zeSQhI|a5J{T9+l3tl)6R@ z>SGG-yC_57Lev%RGA>0~LR11$?3c_f4$*^C==G0f?<|6)YQB}`)HPYBW}B0D8p`?qYNs9_~Hp9gmQC+ zeHpy75jpq~yd#*yX;Sl5$8R_WL^PVl{GT&8ykEm8imE~eaQzz`*) z41qG4PFIOp@)cc!)Bdg~M(%s7SyrF=mX{yM4VrA4JskSD0AsRR{fD|9_MKu6^lu*B zaI3rh$4~ZDaOBJ`U)#~h4$N*Uj;@w$^i#YMlrvwxF}=@k@QLr!)m~oa4ia1XAMd%O$m?bM$)P-y&D)Bd5x79 zxRr`wt3l|Ua?+S-rMcd)oCUod-BCI1SLMFwR^@1d11=4A>p9jWS29_rU}CIL>idBT_tdzw^tICJ(7Js?}T1E z7e!;*>IlP3U?|66FZ451eV%3G;8Gm6)G>MJi1q6#zY}%FS+c-hnx6RjF;7d0o)kzQ zn(h6l(6s{UB(A&&*cL>Zo}T;LsHe{>fXPyv&_`6aG`HUJJg>^;2cJ@ak30q~`?>AjxY7GBKJFu-ll!_KKbj7AuPz=w^PyLkm;)}Ahu&@h^ z$VoAI2*M{%Xwts8*z{YQ^E0Rg-utq=swlU+Ls|dmTBS?>{m$n9^LB8vjitku7;zr$ z-g+^XeYD3EhL2Hsj7h{QEK6Np`E#YXGqG-h!bGlryDf=n5O#M%w*zs5Xfx1+$>PpwK}aKPM-O0hP5~q z8G6U$^dq5v?oT{&ZgVx|&Crvpoc^yO7~iStzro~j-&Q5u>P@yjXurEO0!H-2#F-XA z^Glw}5`A2Z*O6}|^%8mg*tE?QnkGlPe~-jNZ2O|$eyYFBS;}5t9vl%gIqHRe;a<`E zC^d`Z+5h#h2z1&eBpX(ze3J;_zb^QyGOMIVZ3=1BmA{+kQGWS`fXMSDS*k`Fv~eRx zfXrgii>;6ozgn$l#1c$pCrg)5B2}9@c6GnIX0IAaFua)I2cAGQe^ycyZ-05@JWVm^ ze6rTAq~R+^fDpE=b)yQ~0#A71U|sBj3u%Z>x0|>{B!9IQD&sXCvS7ThC6~dJ^#t#D zNE;Z9{Ytj~mCfZ=Q`7V7@{)MMbr2~f5>#4^Fx~Un$9KO8`vD$u z@M??ObuW2vGuowxB&D_Po-kdhw1p&gqZZ%e%^I|?h{BwB{`s0faQ$e8xmJ1yi~uU znKV+H3LtyCv*p*+sCYZU?U2uU=Xh>bS^OS3_)@0FPnqEVj z?aaf^Vm(t-*cEAfA|&7?xXZ)FpkT_pbz?=iFx3WUtY;j;Y3hM4EnUBRaA2WdMhF(D z-&Punu$9RV*csFiKXewvqQW*(wvAgQR7)Aoq+n{+DX5khoirAZDz<)O1L5~*lbWF0 z&%qC2IR4;9uEQ7Apyn?B33a73^me}>Lu|$Xy(sFY9%mKqc(U#GwO#_4HrEvv5u3MW zcvBkmL*Ax-uS68v*y7xGTG?HtGw{v5EBq~p+7{vx<%o5VBOS1wJP?qOgR5~zDFawE+XB|G}0 z$XmxW(%_pWc61+$u!H$Kvj?_v6mv$9f$%_#C}xtKVyWdG7v1MK6EQ>Ub`d~cw_WuBwXBFvx(KbOaP6OYkQ-j^Wx&v zDMQqbj~wfxyA~j&;y&fZEh{QJI*d507tf47!haA5+wSWn#E7ax*sIx`L*5=pSV{@} z5Z%e<={SAPIB|WSNpEF8!ZESqQQ>48qM@Q9QFhMAPCHe5&67rhX(5*;{}x6|=s^>e zNU&`MkI20eKFm`T_IaQs!6Bt^|Ib=pYx(eC6Ky0k5>wSHRdqwvMNju<+Cu9gfmLeN z&pJuJC1R2)f1bC{N&fXFl(oAuh;z(Mfz%~ex65*QZw{-?LzL4 zfK`XYJws8I-xx`(0%L;6O=z=T+-}gr;;ZdL!&^4DZ)_K83;S3$yURoE4;ib4gu#S` zu2Os5yah$}i>dRCZT@6->t6cmBVhMnWoOlfoObZju-Of>6qWhBuDmsm&KG}!b#mA_ z6<7N-D~J3(LG~$10!@dcDti}N#nKaLt;>$2d`!?n4f|mUk2~Loq=t6g~HNSrsX6MBBpxN-(xh|ewmENI?`J2j;H8jpvLd_x~4`VbO)U=hCTd- zqvLFXp3E{3pNCVm7*pd<8o~QLIziCI>AA~tY(}G(q3_MsaxZa#1$f1da4OG5Q1Q(_ zF5!Nm6ws*BdeFUixN6)j^yZCe<6{U4hZzh%V;xU|4uYP(93nO48wWvooZwC>p7wfz zbZ2BBZLPC~cK6%pHX!GCktD3*V_JO|{*&wQZCGwq)jnV=wMlmQMbY&dxrooyj82U) zSs43G%cz&IXC2=&-Q-IK8ZvrpUJT;LT5>EU7_wQ z%kJNl_mMvr>7oIS3o5-MS&;I#PHrn|%&~;*@dOdCnAEWIUNyk=DX=5+Bxacxvb-nt zm^8Y1n&O~rCI}Umugc}oI;#Q+=Ccr7;}^DPMM5*NX^>Fq7{v1?ev`&|T3le8&z4Pu zHiNmR-q~yx#l0l0&K)BLHnM=1)1O+ta;Fq!OitpphURGEvDXztnPxW_alUN|s!ogW zd!LCFo8DsIwxI3Bw!4x*h&mwXXeMjAsb2+52>jcGC(JpIoF1m5b(E?Y;f4FoC7E7A z1p!;xa&GCZ8KKg;FonB6-Dt}Ft`saHUz0&_pkH-6MQR8bp?*;3ZX5LyJgsfRFXNi!^kUsjQ|#t zzu|U&K=e^RbS20_PrV6T(vaw1ukpOS=?|c^ zF2XJ-E;U}%lhF|wybW7TXDeupB@W1j$ovKFxF&ulkiF3`GlQq8>=hyIh)OA6AL|pOl-DjrC6TEpoG5_ zvzA~}PWhw$!`L|mX9BFf5gB>h-L(=ADOl?8_F>5ECzi=IDh)ip_WttS=M0k=aY4wDAx)Y6cJD51S|gi%-cU zQVv{Fw|tOT;~fd>{5O$S7rgFR?%2`Oy6mgEN&3%lAIW8icIlJ#{3JP%{i(m6~1Gi@6ya%2J z9q`4;B+$9nb|{s$CS881bU_?NwF7(W$+8-X%{VBV^wQFZD`bD)nT7I85KHou7Q8M< z$G~KKSnYAg<>z9Gb`pD5Fx%?7vPGyS3J; zJ0AxVl5zD)^GBl@36qmIkP7NYk+Cb4Rvz{jMBeRvwOfp$ye8Bi*~A6d159Au+1`$( znST~|&VW6+^qvwk@@is@)g&t9{Sw7{=?M1N? z?#^Bv9gDz{Jc}nsbh^0xiD1ejGj^<(USKUqnm+rY)ZHzbK0}B_R^UJ$HvLZnS^XK zsGk|Ro2n_{T;{52-BGlYlg)5ShAh#<08LG6FGe>^9%x-~KHKAa=CbbdU{^0A3(S%D-movUj8|4J6 z_VDS21K$dvdEM}uPo)QWt}N>`ALNIo_~0JRCST&sd0*>3HP#Md-x;64ydi{t~%H@ z*}K@$$voH{j3@h;&i8hIfbxDyk^eWLmxbwn6MEU1*#0Z+G81ufvT*))`kz8C7bh3n z|981}>%VeuZA^A~7!u-bMi=++e_I(8j*;<^h>jS3VPSiFJ121=pH)&Sik0x(cgOpm zce(D#*LvlB+S4tk=f(3`GdxUKE=g=_>n|Fau|1^eo`ESQm?SmLLt9WcP@bqS2?&H8be&7UvwbZi zI2%YI3zYRJ1*j5%s7qi(+8-_**#8NluYclh$HCw82L`P5;|h+IrK!yoXrm+eiWV5d z017Ifx@ZW-HJBMR!0i|S7l>s3LE*ovO@sx)>dX9^!-YgdT8jY0kN&FeIb$Yo09npb z#e#KTCEBWQnA=HfYff)zZ~YH};x77}P=L7vWA?V{;@QkgYH4V4Z+ZBH)d;wnqVq#H zyx#9CwS{zZ0Unq6GQB4ge$zIC4g&F5dwXkt{U7WS}3I5i&~%xRgky9)DtIK5vL9 zTHy8UHmA=nfa6kO>j0?!=l#pw^i`C>*_$WgW9Jw!nHo)BcS)LFHR0t-rGk+5`!$7c8bGsIBs&9f@ zgEy+P#`Dwrbdc&<|l4!9DudY;+Ucb`nc^K@Q=<;^N09{jo`C zgQibcK7O`WdsI81tYrZr!~pnD#4%Wdrf*1}iIHQ%c)~u2H(dUNl<8~2TdI2j_I;12 z%TL5tH0*cW?<#LIdU<(;t1r3tvXyVhpWXpMB93_MiT&)J48;IfIl)cU6wU^k$>(;) zeaD3q0*XnGTx8~EeXk7gY^UAfVj+RxSt1|IXvkMu(w3;Sr} zw^U%Q6)rBS=p|Hp2~ekab{2wJa^cObp7cl6)js`cvN z;$ds`Uy@!Sy!`gK0Qmm9%frbSI3x-C;+0F9<3fN*S|9KDpd(A_XgcE2TeD2!T1qdT z7X25Xeu{RdA-9vkSeaVIxVk5yaox<pr^rX%rsyUqI41`^<#ddcFf6#5^fv-(O%gSI@csqI+a#nlairP552-bcEB3z8dc0ag84B!Zk~ac4P{( z!hmr{BN-~K8j`}Kq2-P zU8@=EP-hb2cmW)Xz;vU0P(#n?`bbdLDNNWO2?4m1R&=>uw0L<@F_(Pg?n9 z9y7N!e#rqQB7DivHd*_knpr`3W0NGE^9ILYkS-lcY5QxHBmDI`t3k&p`fe=;JMT3T z{xDl+l~yqD^w zIwp{woMS7VVv0F{l41GX0h5ZWrU}y9%$DZyTAy1| zw`q?qL=}l_0oC=wH_0Z=U^+B$qgUt<9Xu#GM>Pv99rL(^OX)# zm&vH6HJ-UJ(F2>VqPGp;#wDn!IU7jILD$A0-ZC(G%iL>>PsQLXP}?^W!il zHh$#xPiWY_NP6%i#e#UE=BhsoRU+kF(Q z*Lj>ksOjWgw@XBC( G$9OX)cP$Pwb8>8sQk{9%CEo~m+c$vG**}WUC3B|4WphL0 zdW(b?;yDiqfSdIogl~9tTh07g-IXWo9Z214$r!PMe6(%2d|EI#J%BCE7#kRyTX4@g zIn5H^vZ$GQl{!cUR*`Z;d%6<1muSH|;vuWRu6mn)yUwW{lgNt1x$}SqalIeP>`u9{ zSr0{&d{G6C%D3$lcIa?_Wl8{{O3SngvI+xB#eOgAVo#&+{EN`x9t`)M|R9s zRaN6$3@cTHhH*CC`s*e({O^-GiaVymIygIxHVp*Qqe8eiaJWABoD!>c`kPpqbtPrs z0^@eERgvVl*poOB723Z=ofNz=&#ZlT9bgpZG!Bqo841hlLE%f*Wg7K|1&Hp58F3$= zU1~f3Hh%=>k=?C?KCJT@LlS>q~|G5H*YX(O;wevubr>+C-vrzs{o9V{+u`+)I9-HQI;L{{AnLiP$f{uVl z-+(MXe|41Z(qc(AkVv!Ei(PnqmBPD#~vj8Ua4)n@2rO%l6Sm?VRjLH9}jKz=4!SkGgi|sH2Lc8e&oLk^# znM2_#w6C7rfaaLLEN!m2^+?r_&M&N|Aw+p?LdHCy`mX(Yve4a(Y)>2VvJMfmTuUx# z&>pWc2a2u(q4;FP5Q z)QHWv{GX4=x0>DSu_+e%s~5|*=*$oqt+dt$oEiIpGYC2}cB5W-L7^+CF05BmnkL-7 zU!{w;a+Le@b&qTAz6aSsXGEnf?Z?kwy)G#LsbtC$>N2_$!ewzVK5eJwHf^Kr zm?&3@4(X_|#c6j>G*c(11ZRZ@g7@2aRb4vyU&DU6=hJVjUbF)d?!-7s`~|yq)3Q+z zg5pw2`qy)lJTB`jkM7jU3ZfFtZXxATUM`^>cG9`i;Q|dX8n^zS2OXKm2B-$`P~!1{ zZVqI46^v;=Rk1UHGRovzRHotqVp>$^BUKk1d{CVd; z{|vU8R)S01nyBoouWYj)YPYc{e}&8G&pZ@<>xZn~>ko$(jn}wEd@$UW9OI}3o`^7Z z2)>WW*cIiqwu-E6LDRu0C_anT8sNvY${Edm+F5xSFuMPpUoQ0?%*uA=BXYUPnV!3` zaZH|}O9EW1KcvssW4QM?RRG=p7E%?j#A}K}E}Mh>dMMW)@cVitpb-DfW~+?OVXjYG z+Rf74o8mEvpR|;8AXy4{L{%2P@eX4o#TFCLw+COTl44pwwnO~0OdcEiDn~_c#fd9y zCh(jDvUR=W<++O|AnZnExaLX@EhQTtyn*Rj<~2^>pm{$R6jM+%#N)K_`NBzz{(^l6 z5o4v*3Gvs3j`tMwg8?{LCNYEHOo?dE`2CpS-z$o2hMmiE=Tafz9E=jA7DLo=3#1f< zqxjF&Y)MiUlk~3$<)>L*n zSTJS4;?Ni{mG2fQJ2(K*{}@C-#7@qa-msQYu19xqs9Z75p zMUYxu7Y0PX5?}zPh0Fc?d{F#8B(hX~P}%lQ{LBv0ObV-$*20O-n+@v~{3-8l%k`fs{xKpr2^0 zatooHX+b-UWxgUZAO4|jVn{E!027bMo1*?UUV>%KnqJpxp&?C3&B%7#JM)I6a9Hm7 zSmocit|#W;!(KF%4|)XYf_1fj^&?uv6hJ9%>K8!s5`M3QZHIrDY|v5RgSMKW+!O{; zwHmE1W@trsKMSNFtUQu1FHHtje3A*;7Bfwa#73fD>eQ>+j}tKFBe(pk%zDG=Wdl1Q zY`kYk?~tUIv}Pr(VV3!f$;Ck&S_Jk>a?y>c`>KI9bfq5_H~Xc-hV#sU?wd^~Ezn$U zG7v2~_`KfXP({XI7xU&&N-S}d*j3ARsk^3txZB*Oe7Z^a+LO@v=A%?llz>@U>YDWq zvkO^zbTt*7TIQ_g?X}G<0<0Yh{3;48P2~f>WEInSBqwN%__R@c87=}hGhO3T#Fn(K zBI;tO2CMQVG?E(b_+NvBJDiiHaT*HiPOA?891_j1%A0W8Ibb&@-^zsR$aZjk#kN_$ zz7&yE9J5vTHluvPb#!iD(qzTtB^@?bj^K`q8QLB>Sy)d9a!`??a!jicLXbRERFi{g#&D0D>=mfG?e2`VLN^NhDIIDv81wu%F&AeO z_0NW*wpDikGusXV9pZFQ>4+F+vr?}~Fho7o$8gH5VN7Q${a3pd-~J40T=kCX3!b(1IZrFN4dIozn3Y=+*-}mJY3v@9 z_SAKd>Lx#a+@=%jYh?9o++#CApxFHcUG1jl^lsX;9Z#>r%%W z*tP~n@GDguEzYaeV-ltbEV3!Wy}5_bq%hbE1%!i39IdEJ} zPY7`yHYe6#87aVLCFh`Lz~*@xfqr><&sH0{wzD_kKH4f&=#*y;Cd;bfs2ai!%ZSno z22mCp@3Y5IlWx6AzzGet!;yHpAV^d^8v}m}(-wQMNwTMg4Vf z=3#&5?EU48y>6z?Viv7Q%ZsF2=n`qo4`X97i;5Cm4yqD6OMht+MjoP^dB0F4%I}qR zF&D%Txf*GKW$7X9=#-(^=I%QXE$(V`MMn=htr2?PNde#p?I8lzYYJ88o`bu37mR8o zNXujCR79clZ|pplGy2;}LxeEAclDE5M{i{7SP-cB8Z24$(Y0``8Wbok76LGAH1(v?Sii?9M7Db>$j!?lhm?*qoTAA4o5mb8wfO#eYw}@le_Io{3?Bw;-3sZDHdY%SzT$jJtY0J%H;S!06j1-1V)h|49bF4w^m2x*Chv79x8%Xj?s9x z((JM8QXJ1r@gax|kFAxK&c1b_^ zsx<6h@#T9hJrJAsnr^&XYuyhL*fAb4a>SG!22yNwnEFTJ2(fs`L&?x+XDn!7#j47S zY5%e$rhj!IDXwEUJb>wvZbU)FEylL~?fY22)gXdsPEc~px%^~gH6{7d*K%`REUG&Z zPt@{~gZ0Dn?lBR*y7;nj*3P?46_s4S$g8Y{ctW{5M21O15k(XM*Yp(WP!dNF*cqC2 zXtpWA*N=H($(l#pOBk+=FOh{oSc-7fs6SGGbmPwI3Njlq&GYf+7Xp4o0u+;0W;N8# zqr@-rJKsm)-oSqAsN(tAx7O3HT>srzuUapT)2d*24!>i2ZrusTW+;2g-5hV+KOW}~ zBoPlN_NA;^GI(9Q8~|INL!1;^)czR}6)IpUT{5Vrr;m7gxuc#K`Q4W)>uM@=OYR3yC0<}W-l;BHQ6ebWm!J^+25Z|&KANoBz#D39d;1|ez< z=t&{R6a1R7Ohyvf7#np;RZ}F<1-x2?eUS!zsKvj4>1EK7z>o~g6|+pKV-+#i)n|LS zILa;sgl^-DFE3*xa72(e?6_Np^X>I{1nwRH1wJ01H)SfbiQm1=rj872A_lK=>+<3u zDRxNUd}$3)|KDdi*-(MQnzoJ3^9Bz>e6MYJGP6zn3lOj0%h3cAdxMqgmL2#cZiy`) zHDltsc3R-tWmk${r7R%jY(^7^T{T-OwYyh>=esPgjZXoQkz|B~-DMri6_&oFzZlbO zZii7$vhBH)h!2l7Ob`UbLa^vh**2~y6{)$;JPJDfeko5G0~0ShhB-U!b#jvwIR8@W z`+f4S^STUr@<>vIlL@i1mTWk!sN+plo;4RFQc_1frfUK6({5u^`dAt#*EdsS!rtgx zdIx=^s>t?b&LxRY;9lRIrC3ebI@-uPdrEuyqNTvouQoK2NyV6}(b7%|b9hQ}a_-ab zkYi8q40o-c`~~hTv=m0Gsk2kYY}vQ|3>IDj>jW{$X8JLJ=4j7|Iz$4&7Y^TE`D~i6 z)h6^w=K4Y6V_wa-E#ocS#6bsUrmTI&sm1o7%VUVLG@=@M08>uRaeEuJFz2L!r>S{J za%rmLFsNo&rwznGk0Pt+CU?3Wq6V#@R(%{Ijx%_e?B#&ZkjwK^{W^*y1Zwv}jha)! z%yhH)=

    !1q8F6?3>p54Q9y-%1a!_Yr03nJVA0z9apbZb8Ejoq!(q8BUOGGjTR+ zV9MVFIhXeCZ^F`}adZl0O??(B$@nf7t@?`fKwmMgGY(2~6``*MNo^(f)F{HlOZ$yN zotWcgJ-iKX#JVzC_w{YaN=>yxJ1wYgk^Ydjo#tJoyKju@I)K~4d(M5Cb6I2SPi~9D zyV@M!GD||}Cb6O38o8rcPv)s7!Jzj_@pn;~H|pDW1Z?%}MrA;bQs&hvXP{$^+|K|B zd0K>EsvW!OF^n=r@i$d1H(Vp9Wca+b)Dp@fh%bXgwFt;7_<(fr_EJHN@pJVW0BlYAmcnmz5k7>fjfdv(W2 zgy>yxo5@x{*hf#_NJJeRA%R*98P>(+p7&z%Y-gm#AWY*q3_~Z*R>8Ofw#5^SQ+$>r zCpP%Asv(|)sCrkbJ{cS&T{LALYqnJGPM^!o2@6SkX3xoX!b~WZ$y2{P++EC`e>4J9l+GG=6k)DGB>j6saw38%5&$A0tB%hnpy;pZ%ibt{9YB^b+$F; zJ(7Q4jvs5S?W!lKlYWnDMvmH|Dmn+FMVk<8#CPHy9?NWP;C3?ZY~YmA{A+=Ezx-S8 z!NZnMXheJp7@tp==;Q2|qcw22&Ss1#T1Z%Xz~2wq`L;T>XoA;v{G~kJZz0^|<76p( zPXzN^WN4==BM169ODmh!Kj{VY15cIDBsDR0f!gE6dxw!5Sz#I_ULGx`3bfkE$=)>QFjgwy0fGl|b-d*u-5N`{wkh|LGIYn-~uNI!PZ?v+9* zu$U;ow%Ln8oR&O$gGV}H0OVfA0|0hT3cX>Yse(32t_Wdw2r9oaGPA3YP*&x($^KV# zM;+TOXFIynMKNdpFpzb+M?5-+KD3=keaWhws_a%XKcTS`virP%K}2oVOuY&byR|N` z{9hR3k`_h3nKxNNs=P~uZk*{Gom2n9;=>}@#)Cy#^xnC6;AB=+8M;qvxY%i&l8`I)4 zEwlFQviF^bz$Tn$_hvbCmJ>2L4vx3A(kMHU?_d3|D`{teiP~xW;$F|Wf0_n22f=i) zP7Lkv3cTLZFwDm^G9GrO&dqXEv!MC9z@*{4(xlSpB)r5^UFU%9E+1Sk_`{xV{PkRxvR6hQ21gf7b z0G&OpW0yPlM|>@{kZ{KMjdfN z&l%^d)dQRwBM_XD$L;bl6AVh%ra#_QN2niJ~T~?L*o! zwB_dFP?Fu(6Jzplh-D?D@KkfjOe0=J&F%+EYVAR@mJtmXV{K(q+$_&zr3g&x>)6$& ze1!}@)V;Eqi0g(U!)tTW;*8aP^DYAU&HdspTKewKJ@^34bE{QE_Q%isWh-tmZe= z5Km%}qiDmF28JYYXRxH{QIz-f214u4zce|F1co8Ad|K+yN6#@+;_2KZr9KXE13}ub zNW`;i*~)`zlOPRLYAfS2YYdrqWXd5fI`cup zbJvBlt*tW_L1vXMm<_W^=g3IHT;j{O2X}slz3sd0ma*04O0t@ROWJ7pCiF^#Vz(=Y zN-4+VBNK=%#*O7pF?8E5z^GxE#SW!OXNyw#HL!{atx=69s+qI4F@>u?gsD;y$|LF) zYcS+A30pHc%8Bsjhjzi|aO>gLZMA5& zItwLcK6MW|^Z=@}zYf|UA$lJ7HdV;aU~H;h+Szj^#ZQaU{HMsEoHDU?gb{Rc7jaR* z&jqZmG6xefs3wC|4PJAqkOUpjx_Zk-9Ek$q;VVL$U*vwlL>o}=!0LKc6maHL@&fme zpbi1tubf=@#`B)ne30&_>Z(f*+xQ5ms^8y{)BdjRQ0Q!#FyVQ?*I29Pl)vMQD1N|V znkw6HQ+OXyYpOw$z;T>qA;UdeB7WggO4gc%MJP#&;CdQ`AuOyukdw%EGcB=2_953g+bqKO;BFL~&E5~&PP!pleM!_r-ln&pX^2A?*cN7|9F?Op;# z>(ZYTmr;U3j#E}Dn$mY@3{xxj?t$Z(T|BJEQB(ZqgQo_Yh0+iN{saeVFUMy_k>5ty z8~vftgD28j6@i1^fwKxV`VIcEi81)6@KQJv@%)58JVapXTim`#x;w6I_ zMr#u2pY_K-jZJX#DX`RBA@5PI7$M+F4u*$Hd}SWUo#e^rvqShLzy^b^%A4dl{AEk$ z!#D%xS4Mg9oPh{d<{=kjGtKu|U{oiK+EONl2)37VOauTy7g|Hm!=ZfN13?|mD1~G= zpC6u8QThHT>$BD!H73XXb)_}s`tfjD)iGv!E_dc^)}uH&1aMAOa^92 z233yhFxG&ezEMEx+;fbDIdMmB7^q5j0)12(YOY@AFDlP)D)0!Dh>dMJS>xSgbN5?j z(_7=57)#36!{0mABuTKc*B(x&p35_trGAsMr{J2qCoSE&QOl2l-CsVFoifqv@~KKt zA>V>kwkn5qFGh4dbf9_v^qOW{?E%D<3B5HKcqpc}6`UeOh)cTT*GI!nK9b(ol^jw7 zPfqa)bcP&c#6n2EU`Dq(2_r!&Jlk6)N3Xo-*#yblzYNlC)u~|X>ZG_#q5|z00_mty zrG=aWUyRD#7@c3Kyr9kWecae*|JW#jgHWKJFj!Mr3bf1;fkxUj~keh?$d-KlML*VbNt%un~}f#R88 z8k;~Un}E=CvI7YumlEk~d#~NtTZtSpfA~O7Y0rQ!KR>%={X0O1assa1QjceVOr7KD z=Ag6Z7q*b|&x|Y~!QQ?pz;fd0pbn|~CeE*}rj4!-`}g{BSg1e`;1A*%M=4Vh&FM*$LU0OjpLHovmGw-E= zRMqnzcK*?ExQxKxT)03yupfZE@4IjGv6(jpb7vVDObT^pbA29j+<=xGQl$UjaUl1= zOu$n)HGbHcJYMYqU(-EPS9sHOeGvXk9FSuXRiIP-;NQP(UFulFAWreq%^SBog%`XwH> z!Ldm*$iLyopWq3g^Zg_DT1WX~FY@gVJ?_EH{asS}A@lQ7#O~hc{P;Br#M_)pbPGb+ z6|ma(_LF%I@}s9^nxB$Ww)l^a3!dtaCc3scc)elT@Eluv1FBiN6ijXPSD4&!y3*G^ zwm5-PalWhnaIFDK@2`0i;J&re`_*7Uav=6?ZEtU3 zLT{Nc?nAsb1-s9~oIb1~fof=G>k1lR0=0Jw2DC);EY!u`JAi5o`$v9@^8%?w?nGer zQNQ8d0c(`_k@^8uJpv-q;CX!k$UFh6&m8+e^%Gy>*+6PhG9=@F`O{ zwAEAo7yUlT{-lhADLYV85>NU=kjF*OxPfowKjH@e`WlfrV~*{Izzvq)WBM+e|DEH> z`FBq2g#*NS{v)PO=kZ7E(_nIk%^|QU%RAs?a%OO^4SH>Rp95sE#et*E1t>^gawUJq zX~zG^pJ5pQ*qMNcLG4fFP|eq znSp%b1N#8={g9cR0EGi_Yi4+_eG`K&g2kQXG3V+#Zt?a{e%U+wW4~!|XYzcp8-3)B z!T8Yp2!Z$*tpJEQlb;CVFEE=wNO`b+!nU#j`KvcLYyQxFi@V>Z*ZXJR672PX(}YNP zKkoQCyMgsjt}Wo-Qi!x4qyo6F@s~dVyT?4A!2NO#pP)gwCyx@AyQr`D8Mv3{aJ``4 zbHUc`Z*mZqm-mEh?O3ZjRt}8nw^iG30xUzr-*Jxs)FE)QE0|oVw4Lb_5WUEQADM7SSSnAz1O_%Y#jjlkGY5E_x$H-?hoOaf6Ti7(?^_L zLonhGhlpK$66D- z*agI|8{albh_L&wkWbK|sOLMt!0fL-9M#(92_h82%?BhHVd0Lw)2^hS;0xgQ*U5R? zqYESl%H!%JcDKXNpuevba3H^+OmT@PrcA%X$NTL}mzJZE{qZ*R9`?EJHsa&dx6HL} zE~3Tl&6#zh@anex&<>)1zs7oMX%~j}FYjjoE9(&d#oWTbcUZS3nZ-;!n}N-op&X2w z9%O&#eqa(pG-YfUcGu|yDTaVM;qRM3TywK12s5>SpL5*vsue{1-`X0+-gKXOa0tW> z%kJx@95?J^gr&_Y9_SiRpeT0*r|OWf>SuiC%YXU`$Iue75$KU_cOVcDGt}1F~$r-EIV=o>Ert}rfOVu&!084 zDv)X(|7_fXq>C-L@xj<#-TB+NXyX%L8}!D=S_5$Hu-C7lm*|kMFv%P4%*^9k+5Tw0 z{fd91hHu4VMOdzZO&;wx(0cZoeF3v3AU-7YBEAzG>Qx;ZG3$fegyj-sRWc;PR~nQqyU`S8vH)o&Drf z1QRD#Ih7_$|<`W8$c!+%h^f`2!sQ+XJn^td~rEPF@XJ!ql(-o-2X+vy{F3cxr;30hsB zMlk-vmb=*)1^#Wo&0*xIlW}`9J#U4n#(LxLe#|79Yeo}j-_t<>6Be}eE4@5BUP7cX zm!KiG?MkLHGU?2uk96!;s($MlsHSk0Lrb{Q7tTzJqG)KnQX4?N5dwyxVz6ID~=!y?0`-SwZ4FU;ae|T*% zmS~gZCT7$y0^+|(mhQICsvC~{n5=Ero_**Te0t8k8HIoUwzVxiWh}@zCAU9ECTKj< zAgJE^P)PIPw-VO5bgrWh6-sh0LMYF%5ukG^Ru@@AAwrT;MEOErr~;r`dr~nT739Bb@QT4?zi{D ztJF!q@uGBxpG(fye|mUTI^Q8jUmhjiY{TQ%cym6FEq^iAMPpi*L_I4#EZNA`bP+3~kuZSrv}z)Otwp<%0?Eu1xx<*z7kr z@2#9&9BluaWu1jLLVwhA5n#1wuH?C?42dN;Y@ZB`MqiP3O*Un9Cs=LA)-P*r&vj3pZxLIdo7q3W@_ANRjkerwd! zc{kyAl`j`_-GfWI4xO=)Cu_WfOx($LG)$5^4++%nnDM}J!6WNAvdkC5P$!MIoh(S$PwC-w&(c zAf}fiwOYeP84f2ToAO1O$A&9>9CWG6QpP}K`rb<3*?2#YYy;?js3dOweI(PhbEuuM z>JXt3d-Q^irjI6C8ORvTjRM_?LKgVJ{TRtelPR)u36*g_E4(5-!&-l-Y)~5Pduanj&76xE5c6p=_ZU?X2nW4yx(mZ%@KpC&8%J7!^K(>lI$Xq#&J%GbfsZU}~ zzJVJtTqdJrLC|W4kbrrwON}EAQ>k#?$3H!VqCa+zm6*;iFjB2*EI+ncV{*N}Q=Li* z!+#MMUps`sg|?4S8nfZ0oY=BF(&qJ(d@n{txsg1v_`RLfV{_L+ZI{yhl&6Qy`;sg1}6E;=*UTRTOT#+BK{zAE)-Dr-mXu{s8E=EAYp+Q z=c#uci}zbak>I$5nf&zY{0?Fjim5uuGnRsYnCsB-9^C-2JK%Yypf0$&PP1jN; z#kO;s_lH1Mf;x78Er`!|!mf4TWZda&+@rHc^v;2b#AD`h!@k`y6KA}n$c%3m(ktRB zSc3BS6NxyLzU$BI;n}6o26x|a*>7c?q`24{*G1-I7xqx55`82gt;nj?ID(~1^#rLi zj_9uv+G~{0d6o8=n)gK2#7jiqd?y;FiA`nx2r9@Fj;4mFmUvH=Ai^$0^WS(PCIqLu z@t8Z6IwNQzFm^T=nqSqQ_Z}b_I-z&XGjrIatcuw`eqDq-cwKlKMP2Fo&O* z!YAH=SK_M+7586hlcaT-y};;;=$g zmqcZb-&g=2O%vG3ouv$Ooh_K`DXFnX31n5o%o0q~-vCnb-}022K4+&bIk_r&drUUx z*~^YmmUz|8b9>HuOEata3#-NVvf6ZURy|WXb5nqxe18{@e5yPgfBy0yUd9|>nW>`p zMl-=$~bg!!<{iqIJ`7AjrW>F$z{{-c)>B$=9dB{t*cKZip4K#ykX`nA_A z>$SbbNWJtfKOIh^K~I9nv5TblQlWI4MSI4J5XR3AUN(gOvT(Hcce^wjc~~}-cnjbA zT=YGXyln#CzoQBYvQ9XB=)p7zlIGD;wh4Y)H3PAh8x==#sNO5uo>y$82*4&9AR8RD zlMWgF>%4!wE%R?}B;$znYu8sA?)HL42|qk^k~$8`aco|k502~u#$yxsc}I$jmBGr3 zJYX+-xX*ahU8R5n89?uA(!%g(?Non)0#S#>+ue&ytVjlhSEZMwu69)%oT5#yF^(T1 zk)irr)Q69Cw6R#hiMaLjkM>?}l%bdFWjD$_IPg=_`69cd4tT02^fDJ4yBykz3;gU5 z>wXrzywh(*gujA82HDt_S4&bAg+o~_&IAVf&a*I@a>_J`V_l%5v*)!^38LuWb>^pC zq*+ZjSy6uVBhUlZC<}$@&APCc0S0L2m%|8-KGZk^#b;|K5?~Y?j)00Tq2V<6Ugx<& zTb|i|q$y-+7g9I9tvfhiE^4X9vePHv_R+|N_^m{Y_pM%x(1`0H`L_lcD`vMOpMRMP z@Fd^}B9=~nNS)Ovi>VpnLICc?UFnvE!bG-^2vs+Y+#Qt;H21>i{Gi4lr``a%+Kkb$ z5;a?_=IJE|&k;*Vzw4XLn;z=W!FdSTq`1;^fB=6;J4Ie-vPAmw4qeVTxk@pAJ#AvG zCEqXKDYR4#oFtB42rD7R0B}XUnP%gS!WisI3F`IK3znNO2+Pi&N466P%Br);)M+{B z#QVXa1gybixq}Ol-C^+vM@WjgT7^Yq;%!s%NFwu>uogI(@pS-I-`aDZ>nQw_rj*!* z@f%4aFPr}FB!RPdwVum03dtlb5vpcDw$cY^x}-f{59vXg(GJv4DCl|&Nt zBgkfk4-Dv|Q`qhx!gwk)In%~U1V;^paT3!^>VaA>@N?B~=OAq&Tfsp8X_ z-z#aEJKmX(?ZKki!y!w!l@`6pDsM$=-5AF&RaQa$gX{LJw4y{6P)9Wb#^vD_xZ&p$ zuXDYqSzWmWJ8M3 zYK_7RIOoLvr_>_JRFI5`Pchcnz?qFmVfx!*qrPp=i(xh@Wn4>uWb=s1Kp$~5g;JUO z`hVD)Wdp}5>eW?FZ&)7TKjiA$FD2Zt^B?KYmiuCJJ^QNzQRqJG$$AVdfA)cKnan>+ zE(34Sb{(-gZ$4cEmqg7jx`$4DNt~Y_c`J}z2+FkSiC+`!5Z#}s9&}tn?sr`qv)YzY zk16EyzVq<_cMy8!sgS<+&Z}mDsEYLd9{@o>zQ4bc(fRb#Z3+%gq|)v_qBs(z>MO(xAXvYykLV!Qx3kDUH{!;&&XG2_qU+eJoTE%1r9=W< z;TZR<%We2=sa`#l_Cp$rohjd&Et-67lU2MC zPJ0Y)rIK>_Zp)^?09(>-sw6+DEo|+{FNxkA`f-e1&y@xO6KDH&UBk$;nR1W-+07- zU~^_b^GB<36g4RGyNrE5f)y*$y3cn)=E|%zO*8cI5&BHgOax%oSW5lHEVbZt_4BYt zxoErBXvctw(Ni=-GVc7d`p9OfiiLFqu+dP!9~9P(wC1FI=K}9L8S~xk}|S#tSkReq@;ROt~omUFx$w zXrEjLq1+ZFCr|N;9McaJUZ%@AC+0x4msW}MQhfK9iqsHds=*Ve=N(IhTeLae12raUMkj;J}ybc7-BixB=4T;rC?C_rpb%ey{u1KgFtcsduIO) z^%c$6CGi6V6vm3ZsLyR32w2Nl!q=%P`MXp+UiF$pTKbsLl-~%dmC|0gCQ45CMKd8L zX>X2id+%S%;9Kd)D$O%7?&EpjR?7Y?+%REnEpuz^g&Dqqw0+x;UU`3SKw9Y+E>#8+ zL*cvyVr69J9w;x0iP+N%>Drp@D0fDQyet$9zXWXpH%@e<6y^fb+S~Qe1E)(Q-D8IE z2egL7hYpaf37(-od`y0)7AOcCLow5-cr!yek))N^f+lnOV6;#4d}}hB0{w~z8d)$M zu{+>U10ZG87m6z9Im`2+-v2!Hfi_#6bI3x_hq5)EjPsIAb4;Mz-U9RF8+9v4Aqk#U zWF%kp4`#Q!;`WOe!>`wAglK zF-CPN>OJy5^Ga*MAsI*GsPDw&u)!ZWMBgbjL0-OB4%-)=Hc78QN zYF-4L{QRlE$!(T^FB4>%>C+Pz2CbbF5KF6<+%)(mTviNSdme*F9@&U2J$!%VM&wCg zSjY4cYFK2hn4dwOEf8;}$%w*#5f|Z%Q+wHO;9}TwM<&Y}dTgmM;#zIJbc9|yF^Ug8 z^hvuY>%p78`rHOPW)#tMpX}ME2QtO?-G9d5R(DTV|0En!@cP1} zNEQHz_@gmm^1aSlVqzB3ho?;S@J7RxH6iUDJpmG!(B*HUmW(&l8+C{$Djh2ln%w-6 zcVRsZka6WX6ut9(Sq(M^THiZYcT6nGbo&wDzR}e)Pyyb0!&TlL(BsCuP1%kx!BHW1 zuj%AoG~O3 zy_HLa1z~)_K`o@-wzn0u2W@MzNxJ=g?6~&z$3e>FL4T`aSMTZYR}gj&c86px2>k9T zWQ!c9y7Sg9(pc~g(-@kqA)X`+Dq?eg zE`(ifz|WtT!0(Nq^{{A4F6LOu>Znc9ny9Vvd5JjF(=3IKln}{-SE+BQNaXC#3eHcP z=EkOP&}Wu=;ZliXwYJ6VTML=Z9M#{d@#%hk1t&h}^|s{$ltBZ-SXWn5F-KbMDR%Y1 zzN9{oA7=WHINPA(=M~kGZWE0+CS7Pth}het&TkNC3N6>ZpTrakoVl4kXXnwZ_{{o=;+D!NcTQ(QK=9gO?tyvcj}? z356{WM}F$^Y|$XB!_m6!L(MApr?U;CgA>qckd83wNGHt-al*%+I9v6cI+-uH^ZHP+ z+g{Rp{FdK&ebyhrU$$razR4KtD2*b4Iejg_uD4x%Rr@saE6(Q+O~5YBPaqT;qS+Iw zgRW<8sIi+bM3CYUHz${)guGUxnQb!D#V)s(J`l`whAlr&whQmW5M9%p0O)J9Hlh+$K zq{9y1T5ho>QYyFNw?6OJ8sE05Bfk`wSr3lWQiJNg;p#UgWs1AFBZ%Jci(6cwkYvvS zce$*e&zu!RVH>y2GA#=j)^(M~^`jQ2b*|*1vww^!^3uIi zndE!5za93FabUk!&G(~6AjJ)dPcmq>NXVP--br``rzg;9__`)?m-y{W9mxBW0E9A1 zOc^KqxBL1&KC79`FruTVca8yR+{n=)Hw?(tiKN^_Gz(GLShr}Q1L|+Rv<4~od8T~2 zMT(wq0MllI9-B%ff;j07@3COrrfAOK8IZCPOXT&C6ibaegf-*$`C^b(xu z5~UJdN$#&9e~!Njx<3&4yy{UB$CndUTe`AO)%?=@1dC!tv!VW=@Fc_ZYrhqQO> z`h^d1;kW>629Ij8lio7H(dq}xGc)fq$@#FvQ1U*dbapK^-KR3k9bu}3LnY8`l#Y`U zL*d|x&&4RF)}CM{wU8ph$I+m&xo`$prrrotFVfo5+(F<342c7_v9L{8M0?@2@xVd% zn4fTY0TAgmcY3nBt3GpyNm?ywpn6gfE3@Vv6W_X;$19!7Yw5WspX$&PG(LJS#YsJg zks1cIX{+>_$q(2n;WsKee71_Tn;#MiuwOiRfl(BKNq*{2Iwn$g=fMfZ)Padxn(CZ{ ze&>AqaJ3lzy}b%R^iAIL0B?6XXt&LKOF5PH4;e2|F*xlGsEW<}Z!q|*NZsZ= z-27K~nvcZ}o1&$91cO2aVH6ym(aR|~gh=~T?rM5I&$e;R^m50X2J(>&MZe=Gm$2eI zM8e<=#TsB5 zC+m!r)!Na{c*KVDl$|v7o@0XyCLG!pOmkk619Ki)HAu*4#u_=0KtWk|VuXi)^q3Ml zCmUPzi8rcC>~2{G8MjwR#KhP-{RB^`iiHb3WA&I_bXlXuPBxNNc%b7tlruZ+Y__kf z>@#-0{pmxi9}){+d3Sq641e+c*^%#-omu2Qr!Xy*n8>$)%e2fOb8#5d&A!hePN5J> zuw2g#V+|V%^B6{v=7&3!+(EQJ+4ZBJ@76SxLa=?n$e^buh{7~8EmA}6ILV8BjMq~y zn~R$3_VoGgZSi8;E6j~SxAk;%pZOH6pGhY*bB~mii3^lj(;|U!+vL&2;=981c0+wW zo(^zO;%i--4A5hykuTN)g+Yuf2I|GjTw21`sx_pzUqdoPH}dcwTN)r{3bqf+WM%Fc zOZeSUElK#iRokRhIV7(ulIN%}davhq!z%}HbD60spxr@~|1;jt&V}2%0i3$>4Y+V0pDmXo1 zMG^+lpE6QUD>=Pnrs?B8DdpV4ka9CVAMzAXSgnt6Z*Nmvs&?^_{-H@#69;h;MBcF> zco+%UsJWUWgydAe&@4lT{PdGB>63n06AW?2wIoFIz5_wleYgp4u0qgS+PBfTU@5Q4 zD3NBN3=Yl`Ih!mPHVm(dG2#8lrg+wrvzl6wS#Cl<|KcklyYXmuu8;a`Y910#nnz}~ zVIfv--#}{JBkL3RJi_KB`h)OYfo*QB+;%quSzmfmf&1ncl-RQ`{NvfxQe`$5;v8Dkv+=~^!QWBRkmxcX8q8(K6}bvp+Y_bhuTu<^b0 zS7rpVrdG=sm_ES~9i}9!b8JuV{*$HYdvpwH$QFpXtCK6zdj$V=S}Y78Vtk#rz-H;G zK=MoCh5;R=l3O=2qIIvDU=WwUIPp86LgsA4n+QGmYn@cS6V+}3OP^Nl^-r#N2+gvM zI~LPuSy&Fz68NK`?dahf?r+QPJ>5(7D-#3{(yA`tA1-IuzuejD)jH0NAPqeluwZ60 zU|H{s)BWt#PKuEn;^Q03;Q^#Q+Mm|%Hj zkvAx`B1rF?HAqx_et-Vq>hV#pU33cmxx#=A2+s(^Pz7aOxi*RwSEG2jol0dhDBJ$5 z&$U#OidcHd|K5p`ZV2jF)lta;UW5K3qMHCy?(3BM%Nkpuei#fU?zdo4k#wq09c=z4 zQ#)<~Ddq)uE@>t?2l!O^8695hqd$;wgiKwkL=;3_m1Cn>dR3^EkktxTnuU$@X^V$P zZb>u=ni79{tzGr`WmjH1>2XEc8fD|84{^82el1TbaJr%$dkKe6hBMxq@!~^3A+izQ zb@CMuMtJ8WxFGugbL)qDuxIoY21~rIGlFnSU_;M9rEmSwydX?#w|o8?Uv-$-QM{YO+=EAB~J!j^?>S$ZPGD{rN?9V^fp1)7`# zBDw+OV1w}xnlGtrRKcOs>yL~pK^f`(HjxNXHs5?9#g$->+ns~wbE31K~KS#q3@jeeS)l^R(#cbi4up1_@W3cPr7>}hY z*msT@mA6m6K7i<6IXhBYP9^=!!|MyE^xkI#x>Mvo*#=!2FTI9#m`7C+{Xjy4^Zq*} zTkYBuu73Ifib+ku^Gb+NtE>)#+ zL)2nk{1@t4C&{TdiCs%2vV;MU0)DxrgYfyZ7s#;w^PxvU@OyVH@GJVR217s5D2Gj6r-wi zK2U6M#n--_mW4OPkQGz=F(z)CC3%pl`@22&b4kjB?EazX?1%_Vg|&zASIe3Gy9GgP z1TR6T8Mv;?l#03M#%H?X6Y;tG0$fd!VV^BNSvAJ1e3(u@oE*2Mct4@39~ddpsDv~@ z{6KxC*301hT+@}6$ANrgv-sHNJbSj7ZyAPqp7ZQq_X#Mhk~;I6Mo&Xf|WWxJ?S-^HcR;XYa3n745tN%^-)^P0&Vw5V((PkTBvcKb$+t^=5wie zjoQ>h{VIt|`S{9nDbS&&-%W=f1Cc~UVkNb$eeRd9pux2iK9lFWnxwJm$ zXnWNrITQp-L_6U`t_<)|sZfyMeNRvY8-?o;CNmt8Ao5R5`gheFS zXHksS`xrK3Jxzt=$G&v=)1Vmb4_~wz5+1J$`!*PVNq0Jh!RM7#32R74p+W76?h@jN z6j!CTl!>jJd4elQQCTa|h>ZSX+IJPchok|g_s+_bf&p&Wzk5VhI3h%b;^&rg_D%Gv zrVio{+OPyz!AIT=@?e%qI?$^V;W8#y0u8y)R?fnt21uZH1%J31K%OfDZU+TdJBW z@CLtR_W6OAxw4mTmTe_rEMi8m~b!>oc8IVIa&dABhgkq;_aIu0@@yb{&s1sB)FJ$dhJ z8v@-U&-^)1C(IG}4kLWW9G`m0OPweyR+fh*aK+v^iJ%VVx(dSpYnrpM0&gX*smy4@ zIF23FFlIUAj{M~9JCuXX%%T{ak1?avMm__!@zQ||!9CAA6d|AI+Pv<~KZHhYwm;VD zC08%f&A&t{Pn)$U{vvS z%E8anN%*Vh(;(;FH#pHo(rh~)*2ItVF z8JSTDn+^-CdEqIFZ86(BV-t0*zbls-LtnnKLN!#I%s1SafHL8VF#f1ClPrFIef>=k zGm4!GB}#VFbwbuHbxgBuTqCa=cm9#ZBb-#ok-3PUCOb5asyO@*ChGGvQSbCD-G7fQImdL0WV(FqM#il)axAeo`DRd5j;_lx&AQf!_0->9)tU$r-1!xy{S8SV{} ze|5Q>GBKwt;-vCR0!7167f1&@IksDoN~9+S#P$#-q^a;8ghn8w8!B0%n9-?Ek0ZT_ z8GB?RqcbfH@)kAJYsL!9to{(|?7`b&@r8i-fFi?ZOiL@Nldi*flqj_9ooUrm5c+Ay zo=~MpZwLiB@pq&mpW}YK1O!mZ{w6&T_j+(4+)lGG$R_*obkPraPfTjn`%E0cM~e`_BSM6=1CIs<(Pw>x)4-j)O^m*&y8uL(IHC^Wc#FE)Kb%Dm8VG+ zVIC_)#NCvCSoAg?yBX1j(O%wM3bK1`neR@q2e1#aF{8M!{1o${XcriC8!6|@M#=6# zFHPe)gEvcJ1Or;>_xp&YwfUi#EAi$n3<;Mv@>`2o=)Gh;#t^b&?VD}ZTc)ODpZBu3 zc%V*uxaKii#+4E2I%)wJlLesi{bv+%|6J0$CB2n#TJ0uD(k*KMlFxWhPqPXShThJ0 zRIsY~7y51z@@bRWHVvVXbvhmlj&t$Ggn3tMJ!p$AP^_JXPN!AZ!x_URQ+Vi)&@Q9* zg>YV&oYIU7Jbi0M50`}YUY8TJUv9^+9`=IvV=?W-<5b1aa!l`SE<1LrQ?*9U2I7<*N}wzyaod30ap_??3kR_#rX zoCC6#NI(5sEZ#YD0IX@fkBc#zO?gmb9S4#V6Nc_qmIs{ze*8vfTEXUC7(hNuBqGf9 zlO+74^BLVIM8hAE^`#prgO)bb6u1r0!VIu^8=N>R8Tw2et0;r(Sav znaAG+0kklGN>L6hLN$yRDDJkY#@vf6)=ymQBz8 z)@!o2*|I}1n_Vco@{vK8+F50K&NmzC9cM@KoE=C!9P}e2V4pH5(#h=XkO$YzNg>E4 zbRqku8wg)Ue~#&>i80yNsH^Rss#%1zQ;6`!NW5>lU3ll`@d1LLv4Mk1hK{|eZs_z6 zIrx;6WAzBDq=-CGg1UJZK?sa=5-NsQj^y??dClxUJ-TWNlA6X?`z*X>_wARMOt>ky zRa2Bj*t!}%wb7?}RDO5U_h_Whfgcqpi>;VPMq+Z;j^J12Z>oes3+V6jy(M(XbNJ4p z-JT$$pDe{a;p&ix&tsNK{@IT^0{!Wl=4`BbXNam(yrBZhY{YE3PS=jcng!j$CE|z7 zc)@h^l_3VlOh9qN5N_CtmaRoTqiTr^skl!#>awD*r=n&UKP@5#9bs&C2JpHkp{lmq66O}Sc@pWrFoDFuL^W&_M?b_tk3*Op3bthXxdc9vwWqE~KN?m!z1|v8?`9iS&?niuZ<(h~1m6Skoj39$AW2Z$E=;B2u412`e%@nhNi*-_< zWHGRQ>t}Y|Wjf4-fY(%C591Um>I~&epyDAecOhX5lc@7#Y7AL;PZ!@ZK;pJS2 z!s0HoOrZqhDOu&Va<&?zAbO+6mFfqi=t7Q^914AERw;2(e&ce9JZ*Cbjdx42Y5_L| zaT|-j^TR@3@tgee*Sp~=uHoktrcHZ^{jk@Du>6SeDc4t@UG^!%ab5Qm+?ANEy;cW;c&mv8DyDKMuZu(j?Xxo!JVC7uB< zF|3vVQEFBL-T<)bQ%?9odDrAXqLW%>TsBOfS>9E7(dnXqMVjKbFL>P{#e&$Q1i+L8dZV3oRWd#;q!c&z*^ql{?Q$XH_ z)W6tP^(^ZVQO7;2QR47HNun2!TC~k$aP{L2WQ!P1(t3;r%2fa$*t2#*_8i47aCKZR zK*uB$nz06j-cbgDX3UURrTCr)S%aB`!P0mS z_f%iGl~Zyz>5)*UP|Jz%2Pn6k=yH71|5G`V|D6^*+3H11%^)x5(MN1;PVS(6H#$WfQ zfh`S+$UCJ-46vP`bM{mtmea#!V%Bp1UYHh%6ZP?L%VkSb%XT zdmxc`wljQOqDR~8=Zf=n;{CA`Ys(KCthP5(+r}fEufJvs2ci=bB9?l&y?Gk6!3Ybz zWUBN)Af0=iJk&Za)RGo!b~Sc9aF12biu) zKm_cBA0Oz5P^%nNgBj`RSnZy_ZqB(FHcB7$R^cx^bnwOR< z*p_usja-ZAjLnc>U`BeAkdYt;|A=U37Y;Iir8el}z6cr*u|6AOAYE!vkVg=+3=N@> zoeI3my69nwh9twbD z2P2kesUa$H^N(3Oz_>hJ;^44UO~gF;CWC?Ygh15p2qS{t6Q}0Oa>LFT>;oc8q{2O( zfrC^z_jkjU%#rJv45tBFyxzgJ&k!_r0b{mhqmBjz(A(Rp9VV3-bcOMO@AVH(QX7m!06!3;eNb7$)l``hg1X6$`-7&Is8GA$ zhy)jKWPQluBr?z0&D#l=Xs;Bogq9{Iw;6oD(aKSqE0>e&8h^yURIBB0FavOGC%)1f=Py{)`5>rHuvy)8V|lC>`lq;naPoC$*n9UgyMH@ zB<5XtyhcGn!_cSZdf3M~Z?OrnCYqwim(CdqXl?>oc0=inON z_*QK8L9VC9hv`ELga>FAPF(ef@5?Pfm5tc;Sz5XilvrQn|2)QTM>|hqWKP|ygNe^C zo+BEq_V=KHkCL5~LTXXq`tm%^+i`rcA*u0p)1a5td{TIVp(s`k3JO|qoMKlzs*pa; zK4>IYEF~Kb_vy3ItzE##ejKS}*l~i^;zaB5=or7ymL40C83v=;G*>FLw=VdD{IhqQ ziFu7odU}I>_*pTWcYQnqao*e=O z4EkMxjJbnnyEJXbHdHLUa!Q^Vs*@?}Rj3_#IxUd21e7;WMU%)T@cBt{%QrwnoC8*^ z*S;dNHkdNS8XE!Ud8y8m?=;pHE~=W^%}&QAnS}hXl;D{(Z@-7c?cEMrp$*&I`{!T<#>cEOn%7i7 z!YUimwEA4seEr>f{P&f?)}6@@?i|js0jR>9dVP{=AEb4rlF1-UREKk;Njn9Ow2 zLz^HTsg_GaLg3l-im?YedOD@jV+KH{0CFr-KJM)+5C?O^H)9<~W|DzC1S3wXVX{t%s<>eUVp|n)EX>Y+>VMu;x%;qZ!mGIa^Bb|A*2mjuh!3H- z*(2FK`tUL9r41?-6jlJ~MVfXiL)0wCos}aMF8gr>=}lP~E0}8DqOnonPc>sWqrGi99ku{pYjfruqc| ze+S|HywY^jyA#3Ooyr639mTB686)#-)?&RU#a4+0yw!`i`sz^;LzMt+#FR?GvAWE4 zu59?vbc+x0k@XDpIQ{;+rn45jhCH6`yxu&%G`Wy@GVMlOSqjk|K`h=2q!7@Nv=D?m z7;B&g99v6<({_#6)cBgF9Bps z)wC36yJgAV>9&>Zqxw68#(}ERyo5q)BV;(vIsP!qTg}Ij(9MfNVHAyRn{pyr={M#L z3=Yu#Y62;VNM{RhwMiZ0RM`99u~{yhBBE7DsL(p)h&JmWV*;|pXnW5SpU3Yoxsz~1 z;JIVVrk;Hg@3U_vavE)npHWmzY!x(R=j~X{H1w|CLi6l;#H73z3vo8?#n9@rk(EZ> zT2`V>n_AYfp_0<#MK*#A!24mLo%=Av5ImXOH%4}tId<1S700@GrjkP4fk%`Y^&HVp z5`IP-X5xE9*t$84t19_w(X^f63C*u#vMMor{|34m_O>C+h^;uqa1K{x)kZzH1G1^S zM>vCUUzw0%VhionzFs5WX-R=~Qb&I7h&%pCHZ!W%N*H%uZ<>gx%KdB0QCPXI*a^+q zfg7$b2Upm`SDS*{;^fY*30`}}OP`5=)YQ*CNugufh@X9X^Ne=E!IHm=ZSiLM7doVQC;V+xf| z)GP7M&aQ}n6@r0P6vq9BuFl>U_WlEM>xJ-Dzep{j6i!y&jnyN@C(n^}%a+NkFWsyW zGETV}n(rt>M%pxsI&xFfBHoik%5Y=0wy5uLPNyM#_{Q|Ju-T&qO;wC5iOo(&fDh)% zjG=Yk22xn@L)mQ}(N){(so%?4^3W1&xc{X}0uoxb1ldxziuLR|Nm(DvJ)bl&qX7vT zIkObjT7y)rsPkRHgw(Lzrx81Yx4 zdIJxXq!=0^JRx7`-Hn;|@Ra0x21Ga;@W>mEl=&ZxJy%idT*_TJiA#|(TP4CJE3U(k zy2Ou*wR_S&p{+snm_aYlh-{93>?}AZX?_ZX2^Gg**~#m`YHr_Sw5Z7zh}U2V^p1G? zM$P;4)M?Xde6s#M8;n4oPFSArm;Wa@BF5eNdfK2pT8aN;hlVPA(=1wuz}J`pA-=qB&CGHM) z^q@O-7x}p-%xFqct|0ycEPUN@d((_hGlRR&t)eS*DlCm%`=-R!&|XLiP9~#>Lya;y z!TbZb0%BGWZWFEe=^d{E+mtW_X4B>TEH1?Y)Y5G4C$*qP@DBu|d~?BU1Xy~h)@x%j z?Rn?VzHtWWY(jopd#rh3ndJCwUbWLZRfC^&R3vqttd;8gXlQD4P~V#%gFUhc}XB}MyVp<&Pe{cJ{YTd zTJw0k>G0gvP4CAyhBW(^0gy#uGT;Mhf9;Qw`_GKsC|~voW!?0!naL1vnJqXf{tlY* zAJ>wvGIE%I<&gkKN2|GOXL@r?Uo1SHraEn^AXZN4Jt$z9xi79Cy&_EC*>apLcATg| z3MSE$A}!ezJ$Vf+2NYpD73GJDKUh-x=Itg!L-cGcQ;Lz+nX%{AYN0Q}*>nl2DfC9O zy({5(y*(VN3{d(+vUL=MOHnwXwuG*V*Q@E2%Iv13p5GKjU=2Gp(6Tqo44_I882S1S z59pHK&848TJBV|ZHCNiMlV0P@_|=$E?0x9(Ay>4M_l|pFQ5TEqJTZEQw4H|&-@slu zRi>NcG63FPcsVccZi#Ar;ic|XqkB+SlxqHCF0)Anu##e397dmgpJT4z$V+5QrurV` z#2A-OOiMv1=3xak?8QJ( zm-l>-b3GEcQ&E2@i=@Am*XmisazE+lix}lLAJd0<%UulO&aW*#qy&!Pb~ym$1toJs zK`|-{2v(dx(-eMnSAfN~Q&rPGu(6e$W`Ud-QMoDbG#Qgf zjO8gzOTHpvr_ZYJJ*ABu(0S%Z12~?_q(P-W4I@5!C@+ZgVqNi_s5^dLM#PPC!6?|v% z5~&c!a*bZDpumK;^j8nH0FyUl7sq?s3^6W1|ETEbt*6{5Mn2HRrx#~U4A$(jm*BC z0pD$0ydF_v^ne=;Yx{oe*+QyK_0W$F6Tb```Tt~~B2DpJQqemnyPmhn&`f^dxm3&x@*^JcVJ^|L#NzOb(? z-Wf7^+HlOR>OAKx7Qa1w5atkYta3jyvX9AjoL62*X`S_<_dEeDjPGP-*~&D0P6y6p z56m%|D`Zwq(6*v(ZmqD|b%9ks@VH|yo(#iaA(feq?FymarbCt%ZI|ws-srDE zNe4FZDe!RZVU@*jaO^YT=NYouzK>7KC4N;J0KAL_*}ZYOC%tLufc{*}c6WBKair|T z?WD4#d1h0VQwoA-oFLR|F;MTLGm}xe6a-*3kNTI7#?;mX!nWr0l>Ta;l6b4|#da?pxXVq=O|2l-erznqIN$|Dh5$7~Y4;VyBtMP>jPPD#(TDMqmVpuO<>`z#^KDznUN!d8$k^9S?g`tM{>^d2D@ z)$8?x$uM-L4Og9UjKDWbA$oH5He6Du5+0hb1Pv*!_yZp-~) ztM=dxX5{IB2=6-tjSW`77{(c)ecY=Qc;h4{#cCd9m}eGW0z;z!0K%bYoW|acSlp-_ z(x6zFJr}TjPUXF5zaJUwR({NTnTJ;pdmk^tZ(2}p&Umx1{cMZO?ffB-3@Bl*lRy~G z4Q|$GBx40XXK8Gy{`MD77F;LUi1)(a#vpknFAw5@1|Gfq2P>=eJIzC2S59)9Xsmv%AHkQ(;1!1^b zVV=AsMNwk0Px6aZ<4w{iSn85jQ9-5jjE&ks*e?JW2>rd)8e%0hA#XZ0@Py7(Id#VV zUWxL3;%U3RjvG0aP4iaV#D66};}3KXT_SO7kT&dluG%aBEN$Qe!bQq?kv=L%$_>?A z6fou~{i9@yFNTr$UCeFvP5owg>VujreyW9Ga@-89BWYI9BhvIQ{5@1@bH4}4tjP4) zfI1^jxr)B9h6Omfg=CZ;wKNAfd`0cw<3VhY1_iaO(f6l?^CiAEg>+=@{m)}>W{izK zcHhkKOgnoq9ex^bN-*(*rfbcXEeBescY4Z4sH2RWa}D%t!u!MX8yWTFv&=sWHt`Sx z0l7xkyYIJGI*(`=ZFqs;^EZ{O^JAkj;te-SMCHl9+#mn@)x4X18hl(fbRloXBmagl zdo{8;CuYX^KVHyu717yLcLuq7l_I_4$Z%AVGN|Tp6EiJL6ZTYE25rEiZGk?(KKPJo zB8^9`@8KaE6=p(Xvj)~h`irK~14F($s3HR+1TNDr)WqOTNHv-mFhL%SMmMa>VTEU~`R7@s=ba0;h{niVU>bSWBA&+K z>LCv9ACM=O6z~8Ypt6L3V-MGzlrLu8c@vAyCPC_Czs*n->3yx}WuI6Xg-u&WPh&uQ z;21_Zt1I8FyJ0xTUy}a1`2F+)a(SYgwj(Zi1stIi)Fam_l>P>QPTSBF+=o%oesXX2 z*50DWSMZE~(Q}vVAX6()NHgDtu2xmEUe^#L0SFNejoDPwT${KF^{kLPT(hrGW?rXY z_Ws3I%(^J)X*eqqKynnLbFBPQEb_&1>0(=VmbOj7GPOq>V&A483m5yi4(lskH(pO@AOk1GE9dV!U`x_ObHdLo<&qHP%?>+`L1~V2&;KeVGqFB% z=U2W6?pWMczn1E18E!q71xPuQ4`Jj2Ul=CX2=N*cQAKQ+EVPH{t3@ccvIDVo?+cjg zcUu*+uZ+_FOPHm@h|*%{zSqrjK%{q=2UgsC30|W8b#FCKyE!>SP)}XlbNN{!F0P~Q zEvcHFl~e(}!FWIXipA@Ac3=w)cR1lteM&L;88Zznr45pYHR3Td?Xmv*Mq`43xM=d7 z&7t$Nt@uB|=+WMPofNfV_JMMB{&gU_pY!3``;;_}kX;5Dfs!--CEIIbDrGfj+FwpC3 z$I%Mzo~|p=T~avLRuf7NAaig34_4CQSJ;MU5!k)O?&gQT0TE*+mqW+duhGPI8GS?O z4Melb+XSVnx^y78$|%hn`mh{3?BDcqRC!d1@8JY08op{Pp44qI?uS#=K}|>)P2Rq3 zY?0QH1WcBjVTGZ^mXw)MrmmL>34M^i<5mbtNq>JQHPJu|9 zJ#=h;&PYz3jWA-5xU%2^fsUgwaD16y(cv(csQB}j#T1(|2W@)40I`Hx!EBw^E?EDDnq{!|5M`eeJTdvWGN=&40~mF?xP z(w0-B0SJ4ZM_n7c;^(m#W+D2lXGuDqHlPN2i9P@QWZU<$L$A-{VPfL2*`7h~gr(|r zWM@84G_IduewIGrc&>EL)7gL9mgcaiRrt0xm z{vjc#03+oBu|R;&1bLev@E`KXtg$X%wq|6|jR@FXmk`$U1O@C zI*0G^qatK13X7eag=+R507Tf~<+TE;Aueu0xqFB6d<2BhWkG}olW;XtsyGd)hVKW3 z%EmD^4goz+s+s07n!W){JW^J@&zBR9yx=H9t<Wcj}Y4{UnPgq8Wzi65aKg=w%QO^gJq}p6b3J?Dj5;@ z-deytT7zfI7Z}393>Gbi^%SRX#}U~LuV=+ z)p7H?Mk{}dVXyPKXW&0C;h7Z1b!a5X%>9*%6lycZ{25XrC)|KN=^P%|6%?|3 zut$PGmN0Gd!sKgKwVcepHL)w#qXA5ggiEL#V^}j<@1`C-$JwJ)j zNQdeR$}_l^?yFI{CHH;$L<+I|_$1#v)j&(f5e1SMRr#*?I%P>EM&-Ev0Z?cO`tcr; z*OStWG+k7sCF~yg5rEOMZMH``X3^ek!!pTfgHuuJVQHqYW_Iq$&58 zP$X)!N3v?_m8watD^}!tP%{mT*vM0n~k zvO#@-R|&o;NzHx9Vr{=g@%E{7|ulux9x!=BYM!Cx6=*;$_rFTf$r!A&3$Hl{*N zDv3jO;npXZ4}IMx!(JSSSm#}HiXoBY3(`&93o*_(YBB5Xs`mHr7IPzV=J!gt%8cU_ z?td6KBJJ|%*10#5$GiW`@&E_WZV9IxzAkidggxf&Q0O;K8+9VAg9|6Cf7oW0GvHf^ ztABi_p)d5gNr{ME}X_cJqn2r0shokOfB zK(}U(ZQokpVi0*>+|_i#Ok+B9SmCXB-~Ztsq1icfveMjmK6Z{ zg2lbSi@&!XO{Vl_n*?Sl=w#M06b;U+)cj|B)h=a{7wU;@-4Er%Qr-0;t(~ZJEBjU~ znzWtIYt#|XoRU&)3YYvaqg+?b`{=TYO>D>VO1gj84iTiTJYr0ET`$>bF5x-OR6O-3 zV7=6oL_DB_^v!3@jy>+$8Fz9SRTK3fq6rP=%0O3PCUQgk6FSL{BzO0D%ua(5-a3kW zf-;H?kKTJ!bE7{oG+}=>A6;PCNfC{essty1;Qn5dk@h%erc08sc{6@-2oEem{V3)t zlLo&^L}H-&K~WH@G(HSMnkg9VutfyFG#I_{<&4uC{7#h>X4nG?8-YAkp0oJtYgFMD zf&?&}<0K)OfNj4L#jfHdvyesuY`=6SYtHtL?#FOmDp=pHNoxxM%*MpDKy zo;da{Go}k}$;{85(uGQ0s%zo?ce-(7fxgX67yJ*0g<+(dJ&pzEY>~(3b1mC@3lE_W zq6nRnTNFduIT+GDnAUg;ox6OvcxqblF3fsNXx5xy*@zwv6PvK$dfoCB^?|g==ee$w ztO^4$C21Z@Qw|x{i2_u>1?B2{ z;5fXQ-Q!~2MH`7k2)?tDI+2>l$fa0H8%pKG6$QUtxMFZNrpi`W ziYDhN?Ft&^ZN)C#Uys$}@GYH-7xumeelk2p(3`?HyGF|vfQd#Jlhu`1XGNMp672*n zQHS#C-QKD5r_q)E1o2yI{`V(O+n>U6jAr<=21SlRbQdFME*n4;57}`G!jc!ioK=P{ z;7Ka$Frs&Sm{G7QB`>!_DXDscA^r0v?R`ewAAB(CGVN>}=e(^}<-piN0!7lc&OOrBd>dmJU2{Lz5!B7ra_py~fs}Sww z%!{Y zPoE5XN#L-xJ{d5M+5rxWDxRh2SCGF}>K)*-4nWnvEX*+D4Z!Pf3I%_(L*`EFLU|{* zbhY9>-S~Jff+hL51GJp@z5*p0Z^efFlK_-u&(Eop(N^<>37)Ww4Fo6GIoR zxV%)Mpar)cf(}}@UohKP3~?!*eK`)jZ>Zcem9uMztSr--hN7J*GcvrHpEzf6VdO}Z zyY2Ay9M&9VILeibGBoXcm=r}RCpxoi*sDMkiVgD@_#$t-X~4o$xkIx0l!?YcHDvM3 zUe#H^<6fOJefp0_JYKWV&#R-2QR>d82@*^R9$j5(I5Z32o))-^$WiJfg$H2MR5qH?` z8&f|p=SejOE1n{G7m2))NHmqPs%+s1vRP!OPYP*W%iKQnfg=ennO4YOBmwq$KA8hC zD~^M%buNCr=iN}z4wI||%$h49j%$v>rK3&A#(f$-r{YzCGS-S^XB$60rrEla+udBp zqsMg5S5{`60G|k3uloL3Q)u+xTpaI9g=#O_Y-paJpx&&J-s(P5t%BaCnA{;9a1-Nj z91SjAVMus0m!QcvEReEIrd?T?@C8M5#73u1o%$Ty{k96PnYDE7|2FiM@tCAnF64u2I z1{iw-0dv%*%ldYT^IaaRfw)-R`E@!RMX))9f|je8<|~?*rJ6Ql(~msgc=(8)@V|$Q zmWBlB@3>r(@x*1u`Uum%JQ)YdPC%tDj>gp@jWF(k=$!?hxOpEr&GUeA$T0UbL$mbS zzahQA)lVREYZ)CF0ioe;*&!^K>AoO7I6UqmC|~N>#xmWkzUJGCcyF-%YQc(TB=PZu z&Y}d$5SV~uy<0jR-8z6xC}qQ@-@_Wb(`Y-0BFlczF2ZqcLATytCRn(Xg8gzB*h3GN~x36d^jPTa(%`x#YUP~x-p zLsUh5#g$#+!xtb9o`lWvvw#hcalwv?msWl&=GBg^GT(g^2*rT6!?{?M>Jq!MnZ(mh+frdMh3cC<(^l^j%qbPcH+V#u96 zKfmA`fshj4N{>&5dps8bJ+d?f=K&R{8_eMjJ)L+Z+&KyTor)CRh=nD=PS>^N zy3*#r-M}@h453WYM^QXcnJ@qW8o$s`^Myzy%eJKhLblRJx(TrSMJlIA-NDN&d`=9v zt!u^FZ3I8Nm52eHssnUgZt+Iq*bc{to<`H*SH4I;$;!4 zi2cG-E2$vR?HUhhq6DI`Tvmzx;SPJCu2PJEojU;xR%z*%5|{0o@%w|AXOT%me&0Yv z@i<13HC*%F zxdf-C$m%s^8H?Kt`qQ~VrlQPb zhVG254q)V26r7t zN#Ui96wDmkMm6?13Puj)s~Y9^4FY$vQR8@;q)JDM4ajEsYSu>l6V?lwSiRn6j$YLU{R%Gcg197-D| ztH6|AaFRS!E3Rz#z#apVmI@x81jh4gEQ|}!rYe(^MpWg3JH6CR%p48)%(7uLco~n> zfA54jpU!e-CVNOmY+EARr_e)E+HlAlpU)N#adpI;f-Bb=&Eg{b&_MK`QzDcoAQ&`; z9rxFa1T;KiUEt7%N+zatiz|o0F(P^70i)xRA*@_nV{*0bYhxgw)d8+VMiQ?{ZAdw=GjKm7>Wmk|AN=!5(UM--3OudRJSaSt?UnQ`_%0_Wo}0!p>AL{iBK+ZX7XQJFdaSgi0XBI@axdX%uHWb59`QK`J=UkFV_&i236390IQ;j78~mA{F&W#>&ScJ)E} zl0WZLlNsf9{E&Er$X1sQgr9w2q--XQeppcC0^W}ncIK0AX{eKr&~G90YoI2%re;xZ zqKHxSj-gQ^U$n1aB&@0B>F{qmsQ|9yX4TyIEb^%6M5+11Q`==lhSxYwK0Rs2zMA`5 zS%>*+Yp837hehh)LS!(c#UP;G4f1MpZ!Qq%VjZlut!)_Ek*&nGhBi-PtofsB!Pl~-JZ}p3;m>tRj zl@fCzRw%nk#q*sHsBQFSS3pKGbwvP_1X$-&(fU0@Kk34%L#&OY<(syL^S zNhkbAM+wV+aFj5xu+#q^M+rM4!~d@SyP|}Hk(uLv8cOj0--?o$CQxOR3p7?~qHP^u z@zuHQ7-y+*0ALsxU^pSSFlNGSdhU9j@PYUz01#)Di$WM zTeH*8tLcGqt3D#TQ%hh~hY$kyH;(`$01+A=UqAo^@-b)-DE-Dd3_%3>J3UKlG$Z;g zoCBz&H#&bpY#2fAvt<5o@a$A7nEZV}&^u_LHxc4D5fXoX|9@M5@bam&f$~8fg4Y0> z+yOCb=xhjtPor zAfV{&n?w8&d4Hk$X^+GC+a&JpJv=<_1GTq2boSvGv9|!|AO;Zg;a$N8dHP-b^?!Y|)@#W*Ef%n{w@%m?_VljXHwOr8A>4G`AfD8syn6?@r8WMTmYrQ3 z0EH54)%z`%fdmBE;Emi2zMf8U4r+Jn`}#q?Af)Gf*OFdwZ@oq9$DiWryOi|e!&6@Q zIm79L@MA!LL`Fgb_RRw7+i8jQ=*f0^kA~`1-e{WAH0uKtQ~? zq39qS)l&NZw*4Kv(g8g1L;IvJ`9-;UU;S+SZN|d(_ZwYs^}(mX==*^mrSTu&-wdPs z`86y3b$$OO`X7c8w%A`g0ZLr?GdreFyU*WI7{>s9pC2G@`xW5(K0lh(FdF}Fx+RdW z(;3TvYkXYVUn>Hc*P03cyO-gN=+!bk{cU~l() zRfRZfpKM`(-d*%+LqX7c1>FGt-Bj40t5K0qfN#vc6~0o2@QM4oiEZTm@K3G8Px@Z! z=4pP+U+~^Xz`r!SN2i}ooWB6L-q^oVD8P3DzliSv0K98__rrkR@M;geQ}8o)|IXhZ zQMcyT#J7Cr5Km#R04>iikjMA|bnrL$*Gj(y*ZysA{7vRO%;HDv$0x5(->#14WuU6E z+PF>0$Nf~LnmY!4cBSo!c`{W33_NZZsB7{N438Io5Vj&(f+#KU)r8SQd z0ftjG-3}-`nP1@@mX@1`M7)l{o6eGIKhRyCdP9?pc>S`%BOwwMKg8CJn$!cuk@P@< zWUnU;qh+mc;il=494#_X$68=i8-$fn#NCVTal5l`bUO~1?GdFab(nQpKXp#H_8ns zw;*ImPiNDtYtFT9o)gyhlPh`N)=y%uI7Zhmz@xtPCpYU#l0Fi^D_DyO<7Q(g}}$e==`(~##Vw?8*4J-Y+A zSQmS?gYvh-(`6x0Z^DUF;?~1&I0{j1iXcL?PkL;B8aLHEe-MBVHIMv<2qIQ_s8I8j zxblsDv-RZTlc7h*0BeKhztq?gj1l1mf&$75YD3`@>S_ngErwKtaDonj$lzqn*o#46 zNh$6LuR5p{m_Oo8DVWdmoO;-AO$#E{;vWnT>FnV-nio_bsBL2>iKg~duI-rpT|BdJ zeCZ?zUUO!C`m?O=2vshl1Be_YEQ?8QI#1=cEk^ZCDSTZ_bIi1ECP{F<2PxCwaGQOw zz>iq1WTmtrqQ@#fmy!pH@Z8^NJ5sQBtl6+4s(=W6S8QJzV?h{D(vVw&)9(?Q^590D zHB*q$a5mCa%HBqwTpC6+j+Ib$l-5i4Zd;gb<5%%=_g+kqu1cePed#LG`XzH|f*0&o z_y!Yv)doax4hvUjMG0vecx!1R6+nxBLDBI1%%?j}HnQrpT9ns(L^wmp zxRMX#!5%Dlll^q~ESlF94Pp}9X=QUsraGY|4xysF$^ve5f~e-Ty1qRQ?kxO&Rw2U* zXzu$m<2u82%I9G-=!`;0v{1BP!l=u51}{?l7RsU|UI>qwmUsGXIiBFO3Dcci^Kaqa z^ch_9)lUUW?M#G-=xPLb^N8%Yix?-m@Sux|BAKIR$V=ru$U0^XxJ&LhGBziRRKLB8 zCRdP=RtWUXyf`Ej$v3HTo3GfO4T&w1AfCNE>}KWWwRSaS`-jtU@#j8f^Vr(HmZT>jO z&Uro27HXJ4gV*XjB{`+o5$vM0nY~PG2K~KC&fxtpFG}>XD{5zIx zlnT+ok=i$4xj6bo>p_`<~&^VOp$TM3n>7-^yB+cAaYOm9pizwfVzMzlCwlt!5~Cl7#PL`vQXj2>Mw3& zJE?Ae%XB0hVt;g#F!mC>rex0LQIgOLJc3d6Sc<*A^|zF@t!t5cR2rD@(nK#BsbU5S ziDF)&I82j;j1^V(l+2-_1rn!oda&1hbhidNNZ}kBsTv!yA?G+2HaCXUnt@!fx{6*D z7%j^qH)^t3t|stSt?uZ8^G4SQt?6yl(_(l)$wp#W&1HOz?Xfs}n3LX$c#%>#Z0Sug zN-KEb8GV_YD|oj%2W}*No6(Xm>rl1e8Sn558x1{HQV|u}aLqBQzYJ!PweQ<}X6yqk zhd9F3YR@75w@eBh4du^Z4dm&@vskBnT=+(rqh{S2TATy26`F=65D!BK6P=0xc*h>s zxGZ+3V)V-F9DI$s(bB)R=%5s{A~(z9DcoaBKGUOLfa`AQK2z$4#wL8t9Fly?IVo4B z0th|VC3PgoDVZ|YZgqgw+>;Fb$(h5KQzsHC%u2YFIj3F`5QA6a|7qy_=5VYuSEk9r zNd10<502m7u_N_YsRC6Z`Ux-hM-iMbo#`)hmSgzaX=#E3<0Vmq?FEXRhUNOX%q;gJ zuXPmI9a|)k5Y@3&F10E+5mR_F5|8Ke1Y>hrJk_OXHC(3mi*)c+@-^ymYg}Mnbq)ut zL)LobuKLL{VmQR*>|^?C16A*K+NwT^a~eOm(**jp4=wJn2wP_*hN`RGQf{=9Mbo#s z!_;J_GffcIGq2|dv6yHrS7dX{$#T5g^GfSHtDZWTubXpmqoGIjw-a)1NK>8x;jEE1 z0|(Pqn>!tLcD^a7y{8z6%t2dKelS0U;l6u+Sc)h~(!A8g0mmT0kAO`WRP73L58iQ> z%Q&?M{?!O+iRMaU-ciL1dz$FSo+#|NKZI5P;rA7ugd#idkk^zgNE&i;IsHW)Q<O?=u{j(b5tW^dNzjn_}>r400PxzrtKTNgx}ysMQEx=4-6vPYmCk(hj=|xa1k>W2V8Xh zU}w9?e^ELZ%JAgt3GB143T12DHQfxnxRF(Lf?Y^Z_9$RvwdEFKgP+Sgf72Wj!U%nq6MV(KEUQ#MSYfVIFb+{Cg6wYo)hjZcguhWY8JDpfqc$ zy3hHfW*gna{yNEoQG3G&vj`+(P?2aCimU}N=q?G!fGfXVCmw%Q;+fD=}asgt^d zzT;2X*?ptNvjfWXz-QA7YwT^FM^4@0W7#@|J42D+c8qCfhNGiQTZ`M=WmMtbA^+_YuJ4h3Qp?)yby$z$mNS1sGk2izCkb&?P%bj+u;!BXZN0AxEF$r$TiOlqm9G5lZL#|owPg-?z(bQj$W=xCXsS!~nq>2GrFF-hFLmS9 z31>c8O15=r@GTl|j$_*ny!Mr zC~8Uo8S03N`Y)I-VB5s~OqLteyAWpwLwTuCm)B&g+&2!<#$~@LJEFQu=ce+e4DU$_ zLTEx~NldX2Bcl&@T5EWG#b+A!T*7&}ceBaGK#oJLBj zqNA`e*3EyW<5}H=14`Nwc$3J;l}B}W8g9`_kILir$ab+-v723l{)-(vwpcA1!-=)q zKA6U=a7MXj!VMVsfcmga8sg&4nKnl4RGz3czjI3eUV`Q=g@6zw9Wk!pRVjZ#yyNPW z;vJiiZI_poulk(C{oHlxeU=;LJSD$LO>@d2y|CBHhPJdAK*`Qef1pykg%9f$dmtvj5uHyP%Uj{jj@SYYoL;_I(jQkuw*2>)cCxR~%Nl|Gx z6IBW!HY0JQV~7bTPx>Si0LMlsi&uWRhrkAch`zcgUSX)qXRkK=aBTJ`8~=ozAE}8s zI8U)E0k}%Yj68;EYDJcjg+{L~sITUq2GX7*4Vc51 zn9PR8kcO6?r1&{)L0PI40821a4Q-vw>);iA-0020KD8xUp8#1gIwwWk3iky}cpwbJ zTv?~{6Rou=fIih_R558OS*NUaQ-s$KygaXmln%ojTqsR7e%=9O9?~+fvG%NxFFY)Gh zi}16`Qax|;FK*1^^M;0X{(eW_?bU=`dJ#(vlIltf1mDm1jK0%?Kc{)8#l%&+U<&rG zB>gUb3!Ny=N-k<^4m$ijU%I`o$I;d6`7p{=;Ts?OqQUgOK#>$xcqK<>N&CkFK}lv* zauN$^Ie>B&8${8Y){gX&Y0f9f7g}m9H9)u2MK>%c-J2S`Okm*afOsn`?UAr&x|qVj zKay_9J>ffC(*&Ci1M|i#CQXKXh^E_`YR`AId*G1OD`-66GeXcKWedd`=Fk${M`dFn zQzCoV5k8BK@wwY*E!)J`IPQ{$bku4R)3B6EiWeQKxi_Y@svN9wPlyo<& zQ20d*74sC#y0ZKUc08ge{nerZG;(a94?LA_<@~a+1fNFUSdVqKzC_hxiIXkX{6MAPPIMlKb zw+}_%ik}3Pr4?CVsn5+0)eJ7@n+$K7U3xNzsM?C_sGHxy-id(zbYow0s4zj8sxM!d z$TkRh7H2i-9X&Ax?o01QZ=}O~;>F;S>MWM@{H%u-#bAwGXkxLvWLFOF6W)%~i`n$5 z(rHSRoSs3)c|5qQIN4etPLYY~<@FrEv(S3RKu08QQ$sDw*Ts?N|Ff5t{bGV5AGH2U zdm%pxAH)sN=0BuISc{-}i8W(2u%#=sidMdfPo4FTAZu37WYm_{>a&C44Eh<$0$$c74?2c&7ET!!<#h*(uyM&UovE zUIyGg-_>HG@g9OHUqs)0Z0_U4=2lklQcT}8f1Lsa{3!5kQOFFxn&3Vau>Ydd-ZjFfxSam8my zkZ|*ftC3V%Vo3hZP9li{I3iN=T1&G4Wbagy?cbe+LckUmQC+kdjcC|igElxu>KxMSjwURl-hEmY=3DMza@};$5WEK1 zK4i3Anx<$eC)B$e!dw;^heps|-`dG~_m6sN_!$nFCR$^peb(1DfUuRZxLC59c5g;y zg3uF`csz88Z|{2iMhGn9YNmhlbD|Mi;BI>pA8q?IOqY(@@B0tj-HPAj)E^n>I2Y_` zP1qYOi3FQ!tlxky-mt!;y~#3wIH*U?GssS>(*d3l>2P2dQsoT&U8?4iW;fPsDt6kj z>nYp%eiX^fa^s7Be$C{v$VE{*qWlmb->6p9LCD;!PR)=rx(v^#=JDHNszI3WMe3(< zCYNWq5PBGVrDB8SX27L?O6?j;$TpjBqNYz@qhS2<4rCZAR5CPUaB$yL&l z!rTG#__T__((K0C#@mlWya2O+0EdS4&=h>GW*l@|*VZ z(Jl~c5%Nw5sg|d&a(?W49Q{;|$QQFsa1yfNBmIiBCUMV(3bk<7Ik^di{I`oOfn*k8 zGLl8cr(!m&IXirP0$Q@aLYvuE<`1zWnxk}aIUX1cw9UU@CS?NKszYdLlPI|sp>F!p zA}{k!WfCqw&xm-si!GFb#d{FVn;hQHwWTYv`kAYXqpA&1NA#8qnUrSGD>4t>RnQ;l zmb;94xk=8pSgP={{$dNb${n0LF@+D7U#VD^)49_I;6zf=-oUmD*Dd9}JgQU)#aO02 z&s(siA8(&%G8wn@G@E9E2kXOflAW?ckC{zc*Dr)>EYsb}pMT0qZXyp~^>0+9&GC znmoofD9kk{{aq(-&XnBCH6=cydirWQW{fN9PuCu$P|+DRlaFKk!WGf9Qs(YUp7EB@ zv;P*=^_SwBy1`mRmm@|+q&|K`c@)wO9Jse&vbmNg!R&~6)%$}@F@6yF{Uc{vy)LJtXnu#%5s(kP?NtDxIL|n4=RhJVtdqYU=ZAN^jrM^Amb!3>S z`#{C=HZN)!Dmqyj0TLHICNFym)MtX13hEG+VQgRzvozj_ZX{Z9?+CEygyTE7CsVa6^f+usXwsN09maK&JQzXMwJ$ zom7Uo{K(MvX`D7v^pPf!#xtBNGe-OILcMVr%8;BB;tbTI#a(9?vX1TuBVE?9f?GCFA`H(in(v0c862XFx zEI&&2W1Z7J{u-%caz=0mDO#y#7gcyx?T;Ptb4NrZ_TenD}UY!!x_b#Q@r!Drk@hQR#w-fDyL!QuXu zqxUhg@P4kh*2a_0|fsv$_BR~$={ z574WoGF)hGq)vJ)v*ty6O&TRQwm3pYVdpSv=VIon%S7Z}Wro7mqu(?N6Rnp*9MkUS)t zZR%!uUh!)%Xy}x<#HX?WWc&6SiB`z!_I^YSi664Z^n`RDf&52uUHSY7;nh zpyO3EtQgOHvq)2p^{jTtOHyCuk(N}auWVmsUcc<+-FKXJJQN7`TAysu#BJ9~#n0Ge zE?lZq$%;`%?=giGDCN}6V72F^O8(N&Ugk7K>u&N{fLX{}RHbk>*f;7C=nw{MW27;x zirX8|Uqn+5<(pImO%*73GzRK95bDwA@F&fWBR0wIajQ@A1(NO`fm4i?sxyA&C_auk z)NUdoYu~6U;Gg+~2^UGu4;lIyW+wCDCLwnyOqLDonF7&3-RnCZB6qt;$Sr<%CBj!; zb)Lo|4eBrMm5Y_ug0CF$YyTvyy-%Exbvp6>F@`UJGNzc3SqEUf z0N2lW6rl~GRyXxfdCb1dVyf{|%s7c)oSS!0erOE!-FNKn?Z}v^wKH-V{B$i}C8IsB zUT5{4#!~s}G0+5Rbtu^QCr8`O9ha9YcR0?Ww_MB4IJh2MhPP>G3nJ4&UG2m#sCvIm znUSj6_0ea%i6AyJDF-P8+t(RQr4^ifoVL=R-MpB$oSA;h$H@mLTW7*?LjfYI8(Yzz z-F9Y5JX+lkY|05y#}bJ{4Ce>}OyukBmyDYpVRkR!7fJ?IG7*-P{NU&2Pdn0&hgi&~ za0DFDjb>wTG6=`)PjR%W*6z+tO4Bq{c>_ygl#HAqJv+l?&IOzo3t-7Owa0^y>6kP_ zYlBf&Ykw3YZW%{|oEakFzCrL6UU%V*c|6~tC;jXnw5*A$I@ZNtB}s0|ZyM8KBD-bX ziOf}XJKbi*N@V_x6}9-P3;i0kjMu|DCF^-Q-&x?c|7>zfa;kBF5l$SI_gQbTNz&3Z z(?QmWACfAT3kC3cCXaVB#6{hAK!u874Lx!dDg>m_OEp0POqA z+}EGl+8C_)h30}l$J3r-|M}Hm!{;-N@0V)&g0|lXUB)2!+6xQ9$5XUMrPgq}Z;UPT zXTl0PFp45M0bv-w-@XK9#rw5COLfS`)SPrV3lrPB^_gaxxk9=P={gu=#6Ks#yxEx5lSfuQD$;8GEYUWyagqT zWkcs4k(?kefbW>)b!Jex+-kFpkQ}K6MvgecS@j+V9e0`%c^g&^Z^qE;3c8^?0n=zk zdjJBP0bh9$m_03P=2}auYye@Sv}qZ&1dK>no5Jdijs1BhV_7MO$M&2~&SA?9KVjAt z_4TFZEhTa3JL-bR2&;poU;2Dp6*sl^6`74_i#QOGK^a?mv;pamrHU%94a;C zsnwdPmjUfBKlYG}CNQ*H8QXI#D5h5d&vYa2Qa!A+oEt1Bsa^XscsGZvUPbM79k6raksi-I+> zjtgbdRo2eaIP|1;La4OGWT4D6hpNRvU-A%V@57GEqd|(+zo|A)vz@=OK-nJ@+@h!$ zyl|tZ{8P#7gcR5F0s=wzwL*!Nc8TxDWpciI2@eq-FCObLqH$X;2*tQ zjQ4P9*BX~h8qP!t-Axs`k_CFrE$c!u4qGQRzx(sAMN6|{fhl5HCFBAQ@3w)#Kf}`& z)#ySN>-jA}hqGm_cgoao%SKrT{EmTtlb4+-&1N##M=%Zr*CUQ`O3~BmH4qYe*EZlGaj)1o~4+j>*nmHcu4PC*{2|>z$IMj~3+4Jck zj=~7S3!J!J1wjor)=rBcvU0p);-q{8A^UBXU<9thxAvI4n3$}0W!N+Fu zyy%PgU_}5+p4q4_tr8BR?L=>vxefD)0hl8}-brQE*&R=*rr5KZmzf4Xv?OcBH4@&` zTsL*i;4;)F0W*cRH>{~$#ci#SPU-RS`j5#5KUzI!Tpf2f`oSW0;IbQy9t{_Ue#p#H z=&-glsu*%@E2*Uxmvp$4CCL&OigOy~zS3t9(Tg~N4>Tq7B5P_7=`TwI(xmImfvA=R zv5#fBIfR`yiEy^N}cKO)l+fs6|bz`JBc^XSaJKtKD6>zAz8eaEj z-!f%nRy-OO6#Lmq4|4k;ffGQ_jp|eIiw+1i8FKp)sxw*m755eFpQFdtdxs}f9)-`pu?1`mDsKu(&QE}^rmRU(p41AxHnMU}G400-_>>9*00#)j zd$M~204Wv^y|#c2B+u&B2+F~0(!}frU@l10kI#1d3nf5jeR*<1JT`K2em-t_b2b6x zQjch&59S`YZ4HQtuNEH#J_dDHY2Y8(PIOi~qpn~9sM(^w+Iy5KZ^b6(gpRN$u?Nrs zBA}hey+xpkkKU)`=wI4}#J>y)@;<44P6uq-x7!G4U+4IRd}DX37tj~KJ9CnnDlbOn z6wZcW2wVro+lGmaRdhEgCYRB3yr-}#U0`mSH zOFf7{b)`46&e6?qG1Nb2Ti{{AFN-@u{x@aae+z*7>gviHh#MfD3E;@YV)BKmE43B* ztTpj4?X3cs509)Ix$mO_G9GUY^XWbqR2tWGEwCLCQ^^5qWmi&t~`rC@1-x)M$$MS9W z{VQg31L1o2v$+@1cw;N~r54I-19;>o<09a9UBx&Cb#?RBtLee^SjH3YzsCN>Bw9y> za0S|+2;8Z$@gtJjd$iG;It2&=SRtU(-)oBs01eLd`FobjI=S$3eq!%qcw~oqX5sL| zRRS}FWch40$nN0|ctT5ivQvH~Cwy?U5BO%!U0sMecKMG^vaUiX-%NtutKi}DXITP$ zUX6ID2VV2<74Aj+MOOSocK}>t{uKc724H>kO91ene!v^LAChLB!@C<_Jb@nr)(8Ft z%p+X?1$+mzhWizaEyKk3>nj_Z}HdhOW(NW*ZC5rXV!4W zpQjfO6`Uv}`5AugUsod=!>zg2hy$|8ZRFxB)dbv$IrXnn8`OV4t-pKMd8T9OiZp*c zUZk#VHi`+9G_`o7X*dlpN7z;$i~r*w*Ij2yS8HnTM21I!f|M@*4X5XX`iWs}-}BD! zYT2w9wb-1N9=hfq4s(O#W*s>r=13qB@Qdr>@h6vtkbTDJzK z#?!;*bR!0(MDhnjKZ-w^;pL{e<&14sNAX_a9MlEIapLeheY=|(J?f)F&IZaDtVnz3 zkxk;_@XY9@wsJbWJ4J_fY*6&ADs^Txra5!{l|*HUdIaU&%M6_1#)?3CRDVBf%_Bec zVP(5m)}f*S`-=2=W+1sWz*?>0ScAGmwR*?&qB$?7yOF;In|7Z7OkkiyZW%Z$Sneq1 zOr}kAZ65wB*|)=HyZu}0Ccm3Xw3cS`e8%M_oRraH7KJQ2L3khA;^$q-hZbjmCoURZ zX&L_EsOr_=bxy7_VdHsZqVIKj>hnrmM{* z3(6Rg$!YQn2QfcJqn9rVSrZFHXwzbWO@OHPSdA^aOlLY&4`9>darlJFBW;5KXUT=J zbeZqWt7)u~(I}F#ZJ8tN5u}KqDeRyaB+q<(|1#kWPn{4~inNqjD!Uuj^VoQUvkr4_y=ma$NxJT60>=#iwB1s`2qV$z4iCm)Xu(p-cYT zc3MoI|6ec7{U!EoO#L*6Ht*}BVf=A;-Rz2VNHw{MabpfbZ52_#;{*%JwGMB1iLSND zi+&jeu**c0@cO)EW$ol6$3f`3Sz2*gwFmCp>>PQ=sw}RGV9D~*-N&3d{{|q!q(U>C zHr}s_lcuDU(#YmgDQ%>&6Nr!nL5-13(pqprNReyk9dov~NNtp3A(=zos*YYy7r}_8 zHIeA{6ryyjIaF>}3_DTD(7|_E@oU|V5UNM%tyLLXnEheqb22s~?@wNv`)q7pD_Sxl zlXD~EDTzN&gJPfhRS%qKL6D=s6dZ64Ncn%sF*n**qz*e$4=rAj=Z}v`0b@M4pJ*0C zdeVbAG$Lv$jijrB2M*$J?4)?4oS&ONRzn3_faA8wdp~Dn*Wj247#QVvsG;=F*F7JV zLDU`R(GJ&4u@kE9*BL53r-hreYlX=F-T{|^XgED=pBA+ z^wtOGoVl6~CoD`7g+2Jjh~D88dl;GB%CQg)md~ZrBbA~sr#P!YkMdd;Nfop}x##NH1q$JMkrJ!!fP zX+s^p!X50-o9r~FC+oS&Rzkdg-%VkDiL-XX(e9mkXk+9hSlzsxXR&x@@~!-~5p&Wx z`Mtu&o2!}Kf4z+K;K`!|rOKD=YvYTuylu4vd$j5?S0weL5;1Ah){5n;6ty+J2_ zVdzTGln}^sk@k8wYc?$z-&13vcKMa=rC==@G)nsMcRkRK;&i`cTg}5z_=Ftu zj@CKu)7G-HH_OGtG`cZdK)dztT}h{{nNrD+DN=q`GMwKdafwfn2K15#;zr(zmR-Jh3-(rd78jDUOR&u<(!s)gvQd5t`ftqICek>PMF^a zAnFKm4g+BB%0bgv|0}e2ddBNyWhZrqbRPa&&+-n48mKMX6zIaTgHzu9josvpD;fPG*#|~WLhJj| z4Ak_nPlsaz@0D0%rsp6lE5@<)JE;I8{7HTgP~0TD?h9@vU>l-e#GGLLT#XI}K(Xfs z$^BH(z^5!GW8$#cEhG!U?rt8+@FG6nVyC9tw_&Y$h290~RF9y|&LO2>2ow~ZX5KF8 z^n#2-^x&g`yHIOpKEhm~7tsVqCD!=23_y!c)(Z0GR(Vp5ym7Z;4Sw~HD4dH$|H3QU zpB)NZ-3v9k{&DgbgLOT&%0zHf`Q`+ILD1Hcs7Tg}f_}G(1lE!%ymX|ZbJz)bQ5tt) zjuLyNe7Z4F*_;zgIQ_*cj@#C}uX(RTLryYWLV{gD`bZvS2ipmXv)UN5@Qw=qEk0sjF|a^rUAHgde)O2-QeOGhiMN|}7tKQaXRRa^*x`ASb7Uv8!hp{ zc`t`1`j?G)>9vPs=^`ZBL+a|R#CijS(kxMM)1^gLJoFHgclc;$QPAlNR|+?^*8N{p z2wgFq;Q<8%;rUVgJfvSjYO2|rvsG2igHgZ5Ea!EJ8)O~zr9sxx463!9t{SBI^v_sn zi)BSV4N}E<<+FpF$D-V$1EyD!6>D2pLsw)q@Gf4-K9}T82AfgFAh=UTT5II5-&QbE z$@CdFgs8-3^KMMgVjlUocUbeYG`krw0LpXH)tIg|ha3BS@IULtffR311|fQ)A%0(( z=4tRUG~?5u@7&++gf~`uQvP}0?NawFeZKr1H*HEiqAT=a-3Je+H@q-OCMx>~o5g$^ zHhjtCA7Q4rpVvC}QO?y_GnxhKeU8OH2qHrE$C~35Wpf%9Fka))e zKkJ;#&!ajmNn>D}-ANEC-5@K=WyyaxJz2_MGadCVwe?W5>T!7+$*$t0+RuS9P8)2q zvkE4Gi*{&Z$H3SPI7o3$V6RS?TxuLY5g?EKQo2S91mC<}y>l3z002vu;$QVic8=O2 z;`Jy!beMo|O1-hmEM-o6Hg+ufjIcKf?{Q@Qb*kgV*7rxA6F@V&I4CFNUG$rNW>KA3 z8~Mh|wHih2=d`u`HSNTr2cL4&He_iWUyV&fyD=e&vLmN*7xf~E_y@j1d@=#g3H1$J zk?2QRX|OaHe3GfNaD%3sc>hz5dvZ=qDF;U^!3z2liMWNygRMc6*o^hL{laXF-3(8) z9C-}8g@vk1s&3HYWoioJ-BMpL7nUI8vvgbb<*b4$#%xOxYh-jKF8f8lZ5hBYUj&|? zC^{6Hu6hTfU)V9p@aeo@=ciW&kCOgCs{c*4?K?woqJ3B>9C_xzIyJ<6DzqHoKEVNl zCVb3HPahF!eE!-_P#nkj%6LH=i;v%Jd#zN&U5%KeSGPe%pt)J}zG8*fV0PD=9Oh|? zEOE)m=IW7-Io)u<{OHUM9R)g! zcvS;GCIcEujYMw!lR=BQ=1!F91YVjCFIuaQaBBX>zgr>sONRr3_uFwvYP)h)b7QG{ zk+J|v^Skv?oRg)u-})xa(J%i^G@f*nV)kkdBObcF5-(U~qcHA{r+BL2rWpH-FeqPO z&pFB*_h(#nrlCxykXcbsDU%gBW2c+Z2t_z+DMOi-A~5SCs4?_sFPMn4TQc|GRPz4x zylW4Q6M%>!^Ud`V^m<6+gIPQ2>nZfHj&HC|Qa>GXLCmaeH;uzC%_|}?ox9*($Colu zz#4EFq9QRoL-ROdoX0*SQ8Im$jokSGj ziq0S2mKFnvk46L{j$ram*dDtuJE;vG@j4aiaol_n4u!UcjJZsvmB}o7c6(jZ?+;Xa zzNnMt(tE_ARs@DIjM8GlMIxQD+N?7p5_@VQAMZm7{W8^0oO0Ic-pO;x;y1@7qP@DTkm}K1X-5g(O)i>x%A@^nce)ypfyhKmAOSaRQ2}$J8Q%c!1-g}g~59Lo_Fob z_dQ0$C1qle229!QPKPf<|67x_za2|x_w5=JEp`zOD9iRU!P^k&nek1^JB^;0u>@dK z(9?}}$U~AYuWZI}LbJ<_8`G9T910RYrE`7KdWc)^O)KjxoJBM`*$C0lij|n6O0gTa zN)H;EMifg~l#A=#WCGmV+WOIk`ue9u4|$k;qJ!Ae8D~|-phNQ@NJuiLBq+<3=m}xn zr@xorPg2v7CcMuNrT06KZ56sdkf0k@=i<9>5!3QKa84Oe9`n5WxXJcL3ytGNwDB0a+^v$W-H|FlzhK!TLHOQn zf2uv@zBMFGP@hI%LllgnsZJk|t>CCPaBHfQ%csEks6|UGN;4N~6fMR|hj`@<%UUXR zumj3`J6RM3IyP_?XViJekOV==)bV9Ple;z*w8{4ra8VcIMI7E*E-71X z-RzZF-5G@~ZAjLgx;w*QK$3;TjHUMpIGqx~JR z-eDRo3{pZVofPnXx*|CqX3h$<-ZGGr*(FE=7*2e2Qkp4|6*sy>ok=kxSqmoMKzd;z zcwi9^EU*3A)6BXi-;i2*2&2g^W+#6)><`NQ@z^Hc-qFdhdza4W!+J9Ty6m*ZO(1*L zL~?EVa5WK`tCh~-EUTbE()=-p4r*dH{)I4XWo)$Nm`r-A@*|(5F%mb$ zlzn4{IAo-2vbk4fg`tXgV*Qz9Q>$a)+^4Wfak)$&n-BMkEN$YfQ7yyBSSmWfl~RTC zzYH74Td^i4vfu~a(>|T!jvXWChrEteoq6j&WZy(@sr72)3EJvRMUr)K)mz`+p|kId z+d}=IXuu<%g8sYa-D}Pg;l?8qIW8*{PbP#I(%sTpB`nvkS>&QI_wSZYg3=|2fjR5* z+AV?w}PcR;QZ^*cDPEx~fCx41@zGPWNziD_A5 zWxZ0pRq=sbqz0Wt;vK&w@eFaL=qaGsl_^RyH
    z@Xna0=I_tTqbuEGk@nHG$%@Y zS!P!?Bu*cRFV*Eu)ppWQu^+-xPd2E?%oaZfCjmp z8y8S+rAJIUV7`d0Bcqhhu(qoDHb%$Y{JK}?6AV>NM=q*gD|b&_93`riUL0p~V1e4i zfy`mmCwQ8H@VBdDX#551BU8KB2v33dwiM73unUu6=g{48el3V zRM+iskwUt)Qo9Tlo-dKklr^h~Mavqt&8yO%#fFSu@3Lupbe~{1$9X8U7*1!$yih*A zg4~2BGE~_9OpmK)R{eu(n?y$xuNpB zO6C9q#W9>$tM-!GpZZv^+aQYtBBtz$>@>!dHH~)l?Qd?hshLQ&c&5I9S)&0Q_^3(6 z+VzIfgo_P2A|!x6*-K{{3^Q-J60T{vv^PP1WZWSqHk=Zn_FY;~ZiE{t>4p7RpUha5 zB8QJ_1m^-i?ichN7&M$TTYNV;5Ceh<9#IHG%_Y%KYh>W-XGlm^Z^QasR@tpYeIE3& zHdU(ijKrWiKQQw*LlbT(Bb{G%DKAi8vcXi#cARhUeYTlZu?bij*WfC*o`{Hf3`Q%R zOMI86Ul?8V@kQ1G*E_<(nOS6%W@g&nYELvAp@| zJ+w(CxIhw#WF?yUKb1VtlEo476jzUh=cXsc(Z&}KRFt%qIxYj(7I|J3;&>3VgIHWe z3VlYC6A^btj;STzFHr)z&WMZ8*=B?44__1Ep0_a_8t(twR-SwNHw9AmHLn^B;T1Kf~>lt!1?XCUe1kL%=o%>Q{FeW`;D}6*KA5L;hKMt^q&+Ib_ z#U_o)RuJlyl#76&EP?fqMOso`cy;m6UFohhO3H8&^Rl~nHbF0^Rlo+t5%xv=~-hwTIm=oC@nK$zAUbNYu z#Ed+H!a3<_lM=;)8hOGFJ`X6wp$5VZ;?2FR zmT6sF!d(h+@6XwSTneWxbMmHZ&sWMmADL`UOj~@WQq-5|8SSA{0(dF0RsXi~2AQiL z2Vb?+u{YX|PAm?l35dS?a^+iz`q!7-p{Bug{RvZiUv8mRoMtAW6_N0%H*ncUW&pRL;Oq??FI zXCavcAhzjU5;_rOOd_eiW&w5zl7NhtlwYI;qYW!I33{01t!44;L&fA_-{FYdpr=J? zkl)nz{uf7TeQ@a9w6Va_y(-OYYkFuQ0XCD2SqmUdRhz%AYs?WEad1(aXLo6rp8XLG zvn#T)ULKZ8{hU5ZOKYQ~!(*LS^?bM1iACN&!0~03&^=syS7^^ci5O=^lmBvz4wQd_2XgHNg}&|0_hn4GF(fC9gpd5pk1(DU#|{w(aL( z5MIwLvYxd7S+s|ZI9ZCjEYh{r)MIhH|Mghe2zfUV$7 z-$aYn&;1tJua(PQT9I3zaX6vi7E$gFYA*?4JmK;Qd~!@ZH1r`(KT33iq*^5#vjY~B zavQ72WQ`+77yywhi4zhGmtxm%Eq8V6vz}x_QgNo&;U-mfM4W1_Bq{8hm5Uuv7BZpQC5hr-Lj=KYeV%*qb;7 zML8W-{raciIY1b;>WYw~ZlM^|>hCQ?@7#*`J9PTa^uNVH==Sj77oQ!CG1DZA=R6ZI zLTlpOU9U2k?ci{@F!*3Ll5MFIG=Td)U9e2<3G8xd&BZ(N!j7?QSPAfSm!+V>~-{P~?2fM#oT zjKdXDVRXnMPKXe`Kus-0$vnRn3kdsnV&e)Y9&&6PItr42c{-k@T_{}67F^IUstihHJ%mPky>$)sh6TMOa z^Eti@;K6An>qq=T-cYYexkwSl8`XqI3UR@n~b3royX`W#nzJvvo~8oTXM^jX?H4~g74T;hzn z%L=hdl1<1N#R9Aqbw;EC#nlBVZsIHV%^w$k-50;{jpo8C@QTJ5qLnyLBr&aXuJ79R zC73qRBd1=(s>%qu(`@l3Bam)Db2& zwsZD->9Mv*RH97x4@j5xMwYwZ&T6pNXOFoL!aTfY37QCOy~Y$Rww{!fW;MyaL?FY& z($>uLdE#U=J#5^k6PHe@!oCA0b{$9+#)~Gq{tI45XRu#F)}8lSQ_(RCt@>xhUC~4S zFoACiX@ppNDcukD&)o15wXJiPvXoWD8>uz@515oE)Ox)EGNcp*_x=)OEy}d5j0{-M ziibOzII=v^eO&Q1VU|+9g=MQkQ)N-MHZ@uPad&}%hcrSaYULw2Y2|Qz_bDo(g;}3D zl12opKF*h=_;wXpoJ3qrBfnPht3Wq)(nk1GDNt{1XJFLC7y4qWuuDSdIX#lD;PaLY zuQX;HVp$(KPTD1!1aIThg(M#%5F;~qh-I;6K4`ZcjUMFw;)htyr@sNcnDU-Kv1WiB z2_`&;rV95dr;p$ab={Wr5JW{!h$XDI#;;Y3T^BD|=zy*i9>0whzCp_12P9|aSj>uniK*vukuSr2%u#n}avbXQm=p*coOIJSJy69r!r315_r7st*YZ`@;y}654-F)E-o3ojI z+YU(vezG+3HOzweZS$Do<%uYTXy=nHsK-pbxv8joo4#Sta+I1*zaOMuq8Y(3ma@wQ zL^8BCt91a$^rqt$oYMVb?SYc6sQwT;=qu=TSQEKYmDfbQNsAx6%s2&#U+b&U+dI@# z;5mbqq^1thIQEOl4VGW{txs^V|3uw5{|j|vW@r9ixQ&T`jgf)ze^386>c-B%!v6n^ zy1D%e;ksI(Bg9oo3K9-p0$7N3ksw|GhM5Ln2A=*)P#NM993c_R^6wgIfsj;+S{LZ| z>^0Z<=XR@mrPq2T%hUb#`{vYhwSoB(>yC1b&}M)Nf+I>k0iOcWqo$S~2mmPbJy3v9 z$jwcdVhZysJuP7y<0>qKXfNsa&(9hxj8LJg6amVHEH)sxMF%%9NGM=XQBsgmk^q4K z1VqYPI`NP!(!Ut4fDOQwcR(zNf6wy7561q%HJEEa!C%!MR}hDFCtwg#k`a&J5MUGo z1NI792)Mssg#-o|T}8ALm<9n2p+Sl}zY>F_u!4m;B%mNXyu9y%3?%$RGlFT^=zEZ& zf&d=|Bx^IkHsEi(bbF8xU_Zf@~Jy{IS6RR8U?32wr{t<-!|Xg1QP4ek4op zuOUGFiv{$Wn0BuifWd+L6eRn%KPd%v2HH=x-q2r~)yO#ekgwmDHt?aF>%Vw|v)iHr z5OA)p;MLUM*MVw?KjNnVVt^t60tFcz|9~_o0Pl4n5I=JECpW-fMyMaP;?LJtSHTW| zt9jyp@4^>@C-_2oq$5DEf~~E=pT6JCJNZZj1q1`|R#8Bk0XPMYegCH7WrNRtlc$sI z0zCj`0xXXpfW6zfet9$tn{~py*_~g<-)0>^UshsPT-Q8);NQ)XiikU)w+BcdKp!C@ z0T#8ucmSib;9vgcv!DWhcfc?C8m=uoz=XGI%_rLLYQy;c_PJ+v#ty*W>1U8YF&d14 zXZ(O{V9|iKGy1__`;1@6_x{39_q1Q|f!}U?RCn`Jezm&Yliy*eAi><;-?rlWi#Q=; zee6IpfUkbt{Gi{WYPL1F3%F1FYA&ddlK`Nt!S~&C2+=Bm-T}8Rg%sK&`iieo_J6(+ za|)cAXaOOAehPr6pnzXf;pV9o$ZrdRd5p=_krjJjWc&B60HdlsZQzv64$ z@ioQL69dxLDRav2iTm}1InGhYcEoz!VBYlwom^G6u;sRpG7gnW5JN*i#wZrnT4i8vuLo{SUZJ(qx(v=BG>PrHqy?LC?C_0Y~d=Z z!ngX}N4zTDu(NHDeseNlVGc}hiav66)MaJOmWIoXDvNe+k%%fJcOWMF<`wE`<;-(= z<~y=n(}VjCe2bz{GxFH^>xd}i$lGs3Fl3KUc5wqhEG1%|R>AfQHGRmjcklfq1Jr8% zj{r7&p1=H7?*+r>D9-%=Ttnoe=XP-$i&(ml;PFvU_IFc60mtp^#%XbJwIY1Ja8IM+ z2x%&VD~>+&`A0lKWI{BN*XK)=W-t%1jcZvwnfXzIIG2NUYHmUft0F&FZs{AQn4+TL zhnjuAv=+`t(aboukUwZ11F)#Bh2r$GS|HZdrrqG+vxkpmwecFtVpONv)Gri zW-8@~Ii+gq_l~4Y1J7>e%VT&x$=h|emb$V#$K0PDdzHV%{Jef>>?I~h-wwwdCUDEjI9gNf(%c|3C5x-_)-9;=hN&5Lo?tjSPXVeQSz7=N%2KCd7D z(y-ZA7I*hnO=Ra^EM7r`r#-_DxF{i$AKueomgZu^Ku;D@j&lnu0SQ5-DSJRujjMHK z2Cm92GmTH}`k!ocq|;U4ukyX@0qOKfn_tz{rg9Fi5na#|dX)Hk{MBM2#r@<`g4#c4 zQG1gW#p@`V;a$Q}wzZ_4-jT-5F){uQF$kSyXz3N6PE=w&^O2I@ys45i0dewu$hdW; zFQnWJU@^Xm6f1N5l93hqO>BfLIy0DevR^1Xs(aNAhq_YfX`C2`X*{uJB^)|TbZ-@t z^H94p^WHeM3ud+6KhaN?D zU5_%oAD%Hyo@FO#PW!QWMnl@2d4D0y9d^areRu_br4SDtO ztgDS9MVcQFsEZWiEqVuJ#cX+-hTCKk4VM67yCPywyPd;iVm6@V_;3e93hw6g31%>^ zbPSp%MY!dXWGm}I>u`H=hk(JD9{LeSwz$S?%hcTiFHe^X)v4b)S>LXXzlNH1mca$|8T;bVsc$B-58cF+%pO^9r9nLd%#me%{{-8?xz72wY z*e+v*a7yG6Ein*Nv~~pGUJka$n@DssQ=i+p{8^`^<}b5nMSqTk|hLCub&|#t!fChu8PQ zR#7Aqp4)Q@kNbD4$$Ie(ne&GqoYqQL=xeDe*wufnxWO z2BZ6yJ~|dle{;*>f(HIHs8$hN#MoG8gV-IeRW80rHGhJ47yi)RvP+JqQq}v~_46W5 zAwW*LTUD%`HL>8mZQ}qjwUM!FdObW&I(Z1Fp1CZArOM?~X8_Rd9=xi=v1P@pLxjo{ z6;y96`{|Ni6-eTRsDQ4Ma(&V}lGAqUS@atFc_hk^u%_wcB^85Rfpio%1TJnVsR_Ss z4)(U^GnO(IQ&(l#p!nx;Zx%W^OVK;d_^2k|S|JmmqPWpy4=f%^C>_F_M3#u#LDdLfg}#yo8-JA={kQXfkHyQ{kF+2Z{%^4weW!s!vj zLQ}pbG{!TdJho`jL=@0;Ms&uOLIboB>`B&LV#RxMg=Hgq7mc=MF0x&5{5R7SmgJ-j zb1X$3Z|3-+zZ;xkeYXNuxj>wOQtQ8c35y!;xT;sbw`_H3SHRD`A$nP?zFJ@oVD0)I zk9Nknq)?WJt|{@$QH#Y9SI8*301qMV+~Z0Znd9j^>uX+jUK#cNBXl)j+MzS;i-uDj zeX9f1zkvGHs)%9zmj$A51DQi5Yq8w2xr!XuT)DWZhxA>&t&W;(Ke+5J_1B~&njxgc z9t1Z7*FZ=!4OcAr?Sc}50r4JbU0owR*+7uc(bE>4dBzl&BwFbH6Vg!)bgF12!fhh@W^O)3Q00|C2-@=<4Dt;&yU(ZD4~l6{nBm5 zK&%q#&WEU|Ywa9-d6SP?X3KX4AY90}CO)(2JWsYOwVx}=MAD4y!cv^*bhPz8kSJE2 zVN|aE5=S9EJ-nTeM+h)w3!bg(lNGKkSyL){3yH)gveObc^qW3*R#)-wK9e)z{z5mO zIu#0}ADgw&=o!gkMdY$2{ORjKqnAX>oEVuH#b8XQEC`v6{GU9Y=H>LI=60?T?<+-* z=vGe8CA$@ToQ&LH0$+XJJHa;K_uSB)-l5mD0rEr3pdPehzjE-BuUTh_l9UIHW8N+l z;--ifPt~rGKD@@VR@fN&-V&(zxQ?Z=P7L;o>RdljQe*^9nvSh*LCD2O1oWN$tl$;{ zjjHFTtUluUc1e2EEaE<%Rl}iaCwHg2jAsSNUq|C*f;_6E!(1vhqB0CmS7@xpNtE&!FjoFuCdMRH9Oltl;=E8u2Aqvjd&L!(A{JPep7zQY!bWp!fa%ynX zHYVD4`2;_3W98)7b%bZ6FWB4JZ2}IP1`At z7Yr#rXgC;+lpGYf)&8953SIJC8d<>9baE*@ELv=GMK;nawqz_U$Ls5j2nxCVqb(MH z4{WaQ#}*s@Jl!`tr%6&=thWEi^*E-ao<1(z4Wa`@oYC(UcfIAT&QnUM)9?_i&fC-k z*v_+@Bd*%QN2}$7hqjTYr&LiWIF1H9@S7<+LXX;s0WMqWCv4C zZpmLW-tyH_q4;U2ki>HDe{(XUXm|P4o6Dcx*Nag1DzR$(6kWK%N)ZRHsTf>L``@6{ z_vjo}@}oxS`rCAB)u8&Q%BwOg@OjWQ8n6==MMTAPeiWwS5uL6toK=RjCakYVZc@J- zUx^#-D3^Ac%p@VlyQ>xln!Nt@%ra-S9}=Xnw41W-29|s$SRR}}7uvpN;WgV%pZP%3 zp{ojdZC|Z!{*0x4cr!VjZ(Z_HiahSTdfzCsYH^TRWE8xm-M3+0CK8EHM=qBOnK1v{ z`q)TfWub!{&*imVXN6C|J2I|p4vRzuDlNi$E#gC@BzCVV<(Sq-!GON?lJ$`WVS}W&-F6y}T z{ROe20hf;Yc*a&&T&FAWC9B^B^RZ@46f<4!g~JJbTvN|*Esf6dnhA{i);8$*vEcxB~+-gk;Iy0el^ zA}8Kvzr_i2u|`RZg83s#73;fEl_^_Qg1bN3P+fgkFX@zRGN%+vy(Wes?&dDl7gDoR zZnai(uH=p~IoDPvAO*tjZPoQ+CK_k|mrt1fX9dZDK*%3&)n&wO)j14dd`F?sp;A;j z$SC~Aj1S-6%&3q-Bwdv~(tH%Ef&X@T!1N@Pu|%k(T_k}=lf0u!Y4MA9!{%d&OLnO}{)n!! zw{v-(Vz=G|CPd5N@fi(+2d^67gQ=G@j{83E%=9jd=;0%DPRo7pl(4K5%*7-2+{hbO zPL?673CBoQ`%}*l;2gJ&>+x(3G8lU54&p0BmV*)kW=gJol3f4Hy>1&iqQnz@0+B#EvY>3C=nQY#A ziJjT_O(=#+<(OIgkEdI6AIog!|2%oYv3o&*;w%%gZY&%HIFk}caD&Vq>~7dd$Nfh5Z|qM0z)&dLLDgcyOGV^tR$o# zlp|9W%MT0&ZSY2=IqVuH#dA96>qQ|eso5|1sfCc3A8H3(@(sxaF3#WOyCAoG0X3Eg zO~ofTWDP}|lYx_BFL+65udkN%%+$|%bOyI@wQXL}?s4=t-++8bp%67ilA0R@i7e5<{8 zRgP1H#;OZAa?!?%lrCsh4rjBc{h>{rb`Hs`3nHl@bG`2d=Guf@>mp)Bc7x247Xt-YsUOQy zC-^l>-o0lX?!UJGCHUhu>ZgNcwR@bURH8cvxh;yotvw=Roq(8xF{W};HK+`}jbk$E zM`581d0k#$W}{99n$h61x2HV&f$EmO9_Q1Vqh?J0vrqO_XYq2{acVhZZXg(?4|=Lz zyg9uxxdz%A!4~t+#xXLFMhm=ejx$rm;${Yn^rhp~OAh0p>{OeZtSR#L==uXJ?Q$%_ zjuQv?wBGtt4zm6;{#;kkUDxX$R>#tlBHs!FdpN3ZyY4@83H&kj?+BXg*w=Oe!PvFd zJo72A{j_Ll{r7I#3Ch;$-1DGw`0Zb_-K09VnSzrakh!znpF3rh^tqVer}Xt~VM|@9 zq=$3zg<>m$&~IP6I3gck`lluHlkH`3>yAfOSSV*Mv2V>{U8e!y9IbeWd6v4Xw3cGF zoiFRO#Fi&HB5*LB^c<%$5^+)tDWpUB;7!T;Td~7;^SQJDzgCWI%>`AS@X@5Q9-_zo;)PxM#F6_AmGZn`Lfq} zI{Y;b9KN?w4%t7`9W{4MZlU}xPqndMEf>MS8#vZY!L#*W1WYEsRw-|#b%QZ`3)A-> ztA&vvfT}a@Xh7c?V&H|ly6DS#`8tP`HK#>2mL%``=@kCTDE=3IGHSg@FN1q}6szVH zKf7@A$#+F>(jYr_a+w9+Zhw2EY_N z4fXu?Q%OEsy54iNzNk(S0cF4_bDLQ{>KN*S<9A%%P+SHc?n(XQa!cz~law1S8{I*l zfliKM&L0^}X`E(wG^dE)LW?5Sd&dO?-?|TE($p>x4V^CK=Kkt7gzUs+^jerOPO3Nj-ln zHT}6tP;Cq-x@;Pc1vv6N3d>SpSC92>^S&a|Fl;E-HwR=-oO_#^7x^Q?M_ zyj@QQ!e5c`hihvRw@)L+kSl#OKn4ji*E2qwS#a^>jYbkf$)?0o7pZVf(NA)ciC@05 zZ&O#%%1dc)QleFTxX0Cs#b1*sV)43zEh%4RGe%*e373USEy#rbDhmnekd=XN(?l-2wH>NI8C@7* zuUli)3#7H}SqmM1UnFfGIE&DGc=|f4c>HnCu=uFG+~+#|GuLXpFZ0}NOBc&A7b24J zc1jl=>AhxYKBE&{G_{+sT?;Ey`d^iYhfGDWX?46A#b=NRz9 z3D>xJL~6Y+H28>MOJ6a%^pfwv?6Yd3v|JSaJy=b)vh=93UdI@& zs>)TTsxe;h4f&p9JRO|bZGr@*Us3I7hVfb!4(+DXN8co%GPIu3itUHwpAXi9@tK`k zsL`>nmMDhiuxK$#KijEqnI?5YUJlhM{5X5t6#qfKVJ9qV`0+oVS_AEyl1${5JST(G zp<9_|WR_}JS`w2cMG$)LSWR>`2Pr*%y=-cO*8l2X_nqldNnRX!ydJ-j=mRQ9JrA{m zUWuClr6pGs*`(6m_Em!Hx8Gq;jf{T4w|x5j|4aX4Vf-)skA?mJ)b9M#|Jd07TmNHY zWBvcp|B!7y*-06>QvQA9dSg*ay1Prq)(i&NjEcpIAs~Q=3W7>lh@x6pARMmvWq9Qvps;I|6>p}&MM+puLJPW!CGieZD z(on#INdbU>&?IWmzu=(|8iGDQ2pKKje@WF}LxmebWPqbcD=>}z3h?HjBM?D`OiT!y z91j{4fMC$P;)}-A^C$pc#JhlEMFBrESajeE2;d !0x2k0a^5&mmGkAOi^<9hr#w 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 literal 0 HcmV?d00001 diff --git a/noweb/code.tex b/noweb/code.tex new file mode 100644 index 00000000..692b4f19 --- /dev/null +++ b/noweb/code.tex @@ -0,0 +1,17262 @@ +\documentclass{article} +\usepackage{noweb} +\usepackage{amsmath} +\usepackage{fancyvrb} +\usepackage{graphicx} +\addtolength{\textwidth}{1in} +\addtolength{\oddsidemargin}{-.5in} +\setlength{\evensidemargin}{\oddsidemargin} + +\newcommand{\myfig}[1]{\includegraphics[width=\textwidth]{figures/#1.pdf}} +\newcommand{\code}[1]{\texttt{#1}} +\newcommand{\xbar}{\overline{x}} +\newcommand{\sign}{{\rm sign}} + +\noweboptions{breakcode} +\title{Survival Package Functions} +\author{Terry Therneau} + +\begin{document} +\maketitle +\tableofcontents + +\section{Introduction} + +\begin{quotation} +Let us change or traditional attitude to the construction of programs. +Instead of imagining that our main task is to instruct a \emph{computer} +what to do, let us concentrate rather on explaining to \emph{humans} +what we want the computer to do. (Donald E. Knuth, 1984). +\end{quotation} + +This is the definition of a coding style called +\emph{literate programming}. +I first made use of it in the \emph{coxme} library and have become a full +convert. For the survival library only selected objects are documented in +this way; as I make updates and changes I am slowly converting the source +code. +The first motivation for this is to make the code easier for me, both to +create and to maintain. As to maintinance, I have found that whenver I +need to update code I spend a lot of time in the ``what was I doing in these +x lines?'' stage. The code never has enough documentation, even for the +author. (The survival library is already better than the majority of packages +in R, whose comment level is abysmal. +In the pre-noweb source code about 1 line in 6 +has a comment, for the noweb document the documentation/code ratio is 2:1.) +I also find it helps in creating new code to have the real documentation of +intent --- formulas with integrals and such --- closely integrated. +The second motivation is to leave code that is well enough explained that +someone else can take it over. + +The source code is structured using \emph{noweb}, one of the simpler literate +programming environments. +The source code files look remakably like Sweave, and the .Rnw mode of +emacs works perfectly for them. This is not too surprising since Sweave +was also based on noweb. Sweave is not sufficient to process the files, +however, since it has a different intention: it is designed to +\emph{execute} the code and make the results into a report, while noweb +is designed to \emph{explain} the code. We do this using the \code{noweb} +library in R, which contains the \code{noweave} and \code{notangle} functions. +(It would in theory be fairly simple to extend \code{knitr} to do this task, +which is a topic for further exploration one day. A downside to noweb is +that like Sweave it depends on latex, which has an admittedly steep learning +curve, and markdown is thus attractive.) + + +\section{Cox Models} +\subsection{Coxph} +The \Verb!coxph! routine is the underlying basis for all the models. +The source was converted to noweb when adding time-transform terms. + +The call starts out with the basic building of a model frame +and proceeds from there. +The aeqSurv function is used to adjucate near ties in the time +variable, numerical precision issues that occur when users base +caculations on days/365.25 instead of days. + +A cluster term in the model is an exception. The variable mentioned is +never part of the formal model, and so it is not kept as part of the saved +terms structure. + +The analysis for multi-state data is a bit more complex. +\begin{itemize} + \item If the formula statement is a list, we preprocess this to find out + any potential extra variables, and create a new global formula which + will be used to create the data frame. + \item In the above case missing value processing needs + to be deferred, since some covariates may apply only to select + transitions. + \item After the data frame is constructed, the transitions matrix can be + used to check that all the state names actually exist, construct the + cmap matrix, and do missing value removal. +\end{itemize} + +\begin{nwchunk} +\nwhypn{coxph}= + #tt <- function(x) x + coxph <- function(formula, data, weights, subset, na.action, + init, control, ties= c("efron", "breslow", "exact"), + singular.ok =TRUE, robust, + model=FALSE, x=FALSE, y=TRUE, tt, method=ties, + id, cluster, istate, statedata, nocenter=c(-1, 0, 1), ...) \{ + + ties <- match.arg(ties) + Call <- match.call() + ## We want to pass any ... args to coxph.control, but not pass things + ## like "dats=mydata" where someone just made a typo. The use of ... + ## is simply to allow things like "eps=1e6" with easier typing + extraArgs <- list(...) + if (length(extraArgs)) \{ + controlargs <- names(formals(coxph.control)) #legal arg names + indx <- pmatch(names(extraArgs), controlargs, nomatch=0L) + if (any(indx==0L)) + stop(gettextf("Argument %s not matched", + names(extraArgs)[indx==0L]), domain = NA) + \} + if (missing(control)) control <- coxph.control(...) + + # Move any cluster() term out of the formula, and make it an argument + # instead. This makes everything easier. But, I can only do that with + # a local copy, doing otherwise messes up future use of update() on + # the model object for a user stuck in "+ cluster()" mode. + if (missing(formula)) stop("a formula argument is required") + + ss <- c("cluster", "offset") + if (is.list(formula)) + Terms <- if (missing(data)) terms(formula[[1]], specials=ss) else + terms(formula[[1]], specials=ss, data=data) + else Terms <- if (missing(data)) terms(formula, specials=ss) else + terms(formula, specials=ss, data=data) + attr(Terms,'term.labels') = gsub('{\textbackslash}n',' ', attr(Terms,'term.labels')) + colnames(attr(Terms,'factors')) = gsub('{\textbackslash}n',' ', colnames(attr(Terms,'factors'))) + rownames(attr(Terms,'factors')) = gsub('{\textbackslash}n',' ', rownames(attr(Terms,'factors'))) + + tcl <- attr(Terms, 'specials')$cluster + if (length(tcl) > 1) stop("a formula cannot have multiple cluster terms") + + if (length(tcl) > 0) \{ # there is one + # subscripting of formulas is broken at least through R 3.5, if the + # formula contains an offset. Adding offset to the "specials" above + # is just a sneaky way to find out if one is present, then call + # reformulate ourselves. tt is a correct index into the row labels + # of the factors attribute, tt+1 to the variables attribute (which is + # a list, so you have to skip the "list" call). The term.labels attr + # contains neither the response nor the offset, but does contain the + # interactions, which we need. + factors <- attr(Terms, 'factors') + if (any(factors[tcl,] >1)) stop("cluster() cannot be in an interaction") + if (attr(Terms, "response") ==0) + stop("formula must have a Surv response") + # reformulate with the response option puts ` ` around Surv, which messes + # up evaluation, hence the fancy dance to replace a piece rather + # than recreate + temp <- attr(Terms, "term.labels") + oo <- attr(Terms, 'specials')$offset + if (!is.null(oo)) \{ + # add the offset to the set of labels + ooterm <- rownames(factors)[oo] + if (oo < tcl) temp <- c(ooterm, temp) + else temp <- c(temp, ooterm) + \} + if (is.null(Call$cluster)) + Call$cluster <- attr(Terms, "variables")[[1+tcl]][[2]] + else warning("cluster appears both in a formula and as an argument, formula term ignored") + if (is.list(formula)) + formula[[1]][[3]] <- reformulate(temp[1-tcl])[[2]] + else formula[[3]] <- reformulate(temp[1-tcl])[[2]] + + Call$formula <- formula + + \} + + # create a call to model.frame() that contains the formula (required) + # and any other of the relevant optional arguments + # but don't evaluate it just yet + indx <- match(c("formula", "data", "weights", "subset", "na.action", + "cluster", "id", "istate"), + names(Call), nomatch=0) + if (indx[1] ==0) stop("A formula argument is required") + tform <- Call[c(1,indx)] # only keep the arguments we wanted + tform[[1L]] <- quote(stats::model.frame) # change the function called + + # if the formula is a list, do the first level of processing on it. + if (is.list(formula)) \{ + \nwhypf{coxph-multiform11}{coxph-multiform1}{coxph-multiform12} + \} + else \{ + multiform <- FALSE # formula is not a list of expressions + covlist <- NULL + dformula <- formula + \} + + # add specials to the formula + special <- c("strata", "tt", "frailty", "ridge", "pspline") + tform$formula <- if(missing(data)) terms(formula, special) else + terms(formula, special, data=data) + + # Make "tt" visible for coxph formulas, without making it visible elsewhere + if (!is.null(attr(tform$formula, "specials")$tt)) \{ + coxenv <- new.env(parent= environment(formula)) + assign("tt", function(x) x, envir=coxenv) + environment(tform$formula) <- coxenv + \} + + # okay, now evaluate the formula + mf <- eval(tform, parent.frame()) + Terms <- terms(mf) + attr(Terms,'term.labels') = gsub('{\textbackslash}n',' ', attr(Terms,'term.labels')) + colnames(attr(Terms,'factors')) = gsub('{\textbackslash}n',' ', colnames(attr(Terms,'factors'))) + rownames(attr(Terms,'factors')) = gsub('{\textbackslash}n',' ', rownames(attr(Terms,'factors'))) + + # Grab the response variable, and deal with Surv2 objects + n <- nrow(mf) + Y <- model.response(mf) + isSurv2 <- inherits(Y, "Surv2") + if (isSurv2) \{ + # this is Surv2 style data + # if there were any obs removed due to missing, remake the model frame + if (length(attr(mf, "na.action"))) \{ + tform$na.action <- na.pass + mf <- eval.parent(tform) + \} + if (!is.null(attr(Terms, "specials")$cluster)) + stop("cluster() cannot appear in the model statement") + new <- surv2data(mf) + mf <- new$mf + istate <- new$istate + id <- new$id + Y <- new$y + n <- nrow(mf) + \} + else \{ + if (!is.Surv(Y)) stop("Response must be a survival object") + id <- model.extract(mf, "id") + istate <- model.extract(mf, "istate") + \} + if (n==0) stop("No (non-missing) observations") + + type <- attr(Y, "type") + multi <- FALSE + if (type=="mright" || type == "mcounting") multi <- TRUE + else if (type!='right' && type!='counting') + stop(paste("Cox model doesn't support {\textbackslash}"", type, + "{\textbackslash}" survival data", sep='')) + data.n <- nrow(Y) #remember this before any time transforms + + if (!multi && multiform) + stop("formula is a list but the response is not multi-state") + if (multi && length(attr(Terms, "specials")$frailty) >0) + stop("multi-state models do not currently support frailty terms") + if (multi && length(attr(Terms, "specials")$pspline) >0) + stop("multi-state models do not currently support pspline terms") + if (multi && length(attr(Terms, "specials")$ridge) >0) + stop("multi-state models do not currently support ridge penalties") + + if (control$timefix) Y <- aeqSurv(Y) + \nwhypf{coxph-bothsides1}{coxph-bothsides}{coxph-bothsides2} + + # The time transform will expand the data frame mf. To do this + # it needs Y and the strata. Everything else (cluster, offset, weights) + # should be extracted after the transform + # + strats <- attr(Terms, "specials")$strata + hasinteractions <- FALSE + dropterms <- NULL + if (length(strats)) \{ + stemp <- untangle.specials(Terms, 'strata', 1) + if (length(stemp$vars)==1) strata.keep <- mf[[stemp$vars]] + else strata.keep <- strata(mf[,stemp$vars], shortlabel=TRUE) + istrat <- as.integer(strata.keep) + + for (i in stemp$vars) \{ #multiple strata terms are allowed + # The factors attr has one row for each variable in the frame, one + # col for each term in the model. Pick rows for each strata + # var, and find if it participates in any interactions. + if (any(attr(Terms, 'order')[attr(Terms, "factors")[i,] >0] >1)) + hasinteractions <- TRUE + \} + if (!hasinteractions) dropterms <- stemp$terms + \} else istrat <- NULL + + if (hasinteractions && multi) + stop("multi-state coxph does not support strata*covariate interactions") + + + timetrans <- attr(Terms, "specials")$tt + if (missing(tt)) tt <- NULL + if (length(timetrans)) \{ + if (multi || isSurv2) stop("the tt() transform is not implemented for multi-state or Surv2 models") + \nwhypf{coxph-transform1}{coxph-transform}{coxph-transform2} + \} + + xlevels <- .getXlevels(Terms, mf) + + # grab the cluster, if present. Using cluster() in a formula is no + # longer encouraged + cluster <- model.extract(mf, "cluster") + weights <- model.weights(mf) + # The user can call with cluster, id, robust, or any combination + # Default for robust: if cluster or any id with > 1 event or + # any weights that are not 0 or 1, then TRUE + # If only id, treat it as the cluster too + has.cluster <- !(missing(cluster) || length(cluster)==0) + has.id <- !(missing(id) || length(id)==0) + has.rwt<- (!is.null(weights) && any(weights != floor(weights))) + #has.rwt<- FALSE # we are rethinking this + has.robust <- (!missing(robust) && !is.null(robust)) # arg present + if (has.id) id <- as.factor(id) + + if (missing(robust) || is.null(robust)) \{ + if (has.cluster || has.rwt || + (has.id && (multi || anyDuplicated(id[Y[,ncol(Y)]==1])))) + robust <- TRUE else robust <- FALSE + \} + if (!is.logical(robust)) stop("robust must be TRUE/FALSE") + + if (has.cluster) \{ + if (!robust) \{ + warning("cluster specified with robust=FALSE, cluster ignored") + ncluster <- 0 + clname <- NULL + \} + else \{ + if (is.factor(cluster)) \{ + clname <- levels(cluster) + cluster <- as.integer(cluster) + \} else \{ + clname <- sort(unique(cluster)) + cluster <- match(cluster, clname) + \} + ncluster <- length(clname) + \} + \} else \{ + if (robust && has.id) \{ + # treat the id as both identifier and clustering + clname <- levels(id) + cluster <- as.integer(id) + ncluster <- length(clname) + \} + else \{ + ncluster <- 0 # has neither + \} + \} + + # if the user said "robust", (time1,time2) data, and no cluster or + # id, complain about it + if (robust && is.null(cluster)) \{ + if (ncol(Y) ==2 || !has.robust) cluster <- seq.int(1, nrow(mf)) + else stop("one of cluster or id is needed") + \} + + contrast.arg <- NULL #due to shared code with model.matrix.coxph + attr(Terms, "intercept") <- 1 # always have a baseline hazard + + if (multi) \{ + \nwhypf{coxph-multiform21}{coxph-multiform2}{coxph-multiform22} + \} + + \nwhypf{coxph-make-X1}{coxph-make-X}{coxph-make-X2} + \nwhypf{coxph-setup1}{coxph-setup}{coxph-setup2} + if (multi) \{ + \nwhypf{coxph-multi-X1}{coxph-multi-X}{coxph-multi-X2} + \} + + # infinite covariates are not screened out by the na.omit routines + # But this needs to be done after the multi-X part + if (!all(is.finite(X))) + stop("data contains an infinite predictor") + + + # init is checked after the final X matrix has been made + if (missing(init)) init <- NULL + else \{ + if (length(init) != ncol(X)) stop("wrong length for init argument") + temp <- X %*% init - sum(colMeans(X) * init) + offset + # it's okay to have a few underflows, but if all of them are too + # small we get all zeros + if (any(exp(temp) > .Machine$double.xmax) || all(exp(temp)==0)) + stop("initial values lead to overflow or underflow of the exp function") + \} + + \nwhypf{coxph-penal1}{coxph-penal}{coxph-penal2} + \nwhypf{coxph-compute1}{coxph-compute}{coxph-compute2} + \nwhypf{coxph-finish1}{coxph-finish}{coxph-finish2} + \} +\end{nwchunk} + + +Multi-state models have a multi-state response, optionally they have a +formula that is a list. +If the formula is a list then the first element is the default formula +with a survival response and covariates on the right. +Further elements are of the form from/to ~ covariates / options and +specify other covariates for all from:to transitions. +Steps in processing such a formula are +\begin{enumerate} + \item Gather all the variables that appear on a right-hand side, and + create a master formula y ~ all of them. This is used to create the + model.frame. We also need to defer missing value processing, since + some covariates might appear for only some transitions. + \item Get the data. The response, id, and statedata variables can now + be checked for consistency with the formulas. + \item After X has been formed, expand it. +\end{enumerate} +Here is code for the first step. + +\begin{nwchunk} +\nwhypb{coxph-multiform12}{coxph-multiform1}{coxph-multiform11}= + multiform <- TRUE + dformula <- formula[[1]] # the default formula for transitions + if (missing(statedata)) covlist <- parsecovar1(formula[-1]) + else \{ + if (!inherits(statedata, "data.frame")) + stop("statedata must be a data frame") + if (is.null(statedata$state)) + stop("statedata data frame must contain a 'state' variable") + covlist <- parsecovar1(formula[-1], names(statedata)) + \} + + # create the master formula, used for model.frame + # the term.labels + reformulate + environment trio is used in [.terms; + # if it's good enough for base R it's good enough for me + tlab <- unlist(lapply(covlist$rhs, function(x) + attr(terms.formula(x$formula), "term.labels"))) + tlab <- c(attr(terms.formula(dformula), "term.labels"), tlab) + newform <- reformulate(tlab, dformula[[2]]) + environment(newform) <- environment(dformula) + formula <- newform + tform$na.action <- na.pass # defer any missing value work to later +\end{nwchunk} + +\begin{nwchunk} +\nwhypb{coxph-multiform22}{coxph-multiform2}{coxph-multiform21}= + # check for consistency of the states, and create a transition + # matrix + if (length(id)==0) + stop("an id statement is required for multi-state models") + + mcheck <- survcheck2(Y, id, istate) + # error messages here + if (mcheck$flag["overlap"] > 0) + stop("data set has overlapping intervals for one or more subjects") + + transitions <- mcheck$transitions + istate <- mcheck$istate + states <- mcheck$states + + # build tmap, which has one row per term, one column per transition + if (missing(statedata)) + covlist2 <- parsecovar2(covlist, NULL, dformula= dformula, + Terms, transitions, states) + else covlist2 <- parsecovar2(covlist, statedata, dformula= dformula, + Terms, transitions, states) + tmap <- covlist2$tmap + if (!is.null(covlist)) \{ + \nwhypf{coxph-missing1}{coxph-missing}{coxph-missing2} + \} +\end{nwchunk} + +For multi-state models we can't tell what observations should be removed until +any extra formulas have been processed. +There may be rows that are missing \emph{some} of the covariates but +are okay for \emph{some} transitions. Others could be useless. +Those rows can be removed from the model frame before creating the X matrix. +Also identify partially used rows, ones where the necessary covariates are +present for some of the possible transitions but not all. +Those obs are dealt with later by the stacker function. +\begin{nwchunk} +\nwhypb{coxph-missing2}{coxph-missing}{coxph-missing1}= + # first vector will be true if there is at least 1 transition for which all + # covariates are present, second if there is at least 1 for which some are not + good.tran <- bad.tran <- rep(FALSE, nrow(Y)) + # We don't need to check interaction terms + termname <- rownames(attr(Terms, 'factors')) + trow <- (!is.na(match(rownames(tmap), termname))) + + # create a missing indicator for each term + termiss <- matrix(0L, nrow(mf), ncol(mf)) + for (i in 1:ncol(mf)) \{ + xx <- is.na(mf[[i]]) + if (is.matrix(xx)) termiss[,i] <- apply(xx, 1, any) + else termiss[,i] <- xx + \} + + for (i in levels(istate)) \{ + rindex <- which(istate ==i) + j <- which(covlist2$mapid[,1] == match(i, states)) #possible transitions + for (jcol in j) \{ + k <- which(trow & tmap[,jcol] > 0) # the terms involved in that + bad.tran[rindex] <- (bad.tran[rindex] | + apply(termiss[rindex, k, drop=FALSE], 1, any)) + good.tran[rindex] <- (good.tran[rindex] | + apply(!termiss[rindex, k, drop=FALSE], 1, all)) + \} + \} + n.partially.used <- sum(good.tran & bad.tran & !is.na(Y)) + omit <- (!good.tran & bad.tran) | is.na(Y) + if (all(omit)) stop("all observations deleted due to missing values") + temp <- setNames(seq(omit)[omit], attr(mf, "row.names")[omit]) + attr(temp, "class") <- "omit" + mf <- mf[!omit,, drop=FALSE] + attr(mf, "na.action") <- temp + Y <- Y[!omit] + id <- id[!omit] + if (length(istate)) istate <- istate[!omit] # istate can be NULL +\end{nwchunk} + +For a multi-state model, create the expanded X matrix. Sometimes it is +much expanded. +The first step is to create the cmap matrix from tmap by expanding terms; +factors turn into multiple columns for instance. +If tmap has rows (terms) for strata, then we have to deal with the complication +that a strata might be applied to some transitions and not to others. +\begin{nwchunk} +\nwhyp{coxph-multi-X2}{coxph-multi-X}{coxph-multi-X1}{coxph-multi-X3}= + if (length(strats) >0) \{ + stratum_map <- tmap[c(1L, strats),] # strats includes Y, + tmap has an extra row + stratum_map[-1,] <- ifelse(stratum_map[-1,] >0, 1L, 0L) + if (nrow(stratum_map) > 2) \{ + temp <- stratum_map[-1,] + if (!all(apply(temp, 2, function(x) all(x==0) || all(x==1)))) \{ + # the hard case: some transitions use one strata variable, some + # transitions use another. We need to keep them separate + strata.keep <- mf[,strats] # this will be a data frame + istrat <- sapply(strata.keep, as.numeric) + \} + \} + \} + else stratum_map <- tmap[1,,drop=FALSE] +\end{nwchunk} + +Also create the initial values vector. + +The stacker function will create a separate block of observations for every +unique value in \code{stratum\_map}. +Now say that two transitions A:B and A:C share the same baseline hazard. +Then either a B or a C outcome will be an ``event'' in that stratum; they +would only be distinguished by perhaps having different covariates. +The first thing we do with the result is to rebuild the transitions matrix: +the working version was created before removing missings and can +seriously overstate the number of transitions available. +Then set up the data. + +\begin{nwchunk} +\nwhyp{coxph-multi-X3}{coxph-multi-X}{coxph-multi-X2}{coxph-multi-X4}= + cmap <- parsecovar3(tmap, colnames(X), attr(X, "assign"), covlist2$phbaseline) + xstack <- stacker(cmap, stratum_map, as.integer(istate), X, Y, strata=istrat, + states=states) + + rkeep <- unique(xstack$rindex) + transitions <- survcheck2(Y[rkeep,], id[rkeep], istate[rkeep])$transitions + + X <- xstack$X + Y <- xstack$Y + istrat <- xstack$strata + if (length(offset)) offset <- offset[xstack$rindex] + if (length(weights)) weights <- weights[xstack$rindex] + if (length(cluster)) cluster <- cluster[xstack$rindex] +\end{nwchunk} + +The next step for multi X is to remake the assign attribute. +It is a list with one element per term, and needs to be expanded in the +same way as \code{tmap}, which has one row per term (+ an intercept row). +For \code{predict, type='terms'} to work, no label can be repeated in the +final assign object. +If a variable `fred' were common across all the states we would want to +use that as the label, but if it appears twice, as separate terms for +two different transitions, then we label it as fred\_x:y where x:y is the +transition. +\begin{nwchunk} +\nwhypb{coxph-multi-X4}{coxph-multi-X}{coxph-multi-X3}= + t2 <- tmap[-c(1, strats),,drop=FALSE] # remove the intercept row and strata rows + r2 <- row(t2)[!duplicated(as.vector(t2)) & t2 !=0] + c2 <- col(t2)[!duplicated(as.vector(t2)) & t2 !=0] + a2 <- lapply(seq(along.with=r2), function(i) \{cmap[assign[[r2[i]]], c2[i]]\}) + # which elements are unique? + tab <- table(r2) + count <- tab[r2] + names(a2) <- ifelse(count==1, row.names(t2)[r2], + paste(row.names(t2)[r2], colnames(cmap)[c2], sep="_")) + assign <- a2 +\end{nwchunk} + +An increasingly common error is for users to put the time variable on +both sides of the formula, in the mistaken idea that this will +deal with a failure of proportional hazards. +Add a test for such models, but don't bail out. There will be cases where +someone has the the stop variable in an expression on the right hand side, +to create current age say. +The \code{variables} attribute of the Terms object is the expression form +of a list that contains the response variable followed by the predictors. +Subscripting this, element 1 is the call to ``list'' itself so we always +retain it. My \code{terms.inner} function works only with formula +objects. +\begin{nwchunk} +\nwhypb{coxph-bothsides2}{coxph-bothsides}{coxph-bothsides1}= + if (length(attr(Terms, 'variables')) > 2) \{ # a ~1 formula has length 2 + ytemp <- terms.inner(formula[1:2]) + suppressWarnings(z <- as.numeric(ytemp)) # are any of the elements numeric? + ytemp <- ytemp[is.na(z)] # toss numerics, e.g. Surv(t, 1-s) + xtemp <- terms.inner(formula[-2]) + if (any(!is.na(match(xtemp, ytemp)))) + warning("a variable appears on both the left and right sides of the formula") + \} +\end{nwchunk} + +At this point we deal with any time transforms. +The model frame is expanded to a ``fake'' data set that has a +separate stratum for each unique event-time/strata combination, +and any tt() terms in the formula are processed. +The first step is to create the index vector \Verb!tindex! and +new strata \Verb!.strata.!. This last is included in a model.frame call +(for others to use), internally the code simply replaces the \code{istrat} +variable. +A (modestly) fast C-routine first counts up and indexes the observations. +We start out with error checks; since the computation can be slow we want +to complain early. +\begin{nwchunk} +\nwhyp{coxph-transform2}{coxph-transform}{coxph-transform1}{coxph-transform3}= + timetrans <- untangle.specials(Terms, 'tt') + ntrans <- length(timetrans$terms) + + if (is.null(tt)) \{ + tt <- function(x, time, riskset, weights)\{ #default to O'Brien's logit rank + obrien <- function(x) \{ + r <- rank(x) + (r-.5)/(.5+length(r)-r) + \} + unlist(tapply(x, riskset, obrien)) + \} + \} + if (is.function(tt)) tt <- list(tt) #single function becomes a list + + if (is.list(tt)) \{ + if (any(!sapply(tt, is.function))) + stop("The tt argument must contain function or list of functions") + if (length(tt) != ntrans) \{ + if (length(tt) ==1) \{ + temp <- vector("list", ntrans) + for (i in 1:ntrans) temp[[i]] <- tt[[1]] + tt <- temp + \} + else stop("Wrong length for tt argument") + \} + \} + else stop("The tt argument must contain a function or list of functions") + + if (ncol(Y)==2) \{ + if (length(strats)==0) \{ + sorted <- order(-Y[,1], Y[,2]) + newstrat <- rep.int(0L, nrow(Y)) + newstrat[1] <- 1L + \} + else \{ + sorted <- order(istrat, -Y[,1], Y[,2]) + #newstrat marks the first obs of each strata + newstrat <- as.integer(c(1, 1*(diff(istrat[sorted])!=0))) + \} + if (storage.mode(Y) != "double") storage.mode(Y) <- "double" + counts <- .Call(Ccoxcount1, Y[sorted,], + as.integer(newstrat)) + tindex <- sorted[counts$index] + \} + else \{ + if (length(strats)==0) \{ + sort.end <- order(-Y[,2], Y[,3]) + sort.start<- order(-Y[,1]) + newstrat <- c(1L, rep(0, nrow(Y) -1)) + \} + else \{ + sort.end <- order(istrat, -Y[,2], Y[,3]) + sort.start<- order(istrat, -Y[,1]) + newstrat <- c(1L, as.integer(diff(istrat[sort.end])!=0)) + \} + if (storage.mode(Y) != "double") storage.mode(Y) <- "double" + counts <- .Call(Ccoxcount2, Y, + as.integer(sort.start -1L), + as.integer(sort.end -1L), + as.integer(newstrat)) + tindex <- counts$index + \} +\end{nwchunk} + +The C routine has returned a list with 4 elements +\begin{description} + \item[nrisk] a vector containing the number at risk at each event time + \item[time] the vector of event times + \item[status] a vector of status values + \item[index] a vector containing the set of subjects at risk for event time + 1, followed by those at risk at event time 2, those at risk at event time 3, + etc. +\end{description} + +The new data frame is then a simple creation. +The subtle part below is a desire to retain transformation information +so that a downstream call to \code{termplot} will work. +The tt function supplied by the user often finishes with a call to +\code{pspline} or \code{ns}. If the returned value of the \code{tt} +call has a class for which a \code{makepredictcall} method exists then +we need to do 2 things: +\begin{enumerate} + \item Construct a fake call, e.g., ``pspline(age)'', then feed it and + the result of tt as arguments to \code{makepredictcall} + \item Replace that componenent in the predvars attribute of the terms. +\end{enumerate} +The \code{timetrans\$terms} value is a count of the right hand side of +the formula. Some objects in the terms structure are unevaluated calls +that include y, this adds 2 to the count (the call to ``list'' and +the response). + +\begin{nwchunk} +\nwhyp{coxph-transform3}{coxph-transform}{coxph-transform2}{coxph-transform4}= + Y <- Surv(rep(counts$time, counts$nrisk), counts$status) + type <- 'right' # new Y is right censored, even if the old was (start, stop] + + mf <- mf[tindex,] + istrat <- rep(1:length(counts$nrisk), counts$nrisk) + weights <- model.weights(mf) + if (!is.null(weights) && any(!is.finite(weights))) + stop("weights must be finite") + + tcall <- attr(Terms, 'variables')[timetrans$terms+2] + pvars <- attr(Terms, 'predvars') + pmethod <- sub("makepredictcall.", "", as.vector(methods("makepredictcall"))) + for (i in 1:ntrans) \{ + newtt <- (tt[[i]])(mf[[timetrans$var[i]]], Y[,1], istrat, weights) + mf[[timetrans$var[i]]] <- newtt + nclass <- class(newtt) + if (any(nclass %in% pmethod)) \{ # It has a makepredictcall method + dummy <- as.call(list(as.name(class(newtt)[1]), tcall[[i]][[2]])) + ptemp <- makepredictcall(newtt, dummy) + pvars[[timetrans$terms[i]+2]] <- ptemp + \} + \} + attr(Terms, "predvars") <- pvars +\end{nwchunk} + +This is the C code for time-transformation. +For the first case it expects y to contain time and status sorted from +longest time to shortest, and strata=1 for the first observation of +each strata. +\begin{nwchunk} +\nwhypf{coxcount11}{coxcount1}{coxcount12}= + #include "survS.h" + /* + ** Count up risk sets and identify who is in each + */ + SEXP coxcount1(SEXP y2, SEXP strat2) \{ + int ntime, nrow; + int i, j, n; + int stratastart=0; /* start row for this strata */ + int nrisk=0; /* number at risk (=0 to stop -Wall complaint)*/ + double *time, *status; + int *strata; + double dtime; + SEXP rlist, rlistnames, rtime, rn, rindex, rstatus; + int *rrindex, *rrstatus; + + n = nrows(y2); + time = REAL(y2); + status = time +n; + strata = INTEGER(strat2); + + /* + ** First pass: count the total number of death times (risk sets) + ** and the total number of rows in the new data set. + */ + ntime=0; nrow=0; + for (i=0; i= dtime; istart++) + nrisk--; + for(j= i+1; j=dtime; istart++) \{ + atrisk[sort1[istart]]=0; + nrisk--; + \} + for (j=1; j1)) stop ('Penalty terms cannot be in an interaction') + pcols <- assign[match(pname, names(assign))] + + fit <- coxpenal.fit(X, Y, istrat, offset, init=init, + control, + weights=weights, method=method, + row.names(mf), pcols, pattr, assign, + nocenter= nocenter) + \} +\end{nwchunk} + +\begin{nwchunk} +\nwhypb{coxph-compute2}{coxph-compute}{coxph-compute1}= + else \{ + rname <- row.names(mf) + if (multi) rname <- rname[xstack$rindex] + if( method=="breslow" || method =="efron") \{ + if (grepl('right', type)) + fit <- coxph.fit(X, Y, istrat, offset, init, control, + weights=weights, method=method, + rname, nocenter=nocenter) + else fit <- agreg.fit(X, Y, istrat, offset, init, control, + weights=weights, method=method, + rname, nocenter=nocenter) + \} + else if (method=='exact') \{ + if (type== "right") + fit <- coxexact.fit(X, Y, istrat, offset, init, control, + weights=weights, method=method, + rname, nocenter=nocenter) + else fit <- agexact.fit(X, Y, istrat, offset, init, control, + weights=weights, method=method, + rname, nocenter=nocenter) + \} + else stop(paste ("Unknown method", method)) + \} +\end{nwchunk} + +\begin{nwchunk} +\nwhyp{coxph-finish2}{coxph-finish}{coxph-finish1}{coxph-finish3}= + if (is.character(fit)) \{ + fit <- list(fail=fit) + class(fit) <- 'coxph' + \} + else \{ + if (!is.null(fit$coefficients) && any(is.na(fit$coefficients))) \{ + vars <- (1:length(fit$coefficients))[is.na(fit$coefficients)] + msg <-paste("X matrix deemed to be singular; variable", + paste(vars, collapse=" ")) + if (!singular.ok) stop(msg) + # else warning(msg) # stop being chatty + \} + fit$n <- data.n + fit$nevent <- sum(Y[,ncol(Y)]) + fit$terms <- Terms + fit$assign <- assign + class(fit) <- fit$class + fit$class <- NULL + + # don't compute a robust variance if there are no coefficients + if (robust && !is.null(fit$coefficients) && !all(is.na(fit$coefficients))) \{ + fit$naive.var <- fit$var + # a little sneaky here: by calling resid before adding the + # na.action method, I avoid having missings re-inserted + # I also make sure that it doesn't have to reconstruct X and Y + fit2 <- c(fit, list(x=X, y=Y, weights=weights)) + if (length(istrat)) fit2$strata <- istrat + if (length(cluster)) \{ + temp <- residuals.coxph(fit2, type='dfbeta', collapse=cluster, + weighted=TRUE) + # get score for null model + if (is.null(init)) + fit2$linear.predictors <- 0*fit$linear.predictors + else fit2$linear.predictors <- c(X %*% init) + temp0 <- residuals.coxph(fit2, type='score', collapse=cluster, + weighted=TRUE) + \} + else \{ + temp <- residuals.coxph(fit2, type='dfbeta', weighted=TRUE) + fit2$linear.predictors <- 0*fit$linear.predictors + temp0 <- residuals.coxph(fit2, type='score', weighted=TRUE) + \} + fit$var <- t(temp) %*% temp + u <- apply(as.matrix(temp0), 2, sum) + fit$rscore <- coxph.wtest(t(temp0)%*%temp0, u, control$toler.chol)$test + \} + + #Wald test + if (length(fit$coefficients) && is.null(fit$wald.test)) \{ + #not for intercept only models, or if test is already done + nabeta <- !is.na(fit$coefficients) + # The init vector might be longer than the betas, for a sparse term + if (is.null(init)) temp <- fit$coefficients[nabeta] + else temp <- (fit$coefficients - + init[1:length(fit$coefficients)])[nabeta] + fit$wald.test <- coxph.wtest(fit$var[nabeta,nabeta], temp, + control$toler.chol)$test + \} + + # Concordance. Done here so that we can use cluster if it is present + # The returned value is a subset of the full result, partly because it + # is all we need, but more for backward compatability with survConcordance.fit + if (length(cluster)) + temp <- concordancefit(Y, fit$linear.predictors, istrat, weights, + cluster=cluster, reverse=TRUE, + timefix= FALSE) + else temp <- concordancefit(Y, fit$linear.predictors, istrat, weights, + reverse=TRUE, timefix= FALSE) + if (is.matrix(temp$count)) + fit$concordance <- c(colSums(temp$count), concordance=temp$concordance, + std=sqrt(temp$var)) + else fit$concordance <- c(temp$count, concordance=temp$concordance, + std=sqrt(temp$var)) + + na.action <- attr(mf, "na.action") + if (length(na.action)) fit$na.action <- na.action + if (model) \{ + if (length(timetrans)) \{ + stop("'model=TRUE' not supported for models with tt terms") + \} + fit$model <- mf + \} + if (x) \{ + fit$x <- X + if (length(timetrans)) fit$strata <- istrat + else if (length(strats)) fit$strata <- strata.keep + \} + if (y) fit$y <- Y + fit$timefix <- control$timefix # remember this option + \} +\end{nwchunk} +If any of the weights were not 1, save the results. +Add names to the means component, which are occassionally +useful to survfit.coxph. +Other objects below are used when we need to recreate a +model frame. + +\begin{nwchunk} +\nwhypb{coxph-finish3}{coxph-finish}{coxph-finish2}= + if (!is.null(weights) && any(weights!=1)) fit$weights <- weights + if (multi) \{ + fit$transitions <- transitions + fit$states <- states + fit$cmap <- cmap + fit$stratum_map <- stratum_map # why not 'stratamap'? Confusion with fit$strata + fit$resid <- rowsum(fit$resid, xstack$rindex) + # add a suffix to each coefficent name. Those that map to multiple transitions + # get the first transition they map to + single <- apply(cmap, 1, function(x) all(x %in% c(0, max(x)))) #only 1 coef + cindx <- col(cmap)[match(1:length(fit$coefficients), cmap)] + rindx <- row(cmap)[match(1:length(fit$coefficients), cmap)] + suffix <- ifelse(single[rindx], "", paste0("_", colnames(cmap)[cindx])) + names(fit$coefficients) <- paste0(names(fit$coefficients), suffix) + if (x) fit$strata <- istrat # save the expanded strata + class(fit) <- c("coxphms", class(fit)) + \} + names(fit$means) <- names(fit$coefficients) + + fit$formula <- formula(Terms) + if (length(xlevels) >0) fit$xlevels <- xlevels + fit$contrasts <- contr.save + if (any(offset !=0)) fit$offset <- offset + + fit$call <- Call + fit +\end{nwchunk} + +The model.matrix and model.frame routines are called after a Cox model to +reconstruct those portions. +Much of their code is shared with the coxph routine. + +\begin{nwchunk} +\nwhypf{model.matrix.coxph1}{model.matrix.coxph}{model.matrix.coxph2}= + # In internal use "data" will often be an already derived model frame. + # We detect this via it having a terms attribute. + model.matrix.coxph <- function(object, data=NULL, + contrast.arg=object$contrasts, ...) \{ + # + # If the object has an "x" component, return it, unless a new + # data set is given + if (is.null(data) && !is.null(object[['x']])) + return(object[['x']]) #don't match "xlevels" + + Terms <- delete.response(object$terms) + if (is.null(data)) mf <- stats::model.frame(object) + else \{ + if (is.null(attr(data, "terms"))) + mf <- stats::model.frame(Terms, data, xlev=object$xlevels) + else mf <- data #assume "data" is already a model frame + \} + + cluster <- attr(Terms, "specials")$cluster + if (length(cluster)) \{ + temp <- untangle.specials(Terms, "cluster") + dropterms <- temp$terms + \} + else dropterms <- NULL + + strats <- attr(Terms, "specials")$strata + hasinteractions <- FALSE + if (length(strats)) \{ + stemp <- untangle.specials(Terms, 'strata', 1) + if (length(stemp$vars)==1) strata.keep <- mf[[stemp$vars]] + else strata.keep <- strata(mf[,stemp$vars], shortlabel=TRUE) + istrat <- as.integer(strata.keep) + + for (i in stemp$vars) \{ #multiple strata terms are allowed + # The factors attr has one row for each variable in the frame, one + # col for each term in the model. Pick rows for each strata + # var, and find if it participates in any interactions. + if (any(attr(Terms, 'order')[attr(Terms, "factors")[i,] >0] >1)) + hasinteractions <- TRUE + \} + if (!hasinteractions) dropterms <- c(dropterms, stemp$terms) + \} else istrat <- NULL + + \nwhypb{coxph-make-X3}{coxph-make-X}{coxph-make-X2} + X + \} +\end{nwchunk} + +In parallel is the model.frame routine, which reconstructs the model frame. +This routine currently doesn't do all that we want. To wit, the following code +fails: +\begin{verbatim} +> tfun <- function(formula, ndata) { + fit <- coxph(formula, data=ndata) + model.frame(fit) + } +> tfun(Surv(time, status) ~ age, lung) +Error: ndata not found +\end{verbatim} +The genesis of this problem is hard to unearth, but has to do with non standard +evaluation rules used by model.frame.default. In essence it pays attention to +the environment of the formula, but the enclos argument of eval appears to be +ignored. I've not yet found a solution. + +\begin{nwchunk} +\nwhypb{model.matrix.coxph2}{model.matrix.coxph}{model.matrix.coxph1}= + model.frame.coxph <- function(formula, ...) \{ + dots <- list(...) + nargs <- dots[match(c("data", "na.action", "subset", "weights", + "id", "cluster", "istate"), + names(dots), 0)] + # If nothing has changed and the coxph object had a model component, + # simply return it. + if (length(nargs) ==0 && !is.null(formula$model)) return(formula$model) + else \{ + # Rebuild the original call to model.frame + Terms <- terms(formula) + fcall <- formula$call + indx <- match(c("formula", "data", "weights", "subset", "na.action", + "cluster", "id", "istate"), + names(fcall), nomatch=0) + if (indx[1] ==0) stop("The coxph call is missing a formula!") + + temp <- fcall[c(1,indx)] # only keep the arguments we wanted + temp[[1]] <- quote(stats::model.frame) # change the function called + temp$xlev <- formula$xlevels # this will turn strings to factors + temp$formula <- Terms #keep the predvars attribute + # Now, any arguments that were on this call overtake the ones that + # were in the original call. + if (length(nargs) >0) + temp[names(nargs)] <- nargs + + # Make "tt" visible for coxph formulas, + if (!is.null(attr(temp$formula, "specials")$tt)) \{ + coxenv <- new.env(parent= environment(temp$formula)) + assign("tt", function(x) x, envir=coxenv) + environment(temp$formula) <- coxenv + \} + + # The documentation for model.frame implies that the environment arg + # to eval will be ignored, but if we omit it there is a problem. + if (is.null(environment(formula$terms))) + mf <- eval(temp, parent.frame()) + else mf <- eval(temp, environment(formula$terms), parent.frame()) + + if (!is.null(attr(formula$terms, "dataClasses"))) + .checkMFClasses(attr(formula$terms, "dataClasses"), mf) + + if (is.null(attr(Terms, "specials")$tt)) return(mf) + else \{ + # Do time transform + tt <- eval(formula$call$tt) + Y <- aeqSurv(model.response(mf)) + strats <- attr(Terms, "specials")$strata + if (length(strats)) \{ + stemp <- untangle.specials(Terms, 'strata', 1) + if (length(stemp$vars)==1) strata.keep <- mf[[stemp$vars]] + else strata.keep <- strata(mf[,stemp$vars], shortlabel=TRUE) + istrat <- as.numeric(strata.keep) + \} + + \nwhypb{coxph-transform4}{coxph-transform}{coxph-transform3} + mf[[".strata."]] <- istrat + return(mf) + \} + \} + \} +\end{nwchunk} + +\subsection{Exact partial likelihood} +Let $r_i = \exp(X_i\beta)$ be the risk score for observation $i$. +For one of the time points assume that there that there are $d$ +tied deaths among $n$ subjects at risk. +For convenience we will index them as $i= 1,\ldots,d$ in the $n$ at risk. +Then for the exact parial likelihood, the contribution at this time point +is +\begin{align*} + L &= \sum_{i=1}^d \log(r_i) - \log(D) \\ + \frac{\partial L}{\partial \beta_j} &= x_{ij} - (1/D) + \frac{\partial D}{\partial \beta_j} \\ + \frac{\partial^2 L}{\partial \beta_j \partial \beta_k} &= + (1/D^2)\left[D\frac{\partial^2D}{\partial \beta_j \partial \beta_k} - + \frac{\partial D}{\partial \beta_j}\frac{\partial D}{\partial \beta_k} + \right] +\end{align*} +The hard part of this computation is $D$, which is a sum +\begin{equation*} + D = \sum_{S(d,n)} r_{s_1}r_{s_2} \ldots r_{s_d} +\end{equation*} +where $S(d,n)$ is the set of all possible subsets of size $d$ from $n$ +objects, and $s_1, s_2, \ldots$ indexes the current selection. +So if $n=6$ and $d=2$ we would have the 15 pairs 12, 13, .... 56; +for $n=5$ and $d=3$ there would be 10 triples 123, 124, 125, \ldots, 345. + +The brute force computation of all subsets can take a very long time. +Gail et al \cite{Gail81} show simple recursion formulas that speed +this up considerably. Let $D(d,n)$ be the denominator with $d$ +deaths and $n$ subjects. Then +\begin{align} + D(d,n) &= r_nD(d-1, n-1) + D(d, n-1) \label{d0}\\ + \frac{\partial D(d,n)}{\partial \beta_j} &= + \frac{\partial D(d, n-1)}{\partial \beta_j} + + r_n \frac{\partial D(d-1, n-1)}{\partial \beta_j} + + x_{nj}r_n D(d-1, n-1) \label{d1}\\ + \frac{\partial^2D(d,n}{\partial \beta_j \partial \beta_k} &= + \frac{\partial^2D(d,n-1)}{\partial \beta_j \partial \beta_k} + + r_n\frac{\partial^2D(d-1,n-1)}{\partial \beta_j \partial \beta_k} + + x_{nj}r_n\frac{\partial D(d-1, n-1)}{\partial \beta_k} + \nonumber \\ + & x_{nk}r_n\frac{\partial D(d-1, n-1)}{\partial \beta_j} + + x_{nj}x_{nk}r_n D(d-1, n-1) \label{d2} +\end{align} + +The above recursion is captured in the three routines below. +The first calculates $D$. +It is called with $d$, $n$, an array that will contain all the +values of $D(d,n)$ computed so far, and the the first dimension of the array. +The intial condition $D(0,n)=1$ is important to all three routines. + +\begin{nwchunk} +\nwhypf{excox-recur1}{excox-recur}{excox-recur2}= + double coxd0(int d, int n, double *score, double *dmat, + int dmax) \{ + double *dn; + + if (d==0) return(1.0); + dn = dmat + (n-1)*dmax + d -1; /* pointer to dmat[d,n] */ + + if (*dn ==0) \{ /* still to be computed */ + *dn = score[n-1]* coxd0(d-1, n-1, score, dmat, dmax); + if (d1) d1[indx] += score[n-1]* + coxd1(d-1, n-1, score, dmat, d1, covar, dmax); + \} + return(d1[indx]); + \} + + double coxd2(int d, int n, double *score, double *dmat, double *d1j, + double *d1k, double *d2, double *covarj, double *covark, + int dmax) \{ + int indx; + + indx = (n-1)*dmax + d -1; /*index to the current array member d1[d,n]*/ + if (d2[indx] ==0) \{ /*still to be computed */ + d2[indx] = coxd0(d-1, n-1, score, dmat, dmax)*score[n-1] * + covarj[n-1]* covark[n-1]; + if (d1) d2[indx] += score[n-1] * ( + coxd2(d-1, n-1, score, dmat, d1j, d1k, d2, covarj, covark, dmax) + + covarj[n-1] * coxd1(d-1, n-1, score, dmat, d1k, covark, dmax) + + covark[n-1] * coxd1(d-1, n-1, score, dmat, d1j, covarj, dmax)); + \} + return(d2[indx]); + \} +\end{nwchunk} + +Now for the main body. Start with the dull part of the code: +declarations. +I use \Verb!maxiter2! for the +S structure and \Verb!maxiter! for the variable within it, and +etc for the other input arguments. +All the input arguments except strata are read-only. +The output beta vector starts as a copy of ibeta. +\begin{nwchunk} +\nwhypn{coxexact}= + #include + #include "survS.h" + #include "survproto.h" + #include + + \nwhypb{excox-recur3}{excox-recur}{excox-recur2} + + SEXP coxexact(SEXP maxiter2, SEXP y2, + SEXP covar2, SEXP offset2, SEXP strata2, + SEXP ibeta, SEXP eps2, SEXP toler2) \{ + int i,j,k; + int iter; + + double **covar, **imat; /*ragged arrays */ + double *time, *status; /* input data */ + double *offset; + int *strata; + int sstart; /* starting obs of current strata */ + double *score; + double *oldbeta; + double zbeta; + double newlk=0; + double temp; + int halving; /*are we doing step halving at the moment? */ + int nrisk =0; /* number of subjects in the current risk set */ + int dsize, /* memory needed for one coxc0, coxc1, or coxd2 array */ + dmemtot, /* amount needed for all arrays */ + ndeath; /* number of deaths at the current time point */ + double maxdeath; /* max tied deaths within a strata */ + + double dtime; /* time value under current examiniation */ + double *dmem0, **dmem1, *dmem2; /* pointers to memory */ + double *dtemp; /* used for zeroing the memory */ + double *d1; /* current first derivatives from coxd1 */ + double d0; /* global sum from coxc0 */ + + /* copies of scalar input arguments */ + int nused, nvar, maxiter; + double eps, toler; + + /* returned objects */ + SEXP imat2, beta2, u2, loglik2; + double *beta, *u, *loglik; + SEXP rlist, rlistnames; + int nprotect; /* number of protect calls I have issued */ + + \nwhypf{excox-setup1}{excox-setup}{excox-setup2} + \nwhypf{excox-strata1}{excox-strata}{excox-strata2} + \nwhypf{excox-iter01}{excox-iter0}{excox-iter02} + \nwhypf{excox-iter1}{excox-iter}{excox-iter2} + \} +\end{nwchunk} + +Setup is ordinary. Grab S objects and assign others. +I use \verb!R_alloc! for temporary ones since it is released automatically on +return. +\begin{nwchunk} +\nwhypb{excox-setup2}{excox-setup}{excox-setup1}= + nused = LENGTH(offset2); + nvar = ncols(covar2); + maxiter = asInteger(maxiter2); + eps = asReal(eps2); /* convergence criteria */ + toler = asReal(toler2); /* tolerance for cholesky */ + + /* + ** Set up the ragged array pointer to the X matrix, + ** and pointers to time and status + */ + covar= dmatrix(REAL(covar2), nused, nvar); + time = REAL(y2); + status = time +nused; + strata = INTEGER(PROTECT(duplicate(strata2))); + offset = REAL(offset2); + + /* temporary vectors */ + score = (double *) R_alloc(nused+nvar, sizeof(double)); + oldbeta = score + nused; + + /* + ** create output variables + */ + PROTECT(beta2 = duplicate(ibeta)); + beta = REAL(beta2); + PROTECT(u2 = allocVector(REALSXP, nvar)); + u = REAL(u2); + PROTECT(imat2 = allocVector(REALSXP, nvar*nvar)); + imat = dmatrix(REAL(imat2), nvar, nvar); + PROTECT(loglik2 = allocVector(REALSXP, 5)); /* loglik, sctest, flag,maxiter*/ + loglik = REAL(loglik2); + nprotect = 5; +\end{nwchunk} + +The data passed to us has been sorted by strata, and +reverse time within strata (longest subject first). +The variable \Verb!strata! will be 1 at the start of each new strata. +Separate strata are completely separate computations: time 10 in +one strata and time 10 in another are not comingled. +Compute the largest product (size of strata)* +(max tied deaths in strata) for allocating scratch space. +When computing $D$ it is advantageous to create all the intermediate +values of $D(d,n)$ in an array since they will be used in the +derivative calculation. Likewise, the first derivatives are used +in calculating the second. +Even more importantly, say we have a large data set. It will +be sorted with the longest times first. +If there is a death with 30 at risk and another with 40 at +risk, the intermediate sums we computed for the n=30 case +are part of the computation for n=40. To make this +work we need to index our matrices, within any strata, +by the maximum number of tied deaths in the strata. +We save this in the strata variable: first obs of a new +strata has the number of events. +And what if a strata had 0 events? We mark it with a 1. + +Note that the maxdeath variable is floating point. I had someone call this +routine with a data set that gives an integer overflow in that situation. +We now keep track of this further below and fail with a message. +Such a run would take longer than forever to complete even if integer +subscripts did not overflow. +\begin{nwchunk} +\nwhypb{excox-strata2}{excox-strata}{excox-strata1}= + strata[0] =1; /* in case the parent forgot (e.g., no strata case)*/ + temp = 0; /* temp variable for dsize */ + + maxdeath =0; + j=0; /* start of the strata */ + for (i=0; i0) \{ + /* assign data for the prior stratum, just finished */ + /* If maxdeath <2 leave the strata alone at it's current value of 1 */ + if (maxdeath >1) strata[j] = maxdeath; + j = i; + if (maxdeath*nrisk > temp) temp = maxdeath*nrisk; + \} + maxdeath =0; /* max tied deaths at any time in this strata */ + nrisk=0; + ndeath =0; + \} + dtime = time[i]; + ndeath =0; /*number tied here */ + while (time[i] ==dtime) \{ + nrisk++; + ndeath += status[i]; + i++; + if (i>=nused || strata[i] >0) break; /*tied deaths don't cross strata */ + \} + if (ndeath > maxdeath) maxdeath = ndeath; + \} + /* data for the final stratum */ + if (maxdeath*nrisk > temp) temp = maxdeath*nrisk; + if (maxdeath >1) strata[j] = maxdeath; + + /* Now allocate memory for the scratch arrays + Each per-variable slice is of size dsize + */ + dsize = temp; + temp = temp * ((nvar*(nvar+1))/2 + nvar + 1); + dmemtot = dsize * ((nvar*(nvar+1))/2 + nvar + 1); + if (temp != dmemtot) \{ /* the subscripts will overflow */ + error("(number at risk) * (number tied deaths) is too large"); + \} + dmem0 = (double *) R_alloc(dmemtot, sizeof(double)); /*pointer to memory */ + dmem1 = (double **) R_alloc(nvar, sizeof(double*)); + dmem1[0] = dmem0 + dsize; /*points to the first derivative memory */ + for (i=1; i0) \{ /* first obs of a new strata */ + maxdeath= strata[i]; + dtemp = dmem0; + for (j=0; j=nused || strata[i] >0) break; + \} + + /* We have added up over the death time, now process it */ + if (ndeath >0) \{ /* Add to the loglik */ + d0 = coxd0(ndeath, nrisk, score+sstart, dmem0, maxdeath); + R_CheckUserInterrupt(); + newlk -= log(d0); + dmem2 = dmem0 + (nvar+1)*dsize; /*start for the second deriv memory */ + for (j=0; j 3) R_CheckUserInterrupt(); + u[j] -= d1[j]; + for (k=0; k<= j; k++) \{ /* second derivative*/ + temp = coxd2(ndeath, nrisk, score+sstart, dmem0, dmem1[j], + dmem1[k], dmem2, covar[j] + sstart, + covar[k] + sstart, maxdeath); + if (ndeath > 5) R_CheckUserInterrupt(); + imat[k][j] += temp/d0 - d1[j]*d1[k]; + dmem2 += dsize; + \} + \} + \} + \} +\end{nwchunk} + +Do the first iteration of the solution. The first iteration is +different in 3 ways: it is used to set the initial log-likelihood, +to compute the score test, and +we pay no attention to convergence criteria or diagnositics. +(I expect it not to converge in one iteration). + +\begin{nwchunk} +\nwhypb{excox-iter02}{excox-iter0}{excox-iter01}= + /* + ** do the initial iteration step + */ + newlk =0; + for (i=0; i0") + else weights <- as.vector(weights) + + # Find rows to be ignored. We have to match within strata: a + # value that spans a death in another stratum, but not it its + # own, should be removed. Hence the per stratum delta + if (length(strata) ==0) \{y1 <- y[,1]; y2 <- y[,2]\} + else \{ + if (is.numeric(strata)) strata <- as.integer(strata) + else strata <- as.integer(as.factor(strata)) + delta <- strata* (1+ max(y[,2]) - min(y[,1])) + y1 <- y[,1] + delta + y2 <- y[,2] + delta + \} + event <- y[,3] > 0 + dtime <- sort(unique(y2[event])) + indx1 <- findInterval(y1, dtime) + indx2 <- findInterval(y2, dtime) + # indx1 != indx2 for any obs that spans an event time + ignore <- (indx1 == indx2) + nused <- sum(!ignore) + + # Sort the data (or rather, get a list of sorted indices) + # For both stop and start times, the indices go from last to first + if (length(strata)==0) \{ + sort.end <- order(ignore, -y[,2]) -1L #indices start at 0 for C code + sort.start<- order(ignore, -y[,1]) -1L + strata <- rep(0L, nrow(y)) + \} + else \{ + sort.end <- order(ignore, strata, -y[,2]) -1L + sort.start<- order(ignore, strata, -y[,1]) -1L + \} + + if (is.null(nvar) || nvar==0) \{ + # A special case: Null model. Just return obvious stuff + # To keep the C code to a small set, we call the usual routines, but + # with a dummy X matrix and 0 iterations + nvar <- 1 + x <- matrix(as.double(1:nrow(y)), ncol=1) #keep the .C call happy + maxiter <- 0 + nullmodel <- TRUE + if (length(init) !=0) stop("Wrong length for inital values") + init <- 0.0 #dummy value to keep a .C call happy (doesn't like 0 length) + \} + else \{ + nullmodel <- FALSE + maxiter <- control$iter.max + + if (is.null(init)) init <- rep(0., nvar) + if (length(init) != nvar) stop("Wrong length for inital values") + \} + + # 2021 change: pass in per covariate centering. This gives + # us more freedom to experiment. Default is to leave 0/1 variables alone + if (is.null(nocenter)) zero.one <- rep(FALSE, ncol(x)) + zero.one <- apply(x, 2, function(z) all(z %in% nocenter)) + + # the returned value of agfit$coef starts as a copy of init, so make sure + # is is a vector and not a matrix; as.double suffices. + # Solidify the storage mode of other arguments + storage.mode(y) <- storage.mode(x) <- "double" + storage.mode(offset) <- storage.mode(weights) <- "double" + agfit <- .Call(Cagfit4, nused, + y, x, strata, weights, + offset, + as.double(init), + sort.start, sort.end, + as.integer(method=="efron"), + as.integer(maxiter), + as.double(control$eps), + as.double(control$toler.chol), + ifelse(zero.one, 0L, 1L)) + # agfit4 centers variables within strata, so does not return a vector + # of means. Use a fill in consistent with other coxph routines + agmeans <- ifelse(zero.one, 0, colMeans(x)) + + \nwhypf{agreg-fixup1}{agreg-fixup}{agreg-fixup2} + \nwhypf{agreg-finish1}{agreg-finish}{agreg-finish2} + rval + \} +\end{nwchunk} + +Upon return we need to clean up three simple things. +The first is the rare case that the agfit routine failed. +These cases are rare, usually involve an overflow or underflow, and +we encourage users to let us have a copy of the data when it occurs. +(They end up in the \code{fail} directory of the library.) +The second is that if any of the covariates were redudant then this +will be marked by zeros on the diagonal of the variance matrix. +Replace these coefficients and their variances with NA. +The last is to post a warning message about possible infinite coefficients. +The algorithm for determining this is unreliable, unfortunately. +Sometimes coefficients are marked as infinite when the solution is not tending +to infinity (usually associated with a very skewed covariate), and sometimes +one that is tending to infinity is not marked. Que sera sera. +Don't complain if the user asked for only one iteration; they will already +know that it has not converged. +\begin{nwchunk} +\nwhypb{agreg-fixup2}{agreg-fixup}{agreg-fixup1}= + vmat <- agfit$imat + coef <- agfit$coef + if (agfit$flag[1] < nvar) which.sing <- diag(vmat)==0 + else which.sing <- rep(FALSE,nvar) + + if (maxiter >1) \{ + infs <- abs(agfit$u %*% vmat) + if (any(!is.finite(coef)) || any(!is.finite(vmat))) + stop("routine failed due to numeric overflow.", + "This should never happen. Please contact the author.") + if (agfit$flag[4] > 0) + warning("Ran out of iterations and did not converge") + else \{ + infs <- (!is.finite(agfit$u) | + infs > control$toler.inf*(1+ abs(coef))) + if (any(infs)) + warning(paste("Loglik converged before variable ", + paste((1:nvar)[infs],collapse=","), + "; beta may be infinite. ")) + \} + \} +\end{nwchunk} + +The last of the code is very standard. Compute residuals and package +up the results. +One design decision is that we return all $n$ residuals and predicted +values, even though the model fit ignored useless observations. +(All those obs have a residual of 0). +\begin{nwchunk} +\nwhypb{agreg-finish2}{agreg-finish}{agreg-finish1}= + lp <- as.vector(x %*% coef + offset - sum(coef * agmeans)) + if (resid) \{ + if (any(lp > log(.Machine$double.xmax))) \{ + # prevent a failure message due to overflow + # this occurs with near-infinite coefficients + temp <- lp + log(.Machine$double.xmax) - (1 + max(lp)) + score <- exp(temp) + \} else score <- exp(lp) + + residuals <- .Call(Cagmart3, nused, + y, score, weights, + strata, + sort.start, sort.end, + as.integer(method=='efron')) + names(residuals) <- rownames + \} + + # The if-then-else below is a real pain in the butt, but the tccox + # package's test suite assumes that the ORDER of elements in a coxph + # object will never change. + # + if (nullmodel) \{ + rval <- list(loglik=agfit$loglik[2], + linear.predictors = offset, + method= method, + class = c("coxph.null", 'coxph') ) + if (resid) rval$residuals <- residuals + \} + else \{ + names(coef) <- dimnames(x)[[2]] + if (maxiter > 0) coef[which.sing] <- NA # always leave iter=0 alone + flag <- agfit$flag + names(flag) <- c("rank", "rescale", "step halving", "convergence") + + if (resid) \{ + rval <- list(coefficients = coef, + var = vmat, + loglik = agfit$loglik, + score = agfit$sctest, + iter = agfit$iter, + linear.predictors = as.vector(lp), + residuals = residuals, + means = agmeans, + first = agfit$u, + info = flag, + method= method, + class = "coxph") + \} else \{ + rval <- list(coefficients = coef, + var = vmat, + loglik = agfit$loglik, + score = agfit$sctest, + iter = agfit$iter, + linear.predictors = as.vector(lp), + means = agmeans, + first = agfit$u, + info = flag, + method = method, + class = "coxph") + \} + rval + \} +\end{nwchunk} + +The details of the C code contain the more challenging part of the +computations. +It starts with the usual dull stuff. +My standard coding style for a variable zed to to use +\Verb!zed2! as the variable name for the R object, and \Verb?zed? for +the pointer to the contents of the object, i.e., what the +C code will manipulate. +For the matrix objects I make use of ragged arrays, this +allows for reference to the i,j element as \code{cmat[i][j]} +and makes for more readable code. + +\begin{nwchunk} +\nwhypn{agfit4}= + #include + #include "survS.h" + #include "survproto.h" + + SEXP agfit4(SEXP nused2, SEXP surv2, SEXP covar2, SEXP strata2, + SEXP weights2, SEXP offset2, SEXP ibeta2, + SEXP sort12, SEXP sort22, SEXP method2, + SEXP maxiter2, SEXP eps2, SEXP tolerance2, + SEXP doscale2) \{ + + int i,j,k, person; + int indx1, istrat, p, p1; + int nrisk, nr; + int nused, nvar; + int rank=0, rank2, fail; /* =0 to keep -Wall happy */ + + double **covar, **cmat, **imat; /*ragged array versions*/ + double *a, *oldbeta; + double *scale; + double *a2, **cmat2; + double *eta; + double denom, zbeta, risk; + double dtime =0; /* initial value to stop a -Wall message */ + double temp, temp2; + double newlk =0; + int halving; /*are we doing step halving at the moment? */ + double tol_chol, eps; + double meanwt; + int deaths; + double denom2, etasum; + double recenter; + + /* inputs */ + double *start, *tstop, *event; + double *weights, *offset; + int *sort1, *sort2, maxiter; + int *strata; + double method; /* saving this as double forces some double arithmetic */ + int *doscale; + + /* returned objects */ + SEXP imat2, beta2, u2, loglik2; + double *beta, *u, *loglik; + SEXP sctest2, flag2, iter2; + double *sctest; + int *flag, *iter; + SEXP rlist; + static const char *outnames[]=\{"coef", "u", "imat", "loglik", + "sctest", "flag", "iter", ""\}; + int nprotect; /* number of protect calls I have issued */ + + /* get sizes and constants */ + nused = asInteger(nused2); + nvar = ncols(covar2); + nr = nrows(covar2); /*nr = number of rows, nused = how many we use */ + method= asInteger(method2); + eps = asReal(eps2); + tol_chol = asReal(tolerance2); + maxiter = asInteger(maxiter2); + doscale = INTEGER(doscale2); + + /* input arguments */ + start = REAL(surv2); + tstop = start + nr; + event = tstop + nr; + weights = REAL(weights2); + offset = REAL(offset2); + sort1 = INTEGER(sort12); + sort2 = INTEGER(sort22); + strata = INTEGER(strata2); + + /* + ** scratch space + ** nvar: a, a2, oldbeta, scale + ** nvar*nvar: cmat, cmat2 + ** nr: eta + */ + eta = (double *) R_alloc(nr + 4*nvar + 2*nvar*nvar, sizeof(double)); + a = eta + nr; + a2= a + nvar; + scale = a2 + nvar; + oldbeta = scale + nvar; + + /* + ** Set up the ragged arrays + ** covar2 might not need to be duplicated, even though + ** we are going to modify it, due to the way this routine was + ** was called. But check + */ + PROTECT(imat2 = allocMatrix(REALSXP, nvar, nvar)); + nprotect =1; + if (MAYBE_REFERENCED(covar2)) \{ + PROTECT(covar2 = duplicate(covar2)); + nprotect++; + \} + covar= dmatrix(REAL(covar2), nr, nvar); + imat = dmatrix(REAL(imat2), nvar, nvar); + cmat = dmatrix(oldbeta+ nvar, nvar, nvar); + cmat2= dmatrix(oldbeta+ nvar + nvar*nvar, nvar, nvar); + + /* + ** create the output structures + */ + PROTECT(rlist = mkNamed(VECSXP, outnames)); + nprotect++; + beta2 = SET_VECTOR_ELT(rlist, 0, duplicate(ibeta2)); + beta = REAL(beta2); + u2 = SET_VECTOR_ELT(rlist, 1, allocVector(REALSXP, nvar)); + u = REAL(u2); + + SET_VECTOR_ELT(rlist, 2, imat2); + loglik2 = SET_VECTOR_ELT(rlist, 3, allocVector(REALSXP, 2)); + loglik = REAL(loglik2); + + sctest2 = SET_VECTOR_ELT(rlist, 4, allocVector(REALSXP, 1)); + sctest = REAL(sctest2); + flag2 = SET_VECTOR_ELT(rlist, 5, allocVector(INTSXP, 4)); + flag = INTEGER(flag2); + for (i=0; i<4; i++) flag[i]=0; + + iter2 = SET_VECTOR_ELT(rlist, 6, allocVector(INTSXP, 1)); + iter = INTEGER(iter2); + + /* + ** Subtract the mean from each covar, as this makes the variance + ** computation more stable. The mean is taken per stratum, + ** the scaling is overall. + */ + for (i=0; i0) temp = temp2/temp; /* 1/scale */ + else temp = 1.0; /* rare case of a constant covariate */ + scale[i] = temp; + for (person=0; person$ dtime. + When survSplit was used to create a data set, this will often remove all. + If so we can rezero temporaries and regain precision. + \item Add new observations to the risk set and to the death counts. +\end{enumerate} + + +\begin{nwchunk} +\nwhypf{agfit4-addup1}{agfit4-addup}{agfit4-addup2}= + for (person=0; person 200) \{ + flag[1]++; /* a count, for debugging/profiling purposes */ + temp = etasum/nrisk - recenter; + recenter = etasum/nrisk; + + if (denom > 0) \{ + /* we can skip this if there is no one at risk */ + if (fabs(temp) > 709) error("exp overflow due to covariates{\textbackslash}n"); + + temp = exp(-temp); /* the change in scale, for all the weights */ + denom *= temp; + for (i=0; i0) break; + + for (i=0; i1 && ((newlk -loglik[1])/ fabs(loglik[1])) < -eps) \{ + /* + ** "Once more unto the breach, dear friends, once more; ..." + **The last iteration above was worse than one of the earlier ones, + ** by more than roundoff error. + ** We need to use beta and imat at the last good value, not the + ** last attempted value. We have tossed the old imat away, so + ** recompute it. + ** It will happen very rarely that we run out of iterations, and + ** even less often that it is right in the middle of halving. + */ + for (i=0; i0 || newlk < loglik[1]) \{ + /* + ** The routine has not made progress past the last good value. + */ + halving++; flag[2]++; + for (i=0; i1)) + stop("not able to create a curve for models that contain an interaction without the lower order effect") + + Terms <- object$terms + n <- object$n[1] + if (!has.strata) strata <- NULL + else strata <- object$strata + + if (!missing(individual)) warning("the `id' option supersedes `individual'") + missid <- missing(id) # I need this later, and setting id below makes + # "missing(id)" always false + + if (!missid) individual <- TRUE + else if (missid && individual) id <- rep(0L,n) #dummy value + else id <- NULL + + if (individual & missing(newdata)) \{ + stop("the id option only makes sense with new data") + \} +\end{nwchunk} + +In two places below we need to know if there are strata by covariate +interactions, which requires looking at attributes of the terms +object. +The factors attribute will have a row for the strata variable, or +maybe more than one (multiple strata terms are legal). If it has +a 1 in a column that corresponds to something of order 2 or +greater, that is a strata by covariate interaction. +\begin{nwchunk} +\nwhyp{survfit.coxph-setup13}{survfit.coxph-setup1}{survfit.coxph-setup12}{survfit.coxph-setup14}= + if (has.strata) \{ + temp <- attr(Terms, "specials")$strata + factors <- attr(Terms, "factors")[temp,] + strata.interaction <- any(t(factors)*attr(Terms, "order") >1) + \} +\end{nwchunk} + + +I need to retrieve a copy of the original data. +We always need the $X$ matrix and $y$, both of which might be found in +the data object. +If the fit was a multistate model, +the original call included either strata, offset, weights, or id, +or if either $x$ or $y$ are missing from the \code{coxph} object, +then the model frame will need to be reconstructed. +We have to use \code{object['x'}] instead of \texttt{object\$x} since +the latter will +pick off the \code{xlevels} component if the \code{x} component is missing +(which is the default). +\begin{nwchunk} +\nwhyp{survfit.coxph-setup14}{survfit.coxph-setup1}{survfit.coxph-setup13}{survfit.coxph-setup15}= + coxms <- inherits(object, "coxphms") + if (coxms || is.null(object$y) || is.null(object[['x']]) || + !is.null(object$call$weights) || !is.null(object$call$id) || + (has.strata && is.null(object$strata)) || + !is.null(attr(object$terms, 'offset'))) \{ + + mf <- stats::model.frame(object) + \} + else mf <- NULL #useful for if statements later +\end{nwchunk} + +For a single state model we can grab +the X matrix off the model frame, for multistate some more work +needs to be done. +We have to repeat some lines from coxph, but to do that we need some +further material. +We prefer \code{object\$y} to model.response, since the former will have been +passed through aeqSurv with the options the user specified. +For a multi-state model, however, we do have to recreate since the +saved y has been expanded. +In that case observe the saved status of timefix. Old saved objects +might not have that element, if missing assume TRUE. + +\begin{nwchunk} +\nwhyp{survfit.coxph-setup22}{survfit.coxph-setup2}{survfit.coxph-setup21}{survfit.coxph-setup23}= + position <- NULL + Y <- object[['y']] + if (is.null(mf)) \{ + weights <- object$weights # let offsets/weights be NULL until needed + offset <- NULL + X <- object[['x']] + \} + else \{ + weights <- model.weights(mf) + offset <- model.offset(mf) + X <- model.matrix.coxph(object, data=mf) + if (is.null(Y) || coxms) \{ + Y <- model.response(mf) + if (is.null(object$timefix) || object$timefix) Y <- aeqSurv(Y) + \} + oldid <- model.extract(mf, "id") + if (length(oldid) && ncol(Y)==3) position <- survflag(Y, oldid) + else position <- NULL + if (!coxms && (nrow(Y) != object$n[1])) + stop("Failed to reconstruct the original data set") + if (has.strata) \{ + if (length(strata)==0) \{ + if (length(stangle$vars) ==1) strata <- mf[[stangle$vars]] + else strata <- strata(mf[, stangle$vars], shortlabel=TRUE) + \} + \} + + \} +\end{nwchunk} + +If a model frame was created, then it is trivial to grab \code{y} +from the new frame and compare it to \code{object\$y} from the +original one. This is to avoid nonsense results that arise +when someone changes the data set under our feet. +We can only check the size: with the addition of aeqSurv other packages +were being flagged for tiny discrepancies. +Later note: this check does not work for multi-state models, and we don't +\emph{have} to have it. Removed by using if (FALSE) so as to preserve +the code for future consideration. +\begin{nwchunk} +\nwhypb{survfit.coxph-setup2b2}{survfit.coxph-setup2b}{survfit.coxph-setup2b1}= + if (FALSE) \{ + if (!is.null(mf))\{ + y2 <- object[['y']] + if (!is.null(y2)) \{ + if (ncol(y2) != ncol(Y) || length(y2) != length(Y)) + stop("Could not reconstruct the y vector") + \} + \} + \} + type <- attr(Y, 'type') + if (!type %in% c("right", "counting", "mright", "mcounting")) + stop("Cannot handle {\textbackslash}"", type, "{\textbackslash}" type survival data") + + if (!missing(start.time)) \{ + if (!is.numeric(start.time) || length(start.time) > 1) + stop("start.time must be a single numeric value") + # Start the curves after start.time + # To do so, remove any rows of the data with an endpoint before that + # time. + if (ncol(Y)==3) \{ + keep <- Y[,2] > start.time + Y[keep,1] <- pmax(Y[keep,1], start.time) + \} + else keep <- Y[,1] > start.time + if (!any(Y[keep, ncol(Y)]==1)) + stop("start.time argument has removed all endpoints") + Y <- Y[keep,,drop=FALSE] + X <- X[keep,,drop=FALSE] + if (!is.null(offset)) offset <- offset[keep] + if (!is.null(weights)) weights <- weights[keep] + if (!is.null(strata)) strata <- strata[keep] + if (length(id) >0 ) id <- id[keep] + if (length(position) >0) position <- position[keep] + n <- nrow(Y) + \} +\end{nwchunk} + +In the above code we see id twice. The first, kept as \code{oldid} is the +identifier variable for subjects in the original data set, and is needed +whenever it contained subjects with more than one row. +The second is the user variable of this call, and is used to define multiple +rows for a new subject. The latter usage should be rare but we need to +allow for it. + +If a variable is deemed redundant the \code{coxph} routine will have set its +coefficient to NA as a marker. +We want to ignore that coefficient: treating it as a zero has the +desired effect. +Another special case is a null model, having either ~1 or only an offset +on the right hand side. In that case we create a dummy covariate to +allow the rest of the code to work without special if/else. +The last special case is a model with a sparse frailty term. We treat +the frailty coefficients as 0 variance (in essence as an offset). +The frailty is removed from the model variables but kept in the risk score. +This isn't statistically very defensible, but it is backwards compatatble. %' +A non-sparse frailty does not need special code and works out like any +other variable. + +Center the risk scores by subtracting $ \overline x \hat\beta$ from each. +The reason for this is to avoid huge values when calculating $\exp(X\beta)$; +this would happen if someone had a variable with a mean of 1000 and a +variance of 1. +Any constant can be subtracted, mathematically the results are identical as long +as the same values are subtracted from the old and new $X$ data. +The mean is used because it is handy, we just need to get $X\beta$ in the +neighborhood of zero. + +\begin{nwchunk} +\nwhyp{survfit.coxph-setup2c2}{survfit.coxph-setup2c}{survfit.coxph-setup2c1}{survfit.coxph-setup2c3}= + if (length(object$means) ==0) \{ # a model with only an offset term + # Give it a dummy X so the rest of the code goes through + # (This case is really rare) + # se.fit <- FALSE + X <- matrix(0., nrow=n, ncol=1) + if (is.null(offset)) offset <- rep(0, n) + xcenter <- mean(offset) + coef <- 0.0 + varmat <- matrix(0.0, 1, 1) + risk <- rep(exp(offset- mean(offset)), length=n) + \} + else \{ + varmat <- object$var + beta <- ifelse(is.na(object$coefficients), 0, object$coefficients) + if (is.null(offset)) xcenter <- sum(object$means * beta) + else xcenter <- sum(object$means * beta)+ mean(offset) + if (!is.null(object$frail)) \{ + keep <- !grepl("frailty(", dimnames(X)[[2]], fixed=TRUE) + X <- X[,keep, drop=F] + \} + + if (is.null(offset)) risk <- c(exp(X%*% beta - xcenter)) + else risk <- c(exp(X%*% beta + offset - xcenter)) + \} +\end{nwchunk} + +The \code{risk} vector and \code{x} matrix come from the original data, and are +the raw data for the survival curve and its variance. +We also need the risk score $\exp(X\beta)$ for the target subject(s). +\begin{itemize} + \item For predictions with time-dependent covariates the user will have + either included an \code{id} statement (newer style) or specified the + \code{individual=TRUE} option. If the latter, then \code{newdata} is + presumed to contain only a single indivual represented by multiple + rows. If the former then the \code{id} variable marks separate individuals. + In either case we need to retrieve + the covariates, strata, and repsonse from the new data set. + \item For ordinary predictions only the covariates are needed. + \item If newdata is not present we assume that this is the ordinary case, and + use the value of \code{object\$means} as the default covariate set. This is + not ideal statistically since many users view this as an + ``average'' survival curve, which it is not. +\end{itemize} + +When grabbing [newdata] we want to use model.frame processing, both to +handle missing values correctly and, perhaps more importantly, to correctly +map any factor variables between the original fit and the new data. (The +new data will often have only one of the original levels represented.) +Also, we want to correctly handle data-dependent nonlinear terms such as +ns and pspline. +However, the simple call found in predict.lm, say, +\code{model.frame(Terms, data=newdata, ..} isn't used here +for a few reasons. +The first is a decision on our part that the user should not have +to include unused terms in the newdata: sometimes we don't need the +response and sometimes we do. +Second, if there are strata, the user may or may not +have included strata variables in their data set and we need to +act accordingly. +The third is that we might have an \code{id} statement in this +call, which is another variable to be fetched. +At one time we dealt with cluster() terms in the formula, but the coxph +routine has already removed those for us. +Finally, note that there is no ability to use sparse frailties and newdata together; +it is a hard case and so rare as to not be worth it. + +First, remove unnecessary terms from the orginal model formula. +If \code{individual} is false then the repsonse variable can go. + +The dataClasses and predvars attributes, if present, have elements +in the same order as the first dimension of the ``factors'' attribute +of the terms. +Subscripting the terms argument does not preserve dataClasses or +predvars, however. Use the pre and post subscripting factors attribute +to determine what elements of them to keep. +The predvars component is a call objects with one element for each +term in the formula, so y ~ age + ns(height) would lead to a predvars +of length 4, element 1 is the call itself, 2 would be y, etc. +The dataClasses object is a simple list. + +\begin{nwchunk} +\nwhyp{survfit.coxph-setup32}{survfit.coxph-setup3}{survfit.coxph-setup31}{survfit.coxph-setup33}= + if (missing(newdata)) \{ + # If the model has interactions, print out a long warning message. + # People may hate it, but I don't see another way to stamp out these + # bad curves without backwards-incompatability. + # I probably should complain about factors too (but never in a strata + # or cluster term). + if (any(attr(Terms, "order") > 1) ) + warning("the model contains interactions; the default curve based on columm means of the X matrix is almost certainly not useful. Consider adding a newdata argument.") + + if (length(object$means)) \{ + mf2 <- as.list(object$means) #create a dummy newdata + names(mf2) <- names(object$coefficients) + mf2 <- as.data.frame(mf2) + x2 <- matrix(object$means, 1) + \} + else \{ # nothing but an offset + mf2 <- data.frame(X=0) + x2 <- 0 + \} + offset2 <- 0 + found.strata <- FALSE + \} + else \{ + if (!is.null(object$frail)) + stop("Newdata cannot be used when a model has frailty terms") + + Terms2 <- Terms + if (!individual) Terms2 <- delete.response(Terms) + \nwhypf{survfit.coxph-newdata21}{survfit.coxph-newdata2}{survfit.coxph-newdata22} + \} +\end{nwchunk} + +For backwards compatability, I allow someone to give an ordinary vector +instead of a data frame (when only one curve is required). In this case +I also need to verify that the elements have a name. +Then turn it into a data frame, like it should have been from the beginning. +(Documentation of this ability has been suppressed, however. I'm hoping +people forget it ever existed.) +\begin{nwchunk} +\nwhyp{survfit.coxph-newdata22}{survfit.coxph-newdata2}{survfit.coxph-newdata21}{survfit.coxph-newdata23}= + if (is.vector(newdata, "numeric")) \{ + if (individual) stop("newdata must be a data frame") + if (is.null(names(newdata))) \{ + stop("Newdata argument must be a data frame") + \} + newdata <- data.frame(as.list(newdata), stringsAsFactors=FALSE) + \} +\end{nwchunk} + +Finally get my new model frame mf2. +We allow the +user to leave out any strata() variables if they so desire, +\emph{if} there are no strata by covariate interactions. + +How does one check if the strata variables are or are not available in +the call? +My first attempt at this was to wrap the call in a try() construct and +see if it failed. This doesn't work. +\begin{itemize} + \item What if there is no strata variable in newdata, but they do have, + by bad luck, a variable of the same name in their main directory? + \item It would seem like changing the environment to NULL would be wise, + so that we don't find variables anywhere but in the data argument, + a sort of sandboxing. Not wise: you then won't find functions like ``log''. + \item We don't dare modify the environment of the formula at all. + It is needed for the sneaky caller who uses his own function + inside the formula, 'mycosine' say, and that function can only be + found if we retain the environment. +\end{itemize} +One way out of this is to evaluate each of the strata terms +(there can be more than one) one at a time, in an environment that knows +nothing except "list" and a fake definition of "strata", and newdata. +Variables that are part of the global environment won't be found. +I even watch out for the case of either "strata" or "list" is the name of +the stratification variable, which causes my fake strata function to +return a function when said variable is not in newdata. The +variable found.strata is true if ALL the strata are found, set it to +false if any are missing. + +\begin{nwchunk} +\nwhypb{survfit.coxph-newdata23}{survfit.coxph-newdata2}{survfit.coxph-newdata22}= + if (has.strata) \{ + found.strata <- TRUE + tempenv <- new.env(, parent=emptyenv()) + assign("strata", function(..., na.group, shortlabel, sep) + list(...), envir=tempenv) + assign("list", list, envir=tempenv) + for (svar in stangle$vars) \{ + temp <- try(eval(parse(text=svar), newdata, tempenv), + silent=TRUE) + if (!is.list(temp) || + any(unlist(lapply(temp, class))== "function")) + found.strata <- FALSE + \} + + if (!found.strata) \{ + ss <- untangle.specials(Terms2, "strata") + Terms2 <- Terms2[-ss$terms] + \} + \} + + tcall <- Call[c(1, match(c('id', "na.action"), + names(Call), nomatch=0))] + tcall$data <- newdata + tcall$formula <- Terms2 + tcall$xlev <- object$xlevels[match(attr(Terms2,'term.labels'), + names(object$xlevels), nomatch=0)] + tcall[[1L]] <- quote(stats::model.frame) + mf2 <- eval(tcall) +\end{nwchunk} + +Now, finally, extract the \code{x2} matrix from the just-created frame. +\begin{nwchunk} +\nwhyp{survfit.coxph-setup33}{survfit.coxph-setup3}{survfit.coxph-setup32}{survfit.coxph-setup34}= + if (has.strata && found.strata) \{ #pull them off + temp <- untangle.specials(Terms2, 'strata') + strata2 <- strata(mf2[temp$vars], shortlabel=TRUE) + strata2 <- factor(strata2, levels=levels(strata)) + if (any(is.na(strata2))) + stop("New data set has strata levels not found in the original") + # An expression like age:strata(sex) will have temp$vars= "strata(sex)" + # and temp$terms = integer(0). This does not work as a subscript + if (length(temp$terms) >0) Terms2 <- Terms2[-temp$terms] + \} + else strata2 <- factor(rep(0, nrow(mf2))) + + if (!robust) cluster <- NULL + if (individual) \{ + if (missing(newdata)) + stop("The newdata argument must be present when individual=TRUE") + if (!missid) \{ #grab the id variable + id2 <- model.extract(mf2, "id") + if (is.null(id2)) stop("id=NULL is an invalid argument") + \} + else id2 <- rep(1, nrow(mf2)) + + x2 <- model.matrix(Terms2, mf2)[,-1, drop=FALSE] #no intercept + if (length(x2)==0) stop("Individual survival but no variables") + + offset2 <- model.offset(mf2) + if (length(offset2) ==0) offset2 <- 0 + + y2 <- model.extract(mf2, 'response') + if (attr(y2,'type') != type) + stop("Survival type of newdata does not match the fitted model") + if (attr(y2, "type") != "counting") + stop("Individual=TRUE is only valid for counting process data") + y2 <- y2[,1:2, drop=F] #throw away status, it's never used + \} + else if (missing(newdata)) \{ + if (has.strata && strata.interaction) + stop ("Models with strata by covariate interaction terms require newdata") + offset2 <- 0 + if (length(object$means)) \{ + x2 <- matrix(object$means, nrow=1, ncol=ncol(X)) + \} else \{ + # model with only an offset and no new data: very rare case + x2 <- matrix(0.0, nrow=1, ncol=1) # make a dummy x2 + \} + \} else \{ + offset2 <- model.offset(mf2) + if (length(offset2) >0) offset2 <- offset2 + else offset2 <- 0 + x2 <- model.matrix(Terms2, mf2)[,-1, drop=FALSE] #no intercept + \} +\end{nwchunk} + +\begin{nwchunk} +\nwhypb{survfit.coxph-result2}{survfit.coxph-result}{survfit.coxph-result1}= + if (individual) \{ + result <- coxsurv.fit(ctype, stype, se.fit, varmat, cluster, + Y, X, weights, risk, position, strata, oldid, + y2, x2, risk2, strata2, id2) + \} + else \{ + result <- coxsurv.fit(ctype, stype, se.fit, varmat, cluster, + Y, X, weights, risk, position, strata, oldid, + y2, x2, risk2) + if (has.strata && found.strata) \{ + if (is.matrix(result$surv)) \{ + \nwhypf{newstrata-fixup1}{newstrata-fixup}{newstrata-fixup2} + \} + \} + \} +\end{nwchunk} + +The final bit of work. If the newdata arg contained strata then the +user should not get a matrix of survival curves containing +every newdata obs * strata combination, but rather a vector +of curves, each one with the appropriate strata. +It was faster to compute them all, however, than to use the individual=T +logic. So now pick off the bits we want. +The names of the curves will be the rownames of the newdata arg, +if they exist. +\begin{nwchunk} +\nwhypb{newstrata-fixup2}{newstrata-fixup}{newstrata-fixup1}= + nr <- nrow(result$surv) #a vector if newdata had only 1 row + indx1 <- split(1:nr, rep(1:length(result$strata), result$strata)) + rows <- indx1[as.numeric(strata2)] #the rows for each curve + + indx2 <- unlist(rows) #index for time, n.risk, n.event, n.censor + indx3 <- as.integer(strata2) #index for n and strata + + for(i in 2:length(rows)) rows[[i]] <- rows[[i]]+ (i-1)*nr #linear subscript + indx4 <- unlist(rows) #index for surv and std.err + temp <- result$strata[indx3] + names(temp) <- row.names(mf2) + new <- list(n = result$n[indx3], + time= result$time[indx2], + n.risk= result$n.risk[indx2], + n.event=result$n.event[indx2], + n.censor=result$n.censor[indx2], + strata = temp, + surv= result$surv[indx4], + cumhaz = result$cumhaz[indx4]) + if (se.fit) new$std.err <- result$std.err[indx4] + result <- new +\end{nwchunk} + +Finally, the last (somewhat boring) part of the code. +First, if given the argument \code{censor=FALSE} we need to +remove all the time points from the output at which there +was only censoring activity. This action is mostly for +backwards compatability with older releases that never +returned censoring times. +Second, add +in the variance and the confidence intervals to the result. +The code is nearly identical to that in survfitKM. +\begin{nwchunk} +\nwhypb{survfit.coxph-finish2}{survfit.coxph-finish}{survfit.coxph-finish1}= + if (!censor) \{ + kfun <- function(x, keep)\{ if (is.matrix(x)) x[keep,,drop=F] + else if (length(x)==length(keep)) x[keep] + else x\} + keep <- (result$n.event > 0) + if (!is.null(result$strata)) \{ + temp <- factor(rep(names(result$strata), result$strata), + levels=names(result$strata)) + result$strata <- c(table(temp[keep])) + \} + result <- lapply(result, kfun, keep) + \} + result$logse = TRUE # this will migrate further in + + if (se.fit && conf.type != "none") \{ + ci <- survfit_confint(result$surv, result$std.err, logse=result$logse, + conf.type, conf.int) + result <- c(result, list(lower=ci$lower, upper=ci$upper, + conf.type=conf.type, conf.int=conf.int)) + \} + + if (!missing(start.time)) result$start.time <- start.time + + result$call <- Call + class(result) <- c('survfitcox', 'survfit') + result +\end{nwchunk} +% +% Second part of coxsurv.Rnw, broken in two to make it easier for me +% to work with emacs. +Now, we're ready to do the main compuation. %' +The code has gone through multiple iteration as options and complexity +increased. + +Computations are separate for each strata, and each strata will +have a different number of time points in the result. +Thus we can't preallocate a matrix. Instead we generate an empty list, %' +one per strata, and then populate it with the survival curves. +At the end we unlist the individual components one by one. +This is memory efficient, the number +of curves is usually small enough that the "for" loop is no great +cost, and it's easier to see what's going on than C code. +The computational exception is a model with thousands of strata, e.g., a matched +logistic, but in that case survival curves are useless. +(That won't stop some users from trying it though.) + +First, compute the baseline survival curves for each strata. If the strata +was a factor produce output curves in that order, otherwise in sorted order. +This fitting routine was set out as a separate function for the sake of the rms +package. They want to utilize the computation, but have a diffferent +process to create the x and y data. +\begin{nwchunk} +\nwhypn{coxsurvfit}= + coxsurv.fit <- function(ctype, stype, se.fit, varmat, cluster, + y, x, wt, risk, position, strata, oldid, + y2, x2, risk2, strata2, id2, unlist=TRUE) \{ + + if (missing(strata) || length(strata)==0) strata <- rep(0L, nrow(y)) + + if (is.factor(strata)) ustrata <- levels(strata) + else ustrata <- sort(unique(strata)) + nstrata <- length(ustrata) + survlist <- vector('list', nstrata) + names(survlist) <- ustrata + survtype <- if (stype==1) 1 else ctype+1 + vartype <- survtype + if (is.null(wt)) wt <- rep(1.0, nrow(y)) + if (is.null(strata)) strata <- rep(1L, nrow(y)) + for (i in 1:nstrata) \{ + indx <- which(strata== ustrata[i]) + survlist[[i]] <- agsurv(y[indx,,drop=F], x[indx,,drop=F], + wt[indx], risk[indx], + survtype, vartype) + \} + \nwhypf{survfit.coxph-compute1}{survfit.coxph-compute}{survfit.coxph-compute2} + + if (unlist) \{ + if (length(result)==1) \{ # the no strata case + if (se.fit) + result[[1]][c("n", "time", "n.risk", "n.event", "n.censor", + "surv", "cumhaz", "std.err")] + else result[[1]][c("n", "time", "n.risk", "n.event", "n.censor", + "surv", "cumhaz")] + \} + else \{ + \nwhypf{survfit.coxph-unlist1}{survfit.coxph-unlist}{survfit.coxph-unlist2} + \} + \} + else \{ + names(result) <- ustrata + result + \} + \} +\end{nwchunk} + +In an ordinary survival curve object with multiple strata, as produced by +\code{survfitKM}, the time, survival and etc components are each a +single vector that contains the results for strata 1, followed by +strata 2, \ldots. The strata compontent is a vector of integers, one +per strata, that gives the number of elements belonging to each stratum. +The reason is that each strata will have a different number of observations, +so that a matrix form was not viable, and the underlying C routines were +not capable of handling lists (the code predates the .Call function by +a decade). +The underlying computation of \code{survfitcoxph.fit} naturally creates the list +form, we unlist it to \code{survfit} form as our last action unless the +caller requests otherwise. + +\begin{nwchunk} +\nwhypb{survfit.coxph-unlist2}{survfit.coxph-unlist}{survfit.coxph-unlist1}= + temp <-list(n = unlist(lapply(result, function(x) x$n), + use.names=FALSE), + time= unlist(lapply(result, function(x) x$time), + use.names=FALSE), + n.risk= unlist(lapply(result, function(x) x$n.risk), + use.names=FALSE), + n.event= unlist(lapply(result, function(x) x$n.event), + use.names=FALSE), + n.censor=unlist(lapply(result, function(x) x$n.censor), + use.names=FALSE), + strata = sapply(result, function(x) length(x$time))) + names(temp$strata) <- names(result) + + if ((missing(id2) || is.null(id2)) && nrow(x2)>1) \{ + temp$surv <- t(matrix(unlist(lapply(result, + function(x) t(x$surv)), use.names=FALSE), + nrow= nrow(x2))) + dimnames(temp$surv) <- list(NULL, row.names(x2)) + temp$cumhaz <- t(matrix(unlist(lapply(result, + function(x) t(x$cumhaz)), use.names=FALSE), + nrow= nrow(x2))) + if (se.fit) + temp$std.err <- t(matrix(unlist(lapply(result, + function(x) t(x$std.err)), use.names=FALSE), + nrow= nrow(x2))) + \} + else \{ + temp$surv <- unlist(lapply(result, function(x) x$surv), + use.names=FALSE) + temp$cumhaz <- unlist(lapply(result, function(x) x$cumhaz), + use.names=FALSE) + if (se.fit) + temp$std.err <- unlist(lapply(result, + function(x) x$std.err), use.names=FALSE) + \} + temp +\end{nwchunk} + +For \code{individual=FALSE} we have a second dimension, namely each of the +target covariate sets (if there are multiples). Each of these generates +a unique set of survival and variance(survival) values, but all of the +same size since each uses all the strata. The final output structure in +this case has single vectors for the time, number of events, number censored, +and number at risk values since they are common to all the curves, and a +matrix of +survival and variance estimates, one column for each of the +distinct target values. +If $\Lambda_0$ is the baseline cumulative hazard from the +above calculation, then $r_i \Lambda_0$ is the cumulative +hazard for the $i$th new risk score $r_i$. +The variance has two parts, the first of which is $r_i^2 H_1$ where +$H_1$ is returned from the \code{agsurv} routine, and the second is +\begin{align*} + H_2(t) =& d'(t) V d(t) \\ %' + d(t) = \int_0^t [z- \overline x(s)] d\Lambda(s) +\end{align*} +$V$ is the variance matrix for $\beta$ from the fitted Cox +model, and $d(t)$ is the distance between the +target covariate $z$ and the mean of the original data, +summed up over the interval from 0 to $t$. +Essentially the variance in $\hat \beta$ has a larger influence +when prediction is far from the mean. +The function below takes the basic curve from the list and multiplies +it out to matrix form. +\begin{nwchunk} +\nwhyp{survfit.coxph-compute2}{survfit.coxph-compute}{survfit.coxph-compute1}{survfit.coxph-compute3}= + expand <- function(fit, x2, varmat, se.fit) \{ + if (survtype==1) + surv <- cumprod(fit$surv) + else surv <- exp(-fit$cumhaz) + + if (is.matrix(x2) && nrow(x2) >1) \{ #more than 1 row in newdata + fit$surv <- outer(surv, risk2, '^') + dimnames(fit$surv) <- list(NULL, row.names(x2)) + if (se.fit) \{ + varh <- matrix(0., nrow=length(fit$varhaz), ncol=nrow(x2)) + for (i in 1:nrow(x2)) \{ + dt <- outer(fit$cumhaz, x2[i,], '*') - fit$xbar + varh[,i] <- (cumsum(fit$varhaz) + rowSums((dt %*% varmat)* dt))* + risk2[i]^2 + \} + fit$std.err <- sqrt(varh) + \} + fit$cumhaz <- outer(fit$cumhaz, risk2, '*') + \} + else \{ + fit$surv <- surv^risk2 + if (se.fit) \{ + dt <- outer(fit$cumhaz, c(x2)) - fit$xbar + varh <- (cumsum(fit$varhaz) + rowSums((dt %*% varmat)* dt)) * + risk2^2 + fit$std.err <- sqrt(varh) + \} + fit$cumhaz <- fit$cumhaz * risk2 + \} + fit + \} +\end{nwchunk} +In the lines just above: I have a matrix \code{dt} with one row per death +time and one column per variable. For each row $d_i$ separately we +want the quadratic form $d_i V d_i'$. The first matrix product can %' +be done for all rows at once: found in the inner parenthesis. +Ordinary (not matrix) multiplication followed by rowsums does the rest +in one fell swoop. + +Now, if \code{id2} is missing we can simply apply the \code{expand} function +to each strata. +For the case with \code{id2} not missing, we create a single survival +curve for each unique id (subject). +A subject will spend blocks of time with different covariate sets, +sometimes even jumping between strata. Retrieve each one and save it into +a list, and then sew them together end to end. +The \code{n} component is the number of observations in the strata --- but this +subject might visit several. We report the first one they were in for +printout. +The \code{time} component will be cumulative on this subject's scale. %' +Counting this is a bit trickier than I first thought. Say that the +subject's first interval goes from 1 to 10, with observed time points in +that interval at 2, 5, and 7, and a second interval from 12 to 20 with +observed time points in the data of 15 and 18. On the subject's time +scale things happen at days 1, 4, 6, 12 and 15. The deltas saved below +are 2-1, 5-2, 7-5, 3+ 14-12, 17-14. Note the 3+ part, kept +in the \code{timeforward} variable. +Why all this ``adding up'' nuisance? If the subject spent time in two +strata, the second one might be on an internal time scale of `time since +entering the strata'. The two intervals in newdata could be 0--10 followed +by 0--20. Time for the subject can't go backwards though: the change %` +between internal/external time scales is a bit like following someone who +was stepping back and forth over the international date line. + +In the code the \code{indx} variable points to the set of times that the +subject was present, for this row of the new data. Note the $>$ on +one end and $\le$ on the other. If someone's interval 1 was 0--10 and +interval 2 was 10--20, and there happened to be a jump in the baseline +survival curve at exactly time 10 (someone else died), +that jump is counted only in the first interval. +\begin{nwchunk} +\nwhypb{survfit.coxph-compute3}{survfit.coxph-compute}{survfit.coxph-compute2}= + if (missing(id2) || is.null(id2)) + result <- lapply(survlist, expand, x2, varmat, se.fit) + else \{ + onecurve <- function(slist, x2, y2, strata2, risk2, se.fit) \{ + ntarget <- nrow(x2) #number of different time intervals + surv <- vector('list', ntarget) + n.event <- n.risk <- n.censor <- varh1 <- varh2 <- time <- surv + hazard <- vector('list', ntarget) + stemp <- as.integer(strata2) + timeforward <- 0 + for (i in 1:ntarget) \{ + slist <- survlist[[stemp[i]]] + indx <- which(slist$time > y2[i,1] & slist$time <= y2[i,2]) + if (length(indx)==0) \{ + timeforward <- timeforward + y2[i,2] - y2[i,1] + # No deaths or censors in user interval. Possible + # user error, but not uncommon at the tail of the curve. + \} + else \{ + time[[i]] <- diff(c(y2[i,1], slist$time[indx])) #time increments + time[[i]][1] <- time[[i]][1] + timeforward + timeforward <- y2[i,2] - max(slist$time[indx]) + + hazard[[i]] <- slist$hazard[indx]*risk2[i] + if (survtype==1) surv[[i]] <- slist$surv[indx]^risk2[i] + + n.event[[i]] <- slist$n.event[indx] + n.risk[[i]] <- slist$n.risk[indx] + n.censor[[i]]<- slist$n.censor[indx] + dt <- outer(slist$cumhaz[indx], x2[i,]) - slist$xbar[indx,,drop=F] + varh1[[i]] <- slist$varhaz[indx] *risk2[i]^2 + varh2[[i]] <- rowSums((dt %*% varmat)* dt) * risk2[i]^2 + \} + \} + + cumhaz <- cumsum(unlist(hazard)) + if (survtype==1) surv <- cumprod(unlist(surv)) #increments (K-M) + else surv <- exp(-cumhaz) + + if (se.fit) + list(n=as.vector(table(strata)[stemp[1]]), + time=cumsum(unlist(time)), + n.risk = unlist(n.risk), + n.event= unlist(n.event), + n.censor= unlist(n.censor), + surv = surv, + cumhaz= cumhaz, + std.err = sqrt(cumsum(unlist(varh1)) + unlist(varh2))) + else list(n=as.vector(table(strata)[stemp[1]]), + time=cumsum(unlist(time)), + n.risk = unlist(n.risk), + n.event= unlist(n.event), + n.censor= unlist(n.censor), + surv = surv, + cumhaz= cumhaz) + \} + + if (all(id2 ==id2[1])) \{ + result <- list(onecurve(survlist, x2, y2, strata2, risk2, se.fit)) + \} + else \{ + uid <- unique(id2) + result <- vector('list', length=length(uid)) + for (i in 1:length(uid)) \{ + indx <- which(id2==uid[i]) + result[[i]] <- onecurve(survlist, x2[indx,,drop=FALSE], + y2[indx,,drop=FALSE], + strata2[indx], risk2[indx], se.fit) + \} + names(result) <- uid + \} + \} +\end{nwchunk} + +Next is the code for the \code{agsurv} function, which actually does the work. +The estimates of survival are the Kalbfleisch-Prentice (KP), Breslow, and +Efron. Each has an increment at each unique death time. +First a bit of notation: +$Y_i(t)$ is 1 if bservation $i$ is ``at risk'' at time $t$ and 0 otherwise. +For a simple surivival (\code{ncol(y)==2}) a subject is at risk until the +time of censoring or death (first column of \code{y}). +For (start, stop] data (\code{ncol(y)==3}) a subject becomes a +part of the risk set at start+0 and stays through stop. +$dN_i(t)$ will be 1 if subject $i$ had an event at time $t$. +The risk score for each subject is $r_i = \exp(X_i \beta)$. + +The Breslow increment at time $t$ is $\sum w_i dN_i(t) / \sum w_i r_i Y_i(t)$, +the number of events at time $t$ over the number at risk at time $t$. +The final survival is \code{exp(-cumsum(increment))}. + +The Kalbfleish-Prentice increment is a multiplicative term $z$ +which is the solution to the equation +$$ +\sum w_i r_i Y_i(t) = \sum dN_i(t) w_i \frac{r_i}{1- z(t)^{r_i}} +$$ +The left hand side is the weighted number at risk at time $t$, the +right hand side is a sum over the tied events at that time. +If there is only one event the equation has a closed form solution. +If not, and knowing the solution must lie between 0 and 1, we do +35 steps of bisection to get a solution within 1e-8. +An alternative is to use the -log of the Breslow estimate as a starting +estimate, which is faster but requires a more sophisticated iteration logic. +The final curve is $\prod_t z(t)^{r_c}$ where $r_c$ is the risk score +for the target subject. + +The Efron estimate can be viewed as a modified Breslow estimate under the +assumption that tied deaths are not really tied -- we just don't know the %' +order. So if there are 3 subjects who die at some time $t$ we will have +three psuedo-terms for $t$, $t+\epsilon$, and $t+ 2\epsilon$. All 3 subjects +are present for the denominator of the first term, 2/3 of each for the second, +and 1/3 for the third terms denominator. All contribute 1/3 of the weight +to each numerator (1/3 chance they were the one to die there). The formulas +will require $\sum w_i dN_i(t)$, $\sum w_ir_i dN_i(t)$, and $\sum w_i X_i +dN_i(t)$, i.e., the sums only over the deaths. + +For simple survival data the risk sum $\sum w_i r_i Y_i(t)$ for all +the unique death times $t$ is fast to compute as a cumulative sum, starting +at the longest followup time and summing towards the shortest. +There are two algorithms for (start, stop] data. +\begin{itemize} + \item Do a separate sum at each death time. The problem is for very large + data sets. For each death time the selection \code{(start=t)} + is $O(n)$ and can take more time then all the remaining calculations + together. + \item Use the difference of two cumulative sums, one ordered by start time + and one ordered by stop time. This is $O(2n)$ for the intial sums. The + problem here is potential round off error if the sums get large. + This issue is mostly precluded by subtracting means first, and avoiding + intervals that don't overlap an event time. +\end{itemize} +We compute the extended number still at risk --- all whose stop time +is $\ge$ each unique death time --- in the vector \code{xin}. From +this we have to subtract all those who haven't actually entered yet %' +found in \code{xout}. Remember that (3,20] enters at time 3+. +The total at risk at any time is the difference between them. +Output is only for the +stop times; a call to approx is used to reconcile the two time sets. +The \code{irisk} vector is for the printout, it is a sum of weighted counts +rather than weighted risk scores. +\begin{nwchunk} +\nwhypf{agsurv1}{agsurv}{agsurv2}= + agsurv <- function(y, x, wt, risk, survtype, vartype) \{ + nvar <- ncol(as.matrix(x)) + status <- y[,ncol(y)] + dtime <- y[,ncol(y) -1] + death <- (status==1) + + time <- sort(unique(dtime)) + nevent <- as.vector(rowsum(wt*death, dtime)) + ncens <- as.vector(rowsum(wt*(!death), dtime)) + wrisk <- wt*risk + rcumsum <- function(x) rev(cumsum(rev(x))) # sum from last to first + nrisk <- rcumsum(rowsum(wrisk, dtime)) + irisk <- rcumsum(rowsum(wt, dtime)) + if (ncol(y) ==2) \{ + temp2 <- rowsum(wrisk*x, dtime) + xsum <- apply(temp2, 2, rcumsum) + \} + else \{ + delta <- min(diff(time))/2 + etime <- c(sort(unique(y[,1])), max(y[,1])+delta) #unique entry times + indx <- approx(etime, 1:length(etime), time, method='constant', + rule=2, f=1)$y + esum <- rcumsum(rowsum(wrisk, y[,1])) #not yet entered + nrisk <- nrisk - c(esum,0)[indx] + irisk <- irisk - c(rcumsum(rowsum(wt, y[,1])),0)[indx] + xout <- apply(rowsum(wrisk*x, y[,1]), 2, rcumsum) #not yet entered + xin <- apply(rowsum(wrisk*x, dtime), 2, rcumsum) # dtime or alive + xsum <- xin - (rbind(xout,0))[indx,,drop=F] + \} + + ndeath <- rowsum(status, dtime) #unweighted death count +\end{nwchunk} + +The KP estimate requires a short C routine to do the iteration +efficiently, and the Efron estimate needs a second C routine to +efficiently compute the partial sums. +\begin{nwchunk} +\nwhypb{agsurv2}{agsurv}{agsurv1}= + ntime <- length(time) + if (survtype ==1) \{ #Kalbfleisch-Prentice + indx <- (which(status==1))[order(dtime[status==1])] #deaths + km <- .C(Cagsurv4, + as.integer(ndeath), + as.double(risk[indx]), + as.double(wt[indx]), + as.integer(ntime), + as.double(nrisk), + inc = double(ntime)) + \} + + if (survtype==3 || vartype==3) \{ # Efron approx + xsum2 <- rowsum((wrisk*death) *x, dtime) + erisk <- rowsum(wrisk*death, dtime) #risk score sums at each death + tsum <- .C(Cagsurv5, + as.integer(length(nevent)), + as.integer(nvar), + as.integer(ndeath), + as.double(nrisk), + as.double(erisk), + as.double(xsum), + as.double(xsum2), + sum1 = double(length(nevent)), + sum2 = double(length(nevent)), + xbar = matrix(0., length(nevent), nvar)) + \} + haz <- switch(survtype, + nevent/nrisk, + nevent/nrisk, + nevent* tsum$sum1) + varhaz <- switch(vartype, + nevent/(nrisk * + ifelse(nevent>=nrisk, nrisk, nrisk-nevent)), + nevent/nrisk^2, + nevent* tsum$sum2) + xbar <- switch(vartype, + (xsum/nrisk)*haz, + (xsum/nrisk)*haz, + nevent * tsum$xbar) + + result <- list(n= nrow(y), time=time, n.event=nevent, n.risk=irisk, + n.censor=ncens, hazard=haz, + cumhaz=cumsum(haz), varhaz=varhaz, ndeath=ndeath, + xbar=apply(matrix(xbar, ncol=nvar),2, cumsum)) + if (survtype==1) result$surv <- km$inc + result + \} +\end{nwchunk} + +The arguments to this function are the number of unique times n, which is +the length of the vectors ndeath (number at each time), denom, and the +returned vector km. The risk and wt vectors contain individual values for +the subjects with an event. Their length will be equal to sum(ndeath). +\begin{nwchunk} +\nwhypn{agsurv4}= + #include "survS.h" + #include "survproto.h" + + void agsurv4(Sint *ndeath, double *risk, double *wt, + Sint *sn, double *denom, double *km) + \{ + int i,j,k, l; + int n; /* number of unique death times */ + double sumt, guess, inc; + + n = *sn; + j =0; + for (i=0; i0) + baselinecoef[2, index] <- exp(object$coef[ctemp[index]]) + \} + \} else phbase <- rep(FALSE, nrow(object$cmap)) + + # process options, set up Y and the model frame, deal with start.time + \nwhypb{survfit.coxph-setup15}{survfit.coxph-setup1}{survfit.coxph-setup14} + \nwhypb{survfit.coxph-setup23}{survfit.coxph-setup2}{survfit.coxph-setup22} + istate <- model.extract(mf, "istate") + if (!missing(start.time)) \{ + if (!is.numeric(start.time) || length(start.time) !=1 + || !is.finite(start.time)) + stop("start.time must be a single numeric value") + toss <- which(Y[,ncol(Y)-1] <= start.time) + if (length(toss)) \{ + n <- nrow(Y) + if (length(toss)==n) stop("start.time has removed all observations") + Y <- Y[-toss,,drop=FALSE] + X <- X[-toss,,drop=FALSE] + weights <- weights[-toss] + oldid <- oldid[-toss] + istate <- istate[-toss] + \} + \} + + # expansion of the X matrix with stacker, set up shared hazards + \nwhypf{survfit.coxphms-setupa1}{survfit.coxphms-setupa}{survfit.coxphms-setupa2} + + # risk scores, mf2, and x2 + \nwhypb{survfit.coxph-setup2c3}{survfit.coxph-setup2c}{survfit.coxph-setup2c2} + \nwhypb{survfit.coxph-setup34}{survfit.coxph-setup3}{survfit.coxph-setup33} + + \nwhypf{survfit.coxphms-setup3b1}{survfit.coxphms-setup3b}{survfit.coxphms-setup3b2} + \nwhypf{survfit.coxphms-result1}{survfit.coxphms-result}{survfit.coxphms-result2} + + cifit$call <- Call + class(cifit) <- c("survfitms", "survfit") + cifit + \} +\end{nwchunk} +The third line \code{as.name('survfit')} causes the printout to say +`survfit' instead of `survfit.coxph'. %' + +Notice that setup is almost completely shared with survival for single state +models. The major change is that we use survfitCI (non-Cox) to do all the +legwork wrt the tabulation values (number at risk, etc.), +while for the computation proper it is easier to make use of the same +expanded data set that coxph used for a multi-state fit. + +\begin{nwchunk} +\nwhypb{survfit.coxphms-setupa2}{survfit.coxphms-setupa}{survfit.coxphms-setupa1}= + # Rebuild istate using the survcheck routine + mcheck <- survcheck2(Y, oldid, istate) + transitions <- mcheck$transitions + if (is.null(istate)) istate <- mcheck$istate + if (!identical(object$states, mcheck$states)) + stop("failed to rebuild the data set") + + # Let the survfitCI routine do the work of creating the + # overall counts (n.risk, etc). The rest of this code then + # replaces the surv and hazard components. + if (missing(start.time)) start.time <- min(Y[,2], 0) + # If the data has absorbing states (ones with no transitions out), then + # remove those rows first since they won't be in the final output. + t2 <- transitions[, is.na(match(colnames(transitions), "(censored)")), drop=FALSE] + absorb <- row.names(t2)[rowSums(t2)==0] + + if (is.null(weights)) weights <- rep(1.0, nrow(Y)) + if (is.null(strata)) tempstrat <- rep(1L, nrow(Y)) + else tempstrat <- strata + + if (length(absorb)) droprow <- istate %in% absorb else droprow <- FALSE + + # Let survfitCI fill in the n, number at risk, number of events, etc. portions + # We will replace the pstate and cumhaz estimate with correct ones. + if (any(droprow)) \{ + j <- which(!droprow) + cifit <- survfitCI(as.factor(tempstrat[j]), Y[j,], weights[j], + id =oldid[j], istate= istate[j], + se.fit=FALSE, start.time=start.time, p0=p0) + \} + else cifit <- survfitCI(as.factor(tempstrat), Y, weights, + id= oldid, istate = istate, se.fit=FALSE, + start.time=start.time, p0=p0) + + # For computing the actual estimates it is easier to work with an + # expanded data set. + # Replicate actions found in the coxph-multi-X chunk, + cluster <- model.extract(mf, "cluster") + xstack <- stacker(object$cmap, object$stratum_map, as.integer(istate), X, Y, + as.integer(strata), + states= object$states) + if (length(position) >0) + position <- position[xstack$rindex] # id was required by coxph + X <- xstack$X + Y <- xstack$Y + strata <- strata[xstack$rindex] # strat in the model, other than transitions + transition <- xstack$transition + istrat <- xstack$strata + if (length(offset)) offset <- offset[xstack$rindex] + if (length(weights)) weights <- weights[xstack$rindex] + if (length(cluster)) cluster <- cluster[xstack$rindex] + oldid <- oldid[xstack$rindex] + if (robust & length(cluster)==0) cluster <- oldid +\end{nwchunk} + +The survfit.coxph-setup3 chunk, shared with single state Cox models, has created +an mf2 model frame and an x2 matrix. +For multi-state, we ignore any strata variables in mf2. +Create a matrix of risk scores, number of subjects by number of transitions. +Different transitions often have different coefficients, so there is a risk +score vector per transition. + +\begin{nwchunk} +\nwhypb{survfit.coxphms-setup3b2}{survfit.coxphms-setup3b}{survfit.coxphms-setup3b1}= + if (has.strata && !is.null(mf2[[stangle$vars]]))\{ + mf2 <- mf2[is.na(match(names(mf2), stangle$vars))] + mf2 <- unique(mf2) + x2 <- unique(x2) + \} + temp <- coef(object, matrix=TRUE)[!phbase,,drop=FALSE] # ignore missing coefs + risk2 <- exp(x2 %*% ifelse(is.na(temp), 0, temp) - xcenter) +\end{nwchunk} + +At this point we have several parts to keep straight. The data set has been +expanded into a new X and Y. +\begin{itemize} + \item \code{strata} contains any strata that were specified by the user + in the original fit. We do completely separate computations for each + stratum: the time scale starts over, nrisk, etc. Each has a separate + call to the multihaz function. + \item \code{transtion} contains the transition to which each observation + applies + \item \code{istrat} comes from the xstack routine, and marks each + strata * basline hazard combination. + \item \code{baselinecoef} maps from baseline hazards to transitions. It + has one column per transition, which hazard it points to, and a + multiplier. Most multipliers will be 1. + \item \code{hfill} is constructed below. It contains the row/column to which + each column of baselinecoef is mapped, within the H matrix used to compute + P(state). +\end{itemize} +The coxph routine fits all strata and transitions at once, since the loglik is +a sum over strata. This routine does each stratum separately. + +\begin{nwchunk} +\nwhypb{survfit.coxphms-result2}{survfit.coxphms-result}{survfit.coxphms-result1}= + # make the expansion map. + # The H matrices we will need are nstate by nstate, at each time, with + # elements that are non-zero only for observed transtions. + states <- object$states + nstate <- length(states) + notcens <- (colnames(object$transitions) != "(censored)") + trmat <- object$transitions[, notcens, drop=FALSE] + from <- row(trmat)[trmat>0] + from <- match(rownames(trmat), states)[from] # actual row of H + to <- col(trmat)[trmat>0] + to <- match(colnames(trmat), states)[to] # actual col of H + hfill <- cbind(from, to) + + if (individual) \{ + stop("time dependent survival curves are not supported for multistate") + \} + ny <- ncol(Y) + if (is.null(strata)) \{ + fit <- multihaz(Y, X, position, weights, risk, istrat, ctype, stype, + baselinecoef, hfill, x2, risk2, varmat, nstate, se.fit, + cifit$p0, cifit$time) + cifit$pstate <- fit$pstate + cifit$cumhaz <- fit$cumhaz + \} + else \{ + if (is.factor(strata)) ustrata <- levels(strata) + else ustrata <- sort(unique(strata)) + nstrata <- length(cifit$strata) + itemp <- rep(1:nstrata, cifit$strata) + timelist <- split(cifit$time, itemp) + ustrata <- names(cifit$strata) + tfit <- vector("list", nstrata) + for (i in 1:nstrata) \{ + indx <- which(strata== ustrata[i]) # divides the data + tfit[[i]] <- multihaz(Y[indx,,drop=F], X[indx,,drop=F], + position[indx], weights[indx], risk[indx], + istrat[indx], ctype, stype, baselinecoef, hfill, + x2, risk2, varmat, nstate, se.fit, + cifit$p0[i,], timelist[[i]]) + \} + + # do.call(rbind) doesn't work for arrays, it loses a dimension + ntime <- length(cifit$time) + cifit$pstate <- array(0., dim=c(ntime, dim(tfit[[1]]$pstate)[2:3])) + cifit$cumhaz <- array(0., dim=c(ntime, dim(tfit[[1]]$cumhaz)[2:3])) + rtemp <- split(seq(along=cifit$time), itemp) + for (i in 1:nstrata) \{ + cifit$pstate[rtemp[[i]],,] <- tfit[[i]]$pstate + cifit$cumhaz[rtemp[[i]],,] <- tfit[[i]]$cumhaz + \} + \} + cifit$newdata <- mf2 +\end{nwchunk} + +Finally, a routine that does all the actual work. +\begin{itemize} + \item The first 5 variables are for the data set that the Cox model was built + on: y, x, position, risk score, istrat. + Position is a flag for each obs. Is it the first of a connected string + such as (10, 12) (12,19) (19,21), the last of such a string, both, + or neither. 1*first + 2*last. This affects whether an obs is labeled + as censored or not, nothing else. + \item x2 and risk2 are the covariates and risk scores for the predicted + values. These do not involve any ph(a:b) coefficients. + \item baselinecoef and hfill control mapping from fittes hazards to + transitions and probabilities + \item p0 will be NULL if the user did not specifiy it. + \item vmat is only needed for standard errors + \item utime is the set of time points desired +\end{itemize} + + +\begin{nwchunk} +\nwhypb{survfit.coxphms2}{survfit.coxphms}{survfit.coxphms1}= + # Compute the hazard and survival functions + multihaz <- function(y, x, position, weight, risk, istrat, ctype, stype, + bcoef, hfill, x2, risk2, vmat, nstate, se.fit, p0, utime) \{ + if (ncol(y) ==2) \{ + sort1 <- seq.int(0, nrow(y)-1L) # sort order for a constant + y <- cbind(-1.0, y) # add a start.time column, -1 in case + # there is an event at time 0 + \} + else sort1 <- order(istrat, y[,1]) -1L + sort2 <- order(istrat, y[,2]) -1L + ntime <- length(utime) + + # this returns all of the counts we might desire. + storage.mode(weight) <- "double" #failsafe + # for Surv(time, status), position is 2 (last) for all obs + if (length(position)==0) position <- rep(2L, nrow(y)) + + fit <- .Call(Ccoxsurv2, utime, y, weight, sort1, sort2, position, + istrat, x, risk) + cn <- fit$count # 1-3 = at risk, 4-6 = events, 7-8 = censored events + # 9-10 = censored, 11-12 = Efron, 13-15 = entry + + if (ctype ==1) \{ + denom1 <- ifelse(cn[,4]==0, 1, cn[,3]) + denom2 <- ifelse(cn[,4]==0, 1, cn[,3]^2) + \} else \{ + denom1 <- ifelse(cn[,4]==0, 1, cn[,11]) + denom2 <- ifelse(cn[,4]==0, 1, cn[,12]) + \} + + temp <- matrix(cn[,5] / denom1, ncol = fit$ntrans) + hazard <- temp[,bcoef[1,]] * rep(bcoef[2,], each=nrow(temp)) + if (se.fit) \{ + temp <- matrix(cn[,5] / denom2, ncol = fit$ntrans) + varhaz <- temp[,bcoef[1,]] * rep(bcoef[2,]^2, each=nrow(temp)) + \} + + # Expand the result, one "hazard set" for each row of x2 + nx2 <- nrow(x2) + h2 <- array(0, dim=c(nrow(hazard), nx2, ncol(hazard))) + if (se.fit) v2 <- h2 + S <- double(nstate) # survival at the current time + S2 <- array(0, dim=c(nrow(hazard), nx2, nstate)) + + H <- matrix(0, nstate, nstate) + if (stype==2) \{ + H[hfill] <- colMeans(hazard) + diag(H) <- diag(H) -rowSums(H) + esetup <- survexpmsetup(H) + \} + + for (i in 1:nx2) \{ + h2[,i,] <- apply(hazard %*% diag(risk2[i,]), 2, cumsum) + if (se.fit) \{ + d1 <- fit$xbar - rep(x[i,], each=nrow(fit$xbar)) + d2 <- apply(d1*hazard, 2, cumsum) + d3 <- rowSums((d2%*% vmat) * d2) + # v2[jj,] <- (apply(varhaz[jj,],2, cumsum) + d3) * (risk2[i])^2 + \} + + S <- p0 + for (j in 1:ntime) \{ + H[,] <- 0.0 + H[hfill] <- hazard[j,] *risk2[i,] + if (stype==1) \{ + diag(H) <- pmax(0, 1.0 - rowSums(H)) + S <- as.vector(S %*% H) # don't keep any names + \} + else \{ + diag(H) <- 0.0 - rowSums(H) + #S <- as.vector(S %*% expm(H)) # dgeMatrix issue + S <- as.vector(S %*% survexpm(H, 1, esetup)) + \} + S2[j,i,] <- S + \} + \} + rval <- list(time=utime, xgrp=rep(1:nx2, each=nrow(hazard)), + pstate=S2, cumhaz=h2) + if (se.fit) rval$varhaz <- v2 + rval + \} +\end{nwchunk} + + +\section{The Fine-Gray model} +For competing risks with ending states 1, 2, \ldots $k$, +the Fine-Gray approach turns these into a set of simple 2-state +Cox models: +\begin{itemize} + \item (not yet in state 1) $\longrightarrow$ state 1 + \item (not yet in state 2) $\longrightarrow$ state 2 + \item \ldots +\end{itemize} +Each of these is now a simple Cox model, assuming that we are willing +to make a proportional hazards assumption. +There is one added complication: +when estimating the first model, one wants to use the data set that +would have occured if the subjects being followed for state 1 had +not had an artificial censoring, that is, had continued to be followed +for event 1 even after event 2 occured. +Sometimes this can be filled in directly, e.g., if we knew the enrollment +dates for each subject along with the date that follow-up for the +study was terminated, and there was no lost to follow-up (only administrative +censoring.) +An example is the mgus2 data set, where follow-up for death continued +after the occurence of plasma cell malignancy. +In practice what is done is to estimate the overall censoring distribution and +give subjects artificial follow-up. + +The function below creates a data set that can then be used with coxph. +\begin{nwchunk} +\nwhypn{finegray}= + finegray <- function(formula, data, weights, subset, na.action= na.pass, + etype, prefix="fg", count="", id, timefix=TRUE) \{ + Call <- match.call() + indx <- match(c("formula", "data", "weights", "subset", "id"), + names(Call), nomatch=0) + if (indx[1] ==0) stop("A formula argument is required") + temp <- Call[c(1,indx)] # only keep the arguments we wanted + temp$na.action <- na.action + temp[[1L]] <- quote(stats::model.frame) # change the function called + + special <- c("strata", "cluster") + temp$formula <- if(missing(data)) terms(formula, special) + else terms(formula, special, data=data) + + mf <- eval(temp, parent.frame()) + if (nrow(mf) ==0) stop("No (non-missing) observations") + Terms <- terms(mf) + + Y <- model.extract(mf, "response") + if (!inherits(Y, "Surv")) stop("Response must be a survival object") + type <- attr(Y, "type") + if (type!='mright' && type!='mcounting') + stop("Fine-Gray model requires a multi-state survival") + nY <- ncol(Y) + states <- attr(Y, "states") + if (timefix) Y <- aeqSurv(Y) + + strats <- attr(Terms, "specials")$strata + if (length(strats)) \{ + stemp <- untangle.specials(Terms, 'strata', 1) + if (length(stemp$vars)==1) strata <- mf[[stemp$vars]] + else strata <- survival::strata(mf[,stemp$vars], shortlabel=TRUE) + istrat <- as.numeric(strata) + mf[stemp$vars] <- NULL + \} + else istrat <- rep(1, nrow(mf)) + + id <- model.extract(mf, "id") + if (!is.null(id)) mf["(id)"] <- NULL # don't leave it in result + user.weights <- model.weights(mf) + if (is.null(user.weights)) user.weights <- rep(1.0, nrow(mf)) + + cluster<- attr(Terms, "specials")$cluster + if (length(cluster)) \{ + stop("a cluster() term is not valid") + \} + + # If there is start-stop data, then there needs to be an id + # also check that this is indeed a competing risks form of data. + # Mark the first and last obs of each subject, as we need it later. + # Observations may not be in time order within a subject + delay <- FALSE # is there delayed entry? + if (type=="mcounting") \{ + if (is.null(id)) stop("(start, stop] data requires a subject id") + else \{ + index <- order(id, Y[,2]) # by time within id + sorty <- Y[index,] + first <- which(!duplicated(id[index])) + last <- c(first[-1] -1, length(id)) + if (any(sorty[-last, 3] != 0)) + stop("a subject has a transition before their last time point") + delta <- c(sorty[-1,1], 0) - sorty[,2] + if (any(delta[-last] !=0)) + stop("a subject has gaps in time") + if (any(Y[first,1] > min(Y[,2]))) delay <- TRUE + temp1 <- temp2 <- rep(FALSE, nrow(mf)) + temp1[index[first]] <- TRUE + temp2[index[last]] <- TRUE + first <- temp1 #used later + last <- temp2 + \} + \} else last <- rep(TRUE, nrow(mf)) + + if (missing(etype)) enum <- 1 #generate a data set for which endpoint? + else \{ + index <- match(etype, states) + if (any(is.na(index))) + stop ("etype argument has a state that is not in the data") + enum <- index[1] + if (length(index) > 1) warning("only the first endpoint was used") + \} + + # make sure count, if present is syntactically valid + if (!missing(count)) count <- make.names(count) else count <- NULL + oname <- paste0(prefix, c("start", "stop", "status", "wt")) + + \nwhypf{finegray-censor1}{finegray-censor}{finegray-censor2} + \nwhypf{finegray-build1}{finegray-build}{finegray-build2} + \} +\end{nwchunk} + +The censoring and truncation distributions are +\begin{align*} + G(t) &= \prod_{s \le t} \left(1 - \frac{c(s)}{r_c(s)} \right ) \\ + H(t) &= \prod_{s > t} \left(1 - \frac{e(s)}{r_e(s)} \right ) +\end{align*} +where $c(t)$ is the number of subjects censored at time $t$, $e(t)$ is the +number who enter at time $t$, and $r$ is the size of the relevant risk set. +These are equations 5 and 6 of Geskus (Biometrics 2011). +Note that both $G$ and $H$ are right continuous functions. +For tied times the assumption is that event $<$ censor $<$ entry. +For $G$ we use a modified Kapan-Meier where any events at censoring time $t$ are +removed from the risk set just before time $t$. +To avoid issues with times that are nearly identical (but not quite) we first +convert to an integer time scale, and then move events backwards by .2. +Since this is a competing risks data set any non-censored observation for a +subject is their last, so this time shift does not goof up the alignment +of start, stop data. +For the truncation distribution it is the subjects with times +at or before time $t$ that +are in the risk set $r_e(t)$ for truncation at (or before) $t$. +$H$ can be calculated using an ordinary KM on the reverse time scale. + +When there is (start,stop) data and hence multiple observations per subject, +calculation of $G$ needs use a status that is 1 only for the \emph{last} row +row of a censored subject. + +\begin{nwchunk} +\nwhyp{finegray-censor2}{finegray-censor}{finegray-censor1}{finegray-censor3}= + if (ncol(Y) ==2) \{ + temp <- min(Y[,1], na.rm=TRUE) + if (temp >0) zero <- 0 + else zero <- 2*temp -1 # a value less than any observed y + Y <- cbind(zero, Y) # add a start column + \} + + utime <- sort(unique(c(Y[,1:2]))) # all the unique times + newtime <- matrix(findInterval(Y[,1:2], utime), ncol=2) + status <- Y[,3] + + newtime[status !=0, 2] <- newtime[status !=0,2] - .2 + Gsurv <- survfit(Surv(newtime[,1], newtime[,2], last & status==0) ~ istrat, + se.fit=FALSE) +\end{nwchunk} + +The calculation for $H$ is also done on the integer scale. +Otherwise we will someday be clobbered by times that differ only in +round off error. The only nuisance is the status variable, which is +1 for the first row of each subject, since the data set may not +be in sorted order. The offset of .2 used above is not needed, but due +to the underlying integer scale it doesn't harm anything either. +Reversal of the time scale leads to a left continuous function which +we fix up later. +\begin{nwchunk} +\nwhypb{finegray-censor3}{finegray-censor}{finegray-censor2}= + if (delay) + Hsurv <- survfit(Surv(-newtime[,2], -newtime[,1], first) ~ istrat, + se.fit =FALSE) +\end{nwchunk} + +Consider the following data set: +\begin{itemize} + \item Events of type 1 at times 1, 4, 5, 10 + \item Events of type 2 at times 2, 5, 8 + \item Censors at times 3, 4, 4, 6, 8, 9, 12 +\end{itemize} +The censoring distribution will have the following shape: +\begin{center} + \begin{tabular}{rcccccc} + interval& (0,3]& (3,4] & (4,6] & (6,8] & (8,12] & 12+\\ + C(t) & 1 &11/12 & (11/12)(8/10) & (11/15)(5/6)& (11/15)(5/6)(3/4)& + 0 \\ + & 1.0000 & .9167 & .7333 & .6111 & .4583 + \end{tabular} + \end{center} +Notice that the event at time 4 is not counted in the risk set at time 4, +so the jump is 8/10 rather than 8/11. +Likewise at time 8 the risk set has 4 instead of 5: censors occur after deaths. + +When creating the data set for event type 1, subjects who have an event of +type 2 get extended out using this censoring distribution. The event at +time 2, for instance, appears as a censored observation with time dependent +weights of $G(t)$. The type 2 event at time 5 has weight 1 up through time 5, +then weights of $G(t)/C(5)$ for the remainder. +This means a weight of 1 over (5,6], 5/6 over (6,8], (5/6)(3/4) over (9,12] +and etc. + +Though there are 6 unique censoring intervals, +in the created data set for event type 1 we only need to know case +weights at times 1, 4, 5, and 10; the information from the (4,6] and (6,8] +intervals will never be used. +To create a minimal sized data set we can leave those intervals out. +$G(t)$ only drops to zero if the largest time(s) are censored observations, so +by definition no events lie in an interval with $G(t)=0$. + +If there is delayed entry, then the set of intervals is larger due to a merge +with the jumps in Hsurv. +The truncation distribution Hsurv ($H$) will become 0 at the first entry time; +it is a left continuous function whereas Gsurv ($G$) is right continuous. +We can slide $H$ one point to the left and merge them at the jump points. + +\begin{nwchunk} +\nwhypb{finegray-build2}{finegray-build}{finegray-build1}= + status <- Y[, 3] + + # Do computations separately for each stratum + stratfun <- function(i) \{ + keep <- (istrat ==i) + times <- sort(unique(Y[keep & status == enum, 2])) #unique event times + if (length(times)==0) return(NULL) #no events in this stratum + tdata <- mf[keep, -1, drop=FALSE] + maxtime <- max(Y[keep, 2]) + + Gtemp <- Gsurv[i] + if (delay) \{ + Htemp <- Hsurv[i] + dtime <- rev(-Htemp$time[Htemp$n.event > 0]) + dprob <- c(rev(Htemp$surv[Htemp$n.event > 0])[-1], 1) + ctime <- Gtemp$time[Gtemp$n.event > 0] + cprob <- c(1, Gtemp$surv[Gtemp$n.event > 0]) + temp <- sort(unique(c(dtime, ctime))) # these will all be integers + index1 <- findInterval(temp, dtime) + index2 <- findInterval(temp, ctime) + ctime <- utime[temp] + cprob <- dprob[index1] * cprob[index2+1] # G(t)H(t), eq 11 Geskus + \} + else \{ + ctime <- utime[Gtemp$time[Gtemp$n.event > 0]] + cprob <- Gtemp$surv[Gtemp$n.event > 0] + \} + + ct2 <- c(ctime, maxtime) + cp2 <- c(1.0, cprob) + index <- findInterval(times, ct2, left.open=TRUE) + index <- sort(unique(index)) # the intervals that were actually seen + # times before the first ctime get index 0, those between 1 and 2 get 1 + ckeep <- rep(FALSE, length(ct2)) + ckeep[index] <- TRUE + expand <- (Y[keep, 3] !=0 & Y[keep,3] != enum & last[keep]) #which rows to expand + split <- .Call(Cfinegray, Y[keep,1], Y[keep,2], ct2, cp2, expand, + c(TRUE, ckeep)) + tdata <- tdata[split$row,,drop=FALSE] + tstat <- ifelse((status[keep])[split$row]== enum, 1, 0) + + + tdata[[oname[1]]] <- split$start + tdata[[oname[2]]] <- split$end + tdata[[oname[3]]] <- tstat + tdata[[oname[4]]] <- split$wt * user.weights[split$row] + if (!is.null(count)) tdata[[count]] <- split$add + tdata + \} + + if (max(istrat) ==1) result <- stratfun(1) + else \{ + tlist <- lapply(1:max(istrat), stratfun) + result <- do.call("rbind", tlist) + \} + + rownames(result) <- NULL #remove all the odd labels that R adds + attr(result, "event") <- states[enum] + result +\end{nwchunk} +\subsection{The predict method} +The \code{predict.coxph} function +produces various types of predicted values from a Cox model. +The arguments are +\begin{description} + \item [object] The result of a call to \code{coxph}. + \item [newdata] Optionally, a new data set for which prediction is + desired. If this is absent predictions are for the observations used + fit the model. + \item[type] The type of prediction + \begin{itemize} + \item lp = the linear predictor for each observation + \item risk = the risk score $exp(lp)$ for each observation + \item expected = the expected number of events + \item survival = predicted survival = exp(-expected) + \item terms = a matrix with one row per subject and one column for + each term in the model. + \end{itemize} + \item[se.fit] Whether or not to return standard errors of the predictions. + \item[na.action] What to do with missing values \emph{if} there is new + data. + \item[terms] The terms that are desired. This option is almost never used, + so rarely in fact that it's hard to justify keeping it. + \item[collapse] An optional vector of subject identifiers, over which to + sum or `collapse' the results + \item[reference] the reference context for centering the results + \item[\ldots] All predict methods need to have a \ldots argument; we make + no use of it however. +\end{description} + +%\subsection{Setup} +The first task of the routine is to reconsruct necessary data elements +that were not saved as a part of the \code{coxph} fit. +We will need the following components: +\begin{itemize} + \item for type=`expected' residuals we need the orignal survival y. This %'` + is saved in coxph objects by default so will only need to be fetched in + the highly unusual case that a user specfied + \code{y=FALSE} in the orignal call. + \item for any call with either newdata, standard errors, or type='terms' + the original $X$ matrix, weights, strata, and offset. + When checking for the existence of a saved $X$ matrix we can't %' + use \code{object\$x} + since that will also match the \code{xlevels} component. + \item the new data matrix, if any +\end{itemize} + +\begin{nwchunk} +\nwhypn{predict.coxph}= + predict.coxph <- function(object, newdata, + type=c("lp", "risk", "expected", "terms", "survival"), + se.fit=FALSE, na.action=na.pass, + terms=names(object$assign), collapse, + reference=c("strata", "sample", "zero"), ...) \{ + \nwhypf{pcoxph-init1}{pcoxph-init}{pcoxph-init2} + \nwhypf{pcoxph-getdata1}{pcoxph-getdata}{pcoxph-getdata2} + if (type=="expected") \{ + \nwhypf{pcoxph-expected1}{pcoxph-expected}{pcoxph-expected2} + \} + else \{ + \nwhypf{pcoxph-simple1}{pcoxph-simple}{pcoxph-simple2} + \nwhypf{pcoxph-terms1}{pcoxph-terms}{pcoxph-terms2} + \} + \nwhypf{pcoxph-finish1}{pcoxph-finish}{pcoxph-finish2} + \} +\end{nwchunk} + +We start of course with basic argument checking. +Then retrieve the model parameters: does it have a strata +statement, offset, etc. +The \code{Terms2} object is a model statement without the strata or cluster terms, +appropriate for recreating the matrix of covariates $X$. +For type=expected the response variable needs to be kept, if not we remove +it as well since the user's newdata might not contain one. %' +The type= survival is treated the same as type expected. +\begin{nwchunk} +\nwhypb{pcoxph-init2}{pcoxph-init}{pcoxph-init1}= + if (!inherits(object, 'coxph')) + stop("Primary argument much be a coxph object") + + Call <- match.call() + type <-match.arg(type) + if (type=="survival") \{ + survival <- TRUE + type <- "expected" #this is to stop lots of "or" statements + \} + else survival <- FALSE + + n <- object$n + Terms <- object$terms + + if (!missing(terms)) \{ + if (is.numeric(terms)) \{ + if (any(terms != floor(terms) | + terms > length(object$assign) | + terms <1)) stop("Invalid terms argument") + \} + else if (any(is.na(match(terms, names(object$assign))))) + stop("a name given in the terms argument not found in the model") + \} + + # I will never need the cluster argument, if present delete it. + # Terms2 are terms I need for the newdata (if present), y is only + # needed there if type == 'expected' + if (length(attr(Terms, 'specials')$cluster)) \{ + temp <- untangle.specials(Terms, 'cluster', 1) + Terms <- object$terms[-temp$terms] + \} + else Terms <- object$terms + + if (type != 'expected') Terms2 <- delete.response(Terms) + else Terms2 <- Terms + + has.strata <- !is.null(attr(Terms, 'specials')$strata) + has.offset <- !is.null(attr(Terms, 'offset')) + has.weights <- any(names(object$call) == 'weights') + na.action.used <- object$na.action + n <- length(object$residuals) + + if (missing(reference) && type=="terms") reference <- "sample" + else reference <- match.arg(reference) +\end{nwchunk} + +The next task of the routine is to reconsruct necessary data elements +that were not saved as a part of the \code{coxph} fit. +We will need the following components: +\begin{itemize} + \item for type=`expected' residuals we need the orignal survival y. This %'` + is saved in coxph objects by default so will only need to be fetched in + the highly unusual case that a user specfied \code{y=FALSE} in the orignal + call. We also need the strata in this case. Grabbing it is the same + amount of work as grabbing X, so gets lumped with that case in the + code. + \item for any call with either standard errors, reference strata, + or type=`terms' + the original $X$ matrix, weights, strata, and offset. + When checking for the existence of a saved $X$ matrix we can't %' + use \code{object\$x} + since that will also match the \code{xlevels} component. + \item the new data matrix, if present, along with offset and strata. +\end{itemize} +For the case that none of the above are needed, we can use the +\code{linear.predictors} component of the fit. The variable \code{use.x} signals +this case, which takes up almost none of the code but is common in usage. + +The check below that nrow(mf)==n is to avoid data sets that change under our +feet. A fit was based on data set ``x'', and when we reconstruct the data +frame it is a different size! This means someone changed the data between +the model fit and the extraction of residuals. +One other non-obvious case is that coxph treats the model \code{age:strata(grp)} +as though it were \code{age:strata(grp) + strata(grp)}. +The untangle.specials function will return +\code{vars= strata(grp), terms=integer(0)}; the first shows a strata to extract +and the second that there is nothing to remove from the terms structure. + +\begin{nwchunk} +\nwhyp{pcoxph-getdata2}{pcoxph-getdata}{pcoxph-getdata1}{pcoxph-getdata3}= + have.mf <- FALSE + if (type == "expected") \{ + y <- object[['y']] + if (is.null(y)) \{ # very rare case + mf <- stats::model.frame(object) + y <- model.extract(mf, 'response') + have.mf <- TRUE #for the logic a few lines below, avoid double work + \} + \} + + # This will be needed if there are strata, and is cheap to compute + strat.term <- untangle.specials(Terms, "strata") + if (se.fit || type=='terms' || (!missing(newdata) && type=="expected") || + (has.strata && (reference=="strata") || type=="expected")) \{ + use.x <- TRUE + if (is.null(object[['x']]) || has.weights || has.offset || + (has.strata && is.null(object$strata))) \{ + # I need the original model frame + if (!have.mf) mf <- stats::model.frame(object) + if (nrow(mf) != n) + stop("Data is not the same size as it was in the original fit") + x <- model.matrix(object, data=mf) + if (has.strata) \{ + if (!is.null(object$strata)) oldstrat <- object$strata + else \{ + if (length(strat.term$vars)==1) oldstrat <- mf[[strat.term$vars]] + else oldstrat <- strata(mf[,strat.term$vars], shortlabel=TRUE) + \} + \} + else oldstrat <- rep(0L, n) + + weights <- model.weights(mf) + if (is.null(weights)) weights <- rep(1.0, n) + offset <- model.offset(mf) + if (is.null(offset)) offset <- 0 + \} + else \{ + x <- object[['x']] + if (has.strata) oldstrat <- object$strata + else oldstrat <- rep(0L, n) + weights <- rep(1.,n) + offset <- 0 + \} + \} + else \{ + # I won't need strata in this case either + if (has.strata) \{ + stemp <- untangle.specials(Terms, 'strata', 1) + Terms2 <- Terms2[-stemp$terms] + has.strata <- FALSE #remaining routine never needs to look + \} + oldstrat <- rep(0L, n) + offset <- 0 + use.x <- FALSE + \} +\end{nwchunk} + +Now grab data from the new data set. We want to use model.frame +processing, in order to correctly expand factors and such. +We don't need weights, however, and don't want to make the user +include them in their new dataset. Thus we build the call up +the way it is done in coxph itself, but only keeping the newdata +argument. Note that terms2 may have fewer variables than the +original model: no cluster and if type!= expected no response. +If the original model had a strata, but newdata does not, we need to +remove the strata from xlev to stop a spurious warning message. + +\begin{nwchunk} +\nwhypb{pcoxph-getdata3}{pcoxph-getdata}{pcoxph-getdata2}= + if (!missing(newdata)) \{ + use.x <- TRUE #we do use an X matrix later + tcall <- Call[c(1, match(c("newdata", "collapse"), names(Call), nomatch=0))] + names(tcall)[2] <- 'data' #rename newdata to data + tcall$formula <- Terms2 #version with no response + tcall$na.action <- na.action #always present, since there is a default + tcall[[1L]] <- quote(stats::model.frame) # change the function called + + if (!is.null(attr(Terms, "specials")$strata) && !has.strata) \{ + temp.lev <- object$xlevels + temp.lev[[strat.term$vars]] <- NULL + tcall$xlev <- temp.lev + \} + else tcall$xlev <- object$xlevels + mf2 <- eval(tcall, parent.frame()) + + collapse <- model.extract(mf2, "collapse") + n2 <- nrow(mf2) + + if (has.strata) \{ + if (length(strat.term$vars)==1) newstrat <- mf2[[strat.term$vars]] + else newstrat <- strata(mf2[,strat.term$vars], shortlabel=TRUE) + if (any(is.na(match(newstrat, oldstrat)))) + stop("New data has a strata not found in the original model") + else newstrat <- factor(newstrat, levels=levels(oldstrat)) #give it all + if (length(strat.term$terms)) + newx <- model.matrix(Terms2[-strat.term$terms], mf2, + contr=object$contrasts)[,-1,drop=FALSE] + else newx <- model.matrix(Terms2, mf2, + contr=object$contrasts)[,-1,drop=FALSE] + \} + else \{ + newx <- model.matrix(Terms2, mf2, + contr=object$contrasts)[,-1,drop=FALSE] + newstrat <- rep(0L, nrow(mf2)) + \} + + newoffset <- model.offset(mf2) + if (is.null(newoffset)) newoffset <- 0 + if (type== 'expected') \{ + newy <- model.response(mf2) + if (attr(newy, 'type') != attr(y, 'type')) + stop("New data has a different survival type than the model") + \} + na.action.used <- attr(mf2, 'na.action') + \} + else n2 <- n +\end{nwchunk} + +%\subsection{Expected hazard} +When we do not need standard errors the computation of expected +hazard is very simple since +the martingale residual is defined as status - expected. The 0/1 +status is saved as the last column of $y$. +\begin{nwchunk} +\nwhypb{pcoxph-expected2}{pcoxph-expected}{pcoxph-expected1}= + if (missing(newdata)) + pred <- y[,ncol(y)] - object$residuals + if (!missing(newdata) || se.fit) \{ + \nwhypf{pcoxph-expected21}{pcoxph-expected2}{pcoxph-expected22} + \} + if (survival) \{ #it actually was type= survival, do one more step + if (se.fit) se <- se * exp(-pred) + pred <- exp(-pred) # probablility of being in state 0 + \} +\end{nwchunk} + +The more general case makes use of the [agsurv] routine to calculate +a survival curve for each strata. The routine is defined in the +section on individual Cox survival curves. The code here closely matches +that. The routine only returns values at the death times, so we need +approx to get a complete index. + +One non-obvious, but careful choice is to use the residuals for the predicted +value instead of the compuation below, whenever operating on the original +data set. This is a consequence of the Efron approx. When someone in +a new data set has exactly the same time as one of the death times in the +original data set, the code below implicitly makes them the ``last'' death +in the set of tied times. +The Efron approx puts a tie somewhere in the middle of the pack. This is +way too hard to work out in the code below, but thankfully the original +Cox model already did it. However, it does mean that a different answer will +arise if you set newdata = the original coxph data set. +Standard errors have the same issue, but 1. they are hardly used and 2. the +original coxph doesn't do that calculation. So we do what's easiest. + +\begin{nwchunk} +\nwhypb{pcoxph-expected22}{pcoxph-expected2}{pcoxph-expected21}= + ustrata <- unique(oldstrat) + risk <- exp(object$linear.predictors) + x <- x - rep(object$means, each=nrow(x)) #subtract from each column + if (missing(newdata)) #se.fit must be true + se <- double(n) + else \{ + pred <- se <- double(nrow(mf2)) + newx <- newx - rep(object$means, each=nrow(newx)) + newrisk <- c(exp(newx %*% object$coef) + newoffset) + \} + + survtype<- ifelse(object$method=='efron', 3,2) + for (i in ustrata) \{ + indx <- which(oldstrat == i) + afit <- agsurv(y[indx,,drop=F], x[indx,,drop=F], + weights[indx], risk[indx], + survtype, survtype) + afit.n <- length(afit$time) + if (missing(newdata)) \{ + # In this case we need se.fit, nothing else + j1 <- approx(afit$time, 1:afit.n, y[indx,1], method='constant', + f=0, yleft=0, yright=afit.n)$y + chaz <- c(0, afit$cumhaz)[j1 +1] + varh <- c(0, cumsum(afit$varhaz))[j1 +1] + xbar <- rbind(0, afit$xbar)[j1+1,,drop=F] + if (ncol(y)==2) \{ + dt <- (chaz * x[indx,]) - xbar + se[indx] <- sqrt(varh + rowSums((dt %*% object$var) *dt)) * + risk[indx] + \} + else \{ + j2 <- approx(afit$time, 1:afit.n, y[indx,2], method='constant', + f=0, yleft=0, yright=afit.n)$y + chaz2 <- c(0, afit$cumhaz)[j2 +1] + varh2 <- c(0, cumsum(afit$varhaz))[j2 +1] + xbar2 <- rbind(0, afit$xbar)[j2+1,,drop=F] + dt <- (chaz * x[indx,]) - xbar + v1 <- varh + rowSums((dt %*% object$var) *dt) + dt2 <- (chaz2 * x[indx,]) - xbar2 + v2 <- varh2 + rowSums((dt2 %*% object$var) *dt2) + se[indx] <- sqrt(v2-v1)* risk[indx] + \} + \} + + else \{ + #there is new data + use.x <- TRUE + indx2 <- which(newstrat == i) + j1 <- approx(afit$time, 1:afit.n, newy[indx2,1], + method='constant', f=0, yleft=0, yright=afit.n)$y + chaz <-c(0, afit$cumhaz)[j1+1] + pred[indx2] <- chaz * newrisk[indx2] + if (se.fit) \{ + varh <- c(0, cumsum(afit$varhaz))[j1+1] + xbar <- rbind(0, afit$xbar)[j1+1,,drop=F] + \} + if (ncol(y)==2) \{ + if (se.fit) \{ + dt <- (chaz * newx[indx2,]) - xbar + se[indx2] <- sqrt(varh + rowSums((dt %*% object$var) *dt)) * + newrisk[indx2] + \} + \} + else \{ + j2 <- approx(afit$time, 1:afit.n, newy[indx2,2], + method='constant', f=0, yleft=0, yright=afit.n)$y + chaz2 <- approx(-afit$time, afit$cumhaz, -newy[indx2,2], + method="constant", rule=2, f=0)$y + chaz2 <-c(0, afit$cumhaz)[j2+1] + pred[indx2] <- (chaz2 - chaz) * newrisk[indx2] + + if (se.fit) \{ + varh2 <- c(0, cumsum(afit$varhaz))[j1+1] + xbar2 <- rbind(0, afit$xbar)[j1+1,,drop=F] + dt <- (chaz * newx[indx2,]) - xbar + dt2 <- (chaz2 * newx[indx2,]) - xbar2 + + v2 <- varh2 + rowSums((dt2 %*% object$var) *dt2) + v1 <- varh + rowSums((dt %*% object$var) *dt) + se[indx2] <- sqrt(v2-v1)* risk[indx2] + \} + \} + \} + \} +\end{nwchunk} + +%\subsection{Linear predictor, risk, and terms} +For these three options what is returned is a \emph{relative} prediction +which compares each observation to the average for the data set. +Partly this is practical. Say for instance that a treatment covariate +was coded as 0=control and 1=treatment. +If the model were refit using a new coding of 3=control 4=treatment, the +results of the Cox model would be exactly the same with respect to +coefficients, variance, tests, etc. +The raw linear predictor $X\beta$ however would change, increasing by +a value of $3\beta$. +The relative predictor +\begin{equation} + \eta_i = X_i\beta - (1/n)\sum_j X_j\beta + \label{eq:eta} +\end{equation} +will stay the same. +The second reason for doing this is that the Cox model is a +relative risks model rather than an absolute risks model, +and thus relative predictions are almost certainly what the +user was thinking of. + +When the fit was for a stratified Cox model more care is needed. +For instance assume that we had a fit that was stratified by sex with +covaritate $x$, and a second data set were created where for the +females $x$ is replaced +by $x+3$. The Cox model results will be unchanged for the two +models, but the `normalized' linear predictors $(x - \overline x)'\beta$ %` +will not be the same. +This reflects a more fundamental issue that the for a stratified +Cox model relative risks are well defined only \emph{within} a +stratum, i.e. for subject pairs that share a common baseline +hazard. +The example above is artificial, but the problem arises naturally +whenever the model includes a strata by covariate interaction. +So for a stratified Cox model the predictions should be forced to +sum to zero within each stratum, or equivalently be made relative +to the weighted mean of the stratum. +Unfortunately, this important issue was not realized until late in 2009 +when a puzzling query was sent to the author involving the results +from such an interaction. +Note that this issue did not arise with type='expected', which +has a natural scaling. + +An offset variable, if specified, is treated like any other covariate +with respect to centering. +The logic for this choice is not as compelling, but it seemed the +best that I could do. +Note that offsets play no role whatever in predicted terms, only in +the lp and risk. + +Start with the simple ones +\begin{nwchunk} +\nwhypb{pcoxph-simple2}{pcoxph-simple}{pcoxph-simple1}= + if (is.null(object$coefficients)) + coef<-numeric(0) + else \{ + # Replace any NA coefs with 0, to stop NA in the linear predictor + coef <- ifelse(is.na(object$coefficients), 0, object$coefficients) + \} + + if (missing(newdata)) \{ + offset <- offset - mean(offset) + if (has.strata && reference=="strata") \{ + # We can't use as.integer(oldstrat) as an index, if oldstrat is + # a factor variable with unrepresented levels as.integer could + # give 1,2,5 for instance. + xmeans <- rowsum(x*weights, oldstrat)/c(rowsum(weights, oldstrat)) + newx <- x - xmeans[match(oldstrat,row.names(xmeans)),] + \} + else if (use.x) \{ + if (reference == "zero") newx <- x + else newx <- x - rep(object$means, each=nrow(x)) + \} + \} + else \{ + offset <- newoffset - mean(offset) + if (has.strata && reference=="strata") \{ + xmeans <- rowsum(x*weights, oldstrat)/c(rowsum(weights, oldstrat)) + newx <- newx - xmeans[match(newstrat, row.names(xmeans)),] + \} + else if (reference!= "zero") + newx <- newx - rep(object$means, each=nrow(newx)) + \} + + if (type=='lp' || type=='risk') \{ + if (use.x) pred <- drop(newx %*% coef) + offset + else pred <- object$linear.predictors + if (se.fit) se <- sqrt(rowSums((newx %*% object$var) *newx)) + + if (type=='risk') \{ + pred <- exp(pred) + if (se.fit) se <- se * sqrt(pred) # standard Taylor series approx + \} + \} +\end{nwchunk} + +The type=terms residuals are a bit more work. +In Splus this code used the Build.terms function, which was essentially +the code from predict.lm extracted out as a separate function. +As of March 2010 (today) a check of the Splus function and the R code +for predict.lm revealed no important differences. +A lot of the bookkeeping in both is to work around any possible NA +coefficients resulting from a singularity. +The basic formula is to +\begin{enumerate} + \item If the model has an intercept, then sweep the column means + out of the X matrix. We've already done this. + \item For each term separately, get the list of coefficients that + belong to that term; call this list \code{tt}. + \item Restrict $X$, $\beta$ and $V$ (the variance matrix) to that + subset, then the linear predictor is $X\beta$ with variance + matrix $X V X'$. The standard errors are the square root of + the diagonal of this latter matrix. This can be computed, + as colSums((X %*% V) * X)). +\end{enumerate} +Note that the \code{assign} component of a coxph object is the same +as that found in Splus models (a list), most R models retain a numeric vector +which contains the same information but it is not as easily used. The first +first part of predict.lm in R rebuilds the list form as its \code{asgn} variable. +I can skip this part since it is already done. +\begin{nwchunk} +\nwhypb{pcoxph-terms2}{pcoxph-terms}{pcoxph-terms1}= + else if (type=='terms') \{ + asgn <- object$assign + nterms<-length(asgn) + pred<-matrix(ncol=nterms,nrow=NROW(newx)) + dimnames(pred) <- list(rownames(newx), names(asgn)) + if (se.fit) se <- pred + + for (i in 1:nterms) \{ + tt <- asgn[[i]] + tt <- tt[!is.na(object$coefficients[tt])] + xtt <- newx[,tt, drop=F] + pred[,i] <- xtt %*% object$coefficient[tt] + if (se.fit) + se[,i] <- sqrt(rowSums((xtt %*% object$var[tt,tt]) *xtt)) + \} + pred <- pred[,terms, drop=F] + if (se.fit) se <- se[,terms, drop=F] + + attr(pred, 'constant') <- sum(object$coefficients*object$means, na.rm=T) + \} +\end{nwchunk} + +To finish up we need to first expand out any missings in the result +based on the na.action, and optionally collapse the results within +a subject. +What should we do about the standard errors when collapse is specified? +We assume that the individual pieces are +independent and thus var(sum) = sum(variances). +The statistical justification of this is quite solid for the linear predictor, +risk and terms type of prediction due to independent increments in a martingale. +For expecteds the individual terms are positively correlated so the se will +be too small. One solution would be to refuse to return an se in this +case, but the the bias should usually be small, +and besides it would be unkind to the user. + +Prediction of type='terms' is expected to always return a matrix, or +the R termplot() function gets unhappy. +\begin{nwchunk} +\nwhypb{pcoxph-finish2}{pcoxph-finish}{pcoxph-finish1}= + if (type != 'terms') \{ + pred <- drop(pred) + if (se.fit) se <- drop(se) + \} + + if (!is.null(na.action.used)) \{ + pred <- napredict(na.action.used, pred) + if (is.matrix(pred)) n <- nrow(pred) + else n <- length(pred) + if(se.fit) se <- napredict(na.action.used, se) + \} + + if (!missing(collapse) && !is.null(collapse)) \{ + if (length(collapse) != n2) stop("Collapse vector is the wrong length") + pred <- rowsum(pred, collapse) # in R, rowsum is a matrix, always + if (se.fit) se <- sqrt(rowsum(se^2, collapse)) + if (type != 'terms') \{ + pred <- drop(pred) + if (se.fit) se <- drop(se) + \} + \} + + if (se.fit) list(fit=pred, se.fit=se) + else pred +\end{nwchunk} +\section{Concordance} +\subsection{Main routine} + The concordance statistic is the most used measure of goodness-of-fit +in survival models. +In general let $y_i$ and $x_i$ be observed and predicted data values. +A pair of obervations $i$, $j$ is considered condordant if either +$y_i > y_j, x_i > x_j$ or $y_i < y_j, x_i < x_j$. +The concordance is the fraction of concordant pairs. +For a Cox model remember that the predicted survival $\hat y$ is longer if +the risk score $X\beta$ is lower, so we have to flip the definition and +count ``discordant'' pairs, this is done at the end of the routine. + +One wrinkle is what to do with ties in either $y$ or $x$. Such pairs +can be ignored in the count (treated as incomparable), treated as discordant, +or given a score of 1/2. +\begin{itemize} + \item Kendall's $\tau$-a scores ties as 0. + \item Kendall's $\tau$-b and the Goodman-Kruskal $\gamma$ ignore ties in + either $y$ or $x$. + \item Somers' $d$ treats ties in $y$ as incomparable, pairs that are tied + in $x$ (but not $y$) score as 1/2. The AUC from logistic regression is + equal to Somers' $d$. +\end{itemize} +All three of the above range from -1 to 1, the concordance is +$(d +1)/2$. +For survival data any pairs which cannot be ranked with certainty are +considered incomparable. +For instance $y_i$ is censored at time 10 and $y_j$ is an event (or censor) +at time 20. Subject $i$ may or may not survive longer than subject $j$. +Note that if $y_i$ is censored at time +10 and $y_j$ is an event at time 10 then $y_i > y_j$. +Observations that are in different strata are also incomparable, +since the Cox model only compares within strata. + +The program creates 4 variables, which are the number of concordant pairs, +discordant, tied on time, and tied on $x$ but not on time. +The default concordance is based on the Somers'/AUC definition, +but all 4 values are reported back so that a user +can recreate Kendall's or Goodmans values if desired. + +Here is the main routine. +\begin{nwchunk} +\nwhypf{concordance1}{concordance}{concordance2}= + concordance <- function(object, ...) + UseMethod("concordance") + + concordance.formula <- function(object, data, + weights, subset, na.action, cluster, + ymin, ymax, + timewt=c("n", "S", "S/G", "n/G", "n/G2", "I"), + influence=0, ranks=FALSE, reverse=FALSE, + timefix=TRUE, keepstrata=10, ...) \{ + Call <- match.call() # save a copy of of the call, as documentation + timewt <- match.arg(timewt) + if (missing(ymin)) ymin <- NULL + if (missing(ymax)) ymax <- NULL + + index <- match(c("data", "weights", "subset", "na.action", + "cluster"), + names(Call), nomatch=0) + temp <- Call[c(1, index)] + temp[[1L]] <- quote(stats::model.frame) + special <- c("strata", "cluster") + temp$formula <- if(missing(data)) terms(object, special) + else terms(object, special, data=data) + mf <- eval(temp, parent.frame()) # model frame + if (nrow(mf) ==0) stop("No (non-missing) observations") + Terms <- terms(mf) + + Y <- model.response(mf) + if (inherits(Y, "Surv")) \{ + if (timefix) Y <- aeqSurv(Y) + \} else \{ + if (is.factor(Y) && (is.ordered(Y) || length(levels(Y))==2)) + Y <- Surv(as.numeric(Y)) + else if (is.numeric(Y) && is.vector(Y)) Y <- Surv(Y) + else stop("left hand side of the formula must be a numeric vector, + survival object, or an orderable factor") + if (timefix) Y <- aeqSurv(Y) + \} + n <- nrow(Y) + + wt <- model.weights(mf) + offset<- attr(Terms, "offset") + if (length(offset)>0) stop("Offset terms not allowed") + + stemp <- untangle.specials(Terms, "strata") + if (length(stemp$vars)) \{ + if (length(stemp$vars)==1) strat <- mf[[stemp$vars]] + else strat <- strata(mf[,stemp$vars], shortlabel=TRUE) + Terms <- Terms[-stemp$terms] + \} + else strat <- NULL + + # if "cluster" was an argument, use it, otherwise grab it from the model + group <- model.extract(mf, "cluster") + cluster<- attr(Terms, "specials")$cluster + if (length(cluster)) \{ + tempc <- untangle.specials(Terms, 'cluster', 1:10) + ord <- attr(Terms, 'order')[tempc$terms] + if (any(ord>1)) stop ("Cluster can not be used in an interaction") + cluster <- strata(mf[,tempc$vars], shortlabel=TRUE) #allow multiples + Terms <- Terms[-tempc$terms] # toss it away + \} + if (length(group)) cluster <- group + + x <- model.matrix(Terms, mf)[,-1, drop=FALSE] #remove the intercept + if (ncol(x) > 1) stop("Only one predictor variable allowed") + + if (!is.null(ymin) & (length(ymin)> 1 || !is.numeric(ymin))) + stop("ymin must be a single number") + if (!is.null(ymax) & (length(ymax)> 1 || !is.numeric(ymax))) + stop("ymax must be a single number") + if (!is.logical(reverse)) + stop ("the reverse argument must be TRUE/FALSE") + + fit <- concordancefit(Y, x, strat, wt, ymin, ymax, timewt, cluster, + influence, ranks, reverse, keepstrata=keepstrata) + na.action <- attr(mf, "na.action") + if (length(na.action)) fit$na.action <- na.action + fit$call <- Call + + class(fit) <- 'concordance' + fit + \} + + print.concordance <- function(x, digits= max(1L, getOption("digits") - 3L), + ...) \{ + if(!is.null(cl <- x$call)) \{ + cat("Call:{\textbackslash}n") + dput(cl) + cat("{\textbackslash}n") + \} + omit <- x$na.action + if(length(omit)) + cat("n=", x$n, " (", naprint(omit), "){\textbackslash}n", sep = "") + else cat("n=", x$n, "{\textbackslash}n") + + if (length(x$concordance) > 1) \{ + # result of a call with multiple fits + tmat <- cbind(concordance= x$concordance, se=sqrt(diag(x$var))) + print(round(tmat, digits=digits), ...) + cat("{\textbackslash}n") + \} + else cat("Concordance= ", format(x$concordance, digits=digits), " se= ", + format(sqrt(x$var), digits=digits), '{\textbackslash}n', sep='') + + if (!is.matrix(x$count) || nrow(x$count < 11)) + print(round(x$count,2)) + invisible(x) + \} + + \nwhypf{concordancefit1}{concordancefit}{concordancefit2} + + \nwhypf{btree1}{btree}{btree2} +\end{nwchunk} + +The concordancefit function is broken out separately, since it is called +by all of the methods. It is also called directly by the the \code{coxph} +routine. +If $y$ is not a survival quantity, then all of the options for the +\code{timewt} parameter lead to the same result. + +\begin{nwchunk} +\nwhypb{concordancefit2}{concordancefit}{concordancefit1}= + concordancefit <- function(y, x, strata, weights, ymin=NULL, ymax=NULL, + timewt=c("n", "S", "S/G", "n/G", "n/G2", "I"), + cluster, influence=0, ranks=FALSE, reverse=FALSE, + timefix=TRUE, keepstrata=10, robustse =TRUE) \{ + # The coxph program may occassionally fail, and this will kill the C + # routine further below. So check for it. + if (any(is.na(x)) || any(is.na(y))) return(NULL) + timewt <- match.arg(timewt) + + if (!robustse) \{ranks <- FALSE; influence =0;\} + + # these should only occur if something other package calls this routine + if (!is.Surv(y)) \{ + if (is.factor(y) && (is.ordered(y) || length(levels(y))==2)) + y <- Surv(as.numeric(y)) + else if (is.numeric(y) && is.vector(y)) y <- Surv(y) + else stop("left hand side of the formula must be a numeric vector, + survival object, or an orderable factor") + if (timefix) y <- aeqSurv(y) + \} + n <- length(y) + if (length(x) != n) stop("x and y are not the same length") + if (missing(strata) || length(strata)==0) strata <- rep(1L, n) + if (length(strata) != n) + stop("y and strata are not the same length") + if (missing(weights) || length(weights)==0) weights <- rep(1.0, n) + else if (length(weights) != n) stop("y and weights are not the same length") + + type <- attr(y, "type") + if (type %in% c("left", "interval")) + stop("left or interval censored data is not supported") + if (type %in% c("mright", "mcounting")) + stop("multiple state survival is not supported") + + nstrat <- length(unique(strata)) + if (!is.logical(keepstrata)) \{ + if (!is.numeric(keepstrata)) + stop("keepstrat argument must be logical or numeric") + else keepstrata <- (nstrat <= keepstrata) + \} + + if (timewt %in% c("n", "I") && nstrat > 10 && !keepstrata) \{ + # Special trickery for matched case-control data, where the + # number of strata is huge, n per strata is small, and compute + # time becomes excessive. Make the data all one strata, but over + # disjoint time intervals + stemp <- as.numeric(as.factor(strata)) -1 + if (ncol(y) ==3) \{ + delta <- 2+ max(y[,2]) - min(y[,1]) + y[,1] <- y[,1] + stemp*delta + y[,2] <- y[,2] + stemp*delta + \} + else \{ + delta <- max(y[,1]) +2 + m1 <- rep(-1L, nrow(y)) + y <- Surv(m1 + stemp*delta, y[,1] + stemp*delta, y[,2]) + \} + strata <- rep(1L, n) + nstrat <- 1 + \} + + # This routine is called once per stratum + docount <- function(y, risk, wts, timeopt= 'n', timefix) \{ + n <- length(risk) + # this next line is mostly invoked in stratified logistic, where + # only 1 event per stratum occurs. All time weightings are the same + # don't waste time even if the user asked for something different + if (sum(y[,ncol(y)]) <2) timeopt <- 'n' + + sfit <- survfit(y~1, weights=wts, se.fit=FALSE, timefix=timefix) + etime <- sfit$time[sfit$n.event > 0] + esurv <- sfit$surv[sfit$n.event > 0] + + if (length(etime)==0) \{ + # the special case of a stratum with no events (it happens) + # No need to do any more work + return(list(count= rep(0.0, 6), influence=matrix(0.0, n, 5), + resid=NULL)) + \} + + if (timeopt %in% c("S/G", "n/G", "n/G2")) \{ + temp <- y + temp[,ncol(temp)] <- 1- temp[,ncol(temp)] # switch event/censor + gfit <- survfit(temp~1, weights=wts, se.fit=FALSE, timefix=timefix) + # G has the exact same time values as S + gsurv <- c(1, gfit$surv) # We want G(t-) + gsurv <- gsurv[which(sfit$n.event > 0)] + \} + + npair <- (sfit$n.risk- sfit$n.event)[sfit$n.event>0] + temp <- ifelse(esurv==0, 0, esurv/npair) # avoid 0/0 + timewt <- switch(timeopt, + "S" = sum(wts)*temp, + "S/G" = sum(wts)* temp/ gsurv, + "n" = rep(1.0, length(npair)), + "n/G" = 1/gsurv, + "n/G2"= 1/gsurv^2, + "I" = rep(1.0, length(esurv)) + ) + if (!is.null(ymin)) timewt[etime < ymin] <- 0 + if (!is.null(ymax)) timewt[etime > ymax] <- 0 + timewt <- ifelse(is.finite(timewt), timewt, 0) # 0 at risk case + + # order the data: reverse time, censors before deaths + if (ncol(y)==2) \{ + sort.stop <- order(-y[,1], y[,2], risk) -1L + \} else \{ + sort.stop <- order(-y[,2], y[,3], risk) -1L #order by endpoint + sort.start <- order(-y[,1]) -1L + \} + + # match each prediction score to the unique set of scores + # (to deal with ties) + utemp <- match(risk, sort(unique(risk))) + bindex <- btree(max(utemp))[utemp] + + storage.mode(y) <- "double" # just in case y is integer + storage.mode(wts) <- "double" + if (robustse) \{ + if (ncol(y) ==2) + fit <- .Call(Cconcordance3, y, bindex, wts, rev(timewt), + sort.stop, ranks) + else fit <- .Call(Cconcordance4, y, bindex, wts, rev(timewt), + sort.start, sort.stop, ranks) + + # The C routine gives back an influence matrix which has columns for + # concordant, discordant, tied on x but not y, tied on y, and tied + # on both x and y. + dimnames(fit$influence) <- list(NULL, + c("concordant", "discordant", "tied.x", "tied.y", "tied.xy")) + if (ranks) \{ + if (ncol(y)==2) dtime <- y[y[,2]==1, 1] + else dtime <- y[y[,3]==1, 2] + temp <- data.frame(time= sort(dtime), fit$resid) + names(temp) <- c("time", "rank", "timewt", "casewt", "variance") + fit$resid <- temp[temp[,3] > 0,] # don't return zeros + \} + \} + else \{ + if (ncol(y) ==2) + fit <- .Call(Cconcordance5, y, bindex, wts, rev(timewt), + sort.stop) + else fit <- .Call(Cconcordance6, y, bindex, wts, rev(timewt), + sort.start, sort.stop) + \} + fit + \} + + if (nstrat < 2) \{ + fit <- docount(y, x, weights, timewt, timefix=timefix) + count2 <- fit$count[1:5] + vcox <- fit$count[6] + fit$count <- fit$count[1:5] + if (robustse) imat <- fit$influence + if (ranks) resid <- fit$resid + \} else \{ + strata <- as.factor(strata) + ustrat <- levels(strata)[table(strata) >0] #some strata may have 0 obs + tfit <- lapply(ustrat, function(i) \{ + keep <- which(strata== i) + docount(y[keep,,drop=F], x[keep], weights[keep], timewt, + timefix=timefix) + \}) + temp <- t(sapply(tfit, function(x) x$count)) + fit <- list(count = temp[,1:5]) + count2 <- colSums(fit$count) + if (!keepstrata) fit$count <- count2 + vcox <- sum(temp[,6]) + if (robustse) \{ + imat <- do.call("rbind", lapply(tfit, function(x) x$influence)) + # put it back into data order + index <- match(1:n, (1:n)[order(strata)]) + imat <- imat[index,] + if (ranks) \{ + nr <- lapply(tfit, function(x) nrow(x$resid)) + resid <- do.call("rbind", lapply(tfit, function(x) x$resid)) + resid$strata <- rep(ustrat, nr) + \} + \} + \} + + npair <- sum(count2[1:3]) + if (!keepstrata && is.matrix(fit$count)) fit$count <- colSums(fit$count) + somer <- (count2[1] - count2[2])/npair + if (robustse) \{ + dfbeta <- weights*((imat[,1]- imat[,2])/npair - + (somer/npair)* rowSums(imat[,1:3])) + if (!missing(cluster) && length(cluster)>0) \{ + dfbeta <- tapply(dfbeta, cluster, sum) + dfbeta <- ifelse(is.na(dfbeta),0, dfbeta) # if cluster is a factor + \} + var.somer <- sum(dfbeta^2) + rval <- list(concordance = (somer+1)/2, count=fit$count, n=n, + var = var.somer/4, cvar=vcox/(4*npair^2)) + \} + else rval <- list(concordance = (somer+1)/2, count=fit$count, n=n, + cvar=vcox/(4*npair^2)) + if (is.matrix(rval$count)) + colnames(rval$count) <- c("concordant", "discordant", "tied.x", + "tied.y", "tied.xy") + else names(rval$count) <- c("concordant", "discordant", "tied.x", "tied.y", + "tied.xy") + + if (influence == 1 || influence==3) rval$dfbeta <- dfbeta/2 + if (influence >=2) rval$influence <- imat + + if (ranks) rval$ranks <- resid + if (reverse) \{ + # flip concordant/discordant values but not the labels + rval$concordance <- 1- rval$concordance + if (!is.null(rval$dfbeta)) rval$dfbeta <- -rval$dfbeta + if (!is.null(rval$influence)) \{ + rval$influence <- rval$influence[,c(2,1,3,4,5)] + colnames(rval$influence) <- colnames(rval$influence)[c(2,1,3,4,5)] + \} + if (is.matrix(rval$count)) \{ + rval$count <- rval$count[, c(2,1,3,4,5)] + colnames(rval$count) <- colnames(rval$count)[c(2,1,3,4,5)] + \} + else \{ + rval$count <- rval$count[c(2,1,3,4,5)] + names(rval$count) <- names(rval$count)[c(2,1,3,4,5)] + \} + if (ranks) rval$ranks$rank <- -rval$ranks$rank + \} + + rval + \} +\end{nwchunk} + +\subsection{Methods} + +Methods are defined for lm, survfit, and coxph objects. Detection of +strata, weights, or clustering is the main nuisance, since those are +not passed back as part of coxph or survreg objects. Glm and lm objects +have the model frame by default, but that can be turned off by a user. +This routine gets the X, Y, and other portions from the result of a +particular fit object. + +\begin{nwchunk} +\nwhyp{concordance2}{concordance}{concordance1}{concordance3}= + cord.getdata <- function(object, newdata=NULL, cluster=NULL, need.wt, timefix=TRUE) \{ + # For coxph object, don't reconstruct the model frame unless we must. + # This will occur if weights, strata, or cluster are needed, or if + # there is a newdata argument. Of course, if the model frame is + # already present, then use it! + Terms <- terms(object) + specials <- attr(Terms, "specials") + if (!is.null(specials$tt)) + stop("cannot yet handle models with tt terms") + + if (!is.null(newdata)) \{ + mf <- model.frame(object, data=newdata) + y <- model.response(mf) + if (!is.Surv(y)) \{ + if (is.numeric(y) && is.vector(y)) y <- Surv(y) + else stop("left hand side of the formula must be a numeric vector or a survival object") + \} + if (timefix) y <- aeqSurv(y) + rval <- list(y= y, x= predict(object, newdata)) + # the type of prediction does not matter, as long as it is a + # monotone transform of the linear predictor + \} + else \{ + mf <- object$model + y <- object$y + if (is.null(y)) \{ + if (is.null(mf)) mf <- model.frame(object) + y <- model.response(mf) + \} + if (!is.Surv(y)) \{ + y <- Surv(y) + if (timefix) y <- aeqSurv(y) + \} # survival models will have already called timefix + + x <- object$linear.predictors # used by most + if (is.null(x)) x <- object$fitted.values # used by lm + if (is.null(x)) \{object$na.action <- NULL; x <- predict(object)\} + rval <- list(y = y, x= x) + \} + + if (need.wt) \{ + if (is.null(mf)) mf <- model.frame(object) + rval$weights <- model.weights(mf) + \} + + if (!is.null(specials$strata)) \{ + if (is.null(mf)) mf <- model.frame(object) + stemp <- untangle.specials(Terms, 'strata', 1) + if (length(stemp$vars)==1) rval$strata <- mf[[stemp$vars]] + else rval$strata <- strata(mf[,stemp$vars], shortlabel=TRUE) + \} + + if (is.null(cluster)) \{ + if (!is.null(specials$cluster)) \{ + if (is.null(mf)) mf <- model.frame(object) + tempc <- untangle.specials(Terms, 'cluster', 1:10) + ord <- attr(Terms, 'order')[tempc$terms] + rval$cluster <- strata(mf[,tempc$vars], shortlabel=TRUE) + \} + else if (!is.null(object$call$cluster)) \{ + if (is.null(mf)) mf <- model.frame(object) + rval$cluster <- model.extract(mf, "cluster") + \} + \} + else rval$cluster <- cluster + rval + \} +\end{nwchunk} + +The methods themselves, which are near clones of each other. +There is one portion of these that is not very clear. +I use the trick from nearly all calls to model.frame to deal with +arguments that might be there or might not, such as newdata. +Construct a call by hand by first subsetting this call as Call[...], +then replace the first element with the name of what I really want +to call -- quote(cord.work) --, add any other args I want, and finally +execute it with eval(). +The problem is that this doesn't work; the routine can't find cord.work +since it is not an exported function. A simple call to cord.work is +okay, since function calls inherit from the survival namespace, but +cfun isn't a function call, it is an expression. +There are 3 possible solutions +\begin{itemize} + \item bad: change eval(cfun, parent.frame()) to eval(cfun, evironment(coxph)), + or any other function from the survival library which has + namespace::survival as its environment. If the user calls concordance + with ymax=zed, say, we might not be able to find 'zed'. Especially if they + had called concordance from within a function. We need the call chain. + \item okay: use cfun[[1]] <- cord.work, which makes a copy of the entire + cord.work function and stuffs it in. The function isn't too long, so this + is okay. If cord.work fails, the label on its error message won't be as + nice since it won't have ``cord.work'' in it. + \item speculative: make a function and invoke it. + This creates a new function in the survival namespace, but evaluates it + in the current context. Using parent.frame() is important so that I + don't accidentally pick up 'nfit' say, if the user had used a variable of + that name as one of their arguments. \\ + temp <- function(){} \\ + body(temp, environment(coxph)) <- cfun\\ + rval <- eval(temp(), parent.frame()) +\end{itemize} + +\begin{nwchunk} +\nwhyp{concordance3}{concordance}{concordance2}{concordance4}= + concordance.lm <- function(object, ..., newdata, cluster, ymin, ymax, + influence=0, ranks=FALSE, timefix=TRUE, + keepstrata=10) \{ + Call <- match.call() + fits <- list(object, ...) + nfit <- length(fits) + fname <- as.character(Call) # like deparse(substitute()) but works for ... + fname <- fname[1 + 1:nfit] + notok <- sapply(fits, function(x) !inherits(x, "lm")) + if (any(notok)) \{ + # a common error is to mistype an arg, "ramk=TRUE" for instance, + # and it ends up in the ... list + # try for a nice message in this case: the name of the arg if it + # has one other than "object", fname otherwise + indx <- which(notok) + id2 <- names(Call)[indx+1] + temp <- ifelse(id2 %in% c("","object"), fname, id2) + stop(temp, " argument is not an appropriate fit object") + \} + + cargs <- c("ymin", "ymax","influence", "ranks", "keepstrata") + cfun <- Call[c(1, match(cargs, names(Call), nomatch=0))] + cfun[[1]] <- cord.work # or quote(survival:::cord.work) + cfun$fname <- fname + + if (missing(newdata)) newdata <- NULL + if (missing(cluster)) cluster <- NULL + need.wt <- any(sapply(fits, function(x) !is.null(x$call$weights))) + + cfun$data <- lapply(fits, cord.getdata, newdata=newdata, cluster=cluster, + need.wt=need.wt, timefix=timefix) + rval <- eval(cfun, parent.frame()) + rval$call <- Call + rval + \} + + concordance.survreg <- function(object, ..., newdata, cluster, ymin, ymax, + timewt=c("n", "S", "S/G", "n/G", "n/G2", "I"), + influence=0, ranks=FALSE, timefix=FALSE, + keepstrata=10) \{ + Call <- match.call() + fits <- list(object, ...) + nfit <- length(fits) + fname <- as.character(Call) # like deparse(substitute()) but works for ... + fname <- fname[1 + 1:nfit] + notok <- sapply(fits, function(x) !inherits(x, "survreg")) + if (any(notok)) \{ + # a common error is to mistype an arg, "ramk=TRUE" for instance, + # and it ends up in the ... list + # try for a nice message in this case: the name of the arg if it + # has one other than "object", fname otherwise + indx <- which(notok) + id2 <- names(Call)[indx+1] + temp <- ifelse(id2 %in% c("","object"), fname, id2) + stop(temp, " argument is not an appropriate fit object") + \} + + cargs <- c("ymin", "ymax","influence", "ranks", "timewt", "keepstrata") + cfun <- Call[c(1, match(cargs, names(Call), nomatch=0))] + cfun[[1]] <- cord.work + cfun$fname <- fname + + if (missing(newdata)) newdata <- NULL + if (missing(cluster)) cluster <- NULL + need.wt <- any(sapply(fits, function(x) !is.null(x$call$weights))) + + cfun$data <- lapply(fits, cord.getdata, newdata=newdata, cluster=cluster, + need.wt=need.wt, timefix=timefix) + rval <- eval(cfun, parent.frame()) + rval$call <- Call + rval + \} + + concordance.coxph <- function(object, ..., newdata, cluster, ymin, ymax, + timewt=c("n", "S", "S/G", "n/G", "n/G2", "I"), + influence=0, ranks=FALSE, timefix=FALSE, + keepstrata=10) \{ + Call <- match.call() + fits <- list(object, ...) + nfit <- length(fits) + fname <- as.character(Call) # like deparse(substitute()) but works for ... + fname <- fname[1 + 1:nfit] + notok <- sapply(fits, function(x) !inherits(x, "coxph")) + if (any(notok)) \{ + # a common error is to mistype an arg, "ramk=TRUE" for instance, + # and it ends up in the ... list + # try for a nice message in this case: the name of the arg if it + # has one other than "object", fname otherwise + indx <- which(notok) + id2 <- names(Call)[indx+1] + temp <- ifelse(id2 %in% c("","object"), fname, id2) + stop(temp, " argument is not an appropriate fit object") + \} + + # the cargs trick is a nice one, but it only copies over arguments that + # are present. If 'ranks' was not specified, the default of FALSE is + # not set. We keep it in the arg list only to match the documentation. + cargs <- c("ymin", "ymax","influence", "ranks", "timewt", "keepstrata") + cfun <- Call[c(1, match(cargs, names(Call), nomatch=0))] + cfun[[1]] <- cord.work # a copy of the function + cfun$fname <- fname + cfun$reverse <- TRUE + + if (missing(newdata)) newdata <- NULL + if (missing(cluster)) cluster <- NULL + need.wt <- any(sapply(fits, function(x) !is.null(x$call$weights))) + + cfun$data <- lapply(fits, cord.getdata, newdata=newdata, cluster=cluster, + need.wt=need.wt, timefix=timefix) + rval <- eval(cfun, parent.frame()) + rval$call <- Call + rval + \} +\end{nwchunk} + +The next routine does all of the actual work for a set of models. +Note that because of the call-through trick (fargs) exactly and only those +arguments that are passed in are passed through to concordancefit. +Default argument values for that function are found there. The default +value for inflence found below is used in this routine, so it is important +that they match. + +\begin{nwchunk} +\nwhyp{concordance4}{concordance}{concordance3}{concordance5}= + cord.work <- function(data, timewt, ymin, ymax, influence=0, ranks=FALSE, + reverse, fname, keepstrata) \{ + Call <- match.call() + fargs <- c("timewt", "ymin", "ymax", "influence", "ranks", "reverse", + "keepstrata") + fcall <- Call[c(1, match(fargs, names(Call), nomatch=0))] + fcall[[1L]] <- concordancefit + + nfit <- length(data) + if (nfit==1) \{ + dd <- data[[1]] + fcall$y <- dd$y + fcall$x <- dd$x + fcall$strata <- dd$strata + fcall$weights <- dd$weights + fcall$cluster <- dd$cluster + rval <- eval(fcall, parent.frame()) + \} + else \{ + # Check that all of the models used the same data set, in the same + # order, to the best of our abilities + n <- length(data[[1]]$x) + for (i in 2:nfit) \{ + if (length(data[[i]]$x) != n) + stop("all models must have the same sample size") + + if (!identical(data[[1]]$y, data[[i]]$y)) + warning("models do not have the same response vector") + + if (!identical(data[[1]]$weights, data[[i]]$weights)) + stop("all models must have the same weight vector") + \} + + if (influence==2) fcall$influence <-3 else fcall$influence <- 1 + flist <- lapply(data, function(d) \{ + temp <- fcall + temp$y <- d$y + temp$x <- d$x + temp$strata <- d$strata + temp$weights <- d$weights + temp$cluster <- d$cluster + eval(temp, parent.frame()) + \}) + + for (i in 2:nfit) \{ + if (length(flist[[1]]$dfbeta) != length(flist[[i]]$dfbeta)) + stop("models must have identical clustering") + \} + count = do.call(rbind, lapply(flist, function(x) \{ + if (is.matrix(x$count)) colSums(x$count) else x$count\})) + + concordance <- sapply(flist, function(x) x$concordance) + dfbeta <- sapply(flist, function(x) x$dfbeta) + + names(concordance) <- fname + rownames(count) <- fname + + wt <- data[[1]]$weights + if (is.null(wt)) vmat <- crossprod(dfbeta) + else vmat <- t(wt * dfbeta) %*% dfbeta + rval <- list(concordance=concordance, count=count, + n=flist[[1]]$n, var=vmat, + cvar= sapply(flist, function(x) x$cvar)) + + if (influence==1) rval$dfbeta <- dfbeta + else if (influence ==2) \{ + temp <- unlist(lapply(flist, function(x) x$influence)) + rval$influence <- array(temp, + dim=c(dim(flist[[1]]$influence), nfit)) + \} + + if (ranks) \{ + temp <- lapply(flist, function(x) x$ranks) + rdat <- data.frame(fit= rep(fname, sapply(temp, nrow)), + do.call(rbind, temp)) + row.names(rdat) <- NULL + rval$ranks <- rdat + \} + \} + + class(rval) <- "concordance" + rval + \} +\end{nwchunk} + +Last, a few miscellaneous methods +\begin{nwchunk} +\nwhypb{concordance5}{concordance}{concordance4}= + coef.concordance <- function(object, ...) object$concordance + vcov.concordance <- function(object, ...) object$var +\end{nwchunk} + +The C routine returns an influence matrix with one row per subject $i$, +and columns giving the partial with respect to $w_i$ for the number of +concordant, discordant, tied on $x$ and ties on $y$ pairs. +Somers' $d$ is $(C-D)/m$ where $m= C + D + T$ is the total number of %' +comparable pairs, which does not count the tied-on-y column. +For any given subject or cluster $k$ (for grouped jackknife) the +IJ estimate of the variance is +\begin{align*} + V &\ \sum_k \left(\frac{\partial d}{\partial w_k}\right)^2 \\ + \frac{\partial d}{\partial w_k} &= + \frac{1}{m} \left[\frac{\partial{C-D}}{\partial w_k} - + d \frac{\partial C+D+T}{\partial w_k} \right] \\ +\end{align*} + +The C code looks a lot like a Cox model: walk forward through time, keep +track of the risk sets, and add something to the totals at each death. +What needs to be summed is the rank of the event subject's $x$ value, as +compared to the value for all others at risk at this time point. +For notational simplicity let $Y_j(t_i)$ be an indicator that subject $j$ +is at risk at event time $t_i$, and $Y^*_j(t_i)$ the more restrictive one that +subject $j$ is both at risk and not a tied event time. +The values we want at time $t_i$ are +\begin{align} + C_i &= v_i \delta_i w_i \sum_j w_j Y^*_j(t_i) \left[I(x_i < x_j) \right] + \label{C} \\ + D_i &= v_i \delta_i w_i \sum_j w_j Y^*_j(t_i) \left[I(x_i > x_j)\right] + \label{D} \\ + T_i &= v_i \delta_i w_i \sum_j w_j Y^*_j(t_i) \left[I(x_i = x_j) \right] + \label{T} \\ +\end{align} + +In the above $v$ is an optional time weight, which we will discuss later. +The normal concordance definition has $v=1$. +$C$, $D$, and $T$ are the number of concordant, discordant, and tied +pairs, respectively, +and $m= C+D+T$ will be the total number of concordant pairs. +Somers' $d$ is $(C-D)/m$ and the concordance is $(d+1)/2 = (C + T/2)/m$. + +The primary compuational question is how to do this efficiently, i.e., better +than a naive algorithm that loops across all $n(n-1)/2$ +possible pairs. +There are two key ideas. +\begin{enumerate} +\item Rearrange the counting so that we do it by death times. + For each death we count the number of other subjects in the risk set whose + score is higher, lower, or tied and add it into the totals. + This neatly solves the question of time-dependent covariates. +\item Counting the number with higher, lower, and tied $x$ can be done in + $O(\log_2 n)$ time if the $x$ data is kept in a binary tree. +\end{enumerate} + +\begin{figure} + \myfig{balance} + \caption{A balanced tree of 13 nodes.} + \label{treefig} +\end{figure} + +Figure \ref{treefig} shows a balanced binary tree containing +13 risk scores. For each node the left child and all its descendants +have a smaller value than the parent, the right child and all its +descendents have a larger value. +Each node in figure \ref{treefig} is also annotated with the total weight +of observations in that node and the weight for itself plus all its children +(not shown on graph). +Assume that the tree shown represents all of the subjects still alive at the +time a particular subject ``Smith'' expires, and that Smith has the risk score +of 19 in the tree. +The concordant pairs are those with a risk score $>19$, i.e., both $\hat y=x$ +and $y$ are larger, discordant are $<19$, and we have no ties. +The totals can be found by +\begin{enumerate} + \item Initialize the counts for discordant, concordant and tied to the + values from the left children, right children, and ties at this node, + respectively, which will be $(C,D,T) = (1,1,0)$. + \item Walk up the tree, and at each step add the (parent + left child) or + (parent + right child) to either D or C, depending on what part of the + tree has not yet been totaled. + At the next node (8) $D= D+4$, and at the top node $C=C + 6$. +\end{enumerate} + +There are 5 concordant and 7 discordant pairs. +This takes a little less than $\log_2(n)$ steps on average, as compared to an +average of $n/2$ for the naive method. The difference can matter when $n$ is +large since this traversal must be done for each event. + +The classic way to store trees is as a linked list. There are several +algorithms for adding and subtracting nodes from a tree while maintaining +the balance (red-black trees, AA trees, etc) but we take a different +approach. Since we need to deal with case weights in the model and we +know all the risk score at the outset, the full set of risk scores is +organised into a tree at the beginning, updating the sums of weights at +each node as observations are added or removed from the risk set. + +If we internally index the nodes of the tree as 1 for the top, +2--3 for the next +horizontal row, 4--7 for the next, \ldots then the parent-child +traversal becomes particularly easy. +The parent of node $i$ is $i/2$ (integer arithmetic) and the children of +node $i$ are $2i$ and $2i +1$. In C code the indices start at 0 of course. +The following bit of code arranges data into such a tree. +\begin{nwchunk} +\nwhypb{btree2}{btree}{btree1}= + btree <- function(n) \{ + tfun <- function(n, id, power) \{ + if (n==1L) id + else if (n==2L) c(2L *id + 1L, id) + else if (n==3L) c(2L*id + 1L, id, 2L*id +2L) + else \{ + nleft <- if (n== power*2L) power else min(power-1L, n-power%/%2L) + c(tfun(nleft, 2L *id + 1L, power%/%2), id, + tfun(n-(nleft+1L), 2L*id +2L, power%/%2)) + \} + \} + tfun(as.integer(n), 0L, as.integer(2^(floor(logb(n-1,2))))) + \} +\end{nwchunk} + +Referring again to figure \ref{treefig}, \code{btree(13)} yields the vector +\code{7 3 8 1 9 4 10 0 11 5 12 2 6} +meaning that the smallest element +will be in position 8 of the tree, the next smallest in position 4, etc, +and using indexing that starts at 0 since the results will be passed to a C +routine. +The code just above takes care to do all arithmetic as integer. +This actually made almost no difference in the compute time, but it was an +interesting exercise to find that out. + +The next question is how to compute a variance for the result. +One approach is to compute an infinitesimal jackknife (IJ) estimate, +for which we need derivatives with respect to the weights. +Looking back at equation \eqref{C} we have +\begin{align} + C &= \sum_i w_i \delta_i \sum_j Y^*_j(t_i) w_j I(x_i < x_j) + \nonumber\\ +% \frac{\partial C}{\partial w_k} &= +% (v_k/m_k)\delta_k \sum_j Y^*_{j}(t_k) I(x_k < x_j) + +% \sum_i (v_i/m_i) w_i Y^*_k(t_i) I(x_i < x_k) \label{partialC} +\end{align} +A given subject's weight appears multiple times, once when they are an +event ($w_i \delta_i)$, and then as part of the risk set for other's +events. I avoided this for some time because it looked like an $O(nd)$ +process to separately update each subject's influence for each risk set +they inhabit, but David Watson pointed out a path forward. +The solution is to keep two trees. +Tree 1 contains all of the subjects at risk. We traverse it when each subject +is added in, updating the tree, +and traverse it again at each death, pulling off values to update our sums. +The second tree holds only the deaths and is updated at each death; +it is read out twice per subject, +once just after they enter the risk set and once when they leave. + +The basic algorithm is to move through an outer and inner loop. The +outer loop moves across unique times, the inner for all obs that +share a death time. We progress from largest to smallest time. +Dealing with tied deaths is a bit subtle. +\begin{itemize} + \item All of the tied deaths need to be added to the event tree before + subtracting the tree values from the ``initial'' influence matrix, since + none of the tied subjects are in the comparison set for each other. + \item Changes to the overall concordance/discordance counts need to be done + for all the ties before adding them into the main tree, for the same reason. + \item The Cox model variance just below has to be added up sequentially, + one terms after each addition to the main tree. +\end{itemize} +Thus the inner loop must be repeated at least twice. + +A second variance computation treats the data as a Cox model. +Create zero-centered scores for all subjects in the risk set: +\begin{align} + z_i(t) &= \sum_{j \in R(t)} w_j \sign(x_i - x_j) \nonumber \\ + D-C &= \sum_i \delta_i z_i(t_i) \label{zcord} +\end{align} +At any event time $\sum w_i z_i =0$. +Equation \eqref{zcord} is the score equation +for a Cox model with time-dependent covariate $z$. +When two subjects have an event at the same time, this formulation treats +each of them as being in the other's risk set whereas the concordance +treats them as incomparable --- how can they be the same? +The trick is that $D-C$ does not change: the tied pairs add equally to +$D$ and $C$. +Under the null hypothesis that the risk score is not related to outcome, +each term in \eqref{zcord} is a random selection from the $z$ scores in +the risk set, and the variance of the addition is the variance of $z$, +the sum of these over deaths is the Cox model information matrix, +which is also the variance of the score statistic. +The mean of $z$ is always zero, so we need to keep track of +$\sum w_i z^2$. + +How can we do this efficiently? First note that $z_i$ can be written +as sum(weights for smaller x) - sum(weights for larger x), and in fact the +weighted mean for any slice of $x$, $a < x < b$, is exactly the +same: mean = sum(weights for x values below the range) - + sum(weights above the range). +The second trick is to use an ANOVA decomposition of the variance of $z$ into +within-slice and between-slice sums of squares, where the 3 slices are the +$z$ scores at a given $x$ value (node of the tree), weights for score below that +cutpoint, and above. +Assume that a new observation $k$ has just been added to the tree. +This will add $w_k$ to all the $z$ values above, and to the weighted mean of +all those above, $-w_k$ to the values and means below, and 0 to the values and +means of any tied observations. Thus none of the current `within' +SS change. +Let $s_a$, $s_b$ and $s_0$ be the current sum of weights above, below, and +at the node of the tree. The mean for the above group was $(s_b + s_0)$ with +between SS contribution of $s_a (s_b + s_0)^2$. The below mean was +$-(s_a + s_0)$ with between SS contribution of $s_b(s_a + s_0)^2$. +The change to the between SS from adding the new subject is +$$ +s_a\left( (s_b+s_0 + w_k)^2 - (s_b + s_0)^2 \right) = +s_a (2w_k (s_b + s_0) + w_k^2) +$$ +while the change in between SS for the below group +is $s_b(2w_k(s_a + s_0) + w_k^2)$, and there is no change for the +prior observations in the middle group. +Last we add $w_kz_k^2 = w_k(s_b- s_a)^2$ to the sum for the new observation. +Putting all this together the change is +$$ + w_k \left(s_a (w_k + (s_b + s_c)) + s_b(w_k + (s_a + s_c)) + (s_a-s_b)^2 \right) +$$ + +We can now define the C-routine that does the bulk of the work. +First we give the outline shell of the code and then discuss the +parts one by one. This routine is for ordinary survival data, and +will be called once per stratum. +Input variables are +\begin{description} + \item[n] the number of observations + \item[y] matrix containing the time and status, data is sorted by descending + time, with censorings precedint deaths. + \item[x] the tree node at which this observation's risk score resides %' + \item[wt] case weight for the observation +\end{description} +The routine will return list with three components: +\begin{itemize} + \item count, a vector containing the weighted number of concordant, + discordant, tied on $x$ but not $y$, and tied on y pairs. + The weight for a pair is $w_iw_j$. + \item resid, a three column matrix with one row per event, containing the + score residual at that event, its variance, and the sum of weights. + The score residual is + a rescaled $z_i$ so as to lie between 0 and 1: $(1+ z/\sum(w))/2$. + The concordance is then a weighted sum of the residuals. + \item influence, a matrix with one row per observation and 4 columns, giving + that observation's first derivative with respect to the count vector. +\end{itemize} + +\begin{nwchunk} +\nwhypf{concordance31}{concordance3}{concordance32}= + #include "survS.h" + #include "survproto.h" + + \nwhypf{walkup1}{walkup}{walkup2} + + SEXP concordance3(SEXP y, SEXP x2, SEXP wt2, SEXP timewt2, + SEXP sortstop, SEXP doresid2) \{ + int i, j, k, ii, jj, kk, j2; + int n, ntree, nevent; + double *time, *status; + int xsave; + + /* sum of weights for a node (nwt), sum of weights for the node and + ** all of its children (twt), then the same again for the subset of + ** deaths + */ + double *nwt, *twt, *dnwt, *dtwt; + double z2; /* sum of z^2 values */ + + int ndeath; /* total number of deaths at this point */ + int utime; /* number of unique event times seen so far */ + double dwt, dwt2; /* sum of weights for deaths and deaths tied on x */ + double wsum[3]; /* the sum of weights that are > current, <, or equal */ + double temp, adjtimewt; /* the second accounts for npair and timewt*/ + + SEXP rlist, count2, imat2, resid2; + double *count, *imat[5], *resid[4]; + double *wt, *timewt; + int *x, *sort2; + int doresid; + static const char *outnames1[]=\{"count", "influence", "resid", ""\}, + *outnames2[]=\{"count", "influence", ""\}; + + n = nrows(y); + doresid = asLogical(doresid2); + x = INTEGER(x2); + wt = REAL(wt2); + timewt = REAL(timewt2); + sort2 = INTEGER(sortstop); + time = REAL(y); + status = time + n; + + /* if there are tied predictors, the total size of the tree will be < n */ + ntree =0; nevent =0; + for (i=0; i= ntree) ntree = x[i] +1; + nevent += status[i]; + \} + + nwt = (double *) R_alloc(4*ntree, sizeof(double)); + twt = nwt + ntree; + dnwt = twt + ntree; + dtwt = dnwt + ntree; + + for (i=0; i< 4*ntree; i++) nwt[i] =0.0; + + if (doresid) PROTECT(rlist = mkNamed(VECSXP, outnames1)); + else PROTECT(rlist = mkNamed(VECSXP, outnames2)); + count2 = SET_VECTOR_ELT(rlist, 0, allocVector(REALSXP, 6)); + count = REAL(count2); + for (i=0; i<6; i++) count[i]=0.0; + imat2 = SET_VECTOR_ELT(rlist, 1, allocMatrix(REALSXP, n, 5)); + for (i=0; i<5; i++) \{ + imat[i] = REAL(imat2) + i*n; + for (j=0; j 0) \{ /* for as long as I have a parent... */ + parent = (index-1)/2; + if (index%2 == 1) sums[0] += twt[parent] - twt[index]; /* left child */ + else sums[1] += twt[parent] - twt[index]; /* I am a right child */ + index = parent; + \} + \} + + void addin(double *nwt, double *twt, int index, double wt) \{ + nwt[index] += wt; + while (index >0) \{ + twt[index] += wt; + index = (index-1)/2; + \} + twt[0] += wt; + \} +\end{nwchunk} + +The code for [start, stop) data is almost identical, the primary call +simply has one more index. +As in the agreg routines there are two sort indices, the first indexes +the data by stop time, longest to earliest, and the second by start time. +The \Verb!y! variable now has three columns. +\begin{nwchunk} +\nwhypb{concordance32}{concordance3}{concordance31}= + SEXP concordance4(SEXP y, SEXP x2, SEXP wt2, SEXP timewt2, + SEXP sortstart, SEXP sortstop, SEXP doresid2) \{ + int i, j, k, ii, jj, kk, i2, j2; + int n, ntree, nevent; + double *time1, *time2, *status; + int xsave; + + /* sum of weights for a node (nwt), sum of weights for the node and + ** all of its children (twt), then the same again for the subset of + ** deaths + */ + double *nwt, *twt, *dnwt, *dtwt; + double z2; /* sum of z^2 values */ + + int ndeath; /* total number of deaths at this point */ + int utime; /* number of unique event times seen so far */ + double dwt; /* weighted number of deaths at this point */ + double dwt2; /* tied on both x and y */ + double wsum[3]; /* the sum of weights that are > current, <, or equal */ + double temp, adjtimewt; /* the second accounts for npair and timewt*/ + + SEXP rlist, count2, imat2, resid2; + double *count, *imat[5], *resid[4]; + double *wt, *timewt; + int *x, *sort2, *sort1; + int doresid; + static const char *outnames1[]=\{"count", "influence", "resid", ""\}, + *outnames2[]=\{"count", "influence", ""\}; + + n = nrows(y); + doresid = asLogical(doresid2); + x = INTEGER(x2); + wt = REAL(wt2); + timewt = REAL(timewt2); + sort2 = INTEGER(sortstop); + sort1 = INTEGER(sortstart); + time1 = REAL(y); + time2 = time1 + n; + status = time2 + n; + + /* if there are tied predictors, the total size of the tree will be < n */ + ntree =0; nevent =0; + for (i=0; i= ntree) ntree = x[i] +1; + nevent += status[i]; + \} + + /* + ** nwt and twt are the node weight and total =node + all children for the + ** tree holding all subjects. dnwt and dtwt are the same for the tree + ** holding all the events + */ + nwt = (double *) R_alloc(4*ntree, sizeof(double)); + twt = nwt + ntree; + dnwt = twt + ntree; + dtwt = dnwt + ntree; + + for (i=0; i< 4*ntree; i++) nwt[i] =0.0; + + if (doresid) PROTECT(rlist = mkNamed(VECSXP, outnames1)); + else PROTECT(rlist = mkNamed(VECSXP, outnames2)); + count2 = SET_VECTOR_ELT(rlist, 0, allocVector(REALSXP, 6)); + count = REAL(count2); + for (i=0; i<6; i++) count[i]=0.0; + imat2 = SET_VECTOR_ELT(rlist, 1, allocMatrix(REALSXP, n, 5)); + for (i=0; i<5; i++) \{ + imat[i] = REAL(imat2) + i*n; + for (j=0; j= time2[ii]); i2++) \{ + jj = sort1[i2]; + /* influence */ + walkup(dnwt, dtwt, x[jj], wsum, ntree); + imat[0][jj] += wsum[1]; + imat[1][jj] += wsum[0]; + imat[2][jj] += wsum[2]; + + addin(nwt, twt, x[jj], -wt[jj]); /*remove from main tree */ + + /* Cox variance */ + walkup(nwt, twt, x[jj], wsum, ntree); + z2 -= wt[jj]*(wsum[0]*(wt[jj] + 2*(wsum[1] + wsum[2])) + + wsum[1]*(wt[jj] + 2*(wsum[0] + wsum[2])) + + (wsum[0]-wsum[1])*(wsum[0]-wsum[1])); + \} + + ndeath=0; dwt=0; + dwt2 =0; xsave=x[ii]; j2= i; + adjtimewt = timewt[utime++]; + + /* pass 1 */ + for (j=i; j 1) + stop("Can have only 1 ratetable() call in a formula") + \nwhypf{survexp-setup-rmap1}{survexp-setup-rmap}{survexp-setup-rmap2} + + mf <- eval(tform, parent.frame()) +\end{nwchunk} + +\begin{nwchunk} +\nwhyp{survexp-setup-rmap2}{survexp-setup-rmap}{survexp-setup-rmap1}{survexp-setup-rmap3}= + if(length(rate) == 1) \{ + if (!missing(rmap)) + stop("The ratetable() call in a formula is depreciated") + + stemp <- untangle.specials(Terms, 'ratetable') + rcall <- as.call(parse(text=stemp$var)[[1]]) # as a call object + rcall[[1]] <- as.name('list') # make it a call to list(.. + Terms <- Terms[-stemp$terms] # remove from the formula + \} + else if (!missing(rmap)) \{ + rcall <- substitute(rmap) + if (!is.call(rcall) || rcall[[1]] != as.name('list')) + stop ("Invalid rcall argument") + \} + else rcall <- NULL # A ratetable, but no rcall argument + + # Check that there are no illegal names in rcall, then expand it + # to include all the names in the ratetable + if (is.ratetable(ratetable)) \{ + varlist <- names(dimnames(ratetable)) + if (is.null(varlist)) varlist <- attr(ratetable, "dimid") # older style + \} + else if(inherits(ratetable, "coxph") && !inherits(ratetable, "coxphms")) \{ + ## Remove "log" and such things, to get just the list of + # variable names + varlist <- all.vars(delete.response(ratetable$terms)) + \} + else stop("Invalid rate table") + + temp <- match(names(rcall)[-1], varlist) # 2,3,... are the argument names + if (any(is.na(temp))) + stop("Variable not found in the ratetable:", (names(rcall))[is.na(temp)]) + + if (any(!(varlist %in% names(rcall)))) \{ + to.add <- varlist[!(varlist %in% names(rcall))] + temp1 <- paste(text=paste(to.add, to.add, sep='='), collapse=',') + if (is.null(rcall)) rcall <- parse(text=paste("list(", temp1, ")"))[[1]] + else \{ + temp2 <- deparse(rcall) + rcall <- parse(text=paste("c(", temp2, ",list(", temp1, "))"))[[1]] + \} + \} +\end{nwchunk} + +The formula below is used only in the call to \Verb!model.frame! to ensure +that the frame has both the formula and the ratetable variables. +We don't want to modify the original formula, since we use it to create +the $X$ matrix and the response variable. +The non-obvious bit of code is the addition of an environment to the +formula. The \Verb!model.matrix! routine has a non-standard evaluation - it +uses the frame of the formula, rather than the parent.frame() argument +below, along with the \Verb!data! to look up variables. +If a formula is long enough deparse() will give two lines, hence the +extra paste call to re-collapse it into one. +\begin{nwchunk} +\nwhyp{survexp-setup-rmap3}{survexp-setup-rmap}{survexp-setup-rmap2}{survexp-setup-rmap4}= + # Create a temporary formula, used only in the call to model.frame + newvar <- all.vars(rcall) + if (length(newvar) > 0) \{ + temp <- paste(paste(deparse(Terms), collapse=""), + paste(newvar, collapse='+'), sep='+') + tform$formula <- as.formula(temp, environment(Terms)) + \} +\end{nwchunk} + +If the user data has 0 rows, e.g. from a mistaken \Verb!subset! statement +that eliminated all subjects, we need to stop early. Otherwise the +.C code fails in a nasty way. +\begin{nwchunk} +\nwhyp{survexp-setup4}{survexp-setup}{survexp-setup3}{survexp-setup5}= + n <- nrow(mf) + if (n==0) stop("Data set has 0 rows") + if (!missing(se.fit) && se.fit) + warning("se.fit value ignored") + + weights <- model.extract(mf, 'weights') + if (length(weights) ==0) weights <- rep(1.0, n) + if (class(ratetable)=='ratetable' && any(weights !=1)) + warning("weights ignored") + + if (any(attr(Terms, 'order') >1)) + stop("Survexp cannot have interaction terms") + if (!missing(times)) \{ + if (any(times<0)) stop("Invalid time point requested") + if (length(times) >1 ) + if (any(diff(times)<0)) stop("Times must be in increasing order") + \} +\end{nwchunk} + +If a response variable was given, we only need the times and not the +status. To be correct, +computations need to be done for each of the times given in +the \Verb!times! argument as well as for each of the unique y values. +This ends up as the vector \Verb!newtime!. If a \Verb?times? argument was +given we will subset down to only those values at the end. +For a population rate table and the Ederer method the times argument is +required. +\begin{nwchunk} +\nwhypb{survexp-setup5}{survexp-setup}{survexp-setup4}= + Y <- model.extract(mf, 'response') + no.Y <- is.null(Y) + if (no.Y) \{ + if (missing(times)) \{ + if (is.ratetable(ratetable)) + stop("either a times argument or a response is needed") + \} + else newtime <- times + \} + else \{ + if (is.matrix(Y)) \{ + if (is.Surv(Y) && attr(Y, 'type')=='right') Y <- Y[,1] + else stop("Illegal response value") + \} + if (any(Y<0)) stop ("Negative follow up time") + # if (missing(npoints)) temp <- unique(Y) + # else temp <- seq(min(Y), max(Y), length=npoints) + temp <- unique(Y) + if (missing(times)) newtime <- sort(temp) + else newtime <- sort(unique(c(times, temp[temp nstate)) + stop("numeric state is out of range") + \} + else if (is.list(x$left) && names(x$left)[1] == "stateid")\{ + if (is.null(x$left$value)) + stop("state variable with no list of values: ",x$left$stateid) + else \{ + if (any(k= is.na(match(x$left$stateid, names(statedata))))) + stop(x$left$stateid[k], ": state variable not found") + zz <- statedata[[x$left$stateid]] + if (any(k= is.na(match(x$left$value, zz)))) + stop(x$left$value[k], ": state value not found") + temp1 <- which(zz %in% x$left$value) + \} + \} + else \{ + k <- match(x$left, statedata$state) + if (any(is.na(k))) stop(x$left[is.na(k)], ": state not found") + temp1 <- which(statedata$state %in% x$left) + \} + + # right of colon + if (!is.list(x$right) && length(x$right) ==1 && x$right ==0) + temp2 <- 1:nrow(statedata) + else if (is.numeric(x$right)) \{ + temp2 <- as.integer(x$right) + if (any(temp2 != x$right)) stop("non-integer state number") + if (any(temp2 <1 | temp2> nstate)) + stop("numeric state is out of range") + \} + else if (is.list(x$right) && names(x$right)[1] == "stateid") \{ + if (is.null(x$right$value)) + stop("state variable with no list of values: ",x$right$stateid) + else \{ + if (any(k= is.na(match(x$right$stateid, names(statedata))))) + stop(x$right$stateid[k], ": state variable not found") + zz <- statedata[[x$right$stateid]] + if (any(k= is.na(match(x$right$value, zz)))) + stop(x$right$value[k], ": state value not found") + temp2 <- which(zz %in% x$right$value) + \} + \} + else \{ + k <- match(x$right, statedata$state) + if (any(is.na(k))) stop(x$right[k], ": state not found") + temp2 <- which(statedata$state %in% x$right) + \} + + + state1 <- c(state1, rep(temp1, length(temp2))) + state2 <- c(state2, rep(temp2, each=length(temp1))) + \} +\end{nwchunk} +At the end it has created to vectors state1 and state2 listing all +the pairs of states that are indicated. + +The init clause (initial values) are gathered but not checked: +we don't yet know how many columns a term will expand into. +tmap is a 3 way array: term, state1, state2 containing coefficient numbers and +zeros. + +\begin{nwchunk} +\nwhypb{parse-tmap2}{parse-tmap}{parse-tmap1}= + for (i in 1:length(covar1$rhs)) \{ + rhs <- covar1$rhs[[i]] + lhs <- covar1$lhs[[i]] # one rhs and one lhs per formula + + \nwhypb{parse-lmatch2}{parse-lmatch}{parse-lmatch1} + npair <- length(state1) # number of state:state pairs for this line + + # update tmap for this set of transitions + # first, what variables are mentioned, and check for errors + rterm <- terms(rhs$formula) + rindex <- 1L + termmatch(attr(rterm, "factors"), allterm) + + # the update.formula function is good at identifying changes + # formulas that start with "- x" have to be pasted on carefully + temp <- substring(deparse(rhs$formula, width.cutoff=500), 2) + if (substring(temp, 1,1) == '-') dummy <- formula(paste("~ .", temp)) + else dummy <- formula(paste("~. +", temp)) + + rindex1 <- termmatch(attr(terms(dformula), "factors"), allterm) + rindex2 <- termmatch(attr(terms(update(dformula, dummy)), "factors"), + allterm) + dropped <- 1L + rindex1[is.na(match(rindex1, rindex2))] # remember the intercept + if (length(dropped) >0) \{ + for (k in 1:npair) tmap[dropped, state1[k], state2[k]] <- 0 + \} + + # grab initial values + if (length(rhs$ival)) + inits <- c(inits, list(term=rindex, state1=state1, + state2= state2, init= rhs$ival)) + + # adding -1 to the front is a trick, to check if there is a "+1" term + dummy <- ~ -1 + x + dummy[[2]][[3]] <- rhs$formula + if (attr(terms(dummy), "intercept") ==1) rindex <- c(1L, rindex) + + # an update of "- sex" won't generate anything to add + # dmap is simply an indexed set of unique values to pull from, so that + # no number is used twice + if (length(rindex) > 0) \{ # rindex = things to add + if (rhs$common) \{ + j <- dmap[rindex, state1[1], state2[1]] + for(k in 1:npair) tmap[rindex, state1[k], state2[k]] <- j + \} + else \{ + for (k in 1:npair) + tmap[rindex, state1[k], state2[k]] <- dmap[rindex, state1[k], state2[k]] + \} + \} + + # Deal with the shared argument, using - for a separate coef + if (rhs$shared && npair>1) \{ + j <- dmap[1, state1[1], state2[1]] + for (k in 2:npair) + tmap[1, state1[k], state2[k]] <- -j + \} + \} +\end{nwchunk} + + +Fold the 3-dimensional tmap into a matrix with terms as rows +and one column for each transition that actually occured. + +\begin{nwchunk} +\nwhypb{parse-finish2}{parse-finish}{parse-finish1}= + i <- match("(censored)", colnames(transitions), nomatch=0) + if (i==0) t2 <- transitions + else t2 <- transitions[,-i, drop=FALSE] # transitions to 'censor' don't count + indx1 <- match(rownames(t2), states) + indx2 <- match(colnames(t2), states) + tmap2 <- matrix(0L, nrow= 1+nterm, ncol= sum(t2>0)) + + trow <- row(t2)[t2>0] + tcol <- col(t2)[t2>0] + for (i in 1:nrow(tmap2)) \{ + for (j in 1:ncol(tmap2)) + tmap2[i,j] <- tmap[i, indx1[trow[j]], indx2[tcol[j]]] + \} + + # Remember which hazards had ph + # tmap2[1,] is the 'intercept' row + # If the hazard for colum 6 is proportional to the hazard for column 2, + # the tmap2[1,2] = tmap[1,6], and phbaseline[6] =2 + temp <- tmap2[1,] + tmap2[1,] <- match(abs(tmap2[1,]), unique(abs(temp))) + phbaseline <- ifelse(temp<0, tmap2[1,], 0) + + if (nrow(tmap2) > 1) + tmap2[-1,] <- match(tmap2[-1,], unique(c(0L, tmap2[-1,]))) -1L + + dimnames(tmap2) <- list(c("(Baseline)", colnames(allterm)), + paste(indx1[trow], indx2[tcol], sep=':')) + # mapid gives the from,to for each realized state + list(tmap = tmap2, inits=inits, mapid= cbind(from=indx1[trow], to=indx2[tcol]), + phbaseline = phbaseline) +\end{nwchunk} + + +Last is a helper routine that converts tmap, which has one row per term, +into cmap, which has one row per coefficient. Both have one column per +transition. +It uses the assign attribute of the X matrix along with the column names. + +Consider the model \code{~ x1 + strata(x2) + factor(x3)} where x3 has 4 levels. +The Xassign vector will be 1, 3, 3, 3, since it refers to terms and there are 3 +columns of X for term number 3. +If there were an intercept the first column of X +would be a 1 and Xassign would be 0, 1, 3, 3, 3. + +Let's say that there were 3 transitions and tmap looks like this: +\begin{tabular}{rccc} + & 1:2 & 1:3 & 2:3 \\ +(Baseline) & 1 & 2 & 3 \\ + x1 & 1 & 4 & 4 \\ + strata(x2) & 2 & 5 & 6 \\ + factor(x3) & 3 & 3 & 7 +\end{tabular} +The cmap matrix will ignore rows 1 and 3 since they do not correspond to +coefficients in the model. + +\begin{nwchunk} +\nwhypb{parsecovar5}{parsecovar}{parsecovar4}= + parsecovar3 <- function(tmap, Xcol, Xassign, phbaseline=NULL) \{ + # sometime X will have an intercept, sometimes not; cmap never does + hasintercept <- (Xassign[1] ==0) + + ptemp <- phbaseline[phbaseline >0] + nph.coef <- length(ptemp) + nph.row <- length(unique(ptemp)) + cmap <- matrix(0L, length(Xcol) + nph.row - hasintercept, ncol(tmap)) + uterm <- unique(Xassign[Xassign != 0]) # terms that will have coefficients + + xcount <- table(factor(Xassign, levels=1:max(Xassign))) + mult <- 1+ max(xcount) # temporary scaling + + ii <- 0 + for (i in uterm) \{ + k <- seq_len(xcount[i]) + for (j in 1:ncol(tmap)) + cmap[ii+k, j] <- if(tmap[i+1,j]==0) 0 else tmap[i+1,j]*mult +k + ii <- ii + max(k) + \} + + if (nph.row > 0) \{ + i <- length(Xcol)- hasintercept # non-ph rows in cmap + j <- cbind(i+ match(ptemp, unique(ptemp)), which(phbaseline>0)) + cmap[j] <- max(cmap) + seq(along.with =ptemp) + newname <- paste0("ph(",colnames(tmap)[unique(ptemp)], ")") + \} else newname <- NULL + + # renumber coefs as 1, 2, 3, ... + cmap[,] <- match(cmap, sort(unique(c(0L, cmap)))) -1L + + colnames(cmap) <- colnames(tmap) + if (hasintercept) rownames(cmap) <- c(Xcol[-1], newname) + else rownames(cmap) <- c(Xcol, newname) + + cmap + \} +\end{nwchunk} +\section{Person years} +The person years routine and the expected survival code are the +two parts of the survival package that make use of external +rate tables, of which the United States mortality tables \code{survexp.us} +and \code{survexp.usr} are examples contained in the package. +The arguments for pyears are +\begin{description} + \item[formula] The model formula. The right hand side consists of grouping + variables and is essentially identical to [[survfit]], the result of the + model will be a table of results with dimensions determined from the + right hand variables. The formula can include an optional [[ratetable]] + directive; but this style has been superseded by the [[rmap]] argument. + \item [data, weights, subset, na.action] as usual + \item[rmap] an optional mapping for rate table variables, see more below. + \item[ratetable] the population rate table to use as a reference. This can + either be a ratetable object or a previously fitted Cox model + \item[scale] Scale the resulting output times, e.g., 365.25 to turn days into + years. + \item[expect] Should the output table include the expected number of + events, or the expected number of person-years of observation? + \item[model, x, y] as usual + \item[data.frame] if true the result is returned as a data frame, if false + as a set of tables. +\end{description} + +\begin{nwchunk} +\nwhypn{pyears}= + pyears <- function(formula, data, + weights, subset, na.action, rmap, + ratetable, scale=365.25, expect=c('event', 'pyears'), + model=FALSE, x=FALSE, y=FALSE, data.frame=FALSE) \{ + + \nwhypf{pyears-setup1}{pyears-setup}{pyears-setup2} + \nwhypf{pyears-compute1}{pyears-compute}{pyears-compute2} + \nwhypf{pyears-finish1}{pyears-finish}{pyears-finish2} + \} +\end{nwchunk} + +Start out with the standard model processing, which involves making a copy +of the input call, but keeping only the arguments we want. +We then process the special argument \Verb!rmap!. This is discussed in the +section on the \Verb!survexp! function so we need not repeat the +explantation here. +\begin{nwchunk} +\nwhyp{pyears-setup2}{pyears-setup}{pyears-setup1}{pyears-setup3}= + expect <- match.arg(expect) + Call <- match.call() + + # create a call to model.frame() that contains the formula (required) + # and any other of the relevant optional arguments + # then evaluate it in the proper frame + indx <- match(c("formula", "data", "weights", "subset", "na.action"), + names(Call), nomatch=0) + if (indx[1] ==0) stop("A formula argument is required") + tform <- Call[c(1,indx)] # only keep the arguments we wanted + tform[[1L]] <- quote(stats::model.frame) # change the function called + + Terms <- if(missing(data)) terms(formula, 'ratetable') + else terms(formula, 'ratetable',data=data) + if (any(attr(Terms, 'order') >1)) + stop("Pyears cannot have interaction terms") + + rate <- attr(Terms, "specials")$ratetable + if (length(rate) >0 || !missing(rmap) || !missing(ratetable)) \{ + has.ratetable <- TRUE + if(length(rate) > 1) + stop("Can have only 1 ratetable() call in a formula") + if (missing(ratetable)) stop("No rate table specified") + + \nwhypb{survexp-setup-rmap4}{survexp-setup-rmap}{survexp-setup-rmap3} + \} + else has.ratetable <- FALSE + + mf <- eval(tform, parent.frame()) + + Y <- model.extract(mf, 'response') + if (is.null(Y)) stop ("Follow-up time must appear in the formula") + if (!is.Surv(Y))\{ + if (any(Y <0)) stop ("Negative follow up time") + Y <- as.matrix(Y) + if (ncol(Y) >2) stop("Y has too many columns") + \} + else \{ + stype <- attr(Y, 'type') + if (stype == 'right') \{ + if (any(Y[,1] <0)) stop("Negative survival time") + nzero <- sum(Y[,1]==0 & Y[,2] ==1) + if (nzero >0) + warning(paste(nzero, + "observations with an event and 0 follow-up time,", + "any rate calculations are statistically questionable")) + \} + else if (stype != 'counting') + stop("Only right-censored and counting process survival types are supported") + \} + + n <- nrow(Y) + if (is.null(n) || n==0) stop("Data set has 0 observations") + + weights <- model.extract(mf, 'weights') + if (is.null(weights)) weights <- rep(1.0, n) +\end{nwchunk} + +The next step is to check out the ratetable. +For a population rate table a set of consistency checks is done by the +\Verb!match.ratetable! function, giving a set of sanitized indices \Verb?R?. +This function wants characters turned to factors. +For a Cox model \Verb!R! will be a model matix whose covariates are coded +in exactly the same way that variables were coded in the original +Cox model. We call the model.matrix.coxph function so as not to have to +repeat the steps found there (remove cluster statements, etc). +\begin{nwchunk} +\nwhyp{pyears-setup3}{pyears-setup}{pyears-setup2}{pyears-setup4}= + # rdata contains the variables matching the ratetable + if (has.ratetable) \{ + rdata <- data.frame(eval(rcall, mf), stringsAsFactors=TRUE) + if (is.ratetable(ratetable)) \{ + israte <- TRUE + rtemp <- match.ratetable(rdata, ratetable) + R <- rtemp$R + \} + else if (inherits(ratetable, 'coxph') && !inherits(ratetable, "coxphms")) \{ + israte <- FALSE + Terms <- ratetable$terms + if (!is.null(attr(Terms, 'offset'))) + stop("Cannot deal with models that contain an offset") + strats <- attr(Terms, "specials")$strata + if (length(strats)) + stop("pyears cannot handle stratified Cox models") + + if (any(names(mf[,rate]) != attr(ratetable$terms, 'term.labels'))) + stop("Unable to match new data to old formula") + R <- model.matrix.coxph(ratetable, data=rdata) + \} + else stop("Invalid ratetable") + \} +\end{nwchunk} + +Now we process the non-ratetable variables. +Those of class \Verb!tcut! set up time-dependent classes. For +these the cutpoints attribute sets the intervals, if there +were 4 cutpoints of 1, 5,6, and 10 the 3 intervals will be 1-5, +5-6 and 6-10, and odims will be 3. +All other variables are treated as factors. +\begin{nwchunk} +\nwhypb{pyears-setup4}{pyears-setup}{pyears-setup3}= + ovars <- attr(Terms, 'term.labels') + if (length(ovars)==0) \{ + # no categories! + X <- rep(1,n) + ofac <- odim <- odims <- ocut <- 1 + \} + else \{ + odim <- length(ovars) + ocut <- NULL + odims <- ofac <- double(odim) + X <- matrix(0, n, odim) + outdname <- vector("list", odim) + names(outdname) <- attr(Terms, 'term.labels') + for (i in 1:odim) \{ + temp <- mf[[ovars[i]]] + if (inherits(temp, 'tcut')) \{ + X[,i] <- temp + temp2 <- attr(temp, 'cutpoints') + odims[i] <- length(temp2) -1 + ocut <- c(ocut, temp2) + ofac[i] <- 0 + outdname[[i]] <- attr(temp, 'labels') + \} + else \{ + temp2 <- as.factor(temp) + X[,i] <- temp2 + temp3 <- levels(temp2) + odims[i] <- length(temp3) + ofac[i] <- 1 + outdname[[i]] <- temp3 + \} + \} + \} +\end{nwchunk} + +Now do the computations. +The code above has separated out the variables into 3 groups: +\begin{itemize} + \item The variables in the rate table. These determine where we + \emph{start} in the rate table with respect to retrieving the relevant + death rates. For the US table [[survexp.us]] this will be the date of + study entry, age (in days) at study entry, and sex of each subject. + \item The variables on the right hand side of the model. These are + interpreted almost identically to a call to [[table]], with special + treatment for those of class \emph{tcut}. + \item The response variable, which tells the number of days of follow-up + and optionally the status at the end of follow-up. +\end{itemize} + +Start with the rate table variables. +There is an oddity about US rate tables: the entry for age (year=1970, +age=55) contains the daily rate for anyone who turns 55 in that year, +from their birthday forward for 365 days. So if your birthday is on +Oct 2, the 1970 table applies from 2Oct 1970 to 1Oct 1971. The +underlying C code wants to make the 1970 rate table apply from 1Jan +1970 to 31Dec 1970. The easiest way to finess this is to fudge +everyone's enter-the-study date. If you were born in March but +entered in April, make it look like you entered in Febuary; that way +you get the first 11 months at the entry year's rates, etc. The birth +date is entry date - age in days (based on 1/1/1970). + +The other aspect of the rate tables is that ``older style'' tables, those that +have the factor attribute, contained only decennial data which the C code would +interpolate on the fly. The value of \Verb!atts$factor! was 10 indicating that +there are 10 years in the interpolation interval. The newer tables do not +do this and the C code is passed a 0/1 for continuous (age and year) versus +discrete (sex, race). +\begin{nwchunk} +\nwhypb{pyears-compute2}{pyears-compute}{pyears-compute1}= + ocut <-c(ocut,0) #just in case it were of length 0 + osize <- prod(odims) + if (has.ratetable) \{ #include expected + atts <- attributes(ratetable) + datecheck <- function(x) + inherits(x, c("Date", "POSIXt", "date", "chron")) + cuts <- lapply(attr(ratetable, "cutpoints"), function(x) + if (!is.null(x) & datecheck(x)) ratetableDate(x) else x) + + if (is.null(atts$type)) \{ + #old stlye table + rfac <- atts$factor + us.special <- (rfac >1) + \} + else \{ + rfac <- 1*(atts$type ==1) + us.special <- (atts$type==4) + \} + if (any(us.special)) \{ #special handling for US pop tables + if (sum(us.special) > 1) stop("more than one type=4 in a rate table") + # Someone born in June of 1945, say, gets the 1945 US rate until their + # next birthday. But the underlying logic of the code would change + # them to the 1946 rate on 1/1/1946, which is the cutpoint in the + # rate table. We fudge by faking their enrollment date back to their + # birth date. + # + # The cutpoint for year has been converted to days since 1/1/1970 by + # the ratetableDate function. (Date objects in R didn't exist when + # rate tables were conceived.) + if (is.null(atts$dimid)) dimid <- names(atts$dimnames) + else dimid <- atts$dimid + cols <- match(c("age", "year"), dimid) + if (any(is.na(cols))) + stop("ratetable does not have expected shape") + + # The format command works for Dates, use it to get an offset + bdate <- as.Date("1970-01-01") + (R[,cols[2]] - R[,cols[1]]) + byear <- format(bdate, "%Y") + offset <- as.numeric(bdate - as.Date(paste0(byear, "-01-01"))) + R[,cols[2]] <- R[,cols[2]] - offset + + # Doctor up "cutpoints" - only needed for (very) old style rate tables + # for which the C code does interpolation on the fly + if (any(rfac >1)) \{ + temp <- which(us.special) + nyear <- length(cuts[[temp]]) + nint <- rfac[temp] #intervals to interpolate over + cuts[[temp]] <- round(approx(nint*(1:nyear), cuts[[temp]], + nint:(nint*nyear))$y - .0001) + \} + \} + docount <- is.Surv(Y) + temp <- .C(Cpyears1, + as.integer(n), + as.integer(ncol(Y)), + as.integer(is.Surv(Y)), + as.double(Y), + as.double(weights), + as.integer(length(atts$dim)), + as.integer(rfac), + as.integer(atts$dim), + as.double(unlist(cuts)), + as.double(ratetable), + as.double(R), + as.integer(odim), + as.integer(ofac), + as.integer(odims), + as.double(ocut), + as.integer(expect=='event'), + as.double(X), + pyears=double(osize), + pn =double(osize), + pcount=double(if(docount) osize else 1), + pexpect=double(osize), + offtable=double(1))[18:22] + \} + else \{ #no expected + docount <- as.integer(ncol(Y) >1) + temp <- .C(Cpyears2, + as.integer(n), + as.integer(ncol(Y)), + as.integer(docount), + as.double(Y), + as.double(weights), + as.integer(odim), + as.integer(ofac), + as.integer(odims), + as.double(ocut), + as.double(X), + pyears=double(osize), + pn =double(osize), + pcount=double(if (docount) osize else 1), + offtable=double(1)) [11:14] + \} +\end{nwchunk} + +Create the output object. +\begin{nwchunk} +\nwhypb{pyears-finish2}{pyears-finish}{pyears-finish1}= + has.tcut <- any(sapply(mf, function(x) inherits(x, 'tcut'))) + if (data.frame) \{ + # Create a data frame as the output, rather than a set of + # rate tables + if (length(ovars) ==0) \{ # no variables on the right hand side + keep <- TRUE + df <- data.frame(pyears= temp$pyears/scale, + n = temp$n) + \} + else \{ + keep <- (temp$pyears >0) # what rows to keep in the output + # grab prototype rows from the model frame, this preserves class + # (unless it is a tcut variable, then we know what to do) + tdata <- lapply(1:length(ovars), function(i) \{ + temp <- mf[[ovars[i]]] + if (inherits(temp, "tcut")) \{ #if levels are numeric, return numeric + if (is.numeric(outdname[[i]])) outdname[[i]] + else factor(outdname[[i]], outdname[[i]]) # else factor + \} + else temp[match(outdname[[i]], temp)] + \}) + tdata$stringsAsFactors <- FALSE # argument for expand.grid + df <- do.call("expand.grid", tdata)[keep,,drop=FALSE] + names(df) <- ovars + df$pyears <- temp$pyears[keep]/scale + df$n <- temp$pn[keep] + \} + row.names(df) <- NULL # toss useless 'creation history' + if (has.ratetable) df$expected <- temp$pexpect[keep] + if (expect=='pyears') df$expected <- df$expected/scale + if (docount) df$event <- temp$pcount[keep] + # if any of the predictors were factors, make them factors in the output + for (i in 1:length(ovars))\{ + if (is.factor( mf[[ovars[i]]])) + df[[ovars[i]]] <- factor(df[[ovars[i]]], levels( mf[[ovars[i]]])) + \} + + out <- list(call=Call, + data= df, offtable=temp$offtable/scale, + tcut=has.tcut) + if (has.ratetable && !is.null(rtemp$summ)) + out$summary <- rtemp$summ + \} + + else if (prod(odims) ==1) \{ #don't make it an array + out <- list(call=Call, pyears=temp$pyears/scale, n=temp$pn, + offtable=temp$offtable/scale, tcut = has.tcut) + if (has.ratetable) \{ + out$expected <- temp$pexpect + if (expect=='pyears') out$expected <- out$expected/scale + if (!is.null(rtemp$summ)) out$summary <- rtemp$summ + \} + if (docount) out$event <- temp$pcount + \} + else \{ + out <- list(call = Call, + pyears= array(temp$pyears/scale, dim=odims, dimnames=outdname), + n = array(temp$pn, dim=odims, dimnames=outdname), + offtable = temp$offtable/scale, tcut=has.tcut) + if (has.ratetable) \{ + out$expected <- array(temp$pexpect, dim=odims, dimnames=outdname) + if (expect=='pyears') out$expected <- out$expected/scale + if (!is.null(rtemp$summ)) out$summary <- rtemp$summ + \} + if (docount) + out$event <- array(temp$pcount, dim=odims, dimnames=outdname) + \} + out$observations <- nrow(mf) + out$terms <- Terms + na.action <- attr(mf, "na.action") + if (length(na.action)) out$na.action <- na.action + if (model) out$model <- mf + else \{ + if (x) out$x <- X + if (y) out$y <- Y + \} + class(out) <- 'pyears' + out +\end{nwchunk} +\subsection{Print and summary} +The print function for pyear gives a very abbreviated +printout: just a few lines. +It works with pyears objects with or without a data component. + +\begin{nwchunk} +\nwhypf{print.pyears1}{print.pyears}{print.pyears2}= + print.pyears <- function(x, ...) \{ + if (!is.null(cl<- x$call)) \{ + cat("Call:{\textbackslash}n") + dput(cl) + cat("{\textbackslash}n") + \} + + if (is.null(x$data)) \{ + if (!is.null(x$event)) + cat("Total number of events:", format(sum(x$event)), "{\textbackslash}n") + cat ( "Total number of person-years tabulated:", + format(sum(x$pyears)), + "{\textbackslash}nTotal number of person-years off table:", + format(x$offtable), "{\textbackslash}n") + \} + else \{ + if (!is.null(x$data$event)) + cat("Total number of events:", format(sum(x$data$event)), "{\textbackslash}n") + cat ( "Total number of person-years tabulated:", + format(sum(x$data$pyears)), + "{\textbackslash}nTotal number of person-years off table:", + format(x$offtable), "{\textbackslash}n") + \} + if (!is.null(x$summary)) \{ + cat("Matches to the chosen rate table:{\textbackslash}n ", + x$summary) + \} + cat("Observations in the data set:", x$observations, "{\textbackslash}n") + if (!is.null(x$na.action)) + cat(" (", naprint(x$na.action), "){\textbackslash}n", sep='') + cat("{\textbackslash}n") + invisible(x) + \} +\end{nwchunk} + +The summary function attempts to create output that looks like a +pandoc table, which in turn makes it mesh nicely with Rstudio. +Pandoc has 4 types of tables: with and without vertical bars and +with single or multiple rows per cell. +If the pyears object has only a single dimension then our output will +be a simple table with a row or column for each of the output +types (see the vertical argument). +The result will be a simple table or a ``pipe'' table depending on the +vline argument. +For two or more dimensions the output follows the usual R strategy for printing +an array, but with each ``cell'' containing all of the summaries for that +combination of predictors, thus giving +either a ``multiline'' or ``grid'' table. +The default values of no vertical lines makes the tables +appropriate for non-pandoc output such as a terminal session. + +\begin{nwchunk} +\nwhypb{print.pyears2}{print.pyears}{print.pyears1}= + summary.pyears <- function(object, header=TRUE, call=header, + n= TRUE, event=TRUE, pyears=TRUE, + expected = TRUE, rate = FALSE, rr = expected, + ci.r = FALSE, ci.rr = FALSE, totals=FALSE, + legend=TRUE, vline = FALSE, vertical = TRUE, + nastring=".", conf.level=0.95, + scale= 1, ...) \{ + # Usual checks + if (!inherits(object, "pyears")) + stop("input must be a pyears object") + temp <- c(is.logical(header), is.logical(call), is.logical(n), + is.logical(event) , is.logical(pyears), is.logical(expected), + is.logical(rate), is.logical(ci.r), is.logical(rr), + is.logical(ci.rr), is.logical(vline), is.logical(vertical), + is.logical(legend), is.logical(totals)) + tname <- c("header", "call", "n", "event", "pyears", "expected", + "rate", "ci.r", "rr", "ci.rr", "vline", "vertical", + "legend", "totals") + if (any(!temp) || length(temp) != 14 || any(is.na(temp))) \{ + stop("the ", paste(tname[!temp], collapse=", "), + "argument(s) must be single logical values") + \} + if (!is.numeric(conf.level) || conf.level <=0 || conf.level >=1 | + length(conf.level) > 1 || is.na(conf.level) > 1) + stop("conf.level must be a single numeric between 0 and 1") + if (is.na(scale) || !is.numeric(scale) || length(scale) !=1 || scale <=0) + stop("scale must be a value > 0") + + vname <- attr(terms(object), "term.labels") #variable names + + if (!is.null(object$data)) \{ + # Extra work: restore the tables which had been unpacked into a df + # All of the categories are factors in this case + tdata <- object$data[vname] # the conditioning variables + dname <- lapply(tdata, function(x) \{ + if (is.factor(x)) levels(x) else sort(unique(x))\}) # dimnames + dd <- sapply(dname, length) # dim of arrays + index <- tapply(tdata[,1], tdata) + restore <- c('n', 'event', 'pyears', 'expected') #do these, if present + restore <- restore[restore %in% names(object$data)] + new <- lapply(object$data[restore], + function(x) \{ + temp <- array(0L, dim=dd, dimnames=dname) + temp[index] <- x + temp\} ) + object <- c(object, new) + \} + + if (is.null(object$expected)) \{ + expected <- FALSE + rr <- FALSE + ci.rr <- FALSE + \} + if (is.null(object$event)) \{ + event <- FALSE + rate <- FALSE + ci.r <- FALSE + rr <- FALSE + ci.rr <- FALSE + \} + + # print out the front matter + if (call && !is.null(object$call)) \{ + cat("Call: ") + dput(object$call) + cat("{\textbackslash}n") + \} + if (header) \{ + cat("number of observations =", object$observations) + if (length(object$omit)) + cat(" (", naprint(object$omit), "){\textbackslash}n", sep="") + else cat("{\textbackslash}n") + if (object$offtable > 0) + cat(" Total time lost (off table)", format(object$offtable), "{\textbackslash}n") + cat("{\textbackslash}n") + \} + + # Add in totals if requested + if (totals) \{ + # if the pyear object was based on any time dependent cuts, then + # the "n" component cannot be totaled up. + tcut <- if (is.null(object$tcut)) TRUE else object$tcut + object$n <- pytot(object$n, na=tcut) + object$pyears <- pytot(object$pyears) + if (event) object$event <- pytot(object$event) + if (expected) object$expected <- pytot(object$expected) + \} + + dd <- dim(object$n) + vname <- attr(terms(object), "term.labels") #variable names + \nwhypf{pyears-list1}{pyears-list}{pyears-list2} + if (length(dd) ==1) \{ + # 1 dimensional table + \nwhypf{pyears-table11}{pyears-table1}{pyears-table12} + \} else \{ + # more than 1 dimension + \nwhypf{pyears-table21}{pyears-table2}{pyears-table22} + \} + invisible(object) + \} + + \nwhypf{pyears-charfun1}{pyears-charfun}{pyears-charfun2} +\end{nwchunk} + +\begin{nwchunk} +\nwhypb{pyears-list2}{pyears-list}{pyears-list1}= + # Put the elements to be printed onto a list + pname <- (tname[3:6])[c(n, event, pyears, expected)] + plist <- object[pname] + + if (rate) \{ + pname <- c(pname, "rate") + plist$r <- scale* object$event/object$pyears + \} + if (ci.r) \{ + pname <- c(pname, "ci.r") + plist$ci.r <- cipoisson(object$event, object$pyears, p=conf.level) *scale + \} + if (rr) \{ + pname <- c(pname, "rr") + plist$rr <- object$event/object$expected + \} + if (ci.rr) \{ + pname <- c(pname, "ci.rr") + plist$ci.rr <- cipoisson(object$event, object$expected, p=conf.level) + \} + + rname <- c(n = "N", event="Events", + pyears= "Time", expected= "Expected events", + rate = "Event rate", ci.r = "CI (rate)", + rr= "Obs/Exp", ci.rr= "CI (O/E)") + rname <- rname[pname] +\end{nwchunk} + +If there is only one dimension to the table we can forgo the top legend +and use the object names as one of the margins. +If \code{vertical=TRUE} the output types are vertical, otherwise they +are horizontal. Format each element of the output separately. + + +\begin{nwchunk} +\nwhypb{pyears-table12}{pyears-table1}{pyears-table11}= + cname <- names(object$n) #category names + + if (vertical) \{ + # The person-years objects list across the top, categories up and down + # This makes columns line up in a standard "R" way + # The first column label is the variable name, content is the categories + plist <- lapply(plist, pformat, nastring, ...) # make it character + pcol <- sapply(plist, function(x) nchar(x[1])) #width of each one + colwidth <- pmax(pcol, nchar(rname)) +2 + for (i in 1:length(plist)) + plist[[i]] <- strpad(plist[[i]], colwidth[i]) + + colwidth <- c(max(nchar(vname), nchar(cname)) +2, colwidth) + leftcol <- list(strpad(cname, colwidth[1])) + header <- strpad(c(vname, rname), colwidth) + \} + else \{ + # in this case each column will have different types of objects in it + # alignment is the nuisance + newmat <- pybox(plist, length(plist[[1]]), nastring, ...) + colwidth <- pmax(nchar(cname), apply(nchar(newmat), 1, max)) +2 + # turn the list sideways + plist <- split(newmat, row(newmat)) + for (i in 1:length(plist)) + plist[[i]] <- strpad(plist[[i]], colwidth[i]) + + colwidth <- c(max(nchar(vname), nchar(rname)) +2, colwidth) + leftcol <- list(strpad(rname, colwidth[1])) + header <- strpad(c(vname, cname), colwidth) + \} + + # Now print it + if (vline) \{ # use a pipe table + cat(paste(header, collapse = "|"), "{\textbackslash}n") + cat(paste(strpad("-", colwidth, "-"), collapse="|"), "{\textbackslash}n") + + temp <- do.call("paste", c(leftcol, plist, list(sep ="|"))) + cat(temp, sep= '{\textbackslash}n') + \} + else \{ + cat(paste(header, collapse = " "), "{\textbackslash}n") + cat(paste(strpad("-", colwidth, "-"), collapse=" "), "{\textbackslash}n") + temp <- do.call("paste", c(leftcol, plist, list(sep =" "))) + cat(temp, sep='{\textbackslash}n') + \} +\end{nwchunk} + +When there are more than one category in the pyears object then +we use a special layout. Each 'cell' of the printed table has +all of the values in it. + +\begin{nwchunk} +\nwhypb{pyears-table22}{pyears-table2}{pyears-table21}= + if (header) \{ + # the header is itself a table + width <- max(nchar(rname)) + if (vline) \{ + cat('+', strpad('-', width, '-'), "+{\textbackslash}n", sep="") + cat(paste0('|',strpad(rname, width), '|'), sep='{\textbackslash}n') + cat('+', strpad('-', width, '-'), "+{\textbackslash}n{\textbackslash}n", sep="") + \} else \{ + cat(strpad('-', width, '-'), "{\textbackslash}n") + cat(strpad(rname, width), sep='{\textbackslash}n') + cat(strpad('-', width, '-'), "{\textbackslash}n{\textbackslash}n") + \} + \} + tname <- vname[1:2] #names for the row and col + rowname <- dimnames(object$n)[[1]] + colname <- dimnames(object$n)[[2]] + if (length(dd) > 2) + newmat <- pybox(plist, c(dd[1],dd[2], prod(dd[-(1:2)])), + nastring, ...) + else newmat <- pybox(plist, dd, nastring, ...) + + if (length(dd) > 2) \{ + newmat <- pybox(plist, c(dd[1],dd[2], prod(dd[-(1:2)])), + nastring, ...) + outer.label <- do.call("expand.grid", dimnames(object$n)[-(1:2)]) + temp <- names(outer.label) + for (i in 1:nrow(outer.label)) \{ + # first the caption, then data + cat(paste(":", paste(temp, outer.label[i,], sep="=")), '{\textbackslash}n') + pyshow(newmat[,,i,], tname, rowname, colname, vline) + \} + \} + else \{ + newmat <- pybox(plist, dd, nastring, ...) + pyshow(newmat, tname, rowname, colname, vline) + \} +\end{nwchunk} + + +Here are some character manipulation functions. The stringi package has +more elegant versions of the pad function, but we don't need the speed. +No one is going to print out thousands of lines. + +\begin{nwchunk} +\nwhyp{pyears-charfun2}{pyears-charfun}{pyears-charfun1}{pyears-charfun3}= + strpad <- function(x, width, pad=' ') \{ + # x = the string(s) to be padded out + # width = width of desired string. + nc <- nchar(x) + added <- width - nc + + left <- pmax(0, floor(added/2)) # can't add negative space + right <- pmax(0, width - (nc + left)) # right will be >= left + + if (all(right <=0)) \{ + if (length(x) >= length(width)) x # nothing needs to be done + else rep(x, length=length(width)) + \} + else \{ + # Each pad could be a different length. + # Make a long string from which we can take a portion + longpad <- paste(rep(pad, max(right)), collapse='') + paste0(substring(longpad, 1, left), x, substring(longpad,1, right)) + \} + \} + + pformat <- function(x, nastring, ...) \{ + # This is only called for single index tables, in vertical mode + # Any matrix will be a confidence interval + if (is.matrix(x)) + ret <- paste(ifelse(is.na(x[,1]), nastring, + format(x[,1], ...)), "-", + ifelse(is.na(x[,2]), nastring, + format(x[,2], ...))) + else ret <- ifelse(is.na(x), nastring, format(x, ...)) + \} +\end{nwchunk} + +Create formatted boxes. We want all the decimal points to line up, +so the format calls are in 3 parts: integer, real, and confidence interval. +If there are confidence intervals, format their values and then paste +together the left-right ends. +The intermediag form \code{final} is a matrix with one column per statistic. +At the end, reformat it as an array whose last dimension is the components. + +\begin{nwchunk} +\nwhyp{pyears-charfun3}{pyears-charfun}{pyears-charfun2}{pyears-charfun4}= + pybox <- function(plist, dd, nastring, ...) \{ + ci <- (substring(names(plist), 1,3) == "ci.") # the CI components + int <- sapply(plist, function(x) all(x == floor(x) | is.na(x))) + int <- (!ci & int) + real<- (!ci & !int) + nc <- prod(dd) + final <- matrix("", nrow=nc, ncol=length(ci)) + + if (any(int)) \{ # integers + if (any(sapply(plist[int], length) != nc)) + stop("programming length error, notify package author") + temp <- unlist(plist[int]) + final[,int] <- ifelse(is.na(temp), nastring, format(temp)) + \} + if (any(real)) \{ # floating point + if (any(sapply(plist[real], length) != nc)) + stop("programming length error, notify package author") + temp <- unlist(plist[real]) + final[,real] <- ifelse(is.na(temp), nastring, + format(temp, ...)) + \} + + if (any(ci)) \{ + if (any(sapply(plist[ci], length) != nc*2)) + stop("programming length error, notify package author") + temp <- unlist(plist[ci]) + temp <- array(ifelse(is.na(temp), nastring, + format(temp, ...)), + dim=c(nc, 2, sum(ci))) + final[,ci] <- paste(temp[,1,], temp[,2,], sep='-') + \} + array(final, dim=c(dd, length(ci))) + \} +\end{nwchunk} + +This function prints out a box table. Each cell contains the full set of +statistics that were requested. Most of the work is the creation of +the appropriate spacing and special characters to create a valid +pandoc table. +\begin{nwchunk} +\nwhyp{pyears-charfun4}{pyears-charfun}{pyears-charfun3}{pyears-charfun5}= + pyshow <- function(dmat, labels, rowname, colname, vline) \{ + # Every column is the same width, except the first + colwidth <- c(max(nchar(rowname), nchar(labels[1])), + rep(max(nchar(dmat[1,1,]), nchar(colname)), length(colname))) + colwidth[2] <- max(colwidth[2], nchar(labels[2])) + ncol <- length(colwidth) + + dd <- dim(dmat) # vector of length 3, third dim is the statistics + rline <- ceiling(dd[3]/2) #which line to put the row label on. + if (vline) \{ # use a grid table + cat("+", paste(strpad('-', colwidth, pad='-'), collapse='+'), "+{\textbackslash}n", + sep='') + temp <- rep(' ', ncol); temp[2] <- labels[2] + cat("|", paste(strpad(temp, colwidth), collapse="|"), "|{\textbackslash}n", + sep='') + cat("|", paste(strpad(c(labels[1], colname), colwidth), collapse="|"), + "|{\textbackslash}n", sep='') + cat("+", paste(strpad('=', colwidth, pad='='), collapse="+"), "+{\textbackslash}n", + sep='') + for (i in 1:dd[1]) \{ + for (j in 1:dd[3]) \{ #one printout line per stat + if (j==rline) temp <- c(rowname[i], dmat[i,,j]) + else temp <- c("", dmat[i,,j]) + cat("|", paste(strpad(temp, colwidth), collapse='|'), "|{\textbackslash}n", + sep='') + \} + cat("+", paste(strpad('-', colwidth, '-'), collapse='+'), "+{\textbackslash}n", + sep='') + \} + \} + else \{ # use a multiline table + cat(paste(strpad('-', colwidth, '-'), collapse='-'), "{\textbackslash}n") + temp <- rep(' ', ncol); temp[2] <- labels[2] + cat(paste(strpad(temp, colwidth), collapse=" "), "{\textbackslash}n") + cat(paste(strpad(c(labels[1], colname), colwidth), collapse=" "), + "{\textbackslash}n") + cat(paste(strpad('-', colwidth, pad='-'), collapse=" "), "{\textbackslash}n") + for (i in 1:dd[1]) \{ + for (j in 1:dd[3]) \{ #one printout line per stat + if (j==rline) temp <- c(rowname[i], dmat[i,,j]) + else temp <- c("", dmat[i,,j]) + cat(paste(strpad(temp, colwidth), collapse=' '), "{\textbackslash}n") + \} + if (i< dd[1]) cat(" {\textbackslash}n") #blank line + \} + cat(paste(strpad('-', colwidth, '-'), collapse='-'), "{\textbackslash}n") + \} + \} +\end{nwchunk} + +This function adds a totals row to the data, for either the first +or first and second dimensions. +The ``n'' component can't be totaled, so we turn that into NA. +\begin{nwchunk} +\nwhypb{pyears-charfun5}{pyears-charfun}{pyears-charfun4}= + pytot <- function(x, na=FALSE) \{ + dd <- dim(x) + if (length(dd) ==1) \{ + if (na) array(c(x, NA), dim= length(x) +1, + dimnames=list(c(dimnames(x)[[1]], "Total"))) + else array(c(x, sum(x)), dim= length(x) +1, + dimnames=list(c(dimnames(x)[[1]], "Total"))) + \} + else if (length(dd) ==2) \{ + if (na) new <- rbind(cbind(x, NA), NA) + else \{ + new <- rbind(x, colSums(x)) + new <- cbind(new, rowSums(new)) + \} + array(new, dim=dim(x) + c(1,1), + dimnames=list(c(dimnames(x)[[1]], "Total"), + c(dimnames(x)[[2]], "Total"))) + \} + else \{ + # The general case + index <- 1:length(dd) + if (na) sum1 <- sum2 <- sum3 <- NA + else \{ + sum1 <- apply(x, index[-1], sum) # row sums + sum2 <- apply(x, index[-2], sum) # col sums + sum3 <- apply(x, index[-(1:2)], sum) # total sums + \} + + # create a new matrix and then fill it in + d2 <- dd + d2[1:2] <- dd[1:2] +1 + dname <- dimnames(x) + dname[[1]] <- c(dname[[1]], "Total") + dname[[2]] <- c(dname[[2]], "Total") + new <- array(x[1], dim=d2, dimnames=dname) + + # say dim(x) =(5,8,4); we want new[6,-9,] <- sum1; new[-6,9,] <- sum2 + # and new[6,9,] <- sum3 + # if dim is longer, we need to add more commas + commas <- rep(',', length(dd) -2) + eval(parse(text=paste("new[1:dd[1], 1:dd[2]", commas, "] <- x"))) + eval(parse(text=paste("new[ d2[1],-d2[2]", commas, "] <- sum1"))) + eval(parse(text=paste("new[-d2[1], d2[2]", commas, "] <- sum2"))) + eval(parse(text=paste("new[ d2[1], d2[2]", commas, "] <- sum3"))) + new + \} + \} +\end{nwchunk} +\section{Residuals for survival curves} +\subsection{R-code} +For all the more complex cases, the variance of a survival curve is based on +the infinitesimal jackknife: +$$ +D_i(t) = \frac{\partial S(t)}{\partial w_i} +$$ +evaluated at the the observed vector of weights. The variance at a given +time is then $D'WD'$ where $D$ is a diagonal matrix of the case weights. +When there are multiple states $S$ is replaced by the vector $p(t)$, with +one element per state, and the formula gets a bit more complex. +The predicted curve from a Cox model is the most complex case. + +Realizing that we need to return the matrix $D$ to the user, in order to compute +the variance of derived quantities like the restricted mean time in state, +the code has been changed from a primarily internal focus (compute within the +survfit routine) to an external one. + +The underlying C code is very similar to that in survfitkm.c +One major difference in the routines is that this code is designed to return +values at a fixed set of time points; it is an error if the user does not +provide them. This allows the result to be presented as a matrix or array. +Computational differences will be discussed later. + +The method argument is for debugging. For multi-state it uses either C code +or the optimized R method. +The double call below is because we want residuals to return a simple matrix, +but the pseudo function needs to get back a little bit more. + +\section{Residuals for survival curves} +\subsection{R-code} +For all the more complex cases, the variance of a survival curve is based on +the infinitesimal jackknife: +$$ +D_i(t) = \frac{\partial S(t)}{\partial w_i} +$$ +evaluated at the the observed vector of weights. The variance at a given +time is then $D'WD'$ where $D$ is a diagonal matrix of the case weights. +When there are multiple states $S$ is replaced by the vector $p(t)$, with +one element per state, and the formula gets a bit more complex. +The predicted curve from a Cox model is the most complex case. + +Realizing that we need to return the matrix $D$ to the user, in order to compute +the variance of derived quantities like the restricted mean time in state, +the code has been changed from a primarily internal focus (compute within the +survfit routine) to an external one. + +The underlying C code is very similar to that in survfitkm.c +One major difference in the routines is that this code is designed to return +values at a fixed set of time points; it is an error if the user does not +provide them. This allows the result to be presented as a matrix or array. +Computational differences will be discussed later. + +The method argument is for debugging. For multi-state it uses either C code +or the optimized R method. +The double call below is because we want residuals to return a simple matrix, +but the pseudo function needs to get back a little bit more. + +\begin{nwchunk} +\nwhypf{residuals.survfit1}{residuals.survfit}{residuals.survfit2}= + # residuals for a survfit object + residuals.survfit <- function(object, times, + type= "pstate", + collapse, weighted=FALSE, method=1, ...)\{ + + if (!inherits(object, "survfit")) + stop("argument must be a survfit object") + if (missing(times)) stop("the times argument is required") + # allow a set of alias + temp <- c("pstate", "cumhaz", "sojourn", "survival", + "chaz", "rmst", "rmts", "auc") + type <- match.arg(casefold(type), temp) + itemp <- c(1,2,3,1,2,3,3,3)[match(type, temp)] + type <- c("pstate", "cumhaz", "auc")[itemp] + + if (missing(collapse)) + fit <- survresid.fit(object, times, type, weighted=weighted, + method= method) + else fit <- survresid.fit(object, times, type, collapse= collapse, + weighted= weighted, method= method) + + fit$residuals + \} + + survresid.fit <- function(object, times, + type= "pstate", + collapse, weighted=FALSE, method=1) \{ + + survfitms <- inherits(object, "survfitms") + coxsurv <- inherits(object, "survfitcox") + timefix <- (is.null(object$timefix) || object$timefix) + + start.time <- object$start.time + if (is.null(start.time)) start.time <- min(c(0, object$time)) + + # check input arguments + if (missing(times)) + stop ("the times argument is required") + else \{ + if (!is.numeric(times)) stop("times must be a numeric vector") + times <- sort(unique(times)) + if (timefix) times <- aeqSurv(Surv(times))[,1] + \} + + # get the data + \nwhypf{rsurvfit-data1}{rsurvfit-data}{rsurvfit-data2} + + if (missing(collapse)) collapse <- (!(is.null(id)) && any(duplicated(id))) + if (collapse && is.null(id)) stop("collapse argument requires an id or cluster argument in the survfit call") + + ny <- ncol(newY) + if (collapse && any(X != X[1])) \{ + # If the same id shows up in multiple curves, we just can't deal + # with it. + temp <- unlist(lapply(split(id, X), unique)) + if (any(duplicated(temp))) + stop("same id appears in multiple curves, cannot collapse") + \} + + timelab <- signif(times, 3) # used for dimnames + # What type of survival curve? + if (!coxsurv) \{ + stype <- Call$stype + if (is.null(stype)) stype <- 1 + ctype <- Call$ctype + if (is.null(ctype)) ctype <- 1 + if (!survfitms) \{ + resid <- rsurvpart1(newY, X, casewt, times, + type, stype, ctype, object) + if (collapse) \{ + resid <- rowsum(resid, id, reorder=FALSE) + dimnames(resid) <- list(id= unique(id), times=timelab) + curve <- (as.integer(X))[!duplicated(id)] #which curve for each + \} + else \{ + if (length(id) >0) dimnames(resid) <- list(id=id, times=timelab) + curve <- as.integer(X) + \} + \} + else \{ # multi-state + if (!collapse) \{ + if (length(id >0)) d1name <- id else d1name <- NULL + cluster <- d1name + curve <- as.integer(X) + \} + else \{ + d1name <- unique(id) + cluster <- match(id, d1name) + curve <- (as.integer(X))[!duplicated(id)] + \} + resid <- rsurvpart2(newY, X, casewt, istate, times, cluster, + type, object, method=method, collapse=collapse) + + if (type == "cumhaz") \{ + ntemp <- colnames(object$cumhaz) + if (length(dim(resid)) ==3) + dimnames(resid) <- list(id=d1name, times=timelab, + cumhaz= ntemp) + else dimnames(resid) <- list(id=d1name, cumhaz=ntemp) + \} + else \{ + ntemp <- object$states + if (length(dim(resid)) ==3) + dimnames(resid) <- list(id=d1name, times=timelab, + state= ntemp) + else dimnames(resid) <- list(id=d1name, state= ntemp) + \} + \} + \} + else stop("coxph survival curves not yet available") + + if (weighted && any(casewt !=1)) resid <- resid*casewt + + list(residuals= resid, curve= curve, id= id, idname=idname) + \} +\end{nwchunk} + +The first part of the work is retrieve the data set. This is done in multiple +places in the survival code, all essentially the same. +If I gave up (like lm) and forced the model frame to be saved this would be +easier of course. + +\begin{nwchunk} +\nwhypb{rsurvfit-data2}{rsurvfit-data}{rsurvfit-data1}= + Call <- object$call + + # remember the name of the id variable, if present. + # but we don't try to parse it: id= mydata$clinic becomes NULL + idname <- Call$id + if (is.name(idname)) idname <- as.character(idname) + else idname <- NULL + # I always need the model frame + if (coxsurv) \{ + mf <- model.frame(object) + if (is.null(object$y)) Y <- model.response(mf) + else Y <- object$y + \} + else \{ + formula <- formula(object) + + # the chunk below is shared with survfit.formula + na.action <- getOption("na.action") + if (is.character(na.action)) + na.action <- get(na.action) # this is a temporary hack + \nwhypf{survfit.formula-getdata1}{survfit.formula-getdata}{survfit.formula-getdata2} + # end of shared code + \} + + xlev <- levels(X) + + # Deal with ties + if (is.null(Call$timefix) || Call$timefix) newY <- aeqSurv(Y) else newY <- Y +\end{nwchunk} + +This code has 3 primary sections: single state survival, multi-state survival, +and post-Cox survival. +A motivating idea in all of them is to avoid an $O(nd)$ calculation that +involves the increment to each subject's leverage at each of the $d$ +event times. Since $d$ often grows with $n$ this can get very slow. This +routine is designed for the case where the number of time points in the +output matrix is modest, so we aim for $O(n)$ processes that repeat for +each output time. + +\subsection{Simple survival} +The Nelson-Aalen estimate of cumulative hazard is a simple sum +\begin{align} + H(t) &= H(t-) + h(t) \nonumber \\ + \frac{\partial H(t)}{\partial w_i} &= \frac{\partial H(t-)}{\partial w_i} + + [dN_i(t) - Y_i(t)h(t)]/r(t) \nonumber \\ + &= \sum_{d_j \le t} dN_i(d_j)/r(d_j) - Y_i(d_j)h(d_j)/r(d_j) + \label{NAderiv} +\end{align} +where $H$ the cumulative hazard, +$h$ is the increment to the cumulative hazard, $Y_i$ is 1 when a +subject is at risk, and $dN_i$ marks an event for the subject. +Our basic strategy for the NA estimate is to use a two stage estimate. +First, compute three vectors, each with one element per event time. +\begin{itemize} + \item term1 = $1/r(d_j)$ is the increment to the derivative for any + observation with an event at event time $d_j$ + \item term2 = $-h(d_j)/r(d_j)$ is the increment for any observation that is at + risk at time $d_j$ + \item term3 = cumulative sum of term2 +\end{itemize} + +For any given observation $i$ whose follow-up interval is $(s_i, t_i)$, their +derivative at time $z$ is the sum of +\begin{itemize} + \item term3(min($z$, $t_i$)) - term3(min($z$, $s_i$)) + \item term1($t_i$) if $t_i \le z$ and observation $i$ is an event +\end{itemize} + +The Fleming-Harrington estimate of survival is +\begin{align*} + S(t) &= e^{-H(t)} \\ + \partial{S(t)}{\partial w_i} &= -S(t)\partial{H(t)}{\partial w_i} +\end{align*} +So has exactly the same computation, with a multiplication at the end. + +\begin{nwchunk} +\nwhyp{residuals.survfit2}{residuals.survfit}{residuals.survfit1}{residuals.survfit3}= + rsurvpart1 <- function(Y, X, casewt, times, + type, stype, ctype, fit) \{ + + ntime <- length(times) + etime <- (fit$n.event >0) + ny <- ncol(Y) + event <- (Y[,ny] >0) + status <- Y[,ny] + + # + # Create a list whose first element contains the location of + # the death times in curve 1, second element the death times for curve 2, + # + if (is.null(fit$strata)) \{ + fitrow <- list(which(etime)) + \} + else \{ + temp1 <- cumsum(fit$strata) + temp2 <- c(1, temp1+1) + fitrow <- lapply(1:length(fit$strata), function(i) \{ + indx <- seq(temp2[i], temp1[i]) + indx[etime[indx]] # keep the death times + \}) + \} + ff <- unlist(fitrow) + + # for each time x, the index of the last death time which is <=x. + # 0 if x is before the first death time in the fit object. + # The result is an index to the survival curve + matchfun <- function(x, fit, index) \{ + dtime <- fit$time[index] # subset to this curve + i2 <- findInterval(x, dtime, left.open=FALSE) + c(0, index)[i2 +1] + \} + + # output matrix D will have one row per observation, one col for each + # reporting time. tindex and yindex have the same dimension as D. + # tindex points to the last death time in fit which + # is <= the reporting time. (If there is only 1 curve, each col of + # tindex will be a repeat of the same value.) + tindex <- matrix(0L, nrow(Y), length(times)) + for (i in 1:length(fitrow)) \{ + yrow <- which(as.integer(X) ==i) + temp <- matchfun(times, fit, fitrow[[i]]) + tindex[yrow, ] <- rep(temp, each= length(yrow)) + \} + tindex[,] <- match(tindex, c(0,ff)) -1L # the [,] preserves dimensions + + # repeat the indexing for Y onto fit$time. Each row of yindex points + # to the last row of fit with death time <= Y[,ny] + ny <- ncol(Y) + yindex <- matrix(0L, nrow(Y), length(times)) + event <- (Y[,ny] >0) + if (ny==3) startindex <- yindex + for (i in 1:length(fitrow)) \{ + yrow <- (as.integer(X) ==i) # rows of Y for this curve + temp <- matchfun(Y[yrow,ny-1], fit, fitrow[[i]]) + yindex[yrow,] <- rep(temp, ncol(yindex)) + if (ny==3) \{ + temp <- matchfun(Y[yrow,1], fit, fitrow[[i]]) + startindex[yrow,] <- rep(temp, ncol(yindex)) + \} + \} + yindex[,] <- match(yindex, c(0,ff)) -1L + if (ny==3) \{ + startindex[,] <- match(startindex, c(0,ff)) -1L + # no subtractions for report times before subject's entry + startindex <- pmin(startindex, tindex) + \} + + # Now do the work + if (type=="cumhaz" || stype==2) \{ # result based on hazards + if (ctype==1) \{ + \nwhypf{residpart1-nelson1}{residpart1-nelson}{residpart1-nelson2} + \} else \{ + \nwhypf{residpart1-fleming1}{residpart1-fleming}{residpart1-fleming2} + \} + \} else \{ # not hazard based + \nwhypf{residpart1-AJ1}{residpart1-AJ}{residpart1-AJ2} + \} + D + \} +\end{nwchunk} + +The Nelson-Aalen is the simplest case. +We don't have to worry about case weights of the data, since that has +already been accounted for by the survfit function. + +\begin{nwchunk} +\nwhypb{residpart1-nelson2}{residpart1-nelson}{residpart1-nelson1}= + death <- (yindex <= tindex & rep(event, ntime)) # an event occured at <= t + + term1 <- 1/fit$n.risk[ff] + term2 <- lapply(fitrow, function(i) fit$n.event[i]/fit$n.risk[i]^2) + term3 <- unlist(lapply(term2, cumsum)) + + sum1 <- c(0, term1)[ifelse(death, 1+yindex, 1)] + sum2 <- c(0, term3)[1 + pmin(yindex, tindex)] + if (ny==3) sum3 <- c(0, term3)[1 + pmin(startindex, tindex)] + + if (ny==2) D <- matrix(sum1 - sum2, ncol=ntime) + else D <- matrix(sum1 + sum3 - sum2, ncol=ntime) + + # survival is exp(-H) so the derivative is a simple transform of D + if (type== "pstate") D <- -D* c(1,fit$surv[ff])[1+ tindex] + else if (type == "auc") \{ + \nwhypf{auctrick1}{auctrick}{auctrick2} + \} +\end{nwchunk} + +The sojourn time is the area under the survival curve. Let $x_j$ be the +widths of the rectangles under the curve from event time $d_j$ to +$min(d_{j+1}, t)$, zero if $t \le d_j$, or $t-d_m$ if $t$ is after the last +event time. +\begin{align*} + A(0,t) &= \sum_{j=1}^m x_j S(d_j) \\ + \frac{\partial A(0,t)}{\partial w_i} &= + \sum_{j=1}^m -x_j S(d_j) \frac{\partial H(d_j)}{\partial w_i} \\ + &= \sum_{j=1}^m -x_jS(d_j) \sum_{k \le j} \frac{\partial h(d_k)}{\partial w_i} \\ + &= \sum_{k=1}^m \frac{\partial h(d_k)}{\partial w_i} + \left(\sum_{j\ge k} -x_j S(d_j) \right) \\ + &= \sum_{k=1}^m -A(d_k, t) \frac{\partial h(d_k)}{\partial w_i} +\end{align*} + +For an observation at risk over the interval $(a,b)$ we have exactly the same +calculus as the cumulative hazard with respect to which $h(d_k)$ terms +are counted for the observation, but now they are weighted sums. The weights +are different for each output time, so we set them up as a matrix. +We need the AUC at each event time $d_k$, and the AUC at the output times. + +Matrix subscripts are a little used feature of R. If y is a matrix of +values and x is a 2 colum matrix containing m (row, col) pairs, the +result will be a vector of length m that plucks out the [x[1,1], x[1,2]] +value of y, then the [x[2,1], x[2,2]] value of y, etc. +They are rarely useful, but very handy in the few cases where they apply. + +\begin{nwchunk} +\nwhyp{auctrick2}{auctrick}{auctrick1}{auctrick3}= + auc1 <- lapply(fitrow, function(i) \{ + if (length(i) <=1) 0 + else c(0, cumsum(diff(fit$time[i]) * (fit$surv[i])[-length(i)])) + \}) # AUC at each event time + auc2 <- lapply(fitrow, function(i) \{ + if (length(i) <=1) 0 + else \{ + xx <- sort(unique(c(fit$time[i], times))) # all the times + yy <- (fit$surv[i])[findInterval(xx, fit$time[i])] + auc <- cumsum(c(diff(xx),0) * yy) + c(0, auc)[match(times, xx)] + \}\}) # AUC at the output times + + # Most often this function is called with a single curve, so make that case + # faster. (Or I presume so: mapply and do.call may be more efficient than + # I think for lists of length 1). + if (length(fitrow)==1) \{ # simple case, most common to ask for auc + wtmat <- pmin(outer(auc1[[1]], -auc2[[1]], '+'),0) + term1 <- term1 * wtmat + term2 <- unlist(term2) * wtmat + term3 <- apply(term2, 2, cumsum) + \} + else \{ #more than one curve, compute weighted cumsum per curve + wtmat <- mapply(function(x, y) pmin(outer(x, -y, "+"), 0), auc1, auc2) + term1 <- term1 * do.call(rbind, wtmat) + temp <- mapply(function(x, y) apply(x*y, 2, cumsum), term2, wtmat) + term3 <- do.call(rbind, temp) + \} + + sum1 <- sum2 <- matrix(0, nrow(yindex), ntime) + if (ny ==3) sum3 <- sum1 + for (i in 1:ntime) \{ + sum1[,i] <- c(0, term1[,i])[ifelse(death[,i], 1 + yindex[,i], 1)] + sum2[,i] <- c(0, term3[,i])[1 + pmin(yindex[,i], tindex[,i])] + if (ny==3) sum3[,i] <- c(0, term3[,i])[1 + pmin(startindex[,i], tindex[,i])] + \} + # Perhaps a bit faster(?), but harder to read. And for AUC people usually only + # ask for one time point + #sum1 <- rbind(0, term1)[cbind(c(ifelse(death, 1+yindex, 1)), c(col(yindex)))] + #sum2 <- rbind(0, term3)[cbind(c(1 + pmin(yindex, tindex)), c(col(yindex)))] + #if (ny==3) sum3 <- + # rbind(0, term3)[c(cbind(1 + pmin(startindex, tindex)), + # c(col(yindex)))] + if (ny==2) D <- matrix(sum1 - sum2, ncol=ntime) + else D <- matrix(sum1 + sum3 - sum2, ncol=ntime) +\end{nwchunk} + +\paragraph{Fleming-Harrington} +For the Fleming-Harrington estimator the calculation at a tied time differs +slightly. +If there were 10 at risk and 3 tied events, the Nelson-Aalen has an increment +of 3/10, while the FH has an increment of (1/10 + 1/9 + 1/8). The underlying +idea is that the true time values are continuous and we observe ties due to +coarsening of the data. The derivative will have 3 terms as well. In this +case the needed value cannot be pulled directly from the survfit object. +Computationally, the number of distinct times at which a tie occurs is normally +quite small and the for loop below will not be too expensive. + +\begin{nwchunk} +\nwhypb{residpart1-fleming2}{residpart1-fleming}{residpart1-fleming1}= + stop("residuals function still imcomplete, for FH estimate") + if (any(casewt != casewt[1])) \{ + # Have to reconstruct the number of obs with an event, the curve only + # contains the weighted sum + nevent <- unlist(lapply(seq(along.with=levels(X)), function(i) \{ + keep <- which(as.numeric(X) ==i) + counts <- table(Y[keep, ny-1], status) + as.vector(counts[, ncol(counts)]) + \})) + \} else nevent <- fit$n.event + + n2 <- fit$n.risk + risk2 <- 1/fit$n.risk + ltemp <- risk2^2 + for (i in which(nevent>1)) \{ # assume not too many ties + denom <- fit$n.risk[i] - fit$n.event[i]*(0:(nevent[i]-1))/nevent[i] + risk2[i] <- mean(1/denom) # multiplier for the event + ltemp[i] <- mean(1/denom^2) + n2[i] <- mean(denom) + \} + + death <- (yindex <= tindex & rep(event, ntime)) + term1 <- risk2[ff] + term2 <- lapply(fitrow, function(i) event[i]*ltemp[i]) + term3 <- unlist(lapply(term2, cumsum)) + + sum1 <- c(0, term1)[ifelse(death, 1+yindex, 1)] + sum2 <- c(0, term3)[1 + pmin(yindex, tindex)] + if (ny==3) sum3 <- c(0, term3)[1 + pmin(startindex, tindex)] + + if (ny==2) D <- matrix(sum1 - sum2, ncol=ntime) + else D <- matrix(sum1 + sum3 - sum2, ncol=ntime) + + if (type=="pstate") D <- -D* c(0,fit$surv[ff])[1+ tindex] + else if (type=="auc") \{ + \nwhyp{auctrick3}{auctrick}{auctrick2}{auctrick4} + \} +\end{nwchunk} + +\paragraph{Kaplan-Meier} +For the Kaplan-Meier (a special case of the Aalen-Johansen) the underlying +algorithm is multiplicative, but we can turn it into an additive +algoritm with a slight of hand. + +\begin{align*} + S(t) &= \prod_{d_j\le t} (1- h(d_j)) \\ + &= \exp \left(\sum_{d_j\le t} \log(1- h(d_j)) \right) \\ + &= \exp \left(\sum_{d_j\le t} \log(r(d_j) - dN(d_j)) - log(r(d_j)) \right) \\ + \frac{\partial S(t)}{\partial w_i} &= + S(t) \sum_{d_j\le t} \frac{Y_i(d_j) - dN_i(d_j)}{r(d_j) - dN(d_j)} - + \frac{Y_i(d_j)}{ r(d_j)} +\end{align*} + +The addend for term2 is now $1/n(n-e)$ where $e$ is the number of events, i.e., +the same term as in the Greenwood variance, and term1 is $-1/n(n-e)$. +The jumps in the KM curve are just a big larger than jumps in a FH estimate, +so it makes sense that these are just a bit larger. + +\begin{nwchunk} +\nwhypb{residpart1-AJ2}{residpart1-AJ}{residpart1-AJ1}= + death <- (yindex <= tindex & rep(event, ntime)) + # dtemp avoids 1/0. (When this occurs the influence is 0, since + # the curve has dropped to zero; and this avoids Inf in term1 and term2). + dtemp <- ifelse(fit$n.risk==fit$n.event, 0, 1/(fit$n.risk- fit$n.event)) + term1 <- dtemp[ff] + term2 <- lapply(fitrow, function(i) dtemp[i]*fit$n.event[i]/fit$n.risk[i]) + term3 <- unlist(lapply(term2, cumsum)) + + add1 <- c(0, term1)[ifelse(death, 1+yindex, 1)] + add2 <- c(0, term3)[1 + pmin(yindex, tindex)] + if (ny==3) add3 <- c(0, term3)[1 + pmin(startindex, tindex)] + + if (ny==2) D <- matrix(add1 - add2, ncol=ntime) + else D <- matrix(add1 + add3 - add2, ncol=ntime) + + # survival is exp(-H) so the derivative is a simple transform of D + if (type== "pstate") D <- -D* c(1,fit$surv[ff])[1+ tindex] + else if (type == "auc") \{ + \nwhypb{auctrick4}{auctrick}{auctrick3} + \} +\end{nwchunk} + +\subsection{Multi-state Aalen-Johansen estimate} +For multi-state models a correction for ties of similar spirit to the +Efron approximation in a Cox model (the ctype=2 argument for \code{survfit}) +is difficult: the 'right' answer depends on the study. +Thus the ctype argument is not present. +Both stype 1 and 2 are feasible, but currently only \code{stype=1} is +supported. +This makes the code somewhat simpler, but this is more than offset by the +multi-state nature. +With multiple states we also need to account for influence on the starting +state $p(0)$. + +One thing that can make this code slow is data that has been divided into a +very large number of intervals, giving a large number of observations for +each cluster. We first deal with that by collapsing adjacent observations. + +\begin{nwchunk} +\nwhypb{residuals.survfit3}{residuals.survfit}{residuals.survfit2}= + rsurvpart2 <- function(Y, X, casewt, istate, times, cluster, type, fit, + method, collapse) \{ + ny <- ncol(Y) + ntime <- length(times) + nstate <- length(fit$states) + + # ensure that Y, istate, and fit all use the same set of states + states <- fit$states + if (!identical(attr(Y, "states"), fit$states)) \{ + map <- match(attr(Y, "states"), fit$states) + Y[,ny] <- c(0, map)[1+ Y[,ny]] # 0 = censored + attr(Y, "states") <- fit$states + \} + if (is.null(istate)) istate <- rep(1L, nrow(Y)) #everyone starts in s0 + else \{ + if (is.character(istate)) istate <- factor(istate) + if (is.factor(istate)) \{ + if (!identical(levels(istate), fit$states)) \{ + map <- match(levels(istate), fit$states) + if (any(is.na(map))) stop ("invalid levels in istate") + istate <- map[istate] + \} + \} # istate is numeric, we take what we get and hope it is right + \} + + # collapse redundant rows in Y, for efficiency + # a redundant row is a censored obs in the middle of a chain of times + # if the user wants individial obs, however, we would just have to + # expand it again + if (ny==3 && collapse & any(duplicated(cluster))) \{ + ord <- order(cluster, X, istate, Y[,1]) + cfit <- .Call(Ccollapse, Y, X, istate, cluster, casewt, ord -1L) + if (nrow(cfit) < .8*length(X)) \{ + # shrinking the data by 20 percent is worth it + temp <- Y[ord,] + Y <- cbind(temp[cfit[,1], 1], temp[cfit[2], 2:3]) + X <- X[cfit[,1]] + istate <- istate[cfit[1,]] + cluster <- cluster[cfit[1,]] + \} + \} + + # Compute the initial leverage + inf0 <- NULL + if (is.null(fit$call$p0) && any(istate != istate[1])) \{ + #p0 was not supplied by the user, and the intitial states vary + inf0 <- matrix(0., nrow=nrow(Y), ncol=nstate) + i0fun <- function(i, fit, inf0) \{ + # reprise algorithm in survfitCI + p0 <- fit$p0 + t0 <- fit$time[1] + if (ny==2) at.zero <- which(as.numeric(X) ==i) + else + at.zero <- which(as.numeric(X) ==i & + (Y[,1] < t0 & Y[,2] >= t0)) + for (j in 1:nstate) \{ + inf0[at.zero, j] <- (ifelse(istate[at.zero]==states[j], 1, 0) - + p0[j])/sum(casewt[at.zero]) + \} + inf0 + \} + + if (is.null(fit$strata)) inf0 <- i0fun(1, fit, inf0) + else for (i in 1:length(levels(X))) + inf0 <- i0fun(i, fit[i], inf0) # each iteration fills in some rows + \} + + p0 <- fit$p0 # needed for method==1, type != cumhaz + fit <- survfit0(fit) # package the initial state into the picture + start.time <- fit$time[1] + + # This next block is identical to the one in rsurvpart1, more comments are + # there + etime <- (rowSums(fit$n.event) >0) + event <- (Y[,ny] >0) + # + # Create a list whose first element contains the location of + # the death times in curve 1, second element for curve 2, etc. + # + if (is.null(fit$strata)) fitrow <- list(which(etime)) + else \{ + temp1 <- cumsum(fit$strata) + temp2 <- c(1, temp1+1) + fitrow <- lapply(1:length(fit$strata), function(i) \{ + indx <- seq(temp2[i], temp1[i]) + indx[etime[indx]] # keep the death times + \}) + \} + ff <- unlist(fitrow) + + # for each time x, the index of the last death time which is <=x. + # 0 if x is before the first death time + matchfun <- function(x, fit, index) \{ + dtime <- fit$time[index] # subset to this curve + i2 <- findInterval(x, dtime, left.open=FALSE) + c(0, index)[i2 +1] + \} + + + if (type== "cumhaz") \{ + \nwhypf{residpart2CH1}{residpart2CH}{residpart2CH2} + \} else \{ + \nwhypf{residpart2AJ1}{residpart2AJ}{residpart2AJ2} + \} + + # since we may have done a partial collapse (removing redundant rows), the + # parent routine can't collapse the data + if (collapse & any(duplicated(cluster))) \{ + if (length(dim(D)) ==2) + D <- rowsum(D, cluster, reorder=FALSE) + else \{ #rowsums has to be fooled + dd <- dim(D) + temp <- rowsum(matrix(D, nrow=dd[1]), cluster) + D <- array(temp, dim=c(nrow(temp), dd[2:3])) + \} + \} + D + \} +\end{nwchunk} + +\paragraph{Nelson-Aalen} +The multi-state Nelson-Aalen estimate of the cumulative hazard at time $t$ +is a vector with one element for each observed transition pair. If there +were $k$ states there are potentially $k(k-1)$ transition pairs, though +normally only a small number will occur in a given fit. +We ignore transitions from state $j$ to state $j$. +Let $r(t)$ be the weighted number at risk at time $t$, in each state. +When some subject makes a $j:k$ transition, the $j:k$ transition will +have an increment of $w_i/r_j(t)$. +This is precisely the same increment as the ordinary Nelson estimate. +The only change then is that we loop over the set of possible transitions, +creating a large output object. + +\begin{nwchunk} +\nwhypb{residpart2CH2}{residpart2CH}{residpart2CH1}= + # output matrix D will have one row per observation, one col for each + # reporting time. tindex and yindex have the same dimension as D. + # tindex points to the last death time in fit which + # is <= the reporting time. (If there is only 1 curve, each col of + # tindex will be a repeat of the same value.) + tindex <- matrix(0L, nrow(Y), length(times)) + for (i in 1:length(fitrow)) \{ + yrow <- which(as.integer(X) ==i) + temp <- matchfun(times, fit, fitrow[[i]]) + tindex[yrow, ] <- rep(temp, each= length(yrow)) + \} + tindex[,] <- match(tindex, c(0,ff)) -1L # the [,] preserves dimensions + + # repeat the indexing for Y onto fit$time. Each row of yindex points + # to the last row of fit with death time <= Y[,ny] + ny <- ncol(Y) + yindex <- matrix(0L, nrow(Y), length(times)) + event <- (Y[,ny] >0) + if (ny==3) startindex <- yindex + for (i in 1:length(fitrow)) \{ + yrow <- (as.integer(X) ==i) # rows of Y for this curve + temp <- matchfun(Y[yrow,ny-1], fit, fitrow[[i]]) + yindex[yrow,] <- rep(temp, ncol(yindex)) + if (ny==3) \{ + temp <- matchfun(Y[yrow,1], fit, fitrow[[i]]) + startindex[yrow,] <- rep(temp, ncol(yindex)) + \} + \} + yindex[,] <- match(yindex, c(0,ff)) -1L + if (ny==3) \{ + startindex[,] <- match(startindex, c(0, ff)) -1L + # no subtractions for report times before subject's entry + startindex <- pmin(startindex, tindex) + \} + + dstate <- Y[,ncol(Y)] + istate <- as.integer(istate) + ntrans <- ncol(fit$cumhaz) # the number of possible transitions + D <- array(0, dim=c(nrow(Y), ntime, ntrans)) + + scount <- table(istate[dstate!=0], dstate[dstate!=0]) # observed transitions + state1 <- row(scount)[scount>0] + state2 <- col(scount)[scount>0] + temp <- paste(rownames(scount)[state1], + colnames(scount)[state2], sep='.') + if (!identical(temp, colnames(fit$cumhaz))) stop("setup error") + + for (k in length(state1)) \{ + e2 <- Y[,ny] == state2[k] + add1 <- (yindex <= tindex & rep(e2, ntime)) + lsum <- unlist(lapply(fitrow, function(i) + cumsum(fit$n.event[i,k]/fit$n.risk[i,k]^2))) + + term1 <- c(0, 1/fit$n.risk[ff,k])[ifelse(add1, 1+yindex, 1)] + term2 <- c(0, lsum)[1+pmin(yindex, tindex)] + if (ny==3) term3 <- c(0, lsum)[1 + startindex] + + if (ny==2) D[,,k] <- matrix(term1 - term2, ncol=ntime) + else D[,,k] <- matrix(term1 + term3 - term2, ncol=ntime) + \} +\end{nwchunk} + +\paragraph{Aalen-Johansen} +The multi-state AJ estimate is more complex. Let $p(t)$ be the vector +of probability in state at time $t$. +Then +\begin{align} + p(t) &= p(t-) [I+ A(t)]\nonumber\\ + \frac{\partial p(t)}{\partial w_i} &= \frac{\partial p(t-)}{\partial w_i} + [I+ A(t)] + + p(t-) \frac{\partial A(t)}{\partial w_i} \nonumber\\ + &= U_i(t-) [I+ A(t)] + p(t-) \frac{\partial A(t)}{\partial w_i} + \label{ajresidx}\\ +\end{align} + +When we expand the left hand portion of \eqref{ajresidx} to include all +observations it becomes simple matrix multiplication, not so with +the right hand portion. +Each individual subject $i$ has a subject-specific +nstate * nstate derivative matrix $dA$, which will be non-zero only for the +state (row) $j$ that the subject occupies at time $t-$. +The $j$th row of $p(t-) dH$ is added to each subject's derivative. + +The $A$ matrix at time $t$ has off diagonal elements and derivative +\begin{align} +A(t)_{jk} &= \frac{\sum_i w_i Y_{ij}(t) dN{ik}(t)} + {\sum_i w_iY_{ij}(t)} \\ + &= \lambda_{jk}(t) \\ +\frac{\partial A(t)}{\partial w_i} &= \frac{dN_{ik}(t) - \lambda_{jk}(t)} + {\sum_i w_iY_{ij}(t)} \label{Aderiv} +\end{align} + +This is the standard counting process notation: $Y_{ij}(t)$ is 1 if subject $i$ +is in state $j$ and at risk at time $t-$, and $dN_{ik}(t)$ is a transition to +state $k$ at time $t$. +Each observation at risk appears in at most 1 row of $A(t)$, since they can +only be in one state. +The diagonal element of $A$ are set so that each row sums to 0. +If there are no transitions out of state $j$ at some time point, then that +row of $A$ is zero. +Since the row sums are constant, the sum of the derivatives for each row +must be zero. + +If we evaluate equation \label{ajresidx} directly there will be +$O(nk^2)$ operations at each death time for the matrix product, and another +$O(nk)$ to add in the new increment. For a large data set $d$ is often +of the same order as $n$, which makes this an expensive calculation. +But, this is what the C-code version currently does, because I have code that +actually works. + + +\begin{nwchunk} +\nwhypb{residpart2AJ2}{residpart2AJ}{residpart2AJ1}= + if (method==1) \{ + # Compute the result using the direct method, in C code + # the routine is called separately for each curve, data in sorted order + # + is1 <- as.integer(istate) -1L # 0 based subscripts for C + if (is.null(inf0)) inf0 <- matrix(0, nrow=nrow(Y), ncol=nstate) + if (all(as.integer(X) ==1)) \{ # only one curve + if (ny==2) asort1 <- 0L else asort1 <- order(Y[,1], Y[,2]) -1L + asort2 <- order(Y[,ny-1]) -1L + tfit <- .Call(Csurvfitresid, Y, asort1, asort2, is1, + casewt, p0, inf0, times, start.time, + type== "auc") + + if (ntime==1) \{ + if (type=="auc") D <- tfit[[2]] else D <- tfit[[1]] + \} + else \{ + if (type=="auc") D <- array(tfit[[2]], dim=c(nrow(Y), nstate, ntime)) + else D <- array(tfit[[1]], dim=c(nrow(Y), nstate, ntime)) + \} + \} + else \{ # one curve at a time + ix <- as.numeric(X) # 1, 2, etc + if (ntime==1) D <- matrix(0, nrow(Y), nstate) + else D <- array(0, dim=c(nrow(Y), nstate, ntime)) + for (curve in 1:max(ix)) \{ + j <- which(ix==curve) + ytemp <- Y[j,,drop=FALSE] + if (ny==2) asort1 <- 0L + else asort1 <- order(ytemp[,1], ytemp[,2]) -1L + asort2 <- order(ytemp[,ny-1]) -1L + + # call with a subset of the data + j <- which(ix== curve) + tfit <- .Call(Csurvfitresid, ytemp, asort1, asort2, is1[j], + casewt[j], p0[curve,], inf0[j,], times, + start.time, type=="auc") + if (ntime==1) \{ + if (type=="auc") D[j,] <- tfit[[2]] else D[j,] <- tfit[[1]] + \} else \{ + if (type=="auc") D[j,,] <- tfit[[2]] else D[j,,] <- tfit[[1]] + \} + \} + \} + # the C code makes time the last dimension, we want it to be second + if (ntime > 1) D <- aperm(D, c(1,3,2)) + \} + else \{ + # method 2 + \nwhypf{residpart2AJ21}{residpart2AJ2}{residpart2AJ22} + \} +\end{nwchunk} + +Can we speed this up? +An alternate is to look at the direct expansion. +\begin{align} + p(t) &= p(0) \prod_{d_j \le t} [I+ A(d_j)] \nonumber \\ + \frac{\partial p(t)}{\partial w_i} &= + \frac{\partial p(0)}{\partial w_i} \prod_{d_j \le t} [I+ A(d_j)] \\ + & + p(0)\sum_{d_j \le t} \left( \prod_{kk$. +Let $D(x)$ be the diagonal matrix. +\begin{align} +T_{01} &= D(p'(0))[I+ A(d_1)] & T_{02} &= T_{01}[I + A(d_2)] & + T_{03} &= T_{02} [I + A(d_3)] & \ldots \\ +T_{11} &= D(p(d_1)) B(d_1) & T_{12} &= T_{11}[I + A(d_2)] & + T_{13} &= T_{12}[I + A(d_3)] & \ldots \\ +T_{21} &= 0 & T_{22} &= D(p(d_2)) B(d_2) & T_{23} &= T_{22}[I+ A(d_2)] & \ldots \\ +T_{31} &= 0 & T_{32}&=0 & T_{33} &= D(p(d_3)) B(d_3) &\ldots +\end{align} +(According to the latex guide the above should be nicely spaced, but I get +equations that are touching. Why?) + +If $p(0)$ is a fixed value specified by the user then $p'(0)$ =0. +Otherwise $p(0)$ is the emprical distribution of the initial states, just +before the first death time $d_1$. Let $n_0$ be the (weighted) count of +subjects who are at risk at that time. +The $j$th row of $p'(0)$ is defined as the deviative wrt $w_i$ for a subject +who starts in state $j$. +If no one starts in state $j$ that row of the matrix will be 0, otherwise +it contains $(1-p_j(0)$ in the $jth$ element and $p_j(0)/n_0$ elsewhere. + +Define the matrix $W_{jk} = \sum_{l=1}^j T_{lk}$, with $W_{j0}=0$. +Then for someone who enters at time $s$ such that $d_a < s \le d_{a+1}$, +is censored or has an event at time $t$ such that $d_b \le t 0) \{ + # this death matches one of the reporting times + Wmat[,,i] <- diag(nstate) + Vmat[,,i] <- matrix(0, nstate, nstate) + \} + else \{ + Wmat[,,i] <- Hmat[,,i+1] %*% Wmat[,,i+1] + Vmat[,,i] <- delta[i] + Hmat[,,i+1] %*% Wmat[,,i+1] + \} + \} +\end{nwchunk} + +The above code has created the Wmat array for all reporting times and +for all the curves (if more than one). +Each of them reaches forward to the next reporting time. +Now work forward in time. + +\begin{nwchunk} +\nwhyp{residpart2AJ23}{residpart2AJ2}{residpart2AJ22}{residpart2AJ24}= + iterm <- array(0, dim=c(nstate, nstate, ndeath)) # term in equation + itemp <- vtemp <- matrix(0, nstate, nstate) # cumulative sum, temporary + isum <- isum2 <- iterm # cumulative sum + vsum <- vsum2 <- vterm <- iterm + for (i in 1:ndeath) \{ + j <- dindex[i] + n0 <- ifelse(fit$n.risk[j,] ==0, 1, fit$n.risk[j,]) # avoid 0/0 + iterm[,,i] <- ((fit$pstate[j-1,]/n0) * cmat[,,i]) %*% Wmat[,,i] + vterm[,,i] <- ((fit$pstate[j-1,]/n0) * cmat[,,i]) %*% Vmat[,,i] + itemp <- itemp + iterm[,,i] + vtemp <- vtemp + vterm[,,i] + isum[,,i] <- itemp + vsum[,,i] <- vtemp + j <- match(dindex[i], tindex, nomatch=0) + if (j>0) itemp <- vtemp <- matrix(0, nstate, nstate) # reset + isum2[,,i] <- itemp + vsum2[,,i] <- vtemp + \} + + # We want to add isum[state,, entry time] - isum[state,, exit time] for + # each subject, and for those with an a:b transition there will be an + # additional vector with -1, 1 in the a and b position. + i1 <- match(ystart, sort(unique(yindex)), nomatch=0) # start at 0 gives 0 + i2 <- match(yindex, sort(unique(yindex))) + D <- matrix(0., nrow(Y), nstate) + keep <- (Y[,2] <= max(times)) # any intervals after the last reporting time + # will have 0 influence + for (i in which(keep)) \{ + if (Y[i,3] !=0 && istate[i] != Y[i,3]) \{ + z <- fit$pstate[yindex[i]-1, istate[i]]/fit$n.risk[yindex[i], istate[i]] + temp <- double(nstate) + temp[istate[i]] = -z + temp[Y[i,3]] = z + temp <- temp %*% Wmat[,,i2[i]] - isum[istate[i],,i2[i]] + if (i1[i] >0) temp <- temp + isum2[istate[i],, i1[i]] + D[i,] <- temp + \} + else \{ + if (i1[i] >0) D[i,] = isum2[istate[i],,i1[i]] - isum[istate[i],, i2[i]] + else D[i,] = -isum[istate[i],, i2[i]] + \} + \} +\end{nwchunk} + +By design, each row of $Y$, and hence each row of $D$, corresponds to a unique +curve, and also to a unique period in the reporting intervals. +(Any Y intervals after the last reporting time will have D=0 for the row.) +If there are multiple reporting intervals, create an array with one +n by nstate slice for each. +If a row lies in the first interval, $D$ currently contains its influence +on that interval. It's influence on the second interval is the vector times +$\prod H(d_k)$ where $k$ is the set of event times $>$ the first reporting time +and $\le$ the second one. + +\begin{nwchunk} +\nwhypb{residpart2AJ24}{residpart2AJ2}{residpart2AJ23}= + Dsave <- D + if (!is.null(inf0)) \{ + # add in the initial influence, to the first row of each obs + # (inf0 was created on unsplit data) + j <- which(!duplicated(split$row)) + D[j,] <- D[j,] + (inf0%*% Hmat[,,1] %*% Wmat[,,1]) + \} + if (ntime > 1) \{ + interval <- findInterval(yindex, tindex, left.open=TRUE) + D2 <- array(0., dim=c(dim(D), ntime)) + D2[interval==0,,1] <- D[interval==0,] + for (i in 1:(ntime-1)) \{ + D2[interval==i,,i+1] = D[interval==i,] + j <- tindex[i] + D2[,,i+1] = D2[,,i+1] + D2[,,i] %*% (Hmat[,,j] %*% Wmat[,,j]) + \} + D <- D2 + \} + + # undo any artificial split + if (any(duplicated(split$row))) \{ + if (ntime==1) D <- rowsum(D, split$row) + else \{ + # rowsums has to be fooled + temp <- rowsum(matrix(D, ncol=(nstate*ntime)), split$row) + # then undo it + D <- array(temp, dim=c(nrow(temp), nstate, ntime)) + \} + \} +\end{nwchunk} +\section{Accelerated Failure Time models} +The \Verb!surveg! function fits parametric failure time models. +This includes accerated failure time models, the Weibull, log-normal, +and log-logistic models. +It also fits as well as censored linear regression; with left censoring +this is referred to in economics \emph{Tobit} regression. + +\subsection{Residuals} +The residuals for a \Verb!survreg! model are one of several types +\begin{description} + \item[response] residual [[y]] value on the scale of the original data + \item[deviance] an approximate deviance residual. A very bad idea + statistically, retained for the sake of backwards compatability. + \item[dfbeta] a matrix with one row per observation and one column per + parameter showing the approximate influence of each observation on + the final parameter value + \item[dfbetas] the dfbeta residuals scaled by the standard error of + each coefficient + \item[working] residuals on the scale of the linear predictor + \item[ldcase] likelihood displacement wrt case weights + \item[ldresp] likelihood displacement wrt response changes + \item[ldshape] likelihood displacement wrt changes in shape + \item[matrix] matrix of derivatives of the log-likelihood wrt paramters +\end{description} + +The other parameters are +\begin{description} + \item[rsigma] whether the scale parameters should be included in the + result for dfbeta results. I can think of no reason why one would not + want them --- unless of course the scale was fixed by the user, in + which case there is no parameter. + \item[collapse] optional vector of subject identifiers. This is for the + case where a subject has multiple observations in a data set, and one + wants to have residuals per subject rather than residuals per observation. + \item[weighted] whether the residuals should be multiplied by the case + weights. The sum of weighted residuals will be zero. +\end{description} + +The routine starts with standard stuff, checking arguments for +validity and etc. +The two cases of response or working residuals require +a lot less computation. and are the most common calls, so they are +taken care of first. + +\begin{nwchunk} +\nwhypn{residuals.survreg}= + # + # Residuals for survreg objects + residuals.survreg <- function(object, type=c('response', 'deviance', + 'dfbeta', 'dfbetas', 'working', 'ldcase', + 'ldresp', 'ldshape', 'matrix'), + rsigma =TRUE, collapse=FALSE, weighted=FALSE, ...) \{ + type <-match.arg(type) + n <- length(object$linear.predictors) + Terms <- object$terms + if(!inherits(Terms, "terms")) + stop("invalid terms component of object") + + # If the variance wasn't estimated then it has no error + if (nrow(object$var) == length(object$coefficients)) rsigma <- FALSE + + # If there was a cluster directive in the model statment then remove + # it. It does not correspond to a coefficient, and would just confuse + # things later in the code. + cluster <- untangle.specials(Terms,"cluster")$terms + if (length(cluster) >0 ) + Terms <- Terms[-cluster] + + strata <- attr(Terms, 'specials')$strata + intercept <- attr(Terms, "intercept") + response <- attr(Terms, "response") + weights <- object$weights + if (is.null(weights)) weighted <- FALSE + + \nwhypf{rsr-data1}{rsr-data}{rsr-data2} + \nwhypf{rsr-dist1}{rsr-dist}{rsr-dist2} + \nwhypf{rsr-resid1}{rsr-resid}{rsr-resid2} + \nwhypf{rsr-finish1}{rsr-finish}{rsr-finish2} + \} +\end{nwchunk} + +First retrieve the distribution, which is used multiple times. +The common case is a character string pointing to some element of +\Verb!survreg.distributions!, but the other is a user supplied +list of the form contained there. +Some distributions are defined as the transform of another in which +case we need to set \Verb!itrans! and \Verb?dtrans? and follow the link, +otherwise the transformation and its inverse are the identity. +\begin{nwchunk} +\nwhypb{rsr-dist2}{rsr-dist}{rsr-dist1}= + if (is.character(object$dist)) + dd <- survreg.distributions[[object$dist]] + else dd <- object$dist + ytype <- attr(y, "type") + if (is.null(dd$itrans)) \{ + itrans <- dtrans <-function(x)x + # reprise the work done in survreg to create a transformed y + if (ytype=='left') y[,2] <- 2- y[,2] + else if (type=='interval' && all(y[,3]<3)) y <- y[,c(1,3)] + \} + else \{ + itrans <- dd$itrans + dtrans <- dd$dtrans + + # reprise the work done in survreg to create a transformed y + tranfun <- dd$trans + exactsurv <- y[,ncol(y)] ==1 + if (any(exactsurv)) logcorrect <-sum(log(dd$dtrans(y[exactsurv,1]))) + + if (ytype=='interval') \{ + if (any(y[,3]==3)) + y <- cbind(tranfun(y[,1:2]), y[,3]) + else y <- cbind(tranfun(y[,1]), y[,3]) + \} + else if (ytype=='left') + y <- cbind(tranfun(y[,1]), 2-y[,2]) + else y <- cbind(tranfun(y[,1]), y[,2]) + \} + + if (!is.null(dd$dist)) dd <- survreg.distributions[[dd$dist]] + deviance <- dd$deviance + dens <- dd$density +\end{nwchunk} + +The next task is to decide what data we need. The response +is always needed, but is normally saved as a part of the +model. If it is a transformed distribution such as the +Weibull (a transform of the extreme value) the saved object +\Verb!y! is the transformed data, so we need to replicate that +part of the survreg() code. +(Why did I even allow for y=F in survreg? Because I was +mimicing the lm function --- oh the long, long consequences of +a design decision.) + +The covariate matrix \Verb!x! will be needed for all but +response, deviance, and working residuals. +If the model +included a strata() term then there will be multiple scales, +and the strata variable needs to be recovered. +The variable \Verb!sigma! is set to a scalar if there are no +strata, but otherwise to a vector with \Verb!n! elements containing +the appropriate scale for each subject. + +The leverage type residuals all need the second derivative +matrix. If there was a \Verb!cluster! statement in the model this +will be found in \Verb!naive.var!, otherwise in the \Verb?var? +component. +\begin{nwchunk} +\nwhypb{rsr-data2}{rsr-data}{rsr-data1}= + if (is.null(object$naive.var)) vv <- object$var + else vv <- object$naive.var + + need.x <- is.na(match(type, c('response', 'deviance', 'working'))) + if (is.null(object$y) || !is.null(strata) || (need.x & is.null(object[['x']]))) + mf <- stats::model.frame(object) + + if (is.null(object$y)) y <- model.response(mf) + else y <- object$y + + if (!is.null(strata)) \{ + temp <- untangle.specials(Terms, 'strata', 1) + Terms2 <- Terms[-temp$terms] + if (length(temp$vars)==1) strata.keep <- mf[[temp$vars]] + else strata.keep <- strata(mf[,temp$vars], shortlabel=TRUE) + strata <- as.numeric(strata.keep) + nstrata <- max(strata) + sigma <- object$scale[strata] + \} + else \{ + Terms2 <- Terms + nstrata <- 1 + sigma <- object$scale + \} + + if (need.x) \{ + x <- object[['x']] #don't grab xlevels component + if (is.null(x)) + x <- model.matrix(Terms2, mf, contrasts.arg=object$contrasts) + \} +\end{nwchunk} + + + +The most common residual is type response, which requires almost +no more work, for the others we need to create the matrix of +derivatives before proceeding. +We use the \Verb!center! component from the deviance function for the +distribution, which returns the data point \Verb!y! itself for an +exact, left, or right censored observation, and an appropriate +midpoint for interval censored ones. +\begin{nwchunk} +\nwhypb{rsr-resid2}{rsr-resid}{rsr-resid1}= + if (type=='response') \{ + yhat0 <- deviance(y, sigma, object$parms) + rr <- itrans(yhat0$center) - itrans(object$linear.predictor) + \} + else \{ + \nwhypf{rtr-deriv1}{rtr-deriv}{rtr-deriv2} + \nwhypf{rtr-resid21}{rtr-resid2}{rtr-resid22} + \} +\end{nwchunk} + +The matrix of derviatives is used in all of the other cases. +The starting point is the \Verb!density! function of the distribtion +which return a matrix with columns of +$F(x)$, $1-F(x)$, $f(x)$, $f'(x)/f(x)$ and $f''(x)/f(x)$. %' +The matrix type residual contains columns for each of +$$ + L_i \quad \frac{\partial L_i}{\partial \eta_i} + \quad \frac{\partial^2 L_i}{\partial \eta_i^2} + \quad \frac{\partial L_i}{\partial \log(\sigma)} + \quad \frac{\partial L_i}{\partial \log(\sigma)^2} + \quad \frac{\partial^2 L_i}{\partial \eta \partial\log(\sigma)} +$$ +where $L_i$ is the contribution to the log-likelihood from each +individual. +Note that if there are multiple scales, i.e. a strata() term in the +model, then terms 3--6 are the derivatives for that subject with +respect to their \emph{particular} scale factor; derivatives with +respect to all the other scales are zero for that subject. + +The log-likelihood can be written as +\begin{align*} +L &= \sum_{exact}\left[ \log(f(z_i)) -\log(\sigma_i) \right] + + \sum_{censored} \log \left( \int_{z_i^l}^{z_i^u} f(u)du \right) \\ + &\equiv \sum_{exact}\left[g_1(z_i) -\log(\sigma_i) \right] + + \sum_{censored} \log(g_2(z_i^l, z_i^u)) \\ + z_i &= (y_i - \eta_i)/ \sigma_i + \end{align*} +For the interval censored observations we have a $z$ defined at both the +lower and upper endpoints. +The linear predictor is $\eta = X\beta$. + +The derivatives are shown below. +Note that $f(-\infty) = f(\infty) = F(-\infty)=0$, +$F(\infty)=1$, $z^u = \infty$ for a right censored observation +and $z^l = -\infty$ for a left censored one. +\begin{align*} +\frac{\partial g_1}{\partial \eta} &= - \frac{1}{\sigma} + \left[\frac{f'(z)}{f(z)} \right] \\ %' +\frac{\partial g_2}{\partial \eta} &= - \frac{1}{\sigma} \left[ + \frac{f(z^u) - f(z^l)}{F(z^u) - F(z^l)} \right] \\ +\frac{\partial^2 g_1}{\partial \eta^2} &= \frac{1}{\sigma^2} + \left[ \frac{f''(z)}{f(z)} \right] + - (\partial g_1 / \partial \eta)^2 \\ +\frac{\partial^2 g_2}{\partial \eta^2} &= \frac{1}{\sigma^2} \left[ + \frac{f'(z^u) - f'(z^l)}{F(z^u) - F(z^l)} \right] + - (\partial g_2 / \partial \eta)^2 \\ +\frac{\partial g_1}{\partial \log\sigma} && - \left[ + \frac{zf'(z)}{f(z)} \right] \\ +\frac{\partial g_2}{\partial \log\sigma} &= - \left[ + \frac{z^uf(z^u) - z^lf(z^l)}{F(z^u) - F(z^l)} \right] \\ +\frac{\partial^2 g_1}{\partial (\log\sigma)^2} &=& \left[ + \frac{z^2 f''(z) + zf'(z)}{f(z)} \right] + - (\partial g_1 / \partial \log\sigma)^2 \\ +\frac{\partial^2 g_2}{\partial (\log\sigma)^2} &= \left[ + \frac{(z^u)^2 f'(z^u) - (z^l)^2f'(z_l) } + {F(z^u) - F(z^l)} \right] + - \partial g_1 /\partial \log\sigma(1+\partial g_1 / \partial \log\sigma) \\ +\frac{\partial^2 g_1}{\partial \eta \partial \log\sigma} &= + \frac{zf''(z)}{\sigma f(z)} + -\partial g_1/\partial \eta (1 + \partial g_1/\partial \log\sigma) \\ +\frac{\partial^2 g_2}{\partial \eta \partial \log\sigma} &= + \frac{z^uf'(z^u) - z^lf'(z^l)}{\sigma [F(z^u) - F(z^l)]} + -\partial g_2/\partial \eta (1 + \partial g_2/\partial \log\sigma) \\ +\end{align*} + +In the code \Verb!z! is the relevant point for exact, left, or right +censored data, and \Verb!z2! the upper endpoint for an interval censored one. +The variable \Verb!tdenom! contains the denominator for each subject (which +is the same for all derivatives for that subject). +For an interval censored observation we try to avoid numeric cancellation +by using the appropriate tail of the distribution. +For instance with $(z^l, z^u) = (12,15)$ the value of $F(x)$ will be very +near 1 and it is better to subtract two upper tail values $(1-F)$ than +two lower tail ones $F$. +\begin{nwchunk} +\nwhypb{rtr-deriv2}{rtr-deriv}{rtr-deriv1}= + status <- y[,ncol(y)] + eta <- object$linear.predictors + z <- (y[,1] - eta)/sigma + dmat <- dens(z, object$parms) + dtemp<- dmat[,3] * dmat[,4] #f' + if (any(status==3)) \{ + z2 <- (y[,2] - eta)/sigma + dmat2 <- dens(z2, object$parms) + \} + else \{ + dmat2 <- dmat #dummy values + z2 <- 0 + \} + + tdenom <- ((status==0) * dmat[,2]) + #right censored + ((status==1) * 1 ) + #exact + ((status==2) * dmat[,1]) + #left + ((status==3) * ifelse(z>0, dmat[,2]-dmat2[,2], + dmat2[,1] - dmat[,1])) #interval + g <- log(ifelse(status==1, dmat[,3]/sigma, tdenom)) #loglik + tdenom <- 1/tdenom + dg <- -(tdenom/sigma) *(((status==0) * (0-dmat[,3])) + #dg/ eta + ((status==1) * dmat[,4]) + + ((status==2) * dmat[,3]) + + ((status==3) * (dmat2[,3]- dmat[,3]))) + + ddg <- (tdenom/sigma^2) *(((status==0) * (0- dtemp)) + #ddg/eta^2 + ((status==1) * dmat[,5]) + + ((status==2) * dtemp) + + ((status==3) * (dmat2[,3]*dmat2[,4] - dtemp))) + + ds <- ifelse(status<3, dg * sigma * z, + tdenom*(z2*dmat2[,3] - z*dmat[,3])) + dds <- ifelse(status<3, ddg* (sigma*z)^2, + tdenom*(z2*z2*dmat2[,3]*dmat2[,4] - + z * z*dmat[,3] * dmat[,4])) + dsg <- ifelse(status<3, ddg* sigma*z, + tdenom *(z2*dmat2[,3]*dmat2[,4] - z*dtemp)) + deriv <- cbind(g, dg, ddg=ddg- dg^2, + ds = ifelse(status==1, ds-1, ds), + dds=dds - ds*(1+ds), + dsg=dsg - dg*(1+ds)) +\end{nwchunk} + +Now, we can calcultate the actual residuals case by case. +For the dfbetas there will be one column per coefficient, +so if there are strata column 4 of the deriv matrix needs +to be \emph{un}collapsed into a matrix with nstrata columns. +The same manipulation is needed for the ld residuals. +\begin{nwchunk} +\nwhypb{rtr-resid22}{rtr-resid2}{rtr-resid21}= + if (type=='deviance') \{ + yhat0 <- deviance(y, sigma, object$parms) + rr <- (-1)*deriv[,2]/deriv[,3] #working residuals + rr <- sign(rr)* sqrt(2*(yhat0$loglik - deriv[,1])) + \} + + else if (type=='working') rr <- (-1)*deriv[,2]/deriv[,3] + + else if (type=='dfbeta' || type== 'dfbetas' || type=='ldcase') \{ + score <- deriv[,2] * x # score residuals + if (rsigma) \{ + if (nstrata > 1) \{ + d4 <- matrix(0., nrow=n, ncol=nstrata) + d4[cbind(1:n, strata)] <- deriv[,4] + score <- cbind(score, d4) + \} + else score <- cbind(score, deriv[,4]) + \} + rr <- score %*% vv + # cause column names to be retained + # old: if (type=='dfbetas') rr[] <- rr %*% diag(1/sqrt(diag(vv))) + if (type=='dfbetas') rr <- rr * rep(1/sqrt(diag(vv)), each=nrow(rr)) + if (type=='ldcase') rr<- rowSums(rr*score) + \} + + else if (type=='ldresp') \{ + rscore <- deriv[,3] * (x * sigma) + if (rsigma) \{ + if (nstrata >1) \{ + d6 <- matrix(0., nrow=n, ncol=nstrata) + d6[cbind(1:n, strata)] <- deriv[,6]*sigma + rscore <- cbind(rscore, d6) + \} + else rscore <- cbind(rscore, deriv[,6] * sigma) + \} + temp <- rscore %*% vv + rr <- rowSums(rscore * temp) + \} + + else if (type=='ldshape') \{ + sscore <- deriv[,6] *x + if (rsigma) \{ + if (nstrata >1) \{ + d5 <- matrix(0., nrow=n, ncol=nstrata) + d5[cbind(1:n, strata)] <- deriv[,5] + sscore <- cbind(sscore, d5) + \} + else sscore <- cbind(sscore, deriv[,5]) + \} + temp <- sscore %*% vv + rr <- rowSums(sscore * temp) + \} + + else \{ #type = matrix + rr <- deriv + \} +\end{nwchunk} + +Finally the two optional steps of adding case weights and +collapsing over subject id. +\begin{nwchunk} +\nwhypb{rsr-finish2}{rsr-finish}{rsr-finish1}= + #case weights + if (weighted) rr <- rr * weights + + #Expand out the missing values in the result + if (!is.null(object$na.action)) \{ + rr <- naresid(object$na.action, rr) + if (is.matrix(rr)) n <- nrow(rr) + else n <- length(rr) + \} + + # Collapse if desired + if (!missing(collapse)) \{ + if (length(collapse) !=n) stop("Wrong length for 'collapse'") + rr <- drop(rowsum(rr, collapse)) + \} + + rr +\end{nwchunk} + + + + + + + + +\section{Survival curves} +The survfit function was set up as a method so that we could apply the +function to both formulas (to compute the Kaplan-Meier) and to coxph +objects. +The downside to this is that the manual pages get a little odd, but from +a programming perspective it was a good idea. +At one time, long long ago, we allowed the function to be called with +``Surv(time, status)'' as the formula, i.e., without a tilde. That was +a bad idea, now abandoned. + +A note on times: one of the things that drove me nuts was the problem of +``tied but not quite tied'' times. +As an example consider two values of 24173 = 23805 + 368. These are values from +an actual study with times in days. +However, the user chose to use age in years, and saved those values out +in a CSV file, resulting in values for the above of 66.18206708000000 +and 66.18206708000001. +The R phrase \code{unique(x)} sees these two values as distinct but +\code{table(x)} and \code{tapply} see it as a single value since they +first apply \code{factor} to the values, and that in turn uses +\code{as.character}. +A transition through CSV is not necessary to create the problem: +\begin{nwchunk} +\nwhypn{test}= + tfun <- function(start, gap) \{ + as.numeric(start)/365.25 - as.numeric(start + gap)/365.25 + \} + + test <- logical(200) + for (i in 1:200) \{ + test[i] <- tfun(as.Date("2010/01/01"), 29) == + tfun(as.Date("2010/01/01") + i, 29) + \} + table(test) +\end{nwchunk} +The number of FALSE entries in the table depends on machine, compiler, +and a host of other issues. +There is discussion of this general issue in the R FAQ: ``why doesn't R +think these numbers are equal''. +The Kaplan-Meier and Cox model both pay careful attention to ties, and +so both now use the \code{aeqSurv} routine to first preprocess +the time data. It uses the same rules as \code{all.equal} to +adjudicate ties and near ties. + + +\begin{nwchunk} +\nwhypf{survfit1}{survfit}{survfit2}= + survfit <- function(formula, ...) \{ + UseMethod("survfit") + \} + + \nwhypf{survfit-formula1}{survfit-formula}{survfit-formula2} + \nwhypf{survfit-subscript1}{survfit-subscript}{survfit-subscript2} + \nwhypf{survfit-Surv1}{survfit-Surv}{survfit-Surv2} +\end{nwchunk} + +The result of a survival curve will have a \code{surv} or \code{pstate} +component that is a vector or a matrix, and an optional strata component. +From a user's point of view this is an object with [strata, newdata, state] +as dimensions, where only 1, 2 or all three of these may appear. +The first is always present, and is essentially the number of distinct +curves created by the right-hand side of the equation (or by the strata in +a coxph model). +The newdata portion appears for survival curves from a Cox model, when curves +for multiple covariate patterns were requested; +the state portion only from a multi-state model; or both for a multi-state +Cox model. +The \code{surv} component contains the time points for the first stratum, +the second, third, etc stacked one above the other. +As with R matrices, if only 1 subscript is given for an array or matrix of +curves, we treat the collection of curves as a vector of curves. +We need to make sure that the new object has the same order of elements as +the old -- users count on this. + +\begin{nwchunk} +\nwhypb{survfit-subscript2}{survfit-subscript}{survfit-subscript1}= + dim.survfit <- function(x) \{ + d1name <- "strata" + d2name <- "data" + d3name <- "states" + if (is.null(x$strata)) \{d1 <- d1name <- NULL\} else d1 <- length(x$strata) + if (is.null(x$newdata)) \{d2 <- d2name <- NULL\} else d2 <- nrow(x$newdata) + if (is.null(x$states)) \{d3 <- d3name <- NULL\} else d3 <- length(x$states) + + if (inherits(x, "survfitcox") && is.null(d2) && is.null(d3) && + is.matrix(x$surv)) \{ + # older style survfit.coxph object, before I added newdata to the output + d2name <- "data" + d2 <- ncol(x$surv) + \} + + dd <- c(d1, d2, d3) + names(dd) <- c(d1name, d2name, d3name) + dd + \} + + # there is a separate function for survfitms objects + "[.survfit" <- function(x, ... , drop=TRUE) \{ + nmatch <- function(indx, target) \{ + # This function lets R worry about character, negative, or + # logical subscripts. + # It always returns a set of positive integer indices + temp <- 1:length(target) + names(temp) <- target + temp[indx] + \} + + if (!inherits(x, "survfit")) stop("[.survfit called on non-survfit object") + ndots <- ...length() # the simplest, but not avail in R 3.4 + # ndots <- length(list(...))# fails if any are missing, e.g. fit[,2] + # ndots <- if (missing(drop)) nargs()-1 else nargs()-2 # a workaround + + dd <- dim(x) + # for dd=NULL, an object with only one curve, x[1] is always legal + if (is.null(dd)) dd <- c(strata=1L) # survfit object with only one curve + dtype <- match(names(dd), c("strata", "data", "states")) + + if (ndots >0 && !missing(..1)) i <- ..1 else i <- NULL + if (ndots> 1 && !missing(..2)) j <- ..2 else j <- NULL + + if (ndots > length(dd)) + stop("incorrect number of dimensions") + if (length(dtype) > 2) stop("invalid survfit object") # should never happen + if (is.null(i) && is.null(j)) \{ + # called with no subscripts given -- return x untouched + return(x) + \} + + # Code below is easier if "i" is always the strata + if (dtype[1] !=1) \{ + dtype <- c(1, dtype) + j <- i; i <- NULL + dd <- c(1, dd) + ndots <- ndots +1 + \} + + # We need to make a new one + newx <- vector("list", length(x)) + names(newx) <- names(x) + for (k in c("logse", "version", "conf.int", "conf.type", "type", "call")) + if (!is.null(x[[k]])) newx[[k]] <- x[[k]] + class(newx) <- class(x) + + if (ndots== 1 && length(dd)==2) \{ + # one subscript given for a two dimensional object + # If one of the dimensions is 1, it is easier for me to fill in i and j + if (dd[1]==1) \{j <- i; i<- 1\} + else if (dd[2]==1) j <- 1 + else \{ + # the user has a mix of rows/cols + index <- 1:prod(dd) + itemp <- matrix(index, nrow=dd[1]) + keep <- itemp[i] # illegal subscripts will generate an error + if (length(keep) == length(index) && all(keep==index)) return(x) + + ii <- row(itemp)[keep] + jj <- col(itemp)[keep] + # at this point we have a matrix subscript of (ii, jj) + # expand into a long pair of rows and cols + temp <- split(seq(along.with=x$time), + rep(1:length(x$strata), x$strata)) + indx1 <- unlist(temp[ii]) # rows of the surv object + indx2 <- rep(jj, x$strata[ii]) + + # return with each curve as a separate strata + newx$n <- x$n[ii] + for (k in c("time", "n.risk", "n.event", "n.censor", "n.enter")) + if (!is.null(x[[k]])) newx[[k]] <- (x[[k]])[indx1] + k <- cbind(indx1, indx2) + for (j in c("surv", "std.err", "upper", "lower", "cumhaz", + "std.chaz", "influence.surv", "influence.chaz")) + if (!is.null(x[[j]])) newx[[j]] <- (x[[j]])[k] + temp <- x$strata[ii] + names(temp) <- 1:length(ii) + newx$strata <- temp + return(newx) + \} + \} + + # irow will be the rows that need to be taken + # j the columns (of present) + if (is.null(x$strata)) \{ + if (is.null(i) || all(i==1)) irow <- seq(along.with=x$time) + else stop("subscript out of bounds") + newx$n <- x$n + \} + else \{ + if (is.null(i)) indx <- seq(along.with= x$strata) + else indx <- nmatch(i, names(x$strata)) #strata to keep + if (any(is.na(indx))) + stop(paste("strata", + paste(i[is.na(indx)], collapse=' '), + 'not matched')) + # Now, indx may not be in order: some can use curve[3:2] to reorder + # The list/unlist construct will reorder the data + temp <- split(seq(along.with =x$time), + rep(1:length(x$strata), x$strata)) + irow <- unlist(temp[indx]) + + if (length(indx) <=1 && drop) newx$strata <- NULL + else newx$strata <- x$strata[i] + + newx$n <- x$n[indx] + if (length(indx) ==1 & drop) x$strata <- NULL + else newx$strata <- x$strata[indx] + \} + + if (length(dd)==1) \{ # no j dimension + for (k in c("time", "n.risk", "n.event", "n.censor", "n.enter", + "surv", "std.err", "cumhaz", "std.chaz", "upper", "lower", + "influence.surv", "influence.chaz")) + if (!is.null(x[[k]])) newx[[k]] <- (x[[k]])[irow] + \} + + else \{ # 2 dimensional object + if (is.null(j)) j <- seq.int(ncol(x$surv)) + # If the curve has been selected by strata and keep has only + # one row, we don't want to lose the second subscript too + if (length(irow)==1) drop <- FALSE + + for (k in c("time", "n.risk", "n.event", "n.censor", "n.enter")) + if (!is.null(x[[k]])) newx[[k]] <- (x[[k]])[irow] + for (k in c("surv", "std.err", "cumhaz", "std.chaz", "upper", "lower", + "influence.surv", "influence.chaz")) + if (!is.null(x[[k]])) newx[[k]] <- (x[[k]])[irow, j, drop=drop] + \} + newx + \} +\end{nwchunk} + +\subsection{Kaplan-Meier} +The most common use of the survfit function is with a formula as the first +argument, and the most common outcome of such a call is a Kaplan-Meier +curve. + +The id argument is from an older version of the competing risks code; most +people will use \Verb!cluster(id)! in the formula instead. +The istate argument only applies to competing risks, but don't print +an error message if it is accidentally there. + +\begin{nwchunk} +\nwhypb{survfit-formula2}{survfit-formula}{survfit-formula1}= + survfit.formula <- function(formula, data, weights, subset, + na.action, stype=1, ctype=1, + id, cluster, robust, istate, + timefix=TRUE, etype, error, ...) \{ + + Call <- match.call() + Call[[1]] <- as.name('survfit') #make nicer printout for the user + \nwhyp{survfit.formula-getdata2}{survfit.formula-getdata}{survfit.formula-getdata1}{survfit.formula-getdata3} + + # Deal with the near-ties problem + if (!is.logical(timefix) || length(timefix) > 1) + stop("invalid value for timefix option") + if (timefix) newY <- aeqSurv(Y) else newY <- Y + + if (missing(robust)) robust <- NULL + # Call the appropriate helper function + if (attr(Y, 'type') == 'left' || attr(Y, 'type') == 'interval') + temp <- survfitTurnbull(X, newY, casewt, ...) + else if (attr(Y, 'type') == "right" || attr(Y, 'type')== "counting") + temp <- survfitKM(X, newY, casewt, stype=stype, ctype=ctype, id=id, + cluster=cluster, robust=robust, ...) + else if (attr(Y, 'type') == "mright" || attr(Y, "type")== "mcounting") + temp <- survfitCI(X, newY, weights=casewt, stype=stype, ctype=ctype, + id=id, cluster=cluster, robust=robust, + istate=istate, ...) + else \{ + # This should never happen + stop("unrecognized survival type") + \} + + # If a stratum had no one beyond start.time, the length 0 gives downstream + # failure, e.g., there is no sensible printout for summary(fit, time= 100) + # for such a curve + temp$strata <- temp$strata[temp$strata >0] + if (is.null(temp$states)) class(temp) <- 'survfit' + else class(temp) <- c("survfitms", "survfit") + + if (!is.null(attr(mf, 'na.action'))) + temp$na.action <- attr(mf, 'na.action') + + temp$call <- Call + temp + \} +\end{nwchunk} + +This chunk of code is shared with resid.survfit +\begin{nwchunk} +\nwhypb{survfit.formula-getdata3}{survfit.formula-getdata}{survfit.formula-getdata2}= + # create a copy of the call that has only the arguments we want, + # and use it to call model.frame() + indx <- match(c('formula', 'data', 'weights', 'subset','na.action', + 'istate', 'id', 'cluster', "etype"), names(Call), nomatch=0) + #It's very hard to get the next error message other than malice + # eg survfit(wt=Surv(time, status) ~1) + if (indx[1]==0) stop("a formula argument is required") + temp <- Call[c(1, indx)] + temp[[1L]] <- quote(stats::model.frame) + mf <- eval.parent(temp) + + Terms <- terms(formula, c("strata", "cluster")) + ord <- attr(Terms, 'order') + if (length(ord) & any(ord !=1)) + stop("Interaction terms are not valid for this function") + + n <- nrow(mf) + Y <- model.response(mf) + if (inherits(Y, "Surv2")) \{ + # this is Surv2 style data + # if there are any obs removed due to missing, remake the model frame + if (length(attr(mf, "na.action"))) \{ + temp$na.action <- na.pass + mf <- eval.parent(temp) + \} + if (!is.null(attr(Terms, "specials")$cluster)) + stop("cluster() cannot appear in the model statement") + new <- surv2data(mf) + mf <- new$mf + istate <- new$istate + id <- new$id + Y <- new$y + if (anyNA(mf[-1])) \{ #ignore the response variable still found there + if (missing(na.action)) temp <- get(getOption("na.action"))(mf[-1]) + else temp <- na.action(mf[-1]) + omit <- attr(temp, "na.action") + mf <- mf[-omit,] + Y <- Y[-omit] + id <- id[-omit] + istate <- istate[-omit] + \} + n <- nrow(mf) + \} + else \{ + if (!is.Surv(Y)) stop("Response must be a survival object") + id <- model.extract(mf, "id") + istate <- model.extract(mf, "istate") + \} + if (n==0) stop("data set has no non-missing observations") + + casewt <- model.extract(mf, "weights") + if (is.null(casewt)) casewt <- rep(1.0, n) + else \{ + if (!is.numeric(casewt)) stop("weights must be numeric") + if (any(!is.finite(casewt))) stop("weights must be finite") + if (any(casewt <0)) stop("weights must be non-negative") + casewt <- as.numeric(casewt) # transform integer to numeric + \} + + if (!is.null(attr(Terms, 'offset'))) warning("Offset term ignored") + + cluster <- model.extract(mf, "cluster") + temp <- untangle.specials(Terms, "cluster") + if (length(temp$vars)>0) \{ + if (length(cluster) >0) stop("cluster appears as both an argument and a model term") + if (length(temp$vars) > 1) stop("can not have two cluster terms") + cluster <- mf[[temp$vars]] + Terms <- Terms[-temp$terms] + \} + + ll <- attr(Terms, 'term.labels') + if (length(ll) == 0) X <- factor(rep(1,n)) # ~1 on the right + else X <- strata(mf[ll]) + + # Backwards support for the now-depreciated etype argument + etype <- model.extract(mf, "etype") + if (!is.null(etype)) \{ + if (attr(Y, "type") == "mcounting" || + attr(Y, "type") == "mright") + stop("cannot use both the etype argument and mstate survival type") + if (length(istate)) + stop("cannot use both the etype and istate arguments") + status <- Y[,ncol(Y)] + etype <- as.factor(etype) + temp <- table(etype, status==0) + + if (all(rowSums(temp==0) ==1)) \{ + # The user had a unique level of etype for the censors + newlev <- levels(etype)[order(-temp[,2])] #censors first + \} + else newlev <- c(" ", levels(etype)[temp[,1] >0]) + status <- factor(ifelse(status==0,0, as.numeric(etype)), + labels=newlev) + + if (attr(Y, 'type') == "right") + Y <- Surv(Y[,1], status, type="mstate") + else if (attr(Y, "type") == "counting") + Y <- Surv(Y[,1], Y[,2], status, type="mstate") + else stop("etype argument incompatable with survival type") + \} +\end{nwchunk} + +Once upon a time I allowed survfit to be called without the +`\textasciitilde 1' portion of the formula. +This was a mistake for multiple reasons, but the biggest problem is timing. +If the subject has a data statement but the first argument is not a formula, +R needs to evaluate Surv(t,s) to know that it is a survival object, +but it also needs to know that this is a survival object before evaluation +in order to dispatch the correct method. +The method below helps give a useful error message in some cases. +\begin{nwchunk} +\nwhypb{survfit-Surv2}{survfit-Surv}{survfit-Surv1}= + survfit.Surv <- function(formula, ...) + stop("the survfit function requires a formula as its first argument") +\end{nwchunk} + + +The last peice in this file is the function to create confidence +intervals. It is called from multiple different places so it is well to +have one copy. +If $p$ is the survival probability and $s(p)$ its standard error, +we can do confidence intervals on the simple scale of +$ p \pm 1.96 s(p)$, but that does not have very good properties. +Instead use a transformation $y = f(p)$ for which the standard error is +$s(p) f'(p)$, leading to the confidence interval +\begin{equation*} + f^{-1}\left(f(p) +- 1.96 s(p)f'(p) \right) + \end{equation*} +Here are the supported transformations. +\begin{center} + \begin{tabular}{rccc} + &$f$& $f'$ & $f^{-1}$ \\ \hline +log & $\log(p)$ & $1/p$ & $ \exp(y)$ \\ +log-log & $\log(-\log(p))$ & $1/\left[ p \log(p) \right]$ & + $\exp(-\exp(y)) $ \\ +logit & $\log(p/1-p)$ & $1/[p (1-p)]$ & $1- 1/\left[1+ \exp(y)\right]$ \\ +arcsin & $\arcsin(\sqrt{p})$ & $1/(2 \sqrt{p(1-p)})$ &$\sin^2(y)$ \\ + +\end{tabular} \end{center} +Plain intervals can give limits outside of (0,1), we truncate them when this +happens. The log intervals can give an upper limit greater than 1, but the +lower limit is always valid, and the log-log and logit. The arcsin require +truncation in the middle of the formula. +In all cases we return NA as the CI for survival=0: it makes the graphs look +better. + +Some of the underlying routines compute the standard error of $p$ and some +the standard error of $\log(p)$. The \code{selow} argument is used for the +modified lower limits of Dory and Korn. When this is used for cumulative +hazards the ulimit arg will be FALSE: no upper limit of 1. + +\begin{nwchunk} +\nwhypb{survfit2}{survfit}{survfit1}= + survfit_confint <- function(p, se, logse=TRUE, conf.type, conf.int, + selow, ulimit=TRUE) \{ + zval <- qnorm(1- (1-conf.int)/2, 0,1) + if (missing(selow)) scale <- 1.0 + else scale <- ifelse(selow==0, 1.0, selow/se) # avoid 0/0 at the origin + if (!logse) se <- ifelse(se==0, 0, se/p) # se of log(survival) = log(p) + + if (conf.type=='plain') \{ + se2 <- se* p * zval # matches equation 4.3.1 in Klein & Moeschberger + if (ulimit) list(lower= pmax(p -se2*scale, 0), upper = pmin(p + se2, 1)) + else list(lower= pmax(p -se2*scale, 0), upper = p + se2) + \} + else if (conf.type=='log') \{ + #avoid some "log(0)" messages + xx <- ifelse(p==0, NA, p) + se2 <- zval* se + temp1 <- exp(log(xx) - se2*scale) + temp2 <- exp(log(xx) + se2) + if (ulimit) list(lower= temp1, upper= pmin(temp2, 1)) + else list(lower= temp1, upper= temp2) + \} + else if (conf.type=='log-log') \{ + xx <- ifelse(p==0 | p==1, NA, p) + se2 <- zval * se/log(xx) + temp1 <- exp(-exp(log(-log(xx)) - se2*scale)) + temp2 <- exp(-exp(log(-log(xx)) + se2)) + list(lower = temp1 , upper = temp2) + \} + else if (conf.type=='logit') \{ + xx <- ifelse(p==0, NA, p) # avoid log(0) messages + se2 <- zval * se *(1 + xx/(1-xx)) + + temp1 <- 1- 1/(1+exp(log(p/(1-p)) - se2*scale)) + temp2 <- 1- 1/(1+exp(log(p/(1-p)) + se2)) + list(lower = temp1, upper=temp2) + \} + else if (conf.type=="arcsin") \{ + xx <- ifelse(p==0, NA, p) + se2 <- .5 *zval*se * sqrt(xx/(1-xx)) + list(lower= (sin(pmax(0, asin(sqrt(xx)) - se2*scale)))^2, + upper= (sin(pmin(pi/2, asin(sqrt(xx)) + se2)))^2) + \} + else stop("invalid conf.int type") + \} +\end{nwchunk} +\subsection{Kaplan-Meier} +This routine has been rewritten more times than any other in the package, +as we trade off simplicty of the code with execution speed. +This version does all of the oranizational work in S and calls a C +routine for each separate curve. +The first code did everything in C but was too hard to maintain and the most +recent prior function did nearly everything in S. +Introduction of robust variance +prompted a movement of more of the code into C since that calculation +is computationally intensive. + +\begin{nwchunk} +\nwhypn{survfitKM}= + survfitKM <- function(x, y, weights=rep(1.0,length(x)), + stype=1, ctype=1, + se.fit=TRUE, + conf.int= .95, + conf.type=c('log', 'log-log', 'plain', 'none', + 'logit', "arcsin"), + conf.lower=c('usual', 'peto', 'modified'), + start.time, id, cluster, robust, influence=FALSE, + type) \{ + + if (!missing(type)) \{ + if (!is.character(type)) stop("type argument must be character") + # older style argument is allowed + temp <- charmatch(type, c("kaplan-meier", "fleming-harrington", "fh2")) + if (is.na(temp)) stop("invalid value for 'type'") + type <- c(1,3,4)[temp] + \} + else \{ + if (!(ctype %in% 1:2)) stop("ctype must be 1 or 2") + if (!(stype %in% 1:2)) stop("stype must be 1 or 2") + type <- as.integer(2*stype + ctype -2) + \} + + conf.type <- match.arg(conf.type) + conf.lower<- match.arg(conf.lower) + if (is.logical(conf.int)) \{ + # A common error is for users to use "conf.int = FALSE" + # it's not correct, but allow it + if (!conf.int) conf.type <- "none" + conf.int <- .95 + \} + + if (!is.Surv(y)) stop("y must be a Surv object") + if (attr(y, 'type') != 'right' && attr(y, 'type') != 'counting') + stop("Can only handle right censored or counting data") + ny <- ncol(y) # Will be 2 for right censored, 3 for counting + # The calling routine has used 'strata' on x, so it is a factor with + # no unused levels. But just in case a user called this... + if (!is.factor(x)) stop("x must be a factor") + xlev <- levels(x) # Will supply names for the curves + x <- as.integer(x) # keep the integer index + + if (missing(start.time)) time0 <- min(0, y[,ny-1]) + else time0 <- start.time + + # The user can call with cluster, id, robust, or any combination + # Default for robust: if cluster or any id with > 1 event or + # any weights that are not 0 or 1, then TRUE + # If only id, treat it as the cluster too + has.cluster <- !(missing(cluster) || length(cluster)==0) + has.id <- !(missing(id) || length(id)==0) + has.rwt<- (!missing(weights) && any(weights != floor(weights))) + #has.rwt <- FALSE # we are rethinking this + has.robust <- !missing(robust) && !is.null(robust) + if (has.id) id <- as.factor(id) + + if (missing(robust) || is.null(robust)) \{ + if (influence) \{ + robust <- TRUE + if (!(has.cluster || has.id)) \{ + cluster <- seq(along=x) + has.cluster <- TRUE + \} + \} + else if (has.cluster || has.rwt || + (has.id && anyDuplicated(id[y[,ncol(y)]==1]))) + robust <- TRUE + else robust <- FALSE + \} + if (!is.logical(robust)) stop("robust must be TRUE/FALSE") + + if (has.cluster) \{ + if (!robust) \{ + warning("cluster specified with robust=FALSE, cluster ignored") + ncluster <- 0 + clname <- NULL + \} + else \{ + if (is.factor(cluster)) \{ + clname <- levels(cluster) + cluster <- as.integer(cluster) + \} else \{ + clname <- sort(unique(cluster)) + cluster <- match(cluster, clname) + \} + ncluster <- length(clname) + \} + \} else if (robust) \{ + if (has.id) \{ + # treat the id as both identifier and clustering + clname <- levels(id) + cluster <- as.integer(id) + ncluster <- length(clname) + \} + else if (ncol(y)==2 || !has.robust) \{ + # create our own clustering + n <- nrow(y) + cluster <- 1:n + ncluster <- n + clname <- 1:n + \} + else stop("id or cluster option required") + \} else ncluster <- 0 + + if (is.logical(influence)) \{ + # TRUE/FALSE is treated as all or nothing + if (!influence) influence <- 0L + else influence <- 3L + \} + else if (!is.numeric(influence)) + stop("influence argument must be numeric or logical") + if (!(influence %in% 0:3)) stop("influence argument must be 0, 1, 2, or 3") + else influence <- as.integer(influence) + if (!robust && influence >0) \{ + warning("robust=FALSE implies influence=FALSE") + influence <- 0L + \} + + if (!se.fit) \{ + # if the user asked for no standard error, skip any robust computation + ncluster <- 0L + influence <- 0L + \} + + # if start.time was set, delete obs if necessary + keep <- y[,ny-1] >= time0 + if (!all(keep)) \{ + y <- y[keep,] + if (length(id) >0) id <- id[keep] + if (length(cluster) >0) cluster <- cluster[keep] + x <- x[keep] + weights <- weights[keep] + \} + + + \nwhypf{survfitKM-compute1}{survfitKM-compute}{survfitKM-compute2} + \nwhypf{survfitKM-finish1}{survfitKM-finish}{survfitKM-finish2} + \} +\end{nwchunk} + +At each event time we have +\begin{itemize} + \item n(t) = number at risk = sum of weigths for those at risk + \item d(t) = number of events = sum of weights for the deaths + \item e(t) = unweighted number of events +\end{itemize} +From this we can calculate the Kapan-Meier and Nelson-Aalen estimates. +The Fleming-Harrington estimate is the analog of the Efron approximation +in a Cox model. +When there are no case weights the FH idea is quite simple. +Assume that the real data is not tied, but we saw a coarsened version. +If we see 3 events out of 10 subjects at risk the NA increment is 3/10 but the +FH is 1/10 + 1/9 + 1/8, it is what we would have seen with the +uncoarsened data. +If there are case weights we give each of the 3 terms a 1/3 chance of being +the first, second, or third event +\begin{align*} + KM(t) &= KM(t-) (1- d(t)/n(t) \\ + NA(t) &= NA(t-) + d(t)/n(t) \\ + FH(t) &= FH(t-) + \sum_{i=1}^{3} \frac{(d(t)/3}{n(t)- d(t)(i-1)/3} +\end{align*} + +When one of these 3 subjects has an event but continues, which can happen with +start/stop data, then this gets trickier: the second $d$ in the last equation +above should include only the other 2. The idea is that each of those will +certainly be present for the first event, has 2/3 chance of being present +for the second, and 1/3 for the third. +If we think of the size of the denominator as a random variable $Z$, an +exact solution would use $E(1/Z)$, the FH uses $1/E(Z)$ and the NA uses +$1/\max(Z)$ as the denominator for each of the 3 deaths. + +One problem with survival is near ties in Y: table, unique, ==, etc. can +do different things in this case. Luckily, the parent survfit routine +has dealt with that by using the \code{aeqSurv} function. + +The underlying C code allows the sort1/sort2 vectors to be a different +length than y, weights, and cluster. +When there is only one curve we use that to our advantage to avoid creating +a new copy of the last 3, passing in the original data. +When there are multiple curves I had an internal debate about efficiency. +Is is better to make a subset of y for each curve = more memory, or keep the +original y and address a different subset in each C call = worse memory +cache performance? I don't know the answer. +In either case the cluster vector needs to be re-done for each group. +Say that curve 1 uses subjects 1-10 and curve 2 uses 11-n: we don't want +the first curve to compute or keep the zero influence values for all the +subjects who are not in it. +Especially when returning the influence matrix, which can get too large +for memory. + +If ny==3 and has.id is true, then do some extra setup work, which is to +create a position vector of 1=first obs for the subject, 2 = last, 3=both, +0= other, for each set of back to back times. +This is used to prevent counting a subject with data of (0,10], (10,15] in +both the censored at 10 and entered at 10 totals. +We assume the data has been vetted to prevent overlapping intervals, so that +it suffices to sort by ending time. If a subject has holes in their timeline +they will have more than one first and last indicator. + +\begin{nwchunk} +\nwhypb{survfitKM-compute2}{survfitKM-compute}{survfitKM-compute1}= + if (ny==3 & has.id) position <- survflag(y, id) + else position <- integer(0) + + if (length(xlev) ==1) \{# only one group + if (ny==2) \{ + sort1 <- NULL + sort2 <- order(y[,1]) + \} + else \{ + sort2 <- order(y[,2]) + sort1 <- order(y[,1]) + \} + toss <- (y[sort2, ny-1] < time0) + if (any(toss)) \{ + # Some obs were removed by the start.time argument + sort2 <- sort2[!toss] + if (ny ==3) \{ + index <- match(which(toss), sort1) + sort1 <- sort1[-index] + \} + \} + n.used <- length(sort2) + if (ncluster > 0) + cfit <- .Call(Csurvfitkm, y, weights, sort1-1L, sort2-1L, type, + cluster-1L, ncluster, position, influence) + else cfit <- .Call(Csurvfitkm, y, weights, sort1-1L, sort2-1L, type, + 0L, 0L, position, influence) + \} else \{ + # multiple groups + ngroup <- length(xlev) + cfit <- vector("list", ngroup) + n.used <- integer(ngroup) + if (influence) clusterid <- cfit # empty list of group id values + for (i in 1:ngroup) \{ + keep <- which(x==i & y[,ny-1] >= time0) + if (length(keep) ==0) next; # rare case where all are < start.time + ytemp <- y[keep,] + n.used[i] <- nrow(ytemp) + if (ny==2) \{ + sort1 <- NULL + sort2 <- order(ytemp[,1]) + \} + else \{ + sort2 <- order(ytemp[,2]) + sort1 <- order(ytemp[,1]) + \} + + # Cluster is a nuisance: every curve might have a different set + # We need to relabel them from 1 to "number of unique clusters in this + # curve for the C routine + if (ncluster > 0) \{ + c2 <- cluster[keep] + c.unique <- sort(unique(c2)) + nc <- length(c.unique) + c2 <- match(c2, c.unique) # renumber them + if (influence >0) \{ + clusterid[[i]] <-c.unique + \} + \} + + if (ncluster > 0) + cfit[[i]] <- .Call(Csurvfitkm, ytemp, weights[keep], sort1 -1L, + sort2 -1L, type, + c2 -1L, length(c.unique), position, influence) + else cfit[[i]] <- .Call(Csurvfitkm, ytemp, weights[keep], sort1 -1L, + sort2 -1L, type, + 0L, 0L, position, influence) + \} + \} +\end{nwchunk} + +\begin{nwchunk} +\nwhypb{survfitKM-finish2}{survfitKM-finish}{survfitKM-finish1}= + # create the survfit object + if (length(n.used) == 1) \{ + rval <- list(n= length(x), + time= cfit$time, + n.risk = cfit$n[,4], + n.event= cfit$n[,5], + n.censor=cfit$n[,6], + surv = cfit$estimate[,1], + std.err = cfit$std[,1], + cumhaz = cfit$estimate[,2], + std.chaz = cfit$std[,2]) + \} else \{ + strata <- sapply(cfit, function(x) if (is.null(x$n)) 0L else nrow(x$n)) + names(strata) <- xlev + # we need to collapse the curves + rval <- list(n= as.vector(table(x)), + time = unlist(lapply(cfit, function(x) x$time)), + n.risk= unlist(lapply(cfit, function(x) x$n[,4])), + n.event= unlist(lapply(cfit, function(x) x$n[,5])), + n.censor=unlist(lapply(cfit, function(x) x$n[,6])), + surv = unlist(lapply(cfit, function(x) x$estimate[,1])), + std.err =unlist(lapply(cfit, function(x) x$std[,1])), + cumhaz =unlist(lapply(cfit, function(x) x$estimate[,2])), + std.chaz=unlist(lapply(cfit, function(x) x$std[,2])), + strata=strata) + if (ny==3) rval$n.enter <- unlist(lapply(cfit, function(x) x$n[,8])) + \} + + if (ny ==3) \{ + rval$n.enter <- cfit$n[,8] + rval$type <- "counting" + \} + else rval$type <- "right" + + if (se.fit) \{ + rval$logse = (ncluster==0 || (type==2 || type==4)) # se(log S) or se(S) + rval$conf.int = conf.int + rval$conf.type= conf.type + if (conf.lower != "usual") rval$conf.lower = conf.lower + + if (conf.lower == "modified") \{ + nstrat = length(n.used) + events <- rval$n.event >0 + if (nstrat ==1) events[1] <- TRUE + else events[1 + cumsum(c(0, rval$strata[-nstrat]))] <- TRUE + zz <- 1:length(events) + n.lag <- rep(rval$n.risk[events], diff(c(zz[events], 1+max(zz)))) + # + # n.lag = the # at risk the last time there was an event (or + # the first time of a strata) + # + \} + std.low <- switch(conf.lower, + 'usual' = rval$std.err, + 'peto' = sqrt((1-rval$surv)/ rval$n.risk), + 'modified' = rval$std.err * sqrt(n.lag/rval$n.risk)) + + if (conf.type != "none") \{ + ci <- survfit_confint(rval$surv, rval$std.err, logse=rval$logse, + conf.type, conf.int, std.low) + rval <- c(rval, list(lower=ci$lower, upper=ci$upper)) + \} + \} else \{ + # for consistency don't return the se if std.err=FALSE + rval$std.err <- NULL + rval$std.chaz <- NULL + \} + + # Add the influence, if requested by the user + # remember, if type= 3 or 4, the survival influence has to be constructed. + if (influence > 0) \{ + if (type==1 | type==2) \{ + if (influence==1 || influence ==3) \{ + if (length(xlev)==1) \{ + rval$influence.surv <- cfit$influence1 + row.names(rval$influence.surv) <- clname + \} + else \{ + temp <- vector("list", ngroup) + for (i in 1:ngroup) \{ + temp[[i]] <- cfit[[i]]$influence1 + row.names(temp[[i]]) <- clname[clusterid[[i]]] + \} + rval$influence.surv <- temp + \} + \} + if (influence==2 || influence==3) \{ + if (length(xlev)==1) \{ + rval$influence.chaz <- cfit$influence2 + row.names(rval$influence.chaz) <- clname + \} + else \{ + temp <- vector("list", ngroup) + for (i in 1:ngroup) \{ + temp[[i]] <- cfit[[i]]$influence2 + row.names(temp[[i]]) <- clname[clusterid[[i]]] + \} + rval$influence.chaz <- temp + \} + \} + \} + else \{ + # everything is derived from the influence of the cumulative hazard + if (length(xlev) ==1) \{ + temp <- cfit$influence2 + row.names(temp) <- clname + \} else \{ + temp <- vector("list", ngroup) + for (i in 1:ngroup) \{ + temp[[i]] <- cfit[[i]]$influence2 + row.names(temp[[i]]) <- clname[clusterid[[i]]] + \} + \} + + if (influence==2 || influence ==3) + rval$influence.chaz <- temp + + if (influence==1 || influence==3) \{ + # if an obs moves the cumulative hazard up, then it moves S down + if (length(xlev) ==1) + rval$influence.surv <- -temp * rep(rval$surv, each=nrow(temp)) + else \{ + for (i in 1:ngroup) + temp[[i]] <- -temp[[i]] * rep(cfit[[i]]$estimate[,1], + each=nrow(temp[[i]])) + rval$influence.surv <- temp + \} + \} + \} + \} + + if (!missing(start.time)) rval$start.time <- start.time + rval +\end{nwchunk} + +Now for the real work using C routines. +My standard for a variable named ``zed'' is to use zed2 for the S object +and zed for the data part of the object; the latter is what the C code +works with. +\begin{nwchunk} +\nwhypf{survfitkm1}{survfitkm}{survfitkm2}= + #include + #include "survS.h" + #include "survproto.h" + + SEXP survfitkm(SEXP y2, SEXP weight2, SEXP sort12, SEXP sort22, + SEXP type2, SEXP id2, SEXP nid2, SEXP position2, + SEXP influence2) \{ + + int i, i1, i2, j, k, person1, person2; + int nused, nid, type, influence; + int ny, ntime; + double *tstart=0, *stime, *status, *wt; + double v1, v2, dtemp, haz; + double temp, dtemp2, dtemp3, frac, btemp; + int *sort1=0, *sort2, *id=0; + static const char *outnames[]=\{"time", "n", "estimate", "std.err", + "influence1", "influence2", ""\}; + SEXP rlist; + double *gwt=0, *inf1=0, *inf2=0; /* =0 to silence -Wall */ + int *gcount=0; + int n1, n2, n3, n4; + int *position=0, hasid; + double wt1, wt2, wt3, wt4; + + /* output variables */ + double *n[10], *dtime, + *kvec, *nvec, *std[2], *imat1=0, *imat2=0; /* =0 to silence -Wall*/ + double km, nelson; /* current estimates */ + + /* map the input data */ + ny = ncols(y2); /* 2= ordinary survival 3= start,stop data */ + nused = nrows(y2); + if (ny==3) \{ + tstart = REAL(y2); + stime = tstart + nused; + sort1 = INTEGER(sort12); + \} + else stime = REAL(y2); + status= stime +nused; + wt = REAL(weight2); + sort2 = INTEGER(sort22); + nused = LENGTH(sort22); + + type = asInteger(type2); + nid = asInteger(nid2); + if (LENGTH(position2) > 0) \{ + hasid =1; + position = INTEGER(position2); + \} else hasid=0; + influence = asInteger(influence2); + + /* nused was used for two things just above. The first was the length of + the input data y, only needed for a moment to set up tstart, stime, and + status. The second is the number of these observations we will actually + use, which is the length of sort2. This routine can be called multiple + times with sort1/sort2 pointing to different subsets of the data while + y, wt, id and position can remain unchanged + */ + + if (length(id2)==0) nid =0; /* no robust variance */ + else id = INTEGER(id2); + + /* pass 1, get the number of unique times, needed for memory allocation + Number of xval groups (unique id values) has been supplied + Data is sorted by time + */ + ntime =1; + temp = stime[sort2[0]]; + for (i=1; i0 ) \{ /* robust variance */ + gcount = (int *) R_alloc(nid, sizeof(int)); + if (type <3) \{ /* working vectors for the influence */ + gwt = (double *) R_alloc(3*nid, sizeof(double)); + inf1 = gwt + nid; + inf2 = inf1 + nid; + for (i=0; i< nid; i++) \{ + gwt[i] =0.0; + gcount[i] = 0; + inf1[i] =0; + inf2[i] =0; + \} + \} + else \{ + gwt = (double *) R_alloc(2*nid, sizeof(double)); + inf2 = gwt + nid; + for (i=0; i< nid; i++) \{ + gwt[i] =0.0; + gcount[i] = 0; + inf2[i] =0; + \} + \} + + /* these are not accumulated, so do not need to be zeroed */ + if (type <3) \{ + if (influence==1 || influence ==3) + imat1 = REAL(SET_VECTOR_ELT(rlist, 4, + allocMatrix(REALSXP, nid, ntime))); + if (influence==2 || influence==3) + imat2 = REAL(SET_VECTOR_ELT(rlist, 5, + allocMatrix(REALSXP, nid, ntime))); + \} + else if (influence !=0) + imat2 = REAL(SET_VECTOR_ELT(rlist, 5, + allocMatrix(REALSXP, nid, ntime))); + \} + + \nwhypf{survfitkm-pass21}{survfitkm-pass2}{survfitkm-pass22} + \nwhypf{survfitkm-pass31}{survfitkm-pass3}{survfitkm-pass32} + + UNPROTECT(1); + return(rlist); + \} +\end{nwchunk} + +Pass 2 goes from the last time to the first and fills in the \code{n} matrix. +\begin{nwchunk} +\nwhypb{survfitkm-pass22}{survfitkm-pass2}{survfitkm-pass21}= + R_CheckUserInterrupt(); /*check for control-C */ + /* + ** person1, person2 track through sort1 and sort2, respectively + ** likewise with i1 and i2 + */ + person1 = nused-1; person2 = nused-1; + n1=0; wt1=0; + for (k=ntime-1; k>=0; k--) \{ + dtime[k] = stime[sort2[person2]]; /* current time point */ + n2=0; n3=0; wt2=0; wt3=0; + for (; person2 >=0; person2--) \{ + i2= sort2[person2]; + if (stime[i2] != dtime[k]) break; + + n1++; /* number at risk */ + wt1 += wt[i2]; /* weighted number at risk */ + if (status[i2] ==1) \{ + n2++; /* events */ + wt2 += wt[i2]; + \} else if (hasid==0 || (position[i2]& 2)) \{ + /* if there are no repeated obs for a subject (hasid=0) + ** or this is the last of a string (a,b](b,c](c,d].. for + ** a subject (position[i2]=2 or 3), then it is a 'real' censor + */ + n3++; + wt3 += wt[i2]; + \} + \} + + if (ny==3) \{ /* remove any with start time >=dtime*/ + n4 =0; wt4 =0; + for (; person1 >=0; person1--) \{ + i1 = sort1[person1]; + if (tstart[i1] < dtime[k]) break; + n1--; + wt1 -= wt[i1]; + if (hasid==0 || (position[i1] & 1)) \{ + /* if there are no repeated id (hasid=0) or this is the + ** first of a string of (a,b](b,c](c,d] for a subject, then + ** this is a 'real' entry */ + n4++; + wt4 += wt[i1]; + \} + \} + if (n4>0) \{ + n[6][k+1] = n4; + n[7][k+1] = wt4; + \} + \} + + n[0][k] = n1; n[1][k]=n2; n[2][k]=n3; + n[3][k] = wt1; n[4][k]=wt2; n[5][k]=wt3; + \} + + if (ny ==3) \{ /* fill in number entered for the initial interval */ + n4=0; wt4=0; + for (; person1>=0; person1--) \{ + i1 = sort1[person1]; + if (hasid==0 || (position[i1] & 1)) \{ + n4++; + wt4 += wt[i1]; + \} + \} + n[6][0] = n4; + n[7][0] = wt4; + \} +\end{nwchunk} + +The rest of the code is identical for simple survival or start-stop data. +The cumulative hazard estimates are the Nelson-Aalen-Breslow (same estimate, +three different papers) or the Fleming-Harrington. +\begin{align*} + \Lambda_A(t) &\ \sum{u_j \le t} d_j/r_j \\ + \Lambda_{FH}(t) &= \sum{u_j \le t} \frac{d_j} + {f_j \sum_{k=0}^{f_j-1} (r_j - kd_j/f_j)} +\end{align*} +To understand the Fleming-Harrington estimate, suppose that at some time +point we had three deaths out of 10 at risk. The Aalen estimate gives a +hazard estimate of 3/10. +The FH estimate assumes that the deaths didn't actually all happen at once, +even though rounding in the data collection process makes it appear that +way, so the better estimate is 1/10 + 1/9 + 1/8. The third person to die, +whoever that was, would have had only 8 at risk when their event happened. + +The estimate of survival is either the Kaplan-Meier or the exponential +of the hazard. +\begin{equation*} + KM(t) = \prod_{u_j \le t} \frac{r_j - d_j}{r_j} +\end{equation*} + +The third pass goes from smallest time to largest. 99 times out of 100 the +user will choose type=1, so we try to avoid testing those +expression n times. +\begin{nwchunk} +\nwhypb{survfitkm-pass32}{survfitkm-pass3}{survfitkm-pass31}= + R_CheckUserInterrupt(); /*check for control-C */ + nelson =0.0; km=1.0; + v1=0; v2=0; + if (nid==0) \{ /* simple variance */ + if (type==1 || type==3) \{ /* Nelson-Aalen hazard */ + for (i=0; i0 && n[4][i]>0) \{ /* at least one event with wt>0*/ + nelson += n[4][i]/n[3][i]; + v2 += n[4][i]/(n[3][i]*n[3][i]); + \} + + nvec[i] = nelson; + std[0][i] = sqrt(v2); + std[1][i] = sqrt(v2); + \} + \} else \{ /* Fleming hazard */ + for (i=0; i0 && n[4][i]>0) \{ /* at least one event */ + km *= (n[3][i]-n[4][i])/n[3][i]; + v1 += n[4][i]/(n[3][i] * (n[3][i] - n[4][i])); /* Greenwood */ + \} + kvec[i] = km; + std[0][i] = sqrt(v1); + \} + \} else \{ /* exp survival */ + for (i=0; i< ntime; i++) \{ + kvec[i] = exp(-nvec[i]); + std[0][i] = std[1][i]; + \} + \} + \} + + else \{ /* infinitesimal jackknife variance */ + \nwhypf{survfitkm-influence1}{survfitkm-influence}{survfitkm-influence2} + \} +\end{nwchunk} + +The robust variance is based on an infinitesimal jackknife (IJ). +Let $S_{-i}(t)$ be the survival curve without subject $i$ and +$J_i(t) = S_i(t) - S_{-i}(t)$ be the change in the +survival curve from adding subject $i$ back in. +Then the jackknife estimate of variance is +$$ + \sigma^2_J(t) = \sum \left( J_i(t) - \overline J(t) \right)^2 +$$ +The IJ estimate instead uses the linear approximation to the +jackknife, since it is normally less work to compute the derivative than a +whole new estimate. +Notice that if all the weights were doubled the expression below will stay +the same since the derivative will drop by 1/2. +\begin{align*} + \sigma^2_{IJ}(t_k) & = \sum_i w_i U_{ik}^2 \\ + U_{ik} & = \frac{\partial S(t_k)}{\partial w_i} +\end{align*} + +The big problem with the IJ estimate is that a first derivative matrix $U$ +will have one row per subject and one column per event time. +Since the number of unique event times tends to grow with $n$, this +matrix very rapidly becomes too large to manage. +Instead use a grouped jackknife with $g$ groups, +$g$ will often be on the order of 20--50. +The 0/1 design matrix $B$ has $n$ rows and $g$ columns, one column per group, +marking which subject is in each group. +The grouped jackknife can be written as +\begin{align*} + U'WBB'W U &= V'V +\end{align*} +Our goal is to accumulate and use $V$ instead of $U$. +The working vectors \code{inf1} and \code{inf2} contain the current +estimate for the survival S and cumulative hazard H, at a given time. +They are saved into the \code{imat} array for users, if desired. + +First work this out for the cumulative hazard, which is simpler, and a single +subject $k$. +\begin{align} + H(t) &= \sum_{s\le t} \frac{\sum w_i dN_i(s)}{\sum w_i Y_i(s)} \nonumber\\ + &= \sum _{s\le t} h(s) \nonumber \\ + U_k(t) &= U_k(t-) + \frac{\partial h(t)}{\partial w_k} \nonumber \\ + &= U_k(t-) + \frac{1}{\sum w_i Y_i(t)} \left(dN_k(t) - Y_k(t)h(t) \right) + \label{Una} \\ + \sum_k w_k U_k(t) &= 0 \nonumber +\end{align} +using the counting process notation of $N(t)$ for events and $Y(t)$ for at risk. +The weighted sum of the first derivatives is zero, so we don't need a mean +when computing the variance estimate. (This is true for all IJ estimators.) +$V$ involves the weighted sum of this over groups, +for the increment to each row of $V$ the rightmost term of \eqref{Una} is +replaced by the weighted sum over each group. Since $h$ is the same for +every subject at risk, we only need accumulate the sum of +subjects in and sum of events in each group. The first can be kept as +a running sum with $O(n)$ effort. + +When using the FH2 estimate tied deaths are different. Say that subject $i$ +dies at some time $t$ where there are 2 other tied deaths. +Let $w_i$ for $i=1,2,3$ be the weight of those who die and $s$ the sum of +weights for all the others. +The contribution to the cumulative hazard and derivative at this time point is +\begin{align*} + h &= \frac{w_1+w_2+w_3}{3} \frac{1}{s+w_1+w_2+w_3} + + \frac{w_1+w_2+w_3}{3} \frac{1}{s+ 2(w_1+w_2+w_3)/3} + + \frac{w_1+w_2+w_3}{3} \frac{1}{s+ (w_1 + w_2 + w_3)/3} \\ + &\equiv a(b_1 + b_2 + b_3) + \frac{\partial h}{\partial w_i} &= + &= \left\{ \begin{array}{cl} + \frac{b_1 + b_2 + b_3}{3} - a b_1^2 - (2/3)a b_2^2 - (1/3)a b_3^2 & i\le 3 \\ + -a(b_1^2 + b_2^2 + b_3^2) & i> 3 \end{array} \right . +\end{align*} +The idea is that if the data had been gathered with more precision, then there +would not be ties. The first death has 1/3 chance of being subject 1,2, or 3 +and all are in the denominator. The second also has 1/3 chance of being 1--3, +and each of these has 2/3 chance of still being in the denominator, etc. +The standard variance will be $ab_1^2 + ab_2^2 + ab_3^2$. + +For the Kaplan-Meier we have +\begin{align} + KM(t) &= KM(t-) [1 - h(t)] \nonumber\\ + U_k(t) &= \frac{\partial KM(t)}{\partial w_k} \nonumber\\ + &= U_k(t-) [1- h(t)] - + KM(t-)\frac{\partial h(t)}{\partial w_k} \label{Ukm} +\end{align} +The $V$ matrix is again a weighted sum. The first term of \eqref{Ukm} does +not change, it multiplies the current value times $1-h$. +The second term involves the same summation as the cumulative hazard. + +When using $\exp(-H)$ as the survival estimate then +\begin{align*} + \frac{partial S(t)}{\partial w_k} &= \frac{\partial e^{-H(t)}}{\partial w_k}\\ + &= e^{-H(t)} \partial{H(t)}{\partial w_k} +\end{align*} +so in this case only the robust variance for the cumulative hazard $H$ is +needed, and the parent R routine can fill in the rest. + +The variance for a given survival time is $\sum V^2$, which is always returned. +The code keeps the current $V$ vector for the hazard $H$ in \code{inf2}, and if +necessary that for the KM in \code{inf1}. +A last step is to add up the squares of all of these, so the algorithm is +$O(gp)$ where $p$ is the number of unique event times and $g$ is the number +of groups. +The sum of weights for each group is kept in a vector \code{gwt}, which is +updated as subjects enter and leave. + +Say that a study had n= 10 million subjects in g=100 groups with +d = 1 million deaths. +At each death we update the 'hazard' part of the influence for all 100 +groups, which is O(gd). +The deaths at that time point have a second increment, to whichever +group each is in, but since time is sorted that adds O(n) for indexing and +O(d) for the work. The most important thing is to avoid doing anything +that would be O(ng) or O(nd). +For method=3 the hazard part of the increment is also +different for a death, the solution is to do an ordinary increment for everyone +in the O(gd) step, then correct it when doing the O(d) update. + +\begin{nwchunk} +\nwhypb{survfitkm-influence2}{survfitkm-influence}{survfitkm-influence1}= + v1=0; v2 =0; km=1; nelson =0; + person2=0; + if (ny==3) \{ + person1 =0; + \} else \{ + /* at the start, everyone is at risk */ + for (i=0; i< nused; i++) \{ + i2 = id[i]; + gcount[i2]++; + gwt[i2] += wt[i]; + \} + \} + + if (type==1) \{ + for (i=0; i< ntime; i++) \{ + if (ny==3) \{ + /* add in new subjects */ + for (; person1 < nused; person1++) \{ + /* add in those whose start time is < dtime */ + i1 = sort1[person1]; + if (tstart[i1] >= dtime[i]) break; + gcount[id[i1]]++; + gwt[id[i1]] += wt[i1]; + \} + \} + + if (n[1][i] > 0 && n[4][i]>0) \{ /* need to update the sums */ + haz = n[4][i]/n[3][i]; + for (k=0; k< nid; k++) \{ + inf1[k] = inf1[k] *(1.0 -haz) + gwt[k]*km*haz/n[3][i]; + inf2[k] -= gwt[k] * haz/n[3][i]; + \} + for (; person2 dtime[i]) break; /* those at this time */ + if (status[i2]==1) \{ + inf1[id[i2]] -= km* wt[i2]/n[3][i]; + inf2[id[i2]] += wt[i2]/n[3][i]; + \} + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + \} + km *= (1-haz); + nelson += haz; + + v1=0; v2=0; + for (k=0; k dtime[i]) break; + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + \} + \} + + kvec[i] = km; + nvec[i] = nelson; + std[0][i] = sqrt(v1); + std[1][i] = sqrt(v2); + if (influence==1 || influence ==3) + for (k=0; k= dtime[i]) break; + gcount[id[i1]]++; + gwt[id[i1]] += wt[i1]; + \} + \} + + if (n[1][i] > 0 && n[4][i] >0) \{ /* need to update the sums */ + dtemp =0; /* the working denominator */ + dtemp2=0; /* sum of squares */ + dtemp3=0; + temp = n[3][i] - n[4][i]; /* sum of weights for the non-deaths */ + for (k=n[1][i]; k>0; k--) \{ + frac = k/n[1][i]; + btemp = 1/(temp + frac*n[4][i]); /* "b" in the math */ + dtemp += btemp; + dtemp2 += btemp*btemp*frac; + dtemp3 += btemp*btemp; /* non-death deriv */ + \} + + dtemp /= n[1][i]; /* average denominator */ + if (n[4][i] != n[1][i]) \{ /* case weights */ + dtemp2 *= n[4][i]/ n[1][i]; + dtemp3 *= n[4][i]/ n[1][i]; + \} + nelson += n[4][i]*dtemp; + + haz = n[4][i]/n[3][i]; + for (k=0; k< nid; k++) \{ + inf1[k] = inf1[k] *(1.0 -haz) + gwt[k]*km*haz/n[3][i]; + if (gcount[k]>0) inf2[k] -= gwt[k] * dtemp3; + \} + for (; person2 dtime[i]) break; + if (status[i2]==1) \{ + inf1[id[i2]] -= km* wt[i2]/n[3][i]; + inf2[id[i2]] += wt[i2] *(dtemp + dtemp3 - dtemp2); + \} + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + \} + km *= (1-haz); + + v1=0; v2=0; + for (k=0; k dtime[i]) break; + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + \} + \} + + kvec[i] = km; + nvec[i] = nelson; + std[0][i] = sqrt(v1); + std[1][i] = sqrt(v2); + if (influence==1 || influence ==3) + for (k=0; k= dtime[i]) break; + + gcount[id[i1]]++; + gwt[id[i1]] += wt[i1]; + \} + \} + + if (n[1][i] > 0 && n[4][i]>0) \{ /* need to update the sums */ + haz = n[4][i]/n[3][i]; + for (k=0; k< nid; k++) \{ + inf2[k] -= gwt[k] * haz/n[3][i]; + \} + for (; person2 dtime[i]) break; + if (status[i2]==1) \{ + inf2[id[i2]] += wt[i2]/n[3][i]; + \} + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + \} + nelson += haz; + + v2=0; + for (k=0; k dtime[i]) break; + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + \} + \} + + kvec[i] = exp(-nelson); + nvec[i] = nelson; + std[1][i] = sqrt(v2); + std[0][i] = sqrt(v2); + + if (influence>0) + for (k=0; k= dtime[i]) break; + gcount[id[i1]]++; + gwt[id[i1]] += wt[i1]; + \} + \} + if (n[1][i] > 0 && n[4][i] >0) \{ /* need to update the sums */ + dtemp =0; /* the working denominator */ + dtemp2=0; /* sum of squares */ + dtemp3=0; + temp = n[3][i] - n[4][i]; /* sum of weights for the non-deaths */ + for (k=n[1][i]; k>0; k--) \{ + frac = k/n[1][i]; + btemp = 1/(temp + frac*n[4][i]); /* "b" in the math */ + dtemp += btemp; + dtemp2 += btemp*btemp*frac; + dtemp3 += btemp*btemp; /* non-death deriv */ + \} + + dtemp /= n[1][i]; /* average denominator */ + if (n[4][i] != n[1][i]) \{ /* case weights */ + dtemp2 *= n[4][i]/ n[1][i]; + dtemp3 *= n[4][i]/ n[1][i]; + \} + nelson += n[4][i]*dtemp; + + for (k=0; k< nid; k++) \{ + if (gcount[k]>0) inf2[k] -= gwt[k] * dtemp3; + \} + for (; person2 dtime[i]) break; + if (status[i2]==1) \{ + inf2[id[i2]] += wt[i2] *(dtemp + dtemp3 - dtemp2); + \} + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + \} + + v2=0; + for (k=0; k dtime[i]) break; + gcount[id[i2]] --; + if (gcount[id[i2]] ==0) gwt[id[i2]] = 0.0; + else gwt[id[i2]] -= wt[i2]; + \} + \} + + kvec[i] = exp(-nelson); + nvec[i] = nelson; + std[1][i] = sqrt(v2); + std[0][i] = sqrt(v2); + + if (influence>0) + for (k=0; k 0)) stop("one or more flags are >0 in survcheck") + states <- mcheck$states + istate <- mcheck$istate + nstate <- length(states) + smap <- c(0, match(attr(Y, "states"), states)) + Y[,ncol(Y)] <- smap[Y[,ncol(Y)] +1] # new states may be a superset + status <- Y[,ncol(Y)] + + if (mcheck$flag["overlap"] > 0) + stop("a subject has overlapping time intervals") + # if (mcheck$flag["gap"] > 0 || mcheck$flag["jump"] > 0) + # warning("subject(s) with time gaps, results may be questionable") + + # The states of the status variable are the first columns in the output + # any extra initial states are later in the list. + # Now that we know the names, verify that p0 is correct (if present) + if (!missing(p0) && !is.null(p0)) \{ + if (length(p0) != nstate) stop("wrong length for p0") + if (!is.numeric(p0) || abs(1-sum(p0)) > sqrt(.Machine$double.eps)) + stop("p0 must be a numeric vector that adds to 1") + \} else p0 <- NULL +\end{nwchunk} + +The status vector will have values of 0 for censored. +\begin{nwchunk} +\nwhypb{survfitCI2}{survfitCI}{survfitCI1}= + curves <- vector("list", ncurve) + names(curves) <- levels(X) + + if (ncol(Y)==2) \{ # 1 transition per subject + # dummy entry time that is < any event time + t0 <- min(0, Y[,1]) + entry <- rep(t0-1, nrow(Y)) + for (i in levels(X)) \{ + indx <- which(X==i) + curves[[i]] <- docurve2(entry[indx], Y[indx,1], status[indx], + istate[indx], weights[indx], + states, + id[indx], se.fit, influence, p0) + \} + \} + else \{ + \nwhypf{survfitCI-extracens1}{survfitCI-extracens}{survfitCI-extracens2} + \nwhypf{survfitCI-startstop1}{survfitCI-startstop}{survfitCI-startstop2} + \} + + \nwhypf{survfitCI-finish1}{survfitCI-finish}{survfitCI-finish2} + \} +\end{nwchunk} + +In the multi-state case we can calculate the current P(state) +vector $p(t)$ using the product-limit form, while the cumulative hazard +$c(t)$ is a sum. +\begin{align*} + p(t) &= p(0)\prod_{s<=t} [I + dA(s)] \\ + &= p(0) \prod_{s<=t} H(s) \\ + c(t) &= \sum_{s<=t} dA(s) +\end{align*} +Where $p$ is a row vector and $H$ is the multi-state hazard matrix. +$H(t)$ is a simple transition matrix. +Row $j$ of $H$ describes the outcome of everyone who was in state $j$ at +time $t-0$; and is the fraction of them who are in states $1, 2, \ldots$ +at time $t+0$. +Let $Y_{ij}(t)$ be the indicator function which is 1 if subject $i$ +is in state $j$ at time $t-0$, then +\begin{equation} + H_{jk}(t) = \frac{\sum_i w_i Y_{ij}(t) Y_{ik}(t+)} + {\sum_i w_i Y_{ij}(t)} \label{H} +\end{equation} +Each row of $H$ sums to 1: everyone has to go somewhere. +This formula collapses to the Kaplan-Meier in the simple case where $p(t)$ is a +vector of length 2 with state 1 = alive and state 2 = dead. + +The variance is based on per-subject influence. Since $p(t)$ is a vector +the influence can be written as a matrix with one row per subject and +one column per state. +$$ U_{ij}(t) \equiv \frac{\partial p_j(t)}{\partial w_i}. $$ +This can be calculate using a recursive formula. +First, the derivative of a matrix product $AB$ is $d(A)B + Ad(B)$ where +$d(A)$ is the elementwise derivative of $A$ and similarly for $B$. +(Write out each element of the matrix product.) +Since $p(t) = p(t-)H(t)$, the $i$th row of U satisfies +\begin{align} + U_i(t) &= \frac{\partial p(t)}{\partial w_i} \nonumber \\ + &= \frac{\partial p(t-)}{\partial w_i} H(t) + + p(t-) \frac{\partial H(t)}{\partial w_i} \nonumber \\ + &= U_i(t-) H(t) + p(t-) \frac{\partial H(t)}{\partial w_i} + \label{ci} +\end{align} +The first term of \ref{ci} collapses to ordinary matrix multiplication. +The second term does not: each at risk subject has a unique matrix derivative +$\partial H$; $n$ vectors of length $p$ can be arranged into a matrix, making +the code simple, but $n$ +$p$ by $p$ matrices are not so neat. +However, note that +\begin{enumerate} +\item $\partial H$ is zero for anyone not in the risk set, since their + weight does not appear in $H$. +\item Each subject who is at risk will be in one (and only one) of the + states at the event time, their weight only appears in that row of $H$. + Thus for each at risk subject $\partial H$ has only one non-zero row. +\end{enumerate} +Say that the subject enters the given event time in state $j$ and ends it +in state $k$. +(For most subjects at most time poinnts $k=j$: if there are 100 at risk at +time $t$ and 1 changes state, the other 99 stay put.) +Let $n_j(t)= \sum_i Y_{ij}(t)w_i$ be the weighted number of subjects +in state $j$, these are the contributers to row $j$ of $H$. +Using equation \ref{H}, the derivative of row $j$ +with respect to the subject is $(1_k - H_j)/n_j$ +where $1_k$ is a vector with 1 in position $k$. +The product of $p(t)$ with this matrix is the vector +$p_j(t)(1_k - H_j)/n_j$. +The second term thus turns out to be fairly simple to compute, but I have +not seen a way to write it in a compact matrix form + +The weighted sum of each column of $U$ will be zero (if computed correctly) +and the weighted sum of squares for each column will be the infinitesimal +jackknife estimate of variance for the elements of $p$. +The entire variance-covariance matrix for the states is $U'W^2U$ where +$W$ is a diagonal +matrix of weights, but we currently don't report that back. +Note that this is for sampling weights. +If one has real case weights, where an integer weight of 2 means 2 observations +that were collapsed in to one row of data to save space, then the +variance is $U'WU$. +Case weights were somewhat common in my youth due to small computer memory, +but I haven't seen such data in 20 years. + +The residuals for the cumulative hazard are an easier computation, since each +hazard function stands alone. In a multistate model with $k$ states there +are potentially $k(k-1)$ hazard functions arranged in a $k$ by $k$ matrix, +i.e., as used for the NA update; in the code both the hazard, the IJ scores +and the standard errors are kept as matrices with a column for each combination +that does occur. At each event time only the rows of U2 that correspond to +the risk set will be updated. + +Below is the function for a single curve. +For the status variable a value if 0 is ``no event''. +One nuisance in the function is that we need to ensure the +tapply command gives totals for all states, not just the ones present in the +data --- a call using the \code{subset} argument might not have all the states +--- which leads to using factor commands. +Another more confusing one is for multiple rows per subject data, where the +cstate and U objects have only one row per subject; +any given subject is only in one state at a time. +This leads to indices of \Verb!atrisk! for the set of rows in the risk set but +\Verb!aindx! for the subjects in the risk set, \Verb?death? for the rows that have +an event this time and \Verb!dindx! for the corresponding subjects. + +The setup for (start, stop] data is a bit more work. +We want to ensure that a given subject remains in the same group and that +they have a continuous period of observation. + +If the input data was the result of a tmerge call, say, it might have a +lot of extra 'censored' rows. For instance a subject whose state pattern +is (0, 5, 1), (5,10, 2), i.e., a transition to state 1 at day 5 and state 2 +on day 10 might input as (0,2,0), (2,5,1), (5,6,0), (6,8,0), (8,10,2) +instead. +These extra censors cause an +unnecessary row of output on days 2, 6, and 8. +Remove these before going further. + +\begin{nwchunk} +\nwhypb{survfitCI-extracens2}{survfitCI-extracens}{survfitCI-extracens1}= + # extra censors + indx <- order(id, Y[,2]) # in stop order + extra <- (survflag(Y[indx,], id[indx]) ==0 & (Y[indx,3] ==0)) + # If a subject had obs of (a, b)(b,c)(c,d), and c was a censoring + # time, that is an "extra" censoring/entry at c that we don't want + # to count. Deal with it by changing that subject + # to (a,b)(b,d). Won't change S(t), only the n.censored/n.enter count. + if (any(extra)) \{ + e2 <- indx[extra] + Y <- cbind(Y[-(1+e2),1], Y[-e2,-1]) + status <- status[-e2] + X <- X[-e2] + id <- id[-e2] + istate <- istate[-e2] + weights <- weights[-e2] + indx <- order(id, Y[,2]) + \} +\end{nwchunk} + +\begin{nwchunk} +\nwhypb{survfitCI-startstop2}{survfitCI-startstop}{survfitCI-startstop1}= + # Now to work + for (i in levels(X)) \{ + indx <- which(X==i) + # temp <- docurve1(Y[indx,1], Y[indx,2], status[indx], + # istate[indx], weights[indx], states, id[indx]) + curves[[i]] <- docurve2(Y[indx,1], Y[indx,2], status[indx], + istate[indx], + weights[indx], states, id[indx], se.fit, + influence, p0) + \} +\end{nwchunk} + +\begin{nwchunk} +\nwhyp{survfitCI-finish2}{survfitCI-finish}{survfitCI-finish1}{survfitCI-finish3}= + # Turn the result into a survfit type object + grabit <- function(clist, element) \{ + temp <-(clist[[1]][[element]]) + if (is.matrix(temp)) \{ + do.call("rbind", lapply(clist, function(x) x[[element]])) + \} + else \{ + xx <- as.vector(unlist(lapply(clist, function(x) x[element]))) + if (inherits(temp, "table")) matrix(xx, byrow=T, ncol=length(temp)) + else xx + \} + \} + + # we want to rearrange the cumulative hazard to be in time order + # with one column for each observed transtion. + nstate <- length(states) + temp <- matrix(0, nstate, nstate) + indx1 <- match(rownames(mcheck$transitions), states) + indx2 <- match(colnames(mcheck$transitions), states, nomatch=0) #ignore censor + temp[indx1, indx2[indx2>0]] <- mcheck$transitions[,indx2>0] + ckeep <- which(temp>0) + names(ckeep) <- outer(1:nstate, 1:nstate, paste, sep='.')[ckeep] + #browser() + + if (length(curves) ==1) \{ + keep <- c("n", "time", "n.risk", "n.event", "n.censor", "pstate", + "p0", "cumhaz", "influence.pstate") + if (se.fit) keep <- c(keep, "std.err", "sp0") + kfit <- (curves[[1]])[match(keep, names(curves[[1]]), nomatch=0)] + names(kfit$p0) <- states + if (se.fit) kfit$logse <- FALSE + kfit$cumhaz <- t(kfit$cumhaz[ckeep,,drop=FALSE]) + colnames(kfit$cumhaz) <- names(ckeep) + \} + else \{ + kfit <- list(n = as.vector(table(X)), #give it labels + time = grabit(curves, "time"), + n.risk= grabit(curves, "n.risk"), + n.event= grabit(curves, "n.event"), + n.censor=grabit(curves, "n.censor"), + pstate = grabit(curves, "pstate"), + p0 = grabit(curves, "p0"), + strata= unlist(lapply(curves, function(x) + if (is.null(x$time)) 0L else length(x$time)))) + kfit$p0 <- matrix(kfit$p0, ncol=nstate, byrow=TRUE, + dimnames=list(names(curves), states)) + if (se.fit) \{ + kfit$std.err <- grabit(curves, "std.err") + kfit$sp0<- matrix(grabit(curves, "sp0"), + ncol=nstate, byrow=TRUE) + kfit$logse <- FALSE + \} + + # rearrange the cumulative hazard to be in time order, with columns + # for each transition + kfit$cumhaz <- do.call(rbind, lapply(curves, function(x) + t(x$cumhaz[ckeep,,drop=FALSE]))) + colnames(kfit$cumhaz) <- names(ckeep) + + if (influence) kfit$influence.pstate <- + lapply(curves, function(x) x$influence.pstate) + \} + + if (!missing(start.time)) kfit$start.time <- start.time + kfit$transitions <- mcheck$transitions + +\end{nwchunk} + +\begin{nwchunk} +\nwhypb{survfitCI-finish3}{survfitCI-finish}{survfitCI-finish2}= + # + # Last bit: add in the confidence bands: + # + if (se.fit && conf.type != "none") \{ + ci <- survfit_confint(kfit$pstate, kfit$std.err, logse=FALSE, + conf.type, conf.int) + kfit <- c(kfit, ci, conf.type=conf.type, conf.int=conf.int) + \} + kfit$states <- states + kfit$type <- attr(Y, "type") + kfit +\end{nwchunk} + +The updated docurve function is here. +One issue that was not recognized originally is delayed entry. If most +of the subjects start at time 0, say, but one of them starts at day 100 +then that last subject is not a part of $p_0$. +We will define $p_0$ as the distribution of states just before the first +event. +The code above has already ensured that each subject has a unique +value for istate, so we don't have to search for the right one. +The initial vector and leverage are +\begin{align*} + p_0 &= (\sum I{s_i=1}w_i, \sum I{s_i=2}w_i, \ldots)/ \sum w_i \\ + \frac{\partial p_0}{\partial w_k} &= + [(I{s_k=1}, I{s_k=2}, ...)- p_0]/\sum w_i +\end{align*} + +The input data set is not necessarily sorted by time or subject. +The data has been checked so that subjects don't have gaps, however. +The cstate variable for each subject contains their first istate +value. Only those intervals that overlap the first event time contribute +to $p_0$. +Now: what to report as the ``time'' for the initial row. The values for +it come from (first event time -0), i.e. all who are at risk at the +smallest \code{etime} with status $>0$. +But for normal plotting the smallest start time seems to be a good +default. +In the usual (start, stop] data +a large chunk of the subjects have a common start time. +However, if the first event doesn't happen for a while +and subjects are dribbling in, then the best point to start a plot +is open to debate. Que sera sera. +\begin{nwchunk} +\nwhypb{survfitCI-compute2}{survfitCI-compute}{survfitCI-compute1}= + docurve2 <- function(entry, etime, status, istate, wt, states, id, + se.fit, influence=FALSE, p0) \{ + timeset <- sort(unique(etime)) + nstate <- length(states) + uid <- sort(unique(id)) + index <- match(id, uid) + # Either/both of id and cstate might be factors. Data may not be in + # order. Get the initial state for each subject + temp1 <- order(id, entry) + temp2 <- match(uid, id[temp1]) + cstate <- (as.numeric(istate)[temp1])[temp2] # initial state for each + + # The influence matrix can be huge, make sure we have enough memory + if (influence) \{ + needed <- max(nstate * length(uid), 1 + length(timeset)) + if (needed > .Machine$integer.max) + stop("number of rows for the influence matrix is > the maximum integer") + \} + storage.mode(wt) <- "double" # just in case someone had integer weights + + # Compute p0 (unless given by the user) + if (is.null(p0)) \{ + if (all(status==0)) t0 <- max(etime) #failsafe + else t0 <- min(etime[status!=0]) # first transition event + at.zero <- (entry < t0 & etime >= t0) + wtsum <- sum(wt[at.zero]) # weights for a subject may change + p0 <- tapply(wt[at.zero], istate[at.zero], sum) / wtsum + p0 <- ifelse(is.na(p0), 0, p0) #for a state not in at.zero, tapply =NA + \} + # initial leverage matrix + nid <- length(uid) + i0 <- matrix(0., nid, nstate) + if (all(p0 <1)) \{ #actually have to compute it + who <- index[at.zero] # this will have no duplicates + for (j in 1:nstate) + i0[who,j] <- (ifelse(istate[at.zero]==states[j], 1, 0) - p0[j])/wtsum + \} + + storage.mode(cstate) <- "integer" + storage.mode(status) <- "integer" + # C code has 0 based subscripts + if (influence) se.fit <- TRUE # se.fit is free in this case + + fit <- .Call(Csurvfitci, c(entry, etime), + order(entry) - 1L, + order(etime) - 1L, + length(timeset), + status, + as.integer(cstate) - 1L, + wt, + index -1L, + p0, i0, + as.integer(se.fit) + 2L*as.integer(influence)) + + if (se.fit) + out <- list(n=length(etime), time= timeset, p0 = p0, + sp0= sqrt(colSums(i0^2)), + pstate = fit$p, std.err=fit$std, + n.risk = fit$nrisk, + n.event= fit$nevent, + n.censor=fit$ncensor, + cumhaz = fit$cumhaz) + else out <- list(n=length(etime), time= timeset, p0=p0, + pstate = fit$p, + n.risk = fit$nrisk, + n.event = fit$nevent, + n.censor= fit$ncensor, + cumhaz= fit$cumhaz) + if (influence) \{ + temp <- array(fit$influence, + dim=c(length(uid), nstate, 1+ length(timeset)), + dimnames=list(uid, NULL, NULL)) + out$influence.pstate <- aperm(temp, c(1,3,2)) + \} + out + \} +\end{nwchunk} +\subsubsection{C-code} +(This is set up as a separate file in the source code directory since +it is easier to make emacs stay in C-mode if the file has a .nw +extension.) + +\begin{nwchunk} +\nwhypn{survfitci}= + #include "survS.h" + #include "survproto.h" + #include + + SEXP survfitci(SEXP ftime2, SEXP sort12, SEXP sort22, SEXP ntime2, + SEXP status2, SEXP cstate2, SEXP wt2, SEXP id2, + SEXP p2, SEXP i02, SEXP sefit2) \{ + \nwhypf{survfitci-declare1}{survfitci-declare}{survfitci-declare2} + \nwhypf{survfitci-compute1}{survfitci-compute}{survfitci-compute2} + \nwhypf{survfitci-return1}{survfitci-return}{survfitci-return2} + \} +\end{nwchunk} +Arguments to the routine are the following. +For an R object ``zed'' I use the convention of \Verb!zed2! to refer to the +object and \Verb!zed! to the contents of the object. +\begin{description} + \item[ftime] A two column matrix containing the entry and exit times + for each subject. + \item[sort1] Order vector for the entry times. The first element of sort1 + points to the first entry time, etc. + \item[sort2] Order vector for the event times. + \item[ntime] Number of unique event time values. This fixes the size of + the output arrays. + \item[status] Status for each observation. 0= censored + \item[cstate] The initial state for each subject, which will be + updated during computation to always be the current state. + \item[wt] Case weight for each observation. + \item[id] The subject id for each observation. + \item[p] The initial distribution of states. This will be updated during + computation to be the current distribution. + \item[i0] The initial influence matrix, number of subjects by number of states + \item[sefit] If 1 then do the se compuatation, if 2 also return the full + influence matrix upon which it is based, if 0 the se is not needed. +\end{description} + +Note that code is called with id and not cluster: there is a basic premise that +each id is a single subject and thus has a unique "current state" at any +given time point. The history of this is that before the survcheck routine, +we did not have a good way for a user to normalize the 'current state' variable +for a subject, so this routine takes care of that tracking process. +When multi-state Cox models were added we became more formal about this, and +users can now have data sets with quite odd patterns of transitions and current +state, ones that survcheck calls a teleport. At some point this routine should +be updated as well. Cumulative hazard estimates make at least some sense +when a subject has a hole, though P(state |t) curves do not. + +Declare all of the variables. +\begin{nwchunk} +\nwhyp{survfitci-declare2}{survfitci-declare}{survfitci-declare1}{survfitci-declare3}= + int i, j, k, kk; /* generic loop indices */ + int ck, itime, eptr; /*specific indices */ + double ctime; /*current time of interest, in the main loop */ + int oldstate, newstate; /*when changing state */ + + double temp, *temp2; /* scratch double, and vector of length nstate */ + double *dptr; /* reused in multiple contexts */ + double *p; /* current prevalence vector */ + double **hmat; /* hazard matrix at this time point */ + double **umat=0; /* per subject leverage at this time point */ + int *atrisk; /* 1 if the subject is currently at risk */ + int *ns; /* number curently in each state */ + int *nev; /* number of events at this time, by state */ + double *ws; /* weighted count of number state */ + double *wtp; /* case weights indexed by subject */ + double wevent; /* weighted number of events at current time */ + int nstate; /* number of states */ + int n, nperson; /*number of obs, subjects*/ + double **chaz; /* cumulative hazard matrix */ + + /* pointers to the R variables */ + int *sort1, *sort2; /*sort index for entry time, event time */ + double *entry,* etime; /*entry time, event time */ + int ntime; /* number of unique event time values */ + int *status; /*0=censored, 1,2,... new states */ + int *cstate; /* current state for each subject */ + int *dstate; /* the next state, =cstate if not an event time */ + double *wt; /* weight for each observation */ + double *i0; /* initial influence */ + int *id; /* for each obs, which subject is it */ + int sefit; + + /* returned objects */ + SEXP rlist; /* the returned list and variable names of same */ + const char *rnames[]= \{"nrisk","nevent","ncensor", "p", + "cumhaz", "std", "influence.pstate", ""\}; + SEXP setemp; + double **pmat, **vmat=0, *cumhaz, *usave=0; /* =0 to silence -Wall warning */ + int *ncensor, **nrisk, **nevent; +\end{nwchunk} + +Now set up pointers for all of the R objects sent to us. +The two that will be updated need to be replaced by duplicates. +\begin{nwchunk} +\nwhyp{survfitci-declare3}{survfitci-declare}{survfitci-declare2}{survfitci-declare4}= + ntime= asInteger(ntime2); + nperson = LENGTH(cstate2); /* number of unique subjects */ + n = LENGTH(sort12); /* number of observations in the data */ + PROTECT(cstate2 = duplicate(cstate2)); + cstate = INTEGER(cstate2); + entry= REAL(ftime2); + etime= entry + n; + sort1= INTEGER(sort12); + sort2= INTEGER(sort22); + status= INTEGER(status2); + wt = REAL(wt2); + id = INTEGER(id2); + PROTECT(p2 = duplicate(p2)); /*copy of initial prevalence */ + p = REAL(p2); + nstate = LENGTH(p2); /* number of states */ + i0 = REAL(i02); + sefit = asInteger(sefit2); + + /* allocate space for the output objects + ** Ones that are put into a list do not need to be protected + */ + PROTECT(rlist=mkNamed(VECSXP, rnames)); + setemp = SET_VECTOR_ELT(rlist, 0, allocMatrix(INTSXP, ntime, nstate)); + nrisk = imatrix(INTEGER(setemp), ntime, nstate); /* time by state */ + setemp = SET_VECTOR_ELT(rlist, 1, allocMatrix(INTSXP, ntime, nstate)); + nevent = imatrix(INTEGER(setemp), ntime, nstate); /* time by state */ + setemp = SET_VECTOR_ELT(rlist, 2, allocVector(INTSXP, ntime)); + ncensor = INTEGER(setemp); /* total at each time */ + setemp = SET_VECTOR_ELT(rlist, 3, allocMatrix(REALSXP, ntime, nstate)); + pmat = dmatrix(REAL(setemp), ntime, nstate); + setemp = SET_VECTOR_ELT(rlist, 4, allocMatrix(REALSXP, nstate*nstate, ntime)); + cumhaz = REAL(setemp); + + if (sefit >0) \{ + setemp = SET_VECTOR_ELT(rlist, 5, allocMatrix(REALSXP, ntime, nstate)); + vmat= dmatrix(REAL(setemp), ntime, nstate); + \} + if (sefit >1) \{ + /* the max space is larger for a matrix than a vector + ** This is pure sneakiness: if I allocate a vector then n*nstate*(ntime+1) + ** may overflow, as it is an integer argument. Using the rows and cols of + ** a matrix neither overflows. But once allocated, I can treat setemp + ** like a vector since usave is a pointer to double, which is bigger than + ** integer and won't overflow. */ + setemp = SET_VECTOR_ELT(rlist, 6, allocMatrix(REALSXP, n*nstate, ntime+1)); + usave = REAL(setemp); + \} + + /* allocate space for scratch vectors */ + ws = (double *) R_alloc(2*nstate, sizeof(double)); /*weighted number in state */ + temp2 = ws + nstate; + ns = (int *) R_alloc(2*nstate, sizeof(int)); + nev = ns + nstate; + atrisk = (int *) R_alloc(2*nperson, sizeof(int)); + dstate = atrisk + nperson; + wtp = (double *) R_alloc(nperson, sizeof(double)); + hmat = (double**) dmatrix((double *)R_alloc(nstate*nstate, sizeof(double)), + nstate, nstate); + chaz = (double**) dmatrix((double *)R_alloc(nstate*nstate, sizeof(double)), + nstate, nstate); + if (sefit >0) + umat = (double**) dmatrix((double *)R_alloc(nperson*nstate, sizeof(double)), + nstate, nperson); + + /* R_alloc does not zero allocated memory */ + for (i=0; i1) \{ + /* copy influence, and save it */ + dptr = i0; + for (j=0; j0) cstate[id[j]] = status[j]-1; /*new state */ + atrisk[id[j]] =0; + \} + else break; + \} + itime++; + \} +\end{nwchunk} + +The key variables for the computation are the matrix $H$ and the +current prevalence vector $P$. +$H$ is created anew at each unique time point. +Row $j$ of $H$ concerns everyone in state $j$ just before the time point, +and contains the transitions at that time point. +So the $jk$ element is the (weighted) fraction who change from state $j$ +to state $k$, and the $jj$ element the fraction who stay put. +Each row of $H$ by definition sums to 1. +If no one is in the state then the $jj$ element is set to 1. +A second version which we call H2 has 1 subtracted from each diagonal giving +row sums are 0, we go back and +forth depending on which is needed at the moment. +If there are no events at this time point $P$ and $U$ do not update. +\begin{nwchunk} +\nwhypb{survfitci-compute-matrices2}{survfitci-compute-matrices}{survfitci-compute-matrices1}= + for (j=0; j0) \{ + newstate = status[k] -1; /* 0 based subscripts */ + oldstate = cstate[id[k]]; + if (oldstate != newstate) \{ + /* A "move" to the same state does not count */ + dstate[id[k]] = newstate; + nev[newstate]++; + wevent += wt[k]; + hmat[oldstate][newstate] += wt[k]; + \} + \} + else ncensor[itime]++; + \} + else break; + \} + + if (wevent > 0) \{ /* there was at least one move with weight > 0 */ + /* finish computing H */ + for (j=0; j0) \{ + temp =0; + for (k=0; k0) \{ + \nwhypf{survfitci-compute-U1}{survfitci-compute-U}{survfitci-compute-U2} + \} + \nwhypf{survfitci-compute-P1}{survfitci-compute-P}{survfitci-compute-P2} + \} +\end{nwchunk} + +The most complicated part of the code is the update of the +per subject influence matrix $U$. +The influence for a subject is the derivative of the current +estimates wrt the case weight of that subject. Since $p$ is a +vector the influence $U$ is easily represented as a matrix with one row +per subject and one column per state. +Refer to equation \eqref{ci} for the derivation. + +Let $m$ and $n$ be the old and new states for subject $i$, and +$n_m$ the sum of weights for all subjects at risk in state $m$. +Then +\begin{equation*} + U_{ij}(t) = \sum_k \left[ U_{ik}(t-)H_{kj}\right] + p_m(t-)(I_{n=j} - H_{mj})/ n_m +\end{equation*} +\begin{enumerate} + \item The first term above is simple matrix multiplication. + \item The second adds a vector with mean zero. +\end{enumerate} +If standard errors are not needed we can skip this calculation. + +\begin{nwchunk} +\nwhypb{survfitci-compute-U2}{survfitci-compute-U}{survfitci-compute-U1}= + /* Update U, part 1 U = U %*% H -- matrix multiplication */ + for (j=0; j0) \{ + temp =0; + for (k=0; k 1) + for (k=0; k0 && !missing(..1)) i <- ..1 else i <- NULL + if (ndots> 1 && !missing(..2)) j <- ..2 else j <- NULL + if (ndots> 2 && !missing(..3)) k <- ..3 else k <- NULL + if (is.null(i) & is.null(j) & is.null(k)) return(x) # only one curve + + # Make a new object + newx <- vector("list", length(x)) + names(newx) <- names(x) + for (kk in c("logse", "version", "conf.int", "conf.type", "type", + "start.time", "call")) + if (!is.null(x[[kk]])) newx[[kk]] <- x[[kk]] + newx$transitions <- NULL # may no longer be accurate, and not needed + class(newx) <- class(x) + + # Like a matrix, let the user use a single subscript if they desire + if (ndots==1 && length(dd) > 1) \{ + # the 'treat it as a vector' case + if (!is.numeric(i)) + stop("single subscript must be numeric") + if (any(dmatch==2)) stop("single index subscripts are not supported for a survfit objet with both data and state dimesions") + + # when subscripting a mix, these don't endure + newx$cumhaz <- newx$std.chaz <- newx$influence.chaz <- NULL + newx$transitions <- newx$states <- newx$newdata <- NULL + + # what strata and columns do I need? + itemp <- matrix(1:prod(dd), nrow=dd[1]) + jj <- (col(itemp))[i] # columns + ii <- (row(itemp))[i] # this is now the strata id + + if (dtype[1]!=1 || dd[1]==1) # no strata or only 1 + irow <- rep(seq(along.with= x$time), length(ii)) + else \{ + itemp2 <- split(1:sum(x$strata), rep(1:length(x$strata), x$strata)) + irow <- unlist(itemp2[ii]) # rows of the pstate object + \} + inum <- x$strata[ii] # number of rows in each ii + indx <- cbind(irow, rep(jj,ii)) # matrix index for pstate + + # The n.risk, n.event, .. matrices dont have a newdata dimension. + if (all(dtype!=2) || dd["data"]==1) kk <- jj + else \{ # both data and states + itemp <- matrix(1:(dd["data"]*dd["states"]), nrow=dd[2]) + kk <- (col(itemp))[jj] # the state of each selected one + indx2 <- cbind(irow, rep(k, irow)) + \} + newx$n <- x$n[ii] + newx$time <- x$time[irow] + for (z in c("n.risk", "n.event", "n.censor", "n.enter")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[indx2] + for (z in c("pstate", "std.err", "upper", "lower")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[indx] + + newx$strata <- x$strata[ii] + names(newx$strata) <- seq(along.with=ii) + + return(newx) + \} + + # not a single subscript, i.e., the usual case + # Backwards compatability: If x$strata=NULL, it is a semantic argument + # of whether there is still "1 stratum". I have used the second + # form at times, e.g. x[1,,2] for an object with only data and state + # dimensions. + # If there are no strata, 1 too many subscripts, and the first is 1, + # assume this case and toss the first + if (ndots == (length(dd)+1)) \{ + if (is.null(x$strata) && (is.null(i) || (length(i)==1 && i==1))) \{ + i <-j; j <-k; k <- NULL + \} else stop("incorrect number of dimensions") + \} else if (ndots != length(dd)) stop("incorrect number of dimensions") + + # create irow, which selects for the time dimension of x + if (dtype[1]!=1 || is.null(i)) \{ + irow <- seq(along.with= x$time) + \} + else \{ + i <- nmatch(i, names(x$strata)) + itemp <- split(1:sum(x$strata), rep(1:length(x$strata), x$strata)) + irow <- unlist(itemp[i]) # rows of the pstate object + \} + + # Select the n, strata, and time components of the output. Make j,k + # point to the subscripts other than strata (makes later code a touch + # simpler.) + newx$time <- x$time[irow] + if (dtype[1] !=1) \{ # there are no strata + newx$n <- x$n + k <- j; j <- i; + dd <- c(0, dd) + dtype <- c(1, dtype) + \} + else \{ # there are strata + if (is.null(i)) i <-seq(along.with=x$strata) + if ((drop && length(i)>1) || !drop) newx$strata <- x$strata[i] + newx$n <- x$n[i] + \} + + # The n.censor and n.enter values do not repeat with multiple X values + for (z in c("n.censor", "n.enter")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[irow, drop=FALSE] + + # two cases: with newx or without newx (pstate is always present) + nstate <- length(x$states) + if (dtype[2] !=2) \{ # j indexes the states, there is no data dimension + if (is.null(j)) j <- seq.int(nstate) + else j <- nmatch(j, x$states) + + # keep these as start points for plotting, even though they won't make + # true sense if states are subset, since rows won't sum to 1 + if (!is.null(x$p0)) \{ + if (is.matrix(x$p0)) newx$p0 <- x$p0[i,j, drop=FALSE] + else newx$p0 <- x$p0[j] + \} + if (!is.null(x$sp0)) \{ + if (is.matrix(x$sp0)) newx$sp0 <- x$sp0[i,j, drop=FALSE] + else newx$sp0 <- x$sp0[j] + \} + + # in the rare case of a single strata with 1 obs, don't drop dims + if (length(irow)==1 && length(j) > 1) drop2 <- FALSE + else drop2 <- drop + + for (z in c("n.risk", "n.event")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[irow,j, drop=drop2] + for (z in c("pstate", "std.err", "upper", "lower")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[irow,j, drop=drop2] + if (!is.null(x$influence.pstate)) \{ + if (is.list(x$influence.pstate)) \{ + if (length(i)==1) newx$influence.pstate <- x$influence.pstate[[i]] + else newx$influence.pstate <- lapply(x$influence.pstate[i], + function(x) x[,,j, drop= drop]) + \} + else newx$influence.pstate <- x$influence.pstate[,,j, drop=drop] + \} + + if (length(j)== nstate && all(j == seq.int(nstate))) \{ + # user kept all the states, in original order + newx$states <- x$states + for (z in c("cumhaz", "std.chaz")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[irow,, drop=drop2] + if (!is.null(x$influence.chaz)) \{ + if (is.list(x$influence.chaz)) \{ + newx$influence.chaz <- x$influence.chaz[i] + if (length(i)==1 && drop) + newx$influence.chaz <- x$influence.chaz[[i]] + \} + else newx$influence.chaz <- x$influence.chaz + \} + \} + else \{ + # Some states were dropped, leaving no consistent way to + # subscript cumhaz, or not one I have yet seen clearly + # So remove it from the object + newx$cumhaz <- newx$std.chaz <- newx$influence.chaz <- NULL + if (length(j)==1 & drop) \{ + newx$states <- NULL + temp <- class(newx) + class(newx) <- temp[temp!="survfitms"] + \} + else newx$states <- x$states[j] + \} + \} + else \{ # j points at newdata, k points at states + if (is.null(j)) j <- seq.int(dd[2]) + else j <- nmatch(j, seq.int(dd[2])) + + if (is.null(k)) k <- seq.int(nstate) + else k <- nmatch(k, x$states) + + # keep these as start points for plotting, even though they won't make + # true sense is states are subset, since rows won't sum to 1 + # (all data= sets have the same p0) + if (!is.null(x$p0)) \{ + if (is.matrix(x$p0)) newx$p0 <- x$p0[i,k] else newx$p0 <- x$p0[k] + \} + if (!is.null(x$sp0)) \{ + if (is.matrix(x$sp0)) newx$sp0 <- x$p0[i,k] else newx$sp0 <- x$sp0[k] + \} + + if (length(irow)==1) \{ + if (length(j) > 1) drop2 <- FALSE else drop2<- drop + if (length(k) > 1) drop3 <- FALSE else drop3 <- drop + \} + else drop2 <- drop3 <- drop + + for (z in c("n.risk", "n.event")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[irow, k, drop=drop3] + for (z in c("pstate", "std.err", "upper", "lower")) + if (!is.null(x[[z]])) newx[[z]] <- (x[[z]])[irow,j,k, drop=drop2] + + if (!is.null(x$influence.pstate)) \{ + if (is.list(x$influence.pstate)) \{ + if (length(i)==1) + newx$influence.pstate <- (x$influence.pstate[[i]])[,,j,k, drop=drop] + else newx$influence.pstate <- lapply(x$influence.pstate[i], + function(x) x[,,j,k, drop= drop]) + \} + else newx$influence.pstate <- x$influence.pstate[,,j,k, drop=drop] + \} + + if (length(k)== nstate && all(k == seq.int(nstate))) \{ + # user kept all the states + newx$states <- x$states + for (z in c("cumhaz", "std.chaz")) + if (!is.null(x[[z]])) + newx[[z]] <- (x[[z]])[irow,j,, drop=drop2] + if (!is.null(x$influence.chaz)) \{ + if (is.list(x$influence.chaz)) \{ + newx$influence.chaz <- (x$influence.chaz[i])[,j,] + if (length(i)==1 && drop) + newx$influence.chaz <- x$influence.chaz[[i]] + \} + else newx$influence.chaz <- x$influence.chaz[,j,] + \} + \} + else \{ + # never drop the states component. Otherwise downstream code + # will start looking for x$surv instead of x$pstate + newx$states <- x$states[k] + newx$cumhaz <- newx$std.chaz <- newx$influence.chaz <- NULL + x$transitions <- NULL + \} + + if (length(j)==1 && drop) newx$newdata <- NULL + else newx$newdata <- x$newdata[j,,drop=FALSE] #newdata is a data frame + + \} + newx + \} +\end{nwchunk} + +The summary.survfit and summary.survfitms functions share a significant +amount of code. +One part of the code that once was subtle is dealing with +intermediate time points; the findInterval function in base R has +made that much easier. +Since the result does not involve interpolation, one should be able +to create a special index vector i and return \code{time[i]}, +\code{surv[i,]}, etc, to subscript all the curves in a survfit object +at once. But that approach, though efficient in theory, runs into +two problems. First is the extrapolated value for the curves at +time points before the first event, which is allowed to be different +for different curves in survfitms objects. +The second is that there is interpolation of a sort: the n.event and n.censor +components are summed over intervals when the selected time points are +sparse, and that process is very tricky for multiple curves at once. +At one point the code took that approach, but it became too complex to maintain. +The current approach is slower but more transparent: do the individual +curves one by one, then paste together the results. + +\begin{nwchunk} +\nwhyp{survfitms-summary2}{survfitms-summary}{survfitms-summary1}{survfitms-summary3}= + summary.survfit <- function(object, times, censored=FALSE, + scale=1, extend=FALSE, + rmean=getOption('survfit.rmean'), + ...) \{ + fit <- object #save typing + if (!inherits(fit, 'survfit')) + stop("summary.survfit can only be used for survfit objects") + if (is.null(fit$logse)) fit$logse <- TRUE #older style + + # The print.rmean option is depreciated, it is still listened + # to in print.survfit, but ignored here + if (is.null(rmean)) rmean <- "common" + if (is.numeric(rmean)) \{ + if (is.null(fit$start.time)) \{ + if (rmean < min(fit$time)) + stop("Truncation point for the mean time in state is < smallest survival") + \} + else if (rmean < fit$start.time) + stop("Truncation point for the mean time in state is < smallest survival") + \} + else \{ + rmean <- match.arg(rmean, c('none', 'common', 'individual')) + if (length(rmean)==0) stop("Invalid value for rmean option") + \} + + # adding time 0 makes the mean and median easier + fit0 <- survfit0(fit, fit$start.time) #add time 0 + temp <- survmean(fit0, scale=scale, rmean) + table <- temp$matrix #for inclusion in the output list + rmean.endtime <- temp$end.time + + if (!is.null(fit$strata)) \{ + nstrat <- length(fit$strata) + \} + delta <- function(x, indx) \{ # sums between chosen times + if (is.logical(indx)) indx <- which(indx) + if (!is.null(x) && length(indx) >0) \{ + fx <- function(x, indx) diff(c(0, c(0, cumsum(x))[indx+1])) + if (is.matrix(x)) \{ + temp <- apply(x, 2, fx, indx=indx) + # don't return a vector when only 1 time point is given + if (is.matrix(temp)) temp else matrix(temp, nrow=1) + \} + else fx(x, indx) + \} + else NULL + \} + + if (missing(times)) \{ + \nwhypf{survfitms-simple1}{survfitms-simple}{survfitms-simple2} + \} + else \{ + fit <- fit0 + \nwhypf{survfitms-times1}{survfitms-times}{survfitms-times2} + times <- sort(times) #in case the user forgot + if (is.null(fit$strata)) fit <- findrow(fit, times, extend) + else \{ + ltemp <- vector("list", nstrat) + for (i in 1:nstrat) + ltemp[[i]] <- findrow(fit[i], times, extend) + fit <- unpacksurv(fit, ltemp) + \} + \} + + # finish off the output structure + fit$table <- table + if (length(rmean.endtime)>0 && !any(is.na(rmean.endtime[1]))) + fit$rmean.endtime <- rmean.endtime + + # A survfit object may contain std(log S) or std(S), summary always std(S) + if (!is.null(fit$std.err) && fit$logse) fit$std.err <- fit$std.err * fit$surv + + # Expand the strata + if (!is.null(fit$strata)) + fit$strata <- factor(rep(1:nstrat, fit$strata), 1:nstrat, + labels= names(fit$strata)) + if (scale != 1) \{ + # fix scale in the output + fit$time <- fit$time/scale + \} + + class(fit) <- "summary.survfit" + fit + \} +\end{nwchunk} + +The simple case of no times argument. +\begin{nwchunk} +\nwhyp{survfitms-simple2}{survfitms-simple}{survfitms-simple1}{survfitms-simple3}= + if (!censored) \{ + index <- (rowSums(as.matrix(fit$n.event)) >0) + for (i in c("time","n.risk", "n.event", "surv", "pstate", "std.err", + "upper", "lower", "cumhaz", "std.chaz")) \{ + if (!is.null(fit[[i]])) \{ # not all components in all objects + temp <- fit[[i]] + if (is.matrix(temp)) temp <- temp[index,,drop=FALSE] + else if (!is.array(temp)) temp <- temp[index] #simple vector + else temp <- temp[index,,, drop=FALSE] # 3 way + fit[[i]] <- temp + \} + \} + + # The n.enter and n.censor values are accumualated + # both of these are simple vectors + if (is.null(fit$strata)) \{ + for (i in c("n.enter", "n.censor")) + if (!is.null(fit[[i]])) + fit[[i]] <- delta(fit[[i]], index) + \} + else \{ + sindx <- rep(1:nstrat, fit$strata) + for (i in c("n.enter", "n.censor")) \{ + if (!is.null(fit[[i]])) + fit[[i]] <- unlist(sapply(1:nstrat, function(j) + delta(fit[[i]][sindx==j], index[sindx==j]))) + \} + # the "factor" is needed for the case that a strata has no + # events at all, and hence 0 lines of output + fit$strata[] <- as.vector(table(factor(sindx[index], 1:nstrat))) + \} + \} + #if missing(times) and censored=TRUE, the fit object is ok as it is +\end{nwchunk} + +To deal with selected times we first define a subscripting function. +For indices of 0, which are requested times that are before the first event, +it fills in the initial value. + +\begin{nwchunk} +\nwhyp{survfitms-times2}{survfitms-times}{survfitms-times1}{survfitms-times3}= + ssub<- function(x, indx) \{ #select an object and index + if (!is.null(x) && length(indx)>0) \{ + if (is.matrix(x)) x[pmax(1,indx),,drop=FALSE] + else if (is.array(x)) x[pmax(1,indx),,,drop=FALSE] + else x[pmax(1, indx)] + \} + else NULL + \} +\end{nwchunk} + +This function does the real work, for any single curve. +The default value for init is correct for survival curves. + +Say that the data has values at time 5, 10, 15, 20 \ldots, and a user asks +for \code{times=c(7, 15, 20, 30)}. +In the input object \code{n.risk} refers to the number at risk just before +time 5, 10, \ldots; it is a left-continuous function. +The survival is a right-continuous function. So at time 7 we want to +take the survival from time 5 and number at risk from time 10; +\code{indx1} will be the right-continuous index and \code{indx2} the +left continuous one. The value of n.risk at time 30 has to be computed. +For counts of events, censoring, and entry we want to know the total +number that happened during the intervals of 0-7, 7-15, 15-20 and 20-30. +Technically censorings at time 15 happen just after time 15 so would +go into the third line of the report. +However, this would lead to terrible confusion for the user since +using \code{times=c(5, 10, 15, 20)} would lead to different counts than +a call that did not contain the times argument, so all 3 of the intermediates +are computed using indx1. +A report at time 30 is made only if extend=TRUE, in which case we need +to compute a tail value for n.risk. +\begin{nwchunk} +\nwhyp{survfitms-times3}{survfitms-times}{survfitms-times2}{survfitms-times4}= + findrow <- function(fit, times, extend) \{ + if (FALSE) \{ + if (is.null(fit$start.time)) mintime <- min(fit$time, 0) + else mintime <- fit$start.time + ptimes <- times[times >= mintime] + \} else ptimes <- times[is.finite(times)] + + if (!extend) \{ + maxtime <- max(fit$time) + ptimes <- ptimes[ptimes <= maxtime] + \} + ntime <- length(fit$time) + + index1 <- findInterval(ptimes, fit$time) + index2 <- 1 + findInterval(ptimes, fit$time, left.open=TRUE) + if (length(index1) ==0) + stop("no points selected for one or more curves, consider using the extend argument") + # The pmax() above encodes the assumption that n.risk for any + # times before the first observation = n.risk at the first obs + fit$time <- ptimes + + for (i in c("surv", "pstate", "upper", "lower", "std.err", "cumhaz", + "std.chaz")) \{ + if (!is.null(fit[[i]])) fit[[i]] <- ssub(fit[[i]], index1) + \} + + if (is.matrix(fit$n.risk)) \{ + # Every observation in the data has to end with a censor or event. + # So by definition the number at risk after the last observed time + # value must be 0. + fit$n.risk <- rbind(fit$n.risk,0)[index2,,drop=FALSE] + \} + else fit$n.risk <- c(fit$n.risk, 0)[index2] + + for (i in c("n.event", "n.censor", "n.enter")) + fit[[i]] <- delta(fit[[i]], index1) + fit + \} + + # For a single component, turn it from a list into a single vector, matrix + # or array + unlistsurv <- function(x, name) \{ + temp <- lapply(x, function(x) x[[name]]) + if (is.vector(temp[[1]])) unlist(temp) + else if (is.matrix(temp[[1]])) do.call("rbind", temp) + else \{ + # the cumulative hazard is the only component that is an array + # it's third dimension is n + xx <- unlist(temp) + dd <- dim(temp[[1]]) + dd[3] <- length(xx)/prod(dd[1:2]) + array(xx, dim=dd) + \} + \} + + # unlist all the components built by a set of calls to findrow + # and remake the strata + unpacksurv <- function(fit, ltemp) \{ + keep <- c("time", "surv", "pstate", "upper", "lower", "std.err", + "cumhaz", "n.risk", "n.event", "n.censor", "n.enter", + "std.chaz") + for (i in keep) + if (!is.null(fit[[i]])) fit[[i]] <- unlistsurv(ltemp, i) + fit$strata[] <- sapply(ltemp, function(x) length(x$time)) + fit + \} +\end{nwchunk} + +Repeat the code for survfitms objects. The only real difference is +the preservation of \code{pstate} and \code{cumhaz} instead of \code{surv}, +and the use of survmean2. + +\begin{nwchunk} +\nwhypb{survfitms-summary3}{survfitms-summary}{survfitms-summary2}= + summary.survfitms <- function(object, times, censored=FALSE, + scale=1, extend=FALSE, + rmean= getOption("survfit.rmean"), + ...) \{ + + fit <- object # save typing + if (!inherits(fit, 'survfitms')) + stop("summary.survfitms can only be used for survfitms objects") + if (is.null(fit$logse)) fit$logse <- FALSE # older style + + # The print.rmean option is depreciated, it is still listened + # to in print.survfit, but ignored here + if (is.null(rmean)) rmean <- "common" + if (is.numeric(rmean)) \{ + if (is.null(fit$start.time)) \{ + if (rmean < min(fit$time)) + stop("Truncation point for the mean is < smallest survival") + \} + else if (rmean < fit$start.time) + stop("Truncation point for the mean is < smallest survival") + \} + else \{ + rmean <- match.arg(rmean, c('none', 'common', 'individual')) + if (length(rmean)==0) stop("Invalid value for rmean option") + \} + + fit0 <- survfit0(fit, fit$start.time) # add time 0 + temp <- survmean2(fit0, scale=scale, rmean) + table <- temp$matrix #for inclusion in the output list + rmean.endtime <- temp$end.time + + if (!missing(times)) \{ + if (!is.numeric(times)) stop ("times must be numeric") + times <- sort(times) + \} + + if (!is.null(fit$strata)) \{ + nstrat <- length(fit$strata) + sindx <- rep(1:nstrat, fit$strata) + \} + delta <- function(x, indx) \{ # sums between chosen times + if (is.logical(indx)) indx <- which(indx) + if (!is.null(x) && length(indx) >0) \{ + fx <- function(x, indx) diff(c(0, c(0, cumsum(x))[indx+1])) + if (is.matrix(x)) \{ + temp <- apply(x, 2, fx, indx=indx) + if (is.matrix(temp)) temp else matrix(temp, nrow=1) + \} + else fx(x, indx) + \} + else NULL + \} + + if (missing(times)) \{ + \nwhypb{survfitms-simple3}{survfitms-simple}{survfitms-simple2} + \} + else \{ + fit <-fit0 # easier to work with + \nwhypb{survfitms-times4}{survfitms-times}{survfitms-times3} + times <- sort(times) + if (is.null(fit$strata)) fit <- findrow(fit, times, extend) + else \{ + ltemp <- vector("list", nstrat) + for (i in 1:nstrat) + ltemp[[i]] <- findrow(fit[i,], times, extend) + fit <- unpacksurv(fit, ltemp) + \} + \} + + # finish off the output structure + fit$table <- table + if (length(rmean.endtime)>0 && !any(is.na(rmean.endtime))) + fit$rmean.endtime <- rmean.endtime + + if (!is.null(fit$strata)) + fit$strata <- factor(rep(names(fit$strata), fit$strata)) + + # A survfit object may contain std(log S) or std(S), summary always std(S) + if (!is.null(fit$std.err) && fit$logse) fit$std.err <- fit$std.err * fit$surv + if (scale != 1) \{ + # fix scale in the output + fit$time <- fit$time/scale + \} + class(fit) <- "summary.survfitms" + fit + \} + + \nwhypf{printms1}{printms}{printms2} + \nwhypf{survmean21}{survmean2}{survmean22} +\end{nwchunk} + +Printing for a survfitms object is different than for a survfit one. +The big difference is that I don't have an estimate of the median, or +any other quantile for that matter. Mean time in state makes sense, but +I don't have a standard error for it at the moment. +The other is that there is usually a mismatch between the n.event matrix +and the n.risk matrix. +The latter has all the states that were possible whereas the former only +has states with an arrow pointing in. We need to manufacture the 0 events +for the other states. + +\begin{nwchunk} +\nwhypb{printms2}{printms}{printms1}= + print.survfitms <- function(x, scale=1, + rmean = getOption("survfit.rmean"), ...) \{ + if (!is.null(cl<- x$call)) \{ + cat("Call: ") + dput(cl) + cat("{\textbackslash}n") + \} + omit <- x$na.action + if (length(omit)) cat(" ", naprint(omit), "{\textbackslash}n") + + x <- survfit0(x, x$start.time) + if (is.null(rmean)) rmean <- "common" + if (is.numeric(rmean)) \{ + if (is.null(x$start.time)) \{ + if (rmean < min(x$time)) + stop("Truncation point for the mean is < smallest survival") + \} + else if (rmean < x$start.time) + stop("Truncation point for the mean is < smallest survival") + \} + else \{ + rmean <- match.arg(rmean, c('none', 'common', 'individual')) + if (length(rmean)==0) stop("Invalid value for rmean option") + \} + + temp <- survmean2(x, scale=scale, rmean) + if (is.null(temp$end.time)) print(temp$matrix, ...) + else \{ + etime <- temp$end.time + dd <- dimnames(temp$matrix) + cname <- dd[[2]] + cname[length(cname)] <- paste0(cname[length(cname)], '*') + dd[[2]] <- cname + dimnames(temp$matrix) <- dd + print(temp$matrix, ...) + if (length(etime) ==1) + cat(" *mean time in state, restricted (max time =", + format(etime, ...), "){\textbackslash}n") + else cat(" *mean time in state, restricted (per curve cutoff){\textbackslash}n") + \} + invisible(x) + \} +\end{nwchunk} + +This part of the computation is set out separately since it is called +by both print and summary. +\begin{nwchunk} +\nwhypb{survmean22}{survmean2}{survmean21}= + survmean2 <- function(x, scale=1, rmean) \{ + nstate <- length(x$states) #there will always be at least 1 state + ngrp <- max(1, length(x$strata)) + if (is.null(x$newdata)) ndata <- 0 else ndata <- nrow(x$newdata) + if (ngrp >1) \{ + igrp <- rep(1:ngrp, x$strata) + rname <- names(x$strata) + \} + else \{ + igrp <- rep(1, length(x$time)) + rname <- NULL + \} + + # The n.event matrix may not have nstate columms. Its + # colnames are the first elements of states, however + if (is.matrix(x$n.event)) \{ + nc <- ncol(x$n.event) + nevent <- tapply(x$n.event, list(rep(igrp, nc), col(x$n.event)), sum) + dimnames(nevent) <- list(rname, x$states[1:nc]) + \} + else \{ + nevent <- tapply(x$n.event, igrp, sum) + names(nevent) <- rname + \} + + if (ndata< 2) \{ + outmat <- matrix(0., nrow=nstate*ngrp , ncol=2) + outmat[,1] <- rep(x$n, nstate) + outmat[1:length(nevent), 2] <- c(nevent) + + if (ngrp >1) + rowname <- c(outer(rname, x$states, paste, sep=", ")) + else rowname <- x$states + \} + else \{ + outmat <- matrix(0., nrow=nstate*ndata*ngrp, ncol=2) + outmat[,1] <- rep(x$n, nstate*ndata) + outmat[, 2] <- rep(c(nevent), each=ndata) + + temp <- outer(1:ndata, x$states, paste, sep=", ") + if (ngrp >1) + rowname <- c(outer(rname, temp, paste, sep=", ")) + else rowname <- temp + nstate <- nstate * ndata + \} + + # Caculate the mean time in each state + if (rmean != "none") \{ + if (is.numeric(rmean)) maxtime <- rep(rmean, ngrp) + else if (rmean=="common") maxtime <- rep(max(x$time), ngrp) + else maxtime <- tapply(x$time, igrp, max) + + meantime <- matrix(0., ngrp, nstate) + if (!is.null(x$influence)) stdtime <- meantime + for (i in 1:ngrp) \{ + # a 2 dimensional matrix is an "array", but a 3-dim array is + # not a "matrix", so check for matrix first. + if (is.matrix(x$pstate)) + temp <- x$pstate[igrp==i,, drop=FALSE] + else if (is.array(x$pstate)) + temp <- matrix(x$pstate[igrp==i,,,drop=FALSE], + ncol= nstate) + else temp <- matrix(x$pstate[igrp==i], ncol=1) + + tt <- x$time[igrp==i] + + # Now cut it off at maxtime + delta <- diff(c(tt[tt nrow(temp)) delta <- delta[1:nrow(temp)] + if (length(delta) < nrow(temp)) + delta <- c(delta, rep(0, nrow(temp) - length(delta))) + meantime[i,] <- colSums(delta*temp) + + if (!is.null(x$influence)) \{ + # calculate the variance + if (is.list(x$influence)) + itemp <- apply(x$influence[[i]], 1, + function(x) colSums(x*delta)) + else itemp <- apply(x$influence, 1, + function(x) colSums(x*delta)) + stdtime[i,] <- sqrt(rowSums(itemp^2)) + \} + \} + outmat <- cbind(outmat, c(meantime)/scale) + cname <- c("n", "nevent", "rmean") + if (!is.null(x$influence)) \{ + outmat <- cbind(outmat, c(stdtime)/scale) + cname <- c(cname, "std(rmean)") + \} + # report back a single time, if there is only one + if (all(maxtime == maxtime[1])) maxtime <- maxtime[1] + \} + else cname <- c("n", "nevent") + dimnames(outmat) <- list(rowname, cname) + + if (rmean=='none') list(matrix=outmat) + else list(matrix=outmat, end.time=maxtime/scale) + \} +\end{nwchunk} +\section{Matrix exponentials and transition matrices} +For multi-state models, we need to compute the exponential of the transition +matrix, sometimes many times. +The matrix exponential is formally defined as +\begin{equation*} + \exp(R) = I + \sum_{j=1}^\infty R^i/i! + \end{equation*} +The computation is nicely solved by the expm package +\emph{if} we didn't need derivatives and/or high speed. +We want both. + +For the package there are three cases: +\begin{enumerate} + \item If there is only one departure state, then there is a fast closed + form solution, shown below. This case occurs whenever an event time + is unique, i.e., no other event times are tied with this one. This always + holds for competing risk models. + \item If the rate matrix $R$ is upper triangular and the (non-zero) diagonal + elements are distinct, there is a fast matrix decomposition algorithm. + If the transition matrix is acylic then it can be rearranged to be in upper + triangular form. The decomposition also gives a simple expression for + the derivative. + \item In the general case we use a Pade-Laplace algorithm: the same found + in the matexp package. +\end{enumerate} + +For a rate matrix $R$, $R_{jk}$ is the rate of transition from state $j$ to +state $k$, and is itself an exponential $R_{jk} = \exp(\eta_{jk})$. +Thus all non-diagonal values must be $/ge 0$. Transitions that do not occur +have rate 0. +The diagonal element is determined by the constraint that row sums are 0. +Let $A= \exp(R)$. +Also be aware that $\exp(A)\exp(B) \ne \exp(A+B)$ for the case of matrices. + +If there is only one non-zero diagonal element, $R_{jj}$ say, then +\begin{align*} + A_{jj} &= e^{R_{jj}} \\ + A_{jk} &= \left(1- e^{R_{jj}}\right) \frac{R_{jk}}/{\sum_{l\ne j} R_{jl}} \\ + A_{kk} &= 1; k\ne j +\end{align*} +and all other elements of $A$ are zero. +The derivative of $A$ with respect to $\eta_{jk}$ will be 0 for all rows +except row $j$. +\begin{align*} + \frac{\partial A_{jj}}{\partial \eta_{jk}} &= + \frac{\partial \exp(-\sum_{k!=j} \eta_{jk})}{\partial \eta_{jk}} \\ + &= -\eta_{jk} A_{jj} \\ + \frac{\partial A_{jk}}{\partial \eta_{jk}} &= eta_{jk}A_{jj} + \;\mbox{single event type} \\ + \frac{\partial A_{jk}}{\partial \eta_{jm}}&= + A_{jj} eta_{jm}\frac{R_{jm}}{\sum_{l\ne j} R_{jl}} + + (A_{jj} -1) \frac{\eta_{jm} (1- \sum_{l\ne j} R_{jl})}{(\sum_{l\ne j} R_{jl})^2} +\end{align*} +If time is continuous then most events will be at a unique event time, and this +fast computation will be the most common case. + +If the state space is acylic, the case for many survival problems, then +we can reorder the states so that R is upper triangular. +In that case, the diagonal elements of R are the eigenvalues. If these +are unique (ignoring the zeros), then an algorithm of Kalbfleisch and Lawless +gives both A and the derivatives of A in terms of a matrix decomposition. +For the remaining cases use the Pade' approximation as found in the +matexp package. +The overall stategy is the following: +\begin{enumerate} + \item Call \code{survexpmsetup} once, which will decide if the matrix is + acyclic, and return a reorder vector if so or a flag if it is not. + This determination is based on the possible transitions, e.g., on the + transitions matrix from survcheck. + \item Call \code{survexpm} for each individual transition matrix. + In that routine + \begin{itemize} + \item First check for the simple case, otherwise + \item Do not need derivatives: call survexpm + \item Do need derivatives + \begin{itemize} + \item If upper triangular and no tied values, use the deriv routine + \item Otherwise use the Pade routine + \end{itemize} + \end{itemize} +\end{enumerate} + +\begin{nwchunk} +\nwhypf{survexpm1}{survexpm}{survexpm2}= + survexpmsetup <- function(rmat) \{ + # check the validity of the transition matrix, and determine if it + # is acyclic, i.e., can be reordered into an upper triangular matrix. + if (!is.matrix(rmat) || nrow(rmat) != ncol(rmat) || any(diag(rmat) > 0) || + any(rmat[row(rmat) != col(rmat)] < 0)) + stop ("input is not a transition matrix") + if (!is.logical(all.equal(rowSums(rmat), rep(0, ncol(rmat))))) + stop("input is not a transition matrix") + nc <- ncol(rmat) + lower <- row(rmat) > col(rmat) + if (all(rmat[lower] ==0)) return(0) # already in order + + # score each state by (number of states it follows) - (number it precedes) + temp <- 1*(rmat >0) # 0/1 matrix + indx <- order(colSums(temp) - rowSums(temp)) + temp <- rmat[indx, indx] # try that ordering + if (all(temp[lower]== 0)) indx # it worked! + else -1 # there is a loop in the states + \} +\end{nwchunk} + +\subsection{Decompostion} +Based on Kalbfleisch and Lawless, ``The analysis of panel data under a +Markov assumption'' (J Am Stat Assoc, 1985:863-871), the +rate matrix $R$ can be written as $ADA^{-1}$ for some matrix $A$, where +$D$ is a diagonal matrix of eigenvalues, provided all of the eigenvalues +are distinct. Then $R^k = A D^k A^{-1}$, and using the definition of +a matrix exponential we see that +$\exp(R) = A \exp(D) A^{-1}$. The exponential of a diagonal +matrix is simply a diagonal matrix of the exponentials. +The matrix $Rt$ for a scalar $t$ has decomposition $A\exp(Dt)A^{-1}$; a +single decompostion suffices for all values of $t$. + +A particular example is +\begin{equation} + R = + \begin{pmatrix} + r_{11} & r_{12} & r_{13} & 0 & 0 & r_{15}\\ + 0 & r_{22} & 0 & r_{24} & 0 & r_{25}\\ + 0 & 0 & r_{33} & r_{34} & r_{35} & r_{35}\\ + 0 & 0 & 0 & r_{44} & r_{45} & r_{45} \\ + 0 & 0 & 0 & 0 & r_{55} & r_{55} \\ + 0 & 0 & 0 & 0 & 0 & 0 + \end{pmatrix}. +\end{equation} +Since this is a transition matrix the diagonal elements are constrained so that +row sums are zero: $r_{ii} = -\sum_{j\ne i} r_{ij}$. +Since R is an upper triangular matrix it's eigenvalues lie on the diagonal. +If none of the the eigenvalues are +repeated, then the Prentice result applies. + +The decompostion is quite simple since $R$ is triangular. +We want the eigenvectors, i.e. solutions to +\begin{align*} + R v_i &= r_{ii} v_i \\ +% R v_2 &= r_{22} v_2 \\ +% R v_3 &= r_{33} v_3 \\ +% R v_4 &= r_{44} v_4 \\ +% R v_5 &= r_{55} v_5 \\ +% R v_6 &= r_{66} v_6 +\end{align*} +for $i= 1, \dots, 6$, where $v_i$ are the colums of $V$. + +It turns out that the set of eigenvectors is +also upper triangular; we can solve for them one by one +using back substitution. +For the first eigenvector we have +$v_1 = (1, 0,0,0,0,0)$. +For the second we have the equations +\begin{align*} + r_{11} x + r_{12}y &= r_{22} x \\ + r_{22}y &= r_{22} y +\end{align*} +which has the solution $(r_{12}/(r_{22}- r_{11}), 1, 0,0,0,0)$, +and the process recurs for other rows. +Since $V$ is triangular the inverse of $V$ is upper triangular +and also easy to compute. + +This approach fails if there are tied eigenvalues. +Kalbfleice and Lawless comment that this case is rare, +but one can then use a decomposition to Jordan canonical form re +Cox and Miller, the Theory of Stochastic Processes, 1965. +Although this leads to some nice theorems it does not give a +simple comutational form, however, +and it is easier to fall back on the pade routine. +At this time, the pade routine is as fast as the triangluar code, +at least for small matrices without deriviatives. + +\begin{nwchunk} +\nwhyp{survexpm2}{survexpm}{survexpm1}{survexpm3}= + survexpm <- function(rmat, time=1.0, setup, eps=1e-6) \{ + # rmat is a transition matrix, so the diagonal elements are 0 or negative + if (length(rmat)==1) exp(rmat[1]*time) #failsafe -- should never be called + else \{ + nonzero <- (diag(rmat) != 0) + if (sum(nonzero ==0)) diag(nrow(rmat)) # expm(0 matrix) = identity + if (sum(nonzero) ==1) \{ + j <- which(nonzero) + emat <- diag(nrow(rmat)) + temp <- exp(rmat[j,j] * time) + emat[j,j] <- temp + emat[j, -j] <- (1-temp)* rmat[j, -j]/sum(rmat[j,-j]) + emat + \} + else if (missing(setup) || setup[1] < 0 || + any(diff(sort(diag(rmat)))< eps)) pade(rmat*time) + else \{ + if (setup[1]==0) .Call(Ccdecomp, rmat, time)$P + else \{ + temp <- rmat + temp[setup, setup] <- .Call(Ccdecomp, rmat[setup, setup], time) + temp$P + \} + \} + \} + \} +\end{nwchunk} + +The routine below is modeled after the cholesky routines in the survival +library. +To help with notation, the return values are labeled as in the +Kalbfleisch and Lawless paper, +except that their Q = our rmat. Q = A diag(d) Ainv and P= exp(Qt) + +\begin{nwchunk} +\nwhypn{cdecomp}= + /* + ** Compute the eigenvectors for the upper triangular matrix R + */ + #include + #include "R.h" + #include "Rinternals.h" + + SEXP cdecomp(SEXP R2, SEXP time2) \{ + int i,j,k; + int nc, ii; + + static const char *outnames[]= \{"d", "A", "Ainv", + "P", ""\}; + SEXP rval, stemp; + double *R, *A, *Ainv, *P; + double *dd, temp, *ediag; + double time; + + nc = ncols(R2); /* number of columns */ + R = REAL(R2); + time = asReal(time2); + + /* Make the output matrices as copies of R, so as to inherit + ** the dimnames and etc + */ + + PROTECT(rval = mkNamed(VECSXP, outnames)); + stemp= SET_VECTOR_ELT(rval, 0, allocVector(REALSXP, nc)); + dd = REAL(stemp); + stemp = SET_VECTOR_ELT(rval, 1, allocMatrix(REALSXP, nc, nc)); + A = REAL(stemp); + for (i =0; i< nc*nc; i++) A[i] =0; /* R does not zero memory */ + stemp = SET_VECTOR_ELT(rval, 2, duplicate(stemp)); + Ainv = REAL(stemp); + stemp = SET_VECTOR_ELT(rval, 3, duplicate(stemp)); + P = REAL(stemp); + + ediag = (double *) R_alloc(nc, sizeof(double)); + + /* + ** Compute the eigenvectors + ** For each column of R, find x such that Rx = kx + ** The eigenvalue k is R[i,i], x is a column of A + ** Remember that R is in column order, so the i,j element is in + ** location i + j*nc + */ + ii =0; /* contains i * nc */ + for (i=0; i=0; j--) \{ /* fill in the rest */ + temp =0; + for (k=j; k<=i; k++) temp += R[j + k*nc]* A[k +ii]; + A[j +ii] = temp/(dd[i]- R[j + j*nc]); + \} + ii += nc; + \} + + /* + ** Solve for A-inverse, which is also upper triangular. The diagonal + ** of A and the diagonal of A-inverse are both 1. At the same time + ** solve for P = A D Ainverse, where D is a diagonal matrix + ** with exp(eigenvalues) on the diagonal. + ** P will also be upper triangular, and we can solve for it using + ** nearly the same code as above. The prior block had RA = x with A the + ** unknown and x successive colums of the identity matrix. + ** We have PA = AD, so x is successively columns of AD. + ** Imagine P and A are 4x4 and we are solving for the second row + ** of P. Remember that P[2,1]= A[2,3] = A[2,4] =0; the equations for + ** this row of P are: + ** + ** 0*A[1,2] + P[2,2]A[2,2] + P[2,3] 0 + P[2,4] 0 = A[2,2] D[2] + ** 0*A[1,3] + P[2,2]A[2,3] + P[2,3]A[3,3] + P[2,4] 0 = A[2,3] D[3] + ** 0*A[1,4] + P[2,2]A[2,4] + P[2,3]A[3,4] + P[2,4]A[4,4] = A[2,4] D[4] + ** + ** For A-inverse the equations are (use U= A-inverse for a moment) + ** 0*A[1,2] + U[2,2]A[2,2] + U[2,3] 0 + U[2,4] 0 = 1 + ** 0*A[1,3] + U[2,2]A[2,3] + U[2,3]A[3,3] + U[2,4] 0 = 0 + ** 0*A[1,4] + U[2,2]A[2,4] + U[2,3]A[3,4] + U[2,4]A[4,4] = 0 + */ + + ii =0; /* contains i * nc */ + for (i=0; i=0; j--) \{ /* fill in the rest of the column*/ + temp =0; + for (k=j+1; k<=i; k++) temp += A[j + k*nc]* Ainv[k +ii]; + Ainv[j +ii] = -temp; + \} + + /* column i of P */ + P[i + ii] = ediag[i]; + for (j=0; j0) \{ + indx <- order(setup) + dlist <- list(P = dlist$P[indx, indx], + dmat = apply(dmat,1:2, function(x) x[indx, indx])) + \} + + dlist + \} +\end{nwchunk} + +The Pade approximation is found in the file pade.R. There is a good discussion +of the problem at www.maths.manchester.ac.uk/~higham/talks/exp09.pdf. +The pade function copied code from the matexp package, which in turn is based +on Higham 2005. Let B be a matrix and define +\begin{eqnarray*} + r_m(B) &= p(B)/q(B) \\ + p(B) &= \sum_{j=0^m} \frac{((2m-j)! m!}{(2m)!(m-j)! j!} B^j \\ + q(B) &= p(-B) +\end{eqnarray*} + +The algorithm for calculating $\exp(A)$ is based on the following table +\begin{center} +\begin{tabular}{c|ccccc} + $||A||_1$ & 0.15 & .25 & .95 & 2.1 & 3.4 \\ + m & 3 & 5 & 7 & 9 & 13 +\end{tabular} \end{center} +The 1 norm of a matrix is \code{max(colSums(A))}. If the norm is $\le 3.4$ +the $\exp(A) = r_m(A)$ using the table. +Otherwise, find $s$ such that $B = A/2^s$ has norm $<=3.4$ and use the table +method to find $\exp(B)$, then $\exp(A) \approx B^(2^s)$, the latter involves +repeated squaring of the matrix. + +The expm code has a lot of extra steps whose job is to make sure that elements +of $A$ are not too disparate in size. Transition matrices are nice and we can +skip all of that. This makes the pade function conserably faster than the +expm function from the Matrix library. In fact, if there aren't any +tied event times, most elements of the rate matrix will be zero, and +others are on the order of 1/(number at risk), so that $m=3$ is the most common +outcome. +\section{Plotting survival curves} +This version of the curves uses the newer form of the survfit object, which +fixes an original design decision that I now consider to have been a mistake. +That is, an ordinary survival curve did not store the intial (time=0, S=1) +point in the survfit object, leaving it up to plotting and/or printing routines +to glue it back on. +Later additions of delayed starting time and multi-state curves meant that I +had to store those values anyway, sticking them into appended objects. +The version3 survfit object puts the intial time back where it belongs, and +makes this routine easier to write. + +The plot, lines, and points routines use several common code blocks in order to +maintain consistency. + +The xmax argument has been a long term issue. Using xmax on a plot call, we +would like that xmax to persist in a subsequent lines.survfit call. +But, the problem with this is that lines might not be called after plot.survfit: +someone might have other data and then want to add a survfit line to it (rare +case I know). If we save the xlimits in some global object, there is no way +to erase that object every time a high level call is made. + +\begin{nwchunk} +\nwhypn{plot.survfit}= + plot.survfit<- function(x, conf.int, mark.time=FALSE, + pch=3, col=1,lty=1, lwd=1, + cex=1, log=FALSE, + xscale=1, yscale=1, + xlim, ylim, xmax, + fun, xlab="", ylab="", xaxs='r', + conf.times, conf.cap=.005, conf.offset=.012, + conf.type=c('log', 'log-log', 'plain', + 'logit', "arcsin"), + mark, noplot="(s0)", cumhaz=FALSE, + firstx, ymin, ...) \{ + + dotnames <- names(list(...)) + if (any(dotnames =='type')) + stop("The graphical argument 'type' is not allowed") + x <- survfit0(x, x$start.time) # align data at 0 for plotting + + \nwhypf{plot-log1}{plot-log}{plot-log2} + \nwhypf{plot-data1}{plot-data}{plot-data2} + \nwhypf{plot-confint1}{plot-confint}{plot-confint2} + \nwhypf{plot-transform1}{plot-transform}{plot-transform2} + \nwhypf{plot-setup-marks1}{plot-setup-marks}{plot-setup-marks2} + \nwhypf{plot-makebox1}{plot-makebox}{plot-makebox2} + \nwhypf{plot-functions1}{plot-functions}{plot-functions2} + type <- 's' + \nwhypf{plot-draw1}{plot-draw}{plot-draw2} + invisible(lastx) + \} + + lines.survfit <- function(x, type='s', + pch=3, col=1, lty=1, lwd=1, + cex=1, + mark.time=FALSE, xmax, + fun, conf.int=FALSE, + conf.times, conf.cap=.005, conf.offset=.012, + conf.type=c('log', 'log-log', 'plain', + 'logit', "arcsin"), + mark, noplot="(s0)", cumhaz=FALSE, ...) \{ + x <- survfit0(x, x$start.time) + + xlog <- par("xlog") + \nwhyp{plot-data2}{plot-data}{plot-data1}{plot-data3} + \nwhyp{plot-confint2}{plot-confint}{plot-confint1}{plot-confint3} + \nwhyp{plot-transform2}{plot-transform}{plot-transform1}{plot-transform3} + \nwhyp{plot-setup-marks2}{plot-setup-marks}{plot-setup-marks1}{plot-setup-marks3} + + # remember a prior xmax + if (missing(xmax)) xmax <- getOption("plot.survfit")$xmax + \nwhyp{plot-functions2}{plot-functions}{plot-functions1}{plot-functions3} + \nwhyp{plot-draw2}{plot-draw}{plot-draw1}{plot-draw3} + invisible(lastx) + \} + + points.survfit <- function(x, fun, censor=FALSE, + col=1, pch, noplot="(s0)", cumhaz=FALSE, ...) \{ + + conf.int <- conf.times <- FALSE # never draw these with 'points' + x <- survfit0(x, x$start.time) + + \nwhyp{plot-data3}{plot-data}{plot-data2}{plot-data4} + \nwhyp{plot-transform3}{plot-transform}{plot-transform2}{plot-transform4} + + if (ncurve==1 || (length(col)==1 && missing(pch))) \{ + if (censor) points(stime, ssurv, ...) + else points(stime[x$n.event>0], ssurv[x$n.event>0], ...) + \} + else \{ + c2 <- 1 #cycles through the colors and characters + col <- rep(col, length=ncurve) + if (!missing(pch)) \{ + if (length(pch)==1) + pch2 <- rep(strsplit(pch, '')[[1]], length=ncurve) + else pch2 <- rep(pch, length=ncurve) + \} + for (j in 1:ncol(ssurv)) \{ + for (i in unique(stemp)) \{ + if (censor) who <- which(stemp==i) + else who <- which(stemp==i & x$n.event >0) + if (missing(pch)) + points(stime[who], ssurv[who,j], col=col[c2], ...) + else + points(stime[who], ssurv[who,j], col=col[c2], + pch=pch2[c2], ...) + c2 <- c2+1 + \} + \} + \} + \} +\end{nwchunk} + +\begin{nwchunk} +\nwhypb{plot-log2}{plot-log}{plot-log1}= + # decide on logarithmic axes, yes or no + if (is.logical(log)) \{ + ylog <- log + xlog <- FALSE + if (ylog) logax <- 'y' + else logax <- "" + \} + else \{ + ylog <- (log=='y' || log=='xy') + xlog <- (log=='x' || log=='xy') + logax <- log + \} + + if (!missing(fun)) \{ + if (is.character(fun)) \{ + if (fun=='log'|| fun=='logpct') ylog <- TRUE + if (fun=='cloglog') \{ + xlog <- TRUE + if (ylog) logax <- 'xy' + else logax <- 'x' + \} + if (fun=="cumhaz" && missing(cumhaz)) cumhaz <- TRUE + \} + \} +\end{nwchunk} + +\begin{nwchunk} +\nwhypb{plot-data4}{plot-data}{plot-data3}= + # The default for plot and lines is to add confidence limits + # if there is only one curve + if (missing(conf.int) && missing(conf.times)) + conf.int <- (!is.null(x$std.err) && prod(dim(x) ==1)) + + if (missing(conf.times)) conf.times <- NULL + else \{ + if (!is.numeric(conf.times)) stop('conf.times must be numeric') + if (missing(conf.int)) conf.int <- TRUE + \} + + if (!missing(conf.int)) \{ + if (is.numeric(conf.int)) \{ + conf.level <- conf.int + if (conf.level<0 || conf.level > 1) + stop("invalid value for conf.int") + if (conf.level ==0) conf.int <- FALSE + else if (conf.level != x$conf.int) \{ + x$upper <- x$lower <- NULL # force recomputation + \} + conf.int <- TRUE + \} + else conf.level = 0.95 + \} + + # Organize data into stime, ssurv, supper, slower + stime <- x$time + std <- NULL + yzero <- FALSE # a marker that we have an "ordinary survival curve" with min 0 + smat <- function(x) \{ + # the rest of the routine is simpler if everything is a matrix + dd <- dim(x) + if (is.null(dd)) as.matrix(x) + else if (length(dd) ==2) x + else matrix(x, nrow=dd[1]) + \} + + if (cumhaz) \{ # plot the cumulative hazard instead + if (is.null(x$cumhaz)) + stop("survfit object does not contain a cumulative hazard") + + if (is.numeric(cumhaz)) \{ + dd <- dim(x$cumhaz) + if (is.null(dd)) nhazard <- 1 + else nhazard <- prod(dd[-1]) + + if (cumhaz != floor(cumhaz)) stop("cumhaz argument is not integer") + if (any(cumhaz < 1 | cumhaz > nhazard)) stop("subscript out of range") + ssurv <- smat(x$cumhaz)[,cumhaz, drop=FALSE] + if (!is.null(x$std.chaz)) std <- smat(x$std.chaz)[,cumhaz, drop=FALSE] + \} + else if (is.logical(cumhaz)) \{ + ssurv <- smat(x$cumhaz) + if (!is.null(x$std.chaz)) std <- smat(x$std.chaz) + \} + else stop("invalid cumhaz argument") + \} + else if (inherits(x, "survfitms")) \{ + i <- !(x$states %in% noplot) + if (all(i) || !any(i)) \{ + # the !any is a failsafe, in case none are kept we ignore noplot + ssurv <- smat(x$pstate) + if (!is.null(x$std.err)) std <- smat(x$std.err) + if (!is.null(x$lower)) \{ + slower <- smat(x$lower) + supper <- smat(x$upper) + \} + \} + else \{ + i <- which(i) # the states to keep + # we have to be careful about subscripting + if (length(dim(x$pstate)) ==3) \{ + ssurv <- smat(x$pstate[,,i, drop=FALSE]) + if (!is.null(x$std.err)) + std <- smat(x$std.err[,,i, drop=FALSE]) + if (!is.null(x$lower)) \{ + slower <- smat(x$lower[,,i, drop=FALSE]) + supper <- smat(x$upper[,,i, drop=FALSE]) + \} + \} + else \{ + ssurv <- x$pstate[,i, drop=FALSE] + if (!is.null(x$std.err)) std <- x$std.err[,i, drop=FALSE] + if (!is.null(x$lower)) \{ + slower <- smat(x$lower[,i, drop=FALSE]) + supper <- smat(x$upper[,i, drop=FALSE]) + \} + \} + \} + \} + else \{ + yzero <- TRUE + ssurv <- as.matrix(x$surv) # x$surv will have one column + if (!is.null(x$std.err)) std <- as.matrix(x$std.err) + # The fun argument usually applies to single state survfit objects + # First deal with the special case of fun='cumhaz', which is here for + # backwards compatability; people should use the cumhaz argument + if (!missing(fun) && is.character(fun) && fun=="cumhaz") \{ + cumhaz <- TRUE + if (!is.null(x$cumhaz)) \{ + ssurv <- as.matrix(x$cumhaz) + if (!is.null(x$std.chaz)) std <- as.matrix(x$std.chaz) + \} + else \{ + ssurv <- as.matrix(-log(x$surv)) + if (!is.null(x$std.err)) \{ + if (x$logse) std <- as.matrix(x$std.err) + else std <- as.matrix(x$std.err/x$surv) + \} + \} + \} + \} + + # set up strata + if (is.null(x$strata)) \{ + nstrat <- 1 + stemp <- rep(1, length(x$time)) # same length as stime + \} + else \{ + nstrat <- length(x$strata) + stemp <- rep(1:nstrat, x$strata) # same length as stime + \} + ncurve <- nstrat * ncol(ssurv) +\end{nwchunk} + +If confidence limits are to be plotted, and they were not part of the +data that is passed in, create them. Confidence limits for the +cumulative hazard must always be created, and they don't use transforms. +\begin{nwchunk} +\nwhypb{plot-confint3}{plot-confint}{plot-confint2}= + conf.type <- match.arg(conf.type) + if (conf.type=="none") conf.int <- FALSE + if (conf.int== "none") conf.int <- FALSE + if (conf.int=="only") \{ + plot.surv <- FALSE + conf.int <- TRUE + \} + else plot.surv <- TRUE + + if (conf.int) \{ + if (is.null(std)) stop("object does not have standard errors, CI not possible") + if (cumhaz) \{ + if (missing(conf.type)) conf.type="plain" + temp <- survfit_confint(ssurv, std, logse=FALSE, + conf.type, conf.level, ulimit=FALSE) + supper <- as.matrix(temp$upper) + slower <- as.matrix(temp$lower) + \} + else if (is.null(x$upper)) \{ + if (missing(conf.type) && !is.null(x$conf.type)) + conf.type <- x$conf.type + temp <- survfit_confint(ssurv, std, logse= x$logse, + conf.type, conf.level, ulimit=FALSE) + supper <- as.matrix(temp$upper) + slower <- as.matrix(temp$lower) + \} + else if (!inherits(x, "survfitms")) \{ + supper <- as.matrix(x$upper) + slower <- as.matrix(x$lower) + \} + \} else supper <- slower <- NULL +\end{nwchunk} + +The functional form of the fun argument can be whatever the user wants. +For the character form we try to thin out the obvious mistakes. +If fun=='cumhaz', the code above has already replaced ssurv with the +cumulative hazard, so this part of the code should plug in an identity +function. + +\begin{nwchunk} +\nwhypb{plot-transform4}{plot-transform}{plot-transform3}= + if (!missing(fun))\{ + if (is.character(fun)) \{ + if (cumhaz) \{ + tfun <- switch(tolower(fun), + 'log' = function(x) x, + 'cumhaz'=function(x) x, + 'identity'= function(x) x, + stop("Invalid function argument") + ) + \} else if (inherits(x, "survfitms")) \{ + tfun <-switch(tolower(fun), + 'log' = function(x) log(x), + 'event'=function(x) x, + 'cloglog'=function(x) log(-log(1-x)), + 'cumhaz' = function(x) x, + 'pct' = function(x) x*100, + 'identity'= function(x) x, + stop("Invalid function argument") + ) + \} else \{ + yzero <- FALSE + tfun <- switch(tolower(fun), + 'log' = function(x) x, + 'event'=function(x) 1-x, + 'cumhaz'=function(x) x, + 'cloglog'=function(x) log(-log(x)), + 'pct' = function(x) x*100, + 'logpct'= function(x) 100*x, #special case further below + 'identity'= function(x) x, + 'f' = function(x) 1-x, + 's' = function(x) x, + 'surv' = function(x) x, + stop("Unrecognized function argument") + ) + \} + \} + else if (is.function(fun)) tfun <- fun + else stop("Invalid 'fun' argument") + + ssurv <- tfun(ssurv ) + if (!is.null(supper)) \{ + supper <- tfun(supper) + slower <- tfun(slower) + \} + \} +\end{nwchunk} + +The \code{mark} argument is a holdover from S, when pch could not have +numeric values; mark has since disappeared from the manual page for +\code{par}. We honor it for backwards compatability. +To be consistent with matplot and others, we allow pch to be a character +string or a vector of characters. + +\begin{nwchunk} +\nwhypb{plot-setup-marks3}{plot-setup-marks}{plot-setup-marks2}= + if (missing(mark.time) & !missing(mark)) mark.time <- TRUE + if (missing(pch) && !missing(mark)) pch <- mark + if (length(pch)==1 && is.character(pch)) pch <- strsplit(pch, "")[[1]] + + # Marks are not placed on confidence bands + pch <- rep(pch, length.out=ncurve) + mcol <- rep(col, length.out=ncurve) + if (is.numeric(mark.time)) mark.time <- sort(mark.time) + + # The actual number of curves is ncurve*3 if there are confidence bands, + # unless conf.times has been given. Colors and line types in the latter + # match the curves + # If the number of line types is 1 and lty is an integer, then use lty + # for the curve and lty+1 for the CI + # If the length(lty) <= length(ncurve), use the same color for curve and CI + # otherwise assume the user knows what they are about and has given a full + # vector of line types. + # Colors and line widths work like line types, excluding the +1 rule. + if (conf.int & is.null(conf.times)) \{ + if (length(lty)==1 && is.numeric(lty)) + lty <- rep(c(lty, lty+1, lty+1), ncurve) + else if (length(lty) <= ncurve) + lty <- rep(rep(lty, each=3), length.out=(ncurve*3)) + else lty <- rep(lty, length.out= ncurve*3) + + if (length(col) <= ncurve) col <- rep(rep(col, each=3), length.out=3*ncurve) + else col <- rep(col, length.out=3*ncurve) + + if (length(lwd) <= ncurve) lwd <- rep(rep(lwd, each=3), length.out=3*ncurve) + else lwd <- rep(lwd, length.out=3*ncurve) + \} + else \{ + col <- rep(col, length.out=ncurve) + lty <- rep(lty, length.out=ncurve) + lwd <- rep(lwd, length.out=ncurve) + \} +\end{nwchunk} + + +Create the frame for the plot. +We draw an empty figure, letting R figure out the limits. + +\begin{nwchunk} +\nwhypb{plot-makebox2}{plot-makebox}{plot-makebox1}= + # check consistency + if (!missing(xlim)) \{ + if (!missing(xmax)) warning("cannot have both xlim and xmax arguments, xmax ignored") + if (!missing(firstx)) stop("cannot have both xlim and firstx arguments") + \} + if (!missing(ylim)) \{ + if (!missing(ymin)) stop("cannot have both ylim and ymin arguments") + \} + + # Do axis range computations + if (!missing(xlim) && !is.null(xlim)) \{ + tempx <- xlim + xmax <- xlim[2] + if (xaxs == 'S') tempx[2] <- tempx[1] + diff(tempx)*1.04 + \} + else \{ + temp <- stime[is.finite(stime)] + if (!missing(xmax) && missing(xlim)) temp <- pmin(temp, xmax) + else xmax <- NULL + + if (xaxs=='S') \{ + rtemp <- range(temp) + delta <- diff(rtemp) + #special x- axis style for survival curves + if (xlog) tempx <- c(min(rtemp[rtemp>0]), min(rtemp)+ delta*1.04) + else tempx <- c(min(rtemp), min(rtemp)+ delta*1.04) + \} + else if (xlog) tempx <- range(temp[temp > 0]) + else tempx <- range(temp) + \} + if (!missing(xlim) || !missing(xmax)) + options(plot.survfit = list(xmax=tempx[2])) + else options(plot.survfit = NULL) + + if (!missing(ylim) && !is.null(ylim)) tempy <- ylim + else \{ + skeep <- is.finite(stime) & stime >= tempx[1] & stime <= tempx[2] + + if (ylog) \{ + if (!is.null(supper)) + tempy <- range(c(slower[is.finite(slower) & slower>0 & skeep], + supper[is.finite(supper) & skeep])) + else tempy <- range(ssurv[is.finite(ssurv)& ssurv>0 & skeep]) + if (tempy[2]==1) tempy[2] <- .99 # makes for a prettier axis + if (any(c(ssurv, slower)[skeep] ==0)) \{ + tempy[1] <- tempy[1]*.8 + ssurv[ssurv==0] <- tempy[1] + if (!is.null(slower)) slower[slower==0] <- tempy[1] + \} + \} + else \{ + if (!is.null(supper)) + tempy <- range(c(supper[skeep], slower[skeep]), finite=TRUE, na.rm=TRUE) + else tempy <- range(ssurv[skeep], finite=TRUE, na.rm= TRUE) + if (yzero) tempy <- range(c(0, tempy)) + \} + \} + + if (!missing(ymin)) tempy[1] <- ymin + + # + # Draw the basic box + # + temp <- if (xaxs=='S') 'i' else xaxs + plot(range(tempx, finite=TRUE, na.rm=TRUE)/xscale, + range(tempy, finite=TRUE, na.rm=TRUE)*yscale, + type='n', log=logax, xlab=xlab, ylab=ylab, xaxs=temp,...) + if(yscale != 1) \{ + if (ylog) par(usr =par("usr") -c(0, 0, log10(yscale), log10(yscale))) + else par(usr =par("usr")/c(1, 1, yscale, yscale)) + \} + if (xscale !=1) \{ + if (xlog) par(usr =par("usr") -c(log10(xscale), log10(xscale), 0,0)) + else par(usr =par("usr")*c(xscale, xscale, 1, 1)) + \} +\end{nwchunk} +The use of \Verb!par(usr)! just above is a bit sneaky. I want the +lines and points routines to be able to add to the plot, \emph{without} +passing them a global parameter that determines the y-scale or forcing +the user to repeat it. + +The next functions do the actual drawing. +\begin{nwchunk} +\nwhypb{plot-functions3}{plot-functions}{plot-functions2}= + # Create a step function, removing redundancies that sometimes occur in + # curves with lots of censoring. + dostep <- function(x,y) \{ + keep <- is.finite(x) & is.finite(y) + if (!any(keep)) return() #all points were infinite or NA + if (!all(keep)) \{ + # these won't plot anyway, so simplify (CI values are often NA) + x <- x[keep] + y <- y[keep] + \} + n <- length(x) + if (n==1) list(x=x, y=y) + else if (n==2) list(x=x[c(1,2,2)], y=y[c(1,1,2)]) + else \{ + # replace verbose horizonal sequences like + # (1, .2), (1.4, .2), (1.8, .2), (2.3, .2), (2.9, .2), (3, .1) + # with (1, .2), (.3, .2),(3, .1). + # They are slow, and can smear the looks of the line type. + temp <- rle(y)$lengths + drops <- 1 + cumsum(temp[-length(temp)]) # points where the curve drops + + #create a step function + if (n %in% drops) \{ #the last point is a drop + xrep <- c(x[1], rep(x[drops], each=2)) + yrep <- rep(y[c(1,drops)], c(rep(2, length(drops)), 1)) + \} + else \{ + xrep <- c(x[1], rep(x[drops], each=2), x[n]) + yrep <- c(rep(y[c(1,drops)], each=2)) + \} + list(x=xrep, y=yrep) + \} + \} + + drawmark <- function(x, y, mark.time, censor, cex, ...) \{ + if (!is.numeric(mark.time)) \{ + xx <- x[censor>0] + yy <- y[censor>0] + if (any(censor >1)) \{ # tied death and censor, put it on the midpoint + j <- pmax(1, which(censor>1) -1) + i <- censor[censor>0] + yy[i>1] <- (yy[i>1] + y[j])/2 + \} + \} + else \{ #interpolate + xx <- mark.time + yy <- approx(x, y, xx, method="constant", f=0)$y + \} + points(xx, yy, cex=cex, ...) + \} +\end{nwchunk} + +The code to draw the lines and confidence bands. +\begin{nwchunk} +\nwhypb{plot-draw3}{plot-draw}{plot-draw2}= + c1 <- 1 # keeps track of the curve number + c2 <- 1 # keeps track of the lty, col, etc + xend <- yend <- double(ncurve) + if (length(conf.offset) ==1) + temp.offset <- (1:ncurve - (ncurve+1)/2)* conf.offset* diff(par("usr")[1:2]) + else temp.offset <- rep(conf.offset, length=ncurve) * diff(par("usr")[1:2]) + temp.cap <- conf.cap * diff(par("usr")[1:2]) + + for (j in 1:ncol(ssurv)) \{ + for (i in unique(stemp)) \{ #for each strata + who <- which(stemp==i) + + # if n.censor is missing, then assume any line that does not have an + # event would not be present but for censoring, so there must have + # been censoring then + # otherwise categorize is 0= no censor, 1=censor, 2=censor and death + if (is.null(x$n.censor)) censor <- ifelse(x$n.event[who]==0, 1, 0) + else censor <- ifelse(x$n.censor[who]==0, 0, 1 + (x$n.event[who] > 0)) + xx <- stime[who] + yy <- ssurv[who,j] + if (conf.int) \{ + ylower <- (slower[who,j]) + yupper <- (supper[who,j]) + \} + if (!is.null(xmax) && max(xx) > xmax) \{ # truncate on the right + xn <- min(which(xx > xmax)) + xx <- xx[1:xn] + yy <- yy[1:xn] + xx[xn] <- xmax + yy[xn] <- yy[xn-1] + if (conf.int) \{ + ylower <- ylower[1:xn] + yupper <- yupper[1:xn] + ylower[xn] <- ylower[xn-1] + yupper[xn] <- yupper[xn-1] + \} + \} + + + if (plot.surv) \{ + if (type=='s') + lines(dostep(xx, yy), lty=lty[c2], col=col[c2], lwd=lwd[c2]) + else lines(xx, yy, type=type, lty=lty[c2], col=col[c2], lwd=lwd[c2]) + if (is.numeric(mark.time) || mark.time) + drawmark(xx, yy, mark.time, censor, pch=pch[c1], col=mcol[c1], + cex=cex) + \} + xend[c1] <- max(xx) + yend[c1] <- yy[length(yy)] + + if (conf.int && !is.null(conf.times)) \{ + # add vertical bars at the specified times + x2 <- conf.times + temp.offset[c1] + templow <- approx(xx, ylower, x2, + method='constant', f=1)$y + temphigh<- approx(xx, yupper, x2, + method='constant', f=1)$y + segments(x2, templow, x2, temphigh, + lty=lty[c2], col=col[c2], lwd=lwd[c2]) + if (conf.cap>0) \{ + segments(x2-temp.cap, templow, x2+temp.cap, templow, + lty=lty[c2], col=col[c2], lwd=lwd[c2] ) + segments(x2-temp.cap, temphigh, x2+temp.cap, temphigh, + lty=lty[c2], col=col[c2], lwd=lwd[c2]) + \} + + \} + c1 <- c1 +1 + c2 <- c2 +1 + + if (conf.int && is.null(conf.times)) \{ + if (type == 's') \{ + lines(dostep(xx, ylower), lty=lty[c2], + col=col[c2],lwd=lwd[c2]) + c2 <- c2 +1 + lines(dostep(xx, yupper), lty=lty[c2], + col=col[c2], lwd= lwd[c2]) + c2 <- c2 + 1 + \} + else \{ + lines(xx, ylower, lty=lty[c2], + col=col[c2],lwd=lwd[c2], type=type) + c2 <- c2 +1 + lines(xx, yupper, lty=lty[c2], + col=col[c2], lwd= lwd[c2], type= type) + c2 <- c2 + 1 + \} + \} + + \} + \} + lastx <- list(x=xend, y=yend) +\end{nwchunk} + + + + +\section{State space figures} +The statefig function was written to do ``good enough'' state space figures +quickly and easily. There are certainly figures it can't draw and +many figures that can be drawn better, but it accomplishes its purpose. +The key argument \code{layout}, the first, is a vector of numbers. +The value (1,3,4,2) for instance has a single state, then a column with 3 +states, then a column with 4, then a column with 2. +If \code{layout} is instead a 1 column matrix then do the same from top +down. If it is a 2 column matrix then they provided their own spacing. + +\begin{nwchunk} +\nwhypn{statefig}= + statefig <- function(layout, connect, margin=.03, box=TRUE, + cex=1, col=1, lwd=1, lty=1, bcol= col, + acol=col, alwd = lwd, alty= lty, offset=0) \{ + # set up an empty canvas + frame(); # new environment + par(usr=c(0,1,0,1)) + if (!is.numeric(layout)) + stop("layout must be a numeric vector or matrix") + if (!is.matrix(connect) || nrow(connect) != ncol(connect)) + stop("connect must be a square matrix") + nstate <- nrow(connect) + dd <- dimnames(connect) + if (!is.null(dd[[1]])) statenames <- dd[[1]] + else if (is.null(dd[[2]])) + stop("connect must have the state names as dimnames") + else statenames <- dd[[2]] + + # expand out all of the graphical parameters. This lets users + # use a vector of colors, line types, etc + narrow <- sum(connect!=0) + acol <- rep(acol, length=narrow) + alwd <- rep(alwd, length=narrow) + alty <- rep(alty, length=narrow) + + bcol <- rep(bcol, length=nstate) + lty <- rep(lty, length=nstate) + lwd <- rep(lwd, length=nstate) + + col <- rep(col, length=nstate) # text colors + + \nwhypf{statefig-layout1}{statefig-layout}{statefig-layout2} + \nwhypf{statefig-text1}{statefig-text}{statefig-text2} + \nwhypf{statefig-arrows1}{statefig-arrows}{statefig-arrows2} + + dimnames(cbox) <- list(statenames, c("x", "y")) + invisible(cbox) + \} + \nwhypf{statefig-fun1}{statefig-fun}{statefig-fun2} +\end{nwchunk} + +The drawing region is always (0,1) by (0,1). +A user can enter their own matrix of coordinates. +Otherwise the free space is divided with one portion +on each end and 2 portions between boxes. If there were 3 columns for +instance they will have x coordinates of 1/6, 1/6 + 1/3, 1/6 + 2/3. Ditto +for dividing up the y coordinate. The primary nuisance is that we want to +count down from the top instead of up from the bottom. A 1 by 1 matrix is +treated as a column matrix. + +\begin{nwchunk} +\nwhypb{statefig-layout2}{statefig-layout}{statefig-layout1}= + if (is.matrix(layout) && ncol(layout)==2 && nrow(layout) > 1) \{ + # the user provided their own + if (any(layout <0) || any(layout >1)) + stop("layout coordinates must be between 0 and 1") + if (nrow(layout) != nstate) + stop("layout matrix should have one row per state") + cbox <- layout + \} + else \{ + if (any(layout <=0 | layout != floor(layout))) + stop("non-integer number of states in layout argument") + space <- function(n) (1:n -.5)/n # centers of the boxes + if (sum(layout) != nstate) stop("number of boxes != number of states") + cbox <- matrix(0, ncol=2, nrow=nstate) #coordinates will be here + n <- length(layout) + + ix <- rep(seq(along=layout), layout) + if (is.vector(layout) || ncol(layout)> 1) \{ #left to right + cbox[,1] <- space(n)[ix] + for (i in 1:n) cbox[ix==i,2] <- 1 -space(layout[i]) + \} else \{ # top to bottom + cbox[,2] <- 1- space(n)[ix] + for (i in 1:n) cbox[ix==i,1] <- space(layout[i]) + \} + \} +\end{nwchunk} + +Write the text out. Compute the width and height of each box. +Then compute the margin. The only tricky thing here is that we want +the area around the text to \emph{look} the same left-right and up-down, +which depends on the geometry of the plotting region. + +\begin{nwchunk} +\nwhypb{statefig-text2}{statefig-text}{statefig-text1}= + text(cbox[,1], cbox[,2], statenames, cex=cex, col=col) # write the labels + textwd <- strwidth(statenames, cex=cex) + textht <- strheight(statenames, cex=cex) + temp <- par("pin") #plot region in inches + dx <- margin * temp[2]/mean(temp) # extra to add in the x dimension + dy <- margin * temp[1]/mean(temp) # extra to add in y + + if (box) \{ + drawbox <- function(x, y, dx, dy, lwd, lty, col) \{ + lines(x+ c(-dx, dx, dx, -dx, -dx), + y+ c(-dy, -dy, dy, dy, -dy), lwd=lwd, lty=lty, col=col) + \} + for (i in 1:nstate) + drawbox(cbox[i,1], cbox[i,2], textwd[i]/2 + dx, textht[i]/2 + dy, + col=bcol[i], lwd=lwd[i], lty=lty[i]) + dx <- 2*dx; dy <- 2*dy # move arrows out from the box + \} +\end{nwchunk} + +Now for the hard part, which is drawing the arrows. +The entries in the connection matrix are 0= no connection or $1+d$ for +$-1 < d < 1$. The connection is an arc that passes from the center of +box 1 to the center of box 2, and through a point that is $dz$ units above +the midpoint of the line from box 1 to box 2, where $2z$ is the length +of that line. +For $d=1$ we get a half circle to the right (with respect to traversing the +line from A to B) and for $d= -1$ we get a half circle to the left. +If $d=0$ it is a straight line. + +If A and B are the starting and ending points then AB is the chord of a +circle. Draw radii from the center to A, B, and through the midpoint $c$ of +AB. This last has length $dz$ above the chord and $r- dz$ below where $r$ +is the radius. Then we have +\begin{align*} + r^2 & = z^2 + (r-dz)^2 \\ + 2rdz &= z^2 + (dz)^2 \\ + r &= \left[z (1+ d^2) \right ]/ 2d +\end{align*} +Be careful with negative $d$, which is used to denote left-hand arcs. + +The angle $\theta$ from A to B is the arctan of $B-A$, +and the center of the circle is at +$C = (A+B)/2 + (r - dz)(\sin \theta, -\cos \theta)$. +We then need to draw the arc $C + r(\cos \phi, \sin \phi)$ for some range +of angles $\phi$. +The angles to the centers of the boxes are $\arctan(A-C)$ and $\arctan(B-C)$, +but we want to start and end outside the box. +It turned out that this is more subtle than I thought. +The solution below uses two helper functions \code{statefigx} and +\code{statefigy}. +The first accepts $C$, $r$, the range of $\phi$ values, and a target +$y$ value. It returns the angles, within the range, such that the +endpoint of the arc has horizontal coordinate $x$, or an empty +vector if none such exists. For an arc there are sometimes two +solutions. +First calculate the angles for which the arc will strike the horizontal +line. If the arc is too short to reach the line then there is no +intersection. +The return legal angles. +\begin{nwchunk} +\nwhyp{statefig-fun2}{statefig-fun}{statefig-fun1}{statefig-fun3}= + statefigx <- function(x, C, r, a1, a2) \{ + temp <-(x - C[1])/r + if (abs(temp) >1) return(NULL) # no intersection of the arc and x + phi <- acos(temp) # this will be from 0 to pi + pi <- 3.1415926545898 # in case someone has a variable "pi" + if (x > C[1]) phi <- c(phi, pi - phi) + else phi <- -c(phi, pi - phi) + # Add reflection about the X axis, in both forms + phi <- c(phi, -phi, 2*pi - phi) + amax <- max(a1, a2) + amin <- min(a1, a2) + phi[phi amin] + \} + statefigy <- function(y, C, r, a1, a2) \{ + pi <- 3.1415926545898 # in case someone has a variable named "pi" + amax <- max(a1, a2) + amin <- min(a1, a2) + temp <-(y - C[2])/r + if (abs(temp) >1) return(NULL) # no intersection of the arc and y + phi <- asin(temp) # will be from -pi/2 to pi/2 + phi <- c(phi, sign(phi)*pi -phi) # reflect about the vertical + phi <- c(phi, phi + 2*pi) + phi[phi amin] + \} +\end{nwchunk} + +\begin{nwchunk} +\nwhypb{statefig-fun3}{statefig-fun}{statefig-fun2}= + phi <- function(x1, y1, x2, y2, d, delta1, delta2) \{ + # d = height above the line + theta <- atan2(y2-y1, x2-x1) # angle from center to center + if (abs(d) < .001) d=.001 # a really small arc looks like a line + + z <- sqrt((x2-x1)^2 + (y2 - y1)^2) /2 # half length of chord + ab <- c((x1 + x2)/2, (y1 + y2)/2) # center of chord + r <- abs(z*(1 + d^2)/ (2*d)) + if (d >0) C <- ab + (r - d*z)* c(-sin(theta), cos(theta)) # center of arc + else C <- ab + (r + d*z)* c( sin(theta), -cos(theta)) + + a1 <- atan2(y1-C[2], x1-C[1]) # starting angle + a2 <- atan2(y2-C[2], x2-C[1]) # ending angle + if (abs(a2-a1) > pi) \{ + # a1= 3 and a2=-3, we don't want to include 0 + # nor for a1=-3 and a2=3 + if (a1>0) a2 <- a2 + 2 *pi + else a1 <- a1 + 2*pi + \} + if (d > 0) \{ #counterclockwise + phi1 <- min(statefigx(x1 + delta1[1], C, r, a1, a2), + statefigx(x1 - delta1[1], C, r, a1, a2), + statefigy(y1 + delta1[2], C, r, a1, a2), + statefigy(y1 - delta1[2], C, r, a1, a2), na.rm=TRUE) + phi2 <- max(statefigx(x2 + delta2[1], C, r, a1, a2), + statefigx(x2 - delta2[1], C, r, a1, a2), + statefigy(y2 + delta2[2], C, r, a1, a2), + statefigy(y2 - delta2[2], C, r, a1, a2), na.rm=TRUE) + \} + else \{ # clockwise + phi1 <- max(statefigx(x1 + delta1[1], C, r, a1, a2), + statefigx(x1 - delta1[1], C, r, a1, a2), + statefigy(y1 + delta1[2], C, r, a1, a2), + statefigy(y1 - delta1[2], C, r, a1, a2), na.rm=TRUE) + phi2 <- min(statefigx(x2 + delta2[1], C, r, a1, a2), + statefigx(x2 - delta2[1], C, r, a1, a2), + statefigy(y2 + delta2[2], C, r, a1, a2), + statefigy(y2 - delta2[2], C, r, a1, a2), na.rm=TRUE) + \} + + list(center=C, angle=c(phi1, phi2), r=r) + \} +\end{nwchunk} + +Now draw the arrows, one at a time. I arbitrarily declare that 20 +segments is enough for a smooth curve. +\begin{nwchunk} +\nwhyp{statefig-arrows2}{statefig-arrows}{statefig-arrows1}{statefig-arrows3}= + arrow2 <- function(...) arrows(..., angle=20, length=.1) + doline <- function(x1, x2, d, delta1, delta2, lwd, lty, col) \{ + if (d==0 && x1[1] ==x2[1]) \{ # vertical line + if (x1[2] > x2[2]) # downhill + arrow2(x1[1], x1[2]- delta1[2], x2[1], x2[2] + delta2[2], + lwd=lwd, lty=lty, col=col) + else arrow2(x1[1], x1[2]+ delta1[2], x2[1], x2[2] - delta2[2], + lwd=lwd, lty=lty, col=col) + \} + else if (d==0 && x1[2] == x2[2]) \{ # horizontal line + if (x1[1] > x2[1]) # right to left + arrow2(x1[1]-delta1[1], x1[2], x2[1] + delta2[1], x2[2], + lwd=lwd, lty=lty, col=col) + else arrow2(x1[1]+delta1[1], x1[2], x2[1] - delta2[1], x2[2], + lwd=lwd, lty=lty, col=col) + \} + else \{ + temp <- phi(x1[1], x1[2], x2[1], x2[2], d, delta1, delta2) + if (d==0) \{ + arrow2(temp$center[1] + temp$r*cos(temp$angle[1]), + temp$center[2] + temp$r*sin(temp$angle[1]), + temp$center[1] + temp$r*cos(temp$angle[2]), + temp$center[2] + temp$r*sin(temp$angle[2]), + lwd=lwd, lty=lty, col=col) + \} + else \{ + # approx the curve with 21 segments + # arrowhead on the last one + phi <- seq(temp$angle[1], temp$angle[2], length=21) + lines(temp$center[1] + temp$r*cos(phi), + temp$center[2] + temp$r*sin(phi), lwd=lwd, lty=lty, col=col) + arrow2(temp$center[1] + temp$r*cos(phi[20]), + temp$center[2] + temp$r*sin(phi[20]), + temp$center[1] + temp$r*cos(phi[21]), + temp$center[2] + temp$r*sin(phi[21]), + lwd=lwd, lty=lty, col=col) + \} + \} + \} +\end{nwchunk} +The last arrow bit is the offset. If offset $\ne 0$ and there is a +bidirectional +arrow between two boxes, and the arc for both of them is identical, +then move each arrow just a bit, orthagonal to a segment connecting the middle +of the two boxes. +If the line goes from (x1, y1) to (x2, y2), then the normal to the line at +(x1, x2) is (y2-y1, x1-x2), normalized to length 1. +The -1 below (\code{-offset}) makes the shift obey a left-hand rule: looking +down a line segement towards the arrow head, we shift to the left. +This makes two horizontal arrows stack in the normal typographical order +for chemical reactions, the right facing one above the left facing. +A user can use a negative value for offset to reverse this if they wish. + +\begin{nwchunk} +\nwhypb{statefig-arrows3}{statefig-arrows}{statefig-arrows2}= + k <- 1 + for (j in 1:nstate) \{ + for (i in 1:nstate) \{ + if (i != j && connect[i,j] !=0) \{ + if (connect[i,j] == 2-connect[j,i] && offset!=0) \{ + #add an offset + toff <- c(cbox[j,2] - cbox[i,2], cbox[i,1] - cbox[j,1]) + toff <- -offset *toff/sqrt(sum(toff^2)) + doline(cbox[i,]+toff, cbox[j,]+toff, connect[i,j]-1, + delta1 = c(textwd[i]/2 + dx, textht[i]/2 + dy), + delta2 = c(textwd[j]/2 + dx, textht[j]/2 + dy), + lty=alty[k], lwd=alwd[k], col=acol[k]) + \} + else doline(cbox[i,], cbox[j,], connect[i,j]-1, + delta1 = c(textwd[i]/2 + dx, textht[i]/2 + dy), + delta2 = c(textwd[j]/2 + dx, textht[j]/2 + dy), + lty=alty[k], lwd=alwd[k], col=acol[k]) + k <- k +1 + \} + \} + \} +\end{nwchunk} +\section{tmerge} +The tmerge function was designed around a set of specific problems. +The idea is to build up a time dependent data set one endpoint at at time. +The primary arguments are +\begin{itemize} + \item data1: the base data set that will be added onto + \item data2: the source for new information + \item id: the subject identifier in the new data + \item \ldots: additional arguments that add variables to the data set + \item tstart, tstop: used to set the time range for each subject + \item options +\end{itemize} +The created data set has three new variables (at least), which are +\code{id}, \code{tstart} and \code{tstop}. + +The key part of the call are the ``\ldots'' arguments +which each can be one of four types: +tdc() and cumtdc() add a time dependent variable, event() and cumevent() +add a new endpoint. +In the survival routines time intervals are open on the left and +closed on the right, i.e., (tstart, tstop]. +Time dependent covariates apply from the start of an interval and events +occur at the end of an interval. +If a data set already had intervals of (0,10] and (10, 14] a new time +dependent covariate or event at time 8 would lead to three intervals of +(0,8], (8,10], and (10,14]; +the new time-dependent covariate value would be added to the second interval, +a new event would be added to the first one. + +A typical call would be +\begin{nwchunk} +\nwhypn{dummy}= + newdata <- tmerge(newdata, old, id=clinic, diabetes=tdc(diab.time)) +\end{nwchunk} +which would add a new time dependent covariate \code{diabetes} to the +data set. + +\begin{nwchunk} +\nwhypn{tmerge}= + tmerge <- function(data1, data2, id, ..., tstart, tstop, options) \{ + Call <- match.call() + # The function wants to recognize special keywords in the + # arguments, so define a set of functions which will be used to + # mark objects + new <- new.env(parent=parent.frame()) + assign("tdc", function(time, value=NULL, init=NULL) \{ + x <- list(time=time, value=value, default= init); + class(x) <- "tdc"; x\}, + envir=new) + assign("cumtdc", function(time, value=NULL, init=NULL) \{ + x <- list(time=time, value=value, default= init); + class(x) <-"cumtdc"; x\}, + envir=new) + assign("event", function(time, value=NULL, censor=NULL) \{ + x <- list(time=time, value=value, censor=censor); + class(x) <-"event"; x\}, + envir=new) + assign("cumevent", function(time, value=NULL, censor=NULL) \{ + x <- list(time=time, value=value, censor=censor); + class(x) <-"cumevent"; x\}, + envir=new) + + if (missing(data1) || missing(data2) || missing(id)) + stop("the data1, data2, and id arguments are required") + if (!inherits(data1, "data.frame")) stop("data1 must be a data frame") + \nwhypf{tmerge-setup1}{tmerge-setup}{tmerge-setup2} + \nwhypf{tmerge-addvar1}{tmerge-addvar}{tmerge-addvar2} + \nwhypf{tmerge-finish1}{tmerge-finish}{tmerge-finish2} + \} + \nwhypf{tmerge-print1}{tmerge-print}{tmerge-print2} +\end{nwchunk} + +The program can't use formulas because the \ldots arguments need to be +named. This results in a bit of evaluation magic to correctly assess +arguments. +The routine below could have been set out as a separate top-level routine, +the argument is where we want to document it: within the tmerge page or +on a separate one. +I decided on the former. +\begin{nwchunk} +\nwhyp{tmerge-setup2}{tmerge-setup}{tmerge-setup1}{tmerge-setup3}= + tmerge.control <- function(idname="id", tstartname="tstart", tstopname="tstop", + delay =0, na.rm=TRUE, tdcstart=NA_real_, ...) \{ + extras <- list(...) + if (length(extras) > 0) + stop("unrecognized option(s):", paste(names(extras), collapse=', ')) + if (length(idname) != 1 || make.names(idname) != idname) + stop("idname option must be a valid variable name") + if (!is.null(tstartname) && + (length(tstartname) !=1 || make.names(tstartname) != tstartname)) + stop("tstart option must be NULL or a valid variable name") + if (length(tstopname) != 1 || make.names(tstopname) != tstopname) + stop("tstop option must be a valid variable name") + if (length(delay) !=1 || !is.numeric(delay) || delay < 0) + stop("delay option must be a number >= 0") + if (length(na.rm) !=1 || ! is.logical(na.rm)) + stop("na.rm option must be TRUE or FALSE") + if (length(tdcstart) !=1) stop("tdcstart must be a single value") + list(idname=idname, tstartname=tstartname, tstopname=tstopname, + delay=delay, na.rm=na.rm, tdcstart=tdcstart) + \} + + if (!inherits(data1, "tmerge") && !is.null(attr(data1, "tname"))) \{ + # old style object that someone saved! + tm.retain <- list(tname = attr(data1, "tname"), + tevent= list(name=attr(data1, "tevent"), + censor= attr(data1, "tcensor")), + tdcvar = attr(data1, "tdcvar"), + n = nrow(data1)) + attr(data1, "tname") <- attr(data1, "tevent") <- NULL + attr(data1, "tcensor") <- attr(data1, "tdcvar") <- NULL + attr(data1, "tm.retain") <- tm.retain + class(data1) <- c("tmerge", class(data1)) + \} + + if (inherits(data1, "tmerge")) \{ + tm.retain <- attr(data1, "tm.retain") + firstcall <- FALSE + # check out whether the object looks legit: + # has someone tinkered with it? This won't catch everything + tname <- tm.retain$tname + tevent <- tm.retain$tevent + tdcvar <- tm.retain$tdcvar + if (nrow(data1) != tm.retain$n) + stop("tmerge object has been modified, size") + if (any(is.null(match(unlist(tname), names(data1)))) || + any(is.null(match(tm.retain$tcdname, names(data1)))) || + any(is.null(match(tevent$name, names(data1))))) + stop("tmerge object has been modified, missing variables") + for (i in seq(along=tevent$name)) \{ + ename <- tevent$name[i] + if (is.numeric(data1[[ename]])) \{ + if (!is.numeric(tevent$censor[[i]])) + stop("event variable ", ename, + " no longer matches it's original class") + \} + else if (is.character(data1[[ename]])) \{ + if (!is.character(tevent$censor[[i]])) + stop("event variable ", ename, + " no longer matches it's original class") + \} + else if (is.logical(data1[[ename]])) \{ + if (!is.logical(tevent$censor[[i]])) + stop("event variable ", ename, + " no longer matches it's original class") + \} + else if (is.factor(data1[[ename]])) \{ + if (levels(data1[[ename]])[1] != tevent$censor[[i]]) + stop("event variable ", ename, + " has a new first level") + \} + else stop("event variable ", ename, " is of an invalid class") + \} + \} else \{ + firstcall <- TRUE + tname <- tevent <- tdcvar <- NULL + if (is.name(Call[["id"]])) \{ + idx <- as.character(Call[["id"]]) + if (missing(options)) options <-list(idname= idx) + else if (is.null(options$idname)) options$idname <- idx + \} + \} + + if (!missing(options)) \{ + if (!is.list(options)) stop("options must be a list") + if (!is.null(tname)) \{ + # If an option name matches one already in tname, don't confuse + # the tmerge.control routine with duplicate arguments + temp <- match(names(options), names(tname), nomatch=0) + topt <- do.call(tmerge.control, c(options, tname[temp==0])) + if (any(temp >0)) \{ + # A variable name is changing midstream, update the + # variable names in data1 + varname <- tname[c("idname", "tstartname", "tstopname")] + temp2 <- match(varname, names(data1)) + names(data1)[temp2] <- varname + \} + \} + else topt <- do.call(tmerge.control, options) + \} + else if (length(tname)) topt <- do.call(tmerge.control, tname) + else topt <- tmerge.control() + + # id, tstart, tstop are found in data2 + if (missing(id)) stop("the id argument is required") + if (missing(data1) || missing(data2)) + stop("two data sets are required") + id <- eval(Call[["id"]], data2, enclos=emptyenv()) #don't find it elsewhere + if (is.null(id)) stop("id variable not found in data2") + if (any(is.na(id))) stop("id variable cannot have missing values") + + if (firstcall) \{ + if (!missing(tstop)) \{ + tstop <- eval(Call[["tstop"]], data2) + if (length(tstop) != length(id)) + stop("tstop and id must be the same length") + # The neardate routine will check for legal tstop data type + \} + if (!missing(tstart)) \{ + tstart <- eval(Call[["tstart"]], data2) + if (length(tstart)==1) tstart <- rep(tstart, length(id)) + if (length(tstart) != length(id)) + stop("tstart and id must be the same length") + if (any(tstart >= tstop)) + stop("tstart must be < tstop") + \} + \} + else \{ + if (!missing(tstart) || !missing(tstop)) + stop("tstart and tstop arguments only apply to the first call") + \} +\end{nwchunk} + +Get the \ldots arguments. They are evaluated in a special frame, +set up earlier, so that the definitions of the functions tdc, +cumtdc, event, and cumevent are local to tmerge. +Check that they are all legal: each argument is named, and is one of the four +allowed types. +\begin{nwchunk} +\nwhyp{tmerge-setup3}{tmerge-setup}{tmerge-setup2}{tmerge-setup4}= + # grab the... arguments + notdot <- c("data1", "data2", "id", "tstart", "tstop", "options") + dotarg <- Call[is.na(match(names(Call), notdot))] + dotarg[[1]] <- as.name("list") # The as-yet dotarg arguments + if (missing(data2)) args <- eval(dotarg, envir=new) + else args <- eval(dotarg, data2, enclos=new) + + argclass <- sapply(args, function(x) (class(x))[1]) + argname <- names(args) + if (any(argname== "")) stop("all additional argments must have a name") + + check <- match(argclass, c("tdc", "cumtdc", "event", "cumevent")) + if (any(is.na(check))) + stop(paste("argument(s)", argname[is.na(check)], + "not a recognized type")) +\end{nwchunk} + +The tcount matrix keeps track of what we have done, and is added to +the final object at the end. +This is useful to the user for debugging what may have gone right or +wrong in their usage. + +\begin{nwchunk} +\nwhyp{tmerge-setup4}{tmerge-setup}{tmerge-setup3}{tmerge-setup5}= + # The tcount matrix is useful for debugging + tcount <- matrix(0L, length(argname), 9) + dimnames(tcount) <- list(argname, c("early","late", "gap", "within", + "boundary", "leading", "trailing", + "tied", "missid")) + tcens <- tevent$censor + tevent <- tevent$name + if (is.null(tcens)) tcens <- vector('list', 0) +\end{nwchunk} + +The very first call to the routine is special, since this is when the +range of legal times is set. We also apply an initial sort to the data +if necessary so that times are in order. +There are 2 cases: +\begin{enumerate} + \item Adding a time range: tstop comes from data2, optional tstart, and the + id can be simply matched, by which we mean no duplicates in data1. + \item The more common case: there is no tstop, one observation per subject, + and the first optional argument is an + event or cumevent. We then use its time as the range. +\end{enumerate} +One thing we could add, but didn't, was to warn if any of the three new +variables will stomp on ones already in data1. + +Note that in case 2 we cannot wait for the later code to deal with duplicate +id/time pairs, since that later code requires a valid starting point. That +code will work out which of a duplicate should be retained, however. + +\begin{nwchunk} +\nwhypb{tmerge-setup5}{tmerge-setup}{tmerge-setup4}= + newdata <- data1 #make a copy + if (firstcall) \{ + # We don't look for topt$id. What if the user had id=clinic, but their + # starting data set also had a variable named "id". We want clinic for + # this first call. + idname <- Call[["id"]] + if (!is.name(idname)) + stop("on the first call 'id' must be a single variable name") + + # The line below finds tstop and tstart variables in data1 + indx <- match(c(topt$idname, topt$tstartname, topt$tstopname), names(data1), + nomatch=0) + if (any(indx[1:2]>0) && FALSE) \{ # warning currently turned off. Be chatty? + overwrite <- c(topt$tstartname, topt$tstopname)[indx[2:3]] + warning("overwriting data1 variables", paste(overwrite, collapse=' ')) + \} + + temp <- as.character(idname) + if (!is.na(match(temp, names(data1)))) \{ + data1[[topt$idname]] <- data1[[temp]] + baseid <- data1[[temp]] + \} + else stop("id variable not found in data1") + + if (any(duplicated(baseid))) + stop("for the first call (that establishes the time range) data1 must have no duplicate identifiers") + + if (missing(tstop)) \{ + if (length(argclass)==0 || argclass[1] != "event") + stop("neither a tstop argument nor an initial event argument was found") + # this is case 2 -- the first time value for each obs sets the range + last <- !duplicated(id) + indx2 <- match(unique(id[last]), baseid) + if (any(is.na(indx2))) + stop("setting the range, and data2 has id values not in data1") + if (any(is.na(match(baseid, id)))) + stop("setting the range, and data1 has id values not in data2") + newdata <- data1[indx2,] + tstop <- (args[[1]]$time)[last] + \} + else \{ + if (length(baseid)== length(id) && all(baseid == id)) newdata <- data1 + else \{ # Note: 'id' is the idlist for data 2 + indx2 <- match(id, baseid) + if (any(is.na(indx2))) + stop("setting the range, and data2 has id values not in data1") + if (any(is.na(match(baseid, id)))) + stop("setting the range, and data1 has id values not in data2") + newdata <- data1[indx2,] + \} + \} + + if (any(is.na(tstop))) + stop("missing time value, when that variable defines the span") + if (missing(tstart)) \{ + indx <- which(tstop <=0) + if (length(indx) >0) stop("found an ending time of ", tstop[indx[1]], + ", the default starting time of 0 is invalid") + tstart <- rep(0, length(tstop)) + \} + if (any(tstart >= tstop)) + stop("tstart must be < tstop") + newdata[[topt$tstartname]] <- tstart + newdata[[topt$tstopname]] <- tstop + n <- nrow(newdata) + if (any(duplicated(id))) \{ + # sort by time within id + indx1 <- match(id, unique(id)) + newdata <- newdata[order(indx1, tstop),] + \} + temp <- newdata[[topt$idname]] + if (any(tstart >= tstop)) stop("tstart must be < tstop") + if (any(newdata$tstop[-n] > newdata$tstart[-1] & + temp[-n] == temp[-1])) + stop("first call has created overlapping or duplicated time intervals") + idmiss <- 0 # the tcount table should have a zero + \} + else \{ #not a first call + idmatch <- match(id, data1[[topt$idname]], nomatch=0) + if (any(idmatch==0)) idmiss <- sum(idmatch==0) + else idmiss <- 0 + \} +\end{nwchunk} + +Now for the real work. For each additional argument we first match the +id/time pairs of the new data to the current data set, and categorize +each into a type. If the time value in data2 is NA, then that +addition is skipped. Ditto if the value is NA and options narm=TRUE. +This is a convenience for the user, who will often +be merging in a variable like ``day of first diabetes diagnosis'' which +is missing for those who never had that outcome occur. +\begin{nwchunk} +\nwhypb{tmerge-addvar2}{tmerge-addvar}{tmerge-addvar1}= + saveid <- id + for (ii in seq(along.with=args)) \{ + argi <- args[[ii]] + baseid <- newdata[[topt$idname]] + dstart <- newdata[[topt$tstartname]] + dstop <- newdata[[topt$tstopname]] + argcen <- argi$censor + + # if an event time is missing then skip that obs. Also toss obs that + # whose id does not match anyone in data1 + etime <- argi$time + if (idmiss ==0) keep <- rep(TRUE, length(etime)) + else keep <- (idmatch > 0) + if (length(etime) != length(saveid)) + stop("argument ", argname[ii], " is not the same length as id") + if (!is.null(argi$value)) \{ + if (length(argi$value) != length(saveid)) + stop("argument ", argname[ii], " is not the same length as id") + if (topt$na.rm) keep <- keep & !(is.na(etime) | is.na(argi$value)) + else keep <- keep & !is.na(etime) + if (!all(keep)) \{ + etime <- etime[keep] + argi$value <- argi$value[keep] + \} + \} + else \{ + keep <- keep & !is.na(etime) + etime <- etime[keep] + \} + id <- saveid[keep] + + # Later steps become easier if we sort the new data by id and time + # The match() is critical when baseid is not in sorted order. The + # etime part of the sort will change from one ii value to the next. + indx <- order(match(id, baseid), etime) + id <- id[indx] + etime <- etime[indx] + if (!is.null(argi$value)) + yinc <- argi$value[indx] + else yinc <- NULL + + # indx1 points to the closest start time in the baseline data (data1) + # that is <= etime. indx2 to the closest end time that is >=etime. + # If etime falls into a (tstart, tstop) interval, indx1 and indx2 + # will match + # If the "delay" argument is set and this event is of type tdc, then + # move any etime that is after the entry time for a subject. + if (topt$delay >0 && argclass[ii] %in% c("tdc", "cumtdc")) \{ + mintime <- tapply(dstart, baseid, min) + index <- match(id, names(mintime)) + etime <- ifelse(etime <= mintime[index], etime, etime+ topt$delay) + \} + + indx1 <- neardate(id, baseid, etime, dstart, best="prior") + indx2 <- neardate(id, baseid, etime, dstop, best="after") + + # The event times fall into one of 5 categories + # 1. Before the first interval + # 2. After the last interval + # 3. Outside any interval but with time span, i.e, it falls into + # a gap in follow-up + # 4. Strictly inside an interval (does't touch either end) + # 5. Inside an interval, but touching. + itype <- ifelse(is.na(indx1), 1, + ifelse(is.na(indx2), 2, + ifelse(indx2 > indx1, 3, + ifelse(etime== dstart[indx1] | + etime== dstop[indx2], 5, 4)))) + + # Subdivide the events that touch on a boundary + # 1: intervals of (a,b] (b,d], new count at b "tied edge" + # 2: intervals of (a,b] (c,d] with c>b, new count at c, "front edge" + # 3: intervals of (a,b] (c,d] with c>b, new count at b, "back edge" + # + subtype <- ifelse(itype!=5, 0, + ifelse(indx1 == indx2+1, 1, + ifelse(etime==dstart[indx1], 2, 3))) + tcount[ii,1:7] <- table(factor(itype+subtype, levels=c(1:4, 6:8))) + + # count ties. id and etime are not necessarily sorted + tcount[ii,8] <- sum(tapply(etime, id, function(x) sum(duplicated(x)))) + tcount[ii,9] <- idmiss + \nwhypf{tmerge-addin21}{tmerge-addin2}{tmerge-addin22} + \} +\end{nwchunk} + +A \code{tdc} or \code{cumtdc} operator defines a new time-dependent +variable which applies to all future times. +Say that we had the following scenario for one subject +\begin{center} + \begin{tabular}{rr|rr} + \multicolumn{2}{c}{current} & \multicolumn{2}{c}{addition} \\ + tstart & tstop & time & x \\ + 2 & 5 & 1 & 20.2 \\ + 6 & 7 & 7 & 11 \\ + 7 & 15 & 8 & 17.3 \\ + 15 & 30 \\ + \end{tabular} + \end{center} +The resulting data set will have intervals of (2,5), (6,7), (7,8) and (8,15) +with covariate values of 20.2, 20.2, 11, and 17.3. +Only a covariate change that occurs within an interval causes a new data +row. Covariate changes that happen after the last interval are ignored, +i.e. at change at time $\ge 30$ in the above example. + +If instead this had been events at times 1, 7, and 8, the first event would +be ignored since it happens outside of any interval, so would an event +at exactly time 2. The event at time +7 would be recorded in the (6,7) interval and the one at time 8 in the +(7,8) interval: events happen at the ends of intervals. +In both cases new rows are only generated for new time values that fall +strictly within one of the old intervals. + +When a subject has two increments on the same day the later one wins. +This is correct behavior for cumtdc, a bit odd for cumevent, and the +user's problem for tdc and event. +We report back the number of ties so that the user can deal with it. + +Where are we now with the variables? +\begin{center} + \begin{tabular}{cccc} + itype& class & indx1 & indx2 \\ \hline + 1 & before & NA & next interval \\ + 2 & after & prior interval & NA \\ + 3 & in a gap & prior interval & next interval \\ + 4 & within interval & containing interval & containing interval \\ + 5-1 & on a join & next interval & prior interval \\ + 5-2 & front edge & containing & containing \\ + 5-3 & back edge & containing & containing \\ + \end{tabular} +\end{center} +If there are any itype 4, start by expanding the data set to add +new cut points, which will turn all the 4's into 5-1 types. +When expanding, all the event type variables turn into ``censor'' at the +newly added times and other variables stay the same. +A subject could have more than one new cutpoint added within an interval +so we have to count each. +In newdata all the rows for a given subject are contiguous and in time +order, though the data set may not be in subject order. +\begin{nwchunk} +\nwhyp{tmerge-addin22}{tmerge-addin2}{tmerge-addin21}{tmerge-addin23}= + indx4 <- which(itype==4) + n4 <- length(indx4) + if (n4 > 0) \{ + # we need to eliminate duplicate times within the same id, but + # do so without changing the class of etime: it might + # be a Date, an integer, a double, ... + # Using unique on a data.frame does the trick + icount <- data.frame(irow= indx1[indx4], etime=etime[indx4]) + icount <- unique(icount) + # the icount data frame will be sorted by second column within first + # so rle is faster than table + n.add <- rle(icount$irow)$length # number of rows to add for each id + + # expand the data + irep <- rep.int(1L, nrow(newdata)) + erow <- unique(indx1[indx4]) # which rows in newdata to be expanded + irep[erow] <- 1+ n.add # number of rows in new data + jrep <- rep(1:nrow(newdata), irep) #stutter the duplicated rows + newdata <- newdata[jrep,] #expand it out + dstart <- dstart[jrep] + dstop <- dstop[jrep] + + #fix up times + nfix <- length(erow) + temp <- vector("list", nfix) + iend <- (cumsum(irep))[irep >1] #end row of each duplication set + for (j in 1:nfix) temp[[j]] <- -(seq(n.add[j] -1, 0)) + iend[j] + newrows <- unlist(temp) + + dstart[newrows] <- dstop[newrows-1] <- icount$etime + newdata[[topt$tstartname]] <- dstart + newdata[[topt$tstopname]] <- dstop + for (ename in tevent) newdata[newrows-1, ename] <- tcens[[ename]] + + # refresh indices + baseid <- newdata[[topt$idname]] + indx1 <- neardate(id, baseid, etime, dstart, best="prior") + indx2 <- neardate(id, baseid, etime, dstop, best="after") + subtype[itype==4] <- 1 #all the "insides" are now on a tied edge + itype[itype==4] <- 5 + \} +\end{nwchunk} + +Now we can add the new variable. +The most common is a tdc, so start with it. +The C routine returns a set of indices: 0,1,1,2,3,0,4,... would mean that +row 1 of the new data happens before the tdc variable, 2 and 3 take values from +the first element of yinc, etc. +By returning an index, the yinc variable can be of any data type. Using +is.na() on the left side below causes the \emph{right} kind of NA to be inserted +(this trick was stolen from the merge routine). + +If this is a first call, don't allow the new variable to overwrite a variable +already existing in the data set, we found it leads to problems. (Usually it +is a user mistake.) However, tdc calls themselves can stack. + +\begin{nwchunk} +\nwhyp{tmerge-addin23}{tmerge-addin2}{tmerge-addin22}{tmerge-addin24}= + # add a tdc variable + newvar <- newdata[[argname[ii]]] # prior value (for sequential tmerge calls) + if (argclass[ii] %in% c("tdc", "cumtdc"))\{ + if (argname[[ii]] %in% tevent) + stop("attempt to turn event variable", argname[[ii]], "into a tdc") + if (!(argname[[ii]] %in% tdcvar))\{ + tdcvar <- c(tdcvar, argname[[ii]]) + if (!is.null(newvar) && argclass[ii] == "tdc") \{ + warning(paste0("replacement of variable '", argname[ii], "'")) + newvar <- NULL + \} + \} + \} + if (argclass[ii] == "tdc") \{ + default <- argi$default # default value + if (is.null(default)) default <- topt$tdcstart + else if (length(default) !=1) + stop("initial tdc value must be of length 1") + + # id can be any data type; feed integers to the C routine + storage.mode(dstart) <- storage.mode(etime) <- "double" #if time is integer + uid <- unique(baseid) + index <- .Call(Ctmerge2, match(baseid, uid), dstart, + match(id, uid), etime) + + if (!is.null(yinc)) newvar <- NULL # a tdc can't be updated, other than 0/1 + if (is.null(newvar)) \{ + if (is.null(yinc)) newvar <- ifelse(index==0, 0L, 1L) #add a 0/1 variable + else \{ + newvar <- yinc[pmax(1L, index)] + if (any(index==0)) \{ + if (is.na(default)) is.na(newvar) <- (index==0L) + else \{ + if (is.numeric(newvar)) newvar[index==0L] <- as.numeric(default) + else \{ + if (is.factor(newvar)) \{ + # special case: if default isn't in the set of levels, + # add it to the levels + if (is.na(match(default, levels(newvar)))) + levels(newvar) <- c(levels(newvar), default) + \} + newvar[index== 0L] <- default + \} + \} + \} + \} + \} else \{ + # update a 0/1 variable + if (is.integer(newvar) && all(newvar==0L | newvar==1L)) + newvar[index!=0L] <- 1L + else stop("tdc update does not match prior variable type: ", argname[ii]) + \} + tdcvar <- unique(c(tdcvar, argname[[ii]])) + \} +\end{nwchunk} + +Events and cumevents are easy because +each affects only one interval. +\begin{nwchunk} +\nwhypb{tmerge-addin24}{tmerge-addin2}{tmerge-addin23}= + # add events + if (argclass[ii] %in% c("cumtdc", "cumevent")) \{ + if (is.null(yinc)) yinc <- rep(1L, length(id)) + else if (is.logical(yinc)) yinc <- as.numeric(yinc) # allow cumulative T/F + if (!is.numeric(yinc)) stop("invalid increment for cumtdc or cumevent") + \} + if (argclass[ii] == "cumevent")\{ + ykeep <- (yinc !=0) # ignore the addition of a censoring event + yinc <- unlist(tapply(yinc, match(id, baseid), cumsum)) + \} + + if (argclass[ii] %in% c("event", "cumevent")) \{ + if (!is.null(newvar)) \{ + if (!argname[ii] %in% tevent) \{ + #warning(paste0("non-event variable '", argname[ii], "' replaced by an event variable")) + newvar <- NULL + \} + else if (!is.null(yinc)) \{ + if (class(newvar) != class(yinc)) + stop("attempt to update an event variable with a different type") + if (is.factor(newvar) && !all(levels(yinc) %in% levels(newvar))) + stop("attemp to update an event variable and levels do not match") + \} + \} + + if (is.null(yinc)) yinc <- rep(1L, length(id)) + if (is.null(newvar)) \{ + if (is.numeric(yinc)) newvar <- rep(0L, nrow(newdata)) + else if (is.factor(yinc)) + newvar <- factor(rep(levels(yinc)[1], nrow(newdata)), + levels(yinc)) + else if (is.character(yinc)) newvar <- rep('', nrow(newdata)) + else if (is.logical(yinc)) newvar <- rep(FALSE, nrow(newdata)) + else stop("invalid value for a status variable") + \} + + keep <- (subtype==1 | subtype==3) # all other events are thrown away + if (argclass[ii] == "cumevent") keep <- (keep & ykeep) + newvar[indx2[keep]] <- yinc[keep] + + # add this into our list of 'this is an event type variable' + if (!(argname[ii] %in% tevent)) \{ + tevent <- c(tevent, argname[[ii]]) + if (is.factor(yinc)) tcens <- c(tcens, list(levels(yinc)[1])) + else if (is.logical(yinc)) tcens <- c(tcens, list(FALSE)) + else if (is.character(yinc)) tcens <- c(tcens, list("")) + else if (is.integer(yinc)) tcens <- c(tcens, list(0L)) + else tcens <- c(tcens, list(0)) + names(tcens) <- tevent + \} + \} + + else if (argclass[ii] == "cumtdc") \{ # process a cumtdc variable + # I don't have a good way to catch the reverse of this user error + if (argname[[ii]] %in% tevent) + stop("attempt to turn event variable", argname[[ii]], "into a cumtdc") + + keep <- itype != 2 # changes after the last interval are ignored + indx <- ifelse(subtype==1, indx1, + ifelse(subtype==3, indx2+1L, indx2)) + + # we want to pass the right kind of NA to the C code + default <- argi$default + if (is.null(default)) default <- as.numeric(topt$tdcstart) + else \{ + if (length(default) != 1) stop("tdc initial value must be of length 1") + if (!is.numeric(default)) stop("cumtdc initial value must be numeric") + \} + if (is.null(newvar)) \{ # not overwriting a prior value + if (is.null(argi$value)) newvar <- rep(0.0, nrow(newdata)) + else newvar <- rep(default, nrow(newdata)) + \} + + # the increment must be numeric + if (!is.numeric(newvar)) + stop("data and starting value do not agree on data type") + # id can be any data type; feed integers to the C routine + storage.mode(yinc) <- storage.mode(dstart) <- "double" + storage.mode(newvar) <- storage.mode(etime) <- "double" + newvar <- .Call(Ctmerge, match(baseid, baseid), dstart, newvar, + match(id, baseid)[keep], etime[keep], + yinc[keep], indx[keep]) + \} + + newdata[[argname[ii]]] <- newvar +\end{nwchunk} + +Finish up by adding the attributes and the class +\begin{nwchunk} +\nwhypb{tmerge-finish2}{tmerge-finish}{tmerge-finish1}= + tm.retain <- list(tname = topt[c("idname", "tstartname", "tstopname")], + n= nrow(newdata)) + if (length(tevent)) + tm.retain$tevent <- list(name = tevent, censor=tcens) + if (length(tdcvar)>0) tm.retain$tdcvar <- tdcvar + attr(newdata, "tm.retain") <- tm.retain + attr(newdata, "tcount") <- rbind(attr(data1, "tcount"), tcount) + attr(newdata, "call") <- Call + + row.names(newdata) <- NULL #These are a mess; kill them off. + # Not that it works: R just assigns new row names. + class(newdata) <- c("tmerge", "data.frame") + newdata +\end{nwchunk} + +The summary routine is for checking: it simply prints out the attributes. +\begin{nwchunk} +\nwhypb{tmerge-print2}{tmerge-print}{tmerge-print1}= + summary.tmerge <- function(object, ...) \{ + if (!is.null(cl <- attr(object, "call"))) \{ + cat("Call:{\textbackslash}n") + dput(cl) + cat("{\textbackslash}n") + \} + + print(attr(object, "tcount")) + \} + + # This could be smarter: if you only drop variables that are not known + # to tmerge then it would be okay. But I currently like the "touch it + # and it dies" philosophy + "[.tmerge" <- function(x, ..., drop=TRUE)\{ + class(x) <- "data.frame" + attr(x, "tm.retain") <- NULL + attr(x, "tcount") <- NULL + attr(x, "call") <- NULL + NextMethod(x) + \} +\end{nwchunk} +\section{Linear models and contrasts} +The primary contrast function is \code{yates}. +This function does both simple and population contrasts; the name is a nod +to the ``Yates weighted means'' method, the first population contrast that +I know of. +A second reason for the name is that +the word ``contrast'' is already overused in the S/R lexicon. +Both \code{yates} and \code{cmatrix} can be used with any model that returns +the necessary +portions, e.g., lm, coxph, or glm. +They were written because I became embroiled in the ``type III'' controversy, +and made it a goal to figure out what exactly it is that SAS does. +If I had known that that quest would take multiple years would +perhaps have never started. + +Population contrasts can result in some head scratching. +It is easy to create the predicted value for any hypothethical +subject from a model. +A population prediction holds some data values constant and lets the +others range over a population, giving a mean predicted value or +population average. +Population predictions for two treatments are the familiar g-estimates +of causal models. +We can take sums or differences of these predictions as well, e.g. to +ask if they are significantly different. +What can't be done is to work backwards from one of these contrasts to the +populations, at least for continuous variables. +If someone asks for an x contrast of 15-5 is this a sum of two population +estimates at 15 and -5, or a difference? +It's always hard to guess the mind of a user. +Therefore what is needed is a fitted model, the term (covariate) of interest, +levels of that covariate, a desired comparison, and a population. + +First is cmatrix routine. This is called by users to create a contrast +matrix for a model, users can also construct their own contrast matrices. +The result has two parts: the definition of a set of predicted values and +a set of contrasts between those values. +The routine requires a fit and a formula. The formula is simply a way to +get a set of variable names: all those variables are the fixed ones in +the population contrast, and all others form the ``population''. +The result will be a matrix or list that has a label +attribute containing the name of the term; this is used in printouts in the +obvious way. +Suppose that our model was \code{coxph(Surv(time, status) ~ age*sex + ph.ecog)}. +Someone might want the population matrix for age, sex, ph.ecog, or age+ sex. +For the last it doesn't matter if they say age+sex, age*sex, or age:sex. + +\begin{nwchunk} +\nwhypf{yates1}{yates}{yates2}= + cmatrix <- function(fit, term, + test =c("global", "trend", "pairwise", "mean"), + levels, assign) \{ + # Make sure that "fit" is present and isn't missing any parts. + if (missing(fit)) stop("a fit argument is required") + Terms <- try(terms(fit), silent=TRUE) + + if (inherits(Terms, "try-error")) + stop("the fit does not have a terms structure") + else Terms <- delete.response(Terms) # y is not needed + Tatt <- attributes(Terms) + # a flaw in delete.response: it doesn't subset dataClasses + Tatt$dataClasses <- Tatt$dataClasses[row.names(Tatt$factors)] + test <- match.arg(test) + + if (missing(term)) stop("a term argument is required") + if (is.character(term)) term <- formula(paste("~", term)) + else if (is.numeric(term)) \{ + if (all(term == floor(term) & term >0 & term < length(Tatt$term.labels))) + term <- formula(paste("~", + paste(Tatt$term.labels[term], collapse='+'))) + else stop("a numeric term must be an integer between 1 and max terms in the fit") + \} + else if (!inherits(term, "formula")) + stop("the term must be a formula or integer") + fterm <- delete.response(terms(term)) + fatt <- attributes(fterm) + user.name <- fatt$term.labels # what the user called it + termname <- all.vars(fatt$variables) + indx <- match(termname, all.vars(Tatt$variables)) + if (any(is.na(indx))) + stop("variable ", termname[is.na(indx)], " not found in the formula") + + # What kind of term is being tested? It can be categorical, continuous, + # an interaction of only categorical terms, interaction of only continuous + # terms, or a mixed interaction. + # Key is a trick to get "zed" from ns(zed, df= dfvar) + key <- sapply(Tatt$variables[-1], function(x) all.vars(x)[1]) + parts <- names(Tatt$dataClasses)[match(termname, key)] + types <- Tatt$dataClasses[parts] + iscat <- as.integer(types=="factor" | types=="character") + if (length(iscat)==1) termtype <- iscat + else termtype <- 2 + any(iscat) + all(iscat) + + # Were levels specified? If so we either simply accept them (continuous), + # or double check them (categorical) + if (missing(levels)) \{ + temp <- fit$xlevels[match(parts, names(fit$xlevels), nomatch=0)] + if (length(temp) < length(parts)) + stop("continuous variables require the levels argument") + levels <- do.call(expand.grid, c(temp, stringsAsFactors=FALSE)) + \} + else \{ #user supplied + if (is.list(levels)) \{ + if (is.null(names(levels))) \{ + if (length(termname)==1) names(levels)== termname + else stop("levels list requires named elements") + \} + \} + if (is.data.frame(levels) || is.list(levels)) \{ + index1 <- match(termname, names(levels), nomatch=0) + # Grab the cols from levels that are needed (we allow it to have + # extra, unused columns) + levels <- as.list(levels[index1]) + # now, levels = the set of ones that the user supplied (which might + # be none, if names were wrong) + if (length(levels) < length(termname)) \{ + # add on the ones we don't have, using fit$xlevels as defaults + temp <- fit$xlevels[parts[index1==0]] + if (length(temp) > 0) \{ + names(temp) <- termname[index1 ==0] + levels <- c(levels, temp) + \} + \} + index2 <- match(termname, names(levels), nomatch=0) + if (any(index2==0)) + stop("levels information not found for: ", termname[index2==0]) + levels <- expand.grid(levels[index2], stringsAsFactors=FALSE) + if (any(duplicated(levels))) stop("levels data frame has duplicates") + \} + else if (is.matrix(levels)) \{ + if (ncol(levels) != length(parts)) + stop("levels matrix has the wrong number of columns") + if (!is.null(dimnames(levels)[[2]])) \{ + index <- match(termname, dimnames(levels)[[2]], nomatch=0) + if (index==0) + stop("matrix column names do no match the variable list") + else levels <- levels[,index, drop=FALSE] + \} else if (ncol(levels) > 1) + stop("multicolumn levels matrix requires column names") + if (any(duplicated(levels))) + stop("levels matrix has duplicated rows") + levels <- data.frame(levels, stringsAsFactors=FALSE) + names(levels) <- termname + \} + else if (length(parts) > 1) + stop("levels should be a data frame or matrix") + else \{ + levels <- data.frame(x=unique(levels), stringsAsFactors=FALSE) + names(levels) <- termname + \} + \} + + # check that any categorical levels are legal + for (i in which(iscat==1)) \{ + xlev <- fit$xlevels[[parts[i]]] + if (is.null(xlev)) + stop("xlevels attribute not found for", termname[i]) + temp <- match(levels[[i]], xlev) + if (any(is.na(temp))) + stop("invalid level for term", termname[i]) + \} + + rval <- list(levels=levels, termname=termname) + # Now add the contrast matrix between the levels, if needed + if (test=="global") \{ + \nwhypf{cmatrix-build-default1}{cmatrix-build-default}{cmatrix-build-default2} + \} + else if (test=="pairwise") \{ + \nwhypf{cmatrix-build-pairwise1}{cmatrix-build-pairwise}{cmatrix-build-pairwise2} + \} + else if (test=="mean") \{ + \nwhypf{cmatrix-build-mean1}{cmatrix-build-mean}{cmatrix-build-mean2} + \} + else \{ + \nwhypf{cmatrix-build-linear1}{cmatrix-build-linear}{cmatrix-build-linear2} + \} + # the user can say "age" when the model has "ns(age)", but we need + # the more formal label going forward + rval <- list(levels=levels, termname=parts, cmat=cmat, iscat=iscat) + class(rval) <- "cmatrix" + rval + \} +\end{nwchunk} + +The default contrast matrix is a simple test of equality if there is only +one term. +If the term is the interaction of multiple categorical variables +then we do an anova type decomposition. +In other cases we currently fail. +\begin{nwchunk} +\nwhypb{cmatrix-build-default2}{cmatrix-build-default}{cmatrix-build-default1}= + if (TRUE) \{ + #if (length(parts) ==1) \{ + cmat <- diag(nrow(levels)) + cmat[, nrow(cmat)] <- -1 # all equal to the last + cmat <- cmat[-nrow(cmat),, drop=FALSE] + \} + else if (termtype== 4) \{ # anova type + stop("not yet done 1") + \} + else stop("not yet done 2") +\end{nwchunk} + + +The \code{pairwise} option creates a set of contrast matrices for all pairs +of a factor. + +\begin{nwchunk} +\nwhypb{cmatrix-build-pairwise2}{cmatrix-build-pairwise}{cmatrix-build-pairwise1}= + nlev <- nrow(levels) # this is the number of groups being compared + if (nlev < 2) stop("pairwise tests need at least 2 groups") + npair <- nlev*(nlev-1)/2 + if (npair==1) cmat <- matrix(c(1, -1), nrow=1) + else \{ + cmat <- vector("list", npair) + k <- 1 + cname <- rep("", npair) + for (i in 1:(nlev-1)) \{ + temp <- double(nlev) + temp[i] <- 1 + for (j in (i+1):nlev) \{ + temp[j] <- -1 + cmat[[k]] <- matrix(temp, nrow=1) + temp[j] <- 0 + cname[k] <- paste(i, "vs", j) + k <- k+1 + \} + \} + names(cmat) <- cname + \} +\end{nwchunk} + +The mean option compares each to the overall mean. +\begin{nwchunk} +\nwhypb{cmatrix-build-mean2}{cmatrix-build-mean}{cmatrix-build-mean1}= + ntest <- nrow(levels) + cmat <- vector("list", ntest) + for (k in 1:ntest) \{ + temp <- rep(-1/ntest, ntest) + temp[k] <- (ntest-1)/ntest + cmat[[k]] <- matrix(temp, nrow=1) + \} + names(cmat) <- paste(1:ntest, "vs mean") +\end{nwchunk} + +The \code{linear} option is of interest for terms that have more than one +column; the two most common cases are a factor variable or a spline. +It forms a pair of tests, one for the linear and one +for the nonlinear part. For non-linear functions such as splines we need +some notion of the range of the data, since we want to be linear over the +entire range. + +\begin{nwchunk} +\nwhypb{cmatrix-build-linear2}{cmatrix-build-linear}{cmatrix-build-linear1}= + cmat <- vector("list", 2) + cmat[[1]] <- matrix(1:ntest, 1, ntest) + cmat[[2]] <- diag(ntest) + attr(cmat, "nested") <- TRUE + if (is.null(levels[[1]])) \{ + # a continuous variable, and the user didn't give levels for the test + # look up the call and use the knots + tcall <- Tatt$predvars[[indx + 1]] # skip the 'call' + if (tcall[[1]] == as.name("pspline")) \{ + bb <- tcall[["Boundary.knots"]] + levels[[1]] <- seq(bb[1], bb[2], length=ntest) + \} + else if (tcall[[1]] %in% c("ns", "bs")) \{ + bb <- c(tcall[["Boundary.knots"]], tcall[["knots"]]) + levels[[1]] <- sort(bb) + \} + else stop("don't know how to do a linear contrast for this term") + \} +\end{nwchunk} + + +Here are some helper routines. +Formulas are from chapter 5 of Searle. The sums of squares only makes +sense within a linear model. +\begin{nwchunk} +\nwhyp{yates2}{yates}{yates1}{yates3}= + gsolve <- function(mat, y, eps=sqrt(.Machine$double.eps)) \{ + # solve using a generalized inverse + # this is very similar to the ginv function of MASS + temp <- svd(mat, nv=0) + dpos <- (temp$d > max(temp$d[1]*eps, 0)) + dd <- ifelse(dpos, 1/temp$d, 0) + # all the parentheses save a tiny bit of time if y is a vector + if (all(dpos)) x <- drop(temp$u %*% (dd*(t(temp$u) %*% y))) + else if (!any(dpos)) x <- drop(temp$y %*% (0*y)) # extremely rare + else x <-drop(temp$u[,dpos] %*%(dd[dpos] * (t(temp$u[,dpos, drop=FALSE]) %*% y))) + attr(x, "df") <- sum(dpos) + x + \} + + qform <- function(var, beta) \{ # quadratic form b' (V-inverse) b + temp <- gsolve(var, beta) + list(test= sum(beta * temp), df=attr(temp, "df")) + \} +\end{nwchunk} + +The next functions do the work. Some bookkeeping is needed for +a missing value in beta: we leave that coefficient out of the linear +predictor. +If there are missing coefs then the variance matrix will not have those +columns in any case. +The nafun function asks if a linear combination is NA. It treats +0*NA as 0. + +\begin{nwchunk} +\nwhyp{yates3}{yates}{yates2}{yates4}= + estfun <- function(cmat, beta, varmat) \{ + nabeta <- is.na(beta) + if (any(nabeta)) \{ + k <- which(!nabeta) #columns to keep + estimate <- drop(cmat[,k] %*% beta[k]) # vector of predictions + evar <- cmat[,k] %*% varmat %*% t(cmat[,k, drop=FALSE]) + list(estimate = estimate, var=evar) + \} + else \{ + list(estimate = drop(cmat %*% beta), + var = cmat %*% varmat %*% t(cmat)) + \} + \} + + testfun <- function(cmat, beta, varmat, sigma2) \{ + nabeta <- is.na(beta) + if (any(nabeta)) \{ + k <- which(!nabeta) #columns to keep + estimate <- drop(cmat[,k] %*% beta[k]) # vector of predictions + temp <- qform(cmat[,k] %*% varmat %*% t(cmat[,k,drop=FALSE]), estimate) + rval <- c(chisq=temp$test, df=temp$df) + \} + else \{ + estimate <- drop(cmat %*% beta) + temp <- qform(cmat %*% varmat %*% t(cmat), estimate) + rval <- c(chisq=temp$test, df=temp$df) + \} + if (!is.null(sigma2)) rval <- c(rval, ss= unname(rval[1]) * sigma2) + rval + \} + + nafun <- function(cmat, est) \{ + used <- apply(cmat, 2, function(x) any(x != 0)) + any(used & is.na(est)) + \} +\end{nwchunk} +Now for the primary function. +The user may have a list of tests, or a single term. +The first part of the function does the usual of grabbing arguments +and then checking them. +The fit object has to have the standard stuff: terms, assign, xlevels +and contrasts. +Attributes of the terms are used often enough that we copy them +to \code{Tatt} to save typing. +We will almost certainly need the model frame and/or model matrix as +well. + +In the discussion below I use x1 to refer to the covariates/terms that are +the target, e.g. \code{test='Mask'} to get the mean population values for +each level of the Mask variable in the solder data set, and x2 to refer to +all the other terms in the model, the ones that we average over. +These are also referred to as U and V in the vignette. + +\begin{nwchunk} +\nwhyp{yates4}{yates}{yates3}{yates5}= + yates <- function(fit, term, population=c("data", "factorial", "sas"), + levels, test =c("global", "trend", "pairwise"), + predict="linear", options, nsim=200, + method=c("direct", "sgtt")) \{ + Call <- match.call() + if (missing(fit)) stop("a fit argument is required") + Terms <- try(terms(fit), silent=TRUE) + if (inherits(Terms, "try-error")) + stop("the fit does not have a terms structure") + else Terms <- delete.response(Terms) # y is not needed + Tatt <- attributes(Terms) + # a flaw in delete.response: it doesn't subset dataClasses + Tatt$dataClasses <- Tatt$dataClasses[row.names(Tatt$factors)] + + if (inherits(fit, "coxphms")) stop("multi-state coxph not yet supported") + if (is.list(predict) || is.function(predict)) \{ + # someone supplied their own + stop("user written prediction functions are not yet supported") + \} + else \{ # call the method + indx <- match(c("fit", "predict", "options"), names(Call), nomatch=0) + temp <- Call[c(1, indx)] + temp[[1]] <- quote(yates_setup) + mfun <- eval(temp, parent.frame()) + \} + if (is.null(mfun)) predict <- "linear" + + # we will need the original model frame and X matrix + mframe <- fit$model + if (is.null(mframe)) mframe <- model.frame(fit) + Xold <- model.matrix(fit) + if (is.null(fit$assign)) \{ # glm models don't save assign + xassign <- attr(Xold, "assign") + \} + else xassign <- fit$assign + + + nvar <- length(xassign) + nterm <- length(Tatt$term.names) + termname <- rownames(Tatt$factors) + iscat <- sapply(Tatt$dataClasses, + function(x) x %in% c("character", "factor")) + + method <- match.arg(casefold(method), c("direct", "sgtt")) #allow SGTT + if (method=="sgtt" && missing(population)) population <- "sas" + + if (inherits(population, "data.frame")) popframe <- TRUE + else if (is.character(population)) \{ + popframe <- FALSE + population <- match.arg(tolower(population[1]), + c("data", "factorial", "sas", + "empirical", "yates")) + if (population=="empirical") population <- "data" + if (population=="yates") population <- "factorial" + \} + else stop("the population argument must be a data frame or character") + test <- match.arg(test) + + if (popframe || population != "data") weight <- NULL + else \{ + weight <- model.extract(mframe, "weights") + if (is.null(weight)) \{ + id <- model.extract(mframe, "id") + if (!is.null(id)) \{ # each id gets the same weight + count <- c(table(id)) + weight <- 1/count[match(id, names(count))] + \} + \} + \} + + if (method=="sgtt" && (population !="sas" || predict != "linear")) + stop("sgtt method only applies if population = sas and predict = linear") + + beta <- coef(fit, complete=TRUE) + nabeta <- is.na(beta) # undetermined coefficients + vmat <- vcov(fit, complete=FALSE) + if (nrow(vmat) > sum(!nabeta)) \{ + # a vcov method that does not obey the complete argument + vmat <- vmat[!nabeta, !nabeta] + \} + + # grab the dispersion, needed for the writing an SS in linear models + if (class(fit)[1] =="lm") sigma <- summary(fit)$sigma + else sigma <- NULL # don't compute an SS column + + # process the term argument and check its legality + if (missing(levels)) + contr <- cmatrix(fit, term, test, assign= xassign) + else contr <- cmatrix(fit, term, test, assign= xassign, levels = levels) + x1data <- as.data.frame(contr$levels) # labels for the PMM values + + # Make the list of X matrices that drive everything: xmatlist + # (Over 1/2 the work of the whole routine) + xmatlist <- yates_xmat(Terms, Tatt, contr, population, mframe, fit, + iscat) + + # check rows of xmat for estimability + \nwhypf{yates-estim-setup1}{yates-estim-setup}{yates-estim-setup2} + + # Drop missing coefficients, and use xmatlist to compute the results + beta <- beta[!nabeta] + if (predict == "linear" || is.null(mfun)) \{ + # population averages of the simple linear predictor + \nwhypf{yates-linear1}{yates-linear}{yates-linear2} + \} + else \{ + \nwhypf{yates-nonlinear1}{yates-nonlinear}{yates-nonlinear2} + \} + result$call <- Call + class(result) <- "yates" + result + \} +\end{nwchunk} + +Models with factor variables may often lead to population predictions that +involve non-estimable functions, particularly if there are interactions +and the user specifies a factorial population. +If there are any missing coefficients we have to do formal checking for +this: any given row of the new $X$ matrix, for prediction, must be in the +row space of the original $X$ matrix. +If this is true then a regression of a new row on the old $X$ will have +residuals of zero. +It is not possible to derive this from the pattern of NA coefficients alone. +Set up a function that returns a true/false vector of whether each row of +a matrix is estimable. This test isn't relevant if population=none. + + +\begin{nwchunk} +\nwhypb{yates-estim-setup2}{yates-estim-setup}{yates-estim-setup1}= + if (any(is.na(beta)) && (popframe || population != "none")) \{ + Xu <- unique(Xold) # we only need unique rows, saves time to do so + if (inherits(fit, "coxph")) X.qr <- qr(t(cbind(1.0,Xu))) + else X.qr <- qr(t(Xu)) # QR decomposition of the row space + estimcheck <- function(x, eps= sqrt(.Machine$double.eps)) \{ + temp <- abs(qr.resid(X.qr, t(x))) + # apply(abs(temp), 1, function(x) all(x < eps)) # each row estimable + all(temp < eps) + \} + estimable <- sapply(xmatlist, estimcheck) + \} else estimable <- rep(TRUE, length(xmatlist)) +\end{nwchunk} + +When the prediction target is $X\beta$ there is a four step +process: build the reference population, create the list of X matrices +(one prediction matrix for each for x1 value), +column means of each X form each row of the +contrast matrix Cmat, and then use Cmat to get the pmm values and +tests of the pmm values. + +\begin{nwchunk} +\nwhypb{yates-linear2}{yates-linear}{yates-linear1}= + temp <- match(contr$termname, colnames(Tatt$factors)) + if (any(is.na(temp))) + stop("term '", contr$termname[is.na(temp)], "' not found in the model") + + meanfun <- if (is.null(weight)) colMeans else function(x) \{ + colSums(x*weight)/ sum(weight)\} + Cmat <- t(sapply(xmatlist, meanfun))[,!nabeta] + + # coxph model: the X matrix is built as though an intercept were there (the + # baseline hazard plays that role), but then drop it from the coefficients + # before computing estimates and tests. + if (inherits(fit, "coxph")) \{ + Cmat <- Cmat[,-1, drop=FALSE] + offset <- -sum(fit$means[!nabeta] * beta) # recenter the predictions too + \} + else offset <- 0 + + # Get the PMM estimates, but only for estimable ones + estimate <- cbind(x1data, pmm=NA, std=NA) + if (any(estimable)) \{ + etemp <- estfun(Cmat[estimable,,drop=FALSE], beta, vmat) + estimate$pmm[estimable] <- etemp$estimate + offset + estimate$std[estimable] <- sqrt(diag(etemp$var)) + \} + + # Now do tests on the PMM estimates, one by one + if (method=="sgtt") \{ + \nwhypf{yates-sgtt1}{yates-sgtt}{yates-sgtt2} + \} + else \{ + if (is.list(contr$cmat)) \{ + test <- t(sapply(contr$cmat, function(x) + testfun(x %*% Cmat, beta, vmat, sigma^2))) + natest <- sapply(contr$cmat, nafun, estimate$pmm) + \} + else \{ + test <- testfun(contr$cmat %*% Cmat, beta, vmat, sigma^2) + test <- matrix(test, nrow=1, + dimnames=list("global", names(test))) + natest <- nafun(contr$cmat, estimate$pmm) + \} + if (any(natest)) test[natest,] <- NA + \} + if (any(estimable))\{ + # Cmat[!estimable,] <- NA + result <- list(estimate=estimate, test=test, mvar=etemp$var, cmat=Cmat) + \} + else result <- list(estimate=estimate, test=test, mvar=NA) + if (method=="sgtt") result$SAS <- Smat +\end{nwchunk} + +In the non-linear case the mfun object is either a single function +or a list containing two functions \code{predict} and \code{summary}. +The predict function is handed a vector $\eta = X\beta$ along with +the $X$ matrix, though most methods don't use $X$. +The result of predict can be a vector or a matrix. +For coxph models we add on an ``intercept coef'' that will center the +predictions. + +\begin{nwchunk} +\nwhypb{yates-nonlinear2}{yates-nonlinear}{yates-nonlinear1}= + xall <- do.call(rbind, xmatlist)[,!nabeta, drop=FALSE] + if (inherits(fit, "coxph")) \{ + xall <- xall[,-1, drop=FALSE] # remove the intercept + eta <- xall %*% beta -sum(fit$means[!nabeta]* beta) + \} + else eta <- xall %*% beta + n1 <- nrow(xmatlist[[1]]) # all of them are the same size + index <- rep(1:length(xmatlist), each = n1) + if (is.function(mfun)) predfun <- mfun + else \{ # double check the object + if (!is.list(mfun) || + any(is.na(match(c("predict", "summary"), names(mfun)))) || + !is.function(mfun$predic) || !is.function(mfun$summary)) + stop("the prediction should be a function, or a list with two functions") + predfun <- mfun$predict + sumfun <- mfun$summary + \} + pmm <- predfun(eta, xall) + n2 <- length(eta) + if (!(is.numeric(pmm)) || !(length(pmm)==n2 || nrow(pmm)==n2)) + stop("prediction function should return a vector or matrix") + pmm <- rowsum(pmm, index, reorder=FALSE)/n1 + pmm[!estimable,] <- NA + + # get a sample of coefficients, in order to create a variance + # this is lifted from the mvtnorm code (can't include a non-recommended + # package in the dependencies) + tol <- sqrt(.Machine$double.eps) + if (!isSymmetric(vmat, tol=tol, check.attributes=FALSE)) + stop("variance matrix of the coefficients is not symmetric") + ev <- eigen(vmat, symmetric=TRUE) + if (!all(ev$values >= -tol* abs(ev$values[1]))) + warning("variance matrix is numerically not positive definite") + Rmat <- t(ev$vectors %*% (t(ev$vectors) * sqrt(ev$values))) + bmat <- matrix(rnorm(nsim*ncol(vmat)), nrow=nsim) %*% Rmat + bmat <- bmat + rep(beta, each=nsim) # add the mean + + # Now use this matrix of noisy coefficients to get a set of predictions + # and use those to create a variance matrix + # Since if Cox we need to recenter each run + sims <- array(0., dim=c(nsim, nrow(pmm), ncol(pmm))) + if (inherits(fit, 'coxph')) offset <- bmat %*% fit$means[!nabeta] + else offset <- rep(0., nsim) + + for (i in 1:nsim) + sims[i,,] <- rowsum(predfun(xall %*% bmat[i,] - offset[i]), index, + reorder=FALSE)/n1 + mvar <- var(sims[,,1]) # this will be used for the tests + estimate <- cbind(x1data, pmm=unname(pmm[,1]), std= sqrt(diag(mvar))) + + # Now do the tests, on the first column of pmm only + if (is.list(contr$cmat)) \{ + test <- t(sapply(contr$cmat, function(x) + testfun(x, pmm[,1], mvar[estimable, estimable], NULL))) + natest <- sapply(contr$cmat, nafun, pmm[,1]) + \} + else \{ + test <- testfun(contr$cmat, pmm[,1], mvar[estimable, estimable], NULL) + test <- matrix(test, nrow=1, + dimnames=list(contr$termname, names(test))) + natest <- nafun(contr$cmat, pmm[,1]) + \} + if (any(natest)) test[natest,] <- NA + if (any(estimable)) + result <- list(estimate=estimate,test=test, mvar=mvar) + else result <- list(estimate=estimate, test=test, mvar=NA) + + # If there were multiple columns from predfun, compute the matrix of + # results and variances + if (ncol(pmm) > 1 && any(estimable))\{ + pmm <- apply(sims, 2:3, mean) + mvar2 <- apply(sims, 2:3, var) + # Call the summary function, if present + if (is.list(mfun)) result$summary <- sumfun(pmm, mvar2) + else \{ + result$pmm <- pmm + result$mvar2 <- mvar2 + \} + \} +\end{nwchunk} + + +Build the population data set. +If the user provided a data set as the population then the task is +fairly straightforward: we manipulate the data set and then call +model.frame followed by model.matrix in the usual way. +The primary task in that +case is to verify that the data has all the needed variables. + +Otherwise we have to be subtle. +\begin{enumerate} + \item We have ready access to a model frame, but not to the data. + Consider a spline term for instance --- it's not always possible + to go backwards and get the data. + \item We need to manipulate this model frame, e.g., make everyone + treatment=A, then repeat with everyone treatment B. + \item We need to do it in a way that makes the frame still look + like a correct model frame to R. This requires care. +\end{enumerate} + +For population= factorial we create a population data set that has all +the combinations. If there are three adjusters z1, z2 and z3 with +2, 3, and 5 levels, respectively, the new data set will have 30 +rows. +If the primary model didn't have any z1*z2*z3 terms in it we +likely could get by with less, but it's not worth the programming effort +to figure that out: predicted values are normally fairly cheap. +For population=sas we need a mixture: categoricals are factorial and others +are data. Say there were categoricals with 3 and 5 levels, so the factorial +data set has 15 obs, while the overall n is 50. We need a data set of 15*50 +observations to ensure all combinations of the two categoricals with each +continuous line. + +An issue with data vs model is names. Suppose the original model was +\code{lm(y \textasciitilde ns(age,4) + factor(ph.ecog))}. +In the data set the variable name is ph.ecog, in the model frame, +the xlevels list, and terms structure it is factor(ph.ecog). +The data frame has individual columns for the four variables, the model frame +is a list with 3 elements, one of which is named ``ns(age, 4)'': notice the +extra space before the 4 compared to what was typed. + +\begin{nwchunk} +\nwhyp{yates5}{yates}{yates4}{yates6}= + yates_xmat <- function(Terms, Tatt, contr, population, mframe, fit, + iscat, weight) \{ + # which variables(s) are in x1 (variables of interest) + x1indx <- apply(Tatt$factors[,contr$termname,drop=FALSE] >0, 1, any) + x2indx <- !x1indx # adjusters + if (inherits(population, "data.frame")) pdata <- population #user data + else if (population=="data") pdata <- mframe #easy case + else if (population=="factorial") + pdata <- yates_factorial_pop(mframe, Terms, x2indx, fit$xlevels) + else if (population=="sas") \{ + if (all(iscat[x2indx])) + pdata <- yates_factorial_pop(mframe, Terms, x2indx, fit$xlevels) + else if (!any(iscat[x2indx])) pdata <- mframe # no categoricals + else \{ # mixed population + pdata <- yates_factorial_pop(mframe, Terms, x2indx & iscat, + fit$xlevels) + n2 <- nrow(pdata) + pdata <- pdata[rep(1:nrow(pdata), each=nrow(mframe)), ] + row.names(pdata) <- 1:nrow(pdata) + # fill in the continuous + k <- rep(1:nrow(mframe), n2) + for (i in which(x2indx & !iscat)) \{ + j <- names(x1indx)[i] + if (is.matrix(mframe[[j]])) + pdata[[j]] <- mframe[[j]][k,, drop=FALSE] + else pdata[[j]] <- (mframe[[j]])[k] + attributes(pdata[[j]]) <- attributes(mframe[[j]]) + \} + \} + \} + else stop("unknown population") # this should have been caught earlier + + # Now create the x1 data set, the unique rows we want to test + \nwhypf{yates-x1mat1}{yates-x1mat}{yates-x1mat2} + + xmatlist + \} +\end{nwchunk} + +Build a factorial data set from a model frame. +\begin{nwchunk} +\nwhyp{yates6}{yates}{yates5}{yates7}= + yates_factorial_pop <- function(mframe, terms, x2indx, xlevels) \{ + x2name <- names(x2indx)[x2indx] + dclass <- attr(terms, "dataClasses")[x2name] + if (!all(dclass %in% c("character", "factor"))) + stop("population=factorial only applies if all the adjusting terms are categorical") + + nvar <- length(x2name) + n2 <- sapply(xlevels[x2name], length) # number of levels for each + n <- prod(n2) # total number of rows needed + pdata <- mframe[rep(1, n), -1] # toss the response + row.names(pdata) <- NULL # throw away funny names + n1 <- 1 + for (i in 1:nvar) \{ + j <- rep(rep(1:n2[i], each=n1), length=n) + xx <- xlevels[[x2name[i]]] + if (dclass[i] == "factor") + pdata[[x2name[i]]] <- factor(j, 1:n2[i], labels= xx) + else pdata[[x2name[i]]] <- xx[j] + n1 <- n1 * n2[i] + \} + attr(pdata, "terms") <- terms + pdata + \} +\end{nwchunk} + +The next section builds a set of X matrices, one for each level of the +x1 combination. +The following was learned by reading the source code for +model.matrix: +\begin{itemize} +\item If pdata has no terms attribute then model.matrix will call model.frame + first, otherwise not. The xlev argument is passed forward to model.frame + but is otherwise unused. +\item If necessary, it will reorder the columns of pdata to match the terms, + though I try to avoid that. +\item Toss out the response variable, if present. +\item Any character variables are turned into factors. The dataClass attribute + of the terms object is not consulted. +\item For each column that is a factor + \begin{itemize} + \item if it alreay has a contrasts attribute, it is left alone. + \item otherwise a contrasts attribute is added using a matching + element from contrasts.arg, if present, otherwise the global default + \item contrasts.arg must be a list, but it does not have to contain all + factors + \end{itemize} + \item Then call the internal C code +\end{itemize} + +If pdata already is a model frame we want to leave it as one, so as to +avoid recreating the raw data. +If x1data comes from the user though, so we need to do that portion of +model.frame processing ourselves, in order to get it into the right +form. Always turn characters into factors, since individual elements +of \code{xmatlist} will have only a subset of the x1 variables. +One nuisance is name matching. Say the model had +\code{factor(ph.ecog)} as a term; then \code{fit\$xlevels} will have +`factor(ph.ecog)' as a name but the user will likely have created a +data set using `ph.ecog' as the name. + +\begin{nwchunk} +\nwhypb{yates-x1mat2}{yates-x1mat}{yates-x1mat1}= + if (is.null(contr$levels)) stop("levels are missing for this contrast") + x1data <- as.data.frame(contr$levels) # in case it is a list + x1name <- names(x1indx)[x1indx] + for (i in 1:ncol(x1data)) \{ + if (is.character(x1data[[i]])) \{ + if (is.null(fit$xlevels[[x1name[i]]])) + x1data[[i]] <- factor(x1data[[i]]) + else x1data[[i]] <- factor(x1data[[i]], fit$xlevels[[x1name[i]]]) + \} + \} + + xmatlist <- vector("list", nrow(x1data)) + if (is.null(attr(pdata, "terms"))) \{ + np <- nrow(pdata) + k <- match(x1name, names(pdata), nomatch=0) + if (any(k>0)) pdata <- pdata[, -k, drop=FALSE] # toss out yates var + for (i in 1:nrow(x1data)) \{ + j <- rep(i, np) + tdata <- cbind(pdata, x1data[j,,drop=FALSE]) # new data set + xmatlist[[i]] <- model.matrix(Terms, tdata, xlev=fit$xlevels, + contrast.arg= fit$contrasts) + \} + \} else \{ + # pdata is a model frame, convert x1data + # if the name and the class agree we go forward simply + index <- match(names(x1data), names(pdata), nomatch=0) + + if (all(index >0) && + identical(lapply(x1data, class), lapply(pdata, class)[index]) & + identical(sapply(x1data, ncol) , sapply(pdata, ncol)[index])) + \{ # everything agrees + for (i in 1:nrow(x1data)) \{ + j <- rep(i, nrow(pdata)) + tdata <- pdata + tdata[,names(x1data)] <- x1data[j,] + xmatlist[[i]] <- model.matrix(Terms, tdata, + contrasts.arg= fit$contrasts) + \} + \} + else \{ + # create a subset of the terms structure, for x1 only + # for instance the user had age=c(75, 75, 85) and the term was ns(age) + # then call model.frame to fix it up + x1term <- Terms[which(x1indx)] + x1name <- names(x1indx)[x1indx] + attr(x1term, "dataClasses") <- Tatt$dataClasses[x1name] # R bug + x1frame <- model.frame(x1term, x1data, xlev=fit$xlevels[x1name]) + for (i in 1:nrow(x1data)) \{ + j <- rep(i, nrow(pdata)) + tdata <- pdata + tdata[,names(x1frame)] <- x1frame[j,] + xmatlist[[i]] <- model.matrix(Terms, tdata, xlev=fit$xlevels, + contrast.arg= fit$contrasts) + \} + \} + \} +\end{nwchunk} + +The decompostion based algorithm for SAS type 3 tests. +Ignore the set of contrasts cmat since the algorithm can only +do a global test. +We mostly mimic the SAS GLM algorithm. + +For the generalized Cholesky decomposition $LDL' = X'X$, where $L$ is +lower triangular with $L_{ii}=1$ and $D$ is diagonal, the set of contrasts +$L'\beta$ gives the type I sequential sums of squares, partitioning the +rows of $L$ into those for term 1, term 2, etc. +If $X$ is the design matrix for a balanced factorial design then it is +also true that $L_{ij}=0$ unless term $j$ includes term $i$, e.g., x1:x2 +includes x1. These blocks of zeros mean that changing the order of the terms +in the model simply rearranges $L$, and individual tests are unchanged. + +This is precisely the definition of a type III contrast in SAS. +With a bit of reading between the lines the ``four types of estimable +functions'' document suggests the following algorithm: +\begin{enumerate} + \item Start with an $X$ matrix in standard order of intercept, main effects, + first order interactions, etc. Code any categorical variable with $k$ levels + as $k$ 0/1 columns. An interaction of two categoricals with $k$ and $l$ + levels will have $kl$ columns, etc. + \item Create the dependency matrix $D = (X'X)^-(X'X)$. If column $i$ of $X$ + can be written as a linear combination of prior columns, then column $i$ of + $D$ contains that combination. Other columns of $D$ match the identity + matrix. + \item Intitialize $L = D$. + \item For any row $i$ and $j$ such that $i$ is contained in $j$, make $L_i$ + orthagonal to $L_j$. +\end{enumerate} +The algorithm appears to work in almost all cases, an exception is when the +type 3 test has fewer degrees of freedom that we would expect. + +Continuous variables are not orthagonalized in the SAS type III approach, +nor any interaction that contains a continuous variable as one of its parts. +To find the nested terms first note which rows of \code{factors} refer +to categorical variables (the \code{iscat} variable); +columns of \code{factors} that are non-zero only +in categorical rows are the ``categorical'' columns. +A term represented by one column in \code{factors} ``contains'' the term +represented in some other column iff it's non-zero elements are a superset. + +We have to build a new X matrix that is the expanded SAS coding, and are only +able to do that for models that have an intercept, and use contr.treatement +or contr.SAS coding. +\begin{nwchunk} +\nwhyp{yates-sgtt2}{yates-sgtt}{yates-sgtt1}{yates-sgtt3}= + # It would be simplest to have the contrasts.arg to be a list of function names. + # However, model.matrix plays games with the calling sequence, and any function + # defined at this level will not be seen. Instead create a list of contrast + # matrices. + temp <- sapply(fit$contrasts, function(x) (is.character(x) && + x %in% c("contr.SAS", "contr.treatment"))) + if (!all(temp)) + stop("yates sgtt method can only handle contr.SAS or contr.treatment") + temp <- vector("list", length(fit$xlevels)) + names(temp) <- names(fit$xlevels) + for (i in 1:length(fit$xlevels)) \{ + cmat <- diag(length(fit$xlevels[[i]])) + dimnames(cmat) <- list(fit$xlevels[[i]], fit$xlevels[[i]]) + if (i>1 || Tatt$intercept==1) \{ + if (fit$contrasts[[i]] == "contr.treatment") + cmat <- cmat[, c(2:ncol(cmat), 1)] + \} + temp[[i]] <- cmat + \} + sasX <- model.matrix(formula(fit), data=mframe, xlev=fit$xlevels, + contrasts.arg=temp) + sas.assign <- attr(sasX, "assign") + + # create the dependency matrix D. The lm routine is unhappy if it thinks + # the right hand and left hand sides are the same, fool it with I(). + # We do this using the entire X matrix even though only categoricals will + # eventually be used; if a continuous variable made it NA we need to know. + D <- coef(lm(sasX ~ I(sasX) -1)) + dimnames(D)[[1]] <- dimnames(D)[[2]] #get rid if the I() names + zero <- is.na(D[,1]) # zero rows, we'll get rid of these later + D <- ifelse(is.na(D), 0, D) + + # make each row orthagonal to rows for other terms that contain it + # Containing blocks, if any, will always be below + # this is easiest to do with the transposed matrix + # Only do this if both row i and j are for a categorical variable + if (!all(iscat)) \{ + # iscat marks variables in the model frame as categorical + # tcat marks terms as categorical. For x1 + x2 + x1:x2 iscat has + # 2 entries and tcat has 3. + tcat <- (colSums(Tatt$factors[!iscat,,drop=FALSE]) == 0) + \} + else tcat <- rep(TRUE, max(sas.assign)) # all vars are categorical + + B <- t(D) + dimnames(B)[[2]] <- paste0("L", 1:ncol(B)) # for the user + if (ncol(Tatt$factors) > 1) \{ + share <- t(Tatt$factors) %*% Tatt$factors + nc <- ncol(share) + for (i in which(tcat[-nc])) \{ + j <- which(share[i,] > 0 & tcat) + k <- j[j>i] # terms that I need to regress out + if (length(k)) \{ + indx1 <- which(sas.assign ==i) + indx2 <- which(sas.assign %in% k) + B[,indx1] <- resid(lm(B[,indx1] ~ B[,indx2])) + \} + \} + \} + + # Cut B back down to the non-missing coefs of the original fit + Smat <- t(B)[!zero, !zero] + Sassign <- xassign[!nabeta] +\end{nwchunk} + +Although the SGTT does test for all terms, we only want to print out the +ones that were asked for. +\begin{nwchunk} +\nwhypb{yates-sgtt3}{yates-sgtt}{yates-sgtt2}= + keep <- match(contr$termname, colnames(Tatt$factors)) + if (length(keep) > 1) \{ # more than 1 term in the model + test <- t(sapply(keep, function(i) + testfun(Smat[Sassign==i,,drop=FALSE], beta, vmat, sigma^2))) + rownames(test) <- contr$termname + \} else \{ + test <- testfun(Smat[Sassign==keep,, drop=FALSE], beta, vmat, sigma^2) + test <- matrix(test, nrow=1, + dimnames=list(contr$termname, names(test))) + \} +\end{nwchunk} + + +The print routine places the population predicted values (PPV) alongside the +tests on those values. Defaults are copied from printCoefmat. + +\begin{nwchunk} +\nwhyp{yates7}{yates}{yates6}{yates8}= + print.yates <- function(x, digits = max(3, getOption("digits") -2), + dig.tst = max(1, min(5, digits-1)), + eps=1e-8, ...) \{ + temp1 <- x$estimate + temp1$pmm <- format(temp1$pmm, digits=digits) + temp1$std <- format(temp1$std, digits=digits) + + # the spaces help separate the two parts of the printout + temp2 <- cbind(test= paste(" ", rownames(x$test)), + data.frame(x$test), stringsAsFactors=FALSE) + row.names(temp2) <- NULL + + temp2$Pr <- format.pval(pchisq(temp2$chisq, temp2$df, lower.tail=FALSE), + eps=eps, digits=dig.tst) + temp2$chisq <- format(temp2$chisq, digits= dig.tst) + temp2$df <- format(temp2$df) + if (!is.null(temp2$ss)) temp2$ss <- format(temp2$ss, digits=digits) + + if (nrow(temp1) > nrow(temp2)) \{ + dummy <- temp2[1,] + dummy[1,] <- "" + temp2 <- rbind(temp2, dummy[rep(1, nrow(temp1)-nrow(temp2)),]) + \} + if (nrow(temp2) > nrow(temp1)) \{ + # get rid of any factors before padding + for (i in which(sapply(temp1, is.factor))) + temp1[[i]] <- as.character(temp1[[i]]) + + dummy <- temp1[1,] + dummy[1,] <- "" + temp1 <- rbind(temp1, dummy[rep(1, nrow(temp2)- nrow(temp1)),]) + \} + print(cbind(temp1, temp2), row.names=FALSE) + invisible(x) + \} +\end{nwchunk} + + +Routines to allow yates to interact with other models. +Each is called with the fitted model and the type of prediction. +It should return NULL when the type is a linear predictor, since the +parent routine has a very efficient approach in that case. +Otherwise it returns a function that will be applied to each value +$\eta$, from each row of a prediction matrix. + +\begin{nwchunk} +\nwhyp{yates8}{yates}{yates7}{yates9}= + yates_setup <- function(fit, ...) + UseMethod("yates_setup", fit) + + yates_setup.default <- function(fit, type, ...) \{ + if (!missing(type) && !(type %in% c("linear", "link"))) + warning("no yates_setup method exists for a model of class ", + class(fit)[1], " and estimate type ", type, + ", linear predictor estimate used by default") + NULL + \} + + yates_setup.glm <- function(fit, predict = c("link", "response", "terms", + "linear"), ...) \{ + type <- match.arg(predict) + if (type == "link" || type== "linear") NULL # same as linear + else if (type == "response") \{ + finv <- family(fit)$linkinv + function(eta, X) finv(eta) + \} + else if (type == "terms") + stop("type terms not yet supported") + \} +\end{nwchunk} + +For the coxph routine, we are making use of the R environment by first +defining the baseline hazard and then defining the predict and summary +functions. This means that those functions have access to the baseline. + +\begin{nwchunk} +\nwhypb{yates9}{yates}{yates8}= + yates_setup.coxph <- function(fit, predict = c("lp", "risk", "expected", + "terms", "survival", "linear"), + options, ...) \{ + type <- match.arg(predict) + if (type=="lp" || type == "linear") NULL + else if (type=="risk") function(eta, X) exp(eta) + else if (type == "survival") \{ + # If there are strata we need to do extra work + # if there is an interaction we want to suppress a spurious warning + suppressWarnings(baseline <- survfit(fit, censor=FALSE)) + if (missing(options) || is.null(options$rmean)) + rmean <- max(baseline$time) # max death time + else rmean <- options$rmean + + if (!is.null(baseline$strata)) + stop("stratified models not yet supported") + cumhaz <- c(0, baseline$cumhaz) + tt <- c(diff(c(0, pmin(rmean, baseline$time))), 0) + + predict <- function(eta, ...) \{ + c2 <- outer(exp(drop(eta)), cumhaz) # matrix of values + surv <- exp(-c2) + meansurv <- apply(rep(tt, each=nrow(c2)) * surv, 1, sum) + cbind(meansurv, surv) + \} + summary <- function(surv, var) \{ + bsurv <- t(surv[,-1]) + std <- t(sqrt(var[,-1])) + chaz <- -log(bsurv) + zstat <- -qnorm((1-baseline$conf.int)/2) + baseline$lower <- exp(-(chaz + zstat*std)) + baseline$upper <- exp(-(chaz - zstat*std)) + baseline$surv <- bsurv + baseline$std.err <- std/bsurv + baselinecumhaz <- chaz + baseline + \} + list(predict=predict, summary=summary) + \} + else stop("type expected is not supported") + \} + +\end{nwchunk} +\section{The cox.zph function} +The simplest test of proportional hazards is to use a time dependent +coefficient $\beta(t) = a + bt$. +Then $\beta(t) x = ax + b*(tx)$, and the extended coefficients $a$ and $b$ +can be obtained from a Cox model with an extra 'fake' covariate $tx$. +More generally, replace $t$ with some function $g(t)$, which gives rise to +an entire family of tests. +An efficient assessment of this extended model can be done using a score +test. +\begin{itemize} + \item Augment the original variables $x_1, \ldots x_k$ with $k$ new ones +$g(t)x_1, \ldots, g(t)x_k$ + \item Compute the first and second derivatives $U$ and $H$ of the Cox model +at the starting estimate of $(\hat\beta, 0)$; prior covariates at their +prior values, and the new covariates at 0. No iteration is done. +This can be done efficiently with a modified version of the primary C routines +for coxph. + \item By design, the first $k$ elements of $U$ will be zero. Thus the +first iteration of the new coefficients, and the score tests for them, are +particularly easy. +\end{itemize} + +The information or Hessian matrix for a Cox model is +$$ \sum_{j \in deaths} V(t_j) = \sum_jV_j$$ +where $V_j$ is the variance matrix of the weighted covariate values, over +all subjects at risk at time $t_j$. +Then the expanded information matrix for the score test is +\begin{align*} + H &= \left(\begin{array}{cc} H_1 & H_2 \\ H_2' & H_3 \end{array} \right) \\ + H_1 &= \sum V(t_j) \\ + H_2 &= \sum V(t_j) g(t_j) \\ + H_3 &= \sum V(t_j) g^2(t_j) +\end{align*} +The inverse of the matrix will be more numerically stable if $g(t)$ is centered +at zero, and this does not change the test statistic. +In the usual case $V(t)$ is close to constant in time --- the variance of +$X$ does not change rapidly --- and then $H_2$ is approximately zero. +The original cox.zph used an approximation, which is to assume that +$V(t)$ is exactly constant. +In that case $H_2=0$ and $H_3= \sum V(t_j) \sum g^2(t_j)$ and the test +is particularly easy to compute. +This assumption of identical components can fail badly for models with a +covariate by strata interaction, and for some models with covariate +dependent censoring. +Multi-state models finally forced a change. + +The newer version of the routine has two separate tracks: for the formal test +and another for the residuals. + +\begin{nwchunk} +\nwhypf{cox.zph1}{cox.zph}{cox.zph2}= + cox.zph <- function(fit, transform='km', terms=TRUE, singledf =FALSE, + global=TRUE) \{ + Call <- match.call() + if (!inherits(fit, "coxph") && !inherits(fit, "coxme")) + stop ("argument must be the result of Cox model fit") + if (inherits(fit, "coxph.null")) + stop("there are no score residuals for a Null model") + if (!is.null(attr(terms(fit), "specials")[["tt"]])) + stop("function not defined for models with tt() terms") + + if (inherits(fit, "coxme")) \{ + # drop all mention of the random effects, before getdata + fit$formula <- fit$formula$fixed + fit$call$formula <- fit$formula + \} + + cget <- coxph.getdata(fit, y=TRUE, x=TRUE, stratax=TRUE, weights=TRUE) + y <- cget$y + ny <- ncol(y) + event <- (y[,ny] ==1) + if (length(cget$strata)) + istrat <- as.integer(cget$strata) - 1L # number from 0 for C + else istrat <- rep(0L, nrow(y)) + + # if terms==FALSE the singledf argument is moot, but setting a value + # leads to a simpler path through the code + if (!terms) singledf <- FALSE + + \nwhypf{zph-setup1}{zph-setup}{zph-setup2} + \nwhypf{zph-transform1}{zph-transform}{zph-transform2} + \nwhypf{zph-terms1}{zph-terms}{zph-terms2} + \nwhypf{zph-schoen1}{zph-schoen}{zph-schoen2} + + rval$transform <- tname + rval$call <- Call + class(rval) <- "cox.zph" + return(rval) + \} + + print.cox.zph <- function(x, digits = max(options()$digits - 4, 3), + signif.stars=FALSE, ...) \{ + invisible(printCoefmat(x$table, digits=digits, signif.stars=signif.stars, + P.values=TRUE, has.Pvalue=TRUE, ...)) + \} +\end{nwchunk} + +The user can use $t$ or $g(t)$ as the multiplier of the covariates. +The default is to use the KM, only because that seems to be best at +avoiding edge cases. + +\begin{nwchunk} +\nwhypb{zph-transform2}{zph-transform}{zph-transform1}= + times <- y[,ny-1] + if (is.character(transform)) \{ + tname <- transform + ttimes <- switch(transform, + 'identity'= times, + 'rank' = rank(times), + 'log' = log(times), + 'km' = \{ + temp <- survfitKM(factor(rep(1L, nrow(y))), + y, se.fit=FALSE) + # A nuisance to do left continuous KM + indx <- findInterval(times, temp$time, left.open=TRUE) + 1.0 - c(1, temp$surv)[indx+1] + \}, + stop("Unrecognized transform")) + \} + else \{ + tname <- deparse(substitute(transform)) + if (length(tname) >1) tname <- 'user' + ttimes <- transform(times) + \} + gtime <- ttimes - mean(ttimes[event]) + + # Now get the U, information, and residuals + if (ny==2) \{ + ord <- order(istrat, y[,1]) -1L + resid <- .Call(Czph1, gtime, y, X, eta, + cget$weights, istrat, fit$method=="efron", ord) + \} + else \{ + ord1 <- order(-istrat, -y[,1]) -1L # reverse time for zph2 + ord <- order(-istrat, -y[,2]) -1L + resid <- .Call(Czph2, gtime, y, X, eta, + cget$weights, istrat, fit$method=="efron", + ord1, ord) + \} +\end{nwchunk} + +The result has a score vector of length $2p$ where $p$ is the number of +variables and an information matrix that is $2p$ by $2p$. +This is done with C code that +is a simple variation on iteration 1 for a coxph model. + +If \code{singledf} is TRUE then treat each term as a single degree of +freedom test, otherwise as a multi-degree of freedom. +If terms=FALSE test each covariate individually. +If all the variables are univariate this is a moot point. +The survival routines return Splus style assign components, that is a list +with one element per term, each element an integer vector of coefficient +indices. + +The asgn vector is our main workhorse: loop over asgn to process term by +term. +\begin{itemize} + \item if term=FALSE, set make a new asgn with one coef per term + \item if a coefficient is NA, remove it from the relevant asgn vector + \item frailties and penalized coxme coefficients are ignored: remove + their element from the asgn list +\end{itemize} + +For random effects models, including both frailty and coxme results, the +random effect is included in the linear.predictors component of the +fit. This allows us to do score tests for the other terms while effectively +holding the random effect fixed. + +If there are any NA coefficients these are redundant variables. It's +easiest to simply get rid of them at the start by fixing up X, varnames, +asgn, and nvar. +\begin{nwchunk} +\nwhypb{zph-setup2}{zph-setup}{zph-setup1}= + eta <- fit$linear.predictors + X <- cget$x + varnames <- names(fit$coefficients) + nvar <- length(varnames) + + if (!terms) \{ + # create a fake asgn that has one value per coefficient + asgn <- as.list(1:nvar) + names(asgn) <- names(fit$coefficients) + \} + else if (inherits(fit, "coxme")) \{ + asgn <- attrassign(cget$x, terms(fit)) + # allow for a spelling inconsistency in coxme, later fixed + if (is.null(fit$linear.predictors)) + eta <- fit$linear.predictor + fit$df <- NULL # don't confuse later code + \} + else asgn <- fit$assign + + if (!is.list(asgn)) stop ("unexpected assign component") + + frail <- grepl("frailty(", names(asgn), fixed=TRUE) + if (any(frail)) \{ + dcol <- unlist(asgn[frail]) # remove these columns from X + X <- X[, -dcol, drop=FALSE] + asgn <- asgn[!frail] + # frailties don't appear in the varnames, so no change there + \} + nterm <- length(asgn) + termname <- names(asgn) + + if (any(is.na(fit$coefficients))) \{ + keep <- !is.na(fit$coefficients) + varnames <- varnames[keep] + X <- X[,keep] + + # fix up assign + new <- unname(unlist(asgn))[keep] # the ones to keep + asgn <- sapply(asgn, function(x) \{ + i <- match(x, new, nomatch=0) + i[i>0]\}) + asgn <- asgn[sapply(asgn, length)>0] # drop any that were lost + termname <- names(asgn) + nterm <- length(asgn) # asgn will be a list + nvar <- length(new) + \} +\end{nwchunk} + +The zph1 and zph2 functions do not consider penalties, so we need to add +those back in after the call. +Nothing needs to be done wrt the first derivative: we already ignore the +first ncoef elements of the returned first derivative (u) vector, which would +have had a penalty. The second portion of u is for beta=0, and all of the +penalties that currently are implemented have first derivative 0 at 0. +For the second derivative, the current penalties (frailty, rigde, pspline) have +a second derivative penalty that is independent of beta-hat. +The coxph result contains the numeric value of the penalty at the solution, +and we use a score test that would penalize the new time*pspline() term in +the same way as the pspline term was penalized. + +If no coefficients were missing then allvar will be 1:n, otherwise it +will have holes. + +\begin{nwchunk} +\nwhypb{zph-terms2}{zph-terms}{zph-terms1}= + test <- double(nterm+1) + df <- rep(1L, nterm+1) + u0 <- rep(0, nvar) + if (!is.null(fit$coxlist2)) \{ # there are penalized terms + pmat <- matrix(0., 2*nvar, 2*nvar) # second derivative penalty + pmat[1:nvar, 1:nvar] <- fit$coxlist2$second + pmat[1:nvar + nvar, 1:nvar + nvar] <- fit$coxlist2$second + imatr <- resid$imat + pmat + \} + else imatr <- resid$imat + + for (ii in 1:nterm) \{ + jj <- asgn[[ii]] + kk <- c(1:nvar, jj+nvar) + imat <- imatr[kk, kk] + u <- c(u0, resid$u[jj+nvar]) + if (singledf && length(jj) >1) \{ + vv <- solve(imat)[-(1:nvar), -(1:nvar)] + t1 <- sum(fit$coef[jj] * resid$u[jj+nvar]) + test[ii] <- t1^2 * (fit$coef[jj] %*% vv %*% fit$coef[jj]) + df[ii] <- 1 + \} + else \{ + test[ii] <- drop(solve(imat,u) %*% u) + if (is.null(fit$df)) df[ii] <- length(jj) + else df[ii] <- fit$df[ii] + \} + \} + + #Global test + if (global) \{ + u <- c(u0, resid$u[-(1:nvar)]) + test[nterm+1] <- solve(imatr, u) %*% u + if (is.null(fit$df)) df[nterm+1] <- nvar + else df[nterm+1] <- sum(fit$df) + + tbl <- cbind(test, df, pchisq(test, df, lower.tail=FALSE)) + dimnames(tbl) <- list(c(termname, "GLOBAL"), c("chisq", "df", "p")) + \} + else \{ + tbl <- cbind(test, df, pchisq(test, df, lower.tail=FALSE))[1:nterm,, drop=FALSE] + dimnames(tbl) <- list(termname, c("chisq", "df", "p")) + \} + + # The x, y, residuals part is sorted by time within strata; this is + # what the C routine zph1 and zph2 return + indx <- if (ny==2) ord +1 else rev(ord) +1 # return to 1 based subscripts + indx <- indx[event[indx]] # only keep the death times + rval <- list(table=tbl, x=unname(ttimes[indx]), time=unname(y[indx, ny-1])) + if (length(cget$strata)) rval$strata <- cget$strata[indx] +\end{nwchunk} + +The matrix of scaled Schoenfeld residuals is created one stratum at a +time. +The ideal for the residual $r(t_i)$, contributed by an event for subject +$i$ at time $t_i$ is to use $r_iV^{-1}(t_i)$, the inverse of the variance +matrix of $X$ at that time and for the relevant stratum. +What is returned as \code{resid\$imat} is $\sum_i V(t_i)$. +One option would have been to return all the individual $\hat V_i$ matrices, +but that falls over when the number at risk is too small and it cannot +be inverted. +Option 2 would be to use a per stratum averge of the $V_i$, but that falls +flat for models with a large number of strata, a nested case-control model +for instance. +We take a different average that may not be the best, but seems to be +good enough and doesn't seem to fail. +\begin{enumerate} + \item The \code{resid\$used} matrix contains the number of deaths for + each strata (row) that contributed to the sum for each variable (column). + The value is either 0 or the number of events in the stratum, zero for those + variables that are constant within the stratum. From this we can get the + number of events that contributed to each element of the \code{imat} total. + Dividing by this gives a per-element average \code{vmean}. + \item For a given stratum, some of the covariates may have been unused. For + any of those set the scaled Schoenfeld residual to NA, and use the other + rows/columns of the \code{vmean} matrix to scale the rest. +\end{enumerate} +Now if some variable $x_1$ has a large variance at some time points and a +small variance at others, or a large variance in one stratum and a small +variance in another, the above smoothing won't catch that subtlety. +However we expect such an issue to be rare. +The common problem of strata*covariate interactions is the target of the +above manipulations. + +\begin{nwchunk} +\nwhypb{zph-schoen2}{zph-schoen}{zph-schoen1}= + # Watch out for a particular edge case: there is a factor, and one of the + # strata happens to not use one of its levels. The element of resid$used will + # be zero, but it really should not. + used <-resid$used + for (i in asgn) \{ + if (length(i) > 1 && any(used[,i] ==0)) + used[,i] <- apply(used[,i,drop=FALSE], 1, max) + \} + + # Make the weight matrix + wtmat <- matrix(0, nvar, nvar) + for (i in 1:nrow(used)) + wtmat <- wtmat + outer(used[i,], used[i,], pmin) + # with strata*covariate interactions (multi-state models for instance) the + # imatr matrix will be block diagonal. Don't divide these off diagonal zeros + # by a wtmat value of zero. + vmean <- imatr[1:nvar, 1:nvar, drop=FALSE]/ifelse(wtmat==0, 1, wtmat) + + sresid <- resid$schoen + if (terms && any(sapply(asgn, length) > 1)) \{ # collase multi-column terms + temp <- matrix(0, ncol(sresid), nterm) + for (i in 1:nterm) \{ + j <- asgn[[i]] + if (length(j) ==1) temp[j, i] <- 1 + else temp[j, i] <- fit$coefficients[j] + \} + + sresid <- sresid %*% temp + vmean <- t(temp) %*% vmean %*% temp + used <- used[, sapply(asgn, function(x) x[1]), drop=FALSE] + \} + + dimnames(sresid) <- list(signif(rval$time, 4), termname) + + # for each stratum, rescale the Schoenfeld residuals in that stratum + sgrp <- rep(1:nrow(used), apply(used, 1, max)) + for (i in 1:nrow(used)) \{ + k <- which(used[i,] > 0) + if (length(k) >0) \{ # there might be no deaths in the stratum + j <- which(sgrp==i) + if (length(k) ==1) sresid[j,k] <- sresid[j,k]/vmean[k,k] + else sresid[j, k] <- t(solve(vmean[k, k], t(sresid[j, k, drop=FALSE]))) + sresid[j, -k] <- NA + \} + \} + + # Add in beta-hat. For a term with multiple columns we are testing zph for + # the linear predictor X{\textbackslash}beta, which always has a coefficient of 1 + for (i in 1:nterm) \{ + j <- asgn[[i]] + if (length(j) ==1) sresid[,i] <- sresid[,i] + fit$coefficients[j] + else sresid[,i] <- sresid[,i] +1 + \} + + rval$y <- sresid + rval$var <- solve(vmean) +\end{nwchunk} + +\begin{nwchunk} +\nwhypb{cox.zph2}{cox.zph}{cox.zph1}= + "[.cox.zph" <- function(x, ..., drop=FALSE) \{ + i <- ..1 + if (!is.null(x$strata)) \{ + y2 <- x$y[,i,drop=FALSE] + ymiss <- apply(is.na(y2), 1, all) + if (any(ymiss)) \{ + # some deaths played no role in these coefficients + # due to a strata * covariate interaction, drop unneeded rows + z<- list(table=x$table[i,,drop=FALSE], x=x$x[!ymiss], + time= x$time[!ymiss], + strata = x$strata[!ymiss], + y = y2[!ymiss,,drop=FALSE], + var=x$var[i,i, drop=FALSE], + transform=x$transform, call=x$call) + \} + else z<- list(table=x$table[i,,drop=FALSE], x=x$x, time= x$time, + strata = x$strata, + y = y2, var=x$var[i,i, drop=FALSE], + transform=x$transform, call=x$call) + \} + else + z<- list(table=x$table[i,,drop=FALSE], x=x$x, time= x$time, + y = x$y[,i,drop=FALSE], + var=x$var[i,i, drop=FALSE], + transform=x$transform, call=x$call) + class(z) <- class(x) + z + \} +\end{nwchunk} +\bibliographystyle{plain} +\bibliography{refer} +\end{document} diff --git a/noweb/code.toc b/noweb/code.toc new file mode 100644 index 00000000..e69de29b diff --git a/noweb/coxph.Rnw b/noweb/coxph.Rnw index f5223182..e7b28237 100644 --- a/noweb/coxph.Rnw +++ b/noweb/coxph.Rnw @@ -61,7 +61,10 @@ coxph <- function(formula, data, weights, subset, na.action, terms(formula[[1]], specials=ss, data=data) else Terms <- if (missing(data)) terms(formula, specials=ss) else terms(formula, specials=ss, data=data) - + attr(Terms,'term.labels') = gsub('\n',' ', attr(Terms,'term.labels')) + colnames(attr(Terms,'factors')) = gsub('\n',' ', colnames(attr(Terms,'factors'))) + rownames(attr(Terms,'factors')) = gsub('\n',' ', rownames(attr(Terms,'factors'))) + tcl <- attr(Terms, 'specials')$cluster if (length(tcl) > 1) stop("a formula cannot have multiple cluster terms") @@ -135,7 +138,10 @@ coxph <- function(formula, data, weights, subset, na.action, # okay, now evaluate the formula mf <- eval(tform, parent.frame()) Terms <- terms(mf) - + attr(Terms,'term.labels') = gsub('\n',' ', attr(Terms,'term.labels')) + colnames(attr(Terms,'factors')) = gsub('\n',' ', colnames(attr(Terms,'factors'))) + rownames(attr(Terms,'factors')) = gsub('\n',' ', rownames(attr(Terms,'factors'))) + # Grab the response variable, and deal with Surv2 objects n <- nrow(mf) Y <- model.response(mf) diff --git a/noweb/noweb.sty b/noweb/noweb.sty new file mode 100644 index 00000000..0cb03fa3 --- /dev/null +++ b/noweb/noweb.sty @@ -0,0 +1,25 @@ +% +% The format files for the noweave package +% It looks like a short form of Sweave.sty +% +\NeedsTeXFormat{LaTeX2e} +\RequirePackage{fancyvrb,hyperref} +%forward, backward, and both hyperlinks +% nwhypf{my label}{text to put here}{label of forward link} +% nwhypb{my label}{text to put here}{label of backwards link} +% nwhyp {my label}{text to put here}{label of backwards link}{forward link label} +\newcommand{\nwhypf}[3]{\hypertarget{#1}{$\langle$\textit{#2}}\hyperlink{#3}{$\rangle$}} +\newcommand{\nwhypb}[3]{\hyperlink{#3}{$\langle$}\hypertarget{#1}{\textit{#2}$\rangle$}} +\newcommand{\nwhyp}[4]{\hyperlink{#3}{$\langle$}\hypertarget{#1}{\textit{#2}}\hyperlink{#4}{$\rangle$}} +% no hyperlink code reference +\newcommand{\nwhypn}[1]{$\langle$\textit{#1}$\rangle$} +% dummy out noweboptions, in case someone used them (they are part +% of Ramsay's standalone version +\newcommand{\noweboptions}[1]{} +% The standard font for ~ used in formulas is ugly, redefine it +% to the math mode symbol by making use of an active charcter trick +% Leave the \, {, and } characters active +%\newcommand{\twiddle}{\ensuremath{\sim}} +\newcommand{\twiddle}{\textasciitilde} +\DefineVerbatimEnvironment{nwchunk}{Verbatim}{commandchars=\\\{\},% +codes={\catcode`~=\active},defineactive=\def~{\twiddle}} diff --git a/src/agexact.o b/src/agexact.o new file mode 100644 index 0000000000000000000000000000000000000000..8d3981c6b84539511f67211f7865cce7e1894fe8 GIT binary patch literal 29688 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 literal 0 HcmV?d00001 diff --git a/src/agfit4.o b/src/agfit4.o new file mode 100644 index 0000000000000000000000000000000000000000..878c1c2d663cef4570fcd90e2d5864b7d5cb1b39 GIT binary patch literal 49064 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ΡZGlZXTrGSWG&4>$Wxwf);|XOMrmli{p$Mmu+I_l+66P&q-0 zZ##nuKb8xUQbZpDN4hQ^Zost*be{wP0nrp z-`a1IHT?HA$NW#(>pw)%o2py>{?40l!QI7b!aDlR9{WRoYx5ERpPJYEe`l|cw;>Fz zQ;u)@?_1;S@jvZ*QBC1pn8GjGM_zDfY!DMt`~!S5Y*Hu1S)by(<=n&*nFhe`+(~cM z+ny%!>+VFpjrhpqY9b$@++Lmg$=-ESC&&FYndsJf|0B)LgZ@!4#Y#;70aN^q>u>VM zHenW@zs{e&-Zy>7d%9O#`PNxi&OX=QpN602IAW7?n{V{-&bOXicQ>ZuLYj)c?7`7W zXTl#U*H$&oir=GsS%m=KsqSnf-!^BXQ{<@l_%Ufpo%C(|sdL`C7Jtk)(~eB`k8?8p zOMDHse?WylewR!|Cj$<(;ruz;)h3=-xavwRMJcT(V28iop2k_5d1hi+MI$dL zHT`p9J3y$J={qOQKLwF*pl_T#Yx3rod|88?IC;2p=jN8G$YXPsvXiSx_s!?!zcDZ2 zf9q|SX{yYb;(KqnVrhJqQbk3c|G}jBsu@}?UhjX$!c57GO!oD|M(E;#qPbQ>Y3;IX ztE922t|7KGUSXA0)zw5Bm#qR;cwtFRUD>jdm}0W#mCR@;En60iUA$`f(z+VjQD7IL z*if+~T3c?#qRZ>SH>Y%Yw2`^SFRzV_Us@U~s~R6GZCutkzOkybAzD5@a&bvRT^;sG zb@AF*<9KYs8nN+E#aG80qT{Y8U0xl{9$!|6z1f0BD!G7=%!SxyRD%tBk?IwtHRBr_ z%B*=6C8dq?qNO!xJHM``rnG?@M?q~v-BpcNV|8V1W$ALI>{Zz9M3uVnTEe5{8T7M^ zCG-=OjgU}Y7b~epM@uWC)Dc*uv94xCG+Q@Qi2YF|e#R0lRWFxjO6E6I*Vja6*45P2 zGFGy@v|$<4w#dr!3T9g6b&c2}MNyH=7sbF-tds=9KkAzBut?Uxm6jMb4Lzf)7U zw6vz6b_JBEu3eFB)zy?Qr5~aysjow)V&!#lD2{PzEM1|ygkR>w-X^*Na!`M6Lv%%T zU0lWjO_w&RPBo%~q{_^i(nhzm;QX0$=HpNNYb!Ip2qwr6bLzZZWmX_-#b#K|u9tB07|Y}JHPvPK9a)?vR;pi$ zjn&nZP&gus!iQ)Y=+lqYP~Eu9Li3IB`ul@*-AMY0U~6)OjTfYL_B#m0vVP8=%J%4&0iRVhh003vZ?Zaip2)wyl5qbR*iJijnfP*RV0kGciR>tm~EV3nn*z2(cuNwJh*8N%9BhPbPKVOaGCk;hVN zl2snXk+V^|n;(kK<&HHWVRjzx0CZqW>>?|wUv1dG|U$_ zlr`WdjpwO|!p2tWP{-#~*XZ$g6;M&2HhNXfGOVbyno@gu%Fx`#kM(8iA4guU13vl- zr$jWvl&Gae6RXAil1mC^&c6`0iOg5On4E1Xr_iDEJ5dD6>N2aMw7SNs$NB=7P?Lp* zng0W}SOUMq0m%QvLb+u2pT~On%e2nX8RS}Bo;&5XNGqMyhbY4kb z<4nZ7QvAHLyV{n_)ypQ={LY*O88dTpGtS98D|14|xaF~UZFFj-?f|l-4P{kRaqTkh z?3|2ol^NqM%+45xC^8k7FQ_!GqQ1HeZ#YKTvT^K#bq(NXzyigqHH|{P(yPnTTNZC9 zf&a#rlb-o?F^OaPC#kcOcPPppXXn5o@N>OF(TLG@MujEX5>OkoMk5qdVy&{iGjry- z8DkbK#kM7`yEblOT;;NwvnFLu$Qi3qx+39k!ddp!^DKL1nteiQUuP38NFpd3Nep<@ z#np^~X*c?23>?1EUobGEBQRs&m>c@!51g!DR1C}yn$n8 z49oy8>dYAE%-}C=Xn!?4+hsQjy%KGWrsE5Z-w?#cXe!2qc;qlWok>{aL*lmk% zCqYj)%Ki8)ww@lp!EcuPE&jT<34-?PA5-?Ag!gO_zr`QldusUQufV$D{7GpyoWF9> z4d;*PyW#vd9^G*M(vyMf@2qw2?}>_szqerUk5+WQIGld3!dl& z-`ETO{a)~&_JZHr3x0nu_+!1`PxXSo)C>N0FZd_D;9vHFrz147R1x zNzR$Q;JLlv$%rirW#&0q*=Jjsk(pWa%BI&j^qNSo9D1qJvt-9u@}0Rq$Kxj$mk6Q1{%*Oov27oF$MoviFzg& z_(=vn&A?AK@Cyyxl(XExGYtNgUhp3nxGCpu11FtD&z%NNu}|=Kd%?-?>7kX&i=I<9or24Ez+x5`F&5z(WT9V*@|c!0$Bh(+qr;75_8II06CSdU$$wTa_~pIe<&0B8Ymw;RXz-6U@D>9%`?blyO*`Cf;Aa?e zere#N4g3)U|F(hu*}zRXuNt^1=Mw`r`2)OlBD}#e;HI2)25!np82Bi|KEE<>Q_f=sZpwMez)d-yGfw8C-IDmjC^8rx!fDSexNHfj znD#D$|An`fgpV`u9lUk&%73RnnD7vPCjJ*WvQ;E}yn!znfD9gzL%TQOuQ6~_&(nBo zNpdKb3jg~9k-_8b*B1s(yFlSj=f#rvhZ%T|fzuvQ_;VTew)$wmCf zxx}As^y@Chz5V*Vft&rB$bWS}a!fyY#=y;fyBPVy%j_+$e& z`}J!>j_D8Q>VrZzKYxUAuRYh%qK=2!oq+#EpAj@^@esf1pQA=ASmCCBUT)x~J{636 z<*zwK%kkoy7^im4asPxC13biU`e#TVbh_b+882G)I8-Qz)*yNW@1wKs9#wFu!*1pB zr!s#Ar@~LV(nD({J%Y0vDBGGio86kExRd-L&dUjz!j`m2MM4u!Q(1nBM^2=If6g7{ z>7`D}#2>}~^st*NJ;~Pc&{|9n$q6b-zsNV}5&4-c{~Qgwcp)3^JP)42`~@CdeH8~- z#DhP|2DsRR|BK~c>cNljKvsEh{M^5KWM3-!A7MEwJ^c7sOg$YQJi_bN4?OsvX`u1k zrW4l=?{of_9{f=@_Wd4wJ~=j?hjrr0IiC3+_23_Izn=Br16iL}Jot62|2rQ1IkwwJ zUYy%K=D{bho&&fYv1b|EbC?GgxpY3HNBD=bowGdn`I^n5f7*~9;a|<|&hp@kSWnr9 z3;%BBi+cDk=X`?)Ka2fSel9`ee3#|l;NjoF{6FyE@9?Ui0v8 z;Bh?U!AG#3GA~8WLhi54^#uPN=a2K?b6L&^4}OsCd8!BhiuKI$;v6@odhioi??Mm$ zH}# zp!kP+_+?!=*}#cES8?OteK2s^|DVJC$~17|-^%b>Tk@kAVxPIpUu*D_9Eo>L9$bFT<9ZK%8qcGx9()St zf9AojWV_wx!EfdKE)RY)kK+LYr+yt^JG|w=WgZ>z;4?Y@nSoP(cd|YeI`&vJVOnf_+|c|Y~aM7#|O|eJ@_#y#B;6(-$}yoOfztT`g4EeyeRtr zmJhNE4So{+&|s2cS&IyujUwV969H_@8RFf{D%#k z_@Cf7Dd&4>cQ5lhJYNO3`C{fc11CA}aDRsxIO%x-^UJ&!IqMn!w!u$wILTqyhx zGXJ?A{+oE<^9`KZ&EPM26dE|me~|lov4Io+6U<*^;Kcu9_S>ZfPW+?!Ua!)?iC=yx z^hyIK{w>Te|2_-#i}?S@^4EI!eS9#JpLG^~nV&a$_}^fD`FCH0Kb!3%zu_nLykRsN z$Ma)D4(YR&-46}$D{22S!H;eH)8aN>XUG|m5S11J8?yk7L>{fp>x?^w+* z=V`I?4cy=3J^Za_YW@=poaD<-F`jDRq|XlKKf}O@U+x`p44n8sX8v3QC;lMM$C(CB z{AZ5C3s2aA-KmHy` zJ-;?^;-`PCot}pbocI?of2V;H|1|FJlLk)w_c8wg5B?J4uNgSW`H=ni9Rnvh|6=}s z7&!6&g6;6BffN6U6Y#?0CkMwP{=a~6$G}OB+#?J!aFTNy^A9s{;{TGzYm|W#|BK9j znt>DlXx2~mO;k+$pELhi9{wM5zor>D@sFerG4SLYILV*E@nnvH6aO^kzu3TuznJ~` zaswy+tC)YOffN58)~Ck6iT_v3f2DyF|8kapje!$?8GV?BXRUz~e>=;+fpKzIb_HU$ zzUSc|!2H_`oaFzI<^RNxL#E-dYW>lJ=a6tbFL>~o8n*uF!7pY!g)dr3Pm+Hn<0pIY zYZ<41S&$y#zg1_gi#+(R8Nb4VKhAiI2mc4-KlI?AGyYo-F8BOTdGJ#>KD_0@Co=wT z559=;ajCi?>DLb#zr=&fA8prp@Lw_iwI2Kl#zvT0y(>%ERAVh%&Kge?CdGOB}U+KXeUN5$IaJf(Wtp`7q`8z%M6vkim z;PSbEeE&hltC;znVAuZ2J#xr{%g;N^^x$$|JlBKEeN>GHm*0SB_u%_jpRFET{{6#0 zcyRg0t)B4U?{nPw(1Qnf9uB9ViAU^k2K&LO9$bEHHQR&#jq}qy_#Qt0Ugp6o`CPfd zgYV<>-R&M+{vE}_n2*2Pt9(+C9b5buji&J`X zh*xqs9J+B{w`N%_tS=>O8da3R41}4umD#vzIsTjwX{GU%T|*Ue2WL5u#P$8=yl z)nCi?d0BL&NIgmCbA7M=om`*fn@@(B0evC<@5%noO`5S&C+hE_Xv&KIV*herqzi`| z=0-ABlNm`wQBq&hD}nY@KckoW;y;qMa(z!T)^x5vjpK`yi`^u@21HN&-^2ZX;1tbC z{iQf0dQ1N|0rSeF8f&J|J9+P@bKQCA`))nePvbBCJ@0WWFYi6Q)ct+%)TyMTFRQq93Muz2L2ROh<${t*Q|wSOxYQH;Gp^rdZ34E5 z>sJXQr_z6ckAUdOetUYbA017kzSx!Y@wQE}k8=A5NjM%lrckW*)+h7&@xS*uaGgf* ZgFIaxPgad-PxTM7{_?$65#p`?e*g~#pzi13jt1mdCxpyl0~C z1?^{p_P$`t9t?>Q(h2V|HZ-F%ht!K7g z8f@JV@WN-I)}IIV0gQcF5Gx8SjjattT2ra;gtB{-qECUgU)tCSi6Q7lQDAke73%}g zB1v++@J;#ou`dc@2V$S)w>)VFW6vMi@>OSNLF}Kge`R+Db)6&Yx2Y=+ImgeeiiVkOlYT@EW2hJ|h`k+Z^W@HMOU@1H21Bva zNW{14KD-8771Oq`Gt_zx!J*dk=@x7qt2q1L!M2?5D09nHTcLnA*s6?(1X4q7gZ~<| zU!jO9pgNI&_hdez>MDw=g^Hxtfu8wz9g{OJmXn&_8aZ7>-u!%UtvP4nHc-hFQ9RB? z&4LAp`^P=OyrMvA^ub_RK_C(=TO1ft(5ePE?_kh3`{4AAyL=m;0nj$-Y&}(ELg-$$ zOeXv7V4LS4d&0MAS`v&bLo6x(D~EAe>)ODOjh(*DKZU~9qCjNh3%*S|QNI;!w=NDW z&3-zh8xOVK9oUb8Q0pCmEJRq_>dv-loxzs9cBn1+DKAQn4VC#;xYzS60CZ-z9n5<^ zQk&nJbL+;BBkv&UpWgV|N#CeveVeEYg{_`_z;+e307e9 z!k4~Jx$0TvZ}s_9}55@NDfd(cXu6!0R7hD6Um?}xM$1j_Ardoi?! zfL)r0TE4boH-!dBHk{)>h~eG^BZ82g6KtFGFj-U>`#6ZUs)F{ZAXcWVP#NZ6L7wuPayEowiv#|Od|$@k4?=BYJ|ft6^IX)*r|{A(1Ydll%oBuX{Dp{LjATt9wZfM%W?!&v%%7<8s?ivv zR8NNTGYzt547s@zqKgCGg1pZVc?Zz}FwMW72tNlASGjOWy>HV-S~{V-7{attl%*4w zUNO~|k#ppVw!nMTfbZrtN=%I_TTBBqg$jwtB?9-50^l;g8pvICsO%K!%aZX6j z2fR~T);?ybpi2g_2(zsiF*Xn-(Q{O+Dad=*w|N!f z02Am1vL8yd)6v)dTMApA^n~)>jI1dv^91r+Cf#gDkJFrOc?$8d zR`q3Vz)MnS`Y9NZyjRWKJ<8TpbgUq-8ulm)L8A|gPhrj3tH+;;F^GCmK|4?o3ZT~F zedsq$HgEJ>K`fS81&G2St!YPZ`l7SbH++hvW3%OmtL2pK`_^%|I(Xxgx8SDpiu@({ zB~K{1NFWkB;rrztOv@p8Cw!qjYGIG3*rVru*4ep*I+c}J%4wbE<$U97zD?sH z(l#G4xHFK7g<7_;>=)wsP;2s;v1H19u+8e|7Wa;WTRJV-ZRgF!jE{c{>X z+UHc0e{`V(I!^S4b9Be2YJ@SAOLo)Z=6Uw03mPef3+Y{!*U`@HYU|)zs7*yb{CXRC zruB5ZT1xwzAeLuJayT3}sMH8)l^?FR;B-|Hj<=5f4AW=}3>X!mS_o1|7hv@! zb1?}HhtSMY3I0>7g>{m%{7t5updyY!@NtnVW7~395r{>#M*}+d<585XP znL`L0U95~dMQowHm%5P)B!r;J!o7e7SbP~o!b5IA-qn=KDFyBLlyjUYz%Y@cr*Hh& zx9NsKXaJ5TkI?v0XDNR|9#0xE8FV+H2^ms9NLfuoLb3gr&zOv)aZhlsr$6D* z_k8pP3@N#b;%yJ^)3cG_jzLPjIFK5|VPO}rQ0&bD48NBmDmm18zm6Qe`XI2dYo1L3 zSll#Bwo6z^f!XRALc?|^rj%zd`p`5gsCUooU9=t`&q<<9n-d+6HWCXc5}h}BZmOvm zY1!GWH1jppfb^lhZYAH60Q1zTY?ma5c^Pd7z4sU#mCLRmJF@Y8UI=ZmNtI(lce zMJ(_1jV~bfRY1aNpOR41*`XNQ*OTA&+WC2(H}5TgbI5T>=6svpLzrMPyhdAVJ?TKu z)2c%kNM$vVyzx@5oXft-e~h*xIt3+DoZJa9T3jBW`|fvK$c5CIV`pHCD#2bHD$8o} zaqY`n$85`Qc@O*0WE5j=>&CFeszipukSf5wRNG8!!VL|SZ1ewbPgm5uo|wV?O@f5+GO zo9{#|3S+$ptKkf3V=3RHmi)8JJ`TlB1V1?l>u#h|F2EqpwJK-05GD-M9wdwW`HyIS zVG1GWh6P~pB99+2PdQW5=(t}7Kak(@uD$v!wz#nDacIXHnM!FrcGiJjS|4#X+4LJS zU&jZ>&Fr#wIZ-UcG4%Id2o%~!o<3QgYK z(Ue4Sb-+ryzE+)hft4(KMDe?I1KDMYy7@=66WMFc^h!F=d8h5(DzBA7e|4 z-J!;#falJ1%$cj=dnx8FjLQBveloj5Ejb04T;7>&YkinAuVJoak?BomhGNeITl?$d z)XP|3vI(a3We*N5C!>Fb8M%3TeQnvusLA9xun{4}dFvE2Z@o>4=~<8IQbpQmR;?xi zQ)w&Raj6*L!6tf6+YC$sJxh?oB2^8=z6t?2LBcAuZVtL-ej$BEe33apI&q}K%{T<8 z;P)djqdhPu5p#2B@6&My;~{uOTaF)t`U^5-Ok8i^u@fzazNBNvhK+q;*}q&ZU*QNc3(e4;yHD*DDlfcEC5+g1lR1@v zvvl4KA`+;lIlBYmH0xr0sq!wx6{#fvGIVm@@4NW~@);`KhEkwX>P5X*a4`4>7Rx6p ze7Y9ZXc$-k&BxILWGKE3zvAlqsY|KQLn&$AAsMsEl2tN+^bwYL=yd8y!r0^VI?$t@)&%p=4JeMjPK#zT*2|^|4mFe-CDeS4 z4oWtouVdAtexMSC02yve2livt_y}XdnLazGCQ!c-&k_cvH_d?{CDz%L!kf^$e=ygnzLUY0{S|-vKvpYTOPOZxX0VPo199qNZkry-9vpn!m(Eiu-?W# zIf6oLNT1_rhOaG*WHVUy#O&Ay7rjmfP+6#L3XIyAkmN zsWIGKHn?xl&2d;vrr|&B@4TqPU9{r-3n$h8xTs@Ar+iq}8%ij!-cUl( z!+N8vhmk%I#UY^kM$52-k zsLJ~khrI2|mzakKe4Bze&&Ti(iE~&Sas8j{&)-Q|8=WfB>9iD~^!Mi~r46-3`eNrU zqJ2bf&xO0+b{!k2)+y!Qc+TlbZ<%zH9l01!J3WPY|BAj&XHO`?enSt){FMHu7a$4E z)hnlOl57UuSV8oB9(VYWVjyeo5`SG{_0w4>8csve&CL?iN zq|cndk^|`J+d!TKQ%+ge;v>+7gUi60z!WtDly7ME(PSaTsIusBN>Y(OP*SM0t0z44 zgffao`NwCjyg(=<{^196_bVD+o1rZtcNBKWh2y- zvJiRUlw+CtISVk3TYA2&(}m=h;e&z6NHHJBGxe8z8@7|-^puh&#%Dw&|26Ngy3=I$ zl0T6r4gmO+3JYFBHy6`$uYn+&?~Y+rp$!1)E;<;zGuWEE7fVebr0#fAAk^yFi>I(J zp%tu!Y!~z(3#LXfEf;;E6au2f6;ZYX4n_;`BdxfQ80f+KVw4*1jXp^>Zwx8_!Er}l z!ILG&c7cs1guz&k#$>^AY)Q&esLRre7o8C?`niniTJnAc@lcphfq#?Qm(5Rd3l@$^UZ0q-8Ftql^Y`;t?) zJn3(tlx_@CI&7g$p}5VeDmi0&U_I)SQz+cnWF8q9pXz}pianG@div^t+Mv1{eG!G_ zc$Z*2s-s@<`E=Jw1cXuIyZPZyzNSaq74y3jmSTRtC&=xlVie#?}CH4Pph**rWRLG%`T z^!sjU>&6Gm_7t{Ff~(X{o16--Ig$ovplnc2l%j7I*a!4xbw^+qR7UTSCJ`c`z*0C) zP2FQDa40?K^ZGX3`f+C`o=UH`qsQO`JUPU>hfkrdMLQHsTMsf=_5#jkFN3lo>239$ zK{wn62jSSc8#{9*QpHca!Mzj@*evm0bKak$Ckk5!{{3$B}wAof{oPkw9<2NHGw4HnQFJ9?K_Mf8R_JmTAY@iD5rK|e~> zE^bXddNokmuhc^)nZ?<(9bz8iF%m{Dt7#@ZfFZ9VF>lIb59eSb(CuKsfww6L^)!2LJN9|)j5Z9ptlorN@;Q4k(M4p%O+wh0l(`2!1 zBN7`(n{*-*jO|9dUJ*hMl5=d7pR?DeGL27~l-WojT*Tii61ht#Xv*$Y{f($S*@O6Km+ zOUd@5&8mqF>J+ipI)dj1M?X>rNDeDR>QdDR7EBs9y6`}ho`U1qAHtI6fiE`fsCLjc zaQqndXo`w$edv&Pd-ax%$C{`~srAwC!?P5viT7{SM@{rIE)_g-Slg?nF17#v1rBcP zjHGH!3C*o;91oWS^=A%(trK;5?DgPYI40ikIYj@LrMhA;_WCtPsTT6GYn~uNt`nDO z>JZLh#4eTPg$kmpWOfSxB-pB;!@+wicr%!cl#B$kQDss70^t<#VaCtRn ztEu5~DYv@3>ZU5YZVRK5CfkVY<4yA3N_upazKZrJ0j0msQ9DO!xDU<&sUDvn^n8?q zO#z1tX#1EXnEreNNUz4fAUajkUlKh;(_azo*K{Y*=>zZrt88MjG-E3!S2HffOwo)- zF+t7rQOq38Bq^p?GhVv}7B1CHf4c!pm1dGvm+Cc>s+fpo2H7>RV6|q>u&07qubDIL ztH9i(nIZOSXlv2TF#8rTw`k^kdlkgCXlAT^6PPid;c=zBIH9J3tHN|Sf&Sk%#EMuN;tkXZ>boAi6|-|DwCPWIms zf$Ajh8oVa@*8eScH2~GO{_i;GqYnCA2Yt*zzvrM&IOz8s^hpQ(frI|YL4WR`zjDx> z4%+f0?6e)U%R##xw8ugBanMN)y03%wI_Q25y1#=S;GmNo^l1({#XD}pwDp7XFBL14tl7AKFdL$?VyJ_=yM$Oa0l&o(C0bm5e|B!gTBx~r#tA2 z6s?}P*mEdxp&-{+lD9wjBrgSTj{-e{X{DAumntR{X*mN-D;?L1;Jlt{_Xy5^xJx@& zEaIjbMcRa-o;3gW;DWBrX`MZS3wvtlDzeV>N{?W1Pt|({X>d%Pi=M+~n*fu%OE9K` zA!yk@#%iXofAZbFI~gmsIv}EyYSMKEfpXy!2ymoH+@ zvKP1-!S}4@SFTO}J2huJt)XV@U%Q^^RmCti#3D=ZSz^A3`@dlSIn)N;b#8Mcl+)S<9@x>MFUEg_VcYS3I)1M-d}Cmx5Z2S*EzZKsDj-VZ%y-? z;<`srIbAOjgVy;CRdtpv<%cX9 zzws(Lq7KpcIk@FcPLH0Wv>H_}iC5Ld-!S;xUU`3Qg=Oa%#U?+&D4%HXll}ug*(gu& z{(8$!aN2m2zs#n^iY{ILpZF<;yvgUs%l+lpOQyzIt={CP8RaHlV3bd{^*LV5P4Mwm z>IO5*d8n3B_I+LiWMWqphdHLjtH+&;){RdNeF?Yq_`VP5uWKeFx)&sp}| zKJCZX5;4z%s7y-e{wwM{r|Y$K=z2XBdLAsIx-|~<583aFwLACn+T$JMc&iq3r&^o`(t1r+sTPuMgWnB&G$4zNSU(ESfnhQEM*J zfvzH7eZ2@J3pvPh(csytrSa#sQ#poIP&s9Bj z@Mv5?xQ|M=tuxXZoqfygs;^k<^R%C!HLeJ|XP4$8y4a?55M}Yziq=S&p>TKm5Mz0? zBucCS1qpI$oJ_tWBfPraqW`CrB+%&za#}`BU8P0;Ppe9xGZN&Y1bMe*546uuNgLo! zIXh*bJ*aOgP6MuhHDJJ{fUq_&iEP|+hUHF~Fks?MbF@sK z!nDhVPC}3SrP=P30RyO-jq?7d#dYMO`T%AjPHeKYfJZd8U6@8SQqF_oOceUkP?c1s zavNw@w=s|sfXm%>(#~*J2=C>Y^bun&xJ#&n^T5-Z|YFee|n#|#V&OHjC1Vl zG!iHtu&57}pV`OCPNR|`v72mbAWCr-0tvSfdDg8!T|?TZqLH(y?mT#<_{6Eo*q9v``rkx6sdBfs@FN^SGnTju2bO*pbjkz2>q&q5*Qk z`HoVs7sP!s!0^e1Tn`?m7Sp*Nvllr^p=Ok$6zph+<571ETg!FFW>_?4wJAE1EGvTn zuO2N7WIfNJZ}Q!?76|!i9GWlW?2)u^(<8SJ>;)ad&1KZK<_jqgw6&nFlz0_&sfmh- zLQS2?MH#(|jOU_YLPW?=99m#17CxB?bXdshI5c0#CWgFLqjkMCVx+f2kZ*BGk}m0p zF@IM=$yO#`PC!D+xwdEju)KvBQLGBvUIqXa$D`&nuMul5OP9(q>gpiaY#;>!SNZt zK*(hbDY>`-Omw%S$h1QTr5I8hH>5~NX%rjYCdIhd&Oj ziyOeiHl8j2a}iP_x~Q(u7c+*HLC9|~r0QVlTuw6`l>A-UE#W=dI<~zxKlj(aL*r!YSq=?uB8>+O!~nRzG<;^~br|70-LQjc`}tE~}=7|{_ydPLX#e5WRVa+b#WpRMnN zWig${ch%-$X5Mpx8T>4KG2f|n6VtzOVEN~0?G=0{xzW6rUc-079%K3?2PX6@jHw8E zlbM3}N-;;s`3#Z1JDJ|@z+PnffCHQ6*Y-vDj#+hltuQ}hP#k(g+@W7^NhWU{)Z_}L z+Z~w9&&j-XkX(pqnV^JeBNDHl@m%P1%!y16=p4RNy=ypjmpWqDd%D(h8sAAy;wytg zgs_85OW4>}afFBXKE9KfjP%=%QC-c0usJ?5@LCGHHQnJ}arI{o>__Z7@h;Y^huCG0 zI$W1#qGbR~oZd6-Ke z+*6QBz)H8VBma^;An^-GD^I+h!|T-o$GWwE$FRaNmhDXM;59{c@DXNa^I$4aI#R>t zDo~iU@jfgNvLz195%N3Esvio&OM-2c$efamh$11;B~6(NLlQE-Mr&9%xyif($l_1B zgnoe+Lv&$l^DE4}!FTK;LVoU)lm3fwsvUMMA)Z7?T1SFH%YpzyHgwA(NYFG+37Vd7VXImb)(QD}94ZmgVce0m z!ic*t)x2;#ZEJ~;Vug}3?YNHTd^6t% zAsyi>3D5V`N+o5I^Pq=s@={QxKC?sT&uc$n@^ikstu@UZ!bo~!TUR&pir5lgCLt$G zVllj0NLgUegiNc%DtNUREBCLP%8n`eT$AYfB%U<1Ki4FTb1MF&1clI3KU=(;Mw<--N zP*ltP>-K@?6Z^ovrb)d1JNAKn@pc_e>}wL$a{sy}^5enOetexUi{nAJK*)!ka!)Yx z56-3CR#S6_Fp^XwffZ76WjNsYx*qy*d|eO0a(tcGFZbtpPP`W1GV3j&%h@CkPVnoJ zgcGa#Vp$y*z{7*L*y6AF-p^{X#|7FSSeG%>Z2DoVVw)!a`Rb3li-&0Wy;542^9fAf zw@#SEJS-FU$z8T1S;cLuQb>mvPOUX(3-q7rH7niES!rJ!R6fc1WNiEqs02d1z#Q>- zf!HT^d6bqo7G!nY#<}AbzGF=mQW}Dp5A<*V$m(`_>Pf#m-S}}rzmN|7yShCd>?u1s z#2sp1N_w(xQAc;{N_w(xQ8(*qUAo_o@}0tJERP)h#3Ef7K_T}sL}Ef8 zjEl_^@^1{etp>Z}4Q4Kn_jaC;GZ|8H;({MDNNtEarp3KJU&xsZjkO#f_>hlX-~+3I z3Zy@Y(IM3;xjMBX-g_d^ijd;P9+E0?(;4auN_ZDv8=~4hcaUoKjKQPT=Re~8kkR`( zS+Pc%{yJGbK#A99@j)=U=Hv5PbkXM0B+Lc|@pMqggK@ca%^kvA#xn$RLcSP>u9Yr` znW_ohTH^I6kGcNRmwqt5gvV9JnLIy)eOJJDrA(NG3GjhtVO(s9k`$(Y+`KtLW;x}0 zwAmbDvM134O`XMSk<3_}%7v6!4@0&#oAu7+dduT$*#aS@K8{sFI#g}%rfL$aD37a} zE2PxNIRl^f6i(t%c}OOZctC+NbP{0-G`ldB+uIRuccGBdLNZ6Z`k+_081GtYw%N7R zY}|}v8XF1Y-SL=hzpeSN%t(NuE4MXEXQj=aMpi;cB3wO55Jt51@Hk2$Hk=5~` zk$SM={%%$%(CnzFTbxk0tyvgpV<4%!!=pdbhO?%XG(uXe<_Qnw+nR;>HiOvzh1?mJ zYi{lk<_~eX5+P5;p#?%ZI<>7^r|`tTw=Rw6E+IPaY)%qR<}n`9>|%kZ`0m0fSm?9Z z4qaKesf_l8F6#RuH#Z%f?iBnl)`&sMg*#SP@H$vj8fEOp1wbl~4FoCTV`nm*W3H`$a)-5-F zgJ*-Z)AI`6+ki>fA(r+v2_u2#Ji-Vj9#a*B5ij99E~Lbpk`qRzIOK%fo|xJDnuL*E z2}d^}9TB;&$(-z}5wnZ3=SXhh?2Ta0#q*O=v-%|*p)>h@CdTdJfFpMBG5L=Mjy<=d zyAw+9;UKx6@28|>15TuqZ!uHr(AJ6yF>QPXE|F+wLTonH7x6+L6DFV*amrz(adGlkw#02)Ko9atSl?*F7gejt>svim04FG$y`xg)=<}2R}sl< zsH+dxX69sMWsJ*&s!MV*=SjWHc_rc1k^e;n%POs`sE&-!P=1WuP#NWQC^JBk~l4J+##>LR2b7pX5Rtx-}i0w1~N^B|58xAw7Ln?Eyu(T$UTQR2E_@YuY34L?i-4uQ{8K3Mkg+c zPRWfu}cM5T?@jl#KzhCs&`z;{Q-=wD% z@eB72-Ysrl@!PI(gD1|)YzV2+N7O66D+N*IpF&WsEPC<2K(D0KRpcI;vH8Z0-jOSV z-b)u&x^o_>Y~PFm+dX6E%a6Y4eRN`nck1f;ZMoM~b~LuQZb zYM;TQ4cETm$~xoa=#6Bvy=sw?+NWhF(#`M|3Ant}g3GpIAbMQPsI;j6Bynn+;)0rmQj z_bqQ`)ccZm@6{X>w4IQ&G(fd9%_|z_Xb=P|* zc?Y}ayT;qzrx#7AbQE1Uo;?794|ZKbJd2*39|}kg?DCpGaCuEcX~5ddN(~Y!Mmu7_q0a6{=7*IKk2U8;=aH; zsIX(~(sebVw~yzG5*)-@_(A*I&= zvZfvAN^%8K?|%i-t`|C@vwo<808L}&x$kRwgjTo41KwFLwUoGT$S84tYyig0OdBWlvQO$N*k9qW;RxpHiXMFL-R`->gtdV)J1C}jhV#rR2Y3T4zP?BHQ#Ro^ke9;oDx`mQI8s$t zuH1<788vmwN^7Rqu0$)T1fDg(Ia_NqwF2XI&Kb!TXJ+E4Af~k-B=TqNc7i zVue?RVg0<4ISt{J)pb#EGFmNdR2^tUXTlJeR#Vz2r4{&ETEjSe_pG+kuU@*iqN1U+ zx@Md+_tB#Xr$p;ZmO(GnQ8$oARl|Q)J-KL{RZ>?`(HM?c^^|N`k!m=P@~2uA4i(ik z;o3T@8VR0NyRx*wiiB6xqmk-0VFVP0WJNu+mQ^h;p)9Gc%wlEK?}l(`xwK2&Vqexq z8^h(RDd4JWEi{Ala9+v0x>e3#TNSRZtU`9GRaZ2G!&Ws1ZvnDR))dba;~_ncOUhyN z3aboNtm@kG)#ETku)Smjf)F~V)|A#RpC4(cuC27VCAa|=>maZiF^R1C6khn6UrqIL zRi=7VA8D|{6%BQ@C9BBlD@x~uOKYt1QjGe%lG)H6kC*xN;WB53Q9d1E9xvB6z-fqf zZ3$URvlD^pbj2EqaKLk;b&-Vn5CW)1;$mLO{BXEjIO>R=Eo#gg%jz1!st4mrvP+cL zOB^AjCJ}0IA!4>f39F!03RaY^#yB^?1R6vY@36F?dbQP1-MHL}QfSO836(ZR(7$NH z#4Ad#;9S0x@5}gJW|d&BmS^i5Tu&TUD!S$9+jyv)7jBG{Hbjc*mZOEL(wdbtUh_&8 z)GotPQ@)TIvykC8V36T~x@bdux|XbrlrF0YOJrl3)ioC4E70X^IJp`fC{cm6oVp4P z7))6q)~I=`Lz#wTTC|}7^L09=U%0Wcx{f-m#)u{&B8|qeB<#lDK0k_3x zf@4XgYV*RCWc&>{6|ZhAt-z$CwOcJ}6o1(&3VE{AAk~)fT8+q~nK%v$w_1*P4i+`a zwBUd#z{(Q$h??tGty&|j`Z_3tX{SiI4-=_{}n&_FBy(%jZ(dFK2<>g;V6{3e!%Aq? zhF8^KLO0STnV2awuW5m?Dk>Z5Ej9Xjt(+0YI#^w1)njkKu=7N?qLk+>S`JrIWKjS% zL_!!*Hm!uZhb5BtDrJry;kb!3sukQ8MHAO7uZtpfEi9^~SRm(>qa>=9f4$sNqM?=;?Q2Z-O6)^AMy(msrcLmtFIa}GBC2~f_Ts4G zvYWDVGqQ3n(kRa4{2@ZiUNg_KSEt%%C-?Pk!D&5+vSIj7*Wc-7YD#LGYii1n+uZpn z{%?8mQ_@@d%uUI1HTO?RFG%s{rwoC_)D&<2fX1$XWi3T@^+W)7_4^i(+)TPQxu>W2 z+dNZK(r@cikdpPSr2LfJmcCb{?6Tb-^zEOLo1c<}cBZEIA*;1dAK-d5WuLtuWxqWm z<)D2{${~9Z#PLhD(ES|#(=~!Va*}8R^|=k`<2GibY<0W8KPcq^_kxsd?indN+*haU zau)-2ZD4RdK$zmbo<#rb>d~D10puh4X-~TTNiX>+sVy$o%l%Wl!2$Uxc)ry0MO8f3 z`<*?Ny6Krs50{%B)%0+=_3!$1DWQ*MAh(TUY7D{AC(LZf2e<@}ZPZ0BBiygqxJLT$ z6yaMLmkv>V!tXTjix}Tx;CmUr#lSNeUvJ>wV0^WKPhec)N$i=*c)cNC$hdsMQRJ^= zJl&9Azyn*pl17F2BjSpR-pWdb+{c;I@ z6XV5PAowke3omyPbJIh-9xgY2@298BZSnJOqY!U*8i;1y7JpF4D0O%Lbyp?fw)iu= z-Q@WrlihIs=xsNgKRnqDmsKxOuvwAa`+JANyZh(+j63}(+T8kA3x!qpd+;h_>nzyb z3%(opAdK)K7M9-ydb$_+zx0B?)C>MfFZkQQsa^R@r&>#a{i_%GQ@!A{u=Uhm`c>ba z@KoT`uKdV?T1%mWehj)N`NX4cPDuF-rjs?DX{j@eJ{rjRvUHrBTI95)b9|lc=$uU* zHT5CWnN6x>T^;81u|n^)oZw}Irj4`kl1(p2$7h7DoSGjhx$^SM=T9#xDaxOU3=#Xh zV5RXCmVP#cei@}p#-)XpIUY&yc{zSKm$Y0<(qjN>LnY_%9)9{mz3N|nrFT>C z=Rnn!-3xv>{7sh&|7msc<3C*s4P0`AH3ojS7Ps0AT+buR`o4kR#_~HEr#78-K4Hjj zVELB}oYq6S-Zb!thOLtZUe37cC}`;~t30}n7h+Q17KpJ3pV7{82h z4|r#P=Nj^hS-#A`a~QwQz)2Tfs|;NFd!vC%f9a=>>7pCiB=&DMaIt?Rry?Rhj4I=r z%DCCDLPI`Ti(6M3_;ALrG4R2R*Y~1-l_4*2zSY3*W<7V4fw;te!Jjv9@y`JR59#XG zJB-sU1OKI6{NRncM8C+7W1QqE_YwI#L%v*Bw{9_T8TZWwzL@3zX5f<;m!A|Ad&V%H z!dsr;1&m*6;9}1l1DAf?#kkq8&kcFeqkp75;eXN7%Bh8^=Pur83D3fR@!PA6i~WAK ze>kTiBu{-6dHQ)Wx;1cJb8aVZXuD+Z~ znf9N>ILXo4F71vpP-fz-1o&mT_v&IWHbFbcKOaY|&M0-~}4C zZZq(5#=mXg;)f?0CqHE3zl`I*4SBI&k|VKG{BQv$O(s6pz-7F?Vc_EDi#W9wJ-4y_ z6AV1U_-_nc`t>&h7eD0kSDwuNu3}u;mHysh;L_iRdchwyaOv+K4P5&ByZHCXbS#Sf zdl@(F{Iel1{W@ykV&}lY+ELOk!G{>Q*g3+$#m)o0;O`i?=)aP`awYBhdAx3C+ynk% z{Fiw9twa7o2mYc1Pj}$Q9k^3IpTC$d?XE=~y5>9Zi@-~}w>WUJN#yTx;7<7!{3{hC zo8!>)Amh}o)6T_wkQRF)D5tBX7yMQOmvOnnz-3-M%3re-{bUnej~n=64O=PvZ7`89 zXFSuuB@XKtr~W$k!EJ{89jxaM2EKvurwm;D@SK4MSpH=Lm;Mgs1BU76QNwgavU5EC z%lJ-YT>86~^?#=q{5=B~Js%qQVAj*`98HLRYM-vt4Ln)H)#hbKJni&d(V)``e$tB`JPm_gaGtT=ZXV z;G%!Ffs38H3|#v4yaRX6(*`~WPiAusmaYT&2%T>tG} z^xS30FJ?RMHE=KE5B8$xSBCrsmfvCE#f4)|1zZd|@v*AE(q4RXHn@Dv1k9 z>jU`z1)rlh?NaiDe@Gp{#oKipFV%4Tw}5T%EUHRq&!vm>vuTQ_J%}!8_Ze>YQVqxP zzKl;d@cS7L8Th-*&o}TEcEHsJekbdZeuzDf^Le<+kUz-y3IpH5dR7~_d_$tmz=yjv zpq~dP{P0t9Ag+7#E$)XGnSap0khj?7>H1G(^|H!~kWB>o!z!|pGpI3!X z#Lkth|2acmo+rLy;199i-Zt=u8UMh*cQP)MT-tqt@zdBJf)^f5Ltk zZ{VB;TayetpW`-Y;J;(O$iOpr9G4onj8lh!Phx-GZ{WkZU)v0P65~4!yp8+yR|EeQ z^Zzh#dM}->qXs@jp^5ca{5+fGeC!Xw<+Jm{3_OGFl;^P`e~jBrH{|6@OBWmXFb>2^ z4SXg0S)SjD{zjH7GURL7&m{&vm-*`qoZVo3)4+pl|9S(jXZ$t;pDFXvz?ZRq?l7k`4HOS|iNo^CbprHudFz~AA1?J)3rc|4vp@FwQ>8~A%H|2G4_ zk#UI&@y`?<-wzG>$9Ue!Tk|3>`A{;~6TFUj`R=da$5{`4aleay9%g@L8TjjL=OhDv zjQtZd@Gn@t$iSOreKzo~xSur!zKQj$Ht^AG=LQ4sWPXc*pU-yQZQx5-&jSYjm3E7@ z-M}B?IN4?3bGcv78TfL>C9f3!kK%qEHsl{-{Dgs5@x1tgaWb1+ww3K1$mODcFzY#o zago21C+*q&b+@*F1C4nzJGo?lNI@~qyHuLjF_$rr_6b;whf8$Y2a@#ej2~eEAcRv=i^xhzSgb#b)kXRa6FG=T>7P@EvwLw7d=G|+z(+n|1Waj zG)LcHd&(U+$$y6$!d30SNxqfkBM#gTyuS-CxNb6VId^X{@J%fL9S2VO$MAgI>cIWL zf6ekga^NKY8QZhXfs_1s?9Yc87r)6fwHFMW-ov2lBZnT+e~(AO))$8S6dF)mX?&OQ zy_)6Eb>M!;J(2oa95i9xZX;B>x)A*BE#i+jG4GCp~X)zt$T#mC?1?z!$QAE!$Nl}(z*9N?`|&RZQZd={1nU`U;D=d$ssr~!{us;8F>v|4 z?j;6(5A$UXoZ2m6J8K;{>A#8}46ifrEdE@@O%9y&RIr{l2TpqAb0N1oaFYK4kIN4o zILRmT=PK@V;3O~m*DoA6$v?>QI}Lm~f9_$o11CN2alAd}z)8=uEdLh=PVzIjUw?Dp zBtM@w{x=*r$sh9I1=n#0?gu}TAE>|Yz)3#J@%)7YC;5XcZ}T`voUG+>Pj=uWpUR(0 z80f%B|0itEFb7WZjVynj11I^RJT7A#ILRMi`3VMo4}V_aG6zn2Ca|ApI&ji+oZkSu z(t(qF3b%W;11EVOzu{2gz)5~K>%Y!{ll)MAzrW6blYGR37hG!`xF7tLEZ^+FNnY0f zTOByb|BU4~J8+V(;&Hsofs_23EZ^b4Nj{z9O8#OEjW5X$<ty*Lmjvu65nO{a~UTw8WQLUW&iw==%iz^D093D-%+WxT#ijo>cIVw{aD7=fm8fQ-jeRXNj{T5Uvi0oS1~@(fs>w(cwLo!L*j5d%g;3A zCC@2x;MA`C-1Q;{PWp3seJgX|B;Ps=FSz7SGKe1}zgp>#Cp{t7v%$b8C@q$CyMasI z^>YK4yyy`Fmpn)2f!OmC_Rj%B{$dIiTyGh;ILVI~ffrnVcHks0`Nly9?gxG~%m3Yhlf2{`?>KOh|0&CVXy9u{q7c`o z4xIEzzTxJ)N#fxXD#Yb=-~>s&A%B=b5dL?Nzu4xIEzKCsw<`+>jB@}&-(kuceOTI@k;Tu7S(vQU28n z{*i&7&ExoKFSvYRUix)D_t(ScArqJVh|H#ODJJ7_jiSN8C3u!*tqNWz1g~N|iSMMJ zw>pLJ@~QOjP$^vIAL()8epRY5CthRVhnU}Q;PPBc-k&EO^k1G=TN#ZvtiUgb;2vqv z_bQy`$0?2WW`y&y2ufeK^S&&++)37XjR8YC&H8t8{Rf=FEbD}_!H`Z~7UM-y-|Vm0FZWA( zslSceH|q;8_qkj@-Y^rpxc&g1&r)voKZJsw{C{YZuCa~t5Ar`PDPp(y|5{+CPOACr zH|W)}wm2szcvH5%2aM`n!v~1Qi-=2HX8q+T>dF2s+jX5FS0(#t%`xp?56sjF$og{` zz3T5KXiC4Dvfl*UQ~L+G{Vc9b?bD+Mv;ED$Or2EatN*h7`+BLLQBGPgFQq}vc5Ca0 zz?Jc<4pF`9w+Jqe+U@aFZ~3mt{h&7_e%xFrLS`TJ@B6Dd!o9+D6S_rsVDcx zxxSRkJ%j5DFL$XY{L3H+Gs4u$;`&RC3PyLV7f`n+|M}T}OHoc2`H!Ze)EEEt)Hca) zSxK+hXL(gsRlpFue>j(uVF8REw=DNokEw4S*U(fcxAr<*lZFKwsCQc04Fr{;b}Ncply7hgi?||B7zg>A+#=pLK2#i6CS26!H7pVKvD0VxwAVO zi=L*;Ir`_j-`u(P&Yg$;o!y%{dscc3gUMpB6|5{tma)R+W!%bPE1SY5v+(Bdrtrq_ zhK;>l@yf1aTN_%tj=BvWcOBi(aK7tkPs7=sV~K{Yn+KoiIP@9X4cvB>hp~Zm!(B&z z+%njG^rfytKQaPySTgYL;7~X)-**6>6MUz;4h5 z;<-u5z?{Q83h2G`rNC`(fbFjMP}jh?zd?HSz$}0GnD^#E_dmLhbu^sqdg@K@(wDjh zmNgFrY6F4Wo&fcZqY&Hvh9%ttvs&hz>GJk8wDt@vy4eTavCsK#<9Fcjm*DW-!JdIh z%^HX&ebJ@(m%xM>sflK(AR~-)A`AlcviQx|86C6_D@b=G#hcQXrOMenLydDIhEVA_+b^?N%nAN`T zFNzO|9G!$1e>Kwnx%&chTG=0M3vUf?3vUmbPxHLV%)H$*JUomE;pO}_9hHpXR5Iqr zWyi+hLoEZa3}xZa^U4yCy?*EjmEq@=M@T**D+DSK_N^twu7}pLYQUbK)6K+ml!vI+8sh@GLC?7LI^=F zoD@Qc3l9sSnG25!VS&*EeV!D;LLS?o5Uwy>@N=3~Lp$@`<;QB8?<5XVr1AlTgdfD= z(lmT026Qc}@XrOV!haV?<8UG|?D4o}kj2^L>|x2)u^Ma&;KO%~fxN)23J!Bz;r~-m zsyqcMwWvPkPtd)9x0K=060DdJ1GRDA1Fd)AZvv})U3RFLi43huxte`^D|r39;!#w- z&2z(j_?sqq$(=t~hM_WSF2j}>cm@xUsU0Oa_DL5kRQUJ7vpnjtZ+O!{aDQXpQt;af z{!ay;Q}8j1g@P*;>{oD= zg2yVjTEXKKJYK;y3Jxf^R>2b#JW;`Q3ZA6k$qJsL;He6prr_xco}u8G3ZA9l*$SSc z;CcnmRq#a$zF5JRDY#L=^EjS}3(}Z{Pb~6qH}1I_PVTxKG$Ft;2_F}T;gPLUoXnMH zV_&0>1Z*?5Oxf)+V>V*Xad-_vn_SIv+%G(QMcSB}W=1{k6f9GBva&D@8DlQ)EiC^R z@uHE+nt1WZR!wXe*?NhLN%*}~im;8h^UciFjS0pjHFeeAnwd2djER-CQ(?eUn78Jt z>Z_}}>)@biVAa(tpdAi5f^f2q2>=TR0#>M1c`3unUuSr0s;jZD0b3%8vysRhTdnIbUK1TFF z{!5h}*jRQSe}O>-8En~PTsLX3c*zuj2dI|4N3$p=$zaI~EhfL5#q@<1)4Ihqlq8vN zHAczFgc{7!Evo8Y&UEVcF@2Jvexx+TQQfB^j;4T@xM)3c@ZQow3yH> zjwfOT)v%ByEQhw~LPMK$L-HIb_qt$N!zrWp!aD`A|4WORtH|B1>(_&_hb@P^8pfwJ zI2?9Xpgs$3m%iJhW%YVsr7Lrc63l+|!iG6+>5s(z$r1n6MbvBjG~5SlV?) zsIXAJ;D)m4xSeZ#r%w zVI_n8c>Ch+Em#gf7%n(T=LG}}4&k4(v)3^#+s>pNSF~lLZa*Ms3fpN8;Z;8Z4173^ zz{ga}&P6k5l7CpO5=n>jdcR_LtL|Iw-PPwE=U;aDVdn99EBtPScf9|g*S%vQ$cBFj zKCeFH-}a5m4}0bXx^G|G1dPYOe9NIzn-5`Q#kCd1E!REbtx9%Zm%6)q^>v$p^&ZDZ z4?eiK3DF9C+>4JtEH!KyiMmnLxK$PYz6x)ZKk2{7UkB|T@7{lVS-AGsR}}sGy}6-o zPZg|)-p;;t%yjzmwi_!Znc2P8%;e)cO_xQ?Hai;MX}P_7v$1@JK|UdeTmv*sE0ghG@d>&RuzL;~J5Uei;^30p} z6>Y2OtI=%QS`doo6IN)WgDux06Wkolz{G`|qP;7_L)Z)<n+zZSW6OW*r$;uNY2SJUnBuuW%*96TFW){~? z#O#SWE<|1|2eKx*hMBN@6D^`zAgYC;S|q9~plif(TsSK?$RN>r}R@jBa-A*Yc|%mFI`%HW$=n%bA40RE#|D{DG@G+Q9Ith9Nr?D7B8xA zO4T>5T~OZyYkxVsOF*ZlWFZ}gC(KKHXH&t3ofUWUHfY#zg3-ym0OIK2ag8{9<3-zy z=QG7D#@Uf~<+g)0n1%xkriHc=oLsP#Fd2&%;c->udmr`(sNlaV+FW@2!Ny3zsmE5e zw_jD?xG@I*j*4PrO$&=$YPqpxNw9g*Ji+2?)g*eiGWJE7v8UFUIj+)w2fTW8057jm z_-j~OP3`TTwwh_TdE0902YhWcjkk^o*EAog2-hq*ROwB5#?~~4YZ{>ult8(y#=jCi zpnp*T7jRMi-tcJcUVQf%rFikZW|ZQk8-BgXE8cQ+8m#bJ_)++gub)!ED=vejSgO5@ z-zb-43A`76%fOqw;!aemm1?iJ;w{M%c;P}T>Of41dq%_C7-2N>e4%B zu&2F6{!e5~ewxEKL%hNL48BgmA~S~m>5dE#T*>e!T-rd5(|su^%E%?Znx>Rrk%6A% zBh(*mY2KHgJ>)l|@dt^&UgHPJ&VG%5p7MEI*4!B8|V7*7md4w}KdABl zK;!zp#;*xntkX)tle@FVY8h?QJsT%(Q z<#U$C|Cr)z)cEg`yinsOP@Y$4{CCKHx5oc~#<@Y`e@%8wjenT*zpC*RCc8o7=hJu( zXuQ1sy;b9%CBG*${tlA=T;uO0`;TgTg6#ag#xJ8hJge~$;(w;`uao?m#)nA%zcgO_ zYJstjHU2V+M|@*k-bXKyUM;oDb>*RTK1<^}$#0{^FQ$1}r11+VKdl;{CH)?apFtDZ zr}3xAj?Al!^RGy+py~T)T>CX%{v_%ajemmt-l_3_NqIP_@n0wYyBfcP#`UDe|AzR} z8h;nXc}C+eCjM28f12!^)%Y1Cf1vSi(R|5QXPLJS8t*u2m;BY#f11Wmq473o{H-)E z%^E+M;+N}P+FwiYcWL?yNPmOIKSJ^jjeno?Ga7$}?C;U|@f7D_jlZA9dxysVmh|t@ z_*UW{)_D0o^ti^qLwS?$gE9|CNbjeb{@oLW8mXC*sDA?fuq;t{)W3o9*{1NQe+HGI ztWtQ?KSKH&G=43uhn&W*qj>gf{NIv%MB&k|_*EHW-_-ad`8}!e^8M`F3XgHVOMV|w zc(i{VO~T^}kNP(f|Bnif`trT#X@y7qpObz0c|y)3{zwSR3!46NL9B|qCa{c=#&MNxwDdU&tSdGG?{bOW*n!=-f zIlr?N9`*m7>|dtvsQ)0@xm@8<|4v%xixnRA&yhY2i@$$L49%ra`uhHopF4EE9y>w7 z@F+wsv!Js#3-_B)ySAwNC9b)hvlSmuO7|Q>Eaja$caV?$Y{HEJT;20A*2{kG!f zgff@*r;skx%|gRy{r{N%5)ytrD?3uH>-Gab+W6P~f#@Ln6^x-Q-mjpqLV`ImmsKi<*l`5yodZOS+S^75~=pyatMdFfx)C!k@p{?E}x-hA1S zYS~ZL4^V$ijeRID0<{L&Pty4QjhvPy_A&L}Ar+~XS|BaRiQc?v>AFq4PO;DDF}NGLK+CX)-!gd#$w}=giE3p4#9g4$Bf;EHPhXHAaQl;m^vIQmhmc#RTD7?px+t>T3vO-d|cD z$ox8(c_Ns3*5CV1yFU~3y5B--Fmp6h#czG6pC~Fndhm)Vblv0GjlYMd6GK)!g~)`z(zH)Kl3^&)2Q2t$MR+K6VwyT z?!)#*wnV&vM_rQll+yoZ9Lc4w``znkH7a~S|IGnZ17h4 zfiSJ#Q!q;!+gIZ)RaW=8{Ls9_bLLjmg@1d>TPnG=nfHRwQd)zSgMFtwEqFK<{2l_C4ejqTlB!$a}`$*YK4O+-P3Bb$wZGa^5PV83?8}qsYxNW#^jtq1T=4ZiZUuUO z<*KcC-gEN>0|Ns=h^rK1^HqH0*?KFCRPhf_-$C#_xP7GzCAhu8JIUWSQ^pgB()ZTPO?kbZzFQqQK|$}dK;$@j081UGx$h!r-yg~Q zk#yl81WTc{K#xJ8)dS$`TMV%^cq=mv-kKUP;fIv(hd^6vp{||YAIR(vf{$|o)`7qW zzg^sS`prNX2s&4Krv)=Fy}hAzN1*SbnV8pt>V2+UJP7(djVF}jP5%w@U%>g6S#r|7 z<^46Df?NQf0io$h2)uDmf32tSX@A85U*>>kYY+4fL^fJ!mU;EgRHkuY*KFHGIl2e@lO9M1 z)7Qfk!hV2gF`Swj5d7PYS9)&Q=h-?N0t3@0Dm`D{>#6;qa_e!=wzC!XajRz7xYdq7iVcLtZ5m0#xFKzYksTW-xs{irRKvQDe(1P zbeol)f*$7m+TWLY1=g56G;-+B$bqxe<*#@={nBHQ1->D`G41btvi-|f_*VL^@U8NN zp75Mm3A<*4caA(NV3D5ZIdTvJz%`8yANlc#fdLHg$liYp4B%qp^6tg|7%2ptI#Ap= zhRDN-{3*(llzal^LM0ENJZ&^wz*P&CQl(f@nWGekR4SF?l8Rp`Bc!rKDLGPUREpbL z4<25rlu_0uP}-G}Cj;zON`X{TN*QNG!Gmj*GSQj|$|j|pY6U>qqLfM2bzrSmDW_X_ zir%1OJQOYdqP8jD& zwPIX%$Z445x(9<)sk|3OlK%t4rD^y!PEUczaR&g)asLXmF*x_=c77EIh~jKY^m~ks z7anYqYr=K0g}9O{HQ6WS9QRj&nfnS*3b0Sk^*Fo|Z^()nTg*KTeH!ySV4Vs#*s&rv z4=ULqcM2j>bQj$UEF~6a#geR8nib3JMLY804zQ5pj>9z@!pJwBs{oK8j6AH#M>P4b zn*6pV|4ozM)#UdyxnGlyY4ZD;{IMpV(BuJ47Ot$HmL@wi*{R7cO&+1iIhvfS$!<*^ zsmY@>d9)_yY4R9N&evp*CKqV(SWOTNo6iuF>$rCmCR85|w$&)qtG)mP2J_1Hc?u%8M=cyo{%rNE z!DK_7%B>S(31OYh9xE^YDfNpu57`JlTRnF$*-)qL8f5CT)ft0*{?g#S#XPMlq7okW zROPD>cf(MZ!5KEmTIxJzEfsddebCUR8XRyJwQ=mQi8}0b=VTjx3Jtg0mKp{(Jg6F6 zJKx%9bU8?4Y|zH|6`1-n;cE>16B=Tt&-}Ky%zUF{g3+$O~Or`A$vFcV_WC zO};-Ti@%XGh3$+g&%$r!2y3i$PX74O&ipC)W36$y1u#txuNXagK0xpgMETA!9Ts6knvmmr_#n#1>m4D|>4vfc8Dkt4m zH5qM;A7PK`fbdSy)JbscfIYX03tJ~<&7*p1W{U+WDwEDk`sx--I413^f^L(!0j8)} zpeM0>IX*n@P8kG%^L9C#Bugx1k_!Hv64mI*5#kWRvp{Ao&0hN*uJdj*6KcowMMq~Q#;Cf7Ij;VpTkxY+j`Wt zwTwmGR?`q$zm*?Lgg8pILzM2eW%*GDQ`Vq91Hl(H1UW^jXE!VLS>7%5+3H@Z(HyyC zS4T*aU%7yc9F|AQk8C*P5*Ei0=6p5bQtei!lC04Mw(1z+*+@*JADEFqsR0f`-hB4x5;V$&L3%@9v89qeK z9<3SgT2r~3D_m>22IBXL(4kmEJM?}aK8?AD0T1;iYLDLKk;4?I225jnXYxUS&`D<;tDxmDfLK&LP$dmhtl=7E3g?&~WYcuqjAWLQG{~4K<7u z*s$}4o}8%+@je+XcJAoOp+<94r~n}~*V2mpA=M5r$TF{exH}A8^NmASbEEP;SJ4fQCjH=JB}xJW*!n? z4+Bd?|GC8#HGP^-06!~OBE;ex+Es9$H+z|LgijWn6TVwn;&K-G{^S%__v~hcH>Oi; z?Agr<--noX;WY z1}oXXhpfsk(K0Qe8lG)gRq^@WlI_Q$*6+iOgF1oINkB5&k43HDuAbrg zt+iLg6`Td`XNfD!Uhp-AESso?=vd@l5Z${&yyOpI+q3;xOxq5u9O}SI;@cH}{<S4BPSgp^n!R->w#t#2;-Tb1Z5Od~b*Y zd=S2ub$~_QTX0<3!;r9->I2zcEdIfUma(Wg@bC}^nDpOvza=at?F=j%ngNcEy1{cD zNb1D2pT=Yxk8Tr5_$81Xq8bhh%lbHf3|!^=EvT2IlZld!Sfn%E5-quA&IO?hW)^jJ z#M0LkwZ+mU%^j(vkd)4j=90EZWGH1e_f|YIB}(GmsgkaaNFtt$x28%G@$P7>WM*+` zad`=tx?pBW9rr7#3q`L<{SzJFOSQJHa3Xbnv3w3lt?P~^i`(JxT_jU2EzwqxAzm1z zBd*}CaH<_7IO~BRK@`^|L(xQ{vm=>OEMKBS(%?2-2ftWG6R~h7+J#%dqG(qUc54m-oX1RAbCpI?Cy|ig_ThrX&<}WX8nm2bv@7$)Qx$~Mf!?kI}ruptmdpFMm zKsa2^H}SF)FAqD1D2E1Ktgq~~tuQ)0`7{wBv|lmGs;<==M%#(($XqgSLC1JB`1 zxVJdRyBnX|x_sX9UO=oINB6j#{pn+KFAZG!69k-|)DNI>zoT6?p=T-9E``1_8<9wjUoqE$byK#ZDV25KQEZ6$l#w8+@Y>y{W&FNMV3S1WIj7L_7Qlc(Y zl?X>xM^p9dx|-viIKwcjk^#(6G}a>8!|TI|7GN$8cSV!LE9r`*N}9u|NP9^toLrqO zNw$X*(Uy{6eJBx+!_tkXW2s~b?29BU1=+kloro4)74GVYmX}20uw9lWv1K75#mmE; zu#`%Y>BO3jHQ~;ZWFi71*2FtI!wDL)t~C@(#MdT8vZF257VeTxu7y<>m2ReEh(}ur z@#peTYiGDE2^L!7sZcir7;cNA`vQ!FlL1(sZP5e{(9y-#Lk)?J?#^g+yfYpnECkzR zHTWnne|5Fh&;hd*wY#A8MbT7yyhWsvsdzUK7Iem&!=1IUH6qj<2VYYy@ih1Y8Bd1S zC{J5E1>EQo z5m-(l)CJ1~`d4*^W2@^^iH=yC99m5aG{B;XN3z~@r@+HhBAg0iyoFi(*#Uwuv7J0$b)oub zw1u@K?7y;d>91P1a)OePcp@sn@=#d_kJwm9WG7lKXUI1-!fFahvRqEmfXY8EIUJxI zV-JRtDTpJ@ZpkrJQWlF4?1+{!Re?9Cov*5ys+t8B>Y~XM+$0*}tD`YdSL+J`wlvlZ z+qz{L8WwQyL#6?(kEav%o(Qc;g_}F0yuM(0$6>p*0u81kyVt7Ii3BYF+H1NK(PXkC z4nwHp1=l=8LKC1SGdsa}9BIV5Xd8O54mTh8D&zqt_rJ`vN{31%W)b#&I@X@J z+Eg;#B~sC@ZV?UHM_faa*JWUFL+ygvIvB17_NN`++Gs~xdrHmWC4pdVs2ff=Ak}tt zr`F*VC<542>lnR-<3`ByR~E4cfqUp+Kyv8qcK!WCX6TLpxhIi@4ozFy5Uo z-l7gjTdd8OXal7_5lKWb$G9BqwY#{ZQ_Yk;lG;>Bz6Gc?h?}NMoneq5PLDb+7DVB2 z=!giIqz-w8EDqb-U~#lfO>8|Zx**I04IDzR;f$cuSdOVC#`Z%_hMaHeqsA{6a8|HJ8m94tU;%u*6xl7TwyguRu@q!;t60R;M}E~ z3htsB>F1zZMI@aFMdF?5F7&e|p5i?(Q>X84IBj7AW0EeIiAQOg4rrWYyyeoC#?u-W zbsHSgVnKEFg@x0WHp4A7ts*NrKP|Pgjb(F+OJ`13sC-A-W#w1O>p8<=1GbZA1+T)oa%{jNQ)DnDo;|J z{Oy9#=2UM787Mq}ijhMw1f1$+t08U9p>Op`j#J=k;6sa3z2h{b!3i%$nMLJvxVYr& zPJ_DO+f(DTeDa4E_)+zwqZSW?&m9J@83qpwgX0%3@{KO2^>QUBC&O0{gX4DwC*$+s z2cKGsgVklMiqL}KWmUdl=(0;LsjqDaHTbIFR5qUT_{mY;$Ly0G9tE{Wn?Z-4daxLD z!zcv5u;6DHd=Cg-Wt9a#OkzQNJp3_!F@jJ`K7SrZ9QP{oyO9jV#NnL}Sxo!}4W9rq z+qq*H{6B}mAJXuNnw@TGQ%74KKlR}*VZ4PtvSVEEK7x%C zEO%fo;9T-Z7zH)%mA?{^cM{_>=;I~k1PkN*10{}y1>LegiGn;GK`6+_KQ5&tu$>dM zMQ0oMCh}*#fxkg|t%2W6cJN%r!uC^Sht~&X4Kne^fQwaqXvZpD^&pC~v$D z+0J{!`<=o61C4vwz#pT$9W(GH#OE6r+rNqY98G>PK92Hms(~LOyIuqTCgs1(z{`j~ z-@sp>aW6IScSvtE@Xe%04IKZ80+xhy|@@)feCjNs4 zeih|^kAagJ@vMPwp@!ECd@Rqef#;L`zZ*FJj$~0kp2yRPpKsu26F$YjXAnNkz#k%g zmVtkr@=$Hyd}m*1;0H-xX5ec{Z#M8en#Y)drz!sL8+aY%llML6;Tyak4gMa&4;c7n zitA4Xel_Xu82Ebf=K}+up_Zp`&^YYRWa6D+;D01L(+phwg9jnbH}G{dU-J#Tj`9{T z@MAP?gMqK7yoC&$+!x&jUP*qY4ZMT!%?5rY+3z#(KahUAf!|MdzGdLgP`p1f@ZXdD zUmEx^!uK0^E!la+z+WK#pA7t7!vALAH{s z!tXWkn<%dD8~6+(r_dCsIBqYB*Al5r2w?BcIQ;b2J>Ojr0}O3=K#AOq$1;8jk$05Whmhkw2dN zuhwwnKTG_}4LpniLRqHaXy=ENmn$_K?c7HEsD>l|A>zk19QiZp1AR)vk?*CvZPak& z7ma}nlwJ)-{vT-__Gvisqs0H3h9f^h`|C~(NB&*JzgNSNe+%*N*Kp*&Li`6b9Qms$ z&p+32bSR}=p^4M+Za6z{7Vj{F;m|9cHb{s+WAtl`LilKAgv zIPxDR{&5XQ{wKu$Si_NDNb@@aNl(mp`IThR@^Y=dO241b`VzYrSC;ScrhwtxY`7Z#;1|-l`tmUN?+pB0%ERl! z;D-(T5ZQlw7`)%WbIAYW!{9W$+;=QvO8GlUNeA(avyj3V-A;Zh>FjMR9X7DT)(uREi_X)ErQd(h_Y>w}m=lt#KeqIo#X~ z?>(@FzvAmm_>C{t7DZFp-tbmcl=(2eD2~Lty6_c>;u!p*TMR$^!S8hNyB&3kwuf31 z_{PWow-kZ_%$1&7v{{K4DEzyN(z1DH9sk83F4;;3sD70W7=CwdJm5GEZEu0!p=0?X z{2@-a34~P=YEXi_cDkXX%d^LKhBR{IDW={1j5Pk_wY&bHx{_upYwXMvC;NhG=4WZ phQGz(QZ)PH_A>WAK%$W*WD_b{G2=&{PS*bg@_&!k7e%xG{{m8uB}D)L literal 0 HcmV?d00001 diff --git a/src/agscore2.o b/src/agscore2.o new file mode 100644 index 0000000000000000000000000000000000000000..773cc7f6ff78b640db16bbf8c2012d45c82a64fd GIT binary patch literal 19848 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 literal 0 HcmV?d00001 diff --git a/src/agsurv3.o b/src/agsurv3.o new file mode 100644 index 0000000000000000000000000000000000000000..2dc0409fd62f3b9484ca98ec11c4606fe0f00790 GIT binary patch literal 29984 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 a`E$LLiVuDK7*i?x!xaCqqNzl>{eJ_E>*bvQ literal 0 HcmV?d00001 diff --git a/src/agsurv5.o b/src/agsurv5.o new file mode 100644 index 0000000000000000000000000000000000000000..14f67cfce88cef582f4d51f62a898e6127c23879 GIT binary patch literal 11312 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 ZN$vbW4vRj1jAs{|%=j~e8 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 literal 0 HcmV?d00001 diff --git a/src/chinv2.o b/src/chinv2.o new file mode 100644 index 0000000000000000000000000000000000000000..6887d3b684c22034818bae4e9b856ae71e4cb9d0 GIT binary patch literal 10728 zcmbtZeQ+GbmG9YINn=ael_ev~HXs3p$bfbwVLMigjaDC6D@($WWo##hhtX}$yGsg^5S*ldBz2Wa?ovr5kPn*=C->o`E*xAESE}HE3x-fJ_Q9ER zi0{4b*Sq7+@<;BvO4Gmh>({Sezkc02)B0rp(9Ho&W3p&$6DvuQWvq2o33qeY&6cr7 zcHg^^LstYCOGSSFi};TCt!E;2mtk{!dtYJp{h@-b$H&e_?x{s?d;A9%pls{!IN5PB z(!3wJk%OV;Ern1M^aC5wrz4;GJg})q>nmp>yI(pJS<+JI)w+&H4m}EV-@@sk!kyYJ zg{9Z^t$t}pJC`VAp9A)#p+e1bI`%u9I9Pw*$-zR+3NWapB0G+O3C+8vS;BqP&X}%Zi zGseBSXDPZNH9+~)T2LA&Y}R3F{T=UioE%u_TXind+|33LUftUSpzG=U>AtT2j2tQeGhDb+Ps|_Jh8NEFExdB-E^rL}fcAUtz_$K{ zclsCpBmUnn3@^L~b_NfIB7I%YL&TcS^hD}v^fQrNi@ddfmkiaiyRYvp^j*S+3Lzfe zj-!VmejyEXAg=!Kfxr1z$(+T`%UpdTI}h{PEl3e-XbezB_I_bM_hZm&)mz zB%*r1ly_A!7UF`=)38Q1$oe`yZy|9Q_~m+#f_fElp-@F8=doajOF_K?Nm*%_A}kmX zZ5oV(5?A4tf)5M>BVYkxgF3Qm`n;R&2=9jnx1z*XvB1E~hr6Wy-G3_=!Hle2##*#;KI zrU*VlH)+TV-0j10jw|&?K&k2}P^m-piu-YR0Y6=W3q@GD0)47E23qgK-x5}JMs}!N ziA*rWw?a_o6(6_i6pseCs<$l-(g1q21Y;%GUVy4rO7RNEw~#9 zKFFfq`tT_qe#3{~^x?OB__Pnd?Zan$_^c1VVq(!G~F>`vUgpD1KD^wA zSNQNsAHLLwFZ1DMA8zsCD}4A$AHK?mKjg!$KD?UaddxzNr!XRUqHB+Ag(JB^G$Pct zFU^4-CayMi3FqrEp|Lb(nAU(TSQZy`ee*0|!^J>gr9<4tt#-9559TV8I4fs8w|h!%A<^g5m0F?5lyesJ3Wm zJ!mf`u_DocVznFw_PeGf8n8$06<{X@jo}99dL#VUN7e`%(CMb-NYoJl;|gNQ6)@fU zsCLtG;q`}><3zff9_m?+CL1b>P6V15TMD8sCWqoBC2IkgdLxLk6-4#|z4u+tPYH-Q z8^_?5D_ukeSo;x)UnDNb?$VA(;pGw;I3k79B~m+56liql9yk&tp}ItBM;;;JF+aJQ zoRvw09+CNCC8u$yG;ZL?TCy@gHFi8oxD&>vome(A9!n>avAOl@jCE_;vYA|dt}UI*$37g(Ytq zG{v0^hww`{3U7FplQXkui@&`sq9lMFT&JxF&OI4iJQ$okppORUQms$vyPgU}8#cC` zWr0xeHGJqB4nY;rpVv`gd++hC69H-grL6jKnQQ)=o|t9vd}!95Xp(dE53*kK0*{1Cu5%JPPs96(sZne*w8k^v29o|JD>C17%aI95#Y`H@{ZN^ z33EDQb;gqRgcaNFV#^>h(H&+MVi|Mu&TMAZ%*I?N2_yE|*{tbEpEBuO+MMQ2?SU9u z+^u}h1>Txy!Ixr- z4AE$RFLc0wSj8@AaMDa4X%y9~Vu|mvUlZV1D@-V;n4j0dx@3Hv^$yhMh{e zmdBGc$Ja5H$yzy^xtV zCQVEVVVf`P#Xf#CZ+j(UL)NU7m607awprGMlrRh;k$4PI>@+$I+~qlgl~#dgR;dvd z+29l5t4!g?5Mn}%8bhY*fzSDp3nS(TGawx&Iz-hesvAVLMpSE|>!{^=rsIv-Q&tYd z?YVK-MH9E8F%Y-ed8e3>#;j+KXDzwXkYTo)$fZgL8V_zM<$LpvW97X5xf#cD-HeU) zdDt-jz;Oz3F*AHS9yLa-G@NwKUd9g(zSnqsFf^VuJp z;4lEi{^=QSuZY!%nZR9(hmeT(MF~G@Byv5ypkX=SH9R4)vlDX4=qj3JaPm5tIWRn& zftlsfaVHJJHYe#=DFC=Y#RMA3WJNfO1BtA4<#{ObL1ZUxsm&H_pbVZxBW5w>Myxc( z8kfZJh9EF9dgvSMFFKL9X%VpEa2PNVdFlga2CO49Kp8gPs1bL2VIP@Em~PSQt>Ppj zdGpBjmfo(emJdhQM%!E3roDX5+L#u8f@nI)$&K*)+qP~^OIy07?Uv4#Hc07>@GA_R z+EO!_Bs?L}l2dIn4s4aAXFH(bz^OwAXeap5$NjqKj7;VoBWY*z)97cP?fLf+Z5%jk zU~ga;)~&&VCZEf@)&wLxEEfKd&~CxVLZ+wTjAEO6dq2|Bx_umeFY;neZ8zk()NxP8 z`e^%_)q-V9=^aGdH_EiRI&Ec5m3|n0tA~KUl-l^a)kwJR!9Y*A=}>Sm+)@Y)hFc$~ zNQB!zRk=C5e!eRBrWS6Ghg*BXEuhmAuImZw@n??z%ZZ=;oQ!-x1w+A=$J-amH3#vf zp-c(l3qhF@q?;qPDJb3&R2r=CE1)twzac8a^DBljJinVL!^6vcnG$5RWmtH55ntbb z(iViPfpR6t_?Og0O~MoYR&){1zw1A6zQu2`Vjs+ldSCqI`*rCoj1Kj7FnDyz-)r7i z<`ce=;h2AbTR<$Wyj8px<7kqXD}a9c-xJf0{=V&J;`qYj0HZT zc)?66z9j-)EoiRqU!|yz$8k04v_av&C@v{kLgD|7S1J4!8n;8?|B2*H z3U86TMd4SFyi?)7K>o{q($Duu&r$TRB>z9D@W&{g4=DU5(*K;o|1-_&356$j*tZq_ zA+j$&rKO**limqM|4y?1YlS~R{BIS0f%yMY_`}4@{VKO*VE}GBZD*Pe_Q{Atn;()coNKO(+P;bp!qQ~1wNd@fb^AJMq23ZEzW z28I7M$(t1ZX0o49_y=h|V=7PaHx!=SVKWMU70p-rCF5{2@qel4-%Iuj3criw&nf%@ z*?C;yV`S&=75)w4f2i>CmFOQ8{u?B}pzyyTJ1;BzH;I2s;ol=!)-n!{5??|6B>xp! zmn8~+mgLJ6zLC~zwZdOV@mZ_z!=xWq_!YE}^7mQ#BhNwjM=>vwPm^pZ{PSf04u$_8 zvVXV2f0OtHg&(AS`dNj)miR9#d^e5z4Tb*);=ix(Ns9k-3XlJJ!t$>QFV7vh{xS}~ zBRi)Q{rhPh-%;yuaf^A3XlKo!?ID~HS#~9 z@VAh>UEzN~`liA^PWGo2zLNahtMDJE`QE4S^7rqr6~2q?d{N;2SNQuWPrjq@ zZ6qI4_zfhVQ1}eZ>sJc@W8z;^_)+rnP2y1`Rqknk{F3YVBE?~a!rw~#Dj)Cv>grJV zt0)fg{RQo#zIKvuLDc!gEuUiw5O-x28%^=aAy&POAxrTfIAH8WK9|=2XA`+|D^>? zVC-bvrNwRn#qUd!jg`x+OvN)4|)Jf|*N zv?9%QOA=$(gMc>wul@160moOr*k@>b=`X18B4t@`0=8WL{nTHLmy~7wQR*+Om!5~I z|82^`;8^}L1VXv^@2B|B;m0x*j6d!t>9>skZNRBEfnslw;^j)CBC@Fu=wFQ+9!f&# zpor{F&`~+;H%1@-GJlZ6qUz29S8o32uH@=W_Q(07Np=1Y0;k%oN;`-T~f#Y0@;*)g2+n`T}6H71J+;q@dRiiR{OsQ|8>T4t*DAm*-zH^ zz9Vr_2?07>rl`8lf(~+&uB9H-f3n1IBe!#yhd%ea;u8}ue={GXD; ocn?*sKmI1EX9rNMo%Ro&Z~mgre+e{}>%Wuy|CzrtV734M0&r1T_y7O^ literal 0 HcmV?d00001 diff --git a/src/chinv3.o b/src/chinv3.o new file mode 100644 index 0000000000000000000000000000000000000000..83b433faff482bd1cd571eadfe22f8dab03c85b8 GIT binary patch literal 12704 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 literal 0 HcmV?d00001 diff --git a/src/cholesky2.o b/src/cholesky2.o new file mode 100644 index 0000000000000000000000000000000000000000..75072f9eb412693aef81aa3cbda9b832ad74ae5c GIT binary patch literal 5848 zcmbtXeQ;D)6~FhrO|tpuzJx?c3YHy>3QTu5OZiG^AR7|MhJaK^3k4EiHg7+g{YZD; z21+|HV^W*$Qbs5A1>+73k+s?sSfgQ#O=(5VJ>7>mVo-n-}J z;u&Xq9FEVwmCww~cQ}h{~x;E9_dZ%~d9FJ?uCM_>Jrt7Mr z?N?_uYxQ+}MjJXG*Op&4BYh>$Z?V67>fPwXS>Det_nx_-YRg#fbW_z#1eJRyPJ4UX z-<;{v8tRnd2T>3s6Sw%SA85#DjF+?0rMA@x7P8?S=7*Q}>`nVHn%nuW6Gv zptEnf>H3aR(>2uV=Wm0HPlM%!xVHNunB2^tg70ewe-tV0;u8>_w_nkYeGhcIr$<`v zMoXj0_EMj>d-~bdJ3TAj?^$u(a?YqEp>V&(k}s{_ zR;u#~>uO2kbK%qHaI6d~0qv+I zIP!-=_Mh&9ihHb1FV>#bS-k7>kpvwbS!V0<-Bu#J*;*H1S&i2GeiCa^ zj4vUlHBY*QQMX`>6&PPiR<;vK{1myddmkW?)q1x=Qng;onm6#z`WkCh-x6N~UsP4U z7^>9DYHK$F1l15MB<)$vRNuq38!DoWn_3=efeHlqrWOmT{d`Nb5v@C$ztPpg8)5Jj zwsLK>QE6tZ3Pdm13K42++d(hHs}`QI7sMJ6Ng2di4YG-XPp5rHaGdGH-Vsw?$!@Fv zYzUkr*_jfiJLZBpB24}$C}%NQh2(XDQCQna;^P8S+2NxnUlanR!`TzWTKgBe(U$m+ zg*s>ZszmgCP8R!!9Tt$vo;o^jKuKdS@zrgPbZ-|5Cf-ZU~}tdPv*&AIqU zt~i`FST>i<8i`qtXkvK{WwK^yST|$Ikf|3&3!wtUGDbrEyN2?)oEggGidnM|f|?af zBX4ydF6NEElX@m)tO~_)BSvVTfIWSP1RvMa=@h6H^W&*;Jsm3KV+==;&@&85oKGEM zTXzijH@CO@*9F%E+x&ryS1!0 z?KA=p6)h=zB)mS@wt9t)vL>;*_~9=yeyE-=sjKq7086PK@TH>9T8MqV`sbA%U-L0_ zi_c&3Z1FAsdPT(7_La(rZ~a7-dYSv$BEIEaK7W_5xyx7It*9g5`l70dchW3O_96vh*o|N!C0?$eKVIhx8IMwSJ3IBtTzbfIh5|0a9 zuIEdV{w*P&mT=k`=UupaH`4l{`fL???@IbRg#0H7e@e)=CEPFSLrWh0W84=7t_e!` zPlVj$!f`$5LVm!7qn`s}aec;xqdv8O3%BA5{Z%d;_2a_e5f_g77lgihzqn5~+Tm#C zUgukcKNvSq>kUnI?g0WmCW5AUe z%)+%AgnJsURk&t_k&zsV=k*Lco&N9U2M<^~syjLC6pV9j3Yq4C^zfYUz^{`4LC3`6 z=oK>F-x!C^K=}X7YM+BI;_^+oVa}x4y7)z1cY6>7^!dNqhrt$o$~RP}h%b+qWTKlE zu;00WJ&m8}qrx7@oc1MQPv;?Z%H!{cj&k)sCF{X}u8{s#b)eFDT@5q954 z!PR8lQRtH~RNsq9L0c(JjI4|2vy7qLgxLITD7c!ei|2m1@&8#I#AJ`-$9qs7|MP&! zJ^^As7V&?Gf~(28UxU7K@teg0p*mxHeDlchzXcfjq&$JOT1+Swq<|z6{Vr&iv%i9e zDzue0alT|n^i}8~-cdpZFN!iv)_o0h5SzDMg?&=;LE|U*7r>OOUt5{_;T|P>s%zQU upqCW!eg_dsJAdn}W*L;+!}SL`1=pWICze*<)uwHNtcbQ=RN+y57j{ETb> literal 0 HcmV?d00001 diff --git a/src/cholesky3.o b/src/cholesky3.o new file mode 100644 index 0000000000000000000000000000000000000000..21955e99039a104ccce2358f19a4be1a2ca02c90 GIT binary patch literal 12800 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 literal 0 HcmV?d00001 diff --git a/src/cholesky5.o b/src/cholesky5.o new file mode 100644 index 0000000000000000000000000000000000000000..0dcb69fb3931a632a56064038dcbfa040f11150d GIT binary patch literal 7376 zcmbVQeQ;FO6~A|Ple~PmFCnOjsM*rgLM59l0^B2!f2^d({t{-XZPi0 z`$u~j-aY4czR$hyzPs7i5^A+^&S-FU8_RKoGFEFkaP&of?x5(G_x#>v=?g*K;q@JE}k%*W~c-LiNA|$f1L$yyu~pC!uF9b^LX}AluvZ#n=0npAGP{9eV9ifBI}l zZlB=TqJvXydf7GLi1(@Y90D`0-Qbx#S1jTnJnK{Mb+B1=i^B#|huC64@1fMG;OJqc z!~0I^mjP(3(WMs^A9QPaJETs1zTKbx7*d7!?*{n0LA~s_S_Au4^cngKt-c15WY}km zm#c-B{V3g<>-XrM+DlwJAJ8|#=ACNseB_x5;2R<0wT-Q)@#_)ZrgvV4jajril}a9* z(&|HFV5Yav1=5!~bjRzo9@+gf33*gwq||%fi;uW)&z=nNnSky;qF}zqY$yys#R2c( z)Qs5q{g7XW{;(1pJ<2=MpZL?KruT@Ho0yPql=7DJhb`%MeE)p2BmJ-3{#X6pKSJlL zaO0NYRxj2XfvyN$!5&$)LHAz?@25k)uQ`NVdt9d0f zxxi2@4OZH!7%Ku+0ZYlk`WaRrg=odnuauSmOUfWERUwxk_$)I=3sz?1L7Pkt@WXgg z_IW8SJljlUg&h|HDr65bqCYD!2fN5OXNX&8(j=O8uc2vp$~~=NZLA?faepRLv9m{b zhM1!{(3T|~zn9DzGuS2F z49FR4IV)-E0%!MG100k-#^j7bhZS`h;Aq-?Tx9on9acp6<6W++ika0 z9%%F)2(~MY0NM+cEkb4=v909>a2zIEp|a6lK4Fh5r|lKD+Eqon(>~(vyHi=ZUwK7I zwbzZ>mR2^_T||pB_)yl3D}OWWwL*K9t%2KzeyCJEr?ea36NMD-*1`{zca<~k>x`t_ zAm@dt!qY(y%tXHNY*DIQna@|bXRvG z9@pxJ)L6E0!-iX2%es1?)|8P=-AyUMdG>nNx*Jw4H&A0MFP1x+@4l1q zk#fGItVo%F?TfGWwNfTtT)(sYFN`yyxFO=mTq2v`N5|q{fcWFs7k;7e17ZDuW!CzU#WDEXTk%(!7j|@5ixt- zU)u26!M}XNE^oS4nccX5T4C@aZhd)han;R(i#uo@T>Q4ogXb^YZd@bt=&K7b1njKh zzu=1&;NotXr(Q#IVZC@e!z=jwf#$x?oaWA&C!I^zW8<+=9m>zsrJC%@14fwPqy2O#ie$qaB(xN{t`R6V8Hpw3~;l+~1=~WYs{r5=zqzOm;2POZ$1+SKQer&;a zOT0|Z)X%?5J-n#kz-it-vFKA>J_{~>af5BU3CBF2ko+Ac++5dvCLHzOlYGAgr=L-p z1)r43e%XRAl}9#yt8iew=zojEzh%NPpKi%#OgQTQMe09k!cm{bGbSAMFH3#%du=}5 z=_ErlbDvwKLo4o*IO>}9M=Ut)L*`CCG_1kzDL32=jCp{lM06e0Vqt*A#aQt}<@88^Kiut~SyrI?&yh2oEo~+RK{%m&pan*i%{$vTc%t z_2N$JLwZYqz`rat5g_LYc>sP<@_0|eICO@?-#o;)0iKAe*_Yuvr0gWNqaMf zv{m;diJ8w{)SHm@KS#zisD6Te4Me{Fm0x9OP+zcr_>Pi2^%e86#zxBkUPfV*OCc@? l`moyLH_3W-0K~S)_h%(CreUog)$-Xl$^3t3vPIHr{~svL!TA6H literal 0 HcmV?d00001 diff --git a/src/chsolve2.o b/src/chsolve2.o new file mode 100644 index 0000000000000000000000000000000000000000..5f4fbbff644ba1c821f228e35c8b609a209b25e0 GIT binary patch literal 10016 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 literal 0 HcmV?d00001 diff --git a/src/chsolve3.o b/src/chsolve3.o new file mode 100644 index 0000000000000000000000000000000000000000..6523fd22280c3a660b65ae66212fa00c0af17fe2 GIT binary patch literal 10672 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 literal 0 HcmV?d00001 diff --git a/src/chsolve5.o b/src/chsolve5.o new file mode 100644 index 0000000000000000000000000000000000000000..a43da80e51f4decd110e7d05c7e45ef952340289 GIT binary patch literal 5728 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 literal 0 HcmV?d00001 diff --git a/src/concordance1.o b/src/concordance1.o new file mode 100644 index 0000000000000000000000000000000000000000..040e7d9815378c1518cb665144bd607bdd57bc10 GIT binary patch literal 25824 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 literal 0 HcmV?d00001 diff --git a/src/concordance5.o b/src/concordance5.o new file mode 100644 index 0000000000000000000000000000000000000000..aac262ec1b04c342133724d021021fa883961dfb GIT binary patch literal 29800 zcmcJ24}4VBvH!ihOW5!y8whAX)TnD4ZOI=*Oaw6j0=uw@A%7sTz`EIN{$R43?r!+^ zAVC6^HH1QIUv29X{5@;!YwfeGTH4YIDgw5?BCQJcwY9ZaXe%OCq_xVMIcMhHlar0L ze)_vM_s)FJoS8Xu=FGWw_b%@T(hs=b#*=vzSL =I0oJBi%`sdvg#2Lam% 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 C=OR`B literal 0 HcmV?d00001 diff --git a/src/cox_Rcallback.o b/src/cox_Rcallback.o new file mode 100644 index 0000000000000000000000000000000000000000..41e69066b2898c3d84f9fde592e1f937c077d67e GIT binary patch literal 21672 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 literal 0 HcmV?d00001 diff --git a/src/coxdetail.o b/src/coxdetail.o new file mode 100644 index 0000000000000000000000000000000000000000..f05b5121797b93b9f613dbfdb68d3e34ddb626fd GIT binary patch literal 18960 zcmb_j3wTu3wccmW5Dp|{0t5&TCE{q~Ba;LW69gp>U?RiABtU}5Fquq}kz^*F2d|5~ z0@N{tl3uK6)!5$FPpwKHw&hl9!^?oTy;ZE#NBb3RRYa|binMymU2E^PXLfc%Zy)!3 zU*@d!?|-kg_S$Rjb7s!TrrDl3Hp5`@FxZVOrAd^r-4!W$78hr+(QFheU0S-Nba83T z;%fJn_m4tDM_R{C?vAINd0@realbPQ&J`V#JPD6;t*2wBGY9m<5qDybb3d}Dopog0 zkT{sw;B0dzb~-l$cGfZc8Ru>gJROfai-C@Pt;AE#M*vIw)syJ0NHjRJJm4f3ja4|a zPeBVyoUTZ`?N0o@GSSO*PX~4rV1={TllT?U5`Xd}K6FFBSsXwqCvhtAC&#`ciPP@A zm7N=ouw+YaXGJ~?pa$ZD=r^OE54mMvyZ6rTY&pW*{v)1F=MiXPmHvb711HUSoh?@| zw{gI29Nm7w4dJg`(77BC@KozbEO)vcyS4(m(edH&&bb$g&Na?$X+L5CTH0B5 z;cThn>f`Rt860p-oW*8uKknFN8w?&g?AJrT9(QNPV0Yr+Sx2qS-G0z=m%JGNxY3b! z^sHmW^U!;E#uUdym@`N(bGP?cXC2EAKw@W|cb6QDpLVxDXH}M*i9ZVC%5vrLasK+sJGsMCwd+m^8n95$e$l%VA`lPYiDa^5fy!|YEU(SL^?>!Y?_JL0 zEpMN(%W!P_8JMhWKVZ1qd##ERkF(9O>oI_!o6CN~>enDkF{Aw%zM_oSsIpFbCXSk~ z*}c8?EkK3EyUmGP0i+}wswkrv0Skcb$Id$HGKyiwYG2&=<)327Ho9c~=XX?$IbYe~ z$v$7ylZZL3O5;3KV;0n5-2o74D@LI{98NH0SfAJk2_DP|jyn5|P|S;y6%L(Mcp24JH(gv(_w4g)qJ z+->q;&Txfbz5EeBKEM?O2G-u(IpN=d%*VVJsfBK+N7yG;eD>b-)O;e>5{n8}R{ITx zsLh=K-ZOknoGpWnV-v5!xz0Wj?ZaM@(ThSZ z*gfp&uyds_*|#%$u)A}u0sBg4_K8%!F+yigX$d&Xf=dgyd;=jnY~FS6q9xQCuwnUI zA|8MoS(7j`phF^RPeN>yHagt?k19K-o&z8afHYW4hR1jl_k@z(_+AtCVmD0WBFFYu zq2%7prn_gxNmF3QrAlbQ8 zi;QbI1Gf&;oLnm;E&CAg#b&*;`Y(Lu@cMvZ;Qc`&$Gzq7Q4nsut#on<{LBUXr*(|P!&N~CpAjD1-2U%&>U2wLEo`bn; z=LGI%(7VP8*~5IL5}Cprd4vHl_KN+}G8;P-+LYZKE9h5tTa)q%5XuE}y zZ)^o+uTWfEc}OS)TzNz&gV4>58)t1 zD!+*$$=|}^(lk7b)04&0tV+Prtb?Epy9+)r>`a_rL~%Ab`nW_#G6y#Cny}wwATH!t zid@R&G^-1kgI@*;-ZQbZub_J&-kA~;NpbKvjA_{Gz#0R$b;H@<3^?%)gU2JnMJqoa zSVDBA#DbJqm=cSUMLT3=QXINJ2FB8?_3)V*&Cs{ZAOL(cL*G&4cNO`xBEP4|A1Lw} zMgB;U&noiAiu|b}f3C=XRpbkb%QGmh4niUA!8bfc>HZOdmS^b-`9t#tI`nv znqU+o+13T$k>QY<)kn)39iPmM5<$$#UhRvJhFt`+1dZCd@`N^BPz(EL#bbiZn1O2! zk1@Ba$|^<4!R8cEs55210o5D(wrc84KcaMqzM48qwvLH2qco}bm{BIvIK~IVFPECI zQZAW7t?1i28#f$0MC+Ws>fC=sb@wG#_Em50tIq422u=0$ZJjUsj%k4LB{dQ90@*0k zg?-gUQXPwfG;YDsn_ZhX33656WK{Q6Yh)DTurD4@L+=du8*eN&KQ?N|8#RNv&TQOc zA8*`ZTg_M>UZLRGqQI`PZGg}IoF#%|@49ni+QnJx$g244mJrbCfRV&SivtHn2VMhwmx1B=AT z($jAQ2r@<@Tw&~^nVC5~{f6{PSl)viKml`jLVfU+3{Tcn!5LIJ@}{vfAoD{;8fIpC zI(9Rledw^HjbiAYPAbq*&5$18f@&C*Be6&3Wnj1f8XY5{E1JwAAK+K`7=9THXN1eR zX{?CvOJi{$vvTe!8;cf34odp8!Qiq%wZt$`9i_BFX^d7{K^+6W6mm|=HTE5=s6ZZ< z*lIvFi+J4Q@7iiGTTWLQG)#~Uka-uwphKA=R5=fD<{J^54YpW{a*wsMkB!CM3b&6a zC(~dxQdB$ET(sj{GGnk?q$oR@tZVjm6YBht6nT%8wG3#v&}rCUi^vhlE=Kzuf4S$TM0GF|^d@A{ulDouQO=ZncMplDW4~Ki=?=SCYtk7VF^jj>}F*)b7{s> z)l%3k<-4hk8~YDZ{;5d%*I!}3iIVF+PGQ4VAVs-gV3A8vSpsMJErA_mLXx3;q&S|& zZm=a%lxYEnQdF$(>1SP^W2`7S#ZM>av+I+M3uu0nN%^FoH5scT8Q5|umaF;KQ#jxZ zf1L(?UowY_q!^*fFql_21rYI*r=ui2pE4vxB{zHfjpi}pe?Qevib}uz{rWvi{DY}} zQdIi&^y_D*tc8-JyG@F6l;c>}9=KO2a`IF1Mxm=XZBn=7NFN5fjRHuXWR={W^sq#V z($jF^LAeF#mQB(@-bI4I$Yj4s7YS)eG8Pivr1RT!hVqu890*j$L;aE^cX+wJ4R)&( zWt`CO=tikXW5Clx(AU6F_8{d4e(0w)Aj{rht1i|(MG5K@xfJDQrFxLq-N`lMlcKz0 z8LYlOP1ux|2Y}?r_E4}{?34Ut+@FrjAK!0RI@!;NUypPrT@$`TXM_24$_@hLE@ZG~ zDas_{dfue>+e|yi2|BAukXR~*p?|G=>;Ki=WJ4}=OSd;rVj%8Q8)b@REF9F$={2M7 zn=jK1fx)V!D0fe=wR4kHzM8z`RqN*e)|Ko7ni{Zm=O#J%GV>URZcL9=O}wn{r;{;< z<$aADzrn(~#oPN8QiD$UOTX)Xy-xXi;*v#UW4m*uoC>Vz|I4JjH8EI|6r~sRthPDJuP5>DNzRauzG<%1hg0pU|zZJZyPn6Sn9vUkiYZ zgUL;TYtpgKFMp5~o4HNPboim%OY z3dIZRgRv;%l$Kz9L6hI#pK`tIEqG*#6@=Sj1+77UBpeMl#tI_gwm_(0s;kg7xd2Q} zn_5sM`xR7q18ZadKnKSB;k6Bcm@nAk;+tM$bWU95&NkX1un0-GbAcpy~O*VM)4bsxzSWj8!=GAv0 z@p=3Z9YL~nu3T}S707SiVSafl*fwLeW=5?U-D(c2HFK;PNHK$!>xuR{5RJ44)2w;h z+|OTIS7(h}_86M7-sYcwK<0C|aT0`L{c`S>8<$-Zw4NS-eMVU9Vww9CA`5zVGqkEdBpZ`IAab?(wrSI=v2-vWL=ZrT!G>Z$zd zy!IuYE%Pd$wz98n{boH8*L6pV)gMx=B-@lZ3+8Vd1I`~ zTNd&8R|R6#>ssr>Evz-*3q`TOpr|+x_})OMfi?Tq`yvg%U*KyEM2TI{8j2Ov`(pm) zf|xJ5Dq0Y2_C*2>1)geeBpimd6OM;s(E?bQQ7A#)ygnWY zW<*>|eJxPQ1z4fM)xMU3Xv7a5E5a=;z6iOD2Ae`nzE&RF8mRREk1ifUJkXGfPxicx zExx8GbZiL6ylpT#UsC|1MpMC7vQy=)i3HnP0_EYBaELH(t1q$&qG8puYZq0`E{6`7 zoj|e+8k`@9HHR?~b6djozLwdc)oe{e0M;h+wuO1>!f}WJQXKWI7SV;Ey#bOMZexut zVPA{|RtF%?D(|95V0ADYm+1s|z9OLT*4Tc?W z^VWksFoSW!mJ);vF>koBF&c=mSP(LT+ee5`bz`t45DK#p{=OXxw6;y=pHo;gxIO@N z0*P*I<9XrcBQPLo9Al;oCCiP4;?Y3ETE0_-7`TAVvC3N&UZYmenn19r8TMwF7T8*o zNv49FOh5yK)yn*^`!PRM7xT74)j*%J7GG#pbu1DLHSv(d+_7q20g!zjVp}Z20*#Sy z$h!suSm3J)_*y`i4>pnxtJ?y8Qh3asWF#0}1rd6D(HM*+o(gJ#ZvhKoD>#DH(NH8#q)idpRB^fvEK~)eF<&HB6J8Yv zfx0+U4~x2C3EBj;IvkHA7l?Ot%vawMkQD~?9gbFp8d(FRD-v7_beI6S0HM%ePXVkv z9*Mwmn7y_w5{O2FVf4bYifaIdLh}%fMSL+ITO)R;AT2pL(YQq^-Kqjja7B!)V|>r! zy8<7xNG9eH%|K1?vWC4ND(jE0RSdNPmS%EfYr>ILJk@h5J+r-Su%7{Ac57Q~9p;)R zh%cSBa9PI{grQX8R)pIu=j{%3B#KD+gjA0)vN7Se-2mGJjYj=nt&T4?<=_ zO{I}0P^u&TNT3k}oN~$zcZ(&tAlM@2Ch175nyB3PMb+WLXq7t|ZVz(s*Do`K_^dC@`~0#0;u0;%}Y_cYgWPrsn21 z<>oJ(oSP5JXC~bLL8tu2wxAzAVV?Y}^6}m$;E#nPz<`|rb`O5N;Om(O*XNSpk4L=z za7(-uyT#LZtHp>{FG1%G-H;Nv>CxjMj zOWaEh{P`}(SmDXUJbofh$v6+wmh!BI|AOov((s?rxPGPKpOXH%hJQwW-_h`sRDU09cn$I8#whc4 zFU6ToaY@`k`5dF+uaRA+hTlPXF4AyWH#chdo8)(%hJQ+Wt%k27J)q$((jyxFAjQ8) z!>^(|?9}ipDE@mj{QER74{LZS@qeh{A%^Lq5(wAsBzJQ5Gy@n5= zc?@ZID~{DFr5NUlc>KTi1b8orFi^@fITCjEU4m-Q#trOboePi^E!;Bggl($L^A4YnOhOec(c{Thj#d*7iFC_fmG+h3?yII4R z(YSVM_^sr3uZEu?{o5M;B-#0%hJQeLct*otBKt=*{0!m0*6>AS=cI-|NBs9Syqoaz z8vZS^BVNQ#T?b1E&!V%ehwspQP0;Y)lKnglm+NGzhTlZ_nWf=!J$N+yGO_Gft%g5K zb{aIigyLz_@Y`to8#FwV?A)p0hsf_94WCcz?ja4&C;V{@{|?pRehr^S@f_B0`8LW6 z8oq(}zt!;3grCyzU8H}a;oE5*PBk%I8xWeizkAkA^#GT))up62f26@K-6GKWcb6jaTj;a=c;UpCdkoO%RWC82OR> zb<{XU!PSRL6BHc37s$L{so=;j;no?uM!}Iknc}!k!I2*!ewl_pM)+I>M?3G5om&(f z?Yv3+B?^xG|Drlsso=<$uTKON9Qlt>KBF4`0Oe`JJNR$bX9X^0hgcw;hxR`5K;#U;Muk{92^g zLHiL|KMIca7ZSci!I6KA;$NxY$lpu+fP(Y!LK_}o1xNl1#NVLd7Ue&o;j;+8N5j8G z`27lwewWg`Jgng8_d3$QtKi5#PWk+if+N3`^q(p?@()oS4l6kF<-3l@6dd{TKK>;I zNB(D|zoOvCzl`$prh+4X9Dcy@j)Eh98pZRGf+JP_?sHDTkw1g@@~1CZCx^-YAUeys zx`guVP;eCAAw65c(f-ZwhsUJ~j^af6N$qk4NB%b`|M?1z;tJwVR&eCw|5o8KL%~se zfcT{fj{F^z&v^=t;`_vxuSCf4zDn^d)A;j{0Ebt>(Z2X^dB%bYj^bY8uhH<+gl|xA zv?Jdw*`eSl4#P$`IusnCaWt;G6&%Gv;@_v>2sP6F@NET0QT%fqV~;90=ac>Y8ZN(| zA5?G@Pm|wX1xM%}^82EKqd1Aac%M*kd{wz_H4u z%OO{ET`N2)V=j0CAG9{ceE+v1d$)po#HI-w+K$gD&yD-4FmOm@fy+N zYT1#_vY$MEllp5k_Br*}aoJDeKc@bD_C##Ng#`!Bk9x@QOYHj~43xk91LO~%`N;k< zuNY51-+(of|DzNzmLu-@dVgGA+7tr<^FjO1bgrd7^zma%1NDD_;_pdy<&xh2e*t_u BBoP1r literal 0 HcmV?d00001 diff --git a/src/coxexact.o b/src/coxexact.o new file mode 100644 index 0000000000000000000000000000000000000000..5742b22bf468a855677d258fb45ae72d79b4e39d GIT binary patch literal 45176 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 literal 0 HcmV?d00001 diff --git a/src/coxfit5.o b/src/coxfit5.o new file mode 100644 index 0000000000000000000000000000000000000000..c7d1ee5c005976e719114271a40a7986b278f1ba GIT binary patch literal 49896 zcmb__3w%_?_5Z!QAzUG3!$XaTvcjrSAt8vCAS!`GHnLbA0TNA#A=!jLNNBPPXd$2h z>l%Y#ZA)7!*xJ^%YOS>`Dz<mp&uYy!Xtcq3S|2;G3><*K}+TZ6tA9C-R z@0>Yv=FFKhGxzQ;D~ltS`CQkL8zRI#HZov z|0F*AgNLGU+rPY$#Ao}7t0?hLg_R^85B%zAxcZnv!)soS)fTULqjhFsM``F-B=K%Z z$MP4vj#jM~7^)l}bE^G-OC-a0J*xxmm>ls_EEN*j1M&_69J+_u9D7d#n% zC+t2Ic00puPaykw{7>Pw$Gk{l|5aZrtSJ22qtwbfg&ncbv2gVZk;H-U_SgI+9kCBR zmKRRA;kNBw*xem2ct8IB@s$HZox(YVvr7_tbT?}Q@4bWG%@0@S7PaSv+gFFEJCXL= zLU*bAouMu2zBRNB_i+2hP$%x~V~KM&s5S2#4xF3QQFO7BSRTqkFB(D<5=9}8%3mZ- zC(#Qx)Lb3fXXIO>;l!U4ZxfKX$BRs@on5dHKh}x_078 zlxOdshoW{6R@wf`fk)a&3`%n%?GVEiCv}vLblR7PJT+w0)L3e2)WnXobE&x;AldG= zj`3TP16hrRORA5u0F2&Ir9Zmog{zl`vcsq!3~ztSA9fE3Q@2!Svh>SRhyIX8rqX?; zae&#-Y%zI^wqnPaE#brkR1#SGQ(PnM{U{S@Kap;QZ8g`+CG}Mh*~IKvn_DT-_jii z_6n?Rz?5e*>x3J*xmG6by*)>&5`5(bjSz?KBLVJ2d^F$Ia zhsmwk(D~aU?P?S-ca^2XiKEon%@BX^G@gfOCjYs@0yl8m4tGyc!TvzUW7K+eXSn+F zaL1qyWSo-fj2owRWNd9)-r>0MXB5|m=mJ@H(32RpXNapdko#QVCe^j}Qwj?n4Xl0^ zJY;Z8-);EYb#O#&uEZC}%&IL6kfkB^~44aAF5SD#jIE@#)C9H~s;7vAs5s(@9R5_7sUh#|uzu_;3T5k>MWL}=#U(UI8QdcZgkw!ZO}Jk;(lJI^1|$DCl}$~29BF?*#oRC= zP#M`PT#bt1_N~g>5DK#k#(Xodx)tpw9U5T@GdmoqPTRuRn&+el-0kS*aMRKprgN7fU=teJRAmLHW6R(C60z z-^`_XSQH9RO}r&jam}{Y++_Q3mT*U*7w#A{_TUN1k4aj%;81v{_Tt2L>@(nl?3i#> zHw=N<;R3j0V9j@qs(BucBtFnaZ`I8$3ESF%FDD+bMoB$^Z%FyI{EGG;;7H#IBQIC(2^BpCs`Qew+y) zt51ZSue=X=R$sCwE?LOI*C^`srAirn)mEvXGrsG9oQ9LYgeetzr$ z726{nh|!M2xml6KTPe{n8T|P%n66AQ!5EZ3-i`EPcHrxupe-GQ4{Soa6fIKzK>JtP zyiQF#J!>Y-jPP~;8VjdvPj4R_PVh!GadT)hREZ>3ht|;@CfNcWWYr>s-RND&u6a38 z5vnL^A4S{K%>b~O&BEUBd}vo1nva-Q7PzG~KwFBB0&BnDA2!8|$$~%-dV{NIUOU=v z4&4VKYSyRGT9dW|&W_E-6D!}r2v<-m+fZT6N9|r*~d_|jGO^m7Tq^kSPe!=N6}udIPo#5I!&o3vm7cvO#l+L zL_X4S*)fzZCJ3dSbVowrAasP3C&v2#g}3kX6MYwGgo%o_{cgBph+0u-$=gCK9Th`8 z%8)Nnp+|S*S8+az^Bd^izLC3{@i%0_7YQwkxc>-a(TNvT*4;^6@D#E&M5n^yHJI~*V;&Vs=!Xj7vN5r$sWSv9}b9K%i~gQ~U$BMIzN z_`DZx$E4%Xo7RWQ7ZGGZH4LC*iiZ9-f*?KH zD?)HwHJfBR5Uw7vf%XS6oJR{2FBi3^VQcVgCXND#>Z1ayBM`_{&~uE@J0ujIleWJ# zXviWrZcn=l>R=8m4sXD$P1{Ms4nvGf&iw~Mt57?C8@0X;lwJoAe-Q+;G6o|gX7tuw ze*yxw$KO=bDw`~Z8L3ula&KiqQUZ~@#QhtHAt8!7#VICiA+k{fol&5cNDi`NTZd48 z7t8joBMobJ7S{1HT0%Xoa$xQ6sKx3E;){irJxFGiKt^XI+2zYTzB@!NTC)9he~J5k zN&9l|NJ)EXpCe%xdp!j7tbnW{krQYc>W^FNAi{B4p>Ct?GU(7Bhw#HNPhw0+?LV>t zCGBI-Q7SLbI2}y15$KUb**>$uss~CBu2) z?ZE2$NPVoTX*g}|B_abS7gCzGQFEV$x*2;Q?0m&T+q?Hs^aKe>`^(BZ61!CtC22+H z90_j-w`c4Ow~r4^ZI3(-CrR6hz4!}cAvq6_7>pt{2tO~!kpsd2VNoZ^b73C>%CVy> zBaZ%QYD*g~*cpF}^j$LzTQ}@@vRxW5tT+{+Yz*STz&EeNa|}8-mtj?Jjj~hHqCwF$ ze^N0mqm%-}@Aszzax7;!xYZqqP59eHVPN?Ok8n=hzD_pkpZX+d$z0>ro`} zzA|P};y>v3AR0)$u>gTX0LAcetV!Ya2+lvK zR}u08H~b4U^siX+QEPD+C#Pj$zj93-+E$?kMS2QxXu2P66n{acVfvP((ZIty`=_Pr zdAu|J2Es(^B#B9gj{8uBggu}(2qHx0WzTYW#fBZ6Hr)j`)s?lEVxNT73kp{hCq6Gp zz;BaAgSpo{2c@!FO99eqP7g`S@JOv=kXo4WxTF;i{IHz~w~skOHD5$4@ctwGyoCCP zt|i@f2hIy^JKX}TfGc+(ieUGl9+-TBB|7nHIPso}2!#c&20Fe9<6}Ehk~mm&&IfXq zjdV=I68&OHVp~zil+R1BJfj6Qwo~0lBYxd}Nqfdc2$Ew9+dhG&X$4@Rvt$2^OQ8u& z-aqYPQ1bM(prMN2vcrG@?Mhh;cJ^v7Se)*Y?wajQ=`R-dv+KMJkt`hQxD)N_+BzaEtoJRMlG5OGVb zNs)GRzY1Iw->?zBS#2a$KN0M(aT`{T}IYCB9KLC0%et$6@kF6=gz$2c;)MjcLNu)S8 zmWTsKKcZg9JVB76z=hFN@kwo`-=CV;rz4nt;z98i41+>A-QvN^@!{ct&?-o!9nfxd zzgdL|IZ8({|h)BR2xYTiNH^4tqkSUy#RN{dUp=wU^!mW>QutVEe ztOG|;%3)4LM6Rf#+&;)6*ChpM5u~*?O#$dZ8Nwz3toIY~7hoXl9^{c~nOf%b8iO97 zB=F7ez}b4}4R=EwHMxU`PO;=JRYmfdD)vGv)giQp{fX>A%M=Hs1EW6DI}P+Qu=*u* zam~wtwWpx*B8+>P`1VK1wRxi&_Iy0=+^EhW#pht<%St=H=psCTK`+bF@*z0w{1s!u z)dZ944w2f@v2*Ac&3N7PAj# z%RliD;Z6zfqz3_rm-H5DZ~Rb6J02nHHwl*~h73MLs zVvI%NrNk47$Jr&fhL&mQT{_dz+NBC`Ql}^NS%F(>59x`%4Mpsn?cRZ#fa>{Fgw9tK z)A$ysHuzwu`xJJc;D8@aY$sipDeq0AFh=J_^5S%ybnq5PJ;)(P&(fo)JF_}O2TzQ> zFaG#}iS&XhaY*glj$f(sKSDhfdbX;Fh)o>oWVKFIt2M3B=kgkzF)Fo2ljD%vq&y~E zaDY?HL}9IwzpmJ3I-iGnOQ*&J*G3nX%EdG$;O3f+H?gW}Jj+ zW$tlNZhOx?c!vZ+7`GD&C9=cUJvJ828P6Drh4zj+o&DIX9ekBno?C9f+&s{m9!_yE zB`3{-kmH`vwBwcD6WAZaQ;wi0ka+0b)GELS{sTGe2DI&Dj9Q^Xu--u(xS!Sz$hVf1 zUyx5F-@nN7DZE2&`&V{*@1pjCa3Y577$#{2bmu7*X+M*+ET*ZVj>7y(35SAr@b^)q zRQJ%YCs4n0DW3Gx1JANo zfZ$H&%@KH)`BXugHuKAE2VD$dBC2*lYEU>5DLTAUO%&4h{|g+(8!)~7FeFnb@Y>b! z}IJ3lpL4V0a~WT}4KiscV42>+g%cL%6Ly#Ju}d>3W|42Z)uo?X9+ zum*obom7QKv7XI+8h%y`C!@=AWLLc(n)?`loc*;$ft&UCxs+!gyF^?AIu z%z2!0uOYYnaB*NRy^Y3+x)`GhyiA5nyW%~ECu4)tiPHX4oda!nlAizafezeAX-6@o-t~z%3 ze99sGX}#(jV~)>LIbHeYDC%mmgUDW9x<>)or)&0BbedvN&Gb6p&XpSe7fV2%fIsKO zv=7H%0`?&~?IYq~`qR}QJ&k`xbe5)%5}mE-&xsCd`WVqUeQ|+SE@ejPjH@zZb;hSM z6Lcm`Wx_hsOJ%0%OuEXH>5S(#K*OtbrjOf<%zT~6P+eNAGg&GV)0qKo12kBsGbgzh zA+t(nPIf8qUavFR?lMSg)0rXejmX@nGiSO>!M09kM!MG{vq5KaRc5o!O?x=C{H1@B zn%CrwDKe2Hdk-d^`aJ`#6R<4xcY1#=6?&ga2>Yy0yS0+!jijYYlesA}FGY?@k@-od zJ>lvk*=I`(qSL)=aZUBD&zt^w0IF|&{%Oz$4Ek+@K4{SI81x~7e&3)E8}tVT{h>jB zYS5n>^f7~W(o%Z52JJIwzd@%NbT5NWH|X95?HTk52HnS?`xbe2K) zH|PNdJm81yiM9&XTQ8+49A zpQC8?puwG4i$u6NwY$@X$Tw?6yK=;9W~ z9maKoQc4Z^*5^o;^!BYErL)7i?pVnZvw!_I?&a{LmbyHoc8LDGzv!IVJip0t zCBM(1@jF}X8mU7xr;Oaf<8qjrMp->7<|HfXp-tu0OipEW@i`Xzxjp7jZmf0O^Q>Y! zKf)>>Y31|WZv>Couqm`*(Z`JI+B{U5Y5{a`_apDY`Y_trVzxi*1hqz^!&8bS&sPuPT z$<2rKG`KHRDod@1$Mg2ZB*w&dM=RdVtv&HJLhdNd>t9b2OO^K1DWE4cCZ<`!nH zTnWekXi;osci%Z%4U~jJ=YC#R+>NxJb}n zT+ZX14joxqY?X*T4-rdceCvZ&k*+t7W6W{6u||#}jLudQtABmx@!8#+t+^gL`q#gB ze0HC6o{BbHx}Qs<9`f z3yv?evJDb3w4^W2E;^ps$~H>r2nrTWlGB2%>|!ZRx+|^R^qLXg=>Nc-K|Z|#nd$KC zlur}WNX_Jq0t@DLtD4)r)*k_JJmc&y!$@mwLNjJ7VWUGz)Cy-DJ)RxTa+RvCdrK3@}kQYJM`DDGOwYj&Y{14^HU7P zDRNSZoSY)dQ{+a+?eCtMIk2xk^VH1#?ttD|*kk)bPT#(l0K(j7(u3Qcf}OG% z(gL0cxo*ios*!mH1m~eJFc4KqBtG{fdgwO#)9!ab3iV|>&Ol^6tt@2+<+_)iqH6Uz z`xNTtgzWE5JcZ<+*ej{A4_!Yg)d9+$%wnJ*WwTFn^9NG(vcBcLsP-wnoP1R>IB~t} z^hYVqA0S~=B8S`r)R(<}B2+ky>dtUyoh)@v*Hykf@f2bmnhQfgVdxiBrV6GM!~Q;1 zTA~z4>OV|cBXx$O4)vPV4W&eo5zaJ9kv%KbRmV9yX`sHAfpS;~hM7!o4h!Mzxkf2u zo@bOIJHi+R)E&t!a^2iqhX$}QQxB)(6;{%%P282dFgSC zl1u47y{AS+Y1f${q^L}`n9+?bX7nUWw04~`Aw^}9Rn|=h%DU@7*`}@?D6<=#rp~X9 zvzqUHoZAsrbP~)7>b&dJWH31>1qpd7L#715hNsx2E21%kikhWteN%#9Volds=vZl{ z<&S1{8H{_9zFH^b0}Pq$f{9gJr%sehDNrY*_=PFK(#^S_?J9Fi zpLOfYwOwc4Nlc!fg1V|UuO~s5CTk_FExo`1*tPCu?v&D91aD=Q9ZA8}LO#V%Z>QNg zKeWUdCVI+Pn)VVbrOg6co1d{UQiD?7&P{yRXliumT4$I5qIo}OG4E|uu{hruYJ`t z0n6_+uiPXV={fi$f=EYc+=Ui(U8hvED@u;(3?U_UP)(uhQ*1*1kRhdrWW))eh}|b~ zsLqsQ*(`tNqPKcxd54SAk_ycfQtgc)vYY)7P?hAP24E4go{Qk;LbfvGIW5lDongbh zO@iFOCF#0kQ-br~PYKz~L$MB@B{~KS)Beh1|>#$tv9>xffH6 zLYj@1ZsPJTH;%8c-E<*;n3Po^q$z897g^)D!W_Pn|7>RZK?7qld81EcP!jWZ7pc?( z9Po@$oHWMMgcLno=W9Z4PH_qON)q~-kkXrOLjMKKEh>RUNO1)ZLE(7k5NAl&B}wP_ zUb5+FqRpNZB&2AA<$YN?1WR9-({c2tC>&=rdoFxf$XofijXnMDR>^#yLGTIr`_r^E z#V46P41!O{3)u%0Us3@ky6RDC>!F=e6uCXANU4z0wq}%^G!M@gQZ&(w|6P^o-KjEt zlc=&WsmgRArEzLu`XRUCD`(s4L`9_G+{%q?l6IO)AfX^kECnI2gRs5mlvm1xl+TSAn*; zK`dqx-zm-sJvBM0rwKVd*(x@+vpJJ6>I(g>R9zvzYt|JbA7#5!yIFYNMd^IL6Lv~K zW8?Tv*wajBsgEGxaT&0g>YE|>z!%>MyPN6X^4;%z-Q84y=b)6Ld{xkP=}*4PBT6ZSo( z?=>)??`KRMbspx-;N*;$mc!%~d?$HNFn#h6-4UBI0}l(=g} zcTOMjjyFq(? zr(;8eH?my@eGx166JyXtSv=}i37V~L{X385)2x{S#lgk9X;5r^6{D@O0&ShYNSA%A zAC3Y-Mmheu&Q(Hwlp4KlDdW*P zI@Dgp_TC59fHH4fQs!l#FaXiBV`nyUi;lBU%!p&@v66 z-R6~Am(=xr)+#@_vzaNRG>&@zS|J%R7zR;DX+yr69&?3! zI61JDLdsaW&RiiyLBv8KML}>08Rf7CE+N0gqYbX_Fe!5skdV?ZR1`AR#koR?sljD; zFq8dR#u;uPr05I7>`xk6wvFHu@@bCaicd1qGXyyyMM1?UnLj4GIZa5>R`J>T$_`TI zoH_pnaA-lrRjra4l#Dmigf!;gs$_&Tdb=vQmlxHk6`_qexvJG32i3InP0ZiJoLtpq zi~mKz#ZdZ{q|%2{Vf~d>$(T#B&_?fGY3-&buXNXwS6XGR{+FJ-(xoT%Fqu!%W$0u@ zfXzBr+{?qXDY?|n7t-i?=L(ru@AAUtI`f76L&_MPDzn)bzWF%3v%vc_UDqus}eiO`q<68 zn{?hhoyT{)UlCFkVGPZSE9~avl(I2dZ{BVuW84;p0(~(SX5)lz9xT_x-Pvdf)##srPkf-F->xiUrM1+J@}Y zWj(F#W<5QU)Jzsp_>PbgL(t_T$+jgDgHK3NNAcNu$fFTyoYtTRd7*xU?^wfy6jy_+ z{av0=QQa>iUrxq`963q!PO zrDRNLWnV&Cc{kE->{eQNkJ3K%>E8LA^?dl}-r}~8$$n{?08dUcK9ESMH;)@(8cAJ$ z$}%0cG`U1A)7w+l7xGDi?M0^dCE2D4`36Jk@lGMD^gF)8`vdA5t&Vdc-vJ5Pzz``S z^s*$|3?Y{@gjaU%rt3KKR*Fx^w@p3|pVFr!pU9;)-em0Gd?)N8{(wt4-w9Jc{D!*E z8`$U*lsG(`(0AhdjA=1GVM70&2L$H`A)jZ6*#2dW7uaOz2J;Z&+4(h0-jIZ*2`NrV z!n8)Is|@N&9-99603|*`Ibboq?s1;_$mAv|I?61Am_>cEGRgG~9>zCQ!ztuphSckR z$$XsR6FbDXquuBrMbh!^b?C+hsh(XMT`lnKMk_*O;xBvy9$>iLws6O>Yg4 z86rUcq>D{|0UyDp^lSDA43`E{S8@F*+=``yz;jc@E9KQZbZlUFG2iLqGNVH%5I{O% ziPb;(>Nvk(UCA9DV)s6smF|x@Z3a!|Rd{L|a<^hGQBdwD8 z4}*9tMxW-!V=>XElvO}0LW-j+33k(;GVm&gUcBuUat2#l)sxH+9)5uPTSc;rg#vqO z;UCEsW(z4oQE$~syWT~-(k)1?p0k9MQ1#oUCyV4EV?+gsP6B= zWDkzH?-SRkVMkUSk<1Sm#6DI?!-ZBQUFf=$3$0oyE_7#d9OnyJ!c##tA{iM1G-4Z2 z7899eIQ$J|mCi}3Rwbka5J=zODq6@aRG?&JNnA= zVWnimdofXjtV~U)4J##6lX5m84OiaKMN5ex5`|o+R!G?aVf4E`+a7@t&=E1|18Phj zJ;NRvoqs2&@1OBqe_t2hu3-Lte9!Ko{zf$8b81{nQuou$ez>}zF=HJ!FW%CeSKnCO z5U+{mEgO4b<%MHLHq*LDYp~@@7cAycw0zWwHOEg5y*-Evv1MU65N%W{F+1 zINFjspL)|0tEq|Bf`)O?N_~@t7gfdPgTj&q1_cs%O-p68xw)afC8oIwo9h)D7P%Qf zFvn-$M{lCdja3aKp7JwsM{!HMdCB7DrWlDwBJtH#4T_7*>YTu<9R_G)n){0X+Oo?h zmS1=AJ(a$*293Pf@um6G@5a@a?roXtkL}q^h&P9>ak`B2XO#JWv)mit&+7CqzTBUA z`9+ubzkaN$!;Jl)5P&e3Iwgb4&c5AI7~$e4__mHFnvbX8W%x+q+4p zi|544%g4pr@R7H{Mp_^`vJMW^8!@zVEH57&^A#1^mXaG6mgIL8gHGy ze_8ylWrVMyiz-l;-(S7+p0zt~^^G0mefQy#dq(c9Qv2WPGhacWDWv@47WLzg$ApLbv zKL3^8cz>Q3^v?8u)w^7mjTn&r=4^kK7rW}_O>>ksPf`JX<%X`!{$+2Jdv*2m7A(GE z)*W?qC3XJ0R(iRk!k74lXTN!oa)xy8aJn}Za&K?*?{Mz+jUVV;;=g0%8zuhX>-DtId{s%50}(U@t;uJaSJu{2VZEQ(#I=H_vM}F|EB9* z?w@qM|Kd)6&Uk;B?yf7P9mlo8Kx4Y@N>gwII)r0%a z*>#auo`n5u*jq_}_X4iI$A1DF4)AXE_RgPOSJ(1jU!7u`U3BaaxXsG)6>m+h=irzc=-VBk-G;g$tnoA1(rktvh+PEjS^n^d5b+T!2edUxHp zx{@i;y1KkwEd;t-AMsvW;v1gjjT-ksHwL_yYHI^N<}deR5673HlZVE&DT%wNR7C?d zi!Pz;svr1Ipqc7o!udD2-rc)O>Ry;~m8b3E>4~J`hBxAAc27Or8XV_eTIRohrFXe+ z;y~}Fa>a2>X`%ej3s-m(<}J9_S3IyTy4M@LD}MCJ@;MY^Ff zA(!k)|G@vBR)oXXoIQx3@o{Zx5~e?t?tR_Ae&y|6-h*wG{%gip`agAi!(89FgGi#9 zt!m1tp;iV}j;ydJh=m5vANCKq{g-Vc_g*wb&v}|}(L20y--QELPk|RrQT)ohJQR0g zHV*Jkr>Wuk@!!?>7kJm-;tlry(LL-REK<|B~2){!@u9 zcU+`y$|d*K%nz@Ip+}Zb`@S=?>2?`imeOVNPjGe9Ytz@0QGNbst$&m^V13-*4{pk9-x~X9-a~NNmPyQOZs3F|=(v*@N%0RAv;duX$>mP2pr(FJl%S|s!|KLsk zw^qj5E{gl#amxI+YVuu>>sQA7?>le!*R8zVf5;h+`|bX}I(OGy}2CAtSL;5kfM~~RZkU_!e+f(=bv*oetgb#XBL-Db1GZrH#NuR#cQ4F z`ArScmW9`x?^Kq2wX&h9dSPYES%77Bv@@e}VslmX!f0&fHH+poH8_i+RgEpQtYaxx z+^Am}ZLD$TS6y4xTm$|qsuo3Cm^*J#V=Ql8Rjhh`UaYERVM|`i{Ho??OC##l=pHbX5~_*L<>@#g5r1yzgcqoebxo3KZk)j}ng6OuaztA0J$upg*jQq_>x z(p-%ei<%l5s+ze;e9tyo9dlah>l*8-7AX~%VxtjNO2!)rkJbd~*YzrE8>;GBP`{=r zR=F6Rtg4HW^0M2htV&Yzl2kQ})zZ|kBzitIT)&80ol#lZT)(&>I;p9lsgbeDMODoU zp}RxYo>4pr708y+WEE<6YBV;#sYV$a<&ztl=2bNmH!eXd^^Hr;cbXb%=0#&wPUYez zW%Z^w^u`#qR4vgxYOIM?)i|{cO;s_}pVk~*Qr{F8^P|D47S*Q~^e+mANexvkQd$dB zHIH^;v3m3wYS#tTajU>8kbZxJF)1Z#gJcrZ4@pyqq2Jb!b;lOHB~z- zfqL7FK1yTMBeq~;yd_$*Ozklnoytbq)Xu1!(X`a`z@^dpy7|~sYtgmM(Wq0;j$MR3 za&j!#%SSU%11%Rh)!@WPK+VcUa7752*ihBDaAvHzzOl|>(daBx)MM?mU`F9P81OE9 z$-AL`p(<1AFOD@k(c0#w#>%Cn<`q>lqE!t}O%(=rM&(pUPpUE#4s7<2rxvUftBS>` zE5-2rB)e7#M#B`)ijmqhbK#z*DXt}d2RuFA6ic-hi7tsYh)c|&**8`iexs%oYH%SuwNf!FS5*QQRV~9rY{ve*c_H+mkyNe@b(`y# zInDJg3!ON5#*E5HRZ9$=jHmRxqUs8#64SIMU*BMM${}RYZH&HMfT}a1uv2rav}qwE z&97=$LSr?fa#rI!1e==KB-Ftfq*+avnN9KL})u;g*)z&pHPB{++SflQYXdU(78j4CSRkfI46vtLH=b z)Owh*v97S026bk0b#t^91o;=6Q)xlwzoNcDk9M+oHI-wugpuV`pqYnA<}^l^Hejl@ z&{~*sdYZ8mE7%H-8eJXjCPxv@>ai9i&&A5Isp~ukK}PGyZJ;E^CW7%|{VJ)C2zI;@ zDV_BACH187tL5g%VZ>1&2qCtnDGo1n5G$+d$)yTgCLu&sRl}6b2%pu<8RsWoF)KK! zpdk2_+zWC?1xGH5#T%m+*XceWTLsHrj7Je8FB}sbSr;7n)zQI`nBEuTfdndztX*7R zjVoqV^}>;K49EJ~)C>*;vpQZyRk%@l9k&8j$D1qRhw(+EXHiqkj4T`{uq+@>kWDTe z1FKZVRaDnOmG%}Ya%ih#TGwGs(Jop`3ytGUo-}D(FlW|0>?7j3ee>@Um=-jG(9 znbX#5dgdtK%08JnMVZ0E%xrK>%=8NTwj2-OS7=dPJ*dF_etNZ{%nX88OP}1=|CXD1ms^o}pL<2-7Pl~S zn>!2q)4Js@?28Y3I?fyTqx2p6Ja4LP$mO<+l5J1PJmm8a>6dxLcSYtZ|E$a#{gX4- z`743?)-X5|;7ouEiS;Ib4-MC#sS5Ql246RzcNyKao9c5><~0BPKFES9R+p#rt?0Im ziTorNvb#ytbei-2v2Kd+9EugQ3jOqis+;7eXHHh4#(jny0!?xjD>Q|VWnBDH_%CAoMvH#} zT%-wEh~^M@F_;QZ0FE;xVguL~|wHC3=qkzMWZZH0HW!}porv?D>A7?*KW zS-$x757e5Fb0>1$@jlc8z7zNWjQl>_DXDmk`?L7#PR?I@z$qSd$N!HW@OObzyYgv1 z6{~?A>4D#e5Z0ai6MDc0^necrPVLGs;>fSuhI-&Pwm7`;63)si0R`eA8pj}NgV;y2~nR|^m@-b&D_YOd zC(i+T?^j7rAgCpE9!UOX7)6qi`1?%%zX8YcK~u8v>99K`dV@h_LHtpwvT)g(++yJy zHM{dm3%`x=P7A-8@&7Px>m#pHL?7BuP|D?3EP^*^*cof#HH=TR@YRe*EPOfRvn{-o z@vAMog7F0wK8Ep_g@+h#v+xm&(@*JBvhDC)i$9{-oF7^Ec*cKa;iCWVEL_@s!osCr z<-8@KV$x{{%U{m8t*6Xi;m=_Hge8ae9hAOp;e#~n+|`5pUs?R(&(B!+YL-L)DIz7& zXSvQgA6U59GmAQeB>ZB}p%yN7%dv2=^C$y98}dZYFfTzOf1_#*{|}6X#~A;_!fP0R zB>5R7Juaf>vld>#{O?-0w0kNq^`ved{zT8S41AP4?TVd8Te#S5ts%#Z^WV1kGg$wh_rU)fi@%8ZKkkA5bBkZ>e+Hk9 zM1R3^EPN2lr(bBKB>bZ1#THKXqcnqY%8$mM$e-5({{<{i>JtxY#YkTUwDL{y&d#(%w? z79L{!S__wcwexq5?RGa>xXAC%M-br;vixa`Q@_UGPy8xo@aGu#tp;xT;jawb2u{7JhJ11Ft?zt+G_{&D=}I^w;+kkiOG$v5>Jocu`#y&j2uruBeV zS-AMyd<&OxzlgutC;g3~eM%E8T-u#t;kRjaXNHA~{C<1@r~Y1uKe5|cj7z&>x8*(H zdo5h#ylLTVcIRIfPVG~2`CDevZia@POvZ`NjC&_q{L=3E7A|teS-9x)4GRx)yKNRO zdj7=1rQP3HxbQz|;nME27A|`JopHOr2QB^~tmg+7F72MqU(mDddA5a%J{v7u`jy3B zY$7?P|Bp0qYBR|COgC_o{|?59_bd1l`49Dg?=|F59q~h#J8t)@uZ2s$USgbNnDaX8 zGyq6;zp779;Z$e5&N>S$d<^3;3om8-8y3Er@%09NE-f@k_s^ zSvYTBo$?;!Ty62k9G&VcJk0oF#%+C;TKq-K-)iBD8NZovTh6yE{t3)~kA>gN_-`4v zHkR{z5B#t7fFH2rY-Bm__rRZdhGww!szwFuW|kt7QT)qIMQ$REy;fe_jkL6_hR|aSoi|g=dTw2Gw$!37XC|a_k9aL ziyRN>sJJC$atSw{V8_e>ji!Mb8?R zFW=4;yo&Ywt0m|6Y`3>8{11$OVBwE5t`=&e-KQDv$L&bF&oe&Q!t>eR&bILHvmGw5 zaEUK6o+AGWmJ_!4pXYq3g`dddc(sN9n)|uQ!bh<^@3ioXxL@~Kcp2kcEqoRCOY{=` z=|2voB;R`z{CBL+0ZYyV#qBu%w(us-2iP7WXB6W@Ec|lTbGU^MVE!Bn|26ZUZ{he4 z6I8my!soG_ODud9=SwZTg6&*s;q*TdQj+*2{nDu8e8b{zWV=Z_!v7t{Z?^a^k@;xh zZQS2GE&QJ>=ROO6fbFo=!k=LIofiH&>So}4tkNyvk zQ}N*?mM_nlMb1+^Uh)-7!T-$i$7VhVMZL#o27=O&d zH*tQqg`dFrS1f!j%h_+?B|N_Ww(y_xILa$`>6h$pGPs`L@+$(_7XEjZga3l%IQ#73 zaT#UdpR%6gE&Q+SC-UAw+RbLYOD+C|-0syD-kbCCLkJ@02i&goLvVSIxZ0BQ0q56Q zxV(qkXyL25zjs-92IDgCrQQ43Pqtb7TlgHtU$pSAaKGNLaQWGZLl!=p=jmsR zlX_(0&1&@UA5(L==y^8FKaFwW-@yE5S^Tdu|7eSU9rIsg@wf8$PPX`OWd3OuKmKnY zm1G?deO57llO;#?*~=_BKj(2-ZSl)_aD#=G0e~-m~HS_<@YWHpS^Bop{ z8S_77@&AtPx!2;K#{6$t{Ex6-9k%$x%>SvyFYirzvww*_Coq2&*?c)W&K{9~E_ zOp8B*`*TJq~z{#6!#i1}+Q{(&rivBe)`{%b7$RV;sv z#h=amYc2lovwgmA@nigyZhAVlrN9*ghEsPW*DN?r-2UCLKI~<;&G1hxosXKT2m<{5fo& z5e6OvpTyOC11I?}bZ*Hs2i z{O@vq8w{NIN3xu+8#wXb#P(cn;KX0e{MQ*c@h@fkW& ze}{n+|GkXgZQ#V;D-9Q~dMvcLJnz)4OE`&Dm#4=#TA2ID7Mcm~%$opCZF4b`tn7}7Y4e;@N-YVki9 zRP0W~!aEs{TKJzCm*3wIJ^jolzepka>}CFMS#sWD{B8?>hw%p(C;7whC+RT*4+1=k z^SdlLA5tOG9t)TMKIjb#&kHJc=Y0#mjPcJc{A-N&B?XbBzp^sl5aQWQN1Pkv-)AFYgYxSQ zocM2J{tg2V0*`b42Nu4a^YS?g$`b!4jNfbUll&n2|APij{HO8f75-r0#4qt}mw^-i z&CLHN#>H;(O!=UN(>oqYnOu*GNj`pOOQjPT7di6z&k+{?k~Gc#6$1|f3T9}0yn&N^ zS??wrIPu@b{1F2ue%X)CF>vBPzaK706$VcHvfkAhco6s>n7_fmiT?tQdrJ+R_%Gwn zZLG2IKQVrjfs>r0ypDX&!l{hXT^26u%kM4x82j4`7XEAYlQ%3}*6R-}{1oQ*v0Y_+ zWj{2)!XM@Md76O-q4%x)IgeomPJQ|X%aC%-_cQ)I16Q_Zd){f_LDYYV`F~^KwfrJQ{u>hM*9`WPM=kzR{#-(* zfm6G({yuNu)b45gIfEAsocLv5_qu@-|HI6G*up3AhWKLxCpr7MzdrVN(x2pn_(5%N z11J6;G5-JqC;q=M|H%eU{0Gu-K^kV@LF9kU@5RqHaN?K!+h_wP{%`Pm>#rC%@y}*` zCK@>LZyJIN(qscC{%^BBGYmWk`~dUMF>vCS_&LwOiGL`+=dLqw;+Oqlvw;);9OhqY z;KUzbKe^t(iNAyS*IW2`9H75r;3P-(nRggC$&vTjKQ(aTm;KwX4V?I8z5bnn6Tkez z*LDLZ{?F)w^n`&E|9V~*o;C0w@QO2VLE2;B#4r2a*BF;|M1IElJqusT@u3gLSK%MQ zFFen(aQW}rW?8uW&oe76T>k5r2P}L5`}rONPlNs(4juW0V$tVy=J&C_gq!>s22P>y zC+z3>7XAmuXIr@Z*Dxy?m-ur!HH5Ur;@_uG$JuD{%R2j00}p~%{?EW)8aR!Yth2v0 zaN_^)3|x>NweVctw00Ue$$5p>h35=B2>e>+-)rE+U%~TT)(44KzhVBjEdF9XA00Aq zlJ5@31?fWrC;74;@bd!!vFGo2p7yu!aY_o}frZOH;T!`Gg7>T3?l=Rdc4d7pGH~K= zVg3>WCw^JS=UDh!wrAABuO#O}idnd<`)w9}4)fn?;j)h3Vd1il|Ixy~$K$ofz=P1^ zm)x({E&R4KNlV8$WZ|pN()dveKjCbR`*_~Vc*(gk!@z@J9h{^22V3}$86RrkWM^5I z&oOY4bNV@2POgCyzpTq+4V?H_G5=*2zJ>8A22OHhU7ls&Bbh%^Cv_ z0-wPA^#)G-vTn-fTFGw2{|WOiv-oA*yxzcx|F-jRLHeeFlYCh>*Bf{c_}`fSI|fet zvTklRaN>V^1TIKFF>vCS_2O3s9t3{YNL-K}vGD5{-(lb+N7l`!4Lk_^LFRwfz=>bh z&6f?F_$za9LE6VSg7Rx_S(h^yr|LA0huLmfJ>Vx>xO{Kw)E@9*7T(Em@2np1Nfyq_kTbal z{0a;I5&Of89`JGtAJ6<>>jAH^aQvK-O7nZbn=E_`_qU}7Je}pqxJ=OEol!mD6+PgG zd%*8LTMM-1Khp!w%cOdY!yge<0(g0GNDjM*!sYWqHXc-^n%CrSu<(7H-*4gaoaAZ} zj6^c%PoDofxh>Z$!q2zh9&6V3`9d{E8>(_+^z%Tu>i2eX=e4vrxy?ftur0W`zGX&zdKBH0$1)bdL zrbUbJn=ejoBYs&U7eCd3U)G=>CDCG|^YO(}`cbO?PbmmFWI`EN5j%ki`xjAVoQ03J z*Ay=%2*CI7^_sYm<2oJRsU3+c@}7ydCxrX)XD0tJGnb-yxRU@ab0pKQ?{WRRlAM~5 z_65!dK{7e43+zaJ(NhYfzTD|^ncdY7a{IQuBro^rTwmnNeH7Qfmg9opcK;(N=+6GT zzolzz;r$=kpF)7>E&ci$Fk2?o{KbWIb(|mi^j)qt?_w0#81YUn&^5lx>$}c%l*VejLK~d1wx`Mb>+PZ)%f(vRj|8wp==gpm)8UFV3|9t*edGFls zJ@?#m&OLW~GxO43;=SBvng%D+m~O;!j2gy~9WlBZGIueFruewU7x(z zanvl0J{K)_*Lb_#qA5@JMNg(f_2@eHiW9Dka`zZ-w8mZUsfL=KF41(y)O$@&wAek* z+dbhvY|6DM7YeA<(>>yI1U>tU-IJI=BMbn%ct7DvpKu%nR6qk^cR{Ud%u|2~D*L$W zx^bX??N(RkXt;a224WTRQ*l?hdj+-QH9svi-z@2T5vq>JbZsew&hT_iL+-piu8}|w z=?g`UvrZJcDjj{LJNBJ$RUD4I4J|(5iF(~x!oo}s7@H2{Qg`lAtncZ)cLn*BK}P7+>{DXL+RoP#ktog4VzC z%H9R?IQ(1c9s>0gFq!CZH|{;9u%F&|0bq4Wydr3s3&zkvBXYj{|Wq{3B`X2VLx# zOyDagpJZ7+$&_p$8Opl)fz-X7PrEjaWp`vj6VT~U4h9L=0L!ZYeq~uIipgGKsnOBs z_LyD8ZcoRl9@nO)M4v-!c{)CD7IhWp{-?C#V@Jm+Gklf@m?}Uv#0gv-nYAtmmac=} z_Vg4(e|bw#m4zZ#?5-*4+~eBx0SN0@2R-E4bOd9{^~pyid0%*~F;ISpE)B>)e^OTfqbf0?5_4)4@%T3lBMkZ%R6Qgb;`! zupBzH65!CJ^Y(ytsSphrcv=1o_LBoj(fLcCfLsRT5Hm}=hS-4PNssvqRB@z0 z6}+U6paBAcsFE;ZIha`i6*6p*$L8ek^G5f&Izv4@J%t@lnZ;AWZm;Y5x4-M@=?dep z1h;y@i<3IPXq#nOCZ;kRws}uOXhK|jx+eS;=BmHqILX@+v(K~N@f2bZoM!&x?Z-VG zd(Hf3+MkCG^z^tofAmccI=R?A#?!HH&6UdvmliH7TwdsV!t#%+;&~cue;{cCg&MCc?dHq%9Hg7(F3rwncxoH%$fU}K?q6LcXpPW^_VNh{MOqE$I* z#X>U`=aw{#J?NCBIPpO=!t|6n0Ao=J!{UKpaV!oYYxyDFks`tosyR#%kjY~aY=E$h zMdMzM#ujw%4sa*90gQsNI_B8Rkll*wZE5s7Tynk9{jlmr|5_S-Wlr>2&xQ{l0Gqr~ zhuZ_|VWynkqHh&O_erwr5%(!zh(0N@-sqRGR25rAxab2=U;$15py5sKT~NtFGbIZ1 z8bQz!u6gO6=$8WVMnCaH#d<2UU8s)8gSy1gqjGpauj9}}92R{`&35jAHMXWdFnM9f zrMo)&4={|v=*OPuTi)mpcd_f9&%M>(3gOZBi=*#)qWkAme?g6X@mN|f>99)fN3H7x z4~Us#en-_&s?@W4-8jdi&RAX7J>Pn&dj#98?jheofq~4zHrO4cd%G_h?2U@>Dm4$5 zcCS0bh`uk_XLqmr9B7MMfM|C*cvCgBH2M^2)*^VIlj#1PumZ|uU8#Nr30mitls78b zM2Cp7Qe+gSt|39vfJb57FnT$Lxi`7jLvefs(3C5{G8QL%lY4VwcHHBjE^?`jN#A;U z_DP!b?K*o&=i4YY6Xrg5y0>eH+qLDZe$bTMrND^!qOjZR#-a0~r@IJ7SVkBEv^({{ z2Yt56O~PK7R0esXFyE9`@AK?EV(a_}CFZ)e9Ct!!br-vPio56V>;ZGZXwU(oPposE z?g?T~Sqxh(nEy**Mu*wyGf#Aa`=qN)tPGI<@PjPZ$N~dbshVeT8+!mn;PhXb4@>%C z$dq)AxDIB@@atfZYs(U7877YBK<%e-t0(ur(6$5TYKKi~4qM8K1Ce969D2J(z}R}e z)O-mWNj)IeA>bF2DNKZ5WJbZM()=eP@3TzM2jtmmUFA=pOtCt8@}Fb^q+fP{^=Br8+?syzmwZi;;?Z?=z&M`1?mG1o~Z0Y5?2$f+% zgzIwH;G-l*3L1i2c<4l!9H0*~z0psp^I-HwKPk!Up;ZA2bN3h9{)5p6L%;ZF_eq@7 zaU&%+pi~W%!O5xsRyK!Q`k@Hg%|B5D4NflY*zfe_pNf1ys{!}`Ca~zoBFFDtP`S*Tz<66_!Aq6%ex`(u6Z99;82EZNdGE!%p!Wc@NxEfVO0IzPLXH{pH%S z32xmbI1XMfhSSapZ}cwrZYU{@e&+3-DkRT|eoOs?JL6o}h4S>Ul-3XQxhMK+^b_0) z9Zf%BEvVSGJNmKoWXzA99|7Wa!v!QnaR&xM!Ag+o+AahVzt&PZ$7|Fd!-%a9IwU+ziJPAlS@*vi(RQ1Qd`{pgRkr z5L;Vbf?Wk{-U`g(E_7*^bZOggbQQ$02;igd9;YxBUCCi31FrKU*OuGBTFVvS7RW_E z&U?Bf??s_cT4~o*r#J&vrg*v?ctXl>q=_Qj9OH1pt*o`1 z=p>61R|MpQ1Ah#}RRuwqy(B1A##6tnh$_p?kEdHq9fanBjU+YMmvgF+0+T!{T$b1!!WXkys=Wbd6U;`(205Ejm(CoS}6=u4O z74o#4w+HqRyaO47B{278wvA=Kf!pk2+~TYVWZVo6>qq2GoTrankF6_Hn5$z17|JRh zYr^v)jQ+-Faq)QeSluab0FS)bn8f`u?2%!Pf&KEa7e1pyCYTPKWiLY z^`-P+CaxX1FoEGb7X5_RUokiBhvyYInqh7`n))Gm+=>~Tdf;CH9+_ZSl~Hz@MHNng zuu#D=+4(db{=z@_ek)|hAke~US2T32M)>QKFTi>5$P71n$1eN=RTLv!bPq0586(_0 zRf~FJp&9|x`LBeR#M;2eY@Ugsn+Cu{-0#1ih$qX5*g=c8Sl8q{Y=YmD&%=9q$9ZQ2 zx*sBSsXP7Z6xXH*9EfRFhIOdtn4j|VL=PPM5_%I1f>a&w*BVX!s^*XpF&dhx!bW4D zuCZa25vmURLt&#K><=2Xja7A$ovz0(1EG*UX=hmGd#wDfp@xBzm|@@n(J)f+qNbmS z-Hk+SPQhw3otU@TaB4Pe4taCRn~75!l!-{QJNh&dpyfkj(M+FX=5nrKKU|8OQk+e;2qy)@IPCbm21QZ?1<-z09Nv16yP!U1Y*CGstWN4c5raP;&}o*2~N=a~@yV+aoiVm^+}I zeKKMkzZBh&>DYxvN>~00Nuqy^=2AEO4!bAaNO6_|mg0OIas#h}3#y%l{fj8}raG1JyM~w6nd0GpR3U4Df9&jJw~A~6!f4f!<_mhOu_vi;ABd1Vx$hL8sDn~j|2do z57W5Hj@4z+w0KGXEjWF>CK<w0z_3d9kRK=AwaoO>0EpS49VPq3W&{KjN$uaOIVs@PL@4KG;%pI+qM~T zIcHohUFK#=&dj)6R$Ok(NQjWqzKrc`(V@XxtIx>5lP(qPMvO>fIo3f_c*3%Fp6Qg93k3T1&~+wL~4 zq*9jHeylW(HG(86&OB`6I;sHY5z8Nl-$oU-ss8vJ3Ld5ksz0!WmlEJ6oNYc8c)4vI z*f`(Tsx*@drD+3&?dJ5e%yOIRu}mmDUlzu>9-Eq;0LP}53cMT|(VKEZ={2&JtJTPJ zpXX>b&T(eBomuBY!{(%z?I`CS$=SEvxY+$;<6Km&w@73>OpI-(W6S}@PbH&$Tb9ya zXktH@NTKiJOh*$(CBV^N(GFZ!wr%*i9*D1)|RbkPXuv+d=!pE}Mm%i=;}3N$=jFw0Pc z#a=Gj)|kB+i}s_{8+QabH{FVrrpVhh_*@m@~BTh@q1$%i`vNI=~lLI9AGqLGOS)kTSxMX-ync zo?wa_AINk|9MgEgv{{$*cpTHkg6Whx(ooWSaZD2g(^g$l>LA(gA?$ba62Y`xXUdCX znkbld>r9K{m@XAeyHqChZBR0q1qpn69SLYv!XyNBZkKrM1QP46b|`+zswP|?E5y3* zoW8CN&I?x5tHTlNj*^AR+MOO(SD9k4?y}R@y*jS$#qm1dbo#n~j;lK%zV5-(*F6ze z_mcR!8E_;5XC$*XTNcY1!kidich2eSUKLmO(pcRt@YQB2#1M>MmVW`Ix5?5z+dhNo zAyyFw@WY}Ar=b{*lg~>Da9sL6uo{Z-EvZ7-oh!I&JU(d)n}{40BN5bU3<#`2z+_2MBtSNH|V9h8p&?$pfYgD215s;{q0V z?uIwa_dVahn{$HX=~FuRvNNZ`+SG5bX-^w40IQi$-hZGaV-i#!Kv`hNEX-%J1$bI$ znx%uWM%pM4oCAff!BB`I)2R(;SGJLXoBu(8I;D0tI86_ZF=2K{HmCumeJ(h&bTFD( zkok+EGg1B-eJqV_VERxJ0~%p=7>S{5W-JSl9o=Yx^YVn6XI;0^G;EpMilDLKTmYMZ zZ1b`+rA@tBKATzwJFuy9lq?7tNs3Tu7PU;-QT<8l3^?(e3+)-G2t;Xz-~92)_Qng}a9l_;B$yK^}mXPfAb*l*z}I;Jz|i49`k5k1i%%Mg2?=>I5~ z{A35FVd_CpgUJa5*^QvNvxYLO>5lT`=SNT%rg2P&-9+?X6-<`Ku0u%1P(>EgV+b>i zc}!kJklko8cTOd_1*eh!0NMVi;*Y-(&9*jKv&FOF43NyM)jQxNj3rsxK#u*Mb)2LyRqfPK}<^>8f)2L@svHDaSTg@RODszSn zfXYnrNKqAKh54>`y=nNlNWZg{v`F`qF zZpk#N4pD@^Pj`UWrz{^JT{=Lz>_&?AXRWATd6INtXPL%Iz1CTz(Q9-ETXwYbK>Iv4 z`gXLl3zQ+W!A9AxoX0nFe)UavPF_~>aRZJ?4ZcWta))r5tZumOOS|5|#5H>r1C+D~&)9^8=Hafr8MzVLKW!z|o)#w5yw^-0ZCjV?f3s{M5 zmdh6~`7;Ze$0X}#8Vh31msD@1Ds-i6#%hDL;&#y$6}?=6oZOb`i;C~zi%M=bO?)8* z*TQ8?s;yS`Y84n0HCoxLQ4XVfD7J8)xrgWxbX-A`aXK78&lTp z4y)~z^7~?j!K%XULJv+=0taj!1u3vI$?@xeBYj)SlN35H(p{o@ug63mzl@E0fDBJJ zJ{w0<9()Wsc--)vT*6VI)*esMu!-)mGH{_53Tl~ja_p+l5-Kmx96W2lPM4eG09Dyz zLM7FornYabfwq9X#GMRNG`oT0Ho>f&NrE1?I$;@;ZjueF;REfQ;Re%;RzrS#Il&z= z&fUqa$Ar5SyU7@Kv(#P0P|6CV3hZ z>po}Bv|L-G8>fn8D|rGFGC0Gt85|s#{D$TN!Pi3>p4C*rjIqZ+29xX_m7Ov6l910C zc9~j1_uYTUFAi(ouVV6uwLGjg*j`p0SL)uX`dOVjteJJS-k_0aMdHCzL; zRKKBp-)?LFH;>8tt^QuhBnLD2=y;pnxu&s{ZDfB7KF+XZz{e!JS@3a&eGYuO<$okC z?~iHA+>Yw<(MEQxfba3e6J(KW5oYNtR9m}y_b8{dzbj% zx9U|fsnol-J*J_gz9Rl_WA&I+>h(VAIBC*$S^L#_Ox{Ej7udI}jb{^{@C2wUA$~jr z;Nvl2O!9OJ6C{%?5=5P9W4Vg5r+PUjLKf> z`xjbz%wv*w6Cmo|Udx35d2LWMzSjy5)<|&bng~$WrJQuAi0Q(l(!v3&1vU$W9q1K+ z>qy9LF=0$9hV4#d*zUFjhV8bR<&cGDcU$qx){;RS_|JiCLgv2@&YD# zK!bGMX}og&DJF=?M=U|TR!|=;25ae#n+x{w&y_PK(>%G_jJ%z?1{VP!pUIIhV&Lx4 z`M-wGQEWydJlr(RZ{T}~CM4j&d`=`3%xP$@Zj99UbJk3n=$klUTw_CXWX-s`=19)U zhH%IbER78-bLy(Ad$U~1wIv^kGI9bf;hd(1>R=!gs14@?11v+2eCS)Wiun zWn3?(%;#Sd{x2%v57gGwHiRc;SEHffwJrWoc0F1X3fI*5Yk>ymKr0Oa3Bxbg>Vbl% zj=&&5B-e&~{$Q}NArzKeg~0~F1`n~z;D==XU~^R?$_3w{fanhV1Xf=fIJ??=x~;gR5rHq$=vP$beCagMB9xeb2EX8#N?9e8;FF1Bua zzY2Tv+s^OoXWV7)XFJb)?}i&TI18Z2OmSwVI13g(J*Bb^*;5`8SNQ%rWTxSzG}rmc z;=28_?fnm-lr?@sj*+)5Ny<#8g+&H_#zqoF3eW~B;oc7L?lm4A`um7O+ z6=&6&Mc&J=8M{*opN_(XhNVaea0*g8@v;Rkg2fpG(l+*fd)nLftDSE@UMid*tg@vz zCqtoWzq5Uo{Y~R8`-APyhvu|8Jxj2T-R2&GH|M`mz!v-9ifuRA>zrYG^VXfAG*=GtmPW}0OwYKO#2VT-R2y(?Z#~$ zFLI^aDz4b^95JsTeK%gWU~jb6}x?ybC&bik|_}% zm{<4ooA$Mbgm>S-!cVVsb{x!Ea~$da!He4Rc6)~HQq#Ev@szv7)j4IE^9I|*A(hV2 zfo0C~p3HNOYP~+Uev9*65#_cm%MaU!Y(!Rj@ad&S9vIrf2J`}#^u*~SgFU+&DdzhgMF zLzT|y&wzzXR0~BL@GC^HR$7R9r5sAJFF9dz!Cb$fq+%Y-d{yB{XuRPI)dzy%m62Mb zx<1h853O1YSm_nM#z6HdU)U(~6$PuRSNX#W);6sSG}5nt8&>+mRXBOVgekb8zR%xW zV}$)pEl_7}Rg*tNHFBDo!#OLf!qxRT;i}N8P)?}6D(J7t@hj82Xbd7!C&;R)Ss)&8_1NZ^_)5H;fc2HYEI@vVe5p(!*L*6If67Q+{)tpyVeu^2aFEV1ga!s9yK zEaI-Vp%Emr`^FnJ;Rfib=GH3c2?&Tr2;oKk>Tn<^!V(l{xY`dPO~TPXLGTJIfVOkg zz^dyFb<;2 zz+0#udJgpTH9>fTkfO$_=2Z)zN1N*m?5fpagW8d!QHBgK3aj|%_m&AQ;UIK-uqq6{ zsl?GoLtzdGw^Uou;;*Jmb0h>_mNNkGm%uQx*rX;9k1&R$KB&Ghw4q7$Lz!=WBoL0t z_xfA?jaIPu7Wn-&oI^e3=o6hS-Xt*Iz&S)(H{O@$!<|^OPYEv^o6wE8uYyh#5kq_s z-M(0O%lN7F)kInv8>*|o!A(_bXcS|g;*be8gz#kra*%neLSe8t5>tI{)m*~|!@VX? z-asqNT`X@CFT7X%`~ zYHq^U8m?N|=;ydz9folUJo5sf(&k#D1{@r0SOWm`oHc*c`kGeFz!spl1V9rx;o_hLYpE+`JP1FDFvsaxVJ!34!A>{0))4c*mtWhYuKilGV$Hm-u@5|_#~Vy20O zHI6^{G2(dna*QT9XX8q-sANX@6<{T-6c~~+=%HPl?PmI68f&OFT3{`JPNa~XTSdbT z`pRF2;eoLf411xsNK+r$2@@GAfwP)e%7l)xFD<=A?}^x;no={EDFYD*N5cn|V4^GY z6^1a^ z6SBtDWsSRHeAYM^(bM3}2$jawwlq}36$VfBs&N!Sfgo@MVKt!@SWGcOuU<F zhT$&04OWzveuJ$jEpv;#C@rhoQIt03`aXqex!0r=rcLVTTby>UX}_#b|FlVf6{d{= z9^i#KMQP4b{BRTHHNrnk;%CP(c_o&-VoTn<{t))8rM>how@Ob_Lbptomt> z28*m6&(R5z9goimk{wUITEez%iX8r?9DI)(PzSvGTPA*ZaTekHq=j+(!8G!7V*Fgf zJygK>7{aqOJcsZC4ZnnNtcQu^;FpfE-AMwC;l+gKYWQrz>3NVPXB^=b8vlI4xjnuk zn;oAwBuIAnacZJuH|UcNt1r;`0*t8sU&z`nA#Hg4POnG2*>X~Cc-aB zg6Ac{Cnv$LNP;g)g8P%;fh2fa68!ok_)ST0OoRG4;Gx7|$jK|Bxc$t8gOYkxgFPGwF5?=E0l9wy4uxFp?y`rel>$~Fe z%W=lP;F$8`_WQ}Slvy!XLzi;4Mh{lt_H@q~$Sx6B#^8a{z= zuZCYlc%6o)68?L_(blo>kM%#Q@v|RJYBJm_Y2GaRN=o=k#D1KcrbrClwr!y za2^*~grh&zc5^j;EXQ<768>V1zgV&xr3ycunOOfy1y}u3rQoW6eyHH8pW75%m9tsF zRXM*@a8=G73a-legMzDao*^F=#Oh=O7M-?2;{2V`@C^-6p z$KxP6prQP86#m)7!0qz<@FNZ9e%z?xoeHk@?;n%k_&y{|+>b0Ln{ddpArRZ0 zrnEaU37(e(pOFNwNP;&d!8azse~|?Lor0_O{;z_o_C7#3`aest_b&?nbOnD#!7o$r z7Zf?86#S6FugZB>!BsgQDRRzL6t;iXx@T+nrE4V7BP?0lQk#o7iugY1Z;HsQuik$NmIV%-@RZdXBRXJ-FITt8$ z+7y0O&K3n%<@}8Bu^^*Bk#n2EU#Q@BDR_~BA0Qn23;UA$>p6vAod*tS{5%i5so^ZA zYY+&9g!0vSX@3&@sDh(DEdNstXZd~TYkkP8&hzQk*Ztz>&#M$%)#qA8j=I14iGr)+ z_lP0~+vaufKN`+@4kAO4S6$c6A)NhR4&|6eYdFinH#lL^?Y%yV{Te@IjlXL+w@b%C@#K6c=);MYWr5>o7!zo}PT^+Ze?kXB zIz!$pyqWUw79WxDF$A%S{Dl%0{LF(;u7YE`Hfk5o2$*o&g!mXbAL5wB#Q1B3mq^&c z`A@leHT-|c0Sh$z?<8l5hNlsKy@unflrc5Qo7FC#hu3KM+hkX_hF?R^S#HvBlbm;} zhJQf$J2d;Ufs=_+@*~BRq}dF+P^?;ToPt_!tfEqWHN)!#^fJ z%+T;rQcYu)hTlVS7HRkegs;@_sT7CJ8qWT@Tf^6pKmVZN-8>#O{64~;(eRhau77Gc zzo_U#4S$RJ<4XT&b8!Z~Xne2^dIFE-78h#zg@7D063=nxKf?Zt zhM!G-;Q5l}my?`>8b7~u=ARn=1nK{ghW~}+e5K+1vY|d?AGe!Mah0Lr{YcNVHGBxk zy->rqlm9Q#@Jiw@)bNX>+l)CH&f~mN!|TXizlL*ryl${vm88#)HU2lK-Kd81bI+e? z_;&IS{@p@MEZ<9Z-L2vL`NxAA{w?KsonblUgukHizen=l)bQ=pzsEHEBkHfuHGGB8 z8ov8M^|;*^C_hlc-DK~X8s3-UAOC0}CYEzKwa4=`tr zm4<&t@|!fA*WC+%GvKhd<9^eqI;GY5YZ`XTB!CfaDix z{5@h~mc_W50{JG;Ajem?3Z(OVKzf1nQQRB}d{@-bMCgJyJ za&Dpg!x}$5t}*s${JcIrukq9HGG5jAuOvUi>sm!(zmYn|#~S|`$N=dpg`Zq0@N|;L z{r(Rs9IoKQ1gE@YDL9_9Op22qC^+)BQk`4{NB$L*pQ7N%zmNC}6dd{2QGT|9BR_tx z1XHDkUqg7EhA$_(A{x&7nX45X+r5GEoeGZa^2^z-Q*h*eoW|qN6dd{ACY(P%Wj}AA zc;nAc5l4Pr5AIOpp!};y&V34w{BMx|A5w7SzlY>Mso=;zhvMKF1xNl9B4o~9Q8R&^83(0VE_D!`4k-acane3P;k_L zG3C!vaO7_x`J)va`3KPFQezby`Qa}*h%}LK3^NpQC&gQthCfE~n>8H&s4gacSsBY& zP4aKk+Wm^;->u2v@2&0A_)AF6-xVC~;?MtHQgF2E0QvJx1xNmo=x|8?QgGy_urfYW zaOB@k{QS8s_xn(i|Bc2!kUqyU$luIwt&0kd@_$YIE(J$@enzMC!#VyYYxpA4-=pDokv)qvya?LBRHNa~Q9N9&;Hc*o((_sk{}p{cbiIP3{yZ=J zT)|P!N5p@#f+N5D-l$>xR>6@!LZA0=T(JLnT>nYq=U;h0sNg97XB2Pzc`?dC`S8b0 zMdHtkS^k$a&%CI}LH-Kje?`GjzLx^-p9+rr=hJiNcNHA@CsKbMS8(KCNzZ>jS8(L# zb6}5xBmc|9??A;NvHrZ?r71Y_kEG|PgB2X*^Ll!=f+PR4#DA`WBmWWd&qWH3{6pyh zYMz24zqOt!IP%XW{#hD+4dGWPILcW|^Gv0Jqnt;Hf4PDqKmG;)6MsIA#mN5!@i%Gw zm(#dgt>DN%gB~jL3ly*z<*z3{T%+;dM*Lk0j{MgW|IZX0=}v&-;_T3XZJlv_X7I!I7W$3C}Ay@;4IyK?O&CeAbWYEd@vZ z2Z{e}1xJ4P<5D7htl-F>LJ!gTwI5iF{0@ryZ#Di};q$=CQN4@c?n=X4YtMeu8l<)4w2 z;~M3^O8j#){@Y3a#R`u6=h6pDOBEdDzfbaSi^K)_+JpgBWpCJAVG@SQamudKG#J^0# zKPUWJ4R_OcyjR2X3FjB=u|9JMKcVq2BfLND3z*+eIRD;(aelAXWg7oR;;+3IC~v<6pAF^k)q}i}d@qhVu(-ztQk7iGLXF`&fS)@#ScE2I1uzejefc{SB6L z3E{VD{4)uELc^C5epJJMNcce7Z?gPr2p_NEHxs^C!|xzGq~Z8?*D&$-F`GW9F1;?tiOc?M+7Lk}g zh5UG#h7Tf~-#3Z;D2Kw$Sg!G(OZ-35aQtI&n6@f7${}-%Un)4-HJ$kH*YH_{|4qSB z25o1ILkf;^mJt6*4X-8KN&9-XD+}si;_sQTe_Dw@N8v~L8woE~aMWis3V}3N!IA$b z#J@_ze@}Q+!|x^hHyX}wkbXqN`Ss8*Yj_vg|DlHSE4&HXXgI$f zc$J2?6Fvd{c#eU&u47cL<}NGUu*n~+vxnn{98$WN)mjahX0%7 zXC%ST)bKm#9CvmSe6)r?MEmCpli;};{u0TbkOZHq;kb9lRFDLpsp0&0hi50j%QU>4 z{Ie(tzD&daM)6#g1h3a{eh%K41P^QYZ>fLRB*E8f_%zaIQxg1o4S$UIw8#a1MjIZvR8&eMs_fO8D!7Ph97@YwmKAspLxbIdGPa3QNPB&GE(PjXs!)_ z6hT+5TnR5R;vBs3Cyo=|Y0+El(Sgm=BNRI8+N5p!?QpN$~SR>~m~~ zj#Jj}K+h+frUzLGt~?)G01+rdO&381W$N`0Q;@AtnTc10@*smU$EzUFTz{;FbNhTR zfO4d9?N^hN#)0lHwx92Fpi-jxSxM@%Jif1>`fA%q^L+XnlEdY!H|O!WbE5t`8kQWp zu!A6>J5guWn?F}=1WcC+knu8h3?%-(n9TL&y&8GAP`Mw>mYLts^B6ADd9Q;49Yfx= zvt^B3d9$uMZzq%_vVZf<@%7PuJhJKbx}CqD4+W5h(YadYV(qgY_dx;Ddi_V2$Qu8*_{Z;`vMgCcUXN0J6+>F* zeTgu2E=NAD{{Uu`#P&1vcOVk^@A(A%hg(~&&wfRH^tMsGjdQ j`rHGMakL7r@VS>}u$C2X&PY_>*dgn`DR0(Qum67l;2GHR literal 0 HcmV?d00001 diff --git a/src/coxmart.o b/src/coxmart.o new file mode 100644 index 0000000000000000000000000000000000000000..d4e0e98c891b2f9f16eea8d7ebb232f30654cbeb GIT binary patch literal 13600 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 wZ3jrLB7qAAs;{X5v literal 0 HcmV?d00001 diff --git a/src/coxsafe.o b/src/coxsafe.o new file mode 100644 index 0000000000000000000000000000000000000000..630d8fa1c8cb9d992ec8e9a48e75f96a2e41309e GIT binary patch literal 3264 zcmbVOTW=dx5T5lWjf>kji77M+mj$)ZB6im)ZAgofTD71Q1&Tls5~2$0_4-2W-D)qv zR9uC`8&cokp%UUBz)PQ7@zPhGfH!^u6d@rMsm$y-vtA!>gw%<0X68F{IWy<7{_N$g zS4x@&Od4#$SYs5RF_)85u>p_35x84jI817%YTfy8iM6}cD|b586Ssf5o{pJo|CSKf z8tVjD3w!FognRLGdIIl+Krjf#FVzE9iOjN^!b(fMQv$r;ZcCn zF{o5F5dzRH?fkMnf3EUU<=N#+HL_?N{pP|lu4xwZGU1nMCG^SY2`Opdu=u2e4!~df z-;3sVtREYjvdGJ1(=4nMo=09v-D>-uz)4(=EhKYTyQ=$mw{N zi?c`vMO>8hr?lEHU*34Vq@le%^kci_#BR@yooF|*qn;CbZF}qOoiGSudl)2s9NF$5 ziDEBIr>`ZUXMW%e``#(r4ceZ)9ns8dgjnx5gFzq7l5nrT=M3y9bfFz2t%1i2VvY;D z_{O%;JbTu7(K=(*4RaVLzPHi!d@t;~s5+tB+Ze5{nQNyFvul`_PZ?$uw>P?ef=*`V zDp_@+*l~Bwt6>m(ZXASY5e9x2;9|3R&N#8%!u2O2gZV;|YO9~Fu3PofCk2{z2Obs- zv}2BOwR4M3vxPTbcko*&-;0dWxeo5;fCN}5$W<~sB=2Zs!*!y za9|&N@-(rL4hLDB;5s}sp|hgH)a^{Cbik`rKsqcGpj7YT6kbV@>AFOOStzPNhw4wKC0&5`+}Be5{YgPWn-K>O`Xa;iCKpTrWN_3vGn~U;E0jE1eK1_8faGbW(&nWn=)Xz(<#(y_wpYM6T zUY5y}cUX)2siogm3QY<%$ z*HIypw%1C!JAJt*{H{l##@>Uz@3B4R2g?nHL(j+5K0YuO zzF7Fc;DaNbyxvYHbcUX+>cN?TuGFi1Zz)=X2Bhp93pMMzRAB`LI>QYHn9D20=c9%= z<>9?OD(#+;xcU<9R~f~~6MeZT=7ajLqA$hd`-WmlJ<0i;Ni|zP*U`iYbxmYDk`C`n z&P=tXFKJQ#>au@-NJr`)?GfkY{#`~)jY%%Q(tz};VA-hJUcng^BV$8?oy=1Rs_hVA z6(h^9B*^*D&^|3?&x`qwMyAAO71pZiMdnaYh=UFQEmE|`7~75URI3H9zH1i#awkRBH-8`b(L RW|9Bra{ae5Pa&xO{{f@y`|kh% literal 0 HcmV?d00001 diff --git a/src/coxscho.o b/src/coxscho.o new file mode 100644 index 0000000000000000000000000000000000000000..06eacd1b6bcfef7c57ab5540d6fc853a8b1b067d GIT binary patch literal 13656 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 literal 0 HcmV?d00001 diff --git a/src/coxscore2.o b/src/coxscore2.o new file mode 100644 index 0000000000000000000000000000000000000000..b7f03dcdf1c7a3ac0d644d6048fe658b8b4371ec GIT binary patch literal 18656 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 Dd|mc(7#JyjdyB=4z4YJ{ z+Lt~4&X2S{zo1CWzfg4PtDGnM`(Q-UX(1r0XugUet;^!?Ac$FT zP-$+O->P6pIyC+#z>k!_og>5#OH$64aUIDvns}J(~8*YP<=HvF#_dd$EUW8Z1 Zz9YKyRbM~q9BKYu@_%1?rXckB{{yn*yXyb| literal 0 HcmV?d00001 diff --git a/src/coxsurv1.o b/src/coxsurv1.o new file mode 100644 index 0000000000000000000000000000000000000000..6c9fb5a594b0ad1f5db4446342303a4820811fba GIT binary patch literal 24752 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 literal 0 HcmV?d00001 diff --git a/src/coxsurv2.o b/src/coxsurv2.o new file mode 100644 index 0000000000000000000000000000000000000000..dd6c84ef34ec816fbfd5bc1e8e1b1fba5cdb6227 GIT binary patch literal 26272 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 B+miqQ literal 0 HcmV?d00001 diff --git a/src/dmatrix.o b/src/dmatrix.o new file mode 100644 index 0000000000000000000000000000000000000000..22492fd78963881a9d7e6cc23f21faa869ab3c9b GIT binary patch literal 10904 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 literal 0 HcmV?d00001 diff --git a/src/gchol.o b/src/gchol.o new file mode 100644 index 0000000000000000000000000000000000000000..bb494a398023e851c4c82f1c355e3fecf41faaea GIT binary patch literal 16208 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 literal 0 HcmV?d00001 diff --git a/src/init.o b/src/init.o new file mode 100644 index 0000000000000000000000000000000000000000..319abdd9a3fb7425f9f582a7d0a409db7b7c0a0e GIT binary patch literal 17736 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 literal 0 HcmV?d00001 diff --git a/src/norisk.o b/src/norisk.o new file mode 100644 index 0000000000000000000000000000000000000000..43c3cffaa5a2ce107e8346a872f80d6480d39599 GIT binary patch literal 12208 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 CsMIU~ literal 0 HcmV?d00001 diff --git a/src/pyears1.o b/src/pyears1.o new file mode 100644 index 0000000000000000000000000000000000000000..148a4473dadcf2c34a18f6296acd967275ed9005 GIT binary patch literal 21320 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 JTqMo;{{!4_S{48R literal 0 HcmV?d00001 diff --git a/src/pyears3b.o b/src/pyears3b.o new file mode 100644 index 0000000000000000000000000000000000000000..e29cec2de6b326e9dab298d1a93f5de5af455960 GIT binary patch literal 24000 zcmb_^4SbZV+;cx>o@dxxR&le#vIG}P+$545qe2{AnWPs;a)B5p#){&V#Vd+y zimS`JF4inB?|Q{|_Xp#keMR?^-X^&Fy0>~Ok?*STj;rV@_2&4x4|-S0ntk3o@D4R@ zAJk;k`?`l;n+v*qUAw$)s46^p7A;kD^>uCa?gfh2kBYl~OXR!dT_>3Ifz%FLsvB$- zcRgFd_1)k=dDroZt{0`euj?a}Kfv<7?z_BM0PJI+`!PwEcD?5#71X4cC460Pp^At4 z@ul8XQh(R6;+{>`uia2t>Us2IkUI*bFW4t*%Y$#qDqq*Lpry3yG4FBKQnu|A)Or~B zj`77kEBbsr)u-IP6Tn0J&ZBPM>}L|^%Y&Ds0;vsscb9kl7Na;tB4yh?>{wOYQ`1)g z@!tUrE4n`Q^-TM&3&_Hk-yc~X9G>OtarOE-pKNP$G>(-sK%f+w*_;uT-lo4?5fMXD!g_5^x-h9R(}+yc1~07}ocdXI3u zuj?2!K`|12OWq-CFc3aey48CM$ZdU|`+hMwg-0v8{tW(Dz7wvep-P-^ZO0n~ z1^jy^akl$@Ib_>j_S`qwDMWEkS)cF3R_|^Uf>P1bW-ab&<1`t6A*t00xG1b?-%i9Z-5B$Scg)cXFuH1@s0J%n9@MO8BTqyR8bd3S`V1WLR zILmsl$wN|ZmrOR0opz$zb@v6&$hdbF44Av8vJY$?1(|I}J@+kk2+`pA=)(q2{zcFB zxxjfIJ=N3Rhx#yrg|GWglzJBcC6K6;MAu#3CSUMnU(fJYC2#fmoV#QSVL!J3hRrdY zz8=?ZoN?`#D{a1>tzMk%$mBwoN>LCp7@WMzI}657YaKUr? zCGhS`=)qlHAK-6!wqKH}w|f7I_pa66J1V-qD2EvabA5+|aN>ip&xjdk#}BmBdm+m{ za4+fl{F_!^+`C{&*ZCSyd&~z@*5~W4_AV$zRS+%^UhU15nF3Dj^5&rLoyT*4$pg&- z?yJ3SaPAyXpw@HmCJ3M}c)v6ZBa}7#l?$HQ-V2^pZ{rlXy71-V&bi;W;#sop_kj1} zI1c~4OtablmN)}_hQ4DU^568_yR@&b50XU&sT`(%H*^(DVR%031ERuP34$j;&-0$0 zvvKgYO@%Auz+UV*#J1hnJsn-$*5~V*b{dCe3vixoi_lStz_@@Whyz@!y*{|YSaiDf zTA=lUZ}w_$6ZrHOnLi)`V=yZY;r!?mU*|Cp8L3?O(sOUomwkP{PL<6Tr{iq3!g;>! zxzyJOS&g%8+sTfO!q-c?ACz1vEPUu}1&rNcxZ@aN;=O-0tW4lc=^Nm!8@#>XS@Sg5 z10F3G&;Iw0S>VQp7|Dt^Acyl`SpNbviNCEHHF#FSG^Y99uifU}UxPaFn{2L?tHUul z%s!aYX82ps(YgisnW1r6*1_tcoC{^IJ=r;hhr8v1*=PDN}z)Kb^Dk(*!A;@qym?P3FXBFMVnQj3uJ$L>Rr4<@|i6=)Q&dS78Uizzcy9 z7h*VG^fJ?(aZl{a16#OhfCeu>Skp~&>=_I=^E4=jthrda;ovJ5C|x;2gyP1 z4EIjdqgoD@v`Y#|GlR}qYq*8;bU8{Ybq-~52q5CL>tYEc`B0=?pP)R^Uu*@^t?<7h zou%kYNRLzWmq_O*x)15xVQ>K-Eo7!B#*)k|#W*ChKrt@K_!KipGL?$SkjyH@xUG%g z;T?(@YHb0gNioA^2ip{rC7HNlMp-T3LAzqcSaX2cqL{H3ZcX&wRS>~7OJv-O<`uakNp{)f;LFjc5wC;PSUA~?6oZGu zO*R-j0TD^M^KchbWPXw?NRm^MWTBn3Lyk0qh75NEuE{P8`J;0U0I~~1-qq-H8vUL| zzpv3BYV>)H{Qqa7OU)M%GR57OuijUKGgZjBzI z(L*(Qm_`rR=n)#7snH&d&eG_S8a+y*vo(6OMqj4UV>EiKMvv3z@fv-(Mo-Y_i5h){ zMqjDXIU0SHMqjPb*J$*08l9`r*Gqa7&H-x@4kH&{)nN{g5CTsIn!w+}UdP&$a5{E$ zdy%kmQP#0XjNXuB+?Pq4RF$Q;>y_ZRG0nodK`!DTH0GN+vsP!q!umRkjg|T)_h<9^ zv-$nm0%pgw3u_7n0*g{q=n=T7PzWe|AQHc4mKe7PDhQafsGz zX2+p=>qhi=yd>u!>D=?sX2s4`?7_{Kua66B9yW9CIlNgpbW?wK=X1YRZE@xZ)X3g{ zHCw`}#%vIl%_v0%yO2{v)&7szQZ}R7ma&Tyl&3IGL^L)qsu8Gz%hwe5uJ&{J`TZG3nQ|Q8{DezkWzZ~{!=)QZC<<9ZC zb0$r+s;ybcexb-rCE|#I;DE|oxxGl)9$k$q5!aq0dM|HuqxA@tjb5 zo4~&j{-p3Y&E#Iqm9ZLrNW=e_aTU8FtdZ8Wnc2gfnG-TcTB8PM!9wcriebZU0tog7 zB4I&vjSc0Z0lOhq^@gOT3u`G zhE+`dt3zQ<0ZS$`UxUoVg1xNT&s-6qQj{6pa8+8v?71aYG0C<-+o_a>SEVw1YEvr1 ztNsSVwJ8kurZile%5ZN=!?gnpe@}jq1FI(89b(G`4h=@Ols{;4QR*5$|sWTn0(1jk=5M2WM5Vf z?8|CWVc#-n5gVFZ%$U@CIz7OrY?2?FY{#V5ZpVOjnY7rBvKQS-CMVg@8YVSWyEofD z6H!d^Wp=wtCOJpoz`-QP0%q9W&CKw@2jrO4Ozs_E@>V)!t+5Yal}wHqtlR=sO!A08 z9<%ltv<(2nBpZZ=W)J_K%~_zt$?a6_UK%j3>K4Y8k#bxd9h`{fK3Lslmqtu zD;?!Vrq?;JZaG9NB(-II0pGM*P(TLxfRl7Bnhf=F(N`9slYOLHu)q>7`>QVf>cDtM?JiiQI%s23I^eA?a?jl@wOlqI3oNOS|x zAX*b|mQp~XnP8wrvKU`6gt7!aKIK~O2Itj|MON*cMD3h;@?U4|%6XkD=WV@lYwgN} zyKzouE&i)rzvt%lop;ascuprgdUs|V%=q-=%FbG#E%%?`>Ns+1`8U3SY{n{ieH*Xy z@p7kgNWS}zop&E{Cpu$?0CBqK;Z-VnWQ}v9JKs6o{f@KhUtT~s!;w2G!=3o}?%Fwx z8{JPi+b`^L4t3O6&fy2kor%TH;qH7#WwxVewBzg9?%D)e$be`4E=PuY&aKW3i=CN{ zYb^J3v0vpWcYZJHoWmC5{WiS(3NLkdS%Md5jjVD`M#mlHcxjY)bpza-8Ts<+y#5}% zJ6AS1qwWWsH}yJKA9UW3@9qQC%6JE^j*OR9yT?dYg}~YF{ugKFD)%1uRqhJ7cDfI_ zD-NK5bCF}R<;-%-vVP`11Y&dl)lrb`9POBDIiK9@KIr^|aLZ;1rg`s1R?UlI)j*M{QDH?-D8T0{u5p$Jn6(nktH1Ai!7FPZ`y1JQbD zur$ybijjChYdBs|7l;R&3gUs-+E_uXDG&|S7gQ|wMb%B}-WCeRMXb3o z+!$z;F0O~<4oN2yVZ=lAIr!p+zo8}27!%Fm`cOM)sgK0{ZP3?1V+gyTx+<2JRr{A$ zSCubaS{P}GgbDMv2BK@hc~G*dvZ`z$ zG{9(v>?UY(NhsbFsTZO8=GIt|XpFYOL&YlpqLxTqprtIl4lTw)@#1(q+FU0p%9bvw z_6dJmB!*)UNkA`PuwsFAs(%eFkpK=_Wi+&|Ig;RE0K0*h>{SeU7y^NXErA%j+0jffQ7LZv2I&7oMA&kTX6Rj{?q&bi(gG9Ea zls#BTA)l31nPhrr!jL1-Y*``_Pin6StqZmAfL8gJheGwtVd&Hhki$|RhzE+K<3;{L zzYLyV8+)7>7)4zI(#$V;nP*Z9cC{tcAQuQ23QW{`*aD)>IFl*@u{d-p!S2R` zX<(@c$sqY*rqve;c>`yVo2qWp)NMM5SA}BnKr~(*SsMzAsM)K<&UT zk0he@eDbf02kKfvoM|u%A~01OM5rMU#QcSEv1e<8zjf_G9B4@EL^K)-$IIH=qM=x< zITD6R7)fA=Wz=!PK=){b)~^c%1&)9Up-f3!{WRgKP$O)s(GB`eEtgig=->ob;l@bA zu(4&x5xg&A&lT}HS_O)fc7 zH!r;tYRGI0YL>-#yHN>>vj`X56=e&nZvn^E zg3Iwy3(BGpEEml|5emZMhhewp$z)Dl)FOFgA1cDF~yN8u(=OA9H7mJqGngqR*v~xV|9J+=qo1W;VuW#xz`I6X8TGRIhRy zH+DJKRor1JHp2Q1iO||6#G-`@Z_LT9se|o1q579MH6gjej>1{_Q>I<7P&^63!z*`Ku|T&WUH}6vZj%BcM^|6!bZ80N(%e4p%$XONh+ccc)0* zcjv&jU}YPpz@KFdEKc=K;D8FJkZ)e4z~K?0QQ#Ril!5&nDe-~*9V799aZ?ZE2c?Xt z6JBgIOAY{|v~lFmh}Q$2WeNj7KMh`y2Cq(o-);2);J@gYU3{@R-vd>GEJSXhXcBD_q+%QU-M_!m{& zQc_&uzvbqeaet{UE`jZ_|6!hYRytzK^G5PWqmFxc`q$2;z$W*m6sKc4SmTQi19vq# zf0&;y)S-j775(i0)n^5WkPv=(#WhX6@Ag;t#R(RESKh=oX!7ukU$FevH2D1*4lgy> z@(*hG;C*z!>`cvd+0k7^z&;PK32nZJp~%B>%sTQv6y=B_h5|c@qb>!uLJ?^ zZyXgs!CMaeG2TTuHp6+y_%vFgO+1g5dc<*6X89t*QQcJ!L|d&nF8@rpIWDiIk$*FddKp-YWB~%NwTYGF2k-ohub{k?FJ6NjrOh6GBtB~3lW5#G8~9d=!!85o_2LHx zejUZ(CkFm1>HlW~|1I_FsDab4h!+g}5>@=0fd|RYcMbeb(*Iuu&QH)SYR7TgO!E9l zlkx3@PcY^kA^)E=zHb}&Q^bE@;E$6({I(hQw-A#Uii7&i__wJ2 z6$Xw!lE#v2;34vJs)4^sIKLXh`j1oG$_@Dn;;Rk(BE`*b;L00#MrYu6P=6B!j^BY` zx!b`1o%Ht@_#E>82L^tI^!$T?myn*H8F)GM_bCJS6MoXbA0oT28aThI__l#xMtVLp z@GnTu=LUX1;e+VT^^W9`5I}hWt^If62gW2!F%C`4y{k20onpylCLxp#EAEKlTUSZkJ_*fftjW@do}P z#q(MN|2g?tXy7kWeCC-r$(I}W3zTm)2L1%~htFT^e;w&*HRKnPpBoIE-vQfZ;5Fpu z9s^%Tdj7Y8I|+Z-!1-N_#|``^)UT%v{Fj8kVBq7ZU#}VX4#NLv;2#kG5#7-}>XIDa z46?&@L%Al;24>f6hf&{5wYYMnnGl6vrI~UO@N*8jgDKe}KXAQv=^j z<8{QqKPLQH1D{WEeon*De?Q@`XgJ!fC;T-HM|lt7|DoY1zmM><8jkXZ$e#-uj`E+8 z{HGd@@;8&bMdOCD_?J)d$uw}DhuIpAdOjdMS7nq9OdUw9J)0e<=2t^?`k;8KTYxv8u)zrlHg$t zM?II|56fc)zK-H^%)kc|e#XFWpmBds!_l7v+5Jev(XNN&Ki6=SKSc8UIU6yQf0yL> z^8w=c_a4cQpnkLbNs7-{4ad6g;04M=4M+WJN&h4bN73g0DoBS&~TLh9m$6@9OZdkh-f&gM)CQnhNC?G zEELOO!ci@{5=0QnNdu26SiEiEn+X5hz;_TnlJbl7?ONPr%?pVSknpKFh$j5`LS3^Y26w z2F`~Xo`0-AoAT!oL!Q4!c*el-zx%@SmVw_)_@@TGlyDEt54Ouc6Pak>{Jlq=fzP0Q zDq`T(gm)V_e@^_df!|5;y#~IW@DC0AyMzy+`NaMoAp9x=KS=lt4W}tB&(s0!CD%t&kfxk!i69)cYg#XUKpP>2vx`F>+!p|CbHqG0M2F}m1 zFQat=(*nsGC~wE7!LKs#N2tTsrorWIv8O)`-e}7@_-Zc0D1OGF{ z^T9OuK?9#a{v1w&A2INKB>!X@{J4ShdAm0ae#*eNQ+~dZ2B&byvl2}em<7pq1<*Yj z5{Yjle@#3`)+$+DUgXC%w8Be;aF0jTy@{!4s3nje$Cpm?@s&!EUl)ss{AdIj6few& z*Aa*f#^SSdrf>#u*uFkgmuU1ihZ`cGMbd$~I(T=NIef=dmxQ;@!j16itd7Ai7D6l! zc13ZH%yjPeHFQLIZWAJtwH3~KP8>0Ar^Z$o}al=^hIIzkEMDRMrxcLqT zKFh}xUBCi#-%StJdMSVLIUd^KF&;;9lL)6}fKVaUv!IPAf`;ElCj*6||F7-w`)br# z1b=#A`?RdvRcxQ{3!nyRe8#MoE#$x14d(g21RAAkzncWicr(xUJE*;G8|eeo{xzC+ zT+eK@Ko(Trw2JVP&>YHJHF%dUZzwvDUJ%WaK}|0#ksO)$Z(S@oIN( zW>%Jc6o0~iW5jPNM-mbflDbeK6daYyaa8Wk1}^*r?l6CG!sQCCxCHYTB4W@<6S2$2 z!*!=45xX?jzi%S8y}$3-Aj)0)Uwt-!U_3l~N!R|KWhcUSybGqsHca#!*uHG_KcbtS z1F2>0>2TB0O=GzmE7IZLehNPyzTce=pL#R)6(GJc9=`I$@$i|ikB2XRLCI$}jE8r; zFdjbp@cv-;=;4a)(LxpclfUzXsj$@Krwp z=@;I3FplsYZ$MLQ?Ba>=qyJ(Ak6kb^F~Q?Kuzpz=n%Q@#R0XD958rx^is_fbke;Sr zwjP2GGi8SxpaC3Qc?4~OqgSsx`|FUN=VSkU5*}}ML3j{#)8{a@Gv9>#LB4kW4D>&P z2|0iNS>PKDg1INZ@c9oKCiwkmZ@>lrO}~0J2)-t+0QmG(u`6R&#dgNxPlr#1d1-nV ze7<)q0nI2JTZ-T=HKIYVcpwP$QS7)sa7DQ<2JKxRuU$Aphzco(WZBhtZ3J3n4JjcI zlBy<3fun2j9)kX0p`tRIcSWE=N`X)%lKe12QVOUxLl$QsAXTI#^Y-napx_w7%1|(L zKN?WFGbC1yq^YA7$DBaa^_~h3Bh7|rBah<~dgLr|$Um$K&cmi=#72F^P z1_~`oFr=_r2>~gzE1^OPT}r5w!d4{&rLaQ@AtM73Uaf>GV+e#nCDa%ga8U_$QgD?p z$H4L*Q9^@}1>puI%r}Z4+@ypBh6C0{m9W?t1>rU&oNnv~wY!wiYj3f@+R`#l&u1!Jmt4zwzu>Sl`>pK*uaB4h#;vdpE!8OLNAq`6RYGjvoi zQijnoY$?N5bRvs-=G7jodcp-N7}^W>@&K#;%gh2H{Z;+OhmZO2dp`WW4}a*xAN%m{ ze0bc4Kk?z?K77)LzwqG+9~KqmI1L{T_^|226+T?)!$BXO;lm*xp6SC?K3wg?H9kDc zhiiQ}?89|FJlluo_;9@s&-LMXKHT8L^L==M4=?oLQ+#-l4=?uNFZuAPKHTWTOMG~# z51;14%YC@XhgV2E2Z~Y{jaa69@dj_)kGpq$J}HbwELgne;>~Ep24nlYvVf?5w+l^G za#t7dCIXkSgvI)F0_-fQqgG`{ih;Yy>XHU%4BQ=3J(qGwN_8nl5V*UpAuEh!98JSD zK4HFecsh4e;u(|0s^--GDJVaQ(%Y1t3rHY^dDr&D?QP#ny22`fFZUq{Ed83focVWiQRxA z!?MS1Q++9h-58>mA-f5P-GVVY35dJf8M7DEV_f#w`=>qbV2|7z2ef0FeC_ztwl1H} z*5%XKy8MsXdf!WQf+3GIC_XWd&u;coT^?mZx3-)J4ksX5rUZeU-tRCGZ_yKV7#}AN zDvaR?kJ`%c0x$l4h8GcKitDaF$U@B1+uB9YrYAbxL-=-2t)Jo7JZdY$Cx|jd>H32# z$ZstO&=6ZWgO#)*&;#RI;$T<|>pf~K4bXe&i8Vxmb6oV|O7TcIWJ9DF9`>}74Bzso z6bH(s2pt*z8M9p_zAaxCF=~$PbI(bdM?TXVW|~LN&J2-e$bS7sy>t**NXAd|oD48r z?or7d1bJ=^k-V8G&JIuv@1>?HVUK(oYCb-vdGSH!4pLiIZ*-8dXVu4nJc9%A@xX@syC2zok=PpS}3~Fp={DFIEAzuwF^ZnA8m`YL{_4=Rc+B;HXZGa zTO;nD(E&c*_BgIpj3jYBt}~ZQ<@IS`I+S4LHdb6a)~{95Kk0Z2z{ro3mUq^G^3AQrH-L(46)mS#xKo@!!n4 zH};r2B4%Wxxp!k*pc-bluXD#%5qAa)wmVQti+J~zc&?D#6?a8%e4U+0?y}szJwpS9 z9A*%5A~irWZsk*;vN?fIq=OQ4pp3LRgabGagKVlsmHmX*lRg%!gjY8c3F84 z`||^^1XGuyMG*T6CEF|H_^_K8$XQ$yP?`m&JD--`ddmx>qh#Aw-t8PI+Lq&F3usp6 z4(k=7r#yS5J49Q&uqMN0t;UL8n|V>tS`2BZTB$+}+a|FTw@_ zZaasH?jB5-w3UXV%8K6F}*T6K2I4Hx~?2X5q4p?4^Bn;MzdaK(1 zNZzoyzp>-|^Bd2LoEvFrY#wq;d23BZ#R+1K&#Ee+kjj!OTLTXJ9iE8#+2JXl&{qfZsJGHKyisN>XaQ zu61>!rEP^`>7_>=V*obx_6lR9&RA44BXk$MBWwq5G3m(nrFFG+cLp}rF1W*7SKByN zvA(wH_R3go%PqlJ?ds7P=Bq|kZA)iu6Ev=?T>#4KYD4R*3$-n=$sC!S@&K3c(fzxL zDGflF_|h`XWvX+_DJ>>gn(i{y>&cWRQv|1QNSI>sdm}5E>in2R?`aBo2<^!XOfluJ z6|%`xXREB{Jxz6X>&XmEI0M!%yw^1gAjq4(CMhgd-pkAVrRx`Fr495-)kG22bWMk*pAKNF*{9qw(J(ey_&wCcoEf{Qac=6^;Kc<)6Q@IDY)Q23`-VhnN2+X{kM?@zrGi zCmR1Y$8rnt3h{`>Q#gX>pY6O(_Mg@CPm=ta#y>%Mdt2lGnfQ-1{-?yVJ@)$&@gd3w z^RE#c-|S$)A;*I?$G#kByZ99eoEXG8h;gy^BWrf1Ip(?jo(D$ zdRXJHA^z_*{$3i_ziRx2B>zI=2PmF*H2zFg=Hj;+Z?a7OIsZq<&U}p@CVsKT{}b77 z()h3@^rd|Bg{ z5dZHQ|18;gSK}K={=LROP4mUC&K%Dg8gC7?GasY=3p9S59>&nc8xzk^3@vu8R_RV{xz~cqVY8p=gk^_Cynhtkvr-kAl(0H!5jE_eYBRlu_c(mU|aX#eZQNMxszti~5#6Rid(az&!{}~^Tb_x{F z^FAK+pQieJ)yJbg@8d^(JnDai^#9Yxqy9ePKi2pd<>$DMM?3g$RCw`+BG<`5(kFHK z-N6|3>+l8_4wFnsc_WQm=No0K()H_$h_h!1j`ZN^+UhyT$hLBch>NGT5qWqT8E_mC zu?r|fl8(C?1XM{`1Eownn@<-&QR2kF0GwE}1gC71G~t{npRv$Xxi|cg$YOo)FCxjp z&=8y;ibx*LiXw3M1ZPEXc0`@5!FbxnbNT=8g?YhT`E!dl+wlgM_ua2VFYhFZMF4Qh z+nJ!}32cCCfqDq|*9_?gYXmRm&j5`6sVuQcUVk}hl9*MxWeN5R5YXoTwLgB>p?~?0 zMDXNmg#2^7%(KkT4rsvs`gH^K|C0aE1C(^#i-4Ohe|2=I)-M084*stN^l*;YFXwN| zG&X?}-;)2vC`43qsEOjLKhpn2T!?VJOY2ZcQ{x|k2Hhs={)iT63wNZat~&_)bmQN8 zrs}}`as0eDU<;4`M!>pFY=4LR|6XgSb+Vv44Kv2inv1e~1pYC=9Y%9xM0%4)ymG2)x1vV_F0EWBSJckkgmjQR-i0MSAl1 znf_Y<)8+5JY4V3>d)%M%I-PH{-9<0x_ff!j{)|(q_s25V*FI3AG9;%vDtRyiY6yF1H_t^+f=pySj4>JGwAt?pnA8Gj1!r=qTA&w2OU z*Eg3?<<`Ecy!V~&o_qf8PhQ{d9gU%t1)9dhrLmh?UJ@*0_g3Zc3LCCqQ&|P`ul3*N zU*m6E(;6D=@T?dt4(8fChniyL!JOqe8yvJeOMbxb5d?=y z9v?UXz0RQGvF)BU6_fzQfzl|vxG!GLG~g|hMz$T{FS0El&#d5>-_D!Z=`;|zEXHs;QS2HQL* z8>>%OkG{W(+Ybz_7+s}rc#QdnN|xkagLt*qAk5f_#%q8K)E(JzZT-;H;@q*rXXk0h zj*o<5$1XIKmAj6E^}}1;)?|Ec{>4zA2D;ndgyyEh|6LHMJJc}PHjRDn@|8mYrUi0` z4-d}^Xort~9*n)}9}Eq#g|GRw-`0(6pEk6ucr^DpG;5#p)@#~^7$p6oUu*M}Xr}_& zsYY#s$Cdm2!aoePYJP30r!M4qr)+ltRKl*#VCY%bz^i4u&*K0=&$E!cYZ&4R472-{|hbmMz#@3aAx4d_GQ7rZJv=36y{j$Bzf;P}gj z0J=H;AH?Mxe}#A^$6q6^ zg}K@`5O#6lN^K{o?cqX|HUz?6E_iL>DK7YIVLulZ*}?%X)M&WD9^}Gxc5H{ZaJ{w@ z{JhL2LOXN)ojnXQT~A?>yp%siNcitDT^fdGFxzrgfrTRX zR=DT$obaBW0K)b+;m;BtmhfLB{Jw-gl<+wTpO^3j34bi%PbK`Nguj;XsDzm-AEzea z0txF9c1gHU!bK7;matpGmq~bngeOY4M8cCKTq@x*371QFvV^BdxI)5HB|J^S(+9> z6{%imLxk5-|-f^Dr{!PS6VTmixzk~>j_)dE%3&a9+T#S9UnB7RzTOKFxq9c+y-=7 zJ`0I*BET;vCeMd7rg*jGvv|~3&B8=h%=|(9EHqhB2>;c2HU*H}R1hgS6sJk8GhraX zxTHKI?+cZk>l7i4tr1YnM;H58TeHv6RKOKZ$2I{)N1Z){bD#e!DK& zZ>8feETGiy+;+!-0z_6CTPL9ChY7B`WP(vLRKOl)0*js+Yg61fV%+|Bga36Nb_+a0 zoW?c?I4Y?LoVUKgF-PE5dWt{_*rI)#i4$odH%#1nj>p>s941Od;b0jK@lXTFYx0| zz-u;>PZ18P2`q*Q*2PTnFPx57Ow}U{;Bzp5)pN)3yH53+SH9SLSoNM)&gaX~WFqdT zCzMcC2@!F-qjIZ&B0JbEp1Ww(i+)k+_YD`JSSDiqz|0g-a<}&)ccbJ+ELe@*Atr<9 z2NWqekMS0u{UQz;1`V~&Ol_YqE5-o_w1Ng%l>3_uGU|wF)#Oa8^>-4?&$RVoX$sF8 zTQ3q44uKL-9e<+8P93fV#M8AunK-;K>ktGcgK_~|2?jOo%hE}3w@;r? z_GQhCFPUif#bYsF-;%|V#kEz*L@L`?6;EY-H~12%STfsTFk6p=i}l(QmN`a+`O>|X zuO|`9q|J1v<;$ddjg+s}yU1IE-WJ#T!osvK95MQ=|3e4H%xq>;Lpl{pXF8&(nBk3K zo~G5&VRU-C@F>mN(rcIiA#d=ONOK4pHiU^_ZZRW9CX-B<7H{i`T3vvk$)8Es5Izls zfq@V1Vfe6bWKz*2nzTR2Uq+J+-f?DYPj1xvy!vJ9^vz54k~8jyLRW{r%L-h2k-M`< zuRN2}Z?yE4XIk_o_mlb(?@i76^?US}b{y3wdG+jb?!ZqTalh5fUqvtL}F>r{>z(g_qnsao15J&!SAlU{dq8`6+H>}0{4_6_fNCj!O@~~dijO5i`TDhelxTm zbxz}LN%ITKjOPCM4XCgCcj`yjb9(%j`>ON}XWUc2-&`;Ora)`sy45UVcBL~`d$yBB zn!XcBreoa^i-jZgnP{xruv)kDw5O9;S*Vq*0h$qf4-H3JqCJL53cj9{op*%i$g9llU&B$H0VJV<9#mg$3;WI`eB=B?R`QFT|eCt=k1V(AXUx5mVlZzJPf z8%@H<_;8pLo1#gdnTdhNKsuR>W<*Shcq$(4v4h$SBWBoPWm6{bMn@$c&qO+t(YOg6 zJJMF97ZQrb4U8I1C3?tCIMS9$^d^mlbTXYHF47atbVD=@OB8NwfDTv?!|8$sZ!xT{ zG!|l2GTk0cHl{YQNN?K2Vx_a-9Li}%H}SAKlj$gyb#=zrlt^bq*}!bnv_mo>JcGrs zOrX|~jG96xW0={b#UQwNrF|QdqBM>9@IaQ?-bg!`1v?lfEQtgZghkSwou*+iD**+- zZYg_6I}=GGm1bsQs{sR#L1&C;hcJNQiF(7@NipaJOEnw`r#H*v5Ay?-5AXq4=T4Pq z64ek9gE^tDTo&npv4@WJ$!My()ygDNaXSh=0<6^@M-f%8l>yb3XxNA*0o(#z9cQh* zM$8E{YGrZU8)5D^3fx01ic^UDv8REYMmTb7Hf`l?hKx-{QVc{m(rOqTLc&V%X=m3O z#hOTU1b3KJL>es-KQ+S4h~%dR4HH%wr;k1S)%;Nd;fJE81sP=X0kuS1SOlhWM>T)c z@W*xhQOh6KL)WljTG5QvmhLuEAg)QZ!_?}y4UK`=n$BjN*&NwqMcb2xm>)1n(`Hku z6V#y4`Bl=8&18&})!5eyGtx|?(X3rNoVgG^)!CUr(k6i#VIvM(ZDtEgWfJi&i`mH3{ z@o^ZlV8W56RDAAIN~=OU>QbZkhzn`YQ8m+ysBkQWkX$EPSJ_n7G&*1v zz_{UmCR$Lq@4@ts!*<73H8k8!L*y5PY=f9az8i~OZa`iu4V z3nr8<@|P}vMo+i+OO<}kNkvT>#Ft&(@k;lIo)F?iF2|j7R3&KGVc7jXr&0J*SxCKYhd0_;+ zklIn-{yKqVuf$_p33a+j;s0bG)Wi3>3jZd_;zOZ`=K<1RtLU$%sdA^nf1C0$6#f3jY&Y8qX>`9NXE~zbO2>Bp+7zXUYEW z6n+iG|F*(ckp6oLzl`d6Ug7Vgc)n8je-|?4A;#;sREHS~UrqWRh2KJcs}=qj$u}#! z`1sna@Uux?r|=(8{D#82s16y0H!1!d3SUfi9#r^;NdJclUrhCXM&Zc}`zM9}Bk3Pf z_>V~box=Ys)$NqRzeN0>75)|CKT-JCiPxweVjSNfzEt4{NS>qczot4YRCxOQTNk$j!PPp7)wtnfb| z`%Mb}bIPYp;ol-V5rr3Zzf0jMOm>gLUqSiatMGUrgx7-#|FRf&g@1tLrxkuD**T!_ z?PTXgg`%;pdY62MYfw`5jUCYl-LIcjy0KpCY|-Y8Uh8W3oS2 z;cJLrpz!l)9BUQ+8mi9V|o#I0K@~53S5|3@4QNCA7JnGlkRv5cl;!*!? za#AbtsDC%<`xRcizphsJcS%1g@o4{X8n14NNBiRatykhvU%WqUm3Y*@mGXK(;h!h| zQH2-p89!Edlk$B=;?eK#Db52DkA7Qdp8rbW4-x;m!UxFCDTR*{|6dZ1ejg?~!xE2v z_mTcb5|8?ONqc+}rS zey@~xg#SSLS4%wV?;-tKiAT7Q;--fkCz*g&`b`%+F&%kbv{HU5UkQ46p{}gYyyli3 zI7Nh~mEq4Wfh;^Q_I5?B@E6>x?()4Z?ru^ s{<|n(98O#cYJWWQQ`as~Y$L6oD^QRwHGdq}@%kU5_i_@% literal 0 HcmV?d00001 diff --git a/src/survdiff2.o b/src/survdiff2.o new file mode 100644 index 0000000000000000000000000000000000000000..3ae6da6d372e19e6bfe6783cb3d2a808e64cca9f GIT binary patch literal 14464 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 C;96e* literal 0 HcmV?d00001 diff --git a/src/survfitkm.o b/src/survfitkm.o new file mode 100644 index 0000000000000000000000000000000000000000..ca41e451d3bbef04cebfbaff5fad491c7c54c5b0 GIT binary patch literal 52672 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 AvH$=8 literal 0 HcmV?d00001 diff --git a/src/survfitresid.o b/src/survfitresid.o new file mode 100644 index 0000000000000000000000000000000000000000..12583c54e16d3fa66cd781e2bfabdee6017a536d GIT binary patch literal 30432 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 LmetZE)b{@u5bLY$ literal 0 HcmV?d00001 diff --git a/src/survival.so b/src/survival.so new file mode 100644 index 0000000000000000000000000000000000000000..e5b6258df6d50441c4d4ba5e5d2f58d5cbb35464 GIT binary patch literal 715760 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 literal 0 HcmV?d00001 diff --git a/src/survpenal.o b/src/survpenal.o new file mode 100644 index 0000000000000000000000000000000000000000..d0cd5030eaa50c6b316f5256084bf2e7efe013e9 GIT binary patch literal 18616 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 literal 0 HcmV?d00001 diff --git a/src/survregc2.o b/src/survregc2.o new file mode 100644 index 0000000000000000000000000000000000000000..95eda3cd86c4f01b8da94c524c3aa2920d94a5d1 GIT binary patch literal 24800 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 literal 0 HcmV?d00001 diff --git a/src/survsplit.o b/src/survsplit.o new file mode 100644 index 0000000000000000000000000000000000000000..0c87a9ef37c735739886bc8025ad4fe699fa9c2e GIT binary patch literal 16960 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 Ii_mQUKQ%MDVgLXD literal 0 HcmV?d00001 diff --git a/src/zph1.o b/src/zph1.o new file mode 100644 index 0000000000000000000000000000000000000000..48d0ae1cc335ddd2cd1daedb1630c61fb02f472b GIT binary patch literal 29392 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 literal 0 HcmV?d00001 diff --git a/src/zph2.o b/src/zph2.o new file mode 100644 index 0000000000000000000000000000000000000000..e3c8cb969b0cf3656da0e780d4609beb2e180f99 GIT binary patch literal 36264 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 X84eq)8q