\name{sbh}

\alias{sbh}

\title{Cross-Validated Survival Bump Hunting}

\description{
   Main end-user function for fitting a cross-validated Survival Bump Hunting (SBH) model.
   It returns a cross-validated \code{PRSP} object, as generated by our Patient Recursive Survival Peeling or PRSP algorithm.
}

\usage{
  sbh(dataset, 
      B = 10, K = 5, A = 1000, 
      vs = TRUE, cpv = FALSE,
      cvtype=c("combined", "averaged", "none", NULL), 
      cvcriterion=c("lrt", "cer", "lhr", NULL),
      arg = "beta=0.05,alpha=0.1,minn=10,L=NULL,peelcriterion=\"lr\"",
      probval = NULL, timeval = NULL, 
      parallel = FALSE, conf = NULL, seed = NULL)
}

\arguments{
  \item{dataset}{
    \code{data.frame} or \code{numeric} \code{matrix} of input dataset containing the observed survival and status indicator variables 
    in the first two columns, respectively, and all the covariates thereafter. If a \code{data.frame} is provided, it will be coerced 
    to a \code{numeric} \code{matrix}.
  }
  \item{B}{
    Positive \code{integer} scalar of the number of replications of the cross-validation procedure. Defaults to 10.
  }
  \item{K}{
    Positive \code{integer} scalar of the number of folds for the cross-validation procedure. Defaults to 5.
  }
  \item{A}{
    Positive \code{integer} scalar of the number of permutations for the computation of cross-validated p-values. Defaults to 1000.
  }
  \item{vs}{
    \code{logical} scalar. Flag for optional variable (covariate) pre-selection. 
    Defaults to \code{TRUE}.
  }
  \item{cpv}{
    \code{logical} scalar. Flag for computation of permutation p-values. 
    Defaults to \code{FALSE}.
  }
  \item{cvtype}{
    \code{Character} \code{vector} describing the cross-validation technique in \{"combined", "averaged", "none", NULL\}.
    If \code{NULL}, automatically reset to "none".
  }
  \item{cvcriterion}{
    \code{character} \code{vector} describing the optimization criterion in \{"lrt", "cer", "lhr", NULL\}.
    If \code{NULL}, automatically reset to "none".
  }
  \item{arg}{
    \code{Character} \code{vector} describing the PRSP parameters:
    \itemize{
        \item{\code{alpha}} = fraction to peel off at each step. Defaults to 0.1.
        \item{\code{beta}} = minimum support size resulting from the peeling sequence. Defaults to 0.05.
        \item{\code{minn}} = minimum number of observation in a box. Defaults to 10.
        \item{\code{L}} = fixed peeling length. Defaults to \code{NULL}.
        \item{\code{peelcriterion}} in \{"hr" for Log-Hazard Ratio (LHR), 
                                         "lr" for Log-Rank Test (LRT), 
                                         "ch" for Cumulative Hazard Summary (CHS)\}. 
                    Defaults to "lr".
    }
    Note that the parameters in \code{arg} come as a string of charaters between double quotes, 
    where all parameter evaluations are separated by comas (see example).
  } 
  \item{probval}{
    \code{Numeric} scalar of the survival probability at which we want to get the endpoint box survival time. Defaults to NULL.
  }
  \item{timeval}{
    \code{Numeric} scalar of the survival time at which we want to get the endpoint box survival probability. Defaults to NULL.
  }
  \item{parallel}{
    \code{Logical}. Is parallel computing to be performed? Optional. Defaults to \code{FALSE}.
  }
  \item{conf}{
    \code{List} of parameters for cluster configuration.
    Inputs for R package \pkg{parallel} function \code{makeCluster} (R package \pkg{parallel}) for cluster setup.
    Optional, defaults to \code{NULL}. See details for usage.
  }
  \item{seed}{
    Positive \code{integer} scalar of the user seed to reproduce the results.
 }
}

