Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

starting with fork of @datalorax & @januz #359

Merged
merged 5 commits into from
Oct 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
^renv$
^renv\.lock$
^Meta$
^doc$
^.*\.Rproj$
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,9 @@ README.html
# The devtools zip is downloaded when the package is updating itself. If it's not deleted, there's no reason to commit it to the repository.
devtools.zip
docs

renv/

.Rprofile

renv.lock
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Depends:
Imports:
checkmate (>= 2.0),
dplyr (>= 1.0),
fs (>= 1.5.0),
httr (>= 1.4.0),
magrittr (>= 1.5),
methods,
Expand Down
175 changes: 112 additions & 63 deletions R/redcap-metadata-read.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
#' project. Required.
#' @param token The user-specific string that serves as the password for a
#' project. Required.
#' @param format Format to download the metadata in. The default is "json".
#' @param meta_data_file File path of the metadata file. If it does not exist,
#' the file is downloaded using the API and saved at the specified file path.
#' The default is "data/data-dictionary.csv".
#' @param forms An array, where each element corresponds to the REDCap form
#' of the desired fields. Optional.
#' @param forms_collapsed A single string, where the desired forms are
Expand Down Expand Up @@ -71,6 +75,8 @@
redcap_metadata_read <- function(
redcap_uri,
token,
format = "json",
meta_data_file = fs::path("data", "data-dictionary.csv"),
forms = NULL,
forms_collapsed = "",
fields = NULL,
Expand All @@ -92,78 +98,121 @@ redcap_metadata_read <- function(
if (1L <= nchar(fields_collapsed) )
validate_field_names_collapsed(fields_collapsed, stop_on_error = TRUE)

post_body <- list(
token = token,
content = "metadata",
format = "csv",
forms = forms_collapsed,
fields = fields_collapsed
)
if (!fs::file_exists(meta_data_file)) {
post_body <- list(
token = token,
content = "metadata",
format = format,
forms = forms_collapsed,
fields = fields_collapsed
)

# This is the important line that communicates with the REDCap server.
kernel <- kernel_api(redcap_uri, post_body, config_options)
# This is the important line that communicates with the REDCap server.
kernel <- kernel_api(redcap_uri, post_body, config_options)

if (kernel$success) {
col_types <-
readr::cols(
field_name = readr::col_character(),
.default = readr::col_character()
if (kernel$success) {
col_types <-
readr::cols(
field_name = readr::col_character(),
.default = readr::col_character()
)

try(
# Convert the raw text to a dataset.
if (format == "csv") {
ds <-
readr::read_csv(
kernel$raw_text,
col_types = col_types
)
} else if (format == "json") {
json_df <- jsonlite::fromJSON(kernel$raw_text)
json_tibble <- tibble::as_tibble(json_df)
ds <- dplyr::mutate_all(json_tibble, ~ dplyr::na_if(.x, ""))
},
# Don't print the warning in the try block. Print it below,
# where it's under the control of the caller.
silent = TRUE
)

try(
# Convert the raw text to a dataset.
ds <-
readr::read_csv(
kernel$raw_text,
col_types = col_types
),
# Don't print the warning in the try block. Print it below,
# where it's under the control of the caller.
silent = TRUE
)
if (exists("ds") & inherits(ds, "data.frame")) {
outcome_message <- sprintf(
"The data dictionary describing %s fields was read from REDCap in %0.1f seconds. The http status code was %i.",
format(nrow(ds), big.mark = ",", scientific = FALSE, trim = TRUE),
kernel$elapsed_seconds,
kernel$status_code
)

if (exists("ds") & inherits(ds, "data.frame")) {
outcome_message <- sprintf(
"The data dictionary describing %s fields was read from REDCap in %0.1f seconds. The http status code was %i.",
format(nrow(ds), big.mark = ",", scientific = FALSE, trim = TRUE),
kernel$elapsed_seconds,
kernel$status_code
)
# If an operation is successful, the `raw_text` is no longer returned
# to save RAM. The content is not really necessary with httr's status
# message exposed.
kernel$raw_text <- ""

# If an operation is successful, the `raw_text` is no longer returned
# to save RAM. The content is not really necessary with httr's status
# message exposed.
kernel$raw_text <- ""
} else { # nocov start
# Override the 'success' determination from the http status code
# and return an empty data.frame.
kernel$success <- FALSE
ds <- data.frame()
outcome_message <- sprintf(
"The REDCap metadata export failed. The http status code was %i. The 'raw_text' returned was '%s'.",
kernel$status_code,
# write metadata to file
if (!fs::dir_exists(fs::path_dir(meta_data_file))) {
fs::dir_create(fs::path_dir(meta_data_file))
}
readr::write_csv(
ds,
meta_data_file,
na = ""
)
} else { # nocov start
# Override the 'success' determination from the http status code
# and return an empty data.frame.
kernel$success <- FALSE
ds <- data.frame()
outcome_message <- sprintf(
"The REDCap metadata export failed. The http status code was %i. The 'raw_text' returned was '%s'.",
kernel$status_code,
kernel$raw_text
)
} # nocov end
} else {
ds <- data.frame() #Return an empty data.frame
outcome_message <- sprintf(
"The REDCapR metadata export operation was not successful. The error message was:\n%s",
kernel$raw_text
)
} # nocov end
}

if (verbose)
message(outcome_message)

list(
data = ds,
success = kernel$success,
status_code = kernel$status_code,
outcome_message = outcome_message,
forms_collapsed = forms_collapsed,
fields_collapsed = fields_collapsed,
elapsed_seconds = kernel$elapsed_seconds,
raw_text = kernel$raw_text
)
} else {
ds <- data.frame() #Return an empty data.frame
outcome_message <- sprintf(
"The REDCapR metadata export operation was not successful. The error message was:\n%s",
kernel$raw_text
col_types <- readr::cols(
field_name = readr::col_character(),
.default = readr::col_character()
)
}

if (verbose)
message(outcome_message)

list(
data = ds,
success = kernel$success,
status_code = kernel$status_code,
outcome_message = outcome_message,
forms_collapsed = forms_collapsed,
fields_collapsed = fields_collapsed,
elapsed_seconds = kernel$elapsed_seconds,
raw_text = kernel$raw_text
)
ds <- readr::read_csv(
meta_data_file,
col_types = col_types
)

outcome_message <- sprintf(
"The data dictionary describing %s fields was read from file %s.",
format(nrow(ds), big.mark = ",", scientific = FALSE, trim = TRUE),
meta_data_file
)

if (verbose)
message(outcome_message)

list(
data = ds,
forms_collapsed = forms_collapsed,
fields_collapsed = fields_collapsed
)
}
}
5 changes: 5 additions & 0 deletions R/redcap-read-oneshot-eav.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#' project. Required.
#' @param token The user-specific string that serves as the password for a
#' project. Required.
#' @param meta_data_file File path of the metadata file. If it does not exist,
#' the file is downloaded using the API and saved at the specified file path.
#' The default is "data/data-dictionary.csv".
#' @param records An array, where each element corresponds to the ID of a
#' desired record. Optional.
#' @param records_collapsed A single string, where the desired ID values
Expand Down Expand Up @@ -135,6 +138,7 @@
redcap_read_oneshot_eav <- function(
redcap_uri,
token,
meta_data_file = "data/data-dictionary.csv",
records = NULL,
records_collapsed = "",
fields = NULL,
Expand Down Expand Up @@ -237,6 +241,7 @@ redcap_read_oneshot_eav <- function(
REDCapR::redcap_metadata_read(
redcap_uri,
token,
meta_data_file = meta_data_file,
forms_collapsed = forms_collapsed
)$data
ds_variable <- REDCapR::redcap_variables(redcap_uri, token)$data
Expand Down
41 changes: 24 additions & 17 deletions R/redcap-read.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
#' project. Required.
#' @param token The user-specific string that serves as the password for a
#' project. Required.
#' @param format Format to download the metadata in. The default is "csv".
#' @param meta_data_file File path of the metadata file. If it does not exist,
#' the file is downloaded using the API and saved at the specified file path.
#' The default is "data/data-dictionary.csv".
#' @param records An array, where each element corresponds to the ID of a
#' desired record. Optional.
#' @param records_collapsed A single string, where the desired ID values are
Expand All @@ -29,8 +33,6 @@
#' separated by commas. Optional.
#' @param forms An array, where each element corresponds to a desired project
#' form. Optional.
#' @param forms_collapsed A single string, where the desired form names are
#' separated by commas. Optional.
#' @param events An array, where each element corresponds to a desired project
#' event. Optional.
#' @param events_collapsed A single string, where the desired event names are
Expand Down Expand Up @@ -173,9 +175,11 @@ redcap_read <- function(
continue_on_error = FALSE,
redcap_uri,
token,
format = "csv",
meta_data_file = "data/data-dictionary.csv",
records = NULL, records_collapsed = "",
fields = NULL, fields_collapsed = "",
forms = NULL, forms_collapsed = "",
forms = NULL,
events = NULL, events_collapsed = "",
raw_or_label = "raw",
raw_or_label_headers = "raw",
Expand All @@ -202,7 +206,6 @@ redcap_read <- function(
checkmate::assert_character(fields , any.missing=TRUE , min.len=1, pattern="^.{1,}$", null.ok=TRUE)
checkmate::assert_character(fields_collapsed , any.missing=TRUE , len=1, pattern="^.{0,}$", null.ok=TRUE)
checkmate::assert_character(forms , any.missing=TRUE , min.len=1, pattern="^.{1,}$", null.ok=TRUE)
checkmate::assert_character(forms_collapsed , any.missing=TRUE , len=1, pattern="^.{0,}$", null.ok=TRUE)
checkmate::assert_character(events , any.missing=TRUE , min.len=1, pattern="^.{1,}$", null.ok=TRUE)
checkmate::assert_character(events_collapsed , any.missing=TRUE , len=1, pattern="^.{0,}$", null.ok=TRUE)
checkmate::assert_character(raw_or_label , any.missing=FALSE, len=1)
Expand All @@ -226,25 +229,33 @@ redcap_read <- function(
validate_field_names(fields, stop_on_error = TRUE)

token <- sanitize_token(token)
records_collapsed <- collapse_vector(records , records_collapsed)
fields_collapsed <- collapse_vector(fields , fields_collapsed)
forms_collapsed <- collapse_vector(forms , forms_collapsed)
events_collapsed <- collapse_vector(events , events_collapsed)
filter_logic <- filter_logic_prepare(filter_logic)
verbose <- verbose_prepare(verbose)

if (1L <= nchar(fields_collapsed) )
validate_field_names_collapsed(fields_collapsed, stop_on_error = TRUE)

start_time <- Sys.time()

metadata <- REDCapR::redcap_metadata_read(
redcap_uri = redcap_uri,
token = token,
format = format,
meta_data_file = meta_data_file,
verbose = verbose,
config_options = config_options
)

fields_from_forms <- metadata$data %>%
dplyr::filter(form_name %in% forms) %>%
dplyr::pull(field_name)
fields <- c(fields, fields_from_forms)
fields

records_collapsed <- collapse_vector(records , records_collapsed)
fields_collapsed <- collapse_vector(fields , fields_collapsed)
events_collapsed <- collapse_vector(events , events_collapsed)
filter_logic <- filter_logic_prepare(filter_logic)
verbose <- verbose_prepare(verbose)

if (1L <= nchar(fields_collapsed) )
validate_field_names_collapsed(fields_collapsed, stop_on_error = TRUE)

# if (!metadata$success) {
# error_message <- sprintf(
# "The REDCapR record export operation was not successful. The error message was:\n%s",
Expand All @@ -258,7 +269,6 @@ redcap_read <- function(
token = token,
records_collapsed = records_collapsed,
fields_collapsed = metadata$data$field_name[id_position],
forms_collapsed = forms_collapsed,
events_collapsed = events_collapsed,
filter_logic = filter_logic,
datetime_range_begin = datetime_range_begin,
Expand All @@ -276,7 +286,6 @@ redcap_read <- function(
data = data.frame(),
records_collapsed = "failed in initial batch call",
fields_collapsed = "failed in initial batch call",
forms_collapsed = "failed in initial batch call",
events_collapsed = "failed in initial batch call",
filter_logic = "failed in initial batch call",
datetime_range_begin = "failed in initial batch call",
Expand Down Expand Up @@ -320,7 +329,6 @@ redcap_read <- function(
records = selected_ids,
fields_collapsed = fields_collapsed,
events_collapsed = events_collapsed,
forms_collapsed = forms_collapsed,
raw_or_label = raw_or_label,
raw_or_label_headers = raw_or_label_headers,
export_checkbox_label = export_checkbox_label,
Expand Down Expand Up @@ -387,7 +395,6 @@ redcap_read <- function(
# data_types = data_types,
records_collapsed = records_collapsed,
fields_collapsed = fields_collapsed,
forms_collapsed = forms_collapsed,
events_collapsed = events_collapsed,
filter_logic = filter_logic,
datetime_range_begin= datetime_range_begin,
Expand Down
8 changes: 8 additions & 0 deletions man/redcap_metadata_read.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading