msm/0000755000176000001440000000000012061404554011077 5ustar ripleyusersmsm/MD50000644000176000001440000001141112061404554011405 0ustar ripleyusersa231d5d590e033648a9c96901b69dd5a *ChangeLog 75196e03aa93dda12bfe7c96158b0609 *DESCRIPTION e4c5474e714080a1c2f3c5b5919ffc99 *NAMESPACE 503f6b14b7b0d0b87a719001a20ba708 *R/boot.R b3b7487eb4068cd5f63d11efb2fd9bc3 *R/constants.R 296b339f69766b880450dd39de080788 *R/hmm-dists.R 42b43e9d959917888a1990b505b5c652 *R/hmm.R 78836ea829c6d70773c43ff0962501ab *R/msm.R 506d22697d6b47782486f622744d6f1f *R/outputs.R 1f88d4f2abf383fdbdedd1cbde0ad16b *R/pearson.R ba355f354261c68089000d699b578cc7 *R/simul.R 525bd7ca6e01019d819d37c7169bf5b0 *R/utils.R b67060b607c1bfac5f9982129f6108c4 *data/aneur.txt.gz 151b9f0427d12e00a218f58d41e01322 *data/bos.txt.gz 55dc4fbe15e53c0e5910e80397d14161 *data/cav.txt.gz 4173835800fa252048603a8d84bc9027 *data/fev.txt.gz a89ff05da0d4202143a94d6fc3de7ca2 *data/psor.txt.gz f8474ef9e0f949bccbb4e244a4ac472c *inst/CITATION 80a61bdedca2ddf7bfed9c9c714b96d4 *inst/NEWS 349f1f84a8ce8d5646c8b85297ec4a0e *inst/doc/msm-manual.pdf 24af37433a8bfe10c5f6b3575e824832 *man/MatrixExp.Rd 98ffda61e188fe10473181201fd56c64 *man/aneur.Rd 72e3f719df9ab03b0510ce94cdd9529b *man/boot.msm.Rd e1ca92595fbd79b1699a6e9e32b90c69 *man/bos.Rd 6cb6482578bbef7b28beec6dbf4ff550 *man/cav.Rd 8cecf9f6ad73f40d0ebd63f5db8987e4 *man/coef.msm.Rd 538988186f5a9c49494b786e752d7d1d *man/crudeinits.msm.Rd 5d13d2b7f4c39c53681f397beaf05b32 *man/deltamethod.Rd 42990a1d157f3b7438c2b8757fe218e1 *man/ematrix.msm.Rd 8a64b3b661655a85e9abdf2e392b26c9 *man/fev.Rd c7d808d38d3fd0724aa70a4a2d9820ea *man/hazard.msm.Rd 40373ead2d68006690a2af3b6bdc70a9 *man/hmm-dists.Rd 44a98583acbe1d69ff49d4f0d006586a *man/logLik.msm.Rd 69dd2d2635017721eaf6c9e0c7c2a57a *man/lrtest.msm.Rd 3ec1d838e03adb86c3c1b5d840108542 *man/medists.Rd d2ce3eaaca1f643a79beaafbd36f9072 *man/msm.Rd d9f40e76e98dad52c17d3cc6f7bf2589 *man/odds.msm.Rd 4cc09f0f15270ce18c5b4a0e263359f4 *man/pearson.msm.Rd c72131f68d05c6caa803d8f8cae32b0a *man/pexp.Rd 5dbea8e868f943e06e97699438da0c9a *man/plot.msm.Rd e600fa2541f214650a7894a1091a7317 *man/plot.prevalence.msm.Rd 83ba5a75e6532dae6f4caafc1701fc1b *man/plot.survfit.msm.Rd 9002c80c8c56fe6e4eb7be04f9cdd2d5 *man/plotprog.msm.Rd af7a02194ac303a0c7b3cce3a27721b9 *man/pmatrix.msm.Rd c6a0cf9689dcc7d0587630035cf28902 *man/pmatrix.piecewise.msm.Rd 88e20352b4dbfc3edcb43e4acd0b3114 *man/pnext.msm.Rd f3a14cdb876474cbc6c590acf169b437 *man/prevalence.msm.Rd 66d8a72789422c4ec98310146682a49f *man/psor.Rd 61d12e99fd6d5751c5ec4b38e5dd70c6 *man/qmatrix.msm.Rd 3fae2a8a8644f578ac84355e01527543 *man/qratio.msm.Rd c79410ade195f3e392e57e90537c7db9 *man/scoreresid.msm.Rd 3e4b86cca540044fbf2d58b5432fca7b *man/sim.msm.Rd 7772b96bfdf0b26c88ec421574a72116 *man/simmulti.msm.Rd 041f32d17c6ed60189d9831f6686303a *man/sojourn.msm.Rd b516349dc082d76e4d95ef1d2d076351 *man/statetable.msm.Rd e00ff8b9fda3e4e46668fc2ba7a5a005 *man/summary.msm.Rd 8976bd0da49fd54ae102544b0154a968 *man/surface.msm.Rd f11c0604eed342e0c1200800c12b3182 *man/tnorm.Rd 1723b485db898525780a8fd6d425a9d7 *man/totlos.msm.Rd ba71e20c9fa56b3e1f4c571c613c65eb *man/transient.msm.Rd 74c5e5ed941ba7ce6a58117c4e0f6623 *man/viterbi.msm.Rd 619d13ce6900fca2139e2139408d39ad *src/Makevars 4f64ccbd2a46df2a0a91e0daabd6fc59 *src/analyticp.c b2954670e5c7bfca19cb6bb42e3f5e32 *src/doc/Makefile 8206c9091e718652d132378ade48f125 *src/doc/Sweave-local.sty e3889cf40ff59689f1a6cfac011c7115 *src/doc/figures/general.pdf 06f4bff6b071901d1120c7431193c59d *src/doc/figures/hidden.pdf af3adf546c0c77610b76919d15607a18 *src/doc/figures/illdeath.pdf 2d8ca6ab876fe50cf7bfee4724fdcbc3 *src/doc/figures/multistate.pdf 8ec73693aa663c3a367f7bd5ea663c7c *src/doc/figures/p2q1.pdf 7f89c5f85f787b2b41c623cbf366d042 *src/doc/figures/p2q12.pdf 04f638273c713543f6dad7c71778df07 *src/doc/figures/p3q12.pdf 98c0baea7a7468465b6d5fba30a62cfa *src/doc/figures/p3q124.pdf 634cc49ae5959dbfaab98007521e3150 *src/doc/figures/p3q1246.pdf 0ae4b74fa9984b26cdaf3a37ef0ec733 *src/doc/figures/p3q135.pdf 5178056951a81e36e697d91d6f655348 *src/doc/figures/p3q14.pdf 1d88c1377297306389a460a8a5598ff2 *src/doc/figures/p3q16.pdf a54418b47ce58e6fa28c500af30d5566 *src/doc/figures/p4q13569.pdf 0bbc74d48ecbcee9199ebea6811bf377 *src/doc/figures/p4q159.pdf 684cf4d5299dab735d4ddf4fdaedcca4 *src/doc/figures/p5q1_4_6_8_11_12_16.pdf 3fa510d2be43accb7ce3cbbe125c93a5 *src/doc/figures/p5q1_6_11_16.pdf 2de6c2326f3031d048c31b507d6a2f20 *src/doc/figures/p5q1_6_7_11_12.pdf 2ea085b4ec235c4882c6a0958c9362a5 *src/doc/figures/sampling.pdf 91283d76c9dada5659f71a7b40953d6e *src/doc/msm-manual.Rnw e4bb53eb4c07603be907a13caf1e1fdc *src/doc/msm.bib 9734cf10b511cab913bfd6f7130acfdd *src/hmm.c 5538be8464293b9904f4bd55974ca39b *src/hmm.h 67825a2eb9c28dad65e1d4d3e143f5da *src/lik.c 2832a001dca2910f1074843f60b73ccd *src/msm.h 86c57b2801e67fea208b93566b7789c7 *src/pijt.c a6b2839634a05442a8ca79c82638dbf7 *tests/local.R 0a5a8fb495e63c276f6bc0289d439557 *tests/misc.R 1d161468abacf9ed6e93c1d211fc4760 *tests/simple.R msm/man/0000755000176000001440000000000012061401532011643 5ustar ripleyusersmsm/man/msm.Rd0000644000176000001440000011515512006205066012741 0ustar ripleyusers\name{msm} \title{Multi-state Markov and hidden Markov models in continuous time} \alias{msm} \description{ Fit a continuous-time Markov or hidden Markov multi-state model by maximum likelihood. Observations of the process can be made at arbitrary times, or the exact times of transition between states can be known. Covariates can be fitted to the Markov chain transition intensities or to the hidden Markov observation process. } \usage{ msm ( formula, subject=NULL, data = list(), qmatrix, gen.inits = FALSE, ematrix=NULL, hmodel=NULL, obstype=NULL, obstrue=NULL, covariates = NULL, covinits = NULL, constraint = NULL, misccovariates = NULL, misccovinits = NULL, miscconstraint = NULL, hcovariates = NULL, hcovinits = NULL, hconstraint = NULL, qconstraint=NULL, econstraint=NULL, initprobs = NULL, est.initprobs=FALSE, initcovariates = NULL, initcovinits = NULL, death = FALSE, exacttimes = FALSE, censor=NULL, censor.states=NULL, pci=NULL, cl = 0.95, fixedpars = NULL, center=TRUE, opt.method=c("optim","nlm"), hessian=TRUE, use.deriv=TRUE, analyticp=TRUE, ... ) } \arguments{ \item{formula}{ A formula giving the vectors containing the observed states and the corresponding observation times. For example, \code{state ~ time} Observed states should be in the set \code{1, \dots, n}, where \code{n} is the number of states. The times can indicate different types of observation scheme, so be careful to choose the correct \code{obstype}. For hidden Markov models, \code{state} refers to the outcome variable, which need not be a discrete state. } \item{subject}{Vector of subject identification numbers for the data specified by \code{formula}. If missing, then all observations are assumed to be on the same subject. These must be sorted so that all observations on the same subject are adjacent.} \item{data}{Optional data frame in which to interpret the variables supplied in \code{formula}, \code{subject}, \code{covariates}, \code{misccovariates}, \code{hcovariates}, \code{obstype} and \code{obstrue}.} \item{qmatrix}{Initial transition intensity matrix of the Markov chain. If an instantaneous transition is not allowed from state \eqn{r} to state \eqn{s}, then \code{qmatrix} should have \eqn{(r,s)} entry 0, otherwise it should be non-zero. Any diagonal entry of \code{qmatrix} is ignored, as it is constrained to be equal to minus the sum of the rest of the row. For example,\cr \code{ rbind( c( 0, 0.1, 0.01 ), c( 0.1, 0, 0.2 ), c( 0, 0, 0 ) ) }\cr represents a 'health - disease - death' model, with transition intensities 0.1 from health to disease, 0.01 from health to death, 0.1 from disease to health, and 0.2 from disease to death. The initial intensities given here are with any covariates set to their means in the data (or set to zero, if \code{center} = FALSE). If any intensities are constrained to be equal using \code{qconstraint}, then the initial value is taken from the first of these (reading across rows). } \item{gen.inits}{If \code{TRUE}, then initial values for the transition intensities are generated automatically using the method in \code{\link{crudeinits.msm}}. The non-zero entries of the supplied \code{qmatrix} are assumed to indicate the allowed transitions of the model.} \item{ematrix}{ If misclassification between states is to be modelled, this should be a matrix of initial values for the misclassification probabilities. The rows represent underlying states, and the columns represent observed states. If an observation of state \eqn{s} is not possible when the subject occupies underlying state \eqn{r}, then \code{ematrix} should have \eqn{(r,s)} entry 0. Otherwise \code{ematrix} should have \eqn{(r,s)} entry corresponding to the probability of observing \eqn{s} conditionally on occupying true state \eqn{r}. The diagonal of \code{ematrix} is ignored, as rows are constrained to sum to 1. For example, \cr \code{ rbind( c( 0, 0.1, 0 ), c( 0.1, 0, 0.1 ), c( 0, 0.1, 0 ) ) }\cr represents a model in which misclassifications are only permitted between adjacent states. If any probabilities are constrained to be equal using \code{econstraint}, then the initial value is taken from the first of these (reading across rows). For an alternative way of specifying misclassification models, see \code{hmodel}. } \item{hmodel}{ Specification of the hidden Markov model. This should be a list of return values from the constructor functions described in the \code{\link{hmm-dists}} help page. Each element of the list corresponds to the outcome model conditionally on the corresponding underlying state. For example, consider a three-state hidden Markov model. Suppose the observations in underlying state 1 are generated from a Normal distribution with mean 100 and standard deviation 16, while observations in underlying state 2 are Normal with mean 54 and standard deviation 18. Observations in state 3, representing death, are exactly observed, and coded as 999 in the data. This model is specified as \code{hmodel = list(hmmNorm(mean=100, sd=16), hmmNorm(mean=54, sd=18), hmmIdent(999))} The mean and standard deviation parameters are estimated starting from these initial values. If multiple parameters are constrained to be equal using \code{hconstraint}, then the initial value is taken from the value given on the first occasion that parameter appears in \code{hmodel}. See the \code{\link{hmm-dists}} help page for details of the constructor functions for each available distribution. A misclassification model, that is, a hidden Markov model where the outcomes are misclassified observations of the underlying states, can either be specified using a list of \code{\link{hmmCat}} objects, or by using an \code{ematrix}. For example, \cr \code{ ematrix = rbind( c( 0, 0.1, 0, 0 ), c( 0.1, 0, 0.1, 0 ), c( 0, 0.1, 0, 0), c( 0, 0, 0, 0) ) }\cr is equivalent to \cr \code{hmodel = list( hmmCat(prob=c(0.9, 0.1, 0, 0)), hmmCat(prob=c(0.1, 0.8, 0.1, 0)), hmmCat(prob=c(0, 0.1, 0.9, 0)), hmmIdent()) }\cr } \item{obstype}{A vector specifying the observation scheme for each row of the data. This can be included in the data frame \code{data} along with the state, time, subject IDs and covariates. Its elements should be either 1, 2 or 3, meaning as follows: \describe{ \item{1}{An observation of the process at an arbitrary time (a "snapshot" of the process, or "panel-observed" data). The states are unknown between observation times.} \item{2}{An exact transition time, with the state at the previous observation retained until the current observation. An observation may represent a transition to a different state or a repeated observation of the same state (e.g. at the end of follow-up). } \item{3}{An exact transition time, but the state at the instant before entering this state is unknown. A common example is death times in studies of chronic diseases.} } If \code{obstype} is not specified, this defaults to all 1. If \code{obstype} is a single number, all observations are assumed to be of this type. The obstype value for the first observation from each subject is not used. This is a generalisation of the \code{death} and \code{exacttimes} arguments to allow different schemes per observation. \code{obstype} overrides both \code{death} and \code{exacttimes}. \code{exacttimes=TRUE} specifies that all observations are of obstype 2. \code{death = death.states} specifies that all observations of \code{death.states} are of type 3. \code{death = TRUE} specifies that all observations in the final absorbing state are of type 3. } \item{obstrue}{A vector of logicals (\code{TRUE} or \code{FALSE}) or numerics (1 or 0) specifying which observations (\code{TRUE}, 1) are observations of the underlying state without error, and which (\code{FALSE}, 0) are realisations of a hidden Markov model. Only used in misclassification or hidden Markov models. In HMMs where there are also censored states, \code{obstrue} should be set to 1 for observed states which are \emph{censored} but not \emph{misclassified}. } \item{covariates}{Formula representing the covariates on the transition intensities via a log-linear model. For example, \code{~ age + sex + treatment} } \item{covinits}{Initial values for log-linear effects of covariates on the transition intensities. This should be a named list with each element corresponding to a covariate. A single element contains the initial values for that covariate on each transition intensity, reading across the rows in order. For a pair of effects constrained to be equal, the initial value for the first of the two effects is used. For example, for a model with the above \code{qmatrix} and age and sex covariates, the following initialises all covariate effects to zero apart from the age effect on the 2-1 transition, and the sex effect on the 1-3 transition. \code{ covinits = list(sex=c(0, 0, 0.1, 0), age=c(0, 0.1, 0, 0))} For factor covariates, name each level by concatenating the name of the covariate with the level name, quoting if necessary. For example, for a covariate \code{agegroup} with three levels \code{0-15, 15-60, 60-}, use something like \code{ covinits = list("agegroup15-60"=c(0, 0.1, 0, 0), "agegroup60-"=c(0.1, 0.1, 0, 0))} If not specified or wrongly specified, initial values are assumed to be zero. } \item{constraint}{ A list of one numeric vector for each named covariate. The vector indicates which covariate effects on intensities are constrained to be equal. Take, for example, a model with five transition intensities and two covariates. Specifying\cr \code{constraint = list (age = c(1,1,1,2,2), treatment = c(1,2,3,4,5))}\cr constrains the effect of age to be equal for the first three intensities, and equal for the fourth and fifth. The effect of treatment is assumed to be different for each intensity. Any vector of increasing numbers can be used as indicators. The intensity parameters are assumed to be ordered by reading across the rows of the transition matrix, starting at the first row, ignoring the diagonals. Negative elements of the vector can be used to indicate that particular covariate effects are constrained to be equal to minus some other effects. For example: \code{constraint = list (age = c(-1,1,1,2,-2), treatment = c(1,2,3,4,5)) }\cr constrains the second and third age effects to be equal, the first effect to be minus the second, and the fifth age effect to be minus the fourth. For example, it may be realisitic that the effect of a covariate on the "reverse" transition rate from state 2 to state 1 is minus the effect on the "forward" transition rate, state 1 to state 2. Note that it is not possible to specify exactly which of the covariate effects are constrained to be positive and which negative. The maximum likelihood estimation chooses the combination of signs which has the higher likelihood. For categorical covariates, defined using \code{factor(covname)}, specify constraints as follows:\cr \code{list(..., covnameVALUE1 = c(...), covnameVALUE2 = c(...), ...)}\cr where \code{covname} is the name of the factor, and \code{VALUE1}, \code{VALUE2}, ... are the levels of the factor. Make sure the \code{contrasts} option is set appropriately, for example, the default \code{options(contrasts=c(contr.treatment, contr.poly))} sets the first (baseline) level of unordered factors to zero. To assume no covariate effect on a certain transition, use the \code{fixedpars} argument to fix it at its initial value (which is zero by default) during the optimisation. } \item{misccovariates}{A formula representing the covariates on the misclassification probabilities, analogously to \code{covariates}, via multinomial logistic regression. Only used if the model is specified using \code{ematrix}, rather than \code{hmodel}. } \item{misccovinits}{Initial values for the covariates on the misclassification probabilities, defined in the same way as \code{covinits}. Only used if the model is specified using \code{ematrix}. } \item{miscconstraint}{A list of one vector for each named covariate on misclassification probabilities. The vector indicates which covariate effects on misclassification probabilities are constrained to be equal, analogously to \code{constraint}. Only used if the model is specified using \code{ematrix}. } \item{hcovariates}{ List of formulae the same length as \code{hmodel}, defining any covariates governing the hidden Markov outcome models. The covariates operate on a suitably link-transformed linear scale, for example, log scale for a Poisson outcome model. If there are no covariates for a certain hidden state, then insert a NULL in the corresponding place in the list. For example, \code{hcovariates = list(~acute + age, ~acute, NULL).} } \item{hcovinits}{ Initial values for the hidden Markov model covariate effects. A list of the same length as \code{hcovariates}. Each element is a vector with initial values for the effect of each covariate on that state. For example, the above \code{hcovariates} can be initialised with \code{hcovariates = list(c(-8, 0), -8, NULL)}. Initial values must be given for all or no covariates, if none are given these are all set to zero. The initial value given in the \code{hmodel} constructor function for the corresponding baseline parameter is interpreted as the value of that parameter with any covariates fixed to their means in the data. If multiple effects are constrained to be equal using \code{hconstraint}, then the initial value is taken from the first of the multiple initial values supplied. } \item{hconstraint}{ A named list. Each element is a vector of constraints on the named hidden Markov model parameter. The vector has length equal to the number of times that class of parameter appears in the whole model. For example consider the three-state hidden Markov model described above, with normally-distributed outcomes for states 1 and 2. To constrain the outcome variance to be equal for states 1 and 2, and to also constrain the effect of \code{acute} on the outcome mean to be equal for states 1 and 2, specify \code{hconstraint = list(sd = c(1,1), acute=c(1,1))} } \item{qconstraint}{A vector of indicators specifying which baseline transition intensities are equal. For example, \code{qconstraint = c(1,2,3,3)} constrains the third and fourth intensities to be equal, in a model with four allowed instantaneous transitions. When there are covariates on the intensities and \code{center=TRUE} (the default), \code{qconstraint} is applied to the intensities with covariates taking the values of the means in the data. When \code{center=FALSE}, \code{qconstraint} is applied to the intensities with covariates set to zero. } \item{econstraint}{A similar vector of indicators specifying which baseline misclassification probabilities are constrained to be equal. Only used if the model is specified using \code{ematrix}, rather than \code{hmodel}. } \item{initprobs}{Currently only used in hidden Markov models. Vector of assumed underlying state occupancy probabilities at each individual's first observation. If these are estimated (see \code{est.initprobs}), then this defaults to equal probability for each state. Otherwise this defaults to \code{c(1, rep(0, nstates-1))}, that is, in state 1 with a probability of 1. Scaled to sum to 1 if necessary. The state 1 occupancy probability should be non-zero. } \item{est.initprobs}{Only used in hidden Markov models. If \code{TRUE}, then the underlying state occupancy probabilities at the first observation will be estimated, starting from initial values taken from the \code{initprobs} argument. Structural zeroes are allowed: if any of these initial values are zero they will be fixed at zero during optimisation, and no covariate effects on them are estimated. The exception is state 1, which should have non-zero occupancy probability. Be warned that if any of these initial values are 1, then \code{\link{optim}} will give an "non-finite value" error, since these are logit-transformed during estimation. If you wish to fix any initial probabilities to 1, then that implies all the others are fixed to zero, and there is no need to use \code{est.initprobs} at all. Note that the free parameters during this estimation exclude the state 1 occupancy probability, which is fixed at one minus the sum of the other probabilities. } \item{initcovariates}{ Formula representing covariates on the initial state occupancy probabilities, via multinomial logistic regression. The linear effects of these covariates, observed at the individual's first observation time, operate on the log ratio of the state \eqn{r} occupancy probability to the state 1 occupancy probability, for each \eqn{r = 2} to the number of states. Thus the state 1 occupancy probability should be non-zero. If \code{est.initprobs} is \code{TRUE}, these effects are estimated starting from their initial values. If \code{est.initprobs} is \code{FALSE}, these effects are fixed at theit initial values.} \item{initcovinits}{ Initial values for the covariate effects \code{initcovariates}. A named list with each element corresponding to a covariate, as in \code{covinits}. Each element is a vector with (1 - number of states) elements, containing the initial values for the linear effect of that covariate on the log odds of that state relative to state 1, from state 2 to the final state. If \code{initcovinits} is not specified, all covariate effects are initialised to zero.} \item{death}{Vector of indices of absorbing states whose time of entry is known exactly, but the individual is assumed to be in an unknown transient state ("alive") at the previous instant. This is the usual situation for times of death in chronic disease monitoring data. For example, if you specify \code{death = c(4, 5)} then states 4 and 5 are assumed to be exactly-observed death states. See the \code{obstype} argument. States of this kind correspond to \code{obstype=3}. \code{death = TRUE} indicates that the final absorbing state is of this kind, and \code{death = FALSE} (the default) indicates that there is no state of this kind. The \code{death} argument is overridden by \code{obstype} or \code{exacttimes}. Note that times of death do not necessarily have \code{obstype=3}. If the state is known between the time of death and the previous observation, then you should specify \code{obstype=2} for the death times, or \code{exacttimes=TRUE} if the state is known at all times, and the \code{death} argument is ignored. } \item{censor}{ A state, or vector of states, which indicates censoring. Censoring means that the observed state is known only to be one of a particular set of states. For example, \code{censor=999} indicates that all observations of \code{999} in the vector of observed states are censored states. By default, this means that the true state could have been anything other than an absorbing state. To specify corresponding true states explicitly, use a \code{censor.states} argument. Note that in contrast to the usual terminology of survival analysis, here it is the \emph{state} which is considered to be censored, rather than the \emph{event time}. If at the end of a study, an individual has not died, but their true state is \emph{known}, then \code{censor} is unnecessary, since the standard multi-state model likelihood is applicable. Note in particular that general time-inhomogeneous Markov models with piecewise constant transition intensities can be constructed using the \code{censor} facility. If the true state is unknown on occasions when a piecewise constant covariate is known to change, then censored states can be inserted in the data on those occasions. The covariate may represent time itself, in which case the \code{pci} option to msm can be used to perform this trick automatically, or some other time-dependent variable. } \item{censor.states}{ Specifies the underlying states which censored observations can represent. If \code{censor} is a single number (the default) this can be a vector, or a list with one element. If \code{censor} is a vector with more than one element, this should be a list, with each element a vector corresponding to the equivalent element of \code{censor}. For example \code{censor = c(99, 999), censor.states = list(c(2,3), c(3,4))} means that observations coded 99 represent either state 2 or state 3, while observations coded 999 are really either state 3 or state 4. } \item{pci}{Model for piecewise-constant intensities. Vector of cut points defining the times, since the start of the process, at which intensities change. For example \code{pci = c(5, 10)} specifies that the intensity changes at time points 5 and 10. This will automatically construct a model with a categorical (factor) covariate called \code{timeperiod}, with levels \code{"[-Inf,5)"}, \code{"[5,10)"} and \code{"[10,Inf)"}, where the first level is the baseline. This covariate defines the time period in which the observation was made. Initial values and constraints on covariate effects are specified the same way as for a model with a covariate of this name, for example, \code{covinits = list("timeperiod[5,10)"=c(0.1,0.1), "timeperiod[10,Inf)"=c(0.1,0.1))} Internally, this works by inserting censored observations in the data at times when the intensity changes but the state is not observed. If the supplied times are outside the range of the time variable in the data, \code{pci} is ignored and a time-homogeneous model is fitted. After fitting a time-inhomogeneous model, \code{\link{qmatrix.msm}} can be used to obtain the fitted intensity matrices for each time period, for example, \code{qmatrix.msm(example.msm, covariates=list(timeperiod="[5,Inf)"))} This facility does not support interactions between time and other covariates. Such models need to be specified "by hand", using a state variable with censored observations inserted. Note that the \code{data} component of the \code{msm} object returned from a call to \code{msm} with \code{pci} supplied contains the states with inserted censored observations and time period indicators. These can be used to construct such models. } \item{exacttimes}{By default, the transitions of the Markov process are assumed to take place at unknown occasions in between the observation times. If \code{exacttimes} is set to \code{TRUE}, then the observation times are assumed to represent the exact times of transition of the process. The subject is assumed to be in the same state between these times. An observation may represent a transition to a different state or a repeated observation of the same state (e.g. at the end of follow-up). This is equivalent to every row of the data having \code{obstype = 2}. See the \code{obstype} argument. If both \code{obstype} and \code{exacttimes} are specified then \code{exacttimes} is ignored. } \item{cl}{Width of symmetric confidence intervals for maximum likelihood estimates, by default 0.95.} \item{fixedpars}{Vector of indices of parameters whose values will be fixed at their initial values during the optimisation. These are given in the order: transition intensities (reading across rows of the transition matrix), covariates on intensities (ordered by intensities within covariates), hidden Markov model parameters, including misclassification probabilities (ordered by parameters within states), hidden Markov model covariate parameters (ordered by covariates within parameters within states), initial state occupancy probabilities (excluding the first probability, which is fixed at one minus the sum of the others). If there are equality constraints on certain parameters, then \code{fixedpars} indexes the set of unique parameters, excluding those which are constrained to be equal to previous parameters. For covariates on misclassification probabilities, this is a change from version 0.4 in the parameter ordering. Previously these were ordered by misclassification probabilities within covariates. This can be useful for profiling likelihoods, and building complex models stage by stage. To fix all parameters, specify \code{fixedpars = TRUE}. } \item{center}{If \code{TRUE} (the default, unless \code{fixedpars=TRUE}) then covariates are centered at their means during the maximum likelihood estimation. This usually improves stability of the numerical optimisation. } \item{opt.method}{Quoted name of the R function to perform minimisation of the minus twice log likelihood. Either "optim" or "nlm". \code{\link{optim}} is the default. } \item{hessian}{If \code{TRUE} (the default) then the Hessian matrix is computed at the maximum likelihood estimates, to obtain standard errors and confidence intervals.} \item{use.deriv}{If \code{TRUE} then analytic first derivatives are used in the optimisation of the likelihood, when an appropriate quasi-Newton optimisation method, such as BFGS, is being used. Note that the default for \code{\link{optim}} is a Nelder-Mead method which cannot use derivatives. However, these derivatives, if supplied, are always used to calculate the Hessian. } \item{analyticp}{By default, the likelihood for certain simpler 3, 4 and 5 state models is calculated using an analytic expression for the transition probability (P) matrix. To revert to the original method of using the matrix exponential, specify \code{analyticp=FALSE}. See the PDF manual for a list of the models for which analytic P matrices are implemented. } \item{...}{Optional arguments to the general-purpose \R optimisation routines, \code{\link{optim}} or \code{\link{nlm}}. Useful options for \code{\link{optim}} include \code{method="BFGS"} for using a quasi-Newton optimisation algorithm, which can often be faster than the default Nelder-Mead. If the optimisation fails to converge, consider normalising the problem using, for example, \code{control=list(fnscale = 2500)}, for example, replacing 2500 by a number of the order of magnitude of the likelihood. If 'false' convergence is reported and the standard errors cannot be calculated due to a non-positive-definite Hessian, then consider tightening the tolerance criteria for convergence. If the optimisation takes a long time, intermediate steps can be printed using the \code{trace} argument of the control list. See \code{\link{optim}} for details. } } \value{ To obtain summary information from models fitted by the \code{\link{msm}} function, it is recommended to use extractor functions such as \code{\link{qmatrix.msm}}, \code{\link{pmatrix.msm}}, \code{\link{sojourn.msm}}. These provide estimates and confidence intervals for quantities such as transition probabilities for given covariate values. For advanced use, it may be necessary to directly use information stored in the object returned by the \code{msm} function. This is a list of class \code{msm}, with components: \item{call}{The original call to \code{msm}.} \item{Qmatrices}{A list of matrices. The first component, labelled \code{logbaseline}, is a matrix containing the estimated transition intensities on the log scale with any covariates fixed at their means in the data (or at zero, if \code{center=FALSE}). The component labelled \code{baseline} is the equivalent on the untransformed scale. Each remaining component is a matrix giving the linear effects of the labelled covariate on the matrix of log intensities. To extract an estimated intensity matrix on the natural scale, at an arbitrary combination of covariate values, use the function \code{\link{qmatrix.msm}}. } \item{QmatricesSE}{The standard error matrices corresponding to \code{Qmatrices}. } \item{QmatricesL,QmatricesU}{Corresponding lower and upper symmetric confidence limits, of width 0.95 unless specified otherwise by the \code{cl} argument. } \item{Ematrices}{A list of matrices. The first component, labelled \code{logitbaseline}, is the estimated misclassification probability matrix (expressed as as log odds relative to the probability of the true state) with any covariates fixed at their means in the data (or at zero, if \code{center=FALSE}). The component labelled \code{baseline} is the equivalent on the untransformed scale. Each remaining component is a matrix giving the linear effects of the labelled covariate on the matrix of logit misclassification probabilities. To extract an estimated misclassification probability matrix on the natural scale, at an arbitrary combination of covariate values, use the function \code{\link{ematrix.msm}}.} \item{EmatricesSE}{The standard error matrices corresponding to \code{Ematrices}.} \item{EmatricesL,EmatricesU}{Corresponding lower and upper symmetric confidence limits, of width 0.95 unless specified otherwise by the \code{cl} argument. } \item{sojourn}{ A list with components: \code{mean} = estimated mean sojourn times in the transient states, with covariates fixed at their means (if center=TRUE) or at zero (if center=FALSE). \code{se} = corresponding standard errors. } \item{minus2loglik}{Minus twice the maximised log-likelihood.} \item{deriv}{Derivatives of the minus twice log-likelihood at its maximum.} \item{estimates}{Vector of untransformed maximum likelihood estimates returned from \code{\link{optim}}. Transition intensities are on the log scale and misclassification probabilities are given as log odds relative to the probability of the true state.} \item{estimates.t}{Vector of transformed maximum likelihood estimates with intensities and probabilities on their natural scales.} \item{fixedpars}{Indices of \code{estimates} which were fixed during the maximum likelihood estimation.} \item{center}{Indicator for whether the estimation was performed with covariates centered on their means in the data.} \item{covmat}{Covariance matrix corresponding to \code{estimates}.} \item{ci}{Matrix of confidence intervals corresponding to \code{estimates.t}} \item{opt}{Return value from \code{\link{optim}} or \code{\link{nlm}}, giving information about the results of the optimisation.} \item{foundse}{Logical value indicating whether the Hessian was positive-definite at the supposed maximum of the likelihood. If not, the covariance matrix of the parameters is unavailable. In these cases the optimisation has probably not converged to a maximum. } \item{data}{A list of constants and vectors giving the data, for use in post-processing.} \item{qmodel}{A list of objects specifying the model for transition intensities, for use in post-processing.} \item{emodel}{A list of objects specifying the model for misclassification.} \item{qcmodel}{A list of objects specifying the model for covariates on the transition intensities.} \item{ecmodel}{A list of objects specifying the model for covariates on misclassification probabilities.} \item{hmodel}{A list of class "hmodel", containing objects specifying the hidden Markov model. Estimates of "baseline" location parameters are presented with any covariates fixed to their means in the data, or if \code{center=FALSE}, with covariates fixed to zero. } \item{cmodel}{A list of objects specifying any model for censoring.} Printing a \code{msm} object by typing the object's name at the command line implicitly invokes \code{print.msm}. This formats and prints the important information in the model fit. This includes the fitted transition intensity matrix, matrices containing covariate effects on intensities, and mean sojourn times from a fitted \code{\link{msm}} model. When there is a hidden Markov model, the chief information in the \code{hmodel} component is also formatted and printed. This includes estimates and confidence intervals for each parameter. } \details{ For full details about the methodology behind the \pkg{msm} package, refer to the PDF manual \file{msm-manual.pdf} in the \file{doc} subdirectory of the package. This includes a tutorial in the typical use of \pkg{msm}. The paper by Jackson (2011) in Journal of Statistical Software presents the material in this manual in a more concise form. \pkg{msm} was designed for fitting \emph{continuous-time} Markov models, processes where transitions can occur at any time. These models are defined by \emph{intensities}, which govern both the time spent in the current state and the probabilities of the next state. In \emph{discrete-time models}, transitions are known in advance to only occur at multiples of some time unit, and the model is purely governed by the probability distributions of the state at the next time point, conditionally on the state at the current time. These can also be fitted in \pkg{msm}, assuming that there is a continuous-time process underlying the data. Then the fitted transition probability matrix over one time period, as returned by \code{pmatrix.msm(...,t=1)} is equivalent to the matrix that governs the discrete-time model. However, these can be fitted more efficiently using multinomial logistic regression, for example, using \code{multinom} from the R package \pkg{nnet} (Venables and Ripley, 2002). For simple continuous-time multi-state Markov models, the likelihood is calculated in terms of the transition intensity matrix \eqn{Q}. When the data consist of observations of the Markov process at arbitrary times, the exact transition times are not known. Then the likelihood is calculated using the transition probability matrix \eqn{P(t) = \exp(tQ)}{P(t) = exp(tQ)}, where \eqn{\exp}{exp} is the matrix exponential. If state \eqn{i} is observed at time \eqn{t} and state \eqn{j} is observed at time \eqn{u}, then the contribution to the likelihood from this pair of observations is the \eqn{i,j} element of \eqn{P(u - t)}. See, for example, Kalbfleisch and Lawless (1985), Kay (1986), or Gentleman \emph{et al.} (1994). For hidden Markov models, the likelihood for an individual with \eqn{k} observations is calculated directly by summing over the unknown state at each time, producing a product of \eqn{k} matrices. The calculation is a generalisation of the method described by Satten and Longini (1996), and also by Jackson and Sharples (2002), and Jackson \emph{et al.} (2003). There must be enough information in the data on each state to estimate each transition rate, otherwise the likelihood will be flat and the maximum will not be found. It may be appropriate to reduce the number of states in the model, the number of allowed transitions, or the number of covariate effects, to ensure convergence. Hidden Markov models, and situations where the value of the process is only known at a series of snapshots, are particularly susceptible to non-identifiability, especially when combined with a complex transition matrix. Choosing an appropriate set of initial values for the optimisation can also be important. For flat likelihoods, 'informative' initial values will often be required. } \references{ Jackson, C.H. (2011). Multi-State Models for Panel Data: The msm Package for R., Journal of Statistical Software, 38(8), 1-29. URL http://www.jstatsoft.org/v38/i08/. Kalbfleisch, J., Lawless, J.F., The analysis of panel data under a Markov assumption \emph{Journal of the Americal Statistical Association} (1985) 80(392): 863--871. Kay, R. A Markov model for analysing cancer markers and disease states in survival studies. \emph{Biometrics} (1986) 42: 855--865. Gentleman, R.C., Lawless, J.F., Lindsey, J.C. and Yan, P. Multi-state Markov models for analysing incomplete disease history data with illustrations for HIV disease. \emph{Statistics in Medicine} (1994) 13(3): 805--821. Satten, G.A. and Longini, I.M. Markov chains with measurement error: estimating the 'true' course of a marker of the progression of human immunodeficiency virus disease (with discussion) \emph{Applied Statistics} 45(3): 275-309 (1996) Jackson, C.H. and Sharples, L.D. Hidden Markov models for the onset and progression of bronchiolitis obliterans syndrome in lung transplant recipients \emph{Statistics in Medicine}, 21(1): 113--128 (2002). Jackson, C.H., Sharples, L.D., Thompson, S.G. and Duffy, S.W. and Couto, E. Multi-state Markov models for disease progression with classification error. \emph{The Statistician}, 52(2): 193--209 (2003) Venables, W.N. and Ripley, B.D. (2002) \emph{Modern Applied Statistics with S}, second edition. Springer. } \seealso{ \code{\link{simmulti.msm}}, \code{\link{plot.msm}}, \code{\link{summary.msm}}, \code{\link{qmatrix.msm}}, \code{\link{pmatrix.msm}}, \code{\link{sojourn.msm}}. } \examples{ ### Heart transplant data ### For further details and background to this example, see ### Jackson (2011) or the PDF manual in the doc directory. data(cav) print(cav[1:10,]) twoway4.q <- rbind(c(-0.5, 0.25, 0, 0.25), c(0.166, -0.498, 0.166, 0.166), c(0, 0.25, -0.5, 0.25), c(0, 0, 0, 0)) statetable.msm(state, PTNUM, data=cav) crudeinits.msm(state ~ years, PTNUM, data=cav, qmatrix=twoway4.q) cav.msm <- msm( state ~ years, subject=PTNUM, data = cav, qmatrix = twoway4.q, death = 4, control = list ( trace = 2, REPORT = 1 ) ) cav.msm qmatrix.msm(cav.msm) pmatrix.msm(cav.msm, t=10) sojourn.msm(cav.msm) } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/hazard.msm.Rd0000644000176000001440000000232110616662033014205 0ustar ripleyusers\name{hazard.msm} \title{Calculate tables of hazard ratios for covariates on transition intensities} \alias{hazard.msm} \description{ Hazard ratios are computed by exponentiating the estimated covariate effects on the log-transition intensities. This function is called by \code{\link{summary.msm}}. } \usage{ hazard.msm(x, hazard.scale = 1, cl = 0.95) } \arguments{ \item{x}{Output from \code{\link{msm}} representing a fitted multi-state model.} \item{hazard.scale}{Vector with same elements as number of covariates on transition rates. Corresponds to the increase in each covariate used to calculate its hazard ratio. Defaults to all 1.} \item{cl}{Width of the symmetric confidence interval to present. Defaults to 0.95.} } \value{ A list of tables containing hazard ratio estimates, one table for each covariate. Each table has three columns, containing the hazard ratio, and an approximate upper and lower confidence limit respectively (assuming normality on the log scale), for each Markov chain transition intensity. } \seealso{ \code{\link{msm}}, \code{\link{summary.msm}}, \code{\link{odds.msm}} } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/cav.Rd0000644000176000001440000000361210772455366012732 0ustar ripleyusers\name{cav} \alias{cav} \title{Heart transplant monitoring data} \description{ A series of approximately yearly angiographic examinations of heart transplant recipients. The state at each time is a grade of cardiac allograft vasculopathy (CAV), a deterioration of the arterial walls. } \usage{data(cav)} \format{ A data frame containing 2846 rows. There are 622 patients, the rows are grouped by patient number and ordered by years after transplant, with each row representing an examination and containing additional covariates. \tabular{rll}{ \code{PTNUM} \tab (numeric) \tab Patient identification number \cr \code{age} \tab (numeric) \tab Recipient age at examination (years) \cr \code{years} \tab (numeric) \tab Examination time (years after transplant)\cr \code{dage} \tab (numeric) \tab Age of heart donor (years) \cr \code{sex} \tab (numeric) \tab sex (0=male, 1=female) \cr \code{pdiag} \tab (factor) \tab Primary diagnosis (reason for transplant) \cr \tab \tab IHD=ischaemic heart disease, IDC=idiopathic dilated cardiomyopathy. \cr \code{cumrej} \tab (numeric) \tab Cumulative number of acute rejection episodes \cr \code{state} \tab (numeric) \tab State at the examination. \cr \tab \tab State 1 represents no CAV, state 2 is mild/moderate CAV \cr \tab \tab and state 3 is severe CAV. State 4 indicates death. \cr \code{firstobs} \tab (numeric) \tab 0 = record represents an angiogram or date of death.\cr \tab \tab 1 = record represents transplant (patient's first observation) \cr }} \source{ Papworth Hospital, U.K. } \references{ Sharples, L.D. and Jackson, C.H. and Parameshwar, J. and Wallwork, J. and Large, S.R. (2003). Diagnostic accuracy of coronary angiopathy and risk factors for post-heart-transplant cardiac allograft vasculopathy. Transplantation 76(4):679-82 } \keyword{datasets} msm/man/qmatrix.msm.Rd0000644000176000001440000000741211750003143014416 0ustar ripleyusers\name{qmatrix.msm} \alias{qmatrix.msm} \title{Transition intensity matrix} \description{ Extract the estimated transition intensity matrix, and the corresponding standard errors, from a fitted multi-state model at a given set of covariate values. } \usage{ qmatrix.msm(x, covariates="mean", sojourn=FALSE, ci=c("delta","normal","bootstrap","none"), cl=0.95, B=1000) } \arguments{ \item{x}{A fitted multi-state model, as returned by \code{\link{msm}}.} \item{covariates}{ The covariate values at which to estimate the intensity matrix. This can either be:\cr the string \code{"mean"}, denoting the means of the covariates in the data (this is the default),\cr the number \code{0}, indicating that all the covariates should be set to zero,\cr or a list of values, with optional names. For example \code{list (60, 1)} where the order of the list follows the order of the covariates originally given in the model formula, or a named list, \code{list (age = 60, sex = 1)} } \item{sojourn}{Set to TRUE if the estimated sojourn times and their standard errors should also be returned.} \item{ci}{ If \code{"delta"} (the default) then confidence intervals are calculated by the delta method, or by simple transformation of the Hessian in the very simplest cases. Normality on the log scale is assumed. If \code{"normal"}, then calculate a confidence interval by simulating \code{B} random vectors from the asymptotic multivariate normal distribution implied by the maximum likelihood estimates (and covariance matrix) of the log transition intensities and covariate effects, then transforming. If \code{"bootstrap"} then calculate a confidence interval by non-parametric bootstrap refitting. This is 1-2 orders of magnitude slower than the \code{"normal"} method, but is expected to be more accurate. See \code{\link{boot.msm}} for more details of bootstrapping in \pkg{msm}. } \item{cl}{Width of the symmetric confidence interval to present. Defaults to 0.95.} \item{B}{Number of bootstrap replicates, or number of normal simulations from the distribution of the MLEs.} } \value{ A list with components: \item{estimate}{Estimated transition intensity matrix.} \item{SE}{Corresponding approximate standard errors.} \item{L}{Lower confidence limits} \item{U}{Upper confidence limits} Or if \code{ci="none"}, then \code{qmatrix.msm} just returns the estimated transition intensity matrix. If \code{sojourn} is \code{TRUE}, extra components called \code{sojourn}, \code{sojournSE}, \code{sojournL} and \code{sojournU} are included, containing the estimates, standard errors and confidence limits, respectively, of the mean sojourn times in each transient state. The default print method for objects returned by \code{\link{qmatrix.msm}} presents estimates and confidence limits. To present estimates and standard errors, do something like \code{qmatrix.msm(x)[c("estimates","SE")]} } \details{ Transition intensities and covariate effects are estimated on the log scale by \code{\link{msm}}. A covariance matrix is estimated from the Hessian of the maximised log-likelihood. A more practically meaningful parameterisation of a continuous-time Markov model with transition intensities \eqn{q_{rs}} is in terms of the mean sojourn times \eqn{-1 / q_{rr}} in each state \eqn{r} and the probabilities that the next move of the process when in state \eqn{r} is to state \eqn{s}, \eqn{-q_{rs} / q_{rr}}. } \seealso{ \code{\link{pmatrix.msm}}, \code{\link{sojourn.msm}}, \code{\link{deltamethod}}, \code{\link{ematrix.msm}} } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/crudeinits.msm.Rd0000644000176000001440000000554610767742642015135 0ustar ripleyusers\name{crudeinits.msm} \alias{crudeinits.msm} \title{Calculate crude initial values for transition intensities} \description{ Calculates crude initial values for transition intensities by assuming that the data represent the exact transition times of the Markov process. } \usage{ crudeinits.msm(formula, subject, qmatrix, data=NULL, censor=NULL, censor.states=NULL) } \arguments{ \item{formula}{ A formula giving the vectors containing the observed states and the corresponding observation times. For example, \code{state ~ time} Observed states should be in the set \code{1, \dots, n}, where \code{n} is the number of states. } \item{subject}{Vector of subject identification numbers for the data specified by \code{formula}. If missing, then all observations are assumed to be on the same subject. These must be sorted so that all observations on the same subject are adjacent.} \item{qmatrix}{Matrix of indicators for the allowed transitions. An initial value will be estimated for each value of qmatrix that is greater than zero. Transitions are taken as disallowed for each entry of \code{qmatrix} that is 0. } \item{data}{An optional data frame in which the variables represented by \code{subject} and \code{state} can be found.} \item{censor}{ A state, or vector of states, which indicates censoring. See \code{\link{msm}}. } \item{censor.states}{ Specifies the underlying states which censored observations can represent. See \code{\link{msm}}. } } \value{ The estimated transition intensity matrix. This can be used as the \code{qmatrix} argument to \code{\link{msm}}. } \details{ Suppose we want a crude estimate of the transition intensity \eqn{q_{rs}}{q_rs} from state \eqn{r} to state \eqn{s}. If we observe \eqn{n_{rs}}{n_rs} transitions from state \eqn{r} to state \eqn{s}, and a total of \eqn{n_r} transitions from state \eqn{r}, then \eqn{q_{rs} / q_{rr}}{q_rs / q_rr} can be estimated by \eqn{n_{rs} / n_r}{n_rs / n_r}. Then, given a total of \eqn{T_r} years spent in state \eqn{r}, the mean sojourn time \eqn{1 / q_{rr}}{1 / q_rr} can be estimated as \eqn{T_r / n_r}. Thus, \eqn{n_{rs} / T_r}{n_rs / T_r} is a crude estimate of \eqn{q_{rs}}{q_rs}. If the data do represent the exact transition times of the Markov process, then these are the exact maximum likelihood estimates. Observed transitions which are incompatible with the given \code{qmatrix} are ignored. Censored states are ignored. } \seealso{ \code{\link{statetable.msm}} } \examples{ data(cav) twoway4.q <- rbind(c(-0.5, 0.25, 0, 0.25), c(0.166, -0.498, 0.166, 0.166), c(0, 0.25, -0.5, 0.25), c(0, 0, 0, 0)) statetable.msm(state, PTNUM, data=cav) crudeinits.msm(state ~ years, PTNUM, data=cav, qmatrix=twoway4.q) } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/pnext.msm.Rd0000644000176000001440000000605311750003114014065 0ustar ripleyusers\name{pnext.msm} \alias{pnext.msm} \title{Probability of each state being next} \description{ Compute a matrix of the probability of each state \eqn{s} being the next state of the process after each state \eqn{r}. Together with the mean sojourn times in each state (\code{\link{sojourn.msm}}), these fully define a continuous-time Markov model. } \usage{ pnext.msm(x, covariates = "mean", ci=c("delta","normal","bootstrap","none"), cl = 0.95, B=1000) } \arguments{ \item{x}{A fitted multi-state model, as returned by \code{\link{msm}}.} \item{covariates}{ The covariate values at which to estimate the intensities. This can either be:\cr the string \code{"mean"}, denoting the means of the covariates in the data (this is the default),\cr the number \code{0}, indicating that all the covariates should be set to zero,\cr or a list of values, with optional names. For example \code{list (60, 1)} where the order of the list follows the order of the covariates originally given in the model formula, or a named list, \code{list (age = 60, sex = 1)} } \item{ci}{ If \code{"delta"} (the default) then confidence intervals are calculated by the delta method. If \code{"normal"}, then calculate a confidence interval by simulating \code{B} random vectors from the asymptotic multivariate normal distribution implied by the maximum likelihood estimates (and covariance matrix) of the log transition intensities and covariate effects, then transforming. If \code{"bootstrap"} then calculate a confidence interval by non-parametric bootstrap refitting. This is 1-2 orders of magnitude slower than the \code{"normal"} method, but is expected to be more accurate. See \code{\link{boot.msm}} for more details of bootstrapping in \pkg{msm}.} \item{cl}{Width of the symmetric confidence interval to present. Defaults to 0.95.} \item{B}{Number of bootstrap replicates, or number of normal simulations from the distribution of the MLEs.} } \value{ The matrix of probabilities that the next move of a process in state \eqn{r} (rows) is to state \eqn{s} (columns). } \details{ For a continuous-time Markov process in state \eqn{r}, the probability that the next state is \eqn{s} is \eqn{-q_{rs} / q_{rr}}, where \eqn{q_{rs}} is the transition intensity (\code{\link{qmatrix.msm}}). The model is fully parameterised by these probabilities together with the mean sojourn times \eqn{-1/q_{rr}} in each state \eqn{r}. This gives a more intuitively meaningful description of a model than the intensity matrix. Remember that \pkg{msm} deals with continuous-time not discrete-time models, so these are \emph{not} the same as the probability of observing state \eqn{s} at a fixed time in the future. Those probabilities are given by \code{\link{pmatrix.msm}}. } \seealso{ \code{\link{qmatrix.msm}},\code{\link{pmatrix.msm}},\code{\link{qratio.msm}} } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/deltamethod.Rd0000644000176000001440000000570211376773562014457 0ustar ripleyusers\name{deltamethod} \title{The delta method} \alias{deltamethod} \concept{Delta method} \description{ Delta method for approximating the standard error of a transformation \eqn{g(X)} of a random variable \eqn{X = (x_1, x_2, \ldots)}{X = (x1, x2, \ldots)}, given estimates of the mean and covariance matrix of \eqn{X}. } \usage{ deltamethod(g, mean, cov, ses=TRUE) } \arguments{ \item{g}{A formula representing the transformation. The variables must be labelled \code{x1, x2,\dots} For example, \code{~ 1 / (x1 + x2)} If the transformation returns a vector, then a list of formulae representing (\eqn{g_1, g_2, \ldots}{g1, g2, \ldots}) can be provided, for example \code{list( ~ x1 + x2, ~ x1 / (x1 + x2) )}} \item{mean}{The estimated mean of \eqn{X}} \item{cov}{The estimated covariance matrix of \eqn{X}} \item{ses}{If \code{TRUE}, then the standard errors of \eqn{g_1(X), g_2(X),\ldots}{g1(X), g2(X),\ldots} are returned. Otherwise the covariance matrix of \eqn{g(X)} is returned.} } \value{ A vector containing the standard errors of \eqn{g_1(X), g_2(X), \ldots}{g1(X), g2(X), \ldots} or a matrix containing the covariance of \eqn{g(X)}. } \details{ The delta method expands a differentiable function of a random variable about its mean, usually with a first-order Taylor approximation, and then takes the variance. For example, an approximation to the covariance matrix of \eqn{g(X)} is given by \deqn{ Cov(g(X)) = g'(\mu) Cov(X) [g'(\mu)]^T }{ Cov(g(X)) = g'(mu) Cov(X) [g'(mu)]^T } where \eqn{\mu}{mu} is an estimate of the mean of \eqn{X}. A limitation of this function is that variables created by the user are not visible within the formula \code{g}. To work around this, it is necessary to build the formula as a string, using functions such as \code{sprintf}, then to convert the string to a formula using \code{as.formula}. See the example below. If you can spare the computational time, bootstrapping is a more accurate method of calculating confidence intervals or standard errors for transformations of parameters. See \code{\link{boot.msm}}. } \references{Oehlert, G. W. \emph{A note on the delta method}. American Statistician 46(1), 1992} \examples{ ## Simple linear regression, E(y) = alpha + beta x x <- 1:100 y <- rnorm(100, 4*x, 5) toy.lm <- lm(y ~ x) estmean <- coef(toy.lm) estvar <- summary(toy.lm)$cov.unscaled * summary(toy.lm)$sigma^2 ## Estimate of (1 / (alphahat + betahat)) 1 / (estmean[1] + estmean[2]) ## Approximate standard error deltamethod (~ 1 / (x1 + x2), estmean, estvar) ## We have a variable z we would like to use within the formula. z <- 1 ## deltamethod (~ z / (x1 + x2), estmean, estvar) will not work. ## Instead, build up the formula as a string, and convert to a formula. form <- sprintf("~ \%f / (x1 + x2)", z) form deltamethod(as.formula(form), estmean, estvar) } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{math} msm/man/simmulti.msm.Rd0000644000176000001440000001361311106565444014610 0ustar ripleyusers\name{simmulti.msm} \title{Simulate multiple trajectories from a multi-state Markov model with arbitrary observation times} \alias{simmulti.msm} \concept{Simulation} \description{Simulate a number of individual realisations from a multi-state Markov process. Observations of the process are made at specified arbitrary times for each individual. } \usage{ simmulti.msm(data, qmatrix, covariates=NULL, death = FALSE, start, ematrix=NULL, misccovariates=NULL, hmodel=NULL, hcovariates=NULL, censor.states=NULL) } \arguments{ \item{data}{A data frame with a mandatory column named \code{time}, representing observation times. The optional column named \code{subject}, corresponds to subject identification numbers. If not given, all observations are assumed to be on the same individual. Observation times should be sorted within individuals. The optional column named \code{cens} indicates the times at which simulated states should be censored. If \code{cens==0} then the state is not censored, and if \code{cens==k}, say, then all simulated states at that time which are in the set \code{censor.states} are replaced by \code{k}. Other named columns of the data frame represent any covariates. } \item{qmatrix}{ The transition intensity matrix of the Markov process, with any covariates set to zero. The diagonal of \code{qmatrix} is ignored, and computed as appropriate so that the rows sum to zero. For example, a possible \code{qmatrix} for a three state illness-death model with recovery is: \code{rbind( c( 0, 0.1, 0.02 ), c( 0.1, 0, 0.01 ), c( 0, 0, 0 ) )} } \item{covariates}{List of covariate effects on log transition intensities. Each element is a vector of the effects of one covariate on all the transition intensities. The intensities are ordered by reading across rows of the intensity matrix, starting with the first, counting the positive off-diagonal elements of the matrix. For example, for a multi-state model with three transition intensities, and two covariates \code{x} and \code{y} on each intensity, \code{covariates=list(x = c(-0.3,-0.3,-0.3), y=c(0.1, 0.1, 0.1))} } \item{death}{Vector of indices of the death states. A death state is an absorbing state whose time of entry is known exactly, but the individual is assumed to be in an unknown transient state ("alive") at the previous instant. This is the usual situation for times of death in chronic disease monitoring data. For example, if you specify \code{death = c(4, 5)} then states 4 and 5 are assumed to be death states. \code{death = TRUE} indicates that the final state is a death state, and \code{death = FALSE} (the default) indicates that there is no death state. } \item{start}{A vector with the same number of elements as there are distinct subjects in the data, giving the states in which each corresponding individual begins. Defaults to state 1 for each subject.} \item{ematrix}{An optional misclassification matrix for generating observed states conditionally on the simulated true states. As defined in \code{\link{msm}}.} \item{misccovariates}{Covariate effects on misclassification probabilities via multinomial logistic regression. Linear effects operate on the log of each probability relative to the probability of classification in the correct state. In same format as \code{covariates}.} \item{hmodel}{An optional hidden Markov model for generating observed outcomes conditionally on the simulated true states. As defined in \code{\link{msm}}.} \item{hcovariates}{List of the same length as \code{hmodel}, defining any covariates governing the hidden Markov outcome models. Unlike in the \code{msm} function, this should also define the values of the covariate effects. Each element of the list is a named vector of the initial values for each set of covariates for that state. For example, for a three-state hidden Markov model with two, one and no covariates on the state 1, 2 and 3 outcome models respectively, \code{ hcovariates = list (c(acute=-8, age=0), c(acute=-8), NULL) } } \item{censor.states}{Set of simulated states which should be replaced by a censoring indicator at censoring times. By default this is all transient states (representing alive, with unknown state).} } \value{A data frame with columns, \item{subject}{Subject identification indicators} \item{time}{Observation times} \item{state}{Simulated (true) state at the corresponding time} \item{obs}{Observed outcome at the corresponding time, if \code{ematrix} or \code{hmodel} was supplied} plus any supplied covariates. } \details{ \code{\link{sim.msm}} is called repeatedly to produce a simulated trajectory for each individual. The state at each specified observation time is then taken to produce a new column \code{state}. The effect of time-dependent covariates on the transition intensity matrix for an individual is determined by assuming that the covariate is a step function which remains constant in between the individual's observation times. If the subject enters an absorbing state, then only the first observation in that state is kept in the data frame. Rows corresponding to future observations are deleted. The entry times into states given in \code{death} are assumed to be known exactly. } \seealso{ \code{\link{sim.msm}} } \examples{ ### Simulate 100 individuals with common observation times sim.df <- data.frame(subject = rep(1:100, rep(13,100)), time = rep(seq(0, 24, 2), 100)) qmatrix <- rbind(c(-0.11, 0.1, 0.01 ), c(0.05, -0.15, 0.1 ), c(0.02, 0.07, -0.09)) simmulti.msm(sim.df, qmatrix) } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/ematrix.msm.Rd0000644000176000001440000000647211750004202014404 0ustar ripleyusers\name{ematrix.msm} \alias{ematrix.msm} \title{Misclassification probability matrix} \description{ Extract the estimated misclassification probability matrix, and corresponding confidence intervals, from a fitted multi-state model at a given set of covariate values. } \usage{ ematrix.msm(x, covariates="mean", ci=c("delta","normal","bootstrap","none"), cl=0.95, B=1000) } \arguments{ \item{x}{A fitted multi-state model, as returned by \code{\link{msm}}}. \item{covariates}{ The covariate values for which to estimate the misclassification probability matrix. This can either be:\cr the string \code{"mean"}, denoting the means of the covariates in the data (this is the default),\cr the number \code{0}, indicating that all the covariates should be set to zero,\cr or a list of values, with optional names. For example \code{list (60, 1)} where the order of the list follows the order of the covariates originally given in the model formula, or a named list, \code{list (age = 60, sex = 1)} } \item{ci}{ If \code{"delta"} (the default) then confidence intervals are calculated by the delta method, or by simple transformation of the Hessian in the very simplest cases. If \code{"normal"}, then calculate a confidence interval by simulating \code{B} random vectors from the asymptotic multivariate normal distribution implied by the maximum likelihood estimates (and covariance matrix) of the multinomial-logit-transformed misclassification probabilities and covariate effects, then transforming back. If \code{"bootstrap"} then calculate a confidence interval by non-parametric bootstrap refitting. This is 1-2 orders of magnitude slower than the \code{"normal"} method, but is expected to be more accurate. See \code{\link{boot.msm}} for more details of bootstrapping in \pkg{msm}.} \item{cl}{Width of the symmetric confidence interval to present. Defaults to 0.95.} \item{B}{Number of bootstrap replicates, or number of normal simulations from the distribution of the MLEs} } \value{ A list with components: \item{estimate}{Estimated misclassification probability matrix. The rows correspond to true states, and columns observed states.} \item{SE}{Corresponding approximate standard errors.} \item{L}{Lower confidence limits.} \item{U}{Upper confidence limits.} Or if \code{ci="none"}, then \code{ematrix.msm} just returns the estimated misclassification probability matrix. The default print method for objects returned by \code{\link{ematrix.msm}} presents estimates and confidence limits. To present estimates and standard errors, do something like \code{ematrix.msm(x)[c("estimates","SE")]} } \details{ Misclassification probabilities and covariate effects are estimated on the multinomial-logit scale by \code{\link{msm}}. A covariance matrix is estimated from the Hessian of the maximised log-likelihood. From these, the delta method can be used to obtain standard errors of the probabilities on the natural scale at arbitrary covariate values. Confidence intervals are estimated by assuming normality on the multinomial-logit scale. } \seealso{ \code{\link{qmatrix.msm}} } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/viterbi.msm.Rd0000644000176000001440000000217211376773102014410 0ustar ripleyusers\name{viterbi.msm} \title{Calculate the most likely path through underlying states} \alias{viterbi.msm} \description{ For a fitted hidden Markov model, or a model with censored state observations, the Viterbi algorithm recursively constructs the path with the highest probability through the underlying states. } \usage{ viterbi.msm(x) } \arguments{ \item{x}{A fitted hidden Markov multi-state model, or a model with censored state observations, as produced by \code{\link{msm}}} } \value{ A data frame with columns: \code{subject} = subject identification numbers \code{time} = times of observations \code{observed} = corresponding observed states \code{fitted} = corresponding fitted states found by Viterbi recursion. If the model is not a hidden Markov model and there are no censored state observations, this is just the observed states. } \seealso{ \code{\link{msm}} } \references{ Durbin, R., Eddy, S., Krogh, A. and Mitchison, G. \emph{Biological sequence analysis}, Cambridge University Press, 1998. } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/fev.Rd0000644000176000001440000000335410443527256012735 0ustar ripleyusers\name{fev} \alias{fev} \title{FEV1 measurements from lung transplant recipients} \description{ A series of measurements of the forced expiratory volume in one second (FEV1) from lung transplant recipients, from six months onwards after their transplant. } \usage{data(fev)} \format{ A data frame containing 5896 rows. There are 204 patients, the rows are grouped by patient number and ordered by days after transplant. Each row represents an examination and containing an additional covariate. \tabular{rll}{ \code{ptnum} \tab (numeric) \tab Patient identification number. \cr \code{days} \tab (numeric) \tab Examination time (days after transplant). \cr \code{fev} \tab (numeric) \tab Percentage of baseline FEV1. A code of 999 indicates the patient's date of death. \cr \code{acute} \tab (numeric) \tab 0/1 indicator for whether the patient suffered an acute infection or rejection \cr \tab \tab within 14 days of the visit. \cr }} \details{ A baseline "normal" FEV1 for each individual is calculated using measurements from the first six months after transplant. After six months, as presented in this dataset, FEV1 is expressed as a percentage of the baseline value. FEV1 is monitored to diagnose bronchiolitis obliterans syndrome (BOS), a long-term lung function decline, thought to be a form of chronic rejection. Acute rejections and infections also affect the lung function in the short term. } \source{ Papworth Hospital, U.K. } \keyword{datasets} \references{ Jackson, C.H. and Sharples, L.D. Hidden Markov models for the onset and progression of bronchiolitis obliterans syndrome in lung transplant recipients \emph{Statistics in Medicine}, 21(1): 113--128 (2002). } msm/man/pmatrix.piecewise.msm.Rd0000644000176000001440000001154511750003102016366 0ustar ripleyusers\name{pmatrix.piecewise.msm} \alias{pmatrix.piecewise.msm} \title{Transition probability matrix for processes with piecewise-constant intensities} \description{ Extract the estimated transition probability matrix from a fitted non-time-homogeneous multi-state model for a given time interval. This is a generalisation of \code{\link{pmatrix.msm}} to models with time-dependent covariates. Note that \code{\link{pmatrix.msm}} is sufficient to calculate transition probabilities for time-inhomogeneous models fitted using the \code{pci} argument to \code{\link{msm}}. } \usage{ pmatrix.piecewise.msm(x, t1, t2, times, covariates, ci=c("none","normal","bootstrap"), cl=0.95, B=1000, ...) } \arguments{ \item{x}{A fitted multi-state model, as returned by \code{\link{msm}}. This should be a non-homogeneous model, whose transition intensity matrix depends on a time-dependent covariate. } \item{t1}{The start of the time interval to estimate the transition probabilities for.} \item{t2}{The end of the time interval to estimate the transition probabilities for.} \item{times}{Cut points at which the transition intensity matrix changes.} \item{covariates}{ A list with number of components one greater than the length of \code{times}. Each component of the list is specified in the same way as the \code{covariates} argument to \code{\link{pmatrix.msm}}. The components correspond to the covariate values in the intervals \code{(t1, times[1]], (times[1], times[2]], ..., (times[length(times)], t2]} (assuming that all elements of \code{times} are in the interval \code{(t1, t2)}). } \item{ci}{If \code{"normal"}, then calculate a confidence interval for the transition probabilities by simulating \code{B} random vectors from the asymptotic multivariate normal distribution implied by the maximum likelihood estimates (and covariance matrix) of the log transition intensities and covariate effects, then calculating the resulting transition probability matrix for each replicate. If \code{"bootstrap"} then calculate a confidence interval by non-parametric bootstrap refitting. This is 1-2 orders of magnitude slower than the \code{"normal"} method, but is expected to be more accurate. See \code{\link{boot.msm}} for more details of bootstrapping in \pkg{msm}. If \code{"none"} (the default) then no confidence interval is calculated.} \item{cl}{Width of the symmetric confidence interval, relative to 1.} \item{B}{Number of bootstrap replicates, or number of normal simulations from the distribution of the MLEs} \item{...}{Optional arguments to be passed to \code{\link{MatrixExp}} to control the method of computing the matrix exponential.} } \details{ Suppose a multi-state model has been fitted, in which the transition intensity matrix \eqn{Q(x(t))} is modelled in terms of time-dependent covariates \eqn{x(t)}. The transition probability matrix \eqn{P(t_1, t_n)}{P(t1, tn)} for the time interval \eqn{(t_1, t_n)}{(t1, tn)} cannot be calculated from the estimated intensity matrix as \eqn{\exp((t_n - t_1) Q)}{exp((tn - t1) Q)}, because \eqn{Q} varies within the interval \eqn{t_1, t_n}{t1, tn}. However, if the covariates are piecewise-constant, or can be approximated as piecewise-constant, then we can calculate \eqn{P(t_1, t_n)}{P(t1, tn)} by multiplying together individual matrices \eqn{P(t_i, t_{i+1}) = \exp((t_{i+1} - t_i) Q)}{P(t_i, t_{i+1}) = exp((t_{i+1} - t_i) Q)}, calculated over intervals where Q is constant: \deqn{P(t_1, t_n) = P(t_1, t_2) P(t_2, t_3)\ldots P(t_{n-1}, t_n)}{P(t1, tn) = P(t1, t2) P(t2, t3)\ldotsP(tn-1, tn)} } \value{ The matrix of estimated transition probabilities \eqn{P(t)} for the time interval \code{[t1, tn]}. That is, the probabilities of occupying state \eqn{s} at time \eqn{t_n}{tn} conditionally on occupying state \eqn{r} at time \eqn{t_1}{t1}. Rows correspond to "from-state" and columns to "to-state". } \seealso{ \code{\link{pmatrix.msm}} } \examples{ \dontrun{ ## In a clinical study, suppose patients are given a placebo in the ## first 5 weeks, then they begin treatment 1 at 5 weeks, and ## a combination of treatments 1 and 2 from 10 weeks. ## Suppose a multi-state model x has been fitted for the patients' ## progress, with treat1 and treat2 as time dependent covariates. ## Cut points for when treatment covariate changes times <- c(0, 5, 10) ## Indicators for which treatments are active in the four intervals ## defined by the three cut points covariates <- list( list (treat1=0, treat2=0), list (treat1=0, treat2=0), list(treat1=1, treat2=0), list(treat1=1, treat2=1) ) ## Calculate transition probabilities from the start of the study to 15 weeks pmatrix.piecewise.msm(x, 0, 15, times, covariates) } } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/plot.prevalence.msm.Rd0000644000176000001440000000740611753215360016046 0ustar ripleyusers\name{plot.prevalence.msm} \alias{plot.prevalence.msm} \title{Plot of observed and expected prevalences} \description{ Provides a rough indication of goodness of fit of a multi-state model, by estimating the observed numbers of individuals occupying a state at a series of times, and plotting these against forecasts from the fitted model, for each state. Observed prevalences are indicated as solid lines, expected prevalences as dashed lines. } \usage{ \method{plot}{prevalence.msm}(x, mintime=NULL, maxtime=NULL, timezero=NULL, initstates=NULL, interp=c("start","midpoint"), covariates="mean", misccovariates="mean", piecewise.times=NULL, piecewise.covariates=NULL, xlab="Times",ylab="Prevalence (\%)", lwd.obs=1, lwd.exp=1, lty.obs=1, lty.exp=2, col.obs="blue", col.exp="red", legend.pos=NULL, ...) } \arguments{ \item{x}{A fitted multi-state model produced by \code{\link{msm}}.} \item{mintime}{Minimum time at which to compute the observed and expected prevalences of states.} \item{maxtime}{Maximum time at which to compute the observed and expected prevalences of states.} \item{timezero}{Initial time of the Markov process. Expected values are forecasted from here. Defaults to the minimum of the observation times given in the data. } \item{initstates}{Optional vector of the same length as the number of states. Gives the numbers of individuals occupying each state at the initial time, to be used for forecasting expected prevalences. The default is those observed in the data. These should add up to the actual number of people in the study at the start. } \item{interp}{Interpolation method for observed states, see \code{\link{prevalence.msm}}} \item{covariates}{Covariate values for which to forecast expected state occupancy. See \code{\link{qmatrix.msm}}. Defaults to the mean values of the covariates in the data set.} \item{misccovariates}{(Misclassification models only) Values of covariates on the misclassification probability matrix for which to forecast expected state occupancy. Defaults to the mean values of the covariates in the data set.} \item{piecewise.times}{Times at which piecewise-constant intensities change. See \code{\link{pmatrix.piecewise.msm}} for how to specify this.} \item{piecewise.covariates}{Covariates on which the piecewise-constant intensities depend. See \code{\link{pmatrix.piecewise.msm}} for how to specify this.} \item{xlab}{x axis label.} \item{ylab}{y axis label.} \item{lwd.obs}{Line width for observed prevalences. See \code{\link{par}}.} \item{lwd.exp}{Line width for expected prevalences. See \code{\link{par}}.} \item{lty.obs}{Line type for observed prevalences. See \code{\link{par}}.} \item{lty.exp}{Line type for expected prevalences. See \code{\link{par}}.} \item{col.obs}{Line colour for observed prevalences. See \code{\link{par}}.} \item{col.exp}{Line colour for expected prevalences. See \code{\link{par}}.} \item{legend.pos}{Vector of the \eqn{x} and \eqn{y} position, respectively, of the legend.} \item{...}{Further arguments to be passed to the generic \code{\link{plot}} function.} } \details{ See \code{\link{prevalence.msm}} for details of the assumptions underlying this method. Observed prevalences are plotted with a solid line, and expected prevalences with a dotted line. } \references{ Gentleman, R.C., Lawless, J.F., Lindsey, J.C. and Yan, P. Multi-state Markov models for analysing incomplete disease history data with illustrations for HIV disease. \emph{Statistics in Medicine} (1994) 13(3): 805--821. } \seealso{ \code{\link{prevalence.msm}} } \keyword{models} msm/man/MatrixExp.Rd0000644000176000001440000000521111274616422014065 0ustar ripleyusers\name{MatrixExp} \title{Matrix exponential} \alias{MatrixExp} \concept{Matrix exponential} \description{ Calculates the exponential of a square matrix. } \usage{ MatrixExp(mat, t = 1, n = 20, k = 3, method="pade") } \arguments{ \item{mat}{A square matrix} \item{t}{An optional scaling factor, or a vector or scaling factors, for the eigenvalues of \code{mat}} \item{n}{Number of terms in the series approximation to the exponential} \item{k}{Underflow correction factor, for the series approximation} \item{method}{\code{"pade"} for the Pade approximation, or \code{"series"} for the power series approximation. Ignored unless \code{mat} has repeated eigenvalues. } } \value{ The exponentiated matrix \eqn{\exp(mat)}{exp(mat)}. Or, if \code{t} is a vector of length 2 or more, an array of exponentiated matrices. } \details{ The exponential \eqn{E} of a square matrix \eqn{M} is calculated as \deqn{E = U \exp(D) U^{-1}}{E = U exp(D) U^{-1}} where \eqn{D} is a diagonal matrix with the eigenvalues of \eqn{M} on the diagonal, \eqn{\exp(D)}{exp(D)} is a diagonal matrix with the exponentiated eigenvalues of \eqn{M} on the diagonal, and \eqn{U} is a matrix whose columns are the eigenvectors of \eqn{M}. This method of calculation is used if \eqn{M} has distinct eigenvalues. I If \eqn{M} has repeated eigenvalues, then its eigenvector matrix may be non-invertible. In this case, the matrix exponential is calculated using the Pade approximation defined by Moler and van Loan (2003), or the less robust power series approximation, \deqn{\exp(M) = I + M + M^2/2 + M^3 / 3! + M^4 / 4! + ...}{exp(M) = I + M + M^2/2 + M^3 / 3! + M^4 / 4! + ...} For a continuous-time homogeneous Markov process with transition intensity matrix \eqn{Q}, the probability of occupying state \eqn{s} at time \eqn{u + t} conditional on occupying state \eqn{r} at time \eqn{u} is given by the \eqn{(r,s)} entry of the matrix \eqn{\exp(tQ)}{exp(tQ)}. The implementation of the Pade approximation was taken from JAGS by Martyn Plummer (\url{http://www-fis.iarc.fr/~martyn/software/jags}). The series approximation method was adapted from the corresponding function in Jim Lindsey's R package \code{rmutil} (\url{http://popgen.unimaas.nl/~jlindsey/rcode.html}). } \references{ Cox, D. R. and Miller, H. D. \emph{The theory of stochastic processes}, Chapman and Hall, London (1965) Moler, C and van Loan, C (2003). Nineteen dubious ways to compute the exponential of a matrix, twenty-five years later. \emph{SIAM Review} \bold{45}, 3--49. \cr At \url{http://epubs.siam.org/sam-bin/dbq/article/41801} } \keyword{math} msm/man/scoreresid.msm.Rd0000644000176000001440000000226011472706305015102 0ustar ripleyusers\name{scoreresid.msm} \alias{scoreresid.msm} \title{Score residuals} \description{ Score residuals for detecting outlying subjects. } \usage{ scoreresid.msm(x, plot=FALSE) } \arguments{ \item{x}{A fitted multi-state model, as returned by \code{\link{msm}}.} \item{plot}{If \code{TRUE}, display a simple plot of the residuals in subject order, labelled by subject identifiers} } \value{ Vector of the residuals, named by subject identifiers. } \details{ The score residual for a single subject is \deqn{U(\theta)^T I(\theta)^{-1} U(\theta)}{U(theta)^T I(theta)^{-1} U(theta)} where \eqn{U(\theta)}{U(theta)} is the vector of first derivatives of the log-likelihood for that subject at maximum likelihood estimates \eqn{\theta}{theta}, and \eqn{I(\theta)}{theta} is the observed Fisher information matrix, that is, the matrix of second derivatives of minus the log-likelihood for that subject at theta. Subjects with a higher influence on the maximum likelihood estimates will have higher score residuals. } \author{Andrew Titman \email{a.titman@lancaster.ac.uk} (theory), Chris Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk} (code)} \keyword{models}msm/man/statetable.msm.Rd0000644000176000001440000000210010767742643015074 0ustar ripleyusers\name{statetable.msm} \alias{statetable.msm} \title{Table of transitions} \description{ Calculates a frequency table counting the number of times each pair of states were observed in successive observation times. This can be a useful way of summarising multi-state data. } \usage{ statetable.msm(state, subject, data=NULL) } \arguments{ \item{state}{Observed states, assumed to be ordered by time within each subject.} \item{subject}{Subject identification numbers corresponding to \code{state}. If not given, all observations are assumed to be on the same subject.} \item{data}{An optional data frame in which the variables represented by \code{subject} and \code{state} can be found.} } \value{ A frequency table with starting states as rows and finishing states as columns. } \seealso{ \code{\link{crudeinits.msm}} } \examples{ ## Heart transplant data data(cav) ## 148 deaths from state 1, 48 from state 2 and 55 from state 3. statetable.msm(state, PTNUM, data=cav) } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/tnorm.Rd0000644000176000001440000000704211472706305013307 0ustar ripleyusers\name{tnorm} \alias{tnorm} \alias{dtnorm} \alias{ptnorm} \alias{qtnorm} \alias{rtnorm} \title{Truncated Normal distribution} \description{ Density, distribution function, quantile function and random generation for the truncated Normal distribution with mean equal to \code{mean} and standard deviation equal to \code{sd} before truncation, and truncated on the interval \code{[lower, upper]}. } \usage{ dtnorm(x, mean=0, sd=1, lower=-Inf, upper=Inf, log = FALSE) ptnorm(q, mean=0, sd=1, lower=-Inf, upper=Inf, lower.tail = TRUE, log.p = FALSE) qtnorm(p, mean=0, sd=1, lower=-Inf, upper=Inf, lower.tail = TRUE, log.p = FALSE) rtnorm(n, mean=0, sd=1, lower=-Inf, upper=Inf) } \arguments{ \item{x,q}{vector of quantiles.} \item{p}{vector of probabilities.} \item{n}{number of observations. If \code{length(n) > 1}, the length is taken to be the number required.} \item{mean}{vector of means.} \item{sd}{vector of standard deviations.} \item{lower}{lower truncation point.} \item{upper}{upper truncation point.} \item{log, log.p}{logical; if TRUE, probabilities p are given as log(p).} \item{lower.tail}{logical; if TRUE (default), probabilities are P[X <= x], otherwise, P[X > x].} } \value{ \code{dtnorm} gives the density, \code{ptnorm} gives the distribution function, \code{qtnorm} gives the quantile function, and \code{rtnorm} generates random deviates. } \details{ The truncated normal distribution has density \deqn{ f(x, \mu, \sigma) = \phi(x, \mu, \sigma) / (\Phi(u, \mu, \sigma) - \Phi(l, \mu, \sigma)) }{ f(x, mu, sigma) = phi(x, mu, sigma) / (Phi(upper, mu, sigma) - Phi(lower, mu, sigma)) } for \eqn{l <= x <= u}{lower <= x <= upper}, and 0 otherwise. \eqn{\mu}{mean} is the mean of the original Normal distribution before truncation, \cr \eqn{\sigma}{sd} is the corresponding standard deviation, \cr \eqn{u} is the upper truncation point, \cr \eqn{l} is the lower truncation point, \cr \eqn{\phi(x)}{phi(x)} is the density of the corresponding normal distribution, and \cr \eqn{\Phi(x)}{Phi(x)} is the distribution function of the corresponding normal distribution. If \code{mean} or \code{sd} are not specified they assume the default values of \code{0} and \code{1}, respectively. If \code{lower} or \code{upper} are not specified they assume the default values of \code{-Inf} and \code{Inf}, respectively, corresponding to no lower or no upper truncation. Therefore, for example, \code{dtnorm(x)}, with no other arguments, is simply equivalent to \code{dnorm(x)}. Only \code{rtnorm} is used in the \code{msm} package, to simulate from hidden Markov models with truncated normal distributions. This uses the rejection sampling algorithms described by Robert (1995). These functions are merely provided for completion, and are not optimized for numerical stability or speed. To fit a hidden Markov model with a truncated Normal response distribution, use a \code{\link{hmmTNorm}} constructor. See the \code{\link{hmm-dists}} help page for further details. } \references{ Robert, C. P. Simulation of truncated normal variables. Statistics and Computing (1995) 5, 121--125 } \seealso{ \code{\link{dnorm}} } \examples{ x <- seq(50, 90, by=1) plot(x, dnorm(x, 70, 10), type="l", ylim=c(0,0.06)) ## standard Normal distribution lines(x, dtnorm(x, 70, 10, 60, 80), type="l") ## truncated Normal distribution } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{distribution} msm/man/surface.msm.Rd0000644000176000001440000000621611472706305014375 0ustar ripleyusers\name{surface.msm} \alias{surface.msm} \alias{persp.msm} \alias{contour.msm} \alias{image.msm} \title{Explore the likelihood surface} \description{ Plot the log-likelihood surface with respect to two parameters. } \usage{ surface.msm(x, params=c(1,2), np=10, type=c("contour","filled.contour","persp","image"), point=NULL, xrange=NULL, yrange=NULL,...) } \arguments{ \item{x}{Output from \code{\link{msm}}, representing a fitted msm model.} \item{params}{Integer vector with two elements, giving the indices of the parameters to vary. All other parameters will be fixed. Defaults to \code{c(1,2)}, representing the first two log transition intensities. See the \code{fixedpars} argument to \code{msm} for a definition of these indices.} \item{np}{Number of grid points to use in each direction, by default 10. An \code{np x np} grid will be used to evaluate the likelihood surface. If 100 likelihood function evaluations is slow, then reduce this. } \item{type}{Character string specifying the type of plot to produce. \tabular{ll}{ \code{"contour"} \tab Contour plot, using the R function \code{\link{contour}}. \cr \code{"filled.contour"} \tab Solid-color contour plot, using the R function \code{\link{filled.contour}}. \cr \code{"persp"} \tab Perspective plot, using the R function \code{\link{persp}}. \cr \code{"image"} \tab Grid color plot, using the R function \code{\link{image}}. \cr } } \item{point}{Vector of length \code{n}, where \code{n} is the number of parameters in the model, including the parameters that will be varied here. This specifies the point at which to fix the likelihood. By default, this is the maximum likelihood estimates stored in the fitted model \code{x}, \code{x$estimates}.} \item{xrange}{Range to plot for the first varied parameter. Defaults to plus and minus two standard errors, obtained from the Hessian at the maximum likelihood estimate.} \item{yrange}{Range to plot for the second varied parameter. Defaults to plus and minus two standard errors, obtained from the Hessian at the maximum likelihood estimate.} \item{...}{Further arguments to be passed to the plotting function.} } \details{ Draws a contour or perspective plot. Useful for diagnosing irregularities in the likelihood surface. If you want to use these plots before running the maximum likelihood estimation, then just run \code{msm} with all estimates fixed at their initial values. \code{contour.msm} just calls surface.msm with \code{type = "contour"}. \code{persp.msm} just calls surface.msm with \code{type = "persp"}. \code{image.msm} just calls surface.msm with \code{type = "image"}. As these three functions are methods of the generic functions \code{contour}, \code{persp} and \code{image}, they can be invoked as \code{contour(x)}, \code{persp(x)} or \code{image(x)}, where \code{x} is a fitted \code{msm} object. } \seealso{ \code{\link{msm}}, \code{\link{contour}}, \code{\link{filled.contour}}, \code{\link{persp}}, \code{\link{image}}. } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/prevalence.msm.Rd0000644000176000001440000001575111750003130015056 0ustar ripleyusers\name{prevalence.msm} \title{Tables of observed and expected prevalences} \alias{prevalence.msm} \concept{Goodness of fit} \description{ This provides a rough indication of the goodness of fit of a multi-state model, by estimating the observed numbers of individuals occupying each state at a series of times, and comparing these with forecasts from the fitted model. } \usage{ prevalence.msm(x, times=NULL, timezero=NULL, initstates=NULL, covariates="mean", misccovariates="mean", piecewise.times=NULL, piecewise.covariates=NULL, ci=c("none","normal","bootstrap"), cl=0.95, B=1000, interp=c("start","midpoint"), plot=FALSE, ...) } \arguments{ \item{x}{A fitted multi-state model produced by \code{\link{msm}}.} \item{times}{Series of times at which to compute the observed and expected prevalences of states.} \item{timezero}{Initial time of the Markov process. Expected values are forecasted from here. Defaults to the minimum of the observation times given in the data. } \item{initstates}{Optional vector of the same length as the number of states. Gives the numbers of individuals occupying each state at the initial time, to be used for forecasting expected prevalences. The default is those observed in the data. These should add up to the actual number of people in the study at the start. } \item{covariates}{Covariate values for which to forecast expected state occupancy. See \code{\link{qmatrix.msm}}. Defaults to the mean values of the covariates in the data set.} \item{misccovariates}{(Misclassification models only) Values of covariates on the misclassification probability matrix for which to forecast expected state occupancy. Defaults to the mean values of the covariates in the data set.} \item{piecewise.times}{Times at which piecewise-constant intensities change. See \code{\link{pmatrix.piecewise.msm}} for how to specify this. This is only required for time-inhomogeneous models specified using explicit time-dependent covariates, and should not be used for models specified using "pci". } \item{piecewise.covariates}{Covariates on which the piecewise-constant intensities depend. See \code{\link{pmatrix.piecewise.msm}} for how to specify this.} \item{ci}{If \code{"normal"}, then calculate a confidence interval for the expected prevalences by simulating \code{B} random vectors from the asymptotic multivariate normal distribution implied by the maximum likelihood estimates (and covariance matrix) of the log transition intensities and covariate effects, then calculating the expected prevalences for each replicate. If \code{"bootstrap"} then calculate a confidence interval by non-parametric bootstrap refitting. This is 1-2 orders of magnitude slower than the \code{"normal"} method, but is expected to be more accurate. See \code{\link{boot.msm}} for more details of bootstrapping in \pkg{msm}. If \code{"none"} (the default) then no confidence interval is calculated.} \item{cl}{Width of the symmetric confidence interval, relative to 1} \item{B}{Number of bootstrap replicates} \item{interp}{Suppose an individual was observed in states \eqn{S_{r-1}} and \eqn{S_r} at two consecutive times \eqn{t_{r-1}} and \eqn{t_r}, and we want to estimate 'observed' prevalences at a time \eqn{t} between \eqn{t_{r-1}} and \eqn{t_r}. If \code{interp="start"}, then individuals are assumed to be in state \eqn{S_{r-1}} at time \eqn{t}, the same state as they were at \eqn{t_{r-1}}. If \code{interp="midpoint"} then if \eqn{t <= (t_{r-1} + t_r) / 2}, the midpoint of \eqn{t_{r-1}} and \eqn{t_r}, the state at \eqn{t} is assumed to be \eqn{S_{r-1}}, otherwise \eqn{S_{r}}. This is generally more reasonable for "progressive" models. } \item{plot}{Generate a plot of observed against expected prevalences. See \code{\link{plot.prevalence.msm}}} \item{...}{Further arguments to pass to \code{\link{plot.prevalence.msm}}.} } \value{ A list of matrices, with components: \item{Observed}{Table of observed numbers of individuals in each state at each time} \item{Observed percentages}{Corresponding percentage of the individuals at risk at each time.} \item{Expected}{Table of corresponding expected numbers.} \item{Expected percentages}{Corresponding percentage of the individuals at risk at each time.} Or if \code{ci.boot = TRUE}, the component \code{Expected} is a list with components \code{estimates} and \code{ci}.\cr \code{estimates} is a matrix of the expected prevalences, and \code{ci} is a list of two matrices, containing the confidence limits. The component \code{Expected percentages} has a similar format. } \details{ The fitted transition probability matrix is used to forecast expected prevalences from the state occupancy at the initial time. To produce the expected number in state \eqn{j} at time \eqn{t} after the start, the number of individuals under observation at time \eqn{t} (including those who have died, but not those lost to follow-up) is multiplied by the product of the proportion of individuals in each state at the initial time and the transition probability matrix in the time interval \eqn{t}. The proportion of individuals in each state at the "initial" time is estimated, if necessary, in the same way as the observed prevalences. For misclassification models (fitted using an \code{ematrix}), this aims to assess the fit of the full model for the \emph{observed} states. That is, the combined Markov progression model for the true states and the misclassification model. Thus, expected prevalences of \emph{true} states are estimated from the assumed proportion occupying each state at the initial time using the fitted transition probabiliy matrix. The vector of expected prevalences of true states is then multiplied by the fitted misclassification probability matrix to obtain the expected prevalences of \emph{observed} states. For general hidden Markov models, the observed state is taken to be the predicted underlying state from the Viterbi algorithm (\code{\link{viterbi.msm}}). The goodness of fit of these states to the underlying Markov model is tested. Note that this function assumes intensities are the same for all individuals. By default they are taken from the mean values of the covariates in the population. Piecewise-constant intensities may be assumed, through the arguments \code{piecewise.times} and \code{piecewise.covariates}. For an example of this approach, see Gentleman \emph{et al.} (1994). } \references{ Gentleman, R.C., Lawless, J.F., Lindsey, J.C. and Yan, P. Multi-state Markov models for analysing incomplete disease history data with illustrations for HIV disease. \emph{Statistics in Medicine} (1994) 13(3): 805--821. } \seealso{ \code{\link{msm}}, \code{\link{summary.msm}} } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/hmm-dists.Rd0000644000176000001440000002000611760730165014051 0ustar ripleyusers\name{hmm-dists} \alias{hmm-dists} \alias{hmmCat} \alias{hmmIdent} \alias{hmmUnif} \alias{hmmNorm} \alias{hmmLNorm} \alias{hmmExp} \alias{hmmGamma} \alias{hmmWeibull} \alias{hmmPois} \alias{hmmBinom} \alias{hmmTNorm} \alias{hmmMETNorm} \alias{hmmMEUnif} \alias{hmmNBinom} \alias{hmmBeta} \alias{hmmT} \title{Hidden Markov model constructors} \description{ These functions are used to specify the distribution of the response conditionally on the underlying state in a hidden Markov model. A list of these function calls, with one component for each state, should be used for the \code{hmodel} argument to \code{msm}. The initial values for the parameters of the distribution should be given as arguments. } \usage{ hmmCat(prob, basecat) hmmIdent(x) hmmUnif(lower, upper) hmmNorm(mean, sd) hmmLNorm(meanlog, sdlog) hmmExp(rate) hmmGamma(shape, rate) hmmWeibull(shape, scale) hmmPois(rate) hmmBinom(size, prob) hmmTNorm(mean, sd, lower, upper) hmmMETNorm(mean, sd, lower, upper, sderr, meanerr=0) hmmMEUnif(lower, upper, sderr, meanerr=0) hmmNBinom(disp, prob) hmmBeta(shape1,shape2) hmmT(mean,scale,df) } \arguments{ \code{hmmCat} represents a categorical response distribution on the set \code{1, 2, \dots, length(prob)}. The Markov model with misclassification is an example of this type of model. The categories in this case are (some subset of) the underlying states. The \code{hmmIdent} distribution is used for underlying states which are observed exactly without error. \code{hmmUnif}, \code{hmmNorm}, \code{hmmLNorm}, \code{hmmExp}, \code{hmmGamma}, \code{hmmWeibull}, \code{hmmPois}, \code{hmmBinom}, \code{hmmTNorm}, \code{hmmNBinom} and \code{hmmBeta} represent Uniform, Normal, log-Normal, exponential, Gamma, Weibull, Poisson, Binomial, truncated Normal, negative binomial and beta distributions, respectively, with parameterisations the same as the default parameterisations in the corresponding base R distribution functions. \code{hmmT} is the Student t distribution with general mean \eqn{mu}{\mu}, scale \eqn{sigma}{\sigma} and degrees of freedom \code{df}. The variance is \eqn{sigma^2 df/(df + 2)}{\sigma^2 df/(df + 2)}. Note the t distribution in base R \code{\link{dt}} is a standardised one with mean 0 and scale 1. These allow any positive (integer or non-integer) \code{df}. By default, all three parameters, including \code{df}, are estimated when fitting a hidden Markov model, but in practice, \code{df} might need to be fixed for identifiability - this can be done using the \code{fixedpars} argument to \code{\link{msm}}. The \code{hmmMETNorm} and \code{hmmMEUnif} distributions are truncated Normal and Uniform distributions, but with additional Normal measurement error on the response. These are generalisations of the distributions proposed by Satten and Longini (1996) for modelling the progression of CD4 cell counts in monitoring HIV disease. See \code{\link{medists}} for density, distribution, quantile and random generation functions for these distributions. See also \code{\link{tnorm}} for density, distribution, quantile and random generation functions for the truncated Normal distribution. \item{prob}{ (\code{hmmCat}) Vector of probabilities of observing category \code{1, 2, \dots, length(prob)} respectively. Or the probability governing a binomial or negative binomial distribution.} \item{basecat}{ (\code{hmmCat}) Category which is considered to be the "baseline", so that during estimation, the probabilities are parameterised as probabilities relative to this baseline category. By default, the category with the greatest probability is used as the baseline. } \item{x}{ (\code{hmmIdent}) Code in the data which denotes the exactly-observed state. } \item{mean}{ (\code{hmmNorm,hmmLNorm,hmmTNorm}) Mean defining a Normal, or truncated Normal distribution. } \item{sd}{ (\code{hmmNorm,hmmLNorm,hmmTNorm}) Standard deviation defining a Normal, or truncated Normal distribution. } \item{meanlog}{ (\code{hmmNorm,hmmLNorm,hmmTNorm}) Mean on the log scale, for a log Normal distribution. } \item{sdlog}{ (\code{hmmNorm,hmmLNorm,hmmTNorm}) Standard deviation on the log scale, for a log Normal distribution. } \item{rate}{ (\code{hmmPois,hmmExp,hmmGamma}) Rate of a Poisson, Exponential or Gamma distribution (see \code{\link{dpois}}, \code{\link{dexp}}, \code{\link{dgamma}}). } \item{shape}{ (\code{hmmPois,hmmExp,hmmGamma}) Shape parameter of a Gamma or Weibull distribution (see \code{\link{dgamma}}, \code{\link{dweibull}}). } \item{shape1,shape2}{First and second parameters of a beta distribution (see \code{\link{dbeta}}).} \item{scale}{ (\code{hmmGamma}) Scale parameter of a Gamma distribution (see \code{\link{dgamma}}), or unstandardised Student t distribution. } \item{df}{Degrees of freedom of the Student t distribution.} \item{size}{Order of a Binomial distribution (see \code{\link{dbinom}}).} \item{disp}{Dispersion parameter of a negative binomial distribution, also called \code{size} or \code{order}. (see \code{\link{dnbinom}}).} \item{lower}{ (\code{hmmUnif,hmmTNorm,hmmMEUnif}) Lower limit for an Uniform or truncated Normal distribution. } \item{upper}{ (\code{hmmUnif,hmmTNorm,hmmMEUnif}) Upper limit for an Uniform or truncated Normal distribution. } \item{sderr}{ (\code{hmmMETNorm,hmmUnif}) Standard deviation of the Normal measurement error distribution. } \item{meanerr}{ (\code{hmmMETNorm,hmmUnif}) Additional shift in the measurement error, fixed to 0 by default. This may be modelled in terms of covariates. } } \value{ Each function returns an object of class \code{hmodel}, which is a list containing information about the model. The only component which may be useful to end users is \code{r}, a function of one argument \code{n} which returns a random sample of size \code{n} from the given distribution. } \details{ See the PDF manual \file{msm-manual.pdf} in the \file{doc} subdirectory for algebraic definitions of all these distributions. New hidden Markov model response distributions can be added to \pkg{msm} by following the instructions in Section 2.17.1. Parameters which can be modelled in terms of covariates, on the scale of a link function, are as follows. \tabular{ll}{ PARAMETER NAME \tab LINK FUNCTION \cr \code{mean} \tab identity \cr \code{meanlog} \tab identity \cr \code{rate} \tab log \cr \code{scale} \tab log \cr \code{meanerr} \tab identity \cr \code{prob} \tab (multinomial logistic regression) } Parameters \code{basecat, lower, upper, size, meanerr} are fixed at their initial values. All other parameters are estimated while fitting the hidden Markov model, unless the appropriate \code{fixedpars} argument is supplied to \code{msm}. For categorical response distributions \code{(hmmCat)} the outcome probabilities initialized to zero are fixed at zero, and the probability corresponding to \code{basecat} is fixed to one minus the sum of the remaining probabilities. These remaining probabilities are estimated, and can be modelled in terms of covariates via multinomial logistic regression (relative to \code{basecat}). } \references{ Satten, G.A. and Longini, I.M. Markov chains with measurement error: estimating the 'true' course of a marker of the progression of human immunodeficiency virus disease (with discussion) \emph{Applied Statistics} 45(3): 275-309 (1996). Jackson, C.H. and Sharples, L.D. Hidden Markov models for the onset and progresison of bronchiolitis obliterans syndrome in lung transplant recipients \emph{Statistics in Medicine}, 21(1): 113--128 (2002). Jackson, C.H., Sharples, L.D., Thompson, S.G. and Duffy, S.W. and Couto, E. Multi-state Markov models for disease progression with classification error. \emph{The Statistician}, 52(2): 193--209 (2003). } \seealso{ \code{\link{msm}} } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{distribution} msm/man/psor.Rd0000644000176000001440000000373510323151162013125 0ustar ripleyusers\name{psor} \alias{psor} \title{Psoriatic arthritis data} \description{ A series of observations of grades of psoriatic arthritis, as indicated by numbers of damaged joints. } \usage{data(psor)} \format{ A data frame containing 806 observations, representing visits to a psoriatic arthritis (PsA) clinic from 305 patients. The rows are grouped by patient number and ordered by examination time. Each row represents an examination and contains additional covariates. \tabular{rll}{ \code{ptnum} \tab (numeric) \tab Patient identification number \cr \code{months} \tab (numeric) \tab Examination time in months \cr \code{state} \tab (numeric) \tab Clinical state of PsA. Patients in states 1, 2, 3 and 4 \cr \tab \tab have 0, 1 to 4, 5 to 9 and 10 or more damaged joints, \cr \tab \tab respectively. \cr \code{hieffusn} \tab (numeric) \tab Presence of five or more effusions \cr \code{ollwsdrt} \tab (character) \tab Erythrocyte sedimentation rate of less than 15 mm/h \cr }} \references{ Gladman, D. D. and Farewell, V.T. (1999) Progression in psoriatic arthritis: role of time-varying clinical indicators. J. Rheumatol. 26(11):2409-13 } \examples{ ## Four-state progression-only model with high effusion and low ## sedimentation rate as covariates on the progression rates. High ## effusion is assumed to have the same effect on the 1-2, 2-3, and 3-4 ## progression rates, while low sedimentation rate has the same effect ## on the 1-2 and 2-3 intensities, but a different effect on the 3-4. data(psor) psor.q <- rbind(c(0,0.1,0,0),c(0,0,0.1,0),c(0,0,0,0.1),c(0,0,0,0)) psor.msm <- msm(state ~ months, subject=ptnum, data=psor, qmatrix = psor.q, covariates = ~ollwsdrt+hieffusn, constraint = list(hieffusn=c(1,1,1),ollwsdrt=c(1,1,2)), fixedpars=FALSE, control = list(REPORT=1,trace=2), method="BFGS") qmatrix.msm(psor.msm) sojourn.msm(psor.msm) hazard.msm(psor.msm) } \keyword{datasets} msm/man/sojourn.msm.Rd0000644000176000001440000000555711613232417014446 0ustar ripleyusers\name{sojourn.msm} \title{Mean sojourn times from a multi-state model} \alias{sojourn.msm} \description{ Estimate the mean sojourn times in the transient states of a multi-state model and their confidence limits. } \usage{ sojourn.msm(x, covariates="mean", ci=c("delta","normal","bootstrap","none"), cl=0.95, B=1000) } \arguments{ \item{x}{A fitted multi-state model, as returned by \code{\link{msm}}}. \item{covariates}{ The covariate values at which to estimate the mean sojourn times. This can either be:\cr the string \code{"mean"}, denoting the means of the covariates in the data (this is the default),\cr the number \code{0}, indicating that all the covariates should be set to zero,\cr a list of values, with optional names. For example, \code{list(60, 1)}, where the order of the list follows the order of the covariates originally given in the model formula, or a named list, e.g. \code{list (age = 60, sex = 1)} } \item{ci}{ If \code{"delta"} (the default) then confidence intervals are calculated by the delta method, or by simple transformation of the Hessian in the very simplest cases. If \code{"normal"}, then calculate a confidence interval by simulating \code{B} random vectors from the asymptotic multivariate normal distribution implied by the maximum likelihood estimates (and covariance matrix) of the log transition intensities and covariate effects, then transforming. If \code{"bootstrap"} then calculate a confidence interval by non-parametric bootstrap refitting. This is 1-2 orders of magnitude slower than the \code{"normal"} method, but is expected to be more accurate. See \code{\link{boot.msm}} for more details of bootstrapping in \pkg{msm}.} \item{cl}{Width of the symmetric confidence interval to present. Defaults to 0.95.} \item{B}{Number of bootstrap replicates, or number of normal simulations from the distribution of the MLEs} } \value{ A data frame with components: \item{estimates}{Estimated mean sojourn times in the transient states.} \item{SE}{Corresponding standard errors.} \item{L}{Lower confidence limits.} \item{U}{Upper confidence limits.} } \details{ The mean sojourn time in a transient state \eqn{r} is estimated by \eqn{- 1 / q_{rr}}, where \eqn{q_{rr}} is the \eqn{r}th entry on the diagonal of the estimated transition intensity matrix. A continuous-time Markov model is fully specified by the mean sojourn times and the probability that each state is next (\code{\link{pnext.msm}}). This is a more intuitively meaningful description of a model than the transition intensity matrix (\code{\link{qmatrix.msm}}). } \seealso{ \code{\link{msm}}, \code{\link{qmatrix.msm}}, \code{\link{deltamethod}} } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/transient.msm.Rd0000644000176000001440000000126310756577353014766 0ustar ripleyusers\name{transient.msm} \alias{transient.msm} \alias{absorbing.msm} \title{Transient and absorbing states} \description{ Returns the transient and absorbing states of either a fitted model or a transition intensity matrix. } \usage{ transient.msm(x=NULL, qmatrix=NULL) absorbing.msm(x=NULL, qmatrix=NULL) } \arguments{ \item{x}{A fitted multi-state model as returned by \code{\link{msm}}.} \item{qmatrix}{A transition intensity matrix. The diagonal is ignored and taken to be minus the sum of the rest of the row.} } \value{ A vector of the ordinal indices of the transient or absorbing states. } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/qratio.msm.Rd0000644000176000001440000000625311750003153014233 0ustar ripleyusers\name{qratio.msm} \alias{qratio.msm} \title{Estimated ratio of transition intensities} \description{ Compute the estimate and approximate standard error of the ratio of two estimated transition intensities from a fitted multi-state model at a given set of covariate values. } \usage{ qratio.msm(x, ind1, ind2, covariates = "mean", ci=c("delta","normal","bootstrap","none"), cl = 0.95, B=1000) } \arguments{ \item{x}{A fitted multi-state model, as returned by \code{\link{msm}}.} \item{ind1}{Pair of numbers giving the indices in the intensity matrix of the numerator of the ratio, for example, \code{c(1,2)}. } \item{ind2}{Pair of numbers giving the indices in the intensity matrix of the denominator of the ratio, for example, \code{c(2,1)}. } \item{covariates}{ The covariate values at which to estimate the intensities. This can either be:\cr the string \code{"mean"}, denoting the means of the covariates in the data (this is the default),\cr the number \code{0}, indicating that all the covariates should be set to zero,\cr or a list of values, with optional names. For example \code{list (60, 1)} where the order of the list follows the order of the covariates originally given in the model formula, or a named list, \code{list (age = 60, sex = 1)} } \item{ci}{ If \code{"delta"} (the default) then confidence intervals are calculated by the delta method. If \code{"normal"}, then calculate a confidence interval by simulating \code{B} random vectors from the asymptotic multivariate normal distribution implied by the maximum likelihood estimates (and covariance matrix) of the log transition intensities and covariate effects, then transforming. If \code{"bootstrap"} then calculate a confidence interval by non-parametric bootstrap refitting. This is 1-2 orders of magnitude slower than the \code{"normal"} method, but is expected to be more accurate. See \code{\link{boot.msm}} for more details of bootstrapping in \pkg{msm}.} \item{cl}{Width of the symmetric confidence interval to present. Defaults to 0.95.} \item{B}{Number of bootstrap replicates, or number of normal simulations from the distribution of the MLEs} } \value{ A named vector with elements \code{estimate}, \code{se}, \code{L} and \code{U} containing the estimate, standard error, lower and upper confidence limits, respectively, of the ratio of intensities. } \details{ For example, we might want to compute the ratio of the progression rate and recovery rate for a fitted model \code{disease.msm} with a health state (state 1) and a disease state (state 2). In this case, the progression rate is the (1,2) entry of the intensity matrix, and the recovery rate is the (2,1) entry. Thus to compute this ratio with covariates set to their means, we call \code{qratio.msm(disease.msm, c(1,2), c(2,1))} . Standard errors are estimated by the delta method. Confidence limits are estimated by assuming normality on the log scale. } \seealso{ \code{\link{qmatrix.msm}} } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/medists.Rd0000644000176000001440000001346011355074412013616 0ustar ripleyusers\name{medists} \alias{medists} \alias{dmenorm} \alias{pmenorm} \alias{qmenorm} \alias{rmenorm} \alias{dmeunif} \alias{pmeunif} \alias{qmeunif} \alias{rmeunif} \title{Measurement error distributions} \concept{Measurement error} \description{ Truncated Normal and Uniform distributions, where the response is also subject to a Normally distributed measurement error. } \usage{ dmenorm(x, mean=0, sd=1, lower=-Inf, upper=Inf, sderr=0, meanerr=0, log = FALSE) pmenorm(q, mean=0, sd=1, lower=-Inf, upper=Inf, sderr=0, meanerr=0, lower.tail = TRUE, log.p = FALSE) qmenorm(p, mean=0, sd=1, lower=-Inf, upper=Inf, sderr=0, meanerr=0, lower.tail = TRUE, log.p = FALSE) rmenorm(n, mean=0, sd=1, lower=-Inf, upper=Inf, sderr=0, meanerr=0) dmeunif(x, lower=0, upper=1, sderr=0, meanerr=0, log = FALSE) pmeunif(q, lower=0, upper=1, sderr=0, meanerr=0, lower.tail = TRUE, log.p = FALSE) qmeunif(p, lower=0, upper=1, sderr=0, meanerr=0, lower.tail = TRUE, log.p = FALSE) rmeunif(n, lower=0, upper=1, sderr=0, meanerr=0) } \arguments{ \item{x,q}{vector of quantiles.} \item{p}{vector of probabilities.} \item{n}{number of observations. If \code{length(n) > 1}, the length is taken to be the number required.} \item{mean}{vector of means.} \item{sd}{vector of standard deviations.} \item{lower}{lower truncation point.} \item{upper}{upper truncation point.} \item{sderr}{Standard deviation of measurement error distribution.} \item{meanerr}{Optional shift for the measurement error distribution.} \item{log, log.p}{logical; if TRUE, probabilities \eqn{p} are given as \eqn{\log(p)}{log(p)}.} \item{lower.tail}{logical; if TRUE (default), probabilities are \eqn{P[X <= x]}, otherwise, \eqn{P[X > x]}.} } \value{ \code{dmenorm}, \code{dmeunif} give the density, \code{pmenorm}, \code{pmeunif} give the distribution function, \code{qmenorm}, \code{qmeunif} give the quantile function, and \code{rmenorm}, \code{rmeunif} generate random deviates, for the Normal and Uniform versions respectively. } \details{ The normal distribution with measurement error has density \deqn{ \frac{\Phi(u, \mu_2, \sigma_3) - \Phi(l, \mu_2, \sigma_3)}{\Phi(u, \mu_0, \sigma_0) - \Phi(l, \mu_0, \sigma_0)} \phi(x, \mu_0 + \mu_\epsilon, \sigma_2) }{(Phi(upper, mu2, sigma3) - Phi(lower, mu2, sigma3)) / (Phi(upper, mean, sd) - Phi(lower, mean, sd)) * phi(x, mean + meanerr, sigma2)} where \deqn{\sigma_2^2 = \sigma_0^2 + \sigma_\epsilon^2,}{sigma2*sigma2 = sd*sd + sderr*sderr,} \deqn{\sigma_3 = \sigma_0 \sigma_\epsilon / \sigma_2,}{sigma3 = sd*sderr / sigma2,} \deqn{\mu_2 = (x - \mu_\epsilon) \sigma_0^2 + \mu_0 \sigma_\epsilon^2,}{mu2 = (x - meanerr)*sd*sd + mean*sderr*sderr,} \eqn{\mu_0}{mean} is the mean of the original Normal distribution before truncation, \cr \eqn{\sigma_0}{sd} is the corresponding standard deviation, \cr \eqn{u} is the upper truncation point, \cr \eqn{l} is the lower truncation point, \cr \eqn{\sigma_\epsilon}{sderr} is the standard deviation of the additional measurement error, \cr \eqn{\mu_\epsilon}{meanerr} is the mean of the measurement error (usually 0). \cr \eqn{\phi(x)}{phi(x)} is the density of the corresponding normal distribution, and \cr \eqn{\Phi(x)}{Phi(x)} is the distribution function of the corresponding normal distribution. The uniform distribution with measurement error has density \deqn{(\Phi(x, \mu_\epsilon+l, \sigma_\epsilon) - \Phi(x, \mu_\epsilon+u, \sigma_\epsilon)) / (u - l)}{(Phi(x, meanerr+l, sderr) - Phi(x, meanerr+u, sderr)) / (upper - lower)} These are calculated from the original truncated Normal or Uniform density functions \eqn{f(. | \mu, \sigma, l, u)}{f(. | mu, sd)} as \deqn{\int f(y | \mu, \sigma, l, u) \phi(x, y + \mu_\epsilon, \sigma_\epsilon) dy}{integral f(y | mu, sd, l, u) phi(x, y + meanerr, sderr) dy} If \code{sderr} and \code{meanerr} are not specified they assume the default values of 0, representing no measurement error variance, and no constant shift in the measurement error, respectively. Therefore, for example with no other arguments, \code{dmenorm(x)}, is simply equivalent to \code{dtnorm(x)}, which in turn is equivalent to \code{dnorm(x)}. These distributions were used by Satten and Longini (1996) for CD4 cell counts conditionally on hidden Markov states of HIV infection, and later by Jackson and Sharples (2002) for FEV1 measurements conditionally on states of chronic lung transplant rejection. These distribution functions are just provided for convenience, and are not optimised for numerical accuracy or speed. To fit a hidden Markov model with these response distributions, use a \code{\link{hmmMETNorm}} or \code{\link{hmmMEUnif}} constructor. See the \code{\link{hmm-dists}} help page for further details. } \seealso{ \code{\link{dnorm}}, \code{\link{dunif}}, \code{\link{dtnorm}} } \references{ Satten, G.A. and Longini, I.M. Markov chains with measurement error: estimating the 'true' course of a marker of the progression of human immunodeficiency virus disease (with discussion) \emph{Applied Statistics} 45(3): 275-309 (1996) Jackson, C.H. and Sharples, L.D. Hidden Markov models for the onset and progression of bronchiolitis obliterans syndrome in lung transplant recipients \emph{Statistics in Medicine}, 21(1): 113--128 (2002). } \examples{ ## what does the distribution look like? x <- seq(50, 90, by=1) plot(x, dnorm(x, 70, 10), type="l", ylim=c(0,0.06)) ## standard Normal lines(x, dtnorm(x, 70, 10, 60, 80), type="l") ## truncated Normal ## truncated Normal with small measurement error lines(x, dmenorm(x, 70, 10, 60, 80, sderr=3), type="l") } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{distribution} msm/man/plot.survfit.msm.Rd0000644000176000001440000001060311753215510015412 0ustar ripleyusers\name{plot.survfit.msm} \alias{plot.survfit.msm} \title{Plot empirical and fitted survival curves} \description{ Plot a Kaplan-Meier estimate of the survival probability and compare it with the fitted survival probability from a \code{msm} model. } \usage{ \method{plot}{survfit.msm}(x, from=1, to=NULL, range=NULL, covariates="mean", interp=c("start","midpoint"), ci=c("none","normal","bootstrap"), B=100, legend.pos=NULL, xlab="Time", ylab="Survival probability", lty=1, lwd=1, col="red", lty.ci=2, lwd.ci=1, col.ci="red", mark.time=TRUE, col.surv="blue", lty.surv=2, lwd.surv=1, ...) } \arguments{ \item{x}{Output from \code{\link{msm}}, representing a fitted multi-state model object.} \item{from}{State from which to consider survival. Defaults to state 1. } \item{to}{Absorbing state to consider. Defaults to the highest-labelled absorbing state. } \item{range}{Vector of two elements, giving the range of times to plot for.} \item{covariates}{Covariate values for which to evaluate the expected probabilities. This can either be:\cr the string \code{"mean"}, denoting the means of the covariates in the data (this is the default),\cr the number \code{0}, indicating that all the covariates should be set to zero,\cr or a list of values, with optional names. For example \code{list (60, 1)} where the order of the list follows the order of the covariates originally given in the model formula, or a named list, \code{list (age = 60, sex = 1)} } \item{ci}{If \code{"none"} (the default) no confidence intervals are plotted. If \code{"normal"} or \code{"bootstrap"}, confidence intervals are plotted based on the respective method in \code{\link{pmatrix.msm}}. This is very computationally-intensive, since intervals must be computed at a series of times.} \item{B}{Number of bootstrap or normal replicates for the confidence interval. The default is 100 rather than the usual 1000, since these plots are for rough diagnostic purposes.} \item{interp}{If \code{interp="start"} (the default) then the entry time into the absorbing state is assumed to be the time it is first observed in the data. If \code{interp="midpoint"} then the entry time into the absorbing state is assumed to be halfway between the time it is first observed and the previous observation time. This is generally more reasonable for "progressive" models with observations at arbitrary times. } \item{legend.pos}{Vector of the \eqn{x} and \eqn{y} position, respectively, of the legend.} \item{xlab}{x axis label.} \item{ylab}{y axis label.} \item{lty}{Line type for the fitted curve. See \code{\link{par}}.} \item{lwd}{Line width for the fitted curve. See \code{\link{par}}.} \item{col}{Colour for the fitted curve. See \code{\link{par}}.} \item{lty.ci}{Line type for the fitted curve confidence limits. See \code{\link{par}}.} \item{lwd.ci}{Line width for the fitted curve confidence limits. See \code{\link{par}}.} \item{col.ci}{Colour for the fitted curve confidence limits. See \code{\link{par}}.} \item{mark.time}{Mark the empirical survival curve at each censoring point, see \code{\link[survival]{lines.survfit}}.} \item{col.surv}{Colour for the empirical survival curve, passed to \code{\link[survival]{lines.survfit}}. See \code{\link{par}}.} \item{lty.surv}{Line type for the empirical survival curve, passed to \code{\link[survival]{lines.survfit}}. See \code{\link{par}}.} \item{lwd.surv}{Line width for the empirical survival curve, passed to \code{\link[survival]{lines.survfit}}. See \code{\link{par}}.} \item{...}{Other arguments to be passed to the \code{\link{plot}} function which draws the fitted curve, or the \code{\link[survival]{lines.survfit}} function which draws the empirical curve. } } \details{ If the data represent observations of the process at arbitrary times, then the first occurrence of the absorbing state in the data will usually be greater than the actual first transition time to that state. Therefore the Kaplan-Meier estimate of the survival probability will be an overestimate. This currently only handles time-homogeneous models. } \seealso{\code{\link[survival]{survfit}}, \code{\link[survival]{plot.survfit}}, \code{\link{plot.prevalence.msm}}} \keyword{models} msm/man/coef.msm.Rd0000644000176000001440000000240410616662034013653 0ustar ripleyusers\name{coef.msm} \alias{coef.msm} \title{Extract model coefficients} \description{ Extract the estimated log transition intensities and the corresponding linear effects of each covariate. } \usage{ \method{coef}{msm}(object, \dots) } \arguments{ \item{object}{A fitted multi-state model object, as returned by \code{\link{msm}}.} \item{...}{(unused) further arguments passed to or from other methods.} } \value{ If there is no misclassification, \code{coef.msm} returns a list of matrices. The first component, labelled \code{logbaseline}, is a matrix containing the estimated transition intensities on the log scale with any covariates fixed at their means in the data. Each remaining component is a matrix giving the linear effects of the labelled covariate on the matrix of log intensities. \cr For misclassification models, \code{coef.msm} returns a list of lists. The first component, \code{Qmatrices}, is a list of matrices as described in the previous paragraph. The additional component \code{Ematrices} is a list of similar format containing the logit-misclassification probabilities and any estimated covariate effects. } \seealso{ \code{\link{msm}} } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/sim.msm.Rd0000644000176000001440000000447210616662030013532 0ustar ripleyusers\name{sim.msm} \title{Simulate one individual trajectory from a continuous-time Markov model} \alias{sim.msm} \concept{Simulation} \description{Simulate one realisation from a continuous-time Markov process up to a given time. } \usage{ sim.msm(qmatrix, maxtime, covs=NULL, beta=NULL, obstimes=0, start=1, mintime=0) } \arguments{ \item{qmatrix}{ The transition intensity matrix of the Markov process. The diagonal of \code{qmatrix} is ignored, and computed as appropriate so that the rows sum to zero. For example, a possible \code{qmatrix} for a three state illness-death model with recovery is: \code{rbind( c( 0, 0.1, 0.02 ), c( 0.1, 0, 0.01 ), c( 0, 0, 0 ) )} } \item{maxtime}{ Maximum time for the simulated process. } \item{covs}{Matrix of time-dependent covariates, with one row for each observation time and one column for each covariate.} \item{beta}{Matrix of linear covariate effects on log transition intensities. The rows correspond to different covariates, and the columns to the transition intensities. The intensities are ordered by reading across rows of the intensity matrix, starting with the first, counting the positive off-diagonal elements of the matrix.} \item{obstimes}{Vector of times at which the covariates are observed.} \item{start}{Starting state of the process. Defaults to 1.} \item{mintime}{Starting time of the process. Defaults to 0.} } \value{ A list with components, \item{states}{Simulated states through which the process moves. This ends with either an absorption before \code{obstime}, or a transient state at \code{obstime}. } \item{times}{Exact times at which the process changes to the corresponding states} \item{qmatrix}{The given transition intensity matrix} } \details{ The effect of time-dependent covariates on the transition intensity matrix for an individual is determined by assuming that the covariate is a step function which remains constant in between the individual's observation times. } \seealso{ \code{\link{simmulti.msm}} } \examples{ qmatrix <- rbind( c(-0.2, 0.1, 0.1 ), c(0.5, -0.6, 0.1 ), c(0, 0, 0) ) sim.msm(qmatrix, 30) } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/plotprog.msm.Rd0000644000176000001440000000403011471020401014564 0ustar ripleyusers\name{plotprog.msm} \alias{plotprog.msm} \title{Kaplan Meier estimates of incidence} \description{ Compute and plot Kaplan-Meier estimates of the probability that each successive state has not occurred yet. } \usage{ plotprog.msm(formula, subject, data, legend.pos=NULL, xlab="Time", ylab="1 - incidence probability", lwd=1, xlim=NULL, mark.time=TRUE, ...) } \arguments{ \item{formula}{A formula giving the vectors containing the observed states and the corresponding observation times. For example, \code{state ~ time} Observed states should be in the set \code{1, \dots, n}, where \code{n} is the number of states.} \item{subject}{Vector of subject identification numbers for the data specified by \code{formula}. If missing, then all observations are assumed to be on the same subject. These must be sorted so that all observations on the same subject are adjacent.} \item{data}{An optional data frame in which the variables represented by \code{state}, \code{time} and \code{subject} can be found.} \item{legend.pos}{Vector of the \eqn{x} and \eqn{y} position, respectively, of the legend.} \item{xlab}{x axis label.} \item{ylab}{y axis label.} \item{lwd}{Line width. See \code{\link{par}}.} \item{xlim}{x axis limits, e.g. c(0,10) for an axis ranging from 0 to 10. Default is the range of observation times.} \item{mark.time}{Mark the empirical survival curve at each censoring point, see \code{\link{lines.survfit}}.} \item{...}{Other arguments to be passed to the \code{\link{plot}} and \code{\link[survival]{lines.survfit}} functions.} } \details{ If the data represent observations of the process at arbitrary times, then the first occurrence of the state in the data will usually be greater than the actual first transition time to that state. Therefore the probabilities plotted by \code{\link{plotprog.msm}} will be overestimates. } \seealso{\code{\link[survival]{survfit}}, \code{\link[survival]{plot.survfit}}} \keyword{models} msm/man/aneur.Rd0000644000176000001440000000362210756577301013270 0ustar ripleyusers\name{aneur} \alias{aneur} \title{Aortic aneurysm progression data} \description{ This dataset contains longitudinal measurements of grades of aortic aneurysms, measured by ultrasound examination of the diameter of the aorta. } \usage{data(aneur)} \format{ A data frame containing 4337 rows, with each row corresponding to an ultrasound scan from one of 838 men over 65 years of age. \tabular{rll}{ \code{ptnum} \tab (numeric) \tab Patient identification number \cr \code{age} \tab (numeric) \tab Recipient age at examination (years) \cr \code{diam} \tab (numeric) \tab Aortic diameter\cr \code{state} \tab (numeric) \tab State of aneurysm. \cr } The states represent successive degrees of aneurysm severity, as indicated by the aortic diameter. \tabular{rll}{ State 1 \tab Aneurysm-free \tab < 30 cm \cr State 2 \tab Mild aneurysm \tab 30-44 cm \cr State 3 \tab Moderate aneurysm \tab 45-54 cm \cr State 4 \tab Severe aneurysm \tab > 55 cm \cr } 683 of these men were aneurysm-free at age 65 and were re-screened every two years. The remaining men were aneurysmal at entry and had successive screens with frequency depending on the state of the aneurysm. Severe aneurysms are repaired by surgery. } \source{ The Chichester, U.K. randomised controlled trial of screening for abdominal aortic aneurysms by ultrasonography. } \references{ Jackson, C.H., Sharples, L.D., Thompson, S.G. and Duffy, S.W. and Couto, E. Multi-state Markov models for disease progression with classification error. \emph{The Statistician}, 52(2): 193--209 (2003) Couto, E. and Duffy, S. W. and Ashton, H. A. and Walker, N. M. and Myles, J. P. and Scott, R. A. P. and Thompson, S. G. (2002) \emph{Probabilities of progression of aortic aneurysms: estimates and implications for screening policy} Journal of Medical Screening 9(1):40--42 } \keyword{datasets} msm/man/boot.msm.Rd0000644000176000001440000001372212030112250013665 0ustar ripleyusers\name{boot.msm} \alias{boot.msm} \title{Bootstrap resampling for multi-state models} \description{ Draw a number of bootstrap resamples, refit a \code{\link{msm}} model to the resamples, and calculate statistics on the refitted models. } \usage{ boot.msm(x, stat=pmatrix.msm, B=1000, file=NULL) } \arguments{ \item{x}{A fitted msm model, as output by \code{\link{msm}}.} \item{stat}{A function to call on each refitted msm model. By default this is \code{\link{pmatrix.msm}}, returning the transition probability matrix in one time unit. If \code{NULL} then no function is computed.} \item{B}{Number of bootstrap resamples.} \item{file}{Name of a file in which to save partial results after each replicate. This is saved using \code{\link{save}} and can be restored using \code{\link{load}}, producing an object called \code{boot.list} containing the partial results. Not currently supported when using parallel processing.} } \details{ The bootstrap datasets are computed by resampling independent transitions between pairs of states (for non-hidden models without censoring), or independent individual series (for hidden models or models with censoring). Therefore this approach doesn't work if, for example, the data for a HMM consist of a series of observations from just one individual, and is inaccurate for small numbers of independent transitions or individuals. Confidence intervals or standard errors for the corresponding statistic can be calculated by summarising the returned list of \code{B} replicated outputs. This is currently implemented for most the output functions \code{\link{qmatrix.msm}}, \code{\link{ematrix.msm}}, \code{\link{qratio.msm}}, \code{\link{pmatrix.msm}}, \code{\link{pmatrix.piecewise.msm}}, \code{\link{totlos.msm}} and \code{\link{prevalence.msm}}. For other outputs, users will have to write their own code to summarise the output of \code{\link{boot.msm}}. Most of \pkg{msm}'s output functions present confidence intervals based on asymptotic standard errors calculated from the Hessian. These are expected to be underestimates of the true standard errors (Cramer-Rao lower bound). Some of these functions use a further approximation, the delta method (see \code{\link{deltamethod}}) to obtain standard errors of transformed parameters. Bootstrapping should give a more accurate estimate of the uncertainty. An alternative method which is less accurate though faster than bootstrapping, but more accurate than the delta method, is to draw a sample from the asymptotic multivariate normal distribution implied by the maximum likelihood estimates (and covariance matrix), and summarise the transformed estimates. See \code{\link{pmatrix.msm}}. All objects used in the original call to \code{\link{msm}} which produced \code{x}, such as the \code{qmatrix}, should be in the working environment, or else \code{boot.msm} will produce an \dQuote{object not found} error. This enables \code{boot.msm} to refit the original model to the replicate datasets. However there is currently a limitation. In the original call to \code{msm}, the \code{"formula"} argument should be specified directly, as, for example, \code{msm(state ~ time, data = ...)} and not, for example, \code{form = data$state ~ data$time} \code{msm(formula=form, data = ...)} otherwise \code{boot.msm} will be unable to draw the replicate datasets. \code{boot.msm} will also fail with an incomprehensible error if the original call to msm used a used-defined object whose name is the same as a built-in R object, or an object in any other loaded package. For example, if you have called a Q matrix \code{q}, when \code{q()} is the built-in function for quitting R. If \code{stat} is \code{NULL}, then \code{B} different \code{msm} model objects will be stored in memory. This is unadvisable, as \code{msm} objects tend to be large, since they contain the original data used for the \code{msm} fit, so this will be wasteful of memory. To specify more than one statistic, write a function consisting of a list of different function calls, for example, \code{stat = function(x) list (pmatrix.msm(x, t=1), pmatrix.msm(x, t=2))} } \value{ A list with \code{B} components, containing the result of calling function \code{stat} on each of the refitted models. If \code{stat} is \code{NULL}, then each component just contains the refitted model. If one of the \code{B} model fits was unsuccessful and resulted in an error, then the corresponding list component will contain the error message. } \references{ Efron, B. and Tibshirani, R.J. (1993) \emph{An Introduction to the Bootstrap}, Chapman and Hall. } \seealso{ \code{\link{qmatrix.msm}}, \code{\link{qratio.msm}}, \code{\link{sojourn.msm}}, \code{\link{ematrix.msm}}, \code{\link{pmatrix.msm}}, \code{\link{pmatrix.piecewise.msm}}, \code{\link{totlos.msm}}, \code{\link{prevalence.msm}}. } \examples{ \dontrun{ ## Psoriatic arthritis example data(psor) psor.q <- rbind(c(0,0.1,0,0),c(0,0,0.1,0),c(0,0,0,0.1),c(0,0,0,0)) psor.msm <- msm(state ~ months, subject=ptnum, data=psor, qmatrix = psor.q, covariates = ~ollwsdrt+hieffusn, constraint = list(hieffusn=c(1,1,1),ollwsdrt=c(1,1,2)), control = list(REPORT=1,trace=2), method="BFGS") ## Bootstrap the baseline transition intensity matrix. This will take a long time. q.list <- boot.msm(psor.msm, function(x)x$Qmatrices$baseline) ## Manipulate the resulting list of matrices to calculate bootstrap standard errors. apply(array(unlist(q.list), dim=c(4,4,5)), c(1,2), sd) ## Similarly calculate a bootstrap 95\% confidence interval apply(array(unlist(q.list), dim=c(4,4,5)), c(1,2), function(x)quantile(x, c(0.025, 0.975))) ## Bootstrap standard errors are larger than the asymptotic standard ## errors calculated from the Hessian psor.msm$QmatricesSE$baseline } } \author{C.H.Jackson } \keyword{models} msm/man/summary.msm.Rd0000644000176000001440000000444411050311470014426 0ustar ripleyusers\name{msm.summary} \title{Summarise a fitted multi-state model} \alias{summary.msm} \alias{print.summary.msm} \description{ Summary method for fitted \code{\link{msm}} models. Currently, this produces a table of observed and expected state prevalences for each time. For models with covariates, prints hazard ratios with confidence intervals for covariate effects. } \usage{ \method{summary}{msm}(object, times=NULL, timezero=NULL, initstates=NULL, covariates="mean", misccovariates="mean", hazard.scale=1, \dots) } \arguments{ \item{object}{A fitted multi-state model object, as returned by \code{\link{msm}}.} \item{times}{A sequence of times at which to compare observed and expected prevalences of each state. Defaults to \code{seq(min(times), max(times), (max(times) - min(times))/10). } } \item{timezero}{Initial time of the Markov process. Expected values are forecasted from here. Defaults to the minimum of the observation times given in the data. } \item{initstates}{ Optional vector of the same length as the number of states. Gives the numbers of individuals occupying each state at \code{timezero}. The default is that all individuals are in state 1. } \item{covariates}{Covariate values for which to forecast expected state occupancy. See \code{\link{qmatrix.msm}}. Defaults to the mean values of the covariates in the data set.} \item{misccovariates}{(Misclassification models only) Values of covariates on the misclassification probability matrix for which to forecast expected state occupancy. Defaults to the mean values of the covariates in the data set.} \item{hazard.scale}{Vector with same elements as number of covariates on transition rates. Corresponds to the increase in each covariate used to calculate its hazard ratio. Defaults to all 1.} \item{...}{further arguments passed to or from other methods.} } \value{ A list of class \code{summary.msm}, with components: \item{prevalences}{Output from \code{\link{prevalence.msm}}.} \item{hazard}{Output from \code{\link{hazard.msm}}}. \item{hazard.scale}{Value of the \code{hazard.scale} argument} } \seealso{ \code{\link{msm}},\code{\link{prevalence.msm}}, \code{\link{hazard.msm}} } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/plot.msm.Rd0000644000176000001440000000345010765470602013722 0ustar ripleyusers\name{plot.msm} \title{Plots of multi-state models} \alias{plot.msm} \concept{Survival} \description{ This produces a plot of the expected probability of survival against time, from each transient state. Survival is defined as not entering an absorbing state. } \usage{ \method{plot}{msm}(x, from, to, range, covariates, legend.pos, xlab="Time", ylab="Fitted survival probability", lwd=1, ...) } \arguments{ \item{x}{Output from \code{\link{msm}}, representing a fitted multi-state model object.} \item{from}{States from which to consider survival. Defaults to the complete set of transient states. } \item{to}{Absorbing state to consider. Defaults to the highest-labelled absorbing state. } \item{range}{Vector of two elements, giving the range of times to plot for.} \item{covariates}{Covariate values for which to evaluate the expected probabilities. This can either be:\cr the string \code{"mean"}, denoting the means of the covariates in the data (this is the default),\cr the number \code{0}, indicating that all the covariates should be set to zero,\cr or a list of values, with optional names. For example \code{list (60, 1)} where the order of the list follows the order of the covariates originally given in the model formula, or a named list, \code{list (age = 60, sex = 1)} } \item{legend.pos}{Vector of the \eqn{x} and \eqn{y} position, respectively, of the legend.} \item{xlab}{x axis label.} \item{ylab}{y axis label.} \item{lwd}{Line width. See \code{\link{par}}.} \item{...}{Other arguments to be passed to the generic \code{\link{plot}} and \code{\link{lines}} functions.} } \seealso{ \code{\link{msm}} } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/pearson.msm.Rd0000644000176000001440000002703611730664023014414 0ustar ripleyusers\name{pearson.msm} \alias{pearson.msm} \title{Pearson-type goodness-of-fit test} \description{Pearson-type goodness-of-fit test for multi-state models fitted to panel-observed data. } \usage{ pearson.msm(x, transitions=NULL, timegroups=3, intervalgroups=3, covgroups=3, groups=NULL, boot=FALSE, B=500, next.obstime=NULL, N=100, indep.cens=TRUE, maxtimes=NULL) } \arguments{ \item{x}{A fitted multi-state model, as returned by \code{\link{msm}}.} \item{transitions}{This should be an integer vector indicating which interval transitions should be grouped together in the contingency table. Its length should be the number of allowed interval transitions, excluding transitions from absorbing states to absorbing states. The allowed interval transitions are the set of pairs of states \eqn{(a,b)} for which it is possible to observe \eqn{a} at one time and \eqn{b} at any later time. For example, in a "well-disease-death" model with allowed \emph{instantaneous} 1-2, 2-3 transitions, there are 5 allowed \emph{interval} transitions. In numerical order, these are 1-1, 1-2, 1-3, 2-2 and 2-3, excluding absorbing-absorbing transitions. Then, to group transitions 1-1,1-2 together, and transitions 2-2,2-3 together, specify \code{transitions = c(1,1,2,3,3)}. Only transitions from the same state may be grouped. By default, each interval transition forms a separate group. } \item{timegroups}{Number of groups based on quantiles of the time since the start of the process.} \item{intervalgroups}{Number of groups based on quantiles of the time interval between observations.} \item{covgroups}{Number of groups based on quantiles of \eqn{\sum_r q_{irr}}{sum_r q_{irr}}, where \eqn{q_{irr}} are the diagonal entries of the transition intensity matrix for the \emph{i}th transition. These are a function of the covariate effects and the covariate values at the \emph{i}th transition: \eqn{q_{irr}} is minus the sum of the off-diagonal entries \eqn{q_{rs}^{(0)} exp (\beta_{rs}^T z_i)} on the \emph{r}th row. Thus \code{covgroups} summarises the impact of covariates at each observation, by calculating the overall rate of progression through states at that observation. For time-inhomogeneous models specified using the \code{pci} argument to \code{\link{msm}}, if the only covariate is the time period, \code{covgroups} is set to 1, since \code{timegroups} ensures that transitions are grouped by time. } \item{groups}{A vector of arbitrary groups in which to categorise each transition. This can be an integer vector or a factor. This can be used to diagnose specific areas of poor fit. For example, the contingency table might be grouped by arbitrary combinations of covariates to detect types of individual for whom the model fits poorly. The length of \code{groups} should be \code{x$data$n}, the number of observations used in the model fit, which is the number of observations in the original dataset with any missing values excluded. The value of \code{groups} at observation \eqn{i} is used to categorise the transition which \emph{ends} at observation i. Values of \code{groups} at the first observation for each subject are ignored. } \item{boot}{Estimate an "exact" p-value using a parametric bootstrap. All objects used in the original call to \code{\link{msm}} which produced \code{x}, such as the \code{qmatrix}, should be in the working environment, or else an \dQuote{object not found} error will be given. This enables the original model to be refitted to the replicate datasets. } \item{B}{Number of bootstrap replicates.} \item{next.obstime}{This is a vector of length \code{x$data$n} (the number of observations used in the model fit) giving the time to the next \emph{scheduled} observation following each time point. This is only used when times to death are known exactly. For individuals who died (entered an absorbing state) before the next scheduled observation, and the time of death is known exactly, \code{next.obstime} would be \emph{greater} than the observed death time. If the individual did not die, and a scheduled observation did follow that time point, \code{next.obstime} should just be the same as the time to that observation. \code{next.obstime} is used to determine a grouping of the time interval between observations, which should be based on scheduled observations. If exact times to death were used in the grouping, then shorter intervals would contain excess deaths, and the goodness-of-fit statistic would be biased. If \code{next.obstime} is unknown, it is multiply-imputed using a product-limit estimate based on the intervals to observations other than deaths. The resulting tables of transitions are averaged over these imputations. This may be slow. } \item{N}{Number of imputations for the estimation of the distribution of the next scheduled observation time, when there are exact death times.} \item{indep.cens}{If \code{TRUE}, then times to censoring are included in the estimation of the distribution to the next scheduled observation time. If \code{FALSE}, times to censoring are assumed to be systematically different from other observation times. } \item{maxtimes}{A vector of length \code{x$data$n}, or a common scalar, giving an upper bound for the next scheduled observation time. Used in the multiple imputation when times to death are known exactly. If a value greater than \code{maxtimes} is simulated, then the next scheduled observation is taken as censored. This should be supplied, if known. If not supplied, this is taken to be the maximum interval occurring in the data, plus one time unit. For observations which are not exact death times, this should be the time since the previous observation. } } \value{ A list whose first two elements are contingency tables of observed transitions \eqn{O} and expected transitions \eqn{E}, respectively, for each combination of groups. The third element is a table of the deviances \eqn{(O - E)^2 / E} multiplied by the sign of \eqn{O - E}. If the expected number of transitions is zero then the deviance is zero. Entries in the third matrix will be bigger in magnitude for groups for which the model fits poorly. \cr \item{\code{"test"}}{, the fourth element of the list, is a data frame with one row containing the Pearson-type goodness-of-fit test statistic \code{stat}. The test statistic is the sum of the deviances. For panel-observed data without exact death times, \code{p.lower} and \code{p.upper} are theoretical lower and upper limits for the unknown p-value of the test statistic, based on chi-squared distributions with \code{df.lower} and \code{df.upper} degrees of freedom, respectively. \code{df.upper} is the number of independent cells in the contingency table, and \code{df.lower} is \code{df.upper} minus the number of estimated parameters in the model.} \item{\code{"intervalq"}}{(not printed by default) contains the definition of the grouping of the intervals between observations. These groups are defined by quantiles within the groups corresponding to the time since the start of the process.} \item{\code{"sim"}}{If there are exact death times, this contains simulations of the contingency tables and test statistics for each imputation of the next scheduled sampling time. These are averaged over to produce the presented tables and test statistic. This element is not printed by default. With exact death times, the null variance of the test statistic (formed by taking mean of simulated test statistics) is less than twice the mean (Titman, 2008), and the null distribution is not chi-squared. In this case, \code{p.upper} is an upper limit for the true asymptotic p-value, but \code{p.lower} is not a lower limit, and is not presented.} \item{\code{"boot"}}{If the bootstrap has been used, the element will contain the bootstrap replicates of the test statistics (not printed by default).} } \details{ This method (Aguirre-Hernandez and Farewell, 2002) is intended for data which represent observations of the process at arbitrary times ("snapshots", or "panel-observed" data). For data which represent the exact transition times of the process, \code{\link{prevalence.msm}} can be used to assess fit, though without a formal test. When times of death are known exactly, states are misclassified, or an individual's final observation is a censored state, the modification by Titman and Sharples (2008) is used. The only form of censoring supported is a state at the end of an individual's series which represents an unknown transient state (i.e. the individual is only known to be alive at this time). Other types of censoring are omitted from the data before performing the test. See these references for further details of the methods. The method used for censored states is a modification of the method in the appendix to Titman and Sharples (2008), described at \url{http://www.mrc-bsu.cam.ac.uk/personal/chris/papers/robustcensoring.pdf} (Titman, 2007). Groupings of the time since initiation, the time interval and the impact of covariates are based on equally-spaced quantiles. The number of groups should be chosen that there are not many cells with small expected numbers of transitions, since the deviance statistic will be unstable for sparse contingency tables. Ideally, the expected numbers of transitions in each cell of the table should be no less than about 5. Conversely, the power of the test is reduced if there are too few groups. Therefore, some sensitivity analysis of the test results to the grouping is advisable. To ensure that the null distribution of the statistic is approximated reasonably by a chi-squared distribution with \code{df.lower} degrees of freedom, the table should always be grouped by any fitted covariates (Aguirre-Hernandez and Farewell, 2002). Saved model objects fitted with previous versions of R (versions less than 0.8) will need to be refitted under the current R for use with \code{pearson.msm}. } \references{ Aguirre-Hernandez, R. and Farewell, V. (2002) A Pearson-type goodness-of-fit test for stationary and time-continuous Markov regression models. \emph{Statistics in Medicine} 21:1899-1911. Titman, A. and Sharples, L. (2008) A general goodness-of-fit test for Markov and hidden Markov models. \emph{Statistics in Medicine} 27(12):2177-2195 Titman, A. (2008) Model diagnostics in multi-state models of biological systems. PhD thesis, University of Cambridge. } \seealso{ \code{\link{msm}},\code{\link{prevalence.msm}},\code{\link{scoreresid.msm}}, } \examples{ data(psor) psor.q <- rbind(c(0,0.1,0,0),c(0,0,0.1,0),c(0,0,0,0.1),c(0,0,0,0)) psor.msm <- msm(state ~ months, subject=ptnum, data=psor, qmatrix = psor.q, covariates = ~ollwsdrt+hieffusn, constraint = list(hieffusn=c(1,1,1),ollwsdrt=c(1,1,2)), control = list(REPORT=1,trace=2), method="BFGS") pearson.msm(psor.msm, timegroups=2, intervalgroups=2, covgroups=2) # More 1-2, 1-3 and 1-4 observations than expected in shorter time # intervals - the model fits poorly. # A random effects model might accommodate such fast progressors. } \author{ Andrew Titman (\email{a.titman@lancaster.ac.uk}), Chris Jackson (\email{chris.jackson@mrc-bsu.cam.ac.uk}) } \keyword{models} msm/man/totlos.msm.Rd0000644000176000001440000001055111750003171014254 0ustar ripleyusers\name{totlos.msm} \alias{totlos.msm} \title{Total length of stay} \description{ Estimate the expected total length of stay in each set of states, for a given period of evolution of a multi-state model. } \usage{ totlos.msm(x, start=1, end=NULL, fromt=0, tot=Inf, covariates="mean", ci=c("none","normal","bootstrap"), cl=0.95, B=1000, ...) } \arguments{ \item{x}{A fitted multi-state model, as returned by \code{\link{msm}}. } \item{start}{State at the beginning of the period.} \item{end}{States to forecast the total length of stay in. Defaults to all states.} \item{fromt}{Time from which to estimate total length of stay. Defaults to 0, the beginning of the process.} \item{tot}{Time up to which total length of stay is estimated. Defaults to infinity, giving the expected time spent in the state until absorption. For models without an absorbing state, \code{t} must be specified.} \item{covariates}{ The covariate values to estimate for. This can either be:\cr the string \code{"mean"}, denoting the means of the covariates in the data (this is the default),\cr the number \code{0}, indicating that all the covariates should be set to zero,\cr or a list of values, with optional names. For example \code{list (60, 1)} where the order of the list follows the order of the covariates originally given in the model formula, or a named list, \code{list (age = 60, sex = 1)} } \item{ci}{If \code{"normal"}, then calculate a confidence interval by simulating \code{B} random vectors from the asymptotic multivariate normal distribution implied by the maximum likelihood estimates (and covariance matrix) of the log transition intensities and covariate effects, then calculating the total length of stay for each replicate. If \code{"bootstrap"} then calculate a confidence interval by non-parametric bootstrap refitting. This is 1-2 orders of magnitude slower than the \code{"normal"} method, but is expected to be more accurate. See \code{\link{boot.msm}} for more details of bootstrapping in \pkg{msm}. If \code{"none"} (the default) then no confidence interval is calculated.} \item{cl}{Width of the symmetric confidence interval, relative to 1} \item{B}{Number of bootstrap replicates} \item{...}{Further arguments to be passed to the \code{\link{integrate}} function to control the numerical integration.} } \value{ A vector of expected total lengths of stay for each transient state. } \details{ The expected total length of stay in state \eqn{j} between times \eqn{t_1} and \eqn{t_2}, from the point of view of an individual in state \eqn{i} at time 0, is defined by the integral from \eqn{t_1} to \eqn{t_2} of the \eqn{i,j} entry of the transition probability matrix \eqn{P(t)}. As the individual entries of \eqn{P(t) = \exp(tQ)}{P(t) = exp(tQ)} are not available explicitly in terms of \eqn{t} for a general Markov model, this integral is calculated numerically, using the \code{\link{integrate}} function. This may take a long time for models with many states where \eqn{P(t)} is expensive to calculate. For a model where the individual has only one place to go from each state, and each state is visited only once, for example a progressive disease model with no recovery or death, these are equal to the mean sojourn time in each state. However, consider a three-state health-disease-death model with transitions from health to disease, health to death, and disease to death, where everybody starts healthy. In this case the mean sojourn time in the disease state will be greater than the expected length of stay in the disease state. This is because the mean sojourn time in a state is conditional on entering the state, whereas the expected total time diseased is a forecast for a healthy individual, who may die before getting the disease. The only time-inhomogeneous models handled by this function are those specified using the \code{pci} option to \code{\link{msm}}. For any other inhomogeneous models, the function assumes that covariates are constant on the forecasted interval. } \seealso{ \code{\link{sojourn.msm}}, \code{\link{pmatrix.msm}}, \code{\link{integrate}}, \code{\link{boot.msm}}. } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/pexp.Rd0000644000176000001440000000571311472706301013123 0ustar ripleyusers\name{pexp} \alias{pexp} \alias{dpexp} \alias{ppexp} \alias{qpexp} \alias{rpexp} \title{Exponential distribution with piecewise-constant rate} \description{ Density, distribution function, quantile function and random generation for a generalisation of the exponential distribution, in which the rate changes at a series of times. } \usage{ dpexp(x, rate=1, t=0, log = FALSE) ppexp(q, rate=1, t=0, lower.tail = TRUE, log.p = FALSE) qpexp(p, rate=1, t=0, lower.tail = TRUE, log.p = FALSE) rpexp(n, rate=1, t=0) } \arguments{ \item{x,q}{vector of quantiles.} \item{p}{vector of probabilities.} \item{n}{number of observations. If \code{length(n) > 1}, the length is taken to be the number required.} \item{rate}{vector of rates.} \item{t}{vector of the same length as \code{rate}, giving the times at which the rate changes. The first element of \code{t} should be 0, and \code{t} should be in increasing order.} \item{log, log.p}{logical; if TRUE, probabilities p are given as log(p).} \item{lower.tail}{logical; if TRUE (default), probabilities are P[X <= x], otherwise, P[X > x].} } \value{ \code{dpexp} gives the density, \code{ppexp} gives the distribution function, \code{qpexp} gives the quantile function, and \code{rpexp} generates random deviates. } \details{ Consider the exponential distribution with rates \eqn{r_1, \ldots, r_n}{r1,\dots, rn} changing at times \eqn{t_1, \ldots, t_n}{t1, \dots, tn}, with \eqn{t_1 = 0}{t1 = 0}. Suppose \eqn{t_k}{tk} is the maximum \eqn{t_i}{ti} such that \eqn{t_i < x}{ti < x}. The density of this distribution at \eqn{x > 0} is \eqn{f(x)} for \eqn{k = 1}, and \deqn{\prod_{i=1}^k (1 - F(t_{i} - t_{i-1}, r_i)) f(x - t_{k}, r_{k})}{\prod{i=1 \dots k} (1 - F(ti - t{i-1}, r{i-1})) f(x - tk, rk)} for k > 1. where \eqn{F()} and \eqn{f()} are the distribution and density functions of the standard exponential distribution. If \code{rate} is of length 1, this is just the standard exponential distribution. Therefore, for example, \code{dpexp(x)}, with no other arguments, is simply equivalent to \code{dexp(x)}. Only \code{rpexp} is used in the \code{msm} package, to simulate from Markov processes with piecewise-constant intensities depending on time-dependent covariates. These functions are merely provided for completion, and are not optimized for numerical stability or speed. } \seealso{ \code{\link{dexp}}, \code{\link{sim.msm}}. } \examples{ x <- seq(0.1, 50, by=0.1) rate <- c(0.1, 0.2, 0.05, 0.3) t <- c(0, 10, 20, 30) ## standard exponential distribution plot(x, dexp(x, 0.1), type="l") ## distribution with piecewise constant rate lines(x, dpexp(x, rate, t), type="l", lty=2) ## standard exponential distribution plot(x, pexp(x, 0.1), type="l") ## distribution with piecewise constant rate lines(x, ppexp(x, rate, t), type="l", lty=2) } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{distribution} msm/man/lrtest.msm.Rd0000644000176000001440000000200312011150624014233 0ustar ripleyusers\name{lrtest.msm} \alias{lrtest.msm} \title{Likelihood ratio test} \description{Likelihood ratio test between two or more fitted multi-state models} \usage{ lrtest.msm(...) } \arguments{ \item{...}{Two or more fitted multi-state models, as returned by \code{\link{msm}}, ordered by increasing numbers of parameters.} } \value{ A matrix with three columns, giving the likelihood ratio statistic, difference in degrees of freedom and the chi-squared p-value for a comparison of the first model supplied with each subsequent model. } \section{Warning}{ The comparison between models will only be valid if they are fitted to the same dataset. This may be a problem if there are missing values and R's default of 'na.action = na.omit' is used. The likelihood ratio statistic only has the indicated chi-squared distribution if the models are nested. An alternative for comparing non-nested models is Akaike's information criterion. } \seealso{\code{\link{logLik.msm}},\code{\link{msm}}} \keyword{models} msm/man/pmatrix.msm.Rd0000644000176000001440000001122211750003066014413 0ustar ripleyusers\name{pmatrix.msm} \alias{pmatrix.msm} \title{Transition probability matrix} \description{ Extract the estimated transition probability matrix from a fitted multi-state model for a given time interval, at a given set of covariate values. } \usage{ pmatrix.msm(x, t=1, t1=0, covariates="mean", ci=c("none","normal","bootstrap"), cl=0.95, B=1000, ...) } \arguments{ \item{x}{A fitted multi-state model, as returned by \code{\link{msm}}.} \item{t}{The time interval to estimate the transition probabilities for, by default one unit. } \item{t1}{The starting time of the interval. Used for models \code{x} with piecewise-constant intensities fitted using the \code{pci} option to \code{\link{msm}}. The probabilities will be computed on the interval [t1, t1+t].} \item{covariates}{ The covariate values at which to estimate the transition probabilities. This can either be:\cr the string \code{"mean"}, denoting the means of the covariates in the data (this is the default),\cr the number \code{0}, indicating that all the covariates should be set to zero,\cr or a list of values, with optional names. For example \code{list (60, 1)} where the order of the list follows the order of the covariates originally given in the model formula, or a named list, \code{list (age = 60, sex = 1)} For time-inhomogeneous models fitted using the \code{pci} option to \code{\link{msm}}, "covariates" here include only those specified using the \code{covariates} argument to \code{\link{msm}}, and exclude the artificial covariates representing the time period. For time-inhomogeneous models fitted "by hand" by using a time-dependent covariate in the \code{covariates} argument to \code{\link{msm}}, the function \code{\link{pmatrix.piecewise.msm}} should be used to to calculate transition probabilities. } \item{ci}{If \code{"normal"}, then calculate a confidence interval for the transition probabilities by simulating \code{B} random vectors from the asymptotic multivariate normal distribution implied by the maximum likelihood estimates (and covariance matrix) of the log transition intensities and covariate effects, then calculating the resulting transition probability matrix for each replicate. If \code{"bootstrap"} then calculate a confidence interval by non-parametric bootstrap refitting. This is 1-2 orders of magnitude slower than the \code{"normal"} method, but is expected to be more accurate. See \code{\link{boot.msm}} for more details of bootstrapping in \pkg{msm}. If \code{"none"} (the default) then no confidence interval is calculated.} \item{cl}{Width of the symmetric confidence interval, relative to 1.} \item{B}{Number of bootstrap replicates, or number of normal simulations from the distribution of the MLEs} \item{...}{Optional arguments to be passed to \code{\link{MatrixExp}} to control the method of computing the matrix exponential.} } \value{ The matrix of estimated transition probabilities \eqn{P(t)} in the given time. Rows correspond to "from-state" and columns to "to-state". Or if \code{ci="normal"} or \code{ci="bootstrap"}, \code{pmatrix.msm} returns a list with components \code{estimates} and \code{ci}, where \code{estimates} is the matrix of estimated transition probabilities, and \code{ci} is a list of two matrices containing the upper and lower confidence limits. } \details{ For a continuous-time homogeneous Markov process with transition intensity matrix \eqn{Q}, the probability of occupying state \eqn{s} at time \eqn{u + t} conditionally on occupying state \eqn{r} at time \eqn{u} is given by the \eqn{(r,s)} entry of the matrix \eqn{P(t) = \exp(tQ)}{P(t) = exp(tQ)}, where \eqn{\exp()}{exp()} is the matrix exponential. For non-homogeneous processes, where covariates and hence the transition intensity matrix \eqn{Q} are piecewise-constant in time, the transition probability matrix is calculated as a product of matrices over a series of intervals, as explained in \code{\link{pmatrix.piecewise.msm}}. The \code{\link{pmatrix.piecewise.msm}} function is only necessary for models fitted using a time-dependent covariate in the \code{covariates} argument to \code{\link{msm}}. For time-inhomogeneous models fitted using "pci", \code{pmatrix.msm} can be used, with arguments \code{t} and \code{t1}, to calculate transition probabilities over any time period. } \seealso{ \code{\link{qmatrix.msm}}, \code{\link{pmatrix.piecewise.msm}}, \code{\link{boot.msm}} } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}.} \keyword{models} msm/man/odds.msm.Rd0000644000176000001440000000223110616662031013663 0ustar ripleyusers\name{odds.msm} \title{Calculate tables of odds ratios for covariates on misclassification probabilities} \alias{odds.msm} \description{ Odds ratios are computed by exponentiating the estimated covariate effects on the logit-misclassification probabilities. } \usage{ odds.msm(x, odds.scale = 1, cl = 0.95) } \arguments{ \item{x}{Output from \code{\link{msm}} representing a fitted multi-state model.} \item{odds.scale}{Vector with same elements as number of covariates on misclassification probabilities. Corresponds to the increase in each covariate used to calculate its odds ratio. Defaults to all 1.} \item{cl}{Width of the symmetric confidence interval to present. Defaults to 0.95.} } \value{ A list of tables containing odds ratio estimates, one table for each covariate. Each table has three columns, containing the odds ratio, and an approximate upper 95\% and lower 95\% confidence limit respectively (assuming normality on the log scale), for each misclassification probability. } \seealso{ \code{\link{msm}}, \code{\link{hazard.msm}} } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/man/bos.Rd0000644000176000001440000000327310323151162012722 0ustar ripleyusers\name{bos} \alias{bos} \title{Bronchiolitis obliterans syndrome after lung transplants} \description{ A dataset containing histories of bronchiolitis obliterans syndrome (BOS) from lung transplant recipients. BOS is a chronic decline in lung function, often observed after lung transplantation. The condition is classified into four stages of severity: none, mild, moderate and severe. } \usage{data(bos)} \format{ A data frame containing 638 rows, grouped by patient, including histories of 204 patients. The first observation for each patient is defined to be stage 1, no BOS, at six months after transplant. Subsequent observations denote the entry times into stages 2, 3, 4, representing mild, moderate and severe BOS respectively, and stage 5, representing death. \tabular{rll}{ \code{ptnum} \tab (numeric) \tab Patient identification number \cr \code{time} \tab (numeric) \tab Months after transplant \cr \code{state} \tab (numeric) \tab BOS state entered at this time \cr }} \details{ The entry time of each patient into each stage of BOS was estimated by clinicians, based on their history of lung function measurements and acute rejection and infection episodes. BOS is only assumed to occur beyond six months after transplant. In the first six months the function of each patient's new lung stabilises. Subsequently BOS is diagnosed by comparing the lung function against the "baseline" value. } \source{ Papworth Hospital, U.K. } \references{ Heng. D. et al. (1998). Bronchiolitis Obliterans Syndrome: Incidence, Natural History, Prognosis, and Risk Factors. Journal of Heart and Lung Transplantation 17(12)1255--1263. } \keyword{datasets} msm/man/logLik.msm.Rd0000644000176000001440000000120710762750704014164 0ustar ripleyusers\name{logLik.msm} \alias{logLik.msm} \title{Extract model log-likelihood} \description{ Extract the log-likelihood and the number of parameters of a model fitted with \code{\link{msm}}. } \usage{ \method{logLik}{msm}(object, \dots) } \arguments{ \item{object}{A fitted multi-state model object, as returned by \code{\link{msm}}.} \item{...}{(unused) further arguments passed to or from other methods.} } \value{ The log-likelihood of the model represented by 'object' evaluated at the maximum likelihood estimates. } \seealso{ \code{\link{msm}} } \author{C. H. Jackson \email{chris.jackson@mrc-bsu.cam.ac.uk}} \keyword{models} msm/ChangeLog0000644000176000001440000015067712061341265012670 0ustar ripleyusers2012-12-10 Chris Jackson * tests/simple.R: Modified pmatrix.msm normal bootstrap test output to work with new seeding behaviour of rmvnorm. 2012-09-28 Chris Jackson * src/doc: Remember to copy the up-to-date manual source into src for new releases, as required by Linux distribution package builders. * DESCRIPTION: Version 1.1.3 released 2012-09-27 Chris Jackson * inst/doc/msm-manual.Rnw: Work around texi2dvi problem where non-breaking spaces appear as tildes. 2012-09-25 Chris Jackson * R/outputs.R(qematrix.msm): Bug fix for user-supplied covariate values when center=FALSE. Thanks to Vikki O'Neill for the report. 2012-09-24 Chris Jackson * man/boot.msm.Rd: Documented failure of boot.msm to handle user-defined objects that clash with built-in objects. 2012-09-21 Chris Jackson * R/msm.R: Use BFGS method for one-parameter optimisation unless method supplied explicitly, avoiding warning about unreliability of Nelder-Mead. 2012-07-31 Chris Jackson * R/pearson.R: Browser was still on for pearson.msm. Thanks to Chyi-Hung Hsu. * DESCRIPTION: Version 1.1.2 released 2012-05-28 Chris Jackson * (various files): New Student t distribution for hidden Markov model outcomes. Thanks to Darren Gillis. 2012-05-11 Chris Jackson * R/msm.R(msm.check.times): Bug fix in data consistency checks with unsorted subject IDs. Thanks to Kelly Williams-Sieg for the report. * DESCRIPTION: Version 1.1.1 released 2012-05-01 Chris Jackson * R/utils.R: Corner cases in qtnorm fixed. Thanks to Art Owen for the report. * R/boot.R: Multicore functionality removed from this release since doSMP was removed from CRAN. Will restore when a stable preferred cross-platform solution emerges. 2012-01-31 Chris Jackson * R/pearson.R: Bug fix for models where transitions are only allowed from one state. Thanks to Gavin Chan for the report. 2012-01-31 Chris Jackson * R/msm.R: If user supplies an ematrix with all misclassification probabilities zero, the non-misclassification model is fitted. Thanks to Sharareh Taghipour for the report. * R/msm.R(msm.check.model): Bug fix for error messages when model inconsistent with data. 2011-11-28 Chris Jackson * R/boot.R: boot.msm and functions which use this can now use doSMP to parallelise calculations. 2011-11-25 Chris Jackson * R/boot.R: Fix of bug which affected calculation of confidence intervals by the "normal" method when there were fixed parameters or HMMs. 2011-10-27 Chris Jackson * R/outputs.R: Bug fix: Subset function "[.msm.est" was labelling columns wrong for objects with no SE component (pmatrix.msm, pnext.msm). 2011-09-09 Chris Jackson * DESCRIPTION: Version 1.1 released 2011-07-25 Chris Jackson * R/outputs.R: New function "[.msm.est" to extract specific rows and columns of the output from, e.g., qmatrix.msm() in a more intuitive way. 2011-07-24 Chris Jackson * R/outputs.R: New function "pnext.msm" to compute a matrix of probabilities for the next state of the process. 2011-07-07 Chris Jackson * man/msm.Rd: Doc clarifies that "death" is overridden by "obstype" and "exacttimes", and "exacttimes" is overridden by "obstype". 2011-06-09 Chris Jackson * man/msm.Rd: Correct documentation for factor levels of "timeperiod". * R/outputs.R(qematrix.msm): Fix CIs for diagonal entries when first state is absorbing. * R/msm.R(msm.check.model): Refer to observation numbers, not transition numbers, in "data inconsistent with model" error message. 2011-05-26 Chris Jackson * DESCRIPTION: Version 1.0.1 released 2011-05-20 Chris Jackson * R/outputs.R(msm.fill.pci.covs): Bug fix, pmatrix.msm would break for models with non-integer time change points "pci". Thanks to Christos Argyropoulos for the report. * man/prevalence.msm.Rd: Clarify that "piecewise.times" is not needed for models fitted with "pci". Thanks to Christos Argyropoulos. * R/msm.R(msm): Warning if initcovariates is supplied but the model is not hidden Markov. Thanks to Christos Argyropoulos. 2011-05-05 Chris Jackson * R/utils.R(dtnorm): Return -Inf when log=TRUE and x outside truncation bounds. Thanks to William Leeds for the report. 2011-02-08 Chris Jackson * man/msm.Rd: Help page clarified to say that "state" is also used for the observed outcome in a HMM. Thanks to Ricardo Antunes. 2010-11-24 Chris Jackson * R/outputs.R: Line types, colours and widths can be configured in plotprog.msm, plot.survfit.msm and plot.prevalence.msm. * DESCRIPTION: Version 1.0 finally released to accompany the forthcoming paper on msm in Journal of Statistical Software. 2010-11-12 Chris Jackson * man/msm.Rd: Documentation for the return value of msm corrected to state that the "logbaseline" components of result matrices are evaluated with covariates set to zero if center=FALSE, and at their means if center=TRUE. Previously it stated that "logbaseline" was evaluated at the mean covariate values. * R/msm.R(msm), R/outputs.R(print.msm): Return the "baseline" and "sojourn" components of result matrices at covariate values of 0 if center=0. Thanks to Kenneth Gundersen for the report. 2010-11-01 Chris Jackson * R/boot.R(bootdata.trans.msm): Fix for bootstrapping when some levels of a factor do not appear in a bootstrapped dataset. Thanks to Gale Bravener for the report. 2010-10-29 Chris Jackson * R/msm.R(msm.check.times): Fixed a bug in comparing small floating point numbers to zero, and added "may be" to warning about data inconsistent with transition matrix, due to uncertainty about these comparisons. 2010-09-22 Chris Jackson * R/msm.R(msm.check.times): Added warning for multiple observations at the same time on the same person with different states, which leads to zero likelihood and "cannot be evaluated at initial values" message. 2010-05-18 Chris Jackson * DESCRIPTION: Version 0.9.7 released 2010-05-07 Chris Jackson * R/msm.R: Ematrices and ematrix.msm for models with all "fixedpars" returned correctly. 2010-05-04 Chris Jackson * R/boot.R: Bug fixes. "end" argument wasn't included in totlos.ci.msm and totlos.normci.msm, bootstrapping broke with covariates on HMM outcomes, and "fixedpars" weren't accounted for in normboot.msm. Thanks to Li Su for these reports. 2010-02-09 Chris Jackson * R/pearson.R: Fix for "NA in probability vector" error caused by floating point comparisons in empiricaldists(), which were still happening. Thanks to Wen-Wen Yang for the report. * DESCRIPTION: Version 0.9.6 released 2010-01-29 Chris Jackson * src/pijt.c(Pmat): Don't round extreme likelihood contributions to 0 and 1 for models with "exacttimes", since they are not probabilities. Fixes occasional wrong likelihood calculations. 2010-01-14 Chris Jackson * R/msm.R: The "pci" element of fitted model objects now excludes values which are outside the time range of the data. Allows pmatrix.msm to be used on such models without error. Also give a warning when any "pci" cut points equal the min/max time point in the data. Thanks to Matt Cowperthwaite. 2009-11-25 Chris Jackson * R/pearson.R: Fix for problem revealed by different handling of factors in R-2.10.0, which caused all expected values to be returned as zero. Thanks to Brian Tom for the report. * DESCRIPTION: Version 0.9.5 released. 2009-11-13 Chris Jackson * R/msm.R(msm.form.data): Bug fix for handling missing subject ID. * DESCRIPTION: Version 0.9.4 released. 2009-11-05 Chris Jackson * R/outputs.R(pmatrix.msm, pmatrix.piecewise.msm): Allow options to MatrixExp to be passed through. * R/msm.R(crudeinits.msm): Don't break with missing values. 2009-09-15 Chris Jackson * R/likderiv.msm: Bug fix: Use obstype.obs when calculating score residuals, not obstype. Also fixed misplaced for loop initialising patient derivatives to zero in src/lik.c(derivsimple_subj). Thanks to Aidan O'Keeffe for the report. 2009-08-26 Chris Jackson * R/pearson.R: Fix for "replacement has 0 rows" error - don't add covariates column to internal data when there are no covariates. * R/pearson.R: timeinterval rounded in empiricaldists to avoid "NA in probability vector" errors in R-devel arising from floating point fuzz. 2009-08-20 Chris Jackson * R/msm.R: fix of previous bug fix from 06-24 for derivatives with respect to fixed parameters. Thanks to Aidan O'Keeffe for the report. * DESCRIPTION: Version 0.9.3 released. 2009-07-27 Chris Jackson * R/msm.R(msm.form.output): Bug fix - estimates of covariate effects were being ordered wrongly in matrices outputted by msm in models with "qconstraint". Thanks to Brian Tom for the report. 2009-06-24 Chris Jackson * DESCRIPTION: Version 0.9.2 released. 2009-06-24 Chris Jackson * R/msm.R: Bug fix - don't return derivatives with respect to fixed parameters - this was causing "gradient in optim evaluated to wrong length" error for models with fixed parameters fitted using BFGS. Thanks to Isaac Dinner for the report. 2009-06-12 Chris Jackson * tests/simple.R: Removed a couple of tests which fail due to floating point fuzz on Fedora/Red Hat PPC Linux. * DESCRIPTION: Version 0.9.1 released. 2009-06-09 Chris Jackson * R/pearson.R: Covariate grouping fixed to 1 for pci models with no other covariates, as the covariate group is equivalent to the time group. * DESCRIPTION: Version 0.9 released. 2009-06-05 Chris Jackson * DESCRIPTION: Licence altered from GPLv2 to GPL v2 or later. Licence text removed from src/pijt.c. * R/msm.R(msm): Default changed to use.deriv=TRUE. * R/msm.R(msm.pci): Don't impute observations for pci models at times when there is already an observation. This fixes "times not ordered" errors when bootstrap resampling for Pearson test. 2009-04-29 Chris Jackson * R/outputs.R(factorcov2numeric.msm): Extractor functions now set unspecified covariate values in covariate lists to 0, and ignore unknown covariates. * R/outputs.R(factorcov2numeric.msm): All extractor functions can now accept covariate values as numeric contrasts as well as factor levels. * R/outputs.R(plot.survfit.msm): Call to survfit fixed for compatibility with R version 2.9.0. * R/outputs.R(pmatrix.msm): Adapted to automatically handle "pci" models with piecewise constant intensities, with new "t1" argument representing start time. New internal function "msm.fill.pci.covs" to enable time-constant covariates to be passed through this facility properly. Arguments of all calls to pmatrix.msm changed. As a result, functions which call pmatrix.msm (prevalence.msm, expected.msm, totlos.msm, plot.survfit.msm) now handle time-inhomogeneous models specified using "pci". * R/msm.R(msm.pci): Bug fix - covmeans calculated wrong in pci models with other covariates, leading to error in qmatrix.msm for covariates=0. 2009-04-29 Chris Jackson * src/lik.c: Bug fix - score residuals were being calculated wrongly for models with covariates. 2009-04-24 Chris Jackson * R/pearson.R: Fixed "second argument must be a list" bug. * R/outputs.R: Order of effects in hazard.msm and odds.msm changed to read across rows of the transition/misclassification matrix. This is for consistency with, e.g. fixedpars. 2009-04-08 Chris Jackson * man/msm.Rd: Documentation for qconstraint clarified. * R/outputs.R: Bug fix - interactions now expanded properly when calling extractor functions for models with interactions between covariates. * R/msm.R: Bug fix which affected bootstrap refitting in pearson.msm, giving "Error in `$<-.data.frame`(`*tmp*`, "pci.imp"..." * DESCRIPTION: Version 0.8.2 released. 2009-04-03 Chris Jackson * LaTeX sources for PDF manual included in src/doc to enable msm to be approved as a Debian package. 2008-07-25 Chris Jackson * R/pearson.R: Bug fix, maxtimes was producing negative censoring times. * DESCRIPTION: Version 0.8.1 released. 2008-07-23 Chris Jackson * R/msm.R: New option "pci" to msm, which automatically constructs a model with piecewise-constant transition intensities which change at the supplied times. * R/boot.R: Give an informative error in normal theory CIs when SEs not available from fitted model. 2008-07-22 Chris Jackson * src/lik.c (GetOutcomeProb): HMM now applies to censored outcomes, unless obstrue = 1. Thanks to Norm Good for the suggestion. 2008-04-15 Chris Jackson * R/msm.R: deriv.test argument to msm removed. * src/lik.c: Bug fix in liksimple/derivsimple - the P matrix was not being recalculated when the obstype changed between 1 and 2. Thanks to Peter Jepsen for uncovering this. 2008-03-31 Chris Jackson * R/outputs.R: totlos.msm now computes total length of stay for all states, not just transient states. New argument "end" added. * R/outputs.R: xlim argument added to plotprog.msm. * R/outputs.R: legend added to plot.prevalence.msm. 2008-03-28 Chris Jackson * DESCRIPTION: Version 0.8 released. 2008-03-18 Chris Jackson * R/pearson.R: New file for the Pearson-type goodness-of-fit test. Thanks to Andrew Titman for his work on this. * data/heart.txt: Data "heart" renamed to "cav". * R/simul.R: any() bugs in simmisc.msm for simulating misclassification models fixed 2008-03-11 Chris Jackson * R/outputs.R: logLik.msm degrees of freedom corrected for models with parameter constraints. * R/outputs.R: New function "plot.survfit.msm" to plot Kaplan-Meier estimate of survival probabilty compared with the fitted survival probability from a model. * R/outputs.R: Allow customisable axis titles and line widths in all plot functions. 2008-03-03 Chris Jackson * R/outputs.R: New function "plotprog.msm" to plot Kaplan-Meier estimates of time to first occurrence of each state. Added "survfit" and "Surv" imports from the "survival" package. * R/outputs.R: New likelihood ratio test function "lrtest.msm". 2008-03-03 Chris Jackson * R/outputs.R: logLik method returns the log-likelihood, not the minus log-likelihood. Thanks to Jay Rotella for the report. 2008-02-27 Chris Jackson * R/utils.R: Transformation bug fixed which caused rtnorm to hang for extreme means. Thanks to Bjrn Bornkamp. 2008-02-18 Chris Jackson * R/boot.R: Simulate normal CIs using unreplicated parameters, so that they work with the new release of mvtnorm. Thanks to Peter Jepsen for the report. 2007-12-12 Chris Jackson * R/msm.R,src/lik.c: Score residuals implemented. 2007-12-10 Chris Jackson * R/utils.R: Quantile functions: uniroot() convergence tolerance tightened to solve problems with obtaining quantiles for small arguments. Thanks to Barbara Bredner for the report. * DESCRIPTION: Version 0.7.6 released. 2007-11-21 Chris Jackson * R/simul.R: Bug fix, "cur.t not found" error. * R/simul.R: Allow covariates on misclassification probabilities in simulations 2007-11-20 Chris Jackson * R/msm.R: Don't give no-SEs warning when hessian=FALSE * R/simul.R: Handle only one observation per subject. * R/outputs.R: New internal function intervaltrans.msm to determine set of allowed transitions in an interval. * DESCRIPTION: Version 0.7.5 released. 2007-11-08 Chris Jackson * R/outputs.R(qratio.se.msm): Bug fix for factor covariates. Thanks to Peter Jepsen. 2007-11-05 Chris Jackson * R/boot.R (bootdata.trans.msm,bootdata.subject.msm), R/msm.R (msm.form.data,msm.form.covdata): Handle factor covariates properly when bootstrap refitting, by retaining the original covariates (not the numeric contrasts) in the data. Thanks to Peter Jepsen. * R/outputs.R: qmatrix.msm, ematrix.msm, sojourn.msm and qratio.msm can now be called with ci="none", returning just the matrix of estimates, with no CI. 2007-11-02 Chris Jackson * R/utils.R: MatrixExp now accepts a vector of t, in which case it only needs to calculate the eigensystem once. 2007-10-30 Chris Jackson * R/utils.R: Bug fix in ppexp. Thanks to Mike Murphy. * msm-manual: More explanation of censored states versus censored event times. 2007-10-25 Chris Jackson * src/hmm.c: New beta HMM outcome distribution. * src/lik.c: Ignore initprobs in HMMs if the true state is known at the initial observation. 2007-10-24 Chris Jackson * src/lik.c: Handle censoring properly in Viterbi algorithm. 2007-10-22 Chris Jackson * R/boot.R(bootdata.subject.msm): Bug fix, wrong covariate matrix was being read. Thanks to Peter Jepsen for the report. * msm-manual.pdf: Correction of algebraic typos in Viterbi algorithm. * src/lik.c: Account for obstrue in Viterbi algorithm. * R/outputs.R: Allow Viterbi algorithm to be used to impute censored states in data with censored states but no HMM. 2007-10-18 Chris Jackson * R/outputs.R(prevalence.msm,plot.prevalence.msm): Account for arguments supplied to prevalence.msm when doing the plot. Thanks to Peter Jepsen for the report. 2007-10-01 Chris Jackson * src/Makevars: CR endings removed to satisfy R CMD CHECK in R 2.6.0 * R/outputs.R(print.msm.est): test for CI using is.list(), since $ on an atomic object fails in R 2.7.0 instead of returning NULL. * DESCRIPTION: Version 0.7.4 released. Use standardised license string. 2007-08-15 Chris Jackson * DESCRIPTION: Version 0.7.3 released. 2007-08-14 Chris Jackson * R/boot.R: Handle obstype and obsmisc in bootstrap refitting, and handle refitting of msm models where obstype, obsmisc and subject vectors are calculated within the argument to msm. Thanks to Peter Jepsen for the report. * R/boot.R, R/outputs.R: Add bootstrap handlers (both nonparametric and normal-theory) for qmatrix.msm, ematrix.msm, sojourn.msm, qratio.msm, pmatrix.piecewise.msm, totlos.msm, prevalence.msm. 2007-07-27 Chris Jackson * src/analyticp.c: Bug fix: exponential of certain degenerate 5 state intensity matrices was not being calculated properly. Thanks to Ross Boylan for the report. * man/msm.Rd: Make clear that the initial values for constrained parameters are taken from the first of the multiple initial values supplied. Thanks to Ross Boylan. 2007-06-30 Chris Jackson * R/outputs.R(surface.msm): Bug fix: don't include auxiliary parameters in HMMs. Thanks to Michael Sweeting. 2007-06-29 Chris Jackson * R/utils.R(MatrixExp), src/pijt.c(MatrixExp): Bug fix. When there are complex eigenvalues, don't use the eigensystem method of calculating the matrix exponential. Thanks to Vronique Bouchard. 2007-06-05 Chris Jackson * R/outputs.R(expected.msm): Bug fix, wrong risk set was being calculated for user-specified "times". * R/outputs.R(observed.msm): Allow interpolation of observed states using the midpoint of an interval. * R/outputs.R(pmatrix.msm), R/boot.R: Confidence intervals for P matrix can now be calculated by simulating from multivariate normal distribution of MLEs. * R/outputs.R(plot.prevalence.msm),man/plot.prevalence.msm.Rd: new function for prevalence plots. * man/pmatrix.piecewise.msm.Rd: Example corrected to use four sets of covariates. Thanks to Qing Wang. * DESCRIPTION,NAMESPACE: Added rmvnorm import from "mvtnorm" package. 2007-05-31 Chris Jackson * DESCRIPTION: Version 0.7.2 released. 2007-05-29 Chris Jackson * R/outputs.R: Functions to calculate SEs and CIs for ematrix.msm adapted to deal with multinomial logistic regression. CIs for probabilities are calculated using delta method approximation to variance of logit p, instead of log p as previously. 2007-05-26 Chris Jackson * R/utils.R: Truncated normal random sampling algorithm improved to use the rejection method by Christian Robert. Thanks to Vivek Roy for the suggestion. 2007-05-25 Chris Jackson * R/msm.R: Constraints on intensity covariate effects that some effects are equal to other effects multiplied by -1 are now allowed. * R/msm.R: Structural zeroes are allowed for initial state occupancy probabilities. * inst/doc/msm-manual.pdf: Misclassification examples on heart data changed so that individuals' first observations are not misclassified. 2007-05-21 Chris Jackson * R/lik.c: Serious bug fix. Effects of covariates on outcome probabilities in misclassification models (categorical HMMs) are now estimated using multinomial logistic regressions, instead of (incorrectly) independent univariate logistic regressions for each probability. * R/msm.R, R/lik.c: Effects of covariates on initial state probabilities in HMMs can now be estimated through multinomial logistic regression. 2007-05-13 Chris Jackson * R/outputs.R, R/boot.R: New option "ci.boot" to prevalence.msm, a helper to calculate bootstrap confidence limits for the expected prevalences using "boot.msm". * R/msm.R, src/lik.c: New argument "obstrue" to msm, to allow some observations to be observed without error in misclassification models. 2007-05-11 Chris Jackson * R/msm.R: Return derivatives in $deriv component of the msm object after optimisation. Thanks to Ole Rummel. 2007-04-18 Chris Jackson * R/msm.R: Don't drop covariates on transition process which are missing at the last observation for a patient, because they are not used in the analysis. This has the consequences that output from prevalence.msm may be different from earlier versions (0.7 or earlier) if there are missing values in the data. Users are advised to drop missing values from their data (if statistically appropriate!) before using msm. * DESCRIPTION: Maintainer email address changed. * DESCRIPTION: Version 0.7.1 released. 2007-04-05 Chris Jackson * R/outputs.R(viterbi.msm): Bug fix for models with covariates. Thanks to Hongjie Wang. * R/outputs.R(prevalence.msm): Can now calculate expected prevalences for models with piecewise-constant intensities, in the same manner as pmatrix.piecewise.msm. 2007-04-04 Chris Jackson * R/outputs.R(prevalence.msm): Bug fix, initstates was being ignored. Thanks to Peter Jensen. * R/msm.R: Give a warning when the standard errors cannot be calculated. * R/msm.R(msm.form.houtput): Bug fix for initprobs display with only two states. 2007-03-02 Chris Jackson * R/outputs.R(print.msm, qematrix.msm): Bug fix: When center=FALSE, reported baseline intensity matrix should be labelled as with covariates set to zero, not at their means. Thanks to Ross Boylan. 2007-02-09 Chris Jackson * src/lik.c: Return likelihood of zero for individuals with only one observation in censoring and hidden models. Thanks to Jonathan Williams for discovering the bug. * data/heart.txt: Age at transplant date corrected. Thanks to Jonathan Williams. 2006-11-21 Chris Jackson * R/msm.R: Initial state occupancy probabilities can now be estimated. See new argument "est.initprobs" to msm. * DESCRIPTION: Version 0.7 released. 2006-11-20 Chris Jackson * R/simul.R(sim.msm): Transpose error in bug fix from 0.6.4 corrected. * R/outputs.R: Values of factor covariates are now supplied to extractor functions in a sensible way, at last. Reordering bug fixed with named covariate lists. 2006-11-19 Chris Jackson * R/boot.R: New file. Implements bootstrap resampling for fitted msm models. * R/outputs.R: Bootstrap confidence intervals available for pmatrix.msm and totlos.msm. * R/outputs.R: pmatrix.msm now defaults to one time unit, instead of forcing time unit to be explicitly given. * R/outputs.R: observed.msm function rewritten. Fixes bug in calculating observed prevalence for state at maximum observed time, reported by Jeremy Penn. It is also now much faster. * R/outputs.R: prevalence.msm is also adapted sensibly to handle data where not all individuals start at a common time. 2006-09-29 Chris Jackson * man/deltamethod.Rd: Example fixed to use correct covariance matrix. Thanks to Andreas Beyerlein. 2006-09-21 Chris Jackson * src/Makevars: PKG_LIBS fix to pass R CMD CHECK in R 2.4.0 * DESCRIPTION: Version 0.6.4 released. 2006-09-12 Chris Jackson * R/simul.R(sim.msm) Bug fix: multiply covariates by baseline intensities in the correct order. Also convert vector beta to matrix. Thanks to Stephan Lenz for the report. 2006-09-08 Chris Jackson * R/utils.R(rtnorm) Bug fix: use the correct components of parameters which are vectors. Thanks to Jean-Baptiste Denis for the report. 2006-07-16 Chris Jackson * Rd/msm.Rd, inst/doc/msm-manual.pdf: Documentation correction - the initial values of the qmatrix are with covariates at their means in the data, not with the covariates at zero. This bug has existed since version 0.5. 2006-07-16 Chris Jackson * R/msm.R: Row and column names of crudeinits output retained from qmatrix input. 2006-06-29 Chris Jackson * Definition of initprobs corrected on manual p31. 2006-06-28 Chris Jackson * References reinstated in the PDF manual. * DESCRIPTION: Version 0.6.3 released. 2006-06-23 Chris Jackson * DESCRIPTION: Version 0.6.2 released. 2006-06-21 Chris Jackson * msm.obs.to.fromto,msm.check.times: Support character subject variables. Thanks to Danstan Bagenda for the report. 2006-06-21 Chris Jackson * Analytically-calculated transition probability matrices implemented for selected 3, 4 and 5 state models. These are calculated in new file src/analyticp.c. New option "analyticp" in msm() to revert to the old matrix exponential method. Update to msm-manual.pdf describing this method. 2006-06-20 Chris Jackson * R/simul.R(getobs.msm): Bug fix - Keep only one observation in the absorbing state when absorbing state is not the highest state. 2006-05-29 Chris Jackson * man/logLik.Rd: help page fixed to explain that this returns the minus log likelihood. Thanks to Ole Rummel. * msm.R (likderiv.msm): bug fix - transformation of the derivatives when all parameters are fixed was returning all NAs. 2006-03-26 Chris Jackson * lik.c(Viterbi): Bug fix - don't ignore initprobs. Thanks to Melanie Wall for reporting this. * DESCRIPTION: Version 0.6.1 released. 2006-03-15 Chris Jackson * NAMESPACE: Import persp, plot and contour in from graphics. * msm.R (msm.check.times): Bug fix for factor subjects with empty levels. Thanks to Jacques Gautrais. 2006-01-04 Chris Jackson * msm.R (msm.form.data): use match(, unique()) to convert subject to ordinal, not factor. Also do msm.check.times after dropping missing data. Plus fix for missing obstime. 2005-11-25 Chris Jackson * DESCRIPTION: Version 0.6 released. 2005-11-17 Chris Jackson * R/outputs.R: New function surface.msm for surface plots of likelihoods. 2005-11-16 Chris Jackson * lik.c,pijt.c, etc.: Analytic derivatives of the likelihood implemented for all models, apart from hidden Markov models or models with censoring. New argument "use.deriv" to tell msm to use these where appropriate. Thanks to Andrew Titman for the debugging help. * The Dennis and Schnabel algorithm in the R function "nlm" can now also be used to maximise the likelihood, as an alternative to the algorithms in "optim". 2005-11-11 Chris Jackson * msm-manual.pdf: definition of initial state probability f corrected in hidden likelihood, equation 13. Thanks to Andrew Titman. 2005-11-08 Chris Jackson * man/deltamethod.Rd: Documentation of deltamethod clarified to explain how to use user-defined variables within the formula. 2005-10-11 Chris Jackson * Negative binomial hidden Markov model output distribution added. * DESCRIPTION: Version 0.5.2 released. 2005-10-10 Chris Jackson * lik.c(Viterbi): Bug fix, wasn't handling Markov chains with progressive and regressive states properly. Thanks to Rochelle Watkins. * msm.R(msm.form.covdata): further fix for missing data. 2005-10-1 Chris Jackson * msm.form.qmodel: Bug fix with gen.inits==TRUE and censoring. Thanks to Jacques Gautrais. 2005-07-27 Chris Jackson * sim.msm: collapse.covs fixed to handle covariate matrices with one observation time. * msm.R(msm.form.covdata): bug fix for covariates in global environment, not a data frame. This bug produced the error "Error in 1:n : NA/NaN argument". 2005-05-27 Chris Jackson * sim.msm: sample replaced by resample as in ?sample, to fix simulations with small models. * msm.R: Fix for one-parameter models. (drop=FALSE in subsetting covmat) 2005-05-25 Chris Jackson * utils.R: New functions (dpqr)pexp for the exponential distribution with piecewise-constant rate. * utils.R: Bug fix: arguments lower.tail and log.p implemented for truncated normal and measurement error distributions. * DESCRIPTION: Version 0.5.1 released. 2005-05-23 Chris Jackson * tests/*: Tests are now fully automated. Outputs are compared against known results using stopifnot(). * outputs.R(hazard.msm, odds.msm) Names "L95", "U95" changed to "L","U" for generality. 2005-05-20 Chris Jackson * msm.R: Data reorganised so that covariates are stored in a matrix throughout. These are available from the model output as cov for one per observation time, and covmat for one per time difference. This fixes a bug which prevented covariates with names such as "state", "time", "subject", among others, from being used. 2005-05-16 Chris Jackson * simul.R(sim.msm) Re-written. Fixes a bug in simulating from models with time-dependent covariates, where not every covariate change was accounted for. Uses new function rpexp to simulate from the exponential distribution with piecewise-constant rate. Thanks to Mike Sweeting for the bug report. * simul.R(sim.msm) Simulations now contain a censoring time at maxtime, instead of the future absorption time. * simul.R(getobs.msm) Re-written, replacing ugly loops with vectorised code. 2005-04-11 Chris Jackson * man/simul.Rd: clarified that qmatrix is with covariates set to zero. Thanks to Anne Presanis. 2005-04-11 Chris Jackson * outputs.R(pmatrix.piecewise.msm): Bug fix for times of length 1. Thanks to Anne Presanis. 2005-03-09 Chris Jackson * pijt.c(Pmat): Don't recalculate pii within j loop. 2005-03-08 Chris Jackson * pijt.c: New function Eigen. MatrixExp merged into one function. 2005-03-07 Chris Jackson * msm.R(msm): Argument "hessian" added to msm. Covariance matrix is set to NULL instead of a string when SEs not available. * msm.R(msm): Confidence limits of fixed parameters set to NA, not zero width. 2005-03-06 Chris Jackson * DESCRIPTION: Version 0.5 released. This is a major re-write, so instead of a detailed change log, the NEWS entry is reproduced below. Version 0.5 (2005-03-06) ----------- * Major update. Much of the internal R and C code has been re-written. * General continuous-time hidden Markov models can now be fitted with msm, as well as misclassification models. Allowed response distributions conditionally on the hidden state include categorical, normal, Poisson, exponential and others. See the new "hmodel" argument. Misclassification models can either be fitted in the old style using an ematrix, or using a general HMM with a categorical response distribution. Covariates can be fitted to many of the new hidden response processes via generalized regressions. See "hcovariates", "hcovinits" arguments. * Per-observation observation schemes, generalising the "exacttimes" and "death" concepts. An optional new variable in the data can specify whether each observation is a snapshot of the process, an exactly-observed transition time, or a death state. Observations are allowed to be at identical times, for example, a snapshot followed instantly by an exact transition time. * Various syntax changes for cleaner moder specification. - Instead of 0/1 indicators, qmatrix and ematrix should contain the initial values for the transition intensity / misclassification matrix. These matrices can be named with names for the states of the Markov chain. - The inits argument is abolished. Initial values are estimated automatically if the new argument to msm "gen.inits = TRUE" is supplied. This uses the initial values calculated by crudeinits.msm. - misc no longer needs to be specified if an ematrix is supplied. - fixedpars=TRUE fixes all parameters, or specific parameters can be fixed as before. - crudeinits.msm takes a state ~ time formula instead of two separate state, time arguments, for consistency with the msm function. - Initial values for covariate effects on transition rates / misclassification probabilities are assumed to be zero unless otherwise specified by the new "covinits" / "misccovinits" argument. * Support for 'from-to' style data has been withdrawn. Storing data in this format is inadvisable as it destroys the longitudinal nature of the data. * Speed improvements. The algorithm for calculating the likelihood for non-hidden multi-state models has changed so that the matrix exponential of the Q matrix is only calculated once for each time difference / covariate combination. Therefore, users should see speed improvements for data where the same from-state, to-state, time difference, covariates combination appears many times. * Confidence intervals are now presented instead of standard errors for uncertainty in parameter estimates. * New method of calculating matrix exponentials when the eigenvector matrix is not invertible. It now uses the more robust method of Pade approximants with scaling and squaring, instead of power series. Faster LAPACK routines are now used for matrix inversion. * covmatch argument to msm has been abolished. To take a time-dependent covariate value from the end of the relevant transition instead of the default start, users are expected to manipulate their data accordingly before calling msm, shifting the positions of the covariate back by one within each subject. * Syntax changes for simmulti.msm. Bug fixes --------- * The likelihood is now calculated correctly for individuals with censored intermediate states, as well as censored initial and final states. Thanks to Michael Sweeting for reporting this. * hazard.scale and odds.scale were interpreted wrongly in hazard.msm and odds.msm respectively. * time-dependent covariate values now taken from the start instead of end of the transition under hidden Markov models. 2005-01-28 Chris Jackson * src/lik.c (GetCensoredPObsTrue): Censored outcomes are now assumed to be not misclassified. * msm.R(msm.form.censor): Bug fix - transient states were detected incorrectly. * src/pijt.c: Bug fix. P matrix calculation for misclassification models was ignoring exacttimes. * src/lik.c: Bug fix. Ignore death when exacttimes = TRUE. * DESCRIPTION: Version 0.4.1 released. 2005-01-07 Chris Jackson * DESCRIPTION: Version 0.4 released. 2005-01-06 Chris Jackson * msm/R/msm.process.covs: Bug fix - covariates were not being centered. Thanks to Andrew Titman. 2004-12-29 Chris Jackson Support added for censored observations. * src/lik.c: Bug fix. Don't ignore exacttimes for misclassification models. Fixes in documentation. Thanks to Ross Boylan. 2004-09-18 Chris Jackson * man: Rd syntax errors fixed to pass R CMD CHECK under 2.0.0 * * msm-manual: Reference to the PDF manual for msm made more prominent. * DESCRIPTION: Version 0.3.3 released. 2004-06-23 Chris Jackson * msm.R(msm.process.covs): Bug fix, constraints were not being calculated properly when some covariates were constrained and some were not. Thanks to Mike Sweeting. 2004-06-01 Chris Jackson * msm-manual: Correction - heartmiscsex.msm is actually run using default Nelder-Mead optimization, not BFGS. 2004-05-13 Chris Jackson * R/outputs.R: plot.msm now plots survival curves in different colours as well as different line types. 2004-05-11 Chris Jackson * R/simul.R: simmulti.msm now returns a data frame, as it should do. 2004-04-23 Chris Jackson * New argument "start" in simmulti.msm to give the starting state for each individual. Thanks to Stephan Lenz for the suggestion. 2004-03-25 Chris Jackson * NEWS file moved to inst directory, so that it ends up in the root directory of binary installs. Leave ChangeLog in the source package. * DESCRIPTION: Version 0.3.2 released. 2004-03-24 Chris Jackson * R/outputs.R(print.msm): Bug fix - only say "covariates set to their means" in the output if there actually are any covariates. * msm-manual.pdf: Hidden Markov model theory moved to straight after general model theory, general cleanups. 2004-03-23 Chris Jackson * msm-manual.pdf: R code examples rewritten using Sweave. Examples run again with different death assumption, most estimates are negligibly different. Misclassification model examples corrected to include death. Example of plot.msm added. This is not distributed as a vignette, as the msm model examples take a long time to fit. 2004-03-22 Chris Jackson * R/simul.R(simmulti.msm, getobs.msm): tunit argument abolished and death times assumed to be known exactly. * src/lik.c(fillparvec): Bug fix. Bounds checking on vector of indices of fixed parameters. Thanks to Ross Boylan. 2004-03-21 Chris Jackson * R/msm.R, src/lik.c: tunit argument is now abolished (with warning given). Death states are assumed to have exact entry times, not within one day. This is cleaner and more logical, as in longitudinal studies all observations are usually accurate to one basic time unit, not just deaths. * R/msm.R, src/lik.c: More than one death state is now supported. A death state has exact entry time, with an unknown transient state at the previous instant. Thanks to Jean-Luc Bulliard for suggesting this. * R/msm.R(msm.check.times): Just give a warning if a subject only has one observation, no need to die. * R/msm.R(lik.msm): Bug fix. set diagonal to 0 when calculating number of misclassified states nms, in case user has given non zero diagonal entries in ematrix. * (various) Changes made so that R CMD CHECK passes with R 1.9.0 alpha: codoc mismatches and PACKAGE argument in .C() 2003-10-14 Chris Jackson * src/pijt.c(MatrixExpSeries): Bug fix. Don't overwrite the matrix A, as it is needed after the function exits. This had led to wrong results when exacttimes = TRUE and the intensity matrix had repeated eigenvalues. * src/lik.c(liksimple, liksimple_fromto, UpdateLik): Don't ignore death argument when exacttimes = TRUE. * R/msm.R(msm.check.times): Use table instead of tapply to count the number of observations per subject. Fixes further problems with running out of memory. * DESCRIPTION: Version 0.3.1 released. 2003-09-29 Chris Jackson * R/outputs.R: Debugging print statements removed from pmatrix.piecewise.msm * msm-manual.pdf: Version number added. * DESCRIPTION: Version 0.3 released. 2003-09-26 Chris Jackson * src/lik.c, src/pijt.c: Allocate memory using S_alloc, not Calloc. Solves the problem of running out of memory for large datasets. * R/outputs.R(observed.msm): Fixed a bug with looping over a factor patient ID, which caused prevalence.msm to fail. 2003-09-25 Chris Jackson * R/outputs.R(print.msm) Don't draw ASCII underlines under "Multi-state Markov models" banner - looks ugly in proportional font. * R/msm.R: nmiscs model attribute (number of misclassification probabilities) changed to nmisc for compatibility with C code. * src/lik.c(liksimple, liksimple_fromto): Bug fixed in the likelhood calculation for non-misclassified reversible models with death time known within one day. The error assumed the unobserved states on the day before death could only be states greater or equal than the previously observed state. This is not true for reversible models. * man/summary.msm.Rd: usage and argument lists made consistent, satisfying new R CMD CHECK. 2003-09-24 Chris Jackson * R/msm.R, R/outputs.R, src/lik.c: A new argument "qconstraint" to msm now allow equality constraints between baseline transition intensities. A similar argument "econstraint" allows equality constraints between misclassification probabilities. Thanks to Mike Sweeting and Ross Boylan for suggesting this. 2003-09-23 Chris Jackson * src/pijt.c(pijt): Bug fixed in the likelihood calculation for exact transition times with reversible models. The error assumed Prr(t) was always equal to exp(-qrr t), when this is only satisfied for a state r which is only visited once. 2003-06-30 Chris Jackson * R/outputs.R(qematrix.msm): Didn't work when the baseline rates or probabilities were fixed to zero, bug fixed (now uses x$model$qvector to test whether a transition is allowed, not x$Qmatrices$logbaseline). * R/outputs.R: New function - pmatrix.piecewise.msm, for calculating P-matrices for processes with non-homogeneous but piecewise-constant intensities. Thanks to Mike Sweeting for suggesting this. * DESCRIPTION: Version 0.2.2 released 2003-06-25 Chris Jackson * R/msm.R (msm.check.model): Bug fix - was reporting the wrong subject numbers when there were disallowed transitions in the data. Thanks to Stephan Lenz for spotting this. 2003-06-20 Chris Jackson * R/outputs.R: Covariates argument is now checked that it is a list, to avoid ugly warnings in R 1.7.0 2003-06-16 Chris Jackson * R/msm.R (msm.form.output): Died when only one parameter in the model, fixed by coercing covmat to matrix. 2003-06-03 Chris Jackson * inst/doc/msm-manual.pdf: Edits to manual, e.g. correction of covariates formulae to include baseline intensity, lots of typos corrected. * DESCRIPTION: Version 0.2.1 released 2003-04-29 Chris Jackson * R/simul.R: Bug fix in simmulti.msm: didn't work for one covariate. Thanks to Mike Sweeting for spotting this. * R/msm.R: Subject identification variable is now allowed to be factor or character. Thanks to Pablo Emilio Verde for the suggestion. * R/msm.R: msm.check.times also checks whether all the observations on a subject are adjacent in the data set. 2003-03-20 Chris Jackson * R/R: Bug fix in msm.check.times. Thanks to Pablo Emilio Verde for helping to find this. 2003-02-20 Chris Jackson * R/simul.R: Bug fix in getobs.msm: exact death times were ignored. (obstimes[i] replaced by sim$times[j+1]). 2003-01-05 Chris Jackson * DESCRIPTION: Version 0.2 released. * inst/doc/msm-manual.pdf: PDF manual completed. 2003-01-03 Chris Jackson * man: Heart transplant data added as an example data set * man: Aesthetic cleanups of all help pages * R/msm.R: New function crudeinits.msm to estimate a set of initial values for transition rates by assuming data represent the only transition times. * R/msm.R: New function statetable.msm to calculate frequencies of successive state pairs in data. * R/outputs.R: Methodology changed for prevalencemisc.msm to make it more similar to prevalence.msm, avoiding confusion. Observed counts now common to both, and separated out into a new function observed.msm. Then prevalencemisc.msm (and the internal C onestep) was removed and prevalence.msm was made general to both misclassification and non-misclassification models. 2002-12-18 Chris Jackson * src/lik.c: Bugfix. nms changed to nst in likelihood-calculating functions. Fixes failure to calculate the likelihood where some states where some states are observed without error, but are not death states (Thanks to Martyn Plummer). * R/simul.R: Bugfix in getobs.msm, which led to the entrance to not being observed for models with absorbing states. 2002-12-09 Chris Jackson * R/outputs.R: new function odds.msm to calculate odds ratios for misclassification probabilities. * R/outputs.R: new function ematrix.msm. Calls new internal functions, including qematrix.msm. 2002-12-03 Chris Jackson * R/outputs.R: new function qratio.msm for estimating ratios of intensities and (via new function qratio.se.msm) their standard errors. Documentation in man/qratio.msm.Rd. 2002-12-02 Chris Jackson * R/outputs.R: new internal function qmatrix.diagse.msm * R/msm.R Null components of msm objects removed, e.g. misclassification parameters for non-misclassification models. 2002-11-27 Chris Jackson * R: File msm.R split into msm.R, outputs.R and utils.R. * R/msm.R. New functions absorbing.msm and transient.msm which give the indices of the absorbing or transient states of the model. * R/msm.R. (plot.msm) Now accepts a "covariates" argument for covariates at which to evaluate the survival probabilities. * R/msm.R. Functions which operate on msm objects now have the msm object argument named "x", instead of "msm", for consistency. * man/qmatrix.msm.Rd, man/pmatrix.msm.Rd, man/sojourn.msm.Rd. Updated documentation. * R/msm.R (msm). The contents of msm objects has been reorganised. The first component of Qmatrices is now called "logbaseline" and gives the estimates of the log intensites as returned from the optimisation. Components "qcenter" and "ecenter" are removed, as they were named confusingly. The component 'Pmatrix' is also removed, as it is obsoleted by the function 'pmatrix.msm'. New component 'foundse' is a logical indicating whether the Hessian is positive definite, i.e. whether standard errors are available. * R/msm.R (sojourn.msm) Function rewritten to allow a given set of covariate values, using the new qmatrix.msm. Now takes a fitted msm model as its argument, and the component "mean" in the return is changed to "estimate". * R/msm.R (qmatrix.msm). New function to compute transition intensity matrix at given covariate values. * R/msm.R (pmatrix.msm). New function to compute transition probability matrix at given covariate values. * R/simul.R (simmulti.msm): Check for ordered patient IDs, and sort input data if not ordered. Also check for duplicated observation times and remove them. Default for 'death' argument changed to FALSE for consistency with msm(). Give column names to the simulated data. 2002-11-13 Chris Jackson * R/msm.R: New function msm.check.qmatrix to test for consistency of Markov chain intensity matrices. * R/msm.R, man/totlos.Rd: New function totlos.msm to estimate total length of stay in a state, with documentation. * src/lik.c, src/pijt.c: Unused and uninitialised variables fixed so the library builds cleanly with -Wall. 2002-11-08 Chris Jackson * src/lik.c: Debugging print statements removed from onestep * msm_0.1.tar.gz: First release msm/tests/0000755000176000001440000000000012061401532012232 5ustar ripleyusersmsm/tests/local.R0000744000176000001440000000003110720536274013456 0ustar ripleyusersdeveloper.local <- FALSE msm/tests/misc.R0000644000176000001440000003212112006215472013314 0ustar ripleyusers### TESTS OF MISCLASSIFICATION MODELS ### SPECIFIED USING THE OLD ematrix SYNTAX source("local.R") library(msm) # library(msm, lib.loc="../../lib/sun/0.7.5") data(cav) oneway4.q <- rbind(c(0, 0.148, 0, 0.0171), c(0, 0, 0.202, 0.081), c(0, 0, 0, 0.126), c(0, 0, 0, 0)) rownames(oneway4.q) <- colnames(oneway4.q) <- c("Well","Mild","Severe","Death") ematrix <- rbind(c(0, 0.1, 0, 0),c(0.1, 0, 0.1, 0),c(0, 0.1, 0, 0),c(0, 0, 0, 0)) ## Plain misc model with no covs misc.msm <- msm(state ~ years, subject = PTNUM, data = cav, qmatrix = oneway4.q, ematrix=ematrix, death = 4, fixedpars=TRUE) misc.msm stopifnot(isTRUE(all.equal(4296.9155995778, misc.msm$minus2loglik, tol=1e-06))) if (developer.local) { system.time(misc.msm <- msm(state ~ years, subject = PTNUM, data = cav, qmatrix = oneway4.q, ematrix=ematrix, death = 4, # pci=5, # fixedpars=1:5, control = list(trace=1, REPORT=1), method="BFGS")) stopifnot(isTRUE(all.equal(3951.82919869367, misc.msm$minus2loglik, tol=1e-06))) if(interactive()) save(misc.msm, file="~/msm/devel/models/misc.msm.rda") } ## Covs on transition rates misccov.msm <- msm(state ~ years, subject = PTNUM, data = cav, qmatrix = oneway4.q, ematrix=ematrix, death = 4, fixedpars = TRUE, control = list(trace=1, REPORT=1), method="BFGS", covariates = ~ sex, covinits=list(sex=rep(0.1, 5))) stopifnot(isTRUE(all.equal(4299.35653620144, misccov.msm$minus2loglik, tol=1e-06))) ## Covs on misc probs, old way. misccov.msm <- msm(state ~ years, subject = PTNUM, data = cav, qmatrix = oneway4.q, ematrix=ematrix, death = 4, fixedpars=TRUE, misccovariates = ~dage + sex, misccovinits = list(dage=c(0.01,0.02,0.03,0.04), sex=c(-0.013,-0.014,-0.015,-0.016)), control = list(trace=1, REPORT=1), method="BFGS") stopifnot(isTRUE(all.equal(4304.90609473048, misccov.msm$minus2loglik, tol=1e-06))) if (developer.local) { system.time(misccov.msm <- msm(state ~ years, subject = PTNUM, data = cav, qmatrix = oneway4.q, ematrix=ematrix, death = 4, misccovariates = ~dage + sex, # fixedpars=c(1:5,11), control = list(trace=1, REPORT=1), method="BFGS")) ## stopifnot(isTRUE(all.equal(3929.39438312539, misccov.msm$minus2loglik, tol=1e-06))) ## 0.7.1 and earlier stopifnot(isTRUE(all.equal(3929.59504496140, misccov.msm$minus2loglik, tol=1e-06))) if(interactive()) save(misccov.msm, file="~/msm/devel/models/misccov.msm.rda") system.time(misccovboth.msm <- msm(state ~ years, subject = PTNUM, data = cav, qmatrix = oneway4.q, ematrix=ematrix, death = 4, fixedpars=FALSE, control = list(trace=1, REPORT=1), method="BFGS", covariates = ~ sex, covinits=list(sex=rep(0.1, 5)), misccovariates = ~dage + sex, misccovinits = list(dage=c(0.01,0.02,0.03,0.04), sex=c(-0.013,-0.014,-0.015,-0.016)) )) ## stopifnot(isTRUE(all.equal(3921.40046811911, misccovboth.msm$minus2loglik, tol=1e-06))) # 0.7.1 and earlier stopifnot(isTRUE(all.equal(3921.42240883417, misccovboth.msm$minus2loglik, tol=1e-06))) if(interactive()) save(misccovboth.msm, file="~/msm/devel/models/misccovboth.msm.rda") if(interactive()) load("~/msm/devel/models/misccovboth.msm.rda") print(misccovboth.msm) ########## OUTPUT FUNCTIONS ################### if(interactive()) load("~/msm/devel/models/misc.msm.rda") if(interactive()) load("~/msm/devel/models/misccov.msm.rda") if(interactive()) load("~/msm/devel/models/misccovboth.msm.rda") e <- ematrix.msm(misc.msm) stopifnot(isTRUE(all.equal(0.00766164690017842, e$estimates[1,2], tol=1e-06))) stopifnot(isTRUE(all.equal(0.00334014173130528, e$SE[1,2], tol=1e-06))) stopifnot(isTRUE(all.equal(0.00325308687951399, e$L[1,2], tol=1e-06))) stopifnot(isTRUE(all.equal(0.0179371415700995, e$U[1,2], tol=1e-06))) print(ematrix.msm(misc.msm), digits=2) print(viterbi.msm(misc.msm)[1:50,]) vit <- viterbi.msm(misc.msm)[viterbi.msm(misc.msm)$subject==100063,] stopifnot(isTRUE(all.equal(c(1, 1, 1, 1, 2, 2, 2, 2, 2, 2), vit$fitted, tol=1e-06))) ### TEST VITERBI ON SUBSET WITH FIXEDPARS BUG REPORT pt <- 100046 for (pt in unique(cav$PTNUM)){ subs <- cav[cav$PTNUM==pt,] x <- viterbi.msm(misc.msm); x <- x[x$subject==pt,] miscfix.msm <- msm(state ~ years, subject = PTNUM, data = subs, qmatrix = qmatrix.msm(misc.msm)$estimates, ematrix=ematrix.msm(misc.msm)$estimates, death = 4, fixedpars=TRUE) y <- viterbi.msm(miscfix.msm) print(pt) stopifnot(all(x$fitted==y$fitted)) } odds <- odds.msm(misccov.msm) # stopifnot(isTRUE(all.equal(0.924920277547759, odds$dage[1,2], tol=1e-06))) # stopifnot(isTRUE(all.equal(0.9350691888108385, odds$dage[2,2], tol=1e-06))) # stopifnot(isTRUE(all.equal(24.76686951404301, odds$sex[1,3], tol=1e-04))) # stopifnot(isTRUE(all.equal(30.90173037227264, odds$sex[3,3], tol=1e-04))) stopifnot(isTRUE(all.equal(0.92024511282455, odds$dage[1,2], tol=1e-03))) stopifnot(isTRUE(all.equal(0.937622692212605, odds$dage[2,2], tol=1e-03))) stopifnot(isTRUE(all.equal(23.6267954503319, odds$sex[1,3], tol=1e-01))) stopifnot(isTRUE(all.equal(30.7225710461079, odds$sex[3,3], tol=1e-01))) e <- ematrix.msm(misccov.msm) stopifnot(isTRUE(all.equal(0.00271289377320006, e$estimates[1,2], tol=1e-02))) stopifnot(isTRUE(all.equal(0.0351301610655661, e$SE[1,2], tol=1e-02))) e <- ematrix.msm(misccov.msm, covariates=0) stopifnot(isTRUE(all.equal(0.00523189426375198, e$estimates[1,2], tol=1e-02))) stopifnot(isTRUE(all.equal(0.00717339683841909, e$SE[1,2], tol=1e-02))) stopifnot(isTRUE(all.equal(0.000182524613416697, e$L[1,2], tol=1e-02))) stopifnot(isTRUE(all.equal(0.0389554284408482, e$U[1,2], tol=1e-02))) e <- ematrix.msm(misccov.msm, covariates=list(dage=50, sex=0)) stopifnot(isTRUE(all.equal(0.0126402839581582, e$estimates[1,2], tol=1e-02))) stopifnot(isTRUE(all.equal(0.0127991364840901, e$SE[1,2], tol=1e-02))) stopifnot(isTRUE(all.equal(0.000364352259872661, e$L[1,2], tol=1e-02))) stopifnot(isTRUE(all.equal(0.0198983271598344, e$U[1,2], tol=1e-02))) ### Non misclassification-specific output functions q <- qmatrix.msm(misccov.msm) stopifnot(isTRUE(all.equal(0.234871828782083, q$estimates[2,3], tol=1e-02))) stopifnot(isTRUE(all.equal(0.0388940534715571, q$SE[2,3], tol=1e-02))) stopifnot(isTRUE(all.equal(0.169775324070530, q$L[2,3], tol=1e-02))) stopifnot(isTRUE(all.equal(0.324928114597637, q$U[2,3], tol=1e-02))) soj <- sojourn.msm(misccov.msm) stopifnot(isTRUE(all.equal(c(6.83075273024829, 3.81966398452026, 3.29901891409971, 0.499352190044205, 0.41662507532632, 0.395976119914232, 5.91892340913934, 3.08447614101601, 2.60745249850692, 7.88305231146405, 4.73008455492069, 4.17400731243225 ), as.numeric(unlist(soj)), tol=1e-02))) p <- pmatrix.msm(misccov.msm, 10) stopifnot(isTRUE(all.equal(0.122616549949547, p[1,3], tol=1e-03))) q <- qratio.msm(misccov.msm, c(1,2), c(2,3), cl=0.99) stopifnot(isTRUE(all.equal(c(0.449639898189716, 0.0948158687296418, 0.261198374155947, 0.774032528714554), as.numeric(q), tol=1e-02))) p <- prevalence.msm(misccov.msm) stopifnot(isTRUE(all.equal(158, p$Observed[5,4], tol=1e-03))) stopifnot(isTRUE(all.equal(134.668020428293, p$Expected[5,4], tol=1e-03))) stopifnot(isTRUE(all.equal(31.43564356435644, p$"Observed percentages"[4,4], tol=1e-03))) stopifnot(isTRUE(all.equal(27.5796638007428, p$"Expected percentages"[4,4], tol=1e-03))) summ <- summary.msm(misccov.msm) p <- summ$prevalences stopifnot(isTRUE(all.equal(158, p$Observed[5,4], tol=1e-03))) stopifnot(isTRUE(all.equal(134.668020428293, p$Expected[5,4], tol=1e-03))) stopifnot(isTRUE(all.equal(31.43564356435644, p$"Observed percentages"[4,4], tol=1e-03))) stopifnot(isTRUE(all.equal(27.5796638007428, p$"Expected percentages"[4,4], tol=1e-03))) if (interactive()) plot.msm(misccov.msm) cf <- coef.msm(misccovboth.msm) stopifnot(isTRUE(all.equal(-0.535346454908361, cf$Qmatrices$sex[1,2], tol=1e-04))) stopifnot(isTRUE(all.equal(-6.71038434136682, cf$Ematrices$sex[1,2], tol=1e-04))) stopifnot(isTRUE(all.equal(c(1,2,3), as.numeric(transient.msm(misccov.msm)), tol=1e-03))) stopifnot(isTRUE(all.equal(4, as.numeric(absorbing.msm(misccov.msm)), tol=1e-03))) tot <- totlos.msm(misccov.msm) stopifnot(isTRUE(all.equal(c(6.83075273082287, 2.75543070960308, 2.13503613252349), as.numeric(tot), tol=1e-03))) stopifnot(isTRUE(all.equal(-1964.79752248070, as.numeric(logLik.msm(misccov.msm)), tol=1e-03))) ########## OTHER FEATURES ################### ## Baseline intens constraints misc.msm <- msm(state ~ years, subject = PTNUM, data = cav, qmatrix = oneway4.q, ematrix=ematrix, death = 4, fixedpars=4:7, qconstraint = c(1, 2, 1, 2, 3), control = list(trace=1, REPORT=1), method="BFGS") stopifnot(isTRUE(all.equal(4209.65938095232, misc.msm$minus2loglik, tol=1e-06))) q <- qmatrix.msm(misc.msm) stopifnot(isTRUE(all.equal(-0.145819054714827, q$estimates[1,1], tol=1e-06))) ## Baseline misc constraints ematrix2 <- rbind(c(0, 0.1, 0, 0),c(0.1, 0, 0.11, 0),c(0, 0.11, 0, 0),c(0, 0, 0, 0)) misc.msm <- msm(state ~ years, subject = PTNUM, data = cav, qmatrix = oneway4.q, ematrix=ematrix2, death = 4, fixedpars=1:5, econstraint = c(1, 1, 2, 2), control = list(trace=1, REPORT=1), method="BFGS") stopifnot(isTRUE(all.equal(4161.05767600322, misc.msm$minus2loglik, tol=1e-06))) e <- ematrix.msm(misc.msm) stopifnot(isTRUE(all.equal(0.970221499780077, e$estimates[1,1], tol=1e-06))) ## intens covariate constraints ## Give replicated inits for replicated cov effs, as that's consistent with constraints on q, e and h. misc.msm <- msm(state ~ years, subject = PTNUM, data = cav, fixedpars=c(1:5, 9:12), qmatrix = oneway4.q, ematrix=ematrix, death = 4, control = list(trace=1, REPORT=1), method="BFGS", covariates = ~ sex, covinits=list(sex=c(0, 0, 0.1, 0, 0)), constraint = list(sex = c(1, 2, 1, 2, 3)) ) stopifnot(isTRUE(all.equal(4277.77801412343, misc.msm$minus2loglik, tol=1e-06))) q <- qmatrix.msm(misc.msm, covariates=0) stopifnot(isTRUE(all.equal(-0.17619654476216, q$estimates[1,1], tol=1e-06))) ## misc covariate constraints. misccov.msm <- msm(state ~ years, subject = PTNUM, data = cav, qmatrix = oneway4.q, ematrix=ematrix, death = 4, fixedpars=c(1:5), misccovariates = ~dage + sex, misccovinits = list(dage=c(0.01,0.01,0.001,0.001), sex=c(0.0131,0.0132,0.0133,0.0134)), miscconstraint = list(dage = c(1, 1, 2, 2)), control = list(trace=1, REPORT=1), method="BFGS") stopifnot(isTRUE(all.equal(4017.02699645160, misccov.msm$minus2loglik, tol=1e-06))) e <- ematrix.msm(misccov.msm) stopifnot(isTRUE(all.equal(0.999683601766175, e$estimates[1,1], tol=1e-06))) e <- ematrix.msm(misccov.msm, covariates=0) stopifnot(isTRUE(all.equal(0.992813688955682, e$estimates[1,1], tol=1e-06))) ## fixedpars for misc covariates. Parameters are ordered within covariate, within parameter, within state. misccov.msm <- msm(state ~ years, subject = PTNUM, data = cav, qmatrix = oneway4.q, ematrix=ematrix, death = 4, misccovariates = ~dage + sex, misccovinits = list(dage=c(0.01,0.02,0.03,0.04), sex=c(-0.013,-0.014,-0.015,-0.016)), fixedpars = c(10, 11, 12, 15), control = list(trace=1, REPORT=1), method="BFGS") stopifnot(isTRUE(all.equal(3946.96900738597, misccov.msm$minus2loglik, tol=1e-06))) ## multiple death states (Jean-Luc's data) ## Misclassification between states 2 and 3 c2.df <- read.table("~/msm/tests/jeanluc/donneesaveccancerPT.txt", header=TRUE) print(statetable.msm(state, PTNUM, c2.df)) qx <- rbind( c(0, 0.005, 0, 0, 0), c(0, 0, 0.01, 0.02,0), c(0, 0, 0, 0.04, 0.03), c(0, 0, 0, 0, 0), c(0, 0, 0, 0, 0)) ex <- rbind( c(0, 0, 0, 0, 0), c(0, 0, 0.1, 0, 0), c(0, 0.1, 0, 0, 0), c(0, 0, 0, 0, 0), c(0, 0, 0, 0, 0) ) c2.msm <- msm(state~years, subject=PTNUM, data=c2.df, qmatrix=qx, ematrix=ex, death=c(4, 5), method="BFGS", fixedpars = TRUE) stopifnot(isTRUE(all.equal(70084.3665626129, c2.msm$minus2loglik, tol=1e-06))) ## multiple death states specified using an obstype vector d45 <- rep(1, nrow(c2.df)); d45[c2.df$state %in% c(4,5)] <- 3 c2.msm <- msm(state~years, subject=PTNUM, data=c2.df, qmatrix=qx, ematrix=ex, obstype=d45, method="BFGS", fixedpars = TRUE) stopifnot(isTRUE(all.equal(70084.3665626129, c2.msm$minus2loglik, tol=1e-06))) } cat("misc.R: ALL TESTS PASSED\n") msm/tests/simple.R0000644000176000001440000004553712061401032013657 0ustar ripleyuserssource("local.R") library(msm) #library(msm, lib.loc="~/lib/R") #library(msm, lib.loc="~/msm/lib/sun/0.7.5") data(cav) ###TESTS FOR SIMPLE NON-HIDDEN MARKOV MODELS twoway4.q <- rbind(c(-0.5, 0.25, 0, 0.25), c(0.166, -0.498, 0.166, 0.166), c(0, 0.25, -0.5, 0.25), c(0, 0, 0, 0)) twoway4.q2 <- rbind(c(-0.51, 0.24, 0, 0.25), c(0.162, -0.498, 0.168, 0.166), c(0, 0.26, -0.5, 0.25), c(0, 0, 0, 0)) twoway3.q <- rbind(c(-0.5, 0.25, 0), c(0.166, -0.498, 0.166), c(0, 0.25, -0.5)) oneway4.q <- rbind(c(0, 0.148, 0, 0.0171), c(0, 0, 0.202, 0.081), c(0, 0, 0, 0.126), c(0, 0, 0, 0)) rownames(twoway4.q) <- colnames(twoway4.q) <- c("Well","Mild","Severe","Death") rownames(oneway4.q) <- colnames(oneway4.q) <- c("Well","Mild","Severe","Death") twoway4.i <- twoway4.q; twoway4.i[twoway4.i!=0] <- 1 oneway4.i <- oneway4.q; oneway4.i[oneway4.i!=0] <- 1 ### CAV DATA (stab <- statetable.msm(state, PTNUM, data=cav)) stopifnot(all(stab == c(1367, 46, 4, 204, 134, 13, 44, 54, 107, 148, 48, 55))) (cinits <- crudeinits.msm(state ~ years, PTNUM, data=cav, qmatrix=twoway4.q)) stopifnot(isTRUE(all.equal(c(-0.117314905786477, 0.116817878212849, 0, 0, 0.067989320398981, -0.375848825554382, 0.049084006577444, 0, 0, 0.137134030945518, -0.256747111328168, 0, 0.049325585387496, 0.121896916396016, 0.207663104750724, 0), as.numeric(cinits)))) ##Simple model cav.msm <- msm( state ~ years, subject=PTNUM, data = cav, qmatrix = twoway4.q, death = TRUE, fixedpars=TRUE, method="BFGS", control=list(trace=5, REPORT=1)) stopifnot(isTRUE(all.equal(4908.81676837903, cav.msm$minus2loglik, tol=1e-06))) cav.msm <- msm( state ~ years, subject=PTNUM, data = cav, qmatrix = cinits, death = TRUE, fixedpars=TRUE, method="BFGS", control=list(trace=5, REPORT=1)) stopifnot(isTRUE(all.equal(4113.16601901957, cav.msm$minus2loglik, tol=1e-06))) if (developer.local) { system.time(cav.msm <- msm( state ~ years, subject=PTNUM, data = cav, qmatrix = twoway4.q, death = TRUE, fixedpars=FALSE, # opt.method="nlm" method="BFGS", control=list(trace=5, REPORT=1, fnscale=1) ) ) stopifnot(isTRUE(all.equal(3968.7978930519, cav.msm$minus2loglik, tol=1e-06))) pnext.msm(cav.msm) pnext.msm(cav.msm, ci="normal") pnext.msm(cav.msm, ci="bootstrap", B=3) if (0) pnext.msm(cav.msm, ci="bootstrap") } ## No death state. system.time(cav.msm <- msm( state ~ years, subject=PTNUM, data = cav, qmatrix = twoway4.q, death = FALSE, fixedpars=FALSE, method="BFGS", control=list(trace=1, REPORT=1, fnscale=4000)) ) stopifnot(isTRUE(all.equal(3986.08765893935, cav.msm$minus2loglik, tol=1e-06))) cav.msm ## auto-generated initial values. state.g <- cav$state; time.g <- cav$years; subj.g <- cav$PTNUM cav.msm <- msm(state.g ~ time.g, subject=subj.g, qmatrix = twoway4.i, gen.inits=TRUE, fixedpars=TRUE) stopifnot(isTRUE(all.equal(4119.9736299032, cav.msm$minus2loglik, tol=1e-06))) if (developer.local) { system.time(cav.msm <- msm(state.g ~ time.g, subject=subj.g, qmatrix = twoway4.i, gen.inits=TRUE, fixedpars=TRUE)) stopifnot(isTRUE(all.equal(4119.9736299032, cav.msm$minus2loglik, tol=1e-06))) cav.msm <- msm(state.g ~ time.g, subject=subj.g, qmatrix = crudeinits.msm(state ~ years, PTNUM, twoway4.i, data=cav), fixedpars=TRUE) stopifnot(isTRUE(all.equal(4119.9736299032, cav.msm$minus2loglik, tol=1e-06))) } ## Covariates cav.msm <- msm( state ~ years, subject=PTNUM, data = cav, qmatrix = twoway4.q, death = TRUE, fixedpars=TRUE, covariates = ~ sex, covinits = list(sex=rep(0.01, 7)), # , dage=rep(0, 7)), method="BFGS", control=list(trace=5, REPORT=1)) stopifnot(isTRUE(all.equal(4909.08442586298, cav.msm$minus2loglik, tol=1e-06))) if (developer.local) { system.time(cav.msm <- msm( state ~ years, subject=PTNUM, data = cav, qmatrix = twoway4.q, death = TRUE, fixedpars=FALSE, covariates = ~ sex, method="BFGS", control=list(trace=5, REPORT=1))) # 44.13 on new, 260.14 on old stopifnot(isTRUE(all.equal(3954.77699876128, cav.msm$minus2loglik, tol=1e-06))) qmat <- qmatrix.msm(cav.msm)[c("estimates","SE")] stopifnot(isTRUE(all.equal(c(0.226768225214069, -0.583572966218831, 0.337068668450776, 0.0197360725539862), as.numeric(qmat$estimates[2,]), tol=1e-06))) stopifnot(isTRUE(all.equal(c(0.0341912476474469, 0.177757314782152, 0.0383135782775986, 0.171176619065207), as.numeric(qmat$SE[2,]), tol=1e-02))) ### SEs slightly different on different machines. stopifnot(isTRUE(all.equal(5.29003443121721, sojourn.msm(cav.msm)[1,3], tol=1e-06))) } if (developer.local) { ## Baseline constraints system.time(cav.msm <- msm( state ~ years, subject=PTNUM, data = cav, qmatrix = twoway4.q, death = TRUE, fixedpars=FALSE, qconstraint = c(1,1,2,2,2,3,3), method="BFGS", control=list(trace=2, REPORT=1) )) # 3.22 on new, 17.55 on old stopifnot(isTRUE(all.equal(4116.22686367935, cav.msm$minus2loglik, tol=1e-06))) qmat <- qmatrix.msm(cav.msm)[c("estimates","SE")] stopifnot(isTRUE(all.equal(0.171691686850913, qmat$estimates[2,1], tol=1e-06))) stopifnot(isTRUE(all.equal(2.96494230954565, sojourn.msm(cav.msm)[3,1], tol=1e-06))) ## Covariate constraints. system.time(cav.msm <- msm( state ~ years, subject=PTNUM, data = cav, qmatrix = twoway4.q, death = TRUE, fixedpars=FALSE, covariates = ~ sex, covinits = list(sex=rep(0.01, 7)), constraint=list(sex=c(1,2,3,1,2,3,2)), method="BFGS", control=list(trace=1, REPORT=1))) # 21.2 on new, 86.58 on old stopifnot(isTRUE(all.equal(3959.35551766943, cav.msm$minus2loglik, tol=1e-06))) qmat <- qmatrix.msm(cav.msm)[c("estimates","SE")] stopifnot(isTRUE(all.equal(0.228458428847816, qmat$estimates[2,1], tol=1e-06))) } ## Constraints with psoriatic arthritis data data(psor) psor.q <- rbind(c(0,0.1,0,0),c(0,0,0.1,0),c(0,0,0,0.1),c(0,0,0,0)) system.time(psor.msm <- msm(state ~ months, subject=ptnum, data=psor, qmatrix = psor.q, covariates = ~ollwsdrt+hieffusn, # covinits=list(hieffusn = c(0.5, 0.1, 0), ollwsdrt=c(0.2, 0.1, -0.1)), constraint = list(hieffusn=c(1,1,1),ollwsdrt=c(1,1,2)), fixedpars=FALSE, control = list(REPORT=1,trace=2), method="BFGS")) stopifnot(isTRUE(all.equal(1114.89946121717, psor.msm$minus2loglik, tol=1e-06))) stopifnot(isTRUE(all.equal(0.0953882330391683, qmatrix.msm(psor.msm)$estimates[1,2], tol=1e-03))) pn <- pnext.msm(psor.msm) ## center=FALSE psor.nocen.msm <- msm(state ~ months, subject=ptnum, data=psor, qmatrix = psor.q, covariates = ~ollwsdrt+hieffusn, constraint = list(hieffusn=c(1,1,1),ollwsdrt=c(1,1,2)), fixedpars=FALSE, center=FALSE, control = list(REPORT=1,trace=2), method="BFGS") ## $baseline and component should obey center stopifnot(isTRUE(all.equal(psor.nocen.msm$Qmatrices$baseline, qmatrix.msm(psor.nocen.msm, covariates=0, ci="none")))) stopifnot(isTRUE(all.equal(psor.nocen.msm$Qmatrices$baseline, qmatrix.msm(psor.nocen.msm, covariates=list(ollwsdrt=0), ci="none")))) stopifnot(isTRUE(all.equal(psor.msm$Qmatrices$baseline, qmatrix.msm(psor.msm, covariates="mean", ci="none")))) stopifnot(isTRUE(all.equal(psor.nocen.msm$sojourn, sojourn.msm(psor.nocen.msm, covariates=0)))) stopifnot(isTRUE(all.equal(psor.msm$sojourn, sojourn.msm(psor.msm, covariates="mean")))) stopifnot(isTRUE(all.equal(exp(psor.nocen.msm$Qmatrices$logbaseline[c(5,10,15)]), psor.nocen.msm$Qmatrices$baseline[c(5,10,15)]))) stopifnot(isTRUE(all.equal(exp(psor.msm$Qmatrices$logbaseline[c(5,10,15)]), psor.msm$Qmatrices$baseline[c(5,10,15)]))) ## Bug fixed in 1.1.3 stopifnot(isTRUE(all.equal(qmatrix.msm(psor.nocen.msm, covariates=0)$SE[1,2], qmatrix.msm(psor.nocen.msm, covariates=list(hieffusn=0, ollwsdrt=0))$SE[1,2]))) stopifnot(isTRUE(all.equal(qmatrix.msm(psor.nocen.msm, covariates=0)$SE[1,1], qmatrix.msm(psor.nocen.msm, covariates=list(hieffusn=0, ollwsdrt=0))$SE[1,1]))) stopifnot(isTRUE(all.equal(qmatrix.msm(psor.nocen.msm, covariates=0)$L[1,2], qmatrix.msm(psor.nocen.msm, covariates=list(hieffusn=0, ollwsdrt=0))$L[1,2]))) stopifnot(isTRUE(all.equal(qmatrix.msm(psor.nocen.msm, covariates=0)$L[1,2], qmatrix.msm(psor.nocen.msm, covariates=list(hieffusn=0))$L[1,2]))) cm <- psor.nocen.msm$qcmodel$covmeans stopifnot(isTRUE(all.equal(qmatrix.msm(psor.nocen.msm, covariates="mean")$SE[1,2], qmatrix.msm(psor.nocen.msm, covariates=list(hieffusn=cm["hieffusn"], ollwsdrt=cm["ollwsdrt"]))$SE[1,2]))) ## values not supplied are set to zero, even if center=TRUE (undocumented) stopifnot(isTRUE(all.equal(qmatrix.msm(psor.msm, covariates=list(hieffusn=0)), qmatrix.msm(psor.msm, covariates=list(ollwsdrt=0, hieffusn=0))))) stopifnot(isTRUE(all.equal(qmatrix.msm(psor.nocen.msm, covariates=list(hieffusn=0)), qmatrix.msm(psor.nocen.msm, covariates=list(ollwsdrt=0, hieffusn=0))))) ## No death state cav.msm <- msm( state ~ years, subject=PTNUM, data = cav, qmatrix = twoway4.q, death = FALSE, fixedpars=TRUE) stopifnot(isTRUE(all.equal(4833.0064065267, cav.msm$minus2loglik, tol=1e-06))) ## how big a dataset can if (0) { c3.df <- NULL for (i in 1:10) {c22.df <- c2.df; c22.df$PTNUM <- c2.df$PTNUM + 120000*(i-1); c3.df <- rbind(c3.df, c22.df)} length(unique(c2.df$PTNUM)) length(unique(c3.df$PTNUM)) qx <- rbind( c(0, 0.005, 0, 0, 0), c(0, 0, 0.01, 0.02,0), c(0, 0, 0, 0.04, 0.03), c(0, 0, 0, 0, 0), c(0, 0, 0, 0, 0)) c2.msm <- msm(state~years, subject=PTNUM, data=c2.df, qmatrix=qx, death=c(4, 5), method="BFGS", control=list(trace=1, REPORT=1, fnscale=100000)) c3.msm <- msm(state~years, subject=PTNUM, data=c3.df, qmatrix=qx, death=c(4, 5), method="BFGS", control=list(trace=1, REPORT=1, fnscale=100000)) } ##Multiple death states (Jean-Luc's data) if (developer.local) { c2.df <- read.table("~/msm/tests/jeanluc/donneesaveccancerPT.txt", header=TRUE) qx <- rbind( c(0, 0.005, 0, 0, 0), c(0, 0, 0.01, 0.02,0), c(0, 0, 0, 0.04, 0.03), c(0, 0, 0, 0, 0), c(0, 0, 0, 0, 0)) c2.msm <- msm(state~years, subject=PTNUM, data=c2.df, qmatrix=qx, death=c(4, 5), method="BFGS", fixedpars = 1:5, control=list(trace=2, REPORT=1, fnscale=100000)) stopifnot(isTRUE(all.equal(70646.727505836, c2.msm$minus2loglik, tol=1e-06))) c2.msm <- msm(state~years, subject=PTNUM, data=c2.df, qmatrix=qx, method="BFGS", fixedpars = 1:5, control=list(trace=2, REPORT=1, fnscale=100000)) stopifnot(isTRUE(all.equal(62915.1638036017, c2.msm$minus2loglik, tol=1e-06))) ## Same using an "obstype" vector. obstype <- ifelse(c2.df$state %in% c(4,5), 3, 1) c2.msm <- msm(state~years, subject=PTNUM, data=c2.df, qmatrix=qx, obstype=obstype, method="BFGS", fixedpars = 1:5, control=list(trace=2, REPORT=1, fnscale=100000)) stopifnot(isTRUE(all.equal(70646.727505836, c2.msm$minus2loglik, tol=1e-06))) obstype <- rep(1, length(c2.df$state)) c2.msm <- msm(state~years, subject=PTNUM, data=c2.df, obstype=obstype, qmatrix=qx, method="BFGS", fixedpars = 1:5, control=list(trace=2, REPORT=1, fnscale=100000)) stopifnot(isTRUE(all.equal(62915.1638036017, c2.msm$minus2loglik, tol=1e-06))) ### G Marshall's diabetic retinopathy data marsh.df <- read.table("~/msm/tests/markov/test.dat", col.names=c("subject","eyes","time","duration","hba1")) marsh.df$hba1 <- marsh.df$hba1 - mean(marsh.df$hba1) marsh.msm <- msm(eyes ~ time, subject=subject, qmatrix = rbind(c(0,0.02039,0,0), c(0.007874,0,0.01012,0), c(0,0.01393,0,0.01045), c(0,0,0,0)), covariates = ~ hba1, data = marsh.df, fixedpars=TRUE) stopifnot(isTRUE(all.equal(335.897217906310, marsh.msm$minus2loglik, tol=1e-06))) system.time(marsh.msm <- msm(eyes ~ time, subject=subject, qmatrix = rbind(c(0,0.02039,0,0), c(0.007874,0,0.01012,0), c(0,0.01393,0,0.01045), c(0,0,0,0)), covariates = ~ hba1, data = marsh.df)) stopifnot(isTRUE(all.equal(310.989863258621, marsh.msm$minus2loglik, tol=1e-06))) stopifnot(isTRUE(all.equal(-0.0496235211442196, qmatrix.msm(marsh.msm, covariates=0)$estimates[1,1], tol=1e-06))) } ### Aneurysm dataset different in 0.5 (not fromto, includes imputed initial states) ########## OUTPUT FUNCTIONS ################### qmatrix.msm(psor.msm) stopifnot(isTRUE(all.equal(c(-0.0953882330391683, 0, 0, 0, 0.0953882330391683, -0.163370011525553, 0, 0, 0, 0.163370011525553, -0.255229343798597, 0, 0, 0, 0.255229343798597, 0), as.numeric(qmatrix.msm(psor.msm)$estimates), tol=1e-03))) stopifnot(isTRUE(all.equal(c(0.0115507014188511, 0, 0, 0, 0.0115507014188511, 0.0195265275850904, 0, 0, 0, 0.0195265275850904, 0.0378507662232158, 0, 0, 0, 0.0378507662232158, 0), as.numeric(qmatrix.msm(psor.msm)$SE), tol=1e-03))) qmat <- qmatrix.msm(psor.msm, covariates=list(ollwsdrt=0.1, hieffusn=0.4)) stopifnot(isTRUE(all.equal(c(-0.121430585652200, 0, 0, 0, 0.121430585652200, -0.207972362475868, 0, 0, 0, 0.207972362475868, -0.257535341208494, 0, 0, 0, 0.257535341208494, 0), as.numeric(qmat$estimates), tol=1e-03))) stopifnot(isTRUE(all.equal(c(0.0162156605802465, 0, 0, 0, 0.0162156605802465, 0.0266727053124233, 0, 0, 0, 0.0266727053124233, 0.0364321127089265, 0, 0, 0, 0.0364321127089265, 0), as.numeric(qmat$SE), tol=1e-04))) try(qmatrix.msm(psor.msm, covariates=list(hieffusn=0.1, foo=0.4))) # deliberate error qmat <- qmatrix.msm(psor.msm, covariates=list(ollwsdrt=0.1, hieffusn=0.4), cl=0.99) stopifnot(isTRUE(all.equal(c(-0.171282667596986, 0, 0, 0, 0.0860880282792585, -0.289385121267802, 0, 0, 0, 0.149463467106753, -0.370756460718086, 0, 0, 0, 0.178889538008097, 0), as.numeric(qmat$L), tol=1e-04))) soj <- qmatrix.msm(psor.msm, covariates=list(ollwsdrt=0.1, hieffusn=0.4), sojourn=TRUE)$sojourn stopifnot(isTRUE(all.equal(c(8.23515751512713, 4.80833120370037, 3.88296221911705, Inf), as.numeric(soj), tol=1e-03))) qmatrix.msm(psor.msm, ci="normal", B=2) qmatrix.msm(psor.msm, ci="boot", B=2) soj <- sojourn.msm(psor.msm, covariates=list(ollwsdrt=0.1, hieffusn=0.4)) stopifnot(isTRUE(all.equal(c(8.23515751512713, 4.80833120370037, 3.88296221911705, 1.09971073904434, 0.616674252838334, 0.549301375677405, 6.33875136203292, 3.73961380505919, 2.94271599303942, 10.6989240349703, 6.18246967994404, 5.12363260020806), as.numeric(unlist(soj)), tol=1e-04))) soj <- sojourn.msm(psor.msm, covariates=list(ollwsdrt=0.1, hieffusn=0.4), cl=0.99) stopifnot(isTRUE(all.equal(5.83830234564607, soj[1,"L"], tol=1e-04))) stopifnot(isTRUE(all.equal(0.148036812842411, pmatrix.msm(psor.msm, ci="none", t=10)[1,3], tol=1e-04))) try(pmatrix.msm(psor.msm, t=10, covariates=list(hieffusn=0.1))) # deliberate error p <- pmatrix.msm(psor.msm, t=10, covariates=list(ollwsdrt=0.1, hieffusn=0.2)) stopifnot(isTRUE(all.equal(0.18196160265907, p[1,3], tol=1e-04))) set.seed(22061976); stopifnot(isTRUE(all.equal(0.12, pmatrix.msm(psor.msm, ci="normal", B=3)$L[2,3], tol=1e-01, scale=1))) q <- qratio.msm(psor.msm, c(1,2), c(2,3)) stopifnot(isTRUE(all.equal(c(0.583878474075081, 0.0996029045389022, 0.417943274168735, 0.815694601537263), as.numeric(q), tol=1e-04))) q <- qratio.msm(psor.msm, c(1,2), c(2,3), cl=0.99) stopifnot(isTRUE(all.equal(0.376262194364283, as.numeric(q["L"]), tol=1e-04))) q <- qratio.msm(psor.msm, c(1,1), c(2,3)) stopifnot(isTRUE(all.equal(c(-0.583878474075081, 0.0996029045389022, -0.815694601537263, -0.417943274168735), as.numeric(q), tol=1e-04))) q <- qratio.msm(psor.msm, c(2,2), c(2,3)) stopifnot(isTRUE(all.equal(c(-1,0,-1,-1), as.numeric(q), tol=1e-06))) qratio.msm(psor.msm, c(1,2), c(2,3), ci="norm", B=2) qratio.msm(psor.msm, c(1,2), c(2,3), ci="boot", B=2) print(interactive()) if (interactive()) { plot.msm(psor.msm) plot.msm(psor.msm, from=c(1,3), to=4, range=c(10,30)) plot.msm(psor.msm, from=c(1,2), to=4, range=c(10,80), legend.pos=c(70,0.1)) surface.msm(psor.msm) surface.msm(psor.msm, type="filled") surface.msm(psor.msm, c(3,5), type="filled") surface.msm(psor.msm, c(3,4)) x <- psor.msm$paramdata$params.uniq x[6] <- 0 surface.msm(psor.msm, c(3,4), point=x) surface.msm(psor.msm, c(3,4), point=x, xrange=c(-2, -0.6)) surface.msm(psor.msm, c(3,4), point=x, yrange=c(-1.2, 0.1)) surface.msm(psor.msm, c(3,4), point=x, np = 5) contour(psor.msm) persp(psor.msm) persp(psor.msm, np=5) image(psor.msm) plot.prevalence.msm(psor.msm) plot.prevalence.msm(psor.msm, col.obs="green", col.exp="brown", lty.obs=2, lty.exp=3, lwd.obs=2, lwd.exp=4, cex.axis=2) ## plotprog.msm(state ~ months, subject=ptnum, data=psor, legend.pos=c(20,0.99), lwd=3, xlab="Months") plotprog.msm(state ~ months, subject=ptnum, data=psor, legend.pos=c(20,0.99), lwd=1, mark.time=FALSE, xlab="Months") plot.survfit.msm(psor.msm, lwd=3, xlab="Months") plot.survfit.msm(psor.msm, lwd=3, lwd.surv=3, mark.time=FALSE, col.surv="green", lty.surv=4, xlab="Months") plot.survfit.msm(psor.msm, lwd=3, lwd.surv=3, ci="normal", B=4, col.surv="green", lty.surv=4, xlab="Months", lty.ci=1, lwd.ci=2, col.ci="purple") } co <- coef.msm(psor.msm) stopifnot(isTRUE(all.equal(0.498319866154661, co$hieffusn[1,2], tol=1e-04))) haz <- hazard.msm(psor.msm) stopifnot(isTRUE(all.equal(0.385347226135311, haz$ollwsdrt[1,2], tol=1e-04))) stopifnot(isTRUE(all.equal(0.385347226135311, haz$ollwsdrt[2,2], tol=1e-04))) stopifnot(isTRUE(all.equal(2.35928404626333, haz$hieffusn[1,3], tol=1e-04))) stopifnot(isTRUE(all.equal(2.35928404626333, haz$hieffusn[3,3], tol=1e-04))) haz <- hazard.msm(psor.msm, hazard.scale=2) stopifnot(isTRUE(all.equal(0.148492484690178, haz$ollwsdrt[1,2], tol=1e-04))) stopifnot(isTRUE(all.equal(0.148492484690178, haz$ollwsdrt[2,2], tol=1e-04))) #stopifnot(isTRUE(all.equal(5.56622121095267, haz$hieffusn[1,3], tol=1e-04))) #stopifnot(isTRUE(all.equal(5.56622121095267, haz$hieffusn[3,3], tol=1e-04))) haz <- hazard.msm(psor.msm, hazard.scale=c(1,2)) stopifnot(isTRUE(all.equal(0.385347226135311, haz$ollwsdrt[1,2], tol=1e-04))) stopifnot(isTRUE(all.equal(0.385347226135311, haz$ollwsdrt[2,2], tol=1e-04))) #stopifnot(isTRUE(all.equal(5.56622121095267, haz$hieffusn[1,3], tol=1e-04))) #stopifnot(isTRUE(all.equal(5.56622121095267, haz$hieffusn[3,3], tol=1e-04))) stopifnot(isTRUE(all.equal(c(1,2,3), as.numeric(transient.msm(psor.msm)), tol=1e-06))) stopifnot(isTRUE(all.equal(4, as.numeric(absorbing.msm(psor.msm)), tol=1e-06))) cat("simple.R: ALL TESTS PASSED\n") msm/NAMESPACE0000644000176000001440000000243111760723160012320 0ustar ripleyusersuseDynLib(msm) export( absorbing.msm, boot.msm, coef.msm, contour.msm, crudeinits.msm, deltamethod, ematrix.msm, hazard.msm, image.msm, MatrixExp, msm, logLik.msm, lrtest.msm, odds.msm, pearson.msm, persp.msm, plot.msm, plotprog.msm, plot.prevalence.msm, plot.survfit.msm, pmatrix.msm, pmatrix.piecewise.msm, pnext.msm, prevalence.msm, qmatrix.msm, qratio.msm, scoreresid.msm, sim.msm, simmulti.msm, sojourn.msm, statetable.msm, summary.msm, surface.msm, totlos.msm, transient.msm, viterbi.msm, hmmCat, hmmIdent, hmmUnif, hmmNorm, hmmLNorm, hmmExp, hmmGamma, hmmWeibull, hmmPois, hmmBinom, hmmTNorm, hmmMETNorm, hmmMEUnif, hmmNBinom, hmmBeta, hmmT, dtnorm, ptnorm, qtnorm, rtnorm, dmenorm, pmenorm, qmenorm, rmenorm, dmeunif, pmeunif, qmeunif, rmeunif, dpexp, ppexp, qpexp, rpexp ) importFrom(graphics, plot) importFrom(graphics, persp) importFrom(graphics, contour) importFrom(graphics, image) importFrom(stats, coef) importFrom(mvtnorm, rmvnorm) importFrom(survival, Surv) importFrom(survival, survfit) S3method(print, msm) S3method(summary, msm) S3method(plot, msm) S3method(contour, msm) S3method(persp, msm) S3method(image, msm) S3method(coef, msm) S3method(logLik, msm) S3method(print, hmodel) S3method(print, hmmdist) S3method(print, msm.est) S3method("[", msm.est) S3method(print, pearson.msm) msm/src/0000755000176000001440000000000012061401532011657 5ustar ripleyusersmsm/src/lik.c0000644000176000001440000007635512061401532012622 0ustar ripleyusers/* ***************************************************************** PROGRAM: lik.c AUTHOR: Chris Jackson DATE: July 2004 Routines for calculating likelihoods for multi-state Markov and hidden Markov models. ****************************************************************** */ #include "msm.h" #include "hmm.h" #include #define NODEBUG #define NODEBUG2 #define NOVITDEBUG linkfn LINKFNS[3][2] = { {identity, identity}, {log, exp}, {logit, expit} }; /* MUST KEEP THIS IN SAME ORDER AS .msm.HMODELPARS IN R/constants.R */ hmmfn HMODELS[] = { hmmCat, hmmIdent, hmmUnif, hmmNorm, hmmLNorm, hmmExp, hmmGamma, hmmWeibull, hmmPois, hmmBinom, hmmTNorm, hmmMETNorm, hmmMEUnif, hmmNBinom, hmmBeta, hmmT }; #define OBS_SNAPSHOT 1 #define OBS_EXACT 2 #define OBS_DEATH 3 double logit(double x) { return log(x / (1 - x)); } double expit(double x) { return exp(x) / ( 1 + exp(x) ); } double identity(double x) { return x; } /* Good-enough floating point equality comparison */ int all_equal(double x, double y) { return fabs (x - y) <= DBL_EPSILON * fabs(x); } /* Add effects of covariates at an observation number obs to a set of link-transformed parameters For covs on the qmatrix, we have npars q's, each with the same number of covs on them For HMMs, each set is the set of parameters of the model for one state Only certain of these parameters (means and rates) can have covariates on them, ncovs[i] > 0 whichcov[j] is the column of the (vectorised) data matrix "cov" containing the jth covariate totcovs is a call-by-referenced integer which counts the covariates so far, used for indexing whichcov coveffect is a vectorised ncovs * npars matrix, filled by rows (par1) cov1 cov2 .. (par2) cov1 cov2 */ void AddCovs(int obs, int nobs, int npars, int *ncovs, double *oldpars, double *newpars, double *coveffect, double *cov, int *whichcov, int *totcovs, double link(double x), double invlink(double x)) { int i, j, k=0; double x; for (i = 0; i < npars; ++i) { newpars[i] = oldpars[i]; if (ncovs[i] > 0) { newpars[i] = link(newpars[i]); for (j = 0; j < ncovs[i]; ++j) { x = cov[MI(obs, whichcov[j]-1, nobs)]; newpars[i] += coveffect[k] * x; ++k; } newpars[i] = invlink(newpars[i]); *totcovs += ncovs[i]; } } } void GetCovData(int obs, double *allcovs, int *whichcov, double *thiscov, int ncovs, int nobs) { int i; for (i=0; icensor. Return one-indexed current (*states) */ void GetCensored (double obs, cmodel *cm, int *nc, double **states) { int j, k=0, n, cens=0; if (cm->ncens == 0) n = 1; else { while (!all_equal(obs, cm->censor[k]) && k < cm->ncens) ++k; if (k < cm->ncens) { cens = 1; n = cm->censstind[k+1] - cm->censstind[k]; } else n = 1; } if (cm->ncens == 0 || !cens) (*states)[0] = obs; else { for (j = cm->censstind[k]; j < cm->censstind[k+1]; ++j) (*states)[j - cm->censstind[k]] = cm->censstates[j]; } *nc = n; } /* Calculate p (obs curr | true i) for hidden Markov models If observation is not necessarily of the true state (!obstrue), then this is just the HMM outcome probability (summed over censor set if necessary) If obstrue, this observation is not misclassified. e.g. censor set 1,2,3, state set 1,2,3,4, pout = if i in curr 1, else 0 */ void GetOutcomeProb(double *pout, double *curr, int nc, double *newpars, hmodel *hm, qmodel *qm, int obstrue) { int i, j; for (i=0; inst; ++i) { pout[i] = 0; if (!obstrue) { for (j=0; jmodels[i]])(curr[j], &(newpars[hm->firstpar[i]])); } else { for (j=0; jnst, double); double *T = Calloc((qm->nst)*(qm->nst), double); double *newintens = Calloc(qm->npars, double); double *pmat = Calloc((qm->nst)*(qm->nst), double); double *newpars = Calloc(hm->totpars, double); AddCovs(obsno-1, d->nobs, qm->npars, qcm->ncovs, qm->intens, newintens, qcm->coveffect, d->cov, d->whichcov, &totcovs, log, exp); totcovs = 0; for (i = 0; i < qm->nst; ++i) { fp = hm->firstpar[i]; /* index into concatenated vector of parameters */ AddCovs(obsno, d->nobs, hm->npars[i], &(hm->ncovs[fp]), &(hm->pars[fp]), &(newpars[fp]), &(hm->coveffect[totcovs]), d->cov, &(d->whichcovh[totcovs]), &totcovs, LINKFNS[hm->links[i]][0], LINKFNS[hm->links[i]][1]); } GetOutcomeProb(pout, curr, nc, newpars, hm, qm, d->obstrue[obsno]); #ifdef DEBUG2 printf("pout: %4.3f, %4.3f, %4.3f, %4.3f\n", pout[0], pout[1], pout[2], pout[3]); #endif /* calculate the transition probability (P) matrix for the time interval dt */ Pmat(pmat, d->time[obsno] - d->time[obsno-1], newintens, qm->npars, qm->ivector, qm->nst, (d->obstype[obsno] == OBS_EXACT), qm->analyticp, qm->iso, qm->perm, qm->qperm, 0); for(j = 0; j < qm->nst; ++j) { newp[j] = 0.0; for(i = 0; i < qm->nst; ++i) { if (d->obstype[obsno] == OBS_DEATH) { /* Find the true state that obs represents. This should be the state with outcome model hmmIdent(obs) */ if (d->obstrue[obsno]) ideath = curr[0] - 1; else for (ideath=0; ideath < qm->nst; ++ideath) if (hm->models[ideath] == 1 && hmmIdent(curr[0], &(newpars[hm->firstpar[ideath]]))) break; T[MI(i,j,qm->nst)] = pmat[MI(i,j,qm->nst)] * qij(j, ideath, newintens, qm->ivector, qm->nst); } else { T[MI(i,j,qm->nst)] = pmat[MI(i, j, qm->nst)] * pout[j]; } if (T[MI(i,j,qm->nst)] < 0) T[MI(i,j,qm->nst)] = 0; newp[j] = newp[j] + cump[i]*T[MI(i,j,qm->nst)]; #ifdef DEBUG2 printf("%4.3f, ", pmat[MI(i,j,qm->nst)]); #endif } #ifdef DEBUG2 printf("\n"); printf("newp: "); printf("%lf, ", newp[j]); #endif } /* re-scale the likelihood at each step to prevent it getting too small and underflowing */ /* while cumulatively recording the log scale factor */ normalize (newp, cump, qm->nst, lweight); Free(pout); Free(T); Free(newintens); Free(pmat); Free(newpars); } /* Likelihood for the hidden Markov model for one individual */ double likhidden(int pt, /* ordinal subject ID */ msmdata *d, qmodel *qm, qcmodel *qcm, cmodel *cm, hmodel *hm ) { double *curr = Calloc (qm->nst, double); /* no more than nst states allowed */ double *cump = Calloc(qm->nst, double); double *newp = Calloc(qm->nst, double); double *pout = Calloc(qm->nst, double); double *newpars = Calloc(hm->totpars, double); double *newinitp = Calloc(qm->nst, double); double lweight, lik; int i, fp, totcovs=0, obsno, nc=1; if (d->firstobs[pt] + 1 == d->firstobs[pt+1]) return 0; /* individual has only one observation */ /* Likelihood for individual's first observation */ for (i = 0; i < qm->nst; ++i) { fp = hm->firstpar[i]; AddCovs(d->firstobs[pt], d->nobs, hm->npars[i], &(hm->ncovs[fp]), &(hm->pars[fp]), &(newpars[fp]), &(hm->coveffect[totcovs]), d->cov, &(d->whichcovh[totcovs]), &totcovs, LINKFNS[hm->links[i]][0], LINKFNS[hm->links[i]][1]); } GetCensored((double)d->obs[d->firstobs[pt]], cm, &nc, &curr); GetOutcomeProb(pout, curr, nc, newpars, hm, qm, d->obstrue[d->firstobs[pt]]); /* Add covariate effects on initp (expressed as p(cat) / p(baseline cat)) */ AddCovs(d->firstobs[pt], d->nobs, qm->nst - 1, hm->nicovs, &hm->initp[1], &newinitp[1], hm->icoveffect, d->cov, d->whichcovi, &totcovs, log, exp); /* Transform initp from probs relative to state 1 prob back to absolute probs */ relative2absolutep(newinitp, newinitp, qm->nst, 0); /* Likelihood contribution for initial observation */ for (i = 0; i < qm->nst; ++i) { /* Ignore initprobs if observation is known to be the true state */ if (d->obstrue[d->firstobs[pt]]) newinitp[i] = 1; cump[i] = pout[i] * newinitp[i]; } lweight=0; /* Matrix product loop to accumulate the likelihood for subsequent observations */ for (obsno = d->firstobs[pt]+1; obsno <= d->firstobs[pt+1] - 1; ++obsno) { R_CheckUserInterrupt(); GetCensored((double)d->obs[obsno], cm, &nc, &curr); update_likhidden(curr, nc, obsno, d, qm, qcm, hm, cump, newp, &lweight); } #ifdef DEBUG2 printf("cump: "); #endif for (i = 0, lik = 0; i < qm->nst; ++i) { #ifdef DEBUG2 printf("%lf, ", cump[i]); #endif lik = lik + cump[i]; } #ifdef DEBUG2 printf("\n"); #endif Free(curr); Free(cump); Free(newp); Free(pout); Free(newpars); Free(newinitp); /* Transform the likelihood back to the proper scale */ return -2*(log(lik) - lweight); } void update_likcensor(int obsno, double *prev, double *curr, int np, int nc, msmdata *d, qmodel *qm, qcmodel *qcm, hmodel *hm, double *cump, double *newp, double *lweight) { double *newintens = Calloc(qm->npars, double); double *pmat = Calloc((qm->nst)*(qm->nst), double); double contrib; int i, j, k, totcovs = 0; AddCovs(obsno-1, d->nobs, qm->npars, qcm->ncovs, qm->intens, newintens, qcm->coveffect, d->cov, d->whichcov, &totcovs, log, exp); Pmat(pmat, d->time[obsno] - d->time[obsno-1], newintens, qm->npars, qm->ivector, qm->nst, (d->obstype[obsno] == OBS_EXACT), qm->analyticp, qm->iso, qm->perm, qm->qperm, 0); for(i = 0; i < nc; ++i) { newp[i] = 0.0; for(j = 0; j < np; ++j) { if (d->obstype[obsno] == OBS_DEATH) { contrib = 0; for (k = 0; k < qm->nst; ++k) if (k != curr[i]-1) contrib += pmat[MI((int) prev[j]-1, k, qm->nst)] * qij(k, (int) curr[i]-1, newintens, qm->ivector, qm->nst); newp[i] += cump[j] * contrib; } else { newp[i] += cump[j] * pmat[MI((int) prev[j]-1, (int) curr[i]-1, qm->nst)]; } } } normalize(newp, cump, nc, lweight); Free(pmat); Free(newintens); } double likcensor(int pt, /* ordinal subject ID */ msmdata *d, qmodel *qm, qcmodel *qcm, cmodel *cm, hmodel *hm ) { double *cump = Calloc(qm->nst, double); double *newp = Calloc(qm->nst, double); double *prev = Calloc(qm->nst, double); double *curr = Calloc(qm->nst, double); double lweight = 0, lik; int i, obs, np=0, nc=0; if (d->firstobs[pt] + 1 == d->firstobs[pt+1]) return 0; /* individual has only one observation */ for (i = 0; i < qm->nst; ++i) cump[i] = 1; GetCensored((double)d->obs[d->firstobs[pt]], cm, &np, &prev); for (obs = d->firstobs[pt]+1; obs <= d->firstobs[pt+1] - 1; ++obs) { /* post-multiply by sub-matrix of P at each obs */ GetCensored((double)d->obs[obs], cm, &nc, &curr); update_likcensor(obs, prev, curr, np, nc, d, qm, qcm, hm, cump, newp, &lweight); np = nc; for (i=0; inst)*(qm->nst), double); double *newintens = Calloc ( qm->npars , double); #ifdef DEBUG int j; #endif for (i=0; i < d->nobs; ++i) { R_CheckUserInterrupt(); if ((i==0) || (d->whicha[i] != d->whicha[i-1]) || (d->obstype[i] != d->obstype[i-1])) { /* we have a new timelag/covariates/obstype combination. Recalculate the P matrix for this */ AddCovs(i, d->nobs, qm->npars, qcm->ncovs, qm->intens, newintens, qcm->coveffect, d->cov, d->whichcov, &totcovs, log, exp); Pmat(pmat, d->timelag[i], newintens, qm->npars, qm->ivector, qm->nst, (d->obstype[i] == OBS_EXACT), qm->analyticp, qm->iso, qm->perm, qm->qperm, 0); } if (d->obstype[i] == OBS_DEATH) contrib = pijdeath(d->fromstate[i], d->tostate[i], pmat, newintens, qm->ivector, qm->nst); else contrib = pmat[MI(d->fromstate[i], d->tostate[i], qm->nst)]; lik += d->nocc[i] * log(contrib); #ifdef DEBUG printf("obs %d, from %d, to %d, time %lf, obstype %d, ", i, d->fromstate[i], d->tostate[i], d->timelag[i], d->obstype[i]); for (j = 0; j < qcm->ncovs[0]; ++j) printf("cov%d %lf, ", j, d->cov[MI(i, d->whichcov[j]-1, d->nobs)]); printf("nocc %d, con %lf, lik %lf\n", d->nocc[i], log(contrib), lik); #endif } Free(pmat); Free(newintens); return (-2*lik); } /* Find zero-based index of maximum element of a vector x */ void pmax(double *x, int n, int *maxi) { int i=0; *maxi = i; for (i=1; i x[*maxi]) { *maxi = i; } } } /* Calculates the most likely path through underlying states */ void Viterbi(msmdata *d, qmodel *qm, qcmodel *qcm, cmodel *cm, hmodel *hm, double *fitted) { int i, j, tru, fp, k, kmax, obs, totcovs=0, nc = 1; double *newintens = (double *) S_alloc(qm->npars, sizeof(double)); double *newpars = (double *) S_alloc(hm->totpars, sizeof(double)); double *newinitp = (double *) S_alloc(qm->nst, sizeof(double)); double *pmat = (double *) S_alloc((qm->nst)*(qm->nst), sizeof(double)); int *ptr = (int *) S_alloc((d->nobs)*(qm->nst), sizeof(int)); double *lvold = (double *) S_alloc(qm->nst, sizeof(double)); double *lvnew = (double *) S_alloc(qm->nst, sizeof(double)); double *lvp = (double *) S_alloc(qm->nst, sizeof(double)); double *curr = (double *) S_alloc (qm->nst, sizeof(double)); double *pout = (double *) S_alloc(qm->nst, sizeof(double)); double dt; /* Add covariate effects on initp (expressed as p(cat) / p(baseline cat)) */ i = 0; if (d->obstrue[i]) { for (k = 0; k < qm->nst; ++k) lvold[k] = (k+1 == d->obs[i] ? 1 : R_NegInf); } else { GetCensored(d->obs[i], cm, &nc, &curr); /* initial observation is a censored state. No HMM here, so initprobs not needed */ if (nc > 1) { for (k = 0, j = 0; k < qm->nst; ++k) { if (k+1 == curr[j]) { lvold[k] = 1; ++j; } else lvold[k] = R_NegInf; } } else { /* use initprobs */ AddCovs(i, d->nobs, qm->nst - 1, hm->nicovs, &hm->initp[1], &newinitp[1], hm->icoveffect, d->cov, d->whichcovi, &totcovs, log, exp); relative2absolutep(newinitp, newinitp, qm->nst, 0); for (k = 0; k < qm->nst; ++k) lvold[k] = log(newinitp[k]); } } for (i = 1; i <= d->nobs; ++i) { R_CheckUserInterrupt(); #ifdef VITDEBUG printf("obs %d\n", i); #endif if ((i < d->nobs) && (d->subject[i] == d->subject[i-1])) { #ifdef VITDEBUG printf("subject %d\n ", d->subject[i]); #endif dt = d->time[i] - d->time[i-1]; AddCovs(i - 1, d->nobs, qm->npars, qcm->ncovs, qm->intens, newintens, qcm->coveffect, d->cov, d->whichcov, &totcovs, log, exp); totcovs = 0; for (j = 0; j < qm->nst; ++j) { fp = hm->firstpar[j]; AddCovs(i - 1, d->nobs, hm->npars[j], &(hm->ncovs[fp]), &(hm->pars[fp]), &(newpars[fp]), &(hm->coveffect[totcovs]), d->cov, &(d->whichcovh[totcovs]), &totcovs, LINKFNS[hm->links[j]][0], LINKFNS[hm->links[j]][1]); } GetCensored(d->obs[i], cm, &nc, &curr); GetOutcomeProb(pout, curr, nc, newpars, hm, qm, d->obstrue[i]); #ifdef VITDEBUG for (tru=0;trunpars; ++k) printf("intens[%d] = %f", k, qm->intens[k]); printf("\n"); for (k=0; kncovs[0]; ++k) printf("cov[%d] = %f", k, d->cov[MI(i-1,k,d->nobs)]); printf("\n"); for (k=0; knpars; ++k) printf("newintens[%d] = %f", k, newintens[k]); printf("\n"); for (j = 0; j < qm->nst; ++j) { for (k=0; knpars[j]; ++k) printf("hpar[%d] = %f", k, hm->pars[k]); printf("\n"); } #endif Pmat(pmat, dt, newintens, qm->npars, qm->ivector, qm->nst, (d->obstype[i] == OBS_EXACT), qm->analyticp, qm->iso, qm->perm, qm->qperm, 0); for (tru = 0; tru < qm->nst; ++tru) { if (d->obstrue[i-1]) { lvnew[tru] = (tru == d->obs[i-1] - 1 ? 1 : R_NegInf); ptr[MI(i, tru, d->nobs)] = kmax = d->obs[i-1] - 1; } else { for (k = 0; k < qm->nst; ++k) lvp[k] = lvold[k] + log(pmat[MI(k, tru, qm->nst)]); pmax(lvp, qm->nst, &kmax); lvnew[tru] = log ( pout[tru] ) + lvp[kmax]; ptr[MI(i, tru, d->nobs)] = kmax; } #ifdef VITDEBUG printf("true %d, pout[%d] = %lf, lvold = %lf, pmat = %lf, lvnew = %lf, mi = %d, ptr=%d\n", tru, tru, pout[tru], lvold[tru], pmat[MI(kmax, tru, qm->nst)], lvnew[tru], MI(i, tru, d->nobs), ptr[MI(i, tru, d->nobs)]); #endif } for (k = 0; k < qm->nst; ++k) lvold[k] = lvnew[k]; } else { #ifdef VITDEBUG printf("traceback for subject %d\n ", d->subject[i-1]); #endif /* Traceback for current individual */ pmax(lvold, qm->nst, &kmax); #ifdef VITDEBUG printf("kmax = %d\n", kmax); #endif obs = i-1; fitted[obs] = (d->obstrue[obs] ? d->obs[obs]-1 : kmax); /* if last obs censoring, then kmax=0 since pout all 0 for prev obs, wrong, should be 0,1,1,0. */ while ( (obs > 0) && (d->subject[obs] == d->subject[obs-1]) ) { fitted[obs-1] = ptr[MI(obs, fitted[obs], d->nobs)]; #ifdef VITDEBUG printf("mi = %d, ptr %d = %1.0lf, ", MI(obs, (int) fitted[obs], d->nobs), obs-1, fitted[obs-1]); #endif --obs; } /* Add covariate effects on initp (expressed as p(cat) / p(baseline cat)) */ if (d->obstrue[i]) { for (k = 0; k < qm->nst; ++k) lvold[k] = (k+1 == d->obs[i] ? 1 : R_NegInf); } else { GetCensored(d->obs[i], cm, &nc, &curr); /* initial observation is a censored state. No HMM here, so initprobs not needed */ if (nc > 1) { for (k = 0, j = 0; k < qm->nst; ++k) { if (k+1 == curr[j]) { lvold[k] = 1; ++j; } else lvold[k] = R_NegInf; } } else { /* use initprobs */ AddCovs(i, d->nobs, qm->nst - 1, hm->nicovs, &hm->initp[1], &newinitp[1], hm->icoveffect, d->cov, d->whichcovi, &totcovs, log, exp); relative2absolutep(newinitp, newinitp, qm->nst, 0); for (k = 0; k < qm->nst; ++k) lvold[k] = log(newinitp[k]); } } } } } void msmLikelihood (msmdata *d, qmodel *qm, qcmodel *qcm, cmodel *cm, hmodel *hm, double *returned) { int pt; double likone; /* Likelihood for hidden Markov model */ if (hm->hidden) { *returned = 0; for (pt = 0; pt < d->npts; ++pt){ likone = likhidden (pt, d, qm, qcm, cm, hm); #ifdef DEBUG printf("pt %d, lik %lf\n", pt, likone); #endif *returned += likone; } } /* Likelihood for Markov model with censored outcomes */ else if (cm->ncens > 0) { for (pt = 0; pt < d->npts; ++pt){ likone = likcensor (pt, d, qm, qcm, cm, hm); #ifdef DEBUG printf("pt %d, lik %lf\n", pt, likone); #endif *returned += likone; } } /* Likelihood for simple non-hidden, non-censored Markov model */ else { *returned = liksimple (d, qm, qcm, cm, hm); } } /* First derivatives of the log-likelihood for the non-hidden multi-state Markov model. */ void derivsimple(msmdata *d, qmodel *qm, qcmodel *qcm, cmodel *cm, hmodel *hm, double *deriv) { int i, p, np=qm->npars, ndp=qm->ndpars, ndc=qcm->ndpars, totcovs=0; double contrib=0; double *dcontrib = Calloc(ndp+ndc, double); double *dpmat = Calloc(qm->nst * qm->nst * (ndp+ndc), double); double *pmat = Calloc(qm->nst * qm->nst, double); double *newintens = Calloc(np, double); double *x = Calloc(qcm->ncovs[0], double); for (i=0; i < d->nobs; ++i) { R_CheckUserInterrupt(); if ((i==0) || (d->whicha[i] != d->whicha[i-1]) || (d->obstype[i] != d->obstype[i-1])) { /* we have a new timelag/covariates/obstype combination. Recalculate the P matrix and its derivatives for this */ GetCovData(i, d->cov, d->whichcov, x, qcm->ncovs[0], d->nobs); AddCovs(i, d->nobs, np, qcm->ncovs, qm->intens, newintens, qcm->coveffect, d->cov, d->whichcov, &totcovs, log, exp); Pmat(pmat, d->timelag[i], newintens, qm->npars, qm->ivector, qm->nst, (d->obstype[i] == OBS_EXACT), qm->analyticp, qm->iso, qm->perm, qm->qperm, 0); DPmat(dpmat, d->timelag[i], x, newintens, qm->intens, qm->ivector, qm->nst, np, ndp, ndc, qm->constr, qcm->constr, qcm->wcov, (d->obstype[i] == OBS_EXACT)); } if (d->obstype[i] == OBS_DEATH) { contrib = pijdeath(d->fromstate[i], d->tostate[i], pmat, newintens, qm->ivector, qm->nst); dpijdeath(d->fromstate[i], d->tostate[i], x, dpmat, pmat, newintens, qm->intens, qm->ivector, qm->nst, qm->constr, qcm->constr, ndp, ndc, qcm->ncovs[0], dcontrib); } else { contrib = pmat[MI(d->fromstate[i], d->tostate[i], qm->nst)]; for (p = 0; p < ndp+ndc; ++p) dcontrib[p] = dpmat[MI3(d->fromstate[i], d->tostate[i], p, qm->nst, qm->nst)]; } for (p = 0; p < ndp+ndc; ++p) { deriv[p] += d->nocc[i] * dcontrib[p] / contrib; } #ifdef DEBUG for (p = 0; p < ndp+ndc; ++p) { printf("%d, %d, %d, %d, %6.4f, %d, %d, %lf\n", i, p, d->fromstate[i], d->tostate[i], d->timelag[i], d->obstype[i], d->nocc[i], -2 * d->nocc[i] * dcontrib[p] / contrib); } #endif } for (p = 0; p < ndp+ndc; ++p) deriv[p] *= -2; Free(dcontrib); Free(dpmat); Free(pmat); Free(newintens); Free(x); } /* First derivatives of the likelihood for the non-hidden multi-state Markov model. Uses data of form "subject, time, state, covariates". Returns derivatives by individual and parameter for use in the score residual diagnostic. */ void derivsimple_subj(msmdata *d, qmodel *qm, qcmodel *qcm, cmodel *cm, hmodel *hm, double *deriv) { int pt, i, p, np=qm->npars, ndp=qm->ndpars, ndc=qcm->ndpars, totcovs=0; double *dcontrib = Calloc(ndp+ndc, double); double *dpmat = Calloc(qm->nst * qm->nst * (ndp+ndc), double); double *pmat = Calloc(qm->nst * qm->nst, double); double *newintens = Calloc(np, double); double *x = Calloc(qcm->ncovs[0], double); double contrib=0, dt; int from, to; for (pt = 0; pt < d->npts; ++pt){ { R_CheckUserInterrupt(); if (d->firstobs[pt+1] > d->firstobs[pt] + 1) { /* individual has more than one observation? */ for (p = 0; p < ndp+ndc; ++p) { deriv[MI(pt,p,d->npts)] = 0; } for (i = d->firstobs[pt]+1; i < d->firstobs[pt+1]; ++i) { GetCovData(i, d->covobs, d->whichcov, x, qcm->ncovs[0], d->n); AddCovs(i, d->n, np, qcm->ncovs, qm->intens, newintens, qcm->coveffect, d->covobs, d->whichcov, &totcovs, log, exp); dt = d->time[i] - d->time[i-1]; from = fprec(d->obs[i-1] - 1, 0); /* convert state outcome to integer */ to = fprec(d->obs[i] - 1, 0); Pmat(pmat, dt, newintens, qm->npars, qm->ivector, qm->nst, (d->obstype[i] == OBS_EXACT), qm->analyticp, qm->iso, qm->perm, qm->qperm, 0); DPmat(dpmat, dt, x, newintens, qm->intens, qm->ivector, qm->nst, np, ndp, ndc, qm->constr, qcm->constr, qcm->wcov, (d->obstype[i] == OBS_EXACT)); if (d->obstype[i] == OBS_DEATH) { contrib = pijdeath(from, to, pmat, newintens, qm->ivector, qm->nst); dpijdeath(from, to, x, dpmat, pmat, newintens, qm->intens, qm->ivector, qm->nst, qm->constr, qcm->constr, ndp, ndc, qcm->ncovs[0], dcontrib); } else { contrib = pmat[MI(from, to, qm->nst)]; for (p = 0; p < ndp+ndc; ++p) dcontrib[p] = dpmat[MI3(from, to, p, qm->nst, qm->nst)]; } for (p = 0; p < ndp+ndc; ++p) { deriv[MI(pt,p,d->npts)] += dcontrib[p] / contrib; /* on loglik scale not -2*loglik */ #ifdef DEBUG printf("%d, %d, %d, %d, %d, %6.4f, %d, %lf, %lf\n", i, p, pt, from, to, dt, d->obstype[i], -2 * dcontrib[p] / contrib, -2*deriv[MI(pt,p,d->npts)]); #endif } } for (p = 0; p < ndp+ndc; ++p) deriv[MI(pt,p,d->npts)] *= -2; } else for (p = 0; p < ndp+ndc; ++p) deriv[MI(pt,p,d->npts)] = 0; } } Free(dcontrib); Free(dpmat); Free(pmat); Free(newintens); Free(x); } /* Derivative of log-likelihood. Not available for hidden models or models with censoring. */ void msmDLikelihood (msmdata *d, qmodel *qm, qcmodel *qcm, cmodel *cm, hmodel *hm, double *returned) { derivsimple (d, qm, qcm, cm, hm, returned); } void msmDLikelihood_subj (msmdata *d, qmodel *qm, qcmodel *qcm, cmodel *cm, hmodel *hm, double *returned) { derivsimple_subj (d, qm, qcm, cm, hm, returned); } /* This function is called from R to provide an entry into C code for evaluating likelihoods, derivatives and doing Viterbi state reconstruction */ void msmCEntry( int *do_what, /* 1 = eval likelihood, 2 = Viterbi */ int *qvector, /* vectorised matrix of allowed transition indicators */ /* Parameters */ double *intens, double *coveffect, double *hmmpars, double *hcoveffect, /* Data for non-HMM multi-state models */ int *fromstate, /* Distinct combinations of from, to, time lag, covariates */ int *tostate, double *timelag, double *covvec, /* vectorised matrix of covariate data (also used for HMMs) */ double *covobsvec, /* vectorised matrix of covariate data (by observation) used when calculating derivs by individual */ int *whichcov, /* which column in the covariate data each cov corresponds to */ int *nocc, /* Number of occurrences of each distinct combination */ int *whicha, /* indicator for the from, to, time lag, covs combination corresponding to the current obs */ int *obstype, /* observation scheme, 1 snapshot, 2 exact, 3 death */ /* Data for HMMs */ int *subjvec, /* vector of subject IDs */ double *timevec, /* vector of observation times */ double *obsvec, /* vector of observations (observed states in the case of misclassification models) */ int *firstobs, /* 0-based index into data of the first observation for each individual */ int *obstrue, /* which observations in a HMM represent the true underlying state (none by default) */ /* HMM specification */ int *hidden, /* well, is it or isn't it? */ int *hmodels, /* which hidden Markov distribution */ int *hnpars, /* number of basic HMM parameters for each state, not including covariate effects */ int *htotpars, /* total number of HMM parameters */ int *hfirstpar, /* index into hmmpars of first parameter for each state */ int *hncovs, /* number of covariate effects on each HMM parameter */ int *whichcovh, /* which column in the covariate data */ int *links, /* link function for each state distribution */ double *initprobs, /* initial state occupancy probabilities */ int *nicovs, /* number of covariate effects on these */ double *icoveffect, /* values of these effects */ int *whichcovi, /* which column in the covariate data */ int *nst, /* number of Markov states */ int *analyticp, /* should P matrix be calculated analytically */ int *iso, /* graph isomorphism ID */ int *perm, /* permutation to the base isomorphism */ int *qperm, /* permutation of intensity parameters from the base isomorphism */ int *nintens, /* number of intensity parameters */ int *ndintens, /* number of distinct intensity parameters */ int *ndcovpars, /* number of distinct covariate parameters */ int *nobs, /* number of observations in data set (hmm/cens) or number of aggregated transitions (standard) */ int *n, /* number of observations in data set (used for derivs by individual in standard models. no of rows of covobsvec) */ int *npts, /* number of individuals in data set */ int *ncovs, /* number of covariates on transition rates */ int *ncens, /* number of distinct forms of censoring */ int *censor, /* censoring indicators in data, of length ncens */ int *censstates, /* list of possible states represented by censoring indicators */ int *censstind, /* starting index into censstates for each censoring indicator */ int *qconstraint, /* constraints for baseline intensities. needed to calculate derivs */ int *cconstraint, /* constraints for covariates. needed to calculate derivs */ int *whichcovd, /* which covariate each _distinct_ covariate parameter corresponds to */ double *returned /* returned -2 log likelihood , Viterbi fitted values, or predicted values */ ) { msmdata d; qmodel qm; qcmodel qcm; cmodel cm; hmodel hm; d.fromstate = fromstate; d.tostate = tostate; d.timelag = timelag; d.cov = covvec; d.covobs = covobsvec; d.nocc = nocc; d.whicha = whicha; d.obstype = obstype; d.obstrue = obstrue; d.whichcov = whichcov; d.whichcovh = whichcovh; d.whichcovi=whichcovi; d.subject = subjvec; d.time = timevec; d.obs = obsvec; d.firstobs = firstobs; d.nobs = *nobs; d.n = *n; d.npts = *npts; qm.nst = *nst; qm.npars = *nintens; qm.ndpars = *ndintens; qm.ivector = qvector; qm.intens = intens; qm.analyticp = *analyticp; qm.iso = *iso; qm.perm = perm; qm.qperm = qperm; qm.constr = qconstraint; qcm.ncovs = ncovs; qcm.coveffect = coveffect; qcm.constr = cconstraint; qcm.ndpars = *ndcovpars; qcm.wcov = whichcovd; cm.ncens = *ncens; cm.censor = censor; cm.censstates=censstates; cm.censstind=censstind; hm.hidden = *hidden; hm.models = hmodels; hm.npars = hnpars; hm.totpars = *htotpars; hm.firstpar = hfirstpar; hm.ncovs = hncovs; hm.pars = hmmpars; hm.coveffect = hcoveffect; hm.links = links; hm.initp = initprobs; hm.nicovs = nicovs; hm.icoveffect = icoveffect; if (*do_what == 0) { msmLikelihood(&d, &qm, &qcm, &cm, &hm, returned); } else if (*do_what == 1) { msmDLikelihood(&d, &qm, &qcm, &cm, &hm, returned); } else if (*do_what == 2) { Viterbi(&d, &qm, &qcm, &cm, &hm, returned); } else if (*do_what == 3) { msmDLikelihood_subj(&d, &qm, &qcm, &cm, &hm, returned); /* derivative of loglik by subject. used for score residuals */ } } msm/src/analyticp.c0000644000176000001440000015625412061401532014024 0ustar ripleyusers/* Analytic formulae for P(t) in terms of transition intensities, for selected 2, 3, 4 and 5-state models. These were derived using symbolic algebra software (Mathematica). Increases speed and stability by avoiding the numeric calculation of the matrix exponential. ### The numbered label gives the indices into the matrix of rates (vectorised by reading across rows) ### e.g. the 3-state model with qmatrix of the form ### well-disease, well-death, disease-death transitions allowed. ### *,1,1 ### 0,*,1 ### 0,0,* uses the function p3q124() ### Some models are isomorphic and use the same p?q? function. ### See .msm.graphs in R/constants.R for permutations. */ #include "msm.h" void p2q1(Matrix pmat, double t, vector intens, int *degen); void p2q12(Matrix pmat, double t, vector intens, int *degen); void p3q12(Matrix pmat, double t, vector intens, int *degen); void p3q14(Matrix pmat, double t, vector intens, int *degen); void p3q16(Matrix pmat, double t, vector intens, int *degen); void p3q124(Matrix pmat, double t, vector intens, int *degen); void p3q135(Matrix pmat, double t, vector intens, int *degen); void p3q1246(Matrix pmat, double t, vector intens, int *degen); void p4q159(Matrix pmat, double t, vector intens, int *degen); void p4q13569(Matrix pmat, double t, vector intens, int *degen); void p5q1_6_11_16(Matrix pmat, double t, vector intens, int *degen); void p5q1_4_6_8_11_12_16(Matrix pmat, double t, vector intens, int *degen); void p5q1_6_7_11_12(Matrix pmat, double t, vector intens, int *degen); typedef void (*pfn)(Matrix pmat, double t, vector intens, int *degen); pfn P2FNS[] = { p2q1, p2q12 }; pfn P3FNS[] = { p3q12,p3q14,p3q16,p3q124,p3q135,p3q1246 }; pfn P4FNS[] = { p4q159,p4q13569 }; pfn P5FNS[] = { p5q1_6_11_16,p5q1_4_6_8_11_12_16,p5q1_6_7_11_12 }; void AnalyticP(Matrix pmat, double t, int nstates, int iso, int *perm, int *qperm, vector intens, int nintens, int *degen) { int i, j; vector intens_base = (vector) Calloc(nintens, double); Matrix pmat_base = (Matrix) Calloc( (nstates)*(nstates), double); for (i=0; i>= version <- gsub("Version: +", "", packageDescription("msm", lib.loc="~/work/msm")$Version) @ \title{Multi-state modelling with R: the {\tt msm} package \vskip 0.2in \large{Version % <>= cat(version) @ \vskip 0.1in <>= cat(format(Sys.time(), "%d %B, %Y")) @ }} \author{Christopher Jackson\\Medical Research Council Biostatistics Unit\\Cambridge, U.K.\\ \texttt{chris.jackson@mrc-bsu.cam.ac.uk}} \date{} %% label with date when Rnw is compiled, not when tex is compiled. should be release date of package \bibliographystyle{unsrt} \begin{document} \maketitle \begin{abstract} The multi-state Markov model is a useful way of describing a process in which an individual moves through a series of states in continuous time. The \Rpackage{msm} package for R allows a general multi-state model to be fitted to longitudinal data. Data often consist of observations of the process at arbitrary times, so that the exact times when the state changes are unobserved. For example, the progression of chronic diseases is often described by stages of severity, and the state of the patient may only be known at doctor or hospital visits. Features of \Rpackage{msm} include the ability to model transition rates and hidden Markov output models in terms of covariates, and the ability to model data with a variety of observation schemes, including censored states. Hidden Markov models, in which the true path through states is only observed through some error-prone marker, can also be fitted. The observation is generated, conditionally on the underlying states, via some distribution. An example is a screening misclassification model in which states are observed with error. More generally, hidden Markov models can have a continuous response, with some arbitrary distribution, conditionally on the underlying state. This manual introduces the theory behind multi-state Markov and hidden Markov models, and gives a tutorial in the typical use of the \Rpackage{msm} package, illustrated by some typical applications to modelling chronic diseases. Much of the material in this manual is published, in a more concise form, in Journal of Statistical Software (2011) 38(8):1-29, \url{http://www.jstatsoft.org/v38/i08/} \end{abstract} \tableofcontents \clearpage \section{Multi-state models} \label{sec:multistate} \subsection{Introduction} \label{sec:intro} Figure~\ref{fig:multi} illustrates a multi-state model in continuous time. Its four states are labelled {\bf 1, 2, 3, 4}. At a time $t$ the individual is in state $S(t)$. The arrows show which transitions are possible between states. The next state to which the individual moves, and the time of the change, are governed by a set of {\em transition intensities} $q_{rs}(t, z(t))$ for each pair of states $r$ and $s$. The intensities may also depend on the time of the process $t$, or more generally a set of individual-specific or time-varying explanatory variables $z(t)$. The intensity represents the instantaneous risk of moving from state $r$ to state $s$: \begin{equation} \label{eq:multi:intensity} q_{rs}(t, z(t)) = \lim_{\delta t \rightarrow 0} P (S(t+\delta t) = s | S(t) = r) / \delta t \end{equation} The intensities form a matrix $Q$ whose rows sum to zero, so that the diagonal entries are defined by $q_{rr} = - \sum_{s \neq r} q_{rs}$. To fit a multi-state model to data, we estimate this transition intensity matrix. We concentrate on {\em Markov} models here. The Markov assumption is that future evolution only depends on the current state. That is, $q_{rs}(t, z(t), \mathcal{F}_t)$ is independent of $\mathcal{F}_t$, the observation history $\mathcal{F}_t$ of the process up to the time preceding $t$. See, for example, Cox and Miller\cite{cox:miller} for a thorough introduction to the theory of continuous-time Markov chains. \begin{figure}[p] \begin{center} \scalebox{0.4}{\includegraphics{figures/multistate}} \[ Q = \left( \begin{array}{llll} q_{11} & q_{12} & q_{13} & q_{14}\\ q_{21} & q_{22} & q_{23} & q_{24}\\ q_{31} & q_{32} & q_{33} & q_{34}\\ q_{41} & q_{42} & q_{43} & q_{44}\\ \end{array} \right ) \] \caption{\label{fig:multi}General multi-state model.} \end{center} \end{figure} In a continuous-time Markov model, a single period of occupancy (or \emph{sojourn time}) in state $r$ has an exponential distribution, with rate given by $-q_{rr}$, (or mean $-1 / q_{rr}$). The remaining elements of the $r$th row of $Q$ are \emph{proportional to} the probabilities governing the next state after $r$ to which the individual makes a transition. The probability that the individual's next move from state $r$ is to state $s$ is $-q_{rs} / q_{rr}$. \subsection{Disease progression models} The development of the \Rpackage{msm} package was motivated by applications to disease modelling. Many chronic diseases have a natural interpretation in terms of staged progression. Multi-state Markov models in continuous time are often used to model the course of diseases. A commonly-used model is illustrated in Figure~\ref{fig:disease}. This represents a series of successively more severe disease stages, and an `absorbing' state, often death. The patient may advance into or recover from adjacent disease stages, or die at any disease stage. Observations of the state $S_i(t)$ are made on a number of individuals $i$ at arbitrary times $t$, which may vary between individuals. The stages of disease may be modelled as a homogeneous continuous-time Markov process, with a transition matrix $Q$, pictured below Figure~\ref{fig:disease}. A commonly-used model is the \emph{illness-death} model, with three states representing health, illness and death (Figure~\ref{fig:multi:illdeath}). Transitions are permitted from health to illness, illness to death and health to death. Recovery from illness to health is sometimes also considered. A wide range of medical situations have been modelled using multi-state methods, for example, screening for abdominal aortic aneurysms (Jackson \etal\cite{jackson:sharples:2003}), problems following lung transplantation (Jackson and Sharples\cite{jackson:sharples:2002}), problems following heart transplantation (Sharples\cite{sharp:gibbs}, Klotz and Sharples\cite{klotz:est}), hepatic cancer (Kay\cite{kay:mark}), HIV infection and AIDS (Longini \etal\cite{long1}, Satten and Longini\cite{sattlong}, Guihenneuc-Jouyaux \etal\cite{rich}, Gentleman \etal\cite{gentlaw}), diabetic complications (Marshall and Jones\cite{retino2}, Andersen\cite{andersen88}), breast cancer screening (Duffy and Chen\cite{duffy95}, Chen \emph{et al.}\cite{duffy96}), cervical cancer screening (Kirby and Spiegelhalter\cite{kirby:spiegelhalter}) and liver cirrhosis (Andersen \etal\cite{ander:proth}). Many of these references also describe the mathematical theory, which will be reviewed in the following sections. \begin{figure}[p] \centering \vskip 1cm \scalebox{1.0}{\includegraphics{figures/general}} \[ Q = \left( \begin{array}{llllll} q_{11} & q_{12} & 0 & 0 & \ldots & q_{1n}\\ q_{21} & q_{22} & q_{23} & 0 & \ldots & q_{2n}\\ 0 & q_{32} & q_{33} & q_{34} & \ddots & q_{3n}\\ 0 & 0 & q_{43} & q_{44} & \ddots & q_{4n}\\ \vdots & \vdots & \ddots & \ddots & \ddots & \vdots\\ 0 & 0 & 0 & 0 & \ldots & 0\\ \end{array} \right ) \] \caption{\label{fig:disease}General model for disease progression.} \end{figure} \begin{figure}[p] \begin{center} \scalebox{0.4}{\includegraphics{figures/illdeath}} \caption{Illness-death model.} \label{fig:multi:illdeath} \end{center} \end{figure} \subsection{Arbitrary observation times} \label{sec:arbitr-observ-times} Longitudinal data from monitoring disease progression are often incomplete in some way. Usually patients are seen at intermittent follow-up visits, at which monitoring information is collected, but information from the periods between visits is not available. Often the exact time of disease onset is unknown. Thus, the changes of state in a multi-state model usually occur at unknown times. Also a subject may only be followed up for a portion of their disease history. A fixed observation schedule may be specified in advance, but in practice times of visits may vary due to patient and hospital pressures. The states of disease progression models often include death. Death times are commonly recorded to within a day. Also observations may be censored. For example, at the end of a study, an individual may be known only to be alive, and in an unknown state. A typical sampling situation is illustrated in Figure~\ref{fig:multi:sampling}. The individual is observed at four occasions through 10 months. The final occasion is the death date which is recorded to within a day. The only other information available is the occupation of states 2, 2, and 1 at respective times 1.5, 3.5 and 5. The times of movement between states and the state occupancy in between the observation times are unknown. Although the patient was in state 3 between 7 and 9 months this was not observed at all. \paragraph{Informative sampling times} To fit a model to longitudinal data with arbitrary sampling times we must consider the reasons why observations were made at the given times. This is analogous to the problem of missing data, where the fact that a particular observation is missing may implicitly give information about the value of that observation. Possible observation schemes include: \begin{itemize} \item {\em fixed}. Each patient is observed at fixed intervals specified in advance. \item {\em random}. The sampling times vary randomly, independently of the current state of the disease. \item {\em doctor's care}. More severely ill patients are monitored more closely. The next sampling time is chosen on the basis of the current disease state. \item patient {\em self-selection}. A patient may decide to visit the doctor on occasions when they are in a poor condition. \end{itemize} Gr\"uger \etal~\cite{gruger:valid} discussed conditions under which sampling times are \emph{informative}. If a multi-state model is fitted, ignoring the information available in the sampling times, then inference may be biased. Mathematically, because the sampling times are often themselves random, they should be modelled along with the observation process $X_t$. However the ideal situation is where the joint likelihood for the times and the process is proportional to the likelihood obtained if the sampling times were fixed in advance. Then the parameters of the process can be estimated independently of the parameters of the sampling scheme. In particular, they showed that fixed, random and doctor's care observation policies are not informative, whereas patient self-selection is informative. \begin{figure}[p] \begin{center} \scalebox{0.6}{\rotatebox{270}{\includegraphics{figures/sampling}}} \caption{Evolution of a multi-state model. The process is observed on four occasions.} \label{fig:multi:sampling} \end{center} \end{figure} \subsection{Likelihood for the multi-state model} \label{sec:multi:likelihood} Kalbfleisch and Lawless\cite{kalbfleisch:lawless} and later Kay~\cite{kay:mark} described a general method for evaluating the likelihood for a general multi-state model in continuous time, applicable to any form of transition matrix. The only available information is the observed state at a set of times, as in Figure~\ref{fig:multi:sampling}. The sampling times are assumed to be non-informative. \paragraph{Transition probability matrix} The likelihood is calculated from the \emph{transition probability matrix} $P(t)$. For a time-homogeneous process, the $(r,s)$ entry of $P(t)$, $p_{rs}(t)$, is the probability of being in state $s$ at a time $t+u$ in the future, given the state at time $u$ is $r$. It does not say anything about the time of transition from $r$ to $s$, indeed the process may have entered other states between times $u$ and $t+u$. $P(t)$ can be calculated by taking the matrix exponential of the scaled transition intensity matrix (see, for example, Cox and Miller~\cite{cox:miller}). \begin{equation} \label{eq:exptq} P(t) = \Exp(tQ) \end{equation} The matrix exponential $\Exp$ is different from a scalar exponential. The exponential of a matrix is defined by the same "power series" $\Exp(X) = 1 + X^2/2! + X^3/3! + ...$ as the scalar exponential, except that each term $X^k$ in the series is defined by matrix products, not element-wise scalar multiplication. It is notoriously difficult to calculate reliably, as discussed by Moler and van Loan~\cite{matrixexp}. For simpler models, it is feasible to calculate an analytic expression for each element of $P(t)$ in terms of $Q$. This is generally faster and avoids the potential numerical instability of calculating the matrix exponential. Symbolic algebra sofware, such as Mathematica, can be helpful for obtaining these expressions. For example, the three-state illness-death model with no recovery has a transition intensity matrix of \[ Q = \left( \begin{array}{llllll} -(q_{12} + q_{13}) & q_{12} & q_{13}\\ 0 & - q_{23} & q_{23}\\ 0 & 0 & 0\\ \end{array} \right ) \] The corresponding time $t$ transition probabilities are \begin{eqnarray*} p_{11}(t) & = & e^{-(q_{12} + q_{13})t}\\ p_{12}(t) & = & \left\{ \begin{array}{ll} \frac{ q_{12}(-1 + e^{(q_{12}+q_{13}-q_{23})t})e^{-(q_{12}+q_{13})t} } { (q_{12} + q_{13} - q_{23}) } & (q_{12} + q_{13} \neq q_{23})\\ q_{12}te^{(-(q_{12} + q_{13})t} & (q_{12} + q_{13} = q_{23}) \end{array} \right. \\ p_{13}(t) & = & \left\{ \begin{array}{ll} \frac{1 + (-q_{13} + q_{23})e^{-(q_{12}+q_{13})t}} {q_{12} + q_{13} - q_{23}} - \frac { q_{12}e^{-q_{23}t}} {q_{12} + q_{13} - q_{23} } & (q_{12} + q_{13} \neq q_{23})\\ (-1 + e^{(q_{12} + q_{13})t} - q_{12}t)e^{-(q_{12} + q_{13})t} & (q_{12} + q_{13} = q_{23}) \end{array} \right. \\ p_{21}(t) & = & 0\\ p_{22}(t) & = & e^{-q_{23}t}\\ p_{23}(t) & = & 1 - e^{-q_{23}t}\\ p_{31}(t) & = & 0\\ p_{32}(t) & = & 0\\ p_{33}(t) & = & 1\\ \end{eqnarray*} The \Rpackage{msm} package calculates $P(t)$ analytically for selected 2, 3, 4 and 5-state models. These models are illustrated in Figures~\ref{fig:anp2}--\ref{fig:anp5}. For other models, $P(t)$ is determined from the matrix exponential, calculated using eigensystem decomposition (if eigenvalues are distinct) or a method based on Pad\'e approximants with scaling and squaring~\cite{matrixexp} (if there are repeated eigenvalues). Notice that the states are not labelled in these figures. Each graph can correspond to several different $Q$ matrices, depending on how the states are labelled. For example, Figure 1 a) illustrates the model defined by either \( Q = \left( \begin{array}{ll} - q_{12} & q_{12} \\ 0 & 0 \end{array} \right) \) or \( Q = \left( \begin{array}{ll} 0 & 0\\ q_{21} & - q_{21} \end{array} \right) \). \begin{figure} \begin{center} a) \includegraphics[width=3cm]{figures/p2q1} \hskip 3cm b) \includegraphics[width=3cm]{figures/p2q12} \end{center} \caption{\label{fig:anp2}Two-state models fitted using analytic $P(t)$ matrices in \Rpackage{msm}. Implemented for all permutations of state labels 1, 2.} \end{figure} \begin{figure} \begin{center} a) \includegraphics[width=3cm]{figures/p3q12} \hskip 3cm b) \includegraphics[width=5cm]{figures/p3q14} \vskip 1cm c) \includegraphics[width=3cm]{figures/p3q16}\hskip 3cm d) \includegraphics[width=3cm]{figures/p3q124}\vskip 1cm e) \includegraphics[width=3cm]{figures/p3q135}\hskip 3cm f) \includegraphics[width=3cm]{figures/p3q1246} \end{center} \caption{\label{fig:anp3}Three-state models fitted using analytic $P(t)$ matrices in \Rpackage{msm}. Implemented for all permutations of state labels 1, 2, 3.} \end{figure} \begin{figure} \begin{center} a) \includegraphics[width=7cm]{figures/p4q159} \vskip 1cm b) \includegraphics[width=7cm]{figures/p4q13569} \end{center} \caption{\label{fig:anp4}Four-state models fitted using analytic $P(t)$ matrices in \Rpackage{msm}. Implemented for all permutations of state labels 1, 2, 3, 4.} \end{figure} \begin{figure} \begin{center} a) \includegraphics[width=9cm]{figures/p5q1_6_11_16}\vskip 1cm b) \includegraphics[width=9cm]{figures/p5q1_4_6_8_11_12_16}\vskip 1cm c) \includegraphics[width=5cm]{figures/p5q1_6_7_11_12} \end{center} \caption{\label{fig:anp5}Five-state models fitted using analytic $P(t)$ matrices in \Rpackage{msm}. Implemented for all permutations of state labels 1, 2, 3, 4, 5.} \end{figure} \paragraph{Likelihood for intermittently-observed processes} Suppose $i$ indexes $M$ individuals. The data for individual $i$ consist of a series of times $(t_{i1}, \ldots, t_{in_i})$ and corresponding states $(S(t_{i1}), \ldots, S(t_{in_i}))$. Consider a general multi state model, with a pair of successive observed disease states $S(t_j), S(t_{j+1})$ at times $t_j, t_{j+1}$. The contribution to the likelihood from this pair of states is \begin{equation} \label{eq:multi:lik:contrib} L_{i, j} = p_{S(t_j)S(t_{j+1})}(t_{j+1} - t_j) \end{equation} This is the entry of the transition matrix $P(t)$ at the $S(t_j)$th row and $S(t_{j+1})$th column, evaluated at $t = t_{j+1} - t_j$. The full likelihood $L(Q)$ is the product of all such terms $L_{i,j}$ over all individuals and all transitions. It depends on the unknown transition matrix $Q$, which was used to determine $P(t)$. \paragraph{Death states} In observational studies of chronic diseases, it is common that the time of death is known, but the state on the previous instant before death is unknown. If $S(t_{j+1}) = D $ is such a death state, then the contribution to the likelihood is summed over the unknown state $m$ on the instant before death: \begin{equation} \label{eq:multi:lik:death} L_{i, j} = \sum_{m \neq D} p_{S(t_j),m}(t_{j+1} - t_j) q_{m, D} \end{equation} The sum is taken over all possible states $m$ which can be visited between $S(t_j)$ and $D$. \paragraph{Exactly observed transition times} If the times $(t_{i1}, \ldots, t_{in_i})$ had been the {\em exact} transition times between the states, with no transitions between the observation times, then the contributions would be of the form \begin{equation} \label{eq:multi:lik:exact} L_{i, j} = \exp(-q_{S(t_j)S(t_{j})}(t_{j+1} - t_j)) q_{S(t_j)S(t_{j+1})} \end{equation} since the state is assumed to be $S(t_j)$ throughout the interval between $t_j$ and $t_{j+1}$ with a known transition to state $S(t_{j+1})$ at $t_{j+1}$. \Rpackage{msm} is restricted to Markov models, but much richer models are possible for this type of data. For example, Putter \etal~\cite{putter:mstate} discussed the \Rpackage{mstate} software for semi-parametric multi-state models with non-parametric baseline hazards and Cox regression. The Markov assumption is restrictive but necessary in general to compute a likelihood for intermittently-observed processes. \paragraph{Censored states} A censored quantity is one whose exact value is unknown, but known to be in a certain interval. For example, in survival analysis, a death time is \emph{right-censored} if the study ends and the patient is still alive, since the death time is known to be greater than the end time. In multi-state models for intermittently-observed processes, the times of changes of state are usually \emph{interval censored}, known to be within bounded intervals. This leads to a likelihood based on equation~\ref{eq:multi:lik:contrib}. In some circumstances, \emph{states} may be censored as well as \emph{event times}. For example, at the end of some chronic disease studies, patients are known to be alive but in an \emph{unknown state}. For such a censored observation $S(t_{j+1})$, known only to be a state in the set $C$, the equivalent contribution to the likelihood is \begin{equation} \label{eq:multi:lik:deathcens} L_{i, j} = \sum_{m \in C} p_{S(t_j),m}(t_{j+1} - t_j) \end{equation} Note that this special likelihood is not needed if the state is known at the end of the study. In this case, likelihood~\ref{eq:multi:lik:contrib} applies. Although the \emph{survival time} is censored, the \emph{state} at the end of the study is not censored. More generally, suppose every observation from a particular individual is censored. Observations $1, 2, \ldots n_i$ are known only to be in the sets $C_1, C_2, \ldots, C_{n_i}$ respectively. The likelihood for this individual is a sum of the likelihoods of all possible paths through the unobserved states. \begin{equation} \label{eq:multi:lik:cens} L_i = \sum_{s_{n_i} \in C_{n_i}} \ldots \sum_{s_2 \in C_2} \sum_{s_1 \in C_1} p_{s_1 s_2}(t_2 - t_1) p_{s_2 s_3} (t_3 - t_2) \ldots p_{s_{n_i-1} s_{n_i}} (t_{n_i} - t_{n_i-1}) \end{equation} Suppose the states comprising the set $C_j$ are $c^{(j)}_1, \ldots, c^{(j)}_{m_j}$. This likelihood can also be written as a matrix product, say, \begin{equation} \label{eq:multi:lik:cens:matrix} L_i = \mathbf{1}^T P^{1,2} P^{2,3} \ldots P^{n_i-1, n_i} \mathbf{1} \end{equation} where $P^{j-1, j}$ is a $m_{j-1} \times m_j$ matrix with $(r,s)$ entry $p_{c^{(j-1)}_r c^{(j)}_s}(t_j - t_{j-1})$, and $\mathbf{1}$ is the vector of ones. The \Rpackage{msm} package allows multi-state models to be fitted to data from processes with arbitrary observation times, exactly-observed transition times, ``death'' states and censored states, or a mixture of these schemes. \subsection{Covariates} \label{sec:multi:covariates} The relation of constant or time-varying characteristics of individuals to their transition rates is often of interest in a multi-state model. Explanatory variables for a particular transition intensity can be investigated by modelling the intensity as a function of these variables. Marshall and Jones~\cite{retino2} described a form of a {\em proportional hazards} model, where the transition intensity matrix elements $q_{rs}$ which are of interest can be replaced by \[ q_{rs}(z(t)) = q_{rs}^{(0)} \exp(\beta_{rs}^T z(t)) \] The new $Q$ is then used to determine the likelihood. If the covariates $z(t)$ are time dependent, the contributions to the likelihood of the form $p_{rs} (t - u)$ are replaced by \[ p_{rs}(t - u, z(u)) \] although this requires that the value of the covariate is known at every observation time $u$. Sometimes covariates are observed at different times to the main response, for example recurrent disease events or other biological markers. In some of these cases it could be assumed that the covariate is a step function which remains constant between its observation times. If the main response (the state of the Markov process) is not observed at the times when the covariate changes, it could be considered as a "censored" state (as in Section~\ref{sec:multi:likelihood}). The \Rpackage{msm} package allows individual-specific or time dependent covariates to be fitted to transition intensities. In order to calculate transition probabilities $P(t)$ on which the likelihood depends, time-dependent covariates are assumed to be piecewise-constant. Models whose intensities change with time are called \emph{time-inhomogeneous}. An important special case handled by \Rpackage{msm} is the model in which intensities change at a series of times common to each individual. Marshall and Jones~\cite{retino2} described likelihood ratio and Wald tests for covariate selection and testing hypotheses, for example whether the effect of a covariate is the same for all forward transitions in a disease progression model, or whether the effect on backward transitions is equal to minus the effect on forward transitions. \subsection{Hidden Markov models} \label{sec:hmm} In a {\em hidden Markov model} (HMM) the states of the Markov chain are not observed. The observed data are governed by some probability distribution (the \emph{emission} distribution) conditionally on the unobserved state. The evolution of the underlying Markov chain is governed by a transition intensity matrix $Q$ as before. (Figure~\ref{fig:multi:hidden}). Hidden Markov models are mixture models, where observations are generated from a certain number of unknown distributions. However the distribution changes through time according to states of a hidden Markov chain. This class of model is commonly used in areas such as speech and signal processing \cite{juang:rabiner} and the analysis of biological sequence data \cite{biolog:seq}. In engineering and biological sequencing applications, the Markov process usually evolves over an equally-spaced, discrete `time' space. Therefore most of the theory of HMM estimation was developed for discrete-time models. HMMs have less frequently been used in medicine, where continuous time processes are often more suitable. A disease process evolves in continuous time, and patients are often monitored at irregular and differing intervals. These models are suitable for estimating population quantities for chronic diseases which have a natural staged interpretation, but which can only be diagnosed by an error-prone marker. The \Rpackage{msm} package can fit continuous-time hidden Markov models with a variety of emission distributions. \begin{figure}[htbp] \begin{center} \scalebox{0.6}{\rotatebox{270}{\includegraphics{figures/hidden}}} \caption{A hidden Markov model in continuous time. Observed states are generated conditionally on an underlying Markov process. } \label{fig:multi:hidden} \end{center} \end{figure} \subsubsection{Misclassification models} An example of a hidden Markov model is a multi-state model with misclassification. Here the observed data are states, assumed to be misclassifications of the true, underlying states. For example, consider a disease progression model with at least a disease-free and a disease state. When screening for the presence of the disease, the screening process can sometimes be subject to error. Then the Markov disease process $S_i(t)$ for individual $i$ is not observed directly, but through realisations $O_i(t)$. The quality of a diagnostic test is often measured by the probabilities that the true and observed states are equal, $Pr(O_i(t) = r | S_i(t) = r)$. Where $r$ represents a `positive' disease state, this is the {\em sensitivity}, or the probability that a true positive is detected by the test. Where $r$ represents a `negative' or disease-free state, this represents the {\em specificity}, or the probability that, given the condition of interest is absent, the test produces a negative result. As an extension to the simple multi-state model described in section~\ref{sec:multistate}, the \Rpackage{msm} package can fit a general multi-state model with misclassification. For patient $i$, observation time $t_{ij}$, observed states $O_{ij}$ are generated conditionally on true states $S_{ij}$ according to a {\em misclassification matrix} $E$. This is a $n \times n$ matrix, whose $(r,s)$ entry is \begin{equation} \label{eq:misc} e_{rs} = Pr(O(t_{ij}) = s | S(t_{ij}) = r), \end{equation} which we first assume to be independent of time $t$. Analogously to the entries of $Q$, some of the $e_{rs}$ may be fixed to reflect knowledge of the diagnosis process. For example, the probability of misclassification may be negligibly small for non-adjacent states of disease. Thus the progression through underlying states is governed by the transition intensity matrix $Q$, while the observation process of the underlying states is governed by the misclassification matrix $E$. To investigate explanatory variables $w(t)$ for the probability $e_{rs}$ of misclassification as state $s$ given underlying state $r$, a multinomial logistic regression model can be used: \begin{equation} \label{eq:misccovs} \log \frac{e_{rs}(t)}{e_{rs_0}(t)} = \gamma_{rs}^T w(t). \end{equation} where $s_0$ is some baseline state, usually chosen as the underlying state, or the state with the highest probability (for numerical stability). \subsubsection{General hidden Markov model} \label{sec:hmm:general} Consider now a general hidden Markov model in continuous time. The true state of the model $S_{ij}$ evolves as an unobserved Markov process. Observed data $y_{ij}$ are generated conditionally true states $S_{ij} = 1, 2, \ldots, n$ according to a set of distributions $f_1(y | \theta_1, \gamma_1)$, $f_2(y | \theta_2, \gamma_2)$, $\ldots$, $f_n(y | \theta_n, \gamma_n)$, respectively. $\theta_r$ is a vector of parameters for the state $r$ distribution. One or more of these parameters may depend on explanatory variables through a link-transformed linear model with coefficients $\gamma_r$. \subsubsection{Likelihood for general hidden Markov models} A type of EM algorithm known as the {\em Baum-Welch} or {\em forward-backward} algorithm \cite{baum:petrie66, baum:petrie70}, is commonly used for hidden Markov model estimation in discrete-time applications. See, for example, Durbin \etal \cite{biolog:seq}, Albert \cite{albert99}. A generalisation of this algorithm to continuous time was described by Bureau \etal \cite{bureau:hughes:shiboski:00}. The \Rpackage{msm} package uses a direct method of calculating likelihoods in discrete or continuous time based on matrix products. This type of method has been described by Macdonald and Zucchini \cite[pp. 77--79]{macdonald:zucchini}, Lindsey \cite[p.73]{lindsey:rm} and Guttorp \cite{guttorp}. Satten and Longini \cite{sattlong} used this method to calculate likelihoods for a hidden Markov model in continuous time with observations of a continuous marker generated conditionally on underlying discrete states. Patient $i$'s contribution to the likelihood is \begin{eqnarray} \label{eq:multi:hiddencontrib} L_i & = & Pr(y_{i1}, \ldots, y_{in_i})\\ & = & \sum Pr(y_{i1}, \ldots, y_{in_i} | S_{i1}, \ldots, S_{in_i}) Pr(S_{i1}, \ldots, S_{in_i}) \nonumber \end{eqnarray} where the sum is taken over all possible paths of underlying states $S_{i1}, \ldots, S_{in_i}$. Assume that the observed states are conditionally independent given the values of the underlying states. Also assume the Markov property, $Pr(S_{ij}|S_{i,j-1}, \ldots, S_{i1}) = Pr(S_{ij}|S_{i,j-1})$. Then the contribution $L_i$ can be written as a product of matrices, as follows. To derive this matrix product, decompose the overall sum in equation~\ref{eq:multi:hiddencontrib} into sums over each underlying state. The sum is accumulated over the unknown first state, the unknown second state, and so on until the unknown final state: \begin{eqnarray} \label{eq:multi:hiddenlik} L_i & = & \sum_{S_{i1}} Pr(y_{i1}|S_{i1})Pr(S_{i1}) \sum_{S_{i2}} Pr(y_{i2}|S_{i2})Pr(S_{i2}|S_{i1}) \sum_{S_{i3}} Pr(y_{i3}|S_{i3}) Pr(S_{i3}|S_{i2}) \nonumber \\ & & \ldots \sum_{S_{in_i}} Pr(y_{in_i}|S_{in_i}) Pr(S_{in_i}|S_{in_{i-1}}) \end{eqnarray} where $Pr(y_{ij}|S_{ij})$ is the emission probability density. For misclassification models, this is the misclassification probability $e_{S_{ij} O_{ij}}$. For general hidden Markov models, this is the probability density $f_{S_{ij}}(y_{ij}|\theta_{S_{ij}},\gamma_{S_{ij}})$. $Pr(S_{i,j+1}|S_{ij})$ is the $(S_{ij}, S_{i,j+1})$ entry of the Markov chain transition matrix $P(t)$ evaluated at $t = t_{i,j+1} - t_{ij}$. Let $f$ be the vector with $r$ element the product of the initial state occupation probability $Pr(S_{i1}=r)$ and $Pr(y_{i1}| r)$, and let $\mathbf 1$ be a column vector consisting of ones. For $j = 2, \ldots, n_i$ let $T_{ij}$ be the $R \times R$ matrix (where $R$ is the number of states) with $(r,s)$ entry \[ Pr(y_{ij}| s) p_{rs} (t_{ij} - t_{i,j-1}) \] Then subject $i$'s likelihood contribution is \begin{equation} L_i = f T_{i2} T_{i3}, \ldots T_{in_i} \mathbf 1 \label{eq:multi:hidden:matprod} \end{equation} If $S(t_{j}) = D$ is an absorbing state such as death, measured without error, whose entry time is known exactly, then the contribution to the likelihood is summed over the unknown state at the previous instant before death. The $(r,s)$ entry of $T_{ij}$ is then \[ p_{rs}(t_{j} - t_{j-1}) q_{s, D} \] Section~\ref{sec:fitting:hmm:misc} describes how to fit multi-state models with misclassification using the \Rpackage{msm} package, and Section~\ref{sec:fitting:hmm:general} describes how to apply general hidden Markov models. \subsubsection{Example of a general hidden Markov model} \label{sec:hmm:example:fev} Jackson and Sharples~\cite{jackson:sharples:2002} described a model for FEV$_1$ (forced expiratory volume in 1 second) in recipients of lung transplants. These patients were at risk of BOS (bronchiolitis obliterans syndrome), a progressive, chronic deterioration in lung function. In this example, BOS was modelled as a discrete, staged process, a model of the form illustrated in Figure~\ref{fig:disease}, with 4 states. State 1 represents absence of BOS. State 1 BOS is roughly defined as a sustained drop below 80\% below baseline FEV$_1$, while state 2 BOS is a sustained drop below 65\% baseline. FEV$_1$ is measured as a percentage of a baseline value for each individual, determined in the first six months after transplant, and assumed to be 100\% baseline at six months. As FEV$_1$ is subject to high short-term variability due to acute events and natural fluctuations, the exact BOS state at each observation time is difficult to determine. Therefore, a hidden Markov model for FEV$_1$, conditionally on underlying BOS states, was used to model the natural history of the disease. Discrete states are appropriate as onset is often sudden. \paragraph{Model 1} Jackson~\cite{my:phd} considered models for these data where FEV$_1$ were Normally distributed, with an unknown mean and variance conditionally each state~(\ref{eq:fev:normal}). This model seeks the most likely location for the within-state FEV$_1$ means. \begin{equation} \label{eq:fev:normal} y_{ij} | \{ S_{ij} = k\} \sim N(\mu_k + \beta x_{ij}, \sigma^2_k) \end{equation} \paragraph{Model 2} Jackson and Sharples~\cite{jackson:sharples:2002} used a more complex two-level model for FEV$_1$ measurements. Level 1~(\ref{eq:fev:level1}) represents the short-term fluctuation error of the marker around its underlying continuous value $y^{hid}_{ij}$. Level 2~(\ref{eq:fev:level2}) represents the distribution of $y^{hid}_{ij}$ conditionally on each underlying state, as follows. \begin{equation} \label{eq:fev:level1} y_{ij} | y^{hid}_{ij} \qquad \sim N ( y^{hid}_{ij} + \beta x_{ij} , \sigma^2_\epsilon) \end{equation} \begin{equation} \label{eq:fev:level2} y^{hid}_{ij} | S_{ij} \quad \sim \quad \left\{ \begin{array}{cll} \mbox{State}& \mbox{Three state model} & \mbox{Four state model} \\ S_{ij} = 0 & N(\mu_0, \sigma^2_0)I_{[80, \infty)} & N(\mu_0, \sigma^2_0)I_{[80, \infty)} \\ S_{ij} = 1 & N(\mu_1, \sigma^2_1)I_{(0, 80)} & Uniform(65, 80) \\ S_{ij} = 2 & \mbox{(death)} & N(\mu_2, \sigma^2_2)I_{(0, 65)} \\ S_{ij} = 3 & & \mbox{(death)} \end{array} \right . \end{equation} Integrating over $y^{hid}_{ij}$ gives an explicit distribution for $y_{ij}$ conditionally on each underlying state (given in Section~\ref{sec:fitting:hmm:general}, Table~\ref{tab:hmm:dists}). Similar distributions were originally applied by Satten and Longini~\cite{sattlong} to modelling the progression through discrete, unobserved HIV disease states using continuous CD4 cell counts. The \Rpackage{msm} package includes density, quantile, cumulative density and random number generation functions for these distributions. In both models 1 and 2, the term $\beta x_{ij}$ models the short-term fluctuation of the marker in terms of acute events. $x_{ij}$ is an indicator for the occurrence of an acute rejection or infection episode within 14 days of the observation of FEV$_1$. Section~\ref{sec:fitting:hmm:general} describes how these and more general hidden Markov models can be fitted with the \Rpackage{msm} package. \clearpage \section{Fitting multi-state models with {\tt msm}} <>= options(width = 60) @ \Rpackage{msm} is a package of functions for multi-state modelling using the R statistical software. The \Rfunction{msm} function itself implements maximum-likelihood estimation for general multi-state Markov or hidden Markov models in continuous time. We illustrate its use with a set of data from monitoring heart transplant patients. Throughout this section ``\textsl{\texttt{>}}'' indicates the R command prompt, \textsl{\texttt{slanted typewriter}} text indicates R commands, and \texttt{typewriter} text R output. \subsection{Installing \tt{msm}} \label{sec:installing} The easiest way to install the \Rpackage{msm} package on a computer connected to the Internet is to run the R command: \begin{Scode} install.packages("msm") \end{Scode} This downloads \Rpackage{msm} from the CRAN archive of contributed R packages (\texttt{cran.r-project.org} or one of its mirrors) and installs it to the default R system library. To install to a different location, for example if you are a normal user with no administrative privileges, create a directory in which R packages are to be stored, say, \texttt{/your/library/dir}, and run \begin{Scode} install.packages("msm", lib='/your/library/dir') \end{Scode} After \Rpackage{msm} has been installed, its functions can be made visible in an R session by <<>>= library(msm) @ or, if it has been installed into a non-default library, \begin{Scode} library(msm, lib.loc='/your/library/dir') \end{Scode} \subsection{Getting the data in} \label{sec:datain} The data are specified as a series of observations, grouped by patient. At minimum there should be a data frame with variables indicating \begin{itemize} \item the time of the observation, \item the observed state of the process. \end{itemize} If the data do not also contain \begin{itemize} \item the subject identification number, \end{itemize} then all the observations are assumed to be from the same subject. The subject ID does not need to be numeric, but data must be grouped by subject, and observations must be ordered by time within subjects. An example data set, taken from monitoring a set of heart transplant recipients, is provided with \Rpackage{msm}. Sharples \etal~\cite{my:cav} studied the progression of coronary allograft vasculopathy (CAV), a post-transplant deterioration of the arterial walls, using these data. Risk factors and the accuracy of the screening test were investigated using multi-state Markov and hidden Markov models. This data set can be made available to the current R session by issuing the command <<>>= data(cav) @ The first three patient histories are shown below. There are 622 patients in all. \Robject{PTNUM} is the subject identifier. Approximately each year after transplant, each patient has an angiogram, at which CAV can be diagnosed. The result of the test is in the variable \Robject{state}, with possible values 1, 2, 3 representing CAV-free, mild CAV and moderate or severe CAV respectively. A value of 4 is recorded at the date of death. \Robject{years} gives the time of the test in years since the heart transplant. Other variables include \Robject{age} (age at screen), \Robject{dage} (donor age), \Robject{sex} (0=male, 1=female), \Robject{pdiag} (primary diagnosis, or reason for transplant - IHD represents ischaemic heart disease, IDC represents idiopathic dilated cardiomyopathy), \Robject{cumrej} (cumulative number of rejection episodes), and \Robject{firstobs}, an indicator which is 1 when the observation corresponds to the patient's transplant (the first observation), and 0 when the observation corresponds to a later angiogram. <<>>= cav[1:21,] @ A useful way to summarise multi-state data is as a frequency table of pairs of consecutive states. This counts over all individuals, for each state $r$ and $s$, the number of times an individual had an observation of state $r$ followed by an observation of state $s$. The function \Rfunction{statetable.msm} can be used to produce such a table, as follows, <<>>= statetable.msm(state, PTNUM, data=cav) @ Thus there were 148 CAV-free deaths, 48 deaths from state 2, and 55 deaths from state 3. On only four occasions was there an observation of severe CAV followed by an observation of no CAV. \subsection{Specifying a model} \label{sec:specifying:model} We now specify the multi-state model to be fitted to the data. A model is governed by a transition intensity matrix $Q$. For the heart transplant example, there are four possible states through which the patient can move, corresponding to CAV-free, mild/moderate CAV, severe CAV and death. We assume that the patient can advance or recover from consecutive states while alive, and die from any state. Thus the model is illustrated by Figure~\ref{fig:disease} with four states, and we have \[ Q = \left( \begin{array}{llll} -(q_{12} + q_{14}) & q_{12} & 0 & q_{14}\\ q_{21} & -(q_{21}+q_{23}+q_{24}) & q_{23} & q_{24}\\ 0 & q_{32} & -(q_{32}+q_{34}) & q_{34}\\ 0 & 0 & 0 & 0 \\ \end{array} \right ) \] It is important to remember that this defines which \emph{instantaneous} transitions can occur in the Markov process, and that the data are \emph{snapshots} of the process (see section~\ref{sec:arbitr-observ-times}). Although there were 44 occasions on which a patient was observed in state 1 followed by state 3, the underlying model specifies that the patient must have passed through state 2 in between. If your data represent the exact and complete transition times of the process, then you must specify \Rfunarg{exacttimes=TRUE} or \Rfunarg{obstype=2} in the call to \Rfunction{msm}. To tell \Rfunction{msm} what the allowed transitions of our model are, we define a matrix of the same size as $Q$, containing zeroes in the positions where the entries of $Q$ are zero. All other positions contain an initial value for the corresponding transition intensity. The diagonal entries supplied in this matrix do not matter, as the diagonal entries of $Q$ are defined as minus the sum of all the other entries in the row. This matrix will eventually be used as the \Rfunarg{qmatrix} argument to the \Rfunction{msm} function. For example, <<>>= twoway4.q <- rbind ( c(0, 0.25, 0, 0.25), c(0.166, 0, 0.166, 0.166), c(0, 0.25, 0, 0.25), c(0, 0, 0, 0) ) @ Fitting the model is a process of finding values of the seven unknown transition intensities: $q_{12}$, $q_{14}$, $q_{21}$, $q_{23}$, $q_{24}$, $q_{32}$, $q_{34}$, which maximise the likelihood. \subsection{Specifying initial values} \label{sec:inits} The likelihood is maximised by numerical methods, which need a set of initial values to start the search for the maximum. For reassurance that the true maximum likelihood estimates have been found, models should be run repeatedly starting from different initial values. However a sensible choice of initial values can be important for unstable models with flat or multi-modal likelihoods. For example, the transition rates for a model with misclassification could be initialised at the corresponding estimates for an approximating model without misclassification. Initial values for a model without misclassification could be set by supposing that transitions between states take place only at the observation times. If we observe $n_{rs}$ transitions from state $r$ to state $s$, and a total of $n_r$ transitions from state $r$, then $q_{rs} / q_{rr}$ can be estimated by $n_{rs} / n_r$. Then, given a total of $T_r$ years spent in state $r$, the mean sojourn time $1 / q_{rr}$ can be estimated as $T_r / n_r$. Thus, $n_{rs} / T_r$ is a crude estimate of $q_{rs}$. The \Rpackage{msm} package provides a function \Rfunction{crudeinits.msm} for calculating initial values in this way. <<>>= twoway4.crude.q <- crudeinits.msm(state ~ years, PTNUM, data=cav, qmatrix=twoway4.q) @ However, if there are are many changes of state in between the observation times, then this crude approach may fail to give sensible initial values. For the heart transplant example we could also guess that the mean period in each state before moving to the next is about 2 years, and there is an equal probability of progression, recovery or death. This gives $q_{rr} = - 0.5$ for $r = 1, 2, 3$, and $q_{12} = q_{14} = 0.25$, $q_{21} = q_{23} = q_{24} = 0.166$, $q_{32} = q_{34} = 0.25$, and the initial value matrix \Robject{twoway4.q} shown above, which we now use to fit the model. %% TODO explain about gen.inits=TRUE here \subsection{Running \Rfunction{msm}} \label{sec:running} To fit the model, call the \Rfunction{msm} function with the appropriate arguments. For our running example, we have defined a data set \Robject{cav}, a matrix \Robject{twoway4.q} indicating the allowed transitions, and initial values. We are ready to run \Rfunction{msm}. \paragraph{Model 1: simple bidirectional model} <<>>= cav.msm <- msm( state ~ years, subject=PTNUM, data = cav, qmatrix = twoway4.q, death = 4 ) @ In this example the day of death is assumed to be recorded exactly, as is usual in studies of chronic diseases. At the previous instant before death the state of the patient is unknown. Thus we specify \Rfunarg{death = 4}, to indicate to \Rfunction{msm} that state 4 is a ``death'' state. In terms of the multi-state model, a ``death'' state is assumed to have a known entry time, but the individual is in an unknown transient state at the previous instant. If the model had five states and states 4 and 5 were two competing causes of death with death times recorded exactly, then we would specify \Rfunarg{death = c(4,5)}. By default, the data are assumed to represent snapshots of the process at arbitrary times. However, observations can also represent exact times of transition, ``death'' times, or a mixture of these. See the \Rfunarg{obstype} argument to \Rfunction{msm}. While the \Rfunction{msm} function runs, it searches for the maximum of the likelihood of the unknown parameters. Internally, it uses the R function \Rfunction{optim} to minimise the minus log-likelihood. When the data set, the model, or both, are large, then this may take a long time. It can then be useful to see the progress of the optimisation algorithm. To do this, we can specify a \Rfunarg{control} argument to \Rfunction{msm}, which is passed internally to the \Rfunction{optim} function. For example \texttt{control = list(trace=1, REPORT=1)}. See the help page for \Rfunction{optim}, <>= help(optim) @ for more options to control the optimisation. When completed, the \Rfunction{msm} function returns a value. This value is a list of the important results of the model fitting, including the parameter estimates and their covariances. To keep these results for post-processing, we store them in an R object, here called \Robject{cav.msm}. When running several similar \Rfunction{msm} models, it is recommended to store the respective results in informatively-named objects. \subsection{Showing results} To show the maximum likelihood estimates and 95\% confidence intervals, type the name of the fitted model object at the R command prompt. \footnote{This is equivalent to typing \texttt{print.msm(cav.msm)}. The function \Rfunction{print.msm} formats the important information in the model object for printing on the screen.} The confidence level can be changed using the \Rfunarg{cl} argument to \Rfunction{msm}. <<>>= cav.msm @ From the estimated intensity matrix, we see patients are three times as likely to develop symptoms than die without symptoms (first row). After disease onset (state 2), progression to severe symptoms (state 3) is 50\% more likely than recovery. Once in the severe state, death is more likely than recovery, and a mean of 1 / -0.44 = 2.3 years is spent in state 3 before death or recovery. Section \ref{sec:extractor} describes various functions that can be used to obtain summary information from the fitted model. \subsection{Covariates on the transition rates} \label{sec:msm:covariates} We now model the effect of explanatory variables on the rates of transition, using a proportional intensities model. Now we have an intensity matrix $Q(z)$ which depends on a covariate vector $z$. For each entry of $Q(z)$, the transition intensity for patient $i$ at observation time $j$ is $q_{rs}(z_{ij}) = q_{rs}^{(0)} \exp(\beta_{rs}^T z_{ij})$. The covariates $z$ are specified through the \Rfunarg{covariates} argument to \Rfunction{msm}. If $z_{ij}$ is time-dependent, we assume it is constant in between the observation times of the Markov process. \Rfunction{msm} calculates the probability for a state transition from times $t_{i,j-1}$ to $t_{ij}$ using the covariate value at time $t_{i,j-1}$. We consider a model with just one covariate, female sex. Out of the 622 transplant recipients, 535 are male and 87 are female. By default, all linear covariate effects $\beta_{rs}$ are initialised to zero. To specify different initial values, use a \Rfunarg{covinits} argument, as described in \Rfunction{help(msm)}. Initial values given in the \Rfunarg{qmatrix} represent the intensities with covariate values set to their means in the data. \paragraph{Model 2: sex as a covariate} <<>>= cavsex.msm <- msm( state ~ years, subject=PTNUM, data = cav, qmatrix = twoway4.q, death = 4, covariates = ~ sex) @ The \Robject{msm} object will now include the estimated covariate effects and their confidence intervals. <<>>= cavsex.msm @ Comparing the estimated log-linear effects of sex and their standard errors, we see that the disease onset rate is smaller for females, whereas none of the other effects are significant. The first matrix shown in the output of printing \Robject{cavsex.msm} is the estimated transition intensity matrix $q_{rs}(z) = q_{rs}^{(0)} \exp(\beta_{rs}^T z)$ with the covariate $z$ set to its mean value in the data. This represents an average intensity matrix for the population of 535 male and 87 female patients. To extract separate intensity matrices for male and female patients ($z = 0$ and $1$ respectively), use the function \Rfunction{qmatrix.msm}, as shown below. This and similar summary functions will be described in more detail in section~\ref{sec:extractor}. <<>>= qmatrix.msm(cavsex.msm, covariates=list(sex=0)) # Male qmatrix.msm(cavsex.msm, covariates=list(sex=1)) # Female @ We may also want to constrain the effect of a covariate to be equal for certain transition rates, to reduce the number of parameters in the model, or to investigate hypotheses on the covariate effects. A \Rfunarg{constraint} argument can be used to indicate which of the transition rates have common covariate effects. \paragraph{Model 3: constrained covariate effects} <>= cav3.msm <- msm( state ~ years, subject=PTNUM, data = cav, qmatrix = twoway4.q, death = 4, covariates = ~ sex, constraint = list(sex=c(1,2,3,1,2,3,2)) ) @ This constrains the effect of sex to be equal for the progression rates $q_{12}, q_{23}$, equal for the death rates $q_{14}, q_{24}, q_{34}$, and equal for the recovery rates $q_{21}, q_{32}$. The intensity parameters are assumed to be ordered by reading across the rows of the transition matrix, starting at the first row: ($q_{12}, q_{14}, q_{21}, q_{23}, q_{24}, q_{32}, q_{34}$), giving constraint indicators \Rfunarg{(1,2,3,1,2,3,2)}. Any vector of increasing numbers can be used for the indicators. Negative entries can be used to indicate that some effects are equal to minus others: \Rfunarg{(1,2,3,-1,2,3,2)} sets the fourth effect to be minus the first. In a similar manner, we can constrain some of the baseline transition intensities to be equal to one another, using the \Rfunarg{qconstraint} argument. For example, to constrain the rates $q_{12}$ and $q_{23}$ to be equal, and $q_{24}$ and $q_{34}$ to be equal, specify \Rfunarg{qconstraint = c(1,2,3,1,4,5,4)}. \subsection{Fixing parameters at their initial values} For exploratory purposes we may want to fit a model assuming that some parameters are fixed, and estimate the remaining parameters. This may be necessary in cases where there is not enough information in the data to be able to estimate a proposed model, and we have strong prior information about a certain transition rate. To do this, use the \Rfunarg{fixedpars} argument to \Rfunction{msm}. For model 1, the following statement fixes the parameters numbered 6, 7, that is, $q_{32}$, $q_{34}$, to their initial values (0.25 and 0.25, respectively). \paragraph{Model 4: fixed parameters} <>= cav4.msm <- msm( state ~ years, subject=PTNUM, data = cav, qmatrix = twoway4.q, death = 4, control = list(trace=2, REPORT=1), fixedpars = c(6, 7) ) @ A \Rfunarg{fixedpars} statement can also be useful for fixing covariate effect parameters to zero, that is to assume no effect of a covariate on a certain transition rate. \subsection{Extractor functions} \label{sec:extractor} We may want to extract some of the information from the \Rfunction{msm} model fit for post-processing, for example for plotting graphs or generating summary tables. A set of functions is provided for extracting interesting features of the fitted model. \begin{description} \item[Intensity matrices] The function \Rfunction{qmatrix.msm} extracts the estimated transition intensity matrix and its confidence intervals for a given set of covariate values, as shown in section~\ref{sec:msm:covariates}. Confidence intervals are calculated from the covariance matrix of the estimates by assuming the distribution is symmetric on the log scale. Standard errors for the intensities are also available from the object returned by \Rfunction{qmatrix.msm}. These are calculated by the delta method. The \Rpackage{msm} package provides a general-purpose function \Rfunction{deltamethod} for estimating the variance of a function of a random variable $X$ given the expectation and variance of $X$. See \texttt{help(deltamethod)} for further details. Bootstrap confidence intervals are also available for \Rfunction{qmatrix.msm} and for most output functions; these are often more accurate, at the cost of computational time. For more about bootstrapping in \Rpackage{msm}, see Section~\ref{sec:boot}. \item[Transition probability matrices] The function \Rfunction{pmatrix.msm} extracts the estimated transition probability matrix $P(t)$ within a given time. For example, for model 1, the 10 year transition probabilities are given by: <<>>= pmatrix.msm(cav.msm, t=10) @ Thus, a typical person in state 1, disease-free, has a probability of 0.5 of being dead ten years from now, a probability of 0.3 being still disease-free, and probabilities of 0.1 of being alive with mild/moderate or severe disease, respectively. This assumes $Q$ is constant within the desired time interval. For non-homogeneous processes, where $Q$ varies with time-dependent covariates but can be approximated as piecewise constant, there is an equivalent function \Rfunction{pmatrix.piecewise.msm}. Consult its help page for further details. If \Rfunarg{ci=''norm''} is specified, then a confidence interval is calculated based on drawing a random sample (default size 1000) from the assumed multivariate normal distribution of the maximum likelihood estimates and covariance matrix, and transforming. If \Rfunarg{ci=''boot''} is specified, then a bootstrap confidence interval for the transition probability matrix is calculated (see Section~\ref{sec:boot}) . However, both of these are computationally intensive, particularly the bootstrap method, so no confidence interval is calculated by default. \item[Mean sojourn times] The function \Rfunction{sojourn.msm} extracts the estimated mean sojourn times in each transient state $r$, for a given set of covariate values. This is calculated as $-1 / \hat q_{rr}$, where $\hat q_{rr}$ is the $r$th diagonal entry of the estimated transition intensity matrix. <<>>= sojourn.msm(cav.msm) @ \item[Probability that each state is next] The function \Rfunction{pnext.msm} extracts the matrix of probabilities $-q_{rs} / q_{rr}$ that the next state after state $r$ is state $s$, for each $r$ and $s$. Together with the mean sojourn times, this gives a more intuitive parameterisation of a continuous-time Markov model than the raw transition intensities $q_{rs}$. Note these are different from the transition probabilities in a given time $t$ returned by \Rfunction{pmatrix.msm}. <<>>= pnext.msm(cav.msm) @ \item[Total length of stay] Mean sojourn times describe the average period in a single stay in a state. For processes with successive periods of recovery and relapse, we may want to forecast the total time spent healthy or diseased, before death. The function \Rfunction{totlos.msm} estimates the forecasted total length of time spent in each transient state $s$ between two future time points $t_1$ and $t_2$, for a given set of covariate values. This defaults to the expected amount of time spent in each state between the start of the process (time 0, the present time) and death or a specified future time. This is obtained as \[ L_s = \int_{t_1}^{t_2} P(t)_{r,s} dt \] where $r$ is the state at the start of the process, which defaults to 1. This is calculated using numerical integration. For model 1, each patient is forecasted to spend 8.8 years disease free, 2.2 years with mild or moderate disease and 1.8 years with severe disease. Bootstrap and asymptotic confidence intervals are available, as for \Rfunction{pmatrix.msm}, but are not calculated by default. <<>>= totlos.msm(cav.msm) @ \item[Ratio of transition intensities] The function \Rfunction{qratio.msm} estimates a ratio of two entries of the transition intensity matrix at a given set of covariate values, together with a confidence interval estimated assuming normality on the log scale and using the delta method. For example, we may want to estimate the ratio of the progression rate $q_{12}$ into the first state of disease to the corresponding recovery rate $q_{21}$. For example in model 1, recovery is 1.8 times as likely as progression. <<>>= qratio.msm(cav.msm, ind1=c(2,1), ind2=c(1,2)) @ \item[Hazard ratios for transition] The function \Rfunction{hazard.msm} gives the estimated hazard ratios corresponding to each covariate effect on the transition intensities. 95\% confidence limits are computed by assuming normality of the log-effect. For example, for model 2 with female sex as a covariate, the following hazard ratios show more clearly that the only transition on which the effect of sex is significant at the 5\% level is the 1-2 transition. <<>>= hazard.msm(cavsex.msm) @ \end{description} \paragraph{Setting covariate values} All of these extractor functions take an argument called \Rfunarg{covariates}. If this argument is omitted, for example, <>= qmatrix.msm(cav.msm) @ then the intensity matrix is evaluated as $Q(\bar x)$ with all covariates set to their mean values $\bar x$ in the data. Alternatively, set \Rfunarg{covariates} to 0 to return the result $Q(0)$ with covariates set to zero. This will usually be preferable for categorical covariates, where we wish to see the result for the baseline category. <>= qmatrix.msm(cavsex.msm, covariates = 0) @ Alternatively, the desired covariate values can be specified explicitly as a list, <>= qmatrix.msm(cavsex.msm, covariates = list(sex = 1)) @ Values of categorical covariates must be quoted. For example, consider a covariate \texttt{smoke}, representing tobacco smoking status, with three levels, \texttt{NON, CURRENT, EX}, representing a non-smoker, current smoker or ex-smoker. \begin{Scode} qmatrix.msm(example.msm, covariates = list(age = 60, smoke=''CURRENT'')) \end{Scode} \subsection{Survival plots} In studies of chronic disease, an important use of multi-state models is in predicting the probability of survival for patients in increasingly severe states of disease, for some time $t$ in the future. This can be obtained directly from the transition probability matrix $P(t)$. The \Rfunction{plot} method for \Robject{msm} objects produces a plot of the expected probability of survival against time, from each transient state. Survival is defined as not entering the final absorbing state. <>= plot(cav.msm, legend.pos=c(8, 1)) @ This shows that the 10-year survival probability with severe CAV is approximately 0.1, as opposed to 0.3 with mild CAV and 0.5 without CAV. With severe CAV the survival probability diminishes very quickly to around 0.3 in the first five years after transplant. The \Rfunarg{legend.pos} argument adjusts the position of the legend in case of clashes with the plot lines. A \Rfunarg{times} argument can be supplied to indicate the time interval to forecast survival for. A more sophisticated analysis of these data might explore competing causes of death from causes related or unrelated to the disease under study. \subsection{Bootstrapping} \label{sec:boot} Most of \Rpackage{msm}'s output functions present confidence intervals based on asymptotic standard errors calculated from the Hessian, or transformations of these using the delta method. The asymptotic standard errors are expected to be underestimates of the true standard errors (Cramer-Rao lower bound). For some output functions, such as \Rfunction{pmatrix.msm}, and functions based on \Rfunction{pmatrix.msm} such as \Rfunction{totlos.msm} and \Rfunction{prevalence.msm}, the delta method cannot be used at all to obtain standard errors. In these cases, confidence intervals can be calculated by drawing a random sample from the assumed multivariate normal distribution of the maximum likelihood estimates and covariance matrix, and transforming. However, this is still based on potentially inaccurate asymptotic theory. The \Rpackage{msm} package provides the function \Rfunction{boot.msm} to enable bootstrap refitting of \Rfunction{msm} models, an alternative way to estimate uncertainty. For non-hidden Markov models, a bootstrap dataset is drawn by resampling pairs of consecutive states from the full data, i.e. \emph{transitions}. These are assumed to be independent when calculating the likelihood (Section~\ref{sec:multi:likelihood}). For hidden Markov models and models with censoring, a bootstrap dataset is drawn by resampling complete series from independent subjects. The bootstrap datasets have the same number of transitions, or subjects, respectively, as the original data. For most output extractor functions provided with \Rpackage{msm}, the option \Rfunarg{ci=''boot''} is available, as a wrapper around \Rfunction{boot.msm}, to enable bootstrap confidence intervals to be calculated. But any user-defined output statistic can be bootstrapped, as follows. The function \Rfunction{boot.msm} is called with the fitted \Rfunction{msm} model as first argument, and an R function specifying the statistic to be bootstrapped as the second argument \texttt{stat}. The return value from \Rfunction{boot.msm} is a list of \texttt{B} replicates (by default, \texttt{B=1000}) of the desired statistic. For example, to bootstrap the transition intensity matrix of the heart transplantation model \Robject{cav.msm}: \begin{Scode} q.list <- boot.msm(cav.msm, stat=function(x){qmatrix.msm(x)$estimates}) \end{Scode} Note that for \Rfunction{boot.msm} to be able to refit the original model that produced \Robject{cav.msm}, all objects used in the original model fit (for example, in this case, \Robject{twoway4.q}) must be in the working environment. Otherwise, \Rfunction{boot.msm} will give an ``object not found'' error. The user can then summarise these replicates by calculating empirical standard deviations or quantile-based intervals. In this example, \Robject{q.list} is a list of 1000 4$\times$4 matrices. The following code calculates the bootstrap standard error as the empirical standard deviation of the 1000 replicates, and a similar 95\% bootstrap confidence interval. \begin{Scode} q.array <- array(unlist(q.list), dim=c(4,4,1000)) apply(q.array, c(1,2), sd) apply(q.array, c(1,2), function(x)quantile(x, c(0.025, 0.975))) \end{Scode} Note that when bootstrapping, the refits of the model to the resampled datasets may occasionally fail to converge (as discussed in Section~\ref{sec:failure}) even if the original model fit did converge. In these cases, a warning is given, but \Rfunction{boot.msm} simply discards the failed dataset and moves on to the next bootstrap iteration. Unless convergence failure occurs for a large proportion of iterations, this should not affect the accuracy of the final bootstrap confidence intervals. \subsection{Convergence failure} \label{sec:failure} Inevitably if over-complex models are applied with insufficient data then the parameters of the model will not be identifiable. This will result in the optimisation algorithm failing to find the maximum of the log-likelihood, or even failing to evaluate the likelihood. For example, it will commonly be inadvisable to include several covariates in a model simultaneously. In some circumstances, the optimisation may report convergence, but fail to calculate any standard errors. In these cases, the Hessian of the log-likelihood at the reported solution is not positive definite. Thus the reported solution may be a saddle point rather than the maximum likelihood, or it may be close to the maximum. \begin{description} \item[Initial values] Make sure that a sensible set of initial values have been chosen. The optimisation may only converge within a limited range of `informative' initial values. It is also sensible to run the model for several different initial values to ensure that the estimation has converged to a global rather than a local optimum. \item[Scaling] It is often necessary to apply a scaling factor to normalise the likelihood (\Rfunarg{fnscale}), or certain individual parameters \Rfunarg{(parscale)}. This may prevent overflow or underflow problems within the optimisation. For example, if the value of the -2 $\times$ log-likelihood is around 5000, then the following option leads to an minimisation of the -2 $\times$ log-likelihood on an approximate unit scale: \Rfunarg{control = list(fnscale = 5000)} It is also advisable to analyse all variables, including covariates and the time unit, on a roughly normalised scale. For example, working in terms of a time unit of months or years instead of days, when the data range over thousands of days. \item[Convergence criteria] ``False convergence'', in which \Rfunction{optim()} reports convergence of the optimisation but the Hessian is not positive definite, can sometimes be solved by tightening the criteria (\Rfunarg{reltol}, defaults to \texttt{1e-08}) for reporting convergence. For example, \Rfunarg{control = list(reltol = 1e-16)}. Alternatively consider using smaller step sizes for the numerical approximation to the gradient, used in calculating the Hessian. This is given by the control parameter \Rfunarg{ndeps}. For example, for a model with 5 parameters, \Rfunarg{control = list(ndeps = rep(1e-6, 5))} \item[Choice of algorithm] By default, \Rfunction{msm} uses a Nelder-Mead algorithm which does not use analytic derivatives of the objective function. For potentially greater speed and accuracy, consider using a quasi-Newton algorithm such as the ``BFGS'' method of \Rfunction{optim}, which can make use of analytic derivatives, for example, \Rfunarg{method = ``BFGS'', use.deriv = TRUE}. \item[Model simplification] If none of these numerical adjustments lead to convergence, then the model is probably over-complicated. There may not be enough information in the data on a certain transition rate. It is always recommended to count all the pairs of transitions between states in successive observation times, making a frequency table of previous state against current state (function \Rfunction{statetable.msm}). Although the data are a series of snapshots of a continuous-time process, and the actual transitions take place in between the observation times, this type of table may still be helpful. If there are not many observed `transitions' from state 2 to state 4, for example, then the data may be insufficient to estimate $q_{24}$. For a staged disease model (Figure~\ref{fig:disease}), the number of disease states should be low enough that all transition rates can be estimated. Consecutive states of disease severity should be merged if necessary. If it is realistic, consider applying constraints on the intensities or the covariate effects so that the parameters are equal for certain transitions, or zero for certain transitions. Be careful to use a observation scheme and transition matrix appropriate to your data (see Section~\ref{sec:arbitr-observ-times}). By default, \Rfunction{msm} assumes that the data represent snapshots of the process, and the true state is unknown between observation times. In such circumstances, it is rarely feasible to estimate an intensity matrix with \emph{instantaneous} transitions allowed between every pair of states. This would be easier if the complete course of the process is known \Rfunarg{(exacttimes = TRUE)} in the call to \Rfunction{msm}. Understand the difference between \emph{instantaneous} and \emph{interval} transitions - although individuals may be in state 1 at time $t_r$, and state 3 at time $t_{r+1}$, that doesn't mean that instantaneous transitions from 1 to 3 should be permitted. \end{description} \subsection{Model assessment} \label{sec:model-assessment} \paragraph{Observed and expected prevalence} To compare the relative fit of two nested models, it is easy to compare their likelihoods. However it is not always easy to determine how well a fitted multi-state model describes an irregularly-observed process. Ideally we would like to compare observed data with fitted or expected data under the model. If there were times at which all individuals were observed then the fit of the expected numbers in each state or {\em prevalences} can be assessed directly at those times. Otherwise, some approximations are necessary. We could assume that an individual's state at an arbitrary time $t$ was the same as the state at their previous observation time. This might be fairly accurate if observation times are close together. This approach is taken by the function \Rfunction{prevalence.msm}, which constructs a table of observed and expected numbers and percentages of individuals in each state at a set of times. A set of expected counts can be produced if the process begins at a common time for all individuals. Suppose at this time, each individual is in state 0. Then given $n(t)$ individuals are under observation at time $t$, the expected number of individuals in state $r$ at time $t$ is $n(t) P(t)_{0,r}$. For example, we calculate the observed and expected numbers and percentages at two-yearly intervals up to 20 years after transplant, for the heart transplant model \Rfunction{cav.msm}. The number of individuals still alive and under observation decreases from 622 to 251 at year 20. The observed and expected percentages are plotted against time. <<>>= options(digits=3) prevalence.msm(cav.msm, times=seq(0,20,2)) @ <>= plot.prevalence.msm(cav.msm, mintime=0, maxtime=20) @ Comparing the observed and expected percentages in each state, we see that the predicted number of individuals who die (State 4) is under-estimated by the model from about year 8 onwards. Similarly the number of individuals sill alive and free of CAV (State 1) is over-estimated by the model from about year 8 onwards. Such discrepancies could have many causes. One possibility is that the transition rates vary with the time since the beginning of the process, the age of the patient, or some other omitted covariate, so that the Markov model is {\em non-homogeneous}. This could be accounted for by modelling the intensity as a function of age, for example, such as a piecewise-constant function. The \Rfunarg{pci} argument to \Rfunction{msm} can be used to automatically construct models with transition intensities which are piecewise-constant in time. In this example, it is likely that the hazard of death increases with age, so the model underestimates the number of deaths when forecasting far into the future. Another cause of poor model fit may sometimes be the failure of the Markov assumption. That is, the transition intensities may depend on the time spent in the current state (a semi-Markov process) or other characteristics of the process history. Accounting for the process history is difficult as the process is only observed through a series of snapshots. For a multi-state model with one-way progression through states, and frequent observations, we may be able to estimate the time spent in each state by each individual. \paragraph{Pearson-type goodness-of-fit test} \label{sec:pearson} Suppose that the true transition times are unknown, and data consist of observations of the process at arbitrary times which differ between individuals (panel data). Assessing goodness of fit by prevalence counts then involves estimating the observed prevalence at a series of points by some form of interpolation. This is only advisable if observation times are close together. An alternative method of assessing goodness-of-fit is to construct tables of observed and expected numbers of transitions, as described by Aguirre-Hernandez and Farewell~\cite{ahf}. This leads to a formal test of goodness-of-fit, analogous to the classical Pearson $\chi^2$ test for contingency tables. The tables are constructed as follows. Each pair of successive observations in the data (\emph{transition}) is classified by \begin{itemize} \item the starting state $r$ and finishing state $s$, \item time between the start of the process and the first of the pair of observations (indexed by $h$), \item time interval between the observations (indexed by $l_h$, within categories $h$), \item (if there are fitted covariates) the impact of covariates, as summarised by $q_{rr}$ (indexed by $c$), \item any other grouping of interest for diagnosing lack of fit (indexed by $g$). \end{itemize} Groupings of continuous quantities are normally defined by quantiles, so that there are a similar number of observed transitions in each (one-dimensional) category. The observed and expected numbers of transitions in each group are then defined by \[ o_{hl_h rscg} = \sum I(S(t_{i,j+1}) = s, S(t_{ij}) = r) \] \[ e_{hl_h rscg} = \sum P(S(t_{i,j+1}) = s | S(t_{ij}) = r) \] where $I(A)$ is the indicator function for an event $A$ and the summation is over the set of transitions in the category defined by $h,l_h,c,g$, over all individuals $i$. The Pearson-type test statistic is then \[ T = \sum_{hl_h rscg} \frac{(o_{hl_h rscg} - e_{hl_h rscg})^2}{e_{hl_h rscg}} \] The classical Pearson test statistic is distributed as $\chi^2_{n-p}$, where $n$ is the number of independent cells in the table and $p$ is the number of estimated parameters $p$. But the null distribution of $T$ is not exactly $\chi^2$, since the time intervals are non-identical, therefore the observed transitions are realizations from a set of independent but non-identical multinomial distributions. Aguirre-Hernandez and Farewell~\cite{ahf} showed that $\chi^2_{n-p}$ is a good approximation if there are no fitted covariates. For models with covariates, the null mean of $T$ is higher than $n - p$, but lower than $n$. Therefore, upper and lower bounds for the true $p$-value of the statistic can be obtained from the $\chi^2_{n-p}$ and $\chi^2_n$ distributions. Aguirre-Hernandez and Farewell~\cite{ahf} described a bootstrap procedure for obtaining an accurate $p$-value. Titman and Sharples~\cite{titman:sharples} described modifications to the test to correct for the biases introduced where in addition to the panel-data observation scheme: \begin{itemize} \item Times of death are known exactly. In this case, transitions ending in death are classified according to the next scheduled observation time after the death, which is estimated by multiple imputation from a Kaplan-Meier estimate of the distribution of time intervals between observations. \item An individual's final observation is censored, so that they are only known to be alive at that point. \item States are misclassified. \end{itemize} The \Rpackage{msm} package provides the function \Rfunction{pearson.msm} to perform the Pearson-type test. By default, three groups are used for each of $h$, $l_h$ and $c$. Often the number of groups will need to be reduced in cases where the resulting contingency tables are sparse (thus there are several low expected counts and the variance of $T$ is inflated). The test is now performed on the model \Robject{cav.msm} for the heart transplant dataset (a version of which was also analysed by Titman and Sharples~\cite{titman:sharples}). The default three interval groups are used, and two groups of the time since the start of the process. The \Rfunarg{transitions} argument groups the transitions from state 3 to each of states 1, 2 and 3 (the 9th, 10th and 11th transitions) together in the table, since these transitions are infrequent. <<>>= options(digits=2) pearson.msm(cav.msm, timegroups=2, transitions=c(1,2,3,4,5,6,7,8,9,9,9,10)) @ The first two tables in the output show the contingency tables of observed and expected numbers of transitions. Note that the observed number of transitions in certain categories is not a whole number, since these are averaged over multiple imputations of the next scheduled observation time following deaths. The column \texttt{Time} is the group defined by time since the start of the process, and the column \texttt{Interval} is the group defined by intervals between observations. The columns indicate the allowed transitions, or pairs of states which can be observed in successive observations. The third table presents the ``deviance'', the value of $\frac{(o_{hl_h rscg} - e_{hl_h rscg})^2}{e_{hl_h rscg}}$ for each cell, multipled by the sign of $o_{hl_h rscg} - e_{hl_h rscg}$ to indicate whether there were more or fewer transitions than expected in each cell. These can indicate areas of bad fit. For example, systematic changes in deviance by time or time interval between observations can indicate that a model with time-varying transition intensities is more suitable. Changes in deviance by covariate impact may indicate heterogeneity between individuals which is unexplained by the fitted covariates. Changes in deviance with the length of the interval between observations may also indicate failure of the Markov assumption, and that a semi-Markov model (in which intensities depend on the time spent in the current state) may fit better. In this example, the test statistic is 100. \Robject{p.upper} is an upper bound for the $p$-value of the statistic based on an asymptotic $\chi^2_{42}$ distribution, therefore the model does not fit well. It is not clear from the table of deviances which aspects of the fit are most influental to the test statistic. However, the two-way Markov model itself is not biologically plausible, as discussed in Section~\ref{sec:fitting:hmm:misc}. \subsection{Fitting misclassification models with \Rpackage{msm}} \label{sec:fitting:hmm:misc} In fact, in the heart transplant example from section~\ref{sec:datain}, it is not medically realistic for patients to recover from a diseased state to a healthy state. Progression of coronary artery vasculopathy is thought to be an irreversible process. The angiography scan for CAV is actually subject to error, which leads to some false measurements of CAV states and apparent recoveries. Thus we account for misclassification by fitting a \emph{hidden Markov model} using \Rpackage{msm}. Firstly we replace the two-way multi-state model by a one-way model with transition intensity matrix \[ Q = \left( \begin{array}{llll} -(q_{12} + q_{14}) & q_{12} & 0 & q_{14}\\ 0 & -(q_{23}+q_{24}) & q_{23} & q_{24}\\ 0 & 0 & -q_{34} & q_{34}\\ 0 & 0 & 0 & 0 \\ \end{array} \right ) \] We also assume that true state 1 (CAV-free) can be classified as state 1 or 2, state 2 (mild/moderate CAV) can be classified as state 1, 2 or 3, while state 3 (severe CAV) can be classified as state 2 or 3. Recall that state 4 represents death. Thus our matrix of misclassification probabilities is \[ E = \left( \begin{array}{llll} 1 - e_{12} & e_{12} & 0 & 0 \\ e_{21} & 1 - e_{21} - e_{23} & e_{23} & 0 \\ 0 & e_{32} & 1 - e_{32} & 0 \\ 0 & 0 & 0 & 0\\ \end{array} \right) \] with underlying states as rows, and observed states as columns. To model observed states with misclassification, we define an matrix \Rfunarg{ematrix} indicating the states that can be misclassified. Rows of this matrix correspond to true states, columns to observed states. It should contains zeroes in the positions where misclassification is not permitted. Non-zero entries are initial values for the corresponding misclassification probabilities. We then call \Rfunction{msm} as before, but with this matrix as the \Rfunarg{ematrix} argument. Initial values of 0.1 are assumed for each of the four misclassification probabilities $e_{12}, e_{21}, e_{23}, e_{32}$. Zeroes are given where the elements of $E$ are zero. The diagonal elements supplied in \Rfunarg{ematrix} are ignored, as rows must sum to one. The matrix \Rfunarg{qmatrix}, specifying permitted transition intensities and their initial values, also changes to correspond to the new $Q$ representing the progression-only model for the underlying states. The true state for every patient at the date of transplant is known to be ``CAV-free'', not misclassified. To indicate this we use the argument \Rfunarg{obstrue} to \Rfunction{msm}. This is set to be a variable in the dataset, \Rfunarg{firstobs}, indicating where the observed state equals the true state. This takes the value of 1 at the patient's first observation, at the transplant date, and 0 elsewhere. We use an alternative quasi-Newton optimisation algorithm \Rfunarg{(method="BFGS")} which can often be faster or more robust than the default Nelder-Mead simplex-based algorithm. An optional argument \Rfunarg{initprobs} could also have been given here, representing the vector of the probabilities of occupying each true state at the initial observation (equation~\ref{eq:multi:hidden:matprod}). If not given, all individuals are assumed to be in true state 1 at their initial observation. If \Rfunarg{est.initprobs=TRUE} is specified, then these probabilites are estimated as part of the model fit, using \Rfunarg{initprobs} as initial values. Covariate effects on these probabilities can also be estimated using a multinomial logistic regression model, if an \Rfunarg{initcovariates} argument is specified. See \Rfunction{help(msm)} for further details. \paragraph{Model 5: multi-state model with misclassification} <<>>= oneway4.q <- rbind(c(0, 0.148, 0, 0.0171), c(0, 0, 0.202, 0.081), c(0, 0, 0, 0.126), c(0, 0, 0, 0)) ematrix <- rbind(c(0, 0.1, 0, 0), c(0.1, 0, 0.1, 0), c(0, 0.1, 0, 0), c(0, 0, 0, 0)) cavmisc.msm <- msm(state ~ years, subject = PTNUM, data = cav, qmatrix = oneway4.q, ematrix = ematrix, death = 4, obstrue = firstobs, method="BFGS") cavmisc.msm @ Thus there is an estimated probability of about 0.03 that mild/moderate CAV will be diagnosed erroneously, but a rather higher probability of 0.17 that underlying mild/moderate CAV will be diagnosed as CAV-free. Between the two CAV states, the mild state will be misdiagnosed as severe with a probability of 0.06, and the severe state will be misdiagnosed as mild with a probability of 0.12. The model also estimates the progression rates through underlying states. An average of 8 years is spent disease-free, an average of about 3 years is spent with mild/moderate disease, and periods of severe disease also last about 3 years on average before death. \subsection{Effects of covariates on misclassification rates} We can investigate how the probabilities of misclassification depend on covariates in a similar way to the transition intensities, using a \Rfunarg{misccovariates} argument to \Rfunction{msm}. For example, we now include female sex as a covariate for the misclassification probabilities. The linear effects on the log odds of each misclassified state relative to the true state are initialised to zero by default (but this can be changed with the \Rfunarg{misccovinits} argument). \paragraph{Model 6: misclassification model with misclassification probabilities modelled on sex} <<>>= cavmiscsex.msm <- msm(state ~ years, subject = PTNUM, data = cav, qmatrix = oneway4.q, ematrix = ematrix, death = 4, misccovariates = ~sex, obstrue=firstobs, method="BFGS") @ <<>>= cavmiscsex.msm @ The large confidence interval for the 1/2 misclassification suggests that women are no more or less likely than men to have a false positive angiography scan. On the other hand, women have slightly more false negatives. \subsection{Extractor functions} As well as the functions described in section~\ref{sec:extractor} for extracting useful information from fitted models, there are a number of extractor functions specific to models with misclassification. \begin{description} \item[Misclassification matrix] The function \Rfunction{ematrix.msm} gives the estimated misclassification probability matrix at the given covariate values. For illustration, the fitted misclassification probabilities for men and women in model 6 are given by <<>>= ematrix.msm(cavmiscsex.msm, covariates=list(sex=0)) ematrix.msm(cavmiscsex.msm, covariates=list(sex=1)) @ The confidence intervals for the estimates for women are higher, since there are only 87 women in this set of 622 patients. \item[Odds ratios for misclassification] The function \Rfunction{odds.msm} gives the estimated odds ratios corresponding to each covariate effect on the misclassification probabilities. <<>>= odds.msm(cavmiscsex.msm) @ \item[Observed and expected prevalences] The function \Rfunction{prevalence.msm} is intended to assess the goodness of fit of the hidden Markov model for the \emph{observed} states to the data. Tables of observed prevalences of observed states are calculated as described in section~\ref{sec:model-assessment}, by assuming that observed states are retained between observation times. The expected numbers of individuals in each observed state are calculated similarly. Suppose the process begins at a common time for all individuals, and at this time, the probability of occupying \emph{true} state $r$ is $f_r$. Then given $n(t)$ individuals under observation at time $t$, the expected number of individuals in true state $r$ at time $t$ is the $r$th element of the vector $n(t) f P(t)$. Thus the expected number of individuals in \emph{observed} state $r$ is the $r$th element of the vector $n(t) f P(t) E$, where $E$ is the misclassification probability matrix. The expected prevalences (not shown) for this example are similar to those forecasted by the model without misclassification, with underestimates of the rates of death from 8 years onwards. To improve this model's long-term prediction ability, it is probably necessary to account for the natural increase in the hazard of death from any cause as people become older. \item[Goodness-of-fit test] The Pearson-type goodness-of-fit test is performed, as in Section~\ref{sec:pearson}. The table of deviances indicates that there are more 1-3 and 1-4 transitions than expected in short intervals, and fewer in long intervals. This may indicate some time-dependence in the transition rates. Indeed, Titman \cite{titman:phd} found that a model with piecewise-constant transition intensities gave a greatly improved fit to these data. <<>>= pearson.msm(cavmisc.msm, timegroups=2, transitions=c(1,2,3,4,5,6,7,8,9,9,9,10)) @ \end{description} \subsection{Recreating the path through underlying states} In speech recognition and signal processing, {\em decoding} is the procedure of determining the underlying states that are most likely to have given rise to the observations. The most common method of reconstructing the most likely state path is the {\em Viterbi} algorithm. Originally proposed by Viterbi~\cite{viterbi}, it is also described by Durbin \etal~\cite{biolog:seq} and Macdonald and Zucchini~\cite{macdonald:zucchini} for discrete-time hidden Markov chains. For continuous-time models it proceeds as follows. Suppose that a hidden Markov model has been fitted and a Markov transition matrix $P(t)$ and misclassification matrix $E$ are known. Let $v_k(t_i)$ be the probability of the most probable path ending in state $k$ at time $t_i$. \begin{enumerate} \item Estimate $v_k(t_1)$ using known or estimated initial-state occupation probabilities. \item For $i = 1 \ldots N$, calculate $v_l(t_i) = e_{l,O_{t_i}} \max_k v_k(t_{i-1}) P_{kl}(t_{i} - t_{i-1})$. Let $K_i(l)$ be the maximising value of $k$. \item At the final time point $t_N$, the most likely underlying state $S^*_N$ is the value of $k$ which maximises $v_k(t_N)$. \item Retrace back through the time points, setting $S^*_{i-1} = K_i(S^*_i)$. \end{enumerate} The computations should be done in log space to prevent underflow. The \Rpackage{msm} package provides the function \Rfunction{viterbi.msm} to implement this method. For example, the following is an extract from a result of calling \Rfunction{viterbi.msm} to determine the most likely underlying states for all patients. The results for patient 100103 are shown, who appeared to `recover' to a less severe state of disease while in state 3. We assume this is not biologically possible for the true states, so we expect that either the observation of state 3 at time 4.98 was an erroneous observation of state 2, or their apparent state 2 at time 5.94 was actually state 3. According to the expected path constructed using the Viterbi algorithm, it is the observation at time 5.94 which is most probably misclassified. <<>>= vit <- viterbi.msm(cavmisc.msm) vit[vit$subject==100103,] @ \subsection{Fitting general hidden Markov models with \Rpackage{msm}} \label{sec:fitting:hmm:general} The \Rpackage{msm} package provides a framework for fitting continuous-time hidden Markov models with general, continuous outcomes. As before, we use the \Rfunction{msm} function itself. \paragraph{Specifying the hidden Markov model} A hidden Markov model consists of two related components: \begin{itemize} \item the model for the evolution of the underlying Markov chain, \item the set of models for the observed data conditionally on each underlying state. \end{itemize} The model for the transitions between underlying states is specified as before, by supplying a \Rfunarg{qmatrix}. The model for the outcomes is specified using the argument \Rfunarg{hmodel} to \Rfunction{msm}. This is a list, with one element for each underlying state, in order. Each element of the list should be an object returned by a hidden Markov model \emph{constructor function}. The HMM constructor functions provided with \Rpackage{msm} are listed in Table~\ref{tab:hmm:dists}. There is a separate constructor function for each class of outcome distribution, such as uniform, normal or gamma. Consider a three-state hidden Markov model, with a transition intensity matrix of \[ Q = \left( \begin{array}{llll} -q_{12} & q_{12} & 0 \\ 0 & -q_{23} & q_{23}\\ 0 & 0 & 0 \\ \end{array} \right ) \] Suppose the outcome distribution for state 1 is Normal$(\mu_1, \sigma^2_1)$, the distribution for state 2 is Normal$(\mu_2, \sigma^2_2)$, and state 3 is exactly observed. Observations of state 3 are given a label of -9 in the data. Here our \Rfunarg{hmodel} argument should be a list of objects returned by \Rfunction{hmmNorm} and \Rfunction{hmmIdent} constructor functions. We must specify initial values for the parameters as the arguments to the constructor functions. For example, we take initial values of $\mu_1 = 90, \sigma_1 = 8, \mu_2 = 70, \sigma_2 = 8$. Initial values for $q_{12}$ and $q_{23}$ are 0.25 and 0.2. Finally suppose the observed data are in a variable called \Robject{y}, the measurement times are in \Robject{time}, and subject identifiers are in \Robject{ptnum}. The call to \Rfunction{msm} to estimate the parameters of this hidden Markov model would then be \begin{Scode} msm( y ~ time, subject=ptnum, data = example.df, qmatrix = rbind( c(0, 0.25, 0), c(0, 0, 0.2), c(0, 0, 0)), hmodel = list (hmmNorm(mean=90, sd=8), hmmNorm(mean=70, sd=8), hmmIdent(-9)) ) \end{Scode} \begin{table}[htbp] \scriptsize \centering \begin{tabular}{lp{0.8in}p{0.6in}p{0.6in}p{0.7in}l} \hline Function & Distribution & Parameters & & Location (link) & Density for an observation $x$ \\ \hline \Rfunction{hmmCat} & Categorical & \Rfunarg{prob, basecat} & $p,c_0$ & $p$ (logit) & $p_x$, $x = 1, \ldots, n$ \\ \Rfunction{hmmIdent} & Identity & \Rfunarg{x} & $x_0$ & & $I_{x = x_0}$ \\ \Rfunction{hmmUnif} & Uniform & \Rfunarg{lower, upper} & $l,u$ & & $1 / (u - l)$, $u \leq x \leq l$ \\ \Rfunction{hmmNorm} & Normal & \Rfunarg{mean, sd} & $\mu,\sigma$ & $\mu$ (identity) & $\phi(x, \mu, \sigma) = \frac{1}{\sqrt{2 \pi \sigma^2}} \exp(-(x - \mu)^2/(2 \sigma^2) )$ \\ \Rfunction{hmmLNorm} & Log-normal & \Rfunarg{meanlog, sdlog} & $\mu,\sigma$ & $\mu$ (identity) & $\frac{1}{x \sqrt{2 \pi \sigma^2}} \exp(-(\log x - \mu)^2 / (2 \sigma^2))$ \\ \Rfunction{hmmExp} & Exponential & \Rfunarg{rate} & $\lambda$ & $\lambda$ (log) & $\lambda e^{- \lambda x}$, $x > 0$ \\ \Rfunction{hmmGamma} & Gamma & \Rfunarg{shape, rate} & $n,\lambda$ & $\lambda$ (log) & $\frac{\lambda^n}{\Gamma(n)}x^{n-1} \exp(-\lambda x)$, $x > 0, n > 0, \lambda > 0$ \\ \Rfunction{hmmWeibull} & Weibull & \Rfunarg{shape, scale} & $a, b$ & $b$ (log) & $\frac{a}{b} (\frac{x}{b})^{a-1} \exp{(-(\frac{x}{b})^a)}$, $x > 0$ \\ \Rfunction{hmmPois} & Poisson & \Rfunarg{rate} & $\lambda$ & $\lambda$ (log) & $\lambda^x \exp(-\lambda)/x!$, $x = 0, 1, 2, \ldots$ \\ \Rfunction{hmmBinom} & Binomial & \Rfunarg{size, prob} & $n,p$ & $p$ (logit) & ${n \choose x} p^x (1-p)^{n-x}$ \\ \Rfunction{hmmNBinom} & Negative binomial & \Rfunarg{disp, prob} & $n,p$ & $p$ (logit) & $\Gamma(x+n)/(\Gamma(n)x!) p^n (1-p)^x$ \\ \Rfunction{hmmBeta} & Beta & \Rfunarg{shape1,shape2} & $a,b$ & & $ \Gamma(a+b) / (\Gamma(a)\Gamma(b))x^{a-1}(1-x)^{b-1}$ \\ \Rfunction{hmmT} & Student $t$ & \Rfunarg{mean, scale, df} & $\mu,\sigma,k$ & $\mu$ (identity) & $\frac{\Gamma\left((k+1)/2\right)}{\Gamma(k/2)}{\sqrt{\frac{1}{k\pi\sigma^2}}}\left\{1 + \frac{1}{k\sigma^2}(x - \mu)^{2} \right\}^{-(k + 1)/2}$ \\ \Rfunction{hmmTNorm} & Truncated normal & \Rfunarg{mean, sd, lower, upper} & $\mu,\sigma,l,u$ & $\mu$ (identity) & \parbox[t]{2in}{$\phi(x, \mu, \sigma) / \\ (\Phi(u, \mu, \sigma) - \Phi(l, \mu, \sigma))$, \\ where $\Phi(x,\mu,\sigma) = \int_{-\infty}^x \phi(u,\mu,\sigma) du$} \\ \Rfunction{hmmMETNorm} & Normal with truncation and measurement error & \Rfunarg{mean, sd, lower, upper, sderr, meanerr} & \parbox[t]{1in} {$\mu_0,\sigma_0,l,u$, \\ $\sigma_\epsilon,\mu_\epsilon$} & $\mu_\epsilon$ (identity) & \parbox[t]{2in}{$( \Phi(u, \mu_2, \sigma_3) - \Phi(l, \mu_2, \sigma_3)) / $ \\ $(\Phi(u, \mu_0, \sigma_0) - \Phi(l, \mu_0, \sigma_0)) $ \\ $\times \phi(x, \mu_0 + \mu_\epsilon, \sigma_2)$, \\ $\sigma_2^2 = \sigma_0^2 + \sigma_\epsilon^2$, \\ $\sigma_3 = \sigma_0 \sigma_\epsilon / \sigma_2$, \\ $\mu_2 = (x - \mu_\epsilon) \sigma_0^2 + \mu_0 \sigma_\epsilon^2$} \\ \Rfunction{hmmMEUnif} & Uniform with measurement error & \Rfunarg{lower, upper, sderr, meanerr} & $l,u,\mu_\epsilon,\sigma_\epsilon$ & $\mu_\epsilon$ (identity) & \parbox[t]{2in}{$(\Phi(x, \mu_\epsilon+l, \sigma_\epsilon) - \Phi(x, \mu_\epsilon+u, \sigma_\epsilon)) / \\ (u - l)$} \\ \hline \end{tabular} \caption{Hidden Markov model distributions in \Rpackage{msm}.} \label{tab:hmm:dists} \end{table} \paragraph{Covariates on hidden Markov model parameters} Most of the outcome distributions can be parameterised by covariates, using a link-transformed linear model. For example, an observation $y_{ij}$ may have distribution $f_1$ conditionally on underlying state 1. The link-transformed parameter $\theta_1$ is a linear function of the covariate vector $x_{ij}$ at the same observation time. \begin{eqnarray*} \label{eq:hmm:covs} y_{ij} | S_{ij} & \sim & f_1 (y | \theta_1, \gamma_1)\\ g(\theta_1) & = & \alpha + \beta^T x_{ij} \end{eqnarray*} Specifically, parameters named as the ``Location'' parameter in Table~\ref{tab:hmm:dists} can be modelled in terms of covariates, with the given link function. The \Rfunarg{hcovariates} argument to \Rfunction{msm} specifies the model for covariates on the hidden Markov outcome distributions. This is a list of the same length as the number of underlying states, and the same length as the \Rfunarg{hmodel} list. Each element of the list is a formula, in standard R linear model notation, defining the covariates on the distribution for the corresponding state. If there are no covariates for a certain hidden state, then insert a \texttt{NULL} in the corresponding place in the list. For example, in the three-state normal-outcome example above, suppose that the normal means on states 1 and 2 are parameterised by a single covariate $x$. \[ \mu_1 = \alpha_1 + \beta_1 x_{ij}, \qquad \mu_2 = \alpha_2 + \beta_2 x_{ij}. \] The equivalent call to \Rfunction{msm} would be \begin{Scode} msm( state ~ time, subject=ptnum, data = example.df, qmatrix = rbind( c(0, 0.25, 0), c(0, 0, 0.2), c(0, 0, 0)), hmodel = list (hmmNorm(mean=90, sd=8), hmmNorm(mean=70, sd=8), hmmIdent(-9)), hcovariates = list ( ~ x, ~ x, NULL) ). \end{Scode} \paragraph{Constraints on hidden Markov model parameters} Sometimes it is realistic that parameters are shared between some of the state-specific outcome distributions. For example, the Normally-distributed outcome in the previous example could have a common variance $\sigma^2_1 = \sigma^2_2 = \sigma^2$ between states 1 and 2, but differing means. It would also be realistic for any covariates on the mean to have a common effect $\beta_1 = \beta_2 = \beta$ on the state 1 and 2 outcome distributions. The argument \Rfunarg{hconstraint} to \Rfunction{msm} specifies which hidden Markov model parameters are constrained to be equal. This is a named list. Each element is a vector of constraints on the named hidden Markov model parameter. The vector has length equal to the number of times that class of parameter appears in the whole model. As for the other constraint arguments such as \Rfunarg{qconstraint}, identical values of this vector indicate parameters constrained to be equal. For example consider the three-state hidden Markov model described above, with normally-distributed outcomes for states 1 and 2. To constrain the outcome variance to be equal for states 1 and 2, and to also constrain the effect of \Robject{x} on the outcome mean to be equal for states 1 and 2, specify \begin{Scode} hconstraint = list(sd = c(1,1), x=c(1,1)) \end{Scode} \paragraph{FEV$_1$ after lung transplants} Now we give an example of fitting a hidden Markov model to a real dataset. The data on FEV$_1$ measurements from lung transplant recipients, described in \ref{sec:hmm:example:fev}, are provided with the \Rpackage{msm} package in a dataset called \Robject{fev}. <<>>= data(fev) @ We fit models Models 1 and 2, each with three states and common $Q$ matrix. <<>>= three.q <- rbind(c(0, exp(-6), exp(-9)), c(0, 0, exp(-6)), c(0, 0, 0)) @ The simpler Model 1 is specified as follows. Under this model the FEV$_1$ outcome is Normal with unknown mean and variance, and the mean and variance are different between BOS state 1 and state 2. \Rfunarg{hcovariates} specifies that the mean of the Normal outcome depends linearly on acute events. Specifically, this covariate is an indicator for the occurrence of an acute event within 14 days of the observation, denoted \texttt{acute} in the data. As an initial guess, we suppose the mean FEV$_1$ is 100\% baseline in state 1, and 54\% baseline in state 2, with corresponding standard deviations 16 and 18, and FEV$_1$ observations coinciding with acute events are on average 8\% baseline lower. \Rfunarg{hconstraint} specifies that the acute event effect is equal between state 1 and state 2. Days of death are coded as 999 in the \texttt{fev} outcome variable. <<>>= hmodel1 <- list(hmmNorm(mean=100, sd=16), hmmNorm(mean=54, sd=18), hmmIdent(999)) fev1.msm <- msm(fev ~ days, subject=ptnum, data=fev, qmatrix=three.q, death=3, hmodel=hmodel1, hcovariates=list(~acute, ~acute, NULL), hcovinits = list(-8, -8, NULL), hconstraint = list(acute = c(1,1)), method="BFGS") fev1.msm sojourn.msm(fev1.msm) @ Printing the \Rclass{msm} object \Rfunarg{fev1.msm} shows estimates and confidence intervals for the transition intensity matrix and the hidden Markov model parameters. The estimated within-state means of FEV$_1$ are around 98\% and 52\% baseline respectively. From the estimated transition intensities, individuals spend around 1421 days (3.9 years) before getting BOS, after which they live for an average of 1248 days (3.4 years). FEV$_1$ is lower by an average of 8\% baseline within 14 days of acute events. Model 2, where the outcome distribution is a more complex two-level model, is specified as follows. We use the distribution defined by equations \ref{eq:fev:level1}--\ref{eq:fev:level2}. The \Rfunction{hmmMETNorm} constructor defines the truncated normal outcome with an additional normal measurement error. The explicit probability density for this distribution is given in Table~\ref{tab:hmm:dists}. Our initial values are again 100 and 54 for the means of the within-state distribution of \emph{underlying} FEV$_1$, and 16 and 18 for the standard errors. This time, underlying FEV$_1$ is truncated normal. The truncation limits \Rfunarg{lower} and \Rfunarg{upper} are not estimated. We take an initial measurement error standard deviation of \Rfunarg{sderr=8}. The extra shift \Rfunarg{meanerr} in the measurement error model is fixed to zero and not estimated. The \Rfunarg{hconstraint} specifies that the measurement error variance $\sigma^2_\epsilon$ is equal between responses in states 1 and 2, as is the effect of short-term acute events on the FEV$_1$ response. <<>>= hmodel2 <- list(hmmMETNorm(mean=100, sd=16, sderr=8, lower=80, upper=Inf, meanerr=0), hmmMETNorm(mean=54, sd=18, sderr=8, lower=0, upper=80, meanerr=0), hmmIdent(999)) fev2.msm <- msm(fev ~ days, subject=ptnum, data=fev, qmatrix=three.q, death=3, hmodel=hmodel2, hcovariates=list(~acute, ~acute, NULL), hcovinits = list(-8, -8, NULL), hconstraint = list(sderr = c(1,1), acute = c(1,1)), method="BFGS") fev2.msm sojourn.msm(fev2.msm) @ Under this model the standard deviation of FEV$_1$ measurements caused by measurement error (more realistically, natural short-term fluctuation) is around 9\% baseline. The estimated effect of acute events on FEV$_1$ and sojourn times in the BOS-free state and in BOS before death are similar to Model 1. The following plot illustrates a trajectory of declining FEV$_1$ from the first lung transplant recipient in this dataset. This is produced by the following R code. The Viterbi algorithm is used to locate the most likely point at which this individual moved from BOS state 1 to BOS state 2, according to the fitted Model 2. This is illustrated by the vertical dotted line. This is the point at which the individual's lung function started to remain consistently below 80\% baseline FEV$_1$. <>= keep <- fev$ptnum==1 & fev$fev<999 plot(fev$days[keep], fev$fev[keep], type="l", ylab=expression(paste("% baseline ", FEV[1])), xlab="Days after transplant") vit <- viterbi.msm(fev2.msm)[keep,] (max1 <- max(vit$time[vit$fitted==1])) (min2 <- min(vit$time[vit$fitted==2])) abline(v = mean(max1,min2), lty=2) text(max1 - 500, 50, "STATE 1") text(min2 + 500, 50, "STATE 2") @ \paragraph{An alternative way of specifying a misclassification model} This general framework for specifying hidden Markov models can also be used to specify multi-state models with misclassification. A misclassification model is a hidden Markov model with a categorical outcome distribution. So instead of an \Rfunarg{ematrix} argument to \Rfunction{msm}, we can use a \Rfunarg{hmodel} argument with \Rfunction{hmmCat} constructor functions. \Rfunction{hmmCat} takes at least one argument \Rfunarg{prob}, a vector of probabilities of observing outcomes of $1, 2, \ldots, n$ respectively, where $n$ is the length of \Rfunarg{prob}. All outcome probabilities with an initial value of zero are assumed to be fixed at zero. \Rfunarg{prob} is scaled if necessary to sum to one. The model in section~\ref{sec:fitting:hmm:misc} specifies that an individual occupying underlying state 1 can be observed as states 2 (and 1), underlying state 2 can be observed as states 1, 2 or 3, and state 3 can be observed as states 2 or 3, and underlying state 4 (death) cannot be misclassified. Initial values of 0.1 are given for the 1-2, 2-1, 2-3 and 3-2 misclassification probabilities. This is equivalent to the model below, specified using a \Rfunarg{hmodel} argument to \Rfunction{msm}. The maximum likelihood estimates should be the same as before (Model 5). <<>>= oneway4.q <- rbind(c(0, 0.148, 0, 0.0171), c(0, 0, 0.202, 0.081), c(0, 0, 0, 0.126), c(0, 0, 0, 0)) cavmisc.msm <- msm(state ~ years, subject = PTNUM, data = cav, hmodel = list (hmmCat(c(0.9, 0.1, 0, 0)), hmmCat(c(0.1, 0.8, 0.1, 0)), hmmCat(c(0, 0.1, 0.9, 0)), hmmIdent(4)), qmatrix = oneway4.q, obstrue=firstobs, death = 4, method="BFGS") cavmisc.msm @ \subsubsection{Defining a new hidden Markov model distribution} Suppose the hidden Markov model outcome distributions supplied with \Rpackage{msm} (Table~\ref{tab:hmm:dists}) are insufficient. We want to define our own univariate distribution, called \Rfunction{hmmNewDist}, taking two parameters \Robject{location} and \Robject{scale}. Download the source package, for example \texttt{msm-0.7.2.tar.gz} for version 0.7.2, from CRAN and edit the files in there, as follows. \begin{enumerate} \item Add an element to \Robject{.msm.HMODELPARS} in the file \texttt{R/constants.R}, naming the parameters of the distribution. For example \begin{Scode} newdist = c('location', 'scale') \end{Scode} \item Add a corresponding element to the C variable \texttt{HMODELS} in the file \texttt{src/lik.c}. This MUST be in the same position as in the \Robject{.msm.HMODELPARS} list. For example, \begin{Scode} hmmfn HMODELS[] = { ..., hmmNewDist };. \end{Scode} \item The new distribution is allowed to have one parameter which can be modelled in terms of covariates. Add the name of this parameter to the named vector \Robject{.msm.LOCPARS} in \texttt{R/constants.R}. For example \texttt{newdist = 'location'}. Specify \texttt{newdist = NA} if there is no such parameter. \item Supposed we have specified a parameter with a non-standard name, that is, one which doesn't already appear in \Robject{.msm.HMODELPARS}. Standard names include, for example, \texttt{'mean'}, \texttt{'sd'}, \texttt{'shape'} or \texttt{'scale'}. Then we should add the allowed range of the parameter to \Robject{.msm.PARRANGES}. In this example, we add \texttt{meanpars = c(-Inf, Inf)} to \Robject{.msm.PARRANGES}. This ensures that the optimisation to estimate the parameter takes place on a suitable scale, for example, a log scale for a parameter constrained to be positive. If the parameter should be fixed during maximum likelihood estimation (for example, the denominator of a binomial distribution) then add its name to \Robject{.msm.AUXPARS}. \item Add an R constructor function for the distribution to \texttt{R/hmm-dists.R}. For a simple univariate distribution, this is of the form \begin{Scode} hmmNewDist <- function(location, scale) { hmmDIST(label = "newdist", link = "identity", r = function(n) rnewdist(n, location, scale), match.call()) } \end{Scode} \begin{itemize} \item The \texttt{'label'} must be the same as the name you supplied for the new element of \Robject{.msm.HMODELPARS} \item \texttt{link} is the link function for modelling the location parameter of the distribution as a linear function of covariates. This should be the quoted name of an R function. A log link is \texttt{'log'} and a logit link is \texttt{'qlogis'}. If using a new link function other than \texttt{'identity'}, \texttt{'log'}, or \texttt{'qlogis'}, you should add its name to the vector \Robject{.msm.LINKFNS} in \texttt{R/constants.R}, and add the name of the corresponding inverse link to \Robject{.msm.INVLINK}. You should also add the names of these functions to the C array \texttt{LINKFNS} in \texttt{src/lik.c}, and write the functions if they do not already exist. \item \texttt{r} is an R function, of the above format, returning a vector of \texttt{n} random values from the distribution. You should write this if it doesn't already exist. \end{itemize} \item Add the name of the new constructor function to the NAMESPACE in the top-level directory of the source package. \item Write a C function to compute the probability density of the distribution, and put this in \texttt{src/hmm.c}, with a declaration in \texttt{src/hmm.h}. This must be of the form \begin{Scode} double hmmNewDist(double x, double *pars) \end{Scode} where \texttt{*pars} is a vector of the parameters of the distribution, and the density is evaluated at \texttt{x}. \item Update the documentation (\texttt{man/hmm-dists.Rd}) and the distribution table in\\ \texttt{inst/doc/msm-manual.Rnw}) if you like. \item Recompile the package (see the ``Writing R Extensions'' manual) \end{enumerate} Your new distribution will be available to use in the \Rfunarg{hmodel} argument to \Rfunction{msm}, as, for example \begin{Scode} hmodel = list(..., hmmNewDist(location = 0, scale = 1), ...) \end{Scode} If your distribution may be of interest to others, ask me nicely (\texttt{chris.jackson@mrc-bsu.cam.ac.uk}) to include it in a future release. \clearpage \section{\Rpackage{msm} reference guide} The R help page for \Rfunction{msm} gives details of all the allowed arguments and options to the \Rfunction{msm} function. To view this online in R, type: <>= help(msm) @ Similarly all the other functions in the package have help pages, which should always be consulted in case of doubt about how to call them. The web-browser based help interface may often be convenient - type <>= help.start() @ and navigate to \textsf{Packages} $\ldots$ \textsf{msm}, which brings up a list of all the functions in the package with links to their documentation, and a link to this manual in PDF format. \appendix \section{Changes in the msm package} For a detailed list of the changes in recent versions of \Rpackage{msm}, see the \texttt{NEWS} file in the top-level directory of the installed package. The \texttt{Changelog} file in the top-level directory of the source package contains more technical detail about these changes. \section{Get in touch} If you use \Rpackage{msm} in your work, whatever your field of application, please let me know, for my own interest! Suggestions for improvement are welcome. \clearpage \bibliography{msm} \end{document} msm/src/doc/figures/0000755000176000001440000000000012031345044014072 5ustar ripleyusersmsm/src/doc/figures/general.pdf0000644000176000001440000000463012031345744016214 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream xXKo6WXF #=w6` "EPyP$QUgxQ }64A @JAΰ2Q5 *dk}Q!LaH15FT0R-ۜc\y͙̌ml)Ml,$j򮴚fvkl&&9MKn5mZMAY&&EYvɖaXJPn -}.1D]⫩(#<Ă/= {qk$̷>pQLj$(9\J~BSs p?aP8Yx L6O)e`dx2LOrl GlW gHFm1n.BHiM4=qr|\g[FfvX׺;Cmf]2XklՀNa [muޖ=9v[h@]46/4 eئk]hk͌!?$Ůc .MBa [muؑi''X)C:Th%LG 8y Ei&*\븀kw 6SZ[Ӡ59~ YIʣ)soʰ͔ЉاmtK>FX>^fe&*52l3eg]}6 . :2 izGSwT $2l˿4ܝԻG%E/GqiROÏ9\{dn>~WwY@?oEg;C Yx> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 11 0 obj <> endobj 2 0 obj <>endobj xref 0 12 0000000000 65535 f 0000001554 00000 n 0000001845 00000 n 0000001495 00000 n 0000001336 00000 n 0000000015 00000 n 0000001316 00000 n 0000001602 00000 n 0000001702 00000 n 0000001643 00000 n 0000001672 00000 n 0000001787 00000 n trailer << /Size 12 /Root 1 0 R /Info 2 0 R /ID [<4772CDDC270CC9832170B8A6062C540F><4772CDDC270CC9832170B8A6062C540F>] >> startxref 2063 %%EOF msm/src/doc/figures/p2q1.pdf0000644000176000001440000000200412031345744015353 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream xMA 0  {h%; ΡPJ KvGK|b}Nn/LAېWWE܉\#K &,@LKӐD"ATC7?-endstream endobj 6 0 obj 135 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 9 0000000000 65535 f 0000000428 00000 n 0000000546 00000 n 0000000369 00000 n 0000000239 00000 n 0000000015 00000 n 0000000220 00000 n 0000000476 00000 n 0000000517 00000 n trailer << /Size 9 /Root 1 0 R /Info 2 0 R /ID [<325056F4C9C207604170BC2D639E1D53><325056F4C9C207604170BC2D639E1D53>] >> startxref 698 %%EOF msm/src/doc/figures/p2q12.pdf0000644000176000001440000000203312031345744015437 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream xMN;09slc''6r Ƒ"HFp{\a*6v)tBƸ*p Mѧ 3MTNYU\GNc.*<~4.! l &Y&I{<p9endstream endobj 6 0 obj 158 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 9 0000000000 65535 f 0000000451 00000 n 0000000569 00000 n 0000000392 00000 n 0000000262 00000 n 0000000015 00000 n 0000000243 00000 n 0000000499 00000 n 0000000540 00000 n trailer << /Size 9 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 721 %%EOF msm/src/doc/figures/p4q159.pdf0000644000176000001440000000212412031345744015536 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream xMP;0 u ohc@H,:i&DRI|MKI/Iz$N'Z{w.Cn$JD 0HanNwR-PcҜیMU-/4eѨ g&V-Ϫ_b8[  bX'Ŧ{4 ݴL`{Xclg:?bendstream endobj 6 0 obj 215 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 9 0000000000 65535 f 0000000508 00000 n 0000000626 00000 n 0000000449 00000 n 0000000319 00000 n 0000000015 00000 n 0000000300 00000 n 0000000556 00000 n 0000000597 00000 n trailer << /Size 9 /Root 1 0 R /Info 2 0 R /ID [<8F7CF8F2C2D4FF6135A25FAEF128A59F><8F7CF8F2C2D4FF6135A25FAEF128A59F>] >> startxref 778 %%EOF msm/src/doc/figures/p3q12.pdf0000644000176000001440000000206412031345744015444 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream x]K0 D>,8=k(f "tdrze8]0> .) V=J{ٺÿf`y20JZݳew8@qPڰ8 >ջ dZ|MP(:Y~ث.BLi2k%7 ,qb?V+Liendstream endobj 6 0 obj 182 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 9 0000000000 65535 f 0000000476 00000 n 0000000594 00000 n 0000000417 00000 n 0000000286 00000 n 0000000015 00000 n 0000000267 00000 n 0000000524 00000 n 0000000565 00000 n trailer << /Size 9 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 746 %%EOF msm/src/doc/figures/p3q16.pdf0000644000176000001440000000205612031345744015451 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream xeK 1 @9E.4/ \G: `v> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 9 0000000000 65535 f 0000000470 00000 n 0000000588 00000 n 0000000411 00000 n 0000000280 00000 n 0000000015 00000 n 0000000261 00000 n 0000000518 00000 n 0000000559 00000 n trailer << /Size 9 /Root 1 0 R /Info 2 0 R /ID [<246D0C83F38FA09D6CA84E3971E1D234><246D0C83F38FA09D6CA84E3971E1D234>] >> startxref 740 %%EOF msm/src/doc/figures/hidden.pdf0000644000176000001440000000502312031345744016027 0ustar ripleyusers%PDF-1.3 %쏢 8 0 obj <> stream xVMo!+8R2ǵR.Tn\Me-%Zw`5%VR}7?J@)^<{nw=zZ>Cک]|G(! ^~زX (XdX?Xm~[oq{AʻG!12FvxN\N+چV[J1ƙVz` 3Zccb"ޭq,ϞxIZeB3"uqatSB;sN ex5TysΆW$ ARUtϰi/F6<ۗ`kx& _K}.*.* L r|}d pVǛK48xC8G@x‡#*MskDbF+=Ao R^ۤgљ^2ZȶPq8#K.Ei5{$-ozzSB9~/9vSvA16qDRD'~WHl,-Ƅ+y/үdL8ɕ~Wul2F_FѨbvu06x1⻂KOB}Fwe> /Contents 8 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 7 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 6 0 obj <> endobj 15 0 obj <> endobj 16 0 obj <> endobj 5 0 obj <>stream xkhD endstream endobj 4 0 obj <>stream xc` endstream endobj 14 0 obj <> endobj 13 0 obj <> endobj 12 0 obj <> endobj 11 0 obj <> endobj 10 0 obj <> endobj 2 0 obj <>endobj xref 0 17 0000000000 65535 f 0000001076 00000 n 0000002005 00000 n 0000001017 00000 n 0000001466 00000 n 0000001318 00000 n 0000001124 00000 n 0000000866 00000 n 0000000015 00000 n 0000000847 00000 n 0000001934 00000 n 0000001848 00000 n 0000001766 00000 n 0000001687 00000 n 0000001613 00000 n 0000001212 00000 n 0000001242 00000 n trailer << /Size 17 /Root 1 0 R /Info 2 0 R >> startxref 2161 %%EOF msm/src/doc/figures/p5q1_4_6_8_11_12_16.pdf0000644000176000001440000000240412031345744017372 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream xUSIN0>saĦDǽ8hR\U^#r^{KJ~N8z).rz{LgU-bVJH]1!f=]+88 o5(Pn2\պ͓܄V/XX_"qиbV 6fK)V=͎WlКhj",^bssqe Z,DȕBŶң+6Nh5j&Pܜ5l4h>[G,qfkb(D< mkUuj9n\bulĹAQ#Tq+FX>m\1.$11y_wf-=֗ݻs^C%endstream endobj 6 0 obj 390 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 9 0000000000 65535 f 0000000684 00000 n 0000000802 00000 n 0000000625 00000 n 0000000494 00000 n 0000000015 00000 n 0000000475 00000 n 0000000732 00000 n 0000000773 00000 n trailer << /Size 9 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 954 %%EOF msm/src/doc/figures/p4q13569.pdf0000644000176000001440000000231412031345744015710 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream xURN1 +|~=C?B/NvzfϟQ QDx1`Q nK(2M "Y5æGܱsּnȢ~L5IK1QNj_/*e>UOCfxpH;f`2*uYZ ,f 9K^CcS0Μ-YXV+侇<'8&osYT} c9 HJӬ;Ƶ\Effﵗn)̴ϥVW.qjt1$+gy:endstream endobj 6 0 obj 334 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 9 0000000000 65535 f 0000000628 00000 n 0000000746 00000 n 0000000569 00000 n 0000000438 00000 n 0000000015 00000 n 0000000419 00000 n 0000000676 00000 n 0000000717 00000 n trailer << /Size 9 /Root 1 0 R /Info 2 0 R /ID [<49ADAC326405A727B34AB09603D356DB><49ADAC326405A727B34AB09603D356DB>] >> startxref 898 %%EOF msm/src/doc/figures/p3q135.pdf0000644000176000001440000000211112031345744015523 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream xU;0 w3I'`BKqRQUU>8HqJFpd .^0{s5gO1yw0iMKmTw{pn%݄$(G{zVx4z*]\UH"ȑľ3.nX2v n9(Ǎj=^hZVendstream endobj 6 0 obj 203 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 9 0000000000 65535 f 0000000497 00000 n 0000000615 00000 n 0000000438 00000 n 0000000307 00000 n 0000000015 00000 n 0000000288 00000 n 0000000545 00000 n 0000000586 00000 n trailer << /Size 9 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 767 %%EOF msm/src/doc/figures/p3q124.pdf0000644000176000001440000000210212031345744015521 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream x]M! =E.pL,OȌ!/Hy_t>83,WTB;,pp-aϭgh+ǀhZjQ|w۠V۔SK $/Q?TڳPe=RUF#WI+EmL ?\u~c!7,.Xendstream endobj 6 0 obj 196 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 9 0000000000 65535 f 0000000490 00000 n 0000000608 00000 n 0000000431 00000 n 0000000300 00000 n 0000000015 00000 n 0000000281 00000 n 0000000538 00000 n 0000000579 00000 n trailer << /Size 9 /Root 1 0 R /Info 2 0 R /ID [<18776D8BF95E9FF7BDC22AF23A1A5A27><18776D8BF95E9FF7BDC22AF23A1A5A27>] >> startxref 760 %%EOF msm/src/doc/figures/p5q1_6_11_16.pdf0000644000176000001440000000217312031345744016421 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream xMQKN0 Y&=kxԷ@_${&I,7t%Iw+i^{zZ{|AI_tdN@ F9HJfCmIK3:4''lHmƹp* Z-By&{Wy@'+2e[qq۫^a!΅/3" R,º1%+"fr1 0ԓ_a!s%3afH5%z?(B}]endstream endobj 6 0 obj 254 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 9 0000000000 65535 f 0000000547 00000 n 0000000665 00000 n 0000000488 00000 n 0000000358 00000 n 0000000015 00000 n 0000000339 00000 n 0000000595 00000 n 0000000636 00000 n trailer << /Size 9 /Root 1 0 R /Info 2 0 R /ID [<7C8FD2A157BC7182115B5A22DDCBAA1B><7C8FD2A157BC7182115B5A22DDCBAA1B>] >> startxref 817 %%EOF msm/src/doc/figures/multistate.pdf0000644000176000001440000000415212031345744016771 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream xWK'h)zG!i8HN 3+D{70_8׶̗hxun&ᶬ/yb-s4ץC_Lb:/ sDnKf~ЭtMxF3hU!;MP|T@7.fG.n(n Ь 8\9R9v4BCJkH؂b~W`#a)s"ͮ( ::p!{ӡ`RY29̫ebZ#۵2*2TphH8#LC7zQs}87܁TCCuvڕmt+(h U3:\AKB2$*(J VTgj/?tR޼t[|l/b%;tW1k5VAH{ӎ6 ަd#x-/5$mGD+;AѺ~QG[y *gvƃ"=,S@>1z'`9:Gp;{QMer,k j:}mnCdקuTx6 zh&G>)N\H.Ҹudhd3OPhw)Ou9F@k5'`p5[l6ʮuTV]IsQE񃗉; *C6Ub.$ڨakbc'O"1Z ?!JղS^f{ TFB@}#rnO$1*J_ph9Ry>Kt_ 7Iݣ1ȍsMqKS`,e+sK,05,lD: O[?fvKz2"$Xn4&}v?}ijP`x^dwm ‡\X>T̥-> S|4r\~_} |Ao_Jendstream endobj 6 0 obj 1020 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 11 0000000000 65535 f 0000001343 00000 n 0000001560 00000 n 0000001284 00000 n 0000001125 00000 n 0000000015 00000 n 0000001105 00000 n 0000001391 00000 n 0000001491 00000 n 0000001432 00000 n 0000001461 00000 n trailer << /Size 11 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 1781 %%EOF msm/src/doc/figures/p5q1_6_7_11_12.pdf0000644000176000001440000000222512031345744016641 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream x]QAn0 >Y%;/y [lY3EؚdH'W }ocxB27PbQ%O_p̄naS#LypeJGX%`ڸp{QcǗN02a3<8ݰul [KVjg<8S'x.ɗZbAi \;%o1z[+㹙x-Nfk,P?, 1Ɉ@\ӄ0Ӝ^ƫkʒ: U!Fkh|V!?ٕendstream endobj 6 0 obj 279 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 9 0000000000 65535 f 0000000573 00000 n 0000000691 00000 n 0000000514 00000 n 0000000383 00000 n 0000000015 00000 n 0000000364 00000 n 0000000621 00000 n 0000000662 00000 n trailer << /Size 9 /Root 1 0 R /Info 2 0 R /ID [<0507AE57B35FF484D029A4B37E531833><0507AE57B35FF484D029A4B37E531833>] >> startxref 843 %%EOF msm/src/doc/figures/p3q14.pdf0000644000176000001440000000205412031345744015445 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream xMOK1s . \Iga"V'M Cy#^n0z_@x)Y Uߘ֘i O'a31pgh7p(%hpI(1 㠖úE(trgң zO`QmNNPgl8_.*,{h|+|Gendstream endobj 6 0 obj 175 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 9 0000000000 65535 f 0000000468 00000 n 0000000586 00000 n 0000000409 00000 n 0000000279 00000 n 0000000015 00000 n 0000000260 00000 n 0000000516 00000 n 0000000557 00000 n trailer << /Size 9 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 738 %%EOF msm/src/doc/figures/sampling.pdf0000644000176000001440000000440012031345744016404 0ustar ripleyusers%PDF-1.3 %쏢 8 0 obj <> stream xTn@+ mvflq@ ÅaDB ')} DPS8o?-<WlSvWtxM]$}ZI-J<Ɨ_W_(H4*^=Shu0>43-fۙ9d~p<ँ?2>yMXXZTGqAghJPq CVEQq`2+Eŝ5+> /Contents 8 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 7 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 6 0 obj <> endobj 15 0 obj <> endobj 16 0 obj <> endobj 5 0 obj <>stream xkhD endstream endobj 4 0 obj <>stream xc` endstream endobj 14 0 obj <> endobj 13 0 obj <> endobj 12 0 obj <> endobj 11 0 obj <> endobj 10 0 obj <> endobj 2 0 obj <>endobj xref 0 17 0000000000 65535 f 0000000801 00000 n 0000001730 00000 n 0000000742 00000 n 0000001191 00000 n 0000001043 00000 n 0000000849 00000 n 0000000591 00000 n 0000000015 00000 n 0000000572 00000 n 0000001659 00000 n 0000001573 00000 n 0000001491 00000 n 0000001412 00000 n 0000001338 00000 n 0000000937 00000 n 0000000967 00000 n trailer << /Size 17 /Root 1 0 R /Info 2 0 R >> startxref 1886 %%EOF msm/src/doc/figures/illdeath.pdf0000644000176000001440000000327712031345744016373 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream xTn0 +tLTM=)>5pm @C|Hw"A<5$ghzO{Ϋyw n{dhޮ;!8>RRlʔE`Ĕ fX^ FN*X2 -{Ε4|3GN.XLZCŒ[B].IpkaͪlS>KB׍A%A&lnOq<^H `w=Ƞ ˆkØXCDi,]Z&#@M\ƔP]Yiړ&Tz Ddy -7PTtFZ_Jx^Z?^Met  PjOFhtċ<×xwL?L Qo(G<3twwHk):C"1Wm+d9 C>Iޣ.m/g9aL|OU̐v3zI[&&G˹)| ,X$F%D֬QwnVES֗ҝR[,$vc>_ ,bendstream endobj 6 0 obj 596 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 11 0000000000 65535 f 0000000918 00000 n 0000001135 00000 n 0000000859 00000 n 0000000700 00000 n 0000000015 00000 n 0000000681 00000 n 0000000966 00000 n 0000001066 00000 n 0000001007 00000 n 0000001036 00000 n trailer << /Size 11 /Root 1 0 R /Info 2 0 R /ID [<8524F37507AD62BF2165B7063CA4B90E><8524F37507AD62BF2165B7063CA4B90E>] >> startxref 1354 %%EOF msm/src/doc/figures/p3q1246.pdf0000644000176000001440000000214712031345744015620 0ustar ripleyusers%PDF-1.3 %쏢 5 0 obj <> stream xUQAn1 {H6`6OԴPRn`'7^?4]7`z4ULw(j`[rjeAT68vg<{6$i2SYr{Fw(1]g" $pq~ţiK%}g]FHx$N*{ Xm2{P־\ #1I:=ᥔWp. a_,ZUEq3a_Ezu8+^gendstream endobj 6 0 obj 233 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 9 0000000000 65535 f 0000000527 00000 n 0000000645 00000 n 0000000468 00000 n 0000000337 00000 n 0000000015 00000 n 0000000318 00000 n 0000000575 00000 n 0000000616 00000 n trailer << /Size 9 /Root 1 0 R /Info 2 0 R /ID [<043BADFF288CA31BAAF50CBE8CB75FF8><043BADFF288CA31BAAF50CBE8CB75FF8>] >> startxref 797 %%EOF msm/src/doc/msm.bib0000644000176000001440000004465512031345744013725 0ustar ripleyusers@Book{biolog:seq, author = {Durbin, R. and Eddy, S. and Krogh, A. and Mitchison, G.}, ALTeditor = {}, title = {{Biological Sequence Analysis: Probabilistic Models of Proteins and Nucleic Acids}}, publisher = {Cambridge University Press}, year = {1998}, OPTkey = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, OPTaddress = {}, OPTedition = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Book{cox:miller, author = {Cox, D. R. and Miller, H. D.}, ALTeditor = {}, title = {{The Theory of Stochastic Processes}}, publisher = {Chapman and Hall}, year = {1965}, OPTkey = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, address = {London}, OPTedition = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{klotz:est, author = {Klotz, J. H. and Sharples, L. D.}, title = {Estimation for a {M}arkov heart transplant model}, journal = {The Statistician}, year = 1994, volume = 43, number = 3, pages = {431--436} } @Article{sharp:gibbs, author = {Sharples, L. D.}, title = {Use of the {G}ibbs Sampler to estimate transition rates between grades of coronary disease following cardiac transplantation}, journal = {Statistics in Medicine}, year = 1993, volume = 12, pages = {1155--1169} } @Article{kay:mark, author = {Kay,R.}, title = {A {M}arkov model for analysing cancer markers and disease states in survival studies}, journal = {Biometrics}, year = 1986, volume = 42, pages = {855--865} } @Article{gruger:valid, author = {Gr\"uger, J. and Kay, R. and Schumacher, M.}, title = {The validity of inferences based on incomplete observations in disease state models}, journal = {Biometrics}, year = {1991}, OPTkey = {}, volume = {47}, OPTnumber = {}, pages = {595--605}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{long1, author = {Longini, I. M. and Clark, W. S. and Byers, R. H. and Ward, J. W. and Darrow, W. W. and Lemp, G. F. and Hethcote, H. W.}, title = {Statistical analysis of the stages of {HIV} infection using a {M}arkov model}, journal = {Statistics in Medicine}, year = {1989}, OPTkey = {}, volume = {8}, OPTnumber = {}, pages = {851--843}, OPTmonth = {}, OPTnote = {}, annote = {Original HIV Markov paper, four states} } @Article{long2, author = {Longini, I. M. and Clark, W. S. and Gardner, L. I. and Brundage, J. F.}, title = {The dynamics of {CD4}+ {T}-lymphocyte decline in {HIV}-infected individuals: a {M}arkov modelling approach}, journal = {Journal of Acquired Immune Deficiency Syndromes}, year = {1991}, OPTkey = {}, volume = {4}, OPTnumber = {4}, pages = {1141--1147}, OPTmonth = {}, OPTnote = {}, annote = {original paper defining CD4 ranges as disease states} } @Article{sattlong, author = {Satten, G. A. and Longini, I. M.}, title = {Markov chains with measurement error: {E}stimating the `true' course of a marker of the progression of human immunodeficiency virus disease}, journal = {Applied Statistics - Journal of the Royal Statistical Society Series C}, year = {1996}, OPTkey = {}, volume = {45}, number = {3}, pages = {275--295}, month = {}, OPTnote = {}, OPTannote = {} } @Article{retino2, author = {Marshall, G. and Jones, R. H.}, title = {Multi-state {M}arkov models and diabetic retinopathy}, journal = {Statistics in Medicine}, year = {1995}, OPTkey = {}, volume = {14}, OPTnumber = {}, OPTpages = {}, OPTmonth = {}, OPTnote = {}, annote = {This is the paper that includes covariates in multistate models.} } @Article{duffy95, author = {Duffy, S. W. and Chen, H. H.}, title = {Estimation of mean sojourn time in breast cancer screening using a {M}arkov chain model of entry to and exit from preclinical detectable phase}, journal = {Statistics in Medicine}, year = {1995}, OPTkey = {}, volume = {14}, OPTnumber = {}, pages = {1531--1543}, OPTmonth = {}, OPTnote = {}, annote = {3 states, no death or recovery. Fitted with NLIN} } @Article{duffy96, author = {Chen, H. H. and Duffy, S. W. and Tabar, L.}, title = {A {M}arkov chain method to estimate the tumour progression rate from preclinical to clinical phase, sensitivity and positive predictive value for mammography in breast cancer screening}, journal = {The Statistician}, year = {1996}, OPTkey = {}, volume = {45}, number = {3}, pages = {307--317}, OPTmonth = {}, OPTnote = {}, annote = {Measurement error introduction} } @Article{duffy:mover, author = {Chen, H. H. and Duffy, S. W. and Tabar, L.}, title = {A mover-stayer mixture of {M}arkov chain models for the assessment of dedifferentiation and tumour progression in breast cancer}, journal = {Journal of Applied Statistics}, year = {1997}, OPTkey = {}, volume = {24}, number = {3}, pages = {265--278}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @InCollection{kirby:spiegelhalter, author = {Kirby, A. J. and Spiegelhalter, D. J.}, title = {Statistical modelling for the precursors of cervical cancer}, booktitle = {Case Studies in Biometry}, OPTcrossref = {}, OPTkey = {}, OPTpages = {}, publisher = {Wiley}, year = {1994}, OPTeditor = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, OPTtype = {}, OPTchapter = {}, address = {New York}, OPTedition = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{ander:proth, author = {Andersen, P. K. and Hansen, L. S. and Keiding, N.}, title = {Assessing the influence of reversible disease indicators on survival}, journal = {Statistics in Medicine}, year = {1991}, OPTkey = {}, volume = {10}, OPTnumber = {}, pages = {1061--1067}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{kalb:agg, author = {Kalbfleisch, J. D. and Lawless, J. F. and Vollmer, W. M.}, title = {Estimation in {M}arkov models from aggregate data}, journal = {Biometrics}, year = {1983}, OPTkey = {}, volume = {39}, OPTnumber = {}, pages = {907--919}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{klein:marker, author = {Klein, J. P. and Klotz, J. H. and Grever, M. R.}, title = {A biological marker model for predicting disease transitions}, journal = {Biometrics}, year = {1984}, OPTkey = {}, volume = {40}, OPTnumber = {}, pages = {927--936}, OPTmonth = {}, OPTnote = {}, annote = {Only transitions 1->2->3, with covariates included as in a Cox model} } @Article{gail, author = {Gail, M. H.}, title = {Evaluating serial cancer marker studies in patients at risk of recurrent disease}, journal = {Biometrics}, year = {1981}, OPTkey = {}, volume = {37}, OPTnumber = {}, pages = {67--78}, OPTmonth = {}, OPTnote = {}, annote = {Interpolation to reduce to common monitoring times} } @Article{gentlaw, author = {Gentleman, R. C. and Lawless, J. F. and Lindsey, J. C. and Yan, P.}, title = {Multi-state {M}arkov models for analysing incomplete disease history data with illustrations for {HIV} disease}, journal = {Statistics in Medicine}, year = {1994}, key = {}, volume = {13}, number = {3}, pages = {805--821}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{rich, author = {Guihenneuc-Jouyaux, C. and Richardson, S. and Longini, I. M.}, title = {Modelling markers of disease progression by a hidden {M}arkov process: Application to characterising {CD4} cell decline}, journal = {Biometrics}, year = {2000}, OPTkey = {}, volume = {56}, OPTnumber = {}, pages = {733--741}, OPTmonth = {September}, OPTnote = {}, OPTannote = {} } @Book{andersen, author = {Andersen, P. K. and Borgan, O. and Gill, R. D. and Keiding, N.}, ALTeditor = {}, title = {Statistical Models based on Counting Processes}, publisher = {Springer}, year = {1993}, OPTkey = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, address = {New York}, OPTedition = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Book{macdonald:zucchini, author = {Macdonald, I. L. and Zucchini, W.}, ALTeditor = {}, title = {Hidden Markov and Other Models for Discrete-Valued Time Series}, publisher = {Chapman and Hall}, year = {1997}, OPTkey = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, address = {London}, OPTedition = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Book{guttorp, author = {Guttorp, P.}, ALTeditor = {}, title = {Stochastic Modeling of Scientific Data}, publisher = {Chapman and Hall}, year = {1995}, OPTkey = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, address = {London}, OPTedition = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{juang:rabiner, author = {Juang, B. H. and Rabiner, L. R.}, title = {Hidden {M}arkov models for speech recognition}, journal = {Technometrics}, year = {1991}, OPTkey = {}, volume = {33}, OPTnumber = {}, pages = {251--272}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{baum:petrie66, author = {Baum, L. E. and Petrie, T.}, title = {Statistical inference for probabilistic functions of finite state {M}arkov chains}, journal = {Annals of Mathematical Statistics}, year = {1966}, OPTkey = {}, volume = {37}, OPTnumber = {}, pages = {1554--1563}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{baum:petrie70, author = {Baum, L. E. and Petrie, T. and Soules, G. and Weiss, N.}, title = {A maximisation technique occurring in the statistical analysis of probabilistic functions of {M}arkov chains}, journal = {Annals of Mathematical Statistics}, year = {1970}, OPTkey = {}, volume = {41}, OPTnumber = {}, pages = {164--171}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{rabiner, author = {Rabiner, L. R.}, title = {A tutorial on hidden {M}arkov models and selected applications in speech recognition}, journal = {Proceedings of the {IEEE}}, year = {1989}, OPTkey = {}, volume = {77}, OPTnumber = {}, pages = {257--286}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Book{rabiner:juang, author = {Rabiner, L. R. and Juang, B. H.}, ALTeditor = {}, title = {Fundamentals of speech recognition}, publisher = {Prentice-Hall}, year = {1993}, OPTkey = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, OPTaddress = {}, OPTedition = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{albert99, author = {Albert, P. S.}, title = {A mover-stayer model for longitudinal marker data}, journal = {Biometrics}, year = {1999}, OPTkey = {}, volume = {55}, number = {4}, pages = {1252--1257}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{albert:wac, author = {Albert, P. S. and Waclawiw, M. A.}, title = {A two-state {M}arkov chain for heterogeneous transitional data: A quasi-likelihood approach}, journal = {Statistics in Medicine}, year = {1998}, OPTkey = {}, volume = {17}, number = {13}, pages = {1481--1493}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{albert94, author = {Albert, P. S.}, title = {A {Ma}rkov model for sequences of ordinal data from a relapsing-remitting disease}, journal = {Biometrics}, year = {1994}, OPTkey = {}, volume = {50}, number = {1}, pages = {51--60}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{viterbi, author = {Viterbi, J.}, title = {Error bounds for convolutional codes and an asymptotically optimal decoding algorithm}, journal = {IEEE Transactions on Information Theory}, year = {1967}, OPTkey = {}, volume = {13}, OPTnumber = {}, pages = {260--269}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{albert:2000, author = {Albert, P. S.}, title = {A transitional model for longitudinal binary data subject to nonignorable missing data}, journal = {Biometrics}, year = {2000}, OPTkey = {}, volume = {56}, number = {2}, pages = {602--608}, month = {June}, OPTnote = {}, OPTannote = {} } @Article{aalen:deangelis, author = {Aalen, O. O. and Farewell, V. T. and DeAngelis, D. and Day, N. E. and Gill, O. N.}, title = {A {M}arkov model for {HIV} disease progression including the effect of {HIV} diagnosis and treatment: Application to {AIDS} prediction}, journal = {Statistics in Medicine}, year = {1997}, OPTkey = {}, volume = {16}, number = {19}, pages = {2191--2210}, OPTmonth = {October}, OPTnote = {}, OPTannote = {} } @Article{destavola, author = {de Stavola, B. L.}, title = {Testing departures from homogeneity in multistate {M}arkov processes}, journal = {Applied Statistics - Journal of the Royal Statistical Society, Series C}, year = {1988}, OPTkey = {}, volume = {37}, OPTnumber = {}, pages = {242--250}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{andersen88, author = {Andersen, P. K.}, title = {Multistate models in survival analysis: a study of nephropathy and mortality in diabetes}, journal = {Statistics in Medicine}, year = {1988}, OPTkey = {}, volume = {7}, number = {6}, pages = {661--670}, OPTmonth = {June}, OPTnote = {}, OPTannote = {} } @Article{leroux:consist, author = {Leroux, B. G.}, title = {Maximum-likelihood estimation for hidden {M}arkov models}, journal = {Stochastic Processes and their Applications}, year = {1992}, OPTkey = {}, volume = {40}, OPTnumber = {}, pages = {127--143}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{bickel:ritov:ryden, author = {Bickel, P. J. and Ritov, Y. and Ryd\'en, T.}, title = {Asymptotic normality of the maximum likelihood estimator for general hidden {M}arkov models}, journal = {Annals of Statistics}, year = {1998}, OPTkey = {}, volume = {26}, OPTnumber = {}, pages = {1614--1635}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{perez, author = {P\'erez-Oc\'on, R. and Ruiz-Castro, J. E. and G\'amiz-P\'erez, M.Luz}, title = {Non-homogeneous {M}arkov models in the analysis of survival after breast cancer}, journal = {Applied Statistics - Journal of the Royal Statistical Society, Series C}, year = {2001}, OPTkey = {}, volume = {50}, number = {1}, pages = {111--124}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @ARTICLE{bureau:hughes:shiboski:00, author = {Bureau, A. and Hughes, J. P. and Shiboski, S. C.}, title = {An {S-Plus} implementation of hidden {M}arkov models in continuous time}, journal = {Journal of Computational and Graphical Statistics}, year = {2000}, volume = {9}, pages = {621--632}, abstract = {} } @Article{oehlert, author = {Oehlert, G. W.}, title = {A note on the delta method}, journal = {American Statistician}, year = 1992, volume = 46, number = 1, month = {February} } @Book{lindsey:rm, author = {Lindsey, J. K.}, ALTeditor = {}, title = {Models for Repeated Measurements}, publisher = {Oxford University Press}, year = {1999}, OPTkey = {}, OPTvolume = {}, OPTnumber = {}, series = {Oxford Statistical Science Series}, OPTaddress = {}, edition = {second}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{jackson:sharples:2002, author = {Jackson, C. H. and Sharples,L. D.}, title = {Hidden {M}arkov models for the onset and progression of bronchiolitis obliterans syndrome in lung transplant recipients}, journal = {Statistics in Medicine}, year = {2002}, OPTkey = {}, volume = {21}, OPTnumber = {1}, pages = {113--128}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{jackson:sharples:2003, author = {Jackson, C. H. and Sharples, L. D. and Thompson, S. G. and Duffy, S. W. and Couto, E.}, title = {Multistate {M}arkov models for disease progression with classification error}, journal = {Journal of the Royal Statistical Society, Series D - The Statistician}, year = {2003}, OPTkey = {}, volume = {52}, number = {2}, pages = {193--209}, month = {July}, note = {}, OPTannote = {} } @PhdThesis{my:phd, author = {Jackson, C. H.}, title = {Statistical models for the latent progression of chronic diseases using serial biomarkers}, school = {University of Cambridge}, year = {2002}, OPTkey = {}, OPTtype = {}, OPTaddress = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{kalbfleisch:lawless, author = {Kalbfleisch, J.D. and Lawless, J.F.}, title = {The analysis of panel data under a {M}arkov assumption}, journal = {Journal of the American Statistical Association}, year = {1985}, OPTkey = {}, volume = {80}, number = {392}, pages = {863--871}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{my:cav, author = {Sharples, L.D. and Jackson, C.H. and Parameshwar, J. and Wallwork, J. and Large, S.R.}, title = {Diagnostic accuracy of coronary angiography and risk factors for post-heart-transplant cardiac allograft vasculopathy}, journal = {Transplantation}, year = {2003}, OPTkey = {}, volume = {76}, number = {4}, pages = {679--682}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{matrixexp, author = {Moler , C. and van Loan, C.}, title = {Nineteen Dubious Ways to Compute the Exponential of a Matrix, Twenty-Five Years Later}, journal = {SIAM Review}, year = {2003}, OPTkey = {}, volume = {45}, number = {1}, pages = {3--49}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{ahf, author = {Aguirre-Hernandez, R. and Farewell, V.}, title = {{A Pearson-type goodness-of-fit test for stationary and time-continuous Markov regression models}}, journal = {Statistics in Medicine}, year = {2002}, OPTkey = {}, volume = {21}, OPTnumber = {}, pages = {1899-1911}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{titman:sharples, author = {Titman, A. and Sharples, L. D.}, title = {{A general goodness-of-fit test for Markov and hidden Markov models}}, journal = {Statistics in Medicine}, year = {2008}, OPTkey = {}, volume = {27}, number = {12}, pages = {2177--95}, OPTmonth = {}, OPTannote = {} } @PhdThesis{titman:phd, author = {Titman, A.}, title = {Model diagnostics in multi-state models of biological systems}, school = {University of Cambridge}, year = {2008}, OPTkey = {}, OPTtype = {}, OPTaddress = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{putter:mstate, author = {Putter, H. and Fiocco, M. and Geskus, R. B.}, title = {{Tutorial in biostatistics: competing risks and multi-state models}}, journal = {Statistics in Medicine}, year = {2007}, OPTkey = {}, volume = {26}, OPTnumber = {}, pages = {2389--2430}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } msm/src/doc/Makefile0000644000176000001440000000152712061401532014071 0ustar ripleyusers### This directory contains the sources for the manual "Multi-state ### modelling with R: the msm package" which is included in the source ### package as inst/doc/msm-manual.pdf, and in the installed package as ### doc/msm-manual.pdf. ### ### To build msm-manual.pdf, first the msm package must be ### installed. Then type ### ### make ### ### Or equivalently, open R in this directory and run ### ### Sweave("msm-manual.Rnw") ### ### Exit from R. The resulting LaTeX file, msm-manual.tex, can be ### compiled to PDF with the shell command ### ### texi2dvi msm-manual.tex LATEX=msm-manual.tex PDF=msm-manual.pdf all: $(LATEX) $(PDF) $(LATEX): R --vanilla --slave -e Sweave\(\'msm-manual.Rnw\'\) $(PDF): texi2dvi msm-manual.tex clean: rm -f msm-manual*.pdf msm-manual.tex msm-manual*.eps *.dvi *.toc *.aux *.bbl *.blg *.log *~ Rplots.pdf msm/src/doc/Sweave-local.sty0000644000176000001440000000102512031345744015516 0ustar ripleyusers\RequirePackage[T1]{fontenc} %%Check if we are compiling under latex or pdflatex \ifx\pdftexversion\undefined \RequirePackage[dvips]{graphicx} \else \RequirePackage[pdftex]{graphicx} \RequirePackage{epstopdf} \fi \RequirePackage{ae,fancyvrb} \IfFileExists{upquote.sty}{\RequirePackage{upquote}}{} \setkeys{Gin}{width=0.8\textwidth} \DefineVerbatimEnvironment{Sinput}{Verbatim}{fontshape=sl} \DefineVerbatimEnvironment{Soutput}{Verbatim}{} \DefineVerbatimEnvironment{Scode}{Verbatim}{fontshape=sl} \newenvironment{Schunk}{}{} msm/src/pijt.c0000644000176000001440000006036412061401532013002 0ustar ripleyusers/* ***************************************************************** pijt.c: Linear algebra routines for msm. To obtain Markov transition probabilities (the P-matrix) from transition intensities (the Q-matrix). Copyright (c) Chris Jackson 2001-2005 Pade approximants method of calculating matrix exponentials is based on matexp.cc from JAGS, Copyright (c) 2004, Martyn Plummer. http://www-fis.iarc.fr/~martyn/software/jags ****************************************************************** */ #include "msm.h" /* Crude benchmarks have shown that using the eigensystem routines from LINPACK, and the matrix inversion routines from LAPACK, is the faster combination. However... Occasional crashes on extremely flat optimisations. Valgrind reveals memory errors within LINPACK Fortran eigen code. Crashes don't occur if use LAPACK code. */ #define _USE_LAPACK_EIGEN_ #define _USE_LAPACK_INVERSE_ #define _MEXP_METHOD_ 1 /* 1 for Pade approximation, 2 for series. Pade is more robust. */ #include "R_ext/Lapack.h" /* Set A to be an n x n identity matrix */ void FormIdentity(Matrix A, int n) { int i; for (i = 0; i < (n*n); ++i) A[i] = 0; for (i = 0; i < n; ++i) A[MI(i, i, n)] = 1; } /* Invert a matrix by calling LINPACK QR decomposition routines */ /* DGETRF/DGETRI method (current) is from LAPACK. This is the fastest. */ /* DQR method (used in <=0.4.1) is from LINPACK */ void MatInvDGE(Matrix A, Matrix Ainv, int n) { int i, j; Matrix temp = (Matrix) Calloc(n*n, double); Matrix work = (Matrix) Calloc(n*n, double); int nsq=n*n, info, *pivot = Calloc(n, int); for (i=0; i 0) REprintf("Lapack routine dgesv: system is exactly singular\n"); Free(Acopy); Free(ipiv); Free(work); } static void padeseries (double *Sum, double *A, int m, int order, double scale, double *Temp) { int i, j, r; int N = m*m; FormIdentity(Sum, m); for (j = order; j >= 1; --j) { double s = (order-j+1) / (j*(2*order-j+1) * scale); MultMat(Sum, A, m, m, m, Temp); for (i = 0; i < N; ++i) { Sum[i] = Temp[i] * s; } for (r = 0; r < m; ++r) { Sum[r*m+r] += 1; } } } void MatrixExpPade(double *ExpAt, double *A, int n, double t) { /* Calculate exp(A*t) by diagonal Pade approximation with scaling and squaring */ int i, j; int order = 8; int N = n*n; double *workspace = Calloc( 4*N, double); double * Temp = workspace; double * At = workspace + N; double * Num = workspace + 2*N; double * Denom = workspace + 3*N; double l1 = F77_CALL(dlange)("1", &n, &n, At, &n, 0); /* L-1 norm */ double linf = F77_CALL(dlange)("i", &n, &n, At, &n, Temp); /* L-Infinity norm */ double K = (log(l1) + log(linf))/log(4); int npower = (int)(K) + 4; double scale = 1; /* Multiply by t */ for (i = 0; i < N; ++i) { At[i] = A[i] * t; } /* Scale the matrix by a power of 2 */ /* The expression below is not clear because it is optimized. The idea is that sqrt(l1 * linf) is an upper bound on the L2 norm of the matrix At (i.e the largest eigenvalue). We want to take the log, to base 2 of this to get the smallest K, st ||At/2^K|| <= 1. */ if (npower < 0) { npower = 0; } for (i = 0; i < npower; ++i) { scale *= 2; } /* Calculate exp(A/scale) by Pade series */ padeseries (Num, At, n, order, scale, Temp); for (i = 0; i < N; ++i) { At[i] = -At[i]; } padeseries (Denom, At, n, order, scale, Temp); solve(ExpAt, Denom, Num, n); /* Now repeatedly square the result */ for (i = 0; i < npower; ++i) { for (j = 0; j < N; ++j) { Temp[j] = ExpAt[j]; } MultMat(Temp, Temp, n, n, n, ExpAt); } Free(workspace); } /* R interface to Pade method */ void MatrixExpPadeR(double *ExpAt, double *A, int *n, double *t) { MatrixExpPade(ExpAt, A, *n, *t); } /* Tests if a vector has any non-unique entries */ int repeated_entries(vector vec, int n) { int i, j; for (i=1; i 0) && (analyticp)) AnalyticP(pmat, t, nstates, iso, perm, qperm, intens, nintens, °en); else MatrixExp(qmat, nstates, pmat, t, debug, degen); /* Floating point fuzz sometimes causes trouble */ for (i=0; i 1 - DBL_EPSILON) pmat[MI(i, j, nstates)] = 1; } } Free(qmat); } double pijdeath(int r, int s, Matrix pmat, vector intens, ivector qvector, int n) { int j; double contrib; if (r == s) return 1; /* absorbing-same absorbing transition has probability 1 */ else { /* sum over unobserved state at the previous instant */ contrib = 0; for (j = 0; j < n; ++j) if (j != s) contrib += pmat[MI(r, j, n)] * qij(j, s, intens, qvector, n); } return contrib; } /*************************************************** CODE FOR DERIVATIVES OF P MATRIX. ***************************************************/ /* Derivatives of Q matrix wrt q With constraints on q p is the index of the current distinct intensity parameter being differentiated with respect to nc is length of constraint vector, ie number of intensities inc duplicates qmat includes duplicates. ic loops over non-distinct intensities in constr constr indexed from 1 diag: - no of times that parameter appears in the current row other: 1 if that parameter appears. for example 4x4 reversible constr = 1 1 1 2 2 3 4 q with constr = * 1 * 1 1 * 2 2 * * 3 4 * * * * consider parameter 1 . DQ = -2 1 0 1 1 -1 0 0 0 0 ... */ void FormDQ(Matrix DQ, Matrix qmat, Matrix qbase, int p, int n, ivector qconstr, int np) { int i, j, ic=0; int found=0; /* found parameter in current row */ /* Loop through entries of result matrix */ for (i=0; i 0) { /* check which distinct intens this one corresponds to */ if (qconstr[ic]-1 == p) { /* the pth intensity parameter starting from 0 */ DQ[MI(i,j,n)] = qmat[MI(i,j,n)] / qbase[MI(i,j,n)]; DQ[MI(i,i,n)] += -qmat[MI(i,j,n)] / qbase[MI(i,j,n)]; found = 1; } ++ic; } } } } } /* Derivative of Q with respect to covariate coefficients */ void FormDQCov(Matrix DQ, Matrix qmat, int p, int n, ivector bconstr, ivector wcov, int np, vector x) { int i, j, ic=0, found=0; /* found parameter in current row */ /* Loop through entries of result matrix */ for (i=0; i 0) { /* check which distinct intens this one corresponds to */ if (bconstr[(wcov[p]-1)*np + ic] - 1 == p) { /* the pth intensity parameter starting from 0 */ DQ[MI(i,j,n)] = x[wcov[p]-1]*qmat[MI(i,j,n)]; DQ[MI(i,i,n)] += -x[wcov[p]-1]*qmat[MI(i,j,n)]; found = 1; } ++ic; } } } } } /* Derivs for exact times P_rr = P = exp(-(qrs + rest of row r..)*t) P_rs = P q = exp(-(qrs + rest of row r..)*t) qrs WRT qrs: for row r of dP: dP/dqrs _ rr = -t*P = - t exp(-(qrs + ..)*t) dP/dqrs _ rs = P - t*q*P = exp(-(qrs + rest)*t) - t qrs exp(-(qrs + rest)*t) dP/dqrs _ ru (Pru >0) = -t*q*P = - t qru exp(-(qrs + rest)*t) for other rows of dP: dP/dqrs _ vs = 0 */ /* With constraints on Q. P_rr = P = exp(-(n*qrs + rest of row r..)*t) P_rs = P q = exp(-(n*qrs + rest of row r..)*t) qrs rr entries: -n*t*P, where n is no of times qrs appears in row r rs entries: P - n*t*q*P. This appears for each qrs ru entries: -n*t*q*P (other distinct qru in same row) vs entries: 0 (other distinct qru in different rows) With covariates. qrs = qrs0 exp(betars x) WRT qrs0: rr entries: -sum(exp(betars x))*t*P rs entries: P*exp(betars x) - sum(exp betars x)*t*q*P ru entries: -sum(exp betars x)*t*q*P vs entries: 0 WRT betars: rr entries: -sum(x qrs)*t*P rs entries: P*x*qrs - sum(x qrs)*t*q*P ru entries: -sum(x qrs)*t*q*P vs entries: 0 */ void DPmatEXACT(Array3 dpmat, double t, vector x, Matrix qmat, Matrix qbase, int n, ivector constr, ivector bconstr, ivector wcov, int np, int ndp, int ndc) { int i, j, p, q, dp; double pii, dqsum; for (dp=0; dp 0) { if ((dp < ndp) && (constr[p]-1 == dp)) dqsum += qmat[MI(i,j,n)] / qbase[MI(i,j,n)]; else if ((dp >=ndp) && (bconstr[(wcov[dp-ndp]-1)*np + p]-1 == dp-ndp)) dqsum += x[wcov[dp-ndp]-1] * qmat[MI(i,j,n)]; ++p; } } for (j=0; j 0) { if ((dp < ndp) && (constr[q]-1 == dp)) dpmat[MI3(i, j, dp, n, n)] = (1 / qbase[MI(i,j,n)] - dqsum*t)*pii*qmat[MI(i,j,n)]; else if ((dp >=ndp) && (bconstr[(wcov[dp-ndp]-1)*np + q]-1 == dp-ndp)) dpmat[MI3(i, j, dp, n, n)] = (x[wcov[dp-ndp]-1] - dqsum*t)*pii*qmat[MI(i,j,n)]; else dpmat[MI3(i, j, dp, n, n)] = - dqsum*t*pii*qmat[MI(i,j,n)]; ++q; } else dpmat[MI3(i, j, dp, n, n)] = 0; } } } } /* Derivative of matrix exponential using a power series approximation dP(t) / dq = sum_s=0^inf d/dq Q^s t^s / s! = sum_s=0^inf ( sum_k=0^{s-1} Q^k dQ/dq Q^{s-1-k} ) t^s / s! Calc: at each s need to have stored previous 0..s-1 powers of Q. TODO - overflow correction. */ void DMatrixExpSeries(Matrix A, Matrix Abase, int n, int np, int ndp, int ndc, ivector constr, ivector bconstr, ivector wcov, Array3 DexpA, double t, vector x) { int i, j, k, p; int order = 20; int nsq = n*n; vector tpower = Calloc(order+1, double); /* values of t^i / i! */ Matrix DApower = Calloc(nsq, double); /* cumulative outer sum */ Array3 Apower = Calloc(nsq*(order+1), double); /* storage for successive powers of A */ Matrix Temp = Calloc(nsq, double); /* workspace */ Matrix Inner = Calloc(nsq, double); /* one term of inner sum */ Matrix CInner = Calloc(nsq, double); /* cumulative inner sum */ Matrix DA = Calloc(nsq, double); /* workspace for derivative of A */ FormIdentity(&Apower[0], n); /* A to the power 0 is identity */ tpower[0] = 1; for (i=1; i<=order; ++i) { /* calculate ith power of A and store it in next nsq entries of Apower. */ MultMat(A, &Apower[(i-1)*nsq], n, n, n, &Apower[i*nsq]); tpower[i] = tpower[i-1] * t/i; } for (p=0; p 0) { if (j == s) { dq = qmat[MI(i,j,n)] / qbase[MI(i,j,n)]; dcontrib[constr[p]-1] += pmat[MI(r, i, n)] * dq; } ++p; /* p indexes constraint vector */ } } } p=0; /* derivatives with respect to covariate coefficients */ for (k=0; k 0) { if (j == s) { dq = x[k] * qmat[MI(i,j,n)]; dcontrib[ndp+bconstr[p]-1] += pmat[MI(r, i, n)] * dq; } ++p; } } } } Free(qmat); Free(qbase); } /* Derivatives of P matrix */ void DPmat(Array3 dpmat, double t, vector x, vector intens, vector oldintens, ivector qvector, int n, int np, int ndp, int ndc, ivector qconstr, ivector bconstr, ivector wcov, int exacttimes) { int i, j, p, pp, err=0; double eit, ejt; Matrix DQ = (Matrix) Calloc(n*n, double); /* should initialize to zero */ vector revals = (vector) Calloc(n, double); vector ievals = (vector) Calloc(n, double); Matrix evecs = (Matrix) Calloc(n*n, double); Matrix evecsinv = (Matrix) Calloc(n*n, double); Matrix work = (Matrix) Calloc(n*n, double); Matrix G = (Matrix) Calloc(n*n, double); Matrix V = (Matrix) Calloc(n*n, double); Matrix qmat = (Matrix) Calloc(n*n, double); Matrix qbase = (Matrix) Calloc(n*n, double); FillQmatrix(qvector, intens, qmat, n); FillQmatrix(qvector, oldintens, qbase, n); if (exacttimes) { DPmatEXACT(dpmat, t, x, qmat, qbase, n, qconstr, bconstr, wcov, np, ndp, ndc); } else { Eigen(qmat, n, revals, ievals, evecs, &err); if (err > 0) REprintf("error code %d from EISPACK eigensystem routine rg\n", err); if (repeated_entries (revals, n)) { DMatrixExpSeries(qmat, qbase, n, np, ndp, ndc, qconstr, bconstr, wcov, dpmat, t, x); } else { MatInv(evecs, evecsinv, n); /* TODO don't calculate derivatives wrt fixed parameters, this is wasteful. Currently these are calculated, but omitted in msm.R(likderiv.msm) just after exiting C. Should retain meaning of p, ndp, ndc, but add new index pp, indexing unique non-fixed params and a vector of length ndp+ndc indicating which are fixed. Add line like if (fixed[p]==1) { ++pp; } and replace p by pp in formdq and last multmat assignment need to edit dpijdeath, dmatrixexpseries, dpmatexact, derivsimple, derivsimple_subj in same way. */ for (p=0, pp=0; p #include #include #include /* index to treat a vector as a matrix. ith row, jth column. Fills columns first, as in R */ #define MI(i, j, nrows) ( (int) ((j)*(nrows) + (i)) ) /* index to treat a vector as a 3-dimensional array. Left-most index varies fastest, as in R */ #define MI3(i, j, k, n1, n2) ( (int) ((k)*(n1*n2) + (j)*(n1) + (i)) ) /* Macros to switch quickly between C and S memory handling. Currently not used */ #define USE_CALLOC /* #define USE_SALLOC */ #ifdef USE_CALLOC #define MSM_ALLOC(length, type) Calloc((length), type) #define MSM_FREE(var) Free((var)) #else #define MSM_ALLOC(length, type) (type *) S_alloc((length), sizeof(type)) #define MSM_FREE(var) #endif typedef double * Array3; typedef double * Matrix; typedef int * iMatrix; typedef double * vector; typedef int * ivector; struct msmdata { /* for non-hidden model */ int *fromstate; int *tostate; double *timelag; double *cov; double *covobs; int *whichcov; int *nocc; int *whicha; int *obstype; int *obstrue; /* for hidden model */ int *subject; double *time; double *obs; /* observed state or any other HMM observation */ int *firstobs; int *whichcovh; int *whichcovi; int nobs; int n; int npts; }; struct qmodel { int nst; int npars; int ndpars; int *ivector; double *intens; int analyticp; int iso; int *perm; int *qperm; int *constr; }; struct qcmodel { int *ncovs; double *coveffect; int *constr; int ndpars; int *wcov; }; struct cmodel { int ncens; int *censor; int *censstind; int *censstates; }; struct hmodel { int hidden; int *models; int *npars; int *firstpar; int *ncovs; double *pars; int totpars; double *coveffect; int *links; double *initp; int *nicovs; double *icoveffect; }; typedef struct msmdata msmdata; typedef struct qmodel qmodel; typedef struct qcmodel qcmodel; typedef struct cmodel cmodel; typedef struct hmodel hmodel; double qij(int i, int j, vector intens, ivector qvector, int nstates); double pijdeath(int r, int s, Matrix pmat, vector intens, ivector qvector, int n); void Pmat(Matrix pmat, double t, vector intens, int nintens, int *qvector, int nstates, int exacttimes, int analyticp, int iso, int *perm, int *qperm, int debug); void DPmat(Array3 dpmat, double t, vector x, vector intens, vector oldintens, ivector qvector, int n, int np, int ndp, int ndc, ivector qconstr, ivector bconstr, ivector wcov, int exacttimes); void dpijdeath(int r, int s, vector x, Array3 dpmat, Matrix pmat, vector intens, vector oldintens, ivector qvector, int n, ivector constr, ivector bconstr, int ndp, int ndc, int ncovs, vector dcontrib); int repeated_entries(vector vec, int n); double logit(double x); double expit(double x); double identity(double x); int all_equal(double x, double y); void relative2absolutep(double *relative, double *absolute, int n, int baseline); void MatrixExpPadeR(double *ExpAt, double *A, int *n, double *t); void AnalyticP(Matrix pmat, double t, int nstates, int iso, int *perm, int *qperm, vector intens, int nintens, int *degen); msm/src/hmm.c0000644000176000001440000001033112061401532012602 0ustar ripleyusers#include "hmm.h" #include #include "msm.h" /* Response (emission) functions for hidden Markov models (probability of outcome conditionally on the hidden state). All of the form double f(double x, double *pars) */ /* Categorical distribution on the set (1, 2, 3, ..., pars[0]), Baseline category is given by pars[1] Probabilities are defined by pars[2], ... pars[ncats+1] Multinomial logistic regression: On entry to this function, the baseline probabilities "oldpars" may have been transformed by covariates using AddCovs, as: newpars[r] --> oldpars[r]*exp(beta x) In this function, these are used to calculate the actual probabilities as: p[r] = newpars[r] / (sum of non-baseline newpars) for r = not baseline p[r] = 1 / (sum of non-baseline newpars) for r = baseline */ double hmmCat(double x, double *pars) { /* check that data x is in the set should already have been done in R */ int cat = fprec(x, 0); int ncats = fprec(pars[0], 0); int basecat = fprec(pars[1], 0); /* pars[2], ... pars[ncats+1] are the probabilities */ double ret, *p = Calloc(ncats, double); relative2absolutep(&pars[2], p, ncats, basecat-1); ret = p[cat-1]; Free(p); return ret; } double hmmIdent(double x, double *pars) { return all_equal(x, pars[0]); } double hmmUnif(double x, double *pars) { double lower = pars[0], upper = pars[1]; return dunif(x, lower, upper, 0); } double hmmNorm(double x, double *pars) { double mean = pars[0], sd = pars[1]; return dnorm(x, mean, sd, 0); } double hmmLNorm(double x, double *pars) { double meanlog = pars[0], sdlog = pars[1]; return dlnorm(x, meanlog, sdlog, 0); } double hmmExp(double x, double *pars) { double rate = 1 / pars[0]; return dexp(x, rate, 0); } double hmmGamma(double x, double *pars) { double shape = pars[0], scale = 1 / pars[1]; return dgamma(x, shape, scale, 0); } double hmmWeibull(double x, double *pars) { double shape = pars[0], scale = pars[1]; return dweibull(x, shape, scale, 0); } double hmmPois(double x, double *pars) { double lambda = pars[0]; return dpois(x, lambda, 0); } double hmmBinom(double x, double *pars) { double size = pars[0], prob = pars[1]; return dbinom(x, size, prob, 0); } /* Truncated normal distribution. Infinite bounds are allowed through a parameter with a value of "Inf" or "-Inf" passed from R */ double hmmTNorm(double x, double *pars) { double mean = pars[0], sd = pars[1], lower = pars[2], upper = pars[3]; double denom = pnorm(upper, mean, sd, 1, 0) - pnorm(lower, mean, sd, 1, 0); if (x < lower) return 0; if (x > upper) return 0; return dnorm(x, mean, sd, 0) / denom; } /* Satten and Longini's truncated normal distribution with normal measurement error */ /* To parameterise so covariates go on observation: Put in a dummy parameter meanerr = 0 for the measurement error model xobs ~ N(xhid + meanerr, sderr), then covs go on meanerr. */ double hmmMETNorm(double x, double *pars) { double mean = pars[0], sd = pars[1], lower = pars[2], upper = pars[3], sderr = pars[4], meanerr = pars[5]; double sumsq = sd*sd + sderr*sderr; double sigtmp = sd*sderr / sqrt(sumsq); double mutmp = ((x - meanerr)*sd*sd + mean*sderr*sderr) / sumsq; double nc = 1/(pnorm(upper, mean, sd, 1, 0) - pnorm(lower, mean, sd, 1, 0)); double nctmp = pnorm(upper, mutmp, sigtmp, 1, 0) - pnorm(lower, mutmp, sigtmp, 1, 0); return nc * nctmp * dnorm(x, meanerr + mean, sqrt(sumsq), 0); } /* Satten and Longini's uniform distribution with normal measurement error */ double hmmMEUnif(double x, double *pars) { double lower = pars[0], upper = pars[1], sderr = pars[2], meanerr = pars[3]; return ( pnorm(x, meanerr + lower, sderr, 1, 0) - pnorm(x, meanerr + upper, sderr, 1, 0) ) / (upper - lower) ; } double hmmNBinom(double x, double *pars) { double size = pars[0], prob = pars[1]; return dnbinom(x, size, prob, 0); } double hmmBeta(double x, double *pars) { double shape1 = pars[0], shape2 = pars[1]; return dbeta(x, shape1, shape2, 0); } double hmmT(double x, double *pars) { double tmean = pars[0], tscale = pars[1], tdf=pars[2]; return (1/tscale)*dt((x-tmean)/tscale, tdf, 0); } msm/src/Makevars0000644000176000001440000000006110700144622013352 0ustar ripleyusersPKG_LIBS = $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) msm/inst/0000755000176000001440000000000012061401532012045 5ustar ripleyusersmsm/inst/NEWS0000644000176000001440000006440312061341461012557 0ustar ripleyusers-*- text -*- USER-VISIBLE CHANGES (for detailed changes see ChangeLog in the source package) -------------------- Version 1.1.4 (2012-12-10) ------------- o Minor modification of package tests to enable R CMD check to pass with the forthcoming release of mvtnorm. Version 1.1.3 (2012-09-28) ------------- o Bug fix: qmatrix.msm and ematrix.msm were returning inaccurate delta method standard errors / CIs with center=FALSE, covariates and user-supplied covariate values. Thanks to Vikki O'Neill for the report. o Use BFGS method for one-parameter optimisation unless method supplied explicitly, avoiding warning about unreliability of Nelder-Mead. Version 1.1.2 (2012-07-31) ------------- o New Student t distribution for hidden Markov model outcomes. Thanks to Darren Gillis. o Removed debugging browser which had been inadvertently left in pearson.msm. Thanks to Chyi-Hung Hsu. o Corrected equation 5 in the PDF manual for the likelihood under exact transition times. The code was unaffected. Thanks to Simon Bond. Version 1.1.1 (2012-05-11) ------------- o Fix of bug in calculation of confidence intervals using "ci=normal". Affected models were those with fixed parameters or HMMs. Users are advised to check their results with the corrected package - apologies. o If user supplies an ematrix with all misclassification probabilities zero, this degrades gracefully to a non-misclassification model. Thanks to Sharareh Taghipour for the report. o Bug fix for error messages when model inconsistent with data, and when subject IDs not adjacent. Thanks to Kelly Williams-Sieg for the report. o Bug fix in pearson.msm for models where transitions are only allowed from one state. Thanks to Gavin Chan for the report. o qtnorm fixed for p=0 or 1 and upper < lower. Thanks to Art Owen for the report. Version 1.1 (2011-09-09) ------------- o New function "pnext.msm" to compute a matrix of probabilities for the next state of the process. o New "[" method to intuitively extract a row and column of matrix-based estimates and confidence intervals, for example qmatrix.msm(x)[1,2] o Miscellaneous doc and minor bug fixes, see Changelog. Version 1.0.1 (2011-05-26) ------------- o Fix of a bug which made pmatrix.msm break for time-inhomogeneous models with non-integer time cut points "pci". Thanks to Christos Argyropoulos for the report. o Return -Inf in dtnorm when outside truncation bounds and log=TRUE. Version 1.0 (2010-11-24) ------------- o 1.0 release to accompany the forthcoming Journal of Statistical Software paper about msm. o Line types, colours and widths can be configured in plotprog.msm, plot.survfit.msm and plot.prevalence.msm. o Added warning for multiple observations at the same time on the same person with different states, which leads to zero likelihood and the dreaded "cannot be evaluated at initial values" message. o If center=FALSE, the $Qmatrices$baseline, $Ematrices$baseline and $sojourn components of msm objects are evaluated with covariate values of 0, for consistency with "logbaseline". Documentation and printed output corrected accordingly. These issues caused problems with viterbi.msm. Thanks to Kenneth Gundersen for the report. Version 0.9.7 (2010-05-18) ------------- o Bug fixes for bootstrapping with totlos, covariates on HMM outcomes and fixedpars. Thanks to Li Su for the report. Version 0.9.6 (2010-02-09) ------------- o Fix of a bug which caused occasional wrong likelihood calculations for models with "exacttimes". Thanks to Brian Tom for the report. o Fix for "NA in probability vector" error in pearson.msm. Thanks to Wen-Wen Yang for the report. Version 0.9.5 (2009-11-25) ------------- o Fix for a bug in pearson.msm triggered by a change in R version 2.10.0, which caused all expected values to be returned as zero. Thanks to Brian Tom for the report. Version 0.9.4 (2009-11-13) ------------- o Bug fix for calculation error in scoreresid.msm. Thanks to Aidan O'Keeffe for the report. o Options to MatrixExp for calculating the matrix exponential can be passed through from pmatrix.msm and pmatrix.piecewise.msm. Thanks to Peter Adamson for the suggestion. o Missing data handling bug fixes, in particular, crudeinits.msm and gen.inits no longer give errors if there are missing values in the subject, time or state variable. o Other minor bug fixes, see ChangeLog. Version 0.9.3 (2009-08-20) ------------- o Bug fix - estimates of covariate effects in matrices outputted by msm were ordered wrongly in models with "qconstraint". Thanks to Brian Tom for the report. o Bug fix - "gradient in optim evaluated to wrong length" was still affecting certain models with fixed parameters. Thanks to Aidan O'Keeffe for the report. o Fix to pearson.msm for R versions >= 2.9.1 ("replacement has 0 rows" error) Version 0.9.2 (2009-07-07) ------------- o Bug fix for models with fixed parameters fitted using optimisation methods with derivatives ("BFGS"), which failed with the error "gradient in optim evaluated to wrong length". Thanks to Isaac Dinner for the report. Version 0.9.1 (2009-06-12) ------------- o Minor update to the test suite to allow build on Fedora / Red Hat Linux. Version 0.9 (2009-06-09) ----------- o Time-inhomogeneous models fitted with the "pci" argument to msm are now fully supported in all output functions. pmatrix.msm can now compute transition probabilities over any given time interval for time-inhomogeneous models fitted with "pci". A new argument "t1" to pmatrix.msm specifies the starting time, while "t" still specifies the interval length. All functions which call on pmatrix.msm, such as plot.msm, plot.survfit.msm, prevalence.msm and totlos.msm, now account for time-inhomogeneity in models fitted using "pci". o Extractor functions are now more tolerant. If a list of covariate values is supplied, unknown covariates are ignored and covariates with unspecified values are set to zero. Factor values can be specified either by factor levels or by 0/1 contrasts. o Bug fix - score residuals were being calculated wrongly for models with covariates. o Derivatives are now used in the optimisation by default (use.deriv=TRUE) for optimisation methods such as BFGS which employ them. o Licence clarified as GPL-2 or later, to enable packaging of msm for Fedora/Red Hat Linux. Version 0.8.2 (2009-04-08) ------------- o Bug fix - extractor functions were not being calculated for models with interactions between covariates. o Sources for the PDF manual included in the source package, to enable inclusion of msm in Debian GNU/Linux. Version 0.8.1 (2008-07-25) ------------- o New option "pci" to msm, which automatically constructs a model with piecewise-constant transition intensities which change at the supplied times. o The HMM outcome model is assumed to apply to censored states in HMMs, unless obstrue = 1. o totlos.msm now calculates total length of stay for all states, not just transient states. New argument "end" added. o Bug fix in the likelihood calculation for data containing a mixture of obstype = 1 and obstype = 2. Thanks to Peter Jepsen for uncovering this. Version 0.8 (2008-03-28) ------------- o New function "pearson.msm" implementing the Pearson-type goodness-of-fit test for multi-state models fitted to panel data (Aguirre-Hernandez and Farewell, Statistics in Medicine 2002; Titman and Sharples, Statistics in Medicine 2007). Thanks to Andrew Titman for his work on this. o New function "scoreresid.msm" to compute and plot score residuals for detecting influential subjects. o New function "plotprog.msm" to plot Kaplan-Meier estimates of time to first occurrence of each state. o New function "plot.survfit.msm" to plot Kaplan-Meier estimate of survival probabilty compared with the fitted survival probability from a model. o New convenience function "lrtest.msm" for comparing a set of models with likelihood ratio tests. o logLik method returns the log-likelihood, not the minus log-likelihood, for consistency with methods in other packages. Thanks to Jay Rotella. o msm now depends on the "survival" package. o Data "heart" renamed to "cav" to avoid clashing with the dataset in the "survival" package. Version 0.7.6 (2007-12-10) ------------- o Covariates on misclassification probabilities can now be specified in simmulti.msm. Simulation bug introduced in 0.7.5 fixed. o quantile functions (qtnorm,qmenorm,qmeunif,qpexp) made more robust for small probabilities. Version 0.7.5 (2007-11-20) ------------- o The Viterbi algorithm can now be used to impute the most likely true state for censored states, as well as for HMMs o prevalence.msm now handles models with censored states correctly, using the Viterbi algorithm to determine the observed states. o Bug fix: account for extra arguments supplied to "prevalence.msm" when producing the plot of prevalences against time. Thanks to Peter Jepsen for the report. o Bug fixes involving factor covariates in bootstrapping and qratio.msm. Thanks to Peter Jepsen. o New beta outcome distribution for hidden Markov models. Version 0.7.4 (2007-10-01) ------------- o Minor changes to satisfy the package-building tools in the new R version 2.6.0. Version 0.7.3 (2007-08-15) ------------- o Confidence intervals in various output functions can now be calculated by simulating from the asymptotic normal distribution of the maximum likelihood estimates of the Q matrix and transforming. The "ci.boot" argument in these functions has been replaced by the "ci" argument, which can take values "none", "normal" and "bootstrap". This is implemented for qmatrix.msm, ematrix.msm, sojourn.msm, qratio.msm, pmatrix.msm, pmatrix.piecewise.msm, totlos.msm and prevalence.msm. Such CIs are expected to be more accurate than the delta method, but less accurate than bootstrapping. There is a similar compromise in computation time. Thanks to Andrew Titman for the suggestion. o As a result, msm now depends on the mvtnorm package. o In prevalence.msm, observed and expected prevalences can now be plotted against time. Thanks to Andrew Titman for the suggestion. o In prevalence.msm, observed states can be interpolated using the assumption that they change at the midpoints between observation times. o Matrix exponential routines now handle matrices with complex eigenvalues. Thanks to Vronique Bouchard for uncovering the bug. o Bug fix to surface.msm for HMMs. Thanks to Michael Sweeting. o Bug fix for bootstrapping - now handles models with obstype and obstrue. Thanks to Peter Jepsen for the report. Version 0.7.2 (2007-05-31) ------------- o An error in the calculation of multinomial logistic regression probabilities has been fixed. This will change the results of misclassification models where there were both a) three or more possible classifications for a particular underlying state and b) covariates on the corresponding classification probabilities. Any changes are not expected to be substantial. o Misclassification probabilities are now estimated on a different scale during the optimisation: log relative to baseline probability, instead of on a univariate logit scale. Therefore maximum likelihood estimates for misclassification models may be very slightly different from previous versions. o Confidence intervals for probabilities are now more appropriately calculated using a delta method approximation to the variance of logit(p), instead of log(p). o New argument "initcovariates" and "initcovinits" to msm, to allow covariate effects on initial state probabilities in hidden Markov models to be estimated through multinomial logistic regression. o Initial state probabilities initialised to zero are now fixed at zero during optimisation, if initprobs is being estimated ("structural zeroes"). o New argument "obstrue" to msm, to allow some observations to be observed without error in misclassification models. o Constraints on covariate effects on transition intensities are now allowed such that some effects are equal to other effects multiplied by -1. o New option "ci.boot" to prevalence.msm. This is a helper to calculate bootstrap confidence limits for the expected prevalences using "boot.msm". o rtnorm() for sampling from the truncated normal distribution now uses the efficient rejection sampling methods by Christian Robert. Version 0.7.1 (2007-04-18) ------------- o Maintainer's email address is now chris.jackson@mrc-bsu.cam.ac.uk o msm now gives a warning when the standard errors cannot be calculated due to the Hessian at the converged "solution" being non-positive-definite. This issue had been causing a lot of user confusion. o prevalence.msm can now calculate expected prevalences for models with piecewise-constant intensities, in the same manner as pmatrix.piecewise.msm. Intensities must still be common to all individuals. o Bug fix for presentation of intensity matrices in print.msm and qmatrix.msm when center = FALSE. These had been returning matrices with covariates set to zero, when they should have been set to their means. Thanks to Ross Boylan. o Covariates on transition process which are missing at an individual's last observation are not dropped, because they are not used in the analysis. Thanks to Jonathan Williams. This has the consequence that output from prevalence.msm may be different from earlier versions (0.7 or earlier) if there are missing values in the data. Users are advised to deal with missing values in their data appropriately before using msm. o Miscellaneous other bug fixes, see ChangeLog. Version 0.7 (2006-11-21) ----------- o Initial state occupancy probabilities in hidden Markov models can now be estimated. See new argument "est.initprobs" to msm. o Bootstrap resampling is implemented. This may be used to calculate confidence intervals or standard errors for quantities such as the transition probability matrix where this was previously not possible with msm, or as an alternative to Hessian-based standard errors or the delta method for other quantities. See new function boot.msm. o Bootstrap confidence intervals can be calculated directly from pmatrix.msm and totlos.msm. o Bug fix in estimation of observed prevalences at maximum observed time. Thanks to Jeremy Penn for the report. The function has also been rewritten so that the calculation of these prevalences is now much faster. o prevalence.msm is adapted sensibly to handle data where not all individuals start at a common time. o The values of categorical (factor) covariates in output functions, such as qmatrix.msm, are now specified in an intuitive way. For example, to calculate a statistic with the categorical covariate "smoke" at the level "CURRENT", just supply list(smoke="CURRENT") as the "covariates" argument to the output function. Version 0.6.4 (2006-09-21) ------------- o Bug fix to rtnorm for vector parameters. Thanks to Jean-Baptiste Denis for the report. o Bug fix to sim.msm: multiply covariates by baseline intensities in the correct order. Thanks to Stephan Lenz for the report. Version 0.6.3 (2006-06-28) ------------- o Correction to version 0.6.2 with the references reinstated in the manual. Version 0.6.2 (2006-06-23) ------------- o The likelihood for certain transient 2, 3, 4 and 5 state models is now calculated using analytic expressions for the transition probability matrix, instead of by numerically calculating the matrix exponential. This can give big speed improvements. o Various bug fixes, including support for character subject IDs. Version 0.6.1 (2006-03-26) ------------- o Bug fix release. In Viterbi algorithm, don't ignore initial state occupancy probabilities. Thanks to Melanie Wall for reporting this. For other bug fixes see the ChangeLog. Version 0.6 (2005-11-25) ------------- o New argument "use.deriv" to msm. If TRUE, then analytic derivatives are used in the algorithm to maximise the likelihood, where an appropriate algorithm is being used, such as optim's BFGS. These derivatives are also used to calculate the Hessian at the maximum. Not supported for hidden Markov models or models with censoring. This may substantially speed up convergence, especially for larger models. o The Newton-type algorithm (Dennis and Schnabel) from the R function "nlm" can also be used to maximise the likelihood, as an alternative to the algorithms in "optim". o New function "surface.msm" to plot likelihood surfaces, for example, in the region of a suspected maximum. Includes methods for the generic R functions contour(), persp() and image(), to produce each respective type of surface plot for a "msm" object. Version 0.5.2 (2005-10-11) ------------- o Bug fix in Viterbi algorithm. It didn't handle underlying Markov models with progressive and regressive states properly. Thanks to Rochelle Watkins. o Negative binomial hidden Markov output distribution added. o Miscellaneous other bug fixes, see ChangeLog. Version 0.5.1 (2005-05-25) ------------- o Bug fix in simulation functions (sim.msm, simmulti.msm). Models with time dependent covariates were not being simulated properly, the covariate changes were not fully accounted for. Thanks to Mike Sweeting for the report. o New functions dpexp, ppexp, qpexp, rpexp for the exponential distribution with piecewise-constant rates. o Bug fix. covariates with the same names as internal msm variable names, such as "subject", "time" and "state", are now allowed. o Argument "hessian" added to msm, to avoid calculating standard errors, for example when bootstrapping. o Miscellaneous internal edits and fixes, see ChangeLog. Version 0.5 (2005-03-06) ----------- o Major update. Much of the internal R and C code has been re-written. o General continuous-time hidden Markov models can now be fitted with msm, as well as misclassification models. Allowed response distributions conditionally on the hidden state include categorical, normal, Poisson, exponential and others. See the new "hmodel" argument. Misclassification models can either be fitted in the old style using an ematrix, or using a general HMM with a categorical response distribution. Covariates can be fitted to many of the new hidden response processes via generalized regressions. See "hcovariates", "hcovinits" arguments. o Per-observation observation schemes, generalising the "exacttimes" and "death" concepts. An optional new variable in the data can specify whether each observation is a snapshot of the process, an exactly-observed transition time, or a death state. Observations are allowed to be at identical times, for example, a snapshot followed instantly by an exact transition time. o Various syntax changes for cleaner moder specification. - Instead of 0/1 indicators, qmatrix and ematrix should contain the initial values for the transition intensity / misclassification matrix. These matrices can be named with names for the states of the Markov chain. - The inits argument is abolished. Initial values are estimated automatically if the new argument to msm "gen.inits = TRUE" is supplied. This uses the initial values calculated by crudeinits.msm. - misc no longer needs to be specified if an ematrix is supplied. - fixedpars=TRUE fixes all parameters, or specific parameters can be fixed as before. - crudeinits.msm takes a state ~ time formula instead of two separate state, time arguments, for consistency with the msm function. - Initial values for covariate effects on transition rates / misclassification probabilities are assumed to be zero unless otherwise specified by the new "covinits" / "misccovinits" argument. o Support for 'from-to' style data has been withdrawn. Storing data in this format is inadvisable as it destroys the longitudinal nature of the data. o Speed improvements. The algorithm for calculating the likelihood for non-hidden multi-state models has changed so that the matrix exponential of the Q matrix is only calculated once for each time difference / covariate combination. Therefore, users should see speed improvements for data where the same from-state, to-state, time difference, covariates combination appears many times. o Confidence intervals are now presented instead of standard errors for uncertainty in parameter estimates. o New method of calculating matrix exponentials when the eigenvector matrix is not invertible. It now uses the more robust method of Pade approximants with scaling and squaring, instead of power series. Faster LAPACK routines are now used for matrix inversion. o covmatch argument to msm has been abolished. To take a time-dependent covariate value from the end of the relevant transition instead of the default start, users are expected to manipulate their data accordingly before calling msm, shifting the positions of the covariate back by one within each subject. o Syntax changes for simmulti.msm. Bug fixes --------- o The likelihood is now calculated correctly for individuals with censored intermediate states, as well as censored initial and final states. Thanks to Michael Sweeting for reporting this. o hazard.scale and odds.scale were interpreted wrongly in hazard.msm and odds.msm respectively. o time-dependent covariate values now taken from the start instead of end of the transition under hidden Markov models. Version 0.41 (January 28, 2005) ------------ o Censored outcomes in misclassification models are assumed to be not subject to misclassification. o A couple of bug fixes for exact transition times. Version 0.4 (January 7, 2005) ----------- o Censored observations are now supported, via new "censor" and "censor.states" arguments. A censored observation is unknown, but known to be one of a particular set of states. A major update to msm is under development, for release in the first half of 2005. This will support hidden Markov models with general response distributions. Version 0.3.3 (September 18, 2004) ------------- o Maintenance release with minor fixes and enhancements ready for R-2.0.0. Version 0.3.2 (March 25, 2003) ------------- o More than one death state is now permitted, through the "death" argument. Death states are those whose exact entry time is known, but the state at the previous instant before death is unknown. o The "tunit" argument has been abolished. Death times are now assumed to be exact rather than known within one day. This makes more sense since for longitudinal studies, all observations are usually recorded to within one basic time unit, not just death times. o Cleanups of the manual and minor fixes, as detailed in ChangeLog. Version 0.3.1 (October 14, 2003) ------------- o Bug fix. The likelihood was being wrongly calculated in cases when both the data represent exact transition times and the transition intensity matrix had repeated eigenvalues. o The "death" argument is no longer ignored when exacttimes=TRUE, as it is reasonable to have the entry time into one state accurate to within one day, and all other times exactly accurate. o More memory problems should be fixed. Version 0.3 (September 29, 2003) ------------- o Two errors in the calculation of the likelihood for a multi-state model have been corrected. These bugs affect only models with reversible transition matrices, that is, models which allow progression and regression between states. o The first bug occurred when death times were known to within one time unit (death = TRUE) - the likelihood calculation did not account for reversible states. o The second bug occurred when the data represent exact transition times (exacttimes = TRUE). The likelihood calculation did not properly account for reversible states. o Baseline transition intensities, or misclassification probabilities, can now be constrained to be equal to each other, in the same manner as covariate effects. Specified by new arguments "qconstraint" or "econstraint". o The memory allocation problems of version 0.2 have been fixed. Version 0.22 (June 30, 2003) -------------- o Fixed some minor bugs, as detailed in ChangeLog. o New function, pmatrix.piecewise.msm, for calculating transition probability matrices for processes with piecewise-constant intensities. Version 0.21 (June 3, 2003) -------------- o Fixed a handful of minor bugs, as detailed in ChangeLog. o Minor edits and additions to the manual. o The subject ID can now be factor or character. Version 0.2 (January 2003) ------------- o A full manual in PDF format is included in the doc directory. This gives the mathematical background behind multi-state modelling, and a tutorial in the typical use of the functions in the msm package. o Many more methods for extracting summary statistics from the fitted model are included. These are generally called with the fitted model as the argument, plus an optional argument indicating the assumed covariate values. The functions include qmatrix.msm, ematrix.msm, pmatrix.msm, qratio.msm, sojourn.msm, totlos.msm, hazard.msm, odds.msm, prevalence.msm. o New function statetable.msm to calculate frequencies of transitions between pairs of states observed in the data. o New function crudeinits.msm to estimate transition intensities assuming the data represent the exact transition times of the Markov process. These can be used as initial values in the msm function for fitting the model. o prevalencemisc.msm has been removed, as its methodology was overcomplicated and confusing. The methods used in prevalence.msm have been extended naturally to deal with misclassification models. o Fix of a bug in the likelihood calculation for misclassification models (the number of non-death states was assumed to be the same as the number of states that could be misclassified, leading to failure to calculate the likelihood for models where some states are observed without error, but are not death states. ) Thanks to Martyn Plummer for reporting this. o Fix of a bug in the simulation routines (getobs.msm, called by simmulti.msm), where for models with absorbing states, the absorbing state is not retained in the simulated data. o New heart transplant example data set, as used in the manual, so that all the examples given in the manual can be run by the user. o Tidying of the help pages. Version 0.1 (November 2002) ------------- o First release. msm/inst/CITATION0000644000176000001440000000122711471175560013221 0ustar ripleyuserscitHeader("To cite msm in publications use:") citEntry(entry = "Article", title = "Multi-State Models for Panel Data: The {msm} Package for {R}", author = personList(as.person("Christopher H. Jackson")), journal = "Journal of Statistical Software", year = "2011", volume = "38", number = "8", pages = "1--29", url = "http://www.jstatsoft.org/v38/i08/", textVersion = paste("Christopher H. Jackson (2011).", "Multi-State Models for Panel Data: The msm Package for R.", "Journal of Statistical Software, 38(8), 1-29.", "URL http://www.jstatsoft.org/v38/i08/.") ) msm/inst/doc/0000755000176000001440000000000012061401532012612 5ustar ripleyusersmsm/inst/doc/msm-manual.pdf0000644000176000001440000147023112061401532015364 0ustar ripleyusers%PDF-1.4 % 3 0 obj << /Length 1886 /Filter /FlateDecode >> stream xXK4ѩ"oe,ؚXcdyt[3gHn[WoMN"i{xi(rY2v~>j08:ݟIۖfh[Hң8Lw!=guCMTԲQ2M#xq!,BIN 쥔2zF ) C> /2bFQ;opipcHsu?^5:J25#~ZWz@AG"kgpd|htsR kjTlqD]EUIw(٧LDFC(KIʻhMULLR!a~Hb>E_*|\@̧ a/3oBipȂiT/=![L#k䬞/ .fȲtZzF#PD7X|!AlɮqA a:Q0*:*hxu"8Cou? JYT8|2ĎF`-{d)2q?&YݮO'+Q0NW֌r0G^- #kUZe I۩}|Me+|B”ãU=MBy<֟GzնwQx} $QT3})F3780`(t?1".>js0^H۪?a}п#Md-~9Á>| l܆Ίs]vcO6Ck"6%#6PXpL#܄_  y_㴀(c~V/p-k7aUff8ͤs3|ɕ{tfxl-~}֣#*;wF V*}M +JG!NNO <YL;]yBX*zm(ԡV74 a܉fy2g&Hf~ 4LAyJjk9eSe{rR&8֭/B|n]jՏq9TJn#+[JuR5^ Ic+}YywnQf8gjRƀC;@.]KA}VW]=T)%o-(AQ9ǪvkfP]qԛggN}L|r‡1`TY@VLEb:',x*ySƊ!)ϧXwPv_{f1.Df ;?l"B^~\\;Y"Yz*aVOwDx]jxe`.E {ppC(f?P}5dZgYOH0Y34Sxdp:Zrd&ȞO*;qI^ԓ^*K3 v}|A*e<_"6&ym6=ʗ =$st@-MnRrt=g̵^ =w[Gܮ?vU?衕sX ;"84[;ʴtR.A3V,\G>zr>0jwW ^W.Oɟ1Ǐ(-'Z(%(q4o%@\Yų^===?G8E t9.tXoCMd@ЯD ?P!@6%e#!c|N?lB7IE3=xYp{yiaMd%%C5E6+y1Cm6L"/)vqQSvvB\fYSqɷqI7)p,?Im)O)^l<`Fi"yV@.қoz endstream endobj 2 0 obj << /Type /Page /Contents 3 0 R /Resources 1 0 R /MediaBox [0 0 612 792] /Parent 8 0 R >> endobj 1 0 obj << /Font << /F41 4 0 R /F42 5 0 R /F45 6 0 R /F47 7 0 R >> /ProcSet [ /PDF /Text ] >> endobj 11 0 obj << /Length 1000 /Filter /FlateDecode >> stream xMs6<7p]N}Iuk{@)H„"5p_eQ"$i'R}x]@`$dEU9QbG&)DY?&/TӘ߳ 5UfZIR*p Ŏ %,~@ţ.u ,:xRfq@?IR s$p ՅT;jfL6{ MV$ LVAE"  …f|0mkup+Z6jBϦ݄ѡ0Bt?Np?0H1^/kVf?Si* g S?`gX c.]ɠ#JLc(nB,UvqDwzuܬsT#a_+79nd)Mky~NU^@CtcWrI%rI9r\!b7 ucOW[Sq#_ޅmؔ$!C?Zy-bj?r? 84 JPee;Unu`vS\^U!y;T1]Xo9*`t:`JWW?!8BdS/ص#3,gy[Yj6w~RГ3wg%8(\]_2\,v71Ğᓯ-àitlu:`8<~@⹍#G >6"mO/ dSy|B!ޯyیlnxHMrۍ,yGN:rk&O;e7\xTW:ʥfA ?_L(ῠNRu@ fS2 8F\~NC[:}| h^$Wk{a 33]zw|K|v;tBRk`smTΐOj?&S&nn~D%[ml aF/n! H endstream endobj 10 0 obj << /Type /Page /Contents 11 0 R /Resources 9 0 R /MediaBox [0 0 612 792] /Parent 8 0 R >> endobj 9 0 obj << /Font << /F41 4 0 R /F45 6 0 R /F42 5 0 R /F47 7 0 R /F57 12 0 R >> /ProcSet [ /PDF /Text ] >> endobj 17 0 obj << /Length 3762 /Filter /FlateDecode >> stream x]۶=jj@d3~pL?i.)$$&C{wLܜbߋ?w_򎥱H{pDŽ3)\Ȼ7,Is՗׽YLc3Uzaq!ܭysY8ˣfweS쮈 ŕ[K.TDeU :H#Mj؁єmSe}nni_MZ$^94j7n8HE,p3!\; XqƘ_iQʣ=mqZdyDxǦx<*f&u@]2zW',8v _ӌ|ʅ.I,]eO`10BFo u6xǎNIr{O`+ALb95]Wn*ژјA,ӅTe jb2zw,Xj..A@vwYF_bh{ؕN ض6;\hfg."[W[ Q2{c;L<?nFTd"iZ ivifrdGTx 8)o4Kb9 CKׇ=N}jeJ K@XAtpuDS&j[8Ft5Ե3'\d$HgRZt, G9SlM"FOi$*ǦuMmZ]Uk?t!dwI·nGY[YyFIc*]i/D"%S-,5(ЙED#X[h~MM id` 5[sjMgjkemNϐ]ǹe}Y[?j3"%H_s˕xZL&Pm?O$qQ y kw_])ʏU#XG~u+ϣ竵YTXTG$BܭU,` NLL8ohB6"Cgn߮ϓBQ6 kĒ-A43vL g >$d?i>>@5,p3vn|I?;#@L[9ZFEDf:o@>AQm>tJVr㿇=4{<4u_C;~MNݐI*_m-rld3~3MV?0B~ݏ˹e`Z`q%Ma} v ':);'Þs|E]qQEM]]h9s)"gAApK^PC0Zє@P ̖b3*Q]9 f >8Kx5^=EID3>> eT6/lLKDF >r'C}/'lXti瓛8 x2Ckf5@ QU`O`!>*?eޅ>:*޳TZ0>4msп24к3D99DMD 5R#1vTΥD20!Ҧ$K~۬.k;Et2m⌿-BPj @!|:TǼ<ς-4q 'S`ۧ#]6FyM $Gݺ-+(XZ'LSMPp,e?k~,->҈ܿiTw wY]t'F6k YӀ_ɋzdtp >9 Q/2GyBr_i@|!c>rFM [Pc0/eI'铁 xP`4q-z;TFͩigm'}Ti,u :7eb1-e+%@>S?&3fHXMTgjHtW ٠Hb~W!Jцf3F2slԄ7B?տR}>_I9#IbI=礌^ksS>_^>w6kIP湵2rT> 5 ?xx{}a|Ȱ ށ$+%'@ Ρ,o }-VT&sTKQ߷/\<~̼ԡ[o/~>)<">|j xʢj>zG2RoǢXGօSK:/λv*QȋS0ߐC JyrZ*/cώfػɼ7KOL|JL%,-CѼ`'g;~Z)O1qQzjvF.ƴSd FՀj~גA"ՠVkmYXSX )b^!X,Zh,xRzya2/&a*hEmcelҡ\a OiX5.8]6W*Wb9S{Ć Os;@sԦ.FIb.+M]jq\rvvA\'kWU5Pdmu]Rx!OzvBcx݃p,:]c'EjG)4ћ!,#醏zt>z2a.|N2<ܣfE$M49>IPףEIeYGΘ [75GCJLLSW^n^{/ͫ>.6[8H680p0n[j8H ?m ]*=fK _ctuߵ9:0x]$+9l aTqNs{!eehSijrz`@:ӗ$8خMБv0[Uw/T-sڞF-. 4蛪 ɀ(1F zXx?)P4wF_t_Fl=Zɋ_.\ޗu\A$`/߼||> endobj 15 0 obj << /Font << /F45 6 0 R /F41 4 0 R /F11 18 0 R /F8 19 0 R /F47 7 0 R /F10 20 0 R /F13 21 0 R /F7 22 0 R /F14 23 0 R /F1 24 0 R >> /ProcSet [ /PDF /Text ] >> endobj 29 0 obj << /Length 2584 /Filter /FlateDecode >> stream xڕYI-20V$jN:H^s%,o2=Q:\,X,|PU'IX!ϊP%=U0޴,A_F;;gj ,|0c1ς47f::AU|1y-~ō:K,|!:82ًhlBgU{Ue%arMU1 ;$U?6pg18;5EI^dLU>%fM;, q>\^!8Yjn鹀+vy,Y#J`[6uq+gHϐɴgor#"ihGa 0/^?Y~t͊uX8P[,fD)9B< k˄[ڞZz4e//Ōɋ'4T'o>\o;M-Aش{r ~ k8)A-i!uy땙[-y܃Ɣ WZ nT@ rM ΐ]`(*j` y'@$UaQH8f endstream endobj 28 0 obj << /Type /Page /Contents 29 0 R /Resources 27 0 R /MediaBox [0 0 612 792] /Parent 8 0 R >> endobj 27 0 obj << /Font << /F41 4 0 R /F45 6 0 R /F47 7 0 R /F11 18 0 R /F10 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 32 0 obj << /Length 782 /Filter /FlateDecode >> stream xVMo0 W̊"5`n[܆5-4͚euv$Nk zI=r2.BNYBa M\9lZ%/esUVu&J8FR Q \D5V?O.f?N/B58sh>&;XtZrmt%G*`&Y6Zl(>!z12Cr{Hn^9P{10{ 99!fqevaǢUy',G|\fre+X.\4bhre:P.;3$`-A@SuMҗ0r}Zϧ?L+B}m~?__%qQm[z~5YQ Yt+R@HD(2Nz#1{z \4\R/.WhpwPIJғJ"vl!h暛ֺJsiuMc/&ڿ͈$hF$,a/T@^"[A!ʼSZNh\*hcMCܶd@!FL#i?1cR.[`ڿC#SÈMvgqтft 8vNjc]l/C3s[K}Ofwp2V}~0/\Xu@mv{TYR+Y w]fN׋jӞ^ݮbuf!ZNԒ?ܤ06q1 endstream endobj 31 0 obj << /Type /Page /Contents 32 0 R /Resources 30 0 R /MediaBox [0 0 612 792] /Parent 8 0 R >> endobj 13 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/multistate.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 33 0 R /BBox [0 0 263 254] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 34 0 R >>/Font << /R8 35 0 R>> >> /Length 1020 /Filter /FlateDecode >> stream xWK'h)zG!i8HN 3+D{70_8׶̗hxun&ᶬ/yb-s4ץC_Lb:/ sDnKf~ЭtMxF3hU!;MP|T@7.fG.n(n Ь 8\9R9v4BCJkH؂b~W`#a)s"ͮ( ::p!{ӡ`RY29̫ebZ#۵2*2TphH8#LC7zQs}87܁TCCuvڕmt+(h U3:\AKB2$*(J VTgj/?tR޼t[|l/b%;tW1k5VAH{ӎ6 ަd#x-/5$mGD+;AѺ~QG[y *gvƃ"=,S@>1z'`9:Gp;{QMer,k j:}mnCdקuTx6 zh&G>)N\H.Ҹudhd3OPhw)Ou9F@k5'`p5[l6ʮuTV]IsQE񃗉; *C6Ub.$ڨakbc'O"1Z ?!JղS^f{ TFB@}#rnO$1*J_ph9Ry>Kt_ 7Iݣ1ȍsMqKS`,e+sK,05,lD: O[?fvKz2"$Xn4&}v?}ijP`x^dwm ‡\X>T̥-> S|4r\~_} |Ao_J endstream endobj 33 0 obj << /Producer (GPL Ghostscript 8.50) /CreationDate (D:20060622174558) /ModDate (D:20060622174558) /Title (multistate.fig) /Creator (fig2dev Version 3.2 Patchlevel 4) /Author (chris@bumblebee \(Chris Jackson,,,\)) >> endobj 34 0 obj << /Type /ExtGState /OPM 1 >> endobj 35 0 obj << /BaseFont /Helvetica-Bold /Type /Font /Subtype /Type1 >> endobj 14 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/general.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 36 0 R /BBox [0 0 650 218] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 37 0 R >>/Font << /R8 38 0 R>> >> /Length 1231 /Filter /FlateDecode >> stream xXKo6WXF #=w6` "EPyP$QUgxQ }64A @JAΰ2Q5 *dk}Q!LaH15FT0R-ۜc\y͙̌ml)Ml,$j򮴚fvkl&&9MKn5mZMAY&&EYvɖaXJPn -}.1D]⫩(#<Ă/= {qk$̷>pQLj$(9\J~BSs p?aP8Yx L6O)e`dx2LOrl GlW gHFm1n.BHiM4=qr|\g[FfvX׺;Cmf]2XklՀNa [muޖ=9v[h@]46/4 eئk]hk͌!?$Ůc .MBa [muؑi''X)C:Th%LG 8y Ei&*\븀kw 6SZ[Ӡ59~ YIʣ)soʰ͔ЉاmtK>FX>^fe&*52l3eg]}6 . :2 izGSwT $2l˿4ܝԻG%E/GqiROÏ9\{dn>~WwY@?oEg;C Yx> endobj 37 0 obj << /Type /ExtGState /OPM 1 >> endobj 38 0 obj << /BaseFont /Helvetica-Bold /Type /Font /Encoding 39 0 R /Subtype /Type1 >> endobj 39 0 obj << /Type /Encoding /Differences [ 45/minus] >> endobj 30 0 obj << /Font << /F11 18 0 R /F8 19 0 R /F1 24 0 R /F7 22 0 R /F41 4 0 R /F10 20 0 R >> /XObject << /Im1 13 0 R /Im2 14 0 R >> /ProcSet [ /PDF /Text ] >> endobj 42 0 obj << /Length 306 /Filter /FlateDecode >> stream xuMo0 4NB;Nk6۴"A߿,"l?A`n!pӜ)H\(;bTz{^4G}9z ς;^ljz.A"8GqE<+%=>y0 )SBu36t^֦G[aHМr%UQ`uí``mlzyD iISG2 _bSk/e%M-r29_%iC j4vRUjk<.ҸZEɎ> endstream endobj 41 0 obj << /Type /Page /Contents 42 0 R /Resources 40 0 R /MediaBox [0 0 612 792] /Parent 8 0 R >> endobj 25 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/illdeath.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 43 0 R /BBox [0 0 110 103] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 44 0 R >>/Font << /R8 45 0 R>> >> /Length 596 /Filter /FlateDecode >> stream xTn0 +tLTM=)>5pm @C|Hw"A<5$ghzO{Ϋyw n{dhޮ;!8>RRlʔE`Ĕ fX^ FN*X2 -{Ε4|3GN.XLZCŒ[B].IpkaͪlS>KB׍A%A&lnOq<^H `w=Ƞ ˆkØXCDi,]Z&#@M\ƔP]Yiړ&Tz Ddy -7PTtFZ_Jx^Z?^Met  PjOFhtċ<×xwL?L Qo(G<3twwHk):C"1Wm+d9 C>Iޣ.m/g9aL|OU̐v3zI[&&G˹)| ,X$F%D֬QwnVES֗ҝR[,$vc>_ ,b endstream endobj 43 0 obj << /Producer (GPL Ghostscript 8.50) /CreationDate (D:20060622174557) /ModDate (D:20060622174557) /Title (illdeath.eps) /Creator (fig2dev Version 3.2.3 Patchlevel ) /Author (chris@blankenburg \(Chris Jackson\)) >> endobj 44 0 obj << /Type /ExtGState /OPM 1 >> endobj 45 0 obj << /BaseFont /Helvetica-Bold /Type /Font /Subtype /Type1 >> endobj 26 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/sampling.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 46 0 R /BBox [0 0 360 720] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R6 47 0 R >>/Font << /R14 48 0 R/R13 49 0 R/R12 50 0 R/R11 51 0 R/R10 52 0 R>> >> /Length 487 /Filter /FlateDecode >> stream xTn@+ mvflq@ ÅaDB ')} DPS8o?-<WlSvWtxM]$}ZI-J<Ɨ_W_(H4*^=Shu0>43-fۙ9d~p<ँ?2>yMXXZTGqAghJPq CVEQq`2+Eŝ5+> endobj 47 0 obj << /Type /ExtGState /Name /R6 /TR /Identity /BG 53 0 R /UCR 54 0 R /OPM 1 /SM 0.02 >> endobj 48 0 obj << /BaseFont /Helvetica /Type /Font /Name /R14 /Subtype /Type1 >> endobj 49 0 obj << /BaseFont /Helvetica-Bold /Type /Font /Name /R13 /Subtype /Type1 >> endobj 50 0 obj << /BaseFont /Helvetica-Oblique /Type /Font /Name /R12 /Subtype /Type1 >> endobj 51 0 obj << /BaseFont /Helvetica-BoldOblique /Type /Font /Name /R11 /Subtype /Type1 >> endobj 52 0 obj << /BaseFont /Symbol /Type /Font /Name /R10 /Subtype /Type1 >> endobj 53 0 obj << /Filter /FlateDecode /FunctionType 0 /Domain [ 0 1] /Range [ 0 1] /BitsPerSample 8 /Size [ 256] /Length 12 >> stream xc` endstream endobj 54 0 obj << /Filter /FlateDecode /FunctionType 0 /Domain [ 0 1] /Range [ -1 1] /BitsPerSample 8 /Size [ 256] /Length 12 >> stream xkhD endstream endobj 40 0 obj << /Font << /F41 4 0 R >> /XObject << /Im3 25 0 R /Im4 26 0 R >> /ProcSet [ /PDF /Text ] >> endobj 57 0 obj << /Length 3219 /Filter /FlateDecode >> stream x[K6ƌ|"n Ad"KIN/[ERd$J"YU_U}Urywׯ1F~Ƅ FۙVpfw9#v(oogEPUWt~ռEͶhEӦm7PݿaI6KHl,%RߤJE7xyZBFͿMo?YӼen+~׷_gͪΗ:ANj" %.YṼ7`Z6-?29wpNݶq"A0d):Uۅd۶7T֋LӴi,`۩pNLPsF\Ne."o)"„"Fpx`x$9q-zF0knF6-ձMD&l'AC*KknkS3E8A4 jz&C_ǺZA .z-4#V'gH#g[n ͼ(`h$r¬lg/8OduI!OÞa#Yw1ܧ(ߧdB-aO~(B.eKsxcu '!DžvZk"3DuQKA?2%#jф)_Ef`@F<\'prm!£2)]FAڣB1 !ڲS{=5I Ơ#_ace 8+0Ԥa>|Ȳڶl$) ;$õK1#Y8H}%fX:yrpE8C` h|?. 2^qƟ/)^A1cr y  E$!hvkI`rkXc#DDv<֛$_MtViy21Wgl=#0u/U =WǾ̵pٻ16nA`&s럮@gU |EVCŌŴ"fæg_̿м{(ȱ´jʻG lH C${ 8k#+dH{eֹm!_-h"Vi L]TXSx7JfC4x\gP&Q;rXd~ xr!γ泈٤$ u`+*YBhDj8 "Ihf63k@fA <2#=qJUI\eO=}1H3ZL:cGWcE, 3Lc¦D#.q3яQaHV2 a;renƱvպ`E,[7Q)T#sP $~P!j:UC}Y<up؈.I⥘YUj.e\3YmeX໪jN9JKHQɻhCky,79;wa}&[ﳴ}uȃL6_рO8];3>Pe&TQ[F !_hp1H@#oocTPI1;kl2ljG`$ytX=rW\V' 6whht@}%%P>F(*5y  PϖuMuD}u^jߥ>6VixsU*~[ŦX楗B;ڄ>} ׻SJ)1YksuEQTuC]/Nr?h!:[U8/[N peTWQez$ʹHv j-w2 J ȃnC$nU9n$qsRJ@^iHǔ)*9Lp2D &!:`,f)M˖z05꺝 l+vC/-GcC,Q$᭪b׵i=$FKIN&<;0)0k͇c"_TBT ͨ'l&-a1R7cA]vJ7fՠG#h_bPDM874dM2Fv5΍bDx!{CC"KaW_8cAh:(X QqC~GOFX=f\iy Jv 2hiYFŰ;@d Qk&03lFJt3)r1A;N `0~]ʄ A \wb< 8ۃ/9~^C_`4 l$4^.F7nDq9[( ǰj # endstream endobj 56 0 obj << /Type /Page /Contents 57 0 R /Resources 55 0 R /MediaBox [0 0 612 792] /Parent 61 0 R >> endobj 55 0 obj << /Font << /F45 6 0 R /F41 4 0 R /F47 7 0 R /F11 18 0 R /F8 19 0 R /F10 20 0 R /F7 22 0 R /F1 24 0 R /F14 23 0 R /F13 21 0 R /F6 58 0 R /F9 59 0 R /F12 60 0 R >> /ProcSet [ /PDF /Text ] >> endobj 77 0 obj << /Length 3287 /Filter /FlateDecode >> stream x[KW0=cU.*UC,$VMZſ=]i73=^?d :vLR -lj_\?'L_gl[L֚rU={,K3Sn0J-^4^_hϹM ˜T*=&ƣ6R~<2!RBg:u&|{WKn\Z m+%X4˶˻jŶ{x&xkzrh-uؕ+/T deDbG&5 "Ԛat *gFs0"B9鞦ʻ}*ZbKfzXjȜ 4YO I^UmQ5 v샘[ ,Ou%ciyW65@t+OeTpC3]oq&,u@WoqyU]MQ8g.PS󞦷PPGiE-ŊiDUDp^jpQ]^Yv[Ьo8h&tP  !r=>,sma LYG{z*"KhRfuʖ.:p7o*z{ [Cg@nî|U!RTx%J&EۏmWTl]j״%Ѡ [zd~"$% ʶ+UG遄~VEi4t=Sj?AC/ǃ|7*;e6w&%;_hޣqɾ Wdϸ90Ctʻa Acoj&uшe[, {g~6P=]|'onC@xş7-{G*J"H e'kbJ_0f1@(ǔ<L-NO<9n0$&?S K-3IDMe&#3s\c) ⷷJ0OnX EJWPDD]jyGkb{2=ًj2d,K[Ŭ%ں`&;A81wQC&m4pp @B<ܗCN, .r"Gf(!M)-*+bY$O3㠝ẗ́h aQ0lbm`Z:UbV=3:![=̢LAm}T$(<0Bאd\Bhµ'QQqP> 4ev,"e/Q(hj#E܁w5"nbn; 3$ƕH3rڳk}2O".ǜ8w4;D_F]vn<FVFӜIxN|C`.4>ѬIaiQcúOwI=y=Tw%F&Y^ǂ5b2= ]ݾYVWx yIH%6b_Eső]J8tJdުƒV@&[<Կ'S%;` s FC+jP#7ݡ}`n6#Z>Ǯm0E{\BNRթsH2«Ca=B,y[6.WIq -Ϊ&^Fxr+[(C38p<6yF%!2`qg7Q(CK~>jen"<4|iǠj*PǑFsv$;InaGz\PUEJӠs-%`8vCxR)I>)3 ϻx{%|C C/I8gd%ͱ;Bc1Azy/ѧ6AtSXxMuXrV7 W;!9lG.vլ8#b.H ϭǂ#Lf5TE-!xպm˛m1Ųyl0_ Y,bY#?$̤%@wcK2g'` T%A^+Aľ:p93f{.tDیpaY*|!iFx3+4'}x}خcoP )*Za7(n3&۽?FhܳqOa!?aa πa*?ߧmMucknR[cf5T[Pm '- W26to /ѧ6v"X,[Бp `v0L3X|rXx' Q$ Botr,LT2(xr ŷE{ruFOs~vV?3_S >huCoxGq%B`G38~z-N@C?% > endstream endobj 76 0 obj << /Type /Page /Contents 77 0 R /Resources 75 0 R /MediaBox [0 0 612 792] /Parent 61 0 R >> endobj 62 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/p2q1.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 78 0 R /BBox [0 0 171 57] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 79 0 R >>>> /Length 135 /Filter /FlateDecode >> stream xMA 0  {h%; ΡPJ KvGK|b}Nn/LAېWWE܉\#K &,@LKӐD"ATC7?- endstream endobj 78 0 obj << /Producer (GPL Ghostscript 8.50) /CreationDate (D:20060622174558) /ModDate (D:20060622174558) /Creator (GPL Ghostscript 850 \(epswrite\)) >> endobj 79 0 obj << /Type /ExtGState /OPM 1 >> endobj 63 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/p2q12.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 80 0 R /BBox [0 0 171 57] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 81 0 R >>>> /Length 158 /Filter /FlateDecode >> stream xMN;09slc''6r Ƒ"HFp{\a*6v)tBƸ*p Mѧ 3MTNYU\GNc.*<~4.! l &Y&I{<p9 endstream endobj 80 0 obj << /Producer (GPL Ghostscript 8.50) /CreationDate (D:20060622174558) /ModDate (D:20060622174558) /Creator (GPL Ghostscript 850 \(epswrite\)) >> endobj 81 0 obj << /Type /ExtGState /OPM 1 >> endobj 75 0 obj << /Font << /F41 4 0 R /F11 18 0 R /F8 19 0 R /F47 7 0 R /F1 24 0 R /F14 23 0 R /F7 22 0 R /F45 6 0 R /F10 20 0 R /F9 59 0 R /F6 58 0 R /F13 21 0 R >> /XObject << /Im5 62 0 R /Im6 63 0 R >> /ProcSet [ /PDF /Text ] >> endobj 84 0 obj << /Length 491 /Filter /FlateDecode >> stream xڥOo@|=bwS+qkz 6NNxYb)8yy(dda1 914w,߱i5~_yZmJ8(򬘔V7X?6=o,zfT׈KR89"q}an]oC"i T.Q n($g61]-bA! X)pvVdT~s> endobj 64 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/p3q12.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 85 0 R /BBox [0 0 171 171] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 86 0 R >>>> /Length 182 /Filter /FlateDecode >> stream x]K0 D>,8=k(f "tdrze8]0> .) V=J{ٺÿf`y20JZݳew8@qPڰ8 >ջ dZ|MP(:Y~ث.BLi2k%7 ,qb?V+Li endstream endobj 85 0 obj << /Producer (GPL Ghostscript 8.50) /CreationDate (D:20060622174558) /ModDate (D:20060622174558) /Creator (GPL Ghostscript 850 \(epswrite\)) >> endobj 86 0 obj << /Type /ExtGState /OPM 1 >> endobj 65 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/p3q14.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 87 0 R /BBox [0 0 284 57] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 88 0 R >>>> /Length 175 /Filter /FlateDecode >> stream xMOK1s . \Iga"V'M Cy#^n0z_@x)Y Uߘ֘i O'a31pgh7p(%hpI(1 㠖úE(trgң zO`QmNNPgl8_.*,{h|+|G endstream endobj 87 0 obj << /Producer (GPL Ghostscript 8.50) /CreationDate (D:20060622174600) /ModDate (D:20060622174600) /Creator (GPL Ghostscript 850 \(epswrite\)) >> endobj 88 0 obj << /Type /ExtGState /OPM 1 >> endobj 66 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/p3q16.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 89 0 R /BBox [0 0 171 171] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 90 0 R >>>> /Length 176 /Filter /FlateDecode >> stream xeK 1 @9E.4/ \G: `v> endobj 90 0 obj << /Type /ExtGState /OPM 1 >> endobj 67 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/p3q124.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 91 0 R /BBox [0 0 171 171] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 92 0 R >>>> /Length 196 /Filter /FlateDecode >> stream x]M! =E.pL,OȌ!/Hy_t>83,WTB;,pp-aϭgh+ǀhZjQ|w۠V۔SK $/Q?TڳPe=RUF#WI+EmL ?\u~c!7,.X endstream endobj 91 0 obj << /Producer (GPL Ghostscript 8.50) /CreationDate (D:20060622174559) /ModDate (D:20060622174559) /Creator (GPL Ghostscript 850 \(epswrite\)) >> endobj 92 0 obj << /Type /ExtGState /OPM 1 >> endobj 68 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/p3q135.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 93 0 R /BBox [0 0 171 171] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 94 0 R >>>> /Length 203 /Filter /FlateDecode >> stream xU;0 w3I'`BKqRQUU>8HqJFpd .^0{s5gO1yw0iMKmTw{pn%݄$(G{zVx4z*]\UH"ȑľ3.nX2v n9(Ǎj=^hZV endstream endobj 93 0 obj << /Producer (GPL Ghostscript 8.50) /CreationDate (D:20060622174559) /ModDate (D:20060622174559) /Creator (GPL Ghostscript 850 \(epswrite\)) >> endobj 94 0 obj << /Type /ExtGState /OPM 1 >> endobj 69 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/p3q1246.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 95 0 R /BBox [0 0 171 171] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 96 0 R >>>> /Length 233 /Filter /FlateDecode >> stream xUQAn1 {H6`6OԴPRn`'7^?4]7`z4ULw(j`[rjeAT68vg<{6$i2SYr{Fw(1]g" $pq~ţiK%}g]FHx$N*{ Xm2{P־\ #1I:=ᥔWp. a_,ZUEq3a_Ezu8+^g endstream endobj 95 0 obj << /Producer (GPL Ghostscript 8.50) /CreationDate (D:20060622174559) /ModDate (D:20060622174559) /Creator (GPL Ghostscript 850 \(epswrite\)) >> endobj 96 0 obj << /Type /ExtGState /OPM 1 >> endobj 82 0 obj << /Font << /F41 4 0 R /F11 18 0 R /F8 19 0 R /F47 7 0 R >> /XObject << /Im7 64 0 R /Im8 65 0 R /Im9 66 0 R /Im10 67 0 R /Im11 68 0 R /Im12 69 0 R >> /ProcSet [ /PDF /Text ] >> endobj 99 0 obj << /Length 581 /Filter /FlateDecode >> stream x͔O0| A*{wz\VʭmB*` ԕ*U؏x~yX% 2D@ֱՆ}O'Ec%J %\7τ" ·͸xldƽ|'1L b٘gb6^R5)K` 1q_f9ZڏY.Ni{gݰinOcוxv/ATwW/"O=|k‚q3&r-PJ%MuUNI}zX hpԀ/ucZMutw+9潡F';K$ jw}:vN.ÝFX5X-SܟܤԤV&w%.D`Ic9nNw41{|;S瘰 )׳)?,sF>gi~vMPSz ug> endobj 70 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/p4q159.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 100 0 R /BBox [0 0 398 57] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 101 0 R >>>> /Length 215 /Filter /FlateDecode >> stream xMP;0 u ohc@H,:i&DRI|MKI/Iz$N'Z{w.Cn$JD 0HanNwR-PcҜیMU-/4eѨ g&V-Ϫ_b8[  bX'Ŧ{4 ݴL`{Xclg:?b endstream endobj 100 0 obj << /Producer (GPL Ghostscript 8.50) /CreationDate (D:20060622174601) /ModDate (D:20060622174601) /Creator (GPL Ghostscript 850 \(epswrite\)) >> endobj 101 0 obj << /Type /ExtGState /OPM 1 >> endobj 71 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/p4q13569.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 102 0 R /BBox [0 0 398 171] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 103 0 R >>>> /Length 334 /Filter /FlateDecode >> stream xURN1 +|~=C?B/NvzfϟQ QDx1`Q nK(2M "Y5æGܱsּnȢ~L5IK1QNj_/*e>UOCfxpH;f`2*uYZ ,f 9K^CcS0Μ-YXV+侇<'8&osYT} c9 HJӬ;Ƶ\Effﵗn)̴ϥVW.qjt1$+gy: endstream endobj 102 0 obj << /Producer (GPL Ghostscript 8.50) /CreationDate (D:20060622174600) /ModDate (D:20060622174600) /Creator (GPL Ghostscript 850 \(epswrite\)) >> endobj 103 0 obj << /Type /ExtGState /OPM 1 >> endobj 72 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/p5q1_6_11_16.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 104 0 R /BBox [0 0 511 57] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 105 0 R >>>> /Length 254 /Filter /FlateDecode >> stream xMQKN0 Y&=kxԷ@_${&I,7t%Iw+i^{zZ{|AI_tdN@ F9HJfCmIK3:4''lHmƹp* Z-By&{Wy@'+2e[qq۫^a!΅/3" R,º1%+"fr1 0ԓ_a!s%3afH5%z?(B}] endstream endobj 104 0 obj << /Producer (GPL Ghostscript 8.50) /CreationDate (D:20060622174601) /ModDate (D:20060622174601) /Creator (GPL Ghostscript 850 \(epswrite\)) >> endobj 105 0 obj << /Type /ExtGState /OPM 1 >> endobj 73 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/p5q1_4_6_8_11_12_16.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 106 0 R /BBox [0 0 511 171] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 107 0 R >>>> /Length 390 /Filter /FlateDecode >> stream xUSIN0>saĦDǽ8hR\U^#r^{KJ~N8z).rz{LgU-bVJH]1!f=]+88 o5(Pn2\պ͓܄V/XX_"qиbV 6fK)V=͎WlКhj",^bssqe Z,DȕBŶң+6Nh5j&Pܜ5l4h>[G,qfkb(D< mkUuj9n\bulĹAQ#Tq+FX>m\1.$11y_wf-=֗ݻs^C% endstream endobj 106 0 obj << /Producer (GPL Ghostscript 8.50) /CreationDate (D:20060622174601) /ModDate (D:20060622174601) /Creator (GPL Ghostscript 850 \(epswrite\)) >> endobj 107 0 obj << /Type /ExtGState /OPM 1 >> endobj 74 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/p5q1_6_7_11_12.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 108 0 R /BBox [0 0 284 171] /Resources << /ProcSet [ /PDF ] /ExtGState << /R7 109 0 R >>>> /Length 279 /Filter /FlateDecode >> stream x]QAn0 >Y%;/y [lY3EؚdH'W }ocxB27PbQ%O_p̄naS#LypeJGX%`ڸp{QcǗN02a3<8ݰul [KVjg<8S'x.ɗZbAi \;%o1z[+㹙x-Nfk,P?, 1Ɉ@\ӄ0Ӝ^ƫkʒ: U!Fkh|V!?ٕ endstream endobj 108 0 obj << /Producer (GPL Ghostscript 8.50) /CreationDate (D:20060622174601) /ModDate (D:20060622174601) /Creator (GPL Ghostscript 850 \(epswrite\)) >> endobj 109 0 obj << /Type /ExtGState /OPM 1 >> endobj 97 0 obj << /Font << /F41 4 0 R /F11 18 0 R /F8 19 0 R /F47 7 0 R >> /XObject << /Im13 70 0 R /Im14 71 0 R /Im15 72 0 R /Im16 73 0 R /Im17 74 0 R >> /ProcSet [ /PDF /Text ] >> endobj 112 0 obj << /Length 3680 /Filter /FlateDecode >> stream xڽˎ6э")Rd9d `;@@VȒ#9̷oH~L&'STw[(V׷+&D+R2O.6*$(Zmg݈s*7Ifׇ~(2 I&vb薜CVDfja,1rdhr-z}8CmiݕuOjȬ,?)ݾvâm,yՆ7j}wkXt#Y-¾T!Eߟǡj$I ,#bCuK7W<]zh-_tc]ٔ]Q=O[ќ<t@~ش7}&%ǮEd~)`J$> ۲aVY[ElFE?NE3T=Yok }ۻ3@E}*/OM0,tx=G_Wq)?`նpa#}hBe;_lC_]Ypۺ0YffxW 1JN !)bRu6}P݃ΚOrkfOqp, r\kg!5ٖuv?N(W݊EXS|"wE`L_6? 9ԢV1wdc@~O뇈^1Bj JGt/j~QiL !@hEVrnS̀ߊzk .]X7K l*Ǡ("\%mn{h ;g&'{r䙞kf*qiDsq3eyom e:G$,#x{ p\θu 0@!vc}66\k."SFOHa+fUA,\F[&kᚘ4D6qƐfD.AbvOp"$K =[;G` -9hO}w(=f2,"O OM.4Hό~#<;Grذ/B'm˗"q&!~;D}ޕC,Ӊm,}I ĦU\Zɟ=:V L:@6yF,#TAz[DTu]&eܘ`1 큱xQ dijV41F]WlgM9 F`)3x/@DE~I:8B'>K`WaP9EA\` T_ZCr!Q!8嶲:?T}۔q[J)?<(88kt%1Ix[RQXWeZԐ t_J=(SN 66Rƨ\YW,b`N0?Ž>8Ʋ' LNJ=4e, [p3VR) NGv9VS6c;"=K,mhTԱj{fGqڝ,1oAn|*ut|a1+Y|(ǟ&HHaAR*p'(6Ę~ ~̍Y"L@ؐ.ey)TM 8D,LlΔe|I vkΣ$07"`ͺ++&FoգS%4lANmCE~f$xf:-5cQ u9VShH2]$9Q'2W/IcDL1zfO&DdNVs@h 44 C,e?L ~%S,c"‚Ι''%(6SlRI3Pߊ簖+Hcsh3OЖE E-'AkRc-^,H{x, Ge/n 5 ^W\ލEe=&6bO[K-,RYjyLGt,,4081QU,1Ib7*&gFuOÊT$\HHcB(`?MSD=I< j@8Ö^G~^.IF̰LX.lMrj(=;6sPfI3*)\%de(SȂVo !LB@;Sl>f<34qnwӽ;cǍb6i;Cžp=xkWteO){BK$S\:µ@S fmhM/YeOEDDYb*.|8D\ĬCGaYI(KSfF{ ≎:p ߗQ?p5!. b,/a00汌i6&UiAnf)=ĻeWЖ]::<x_2F7Z`Tw`~N]q=FHߘ <-ڱj>){ӑOUr5Hda&AA^)F/<;We0v`itFg#K# q9!E^Gz(THJK&\t)aY|a^c敿n;gU /% WѦbcN ܴ+zہdɦHI/~5W1T̷S;=ŝ3LOa;nk;aBf -mqzt@M5ty'(h _pN}._VW4}΅ ?Ow郸%`%6ՇDtLK\t*ѻs~/=aAsH`-x8['JϪ^we=26[6xop"6jaX]B}Tc؞u`Y7P~{O Nm52F`7PI5!kR:: F%SuI2:C^XڒB~ob~@nό#eWۮBHN!4A!D2]j|r mMI> RirKe@YE]B >nJ2<l# ey u0<}^dc~_m!&Agŷh‹] ڽ}CԇGFf/CA|xE:oε rs2 MLR jD$FHi" eڨQe/X?Q X,f:k JP ZAz(B؇A L/F endstream endobj 111 0 obj << /Type /Page /Contents 112 0 R /Resources 110 0 R /MediaBox [0 0 612 792] /Parent 61 0 R >> endobj 110 0 obj << /Font << /F41 4 0 R /F47 7 0 R /F45 6 0 R /F11 18 0 R /F8 19 0 R /F10 20 0 R /F7 22 0 R /F1 24 0 R /F13 21 0 R /F9 59 0 R /F14 23 0 R /F6 58 0 R /F12 60 0 R /F61 113 0 R >> /ProcSet [ /PDF /Text ] >> endobj 117 0 obj << /Length 2949 /Filter /FlateDecode >> stream xZKW | ء&xdpzg:ċ~{|p- ]Zpy."?M]S_Ezx}/fB5fwQ懡Xb9YqboIZ=tm$ʒTҶ'Ёēk_qEgVQ',-9,Nf:O: `'RtĶ6WӜL3C zv(~X8ree =Um0~J%O7BOmWo;Lr?˧m_E$%~F/`g~,ၼJ@-$xueg?zr2ֵAƕ%~՝:s҈)/b-𪃂 ?_0I'Ծ ?=WrF5{K;/p!;*L~mgz7^ ɰG5X [i *v ?/M"X*So*!o2\*ϼڠ^C>F.*ıA[GC>gOC!^[%gua_ J#0oE},n~)z[ Q-1񎶭ڳ4-c(z0[BJixo E CX(REߏ57co=;oa+ ~s:ؔ;q=_lyΠ"b\釂lSG3<#ء{g&QQ18qImj;cPqOr bkז)iJ6kA27uȾa#8jv+qR4g?Ȳ%|7֞ d3~WoA;rցG&4t> x  NTOy P$s-ʯw ȫwۜ,E=Eu详&TElA]hbg.bv 04&A|ym3bM du'#è`cOVi\XmEڶR\ $#ZNwNH$3>+"7OCWA UB0ڼ(TF ޯ֔\TD!CԞLճ%ȅo,[09;\Nt}݇LC.aK[h31oC,7m}m;`|ءCe[pSEG !d~Go4>^[M 2BdZۜA]{D.(Clj4d13bBʁ'[VYJK5}QԴ2<$_MI,ѨIL0(_z̒_>p(3o P`uR|g w5>YB 쏽m3JYYXR$/̢Wzǚ(U] RPpy !Cw($ lcI\dA^0Z,aρZf>1M#&& >M2>tv=Ұ {( &zc(ΰ~JF~ILJx ?:-,Q4YԖ޼QfBuR*LMmLM"H`6gGՅ?:.5,V\^Ø-V϶  YdIͰftum~7Q8umc, .:Or?ؙo9SrSܢWX smFIS3 ̤?MuNa;K̆ xkk||>BcX fT066NNܺ!rDEGZ68tP(.6)ۥ 7#e D|&Z@ƸN%w١9CQ;&+9P%1 w؏͵7\᱘i sI  9J\x>(^z+)RW%kMS7 Y}=최mc5hMX,AM ^b^+%ߡDm˙/c? zJr"T i";?);C($_$Sѱ#T u?;w~h&A2% ]ޙDrZSuln]]ρOp"| `7h;@ (&$v$WMר\ ~D;o2); o("=Ό^fw+S>'ʜãF(M:*ar\I>aGr̹) yxp@^% %`Wn(}\9ֿTQ~$H/g M[(4r,~`L'(іs6bzï@C)a8L#8$蕮[:Hescg%Z@Lm0|6̻Ԇwl XXXpAn6z]p__}Y`ҜeS9(Ȉu&ׁ:uoC7Qbz^>PQJdy.<_g+luqNUෂ-eI97?J=ȝ J#)Xg7<-"NpQ`5)G; Mףv> endobj 115 0 obj << /Font << /F41 4 0 R /F11 18 0 R /F8 19 0 R /F10 20 0 R /F14 23 0 R /F47 7 0 R /F45 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 120 0 obj << /Length 2430 /Filter /FlateDecode >> stream xZݏF߿o'|h>r CSVٗۏdI;ޏE{P!#HV.Ldn9^rř3Lb%G0K"l&(__FT,2i7 -Rmtnq]/wXdrrWh_ye)xR/NZ.٦:էHX0`ú-yŶ˻^]Q `-a?+!X5_Κ'yxmjGmz~= +nZ' 2٣ pI/p`Ĺmy[e߼9vH°*$ (KJ"r#6)a#O\v9ͺ~x"xe\ 4̲pr{c<cAK|#w!7Ŧ/0:)&w}{Ke6e;ŌZ%k&}4Lx*_v)|I}KϜֶe+74 װ)_}:cC:Gu {2#}ͨTe,?g+sL$p z y͘&w_/x*I"; "H{hE` D 8?8o~l$}B8{ YSYL3 ee@1wKsWDvW23Dr>DZ4?Mk$Dz@puT/12#"E"OAJ!"Eg;^&͖/&Q]Aq:vwM-r J Z7>(G Wi;5jQ& !VQbnuKK4llF0Aa{#A l&'/K! OחQ?4JO QL0Ιx]rH5/"%nhp<@7 Enău.\"ߗ=z1`4mt 6=q- Sb\0!%}6pM£*@wN]}jS9Av}ѽ%IX&jS=[t$L (> \#mhLXh XRKU#?]ȩD_Ў\Yn( LAOg&S8p`s(ͮAsb+g݇rWa= @Uo%jԤtdx(HNb`HwŤÆ0.sh"[ *#&5W~^ڠ t1a{s"ū(f"oà03ɓJk( >*kg3Vq u#W(Yʸ7K=u^^<v%U>>p'ywu@"2_7͘t]cY&W$6m-SL *=R6v!xjJy"-@%!#Zs {jVCԯc3dm꼞|E\җ0ٯ mqe𱰏OIb[lFL5xam27P~&f!:c ǟb ԡ\w{Oz\Hx?\})gA o sBPCd!%0T"$01(S/_>q# L(t jik"oYz*$>2@M9)cm`(D/48Pbԧvh fXʿ!TY9з d7Me[qc⾵B?o/w{l2ƍ|3Έjg(ߏ)7} %6"%ثB;&? endstream endobj 119 0 obj << /Type /Page /Contents 120 0 R /Resources 118 0 R /MediaBox [0 0 612 792] /Parent 121 0 R >> endobj 114 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figures/hidden.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 122 0 R /BBox [0 0 360 720] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R6 123 0 R >>/Font << /R14 124 0 R/R13 125 0 R/R12 126 0 R/R11 127 0 R/R10 128 0 R>> >> /Length 762 /Filter /FlateDecode >> stream xVMo!+8R2ǵR.Tn\Me-%Zw`5%VR}7?J@)^<{nw=zZ>Cک]|G(! ^~زX (XdX?Xm~[oq{AʻG!12FvxN\N+چV[J1ƙVz` 3Zccb"ޭq,ϞxIZeB3"uqatSB;sN ex5TysΆW$ ARUtϰi/F6<ۗ`kx& _K}.*.* L r|}d pVǛK48xC8G@x‡#*MskDbF+=Ao R^ۤgљ^2ZȶPq8#K.Ei5{$-ozzSB9~/9vSvA16qDRD'~WHl,-Ƅ+y/үdL8ɕ~Wul2F_FѨbvu06x1⻂KOB}Fwe> endobj 123 0 obj << /Type /ExtGState /Name /R6 /TR /Identity /BG 129 0 R /UCR 130 0 R /OPM 1 /SM 0.02 >> endobj 124 0 obj << /BaseFont /Helvetica /Type /Font /Name /R14 /Subtype /Type1 >> endobj 125 0 obj << /BaseFont /Helvetica-Bold /Type /Font /Name /R13 /Subtype /Type1 >> endobj 126 0 obj << /BaseFont /Helvetica-Oblique /Type /Font /Name /R12 /Subtype /Type1 >> endobj 127 0 obj << /BaseFont /Helvetica-BoldOblique /Type /Font /Name /R11 /Subtype /Type1 >> endobj 128 0 obj << /BaseFont /Symbol /Type /Font /Name /R10 /Subtype /Type1 >> endobj 129 0 obj << /Filter /FlateDecode /FunctionType 0 /Domain [ 0 1] /Range [ 0 1] /BitsPerSample 8 /Size [ 256] /Length 12 >> stream xc` endstream endobj 130 0 obj << /Filter /FlateDecode /FunctionType 0 /Domain [ 0 1] /Range [ -1 1] /BitsPerSample 8 /Size [ 256] /Length 12 >> stream xkhD endstream endobj 118 0 obj << /Font << /F41 4 0 R /F11 18 0 R /F10 20 0 R /F8 19 0 R /F14 23 0 R /F47 7 0 R /F6 58 0 R /F7 22 0 R >> /XObject << /Im18 114 0 R >> /ProcSet [ /PDF /Text ] >> endobj 133 0 obj << /Length 3746 /Filter /FlateDecode >> stream x˒ܶ[8B|U)䊷*H:p8%9!9oO`^VRD~w1~H "nn`JFp7뛗FqY%qtퟓZ8z:+o*+ZMŒ:*]y5mhlfQK}o{o3X2%Mo5mfFv; %5nW?$HKpaiFoYRMU Fƈ f)Z7`+DgZ5YƬ]KDhWWi4*d7M$wۼl!mj$4J̭vyWeRˑ’ $L!nЍ!TQcY(%Lt8p6Qw!01{|:)FRvs$iZ뼼3Q[9'Zn:yʰޠ>a"QzW1C9߱#݀!#ULHbxFȞBbԈ+q 8DS@u4=G5|v$!I.1iLU#s$3(ypmUwju%uڬ߸b਼Vid^7 Q&x-%<62?@|ᾋӵp}wROM^%Ay0u$+BVS=ucͬDO`Gؼvn5,m{Ik;~Mx=;tN٘.'1 Ж)ǹ&Hc80}1v:<'lNFM3d\zL֞Oguh;㜆u9{/Y];7.N1C<_j1B.FbqtrGMw>RJY z y!̆KPk`zf Ir&S~yFEg`q(87dNBb¦x]:o]2z()L Ha6=#X5i0ֆ1SRPR&@r4#??ؓ~60?d= uAJ! 01z?B>{Idgd&@Wo]u͗}ބɜnXliW5M*)lĒgD20ʳiy59GˬYT컉;ϰ0ᘅgESy.c:xdQM+2J'7oĬQeJ&q l2vLJ"!-:2UoI Q/r ;y@^xqgAR,DQנ6I?鐈WQͣAik!Vk>̓|sS\Šجy$Q.3f%i֘$pY8cBUfJre]O!/~uV[0 ژVPt6/lq-ƍ:[mͯѱ̕A~$M[X%pwC`!ؕ9Wv"z'p2c DzT1D9ZūS4"T@7L/qV9?Kҏt!R|a, Y>?O颟__ o]z%DƔqx<# k^*D,8e$Y"imVF17p<OvtM /+SG b!ԩ'&_1y[%`r-ORx,5TNNI7tRR@q>*GG4좤{\."u UHC#MNmWWdy{:Y/Z]RG?b}EzF_)e? ?IP+r05)QUS+<1QA5t˜AJs4LL4#M0#dƇKx ^9,x#=fشa=->N䱃?\8p% 4մjT:44+Q)"?֖+ M{R$J7Iu-k&B!&٥Dmkzv1%*8D)ѷ+q*zl8N?ܫBM&a3i;', P[}~޼ܗ*u' _Q35#|:\f:鰨BVkO=].TvMHٍCI]P^bVZ$Yk [%H#Bg8ۺЍcBt(*];e/FJ~\ ;svHN:N&O68t ,RU\CVA͟ /ۈ3]wJq'gXb:!> endobj 131 0 obj << /Font << /F45 6 0 R /F41 4 0 R /F11 18 0 R /F10 20 0 R /F8 19 0 R /F7 22 0 R /F14 23 0 R /F47 7 0 R /F9 59 0 R /F1 24 0 R /F13 21 0 R /F6 58 0 R /F12 60 0 R /F61 113 0 R >> /ProcSet [ /PDF /Text ] >> endobj 136 0 obj << /Length 3399 /Filter /FlateDecode >> stream x˒6%UTbp٪&8d#qF)r‡so7|@FHx4@o>d,W&֌Tc.n*zq~}×ϙBUB / ,T4k&t@K3- ^mX,3IPb1jz&<:Xl-AT1nEy.[v}Q7lƭyȄE"}'mv-ȁpSu>P/v:]XbBGof辦nfi.Z@&5 `*xbLx[Dx#3@N6>SwG ,zmNlj"Ζ>׻+ۼoښj8_WQq-6$2DJ̶+X0Cj  o;y}Ѻqtߖ%5mSoeS}9n:~PPO~U~m D]Fpa[(`/|lQUEJd)wdh Ipn\Hб`%3hʲmlG y ܒ(<N"D ""Cc@4TV[$iR2O> 7a*dq&oJ*ψ"7ue옛n ʞ`p_i7mA q-,Y8K@l N#1qz~aXw.I!OMJ̒E]Ejc~,G0^-å0hSU h#alѡkh6P4iȶ9X %p`( ȉ3VqU 8(9λOWhvHm@ČDMoUͣHGq2 v[tX7nr3+1mف)\sNs5arU8%߅݀<X̉H!L^`BW-r> }as96A`R/Ǿ>3N63j*;h+0˒A-MA\":\MԛxJ1טePC>װ~m(ؿRX5*x|aߜ"1Iř"ai\NVQ q%\Ns23{Â%s%E0+ e ;~k7Mݠ/d\:g}^z9V2рsTNzdG0 7S~yLTƁ7og$$IL,Ad(sd3~q) O!pdY2S! Gv 7w)Q:Ti٧a?<C4 =RlȂriTJ=1QIYтC@3:kpCXEۂ->}tJL3Á.N`͎@I7jzM*N} { 5X5qJ{-o>Dq V>]QwxSSk>g 0Tγ mB9PפM&bƏnna̽NoӺח,*" .?GOlLwWJ endstream endobj 135 0 obj << /Type /Page /Contents 136 0 R /Resources 134 0 R /MediaBox [0 0 612 792] /Parent 121 0 R >> endobj 134 0 obj << /Font << /F41 4 0 R /F11 18 0 R /F8 19 0 R /F10 20 0 R /F14 23 0 R /F13 21 0 R /F7 22 0 R /F47 7 0 R /F45 6 0 R /F1 24 0 R >> /ProcSet [ /PDF /Text ] >> endobj 139 0 obj << /Length 507 /Filter /FlateDecode >> stream xڍS=o0+4R@Ő?ĵ@ @ ]DJ") i]KQx#m9-4֒ɢ7XQVH0EOe*+V7h7Tj(C>/'(,4uczWj !5X9c)n(*wE_ u!\BuuV@H}фaR3q%%:83LqLdI]REtǐnj$%TR<XhseTv4jI$:f=*٩[{r-'e#bs}||{!x6MQL%6- zCu/l[wJ.Bm)j:Z^Gox1zmί$/ôIaШszX PFǠG;Yg^9e[Qg2p/f!? V+Xs~-l oJ%{6 D!eܷ! endstream endobj 138 0 obj << /Type /Page /Contents 139 0 R /Resources 137 0 R /MediaBox [0 0 612 792] /Parent 121 0 R >> endobj 137 0 obj << /Font << /F41 4 0 R /F11 18 0 R /F10 20 0 R /F7 22 0 R /F47 7 0 R >> /ProcSet [ /PDF /Text ] >> endobj 142 0 obj << /Length 2085 /Filter /FlateDecode >> stream xڍXo _h-@ }hi޾3d@7/%EcOMN)")G~4H\<od"/o*n_#8_8iWYuS;Q3ahthlxd"2Ip:*n*Q*G}+%T_"- J÷Im88 =K=i99h<1=}&Fs[8>dV>SE{C.'y,*폥T`K)/%'*2-ZtVwu鍊}kN5ahhM]Hv,<^[oO~`Gma';1' 0jp"\C6 ASfٕ`m5m;ђn}d1q'}48=iꑗvh 4#k BTDp|m\Io4L3UJ%ty8 ɟ6B$UQt7vXM{C}*v|梄XC3u=ORd\r֌n+,K }$X 4>Qי$U%lFTPy WuF"y)KJs" H!%(3^v|', g|u ,~Ȉ VƁg:W(*c-Yş(,ਚ>~WR1ֿ@g=b5ىe{ 4*E#[AKl{4#e/kYXL DUVk>seGͰSYܷCݸ 'Hec!/>&Ax|Op2xwV^FҚǝG= XB7G ΄$R i,JUY*bDHeUQg>+AB14 4^ܨ;eg`pRK@Yʯih|V,DnU_1D/ 2LDn(5 `;,Ŋٛ׸Uɴ|hjj8 9['Y\}>ÉH[A~-{o0>ɺav&RC\03~ *neQA5@B'܀"'+q;^JtR Vs]36PT& )`m}uuóƙVysԛ-gPq \Ip$ fṘV3vq]=8B,x kS.">,a>b>GENx-LλdNzȀ;NJxP+Bo @H㑐z1=A_{&1 CEܕit7! ^!vYA[ :(~]puMh55[}H}_u8h3x O+{%\9R*7%6&@j~u$gsH/7Bs׭Bݏ5=G,Kx>j\Lݣ}S_%X_s˒u\1ڹ^My8G3R`B8ɴ_ &D/NFCU [2V`Mia%o7\^lIśHf()|W Dmz!Y[5S=|%0[<ߙг)hfŜ32B_,>뺚wBx0z"שgD2D,Wڶbt~vDFnCB,KpX aC_.Ο_}i;L8|ean',7[yU7qȆFC_c0H֜%d/ԜH{0|ѽq߈H;Vǒ}NaeVg#$.}/?}%17n4O;̼A??VM4Mh\LEk 幆{Φvz5bEi #x=ɯ/ɫ_BNeM,p_>= endstream endobj 141 0 obj << /Type /Page /Contents 142 0 R /Resources 140 0 R /MediaBox [0 0 612 792] /Parent 121 0 R >> endobj 140 0 obj << /Font << /F45 6 0 R /F42 5 0 R /F47 7 0 R /F41 4 0 R /F69 143 0 R >> /ProcSet [ /PDF /Text ] >> endobj 146 0 obj << /Length 1543 /Filter /FlateDecode >> stream xڥXM6WVX+R$)& 8$9hmV`KM3"i8 q8ofue&&7|5!rʉ:BNɻL1-z$[T?)`MQLfK7~zo~>U2˧3Yڇm`f6ny oQv3Kex3p]\ʬ^jM:{wzWv5mѣ:Z}W5nHpeS9Z5FuW<(~h`r BfIK- .jݴ. 2uޏە^XduA4\"}}hW]]om"b\X.1kYQ }.d~As5 6 |\19gqhLh@{۬iE/0f+dرKitj]ڎ}%ڟjQŘ:x̯O1c(lgmt>NJu"kb~4MLj]:ӘVQk=rɝa (,.zafa6lP};$XIXE)NI7n "_e_E2E`0jd/@pcnj:%@ :ge1Y@:YK%5_nrU!D)sSI`R\: ;VT!Xjwk"wr-*.3~~Hw[l*^4:W R7Zno3m酋CqИbtP*~L`"C7{P? zI}9(קq}4:/9J:ڷ7AmdY/E0FC_ѐlAR{TVfɶ"۟;oiR<^J\s$!h'8!C KlNz }[:y%CO>j&hPxٿ;iFTVO~ #"^1Q [0ް߂u0|3Kr3^V*iy H Pq]ē@E )Xgآ ?$S@jk@*@hHt ̅d 6v"TbMN82IoI:,WpVZ @]2}7Os;P2F ~Gƀ.o_Phx3|H)T@EH:0#SbZc @#†|c @kOTYT2rof*g ,`@:DŽş@8KQ"лD U'V ""a?:n0IEIB#+ARBCS^kB}MX^sŌwYz4D> endstream endobj 145 0 obj << /Type /Page /Contents 146 0 R /Resources 144 0 R /MediaBox [0 0 612 792] /Parent 121 0 R >> endobj 144 0 obj << /Font << /F69 143 0 R /F41 4 0 R /F42 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 149 0 obj << /Length 2045 /Filter /FlateDecode >> stream xڽ˒_TYēaS^oy*'q2Nq ZB2;h"%<޸|B~zx{%V+0ÊKrcWFLHzدflV[Y,;+,Oʻ*9k¬Kkwgެ,+ZmEƄVDva~l]>؏SUXն! Py# 8fzL+sYu%ֻnHhy7lmsW=Q !- >bk=IcYgCѴ+wG ýÅdZ@>%gVO0Qq>h9iٌhqCurIJˏ~Z*bȥ[u؉Bn)X4ME\phEOnOi,@yZpX뗺a0"5ÙT=C>٩?0]ȸ|-Q s]GNʰ Ƌ_!Z-ß7[di<5`ovGXN ` ZgCמ@o;"2SÉ)UrRK s̎JW6d:H'Iʋ^ / 呃N60q}+ <o "Qyzv!N;[o!ӆ{WGƸ@}gH" lL@ɯAHFj9C;vnWpBx>>|#pUǓK4S.5 Wd}‰adݮ:X5CC.7Q+ɡ:ן[1pmN@s]ׄ>Tu>=3C5e?P!B_lF쎎%#{:.P-92H֎0a؎:z_}~MT^Cd1,O0WW}a"j8t(&?Yr#h~0qfE-Gk5,o 0,K3"R"ϯpE ÿ8?MC?s&1@z8t gBJG GFtHW ZiOCm-{QBVQ4G7<9`77>S) Pxȶ[B=q7'[ly\^?dwnsx yaO 1fjoڠKdvzoTD˷.N5|voD*S&lq+W=?[1ZLLY)^ͦ>w 9TNT`~ endstream endobj 148 0 obj << /Type /Page /Contents 149 0 R /Resources 147 0 R /MediaBox [0 0 612 792] /Parent 150 0 R >> endobj 147 0 obj << /Font << /F42 5 0 R /F41 4 0 R /F11 18 0 R /F69 143 0 R /F45 6 0 R /F8 19 0 R /F1 24 0 R /F14 23 0 R /F7 22 0 R /F47 7 0 R >> /ProcSet [ /PDF /Text ] >> endobj 153 0 obj << /Length 2999 /Filter /FlateDecode >> stream xڽ˒۸_1GA'I'*l6R9ds$ΈkIC=h$hx}"F?;oJVanV7\, oVۛ/V"[t[T DN,S&愸EƔ~:9~-^<[ڡ95];wϱ{HzlL[QSn`~ $ e5)-NOK"7^fMמmxj0׋%c7kw_)u "ntɮr}Q1k܌AVr`PZĝѷE27BIƋXU 䋏~DR,$D}=vK:IiД=xZ@3XۦzZOnVqXX=Cg^ !-y/I+Vv*ۉ%_'](94C=;q;7}}-s V3aa8`L#dFq7k@95!XL^LIU1E0t0r,!M!'zfhBkΫʊC}z Yn 1Uw\H!y-QSByXA?c<ۦPюGD N }+Ȝ[%ȺTDvkXG ]74|غA};dCB%qwo{=b h;zGAb'WA'#Slv]c eY2Ъg],؂HΚ0;hO ~aܟ[9wn`)1$$ R"A\P#(+.Vc lͰك67ՌhC{׎$I`"<6%RP<4U|%NV-#dpʴsCO~)P}?9YHD2D831sI U`hz xr(2;~X5 gVd?帯6X4rn==m7a? e`HH[7% fepX"O2qj-8zITh3O쒌aE>(yTxV/r NT tsV^"X)4W֩R@R*TiA qKJU,ySյ. $DƜ%DWd4~3J0.L`fsm@֓:S1\.Ѹ"e _5P/mCe dEo0LrؽԫԅWyY#WH Z3/Y[9C$}tw/8 Uj gMyTZE+g`!6ibә/ZW7Uܫ8j-ə*-Hjn<+BdKF*ڡM?n8ACVjA_v/t=dgc5af!s=cy_= >4m=|1ңu`i)8}ﻐPJnƽO5/+ q}i}:]LY2 iN=ge$ُ_oSu>WZLUd;f%Cc!F6} έwY-$X"\Xcf顴IHҞ-;CGEUW)o [9j3 6Hm \҄GUCaYi\p! AǺo Y;}H58\pnrwbmяx\ĺ#k[;Zz Aކe)ovXzZhDպf= Oi pn|*Z@ ^DPs.7/;Pő_S"uiv)gBEv`\dn:(+"OËX̜88sKDc1+^dJ pJ>!M MH&]JCi->/"!&_Kyņ]IZa.=._E[/0yľʆznW2)f/CgR> f>0H5QY_ /цbJ| :wO.wW :=]OkV1tv)ݥ\D[Õ9vV\ܺI~JQ m$}毌L,ƙ].mzJÁIV:H2a gN[z(AhHb[{ )X|$ 1B 6S*()Q'xں"<{9hm 4G:\Bw? > endobj 151 0 obj << /Font << /F41 4 0 R /F42 5 0 R /F11 18 0 R /F69 143 0 R /F7 22 0 R /F45 6 0 R /F10 20 0 R /F8 19 0 R /F47 7 0 R /F14 23 0 R /F71 154 0 R >> /ProcSet [ /PDF /Text ] >> endobj 157 0 obj << /Length 2501 /Filter /FlateDecode >> stream xڕYK8e9Kf1fٝIwp5: O3qhx9uh}Xzv 03<$~8KOškj+ȌQzMeb5Z}lu$Y;8vnlO=SʦwmG[8l'^ YCs?5_%>7JC]Q>RL5qft(oy04IY:RvR pk҄u_/PHe2y!e4R39Q1)^u?HOCxG}r;JJuwib80ƻٛ>4F6Nhx7*Z?a$;ѷ߽eRçA 8#qO7<MO^DI}r Y?s) $Գ̛5\Y][&m}tCLoGж{^4ES=Dl/t?]^;(Dx~h`Zk5|)@QkԂ$=B-PkPl[[MYC\FB ܡjsxe~Cx#ݕLEesP>U~ޤ t(t:14Ņ+!T&4q6ٱ /1"87c6=qX4?now|i8!8֐j2t#}#T c^/RF.(Y(9ܗT'C81:sbH1Fe}l;~"` ZЩ g|k< DG"t׃}ǎV})Kh1X̛> +J P 7^1f¶~8jN SOa]1x~hhl"_o͊I,"5j(54dlm5ԛIK=$BTcY\B<(*{=\(SdܑX ;5z 6xC / q z y޳GC˶bkeWRH СDpӡz'6/lB( ? 2[!aFkL;g/ywjO~sQOGhV5ˀ&KzTy2QMs ~| ҫ>b],DtIGbT];.ҪI sk~OqțGVMAƞNo:R_R/i wHQ4N11"&Z:GuKc|֦< cVO>^&'~ן:w_,'R+V91A4Z24 $S> endobj 155 0 obj << /Font << /F41 4 0 R /F42 5 0 R /F69 143 0 R /F45 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 160 0 obj << /Length 2462 /Filter /FlateDecode >> stream xڽێ}b^ XԶ[ @ l".Ac;Ҭ$sx(YmZEx9ɯ7zMFK[nf)a(Z2N [fəZ r&WjQ8lrn֜煾)"\*f怄 p2Y 1r@y!a!WB~H KO`@knoH2RTLe! T2 慔*Joi`mw@ r$nn\RJ+k YfcfP|W3LW=٣5{ʡpv7~iXq9n٧ u@ T+y?V}{G)Tό]Qj-|GeM&ғqF[?t}FHnj.n\08Z!8FnSoshj)^9z߶;2:Em^58pA4!Q(qXMTZbnSU6he%5OfYS5銺oγ/Ul8NZ ;'?;jr nv!:;o. ~B]&l ǁz2ʸPVqU<~SxuC(bBڝt ]C=q7n1~IwFU@Ƈ`T]X{f\, qi!禟@*u =.؃V ͧlʡEਗFqI[$inO0OlȢ%U{ZSRApIY`U&-&&a4Jh4"e1R$U>& FKl͝5< kԸK:g`~<c.;'6ɎbA>!C?=\)ɆJ64 6䰠S$14-(L>>^p=,I6!%ZqRD sq֝VCrXt=xZ}29% Kj>TdIkO- &دB![(Gã'G28_lٻ y*-VjF)#mz{cIgxD @sWU5-$3%5cݍeR %J F& Jл#5^. S=WX )My6)9X_.(P4Pc/+2YQK|,s%{9C>6<ʎUDr!= W܏XE 9`Wkip9MRI8Z:. WVq?J,0BP'8CJ8nVMK0.%V5vGR48~L;8!AXcp,6UGjZatJm3/q \VE3qW5Rʺ d$8H`1n) ZIK90d=0]b#|@}ha\jXRV*I uaG!29t|r{_ BEnuoHbKyĂaNWL UM˛)N|`b?t=nLnyFOǩT̄s⭠W.vQ"3@(>]9E2 }G)\pFw`@S*WfQrp H1?%`ӟ.EMhǻoH7 x%^t:oYGt57[̬&OGj+=E֙d6"O'?_ |ݘִA,ǪFr[wNl~aYD"-m}P~D9e= ;EK|U׌%YJη|9u+Z^LBPb6z/d!`ߋO:O^uo:Yig7/1gPKW6>$E BBNAt{!> endobj 158 0 obj << /Font << /F42 5 0 R /F41 4 0 R /F45 6 0 R /F11 18 0 R /F8 19 0 R /F10 20 0 R /F7 22 0 R /F13 21 0 R /F69 143 0 R >> /ProcSet [ /PDF /Text ] >> endobj 163 0 obj << /Length 1579 /Filter /FlateDecode >> stream xڭXKs6Wh#!Ns货@˴)%*$;=wKQ \.}/i;(7[ϔ»0s v]1_:)3?rTB(oK+YBXH$__grTJD{gz~Eu#TB)NTq+/vH H}4S -CG,&m.V!ޞs"D NYX&NA3ASt4ubAaY"o/]=Ki0™غV };H-~ )4q8 pHA);FeZg_t*PF%敏\cMc"փ $ &TyeZ < %U^DIxc'/|T]a,}ZMz! x@Af7a2f#dەդbsP@UK/bl|{T-RfxQ4Mݴ |=KQ?˻#ʶQ۶CU9WYvWU}_H.XȞն(C W+|7S[>lR:vb4Ag=ћv=ݔ/jk~uV~vOݰ;gG!HkX/#Yi7gŁpeB0͐۶zԴ+}RǪj/"gNDyJ[t Z&Tgj yЉ>9 5UNAZDA7G6S~tX_Yʠ *  SlH ]ІW򱫒}@`h~O @=#Jr(DuM#1*S]GApmjݨ wRl$l|+X= Z#.NJw\=MkLe({on0-*Ek \Hջ**@I}&RLbhhn@ {jC0Ous\ z8.s+KiYCdd1?ϝuѢMY9xl-x.W)o-ɛҷmу " 6ʼn2=g(߯Nڛl;A[OGT 9[)4KAO,ػa<{dgardUI(4HY')+ܭlCoؠz*@o~ki齁 W {6ҽ|  \?рe &ȱ706%W;x"gv.Ql-櫪7V3XxrL=-I=KntLU8z endstream endobj 162 0 obj << /Type /Page /Contents 163 0 R /Resources 161 0 R /MediaBox [0 0 612 792] /Parent 150 0 R >> endobj 161 0 obj << /Font << /F42 5 0 R /F41 4 0 R /F11 18 0 R /F10 20 0 R /F8 19 0 R /F7 22 0 R /F69 143 0 R >> /ProcSet [ /PDF /Text ] >> endobj 166 0 obj << /Length 2374 /Filter /FlateDecode >> stream xn>_#HLٜ6YzC6Jj DCRc;|{ERuë,D Ps,O'Ǭs] >=F$+*FRX@/rx ү?(vZ( #[Zd4m!q!<(JsEPuiY8IU<Ӣ8t %E[vMmQa> pm|%)ҳ>ƺX>-M,ٺEݕ}لPu+Xgy:u$[$e8 {E[TwmGPIs$*`ن xp[.܇|ۥ䛠q :0"e2#h&wy {QpJ@вw喸r{OK/Oxp1{X(@*3)ѕT<¤\(44Z$毪'Yc:`=a3ؔKK4@-ȴ*zN/dz+ZmP {/hus ƒUѷP<*@\:!6_H4TD5eףf +~!P`x-{_?"Vxqw4Y|v )@7Cp#Cܵ뼑瘏99d^EL ¤y7/T+*bw3-z=A(,!c'W}Q!IĠ 5BpZ^zJuEc U)!;;P/o/ys1bl PR$Tc ċ i!UBLb|/Wtk;Ier pDg\?n1bWwYlۦpm0N,Rp jgNZ#ٳd,V\gPCi6+'Ц1`%\T9T̓#o~q0Yst5@d(u B[%$3czQ X[ cSEͯ2dd&YG~] 'D^2vݻ-smC>gvLJԵ>IalG0kY*5\R@!BfnSD̂P)P--\?F_'`eDCbA͒cМ@|qNg'9]=- R!tP嬍@B샽ɅDO>Py "Ku}Y&eHiȮ@`-@B 8j]|Fx.>.$"pJnwc`b{hĔʼn09 < bseNA譊sLQ'P, QxyD̝Ms &1 TX1@uvك,i\RCs}q_>}3IήL"ɸ/уp6 LKYõhʹ7iH]^Wh#XzSqJ`L2?3oGMRM~cN53 /45ș( E Ф S\ ɨuKby1/Va^g#^ sa? FL)dsXa/Doo8WF. e|e}c?4 JNP?T `xЀ*п`{TIdc䟮m95Éw(Y-;cKP|'%M-Sr*BSS:j{4 NC,Z;.}?|{߆~ endstream endobj 165 0 obj << /Type /Page /Contents 166 0 R /Resources 164 0 R /MediaBox [0 0 612 792] /Parent 150 0 R >> endobj 164 0 obj << /Font << /F42 5 0 R /F41 4 0 R /F45 6 0 R /F69 143 0 R /F11 18 0 R /F7 22 0 R >> /ProcSet [ /PDF /Text ] >> endobj 169 0 obj << /Length 2733 /Filter /FlateDecode >> stream xڵێ۸}be fx)]l-PEhdkזIN2}Rd$/5`7]?>6Bx|J")TLrCW퇶l쇺mͿ C\?leʃ[.3xe#xV5--=Fб7c8zrU7ǶTH2!dBTYa:O֥.93ϴw&9]~^vnચ-by)t'zFv oi]0lD O]u=t5RuPήgEp :<s}pzq&x+>gn׹>J+4IW/#6 wb¥",Z5t5eZrx+\#U"Y_Yiae몒[fl" d(|B⼞)$4(0 $׾mP]›&=-=O5nF]CK$6,I<h;UޖYO-n}i"%+@+5Om]Ӡ % \9d8"9# b?FVg/ vo6;^!PyC0}W!kn3K$M]8> #gtk|Yr7~uqs`Ս<쀄 Id{߰$ 3E-k99lˁ@  Aԧ0 xV%E_ |Zi94% o>oBW !# &p_WGDҁAR-7|BۦHYz_gƔ|2[oߋlQp.($S^)DA ^rWPj%)O+ּFQɸ,d}pkIVY;_?rÓXk ;Vi1fuuƋ^ ضJ`<8cѪcFZQ_J^|wz4' i*V ~Q{7ǤW"Y1</V %Ji0:@Saoι޷kZuL}1;aTZO= wcT7+nIּB %!21LE<%y6ϖ4 BOӎ9x|pxiʼq8EaJmpmk)ݜT:. a,Gp6Wz49yV 7u MY9r祕:]pc<~.o.|_F OaZχuWj{;+'pIWpUyK:$8S[hu_wnNąÃ*Bf f` mhPGSg.} "LbI ąd8BbP}>Eԑ08~$ezdg qfQXOK|` V;tczBH@}&' clQmv}VIN;ԖIn+ԝ~XFhYaN(g92sG_N({.e_O(&ޱK/PۃrՁv= %5MUCw گ1N޻nKE9;e,<'hIlh>݂x{qR,+2!Y/d:B E' v8!-]}Q B X9P T'rѵĊr\Ȳ|*QR.\f=`;Q khhǢTJpc6@=tFhP0+MBKOЈ~Ԛ o`žOfO*,4aD |'&Db vPI/J@gIT`u>׿!\=u.g.l5a}sLMZhc S=ƃÉU96ʅ`YLD"fCF, +d eε Wڅ+ފpIZbsD9q*ԻVnF*E4m4]V<45} iZŞi7t'IɱO\^hiK&<mҺq%3%@ڷ$-:䷙ % U!j^i,>$!K?$XungCFU奤_LN}‰fE!Ӟ%^wgc E> FK`jJ>Utc+OE#@75` 5!| '8Te,2C*{ , $F%,-ɄЊǯ|S1˿tXijӁjw/|Lʯ/_Ưl@2].K-J/WHiI'X[S< endstream endobj 168 0 obj << /Type /Page /Contents 169 0 R /Resources 167 0 R /MediaBox [0 0 612 792] /Parent 170 0 R >> endobj 167 0 obj << /Font << /F45 6 0 R /F41 4 0 R /F42 5 0 R /F47 7 0 R /F11 18 0 R /F8 19 0 R /F69 143 0 R /F14 23 0 R /F10 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 173 0 obj << /Length 2232 /Filter /FlateDecode >> stream xڥX͏ "G=, -=826_R;񼙾,SEQQ=~V QxW^¯ Bzܯ~bWzcs)ǿ66\F)Q8^s \jQNJU c^ѯK,y J囒5KVƒ$+]Bj^XeCnΗw$r:8Yb+ YQAgXw-Ln*ޮU5r[uNfs(guu>j^WϰX.L/9+(Xӂc\+}rwGO <9leg2Ƈ~R2T 5ʋ" _PY ,*ՄOK au ]% 0OxRTl$ɀDƉvJWY)PLXLN5yFfqp7aK5-)^Xa*& )y=s5OLTO)wE7swsik5 !Ybc RZk}[L*sjH/WF"˶(Wyo|_3p5 9?ׅΚ)'|Rb'l][m#O<\k٨-xi/Y|U?-i6aʉ) [ݴUҌ-f,]z ŨpbV搃)A q+啨X[幋1^Xҩ|,~%~$ }]C5>M}-FT3>'r+#%e @XuKP_~Ǧ{+ku҈財+I* >g辌4 ;_˽y#[Rrk-hm_b8pjoU<7VQZM1b eAZ؅TSxO7"EƮlWf5)r` 5Ɇ0Ʋ2ء98nj`>Rx]f 03Ʈf_qׯUԩPHqw*\ބĊ!wea4V^ ݓ˵=nrh=9~@#S/j\NQ:Apv@ UП_J12lFe5rѧKo\?.o>YIL]4ʪ&pZ-JϚ{"2=~&j G0d.#WG/-Kv#dGGYj&y p21o#c/5K !n4H/.&0#r'f/q`F'i)s~D9uJ 7I4U#λ!!qw9"PstA|Å<ï|R-fç6 $8RcC˨䡰H t|⼅?;ԥnc)&F(':tÏwWDHm5pjO;s@߂7> endobj 171 0 obj << /Font << /F42 5 0 R /F45 6 0 R /F41 4 0 R /F14 23 0 R /F11 18 0 R /F10 20 0 R /F69 143 0 R /F7 22 0 R /F8 19 0 R /F1 24 0 R /F6 58 0 R >> /ProcSet [ /PDF /Text ] >> endobj 176 0 obj << /Length 1993 /Filter /FlateDecode >> stream xڵX_oܸϧ؇^I"mZ)Md-+VrDmߧ Jk9q-r8o7?|cs[rs{peRMt. o9?6jt`&?f]?hwm}]Vu񨳟ΉtwXcϷ;id~Up:=(߷ް͎ܪ zqqVdcOd͢ 2鉳?\= oD=)85(L,zSV9d.usi%1qA\+8gtIU}bL ~$'ƻʻ}΍Kv>ݞ`][y{0 ls!xf@6-z'"qظfl.*OȵO= JNVvf`0d,B/?'X]} 5ݞ.n8|.o/Q$*pR21$ %a;ue \+-\XЁ KSEYXh*s-ZV;!sR_0B(Fi| sCfD\! Mې(gsW϶,rfT@^ L EI̘ͱha8ɶäYF%EI,J>%4(R M;DIUFI`VBهYj^#F&F$%WD1"L )jF10"F+ˡbd*%JOրϬIbdθ׈ATnJ 5;bȹfI Z4-*W 5b&kecn %'Iˍf%q$, fZcl$gWXOۖ h@B=R>2Wԇb&?\&Tj[9ϡ@iIBiluXs+![¹+fCzx,*K8ղich^u3/~r[BL-pS,Xsn`kRL}߈8tn.F , QWy}}~|snl> ߶d޳ | Mh1%E\;x_[qWWF.,9cSsnS{d_6MRAnmjIcVU9qa&VVEç86y8v\񉕹"sᯗ׏::n=(7ѓԵk7{~lt)| ];حB߇ C FM G[$ )2Ձ8qdwwmӹ:4S/M?@U[vUa6JUq=o;7̵b4&Pg`pC/"~hUcH čoB!ȏ ί~X$|llZc U{rT5[ O3.ۂC <4+雽Q+hUJOnna?D{%$9EVC@=_,f]U=MPN\ᇸ3f)t^Ɉ߬*RM_?O?pgV%J13EqWTmwjfZa+Yʨ< So3gfUq_ݻdq_X/:2M$P!8:(B,5ryw? endstream endobj 175 0 obj << /Type /Page /Contents 176 0 R /Resources 174 0 R /MediaBox [0 0 612 792] /Parent 170 0 R >> endobj 174 0 obj << /Font << /F41 4 0 R /F11 18 0 R /F7 22 0 R /F69 143 0 R /F42 5 0 R /F45 6 0 R /F8 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 180 0 obj << /Length 1256 /Filter /FlateDecode >> stream xuVK&[f?49%J+9dsmfmTv3^ԆG/wfӑ))򘋂T/FOgF)MO34Zo+R2ku^I7o;i򔓪,~*J E9/aE"{TYsxZV[.x\_|Ǜ焃UTꔻD8()2&R2 }Xu߼vݞW~vJR0~<#3dV bOS@Q%ǰ&a jw*xbPp 3C|PXTPXPdܮv`D`c2{EFi4nEn o岏bJD\,ʌWPGߧ x:;~9ބd{Vѝfn> endobj 177 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./msm-manual-028.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 181 0 R /BBox [0 0 432 432] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 182 0 R>> /ExtGState << >>/ColorSpace << /sRGB 183 0 R >>>> /Length 1564 /Filter /FlateDecode >> stream xXnV7ߧ2Yzfl_{ *Z&RET JJIR}όn킐awg ‘{>n/GctV^_oww?=;ȇ\X~=i ~Okܻ y~~v8nPsu[>B'vͧSPˮ>\}!EOeO g_>AL.$'^fG zFLbH =GݗOЗn};gS.EGPd3̚=;dUSЧ]o8&D^2@s!As% }lG ?ًUkajqP='S{E oA!vATy.{|UTDú$ 0r6k0D{ϏzYLdk#!AE|>ǖ]HMV%FT}M<]+'YY!gbbci#pTOD[b"v;S8N'Հkw@$4-7]z.NEsn꟞=[LH;ա]~4Y/h]u~N©;}n~<,czXг>f(5b>ܦ:+FM} kI;ISKѮ..jo88wqGckft.@jΓU[ -m Qve߽mg뛧3dUgϯn.9d_<|=uON>]}:E󺓋k7o:}_-qʤ֩X_0tJʃl @66H6^dɦɦ8)}&b%O6l&¦W6%9?\c_MeaS(u]*w6v}'BS2[gSi)lMrdSilP"cM)H<ٔƾRalJ[օM3 J6ƆB~M`S:U¦0Ս 6RDuaSV6WΦ}M!-M¦7ؔM!^ 6Ńu67m;l uP3HFAqh!HOz&XĠ ~ Z$ ີ€Z׈w-*heQ4ch)BѠG dZw-5mRiB]ƀZŲ3%Zm@KB_,:&ZhKJ_Vh!,ТaC iIFWZ@@\ϺN BEZ_#Z(Z-;bۊB߀}]T ŦC+hZߡ*.BK،5\)Y`DwBL&M<^'p aE%0G #de~=1<}}kv/PFÍttRcgv_CQ! ;/_c endstream endobj 181 0 obj << /CreationDate (D:20121210154330) /ModDate (D:20121210154330) /Title (R Graphics Output) /Producer (R 2.15.1) /Creator (R) >> endobj 182 0 obj << /Type /Font /Subtype /Type1 /Name /F2 /BaseFont /Helvetica /Encoding 184 0 R >> endobj 183 0 obj [/ICCBased 185 0 R] endobj 184 0 obj << /Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [ 45/minus 96/quoteleft 144/dotlessi/grave/acute/circumflex/tilde/macron/breve/dotaccent/dieresis/.notdef/ring/cedilla/.notdef/hungarumlaut/ogonek/caron/space] >> endobj 185 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~ endstream endobj 178 0 obj << /Font << /F45 6 0 R /F41 4 0 R /F11 18 0 R /F8 19 0 R /F42 5 0 R /F69 143 0 R >> /XObject << /Im19 177 0 R >> /ProcSet [ /PDF /Text ] >> endobj 188 0 obj << /Length 3164 /Filter /FlateDecode >> stream xڥZIC@=H_zLIIɁ6ӲՅ yeV 2HoޢɃ֪Ht|Q4HL(yxn0 >t8\\qϧ?PEjR|?|\0&Awb1 =`3w$ q/ǩ-G׵2unk CSmY3ŵcٙ$PWo˿vx9_nt%?m+WB]/Ǖ#D46 (\Ni" }wƑ Sͤap}0 v8vy'"4 OeZU7eڹO]v8ʃ'`u;XKkit2m_ q.)\㙃ڪ} bT 1ߜS\;t纗s;8juo_rݹ7&Ƅ*1y0Lg j'Jg7 \w_ն9ʒد.qb_urhTo<9Wyҕb;Bھ'v4tkgEDze*3W۠edK%)O%qҶm7 K')ئZ.vѺW,U:)6aSU,ewj4)䷘<8;4W0A VE~f! {45 NY,48O1w/klë*Q3'4a^~3lftfj>4@iN, ԒD.ukتԺFj)Jcg'MϥH!HߖD&^ABs/mA`X+_ 3 8ktE/& ٕaTȁ I 1)>B4iGo U&"㋠T;&dz!i+]7#Ġb !Z ;[RT6'XR I*̲R>&ƱQt69L 9@o\O`L׋+C UD]}h~iɗ{m?DvMvg./f%k[iԂVؾ#|Vl&i78T3(sq+ߟݔR=^(OT@U`GPnH&UV(̪*WB3Rhy&dvnTS&LUeVlt!&8A$N^ťkWJ <d&͸mx$dbOPf[tg[ so9`t7q[lK|q҅2X|tZ]POQ; ny2m^VEN;%!)NNPZ7@+828\ygۻ'pΛ, <$ae#;g|=| iۥ 5~nO)qηҵenKJ6M}jqč$pEuL!f3sȍ}m|aףp`+:Cu|CĮUˁv,OPSbT9җ/fk˓YlHVY*{%9wZGj"-VzxW&6*Q=vaHSƀ#6%( ;/q&~8/慷ez_?ŶCqa IBK*b-@ Xq\_YuşE788K{49#InGP'j j3/Ι@5b)3otR7.Fc@s endstream endobj 187 0 obj << /Type /Page /Contents 188 0 R /Resources 186 0 R /MediaBox [0 0 612 792] /Parent 170 0 R >> endobj 186 0 obj << /Font << /F45 6 0 R /F41 4 0 R /F47 7 0 R /F42 5 0 R /F69 143 0 R /F14 23 0 R >> /ProcSet [ /PDF /Text ] >> endobj 191 0 obj << /Length 3115 /Filter /FlateDecode >> stream xڍZIsWJD/!v%N}S*P 4x!=_/|==[O/! HDCd^%ai˱m~~ iKOC?y 9N(gb.^KSlr4mV hrY&_5Ќ2SӶSkߵB?>8W$zЦ+돍-O-졗oUT+ѮN7~!n|K\\v,;OJ{ bƾ,Al5ԊU3Tb|e,HI(ck*ai0A~x1Q'<=BT( @ Q/eG3Bj>q\fJ"C~AǰFUit062n iMhIdE+߮Q6cܻPk]3oO/IȢyQyQwA8)s\e]JM7T%feY)lBB}kXu6קI4U;He1%Y! f 1K9M|dj' \CQByܷCdE:@01e=Aw36V4/%)|!Z<]~Xh"{x~o5B4{'dB *b V eXAp-'aK|yq8OߌANek{,b$aTcj7۳ous& eSfX:z |Wa,C/X.w:wLON[gc/c7c3Zk|ߚTg nd3^''8ۭUR)kAjd rF]j!f*:_wv9mfqq0[$v$@严<^Xɺk1:@Cy5>?p~,el>T—' 9zXAjJIN]60ƫUWf_[), 7D{MבGNAthwȘ3CR?O,ˢ1ynZ@ :Day1Tؕ; T @+_k '-]W@ !Q<{Bbg}BX;2nKΨXlUbطSI)ޟ 09= '`$p6kxN:1+C9wFU)CW8Vs ~@#tYQH )jF "vp_hj^|d`@KBS&o+n.^ c`~!u"Stk'5bU5v41 w[%d^}\s2H$H$5udP. *k"4-@utM[o9+D0\D}H:'YzʺA@LY.XoN38 A!rf3un4"hΑ/F?@u7N4a!~VykJȽRAIKp$"ݺřJػj CNP2}҈s_|^}u;7*ۗ0s0ɜ|Ac1ҝht{%ՁYw55WeJލWhJ¦Fcf)mu.e ;LuWCy*.(0_ Cn=zBa)G馽eԨi(+)" C6_Ǝ Ifᗩ;ο>x#J0ى%IV(lc),.%vO;El‚瓀̹VZp.wY.v^1@±dORvt/6|s.ĶJsfp6&4U,Yb">B2A+Ghw + 5"K+RN'RI]vN‹xޗ6]zEѫ܋DHAI"lXhӃʛYGPtDYQFl[t|N"u7EQT @SeM1bѥ;T8m7>c)0&~ۤI.)#$fӹ;Aʖ5y#ʏ+iIH硿-BnB]_(]*/gV;[c#Fz'=o^)!+r8:"r "KÊ[U&h-Q,x3kƚ+^q0G!мL_S6SNZkq<[]\n0g`(_[iVIoTQǚj +8oP w91Ud5˃&6> endobj 189 0 obj << /Font << /F41 4 0 R /F45 6 0 R /F42 5 0 R /F14 23 0 R /F11 18 0 R /F7 22 0 R >> /ProcSet [ /PDF /Text ] >> endobj 194 0 obj << /Length 2548 /Filter /FlateDecode >> stream x]H}< #&Eb;qH3.۩vijHiTWWUw~}wV=qaP.=.qo'ٚ\EU?ƎAvKtO_6Et-OB_CsE:c|}StJO޺KϫOK7!y*ND+dORf}!8\TF%Qy9HH8MS KNIJ*N80\N~@6Ȍƃg ޟ{?v䍡-ágh /U:3COZhIl]ڟMƓ_oyΒDuE lT>R5}u9$AVQ3.E7}94OUӑMx Ц=z'߁f<)m;5iQLeX1*B}Ձ#k,:^6`4ߋy K Ę*&+mݡ!g+:iw9\BE>3WEGUw:( ;UB}\3kz0=z26Mhx\ѻq&+(^@݊\6U_WŅ,K6яm{zPG5`'̺ [Bd|#ey\!5;Ho7at[ x.χNuC>ԗ(O|\*6O?Қ8MP*uy$#/) N|rD>^;Ge]Rpd&E{{."Etl~&CX0\Rfщ;P m;@&2tm`d5pV80)#ù"V:Agl |UYSP5Pppd˱o[iN5cH CMhMj⍷^ͼϠCEwWpfBs+5?»$亸BŇܸ,N3WYixI7 udB .ÓHeZKjGi \b(,nn rz ?B+INXԑiy$X4|6V0zl=m bMWLO_-3m47:&!&atSľW3UDߖalғ8 B,FEf  Tr?w̄^ U -Cæ,B_U]jz6%&qfNݳG_A xKx}t,9W 7tKKJO|c}PLJqlSZH)$4AKhI48n$S@ rW]2H}ֈ!$\D*eoNhIop0g~1sn tvs;܁ ni݊ZΞ0x}j#DضNgL* ؤxNH9 =V!¢Z9Wl%MZ}:SMEɁ4"dQ"vTg<ڵa`%OWq'"&3{ž[Xk3hxu>Peܒ =P@We$ R_ŋK.isϒC4Ku^簾&U;ު80s.pPlQqV_P9w"L<.]y)LUc(} .(՚xF0Nr¢4פ3z,Yqو`Zɱ'ys5IZ,2 T~ݙ yn {+XvsxP|?p+ygL/կ)EF_y7]H+8rRAA<w#i94FַVW傱2h!LV: g5V ҘV+6Wk4RS5F BZ!"*𷁿VH>jRiXhwGd.5ITP.B $:KVYoH> endobj 192 0 obj << /Font << /F41 4 0 R /F42 5 0 R /F47 7 0 R /F11 18 0 R /F10 20 0 R /F7 22 0 R /F45 6 0 R /F8 19 0 R /F69 143 0 R >> /ProcSet [ /PDF /Text ] >> endobj 199 0 obj << /Length 898 /Filter /FlateDecode >> stream xڥ=o1-( $RPpPɂ"%!JN?Y:ۻ~CHOa A7.ϧ/.݇=Dc+o|:HJو!C2߲gN׾Fm5T1j0X܋KoDPAꂵش\M/V:Сtg a k V$~饇Ll6``A/ cPnmb5'Di +XaYbYD2SCْ걱H3 uUj]h^bk̜L@MȸׯպL@ ӶXcz-8I0`wب;,ʡ3$5||Et1WXG(C=L% s7_La~C =ucJ4>78\ XChWp:ܪV1 3~5nd#^Z+m67iVc! V,P@[b}NaG]VkC9 M(/Gb-zq 2Qo,Ǽ<0#ۇ;*^\g3}F-2yq=^LppE9uK7W鍪׊-߲e|81e3&yoP^ endstream endobj 198 0 obj << /Type /Page /Contents 199 0 R /Resources 197 0 R /MediaBox [0 0 612 792] /Parent 195 0 R >> endobj 197 0 obj << /Font << /F42 5 0 R /F69 143 0 R /F41 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 202 0 obj << /Length 1434 /Filter /FlateDecode >> stream xuWK6 ϯjm.A/m$Bm+;M}IƳ 0I_b_+UvOO_򬭊Z{: Ɍw2d~(KO>VŮ˺lvϧ]Q(wBTYagNtڜiY4rQH=z:QH%fzeyVT!(EtY%/yJSB|0Ԡ mb_[~UZd]]O/V9zb\,VDg}V]޳+$U~ѓ 7AJk)Hى(yBUIGԁk^EH7 DYOznk QT1FE!^#Qr$i#0HR[c Q'.FYP|Ed>T" B7'8Zt9ves:вCC>{fizJ)ޮ@ҋ[p$HTUazz iU bd9iƀhk ԾbnE/ L 41#3J9ji`av7:}cC"?  mMfI/Դs/5?XqSdQW)([ǡb{p8&ɢ3SF5nG%އB oW8dLC|UGzܪ\9m~X^ZNcՔ$CT<0>i Ѽ9k%y^5fyà8b]\Xtu a->Q:8$uRt}`γkO PfU[nCT3BC3x/<Xtqd<λ_P=L@ЅFYW:> ?h06߆O%rUZR#&uh$&72u3  J0^Pޚx0RqDoDO6!QkUPse -z '` dWO:uZ7 d( ؿ=s)S2/r]p3 G_Z;quݵ4@Iif >AEEͦl}"vAUx5`0 BGsh$Z$K+z jkWQ?H'4dˆ[s4O /ϓeZF⡁96>I 1)vVk+Sۧx|8^CA$Brk3rM%dp t'N9AȏdȴF<8Ck{0Hހ9B?#@ޟ_Ve|8`ޜ~8J đ82-k|3!+Q\HF_+(\n[훛q3.+B=?5g endstream endobj 201 0 obj << /Type /Page /Contents 202 0 R /Resources 200 0 R /MediaBox [0 0 612 792] /Parent 195 0 R >> endobj 196 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./msm-manual-030.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 203 0 R /BBox [0 0 432 432] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 204 0 R/F3 205 0 R>> /ExtGState << >>/ColorSpace << /sRGB 206 0 R >>>> /Length 5554 /Filter /FlateDecode >> stream x\ˎeqW܍J C1`#X$aYU9$::u*#20޾7>[W5-xp]ܾp__~)ȑᆟ~?_{x ??W7OQS-Wj.֫NSFǕ`p^ LW[+%v` 5`Wخ Tje9G.!p\C:Yզ@9*ʹҹWh0襤;C:)6rEdM$UA H+J'kvRFAid.jz(,қ0_E:e$Q.vnb4ϣ_E: C,gj0H's8Ϩ9fUXsԮ;VhݘTdzh9CW*pyR7 hɱټƢ7Uܯi5X;faQ_.ˁ򊳜V|M\65U;Z2%cU۽Wc)\-ݒJ'"T, n T Gq2ұ*8mIXBbCy-ä8J"fyr:c_> ]_T5me2ʲXjd,NwT(S[Va)JՍ_Е8zb9qd`|j+N6޲td }eG%lV]l7!kG60 'oٕJBfw:z{bZ?$'?e˒K2efx{v?wX4>έnX>9κ%gqvZ&LHC= c`Ƕv eYGl(vw9WHIũ#%ˌ>[tíg/ ^zv{l%T2|:{ L ~sVv,Ofy+[=лÇ[|BޤЁ>~*6~_Vx{o???}/g-)V_$5*xK*B!՘'طԐpmRC-5PԨRCQ.B2F6(5@=@jzJ!i-5dk0rMQ)5R猸Rj+Ԩڹ-52:R#Q[Pj(NRC)F2^句kUIӖOR#cp\j$R/J aܠCNjLϱF'uѱ9,H(5DAPZ@jȖ8N fK 3 !5xH 6¥|H >MQjd<֒cRCgRC)[J8W)5Cjj[j( IҪ-5DzJ6P*FRCq>F2,}K ŵoRC#~[j( 5C:Qj4l8ڙ1KHiҖ"m9)5KUJ Y$RCp+ԘҎRcFtFk<tH x~JY8^c>̔[>|J y)5/<싒bJM*^(u{Wnee*KЉy%Z'1 >F- So:aKy<4a0a `24a:y}K#=.b,ye֪’vUk2+ Agy 'Sy7Ɇ'`qE Zi'W fwf#ڻxO OÎ`АE(r$͛JfW74[i`Pۉ'[T: j9qFެ x*9V4\PͲ.+-s<$T| PF5mኼF{ˉy3Dz_tℼy+f 7͸e x"oXQ#f gFRb㊼y],uͲ.Pj:;],#ͲEYF:q| OI-v ngl},3y>Bё<[xq߳xGI4?³h~NG#v"͏LSi}G(jl`:?OLʨ3史X]Jx]<ϒj̧rZ͔'j Hh՗ՒGj/)_XI;Xr:\i{K %W&k.W>\K@HM+J!WT+C zrEs\qyr%W&˕Iyre\|+ @+eK 䇗\-²%W:߿˕t+]qȕNrs\鼿˕r%W˕w8]4[+ T\i.W%WrKT[\˕\ޒ+-/\ݒ+rJ\˕r}\)ȝ.B %W s_<׸AByZ!G04ˀ7i -dg,dPْ-8 A)Ǜc";6#$` RvPc~n *}04kUh +ҋN {0:7u@=a  :0z Hmlp: Eltā bv=3cYվ1oJG{5sH`niQQa]%>Ҋ$7LmE9y>ݫ`plhOg%!{tޘۣE XVR3GK%QdfĆfT9|6Y1gCsy&Vx[ x`HIusw41w1GsgCviSdgA; Jl \ iy,lhΆlhvΆO֙Yм - Q|ݥ\ <alhKfC3p|S7_P eU`21owEb [Y x lggVv+pm>a*Î_^O~^F @ak, [VuIZ5k€v$hO, #<ڵcj}ڨ $b?^EE>^`z0;/] G1XX u:sVť`Z%`#a] ,GW56W7 Wi:7oc}ѐ+%W%7G/,?-#,$^wu!Y0WF?<,eY9dӋ,KY,'L?XF?XH?(H|f]/$~ר BCTfx[4C'e١ѥk¬Ga'*htK/ob̹bѧhپ Ufp%M[))}Ơ11%12%ɆSa򠱡y~@5&wRZhYLM=9BSy :szeN5aQahaG7и04T@> DzF(34bJX444@04w['ahphhhT`=PeЭ 044ףo H8 XPi)6q.5bt"},R#:Ԑa›Fc.5׺Qjd0PjdԐiZ(H f2ͬ¥FaK>P)N!SJB;F*.t[[ le~*kWݴO?W͗~QXɟ_E1j9yݿb{+O? W)d{þ6 endstream endobj 203 0 obj << /CreationDate (D:20121210154331) /ModDate (D:20121210154331) /Title (R Graphics Output) /Producer (R 2.15.1) /Creator (R) >> endobj 204 0 obj << /Type /Font /Subtype /Type1 /Name /F2 /BaseFont /Helvetica /Encoding 207 0 R >> endobj 205 0 obj << /Type /Font /Subtype /Type1 /Name /F3 /BaseFont /Helvetica-Bold /Encoding 207 0 R >> endobj 206 0 obj [/ICCBased 208 0 R] endobj 207 0 obj << /Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [ 45/minus 96/quoteleft 144/dotlessi/grave/acute/circumflex/tilde/macron/breve/dotaccent/dieresis/.notdef/ring/cedilla/.notdef/hungarumlaut/ogonek/caron/space] >> endobj 208 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~ endstream endobj 200 0 obj << /Font << /F41 4 0 R /F47 7 0 R /F42 5 0 R >> /XObject << /Im20 196 0 R >> /ProcSet [ /PDF /Text ] >> endobj 211 0 obj << /Length 3305 /Filter /FlateDecode >> stream xZ͎SQl3")Rdր8A;4jʹlԖ;^bjI͞@.ERŪbc_߾XfЛ lʙjs|#Ҥ*kcu:MnVð?'c57npfYMJ$ߟn}~އ4vǺkw}]ϩnJ۷PcLR;jcl-*/Zq`x+N{#+pax±J> Oj`;X|垊W=}UcUQ[?ֻSLUz,ڪ@*̉.ez7 V>@LOD_N 'zA8ԎwRd)vNxUR>`4 e^!6n,HxxCw@rF']XU7fSSmX&Wܼ*?6PJ)o #X=p*.ւktP[EWԫ+KBŏ|.+ ө:ϓ~d22C93:83@!eh؝kI K-)A4Ƣ*bC9؇>jBЁCz??@Ƭ5!2@do}֒q+\Xx֢SLbv135\pgoj禘In :4+I-T)gszl^O\)} q̤:.) ,,SBsY4c=kyV=t.GO16LfnN{̐1(IRl_C3ׇcQLGp:exҔqReWUp[ɣ.@}T2$QgIцXtHt}3Yl>97mOto`"4f5Mc%LOMW:,!iiHciz2̠_$Y(gleKMuz=<&JSLZeT8"Wbzs",͌\:4&+ H_: +`U~_ޠKO7|#yRa6R`1۔7?|H7;hMX) P',`*̝ɉl8&RF䧤0v9m2)ʱ53<{~-Ha^t ^!4pp<>Px,#xj.hsMq¦E^LW&}U4]s| ~ 9}<$HedSBj?nCMFwhm"<]2~fM+%$chX&C1vѲ8:lO%H.'zQg*ΧuyȀG6'w?S3 *gڸs*O-e;,*|wZ1tvk̾~vyƛKzMx(+sUw&i)!{dnARʧbV܎ ?xtJܟK[tyNn&'E`ŖLX7[/݅.Q؟b jKwᇻfFسZ£^3w qsfK]kZ1d!pAl.C#v$^#_wz~{T{ux+O GjtܛC7FDey$lϱpGW?noJ@nQ }j6=#tz}#=^=`J_I9/-b<56};6eIؑ$x<S.]\hf.\Cir_\^1`R!]2s4V`" &}PJ:$T$qO SK@h;^*i\f}'.DypJ|Tڝ Q&JPz*ju%Xjb -p> endobj 209 0 obj << /Font << /F45 6 0 R /F41 4 0 R /F11 18 0 R /F7 22 0 R /F47 7 0 R /F10 20 0 R /F9 59 0 R /F8 19 0 R /F1 24 0 R /F14 23 0 R /F13 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 214 0 obj << /Length 1693 /Filter /FlateDecode >> stream xڥWK6WP6 3|tHHmVBdɕlI^9y7͋oS(XaYlv 9<[1b]-?JWkvV,v[^~urlsٖ u`9]%+]o pq_$0Jkv+;FC>s䋵>cW#sp ϒa,G H;$P50ԘzK }g??gY$r^dZ")6AXVN0V( L#vr% }rjRj25ڲ7ZYq4l]lEs ]ٵj2#ӂe"%0wkw+I=5c@x}w:DSSq(p[V{E".:=`0 g,Ɍ 8/b/]꧷LqvaeQ2%bm0\/FR0@ýcnen/iCZ]yo}݄fdt`Oސ\FS.rpSǽus\ z;@^V~py4i@ Gh/#|ܟx6sg,~K?$";cvK\_m9] EL f8ߵ7X' f *&͍aC1\`uՂ3Dgdf.L FUT)1rn,[d/e;obmK 5y+|eʤ} bF8lp8 6ՓC|fe@/#4wJ}:S&r1u,Lb"Av3`(^SgB!CAN*NSǃ9h##K3 > endobj 212 0 obj << /Font << /F41 4 0 R /F47 7 0 R /F42 5 0 R /F11 18 0 R /F10 20 0 R /F69 143 0 R >> /ProcSet [ /PDF /Text ] >> endobj 217 0 obj << /Length 2382 /Filter /FlateDecode >> stream xڭY;W(p@0^ξ+|.M%aF,SLR'OYop@F??t7?x0iܚm|~vR]OW'XWg\H}}T@uUaqbo,̩-ݼZ>(8^:硟C_T~;P:~ZL|1q md-vd| oD nX }TxL4Q_ 6"]3#73j(. o\͔C$ Y PeүY[edl, ! 1yOLQ7P`+6|s=(L9EӦZl~}ӏቺ̛We@-؏"##, ȵhR%MCN%K2KэǦiʼnt1LkyE 2Rc TɄK ʊyBt zޓ,SP|gzg螻 `Ȗj Jah1c1nG u>NmZ§S Tx4rj2+4L. F aCY=S;PsW sS9Q؄YXHK $U6/kQ Hs(ŢE#ԡMбE8Uۧ8Qdo͓`eC@1&\ֱAٟM9],RbB|iVc6aS 爯3608q5'+Mɗ fwj+=An%$!$*ejḖqXǓU33-a0P_vN9,0cAK8$a ܻs*4_Z!UW >3wU)@i5~(XQAhE&ܵ˰zWc/+:21䳱8I8L||j͢! Kh1Jw@bXWlr W$ C0Q&Ā\cgZut#.i:] kc}^ Ha{CX$FR{}.}ew0w=s~w7nQzJwЄ`#+KƎh'R}}ubc<<2-\}p_9=[ZCHU>?fcEژ CzZ(n hӐ4 ׾рZ`a@@%EFs%Mx endstream endobj 216 0 obj << /Type /Page /Contents 217 0 R /Resources 215 0 R /MediaBox [0 0 612 792] /Parent 195 0 R >> endobj 215 0 obj << /Font << /F42 5 0 R /F41 4 0 R /F7 22 0 R /F10 20 0 R /F9 59 0 R /F13 21 0 R /F6 58 0 R /F11 18 0 R /F14 23 0 R >> /ProcSet [ /PDF /Text ] >> endobj 220 0 obj << /Length 3291 /Filter /FlateDecode >> stream xڽZ_ϧX2VDR$rH$h٦jdɑ\;=$ȋISCr8Cf/>msN([mc_EZ$Ieߗj-un[]W$r[eSf窎OeX/v>I.9ݑRqǹZd1I,~%7ϣmUD}[ݩ*>T1mT?a`TvT 7ݮU&i]Q+u}} %Š$ZNJAkZAŮ\ѹwTt _uaFm: ?6{*ME]@zn_I\5ٸexMx@1868_TmpX^pWn*8u(J,^0FQ?|qXn;H7_y'gVt@s3`1$-Pn@(rŮ ehgV=έ;[w\9+MR:$tOb+KW>XIIQ,(ovM~B*IT0YʝʒQ#iu#mOG}߫]X8lNi[#!̳9?3-~ ?ʤTbSV^D1M| U ܼTbP.Jԙc+,WUj/"C^xⱩs6dԝON -ةbW>{fc#Kc g~6_h ;~`HMэ 1~1-ڷ]llՔ;G6 dwrrϐŪtCԼՀ60H|pe;![, iq{(aBɥWP> gG~HbeF1F#8Mt릮o "λA!!u(T^_}-P!k4TW ~+q od~/AcMf7)U %e+;oWg`L &t&֞܍Zwb9]cQ9(ړc&27lO>{XḎ\ox]N[t%3- B5vƾ\v]`sUJ/Zs"{f]!itF3DTp,_j:6[i8iԄEhp@fq0˸*\EI/ܘ7w;V|Tzdەoh[nhmN} q@8PشJ!X39>˷~dy[L8Y\\!Yy{/8%w{>o@PִL(l_0iqd;jJ7ӿكV<:Ӄ@NNn# ?mbG К}P:F{3jv#n8oեvreۓ0F_b:7vi(ȣf=PHƈ!ܔFCDnR4-PEъ,zl_JgShrv z iBC憟,zexZpue{RnBg^>->o!-̞nx|"*$|Ud"^A8m J/e,O)EwQ|7aPGOë SX7]e!kcW. M>í ؔ[\74]BcQG t-cia a[Cϴ/!Z*ۗ9IUX7z6>4 lh/pZ~^9kb.mVuf Ʋx-Exy| &Dy(W7\Ra܂6/ʊT_a.RB&۷'@>hәXb؈y| endstream endobj 219 0 obj << /Type /Page /Contents 220 0 R /Resources 218 0 R /MediaBox [0 0 612 792] /Parent 221 0 R >> endobj 218 0 obj << /Font << /F45 6 0 R /F57 12 0 R /F41 4 0 R /F47 7 0 R /F11 18 0 R /F8 19 0 R /F1 24 0 R /F14 23 0 R /F7 22 0 R /F42 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 224 0 obj << /Length 984 /Filter /FlateDecode >> stream xڵVK60r[K#hn)큶5[=INK{I m^yޢpǡf~s{/DgZ1'L 5\f|5-~ ʿ>faC3 3dKl g0NSL6Dԋ$oE@-/Mدb6 NPDGɓE|\^|.mʶrLvi.̗,`x?㻠_DJlAv|vwj">nnMgOmlh6mgwzuO^=BUEY32hvGf)EAK?{."> endobj 222 0 obj << /Font << /F69 143 0 R /F42 5 0 R /F41 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 227 0 obj << /Length 1533 /Filter /FlateDecode >> stream xڵWK6W9ɨHIAS RhF׻=w31 w>bfXORab҉I(,AU.Υсmq4StTDQ0_7΅ӹ:x纃siu[GǺ(5-gNε3\ddD/(K:8nHt BegJ#8̐Wdž}rBN+u{$oQ0+mSEC>D[GghzB^ILC-RQBOPQavfߪ%g@ErePF]cTBzqRTӸ$f y8)|ɩx t8:r92#m18ޖ=򣥣mbގ%@*ŽR$[]R4طPh9z&L2@/{_/&a^\i|{ WݍI)@CP1zuCwuw@TLoИcg#Tr~ْ-= i%|} 7{L>OE,rkD+P 0z3uN];- Glo h6_O]0eٻ;g!\8eA`g[npQL}ّK%}]+xj.@t2 SB9z>IJ)Dz6x:1ڄ& M%;Ppʼmw=]^+ӠI}HzݐP +tni5‘ }?6,FQf4o˿ i_?@1gHP _Mq38TW`o+[u#: 6'Axll:ެ`;mwտ!L;۲|=:i/A?8Qѓ04Q><(g D#(4W)v{ەŶ GX˨ݿ˷ IJ Dl1L$rsI𹯢'b0 ?K)}҄D' #HɆg6P fĆF/`R1=Be@.?''01TJdCk=#!L ,U`z ?ȤƳfzz=Y JURir(CEH }[P1P7Q0"I F1BFglh#RE"yLjy Co"ZUV@sžyI7aix+}Rjx/۷J endstream endobj 226 0 obj << /Type /Page /Contents 227 0 R /Resources 225 0 R /MediaBox [0 0 612 792] /Parent 221 0 R >> endobj 225 0 obj << /Font << /F41 4 0 R /F45 6 0 R /F42 5 0 R /F69 143 0 R >> /ProcSet [ /PDF /Text ] >> endobj 230 0 obj << /Length 1183 /Filter /FlateDecode >> stream xڥWKo6Wh÷[E Էn,Be)l)GEo^/ϒ/,f`eBpC1TLSQD&Wo~]d2'EN R 7y'T+(DnؚƸ xb3Z.W&4MDcp*vdk"2\atsal|t[۸upX\A,V'!9M*ٜ|m(Q:MۅI=)3ZV*1} @jᘼ¢ަy>(B&!f(֌t[ofp- tb!RBp%H}ݏxrBXrUec Xd6GpPPl~_ˮB)Um%u;TӊeѠ-]09ծl j)ƣ |8TOtX y>UQ#bEnFʹ"A>j b60^ᨖbiԲ +EP4.J;W5>muwJ-1W-YeRGcǨSpi04rkqhfb YN_@;%$0S9$qW5n=_Xh2>U ~pL\z22c!̿1J_K'OosgC_?ԎQMt/-iߣ$*@;kEFC`g PqcmTͭu+uSx&s;  A, keokfx2a3:j4gG( Н٠@ *9h*c?r+\Hv\&Z T_:~mj{c?YRwFJABݧvΪO4҇%_~Ftb`IOZdk;)BIEsRf9|J}ɍX5ssi_b]8:*&^ݸ4u*|gR)Or#O,%;bOmC"H{CM=lvF endstream endobj 229 0 obj << /Type /Page /Contents 230 0 R /Resources 228 0 R /MediaBox [0 0 612 792] /Parent 221 0 R >> endobj 228 0 obj << /Font << /F42 5 0 R /F41 4 0 R /F45 6 0 R /F69 143 0 R >> /ProcSet [ /PDF /Text ] >> endobj 233 0 obj << /Length 2314 /Filter /FlateDecode >> stream xX͏‡5OI<$IѢE)AP[2$y7[3!eɖCK 73?|]jWTJY&cRc1fI9Oܱv?qXeєsu? |-`??ﴜ˥XmL ,Xo0Idڌ;fq"mT@٤bXfB(ϕh0z Ù6B_p97l SafX;,{Ip+nrU0LokU џ+q/WJʹmUJӀh5sIVj5q7i؋I{`&5?q.+הan=ICOS~+I{t }]O{׭5ORG4msxQ]s^N VuO 4hw+qp*5CςJfysflF̿mB^mt(F[H,@h?>R6ٝreaZ븣`[m j?o+oFv$uև|=7$|C - wL"LY3\o1"-o{:m˜" ,reR%,, hZaCN/9R| RY&;gPyXIR)TdBQ#yHFw?  r3C`<M_Nq0 ~ /W\΄<3P`Uq33 17?|!rUnpitO+sC5 uNiXUL8YHLe$, ТcA[Օe@N!ߖÙ*zN98l{pWۘuβ<,_Kt %^_=~3x08%i*ח]Ӿ!cWu};3}XX?0ػ;7uInxqq@/Y M^a2YCMq뺞2 ۊJZ]-J>򠺃s=̀ fEX:$ өݲmIbꦧE4-Y#,4S4s(xSͅ NdL/ͅO ~qfQ@% qF22}D.ʝ'R(q0*" |ykmp,GQ :5 ɂ&b⃙`T|)mJP4atֿXwOkZKB z8,^%)p<3Δ \<'W>~ ZZ endstream endobj 232 0 obj << /Type /Page /Contents 233 0 R /Resources 231 0 R /MediaBox [0 0 612 792] /Parent 221 0 R >> endobj 231 0 obj << /Font << /F69 143 0 R /F42 5 0 R /F41 4 0 R /F45 6 0 R /F47 7 0 R /F11 18 0 R /F10 20 0 R /F8 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 236 0 obj << /Length 1013 /Filter /FlateDecode >> stream xڥWKo6WC\H :@zeoNZvxXF~I3֒a,ҷxn49]S?;X ÉN1ܟOM{ tOO}pv< Gh)}kNݰY@au<׏7Q 4$p] 9Xj\$I NZB NTl,D\ Ha,gj4 q$KH Ls\aN`䣘N+Q jkl1i@piG1VJP8S@^;=0U0D/59UT3>nfzU-5\n ? A5sjAC%JP2Ah}Ϋ&ny$h.'Hp^_3ۘ!aeh !{l'L~ FRxl:Jei҄ &ɡA$5&}f Z-E0^!5hnsd )s4LH'Y,5JS$EZCt4Xo!u:95g&EXTaZ۹ڸ,<&T[XLabێ4#+Ÿ3 -v;%Qr7H"N6qPf0)z wF)&Lf}`jzmFZ3jr>Kf|pu /Y/UsI,yU(%" DgwN &|$P\e*w1(lTDKH:2kb1DNi$Q¾uV0gQdOcFE/䦠 he%xnz=}Тq闟I*\>ΥZuuw1G endstream endobj 235 0 obj << /Type /Page /Contents 236 0 R /Resources 234 0 R /MediaBox [0 0 612 792] /Parent 221 0 R >> endobj 234 0 obj << /Font << /F69 143 0 R /F42 5 0 R /F41 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 239 0 obj << /Length 2616 /Filter /FlateDecode >> stream xZݏܸ _d\}X6R4rh.@=v]==DkFa`YH,δW7W\6J+ ˫wl5cі\OM $6SN"N_-q< h8ƨWR$ȉI' DP5ijccBpb0N\:H@mĬ#7#!s`Pqf5~Pu`;|;._x?HV,Mro_oRS$Q7oEl3aixJ8p3rhnCnBh[la?vytK]qm{R/P$k\?Z[8VD-ۦ>M_krc3g?d5&s@jU=>)X:Ia$:+{/~׮IޑMa_c(XUV@X[AȏoZ>uQ+sg2O-B7bwEIˋ8 -%U0LUOƉOC~"*˾jw{T&Ǵ6Ir@|3:+dagM(>Eɾ)tӀP1}{2#m,~a[lG+|sVu(;G8LR^TCG KN &wSUbЁ$ZuT*nNMOl(EϾ)X iExiyu8aE^64 y5\ n*mX@/Y=8hYh4Ci"Քaj-i 6<<:;- 2Xt9(ś9E endstream endobj 238 0 obj << /Type /Page /Contents 239 0 R /Resources 237 0 R /MediaBox [0 0 612 792] /Parent 240 0 R >> endobj 237 0 obj << /Font << /F42 5 0 R /F45 6 0 R /F41 4 0 R /F47 7 0 R /F11 18 0 R /F8 19 0 R /F10 20 0 R /F7 22 0 R /F9 59 0 R /F13 21 0 R /F14 23 0 R /F69 143 0 R >> /ProcSet [ /PDF /Text ] >> endobj 243 0 obj << /Length 2456 /Filter /FlateDecode >> stream xڭYKϯ z$h `&A AWg/S*J͞bQY/*zQ~eQ- W mnҕzVZʥRI/`3m!kD&znmyw6nA5t%C{|X]vGhO+喧4w8vx$`X853U% r~(:5 㚧fy`,fzw[~AN*M:|Ru{:tC{`Z8&k%h-Gk-V WnȲ3z?{{x/hιkE^1Vx>nNߋG GPLog%`&kOvT)({0QS'ao3o{ hftZEqBXA^͟?jVk'Y0[<0NyAy2< ;w?RHM{Cץ_k9OwZ gvЌkQf嬇oy.֎%.6Ng4V#kxuO_6~k9KX =z,)u3e;:S@9|B쐯*ZNS$i: Jx[Up MBgC?5%jĔ;1oicL1d"|%f&5D &8W>8Xrph(&a_1Y:J4fjcfq(80lP\ļ?h j& \x pRĎfC{Y2^xڅZ%Gҧsel5A`F4M(l)JGe3˞^&D> /+_003%Jf~MeǜCԖ pI7B %BPPiԪWjyբ}"nG xxE_,XvX"Hi.Y@wiBg Mf6*/`N @Rߘ H=O+P"ڎ@1*qssc5*¼|QsvͿ{ձ/ 7" ¿ȒC1T)M|#Fa/r)v43VS5vc pg#+em޵X҇-k$X~JϹ (.&ϝ , N p<°Eh\Kck# L>/(Om d35D34)OԀ꫹hkmlAZkM${a(N2 DjD=/b<|vˀl>2zoS!m;ϑ$m"ηtoq(>8DLz[3}u .Elp0ntm5}^Zp]QQ"n7zl0&t_`OBԅzrPK1}8hMX eumo#o&I$W Y0t5Gw#-h-c4e?C mC^5 8&DRPrJk\XUIsݕL2\U$õ? Ja D6w endstream endobj 242 0 obj << /Type /Page /Contents 243 0 R /Resources 241 0 R /MediaBox [0 0 612 792] /Parent 240 0 R >> endobj 241 0 obj << /Font << /F42 5 0 R /F45 6 0 R /F57 12 0 R /F41 4 0 R /F47 7 0 R /F11 18 0 R /F8 19 0 R /F1 24 0 R /F14 23 0 R /F7 22 0 R /F69 143 0 R /F10 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 246 0 obj << /Length 3263 /Filter /FlateDecode >> stream x\Ys~@ހpJyP,%vI*'f@b%(1sfww@B**Zzz^~E'yHa2nvsod_0!fX-2 ֓uKA'*[ e3-b"jr2}y=v\Pi߭f|,"gTN&?lN.ELDj~Rxb~o߿ c~8c@O_Rq5[8S[rwD<$#T+q]n~TS¾@ NDvb]+I[o.r.`\&" -&sY[i $x93#k ޭN&U&If=DFG{` xRδil6`fϔe\63jiwaeTF!?E3ߴonQB0!BQTek)"Rg8 ]qW1j{-7솜w dmx`^? V f @j(e Ca^SK 5^TJu{r Ap@zMʘGnK5Д'a)@W\R"Ke_&p֢E(!5Yւ2j!4\#D°D:qf(@HV@6FI"#Le4(ˑdȝwJi5jL{jvt`D %[$ͽ&DXƆ5ȀTOr|q.! JUfL&3^|9fz͖<c9=㈤Ňtyk42\(gE69}foʻY1>TMY/W7k{]֏nD:5 b<*@C۰gyBk<\/^L_x;ޒ(?>h] 0m#=O]$oH>)~Qj뿱{TOY`BV̘`\`⒞$0Do"Ӊz CD^WڣǻC,߸p1CG4: {?x[l7A?&I.1jPEs"B 4w$·ք,E (ɄX\3 _?(,kpK$0"*VTRK0z9@x SVG,$uLڰkv06B_ԟ=J赩HFH&XIE/$Y CC>FEh踱35ӇmPi$!۰cc#L%*gvf8*I+N^#uJq {0ҭd>}J<([F."E 8kj U Czk8JªtM=ȕ9k'!NyGp\.GW^j`\? ?S2j@N (=S{a ~[z^kU, _zڪl)]uX oJW1 +5 * Cn:CVQY8ZTC/V$c @;z Фv/Tz=UzzR ՓAN s3~ =0cL9{eq鷐P2j \>{8|6X>tӱ|ϵ߾rMFcsƄ2Sb9FWZ^L endstream endobj 245 0 obj << /Type /Page /Contents 246 0 R /Resources 244 0 R /MediaBox [0 0 612 792] /Parent 240 0 R >> endobj 244 0 obj << /Font << /F41 4 0 R /F10 20 0 R /F42 5 0 R /F6 58 0 R /F9 59 0 R /F7 22 0 R /F13 21 0 R /F12 60 0 R /F1 24 0 R /F47 7 0 R >> /ProcSet [ /PDF /Text ] >> endobj 249 0 obj << /Length 2883 /Filter /FlateDecode >> stream xڽZsܺ أ]fIf(>%2 ]Drx( jMv,=VL&޵HFMLh~r!tgL Y`rzf%00tQxݝMA+q:%7aee.G:/߷}c&^_8ѻ:<&- [n"8R_`_c/S5jaR&j;hW}"|EctypGѤL߇0˾/}wH B{;%bHxvO"7UmiU6rBsW99> =C%P& Yoi`$,B€@[J]c:YKWL'Dv3}V2zwXG#ZdpT!wTs݌sU%p%UH)pj{j3QTd\?߿7@.a>pUuCֈb3kZ6xܷ ʿ WS\S^PE&^<.^|>4Qc,6{:Nô_n@ bp-S}9s0ϣx}GCcDvO 4Z.TJ sQv 2$9h%Bftdn;)$.S^nX]7i]u/º/ѽY݋ QDh KUŊδ6_硇voYET?R(ACsgC  D#eJp.,Ilf|קWsEP`eu(}=VV{m_eq˧J, Q@8\ c g-]~IC\βt+ߍK_8ܻGLJw<\&9ʵ+aP+`yt2#xIΌS`B莭-=gN0!YZ,>;ڪ٭i,m,$DutǨه j% nljU;'Z&ڦ,(;5u5r fD$x]0jQj(xyMB[tůC*^6Sj&/X^lb&X/@U>eF8L7ΐy nh-x&>^PhV9Mc \`>Ecl4szkJ?c {bMw`Zpo S#L@+[U)KXfPQJ] XB[uM %`iMHayT|VVfmjV]Cljڂ9-1XtETLju-{cE740j@^ tj*a^RC'Mf`;Cgy0z/hN9O;9cxzq AbZ|V-7"m몳4uitnv詟\md-²5/+my'0Z4pOHg sptL5@Wݨ4PD 0Q-S ӏH$ #ʞ^љo 4U^nIiТr&4{Bj)mpwr9dU"q%)&JmON׎.sx _Iq[2b8i]Ik_Y,LLEhP7. V)Pc@3Y r* oWZه-|h(G3Nb4.L*"Ztvuں?O(Yh> endobj 247 0 obj << /Font << /F41 4 0 R /F11 18 0 R /F7 22 0 R /F10 20 0 R /F14 23 0 R /F8 19 0 R /F42 5 0 R /F69 143 0 R /F45 6 0 R /F47 7 0 R >> /ProcSet [ /PDF /Text ] >> endobj 252 0 obj << /Length 1616 /Filter /FlateDecode >> stream xڝ]oF콿(Pl>4ڮ:ú:Z-ɕyo),V/GM:ϯ=}eIFf"BMLzJt1M&y/~ʗ}nߋ}PҋeH"1 !0/S ~Ӄ%}"%@kaV%Mw]yY2h"H?L6ȓ>{D7pBҋDTĵ;oQD}>1&P>6rUۊ,ho=πx&]TI2pT>ً@鳚P dEdi<|8غfn>et'R OzACI!p 0xUR[L>p0ue 6a՚"p/k; <.!Y} iU|@TET,<,ڐ֬Q`Čdƨ#eEnta댍0t ^A LT%3zBD= 8-"/quS%۹g9tݰٵ J8g"4'5(k>g,~:m^]?_zWӻSj@6{@+8H&L1XtLSasq| KF!`ڶ[n_np#9,qGӥoa#=XC:^ŭ߷{rdoC>%K^Aw}-O< -PH 6YE3rEdGc]_cRݴ˓9ͶLCCvb/`qL/$a ? -081nsrdp|_at|w=z=Hy( I>g!w|-[7YM*) g$Qq &wKjHIz-U#!B#:oqzN`j'R{t-Ո-k)ГAnAHy)s:|oYKBhig3d E6KDsvΝgk,M-'Xrk{|p$#O3W;*W*+1$#JJounR)ͨ8OB 4b< z?: endstream endobj 251 0 obj << /Type /Page /Contents 252 0 R /Resources 250 0 R /MediaBox [0 0 612 792] /Parent 240 0 R >> endobj 250 0 obj << /Font << /F69 143 0 R /F41 4 0 R /F11 18 0 R /F7 22 0 R /F42 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 255 0 obj << /Length 1832 /Filter /FlateDecode >> stream xڵXKKu(ʀ !9[ji"wv|oO1 lT],YEn;eȬYч>RF>1}5e]uUuNbDwa٤Y2_J#P'tE ȝ%H u,}8 {e#[&+H}$ټMTIaKqNȷ3{/ xϬWߔ}5==T1]_f/6X..7,Ihϴ@,u{ϾڶrR;;/8ֹp)G*&k5_>T'Ŵ"M+8H2Z+즞on=]ޥHɦ )Jtz+5Ezt)1s2QZ]"rpʼ LUy_ؗJ.E%_6tN X=OÆu&L2PG:" ^SO\MIĩm>JRN8`>ޢ2:l+]TJUPJA&))@Lww'f;+8Sk00x"ME^fs'fT3XP o|IQa0>|iGBH,9Lo$Uyxo!L **( fT-g_t}@vF{?Po՟!D2j"Ɓ^x8!;.ZDWܳ9\A`J6ɍr;GTQ$"2XSUś/\%t'Z%^nH٩:aлT|ƹHCm T, pj/;/A7pzXfOzqz{ f*5pB X~#{')\t홠Kl \5쒌"lkB=TG-taj+4arywBϢpizog, ŵ91pqDkXfQ!=[aH|@0vyEF;/d\S8?Ja+s*]`Xو-.R@~ p|AyjI@Ph@;BkM_C i$?w3V{K3 l!LN 4|@;Z-! @MYt, 9 (]]<4,m3)~TݺXӵ<jwS'5K5`a34-74ZN0| P)s*<>/Bn V.Ə0%3PIΓdL+`"M1f(ǩJ{H;VhLV W[d F.# `Ÿyk|0n~@-q[!8OɇV|cc+ Q@jj9-3u:s5b/ ѻzߓ Ls[2YcBSÛ]K endstream endobj 254 0 obj << /Type /Page /Contents 255 0 R /Resources 253 0 R /MediaBox [0 0 612 792] /Parent 240 0 R >> endobj 253 0 obj << /Font << /F42 5 0 R /F69 143 0 R /F41 4 0 R /F47 7 0 R /F7 22 0 R /F11 18 0 R /F10 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 258 0 obj << /Length 897 /Filter /FlateDecode >> stream xڝWKS0+2=4ԩ;Sh3Sۃ)\ӱ$2Jow?% (`r?@"L8燃|CxȊ9O=#|oT7 "ˮ/&7E)),CTc1/˘X)-q)9zU~oeRrS4<31BǓF Z4y\R ԯf?y n:B.|r_>Ru6t˂ƊeE9xtJEŌmMw7+X0jfn<6 3q'2bܥې&%Krѻrgei[Zb8vaߺJk.iID9KO};9H.)M:I"t44u$^1}8byXG0&ϗ0fIVgOE6H2^LJWHhL(fM&C]~O5 ׬|(lo}iرnL=dIXR3b6,c,)&Tv/h `b|n;-Kܗ]~~W,톲ɴ֭OV2i˾||"QpQ"kBB 2CT+#E )r+ l~kZLdZ]jTzm~gs?oF\?:nHAC੢> _D@?v endstream endobj 257 0 obj << /Type /Page /Contents 258 0 R /Resources 256 0 R /MediaBox [0 0 612 792] /Parent 259 0 R >> endobj 256 0 obj << /Font << /F69 143 0 R /F42 5 0 R /F41 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 263 0 obj << /Length 1434 /Filter /FlateDecode >> stream xڝWK6+ $;’Td9ȣeكva5%tY 0V_aͳb%Eڭx"/WyV0djuUכ<#AˆFnhu 1*Upd,%'8-X)\MLPW@fIѪ]oR$˃ "rʟ8z-.M9I b)Pbbp8x%tQ~VWi7* %KC5+&QmD+mx|H"8AQ$ɬHLo$ceW!X >t>v.& y4 6syd=V @`¯Mm쭭eSA{a%dޯ9_}% "዇d(V_5x@^c +AYCl D!!ֺ;_4ba"xqjG99䮶O!St1g$UIm [~-ٟ 03_gY-{/h0tl4p7m;>աDi[Ə?l-wq?8e)[&Bl1Yr Zzyxۡϊ_i 8»a5z9A_gKF$cn/]Gk$; k~R'4w+DG{9 EwE?< .KC_IH 6 $tgg> endobj 261 0 obj << /Font << /F42 5 0 R /F69 143 0 R /F41 4 0 R /F7 22 0 R >> /ProcSet [ /PDF /Text ] >> endobj 266 0 obj << /Length 1384 /Filter /FlateDecode >> stream xڍWKo6W,rҢ# RiS r( #ñso JRylfp]pC)TӉ._ћ ۮ LuXt QVWǽɁWq|6\]#k $jJ + (8aR~)vjL; S*b/5Ca,\>0dJ#@&6&?1%䏯`3z8]Xo~֋McEBL+4&t`~y8^c9{@E!#RF#֐l \2qoKd9_PJ;mgl(ZǪ+ԟvwv % ![ yΙx.N|U,r{Rbs񼁐C$!zV8K.=j5>^>Q6L omlyəԄX*Ƴ!6EJ!]>d~N= DমeϸO7,(Z8ֵˆe2_ 灊hn8ݻ#P%=qX;loh3x$,2hsTpk 3 Xkt*pu86l. #ND_Oh9=8:TU9ig+ EP4˳#ˉ>Nn-?g$ D] "'q%ūG'Yc+P3CIdpcx^^ u ݊;ɣ{9D0dnVn$GZ~LpזVe@Z0"xp-hj?;%kDgNm]PjPm}PiPioic?ZHq 4EQQIilvZb,B2zLd[ù_j(bofj2 |-uu:'3U۹r= n1k}*viS , endstream endobj 265 0 obj << /Type /Page /Contents 266 0 R /Resources 264 0 R /MediaBox [0 0 612 792] /Parent 259 0 R >> endobj 260 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./msm-manual-043.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 267 0 R /BBox [0 0 432 432] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 268 0 R>> /ExtGState << >>/ColorSpace << /sRGB 269 0 R >>>> /Length 1033 /Filter /FlateDecode >> stream xWMO\7ݿ_q7`Q{٤R+EITak={I;$ ھsbOD)9=9/& I)&_tKzuXc/o Yca:º~^H(thJ O7K>L  7E69UU-8ێ}g*K;aORMޙ:'Nָ]G#KMnΛ닑K`O8tA |j]Űfyˆy}yܿbLM-p\quXVzQx ÿF?Efoa|2~y] {x{>#;h  +_+U?0W\a?pdϫ&>h]M|2'yAK} MXζs/!Iݠ8k>x-tΤXAXBSK-C G?&\m@Ֆ'M«hu#GB{׵:4M^-ڔjn. X[X2mtq|OΕp"opN6 N|vy#{}DM'G=JgwK'S]/gjbFCkjG@~DwyQkC vwhivwjNi6ht_ NS3֠?1W4XF+tj/0w8~p}\:=߮v&}?Q'@Ԗ9ג)QNt\:>CDgjO 5un'/PcX0AkoRuio+t2=p]Ww5F:qط'?^" =]~|S,:usypv=5 ϻ+:¥͌x=]ͼ~8c@gNj%ۂgŹjࢯGJy~o5$/m6&շ\JqX)tCɴ(7˿V endstream endobj 267 0 obj << /CreationDate (D:20121210154421) /ModDate (D:20121210154421) /Title (R Graphics Output) /Producer (R 2.15.1) /Creator (R) >> endobj 268 0 obj << /Type /Font /Subtype /Type1 /Name /F2 /BaseFont /Helvetica /Encoding 270 0 R >> endobj 269 0 obj [/ICCBased 271 0 R] endobj 270 0 obj << /Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [ 45/minus 96/quoteleft 144/dotlessi/grave/acute/circumflex/tilde/macron/breve/dotaccent/dieresis/.notdef/ring/cedilla/.notdef/hungarumlaut/ogonek/caron/space] >> endobj 271 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~ endstream endobj 264 0 obj << /Font << /F69 143 0 R /F45 6 0 R /F41 4 0 R /F42 5 0 R /F8 19 0 R /F11 18 0 R >> /XObject << /Im21 260 0 R >> /ProcSet [ /PDF /Text ] >> endobj 274 0 obj << /Length 860 /Filter /FlateDecode >> stream xڽWKS0+<`-wJg -`!4.~PW䇈$C߮*92]!n10Sg:_O{y}wS=8  &zFnԂop>5nO!R6Ԃ@!v"6^}L1MԎ\PJT^HP.?ғC=\.o.~(*amJwXw!,oH0J,Lƃ:"ME]o+U#k$г0j0Fx𐊪8 n*m\41DQݣӏ׻[:8%W$r9IvȘIۼH X.t&%9ibݵ2u8匵?\Ќ_8]MH$^䍁bNT&ˬYWqi8"lNiU@A8 *\ 5T Fa*casԜx|FtKm;p)<걉TlĬci;ĄhGgu `>ԷĆ@Hm"Q#H fV1FDFPޕlCQn>&>֔!]A]}E[X> endobj 272 0 obj << /Font << /F69 143 0 R /F42 5 0 R /F41 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 277 0 obj << /Length 1641 /Filter /FlateDecode >> stream xڝXKs6Wfc"x NNGNaHu YmqZ[]}v/6ORj~UUhM(w޽sql 1kyqJ ,%[̶Y9IJ8KJu__/#""JsCB4>öH ThMur%$B4w~ ?Y/,6MI&5=†Kqg&'L=3ERHl bk>XlV.?Zdy zM1P s5Xxo1h44jFcd45ѐ;O@IY~'vDg cD,3!kȝ2yP7.eZXɧ{*0!2 Oz H?:kCQħW!w<-6_-XV`z3,i uSnLs{;DxVƕ lfMAZ.\g_z˵ /HeBķwb>&ܻѩܺAaZ3"uP|ڨ!2+*^tx&hE?_RN4\p5_v+f٫GA endstream endobj 276 0 obj << /Type /Page /Contents 277 0 R /Resources 275 0 R /MediaBox [0 0 612 792] /Parent 259 0 R >> endobj 275 0 obj << /Font << /F42 5 0 R /F45 6 0 R /F41 4 0 R /F47 7 0 R /F69 143 0 R >> /ProcSet [ /PDF /Text ] >> endobj 280 0 obj << /Length 2331 /Filter /FlateDecode >> stream xڝrܸ_Ϥ40$X<((Udm9,Hv?޾y1QgS~9ڈ4g΄߫ =Eg5-,(FBʣ $ʣ n ՎvǛ~P[UZifHk{5_N/Z>oܫX 둭Cw?^\\S@ ԤqIVg)EYW X]zhǪ88sB# i6y$e KhZ#m/vp"$ˏ jlVvސ~8ɖ醶DjPq9l_65@l_O ό׵:Vv)״ZtCۻ{qoV_FDK1ؘBq6m8=ΌYmomYWʊ]AKt"/Z0F{%]K#)X?GztDv!qvC[rua8Џ$VivtƦ H[G5.=l+튺9=..bSޭ Rve`9Fiv.};Ԡ "$_Oy&!7ʓT &: ^!0E^7?lI/CezAtR U2R"p ,2, ?)=oxJ, 5&mQ R'QOpW|Cq |n hD.گjE=lPdVOX񗋽'k@諢*`+>hja|,Y>\~BrBgf7f4sTLp3vA<2S݂C+URty W Pnp7!plu 5])i nY% ]R&Y6~WG=sdIF"V];'J`C}t a2ܶ} y@"zxI"8U2 ޵w0m(cjKG0뷥on&+vMc}|3ɪ-쎡4q@LIo/mhF/ 2xC}lQvD*J0lfmE?5y7,q̀6\Dh[`@jVD~1RrV<)10=͠^X콍~F?cZl\|q1c%.m30<]dfX.~:W@RzI8e}rQ7U1welD# m:^ 5Cn{|6 eIFEF*'Yޕb:܍?fOn-spQ@QZpD9(d3Cٿm+[2tE4=[߼cvt{YpwWA {^e5{n{qvCy3tBI&9y͎ō*d:"\neC-Z*T-qJ2=ɗ)/p0)!Bo54z=l[H5X7U8P5W'cț@3[HbԸ(鸳j8Μ$bH>zn 0kN7WGؗfTHi, iٝ9uHPa PeVqBR<2(- ^H5A|syWT.m endstream endobj 279 0 obj << /Type /Page /Contents 280 0 R /Resources 278 0 R /MediaBox [0 0 612 792] /Parent 259 0 R >> endobj 278 0 obj << /Font << /F42 5 0 R /F41 4 0 R /F69 143 0 R >> /ProcSet [ /PDF /Text ] >> endobj 283 0 obj << /Length 246 /Filter /FlateDecode >> stream xUN0} D$HP q&ط'^ <֌H oH?&MGl $H>m.E١䴈[ꖂ$݂qƇ=w8PVB9CfY2"-,cM6YJ~ߞVGj!Pg9EZPh:A*@b7$܋IU)3Q/I$hijyy/?rh endstream endobj 282 0 obj << /Type /Page /Contents 283 0 R /Resources 281 0 R /MediaBox [0 0 612 792] /Parent 284 0 R >> endobj 281 0 obj << /Font << /F41 4 0 R /F42 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 287 0 obj << /Length 1190 /Filter /FlateDecode >> stream xڕVK6 ϯHo6h%ٖ9;E{(;z8Jlm~ H'$t/M|<|xEW*DjIRd٭t)HJD;$sm-R"YUؽ+m։ SVȍ6N"!eZk-1dcSy$ *q,|w= sq:|RKf9ԡNoJ;m'f4Dsqjw$ZSkMݎwk1wtncб'ԕh_jXTDp}7a&GV[9}U=度buGYtH<2zpm%* áDZnS"M9G TO@B4/-ȭPK2s1N*mOz =mM[fF˾n=V˨ 03Հ|BŒƢ97` :p}FKLH˅<>Eg# ¤tP&O}:L5C f:YH^x<`ǿ[ޟ{|jq+ aȝ++9<F*3<^VkC]",% 45/Vc`(4>Kۈ4H5{KphN\HQt#_bR7nK{;Y)5f-\ϘmYuu9ۋA|`F随5MǸ1d'\HL8&23z}nO_g\86;peq<6HTXDv 3^:^& X{ĦDGe5F(UUCJsG(ɢ|{B-f ڦtz*O!yH ^>|< IC! endstream endobj 286 0 obj << /Type /Page /Contents 287 0 R /Resources 285 0 R /MediaBox [0 0 612 792] /Parent 284 0 R >> endobj 285 0 obj << /Font << /F45 6 0 R /F57 12 0 R /F41 4 0 R /F42 5 0 R /F69 143 0 R /F90 288 0 R /F11 18 0 R /F47 7 0 R >> /ProcSet [ /PDF /Text ] >> endobj 291 0 obj << /Length 2411 /Filter /FlateDecode >> stream xڭXߏ۸~_oI沷mren,}iY I3gủW)QW6Ei~]ѶC͒#N ;ɔe\?Usbox.? E{P'X%q~$9x 9;P jeS',8q&BGM[s VmS벩J0"ZÖ0XEݮ^ƒIZ 8u['Mkr[ں1l +u T ȹDΙL副ADǪM]J zJΣr)ZjB/ִ5]9Ag8ɨw2f44^n)J1ܤ nhDќ b:]h\Eoa=d3cNLjt ]Gaaxoaێ֓@3.vw~-"]rAi?J;n.ƻY"^gd\go2fȐ*!3og`|)7#Y?zufOʐ8L^|72 \"#gH{>O2):M =ls\<ټhzrwk2DcD/DyߩS/GJ3eiSu9S~ `[&ydZg'0 Fj "uQIcTCTR|~ʵk;˻fؙk_@YڕnbD&2UG@LU= p$l!_Bi=5Ԭ=aAD\'9P0h|[+$[4,و+*G$r/IyZ7tl6MHYHJXڗWk H7ho:7! 6z;6J8`_*Y(TͺgUM3g*ͧ`8IA ƭq찄 ~^'zU5t=h$::ւ_'t2P/4\ʩ.a: I%s<L81\RDp'TPW AH)ր=obƢ,[M?IYϓzHgPSGhGo4[;^̏n@}(: WTruDw8e,EW#E||Vz{rӳϝL$X,c* ͊^A#zΰp]Ȕ@)8"?A6g_@q,UL1W=*S:2`fsP3S1kBOl,fbQWޚCWhrOE2}-Z0 ?2NuYCV)>4,@{óX endstream endobj 290 0 obj << /Type /Page /Contents 291 0 R /Resources 289 0 R /MediaBox [0 0 612 792] /Parent 284 0 R >> endobj 289 0 obj << /Font << /F45 6 0 R /F41 4 0 R /F47 7 0 R >> /ProcSet [ /PDF /Text ] >> endobj 294 0 obj << /Length 2541 /Filter /FlateDecode >> stream xڭXr:+"61pΎ8ݝ~y %)R!7 %Zrz#sp.d'y'<98aBi$qr/O d_yEY|X%Fx ]7D*qGL]}v<4v$}GdLA1B6h?a?1;J-01cKM_v0;'Äwr)Yhs)tyNg!ӽŀyU x/x*K\'i4IAAjAW9oB1,.puJrɢ $h$.¹gzPlo\(A^ANIsSna 銵iY2TY#+4a;o/yM(X{k_/Ҵ1"DS8LpMϼNUPRgY /cَ D\Y4frɴo$ƜP8k}i~-;è6 -G[N'& rP 𺄹 1M |h 9L'(07gP$ xRDzXZ'b`!IRpdR>  Hѷ})z]݃qϖ*\%7TA 0g R4V0-4+fD)~me;X2p(X`1[ՐtUJ-3$DW6WQ 2@jA3{V@a}=哠 ȱXIwv_2 Q؏ j 7  $bW;|0K5I"*GH\0/ 4s`A[N2htKjv2@,@fVVL@rt߉$ طkw#Y]_} ȝrOz;&@%u(aْ֪ Hҍ9H~vM,Mjwq{e#w,Xa 9FKjg0@CUPs-$)"4 W $0ӽ7 zRZ5ݼkTnKeOR(e<1jGo^[PWb((D> "'(78vOi,l,dRIj(Jea~s8á7v endstream endobj 293 0 obj << /Type /Page /Contents 294 0 R /Resources 292 0 R /MediaBox [0 0 612 792] /Parent 284 0 R >> endobj 292 0 obj << /Font << /F41 4 0 R /F47 7 0 R >> /ProcSet [ /PDF /Text ] >> endobj 297 0 obj << /Length 714 /Filter /FlateDecode >> stream xڭTR0>3XdK0e))J-1B'=ۻdCbWVu~IFX2_%,gu(GɼK҇c f!=Fҙ1cQ.Vu6ث = @ 8uD?mu"9qiwatL;ץZZn3ӟpXfyFijilcKOsJA8╍0>JY}$3 ٓa| ET@W&ml~S endstream endobj 296 0 obj << /Type /Page /Contents 297 0 R /Resources 295 0 R /MediaBox [0 0 612 792] /Parent 284 0 R >> endobj 295 0 obj << /Font << /F41 4 0 R /F47 7 0 R >> /ProcSet [ /PDF /Text ] >> endobj 299 0 obj [667 778 722 667 611 722 667 944 667 667 611 278 278 278 469 556 222 556 556 500 556 556 278 556 556 222 222 500 222 833 556 556 556 556 333 500] endobj 300 0 obj [600 600 600 600 600 600 600] endobj 301 0 obj [600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600] endobj 302 0 obj [575] endobj 303 0 obj [1083.3 458.3 1083.3 736.1 1083.3 736.1 1083.3 1083.3 1083.3 1083.3 1083.3 1083.3 1083.3 1361.1 736.1 736.1 1083.3 1083.3 1083.3 1083.3 1083.3 1083.3 1083.3 1083.3 1083.3 1083.3 1083.3 1083.3 1361.1 1361.1 1083.3 1083.3 1361.1 1361.1 736.1 736.1 1361.1 1361.1 1361.1 1083.3 1361.1 1361.1 875 875 1361.1 1361.1 1361.1 1083.3 441 1361.1] endobj 304 0 obj [613.5 666.7 743.8 677.1 549.8 827.6 840.3 849.8 712 666.7 831.1 726 815.2 681.6 791.7 841.7 864.6 930.6 886.4 674.7 855.3 1144.8 726 578.1 918.1 1361.1 1361.1 1361.1 1361.1 458.3 458.3 736.1 736.1 736.1 736.1 736.1 736.1 736.1 736.1 736.1 736.1 736.1 736.1 458.3 458.3 1083.3 736.1 1083.3 736.1 749 1036.1 1037 996 1109.9 1007 867.4 1064 1110.4 626.7 772.9 1138.9 955.6 1284 1075.7 1047.5 875.4 1082.2 1030 856.3 832.3 943.9 827.8 1279.2 1112.9 824.3 943.1 597.2 597.2 597.2 1361.1 1361.1 597.2 774.4 633.3 649.4 739.7 677 684 700.6 827.6 533.6 588.2 758.1 480.3 1228 880.8 702.8 739.7 658.9 671.3 670.1 563.7 846.1 722.2 1009 791.7] endobj 305 0 obj [830.6 1097.2 1027.8 911.1 888.9 980.6 958.3 1027.8 958.3 1027.8 958.3 680.6 680.6 402.8 402.8 645.8 402.8 437.5 680.6 680.6 680.6 680.6 680.6 980.6 611.1 680.6 958.3 1027.8 680.6 1177.8 1316.7 1027.8 402.8 402.8 680.6 1097.2 680.6 1097.2 1027.8 402.8 541.7 541.7 680.6 1027.8 402.8 472.2 402.8 680.6 680.6 680.6 680.6 680.6 680.6 680.6 680.6 680.6 680.6 680.6 402.8 402.8 1027.8 1027.8] endobj 306 0 obj [458.3 458.3 416.7 416.7 472.2 472.2 472.2 472.2 583.3 583.3 472.2 472.2 333.3 555.6 577.8 577.8 597.2 597.2 736.1 736.1 527.8 527.8 583.3 583.3 583.3 583.3 750 750 750 750 1044.4 1044.4 791.7 791.7 583.3 583.3 638.9 638.9 638.9 638.9 805.6 805.6 805.6 805.6 1277.8 1277.8 811.1 811.1 875 875 666.7 666.7 666.7 666.7 666.7 666.7 888.9 888.9 888.9 888.9 888.9 888.9 888.9 666.7 875 875 875 875 611.1 611.1 833.3 1111.1 472.2 555.6 1111.1 1511.1 1111.1 1511.1 1111.1 1511.1 1055.6 944.5 472.2 833.3 833.3 833.3 833.3 833.3 1444.5 1277.8 555.6 1111.1 1111.1 1111.1 1111.1 1111.1 944.5 1277.8 555.6 1000 1444.5 555.6 1000 1444.5 472.2 472.2 527.8 527.8 527.8 527.8 666.7 666.7 1000] endobj 307 0 obj [777.8 277.8 777.8 500 777.8 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 500 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 1000 777.8 777.8 1000 1000 500 500 1000 1000 1000 777.8 1000 1000 611.1 611.1 1000 1000 1000 777.8 275 1000 666.7 666.7 888.9 888.9 0 0 555.6 555.6 666.7 500 722.2 722.2 777.8 777.8 611.1 798.5 656.8 526.5 771.4 527.8 718.7 594.9 844.5 544.5 677.8 762 689.7 1200.9 820.5 796.1 695.6 816.7 847.5 605.6 544.6 625.8 612.8 987.8 713.3 668.3 724.7 666.7 666.7 666.7 666.7 666.7 611.1 611.1 444.4 444.4 444.4 444.4 500 500 388.9 388.9 277.8] endobj 308 0 obj [706.4 938.5 877 781.8 754 843.3 815.5 877 815.5 877 815.5 677.6 646.8 646.8 970.2 970.2 323.4 354.2 569.5 569.5 569.5 569.5 569.5 843.3 507.9 569.5 815.5 877 569.5 1013.9 1136.9 877 323.4 323.4 569.5 938.5 569.5 938.5 877 323.4 446.4 446.4 569.5 877 323.4 384.9 323.4 569.5 569.5 569.5 569.5 569.5 569.5 569.5 569.5 569.5 569.5 569.5 323.4 323.4 323.4 877 538.7 538.7 877 843.3 798.6 815.5 860.1 767.9 737.1 883.9 843.3 412.7 583.3 874 706.4 1027.8 843.3 877 767.9 877 829.4 631 815.5 843.3 843.3 1150.8 843.3 843.3 692.5 323.4 569.5 323.4 569.5 323.4 323.4 569.5 631 507.9 631 507.9 354.2 569.5 631 323.4 354.2 600.2 323.4 938.5 631 569.5 631 600.2 446.4 452.6 446.4 631 600.2 815.5 600.2] endobj 309 0 obj [892.9 339.3 892.9 585.3 892.9 585.3 892.9 892.9 892.9 892.9 892.9 892.9 892.9 1138.9 585.3 585.3 892.9 892.9 892.9 892.9 892.9 892.9 892.9 892.9 892.9 892.9 892.9 892.9 1138.9 1138.9 892.9 892.9 1138.9 1138.9 585.3 585.3 1138.9 1138.9 1138.9 892.9 1138.9 1138.9 708.3 708.3 1138.9 1138.9 1138.9 892.9 329.4 1138.9 769.8 769.8 1015.9 1015.9 0 0 646.8 646.8 769.8 585.3 831.4 831.4 892.9 892.9 708.3 917.6 753.4 620.2 889.5 616.1 818.4 688.5 978.7 646.5 782.2 871.7 791.7 1342.7 935.6 905.8 809.2 935.9 981 702.2 647.8 717.8 719.9 1135.1 818.9 764.4 823.1 769.8 769.8 769.8 769.8 769.8 708.3 708.3 523.8 523.8 523.8 523.8 585.3 585.3 462.3 462.3 339.3 585.3 585.3 708.3 585.3 339.3 938.5] endobj 310 0 obj [519.3 476.1 519.8 588.6 544.1 422.8 668.8 677.6 694.6 572.8 519.8 668 592.7 662 526.8 632.9 686.9 713.8 756 719.7 539.7 689.9 950 592.7 439.2 751.4 1138.9 1138.9 1138.9 1138.9 339.3 339.3 585.3 585.3 585.3 585.3 585.3 585.3 585.3 585.3 585.3 585.3 585.3 585.3 339.3 339.3 892.9 585.3 892.9 585.3 610.1 859.1 863.2 819.4 934.1 838.7 724.5 889.4 935.6 506.3 632 959.9 783.7 1089.4 904.9 868.9 727.3 899.7 860.6 701.5 674.8 778.2 674.6 1074.4 936.9 671.5 778.4 462.3 462.3 462.3 1138.9 1138.9 478.2 619.7 502.4 510.5 594.7 542 557.1 557.3 668.8 404.2 472.7 607.3 361.3 1013.7 706.2 563.9 588.9 523.6 530.4 539.2 431.6 675.4 571.4 826.4 647.8] endobj 311 0 obj [500 750 444.4 500 722.2 777.8 500 902.8 1013.9 777.8 277.8 277.8 500 833.3 500 833.3 777.8 277.8 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6 527.8 722.2 527.8] endobj 312 0 obj [639.7 565.6 517.7 444.4 405.9 437.5 496.5 469.4 353.9 576.2 583.3 602.6 494 437.5 570 517 571.4 437.2 540.3 595.8 625.7 651.4 622.5 466.3 591.4 828.1 517 362.8 654.2 1000 1000 1000 1000 277.8 277.8 500 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 777.8 500 777.8 500 530.9 750 758.5 714.7 827.9 738.2 643.1 786.3 831.3 439.6 554.5 849.3 680.6 970.1 803.5 762.8 642 790.6 759.3 613.2 584.4 682.8 583.3 944.4 828.5 580.6 682.6 388.9 388.9 388.9 1000 1000 416.7 528.6 429.2 432.8 520.5 465.6 489.6 477 576.2 344.5 411.8 520.6 298.4 878 600.2 484.7 503.1 446.4 451.2 468.8 361.1 572.5 484.7 715.9 571.5 490.3 465.1] endobj 313 0 obj [778 556 500 500 500 389 389] endobj 314 0 obj [500 500 167 333 556 278 333 333 0 333 675 0 556 389 333 278 0 0 0 0 0 0 0 0 0 0 0 0 333 214 250 333 420 500 500 833 778 333 333 333 500 675 250 333 250 278 500 500 500 500 500 500 500 500 500 500 333 333 675 675 675 500 920 611 611 667 722 611 611 722 722 333 444 667 556 833 667 722 611 722 611 500 556 722 611 833 611 556 556 389 278 389 422 500 333 500 500 444 500 444 278 500 500 278 278 444 278 722 500 500 500 500 389 389 278 500 444 667 444 444 389] endobj 315 0 obj [556 556 167 333 667 278 333 333 0 333 570 0 667 444 333 278 0 0 0 0 0 0 0 0 0 0 0 0 333 278 250 333 555 500 500 1000 833 333 333 333 500 570 250 333 250 278 500 500 500 500 500 500 500 500 500 500 333 333 570 570 570 500 930 722 667 722 722 667 611 778 778 389 500 778 667 944 722 778 611 778 722 556 667 722 722 1000 722 722 667 333 278 333 581 500 333 500 556 444 556 444 333 500 556 278 333 556 278 833 556 500 556 556 444 389 333 556 500 722 500 500 444] endobj 316 0 obj [600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 0 0 0 600 600 600 600 600 600 600 600 600 600 600 0 0 0 0 0 0 600 600] endobj 317 0 obj [556 556 167 333 611 278 333 333 0 333 564 0 611 444 333 278 0 0 0 0 0 0 0 0 0 0 0 0 333 180 250 333 408 500 500 833 778 333 333 333 500 564 250 333 250 278 500 500 500 500 500 500 500 500 500 500 278 278 564 564 564 444 921 722 667 667 722 611 556 722 722 333 389 722 611 889 722 722 556 722 667 556 611 722 722 944 722 722 611 333 278 333 469 500 333 444 500 444 500 444 333 500 500 278 278 500 278 778 500 500 500 500 333 389 278 500 500 722 500 500 444 480 200 480 541 0 0 0 333 500 444 1000 500 500 333 1000 556 333 889 0 0 0 0 0 0 444 444 350 500 1000 333 980 389 333 722 0 0 722 0 333 500 500 500 500 200 500 333 760 276 500 564 333 760 333 400 564 300 300 333 500 453 250 333 300 310 500 750 750 750 444 722 722 722 722 722 722 889 667 611 611 611 611 333 333 333 333 722 722 722 722 722 722 722 564 722 722 722 722 722 722 556 500 444 444 444 444 444 444 667 444 444 444 444 444 278 278 278 278 500 500 500 500 500 500 500 564 500 500 500 500 500] endobj 318 0 obj << /Length1 1393 /Length2 5949 /Length3 0 /Length 6889 /Filter /FlateDecode >> stream xڍt4]6FA7BtktØafkD aD= z-H!zI<>}kֺ眽`50WrB:@Ց XPS`,Laۉ8̠(4  l Dp@Ha0Xo % B|`ND@D*HOr$~JP W##aP?Rpɺb0҂"0 E@_}5"atBPPg4.Eꀱ.p s9п qtDzxB0 C;? A8Bh$.!8Cu%CcĠ0/Y ᤂ"0h_S{\wprESjLD@1 ^UWOo/3CP'pр?4 `PРtsG$$81 wvOke0'$o *iSC_Nee/& !!qQ@g[ ?Zg$  Mdp 7 HqnQ/:&?gn"_b<;$ O j6>$ZVІ S5KE c/D$<S&\)٣@38Y2t*g6.V1ܥ 5֌% `Rx~Ur7K)]oz;_5#VR;62!Iѕ d1^ r2y.>̹S6g2b;.g?K2ק_ 1OD?WuTqqD@?xj6V,a.L屼Z{2t d͒&olKARW`7k,8VqżPc Wb{&_IrGEPm4BThPg+zIy+3 #n!VW'U6_= 7zI/SxÀ=cE›_%7~]ʷr#!'Blv| I2< &NR!§!T 59_H$|b4dKL΍=p#{#=jV`ϺRmJ, v hRו +o~spoU"&_Z&g)anw!X8>90BLglJ&1ﴔv}a0 幆vq8 æi ߶tQ[7xEw˽E:T%z[\Lo}xtOvKTfFp\J=Ծ^uB ՝7).=³ ch$~yZ~]jC Z)#G+y0 4$<([kw}x1`%GU z0Ra!;n?㬒l|\8lb K+|-VygzK"f0U5.QoJN_ۖٽl~J6&ˆzxuN6_KvW2)BM@%!ZK9ZUR7D?E#ɬj]gSnw XfS _E̶CwG#I=_ƞY:^kٚ#iH#1.YG8ko=czKE3c:[Y fm-rz..uO=q5upEE F{kM!;)QDoF㪳5z' .Y?SFm*pT-ZqI$JЄ+pY:ʙ__]ŋF;|R l'LA~7+bgЦ`Kbyib Ҷ=B_(?Z)-֊"s';O7 bHޜ,Oh aV vf|"ǭ\+ueW)K^fJqyojKc}>R>q@Hr3fn-8tOe])7`vx+pZty>=+&fMGv{ ѶVPjr2iZhp`$z|4P0ymg,}v6"%Oé0be ")r,q>LWD>hetR^V,LTk?늻{2-#Irq\e$NhS#= +Oh׋:qQ,ǯ0`?l{$͈2䆎P٪m!ϚG)W9뮾 ㋜wuY #z؊51>.S<ӣQ{X9oO'^ q+/Xs3h, /so2|#Q<8jd]%myXd -ay|Rb;VÑIv q=2 $lFL<˲qbiYz̅HF)x+]o i+xj^^S)KN-f1AΤ$HV_-|FUbZcgϏO5z?xF4cT.䲮 (4A0DMWn'71KFf^I@i& 8v*vz`&BܜI':zE֋l-Tttŋ+7{}5ir_C.0_I'kEL6|\$i8WHI2u#ϾAtR)Nˑz=;68-+#nC~Fޤh[Vo_JmX0~ARQW}[TO{,}Zan}q0%/'a}T-_9sZxN@t+Gq 0C;īq\FJ)[=-Zژ:[<#IO?ZOet+AiQjДڍHKfI #If ltmOvb-HgN\/\%^VR}h7~![Z4^K0wKlq"Tk_# 4"`SlAQ8?fHZ#jvm,?vJ`䗢v8Sg?Oq3' |K4BG2*0nyIݭӧ'%* |(1T{3Cc_bzSG<_:R^7eZ")ވoYRLR _1֛|asT5Q|(_u+!+i-2#|2$!jY?8}B(v]k؄lVC*QP"2'ΨgS+=8^Gc@?;3J?C#jo<) outU .?"Z+q>'A<% N&CﹱEEsR/`4Xj(Ns*`f@'zh%u9 s$H \t/yQACcd~g6kuCCܿdZ⫬Ec`c >AW8NH?_,PZb;H#wlJ>lwtohܚ8vrɷ2cJҍ_ 4[n?؞*)A[XS4 og='\/B:-ٕjs{P/yr#b:oNʈ.h_}v8Usz|;hR -/v.%*haZ >l,`wzj< ٬;~;Mɓz:Z- L /6AVm :Ei{řRݘ<R[ymN(BЧYY"9wK3nLCD__.Ru&]t9& md? ;'y=[OQRj9<;ckM6ς;^ seXsTDzd7^8V;QR*FMJML𹲸Ytlf8jZپ^G tgsJxEk3||vuk~n Ǩ֣Ŵ7x-;lb|} mj$k:5xd)ԽF "-̦*T,3]Z6Μ|='-Z vXѾROB[Ұ9Of>lчrMe>3::ޔec33Ѩ65mA+T53#Sg;6ޟY&arYhձk)}սo4BatVZJ7VU*SoQ"5nSu7uYyGO# _wkq谊X|}KEkc*G[:f"xe*TVJo'GK8W2z~DRJuMKn$0+ǎssBW~]ZphY%"me^^-aW OHe gZ̲soۍktw.܎ާM_A(6g.fWu^&#iČ5Iu8I&K׿;v0\*#̩򻪅.ۛL}{)C.<6D&?ƾB{G'9EWOɡU*-RB̝fĴG6g#Go]tVc_^ :yR|qj-z"[Z+ƞ0@RXvwޥ@1pf ~1I뻈 c!oH6Nt*ĵ_OzvYJ#ޤ`j(ȸaHo@z]7YcГ)'3[}[i-`t<;EOg61Eh¼/^4[6Lɲ}m\@t۟'/{G "j';O 9s*C+ ְN5עʓxQkiݡ:iɖq_+ji~(kSZ@&#oٞEy֣Ìv{c4L$0%VZ6.[5ux[iL40'E endstream endobj 319 0 obj << /Type /FontDescriptor /FontName /UAGOMC+CMBX10 /Flags 4 /FontBBox [-56 -250 1164 750] /Ascent 694 /CapHeight 686 /Descent -194 /ItalicAngle 0 /StemV 114 /XHeight 444 /CharSet (/one) /FontFile 318 0 R >> endobj 320 0 obj << /Length1 1929 /Length2 8986 /Length3 0 /Length 10128 /Filter /FlateDecode >> stream xڍTJw9tIw7R0 00tw !(Ht4H(!"[|>;g0kqX,!0'W  ab҇" 8L+$Ba ĝ Bb@a1^^/߆0@hpTaNW&9jc# sr8BP0 BB2A= Ax'-, rtm$8P-@ C?%4AҸqP׿=5(zdTZ2. 'oNA`0uXC -Eun'rirpAP2:Н\p3•S#0weVp9:B8?'Cwu}N0'WP'+2ܜy .n6wο @\O-^ΐ_$'| ZC>p|\A XA%o;bPO)]?_%ܙ0ߘ!  @ A.7ftע8 wW|r|n>.PĿB,՟ @a-fO?JY?mח)#?uOwnV{ gnmV+ksGMt6.9xwL`7'3ykW-I:o|X<ӝ|3;Nh_K_z0C)M@GgC_HV\qfALS .,vcOɳ$oTq_Ny/UvR=2A=#`IU7SV\8Io|$ezwbrWʦxGG aXJA_=a|$N#xMZ"vsq c#`fM: E|sAu}lOT eR&0m`LgN L?(Եk("XZP9rN~ i3$Wl0 xng)R<083`]+j j4V*b (n[w}eNFLctXB9eôptWyǏ0M!Tw'L/A큔-[[I%RDlVR:yȸl~Sd|/hS]?V?7l*CT"hrB6G|}t^qWZR'K1&$4UYD=z´Qޠfyj@X#VԘZpZLB".}"w;U_ّS:\Ņ~I]eO)X>1U|Yq~'6+|YL 9UܔDGe5B8TgS Ay߃92| kfe $WzåGaI^5vSϓ^GܯZh»dj{C Xo=M%m^*cS4cD7EpW^dJ`}}\vlm/GIf[I3(@K\?+Ai4 uGe\\aVQ[^ud4sR5\}w)T>S^K(HT?pg7=GلNӮa5s.M/Y`E\ÜO*, Ǝ"0zu~tF~P>ځ)$qA~f*HJDZ&hrqGڪaQ]b*kt-#0=c{wNeO68Ql>ţ8Q353f0`aZxٍ&\h:\' SKyUS-IֆM&|9=lO:z|^?+x` N%~e]!}v2WS< ̈ ['2C$R3?+C'>?LBk}"Uq-s~b"M?@c;uҞ?'X4 gPFnǽ01iFXDZxurYLyN y+5HSCGEucbZM?Xr.8؛) Dךm yJ;^"~S1;c^'G%2&X`8~<3+=p ,a9 krXi?gCn,T]\5\zZ71i{'˕nH}XJP:CiA3OYʼnBV91b^!9ݳѝTb)JdƟNC[(5 {F12An6a?f(#՟"o.fҬC+>s*XmDO0( ߗ2 >Orz`ɪh,2D}@-w>D ޼L9` 2^$d,\?_(gi#TK"V6p:H$fwJSxs; ծ{ߦ ?LyK/H"R ^ڶ4+&#.=G[pcRZW<1${]8g6޶XdV cJ;`EDXݓ S"'/r-B1I)v~oqE8h/?ku\>VOO3T>v.rs?!Dby:9nWh.cb+ƚ5u6n֓ۀP :ӼyL8ZuUW/*Mt]\ygO.fy? bKPJl^?԰%jzp38{*+Mbq !UV0:+=Tkmdži-|- 禥5}Oem񚢧H.y>ʪ^ڄ 䟳s>@=+::z+4ə9f\C`Vj'darmMvO9R%uu3u$GYUTq.cP,+ ~ h+DV߶2 (0 heɊ_0|Wu,^1Ok:Wl~ɥS`:.P=!ȭ!$ ]zg߭2J14Ou%# ʶZr~,<ff0xC;t>9Cg,d=b{p TVuD)O?]JN@(-WCOxG'XnM/"_y8pCb^|\飯6NKΜfQ\}45Y~)&]Fw>ҊjT (D/U>c j.2D:봔H(gͽG&ZGOqZ3&h#lޡtLW._MMd˳!pɬyjjvMch$OKcVf@Eubp[Z< 4h/qAOQzEI2O5PDGQ!}o,Р!96+a?#DMi|򋠒P׊(gGJl@DS4ANL9rS[fr*;!ܞ0sʇNrӎ,,l.1,Hm˧`:oБQ6{)3JO/H¯(P 2y_)_DɍDh.qoT$kB/ZDݾ 1{stv@q])RVr"8C&|Oujʐ-a⃹ bUPp?k [oPIJ@Q*]=H^Q0P~7(=ޱ|K=!`oÕ*Q[v` B0E&t@:'Xqr JZPԿIaq^lo%x$%'UſzFkY#3֮cYMsivai9Kby {qrPwқl'CKAm 6o1*bo:QHe /AZOc9?T[\@ʒϹҾ2z?ܝ >׵C&_§)ts#Qа݉%a4͍lD&`aUo-*RFu]4^4gqUS lT7:N% @2M2TɞGuCz?1$g f,v"'nqЕ(ARP 檕E^ Q0^CLW7ЩU%nWYt`,/{<)c"IZ'I;Ե[8 i?\/qT4xLy,02wŦ8~ya!t- A J^L@09HbH$(L*8*kHـ$Oƻ.HU5,tZg+f^4Z$I9:22*0D)5*1hFuCӒ.iJ %V ]}n5P)Y~)i. O&0­yL#kfcՌІAi0dj):T2 i|o!]3}c3F+=D UmK:6_SV0gn:dqI/dR-u=Z>aoa~QE=嫉igwt ,JZ=Vx &`y,u%CMz,19E-wA#!YGΠ$%GZ׭ԺGBRa#hHe+Yd0hY!Q\),4Hyz?R]gL*o6|I(ͪCA_O%۴^Mlo!tLfOޭ;ep9h84Ԧy&j&>?*v4We6s3q~׳ueHy7V,ߞBw蠴Mh)P~sX@‚fOSZ`ւ*àˡw ׷a ^odbI+18xxPkfNnun6d:3%>[4Dhr!m_ء8=٦АU( DFYYԟ4[C IgX^4DWO9(/O'LnZ4G5)tgdIh 1z6^\t(."Ӽ{ӈsFRfw͔@E۵m؅P8J@EV ^!?`й-2AM/5VYZ]X!i\ܖo Ǵyn8 A*/mΠROrZ{%/n[>~N{\RXdt 7*܏1K!b !&v! u[Z*6: ,W<jCZ1Hq-zѓY)F;FIq%Ɨ&T' osLqE5I$cY9; =<[R.5Q]0wq_#mOX= 8{ sHlELgr5%4jn:dui$Z 2=4^ݔ-S Y\ w-̎M9+'OGNكB㞊Z<kc"dۛ33#-x'޴t.u]NE 6dnBv~.چeO-D zu~j*Pc-۪1}&pt<Sg{5 Ԝ,5 vMu-_KFM0r&yG'jڧO;QL.-|A( Ur"ƣaPĮtwz3"E1:A$ݕJ_~wpWpFu54 ԆCMň_xW弨kk J83V&PՏe#=9Ax/Bꨊef*\ܭBWs'Rk ~4̈Y$R ,=R)A$DOX9 H: y+"v1W=kI22H#>녖焺/d{ݰ:n3ս/6Y;TQ *a xQ+zΟYHnqQ!mX|M2i^$d[hF!`c.?&Fdͫv?+.1xx^5Mhxʻ2YQZpO̧htƳH {~t%2M[=mzM#ч o"u]簭/΂XYs ;& hԖ#&k9,ˊzmmsTNkhK;`Vx$ncN\KJ~ Vh(CgAr; gFH9gO{LRW"i.3\@є\|l=`T$pDAU>D)q~~8QKB) q7V%R{(T8͕KE4<<a$b& WBf>#n%AZK]{s hhO:g\v`toI 1ꎍ0GQ'0Li]I 'n*^TH #lIPF> 8o 17dUޤKkh0Oz]}W!4!|2m9u LSz~,S25"1BƣUŕ0fbP8@xVR5G+ endstream endobj 321 0 obj << /Type /FontDescriptor /FontName /IGWSTC+CMEX10 /Flags 4 /FontBBox [-24 -2960 1454 772] /Ascent 40 /CapHeight 0 /Descent -600 /ItalicAngle 0 /StemV 47 /XHeight 431 /CharSet (/braceex/braceleftBigg/braceleftbig/braceleftbt/braceleftmid/bracelefttp/bracerightbig/integraldisplay/integraltext/parenleftbig/parenleftbigg/parenleftbt/parenleftex/parenlefttp/parenrightbig/parenrightbigg/parenrightbt/parenrightex/parenrighttp/radicalbig/summationdisplay/summationtext) /FontFile 320 0 R >> endobj 322 0 obj << /Length1 2191 /Length2 16820 /Length3 0 /Length 18126 /Filter /FlateDecode >> stream xڌP[ӆ < !>Xpwwww`=@p!8_y:z{y(HTM@F ;gzf&43B?v SG'K@wQdb`f0s0s01Xr],M (=>ܜtoۚ:Z@g S@*BPY8;022m@tWKg /鿥1 P,, 2sv: 6ƦvN[ؙ:޳Tvr߇`f`o+ߛ [{9(!Lڙq-mFH+ ى/y?fq;Q_Y:;/j231K{Fu;K/by7!c37u3qqrLn%Ps7{/oO{=]O')񋩷 KKcg?ͦfwt|fzo?f_?a& ;bFe1E) K Igag03q8?xomUZ?"JۙKG˿[sC  6PLL￘?O[5_Q_V$u9m-m_߇C>"vU_-ojbJ;߇Dett35Qt6W36sXڙ*,zbb?kglpqz-MG35,#%މ>&n<`rD9EF (qKF=?`cC1%.&?> QzϮZ|ZAe[52u^}/|O{F?]?7{D?]~Va[mm,~lޅewo=PPW{ݎ{N~lNHe~|zyQuwyG>{#,-y:]w'X'g ~%fg-VH, 0K[u+8i$nrg'80'6[xKM@ "BS8D/hb>J1ѕLS&C,K[dKŹhDmSmlvnxB,_Bk-*aoKy38ljsnq$б`u}•ձ URaY!*Hc^^JN(1d˰@o'tK-Bk`Y/ҟ'_vNRtF@KAʢ>6 ,"^ d̕fѡ&P2F0lkuWCm]4zfWFQ93&(QW_w^nmA짛?b@<hp큰[*82C0V2cc }tG^nsAD%KTE?6[a6.tn__v'vP,1Vb>`*&Fuo޴FRϝ"u1pg߰]g#2 ~3z|!(x m$%>Ņi^t$㩃(MX\UJ ܊y^dj'#w63[!t3ueT ,K|{]ύ?S2Y%]4hqߛ#`YશPBzۿ-O 6lv*כ݄ѦB4^)ɚ -1"!1NytQF cmp@ı`6# hէGseYpͯ ,,p.7QRz2TF"|iwvik6\;Z 7R$WMIxM ՊQy]0ɌeciVxi=&?jEբ{|`)n 8v&dQ)M5]X>̒[ܭSؒ롦sob[|V&=10cs$=:;`BN=f)zzFGK6}XiR[fA%4m;G`o? $r:mE u[*l'rp4{AߛN RUJvFrjbJV؎Jу)0͘WU[.j eη_6b@w+2U1A<ZhOo uGd%hl&4}z"E&5>3@@x/!h>^DfC>A,kfWfanӖd3֐ƭ2p'w6 \P8a3c~?'}BWJvKfQ;+q!+ׁvob\R`Gaw$G9l әFķ(ؕqRp+kW3ׄu#-)!(7N o zLL#Lb*FμȇVEֈ; wlճ0l7oV43 T%cuԉD~qRJ|D(x~{(v8Mh7 E1S\.-;>ښ1LExz 9m 6L_ƭH{⺚S26jR#v3CCoNPY`V /=b@^GB e2^:FniiI $.?EFYHfny RR4+F։ fT4H]v؂92͸D0#Xfi~?ͤi>CȣcRSt\נ&:T4+RAwD#HQ8*}%Tf+U1f`F?ͯZʉFϓ@KNI0(h͞ݼeddaH4?4Ŏ"ɯfrHZ$"6F#Z_y |LSdɛSGqlU0~|I1[@Kh6`~,q ~;.'Pd C^p ؖotG y~vr߃[i+4C"QhNR'uh !"(zCe% ҀffTO֐{awהNZnv-19 Xb]Q[u%1PI^C"aC =#{2>,OÙ7v0ciBl9STqdU'?D EQ~t E4 *N"ŎXĨRV,W+&ˣ>/uDn=28A].zi9E>,LٍuF9ڜ!/@`i,ϙ`d菐pўHUŖQJux!Bf-g(ź7Y5u"O{?{tg{ULm>CVGD]\#h& p {,gAt)L'uotܥ~l,AKTʭžqo64aDi{{U/y]n7zEniU3tLkYnYS$S1<T/p:n϶ .@s==} JgD 6 ii:Yŗ_u4j\jsSFU+ F{`I՞@y ,Ei"H^/brPٵ̴!gp&yM>7m#7-ZaL@bں6h6^IM!>GwHNUj:ry JݣYRSaѢ53v.t|oʯW(KMpgMwS1&+RS•#zgEF;bd\HWMoNPGuMk?=`y ;}LRψ園1miyPDoa/q3iZ8oG,QnIMxƐf4L|~K2+Zbi.vШp@oLF]7/RwuXZubq={aX,m~Ukc @ -U(8C݄>0t땶, +Ks%xh?x:dYí!P z4.a>ˋ{&d7?C:4:=֧l=]:cir/3Q x3)JK%qN!sjBSP>OHPBG ʞԅm߰V>LJ:mmyX}`q$,hxn2L:a<2!dms^4F_T$WA&cܴafC5Zw)~AS#`=sKD+d̏hJ>oko{ᅎ,F1-سvoiW9B0sFNT;!<|/.5SUIgq Zj&v {(HVɅ+*'^u4;gK11_0Tf{za<4òE\QW6,bsb( wٵW ^>ܩg~ʖ 945Fs¦*  ~n՞8٥dң_dk7 By^2o7RP0tI3.b|~c)zE/Eg.%zZ2~Gepa1zյtr AC@;%,83zHmG % %ʩhO@n}ChkIZ$P//l)ƨv(Y.k)u4krKzajU">E1߭}:rb [" mj"n8N./w}:~7Juo=pV"\Abߢ >ܸ%-uj%ER\Ѥ 7Q-@/S'=L=)눰垻P)l# L0DO .y 1v\j^Iѯ-P qz=D1E*>ZӞs]eo" }KԳ$wvۙqM$=%ĥU\Fʶyd9?c=J7%ekF*|{thQvkI4-GBߝ,BqBMP>{Q<=tOi.OVS9E|{ӼPnԠr<|F B8犫%iuzrE7"[h(8+||Cf6m?67 vZ<PYE`{9G$22ٴ5phwfIOLC+xJ_ֿb)^l4DM| X*-kcdjZ^V5E t0U(*3*FwnhYsVT4 !`cPt#wKpGjͫ3璕48cj$_xh^Y hv^A6vt?/A;9UuYp8.]%RhjG t+ʙDBf~zb=SU/duX.N3bD1 jK;=0CPY>t엗uz).9#κLe$bf"mo-~Zbj^%Jf~d=̢KKRjTeCgl8ɍA0B8vIC*e6^ͷc{̖7 _؇QLOe?!:74 } 8$VpT Jes>K^h;=å/\ۛ}"\BIR,ckG~i:ml3EP$?iĜfi!a(c 1Of63tF~J2JZH2ꍢttGIlNGϬZoƒ2Y&m J:p #ͥF'1pҵ:޳h KQ'}cQ#(2MՊH?s4·z<2G SթI[Xi5ȹ_[̮ i{1| Oɐ1xL{8v֙ͩ 3#fg x%/-t&uNֽRoE/0Mj_;. _φpp:sZQcj{,9c:*8#XC5D/Qų%26\P4bpRqVvU,J9nV&*_}:GgSffFi_(ZEBFSjUe@k-U0T,u73?(zDD$im5̃!/%HP NXG"\%R?!h[ *GbZ/pp~7He+?,-ְQsn5G$RyoC˗hNH+*0 dZ?Qr-{qg'p3TkUV=Mp1rƢ,sf&B4.j>dz]T;?Qx%#B}+$\^aOpƽ(uMA]}e!&^Ʉo'S ?%i+\JA.6+T"$B$&Kii`|F~"%c^"괔뷈{PO! PNp{M|X0ѪN,bh>ڋff`w{H+8 Dq@Π9_*ѩ.D7 7h@|q_ {O.sSI,:!~F4?JGh: u?\RM(,ǝ-3jol72"6Ʋ'TIE H/@=U`x!H0&ĜK:< Z//=umjK M}X.::kwmɆF+:(nmx=,iE>"!*È'dy3x?, `V! 0!CМ!݀yAP)96UgTߧB Fjif@dTnD9vܚCm%"V!ґcϞ+ֽdRjكI`%g|̱8&qj|磷Jqtd_00fk5 M26oʔfXʕb?KXXRu-9g=`slcdJ>Dwl!+oCpy5>,3D'e6ȋCa=[m<qY9go eA! ~ o.@ ~YfLlёXB}aL} r 1JGDX. 5~ɓbI'R^KIAɖD0~aH<Ƃ4[]ZoX߱F,~3˺VLh.BΥLr ځ 7,zq 4JQ+a"e*adrA>//+⃝Fڭȉ7:̧̌O AVZqk /}M%t&"Kw=J^;FID0n05N: Ѯ{(½\Sm&^B/Ġr@\@] eSavTU v1^}zc7NrYi`m_ri2j.S ܼD7ݱ'oBY5xtԞ0 gI—,\;}&GTSD4K_Ip37S^_-'o;RĆ>V1nEJ]g|'}J-2xzI%چZ\ / 6}H V|%i\T|nŶ#<@a8@/ҏYOwr#67^l%8rGӁܐc~.T]IfMO@UͮAR @t:Q<*[yHbEhgIΡ_V) Fbn۞8F`e}f(P8-g/΂L8%Z %c߫+ѝ0/Ka1,ҁJBVKJMDl ~]%fB#Uyi/%.ׁ~uf)D$(TB,/l6,cC.S~nAOGʶz^Ë%76%&qV"7>;zo5TVA.Kkyb$Vu-?,jGfG;mT% rRKٿC>*C?:e7o]JI4ljLPyNJ((B) ccj ʕYC%[ݟ4:}t^as ]}υ!FEӇis|41\c16Ȣ"j?Qh'Mik`b%F$=޿'8?̽H|kŗiBĭ77Fj\GޔI-B;W3Et"BGot^%d'v`i`'eQnU2 *427rÍGLkT,ʢA:8'kkiNZ\qoAhI@EfIϒ bJm%¹TfUDEW'mMHP+ebƅY~Li~!^v|4fߚB<6H T=urݙpgXDsAF!'Y`K}r㸙 $f^z9FOs/70C+6a>9VIy ٢AP0@l=BVٔ!LGsUAnjNWn0@֫w>2F*6&d|cCjce\DWlǚ6@÷lTC*v׻|ЩtgB=`&5$wSj-m'{ip NT ~ f[a Q#8J k.8kO:s)hKK n$2UJSA䜨{z6UQ0F (a3щ7l|kOF]]/ 7}>/\Q~0jE SfMg umT_HΉX,4It垷\>kɭMmԏsFa9|m̠֐ 7( TܸE d6~$ UjtvϳN몹K[VEGAJȶsofuezרRH^8#b1!򟥐[lô:16Ke7wW2͂_/2}`J}|fLjF5q"Ux{|6f8D}L;5a9UuUlW%PǼPldA.7 ז֚s6ɩb8>X2}%Uz >Z{O20.R^~jN Q\ԇB$^e ǥ*bb) ;`܀MYO8lZfe/TsѰ "v_s7a,-$pܐXWQ6jaB"މ#̐N{ Wl ( & ~msBH= Rj.4R}}/,zY;]̆\#ǁ,Kݟi]&d$qg0&r,1"F 8omP=Ә򜋳Gv \(^yf!ɨ}qqY)4iƒݬ_yzZqR']#w3MMHkh <ېERz܄5ë #%8[V -cv:!}5_}̢Oixϛm2XOMHmkn]k cpy/|PuLXq*QɌ 5`S7]Kc LV +pMWilbL]wD{vCB&<@mcBO]$%̹-[;$tnmjnQ/ucA1T!鿹^ٝAvhܭ˻tIIuө% u&v_*3 g{2rDzO//Xj弄 lWa*badVgHTd_o>P7,\B9E{bO JcT4Wbxl2҂)N8v9I&ҤRa6C5>q.RD|{fw;[)}EJDƏڕSN!> k/F-JC ͐nl+IPO.W TlySŇq %"1#D66(6}S~Ǘ4 R4Ozm[1*A̷=tl7vcWDNjFߩ LVu~wTGGCKuJe~KA0 nS_:bm[}WL;$V?''p!,0yQ!0LaGѽ.7u3Ä 6K$˄IXEl`sGY6iU@BU^њ3:'}_`|f]6^ Qs5ӡ=K!%vNBEk215s;¸Y6"!7- 6.X̏|Lb,iv GEJsl.{uu|ptIx' -31sj!]Eg S+&HZ%lY:%]3I/1B"1e ?\a! 4O8[[J=]Ngܝ͔Q4 Â_η ~z(xbm#; ЦeDU7Ayo##ڸH+Uai>*֜0"}ia Y #9Hb$b=V ^ՠJ3f ;49}dX#2$+XQj-Kr W棠ಐL <ά3z;\MpK v42Ň-vS87|jL2mk< =MrAFy)d~u'-CWi*v'ad~* v^PQDV :ϢGӒeMɢhYi CGVN[t)޷S_zbXtj)p2Hƀg OMd<\tZ,uػ|`bnKSr1㸙p׽hS( K5[E(A|Kޢ^/yb ٰ̒f z&^T.}RB |TW@\unQ;k,xH]w,"_uΒY-vuy 2=9F/HmFJ=bi'؋ ^zhcw.ky_!=p*"F$YO |G%X7>2~"ch㤉>E. m@ˏ5 LJLhjs_7հ =PU_fVUqISEcNd,6̸'^њC $#۩NX\+ZK )N1ރr$ bdJz3T\f@_7 {q}ǔW"J .vL-n3[wzH7 O"^ݞ͚LP-}n&Ȃ-oP{u^jȰ[pkfk֑,{s9JW 6voiNe$d(RV#xZ:`UPpDSYeE~(nȰ?x`ՔgK$uj3ιkIۅ`$뤅mKI*d;[쇬f|t^ T='YKMh2Ix_88tB6i|~<íwAרYyL1Ə$J{Xi.HE<a1i4˵w5Pc]W= O:^"u%,=zL0mW STHؑە*<$_d ,#Q/$w!F O)Iۆ۲݋{Эk;pՊY87. o{;~pXTgK`B7 _iB~AVZn|}y2d$W=ipn/,#^kҐ* CPuʔVOx!be/ [WRϩv1 OFƲ$R-(NU+0{z؍ #|Rj4 W'toЪ!XTƫ^Kd_jCpx^1c+^@?V #ngqnkbzy ku},Q0D Mύ)Cs FninlEdI 039@BHn?M+ūn†w%q*>|`ckh%~e?x9vq |,]%2f9<5$&73 ˃-]dT,A!鈜!KQ(ɟdg/(^rv^ԡ|Z=MgeH]wPg aT1ofh8QLhK8Jm/'fhuSCYE8qx@H5C6:Sў!R=)E]lyQKVѭf6(> ?nJYHfNJSEioO mWXv=VN[ :Ud8 gAmy:Z; P eU!20asRAI(: c&P\ђ =X?OoJ\%G#)$h+{$3A_<;cs;d2&8?x-ʣeG^-vR8Ljb&Zkv^-sFr GqL9WRyR]5hg(3mܕR{SrOJWEiMŨ5 ;I2f/$dWJ$zdpw60?i!|NT){2/΃b8ߊkL4%9SV%:u HFLζy#AA&,K++;mpXaof11> endobj 324 0 obj << /Length1 1705 /Length2 9669 /Length3 0 /Length 10769 /Filter /FlateDecode >> stream xڍP-kAwww `p!w w .-#{꽚ojݫ75:1H&TVqqPSk!֠(Z G' $A@ȋL yS(8[9<ll66 R@)@`g rBww[@^}Йypۀ&@[2byhۙA A'd mXE` 2n 5@\ t^`Ӌ).Pi௻'_޿mpm35*q0 Nv/@ hbG@[s2qCXֿ[d喥mM%ll@'IA&/dl\m=f`[SM:۳jڂARP n6>^N>6r3`^oO{;{K o @AޞV7BagM c9/bٟe`7 l9?˪-ώsxr9^}9xwwHՀjc'^.>\_+C*v/\>7ˇyp(7oA2@_/Tvr6UVmW+ řٹXظdn S50O"=`[?3zyU^& ?^됶53<#/ ?`e^z93?/['&AV˾ٲ#d rX-_|<VV/ɭ9__jKpEyY_Jq|v%vC/*w9k =wܹndɌ@&zSc@kH :CDbv!Scx.&|UU1K _dxHcmMlv~xJP=Jk5 VIwKUKZpX Zk18㵧,رi:}]ʕձ9C_N3AIlOF~Hx|xP57/cpS\X{0>oQMGrv:ߔ/\ |Z]C iP}ŊELYT]x1 :9ܯDr\.ݶֶN(ܼ>6(M*Q(HD?5m-(饺QZyu]]E(JvdXJ3z$bmOm$[GoJSxXʛV«h AZ?_/.@'r2 o7XZVB6_vRK"P띱dJrh0a&h؎źt~HO\ F_7։qo[OˤegODgLPދtֵ43 ś=Օ9 T'w};~1BY"3&j C5BP} ƍ Y;ACZ;V^}g%rkDҚDOb5JK_ :80ХCd]h2_OH 4QɢM\ɮ±8|g":/h':xC4^3NǿޝԊ$PAg>H3ɡvk&5{$|DUx]K M&n[J7HJCN PiǛ P71Бr}$Pۇ5 g VDC~̯׫dSMx3C)j]`r#k:y#4]8CzB/Bj|DàWh[=@OdpL̗k}mODTq?{  XK6àj4 F(ӨHdjppX`.*d]9$QCM"r~ 0A,z Ȥ zqqA)9_5amN_IQ?u`QeKB0S |A%3{ ZbC* iUjŏ,Fԛ4~4s_ ]ayUuuF8FP/^3`od_xc~`ʶ˧D9}{wWr8AѶ4^(3au-Sova8/u=U*ł4CVlIvk>.qÄKs#˗/ Dlgl !щqcjB c1BdCt٤)P n|A$w-}0e+~ڷ*pG7s4ةaUz» >e&ԷWۯS|Ѩ ~%I7%9y=>jgo`)vLԁtQ*^|9#aoe'hfi`͉SD,= $;uZMSHC0|,f& 2PI*[w= ^r˫Nz{Ucq,sT{0Gط_u?*w5Yh&9Ka5=r^xOaI$3抦7uMSJqnv֊_‘lb.3J-H .-ʞi;SI%Ԏ/Mk#&Ph|` [S]r) Ԟz%K^Hӏ&G3w1嘵G4KbǦ _ҲNXLv5O.O1nqۈ|Kga+kce-R\h)N]g1VQHqVQN6A-WL}¤s<} (Hɩzn\ulJr{dhG5+-hșNqռwx ϛzK~SBL%1ń5)+:D'o+W-B(-7 c?"˥9}wm#_K7ۖvOC#ឧN~JxDl"rz`#{О!:vDsE Ğ3=iwݮ4(4Qu6uRb !;C9d]@|u+䞯7jz,>;Jag"›Qq ._No5]17]u nҎqHVLnvlq$'db QIabD8QcV'L4QQ]^DqP\f26YhE}Na Ek)`A h4"f@ioA.KrwKQ± s"AAGĴY1o*2 1-x9ƣ' zPU_mqgswbbfcק]5>hvXӓ[2!OV/*7tJȃ2:;5Xsea1-3'Jhco‰8C971H=CSl (cէ6Eb5O-J_eo$x9pBul8~l_.UcR& țkic hNNQ" {67i=wTjՠqJ]mB j#DM\kh)4+7 %~KҒc;3H tPdv\ͫ£em)!&y( ?rjh4fR-淌h.5 9 v]&IrΜڑP{uo*%^jizE)j ]> ld:¾g_'Vxx=߼o2c/t=MgnXw Ȱ6sf}<;H" qQ+$oqfp1-dy8 t\Uر1P{־ՠU@usq,JWoI0W~rExl膃AB;gHg|7䢱$cu*Ȭ )p%=kUwlP%=A;7K]ߣ%y}\;Gs?#zVϰN\ c.A_[t/ u!95oX,5a/X,LO(J(r~]-5= q3m }u؈;l-g{cY,: {0ύ~,[b0-He쩗uO6R'/^v?Xrn0{?$w)#N'7Ƨ $Ef>#X+=ϝHQ!Py#Q&2N*.(ȴvqLssoݽR^k. rX0ڑ+s8Jʱ?6Zs0ъP3y$y阷2:(GWQzq?aEc2 [LK# ++Hz:; &|,/ԇwk}x݋}&ĭ,j:sEks|- U'cPy1G>} 9%9oQ.|JTUWE:=<]hC[JB\7)PE]>b. qGv$l7`4M&\&s ďoOv(3**G^Uy$X!~Dz|̈́٢)L.Q.t}A?{%U™-h&aKX.tR*a!8x@d?;P*x%kwGՔ+9.Bî@Z4Ҷ+׷xԥ1T.o"CvJуՅ.YǶ-l6Viy(#5ڋ2Ad)M21nUen(*D*Dα?d+S;%*,븶jāO)-DgQL~I֒ZXlА./ YZ$W-B WƂWfsFȸa z<#:3ᗭN y„Lhi ԑ12wzsiDGקO3l$8q=C7jVdڠ}t9k?xu[fl:-?ߑ hcF/q?dA?yWV&⋃Ck|%+ɽ7W?({*as ,J ]6' 43VЗ^_esu RaЃK0"/[:K>G5,]+B}(\h>طщsKژ]6\RJ"E1ْ'bS\A{y?|g{2{paQxWL̬*7OQ'>cA{3T*ZΚILdsQpucM9DdIk7}ªd q's( UMR ^ی4 ,JڢZH-R|yˢITGNfXw$Cz 2wژ>97 cj?b{769 gPL")?%> k Xȃlz ! #3nٷX5!P> ea~F2KvdN@H_ .=D uL:X~S!J7`rneŀjQ80k-IhzWRG8TI`<"+zפqmB/JД-ܙF2-,d:ˈ\`61cDNFA -"L8{@Ks`$^s0 m*̞ƍ&QoWEDrYx 'FgfXYW$餆v o2z"]&w&ܘdnzbR }NX1^hhVl9Rہ$xWPtnv; SM@9j0 &fWκ ]j#*RuDG`-J'6mMP 'ePU.o"\̒p:^{e>r辆EՐT`_ih6*[2O__~cP(D&| 6=h*֬0 =$j?=U8!iGÚ6^9Yh+VM+hU3kh|Kz)E#6CqT7Bwۻ!Lq+dwS85c2aQN-5I^]VEg\3R/FFrϥj\ 5Wv u&nzvg}7"CW6:9,=i,=p%V$5- ?1&_bbi;wn~sD *qi]'ИmlS:U>#<ٳ5xb)6-r ;̃,ԒҽI\}Yp JgGTԷ%G(8y#@]V F ǃ'~6#}w8mC վ*@z>F4df+*;ju ~vR"/AKokq vzRF8^00 IɊ˟8yB UNnb~=׬SIf YRW7r9`^ :sGf_byYd'wKcdo<-?q4Ꞿ.X57b31&,y?FnϧX,s8L_o4\^l"U'[`7皮t64pƘes̿jؕbʼn=h/q|ocu/҂`#cfFhGhIDyPkzG 'nH WLheؼcuN/e}-R8?4?i9n9)<)3&):)?&Wx#tG70H5Ŷ}73^ɝ:k]1E ;UvؖͩSl荖L_dsʭ6<1krEL}*a~󹋯Ә=Ǔ߃[C r2VN06/cJxX:& [@W.0a59ex^]$h319}FjѠt8$tV+P2qȊ1}-`(w_fXu=YulCOE埗DVH!#moI4oV쓊Hej`r1p0)lm. ?S˘MTү/'_YPFwl{tL&#ݠ1s]ať,-(ҮZ),VT؅|%)llCR^Y?a=|۰yl|{d+]8$q4o,9wSG޵]z#I#spy1 Xa霝sTe[[4Xު^傝;ŷUPf :p"Pycൻ+%z/U#%f l910hu[ha@*"J4^cVvZ/-9dAӓxcB}ii:PpZ;e5H2 ó+T\`Ĵqs6\t z-G#љ@QKf+Cr|GRvN$[V;V=G+l>{,vKVBc߬ގ\OlB~͙SP׋_ K!DSkEeӚs[fV6< /AA<6tfڴ{?Y+D]?g0 vv,J֐{Q5X|*+ I`1A]+9\xb|g>65S!3Ҁb/B|!: 6>L93O5'qy=KFWPV^]Z_8M Io<(?wo7 ׊h(p?m/=գv>Aϻ*hY>N夲*;%П;D:SHOĹozo9%z# 5-4Um<\tyzNg@!Mb}r؜{|IX;ItȰp8+Lt{#[jDdO2"OW{\^N 7DMoqb`A F Is;~8`_TM(,Y/qͶ-ZGbL U5]lcBqICסs&);Kg~"РՉa6l$Y;#W;{Fv NpD,ְq ky3z1~wc]>A=uS*-ޠszWR;]d < _~l:$*seDZotI7c'BJ'˳=ԫKd5. t C]0U*5Egq\΄&ћ75wX.sFIwqhJP*|{݆4bO7ޔ"tƾ }n]/^0[%$VR4CElum6$ #fmz0?R?k0w]{Z;C__©Y~C>C.=m|nk lUب}/L:߭_9.ə Z;q&,iKw*vUKejNػFɥQ q8PHG`3$? a1^oV4pfx<{҇SR:TSD,ۨұ *c\_E۪n+n*~mKu%0^ |clxH4sJ&[Euĭl\eEc`AClEadd1KhֻZd#OvuqN\+\$N-&yYe 妔KyglO1te[=~vQ,1; ;xKGSV),' Jt+W6 +{!XˆKX\$Qz}TNjXs+,G ܧS /aoH?13U>Ͳ-3 :xGh`6>#"7kp#9VASlGN-_m:k>Rq~ZT< GϝY'7i>D@RN),M%eԲO%xhd'D=kwKEh$:%wÄKf2/(GtlJ~QFa#-Oܯ{0(uO+³f*d1ͨ'Mj<[ ذsŭNd;h}8(n1큠m×gC_Bl -5l$mvvܝxdtmD87HZ ϤM'qh/0j=Qy_cKh'LyP WDq2-ղ!^ LBi<5a5z r 0-M4ݍkU_zki~XhdDvRmrGdNEC endstream endobj 325 0 obj << /Type /FontDescriptor /FontName /VWIWYR+CMMI5 /Flags 4 /FontBBox [37 -250 1349 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 90 /XHeight 431 /CharSet (/a/b/c/epsilon1/g/h/i/j/k/l/lambda/n/pi/q/r/s/sigma/slash/t/x) /FontFile 324 0 R >> endobj 326 0 obj << /Length1 1984 /Length2 12931 /Length3 0 /Length 14155 /Filter /FlateDecode >> stream xڍt 'iĶm4mlcil5vcjl֗s>}k֚y׍g(HT M$lA @Ff4'BdmBΖ_&wN l <@Nff 33 yb.yF9=F4 77'aG #[=5@?!A {&&WWWF'F;G3zbdbb 0@/fp5s v WG*-P7X/z߽ ,lt6027u5ZX%An zNv.VnV=ȉLyﲸ- ,Mdl\m=Ʀ0vgRpp6]`gdb8L܌̙no= lo"8 `laY]lb~@}?>}^v9_&m%q M9W'"bdXؙ@ 'Q?*X]?mM@87?<\^ O)w@ffg6z>?]QV$lmOoUvq_SMNYjA!lk @6FfNn&J #?xamakdd݋ޯ>TN's`#:mFv;B#v'lMw`jǘ98LB\&"NV?]0)q[LjE AQ AQ@b266`2#w-_6ՙÑ2?&X r,Y S/dy/EWd/_?%nojߩ-rw*Nfj9{z'kuN/Y g17abfb8gg`Yv_%ʰ;u|0 $[" еPq\ܩ%sge mFl3v >yG@:(BSD +hl֧JEUӳJQ$)ئ𳳪(][xKl8~Ce94I!TwJ^®p_s 8 tJsVQ*$4M\QnZOp^s.o7ˣtՀ:Bdt}+kaۢ+Xυ2.ژ *{K[@Tybu(JfcT3-x=fqUaIfG^ՌiqBEf)M2/q}ԋhfVPi$0ͭf6[^.އҫ7t8!GWjX'01R C~z t:.eq׮M$)SStFOׇR~pTÄдUQ!NWᅸ+Pڕ5|N_kr "(+\Qp}x1 uzt]9Cy ݀G 7Bp̤Ddd14GWIgM0K1H-We ,', R3ESUB幝GioB۟ѢtolW`8{,K$3Ku&҉`#t xO1|D ;. |OC0!c0d^z݇Hճ_ax|rt0Qӽlx噖 bRx4]FVHji,"g]SILCyk$08j#m$?iq+@;s gj~!1)b:`aҨscX\Oܷ8yn1˪ yF:Rss8v|m`rAk 2UHdlGMs6(MN[#^TX ]dy)kUYHW&>MND_eJ% ,PCvm 40m£O%8S.ef^C e׽1ˇ%NYo5uaM&~4!dh;t6N{<%{̩ y- bƎ:Hk1ANMSʂ٢5T/Eav7+,C4iB!=~~ OdA%rjh|U5o?Պ+xf`xaUO W!gzOk(1J%hi7XqvUq=R5#~Kq٣e@aO _vLBGLO݆~b|NF[O>uLJ0bF++Ĭysָ2 6SiRJ0 6Fw/~%(u>5.R['q]E_w?/?W;⚱X)$Qbu&e,mg2Li^|$H"- Ž{1(?-sK2X?t鈩6cYY vo]g qڰR}f;`o5|)9uQO_5!YF?˟7xU.2mID;<#h<^_AWߎz3/I}(È7X) ???^KT, *Qm ,^4s&oJ`a^(K3N/eiw MEmĞ-_i5|To2'?MFGR2Ԙk]:It&H序 GZ)b>Dfmdtg79ܡ=Kǚn0ԽTX_!.gvs_hۇ]wFL=|@(OcCt Cd:jJ~5jTC3\7L h[%l\oX@RZQ1%'#DUhYqS/bT,h p9>|ҊcC$~ ֲ @]0ह]y:`䤝dKTi5HӜb`J!5 Xme rNw]Fg^ %IjH(K%)ZoR}YzP_$5Az̑:m CkڜDG:Yy >bgkHr?'ٗ47a 1%KPrpU4"׬yH8 b\sஞQJJZZ:1Uӎް8X-"+3a/Npa mCb?9fʆ7?At~i9cW⋚j \N%xTTGȄ=/!wCB.ٝ"z?BBa)5 ]g^zn5 Ԗ**`':asC>s{s)/%ܾR&)mQr}_ظ#EbJ 1kP^&%7WM=ϢӋo\WtSEvOBci!;2(YS#*kuC[~tjAb} Ŷ|-(3>J Brm)+8qvD.pK4T/1G纟KgǤ\\t/- Glw{߿Nn} /[fI>(b#Xx%?M Z2=yXwQi*hnΖ%ކĖYEuɜ }_DwkZ2k=DWM+,$U4x`V.JPq8wZR2 -Qs""jtCLoڷ+QR(i|VL{~?|2܃rPa^-Ck;HI99P/O b.(!yS.|5?+ҙbl2 TَƗ,4,}E*5jJ'w(7ipkKz!0@u{;uAU|~|w ̃Ugf'y4/B[őYqAz.40-Ě=<LeqJ]Udc~[s$%% 6ddar+%&eFWҌj^^[8/Fou{w@gLm=AҲ"\"}IE^}:!wzq02Z6%mؒo[f j:hZqb湠l z5ger-=3tSʬD bM-[TQJA]"y!.b"7$aY!Eɺm[y<\YԘkyB\_I_?Mg`wʒO^Y$%;9YK[Uh(n%h_SXKjuiZ|:F?apgѫ;q@d̙E{f;•7 tK?R/޹OP>A,X1jmDYrAC:U: NHRDffH&~DMXc@scʼn|l9d._=mW;r*ҩo@[ʚ$Q\db({͹EQ9`7H5٘N izߞX(3,zwfģ䣓b_=۶7tyNmT9 )+w}87߹6 }hu6ѩA 0jU]d,5va6l+T.mOh3zDGGmqӡj(=y s9I&L`;U"ӈXLBuld,CuDblƝU>pC8>;(: "{Hs+vS%}%!1o!?SD.JruAtyy6DϙZ/J 'V-陪'J}WU@lVVvΪz 6WqsdjA5 ŷe6oٮFZfcS,R1F:ʕv!goj;X*~Cm-ut4ߍx1I(ӄѫP;?6VDI9yp^}E]R`}sT?rCTIaV\/Mq+w+Qm:(b?a`foIњ'ZcY|!Wcl-X&8p25|:÷&SVƟ[L$<qA$y3sB(S[WGrM^LX/?B3eĽpu0$2uyjRq;AFK!^vMp.z'ߪpKLd4}z}{ɥ$.6c\LR#$M:p"8~_ 3#B!2Ն?A$UGhZj#Ah89Cn!Mؾl5)ŀ3mS*2Fma`Oi_gC+5pJrGjrQ5 yU$ a؆q2TQ{>%*VoZxA-+ }e6M是EuwgtZbyC^-J;hf)lV&~KޑiVm%g]ظ$kSaP!*˪k"8c|WPZtQO}`e&eLV{NБ93E\DnTLڱ?~Ѓ;)$EO)q-BJ$vk6 V^wի4StՉ!YF(WGPc{Ouլ>qwLne!v褍1 oz գ!gjcpd+䃕3BqdHV~;h J@ӿ,ϕoN `5Q!jC8.@{ݏOi%n+W(',k;;[牦I a_ eO' v1P3HZE\:]8'rtafo褃L w[~Kǹ;|X;Δi"O>|1LH}1\wŽ 8^*wS X6%o?NHyA%Ӆʁ`ORo Xu+#GnEϔJ91;:ݜ*{r =R*>|N6gIpNc0Al83[kRQB@v \d61sCÌG|D|l {4$@BL"/hmyBV`S}^ؚ@Ot;| oe}؝X.Lh,PAc !+deDH@+'dX<4iߕU-E|03ś:ӀJ"aZ@ҋmo0&HUg?٬/{zmh+iA81Xw7f@dnC"=#pӋY+X oVTlQb+UVLz=l? gƣrx=`#a4 WݬڹD>7w74(T>ajx@5$,sk|/pOͥ^:,y\euK4D_fJ,5'T֩ zcԱ̈.'z2PS>T/UOz.7?4٠%>$)LLSG.>@DJ:H2-KPzh%nV(ϝwj=@m)nqm>q*OmDTМql].sISrspfd/}*J|//慦 4>!z2b%A41a8l}h־Z^-v4RķpGo| uh\XB?5TKg /axtI2xXX`3!UHK^ۓR $Qh5Ӂ^LƳ`c8,2F}!$pK=ĵLdA_:0s@ <栏m'#hFEJSEͽ%pj :Dߋ4?]ۙ~ŋ" lZBip\rZPJw_W%Eh Zx_$ח3j:!͊r-t5pu3\4Ʒ(%gn|7G^xFuQ*( i>hſ$G8IZGSN#[z> 誜r|ͽfX& T=+ćי$ S2|k-cTnc@`v=W:Yq24͕ =trW>)2g6ldy"Pw{7UARPYc{WMIh>MLw&L*;F֦7 щqYl4\~sሬ^̬# ēdc~>ܮJ{}5)}(r$HRIgmq3LvkZvHݾL>b-؃:u%抌<`?DF M;%4Du/ɻ7x3ۡhphd^~l賙qq0,yXVVW1z2O-4t[A +q1b/=E!)ڴ5ݶ["/byu]}oF& 2/^nw ac@sY% 5H)j sӔ A3ՏBl)[ reA{r:j>c&gOv`[~m Ê{ t،j_exwEԶ6~S֠ZI@G5Ŝrf U+SkWo(A- zJBK y߶F1.wǐ<rVʪf>Elֹ@*}ǁPpM!SI^W؉?vUeJZaְv$&2t2o$SfȤDrx9d7]Opf; dkMP E%ARf#Q[?TΎtqûF?R{R0UG?nKħB^}:Ovԅkxqi@#'&3إavsT j!:m^j68ܚ;z^Zybg[Jk%@u8lnF'%^ /]I+R,/Q{FUAJ~Lrg7ҿOjh+EBË[6ׄ E4΅7X+0G+ւal&WbsBg͵aWdžTu2gDF vᅗi<(\' sw3f<;zHB/NG%Ď1yGVchͮDJuB hA̛[=,Ob oGL:`EÞ5k5C[0MB?ewegֽyMY%JhJܐUY|[Z{p&p#qcbl mۑ`rvç%]D!m)\)hQ&JқDnXD֪BKm0@щ[{O}CiAԎ=\dpYI>A.I׹񂢬L29"1S  mގ-';Q8@i=Mx[95E`Ҁaܮ%!hH’ wA)W:D k)*}{K$t:1b`hum*ߓ<=Cb1@ L9 lam۱i=rdѢF|Ğt;($HG͍{sиQ#!MG033zu&HcF%yZC?6NhCNsDV[)$Uwf {QEI$^t}/:2ۀ T}+E\GťRz2ղ΅P\_):9iQ @1Mx;c46M!)f(u5s*PsSG )Qn۸\QЂ[:d![ͭl! xS'Ґ[K GhΈ;s(e$\b+{G-9 ,`Y*R<9҈L}jڏ|c͟4ɠd$O$`/TL4p=)å䇴|3}&IY08]Y :Tw7|Iïdxe^%'A&V+'r endstream endobj 327 0 obj << /Type /FontDescriptor /FontName /YPEFWL+CMMI7 /Flags 4 /FontBBox [-1 -250 1171 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 81 /XHeight 431 /CharSet (/C/D/I/N/O/S/T/a/b/c/comma/d/delta/e/epsilon1/g/greater/h/i/j/k/l/lambda/m/mu/n/o/p/period/phi/q/r/s/sigma/slash/t/u/x) /FontFile 326 0 R >> endobj 328 0 obj << /Length1 1813 /Length2 12400 /Length3 0 /Length 13564 /Filter /FlateDecode >> stream xڍP .kqHpwNq  R(Pܡ[-'̽=; 5MqKs.T`ssh va ,@3+&eySv\\^A>Avv'; Rfn K2+@ tAtptY@^@oc ntYfkF 3;6 ; 3h]n@K*fl@.Vw3g Y.`K359@S^ e38X9o?:YX8;=A`kPQbx@f`? \^@vfVnW3"a^, t!.('rZݓ~;@`K?HX:iAN@yM^!0k ':6lt~ez%Y_P]܀+?-pp,A9F'+ K~3`{?>~2z]/K?ΗMOWIMM/IH8xY,<?"'f(ryZ}2 Π@?on|QoɸSQك<6x]eWY(;Mu2jZyyF hXCkx;e`y^ uV)'/uB-6yuX981Q^Пfrp{/u;ـ_ӲՔ!\_g/3#+b" "??׺ *Y8v__[19[~ __%h3nQ"Z?_kw^i%Al׌ |q~tK_+`Z#}ݏ@򂃅Pm]Hm[ww4{) ,ΝI AI#k;Wb+OG |M4Q"h<9~m@ʏs/Q?P:_ͫX6mXB{U譿{7^MDMOH {=>M-q@]R6*\He3nu_IнM-m5qTūn7r}vYIw\X~!Y̡x?48܄}ii-%v`1\[L'_b2%?› {'.`g'9[xҵ5hm̫by iF}ntODFPq.|Uԓ\6ү!BnyپŪH O;|SJx|u(a~kr c:w#ߵBr#4]TSeţ`nvͩN$(0tLt=3K.+(l$UGT qYשzK&s=&cʤsY3[M<*-řjoJbOt*]-N@;gȖ mwA8b';.cC e!1v+S<]aph;n=hM)pSI3iDjY(JPYiXw (B!YbE!A%QΥaŢzGWf_TRAy!֢PLMu/ͿMb+EYvK3ڧ%A]x` *괩_p&{Rp滥󍜐H55#D|G&9I]j nV0ЄxS[[|]9~p=iKB uӳמd ~d4Ngmmܪn&7my5gՏxQ웤 wzqn޼ o0N#i\Dn`?gj))aa&U6 ԗD!#\GT TeR+FMm㾢%`ˠh81u;DD8HIcټ8Q*rg?׆ԜsiEhh/_'K6E?[0}nxn -݉uޙAcb(ْ^0zMPӃ߉BrjÑ.[;'zrOnh+NiPַ 2yp=̕?A l@GZJD* ^ʠ*y4/iKYfkdnK~K?!hr߰ཫ @OUrǃ5uS*k֝$,_3a_Ng7M;BMLd˴Q$gДPb.?)߼ɴFj[zADﭱ _~D\_Aga.3IB' o@yNq$IL(-J&.O2 e)uX6o2vew唽 "U@%8] x5UsYF6~ ~agLlYZ&at-\{p,9hZj/Wn9w(QO+6-CM켉n7 &bV\rjfn^Dx&5deC1qLCaBeȁ\::BKhUY[ ~㾰Pw(eenrRtcz2Wg*c)Z ?ݙqsԌt [ \?XƦѽz+ Hb˜Q# ʂTe@ϴKox=?* ɨ6^+"MƊ%o4-6-OBLv*@ȠWd,^I~/ql.hO ukeYGoK,҂S 1 x:e*na޶,:ta"6IZkldoqO9L]Y/]Nw)/EΙFiPګ7s<`S\u9d<~X?'4zx^5`MgRQy~)vtA$ KH^(auIVJrC,ŨnJ>|RΙ9h(sOrY-S%&cG`QnNNKwpliΏ<Α~7!X0&]v.Bݧ=és_*}JATJe Lt^O?S|#U\pl3͵<)8/.I`MXw7.Wb HQHMgd`-sPkKjiɹtZ%aǯp-v8o|ZYG&vF6&kߥxmDY@Ar j#^\{{*P#Qkݒ(~ cR 3G&9zuTv ϳ.[;'c>"u>@UYQ_DM6MBWq?5e ŘL(J|87W'|>F\?֔yXx#IDƸJpPk+ף>X]vTh oU &t-,L,x]@$G~~@ݨ)/IMn|5>?2&*WBhHFj$6 "0҇oui,R.rKu5F@A\m4X^O;9hy9l"ECBcwFo48nTmX6aJ6ez,{A~Ϟf<e5=)!2#i=(P1O( "}#Rr0w\<֒QY{EVs}Rb/D\M%|VsgޕJ7mjۑӔM~t tCfԖq \USxzveͲ8O2ʗk39hhhR4Jequcs^c1j"\Y D,]SǺ m\@5*e2U:I@TM'_bif ,a?t/VMz޶\>v0nUmtv9O[{ WjޟSM:.~5l>MqSF|~bkGn4y] ðR _2 zvBp=g +8+4]Nߐ&Nm mkǘpkL"Ɠ&@Eka-{\O,\!7E9@oOZ4XүY&4wzǗ< ]-HWh4nu1MGm\(zEϡ>oŌolqGrTMD|ʬlIKΔLgZex ܇v坝Kă6@}g3zΘ?HbV,5 a7G,e̸ mfe#m6 ]_4?`k)uIlR 6؆z4 'OaɣT\&mcCM%7޽]/B_p[@׋F;e`!hS[1bcrÆA޷lYfEhՓ3]Y=fdoz.B}mGkF#|=0tS]bSv^QIQ"-',JӴg"ӆ^#.emncƆG[2vtmd9P",k#wxM_Z0ۍwməNyRV1s3l}-Ө7D.m"/}"͸gI P}rӧ)>cT9p|L[I8o0 a6Nȓ;/͘~\^8sw>JFUM>=j$C3U4RڙeC7L_[ۑW]%QikaEPV)}y,>=MFw}|w/C`#tW!\eR7r m=QqwOV"U {uNK>T^eֵ1UyYy:ёRwX9r`PkX|Պ &%g5_!HYft{DXRbXTTn) 499Luas!XrKrq2[sUB"hiF`/QM+BYvOQ],CA& m 4ҰVEGBnnyؒ *uZ v-NnVfU֥z-cMiP3jJ4ޔ$T= x`W9Wnj!JY;iIGOL0vOOCCd00yQ SC֮EGtL`FD}g )θWdX/^m2HLJc=jfܻ3T[D9 nYRV : ft8}BQۡQ_vпr Woĉ, *(:[8DG`PoټaVOVIroqBx0L?p~īꞮz&WpeV$Fh`!^.heUԂfD}MBG 6:,o?PGy*}#5 /2:q'W¹OϫP0[S@_[4Sd"71D" nZDx,]p?~=A̸Ҕ_A5ىޮKr¢QڰDv656/Nam}Xd;?ƏkV-ݧCH@HΉ`1_^Mwj&;'Zu-GB U']U2Vb_ōQ$h k lL-uW7u?)4me MR2^F ֬wM`7bUδ+Uoِ_خ0\ش(+Ś7[ğ%*&ڿˏ%ͮ\⬀g1d-?!ܨUL8}B\&]2w-7p[QAb Vk\(F]Td.JBw\tENo1:y CTWI @o##BxbKXhtlY|˩Fa/8B#@5n,oO3&7 i&@Sp;yNM J鋖%mq2?eK_,-;EUa6g.3S3Ғ;]?AOso ήu ͨ:^}{ Usbřut?U~-K<[YX;j#iqT5wɟrí 3!;<0V̚X0c)UJ:)QRu.L<0=4A\nna8?_1}< hg9oȢ2LlDƚ2utu9<=qbKGpedG5D5#%nK=Rm^O=^)X6tщj)8( h͛6OOONP.<˛oNcj<"Of=b\Ա)+\aIs;;K>Qn?I8X e\By&~a,Ώ7*`F "CH񷦅f+W%r#N. F0(B[[~ϏS6Au{F}3k0<=WB;uъ?FzRSK`M]#!JW$zғT[, hQ:Hq8.Z0A2i17 kܜdKRh2/u:0M}L}/|.ٯgpi3"?PFffw"xQmo9oo8wϙ˖CR="mKHɬN$`c҇33 #& 6ï&{~X9ƦrZy'iǓI1IY-[+#^=2 ?2 zj#)-Q }<jkNڥl_B6RbZTAuUR]VTt*J\S̍$>jmf(lbu-8Jk[:Q3&e,>Z+PCD.nMjrZ{{_oDg!,/Y9d`|z ?q^Oc3#W`iDD[m`/t;_S?\i1\83~f/kESWH' xa瓓pRCd͝g P…i5.j(ހPy9+ ,R/=#ӦsY$C[sPهB|F$RvohmseIjjI覢dUx\fwS֝K,~P *+qkp٥[!p Nݾ eq o89B˿%Ӟ]`^HRl[ Y9~R4Yzbŷw7[@TMumz8- .ERç,]ߥ6fRmӏ</.!e'0oiuŏ%m'e%<-7 |qVW?Z1Y_D|tLx |(=1;?qgYY%CryTU.E/B Ѭ0ީ[?~غ|WS,$mА2GVCXv P*:O6Jh/n/uΛ¿ih?/kUӅ&/d$oP2#3N%P'oo'N.Bv00&ϓ"F纓+-f<w-_Z97OJ1S79 Yjqb߇VfnbzGdQ/I* ŋ!9;GfwMF ȽũJy;xɒLs3hZקfn(/Qa*MC`gx3 ߲ ׆N`6CiQU+&ςoo }.cq9r8ԉ擬o/b`XG{CU;>^u) ILOf^>.[b:o}>pf?w2?D& 7Q>\.%Twt ~Ҥ J/<Yf]rNR<{r{* csF`#lL67/me߷1ɯ:[ twׇ0x"8A_SUu*NMwt"ZFm,c̵БAydNп4tTK ;RZH]Sإ` 0M`?Ty:91 'p?P+m4;{p YlDȯM ir3KiG~h&/Q80ۂ7(%[jߪksj %$T:[\$3:0vCtWoLnШgr97ͭxJsȕY N2wL]jW̶ MN ~] O?Yr@]sL\qSfwF~a'9sp ,ՓΙ_|-ur89h6 jYU,vqW*1`?{/ Z]VvcB+꟩:a~X%iұKTyk`+b]T!p.V.Vs Ҋ~9z&3z#d>85}^ZWZ5;eH=AIY.Jye|g4+TC_@sZ`1=cl!d18܂&l뽚)3bo:XgwHGw+iljM1oHw( $'JW91x\5*k2)wɦ\BF+EU{p$AzKgReh# RŜbd|gaٟe$BˏrmW*U[E=}H6bðZ!;n$&dx/%@SPK~ʻ1#55 )fIo\tbe:Mg1<""[3k4+C? lyMalx4d\o..lveNlЇOBQu1?_7,/#C!)W^kl~sR.?x5mJB⁝[~lDlkS"5|CYэjG|i5W ޮ/>oV),Բuo7֏Jc>X+ rz{>1ZD Xb-)?GTGP8c֮&Ă endstream endobj 329 0 obj << /Type /FontDescriptor /FontName /YWLPPL+CMR10 /Flags 4 /FontBBox [-40 -250 1009 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 69 /XHeight 431 /CharSet (/E/a/circumflex/e/eight/equal/exclam/five/g/i/l/m/macron/nine/o/one/p/parenleft/parenright/plus/seven/six/three/two/x/zero) /FontFile 328 0 R >> endobj 330 0 obj << /Length1 1527 /Length2 7001 /Length3 0 /Length 8026 /Filter /FlateDecode >> stream xڍvT\- 1H4HHtH03 t R ! !*!J }ufO}5wu a /, $x/ OaF 8_G )(7m I K  I(m p7A^ {/@7169  pہpT'@kt@?Z] @X@tEJ n@/p:*ZtP@/ hr}p @EAD솀  Jde#"Χ١nWw[]0oj RW9Q!!!q s ( F? p@Q@8 @xx?w{` rC ͎A{}B( ~}YYeFf&jF cRTEPZzG-3?:пա0 _k\xY1 c_[ ١;_Yxr2V bOj"a k#P:s` d F9=@wCA083@MlYsA=%pT~@QϒP;/*zx} PGD¨5@P CB(z~ U=Qmy DgQ1nW r@ i? v pEM 7D Y;OTo1n,ÝkΫe?rl_hDTeyTH&[R>_dk~ђzpe?J0?ApO Ps{q f3zGn>wO]_mUbWSF1!%mghYqLx(~NHE# p?Vl~ŌJ}x';-)$4 9Ңyf"\be~2_U_@{jF Ks1S~J)k`չSjQ#bAqB@iNޛ } 1q sq"3K%"lLHw7D0{W[^q *RB͏Ǘ^~GaH*6!aU̟Lȝ@mT7tVD{n/8-ЋKDt<s}رGz5u-iJV"/WdL~?X g^RQ{[D;SaG3Ȥ@ytΩ+^@Փ6ɹ7~<ָ%B~\lN?Mcs>Î)+s2w%Iagx&t Omˊd)SHS*b}7=M 8pt]}ӬGIˆiIdV1+dX%Ч:~%!Ӌ3+"uvLF>œ˞{# wo$/ǑyL gOU0ǶwB$.Ɠ9J{7hR#3X#҂fpTNu]jeO(XR? @`꭯=C!,t^>#*Z䳊к6Hk\G?uhcu:NqgJՐ=m1G dO5MaVߦI}s0q?D?bج &;]ǝiW%~P&["»st*Ūê5k]V썖_,F> %mBRΐZ4Z)@J]?+)$,1ݦn*> Yr. ~C8}ljcpXT9+7yV帤A!Bwh=+p UWXNlg.t?_TCT7Gɧ $~Qܠ,ZҷGybC!_bwVn~2deBڱ q  'ҕVJa!ioH=i< Y~P.5벋2;%N<uG4N۪gidGwHF+)Mچ:R :T +K^/ t[px~N1){nȲ$v%!1Ul%+/}<#hW̘eK)2]ͅ ˬ.Am!8vEsi J"..h"'0CUMˌN|SHˀ!9 דۡBTFؽxHwe[6 ط iHb\ hzߗ8ƒشUܴ{?$,X,a{o)m_\ZV 8ꢌ,fJl.*4;}|y")%Ol'7!DƠ!aqI cYʏa7Z;LSL&w"7: vaiO'#9u(%V0S7RM;Ƈf P1͑P 3zH[Y(Ϧ .l3{]!S/ p(JrN=G`PҦ%IGwX77T˦»n 8Xte6AQ!["=Ń>oj $;P3HCJE,a=_ "D[)KJ}1@U1 r{a{zj 9P9:K4> [NRh_φbE.x!Eg.:2l"[z>vrgIJM( ޞ%_s>Kiq֓v~Q%Ctn{6s)Ыe-|ilӿWx.Mt"Fvƒ>+JPxs<,H 5eY `?J2-y)!md[Rvz$k St.'܎hJA;#cS+`:E>:vVgn|*"0m2{ODr]f6Z]fTWI<=Z PqC"6f$zaaˠ=fp{3/zNI&420$߯vw?o/dYTUP֚6.J_cH.ҝC u`}> qPQa7[M:GŦ*vA65)wA쓬!UxMc50fL,M:GMӥ3ܐٸQ/#CmL"<=LܟM:_E J2} Ǟ9yi{Gx/`1c/pLa=i]F)> 1u7V]㝳8S6t?Mb2H W^zX[KYp"jڃ04)}FGUXrf #TzvqB7g :1 *S`R[G@=k~Nm+Zi4k\07&*ՅRvb}K\9Y7턁_GI{tZjS^)zQԴ (;Y ;Ɍ[-mRohdjU$2gwr1PtSl{EI}YKSh LYi>ʟ{Ψ4d{"pTxiOuvEHL7sIakgu@:mij7Q1v: HtL; ,L֟yT~bw4S_OjYbs*p꣄}jܭQ҃: ڗ;3#?T'60\8젙w^zgUf^#z,.*s9yރKR1En;a%>è{!'NbAVzc׊<>K `9BI|^Dq Qz >TQRSM$!Mu[VU #qlp&t'B(驠yQq39*m87}V8Rr44\v3.ysR#h {ݥX~jKv3ճSeQ:>D_h8n*RЊ9tM儧^-XpP2z,.mNShA 䩑'1ex5;ϦDVU?vD.-0SDOѼw~"TfiSYd]\Tﭪ0;-fVww"\s{>- b|rZ1;Q 'wzUU%`tj/)rNrF'BΪE;F~B)}3tb-< D8|Ȱ/ْKgDns|d Lsxm͂~*tW>&5iڊ*e-P2FmLr,j/u#*#"37s<7S䰁ݽxd!%|TxNmQ ^}pRigO0/G]R69ݵ5[6 ľ"\~%cxe\ɏK&w~j41Oxw>s0|yv6ζMOZt=T0{H #]2z}سKiz=Bk68~4Y[i'ǯB'^pJPlK0O0٣ 1c\X#C(=`0Ci%)ctF yf@^Ϥ|jD;]"Y φf6zw0)¾Fᒜ#;MrI.ҩ_n}gIudz|ܲ˥\ l$ejmUx0]Ky)%˰e%Ԉj;a*]X*wq.b cSQ al\8p%kf1޶UhU8Mu"Ok:c>|䁩Rsmg;ȏX*~vVi irG a=uH鲏 ںXv*Bk%mtͫր͖Ğ2F7 O&‡ENنDxyF~W]BАop'+=WGﰣ^&͚-Z??~M DCU9rcz0)Q/p!2{x2vd<-YT|^ccbmZ8,h\;_ٲDq@VʡI AU,:b& I|1|`WZ&;hhKhlqOwd 38-hⓆy0I%("'nA3or9Be U|N2x tUGuKLV'>]T3Y7edoUy9vH endstream endobj 331 0 obj << /Type /FontDescriptor /FontName /UZEWHU+CMR5 /Flags 4 /FontBBox [-10 -250 1304 750] /Ascent 694 /CapHeight 680 /Descent -194 /ItalicAngle 0 /StemV 89 /XHeight 431 /CharSet (/Gamma/equal/one/parenleft/parenright/plus/three/two/zero) /FontFile 330 0 R >> endobj 332 0 obj << /Length1 1743 /Length2 9528 /Length3 0 /Length 10655 /Filter /FlateDecode >> stream xڍT7N(1&!  JwwJ1`6KTJRJBF$[PBSRJg󜝳}}}8ۣ`*(?X$T6@  p<<(Կ0SxʹQH+, Iť@ $!C ($r;:yr|݁ A!^N0:# 4DA0/&%(+Ax <ep/' ԁ ` 8FNp?`C/Dp( vF<@Cu- |?O_(p HGUB !(?wء ~!h~zݼ<<ᮿ >de" !<S{SV$dzi1 SW a^@Q$. ܁0?FnJ/]p 耦 ;?@O  á^@;# ':9!;> d-{S606Mo/$`!!8!Qߨgm"#P@?(/>ן oza@$ oE֣[KBpW?)Bo6 550{7^f#]>D f:1@<΅ ?zנ.ݩ*zR E9!Q1 @7-崇kvP_U!@oQ @]`oOA":'"Kn_0B!ϿǿM%'$]EIKM }!D'Ey\=)M(^ӿe_ţ{SX .=?Mz{{^2tߢ0 GA=v~RuPzc97G91n*yԾvҙeec)p#/.m 6&^ot13ɭ] `+A-oSFӌ6]5ٰ((3k2Rpp4*;'9m) E+ v!~KGZLNś)G Di q_J^O0=BbV7KRmkVmr17 o{>ӶGz}F8 _!6{o)#&N, E7r ݿ~ `g*N3Ar#x$09jq]BŮ1xLO_*g?oќTkX'08#a]$(dZO]L׮^CmrFx!\{#-đ Ɋ>EֳODL*U֛>5(kU?R~X}^=Rl/mrQ߼d3ʉ΂ ./"|a?>4“4^NWq+cī-S 8 }G]ケ`5   K+_N9WlaZ|`= } {yDzc-]n-R{GwosgGX"Tv'zcR+Bb8M5]YLVfU. Q%=[Z|٬D1m5 MoU;ˌSO9eJW 4g(68|-F5o$ҥd{7V7 2QyrUg^JVg݊ G!ZS]d6V9_`F6Q6Ibw[<SOeVHXDvzXegjq| if:+z*$Bקsr+zi;q݅M0J8_r]QК`:!A㦝 gSWX],uQ $OғMS=Ϲk=Jo ,xZ:L]l-p1'zj<Jdew;^'viaتE>C`vNe _c8*0K$j[`#B2EKU}FZrzmR#pn/j׎,>)K;cĠ-Slw[*6Lfiy*'OEMHcMeFGtSnW>z|r7^$㹆;s 6\Xd}zS ŀj԰G,Bҭ g>DUmB.~ (t#{pYGG^?a9شXS7﵆![w-> Ef l?mS0TCݯ4g![Xq)x !}epYAF3ij,g2L?(_y >jƤ&jpBKc3a0G>ERP񿈝` J'::4P+'D:12U}m`FT_x/Y ,n[+0c3;6W?f4 7)dȮN#~ԠR.f}k!7*7rY'CU#dSPaϞsyg#R'7?Q+]6U=nE)_hF@n%ҁʖ;'+.x'>4 xdM4D WB)<˖Ec Qtd5R{gZoz'.%r'NPQUn')YwRSKOT?VY^`c|L儹\yрSe; QJict܌lWlTN52Bs8td]IXH(}׍ق0پҶW_XyCZP3hr |G&]Jݔ5eP|QIuɍ.7ZXѱdK%%'r3{:\8)jM׻ZsӢ!E_zP_닡qѐk{{&vư}1gޤwj BW͵ؔ_< #Iv-x^5bN*>fm m#xIg][Ud\|]Bض(r@TqKiJ*dhrn&C"F^C͙oS$Ss Sc񔅉F92{Nvbb 3jf*yeOMm9 Rxl:-/^n}cc[_RY g 9MaWԟۍ 9%R_=S1JvJ_ݒWĕ,Few*Sy~[OX`&sݱievjp9Ѓ{ Em1|G&Z(5Lo*&mNmD`8ֳ`?):\97p[ħȾ%qM'v2}{~$`Ax̧4ޣm֌-IgZ5?Pvw=yl6j:M[R Z8<Ľ[SN^ULAGf}n!oMP:|fZaۮQ(S ! 8FA'ދR.ǝx6V? d ,F0൘<ڿm\ W$`KRN2>vxQE\`L](S&{Ndj8I}ۮ=[x(%I n"}7?p6>[/ǃ#{3~ZVEώ#CR倩vՃeC%^j;MЋiAčb娪rcLmͷ@fj%"j^;ضcx\gaS!! I@vC HD:xŹpْg5Βup˸<'PiRMPW2nGhठU F㞟[w6(V娷>~rn,k)=A~ Q;cq!zvi4i_ph@ nD~R^ZGU7kSqߟ)vI1u.mhaYY5FJY; 1C>'󄫩us&}GXVY nsnI6]bL&CjfKk=l,mVagV8w LzY>PmxJڼ%qp UR$e/|Z#'Cq]{dώ[\N[w@f.+v},73,r{[BEl%D,?p'\=yi$vK@\EqMp^!e'܈au>Ggh#Hβ7h-Anv,U8t$,x|\moP|YlДU Z̠Ύ޾O2ymhkta}MDP(6|i±r(64tzHۛt#F#1 jP./҃ST@APcӃ|1xN[PEa=z9Rmmv -zL7RB_t<#8=PlbSޭVNA+PV"ַ"}EYE5ۊGEn p0ʓْØrXvTka-zu=5 nkJTXN9sa+n$(?HF[~ԛ?V`5xlRYnU[3 N)o_}-FDaTN#ghJix[4 }f :>'W|Oٗjy ͵lR wtX730o?N HɅd}"Ywl`/lGw\NR`QrXN#q=kW#rrU zOQXCc>RL6ՖAsPaTfǗB~(7Z$o=XXom~OgiLZ.@m1Sڇ~Ԩj :v$tV*Zg؀,VԈ~O J,4`.\ j>pܮpZRb@QIacw28ƌ;=xID$'i^ f3c8B YET͖hcQvVF˧H|~9LGxOw 0"4ZYFTU%DJӺf`Նc:W]=4SV)Zh1qa:y];\^~~{5XZv 2ոwNO Q̶;XtɥI-Ꙭmde}o}Q{lysk?iw?*P=:ڎяfY܋J>էu)>/i(9~sbcU&!,lЮ>]g Il?Sj3֙_-rH'3F0oD}iA F<^pXKF_.nw;h(?agLvJcC[Ğnl(lTk(֣J\&5J|f8?a$MwG^T}&rwp,L6.u_XKHDCG;t^gN 9ve?4C* :54G?X`51r6/H[9'[;i3Fk_˷fZh\X /s"aK\ uKR=Pu?JiHl&3 7ʴ0(濳^7kDVBnc@}P?@Tk$|^] ݳ^.خ۟'Bt-ݺ|^NjgJl蓙o9#RW& !V@P3+xFFSq27U7ϡrṀwfFe(SRҮ43Cyݯ` IYkz1}P׷k⺒$N;}ۼAAuu,*A82, T'*P?PC~Yv.:q!\A)+q.EYI|;s>vĺ|mIh.*L[JX@YxC.;W'hVz:.YGN!N/KB;&'UJ5Evqý4Cxz&b]UkZMMOfuᡧ0g=͓ѓ_9((ߤV&}2+ՙuKd>)<)z;)h~:6$>YCߪjP}&U\Y"7^blPPB,uR{[?BU47p絫Ob1O-'dG8%`raqPUa 3SN3j̬" .eUq2?dD2#ޜ1õwr<,&CXI` *㏌Bac"]SD^Bp,(ǽl,^CqUsI+ˉ؛D15|wjT$^SY^D)aˣ3 ZEYIrQMѬ+R3JvfoJDowۅw90?O'~)M>|FV38@YVٙWs H^^<ѭ ݟfew/k)RFb0VϬbQU {!y-'dvElZ+sQX ԏ9.tp*3 gYf|ϫFvs1m,7#tLk?~!H@vUyOStx[#Lؔ]yH[]+Wg}EJb/w;ؚ>r`T(g=c/;.d1T5n|z[o4cQOGI1^*Wch>?x\Á!->U y_خCEl7c=ĝ0})vM_b1~JWunqRi >skP ƌ-dVhi1XN({RF(,n4+リsZhԵ$ˆ7isdS>vӛ=;6,p~#At[ ëmGq%fo!1As z>%Hv~ C5&"WK-+C)˝iYN[VWPӫMj-,帡]@S%. ér=xmVb1)Xxxz=I~p YX 7wy~]c*C,5A _8=i8XmXt4MOd˴)M"ؖyf߷}]P@%=ٌ;^`nZqm PklDْs3: ]yU]MaXg6@iDWcճ/A8k ۈ:uY_1s00hIÆlԯvNvڗbb#Cp\(2g Hqr`֥)Z\T~ql"muzErq×0 XcW`d8+v nȆ Optb25ͅ` A^7T kufw{ݳ48#a7$uVʘ4%TalQzOqtd8Fl}o,a,auXmJou/{lΛ;\.δf,j~|?M5槇nh,(V"[áؕ܈@]|2O}ms~l,{5] $;|tAUi}d78 xĔw/ȇg}ꄓ :Zwd?Mxñ]]n9mQlcN L'=ܺum 5> endobj 334 0 obj << /Length1 1545 /Length2 7046 /Length3 0 /Length 8080 /Filter /FlateDecode >> stream xڍx8m۾^j+j՞ !ԞUZԦFZVQ**}q|ߑH~y#BJ({:  Tt-A@(& rs18) G!;b` Qhy 1H.H.vD=]a Er|Nl|~HZZp+#`[FQ8|N]///a+Z(8h'2@ CM`Ge0F0^`w( ( @:@cM_+ݟ_`Fc1`/G0ƃ=p{`!ewàp/"`Y 頂ru"1h_SC!s\$ G:~pp1Ez@5U`!cP @(-!!@'_L|ܠa,?7 àR?4 {@)pC0{#IX k;`z0o-1U5C_Fee7OHT $-@ 8 yuv50@/e~?+衰z-@q ?e_;R@ ~r`W8Vl袰oWs_ u{UΈs!ap8Z u0c Nif`k H u`aG₽[ؖ6AϺjHK`R+q;P#Ql1Cj$ %"`D;E@auo@ Fz 0p7vDPߗ-F;kAñ 0xc/ߒ7 ͠ 2aίZϪX>.-G'XDcx?s!ʼ7P%S҈o4r18j=Byߏ:BP̎OW$QY[&\KvmT\7K\E'Ti,'J9;-91hܭ=L4MG/qN[cZe ,,y*vU%2W#g0>1[5GYD455gNrd~oKbGJuGC (CV۵,"䌍INr)sW9 Cv3k?ԝDZ7= Yc<{NCH}z,a`w_Ȧhi 48=o^nq3yu3ŵF?`іӽZSdL@MSa?ho~O澢ge { t=˻JAT.lCBR>\S5܍Yn&@DF;]Na'bSr"@rf1W4Жу\ؓq6Z(FGDtLھbkǚfl7u[~>ΰBDyCxB/}U/Xؽsp du*sg-f^ۏʪJpi՗A<~dQfߤhc!3Ha'XBA{!NJqc u=.V>_)^aOD,%(:jlX?dQ m"T|Ho?=oavs)j+teS)J#Տt{ՃɿE~vrnw(S-h/)~Oj:O:ԸFNJvE/G#*gր|aiT l1[wgfm)B"Ź&Шbݺ5bj ^]?ǡy=ߌl12C_<nai'>_0,Y~$_BT0I0W*|"S1o8vE<@j}9g7I6LJvGa8˿7f7#4RI-6Tu"eT0MBP<3-ˤ-ruნzH`505Ьi-ZDv=ƏZ5eoSH]4z1!3qv/WiqrL'r @{ɊzI6b&k`fâ&}: 7E8I=$#GG-1jUDzk~+ʩ3ozrТ0^#ŕj۾JEkTr Y!o(5;.r7gLI% PjoNePH?ij ===29b5OCkj)DjktOX[LA`#e6c< hR% e9&/3kF[9OKiE{s'f)]B#nuJCp8qmp/0}0_ fZo*L&;!ӝ$Gyvm J'l 8 NI&6K)ѻ9.BCP&ì~̴{`f]e{OE;PűY6,d`kuݟmSmqjf7 x+>w55ap `xu0sw'QnELFT㣆oDsX f]#R%Ҙ^g֌bK (j,iB-CûO]-n*Ԧm~"Z2㛟*]\ĎPn!]CQvK0~n?9~&G )jWsxI;E^1`f.4s*u[z$ȊvrsAyJ7ĦoT5M]WR ц.[vg0BPؕZWcmÜN0hkw(/b7)-GVGվ[fmTZKizۆA׌h\Y{Gt CEv/HF3 $qI~.57 dz4kQ)vƟc|-TTH[@yɷt/#HI ,Qh|9ܲQ\ZE>(n4? 'wqظiCӋ 3]LqkHݔnW~+\.*N"m,KZUYV@-A`~({9W JAa6vSYI i{4(VbHաnv@Z-!Y|A-idGgkYJ%4m_ R\z8~(= alTic"8=cܓ+qJܽ*q᭧'OnwzV=*4r}(uɍ)9Ɨoa7l+&"6jS{KilSt}Bނk*'焙3)Ӊ>gz’/(+F%MHg ?-!O 3yJly/ 8+5V;UVά Xw%v= cZΠ7[pbdppY٩?ΫZT~=;yvaXVX9Z ٳE<%c؆r`Ŵ/jK_0ڬO _psc>[aAQ Oe-VƜF=:-ŜU#b9ݭD|NL GaR񞮨~Z̀E{$"Bu²*I,K=!;d8IJEU~ۗXW#ָ[W|R\Ңgdc9Dq9zTܡ!&:Enuξ^H“{ڳN5lTL|'`$$i)`@3Z \vF$!DJWD]`#س@C@~ٺb 㟔Zk$CGy3!*bE LfItmB.IA@k4.މZehܸE$71AAy`{G6m%<oYOQѵǧ:;y< %=_m;GOe^{snʜ4NMl.Ҳ^~_1u! 8'3(N}o2XZ+XA] 6ɘZStHfLid"X{+TC\Ocy;b.+[yMWEy8tu @u4u/zĺwȜ1\69ʕB8E#c(=Y[W!ݭodnR? |; Q8 Xq];1gtV16ۤ"0 >3nC5";9"'[JZreÞS"!@/^Ń>h2C:hoUĤ&@z)EU\ ?K时ZTg+bȦ5-~^=Uz}~V Fݍ:_2X Vph/E r|JXSq㔻A gCM ƐcG3@\얔׸T)qC%MROī+Q)J*:G ^$ڋxq%G7Sy>9_eb!ōԔR9aO{a"}[W&e/7GX"?JxJXRPf'bz sTe vZm>ډbT [bmIF{٤q|8@g$Uh4>TeZҮ_O_|AԚybՆz&s)tiAd}%K<S_R?ym?]L< XFW F !M3TF%u6woF{);%^_dq/Cd4դkL?P{Ovp;ͽE"b'stD@4t-xSͨlqM'hi4IL{]|[ (W\@/'b#naZmzty1a jDWfr7PtBZ>Ow'MDAQ%sRv7?տ6xG@G0Rnsqvv6~w[nG&Œ1m%qzLHPL25-\?4l z1w*c0*bxߗ]4FQΌT W|#8u~[>%+*&s-ӜJ˒{[OMܔ\rt 53JJ#xR2vlf?}>v! |yQ6 04~A`:bqQ''{ I<#{Ô -U,|`^nYvPSQ*߲bOYWq>Bm΂znVf>9#ݺtC,jݦ8yYg[I@Veޫ5}WhL{'QzA]⇂Ns>t"c'M.BvcR/ap,J/݋L/OP箯ݜgS$kxO0fMDYAF{"Ӂ )8e )pYbXY[(;X Eܮ\@&~V.8'79TY1+l">=(\8|+$d<UP7vb^{]QpcY{QY{W94s6O݂WGW}、49 _(ez?@q۵0NnU2x&On)LP;Cm/i浶 3 TGsea ]%̑f NVg|))J=MM'{ERl{+"xq-iqk %uʺrqNF@y-3J&{UyVMF84/;ACU:g ! W9ƃO ܪi%RP"ZśyI݇  r9K#_ܔ9āU6Nv9P ze@oMm~{`N\wdW|Ss-]hjϼq!c֐RCa ;`st`yJRt39~Ĝ[l,)r#FSSqoI[JJSwȐVcQU"IGciy.&Y.zxgIAky&|C9-<xI)BؗSM9}b|Sp*ls;/t$$^mR2Y tV2Z<~+}.FDYأ̓RƔ$oA무#Fy+JŴ:c DsP'?坚f myi)rFKUKCb%)u(=*|C2OznUR-b-S" w.#=(ޔL1L - Uq~[}u˶ӽ@ ~t5%1>\;}k96 l endstream endobj 335 0 obj << /Type /FontDescriptor /FontName /UFMTYJ+CMSY10 /Flags 4 /FontBBox [-29 -960 1116 775] /Ascent 750 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 40 /XHeight 431 /CharSet (/F/bar/braceleft/braceright/minus/multiply/negationslash/similar) /FontFile 334 0 R >> endobj 336 0 obj << /Length1 1413 /Length2 6232 /Length3 0 /Length 7198 /Filter /FlateDecode >> stream xڍvT6H HI )!] JI " H7)!)- %J(<=;g}}'>< BI@QSD@ ' &4#PHD!'@@@ADD$@M0pp*\vh옿6<w9 wC@&mwN:(Rh$?'FOЃ<0a@ L #([' `' 鎭 ap7;W]?@_g_P @'8F{A urGaP!6Ρ.vG8 0E3v'?%{nDE aH0.W \M,DfG" QQaQ l7v }]P.-a ~C= ߁H aa@@XX?Ձ"䟆jH[ *r  Z(?7@lo]./T0NNܿGp+d  MN5q&8wT źCiU80"G 0 'rGz` aMg}c/wԿ*#mP_nnPoVc""֥0oy`$ -[ɯkHqsF~ĸ5oU`p/ $nCUhI<'Յ8p4Taꨫ5FsG&x y'D(w-+z~b{LBamov;h"LChluSm;dKfB?hپeƱ31f1P{0J"X){,&on7Azghcjl = ߺp))&bu~5g-6>#R &ża$W%5ծ_h ="ndH' Uк/)P,29I.܍d T؇UP4T̴}|3}8Ynu{Ke#y8x>zF=3i~ÎY[+CVtH1>52 P'M涳2 2[ér7HHE] >\\9FKag  &})ߜ3Ϧ+ r[h.%mv&(׫a_u /k,w8.˝N~S#[Lֿ ϯ2}nC뾼hPwqbinQeLSb2ijlRTpl=4(FbSn?y-A]PsXL 9U%e:[ s%%?aaf2v0#?UNhRW$RH'Y#]Q`1,?_s;/Hk/Q!)!\gz?UVԹDZftO j?й<xSRx\*EZ>G_y0TW՛z.u͔c>4-#t!u=-aIgV7u/.iƏj gGZbB.&K/SӖ ]5!2'U*| ~/<Է͒yy+oMJWjm' h-6 ~BgWa@#-BrWko/OK':Xu.|LvԑզS,B@Sk$J"Y[;}(πq/$J RR.|eN _Mk)DAuX=2~uF ߙZ%hPWR_go*;(Wt_/0@wձIoyEeE!jÿxEε,ժޓK|}tviBf{2k3G_ei4hhLQ0\:2Vr.ވ?d$dC!7%_J)]kwD&Ռί=cn[C -܏$D2M?ƃoU+Wyt*XiX2Rѓm-aj_[|JFfqdg{ѧAB<զzzT .R&:u%^Ɋd1HŲ"q{yǿ h l% O7"D?Dt&>$Z꨽ q nhzdښlG9,93;h{Fv\9L7gZȡqfᖺVaٳ V+ݦ#tv c$dɏA6>|=^̣;UHL&ƫ֟ZNZ2)Zmi^~ZD*уm}W4I}-+ ?Pf;I]a偸 jKX3.=:R?Q%0Hzn!-кyJMβ ZZ,ή e]l˒U#Z Sy޿J}u3U)eO{XJ0ply-MG]ܺh1Aoϸi:{'{B޾t|U<|wgTV͜.)nm›` 3/`,["Ok\ S~R _Z?)4ޙ+TJ}A5s# <"*A}@LF#aS+>3gLt.9F~ TmR!b)Ԙ6쨾_|GK޲KWgά}м.g Lk $ f#vdwgk8[Zkl&ɭ! xxfrg$$f95U$"H7u2ch|4IEZܝYmn,ݺzL9Px c z*nD<8LFxDzGeKjʗ%+}=27'dFJ4M ]U ;T=rT.n^Gf Iy񋒒yt͐;89̎mgM{Tχ_nɄ~qbYF|WiMg`t vU܊1`tfj̈z'H l5BŇbUwR;=ED5#xNcXPƽx<2V/-pȌJ~fF^6:DcR*EI&"8Ϡ׽XUyIWK=VnIIV a1衮z*ʠj"R" Zׂhf-k">wE=E0?HbduKNۆUqJOm v*7˓Q[/ZTZCFFWnk4sY7`V8כ31?" JE2LW|40X,Q݃ʏKCT1[87и$ @"{zÈBx@6Cs!^}*TDU${;uYbޱsy(['@T'q}vaRϵ{̮]W7b^Y5YCgפ(~/XV:'a3 uo% mnO2E@'4׌3yMASԯWvY|q sP[UPeo~zVEg`/H;A Ƭ XJv|~~ʃɌ߈`v5[}@E:vJ iRKkN\4:KyuQgHN,}&tƒ,^,cbB\>0G+? dD1B['Eo/شJNȗZ5dj4q'x]5/xsjOŴXxC7%:ë;;.̕i*?ak9֊'=#=Krxbm!ō$c>NE4xƄBg/g.(ߟW;hT[o;>/yG;h)+Y k4AR٢ٕJٛg\`;G52a⥐M/r;Wj׽r>1He3)nbr)m̉?Op߃߿tI+'; xZ{q*k3U zI;]6^t8tE'#@p7ڕXlb,'xo=Mo~h 'b,)}~7m^rdN7wFW<սѬ i٪~=IQQXi⹱GEflog{w%`$mv 2Dl5vgy®Cm]˧决d~NK=4^П}Q|-pt@%DClaq\ڼ~:28ʇCݬѸxQ4ˀx4sW:}ihА|ۨW܎)?=ư ՈM7Ic:{܉U!lf]@YmkobZU~C>ժ.9͗iQܣi42-u'ʠymU+iFa}`=! $mAh1BbJOsm ='IPqjNK^:Lzf590?KaI[{:U_*]ޘ:z7[)M+EӬ7;;M$Xj`PibIܵ7&o|'avI{)`Z 5AU43*'Yv9RDCÇm!E<`%ƗO:@yB5beW_?&0*rk_q8/ckjHyќ\ '@ 3BAI['D== zPj;jcs'd/&7Ȓ}ü%w P|ipt=)e-giA#Fm_eE^bn3/K?PQ7aro<_nl= rJ.}G! endstream endobj 337 0 obj << /Type /FontDescriptor /FontName /XMIFGE+CMSY5 /Flags 4 /FontBBox [21 -944 1448 791] /Ascent 750 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 56 /XHeight 431 /CharSet (/infinity/minus) /FontFile 336 0 R >> endobj 338 0 obj << /Length1 1570 /Length2 7305 /Length3 0 /Length 8364 /Filter /FlateDecode >> stream xڍtTo6]²4HHH .KKw7)Rtt7twK W};{γs53\s2kpK#̠ 8+U1п`V= _YG(HO8@HX+7(<D*wwYZ!Qi~C8 QQGvPG VP;TFH.nDڋ<`;'$#+ iІ:A]_*!`Z: + @0pCe5=Wo ? @v`; n B jrQP% @P7Wx]w{o#a@Y@QN`( ߆"0` QwxQxy{9n/|Z:Zj\*&#pxrܢ xgwQM0QnռpK ?3AA'Py$`p$5V~~p3,BP9٠c:j ` Z>jt|(-Pg`FQ / 8"a pkovw/?ZqvtDbQ}A!&AAetܫ8MaH7Vji2/K5BF&8݌[2璔h29=-PFspr2~ýFXF_?,ʿ^wn(  fNCFKg5mcD0,"{ cHRu ]cDbdh.ܗbR{gg3:;ު}* !!PaPuBc![{&.mӮbDONk(;jSjhcgUbnn- +al55+VO& m X2#tv[e#>ոXXoIo `*1֙Q F}:^3yEJJ-{Pm2Mp{B @K<C4uEuK%6".٢ٴ}ּY0Io&~ J`(27&G to2|@ܐ|tOa{8,0>TI̯ Υxn}T)k}Rp,g~$/ωw0G7ʜSo ٷsI*.,;N˜td/luce2}18 *tz8z*Ot)R_0[O3XaT-a O%i}(ɋ }!#3rj8<[3}"Ԩ钋}gN&Gϔ7YCBLީ}3|̷?_ 3Sl.eRڍcϖЛAnOwemO'A\MByc\@\ u,sRo'IX/?zE $-&C{OPDR^~ [MXxxIE!FsfpQF87'`E ,>eƫː>&;uJ%'%, _zz}A.K~#ZKsBp^T* O lp=&%>< '9iwT!eD]>a+ lV {7y80=Հ)XVT)7C>K6̈X+!nn}]N \yAa47&^0)M.W<.Kꦸ.S(jH*/%s4a23AS?cfϦY@'zϬ1˕>,<؆% -P6a KS~^&䃵4~}~f8AM69hS-Rc0Pd=4:׆c}kX]Z"!m ymX&[G?qU,琦Ӻ~KRmw7/ :#+8<̜/鷸B~BD+/z~b$nhdzM"!d$UyZsCb"xX1!@[w^^?ɛHqbm8h=1~ُqYл [tYj;֌ܕm͒/?o!}'ly݃X:d懍.Tz{oi o3PYbE"Ӿmj:v'D w+^DmZ%5;u}T|$H-.]=ݜ倷ƁԎsJo^Q6AIَ7HökYar ~Ǒ}?=Y֢DfIMlЪ$å0^q VE-b) >{zs.'xP^ LEd"t$46MQ$iݚ=5U 'Iuà*KLJ5@2ḃs XUO{BvLw ,1Chu@߷G>~krVApq F./8P{*'¦ M:=먬ߵ?%,zM8Bf3.2XrK_ypC͒~Ƶ1_ec& %cxwԲW &/U& VK_"SXRD"|,L)D~\z:[M -y52̮,JZXD:.#nk k",u=G}^ g\Ȏ4>oXPTW_kļ:9C@㇂ _N?~#'lVy6?qX]Ǫu1%"-7}Z9]|>^+_}k 告| |/9wD!2۬Sr_l2QLM?\"*WѴ5d)`wJ^rWJ(9Ōyh2Bw39jåA]6|6H_Lr=Jԡ{v@V{ݦ [2¤=cwSN/7KXqj^Sc8FMTw] Ե6^ꂡ,W]/]! 3;[DOtGV۶Viukj[M(2S{MJo`l>?l8m$M)AFLe[[SI-ssA.GLۄ k+;g܄VSwI8S)ϟ6%ܔeXj0!R]BJG׷~êKrwK?/r/?klc%1| sO6$''v w&^}񍝌f@*) fLS+"WSS;/_,fH}ip||Z`6^br杛N_ՙP.SE$ﴂ$J@f{?2!j꙳>t:Dj[tljVf3g.XS޽|-d#OwYiO4wj M$Ls>Դ^k\yIxYNՔ̊XfU*gH<{v6{ gImcv Dx*gyaJ E9]L@"~Ce:5'd3aM(ite6V+iVWthNXSf-FwΊV :;/F9/0kc8 %ZHkeG c$2_l.qڝ3F\eu|0Ou:D]B56mgJiAÆfxW_Vt6 Q߈`ls+?k>l+>85C@, H ;nlXB-pek}dԦ\?3M'RR("[] =+gT") p=㻴) ^-s9+&y8qbm ͛Cͨ=R8#% `ǽ@҂'頋8Hk)u{ .XCky\s:7}"{?9^2촿_GoowYq:~ e彤s|zͧs|'7 {gc= +$vTa =%cM-5D}BtQL7*-AdYyYfppK*y'?NxS5@ǝ@2Q{cB EKv jnnW?bO^NX_>oiy\XؼPdxB6o:8xnC%(at+r8)NoɄ4:г 1iKقwsFTN@1vv9[/cm1ۋ*|F= S~P # 9_յ2]R֑f1U+ޣ3j9=U3S 7ʾrM<+:Q}Pچޭp mtUDjgwY ܍F>K?z½]}-He)磾|CV|4L4X$ʯyq_]H ڄVDMkF]2Aln/]d4jQkZ|h5`S(|l Ԩ41hC\BfVOX{x\ՌH*=C]MOϝt[ Lt'|TA_K8kf=1B bo&}cdTS dC˟!H?OtijLyĀfKӻؐ$Ӿ-&\ y K3z2f /b0.&F f&?;\˿^Iy6h^奻8VQb.;h6]Џc;L`Fqo_:*zAY)ald{}/wD.UC=X&>Q^֗?\ֹcOsӸ_400#&-U$Ah1^-,rc#bv6dkk_K2pњս6 |c> дzǾ-Au)ܟ^+fdaIʼkKiFU7?Fw#k1UC俿l:+)Rks?'e3 30lkCIdz?ؽ7m+(Um</)bd.eL4!a5sת:6K:P v]LO.#*]paY,`>x1;3?QI šwF^&nA\N4/Ɠ00)3YV4< endstream endobj 339 0 obj << /Type /FontDescriptor /FontName /QIYSQL+CMSY7 /Flags 4 /FontBBox [-15 -951 1251 782] /Ascent 750 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 49 /XHeight 431 /CharSet (/arrowright/asteriskmath/element/infinity/lessequal/minus/multiply/negationslash/radical) /FontFile 338 0 R >> endobj 340 0 obj << /Length1 1606 /Length2 4643 /Length3 0 /Length 5427 /Filter /FlateDecode >> stream xڭVgTF"R^HUTE)!  &A:THE"EЫ4)J"U^/8w5w~dwggel* #0hXT\0Dػ 0h}5 RT||XĠ5x<` !u'M, 9M=O␎h@a\]h<>h@x'D!u#ۺڀ9@#P`fB}$ !,`4yNC!<`Ӑ0 q87X(O 0E!fcD0c axXXCwx'(6I b&s;mWCH4#<sEA=`X/n8$OQC>Ο}=4Wֿ9 8A ,A k;"Tbv`p7?b 5" (Fyp!O, w*s"##oU}+ eu!. @|a0>p\ 7MD@tPTюD)Ew"qZH9PqFh8BD-%f愄9O.{9Q_nY 5eLToJ$> 0jjKDHҲ`@V7~ x,ClYa[b4 sbzĆ8၀Q}K"$_dvkijm v/7K +;. Y9cNOpu>s1|M>Me&6Ϗ){k {yܳyw]i}aeQL$ sW-^mhkm o"Eɧe_{aa?ehgB1 ^ 4K\(b@PDr"hBuE7YMsq3ґFY]%gKGl0CLi>[~X=yޤ^z~ NN獠F6jr\hVHoo(.˷Raw3>_ts<%o3bp1]Sdo[}!k&Iv+mN.c^k|M+Nw rTxF@kEKjlB#G4f"?ta1utv;8LRۨ{BU9̎[^s`aб`:,+?.dD5; %J`Y5"$*ޚB^^GZ Yoc_   Hk&owAy-k9LzX1nC !9'h#fcv[%DsuUgXUΎݽ wRyɌ}\~{F*} ozVRntIA@!ڜD68'=+ ).muJ%Oi}#K+̆^Mc@3M4nX@h"Qj ;h x*YMV 6J֗Bɜ\I{;iE*}ٳgDKPPq&[vr3j{3F7w20ӊ=8snEqǩ]sJc>[i+T0Gyg?ǫCH nD$'**i W~a449Ta}G"g9+?RL3N]܃Ć84$U1zS ɨˤ Odӊ'$Xk0ZW)7u4XLko:l@.Z5ޗnl, h_>̌մK~ןObVN%s[ 3/7$n3z{BeT,}-&&j>oQڪ+@y LaiIG^T8k٭ぜt'd~IM>Ng2L6;4 =#)+f=h(s(Qx9و3K;niRqٰ@ӭK-HʼssY/[T+m]2hyl,(!xdH5,|5Yz4y#7˞n|x09c7MwJxa }&re}|3"oe{>`a$w]~|*X7 >"Y\pv՝6 }Z_ʀt%@^t ;S][8(Ȍ"$^17.+hft3(  U!5W)oɕmyruNJ'x~K M0OQ({( 5 IFSHlY_8f3&,R~(CrTZfpxI-^dԚyvǙH`.0!wTPP 3jswS,l)t6KR~YjwK[:eE_'?,h^EW$HH%ֶE#ԓ"֝);|d !|;!Ad~"T7#i;7WԓL{*"FBȸ!2<7#thT _|>w?c&TqAah}>Svo|#tzɄH;WԶ:h5vc86|Y-ښ21s %p -X!{1ܹv2|ewugj\? 0V!K񢔏7/Q/WLJYg]B} L2.2]eL0FSh1#2k^8 AGXn>o\cVѵ Zɳ'Mн͖|k-T"!HÑzgJ*xĥrt3'%IHf 5L*G{c)͹xo9b75B)&:JHY=Eg.{z_jØqTx+@b|k`GR8ƢBoPݛ#h*^MKZƞ~U\0t^]i'w9mC@7C`}jsQϛIN ]n 8PNܦVDzZbxowT%ɫ BQFiq[í#\jXPRLBgA Em=G_̑h%ҁX"2W]^gfY]ϓ3ߐpe3zTHKöNU%n~su8"`I;(*h4v٦tGWvĭU fưj99bZ. :dnb \ '9jdN.#ύu^uS4""A%j$^c_`]c!}SpTF'^izWXxʳO+H]ئ]*;Z^:*uSs3بax$“Ht1m?TN\u~ \y:.4XqBv 4@~KGPIza5xeF KjP̲=eK]3 pB̷ڛErYdjfg諧9oY} M_ 3lrzHqz0LuXePֱѝVd$ĉw1\[RH넙 _w|.ullFC*8x( ^s @ڮϋRDŽw}mQM !gz҃NܢjӞ`|N}Kǧ֟zX4 ZXceRIc;} K2)AdP'?P~},oH|VpO}ǸٸKl\tEIdf6|#n=[|>h<:ҜԊ^ёlYVv>!(2-;,zqJQ]G$ՒcoA&xR%喑'eѡi]/o>E9NLE4 KG0\*7c#bkdf&,ƣ!nb*Y:TNln~s&hd?1|u_\hQ|3kcXrRN?aHr'M>X ltHeyC +Âοb' :&W "y\,aa<"nH?Aך I1p9Yܼ_}w+M&!h.Z endstream endobj 341 0 obj << /Type /FontDescriptor /FontName /XJNOWL+NimbusMonL-Bold /Flags 4 /FontBBox [-43 -278 681 871] /Ascent 623 /CapHeight 552 /Descent -126 /ItalicAngle 0 /StemV 101 /XHeight 439 /CharSet (/m/s) /FontFile 340 0 R >> endobj 342 0 obj << /Length1 1612 /Length2 17302 /Length3 0 /Length 18145 /Filter /FlateDecode >> stream xڬcx]-IXݱqǶVl۶m۶m8}g?|?gUQjԜkJBƶ@1['zf&nO[zE3௑ \hdnk#j@#  bk`njRQT/?!C@hekg q Q 8&V@8J\V :X ̍2F@G 5`b 9 v@#ۀnF@\t;w#ol6FVk7!;ۿ}mʋ?&#m)_0N6'? csG;+918M abӝUo`ggݶ_̝V& p,s9mjnϠHژm7v>ÿDP%a`lkc01:M SO[ovs5;`o[ ;n`mnjt2 !ӿ010h(f47w22XԿ*6@+s_EL=3̍,mi=ۿ]@$WQgTQIw꿢jn(姭Z!,l{YX9r23{ ? ZKfbW15gV l26rvpN߂_Wlx,2ӝrGDGJ jl{}*?jf?ݗIaZQI P):9huK/Ԣf:Y`nH] 0Ȟ|Rbu4_P$=?Q A’`$'9;<4}Bp(T3\$Ey9h 5{BpX`+ 9+b5S 41Mna`٨Z0tv !`ZMطcʎ"4D uHq_:wD[m¸eݗqd58r0?M7zQ/1VKǽo<8oG#t: s"iɖi)_]-zq> d9z ߳籅i7"-vH=i+ot *0NV2.r ]I#}ƼIFWWKB׉[B7',k1Cb%c*GW|]@سsMfx3<\ imz}Z{e)(S>xTf'U쑄rEC>{F ) B:v>uk?QZB*M,͢H 4t``iu?k?|-> "2LJOk?¨hi`e0XyMCajVUʢhXyV}(+pն[uOF"Xl,OpāB8s|>2`j;Ii+%wK:dU10}㨢=ȨXzlSh zjmvfyo:_AO>xʳS*7P ‰Kj$9B2Jj:$&͊QQsBB=mL4#P* ^P.z^ؽxZ?cB=}ٸd?Va=툈-a3hTE-tMvN+ &HS1T8dkZfGQS`3׏P? V\Tjq#Tr.='c6 ڭA~1{| SNȺU,\ }؂#"[`Ҏ:d옦Tk"Z].E/$+A~^Z$(yD3?()@lxhnֽfU|_gm6xJx)D?6c3ޞ^-[xub-+^ Fʹ1Cr΋0K R'-r))c>R]JfP˿ SbgҺiIsK:gCRHK[S+,HB@8{aM]4D$ B3!g_ ˍ,a u._a2 Ax|T;w#"s&# Lhڃ pe4Hφ\"N@B+~y0Zr$v2dqKH`f4ǮEs''ZT2Z1ӝCɟRl.`xYP!"]Yyusع-wC?$spKK!7M `o4Lnb$QЫ vIndlw} 2: |SL9M8* 0t3G} X!lJlau[!`~JWo.wYXHTOcCH0M眸>B*mP2i1,=`Rx;ѳ ,"sJ͟ $Fomƌ>.$83?T̵Γ Ocf #&uK_“7<6"g¼ 䕼&ĩٵ/+_s2vIAi[ ,]Ƽ %,A rӶ nC E^C!y]X$[MmG;YwgmuhYh ۿ6Wi hhx<%ІYb^*EclA #b &-/ MjK<UB,@ek7#uXX, ݯ^6%7:E+}R3LP>-[IbJ^9˨=$q:;')<ʋm*NL)6G &– kɊP cԛXu}eFcorׯ3y*+*PzMմg̓ЫVf`B>w/CO >-Q*+A})~ůݗ!)J.t\ l7@bB"* X\AKڌLk(v! f5ro.J?ײ[D*ӣ:VfQi@ D %/a]N 0z` @D2JQ /%sB7.Z)qS.ۏ7P3g^Qr:&aLf `M;ky>lc?=F X= q9B <ң !~t&Tn8EԗO9~Žy0XPǩ fgX5tU`4V_/<\fOX :a( $:=l1B^%smrVg`=56V6|fN|ALgV[TMQޑ"[*Z* ^a A,nMc,̮aP\CgHb~*#vp'+W>OSz ݸV2ECarEEwC b0sŢp%ds,FJWos Y /@/ڞRMYAK^$KX";MZcYaKom{d+WS檰&s6ⴙgmiOD~,89bEX=fBp]-x|St):a;7CtNHܣ.^mmPLdJǦw=hx#yݺ3D,+I'hutwCp?HeʽeIݙ>@ֈ%:4.R!Lfe1WVy Sr:5n=`廃l~ зqR 1V]kx*S廖oAo]Wg} FOǫlRoDIrLfe lsJ-# BC*.?Kw_@@_( x"aJ竰psԏRB~y,x?5j<6V4Ÿs7M>wl.q]W4:#ȝ}DAܙ>-dռ,ڮ$qQqR |w>z($2Î?B*~d{'IJg|Ó]5j(x E/F(KȂT蟢Sb#52(Ln:*jXXǝP}ma*A<67Z2(uDp/wuEYt01K-*̦?*W1EK;JANÃ&ס "pWh{>G!9ؼ=(Ildž4!e^կ-QGj[gZMϘzS~hy U^%RRgԿ{fE 7cFm#2NYuD_ &KX^8"bnnŒ2]z @ĭL5 3Ee(dE7TR101y=W MFfSTEЧh:*O؝&^{?x6]ۭOhEA]酌ǡɬyHT-<;o5}/jstt( Y[ˠS\ "{f]%EI&\ N7cNLwC `~&Xg~{,6CIK K TQ8" V&2QlJY"4eF ȥ5^8(GZAc>exĬ; %9e?Eݘ|';8uNIv13yQ*IxPjoM~5]{}KY 4Ȟ{ቖt=kDZž\Ajhyl4)i]XJ6_+vymd<)jI=N0;kv0tbMxG-[OSN7[E06\[J'|`7ErުeF+OaPT6N*ub?Z*c&ZZ5^w&vdCA-\p!zXb5)p%d{D8+PghВqVtn`Y՟uy[;1AU.<訍&U2?~CAC ;n-XxZi2wz H5 mSyLҼ:_J뱑Z7G̒ <EJ)~ouHt^!!@NP. ?MZ:_ |H#6)\]ZHج8)<1||P_}8FA45PF:F2  ;5nG]kr8 :R/wǸUWs%f6r^+E'>m[;FVǎY'ZdLgDx0ؖ4CVd r޸[z(\lFFJ2h :&wě(X K&Cm Ί%k;cׂd\p_5YtD-%|Mxcڊ"M-_۶:|.->[ՆLFp6^$o;lx~_$0N~fjcF$1,c)rP*bW3FTُ' NKǨf4}(Haq v]2S{/>{d(rjܔ~9\7SG@*2% %%{E%Lmg ϋ2vWq@#UNnR43ʺtX3!#L03zEwQ9^dt`!A'桴g0 1++ ZLF37 ߋjы·pA[o[319$ H r~Zfe&TOuٗoEe@0Ŋ{:{*?Ň`Έ[5mQ-VO_ }HO{F¬uh[vFD< >{/M^,h/Z_ڷnu]x)j<9H@n ~J7 J~^Wº2gFzqil'+wmŘC~'^~nWVq[10RWVO >QӧzL(W )\LugN4A8Knc5%镬{ib- y]>b'Ht'~Ef$qԑ2[‡razj)2m\ #đN/-ڹ<3h Ɵ<֎?;5p n>eb6Г!wFR#CWcKseIW{@G10(=" mS_obzT%")} ?pW=RQ -k*k`F7D|l ,˒V4Mw2Q4(qUQA;b`l:~gofk4-'R3>Ic)-[?qG4zC_H^D wM'q[.ÿ\6?z \D/ce,۠p^ѡjsɡ%UƬ%-oӱ녔n:eӇyf ĿN'Bt Wg-{6rL_8C2kq_`>>CiRuV$Hwz`Gk糹ԼKUbn fCY~߼iuJ3=L/}"1\󫀜~@6C+k,,_ܩr-:]EqX!سQl δc9_>!$N,kYݺ}AGwn RN; rrTK+ W9qTƺC+H2hU+7|Ss}|KE EUa^[0 A1`2bߦZ03ODGC& DmI^p{35 R0Il}[rm_5M*YfBvEn$eVB};l14Ud{61MK2I <|,q̈́09="+b]*fcl*r%|,+k-8 &-M(_>^kx# // {6=F AF #UhhWpIdejyٸBeWlIv,2wn F LR_ =~Pf\lb i#3rpW2{WvtO9/O{-Ev؁ c|U]rr0MDC]G{V t% oqJ04,n#:jᇓŝ8ͻp|[_P${߬C">ࣉdzK.蒇8aХ]S†ʭicuq'Or%WNv+i*LOeI(#=Sx"1Tw){'46| gOLӪI<E)!&]|rA4m*Qzo7q;#tval?LYqX X4H+$]\m3q_~mKub[>s?&52!Q^,AC&a8ǐF5V)ݡ.8I:wT~e#iawL>}v_+ϊhfo2dڏc=C)OuTF:ZnRۘ~kD9qHV&?>i{(d֒m7J)Ϧe Z%(p'ɭ榖AXf[smʸzk^ƪ~@P]kaId'd#LkKgcȀ:"q L3:T8Aen!匸1 oEb;j-03G)z禎 ؀BҼM3硭5 D⃄urQO~_v0A޾mOv%Ek#*ECgxEݒPp ⑮ל-p.%Got܆[0=WZa:y~ĕĀ5yRt`dCGˤûÉJkŗ j,:W*R?zdq&5A }:d )bkUBD~!g,J%0i%:F6 X30glq>ޑ+iRN}Q-dӳqM-x6s}|`(y4Pvoc( V^\TKL=:( YC];' 1jΊKGGRlB5{~Cqlqs5yv2N'UG =݉/,N\YvXcIc9V]O D9Keʜj*lsL RAgΆ m^k2YV9ғLx4? V=V ̤PC.dpQp%BmvR!:00+WS< /Dp8ZV Xk-,G $8CҠE%fƜWdeQ)F"t]BX?dI|jOL/mgI3lL9V0(.mۙ&C17\``Ab/ k5ݽ!mỆ&#>#?w<)jf'1 5JkvDD-JnI:\%莎~ׁ*ྈ5רoH9xY}BͿ`Gv@ mԟq}Kn:LTrSpɑOr]!]=:HedЈҳ%a6>x9)Jz''!WϴnuSdck<HЦEZ c1@\BGY|YC)gT12YGש4=H ]q>2#Kر!eW壊)md[)Uf.iD*"s'u>t-̅ѯ[`f:֢rIQtI ]5rڻy k'$u܏YZ]ͪY#mi g%a2+LmXj˶b2,2Lh`lo7 .\?K@Kw?>;(z6\rI$@X]q^-Y]#~ɞtwUSUCO<uҲ̐[sQN:K6̔<sa;{`Aeٵd) FK)+Z' J!!LvHNhзs.31 KN2_l9k\aGTJLf1^TL +$4P_*OvQR;+55?+r $LD35 D;E >~V̺ft9gpq|Zt%l-61wL"E#+u%R]sb]]W=C/T˃ďH>ӶZ짊_Hv:#J)c۹~KfSBq1#Ew"Q ۷"#cb(БTk+ʗ@@$թymQSAGĸ/qFr;{3pP;ۀY9E5k?8hMfc kRZ=ne9cm=k;0Da+Z.rs"zVr>D4K@?L4΃ugXBa$Mk.-p3h 놋,f Z#8V HT{7u5~=z:!¾Bq`h6X,Z/ ԦlZS\cI. bX7KKz\Coſ;sRH6HP/X`Β%.~cmDua^M}+2Vjչ0vTϱ`AcGp0=(@R cS@vNG) 55SzvNB*!B'Z6/o0? [JBCǑ%`4)X~5LYw} !C>sL%BUQNq?d@{k,^w1BqqBn{>Ejp72::nBBJ>8b+N׎O ^#.b~kӴ&D)4DxbD/:]cњ%0zrcx:;ŧ(" 0EogN=q!A"N:#b|"n]fc|I{Q>|ariZȆ7 3K ,A&yv̜9GPB9ѫ>LӍ6ʬUEb{VDŽ ^q,f -lZpv, L޶Lcԑ}x p#+,\u>=$AefLh}o'pH!QpAY%1O$pltI 4(j|x]5 oh\JjQ&<6e}g]SJIX}bM?IAVWv_QLK 4~pG5OQ$0: 7>Y_--gbH()3svu^e2w#}il)\J{2\l;E-tz@?! 'lKGb4 vmǖ#jw %K=N.b >zhcE2`N]DǡX>6>ϴy0lӗ]yt+k 2桵1bL~vȝ`z{g,Kz3/Y܈.V15PA37~orȪr6Qj}{{l7?ɄR R sp_N@8\QVj=[ do| hp{boI(bU.k>a]W$C͔WW?xW+_Yq᭼?uXaGWZ OޔzlٞJGK @ pf^3k9)htU]{X#UOg1cNw~NX@@إ9iclLrcm8U`کfUV1V4?_qAΎ[hi=dkٺfϡM47i_k_kY7 DĖ9HI)8XL;HzW~57x^w!'?C[$Α62Ґ*eCq7!FFGxUvffmkYr]t0)X,U+T+>#:/]y 7V#1A>NmSҸ2#gy!LEQ!:P^bu2?1ͅS~~BV㩏#3p{y\3AMfi؏60eq (& [ewBnjL0SJqڟ5D[}- o?~ UXSLs3\Z?.51ӡPgU;* [-֖nDX35+ C')4 ̞=gя$ C8RԋT0ˑuwLR5!:alNp{A:d۴--fKk2*K2VprPE SN0Qs!5wǧ{y@3]&cxӳʯG+şVIb*. d-dP*QQ4E7/TveR 0'(pݢ?6 -1Z3.5:Q=UPky K=B@>1T0Wci7`.C=l*gٗ ;[]|Q BIOke5-i')gM2odbU1'(WixtUL^Q [5u Sy$6}_0IiFPF{*| PrmoOw1`$}z?HuJ+x҈P^Nq]OZm?2SZ=>Rd ÏGMGLM/sNW\]@I'kgIuv^̹g4:`X<ſSO (VEJXj N*ٸy TʧwW(O8p &w^ҳ5-QAn_>`BV4%Q~u0 Z"O=QF9DnaZܵDiLȄ%R}GfE =m_J,8\V9G"8Q=6⷏(2{k}x/w(ކט˚e,&x< Ħ(jmuҚ%!,%X [Py|_ΒPN72c ϯsƃ]#R7Ğvҏ"dA. )[耸G*q=% ؆"4SO Bap:S:bbnd(o]ZSxY{88=?7|H&,F?u+#}g@lMwǂɋܔq$˒|9m&IY_;q1ߏ<@dqTğJQXŁiٚeWO, l#^fA~ED#~wD&QoLSx۴kSzd0SEȩc !w*9H#Vgr3ɐ Um?dݥQToO"=ݔ [+m)it2_uJں8LwRv.C!c[0H6HorăСNѭ(!B \<"D\Xh0FtP =G]|XGW~{yaY ߿I|Q*a.ζ},!u)6zCm6`0Si :w*wMDYL|Bcyc(O nk8H(6Ȑ_ʱ%v*iKA&[ " endstream endobj 343 0 obj << /Type /FontDescriptor /FontName /UQJLLM+NimbusMonL-Regu /Flags 4 /FontBBox [-12 -237 650 811] /Ascent 625 /CapHeight 557 /Descent -147 /ItalicAngle 0 /StemV 41 /XHeight 426 /CharSet (/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/R/S/T/U/V/W/X/a/asciitilde/asterisk/at/b/bar/bracketleft/bracketright/c/colon/comma/d/dollar/e/eight/equal/f/five/four/g/grave/h/hyphen/i/j/k/l/m/n/nine/o/one/p/parenleft/parenright/period/plus/q/quotedbl/quotedblleft/quotedblright/quoteright/r/s/seven/six/slash/t/three/two/u/v/w/x/y/z/zero) /FontFile 342 0 R >> endobj 344 0 obj << /Length1 1630 /Length2 16346 /Length3 0 /Length 17203 /Filter /FlateDecode >> stream xڬcte]-T̊۶mU۶mbbN*vRay{ι|׽m}̹ڢ QVc1%Av ,̼E+['<*E s;[č-@h `eS@Vj U-::`_O'+ ;W hQ 8[V6@ZJQ :]b 29i GͿS?91q쁦V݀@ z=3 `hl ? #ۿ_2e3oTeqliOl'0dw埒:[92̬m=Kfh4\,+z#/?:[6k`1ggaol +;xE`a?0WDM dg03)Pߩ?'#&;SK(_2  瞱1vs8nƶV6Q de6E0 ,6[9IZ͔M-6{/W3-L#ǿ!O\JISKW][tkIpVW-.8Y l\..v7 !hXk`hcfdff )Qs63;li6uqtߢc݁k S` :Iq^FBP_zO[mc4Gҙ,h/ UO*wM_!e'a ӷ2shEmH]NfIooЄӝlW4dȾi q?Q)NFznr(}SH=M?^\vTP ϓۢ}FtD E [q(2Tr+XJ %ioH,ZJ2bb[%fׄ!r%F9!EfBH~OhQU%~a +GLo :{7aˡ a{kP܅ h"jk^~Q^Tqe %hfFOШHʒKVc:.GvdMxؕ72iݾ `E7Yj*?k!/ŝpˬQ50bO: kBv-%ZD1e>II]:J11/ `q8ͽ놔)s$ 4m!'Z>cVՈI-wfd69 !7<{{>BKA:EL~"otUkؾ?hK;t?4_ڣWqHo~G&^!?K- -49Jl}* ZAG4&IݿqRo CTzָ,40CʫF݀w`RABpA)<c/2*IT)s*،;;T!o0|KқnfR|vBUѥӊP^:XvB\87ML%r5 GhawoDNn3NH9K8P3 s8ImY%+1͈C&x5>!rlR+ }`~UUלRm:7bSYc {EHN,cȗs::FugK:[}{x o5Ozן}׉p LHƳ@R:8e%S vX~ IxE^5:9)NJ]@]1Nzu6iq VO>BKTH"qkEGKE]뉇4]:iW 7{\#i@❵cGZH˰ U/DPuP CM!8ge5,OF!6mYtraɞQ:e]^͠HN##5qwқp6Sn'~aW:éʾP}YgdauiXʈz{o3 9 OJhPNl, [y ,f"K ⛵V"o;ydy:F3duc$2+R As)|]gXz@+>bmѝ̥/p!|?eyO!/*~ ֙Cq4*͐_^+HoӾL*HRϜz6׎>ĕ_n~"-O]GUT- 6` x厅w>)G4.@ btU ; ?5?]=)o55s]JQ9_0~O}bNjE biץ@gzs8'-!ŃJH15s'6. H ᰙc鶫[BU}I&ص}ae~p?걿dA(tK(4FLג CnrAZ4%ն_tӽ5jՕ$8)<lQm[q.cY%7ai?7Cg?9#Vˬzrݍf)-a ] jݧn+K>am–[xv(Kͯ:@)[yEL3YinzH2r]Qa Y;#r[q|*. zDfߍf`{[?Šhjsasn\>zh\Bڶ!\^ҜSOY6LB-4aΝ# qIvti1<'IeP6M#VUE YjJXAnjAm5a#hbp®Y3w:ċw&==΋nm+UR^.kIo S0XNrHVI *r*P÷b"1.&SnXo yCA/mhqB@_%IWjhC'@yroٺVՋ XS$\1}7mk/|#4_V],]SyF2@J$s'Eϵ) e-^aXq1+):|E_cxT f^_}:ԏN64փEObS^24.ŭ{~oEOFǮht~1~k6H {oP`Ѫfz(gOB7S4%Y 3$y}2k_ pڰĹ+u8ґG%6 JK a"'FN٠dHݏ#րaฉ mx2N1Ps ^cyM Cάȳ![ssp^yTcVțڤiwzmB^ꯙ,(w]jP wL.//=qDr(@Txg"t]wD?J6EIZKppR f n3X$#R\ aZvp+A{-*Iw.󶼩P ,m 1k3!;am"^G;A]YKjx$@"JS|CJW)i{9,MTlR0A~єH 4Ϊa.C?j/`9%-Y`̇OuV,pU-5m@`i zav;0FP{Hj37kdlq"֒SMy @y AHV}W0 4c^)93JPF(y N[y?K+%!{ w]$/ RSֳީXxs?U($7؅hVԯОAc)TAegp`hpkD1~ҟM΃03*tb-j= D0_v*D6bu_rfR8ɔwPQ\~jFJіv6H);^ $#hgqT/T_F݈_Z}=HnbC{].sֿK],+%RP굒 ˪㸋#4Xƨ4 JO19^ZXLyd3+{~()gQg$i5_5)O/=ʆ:ɍ}&|R'`x%|\c ʼ!_VĝGjJl6vo?xwgKg1RCt1Wk>|!1;B-8Nt/}8n2DKϻ~8e]?N-b0p؍X}Xbd% Ub=/nԒrL|]j3cËo- 7{x݋ N謹y_`2Mg||#Wc(6%:|:Nţg9jъ9QN\͸a1k4UBUL*σVԝђX7y/:j_RwDSf rl@^$E0@0hu4J<#+zNUXWI/TTXz?0G'}6b/Ro5 ,oec,3;QAUeݕsp>1С ey#X Ofot!> 9X8'>:E۞a[\y57aY t;QN`~)} rG![s'ES˯-r0`>hgzf#-5xz$lD]:C󫾒)Bl-C< RA`l-HO4%uN>a'22ʔ"r~5[,ϵh2=Ј}QrM$[ϏU7u{\g]pA[5!,¦֟˩Fs' i&X1 'kȝ hoXٕ>n(yg.bB'pe jP+-ntL?)qs KֹWַ :D]0(WZt#u-k] e/t,?!5/;s  Xh/v1闑H&d(7TK= 0M$Å3A=:B@ԔQnjoXInVjJhV]&Lnh.4q1@3Bñ}V.Vf* Il\wIl)0(D2K Thft̯&!%zzAa; sm̔BΛ(Zz|scpK eL4 Ug25<5(ήJƋ}&z]Q(XI*! Ǫ]BC;ۘLPy-݋2Kю )/N<& x,47D˂5Qz^ Rj~b({В?$)tz:y͆f -ߪ_ÔLzת>Gū񖚎?lg(}m͒gq:b k&)fΒC7-oQ{J~[pW%l&j,_aX gLo8R;Zʎ1׽fYtGh-WQ1^Q0J6$0KKeHf(MȲ7@?7ÚMh4fL8S(9V:G^h`K+B24ؓ?VQZ0J2`LB{_A]RzIySA΋3Cb LLIBJ]+:\FGHEYbNM>y}i9AJ:c#PG6܈L{e2+UKʶR+ψ~M?t ɬf50jnӂH{f#P-b/Uc񯒺d}!6$Z~ZU{P"72\꾈ȧJ0/GA@ڃ9v(t+ H  S'b> &ywz`1ኀ:"=j^5vqk~^UA#ޣ#6w3;Nḕzg)һHè0#;fG,H}){˗k'SLⱡN$K=jPѼuD҈~#퀒Bs$ +.h Ch:5NKvNV^7i/\PI޹Mu锜m_.`![mHSi:ljt¸Fk]NWQӨo kgLPk2Fy+s-PTru+Tc78,ݐ*PCӟme ^$_wtTClfJ5V?٭'Eٺk/~dGJ"[M;Sx{gRb8w]`{2~V .~gSX)>+/Ev!0 j~AEI$-]i1a5dZ,Ө Aٻh+bOeH p%?>],&GaΌ`&8\FajJ: e-Uؕ\eLmTr۔j JqAàD>9NRn2nɮt85t+s˰ K9jZfMw&+la2 SCh0Q6ZHj.*iV2<{U%cx붝9MH"iz>"ȓWxh˓,]ߦ;Oؚܻkˋ"_ـ}| ]0k LDgXlx{u׀ݯZN sK?YIP 5g]vç68Ҙ>B붕K0mg:c`"dttVUU8 X+۟2'A;._ ۤ5aeHP.$I n5,K<*t.ʡj*bK"pA1~_QSDų{ߚv-*+~մ_C'[JPc5მkŸw6Ŵ;ɖ%t N6H#'h^ssyAFc|ruw ~*Zqg YJe}lx& &)ٕ?O[vGK)?.j}A^׊JmALCƱB6Nq' 6)ۉ]I~>8-Jim*Fkh l~)+bƳbm9l|;݆;")-efѓc>% w@q0J9hda8vn_8O_uf'?Y --^[od̵5 6?F='TϺ˰xџI-fOY][Ȑ?&"i@~d>;Lo OӢ dhJCuߊ3^ZV@4ˆ!6%93MKR `83]\~/gХ;UY a0i4G("XSKEwJ#9/I ڼ(IѱŚ];Hf|3?l N¾:80| X!]>} O 1rR [lzy=#H534fW|kHd7?]߂F! bwo$׽e13e iRl[jbY=:zb+K0Y_ ɦIAw#;ȡE$tqb5[N\iI'SpSFpLA ?vYԯd(aGc7QHˀw8D ^hw(D 5Eο#ATA:h|Ad͵W:;۽: EEzłη6NWKlh{5E05VCç?NSÍ kv/'Dyh% Սv@ϐj 2i?J#iF؂!>o he<g7_X"5upg;4)bڏAsgch7}#D)CP@ x|T@FB "ΗΕb$(?Sop$/P=L* RIS:4 k2@Eb5rkC6{֭fjU[xwqfꊓWкcbPزL%G^^ 3.dc^ʃIY2r@hI͕X# [_w'j3Q;Gbw+W+vO:DZQum}G׹O], Z\[= j|-GS^lhE@!BNt+l!wIj v0sxu;o}eJMDFT, ?OoWRA>5ەT݇? TQR ?J5+\KaM[ΧWYUXzPpNMwbkk]ޔ9h\+ThXOS6azWotRr젼yg&vc!w&n]N;?=P sQ0(2t.iJlUPWkn=aÆzX` 3,w؜DAV-vGTxhɏ<'lՙB1Knj3Y8c$9K>o#8 =w33i_Ѓy2vV5,sQ>. e1gZ/[3G2q ElNNOyE;\ѳ;* < *WZv3p݁Q F1}kuPO/긃]_\YSiQDyyZrK,n*=W"Ȏ$bn|G.2Sk٧.Vݏ`b >ܙc3ߴu{Kt'Kr3f߽_|=]r,NU.y&S{:Rڍ72.6 p1䩓\1x%  t<8;t35ap̬aTV4YQb[-]/hߟjᯮ QՏ-q䂘v86T3΢mk:{s;e",]©VfELBIBl;W9_aO4NiE+)"4 |56 :idHRF[L|*}\ ?I*϶ U9aj?0UxwVNx% =@1q3A-pM_'QRUvT扔ί;dBȀ)W5 zMb,P#.Jb"uIہ$Ug I^7z}܆+mD<qG*\eVv&8}m/;rj')v>B,Y%ыT`Q\|wyPAPT:rкz2 $UKO{Jo2t",N_3;,Ұϰ:HI~{W8KZNc΍^oe$˺p' ߒc@p frMBW&-IId&kT$޾2SsB^%!_ιn0Kbi?8]L}?.L=¾aap>.?QgHz\b\ug6jt4,_"YD8r)*^sA"9;X& 胼%jo^EW_ R׃8d?eRn/:j>$lML8im{jNJkj,ayyjvGCt_YX{ qٗ,7JQ!Zmr׼kUu=xȟu*75. t1Sݭ8lW\Up=1e"~ 1h{v#xf@Euz Pkv78} a%7 K\NBˆr븭BwWUr#J-\jՔ(Km0Ee%aGHi)7d=Y1ͮӳ~oAvNJv>"̀*ևF^PS/\DWMKx as10/Sk*a~=1s"p4GE-1|'Jpg bus 5=CG;kԔ..bװ1Xuc!v<ڊac݂`\t v)-RͦY逇aMUjeb 8e<3kưffW':WD^AH(T]I%,0J@f$5#d<昸@٫1z9G+(5c?g)`E#Ab< ĉªH|b O/M7%^-eOoԍ%"U4Y%}ËqFòۗ8 s+ ti'W'GIq52 10޴6=LojE.W"ըWup-%?x r ʽ\&й驑T{2$7LgږD"EN0ݔ}*VQ[V OrA_E8B0-(ݰFֈbaYk6,"p2u,?H5loWvv0#?](yQ`"Y[Q90Ojd}fqO ELEqs gv~ryC2 ۈXRn927Ғ~\0WgrklzW +g$MSuQw 2Px(s|3/ȯf<8(ې42){0$?6Upk>",q>sVkpCkfMY/egDvc+m`; Bi2EyPdz>p-NX4}9*{r_GA%wgm}S~?ZFka*| H| %ONT^3~c7;b?8 ė2%3\[&ƿ !"|c}S-ySO^V ~z+ߪ*}R>W|#F [&a^s>G>8ՖFS!ecjө?JYvwLg6$6? J,[4pp(RZEF${'IlmLR)o𦁐?Dzj-U5,ENI92pWV.G+l9ݠ`&wz1 +tpG $H {R:~9֝(|D.c;[>#.'Z)>2^K"%8z'V⫚X<Xֲ*qFEq}w͟7h,T\ `;-U 8K$ ?K.~%@0V&$J t[my jfN6 }~KsS:|j|/;gt 7-i./tEl ݖWppc.ѺEwPK j''kZs~6f͠hd^-˖$Г %GVi7):X6.g2ݜ0by=;5Wj~Iz%4Օh fOOHJiCbo51i8%08 Q 9Z-MV;ң3]Δ ʪ{$eQWKW&4pJf,]`Lubjג[n1xUS$IpMꇔwǸ4bR'|'?lU!)dB>b(7ŏP޿ؙn_./, 癃8{ӷ(^w{w|Q̄" U\1%t)B8 i2:Ҏr_DԢբ*גAn-gl ~iBp nB5PIa1 F2!uNII\^>f,p:3ws|g=(gi|튐IhIXb=$0ui]7CXbuhc`/SQFd'՞wU1SU'Bx;_wÊ  qʭP(qZ/6{Eu HhJjƆ`!QnT(A;{q /V4l93Q Ҵ7{Ub5RS"K\a>f(O(SYo?ƛtYmIPain:!";/ W,kp"u.bGܝ"H?]H5iߧ-V Jۍ1lk(h&anklCMA.9K^ob<2~޺//>M-G~Ɉ^v02'H!Y m"+tcP⠗VlԴ+ArF>"YtW>-xwuH oӘ)>^3DŒ98ل4B`6akæ鐕OjbA{L 3V )}aԠjwa4onJ+kË ڳb&$Ox\&W eō{$aRw\GB)GOhb."ښFMSnF}F.0Lv|P>_*THI:r2M ڞN :)'J`_!1Ags$SYj"t`"%|ܣ1&35uI3 A CF&[摤f(Qk#8kEkR%HAlp6!¬e. /"K)IhpJ?bt^Y18;p):L BwlƇrU2:j vZA~}Pf0q遏%:K+ˆ{+mQ jW6>Ѡ̫.!>^^JԐqmY9a]p%g4A:NaWa>0UP}&,Ց'٭a:Նrwv2(d$&=PAO Vc70 endstream endobj 345 0 obj << /Type /FontDescriptor /FontName /VWZTXD+NimbusMonL-ReguObli /Flags 4 /FontBBox [-61 -237 774 811] /Ascent 625 /CapHeight 557 /Descent -147 /ItalicAngle -12 /StemV 43 /XHeight 426 /CharSet (/A/B/C/D/E/F/G/H/I/L/M/N/O/P/R/S/T/U/V/a/ampersand/asciitilde/asterisk/b/braceleft/braceright/bracketleft/bracketright/c/colon/comma/d/dollar/e/eight/equal/f/five/four/g/greater/h/hyphen/i/j/k/l/less/m/n/nine/numbersign/o/one/p/parenleft/parenright/percent/period/plus/q/quotedbl/quotesingle/r/s/semicolon/seven/six/slash/t/three/two/u/v/w/x/y/z/zero) /FontFile 344 0 R >> endobj 346 0 obj << /Length1 1166 /Length2 2936 /Length3 0 /Length 3685 /Filter /FlateDecode >> stream xuSy<['YK.ɮ'XŒ-ƒ}6=c̘Y5r#J MY"k$Y*,Y;۽9=#}i!&DUCָET4 8* #PTGPd@aB XTIC$HxAѴ@Hx)D R/V $:2vβG~"pMMM@ K3A HکHa @2iN,eQwdTBI"WRd0ĀȎfF82f EWUb0!/:FRr$i'L S@WiVw\٦P$*j:Y$z}YRO̝Ŋ96U8hIM:Ev>]f"j[#8d5\Hʼ6cHb6dUZװ>(!65h&*Qrt93|-Y?*.xkn?|/h1V5P,Ew6(Y37u>:5LMQ.!H5!4hV2ϸ4^*K )ɕYO >Pn{I]z&F}ز4 8.ȰJ &[bŨ ^o^Q7MQӞEԗfq겟?a#ȒA_J5yc2׷L U-q X%HЫ>94|4JL.v\xxXٚ]aadv-,no^ꌉOc53HX݈;w/¡ McRW [[=L1IgqqŤreR_LKitvBkiJrj; ]FVr'!}鐍IKMb+WҒKdS9͇%^Leg^ lF"" ~bB 7792k}^ٰw-J2e ~&mn(舔T]|y+bTҐzOrnW;Lsw #)Zfk5i҃ޱ3i}Yi L'%l9 ŪbKz+? _,$>J;?&Ox49YQltZCfduG=?]xz35&jYGKGzaϞ"'w{[!?t8~Jx$TeՄ'' +-VUox?->|3vQ,}瑑[/ml۝bLS%fi˒kEdӌUx;<ڥdtR>XBe˅@3zr1 I`擆k./W1^RL+y ۏ[q}|yLPo[rז,?`Z$s sa.R=>NL<=9!K1wVh.ةb$nhûqUW fхNOPKZLJ}~,V¼Wc 䵕1]:7<6߽ LX)R[w$Phirkm)}ԹZC4i¢Gq(l-엞hEI8YVr+SZx0jGXJmc2xmuig 't̫nQAc3]8r%<6&Uo֭>(.Y[#Ej[&iyn>AxβpAV]YlzNhoL.qg=1zyO3ХrKZ/J.o&*I(3]W:bɭ ˝zH0ɶmnsΪLg=b5aU'/ 0yxlGٷ NMp`EFNqVAMQro󤦆CD&Ɍl0A/z0d\FTjq ܩZώ&.zƺ:Z3Tf(T:!TQU>1Z<\wNUm—]8t7]1iǛaș-Ul5> endobj 348 0 obj << /Length1 1626 /Length2 14227 /Length3 0 /Length 15066 /Filter /FlateDecode >> stream xڭwctfnRqR+bf6*6ةخضm۪ة6n>}8cggsEJ(D+h40821pdͭ ֲ@NiZc#sTXh#hP36a#BEQ_Ln|z:>_6!ǎJG3c1@XN^CBV @!&31׷;X m)&@{?C_9}tl ?݌] mRl>S{}86VNFdk}:8:ڛ:>ʋ_?ɧ鯒}:8]e` 02wwoN6B@76շ72vp N^ooVʄ3gnSsXfE`d:gcDP~7XM`e)3H_zw%ZJVscKFgҀomnrwk5ZNQ%601Ch jjl$ohh0ѷr#c{+sO^n)tf憖6ѿoj*rPsl?G)2@<FH ed20~޽O@l ^Mʿ1,ho I|156J6FԆN}?76v56]^rX$8Vcf hv3 )TC8^'[mv%1Ȼsp){rةuSN"<.~Kok1m+(BM1C_!;|'躂šΌ!pLg[gn 2d),LkК*cRNFG]N=_Uyc-!d}_(Tu8[#f?RJX<;J_ !\^LjڍzBK^,3Ě0[cU u/ܸK( \#}wr@ {}ۢwpr&t6;ưP2X6 -w/-.{׍,. 7XID[r^El'P3geL~w /yJ cT-h8;&iΆ̾uLms쳤#t=bT/2,r ( ~nNira8Evӳrxat͞lf>N]gt31bf<řu`tc?fݚc,EDqGҕJSI|_ȅrp8n3 k5ηeD]363=jӄ] gl^$6*܌*Pݤk6|:NjVh+Űg.pEҠɅڅS-s16s/P?R//?U7.!#L"N;aN7]{%h-$Pzxis-Bǟ^.|#XZIm$$3Gɢ= \ _7Ԓϥ+Dg]p2nMC[$HK i#5:MY]K 8!gwGFpkg2AJQ."QO!֚jQ6~h|" v 1^-7Όtm2l^z49u{<G qҞi~ mAoDf$%{a{631׫Ǩ:Sv(d&=R-boc{q|ġ{KKmB)8"):>}B95U,S!^ȇ5CmʴU;څPn*:[KCs6 **26H+a՛zԴѶZI9Nj7PifuA+D NFI֞Wa@ӄ kD Z.,H̚xw0f#r"ǵ\}M̹>PI]!-t[{ObQ˟= &8*4WծZ9@XapXͶd3D\i~felϭ{0EP zmtəҝK I=4yc΀-nzҩ+d[!+2`cb $qWXUӜ(q) [fVRDdg9 mUOf3!ڿEC &zћ9ਈ $0\!4OFo{CĂ,m6Ž5*Å*C(]l8ddfR"Tj#Dx#{׆ksB~KǯX :bo/ߦb6p1o &|ڄ_V+b!bkM?΃ܹohW#'UH{r) @"`JI/R~[z=i&Ad=a]9]jheJ߲`)Un{La[}p\"36¨3p9/j7HOۺ+Ҩ%'BsQx:~팾6Hҽ$]ebG{BON3+K0.\JŖF)Oq@Vʮ?79b~zI?!s{$D=ZK I,d}a HѺ{"LvPwn7W\ҪdSh]_PJ}G"&S%ʕ,qR8hTA{("v2+7`]N2 ֫K%#xJosծ3Iצ 3bwpn~h ˑ=E?6A5 s/(ƷjWoր^2Yz)eȯd^$ V(+_/XѥU6JW cVHHM!m덡ɀ M=7=4eĞw9vX.ǙUq`H[~%7]ygDqH!Ӡٗ{7)kC4B !Y9V;|| Cc4RYCL=ƌT2ϩuL.78uuJn(bEaG`aB<.'|Fg 3˫oqiwZq| 'i&wTg>8ʚOyiTS.ͅV[{4,!C41ڃc2%JI&D_J%/ؽm(Tߺ“ǃykuo=Otq3d Aul٥Ng.eQu$0=MJnk W:ed{Sчx$ITsan{h}|Ν>n{;]#㊆+}[A::^Fo`kf@An/~ {y2yH]D@1'QK@"gz@2ԱbZKjט{/#H l҆CgtY[6cґ2G 3Az&YSt]ןO W kAA4EX0K_=hbD_;=[!pmdV Z6|DokZN4LBg s[p; l!ӄ2֬N8_=TtƛL<tPZ7^F\ N =y&DG_SOHSx[G4}6ytk yY)ك E?~Fު@(NDMc3k703Ġ\;gz X4&EM9'H0e |m>:',xbb]j`Dg3fE'T.E<}[{HZ0X/xJpGVp5wu2=D_cz]`9)>zΉS-gWw֤r-iuiݓY&혪vbgwZn*ne(W4{ߔ`~R`Wr4p}U@~3Z p y`f/Ɋ! C2D5JL;ӧog_2N+2!1Mw)D _ϢZd,_3~s-lsg)~ TN d Esc (EXX-ڙmJg q^|1[gaD烳n+|XgC)S)v0Qve"YR>U(ebhOEd֙D-B*f{qϠ'r4-*NBYY27Όvl Y-񆶙uH 8FLOgGvڠJJo_ۯ[4JlGgdJa`4\=X$3:҉jһF}v/o!@ o-u&wݽA C]S/2x@,%jJt"ix$*:mܖi&NR64lX7׾~p]guST{13WN1BP兒NY[W9 !8N#,eqfV H2ʦ7"1 i6-Zdpj+r1c8 g]1Jm㏇qMTrF5/n\rӪ7!EI(☔?!~gK|DO.āTeD;n~Kq a AhJɯ7!~Q*co]*m;{R0%')zp){A};"#b7*7C9ڗh_fuaDd[%iJdٽGݔZPp[:XblжՕoQOb#ԲDKDq&}—0?((am"A{;T;FNː2rU%K' P^>ix&䠃髑 o)l ituܨL䎓SrA*qjϋf*0];^#ǻVZ7g[1-Wx.'8S8[ hE3i)M%BxF9:$tKAdžÖJIvqιUp۳[r7b.^j/*'mR`HFڸ=Uu*Cb'GXcn2Jmr6[w2 ,UnSƯ#Eb!_>Cu g'=GLO(EPFVԇ:p&p1b)Ykr@[?І#dJǀm\֝5?5ykaH O@]Twz7P62I'RU62gG_Q 9U`pL1nܙ4vrK4>T7+b* R2WL%]Dg`\I6m=Ve@ڳ7ƶw37$4sΩǩʺ,._T ]/,T67XΩ<>lQ-= M tI[mC%PI"RlG-bb597o8 LW2 p>%Gkf̣Ȃ#o,\j=*r-_GwM I7d) %29J3zu{!̚ߡh,u#9ţЩ%x9\SΕAɥ~ ݠ:wxFK{cE/_DmxunuU ݼw늴""r8W`6'^d倒&AN3K AAq)0=b$DgO_e.)t!y;d-ނؚ&aE\شC%U 6{Lk3tЉ9 9M w_F!(k7y<ʶqn%R5c+\UѪVǪ╭cŔsHcQdeJP⚺Փ^+n*"M(y3=SWJx$̸Oms阭+gqP)zgOM;p 7)_hxV)܏RyWœ p=@ oհCez-9.a #eoAƜ3 Vd)Qg,Պ$̺ݙAtHo^Xr !:y)7nǯ"Q;yy0WlJ+ ȈRTV%6⢹m73u8|YrՃyS1I_Q~t"Hҵ0Žf^*)Jf_`hҵK:aX/KnOO<„Y\UbR6iXr5 dHM,LRʢ ,tLW_634%VIA΃K)͓=~ ]Sʿ0',i 'Jx-wexyXop}9wLxcy XώA.d| [wP>q W{2+XPhg'1UR"x'` ܧs99"5ώpPeTa7 o4k Ei2ܤ991Ua#X~N,Wd.e+۵hD 2[n3[:*bSkUL7~'`yNJ#tbNBtoo{&k7G&@e ,?mҔŌx$ȹp-NEZM釠[6^6uƟ,dR`8jCZSvܭeQ<:pY,&>CpUNڤ5S /, t|-z-`E7LJ^Od"gc./wÜْqR&v܂|HShrHDNxx\ml7 qqbTM̓!-Q\M]R fֵf.(0.FCh4GHR;3ws}XUvIz^䩓E;h7UMSr$׭[7nޡ.O͚# r"Ohf=(E~.7M|tvN|ԚZrkDmS)r*sqq^rJڢۯ];v lՋ?2i/׾k.ЮP>935mdۇ=񛺰6]"^͗5\i _>mx9,@B?&+:twn~qX\7v&iBʚU КSL>SZ]sfKT`/O^B7JP`x dI69 a(< )}fIYWX#@ HPo諟!M+OWl l_:S1Hdr|a`4n1TpUWi{J9"LؤE,~!,TY (C0,:XsPNEXYo&%[1e)fj{jr#R=mB"Z]/wyh6EcBaqڶR}vl`C)Q mnUDžrZgu;w{~ΐU=NKST q!S!9S-9@K柡Մ;Wkނ+ !(Ky"j\EkmRDzַ|ct ua>xH#.l2Y4Hb`@܋/dzy^bw4"j˱\ױA_bR>LN W ~ŽPb zx-Dѓsqj艹gİS Ffa@ٮ'sv-۪d6+(S!=wDf`Bh>W1-?-" :˥Z|\xW?jx\!qDmIep05Xؓ0`߻ﺭlZJ~s4S`p8!+Ҽ,11s={􄊷PWKU0׸nv}95J'V?R3@ _Uf(]{lX, h׶\tIdѮ|j8a2a񽭫Db+sт|i$JUYj'#Et"[scե!(<ѥ&̪7nƲZyd3HQS.5P%lObŅv!hYW>wo2h9_S1ҠՕ)&Mɋ &Ȩ ~PeAVlB72^c'.o5 #>2ڐ='Zz™0VO~"ZEPS<#M߻gܷXzdޔ#33| o,wЦFǔZ*s#}(KҀ>L;m!D$IeiT<&wϏHˉUWj3zaw`˅yuT1ud)ԅ.fv4)dRPuܷ?vP)|dENmdjut)j>Ԯ;*489.wW;lP_,61.RlV )'8\ GV%تf/ GoˌVF.c/[\A%>˻:# 1:f[Q!|U.vyC&fg}91'bK~%;޹H;򆣯-f3q~vV={eQN,|eޙjbdOM?a–8;[sd ÷sq{Tgkκ0OYR鲉i&Ql# @џa,(jP03xV: )⨐kP[U?(% v⼦ٻ%~G3l{DGE^߉G`zHE`Kb5"':n'eWf1_<N:y JH r/=-8X]^qPpӡi]j.˾/ᙺ]կJit];MI6n9RsfcU743S+2Rz邏ǗdO~605Y\c,e4"3mkPD" # {y &q 1Z`5aA̟ڔYEA0k8SȎ*B>o}d-{OHp MZBm$^φf g@zc߉<]MحJV{_70HxC|svp{p%LL87G҉lN78|1D6n|a6w[~4$_[:jJU D~vK \tr~9K2R\>^zDgO fg:|@fsXQ)uΨXΔ/i1Lo-h=$^R* MϲSq>EeQ_"CpT]T_? 5]'B]ѣppg8llDVps }w#'Ӥ^޽W/8CmoTu9 D9`FGLacP?xݟ=:kx&%3yO+sQӲZ\RQs J|WXҢM6K3`>6@d 8#h>ž o,CP:>L{S8[C8$ uu3 JxJF\T͒ 71E%tYՎj,l;CYIASK;aQ@ۡA0IW.!es ?{ϋ0XVH׊OD5~;?/}yC҂%>vLx KL^OO$vwm{|,5OV@e{'~Fi]Vzw#{=<A@K_?Jovv!:KA?#[<|[Ru !*?RN1LfY!+%H`$zְ߿]m`Hu-oV5բ=NTf~`@cX0Q7Vn.OR;'fmrm#k1fیdm&uZ-KmE l`T}_AKmC~{[OD),dײxnh0Qtc҄L= C耠=}r=<8z=32VT.i߆ Đ4sFX=ʒ*Vwy<=R<>ĺ,U uwx!1oo] 0 Kݽ3"S) I#-"^j-~Dz‡3#V MX c)Y SN;AWPL ۮ=Pԣ Apdy"Sܕ˥+}J_H5.D&bŢX(!zGvgr!&|P 8}SKC.ֱe`=b)Ka |)Z'#y'scTI >i?V̺2꫸j( (&PBxK+ {t&Mf)'sq6ԉUP1]V1 bzsk˥s}\+A)4 Lw&lqSA0Nzge&`]xCJ"|um@`Jh}{ +&3> ~nxܕx 3QAcb&?vRBup,Нh`Jdכ;{r2YI]" %!5I{HKDSo|wܟJlJroDũg You O\"I(|%/5XKE /~-g$$ `'zEsnzZ=G ^<͹An3 BjèTcnUm>uum+;Z-RFXÚŵFZ3N5-Fn \IDLbf ῺkiQ].Ay6IX] 5X D좽L 2j,85Nyma(h1M/J`{bg]3&,G)+w@NcƕpQJ:ޙe8W2rbniw1xRXkWٹVv"H[U=vԻ#7=6Ϧ 6OA$e]Iit(BN oOy?="ZIFR"2{CF:U3Hܜ>_cmYJM,ޏ/[[ykxʌwl}&:q2t4O> endobj 350 0 obj << /Length1 1642 /Length2 4693 /Length3 0 /Length 5517 /Filter /FlateDecode >> stream xڭVg8-:KND6fØ3EE"{.Q"|#9s;w~\sw]/?* BbRJ!gv3D+a]<  ~~u,GQ<\ 8A:E89!sS aѿ,g.ϟ!pBO8q8 pFƖڀ9 G&=(Q80Fg \80p(1g(c8@',' PP Mp#`2c4b<@jN3 ڑ CC=Zh(@<8 CM `!PNU `N, 4O_`0H__^ )iBN( I͋. HI<0bp :aB`pG!OH g*D/H_"Oܿk//};iq# = v -7l +@ؿ{[FWE9*.یi!0c 8Be7GX$'n An9#3%( h|:`=i9& JM IJE9Y#/< ܕ:FEF ASO b bZ<8MB]RS4Jvan>GD+R:yʂlIo^nc /,a[|>u߭192+9LLm)8dy=ah/b_1V䯮 į||ղC޶.C r?q;cݫycUAivxSvce; eMml&iijYBvҢ*onScQU :F-tiiRz=Z_bKL2}usB1kwG]mϻ]7dG)|UC/W>8oZi:|HV=#}GOX|akxցRSMELsK1]lRG`ծD5xb/\Z{_SúT37T Xwz덕A>Vɓ9`d:0eT};k6ܨnTDut`:PS@0( p_2jŃ6)=J0}rVT9Z8XH. cVYE{X׿y Uԅ( 6to饵P4nҾ Xrx./1ob'˴ddludd$~ҩk UsnݳuԽ])C0{zSߴ4:w8J- a"RkϱίdxSʭGsVgAbF򭸚XؒǤ0 U5+v@58_2H61˅2 { 㾸"ǵ$}3m,<"PO67fJA#bˉA6/X ;ߌuθN|oCgݾcWtzuCs8k/Ó΀HP##)Cٲz;m"sL;J\V/<#I0V"3XsZ`i{uɕ8v8y6%aRǃG5+ 9:",L5~$eOkhXF`laMA&@F|f hvdok'K4ȓ$0f1U([coF[T@hpcs(mR="_6ɤ:ކϠi4`߰Ifـ:4m \%3L6j׭wMMD;Y* 3C]/d}4q*1 .warNrHkATtl C\RR-'a2d73ݝ$3E3S.BFm˛Dv h,]S)1,ow\I5&|=6m- i6`Ɋ7wzu5xr{*m;e<898f^ _h|:XۢlVW^xvH' |JoN Yksf{׋ɝ-$7P 5 ]DfH:Jzj6& ڨ'Xoͯ\ë(|(w]|ѢQvͷ *K{eVD*YȊʇ *#nXrM]EFy>COS72#vbgx%1h񻰉䩌6%B%P_f_ Ft'xG\9E])ӛ+#]%Zv4B'ݘ,4d/LǏPCr=޺^~6ɐJa_ twqy6(_6}Fi`a"1mIUi"=6yqw|:)nߥÒKJQ S,]8g\WmeŊj0kP ='H$^qHLbAj9mL0_RYY{۫od?քaOZ`wָ(}-L?g`Ʊ;-A ڴehBGYkD';-M )m~fKA~=)k2P6Ϥ(Ϸ%`Dɦ_7GL"9jy ޛRGr"+X584?zT|\Pt ĺ.ƺ$.O!L o }9P$"jE:]ܠl兮͂u1M"T~ {Ð-d{Urwұ<Ưm܏9*az?WH1 JOF`{8Eco;w<.tnml|*5}W͸}VKؙ{D"vmul嬽5l[y+JFx-DBR" |suP^і)AѫC,6Qd`b&6z̼ձW)_ .%z l:Ȟ\kz:T\O,R?o{"V\XCzk+f& bHwj~g[! E/rGr]N[YISS{Z F`cBvLSֲHﻘ,"O0ZF])x{QEٔ~J0A% rjU?, k,TFk|JvV5p38J1֥o\֝cH:}\%M)^VQ= h'!\z@ƫVizqIJ郔y; bWOK\r?wr` (1e\ƶECVK_A <^uU ὜k%"b\@X8iOgւ8r&KϋIJ|z_Oˉ40FA&:'>HSI8y[D1ň8}UMshz2=!#wbώZ-̋M65[ZGuF_-^b6nDʲG@ԒWυjNEV޼ι'o}; <{ijjsO%OGi/g|oz+_moZS#ᆌcq'=.ES^n绞!-7 p'\'+?i~!75OR1鈈))Y)Pr,iA9Һ/i g9 )i"Gםv x筛J'hH8B7XyKtzr w}S;2C?ϛ&zgH\ţ[+ ~AYT}).Es3/ܥǎmQhuDER2Qr:41S+iaL,WqOz5q$S%'t&FR cS= Eѻގ EK\GS/L2Wibϝ>R5beGKAMP^,rEaIl?_wXzj68Na\I,-cd(+h~|ޔbkIrнG{~gO8$d͑hǓ._.̬qRթ@sQwE~tVgJƺSy/&Xk6kS@ '\܉ Yվ8!* j _UpYU9qB iwj ii rO:* lا/Oi_*I/Wg3Kx6\h>U)E)\UU^5p0uXD9(Co$U/]=NJ6ȕbn0m3 Bwja D%nލh(?s4䳪u;eN>硡qkfiGWTTLr>WRg~>cIw zI;e/4/o0;i$j*Fþa8@ܨ}OۋغG ZK6х4?|)R?IQx ydffjɋEk7 7qһ|F*)=:X!K?ݯ728AQvB0T%+0;kH@>2y.dҗ`"߫cbiޗ1ȰSB6).H;)Ha}*bfAMs7a}ĄYғ|+y=E7ڑu/;4bwc؋_H;z~? endstream endobj 351 0 obj << /Type /FontDescriptor /FontName /VCHGJK+NimbusRomNo9L-MediItal /Flags 4 /FontBBox [-200 -324 996 964] /Ascent 688 /CapHeight 688 /Descent -209 /ItalicAngle -15 /StemV 120 /XHeight 462 /CharSet (/m/s) /FontFile 350 0 R >> endobj 352 0 obj << /Length1 1630 /Length2 18973 /Length3 0 /Length 19806 /Filter /FlateDecode >> stream xڬctem&vvTm۶UmvRmRTlVӧt{uO\׼kMAJ/l41ڻ330L\Uv @n9zsKW_9;^Ŝin37(@O'+.*uMjZZc0_Og+K{n@;s{׎ +[s$JRA inodl Pr52Y;S,N@{3Jsf% 08;Zu305wGEp0wrv rX:ۻ `eojjO%kaWL ldUILy|7v'_5h hOIu1w{`f`k7_0'leo-l͝;Y'_Y\m-Y4uY-7suӿDPM ho 03cT c῏[or_pU0;1Kw,[cZk;߶[B+g +s3%+ cۿ=\/j+Ծ[CUft+FMqMiU%͂ApQtFh?=\z.oB,lbϳ@oL_`MfiԦNNI[5pk@SLzI1~fP&⢀Z`F.w{](C4gҙoñ~,[ʾ4B_2"ԭo]Ae1׋r;:L{*P]N0܊0ȟL1QAK>D9H-o|ڼxX ^cl3O#&OW7N꥜6Zduw/eWbǸ]tKV"/a&exY08$:q5eUF U8+e bOT *!lD3) &.LemhNm}=A F3ǃͲ{0MR 岰q ~l:H&u#t'zU9"i}Q)ـk6oniaQ6H q#h2@ -lOej`]:8υQv`&{rSТo``)U(`}ܲ k0z>B\[SAJ26gܠr6،jAM (Wxyl?(O(4cxe}hj$ȪFKrjP C=5P<0XAZ(b—Ś5QVf*8!yBP`f ~uOI5/bY =b=7,ia.Q j A)ʅW䯆,*tP"-dgq1`UrO͘7aV-O>XeϦ.j蘡U3FT(ifM9?r1hblI"&~C|rRO񚦮)OU%װ3srlv~ƿKgNR;b2ol6e&[fgeM[34 ǎ`6ysUѴTw:xaEW{,:^}/bɪ6v'! -b6; B|C%m+p: Ph- 'j Ixİcq >`;߹ X{U+cz_+[;s3'-=WBA36^.7ߵ6Lyc39GUߦޣSR:44x 5V<5 #i|e뿠Z&8ѕtbWᦚ<4&N ܱW󿓀2' YM]!xRQ\Tʛ!ÃI fF<}<לTj-,iIAþ)yjg9Nౡ7C㖦0O3q鎑?2:1Nǰ1'}2nM68͈kv<@CZDRYBbXQ"IK86`#+؟$/mBˌСcjb'uؓW 1\/,y(ڔ`B7c_|ݭ0Ț} jf3,'PuDäSL<=x:ky[6;I q92"~K\q>@)l(&bGꘓl1kdS]֕ qT|nI粇ԚG_G2*M mo\fiVevL7kEī!R!q>PWlYqk_D^ñ!ΰ|8[&gy(*M%\xjM\~ -8%8ʅ޵i b]aϘAcּoY@RCԳx!]Ek\픮zq[8-9[C ~u1Dꏻe餂u~c^?̓Y>H b}Ek"6r!ʠ ߸-L"->ZɞDD1.“gp Xr";ذ3UiQɶJ)CI|l >*'9om;lvD]Oi/{ݖ4[ u!۞♤#zW}P3o MQ^3ƤitO WF;G$;iļWB_3KClmZ?D8~bn,aV c78"BQ}cݰMՁf:60S5-6)9Z"O0m H_a:],KNO?;Yhwa⴫o|0ci@(~"3*:, gkyFFjǬ'Ѓ5l'w{JKNdi?7fAGUD'܃:8)+.^jPKa2ռZ9ӮHczԛE޻(z!Hxspq-ZK]\԰itEn>X1`aI,7Czg'=(,ڵoNZe؋?w,B69#  Wt[#0;D5|$Wޢ޹@nD,mdȜ2<], zlͩo@xi|fE;K:WYLӍ% & w6>wI0Ca7'#0E~T+%~ߧ&]jXlKDCU蔄h0CX:E[h}%oq;7'*RoY8}a sZ`| .<)Ju2%a.dR2l6  dr').UF(E^5Pݳ_ @{ ŘG{;p6NlE; h{3D!tdzge9{skds1²%^><B^Rrڄ7Dq(ސeG5t"w'5Y~(cDxrE\0d"nd1u8r)i c#E9_^ G]0O@R/L`#m#,cx۷E+|Jy6;s]Gxcwa'!/\$.ArZ)&| 0;ȖX-!J7/DZ[9"-_ pur1e5Qs^E` f*CҘi{]k͡<%V VOxvUEGl3,촪.0B;mP†I3K#{-OtWtN Ñ$>xզR`ÝEѧWd/_*=4{0нY+'FS:*Sc.i-䬲k4b6{\Zް,bG1'ϠN!?xBB0RWО?3 <Σ~lB0-64%խO.jwe߆DyfR5z پ(+%L< raYMh9сŘ퓓m`f=r։QE5oHJRb˂aDIK 5 YxW$s]ߍbF bW@W"g^pQ3)7D2S5;skaX\N{xn^rp{ZKuبqMCshS(ӊ}jvJ ߛ$ ľ:0M)5p>s8~:~:}jEHwOIC0)gP2%m~uJ@ʴJl`sC i_@U I ۰@y'a|ąBݩ_]SPoiaZMu/*hVʉyσJ4k;뷫y<1è ['Au`XrATY_+ri\;,f~kqzj$HxugX h2$*^K fm/CN i48qMzPa) 'Q|0CUY`igq.IM{''OCD)utƫY2(qW_!sO["אHjehXɷt)Juʯ%kKۮ}郍?n;+~E1JSz Qs jktb;EH\zbyL9ۖ3YEX{l_MG| tClUģN"!ەUcؐ0G2>NT2]eÄ`8[pYr@N-Տ"P}p:w U ΂\$TrrP8vt=Y#:T/4m2n2QsJ|M3@8Of,Դ΂!M>I7sOAk'+= 덥ѡVޅXh4!4F:ћ%^H>+?e'Xu+..Vln)dGzB6Cs7Ih͖f0FD8(Jf S1wGŏ 8)>y7yv$!$8=w ͒GiީpUs=Fh$r?17b7|ŲRseA`RY&nFD3/B(0|uV &wg;z?sOdio/1ȽygH(I4s~._lJr'>uӕSD^-MSj:Z^T߶F[+J(ߓQINN ht0oV/ ζ9urWB2uXy>ŒVrCxF%>j4#t =+_dn槊diPt{$@u?4dav %^CӫpҢTR=4+]\FAPUCZ6o|h #+}d}:îoe]pɎ/f|q@'U̶[ZJufH' rk45 K#A )FzLWj9#|j.}$].$+xP i :7P'-?:N`]ݰg[(YMenĄ3o8_Il@;^WDŽxmdρ:a e6ZªtYNOk-Dj7rhBD` X2e:=<6k>y rH5Zj?|j1DV)o[%,o% 0KtDQd!C(nXiMJmEf i+τ:0B 8K§-ѺTPc6+(={;}$@?GWT[x;XagIdCvtܟBOoq3;uI_Hx|7˟]$J(6UimTsC`сc PQW1ȨW._!hp~N9ҿ;>O.53^6c{\iwp؉4d0# ,Ve ">ZgVJgA-BȯPZhj߂a–_IwQRzT糭89ƹ}k ~>Ah# Dqq?\LUnUv+5MDud<γ?zYKۓ{2#b v<)Ykϒ>"ې{g$[>:یPt>ƥѴOG=9`+&OҬlQ/k0 s4{@76xScH,r)^wZnM]=nT& u,T3:W@?0[ mz>&̧IGZ9!h(L 𬯺QxJ@Y Q=hPV">qEA&6ZGlӍy@V81:")KrЮazc4 <> Ы y] H ^ދ=|Q|[ ©)WNC/`NRgK{a.:=/3fsSii} $ |朊,}Tq ٦4\R`,1+үyH؇6qُ\{1Φ/}ee,i5[ 3(ƕaЈ_"t1Zg eU|qqs+bJkJoV?F??;@ rBU*_=ZxV^θ5n])yվϟf!RB wՁR[g*1KGYY)lY( ZᝮP=%V`hA|3kFHt 2(>V; ,K#BVOQ:ܝLy?$tJVmc>(K7 P?m$SXع3*c Nӥ5"uɈ;?٠ߘq-ZqRX`}N΀:~LWTtF% e5i 7nvXOi&h]vEJ$S|P'M!kp PB(ˎl[Wm:J*;,=XEVd=2K"ކfvL##+DF?YH[B]ӣTKb"a z=Zy )(!1zt;X.%z|N"Mu[_gKqK_ &pvi" =b]q;Z QC=NP.klo\eZHTE,#DL٢, C;C0 D`e [KIՂe'NW̋5i/?be~j.RX) ![)0( gt?86A ~$"td )X[#57=@QJ 'V=2:Y!:aNIyаfa$hۺ8d0$BY_kKd`(<}.ɓU>|y8ZΈn^CKosCp# lG>8/+7umkm i&of @~]A'ЦQI^ WuG욡w~kjR"哔4vs_7^Yoc`B'bP;T І\imHIc f3 XRgPkJ8zD16V oSNT M `R-99EĴ$]U6%dKٻexHP:[洂_g=O70]\UwHW/Cãj gJWF ?͘ گr'\d[UO `ߛ)~'8+.bѦ#R=E)S2RΡ 4Ⱥ1h1n\\^=e5w)y07*FBZt]mS4w{귣d.͖M3Sٺ|[4PdMğ9w_h p&ywfqn^d,a  MNޫ79aFܢǐYb+؞p%_B^ۆTiu/X2`ώL*VXU?}xzq*'~7i]eXU Iύ`3e|Aɑ~bmX14Fjx;̷<9oTQN!5(,{׷)[@u M*KkQpUqBhZ4:$5*nؠa3vz]\[\U/tS",jA}jzhN6=w$=(wiBw!oYq ʐǻߴhH_P]ad]`Ў[w(ZZ H4~*YӶv $X s82M QڢUSڅ6ڋSisV3y\MY SGAZ <&~)=2jRYŊ>'`AɍytQv/̓m}:2ؤҧoM+s]u*.bw1z}ג%C~K1AY(J8"fGGM?UxV}Ƣ/:UM&wVZ;WhE% ]kouܣ:פo"є{wj S{`Y/ 4=p9Q|ӂ6&,q TGkLBY{-Qxgߔ呯n9ڥ KCGd4~۫"'ٲDԝ߇ 70p Z|'l y7cީ B$=1hN6vx~Q2m)"{fpg*ʐE7BŤ+fntJIG#̾QJZN9'wc[JSHewʰ(;n{3tu>0YžH6hmw!NΈ'']eTr_]X(h']Sң5Pbֲ0$U,_h;U` Zgpȿ1h\#ߨS;IOb'5)`f!Q cYHR@D$)gP\E=]:*I2ky&q?FKx\4_p"lʹz/ 8S5UiY. ${^ǹ>*la}a6o/jlN])爆1_G0hcPE:t%DA߹]rU2F\9FtЂV˟nƏ<4N2g-R o}X~y?DYh6<8nՂ%blxX NS,{"]Hv.NPK݇Ny 3: `oU}Kq#]$p2|ilD!Ԥ."& ݖ˻tX'4FH}][V||72Pq/|=DEOX][ZzxhzQ,'X6Q s(&|굃!k;hKľLrCUílX=W 5h}2DH=vġ-F8mFBc}تj(Y f$uP7r(lcucV>$y"t2X\)շE.NJo%dKS_}y lcj/q:,* !˻gO NUǰZڌ(<\lvt 6&FSJd!kӐqGxpx8골 C0ՇMVs٦Vh/GV=~D$v SAUy58 %7) Fv| [wQe_Sv´cgY[O=4ܞ i>,N[F%҃<~:Y]^+d2a*o0DqI~}3Rn= B[LlTF5`dsU@vh”i$}ş* ؗy1lIlKT47fHJCGxi\+*sj6= O 5lQv^> %~2(Ҍ0S7)8AΏ?AѤOPk|ov'fiuΊBlH])q0iNvL; Va94iL27籘{9Yuou&NyEw7D qӣWRl|\BzPs8@&v5)Z͍n7HGcSp܃{D=B]RQLWTej-d9eCQ 2Ƿb{ P8+\xk},78u3ŊCM}mx8⑏tȺqS-:OK dR2y;BfD+/r{U m[bӟӽ}*v|Q)gv*1H8gp\ ;_l#О'CJXYg#\BBWڻ&ì0dIJ,90T{T1d 4SWڑ@39u(̎} SG?MS /";v:,KJ䜜QlmXUQ"x7,W~ A Yȓb=ipO`t#ItA\r.`a2T- tYV Sv@DԉY^_߹c,4#k3xor,2O J z8QPૼhWIG3qnWR6LK.6"&EcIqZ+eJaYd09oP(ۨj7/ Ԃ }V]U{ 0G*y[??6|6x5& }\(hO( Ga`i(@hf$xkkh%ݦz^`B6t|='8ܫTٌEL ikmSB\U1vQ<\Y؈֛0:@QVw< n=+lbbc-Lqe`a|GE2K$S/":,ЀA%"ND&nڬ (=z>^MbA^^8 g%1/҇*Ij`k2q0N5]9+fI^`ވ'pE\6P-|ں_l:7CyF.x%Ȧ`̀\p`} \eKQ(5F.D+ ,idJ(^H5CZc[Bo77ĜMTf)1d*{IsP 89cЗg؂AP,P=U샥4E4Mq`ϥZ';IsH$HU6cy(^5^t! $eWΥ ZOh :C#3pE Mĉg\jjh?!t+FVso42?MfҚ/ag N{m\,qGqAk 88r=ID(9D 6$ڼqwȀwڪz5J㆔{Oi6U؄y5Fu=Yr/"^'Ym פ<&bVc!y"Lh{y2QJvړ|@uAF7 -UT ;U:c*v.GTGx;'U+ƿaA.y $u_= ^]Fh޴3:iW+ܣ~ ̇U}SlMLxȟw~e{i//ޅKfFڈ'< w=ղ'G=fK㎕)Ѷxd}`Dj0\9O\'9uBk[h 0y9|qk}PHzW(x=#SSÑW וHst1cې7&SkqOa֝J\V(=L_UxI\s NkI78Dhm6W~“eQ{"}Qл9sKN1 xs.$q"ȴC˽S9{{o&Al\^"1 ߅[#C`eniWp~B*#%Ta; R"<:=CB ?ZĤD); #*Ri[5.\k0t U]JWC ĤӶ~1A0͢2pp  ۘwglŦusLl*XS/wcw;|Y.t*&6m+ZN-W٪؜֒25r!cՙ b CW*ڸF-4T$t+=z" oN^XӰEڢǻ`A,lZ68`iK os"P@Pu^{*šy!7ct0ZBbF{sx+?K^ho a>3scy>??N/2!>:4Rt7q A @J"OQ=e6q2'ɢΫ^54Xf{>Ƌ,뿋,ZiQ~|ݝ7O:=z%ebaMKEBJꍕƞڷIcwC};0㫶}٦+s豼>jF+h_ζŸxh67kQN5bڗ& +^hR" XW3ǐ:sk-j@D`0z[t@Z\#T)f0লBE?llRR TI&$Tp IlGu%KJ(^gTܕVd$ֽEƛ^f^KFy2jv/?hDbe"*])x%oUսx7t eZȎP#v1ys&"xXfvu ,o}-Fe>Zm9S~ޱWф3cS^: 07ˮ^ g)(v]¢S~Ó( jD^֊t>ݱ$VMHTp~I'R_4WKOj"ݍG/h(PƸY(NXqhٖ93:۪VpzgY ;Rde3 s)ΟVc#g@J.שA% 卖uuAztt fbn^HN&RrczMZλ1,kIQ &ŵu yX]^8lиV .a0<ה(2kZbg2[+كvդp ؠ;Ω⁚DdDԈK=fuj<"v]{ɂ WF;LUޓȃЧ+.BvG4vvŽ*iK#hsuHjx©9569W0w9pLXm $pcaEeBTFwf~ILPM ƒZ: «\l^ҋ{}3v (A!׌LlFg.ko4NC8(ˋ"$uY [wR}46r <졆Lfd>>Uc|~N<S QhWbH{{ɕ VSĕNVsmTK:Ht*ƞvS.YkNSfI%I ѲiH-5){DOރK9D]UY .o۬5**LovI"/iԕ j"DDS,+˖qn*Mf҄a~ x+;5'|^?V.RbGD\.YK@ iD!Kp6|16=!H7v M $@*ځƐN~-]>+<߫׿h4 QqD endstream endobj 353 0 obj << /Type /FontDescriptor /FontName /WEWISP+NimbusRomNo9L-Regu /Flags 4 /FontBBox [-168 -281 1000 924] /Ascent 678 /CapHeight 651 /Descent -216 /ItalicAngle 0 /StemV 85 /XHeight 450 /CharSet (/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/R/S/T/U/V/W/Y/Z/a/asciitilde/b/bracketleft/bracketright/bullet/c/colon/comma/d/e/eacute/eight/endash/equal/exclam/f/fi/five/fl/four/g/h/hyphen/i/j/k/l/m/n/nine/o/one/p/parenleft/parenright/percent/period/q/quotedbl/quotedblleft/quotedblright/quoteleft/quoteright/r/s/semicolon/seven/six/slash/t/three/two/u/udieresis/v/w/x/y/z/zero) /FontFile 352 0 R >> endobj 354 0 obj << /Length1 1647 /Length2 13388 /Length3 0 /Length 14246 /Filter /FlateDecode >> stream xڭyUTdے-^HS%CAZ8?#ssŌ5c1HQN(ngLD 1rqR㒥SH9Z>16X22G34&...X23RMY_<|z:Y?\v6@[O p6L-oRJ y5Y1@h9ٚXU'd4th@G 'g .&%i7;!{G6'33?t67t+' 3ibgWIc4W,# 3'i8Yؚ+Z#INoowgN@kSzX&ϘΟ,la)[S;?&.\_=Ch o@?SOW_O\.6 94Y5l   sd#٧BtLll0[8[M-֟]hma tbd7L/5mMOAQMHD3mެΪ@DҐ3_Tv/:&v.3e\̬>1k-ghfgdd|~шۙG*Ά&`cGOs%݁ư vR>#|7YށRrJx@?248g&+{ gǻzwW87x/?.$)v"(ۋo'u:/70z^ޙB8kHbCnzy6h:]5뗒(YΤo s4 5Y͛yW(WT]|qr3sEVڊQ&@lbIy N@ [xg?9 +W2Ԯ1[.GxՙsH~TFBE/U=tT'jtPd4k}:"1Z5InB#&hi%V3}'[_Fy"oT^Y?[5Z τZ'vyw6890YKPaB_ f,tMo^ϱ apk~7B? ^s5B΄Ȫ* #ɠL{+EL]]$XK7|x]hjq͐hOU7ϝ"8Q!<hB$J72`y^G]d!ܢgdkk\B}ʆ_8r渠st:Ka ,-ͺġv5RJ4J\}jY :0c=«UބcPQ\ѯ& Upuj/؉1.7!9ZHSw{C*m_`f_lӲzۺ[(ޖ}7ʩH\:{~ƾW: lMLaPdKB,⻑pG@JrbFwfu6Mڔ03T7VnCE&:\f3%&cم+o`,gF+r[,ؙF&Lp^7m!0 .ڑ8֔.Q!!?݉MC=&)~^T?Ӳ CuJcRԔI~ zjdXpSVؘ%MR 'FhU@!@Ip6˧Tp\e8O0.EViMG̢4Ƴ?:{X3G |Ցt 3]ߴ|B,OU2L*Kv5J.ىK &m{aZ:8[r';"Ȟ ҷr<+×r%,J"El9W^ӤM1/Mo`* UBBS9=r%MYҧhlh;h_| G4.} 5v>aiNM?ĆfIQ+5NވZkgvk$}@#EQRhSWbuh _&O9~|:nh38@ƒMxU,iUHSRM^H"\> DZ&aK*/ ._msҘw{/2{dμlS-|X\Sx檍m|jvBjV>,B;aeV]ݒ$,{zRJ+BuZas]Ұ#ND=ssOnQ1 F]TY)(?cլf F*?d@jG`L"A! ᓌ\p7v)k@2-P$oLJEb؂6}ƚg:U xhڵQ'oM5mG)?\|" InsCɹON0,$)0TM蔫bVvH=dQߢ-MٮI -*t#"Nn|=TeܸÉ{j#)l(Omw՜mȃrBgwp?4/iyraVoaZlݣi?qQq50xmuGv$Y2#Oo=vv4TXywZ\Gm,2@ fI!5gF J@B}:3 l\Ğ2F?ASETA?Z+귾Џҳ,G27IXABûsP>ۂmeI1;ъyGWƽxQnZ]z|/IJ֬f~3"M7n\c- 9wp+}>b&4͆2JWeu9S.^cmz3!~Ak M{S'3ъgnTCXnXR ^^O\~Tݱ˃edĭO*htdayP0.¡,-@R햟vV(&@|tڃŰ?̀T˪૙w m6ԸݖS[KlSӷAw'm67f|F5^4q!R'nMNwxّjYnN4f ]J>9^R$YV.ãŭ^q:ے7j֫]^_x:W7uT{]8r -z$#ϖ ]:}(ok<^OP7c2璸I煹"5׽1X@enW|^.AڔBT35gwJ&4{8 bQRp`0%k88+PP83?6$ K8QP >qڡh#{|[?J#V,&&͝XBJyغBRRԧĨsη13*k) su!r Ec/%QbW`uXMMڠь⚫?u(=SNfo_Pц|?W'R*"XȚxNdQ}C'^ rձ.z_ǡq^M|08N pZg"5cX?quM[+u5I4=3}7E|zJ PU5c [ʼnu nu+2j<ƊUbB620 “7{!Xۊ;T32bL^/h{d% Cs;jآ _ʋ/_b U.HLuޫz[uhꭑdpQкG v?xti.~XTmQ㍃O n3p9g6nlt SW-vniBzCEI*GoJoxhz(A^B7muZI5i'bPw >p5;U/&h 7 ^E7IBO >džIQ -rZ՗lG^;Չe Dq x,1ZW9VAQ|EE9.#)+"$;Qw;mD'C1qKk2'Qa D)vQW/IC'!{H-5i3nbE`_r ͪ# wY!h`8b9ϻm1`՞eBM{3\Lp2s|ݿ؟ D#qWwՁl`03'D!FoÍ,M+E")0 @̵І zwޛ!~ܦg(L)C)Þ;9=]*/Lr]~/h>FD6{cVzf _SB#<JmHV~qjy,Y0H/)P]/`ŵX+2Ux to2gsV}}F=P+0_~j^ٷjꂏ Heb+Zcj<۸%Ɵ•.&;x9L_*JݬlUApü=eXt'SW%a{($Y)\yVoƤԣ!UK{ Y@μϨg\vH3ܾ$b<Fj |LZ v3,n|uYdOӂ.WӏL9-65:qI۾pC k if!wx=*4OA\\شV"&3]lZm֞7\ߢv'.ى{?cߟx(@+P6gE6jl΍ 3^R@BG_\bӕqPwV來5 |fQ? U#12z[.V0Fi̓F7YaOow׀Q*7A{;J/1GRf+Tgt7R1QsZ17}dOއX/U/M&7q`%%i~\|MNȍ@Q4 үAY]z݆I›.b D^ĝ啚6Rq&w4-·`kWd%jG0nrA=!?}M![BL3F6gݲ30/]rO"lbQh2t5{ߒP_yY}Gt1Fo kp xJ]YECD&-!Fٿ6HLZ5AztWU 1ʘ:`8.T ))6𣱬Warΰ}O!(\`AKIy:"0j6Iv5^Y]p=A6mZ\HU05-|2  \d_KBDۉOW gp KˡݸHJL+$5LwKnMi(O1*c(rT$Ԍ},ǩl]atU!Hxf0'qC#O,/Ia Hg W9P]aꆎ=ezW^"*ۈS0/4.JA TPy\0 O+tCÃ}t|s{d̞hG5Rx].e.K9V~$j^qԫS`*OQS孨~4t~ζ`׬eV=(f^S4L.}  Wl"5Kwq?jS^cXuD$P$|6/n>.3 ޚl8N@=5mBdzf|*^hdg+.n7xA1U: ̟Ur; soGelh)'sl̙_QI+Z @%9oj|ίR`BeTS}^Y]ePLwӥwJ k;q#w;pޢ&!ÜxMo<|E%rxB)aۣ*͝A388PYn(xJ+ -.|FA[Ukqx#G+Q8 zЈ|0ۏTP R ̕:o#[o3FI>V|29{)_ NAԣgFbn[fE `uIpddI;'c+ $)wޱ05q~gh$NcVNC*Nʷ) f~.>#>O]@>#fov9 [!E(OiS! ZUZN~6>Br_pr4@]Q)]qedjP2j < 9 j:}y8Ot~Sr7GGq-h7r#z)Ho*,. ! Eh(9*;O>;? K鰶+Yui?4)ÖRZ9 0Nnd1S3-~ !KHzulxE 6&&w:8=.36v^m62%K0/2e44h/^$_?qM jꓳA퍐o˹[/e"ŇF/8T<6e:sL; |Frm\~n+QziB|k9,UN,6l>N@sg^y㚡IN' kc_Tf8sػY@G|~z2a=+X6z0(Z/zmժ$3#-&A{#6J~h ^"f Oȏ\L+r-d껐^QS~齪EZއ ;'%3.cDOn7Q7~ӌ[8鰰Uc׭e`VwDBޞ P)yRpB3fG&"o>I O,Xtx'( mZr )Nz)L{e[u@& w 2?:y `h(G\_^ @΋haH';,AẚP,Z8l'|3<LL6$*2=`Ds85Z=]v3*NPcXwgY8 'ɢ&z)xްaK-ߗIky`+j'nn6y\90wG|` uԞX J<#[8<8 7CkF趕W0Í.+ IYanE+ zTbng":$L&7rTJ總؛9 %l* Wu.8SE}W° "ߒjEF:ao%/mAXSf0JaF+xƟ]批X-Ӳ-՘\_dQ8g,WGkX&>X4@spU2N|eMVȍL=tżY݀: T;J@Eَ)"{\xY?mӯR6F!Ba?q,"b#"\`7W6ⓎF!&PTXo%{֢}tb? U9zg.$Kfj10\װ'ku}@=Ei8"vi9}kn˃JD#\Wu|{jȈ6f}q 6Msnoi|%W Ŵ%h` gD+Ujr/vGsR7}}:rJMACMh=X}#vIwxW\Mҩ*FD?oUC/:ߑAWSJ\|yܝ^\b}]YfbI(Ens r}}_M1"a5r?&#oqi5+Ip=-d^U U/'A8ǥ@]7p'ȶ e2BP~o47}s+6oxX?Ԭ$O6VT,&vwu 3ѥb 'N8\DlVn7Eתܴ]~z`!(VXVV\Som B %hhԶGTo+{U3XP5t.#zhtVf]?p PN>07T%o4֖vC4)Yw|vfY):ГG U~pxʳdcU>ͧ꬗q1T|IY5\L<Qi,PE%Ǡ3dƔb14 iKsCMTc։z[ O1x>A5ؖk_RN_KO@طvg=`aM_Ĭw]lEDY.VBEYphC7ShdL\Rܻ4t?2 pŀ:.o!kO\MO 599<~-n,+S(Y(J1qi0fs["V{Y$I )~oE3>bun/:+R%_S-[BmC#1h짳lSUYEKJc@}S|hYeB <5F~s^A oke}oM^ ׯnTUᎳ^G okeH,=Eź+t)]Ǘp?aeuy&ˣ Q0F5.?Xk뜾$7Ɗ2J%*Gyć@in$L!J[$߃Ñ5޴ '0@|p,z"ow .M? qq yM /eW8I;*fـmߚAӯrncqPW.}5 yfdrJ-jZgpKDY|R^u 3JX1tR[-?nnbݧi< l^]Mpx{U}u"Miwnܟ6'At'A4V%y%_mYx>P&66'}oݶKfn l md96(ɣ6 ?RJؐ75ȂeB},r*0y:7 57X}ve70<3+l$0 h Z? ҧ_1ET~ igR鳍B;Ճ[!v֟HV5VUOE >螣>sh`CՄ btĴY!]h=Qv%HkO&qy|?M5i?H$乎Rqes@o3Σ)Iy.1EN֞1uA6q&whpP+Lf@(㡽h7yǸFvSi!rx&Wkv8>&f9ז{66"Kj(EG{;l>Ɋ~ܮ9Law͍%f1;YY{mB *}co?Pe!yy`=?+Ae? Si1B;CQbP7 -V1w2U("fЩԨ'C%2@rE˩n\<13 0>Tj@fl|F|uWbz,sZffA4@d Xk$r8c8LdiKo-=&<31kXx8ˆV{?öp_]/p׆hutCBίN7S7=/ n<!t6rʡCvfJ5E7PlDꍲDߣ t]&{+XK܃ž&4ԍ9@h$02ܾc/ 8u충˿ӒV1;LCެcNB^O6wͅ,|By_⫍4U h*xִ?54?tG aqjIo Ϊ_b,LN.s+:֎!?6tWU)ק/L|˜dc> endobj 298 0 obj << /Type /Encoding /Differences [2/fi/fl 30/grave/quotesingle 33/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater 64/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P 82/R/S/T/U/V/W/X/Y/Z/bracketleft 93/bracketright 96/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde 147/quotedblleft/quotedblright/bullet/endash 233/eacute 252/udieresis] >> endobj 113 0 obj << /Type /Font /Subtype /Type1 /BaseFont /UAGOMC+CMBX10 /FontDescriptor 319 0 R /FirstChar 49 /LastChar 49 /Widths 302 0 R >> endobj 24 0 obj << /Type /Font /Subtype /Type1 /BaseFont /IGWSTC+CMEX10 /FontDescriptor 321 0 R /FirstChar 0 /LastChar 112 /Widths 306 0 R >> endobj 18 0 obj << /Type /Font /Subtype /Type1 /BaseFont /QDOZHF+CMMI10 /FontDescriptor 323 0 R /FirstChar 11 /LastChar 122 /Widths 312 0 R >> endobj 59 0 obj << /Type /Font /Subtype /Type1 /BaseFont /VWIWYR+CMMI5 /FontDescriptor 325 0 R /FirstChar 15 /LastChar 120 /Widths 304 0 R >> endobj 20 0 obj << /Type /Font /Subtype /Type1 /BaseFont /YPEFWL+CMMI7 /FontDescriptor 327 0 R /FirstChar 14 /LastChar 120 /Widths 310 0 R >> endobj 19 0 obj << /Type /Font /Subtype /Type1 /BaseFont /YWLPPL+CMR10 /FontDescriptor 329 0 R /FirstChar 22 /LastChar 120 /Widths 311 0 R >> endobj 58 0 obj << /Type /Font /Subtype /Type1 /BaseFont /UZEWHU+CMR5 /FontDescriptor 331 0 R /FirstChar 0 /LastChar 61 /Widths 305 0 R >> endobj 22 0 obj << /Type /Font /Subtype /Type1 /BaseFont /PPERUW+CMR7 /FontDescriptor 333 0 R /FirstChar 0 /LastChar 120 /Widths 308 0 R >> endobj 23 0 obj << /Type /Font /Subtype /Type1 /BaseFont /UFMTYJ+CMSY10 /FontDescriptor 335 0 R /FirstChar 0 /LastChar 106 /Widths 307 0 R >> endobj 60 0 obj << /Type /Font /Subtype /Type1 /BaseFont /XMIFGE+CMSY5 /FontDescriptor 337 0 R /FirstChar 0 /LastChar 49 /Widths 303 0 R >> endobj 21 0 obj << /Type /Font /Subtype /Type1 /BaseFont /QIYSQL+CMSY7 /FontDescriptor 339 0 R /FirstChar 0 /LastChar 112 /Widths 309 0 R >> endobj 154 0 obj << /Type /Font /Subtype /Type1 /BaseFont /XJNOWL+NimbusMonL-Bold /FontDescriptor 341 0 R /FirstChar 109 /LastChar 115 /Widths 300 0 R /Encoding 298 0 R >> endobj 5 0 obj << /Type /Font /Subtype /Type1 /BaseFont /UQJLLM+NimbusMonL-Regu /FontDescriptor 343 0 R /FirstChar 30 /LastChar 148 /Widths 316 0 R /Encoding 298 0 R >> endobj 143 0 obj << /Type /Font /Subtype /Type1 /BaseFont /VWZTXD+NimbusMonL-ReguObli /FontDescriptor 345 0 R /FirstChar 31 /LastChar 126 /Widths 301 0 R /Encoding 298 0 R >> endobj 288 0 obj << /Type /Font /Subtype /Type1 /BaseFont /FYVMNP+NimbusSanL-Regu /FontDescriptor 347 0 R /FirstChar 80 /LastChar 115 /Widths 299 0 R /Encoding 298 0 R >> endobj 6 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ZWVFYU+NimbusRomNo9L-Medi /FontDescriptor 349 0 R /FirstChar 2 /LastChar 122 /Widths 315 0 R /Encoding 298 0 R >> endobj 12 0 obj << /Type /Font /Subtype /Type1 /BaseFont /VCHGJK+NimbusRomNo9L-MediItal /FontDescriptor 351 0 R /FirstChar 109 /LastChar 115 /Widths 313 0 R /Encoding 298 0 R >> endobj 4 0 obj << /Type /Font /Subtype /Type1 /BaseFont /WEWISP+NimbusRomNo9L-Regu /FontDescriptor 353 0 R /FirstChar 2 /LastChar 252 /Widths 317 0 R /Encoding 298 0 R >> endobj 7 0 obj << /Type /Font /Subtype /Type1 /BaseFont /PUACUY+NimbusRomNo9L-ReguItal /FontDescriptor 355 0 R /FirstChar 2 /LastChar 122 /Widths 314 0 R /Encoding 298 0 R >> endobj 8 0 obj << /Type /Pages /Count 6 /Parent 356 0 R /Kids [2 0 R 10 0 R 16 0 R 28 0 R 31 0 R 41 0 R] >> endobj 61 0 obj << /Type /Pages /Count 6 /Parent 356 0 R /Kids [56 0 R 76 0 R 83 0 R 98 0 R 111 0 R 116 0 R] >> endobj 121 0 obj << /Type /Pages /Count 6 /Parent 356 0 R /Kids [119 0 R 132 0 R 135 0 R 138 0 R 141 0 R 145 0 R] >> endobj 150 0 obj << /Type /Pages /Count 6 /Parent 356 0 R /Kids [148 0 R 152 0 R 156 0 R 159 0 R 162 0 R 165 0 R] >> endobj 170 0 obj << /Type /Pages /Count 6 /Parent 356 0 R /Kids [168 0 R 172 0 R 175 0 R 179 0 R 187 0 R 190 0 R] >> endobj 195 0 obj << /Type /Pages /Count 6 /Parent 356 0 R /Kids [193 0 R 198 0 R 201 0 R 210 0 R 213 0 R 216 0 R] >> endobj 221 0 obj << /Type /Pages /Count 6 /Parent 357 0 R /Kids [219 0 R 223 0 R 226 0 R 229 0 R 232 0 R 235 0 R] >> endobj 240 0 obj << /Type /Pages /Count 6 /Parent 357 0 R /Kids [238 0 R 242 0 R 245 0 R 248 0 R 251 0 R 254 0 R] >> endobj 259 0 obj << /Type /Pages /Count 6 /Parent 357 0 R /Kids [257 0 R 262 0 R 265 0 R 273 0 R 276 0 R 279 0 R] >> endobj 284 0 obj << /Type /Pages /Count 5 /Parent 357 0 R /Kids [282 0 R 286 0 R 290 0 R 293 0 R 296 0 R] >> endobj 356 0 obj << /Type /Pages /Count 36 /Parent 358 0 R /Kids [8 0 R 61 0 R 121 0 R 150 0 R 170 0 R 195 0 R] >> endobj 357 0 obj << /Type /Pages /Count 23 /Parent 358 0 R /Kids [221 0 R 240 0 R 259 0 R 284 0 R] >> endobj 358 0 obj << /Type /Pages /Count 59 /Kids [356 0 R 357 0 R] >> endobj 359 0 obj << /Type /Catalog /Pages 358 0 R >> endobj 360 0 obj << /Producer (pdfTeX-1.40.10) /Creator (TeX) /CreationDate (D:20121210154426Z) /ModDate (D:20121210154426Z) /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.1415926-1.40.10-2.2 (TeX Live 2009/Debian) kpathsea version 5.0.0) >> endobj xref 0 361 0000000000 65535 f 0000002084 00000 n 0000001980 00000 n 0000000015 00000 n 0000412570 00000 n 0000411706 00000 n 0000412221 00000 n 0000412741 00000 n 0000412916 00000 n 0000003371 00000 n 0000003265 00000 n 0000002185 00000 n 0000412392 00000 n 0000011460 00000 n 0000013142 00000 n 0000007433 00000 n 0000007326 00000 n 0000003484 00000 n 0000410263 00000 n 0000410690 00000 n 0000410548 00000 n 0000411393 00000 n 0000410971 00000 n 0000411111 00000 n 0000410121 00000 n 0000015767 00000 n 0000017020 00000 n 0000010376 00000 n 0000010269 00000 n 0000007605 00000 n 0000015109 00000 n 0000011353 00000 n 0000010491 00000 n 0000012789 00000 n 0000013020 00000 n 0000013066 00000 n 0000014679 00000 n 0000014907 00000 n 0000014953 00000 n 0000015046 00000 n 0000018876 00000 n 0000015660 00000 n 0000015274 00000 n 0000016669 00000 n 0000016898 00000 n 0000016944 00000 n 0000017858 00000 n 0000018023 00000 n 0000018125 00000 n 0000018207 00000 n 0000018294 00000 n 0000018384 00000 n 0000018478 00000 n 0000018557 00000 n 0000018716 00000 n 0000022391 00000 n 0000022283 00000 n 0000018984 00000 n 0000410832 00000 n 0000410406 00000 n 0000411253 00000 n 0000413024 00000 n 0000026072 00000 n 0000026686 00000 n 0000028236 00000 n 0000028899 00000 n 0000029554 00000 n 0000030211 00000 n 0000030889 00000 n 0000031574 00000 n 0000033252 00000 n 0000033952 00000 n 0000034774 00000 n 0000035519 00000 n 0000036408 00000 n 0000027324 00000 n 0000025964 00000 n 0000022597 00000 n 0000026480 00000 n 0000026640 00000 n 0000027118 00000 n 0000027278 00000 n 0000032290 00000 n 0000028128 00000 n 0000027557 00000 n 0000028693 00000 n 0000028853 00000 n 0000029348 00000 n 0000029508 00000 n 0000030005 00000 n 0000030165 00000 n 0000030683 00000 n 0000030843 00000 n 0000031368 00000 n 0000031528 00000 n 0000032084 00000 n 0000032244 00000 n 0000037181 00000 n 0000033144 00000 n 0000032483 00000 n 0000033744 00000 n 0000033905 00000 n 0000034566 00000 n 0000034727 00000 n 0000035311 00000 n 0000035472 00000 n 0000036200 00000 n 0000036361 00000 n 0000036973 00000 n 0000037134 00000 n 0000041236 00000 n 0000041125 00000 n 0000037364 00000 n 0000409978 00000 n 0000047359 00000 n 0000044597 00000 n 0000044486 00000 n 0000041456 00000 n 0000049507 00000 n 0000047247 00000 n 0000044736 00000 n 0000413136 00000 n 0000048478 00000 n 0000048644 00000 n 0000048749 00000 n 0000048832 00000 n 0000048920 00000 n 0000049011 00000 n 0000049106 00000 n 0000049186 00000 n 0000049346 00000 n 0000053625 00000 n 0000053513 00000 n 0000049686 00000 n 0000057437 00000 n 0000057325 00000 n 0000053845 00000 n 0000058310 00000 n 0000058198 00000 n 0000057610 00000 n 0000060704 00000 n 0000060592 00000 n 0000058426 00000 n 0000411875 00000 n 0000062556 00000 n 0000062444 00000 n 0000060820 00000 n 0000064888 00000 n 0000064776 00000 n 0000062650 00000 n 0000413253 00000 n 0000068253 00000 n 0000068141 00000 n 0000065061 00000 n 0000411534 00000 n 0000071134 00000 n 0000071022 00000 n 0000068440 00000 n 0000073894 00000 n 0000073782 00000 n 0000071239 00000 n 0000075829 00000 n 0000075717 00000 n 0000074057 00000 n 0000078536 00000 n 0000078424 00000 n 0000075969 00000 n 0000081590 00000 n 0000081478 00000 n 0000078664 00000 n 0000413370 00000 n 0000084178 00000 n 0000084066 00000 n 0000081753 00000 n 0000086549 00000 n 0000086437 00000 n 0000084363 00000 n 0000088137 00000 n 0000093252 00000 n 0000088025 00000 n 0000086688 00000 n 0000090029 00000 n 0000090174 00000 n 0000090274 00000 n 0000090311 00000 n 0000090554 00000 n 0000096766 00000 n 0000096654 00000 n 0000093409 00000 n 0000100202 00000 n 0000100090 00000 n 0000096894 00000 n 0000103070 00000 n 0000102958 00000 n 0000100329 00000 n 0000413487 00000 n 0000106044 00000 n 0000104323 00000 n 0000104211 00000 n 0000103232 00000 n 0000115265 00000 n 0000105932 00000 n 0000104417 00000 n 0000111937 00000 n 0000112082 00000 n 0000112182 00000 n 0000112287 00000 n 0000112324 00000 n 0000112567 00000 n 0000118884 00000 n 0000118772 00000 n 0000115386 00000 n 0000120954 00000 n 0000120842 00000 n 0000119068 00000 n 0000123658 00000 n 0000123546 00000 n 0000121083 00000 n 0000127304 00000 n 0000127192 00000 n 0000123820 00000 n 0000413604 00000 n 0000128653 00000 n 0000128541 00000 n 0000127476 00000 n 0000130473 00000 n 0000130361 00000 n 0000128747 00000 n 0000131954 00000 n 0000131842 00000 n 0000130578 00000 n 0000134566 00000 n 0000134454 00000 n 0000132059 00000 n 0000135923 00000 n 0000135811 00000 n 0000134717 00000 n 0000138826 00000 n 0000138714 00000 n 0000136017 00000 n 0000413721 00000 n 0000141672 00000 n 0000141560 00000 n 0000139023 00000 n 0000145325 00000 n 0000145213 00000 n 0000141869 00000 n 0000148573 00000 n 0000148461 00000 n 0000145497 00000 n 0000150556 00000 n 0000150444 00000 n 0000148747 00000 n 0000152698 00000 n 0000152586 00000 n 0000150673 00000 n 0000153928 00000 n 0000153816 00000 n 0000152838 00000 n 0000413838 00000 n 0000157331 00000 n 0000155649 00000 n 0000155537 00000 n 0000154022 00000 n 0000161915 00000 n 0000157219 00000 n 0000155754 00000 n 0000158692 00000 n 0000158837 00000 n 0000158937 00000 n 0000158974 00000 n 0000159217 00000 n 0000163125 00000 n 0000163013 00000 n 0000162072 00000 n 0000165053 00000 n 0000164941 00000 n 0000163219 00000 n 0000167693 00000 n 0000167581 00000 n 0000165169 00000 n 0000168226 00000 n 0000168114 00000 n 0000167787 00000 n 0000413955 00000 n 0000169690 00000 n 0000169578 00000 n 0000168307 00000 n 0000412050 00000 n 0000172447 00000 n 0000172335 00000 n 0000169843 00000 n 0000175273 00000 n 0000175161 00000 n 0000172539 00000 n 0000176261 00000 n 0000176149 00000 n 0000175354 00000 n 0000409425 00000 n 0000176342 00000 n 0000176505 00000 n 0000176552 00000 n 0000176955 00000 n 0000176978 00000 n 0000177331 00000 n 0000177983 00000 n 0000178388 00000 n 0000179084 00000 n 0000179702 00000 n 0000180411 00000 n 0000181116 00000 n 0000181774 00000 n 0000182327 00000 n 0000182968 00000 n 0000183015 00000 n 0000183490 00000 n 0000183967 00000 n 0000184444 00000 n 0000185418 00000 n 0000192427 00000 n 0000192650 00000 n 0000202898 00000 n 0000203402 00000 n 0000221649 00000 n 0000222012 00000 n 0000232901 00000 n 0000233180 00000 n 0000247456 00000 n 0000247792 00000 n 0000261477 00000 n 0000261816 00000 n 0000269962 00000 n 0000270235 00000 n 0000281010 00000 n 0000281338 00000 n 0000289538 00000 n 0000289822 00000 n 0000297140 00000 n 0000297373 00000 n 0000305857 00000 n 0000306164 00000 n 0000311711 00000 n 0000311942 00000 n 0000330208 00000 n 0000330756 00000 n 0000348080 00000 n 0000348662 00000 n 0000352467 00000 n 0000352711 00000 n 0000367898 00000 n 0000368293 00000 n 0000373930 00000 n 0000374171 00000 n 0000394098 00000 n 0000394693 00000 n 0000409060 00000 n 0000414064 00000 n 0000414179 00000 n 0000414281 00000 n 0000414351 00000 n 0000414404 00000 n trailer << /Size 361 /Root 359 0 R /Info 360 0 R /ID [<763EC6EA0AC0C3B2B3BB2A3F9F22BC58> <763EC6EA0AC0C3B2B3BB2A3F9F22BC58>] >> startxref 414659 %%EOF msm/R/0000755000176000001440000000000012061401532011271 5ustar ripleyusersmsm/R/msm.R0000644000176000001440000022330212030037030012204 0ustar ripleyusers### Function to fit Markov multi-state models in continuous time ### with either arbitrary observation times or observed exact transition times ### with or without misclassification between true and underlying states msm <- function(formula, # formula with observed Markov states ~ observation times (required) subject = NULL, # optional, defaults to all the same if not given data=list(), # data frame in which to interpret variable names qmatrix, # matrix of 1s and 0s with indices of allowed transitions (diagonal is ignored) (required) gen.inits = FALSE, # generate initial values for transition intensities using crudeinits.msm ematrix = NULL, # matrix of 1s and 0s with indices of allowed misclassfications (diagonal is ignored) (required) hmodel = NULL, #list of constructors for hidden emission distributions obstype = NULL, # optional, defaults to all 1 (snapshots) if not given obstrue = NULL, # for hidden Markov models, which observations represent the true state covariates = NULL, # formula specifying covariates on transition rates. covinits = NULL, # initial values for covariate effects constraint = NULL, # which intensities have covariates on them (as in Marshall et al.) misccovariates = NULL, # formula specifying covariates on misclassification probs misccovinits = NULL, # initial values for misclassification covariate effects miscconstraint = NULL, # which misc probs have covariates on them hcovariates = NULL, # list of formulae specifying covariates model for each hidden state hcovinits = NULL, # initial values for covariate effects on hidden emission distribution hconstraint = NULL, # constraints on hidden Markov model parameters qconstraint = NULL, # constraints on equality of baseline intensities econstraint = NULL, # constraints on equality of baseline misc probs initprobs = NULL, # initial state occupancy probabilities est.initprobs = FALSE, # should these be estimated, starting from the given values? initcovariates = NULL, # If these are specified, then assume est.initprobs=TRUE, and initprobs gives initial values with these covs set to zero. initcovinits = NULL, death = FALSE, # 'death' states, ie, entry time known exactly, but unknown transient state at previous instant exacttimes = FALSE, # TRUE is shortcut for all obstype 2. censor = NULL, censor.states = NULL, pci = NULL, cl = 0.95, # width of confidence intervals fixedpars = NULL, # specify which parameters to fix. TRUE for all parameters center = TRUE, # center covariates at their means during optimisation opt.method = c("optim","nlm"), hessian = TRUE, use.deriv = TRUE, analyticp = TRUE, ... # options to optim or nlm ) { if (missing(formula)) stop("state ~ time formula not given") subject <- if (missing(subject)) NULL else eval(substitute(subject), data, parent.frame()) obstype <- if (missing(obstype)) NULL else eval(substitute(obstype), data, parent.frame()) obstrue <- if (missing(obstrue)) NULL else eval(substitute(obstrue), data, parent.frame()) if (missing(data)) data <- environment(formula) ### MODEL FOR TRANSITION INTENSITIES qmodel <- msm.form.qmodel(qmatrix, qconstraint, exacttimes, gen.inits, formula, subject, data, censor, censor.states, analyticp) ### MISCLASSIFICATION MODEL if (!missing(ematrix)) { emodel <- msm.form.emodel(ematrix, econstraint, initprobs, est.initprobs, qmodel) } else emodel <- list(misc=FALSE, npars=0, ndpars=0) if (emodel$npars==0) emodel <- list(misc=FALSE, npars=0, ndpars=0) # user supplied degenerate ematrix with no misclassification ### GENERAL HIDDEN MARKOV MODEL if (!missing(hmodel)) { msm.check.hmodel(hmodel, qmodel$nstates) if (!missing(hcovariates)) msm.check.hcovariates(hcovariates, qmodel) hmodel <- msm.form.hmodel(hmodel, hconstraint, initprobs, est.initprobs, qmodel) } else { if (!missing(hcovariates)) stop("hcovariates have been specified, but no hmodel") hmodel <- list(hidden=FALSE, models=rep(0, qmodel$nstates), nipars=0, nicoveffs=0, totpars=0, ncoveffs=0) # might change later if misc } ### CONVERT OLD STYLE MISCLASSIFICATION MODEL TO NEW GENERAL HIDDEN MARKOV MODEL if (emodel$misc) { hmodel <- msm.emodel2hmodel(emodel, qmodel) } else emodel <- list(misc=FALSE, npars=0, ndpars=0, nipars=0, nicoveffs=0) ### DEATH STATES. Logical values allowed for backwards compatibility (TRUE means final state is death, FALSE means no death state) dmodel <- msm.form.dmodel(death, qmodel, hmodel) #returns death, ndeath, if (dmodel$ndeath > 0 && qmodel$exacttimes) warning("Ignoring death argument, as all states have exact entry times") ### CENSORING MODEL cmodel <- msm.form.cmodel(censor, censor.states, qmodel$qmatrix) msmdata.obs <- msm.form.data(formula, subject, obstype, obstrue, covariates, data, hcovariates, misccovariates, initcovariates, qmodel, emodel, hmodel, cmodel, dmodel, exacttimes, center) ### EXPAND DATA AND MODEL FOR TIME DEPENDENT INTENSITIES if (!is.null(pci)) { tdmodel <- msm.pci(pci, msmdata.obs, qmodel, cmodel, center) if (is.null(tdmodel)) # supplied cut points not in range of data pci <- NULL else { cmodel <- tdmodel$cmodel msmdata.obs.orig <- msmdata.obs names(msmdata.obs.orig)[names(msmdata.obs.orig) %in% c("covmat","covmat.orig")] <- c("cov","cov.orig") # used in bootstrap msmdata.obs <- tdmodel$dat pci <- tdmodel$tcut } } if (hmodel$hidden || (cmodel$ncens > 0)) { msmdata <- msm.aggregate.hmmdata(msmdata.obs) msmdata$fromstate <- msmdata$tostate <- msmdata$timelag <- numeric(0) } else { ## To speed calculation of the likelihood for the simple model (no ## HMM or censoring) data are aggregated by distinct fromstate, ## tostate, timelag, covariates combinations msmdata <- msm.obs.to.fromto(msmdata.obs) msm.check.model(msmdata$fromstate, msmdata$tostate, msmdata$obs, msmdata$subject, msmdata$obstype, qmodel$qmatrix, cmodel) msmdata <- msm.aggregate.data(msmdata) msmdata$subject <- msmdata$state <- msmdata$time <- numeric(0) for (i in c("subject", "time", "state", "n")) msmdata[[i]] <- msmdata.obs[[i]] msmdata$obstype.obs <- msmdata.obs$obstype msmdata$firstobs <- msmdata.obs$firstobs } if (is.null(pci)) { msmdata.obs.orig <- NULL msmdata$pci.imp <- rep(0, msmdata$n) } msmdata$cov <- msmdata.obs$covmat msmdata$cov.orig <- msmdata.obs$covmat.orig msmdata$covlabels.orig <- msmdata.obs$covlabels.orig ### MODEL FOR COVARIATES ON INTENSITIES qcmodel <- if (msmdata$covdata$ncovs > 0) msm.form.covmodel(msmdata$covdata, constraint, qmodel$npars, covinits) else { if (!is.null(constraint)) warning("constraint specified but no covariates") list(npars=0, ncovs=0, ndpars=0) } ### MODEL FOR COVARIATES ON MISCLASSIFICATION PROBABILITIES if (!emodel$misc || is.null(misccovariates)) ecmodel <- list(npars=0, ncovs=0) if (!is.null(misccovariates)) { if (!emodel$misc) { warning("misccovariates have been specified, but misc is FALSE. Ignoring misccovariates.") } else { ecmodel <- msm.form.covmodel(msmdata$misccovdata, miscconstraint, emodel$npars, misccovinits) hcovariates <- msm.misccov2hcov(misccovariates, emodel) hcovinits <- msm.misccovinits2hcovinits(misccovinits, hcovariates, emodel, ecmodel) } } ### MODEL FOR COVARIATES ON GENERAL HIDDEN PARAMETERS if (!is.null(hcovariates)) { hmodel <- msm.form.hcmodel(hmodel, msmdata$hcovdata, hcovinits, hconstraint) if (emodel$misc) hmodel$covconstr <- msm.form.hcovconstraint(miscconstraint, hmodel) } else if (hmodel$hidden) { hmodel <- c(hmodel, list(ncovs=rep(rep(0, hmodel$nstates), hmodel$npars), ncoveffs=0)) class(hmodel) <- "hmodel" } if (!is.null(initcovariates)) { if (hmodel$hidden) hmodel <- msm.form.icmodel(hmodel, msmdata$icovdata, initcovinits) else warning("initprobs and initcovariates ignored for non-hidden Markov models") } else if (hmodel$hidden) { hmodel <- c(hmodel, list(nicovs=rep(0, hmodel$nstates-1), nicoveffs=0)) class(hmodel) <- "hmodel" } if (hmodel$hidden && !emodel$misc) { hmodel$constr <- msm.form.hconstraint(hconstraint, hmodel) hmodel$covconstr <- msm.form.hcovconstraint(hconstraint, hmodel) } ### FORM LIST OF INITIAL PARAMETERS, MATCHING PROVIDED INITS WITH SPECIFIED MODEL, FIXING SOME PARS IF REQUIRED p <- msm.form.params(qmodel, qcmodel, emodel, hmodel, fixedpars, est.initprobs) ### CALCULATE LIKELIHOOD AT INITIAL VALUES... if (p$fixed) { p$lik <- lik.msm(p$inits, msmdata, qmodel, qcmodel, cmodel, hmodel, p) p$deriv <- if (!hmodel$hidden && cmodel$ncens==0) deriv.msm(p$inits, msmdata, qmodel, qcmodel, cmodel, hmodel, p) else NULL p$params.uniq <- p$allinits[!duplicated(abs(p$constr))] p$params <- p$allinits[!duplicated(abs(p$constr))][abs(p$constr)]*sign(p$constr) p$foundse <- FALSE p$covmat <- NULL } ### ... OR DO MAXIMUM LIKELIHOOD ESTIMATION else { p$params <- p$allinits gr <- if (!hmodel$hidden && cmodel$ncens==0 && use.deriv) deriv.msm else NULL opt.method <- match.arg(opt.method) if (opt.method == "optim") { optim.args <- list(...) if (is.null(optim.args$method)) optim.args$method <- if (length(p$inits)==1) "BFGS" else "Nelder-Mead" optim.args <- c(optim.args, list(par=p$inits, fn=lik.msm, hessian=hessian, gr=gr, msmdata=msmdata, qmodel=qmodel, qcmodel=qcmodel, cmodel=cmodel, hmodel=hmodel, paramdata=p)) opt <- do.call("optim", optim.args) p$lik <- opt$value p$deriv <- if (!hmodel$hidden && cmodel$ncens==0) deriv.msm(opt$par, msmdata, qmodel, qcmodel, cmodel, hmodel, p) else NULL p$params[p$optpars] <- opt$par } else if (opt.method == "nlm") { nlmfn <- function(par) { ret <- lik.msm(par, msmdata=msmdata, qmodel=qmodel, qcmodel=qcmodel, cmodel=cmodel, hmodel=hmodel, paramdata=p) if (!is.null(gr)) attr(ret, "gradient") <- deriv.msm(par, msmdata=msmdata, qmodel=qmodel, qcmodel=qcmodel, cmodel=cmodel, hmodel=hmodel, paramdata=p) ret } opt <- nlm(nlmfn, p$inits, hessian=hessian, ...) p$lik <- opt$minimum p$deriv <- if (!hmodel$hidden && cmodel$ncens==0) deriv.msm(opt$estimate, msmdata, qmodel, qcmodel, cmodel, hmodel, p) else NULL p$params[p$optpars] <- opt$estimate } p$opt <- opt ## Replicate constrained pars. (Replicate pr, not log(pr/pbase), then recalculate baseline) p$params[p$hmmpars] <- msm.mninvlogit.transform(p$params[p$hmmpars], hmodel$plabs, hmodel$parstate) p$params.uniq <- p$params[!duplicated(abs(p$constr))] p$params <- p$params[!duplicated(abs(p$constr))][abs(p$constr)]*sign(p$constr) if (hessian && all(!is.na(opt$hessian)) && all(!is.nan(opt$hessian)) && all(is.finite(opt$hessian)) && all(eigen(opt$hessian)$values > 0)) { p$foundse <- TRUE p$covmat <- matrix(0, nrow=p$npars, ncol=p$npars) p$covmat[p$optpars,p$optpars] <- solve(0.5 * opt$hessian) p$covmat.uniq <- p$covmat[!duplicated(abs(p$constr)),!duplicated(abs(p$constr)), drop=FALSE] p$covmat <- p$covmat[!duplicated(abs(p$constr)),!duplicated(abs(p$constr)), drop=FALSE][abs(p$constr),abs(p$constr), drop=FALSE] p$ci <- cbind(p$params - qnorm(1 - 0.5*(1-cl))*sqrt(diag(p$covmat)), p$params + qnorm(1 - 0.5*(1-cl))*sqrt(diag(p$covmat))) p$ci[p$fixedpars,] <- NA } else { p$foundse <- FALSE p$covmat <- p$ci <- NULL if (hessian) warning("Could not calculate asymptotic standard errors - Hessian is not positive definite. Optimisation has not converged to the maximum likelihood") } p$params[p$hmmpars] <- msm.recalc.basep(p$params[p$hmmpars], hmodel$plabs, hmodel$parstate) p$params[p$hmmpars] <- msm.mnlogit.transform(p$params[p$hmmpars], hmodel$plabs, hmodel$parstate) } p$estimates.t <- p$params # Calculate estimates and CIs on natural scale p$estimates.t[p$hmmpars] <- msm.mninvlogit.transform(p$estimates.t[p$hmmpars], hmodel$plabs, hmodel$parstate) for (lab in rownames(.msm.TRANSFORMS)) { p$estimates.t[p$plabs==lab] <- get(.msm.TRANSFORMS[lab,"inv"])(p$params[p$plabs==lab]) if (p$foundse) p$ci[p$plabs==lab] <- get(.msm.TRANSFORMS[lab,"inv"])(p$ci[p$plabs==lab, ]) } ## calculate CIs for misclassification probabilities (needs multivariate transform and delta method) if (any(p$plabs=="p")){ if (p$foundse) { p.se <- p.se.msm(qmodel,emodel,hmodel,qcmodel,ecmodel,p,center, covariates = if(center) "mean" else 0) if (p$foundse) p$ci[p$plabs %in% c("p","pbase"),] <- as.numeric(unlist(p.se[,c("LCL","UCL")])) } } ### REARRANGE THE VECTOR OF PARAMETER ESTIMATES (LOG-INTENSITIES, MISC PROBS AND ### COVARIATE EFFECTS) INTO LISTS OF MATRICES output <- msm.form.output("intens", qmodel, qcmodel, p) Qmatrices <- output$Matrices QmatricesSE <- if (p$fixed) NULL else output$MatricesSE QmatricesL <- if (p$fixed) NULL else output$MatricesL QmatricesU <- if (p$fixed) NULL else output$MatricesU if (emodel$misc) { output <- msm.form.output("misc", emodel, ecmodel, p) Ematrices <- output$Matrices EmatricesSE <- if (p$fixed) NULL else output$MatricesSE EmatricesL <- if (p$fixed) NULL else output$MatricesL EmatricesU <- if (p$fixed) NULL else output$MatricesU names(Ematrices)[1] <- "logitbaseline" if (p$foundse & !p$fixed) names(EmatricesSE)[1] <- names(EmatricesL)[1] <- names(EmatricesU)[1] <- "logitbaseline" } else { Ematrices <- EmatricesSE <- EmatricesL <- EmatricesU <- NULL } if (hmodel$hidden) { hmodel <- msm.form.houtput(hmodel, p) } ### FORM A MSM OBJECT FROM THE RESULTS msmobject <- list ( call = match.call(), Qmatrices = Qmatrices, QmatricesSE = QmatricesSE, QmatricesL = QmatricesL, QmatricesU = QmatricesU, minus2loglik = p$lik, deriv = p$deriv, estimates = p$params, estimates.t = p$estimates.t, fixedpars = p$fixedpars, center = center, covmat = p$covmat, ci = p$ci, opt = p$opt, foundse = p$foundse, data = msmdata, data.orig = msmdata.obs.orig, # before any pci imputation, NULL if no pci qmodel = qmodel, emodel = emodel, qcmodel = qcmodel, ecmodel = ecmodel, hmodel = hmodel, cmodel = cmodel, pci = pci, paramdata=p ) attr(msmobject, "fixed") <- p$fixed class(msmobject) <- "msm" q <- qmatrix.msm(msmobject, covariates=(if(center) "mean" else 0)) # intensity matrix on natural scale msmobject$Qmatrices$baseline <- q$estimates msmobject$QmatricesSE$baseline <- q$SE msmobject$QmatricesL$baseline <- q$L msmobject$QmatricesU$baseline <- q$U if (emodel$misc) { msmobject$Ematrices <- Ematrices msmobject$EmatricesSE <- EmatricesSE msmobject$EmatricesL <- EmatricesL msmobject$EmatricesU <- EmatricesU e <- ematrix.msm(msmobject, covariates=(if(center) "mean" else 0)) # misc matrix on natural scale msmobject$Ematrices$baseline <- e$estimates msmobject$EmatricesSE$baseline <- e$SE msmobject$EmatricesL$baseline <- e$L msmobject$EmatricesU$baseline <- e$U } ## Calculate mean sojourn times at baseline msmobject$sojourn <- sojourn.msm(msmobject, covariates=(if(center) "mean" else 0)) msmobject } msm.check.qmatrix <- function(qmatrix) { if (!is.numeric(qmatrix) || ! is.matrix(qmatrix)) stop("qmatrix should be a numeric matrix") if (nrow(qmatrix) != ncol(qmatrix)) stop("Number of rows and columns of qmatrix should be equal") q2 <- qmatrix; diag(q2) <- 0 if (any(q2 < 0)) stop("off-diagonal entries of qmatrix should not be negative") invisible() } msm.fixdiag.qmatrix <- function(qmatrix) { diag(qmatrix) <- 0 diag(qmatrix) <- - rowSums(qmatrix) qmatrix } msm.fixdiag.ematrix <- function(ematrix) { diag(ematrix) <- 0 diag(ematrix) <- 1 - rowSums(ematrix) ematrix } msm.form.qmodel <- function(qmatrix, qconstraint=NULL, exacttimes=FALSE, gen.inits=FALSE, formula, subject, data, censor, censor.states, analyticp) { if (gen.inits) qmatrix <- crudeinits.msm(formula, subject, qmatrix, data, censor, censor.states) msm.check.qmatrix(qmatrix) nstates <- dim(qmatrix)[1] qmatrix <- msm.fixdiag.qmatrix(qmatrix) if (is.null(rownames(qmatrix))) rownames(qmatrix) <- colnames(qmatrix) <- paste("State", seq(nstates)) else if (is.null(colnames(qmatrix))) colnames(qmatrix) <- rownames(qmatrix) imatrix <- ifelse(qmatrix > 0, 1, 0) inits <- t(qmatrix)[t(imatrix)==1] npars <- sum(imatrix) if (!is.null(qconstraint)) { if (!is.numeric(qconstraint)) stop("qconstraint should be numeric") if (length(qconstraint) != npars) stop("baseline intensity constraint of length " ,length(qconstraint), ", should be ", npars) constr <- match(qconstraint, unique(qconstraint)) } else constr <- 1:npars ndpars <- max(constr) ipars <- t(imatrix)[t(lower.tri(imatrix) | upper.tri(imatrix))] graphid <- paste(which(ipars==1), collapse="-") if (graphid %in% names(.msm.graphs[[paste(nstates)]])) { ## analytic P matrix is implemented for this particular intensity matrix iso <- .msm.graphs[[paste(nstates)]][[graphid]]$iso perm <- .msm.graphs[[paste(nstates)]][[graphid]]$perm iperm <- match(1:nstates, perm) imatrix.ind <- t(imatrix) imatrix.ind[t(imatrix)>0] <- 1:npars imatrix.ind <- t(imatrix.ind) qperm <- imatrix.ind[iperm,iperm] qperm <- t(qperm)[t(qperm)>0] } else { iso <- 0 perm <- qperm <- NA } qmodel <- list(nstates=nstates, analyticp=analyticp, iso=iso, perm=perm, qperm=qperm, npars=npars, imatrix=imatrix, qmatrix=qmatrix, inits=inits, constr=constr, ndpars=ndpars, exacttimes=exacttimes) class(qmodel) <- "msmqmodel" qmodel } msm.check.ematrix <- function(ematrix, nstates) { if (!is.numeric(ematrix) || ! is.matrix(ematrix)) stop("ematrix should be a numeric matrix") if (nrow(ematrix) != ncol(ematrix)) stop("Number of rows and columns of ematrix should be equal") if (!all(dim(ematrix) == nstates)) stop("Dimensions of qmatrix and ematrix should be the same") if (!all ( ematrix >= 0 | ematrix <= 1) ) stop("Not all elements of ematrix are between 0 and 1") invisible() } msm.form.emodel <- function(ematrix, econstraint=NULL, initprobs=NULL, est.initprobs, qmodel) { msm.check.ematrix(ematrix, qmodel$nstates) diag(ematrix) <- 0 imatrix <- ifelse(ematrix > 0 & ematrix < 1, 1, 0) diag(ematrix) <- 1 - rowSums(ematrix) if (is.null(rownames(ematrix))) rownames(ematrix) <- colnames(ematrix) <- paste("State", seq(qmodel$nstates)) else if (is.null(colnames(ematrix))) colnames(ematrix) <- rownames(ematrix) dimnames(imatrix) <- dimnames(ematrix) npars <- sum(imatrix) nstates <- nrow(ematrix) inits <- t(ematrix)[t(imatrix)==1] if (is.null(initprobs)) { initprobs <- if (est.initprobs) rep(1/qmodel$nstates, qmodel$nstates) else c(1, rep(0, qmodel$nstates-1)) } else { if (!is.numeric(initprobs)) stop("initprobs should be numeric") if (length(initprobs) != qmodel$nstates) stop("initprobs of length ", length(initprobs), ", should be ", qmodel$nstates) initprobs <- initprobs / sum(initprobs) } nipars <- qmodel$nstates - 1 if (!is.null(econstraint)) { if (!is.numeric(econstraint)) stop("econstraint should be numeric") if (length(econstraint) != npars) stop("baseline misclassification constraint of length " ,length(econstraint), ", should be ", npars) constr <- match(econstraint, unique(econstraint)) } else constr <- seq(length=npars) ndpars <- if(npars>0) max(constr) else 0 # handle degenerate ematrix with no misclassification emodel <- list(misc=TRUE, npars=npars, nstates=nstates, imatrix=imatrix, ematrix=ematrix, inits=inits, constr=constr, ndpars=ndpars, nipars=nipars, initprobs=initprobs) class(emodel) <- "msmemodel" emodel } ### Extract data from supplied arguments, check consistency, drop missing data. ### Returns dataframe of cleaned data in observation time format ### Covariates returned in covmat msm.form.data <- function(formula, subject=NULL, obstype=NULL, obstrue=NULL, covariates=NULL, data=NULL, hcovariates=NULL, misccovariates=NULL, initcovariates=NULL, qmodel, emodel, hmodel, cmodel, dmodel, exacttimes, center) { ## Parse the model formula of subject and time, getting missing values if (!inherits(formula, "formula")) stop("\"formula\" argument should be a formula") mf <- model.frame(formula, data=data) state <- mf[,1] if (!hmodel$hidden || emodel$misc) msm.check.state(qmodel$nstates, state=state, cmodel$censor) ## replace after splitting form.hmodel time <- mf[,2] droprows <- as.numeric(attr(mf, "na.action")) n <- length(c(state, droprows)) statetimerows.kept <- (1:n)[! ((1:n) %in% droprows)] if (is.null(subject)) subject <- rep(1, nrow(mf)) obstype <- msm.form.obstype(obstype, n, state, statetimerows.kept, dmodel, exacttimes) obstrue <- msm.form.obstrue(obstrue, nrow(mf), hmodel) subjrows.kept <- (1:n) [!is.na(subject)] otrows.kept <- statetimerows.kept[!is.na(obstype)] omrows.kept <- statetimerows.kept[!is.na(obstrue)] ## Don't drop NA covariates on the transition process at the subject's final observation, since they are not used lastobs <- c(which(subject[1:(n-1)] != subject[2:n]), n) ##Parse covariates formula and extract data covdata <- misccovdata <- icovdata <- list(ncovs=0, covmat=numeric(0)) if (!is.null(covariates)) { covdata <- msm.form.covdata(covariates, data, lastobs, center) } if (!is.null(misccovariates) && emodel$misc) { misccovdata <- msm.form.covdata(misccovariates, data, NULL, center) hcovariates <- lapply(ifelse(rowSums(emodel$imatrix)>0, deparse(misccovariates), deparse(~1)), as.formula) } hcovdata <- vector(qmodel$nstates, mode="list") if (!is.null(hcovariates)) { for (i in seq(qmodel$nstates)) { if (!is.null(hcovariates) && !is.null(hcovariates[[i]])) hcovdata[[i]] <- msm.form.covdata(hcovariates[[i]], data, NULL, center) else hcovdata[[i]] <- list(ncovs=0) } } ## Only drop NA covariates on initprobs at initial observation firstobs <- c(1, which(subject[2:n] != subject[1:(n-1)]) + 1) if (!is.null(initcovariates)) { icovdata <- msm.form.covdata(initcovariates, data, !firstobs, center) } ## List of which covariates are in which model all.covlabels <- unique(c(covdata$covlabels, unlist(lapply(hcovdata, function(x)x$covlabels)), icovdata$covlabels)) # factors as numeric contrasts orig.covlabels <- unique(c(covdata$covlabels.orig, unlist(lapply(hcovdata, function(x)x$covlabels.orig)), icovdata$covlabels.orig)) # factors as single variables covdata$whichcov <- match(covdata$covlabels, all.covlabels) covdata$whichcov.orig <- match(covdata$covlabels.orig, orig.covlabels) if(!is.null(hcovariates)) { for (i in seq(along=hcovdata)){ hcovdata[[i]]$whichcov <- match(hcovdata[[i]]$covlabels, all.covlabels) hcovdata[[i]]$whichcov.orig <- match(hcovdata[[i]]$covlabels.orig, orig.covlabels) } } if (!is.null(initcovariates)) icovdata$whichcov <- match(icovdata$covlabels, all.covlabels) ## Drop missing data final.rows <- intersect(statetimerows.kept, subjrows.kept) final.rows <- intersect(final.rows, otrows.kept) final.rows <- intersect(final.rows, omrows.kept) if (covdata$ncovs > 0) final.rows <- intersect(final.rows, covdata$covrows.kept) if (!is.null(hcovariates)) for (i in seq(along=hcovariates)) if (hcovdata[[i]]$ncovs > 0) final.rows <- intersect(final.rows, hcovdata[[i]]$covrows.kept) if (icovdata$ncovs > 0) final.rows <- intersect(final.rows, icovdata$covrows.kept) subject <- subject[final.rows] time <- subset(time, statetimerows.kept %in% final.rows) state <- subset(state, statetimerows.kept %in% final.rows) msm.check.times(time, subject, state) obstype <- subset(obstype, statetimerows.kept %in% final.rows) obstrue <- subset(obstrue, statetimerows.kept %in% final.rows) covmat <- covmat.orig <- numeric() if (covdata$ncovs > 0) { covmat <- subset(covdata$covmat, covdata$covrows.kept %in% final.rows) covmat.orig <- subset(covdata$covmat.orig, covdata$covrows.kept %in% final.rows) covdata$covmat <- covdata$covmat.orig <- NULL } for (i in seq(along=hcovariates)) { if (hcovdata[[i]]$ncovs > 0) { hcovdata[[i]]$covmat <- subset(hcovdata[[i]]$covmat, hcovdata[[i]]$covrows.kept %in% final.rows) hcovdata[[i]]$covmat.orig <- subset(hcovdata[[i]]$covmat.orig, hcovdata[[i]]$covrows.kept %in% final.rows) covmat <- cbind(covmat, as.matrix(hcovdata[[i]]$covmat)) covmat.orig <- cbind(covmat.orig, as.matrix(hcovdata[[i]]$covmat.orig)) hcovdata[[i]]$covmat <- hcovdata[[i]]$covmat.orig <- NULL } } if (icovdata$ncovs > 0) { icovdata$covmat <- subset(icovdata$covmat, icovdata$covrows.kept %in% final.rows) icovdata$covmat.orig <- subset(icovdata$covmat.orig, icovdata$covrows.kept %in% final.rows) covmat <- cbind(covmat, as.matrix(icovdata$covmat)) covmat.orig <- cbind(covmat.orig, as.matrix(icovdata$covmat.orig)) icovdata$covmat <- icovdata$covmat.orig <- NULL } if (length(all.covlabels) > 0) { covmat <- as.data.frame(covmat, optional=TRUE)[all.covlabels] covmat.orig <- as.data.frame(covmat.orig, optional=TRUE)[orig.covlabels] } nobs <- length(final.rows) nmiss <- n - nobs plural <- if (nmiss==1) "" else "s" if (nmiss > 0) warning(nmiss, " record", plural, " dropped due to missing values") dat <- list(state=state, time=time, subject=subject, obstype=obstype, obstrue=obstrue, nobs=nobs, n=nobs, npts=length(unique(subject)), firstobs = c(1, which(subject[2:n] != subject[1:(n-1)]) + 1, n+1), ncovs=length(all.covlabels), covlabels=all.covlabels, covlabels.orig=orig.covlabels, covdata=covdata, misccovdata=misccovdata, hcovdata=hcovdata, icovdata=icovdata, covmat=covmat, # covariates including factors as 0/1 contrasts covmat.orig=covmat.orig # covariates in which a factor is a single variable ) class(dat) <- "msmdata" dat } ### Check elements of state vector. For simple models and misc models specified with ematrix ### No check is performed for hidden models msm.check.state <- function(nstates, state=NULL, censor) { statelist <- if (nstates==2) "1, 2" else if (nstates==3) "1, 2, 3" else paste("1, 2, ... ,",nstates) states <- c(1:nstates, censor) if (!is.null(state)) { if (length(setdiff(unique(state), states)) > 0) stop("State vector contains elements not in ",statelist) miss.state <- setdiff(states, unique(state)) if (length(miss.state) > 0) warning("State vector doesn't contain observations of ",paste(miss.state, collapse=",")) } invisible() } msm.check.times <- function(time, subject, state=NULL) { ### Check if any individuals have only one observation (after excluding missing data) subj.num <- match(subject,unique(subject)) # avoid problems with factor subjects with empty levels nobspt <- table(subj.num) if (any (nobspt == 1)) { badsubjs <- unique(subject)[ nobspt == 1 ] andothers <- if (length(badsubjs)>3) " and others" else "" if (length(badsubjs)>3) badsubjs <- badsubjs[1:3] badlist <- paste(badsubjs, collapse=", ") plural <- if (length(badsubjs)==1) "" else "s" has <- if (length(badsubjs)==1) "has" else "have" warning ("Subject", plural, " ", badlist, andothers, " only ", has, " one complete observation") } ### Check if observations within a subject are adjacent ind <- tapply(1:length(subj.num), subj.num, length) imin <- tapply(1:length(subj.num), subj.num, min) imax <- tapply(1:length(subj.num), subj.num, max) adjacent <- (ind == imax-imin+1) if (any (!adjacent)) { badsubjs <- unique(subject)[ !adjacent ] andothers <- if (length(badsubjs)>3) " and others" else "" if (length(badsubjs)>3) badsubjs <- badsubjs[1:3] badlist <- paste(badsubjs, collapse=", ") plural <- if (length(badsubjs)==1) "" else "s" stop ("Observations within subject", plural, " ", badlist, andothers, " are not adjacent in the data") } ### Check if observations are ordered in time within subject orderedpt <- ! tapply(time, subj.num, is.unsorted) if (any (!orderedpt)) { badsubjs <- unique(subject)[ !orderedpt ] andothers <- if (length(badsubjs)>3) " and others" else "" if (length(badsubjs)>3) badsubjs <- badsubjs[1:3] badlist <- paste(badsubjs, collapse=", ") plural <- if (length(badsubjs)==1) "" else "s" stop ("Observations within subject", plural, " ", badlist, andothers, " are not ordered by time") } ### Check if any consecutive observations are made at the same time, but with different states if (!is.null(state)){ prevsubj <- c(-Inf, subj.num[1:length(subj.num)-1]) prevtime <- c(-Inf, time[1:length(time)-1]) prevstate <- c(-Inf, state[1:length(state)-1]) sametime <- (subj.num==prevsubj & prevtime==time & prevstate!=state) badlist <- paste(paste(which(sametime)-1, which(sametime), sep=" and "), collapse=", ") if (any(sametime)) warning("Different states observed at the same time on the same subject at observations ", badlist) } invisible() } ### Convert observation time data to from-to format msm.obs.to.fromto <- function(dat) { n <- length(dat$state) subj.num <- match(dat$subject, unique(dat$subject)) prevsubj <- c(-Inf, subj.num[1:(n-1)]) firstsubj <- subj.num != prevsubj nextsubj <- c(subj.num[2:n], Inf) lastsubj <- subj.num != nextsubj fromstate <- c(-Inf, dat$state[1:(n-1)])[!firstsubj] tostate <- dat$state[!firstsubj] timelag <- diff(dat$time)[!firstsubj[-1]] subject <- dat$subject[!firstsubj] obstype <- dat$obstype[!firstsubj] obs <- seq(n)[!firstsubj] datf <- list(fromstate=fromstate, tostate=tostate, timelag=timelag, subject=subject, obstype=obstype, time=dat$time, obs=obs, firstsubj=firstsubj, npts=dat$npts, ncovs=dat$ncovs, covlabels=dat$covlabels, obstype.obs=dat$obstype, # need to keep this, e.g. for bootstrap resampling. covdata=dat$covdata, hcovdata=dat$hcovdata) if (datf$ncovs > 0) { ##match time-dependent covariates with the start of the transition # datf <- c(datf, subset(as.data.frame(dat[dat$covlabels], optional=TRUE), !lastsubj)) datf$covmat <- subset(as.data.frame(dat$covmat, optional=TRUE), !lastsubj) } ##n.b. don't need to use this function for misc models class(datf) <- "msmfromtodata" datf } ## Replace censored states by state with highest probability that they ## could represent. Used in msm.check.model to check consistency of ## data with transition parameters msm.impute.censored <- function(fromstate, tostate, Pmat, cmodel) { ##e.g. cmodel$censor 99,999; cmodel$states 1,2,1,2,3; cmodel$index 1, 3, 6 ## Both from and to are censored wb <- which ( fromstate %in% cmodel$censor & tostate %in% cmodel$censor) for (i in wb) { si <- which(cmodel$censor==fromstate[i]) fc <- cmodel$states[(cmodel$index[si]) : (cmodel$index[si+1]-1)] ti <- which(cmodel$censor==tostate[i]) tc <- cmodel$states[(cmodel$index[ti]) : (cmodel$index[ti+1]-1)] mp <- which.max(Pmat[fc, tc]) fromstate[i] <- fc[row(Pmat[fc, tc])[mp]] tostate[i] <- tc[col(Pmat[fc, tc])[mp]] } ## Only from is censored wb <- which(fromstate %in% cmodel$censor) for (i in wb) { si <- which(cmodel$censor==fromstate[i]) fc <- cmodel$states[(cmodel$index[si]) : (cmodel$index[si+1]-1)] fromstate[i] <- fc[which.max(Pmat[fc, tostate[i]])] } ## Only to is censored wb <- which(tostate %in% cmodel$censor) for (i in wb) { si <- which(cmodel$censor==tostate[i]) tc <- cmodel$states[(cmodel$index[si]) : (cmodel$index[si+1]-1)] tostate[i] <- tc[which.max(Pmat[fromstate[i], tc])] } list(fromstate=fromstate, tostate=tostate) } ### CHECK THAT TRANSITION PROBABILITIES FOR DATA ARE ALL NON-ZERO ### (e.g. check for backwards transitions when the model is irreversible) ### obstype 1 must have unitprob > 0 ### obstype 2 must have qunit != 0, and unitprob > 0. ### obstype 3 must have unitprob > 0 msm.check.model <- function(fromstate, tostate, obs, subject, obstype=NULL, qmatrix, cmodel) { n <- length(fromstate) qmatrix <- qmatrix / mean(qmatrix[qmatrix>0]) # rescale to avoid false warnings with small rates Pmat <- MatrixExp(qmatrix) Pmat[Pmat < 1e-16] <- 0 imputed <- msm.impute.censored(fromstate, tostate, Pmat, cmodel) fs <- imputed$fromstate; ts <- imputed$tostate unitprob <- apply(cbind(fs, ts), 1, function(x) { Pmat[x[1], x[2]] } ) qunit <- apply(cbind(fs, ts), 1, function(x) { qmatrix[x[1], x[2]] } ) if (identical(all.equal(min(unitprob, na.rm=TRUE), 0), TRUE)) { badobs <- which.min(unitprob) warning ("Data may be inconsistent with transition matrix for model without misclassification:\n", "individual ", if(is.null(subject)) "" else subject[badobs], " moves from state ", fromstate[badobs], " to state ", tostate[badobs], " at non-missing observation ", obs[badobs], "\n") } if (any(qunit[obstype==2]==0)) { badobs <- min (obs[qunit==0 & obstype==2], na.rm = TRUE) warning ("Data may be inconsistent with intensity matrix for observations with exact transition times and no misclassification:\n", "individual ", if(is.null(subject)) "" else subject[obs==badobs], " moves from state ", fromstate[obs==badobs], " to state ", tostate[obs==badobs], " at non-missing observation ", badobs) } absorbing <- absorbing.msm(qmatrix=qmatrix) absabs <- (fromstate %in% absorbing) & (tostate %in% absorbing) if (any(absabs)) { badobs <- min( obs[absabs] ) warning("Absorbing - absorbing transition at non-missing observation ", badobs) } invisible() } ## Extract covariate information from a formula. ## Find which columns and which rows to keep from the original data msm.form.covdata <- function(covariates, data, ignore.obs, center=TRUE) { if (!inherits(covariates, "formula")) stop(deparse(substitute(covariates)), " should be a formula") mf1 <- model.frame(covariates, data=data, na.action=NULL) ## We shouldn't drop NA covariates at the subject's final ## observation, since they are not used in the analysis, therefore ## we impute observed zeros when final observations are NA. mf.imp <- mf1 for (i in names(mf.imp)) if (!is.null(ignore.obs)) mf.imp[ignore.obs,i][is.na(mf.imp[ignore.obs,i])] <- if (is.factor(mf.imp[,i])) levels(mf.imp[,i])[1] else 0 mm <- na.omit(as.data.frame(model.matrix(covariates, data=mf.imp))) n <- nrow(mf.imp) covlabels <- names(mm)[-1] ncovs <- length(covlabels) mm <- subset(mm, select=-1) mf2 <- na.omit(mf.imp) droprows <- as.numeric(attr(mf2, "na.action")) covrows.kept <- (1:n)[! ((1:n) %in% droprows)] covfactor <- sapply(mf2, is.factor) covfactorlevels <- lapply(mf2, levels) ## for consistency with version 0.7 and earlier, don't include imputed last obs when calculating covariate means covmeans <- apply(na.omit(model.matrix(covariates, data=data)), 2, mean, na.rm=TRUE)[-1] ## centre the covariates about their means if requested if (center && ncovs > 0) mm <- sweep(mm, 2, covmeans) colnames(mm) <- covlabels # ( ) in names are converted into . in sweep, breaks factor covs covdata <- list(covlabels=covlabels, ncovs=ncovs, covmeans=covmeans, covfactor=covfactor, covfactorlevels=covfactorlevels, covmat=mm, # data with factors as set of 0/1 contrasts, and centered. (for model fitting) covmat.orig=mf2, # with factors kept as one variable, and not centered (for bootstrap refitting) covlabels.orig=colnames(mf2), covrows.kept=covrows.kept) class(covdata) <- "msmcovdata" covdata } ### Aggregate the data by distinct values of time lag, covariate values, from state, to state, observation type ### Result is passed to the C likelihood function (for non-hidden multi-state models) msm.aggregate.data <- function(dat) { dat2 <- as.data.frame(dat[c("fromstate","tostate","timelag","obstype")], optional=TRUE) dat2$covmat <- dat$covmat nobsf <- length(dat2$fromstate) apaste <- do.call("paste", c(dat2[,c("fromstate","tostate","timelag","obstype")], dat2$covmat)) msmdata <- dat2[!duplicated(apaste),] msmdata <- msmdata[order(unique(apaste)),] msmdata$nocc <- as.numeric(table(apaste)) apaste2 <- msmdata[,"timelag"] if (dat$ncovs > 0) apaste2 <- paste(apaste2, do.call("paste", msmdata$covmat)) ## which unique timelag/cov combination each row of aggregated data corresponds to ## lik.c needs this to know when to recalculate the P matrix. msmdata$whicha <- match(apaste2, unique(apaste2)) msmdata <- as.list(msmdata[order(apaste2),]) msmdata <- c(msmdata, dat[c("covdata", "hcovdata", "npts", "covlabels")]) msmdata$nobs <- length(msmdata[[1]]) class(msmdata) <- "msmaggdata" msmdata } ###Make indicator for which distinct from, to, timelag, covariate combination each observation corresponds to ### HMM only. This indicator is not used at the moment, but may be in the future. msm.aggregate.hmmdata <- function(dat) { dat2 <- msm.obs.to.fromto(dat) firstsubj <- dat2$firstsubj dat2 <- as.data.frame(c(dat2[c("fromstate","tostate","timelag")], dat2$covmat), optional=TRUE) apaste <- as.character(do.call("paste", dat2)) dat$whicha <- rep(0, dat$nobs) dat$whicha[!firstsubj] <- match(apaste, unique(apaste)) ## index of patient's first observation, plus extra element for ## last person's last observation plus one. This is used. dat$firstobs <- c(which(firstsubj), dat$nobs+1) dat } ### Process covariates constraints, in preparation for being passed to the likelihood optimiser ### This function is called for both sets of covariates (transition rates and the misclassification probs) msm.form.covmodel <- function(covdata, constraint, nmatrix, # number of transition intensities / misclassification probs covinits ) { ncovs <- covdata$ncovs covlabels <- covdata$covlabels covlabels.orig <- covdata$covlabels.orig covfactor <- covdata$covfactor if (is.null(constraint)) { constraint <- rep(list(1:nmatrix), ncovs) names(constraint) <- covlabels constr <- 1:(nmatrix*ncovs) } else { if (!is.list(constraint)) stop(deparse(substitute(constraint)), " should be a list") if (!all(sapply(constraint, is.numeric))) stop(deparse(substitute(constraint)), " should be a list of numeric vectors") if (!all(names(constraint) %in% covlabels)) stop("covariate ", paste(setdiff(names(constraint), covlabels), collapse=", "), " in ", deparse(substitute(constraint)), " unknown") ## check and parse the list of constraints on covariates for (i in names(constraint)) if (!(is.element(i, covlabels))){ factor.warn <- if (covfactor[i]) "\n\tFor factor covariates, specify constraints using covnameCOVVALUE = c(...)" else "" stop("Covariate \"", i, "\" in constraint statement not in model.", factor.warn) } constr <- inits <- numeric() maxc <- 0 for (i in seq(along=covlabels)){ ## build complete vectorised list of constraints for covariates in covariates statement ## so. e.g. constraints = (x1=c(3,3,4,4,5), x2 = (0.1,0.2,0.3,0.4,0.4)) ## turns into constr = c(1,1,2,2,3,4,5,6,7,7) with seven distinct covariate effects ## Allow constraints such as: some elements are minus others. Use negative elements of constr to do this. ## e.g. constr = c(1,1,-1,-1,2,3,4,5) ## obtained by match(abs(x), unique(abs(x))) * sign(x) if (is.element(covlabels[i], names(constraint))) { if (length(constraint[[covlabels[i]]]) != nmatrix) stop("\"",names(constraint)[i],"\" constraint of length ", length(constraint[[covlabels[i]]]),", should be ",nmatrix) } else constraint[[covlabels[i]]] <- seq(nmatrix) constr <- c(constr, (maxc + match(abs(constraint[[covlabels[i]]]), unique(abs(constraint[[covlabels[i]]]))))*sign(constraint[[covlabels[i]]]) ) maxc <- max(abs(constr)) } } inits <- numeric() if (!is.null(covinits)) { if (!is.list(covinits)) warning(deparse(substitute(covinits)), " should be a list") else if (!all(sapply(covinits, is.numeric))) warning(deparse(substitute(covinits)), " should be a list of numeric vectors") else if (!all(names(covinits) %in% covlabels)) warning("covariate ", paste(setdiff(names(covinits), covlabels), collapse=", "), " in ", deparse(substitute(covinits)), " unknown") } for (i in seq(along=covlabels)) { if (!is.null(covinits) && is.element(covlabels[i], names(covinits))) { thisinit <- covinits[[covlabels[i]]] if (!is.numeric(thisinit)) { warning("initial values for covariates should be numeric, ignoring") thisinit <- rep(0, nmatrix) } if (length(thisinit) != nmatrix) { warning("\"", covlabels[i], "\" initial values of length ", length(thisinit), ", should be ", nmatrix, ", ignoring") thisinit <- rep(0, nmatrix) } inits <- c(inits, thisinit) } else { inits <- c(inits, rep(0, nmatrix)) } } npars <- ncovs*nmatrix ndpars <- max(unique(abs(constr))) ## which covariate each distinct covariate parameter corresponds to. Used in C (FormDQCov) whichdcov <- rep(1:ncovs, each=nmatrix)[!duplicated(abs(constr))] list(npars=npars, ndpars=ndpars, # number of distinct covariate effect parameters ncovs=ncovs, constr=constr, whichdcov=whichdcov, covlabels=covlabels, # factors as separate contrasts covlabels.orig=covlabels.orig, # factors as one variable inits = inits, covmeans=covdata$covmeans ) } msm.form.dmodel <- function(death, qmodel, hmodel) { nstates <- qmodel$nstates statelist <- if (nstates==2) "1, 2" else if (nstates==3) "1, 2, 3" else paste("1, 2, ... ,",nstates) if (is.logical(death) && death==TRUE) states <- nstates else if (is.logical(death) && death==FALSE) states <- numeric(0) ##Will be changed to -1 when passing to C else if (!is.numeric(death)) stop("Death states indicator must be numeric") else if (length(setdiff(death, 1:nstates)) > 0) stop("Death states indicator contains states not in ",statelist) else states <- death ndeath <- length(states) if (hmodel$hidden) { ## Form death state info from hmmIdent parameters. ## Special observations in outcome data which denote death states ## are given as the parameter to hmmIdent() if (!all(hmodel$models[states] == match("identity", .msm.HMODELS))) stop("Death states should have the identity hidden distribution hmmIdent()") obs <- ifelse(hmodel$npars[states]>0, hmodel$pars[hmodel$parstate %in% states], states) } else obs <- states if (any (states %in% transient.msm(qmatrix=qmodel$qmatrix))) stop("Not all the \"death\" states are absorbing states") list(ndeath=ndeath, states=states, obs=obs) } msm.form.cmodel <- function(censor=NULL, censor.states=NULL, qmatrix) { if (is.null(censor)) { ncens <- 0 if (!is.null(censor.states)) warning("censor.states supplied but censor not supplied") } else { if (!is.numeric(censor)) stop("censor must be numeric") if (any(censor %in% 1:nrow(qmatrix))) warning("some censoring indicators are the same as actual states") ncens <- length(censor) if (is.null(censor.states)) { if (ncens > 1) { warning("more than one type of censoring given, but censor.states not supplied. Assuming only one type of censoring") ncens <- 1; censor <- censor[1] } absorbing <- absorbing.msm(qmatrix=qmatrix) if (!length(absorbing)) { warning("No absorbing state and no censor.states supplied. Ignoring censoring.") ncens <- 0 } else { transient <- setdiff(seq(length=nrow(qmatrix)), absorbing) censor.states <- transient states.index <- c(1, length(censor.states)+1) } } else { if (ncens == 1) { if (!is.vector(censor.states) || (is.list(censor.states) && (length(censor.states) > 1)) ) stop("if one type of censoring, censor.states should be a vector, or a list with one vector element") if (!is.numeric(unlist(censor.states))) stop("censor.states should be all numeric") states.index <- c(1, length(unlist(censor.states))+1) } else { if (!is.list(censor.states)) stop("censor.states should be a list") if (length(censor.states) != ncens) stop("expected ", ncens, " elements in censor.states list, found ", length(censor.states)) states.index <- cumsum(c(0, lapply(censor.states, length))) + 1 } censor.states <- unlist(censor.states) } } if (ncens==0) censor <- censor.states <- states.index <- NULL ## Censoring information to be passed to C list(ncens = ncens, # number of censoring states censor = censor, # vector of their labels in the data states = censor.states, # possible true states that the censoring represents index = states.index # index into censor.states for the start of each true-state set, including an extra length(censor.states)+1 ) } ### Observation scheme ### 1: snapshots, ### 2: exact transition times (states unchanging between observation times), ### 3: death (exact entry time but state at previous instant unknown) msm.form.obstype <- function(obstype, nobs, state, notna, dmodel, exacttimes) { if (!is.null(obstype)) { if (!is.numeric(obstype)) stop("obstype should be numeric") if (length(obstype) == 1) obstype <- rep(obstype, nobs) else if (length(obstype) != nobs) stop("obstype of length ", length(obstype), ", expected 1 or ", nobs) if (any(! obstype %in% 1:3)) stop("elements of obstype should be 1, 2, or 3") } else if (!is.null(exacttimes) && exacttimes) obstype <- rep(2, nobs) else { obstype <- rep(1, nobs) if (dmodel$ndeath > 0) obstype[notna][state %in% dmodel$obs] <- 3 } obstype[notna] } msm.form.obstrue <- function(obstrue, nobs, hmodel) { if (!is.null(obstrue)) { if (!is.numeric(obstrue) && !is.logical(obstrue)) stop("obstrue should be logical or numeric") else if (length(obstrue) != nobs) stop("obstrue of length ", length(obstrue), ", expected ", nobs) if (!hmodel$hidden) warning("Specified obstrue for a non-hidden model, ignoring.") } else if (hmodel$hidden) obstrue <- rep(0, nobs) else obstrue <- rep(1, nobs) obstrue } ### Transform set of sets of probs {prs} to {log(prs/pr1)} msm.mnlogit.transform <- function(pars, plabs, states){ res <- pars if (any(plabs=="p")) { whichst <- match(states[plabs == "p"], unique(states[plabs == "p"])) res[plabs == "p"] <- log(pars[plabs=="p"] / pars[plabs=="pbase"][whichst]) } res } ### Recalculate baseline misclassification probabilities to be 1 - the sum of the rest msm.recalc.basep <- function(pars, plabs, states){ res <- pars if (any(plabs=="p")) { psum <- tapply(pars[plabs=="p"], states[plabs=="p"], sum) whichst <- match(states[plabs == "p"], unique(states[plabs == "p"])) res[plabs == "pbase"] <- 1 - psum } res } ### Transform set of sets of murs = {log(prs/pr1)} to probs {prs} ### ie psum = sum(exp(mus)), pr1 = 1 / (1 + psum), prs = exp(mus) / (1 + psum) msm.mninvlogit.transform <- function(pars, plabs, states){ res <- pars if (any(plabs=="p")) { psum <- tapply(exp(pars[plabs=="p"]), states[plabs=="p"], sum) res[plabs=="pbase"] <- 1 / (1 + psum) whichst <- match(states[plabs=="p"], unique(states[plabs=="p"])) res[plabs=="p"] <- exp(pars[plabs=="p"]) / (1 + psum[whichst]) } res } msm.form.params <- function(qmodel, qcmodel, emodel, hmodel, fixedpars, est.initprobs) { ## Categories of parameter: inits <- c(qmodel$inits, qcmodel$inits) ## Transition intensities ni <- qmodel$npars ## Covariates on transition intensities nc <- qcmodel$npars; plabs <- c(rep("qbase",ni), rep("qcov", nc)) ## HMM response parameters nh <- sum(hmodel$npars) ## Covariates on HMM response distribution nhc <- sum(hmodel$ncoveffs) ## Initial state occupancy probabilities in HMM nip <- hmodel$nipars ## Covariates on initial state occupancy probabilities. nipc <- hmodel$nicoveffs npars <- ni + nc + nh + nhc + nip + nipc hmodel$pars <- msm.mnlogit.transform(hmodel$pars, hmodel$plabs, hmodel$parstate) inits <- c(inits, hmodel$pars, unlist(hmodel$coveffect)) plabs <- c(plabs, hmodel$plabs, rep("hcov", nhc)) if (nip > 0) { inits <- c(inits, hmodel$initprobs[-1]) initplabs <- rep("initp",nip) initplabs[hmodel$initprobs[-1]==0] <- "initp0" # those initialised to zero will be fixed at zero plabs <- c(plabs, initplabs) if (nipc > 0) { inits <- c(inits, unlist(hmodel$icoveffect)) plabs <- c(plabs, rep("initpcov",nipc)) } } ## store indicator for which parameters are HMM location parameters (not HMM cov effects or initial state probs) hmmpars <- which(!(plabs %in% c("qbase","qcov","hcov","initp","initp0","initpcov"))) for (lab in rownames(.msm.TRANSFORMS)) inits[plabs==lab] <- get(.msm.TRANSFORMS[lab,"fn"])(inits[plabs==lab]) names(inits) <- plabs ## Form constraint vector for complete set of parameters ## No constraints allowed on initprobs and their covs for the moment constr <- c(qmodel$constr, if(is.null(qcmodel$constr)) NULL else (ni + abs(qcmodel$constr))*sign(qcmodel$constr), ni + nc + hmodel$constr, ni + nc + nh + hmodel$covconstr, ni + nc + nh + nhc + seq(length=nip), ni + nc + nh + nip + seq(length=nipc)) constr <- match(abs(constr), unique(abs(constr)))*sign(constr) ## parameters which are always fixed and not included in user-supplied fixedpars auxpars <- which(plabs %in% .msm.AUXPARS) duppars <- which(duplicated(abs(constr))) naux <- length(auxpars) ndup <- length(duppars) realpars <- setdiff(seq(npars), union(auxpars, duppars)) nrealpars <- npars - naux - ndup if (is.logical(fixedpars)) fixedpars <- if (fixedpars == TRUE) seq(nrealpars) else numeric() if (any(! (fixedpars %in% seq(along=realpars)))) stop ( "Elements of fixedpars should be in 1, ..., ", npars - naux - ndup) fixedpars <- sort(c(realpars[fixedpars], auxpars)) if (!est.initprobs) fixedpars <- union(fixedpars, which(plabs %in% c("initp","initp0","initpcov"))) notfixed <- setdiff(seq(npars), fixedpars) allinits <- inits nfix <- length(fixedpars) optpars <- intersect(notfixed, which(!duplicated(abs(constr)))) nopt <- length(optpars) inits <- inits[optpars] fixed <- (nfix + ndup == npars) # TRUE if all parameters are fixed, then no optim needed, just eval likelihood names(allinits) <- plabs; names(fixedpars) <- plabs[fixedpars]; names(plabs) <- NULL paramdata <- list(inits=inits, plabs=plabs, allinits=allinits, hmmpars=hmmpars, fixed=fixed, notfixed=notfixed, optpars=optpars, fixedpars=fixedpars, constr=constr, npars=npars, nfix=nfix, nopt=nopt, ndup=ndup) paramdata } ### Wrapper for the C code which evaluates the -2*log-likelihood for a Markov multi-state model with misclassification ### This is optimised by optim likderiv.msm <- function(params, deriv=0, msmdata, qmodel, qcmodel, cmodel, hmodel, paramdata) { do.what <- deriv p <- paramdata pars <- p$allinits; plabs <- p$plabs pars[p$optpars] <- params ## Untransform parameters optimized on log/logit scale for (lab in rownames(.msm.TRANSFORMS)) pars[plabs==lab] <- get(.msm.TRANSFORMS[lab,"inv"])(pars[plabs==lab]) ## Before replication, transform probs on log(pr/pbase scale) back to pr scale, ## so that econstraint applies to pr not log(pr/pbase). After, transform back. pars[p$hmmpars] <- msm.mninvlogit.transform(pars[p$hmmpars], hmodel$plabs, hmodel$parstate) ## Replicate constrained parameters plabs <- plabs[!duplicated(abs(p$constr))][abs(p$constr)] pars <- pars[!duplicated(abs(p$constr))][abs(p$constr)]*sign(p$constr) pars[p$hmmpars] <- msm.mnlogit.transform(pars[p$hmmpars], hmodel$plabs, hmodel$parstate) ## In R, work with states / parameter indices / model indices 1, ... n. In C, work with 0, ... n-1 msmdata$fromstate <- msmdata$fromstate - 1 msmdata$tostate <- msmdata$tostate - 1 msmdata$firstobs <- msmdata$firstobs - 1 hmodel$models <- hmodel$models - 1 hmodel$links <- hmodel$links - 1 pars[plabs == "p"] <- exp(pars[plabs == "p"]) initprobs <- c(1 - sum(pars[plabs=="initp"]), pars[plabs %in% c("initp","initp0")]) initprobs <- initprobs / initprobs[1] ## initprobs[1] documented as not allowed to be zero. if (!do.what %in% c(0,1,3)) stop("deriv should be 0, 1 or 3") lik <- .C("msmCEntry", as.integer(do.what), as.integer(as.vector(t(qmodel$imatrix))), as.double(pars[plabs=="qbase"]), as.double(as.vector(t(matrix(pars[plabs=="qcov"], nrow=qmodel$npars)))), as.double(pars[!(plabs %in% c("qbase", "qcov", "hcov","initp","initp0","initpcov"))]), as.double(pars[plabs=="hcov"]), ## data for non-HMM as.integer(msmdata$fromstate), as.integer(msmdata$tostate), as.double(msmdata$timelag), as.double(unlist(msmdata$covmat)), # covariate matrix by unique transition (non-HMM) or by obs (HMM/cens) as.double(unlist(msmdata$cov)), # covariate matrix by observation (non-HMM and calculating derivs by individual) as.integer(msmdata$covdata$whichcov), # this is really part of the model as.integer(msmdata$nocc), as.integer(msmdata$whicha), as.integer(if(do.what==3) msmdata$obstype.obs else msmdata$obstype), # need per-observation obstype when doing derivs by subject. ## data for HMM or censored as.integer(match(msmdata$subject, unique(msmdata$subject))), as.double(msmdata$time), as.double(msmdata$state), # If this is a misc or censored state, this is indexed from 1. as.integer(msmdata$firstobs), as.integer(msmdata$obstrue), ## HMM specification as.integer(hmodel$hidden), as.integer(hmodel$models), as.integer(hmodel$npars), as.integer(hmodel$totpars), as.integer(hmodel$firstpar), as.integer(hmodel$ncovs), as.integer(hmodel$whichcovh), as.integer(hmodel$links), as.double(initprobs), as.integer(hmodel$nicovs), as.double(pars[plabs=="initpcov"]), as.integer(hmodel$whichcovi), ## various constants as.integer(qmodel$nstates), as.integer(qmodel$analyticp), as.integer(qmodel$iso), as.integer(qmodel$perm), as.integer(qmodel$qperm), as.integer(qmodel$npars), as.integer(qmodel$ndpars), as.integer(qcmodel$ndpars), as.integer(msmdata$nobs), # number of aggregated observations as.integer(msmdata$n), # number of observations as.integer(msmdata$npts), # HMM only as.integer(rep(qcmodel$ncovs, qmodel$npars)), as.integer(cmodel$ncens), as.integer(cmodel$censor), as.integer(cmodel$states), as.integer(cmodel$index - 1), ## constraints needed in C to calculate derivatives as.integer(qmodel$constr), as.integer(qcmodel$constr), as.integer(qcmodel$whichdcov), returned = double(if (deriv==1) qmodel$ndpars + qcmodel$ndpars else if (deriv==3) msmdata$npts*(qmodel$ndpars + qcmodel$ndpars) else 1), ## so that Inf values are allowed for parameters denoting truncation points of truncated distributions NAOK = TRUE # , # PACKAGE = "msm" ) ## transform derivatives wrt Q to derivatives wrt log Q if (deriv==1) { lik$returned[1:qmodel$ndpars] <- if (length(params)==0) lik$returned[1:qmodel$ndpars]*exp(p$allinits[!duplicated(p$constr)][1:qmodel$ndpars]) else lik$returned[1:qmodel$ndpars]*exp(params[1:qmodel$ndpars]) lik$returned <- lik$returned[setdiff(seq(along=lik$returned), p$constr[p$fixedpars])] } ## subject-specific derivatives, to use for score residuals else if (deriv==3) { lik$returned <- matrix(lik$returned, nrow=msmdata$npts) lik$returned[,1:qmodel$ndpars] <- if (length(params)==0) lik$returned[,1:qmodel$ndpars]*rep(exp(p$allinits[!duplicated(p$constr)][1:qmodel$ndpars]), each=msmdata$npts) else lik$returned[,1:qmodel$ndpars]*rep(exp(params[1:qmodel$ndpars]), each=msmdata$npts) lik$returned <- lik$returned[,setdiff(seq(length=ncol(lik$returned)), p$constr[p$fixedpars])] } lik$returned } lik.msm <- function(params, ...) { likderiv.msm(params, deriv=0, ...) } deriv.msm <- function(params, ...) { likderiv.msm(params, deriv=1, ...) } ## Convert vector of MLEs into matrices msm.form.output <- function(whichp, model, cmodel, p) { Matrices <- MatricesSE <- MatricesL <- MatricesU <- list() for (i in 0:cmodel$ncovs) { matrixname <- if (i==0) "logbaseline" else cmodel$covlabels[i] # name of the current output matrix. mat <- t(model$imatrix) # I fill matrices by row, while R fills them by column. Is this sensible...? if (whichp=="intens") parinds <- if (i==0) which(p$plabs=="qbase") else which(p$plabs=="qcov")[(i-1)*model$npars + 1:model$npars] if (whichp=="misc") parinds <- if (i==0) which(p$plabs=="p") else which(p$plabs=="hcov")[i + cmodel$ncovs*(1:model$npars - 1)] mat[t(model$imatrix)==1] <- p$params[parinds] mat <- t(mat) dimnames(mat) <- dimnames(model$imatrix) if (p$foundse && !p$fixed){ intenscov <- p$covmat[parinds, parinds] intensse <- sqrt(diag(as.matrix(intenscov))) semat <- lmat <- umat <- t(model$imatrix) semat[t(model$imatrix)==1] <- intensse lmat[t(model$imatrix)==1] <- p$ci[parinds,1] umat[t(model$imatrix)==1] <- p$ci[parinds,2] semat <- t(semat); lmat <- t(lmat); umat <- t(umat) diag(semat) <- diag(lmat) <- diag(umat) <- 0 dimnames(semat) <- dimnames(mat) } else if (!p$fixed){ semat <- lmat <- umat <- NULL } Matrices[[matrixname]] <- mat if (!p$fixed) { MatricesSE[[matrixname]] <- semat MatricesL[[matrixname]] <- lmat MatricesU[[matrixname]] <- umat } } list(Matrices=Matrices, # list of baseline log intensities/logit misc probability matrix # and linear effects of covariates MatricesSE=MatricesSE, # corresponding matrices of standard errors MatricesL=MatricesL, # corresponding matrices of standard errors MatricesU=MatricesU # corresponding matrices of standard errors ) } ## Format hidden Markov model estimates and CIs msm.form.houtput <- function(hmodel, p) { hmodel$pars <- p$estimates.t[!(p$plabs %in% c("qbase","qcov","hcov","initp","initp0","initpcov"))] hmodel$coveffect <- p$estimates.t[p$plabs == "hcov"] hmodel$fitted <- !p$fixed hmodel$foundse <- p$foundse if (hmodel$nip > 0) { if (hmodel$foundse) { initpsum <- sum(p$estimates.t[p$plabs == "initp"]) hmodel$initprobs <- rbind(c(1 - initpsum, NA, NA), cbind(p$estimates.t[p$plabs %in% c("initp","initp0")], p$ci[p$plabs %in% c("initp","initp0"),,drop=FALSE])) rownames(hmodel$initprobs) <- paste("State",1:hmodel$nstates) colnames(hmodel$initprobs) <- c("Estimate", "LCL", "UCL") if (any(hmodel$nicovs > 0)) { covnames <- names(hmodel$icoveffect) hmodel$icoveffect <- cbind(p$estimates.t[p$plabs == "initpcov"], p$ci[p$plabs == "initpcov",,drop=FALSE]) iplabs <- p$plabs[p$plabs %in% c("initp","initp0")] whichst <- which(iplabs == "initp") + 1 # init probs for which states have covs on them (not the zero probs) rownames(hmodel$icoveffect) <- paste(covnames, paste("State",whichst), sep=", ") colnames(hmodel$icoveffect) <- c("Estimate", "LCL", "UCL") } } else { hmodel$initprobs <- c(1 - sum(p$estimates.t[p$plabs == "initp"]), p$estimates.t[p$plabs %in% c("initp","initp0")]) names(hmodel$initprobs) <- paste("State", 1:hmodel$nstates) if (any(hmodel$nicovs > 0)) { covnames <- names(hmodel$icoveffect) hmodel$icoveffect <- p$estimates.t[p$plabs == "initpcov"] names(hmodel$icoveffect) <- paste(covnames, paste("State",2:hmodel$nstates), sep=", ") } } } if (hmodel$foundse) { hmodel$ci <- p$ci[!(p$plabs %in% c("qbase","qcov","hcov","initp","initp0","initpcov")), , drop=FALSE] hmodel$covci <- p$ci[p$plabs %in% c("hcov"), ] } names(hmodel$pars) <- hmodel$plabs hmodel } ## Table of 'transitions': previous state versus current state statetable.msm <- function(state, subject, data=NULL) { if(!is.null(data)) { data <- as.data.frame(data) state <- eval(substitute(state), data, parent.frame()) } n <- length(state) if (!is.null(data)) subject <- if(missing(subject)) rep(1,n) else eval(substitute(subject), data, parent.frame()) subject <- match(subject, unique(subject)) prevsubj <- c(NA, subject[1:(n-1)]) previous <- c(NA, state[1:(n-1)]) previous[prevsubj!=subject] <- NA ntrans <- table(previous, state) names(dimnames(ntrans)) <- c("from", "to") ntrans } ## Calculate crude initial values for transition intensities by assuming observations represent the exact transition times # if (nmiss > 0) warning(nmiss, " record", plural, " dropped due to missing values") crudeinits.msm <- function(formula, subject, qmatrix, data=NULL, censor=NULL, censor.states=NULL) { cens <- msm.form.cmodel(censor, censor.states, qmatrix) mf <- model.frame(formula, data=data, na.action=NULL) state <- mf[,1] time <- mf[,2] n <- length(state) if (missing(subject)) subject <- rep(1, n) if (!is.null(data)) subject <- eval(substitute(subject), as.list(data), parent.frame()) subject <- match(subject, unique(subject)) notna <- !is.na(subject) & !is.na(time) & !is.na(state) subject <- subject[notna]; time <- time[notna]; state <- state[notna] msm.check.qmatrix(qmatrix) msm.check.state(nrow(qmatrix), state, cens$censor) nocens <- (! (state %in% cens$censor) ) state <- state[nocens]; subject <- subject[nocens]; time <- time[nocens] n <- length(state) nextsubj <- c(subject[2:n], NA) lastsubj <- (subject != nextsubj) timecontrib <- ifelse(lastsubj, NA, c(time[2:n], 0) - time) tottime <- tapply(timecontrib[!lastsubj], state[!lastsubj], sum) # total time spent in each state ntrans <- statetable.msm(state, subject, data=NULL) # table of transitions nst <- nrow(qmatrix) estmat <- matrix(0, nst, nst) rownames(estmat) <- colnames(estmat) <- paste(1:nst) tab <- sweep(ntrans, 1, tottime, "/") for (i in 1:nst) # Include zero rows for states for which there were no transitions for (j in 1:nst) if ((paste(i) %in% rownames(tab)) && (paste(j) %in% colnames(tab))) estmat[paste(i), paste(j)] <- tab[paste(i),paste(j)] estmat[qmatrix == 0] <- 0 # estmat <- msm.fixdiag.qmatrix(estmat) rownames(estmat) <- rownames(qmatrix) colnames(estmat) <- colnames(qmatrix) estmat } ### Construct a model with time-dependent transition intensities. ### Form a new dataset with censored states and extra covariate, and ### form a new censor model, given change times in tcut msm.pci <- function(tcut, dat, qmodel, cmodel, center) { if (!is.numeric(tcut)) stop("Expected \"tcut\" to be a numeric vector of change points") old <- as.data.frame(dat[c("subject","time","state","obstype","obstrue")]) if (dat$ncovs > 0) old[c("covmat","covmat.orig")] <- dat[c("covmat","covmat.orig")] ## new dataset ntcut <- length(tcut) nextra <- ntcut*dat$npts extra <- data.frame(subject = rep(unique(dat$subject), each=ntcut), time = rep(tcut, dat$npts), state = rep(NA, nextra), obstype = rep(1, nextra), obstrue = rep(TRUE, nextra), pci.imp = 1 ) old$pci.imp <- 0 if (dat$ncovs > 0){ extra$covmat <- as.data.frame(matrix(NA, nrow=nextra, ncol=ncol(old$covmat))) extra$covmat.orig <- as.data.frame(matrix(NA, nrow=nextra, ncol=ncol(old$covmat.orig))) rownames(old$covmat.orig) <- rownames(old$covmat) <- 1:nrow(old) rownames(extra$covmat.orig) <- rownames(extra$covmat) <- nrow(old) + 1:nrow(extra) # get rid of dup / null rownames errors } ## merge new and old observations new <- rbind(old, extra) new <- new[order(new$subject, new$time),] label <- if (cmodel$ncens > 0) max(cmodel$censor)*2 else qmodel$nstates + 1 new$state[is.na(new$state)] <- label ## Only keep cutpoints within range of each patient's followup mintime <- tapply(old$time, old$subject, min)[as.character(unique(old$subject))] maxtime <- tapply(old$time, old$subject, max)[as.character(unique(old$subject))] nobspt <- as.numeric(table(new$subject)[as.character(unique(new$subject))]) new <- new[new$time >= rep(mintime, nobspt) & new$time <= rep(maxtime, nobspt), ] ## drop imputed observations at times when there was already an observation ## assumes there wasn't already duplicated obs times prevsubj <- c(NA,new$subject[1:(nrow(new)-1)]); nextsubj <- c(new$subject[2:nrow(new)], NA) prevtime <- c(NA,new$time[1:(nrow(new)-1)]); nexttime <- c(new$time[2:nrow(new)], NA) prevstate <- c(NA,new$state[1:(nrow(new)-1)]); nextstate <- c(new$state[2:nrow(new)], NA) new <- new[!((new$subject==prevsubj & new$time==prevtime & new$state==label & prevstate!=label) | (new$subject==nextsubj & new$time==nexttime & new$state==label & nextstate!=label)) ,] ## Carry last value forward for other covariates if (dat$ncovs > 0) { eind <- which(is.na(new$covmat[,1])) while(length(eind) > 0){ new$covmat[eind,] <- new$covmat[eind - 1,] new$covmat.orig[eind,] <- new$covmat.orig[eind - 1,] eind <- which(is.na(new$covmat[,1])) } } ## constants in dataset new <- as.list(new) new$nobs <- new$n <- n <- length(new$state) new$npts <- dat$npts new$firstobs <- c(1, which(new$subject[2:n] != new$subject[1:(n-1)]) + 1, n+1) new$ncovs <- dat$ncovs + ntcut ## Check range of cut points if (any(tcut <= min(dat$time))) warning("Time cut point", if (sum(tcut <= min(dat$time)) > 1) "s " else " ", paste(tcut[tcut<=min(dat$time)],collapse=","), " less than or equal to minimum observed time of ",min(dat$time)) if (any(tcut >= max(dat$time))) warning("Time cut point", if (sum(tcut >= max(dat$time)) > 1) "s " else " ", paste(tcut[tcut>=max(dat$time)],collapse=","), " greater than or equal to maximum observed time of ",max(dat$time)) tcut <- tcut[tcut > min(dat$time) & tcut < max(dat$time)] ntcut <- length(tcut) if (ntcut==0) res <- NULL # no cut points in range of data, continue with no time-dependent model else { ## Insert new covariate in data representing time period tcovlabel <- "timeperiod" while (tcovlabel %in% dat$covlabels) tcovlabel <- paste(tcovlabel, ".1", sep="") tcov <- factor(cut(new$time, c(-Inf,tcut,Inf), right=FALSE)) levs <- levels(tcov) levels(tcov) <- gsub(" ","", levs) # get rid of spaces in e.g. [10, Inf) levels assign(tcovlabel, tcov) mm <- model.matrix(as.formula(paste("~", tcovlabel)))[,-1,drop=FALSE] new$covmat <- cbind(new$covmat, mm) new$covmat.orig <- if(is.null(new$covmat.orig)) data.frame(timeperiod=tcov) else cbind(new$covmat.orig, timeperiod=tcov) if (center) new$covmat <- sweep(new$covmat, 2, colMeans(new$covmat)) ## new censoring model cmodel$ncens <- cmodel$ncens + 1 cmodel$censor <- c(cmodel$censor, label) cmodel$states <- c(cmodel$states, 1:qmodel$nstates) cmodel$index <- if (is.null(cmodel$index)) 1 else cmodel$index cmodel$index <- c(cmodel$index, length(cmodel$states) + 1) ## new auxiliary information about covariates for (i in c("covdata","misccovdata","hcovdata","icovdata")) new[[i]] <- dat[[i]] new$covlabels <- c(dat$covlabels, colnames(mm)) new$covlabels.orig <- c(dat$covlabels.orig, tcovlabel) new$covdata$covlabels <- c(dat$covdata$covlabels, colnames(mm)) new$covdata$ncovs <- dat$covdata$ncovs + ntcut new$covdata$covmeans <- c(dat$covdata$covmeans, colMeans(mm)) new$covdata$covfactor <- c(dat$covdata$covfactor, timeperiod=TRUE) new$covdata$covfactorlevels <- c(dat$covdata$covfactorlevels, list(timeperiod=levels(tcov))) new$covdata$covlabels.orig <- c(dat$covdata$covlabels.orig, tcovlabel) new$covdata$whichcov <- match(new$covdata$covlabels, new$covlabels) new$covdata$whichcov.orig <- match(new$covdata$covlabels.orig, new$covlabels.orig) res <- list(dat=new, cmodel=cmodel, tcut=tcut) } res } ### Unload shared library when package is detached with unloadNamespace("msm") .onUnload <- function(libpath) { library.dynam.unload("msm", libpath) } msm/R/pearson.R0000644000176000001440000010216212006004317013064 0ustar ripleyusers### Pearson-type goodness-of fit test (Aguirre-Hernandez and Farewell, 2002; Titman and Sharples, 2007) ### TODO for pci models, don't group by pearson.msm <- function(x, transitions=NULL, timegroups=3, intervalgroups=3, covgroups=3, groups=NULL, boot=FALSE, B=500, next.obstime=NULL, # user-supplied next observation times, if known. N=100, indep.cens=TRUE, # use censoring times when calculating the empirical distribution of sampling times maxtimes=NULL # upper limit for imputed next observation times ) { dat <- x$data ## Error handling if (!inherits(x, "msm")) stop("expected \"x\" t to be a msm model") if (x$hmodel$hidden && !x$emodel$misc) stop("only HMMs handled are misclassification models specified using \"ematrix\"") if (any(dat$obstype==2)) stop("exact transition times are not supported, only panel-observed data") if (!is.null(transitions) && !is.numeric(transitions)) stop("expected \"transitions\" to be numeric") if (!is.numeric(timegroups) || length(timegroups) != 1) stop ("expected \"timegroups\" to be a single number") if (!is.numeric(intervalgroups) || length(intervalgroups) != 1) stop ("expected \"intervalgroups\" to be a single number") if (!is.numeric(covgroups) || length(covgroups) != 1) stop ("expected \"covgroups\" to be a single number") if (!is.numeric(B) || length(B) != 1) stop ("expected \"B\" to be a single number") if (!is.numeric(N) || length(N) != 1) stop ("expected \"N\" to be a single number") ## Use only one covariate group for pci models with no other covariates if (!is.null(x$pci) && length(grep("timeperiod\\[([0-9]+|Inf),([0-9]+|Inf)\\)", x$qcmodel$covlabels)) == x$qcmodel$ncovs) covgroups <- 1 ## Label various constants nst <- x$qmodel$nstates exact.death <- any(dat$obstype == 3) dstates <- if (exact.death) absorbing.msm(x) else NULL ndstates <- if (exact.death) transient.msm(x) else 1:nst nndstates <- length(ndstates) ## Add a few useful variables to the data obstypename <- if (x$hmodel$hidden || x$cmodel$ncens > 0) "obstype" else "obstype.obs" od <- as.data.frame(dat[c("subject","time","state",obstypename)]) ncovs <- x$qcmodel$ncovs if (ncovs > 0) od$cov <- dat$cov.orig od$state <- factor(od$state, levels=sort(unique(od$state))) n <- dat$n od$ind <- 1:n # index into original data (useful if any rows of od are dropped) od$prevstate <- factor(c(NA,od$state[1:(n-1)]), levels=1:nndstates) od$prevtime <- c(NA, od$time[1:(n-1)]) od$firstobs <- rep(tapply(1:n,od$subject,min)[as.character(unique(od$subject))], table(od$subject)[as.character(unique(od$subject))]) od$obsno <- 1:n - od$firstobs + 1 if (!is.null(next.obstime) && (!is.numeric(next.obstime) || length(next.obstime) != n)) stop (paste("expected \"next.obstime\" to be a numeric vector length", n)) od$timeinterval <- if (is.null(next.obstime)) (od$obsno>1)*(od$time - od$time[c(1,1:(n-1))]) else next.obstime if (!is.null(maxtimes) && (!is.numeric(maxtimes) || !(length(maxtimes) %in% c(1,n)))) stop (paste("expected \"maxtimes\" to be a numeric vector length 1 or", n)) if (!is.null(groups) && (!(length(groups) == n))) stop (paste("expected \"groups\" to be a vector length", n)) od$maxtimes <- if (is.null(maxtimes)) ifelse(od$state %in% dstates, max(od$timeinterval) + 1, od$timeinterval) ## Set max possible obs time for deaths to be max observed plus arbitrary one unit else rep(maxtimes, length=n) # if supplied as a scalar, use it for all obs od$usergroup <- factor(if (!is.null(groups)) groups else rep(1, n)) ## User-supplied groups ## Method is restricted to "terminal" censoring (means not dead, occurs at end) ## Drop censored states not at the end of individual series lastobs <- c(od$subject[1:(n-1)] != od$subject[2:n], TRUE) cens.notend <- (od$state %in% x$cmodel$censor) & (!lastobs) if (any(cens.notend)) { od <- od[!cens.notend,] warning("Omitting censored states not at the end of individual series") } ## Drop individuals with only one observation od <- od[!od$subject %in% unique(od$subject)[table(od$subject)==1],] ## Drop observations of censoring types other than "not dead" if (length(x$cmodel$censor) >= 2) { ind <- NULL for (i in 1:length(x$cmodel$censor)) { if (identical(x$cmodel$states[x$cmodel$index[i] : (x$cmodel$index[i+1]-1)], as.numeric(transient.msm(x)))) {ind <- i; break} } if (is.null(ind)) warning("Omitting all censored states") else { cens.drop <- od$state %in% x$cmodel$censor[-ind] warning("Omitting censored states of types other than ",x$cmodel$censor[ind]) } od <- od[!cens.drop,] } n <- nrow(od) nstcens <- length(unique(od$state)) # no. unique states in data, should be same as number of markov states plus number of censor types (max 1) cens <- nstcens > nst # is there any remaining censoring ## Check and label transition groupings. Store data in a list ## Includes transitions to terminal censoring as separate states trans <- list() trans$allowed <- intervaltrans.msm(x, exclude.absabs=TRUE, censor=cens) trans$labsall <- paste(trans$allowed[,1], trans$allowed[,2], sep="-") trans$allowed[trans$allowed[,2] > nst, 2] <- nst+1 # these are to be used as indices, so label censoring as nst+1 not e.g. 99 trans$na <- nrow(trans$allowed) trans$use <- if (is.null(transitions)) 1:trans$na else transitions # why was this a matrix before? if (length(trans$use) != trans$na) stop("Supplied ", length(trans$use), " transition indices, expected ", trans$na) else if (!x$emodel$misc && ! all(tapply(trans$allowed[,1], trans$use, function(u)length(unique(u))) == 1) ) stop("Only transitions from the same origin can be grouped") ## convert ordinal transition indices to informative labels trans$labsagg <- tapply(trans$labsall, trans$use, function(u)paste(u,collapse=",")) trans$from <- trans$allowed[,1][!duplicated(trans$use)] # from-state corresp to each element of trans$labsagg trans$to <- trans$allowed[,2][!duplicated(trans$use)] # to-state corresp to each element of trans$labsagg trans$ngroups <- length(unique(trans$use)) ## Determine unique Q matrices determined by covariate combinations if (ncovs>0) { uniq <- unique(as.data.frame(od$cov[,dat$covdata$whichcov.orig,drop=FALSE])) nouniq <- dim(uniq)[1] pastedu <- do.call("paste",uniq) pastedc <- do.call("paste",as.data.frame(od$cov[,dat$covdata$whichcov.orig,drop=FALSE])) qmatindex <- match(pastedc,pastedu) qmat <- array(0,dim=c(nst,nst,nouniq)) for (i in 1:nouniq) qmat[,,i] <- qmatrix.msm(x, covariates=as.list(uniq[i,]), ci="none") }else{ qmatindex <- rep(1,n) nouniq <- 1 qmat <- array(qmatrix.msm(x,ci="none"),dim=c(nst,nst,1)) } qmatmaster <- qmat qmat <- qmat[,,qmatindex] od$rates <- apply(qmat,3,function(u) sum(diag(u))) ## Now work with a dataset with one row per transition md <- od[od$obsno>1,] qmat <- qmat[,,od$obsno>1] qmatindex <- qmatindex[od$obsno>1] ntrans <- nrow(md) nfromstates <- length(unique(md$prevstate)) ## Groups based on time since initiation (not observation number) timegroups.use <- min(length(unique(md$time)), timegroups) md$timegroup <- qcut(md$time, timegroups.use) ## Group time differences by quantiles within time since initiation intervalq <- tapply(md$timeinterval[md$state %in% ndstates], md$timegroup[md$state %in% ndstates], ## Categorise quantiles based only on full observations, not deaths or censoring. function(x) quantile(x,probs=seq(0,1,1/intervalgroups))) md$intervalgroup <- rep(1, ntrans) for (i in levels(md$timegroup)) md$intervalgroup[md$timegroup==i] <- unclass(qcut(md$timeinterval[md$timegroup==i], qu = intervalq[[i]])) md$intervalgroup <- factor(md$intervalgroup) ## Groups based on covariates covgroups.use <- min(length(unique(md$rates)), covgroups) md$covgroup <- if (ncovs > 0) qcut(md$rates, covgroups.use) else factor(rep(1,ntrans)) groupdims <- c(length(levels(md$timegroup)),length(levels(md$intervalgroup)),length(levels(md$covgroup)),length(levels(md$usergroup))) groupdimnames <- list(levels(md$timegroup),levels(md$intervalgroup),levels(md$covgroup),levels(md$usergroup)) ## Determine empirical distribution of time interval lengths. ## Then impute next scheduled observation for transitions which end in exact death times md$obtype <- rep(0, ntrans) if (exact.death) md$obtype[md$state %in% dstates] <- 1 md$obtype[md$state %in% x$cmodel$censor] <- 2 md$cens <- factor(as.numeric(md$obtype==2), levels=c(0,1)) ndeath <- sum(md$obtype==1) if (exact.death && is.null(next.obstime)) { cat("Imputing sampling times after deaths...\n") incl <- if (indep.cens) (0:2) else (0:1) empiricaldist <- empiricaldists(md$timeinterval[md$obtype %in% incl], md$state[md$obtype %in% incl], as.numeric(md$timegroup[md$obtype %in% incl]), timegroups, ndstates) imputation <- array(0,c(ndeath,N,4)) dimnames(imputation) <- list(NULL, NULL, c("times","cens","intervalgroup","timeqmatindex")) deathindex <- which(md$obtype==1) for (i in 1:ndeath) { mintime <- md$timeinterval[deathindex[i]] centime <- md$maxtimes[deathindex[i]] # - md$time[deathindex[i]] + mintime tg <- md$timegroup[deathindex[i]] ## returns list of times, whether would have ended in censoring, and time category. st <- sampletimes(mintime, centime, empiricaldist[,tg,empiricaldist["time",tg,]>0], N, tg, intervalq) for (j in c("times","cens","intervalgroup")) imputation[i,,j] <- st[,j] } } else imputation <- deathindex <- NULL ndeathindex <- setdiff(1:ntrans, deathindex) ## Transition probability matrices are indexed by unique combinations of time intervals and Q matrices. timeint <- c(md$timeinterval[md$obtype != 1],c(imputation[,,"times"])) # time intervals, excluding deaths, concatenated with imputations of next interval after death qmatint <- c(qmatindex[md$obtype != 1],rep(qmatindex[deathindex],N)) # index into unique Q matrices timeqmata <- unique(data.frame(timeint,qmatint)) timeqmat <- paste(timeint,qmatint,sep="-") pastedu <- unique(timeqmat) timeqmatindex <- match(timeqmat,pastedu) ## Work out the transition probability matrix for each unique time interval and Q matrix npmats<-length(pastedu) pmi <- array(0,dim=c(nst,nst,npmats)) for (i in unique(timeqmata[,2])) pmi[,,timeqmata[,2]==i] <- MatrixExp(qmatmaster[,,i], timeqmata[timeqmata[,2]==i,1]) md$timeqmatindex<-rep(0,ntrans) md$timeqmatindex[md$obtype != 1] <- timeqmatindex[1:(ntrans-ndeath)] if (exact.death && is.null(next.obstime)) imputation[,,"timeqmatindex"] <- timeqmatindex[(ntrans-ndeath+1):length(timeqmatindex)] ### Calculate transition probabilities for non-death intervals prob <- array(0,dim=c(nst,ntrans)) ## array of obs state probs, conditional on previous obs state if (x$emodel$misc) { misccov <- if (x$ecmodel$ncovs > 0) od$cov[x$hmodel$whichcovh.orig[1:x$ecmodel$ncovs]][od$obsno>1,,drop=FALSE] else NULL p.true <- array(dim=c(nst, ntrans)) # prob of each true state conditional on complete history including current obs initp <- if (x$foundse) x$hmodel$initprobs[,"Estimate"] else x$hmodel$initprobs if (x$ecmodel$ncovs > 0) { uniqmisc <- unique(misccov) ematindex <- match(do.call("paste",misccov), do.call("paste", uniqmisc)) emat <- array(0,dim=c(nst,nst,nrow(uniqmisc))) for (i in 1:nrow(uniqmisc)) emat[,,i] <- ematrix.msm(x, covariates=as.list(uniqmisc[i,]),ci="none") } else emat <- ematrix.msm(x, ci="none") for (i in 1:ntrans) { ematrix <- if (x$ecmodel$ncovs>0) emat[,,ematindex[i]] else emat if (md$state[i] %in% ndstates) { T <- pmi[,,md$timeqmatindex[i]] * matrix(ematrix[,md$state[i]], nrow=nst, ncol=nst, byrow=TRUE) p.true[,i] <- if (md$obsno[i] == 2) t(initp) %*% T else t(p.true[,i-1]) %*% T p.true[,i] <- p.true[,i] / sum(p.true[,i]) # prob of each true state } if (!(md$state[i] %in% dstates)) { prob[,i] <- if (md$obsno[i] == 2) initp %*% pmi[,,md$timeqmatindex[i]] %*% ematrix else p.true[,i-1] %*% pmi[,,md$timeqmatindex[i]] %*% ematrix } } } else prob[cbind(rep(1:nst,ntrans-ndeath),rep((1:ntrans)[ndeathindex],each=nst))] <- pmi[cbind(rep(md$prevstate[(1:ntrans)[ndeathindex]],each=nst), rep(1:nst,ntrans - ndeath),rep(md$timeqmatindex[(1:ntrans)[ndeathindex]],each=nst))] if (exact.death && is.null(next.obstime)) { stat.sim <- rep(0,N) obs.rep <- exp.rep <- dev.rep <- array(0, dim=c(groupdims, trans$ngroups, N)) dimnames(obs.rep) <- dimnames(exp.rep) <- dimnames(dev.rep) <- c(groupdimnames, list(trans$labsagg), list(1:N)) cat("Calculating replicates of test statistics for imputations...\n") for (i in 1:N) { ## Calculate transition probabilities for death intervals if (x$emodel$misc) { for (j in 1:ndeath) { k <- deathindex[j] ematrix <- if (x$ecmodel$ncovs>0) emat[,,ematindex[k]] else emat prob[,k] <- if (md$obsno[k] == 2) initp %*% pmi[,,imputation[j,i,"timeqmatindex"]] %*% ematrix else p.true[,k-1] %*% pmi[,,imputation[j,i,"timeqmatindex"]] %*% ematrix } } else prob[cbind(rep(1:nst,ndeath),rep(deathindex,each=nst))] <- pmi[cbind(rep(md$prevstate[deathindex],each=nst),rep(1:nst,ndeath),rep(imputation[,i,"timeqmatindex"],each=nst))] md$intervalgroup[deathindex] <- factor(imputation[,i,"intervalgroup"], labels=levels(md$intervalgroup[deathindex])[sort(unique(imputation[,i,"intervalgroup"]))]) md$cens[deathindex] <- as.numeric(imputation[,i,"cens"]) # factor levels 0/1 ## Observed transition table, including to censoring indicators obs.rep.i <- table(md$state, md$prevstate, md$timegroup, md$intervalgroup, md$covgroup, md$usergroup) ## Expected transition table exp.cens <- array(0, dim = c(nst, nndstates, groupdims, 2)) for (j in 1:nst) exp.cens[j,,,,,,] <- tapply(prob[j,], list(md$prevstate,md$timegroup,md$intervalgroup,md$covgroup,md$usergroup,md$cens), sum) exp.cens <- replace(exp.cens,is.na(exp.cens),0) exp.unadj <- array(0, dim=c(nstcens, nndstates, groupdims)) exp.unadj[1:nst,,,,,] <- exp.cens[,,,,,,1] for (j in dstates) exp.unadj[j,,,,,] <- exp.cens[j,,,,,,1] + exp.cens[j,,,,,,2] if (cens) exp.unadj[nst+1,,,,,] <- apply(exp.cens[1:nndstates,,,,,,2,drop=FALSE], 2:6, sum) # total censored from any non-death state ## Remove very small values, caused by inaccuracy in numerical matrix exponential. exp.unadj <- replace(exp.unadj,(exp.unadj 1 , , , ,] == 0) df.upper <- prod(dim(obstable)[1:4])*n.indep.trans - n.zerofrom df.lower <- df.upper - length(x$opt$par) test <- data.frame(stat=stat, df.lower = if (exact.death && is.null(next.obstime)) NA else df.lower, p.lower = if (exact.death && is.null(next.obstime)) NA else 1-pchisq(stat, df.lower), df.upper=df.upper, p.upper=1-pchisq(stat, df.upper)); rownames(test) <- "" ## Simulated observation times to use as sampling frame for bootstrapped data if (!is.null(imputation)) { imp.times <- matrix(rep(od$time, N), nrow=length(od$time), ncol=N) prevtime <- imp.times[which(od$state %in% dstates) - 1,] imp.times[od$state %in% dstates, ] <- prevtime + imputation[,,"times"] } else imp.times <- NULL if (boot) { cat("Starting bootstrap refitting...\n") boot.stats <- pearson.boot.msm(x, imp.times=imp.times, transitions=transitions, timegroups=timegroups, intervalgroups=intervalgroups, covgroups=covgroups, groups=groups, B=B, df=df.upper) test$p.boot <- sum(boot.stats > stat) / B } pearson <- list(observed=obstable, expected=exptable, deviance=devtable*sign(obstable-exptable), test=test, intervalq=intervalq) names(pearson) <- c("Observed","Expected","Deviance*sign(O-E)","test","intervalq") if (exact.death && is.null(next.obstime)) pearson$sim <- list(observed=obs.rep, expected=exp.rep, deviances=dev.rep, stat=stat.sim, imputation=imputation) if (boot) pearson$boot <- boot.stats pearson <- reformat.pearson.msm(pearson) class(pearson) <- "pearson.msm" pearson } ### Reformat array output from Pearson test as a matrix with transition type in columns reformat.pearson.msm <- function(pearson) { pp <- pearson nd <- length(dim(pearson$Observed)) for (i in 1:3) { dim(pp[[i]]) <- c(prod(dim(pp[[i]])[-nd]), dim(pp[[i]])[nd]) rnames <- do.call("expand.grid", dimnames(pearson$Observed)[1:4]) colnames(pp[[i]]) <- dimnames(pearson$Observed)[[nd]] pp[[i]] <- as.data.frame(pp[[i]]) pp[[i]] <- cbind(rnames, pp[[i]]) colnames(pp[[i]])[1:4] <- c("Time","Interval","Cov","User") drop <- NULL # drop columns labelling categories with only one value for (j in 1:4) if (length(unique(pp[[i]][,j]))==1) drop <- c(drop,j) pp[[i]] <- pp[[i]][,-drop] } pp } ### Keep the simulation and bootstrap output but don't print it print.pearson.msm <- function(x, ...){ print(x[!(names(x) %in% c("sim","boot","intervalq"))]) } ### Adaptation of cut(quantile()) so that if two quantiles are equal, a unique category is created for x equal to that ### For point intervals, the label is just the value of the point ### Else, the labels are in (a,b] or [a,b) type interval notation qcut <- function(x, n, qu=NULL, eps=1e-06, digits=2, drop.unused.levels=FALSE) { if (is.null(qu)) qu <- quantile(x, probs = seq(0, 1, 1/n)) q2.equal <- sequence(table(qu)) <= 2 qu <- qu[q2.equal] ## If three or more quantiles are equal, only keep two of them. ## Ensure all x fall within intervals, widening upper and lower intervals if necessary. qu[qu==max(qu)] <- max(max(qu),x) qu[qu==min(qu)] <- min(min(qu),x) n <- length(qu)-1 lagq <- c(-Inf, qu[1:n]) qlabs <- paste("[",round(qu[1:n],digits),",",round(qu[2:(n+1)],digits),")",sep="") inti <- qu[1:n]==qu[2:(n+1)] # which intervals are points qlabs[inti] <- round(qu[1:n][inti], digits) lastopen <- if (n==1) FALSE else c(FALSE, inti[1:(n-1)]) substr(qlabs[lastopen],1,1) <- "(" # interval with a point interval just before it is open on the left if (!inti[n]) substr(qlabs[length(qlabs)], nchar(qlabs[length(qlabs)]), nchar(qlabs[length(qlabs)])) <- "]" # last interval is closed on the right qu[qu==lagq] <- qu[qu==lagq] + eps x.cut <- cut(x, qu, right=FALSE, include.lowest=TRUE, labels=qlabs) tx <- tapply(x, x.cut, unique) nxcats <- sapply(tx, length) # number of unique x values in each category nxcats[is.na(tx)] <- 0 ## If only one unique x value is in a category, then label the category with that value if (any(nxcats==1)) levels(x.cut)[nxcats == 1] <- round(unlist(tx[nxcats==1]), digits) if (drop.unused.levels) x.cut <- factor(x.cut, exclude=NULL) # drop unused factor levels x.cut } ### Parametric bootstrap ### Simulate data from fitted model with same observation scheme boot.param.msm <- function(x){ dat <- x$data sim.df <- as.data.frame(dat[c("subject","time","cens")]) sim.df$obstrue <- dat$obstrue # NULL if not HMM sim.df$obstype <- if (!is.null(dat$obstype.obs)) dat$obstype.obs else dat$obstype sim.df$pci.imp <- dat$pci.imp if (x$qcmodel$ncovs > 0) { sim.df <- cbind(sim.df, dat$cov[,x$qcmodel$covlabels,drop=FALSE]) sim.df <- cbind(sim.df, dat$cov.orig[,x$qcmodel$covlabels.orig,drop=FALSE]) cov.effs <- lapply(x$Qmatrices, function(y)t(y)[t(x$qmodel$imatrix)==1])[x$qcmodel$covlabels] } else cov.effs <- NULL if (x$ecmodel$ncovs > 0) { sim.df <- cbind(sim.df, dat$cov[,setdiff(x$ecmodel$covlabels,x$qcmodel$covlabels),drop=FALSE]) sim.df <- cbind(sim.df, dat$cov.orig[,setdiff(x$ecmodel$covlabels.orig,x$qcmodel$covlabels.orig),drop=FALSE]) misccov.effs <- lapply(x$Ematrices, function(y)t(y)[t(x$emodel$imatrix)==1])[x$ecmodel$covlabels] } else misccov.effs <- NULL boot.df <- simmulti.msm(data=sim.df, qmatrix=qmatrix.msm(x, covariates=0, ci="none"), covariates=cov.effs, death=FALSE, ematrix=ematrix.msm(x, covariates=0, ci="none"), misccovariates=misccov.effs ) } pearson.boot.msm <- function(x, imp.times=NULL, transitions=NULL, timegroups=4, intervalgroups=4, covgroups=4, groups=NULL, B=500, df){ bootstat <- numeric(B) x$call$formula <- if (x$emodel$misc) substitute(obs ~ time) else substitute(state ~ time) x$call$qmatrix <- qmatrix.msm(x,ci="none") # put MLE in inits. x$call$hessian <- x$call$death <- FALSE x$call$obstype <- NULL x$call$subject <- substitute(subject) i <- 1 while (i <= B) { if (!is.null(imp.times)) x$data$time <- imp.times[,sample(ncol(imp.times), size=1)] # resample one of the imputed sets of observation times x$data$cens <- ifelse(x$data$state %in% 1:x$qmodel$nstates, 0, x$data$state) # 0 if not censored, cens indicator if censored, so that censoring is retained in simulated data boot.df <- boot.param.msm(x) boot.df <- boot.df[!boot.df$pci.imp,] x$call$data <- substitute(boot.df) refit.msm <- try(eval(x$call)) # estimation might not converge for a particular bootstrap resample if (inherits(refit.msm, "msm")) { p <- pearson.msm(refit.msm, transitions=transitions, timegroups=timegroups, intervalgroups=intervalgroups, covgroups=covgroups, groups=groups, boot=FALSE) bootstat[i] <- p$test$stat i <- i + 1 } } bootstat } ### Work out empirical distribution of sampling times for each observation (or time since initiation) group: empiricaldists <- function(timeinterval, state, obgroup, obgroups, ndstates) { empdist <- array(0,c(3, obgroups, max(table(obgroup[state %in% ndstates])))) # Need times, cum value and point mass value dimnames(empdist) <- list(c("time", "surv", "pdeath"), levels(obgroup), NULL) ## First dimension: 1: time, 2: surv prob 3: death prob in prev interval ## Second dim: observation group. Third dim: size of biggest obs group (i.e. maximum number of event times for KM estimate) for (i in 1:obgroups) { ##s1 <- survfit(Surv(timeinterval[obgroup==i],(state[obgroup==i] %in% ndstates))~1,type="kaplan-meier") ##survfit seems to ignore increments of small size ## TODO investigate this ##Instead use own code to create KM t <- round(timeinterval[(obgroup==i & state %in% ndstates)],4) eligt <- sort(unique(t)) events <- table(t) allt <- sort(round(timeinterval[obgroup==i],4)) empdist["time",i,1:length(eligt)] <- eligt for (j in 1:length(eligt)) { nrisk <- sum(allt + sqrt(.Machine$double.eps) >= eligt[j]) if (nrisk==0) nrisk <- 1 # avoid floating point fuzz in comparing last point empdist["surv",i,j] <- if (j>1) (empdist["surv",i,j-1]*(1 - events[j]/nrisk)) else (1 - events[j]/nrisk) empdist["pdeath",i,j] <- if (j>1) (empdist["surv",i,j-1] - empdist["surv",i,j]) else (1 - empdist["surv",i,j]) ## Now deals with ties correctly } } empdist } ### For a single death, sample N points from the distribution of the next sampling time ### mintime, centime: minimum and maximum possible times ### dist: matrix of times, survival probs and previous-interval death probs sampletimes <- function(mintime, centime, dist, N, obgroup, intervalq) { ## dist takes the overall distribution from the relevant obgroup, but since we supply obgroup it might be better to just supply the whole thing dist <- dist[,dist[1,]>mintime,drop=FALSE] # Remove times before the minimum possible time. if (length(dist) > 0) { dist[c("surv","pdeath"),] <- dist[c("surv","pdeath"),] / dist["surv",1] # Normalise ## Compute the censoring fraction cen <- 1 - sum(dist["pdeath",dist["time",]0) { cend <- as.numeric(runif(N) < cen) if (length(dist["time",])>1) { ## Suppress "Walker's alias method used, results incompatible with R < 2.2.0" warning times <- suppressWarnings(sample(dist["time",],N,replace=TRUE,prob=dist["pdeath",])) * (cend==0) + centime*(cend==1) }else{ times <- dist["time",]*(cend==0) + centime*(cend==1) } }else{ cend <- rep(1,N) times <- rep(centime,N) } }else{ cend <- rep(1,N) times <- rep(centime,N) } intervalgroup <- qcut(times,qu=intervalq[[obgroup]]) cbind(times=times, cens=cend, intervalgroup=intervalgroup) } ## make internal to pearson function ## requires table of expected values with dims: nstcens, nndstates, groupdims ## also observed table with same dims ## prob need to calculate these in every case. ## why not do this calculation with the ungrouped version of the table, collapse the first two dims, then aggregate the table by trans$use ### Replace fromstate,tostate dimensions at beginning by a single allowed-transition dimension at end agg.tables <- function(obs.full, exp.full, groupdims, groupdimnames, trans) { obstable <- exptable <- array(dim=c(groupdims, trans$na)) for (i in 1:trans$na) { obstable[,,,,i] <- obs.full[trans$allowed[i,2],trans$allowed[i,1],,,,] exptable[,,,,i] <- exp.full[trans$allowed[i,2],trans$allowed[i,1],,,,] } obstable <- replace(obstable,is.na(obstable),0) exptable <- replace(exptable,is.na(exptable),0) ## Aggregate by transition groups obstable <- aperm(apply(obstable, 1:4, function(u)tapply(u, trans$use, sum)), c(2:5,1)) exptable <- aperm(apply(exptable, 1:4, function(u)tapply(u, trans$use, sum)), c(2:5,1)) dimnames(obstable) <- dimnames(exptable) <- c(groupdimnames, list(trans$labsagg)) list(obs=obstable, exp=exptable) } ### Adjust expected counts to account for informative censoring times, according to method in paper addendum. adjust.expected.cens <- function(exp.unadj, obs, nst, ndstates, dstates, groupdims, N, cens, md, nstcens) { ## Compute total expected counts from each from-state, summed over destination state (n-tilde in paper addendum) nndstates <- length(ndstates) dims <- c(nndstates, groupdims) nobs <- apply(obs, 2:6, sum) # Obs trans summed over first dimension = destination state = Number of trans from state r in group nobs.xd <- nobs - array(obs[nst,,,,,], dim=dims) # Number of trans excluding death nobs.xdc <- if (cens) nobs.xd - array(obs[nst+1,,,,,,drop=FALSE], dim=dims) else nobs.xd # excluding death and censoring po <- array(0, dim = c(nst+1, dims)) # p-hat in appendix to paper, MLEs from unrestricted alternative model for (j in ndstates) # prop of uncensored trans from state r (and group) ending in state j (not death), multiplied by prop of trans not ending in death. po[j,,,,,] <- (array(obs[j,,,,,], dim=dims) * nobs.xd)/(nobs.xdc*nobs + (nobs.xdc*nobs==0)) for (j in dstates) po[nst,,,,,] <- array(obs[j,,,,,], dim=dims) / (nobs + (nobs==0)) # prop of trans from state r (and group) ending in death. (if zero in denom, this is 0) po[nst+1,,,,,] <- 1 - apply(po[dstates,,,,,,drop=FALSE], 2:6, sum) po <- replace(po, is.na(po), 0) nexp <- apply(exp.unadj, 2:6, sum) nexp.xd <- nexp - array(exp.unadj[nst,,,,,], dim=dims) nexp.xdc <- if (cens) nexp.xd - array(exp.unadj[nst+1,,,,,,drop=FALSE],dim=dims) else nexp.xd ps <- array(0,dim=c(nst+1, dims)) # p-tilde-star in addendum to paper. "robustified" MLEs from null Markov model for (j in ndstates) ps[j,,,,,] <- (array(exp.unadj[j,,,,,], dim=dims)*nexp.xd)/(nexp.xdc*nexp + (nexp.xdc*nexp==0)) for (j in dstates) ps[j,,,,,] <- array(exp.unadj[j,,,,,], dim=dims)/(nexp + (nexp==0)) ps[nst+1,,,,,] <- 1 - apply(ps[dstates,,,,,,drop=FALSE], 2:6, sum) ps <- replace(ps,is.na(ps),0) ncen <- tapply(md$cens, list(md$prevstate,md$timegroup,md$intervalgroup,md$covgroup,md$usergroup), function(x)sum(x==1)) dim(ncen) <- dims ncen <- replace(ncen, is.na(ncen), 0) exp.adj <- array(0, dim=c(nstcens,dims)) # = p-tilde-star * n / phat (in notation of paper) = ps * obs / po exp.adj[ndstates,,,,,] <- ps[ndstates,,,,,,drop=FALSE] * rep(nobs.xdc * nobs,each=nndstates) / rep(nobs.xd + (nobs.xd==0),each=nndstates) for (j in dstates) exp.adj[j,,,,,] <- array(ps[j,,,,,], dim=dims) * nobs if (cens) exp.adj[nst+1,,,,,] <- nobs - apply(exp.adj[1:nst,,,,,,drop=FALSE], 2:6, sum) exp.adj } msm/R/hmm-dists.R0000644000176000001440000001360011760723101013325 0ustar ripleyusers ### CONSTRUCTORS FOR VARIOUS DISTRIBUTIONS FOR RESPONSE CONDITIONALLY ON HIDDEN STATE ### Categorical distribution on the set 1,...,n hmmCat <- function(prob, basecat) { label <- "categorical" prob <- lapply(prob, eval) p <- unlist(prob) if (any(p < 0)) stop("non-positive probability") if (all(p == 0)) stop("insufficient positive probabilities") p <- p / sum(p) ncats <- length(p) link <- "log" # covariates are added to log odds relative to baseline in lik.c(AddCovs) cats <- seq(ncats) basei <- if (missing(basecat)) which.max(p) else which(cats==basecat) r <- function(n, rp=p) sample(cats, size=n, prob=rp, replace=TRUE) pars <- c(ncats, basei, p) plab <- rep("p", ncats) plab[p==0] <- "p0" plab[basei] <- "pbase" names(pars) <- c("ncats", "basecat", plab) hdist <- list(label=label, pars=pars, link=link, r=r) ## probabilities are always pars[c(3,3+pars[0])] class(hdist) <- "hmmdist" hdist } ### Constructor for a standard univariate distribution (i.e. not hmmCat) hmmDIST <- function(label, link, r, call, ...) { call <- c(as.list(call), list(...)) miss.pars <- which ( ! (.msm.HMODELPARS[[label]] %in% names(call)[-1]) ) if (length(miss.pars) > 0) { stop("Parameter ", .msm.HMODELPARS[[label]][min(miss.pars)], " for ", call[[1]], " not supplied") } pars <- unlist(lapply(call[.msm.HMODELPARS[[label]]], eval)) hmmCheckInits(pars) hdist <- list(label = label, pars = pars, link = link, r = r) class(hdist) <- "hmmdist" hdist } ## Check for initial values outside defined ranges hmmCheckInits <- function(pars) { for (i in names(pars)) { if (!is.numeric(pars[i])) stop("Expected numeric values for all parameters") else if (i %in% .msm.INTEGERPARS) { if (!identical(all.equal(pars[i], round(pars[i])), TRUE)) stop("Value of ", i, " should be integer") } else if (i %in% names(.msm.PARRANGES)) if (!in.range(pars[i], .msm.PARRANGES[[i]])) stop("Initial value ", pars[i], " of parameter ", i, " outside allowed range ", "[", paste(.msm.PARRANGES[[i]], collapse=","), "]") } } in.range <- function(x, interval) { if (!is.numeric(interval) || length(interval)!=2) stop("interval should be a numeric vector of length 2") if (!is.numeric(x)) stop("x should be numeric") ( (x >= interval[1]) & (x <= interval[2]) ) } hmmIdent <- function(x) { hmm <- hmmDIST(label = "identity", link = "identity", r = function(n)rep(x, n), match.call()) hmm$pars <- if (missing(x)) numeric() else x names(hmm$pars) <- if(length(hmm$pars)>0) "which" else NULL hmm } hmmUnif <- function(lower, upper) { hmmDIST (label = "uniform", link = "identity", r = function(n) runif(n, lower, upper), match.call()) } hmmNorm <- function(mean, sd) { hmmDIST (label = "normal", link = "identity", r = function(n, rmean=mean) rnorm(n, rmean, sd), match.call()) } hmmLNorm <- function(meanlog, sdlog) { hmmDIST (label = "lognormal", link = "identity", r = function(n, rmeanlog=meanlog) rlnorm(n, rmeanlog, sdlog), match.call()) } hmmExp <- function(rate) { hmmDIST (label = "exponential", link = "log", r = function(n, rrate=rate) rexp(n, rrate), match.call()) } hmmGamma <- function(shape, rate) { hmmDIST (label = "gamma", link = "log", r = function(n, rrate=rate) rgamma(n, shape, rrate), match.call()) } hmmWeibull <- function(shape, scale) { hmmDIST (label = "weibull", link = "log", r = function(n, rscale=scale) rweibull(n, shape, rscale), match.call()) } hmmPois <- function(rate) { hmmDIST (label = "poisson", link = "log", r = function(n, rrate=rate) rpois(n, rrate), match.call()) } hmmBinom <- function(size, prob) { hmmDIST (label = "binomial", link = "qlogis", r = function(n, rprob=prob) rbinom(n, size, rprob), match.call()) } hmmNBinom <- function(disp, prob) { hmmDIST (label = "nbinom", link = "qlogis", r = function(n, rprob=prob) rnbinom(n, disp, rprob), match.call()) } hmmBeta <- function(shape1, shape2) { hmmDIST (label = "beta", link = "log", r = function(n) rbeta(n, shape1, shape2), match.call()) } hmmTNorm <- function(mean, sd, lower=-Inf, upper=Inf) { hmmDIST (label = "truncnorm", link = "identity", r = function(n, rmean=mean) rtnorm(n, rmean, sd, lower, upper), match.call(), lower=lower, upper=upper) } hmmMETNorm <- function(mean, sd, lower, upper, sderr, meanerr=0) { hmmDIST (label = "metruncnorm", link = "identity", r = function(n, rmeanerr=meanerr) rnorm(n, rmeanerr + rtnorm(n, mean, sd, lower, upper), sderr), match.call(), meanerr=meanerr) } hmmMEUnif <- function(lower, upper, sderr, meanerr=0) { hmmDIST (label = "meuniform", link = "identity", r = function(n, rmeanerr=meanerr) rnorm(n, rmeanerr + runif(n, lower, upper), sderr), match.call(), meanerr=meanerr) } hmmT <- function(mean, scale, df) { hmmDIST(label="t", link="identity", r = function(n, rmean=mean) { rmean + scale*rt(n,df) }, match.call()) } msm/R/boot.R0000644000176000001440000003315511750003543012372 0ustar ripleyusers### Take a bootstrap sample from the data contained in a fitted msm ### model. Sample pairs of consecutive observations, i.e. independent ### transitions. Not applicable if model is hidden or some states are ### censored. bootdata.trans.msm <- function(x) { dat <- if (!is.null(x$data.orig)) x$data.orig else x$data subj.num <- match(dat$subject, unique(dat$subject)) nextsubj <- c(subj.num[2:length(subj.num)], Inf) lastsubj <- subj.num != nextsubj inds <- sample(which(!lastsubj), replace=TRUE) data.boot <- as.data.frame(matrix(nrow=length(inds)*2, ncol=length(dat$covlabels.orig) + 4)) state.name <- deparse(as.list(x$call$formula)[[2]]) time.name <- deparse(as.list(x$call$formula)[[3]]) colnames(data.boot) <- c("subject.name", time.name, state.name, "obstype.name", dat$covlabels.orig) data.boot[,state.name] <- as.vector(rbind(dat$state[inds], dat$state[inds+1])) # in the bootstrap data, label each transition as being from a different subject data.boot[,"subject.name"] <- rep(seq(along=inds), each=2) data.boot[,time.name] <- as.vector(rbind(dat$time[inds], dat$time[inds+1])) data.boot[,"obstype.name"] <- as.vector(rbind(dat$obstype.obs[inds], dat$obstype.obs[inds+1])) for (j in dat$covlabels.orig) { frominds <- seq(1, 2*length(inds)-1, 2) data.boot[frominds, j] <- data.boot[frominds+1,j] <- dat$cov.orig[inds, j] if (is.factor(dat$cov.orig[, j])) { data.boot[, j] <- factor(data.boot[,j], labels=sort(unique(dat$cov.orig[inds, j]))) } } colnames(data.boot) <- gsub("factor\\((.+)\\)", "\\1", colnames(data.boot)) data.boot } ### Take a bootstrap sample from the data contained in a fitted msm ### model. Sample subjects. Used for hidden models or models with ### censoring, in which the transitions within a subject are not ### independent. bootdata.subject.msm <- function(x) { dat <- if (!is.null(x$data.orig)) x$data.orig else x$data subj.num <- match(dat$subject, unique(dat$subject)) subjs <- sample(unique(subj.num), replace=TRUE) inds <- new.subj <- NULL for (i in seq(along=subjs)) { subj.inds <- which(subj.num == subjs[i]) inds <- c(inds, subj.inds) new.subj <- c(new.subj, rep(i, length(subj.inds))) } data.boot <- as.data.frame(matrix(nrow=length(inds), ncol=length(dat$covlabels.orig) + 5)) state.name <- deparse(as.list(x$call$formula)[[2]]) time.name <- deparse(as.list(x$call$formula)[[3]]) colnames(data.boot) <- c("subject.name", time.name, state.name, "obstype.name", "obstrue.name", dat$covlabels.orig) data.boot[,"subject.name"] <- new.subj data.boot[,time.name] <- dat$time[inds] data.boot[,state.name] <- dat$state[inds] data.boot[,"obstype.name"] <- dat$obstype[inds] data.boot[,"obstrue.name"] <- dat$obstrue[inds] for (j in dat$covlabels.orig) { data.boot[, j] <- dat$cov.orig[inds, j] if (is.factor(dat$cov.orig[, j])) data.boot[, j] <- factor(data.boot[,j], labels=sort(unique(dat$cov.orig[, j]))) } colnames(data.boot) <- gsub("factor\\((.+)\\)", "\\1", colnames(data.boot)) data.boot } ### Given a fitted msm model, draw a bootstrap dataset, refit the ### model, and optionally compute a statistic on the refitted model. ### Repeat B times, store the results in a list. ### msm objects tend to be large, so it is advised to compute a statistic on them by specifying "stat", instead ### of using this function to return a list of refitted msm objects. ### To compute more than one statistic, specify, e.g. stat=function(x)list(stat1(x),stat2(x)) ### Some of the arguments to the msm call might be user-defined objects. ### e.g. qmatrix, ematrix, hmodel, ... ### Put in help file that these must be in the working environment. ### a) if call supplied as factor(), strip factor() from name. boot.msm <- function(x, stat=pmatrix.msm, B=1000, file=NULL){ if (!is.null(x$call$subject)) x$call$subject <- substitute(subject.name) if (!is.null(x$call$obstype)) x$call$obstype <- substitute(obstype.name) if (!is.null(x$call$obstrue)) x$call$obstrue <- substitute(obstrue.name) boot.fn <- function(dummy){ boot.data <- if (x$hmodel$hidden || x$cmodel$ncens) bootdata.subject.msm(x) else bootdata.trans.msm(x) x$call$data <- substitute(boot.data) res <- try(eval(x$call)) if (!inherits(res, "try-error") && !is.null(stat)) res <- try(stat(res)) res } boot.list <- vector(B, mode="list") for (i in 1:B) { boot.list[[i]] <- boot.fn() if (!is.null(file)) save(boot.list, file=file) } boot.list } ### Utilities for calculating bootstrap CIs for particular statistics qematrix.ci.msm <- function(x, covariates="mean", intmisc="intens", sojourn=FALSE, cl=0.95, B=1000) { q.list <- boot.msm(x, function(x)qematrix.msm(x=x, covariates=covariates, intmisc=intmisc)$estimates, B) q.array <- array(unlist(q.list), dim=c(dim(q.list[[1]]), length(q.list))) q.ci <- apply(q.array, c(1,2), function(x)(c(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)), sd(x)))) q.ci <- aperm(q.ci, c(2,3,1)) if (sojourn) { soj.array <- apply(q.array, 3, function(x) -1/diag(x)) soj.ci <- apply(soj.array, 1, function(x)(c(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)), sd(x)))) list(q=q.ci, soj=soj.ci) } else q.ci } qratio.ci.msm <- function(x, ind1, ind2, covariates="mean", cl=0.95, B=1000) { q.list <- boot.msm(x, function(x)qratio.msm(x=x, ind1=ind1, ind2=ind2, covariates=covariates)["estimate"], B) q.vec <- unlist(q.list) c(quantile(q.vec, c(0.5 - cl/2, 0.5 + cl/2)), sd(q.vec)) } pnext.ci.msm <- function(x, covariates="mean", cl=0.95, B=1000) { p.list <- boot.msm(x, function(x)pnext.msm(x=x, covariates=covariates, ci="none")$estimates, B) p.array <- array(unlist(p.list), dim=c(dim(p.list[[1]]), length(p.list))) p.ci <- apply(p.array, c(1,2), function(x)(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)))) aperm(p.ci, c(2,3,1)) } pmatrix.ci.msm <- function(x, t, t1, covariates="mean", cl=0.95, B=1000) { p.list <- boot.msm(x, function(x)pmatrix.msm(x=x, t=t, t1=t1, covariates=covariates,ci="none"), B) p.array <- array(unlist(p.list), dim=c(dim(p.list[[1]]), length(p.list))) p.ci <- apply(p.array, c(1,2), function(x)(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)))) aperm(p.ci, c(2,3,1)) } pmatrix.piecewise.ci.msm <- function(x, t1, t2, times, covariates="mean", cl=0.95, B=1000) { p.list <- boot.msm(x, function(x)pmatrix.piecewise.msm(x=x, t1=t1, t2=t2, times=times, covariates=covariates,ci="none"), B) p.array <- array(unlist(p.list), dim=c(dim(p.list[[1]]), length(p.list))) p.ci <- apply(p.array, c(1,2), function(x)(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)))) aperm(p.ci, c(2,3,1)) } totlos.ci.msm <- function(x, start=1, end=NULL, fromt=0, tot=Inf, covariates="mean", cl=0.95, B=1000) { t.list <- boot.msm(x, function(x)totlos.msm(x, start, end, fromt, tot, covariates), B) t.array <- do.call("rbind", t.list) apply(t.array, 2, function(x)(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)))) } expected.ci.msm <- function(x, times=NULL, timezero=NULL, initstates=NULL, covariates="mean", misccovariates="mean", piecewise.times=NULL, piecewise.covariates=NULL, risk=NULL, cl=0.95, B=1000) { if(is.null(risk)) risk <- observed.msm(x)$risk e.list <- boot.msm(x, function(x){ expected.msm(x, times, timezero, initstates, covariates, misccovariates, piecewise.times, piecewise.covariates, risk) }, B) e.tab.array <- array(unlist(lapply(e.list, function(x)x[[1]])), dim=c(dim(e.list[[1]][[1]]), length(e.list))) e.perc.array <- array(unlist(lapply(e.list, function(x)x[[2]])), dim=c(dim(e.list[[1]][[2]]), length(e.list))) e.tab.ci <- apply(e.tab.array, c(1,2), function(x)(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)))) e.perc.ci <- apply(e.perc.array, c(1,2), function(x)(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)))) res <- list(aperm(e.tab.ci, c(2,3,1)), aperm(e.perc.ci, c(2,3,1))) names(res) <- c("Expected", "Expected percentages") res } ### Compute a CI for a statistic using a sample from the assumed MVN ### distribution of MLEs of log Q, logit E and covariate effects on these ### Not user visible: only support statistics based on Q matrix and E matrix ### i.e. statistics computed as functions of x$Qmatrices, x$Ematrices and x$paramdata$params normboot.msm <- function(x, stat, B=1000) { ## simulate from vector of unreplicated parameters, to avoid numerical problems with rmvnorm when lots of correlations are 1 if (!x$foundse) stop("Asymptotic standard errors not available in fitted model") sim <- rmvnorm(B, x$opt$par, solve(0.5 * x$opt$hessian)) params <- matrix(nrow=B, ncol=x$paramdata$npars) # replicate constrained parameters. params[,x$paramdata$optpars] <- sim params[,x$paramdata$fixedpars] <- rep(x$paramdata$params[x$paramdata$fixedpars], each=B) params[,x$paramdata$hmmpars] <- rep(msm.mninvlogit.transform(x$paramdata$params[x$paramdata$hmmpars], x$hmodel$plabs, x$hmodel$parstate), each=B) params <- params[, !duplicated(abs(x$paramdata$constr)), drop=FALSE][, abs(x$paramdata$constr), drop=FALSE] * rep(sign(x$paramdata$constr), each=B) sim.stat <- vector(B, mode="list") for (i in 1:B) { x.rep <- x x.rep$paramdata$params <- params[i,] output <- msm.form.output("intens", x.rep$qmodel, x.rep$qcmodel, x.rep$paramdata) x.rep$Qmatrices <- output$Matrices if (x$emodel$misc) { output <- msm.form.output("misc", x.rep$emodel, x.rep$ecmodel, x.rep$paramdata) x.rep$Ematrices <- output$Matrices names(x.rep$Ematrices)[1] <- "logitbaseline" } sim.stat[[i]] <- stat(x.rep) } sim.stat } qematrix.normci.msm <- function(x, covariates="mean", intmisc="intens", sojourn=FALSE, cl=0.95, B=1000) { q.list <- normboot.msm(x, function(x)qematrix.msm(x=x, covariates=covariates, intmisc=intmisc, ci="none"), B) q.array <- array(unlist(q.list), dim=c(dim(q.list[[1]]), length(q.list))) q.ci <- apply(q.array, c(1,2), function(x)(c(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)), sd(x)))) q.ci <- aperm(q.ci, c(2,3,1)) if (sojourn) { soj.array <- apply(q.array, 3, function(x) -1/diag(x)) soj.ci <- apply(soj.array, 1, function(x)(c(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)), sd(x)))) list(q=q.ci, soj=soj.ci) } else q.ci } qratio.normci.msm <- function(x, ind1, ind2, covariates="mean", cl=0.95, B=1000) { q.list <- normboot.msm(x, function(x)qratio.msm(x=x, ind1=ind1, ind2=ind2, covariates=covariates, ci="none")["estimate"], B) q.vec <- unlist(q.list) c(quantile(q.vec, c(0.5 - cl/2, 0.5 + cl/2)), sd(q.vec)) } pnext.normci.msm <- function(x, covariates="mean", cl=0.95, B=1000) { p.list <- normboot.msm(x, function(x)pnext.msm(x=x, covariates=covariates, ci="none")$estimates, B) p.array <- array(unlist(p.list), dim=c(dim(p.list[[1]]), length(p.list))) p.ci <- apply(p.array, c(1,2), function(x)(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)))) aperm(p.ci, c(2,3,1)) } pmatrix.normci.msm <- function(x, t, t1, covariates="mean", cl=0.95, B=1000) { p.list <- normboot.msm(x, function(x)pmatrix.msm(x=x, t=t, t1=t1, covariates=covariates, ci="none"), B) p.array <- array(unlist(p.list), dim=c(dim(p.list[[1]]), length(p.list))) p.ci <- apply(p.array, c(1,2), function(x)(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)))) aperm(p.ci, c(2,3,1)) } pmatrix.piecewise.normci.msm <- function(x, t1, t2, times, covariates="mean", cl=0.95, B=1000) { p.list <- normboot.msm(x, function(x)pmatrix.piecewise.msm(x=x, t1=t1, t2=t2, times=times, covariates=covariates, ci="none"), B) p.array <- array(unlist(p.list), dim=c(dim(p.list[[1]]), length(p.list))) p.ci <- apply(p.array, c(1,2), function(x)(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)))) aperm(p.ci, c(2,3,1)) } totlos.normci.msm <- function(x, start=1, end=NULL, fromt=0, tot=Inf, covariates="mean", cl=0.95, B=1000, ...) { t.list <- normboot.msm(x, function(x)totlos.msm(x, start, end, fromt, tot, covariates, ci="none", ...), B) t.array <- do.call("rbind", t.list) apply(t.array, 2, function(x)(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)))) } expected.normci.msm <- function(x, times=NULL, timezero=NULL, initstates=NULL, covariates="mean", misccovariates="mean", piecewise.times=NULL, piecewise.covariates=NULL, risk=NULL, cl=0.95, B=1000) { if(is.null(risk)) risk <- observed.msm(x)$risk e.list <- normboot.msm(x, function(x){ expected.msm(x, times, timezero, initstates, covariates, misccovariates, piecewise.times, piecewise.covariates, risk) }, B) e.tab.array <- array(unlist(lapply(e.list, function(x)x[[1]])), dim=c(dim(e.list[[1]][[1]]), length(e.list))) e.perc.array <- array(unlist(lapply(e.list, function(x)x[[2]])), dim=c(dim(e.list[[1]][[2]]), length(e.list))) e.tab.ci <- apply(e.tab.array, c(1,2), function(x)(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)))) e.perc.ci <- apply(e.perc.array, c(1,2), function(x)(quantile(x, c(0.5 - cl/2, 0.5 + cl/2)))) res <- list(aperm(e.tab.ci, c(2,3,1)), aperm(e.perc.ci, c(2,3,1))) names(res) <- c("Expected", "Expected percentages") res } msm/R/hmm.R0000644000176000001440000003061311446654427012223 0ustar ripleyusers### FUNCTIONS FOR HIDDEN MARKOV MODELS IN CONTINUOUS TIME ### WITH ARBITRARY RESPONSE DISTRIBUTION print.hmmdist <- function(x, ...) { cat("Hidden Markov model", x$label, "distribution\n\n") pnames <- if(x$label=="categorical") paste("P(",seq(x$pars[1]),")",sep="") else names(x$pars) pars <- if(x$label=="categorical") x$pars[3:(2+x$pars[1])] else x$pars cat("Parameters: ", paste(paste(pnames, pars, sep=" = "), collapse=", ")) cat("\n") } msm.check.hmodel <- function(hmodel, nstates) { if (is.null(hmodel)) stop("Hidden model not specified") if (!is.list(hmodel)) stop("Hidden model should be a list") if (length(hmodel) != nstates) stop("hmodel of length ", length(hmodel), ", expected ", nstates) for (i in hmodel) { if (class(i) != "hmmdist") stop("hmodel should be a list of HMM distribution objects") } } msm.check.hcovariates <- function(hcovariates, qmodel) { if (!is.list(hcovariates)) stop("hcovariates should be a list") if (length(hcovariates) != qmodel$nstates) stop("hcovariates of length ", length(hcovariates), ", expected ", qmodel$nstates) for (i in hcovariates) { if (!is.null(i) ) if ( class(i) != "formula") stop("hcovariates should be a list of formulae or NULLs") } } msm.form.hmodel <- function(hmodel, hconstraint=NULL, initprobs=NULL, est.initprobs, qmodel) { nst <- length(hmodel) if (is.null(initprobs)) initprobs <- if (est.initprobs) rep(1/nst, nst) else c(1, rep(0, nst-1)) else { if (!is.numeric(initprobs)) stop("initprobs should be numeric") if (length(initprobs) != nst) stop("initprobs of length ", length(initprobs), ", should be ", nst) initprobs <- initprobs / sum(initprobs) } nipars <- nst - 1 labels <- sapply(hmodel, function(x) x$label) models <- match(labels, .msm.HMODELS) pars <- lapply(hmodel, function(x) x$pars) plabs <- lapply(hmodel, function(x) names(x$pars)) ## where non-misclassified outcome for hmmIdent distribution is not specified, this is ## just the state pars[labels=="identity"][sapply(pars[labels=="identity"], length) == 0] <- which(labels=="identity") plabs[labels=="identity"] <- "which" names(plabs) <- paste("state", 1:nst, sep=".") npars <- sapply(pars, length) links <- lapply(hmodel, function(x) x$link) links <- match(links, .msm.LINKFNS) parstate <- rep(1:nst, npars) firstpar <- c(0, cumsum(npars)[-qmodel$nstates]) pars <- unlist(pars) plabs <- unlist(plabs) locpars <- which(plabs == rep(.msm.LOCPARS[labels], npars)) names(pars) <- plabs hmod <- list(hidden=TRUE, nstates=qmodel$nstates, fitted=FALSE, models=models, labels=labels, npars=npars, nipars=nipars, totpars=sum(npars), pars=pars, plabs=plabs, parstate=parstate, firstpar=firstpar, links=links, locpars=locpars, initprobs=initprobs) class(hmod) <- "hmodel" hmod } msm.form.hcmodel <- function(hmodel, hcovdata, hcovinits, hconstraint) { nst <- hmodel$nstates ncovs <- if (is.null(hcovdata)) rep(0, nst) else sapply(hcovdata, function(x) x$ncovs) ncovs2 <- rep(rep(0, nst), hmodel$npars) ncovs2[hmodel$locpars] <- ncovs[hmodel$parstate[hmodel$locpars]] coveffstate <- rep(1:nst, tapply(ncovs2, hmodel$parstate, sum)) if (is.null(hcovinits)){ coveffect <- rep(0, sum(ncovs2)) } else { if (!(sum(ncovs2) == length(unlist(hcovinits)))) { warning("Initial values for hidden covariate effects do not match numbers of covariates, ignoring") coveffect <- rep(0, sum(ncovs2)) } coveffect <- unlist(hcovinits) if (!is.numeric(coveffect)) { warning("hcovinits should be numeric") coveffect <- rep(0, sum(ncovs2)) } } covlabels <- lapply(hcovdata, function(x) x$covlabels) covlabels <- unlist(covlabels[hmodel$parstate[hmodel$locpars]]) names(coveffect) <- covlabels hcmod <- list(ncovs=ncovs2, coveffect=coveffect, covlabels=covlabels, coveffstate=coveffstate, ncoveffs=length(coveffect)) hmodel <- c(hmodel, hcmod) hmodel$plabs[hmodel$plabs=="hcov"] <- paste("hcov.",covlabels,sep="") whichcovh <- lapply(hcovdata, function(x) x$whichcov) # factor contrasts as separate covariates hmodel$whichcovh <- unlist(rep(whichcovh, tapply(ncovs2>0, hmodel$parstate, sum))) whichcovh.orig <- lapply(hcovdata, function(x) x$whichcov.orig) # factors considered as one variable hmodel$whichcovh.orig <- unlist(rep(whichcovh.orig, tapply(ncovs2>0, hmodel$parstate, sum))) class(hmodel) <- "hmodel" hmodel } msm.form.icmodel <- function(hmodel, icovdata, icovinits) { nst <- hmodel$nstates nicovs <- if (is.null(icovdata)) 0 else icovdata$ncovs # distinct covariates nicovs <- rep(nicovs, nst-1) nicovs[hmodel$initprobs[-1] == 0] <- 0 # don't estimate cov effects on probs which are fixed to zero if (is.null(icovinits)) icoveffect <- rep(0, sum(nicovs)) else { icoveffect <- unlist(icovinits) if (!(length(icoveffect) == sum(nicovs))) { warning("Initial values for initial state covariate effects do not match numbers of covariates, ignoring") icoveffect <- rep(0, sum(nicovs)) } else if (!is.numeric(icoveffect)) { warning("icovinits should be numeric") icoveffect <- rep(0, sum(nicovs)) } } names(icoveffect) <- rep(icovdata$covlabels, each=sum(nicovs>0)) icmod <- list(nicovs=nicovs, icoveffect=icoveffect, nicoveffs=length(icoveffect), whichcovi=icovdata$whichcov) hmodel <- c(hmodel, icmod) class(hmodel) <- "hmodel" hmodel } ## Convert old-style misclassification model specification to a new-style HMM with categorical response msm.emodel2hmodel <- function(emodel, qmodel) { nst <- qmodel$nstates if (emodel$misc) { hidden <- TRUE nepars <- rowSums(emodel$imatrix) npars <- ifelse(nepars > 0, 2 + nst, 1) models <- ifelse(nepars > 0, 1, 2) pars <- plabs <- vector(nst, mode="list") parstate <- rep(1:nst, npars) names(pars) <- names(plabs) <- paste("state", 1:nst, sep=".") for (i in seq(nst)) { if (models[i]==1) { ppars <- emodel$ematrix[i,] plab <- rep("p", nst) plab[ppars==0] <- "p0" plab[i] <- "pbase" plabs[[i]] <- c("ncats", "basecat", plab) ## Baseline category is the probability of no misclassification (diagonal of ematrix) pars[[i]] <- c(nst, i, ppars) } else { plabs[[i]] <- "which" pars[[i]] <- i } } firstpar <- c(0, cumsum(npars)[-qmodel$nstates]) pars <- unlist(pars) plabs <- unlist(plabs) names(pars) <- plabs links <- ifelse(models==1, "log", "identity") links <- match(links, .msm.LINKFNS) labels <- .msm.HMODELS[models] locpars <- which(plabs == rep(.msm.LOCPARS[labels], npars)) hmod <- list(hidden=TRUE, fitted=FALSE, nstates=nst, models=models, labels=labels, npars=npars, totpars=sum(npars), links=links, locpars=locpars, pars=pars, plabs=plabs, parstate=parstate, firstpar=firstpar, nipars=emodel$nipars, initprobs=emodel$initprobs) hmod$constr <- msm.econstr2hconstr(emodel$constr, hmod) } else { hmod <- list(hidden=FALSE, fitted=FALSE, models=rep(0, qmodel$nstates), npars=0, ndpars=0) } class(hmod) <- "hmodel" hmod } msm.misccov2hcov <- function(misccovariates, emodel) { nst <- nrow(emodel$imatrix) whichst <- rep(1:nst, rowSums(emodel$imatrix)) hcov <- vector(nst, mode="list") for (i in 1:nst) { if (!any(whichst==i)) hcov[[i]] <- ~ 1 else hcov[[i]] <- misccovariates } hcov } msm.misccovinits2hcovinits <- function(misccovinits, hcovariates, emodel, ecmodel) { nst <- nrow(emodel$imatrix) whichst <- rep(1:nst, rowSums(emodel$imatrix)) hcovinits <- vector(nst, mode="list") for (i in 1:nst) { if (is.null(misccovinits)) hcovinits[[i]] <- rep(0, ecmodel$ncovs * rowSums(emodel$imatrix)[i]) else if (!any(whichst==i)) hcovinits[[i]] <- numeric(0) else hcovinits[[i]] <- as.vector(t(sapply(misccovinits, function(x)x[whichst==i]))) } hcovinits } msm.econstr2hconstr <- function(econstr, hmodel) { constr <- seq(length=hmodel$totpars) for (i in unique(econstr)) { constr[hmodel$plabs == "p"][econstr == i] <- min(constr[hmodel$plabs == "p"][econstr == i]) } constr } print.hmodel <- function(x, ...) { ci <- (x$fitted && x$foundse) cols <- if (ci) c("Estimate","LCL","UCL") else ("") if (!x$hidden) cat("Non-hidden Markov model\n") else { cat("Hidden Markov model, ") nst <- length(x$models) cat(nst, "states\n") cat("Initial state occupancy probabilities:") if (x$nipars > 0) { cat("\n") print(x$initprobs) cat("\n") if (any(x$nicovs > 0)) { cat("Covariates on log odds of initial states relative to state 1\n") print(x$icoveffect) } cat("\n") } else cat(paste(x$initprobs, collapse=","), "\n\n") for (i in 1:nst) { cat("State", i, "-", x$labels[i], "distribution\n") cat("Parameters: \n") if (x$label[i]=="categorical") pars <- print.hmmcat(x, i) else { pars <- as.matrix(x$pars[x$parstate==i]) if (ci) pars <- cbind(pars, matrix(x$ci[x$parstate==i ,], ncol=2)) dimnames(pars) <- list(x$plabs[x$parstate==i], cols) } if (any(x$ncovs[x$parstate==i] > 0)){ coveffs <- as.matrix(x$coveffect[x$coveffstate==i]) if (ci) coveffs <- cbind(coveffs, matrix(x$covci[x$coveffstate==i,], ncol=2)) rownames(coveffs) <- x$covlabels[x$coveffstate==i] pars <- rbind(pars, coveffs) } print(pars) cat("\n") } } } print.hmmcat <- function(x, i) { pars <- x$pars[x$parstate==i] res <- matrix(pars[3:(2+pars[1])], ncol=1) rownames(res) <- paste("P(",seq(length=pars[1]),")",sep="") if (x$fitted && x$foundse) { ci <- matrix(x$ci[x$parstate==i,], ncol=2) res <- cbind(res, ci[3:(2+pars[1]),]) colnames(res) <- c("Estimate","LCL","UCL") } else colnames(res) <- "prob" res } msm.form.hconstraint <- function(constraint, hmodel) { constr <- seq(length=hmodel$totpars) for (con in names(constraint)) { if ( ! (con %in% c(hmodel$plabs, hmodel$covlabels))) stop("parameter \"", con, "\" in hconstraint unknown") if (con %in% hmodel$plabs) { tc <- constraint[[con]] np <- length(tc) if (np != sum(hmodel$plabs==con)) stop("constraint for \"", con, "\" of length ", np, ", should be ", sum(hmodel$plabs==con)) for (i in unique(tc)) constr[hmodel$plabs == con][tc == i] <- min(constr[hmodel$plabs == con][tc == i]) } } match(constr, unique(constr)) } msm.form.hcovconstraint <- function(constraint, hmodel) { constr <- seq(length=hmodel$ncoveffs) for (con in names(constraint)) { if ( ! (con %in% c(hmodel$plabs, hmodel$covlabels))) stop("parameter \"", con, "\" in hconstraint unknown") if (con %in% hmodel$covlabels) { tc <- constraint[[con]] np <- length(tc) if (np != sum(hmodel$covlabels==con)) stop("constraint for \"", con, "\" of length ", np, ", should be ", sum(hmodel$covlabels==con)) for (i in unique(tc)) constr[hmodel$covlabels == con][tc == i] <- min(constr[hmodel$covlabels == con][tc == i]) } } match(constr, unique(constr)) } msm/R/outputs.R0000644000176000001440000021513112030337342013145 0ustar ripleyusers### METHODS FOR MSM OBJECTS print.msm <- function(x, ...) { cat("\nCall:\n", deparse(x$call), "\n\n", sep = "") if (!attr(x,"fixed")) { cat ("Maximum likelihood estimates: \n") covmessage <- if (x$qcmodel$ncovs == 0) "" else paste("with covariates set to ", (if (x$center) "their means" else "0")) for (i in c("baseline", x$qcmodel$covlabels)) { title <- if (i == "baseline") paste("Transition intensity matrix",covmessage,"\n") else paste("Log-linear effects of", i, "\n") cat (title, "\n") print.ci(x$Qmatrices[[i]], x$QmatricesL[[i]], x$QmatricesU[[i]]) cat("\n") } if (x$emodel$misc) { for (i in c("baseline", x$ecmodel$covlabels)) { title <- if (i == "baseline") paste("Misclassification matrix",covmessage,"\n") else paste("Effects of", i, "on log (P(state r)/P(baseline state))\n") cat (title, "\n") print.ci(x$Ematrices[[i]], x$EmatricesL[[i]], x$EmatricesU[[i]]) cat("\n") } if (any(x$paramdata$plabs[x$paramdata$notfixed] == "initp")) { cat("Initial state occupancy probabilities\n\n") print(x$hmodel$initprobs) cat("\n") if (any(x$hmodel$nicovs > 0)) { cat("Covariates on logit initial state probabilities\n") print(x$hmodel$icoveffect) } cat("\n") } } else if (x$hmodel$hidden) {print(x$hmodel); cat("\n")} } cat ("-2 * log-likelihood: ", x$minus2loglik, "\n") } summary.msm <- function(object, # fitted model times = NULL, # times at which to compare observed and expected prevalences timezero = NULL, initstates = NULL, covariates = "mean", misccovariates = "mean", hazard.scale = 1, ... ) { if (!inherits(object, "msm")) stop("expected object to be a msm model") prevalences <- prevalence.msm(object, times, timezero, initstates, covariates, misccovariates) if (object$qcmodel$ncovs > 0) { if (missing (hazard.scale)) hazard.scale <- rep(1, object$data$covdata$ncovs) hazard <- hazard.msm(object) } else {hazard <- hazard.scale <- NULL} ret <- list(prevalences=prevalences, hazard=hazard, hazard.scale=hazard.scale) class(ret) <- "summary.msm" ret } print.summary.msm <- function(x,...) { if (!is.null(x$prevalences)) { cat("\nObserved numbers of individuals occupying states at each time\n\n") print(x$prevalences$Observed) cat("\nExpected numbers of individuals occupying states at each time\n\n") print(x$prevalences$Expected) cat("\nObserved prevalences of states (percentages of population at risk)\n\n") print(x$prevalences$"Observed percentages") cat("\nExpected prevalences of states (percentages of population at risk)\n\n") print(x$prevalences$"Expected percentages") } i <- 1 for (cov in names(x$hazard)) { cat ("\nTransition hazard ratios corresponding to covariate effects\n\n" ) cat (cov, " ( unit of",x$hazard.scale[i],")\n") print(round(x$hazard[[cov]], 2)) i <- i+1 } invisible() } ### Estimated survival probability from each state plot.msm <- function(x, from=NULL, to=NULL, range=NULL, covariates="mean", legend.pos=NULL, xlab="Time", ylab="Fitted survival probability", lwd=1,...) { if (!inherits(x, "msm")) stop("expected x to be a msm model") if (is.null(from)) from <- transient.msm(x) else { if (!is.numeric(from)) stop("from must be numeric") if (any (! (from %in% 1:x$qmodel$nstates ) ) ) stop("from must be a vector of states in 1, ..., ", x$qmodel$nstates) } if (is.null(to)) to <- max(absorbing.msm(x)) else { if (!is.numeric(to)) stop("to must be numeric") if (! (to %in% absorbing.msm(x) ) ) stop("to must be an absorbing state") } if (is.null(range)) rg <- range(x$data$time) else { if (!is.numeric(range) || length(range)!= 2) stop("range must be a numeric vector of two elements") rg <- range } timediff <- (rg[2] - rg[1]) / 50 times <- seq(rg[1], rg[2], timediff) pr <- numeric() cols <- rainbow(length(from)) for (t in times) pr <- c(pr, pmatrix.msm(x, t, times[1], covariates)[from[1], to]) plot(times, 1 - pr, type="l", xlab=xlab, ylab=ylab, lwd=lwd, ylim=c(0,1), lty = 1, col=cols[1],...) lt <- 2 for (st in from[-1]){ pr <- numeric() for (t in times) pr <- c(pr, pmatrix.msm(x, t, times[1], covariates)[st, to]) lines(times, 1 - pr, type="l", lty = lt, lwd=lwd, col=cols[lt],...) lt <- lt+1 } if (!is.numeric(legend.pos) || length(legend.pos) != 2) legend.pos <- c(max(times) - 15*timediff, 1) legend(legend.pos[1], legend.pos[2], legend=paste("From state",from), lty = seq(lt-1), col=cols, lwd=lwd) invisible() } ### Plot KM estimate of time to first occurrence of each state plotprog.msm <- function(formula, subject, data, legend.pos=NULL, xlab="Time", ylab="1 - incidence probability", lwd=1, xlim=NULL, mark.time=TRUE, ...) { data <- na.omit(data) mf <- model.frame(formula, data=data) state <- mf[,1] time <- mf[,2] if (!is.null(data)) subject <- eval(substitute(subject), as.list(data), parent.frame()) subject <- match(subject, unique(subject)) rg <- range(time) if (is.null(xlim)) xlim=rg plot(0, xlim=xlim, ylim=c(0,1), type="n", xlab=xlab, ylab=ylab, ...) states <- sort(unique(state))[-1] cols <- rainbow(length(states)) for (i in states) { dat <- cbind(subject, time, state) st <- as.data.frame( do.call("rbind", by(dat, subject, function(x) { c(anystate = if(any(x[,"state"]>=i)) 1 else 0, mintime = if(any(x[,"state"]>=i)) min(x[x[,"state"] >= i, "time"]) else max(x[,"time"])) } ))) # slow lines(survfit(Surv(st$mintime,st$anystate) ~ 1), col=cols[i-1], lty=i-1, lwd=lwd, mark.time=mark.time, ...) } timediff <- (rg[2] - rg[1]) / 50 if (!is.numeric(legend.pos) || length(legend.pos) != 2) legend.pos <- c(max(time) - 25*timediff, 1) legend(legend.pos[1], legend.pos[2], lty=states-1, lwd=lwd, col=cols, legend=paste("To state", states, c(rep("or greater", length(states)-1), ""))) invisible() } ### Likelihood surface plots surface.msm <- function(x, params=c(1,2), np=10, type=c("contour","filled.contour","persp","image"), point=NULL, xrange=NULL, yrange=NULL,...) { type <- match.arg(type) if (is.null(point)) point <- x$paramdata$opt$par se <- sqrt(diag(solve(0.5 * x$paramdata$opt$hessian))) i1 <- params[1]; i2 <- params[2] if (is.null(xrange)) { pmin <- point[i1] - 2*se[i1] pmax <- point[i1] + 2*se[i1] p1 <- seq(pmin, pmax, length=np) } else p1 <- seq(xrange[1], xrange[2], length=np) if (is.null(yrange)){ pmin <- point[i2] - 2*se[i2] pmax <- point[i2] + 2*se[i2] p2 <- seq(pmin, pmax, length=np) } else p2 <- seq(yrange[1], yrange[2], length=np) z <- matrix(nrow=np, ncol=np) for (i in 1:np) { for (j in 1:np) { point[i1] <- p1[i]; point[i2] <- p2[j] z[i,j] <- -0.5*likderiv.msm(point, 0, x$data, x$qmodel, x$qcmodel, x$cmodel, x$hmodel, x$paramdata) } } switch(type, contour = contour(p1, p2, z, ...), filled.contour = filled.contour(p1, p2, z, ...), image = image(p1, p2, z, ...), persp = persp(p1, p2, z, zlab="Log-likelihood",...) ) invisible() } contour.msm <- function(x, ...) { surface.msm(x, type="contour",...) } persp.msm <- function(x, ...) { surface.msm(x, type="persp",...) } image.msm <- function(x, ...) { surface.msm(x, type="image",...) } ### Given a "covariates" argument of an extractor function containing ### covariates which interact in the model, form the corresponding ### "covariates" argument with the interactions expanded. expand.interactions.msm <- function(covariates, covlabels){ cn.nointer <- names(covariates) elist <- strsplit(covlabels, ":") elist <- lapply(elist, function(x)covariates[x]) elist <- lapply(elist, function(x)prod(unlist(x))) names(elist) <- covlabels elist } ### Given a "covariates" argument of an extractor function containing ### factor covariates, convert the factor covariates to numeric ### contrasts. For example, for a categorical covariate "smoke" with ### three levels "NON","CURRENT","EX", with baseline level "NON", ### convert list(smoke="CURRENT") to list(smokeCURRENT=1, smokeEX=0) ### Any unspecified covariate values are set to zero. ### Any unknown covariates are dropped with a warning. ### covlabels includes interactions factorcov2numeric.msm <- function(covariates, x, intmisc="intens") { covdata <- if (intmisc=="intens") x$data$covdata else x$data$misccovdata covnames <- names(covdata$covfactor) if (is.null(names(covariates))) { if (length(covariates)!=length(covnames)) stop("Expected covariate list of length ",length(covnames)) names(covariates) <- covnames } all.covnames <- union(x$data$covdata$covlabels,covnames) # including both factor and contrast names miss.covs <- ! names(covariates) %in% all.covnames if (any(miss.covs)){ plural <- if(sum(miss.covs)>1) "s" else "" warning("Covariate",plural," \"", paste(names(covariates)[which(!names(covariates) %in% all.covnames)], collapse=", "), "\" unknown, ignoring") } cfac <- covariates[names(covariates) %in% covnames[which(covdata$covfactor)]] cnum <- covariates[! names(covariates) %in% covnames[which(covdata$covfactor)]] cfac.new <- list() for (i in seq(along=cfac)) { levs.i <- covdata$covfactorlevels[[names(cfac)[[i]]]] cfac.i <- rep(0, length(levs.i)) if (! cfac[[i]] %in% levs.i) stop("Level \"", cfac[[i]], "\" of covariate ", names(cfac)[[i]], " unknown") cfac.i[match(cfac[[i]], levs.i)] <- 1 names(cfac.i) <- paste(names(cfac)[[i]], levs.i, sep="") cfac.i <- as.list(cfac.i[-1]) cfac.new <- c(cfac.new, cfac.i) } covlabels.noint <- covdata$covlabels[setdiff(seq(along=covdata$covlabels), grep(":", covdata$covlabels))] covs.out <- as.list(numeric(length(covlabels.noint))) names(covs.out) <- covlabels.noint covs.out[names(cnum)] <- cnum covs.out[names(cfac.new)] <- cfac.new covs.out <- expand.interactions.msm(covs.out, covdata$covlabels) covs.out } ### Extract the transition intensity matrix at given covariate values qmatrix.msm <- function(x, # fitted msm model covariates = "mean", # covariate values to calculate transition matrix for sojourn = FALSE, # also calculate mean sojourn times and their standard errors ci=c("delta","normal","bootstrap","none"), cl=0.95, B=1000 ) { if (!inherits(x, "msm")) stop("expected x to be a msm model") qematrix.msm(x, covariates, intmisc="intens", sojourn=sojourn, ci=ci, cl=cl, B=B) } ### Extract the misclassification probability matrix at given covariate values ematrix.msm <- function(x, covariates = "mean", ci=c("delta","normal","bootstrap","none"), cl=0.95, B=1000) { if (!inherits(x, "msm")) stop("expected x to be a msm model") if (!x$emodel$misc) NULL else qematrix.msm(x, covariates, intmisc="misc", sojourn=FALSE, ci=ci, cl=cl, B=B) } ### Extract either intensity or misclassification matrix qematrix.msm <- function(x, covariates="mean", intmisc="intens", sojourn=FALSE, ci=c("delta","normal","bootstrap","none"), cl=0.95, B=1000) { nst <- x$qmodel$nstates if (intmisc=="intens"){ ni <- x$qmodel$npars if (is.list(covariates)) nc <- x$qcmodel$ncovs else if (((covariates == "mean") && x$center) || ((covariates == 0 ) && !x$center)) nc <- 0 else nc <- x$qcmodel$ncovs if (nc==0){ logest <- x$Qmatrices$logbaseline mat <- exp(logest) mat[x$qmodel$imatrix == 0] <- 0 mat <- msm.fixdiag.qmatrix(mat) } covlabels <- x$qcmodel$covlabels covmeans <- x$qcmodel$covmeans } else if (intmisc=="misc"){ ni <- x$emodel$npars nc <- if (!is.list(covariates) && ((covariates == "mean") && x$center) || ((covariates == 0) && !x$center)) 0 else x$ecmodel$ncovs if (nc==0){ logest <- x$Ematrices$logitbaseline plabs <- x$emodel$imatrix; plabs[x$emodel$imatrix==1] <- "p"; diag(plabs)[rowSums(x$emodel$imatrix)>0] <- "pbase" mat <- matrix(msm.mninvlogit.transform(t(logest), t(plabs), rep(1:nst, each=nst)), nrow=nst, byrow=TRUE) diag(mat)[rowSums(x$emodel$imatrix)==0] <- 1 } covlabels <- x$ecmodel$covlabels covmeans <- x$ecmodel$covmeans } se <- lse <- numeric(ni) if ((nc == 0) && (is.list(covariates)) && (length(covariates) > 0)) warning(paste("Ignoring covariates - no covariates in model for", if (intmisc=="intens") "transition intensities" else "misclassification probabilities")) covs.orig <- covariates # with factors as labels if (nc > 0) { if (!is.list(covariates)) { if (covariates == 0 && x$center) # if no centering, then can't end up in this block, as no need to adjust. {covariates <- list(); for (i in 1 : nc) covariates[[covlabels[i]]] <- 0} else if (covariates == "mean" && !x$center) # if center, then can't end up in this block, as no need to adjust. {covariates <- list(); for (i in 1 : nc) covariates[[covlabels[i]]] <- covmeans[i]} else stop("covariates argument must be 0, \"mean\", or a list of values for each named covariate") } else { ## Check supplied list of covariate values, convert factors to numeric contrasts, expand interactions, set unknown values to zero. ## Maybe merge above block of code with this? tidy up other calls e.g. qratio.se, qmatrix.diagse? covariates <- factorcov2numeric.msm(covariates, x, intmisc) } if (intmisc=="intens"){ logest <- x$Qmatrices$logbaseline for (i in 1 : nc) { covi <- if (x$center) covariates[[i]] - covmeans[i] else covariates[[i]] logest <- logest + x$Qmatrices[[i+1]] * covi } mat <- exp(logest) mat[x$qmodel$imatrix == 0] <- 0 mat <- msm.fixdiag.qmatrix(mat) } else if (intmisc=="misc"){ logest <- x$Ematrices$logitbaseline for (i in 1 : nc) { covi <- if (x$center) covariates[[i]] - covmeans[i] else covariates[[i]] logest <- logest + x$Ematrices[[i+1]] * covi } plabs <- x$emodel$imatrix; plabs[x$emodel$imatrix==1] <- "p"; diag(plabs)[rowSums(x$emodel$imatrix)>0] <- "pbase" mat <- matrix(msm.mninvlogit.transform(t(logest), t(plabs), rep(1:nst, each=nst)), nrow=nst, byrow=TRUE) diag(mat)[rowSums(x$emodel$imatrix)==0] <- 1 } } if (sojourn) soj = -1 / diag(mat) ci <- match.arg(ci) if (x$foundse && (ci!="none")) { if (ci == "delta") { ## Work out standard errors. ## Transformation for delta method is (intensities) ## exp (x1 + x2 (cov1 - covmean1) + x3 (cov2 - covmean2) + ... ) ## expit(sum covs) / (1 + expit(sum(covs))) or 1 / (1 + expit(sum(covs))) ## Use delta method to find approximate SE of the transform on log scale ## Work out a CI for this by assuming normal and transforming back coefs <- if (nc==0) 1 else c(1, if (x$center) unlist(covariates) - covmeans else unlist(covariates)) semat <- lsemat <- lmat <- umat <- matrix(0, nst, nst) if (intmisc=="intens") { form <- as.formula(paste("~", expsum(seq(nc + 1), coefs))) lform <- as.formula(paste("~", lsum(seq(nc + 1), coefs))) ## indices into estimates vector of all intens/miscs, intens covs / misc covs inds <- seq(length=x$qmodel$npars + x$qcmodel$npars) for (i in 1 : ni){ ## indices into estimates vector of all intens/miscs, intens covs / misc covs for that particular fromstate-tostate. parinds <- inds[seq(i, (nc * ni + i), ni)] ests <- x$estimates[parinds] cov <- x$covmat[parinds, parinds] se[i] <- deltamethod(form, ests, cov) lse[i] <- deltamethod(lform, ests, cov) } ivector <- as.numeric(t(x$qmodel$imatrix)) semat[ivector == 1] <- se; semat <- t(semat) lsemat[ivector == 1] <- lse; lsemat <- t(lsemat) lmat <- exp(logest - qnorm(1 - 0.5*(1 - cl))*lsemat) umat <- exp(logest + qnorm(1 - 0.5*(1 - cl))*lsemat) imatrix <- x$qmodel$imatrix lmat[imatrix == 0] <- umat[imatrix == 0] <- 0 ## SEs of diagonal entries diagse <- qmatrix.diagse.msm(x, covariates, sojourn, ni, ivector, nc, covlabels, covmeans) diag(semat) <- diagse$diagse diag(lmat) <- sign(diag(mat)) * (exp(log(abs(diag(mat))) - sign(diag(mat)) * qnorm(1 - 0.5*(1 - cl))*diagse$diaglse)) diag(umat) <- sign(diag(mat)) * (exp(log(abs(diag(mat))) + sign(diag(mat)) * qnorm(1 - 0.5*(1 - cl))*diagse$diaglse)) if (sojourn) { sojse <- diagse$sojse sojl <- exp(log(soj) - qnorm(1 - 0.5*(1 - cl))*diagse$sojlse) soju <- exp(log(soj) + qnorm(1 - 0.5*(1 - cl))*diagse$sojlse) } } else if (intmisc=="misc"){ p.se <- p.se.msm(x$qmodel, x$emodel, x$hmodel, x$qcmodel, x$ecmodel, x$paramdata, x$center, covariates) ivector <- as.numeric(t(x$emodel$imatrix)) semat[ivector==1] <- p.se$se[p.se$lab=="p"]; semat <- t(semat) lmat[ivector==1] <- p.se$LCL[p.se$lab=="p"]; lmat <- t(lmat) umat[ivector==1] <- p.se$UCL[p.se$lab=="p"]; umat <- t(umat) diag(semat)[rowSums(x$emodel$imatrix)>0] <- p.se$se[p.se$lab=="pbase"] diag(lmat)[rowSums(x$emodel$imatrix)>0] <- p.se$LCL[p.se$lab=="pbase"] diag(umat)[rowSums(x$emodel$imatrix)>0] <- p.se$UCL[p.se$lab=="pbase"] diag(lmat)[rowSums(x$emodel$imatrix)==0] <- diag(umat)[rowSums(x$emodel$imatrix)==0] <- 1 } } else if (ci %in% c("normal","bootstrap")) { q.ci <- if (ci=="normal") qematrix.normci.msm(x, covs.orig, intmisc, sojourn, cl, B) else qematrix.ci.msm(x, covs.orig, intmisc, sojourn, cl, B) if (sojourn) { soj.ci <- q.ci$soj q.ci <- q.ci$q sojl <- soj.ci[1,]; soju <- soj.ci[2,]; sojse <- soj.ci[3,] } lmat <- q.ci[,,1]; umat <- q.ci[,,2]; semat <- q.ci[,,3] } dimnames(semat) <- dimnames(lmat) <- dimnames(umat) <- dimnames(x$qmodel$qmatrix) } else semat <- lmat <- umat <- sojse <- sojl <- soju <- NULL dimnames(mat) <- dimnames(x$qmodel$qmatrix) if (ci=="none") res <- if (sojourn) soj else mat else { if (sojourn) res <- list(estimates=mat, SE=semat, L=lmat, U=umat, sojourn=soj, sojournSE=sojse, sojournL=sojl, sojournU=soju) else res <- list(estimates=mat, SE=semat, L=lmat, U=umat) class(res) <- "msm.est" } res } print.msm.est <- function(x, digits=NULL, ...) { if (is.list(x)) print.ci(x$estimates, x$L, x$U, digits=digits) else print(unclass(x)) } print.msm.est.cols <- function(x, digits=NULL, diag=TRUE, ...) { inc <- if (diag) (x$estimates>0 | x$estimates<0) else (x$estimates>0) res <- cbind(x$estimates[inc], x$L[inc], x$U[inc]) rn <- rownames(x$estimates)[row(inc)[inc]] cn <- colnames(x$estimates)[col(inc)[inc]] rownames(res) <- paste(rn, cn, sep="-") colnames(res) <- c("Estimate", "LCL", "UCL") res } "[.msm.est" <- function(x, i, j, drop=FALSE){ Narg <- nargs() - (!missing(drop)) # number of args including x, excluding drop if ((missing(i) && missing(j))) res <- x else if (!is.list(x)) res <- unclass(x)[i,j] else { if (missing(j) && (Narg==2)) stop("Two dimensions must be supplied, found only one") if ("SE" %in% names(x)) { x <- array(unlist(x), dim=c(dim(x[[1]]),4)) dimnames(x) <- list(rownames(x[[1]]), colnames(x[[1]]), c("estimate","SE","lower","upper")) } else { x <- array(unlist(x), dim=c(dim(x[[1]]),3)) dimnames(x) <- list(rownames(x[[1]]), colnames(x[[1]]), c("estimate","lower","upper")) } res <- x[i,j,] } res } print.ci <- function(x, l, u, digits=NULL) { est <- formatC(x, digits=digits) if (!is.null(l)) { low <- formatC(l, digits=digits) upp <- formatC(u, digits=digits) res <- paste(est, " (", low, ",", upp, ")", sep="") res[x==0] <- 0 } else res <- est dim(res) <- dim(x) dimnames(res) <- dimnames(x) names(res) <- names(x) print(res, quote=FALSE) } ### Work out standard errors of diagonal entries of intensity matrix, or sojourn times, using delta method qmatrix.diagse.msm <- function(x, covariates="mean", sojourn, ni, ivector, nc, covlabels, covmeans) { nst <- x$qmodel$nstates diagse <- diaglse <- sojse <- sojlse <- numeric(nst) indmat <- matrix(ivector, nst, nst) indmat[indmat==1] <- seq(length = ni) indmat <- t(indmat) # matrix of indices of estimate vector inds <- seq(length = ni + ni*nc) cur.i <- 1 if (covariates == 0 && nc > 0) {covariates <- list(); for (i in 1 : nc) covariates[[covlabels[i]]] <- 0} coefs <- if (nc==0) 1 else c(1, if (x$center) unlist(covariates) - covmeans else unlist(covariates)) for (i in 1:nst){ ## Transformation for delta method is ## exp(x1 + x2 (cov1 - covmean1) + x3 (cov2 - covmean2) + ... ) + ## exp(x4 + x5 (cov1 - covmean1) + x6 (cov2 - covmean2) + ... ) + (or expit(...)) nir <- sum(indmat[i,-i] > 0) # number of intens/misc for current state if (nir > 0) { qf <- expsum.formstr(nir, inds, cur.i, ni, nc, coefs) form <- as.formula(paste("~", paste(qf$formstr, collapse = " + "))) lform <- as.formula(paste("~ log (", paste(qf$formstr, collapse = " + "), ")")) ests <- x$estimates[qf$parinds2] cov <- x$covmat[qf$parinds2, qf$parinds2] diagse[i] <- deltamethod(form, ests, cov) diaglse[i] <- deltamethod(lform, ests, cov) if (sojourn){ ## Mean sojourn times are -1 / diagonal entries of q matrix. Calculate their SEs and CIs. form <- as.formula(paste("~ 1 / (", paste(qf$formstr, collapse = " + "), ")")) lform <- as.formula(paste("~ log ( 1 / (", paste(qf$formstr, collapse = " + "), ")", ")")) sojse[i] <- deltamethod(form, ests, cov) sojlse[i] <- deltamethod(lform, ests, cov) } cur.i <- cur.i + nir } else diagse[i] <- 0 } list(diagse=diagse, diaglse=diaglse, sojse=sojse, sojlse=sojlse) } ### Work out SE and CIs of misclassification probabilities for given covariate values. ### Know SEs of beta_rs, use delta method to calculate. ### SE of p_rs = exp(beta_rs x) / (1 + sum(exp(beta_rs x))) (non-baseline p) or 1 / (1 + sum(exp(beta_rs x))) (baseline p). ### To calculate symmetric CI for resulting p_rs, assume logit(p_rs) normal, and use SE(logit(p_rs)) calculated by delta method. p.se.msm <- function(qmodel, emodel, hmodel, qcmodel, ecmodel, paramdata, center, covariates="mean") { nst <- qmodel$nstates inds <- (qmodel$npars + qcmodel$npars + 1) : (qmodel$npars + qcmodel$npars + sum(hmodel$npars) + hmodel$ncoveffs) ni <- emodel$npars nc <- if (!is.list(covariates) && ((covariates == "mean") && center) || ((covariates == 0) && !center)) 0 else ecmodel$ncovs coefs <- if (!is.list(covariates) && (covariates=="mean")) 1 else c(1, unlist(covariates) - ecmodel$covmeans) ppars <- hmodel$plabs %in% c("p","pbase") res <- data.frame(lab=hmodel$plabs[ppars]) hmmallpars <- !(paramdata$plabs %in% c("qbase","qcov","initp","initp0","initpcov")) res$est <- msm.mninvlogit.transform(paramdata$params[paramdata$hmmpars], hmodel$plabs, hmodel$parstate)[ppars] res$parstate <- hmodel$parstate[ppars] res$se <- res$lse <- res$LCL <- res$UCL <- res$inds <- res$strs <- 0 cur.i <- 1 for (i in unique(res$parstate)) { nir <- sum(hmodel$parstate[hmodel$plabs=="p"] == i) # number of independent misc probs for current state p.inds <- which(hmodel$plabs=="p" & hmodel$parstate==i) # indices into HMM parameter vector of logit baseline p for that state cov.inds <- sum(hmodel$npars) + (cur.i-1)*nc + seq(length=(nc*nir)) # indices into HMM parameter vector of corresp cov effects parinds <- numeric(); formstr <- character(nir) for (j in 1:nir) { formstr[j] <- expsum(1:((nc+1)*nir), coefs) # string of form exp(1*x1+beta1*x2*beta2*x3), exp(x4+beta*x5+...) parinds <- c(parinds, p.inds[j], cov.inds[(j-1)*nc + seq(length=nc)]) # indices into HMM par vector corresp to x1,x2,x3,... } sumstr <- paste(formstr, collapse = " + ") # "parinds" are formstr <- paste("1 / (1 + ", sumstr, ")") form <- as.formula(paste("~ ",formstr)) lform <- as.formula(paste("~ log( (", formstr, ") / (1 - ", formstr, "))")) ests <- paramdata$params[hmmallpars][parinds] cov <- paramdata$covmat[hmmallpars,hmmallpars][parinds, parinds] res$se[res$parstate==i & res$lab=="pbase"] <- deltamethod(form, ests, cov) res$lse[res$parstate==i & res$lab=="pbase"] <- deltamethod(lform, ests, cov) res$strs[res$parstate==i & res$lab=="pbase"] <- paste(as.character(form),collapse="") res$inds[res$parstate==i & res$lab=="pbase"] <- paste(parinds,collapse=",") for (j in 1:nir){ istr <- expsum(((j-1)*(nc+1)+1):(j*(nc+1)), coefs) formstr <- paste(istr, "/ (1 + ", sumstr, ")") form <- as.formula(paste("~ ",formstr)) lform <- as.formula(paste("~ log( (", formstr, ") / (1 - ", formstr, "))")) res$se[res$parstate==i & res$lab=="p"][j] <- deltamethod(form, ests, cov) res$lse[res$parstate==i & res$lab=="p"][j] <- deltamethod(lform, ests, cov) res$strs[res$parstate==i & res$lab=="p"][j] <- paste(as.character(form), collapse="") res$inds[res$parstate==i & res$lab=="p"][j] <- paste(parinds,collapse=",") } cur.i <- cur.i + nir } res$LCL <- plogis(qlogis(res$est) - qnorm(0.975)*res$lse) res$UCL <- plogis(qlogis(res$est) + qnorm(0.975)*res$lse) res } ## Form a string, exp ( x1 1 + x2 (cov1 - covmean1) + x3 (cov2 - covmean2) + ... ) ## to be made into a formula for deltamethod. ## Also return indices of estimates and covariance matrix output from optim() to use ## to inform deltamethod expsum.formstr <- function(nir, inds, cur.i, ni, nc, coefs) { formstr <- character(nir) parinds <- numeric() for (j in (cur.i : (cur.i + nir - 1))) { indj <- seq(j, (nc * ni + j), ni) parinds <- c(parinds, inds[indj]) # first 1 5 7, then 2 5 7 } ## e.g. parinds = 1 5 7 2 5 7 becomes xinds = 1 3 4 2 3 4 parinds2 <- sort(unique(parinds)) xinds <- rank(parinds2)[match(parinds, parinds2)] for (j in 1:nir) formstr[j] <- expsum(xinds[1:(nc+1) + (j-1)*(nc+1)], coefs) list(formstr=formstr, parinds=parinds, parinds2=parinds2) } ## Form a string, exp ( x1 1 + x2 (cov1 - covmean1) + x3 (cov2 - covmean2) + ... ) ## to be made into a formula for deltamethod expsum <- function(inds, coefs) { xseq <- paste("x", inds, sep="") inprod <- paste(paste(coefs, xseq, sep="*"), collapse=" + ") paste("exp(", inprod, ")", sep="") } lsum <- function(inds, coefs) { xseq <- paste("x", inds, sep="") paste(paste(coefs, xseq, sep="*"), collapse=" + ") } ### Extract a ratio of transition intensities at given covariate values qratio.msm <- function(x, ind1, ind2, covariates = "mean", ci=c("delta","normal","bootstrap","none"), cl=0.95, B=1000) { q <- qmatrix.msm(x, covariates, ci="none") if (!is.numeric(ind1) || length(ind1) != 2 || !is.numeric(ind2) || length(ind2) != 2) stop("ind1 and ind2 must be numeric vectors of length 2") if (any (! (ind1 %in% 1 : x$qmodel$nstates)) | any (! (ind2 %in% 1 : x$qmodel$nstates) ) ) stop("ind1 and ind2 must be pairs of states in 1, ..., ", x$qmodel$nstates) if (q[ind2[1], ind2[2]] == 0) stop (paste("Denominator q[",ind2[1],",",ind2[2],"", "] is zero\n", sep="")) else if (q[ind1[1], ind1[2]] == 0) { warning(paste ("Numerator q[",ind1[1],",",ind1[2],"", "] is zero\n", sep="")) estimate <- se <- 0 } else { estimate <- q[ind1[1], ind1[2]] / q[ind2[1], ind2[2]] ci <- match.arg(ci) if (x$foundse && (ci != "none")) { if (ci == "delta") { se <- qratio.se.msm(x, ind1, ind2, covariates, cl)$se lse <- qratio.se.msm(x, ind1, ind2, covariates, cl)$lse L <- exp ( log(abs(estimate)) - sign(estimate)*qnorm(1 - 0.5*(1 - cl)) * lse ) * sign(estimate) U <- exp ( log(abs(estimate)) + sign(estimate)*qnorm(1 - 0.5*(1 - cl)) * lse ) * sign(estimate) } else if (ci=="normal") { q.ci <- qratio.normci.msm(x, ind1, ind2, covariates, cl, B) L <- q.ci[1]; U <- q.ci[2]; se=q.ci[3] } else if (ci=="bootstrap") { q.ci <- qratio.ci.msm(x, ind1, ind2, covariates, cl, B) L <- q.ci[1]; U <- q.ci[2]; se=q.ci[3] } } else {se <- L <- U <- NULL} } c(estimate=estimate, se=se, L=L, U=U) } ### Work out standard error of a ratio of intensities using delta method ### Uuugh. What a fuss for one little number. qratio.se.msm <- function(x, ind1, ind2, covariates="mean", cl=0.95) { nst <- x$qmodel$nstates ni <- x$qmodel$npars nc <- if (!is.list(covariates) && (covariates == "mean")) 0 else x$qcmodel$ncovs indmat <- t(x$qmodel$imatrix) indmat[indmat == 1] <- seq(length = x$qmodel$npars) indmat <- t(indmat) # matrix of indices of estimate vector inds <- seq(length = x$qmodel$npars+x$qcmodel$npars) # identifiers for q and beta parameters if (is.list(covariates)) { covariates <- factorcov2numeric.msm(covariates, x) } if (!is.list(covariates) && covariates == 0) {covariates <- list(); for (i in 1 : nc) covariates[[x$qcmodel$covlabels[i]]] <- 0} coefs <- if (!is.list(covariates) && (covariates=="mean")) 1 else c(1, unlist(covariates) - x$qcmodel$covmeans) parinds <- numeric() indmatrow.n <- indmat[ind1[1],-ind1[1]] nir.n <- sum(indmatrow.n > 0) indmatrow.d <- indmat[ind2[1],-ind2[1]] nir.d <- sum(indmatrow.d > 0) formstr.n <- character(nir.n) formstr.d <- character(nir.d) if (ind1[1]!=ind1[2] && ind2[1]!=ind2[2]) { # both intensities are off-diagonal parinds <- c(inds[indmat[ind1[1],ind1[2]] - 1 + seq(1, (nc * ni + 1), ni)], inds[indmat[ind2[1],ind2[2]] - 1 + seq(1, (nc * ni + 1), ni)]) parinds2 <- sort(unique(parinds)) xinds <- rank(parinds2)[match(parinds, parinds2)] formstr.n <- expsum(xinds[1:(nc+1)], coefs) formstr.d <- expsum(xinds[1:(nc+1) + nc+1] , coefs) } else if (ind1[1]!=ind1[2] && ind2[1]==ind2[2]) { # numerator off-diagonal, denom diagonal parinds <- inds[indmat[ind1[1],ind1[2]] - 1 + seq(1, (nc * ni + 1), ni)] cur.i <- min(indmatrow.d[indmatrow.d>0]) for (j in 1:nir.d) parinds <- c(parinds, inds[cur.i - 1 + seq(j, (nc * ni + j), ni)]) parinds2 <- sort(unique(parinds)) xinds <- rank(parinds2)[match(parinds, parinds2)] formstr.n <- expsum(xinds[1:(nc+1)], coefs) for (j in 1:nir.d) formstr.d[j] <- expsum(xinds[1:(nc+1) + j*(nc+1)], coefs) } else if (ind1[1]==ind1[2] && ind2[1]!=ind2[2]) { # numerator diagonal, denom off-diagonal cur.i <- min(indmatrow.n[indmatrow.n>0]) for (j in 1:nir.n) parinds <- c(parinds, inds[cur.i - 1 + seq(j, (nc * ni + j), ni)]) parinds <- c(parinds, inds[indmat[ind2[1],ind2[2]] - 1 + seq(1, (nc * ni + 1), ni)]) parinds2 <- sort(unique(parinds)) xinds <- rank(parinds2)[match(parinds, parinds2)] for (j in 1:nir.n) formstr.n[j] <- expsum(xinds[1:(nc+1) + (j-1)*(nc+1)], coefs) formstr.d <- expsum(xinds[nir.n*(nc+1) + 1:(nc+1)], coefs) } else if (ind1[1]==ind1[2] && ind2[1]==ind2[2]) { # both intensities diagonal cur.i <- min(indmatrow.n[indmatrow.n>0]) for (j in 1:nir.n) parinds <- c(parinds, inds[cur.i - 1 + seq(j, (nc * ni + j), ni)]) cur.i <- min(indmatrow.d[indmatrow.d>0]) for (j in 1:nir.d) parinds <- c(parinds, inds[cur.i - 1 + seq(j, (nc * ni + j), ni)]) parinds2 <- sort(unique(parinds)) xinds <- rank(parinds2)[match(parinds, parinds2)] for (j in 1:nir.n) formstr.n[j] <- expsum(xinds[1:(nc+1) + (j-1)*(nc+1)], coefs) for (j in 1:nir.d) formstr.d[j] <- expsum(xinds[nir.n*(nc+1) + 1:(nc+1) + (j-1)*(nc+1)], coefs) } num <- paste(formstr.n, collapse = " + ") denom <- paste(formstr.d, collapse = " + ") form <- as.formula(paste("~", "(", num, ") / (", denom, ")")) lform <- as.formula(paste("~ ", "log (", num, ") - log (", denom, ")")) ests <- x$estimates[parinds2] cov <- x$covmat[parinds2,parinds2] se <- deltamethod(form, ests, cov) lse <- deltamethod(lform, ests, cov) list(se=se, lse=lse) } ### Extract the transition probability matrix at given covariate values pmatrix.msm <- function(x, # fitted msm model t = 1, # time interval t1 = 0, # start time for pci models covariates = "mean", # covariate values to calculate transition matrix for ci=c("none","normal","bootstrap"), # calculate a confidence interval # using either simulation from asymptotic normal dist of MLEs, or bootstrap cl = 0.95, # width of symmetric confidence interval B = 1000, # number of bootstrap replicates or normal simulations ... ) { if (!is.numeric(t) || (t < 0)) stop("t must be a positive number") if (is.null(x$pci)) { q <- qmatrix.msm(x, covariates, ci="none") p <- MatrixExp(q, t, ...) colnames(p) <- rownames(p) <- rownames(q) ci <- match.arg(ci) p.ci <- switch(ci, bootstrap = pmatrix.ci.msm(x=x, t=t, t1=t1, covariates=covariates, cl=cl, B=B), normal = pmatrix.normci.msm(x=x, t=t, t1=t1, covariates=covariates, cl=cl, B=B), none = NULL) res <- if (ci=="none") p else list(estimates = p, L=p.ci[,,1], U=p.ci[,,2]) } else { piecewise.covariates <- msm.fill.pci.covs(x, covariates) res <- pmatrix.piecewise.msm(x, t1, t1 + t, x$pci, piecewise.covariates, ci, cl, B, ...) } class(res) <- "msm.est" res } ### Extract the transition probability matrix at given covariate values - where the Q matrix is piecewise-constant pmatrix.piecewise.msm <- function(x, # fitted msm model t1, # start time t2, # stop time times, # vector of cut points covariates, # list of lists of covariates, for (, times1], (times1, times2], ... # of length one greater than times ci=c("none","normal","bootstrap"), cl = 0.95, # width of symmetric confidence interval B = 1000, # number of bootstrap replicates or normal simulations ... # arguments to pass to MatrixExp ) { x$pci <- NULL # to avoid infinite recursion when calling pmatrix.msm ## Input checks if (t2 < t1) stop("Stop time t2 should be greater than or equal to start time t1") if (!is.numeric(times) || is.unsorted(times)) stop("times should be a vector of numbers in increasing order") if (length(covariates) != length(times) + 1) stop("Number of covariate lists must be one greater than the number of cut points") ## Locate which intervals t1 and t2 fall in, as indices ind1, ind2 into "times". if (t1 <= times[1]) ind1 <- 1 else if (length(times)==1) ind1 <- 2 else { for (i in 2:length(times)) if ((t1 > times[i-1]) && (t1 <= times[i])) {ind1 <- i; break} if (t1 > times[i]) ind1 <- i+1 } if (t2 <= times[1]) ind2 <- 1 else if (length(times)==1) ind2 <- 2 else { for (i in 2:length(times)) if ((t2 > times[i-1]) && (t2 <= times[i])) {ind2 <- i; break} if (t2 > times[i]) ind2 <- i+1 } ## Calculate accumulated pmatrix ## Three cases: ind1, ind2 in the same interval if (ind1 == ind2) { P <- pmatrix.msm(x, t = t2 - t1, covariates=covariates[[ind1]], ...) } ## ind1, ind2 in successive intervals else if (ind2 == ind1 + 1) { P.start <- pmatrix.msm(x, t = times[ind1] - t1 , covariates=covariates[[ind1]], ...) P.end <- pmatrix.msm(x, t = t2 - times[ind2-1], covariates=covariates[[ind2]], ...) P <- P.start %*% P.end } ## ind1, ind2 separated by one or more whole intervals else { P.start <- pmatrix.msm(x, t = times[ind1] - t1, covariates=covariates[[ind1]], ...) P.end <- pmatrix.msm(x, t = t2 - times[ind2-1], covariates=covariates[[ind2]], ...) P.middle <- diag(x$qmodel$nstates) for (i in (ind1+1):(ind2-1)) { P.middle <- P.middle %*% pmatrix.msm(x, t = times[i] - times[i-1], covariates=covariates[[i]], ...) } P <- P.start %*% P.middle %*% P.end } ci <- match.arg(ci) P.ci <- switch(ci, bootstrap = pmatrix.piecewise.ci.msm(x=x, t1=t1, t2=t2, times=times, covariates=covariates, cl=cl, B=B), normal = pmatrix.piecewise.normci.msm(x=x, t1=t1, t2=t2, times=times, covariates=covariates, cl=cl, B=B), none = NULL) res <- if (ci=="none") P else list(estimates = P, L=P.ci[,,1], U=P.ci[,,2]) res } ### Make a list of covariate lists to supply to pmatrix.piecewise.msm for models with "pci" time-dependent intensities. ### One for each time period, with time constant covariates replicated. ### For use in model assessment functions ### Returns factor covariates as contrasts, not factor levels. msm.fill.pci.covs <- function(x, covariates="mean"){ nc <- x$qcmodel$ncovs ## indices of covariates representing time periods ti <- grep("timeperiod\\[.+\\)", x$qcmodel$covlabels) ni <- setdiff(1:nc, ti) # indices of other covariates covlist <- vector(nc, mode="list") names(covlist) <- x$qcmodel$covlabels if (!is.list(covariates)){ if (covariates == 0){ for (i in ni) covlist[[i]] <- 0 } else if (covariates == "mean"){ for (i in ni) covlist[[i]] <- x$qcmodel$covmeans[i] } } else { ## supplied values of non-time covariates covariates <- factorcov2numeric.msm(covariates, x, intmisc="intens") # convert any factors to numeric contrasts for (i in names(covariates)) if (length(grep("^timeperiod",i))==0) { if (i %in% union(x$qcmodel$covlabels.orig,x$qcmodel$covlabels)) covlist[[i]] <- covariates[[i]] else warning("Covariate ",i," unknown") } } for (i in ti) covlist[[i]] <- 0 ## set contrasts for each successive time period to 1 ncut <- length(x$pci) covlistlist <- vector(ncut+1, mode="list") names(covlistlist) <- x$data$covdata$covfactorlevels$timeperiod covlistlist[[1]] <- covlist for (i in seq(length=ncut)){ covlistlist[[i+1]] <- covlist covlistlist[[i+1]][[ti[i]]] <- 1 } covlistlist } ### Extract the mean sojourn times for given covariate values sojourn.msm <- function(x, covariates = "mean", ci=c("delta","normal","bootstrap","none"), cl=0.95, B=1000) { qmatrix <- qmatrix.msm(x, covariates, sojourn=TRUE, ci=ci, cl=cl, B=B) sojstates <- (1 : x$qmodel$nstates) [transient.msm(x)] soj <- qmatrix$sojourn[sojstates] names (soj) <- rownames(x$qmodel$qmatrix)[sojstates] if (x$foundse && (ci != "none")){ sojse <- qmatrix$sojournSE[sojstates] sojl <- qmatrix$sojournL[sojstates] soju <- qmatrix$sojournU[sojstates] names(sojse) <- names(sojl) <- names(soju) <- names(soj) res <- data.frame(estimates=soj, SE=sojse, L=sojl, U=soju) } else res <- list(estimates=soj) res } ### Extract the probabilities of occupying each state next pnext.msm <- function(x, covariates="mean", ci=c("delta","normal","bootstrap","none"), cl=0.95, B=1000) { ci <- match.arg(ci) Q <- qmatrix.msm(x, covariates, ci="none") pnext <- - Q / diag(Q) pnext[x$qmodel$imatrix==0] <- 0 p.ci <- array(0, dim=c(dim(pnext), 2)) if (x$foundse && (ci != "none")){ if (ci == "delta") { for (i in 1:x$qmodel$nstates) { for (j in 1:x$qmodel$nstates) { if (pnext[i,j] > 0) { se <- qratio.se.msm(x, c(i,j), c(i,i), covariates, cl)$se lse <- qratio.se.msm(x, c(i,j), c(i,i), covariates, cl)$lse p.ci[i,j,1] <- exp ( log(pnext[i,j]) - qnorm(1 - 0.5*(1 - cl)) * lse ) p.ci[i,j,2] <- exp ( log(pnext[i,j]) + qnorm(1 - 0.5*(1 - cl)) * lse ) } } } } else if (ci=="normal") p.ci <- pnext.normci.msm(x, covariates, cl, B) else if (ci=="bootstrap") p.ci <- pnext.ci.msm(x, covariates, cl, B) res <- list(estimates=pnext, L=p.ci[,,1], U=p.ci[,,2]) } else res <- list(estimates=pnext) class(res) <- "msm.est" res } ### Extract the coefficients coef.msm <- function(object, ...) { if (!inherits(object, "msm")) stop("expected object to be a msm model") if (object$emodel$misc) object[c("Qmatrices", "Ematrices")] else object$Qmatrices } ### Extract the log-likelihood logLik.msm <- function(object, ...) { if (!inherits(object, "msm")) stop("expected object to be a msm model") val <- - 0.5 * object$minus2loglik attr(val, "df") <- object$paramdata$nopt class(val) <- "logLik" val } ### Likelihood ratio test between two or more models lrtest.msm <- function(...){ mods <- list(...) if (length(mods) < 2) stop("Expected 2 or more models as arguments") lx <- logLik(mods[[1]]) res <- matrix(nrow=length(mods)-1, ncol=3) colnames(res) <- c("-2 log LR","df","p") rownames(res) <- sapply(as.list(match.call())[-(1:2)], deparse) for (i in 2:length(mods)) { if (!inherits(mods[[i]], "msm")) stop("Expected argument",i,"to be a msm object") ly <- logLik(mods[[i]]) lr <- as.numeric(-2 * (lx - ly)) df <- attr(ly,"df") - attr(lx,"df") res[i-1,] <- c(lr, df, 1 - pchisq(lr, df)) } res } ## Estimate total length of stay in a given state. totlos.msm <- function(x, start=1, end=NULL, fromt=0, tot=Inf, covariates="mean", ci=c("none","normal","bootstrap"), # calculate a confidence interval cl = 0.95, # width of symmetric confidence interval B = 1000, # number of bootstrap replicates ...) { if (!inherits(x, "msm")) stop("expected x to be a msm model") if (! start %in% 1 : x$qmodel$nstates) stop("start should be a state in 1, ..., ", x$qmodel$nstates) if (is.null(end)) end <- 1 : x$qmodel$nstates if (! all(end %in% 1 : x$qmodel$nstates)) stop("end should be a set of states in 1, ..., ", x$qmodel$nstates) if (!is.numeric(fromt) || !is.numeric(tot) || length(fromt) != 1 || length(tot) != 1 || fromt < 0 || tot < 0) stop("fromt and tot must be single non-negative numbers") if (fromt > tot) stop("tot must be greater than fromt") if (length(absorbing.msm(x)) == 0) if (tot==Inf) stop("Must specify a finite end time for a model with no absorbing state") tr <- seq(length=x$qmodel$nstates) # transient.msm(x) totlos <- numeric(length(end)) if (tot==Inf) { totlos[end %in% absorbing.msm(x)] <- Inf # set by hand or else integrate() will fail rem <- seq(along=end)[!(end %in% absorbing.msm(x))] } else rem <- seq(along=end) for (j in rem){ f <- function(time) { y <- numeric(length(time)) for (i in seq(along=y)) y[i] <- pmatrix.msm(x, time[i], covariates=covariates, ci="none")[start,end[j]] y } totlos[j] <- integrate(f, fromt, tot, ...)$value } names(totlos) <- rownames(x$qmodel$qmatrix)[end] ci <- match.arg(ci) t.ci <- switch(ci, bootstrap = totlos.ci.msm(x=x, start=start, end=end, fromt=fromt, tot=tot, covariates=covariates, cl=cl, B=B), normal = totlos.normci.msm(x=x, start=start, end=end, fromt=fromt, tot=tot, covariates=covariates, cl=cl, B=B), none = NULL) if (ci=="none") totlos else rbind(totlos, t.ci) } ## Return indices of transient states (can either call for a fitted model or a qmatrix) transient.msm <- function(x=NULL, qmatrix=NULL) { if (!is.null(x)) { if (!inherits(x, "msm")) stop("expected x to be a msm model") qmatrix <- x$Qmatrices[[1]] nst <- x$qmodel$nstates } else if (!is.null(qmatrix)) { nst <- nrow(qmatrix) } else stop("Neither a fitted msm model nor a qmatrix have been supplied") which(diag(msm.fixdiag.qmatrix(qmatrix)) != 0) } ## Return indices of absorbing states (can either call for a fitted model or a qmatrix) absorbing.msm <- function(x=NULL, qmatrix=NULL) { if (!is.null(x)) { if (!inherits(x, "msm")) stop("expected x to be a msm model") qmatrix <- x$Qmatrices[[1]] nst <- x$qmodel$nstates } else if (!is.null(qmatrix)) { nst <- nrow(qmatrix) } else stop("Neither a fitted msm model nor a qmatrix have been supplied") which(diag(msm.fixdiag.qmatrix(qmatrix)) == 0) } ## Return two-column matrix containing pairs of states with allowed ## transitions in an interval. Handles transitions between observed ## states in misclassification models intervaltrans.msm <- function(x=NULL, qmatrix=NULL, ematrix=NULL, exclude.absabs=FALSE, censor=FALSE) { if (!is.null(x)) { if (!inherits(x, "msm")) stop("expected x to be a msm model") qmatrix <- qmatrix.msm(x, ci="none") if (is.null(ematrix) & x$emodel$misc) ematrix <- ematrix.msm(x, ci="none") > 0 abs <- absorbing.msm(x) } else if (!is.null(qmatrix)) { abs <- absorbing.msm(qmatrix=qmatrix) } else if (is.null(qmatrix)) stop("Neither a fitted msm model nor a qmatrix have been supplied") P <- MatrixExp(qmatrix) if (!is.null(ematrix)) P <- t(ematrix) %*% P %*% ematrix # > 0 iff P(obs state=s | prev obs state = r) > 0 ## P(obs state = s | obs prev = r) = Sum_ij P(obsst = s | truest = j) P(truest = j | trueprev = i) P(trueprev = i | obsprev = r) ## Sum_ij Ejs Pij Eir = Eir Pij Ejs gt0 <- abs(P) > .Machine$double.eps ^ 0.5 at <- cbind(row(P)[gt0], col(P)[gt0]) if (exclude.absabs) at <- at[!(at[,1] %in% abs & at[,2] %in% abs),] if (censor && x$cmodel$ncens > 0) { # consider censoring as separate state atcens.all <- numeric() for (i in 1:x$cmodel$ncens) { truestates <- x$cmodel$states[x$cmodel$index[i] : (x$cmodel$index[i+1] - 1)] atcens <- at[at[,2] %in% truestates,] atcens[,2] <- 99 atcens <- unique(atcens) atcens.all <- rbind(atcens.all, atcens) } at <- rbind(at, atcens.all) } at[order(at[,1],at[,2]),] } ### Estimate observed state occupancies in the data at a series of times ### Assume previous observed state is retained until next observation time ### Assumes times are sorted within patient (they are in data in msm objects) observed.msm <- function(x, times=NULL, interp=c("start","midpoint")) { if (!inherits(x, "msm")) stop("expected x to be a msm model") ## For general HMMs use the Viterbi estimate of the observed state. state <- if ((x$hmodel$hidden && !x$emodel$misc) || (!x$hmodel$hidden && x$cmodel$ncens>0) ) viterbi.msm(x)$fitted else x$data$state subject <- x$data$subject ## fixme subj char/factor? time <- x$data$time if (is.null(times)) times <- seq(min(time), max(time), (max(time) - min(time))/10) states.expand <- matrix(nrow=length(unique(subject)), ncol=length(times)) pts <- unique(subject) absorb <- absorbing.msm(x) interp <- match.arg(interp) for (i in seq(along=pts)){ state.i <- state[subject==pts[i]] time.i <- time[subject==pts[i]] j <- 1 while(j <= length(times)) { if (times[j] < time.i[1]) { mtime <- max(which(times-time.i[1] < 0)) states.expand[i, j:mtime] <- NA j <- mtime + 1 next; } else if (times[j] > time.i[length(time.i)]) { if (state.i[length(time.i)] %in% absorb) { states.expand[i, j:(length(times))] <- state.i[length(time.i)] } else states.expand[i, j:(length(times))] <- NA break; } else { prevtime <- max(which(time.i <= times[j])) if (interp=="midpoint") { nexttime <- min(which(time.i >= times[j])) midpoint <- (prevtime + nexttime) / 2 states.expand[i,j] <- state.i[if (times[j] <= midpoint) prevtime else nexttime] } else states.expand[i,j] <- state.i[prevtime] } j <- j+1 } } obstab <- t(apply(states.expand, 2, function(y) table(factor(y, levels=seq(length=x$qmodel$nstates))))) obsperc <- 100*obstab / rep(rowSums(obstab), ncol(obstab)) dimnames(obstab) <- dimnames(obsperc) <- list(times, paste("State", 1:x$qmodel$nstates)) obstab <- cbind(obstab, Total=rowSums(obstab)) list(obstab=obstab, obsperc=obsperc, risk=obstab[,ncol(obstab)]) } expected.msm <- function(x, times=NULL, timezero=NULL, initstates=NULL, covariates="mean", misccovariates="mean", piecewise.times=NULL, piecewise.covariates=NULL, risk=NULL, ci=c("none","normal","bootstrap"), cl = 0.95, B = 1000 ) { if (!inherits(x, "msm")) stop("expected x to be a msm model") time <- x$data$time if (is.null(times)) times <- seq(min(time), max(time), (max(time) - min(time))/10) if (is.null(timezero)) timezero <- min(time) if (is.null(risk)) risk <- observed.msm(x, times=times)$risk exptab <- matrix(nrow=length(times), ncol=x$qmodel$nstates) if (x$emodel$misc){ # exptab <- x$emodel$initprobs * risk[1] start <- min(which(times - timezero > 0)) if (length(times) >= start) { for (j in start:length(times)) { pmat <- if (is.null(piecewise.times)) pmatrix.msm(x, t=times[j] - timezero, t1=timezero, covariates=covariates) else pmatrix.piecewise.msm(x, timezero, times[j], piecewise.times, piecewise.covariates) emat <- ematrix.msm(x, covariates=misccovariates)$estimates exptruej <- risk[j] * x$emodel$initprobs %*% pmat expobsj <- exptruej %*% emat exptab[j,] <- expobsj } } } else { if (is.null(initstates)) initstates <- observed.msm(x, times=timezero)$obstab[1:x$qmodel$nstates] initprobs <- initstates / sum(initstates) start <- min(which(times - timezero >= 0)) if (length(times) >= start) { for (j in start:length(times)) { pmat <- if (is.null(piecewise.times)) pmatrix.msm(x, t=times[j] - timezero, t1=timezero, covariates=covariates) else pmatrix.piecewise.msm(x, timezero, times[j], piecewise.times, piecewise.covariates) expj <- risk[j] * initprobs %*% pmat exptab[j,] <- expj } } } exptab <- cbind(exptab, apply(exptab, 1, sum)) dimnames(exptab) <- list(times, c(rownames(x$qmodel$qmatrix),"Total")) expperc <- 100*exptab[,1:x$qmodel$nstates] / exptab[, x$qmodel$nstates+1] ci <- match.arg(ci) e.ci <- switch(ci, bootstrap = expected.ci.msm(x, times, timezero, initstates, covariates, misccovariates, piecewise.times, piecewise.covariates, risk, cl, B), normal = expected.normci.msm(x, times, timezero, initstates, covariates, misccovariates, piecewise.times, piecewise.covariates, risk, cl, B), none = NULL) res <- if (ci=="none") list(exptab=exptab, expperc=expperc) else list(exptab=list(estimates=exptab, ci=e.ci[[1]]), expperc=list(estimates=expperc, ci=e.ci[[2]])) names(res) <- c("Expected","Expected percentages") res } ### Table of observed and expected prevalences (works for misclassification and non-misclassification models) prevalence.msm <- function(x, times=NULL, timezero=NULL, initstates=NULL, covariates="mean", misccovariates="mean", piecewise.times=NULL, piecewise.covariates=NULL, ci=c("none","normal","bootstrap"), cl = 0.95, B = 1000, interp=c("start","midpoint"), plot = FALSE, ... ) { ## Estimate observed state occupancies in the data at a series of times time <- x$data$time if (is.null(times)) times <- seq(min(time), max(time), (max(time) - min(time))/10) obs <- observed.msm(x, times, interp) risk <- obs$obstab[,ncol(obs$obstab)] ## Work out expected state occupancies by forecasting from transition probabilities expec <- expected.msm(x, times, timezero, initstates, covariates, misccovariates, piecewise.times, piecewise.covariates, risk, ci, cl, B) res <- list(observed=obs$obstab, expected=expec[[1]], obsperc=obs$obsperc, expperc=expec[[2]]) names(res) <- c("Observed", "Expected", "Observed percentages", "Expected percentages") if (plot) plot.prevalence.msm(x, mintime=min(times), maxtime=max(times), timezero=timezero, initstates=initstates, interp=interp, covariates=covariates, misccovariates=misccovariates, piecewise.times=piecewise.times, piecewise.covariates=piecewise.covariates, ...) res } plot.prevalence.msm <- function(x, mintime=NULL, maxtime=NULL, timezero=NULL, initstates=NULL, interp=c("start","midpoint"), covariates="mean", misccovariates="mean", piecewise.times=NULL, piecewise.covariates=NULL, xlab="Times",ylab="Prevalence (%)", lwd.obs=1, lwd.exp=1, lty.obs=1, lty.exp=2, col.obs="blue", col.exp="red", legend.pos=NULL,...){ time <- x$data$time if (is.null(mintime)) mintime <- min(time) if (is.null(maxtime)) maxtime <- max(time) t <- seq(mintime, maxtime, length=100) obs <- observed.msm(x, t, interp) expec <- expected.msm(x, t, timezero=timezero, initstates=initstates, covariates=covariates, misccovariates=misccovariates, piecewise.times=piecewise.times, piecewise.covariates=piecewise.covariates, risk=obs$risk)[[2]] states <- seq(length=x$qmodel$nstates) S <- length(states) ncols <- ceiling(sqrt(S)) nrows <- if (floor(sqrt(S))^2 < S && S <= floor(sqrt(S))*ceiling(sqrt(S))) floor(sqrt(S)) else ceiling(sqrt(S)) par(mfrow=c(nrows, ncols)) for (i in states) { plot(t, obs$obsperc[,i], type="l", ylim=c(0, 100), xlab=xlab, ylab=ylab, lwd=lwd.obs, lty=lty.obs, col=col.obs, main=rownames(x$qmodel$qmatrix)[i],...) lines(t, expec[,i], lwd=lwd.exp, lty=lty.exp, col=col.exp) } if (!is.numeric(legend.pos) || length(legend.pos) != 2) legend.pos <- c(0.4*maxtime, 40) legend(x=legend.pos[1], y=legend.pos[2], legend=c("Observed","Expected"), lty=c(lty.obs,lty.exp), lwd=c(lwd.obs,lwd.exp), col=c(col.obs,col.exp)) invisible() } ### Empirical versus fitted survival curve plot.survfit.msm <- function(x, from=1, to=NULL, range=NULL, covariates="mean", interp=c("start","midpoint"), ci=c("none","normal","bootstrap"), B=100, legend.pos=NULL, xlab="Time", ylab="Survival probability", lty=1, lwd=1, col="red", lty.ci=2, lwd.ci=1, col.ci="red", mark.time=TRUE, col.surv="blue", lty.surv=2, lwd.surv=1, ...) { if (!inherits(x, "msm")) stop("expected x to be a msm model") if (is.null(to)) to <- max(absorbing.msm(x)) else { if (!is.numeric(to)) stop("to must be numeric") if (! (to %in% absorbing.msm(x) ) ) stop("to must be an absorbing state") } if (is.null(range)) rg <- range(x$data$time) else { if (!is.numeric(range) || length(range)!= 2) stop("range must be a numeric vector of two elements") rg <- range } interp <- match.arg(interp) ci <- match.arg(ci) timediff <- (rg[2] - rg[1]) / 50 times <- seq(rg[1], rg[2], timediff) pr <- lower <- upper <- numeric() for (t in times) { P <- pmatrix.msm(x, t, t1=times[1], covariates=covariates, ci=ci, B=B) if (ci != "none") { pr <- c(pr, P$estimates[from, to]) lower <- c(lower, P$L[from, to]) upper <- c(upper, P$U[from, to]) } else pr <- c(pr, P[from, to]) } plot(times, 1 - pr, type="l", xlab=xlab, ylab=ylab, lwd=lwd, ylim=c(0,1), lty = lty, col=col,...) if (ci != "none") { lines(times, 1 - lower, lty=lty.ci, col=col.ci, lwd=lwd.ci) lines(times, 1 - upper, lty=lty.ci, col=col.ci, lwd=lwd.ci) } dat <- as.data.frame(x$data[c("subject", "time", "state")]) st <- as.data.frame( do.call("rbind", by(dat, dat$subject, function(x) { dind <- which(x[,"state"] == to) if(any(x[,"state"]==to)) mintime <- if(interp=="start") min(x[dind, "time"]) else 0.5 * (x[dind, "time"] + x[dind-1, "time"]) else mintime <- max(x[,"time"]) c(anystate = as.numeric(any(x[,"state"]==to)), mintime = mintime) } ))) # slow lines(survfit(Surv(st$mintime,st$anystate) ~ 1), mark.time=mark.time, col=col.surv, lty=lty.surv, lwd=lwd.surv,...) timediff <- (rg[2] - rg[1]) / 50 if (!is.numeric(legend.pos) || length(legend.pos) != 2) legend.pos <- c(max(x$data$time) - 25*timediff, 1) if (ci=="none") legend(legend.pos[1], legend.pos[2], lty=c(lty, lty.surv), lwd=c(lwd, lwd.surv), col=c(col, col.surv), legend=c("Fitted","Empirical")) else legend(legend.pos[1], legend.pos[2], lty=c(lty, lty.ci, lty.surv), lwd=c(lwd,lwd.ci, lwd.surv), col=c(col ,col.ci, col.surv), legend=c("Fitted","Fitted (confidence interval)", "Empirical")) invisible() } ### Obtain hazard ratios from estimated effects of covariates on log-transition rates hazard.msm <- function(x, hazard.scale = 1, cl = 0.95) { if (!inherits(x, "msm")) stop("expected x to be a msm model") if (length(hazard.scale) == 1) hazard.scale <- rep(hazard.scale, x$qcmodel$ncovs) if (length(hazard.scale) != x$qcmodel$ncovs) stop ("hazard.scale of length ", length(hazard.scale), ", expected ", x$qcmodel$ncovs) keep <- (x$qmodel$imatrix != 0) nst <- x$qmodel$nstates keepvec <- as.vector(t(keep)) fromlabs <- rep(rownames(keep), each=nst) [keepvec] tolabs <- rep(colnames(keep), nst) [keepvec] if (x$qcmodel$ncovs > 0) { haz.list <- list() if (x$foundse) { for (i in 1:x$qcmodel$ncovs) { cov <- x$qcmodel$covlabels[i] haz.rat <- t(exp(hazard.scale[i]*x$Qmatrices[[cov]]))[keepvec] LCL <- t(exp(hazard.scale[i]*(x$Qmatrices[[cov]] - qnorm(1 - 0.5*(1 - cl))*x$QmatricesSE[[cov]]) ))[keepvec] UCL <- t(exp(hazard.scale[i]*(x$Qmatrices[[cov]] + qnorm(1 - 0.5*(1 - cl))*x$QmatricesSE[[cov]]) ))[keepvec] haz.tab <- cbind(haz.rat, LCL, UCL) dimnames(haz.tab) <- list(paste(fromlabs, "-", tolabs), c("HR", "L", "U")) haz.list[[cov]] <- haz.tab } } else { for (i in 1:x$qcmodel$ncovs) { cov <- x$qcmodel$covlabels[i] haz.tab <- as.matrix(t(exp(hazard.scale[i]*x$Qmatrices[[cov]]))[keepvec]) dimnames(haz.tab) <- list(paste(fromlabs, "-", tolabs), "HR") haz.list[[cov]] <- haz.tab } } } else haz.list <- "No covariates on transition intensities" haz.list } ### Obtain odds ratios from estimated effects of covariates on logit-misclassification probabilities ### TODO - equivalent for general HMMs which presents cov effects on natural scale. odds.msm <- function(x, odds.scale = 1, cl = 0.95) { if (!inherits(x, "msm")) stop("expected x to be a msm model") if (!x$emodel$misc) stop("Requires a misclassification model specified with ematrix") if (length(odds.scale) == 1) odds.scale <- rep(odds.scale, x$ecmodel$ncovs) if (length(odds.scale) != x$ecmodel$ncovs) stop ("odds.scale of length ", length(odds.scale), ", expected ", x$ecmodel$ncovs) keep <- (x$emodel$imatrix != 0) nst <- x$qmodel$nstates keepvec <- as.vector(t(keep)) truelabs <- rep(rownames(keep), each=nst) [keepvec] obslabs <- rep(colnames(keep), nst) [keepvec] if (x$ecmodel$ncovs > 0) { odds.list <- list() if (x$foundse) { for (i in 1:x$ecmodel$ncovs) { cov <- x$ecmodel$covlabels[i] odds.rat <- t(exp(odds.scale[i]*x$Ematrices[[cov]]))[keepvec] LCL <- t(exp(odds.scale[i]*(x$Ematrices[[cov]] - qnorm(1 - 0.5*(1 - cl))*x$EmatricesSE[[cov]]) ))[keepvec] UCL <- t(exp(odds.scale[i]*(x$Ematrices[[cov]] + qnorm(1 - 0.5*(1 - cl))*x$EmatricesSE[[cov]]) ))[keepvec] odds.tab <- cbind(odds.rat, LCL, UCL) dimnames(odds.tab) <- list(paste("Obs", obslabs, "|", truelabs), c("OR", "L", "U")) odds.list[[cov]] <- odds.tab } } else { for (i in 1:x$ecmodel$ncovs) { cov <- x$ecmodel$covlabels[i] odds.tab <- as.matrix(t(exp(odds.scale[i]*x$Ematrices[[cov]]))[keepvec]) dimnames(odds.tab) <- list(paste("Obs", obslabs, "|", truelabs), "OR") odds.list[[cov]] <- odds.tab } } } else odds.list <- "No covariates on misclassification probabilities" odds.list } ### Viterbi algorithm for reconstructing the most likely path through underlying states ### This is all done in C viterbi.msm <- function(x) { if (!inherits(x, "msm")) stop("expected x to be a msm model") if (x$cmodel$ncens > 0 && !x$hmodel$hidden) { ## If censoring but not HMM, then define an identity HMM with ## true state known at every time except censoring times hmod <- vector(x$qmodel$nstates, mode="list") for (i in 1:x$qmodel$nstates) hmod[[i]] <- hmmIdent(i) x$hmodel <- msm.form.hmodel(hmod, est.initprobs=FALSE, qmodel=x$qmodel) x$hmodel <- c(x$hmodel, list(ncovs=rep(rep(0,x$hmodel$nstates),x$hmodel$npars), ncoveffs=0, nicovs=rep(0,x$hmodel$nstates-1), nicoveffs=0)) x$data$obstrue <- ifelse(x$data$state %in% x$cmodel$censor, 0, 1) } if (x$hmodel$hidden) { do.what <- 2 x$data$fromstate <- x$data$fromstate - 1 x$data$tostate <- x$data$tostate - 1 x$data$firstobs <- x$data$firstobs - 1 x$hmodel$models <- x$hmodel$models - 1 x$hmodel$links <- x$hmodel$links - 1 if (any(x$hmodel$plabs == "p")) { ## Express other probabilities relative to this baseline prob pst <- match(x$hmodel$parstate[x$hmodel$plabs=="p"], unique(x$hmodel$parstate[x$hmodel$plabs=="p"])) x$hmodel$pars[x$hmodel$plabs == "p"] <- x$hmodel$pars[x$hmodel$plabs == "p"] / x$hmodel$pars[x$hmodel$plabs == "pbase"][pst] } x$hmodel$initprobs <- x$hmodel$initprobs / x$hmodel$initprobs[1] vit <- .C("msmCEntry", as.integer(do.what), as.integer(as.vector(t(x$qmodel$imatrix))), as.double(as.vector(t(x$Qmatrices$baseline)[t(x$qmodel$imatrix)==1])), as.double(unlist(lapply(x$Qmatrices[x$qcmodel$covlabels], function(y) t(y)[t(x$qmodel$imatrix)==1]))), as.double(x$hmodel$pars), as.double(x$hmodel$coveffect), # estimates ## data for non-HMM as.integer(x$data$fromstate), as.integer(x$data$tostate), as.double(x$data$timelag), as.double(unlist(x$data$covmat)), as.double(unlist(x$data$cov)), as.integer(x$data$covdata$whichcov), # this is really part of the model as.integer(x$data$nocc), as.integer(x$data$whicha), as.integer(x$data$obstype), ## data for HMM / censored as.integer(match(x$data$subject, unique(x$data$subject))), as.double(x$data$time), as.double(x$data$state), as.integer(x$data$firstobs), as.integer(x$data$obstrue), ## HMM specification as.integer(x$hmodel$hidden), as.integer(x$hmodel$models), as.integer(x$hmodel$npars), as.integer(x$hmodel$totpars), as.integer(x$hmodel$firstpar), as.integer(x$hmodel$ncovs), as.integer(x$hmodel$whichcovh), as.integer(x$hmodel$links), as.double(x$hmodel$initprobs), as.integer(x$hmodel$nicovs), as.double(x$hmodel$icoveffect), as.integer(x$hmodel$whichcovi), ## various dimensions as.integer(x$qmodel$nstates), as.integer(x$qmodel$analyticp), as.integer(x$qmodel$iso), as.integer(x$qmodel$perm), as.integer(x$qmodel$qperm), as.integer(x$qmodel$npars), as.integer(x$qmodel$ndpars), as.integer(x$qcmodel$ndpars), as.integer(x$data$nobs), as.integer(x$data$n), as.integer(x$data$npts), # HMM only as.integer(rep(x$qcmodel$ncovs, x$qmodel$npars)), as.integer(x$cmodel$ncens), as.integer(x$cmodel$censor), as.integer(x$cmodel$states), as.integer(x$cmodel$index - 1), as.integer(x$qmodel$constraint), as.integer(x$qcmodel$constraint), as.integer(x$qcmodel$whichdcov), fitted = double (x$data$nobs), PACKAGE = "msm", NAOK = TRUE ) fitted <- vit$fitted + 1 } else fitted <- x$data$state data.frame(subject = x$data$subject, time = x$data$time, observed = x$data$state, fitted = fitted) } scoreresid.msm <- function(x, plot=FALSE){ if (x$hmodel$hidden | (x$cmodel$ncens > 0)) stop("Score residuals not implemented for hidden Markov models or models with censored states") derivs <- likderiv.msm(x$paramdata$opt$par, deriv=3, x$data, x$qmodel, x$qcmodel, x$cmodel, x$hmodel, x$paramdata) cov <- solve(0.5*x$opt$hessian) sres <- colSums(t(derivs) * cov %*% t(derivs)) names(sres) <- unique(x$data$subject) if (plot) { plot(sres, type="n") text(seq(along=sres), sres, names(sres)) } sres } msm/R/simul.R0000644000176000001440000003623411446423716012573 0ustar ripleyusers### FUNCTIONS FOR SIMULATING FROM MULTI-STATE MODELS ### from help(sample) in base R resample <- function(x, size, ...) if(length(x) <= 1) { if(!missing(size) && size == 0) x[FALSE] else x } else sample(x, size, ...) ### General function to simulate one individual's realisation from a continuous-time Markov model ### Produces the exact times of transition sim.msm <- function(qmatrix, # intensity matrix maxtime, # maximum time for realisations covs=NULL, # covariate matrix, nobs rows, ncovs cols beta=NULL, # matrix of cov effects on qmatrix. ncovs rows, nintens cols. obstimes=0, # times at which time-dependent covariates change start = 1, # starting state mintime = 0 # time to start from ) { ## Keep only times where time-dependent covariates change if (!is.null(covs)) { covs2 <- collapse.covs(covs) covs <- covs2$covs obstimes <- obstimes[covs2$ind] } else {obstimes <- mintime; covs <- beta <- 0} if (is.vector(beta)) beta <- matrix(beta, ncol=length(beta)) nct <- length(obstimes) nstates <- nrow(qmatrix) ## Form an array of qmatrices, one for each covariate change-time qmatrices <- array(rep(t(qmatrix), nct), dim=c(dim(qmatrix), nct)) qmatrices[rep(t(qmatrix)>0, nct)] <- qmatrices[rep(t(qmatrix)>0, nct)]*exp(t(beta)%*%t(covs)) # nintens*nobs for (i in 1:nct) qmatrices[,,i] <- msm.fixdiag.qmatrix(t(qmatrices[,,i])) cur.t <- mintime; cur.st <- next.st <- start; rem.times <- obstimes; t.ind <- 1 nsim <- 0; max.nsim <- 10 simstates <- simtimes <- numeric(max.nsim) ## allocate memory up-front for simulated outcome absorb <- absorbing.msm(qmatrix=qmatrix) ## Simulate up to maxtime or absorption while (cur.t < maxtime) { nsim <- nsim + 1 cur.st <- next.st simstates[nsim] <- cur.st; simtimes[nsim] <- cur.t if (cur.st %in% absorb) break; rate <- -qmatrices[cur.st,cur.st, t.ind:length(obstimes)] nextlag <- rpexp(1, rate, rem.times-rem.times[1]) cur.t <- cur.t + nextlag t.ind <- which.min((cur.t - obstimes)[cur.t - obstimes > 0]) rem.times <- cur.t if (any(obstimes > cur.t)) rem.times <- c(rem.times, obstimes[(t.ind+1): length(obstimes)]) cur.q <- qmatrices[,, t.ind] next.st <- resample((1:nstates)[-cur.st], size=1, prob = cur.q[cur.st, -cur.st]) if (nsim > max.nsim) { ## need more memory for simulated outcome, allocate twice as much simstates <- c(simstates, numeric(max.nsim)) simtimes <- c(simtimes, numeric(max.nsim)) max.nsim <- max.nsim*2 } } ## If process hasn't absorbed by the end, then include a censoring time if (cur.t >= maxtime) { nsim <- nsim+1 simstates[nsim] <- cur.st simtimes[nsim] <- maxtime } list(states = simstates[1:nsim], times = simtimes[1:nsim], qmatrix = qmatrix) } ## Drop rows of a covariate matrix which are identical to previous row ## Similar method to R's unique.data.frame collapse.covs <- function(covs) { if (nrow(covs)==1) list(covs=covs, ind=1) else { pcovs <- apply(covs, 1, function(x) paste(x, collapse="\r")) lpcovs <- c("\r", pcovs[1:(length(pcovs)-1)]) ind <- pcovs!=lpcovs list(covs=covs[ind,,drop=FALSE], ind=which(ind)) } } ### Given a simulated Markov model, get the current state at various observation times ### Only keep one observation in the absorbing state getobs.msm <- function(sim, obstimes, death=FALSE, tunit=1.0) { absorb <- absorbing.msm(qmatrix=sim$qmatrix) # Only keep one observation in the absorbing state if (any(sim$states %in% absorb)) { if (any(sim$states %in% death)) keep <- which(obstimes < max(sim$times)) else { lo <- c(-Inf, obstimes[1:(length(obstimes)-1)]) keep <- which(lo <= max(sim$times)) } } else keep <- 1 : length(obstimes) obstimes <- obstimes[keep] state <- sim$states[rowSums(outer(obstimes, sim$times, ">="))] time <- obstimes if (any(sim$states %in% death)) { # Keep the exact death time if required state <- c(state, sim$states[sim$states %in% death]) time <- c(time, sim$times[sim$states %in% death]) state <- state[order(time)] time <- time[order(time)] keep <- c(keep, max(keep)+1) } list(state = state, time = time, keep=keep) } ### Simulate a multi-state Markov or hidden Markov model dataset using fixed observation times ###Would it be better to make specification of covariate model consistent with model fitting function? ### e.g. separate hcovariates and covariates formulae, ### plus covinits and hcovinits? simmulti.msm <- function(data, # data frame with subject, times, covariates... qmatrix, # intensity matrix covariates=NULL, # initial values death = FALSE, # vector of indicators for "death" states, ie absorbing states whose entry time is known exactly, # but with unknown transient state at previous instant start, # starting states of the process, defaults to all 1. ematrix = NULL,# misclassification matrix misccovariates = NULL, # covariates on misclassification probabilities hmodel = NULL, # hidden Markov model formula hcovariates = NULL, # covariate effects on hidden Markov model response distribution censor.states = NULL ) { ### Check consistency of qmatrix and covariate inits nstates <- nrow(qmatrix) msm.check.qmatrix(qmatrix) qmatrix <- msm.fixdiag.qmatrix(qmatrix) ###Subject, time and state if (!("subject" %in% names(data))) data$subject <- rep(1, nrow(data)) if (!("time" %in% names(data))) stop("\"time\" column missing from data") data <- as.data.frame(data) subject <- data[,"subject"] time <- data[,"time"] if (is.unsorted(subject)){ warning("Data are not ordered by subject ID and time - output will be ordered.") data <- data[order(subject, time),] } if (any(duplicated(data[,c("subject", "time")]))){ warning("Data contain duplicated observation times for a subject - removing duplicates.") data <- data[!duplicated(data[,c("subject", "time")]), ] } subject <- data[,"subject"]; time <- data[,"time"]; cens <- if (any(colnames(data)=="cens")) data[,"cens"] else rep(0, length(subject)) msm.check.times(time, subject) times <- split(time, subject) cens <- split(cens, subject) n <- length(unique(subject)) ### Covariates on intensities covnames <- names(covariates) ncovs <- length(covnames) misscovs <- setdiff(covnames, names(data)) if (length(misscovs) > 0) stop("Covariates ", paste(misscovs, collapse=", "), " not found in data") covs <- if (ncovs > 0) lapply(split(data[,covnames], subject), as.matrix) else NULL allcovs <- covnames ### Covariates on misclassification misccovnames <- names(misccovariates) nmisccovs <- length(misccovnames) misscovs <- setdiff(misccovnames, names(data)) if (length(misscovs) > 0) stop("Misclassification covariates ", paste(misscovs, collapse=", "), " not found in data") misccovs <- if (nmisccovs > 0) lapply(split(data[,setdiff(misccovnames,covnames)], subject), as.matrix) else NULL allmisccovs <- misccovnames ### Covariates on HMM if (!is.null(hcovariates)) { if (is.null(hmodel)) stop("hcovariates specified, but no hmodel") hcovnames <- unique(names(unlist(hcovariates))) if (length(hcovariates) != nstates) stop("hcovariates of length ", length(hcovariates), ", expected ", nstates) msm.check.hmodel(hmodel, nstates) misscovs <- setdiff(hcovnames, names(data)) if (length(misscovs) > 0) stop("Covariates ", paste(misscovs, collapse=", "), " not found in data") hcovs <- lapply(split(data[,setdiff(hcovnames, setdiff(misccovnames,covnames))], subject), as.matrix) } else hcovs <- hcovnames <- NULL ### Extra variables to return extravars <- setdiff(names(data), unique(c("subject","time", "cens", covnames, misccovnames, hcovnames))) extradat <- if(length(extravars)>0) split(data[,extravars,drop=FALSE], subject) else NULL ### Starting states if (missing(start)) start <- rep(1, n) else if (length(start) != n) stop("Supplied ", length(start), " starting states, expected ", n) nq <- length(qmatrix[qmatrix > 0]) misspeccovs <- covnames[sapply(covariates, length) != nq] if (length(misspeccovs) > 0) stop("Initial values for covariates ", paste(misspeccovs, collapse=", "), " should be of length ", nq) beta <- do.call("rbind", as.list(covariates)) ne <- length(ematrix[ematrix > 0]) misspeccovs <- covnames[sapply(misccovariates, length) != ne] if (length(misspeccovs) > 0) stop("Initial values for misclassification covariates ", paste(misspeccovs, collapse=", "), " should be of length ", ne) beta.misc <- do.call("rbind", as.list(misccovariates)) ### Check death argument. Logical values allowed for backwards compatibility ### (TRUE means final state is death, FALSE means no death state) statelist <- if (nstates==2) "1, 2" else if (nstates==3) "1, 2, 3" else paste("1, 2, ... ,",nstates) if (is.logical(death) && death==TRUE) {death <- nstates} else if (is.logical(death) && death==FALSE) {death <- 0} else if (length(setdiff(unique(death), 1:nstates)) > 0) stop(paste("Death states indicator contains states not in",statelist)) ### Simulate a realisation for each person state <- numeric() keep.data <- numeric() subj <- split(subject, subject) for (pt in 1:n) { sim.mod <- sim.msm(qmatrix, max(times[[pt]]), covs[[pt]], beta, times[[pt]], start[pt], min(times[[pt]])) obsd <- getobs.msm(sim.mod, times[[pt]], death) pt.data <- cbind(subj[[pt]][obsd$keep], obsd$time, obsd$state, cens[[pt]][obsd$keep]) if (!is.null(covnames)) pt.data <- cbind(pt.data, covs[[pt]][obsd$keep,,drop=FALSE]) if (!is.null(misccovnames)) pt.data <- cbind(pt.data, misccovs[[pt]][obsd$keep,,drop=FALSE]) if (!is.null(hcovnames)) pt.data <- cbind(pt.data, hcovs[[pt]][obsd$keep,,drop=FALSE]) if (!is.null(extravars)) pt.data <- cbind(pt.data, extradat[[pt]][obsd$keep,,drop=FALSE]) keep.data <- rbind(keep.data, pt.data) } colnames(keep.data) <- c("subject","time","state","cens",union(union(covnames,misccovnames),hcovnames),extravars) keep.data <- as.data.frame(keep.data) ### Simulate some misclassification or a HMM conditionally on the underlying state if (!is.null(ematrix)) { if (!all(dim(ematrix) == dim(qmatrix))) stop("Dimensions of qmatrix and ematrix should be equal") keep.data <- cbind(keep.data, obs=simmisc.msm(keep.data$state, ematrix, beta.misc, keep.data[,misccovnames,drop=FALSE])) } else if (!is.null(hmodel)) keep.data <- cbind(keep.data, obs=simhidden.msm(keep.data$state, hmodel, nstates, hcovariates, keep.data[,hcovnames,drop=FALSE])) ### Replace state at censor times by censoring indicators censor <- unique(keep.data$cens[keep.data$cens != 0]) if (is.null(censor.states)) censor.states <- 1:(nstates-1) if (!is.null(keep.data$obs)) keep.data$obs <- ifelse(keep.data$cens > 0 & keep.data$state %in% censor.states, keep.data$cens, keep.data$obs) else keep.data$state <- ifelse(keep.data$cens > 0 & keep.data$state %in% censor.states, keep.data$cens, keep.data$state) keep.data$cens <- NULL attr(keep.data, "keep") <- obsd$keep keep.data } ## Simulate misclassification conditionally on an underlying state simmisc.msm <- function(state, ematrix, beta, misccovs) { ostate <- state if (is.null(ematrix)) warning("No misclassification matrix given, assuming no misclassification") else { if (any(ematrix < 0)) stop("Not all elements of ematrix are > 0") if (any(ematrix > 1)) stop("Not all elements of ematrix are < 1") if (nrow(ematrix) != ncol(ematrix)) stop("Number of rows and columns of ematrix are not equal") nstates <- nrow(ematrix) ematrix <- msm.fixdiag.ematrix(ematrix) ostate <- state beta.states <- t(row(ematrix))[t(ematrix) > 0 & !(row(ematrix)==col(ematrix))] for (i in 1:nstates) if (any(state==i)) { n <- length(state[state==i]) if (!is.null(beta)) { # covariates on misclassification probabilities X <- as.matrix(misccovs[state==i,]) b <- beta[,beta.states == i,drop=FALSE] p <- matrix(rep(ematrix[i,], n), nrow=n, byrow=TRUE) mu <- log(p / p[,i]) emu <- array(0, dim=dim(p)) miscstates <- setdiff(which(ematrix[i,] > 0), i) for (j in seq(along=miscstates)) emu[,miscstates[j]] <- exp(mu[,miscstates[j]] + X %*% b[,j]) emu[,i] <- 1 emu[,ematrix[i,]==0] <- 0 p <- emu / rowSums(emu) for (j in 1:n) ostate[state==i][j] <- resample(1:nstates, size=1, prob=p[j,], replace=TRUE) } else ostate[state==i] <- resample(1:nstates, size=n, prob=ematrix[i,], replace=TRUE) } } ostate } ## Simulate HMM outcome conditionally on an underlying state simhidden.msm <- function(state, hmodel, nstates, beta=NULL, x=NULL) { y <- state msm.check.hmodel(hmodel, nstates) for (i in 1:nstates) if (any(state==i)) { ## don't change the underlying state if the HMM is the null (identity) model if (!(hmodel[[i]]$label=="identity" && (length(hmodel[[i]]$pars) == 0))) { ## simulate from the sampling function "r" in the HMM object ##transform the location parameter by covariates if necessary rcall <- list(n=length(state[state==i])) if (!is.null(beta[[i]])) { link <- get(hmodel[[i]]$link) invlink <- get(.msm.INVLINK[hmodel[[i]]$link]) locpar <- .msm.LOCPARS[hmodel[[i]]$label] loc <- hmodel[[i]]$pars[locpar] loc <- invlink(link(loc) + as.matrix(x[state==i,names(beta[[i]])]) %*% beta[[i]]) rcall[[paste("r",locpar,sep="")]] <- loc } rfn <- hmodel[[i]]$r y[state==i] <- do.call("rfn", rcall) } } y } msm/R/utils.R0000644000176000001440000004115312006004702012555 0ustar ripleyusers### msm PACKAGE ### USEFUL FUNCTIONS NOT SPECIFIC TO MULTI-STATE MODELS ### Delta method for approximating the covariance matrix of f(X) given cov(X) deltamethod <- function(g, # a formula or list of formulae (functions) giving the transformation g(x) in terms of x1, x2, etc mean, # mean, or maximum likelihood estimate, of x cov, # covariance matrix of x ses=TRUE # return standard errors, else return covariance matrix ) { ## Var (G(x)) = G'(mu) Var(X) G'(mu)^T cov <- as.matrix(cov) n <- length(mean) if (!is.list(g)) g <- list(g) if ( (dim(cov)[1] != n) || (dim(cov)[2] != n) ) stop(paste("Covariances should be a ", n, " by ", n, " matrix")) syms <- paste("x",1:n,sep="") for (i in 1:n) assign(syms[i], mean[i]) gdashmu <- t(sapply(g, function( form ) { as.numeric(attr(eval( ## Differentiate each formula in the list deriv(form, syms) ## evaluate the results at the mean ), "gradient")) ## and build the results row by row into a Jacobian matrix })) new.covar <- gdashmu %*% cov %*% t(gdashmu) if (ses){ new.se <- sqrt(diag(new.covar)) new.se } else new.covar } ### Matrix exponential ### If a vector of multipliers t is supplied then a list of matrices is returned. MatrixExp <- function(mat, t = 1, n = 20, k = 3, method="pade") { if (!is.matrix(mat) || (nrow(mat)!= ncol(mat))) stop("\"mat\" must be a square matrix") nr <- nrow(mat) ev <- eigen(mat) if (length(t) > 1) res <- array(dim=c(dim(mat), length(t))) if (any ( duplicated(ev$values) ) || is.complex(ev$values) || det(ev$vectors) == 0) { for (i in seq(along=t)) { if (method=="series") { ## series approximation ## adapted from mexp in Jim Lindsey's rmutil x matt <- mat*t[i] / 2^k sum <- power <- diag(nr) for (r in 1:n) { power <- matt %*% power / r sum <- sum + power } for (s in 1:k) sum <- sum %*% sum resi <- sum } else if (method == "pade") { ## C function adapted from JAGS by Martyn Plummer resi <- .C("MatrixExpPadeR", res=double(length(mat)), as.double(mat), as.integer(nr), as.double(t[i]))$res resi <- matrix(resi, nrow=nrow(mat)) } else stop("Method should be \"pade\" or \"series\"") if (length(t)==1) res <- resi else res[,,i] <- resi } } else { ## spectral decomposition evinv <- solve(ev$vectors) for (i in seq(along=t)) { resi <- ev$vectors %*% diag(exp(ev$values * t[i])) %*% evinv if (length(t)==1) res <- resi else res[,,i] <- resi } } res } ### Truncated normal distribution dtnorm <- function(x, mean=0, sd=1, lower=-Inf, upper=Inf, log=FALSE) { ret <- numeric(length(x)) ret[x < lower | x > upper] <- if (log) -Inf else 0 ind <- x >=lower & x <=upper if (any(ind)) { denom <- pnorm(upper, mean, sd) - pnorm(lower, mean, sd) xtmp <- dnorm(x, mean, sd, log) if (log) xtmp <- xtmp - log(denom) else xtmp <- xtmp/denom ret[x >=lower & x <=upper] <- xtmp[ind] } ret } ptnorm <- function(q, mean=0, sd=1, lower=-Inf, upper=Inf, lower.tail=TRUE, log.p=FALSE) { ret <- numeric(length(q)) ret[q < lower] <- 0 ret[q > upper] <- 1 ind <- q >=lower & q <=upper if (any(ind)) { denom <- pnorm(upper, mean, sd) - pnorm(lower, mean, sd) if (lower.tail) qtmp <- pnorm(q, mean, sd) - pnorm(lower, mean, sd) else qtmp <- pnorm(upper, mean, sd) - pnorm(q, mean, sd) if (log.p) qtmp <- log(qtmp) - log(denom) else qtmp <- qtmp/denom ret[q >=lower & q <=upper] <- qtmp[ind] } ret } qtnorm <- function(p, mean=0, sd=1, lower=-Inf, upper=Inf, lower.tail=TRUE, log.p=FALSE) { if (log.p) p <- exp(p) if (!lower.tail) p <- 1 - p ret <- numeric(length(p)) ret[p == 1] <- upper ret[p == 0] <- lower ret[p < 0 | p > 1] <- NaN ret[upper < lower] <- NaN ind <- (p > 0 & p < 1 & lower <= upper) if (any(ind)) { hind <- seq(along=p)[ind] h <- function(y) { (ptnorm(y, mean, sd, lower, upper) - p)[hind[i]] } ptmp <- numeric(length(p[ind])) for (i in 1:length(p[ind])) { interval <- c(-1, 1) while (h(interval[1])*h(interval[2]) >= 0) interval <- interval + c(-1,1)*0.5*(interval[2]-interval[1]) ptmp[i] <- uniroot(h, interval, tol=.Machine$double.eps)$root } ret[ind] <- ptmp } if (any(is.nan(ret))) warning("NaNs produced") ret } ## Rejection sampling algorithm by Robert (Stat. Comp (1995), 5, 121-5) ## for simulating from the truncated normal distribution. rtnorm <- function (n, mean = 0, sd = 1, lower = -Inf, upper = Inf) { if (length(n) > 1) n <- length(n) mean <- rep(mean, length=n) sd <- rep(sd, length=n) lower <- rep(lower, length=n) upper <- rep(upper, length=n) lower <- (lower - mean) / sd ## Algorithm works on mean 0, sd 1 scale upper <- (upper - mean) / sd ind <- seq(length=n) ret <- numeric(n) ## Different algorithms depending on where upper/lower limits lie. alg <- ifelse( lower > upper, -1,# return NaN if lower > upper ifelse( ((lower < 0 & upper == Inf) | (lower == -Inf & upper > 0) | (is.finite(lower) & is.finite(upper) & (lower < 0) & (upper > 0) & (upper-lower > sqrt(2*pi))) ), 0, # standard "simulate from normal and reject if outside limits" method. Use if bounds are wide. FIXME HSOULD BE ifelse( (lower >= 0 & (upper > lower + 2*sqrt(exp(1)) / (lower + sqrt(lower^2 + 4)) * exp((lower*2 - lower*sqrt(lower^2 + 4)) / 4))), 1, # rejection sampling with exponential proposal. Use if lower >> mean ifelse(upper <= 0 & (-lower > -upper + 2*sqrt(exp(1)) / (-upper + sqrt(upper^2 + 4)) * exp((upper*2 - -upper*sqrt(upper^2 + 4)) / 4)), 2, # rejection sampling with exponential proposal. Use if upper << mean. 3)))) # rejection sampling with uniform proposal. Use if bounds are narrow and central. ind.nan <- ind[alg==-1]; ind.no <- ind[alg==0]; ind.expl <- ind[alg==1]; ind.expu <- ind[alg==2]; ind.u <- ind[alg==3] ret[ind.nan] <- NaN while (length(ind.no) > 0) { y <- rnorm(length(ind.no)) done <- which(y >= lower[ind.no] & y <= upper[ind.no]) ret[ind.no[done]] <- y[done] ind.no <- setdiff(ind.no, ind.no[done]) } stopifnot(length(ind.no) == 0) while (length(ind.expl) > 0) { a <- (lower[ind.expl] + sqrt(lower[ind.expl]^2 + 4)) / 2 z <- rexp(length(ind.expl), a) + lower[ind.expl] u <- runif(length(ind.expl)) done <- which((u <= exp(-(z - a)^2 / 2)) & (z <= upper[ind.expl])) ret[ind.expl[done]] <- z[done] ind.expl <- setdiff(ind.expl, ind.expl[done]) } stopifnot(length(ind.expl) == 0) while (length(ind.expu) > 0) { a <- (-upper[ind.expu] + sqrt(upper[ind.expu]^2 +4)) / 2 z <- rexp(length(ind.expu), a) - upper[ind.expu] u <- runif(length(ind.expu)) done <- which((u <= exp(-(z - a)^2 / 2)) & (z <= -lower[ind.expu])) ret[ind.expu[done]] <- -z[done] ind.expu <- setdiff(ind.expu, ind.expu[done]) } stopifnot(length(ind.expu) == 0) while (length(ind.u) > 0) { z <- runif(length(ind.u), lower[ind.u], upper[ind.u]) rho <- ifelse(lower[ind.u] > 0, exp((lower[ind.u]^2 - z^2) / 2), ifelse(upper[ind.u] < 0, exp((upper[ind.u]^2 - z^2) / 2), exp(-z^2/2))) u <- runif(length(ind.u)) done <- which(u <= rho) ret[ind.u[done]] <- z[done] ind.u <- setdiff(ind.u, ind.u[done]) } stopifnot(length(ind.u) == 0) ret*sd + mean } ### Normal distribution with measurement error and optional truncation dmenorm <- function(x, mean=0, sd=1, lower=-Inf, upper=Inf, sderr=0, meanerr=0, log = FALSE) { sumsq <- sd*sd + sderr*sderr sigtmp <- sd*sderr / sqrt(sumsq) mutmp <- ((x - meanerr)*sd*sd + mean*sderr*sderr) / sumsq nc <- 1/(pnorm(upper, mean, sd) - pnorm(lower, mean, sd)) nctmp <- pnorm(upper, mutmp, sigtmp) - pnorm(lower, mutmp, sigtmp) if (log) log(nc) + log(nctmp) + log(dnorm(x, meanerr + mean, sqrt(sumsq), 0)) else nc * nctmp * dnorm(x, meanerr + mean, sqrt(sumsq), 0) } pmenorm <- function(q, mean=0, sd=1, lower=-Inf, upper=Inf, sderr=0, meanerr=0, lower.tail = TRUE, log.p = FALSE) { ret <- numeric(length(q)) dmenorm2 <- function(x)dmenorm(x, mean=mean, sd=sd, lower=lower, upper=upper, sderr=sderr, meanerr=meanerr) for (i in 1:length(q)) { ret[i] <- integrate(dmenorm2, -Inf, q[i])$value } if (!lower.tail) ret <- 1 - ret if (log.p) ret <- log(ret) ret } qmenorm <- function(p, mean=0, sd=1, lower=-Inf, upper=Inf, sderr=0, meanerr=0, lower.tail = TRUE, log.p = FALSE) { if (log.p) p <- exp(p) if (!lower.tail) p <- 1 - p ret <- numeric(length(p)) ret[p == 1] <- Inf ret[p == 0] <- -Inf ret[p < 0 | p > 1] <- NaN ind <- (p > 0 & p < 1) if (any(ind)) { hind <- seq(along=p)[ind] h <- function(y) { (pmenorm(y, mean, sd, lower, upper, sderr, meanerr) - p)[hind[i]] } ptmp <- numeric(length(p[ind])) for (i in 1:length(p[ind])) { interval <- c(-1, 1) while (h(interval[1])*h(interval[2]) >= 0) interval <- interval + c(-1,1)*0.5*(interval[2]-interval[1]) ptmp[i] <- uniroot(h, interval, tol=.Machine$double.eps)$root } ret[ind] <- ptmp } if (any(is.nan(ret))) warning("NaNs produced") ret } rmenorm <- function(n, mean=0, sd=1, lower=-Inf, upper=Inf, sderr=0, meanerr=0) { rnorm(n, meanerr + rtnorm(n, mean, sd, lower, upper), sderr) } ### Uniform distribution with measurement error dmeunif <- function(x, lower=0, upper=1, sderr=0, meanerr=0, log = FALSE) { if (log) log( pnorm(x, meanerr + lower, sderr) - pnorm(x, meanerr + upper, sderr) ) - log(upper - lower) else ( pnorm(x, meanerr + lower, sderr) - pnorm(x, meanerr + upper, sderr) ) / (upper - lower) } pmeunif <- function(q, lower=0, upper=1, sderr=0, meanerr=0, lower.tail = TRUE, log.p = FALSE) { ret <- numeric(length(q)) dmeunif2 <- function(x)dmeunif(x, lower=lower, upper=upper, sderr=sderr, meanerr=meanerr) for (i in 1:length(q)) { ret[i] <- integrate(dmeunif2, -Inf, q[i])$value } if (!lower.tail) ret <- 1 - ret if (log.p) ret <- log(ret) ret } qmeunif <- function(p, lower=0, upper=1, sderr=0, meanerr=0, lower.tail = TRUE, log.p = FALSE) { if (log.p) p <- exp(p) if (!lower.tail) p <- 1 - p ret <- numeric(length(p)) ret[p == 1] <- Inf ret[p == 0] <- -Inf ret[p < 0 | p > 1] <- NaN ind <- (p > 0 & p < 1) if (any(ind)) { hind <- seq(along=p)[ind] h <- function(y) { (pmeunif(y, lower, upper, sderr, meanerr) - p)[hind[i]] } ptmp <- numeric(length(p[ind])) for (i in 1:length(p[ind])) { interval <- c(-1, 1) while (h(interval[1])*h(interval[2]) >= 0) interval <- interval + c(-1,1)*0.5*(interval[2]-interval[1]) ptmp[i] <- uniroot(h, interval, tol=.Machine$double.eps)$root } ret[ind] <- ptmp } if (any(is.nan(ret))) warning("NaNs produced") ret } rmeunif <- function(n, lower=0, upper=1, sderr=0, meanerr=0) { rnorm(n, meanerr + runif(n, lower, upper), sderr) } ## The exponential distribution with piecewise-constant rate. Vector ## of parameters given by rate, change times given by t (first should ## be 0) dpexp <- function (x, rate = 1, t = 0, log = FALSE) { if (length(t) != length(rate)) stop("length of t must be equal to length of rate") if (!isTRUE(all.equal(0, t[1]))) stop("first element of t should be 0") if (is.unsorted(t)) stop("t should be in increasing order") ind <- rowSums(outer(x, t, ">=")) ret <- dexp(x - t[ind], rate[ind], log) if (length(t) > 1) { dt <- t[-1] - t[-length(t)] if (log) { cs <- c(0, cumsum(pexp(dt, rate[-length(rate)], log.p=TRUE, lower.tail=FALSE))) ret <- cs[ind] + ret } else { cp <- c(1, cumprod(pexp(dt, rate[-length(rate)], lower.tail=FALSE))) ret <- cp[ind] * ret } } ret } ppexp <- function(q, rate = 1, t = 0, lower.tail = TRUE, log.p = FALSE) { if (length(t) != length(rate)) stop("length of t must be equal to length of rate") if (!isTRUE(all.equal(0, t[1]))) stop("first element of t should be 0") if (is.unsorted(t)) stop("t should be in increasing order") q[q<0] <- 0 ind <- rowSums(outer(q, t, ">=")) ret <- pexp(q - t[ind], rate[ind]) mi <- min(length(t), max(ind)) if (length(t) > 1) { dt <- t[-1] - t[-mi] pe <- pexp(dt, rate[-mi]) cp <- c(1, cumprod(1 - pe)) ret <- c(0, cumsum(cp[-length(cp)]*pe))[ind] + ret*cp[ind] } if (!lower.tail) ret <- 1 - ret if (log.p) ret <- log(ret) ret } qpexp <- function (p, rate = 1, t = 0, lower.tail = TRUE, log.p = FALSE) { if (length(t) != length(rate)) stop("length of t must be equal to length of rate") if (!isTRUE(all.equal(0, t[1]))) stop("first element of t should be 0") if (is.unsorted(t)) stop("t should be in increasing order") if (log.p) p <- exp(p) if (!lower.tail) p <- 1 - p ret <- numeric(length(p)) ret[p == 1] <- Inf ret[p == 0] <- -Inf ret[p < 0 | p > 1] <- NaN ind <- (p > 0 & p < 1) if (any(ind)) { hind <- seq(along = p)[ind] h <- function(y) { (ppexp(y, rate, t) - p)[hind[i]] } ptmp <- numeric(length(p[ind])) for (i in 1:length(p[ind])) { interval <- c(-1, 1) while (h(interval[1]) * h(interval[2]) >= 0) interval <- interval + c(-1, 1) * 0.5 * (interval[2] - interval[1]) ptmp[i] <- uniroot(h, interval, tol=.Machine$double.eps)$root } ret[ind] <- ptmp } if (any(is.nan(ret))) warning("NaNs produced") ret } ## Simulate n values from exponential distribution with parameters ## rate changing at t. Simulate from exponentials in turn, simulated ## value is retained if it is less than the next change time. rpexp <- function(n=1, rate=1, t=0) { if (length(t) != length(rate)) stop("length of t must be equal to length of rate") if (!isTRUE(all.equal(0, t[1]))) stop("first element of t should be 0") if (is.unsorted(t)) stop("t should be in increasing order") if (length(rate) == 1) return(rexp(n, rate)) if (n == 0) return(numeric(0)) if (length(n) > 1) n <- length(n) ret <- numeric(n) # outcome is a vector length n left <- 1:n for (i in seq(along=rate)){ re <- rexp(length(left), rate[i]) # simulate as many exponentials as there are values remaining r <- t[i] + re success <- if (i == length(rate)) seq(along=left) else which(r < t[i+1]) ret[left[success]] <- r[success] left <- setdiff(left, left[success]) # indices of values in outcome remaining to simulate. if (length(left)==0) break; } ret } ## TODO remove this when enough people have upgraded to R 2.7.0, which ## has this in base. identity <- function(x)x msm/R/constants.R0000644000176000001440000001301011760722214013433 0ustar ripleyusers### PACKAGE GLOBAL CONSTANTS ### ### List of allowed hidden Markov model distributions ### and names of parameters for each distribution ### MUST BE KEPT IN THE SAME ORDER as the C variable HMODELS in src/lik.c .msm.HMODELPARS <- list( categorical=c("ncats","basecat","prob"), # vector identity = NULL, uniform = c("lower", "upper"), normal = c("mean", "sd"), lognormal = c("meanlog", "sdlog"), exponential = c("rate"), gamma = c("shape","rate"), weibull = c("shape","scale"), poisson = c("rate"), binomial = c("size","prob"), truncnorm = c("mean", "sd", "lower", "upper"), metruncnorm = c("mean", "sd", "lower", "upper", "sderr", "meanerr"), meuniform = c("lower", "upper", "sderr", "meanerr"), nbinom = c("disp","prob"), beta = c("shape1","shape2"), t = c("mean","scale","df") ) ## TODO - non-central beta, cauchy, chisq, noncentral chisq, F, ## non-central F, geometric, hypergeometric, logistic, t, noncentral ## t. .msm.HMODELS <- names(.msm.HMODELPARS) ### Parameter in each distribution that can have covariates on it .msm.LOCPARS <- c(categorical="p", identity=NA, uniform=NA, normal="mean", lognormal="meanlog", exponential="rate", gamma="rate", weibull="scale", poisson="rate", binomial="prob", truncnorm="mean", metruncnorm="meanerr", meuniform="meanerr", nbinom="prob", beta=NA, t="mean") ### Link functions for generalised regressions. ### MUST BE KEPT IN SAME ORDER as LINKFNS in lik.c .msm.LINKFNS <- c("identity", "log", "qlogis") .msm.INVLINK <- c(identity="identity", log="exp", qlogis="plogis") ### Parameters which are always fixed, never estimated .msm.AUXPARS <- c("lower", "upper", "which", "size", "meanerr", "ncats", "basecat", "p0", "pbase", "initp0") ### Parameters which should be defined as integer .msm.INTEGERPARS <- c("size") ### Defined ranges for parameters .msm.PARRANGES <- list(qbase=c(0, Inf), lower=c(-Inf,Inf), upper=c(-Inf, Inf), mean=c(-Inf, Inf), sd=c(0, Inf), meanlog=c(-Inf,Inf), sdlog=c(0, Inf), rate=c(0, Inf), shape=c(0, Inf), shape1=c(0,Inf), shape2=c(0,Inf), prob=c(0, 1), meanerr=c(0, Inf), sderr=c(0, Inf), disp=c(0, Inf), initp=c(0, 1), initpcov=c(-Inf,Inf), df=c(0, Inf) ) ### Transforms to optimise some parameters on a different scale ### Univariate transforms only: doesn't include multinomial logit transform used for misclassification p. .msm.TRANSFORMS <- do.call("rbind", lapply(.msm.PARRANGES, function(x) { if (identical(x, c(0, Inf))) c(fn="log",inv="exp") else if (identical(x, c(0, 1))) c(fn="qlogis",inv="plogis") else NULL } ) ) ### Distinct labelled (1 and) 2 and 3 state directed graphs. ### graphs with common "iso" are isomorphic (i.e. identical when states are unlabelled) ### "perm" is permutation of states needed to transform graph into the first in the list of isomorphisms ### This database is used to determine the appropriate method for calculating the analytic P matrix. ### The numbered label gives the indices into the matrix of rates (vectorised by reading across rows) ### e.g. the model with qmatrix of the form ### *,1,1 ### 0,*,1 ### 0,0,* is "1-2-4" ### well-disease, well-death, disease-death transitions allowed. .msm.graphs <- list( "1" = list(), "2" = list( "1" = list(iso=1, perm=c(1,2)), "2" = list(iso=1, perm=c(2,1)), "1-2" = list(iso=2, perm=c(1,2)) ), "3" = list( "1-2" = list(iso=1, perm=c(1,2,3)), "3-4" = list(iso=1, perm=c(3,1,2)), "5-6" = list(iso=1, perm=c(2,3,1)), "1-4" = list(iso=2, perm=c(1,2,3)), "1-5" = list(iso=2, perm=c(2,3,1)), "2-3" = list(iso=2, perm=c(2,1,3)), "2-6" = list(iso=2, perm=c(1,3,2)), "3-6" = list(iso=2, perm=c(3,2,1)), "4-5" = list(iso=2, perm=c(3,1,2)), "1-6" = list(iso=3, perm=c(1,2,3)), "2-4" = list(iso=3, perm=c(3,1,2)), "3-5" = list(iso=3, perm=c(2,3,1)), "1-2-4" = list(iso=4,perm=c(1,2,3)), "1-2-6" = list(iso=4,perm=c(1,3,2)), "1-5-6" = list(iso=4,perm=c(2,3,1)), "2-3-4" = list(iso=4,perm=c(2,1,3)), "3-4-5" = list(iso=4,perm=c(3,1,2)), "3-5-6" = list(iso=4,perm=c(3,2,1)), "1-3-5" = list(iso=5,perm=c(1,2,3)), "1-3-6" = list(iso=5,perm=c(2,1,3)), "1-4-6" = list(iso=5,perm=c(3,1,2)), "2-3-5" = list(iso=5,perm=c(1,3,2)), "2-4-5" = list(iso=5,perm=c(2,3,1)), "2-4-6" = list(iso=5,perm=c(3,2,1)), "1-2-4-6" = list(iso=6,perm=c(1,2,3)), "1-3-5-6" = list(iso=6,perm=c(2,3,1)), "2-3-4-5" = list(iso=6,perm=c(3,1,2)) ), "4" = list( "1-5-9" = list(iso=1,perm=c(1,2,3,4)), "1-3-5-6-9" = list(iso=2,perm=c(1,2,3,4)) ), "5" = list( "1-6-11-16" = list(iso=1,perm=c(1,2,3,4,5)), "1-4-6-8-11-12-16" = list(iso=2,perm=c(1,2,3,4,5)), "1-6-7-11-12" = list(iso=3,perm=c(1,2,3,4,5)) ) ) msm/data/0000755000176000001440000000000012061401532012001 5ustar ripleyusersmsm/data/psor.txt.gz0000644000176000001440000001134712061401532014152 0ustar ripleyusersU[lmG "c&9 A~)淫ViIS?_?$?S{?S~Oc*By}cGiOu|x̅l!֏R3Z:V#b?Ln2ڕS*f!{㣣M_iKǧc+ʼnT9goq|Z-#Y1k={DquE᳆-=Ő:<+5ױyu] kH`Yg!K>I jeJOYJ!G3zW ꧚fgKd%U*@ժď.io%=4½38ѷfX<7Z}fY\y'g\?`Io+:ZW*z$e~cuO:ͽdw5Wk[љ^vh%,::'.q Kkq`UG8o|lJ>ms-{F:*3?[c#*E0YPy8;|c|QOW#"RyyY(laڌt0%R/0}8:0 V5w]WZkq g8c^OGS'zQkӬ nEtBlq^5=d궮)~#]"tA68`D.+=6t$ \v$#u牶 35T20%UǕك+7xyȈZdI+=MA:O3 2z88 Q235C#\Kz{2 Ƚg]"cC2":\HS,'m.= ¡͞>/=h6wP `%̞JP`P}=`2nMջlQ#aF$up'.5²HYkJ 4y/j*k,d5#*־rUeUzXDwZzl˚ S#/ HO`@픑,yHC g9)PJ<@)Ri(=X\el;rP e,1J3|$uw#v*ͦqAՌ x|?*Lȴ_\gwj¬A]EeVOy1]NjP-6An ^I.,K_! 6/+m̝' z]j#}lK]mjeOjsEj*p:Mu?Ǹvyw 0Ie9]`v Ҵeʪ/`Xe2]>?#AV$ ڵ41(rs0 6ۺS[0䜴/5PsbSQzf0,krl"Z_w ::}tfvH%Qz'[٨ j!b&&ǐ%r4'ѝ B6A*0%F(ӗyjtx<"VG"Km:}ؚdw@.<2f5]𜨛EωP+h&KVKr/YPxK={~ hةY-=C%mseofoxLdyWt޽tKE+BrmjlP%`:U5L GaAz6KCY]u&:u; HqJr1˧RMxYWZVk-qE ":p>Q~Rn>$sM"@f%toCm,T3R@iZD e3gHUw`%r*vW4ܩNTFx z/kM/Wgwu#`=~T'P稷\|;A̤MUe}J`l i HΕf Ϟ3Ɠ=уɾ";L <+0'-zkI: N2( s%EUDA疾g4O}#Ԭ$g$kbɮm)!eT4wĆo{̿8HDIz&;X{i ]An@~1Ȏz,j͉ AݩVRF;LfY!AUH-`6&:X̙hc%͕]0NT/|ɤwNbm@ 7&7RR/a(r'l@KU #oֵK%Y{6<4IId78!c[w58=mG"͌AM'1،"F6$tO3Q].4]dM< M r 1Z]}RuN N/ Y5N,8{>LOX0yO>&z?sz;B, nKdZonj! >-8`y{u f[钗+P|qgw:ѹ!zP PkuBDdz^\h]PJv t.@Ql|ŝc$TGa3z[EEEzv{^97pVLҾ|_)t9={?kFoi/ :}cxz֝f/>%rm޻a~r٬G͏H5ڙHMBkA*M@ZsS[-Yپv&v'bw-~1m&gC_9!ོc{yHk+'0p"ۋ-3l'TD&2MPlJEJ; M# BAqZ`C9LWeӰRZÑr2^8YL l@C7=ԌS:6)Ľj#ÑC8fu($jUD&][j#Wu7zf()y=ѐ9yFl5_&-+@n֡+97^;o/vUM*' UzH&ͭ2Xyxvq_TswE\ !x,5 Dz22NKV*ӖڵdBZ1/6w$crͼ1ed7v* pv%zV:Ri/o=mݒ2gwFWW~zqmu9'$+RX3dٺ~AB~q:-ONh&!XjyRż&aԼFP|/KywZgwoJWlOZͅ>ݵm`FWanW2imiw}9vC. 3ļGi'ٹ5Ie1 sEV' I{^߄nvYNulKM7GB#w D8g>6UnNoȭ 4p&L"'2"d] XoeN(v&6|w2U^wҽp2G ~OG8' EW|Ξ:AzXٳ}}གӳ''v6bh6\>*^up܉H;_xG6VfˏBHon,`7`gvOC6yM5xӭgn_)o3fQWٍW.h-Sp2.Og&, I-e_Yc}AI,D~๛7Vt SбNn$&LJPvo0n'Xgk1|p`G Ru!.7rg3v ~ֱl=Ͼ}ϗ0(][=s||H@&\/1^wKC@R%T/W ºTKX[%<ݐ$j+ s º`K PNs4TIN!$L\GIh.i?}f%`/^yg QN!MC\  C6aܿRT2*&+eG: =,Yo%6!㑬KZ7~.<<ق\;_~_asy=|5T;ds,v(gW7z^.97ٸ9ṗb,nil9970ٸ9'f6_yE(sӋ~g < qKC9L^g S| gm$crw ”+b=DRLBRb_,& eb= P&,N6RZ .\jύgE?Ә !.gk8>i;݌ n>$J"ȫy-=^^}]tjlU4V* CR./F45J.L%zU'DC\MF[Ex"aBhX3mko!|MIB6X3Í5L3kq&.ɻ{Z DVo!LMZVr"tZEOKx,<@G i0fSyMvx!M^g7 Yh6.f ahWH0̈́L*.hj.es9Bye׫.HO[C|tEzp~W& |Rf?ߍ[HL x,SCt3<"+w7HQ)]FbJ,5G%<{.L/-0@*sss/2=x+ 6RIfg0X\;kߔʐxCr\?t,GpU<#X`KC7%ĪR sr(an!MKӅ3{8|1m5MtmqZt0M& RK! :44%=M7P/3Xo&NIetwY#qO0Tm, ^u>3F?g=Y ½}|:SRU!°t ]\K GfGZfÓw})kӴx0pk0כ@hWT2) M7;纃Mo^C[[ܷ0ܲ۸zCyƇHcg`/ŋ]R`]{"nnr8ȷ)vÕC n%c5nH!w;rCRKM&j0mFh~ѾMw!Fw?ݏt}t[[wwq!8,=Cy[EJ(m%#x߇%zx&zdsm)^83^Q/aʢsɔ2JVJK:ucYt@$Tvr#Mk倳\&W $9]ta'WUZ/= KW;LQհQ-M=x8%3MXuEWv$<ޥ"VaZJ4TVJ]V,^>Q mp"|bP3rABPRXDS'<$_II dj")30# $`5WDRe{)/l`:{%s B*3!kyJvXCqoN8SxHe.U"8ЄSCΓ;NR 85 OMayєe|ΟId9XlTҚR kĂK'K'5A^MWYP&Ca"ugmF,ׂ=/3J@ZVxicQ$u 2-,5 LEPM':S8ePj R* >i~FR[Zme^mL5mP5<~_rփzf ! WP;01dWf3p@o,1._ 5)rc8m8!r?gvHܱB;+o ގâMv;(}\^|%@Wtf|$+rM`j&\x&"Lx5^ CX88 -Ny zJx1R or6JoS=.48$,EKV,B $p)Z\ }OrQ&]1!,]'0)OF) ,K@P T C%MF2 m.BA'lRU Z瑏HBB+V5R5U(SX-`rPywo2BTqAL%GMB):(81_s )."EןF`UQ 5 DEE,\7U1@1XMBVY~:[,V>3$C [p%Yi,H03K)X0@T-v $6v"]Ih,RIxly+܆D40$xrj,N@h Z+(9Na(.!ԋ0+PAnN ^D2ӕ|yz > O*"{T'AZK=Jzy|,dx2J :P'a74ļT^̪=6( .xz?> 0 pR B g@?}۩BV(H7& uF@LDUARYM֦ sȏ76Mа*HZU$w31!aQOTP@H\]T$T$TCФ"q"`4">( t3ּ=w+}f \?97~hP] a3 *Uj0$П<)Կ}O$g'Crꀗb{(N,O}ZLtӍǮ:%# WMxhj| R =aX @? Ge5G" R(*ܹ2F1ef6*UY*nNȂQcOOF!@X(c?l2u먠ͪʪqhhr<~nez, {Aye>YRMʨ%Ȫ%`fTK8<ɬpv&!&mX\f {J@]C0581D|UÀ2hzV bE  VUKT0d`@/䌚Z^րV5d^rs((t^22ɬbm^VT:6 vAKy>ȯ(k~Vo̬gBd˦pU1\e' Pg8r( 㪏y}WoY{W~Z[m.s訑ɚV(ɹ*,/fq0|_e1+s`p & Uhp}H dvgV* h\UJ8@ | β'hJÑQal M$gY?¯\ u.t0u## 'KQ(]V8\dpa ^QQ"KmO7eFBVC8T3ԣJ34!) *OVVyBLv*.x(Xt`JP obT f# ӘQzQ . d "RX΅rrf)I(X^  D↬j dU+ ҢD;qG*ú'o /Upα,w6JCEyEQk;%TdoTS fY)zVdЃSyY-}Usqo ?%.J8, )l*a-bXGJͫYC/^>T>З,d>+n # ' [/@HX _b{v t1r<8\S G^.;!x}d xԊf`,ߢj,gte[?ra6p*ς?čQ?wÙP@=^5N[jc2,Y9d]: /=Կx{?/p ;; fs4:hF/+g O2]0,0 HsvrHspqQh2+g5fS%{g6q煃3l(G{@V{6*]qd7%|}a WiK1H9ZL_H?X@|p 9p$<<&Fl@9 PLRʈ'3 C@0,̙c`tǜ<(oKg5c M(3G+@ 5qzȬpr΁)yFw;nJR-߼~uuiꢪ' 5Lo0l2?}ZZ RW -w8<Ӽa,w9(@uswC >23جme5m3ߡmzfm>msQzr\&|GI?s%r$,<Ǟ3X0 [x, bX34ڰ9mD;95Q>h'|{@rF;afa{fPip_-jhPj*w9>X:bQ PE( C>z "E(J:9,R#z.I91(Q8ygf`ÖE) ryCEh"Lelqg[$Z@lDa=T!l9nesQe"[e*Ja0EX% p"ʴ_+CpJ)* R4Vs x_h$H[9xr~xdѡ^7UoVI(1_3()M)PiE%69nyGgǜPE %R&+);ZJYySw 0yy@1I^EّP $? |gp~#,)Q]SSS9K*Y|5F%\b{ݔ d&0HEd3prgemG_cq;p",EXf ,6*)e*evBM+Te6vӂjÖ9[ '"l'3R|Tȏ@i /nJ9gjJ?x%rKQ{Z_r(>cGw#9Q> ^@Kd@*E AK\hJsp$lz? Gk/7{ KDhrj^&ռ0LTa`0X!\jG,gjH60)@^}_p"3t4AH5f~?.Ku(zV!ەķ'ƫņ>7[ fqddDzTgP((X-MuPUBZ!+ǪCϊht\9J ۦFg "Fg\Wμ:UjQaqFz0*0~X1R Ky(`V4 No@J{H5ufV~.?K kgnv 0,me~\C/!5'[L, 6Ogs0izڷbu࣮[:ep]mST.\K E=4..KwQKGr~]}Ջ|xޤ(-7o+ MT? MuaMX090Q>I9sӀ&bZ>V:2F3qfb1>}1et^;0L$0UoڄNNZ,8QZp,8,>;u"SS,35(3zy nY ސPnQF.ZbKӐ=3-F1,L"" eG,>u:n _'^f:chJƻXh"BL/i 8,E,>a#aǧ*xOyl?)2QR|Q?+ 2)* k<՝_))jVukr4r3"2ߒ!H=gYK WX*c[y\@FlQGv-9@-w; "㧡l}4`>VZb\9ԴP"L8C|2 VgUB&7Sk*c&RԚ" il@hlF1U}PCU}'|k+thIH_3ul䓦COggVmb.,SsbTZsro Z]V᠟USڈ* {} h^T:9 DaU'lnU'"6ķm.o-c#U=:v4JZ}Ht سz7gn쉠Ҭ>%{y%SCp|J9yn4?3G)-uAģXL 8hԎ@Ь>\:U&Z9+;6yPTAH-Uo'_yėJ~nq>ߞa~>94&wG&dWm@͏*76=r91\:>O |@O޲>Ru# wļ RUs;GN-ca՟^ڼ-K:  TnTMVT`xucxo@]wbD޳fMUoZ # #6BA)~F,L'C4X' G~gmY8#ysInꑄ96Y<$b~JkTOOTY}{+P"Z\DҼCG6YM=d9AlakHPOf)@|-SUhL1r.@8k?jnph~CU!@f G,GCRsoJX Uo~lrT?ķoX-*pB/D%F g"fD!@kɒM[aD4:hmY}[[ꍘE5by})r z'F-('7N}2O  ^};Z\+źťVO}(-qL4I7 P^r[0qU&pbʼ|ڄn!U]0:*`ɺ{JyZK mSVqow(5~G|ԫVuə崒@ #|H%`9jnj3HYEڙ$X'@k:Oh#9[p#ëFFqNϳq ^u֪FҍlY}^F(;$umF)Wd9v:AR>2)}Gh;^**.cPad#V"_.gHty5w=p5kҍX#S}U#Nrmjbw!N>2>ХTEB܇Ne_߰βf45TmXv]GAj6KU p_s]Ҧ+ķ9Fk+| (] n'p_߯kk@SC#$ћ4 C8k,`?ʚՏvvM]׮q: Ka욺v S7(maB' a\GkBCM]ooȰmu [:Y@ĶGo`aY" d66 ۀ63m^Ԓ.jCWùo 83f{ڂKxր!6Ȝ5ͧr)I mw,"x6Y|0>tcR~Ce|cU\=(qhMn bgȵ7r9| 9I.a^{KHo\}oXV(_go_}|;FETS""~?1/(6!prq!Ѹs!7Yr sT^ׄaVS|gT@!x' C܄}!^+ O4x4x(n6up.\&p뚣s0)Bkkd; S4#x\~M{5& t'& u«o&,|EjtZ|$*li 8Z-g9HZdU,0 }~`؋z-T}Yq=X Kgy!d aeiC|*M"t9 d1y"gjUC|*f=7F@z&&NR=zdzVQse!c՛q.yK9R-P<+ei䉤G9RWgWYijl#{jK"!sX%$ǛNH mC&6di4HR:HaQ4cf~4d9 E޼W9A(iyzh7hmaG9&t7,pm_i}Ŷ9 IvgYU yTv4V4'má1㘰':jk>< (dW mu>ĸ;w9 [j~Nj._p9v6o Q%63 9mXzěo@NwTv/Q|# 7J./Ç"rō {,j_[O/\+)@R8қ9ڄr7=MVO&69|tj_@_?Rj R;H/mš9" 9 OPl 6~`OڼS}y5͢0mrQϺ6o"ݼ dnQ4aLjHa:{ۼ4$!]pۀ6F :ܮYLj~ep\:来`!Y YfnD&@ֱ5j~m'Sl[b \6_y*S5Nkxd>uN;j6Qk^Ώ#ڝRaF:.`mmW=]G 1RO'S:E;޵CY:V{jCw祉WI\RMFvVX{f5ܽ54Zjڅ#Y \;NmJ&u\jK:;F۽ɷ qv@!vqSp:hYB+@PlDF"(k'pk=M뀲*t] vOՒCsYȻ So}KL^qFbqĻ5&N-L)W Ah$}/ p8 X^HRXmx^#1s>jeO=բ|u@{QBV8\Es!.兏syˋ nS\^,9.svBʩ5ޮVϳ˹-Xv>xq9kF9.ܮ't`罜ӛc1;r da1gX:1kkk@I=* P G}on{-v{haw~gD'3kT/%Pzn`7z]8nuuHu޽q7v!ey}[y󙽿+c6ufs&;01|/8`}UIgu罢&v޽AڄONM?xv#~C?.P9O<{z!(xv膆1Hw`[m iwy|)w; uDD;y6V'D l>FAnOGQ>V:`7#'{3pw7Dwo 97C @zO2X8xǯyJ;Gow5%SwZCеPcvbNLuywGl* @;{?ͻO1u|T?uབྷL>8 λ,GGXsCgqn qvYa|a;]Nt8x:LSy1 F.YK1`ݚbr \SýݽnP̀8'gq{qiWwb 4`qqaWwǫӣ>w0:>>!hC?i^ `"1"L$;+$ˑpS҂po:6Qb< F|̍.?v ; )Bh{0pnH鯾?Q*?Hq9)s_i~Dg<s\O7V;Ӡt[Z x*mSޛcSڟ`߄ǔ]­@*עߓ \Qzj?4߽3oBsvD&+w{Of^{Ӫg3󟱙 u ]Heõaey41oFޔwQS>niw٧Y[{tCQUⶱݔ7zd փ'>v"Y)鯁7mm@hԀ/pY/]zmnySck6E'Ew ^kST(=X.mDuSLpnO{I{iZm翗ځTL$XegL9_V[K4mkR7gMM`}^[LTH(}_T*\۶7e Àr%kA ȝF(]g'mh&r)Bghvx\ܠzMMAڔM (Ϗ*[0$mSV3% ( LS ly 2&{uǿ_޽70m7P04"{j;kX#9 i3wе)XU\3JUleFl ?͂3Ϣ8UFFLsNQN(1{-hS,um]s%E)ҏ[)K9MTU'&F{VR۔7/,AFP4movlq) do~ ^˜ұ憉+Hs0p5m*վKAMER-OMoy$BWˠ)"*pstH)홃\LQ" 6%pHQeZ'ܸE4d>TTnO)w N\UM?f5MU"Q7bB^e G̋MXqz7\Y!~,'(/iVn65dQ|(wj4Iq(6eUvm̒SpQ[0x[k:=L RAqs7\}%v|Pv4,yV41oJJaKم@~S=mRAmB?LWIk@R"?Pwi۔ LS SAwh-ۦOYQxh)@l)m]G3]8AC* ?Gc\bvP6T& &f V))ORDQ82^LZ BbҪrYYQ߹Mo\(sze @U _ 'f&ոCl]MLeG@֋2#+'&(*MvMhQIgr=Q$l2fP#19IQWP|}%=˯0DO$]siJZEp$B(%0"4);'@i_CBc޾"[H֮hkEE41_zd) Q׵)Ñ2 S{(*ef]3{Ɔ\ E,0{y~0r}^H?IMF)ؔ{iUw)<)4^.T/PKZ Psy%.DNGߔ'؄!s3"JJ2#Ѩ>M qӼV39t㤥#aX&EĢs}^ BA"KE+Xb#kQnAw/Eb·2|)݉>=^J)%Q:TOڌglZ}qH+Mc^!APYrU`Rgʌ4u%\MٕV#gG!uEQQ̤{e@D&E!;yorR[PKˀQG(?)ӋgMv/I{0/Po<4@3,VS֤@-ʣx9NQ<;D~6+lh\ڦ"tSLVճC|un%"-[ɖ׺$'Mþ!(ere9|UZ'?fs o{3_+>tb9B*-F6"c7i)G9+,R M1PFTLu2Q>/Gk^eM_~a^Jw3'C(YEx3f&ȓE [ơ[ U"C#(1(a3!4 S$z5^ޑ(rٛ ٛ‘H֊2"r>+BKQ\18>fIQn`(*vVDWBclZo^+GMQe1[BBL\i=*,@LBPv??_yMbΙ%uQ>[ tܲnzRsޭIx~%*\RL Kߎ Ble2VlgkPμi]%fvXx_ЭifEkfl# 4f<R9(=c'k;`a߾U=zo;kU2Wse*)Rm Q|A 'M?_=>lɊ\OZD9N 2Z+WwDcⅢ~ P+M 5CxB.j"a(r 3H)Hb( MSiS.<ŘV DP!tL(h}H%t g'/JBϋ-o(aҗLUJ ݐ dO,4WNeeRQ{܊IQVAU)m  L)(FUŪ~P,)szSӒ5PicbyeCŠO(ü)duD`PhDR<#Őn,Ak&sErDJۜAMsNv ,"̷4E?-U$o FU jnJH9ŸU;z: fu@Y2 zC#KAMFɘ T]WZy+A@x7B$EQx)e 4_Z2zgK)|k*WNOZC*J Vt5 f],%}S83o#-,m`߶gWY+J54x@ -e^ &vP h)RJd_14+{g|;vY }yp>/~Aݝbmek$4⇹Y5>r%!>t/FAԸM ICMkqHfDLo)&skB6 M5o1ܵS˕&]wv,)r5}1}wɏ}d-f," +*vو oa2^p J6D[TˆmgCzY1#BsSnOi=W8̪GbqT\M);gbyiǦtN0ʞ@  \Nx2z hz@l~'*)ue}yMey)-*-Y մq6EʱI_ЀS}?w!;%aD3<j7 EkcKMɞԔ?7e␆n(Ƹ#ݲ(2E"E2%E RޡPW1ʣu)gG>JPSQ@+juL(PEpeg MmZ4G@Ӈ7hИPUW /.O6%E8yPEHr{EpJS# |W'zAF{W(wF[]ȧ[,|1YJ>F}S4 γ=cMFhiڊTxrٔSצ4D~ʷRH`S?y (65;Tz2"ڔzP22kHR)rLg8fzcj70Rv?ьZ:RT7zKb"mO<msm/data/fev.txt.gz0000644000176000001440000007070212061401532013747 0ustar ripleyusers]Ym+Vl, jhϖ%#"2!g0d??/j6uK)-1/DX_PQkJK@oCÛ%,lU2"}J7Cy7=r͊hǟf1SZ_B\)=gAR*kWk`o1;/Rsۆr _V%[O#j{3S quY4(qr 0ݏm$Y",96۰po`^8GNOu}A}R=ptE8>*~'WZ2b=V]n)󅖱ئmPKW~6`!/y'‚&9֊$ߝ(L@PHB{aH+ԉK6d#͞/!LhOkؿz|gJ{~/N_#Xo̿n+sn@{$RE8yNKM[I;p|6ς@UhauP c>GAnwPuϢ܅Co5J5-s[NذǦY խ.\x?[6g5ppz ` Z6u7\Ц-[)D?05U,qccaKo8㪍3kܹφW'4p&2<c =0ny3q1ejh-m&>˜GlpZ pO,(0wyQXd"Ony4!=_j}fz_wq_V*OlMWvwU7a9)4)WHp$e*F!ۍdC:hWlDevA+ezeWHB^ R;%8q}ػ^)޼oɼ ߒ+u {K<`Moϔ+NN(͝TGCGQκ7>W L-{ӷφ*X˺7&޿Nk:C_x}ےByqYʛGg_oڽ?6u*8rmʛ$Cʹ^ryW3 ]Lc7}l.#A0?ܿNJ=M.i|eYoSkŹdJn"49_XQH ֽ]o>)h{eh%͘oksCl@)MNkDX>e>Y$GX@v]@\_闁kss ״[+83,~+g$R\8~eP:o^7Oh*dA$G7TB=\M<\}-fhQ>ڜϐ*wOLa ^\t]}(<}6l.{6^X G0؃%0^*alpJe^t 6pFÕ hCj3h/;Ne4})@+H9rCJ@59?9B {+n?u]1 8V9g&\2 I*?G䭽̈ Z.K_('soܐ)6/ ` P\yM E8&tmk,¶ 0([5/T7~}G-[!exFܺtlif#"Mf>s TǏ6 Wl{k&~xYssۧU.Hy$eµ"ȷ&!&@e#{{' 4c.NV7}|tn`_<==IR mŽZyab YX r~,?Om,o{pKqdjփ&nb;Ы:^\ӫD {pS%4m7$A|Gkh;&<>~ nZZkt k38WoK11~~}ox/,V_<:ϵM=0{ qcnғhwKuHb =ʤd'.5V( lآs!C7!HC#oleφ-V[ ~j,` ?oiҘY1fDZ)O,(62҈&f&1ņ\KRXlԃȤ%knGM BS#"Xx(IQ8&t A%k ٟwݐ;e-,#4Uµ"a`oyGbU&2/@EUXʁ \z=<֔uZ-R4x=~?>|sl?: ;Vث؄uj֛xRv!<]6ߑzT3pIJIX6j *8zre Uw{rKHiBMFBX톣Ėq8+?Zyo0A7'PVޢ^*`Xryaɨ*|!ί~ m8E/(A|gֲ`^6Y|3xMs{c3GC[l%f} V@t[VRBq- nCx)`71 I ny(_7dkUmd5f!N>)ݷŰ \3@BXDۛU2Q4\xy؇]Rl&DŽJdHh bлܗx&MwgOS5ŨU{J,j| @a+nA2=;;)Ԡh mI:mCG,f#t Eo:.]ޛN6~W2y|_Oc<+_Q]Zh0ӅLO{riD6TRMm\f{{|ԟtb=xi [H`P~=XQk (i< bBw)r6]zX)@67-A] gX($&T~~ ޝv7dz+q%~@B g$׬j5/^H ,IR2w D6LP^Cj"gIMQ tܒL԰z R,l=g:x1am_@ YXVOX Cp_Po|sgzF;#0x<}nD^ !xkG6N7\^\iGןN+8<[d <ph/ulsƊexzARՅpoҽǝώ)= DB\+0{/G_`|[zуUpK1Qr}B F9,{T ,Kjpn[F&ŰMu4357jvx/Kbۤ-K<ʝz8nټdFKGÝ[B[s(ooP`fb/}V[G,$/|lk.٬Pn5=;bФ-̗BETr1C 1#p! i:ۼyv(.aCFXq e=g~rɆ:NMt{e/eS#a+#TN df^jPĚ'tg$K; ;faHrzS ^!ɇf^-"AZfSAg=-Կ ޛ'~$hԖ:qLh n&p[(/"ب V`L'hZ( K td^Uh 6Ono4 AgP P`aL^˝=p0XߙNtzx4-.epgI&~ =pxpqz/ lXDCP\*SOARzx,yxKןז_Lg70K _G3ho峖LӅrG 0ebԛ Iv0>E4 a%T=P @֓zlޘ]Ӌil= w{0Qpt-?ӃJěJ~@{#W`6@C=/$%79pԥ{Q.a 4JcCYAK5$;./oi24Wa_uy>Դk zQɧdEcغ.'!I$07ZO=-deI093 kD{7baާP7L`_<dE<'v4,@[L1[Qe DlC=.}&Z8|Ec$EI&]Kɐ(R %8 "IYw]JL!X_,)*R{ct9O^ooek]ecjyP ? a,LiW>[4u0'KA.MYæN":lb!#~8w5y y ٧ϊ04>aL/A7kGv:cюnJT7ъP6'w|ҺF+ dp)Wˇ>8#| ڋBuoyU1*)uOvo) =T2v8ߛ?[})9Cg/}$o2ԟ= ~3$M,"GsHq{5#&kr<|-/ 'p0-e rJ>) Fa cX-_+Ϻt m~礄>_g vm=WfUjoj&VVzFDr  a|A;D~0o#?g4C|_dFND|Z{7.#v pZ]֞>)jFOc:x14ږ @=]哼ٌ!ջ0t%[-6@h4 g] ֧xgcI o|UEza 8h{2=7!bɞ㦫DMhxq6kqNQD5w/ѲwvtY`-|hĽ`!w&T%A.^칸Fx g2d% Y"lHta%ZpQc's5 ح#ARSP`طGa)&>ӧA֥;)O^ `Uҋj>-y-a招g#}aN`?#b{\XM&I-.vp{#|\Nt?a8|ٸ?8<%67g`"g1bfEmK S7+h\)޿xI7ƥW$Cy|ϷL AI86ox>pf 2ϯG'4ӣz2o(o㉮gӁa#WVDg'vv$+~kz]]3#r$p c|< s窔UiPJ3=}2Ar?X0 qf%s6vw4^;(Q+?ʙͬaaGx ?r,0=f`KUvX{JOfk k|҃'_dQjn> 'm1oU$h CB_pZ- fbZm m'`[ҽbȰKi w`)[E'ߍ8 C.4Qxi-Qt{v*QUpmJ;pPSp2^GifPBveqoЗlX =܏ ErlB>nN:"B-WM^kONz!Z(\R\\K7B"멻AŒ:뎙&e VCpXgTP7uuMBx{P^TGe!w  SBh7N.XXEV}#6g)q M1Tb7ޕM[OyZ i SIC|.B 49ĕz #׬,we+07,dJ)Zpe/߷/]^"o*| byr_*ޜ1 xOߣϻQPʔtra#PVBv8;R9fw xQvJg]ӓ'7yHuf }%j[Wn n=ӛ{l1m]!/K5Ca|)us7Mȗߗ.te.2,{8ӭT|y/ <`at2 Z\ؾt62\,Ga.m%H!Ǚ5 ;5Z\\!bCp!@E e?i13K>%/<i:g%=#) f+V^tLw1D|=|/zUc[Fw"&[hm>sKv߱$H,AJCM1O!nxos< n!/?.gx7ϋʬ ܗ56hdJl*5G!V- SClbTKV)Aeh֩[c86Igp*MlP?sNpu; z]>'=v|6*y{I#<2#lrM]Q(]?)2M)1L|HPK >C4C6[!iMk(;.]qf=|C{}96ig+fЌ.Vj>L0,{b]&0a+ Sc }}Li#z /,۬۰%øjYxr:iYd뼐 S 5^ 0nuva {otdx+,j(Z߸d߭IU ,e+=n,g-ٴA6HV;ʘ7*; [1ִrC~ iwtFb$]=a.|R˸d#J`f])/wj/"1έ4yd{N(HX^2u`s[fϡb}GAPUO]Ф鴉u{{3> )=,i Q6~fǺ`ܼbpj?vB^3uWX`[ qNϪtV}14L -8;?p>Bs;yw$eSp~:1 u&џ`K$65;1/ǺOR}!,q)kT0/-oXS[w=M.~paqTTuq|8 0L ڢnjrU 'qc`$e=MTqթ;Yvoz.U)pk3iԞю `5a3HPJ 'Y%RAłWX2q0]7R-/p'aLv VYr70M]_c^_`~~|#+B2Fr`2BahNwDTʙ9rlyTM>H%kI<&FȌO/i` JFĝv`r 3暤"ʓM'mW,BfpUB~ <-_9s'0EM!G0Ҋ, g ~7eTM,؍g#3oxtlQߐ Z<e1T%k(B`8'NvykW>WIqeKn`OOM0c;Hً8TRHFv]dŸp1Hq/@s|ҙA ABb[%AF7$m{Z%En&JLXv}H,Y\9B-0 'Wa6;x -R *ryW "|HdS5NdULȰ.>ja C]Z,iwa anHѳXvЦt˨Y#`P~s)$mM/N:ewB,`} {'i\̷Sfɿ; JfZYD阒wk[OJakSID̍e0Xf̰-l6VO£n~tI-cG OˠL'gUM(UX??ªuꈄ(sD5 vay?"=1 5w'z"g? N%!{ :ԅYF(ޖ]0ܫ1> #3s5ߣ >M1l"`SdF J *:GL#=XT)DiG4{XI%G+aMoct0F0oog2/v51Q3EHE,N򝨬nc2`qϸZ7YGL'`s$'̛(8=:uM Z?!{ii+X4goɋ[53gMbd:XV;i`ޅAm_y~,\Yl>- eUi@1JyșƮgJX>lw6{0αdA4 ?np2c , ]@{" QcLU0m:fڝr, gU&6 ?0aj|p%͍Z ^ӈ&)cSNㅼDTïW:b!Hy@|-SO/w @8wIx;!Z]oa ͧƦSȶh=3D[H|6W cNx cg&`L`4WwC=3yt4{D.u|Q~HP'na?1蚬߻H'Th{K8,MjqZ2," P hdE5MeMRTQ> U󈙈lxaԐ[7[ Q +)q2 t\m!5-Sd9Hc ñ"gY nGo5u7鼲i@˷ẋRO.A: ¼0[׺߅|5`;cj~ OGu`r{HuQ;o86rA: r}d>^|qܙ%ԧrme?!} `WSTmVh.vOن's+<6 E͟1:%>e6D"dA gs1dMHD& |Iq;-]eA^|窈76gJ:>(&{uSaCi^OEPNNĈat#T!SK7dʩed~#$ϲ)\_џႜ|`j= T\ ՚L`L.$)bBdhm)nVYTvz͙;x街 N'D? >˧wIܗFo|Wá?ui)^ZvD/mdH<<0 XhP=MS$ #PX|3GҰK+ⶦ˗OQ]3^Vן "`*+$cCphNe !ԞTmrKuG7قo3.!_BGBG1]9&9ecNtZ|oNBAH`Ȧ Ȟ擴h<s'DyO5SOyI,\=SV>:.hL @u<*dw󰋀ɔ#R 2(4f.CaNWͬ5#R_hhG6"̞­- EgPC3O5S}w闝^ebmܽu@4UC_~Ms FUo 1-&Ë@R5ӑX`LFy.rW~nޡ'0tSxR~JWyB?'UTC/P8]G Xc_/w\1oktB#*i>;Dw) ǚ?~=8h[pO2%̖)p 9 :)Nl:d9.Pl˜mV9#½H!śVH4ŬP[42lsv״?pƊ K报IIe^;媈>A + 9*>IQ+`Bygy5>DA7g퓍 ,{e9-BU7S?aqI$s%)[)J~H.~$0~jf&C3OV@GLlJρ g.(ǃ erB83 -S44g R)wG = D >|A|_cf%7ZN\B, 82fr/UR#&=~req9ѵ1>fijr#jȩoNj1[ވ!ιLגv MF` }],$1fdsIXվDn6LCΨRO1%6aojn๹/u  kHש\8BH<~#wԪE߳jH`~A;:poQzڿcy\ 6"TXh+(Plw1 ?i#;/5v'38̈1gNL%e.[AX04ʡ[JRӁU.4^y)DŽ*FZ^ǭ|4!$(űdT`œVH*h߯EfcC >M`H(ĹOV/C}<8&x j2rD5̠~9hi\[i5]BSg(&d4{ay gQYQz®/NrAn(wdXRƅ)ovXJ:f.ԻSC**UGiObk،h'*npw 7tG?fXj#5> \;><ټyQ>yfX'DH ;C{4 &OC Aq &O /+8SEF7RJ'(T3;a?:vHMwͣsC!WI +<_Gp3bL25K@*-E|OLE QTS<{c;Z Y烩ڣvOšoT}m(m059mw1\I8T2`h cDљ}8 -3:9Lvy.Xk6@J6 o_i6,)xYt& H:'v8t F qIeq]r`ʑcT~ٻ~S>pdw#<픦py0Lエr 4̔jpgOiyL^}HwѽI<%'Pkͺϸ6F.1Ӈ$nbIkv xvUÙ.3up"; Zi%gʃ.$q-/e`ruo{c.?g6S\Hن̔-ǗƋ`p.CC| " c_#@P°'8f fӪ1Ӥ:[f&S7ka 76BŴ0)_iYv?1@HK}ZBN,R%SlrADs>u p^ID <唇a t3Y*,J,HOoI=ŤI`J/xu\"$K|$͚&Xhl%ݿ=fAG9r@^{6 e qLgĸc `ʪ%x]<~a4"]-'ʲ~bP:hmEؼp 3EsLG 2vGbo-@-3)C zI&7qODZ44'knMDLϺo:Ku#2[[Z}0z*O҃4i gԢphcV"5ϻQ%|\#b ٞI,go2C8Tb& GvST ZMJҦ'}(-9T 'BLZYhoZx8skWq| L h=*\| @?1NcPO/n+LG4]||p3m>O&kZ_OC~@MPf鱬!WEt/QԉA '5Yܠ"Ғ)NN t6wr٤n¤ƨ@X,W;|:@+/ħ]t/[ e .5K{LÔU2bķ^LcJC{-V-֗ hFÆB*Sɞ7[$|Q3un^J՚^"[]85 :C '$H6- ~ڵSnE55jW[P)iAn%Ql\ʀjk\Vj|~p:XHiwN.kK}i w:bmR`@W\qU,%0j?UIyQf㕓o4Ų :c)i3v[,SS+Ca#y4zʌ%?SօJ,ɿi}ڴf9&d9yxM| 3o}:mF;g>ۙG 'ͥߛ[S:"\ij!v }KJ!NZKKDٱ=~/J|& f_ &Gy]g$d^zj* 58r 'cuCC[wT0|93xyknib0,@UłsB/~RC{]J}Q bJ"@̬6G0l`aQbiIl<+I |DY&ĺ&M5[2g-^Z>w~& '}dK}aj$q=4־7.4-k:`wq9y߻',+N Y=ܘ& T.wDG7.bjspQ$?ēw@pTJpY`?5_qg[l;Ѽ ~&t`@2% m+:<'$"4+D5"Ka0ssAa4K5YPtʒm%133|h5LWbH/)v.a;_0j1BX m̷%0Cw|4`M\T)" s-Ș@r2*%6PXH-.छfMACu@ۦߓK6|.b3[,fPaP֧0O=,NBjg7Mn= n`dQЌ4"\rpz ]ߦ"6_*`EP[3*X)G=&q ߖqYKa2 6p@_$@$b1qp!Afcd̟Bo/WZ~o{fx` DMO@{0)j-3p70Mw"^>/>NyCu6 D3`\0L rȟq!b|m^MpM`~lX{/c{+)c>zEӓe b|pЂO e^"{S2_H.e)Xy@htx_(=|XlM* b -8"!^흸7 #Ntt{W;xcSM R5ӖB} %0Kn !W)ReYḧ́mTZT}FH}xT6QyH])a"#jz7JgOksb޽}KCZ~3'=)2Mtb$7a?US]FE!n[lX!u}rJZ[bL!sY4˓ /W[mg}W@yVRJ럞-DP]4d?V4]UI'JO@^UfE`:J+[T“$Ŝ7{%4:$@!Y:ǽ Z;frIBe r~1-'O% tnQnms*wOQI$M:cw 4=ݗU'<>1sޒ'#ux&͐â|V{]͓f82 tpX?mԲj|@$LD6$tsf8S6sr/6 +,ljጢJGEGɈ|0UǬOi 0k0!-6> InH}$nϯ&6(^B>L&o)V;/-9%nâzԒz1r} ,c: ÖJvY .TbZ ׹<6OJ]XeAw(&'L;N!2!BG)+ nyѻ k<$PfP UqM0p#o"x ? J m}`I xaqП97K㰴J{0@uhROBaO vB-%:}I:UCB+M`Tİ ˛ j.=Su A#3bNPJK&> -Z :(FBو$ $񤏎fAMv2M$HfjdzmE&W m읐^R6ob?t]1{ʹS2%3*F>D^yWӏX'A?NjOΛJdfJhb=&HO| nPӎDLwp=y/}o)[0aLX c%ZcPaXP\"aĖaTM.JN{؏Fz_<#&%$#:PsބN|08'a0h8 UfbPP y]<7⥥:)֌+:uO-0[KqNo Na@U=I>R2Èʿzڸ M + VIKC{'l)=mZ:c5~ƆiD\H/[z>#X&ކB4- GBCho2w:eefDlaNYRMLG>ɇri1n Hpy3$gdP9Ew2 %)3C!<.@f`5?:wYUG}/oݪ))09(dhou8&3wI:Fp 2U dt*npA7+CJHr!,[BU&ӋyJ d*g*si85<=ƐJ)$>!pUNJޑ(S+?ܗS.RWub4?O,7AGryM ˝g&âhþdH bd0MJ RqI+K0,A$O3$y zܣS\o*4?* RlEČUG&1.cJL? &5p ~L<+ QK$mU$P]&I?"Im$@wҘL|j[HR&@3ASr9-&aÓJw<1Oτ ǛE@ 5n~ߓcCϺH .fGbu藛k}1(_e1*!쫧a AHŀ8O>qBCۣ/TAoBad(1B򉄥G.v)N➻Qk}H_z,{PDAZx6ɆqJ]B,.Ļfg:B/?r9M?c:HWwu|96Cz3CaĢٱIݱ8@o+ZFKZ"a7Yl-ֲ-F峌'L_0}aˁsJUL<ȇǚ Ч)wیe9sIp? **5O²'hWB#NF:"ʃ(l :$:704pdϱd4YݢT.z/ZHOX7  G6‰gҭ:k}ڛ+3e̋(vH"I8k!n.\ݢHv~~ #x $^lx>>WE"BgeDNtY(lWu6EN}Qƹ7<8#Iˮ1E/g$FW$')v-~H.'}}MPx㊸:bX aQʓ6 OU3==9Y9[WݴҘɇ/Ow~Tz~p/.o}jF[塬KvL6IOCc^|51X#YxwĺiNql/ڧ|evCx:Vk^~ sэXm0,9ǔ'Kf4`m1ZítpcBI|LS?>;_P`\RAi1P %9m%P ?U7]&Tie*=MBxӝoN:/NvV A7˼d;}:ɑp<wj Nx˂`.w= p<=utGSX1($7RwP p"N QRi/hD9'g-~G2NB2,4Ʉ^OIa/- %R˵l[yptʁ?h72*! ?:&Sł( 0"2Nj˧L[?2pR7"Jt0s &BM0J? 0} (5$t*J!Z|*Ђ|*08dͦɄF? pn|lL&2nE+Zbf<9Q0ߜws~ ^x36w*ձҝ{#\lDdK*}c4rTscJRݭR;k ?F)!2_Xu>3g1f{XL'atN0XηUc&ڱz+-cE%xx;4"w~ GBAn|vLh9ܦEN%W_ 3N9A#1?hL㩴e;M>mTk/'gi1OBxPyp+ , S*G!ۋm$)k:G)EPBq&ѡWz?J `p(IO{I~d/7er,29屫bMO@}}C?tE2i2Ό |%# F\Kt!\>DzE = jWɄ2a-JX &@UdD{MZ|ZxS{ c.u,&sN.pGS`IH;d~ SMzH{ǘ9&&:b#p"!/[d G1UEo ?CtyH$pCIyy&\+L, gE`RO-o/!\㓝&@yMZГ@X1OB*aCc<]N\Lq?!xHh:!]*ǔ5f6= ږ/}mc't&B!oIXԒՆ$}t)MQpRjCsy A |.Y B\"OBӛ!C\D͝8p00=%LwM;]݇UpyŇ/ AX̧Ah9soA~*޿& IȌms\z*UP wO`;pZOS4M{`,ᄒ_R 1X;PzC$z ܄&^͘@ 20 z@Ԕs"gTHMI>6i와M `oT] Ciz0{C%oP':U_&7gd Ъ<6}mC5҈ i߽|6 P(@'A];Ne3K2P,!%iޢ -ww#dH1nw@8\p|40$ׅMr) t+xEK ϘN+`xLhnH$m6>3&Ȉ1$d_IJXoyj<%O (tvwk-?OuxQqaI BlqL"/ƣ}bZ{x zhtmx Ihw_˃O#ͧ?p0̨Ow|S*.6_#]yL1%M bBimwՁb$0WfɈB5EpNyjM;{ZTtC{vzQb ؾ#FR̘Obw$Mi嚭#nn` &nK4hЂ򟊫1MH8K#|D޽2<O$`U-{FkDp MF, w$6VGyW- uݽv<-8Hp,Iɴ9"3nv4ӭŃw`8b˟j)Q(ôޤ!u'b8 )4ܲN)z W#Ix! 6nfA9Յ'mBb4l\h Lte<,,WO>ծ-RMn4 eaјc!f-Zɒ1dD,xR͑aOI'nL Ϡ䥢^d!vRuf>?9}~r6 Ow3g}~ <]1XjŊDњST_zsI6I20D%!;?,Rp(fDZu<8#72% ʁx]$W񃦇AgvO{+ `K% :Z3tD@s MȐ;-*XV^i8aOP;$c^riݘr)N摼j 4"Pm|O]NMNy"n)oq̋*ܱp?p9+ ӥX"efOB M\HywDϻ0B$e*Wy)0(B"yA4Tav1jd9'$d:q5$$ֻ5/5$,һ.J N.^:(kr`W{0,%4<7r5tٖܿ?Kctʉ@\yT`grj)fɉ --1{yKP&zW$ഩTo}=ٳA Gǀ!2Œsz5\aB[030x]`2q B$e9J L?arugrdvf0SPb]a|> x)/o{3 yJu-0u`f" 8!AvL݆a j~d*w#E]kɅNc8_33hҩ S_BN?N# gĊ,c9ũH9z}=ᦐYu9no.DBo JgYAc^3cX-l^}wuO"5;xZz0 \7:3<S~Q@ =04@0dU-0VI@hzi&tt//!eSe¸* Vi $t eoDŽձ͟11 (b–b*"YaH~k[@(ǟ$CWăgK^OgϸQ,fmsm/data/cav.txt.gz0000644000176000001440000010425212061401532013736 0ustar ripleyusersۮ5Ͳt1 :W]Z\`1FB7=]쬈9߲֧UY/O?/>O??o__o'|ɣ;o'DyR niX o  .6O|G [{]]g>&?[ n "O/\w['s's|_x<}?~X1 _OџmFh}KCPx4ot_z?55=y2d|! }/dEπ'1=^ *||'mV[)E⓶u>0W0LW遟M9T׃OocϿ ȢO~j+\d#I>oFct ۞uO7xrëwYY۳_cejϿ7<xSxVR]5+|޺>cu䂟'烽;o͊~맆i$Z*o=6>-&U}unX=xWxz-IңrCᝮ^:=LxxٜoZ6ax#ڞ> ל27;ؤsֿn%':O O?:^DXZ껆^Vgk7x'/o{r]_? Ÿj׃Bsú#ֹnrtoq~s˰;iyVg@/jYљ6g~ˬ>:V'wskMY{ev7#j&𭇌|  · "662zп ֳ"XiQqD5lIEǀg# < l(yO|Snq^㛃n7k]F  }  \ :nv^_1`"O@'@ x6DY3 L?(@_NmQzW \to>WÉϊH`&OS+m Lgcz$v~ѳ8<{7EC'+=P|':Ӯŋl?lN7|$\ yIFrI)>  OH H.(`:H/>t$P|W|ۀ:$DCEZ0e,\-E8&X}I[j`3Pǀ6C=SP̓}C3eM~<"[{w~QO /$\ RށR{qTJW|9Z|qVhoDv&EៀpLR<mYD&)'ŧOur~䱭|ZW;1?4:_R'~aG:Gr_7N$Z>;<-&gEӟ GW{QZјg/=Eݟ̀g"*ًpwptSx&R3?+ǁp'(lp/bďb=qŧ/lf"O|xoI0g8Y+³ Ɠ9=|Q@HovjoqPVK=q)x^moz=Ǻ L٨8ù+_ZSVY{ ZEg~4 8)- g'Er3KXVf]yt,fN\h(N\s%.TuL_H+2Oތ`ϊo\L_ _şWŏO 97:aÚZ <|_.v@‹}I8`[p@^u_rO.>(>c). >){Θr 6Yܴ=DQD> U=R/|X=s?| ܞ# oB"K`qII L0 /:rF2f DxVx|Vc>HwEV J(` aڳ:zx7S뭭2PBjs|/x@yI(`2NP_yH,?Pͫv-+><;)=:WG )Wg &No/V0Cm;5ݚ+a6J` 6̓wW\ꯩVbe*oWp soj%60S]#L du$(,滀JzH!Y6IX t/toguŦj17_\b7{=6;< 㤏m(^b\ si|Yz/׋WN_W,. Fvj=b{tn$bPV; ,wQbŒ-KJ`P=Q sI,azV t:&`t M0TPԗq|1:MKpANbe%5V<1b蜄$6PNhj\$R  0sGʇz^ ޾Y =|V|$WP$YҎc{^IOPb+~$gʽ~g[*i$Q' 0`](R`\_h1Q^PS|'yɨ-+~^b oyAů&wN?z+6oX=; H)j]jA@uzIܦø?7+&P07qrمO@k,۴KD2EL3V,~]]4o)?|vPl`YI+#@oTRX$iI'ʿ6YB>̄E?Ȗc'(SM.OxPI.eX;_c 74sŗ/;Eկ3ƼC9#7~uwc <|Rq ֋Ər"O|z+r<|P<7_0ΚP?_$uO^^Di`X=~}5V4]oQxlp𶛼7`O~7yIt} >Eȟ=e̚UȺ_1Kqd$2~]q/4/UN'냏繠MO<ǜ(i%4:*@KPC _{K^isGЕ iC "އIqDܟ΃3G[0\?u~HMO•P:"a(opQfoj+vx ??][V@z$g}P[Uv(|60-^Op6VW~'>YUmQ6f|R|%`VTHpS(~֖߶2d $OA50| E7~[Hm*dHmv%njWeSēDo+Z6HmG` .h q#-||DMOF&Ë'sCM"؂$'yU߳oyMS_컂1mxWxP|fyn^>guX0L>*~[5VxRxYqXے "nF6$߲죉,r[|xS<5P#xWx"3Zn_߇A܈жsWS<X:-CIj^DoeKÔKjdif2/|{}o^\$Vkf#{-X@[e X7%[NwYxEo sCl$im.SʝEoN!ub^R|#8L95K(BIb*oD:oo^H%HV@tCFv$hD۪u &1T]'K ɸ&q )K lR;0{Y3t*ZGyFEt@o:; jwӁwjL8Ł>Ae7--^}cm@cd,Qi3~l,aa3ȿؒG}pZdfwM×R-ooM?Km<% Wr-f:bEnoog=?1u%K||%ްO4⠛ϊt1B/OE@>EJ EBrW#8@_;?L媇/> V@.^}kV A)>~?π෹H|M~վd av&ЪO;67 V}@;o2f/_ch`^XǨ>*ц3'* \Z&xZqMYDU{b_"U+-i#]4juC ÁK,/ S ꩈ:/[BlizZ"դ8kߵH /I1*9YLៃ4?42"_c?~Ǎ/~Vb /v zMy< $4͊&ގ%qEIs:y9=͞wkE8Yh}7H^D?%a-!~߰h}"ə&ɩ? Q:)aOy|?X1X1d,A/o@1sP45EM~)]y?O[,8_zWϦчY1n6/δm^珥n`+[xa=4P>r΅{9VSېC|1_|g]|P|pG7: JiIR2YѻP@0.1 K6T6?q^* s>*Rat<)Q,dYszʉrF̲%s3*Xp)`+hoR|?-n'xA'g'N,]|Q|>6فW(0J7~`Um 6/_@A<_4N^4WSp 7$7~-(>)?GŗOR^?)R5|78>+ CC~MmaRr*V*}^Mς`by7ƍ >C  'QG4St'xR8 ЏEYzV|v3;ශu15<^lU ޛ⋩-Ox8 oqœ@?X={!y1%" Vp,xϊ/Ԛ5WOa;FF3P R?q F VC7G_ca³z09 (<{3[_9Ya>O? v/Ń>?S&*D:)n| o\?)*>x;!6AD `~}+EfdF;pUmx9קX|*~&On~_I--5&)py75%GJД~oV<&v<|Q|6CHQxxUx1u{N=(zNgƟ%{D!*:U|,*8xz5~p5iw6R[o~Ym%_U# >$̣n;| ٻ3,|SMsoςpۋQ *~X;o/|&%yA+Foyb^;;+T'ӿ#T'qE||6ۄ+ŋ)PM.ϊO'EEPզ_o<& )[؊UϳCSu ['JgV0>!"pT,n+?SB@+݋hqK~_r/2Ǖׂ-%4_U *Hq`n3"LS?E1P?FW/cqKn{? fٙa7|^Qc&L|uTFy7~? c^I``)/5"Ǖ̄K/ q 0a=|U|0To|%i*L6Soxcoi (-hMf ހ'6ıOxU´Z<|{+Q>7بCP|$?*/}:.}(>(pg9.ܲ=ިN4q&B~Z:"VNM{sE?*`_5]kP|:+ڿ%?%;c^VV.^mS{v(ئPE~oV\Yn-ϔg'[tTMr_pMF5~o,H\Ip#t+-/DɟNG<]?c3q??3wY7~ֱsΚ!WGM,D3#P.yuجX\xWy玅p9O>(~v,ݜ|T%PV9:xPx/`ª(Шck4}Y //~fY+sƚTl; ;H>PyX0+ K`8*%cO=E~2c<|R|76qYacv ̬[|zx8q󆋅A EM8hoyu[d6xl2.IqA\Y̱G'ȵ=a|R|#)_dD4Xc&E/Aœ)8Wx_{^xSz]fGxDaD-^=Ϝv\Ë'_Ǽ|"Ox L%|\u3ϊD9o+(` u5G:>Fw'>+ϔ`25Xi]AݿK_R?%[zyynPS]"y]xYPD+mM_?H6<|{+v '8`S(G?-= ^N~o*?SQtQrj3!c{m̍ 7GIT\u"ϩl O=[X%u@.iL#+(u)iYE)>ȘC?~W@ ]f:xjo%b⹧`|W|fuӶ7=9h\ c:p8Sk`b;'fx'DVĠCO5U}YG|9hWf~~v?=&x~}|{"%F. ~[>< QJLI?gP y |>)~P3ׯK78^E|P|ʮjj|T 5tŧg靫7^mmqF腉Vl x*9oo4r+=1NQ]gN^ZR(m`;ۊaMt0={8C44X2ϊTnG=|Q|49j7>m|U<` J'Hvp11+]I="ꊻ'~[vHF>(~]y<*<~a^~09Dϟe.z[ GE3EʎsU-=|{ThH՚ 7>ڞzkW+3އ(}Mb=DQWr A;wGtY(eR=|UӘCyT;D_Uu,OInx(c^[#'9|㙇 /&q:yG>*>Pv{Iؙ3C4v4tG]zEZ AblJ=@o /T)^Y] oT`j;?2~Uc˶H2D/ѿ7 .X{~%&h؁]>+ GEL헇/~k5)>PwG*<³&_X}d?>Q|V ` 2'Q?M!Z?=޳4f=xUxxz3+/ֶ;j#Q*Z!~S!~=ɦʔ :ZceCh'˼ oz{+_??'4Z-JXs%g㤣;MO5~(~FԅH.rSy=|w& EꟙWfxC ($FnCbT 2aߗ2ѱn_H{)Mt]Yb:sɡYԗo[*AROy@pgE7GtX}yl5 ӈfEecYJp,%y;[ԗ`ߘM)A؅d+(Q·`(]H \Bn|xj`=8*W%DQaSv?HOMpK9Ҍ|XhcՔ|ٺ&p`~`fs pw#q%hJ).AWDkfކ|r?R#pŋYf֟q/DTDT [fߞεK%J|+N* 4&Lx%"k)A %J(a ,C쁿qǞU뒢5z $ZJ#HJPhWZP|| x/m|}.^ n;>]q?OD5DTI?k/W= Q'hP?%Ff UJ彝@"h+4%@}f@ ?ZLoW'QjM.{C ;$X_%J1@eMMb<ͤ*yY }-o{]N ̕M > o_j[`A mbϪ%ɔI S; w VmgDQT{@5ۦ!JP@_4%uJV7<rvj=|*~Ќn/%SXãޛ.(")Y1E4Sw'Y 5=<3⴯xU .&N4%D`Zֻ] eovc ^* QohD{#(L/Dž *AݼR+nSJld%ԗ~5Ay j/5ϴvrt4h{MqaSR] mIXSKa M-"|p7.N7|T<ݬPARfnK{@?pb Q,!bU|B4%wﱥ /~ʝW=,|'\|P<'+ŶVc-ELs,JS%`0+DV,n>AR}nռh +㟃~~6*bQ2~ 6X>QG@'bSĠ:rE_Y=p!t @4 8J0л Q76uQa`R<;7$W{MMؓчT^Dq"ؗJ!ʹ(#JI+f(G0^H\cD@ Sbwm\k?#Xe9?Y)$%Ha]$RC[=1M_rUD%Dt U>#o] K0^Ǥzz+D Jo#S,Ԫ>kN$4RިyY :)ls(.E7vM[7Ꮹt{zR(AMaA w'a AP~KFNr D*F Ά+Qr fHxY 2R˄0&-Q ջQ>MpR&AA{r-""#5"fCH(^{mX xA f5z.ڮki%$)Q=11feĩF4e(0ўǼ$TW+ALeh>*TS hd`נL=AoEưћ{H ;gI5ivnA*p@1۸){$8P 1K| 2V#kJ5MLqkT,֖rŮnNk6/~`ϰL!@\(.~k.APHL(T XX"&8*8ٯ` *Rѹ9%m c Xl|! Vy<(U#KC@; A P~kbG0 \Hp /.4K#J> l dSH%+޼` R?ĄKVX?bZn\ۻy$p0*η" ^Xt  zEH ;5vH+N/44X6J`'.YX)dJՉ`_2+A'{x^ËtT%xF)A|ҪjzsEtjbbD.)pI? Djޫ(IুH 6v=5H%0;6)J(` "0M\/岛U.AS`J9#JQ˖K0 f1B7HAURp8xG{@^UMgQhMEByEց{I pƋ=K :C@^u~^\_8.AShy-$J2 `(Aф=`I㞵,F u(s[%( I:pgw:wygmVDž\qK$$שWSۍǭxyGbfs#;: D1--]L'wOaD%xNv#HJ@ݴbve4;AEX#8ڸ:3IӏIx 3\,&ۻ~.Ww@.vʦ3 b_ ŋ6;OЁ}W{ɤ50e 䗠&h ǥ]+1Iѩ*m&%VVJ1$ c?kjZi'w#@^2V2|P|ǔM.gŸV.(.iڐ>s@L($ؗJ0 f Ay d A g$Wrǻ?ws OU5ԤE8>5 LDk>5LA%{u%0PvwxCϊz3?u(c4 KP*L/{by ҭ$^S %*$NPV;tV)HX~ D%Td,x+~pbjkS| J(q&=:%բgI@Y'An[' 5 3運C O MT)K #fkZ>%qZሧY K01Pܭ$ ‚˛3Α8#[0(6w3IP`U%ӖLBo]S  KЕalhɹ4)KH,J;)1ak'ܣ(ҹbT|hU5n6sr\Vg((luͤ\p0G4Ed {m Y%(PankhG h DaNHƁh J1qH$  azO1x,KPKbLs*=j<:L8#yvm!Q0@ݙ7Bd,*0!'l"{ M#pNMAVPXGP >p'q tҢB0 ȇ@,mu!T,Auz3Ǝ%K0ӡ޼7@"?YQ@Bur/o]:)#HJPi8ЀG WVX[%DPЛVNW$reocᔬe fU]4 ~  gW%bP^@]tbvk&ek%BPW~\3%?K` g/%(Ji3%*AK$A{ fVh0 䭋>#~|!O۲&%Q=Y"= L0%25LF?Ȩ.A pgi?3IĠ.sW!%DP| n ~^]өTcAWöv K0.'srYXwi7; '`pg a"_wA]vgzNv>GP`/>BS(#8v֦p\ku,!xM?PF"6}X$4""u (T%/\IP_tEV "&!1 ;ޛ.%7(]IL,L&ݔ`Pٯ`ށ|`(A Q@ !z_y"hHxvAT>W.ޚed57O|َD ۂګ E|/[^OӷH)R a6(RDVY"~H(5JW(Rd ~W])/v{jdj\Guf$)k?h',`Λl 5{bt s/!qd"wP_\7`gyx1uPc{_\(RBnE0 I -="|2.>(.Mv[{/"> )Շf!j{Elu.1"n, @Ylev+F5K Z%=w%fVxC 8b]?Y" 3o$!!=ߖ6!XYBmA5 >ئD6 wql%W|*LLC$s|/]>䞏=~O-4բ 4Áz_$[TAE" }5 hxuEBkQƉ*j!_*fK0j<;@,mO !?\"AFLb֐"AIl$ ?t%YZJ,"~Dtl{0[|1S&I`T-3V {ɤBmB8?h_[$T%h8$\u[<KJ5A4%_ӔXX)hLY$J08ǑW+ Lc4*flI(WL&K=m ]H+HPÚaj<T~&ޕx ?9sSI,".82$D0 C$%Qy *A&FvI\L +A [ S!hsGPormTQcX e[Z$^0V{`8gL.2b=@L 4fcy,/.3׆ frmq +AmDex1՘=w\r({R Ȥڱ^Ey4"U$~0]pv]s$~0.i<#JPIĭ&m9ݔ hFcÊx0+uc3%(JI@<]>^ Afi;z] <ǭE7YR$`7B")7 LN-ڲ +ȋDƚƂfK^YDSpCT6L;oSn"qdN`Mp޴D 6cjaS!HFG88%?Y(Xf85E.APAz*g%K`ʹd ?pUmkiϡnךrQ!}iDۄ0@6 G beҼjܧ8$Ȕ!fwY^>eV> 33 0%%Ja4iOA& xwwgҔ_ĚE (>. #J#hJPH7 \Tf(x Vd́ g7byeJk;򩌠Hu*{Q DL<(HpV!VW|r,ed cg}2!mP9HO;eh<9ijG~`0|ܟy'J>?/ #^(W,nM`q7("T#^2ߨr3]|R<eKи1ٔ,@9|9ƌ$gl`=ႅ{nJP)fi]@^tWFͲ`(AGŶsn &edef!I'ZI.MDݫ'Z0 0o1NNN +W E=_[ U E桜NWlbin9=}x kfNwC[/<xScPKE7' u;քL_Qh2Q׋ \ٷr)*Ap@M~sǶDzbiOJ Tc'BҺA 9tdr*.AR զk.).\2mzb Q> ` @TzbI4%&RGЕSV3 : q y$wSw9(.~7YX:O3w""H=g%@xAju: ʯM0npd塋Օ%őcC:|<F%x} f8)~lwH64!J>K%n$^nH jTdEdhT"ؗ,JPOo6MpsC;ٜѯ4Tji+W4\ kXCP/A l3^?F%(̓G )AK CnR=񂅘{ O*AxoX5g)Oz=|HHp. Nt錸pWLk 8])vITUi 甀OyNQ$(f+tkk;HK8Ǟ8Y\KK |uj@ 5wLj E0 tV {U"iea+/\G֦T"{2[~ Q9w zd\%Ut^ s-5yb}+/Mf?xF3T ؃~@4/#JZx%hJLЕR7J/pV*L!ڊNML \NZY *fҒK^y*&yљO$\v?C,1lLʅ64%HXT:T:3S* w::/: 6 NvSpA^ ݅Q 4 ]vu rru]I Xluh%xmSyd(G3|,m)J&jQ4xn] XMf% ۧS8}j0ȫ^tAbݳ *8MfĸA^Uv.JЩ͊i:T%NG`S?NF𬢆vB}Hvv"'\i/b<.I ^R$Rx hrwNaE u)5M4<˿EP]z%Sed%49π'A_VߵO$4wdIEDn-cyU `K3وDïkWes#O~[C LOn]j9d(v'CK1 Dʻk@lqEo;@y0v5lt\1hZ?$kCzTWdӇ %( iNm٦wtܯh_g7Cc^s̿{ޙ-Q.u =Vu ߣbmtv L?nWV%}]cj}Ms"gBBa:ig8BI "o0o%Jil/K"Oģ/~_);0ó]Sx2 %ֱC"hHi~_+RB&Rd(N՟:(ARF7g!V3Xe#(/A&v4@ *J$~n_j ~`߷J05њ(} d{x"g k~vZ}x; (}t?pK /]4svCH}DILg<(19v W>8?i@C B?nEϮ26"WHisnF-t!YN0(A fUd쑙|~G gbjiaF+jzQ v5QGQd#]bc-sPŋ&)ˮ%0ݤ164-μv$"0 esT[zK 6N/XǸ%>IbdV;ab%(JUtf`KP_Ճ8ႋS[@=靖]Bc}e[v FK[ؗ@bc' Qa1wxkϐmq/-Dn NYvX]cƶH` #/Ƞ@Iո޵;՗gS LMm} R6) Hbnԉ]#_l:]yk'u`e bn+Q9`O#'E4j$n[\2+A7S9`~\`P4Ϧ?{%v+tsFc[똫Qiޫ9W^Յ%_/~d$+?%1:[wE,͔ ~7eKVJ<Λ@(A&]x}ᳪ@o#hJU&.+< @켈ѭP`;9Σ~ho9zT`: *+ukVD(o0zɢ:z؄LZSo %h7N-g^15] "eUq?ٝ^I,Ã.HC£KF% &#H/AWSpCd]}4@ m/=DOkOQL?9/)A`q6<|W|nǜHțW"p\R >4$hFuo !:@l'K[({;DQDdV['ht‡KZ9H #ދ +4=W( @C ө3AE$)L'd *HQ"\TS (>r, ,%v2M ꋘ%>yL%Cq]S!ad>wO4EӶ+^1f*%HrI786]ՀaOAuN%8 yxY)f,^tr%"V?Nl_dQįe8'' X˪cpfdK d""u?> ?5:6ytr\6lLD{3]ir;=CRWNHXk}}r]G ~Y y%c~ Y+F%xWNz:2@p>CutSh ΛM"?9?lm_Ίj7!1:-[qXDï+DixK`Oã4,A 7{%H4ݎ0]+cju Y)_Hs{Y/+&4sV-gœ1"},_~_+~PA{j %(RO 8YD:@x\2/RhuLarMC )3ԽxΆlc'"Yi"V)nġJ٤W<%y] x,oް hmM(tN.ۚ*P¿,~K{L餔YKk+%kDoy.ٷrOH*OĴf{{0DUD /s~TgSqGЕ9i%/A^ ϰk""L8%AD M]Eږm }[ !Q@vqJKZĸDo0z%3o܀ڮ䦽M 'd~_+~<$G]r UK$j;_u<RZs3߾;*^1* RV-d*0Gp,K.N(y E!s!%fp/{{mDWDd 2Eyƅr, u wDM2tZDaK ?_* j%|;cZM" jStΰSՅw2 8}k mۊ>mt}"GlBY2U"*R+ȭ.dRN%6&8JYTHҗ|㛼*:T2ϊ>g,2E?*ܔRL2 aǠ)DF݅M]"X~.} ox@|MM"<\;5/sv~*e T\Ͷcc[a gvhf#Ow&WpG0 Qϓ KJ0{ݛi~$ADEpvnTt`l68e D'ᨄb\Q>_HДRRhŋM12mPDubr 4y5VZ xzA*cE"-fg?yvY1es9f?:BDd>R>۸#I+ %/;k!ԕHy=%xӻ*ֵG%xjPD5#(;0;G*ֵC t t$X"YQ<\Kj~ fk[6e#.^lk%,3Z_LҜ/׹M "9KЕq+y.^Lk@WExU]т$jKYP/ch.mL.9/A岫 @̩58ADENd}ّDdOk1ɊQ$yN#6mLloY=7K 4P+ _DKVt%k7wO2O^.S*hY9(CŬ /:Y`qHM)|hr\y#| vk»0*(% P(U|cB+MZ$|?;amxNJ"m~O1=/ ZMBJIJp겓y$7?f)xWwO\/@LkyxEfjN϶S<$ Yw3JiS͂NO:@/9^Y]}HhywT:{炸sBY&zsJTLtcI$+PJ!)Ǥ8H@r$y *Ŭ^AUӀhI4l+y%ƥ+ L& $3V'gIa'&QMv`_2*Aʹq IJ.pS$Qһ4 $}EZ}KP]D=@ږn haXnv]hD1/Sްmל,"DWH> VEhƦ>b[Ka\I"OĠ\^|lk-Hg`CtH_&|9.XnA[S#D6/+AӞΖy%Q N R=:#8Uvd&DmUO"Ot *A[]e[ 7dpID*`_֮ǜm9c_`_)Ay7젢Zi@.yE.O609*' Έu W ArMkc1dڎHuWeQψsHu屜AH"ODK&䖫 6g/4iw ?A1O<BH)F4bQHm ?"Bgj/]Kh0GpL-?={,y-ib!6;$y[~6`ɟ=D5uƙ۾(2DT lJ;|4zL5%J0i!|FsvANk4i}!.lxb\e-"qN,y_|;,@nMpaQwmp!PޖqHrׇ̅߰y.xs Ĵ֜ k+`'w-65I4]s>BliMpn$"y[PMmAV`w^JǖR1(sD1?\P/]"Mq1ɤ'ȚD3Bgh(c>e]M}ɺh RM "RLvV{?޲ьC9Xe7}ܑg?}/ƴn7o"xkE;ߕ_Z`H/יb-|,bCхOEɠE3ma{Z0g`*_f7E y"դ)Nw,*D44!ˢ \.]|䤜gQnL%f ZAGd8_c#dQ7OK_U[Qgf W΢?u "OD 7Ǻj{|Aɘcd2+9% v^LSc+V/^CGDؒHcI"8L)sG XsO wRz"O@Ú?;bkYQ'~P'a!xUDϢ7`:"#ǮubUFZ28,yGdx %K0S]8#?.6&:5HJ>ryE@$|&y#ATj X@pɣJmd M>jBph8=dQ'Lcf|8zizE x1dscVUD6hd %KPA=gʧS}OsZyFy\"-UvumgQ~Z;D}?.w .M vacEIX\ƍ1QoԮ$hBHELW6 y$\$jyKpLjy[ y:p+=unpM#)\vI6N|sV]qNGؐ8WX2]|d'82y Nt#A]lHp^l[69pn[V) 5cI5V^iܯ:+VY vZO@mWJ{]2=]N2w_d1pOkGV3Q5ܣ"^)vNmO/|1'a%ۚ}M+H;AED>SĖv\l)b =%`ǖNA_~G~1G sF[#EH ѱm3nb0a>Rd_ $7 rINsnG^!Ɩqn+ J7s]c_qŨSD(Uz<ļt\S1O4#Pq}87(A   Z9CXVIZEG{GTbLꃥ،UE7܍.%9|ŘD/v# 0 19PD'2#M>} f?~# >Ytt7a|Q<֔VoHagV9DuR0 /rt/m6>R:( Q,_(ᇀ].c~Giѹ>Y)׽=t$ g5]0psIng^Y f{9hW@,h)&0bLJ/bHK^zɦS 8|s{ ~GgoC'{;9FĄV[=^Ĝ 0%fVZ. N>CIEɟX\R,hPH,NBE͜YܘuQ뙭y4*ڣN9v{]ҙWDk1-JR7(y•򸹩Gp'/FEwKX9ܣVsѯPx-*_`VӲ)l kΉ<ńv-BM؎B :2<498@7YD>iTgOE *=Hc5;=t;@dT@CEYJ'FէG w\-87zI1u^py>({z$&w- ""#5HmIthAY) A<ǘ<2?gI0N"f:W؍*tHQ$ fVeMUT6^9v%&/;N$@/:ݗcLb<"auǝbƫ}ۿCgw*tƀ=4f#+VA"O} ec9A*t >g'$^EovXLigc0UEքn&ZU=j)dWE: 0I1O ΝŞb: Er@4JkZ'Md63$)=5ѕ7'v~"" y{3U"ƥK۫ohm*Ķ)W(rS߉^ruہ|g\LeVV,c/๊VQw/q߶1QwStFnyb=cp"=(66䢈)NKn.jwib=ybti0M=.nc14(;ڰWQ$DK= <W:jる|G2b_L_~t6|*bO&QlM 5Nt>:;t\fTV$jͰ|<žx?[Oe4Q:EgʜrM5яʃ›1;l_&Dqr&ALcIVFi!}|i+v*:UCc`չhc5h;WMD㱺Bⱌ5n%&H1l5'G|I ?SLhUpXٹlKḵ{$ÁV요q:: ќ#(:tݶ+$=B~1;4 ҏ }߂ rcZeRP1ۏ-Pb%XY]WWwKC ]Snُ*:0ُ}X A(njl)܏- ا rcEc7^tQzh< L msm/data/bos.txt.gz0000644000176000001440000000743212061401532013752 0ustar ripleyusersUM-)繊T. c5VKzmM$Bp?ٿן~~7M_?=/u}c~N:g׏$!Z׏ӿg?_IUZ~,ēn|; ~ӰuCV}n#k5GN?+u؉HXOyM1>Cϊ8I?Q쒸0vMûH,=G =Ԣgc,N|[^hq/yMM?BE5A H,LDm&ym >%X,cOј5ߟ%ܱw:CF=6<^X"ɅW}!(&@J3 s="xN/+-s+9R6A5W!! &8y*8g 48u: M+ ̂3Fz;Y/KJp `zr` ϻ0vyX@g0`͹L4 y_0`I~5! D5bNgpm0`l&-?x-Zc; 5C #܃,sGp~#}(6b C| G D20[WpKd(X Jp!iFMPVwJ&waΏMLA3O=a#k%7a|bnb*ٔ`hp z:ƭ G10 z\0mrP0`Y0kI6 3a|{0A Τr=fZTuknC +|DxV¸me~G0Fӡ +Μp&_- Qā0 -gZe^27B.  0lg=,.BtM]5̃q0ClD >=a0.rk0-riUp2 F/YpNHSJM |.ي?4N:\` X3fr&D9lNb#:a# ̳rFH FW.H3xZ LŲ$ڊ*1R} `R0Q թHlOlsWG`PXq^VCvR?x٪n +\jXz10f ,䠀&(e!2ppWkB٪z L&<^ ڕBvzJ;S;`;%p-vhwN`z0]!>O`w(S 8`XjʔLP9` 'zfC vD3=N Z[;V|KO`kVU0% ZΝ@ &AfޞW@VlC7-H/ЄMjO@iQ99pX~EUײzp0Eu&=۸Ca6X=dV=DGR z+Gc&e"g,HѱziIgK5I-kɞ7SR=WÚ\O@ ?9oDu#a)'U (bi0*\@7 +0ϑ c}1' FkQ8= }`ga Fv; ),? ;pa;`?FvliM:}%0pO<#yÀ3j̳Ϗ,z> 8Cɰ+ZuchVmp[ ] n |K~Ĺ-x3 {w50}? hnp{3WU`thGF<^gpOй !C ~岐?x$譊C