text: #!/usr/bin/env python
  # -*- encoding: utf-8 -*-
  from __future__ import unicode_literals
  import bindings as bi
  import sys
  PY3 = sys.version_info[0] == 3
  str_type = str if PY3 else (str, unicode)
  
  # ----------------------------------------------------------------------------------------------------------------------
  #   Generate per-model classes
  # ----------------------------------------------------------------------------------------------------------------------
  
  def gen_module(schema, algo, module):
      help_preamble = help_preamble_for(algo)
      help_details = help_details_for(algo)
      help_return = help_return_for(algo)
      help_epilogue = help_epilogue_for(algo)
      help_references = help_references_for(algo)
      help_example = help_example_for(algo)
      help_extra_params = help_extra_params_for(algo)
      help_extra_checks = help_extra_checks_for(algo)
      help_afterword = help_afterword_for(algo)
      model_name = algo_to_modelname(algo)
  
      yield "# This file is auto-generated by h2o-3/h2o-bindings/bin/gen_R.py"
      yield "# Copyright 2016 H2O.ai;  Apache License Version 2.0 (see LICENSE for details) \n#'"
      yield "# -------------------------- %s -------------------------- #" % model_name
      if help_preamble:
          lines = help_preamble.split("\n")
          for line in lines:
              yield "#' %s" % line.lstrip()
  
      if help_extra_params:
          lines = help_extra_params.split("\n")
          for line in lines:
              yield line.lstrip()
  
      for param in schema["parameters"]:
          if param["name"] in ["ignored_columns", "response_column", "max_confusion_matrix_size"]:
              continue
          if algo == "drf":
              if param["name"] == "offset_column":
                  yield "#' @param offset_column Offset column. This argument is deprecated and has no use for Random Forest."
                  continue
              if param["name"] == "distribution":
                  yield "#' @param distribution Distribution. This argument is deprecated and has no use for Random Forest."
                  continue
          if algo == "naivebayes":
              if param["name"] == "min_sdev":
                  yield "#' @param threshold This argument is deprecated, use `min_sdev` instead. The minimum standard deviation to use for observations without enough data. "
                  yield "#'                  Must be at least 1e-10."
                  yield "#' @param min_sdev The minimum standard deviation to use for observations without enough data. "
                  yield "#'                  Must be at least 1e-10."
                  continue
              if param["name"] == "eps_sdev":
                  yield "#' @param eps This argument is deprecated, use `eps_sdev` instead. A threshold cutoff to deal with numeric instability, must be positive."
                  yield "#' @param eps_sdev A threshold cutoff to deal with numeric instability, must be positive."
                  continue
              if param["name"] == "min_prob":
                  yield "#' @param min_prob Min. probability to use for observations with not enough data."
                  continue
              if param["name"] == "eps_prob":
                  yield "#' @param eps_prob Cutoff below which probability is replaced with min_prob."
                  continue
          if param["name"] == "seed":
              if algo != "stackedensemble":
                  yield "#' @param seed Seed for random numbers (affects certain parts of the algo that are stochastic and those might or might not be enabled by default)"
              else:
                  yield "#' @param seed Seed for random numbers; passed through to the metalearner algorithm. Defaults to -1 (time-based random number)"
              if algo in ["deeplearning", "deepwater"]:
                  yield "#'        Note: only reproducible when running single threaded."
              yield "#'        Defaults to -1 (time-based random number)."
              continue
          phelp = param["help"]
          if param["type"] == "boolean":
              phelp = "\code{Logical}. " + phelp
          if param["values"]:
              phelp += " Must be one of: %s." % ", ".join('"%s"' % p for p in param["values"])
          if (param["name"]==u'distribution') and (not(algo==u'glm') and not(algo==u'gbm')):    # quasibinomial only in glm, gbm
              phelp=phelp.replace(' "quasibinomial",',"")
          if (param["name"]==u'distribution') and not(algo==u'glm'):    # ordinal only in glm
              phelp=phelp.replace(' "ordinal",',"")
          if param["default_value"] is not None:
              phelp += " Defaults to %s." % normalize_value(param, True)
          yield "#' @param %s %s" % (param["name"], bi.wrap(phelp, indent=("#'        "), indent_first=False))
      if algo in ["deeplearning","drf", "gbm","xgboost"]:
          yield "#' @param verbose \code{Logical}. Print scoring history to the console (Metrics per tree for GBM, DRF, & XGBoost. Metrics per epoch for Deep Learning). Defaults to FALSE."
      if help_details:
          yield "#' @details %s" % bi.wrap(help_details, indent=("#'          "), indent_first=False)
      if help_return:
          lines = help_return.split("\n")
          for line in lines:
              yield "%s" % line.lstrip()
          # yield "#' @return %s" % bi.wrap(help_return, indent=("#'         "), indent_first=False)
      if help_epilogue:
          yield "#' @seealso %s" % bi.wrap(help_epilogue, indent=("#'          "), indent_first=False)
      if help_references:
          yield "#' @references %s" % help_references
      if help_example:
          yield "#' @examples"
          lines = help_example.split("\n")
          for line in lines:
              yield "#' %s" % line.lstrip()
      yield "#' @export"
      yield "h2o.%s <- function(%s," % (module, get_extra_params_for(algo))
      # yield indent("training_frame,", 17 + len(algo))
      list = []
      for param in schema["parameters"]:
          if param["name"] in ["ignored_columns", "response_column", "max_confusion_matrix_size", "training_frame"]:
              continue
          if algo == "naivebayes":
              if param["name"] == "min_sdev":
                  list.append(indent("threshold = %s" % normalize_value(param), 17 + len(module)))
                  list.append(indent("min_sdev = %s" % normalize_value(param), 17 + len(module)))
                  continue
              if param["name"] == "eps_sdev":
                  list.append(indent("eps = %s" % normalize_value(param), 17 + len(module)))
                  list.append(indent("eps_sdev = %s" % normalize_value(param), 17 + len(module)))
                  continue
              if param["name"] == "min_prob":
                  list.append(indent("min_prob = %s" % normalize_value(param), 17 + len(module)))
                  continue
              if param["name"] == "eps_prob":
                  list.append(indent("eps_prob = %s" % normalize_value(param), 17 + len(module)))
                  continue
          if (param["name"]==u'distribution'):
              temp = normalize_value(param)
              if not(algo==u'glm') and not(algo==u'gbm'):    # quasibinomial only in glm, gbm
                  temp = temp.replace(' "quasibinomial",',"")
              if not(algo==u'glm'):
                  temp = temp.replace(' "ordinal",',"")
              list.append(indent("%s = %s" % (param["name"], temp), 17 + len(module)))
          else:
              if param["name"] != "metalearner_params":
                  list.append(indent("%s = %s" % (param["name"], normalize_value(param)), 17 + len(module)))
      if algo in ["deeplearning","drf", "gbm","xgboost"]:
          list.append(indent("verbose = FALSE ",17 + len(module)))
      if algo in ["stackedensemble"]:
          list.append(indent("metalearner_params = NULL ",17 + len(module)))
      yield ",\n".join(list)
      yield indent(") \n{", 17 + len(module))
      if algo in ["deeplearning", "deepwater", "xgboost", "drf", "gbm", "glm", "naivebayes", "stackedensemble"]:
          yield "  # If x is missing, then assume user wants to use all columns as features."
          yield "  if (missing(x)) {"
          yield "     if (is.numeric(y)) {"
          yield "         x <- setdiff(col(training_frame), y)"
          yield "     } else {"
          yield "         x <- setdiff(colnames(training_frame), y)"
          yield "     }"
          yield "  }"
          if algo == "gbm":
              yield "  # Required maps for different names params, including deprecated params"
              yield "  .gbm.map <- c(\"x\" = \"ignored_columns\","
              yield "                \"y\" = \"response_column\")"
          elif algo == "naivebayes":
              yield " .naivebayes.map <- c(\"x\" = \"ignored_columns\", \"y\" = \"response_column\", \n \
                           \"threshold\" = \"min_sdev\", \"eps\" = \"eps_sdev\")"
          elif algo == "glm":
              yield "  # if (!is.null(beta_constraints)) {"
              yield "  #     if (!inherits(beta_constraints, 'data.frame') && !is.H2OFrame(beta_constraints))"
              yield "  #       stop(paste('`beta_constraints` must be an H2OH2OFrame or R data.frame. Got: ', class(beta_constraints)))"
              yield "  #     if (inherits(beta_constraints, 'data.frame')) {"
              yield "  #       beta_constraints <- as.h2o(beta_constraints)"
              yield "  #     }"
              yield "  # }"
              yield "  if (inherits(beta_constraints, 'data.frame')) {"
              yield "    beta_constraints <- as.h2o(beta_constraints)"
              yield "  }"
      yield ""
      if algo == "coxph":
          yield "  # If x is missing, then assume user wants to use all columns as features."
          yield "  if (missing(x)) {"
          yield "     if (is.numeric(event_column)) {"
          yield "         x <- setdiff(col(training_frame), event_column)"
          yield "     } else {"
          yield "         x <- setdiff(colnames(training_frame), event_column)"
          yield "     }"
          yield "  }"
          yield "  if (is.null(interactions_only) && (! is.null(interactions) || ! is.null(interaction_pairs))) {"
          yield "     used <- unique(c(interactions, unlist(sapply(interaction_pairs, function(x) {x[1]})), unlist(sapply(interaction_pairs, function(x) {x[2]}))))"
          yield "     interactions_only <- setdiff(used, x)"
          yield "     x <- c(x, interactions_only)"
          yield "  }"
          yield "  if (! is.null(stratify_by)) {"
          yield "     stratify_by_only <- setdiff(stratify_by, x)"
          yield "     x <- c(x, stratify_by_only)"
          yield "  }"
      if algo == "word2vec":
          yield "  # training_frame is required if pre_trained frame is not specified"
          yield "  if (missing(pre_trained) && missing(training_frame)) stop(\"argument \'training_frame\' is missing, with no default\")"
          yield "  # training_frame must be a key or an H2OFrame object"
          yield "  if (!missing(training_frame) && !is.H2OFrame(training_frame))"
          yield "    tryCatch(training_frame <- h2o.getFrame(training_frame),"
          yield "             error = function(err) {"
          yield "               stop(\"argument \'training_frame\' must be a valid H2OFrame or key\")"
          yield "             })"
          yield "  # pre_trained must be a key or an H2OFrame object"
          yield "  if (!missing(pre_trained) && !is.H2OFrame(pre_trained))"
          yield "    tryCatch(pre_trained <- h2o.getFrame(pre_trained),"
          yield "             error = function(err) {"
          yield "               stop(\"argument \'pre_trained\' must be a valid H2OFrame or key\")"
          yield "             })"
      else:
          yield "  # Required args: training_frame"
          yield "  if (missing(training_frame)) stop(\"argument \'training_frame\' is missing, with no default\")"
          # yield "  if( missing(validation_frame) ) validation_frame = NULL"
          yield "  # Training_frame must be a key or an H2OFrame object"
          yield "  if (!is.H2OFrame(training_frame))"
          yield "     tryCatch(training_frame <- h2o.getFrame(training_frame),"
          yield "           error = function(err) {"
          yield "             stop(\"argument \'training_frame\' must be a valid H2OFrame or key\")"
          yield "           })"
      if algo not in ["word2vec", "aggregator", "coxph"]:
          yield "  # Validation_frame must be a key or an H2OFrame object"
          yield "  if (!is.null(validation_frame)) {"
          yield "     if (!is.H2OFrame(validation_frame))"
          yield "         tryCatch(validation_frame <- h2o.getFrame(validation_frame),"
          yield "             error = function(err) {"
          yield "                 stop(\"argument \'validation_frame\' must be a valid H2OFrame or key\")"
          yield "             })"
          yield "  }"
      yield "  # Parameter list to send to model builder"
      yield "  parms <- list()"
      yield "  parms$training_frame <- training_frame"
      if algo == "glrm":
          yield " if(!missing(cols))"
          yield " parms$ignored_columns <- .verify_datacols(training_frame, cols)$cols_ignore"
      elif algo in ["deeplearning", "deepwater", "xgboost", "drf", "gbm", "glm", "naivebayes", "stackedensemble", "coxph"]:
          if any(param["name"] == "autoencoder" for param in schema["parameters"]):
              yield "  args <- .verify_dataxy(training_frame, x, y, autoencoder)"
          elif algo == "coxph":
              yield "  args <- .verify_dataxy(training_frame, x, event_column)"
          else:
              yield "  args <- .verify_dataxy(training_frame, x, y)"
          if any(param["name"] == "offset_column" for param in schema["parameters"]):
              yield "  if( !missing(offset_column) && !is.null(offset_column))  args$x_ignore <- args$x_ignore[!( offset_column == args$x_ignore )]"
          if any(param["name"] == "weights_column" for param in schema["parameters"]):
              yield "  if( !missing(weights_column) && !is.null(weights_column)) args$x_ignore <- args$x_ignore[!( weights_column == args$x_ignore )]"
          if algo != "stackedensemble":
              if algo == "coxph":
                  yield "  if( !missing(start_column) && !is.null(start_column)) args$x_ignore <- args$x_ignore[!( start_column == args$x_ignore )]"
                  yield "  if( !missing(stop_column) && !is.null(stop_column)) args$x_ignore <- args$x_ignore[!( stop_column == args$x_ignore )]"
              else:
                  yield "  if( !missing(fold_column) && !is.null(fold_column)) args$x_ignore <- args$x_ignore[!( fold_column == args$x_ignore )]"
              yield "  parms$ignored_columns <- args$x_ignore"
          yield "  parms$response_column <- args$y\n"
      elif algo == "word2vec":
          yield ""
      elif algo == "kmeans":
          yield "  if(!missing(x)){"
          yield "    parms$ignored_columns <- .verify_datacols(training_frame, x)$cols_ignore"
          yield "    if(!missing(fold_column)){"
          yield "      parms$ignored_columns <- setdiff(parms$ignored_columns, fold_column)"
          yield "    }"
          yield "  }"
      else:
          yield "  if(!missing(x))"
          yield "    parms$ignored_columns <- .verify_datacols(training_frame, x)$cols_ignore"
      if algo == "svd":
          yield "  if(!missing(destination_key)) {"
          yield "    warning(\"'destination_key' is deprecated; please use 'model_id' instead.\")"
          yield "    if(missing(model_id)) {"
          yield "      parms$model_id <- destination_key"
          yield "    }"
          yield "  }"
      #if algo == "stackedensemble":
      #    yield "  if (!missing(model_id))"
      #    yield "    parms$model_id <- model_id"
      if algo == "stackedensemble":
          yield " if (length(base_models) == 0) stop('base_models is empty')"
          yield "  # If base_models contains models instead of ids, replace with model id"
          yield "  for (i in 1:length(base_models)) {"
          yield "    if (inherits(base_models[[i]], 'H2OModel')) {"
          yield "      base_models[[i]] <- base_models[[i]]@model_id"
          yield "    }"
          yield "  }"
          yield " "
          yield "  if (!missing(metalearner_params))"
          yield "      parms$metalearner_params <- as.character(toJSON(metalearner_params, pretty = TRUE))"
      for param in schema["parameters"]:
          if param["name"] in ["ignored_columns", "response_column", "training_frame", "max_confusion_matrix_size"]:
              continue
          if algo == "glm" and param["name"] in ["interactions", "nfolds", "beta_constraints", "missing_values_handling"]:
              continue
          if param["name"] == "loss":
              yield "  if(!missing(loss)) {"
              yield "    if(loss == \"MeanSquare\") {"
              yield "      warning(\"Loss name 'MeanSquare' is deprecated; please use 'Quadratic' instead.\")"
              yield "      parms$loss <- \"Quadratic\""
              yield "    } else "
              yield "      parms$loss <- loss"
              yield "  }"
              continue
          if param["name"] == "min_sdev":
              yield " if (!missing(threshold))"
              yield "   warning(\"argument 'threshold' is deprecated; use 'min_sdev' instead.\")"
              yield "   parms$%s <- threshold" % param["name"]
          if param["name"] == "min_prob":
              yield " if (!missing(min_prob))"
              yield "   parms$%s <- min_prob" % param["name"]
              continue
          if param["name"] == "eps_sdev":
              yield " if (!missing(eps))"
              yield "   warning(\"argument 'eps' is deprecated; use 'eps_sdev' instead.\")"
              yield "   parms$%s <- eps" % param["name"]
          if param["name"] == "eps_prob":
              yield " if (!missing(eps_prob))"
              yield "   parms$%s <- eps_prob" % param["name"]
              continue
          if param["name"] == "metalearner_params":
              continue
          if algo == "drf" and (param["name"] == "offset_column" or param["name"] == "distribution"):
              yield "  if (!missing(%s))" % param["name"]
              yield "    warning(\"Argument %s is deprecated and has no use for Random Forest.\")" % param["name"]
              if param["name"] == "distribution":
                  yield "    parms$%s <- 'AUTO'" % (param["name"])
              else:
                  yield "    parms$%s <- NULL" % (param["name"])
              continue
          yield "  if (!missing(%s))" % param["name"]
          yield "    parms$%s <- %s" % (param["name"], param["name"])
      if help_extra_checks:
          lines = help_extra_checks.split("\n")
          for line in lines:
              yield "%s" % line
      if algo not in ["aggregator", "glm", "deeplearning", "drf", "gbm", "xgboost", "stackedensemble"]:
          yield "  # Error check and build model"
          yield "  .h2o.modelJob('%s', parms, h2oRestApiVersion = %d) \n}" % (algo, 99 if algo in ["svd", "stackedensemble"] else 3)
      if algo in ["stackedensemble"]:
          yield "  # Error check and build model"
          yield "  model <- .h2o.modelJob('%s', parms, h2oRestApiVersion = %d)" % (algo, 99 if algo in ["svd", "stackedensemble"] else 3)
          yield "  #Convert metalearner_params back to list if not NULL"
          yield "  if (!missing(metalearner_params)) {"
          yield "      model@parameters$metalearner_params <- list(fromJSON(model@parameters$metalearner_params))"
          yield "  }"
          yield "  return(model)"
          yield "}"
      if algo in ["deeplearning", "drf", "gbm", "xgboost"]:
          yield "  # Error check and build model"
          yield "  .h2o.modelJob('%s', parms, h2oRestApiVersion = %d, verbose=verbose) \n}" % (algo, 99 if algo in ["svd", "stackedensemble"] else 3)
      if help_afterword:
          lines = help_afterword.split("\n")
          for line in lines:
              yield line.lstrip()
  
  def help_preamble_for(algo):
      if algo == "aggregator":
          return """
              Build an Aggregated Frame
  
              Builds an Aggregated Frame of an H2OFrame.
          """
      if algo == "deeplearning":
          return """
              Build a Deep Neural Network model using CPUs
  
              Builds a feed-forward multilayer artificial neural network on an H2OFrame.
          """
      if algo == "stackedensemble":
          return """
              Builds a Stacked Ensemble
  
              Build a stacked ensemble (aka. Super Learner) using the H2O base
              learning algorithms specified by the user.
          """
      if algo == "deepwater":
          return """
              Build a Deep Learning model using multiple native GPU backends
  
              Builds a deep neural network on an H2OFrame containing various data sources.
          """
      if algo == "xgboost":
          return """
              Build an eXtreme Gradient Boosting model
  
              Builds a eXtreme Gradient Boosting model using the native XGBoost backend.
          """
      if algo == "drf":
          return """
              Build a Random Forest model
  
              Builds a Random Forest model on an H2OFrame.
          """
      if algo == "gbm":
          return """
              Build gradient boosted classification or regression trees
  
              Builds gradient boosted classification trees and gradient boosted regression trees on a parsed data set.
              The default distribution function will guess the model type based on the response column type.
              In order to run properly, the response column must be an numeric for "gaussian" or an
              enum for "bernoulli" or "multinomial".
          """
      if algo == "glm":
          return """
              Fit a generalized linear model
  
              Fits a generalized linear model, specified by a response variable, a set of predictors, and a
              description of the error distribution.
          """
      if algo == "glrm":
          return """
              Generalized low rank decomposition of an H2O data frame
  
              Builds a generalized low rank decomposition of an H2O data frame
          """
      if algo == "kmeans":
          return """
               Performs k-means clustering on an H2O dataset
          """
      if algo == "naivebayes":
          return """
              Compute naive Bayes probabilities on an H2O dataset.
  
              The naive Bayes classifier assumes independence between predictor variables conditional
              on the response, and a Gaussian distribution of numeric predictors with mean and standard
              deviation computed from the training dataset. When building a naive Bayes classifier,
              every row in the training dataset that contains at least one NA will be skipped completely.
              If the test dataset has missing values, then those predictors are omitted in the probability
              calculation during prediction.
          """
      if algo == "pca":
          return """
              Principal component analysis of an H2O data frame
  
              Principal components analysis of an H2O data frame using the power method
              to calculate the singular value decomposition of the Gram matrix.
          """
      if algo == "svd":
          return """
              Singular value decomposition of an H2O data frame using the power method
         """
      if algo == "word2vec":
          return """
              Trains a word2vec model on a String column of an H2O data frame
          """
      if algo == "coxph":
          return """
              Trains a Cox Proportional Hazards Model (CoxPH) on an H2O dataset
          """
  
  def help_details_for(algo):
      if algo == "naivebayes":
          return """The naive Bayes classifier assumes independence between predictor variables conditional
          on the response, and a Gaussian distribution of numeric predictors with mean and standard
          deviation computed from the training dataset. When building a naive Bayes classifier,
          every row in the training dataset that contains at least one NA will be skipped completely.
          If the test dataset has missing values, then those predictors are omitted in the probability
          calculation during prediction."""
  
  def help_return_for(algo):
      if algo == "drf":
          return "#' @return Creates a \linkS4class{H2OModel} object of the right type."
      if algo == "glm":
          return """#' @return A subclass of \code{\linkS4class{H2OModel}} is returned. The specific subclass depends on the machine
          #'         learning task at hand (if it's binomial classification, then an \code{\linkS4class{H2OBinomialModel}} is
          #'         returned, if it's regression then a \code{\linkS4class{H2ORegressionModel}} is returned). The default print-
          #'         out of the models is shown, but further GLM-specifc information can be queried out of the object. To access
          #'         these various items, please refer to the seealso section below. Upon completion of the GLM, the resulting
          #'         object has coefficients, normalized coefficients, residual/null deviance, aic, and a host of model metrics
          #'         including MSE, AUC (for logistic regression), degrees of freedom, and confusion matrices. Please refer to the
          #'         more in-depth GLM documentation available here:
          #'         \\url{https://h2o-release.s3.amazonaws.com/h2o-dev/rel-shannon/2/docs-website/h2o-docs/index.html#Data+Science+Algorithms-GLM}
          """
      if algo == "kmeans":
          return "#' @return Returns an object of class \linkS4class{H2OClusteringModel}."
      if algo == "naivebayes":
          return """#' @return Returns an object of class \linkS4class{H2OBinomialModel} if the response has two categorical levels,
          #'         and \linkS4class{H2OMultinomialModel} otherwise."""
      if algo in ["glrm", "pca", "svd"]:
          return "#' @return Returns an object of class \linkS4class{H2ODimReductionModel}."
  
  def help_epilogue_for(algo):
      if algo == "glm":
          return """\code{\link{predict.H2OModel}} for prediction, \code{\link{h2o.mse}}, \code{\link{h2o.auc}}, \code{\link{h2o.confusionMatrix}}, \code{\link{h2o.performance}}, \code{\link{h2o.giniCoef}}, \code{\link{h2o.logloss}}, \code{\link{h2o.varimp}}, \code{\link{h2o.scoreHistory}}"""
      if algo == "glrm":
          return """\code{\link{h2o.kmeans}, \link{h2o.svd}}, \code{\link{h2o.prcomp}}"""
      if algo == "kmeans":
          return """\code{\link{h2o.cluster_sizes}}, \code{\link{h2o.totss}}, \code{\link{h2o.num_iterations}}, \code{\link{h2o.betweenss}}, \code{\link{h2o.tot_withinss}}, \code{\link{h2o.withinss}}, \code{\link{h2o.centersSTD}}, \code{\link{h2o.centers}}"""
      if algo == "pca":
          return """\code{\link{h2o.svd}}, \code{\link{h2o.glrm}}"""
      if algo in ["deeplearning", "drf", "gbm"]:
          return """\code{\link{predict.H2OModel}} for prediction"""
  
  def help_references_for(algo):
      if algo == "glrm":
          return """M. Udell, C. Horn, R. Zadeh, S. Boyd (2014). {Generalized Low Rank Models}[http://arxiv.org/abs/1410.0342]. Unpublished manuscript, Stanford Electrical Engineering Department
  #'             N. Halko, P.G. Martinsson, J.A. Tropp. {Finding structure with randomness: Probabilistic algorithms for constructing approximate matrix decompositions}[http://arxiv.org/abs/0909.4061]. SIAM Rev., Survey and Review section, Vol. 53, num. 2, pp. 217-288, June 2011."""
      if algo in ["svd", "pca"]:
          return """N. Halko, P.G. Martinsson, J.A. Tropp. {Finding structure with randomness: Probabilistic algorithms for constructing approximate matrix decompositions}[http://arxiv.org/abs/0909.4061]. SIAM Rev., Survey and Review section, Vol. 53, num. 2, pp. 217-288, June 2011."""
  
  def help_example_for(algo):
      if algo == "aggregator":
          return """\donttest{
              library(h2o)
              h2o.init()
              df <- h2o.createFrame(rows=100, cols=5, categorical_fraction=0.6, integer_fraction=0,
                                    binary_fraction=0, real_range=100, integer_range=100, missing_fraction=0)
              target_num_exemplars=1000
              rel_tol_num_exemplars=0.5
              encoding="Eigen"
              agg <- h2o.aggregator(training_frame=df,
                                   target_num_exemplars=target_num_exemplars,
                                   rel_tol_num_exemplars=rel_tol_num_exemplars,
                                   categorical_encoding=encoding)
              }"""
      if algo == "deeplearning":
          return """\donttest{
              library(h2o)
              h2o.init()
              iris.hex <- as.h2o(iris)
              iris.dl <- h2o.deeplearning(x = 1:4, y = 5, training_frame = iris.hex, seed=123456)
  
              # now make a prediction
              predictions <- h2o.predict(iris.dl, iris.hex)
              }"""
      if algo == "gbm":
          return """\donttest{
          library(h2o)
          h2o.init()
  
          # Run regression GBM on australia.hex data
          ausPath <- system.file("extdata", "australia.csv", package="h2o")
          australia.hex <- h2o.uploadFile(path = ausPath)
          independent <- c("premax", "salmax","minairtemp", "maxairtemp", "maxsst",
                           "maxsoilmoist", "Max_czcs")
          dependent <- "runoffnew"
          h2o.gbm(y = dependent, x = independent, training_frame = australia.hex,
                  ntrees = 3, max_depth = 3, min_rows = 2)
          }"""
      if algo == "glm":
          return """\donttest{
          h2o.init()
  
          # Run GLM of CAPSULE ~ AGE + RACE + PSA + DCAPS
          prostatePath = system.file("extdata", "prostate.csv", package = "h2o")
          prostate.hex = h2o.importFile(path = prostatePath, destination_frame = "prostate.hex")
          h2o.glm(y = "CAPSULE", x = c("AGE","RACE","PSA","DCAPS"), training_frame = prostate.hex,
                  family = "binomial", nfolds = 0, alpha = 0.5, lambda_search = FALSE)
  
          # Run GLM of VOL ~ CAPSULE + AGE + RACE + PSA + GLEASON
          myX = setdiff(colnames(prostate.hex), c("ID", "DPROS", "DCAPS", "VOL"))
          h2o.glm(y = "VOL", x = myX, training_frame = prostate.hex, family = "gaussian",
                  nfolds = 0, alpha = 0.1, lambda_search = FALSE)
  
  
          # GLM variable importance
          # Also see:
          #   https://github.com/h2oai/h2o/blob/master/R/tests/testdir_demos/runit_demo_VI_all_algos.R
          data.hex = h2o.importFile(
            path = "https://s3.amazonaws.com/h2o-public-test-data/smalldata/demos/bank-additional-full.csv",
            destination_frame = "data.hex")
          myX = 1:20
          myY="y"
          my.glm = h2o.glm(x=myX, y=myY, training_frame=data.hex, family="binomial", standardize=TRUE,
                           lambda_search=TRUE)
          }"""
      if algo == "glrm":
          return """\donttest{
              library(h2o)
              h2o.init()
              ausPath <- system.file("extdata", "australia.csv", package="h2o")
              australia.hex <- h2o.uploadFile(path = ausPath)
              h2o.glrm(training_frame = australia.hex, k = 5, loss = "Quadratic", regularization_x = "L1",
                       gamma_x = 0.5, gamma_y = 0, max_iterations = 1000)
              }"""
      if algo == "kmeans":
          return """\donttest{
          library(h2o)
          h2o.init()
          prosPath <- system.file("extdata", "prostate.csv", package="h2o")
          prostate.hex <- h2o.uploadFile(path = prosPath)
          h2o.kmeans(training_frame = prostate.hex, k = 10, x = c("AGE", "RACE", "VOL", "GLEASON"))
          }"""
      if algo == "naivebayes":
          return """\donttest{
          h2o.init()
          votesPath <- system.file("extdata", "housevotes.csv", package="h2o")
          votes.hex <- h2o.uploadFile(path = votesPath, header = TRUE)
          h2o.naiveBayes(x = 2:17, y = 1, training_frame = votes.hex, laplace = 3)
          }"""
      if algo == "pca":
          return """\donttest{
          library(h2o)
          h2o.init()
          ausPath <- system.file("extdata", "australia.csv", package="h2o")
          australia.hex <- h2o.uploadFile(path = ausPath)
          h2o.prcomp(training_frame = australia.hex, k = 8, transform = "STANDARDIZE")
          }"""
      if algo == "svd":
          return """\donttest{
          library(h2o)
          h2o.init()
          ausPath <- system.file("extdata", "australia.csv", package="h2o")
          australia.hex <- h2o.uploadFile(path = ausPath)
          h2o.svd(training_frame = australia.hex, nv = 8)
          }"""
      if algo == "stackedensemble":
          return """
          # See example R code here:
          # http://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-science/stacked-ensembles.html
          """
  
  def get_extra_params_for(algo):
      if algo == "glrm":
          return "training_frame, cols = NULL"
      elif algo in ["deeplearning", "deepwater", "xgboost", "drf", "gbm", "glm", "naivebayes", "stackedensemble"]:
          return "x, y, training_frame"
      elif algo == "svd":
          return "training_frame, x, destination_key"
      elif algo == "word2vec":
          return "training_frame = NULL"
      elif algo == "coxph":
          return "x, event_column, training_frame"
      else:
          return "training_frame, x"
  
  def help_extra_params_for(algo):
      if algo == "glrm":
          return "#' @param cols (Optional) A vector containing the data columns on which k-means operates."
      elif algo in ["deeplearning", "deepwater", "xgboost", "drf", "gbm", "glm", "naivebayes"]:
          x_string = """#' @param x (Optional) A vector containing the names or indices of the predictor variables to use in building the model.
              #'        If x is missing, then all columns except y are used."""
      elif algo == "coxph":
          return """#' @param x (Optional) A vector containing the names or indices of the predictor variables to use in building the model.
              #'        If x is missing, then all columns except event_column, start_column and stop_column are used.
              #' @param event_column The name of binary data column in the training frame indicating the occurrence of an event."""
      elif algo == "stackedensemble":
          x_string = """#' @param x (Optional). A vector containing the names or indices of the predictor variables to use in building the model.
              #'           If x is missing, then all columns except y are used.  Training frame is used only to compute ensemble training metrics. """
      elif algo == "svd":
          return """#' @param x A vector containing the \code{character} names of the predictors in the model.
              #' @param destination_key (Optional) The unique hex key assigned to the resulting model.
              #'                        Automatically generated if none is provided."""
      elif algo == "word2vec":
          return None
      else:  #Aggregator, PCA, SVD, K-Means: can this be grouped in with the others?  why are only character names supported?
          return """#' @param x A vector containing the \code{character} names of the predictors in the model."""
      if algo in ["deeplearning", "deepwater", "xgboost", "drf", "gbm", "glm", "naivebayes", "stackedensemble"]:
          return x_string + "\n" + """#' @param y The name or column index of the response variable in the data. The response must be either a numeric or a
              #'        categorical/factor variable. If the response is numeric, then a regression model will be trained, otherwise it will train a classification model."""
  
  
  def help_extra_checks_for(algo):
      if algo == "aggregator":
          # Add aggregator@model$aggregated_frame_id reference to generated model
          # TODO Change h2oRestApiVersion to 3, when Aggregator is not experimental
          return """
    m <- .h2o.modelJob('aggregator', parms, h2oRestApiVersion=99)
    m@model$aggregated_frame_id <- m@model$output_frame$name
    m\n}
          """
      if algo == "glm":
          return """
    if( !missing(interactions) ) {
      # interactions are column names => as-is
      if( is.character(interactions) )       parms$interactions <- interactions
      else if( is.numeric(interactions) )    parms$interactions <- names(training_frame)[interactions]
      else stop(\"Don't know what to do with interactions. Supply vector of indices or names\")
    }
    # For now, accept nfolds in the R interface if it is 0 or 1, since those values really mean do nothing.
    # For any other value, error out.
    # Expunge nfolds from the message sent to H2O, since H2O doesn't understand it.
    if (!missing(nfolds) && nfolds > 1)
      parms$nfolds <- nfolds
    if(!missing(beta_constraints))
      parms$beta_constraints <- beta_constraints
      if(!missing(missing_values_handling))
        parms$missing_values_handling <- missing_values_handling
    m <- .h2o.modelJob('glm', parms, h2oRestApiVersion=3)
    m@model$coefficients <- m@model$coefficients_table[,2]
    names(m@model$coefficients) <- m@model$coefficients_table[,1]
    m \n}
          """
      if algo == "glrm":
          return """
    # Check if user_y is an acceptable set of user-specified starting points
    if( is.data.frame(user_y) || is.matrix(user_y) || is.list(user_y) || is.H2OFrame(user_y) ) {
    # Convert user-specified starting points to H2OFrame
    if( is.data.frame(user_y) || is.matrix(user_y) || is.list(user_y) ) {
      if( !is.data.frame(user_y) && !is.matrix(user_y) ) user_y <- t(as.data.frame(user_y))
      user_y <- as.h2o(user_y)
    }
    parms[["user_y"]] <- user_y
  
    # Set k
    if( !(missing(k)) && k!=as.integer(nrow(user_y)) ) {
      warning("Argument k is not equal to the number of rows in user-specified Y. Ignoring k. Using specified Y.")
    }
    parms[["k"]] <- as.numeric(nrow(user_y))
    # } else if( is.null(user_y) ) {
    #  if(!missing(init) && parms[["init"]] == "User")
    #    warning("Initializing Y to a standard Gaussian random matrix.")
    # } else
    } else if( !is.null(user_y) )
    stop("Argument user_y must either be null or a valid user-defined starting Y matrix.")
  
    # Check if user_x is an acceptable set of user-specified starting points
    if( is.data.frame(user_x) || is.matrix(user_x) || is.list(user_x) || is.H2OFrame(user_x) ) {
    # Convert user-specified starting points to H2OFrame
    if( is.data.frame(user_x) || is.matrix(user_x) || is.list(user_x) ) {
      if( !is.data.frame(user_x) && !is.matrix(user_x) ) user_x <- t(as.data.frame(user_x))
      user_x <- as.h2o(user_x)
    }
    parms[["user_x"]] <- user_x
    # } else if( is.null(user_x) ) {
    #  if(!missing(init) && parms[["init"]] == "User")
    #    warning("Initializing X to a standard Gaussian random matrix.")
    # } else
    } else if( !is.null(user_x) )
    stop("Argument user_x must either be null or a valid user-defined starting X matrix.")
          """
      if algo == "kmeans":
          return """
    # Check if user_points is an acceptable set of user-specified starting points
    if( is.data.frame(user_points) || is.matrix(user_points) || is.list(user_points) || is.H2OFrame(user_points) ) {
      if ( length(init) > 1 || init == 'User') {
        parms[["init"]] <- "User"
      } else {
        warning(paste0("Parameter init must equal 'User' when user_points is set. Ignoring init = '", init, "'. Setting init = 'User'."))
      }
  
      parms[["init"]] <- "User"
    # Convert user-specified starting points to H2OFrame
    if( is.data.frame(user_points) || is.matrix(user_points) || is.list(user_points) ) {
      if( !is.data.frame(user_points) && !is.matrix(user_points) ) user_points <- t(as.data.frame(user_points))
      user_points <- as.h2o(user_points)
    }
    parms[["user_points"]] <- user_points
    # Set k
    if( !(missing(k)) && k!=as.integer(nrow(user_points)) ) {
      warning("Parameter k is not equal to the number of user-specified starting points. Ignoring k. Using specified starting points.")
    }
    parms[["k"]] <- as.numeric(nrow(user_points))
  
    } else if ( is.character(init) ) { # Furthest, Random, PlusPlus{
      parms[["user_points"]] <- NULL
  
    } else{
      stop ("argument init must be set to Furthest, Random, PlusPlus, or a valid set of user-defined starting points.")
    }
          """
  
  def help_afterword_for(algo):
      if algo == "aggregator":
          return """
              #' Retrieve an aggregated frame from an Aggregator model
              #'
              #' Retrieve an aggregated frame from the Aggregator model and use it to create a new frame.
              #'
              #' @param model an \linkS4class{H2OClusteringModel} corresponding from a \code{h2o.aggregator} call.
              #' @examples
              #' \donttest{
              #' library(h2o)
              #' h2o.init()
              #' df <- h2o.createFrame(rows=100, cols=5, categorical_fraction=0.6, integer_fraction=0,
              #'                       binary_fraction=0, real_range=100, integer_range=100, missing_fraction=0)
              #' target_num_exemplars=1000
              #' rel_tol_num_exemplars=0.5
              #' encoding="Eigen"
              #' agg <- h2o.aggregator(training_frame=df,
              #'                      target_num_exemplars=target_num_exemplars,
              #'                      rel_tol_num_exemplars=rel_tol_num_exemplars,
              #'                      categorical_encoding=encoding)
              #' # Use the aggregated frame to create a new dataframe
              #' new_df <- h2o.aggregated_frame(agg)
              #' }
              #' @export
              h2o.aggregated_frame <- function(model) {
                key <- model@model$aggregated_frame_id
                h2o.getFrame(key)
              }
          """
      if algo == "deeplearning":
          return """
              #' Anomaly Detection via H2O Deep Learning Model
              #'
              #' Detect anomalies in an H2O dataset using an H2O deep learning model with
              #' auto-encoding.
              #'
              #' @param object An \linkS4class{H2OAutoEncoderModel} object that represents the
              #'        model to be used for anomaly detection.
              #' @param data An H2OFrame object.
              #' @param per_feature Whether to return the per-feature squared reconstruction error
              #' @return Returns an H2OFrame object containing the
              #'         reconstruction MSE or the per-feature squared error.
              #' @seealso \code{\link{h2o.deeplearning}} for making an H2OAutoEncoderModel.
              #' @examples
              #' \donttest{
              #' library(h2o)
              #' h2o.init()
              #' prosPath = system.file("extdata", "prostate.csv", package = "h2o")
              #' prostate.hex = h2o.importFile(path = prosPath)
              #' prostate.dl = h2o.deeplearning(x = 3:9, training_frame = prostate.hex, autoencoder = TRUE,
              #'                                hidden = c(10, 10), epochs = 5)
              #' prostate.anon = h2o.anomaly(prostate.dl, prostate.hex)
              #' head(prostate.anon)
              #' prostate.anon.per.feature = h2o.anomaly(prostate.dl, prostate.hex, per_feature=TRUE)
              #' head(prostate.anon.per.feature)
              #' }
              #' @export
              h2o.anomaly <- function(object, data, per_feature=FALSE) {
                url <- paste0('Predictions/models/', object@model_id, '/frames/',h2o.getId(data))
                res <- .h2o.__remoteSend(url, method = "POST", reconstruction_error=TRUE, reconstruction_error_per_feature=per_feature)
                key <- res$model_metrics[[1L]]$predictions$frame_id$name
                h2o.getFrame(key)
              }
          """
      if algo == "deepwater":
          return """
              #' Determines whether Deep Water is available
              #'
              #' Ask the H2O server whether a Deep Water model can be built. (Depends on availability of native backends.)
              #' Returns TRUE if a Deep Water model can be built, or FALSE otherwise.
              #' @param h2oRestApiVersion (Optional) Specific version of the REST API to use.
              #' @export
              h2o.deepwater.available <- function(h2oRestApiVersion = .h2o.__REST_API_VERSION) {
                  res <- .h2o.__remoteSend(method = "GET",
                                           h2oRestApiVersion = h2oRestApiVersion,
                                           page = .h2o.__MODEL_BUILDERS("deepwater"))
                  visibility <- res$model_builders[["deepwater"]][["visibility"]]
                  if (visibility == "Experimental") {
                      print("Cannot build a Deep Water model - no backend found.")
                      available <- FALSE
                  } else {
                     available <- TRUE
                  }
                  return(available)
              }
          """
      if algo == "xgboost":
          return """
              #' Determines whether an XGBoost model can be built
              #'
              #' Ask the H2O server whether a XGBoost model can be built. (Depends on availability of native backend.)
              #' Returns True if a XGBoost model can be built, or False otherwise.
              #' @export
              h2o.xgboost.available <- function() {
                  if (!("XGBoost" %in% h2o.list_core_extensions())) {
                      print("Cannot build a XGboost model - no backend found.")
                      return(FALSE)
                  } else {
                      return(TRUE)
                  }
              }
          """
      if algo == "glm":
          return """
              #' Set betas of an existing H2O GLM Model
              #'
              #' This function allows setting betas of an existing glm model.
              #' @param model an \linkS4class{H2OModel} corresponding from a \code{h2o.glm} call.
              #' @param beta a new set of betas (a named vector)
              #' @export
              h2o.makeGLMModel <- function(model,beta) {
                 res = .h2o.__remoteSend(method="POST", .h2o.__GLMMakeModel, model=model@model_id, names = paste("[",paste(paste("\\\"",names(beta),"\\\"",sep=""), collapse=","),"]",sep=""), beta = paste("[",paste(as.vector(beta),collapse=","),"]",sep=""))
                 m <- h2o.getModel(model_id=res$model_id$name)
                 m@model$coefficients <- m@model$coefficients_table[,2]
                 names(m@model$coefficients) <- m@model$coefficients_table[,1]
                 m
              }
  
              #' Extract full regularization path from a GLM model
              #'
              #' Extract the full regularization path from a GLM model (assuming it was run with the lambda search option).
              #'
              #' @param model an \linkS4class{H2OModel} corresponding from a \code{h2o.glm} call.
              #' @export
              h2o.getGLMFullRegularizationPath <- function(model) {
                 res = .h2o.__remoteSend(method="GET", .h2o.__GLMRegPath, model=model@model_id)
                 colnames(res$coefficients) <- res$coefficient_names
                 if(!is.null(res$coefficients_std) && length(res$coefficients_std) > 0L) {
                   colnames(res$coefficients_std) <- res$coefficient_names
                 }
                 res
              }
  
              #' Compute weighted gram matrix.
              #'
              #' @param X an \linkS4class{H2OModel} corresponding to H2O framel.
              #' @param weights character corresponding to name of weight vector in frame.
              #' @param use_all_factor_levels logical flag telling h2o whether or not to skip first level of categorical variables during one-hot encoding.
              #' @param standardize logical flag telling h2o whether or not to standardize data
              #' @param skip_missing logical flag telling h2o whether skip rows with missing data or impute them with mean
              #' @export
              h2o.computeGram <- function(X,weights="", use_all_factor_levels=FALSE,standardize=TRUE,skip_missing=FALSE) {
                 res = .h2o.__remoteSend(method="GET", .h2o.__ComputeGram, X=h2o.getId(X),W=weights,use_all_factor_levels=use_all_factor_levels,standardize=standardize,skip_missing=skip_missing)
                 h2o.getFrame(res$destination_frame$name)
              }
  
              ##' Start an H2O Generalized Linear Model Job
              ##'
              ##' Creates a background H2O GLM job.
              ##' @inheritParams h2o.glm
              ##' @return Returns a \linkS4class{H2OModelFuture} class object.
              ##' @export
              #h2o.startGLMJob <- function(x, y, training_frame, model_id, validation_frame,
              #                    #AUTOGENERATED Params
              #                    max_iterations = 50,
              #                    beta_epsilon = 0,
              #                    solver = c("IRLSM", "L_BFGS"),
              #                    standardize = TRUE,
              #                    family = c("gaussian", "binomial", "poisson", "gamma", "tweedie"),
              #                    link = c("family_default", "identity", "logit", "log", "inverse", "tweedie"),
              #                    tweedie_variance_power = NaN,
              #                    tweedie_link_power = NaN,
              #                    alpha = 0.5,
              #                    prior = 0.0,
              #                    lambda = 1e-05,
              #                    lambda_search = FALSE,
              #                    nlambdas = -1,
              #                    lambda_min_ratio = 1.0,
              #                    nfolds = 0,
              #                    beta_constraints = NULL,
              #                    ...
              #                    )
              #{
              #  # if (!is.null(beta_constraints)) {
              #  #     if (!inherits(beta_constraints, "data.frame") && !is.H2OFrame("H2OFrame"))
              #  #       stop(paste("`beta_constraints` must be an H2OH2OFrame or R data.frame. Got: ", class(beta_constraints)))
              #  #     if (inherits(beta_constraints, "data.frame")) {
              #  #       beta_constraints <- as.h2o(beta_constraints)
              #  #     }
              #  # }
              #
              #  if (!is.H2OFrame(training_frame))
              #      tryCatch(training_frame <- h2o.getFrame(training_frame),
              #               error = function(err) {
              #                 stop("argument \"training_frame\" must be a valid H2OFrame or model ID")
              #              })
              #
              #    parms <- list()
              #    args <- .verify_dataxy(training_frame, x, y)
              #    parms$ignored_columns <- args$x_ignore
              #    parms$response_column <- args$y
              #    parms$training_frame  <- training_frame
              #    parms$beta_constraints <- beta_constraints
              #    if(!missing(model_id))
              #      parms$model_id <- model_id
              #    if(!missing(validation_frame))
              #      parms$validation_frame <- validation_frame
              #    if(!missing(max_iterations))
              #      parms$max_iterations <- max_iterations
              #    if(!missing(beta_epsilon))
              #      parms$beta_epsilon <- beta_epsilon
              #    if(!missing(solver))
              #      parms$solver <- solver
              #    if(!missing(standardize))
              #      parms$standardize <- standardize
              #    if(!missing(family))
              #      parms$family <- family
              #    if(!missing(link))
              #      parms$link <- link
              #    if(!missing(tweedie_variance_power))
              #      parms$tweedie_variance_power <- tweedie_variance_power
              #    if(!missing(tweedie_link_power))
              #      parms$tweedie_link_power <- tweedie_link_power
              #    if(!missing(alpha))
              #      parms$alpha <- alpha
              #    if(!missing(prior))
              #      parms$prior <- prior
              #    if(!missing(lambda))
              #      parms$lambda <- lambda
              #    if(!missing(lambda_search))
              #      parms$lambda_search <- lambda_search
              #    if(!missing(nlambdas))
              #      parms$nlambdas <- nlambdas
              #    if(!missing(lambda_min_ratio))
              #      parms$lambda_min_ratio <- lambda_min_ratio
              #    if(!missing(nfolds))
              #      parms$nfolds <- nfolds
              #
              #    .h2o.startModelJob('glm', parms, h2oRestApiVersion=.h2o.__REST_API_VERSION)
              #}
          """
      if algo == "glrm":
          return """
              #' Reconstruct Training Data via H2O GLRM Model
              #'
              #' Reconstruct the training data and impute missing values from the H2O GLRM model
              #' by computing the matrix product of X and Y, and transforming back to the original
              #' feature space by minimizing each column's loss function.
              #'
              #' @param object An \linkS4class{H2ODimReductionModel} object that represents the
              #'        model to be used for reconstruction.
              #' @param data An H2OFrame object representing the training data for the H2O GLRM model.
              #'        Used to set the domain of each column in the reconstructed frame.
              #' @param reverse_transform (Optional) A logical value indicating whether to reverse the
              #'        transformation from model-building by re-scaling columns and adding back the
              #'        offset to each column of the reconstructed frame.
              #' @return Returns an H2OFrame object containing the approximate reconstruction of the
              #'         training data;
              #' @seealso \code{\link{h2o.glrm}} for making an H2ODimReductionModel.
              #' @examples
              #' \donttest{
              #' library(h2o)
              #' h2o.init()
              #' irisPath <- system.file("extdata", "iris_wheader.csv", package="h2o")
              #' iris.hex <- h2o.uploadFile(path = irisPath)
              #' iris.glrm <- h2o.glrm(training_frame = iris.hex, k = 4, transform = "STANDARDIZE",
              #'                       loss = "Quadratic", multi_loss = "Categorical", max_iterations = 1000)
              #' iris.rec <- h2o.reconstruct(iris.glrm, iris.hex, reverse_transform = TRUE)
              #' head(iris.rec)
              #' }
              #' @export
              h2o.reconstruct <- function(object, data, reverse_transform=FALSE) {
                url <- paste0('Predictions/models/', object@model_id, '/frames/',h2o.getId(data))
                res <- .h2o.__remoteSend(url, method = "POST", reconstruct_train=TRUE, reverse_transform=reverse_transform)
                key <- res$model_metrics[[1L]]$predictions$frame_id$name
                h2o.getFrame(key)
              }
  
              #' Convert Archetypes to Features from H2O GLRM Model
              #'
              #' Project each archetype in an H2O GLRM model into the corresponding feature
              #' space from the H2O training frame.
              #'
              #' @param object An \linkS4class{H2ODimReductionModel} object that represents the
              #'        model containing archetypes to be projected.
              #' @param data An H2OFrame object representing the training data for the H2O GLRM model.
              #' @param reverse_transform (Optional) A logical value indicating whether to reverse the
              #'        transformation from model-building by re-scaling columns and adding back the
              #'        offset to each column of the projected archetypes.
              #' @return Returns an H2OFrame object containing the projection of the archetypes
              #'         down into the original feature space, where each row is one archetype.
              #' @seealso \code{\link{h2o.glrm}} for making an H2ODimReductionModel.
              #' @examples
              #' \donttest{
              #' library(h2o)
              #' h2o.init()
              #' irisPath <- system.file("extdata", "iris_wheader.csv", package="h2o")
              #' iris.hex <- h2o.uploadFile(path = irisPath)
              #' iris.glrm <- h2o.glrm(training_frame = iris.hex, k = 4, loss = "Quadratic",
              #'                       multi_loss = "Categorical", max_iterations = 1000)
              #' iris.parch <- h2o.proj_archetypes(iris.glrm, iris.hex)
              #' head(iris.parch)
              #' }
              #' @export
              h2o.proj_archetypes <- function(object, data, reverse_transform=FALSE) {
                url <- paste0('Predictions/models/', object@model_id, '/frames/',h2o.getId(data))
                res <- .h2o.__remoteSend(url, method = "POST", project_archetypes=TRUE, reverse_transform=reverse_transform)
                key <- res$model_metrics[[1L]]$predictions$frame_id$name
                h2o.getFrame(key)
              }
          """
  
  def algo_to_modelname(algo):
      if algo == "aggregator": return "H2O Aggregator Model"
      if algo == "deeplearning": return "Deep Learning - Neural Network"
      if algo == "deepwater": return "Deep Water - Neural Network"
      if algo == "xgboost": return "XGBoost"
      if algo == "drf": return "Random Forest Model in H2O"
      if algo == "gbm": return "Gradient Boosting Machine"
      if algo == "glm": return "H2O Generalized Linear Models"
      if algo == "glrm": return "Generalized Low Rank Model"
      if algo == "kmeans": return "KMeans Model in H2O"
      if algo == "naivebayes": return "Naive Bayes Model in H2O"
      if algo == "pca": return "Principal Components Analysis"
      if algo == "svd": return "Singular Value Decomposition"
      if algo == "stackedensemble": return "H2O Stacked Ensemble"
      return algo
  
  def indent(string, n):
      return " " * n + string
  
  def normalize_value(param, is_help = False):
      if param["name"] == "metalearner_params":
          return "NULL"
      if not(is_help) and param["type"][:4] == "enum":
          return "c(%s)" % ", ".join('"%s"' % p for p in param["values"])
      if param["default_value"] is None:
          if param["type"] in ["short", "int", "long", "double"]:
              return 0
          else:
              return "NULL"
      if not(is_help) and "[]" in param["type"]:
          if param["name"] == "base_models":
              return "list()"
          else:
              return "c(%s)" % ", ".join('%s' % p for p in param["default_value"])
      if param["type"] == "boolean":
          return str(param["default_value"]).upper()
      if param["type"] == "double":
          return '%.10g' % param["default_value"]
      return param["default_value"]
  
  # ----------------------------------------------------------------------------------------------------------------------
  #   MAIN:
  # ----------------------------------------------------------------------------------------------------------------------
  def main():
      bi.init("R", "../../../h2o-r/h2o-package/R", clear_dir=False)
  
      for name, mb in bi.model_builders().items():
          module = name
          file_name = name
          if name == "drf":
              module = "randomForest"
              file_name = "randomforest"
          if name == "naivebayes": module = "naiveBayes"
          if name == "stackedensemble": module = "stackedEnsemble"
          if name == "pca": module = "prcomp"
          bi.vprint("Generating model: " + name)
          bi.write_to_file("%s.R" % file_name, gen_module(mb, name, module))
  
  if __name__ == "__main__":
      main()
  