R/simQOutput.R

#Contains the functions associated with class SimQOutput for the 
#from data part of the project. See class definition below

##' A class containing the expected (and CI) dates for a specific item of interest
##'
##' For example subject recruitment, events occurring, or subject dropout. 
##' Each item of interest will have its own SimQOutput object. This class will
##' be created for the user and does not need to be manually created
##' 
##' As an example median[1] is the expected date of the first specific item of interest
##' whereas upper[1] is the upper CI of the first specific item of interest.
##' @slot median A vector of the expected (i.e median) dates 
##' of the first, second, ..., item of interest
##' The length of the vector is the total number of this type of item. 
##' @slot upper A vector of the expected dates for the upper CI 
##' of the first, second, ..., item of interest
##' @slot lower A vector of the expected dates for the lower CI
##'  of the first, second, ..., item of interest
##' @seealso \code{\link{simulate,EventModel,missing,missing-method}} \code{\link{FromDataResults-class}}
##' @export
setClass("SimQOutput", 
         slots=list(
           upper="Date",
           median="Date",
           lower="Date"
         )
)

# Constructor for \code{SimQOutput} object
# 
# See class description for further details
# @param upper A vector of the upper CI dates
# @param median A vector for the median dates
# @param lower A vector for the lower CI dates 
# @return A \code{SimQOutput} object
SimQOutput <- function(upper,median,lower){
  
  if(length(upper)!= length(median) || length(median) != length(lower)){
    stop("Invalid arguments when creating SimQOutput object")
  }
  
  
  new("SimQOutput",upper=upper,median=median,lower=lower)
  
}


# Create a SimQOutput object from a matrix of (numeric) Dates
# @param details An unsorted matrix with 1 column per subject
# and one row per simulation of numeric Dates
# @param limit limit and 1 - limit will be used as the quantile
# values to be calculated for the lower and upper slot returned SimQOutput object
# @param Nsim The number of rows in \code{details}
# @param event.type An unsorted matrix with 1 column per subject
# and one row per simulation of event.types (integers)
# @param non.inf.event.type Only dates in the details matrix which have event.type=
# non.inf.event.type will be taken into account for the SimQOutput object all others
# will be ignored
# @return A SimQOutput object with the median and quantiles derived from 
# the details matrix
SimQOutputFromMatrix <- function(details,limit,Nsim,event.type=NULL,non.inf.event.type=NULL){
  
  if(!is.null(event.type)){
    details[event.type!=non.inf.event.type] <- as.Date(Inf,origin="1970-01-01")
  }
  
  times <- apply(details,1,sort)
  if(class(times)=="numeric") times <- matrix(times,ncol=Nsim)
  times <- apply(times, 1, stats::quantile, prob=c(limit, 0.5, 1-limit))
  
  ans <- lapply(1:3,function(x){as.Date(times[x,],origin="1970-01-01")})
  
  w <- which(!(ans[[3]]==ans[[2]]& ans[[2]]==ans[[1]] & ans[[1]]==WithdrawnEventDate()))
  
  SimQOutput(
    upper = ans[[3]][w],
    median= ans[[2]][w], 
    lower = ans[[1]][w] 
  )
}



##' @name show
##' @rdname show-methods
##' @aliases show,SimQOutput-method
##' @export
setMethod("show",
          "SimQOutput",
function(object) {
  cat("Lower CI:\n")
  cat(str(object@lower))
  cat("\nMedian:\n")
  cat(str(object@median))
  cat("\nUpper CI:\n")
  cat(str(object@upper))
  cat("\n")
})


# Output the expected time a given number of events occur
# @param event.pred A vector of target event levels
# @param simQ A SimQOutput object (i.e. eventQuantiles slot of WeibullResults)
# @return A data frame containing the median times and confidence intervals for the target event levels
PredictGivenTargetEvents <- function(event.pred,simQ){
  
  if(any(event.pred <= 0 || event.pred > length(simQ@median))) 
    stop("Invalid event.pred value")
  
  ans <- lapply(event.pred,function(x){
    list(time=simQ@median[x],
         event=x,
         CI_low=simQ@lower[x],
         CI_high=simQ@upper[x])    
  })
  
  ans <- do.call(rbind.data.frame, ans)
  ans$time <- as.Date(ans$time,origin="1970-01-01")
  ans$CI_high <- as.Date(ans$CI_high,origin="1970-01-01")
  ans$CI_low <- as.Date(ans$CI_low,origin="1970-01-01")
  ans
}

# Output the expected (median) number of events for a given set of dates
# @param time.pred A vector of dates
# @param simQ A SimQOutput object (i.e. eventQuantiles slot of WeibullResults)
# @return A data frame containing the median  and confidence intervals for the number of events
# at the requested dates
PredictGivenDates <- function(time.pred,simQ){
  
  findEvents <- function(date,event.times){
    if(date < event.times[1]) return(0)
    if(date > event.times[length(event.times)]) return (length(event.times))
    
    start <- 0
    end <- length(event.times)
    
    while(end-start>1){
      centre <- floor((start+end)/2)
      if(date < event.times[centre]){
        end <- centre
      }
      else{
        start <- centre
      }
    }
    return(start)
    
  }
  
  ans <- lapply(time.pred,function(x){
    list(time=x,
         event=findEvents(x,simQ@median),
         CI_low=findEvents(x,simQ@upper), #These are the right way round!
         CI_high=findEvents(x,simQ@lower)
    )    
  })
  ans <- do.call(rbind.data.frame, ans)
  ans$time <- as.Date(ans$time,origin="1970-01-01")
  
  ans
  
}
scientific-computing-solutions/eventPrediction documentation built on May 29, 2019, 3:44 p.m.