diff --git a/DESCRIPTION b/DESCRIPTION index 4f7a55d..6b740e3 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -15,7 +15,7 @@ Description: A set of utility functions for accessing and working with License: MIT + file LICENSE Encoding: UTF-8 Roxygen: list(markdown = TRUE) -RoxygenNote: 7.3.1 +RoxygenNote: 7.3.2 Config/testthat/edition: 3 URL: https://github.com/hubverse-org/hubData BugReports: https://github.com/hubverse-org/hubData/issues diff --git a/NEWS.md b/NEWS.md index 82e2b3c..cd718f6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # hubData (development version) +* Support the determination of hub schema from v4 configuration files (#63). Also fixes bug in `create_hub_schema()` where `output_type_id` data type was being incorrectly auto-determined as `logical` when only point estimate output types where being collected by a hub. Now `character` data type is returned for the `output_type_id` for all schema versions in such situations when auto-determined. + # hubData 1.2.3 * Fix bug in `create_hub_schema()` where `output_type_id` data type was being incorrectly determined as `Date` instead of `character` (Reported in https://github.com/reichlab/variant-nowcast-hub/pull/87#issuecomment-2387372238). diff --git a/R/create_hub_schema.R b/R/create_hub_schema.R index 433d10f..73304c6 100644 --- a/R/create_hub_schema.R +++ b/R/create_hub_schema.R @@ -15,6 +15,9 @@ #' the `output_type_id` data type automatically from the `tasks.json` #' config file as the simplest data type required to represent all output #' type ID values across all output types in the hub. +#' When only point estimate output types (where `output_type_id`s are `NA`,) are +#' being collected by a hub, the `output_type_id` column is assigned a `character` +#' data type when auto-determined. #' Other data type values can be used to override automatic determination. #' Note that attempting to coerce `output_type_id` to a data type that is #' not valid for the data (e.g. trying to coerce`"character"` values to @@ -149,6 +152,8 @@ get_output_type_id_type <- function(config_tasks) { # retired config_tid <- hubUtils::get_config_tid(config_tasks = config_tasks) + # Get the values of all output type id values across all output types and rounds + # in the hub config values <- purrr::map( config_tasks[["rounds"]], function(x) { @@ -203,7 +208,12 @@ get_output_type_id_type <- function(config_tasks) { # `get_data_type()` which checks characters for ISO date format. # Should Dates be introduced as output type id values in the future, # this will need to be revisited. - typeof(c(values, sample_values)) + type <- typeof(c(values, sample_values)) + + if (type %in% c("NULL", "logical")) { + type <- "character" + } + type } diff --git a/R/reexports-hubUtils.R b/R/reexports-hubUtils.R new file mode 100644 index 0000000..faff4c0 --- /dev/null +++ b/R/reexports-hubUtils.R @@ -0,0 +1,15 @@ +#' @export +#' @importFrom hubUtils as_model_out_tbl +hubUtils::as_model_out_tbl + +#' @export +#' @importFrom hubUtils validate_model_out_tbl +hubUtils::validate_model_out_tbl + +#' @export +#' @importFrom hubUtils model_id_merge +hubUtils::model_id_merge + +#' @export +#' @importFrom hubUtils model_id_split +hubUtils::model_id_split diff --git a/R/utils-hubUtils.R b/R/utils-hubUtils.R deleted file mode 100644 index 0bd4919..0000000 --- a/R/utils-hubUtils.R +++ /dev/null @@ -1,39 +0,0 @@ -#' Convert model output to a `model_out_tbl` class object -#' -#' See [hubUtils::as_model_out_tbl()] for details. -#' -#' @name as_model_out_tbl -#' @inherit hubUtils::as_model_out_tbl return examples -#' @export -#' @importFrom hubUtils as_model_out_tbl -NULL - -#' Validate a `model_out_tbl` object -#' -#' See [hubUtils::validate_model_out_tbl()] for details. -#' -#' @name validate_model_out_tbl -#' @inherit hubUtils::validate_model_out_tbl return examples -#' @export -#' @importFrom hubUtils validate_model_out_tbl -NULL - -#' Merge model output tbl `model_id` column -#' -#' See [hubUtils::model_id_merge()] for details. -#' -#' @name model_id_merge -#' @inherit hubUtils::model_id_merge return examples -#' @export -#' @importFrom hubUtils model_id_merge -NULL - -#' Split model output tbl `model_id` column -#' -#' See [hubUtils::model_id_merge()] for details. -#' -#' @name model_id_split -#' @inherit hubUtils::model_id_merge return examples -#' @export -#' @importFrom hubUtils model_id_split -NULL diff --git a/man/as_model_out_tbl.Rd b/man/as_model_out_tbl.Rd deleted file mode 100644 index 87a3ce5..0000000 --- a/man/as_model_out_tbl.Rd +++ /dev/null @@ -1,23 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils-hubUtils.R -\name{as_model_out_tbl} -\alias{as_model_out_tbl} -\title{Convert model output to a \code{model_out_tbl} class object} -\value{ -A \code{model_out_tbl} class object. -} -\description{ -See \code{\link[hubUtils:as_model_out_tbl]{hubUtils::as_model_out_tbl()}} for details. -} -\examples{ -if (requireNamespace("hubData", quietly = TRUE)) { - library(dplyr) - hub_path <- system.file("testhubs/flusight", package = "hubUtils") - hub_con <- hubData::connect_hub(hub_path) - hub_con \%>\% - filter(output_type == "quantile", location == "US") \%>\% - collect() \%>\% - filter(forecast_date == max(forecast_date)) \%>\% - as_model_out_tbl() -} -} diff --git a/man/coerce_to_hub_schema.Rd b/man/coerce_to_hub_schema.Rd index d58297e..5d2d0f2 100644 --- a/man/coerce_to_hub_schema.Rd +++ b/man/coerce_to_hub_schema.Rd @@ -35,6 +35,9 @@ not set in the config, the argument falls back to \code{"auto"} which determines the \code{output_type_id} data type automatically from the \code{tasks.json} config file as the simplest data type required to represent all output type ID values across all output types in the hub. +When only point estimate output types (where \code{output_type_id}s are \code{NA},) are +being collected by a hub, the \code{output_type_id} column is assigned a \code{character} +data type when auto-determined. Other data type values can be used to override automatic determination. Note that attempting to coerce \code{output_type_id} to a data type that is not valid for the data (e.g. trying to coerce\code{"character"} values to diff --git a/man/connect_hub.Rd b/man/connect_hub.Rd index 0327b25..17c304c 100644 --- a/man/connect_hub.Rd +++ b/man/connect_hub.Rd @@ -48,6 +48,9 @@ not set in the config, the argument falls back to \code{"auto"} which determines the \code{output_type_id} data type automatically from the \code{tasks.json} config file as the simplest data type required to represent all output type ID values across all output types in the hub. +When only point estimate output types (where \code{output_type_id}s are \code{NA},) are +being collected by a hub, the \code{output_type_id} column is assigned a \code{character} +data type when auto-determined. Other data type values can be used to override automatic determination. Note that attempting to coerce \code{output_type_id} to a data type that is not valid for the data (e.g. trying to coerce\code{"character"} values to diff --git a/man/create_hub_schema.Rd b/man/create_hub_schema.Rd index de2bf04..8df50f0 100644 --- a/man/create_hub_schema.Rd +++ b/man/create_hub_schema.Rd @@ -27,6 +27,9 @@ not set in the config, the argument falls back to \code{"auto"} which determines the \code{output_type_id} data type automatically from the \code{tasks.json} config file as the simplest data type required to represent all output type ID values across all output types in the hub. +When only point estimate output types (where \code{output_type_id}s are \code{NA},) are +being collected by a hub, the \code{output_type_id} column is assigned a \code{character} +data type when auto-determined. Other data type values can be used to override automatic determination. Note that attempting to coerce \code{output_type_id} to a data type that is not valid for the data (e.g. trying to coerce\code{"character"} values to diff --git a/man/model_id_merge.Rd b/man/model_id_merge.Rd deleted file mode 100644 index 9862eb3..0000000 --- a/man/model_id_merge.Rd +++ /dev/null @@ -1,39 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils-hubUtils.R -\name{model_id_merge} -\alias{model_id_merge} -\title{Merge model output tbl \code{model_id} column} -\value{ -\code{tbl} with either \code{team_abbr} and \code{model_abbr} merged into a single \code{model_id} -column or \code{model_id} split into columns \code{team_abbr} and \code{model_abbr}. - -a \link[tibble:tibble]{tibble} with \code{model_id} column split into separate -\code{team_abbr} and \code{model_abbr} columns -} -\description{ -See \code{\link[hubUtils:model_id_merge]{hubUtils::model_id_merge()}} for details. -} -\examples{ -if (requireNamespace("hubData", quietly = TRUE)) { - hub_con <- hubData::connect_hub(system.file("testhubs/flusight", package = "hubUtils")) - tbl <- hub_con \%>\% - dplyr::filter(output_type == "quantile", location == "US") \%>\% - dplyr::collect() \%>\% - dplyr::filter(forecast_date == max(forecast_date)) - - tbl_split <- model_id_split(tbl) - tbl_split - - # Merge model_id - tbl_merged <- model_id_merge(tbl_split) - tbl_merged - - # Split / Merge using custom separator - tbl_sep <- tbl - tbl_sep$model_id <- gsub("-", "_", tbl_sep$model_id) - tbl_sep <- model_id_split(tbl_sep, sep = "_") - tbl_sep - tbl_sep <- model_id_merge(tbl_sep, sep = "_") - tbl_sep -} -} diff --git a/man/model_id_split.Rd b/man/model_id_split.Rd deleted file mode 100644 index 701b953..0000000 --- a/man/model_id_split.Rd +++ /dev/null @@ -1,39 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils-hubUtils.R -\name{model_id_split} -\alias{model_id_split} -\title{Split model output tbl \code{model_id} column} -\value{ -\code{tbl} with either \code{team_abbr} and \code{model_abbr} merged into a single \code{model_id} -column or \code{model_id} split into columns \code{team_abbr} and \code{model_abbr}. - -a \link[tibble:tibble]{tibble} with \code{model_id} column split into separate -\code{team_abbr} and \code{model_abbr} columns -} -\description{ -See \code{\link[hubUtils:model_id_merge]{hubUtils::model_id_merge()}} for details. -} -\examples{ -if (requireNamespace("hubData", quietly = TRUE)) { - hub_con <- hubData::connect_hub(system.file("testhubs/flusight", package = "hubUtils")) - tbl <- hub_con \%>\% - dplyr::filter(output_type == "quantile", location == "US") \%>\% - dplyr::collect() \%>\% - dplyr::filter(forecast_date == max(forecast_date)) - - tbl_split <- model_id_split(tbl) - tbl_split - - # Merge model_id - tbl_merged <- model_id_merge(tbl_split) - tbl_merged - - # Split / Merge using custom separator - tbl_sep <- tbl - tbl_sep$model_id <- gsub("-", "_", tbl_sep$model_id) - tbl_sep <- model_id_split(tbl_sep, sep = "_") - tbl_sep - tbl_sep <- model_id_merge(tbl_sep, sep = "_") - tbl_sep -} -} diff --git a/man/reexports.Rd b/man/reexports.Rd new file mode 100644 index 0000000..4bc83e0 --- /dev/null +++ b/man/reexports.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/reexports-hubUtils.R +\docType{import} +\name{reexports} +\alias{reexports} +\alias{as_model_out_tbl} +\alias{validate_model_out_tbl} +\alias{model_id_merge} +\alias{model_id_split} +\title{Objects exported from other packages} +\keyword{internal} +\description{ +These objects are imported from other packages. Follow the links +below to see their documentation. + +\describe{ + \item{hubUtils}{\code{\link[hubUtils]{as_model_out_tbl}}, \code{\link[hubUtils]{model_id_merge}}, \code{\link[hubUtils:model_id_merge]{model_id_split}}, \code{\link[hubUtils]{validate_model_out_tbl}}} +}} + diff --git a/man/validate_model_out_tbl.Rd b/man/validate_model_out_tbl.Rd deleted file mode 100644 index cafaae3..0000000 --- a/man/validate_model_out_tbl.Rd +++ /dev/null @@ -1,26 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils-hubUtils.R -\name{validate_model_out_tbl} -\alias{validate_model_out_tbl} -\title{Validate a \code{model_out_tbl} object} -\value{ -If valid, returns a \code{model_out_tbl} class object. Otherwise, throws an -error. -} -\description{ -See \code{\link[hubUtils:validate_model_out_tbl]{hubUtils::validate_model_out_tbl()}} for details. -} -\examples{ -if (requireNamespace("hubData", quietly = TRUE)) { - library(dplyr) - hub_path <- system.file("testhubs/flusight", package = "hubUtils") - hub_con <- hubData::connect_hub(hub_path) - md_out <- hub_con \%>\% - filter(output_type == "quantile", location == "US") \%>\% - collect() \%>\% - filter(forecast_date == max(forecast_date)) \%>\% - as_model_out_tbl() - - validate_model_out_tbl(md_out) -} -} diff --git a/tests/testthat/test-create_hub_schema.R b/tests/testthat/test-create_hub_schema.R index 0fab3e4..a77162a 100644 --- a/tests/testthat/test-create_hub_schema.R +++ b/tests/testthat/test-create_hub_schema.R @@ -61,6 +61,14 @@ test_that("create_hub_schema works correctly", { output_type_id = "character", value = "integer", model_id = "character" ) ) + + # Validate that configs with only point estimate output types returns character (the default) + # not logical + config_tasks <- hubUtils::read_config_file(test_path("testdata/configs/v3-tasks-point.json")) + expect_equal( + create_hub_schema(config_tasks)$GetFieldByName("output_type_id")$ToString(), + "output_type_id: string" + ) }) test_that("create_hub_schema works with sample output types", { @@ -135,3 +143,30 @@ test_that("create_hub_schema works with config output_type_id_datatype", { "nowcast_date: date32[day]\ntarget_date: date32[day]\nlocation: string\nclade: string\noutput_type: string\noutput_type_id: string\nvalue: double\nmodel_id: string" ) }) + +test_that("create_hub_schema works with v4 output_type_id configuration", { + config_tasks <- suppressWarnings( + hubUtils::read_config_file(test_path("testdata/configs/v4-tasks.json")) + ) + expect_equal( + create_hub_schema(config_tasks)$ToString(), + "forecast_date: date32[day]\ntarget: string\nhorizon: int32\nlocation: string\ntarget_date: date32[day]\noutput_type: string\noutput_type_id: string\nvalue: double\nmodel_id: string" + ) + + # Validate that configs with only point estimate output types returns character (the default) + config_tasks <- suppressWarnings( + hubUtils::read_config_file(test_path("testdata/configs/v4-tasks-point.json")) + ) + expect_equal( + create_hub_schema(config_tasks)$GetFieldByName("output_type_id")$ToString(), + "output_type_id: string" + ) + # Ensure `output_type_id_datatype` arg works with v4 configs + expect_equal( + create_hub_schema( + config_tasks, + output_type_id_datatype = "double" + )$GetFieldByName("output_type_id")$ToString(), + "output_type_id: double" + ) +}) diff --git a/tests/testthat/testdata/configs/v3-tasks-point.json b/tests/testthat/testdata/configs/v3-tasks-point.json new file mode 100644 index 0000000..020c929 --- /dev/null +++ b/tests/testthat/testdata/configs/v3-tasks-point.json @@ -0,0 +1,88 @@ +{ + "schema_version": "https://raw.githubusercontent.com/hubverse-org/schemas/main/v3.0.1/tasks-schema.json", + "rounds": [{ + "round_id_from_variable": true, + "round_id": "forecast_date", + "model_tasks": [{ + "task_ids": { + "forecast_date": { + "required": null, + "optional": [ + "2022-12-12", "2022-12-19", "2022-12-26", "2023-01-02", "2023-01-09", + "2023-01-16", "2023-01-23", "2023-01-30", "2023-02-06", "2023-02-13", + "2023-02-20", "2023-02-27", "2023-03-06", "2023-03-13", "2023-03-20", + "2023-03-27", "2023-04-03", "2023-04-10", "2023-04-17", "2023-04-24", + "2023-05-01" + ] + }, + "target": { + "required": null, + "optional": ["wk ahead inc flu hosp"] + }, + "horizon": { + "required": [2], + "optional": [1] + }, + "location": { + "required": ["US"], + "optional": [ + "01", + "02" + ] + }, + "target_date": { + "required": null, + "optional": [ + "2022-12-19", "2022-12-26", "2023-01-02", "2023-01-09", + "2023-01-16", "2023-01-23", "2023-01-30", "2023-02-06", "2023-02-13", + "2023-02-20", "2023-02-27", "2023-03-06", "2023-03-13", "2023-03-20", + "2023-03-27", "2023-04-03", "2023-04-10", "2023-04-17", "2023-04-24", + "2023-05-01", "2023-05-08", "2023-05-15" + ] + } + }, + "output_type": { + "median": { + "output_type_id": { + "required": null, + "optional": ["NA"] + }, + "value": { + "type": "double", + "minimum": 0 + } + }, + "mean": { + "output_type_id": { + "required": null, + "optional": ["NA"] + }, + "value": { + "type": "double", + "minimum": 0 + } + } + }, + "target_metadata": [{ + "target_id": "wk ahead inc flu hosp", + "target_name": "weekly influenza hospitalization incidence", + "target_units": "rate per 100,000 population", + "target_keys": { + "target": "wk ahead inc flu hosp" + }, + "target_type": "discrete", + "description": "This target represents the counts of new hospitalizations per horizon week.", + "is_step_ahead": true, + "time_unit": "week" + }] + }], + "submissions_due": { + "relative_to": "forecast_date", + "start": -6, + "end": 2 + }, + "derived_task_ids": ["target_date"] + } + + ] +} diff --git a/tests/testthat/testdata/configs/v4-tasks-point.json b/tests/testthat/testdata/configs/v4-tasks-point.json new file mode 100644 index 0000000..fd1ecbc --- /dev/null +++ b/tests/testthat/testdata/configs/v4-tasks-point.json @@ -0,0 +1,88 @@ +{ + "schema_version": "https://raw.githubusercontent.com/hubverse-org/schemas/main/v4.0.0/tasks-schema.json", + "rounds": [{ + "round_id_from_variable": true, + "round_id": "forecast_date", + "model_tasks": [{ + "task_ids": { + "forecast_date": { + "required": null, + "optional": [ + "2022-12-12", "2022-12-19", "2022-12-26", "2023-01-02", "2023-01-09", + "2023-01-16", "2023-01-23", "2023-01-30", "2023-02-06", "2023-02-13", + "2023-02-20", "2023-02-27", "2023-03-06", "2023-03-13", "2023-03-20", + "2023-03-27", "2023-04-03", "2023-04-10", "2023-04-17", "2023-04-24", + "2023-05-01" + ] + }, + "target": { + "required": null, + "optional": ["wk ahead inc flu hosp"] + }, + "horizon": { + "required": [2], + "optional": [1] + }, + "location": { + "required": ["US"], + "optional": [ + "01", + "02" + ] + }, + "target_date": { + "required": null, + "optional": [ + "2022-12-19", "2022-12-26", "2023-01-02", "2023-01-09", + "2023-01-16", "2023-01-23", "2023-01-30", "2023-02-06", "2023-02-13", + "2023-02-20", "2023-02-27", "2023-03-06", "2023-03-13", "2023-03-20", + "2023-03-27", "2023-04-03", "2023-04-10", "2023-04-17", "2023-04-24", + "2023-05-01", "2023-05-08", "2023-05-15" + ] + } + }, + "output_type": { + "median": { + "output_type_id": { + "required": null + }, + "is_required": true, + "value": { + "type": "double", + "minimum": 0 + } + }, + "mean": { + "output_type_id": { + "required": null + }, + "is_required": true, + "value": { + "type": "double", + "minimum": 0 + } + } + }, + "target_metadata": [{ + "target_id": "wk ahead inc flu hosp", + "target_name": "weekly influenza hospitalization incidence", + "target_units": "rate per 100,000 population", + "target_keys": { + "target": "wk ahead inc flu hosp" + }, + "target_type": "discrete", + "description": "This target represents the counts of new hospitalizations per horizon week.", + "is_step_ahead": true, + "time_unit": "week" + }] + }], + "submissions_due": { + "relative_to": "forecast_date", + "start": -6, + "end": 2 + }, + "derived_task_ids": ["target_date"] + } + + ] +} diff --git a/tests/testthat/testdata/configs/v4-tasks.json b/tests/testthat/testdata/configs/v4-tasks.json new file mode 100644 index 0000000..03f7f8a --- /dev/null +++ b/tests/testthat/testdata/configs/v4-tasks.json @@ -0,0 +1,154 @@ +{ + "schema_version": "https://raw.githubusercontent.com/hubverse-org/schemas/main/v4.0.0/tasks-schema.json", + "rounds": [{ + "round_id_from_variable": true, + "round_id": "forecast_date", + "model_tasks": [{ + "task_ids": { + "forecast_date": { + "required": null, + "optional": [ + "2022-12-12", "2022-12-19", "2022-12-26", "2023-01-02", "2023-01-09", + "2023-01-16", "2023-01-23", "2023-01-30", "2023-02-06", "2023-02-13", + "2023-02-20", "2023-02-27", "2023-03-06", "2023-03-13", "2023-03-20", + "2023-03-27", "2023-04-03", "2023-04-10", "2023-04-17", "2023-04-24", + "2023-05-01" + ] + }, + "target": { + "required": null, + "optional": ["wk ahead inc flu hosp"] + }, + "horizon": { + "required": [2], + "optional": [1] + }, + "location": { + "required": ["US"], + "optional": [ + "01", + "02" + ] + }, + "target_date": { + "required": null, + "optional": [ + "2022-12-19", "2022-12-26", "2023-01-02", "2023-01-09", + "2023-01-16", "2023-01-23", "2023-01-30", "2023-02-06", "2023-02-13", + "2023-02-20", "2023-02-27", "2023-03-06", "2023-03-13", "2023-03-20", + "2023-03-27", "2023-04-03", "2023-04-10", "2023-04-17", "2023-04-24", + "2023-05-01", "2023-05-08", "2023-05-15" + ] + } + }, + "output_type": { + "sample": { + "output_type_id_params": { + "type": "character", + "min_samples_per_task": 50, + "max_samples_per_task": 100, + "max_length": 10 + }, + "is_required": true, + "value": { + "type": "integer", + "minimum": 0 + } + }, + "mean": { + "output_type_id": { + "required": null + }, + "is_required": true, + "value": { + "type": "double", + "minimum": 0 + } + } + }, + "target_metadata": [{ + "target_id": "wk ahead inc flu hosp", + "target_name": "weekly influenza hospitalization incidence", + "target_units": "rate per 100,000 population", + "target_keys": { + "target": "wk ahead inc flu hosp" + }, + "target_type": "discrete", + "description": "This target represents the counts of new hospitalizations per horizon week.", + "is_step_ahead": true, + "time_unit": "week" + }] + }, { + "task_ids": { + "forecast_date": { + "required": null, + "optional": [ + "2022-12-12", "2022-12-19", "2022-12-26", "2023-01-02", "2023-01-09", + "2023-01-16", "2023-01-23", "2023-01-30", "2023-02-06", "2023-02-13", + "2023-02-20", "2023-02-27", "2023-03-06", "2023-03-13", "2023-03-20", + "2023-03-27", "2023-04-03", "2023-04-10", "2023-04-17", "2023-04-24", + "2023-05-01" + ] + }, + "target": { + "required": null, + "optional": ["wk flu hosp rate change"] + }, + "horizon": { + "required": [2], + "optional": [1] + }, + "location": { + "required": ["US"], + "optional": [ + "01", + "02" + ] + }, + "target_date": { + "required": null, + "optional": [ + "2022-12-19", "2022-12-26", "2023-01-02", "2023-01-09", + "2023-01-16", "2023-01-23", "2023-01-30", "2023-02-06", "2023-02-13", + "2023-02-20", "2023-02-27", "2023-03-06", "2023-03-13", "2023-03-20", + "2023-03-27", "2023-04-03", "2023-04-10", "2023-04-17", "2023-04-24", + "2023-05-01", "2023-05-08", "2023-05-15" + ] + } + }, + "output_type": { + "pmf": { + "output_type_id": { + "required": ["large_decrease", "decrease", "stable", "increase", "large_increase"] + }, + "is_required": false, + "value": { + "type": "double", + "minimum": 0, + "maximum": 1 + } + } + }, + "target_metadata": [{ + "target_id": "wk flu hosp rate change", + "target_name": "weekly influenza hospitalization rate change", + "target_units": "rate per 100,000 population", + "target_keys": { + "target": "wk flu hosp rate change" + }, + "target_type": "nominal", + "description": "This target represents the change in the rate of new hospitalizations per week comparing the week ending two days prior to the forecast_date to the week ending h weeks after the forecast_date.", + "is_step_ahead": true, + "time_unit": "week" + }] + }], + "submissions_due": { + "relative_to": "forecast_date", + "start": -6, + "end": 2 + }, + "derived_task_ids": ["target_date"] + } + + ] +}