diff --git a/NAMESPACE b/NAMESPACE index d6e0239..a4f2fe0 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -52,6 +52,7 @@ export(listOMLEvaluationMeasures) export(listOMLFlows) export(listOMLRunEvaluations) export(listOMLRuns) +export(listOMLSetup) export(listOMLStudies) export(listOMLTaskTypes) export(listOMLTasks) diff --git a/R/download.R b/R/download.R index af1889f..9130c7a 100644 --- a/R/download.R +++ b/R/download.R @@ -116,7 +116,7 @@ doHTTRCall = function(method = "GET", url, query, body = NULL) { error = parseError(server.response) if (!is.null(error$message)) { - if (error$message == "No results") { + if (grepl("No results", error$message)) { messagef("Server response: %s", error$message) return(NULL) } diff --git a/R/helpers.R b/R/helpers.R index b8c916a..fec858a 100644 --- a/R/helpers.R +++ b/R/helpers.R @@ -101,14 +101,16 @@ assertSortedInt = function(x, ..., .var.name = vname(x)) { assertSorted(x, .var.name = .var.name) } -generateAPICall = function(api.call, task.id = NULL, flow.id = NULL, run.id = NULL, uploader.id = NULL, - task.type = NULL, number.of.instances = NULL, number.of.features = NULL, number.of.classes = NULL, +generateAPICall = function(api.call, task.id = NULL, flow.id = NULL, + setup.id = NULL, run.id = NULL, uploader.id = NULL, task.type = NULL, + number.of.instances = NULL, number.of.features = NULL, number.of.classes = NULL, number.of.missing.values = NULL, tag = NULL, data.name = NULL, data.tag = NULL, evaluation.measure = NULL, limit = NULL, offset = NULL, status = NULL) { assertString(api.call) task.id = collapseNotScientific(assertIntegerish(task.id, null.ok = TRUE)) flow.id = collapseNotScientific(assertIntegerish(flow.id, null.ok = TRUE)) + setup.id = collapseNotScientific(assertIntegerish(setup.id, null.ok = TRUE)) run.id = collapseNotScientific(assertIntegerish(run.id, null.ok = TRUE)) uploader.id = collapseNotScientific(assertIntegerish(uploader.id, null.ok = TRUE)) @@ -139,6 +141,7 @@ generateAPICall = function(api.call, task.id = NULL, flow.id = NULL, run.id = NU url.args = list( "task" = task.id, "flow" = flow.id, + "setup" = setup.id, "run" = run.id, "uploader" = uploader.id, "tag" = tag, diff --git a/R/listOMLSetup.R b/R/listOMLSetup.R new file mode 100644 index 0000000..ef42b3a --- /dev/null +++ b/R/listOMLSetup.R @@ -0,0 +1,91 @@ +.listOMLSetup = function(setup.id = NULL, flow.id = NULL, + limit = 1000, offset = NULL, verbosity = NULL) { + api.call = generateAPICall(api.call = "json/setup/list", + setup.id = setup.id, flow.id = flow.id, limit = limit, offset = offset) + + content = doAPICall(api.call, file = NULL, method = "GET", verbosity = verbosity) + if (is.null(content)) return(data.frame()) + + # Get entries, which are grouped by setup.id + setups = fromJSON(txt = content, simplifyVector = FALSE)$setups$setup + + setups = extractRecursiveList(setups) + if (length(setups) == 0) return(data.frame()) + # setups = lapply(names(setups), function(i) Map(c, setups[[i]], setup_id = i)) + + # We need to postprocess the list + setups = lapply(setups, function(setup) { + # for each setup.id check if it has one or more than one hyperparameters + if (is.null(names(setup))) { + # if there are more than two entries (hyperparameters) create a dataframe: + ret = rbindlist(lapply(setup, function(x) { + replace(x, which(vlapply(x, is.list)), NA_character_) + })) + } else { + # if there is only one entry (hyperparameter) do this to create a dataframe: + ret = setDF(replace(setup, which(vlapply(setup, is.list)), NA_character_)) + } + }) + # rbind the list + # FIXME: rbindlist does not work anymore therefore do this: + #nrows = vnapply(setups, nrow) + #setup.id = rep(names(nrows[nrows != 0]), nrows[nrows != 0]) + #setups = do.call(rbind, setups) + #setups$setup.id = setup.id + #setups = cbind(data.frame(setup.id = setup.id, stringsAsFactors = FALSE), setups) + #setups = rbindlist(setups, idcol = "setup_id") + setups = rbindlist(setups, fill = TRUE) + setups = lapply(setups, type.convert, as.is = TRUE) + setups = as.data.frame(setups, stringsAsFactors = FALSE) + + # # We need to postprocess the list + # setups = lapply(names(setups), function(i) { + # if (is.null(names(setups[[i]]))) { + # ret = Map(c, setups[[i]], setup_id = i) + # lapply(ret, function(x) replace(x, which(vlapply(x, is.list)), NA_character_)) + # } else { + # list(c(replace(x, which(vlapply(x, is.list)), NA_character_), setup_id = i)) + # } + # }) + # # rbind the list + # setups = rbindlist(unlist(setups, recursive = FALSE)) + + cn = c("setup_id", "flow_id", "parameter_name", "data_type", "default_value", "value") + setups = setups[, cn] + names(setups) = convertNamesOMLToR(names(setups)) + return(setups) +} + +extractRecursiveList = function(l) { + if ("parameter" %in% names(l)) { + setupid = list(setup_id = l$setup_id) + lapply(l$parameter, function(x) c(setupid, x)) + } else { + if (is.list(l)) { + unlist(lapply(l, function(i) { + extractRecursiveList(i) + }), recursive = FALSE) + } else { + return(data.table()) + } + } +} + +#' @title List hyperparameters of Flows. +#' +#' @description +#' Lists hyperparameter settings for flows. +#' +#' @template note_memoise +#' +#' @param setup.id [\code{integer(1)}]\cr +#' ID of the setup (which is basically an ID for the parameter configuration). +#' @template arg_flow.id +#' @template arg_limit +#' @template arg_offset +#' @template arg_verbosity +#' @return [\code{data.frame}]. +#' @family listing functions +#' @export +#' @example inst/examples/listOMLSetup.R +listOMLSetup = memoise(.listOMLSetup) diff --git a/inst/examples/listOMLSetup.R b/inst/examples/listOMLSetup.R new file mode 100644 index 0000000..d458d6b --- /dev/null +++ b/inst/examples/listOMLSetup.R @@ -0,0 +1,3 @@ +\dontrun{ + listOMLSetup(limit = 1) +} diff --git a/man/listOMLDataSetQualities.Rd b/man/listOMLDataSetQualities.Rd index 59103dc..79e84a4 100644 --- a/man/listOMLDataSetQualities.Rd +++ b/man/listOMLDataSetQualities.Rd @@ -36,7 +36,7 @@ Other listing functions: \code{\link{listOMLDataSets}}, \code{\link{listOMLEstimationProcedures}}, \code{\link{listOMLEvaluationMeasures}}, \code{\link{listOMLFlows}}, \code{\link{listOMLRuns}}, - \code{\link{listOMLStudies}}, + \code{\link{listOMLSetup}}, \code{\link{listOMLStudies}}, \code{\link{listOMLTaskTypes}}, \code{\link{listOMLTasks}} } diff --git a/man/listOMLDataSets.Rd b/man/listOMLDataSets.Rd index 426fcd2..9c27a4a 100644 --- a/man/listOMLDataSets.Rd +++ b/man/listOMLDataSets.Rd @@ -81,7 +81,7 @@ Other listing functions: \code{\link{listOMLDataSetQualities}}, \code{\link{listOMLEstimationProcedures}}, \code{\link{listOMLEvaluationMeasures}}, \code{\link{listOMLFlows}}, \code{\link{listOMLRuns}}, - \code{\link{listOMLStudies}}, + \code{\link{listOMLSetup}}, \code{\link{listOMLStudies}}, \code{\link{listOMLTaskTypes}}, \code{\link{listOMLTasks}} diff --git a/man/listOMLEstimationProcedures.Rd b/man/listOMLEstimationProcedures.Rd index c275396..bb5051e 100644 --- a/man/listOMLEstimationProcedures.Rd +++ b/man/listOMLEstimationProcedures.Rd @@ -37,7 +37,7 @@ Other listing functions: \code{\link{listOMLDataSetQualities}}, \code{\link{listOMLDataSets}}, \code{\link{listOMLEvaluationMeasures}}, \code{\link{listOMLFlows}}, \code{\link{listOMLRuns}}, - \code{\link{listOMLStudies}}, + \code{\link{listOMLSetup}}, \code{\link{listOMLStudies}}, \code{\link{listOMLTaskTypes}}, \code{\link{listOMLTasks}} } diff --git a/man/listOMLEvaluationMeasures.Rd b/man/listOMLEvaluationMeasures.Rd index c63283e..84007ef 100644 --- a/man/listOMLEvaluationMeasures.Rd +++ b/man/listOMLEvaluationMeasures.Rd @@ -37,7 +37,7 @@ Other listing functions: \code{\link{listOMLDataSetQualities}}, \code{\link{listOMLDataSets}}, \code{\link{listOMLEstimationProcedures}}, \code{\link{listOMLFlows}}, \code{\link{listOMLRuns}}, - \code{\link{listOMLStudies}}, + \code{\link{listOMLSetup}}, \code{\link{listOMLStudies}}, \code{\link{listOMLTaskTypes}}, \code{\link{listOMLTasks}} } diff --git a/man/listOMLFlows.Rd b/man/listOMLFlows.Rd index 3600dd0..0e183bd 100644 --- a/man/listOMLFlows.Rd +++ b/man/listOMLFlows.Rd @@ -54,7 +54,8 @@ Other listing functions: \code{\link{listOMLDataSetQualities}}, \code{\link{listOMLDataSets}}, \code{\link{listOMLEstimationProcedures}}, \code{\link{listOMLEvaluationMeasures}}, - \code{\link{listOMLRuns}}, \code{\link{listOMLStudies}}, + \code{\link{listOMLRuns}}, \code{\link{listOMLSetup}}, + \code{\link{listOMLStudies}}, \code{\link{listOMLTaskTypes}}, \code{\link{listOMLTasks}} diff --git a/man/listOMLRuns.Rd b/man/listOMLRuns.Rd index 943f002..550a746 100644 --- a/man/listOMLRuns.Rd +++ b/man/listOMLRuns.Rd @@ -68,7 +68,8 @@ Other listing functions: \code{\link{listOMLDataSetQualities}}, \code{\link{listOMLDataSets}}, \code{\link{listOMLEstimationProcedures}}, \code{\link{listOMLEvaluationMeasures}}, - \code{\link{listOMLFlows}}, \code{\link{listOMLStudies}}, + \code{\link{listOMLFlows}}, \code{\link{listOMLSetup}}, + \code{\link{listOMLStudies}}, \code{\link{listOMLTaskTypes}}, \code{\link{listOMLTasks}} diff --git a/man/listOMLSetup.Rd b/man/listOMLSetup.Rd new file mode 100644 index 0000000..3e6e3ae --- /dev/null +++ b/man/listOMLSetup.Rd @@ -0,0 +1,60 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/listOMLSetup.R +\name{listOMLSetup} +\alias{listOMLSetup} +\title{List hyperparameters of Flows.} +\usage{ +listOMLSetup(setup.id = NULL, flow.id = NULL, limit = 1000, + offset = NULL, verbosity = NULL) +} +\arguments{ +\item{setup.id}{[\code{integer(1)}]\cr +ID of the setup (which is basically an ID for the parameter configuration).} + +\item{flow.id}{[\code{integer(1)}]\cr +ID of the implementation of an OpenML flow.} + +\item{limit}{[\code{numeric(1)}]\cr +Optional. The maximum number of entries to return. +Without specifying \code{offset}, it returns the first '\code{limit}' entries. +Setting \code{limit = NULL} returns all available entries.} + +\item{offset}{[\code{numeric(1)}]\cr +Optional. The offset to start from. +Should be indices starting from 0, which do not refer to IDs. +Is ignored when no \code{limit} is given.} + +\item{verbosity}{[\code{integer(1)}]\cr +Print verbose output on console? Possible values are:\cr +\code{0}: normal output,\cr +\code{1}: info output,\cr +\code{2}: debug output.\cr +Default is set via \code{\link{setOMLConfig}}.} +} +\value{ +[\code{data.frame}]. +} +\description{ +Lists hyperparameter settings for flows. +} +\note{ +This function is memoised. I.e., if you call this function twice in a running R session, +the first call will query the server and store the results in memory while the second and all subsequent calls will return +the cached results from the first call. +You can reset the cache by calling \code{\link[memoise]{forget}} on the function manually. +} +\examples{ +\dontrun{ + listOMLSetup(limit = 1) +} +} +\seealso{ +Other listing functions: \code{\link{listOMLDataSetQualities}}, + \code{\link{listOMLDataSets}}, + \code{\link{listOMLEstimationProcedures}}, + \code{\link{listOMLEvaluationMeasures}}, + \code{\link{listOMLFlows}}, \code{\link{listOMLRuns}}, + \code{\link{listOMLStudies}}, + \code{\link{listOMLTaskTypes}}, + \code{\link{listOMLTasks}} +} diff --git a/man/listOMLStudies.Rd b/man/listOMLStudies.Rd index 384fa2a..cc1b513 100644 --- a/man/listOMLStudies.Rd +++ b/man/listOMLStudies.Rd @@ -26,6 +26,7 @@ Other listing functions: \code{\link{listOMLDataSetQualities}}, \code{\link{listOMLEstimationProcedures}}, \code{\link{listOMLEvaluationMeasures}}, \code{\link{listOMLFlows}}, \code{\link{listOMLRuns}}, + \code{\link{listOMLSetup}}, \code{\link{listOMLTaskTypes}}, \code{\link{listOMLTasks}} } diff --git a/man/listOMLTaskTypes.Rd b/man/listOMLTaskTypes.Rd index f9bf34d..0389a23 100644 --- a/man/listOMLTaskTypes.Rd +++ b/man/listOMLTaskTypes.Rd @@ -38,7 +38,8 @@ Other listing functions: \code{\link{listOMLDataSetQualities}}, \code{\link{listOMLEstimationProcedures}}, \code{\link{listOMLEvaluationMeasures}}, \code{\link{listOMLFlows}}, \code{\link{listOMLRuns}}, - \code{\link{listOMLStudies}}, \code{\link{listOMLTasks}} + \code{\link{listOMLSetup}}, \code{\link{listOMLStudies}}, + \code{\link{listOMLTasks}} Other task-related functions: \code{\link{convertOMLTaskToMlr}}, \code{\link{deleteOMLObject}}, \code{\link{getOMLTask}}, diff --git a/man/listOMLTasks.Rd b/man/listOMLTasks.Rd index 018b034..ecc4011 100644 --- a/man/listOMLTasks.Rd +++ b/man/listOMLTasks.Rd @@ -104,7 +104,7 @@ Other listing functions: \code{\link{listOMLDataSetQualities}}, \code{\link{listOMLEstimationProcedures}}, \code{\link{listOMLEvaluationMeasures}}, \code{\link{listOMLFlows}}, \code{\link{listOMLRuns}}, - \code{\link{listOMLStudies}}, + \code{\link{listOMLSetup}}, \code{\link{listOMLStudies}}, \code{\link{listOMLTaskTypes}} Other task-related functions: \code{\link{convertOMLTaskToMlr}}, diff --git a/tests/testthat/test_server_listOMLSetup.R b/tests/testthat/test_server_listOMLSetup.R new file mode 100644 index 0000000..a0b7aa8 --- /dev/null +++ b/tests/testthat/test_server_listOMLSetup.R @@ -0,0 +1,44 @@ +context("listOMLSetup") + +skip_on_cran() + +test_that("listOMLSetup", { + exp.cols = c("setup.id", "flow.id", "parameter.name", "data.type", "default.value", "value") + df = .listOMLSetup(limit = 1) + expect_data_frame(df) + if (nrow(df) > 0) { + expect_subset(exp.cols, colnames(df)) + expect_true(length(unique(df$setup.id)) == 1) + } + + df = .listOMLSetup(limit = 10) + expect_data_frame(df) + if (nrow(df) > 0) { + expect_subset(exp.cols, colnames(df)) + expect_true(length(unique(df$setup.id)) <= 10) + } + + with_main_server({ + df = .listOMLSetup(limit = 10) + expect_data_frame(df) + if (nrow(df) > 0) { + expect_subset(exp.cols, colnames(df)) + expect_true(length(unique(df$setup.id)) <= 10) + } + + df = .listOMLSetup(flow.id = 5685) + expect_data_frame(df) + if (nrow(df) > 0) { + expect_subset(exp.cols, colnames(df)) + expect_true(unique(df$flow.id) == 5685) + } + + df = .listOMLSetup(setup.id = 9008) + expect_data_frame(df) + if (nrow(df) > 0) { + expect_subset(exp.cols, colnames(df)) + expect_true(unique(df$setup.id) == 9008) + expect_true(length(unique(df$flow.id)) == 1) + } + }) +})