\details{
    
  At this point, the main function \code{sbh} performs the search of the \emph{first} box of the recursive coverage (outer) loop of our 
  Patient Recursive Survival Peeling (PRSP) algorithm.
    
  Also, the main function relies on an optional variable pre-selection procedure that is run before the PRSP algorithm. 
  At this point, this is done by Elastic-Net (EN) penalization of the partial likelihood, where both mixing (\code{alpha}) 
  and overal shrinkage (\code{lambda}) parameters are simultaneously estimated by cross-validation using 
  the \code{glmnet::cv.glmnet} function of the R package \pkg{glmnet}. 
    
  The \code{PRSP} object contains cross-validated estimates of all the decision-rules of pre-selected covariates and 
  all other statistical quantities of interest at each iteration of the peeling sequence (inner loop of the PRSP algorithm). 
  
  It enables the display of results graphically of/for model tuning/selection, all peeling trajectories, covariate traces 
  and survival distributions (see plotting functions for more details).

  The function offers a number of options for the type of cross-validation desired: \eqn{K}-fold (replicated)-averaged or-combined,
  as well as peeling and optimization critera for model fitting, tuning and selectio and a few more parameters for the PRSP algorithm.

  The function takes advantage of the R package \pkg{parallel}, which allows users to create a cluster of workstations on a local
  and/or remote machine(s), enabling scaling-up with the number of CPU cores specified and efficient parallel execution.
  
  Discrete (or nominal) covariates should be made (or re-arranged into) ordinal variables.
  
  If the computation of cross-validated p-value is desired, then running with the parallelization option is generally advised as it may take a while.
  In the case of large (\eqn{p > n}) or very large (\eqn{p >> n}) datasets, it is required to use the parallelization option preferably
  on a hyperperformance cluster of workstations. 
  
  To run a parallel session (and parallel RNG) of the PRIMsrc procedures (\code{parallel}=\code{TRUE}), argument \code{conf}
  is to be specified (i.e. non \code{NULL}). It must list the specifications of the folowing parameters for cluster configuration:
  "names", "cpus", "type", "homo", "verbose", "outfile". These match the arguments described in function \code{makeCluster}
  of the R package \pkg{parallel}. All fields are required to properly configure the cluster, except for "names" and "cpus",
  which are the values used alternatively in the case of a cluster of type "SOCK" (socket), or in the case of a cluster
  of type other than "SOCK" (socket), respectively. See examples below.
  \itemize{
        \item "names": \code{names} : \code{character} \code{vector} specifying the host names on which to run the job.
              Could default to a unique local machine, in which case, one may use the unique host name "localhost".
              Each host name can potentially be repeated to the number of CPU cores available on the corresponding machine.
        \item "cpus": \code{spec} : \code{integer} scalar specifying the total number of CPU cores to be used
              across the network of available nodes, counting the workernodes and masternode.
        \item "type": \code{type} : \code{character} \code{vector} specifying the cluster type ("SOCK", "PVM", "MPI").
        \item "homo": \code{homogeneous} : \code{logical} scalar to be set to \code{FALSE} for inhomogeneous clusters.
        \item "verbose": \code{verbose} : \code{logical} scalar to be set to \code{FALSE} for quiet mode.
        \item "outfile": \code{outfile} : \code{character} \code{vector} of the output log file name for the workernodes.
  }

  Note that argument \code{B} is internally reset to \code{conf$cpus}*\code{ceiling}(\code{B}/\code{conf$cpus}) in case the parallelization
  is used (i.e. \code{conf} is non \code{NULL}), where \code{conf$cpus} denotes the total number of CPUs to be used (see above).
  
  The actual creation of the cluster, its initialization, and closing are all done internally.
  In addition, when random number generation is needed, the creation of separate streams of parallel RNG per node
  is done internally by distributing the stream states to the nodes (For more details see function \code{makeCluster}
  (R package \pkg{parallel}) and/or \url{http://www.stat.uiowa.edu/~luke/R/cluster/cluster.html}.
  
  The use of a seed allows to reproduce the results within the same type of session: the same seed will reproduce the same results 
  within a non-parallel session or within a parallel session, but it will not necessarily give the exact same results (up to sampling variability)
  between a non-parallelized and parallelized session due to the difference of management of the seed between the two (see parallel RNG and 
  value of retuned seed below).
}

\value{
  Object of \code{class} \code{PRSP} (Patient Recursive Survival Peeling)
  \code{List} containing the following 21 fields:
    \item{x}{\code{numeric} \code{matrix} of original dataset.}
    \item{times}{\code{numeric} \code{vector} of observed failure / survival times.}
    \item{status}{\code{numeric} \code{vector} of observed event indicator in \{1,0\}.}
    \item{B}{positive \code{integer} of the number of replications used in the cross-validation procedure.}
    \item{K}{positive \code{integer} of the number of folds used in the cross-validation procedure.}
    \item{A}{positive \code{integer} of the number of permutations used for the computation of permutation p-values.}
    \item{vs}{\code{logical} scalar of returned flag of optional variable pre-selection.}
    \item{cpv}{\code{logical} scalar of returned flag of optional computation of permutation p-values.}
    \item{cvtype}{\code{character} \code{vector} of the cross-validation technique used.}
    \item{cvcriterion}{\code{character} \code{vector} of optimization criterion used.}
    \item{varsign}{\code{numeric} \code{vector} in \{-1,+1\} of directions of peeling for all pre-selected covariates.} 
    \item{selected}{\code{numeric} \code{vector} of pre-selected covariates in reference to original index.}
    \item{used}{\code{numeric} \code{vector} of covariates used for peeling in reference to original index.}
    \item{arg}{\code{character} \code{vector} of the parameters used:}
    \item{probval}{\code{Numeric} scalar of survival probability used.}
    \item{timeval}{\code{Numeric} scalar of survival time used.}
    \item{cvfit}{\code{List} with 7 fields of cross-validated estimates:
        \itemize{
            \item{cv.maxsteps}: \code{numeric} scalar of maximal ceiled-mean of number of peeling steps over the replicates.
            \item{cv.nsteps}: \code{numeric} scalar of optimal number of peeling steps according to the optimization criterion.
            \item{cv.trace}: \code{numeric} \code{vector} of the modal trace values of covariate usage for all peeling steps.
            \item{cv.boxind}: \code{logical} \code{matrix} in {\code{TRUE}, \code{FALSE}} of individual observation box membership indicator (columns) for all peeling steps (rows).
            \item{cv.rules}: \code{data.frame} of decision rules on the covariates (columns) for all peeling steps (rows).
            \item{cv.stats}: \code{numeric} \code{matrix} of box endpoint quantities of interest (columns) for all peeling steps (rows).
            \item{cv.pval}: \code{numeric} \code{vector} of log-rank permutation p-values of sepraration of survival distributions.}
        }
    \item{cvprofiles}{\code{List} of (\eqn{B}) of \code{numeric} \code{vectors}, one for each replicate, 
        of the cross-validated statistics used in the optimization criterion (one set by user) as a function of the number of peeling steps.}
    \item{cvmeanprofiles}{\code{List} of \code{numeric} \code{vectors} of the cross-validated mean statistics over the replicates.
        used in the optimization criterion (one set by user) as a function of the number of peeling steps.}
    \item{plot}{\code{logical} scalar of the returned flag for plotting results (\code{TRUE} if CV successful).}
    \item{config}{\code{List} with 7 fields of parameters used for configuring the parallelization including \code{parallel} and \code{conf}.}
    \item{seed}{User seed(s) used:
        \code{integer} of a single value, if parallelization is used
        \code{integer} \code{vector} of values, one for each replication, if parallelization is not used.}
}

\references{
    \itemize{
        \item Dazard J-E., Choe M., LeBlanc M. and Rao J.S. (2015).
              "\emph{Cross-validation and Peeling Strategies for Survival Bump Hunting using Recursive Peeling Methods.}"
              (Submitted).
        \item Dazard J-E., Choe M., LeBlanc M. and Rao J.S. (2014).
              "\emph{Cross-Validation of Survival Bump Hunting by Recursive Peeling Methods.}"
              In JSM Proceedings, Survival Methods for Risk Estimation/Prediction Section. Boston, MA, USA.
              American Statistical Association IMS - JSM, p. 3366-3380.
        \item Dazard J-E. and J. S. Rao (2010).
              "\emph{Local Sparse Bump Hunting.}"
              J. Comp Graph. Statistics, 19(4):900-92.
    }
}

\author{
    \itemize{
        \item "Jean-Eudes Dazard, Ph.D." \email{jxd101@case.edu}
        \item "Michael Choe, M.D." \email{mjc206@case.edu}
        \item "Michael LeBlanc, Ph.D." \email{mleblanc@fhcrc.org}
        \item "Alberto Santana, MBA." \email{ahs4@case.edu}
    }
    Maintainer: "Jean-Eudes Dazard, Ph.D." \email{jxd101@case.edu}

    Acknowledgments: This project was partially funded by the National Institutes of Health
    NIH - National Cancer Institute (R01-CA160593) to J-E. Dazard and J.S. Rao.
}

\note{
    Unique end-user function for fitting the Survival Bump Hunting model.
}

\keyword{Exploratory Survival/Risk Analysis}
\keyword{Survival/Risk Estimation & Prediction}
\keyword{Non-Parametric Method}
\keyword{Cross-Validation}
\keyword{Bump Hunting}
\keyword{Rule-Induction Method}


\seealso{
    \itemize{
        \item \code{makeCluster} (R package \pkg{parallel})
        \item \code{cv.glmnet} (R package \pkg{glmnet})
        \item \code{glmnet} (R package \pkg{glmnet})
    }
}

\examples{
#===================================================
# Loading the library and its dependencies
#===================================================
library("PRIMsrc")

\dontrun{
    #===================================================
    # PRIMsrc package news
    #===================================================
    PRIMsrc.news()
    
    #===================================================
    # PRIMsrc package citation
    #===================================================
    citation("PRIMsrc")
    
    #===================================================
    # Demo with a synthetic dataset
    # Use help for descriptions
    #===================================================
    data("Synthetic.1", "Synthetic.5", "Real.1", "Real.2", package="PRIMsrc")
    ?Synthetic.1
    ?Synthetic.5
    ?Real.1
    ?Real.2
}

#===================================================
# Simulated dataset #1 (n=250, p=3)
# Replicated Combined Cross-Validation (RCCV)
# Peeling criterion = LRT
# Optimization criterion = LRT
# Without parallelization
# Without computation of permutation p-values
#===================================================
CVCOMBREP.synt1 <- sbh(dataset = Synthetic.1, 
                       cvtype = "combined", cvcriterion = "lrt",
                       B = 1, K = 5, 
                       vs = TRUE, cpv = FALSE, probval = 0.5, 
                       arg = "beta=0.05,
                              alpha=0.1,
                              minn=10,
                              L=NULL,
                              peelcriterion=\"lr\"",
                       parallel = FALSE, conf = NULL, seed = 123)

# selected covariates:
selected <- CVCOMBREP.synt1$selected
selected
# covariates used for peeling:
used <- CVCOMBREP.synt1$used
used
# some output results:
CVCOMBREP.synt1$cvfit$cv.maxsteps
CVCOMBREP.synt1$cvfit$cv.nsteps
CVCOMBREP.synt1$cvfit$cv.trace
CVCOMBREP.synt1$cvfit$cv.rules$frame[,used]
round(CVCOMBREP.synt1$cvfit$cv.stats$mean,2)

\dontrun{
    #===================================================
    # Examples of parallel backend parametrization 
    #===================================================
    # Example #1 - 1-Quad (4-core double threaded) PC 
    # Running WINDOWS
    # With SOCKET communication
    #===================================================
    if (.Platform$OS.type == "windows") {
        cpus <- detectCores()
        conf <- list("names" = rep("localhost", cpus),
                     "cpus" = cpus,
                     "type" = "SOCK",
                     "homo" = TRUE,
                     "verbose" = TRUE,
                     "outfile" = "")
    }
    #===================================================
    # Example #2 - 1 master node + 3 worker nodes cluster
    # All nodes equipped with identical setups and multicores
    # Running LINUX
    # With SOCKET communication
    #===================================================
    if (.Platform$OS.type == "unix") {
        masterhost <- Sys.getenv("HOSTNAME")
        slavehosts <- c("compute-0-0", "compute-0-1", "compute-0-2")
        nodes <- length(slavehosts) + 1
        cpus <- 8
        conf <- list("names" = c(rep(masterhost, cpus),
                                 rep(slavehosts, cpus)),
                     "cpus" = nodes * cpus,
                     "type" = "SOCK",
                     "homo" = TRUE,
                     "verbose" = TRUE,
                     "outfile" = "")
    }
    #===================================================
    # Example #3 - Multinode multicore per node cluster
    # Running LINUX 
    # with MPI communication
    # Here, a file named ".nodes" (e.g. in the home directory)
    # contains the list of nodes of the cluster
    #===================================================
    if (.Platform$OS.type == "unix") {
        hosts <- scan(file=paste(Sys.getenv("HOME"), "/.nodes", sep=""), 
                      what="", 
                      sep="\n")
        hostnames <- unique(hosts)
        nodes <- length(hostnames)
        cpus <-  length(hosts)/length(hostnames)
        conf <- list("cpus" = nodes * cpus,
                     "type" = "MPI",
                     "homo" = TRUE,
                     "verbose" = TRUE,
                     "outfile" = "")
    }
    
    #===================================================
    # Simulated dataset #1 (n=250, p=3)
    # Replicated Combined Cross-Validation (RCCV)
    # Peeling criterion = LRT
    # Optimization criterion = LRT
    # With parallelization
    # With computation of permutation p-values
    #===================================================
    CVCOMBREP.synt1 <- sbh(dataset = Synthetic.1, 
                           cvtype = "combined", cvcriterion = "lrt",
                           B = 10, K = 5, A = 1024, 
                           vs = TRUE, cpv = TRUE, probval = 0.5, 
                           arg = "beta=0.05,
                                  alpha=0.1,
                                  minn=10,
                                  L=NULL,
                                  peelcriterion=\"lr\"",
                           parallel = TRUE, conf = conf, seed = 123)
                           
    # selected covariates:
    selected <- CVCOMBREP.synt1$selected
    selected
    # covariates used for peeling:
    used <- CVCOMBREP.synt1$used
    used
    # some output results:
    CVCOMBREP.synt1$cvfit$cv.maxsteps
    CVCOMBREP.synt1$cvfit$cv.nsteps
    CVCOMBREP.synt1$cvfit$cv.trace
    CVCOMBREP.synt1$cvfit$cv.pval
    CVCOMBREP.synt1$cvfit$cv.rules$frame[,used]
    round(CVCOMBREP.synt1$cvfit$cv.stats$mean,2)

}

}
