From 3503d125d34b95b9fb317f19afcb56fbeb526dfb Mon Sep 17 00:00:00 2001 From: aclark02-arcus Date: Wed, 10 Sep 2025 14:45:53 +0000 Subject: [PATCH 01/14] Increment version number to 0.3.0.9001 --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 0fedce61..5ac9016e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: clinsight Title: ClinSight -Version: 0.3.0.9000 +Version: 0.3.0.9001 Authors@R: c( person("Leonard Daniël", "Samson", , "lsamson@gcp-service.com", role = c("cre", "aut"), comment = c(ORCID = "0000-0002-6252-7639")), From 56c740295bb8850565f2e67ebd0325f3142d8cd0 Mon Sep 17 00:00:00 2001 From: aclark02-arcus Date: Wed, 10 Sep 2025 14:48:53 +0000 Subject: [PATCH 02/14] export 'get_available_data()' & update docs --- NAMESPACE | 1 + R/fct_appdata_summary_tables.R | 2 +- man/get_available_data.Rd | 1 - man/metadata.Rd | 118 ++++++++++++++++++--------------- 4 files changed, 68 insertions(+), 54 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 5d3f1f26..9613bd4c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -17,6 +17,7 @@ export(db_create) export(db_get_query) export(db_update) export(get_appdata) +export(get_available_data) export(get_base_value) export(get_db_connection) export(get_metadata) diff --git a/R/fct_appdata_summary_tables.R b/R/fct_appdata_summary_tables.R index 0e30e6e0..f8a6279c 100644 --- a/R/fct_appdata_summary_tables.R +++ b/R/fct_appdata_summary_tables.R @@ -166,7 +166,7 @@ get_timeline_data <- function( #' duplicate names exist for each participant. #' #' @return A data frame with available data points per form. -#' @keywords internal +#' @export #' get_available_data <- function( data, diff --git a/man/get_available_data.Rd b/man/get_available_data.Rd index 15cdaf2c..44e71354 100644 --- a/man/get_available_data.Rd +++ b/man/get_available_data.Rd @@ -32,4 +32,3 @@ individual and per form. Required columns are the ones distinctively identifying an item. For now that are site_code, event_name, subject_id, event_label, item_group, item_name. } -\keyword{internal} diff --git a/man/metadata.Rd b/man/metadata.Rd index e875ec61..576dab6c 100644 --- a/man/metadata.Rd +++ b/man/metadata.Rd @@ -9,59 +9,73 @@ \if{html}{\out{
}}\preformatted{str(metadata) #> List of 9 -#> $ column_names : tibble [10 x 2] (S3: tbl_df/tbl/data.frame) -#> ..$ name_raw: chr [1:10] "SiteCode" "SubjectId" "EventId" "EventDate" ... -#> ..$ name_new: chr [1:10] "site_code" "subject_id" "event_id" "event_date" ... -#> $ events : tibble [10 x 10] (S3: tbl_df/tbl/data.frame) -#> ..$ event_id : chr [1:10] "SCR" "VIS1" "VIS2" "VIS3" ... -#> ..$ event_id_pattern : chr [1:10] "^SCR$" "^VIS1$" "^VIS2$" "^VIS3$" ... -#> ..$ is_regular_visit : logi [1:10] TRUE TRUE TRUE TRUE TRUE TRUE ... -#> ..$ event_label_custom : chr [1:10] NA "V1" "V2" "V3" ... -#> ..$ event_name_custom : chr [1:10] "Screening" "Visit 1" "Visit 2" "Visit 3" ... -#> ..$ is_baseline_event : logi [1:10] TRUE FALSE FALSE FALSE FALSE FALSE ... -#> ..$ generate_labels : logi [1:10] FALSE FALSE FALSE FALSE FALSE FALSE ... -#> ..$ meta_event_order : int [1:10] 1 2 3 4 5 6 7 8 9 10 -#> ..$ add_visit_number : logi [1:10] FALSE FALSE FALSE FALSE FALSE FALSE ... -#> ..$ add_event_repeat_number: logi [1:10] FALSE FALSE FALSE FALSE FALSE FALSE ... -#> $ common_forms :'data.frame': 44 obs. of 4 variables: -#> ..$ item_name : chr [1:44] "AE Number" "AE Name" "AESI" "AE start date" ... -#> ..$ item_type : chr [1:44] "other" "other" "other" "other" ... -#> ..$ item_group: chr [1:44] "Adverse events" "Adverse events" "Adverse events" "Adverse events" ... -#> ..$ merge_with: chr [1:44] NA NA NA NA ... -#> $ study_forms :'data.frame': 29 obs. of 6 variables: -#> ..$ item_name : chr [1:29] "Systolic blood pressure" "Diastolic blood pressure" "Pulse" "Resp" ... -#> ..$ item_type : chr [1:29] "continuous" "continuous" "continuous" "continuous" ... -#> ..$ item_group : chr [1:29] "Vital signs" "Vital signs" "Vital signs" "Vital signs" ... -#> ..$ unit : chr [1:29] "mmHg" "mmHg" "beats/min" "breaths/min" ... -#> ..$ lower_limit: chr [1:29] "90" "55" "60" "12" ... -#> ..$ upper_limit: chr [1:29] "160" "90" "100" "20" ... -#> $ general :'data.frame': 20 obs. of 3 variables: -#> ..$ item_name : chr [1:20] "Age" "Sex" "ECOG" "Eligible" ... -#> ..$ item_type : chr [1:20] "other" "other" "other" "other" ... -#> ..$ item_group: chr [1:20] "General" "General" "General" "General" ... -#> $ form_level_data:'data.frame': 11 obs. of 4 variables: -#> ..$ item_group : chr [1:11] "Adverse events" "Medication" "Conc. Procedures" "Medical History" ... -#> ..$ item_scale : logi [1:11] NA NA NA NA FALSE TRUE ... -#> ..$ use_unscaled_limits: logi [1:11] NA NA NA NA TRUE FALSE ... -#> ..$ review_required : logi [1:11] TRUE TRUE TRUE TRUE TRUE TRUE ... -#> $ table_names : tibble [16 x 2] (S3: tbl_df/tbl/data.frame) -#> ..$ table_name: chr [1:16] "Edit date" "Date" "Event" "Event" ... -#> ..$ raw_name : chr [1:16] "edit_date_time" "event_date" "event_label" "event_name" ... -#> $ settings :List of 4 -#> ..$ pre_pivot_fns : chr "apply_study_specific_suffix_fixes" -#> ..$ post_pivot_fns : chr "apply_edc_specific_changes" -#> ..$ post_merge_fns : chr "apply_study_specific_fixes" +#> $ column_names : tibble [15 x 3] (S3: tbl_df/tbl/data.frame) +#> ..$ name_raw: chr [1:15] "SiteCode" "SubjectId" "subjid" "data_page_id" ... +#> ..$ name_new: chr [1:15] "site_code" "subject_id" "subj_id" "data_page_id" ... +#> ..$ col_type: chr [1:15] "c" "c" "i" "i" ... +#> $ events : tibble [24 x 10] (S3: tbl_df/tbl/data.frame) +#> ..$ event_id : chr [1:24] "SCR" "C1D1" "C1D8" "C1D15" ... +#> ..$ event_id_pattern : chr [1:24] "^SCR$" "^C1D1$" "^C1D8$" "^C1D15$" ... +#> ..$ is_regular_visit : logi [1:24] TRUE TRUE TRUE TRUE TRUE TRUE ... +#> ..$ event_label_custom : chr [1:24] NA NA NA NA ... +#> ..$ event_name_custom : chr [1:24] "Screening" "Cycle 1 Day 1" "Cycle 1 Day 8" "Cycle 1 Day 15" ... +#> ..$ is_baseline_event : logi [1:24] TRUE FALSE FALSE FALSE FALSE FALSE ... +#> ..$ generate_labels : logi [1:24] FALSE FALSE FALSE FALSE FALSE FALSE ... +#> ..$ meta_event_order : int [1:24] 1 2 3 4 5 6 7 8 9 10 ... +#> ..$ add_visit_number : logi [1:24] FALSE FALSE FALSE FALSE FALSE FALSE ... +#> ..$ add_event_repeat_number: logi [1:24] FALSE FALSE FALSE FALSE FALSE FALSE ... +#> $ common_forms :'data.frame': 307 obs. of 6 variables: +#> ..$ item_name : chr [1:307] "Day in Study" "Event Date" "Visit" "Lesion ID" ... +#> ..$ item_type : chr [1:307] "other" "other" "other" "other" ... +#> ..$ item_form : chr [1:307] "Efficacy" "Efficacy" "Efficacy" "Efficacy" ... +#> ..$ form_level_id_var: chr [1:307] NA NA NA NA ... +#> ..$ item_group : chr [1:307] "Efficacy" "Efficacy" "Efficacy" "Efficacy" ... +#> ..$ merge_with : chr [1:307] NA NA NA NA ... +#> $ study_forms :'data.frame': 55 obs. of 9 variables: +#> ..$ item_name : chr [1:55] "Temperature" "RespiratoryRate" "PulseRate" "SystolicBloodPressure" ... +#> ..$ item_type : chr [1:55] "continuous" "continuous" "continuous" "continuous" ... +#> ..$ item_form : chr [1:55] "Vital Signs" "Vital Signs" "Vital Signs" "Vital Signs" ... +#> ..$ form_level_id_var: chr [1:55] NA NA NA NA ... +#> ..$ item_group : chr [1:55] "Vital Signs" "Vital Signs" "Vital Signs" "Vital Signs" ... +#> ..$ merge_with : chr [1:55] NA NA NA NA ... +#> ..$ unit : chr [1:55] NA NA NA NA ... +#> ..$ lower_limit : chr [1:55] NA NA NA NA ... +#> ..$ upper_limit : chr [1:55] NA NA NA NA ... +#> $ general :'data.frame': 129 obs. of 6 variables: +#> ..$ item_name : chr [1:129] "Sex" "Age" "Childbearing Potential" "Reason" ... +#> ..$ item_type : chr [1:129] "other" "other" "other" "other" ... +#> ..$ item_form : chr [1:129] "General" "General" "General" "General" ... +#> ..$ form_level_id_var: chr [1:129] NA NA NA NA ... +#> ..$ item_group : chr [1:129] "General" "General" "General" "General" ... +#> ..$ merge_with : chr [1:129] NA NA NA NA ... +#> $ form_level_data:'data.frame': 19 obs. of 5 variables: +#> ..$ item_group : chr [1:19] "Efficacy" "Administration" "Adverse events" "Disease History" ... +#> ..$ item_type : chr [1:19] "other" "other" "other" "other" ... +#> ..$ item_scale : logi [1:19] FALSE FALSE FALSE FALSE FALSE FALSE ... +#> ..$ use_unscaled_limits: logi [1:19] TRUE TRUE TRUE TRUE TRUE TRUE ... +#> ..$ review_required : logi [1:19] TRUE TRUE TRUE TRUE TRUE TRUE ... +#> $ table_names : tibble [15 x 2] (S3: tbl_df/tbl/data.frame) +#> ..$ table_name: chr [1:15] "Subject" "Visit" "Status" "Form Repeat" ... +#> ..$ raw_name : chr [1:15] "subject_id" "event_name" "status" "form_repeat" ... +#> $ settings :List of 6 +#> ..$ pre_merge_fns : chr "arcus_pre_merge" +#> ..$ pre_pivot_fns : chr "arcus_pre_pivot" +#> ..$ post_pivot_fns : chr "arcus_post_pivot" +#> ..$ post_merge_fns : chr "arcus_post_merge" +#> ..$ study_name : chr "PRISM-1" #> ..$ treatment_label: chr "💊 Tₓ" -#> $ items_expanded : tibble [220 x 9] (S3: tbl_df/tbl/data.frame) -#> ..$ form_type : chr [1:220] "common_forms" "common_forms" "common_forms" "common_forms" ... -#> ..$ var : chr [1:220] "AE_AESPID" "AE_AETERM" "AE_AESI" "AE_AESTDAT" ... -#> ..$ suffix : chr [1:220] NA NA NA NA ... -#> ..$ item_name : chr [1:220] "AE Number" "AE Name" "AESI" "AE start date" ... -#> ..$ item_type : chr [1:220] "other" "other" "other" "other" ... -#> ..$ item_group : chr [1:220] "Adverse events" "Adverse events" "Adverse events" "Adverse events" ... -#> ..$ unit : chr [1:220] NA NA NA NA ... -#> ..$ lower_limit: chr [1:220] NA NA NA NA ... -#> ..$ upper_limit: chr [1:220] NA NA NA NA ... +#> $ items_expanded : tibble [958 x 11] (S3: tbl_df/tbl/data.frame) +#> ..$ form_type : chr [1:958] "common_forms" "common_forms" "common_forms" "common_forms" ... +#> ..$ var : chr [1:958] "Day in Study" "Event Date" "Timepoint" "Lesion Number" ... +#> ..$ suffix : chr [1:958] NA NA NA NA ... +#> ..$ item_name : chr [1:958] "Day in Study" "Event Date" "Visit" "Lesion ID" ... +#> ..$ item_type : chr [1:958] "other" "other" "other" "other" ... +#> ..$ item_form : chr [1:958] "Efficacy" "Efficacy" "Efficacy" "Efficacy" ... +#> ..$ form_level_id_var: chr [1:958] NA NA NA NA ... +#> ..$ item_group : chr [1:958] "Efficacy" "Efficacy" "Efficacy" "Efficacy" ... +#> ..$ unit : chr [1:958] NA NA NA NA ... +#> ..$ lower_limit : chr [1:958] NA NA NA NA ... +#> ..$ upper_limit : chr [1:958] NA NA NA NA ... }\if{html}{\out{
}} } } From 46cdfd188eaf699db3ce7537b88ea5217cc79072 Mon Sep 17 00:00:00 2001 From: aclark02-arcus Date: Wed, 10 Sep 2025 15:12:00 +0000 Subject: [PATCH 03/14] add news --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 48c68e03..c9e5d9f4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,8 @@ # clinsight (development version) +- Moved `app_data`, `app_vars`, `app_tables`, & `available_data` to pre-processing step so that doesn't need to compute every session. +- Started using parquet read / writes for `merged_data` & `available_data` to speed startup time. + # clinsight 0.3.0 ## Developer notes From 7daef861de5692a3c6bc10c94301065534588f7d Mon Sep 17 00:00:00 2001 From: aclark02-arcus Date: Wed, 10 Sep 2025 15:18:58 +0000 Subject: [PATCH 04/14] export check_appdata() and get_meta_vars() & update docs --- NAMESPACE | 2 ++ NEWS.md | 1 + R/fct_data_helpers.R | 2 +- R/fct_data_tests.R | 2 +- man/check_appdata.Rd | 1 - man/get_meta_vars.Rd | 1 - 6 files changed, 5 insertions(+), 4 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 9613bd4c..61c96dc7 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -9,6 +9,7 @@ S3method(create_table,default) S3method(create_table,general) S3method(create_table,medical_history) S3method(create_table,medication) +export(check_appdata) export(collapse_column_vals) export(create_clinsight_config) export(create_clinsight_metadata) @@ -20,6 +21,7 @@ export(get_appdata) export(get_available_data) export(get_base_value) export(get_db_connection) +export(get_meta_vars) export(get_metadata) export(get_raw_csv_data) export(get_review_data) diff --git a/NEWS.md b/NEWS.md index c9e5d9f4..25be0146 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ # clinsight (development version) - Moved `app_data`, `app_vars`, `app_tables`, & `available_data` to pre-processing step so that doesn't need to compute every session. +- Export functions used to create the data objects above ^^^. - Started using parquet read / writes for `merged_data` & `available_data` to speed startup time. # clinsight 0.3.0 diff --git a/R/fct_data_helpers.R b/R/fct_data_helpers.R index ad66a6b6..5a2b4a48 100644 --- a/R/fct_data_helpers.R +++ b/R/fct_data_helpers.R @@ -239,7 +239,7 @@ fix_multiple_choice_vars <- function( #' @param meta List. metadata to use. #' #' @return a list with all important names to be used in a clinical trial. -#' @keywords internal +#' @export #' get_meta_vars <- function(data = appdata, meta = metadata){ stopifnot(inherits(data, "list")) diff --git a/R/fct_data_tests.R b/R/fct_data_tests.R index 5b9c5abc..5c0606be 100644 --- a/R/fct_data_tests.R +++ b/R/fct_data_tests.R @@ -7,7 +7,7 @@ #' @param required_cols Character vector, containing the column names that are #' required for the application to run appropriately. #' -#' @keywords internal +#' @export #' check_appdata <- function( data = appdata, diff --git a/man/check_appdata.Rd b/man/check_appdata.Rd index b58d31d6..06bae442 100644 --- a/man/check_appdata.Rd +++ b/man/check_appdata.Rd @@ -22,4 +22,3 @@ required for the application to run appropriately.} \description{ Checks data for compatibility with metadata. } -\keyword{internal} diff --git a/man/get_meta_vars.Rd b/man/get_meta_vars.Rd index 82833b25..ad1cdbea 100644 --- a/man/get_meta_vars.Rd +++ b/man/get_meta_vars.Rd @@ -19,4 +19,3 @@ Prepares and extracts consistent variable names based on both metadata and the provided data. To be used in both the UI and server functions of a Shiny app. } -\keyword{internal} From aa1565bfeaf4e1c317313651e709559d76435ab3 Mon Sep 17 00:00:00 2001 From: aclark02-arcus Date: Wed, 10 Sep 2025 16:46:11 +0000 Subject: [PATCH 05/14] setup clinsight to use other objects besides 'merged_data', thus saving lots of time at app startup --- R/app_server.R | 42 +++-- R/data.R | 98 +++++++++++ R/fct_test_clinsight.R | 60 ++++++- R/run_app.R | 81 +++++++-- data-raw/clinsightful_data.R | 33 +++- data-raw/metadata.R | 6 - data/cs_app_data.rda | Bin 0 -> 43568 bytes data/cs_app_tables.rda | Bin 0 -> 12389 bytes data/cs_app_vars.rda | Bin 0 -> 2109 bytes data/cs_available_data.rda | Bin 0 -> 4537 bytes dev/app.R | 44 ++++- dev/run_dev.R | 9 +- inst/golem-config.yml | 12 +- man/cs_app_data.Rd | 317 +++++++++++++++++++++++++++++++++++ man/cs_app_tables.Rd | 149 ++++++++++++++++ man/cs_app_vars.Rd | 62 +++++++ man/cs_available_data.Rd | 35 ++++ man/metadata.Rd | 192 +++++++++++++-------- 18 files changed, 1028 insertions(+), 112 deletions(-) delete mode 100644 data-raw/metadata.R create mode 100644 data/cs_app_data.rda create mode 100644 data/cs_app_tables.rda create mode 100644 data/cs_app_vars.rda create mode 100644 data/cs_available_data.rda create mode 100644 man/cs_app_data.Rd create mode 100644 man/cs_app_tables.Rd create mode 100644 man/cs_app_vars.Rd create mode 100644 man/cs_available_data.Rd diff --git a/R/app_server.R b/R/app_server.R index 5ccd6406..87cc95e3 100644 --- a/R/app_server.R +++ b/R/app_server.R @@ -18,18 +18,24 @@ app_server <- function( output, session ){ + + # Read in pre-processed R objects meta <- golem::get_golem_options("meta") - merged_data <- golem::get_golem_options("data") + app_data <- golem::get_golem_options("app_data") + app_vars <- golem::get_golem_options("app_vars") + app_tables <- golem::get_golem_options("app_tables") + available_data <- golem::get_golem_options("available_data") + # merged_data <- golem::get_golem_options("data") user_db <- golem::get_golem_options("user_db") credentials_db <- golem::get_golem_options("credentials_db") - app_data <- get_appdata(merged_data, meta = meta) - app_vars <- get_meta_vars(data = app_data, meta = meta) - app_tables <- lapply( - setNames(names(app_data), names(app_data)), \(x){ - create_table(app_data[[x]], expected_columns = names(app_vars$items[[x]])) - }) - check_appdata(app_data, meta) + # app_data <- get_appdata(merged_data, meta = meta) + # app_vars <- get_meta_vars(data = app_data, meta = meta) + # app_tables <- lapply( + # setNames(names(app_data), names(app_data)), \(x){ + # create_table(app_data[[x]], expected_columns = names(app_vars$items[[x]])) + # }) + # check_appdata(app_data, meta) session$userData$pending_review_records <- reactiveValues() session$userData$pending_form_review_status <- reactiveValues() @@ -43,16 +49,16 @@ app_server <- function( ) # For query item selector drop-down menus: - available_data <- get_available_data( - data = app_data, - tables = app_tables, - all_forms = app_vars$all_forms, - form_repeat_name = with( - meta[["table_names"]], - table_name[raw_name == "form_repeat"] - ) |> - tryCatch(error = \(e) "N") - ) + # available_data <- get_available_data( + # data = app_data, + # tables = app_tables, + # all_forms = app_vars$all_forms, + # form_repeat_name = with( + # meta[["table_names"]], + # table_name[raw_name == "form_repeat"] + # ) |> + # tryCatch(error = \(e) "N") + # ) # For summary review data: static_overview_data <- get_static_overview_data( diff --git a/R/data.R b/R/data.R index 701ef0d5..12f055b5 100644 --- a/R/data.R +++ b/R/data.R @@ -95,6 +95,104 @@ #' system.file("raw_data", package = "clinsight")))`. "clinsightful_data" + +#' Application Metadata +#' +#' A list of data frames and settings containing metadata that will be used for +#' the application. The metadata will be merged with with raw data. It controls +#' the variables that will be used in the application, and in which tab the +#' variables will be shown. The goal is that most, if not all, study-specific +#' data will be captured in the metadata, leaving the scripts to run the +#' application largely unaltered between studies.See `vignette("Metadata")` for +#' in-depth information. +#' +#' @format ## `metadata`: A list with `r length(metadata)` objects. +#' +#' ```{r } +#' str(metadata) +#' ``` +#' +#' @source Can be created with an Excel file. The Excel file format is chosen so +#' that the metadata can be changed easily per study. See +#' `raw-data/metadata.R` for details. +#' +"metadata" + + +#' Application Data +#' +#' A list of data frames split by `item_group`. It is currently +#' not needed to provide the application data in this format. However, the +#' function can be useful for clinsight data customization, especially in +#' combination with [create_table()]. It creates table classes of the +#' `item_group` name (in lower case letters, and all punctuation replaced by an +#' underscore), as long as there is a method available with the corresponding +#' item_group name for the function [create_table()]. If all data is of type +#' 'continuous', then laboratory values such as lab limits and units are +#' cleaned. +#' +#' @format ## `cs_app_data`: A list with `r length(cs_app_data)` objects. +#' +#' ```{r } +#' str(cs_app_data) +#' ``` +#' +#' @source See `raw-data/clinsightful_data.R` for details. +#' +"cs_app_data" + + +#' Application Variables +#' +#' Named list version of `metadata` object. +#' +#' @format ## `cs_app_vars`: A list with `r length(cs_app_vars)` objects. +#' +#' ```{r } +#' str(cs_app_vars) +#' ``` +#' +#' @source See `raw-data/clinsightful_data.R` for details. +#' +"cs_app_vars" + + +#' Application Tables +#' +#' A list of data frames containing all application tables. +#' +#' @format ## `cs_app_tables`: A list with `r length(cs_app_tables)` objects. +#' +#' ```{r } +#' str(cs_app_tables) +#' ``` +#' +#' @source See `raw-data/clinsightful_data.R` for details. +#' +"cs_app_tables" + + +#' Application 'Available Data' +#' +#' Data frame containing info about available data per individual, +#' such as visits, adverse events, etc. Will be used in module +#' [mod_queries_server()], to select available items to create a query for per +#' individual and per form. Required columns are the ones distinctively +#' identifying an item. For now that are site_code, event_name, subject_id, +#' event_label, item_group, item_name. +#' +#' @format a data.frame with `r nrow(cs_available_data)` rows and +#' `r ncol(cs_available_data)` variables. +#' +#' ```{r } +#' str(cs_available_data) +#' ``` +#' +#' @source See `raw-data/clinsightful_data.R` for details. +#' +"cs_available_data" + + #' ClinSight key columns #' #' A character string containing the names of the columns that are needed to diff --git a/R/fct_test_clinsight.R b/R/fct_test_clinsight.R index 71273360..fb3766a0 100644 --- a/R/fct_test_clinsight.R +++ b/R/fct_test_clinsight.R @@ -30,19 +30,69 @@ test_clinsight <- function( stopifnot(is.character(clinsight_config)) study_data_path <- get_golem_config("study_data", config = clinsight_config) meta_data_path <- get_golem_config("meta_data", config = clinsight_config) + # app_data_path <- get_golem_config("app_data", config = clinsight_config) + # app_vars_path <- get_golem_config("app_vars", config = clinsight_config) + # app_tables_path <- get_golem_config("app_tables", config = clinsight_config) + # available_data_path <- get_golem_config("available_data", config = clinsight_config) if ( clinsight_config %in% c("default", "dev") | - !is.character(study_data_path) | !is.character(meta_data_path) + !is.character(study_data_path) | + !is.character(meta_data_path) #| + # !is.character(app_data_path) | + # !is.character(app_vars_path) | + # !is.character(app_tables_path) | + # !is.character(available_data_path) ){ stop("The 'default' or 'dev' config cannot be used with custom data, ", - "and study_data and meta_data in the config file ", - "should be character vectors.") + "and meta_data, app_data, app_vars, app_tables, & available_data ", + "in the config file should be character vectors.") } + # Build a version of `app_data` & app_vars + app_data <- get_appdata(data = clinsight_data, meta = meta_data) + app_vars <- get_meta_vars(data = app_data, meta = meta_data) + + # Build a 'app_tables' + app_tables <- lapply( + setNames(names(app_data), names(app_data)), \(x){ + create_table(app_data[[x]], expected_columns = names(app_vars$items[[x]])) + }) + + # Build a 'available_data' + available_data <- get_available_data( + data = app_data, + tables = app_tables, + all_forms = app_vars$all_forms, + form_repeat_name = with( + meta[["table_names"]], + table_name[raw_name == "form_repeat"] + ) |> + tryCatch(error = \(e) "N") + ) temp_folder <- tempfile(tmpdir = tempdir()) dir.create(temp_folder, recursive = TRUE) - saveRDS(clinsight_data, file.path(temp_folder, basename(study_data_path))) - saveRDS(meta_data, file.path(temp_folder, basename(meta_data_path))) + # saveRDS(clinsight_data, file.path(temp_folder, basename(study_data_path))) + # saveRDS(meta_data, file.path(temp_folder, basename(meta_data_path))) + db_path <- file.path(temp_folder, "user_db.sqlite") + if(file.exists(db_path)) file.remove(db_path) + db_create(get_review_data(clinsight_data), + db_path = db_path + ) + save_objs <- c( + "clinsight_data", + "meta_data", + "app_data", + "app_vars", + "app_tables", + "available_data") + purrr::walk(save_objs, function(x){ + rds_file <- file.path(temp_folder, paste0(x, ".rds")) + saveRDS(get(x), rds_file) + if(inherits(get(x), "data.frame")) { + pq_file <- file.path(temp_folder, paste0(x, ".parquet")) + arrow::write_parquet(get(x), pq_file) + } + }) old_config <- Sys.getenv("GOLEM_CONFIG_ACTIVE") Sys.setenv("GOLEM_CONFIG_ACTIVE" = clinsight_config) run_app( diff --git a/R/run_app.R b/R/run_app.R index eb6063ac..a35905eb 100644 --- a/R/run_app.R +++ b/R/run_app.R @@ -24,8 +24,12 @@ run_app <- function( ... ) { - data <- get_golem_config("study_data") + # data <- get_golem_config("study_data") meta <- get_golem_config("meta_data") + app_data <- get_golem_config("app_data") + app_vars <- get_golem_config("app_vars") + app_tables <- get_golem_config("app_tables") + available_data <- get_golem_config("available_data") user_db <- get_golem_config("user_db") use_shinymanager <- isTRUE(get_golem_config("user_identification") == "shinymanager") credentials_db <- get_golem_config("credentials_db") @@ -39,23 +43,50 @@ run_app <- function( "Custom folder path provided in the 'data_folder' argument.", "File paths specified in the config.yml will be ignored." ) - if(is.character(data)) data <- file.path(data_folder, basename(data)) + # if(is.character(data)) data <- file.path(data_folder, basename(data)) if(is.character(meta)) meta <- file.path(data_folder, basename(meta)) + if(is.character(app_data)) app_data <- file.path(data_folder, basename(app_data)) + if(is.character(app_vars)) app_vars <- file.path(data_folder, basename(app_vars)) + if(is.character(app_tables)) app_tables <- file.path(data_folder, basename(app_tables)) + if(is.character(available_data)) available_data <- file.path(data_folder, basename(available_data)) user_db <- file.path(data_folder, basename(user_db)) if(!is.null(credentials_db)){ credentials_db <- file.path(data_folder, basename(credentials_db)) } } - ## Verify study data - if(is.character(data)){ - if(!file.exists(data)) stop(paste0("Cannot find '", data, "'.")) - if(tolower(tools::file_ext(data)) != "rds"){ - stop("Invalid data format. Expecting a file .rds format") + # ## Verify study data + # if(is.character(data)){ + # if(!file.exists(data)) stop(paste0("Cannot find '", data, "'.")) + # if(tolower(tools::file_ext(data)) != "rds"){ + # stop("Invalid data format. Expecting a file .rds format") + # } + # data <- readRDS(data) + # } + # stopifnot("Expecting study data to be in data frame format." = is.data.frame(data)) + + + ## Verify app_data list + if(is.character(app_data)){ + if(!file.exists(app_data)) stop(paste0("Cannot find '", app_data, "'.")) + if(tolower(tools::file_ext(app_data)) != "rds"){ + stop("Invalid 'app_data' format. Expecting a file .rds format") + } + app_data <- readRDS(app_data) + } + stopifnot("Expecting 'app_data' to be in list format." = inherits(app_data, "list")) + + + ## Verify app_vars list + if(is.character(app_vars)){ + if(!file.exists(app_vars)) stop(paste0("Cannot find '", app_vars, "'.")) + if(tolower(tools::file_ext(app_vars)) != "rds"){ + stop("Invalid 'app_vars' format. Expecting a file .rds format") } - data <- readRDS(data) + app_vars <- readRDS(app_vars) } - stopifnot("Expecting study data to be in data frame format." = is.data.frame(data)) + stopifnot("Expecting 'app_vars' to be in list format." = inherits(app_vars, "list")) + ## Verify metadata if(is.character(meta)){ @@ -65,7 +96,33 @@ run_app <- function( } meta <- readRDS(meta) } - stopifnot("Expecting metadata to be in a list format" = inherits(meta, "list")) + stopifnot("Expecting 'metadata' to be in a list format" = inherits(meta, "list")) + + + ## Verify app_tables list + if(is.character(app_tables)){ + if(!file.exists(app_tables)) stop(paste0("Cannot find '", app_tables, "'.")) + if(tolower(tools::file_ext(app_tables)) != "rds"){ + stop("Invalid 'app_tables' format. Expecting a file .rds format") + } + app_tables <- readRDS(app_tables) + } + stopifnot("Expecting 'app_tables' to be in list format." = inherits(app_tables, "list")) + + + ## Verify available_data + if(is.character(available_data)){ + if(!file.exists(available_data)) stop(paste0("Cannot find '", available_data, "'.")) + available_data <- + switch( + tolower(tools::file_ext(available_data)), + "rds" = readRDS(available_data), + "parquet" = arrow::read_parquet(available_data), + stop("Invalid 'available_data' format. Expecting an RDS or Parquet file.") + ) + } + stopifnot("Expecting 'available_data' to be in data frame format." = is.data.frame(available_data)) + ## Verify user database stopifnot("user_db should be a character vector with a file path" = @@ -125,6 +182,10 @@ run_app <- function( ), golem_opts = list( meta = meta, + app_data = app_data, + app_vars = app_vars, + app_tables = app_tables, + available_data = available_data, data = data, user_db = user_db, credentials_db = credentials_db, diff --git a/data-raw/clinsightful_data.R b/data-raw/clinsightful_data.R index 37410c43..39d03212 100644 --- a/data-raw/clinsightful_data.R +++ b/data-raw/clinsightful_data.R @@ -1,9 +1,40 @@ devtools::load_all(".") +metadata <- get_metadata(filepath = app_sys("metadata.xlsx")) + clinsightful_data <- clinsight::get_raw_csv_data( app_sys("raW_data"), synch_time = "2023-09-15 10:10:00 UTC" ) |> merge_meta_with_data(metadata) -usethis::use_data(clinsightful_data, overwrite = TRUE) \ No newline at end of file +# Build a version of `app_data` & app_vars +cs_app_data <- get_appdata(data = clinsightful_data, meta = metadata) +cs_app_vars <- get_meta_vars(data = cs_app_data, meta = metadata) + +# Build a 'app_tables' +cs_app_tables <- lapply( + setNames(names(cs_app_data), names(cs_app_data)), \(x){ + create_table(cs_app_data[[x]], expected_columns = names(cs_app_vars$items[[x]])) + }) + +# Build a 'available_data' +cs_available_data <- get_available_data( + data = cs_app_data, + tables = cs_app_tables, + all_forms = cs_app_vars$all_forms, + form_repeat_name = with( + meta[["table_names"]], + table_name[raw_name == "form_repeat"] + ) |> + tryCatch(error = \(e) "N") +) + +usethis::use_data( + metadata, + clinsightful_data, + cs_app_data, + cs_app_vars, + cs_app_tables, + cs_available_data, + overwrite = TRUE) diff --git a/data-raw/metadata.R b/data-raw/metadata.R deleted file mode 100644 index bacd9d40..00000000 --- a/data-raw/metadata.R +++ /dev/null @@ -1,6 +0,0 @@ -## code to prepare metadata. Raw data is expected to be in Excel format. -devtools::load_all(".") - -metadata <- get_metadata(filepath = app_sys("metadata.xlsx")) - -usethis::use_data(metadata, overwrite = TRUE) diff --git a/data/cs_app_data.rda b/data/cs_app_data.rda new file mode 100644 index 0000000000000000000000000000000000000000..36d2e166c5eca06f89428a3c37c58089f0e9845d GIT binary patch literal 43568 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 F=78<7?tcIP literal 0 HcmV?d00001 diff --git a/data/cs_app_tables.rda b/data/cs_app_tables.rda new file mode 100644 index 0000000000000000000000000000000000000000..fcf691088fd54c046748e9fce4ce23f133624f3d GIT binary patch literal 12389 zcmV-rFq+RoT4*^jL0KkKSv^ig4*>ArgIoDWLlng_V?k>W{TmaM^ISYog(?CTw)K-gZ zwNze!l0sx;AOdJ6O&W|%q&7q{3Hq97j}bj4hC@vaG|{y(9;0e{nluJXgHP0I4Ke{F zifkfen^RCU0009(000000004|fB*mqG>Ifh=tO!`$jPbX(t0D(XvArw5Ydnt0MIl5 z0004?0006{RVf71Q%y$HdZCGg(?bnLnlxl&F*Ibs7()|402*RqX@LfV2x*{Flt4`c z29pyiY?#QVY>IkfX`@v3l>H-VA^Jy^Jws>{X&;pyp!E$jGyniJ0wjb82*?qTs(#3+ z?@dia)5!zUdYPyV4^uKvPy_Wq02vH{>KZ*j03Swtu>Vm4f>}xhlnOQ$ODrsvg9IRq zkti^-QY9G}Qc#pcg$*PjAW<4Ag(Q5>uzU(WWbaQx$(G@~PH6BTKqOj(grjmjmKHyg zTUJcW+R_|pba6rTHcbxKwsM5dUe11Y{BUhuf*WGE9wcWHSJa@g5T4o&up2WB%|O!bC|4icccVx1>{1$9B~f`}St9J{NMN1a;AV-=^-7uRTNh>nJliFj0qZ;#V| zt83*UAsWsxm%9_(14~TdYdd&$0)i3(x3!Hz+5@sT)91bQ)CC8|ckRrCi_i0P-SFkR zWC2Z0NmVHDfuuNmwsdn)MCG}VyCa9)hzmp+igttF%N367W*+3W&TVpaJ^vE;V+p#`*2hRpWft?^XKh zyJcIzw~+L3zaeNLmTq4Pb{T=h;ELoFY^X?v(F=`Z4}24p1Jj{C%`( z719|;k98LAu23H69rKwF7*weE%KkR{CuC@q^8R~dI7QzH9+7!XB5gTAd?&6wW31#% z5&c-9;eOq&QEEG2y*#LAS~y47x=?V3NXUgo_oKE6l+Gc-I>qVNjmw@Bx9*7oP+Iq1 zKs%`{FbvXhQ2*s95G1DZ@rSi+Vq)f5hy?b-zu9uckv!pBP;RvzQ16;m2ANgm<52Y( z@@1*o)Sd}?>f!kRk$uv=h#qU`zNzdsU6KLhMUbLEkDs=!24zQ&W$kFb!qxBie5> zsGc0qk>~mrW0-o8Knttr;|`{pk_=+)FtV_7Gk7?95#6!2H)fVLStYExm^$&T9meW6 zKWCEX$Mm2cun_|bmmK{9( zJ371GG^f+K_mME)q)6V_cyoExBqP@1-(EJ4Rw4k|vzDo~PyuI~zKFp9#RB$v0P=92 zMUgmg$VeqRr1jXm-4VZ!&8O>f;khaEI8!qo_Jycl4}0j%Gf*uZpD^`W2@4(%uwMW{ zbN88^mzCMe7%oSxmQYIu!|Q;LPfw{h3nTq!JnI)+^;O%ua7f#$)7*g@TTA7KGr;El zEo}At?w+s1-IAug)F^vkuMc?AKOdUN*b5QWfpcYb;d;3jn<}T8Qn(E`Xqlknu65W9(f|*6^d^3c1Ghk7*7(y))NDrCZE$4YG<{s-S^ghp+ zUytJMdQt3s9Dh&K$Mt>B1ir51lJEv3qOa-&`Eri<{8)#{g6(3OWp2#LYmx6?lD6WH zJZ=)7Js|)m;CpO7bMV@(ty+Ec=?5$99-BwR_2ZL44yY#oK(#2cXK!aMS*oX>mxh}1ifOZht|nFHbj0z=Kf@%T2O z;NZ@yN{XpVRo!Ol>hy5)=asQfBlLoc5fd6LQD~O$y}ie0BvtJUL+ zUSn!1EwvGHmLr8O*t5;n42gw|z_4jf3%1?!_ki$;;T7KnNfdPSl}GhW zg=;cT9vL+mDQj8qZ87W5E_$ys624nx_$8u>9gtq#tX}s=hFRT(PU~Xea0&$64^%}$ zPVXo~-F)JCl6qQE)p1f@<;(IZ#N9Xww_};a&|QxndBI`k0)@jYFk}(p2+E!jD5%#4 z2gFJUL>9N|p|`Y88sx}m$vh6%IO5@rWo^hLWFb*99?0#t%$5|5mxy~X?aKw~`4>?7 zj`JuZn&`mIrfm{Tt`>E4IG!|KOR*9t#DJt;Yo=zGxX!K0 zV+#djbEiFB&qroNVu8-Nowm;C(#KYs>T8omqmbGy&Tvc$MV8W~Www=;v`}N2h5-_k z3la#CSxQ-Joo6A8ltG9rX}AY*?_W>Y_BZJg+DqtWVQr-XjcC?_*2X>ukHEficon5) zGam+f#37kE*!q{MVQn|G8kRBdg6&xAp8p?F(5X?9JRD-Z3MLVw9JV{@|DJ+No}3UJ9=JktoEcZzeIYl1n^?xzG_s6~ZkWVWLKP(4Gm`rhl>>SbCsjmF`bW_GJaM@W83&^U)= zUQ;qF6SfINP$UL0EZ!a6-Me@EQZ{t^h?*#$33xJvJ5h4bkSMvm-0j`Ge7_j(?t6~< z3zVv&U|A(pQmBB$6pEifAb?95>1x;yoSAT9ykTEws61R0RTW@vZOdcZm}Sf`a|&US zmbFxBrXSA9z=VoOvJSBd^u}AIV@qvr=fmp=5%T!;-2Yh~gycv>bO=3H94H)~xWqvP z5GReo?Scp?B9DJh(g&0vp5qiM&sk2-;9x~iP?q?+WN#v-S;MTYdU~m$GdmVK`kfha zbtqa)@k8N|pA7gf!nXWO&+Bg8aW`q0W+pj-i6QZrLbRoo zS&nk?a@x?gS2G3-jsv-tt~iP-w;fD0qZ!-d$%kEYryNVIDMji}o7Y>x=~WR`x|srS zWbOz|yj0^X!E4pM;6OgSm#(-A)3{e|>t$oDg&13Hs)rHN{Zd&3}+unAPN4#Q> zWS-?ou7oUFu$yY$38t;HOe{D4x@xBc5b^#Ro!y=OI@fhz@wbet;;nh%X;m`e?ke*l zE@GkT<0hvC2y{*~RYX%ck`ugR%~b_1!eAwitcb^91YHJk4u&&MTTTk}IDi~gI@~OS zVFSrWu*k!OFq=(QnwX}HH)vi3vEO%hB5y|=Ls|1cY60}zbSfD-HZ}{DLemiP3LX9< z(tREf{yuc?EMLyj^!xV&3X)Ab?hH`s_O2cpS{1#_%cu#O*cT=SWEp=VMIwS?2xvSl z1eRghzk~+%Gk1=!5$^4w&pTaG?{PIXkE#_#_r!dadPR{1=`EuXQhGv00KWQLM~q*N z7UiMZ0o3TJ!9$56XH_AsZrytwu#jR0N#VNhg*l^ARtpv>5o6qy9KD-uOcgaJ97u?} z)eOsCGN7>}LQ6*|7rr?g!!_@w$;5yHSTw<8(bi&1R{J7e+h>?(q4@)(CZGU#L_b4b zoXR-x?B$K&{^a6?9f9Rxq)Q&vZRCXHA+x*Ikv(_!0`5D?n5Tz-af`gEGcdhN)SjJ1 zRX*)K5;H-fuHjV^9_u%6b)5V!5#k5NV32QI3;~DIi1q+GcJC;7`W=^w@(z6-P_i=$ zkxw2;P88brj;bzo;BGtPiVpGX2RTz@L}a`~&>5X?9Tnl#SxmCGtGZl#Rq*mpK7<$# zu1{w)0Dav6=b4e@XjnwaS~3Vi3IxiI|~;d0t*Xo!1x2 z)eLK$6jqs*zIe+lb5QL=)URT_sPzM>ZpDIhF0XF+4$j`ma@@JvTJ>2H=1|62N)o&( zT{;&?_*@SZ^7Rr<6ieP1oRx5Jy-g@6*qV4l&&YNR!mp}V&b|Oe^)h?14okMw7?*ot zW&4$6!^@3*w+fzQt-O6B4jf9sQ@d_e^DNaxSeHfRK$&REB~qMsRPL~x)ozpusHEay^7c%-$pyrktkG4box`TM z6*q!AxT(e{oc(}X=7KpW5b8kOfe!>d{#vc!APj;MAj8|?UOkoy7s&!zbA~jMh=~A$ zB#qQ&(=9V;>p6)Jwo3L;q83gHl#`Q4g^njEhcj-bN~|>D+V3sy6J#pO5prJeO}rG5 zPa*=4rR7TYZS52!zS7WRFwVh?hFdi`nMgj=PD~lYPZ6=TAxxURHD2&x(*Q#j1(<-@ zwqK{Ma+_^j*Cm@~rE(I2LI=vePeb2ez~5V#Dtai0s(OuLianN5r57(f=FWO{@xeKv zb77gy-86FxSzV@F8*=kGjm~c|)0w74g=MDaH*<`~ULu;WEf<@trOZri*5GG1Oy%JA zr9|c9sl2+6EL%%laon}WV&x6n8`c*n@y=+bqMX*98P{7enB9Rw*#dhAPUHaALUa}) zE*4o(s>;Ds$Vh5H5rD7_WHF2@4!+1r<*%?3eHBO?6TON;urucR<;hZ}p=|@!XM+d| zL*uN7h9Cj9`an7GgpcEkRVtVzG*nLX#0*yaJ1U7WJ-?4eV2u8C zXT9HN2pgQteV)6qirg_W(yr%%jD`y$UeJtnF9%8-7T5}!2Y)wU!m>*20Pjc{*DMYJ zE(qli6DTfl5U2vy4C88Cs?-J%Lo!JuoMfCxq$rX%G!8X@zz~EPh#KfnPq)E8kFZ}F z*xE$Yyeth>Ow_=T0io3W+-?l03^ACT0Mg2k2PCH!fkOybnP|YGcy{1$n-+Ct0;Pb6 zf!^5!h@U`C4^VVMb=mr^ssINgwD;8z2%?*{yO6=@*ard2cR3}3jEaavLU`TkT|nF{ zm>146#%8#1ff`W}qkj_GfvIPK++ZZ#bW_#7{P6GX3N&hd&B~fZ>5=NyKg(B7xq!3)o zkxJ1BD6+L8h?1aDSd1%J+ht}rpyevZIms@Z;Sm}{K^iHUiI!HORZ&qNh2xO^f) zmBQv^i$#fUJS}Vmqq(%@%bs;C&ci)+WY%Sg6H`Fy9h1aiL$&V%3zo)STrYAmQuke~ z%Hi2~Z3yf|CXGp?2)ihX0E9!kyHlXVgGdN24LS`_BB9KPiD-zK!LHB|tA+?5L%cc` zTFbi!aKX$1woGkB5N8Oys&%l#2|Sv6u;A8$gR@RqlS-E;R7Abv;BgMB$RKkf8d+Q* z*%IiG35R{)lBVWZmrCPTAZ4e`VIZ4eC58|J1`IQrh}YazhNw+kSaL1P!%d4L7!1e) zF~!3(Fe!zWcPNorR^lvyX=Mj8U@D=_nVlVTr#G&x?zv8E_SN$*(Ugb%N{0C8a@->O?h)q)|nY!LLV80h%1+kw8Qg zh^!S9k5t_?YYIV(3u;L$l%<7ikQ)mHB%Lx#3}B_!tXUH+Bn_iwadB17ZXnghv0B`~ zR8q2{uT>;Jc<7>PkK+_WPypC~kJ~|e6<1MG-)p_@o^qt!^(UvNJLartZ@*0j$(Fx9FOLK&YcB`Np7{U!Vl z$T&b~{RSW;KLT7w@k6_k96PkUF@*4m`R(3af@rsH=pA?7+_32(JOXHTGh`ANl4ZhX zatUX^E`zi)2`s@hgaE71kAN=jAHg}~y5P&qrQF=j-CUNVyO9%)`EEMuD>G|dBMVN# z9m8XWpwn$r{t&fEi=Gj)oRAjuSpsH-A?Z-;}#^Si2?^ZU#* z-0+*eiVmWhdi{xesQ1GKA9IF_oiBNH*s8wwks9zeM($(Ugwb+DIwV)6RMmL6_#F$t z3lP{(n6^+uUAvkYxz8PwPG19^9sS`nVbl`RHo;k95+%y8Zs@0fsxX}V^X2K5QWIRb zS-Cw9G&<0WfG9NW%t{Pyz2rQp3ZOnPW?*6r4DHoSHy-e-6Gsn$WlypI?j<6v6YOEFS_@ls6r4)%!)EaM7*|DN02BQ3U~po3mpg( zr9(YLhP0r8Rs;D~Ki_Q(5mBb8soBorj+OuTut`SUSLyXid_IM1nSpX4_G1R*Z`+0-G6&l}ua;MhX-K zMMD(qi%!dX)_|f>6e3B*6O}Bjh5Q%^Li-Kx65E)gXzcJDpGBFIg4 zX2vG$o2qxN^?J3@BxVT)$h$o>aLE!zCZU2G%TQ-sCli`!YufJ67bq~IiR(??7n=ca zv|CjUu&vO$Wzr5yJ7w`lW_rt9_H)|KYWuOK?DFdZ1>PQhi@EfB5x*NwTl;DDhL-JB zRXu3*RwCSm+Ffle8#{p>87W*1$(Y zGY;lvXYCGB4@$N0GF&$x25Qag{&6|ElF%7ZZrhYb^ zJ&CryxDRpV-MAua4UZ((KMWkQO&b(@Gz}pzD}akRUiZ0_adQcB_#w{Tsd{{}13x5P z6Y=KLGLkIHx51yT(Y>43&3RnTM59BBEm*CuuEDMjjGF6PB924yNxL;2^A`u5=8@w z7{#=rw$m*0qe31AhD&=}3kx9@^s~pc0Pe$G`tQc6T`)b}&)L(>K;2u3YKyAo4dX*J zp_{_hVz%JsSGE8`{D4v)BISqx@DPZPd{Hvsd*&kx(d5AJh3rM`E1Yb`1{arAE0&on zYVu1m8?Lu$10?QN#;jXqFgs71+n2Z6P(^NSXQnHzrDYbysMp$yup(HqHY5r1Y3a7v zy*@jv!Luw{vN8JzZ%}Vt3Z=&#y-nVnKs^zAy)vTQs-?6GH;g6NK#fFdQo|jpYXB;W zr21Go^kv#UwWu+)M zp-S_K1S`71>dP!J*3u(Uk>$8jsxS$bGfmreX~QE-!#>`g06dXXGQeLdks}E*!Dw5_H#ZxvYq6h5Nb901~c9t6^45Q;0r zxDg@Vo!zi61{sHDwzmtC9sA%UP+=JeHVh;?@EtK7Q8SgNNEk^M$Vq5@6I-J$!8J)z zu%VvRAvL~+b(s$Z2o!Jc>1{+@xoT=-UQ+g>XFkpy=&uPlQGQtNtYQ#kOrs+z1dSB1 zTEJj}4#`gN)bz6U=(gq*P`x}L2Z3Y}e%L}_i%X7phSGUp2RH|iAej<9h&YyWkR-Cs zwLeR#f&2%+0{($C?=5<2zhjet74hNrmroFmLP4Hfv;Z8j=avN zY2NY`PB3w(XGxwh-rsE9t?JgVBu(nUn%TpH0kPt!a}`L02(V^_`5|;c)HWsof`w6P z?jnV5WRMqW^X~SCr6c6+Vw6Oc7L-AawhX=~mI_b`1czwzm$%qag8&(tG6M=8f)4}F z0rSD6ZE%r>jd8jsl;km@1`bA;W-;pkixbLM0huujz<>v=Z~;lT)jdXcEAC2^-F&17 z4YQGyGV5RyvS+Fq*>l1#R^{E~YO^Xx$jD@h>}#k!<_y?tu5*%%)hfYk<%GIgl7Sf9 zKnyY>@@vVnX4YCY8pnITLeIKS*kdYvw0lyuv^0}1gug0_`bW6Z*A*IIlCAe7Aqyq1 zM@RNiSJmmu-|#%iR<-NDwaVDGBdTlHK)>PiW#fPSgO{Gp_ITdv#0mU$HymM5foz~& zFHdB8)dY}*K>FWF=M3OlRZ460Z+%dG>32`fD!(+U%B0f#U*58Lti$ozG_6>ZRxhZ^ zKiJB=>q|u550R7eb?JM5HsO)W1>_K)= z@BAOCZ6ARWF(5>W-27YS|46K)FvTV#7%{PuqD_e^LZUVqCM*Gsl2Z)LH(zaS>6B(F znS@!2Gb=w&=aR0q#P_}5d$!^W0ER=dpfeyb{vK)JYhC&5`Mdo+@^@xHuyaObdz||s z^3tQhx6pf}N1LysE?BHqRP?H8eIKn;+l^zwF#58pWM6yH^6`n3O{p}a%{-H}?mX}8 zh;J?Ve_P(sm+`;zERZPgRCE;kX#TcbCfrXpAD0BFBw&#hi!G`nZEG@3k_WTzkv>PZ zQYM}D)#rV+X^g4f%(z<7#W6TS~iPqvXWYjR+XZ~ zF(e?#6%s`dBmoyA&A_-sSE2Fyswx`xc9HrDKJ9`Bs>P%mlwQLNUpl=WcY$;DPQOsS zklY+G(ktz0Q>5u*#G((IXxfrzweCV5cuHbcwk$>*>w&7qylcW)P`lSxmgoCqw%7IN zx1Yz~(I40j&$x#9`G;0(=PEbj?H-yVP-7*OVT$_eNpRt zUJ-tBk=zmb^>9jTi^oa-nfw3u@5SV;&Usfdx?iF5C43X?+W|Jq32$ai52bNd%r@{Exy>osfxb3&ZrIiv$Z~A_ud9dIz{Q{2diHcqP_Gl>4~Y zsDH0V{eK{Zk?8d|I2%^+sKq7KW@N)K)??`$Vap6cL{CRgYrm&H=fyqz(v3$0oh8}7 zR$gD9*^8u`KJ&}Fy7g|Y&3Ef-y5n8Fod5s;002C```&yWtI*xopZ*%XVF3VA|wnJFiNXj%u$&!q`{dd-_T-(l?JjMC{0Q5pE66O^I;Y-Bs^>}=C zQpR8TW54@aJW>a}Ei%ln+$eX*jiEd-Op!4P`;}izucRl)`f9I^s%*ZfwFa^+Uxrqu z+FGgcRc=+1P6=D;H4RCi-cLX1_Sg9;ZEu?R?{(j*j=0SzXVDKrF# z%$X*NCMd&W42-bL7|R&F-L&0D2FQHqn=i}re-#}1)$_07AC{)tIwj)GD4gZYSIX$A z^8Yng-|l3yDVdBbGG=3eYJg|aLz-SXPS_nT042igRKopjEpzp+2TwA$@om3Do5LiG zkrG7)EM{Y9u0L{&S1JSgCn5N1Zjv4&%_J|Rc1kO1*3lbU*0G~hQ4~r_A~(W7`H}~u zX2}mRfeeQXsoo8`MRmoe@ZgP&XzK6fTpfE$r@Ibmr5%(zQ$@&IKhD;-+VWF|$lC%R z>kz`40{tT^b(&-dNg_#wK5b8XPt#jvQ` zV!OD^N|%qgadRzw8TbDE)m zTR(i3Mi^Ab1GuD4+!-i+f!IX9RZr(DwxTBwW^~l;^sCVNDLwUj;Z_8Pna-iwatF1$ zUKwM?806_Y9C3%Qx^{WnVc6PsPUmWL&XYyAI@4K8sK;H+2F+G#h$<;GV>M8cFdcH{ zXtY@HZCc(oVjA$;rpTK-ly7n0#Vl?%x1El@{>r=aA|TBOLMAre4xmqhVFxrFgYa$( zM`*GHk|_ugXS6aNt^tjchvhwdb zkc=oGgAqLiT)Fql@pb&&jr5lJ)H=L1CbErbrVJ7=2%!~#j98xKWg~2=k=Zy#$~%(l zsnb^a?_jr7;bC6V%pFO4WEn$li$=kYS_sp%%&r98rpPuCXhg|T_5nxirzs((REn&1 z218{IeyxnLrsj*gQ;dzHr@txQso;lpr>h1<%;Z@1yla|_>KE{-3H5*ypLvCy0$`?A7)Z**SJuc}4Y+^_yFH%SwvkPC>vlN7&BgPW4Wixhi2(K@fBK zm3aahAxGJWrByqYs#w!%%3EHd*H<8zqEZ=>M2aGnTehn4bye4Rmi%RR+|i*xgov@4 zNHRteGeK|;5EG*Wb5iQkXot?F^o|WL`E?IEDXVAB&igcnV~XP zq|%WQs!C=yEi{s$Fhy%?!Rc#wwO5k!cHVbyX)el>E0YVGaT?;4DGO9qA}n889(g|4 zA^q||g@o)=yG4G>bB|Trs3x31T~J>2FT_VhPoQ-kL|C^#tRD=pp<|XnE=r!K$z28e zART9u-{vo@KxsoDPN>t$8+=RkJNCRgvtAz$Hs-k55E3j>Vk9(N)~k4{OIxMUF$IAM zArcU&sX9PJ7%FC_|95aY0P1lrt5kDTJ-&LIYWK*^xfd-u4IyOAuo*8IG+QFhAGN@( z^)XvITXg%*iBEQ>`kb9em?sI$=BQhd+g6tPSq^br+)*CrJjnZ8&V4g8= zR}K6q!Q9rXV!3f`^m7bg-k^9PdIA}EO|)kUH|~=XaorW$hlp{8W)Q`Tb8Qb)h4SX% zhZvh`aE@$Ju~QX1ZBqTs@9{sk^nE|z{s(F+mjx-Hut>=r9H{kOykyM8jK(xqAg}&CtGmtt9RG&IPFxy*M*A~S%%9Drp8GmC^Q8W1xwj-xJ)6bHUXP#6*DA6 zwNNCDXru~FHmuZYOTQ*diG^y?sk6#3Jf_M7;OOEd+Ce=Nw-Sy=AFm;Kvo`zGi zQzhEJzZ6CJ?VPI+a&4AM}nrj%4cY_mj^BNCt`Tj z&cSIOV)6#+o?g!-Q8#xfqPvl{GHlsZbY5DP+FE3fPNx*ElHQ4sX>6ATWjE0DytGYX z=3zX9(9$f1;x(Nbx!c5Uq}@@bNewE)OdqK#w4>3E%6+OQbhmoonxxfHcB@#T`ZYZ&mBxdckI5`9T-E%;W4Jk( z13_nJR1YL~gQBJKP|Om-71*iV0A+4iMxv%+QBo@Nu%>{RSRSNo;Zx8S;3i1lyS$Sl zG}fuajjrGB?y1J7JTh{I2$TbwAxex>t`+zPYGH8643(lNbaS4`MiNUv=M`14c(Msm zc-m6q$Ld_&I=NttqAYDY8r02$WnNj3>m`&nJX^b+5qPG9h#*A<=soiA4k^7l^5r?m zVB8`=t9?iw|8L-p;3oeQ6wP@l?2b8nU_aILYD48EDC`^MbxlV zL4uW+-nfUK-u| zTp@QEXsLrDC}CR2N~BgnVjFf{bb^p%h)p}ZytQ_9)KV;^KBKyUbKHXHifXBD^s=SU zT-(hu$hw8lXWmo!s%NUiibR6Qyb=Jh2pp0HDo>K9l-%`rj)RpQg7Q5xlR|V&L&bFZszs4Xo~R!$ z+VVpCph%B+szDyQleIfdn|(Tyvh7K}q}V6d$xU-`i45i+U4{7w#>^5If_|AuKNKH4 z2;dO9w5jey>(&Q^p@H>S?SUh8x>;>1By^kkt==qK+7RW*XD X*@YyrKU}1j|Ha&qP81{$Q;|c!dWL}^ literal 0 HcmV?d00001 diff --git a/data/cs_app_vars.rda b/data/cs_app_vars.rda new file mode 100644 index 0000000000000000000000000000000000000000..8fc6fc2e2295de9a582e05bcd6e1a0fb10126fe0 GIT binary patch literal 2109 zcmV-D2*US5T4*^jL0KkKSqZZ|KLCX1A*WO-wv~S zxo+LvsXMoH+ib-E0IC!k3S>`2)XfTcPXwQ(Jg1a2)6uE4n`l$hYDR~Y4^!001{@g% zjR0iR5Ys`BVi-Ws8Zj{%000`Er=&qAk^lez007fK000002~SERP^J|2rcipGnx2zG z%4B}1dPYEK84Ux}^dlh9I5G_y0Li8yrh_2FFoB>nVq!D^03=9FPg5qQ69^h2dNkEM z(@4poJxw(A89b(&P-*ElriZm3=$mlRV9Bim9vmbFHB&RGl8})}EV2NGgh~-PAc3G5 zG?N-a_dy6ktt3cENP-Z%zb62MtN(6B@-ZO=u02gdPJUPJv1oTw?Y8K(9`gy2m7J8ricg0`#3moS*gCJNf>89%L@ZR6HsaP|L&}fNO z5xA-$6D0LD93v>HTEr*YQS@(vIB^!@Cnc=oE#WR=Ul_(|eG;>&Aa&g+%Fe97VVDqL z@EcSiNsvt)tR$dJ1YVLjj6MZeifwMl@n*9omY|55=OWmw#OI)|St^n?2tbAiNFj#C z8(B7ip^Om0B5V>8A*7NL{Nz9g=4m99F}A^~sAU2r ztCs@N5K1W|_rI~p5C_{rJWxQc7 z>nHs^Yo-e31|_g$1C16ZhRc?Q^$=CE4T5lH%3`Di}jotvCC4XJ{b_ymBtjU zD&*}|mUf7>)~!(GN$ln+!dTBFCL%7FiQvLQ&J>S&{!aqF`}(;C&M@1PAmI5#zR~<+TK=wH~^VgL1rTQ-cR7=MPP#)whPz%Vb z;|0|h>z1v1XU4M^DAK0=y=!v0QL2U=5Fc{jguuAlC6M@jJe_%X9Ya}NY$yZWwXboc z7Hwj$CnO{ez$=t6-_&y(i+rT&fC(xc7(SgP7NpB3xrxqtfHf4HD6DcKhQfU|@kV!xoCIr8A;vg1+ z5UDdUA|^BJfQUkK?eXa#g8w9XlGONSTo1Xs?e%Fq9Pp2a)Z#;dsTYs zG{syEoQlVI=sT(+1W-_4iF2?~wmUY)p-Vy{($cCThJuenY83(jcQLlc;95%<2T7m% zzZ(8k%83m() zs37LG&Q}^VNFQ+r2?10KP{=0wC|Z#$LQvE<^Jvpdr4g>aa@jH*hC^D)*qq8I_+?5! z)x!36e$F`iF1Y?ig8VS?Pqx6|#}PsVBKRy7%&jBAWCpJ!VHWuEDw&xX43gH73pA>5 z!YL;yk#erZ=8ISmO9U;aW$W{Cv|%GfhBh$_C6g{=x2ly_d6?`OATxYXnM<_52{YwJ zfv-k|QqJM8!+Uw}nVcA0d3j-QoGG8$MOP8k-$%5(-enFQYk*@KX}iV+$lPht1lKXh zW%jv<&R$+C*vRVXHQiOEgbVPU%g(R6vFG%H?QVvnPR&mCTpf^_M*ggDI(+Ie76q7% zf%C)%i)@Yb#0aTEN`jc|UnRsFkl#z-AeW{&jD)4mOr?V+$sR4V4q$}6-S1M8Obkuu ze7zJFkg!R547p&<;bqef18zby4`6N+4g$i^#FQMDnzS*ouc;Z!ixWO89|HZoIr0Sq zlOuo4Yeu)a1e|D*vr@<_gnRjJItvijrA5WK!g6j`6yquzNthI|-fCJ~V#QuLG&cvTSWE$BSXSQ&i)}_hBzLX09;FsVwNsi(w=8oG|W1Mgtg-+H4$_gn2pQh@oB) zRN@9H(I4&`2^?cJ_vVF({#HdLaK8KIq%z7-i3np8V?zRgm^qGvO5`&WG6w%T+PZpt z#s$d2V3j90EXGy;ycG7LPI)gli=s&<8S1!+S!&6T$=N;Yok1h5Gz}6Ezf?g+A*7C zd#n~k<2kX6%dE)E-Q?Gi9eYH?Z2kV*m^rbrzGVdkQ@YHg!&5Z=vJGUY-y zF|b9N0j#en!iZ$WONbwuEFAlM3HJ)5U6RME8ufD^*z-i+rcA6`8kknFPF`{+4XJ?m}ZExg!{EdjxVkUaD n@cgsqmO_kY!?BCPeXF@hLEt*(Cd5orU#Pp1DZ+$+Z!mPQP~O&7 literal 0 HcmV?d00001 diff --git a/data/cs_available_data.rda b/data/cs_available_data.rda new file mode 100644 index 0000000000000000000000000000000000000000..32aa47c3d766c5c2618d2077faab27fc02f0f5a7 GIT binary patch literal 4537 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 X%1?{ppZ)Y%pZ+f7ig2MJSU*~P4v@(W literal 0 HcmV?d00001 diff --git a/dev/app.R b/dev/app.R index c1ebc1e5..b420f394 100644 --- a/dev/app.R +++ b/dev/app.R @@ -15,11 +15,49 @@ merged_data <- merge_meta_with_data( data = my_raw_data, meta = metadata ) + +# Build a version of `app_data` & app_vars +app_data <- get_appdata(data = merged_data, meta = metadata) +app_vars <- get_meta_vars(data = app_data, meta = metadata) + +# Build a 'app_tables' +app_tables <- lapply( + setNames(names(app_data), names(app_data)), \(x){ + create_table(app_data[[x]], expected_columns = names(app_vars$items[[x]])) + }) + +# Build a 'available_data' +available_data <- get_available_data( + data = app_data, + tables = app_tables, + all_forms = app_vars$all_forms, + form_repeat_name = with( + meta[["table_names"]], + table_name[raw_name == "form_repeat"] + ) |> + tryCatch(error = \(e) "N") +) # tempdir not useful for production mode data_folder <- "." -data_path <- file.path(data_folder, - "merged_data.rds") -saveRDS(merged_data, data_path) +# data_path <- file.path(data_folder, +# "merged_data.rds") +# saveRDS(merged_data, data_path) +# Current saves both RDS and Parquet for data frames for continuity purposes +save_objs <- c( + "metadata", + "app_data", + "app_vars", + "app_tables", + "available_data") +purrr::walk(save_objs, function(x){ + rds_file <- file.path(data_folder, paste0(x, ".rds")) + saveRDS(get(x), rds_file) + if(inherits(get(x), "data.frame")) { + pq_file <- file.path(data_folder, paste0(x, ".parquet")) + arrow::write_parquet(get(x), pq_file) + } +}) + db_path <- file.path(data_folder, "user_db.sqlite") # if test_mode == FALSE, you'll need to setup... diff --git a/dev/run_dev.R b/dev/run_dev.R index bf2fecd3..20f7637e 100644 --- a/dev/run_dev.R +++ b/dev/run_dev.R @@ -20,12 +20,19 @@ load_and_run_app <- function(){ old_golem_config <- Sys.getenv("GOLEM_CONFIG_ACTIVE") Sys.setenv("GOLEM_CONFIG_ACTIVE" = "dev") + # create db + db_path <- file.path(temp_folder, "user_db.sqlite") + if(file.exists(db_path)) file.remove(db_path) + db_create(get_review_data(clinsightful_data), + db_path = db_path + ) + run_app( data_folder = temp_folder, onStart = \(){onStop(\(){ unlink(temp_folder, recursive = TRUE); Sys.setenv("GOLEM_CONFIG_ACTIVE" = old_golem_config) - })} + })} ) } diff --git a/inst/golem-config.yml b/inst/golem-config.yml index 8f89bb26..f73d673d 100644 --- a/inst/golem-config.yml +++ b/inst/golem-config.yml @@ -5,6 +5,10 @@ default: user_identification: test_user study_data: !expr clinsight::clinsightful_data meta_data: !expr clinsight::metadata + app_data: !expr clinsight::cs_app_data + app_vars: !expr clinsight::cs_app_vars + app_tables: !expr clinsight::cs_app_tables + available_data: !expr clinsight::cs_available_data user_db: user_db.sqlite user_roles: Administrator: admin @@ -17,8 +21,12 @@ default: dev: golem_wd: !expr golem::pkg_path() test: - study_data: study_data.rds - meta_data: metadata.rds + study_data: clinsight_data.rds + meta_data: meta_data.rds + app_data: app_data.rds + app_vars: app_vars.rds + app_tables: app_tables.rds + available_data: available_data.rds shinymanager: app_prod: yes user_identification: shinymanager diff --git a/man/cs_app_data.Rd b/man/cs_app_data.Rd new file mode 100644 index 00000000..08471212 --- /dev/null +++ b/man/cs_app_data.Rd @@ -0,0 +1,317 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/data.R +\docType{data} +\name{cs_app_data} +\alias{cs_app_data} +\title{Application Data} +\format{ +\subsection{\code{cs_app_data}: A list with 11 objects.}{ + +\if{html}{\out{
}}\preformatted{str(cs_app_data) +#> List of 11 +#> $ Adverse events : advrs_vn [719 x 22] (S3: adverse_events/common_forms/tbl_df/tbl/data.frame) +#> ..$ site_code : chr [1:719] "BEL04" "BEL04" "BEL04" "BEL04" ... +#> ..$ subject_id : chr [1:719] "BEL_04_772" "BEL_04_772" "BEL_04_772" "BEL_04_772" ... +#> ..$ event_id : chr [1:719] "COMMON_AE" "COMMON_AE" "COMMON_AE" "COMMON_AE" ... +#> ..$ event_date : Date[1:719], format: "2023-08-31" "2023-08-31" ... +#> ..$ event_repeat : int [1:719] 1 1 1 1 1 1 1 1 2 2 ... +#> ..$ form_id : chr [1:719] "AE" "AE" "AE" "AE" ... +#> ..$ form_repeat : int [1:719] 1 1 1 1 1 1 1 1 2 2 ... +#> ..$ edit_date_time: POSIXct[1:719], format: "2023-08-31 12:09:00" "2023-08-31 12:09:00" ... +#> ..$ day : 'difftime' num [1:719] 87 87 87 87 ... +#> .. ..- attr(*, "units")= chr "days" +#> ..$ event_name : chr [1:719] "Any visit" "Any visit" "Any visit" "Any visit" ... +#> ..$ event_label : Factor w/ 8 levels "SCR","V1","V2",..: NA NA NA NA NA NA NA NA NA NA ... +#> ..$ form_type : chr [1:719] "common_forms" "common_forms" "common_forms" "common_forms" ... +#> ..$ item_name : chr [1:719] "AE Number" "AE Name" "AESI" "AE start date" ... +#> ..$ item_type : chr [1:719] "other" "other" "other" "other" ... +#> ..$ item_group : chr [1:719] "Adverse events" "Adverse events" "Adverse events" "Adverse events" ... +#> ..$ item_unit : chr [1:719] "(unit missing)" "(unit missing)" "(unit missing)" "(unit missing)" ... +#> ..$ lower_lim : num [1:719] NA NA NA NA NA NA NA NA NA NA ... +#> ..$ upper_lim : num [1:719] NA NA NA NA NA NA NA NA NA NA ... +#> ..$ item_value : chr [1:719] "1" "Hypotension" "None" "2023-07-07" ... +#> ..$ significance : chr [1:719] NA NA NA NA ... +#> ..$ reason_notdone: chr [1:719] NA NA NA NA ... +#> ..$ region : chr [1:719] "BEL" "BEL" "BEL" "BEL" ... +#> ..- attr(*, "synch_time")= chr "2023-09-15 10:10:00 UTC" +#> $ CBC regular : continus [381 x 25] (S3: continuous/tbl_df/tbl/data.frame) +#> ..$ site_code : chr [1:381] "BEL04" "BEL04" "BEL04" "BEL04" ... +#> ..$ subject_id : chr [1:381] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... +#> ..$ event_id : chr [1:381] "SCR" "SCR" "SCR" "SCR" ... +#> ..$ event_date : Date[1:381], format: "2023-06-05" "2023-06-05" ... +#> ..$ event_repeat : int [1:381] 1 1 1 1 1 1 1 1 1 1 ... +#> ..$ form_id : chr [1:381] "LBHM" "LBHM" "LBHM" "LBHM" ... +#> ..$ form_repeat : int [1:381] 1 1 1 1 1 1 2 2 2 2 ... +#> ..$ edit_date_time: POSIXct[1:381], format: "2023-07-05 12:29:00" "2023-07-05 12:29:00" ... +#> ..$ day : 'difftime' num [1:381] 0 0 0 0 ... +#> .. ..- attr(*, "units")= chr "days" +#> ..$ event_name : chr [1:381] "Screening" "Screening" "Screening" "Screening" ... +#> ..$ event_label : Factor w/ 8 levels "SCR","V1","V2",..: 1 1 1 1 1 1 2 2 2 2 ... +#> ..$ form_type : chr [1:381] "study_forms" "study_forms" "study_forms" "study_forms" ... +#> ..$ item_name : Factor w/ 6 levels "Haemoglobin",..: 4 5 6 1 2 3 4 5 6 1 ... +#> ..$ item_type : chr [1:381] "continuous" "continuous" "continuous" "continuous" ... +#> ..$ item_group : chr [1:381] "CBC regular" "CBC regular" "CBC regular" "CBC regular" ... +#> ..$ item_unit : chr [1:381] "10^9/L" "10^9/L" "10^9/L" "g/dL" ... +#> ..$ lower_lim : num [1:381] 1.8 1.4 0.2 11.9 0.37 150 1.8 1.4 0.2 11.9 ... +#> ..$ upper_lim : num [1:381] 7.2 4 1 14.5 0.47 400 7.2 4 1 14.5 ... +#> ..$ item_value : num [1:381] 4.16 1.7 0.12 11.5 0.25 ... +#> ..$ significance : Factor w/ 5 levels "within limits",..: 2 1 2 2 2 2 2 1 2 2 ... +#> ..$ reason_notdone: chr [1:381] NA NA NA NA ... +#> ..$ region : chr [1:381] "BEL" "BEL" "BEL" "BEL" ... +#> ..$ value_scaled : num [1:381] 0.437 0.115 -0.1 -0.154 -1.2 ... +#> ..$ out_of_lim : Factor w/ 2 levels "1","0": 2 2 1 1 1 1 1 2 1 1 ... +#> ..$ text_label : chr [1:381] "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 4.16 10^9/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 1.7 10^9/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 0.12 10^9/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 11.5 g/dL" ... +#> $ Conc. Procedures: cnc_prcd [28 x 22] (S3: conc_procedures/common_forms/tbl_df/tbl/data.frame) +#> ..$ site_code : chr [1:28] "BEL07" "BEL07" "BEL07" "BEL07" ... +#> ..$ subject_id : chr [1:28] "BEL_07_645" "BEL_07_645" "BEL_07_645" "BEL_07_645" ... +#> ..$ event_id : chr [1:28] "COMMON_PR" "COMMON_PR" "COMMON_PR" "COMMON_PR" ... +#> ..$ event_date : Date[1:28], format: "2023-09-14" "2023-09-14" ... +#> ..$ event_repeat : int [1:28] 1 1 1 1 1 1 2 2 2 2 ... +#> ..$ form_id : chr [1:28] "CP" "CP" "CP" "CP" ... +#> ..$ form_repeat : int [1:28] 1 1 1 1 1 1 2 2 2 2 ... +#> ..$ edit_date_time: POSIXct[1:28], format: "2023-09-14 09:37:00" "2023-09-14 09:37:00" ... +#> ..$ day : 'difftime' num [1:28] 101 101 101 101 ... +#> .. ..- attr(*, "units")= chr "days" +#> ..$ event_name : chr [1:28] "Any visit" "Any visit" "Any visit" "Any visit" ... +#> ..$ event_label : Factor w/ 8 levels "SCR","V1","V2",..: NA NA NA NA NA NA NA NA NA NA ... +#> ..$ form_type : chr [1:28] "common_forms" "common_forms" "common_forms" "common_forms" ... +#> ..$ item_name : chr [1:28] "CP Number" "CP Name" "CP Indication" "CP Start Date" ... +#> ..$ item_type : chr [1:28] "other" "other" "other" "other" ... +#> ..$ item_group : chr [1:28] "Conc. Procedures" "Conc. Procedures" "Conc. Procedures" "Conc. Procedures" ... +#> ..$ item_unit : chr [1:28] "(unit missing)" "(unit missing)" "(unit missing)" "(unit missing)" ... +#> ..$ lower_lim : num [1:28] NA NA NA NA NA NA NA NA NA NA ... +#> ..$ upper_lim : num [1:28] NA NA NA NA NA NA NA NA NA NA ... +#> ..$ item_value : chr [1:28] "1" "Appendectomy" "Prophylaxis" "2019-NK-NK" ... +#> ..$ significance : chr [1:28] NA NA NA NA ... +#> ..$ reason_notdone: chr [1:28] NA NA NA NA ... +#> ..$ region : chr [1:28] "BEL" "BEL" "BEL" "BEL" ... +#> ..- attr(*, "synch_time")= chr "2023-09-15 10:10:00 UTC" +#> $ Electrolytes : continus [275 x 25] (S3: continuous/tbl_df/tbl/data.frame) +#> ..$ site_code : chr [1:275] "BEL04" "BEL04" "BEL04" "BEL04" ... +#> ..$ subject_id : chr [1:275] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... +#> ..$ event_id : chr [1:275] "SCR" "SCR" "SCR" "SCR" ... +#> ..$ event_date : Date[1:275], format: "2023-06-05" "2023-06-05" ... +#> ..$ event_repeat : int [1:275] 1 1 1 1 1 1 1 1 1 1 ... +#> ..$ form_id : chr [1:275] "LBSER" "LBSER" "LBSER" "LBSER" ... +#> ..$ form_repeat : int [1:275] 1 1 1 1 1 1 2 2 2 2 ... +#> ..$ edit_date_time: POSIXct[1:275], format: "2023-06-23 09:00:00" "2023-06-23 09:00:00" ... +#> ..$ day : 'difftime' num [1:275] 0 0 0 0 ... +#> .. ..- attr(*, "units")= chr "days" +#> ..$ event_name : chr [1:275] "Screening" "Screening" "Screening" "Screening" ... +#> ..$ event_label : Factor w/ 8 levels "SCR","V1","V2",..: 1 1 1 1 1 1 2 2 2 2 ... +#> ..$ form_type : chr [1:275] "study_forms" "study_forms" "study_forms" "study_forms" ... +#> ..$ item_name : Factor w/ 6 levels "Sodium","Potassium",..: 1 2 3 4 5 6 1 2 3 4 ... +#> ..$ item_type : chr [1:275] "continuous" "continuous" "continuous" "continuous" ... +#> ..$ item_group : chr [1:275] "Electrolytes" "Electrolytes" "Electrolytes" "Electrolytes" ... +#> ..$ item_unit : chr [1:275] "mmol/L" "mmol/L" "mmol/L" "mmol/L" ... +#> ..$ lower_lim : num [1:275] 136 3 98 22 2.15 0.66 136 3 98 22 ... +#> ..$ upper_lim : num [1:275] 145 4.5 107 29 2.55 1.07 145 4.5 107 29 ... +#> ..$ item_value : num [1:275] 138 4.5 105 20.5 2.26 0.87 138 4.14 103 23 ... +#> ..$ significance : Factor w/ 5 levels "within limits",..: 1 2 1 3 1 1 1 2 1 1 ... +#> ..$ reason_notdone: chr [1:275] NA NA NA NA ... +#> ..$ region : chr [1:275] "BEL" "BEL" "BEL" "BEL" ... +#> ..$ value_scaled : num [1:275] 0.222 1 0.778 -0.214 0.275 ... +#> ..$ out_of_lim : Factor w/ 2 levels "0","1": 1 1 1 2 1 1 1 1 1 1 ... +#> ..$ text_label : chr [1:275] "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 138 mmol/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 4.5 mmol/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 105 mmol/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 20.5 mmol/L" ... +#> $ General : general [261 x 22] (S3: general/tbl_df/tbl/data.frame) +#> ..$ site_code : chr [1:261] "BEL04" "BEL04" "BEL04" "BEL04" ... +#> ..$ subject_id : chr [1:261] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... +#> ..$ event_id : chr [1:261] "SCR" "SCR" "SCR" "SCR" ... +#> ..$ event_date : Date[1:261], format: "2023-06-05" "2023-06-05" ... +#> ..$ event_repeat : int [1:261] 1 1 1 1 1 1 1 1 1 1 ... +#> ..$ form_id : chr [1:261] "DM" "DM" "DM" "DM" ... +#> ..$ form_repeat : int [1:261] 1 1 1 1 1 1 1 1 1 1 ... +#> ..$ edit_date_time: POSIXct[1:261], format: "2023-06-23 08:31:00" "2023-06-23 08:31:00" ... +#> ..$ day : 'difftime' num [1:261] 0 0 0 0 ... +#> .. ..- attr(*, "units")= chr "days" +#> ..$ event_name : chr [1:261] "Screening" "Screening" "Screening" "Screening" ... +#> ..$ event_label : Factor w/ 8 levels "SCR","V1","V2",..: 1 1 1 1 1 1 1 1 1 2 ... +#> ..$ form_type : chr [1:261] "general" "general" "general" "general" ... +#> ..$ item_name : chr [1:261] "Age" "Sex" "ChildbearingPotential" "MenopauseReason" ... +#> ..$ item_type : chr [1:261] "other" "other" "other" "other" ... +#> ..$ item_group : chr [1:261] "General" "General" "General" "General" ... +#> ..$ item_unit : chr [1:261] "(unit missing)" "(unit missing)" "(unit missing)" "(unit missing)" ... +#> ..$ lower_lim : num [1:261] NA NA NA NA NA NA NA NA NA NA ... +#> ..$ upper_lim : num [1:261] NA NA NA NA NA NA NA NA NA NA ... +#> ..$ item_value : chr [1:261] "88" "Male" "No" "Postmenopausal" ... +#> ..$ significance : chr [1:261] NA NA NA NA ... +#> ..$ reason_notdone: chr [1:261] NA NA NA NA ... +#> ..$ region : chr [1:261] "BEL" "BEL" "BEL" "BEL" ... +#> ..- attr(*, "synch_time")= chr "2023-09-15 10:10:00 UTC" +#> $ Liver function : continus [180 x 25] (S3: continuous/tbl_df/tbl/data.frame) +#> ..$ site_code : chr [1:180] "BEL04" "BEL04" "BEL04" "BEL04" ... +#> ..$ subject_id : chr [1:180] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... +#> ..$ event_id : chr [1:180] "SCR" "SCR" "SCR" "SCR" ... +#> ..$ event_date : Date[1:180], format: "2023-06-05" "2023-06-05" ... +#> ..$ event_repeat : int [1:180] 1 1 1 1 1 1 1 1 3 3 ... +#> ..$ form_id : chr [1:180] "LBSER" "LBSER" "LBSER" "LBSER" ... +#> ..$ form_repeat : int [1:180] 1 1 1 1 2 2 2 2 3 3 ... +#> ..$ edit_date_time: POSIXct[1:180], format: "2023-06-23 09:00:00" "2023-07-05 12:33:00" ... +#> ..$ day : 'difftime' num [1:180] 0 0 0 0 ... +#> .. ..- attr(*, "units")= chr "days" +#> ..$ event_name : chr [1:180] "Screening" "Screening" "Screening" "Screening" ... +#> ..$ event_label : Factor w/ 8 levels "SCR","V1","V2",..: 1 1 1 1 2 2 2 2 4 4 ... +#> ..$ form_type : chr [1:180] "study_forms" "study_forms" "study_forms" "study_forms" ... +#> ..$ item_name : Factor w/ 4 levels "Bilirubin","AST",..: 1 2 3 4 1 2 3 4 1 2 ... +#> ..$ item_type : chr [1:180] "continuous" "continuous" "continuous" "continuous" ... +#> ..$ item_group : chr [1:180] "Liver function" "Liver function" "Liver function" "Liver function" ... +#> ..$ item_unit : chr [1:180] "µmol/L" "U/L" "U/L" "U/L" ... +#> ..$ lower_lim : num [1:180] 0 10 10 5 0 10 10 5 0 10 ... +#> ..$ upper_lim : num [1:180] 21 35 25 36 21 35 25 36 21 35 ... +#> ..$ item_value : num [1:180] 6 21 35 24 11 32 45 25 8 43 ... +#> ..$ significance : Factor w/ 5 levels "within limits",..: 1 2 2 1 1 1 2 1 1 2 ... +#> ..$ reason_notdone: chr [1:180] NA NA NA NA ... +#> ..$ region : chr [1:180] "BEL" "BEL" "BEL" "BEL" ... +#> ..$ value_scaled : num [1:180] 0.286 0.44 1.667 0.613 0.524 ... +#> ..$ out_of_lim : Factor w/ 2 levels "0","1": 1 1 2 1 1 1 2 1 1 2 ... +#> ..$ text_label : chr [1:180] "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 6 µmol/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 21 U/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 35 U/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 24 U/L" ... +#> $ Medical History : mdcl_hst [757 x 22] (S3: medical_history/common_forms/tbl_df/tbl/data.frame) +#> ..$ site_code : chr [1:757] "BEL04" "BEL04" "BEL04" "BEL04" ... +#> ..$ subject_id : chr [1:757] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... +#> ..$ event_id : chr [1:757] "COMMON_MH" "COMMON_MH" "COMMON_MH" "COMMON_MH" ... +#> ..$ event_date : Date[1:757], format: "2023-06-23" "2023-06-23" ... +#> ..$ event_repeat : int [1:757] 1 1 1 1 1 1 1 1 2 2 ... +#> ..$ form_id : chr [1:757] "MH" "MH" "MH" "MH" ... +#> ..$ form_repeat : int [1:757] 1 1 1 1 1 1 1 1 2 2 ... +#> ..$ edit_date_time: POSIXct[1:757], format: "2023-06-23 09:12:00" "2023-06-23 09:12:00" ... +#> ..$ day : 'difftime' num [1:757] 18 18 18 18 ... +#> .. ..- attr(*, "units")= chr "days" +#> ..$ event_name : chr [1:757] "Any visit" "Any visit" "Any visit" "Any visit" ... +#> ..$ event_label : Factor w/ 8 levels "SCR","V1","V2",..: NA NA NA NA NA NA NA NA NA NA ... +#> ..$ form_type : chr [1:757] "common_forms" "common_forms" "common_forms" "common_forms" ... +#> ..$ item_name : chr [1:757] "MH Number" "MH Name" "MH Ongoing" "MH Treatment" ... +#> ..$ item_type : chr [1:757] "other" "other" "other" "other" ... +#> ..$ item_group : chr [1:757] "Medical History" "Medical History" "Medical History" "Medical History" ... +#> ..$ item_unit : chr [1:757] "(unit missing)" "(unit missing)" "(unit missing)" "(unit missing)" ... +#> ..$ lower_lim : num [1:757] NA NA NA NA NA NA NA NA NA NA ... +#> ..$ upper_lim : num [1:757] NA NA NA NA NA NA NA NA NA NA ... +#> ..$ item_value : chr [1:757] "1" "Epilepsy" "Yes" "Medication" ... +#> ..$ significance : chr [1:757] NA NA NA NA ... +#> ..$ reason_notdone: chr [1:757] NA NA NA NA ... +#> ..$ region : chr [1:757] "BEL" "BEL" "BEL" "BEL" ... +#> ..- attr(*, "synch_time")= chr "2023-09-15 10:10:00 UTC" +#> $ Medication : medicatn [2,856 x 22] (S3: medication/common_forms/tbl_df/tbl/data.frame) +#> ..$ site_code : chr [1:2856] "BEL04" "BEL04" "BEL04" "BEL04" ... +#> ..$ subject_id : chr [1:2856] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... +#> ..$ event_id : chr [1:2856] "COMMON_CM" "COMMON_CM" "COMMON_CM" "COMMON_CM" ... +#> ..$ event_date : Date[1:2856], format: "2023-06-23" "2023-06-23" ... +#> ..$ event_repeat : int [1:2856] 1 1 1 1 1 1 1 1 1 1 ... +#> ..$ form_id : chr [1:2856] "CM" "CM" "CM" "CM" ... +#> ..$ form_repeat : int [1:2856] 1 1 1 1 1 1 1 1 1 1 ... +#> ..$ edit_date_time: POSIXct[1:2856], format: "2023-06-23 09:17:00" "2023-06-23 09:17:00" ... +#> ..$ day : 'difftime' num [1:2856] 18 18 18 18 ... +#> .. ..- attr(*, "units")= chr "days" +#> ..$ event_name : chr [1:2856] "Any visit" "Any visit" "Any visit" "Any visit" ... +#> ..$ event_label : Factor w/ 8 levels "SCR","V1","V2",..: NA NA NA NA NA NA NA NA NA NA ... +#> ..$ form_type : chr [1:2856] "common_forms" "common_forms" "common_forms" "common_forms" ... +#> ..$ item_name : chr [1:2856] "CM Number" "CM Name" "CM Indication" "CM Ongoing" ... +#> ..$ item_type : chr [1:2856] "other" "other" "other" "other" ... +#> ..$ item_group : chr [1:2856] "Medication" "Medication" "Medication" "Medication" ... +#> ..$ item_unit : chr [1:2856] "(unit missing)" "(unit missing)" "(unit missing)" "(unit missing)" ... +#> ..$ lower_lim : num [1:2856] NA NA NA NA NA NA NA NA NA NA ... +#> ..$ upper_lim : num [1:2856] NA NA NA NA NA NA NA NA NA NA ... +#> ..$ item_value : chr [1:2856] "1" "Paracetamol (Gliigestatrilat)" "Prophylaxis" "Yes" ... +#> ..$ significance : chr [1:2856] NA NA NA NA ... +#> ..$ reason_notdone: chr [1:2856] NA NA NA NA ... +#> ..$ region : chr [1:2856] "BEL" "BEL" "BEL" "BEL" ... +#> ..- attr(*, "synch_time")= chr "2023-09-15 10:10:00 UTC" +#> $ Renal function : continus [135 x 25] (S3: continuous/tbl_df/tbl/data.frame) +#> ..$ site_code : chr [1:135] "BEL04" "BEL04" "BEL04" "BEL04" ... +#> ..$ subject_id : chr [1:135] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... +#> ..$ event_id : chr [1:135] "SCR" "SCR" "SCR" "VIS1" ... +#> ..$ event_date : Date[1:135], format: "2023-06-05" "2023-06-05" ... +#> ..$ event_repeat : int [1:135] 1 1 1 1 1 1 3 3 3 5 ... +#> ..$ form_id : chr [1:135] "LBSER" "LBSER" "LBSER" "LBSER" ... +#> ..$ form_repeat : int [1:135] 1 1 1 2 2 2 3 3 3 4 ... +#> ..$ edit_date_time: POSIXct[1:135], format: "2023-08-18 15:39:00" "2023-08-18 15:46:00" ... +#> ..$ day : 'difftime' num [1:135] 0 0 0 30 ... +#> .. ..- attr(*, "units")= chr "days" +#> ..$ event_name : chr [1:135] "Screening" "Screening" "Screening" "Visit 1" ... +#> ..$ event_label : Factor w/ 8 levels "SCR","V1","V2",..: 1 1 1 2 2 2 4 4 4 6 ... +#> ..$ form_type : chr [1:135] "study_forms" "study_forms" "study_forms" "study_forms" ... +#> ..$ item_name : Factor w/ 3 levels "Creatinine","eGFR",..: 1 2 3 1 2 3 1 2 3 1 ... +#> ..$ item_type : chr [1:135] "continuous" "continuous" "continuous" "continuous" ... +#> ..$ item_group : chr [1:135] "Renal function" "Renal function" "Renal function" "Renal function" ... +#> ..$ item_unit : chr [1:135] "µmol/L" "ml/min/1.73 m²" "µmol/L" "µmol/L" ... +#> ..$ lower_lim : num [1:135] 45 60 140 45 60 2.9 45 60 2.9 45 ... +#> ..$ upper_lim : num [1:135] 84 90 340 84 90 8.2 84 90 8.2 84 ... +#> ..$ item_value : num [1:135] 58 48 288 110 89 4.1 61 90 7.5 117 ... +#> ..$ significance : Factor w/ 5 levels "within limits",..: 2 2 1 2 2 1 2 2 1 2 ... +#> ..$ reason_notdone: chr [1:135] NA NA NA NA ... +#> ..$ region : chr [1:135] "BEL" "BEL" "BEL" "BEL" ... +#> ..$ value_scaled : num [1:135] 0.333 -0.4 0.74 1.667 0.967 ... +#> ..$ out_of_lim : Factor w/ 2 levels "0","1": 1 2 1 2 1 1 1 1 1 2 ... +#> ..$ text_label : chr [1:135] "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 58 µmol/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 48 ml/min/1.73 m²" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 288 µmol/L" "BEL_04_133\\n2023-07-05\\nVisit 1 (day 30)\\nValue: 110 µmol/L" ... +#> $ Response : tibble [6 x 22] (S3: tbl_df/tbl/data.frame) +#> ..$ site_code : chr [1:6] "BEL04" "BEL04" "BEL04" "BEL04" ... +#> ..$ subject_id : chr [1:6] "BEL_04_133" "BEL_04_133" "BEL_04_772" "BEL_04_772" ... +#> ..$ event_id : chr [1:6] "VIS5" "VIS5" "VIS5" "VIS5" ... +#> ..$ event_date : Date[1:6], format: "2023-08-30" "2023-08-30" ... +#> ..$ event_repeat : int [1:6] 5 5 5 5 5 5 +#> ..$ form_id : chr [1:6] "RS" "RS" "RS" "RS" ... +#> ..$ form_repeat : int [1:6] 1 1 1 1 1 1 +#> ..$ edit_date_time: POSIXct[1:6], format: "2023-09-13 15:23:00" "2023-09-13 15:23:00" ... +#> ..$ day : 'difftime' num [1:6] 86 86 86 86 ... +#> .. ..- attr(*, "units")= chr "days" +#> ..$ event_name : chr [1:6] "Visit 5" "Visit 5" "Visit 5" "Visit 5" ... +#> ..$ event_label : Factor w/ 8 levels "SCR","V1","V2",..: 6 6 6 6 6 6 +#> ..$ form_type : chr [1:6] "study_forms" "study_forms" "study_forms" "study_forms" ... +#> ..$ item_name : chr [1:6] "Response" "Responder" "Response" "Responder" ... +#> ..$ item_type : chr [1:6] "other" "other" "other" "other" ... +#> ..$ item_group : chr [1:6] "Response" "Response" "Response" "Response" ... +#> ..$ item_unit : chr [1:6] "(unit missing)" "(unit missing)" "(unit missing)" "(unit missing)" ... +#> ..$ lower_lim : num [1:6] NA NA NA NA NA NA +#> ..$ upper_lim : num [1:6] NA NA NA NA NA NA +#> ..$ item_value : chr [1:6] "Stable disease (SD)" "No" "Cured" "Yes" ... +#> ..$ significance : chr [1:6] NA NA NA NA ... +#> ..$ reason_notdone: chr [1:6] NA NA NA NA ... +#> ..$ region : chr [1:6] "BEL" "BEL" "BEL" "BEL" ... +#> ..- attr(*, "synch_time")= chr "2023-09-15 10:10:00 UTC" +#> $ Vital signs : continus [478 x 25] (S3: continuous/tbl_df/tbl/data.frame) +#> ..$ site_code : chr [1:478] "BEL04" "BEL04" "BEL04" "BEL04" ... +#> ..$ subject_id : chr [1:478] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... +#> ..$ event_id : chr [1:478] "SCR" "SCR" "SCR" "SCR" ... +#> ..$ event_date : Date[1:478], format: "2023-06-05" "2023-06-05" ... +#> ..$ event_repeat : int [1:478] 1 1 1 1 1 1 1 1 1 1 ... +#> ..$ form_id : chr [1:478] "VS" "VS" "VS" "VS" ... +#> ..$ form_repeat : int [1:478] 1 1 1 1 1 1 1 2 2 2 ... +#> ..$ edit_date_time: POSIXct[1:478], format: "2023-06-23 08:32:00" "2023-06-23 08:32:00" ... +#> ..$ day : 'difftime' num [1:478] 0 0 0 0 ... +#> .. ..- attr(*, "units")= chr "days" +#> ..$ event_name : chr [1:478] "Screening" "Screening" "Screening" "Screening" ... +#> ..$ event_label : Factor w/ 8 levels "SCR","V1","V2",..: 1 1 1 1 1 1 1 2 2 2 ... +#> ..$ form_type : chr [1:478] "study_forms" "study_forms" "study_forms" "study_forms" ... +#> ..$ item_name : Factor w/ 8 levels "Systolic blood pressure",..: 8 7 3 4 5 1 2 8 7 3 ... +#> ..$ item_type : chr [1:478] "continuous" "continuous" "continuous" "continuous" ... +#> ..$ item_group : chr [1:478] "Vital signs" "Vital signs" "Vital signs" "Vital signs" ... +#> ..$ item_unit : chr [1:478] "kg" "kg/m2" "beats/min" "breaths/min" ... +#> ..$ lower_lim : num [1:478] 45 18.5 60 12 35 90 55 45 18.5 60 ... +#> ..$ upper_lim : num [1:478] 200 30 100 20 38.5 160 90 200 30 100 ... +#> ..$ item_value : num [1:478] 50 24.5 60 19 36.7 ... +#> ..$ significance : Factor w/ 5 levels "within limits",..: 1 1 1 1 1 1 1 1 3 1 ... +#> ..$ reason_notdone: chr [1:478] NA NA NA NA ... +#> ..$ region : chr [1:478] "BEL" "BEL" "BEL" "BEL" ... +#> ..$ value_scaled : num [1:478] 0.0323 0.5235 0 0.875 0.4857 ... +#> ..$ out_of_lim : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 2 1 ... +#> ..$ text_label : chr [1:478] "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 50 kg" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 24.52 kg/m2" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 60 beats/min" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 19 breaths/min" ... +}\if{html}{\out{
}} +} +} +\source{ +See \code{raw-data/clinsightful_data.R} for details. +} +\usage{ +cs_app_data +} +\description{ +A list of data frames split by \code{item_group}. It is currently +not needed to provide the application data in this format. However, the +function can be useful for clinsight data customization, especially in +combination with \code{\link[=create_table]{create_table()}}. It creates table classes of the +\code{item_group} name (in lower case letters, and all punctuation replaced by an +underscore), as long as there is a method available with the corresponding +item_group name for the function \code{\link[=create_table]{create_table()}}. If all data is of type +'continuous', then laboratory values such as lab limits and units are +cleaned. +} +\keyword{datasets} diff --git a/man/cs_app_tables.Rd b/man/cs_app_tables.Rd new file mode 100644 index 00000000..8dc1f164 --- /dev/null +++ b/man/cs_app_tables.Rd @@ -0,0 +1,149 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/data.R +\docType{data} +\name{cs_app_tables} +\alias{cs_app_tables} +\title{Application Tables} +\format{ +\subsection{\code{cs_app_tables}: A list with 11 objects.}{ + +\if{html}{\out{
}}\preformatted{str(cs_app_tables) +#> List of 11 +#> $ Adverse events : tibble [90 x 16] (S3: tbl_df/tbl/data.frame) +#> ..$ subject_id : chr [1:90] "BEL_07_193" "NLD_03_207" "BEL_08_885" "NLD_03_207" ... +#> ..$ form_repeat : int [1:90] 1 1 1 1 1 2 2 2 3 6 ... +#> ..$ Name : chr [1:90] "Atelectasis" "Sepsis" "Seizure" "Sepsis" ... +#> ..$ AESI : chr [1:90] "None" "None" "None" "None" ... +#> ..$ start date : chr [1:90] "2023-09-14" "2023-08-14" "2023-08-11" "2023-08-02" ... +#> ..$ end date : chr [1:90] NA "2023-08-14" NA "2023-08-14" ... +#> ..$ CTCAE severity : chr [1:90] "Grade 3" "Grade 5" "Grade 3" "Grade 3" ... +#> ..$ Treatment related : chr [1:90] "Unlikely" "Not related" "Not related" "Not related" ... +#> ..$ Treatment action : chr [1:90] "Not Applicable (Concomitant therapy/medication; Hospitalization/Prolongation of hospitalization)" "Interrupted (Concomitant therapy/medication; Hospitalization/Prolongation of hospitalization)" "Not Applicable (Hospitalization/Prolongation of hospitalization)" "Interrupted (Concomitant therapy/medication; Hospitalization/Prolongation of hospitalization)" ... +#> ..$ Serious Adverse Event: chr [1:90] "Yes" "Yes" "Yes" "Yes" ... +#> ..$ SAE Start date : chr [1:90] "2023-09-14" "2023-08-14" "2023-08-11" "2023-08-02" ... +#> ..$ SAE End date : chr [1:90] NA "2023-08-14" NA "2023-08-14" ... +#> ..$ SAE Category : chr [1:90] "Requires inpatient hospitalization or prolongation of existing hospitalization" "Results in death; Is life-threatening; Requires inpatient hospitalization or prolongation of existing hospitalization" "Requires inpatient hospitalization or prolongation of existing hospitalization" "Results in death; Is life-threatening; Requires inpatient hospitalization or prolongation of existing hospitalization" ... +#> ..$ SAE Awareness date : chr [1:90] "2023-09-14" "2023-08-02" "2023-08-15" "2023-08-02" ... +#> ..$ SAE Date of death : chr [1:90] NA "2023-08-14" NA "2023-08-14" ... +#> ..$ SAE Death reason : chr [1:90] NA "disease progression" NA "disease progression" ... +#> $ CBC regular : tibble [65 x 9] (S3: tbl_df/tbl/data.frame) +#> ..$ subject_id : chr [1:65] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... +#> ..$ event_name : chr [1:65] "Screening" "Visit 1" "Visit 2" "Visit 3" ... +#> ..$ event_date : Date[1:65], format: "2023-06-05" "2023-07-05" ... +#> ..$ Haemoglobin: chr [1:65] "11.5 g/dL" "8 g/dL" "8.2 g/dL" "10.7 g/dL" ... +#> ..$ Haematocrit: chr [1:65] "0.25 Proportion of 1.0" "0.23 Proportion of 1.0" "0.33 Proportion of 1.0" "0.21 Proportion of 1.0" ... +#> ..$ Platelets : chr [1:65] "99.14 10^9/L" "99.14 10^9/L" "99.14 10^9/L" "99.14 10^9/L" ... +#> ..$ Neutrophils: chr [1:65] "4.16 10^9/L" "1.36 10^9/L" "1.36 10^9/L" "1.36 10^9/L" ... +#> ..$ Lymphocytes: chr [1:65] "1.7 10^9/L" "1.55 10^9/L" "1.6 10^9/L" "1.09 10^9/L" ... +#> ..$ Monocytes : chr [1:65] "0.12 10^9/L" "0.1 10^9/L" "0.83 10^9/L" "0.12 10^9/L" ... +#> $ Conc. Procedures: tibble [4 x 9] (S3: tbl_df/tbl/data.frame) +#> ..$ subject_id : chr [1:4] "BEL_07_645" "BEL_07_645" "DEU_02_866" "NLD_06_755" +#> ..$ form_repeat : int [1:4] 1 2 1 1 +#> ..$ Name : chr [1:4] "Appendectomy" "Amputation" "Thrombolysis" "Amputation" +#> ..$ Indication : chr [1:4] "Prophylaxis" "Pain" "Hypertension" "Infection" +#> ..$ Start Date : chr [1:4] "2019-NK-NK" "2019-NK-NK" "2023-08-18" "2023-08-04" +#> ..$ Ongoing : chr [1:4] "No" "No" "No" "Yes" +#> ..$ End Date : chr [1:4] "2019-NK-NK" "2019-NK-NK" "2023-08-18" NA +#> ..$ Related Medical History: chr [1:4] "Sickle cell anemia" "Sickle cell anemia" "Epilepsy" "Familial Mediterranean fever" +#> ..$ Related AE : chr [1:4] NA NA NA "Joint pain" +#> $ Electrolytes : tibble [46 x 9] (S3: tbl_df/tbl/data.frame) +#> ..$ subject_id : chr [1:46] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... +#> ..$ event_name : chr [1:46] "Screening" "Visit 1" "Visit 3" "Visit 5" ... +#> ..$ event_date : Date[1:46], format: "2023-06-05" "2023-07-05" ... +#> ..$ Sodium : chr [1:46] "138 mmol/L" "138 mmol/L" "140 mmol/L" "138 mmol/L" ... +#> ..$ Potassium : chr [1:46] "4.5 mmol/L" "4.14 mmol/L" "4.65 mmol/L" "4.74 mmol/L" ... +#> ..$ Chloride : chr [1:46] "105 mmol/L" "103 mmol/L" "105 mmol/L" "104 mmol/L" ... +#> ..$ Bicarbonate: chr [1:46] "20.5 mmol/L" "23 mmol/L" "23.7 mmol/L" "21.4 mmol/L" ... +#> ..$ Calcium : chr [1:46] "2.26 mmol/L" "2.53 mmol/L" "2.43 mmol/L" "2.39 mmol/L" ... +#> ..$ Magnesium : chr [1:46] "0.87 mmol/L" "0.83 mmol/L" "0.75 mmol/L" "0.88 mmol/L" ... +#> $ General : tibble [25 x 23] (S3: tbl_df/tbl/data.frame) +#> ..$ subject_id : chr [1:25] "BEL_04_133" "BEL_04_772" "BEL_07_193" "BEL_07_431" ... +#> ..$ Age : chr [1:25] "88" "78" "26" "42" ... +#> ..$ Sex : chr [1:25] "Male" "Male" "Female" "Male" ... +#> ..$ ECOG : chr [1:25] "1" "0" "1" "1" ... +#> ..$ Eligible : chr [1:25] "Yes" "Yes" "Yes" NA ... +#> ..$ Eligible_Date : chr [1:25] "2023-07-06" "2023-08-17" "2023-08-23" NA ... +#> ..$ WHO.classification : chr [1:25] "Syndrome K" "Syndrome O" "Syndrome D" NA ... +#> ..$ WHO.subclassification : chr [1:25] NA NA NA NA ... +#> ..$ Race : chr [1:25] "White" "White" "Not reported" "Not reported" ... +#> ..$ ChildbearingPotential : chr [1:25] "No" "No" NA NA ... +#> ..$ MenopauseReason : chr [1:25] "Postmenopausal" "Postmenopausal" NA NA ... +#> ..$ DiscontinuationDate : chr [1:25] NA NA NA NA ... +#> ..$ DiscontinuationReason : chr [1:25] NA NA NA NA ... +#> ..$ DisconDeathDate : chr [1:25] NA NA NA NA ... +#> ..$ DrugAdminDate : chr [1:25] NA NA NA NA ... +#> ..$ DrugAdminDose : chr [1:25] NA NA NA NA ... +#> ..$ DoseModificationDate : chr [1:25] NA NA NA NA ... +#> ..$ DoseModificationReason : chr [1:25] NA NA NA NA ... +#> ..$ DoseModificationNewDose: chr [1:25] NA NA NA NA ... +#> ..$ DrugDiscontDate : chr [1:25] NA NA NA NA ... +#> ..$ DrugDiscontReason : chr [1:25] NA NA NA NA ... +#> ..$ subject_status : chr [1:25] "Enrolled" "Enrolled" "Enrolled" "Unknown" ... +#> ..$ status_label : chr [1:25] "BEL_04_133
Sex: Male
Age: 88yrs.
Status: Enrolled
ECOG: 1
"| __truncated__ "BEL_04_772
Sex: Male
Age: 78yrs.
Status: Enrolled
ECOG: 0
"| __truncated__ "BEL_07_193
Sex: Female
Age: 26yrs.
Status: Enrolled
ECOG: 1
<"| __truncated__ "BEL_07_431
Sex: Male
Age: 42yrs.
Status: Unknown
ECOG: 1
Dx: NA" ... +#> $ Liver function : tibble [45 x 7] (S3: tbl_df/tbl/data.frame) +#> ..$ subject_id: chr [1:45] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... +#> ..$ event_name: chr [1:45] "Screening" "Visit 1" "Visit 3" "Visit 5" ... +#> ..$ event_date: Date[1:45], format: "2023-06-05" "2023-07-05" ... +#> ..$ Bilirubin : chr [1:45] "6 µmol/L" "11 µmol/L" "8 µmol/L" "7 µmol/L" ... +#> ..$ AST : chr [1:45] "21 U/L" "32 U/L" "43 U/L" "42 U/L" ... +#> ..$ ALT : chr [1:45] "35 U/L" "45 U/L" "19 U/L" "27 U/L" ... +#> ..$ gGT : chr [1:45] "24 U/L" "25 U/L" "26 U/L" "21 U/L" ... +#> $ Medical History : tibble [152 x 8] (S3: tbl_df/tbl/data.frame) +#> ..$ subject_id : chr [1:152] "BEL_04_133" "BEL_04_772" "BEL_04_772" "BEL_04_772" ... +#> ..$ form_repeat: int [1:152] 1 1 2 3 4 5 6 7 8 9 ... +#> ..$ Name : chr [1:152] "Epilepsy" "Hypertension" "COPD" "Osteoporosis" ... +#> ..$ Start Date : chr [1:152] NA "2020-NK-NK" "1995-NK-NK" "2005-NK-NK" ... +#> ..$ Ongoing : chr [1:152] "Yes" "Yes" "Yes" "Yes" ... +#> ..$ End Date : chr [1:152] NA NA NA NA ... +#> ..$ Treatment : chr [1:152] "Medication" "Medication" "Medication" "Medication" ... +#> ..$ Comment : chr [1:152] NA NA NA NA ... +#> $ Medication : tibble [283 x 10] (S3: tbl_df/tbl/data.frame) +#> ..$ subject_id : chr [1:283] "DEU_01_541" "DEU_01_541" "BEL_07_645" "BEL_07_645" ... +#> ..$ form_repeat : int [1:283] 1 2 6 7 9 10 3 10 15 33 ... +#> ..$ Name : chr [1:283] "Lisinopril (Sulfaipoetin)" "Oxycodone (Estrizotan)" "Lisinopril (Salsteridone)" "Lisinopril (Nifurasiban)" ... +#> ..$ Indication : chr [1:283] "Insomnia" "Infection" "Nausea" "Insomnia" ... +#> ..$ Dose : chr [1:283] "300 Milligram (mg) Per day (QD); Oral (p.o.)" "500 Milligram (mg) Per day (QD); Oral (p.o.)" "5 Milligram (mg) Per month (QM); Intravenous (i.v.)" "20 Milligram (mg) Per month (QM); Intravenous (i.v.)" ... +#> ..$ Start Date : chr [1:283] "2023-NK-NK" "2023-NK-NK" "2023-09-13" "2023-09-13" ... +#> ..$ Ongoing : chr [1:283] "Yes" "Yes" "Yes" "Yes" ... +#> ..$ End Date : chr [1:283] NA NA NA NA ... +#> ..$ Related Medical History: chr [1:283] NA NA NA NA ... +#> ..$ Related AE : chr [1:283] NA NA NA NA ... +#> $ Renal function : tibble [46 x 6] (S3: tbl_df/tbl/data.frame) +#> ..$ subject_id: chr [1:46] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... +#> ..$ event_name: chr [1:46] "Screening" "Visit 1" "Visit 3" "Visit 5" ... +#> ..$ event_date: Date[1:46], format: "2023-06-05" "2023-07-05" ... +#> ..$ Creatinine: chr [1:46] "58 µmol/L" "110 µmol/L" "61 µmol/L" "117 µmol/L" ... +#> ..$ eGFR : chr [1:46] "48 ml/min/1.73 m²" "89 ml/min/1.73 m²" "90 ml/min/1.73 m²" "47 ml/min/1.73 m²" ... +#> ..$ Urate : chr [1:46] "288 µmol/L" "4.1 mmol/L" "7.5 mmol/L" "294 µmol/L" ... +#> $ Response : tibble [3 x 6] (S3: tbl_df/tbl/data.frame) +#> ..$ subject_id : chr [1:3] "BEL_04_133" "BEL_04_772" "NLD_06_72" +#> ..$ event_name : chr [1:3] "Visit 5" "Visit 5" "Visit 5" +#> ..$ event_repeat: int [1:3] 5 5 5 +#> ..$ event_date : Date[1:3], format: "2023-08-30" "2023-08-30" ... +#> ..$ Response : chr [1:3] "Stable disease (SD)" "Cured" "Stable disease (SD)" +#> ..$ Responder : chr [1:3] "No" "Yes" "No" +#> $ Vital signs : tibble [68 x 11] (S3: tbl_df/tbl/data.frame) +#> ..$ subject_id : chr [1:68] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... +#> ..$ event_name : chr [1:68] "Screening" "Visit 1" "Visit 2" "Visit 3" ... +#> ..$ event_date : Date[1:68], format: "2023-06-05" "2023-07-05" ... +#> ..$ Systolic blood pressure : chr [1:68] "108 mmHg" "123 mmHg" "122 mmHg" "137 mmHg" ... +#> ..$ Diastolic blood pressure : chr [1:68] "62 mmHg" "69 mmHg" "68 mmHg" "72 mmHg" ... +#> ..$ Pulse : chr [1:68] "60 beats/min" "67 beats/min" "69 beats/min" "78 beats/min" ... +#> ..$ Resp : chr [1:68] "19 breaths/min" "19 breaths/min" "18 breaths/min" "16 breaths/min" ... +#> ..$ Temperature : chr [1:68] "36.7 °C" "36.5 °C" "36.2 °C" "36.7 °C" ... +#> ..$ Weight change since screening: chr [1:68] "0 \%" "24 \%" NA "2 \%" ... +#> ..$ BMI : chr [1:68] "24.52 kg/m2" "17.1 kg/m2" NA "24.52 kg/m2" ... +#> ..$ Weight : chr [1:68] "50 kg" "62 kg" NA "51 kg" ... +}\if{html}{\out{
}} +} +} +\source{ +See \code{raw-data/clinsightful_data.R} for details. +} +\usage{ +cs_app_tables +} +\description{ +A list of data frames containing all application tables. +} +\keyword{datasets} diff --git a/man/cs_app_vars.Rd b/man/cs_app_vars.Rd new file mode 100644 index 00000000..a6de469b --- /dev/null +++ b/man/cs_app_vars.Rd @@ -0,0 +1,62 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/data.R +\docType{data} +\name{cs_app_vars} +\alias{cs_app_vars} +\title{Application Variables} +\format{ +\subsection{\code{cs_app_vars}: A list with 6 objects.}{ + +\if{html}{\out{
}}\preformatted{str(cs_app_vars) +#> List of 6 +#> $ items :List of 11 +#> ..$ Adverse events : Named chr [1:17] "ae_number" "ae_name" "aesi" "ae_start_date" ... +#> .. ..- attr(*, "names")= chr [1:17] "AE Number" "AE Name" "AESI" "AE start date" ... +#> ..$ CBC regular : Named chr [1:6] "haemoglobin" "haematocrit" "platelets" "neutrophils" ... +#> .. ..- attr(*, "names")= chr [1:6] "Haemoglobin" "Haematocrit" "Platelets" "Neutrophils" ... +#> ..$ Conc. Procedures: Named chr [1:8] "cp_number" "cp_name" "cp_indication" "cp_start_date" ... +#> .. ..- attr(*, "names")= chr [1:8] "CP Number" "CP Name" "CP Indication" "CP Start Date" ... +#> ..$ Electrolytes : Named chr [1:6] "sodium" "potassium" "chloride" "bicarbonate" ... +#> .. ..- attr(*, "names")= chr [1:6] "Sodium" "Potassium" "Chloride" "Bicarbonate" ... +#> ..$ General : Named chr [1:20] "age" "sex" "ecog" "eligible" ... +#> .. ..- attr(*, "names")= chr [1:20] "Age" "Sex" "ECOG" "Eligible" ... +#> ..$ Liver function : Named chr [1:4] "bilirubin" "ast" "alt" "ggt" +#> .. ..- attr(*, "names")= chr [1:4] "Bilirubin" "AST" "ALT" "gGT" +#> ..$ Medical History : Named chr [1:7] "mh_number" "mh_name" "mh_start_date" "mh_ongoing" ... +#> .. ..- attr(*, "names")= chr [1:7] "MH Number" "MH Name" "MH Start Date" "MH Ongoing" ... +#> ..$ Medication : Named chr [1:12] "cm_number" "cm_name" "cm_indication" "cm_dose" ... +#> .. ..- attr(*, "names")= chr [1:12] "CM Number" "CM Name" "CM Indication" "CM Dose" ... +#> ..$ Renal function : Named chr [1:3] "creatinine" "egfr" "urate" +#> .. ..- attr(*, "names")= chr [1:3] "Creatinine" "eGFR" "Urate" +#> ..$ Response : Named chr [1:2] "response" "responder" +#> .. ..- attr(*, "names")= chr [1:2] "Response" "Responder" +#> ..$ Vital signs : Named chr [1:8] "systolic_blood_pressure" "diastolic_blood_pressure" "pulse" "resp" ... +#> .. ..- attr(*, "names")= chr [1:8] "Systolic blood pressure" "Diastolic blood pressure" "Pulse" "Resp" ... +#> $ all_forms :'data.frame': 10 obs. of 2 variables: +#> ..$ main_tab: chr [1:10] "Common events" "Common events" "Common events" "Common events" ... +#> ..$ form : chr [1:10] "Adverse events" "Medication" "Conc. Procedures" "Medical History" ... +#> $ subject_id : chr [1:25] "BEL_08_45" "BEL_04_133" "BEL_04_772" "BEL_07_193" ... +#> $ Sites : advrs_vn [9 x 2] (S3: adverse_events/common_forms/tbl_df/tbl/data.frame) +#> ..$ site_code: chr [1:9] "BEL04" "BEL07" "BEL08" "BEL09" ... +#> ..$ region : chr [1:9] "BEL" "BEL" "BEL" "BEL" ... +#> ..- attr(*, "synch_time")= chr "2023-09-15 10:10:00 UTC" +#> $ table_names : Named chr [1:16] "edit_date_time" "event_date" "event_label" "event_name" ... +#> ..- attr(*, "names")= chr [1:16] "Edit date" "Date" "Event" "Event" ... +#> $ form_level_data:'data.frame': 11 obs. of 4 variables: +#> ..$ item_group : chr [1:11] "Adverse events" "Medication" "Conc. Procedures" "Medical History" ... +#> ..$ item_scale : logi [1:11] NA NA NA NA FALSE TRUE ... +#> ..$ use_unscaled_limits: logi [1:11] NA NA NA NA TRUE FALSE ... +#> ..$ review_required : logi [1:11] TRUE TRUE TRUE TRUE TRUE TRUE ... +}\if{html}{\out{
}} +} +} +\source{ +See \code{raw-data/clinsightful_data.R} for details. +} +\usage{ +cs_app_vars +} +\description{ +Named list version of \code{metadata} object. +} +\keyword{datasets} diff --git a/man/cs_available_data.Rd b/man/cs_available_data.Rd new file mode 100644 index 00000000..aba55e37 --- /dev/null +++ b/man/cs_available_data.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/data.R +\docType{data} +\name{cs_available_data} +\alias{cs_available_data} +\title{Application 'Available Data'} +\format{ +a data.frame with 1974 rows and +6 variables. + +\if{html}{\out{
}}\preformatted{str(cs_available_data) +#> tibble [1,974 x 6] (S3: tbl_df/tbl/data.frame) +#> $ subject_id : chr [1:1974] "BEL_04_772" "BEL_04_772" "BEL_04_772" "BEL_04_772" ... +#> $ item_name : chr [1:1974] "Hypotension" "Atrial Fibrillation (N: 2)" "Tachycardia" "Urinary Tract Infection" ... +#> $ form_repeat: int [1:1974] 1 2 3 4 5 1 1 1 3 2 ... +#> $ item_group : chr [1:1974] "Adverse events" "Adverse events" "Adverse events" "Adverse events" ... +#> $ event_name : chr [1:1974] "Any visit" "Any visit" "Any visit" "Any visit" ... +#> $ event_label: chr [1:1974] "Any visit" "Any visit" "Any visit" "Any visit" ... +}\if{html}{\out{
}} +} +\source{ +See \code{raw-data/clinsightful_data.R} for details. +} +\usage{ +cs_available_data +} +\description{ +Data frame containing info about available data per individual, +such as visits, adverse events, etc. Will be used in module +\code{\link[=mod_queries_server]{mod_queries_server()}}, to select available items to create a query for per +individual and per form. Required columns are the ones distinctively +identifying an item. For now that are site_code, event_name, subject_id, +event_label, item_group, item_name. +} +\keyword{datasets} diff --git a/man/metadata.Rd b/man/metadata.Rd index 576dab6c..3f0c031a 100644 --- a/man/metadata.Rd +++ b/man/metadata.Rd @@ -9,85 +9,145 @@ \if{html}{\out{
}}\preformatted{str(metadata) #> List of 9 -#> $ column_names : tibble [15 x 3] (S3: tbl_df/tbl/data.frame) -#> ..$ name_raw: chr [1:15] "SiteCode" "SubjectId" "subjid" "data_page_id" ... -#> ..$ name_new: chr [1:15] "site_code" "subject_id" "subj_id" "data_page_id" ... -#> ..$ col_type: chr [1:15] "c" "c" "i" "i" ... -#> $ events : tibble [24 x 10] (S3: tbl_df/tbl/data.frame) -#> ..$ event_id : chr [1:24] "SCR" "C1D1" "C1D8" "C1D15" ... -#> ..$ event_id_pattern : chr [1:24] "^SCR$" "^C1D1$" "^C1D8$" "^C1D15$" ... -#> ..$ is_regular_visit : logi [1:24] TRUE TRUE TRUE TRUE TRUE TRUE ... -#> ..$ event_label_custom : chr [1:24] NA NA NA NA ... -#> ..$ event_name_custom : chr [1:24] "Screening" "Cycle 1 Day 1" "Cycle 1 Day 8" "Cycle 1 Day 15" ... -#> ..$ is_baseline_event : logi [1:24] TRUE FALSE FALSE FALSE FALSE FALSE ... -#> ..$ generate_labels : logi [1:24] FALSE FALSE FALSE FALSE FALSE FALSE ... -#> ..$ meta_event_order : int [1:24] 1 2 3 4 5 6 7 8 9 10 ... -#> ..$ add_visit_number : logi [1:24] FALSE FALSE FALSE FALSE FALSE FALSE ... -#> ..$ add_event_repeat_number: logi [1:24] FALSE FALSE FALSE FALSE FALSE FALSE ... -#> $ common_forms :'data.frame': 307 obs. of 6 variables: -#> ..$ item_name : chr [1:307] "Day in Study" "Event Date" "Visit" "Lesion ID" ... -#> ..$ item_type : chr [1:307] "other" "other" "other" "other" ... -#> ..$ item_form : chr [1:307] "Efficacy" "Efficacy" "Efficacy" "Efficacy" ... -#> ..$ form_level_id_var: chr [1:307] NA NA NA NA ... -#> ..$ item_group : chr [1:307] "Efficacy" "Efficacy" "Efficacy" "Efficacy" ... -#> ..$ merge_with : chr [1:307] NA NA NA NA ... -#> $ study_forms :'data.frame': 55 obs. of 9 variables: -#> ..$ item_name : chr [1:55] "Temperature" "RespiratoryRate" "PulseRate" "SystolicBloodPressure" ... -#> ..$ item_type : chr [1:55] "continuous" "continuous" "continuous" "continuous" ... -#> ..$ item_form : chr [1:55] "Vital Signs" "Vital Signs" "Vital Signs" "Vital Signs" ... -#> ..$ form_level_id_var: chr [1:55] NA NA NA NA ... -#> ..$ item_group : chr [1:55] "Vital Signs" "Vital Signs" "Vital Signs" "Vital Signs" ... -#> ..$ merge_with : chr [1:55] NA NA NA NA ... -#> ..$ unit : chr [1:55] NA NA NA NA ... -#> ..$ lower_limit : chr [1:55] NA NA NA NA ... -#> ..$ upper_limit : chr [1:55] NA NA NA NA ... -#> $ general :'data.frame': 129 obs. of 6 variables: -#> ..$ item_name : chr [1:129] "Sex" "Age" "Childbearing Potential" "Reason" ... -#> ..$ item_type : chr [1:129] "other" "other" "other" "other" ... -#> ..$ item_form : chr [1:129] "General" "General" "General" "General" ... -#> ..$ form_level_id_var: chr [1:129] NA NA NA NA ... -#> ..$ item_group : chr [1:129] "General" "General" "General" "General" ... -#> ..$ merge_with : chr [1:129] NA NA NA NA ... -#> $ form_level_data:'data.frame': 19 obs. of 5 variables: -#> ..$ item_group : chr [1:19] "Efficacy" "Administration" "Adverse events" "Disease History" ... -#> ..$ item_type : chr [1:19] "other" "other" "other" "other" ... -#> ..$ item_scale : logi [1:19] FALSE FALSE FALSE FALSE FALSE FALSE ... -#> ..$ use_unscaled_limits: logi [1:19] TRUE TRUE TRUE TRUE TRUE TRUE ... -#> ..$ review_required : logi [1:19] TRUE TRUE TRUE TRUE TRUE TRUE ... -#> $ table_names : tibble [15 x 2] (S3: tbl_df/tbl/data.frame) -#> ..$ table_name: chr [1:15] "Subject" "Visit" "Status" "Form Repeat" ... -#> ..$ raw_name : chr [1:15] "subject_id" "event_name" "status" "form_repeat" ... -#> $ settings :List of 6 -#> ..$ pre_merge_fns : chr "arcus_pre_merge" -#> ..$ pre_pivot_fns : chr "arcus_pre_pivot" -#> ..$ post_pivot_fns : chr "arcus_post_pivot" -#> ..$ post_merge_fns : chr "arcus_post_merge" -#> ..$ study_name : chr "PRISM-1" +#> $ column_names : tibble [10 x 2] (S3: tbl_df/tbl/data.frame) +#> ..$ name_raw: chr [1:10] "SiteCode" "SubjectId" "EventId" "EventDate" ... +#> ..$ name_new: chr [1:10] "site_code" "subject_id" "event_id" "event_date" ... +#> $ events : tibble [10 x 10] (S3: tbl_df/tbl/data.frame) +#> ..$ event_id : chr [1:10] "SCR" "VIS1" "VIS2" "VIS3" ... +#> ..$ event_id_pattern : chr [1:10] "^SCR$" "^VIS1$" "^VIS2$" "^VIS3$" ... +#> ..$ is_regular_visit : logi [1:10] TRUE TRUE TRUE TRUE TRUE TRUE ... +#> ..$ event_label_custom : chr [1:10] NA "V1" "V2" "V3" ... +#> ..$ event_name_custom : chr [1:10] "Screening" "Visit 1" "Visit 2" "Visit 3" ... +#> ..$ is_baseline_event : logi [1:10] TRUE FALSE FALSE FALSE FALSE FALSE ... +#> ..$ generate_labels : logi [1:10] FALSE FALSE FALSE FALSE FALSE FALSE ... +#> ..$ meta_event_order : int [1:10] 1 2 3 4 5 6 7 8 9 10 +#> ..$ add_visit_number : logi [1:10] FALSE FALSE FALSE FALSE FALSE FALSE ... +#> ..$ add_event_repeat_number: logi [1:10] FALSE FALSE FALSE FALSE FALSE FALSE ... +#> $ common_forms :'data.frame': 44 obs. of 4 variables: +#> ..$ item_name : chr [1:44] "AE Number" "AE Name" "AESI" "AE start date" ... +#> ..$ item_type : chr [1:44] "other" "other" "other" "other" ... +#> ..$ item_group: chr [1:44] "Adverse events" "Adverse events" "Adverse events" "Adverse events" ... +#> ..$ merge_with: chr [1:44] NA NA NA NA ... +#> $ study_forms :'data.frame': 29 obs. of 6 variables: +#> ..$ item_name : chr [1:29] "Systolic blood pressure" "Diastolic blood pressure" "Pulse" "Resp" ... +#> ..$ item_type : chr [1:29] "continuous" "continuous" "continuous" "continuous" ... +#> ..$ item_group : chr [1:29] "Vital signs" "Vital signs" "Vital signs" "Vital signs" ... +#> ..$ unit : chr [1:29] "mmHg" "mmHg" "beats/min" "breaths/min" ... +#> ..$ lower_limit: chr [1:29] "90" "55" "60" "12" ... +#> ..$ upper_limit: chr [1:29] "160" "90" "100" "20" ... +#> $ general :'data.frame': 20 obs. of 3 variables: +#> ..$ item_name : chr [1:20] "Age" "Sex" "ECOG" "Eligible" ... +#> ..$ item_type : chr [1:20] "other" "other" "other" "other" ... +#> ..$ item_group: chr [1:20] "General" "General" "General" "General" ... +#> $ form_level_data:'data.frame': 11 obs. of 4 variables: +#> ..$ item_group : chr [1:11] "Adverse events" "Medication" "Conc. Procedures" "Medical History" ... +#> ..$ item_scale : logi [1:11] NA NA NA NA FALSE TRUE ... +#> ..$ use_unscaled_limits: logi [1:11] NA NA NA NA TRUE FALSE ... +#> ..$ review_required : logi [1:11] TRUE TRUE TRUE TRUE TRUE TRUE ... +#> $ table_names : tibble [16 x 2] (S3: tbl_df/tbl/data.frame) +#> ..$ table_name: chr [1:16] "Edit date" "Date" "Event" "Event" ... +#> ..$ raw_name : chr [1:16] "edit_date_time" "event_date" "event_label" "event_name" ... +#> $ settings :List of 4 +#> ..$ pre_pivot_fns : chr "apply_study_specific_suffix_fixes" +#> ..$ post_pivot_fns : chr "apply_edc_specific_changes" +#> ..$ post_merge_fns : chr "apply_study_specific_fixes" #> ..$ treatment_label: chr "💊 Tₓ" -#> $ items_expanded : tibble [958 x 11] (S3: tbl_df/tbl/data.frame) -#> ..$ form_type : chr [1:958] "common_forms" "common_forms" "common_forms" "common_forms" ... -#> ..$ var : chr [1:958] "Day in Study" "Event Date" "Timepoint" "Lesion Number" ... -#> ..$ suffix : chr [1:958] NA NA NA NA ... -#> ..$ item_name : chr [1:958] "Day in Study" "Event Date" "Visit" "Lesion ID" ... -#> ..$ item_type : chr [1:958] "other" "other" "other" "other" ... -#> ..$ item_form : chr [1:958] "Efficacy" "Efficacy" "Efficacy" "Efficacy" ... -#> ..$ form_level_id_var: chr [1:958] NA NA NA NA ... -#> ..$ item_group : chr [1:958] "Efficacy" "Efficacy" "Efficacy" "Efficacy" ... -#> ..$ unit : chr [1:958] NA NA NA NA ... -#> ..$ lower_limit : chr [1:958] NA NA NA NA ... -#> ..$ upper_limit : chr [1:958] NA NA NA NA ... +#> $ items_expanded : tibble [220 x 9] (S3: tbl_df/tbl/data.frame) +#> ..$ form_type : chr [1:220] "common_forms" "common_forms" "common_forms" "common_forms" ... +#> ..$ var : chr [1:220] "AE_AESPID" "AE_AETERM" "AE_AESI" "AE_AESTDAT" ... +#> ..$ suffix : chr [1:220] NA NA NA NA ... +#> ..$ item_name : chr [1:220] "AE Number" "AE Name" "AESI" "AE start date" ... +#> ..$ item_type : chr [1:220] "other" "other" "other" "other" ... +#> ..$ item_group : chr [1:220] "Adverse events" "Adverse events" "Adverse events" "Adverse events" ... +#> ..$ unit : chr [1:220] NA NA NA NA ... +#> ..$ lower_limit: chr [1:220] NA NA NA NA ... +#> ..$ upper_limit: chr [1:220] NA NA NA NA ... +}\if{html}{\out{
}} +} + +\subsection{\code{metadata}: A list with 9 objects.}{ + +\if{html}{\out{
}}\preformatted{str(metadata) +#> List of 9 +#> $ column_names : tibble [10 x 2] (S3: tbl_df/tbl/data.frame) +#> ..$ name_raw: chr [1:10] "SiteCode" "SubjectId" "EventId" "EventDate" ... +#> ..$ name_new: chr [1:10] "site_code" "subject_id" "event_id" "event_date" ... +#> $ events : tibble [10 x 10] (S3: tbl_df/tbl/data.frame) +#> ..$ event_id : chr [1:10] "SCR" "VIS1" "VIS2" "VIS3" ... +#> ..$ event_id_pattern : chr [1:10] "^SCR$" "^VIS1$" "^VIS2$" "^VIS3$" ... +#> ..$ is_regular_visit : logi [1:10] TRUE TRUE TRUE TRUE TRUE TRUE ... +#> ..$ event_label_custom : chr [1:10] NA "V1" "V2" "V3" ... +#> ..$ event_name_custom : chr [1:10] "Screening" "Visit 1" "Visit 2" "Visit 3" ... +#> ..$ is_baseline_event : logi [1:10] TRUE FALSE FALSE FALSE FALSE FALSE ... +#> ..$ generate_labels : logi [1:10] FALSE FALSE FALSE FALSE FALSE FALSE ... +#> ..$ meta_event_order : int [1:10] 1 2 3 4 5 6 7 8 9 10 +#> ..$ add_visit_number : logi [1:10] FALSE FALSE FALSE FALSE FALSE FALSE ... +#> ..$ add_event_repeat_number: logi [1:10] FALSE FALSE FALSE FALSE FALSE FALSE ... +#> $ common_forms :'data.frame': 44 obs. of 4 variables: +#> ..$ item_name : chr [1:44] "AE Number" "AE Name" "AESI" "AE start date" ... +#> ..$ item_type : chr [1:44] "other" "other" "other" "other" ... +#> ..$ item_group: chr [1:44] "Adverse events" "Adverse events" "Adverse events" "Adverse events" ... +#> ..$ merge_with: chr [1:44] NA NA NA NA ... +#> $ study_forms :'data.frame': 29 obs. of 6 variables: +#> ..$ item_name : chr [1:29] "Systolic blood pressure" "Diastolic blood pressure" "Pulse" "Resp" ... +#> ..$ item_type : chr [1:29] "continuous" "continuous" "continuous" "continuous" ... +#> ..$ item_group : chr [1:29] "Vital signs" "Vital signs" "Vital signs" "Vital signs" ... +#> ..$ unit : chr [1:29] "mmHg" "mmHg" "beats/min" "breaths/min" ... +#> ..$ lower_limit: chr [1:29] "90" "55" "60" "12" ... +#> ..$ upper_limit: chr [1:29] "160" "90" "100" "20" ... +#> $ general :'data.frame': 20 obs. of 3 variables: +#> ..$ item_name : chr [1:20] "Age" "Sex" "ECOG" "Eligible" ... +#> ..$ item_type : chr [1:20] "other" "other" "other" "other" ... +#> ..$ item_group: chr [1:20] "General" "General" "General" "General" ... +#> $ form_level_data:'data.frame': 11 obs. of 4 variables: +#> ..$ item_group : chr [1:11] "Adverse events" "Medication" "Conc. Procedures" "Medical History" ... +#> ..$ item_scale : logi [1:11] NA NA NA NA FALSE TRUE ... +#> ..$ use_unscaled_limits: logi [1:11] NA NA NA NA TRUE FALSE ... +#> ..$ review_required : logi [1:11] TRUE TRUE TRUE TRUE TRUE TRUE ... +#> $ table_names : tibble [16 x 2] (S3: tbl_df/tbl/data.frame) +#> ..$ table_name: chr [1:16] "Edit date" "Date" "Event" "Event" ... +#> ..$ raw_name : chr [1:16] "edit_date_time" "event_date" "event_label" "event_name" ... +#> $ settings :List of 4 +#> ..$ pre_pivot_fns : chr "apply_study_specific_suffix_fixes" +#> ..$ post_pivot_fns : chr "apply_edc_specific_changes" +#> ..$ post_merge_fns : chr "apply_study_specific_fixes" +#> ..$ treatment_label: chr "💊 Tₓ" +#> $ items_expanded : tibble [220 x 9] (S3: tbl_df/tbl/data.frame) +#> ..$ form_type : chr [1:220] "common_forms" "common_forms" "common_forms" "common_forms" ... +#> ..$ var : chr [1:220] "AE_AESPID" "AE_AETERM" "AE_AESI" "AE_AESTDAT" ... +#> ..$ suffix : chr [1:220] NA NA NA NA ... +#> ..$ item_name : chr [1:220] "AE Number" "AE Name" "AESI" "AE start date" ... +#> ..$ item_type : chr [1:220] "other" "other" "other" "other" ... +#> ..$ item_group : chr [1:220] "Adverse events" "Adverse events" "Adverse events" "Adverse events" ... +#> ..$ unit : chr [1:220] NA NA NA NA ... +#> ..$ lower_limit: chr [1:220] NA NA NA NA ... +#> ..$ upper_limit: chr [1:220] NA NA NA NA ... }\if{html}{\out{
}} } } \source{ +Can be created with an Excel file. The Excel file format is chosen so +that the metadata can be changed easily per study. See +\code{raw-data/metadata.R} for details. + Can be created with an Excel file. The Excel file format is chosen so that the metadata can be changed easily per study. See \code{raw-data/metadata.R} for details. } \usage{ +metadata + metadata } \description{ +A list of data frames and settings containing metadata that will be used for +the application. The metadata will be merged with with raw data. It controls +the variables that will be used in the application, and in which tab the +variables will be shown. The goal is that most, if not all, study-specific +data will be captured in the metadata, leaving the scripts to run the +application largely unaltered between studies.See \code{vignette("Metadata")} for +in-depth information. + A list of data frames and settings containing metadata that will be used for the application. The metadata will be merged with with raw data. It controls the variables that will be used in the application, and in which tab the From 95f9f11163a35c811b465b5bb7b04949ecf6c46d Mon Sep 17 00:00:00 2001 From: aclark02-arcus Date: Wed, 10 Sep 2025 16:51:32 +0000 Subject: [PATCH 06/14] move a comment --- R/app_server.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/app_server.R b/R/app_server.R index 87cc95e3..bfcdc655 100644 --- a/R/app_server.R +++ b/R/app_server.R @@ -20,12 +20,12 @@ app_server <- function( ){ # Read in pre-processed R objects + # merged_data <- golem::get_golem_options("data") meta <- golem::get_golem_options("meta") app_data <- golem::get_golem_options("app_data") app_vars <- golem::get_golem_options("app_vars") app_tables <- golem::get_golem_options("app_tables") available_data <- golem::get_golem_options("available_data") - # merged_data <- golem::get_golem_options("data") user_db <- golem::get_golem_options("user_db") credentials_db <- golem::get_golem_options("credentials_db") From bf173ddceaec75a611080ad917d3d9ed0137ddda Mon Sep 17 00:00:00 2001 From: aclark02-arcus Date: Wed, 10 Sep 2025 20:36:19 +0000 Subject: [PATCH 07/14] remove unneccessary comments --- R/fct_test_clinsight.R | 8 -------- 1 file changed, 8 deletions(-) diff --git a/R/fct_test_clinsight.R b/R/fct_test_clinsight.R index fb3766a0..dd539980 100644 --- a/R/fct_test_clinsight.R +++ b/R/fct_test_clinsight.R @@ -30,18 +30,10 @@ test_clinsight <- function( stopifnot(is.character(clinsight_config)) study_data_path <- get_golem_config("study_data", config = clinsight_config) meta_data_path <- get_golem_config("meta_data", config = clinsight_config) - # app_data_path <- get_golem_config("app_data", config = clinsight_config) - # app_vars_path <- get_golem_config("app_vars", config = clinsight_config) - # app_tables_path <- get_golem_config("app_tables", config = clinsight_config) - # available_data_path <- get_golem_config("available_data", config = clinsight_config) if ( clinsight_config %in% c("default", "dev") | !is.character(study_data_path) | !is.character(meta_data_path) #| - # !is.character(app_data_path) | - # !is.character(app_vars_path) | - # !is.character(app_tables_path) | - # !is.character(available_data_path) ){ stop("The 'default' or 'dev' config cannot be used with custom data, ", "and meta_data, app_data, app_vars, app_tables, & available_data ", From a8fbcb132e6184639cc668fa7a2fabf4a97386c0 Mon Sep 17 00:00:00 2001 From: aclark02-arcus Date: Tue, 30 Dec 2025 09:09:19 -0800 Subject: [PATCH 08/14] extract creation of timeline_data outside of the app & remove app_tables from existence --- R/app_server.R | 17 +- R/data.R | 11 +- R/fct_test_clinsight.R | 24 +- R/mod_plot_efficacy.R | 294 +++++++++++++++++++++++++ R/run_app.R | 39 +++- data-raw/clinsightful_data.R | 24 +- data/cs_app_data.rda | Bin 43568 -> 45811 bytes data/cs_available_data.rda | Bin 4537 -> 5577 bytes data/cs_timeline_data.rda | Bin 0 -> 3026 bytes dev/app.R | 27 ++- inst/golem-config.yml | 6 +- man/cs_app_data.Rd | 10 +- man/cs_app_tables.Rd | 149 ------------- man/cs_available_data.Rd | 20 +- man/cs_timeline_data.Rd | 38 ++++ tests/testthat/test-mod_main_sidebar.R | 3 +- 16 files changed, 447 insertions(+), 215 deletions(-) create mode 100644 R/mod_plot_efficacy.R create mode 100644 data/cs_timeline_data.rda delete mode 100644 man/cs_app_tables.Rd create mode 100644 man/cs_timeline_data.Rd diff --git a/R/app_server.R b/R/app_server.R index 503140ee..19886b05 100644 --- a/R/app_server.R +++ b/R/app_server.R @@ -24,7 +24,8 @@ app_server <- function( meta <- golem::get_golem_options("meta") app_data <- golem::get_golem_options("app_data") app_vars <- golem::get_golem_options("app_vars") - app_tables <- golem::get_golem_options("app_tables") + # app_tables <- golem::get_golem_options("app_tables") + timeline_data <- golem::get_golem_options("timeline_data") available_data <- golem::get_golem_options("available_data") user_db <- golem::get_golem_options("user_db") credentials_db <- golem::get_golem_options("credentials_db") @@ -51,8 +52,8 @@ app_server <- function( # For query item selector drop-down menus: # available_data <- get_available_data( # data = app_data, - # tables = app_tables, - # all_forms = app_vars$all_forms, + # tables = app_tables, # outdated arg + # all_forms = app_vars$all_forms, # outdated arg # form_repeat_name = with( # meta[["table_names"]], # table_name[raw_name == "form_repeat"] @@ -70,11 +71,11 @@ app_server <- function( ) # For timeline data - timeline_data <-get_timeline_data( - app_data, - available_data = available_data, - treatment_label = meta$settings$treatment_label %||% "\U1F48A T\U2093" - ) + # timeline_data <- get_timeline_data( + # app_data, + # available_data = available_data, + # treatment_label = meta$settings$treatment_label %||% "\U1F48A T\U2093" + # ) # think of using the pool package, but functions such as row_update are not yet supported. r <- reactiveValues( diff --git a/R/data.R b/R/data.R index 12f055b5..39abd2eb 100644 --- a/R/data.R +++ b/R/data.R @@ -157,19 +157,20 @@ "cs_app_vars" -#' Application Tables +#' Application Timeline Data #' -#' A list of data frames containing all application tables. +#' A data.frame containing timeline data. #' -#' @format ## `cs_app_tables`: A list with `r length(cs_app_tables)` objects. +#' @format ## `cs_timeline_data`: data.frame formatted for comsumption by +#' `timevis` package. #' #' ```{r } -#' str(cs_app_tables) +#' str(cs_timeline_data) #' ``` #' #' @source See `raw-data/clinsightful_data.R` for details. #' -"cs_app_tables" +"cs_timeline_data" #' Application 'Available Data' diff --git a/R/fct_test_clinsight.R b/R/fct_test_clinsight.R index dd539980..0806bef7 100644 --- a/R/fct_test_clinsight.R +++ b/R/fct_test_clinsight.R @@ -36,7 +36,7 @@ test_clinsight <- function( !is.character(meta_data_path) #| ){ stop("The 'default' or 'dev' config cannot be used with custom data, ", - "and meta_data, app_data, app_vars, app_tables, & available_data ", + "and meta_data, app_data, app_vars, timeline_data, & available_data ", "in the config file should be character vectors.") } # Build a version of `app_data` & app_vars @@ -44,16 +44,16 @@ test_clinsight <- function( app_vars <- get_meta_vars(data = app_data, meta = meta_data) # Build a 'app_tables' - app_tables <- lapply( - setNames(names(app_data), names(app_data)), \(x){ - create_table(app_data[[x]], expected_columns = names(app_vars$items[[x]])) - }) + # app_tables <- lapply( + # setNames(names(app_data), names(app_data)), \(x){ + # create_table(app_data[[x]], expected_columns = names(app_vars$items[[x]])) + # }) # Build a 'available_data' available_data <- get_available_data( data = app_data, - tables = app_tables, - all_forms = app_vars$all_forms, + # tables = app_tables, # outdated arg + # all_forms = app_vars$all_forms, # outdated arg form_repeat_name = with( meta[["table_names"]], table_name[raw_name == "form_repeat"] @@ -61,6 +61,13 @@ test_clinsight <- function( tryCatch(error = \(e) "N") ) + # For timeline data + timeline_data <- get_timeline_data( + app_data, + available_data = available_data, + treatment_label = meta_data$settings$treatment_label %||% "\U1F48A T\U2093" + ) + temp_folder <- tempfile(tmpdir = tempdir()) dir.create(temp_folder, recursive = TRUE) # saveRDS(clinsight_data, file.path(temp_folder, basename(study_data_path))) @@ -75,7 +82,8 @@ test_clinsight <- function( "meta_data", "app_data", "app_vars", - "app_tables", + # "app_tables", + "timeline_data", "available_data") purrr::walk(save_objs, function(x){ rds_file <- file.path(temp_folder, paste0(x, ".rds")) diff --git a/R/mod_plot_efficacy.R b/R/mod_plot_efficacy.R new file mode 100644 index 00000000..9314d6d0 --- /dev/null +++ b/R/mod_plot_efficacy.R @@ -0,0 +1,294 @@ +#' plot_efficacy UI Function +#' +#' @description A shiny Module. +#' +#' @param id,input,output,session Internal parameters for {shiny}. +#' +#' @noRd +#' +#' @importFrom shiny NS tagList +mod_plot_efficacy_ui <- function(id) { + ns <- NS(id) + # Create custom class to color navset_card_tab background to white + div( + class = "efficacy-card", + tags$style(HTML( + " + .efficacy-card .card-header { + background-color: #ffffff !important; + } + " + )), + bslib::navset_card_tab( + bslib::nav_panel( + title = "Waterfall Plot", + plotly::plotlyOutput(ns("waterfall_plot")) + ), + bslib::nav_panel( + title = "Spider Plot", + plotly::plotlyOutput(ns("spider_plot")) + ), + full_screen = TRUE + ) + ) +} + +#' plot_efficacy Server Functions +#' +#' @noRd +mod_plot_efficacy_server <- function( + id, + form, + form_data, + form_review_data, + review_type = NULL, + active_subject = NULL +) { + moduleServer(id, function(input, output, session) { + ns <- session$ns + + # Track selected patient (shared between both plots) + selected_patient <- reactiveVal(NULL) + + observeEvent( + { + review_type() + active_subject() + }, + { + rt <- review_type() + as <- active_subject() + + if (!is.null(rt) && !is.null(as)) { + if (rt == "subject") { + # Only update if actually different to force invalidation + if (!identical(selected_patient(), as)) { + selected_patient(as) + } + } else if (rt == "form") { + if (!is.null(selected_patient())) { + selected_patient(NULL) + } + } + } + }, + priority = 100 + ) + + data_p <- reactive({ + req(form_data()) + + form_data() |> + dplyr::mutate( + # Clean HTML + dplyr::across( + .cols = where(is.character), + .fns = \(x) clean_html(x) + ), + # Convert to numeric + dplyr::across( + .cols = c( + `Day in Study`, + Measurement, + `Too Small to Measure`, + `Not Evaluable`, + `Sum of Target Lesion Diameters`, + `Baseline - Sum of Target Lesion Diameters`, + `% Change - TL SOD from Baseline`, + `Nadir`, + `TL SOD Change from Nadir`, + `% Change - TL SOD from Nadir`, + `Best % Change - Sum of Target Lesion Diameters`, + `Best % Change - Sum of Target Lesion Diameters Imputed` + ), + .fns = \(x) as.numeric(x) + ) + ) + }) + + data_wf <- reactive({ + req(data_p()) + data_p() |> + dplyr::select( + subject_id, + `Best % Change - Sum of Target Lesion Diameters`, + `Best RECIST OR` + ) |> + dplyr::distinct() |> + stats::na.omit() + }) + + data_s <- reactive({ + req(data_p()) + data_p() |> + dplyr::select( + subject_id, + `Day in Study`, + `% Change - TL SOD from Baseline`, + `Best RECIST OR` + ) |> + dplyr::mutate( + `Day in Study` = pmax(0, `Day in Study`, na.rm = TRUE) + ) |> + dplyr::distinct() |> + stats::na.omit() + }) + + # Waterfall Plot + output$waterfall_plot <- plotly::renderPlotly({ + req(data_wf()) + + plot_data <- data_wf() + selected <- selected_patient() + + # Modify opacity based on selection + if (!is.null(selected)) { + plot_data$plot_opacity <- ifelse( + plot_data$subject_id == selected, + 1, + 0.2 + ) + } else { + plot_data$plot_opacity <- 1 + } + + arcus.viz::plot_waterfall( + data = plot_data, + id = subject_id, + response = `Best % Change - Sum of Target Lesion Diameters`, + status = `Best RECIST OR`, + static = FALSE, + label_xaxis = "Unique Subject Identifier", + label_yaxis = "Best % Change - Sum of Target Lesion Diameters", + label_legend = "Best RECIST OR", + textposition = "none", + hovertext = rlang::expr( + glue::glue( + " + {label_xaxis}: {subject_id} + {label_yaxis}: {round(`Best % Change - Sum of Target Lesion Diameters`, 2)}% + {label_legend}: {`Best RECIST OR`} + " + ) + ), + colors = c( + "Partial Response (PR)" = "#4DAF4A", + "Progressive Disease (PD)" = "#000000", + "Complete Response (CR)" = "#377EB8", + "Stable Disease (SD)" = "#FFC72C" + ), + opacity = plot_data$plot_opacity, + event_register = "plotly_click", + source = "waterfall" + ) |> + plotly::layout( + title = "Best Percentage Change - Sum of Target Lesion Diameters per Unique Subject Identifier" + ) + }) + + # Spider plot + spider_data <- reactive({ + req(data_s()) + ds <- data_s() |> + dplyr::mutate( + subject_id = as.character(subject_id) # ensure character for matching + ) + + sel <- selected_patient() + + ds$plot_opacity <- if (!is.null(sel)) { + ifelse(ds$subject_id == sel, 1, 0.2) + } else { + 1 + } + ds + }) + output$spider_plot <- plotly::renderPlotly({ + req(data_s()) + sel <- selected_patient() + ds <- data_s() |> + dplyr::arrange(subject_id, `Day in Study`) + + arcus.viz::plot_spider( + data = ds, + id = subject_id, + time = `Day in Study`, + value = `% Change - TL SOD from Baseline`, + color = `Best RECIST OR`, + colors = c( + "Partial Response (PR)" = "#4DAF4A", + "Progressive Disease (PD)" = "#000000", + "Complete Response (CR)" = "#377EB8", + "Stable Disease (SD)" = "#FFC72C" + ), + marker_size = 14, + highlight_id = sel, + highlight_marker_size = 16, + faded_opacity = 0.2, + highlight_opacity = 1, + trace_lines = TRUE, + event_register = "plotly_click", + source = "spider", + ytitle = "% Change - TL SOD from Baseline" + ) + }) + + # Force complete re-render by changing output ID + outputOptions(output, "spider_plot", suspendWhenHidden = TRUE) + + # Click handlers + observeEvent( + plotly::event_data("plotly_click", source = "waterfall"), + { + click_data <- plotly::event_data("plotly_click", source = "waterfall") + if (!is.null(click_data)) { + clicked_patient <- click_data$customdata + golem::cat_dev("Waterfall click - clicked patient:", clicked_patient, "\n") + + if (identical(selected_patient(), clicked_patient)) { + selected_patient(NULL) + } else { + selected_patient(clicked_patient) + } + } + }, + priority = 50 + ) + + observeEvent( + plotly::event_data("plotly_click", source = "spider"), + { + click_data <- plotly::event_data("plotly_click", source = "spider") + golem::cat_dev("Spider click event received!\n") + # golem::cat_dev("Click data:\n") + # print(click_data) + + if (!is.null(click_data) && !is.null(click_data$customdata)) { + clicked_patient <- as.character(click_data$customdata[1]) # Get first element and convert to character + golem::cat_dev("Spider click - clicked patient:", clicked_patient, "\n") + + # Only toggle if clicking the same patient that's already selected + if (identical(selected_patient(), clicked_patient)) { + golem::cat_dev("Deselecting patient\n") + selected_patient(NULL) + } else { + golem::cat_dev("Selecting new patient:", clicked_patient, "\n") + selected_patient(clicked_patient) + } + } + }, + priority = 50, + ignoreNULL = TRUE, + ignoreInit = TRUE + ) + + # Debug selected_patient changes + observeEvent( + selected_patient(), + { + golem::cat_dev("Selected patient is now:", selected_patient(), "\n") + }, + ignoreInit = TRUE + ) + }) +} diff --git a/R/run_app.R b/R/run_app.R index a35905eb..e7270177 100644 --- a/R/run_app.R +++ b/R/run_app.R @@ -28,8 +28,9 @@ run_app <- function( meta <- get_golem_config("meta_data") app_data <- get_golem_config("app_data") app_vars <- get_golem_config("app_vars") - app_tables <- get_golem_config("app_tables") + # app_tables <- get_golem_config("app_tables") available_data <- get_golem_config("available_data") + timeline_data <- get_golem_config("timeline_data") user_db <- get_golem_config("user_db") use_shinymanager <- isTRUE(get_golem_config("user_identification") == "shinymanager") credentials_db <- get_golem_config("credentials_db") @@ -47,8 +48,9 @@ run_app <- function( if(is.character(meta)) meta <- file.path(data_folder, basename(meta)) if(is.character(app_data)) app_data <- file.path(data_folder, basename(app_data)) if(is.character(app_vars)) app_vars <- file.path(data_folder, basename(app_vars)) - if(is.character(app_tables)) app_tables <- file.path(data_folder, basename(app_tables)) + # if(is.character(app_tables)) app_tables <- file.path(data_folder, basename(app_tables)) if(is.character(available_data)) available_data <- file.path(data_folder, basename(available_data)) + if(is.character(available_data)) timeline_data <- file.path(data_folder, basename(timeline_data)) user_db <- file.path(data_folder, basename(user_db)) if(!is.null(credentials_db)){ credentials_db <- file.path(data_folder, basename(credentials_db)) @@ -100,14 +102,14 @@ run_app <- function( ## Verify app_tables list - if(is.character(app_tables)){ - if(!file.exists(app_tables)) stop(paste0("Cannot find '", app_tables, "'.")) - if(tolower(tools::file_ext(app_tables)) != "rds"){ - stop("Invalid 'app_tables' format. Expecting a file .rds format") - } - app_tables <- readRDS(app_tables) - } - stopifnot("Expecting 'app_tables' to be in list format." = inherits(app_tables, "list")) + # if(is.character(app_tables)){ + # if(!file.exists(app_tables)) stop(paste0("Cannot find '", app_tables, "'.")) + # if(tolower(tools::file_ext(app_tables)) != "rds"){ + # stop("Invalid 'app_tables' format. Expecting a file .rds format") + # } + # app_tables <- readRDS(app_tables) + # } + # stopifnot("Expecting 'app_tables' to be in list format." = inherits(app_tables, "list")) ## Verify available_data @@ -124,6 +126,20 @@ run_app <- function( stopifnot("Expecting 'available_data' to be in data frame format." = is.data.frame(available_data)) + ## Verify timeline_data + if(is.character(timeline_data)){ + if(!file.exists(timeline_data)) stop(paste0("Cannot find '", timeline_data, "'.")) + timeline_data <- + switch( + tolower(tools::file_ext(timeline_data)), + "rds" = readRDS(timeline_data), + "parquet" = arrow::read_parquet(timeline_data), + stop("Invalid 'timeline_data' format. Expecting an RDS or Parquet file.") + ) + } + stopifnot("Expecting 'timeline_data' to be in data frame format." = is.data.frame(timeline_data)) + + ## Verify user database stopifnot("user_db should be a character vector with a file path" = is.character(user_db)) @@ -184,8 +200,9 @@ run_app <- function( meta = meta, app_data = app_data, app_vars = app_vars, - app_tables = app_tables, + # app_tables = app_tables, available_data = available_data, + timeline_data = timeline_data, data = data, user_db = user_db, credentials_db = credentials_db, diff --git a/data-raw/clinsightful_data.R b/data-raw/clinsightful_data.R index 39d03212..6d27606f 100644 --- a/data-raw/clinsightful_data.R +++ b/data-raw/clinsightful_data.R @@ -3,7 +3,7 @@ devtools::load_all(".") metadata <- get_metadata(filepath = app_sys("metadata.xlsx")) clinsightful_data <- clinsight::get_raw_csv_data( - app_sys("raW_data"), + app_sys("raw_data"), synch_time = "2023-09-15 10:10:00 UTC" ) |> merge_meta_with_data(metadata) @@ -13,16 +13,16 @@ cs_app_data <- get_appdata(data = clinsightful_data, meta = metadata) cs_app_vars <- get_meta_vars(data = cs_app_data, meta = metadata) # Build a 'app_tables' -cs_app_tables <- lapply( - setNames(names(cs_app_data), names(cs_app_data)), \(x){ - create_table(cs_app_data[[x]], expected_columns = names(cs_app_vars$items[[x]])) - }) +# cs_app_tables <- lapply( +# setNames(names(cs_app_data), names(cs_app_data)), \(x){ +# create_table(cs_app_data[[x]], expected_columns = names(cs_app_vars$items[[x]])) +# }) # Build a 'available_data' cs_available_data <- get_available_data( data = cs_app_data, - tables = cs_app_tables, - all_forms = cs_app_vars$all_forms, + # tables = cs_app_tables, # outdated arg + # all_forms = cs_app_vars$all_forms, # outdated arg form_repeat_name = with( meta[["table_names"]], table_name[raw_name == "form_repeat"] @@ -30,11 +30,19 @@ cs_available_data <- get_available_data( tryCatch(error = \(e) "N") ) +# For timeline data +cs_timeline_data <- get_timeline_data( + cs_app_data, + available_data = cs_available_data, + treatment_label = metadata$settings$treatment_label %||% "\U1F48A T\U2093" +) + usethis::use_data( metadata, clinsightful_data, cs_app_data, cs_app_vars, - cs_app_tables, + # cs_app_tables, cs_available_data, + cs_timeline_data, overwrite = TRUE) diff --git a/data/cs_app_data.rda b/data/cs_app_data.rda index 36d2e166c5eca06f89428a3c37c58089f0e9845d..875112f427e72b598142f91b726b60be7f7e35dc 100644 GIT binary patch literal 45811 zcmV)FK)=62T4*^jL0KkKS?3LSrUdK|fB*mg|NsC0|NsC0|NsC0|NsC0|NsC0|NsC0 z|NsC0|Nr2NTmVo9ea3@I4ZsBe4%%DkyZEf#c z&iFS6AxFE~aqYPtIHTMER`p|c?Z-p_Gqq%T`?nxI+`0Ee!b+4p9_*}_J7M?PGep*R zh3~WD%h$bbvP}aQcL&n@-vt1^`Sr`=M6};KxGIaif$i>~EAIx`cUAP%0Q>Ii%sM*W z&F8qh^P9Jx!9BkFJM8Dowwl>`J?5_y9k}~Bd)wK7Uw6R!;qCwczJLH7lix?VzO^pK zfVxY40euA&g-6qN=6811wQFNj7i?XKAj`G_i?)Pq$6$~Y<~G)89hke=9p=+ot4%~F zySi0-w;2YcwVuscv0%ODXuX;Z52v6200(b#kPo@tY|g+Ow(i2CdcsK%K$!p&38M%m z02&Bj2+5{Q0%XWyFe64yG-;+rMwlZ(kkHdnjR4SS05v@s4FCWDG}OQaJdH9vP-&nN z1PP-=Afrt-noS$jOq!k}O))ekjXe_)kiuvKO&E-f2r!KR+5l)K1i*|4zzBMbOqiag zn3yF$2pa1|G8UgBP8UO$WfSRQUf*CYuAZldElS+Pu zRR2g*HmQ^KN9r=0Q)*_Ill4s=QJ$3AYI=>S>8SNKjGCHyn^0)=0QCSKrkZ-5jUoD> zp|u{MAF3XvngO5z>SP9osAx1Epeacvh$euU7=#%n(<4Jv*b^p`(w-)#@>P+;ePf@izr>WsXWYEeDl4;^iHj(NY zdY*~u9;c!o_#ld-|HR*z{1^OrDAY!gr7ePmpeQsNVktGYLY)qsM3{iqAkdL22Aw4) zgwvo+01HUC$v9ARRJ1T)A_gEf6bl#y!9ziT#<2;hLJ-gakTZfQMu0Xc1xTQXQKcN9 z(knn&Gb@IYno=am29}~sI!&enNEm?#3IL%Z0VxK7S7Zw&AR@AbAQYyIRH0EIK!%Vu zMJ+-ELxh#c56Oo6;`^gkuuqUPpkb&=r5d0po%wF<*zUCt zN2%9+b;F$T&iq@y7ZiHr^Bm+MOWrjTAw+T$kkUt39Bqn%U=5<8)ge0;T~cnX%%P2! z2ifKYIV~Veh!m>EKye{L&@dxPFMJ&h$sCj=gknO$Szclx_y8LULp>8HPle8L3yRre^y)H-?UH z-JmU0!sc*@Q1Ks)B`aoJ>TGs$%EU|TiXnXPB$OG)(aIvkmiT!7+m zGoec@mgFIT7!0yxF+Q_^|osq)co#xU|L95i7OfSqfn1t2nN+yfL0oHHn`p)jYgoYi!7 zMtnq<(9%@Zg+nERWK~aD?h2_YWL8}0u0Rzm08O^@G|H5wG$O`B87?=2FE_I4>F4J9 zn60rX;K(zJadT!Z5}3dmEL4)A2@J_C8(7PF0vO3G$xz>5KoTU}lQJ2FphkUDFpH2# zrJ^X3OO8k@*#*w^$t!YZN`y=%WVnS?EfrXr{=n+Yj~XWx8C4L)7{m{auY`G9-kO7YGoNKo90=F#|kRVRA|&i_sU2 z6!le5$*h~L=iLEW6e9@7)%D%}P_44KfPo+iDgvwMH~hYIy>E}~@0#ts-sf|#ci8-Q z<5g&1d<`yv{u*~Omg|m{X+wm7H#xxNNk)*+lyH?ofuRawT0@gTq#^`Ab08j|k#D{80dMKqJR{cW=v`c0?x*<8$WR@qzEtA2%{R$rZ3EM^_*X6s97YS`j-S z#3|GUk*1$8Zed7_L&8I%UEf?Zi=m={riJUQZH4|M;eq`DE8m=co^!qm`d>-_>P}if zsE48ve*ly@KJDqi6G+lTr3pwIyt{JeM@J61)6@(>z#7*Enhnd15Z{*Qc{mhMGCiw0 z7)PlZN69WCB8aV>G&D^Xvm{j{u_Yl&t|3#UkS3yvXx(D*(sF=C z`o~+I`1?fj#k%as93Ux2%!ZPJsc2fSTN2#B6eVb)EsWJw6aiEe(Ljs%!W74;8Ahn; zLHA0BA>@XUYMrq9L82~BhS)TLKujY-52OG%g}IkVg=q&86a`YTvJ`=fL!^l=^NFO7 zP1FY}K=BT!xs4Qorz8tOpwUWDsSwW5HHyrqKFv8d%1%wxIdRe(b({Tpc5CK}H%~HH zY}TV&%pDFl9FeA*B#S^$dygkaT_(STBy=BwiGl#7%MVDWP^!g1I7@|-7Dh!wR1i%~ zL_-TnM9>vQG{mtoG{ZqbF&+=eoDNi;?V4&JCZeJ>@^KF2;~jil+!|pb zCZwt>xO;)*tpzAhH*jW1XlPMXGw(*|w%7h+PI|NS>t9a|QsSAt-u>5z7$} z#0d~l3kw0s13*o3wS*i*60uQ0L?FaKL_rV|S{9UCK*Ynf%%Pxo5TbNdCUUYv1W5*- zK&in}kr#=YIgFgNLsEt$_n1B8bJ$O#?5XbsnF5v~ipt-6xmzQmoG{GH_ZF6+iJ?2A zNzNQ12-hA-?HW4koUM&$Ho`{E+~Ou9kx6U?C}U95ZERtJA|fD#frOF4j!FjtLIO}C zAcKJ|D42whfD;6##BkvwHlV_mnb>2UoSW6!ZF8HZ6D2?e^&ZZQ0f~)_3S-is;KXgt z7zm1ih*)E6P>v)bG=+mINunjjj06z@5E2+N1|k^}2uQ($B#R7E(StQ7#y4l4j*T3O8fi2=Nb+f_3_wMq(RITIMhrpGj0_NyqXIz! zOkl!e3mBscSfgh&6D$>P>hzKGG7=R#$7{ov)W;@Jjx=~JbN~Myn!yH|< zF^ncH+FD}_V-RDD4zr@Tk~l%p0of45LJ+`2BtsC6O${Wfr;6uD@tC43p@NF|87tvn zr&AhaB(ox_>|s~&uvGhOr19BGJULVxa8DHOp?(qwA&3|~WnIyY!Q2>cKpTk&Su+pHrbJ1e)F=kTM z1f0;7;4r|$0$_W^w6jUIyP&<%<)q@?=`OKp8QYAvvM+sWK2@={dSo-Ds?!=p5Ts1R z+)<)ERq6fJ*V9#R!nRRZ@~eleUK@^8{P^rd0Xqlxz(N552nqmJpENMUVbyF?XQ&ur zFw{ej)y5!*NQN?^b@=n5AcTlsQ-vztZ0Q%OV@y^$4ePsH7{db@H7q@Y7++r5UH40( z(Yc21YmU!+v5hXR9?Wc=cNWi$IoQ~_d3PYkE{7Hv-ZzY7OcrEgDkvOX>qUSaggK*P za9^LavyL|?+uqab9{q0@NV3h%CUQ<2rsdbr!TKCX=KI@en9^0=i9@?x$ z7#*@ZrQolyme^1xEm(3&g$mGIQ^DowWzs=H8BSXUO9IpK3{{VeVUD(d@+1tl@t43Ld?aYPwiaMH> z4@s{b&=}9a)v&CmkDJqu>;?P}g($hgZ0sR%N1)ftK?jdb^XPo^Fzkih5Yp@C@GBI@ z8P!MVrCQ%4|1Cd{)7IO$?M*d=jVWli?Taz;W29`xVP>*rTLlHA=`Fkk&aiTyW()RO zz~wO1#w*;M79Njj#TZ&N(g>gBUWY6DUl40R>cHOt?j@VpNZ1Mn;2^OBc$3=T2a$~M zSN3nOcWwRF`Mtv%+aTqDeMo&Tw;=segQ5aUr6-p>r1hh_@llRyTym)5z~X??CFBM< z+2A?7x!Je!hI6~XX8z+d*_%myMjwiIq>gX6W=mNg-K0jVwq{A_&`R!m)VbDcKk$e+ z{ZE{%_5Og&F1wG$GG8uc>2~uu#Aqxp<;xkcOHH}D@L7_!?9ub|#D+%U1=$5E3B7nz zgPDCwgDbUBvOQ#s(g?kAn2cxY66?&vycBLw(>3aEQi3an(3>m6=tg77^HF5M`|&vh zOYAMDRM&B{X{xWBi;N56vm7%E$G;;Pemvc(Bxom&9t?P8hQ_19bv~H+Ot-21?O1Zz z%KL514e{!Z%GkUVxfZR`<|}I`n)qLV?o4PH3r zvIuYfJY560;il@3ow#wEs9zcRVBHX*fjE=f4BA$0ANxoBXU~II-|Xh%z_9uT+Wok4 zVa{|)2}+VSpoaP0m;m{(u;h+|Pq?LoNbGf!qVY-Oj#d11Bo zRnB9}wS0ccKE|jB`6#EzLw^Lffw4br%r3?D$-giZ{m?&&?#h0lq3N4onm0fuYcYB< z$b*j-qGW6}$-N3q*Gu0~ssy7%=WfqMgLr6|H-nj8bQa`!SqPHN_bi!&KQ@O%;e2S7 zPLsE2y`>vBXX(?0HMhMo`cpRNRHuySA92=M2kt+HSR4@txXp8DhU8KGt@w?m=VPPS zz4R$mwOT`x`1FZcGf7526Ve|H?>~2yP~ny0@o@D09~myY7A$KG)guj#X0+t=e&0V_ zi!>;`Wqb5qa7@Wxc57Fj#g`@iQ}YJ!@t(68tp#Sdlj3PQQME`@DvHd_{!$Oz4r#iLjy zKEDbSZEYJZ8b*sxv?XW&Lfi2=o%*gWZo98XSv@!B{REPGSt>~bt`<$y1;Zj0Jo}ZX1MPS7TY3V&su6O@>lv0LfWk@6m z2$U>{0|rtPCJGE}3 z=2~YnCTa>km5BO#UqAGL0Q{tgeQ5xH4g^mzN2AIK-(?HiMP^i$m`RvZGE~fxtiZbU z+>>G%n8DpuHp+>Zq|7B{f*F*B^k2;^KXC-d(1&Bv=MT90JVfMm^B7BfH*JLt1k6Zg z3%O!Vk%Vw*D`ULNtK{A*5$nuLYe~at0yK4MB$FiJu_O!1c&PHS$av9r3OxGSPe$}_ zNt)x@*4}ou+ta(El6RT%Y&4Dvj#&85-nYnj%9|RRjQCUF& zii4vCU`nrh55ClzK2i4BrVIA0oyA&m-HSLn=Xqp_%nt{=qA&m;)5N`7Hg-A2+Qz*R zJF_Sd6bLmyJHVkrm>^nvCxuZ!a*PQekOu@r0>DH>LE~$&*kN{U`^&@W&v+@#CdPW$ zh~%m{${;p1&O0hMj1Zxi!7grNJhW|&uG$EQqG`Pm50#*Sm=c;PVU&So7?ueDnHV8o zU`t441JoQzKu}Un7%(tEX&e#{xgds=_yyAuLTPakC8jW+0Fm=IrgtLo@jVQymp?a0 zf2VKwc);&u4>uFjU_9KY_{@(_fiF6Rm{FNi858umO*ANI) zN(2fPkxCGy0X`&XX&Mk{282iA0YGR3C`A^42ATy*RZbWeW4p(d$8GlSD5p+UPOcoq z24tWVDg^;Zw2caQ0i-AjQKEq)Iehz0b|m7CC1mYY+XpQf1A06?y*u`@gyR0aJB6zI|sfRtClj5RH zN1tuT0M}v(00aZQ(NfbS%mvvyOSsK?^p@LFs_gW7oZVZkw=*)juJSo^sJD?+obZm= znG=j#h-rwz+g=Hp#vmFP#FJuc2FStG0Eh!+c)?t!_ zj4%-_(Fz52sQ0iz6Okl>lR&s6hyeGgNW~ut5fKe!wTxw$j)d>mYuV)i+w(hI-K^;K zG91Sp!(p|y;2cLX`9&owWcOLbS$scv6U(A;9Ki|*l%S@O`qF9mrP9(OeRwFA*%jY# z^!i+y^!a%@Vymy>LW`s5JqbW~w1VXDNzHXSx!!ZT&9u_XO%|BVG-)`t&MmyhD0!_$ zHZ)aJqgp95R8dn=Xd-kQ5n|SuOX>Z8q4WWwkSU^-6Rx{e2dPkWu5lbqNylOkP}uU< zOUS*Qxt>Qyjk2Md%}c5qNgGwr1Z68AQ$Z!uX$99mcVvkc(4HMu(5);fs_)$jTp=!6 zTZwc3Vjr@(B6;$B&rcz{yfE4~a>9oUW}aQCRoSjoJkv0mmqRToD&9>h+AO;>mWH-; zCM{{DUYsz1(J@aztU!f;q0f-rQm@yBYAbP;aP0%xp8P&`0JEgz&&#zrFkJTz>&3K6 zad4TIy#q0f5zypST&70xVUrT9Z#7Dmk6RGOmQL8jERzW2GM_{GS$j+3{Md{?qEuMh z&A77hQu+`*JPO&zLf6NKob^(e(^bQ8$Z6rUuQaP4QFy^@^M4)IxNRN;T zQiiEPLG% z=*Ez?G@Bb%GeA{U>Ff#t>k0v&P&5S!(3GR>zM`g;*wt2Gv66J7e4%S792pWctVmM7 z025Hsue=&qo5!6R%+1p0S61+PQm3Cn5dr`QG7%9Fb&!Dqc6x*7PaNkwV^)W#)u!2s zyBS$sZF_VJiPNXGbyo%JR^31%9$|-3Swg(nb(AHpUDUIyh0}f;vukYGoVlj{$3soJ zoX1q@D5~q^3$KDB@_ZOU1Dn_5$HDY^)$jB3zTjvgpem4|DOy4xehAc6Nku6`N)+52 z{p2PlhN4J?DZd-L?jR>Uam!cGY`t9*8LFZUCtb5wE=#UN0IZ;Onxn_X6rM&X@_H51 zd4W5-9o`dGQxQbTObCb9e*8ZDrV0cfX+m1%B^?Zk6GJMUX1|40Q>Sd-l4a+Ik*F~ZvX@i(olN<8)J5CcQY|i z&A8$<;x!(3UE{I&1ROQkZpVM>%nKHJlbKSlZJ`Voga*+S_P|Y+GzoOH|c!2PUpk)1)YAq^bg{sH!M7FqEYn z*rd6>%sl1;LRCytpnliNh#!F>A_~8b6bNGl2&^&_6--H0Ocp^2V<`$)!AMMqiDoKF zsd>2y&yC;eg&=eI41j~6RUH7T4uX&LmDp$dRieLKUg@SWTI^FyM2{h7?46_1pv~3+mbdh4YnXcU5A9O$5H{o6z@Nw zss&>m%KY2(K2wLx5%`7qT8E%X1Wt?kX*&*#C5k0`J8Ckn4$r%IfDKY;JkD#A*#r(1 zn5IG!uf+$HGN}_KJe*p>Fs~CUyxxb%xD`6_=j!?I>D`uteN3;k2SUi*Me;RNNh5MG z$rK>sw@tKS>eI0(e21vM9x%_+YR;NjLQX@Y^<8%Mca1u2VO(cI!BzqJ3$zFUfSP*( zdv>`a^!Gm_XnoQEX=zl66>jnds8rf=vow;-G9jdN0i`r4p>3^@MvZ7T&9H`*cEFax zAxP2yGzb>Rs5F70AY>v4N}5%SRI-j@soPXnTS}>73zp)No0tAu}gMWiJTWh%}@{Ldg z$3-~fv3!iJQ9>Tqq5F3z55?+-@E|&n5l)B{5R_p@tNk8uhy72(?0sQsDG8QV7Bd@T z#$O_9skZ$5OluJp`gu~I>co{VndPSMBk|vg$AP?}e0%TzlFzpJCb_5BH?+Yk?ec`Y z+v?t5%J(~#H`%iu~KumrFJ431R5%M`?7!x4rC z76ijE!axv8$U*@y!~rle!m{lroBj`5x543B+r-qT7EF^CDnh;Vk@W1L^F~aWjH-sR zfLrd26RawPfk-+vBEMi8h%4v^@PbWAu?c*Ldtmyo+#kUYQVoOZ*1_#VaN4f8aa>Wc zd*az}T+3;44glOYEYIw>suW?)z;>7K^(3gH&s#5ixrj067oc{h=?o+ z6iOB)nUE=!M^Tevlwib&w<|98`nov+ss3GWmJRGN_T=@xTll2!qDmO>Q96;>?b9KbNOD&o`yX195E3}9Gh5em@Op_>&V@eI`_f}+yt zlIX*&2c=YXa#YHk|2!^a{ud4x1OQ%%e5b3gUzXy*CD+PR`M-A65?^i8_+K{WR^&g4 zKTUtTeM!foj1lv85*5w(nuz(Y=*QlF=m$qZ6hTzQ7xCB-PxWLG{Fkfac;3o|fgsg0 z%W(vGIEuH|kq~SeWZa}tmOcReT}o8HE&$3BzAe<69cCsz#(NB!#ldTeHxv5n+RwAS z&l`-cB?bQ~$M>8$*`Al~_L6TP`*G{v&#&ua?3VDKJ92!_T)o4Ay;B%%&F()r%zpnK zG>H6D(cm zD>L#vRirIffoInLI(oZ~=InDv2l-U}yEzC?2tw+>^H^@9+sfe_L>8WKX(&KFF1*7{zxG+>7=kn)-6MP_ zBG2mj#l%)i;NMmA+S6)0xt!6b$qq>2&DPDOnlMUYB#9CL9$>xe1|dRZ(Q@&fgiVGj zS66+S2$Y0hS#@aJtiy!}ElCTJ%Zh2tR$+8Br4=PpO9f^Y=skro1!af%j8Zo4p+G@b zfiMsO2rL=sl3)-l(FmAr@?PiL&7sl7Uo5^Ri|{WmcPvK&a0qrVzRZM)0!9V65)cwnM<51v zOJc(rmu`-31`GRFLeIcCp@4jEjvX)0+mA}dj%u-)r4WXHI7m4SHb2cE0qp=0J>L2% zA}T0iy~BV5+>8KWUwaP#IS~}JQ4vK%u|yuI;SEItS3}gqltf?y4jcejy4J zEOR`$a-t2>l*ZdtP1Q+4U=#uAK+gByfFWL05`K(TT@u8jLcZ!O5o`h>2m)FR@;MQs zlB>T`!&Wq*8&Vx!8JgQl(_Gcdl9@Gg6DD|NMpTbN4BGJU!H-=rYdB?GjblPYK|KYD zF&+&rZU7)RRui)8s=F9vRv_6B;26@Svm+{GOIrp~Fc~sfFf#99Xfmym;h33AL^eVg z7$$Nca3ohKa9~LkECUOGC{k5`VgQ&HQozPSVliU_EDWl>!v~Bl-2cd`Tm-Mom#mw# zg7bx@_Uu)L43TBPZTNeYjh4`!@Xr&u+Rqon?)RNlp}L4A4StMo`LOUS|<+HC7?6l%Ju}@2NVNg zu+K5KKU=NV&HDMab9T+pH9%ztW*Zf;&&c6)uk z4u_^Xr&Qaov63#uIB@h;cVl%RfQS$cb{hp9n(pg;(pR&ByWNZixRPpFl~!W$Zf48f zzd~Jt@w3 zIC#8VWpjk5Do}I?LILA}m_g!zfe>G?@9X5Jv#YnGbg7y$)X>G7rK?|UKql54D64YH z*CZ7amlO%iCwUNZMb56pb~WeJx}_z>*W&t|d z5y^Q}y46HHveeUobqv?lHbdAj_Ow>kmK06BmqlqcDkX%N#bXrsGbL$WmWZ)%&a-Vw z;$|AjhlguqVNoouwCZaNO&JqYNs5xuX4?|74G>xz4F#p(VW8YWhO<>H?RQT!9VA^< zvAGjX6(Lk&=AEwAjm8?0t`;s}QPDCXHdC-+I-x5`s%>rRI7vIw&&E75s&1s&fXp*0 z@KHQ4o#jmg$92IM;|T0+E(t20DtUAdLY^XeUl;+!5d;M7$P?N}Z-2Ss8@s(h`}R+L z%-$Yqjc$s1V`Uq1?rV%0-9i4#gTNCxZ@`J1BqL+)wXcn-;aGka^xg3#wy;{ycD?55 z(loWK|{tk?Or!S)EMz_BEzrv0VvN+A5S}Y1} zE9Ixj&8U3q@@YMwzZxkq@XPq!zBx%G7trU^EUrnIW+s9^C2ER{Mx6~)rYh037{O4GB!$92!0?@)hxvYW zso}gU>@6N0;p?qY60~53^(9c2XJdsD?8@rp8j9SNvX6ypP{c_H*Gwwc7gY}k@eKB= zW!DAE5oEYg1PN+rA&63mi!9|4-aAqt#!@_|pY`8eXjA2qLm`S-? zAV8IJ8wyP-nqa^|!9iCICUCY=h@3EKEjB}yq^iL5VHvh+>YtGQ@VMU{g= zqfVj0VpUb5T)K(FGAXND#u#7}VuDK-1&G0;WdlmxDqXu{3eF0pQ-z9zye-SN4g{*a z;lPGe7I8AkPRxu6rK4t9K(ZWx2F;Ks5bACT!@C74P-4|2;G&enJ{?*b%-Wz;TEom- zh%QxGkU2<&bx`uOT%suE?S20M&;b&RGkWp;ec(Xw<$%g^mN z2jiJHABCm%c+6CC{#J>>_5M?2gbca|NX#G*mNxRZL0W30iF-?jW6(*h1Db?A70uMb z;L!6M7RBMuPTs+o%w|mUJnS7ll@RGb4FczQrEoSRm#)xARf&hAKtR1AwdXJz17TJI zskZEiw#l#pCV`;fIrX+?=CrI11ys?#ZFK;2s6EP|>kpVsC}`~Rcxll zr-UB^y!PZ=bXLZVGQ92zXjzFOfb`vVOW1mD5+{{APg9)|hmm+aFFA=fR79z^4X-LP zBLJ*a8YQs6f?&ocv~9MkV=OXjMH;{h5UM6nptO2BLqO=BLY=1+;PAn_H!*0^zCk+2 z9vU~v4lOZpaW$=4T%!@q7%p(O-;N~i}}Rv_rDu#*9)*>+SD zP$ZL7U<|P{hIfLwD!6;K9mB$io&@r|AUDBqTvvU5Z2lj@jX%Zuvb$96=MG#7_@s)29tV$37H0xXj2tK5Jj*R z5@7_T>bBEd8s|*qNs8A2i_TgA!a(V$oMe$qK}PWrrX`F|W@d{nv{!(vm8GH;f)$;r zjaq|hA{wwLNsnA!*vfNPTH|N33lgM}H*wSC%hJ9t9;x6w7)>X6bg)pZ6%ha-wcX6h znAU5tGfc>$HbB5l7#@!xY^9ic$~@#1xw2ln&pbv(Ub7cfv)SluHWMZk4Hz1{I|hI< z^S0XHvlopf#pxWF&U6M~DG9J+kt{H=HEe9!?_Frdtq)t54W1E$M)5YblXdHZNR-e~ z+3S;#bsWY6kay`ZoGc+WVg!?Ru97PRB3c^?1Xxhugb2!f4qXW764Y6^2=JZ7>k5Ht zvA|;b?;?s#2(Y7HbuMIc!Ar_o3IdV;bEsNrX#~1n2rwkzlrXeU6Oe=>pYl#{Mu7@a zmB>jk)RKq?eVpTd5JmzCM~Wez0#$YajYvQg_!qEK2P6tY0)(K2gsEGw9|6#*o{{RP zNCpQ74OZD@r9&G=iF|0DY<@HGYmds1AxRJ=1hCWy7dKCCv!K}h)OF(O=8=eA-$;)^ z!Q_`w-THSE+#9qx-hB#170S#CXug9NcybVfFGIqZKFY2}0;JX$mV&ng+E?Y%YgLQd6Nc6loHJLrQ6)mbFg{Ul5t3F4N|}K4 zQb*2)ku14Wa3zijm5?#eVM=KNQPU8#Xg#V)n%*q70|A!;tki(SE6D?(U}QM4%8nz= zCl>pFHuP12t@A#ojNvZ=M8a~{1)^sJKB*LKZVHwuZ@kl+waAqYLaAIY>eVR3a&pX? z9IfONN0^FPOL@H1&I(A;#8Hxkz~NesJBpi)j8ZEoaBq`ERN)c~;-NC-N+?L3CvXrj zH19GhI8KE(#4T;|g@J6X_F7**X}W9>fq z!;Md`PXo@*otas*(~%!xPKiLIkt8t5z2^7ZsL_V-=DC8z^)dc$$VF=LHEMs-Pe_83z#8CGZV1 zcVel=IUBbml`X0)sP5HKjgx6;oQcgsh}>JM%N5i~p+KjhEY1Nf^f4{em}{-=0B8rT zCKNE*J)~0vQ%P36X z&>RA~aUqT#K|%afJ};1JAebVm3Mr~+1b`%AfFOPWKl1yU!kX%Uq3BZjrw9@aJoy*} z8V=NI?)n6b8tF=^I=@BZ`E}Ux&9$CeSnzS(Rleesx5U=CJuaOV7;vMQ5=oM(zA+&s z1x>ZRm=86afPp;`1xS4O>&U)g&bqfT$SS^Y5CZ@h1i%k*&<6W5_$(kXk3u(gSOtg# z5D5iE6u>|LhLDeOuCbz7o5m)!#$w`Hz$jQ+Eae@h97e*a~DhvlV&jr1AyT@28 zXIRyZjcpo@vtrh^;phV@_{XyuLxLPHPL((=WcuN94^Sl+);N0SOX&}52P43D?PcVP z)Rx}wIqDCwL>;HN?1MjD1rhy|%8*UCxn#y9>$YW#vbjbh6X-G5aYZA$2q^3p1@1at z;D~z;1qIrmAZ0!dyOxgnk|=2da;A|uyaR4(S8=>XMul}lYlO>1%N`hN1HiDs1i-`` zE%b<_nJKDjsi=qo03pJ_z+%K*zePJ~)GC$WE#WoDMMPvmdPsT)ehAzNsVOQFs6j^g z;ibL_`A$V29wkvjzXivbu6RWm>ll#XCnW1;y#zS+-WCEbGR6!i$xJZKIfLqahb;+rfpm3sprS49ho!{Q*?kO~`= z4N#fEOqjDWC?lv;sZuoRomCV^OeB)3s+lDhqBNBS2$WHL?k|;w4++5bsPWe~w-0Ft z$`U;`&O(Q-jvNop55OuIP>-K`f)0Bn61EmF#G&x}ghj9dMgsvr?u!6O^S`O+|8VrZ zobF5Te&v5d!(hR%huDFzRuDS)`jLdsVj+Y_RT-`TB=i8z<$lBV=an-((_hUzwpze`{I(iBpe%^00Y|Lw|P$&U_L0(Mjl-t-TvEvdmooTd-ZH&Znu#dsJJM-9h zyT;vW40cj*dV`_R$JE9O3PZAHlg+t=_3_mvWE7x`WYrj_Ate}0no1g6*kg)of?)JP zDTdWS$}W&vk}nHZO;8b8F+_nUG#Y_JLuDeUt78!rY+`xr`8=cP9r}*!I_w*vWa%GN zIE(B=#Q=5U?D$pQ(i-N}+2*qO?afyEXc`+BCSxfAh}{|;Am_Q|zz|*#+eCP6B?>5Q z25x7a=BtXqzmiIHgr^P$V=Sq|gq#DPxhDJqoX&lmgIrrS3rnz z-ra$+-DfsU?lw30+k&jMETPb@GeT+%W3huSqBcX`MTi5UjuI)7=xE}GRnKa$ljEdSA%$a$YE%e7 z5IH9At6q`jup00oHSqjn^u!bAiU`sI(0~*HNKy>|zEwpJHC_vE zJjuZf0rXr(Sw4s_1A{LlMIa`6fSo`Nq)O?abiBsJLm(P~YDRCdXGFJTHq(q6Gq}Co zu;i+z2HTE8I7u8NB{fvtNaa;j-zf@#Y62GEK|yXHa#bFL=^f9Cr1x+R3ysa~z4hCM zq&CxF(AX4OL(p?HRW0*#dy@lHZscD{MSc(vNO&9&^y{LiqKYDh7)%UUurM)Vz`(`E zH*SvB@Gl1l>t;FbEt9Xr6*k)Jieo{tQEa1^4hzH4wX)Lb?RK=v)NQqDEw+tVqKsnN z5Q>Pa3Ulzf6jZ{$2>h7Req}6zzq0}57oOWq9G#Dp;GwC9|$|6{m+rS+RIkmRUvT4-U76&ID{gS0Q4c3aY zeCXGSvD6C#YP6>vjgWW>4!r?vb2Ou$t;3FSQnL{|0msP-GIiwpyyVVllKGXm*1RW1 zaP;)Et*QtKyRmfjYoSiMc_&sk23G@sJ_qDFOgc2$Fk;NT4~KK0C`bwdg&->0sR<-& zG#Eb%V9TvFK!aky3%r7PU}V66AybjTOpZcjum)9vgesLKR7Dju+a8DyhEO~U1|VcU zGs&dT;daLUDn%lJJ#MQwzv#4^5udlTR`Pz3S3e$O0vBgyj&vkH8>Ei*IFcLWz$ zR9TgVX^M7WSyV#6@(et+)V&a8swybcy0kOP&@So;R#4^OEL9{j6{u!vWrGcO6A(o? z6*jE~s$fZijLmeSCasG=Vy$xy;ub=)J2bScE0XIFOgqIzy)x9?GX<-bh)|(K)J?5R ztxZEq%G))>O|rANxQUpcL#btB3Rux^8f%>zzg8{65** zdUf&D_T?u-d;L7%)NpS!be%HL?#*1}E{<)RE=v_zWVm}{JNYkQZso?j^2ZnUs@}c+ zZI?Oep8WIN?6aclmR(un8CYzuCtSL^xsIFi&N=1Yx9s7^Wy^+q8M6{OFI<}4rY8&^ z5vAwEMLY40F`iM5IX&mcGu^ITFLy^Q%iXr@`|RDjy=LzBL6mlCyES)Mt~?~yVD0M8 zvhM%QcZBs_?v4X)8-_<4v1-_C3}Za9$zK@h5_6u`)-oFKT{|0GtD^V&Sz9LKyMpfS z->Qq``0U)gJL@f{LB#Rzz4!X>DyWVb#u;U1TWN#Gmlx_@JeK)8joY{7#Ba6SuKW8j zF8jrJ(WN=;$@lQvTYz^E_9QRJT z2%HuhxHei&G}lSi^AFIZM5@l?b~Uf*Rx&G8SZ%7LA33y;|q@gIruys zc*;UUOadVZC^ zAQRSBDIzw!kUnFb0vOaVk%1Ak45$%-7U8mAyQuuH{mAy$p7(=W{dilK_W%7J7Fx)5 zoEcOcFJ<#OnKnM$*#{jA|0ho8&UM4!m$%MFeeE78!ivULHtFGM`(Jm-pQWp#ov3|u z+%*k{9T#g)4YjW;?2~NXP~q$JHI#9*v?}k*==A&g{+vXsadB@t0o&PyUV}%=)Ehn;wRm5)x!l7zm{1|HX-8uBdCf3zUF2- ztE?wk7SH(DP)nOI!_rH(QoFclEsi`pqp53dxL&FfuA$ts80&wXn2RSCuSMW|R*Uo) z%c)6GdaQiIb?LsB17@_!qhu*B@Z9@P&*{W;?7%UU(>#s3eIV2byCy}uCr zZD+l2OKqd$b#(G-ZjRAkZG2Yl_lu5$1(JQ4in)|G3Td%pZ-qXF4o;SX3yR2VtkXXZ z*EK_-sGX3cbvv~*v-2lQ6oEq8cxkZsO8P4a5Am$Dcqn~(x$5a~*s@CDhqS(;maf%L zF16I2AD4cQ9WXD9T^SB!Go0XQaNhy*MiWs`KHk8B@WCBSmq@u+Whmq!bT&5mvY|{4 z_^z|?%axIaI=L}L7_Ie=w6&eAC!Dwdf6sDp%QhUb#1fI+VT@; z1&Ood{RND0=bRoZAQGmjxDnnin%u#r%OG=CN5G%Xu*)bL4|p2VM(e<%E5id6jc z4MQV1w#^G_T~-_as~_#NM+reH7LV!`dlm)<3qGzSbVCkEw;?l0X|G_-NQ!wvjb^lNq7Di2}F>Lbp6=q zgqquXJK9~F*ujU5=O%Lp?+|OV>AET38PWCe9}%GVjU}kpzwc3amVnifsPOu?8*AkE z;Z1%r&lbBX#bJkGgyj7!TT_=j0F&X^>!EUl{nx?Ne&Yv$tGrE zzY`1eg_I6Jmb4##@?d+PlBcOeLUT>n$)zgE8w&hmv(5qBisf}bm# zQn3xTn41a0;AWmkWXnR=dlzP>)H8|l*1~s&CpTBCmGROBgVO&F@ETYk_1)yx)GBAt zn95tP+Hcn}dM3HniH`S}j5L+30Ri(jEO+fpJ^sM-J|OG20(^d4KQhD6b9W(%rPEJW zR;G^vXfF_+`Us3PdQyXVgkpG(=YihA^yE7r;KWe0v_ajmte7jFHzQU@Orkp>x~k^_ z+AJGoxTU_)91E-xI0)%Ibq8R;=$cVUarMN}ybd?za4K)Hz@{chwzRfEt*C_|=_E?2 zJz?_zd>!D3PZHr^mY}^X%%Mn+lLwf6VCfGfhA0>yLZF|)!g|BRdd>^sj1;fQeU2b* zZ+M9nqeMr}M4%xwu{tdAyS_7>TaH8#qg2vR$H!8?9D(_`L!qT9DM}iue|p~T29l7e z04W43?&6XAxC7@(bxIG;gG!(BLTLeLTlHT~3&;Xgr~>zy_sQu4**~)OXY^%^w%1nZ5DiluQo?MPwZc0o+0k6)=)r zA6Hd-mBxHKjII|Nty|!;hSH`XUd|O#Z(@*D$;F7uWfq}Qch|YS<2a?h^&m5(@!f5p zf-^c44JrbVP|pu7=e-|)&t<*#*sJs3&EHwSXLcm()b-I|2?XucpGO+&zwOaE^^{5E zyyn?x}% zVV96qK<5C+bp(pj2R?pp;5a)h9xzK|@I@1OW(A zqd>w;6hhHR5K#iOioj4biAhLFNC8M8K!ZRCLqiE9LP1E402DHj0u%v5K#&47q74H| z5R5=HpK3&0AVrZgDrQQv24mwoWB-n#|Fhn3PqI(R@cF*tx(>I*$Wde{xV?FNMJux{ z6#M|6gcDTpLU`dnvn%!}pE48ULU+B#+5JYl;=3U^eC<(A5q6Js{KeV@Q^!63JtJY+ z?W<~TI|?#p6Z($_;VbMu8TdOKQ^}<~+?_c+N2t{l^Kz*w^Km44jD^_#heT*6#a}9H zKJR_zUHS#yB1cY8PVPzhX-gs|B4Jd(#D)XIP+)41#ViGiWeH^l1h5$=*!$uV@z;^Z zvR9B{+Wjq2|FvIOTs~L}LYEQ+>1hG&=(rZOEbb2V_ zSCpf3f!we3y-d;U{=oa`>)B~)6kd@_B^2!E-i$z=4@2xaJLNqBB9A_yT!MO3N~6&V z+^=s$JQX|0>&W!Av@{cPy&qba+&|N!)PBd~&xpgINQn!@+_m;S}ZLN|`Ehc|NDw3QlQ#As&w-`LArzOY}FtH}cPiTcQ0{Y` ziUss?Tz;uNdb zIo0X4N4om|$bM%BWSz|YwnVe!4oN{Y=FB?jVF+^YtV#L8F0BT|8T67<86F9{-=T+s z2`bwNcVwi!>Ej;KY~IEoJV3w}&wcN^~5mDDsQa}9my^+lzhod1cSW0a7YqjE|x>mv-V|6Y*eB=aTLg?w& z3y_?B9>7tuk^99L?i7!7NGGeL zgx$Vg1y?U?ETk533Fc@3^chqQ9hgZS-JCT!*BZ2`KIr;%$#nyh0hT-d9$9>fleY?| zjFgj{BE76x6kt1W7*U{A@j6=jUNTtEK;X2%E<9!!VYmkpU;vsf z@R>AvGJ|6UIsTX86o&~v2A+jH^UgHA3VR^~>gpBb1okTH@QJzMfIERFiu_~fYL@jm z3tpl|X5(GyeU~z4Tglc7@_1Ewp6fdw>+^DaDem^G^;lO=(D8~tj9wv2flJpZq= z%nLe^WxGEIn!mk+#;m-A{3Ydz?fCmXN2xz1c#!9(f;r01I=`2d)NWTaVsA1h!cMKG z-*DAk5qy8=Zinm*>%K_YeV)f1mrhTK_y@$3k<$}*s!pmz;7G_0N)c>*ap^_Kxd=EY zY$GHxR`q`V$8aX_g4^n5nBGw$h)ArS959ODInKNfC0&Hf$yWYjHG>T=HuCKU)fy5+ z@F4zcUL}b2D@*(|r5^i$$ShF`OEP;y9g8P`f7$RtaKxL>=nxbPQ0C$$`QfPXdI@4W z@JRtYfH@csrckbJYL)>n(;%JQ^n*Ry;EQpN-wT2Ny$jH<|tvaCiGV8vVsRn{!vQWH8c7xaUaq;?MYT_VLaEk1{}%;_ z|3aZJwvtPixAXo5b|XWZG|MwGYKmwkm>EPjc2oEsGwfq^cNLaa0N$8$Rbhl?kCpnL z@%CPpQQ$B6fAh1>c1DI$s}Fp9dQ_jOJ4)*vPPt2luCI&6dPA)wrqz-+ez4V2)A+nf z({Q-?=k4k{XQ|(QLB^Nw#}Y~~0Ro?&1OgRdQf9WMk?XT3Ouf?b;(kc%fyu_Wt0~89 z&kT9T4{fOVNVnrTRGX=!uh;jWcD|jGhl%|`a`^6PgaVe7=^g<^L=;5TOF&T6RTV@O z#FGk8g;f(3NtvUD1SN{q;uh-9r)YMnY| zIof>PPD#sLrMr7Qc6I$R;~zd~c_!XILW`bvj86>{y%!30?>qMs@~5iSykY69pi#mg zf1CH3zVtd_=`R+XwhR<)f{%~e938WepZLEsuZ5f4V}lR$!do`hY+Ict$u8ThFohhv zhi9bq3)JcWB!wYOkC$p_9m@iPn8btQ(%{Rfn-|Y{}snd$9 z=%ZI4c7w07xO%8@hfP^Tm%kw%&t+zJ>v}@ssNovyt{JCE$g)*( z(pf<;V!<$JMP*W37b-zCa4Vx#Q-TR_H>i{M_sS3+k_8k{Qxif#63r2-5REcW& zsn5c1j9AD1dew$_#dSV_6;I-V4M%E9CtrlU{d3|$ZsOZ4D-earrCn26sa1&t*yX8l zN^QbedZXu(!+lqX_K6Fj&1PdV%Q_rlQgtb{6QSw(`AcsJDa21n2q@#educmO~amJ)(C z$&)IA(t`3Sh0K9Ie&(&bk6N9XRW?q-ol+0C=vVP~?Zyi;p$p#A6y@<~hYNUeI?ets z)9xO9BYT=Bh+UX%B~N#Hq|_yLfLz^bbqUo?mGZ`^v<2Mu9pZZ5TU>d#ogB)EZ4L#| z0do=_|M8ChUcATBeRo%_nRTm1E9UvvJqqXj{v-`Sm?^XIvbMa}=f?Erg zPzof(ps9?alqeWM@Hth;$!G~OsTR^C>D57VKF{Q03*L81>>clVk3jAC-YM&Q0abOL z4+?ncN8;M#;DIzxVUZ(hhrFeUL3DcFE)xu+6@+DBDTWZcm0?^Aj%pQ76`b6P-w}K- zKDmNrigwAuT`S!3kxRJ^o&kz=!?#Zo`HqY#i1^{^iG^G4v0{OJB^*_7hpktlr!p&( z3avCajTPc03D;__8=;4y6(@02yor1!MN7+IUhR}t|64l8B7WPg>Su>ty5u{Tgr2X+ zx%RpR+MbP9<~ZY6-@GPP(%;6~bnEu36G3Ea(NG) zV!7oXv-wS7Gi*?HuP zvU8*pv&NkvvJn`dq-QP%RRfMD9Tsj0&ffPX%PI=iTC(te8d>6hM)Rc&ct`9WfFW-6W5BGC&A& z6eRc~pOyvlO``50C8bC!It;4_zlX#HL2^5#JfFAtS8z`k!QkL8KSnrjW71rm*m&2h zzU@DlZR;`YvsN*otub01Rp=@1cu7>=wxadc*&j{BgtmsjFGDlcf~mzhBJWc3$Voo&c><>Y$^o?5DJ%cP%MGc)a=S zSJ`xj=6mk6s*k*19s9uXEd?rg75mWq`OX>4hAaHpC$jG^*4LUwR!!OKIrlv=%FKsf z0^BRiDtp~d*tGtUFI0?tv-fr&W5(N!7IG1Aiu!yYUy3E^t)2`h!e|5$FxkKjtcpa6 zw3ft;i5dYZh!hM8mXsz0Vo)@hN@XAdU#JiwT`YaVDhMdjC*E17yUA}7NRb^)Oa`Yp zLL#wk0H+2-H8Irb;+f!)F5EbI3PM*2Xr*F13i?O(1$1B9q$U zk88rb?TW9Hb7b^?(vR*l@ZLullRWgdnp04v-9@&qNW&vuARi)*#szJ>{DZ_pyo60-HieFesKYitW?Ix{z77?!N$;ODB z8$~n-I<&j=U*OU;>8m}S$7a8g79!}Sqq_Ji{EtHB24o*zcYj*k52@`n$lH#0HV3|g z+Qt6$V(V7;4q+#yOcbtP{40MyVdWd|E+j3%PMEr%_#SmrywlKRc9KZ1;>MtMSc2x3S20#*q`cp?ly^1ketLBzXcW=Ab`IFQ)g8=V3ccbPjTY5~N^tqx+7ma#*%jXR(Mt@ITmNfXA5ZdP9K!r9b#^W_~?Y z6!3{zD*!2uz+P46j&P)_+ZMO;D<+l&49||rFew-T=z$i&m69&tRD0+IEqsLG0EO8g z`g;c$M*kEX7>!2{pMBqQ#6hp)pNtQcIv?~eW0U}0sS?Kh^m@Nr^dEJWWk1!DlEr`q zyK-CyeXe?aZMqDMqobB^xrV=Z+Ya&0C)Julr~+Ck-t$37q0Il7A6DAQZ(&H1>G9Xd z8PQRf}nGalM=gBht-^^QUC9to4* zp<38x1Zmg=2_a5rvF!n4a_2VQ;EXlb<W4iWro%*H(5T;7cBei#-D-UBVLnWE%XF=jbr8N1?gMsDYiIUd>NpKu*7}lYd47SuzQ5sHFDH_GhS|0l%ibEBoSFtWpf9xU* zNE76Nbn%oO1T!?5t|H!&C5$hppv@EZZF4AYipCkudMDvKsAToXH$$2DSjP-A zQgEx?Ww(a*nlV=a;16=a8rX22SVieUnR-O1ZCasv%Mu337^FDf%k}H{y^OX~TlhIdw^c}7GyY9;WJbX4h zGB{@Rw{{%#9Jft%)?4qG`r5x*mMI>k6m^B_#*zLH+fM&>3%6g}{kpF6)byn~dg~ni z*Bu^DQ4P`xx%zk@*dKfs50a`QMd)vSzOyfxvH!kbCvC3QXlGns;KPlFwPQh!II_X@(^F7^WOX)eRp@$L1~XZ`n(&7G8}iU z4;^ON-{HpbPFEVYQt5x($r5O6J**_GbjL|-r}4k`tT$0Q**tgfc$=8I%9=mt3!0N6 zs)~-v6>(*)F=D$CN+tCv_kSZ05iw3A6c53TSyPg_0z!Tjgby4=XY%2zhoncSQ& zh~{J^9+u#fFT~q^(nVfTAmb%Ku_7lzxD(LACgHL?%6hhe-mx$DkVNqYWH&;ul6mJc zMEMC0-YOb6UW;-`9hRqc5>tsyBVM55;%9NyXIz+wR5X<2eP zq%!NmRF7|*yx#giA&Hns8Ds;#oWkzVXV5q_kpbsOEf@F>l=R^XIm#tY)iIGo<}#o; z&Ds_GXcO){H#x!lq=XUgnMkir=$R0SAqD$|%5a_>7Bu=l`GWE;T)s)r#%~b0XJb;e z9PS&zf34ce7$-bQsKlU!l3-yv(Kn-K@ws{myQdF(r97|c-m`xN&YYoYDq6Zz;_+(a zV`S97^DTAU-D3E1)VA?I{pHE$@hhJrEUB2YGO)&zeVWRNw?wUANduY2q| zaNvkwv+cdo_4c~`f-L%%z1?sHkh^L88VdV(pOGTrkD+KWsWGYg&d1%~tK%GdIQ?oe z#WC1@_B4H4=C0wV3b_#DCHX< zVUz=}^I!+H5U#!_nv|GP6HWsbIOp6s;7}oe>s9##xe+%9N5N^1BJlx<5WnfptZOT+ zI&F0ig^i`vylY!cJ(_<5-o4t_^<6$V`16@ zl^nVuye=Q>dJ7wV#^UG^Igafa(R!fp@|vBI6DL3h!>55DrDYb$$7OIvoxcSIuH7O2 z#D{Gl+GWV$P&Uit75$QDhlwO3f8puB@6tkrS_y=BVWrY?VsM;@C*l*C4wd|{Bw%v) z8q9M#4ZL~A)A92X;ym@IK12@KYrap@f1R4Lbc_^y_rDFPOCTl`ixAGx+9G24rr*O@F9td6wYb^40V2WA6sks@P!cb*88M#`Cn%W7FK_3fI;e) z-~$y?B2bL`;5y&I&^yOr{#{PuSQ<8BFLJw9PoHWoSdHQ(LG!1i^hK{$JT;UOKE(Da z2lU+f?aY71{!EW9dp0-_I-m~9y&-m~uQfrz5L!In6Rhz7Ydk$GfP)1kADGE97-j^N zvT0*He~ou5iDAf*0~poNuDPQ)WeWM z%m^DWi_`JV?Theqk%;qEhn_$|m*71QBZR6gYV1OE*{|47=6$!Sn~cmwd0|NsC0|NsC0|NsC0|NsC0|NsC0|NsC0|NsC0 z|NsC0|NjGq?mc7!PWyfDdh`u~LGpFn9@r{&OaMIC0CeC0HINK|1KpOq4}d3jIq}Q1 z#;rhL8rXfiXHNj}!t9m4;Z(tGrqsLBa!;TXoCnFzE329+_3sy4&jl`D#A2lSYGB_H^#E(S_?*-)y_W^!tDZ-#efOdfn>p zzWZPlBrd&@l&84Pi_6ysLC6P0%K+XxtH=gG94&2u*W*x&WnmWEAO@w%*_e0V0S%CV)*E8WRARCKD4(nJ~}^p^1bv zn*uN?>7z;H8VyX)8VK1FOeUU^dSNuuHkeG9k5N56O)*b2m=j5-gdV2U$&(t0G|&YE zKtm+c)YT7D)Mz%K000000000001X31fB*)700000(0YIX0iX>4000tcA|fV&U`-Iz zdQVhok?8{?(guS@(f|NGPf%oOrhv!~P|=B|jRQc_Mu5-&4FCXW4F-mQ13=Kw000R+ zRH&0Fv}HC*V^Cz!GyrG@nhhENXaE2J000dJfB*m06jne00000000wIk|2Z> z{SrJT$WzqXjMN5?DY9xjQzq2NdXG`HG|=qGEc7sp>N*%_b-6Pa5Q|Y|WouYesUR$ss3H}GO2SqIfXWtv#YzGoB|&6_sR;@S3>r`< zB!o#BLol-%)kl~g1~5L8IgTOd_!#Z^erv9>j}sJ7cpt1xFZ z8)Dp71y;DW+lnBJBtW78Qpi?-RZ9R5b$#!}|L1e*xA#2xMq|`U$ZjEmEHNde3f4fD zBBKhIGTlwC1eRF83Sg2{}9L9?n5 z#sMUq8K6w}Ci`0%x+R*@qcItcVTjBbgpx@{)*?a!O501}wit^Jb0H7irl0|q{0L(9 zWhS z=CsqKx!o_i{o;Kd9+mzlqy0zz6KB)cSN+HMc6&SCx3b-6x^c;n!ifwai>y5shG%yR z{<=TtUKDKp<gAVDH`Q`TUL0~{PW{a4=JPd=$Zz0%Jn%sG z3X&`o8fguKWV<;;DKDJy&sDN@gutqd6DrlK3%Pon6{VeY zEOWUDB(IXboVC<}0JQF{GY1=lmK^PDxFSV+LfYY_s9;>NzV#S6SdtNbdw3)ZtgoMP z`tzwOqNBuHR*HR-Q^KKNUeW-TArNY@u@#L$MlmVH7jy!&0IaT9t}~zIE9g3k1(vo; z#E`BLaJ<+>3eRmiosywx0w}%M(6B}{0dZQa-g60|bDW=kt))#bF$e1^!`p|r1r+Ay z%REd!hAKkzz3%Sg<-PB@+pWcUPhZY_|92x4ePq4vexF+O($qD-Qb_=k8y#r!{D-6D zP$7woC1pULBIa2kSt|gj6&A273X||+5}`4YRuZ9DEDFJ0SU@r$7|BKw(>!`T;iAra z`J9X*Bmk_ER5@XazzkF&i8abJZfOm%O|h6y9>Ycawmr+~+PJq>!x@2@d)9K|Xkl zQW|{daDW^z05r%{ibaBf3ABnBgetJakWpcwtYaMG3vtV<0EHJg%ok5bMYifOs_7cC zXhhK%%L>M}(~FU-a$IgQZY|t4m5U&XicSQm>XcN5*`tj)O~k_u87S()qN<26kx3v@ z60jRYv4K3Cg|ImT3`E$BRi!eLD3l112$H}e9gJ8-fTCq3f?H}3R@?1L?k7P3ktHp$ zmf2=Z-J?m2l8Z=XlS@e2BQD1-OoCanS(#QzDp4jYu&xobl`S!hYLwc^sVv!PN?J-w zNh(WAOId8IWVM-U#x0q)m{|tx+BTxwP--hOX0Xw5SqqBbagkV|D<}nLSjyJv-Bf5K zvnHfPBx|ci+PQN_Im%+xk#WpSTIO6@#d|$+0)vY{*TBQ~_d&3}h7-M!3`zTawu-Nm)usDQZf| zRd;KW+EXUmNRYuVGnv64ND^>xB;4Rs1+AUACx+9GN7CsLDj^WmM=ePP>tS;+U{tRvzt= zQrOBWgD%Q87-5WICNQz=*mLcL;}~NJIT%_e^Su^(z8pA;BH-eTU@#ali6p>+K$TPo>uavB331~q zpI^$ym#m~J!mwd#F^LFZL?-Kyy-zVb)L`V=o zqymS(5fO@v823(Hlv%3x<}n5hX*@QqSZ)}_3}Rur+%;|nCMj&t)Q-zs4VQw^aAK=g zFywEeQSU}DC-WK~$ZVmo_yZWBj7(ZeG;*GHmCWFfe)uF4;qhX3zvG7=6ShZ++GZ+>uUK*^HQtMij zlD0}qxvEl(WBF*tKEyGL)FbSP^yu_R$8_{>IE@~u8Z@ekpGolk@Y5d^XX|<4|JHkO zZ;JuHjVIK2s68aOzkLRDN0uX}K}`dnM9~3v!zeX(XLfdh45;xR@(HZ;(kDj z5B0x;3hdM%f=EkNt7Di6u>$7(kngqo&(vQnmEzD}2b=#w?7Y0bV`HR7#pktldSN`5 zO|tht(4Ws^(CxwxO=ZIqq2qIWXrJ=^<&kPDj!XIaC@~_#H~5fxAb%faLBZJLCtlET z54Qoq1P`;9Hy0A={zUgZsc_(?}XA67r4{!$Xz&C$KL9I|`GX}WIz`(24U#>=Fv)KOWLG_3; zv4`zRHm;uN5P7jT;r65maHH7u9c!(nQ05^=_3IpR1H-G`ZH3NC17`&dzWg!VW#1mK`fhKT}Ro_`_8QqZIA)KKu1ak zp8h}^^H4uGNQkqd^1>MM|KMriN9;$oPh_8BpBX;@pAkPPJ`#LX{WShEdpQ0z>oC1; zeR6)-c5$sGipd4o5Y8Fz?#? zU8&AxaRq773H4$2PD2L-ZQXB12cm(Wqwb05^B`z6oDp{p4U2gQTlWF|v&(kFIPV}x z>74rv@=@%_XVIPlJQz_;>U9_D+k2QCYtNu>c7SbezN?fJ)j$h z)u3;JfxfK+cyJvGF~6X1?jUczK?{!QTsZN_SAjehX2|I`veW{5I4%8Z_*K% zN)25Qc>+9<8h|bj@t|*fBY1;wg4F};4uZ=PhVfllo7*%!?kKEl3eFNu`ASAXoB%f| zLS&(=&1-p!{}h!>ClsR7WB_ic4*dyI^ss7o>2nL$z9P&ZzIykZ9NU^j|4wb7!1>Fb34v4!a`rt9pQE@>`>?9y;b z1li)#643k;i|+W88T1#V9q<+}Gy{308KfDc7hoi{yCN;KGF{q(48RnCcHZEf$HiRp zTzDR#HUKz~+2bxcBp9yelmfZqz;BcRzBvaV1RVe_;6d6X-Jxg&9P}V5Ee*R3yR$*+ zpu~a7T%lqGzo3r*P}XpW*o58ER9L~uCRAVRlE#!c)B9}s!)M1|gPPn!_5PjW>GGn= z^)R;wPXvot!E8T_e%S2-RP(0_+fZs#|dIXzP zh1FR!JOM^d+zKE*^&(YxY^=yvcqv8s-z_@|YH#u0p1cojW?7bIemUuX&dy_sP!}gM z<}DVbP!PP)34oG8gxGVm;OW(t)))9f5QYK}Q~(epl@MT(67{=}TM=g%(}a%5ING(i z>H$u(EI(O}w-jtQ{Z2+>tf@ySfdItGAjyFh8CU|c#YBUox>WxbJWm+x;jQNe?*y^Rg-Hu!~qIuT%KJrEl1B*_N2)RxJ^5x$0Uwx5@VIP8})plQriQL` zh1WDFeAd_vLO+f~KoA5$&&n@E^S*tYu}%YI<)pqw5{rC*6H!H!G_vT(CkufimF^zl zm56N;2``|4;KME>zrz7nzj{L zF&$Mc2wX#g;b*P5Jv_bG&`acIifgFA)z?q3jZAg{<$%t<=v77V6-n+&m>u)qGI{D- zqzzFmc&?sV;d^xysaU3)Ms1a}*{zwfyW3YQjdC%qce>_m&2q{%+@-RW+RZlI?zowv zvc=xxQwy{)%yM_IyvYosyWpzs@EmZtGF|-{iI|;WW+N~>s;VucZToJ`Y*vkL2WrK( zF%MVI*?eSx9qstwC@+phkzv4hB!y(N6tk}6$0nVZUz@E9v*X?ix=zj^6!v>hZQi}> zRaEo$$Q||pwAN$Pn7k@cR)Ksr1)-ekdRObUDnpsb8C%8+B8wM zjja@DqBcz!DJZd`Ac89;Kmbvq$%5J5_$NnmGrGrKtreJ43oOEBN^P1e7kz;%Yrer+ z=FM5Q4y}xeqWT%;Uo3~3Z5Q6L?wI7p8J1PcB~dU`6sv3u zXpB{ARK`(JRYuz5amGcE#B!31lCnjpBOw+Gb1-1FDJuytMEFSpK%Nh9kcXGXc+wF- z76*ID**fi#MDDhEu49<60~nwm0j$JJb&6cFNi!}9?tN`zuUEGoU0vf12m;icHBe&} z1r>tCAzJKLb60_0623C{`^>AitzA~N;)zR~;K_?KV=0o8X_{q}mSaMhBvPhVIdd~{ z$!1d;S(MuC^5&N4=G@fNH8xU}G^R|YbDNqPdI4xll+*y)a2lYh84tq^AZX2of%mfrm0cup|S}dzdLIR4Ob1 zL1`r07A>oc121^D{G#D}U|bl0K#@bQo>ixHyV!-@iowCA+eLkp2s6Uz)0lgF ztlhgph^rJ)Ue?O=NtkiQ^LtSzr3%4SL_zc3uG6mR%Hrd_(8i69IU3~QnSsXJ9W}b3 z?)WE^JUcdqnI&W++1lIQZ(et)tL$9u>@$x^nb-l?gplW{>+dFWlASX+*P4JA6Rqb` z5k&<-rrsAe{LTx)_zq#+{6O8P4?Q;uofZ#i_0;H?BSSE;sGStd(-;w{w;{`4kK@Oa zv{Zo`k^#OBQ%I z&Td343~bCNDa5MdNnCq|j@axygd*;s1}F^y%Qu|h%;N&-+ZQUZ+3&9{BuW>X5L zPSCRAH#97ltG01Wkg-AUk1-(e);7JBav_^ddvUgvq~h*%Z4ARe^QRdX9kA-!uQ1{X zKtTYZ04ZuV-X*HzShkBA)NNf><85)Wxy)SWDJ+FptZFTbC5od(tQvzx+A7Xf3Zn8d zMFuh?Ns2})q8OGDD6FYaEAbx-K~N{^!#&;ha%c{oMO5(dA}^gxBdWzO*2jmGslAm$ z&y_?$t6H>cZE7o9V$w+kkR@RNtb)`nsMHo((G0|h^ci~2g)6_m3Vc@QIIy3MWcP!W zr9!X3PdIi}Yms7ZWQy=JgdYVD>ZHU_g2NLsz*vYZizHd$OR7~{YbBJXoH2Ei9Mal^ z8saF-l#MVWOEj55nN~?Cme~r$g2Y7$0x1BfR?{~dR#2mA*5ffOj&jzsGSs!L2ot8r zoyW0S;LaRL&hx&FKKo>Z{FuV|Zl8&&H}nRCC0T<(gfduuh80qQ-dr?H`#%>=N1iaV zCBqo9RIH4Mf2+jqBUwp)$8GmBCbQ&a3O7aqeShqY2qM~7l&(J=xk){Jgk1`-ozGwD zo<`&hjmSqI&Y6u-tdS7mI5p%`IgWny6|Z8WsA zX|*<%)Yg*ISYR?_rUok@$zowvT5Q^yw52x9O{KGGri~`jYEssu)|dW$C;ao={>tU9 zr4d5-Wlw{hxfw3GQwij+D@wIJY%B~Rm2M&P)S4`{A>?@~R4;vmX(+D5yK?QzbX~b~ zl+f+foRVV{km`S35kNs?A_1@@fuRiA1Y(+E4Hzmr>qA*s zz9Mm%qp7|(I?_(X^Vzp_59bW7qCaRe~SSrZh7djAy?4MXe&A-1QnaSOe>x zZELHewAJxemX#D{|m)=L*w5YkGKUWl;tMFu9XpJX$_UR(X8YiS9*(|c>U>DLd zh(gjLSV+hCaBkABEt|Z)@h@=p!~FE%n^kgT(LeaRG|-r)QQC*ZdkoBtDzzIX_?P)! zncJpn+?&(XaHV*@vwa;F|6csuevd421AEGn0 z$uG^1nJ4GRr`)FLMoIdPhd(Tvl3v*{_Wv+9?oE`xv!U!SK5pt}@Lz>bk)*~6f5T~~ z8Hq0w>l{x(G#6Lp``I@@ZhKRSDSe60EGt*S)bgx(<=L2g9G ze$6s}8VabOrwi&U;0Fh&W{tPPtO}qacp)Fi4=f4@D*(wDo^M%ch$ZG`nn$jk1uj|> z-i$ea2!flmUK9BLIv*}VeDC7EFtBNS|2c6|>se)VW0YBP%FN7W6}o6HDQRhGmf}-P z!M2UMw8cfrYTP*Y@?6;OD44g4FwEjj?A+DIVXJKf{NO@n7^P6U&A5xu2nW%VGkdF< zcpV|EO9}xoGS1B*RU2irt+{gsEwZ+n!r^Rc+Uudrk|FrgNJ-(I07PQ3JRK`*w`sPx zWW*7*+NQcNQblwq2qOtj)unDiswl%y(-cK!5*8K|A*Lp4FjEP<8uVqF@!!8F=u&Tg$9FsC}DVs(N{8cBu7#3ri>TU2ILYeHC9)JoB5k!DLU zvCLLUR*MU0SyqXROfbrZg-n){6-*4QRb`UFs#?%13nhhMN^LgEn@v+`W}0bc(^f_% z1(j0_%3+kjmMvD+`prYzyS15UV$`!(-l_`d;_+`rMP@2okVL!H9pkNR zR+ldu(Z@T(o9*CvemW8z_yX3GRo+*1I*^Us_};pAaoes$$cGM&UUg;SIbnIxLzicn zGV-AFy1fxy7i1AlDg{$DP?(u^b-sY*MLN_Jfkxt@?3O31paeujPY?hRI|5$XW^n)n zKoJA9X&TbNjpu#~WmZU;V+7Gx6*&ViW2t9&Wf++yn;}}V)v3(0skzC>IJFko(!ypG zz6F63YRiz(51EZjTFxxfRi)-odTLf?wQ%bZQ7@HuSocquv0;`Xv7xIkElaZW1b46z z5NrYj@HYzkVc1nRq1SdJ>^65)9izFbm9OD<9bUQ8s^Faq1d4Yl-&DJBJC5h1gWM~f zwdzs5KITbinue*S243k&p(f0*b5$U!moXw$Y39rb24b$>*tOcN%got5V<260aU)C)6uCi;J;b!au7=kXMOdmb8`vw`sVDLq?2y?icJ z?!9f9Ido~nn>)^|xmvcC9mI7}Y^3)oqH}*|rcOxs-T%0@PO@Z}vYgS1cC{Kw&{cge z&?nN?)aD-@p*o58{b@bk)ZU-lXq?Qa2;PH9KGlHMvJSyllQ)67G>w$%45wt^n_5LS z$whS=lRy#i>XA&{YMawo-D;YT!1*7f(QKZr&=3byEoc(SmC+1YjC2IJ+^$i&~tm?#xXnl+_Gp?RsYq9B>uKOe>7jf^z2fy&0R{ zZP~q3H*}j+lv_u8xzs)}kdXI+6>A$ss`4Gpw{){M^p_hJivf`p1W6wK4!By>ivfb9 zwXmZr1AXqtw$_gBIo+x{({33S)9wkay2MJxl)d*0nVRC~WSEzzdy9M1MDY{c*MAV?A&!?cA;!cO;qI-VK^vK0GZ!n$HxDx{X! zv*FsTS@KQU2}rjAwAE~cMM=piJtQg(w|s_ECw8~PWbNdZOkP>ttpkF92tJ@v2!~M= zuvOGqN+#*57EU`fwcDi47Q&H@S(!-D41*F=Ir7oz$6hX;UhgO(XS!c5JqDgfD$a17i;g`%`3?Q^Al<(%0{<+ScTxB2O&)3CX z2p(FV^TMV_&qm=~smL-uJ%rR9ZbY5+=8OFm=_SDT%oOyuC0e}`qp#t3 zL0$azm$&Zv?kahG7< zIB9DOXj|GyajSu1f<1WUog`ttmSkd_7DG(I3)2Ipxuk~>&1ovKlqi)1tt_Z$WDNuX z)D;G9l5>gYl^p!rP0SnMaJC{QGy17 zi9~{hN(w5Y79d+($}BO3NTgethBCBfG(-_bBLqPchiXHz;e9 zq&Lp3pdwwMEUQ@ry)b^*nHCBR1w{uAYy<#4J&JM!AOR^2+~uhl*@%JA<0Y~IZ5cg6 zNOZR2$h>ud!Y2njX9Z^A)9*gaKF}WW339~0_0Cn%Qt^~7!^XugGV9WVSXVNtwkm1U z_^-yh;^ik(c3F>9?L6<4DQ&XYjAn;7gOtxlpGJB%8_Mu+Htm|qY{z*qA;F8cF&x(S zoAKn?y=~0aHK8!e(|X>dH|p_|)mkm7KItzvaJCNX-@=Z2zN5?v$2 z36Y8_tQ6${(%x&Ztb;}=)m#kRHztiClR#TSstTk~QY=O!;d!>w+ifkSt!lNl)m28- zwQW`nwT*G3jA)3#5d>or1<#PD@DPgxZ8`3PIGaqj!4=nq^K2=Hq?=767ea-0&oxy zgg~RHp#bd*06Qe$n&MM9<-Lxr(XtKifg!ri?U~$6QUqq_3t6?ldT7YU2(yvk&Tg^eDp0z5< zxT7YaR#CZ3sts*QYidl)B*?ZILanGwP0CyqS{w49Xd5DEmc%lq=O$@TTaCgRM&TJp zuWo3SuttLTu~Z^Ek#Mpaw; ziXeoZd0`EKNE6Wr9N7WbPPVq|WivAkI@g;FRGVsSCqNG@4-9k5dq9L5^>x0^7?w?~ zUU#My-BmU$5JitZD4WG3n$s{{71nDUaKkC5CE%S!B6t~2?t7@byYp?Iyj0EY_4jo$ z7Yw5RW~?E&Ue$h6P}O9yn0DCG94i_ID@w{~)Z?zIt{7Z-^wo*A90p0j&#`k5#u2$` zV7JXU?p11=lXY2IaNNU%%WO9r=2h1~x2%A# znq$5Ors>I;VRbnURNS^3rbe6h*7DkJt?L%&FE_;o`nL`1PF5js4VD%|4DngrFz(zq zgA6tWfspKQ+ib|#=^O2~$%A7fS;?}xPOB`*ff_Wdwv@EmTS{wJc|YIr&he?)r%)xo zT6pMKnlU%xm_vYvZ0+Q>l^C%iv)2z?48uy~fEWSYAO;|Kp(O7~CcSfSEf>_c8^)*5%yCv$b7boi-9f=46tE>&wOM>8;9Q z@XHA3&B=2rggRy+4ISNC~1_I%^PT^*>;x`=I&D7XzYilf$ zPzp!@f{YLW=jDtv26_zB>U!CTGG(2EaWXQ(SzQ>-HnkRXB3`EjF^AXJ%EC4(xgjd> ziikjKI{De$BeR?C=v{{RSA`ijC zw!NX$*ksrp4&^%7Ea+#RO^!pi&m(JhbsEUl*P*o4uDQP?%en!rO&StTy9ERw&FtRc z0O{)-aw@2bj75;=W(0+=d!}fC4PK7~hspR|Aghw1o!@uQ{TgL*cU^8Sfu?9_rfH?2 zrJ8ollTEWLGesDtO?3zWG7N^pd-DyX z0IGPb?U07XC9a{PIs)Xi9i@7OsCcRsvg@Eon;%uUKmvDQr&dyPUx&y`ba^rwAYrx z8jC5-n~G^@rpzOwAjn2Tm_xAe_#15%Xx7_UC9>OXsca$zkjW&3I{2s%4^Si!B=tQL zC)|j9@D%bSd-Y`!SI{1VGgt+Lgz%8@5(i|2%joC9XGB+8j$qPr!o z@&{5LIpgu2>T(jC2T^Lbt?iI#mqj4cuw2xWpw~d40!-_Hy6N#~0&Yk^HZWn=r3-Af z!rKXB4o<|v8ySIJtCrl0DAcsmEU}Dbj9{5fBcCaXV%?Q?N@}K#iv`f=QqtDLN?6kz z-6YX!#_M!i=DQtuNMQwL(@i$J6(lFWJivCI%!ir=`yi)zODG`A3o6D0JYY`vMFC0V zzzyEi;ZYn6qZV#L(1;-sI{Ct??aVYzLS+MN;r4BIj1pl?bY6Nx6jfarzBtpng}IX) zsb)7VEmUe{!ruft*vJs*gd{B4zZHfQ>diIaI~z-m4!e#~VOCmASWR_g%*-a!X{MV^ zrkZUwneyA+HtT*ERO6*M6k)}aUe8N#U%$F?o^leD?(f)60FrEkq&vwD|AVk?rCOyH zwo;|Ggt1k!Pa*%U5Fx}6Surn$0pLarHQ3~Cq&~QAggy8aYud1692;aAVM+*FWPo2> zhk&}ih010=+gi;~xx|G5kYO!m`;VB}uW#f${h;mvm?_Zn1)0S;s_4uG*Ibv^Hm{)h!N3 zd%Z@j`OS?)>8H(eh;;{U>gCt{dfC@{bpLGq5$@yAj&B@%NS4|bRX~9Bfcnejcj~5Q zhNWc^08{~j1w;;=HQeauS_mW>3^b8Oj#;tAon+~(>(NiP_GwI`N|u#IjntA^CQ|E; zGlh1!IA?FRDYEYDRB@V(Ir;RE)Q4FPfef8kOvM%=Du^&M4n5MGlbdFuF~I24xOu8{ zf;*R(bD^wVrHEHAzE_o{_j1>At@5XLcB+kPNs+Bht(w|Vl`~s178WZ8Mli`NVqpwc zSW3jJ5tOS1gB5`?ELlv&6@si8nkr6B$jeSsU;A$HnMW?}Rpy#Zv6Y(- zFs@~&sBv*2pu3BUr*lNL+OVZ9YVk_bEX=`~tc5ONn&qgpJQBf`y5gKdqvkr7fDUjKJ^Hoqn#S0^zK zmfB4<9>>V+XzyrGog}hJgp9MjyDl>_-ZqHV2KQRNa&l$z#Bkg0vt2VyX?b<|)5|(( zcP{?VsO6+nRynqZ^^@J<=#1FK7UK!$!V^dX{LMKX?Hck8-4h_+}-Ut zoz6E?<8j}rI{7!`*=*}x_W&2!aJKNnvb-y14=a!}Vee`YwNsGOqb=U^zJfK~wBNIL+-bwL$8I+HwT$js>Cqg~qa2>vw*56v9tTrrYc+2MG=AS6Z9FWy ze*Q!}J=@-0-Oo%%edo*ixMzdEKUYZQuM3XR&a26rbTmaX?WOHP`g*j^{A-=v<@~n^ z-T8N|yEynhA|UZm6U0;i0#OHlg=oFoyDr{cPH@Z3ad1}k#9lIdZ-bu0BXv3$oT$Y3 zIZbLGMxLZ=9wdr4*&>X6Rt;(K7>`AYxTm7^sf|&bV1~qI*pl-aNfr1nO4}*Q=Qw)( z%@H3B<5frb-L28(`JeYM!{t2p_x!Bz^M~NtLjTVwK=U`Ne94a+@!VJHFOijhi^Tii ze(}CC?WgM_{b)DTLe{qFEc=0D^Y-#amt~RF-7XgN>^S<(wJTu}sCU!XtxIbe)2!+A z+&Qi^^nA>iE%hqt70wg(8XPW`m0B7*THDNsi__J#thx3+#5lVSB8XtCJou?-$#B2g zxZS0l$ME)1kvsbxzU!%blOm<9&;!!}eO&@9V^6ZAzgxRa=a_Yy7RH3Wmy- z3%xK=ymaQ8?Le=*PC@zn=_<`Ht7ZA(A{}I~qvXrS-tg>-Fm4)-98c9O9I$iXM-yi( zh9mNK|KeFo+b~u5xbmNJP9qzVnyk=8*5e$uEBX3VbQ9;ouQj@{nxL^)ES!I38dzF* zOXb>sFMiV1qeg6uV&hyCGI<#cJ`05`>()alPIR-fmn!Torm;?Wti^TJD#`+aYtw;^p!UN~w zr?|tWdS9{j%zn}*u7Vi@YOo-%pAiB= zg-_ps^n`@8Z}|~sRhY9f~3pz?@3p4GpT+h^dY0w4>MzM?*gLI9Bv4c`l?$RKiNpA~52 z+kY;%9OdS>VVL2|1DC}E$N+!|o{{6w1V!=H8)*~8-*Oif?m5?& zvU%)2j}Mjek)zdQrN0?xCT$wp#h)LQEfzc;Ok)Q4xy~4%DT$zJ^_d)4OjnKr1mY1In+0LRFEwuqi5*)G~%1=UdPk{9J zd$rXZr?HX*qK~m?v7M~?2g1!hD=d(Jpg}ibSRcbkUgV^M!(zj&^5G!@i3tHBzBH_2 zf-wjJ`D}m{fp4nA0wU2%QJU-Xn$Uz;EJX-PH-&lEM+WRR?v>GMp-Zf)iBMl7hz~Sf zBXE6PV(UsPOt_g@GaDEmUbz@|JSjZmJ2`oST^$!rhG*A{bSTtzb zQnoRS7%#+MbqH!Q3?vVZlWwD|;=~%-yXLjV+ffxLtP-+Q9@&vvR#3pirdXjdWulr} zY@2FoHk3;+gEFE_qcXx~P-Qa=#KN-xvlU5ZQaU_Uq-G4tlPrl?V*@gx&Obvuo_|l8 zpR2n>;PTIBK-E1I-Jv|~?Ci>WrQAQqQR%*_Im!olxANSN67Q$sOQhr94y8WN@X|I-F zTp{zn1-g}Y9e0+&N-QX+-$FK`UP`1q#8B3hJ2au$N*d5Snv=H_G>|t`hT>6sFknOp zFI>o{Y@GrqajS${`Gr#LiQC%<<(Z`z2-Qn(9ofB>_sLc@i$*pmGKi$mh?0!5lBr1z z5fdb-jV`9OtIPJSww$#Snn#n7iDFomC6O{FQp#AEn+Y9r(n6O}cO}%?5#aPa1!sGD znR>}^IAmeB+57aBjbNlN^ADX_1~tMdO6M4_ZwL4Tf|UnKQ1YkXe?M?n1qr; znLSWGH`zq@zV6h@*G8hQ){DiCsVjiy333I|7Z0lNH-5V%K$pgmAdja4A0a5exEiz| zHIYIC)v}(i?yBvJ=cTYd^2J&G6op!~V=yPg@g0_Ksz;)zIxd*Xil>r(vvN{BnulsEzKLXShf0r*e9a!dJ(FRr2Zr1n6pY!E7J8^2^8?xOONmpi^U}u zaXjP0M^6ZLVns5$2V%>x(TmMm<*t)F&R~i4eL}_;oG@Z~FCm0X>nFocNI)jHeRncG zN3PJ7^u9b|XHq`gmVIo8%@l)aBd8wOF-%jiD-^UA3kihEWjm5laHS2?*U)z&{yL=E zlsYBB{kPuhSKX(6N-rErEDxg^PY01GdcaRxIz%;Ep1xZnB8y_~&OTprYb0%0B9vRd z7u3T1JM>cs+9So<=e)kNu=QjoAP~Atau2p_BryOqAVvTJ0e~JNhHy$b8aF35*@;$EFP>TZf0hsH5JU+4b*noT82_p+*Nue`l7D&%_F zgR?vlziK(vE6=J|ggq2^uB3sklYFP2;+`M+zv%qEfnSRE>5IlZduTzwmH2ePd4c8g zoSYNK;VZYRg5xMFioGX=HWa+iom^wG?+)DLAN>CP$f%puL#bYO#;)3Y8=(+>Mo~xA zeQuQUeem-F{U=>dhwneJ#`99Da8)aYz6^>wqD&HCtf<0P60le-RKi&-mrw}V67TUG z*>o3K)K$+)x2ouuhwS$B&+~JMv_kl@15iO=2jZ11W?3VZNW&o9*OlT0MJmFQlL8+L z3TJ3$r<_7Q3E)f#Bh)$Z9>{MBp)S{gReOL=%dG6x>Nm>a6Cb66sP;8|HrM{Kr@fQN z4|<<^_%0)utC8+roN35^b-bGAru>rQEBAM}X~Ms6`Ad?X=)~ep#)`AT81@-`LTdF} z;x;d-{Pq{9%vmYpDksASbQNHO5>w;~ymFtg56dF{VJ$=H6x61upVdhG5}S&DnNr?S zfpHaYQq@MPtqHuBO(UXzL#g(pqWi%005)9CZO+PpO5oHy6_LcMN}02u2IWyek`IKx%-bNtMsGK^%*vBK64 zr5)EsbMC5^!dyo46_qOE1b3JD4dQ${J`w9AQH@o|RbEBNGAMfKJ0T(JNbkvOWwouT zRcN+VY@t-ER+P22tv&pK^il^|AR5%3KYaryODc9lcKJ@sT7K*O?aip}ch;`SagaJo zs}8Ku%q%#mzd^won-%Ab!X=@S!&s%YO61XsLky&fV=y?^O3FK;=0+*JLz9|=DyIq@ zijip-c7I#+{+qtGJ;j%oqpDs<{n-?K)QUc1wl@pApEg5M99NR13|k$MrL)UYvX#O; z)98uI&mN^ezTU3y@+VflU-D5H%}IOt+hxohK_CzLqgX_jDRnUhSk!KFc(W>Y!*+}fl%Z(7L@YB%x> zVdPCJQ+Y{>PbtXmBk|rzZmGX=okOraA=-gNYEC4rZq6d-q84M?y{1bN1?R?!@pZDDE9jta8sLI=&-A9Y*}y_qNpB-9=l$ zGV_L}u|q@68*Fdfa~j1BDuYv!&Mg|tn(<^Ri((@dDKs(&y0dUZY-py}D%Wx2ZPV4( z+VPL@=-quYLQLq>a7-sQ-F<4>yhXb`-E>Op?ckcUQV2z*(T+8u)v3-hrFj7l$vpy> zQ*3jj}nq&!HUCKB0F?s-C2<6GVZ;V(F3O&ikxSPd+~kOI z3%&XW!jIx6eFn*Yau#6^PYXd4N-#>&6#@ZZ5>JPd<)4IMT7)YktRSK=g*XNa^pXHI(@(-b&Vj7pF_q$E2?CxK!m6$5Q8` z(<#VqC4C6IdOUlnM2>5gDRL8laSajEU25HJQ)u3idS$Y9%4JfIr;$ej8xqWAD<(~9 z@%6Ubc%F9}BSr#^6BM!{p(Hv$JKB?vb=^+!kw~Z_F%npVBPviXwOvbHuHx!dl}%8w z1&A#Y)FXzdl;}!t66t76!!$GYIFjMcvUA3mQ+PD2*On`D5l2hsal?( z^CgE-Eypr|@SNr{&P^m%`LyRZ3#g{PQeS-bAL#YR@NhaWEIYq(3%rH)P_h?pjnK3a z#@A82?Md({(|5RqB&vgu-E111Da|%E+ipP=L}G-ZE~d3r;k7EZ)yty|7(|J8+~Ol_ zO$wjIxeqM7BHkWR#iBYfOO`br{#D6S+11Fr-usGht9KeM;9HIW}A%24Jx3^IggcipWhepjH7ysfp2XmY8-xrlP& zRK-jxXqMojoJlCx{xwZiJ-~(tdnjZ(YKcx1dfui|YE0P^D``thWm`3BDX{6ML!d~d z)V~D2t3MwM%*EK^TVI8{yT;46TCQ`G6q$x-r9>Mth$2d4D3W4Wu}M&@6p(;hC`4gx zAqYj7!Z5PR%q3d2YMQdp9eBwk5h)fn3n7e~n{LkC7Tax+Yyl}E12SSpU;{CXiG;C+ zV;Pe(B~IeJ%xx(Y?CzsV-XY~j2z2Xp8@DYC$_=$9S5hIhNO^LTcI)0n4X8KTnW7M+ zgHUW^VAK(5F-@zdZpCXn(JEx6)3-Id+>QyhDVdfTWnoGyZVT;_hSheYYi^X?Q`3^L zG~+5)+4NQ+RuoZT%H0c|t>RkoGU6&%9z@zE=&orSA)y${BMGH#QlnV5)}-4+syW1p zd$+4ppDp78cBgsz-IKM^=V+&%i_pQ>3hTC|)v1SBC})Y>Fvc?s%rM4dCT24krA-u0 zgkGidqHLEmNT-;Q+65)TBvV65_Fg!hE7BCzakWkZjZ%(-Zqivp+x(|pja#O))w*t^ zlQT5M44WE9Ye!*MixCrexhs$^0WR99TxVLRDZZ~ZsTAiL8;>JVM(UHEXPgJMWPRHO z`i!LZF+-17bq*6XRbWZEO?y8gQKO*oiAsu_x3>pCKJ4S4ikyYR?A1Tn5 zvuZjfk#S)(CPm1ukIMT;+Gt)c1j<3Wrin77!UzjoP6o#g=8Za`EK0!%EC>^)HwJ{*fwve% zASguyWDpB#$kS9Yz)@Sa+TMh3sTHla=E9U((`;igWw`>>sjBP}${O5z&Dx0T7Urz1 z!p2r&%o&QXj3Wqo8ImaP#@#91y4>$O)>N${bGs9vLDOn4t~k(dt1~b$k$|hrg%sRP zVz|4hmRgksdqWMRaXQM>D5f-1j)?FlMvWHTt@S6Hsr1y8cSk#-zx;gGqnuQeZLb>?ZWtL_cS(X`$b-T{+czrMNX>**XF`@1l zIt)4oma>ijM=2LDT<;3lTnSZeE9=iNZ#as$U|BOPk(j1s7|Nqjw%E2R)WX!QRW7wP zwzqkW$hR`)b((``IbIyHtGDD0c(TyV!?td9b3L?ZTpt`13~sa2HRjhG$pB^W0k4%%MgyRPU%U71fxO zJ$*mvPHyYi)ScYBzq&H)9)aYSMx^d48g#_b+7c=3o@>a{`pMC{9M@RADqdkK_>2K+ zo(t*YEF;J={cv}{rjU|R{Tfd`7ZvXGsUB(XlO&e{OyER*b>YM zVb!9^czTkH*(Uyfr%6YjuSQeTRMLlpG?i#`9&4fUURTBJj@)#n?~(g1SiG%H5y0{v zQUBh0FKNGB)$QZXLkc3Sh~yLCMPCJd1a<=uQb8W2Dt#WQ{rL(#xkwEpQjg@LEP04hRCSP_43`ReNp8WC#iwhd69S zOEpQF>$f%Cd9)a!B!D(6NKLrK)?y+eC{@*J#+OqGD~lTxAp#ugHyRdw{hPDsDDeT- zJxzPti+}(`L;2mNn33E802_93-tWB|A^_rrf*NrUD(ZaH(#HfH<}yM)q7KO&YTbYIP`pb78Us2Z{tcfIe*>8qF43b> zb3PaC^10y_stJ7yU}@F?DgU8ee@lhe!p0^KxPbiKYwqPGpF@7pVIw1fCiWh z*mq!NL_Nw4+S+*R7HuHSpd0qgw$m#r{KvE*=+=9Hk$xC9+hb`3!L2?htpg5`^udVz zRI+IqG#8*FsSm<~cq86H(FlqOhn4;7{M`u`v}4dsp4Zv^3r}r8M~R*S1o9r;QLQyz z{iJDFnw1}I_GV1O4+q!K{kPnHXvH-9mn-_LFB+%+T|8!N)@8fb?0*CDZ*Dxbpj* zPZ@On2NIzIN5XeL!Df-2L7t6o4$~!?fy3{YOfWTc@_!UqpI)<4511%Lc_@&`(n!&o3Z4@H;HF*95s0{Si8M zDG?r_@8x+uN6}WHb$?%N(1`t68`Y6)XEnk*m8PZkemOsbOH$Sq@(4O0JglLlGQ#Hj zrIN>B(lDno0s)=z{dd4z(Vj@auRU96dY>C)NM}%fv>%}&%tde{iHcA_<6xsrRIj2i-xeBYhA+GWL;4*UCP=z3zAE;ZswP z+@CV{+DE`<*+wT-We<;wI34zZZq2pNnc$VqW_1f`+Rt*e{C$oQ>Q>c zJT?$_I_tBdB0G^BS3(}Zy)P@yGl-!A@gKBVyE9n#zCqM zSF)aU^d#1D=vJS}$G%U{PASo?^wV+mj@9+Art}Tj4~T=WWDrJpjq4ExA%;NIF)%Zl z&rCEM9Y69hbWK~c1KmcmQ2>$1zF4dzP-ULf8Wu`hsDt|;`FN}nDyfl4p|{KI`-R(H z5*$!XaCK5NoA`$Vu_Zte5%Dk5B#5M#B#-0k86VRauZjd9!VU8o4x|4%ZT{r@O~JnF z0Vb<^4$_4}$TW7tSmYm+4cLoyasp5^EGJm7IK5j}`-AY4Zz}Fbk~MPQD?#mP_z8Yd z2~_YP&UO$G+FB0TB9cTzETc=<4?1)Czu$BbGWIAph;T7o`I=V*9!&xe?{qx$e_j{Qet4E)#wf$ z%+jk$=f-0*G*54dui?jSJfd*e{7g^ploD)BPyrJ~xm7M-?Dy1zGdrRa;ugHnQF zDhWMI96mGV@Pq39V7|ndO2LUXk;&mXF+HMvf_T%VP8@O=^FMKGm+^8mO|bhMoYx6z z?|x@g*=qU*`+rf_@y*T@z2j0w$YGct^wA3i`auKbe!=plL*IN)8{JmUvtcTu@IXC59ij*b&7)cG zVbtkouy0-+0zi>*logFYIzF7B zrB>oBe*naGzA-P-Oyq$iV9_c-O3-(dmrCXFcrDJZ=>W^1)8ZvuJUlu~!Ez?A+Po2`tEaxFzSnE;XzyOD z)ecC{6mE{!`guQr=g0mJ+LL`%A%9fs9x?fbEBGIh(q>s-)SNv(?m21r(X@pNshNOK TvH2iSzyB9yg^r literal 43568 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 F=78<7?tcIP diff --git a/data/cs_available_data.rda b/data/cs_available_data.rda index 32aa47c3d766c5c2618d2077faab27fc02f0f5a7..32faba73cd0dd49f7e567605f33e580a0776c0fe 100644 GIT binary patch literal 5577 zcmV;)6*lTZT4*^jL0KkKS)Opx8371k|IYva|NsC0|L}kJ-@w2B|L{Nn00=+;2mk49T z+JV~(l+4Uv#G^D(pdzVFVozgT9B60*Km$Mk00E!?000>P01QAHXb4RTr|Lr>^ng80 z1|gu(XaE2J13)wYGzm0{6qyq#=?_FSWB>pFGynhq01W^D1fHr<5}x#^2A-e*0000Q z001-q00001N>LLcX@N8d#WH4tOp_BK=%yN)WXb48Vlhn(sMBeZ4Lv}lq=W<@Mw(N~ zGJdJ(K+`~afuW{>pf;01>HugSpbt^x)p4!3s%wjy$+BWlkzfMJ6sZenQBhlH zkt}Gon&Qb~wZoQ*(}4S5Vo4TFNCu!*04-JmZa7qiiArE6ki&z4IWBN%fTL~ZfKgDW z5GoX4EH<=;<%PQDnqj%J0nQw7Ep}1LawaE@>m%k}*2 zz25get=v3zxr6NJ%w{vPP-<&SF051R8~z{EtM>mlT=NlMz%>xn!Iid467^O zQ;NeCW)m39HDxVXSZP+Yn6wQBD|qiORoQv@O57r_Z!-;Da;lyb_9&k5d zQ_|?snBFw)(~B(0nO0!Z=6KcImGuj|9a^o6IN{7@tkljpc>fMXwI6QEy}K3cvYy5s=2zUx`?&kwUw7Wv`>K+!cBCFJ=bv7?5TSb-|DL5Q z%E~H!-JU)F;kWbU6$iQYk8@2)R2J+KtK;bC{6CNTxn)0;r!9;zm|^^}qw0nEzIMQz z!b8pHJSidI^EY%=a-+wdC94CZSy+u~Z8eJoCFV36_J6cH)KGYSBV5s_tR!faa7zUJEp z$y4R@dwid}Cq6xIxz`)V%elsUKIIC3dkQ(D|DIm_^!k2MUgbUfN_luyeIH8LTMKQG zwM#W#usf=JFL4K6zBx>#TZq@r(<%OJo)iYtmK$h+MJ&&Q<7$cS$H1q6Sq`7^0LB`Eql@ zu!95yHW%#UWeus!=Ui#A8w&=sTN`Tfn$^NFWVC3l9vG|4*E{uSjgB>PZk_zRG*&G{ zRw~J@x~r5}sHik!SnF6eDx%odD`rz=Ul!K28!e{PooxF)kDhZ4rFQOYTS?yzV`#P< z#Po{AMvF$+#<8uncG#mES}PS|*x0qJrYj{`qh)M{(dVC#%r;ER>ifRmE~!JmoV;Re zZEROFn6_I*=U$4rrI>77+-ouE-y@kjHndwCX*P=$UUCSiwk2{^nKLUG%x6D$`gVUV z&R&I1uIW`d;Bg0L`?yn@hVSV%+cRrw3ZM%ikdhKugdiAsexEwi&36t*8MT<&ZIwIK z9)0~f=J-hWQjR#7t(Q|Uw;678b=CK(lK(YN z!KyfwVKNIzk!Z?R8BJC5DEO_#M=<4F5u;karK>M!`VLA-x;?GYutSzN!oZm>O14w2 zMKM8}CAD)?(h&9KRM`uGRILlvpgu}INs2LnriEihnu@Wb7EEPYVlkT4R=;9Z8ewfI zY4H0$7vfIqkB_il*RBlEEUU~mM`&T*tMGZ4%ee)Hm3fQT3{IS)U34K~b-b}CU8uvGO^(LN~W1e zQzERQrJ&NQn>Wqn&!CY4s%=7 zx^xMrx+~VAb0r?JSEoq6X(sb$lRbL-@|RCC@tLiei(#@b7;bVXY`p17=h7FfmM4mV z1H%GF!bv-H?^`=^w+Aq{4)i1^unjy+6W&L`?kVr)r=ly$d?;N#eY1~#xa*zAiiw1G zl6ypaC|>kEsZ`71Q0l8=WsGPxv8pYt(^lKH*zMb;a&M}w*cg>DD!0`cN}H&UY8}r# z<*mo53xn1x%7yBbV5@j5ts{EhyMDUkHt*0@Dz^ykwNcsu_0mlJkH$7f?CXXp2`f?y zQbWA`R36d11uvBo<$=H3rFGaGb?D`1@XWzTJE^c-kXH z;_$5%7B)upHml;Tsv@Gsv7*M)WSc8!wi`xbCdh2I#?`C~6lk+;G&LI9%8Y9(Xo|(E zSg6Fv#irV3lPxx}5vsFTw38HA+Zx*%D64Es5~_;DRBaO_5wQ_5wNYyt+eXzE+ZD8; z4M`hD-yN#v!o-r;Y}qR^-;F8xKWXu~u6?{;lKyr3Z+ur6P8hy7XQSnO$He_L0rKMK zeBUFw%R81{^s1anm2Q&4lH`ToTh%s7d_sI5?JB0pRX@p3&w3Zi%O}zLl{*hl_O$uG zb57H2&70%mRPP<`_l)76r{ps3s(k@~ljHxAi0b;kFpI3Y4b#is@)26fL=eyn6?dQi&AEz76cY-+7_B=A0QL?F1(CobHf-f2O zy=G?0ruk2>L;pSbProVc%753W?>tt7JROws0#5}e=RYHodfeHc#dhLK>nfGmld%hy z7q9O00!)g#6r{=}VJbgBC&DZB#a>bH)KA!yY%kX(tdmj}tM*D-&7n1j_-aQ2D*$h$ zP1G%7wIb4n>Z8?1@XuTQ^2foa{hKk3Bqah7Cfw__ey*EOx2t~oJ{tbj{}nZk6Zmc} zBEK336;I14|J)MzhYV>4mW?D134G#=i&}$)RITav)jgUx6}y1@^=_1TQb&C$OKQ^F zTP>Do?hTLv*F|*E(&qpf$RDE!~RQdzvi%O}e_mbjz$I5AZD)bkZQg>5|pGuwx zcI=HwI(IAW=5AEhlSx+C8&Pj>%23x$5zUL;ADMlSJt+E%$r(>l9pm&T$*Et)j#4>e zLhDL-U}ngg^oVu$Dr{HMOhj@RNqrT8M(Ud56u3?C@1?Shn!@0zt#hhk-5-17lWd=5 zH>^hmOz&70DO1`9HTf+j`AKx3!b-@`YCHsp;;PL zy;GQ0Nv$1vn+<_F9k(sq&OEbSFU=QUx}8$Esn3NS)i~#4tYn{Br*4zYso1YHYsR^@ zhUZn(a6s#oztMn96PpoP0*EnYiDo2{j99^qGG&7pirZ-L6YZCHUa-6Rvu$mRW(1}p z`j*=7)#BQowF8#^1 z2LyFfa=RNIWDbh52dYD-mn9%bk|2Bcc%&0#6mkUHc$p0s!tQQRkD`Q23u)YRQ6#Zc5kxmD9C(^IidYMuBpE=U|Vq^i@- z_jAG%x8h?kyD@g^d3MWur=X`=I^@|FvTzfv*s1AlrAEFi`tquAoupf*9K6J_c;iJ@Dr~7qB;tDgC#xV6pgEI>9(2ZfI*9CFq%Sy~*OHH+QRv5XJ5_W_ZK<_eRbD0a{j!|$bG9j+IqzC%vsHIm?>nSqE^~$V>goQ2)suXJd*M!(CKRS`%>sJR<@xm zWQv$1%Gac=+f{k(ZFTD@0z_tJJEeI^;iwOyB(6yIMI2ObAUPmrn8A@HZB;AN_&Dl$ z)#dMvwVSGWKSxD0r*%%!_a!`3`!BiSeIGp>j6m&^@AesuG8tl%L`a)+Yg+Ks+iPm+ z(7-@sl7b$o>E(gjl~ZbOQ&f9UH>+Z%vBgt{F4Sp9Tk_Ejp}5uui>)c+skW{Vrs$fZ zQX8qdG*_r{pNa>RUZNj}pP?b%uO(Np4~-m`ks;Aj>(r(@Sk(HdCx-1uAb0WJ{v9*5 zTCWvPyeo-y15xF0hw@cl7pJ7AskEqM8YwnywP$UNXB^rsPEiOY6lmFrQQx-WBF2ou z5Sa!;2^l72gd!BmBr_SRx|S zSsSVYv(*Eb^I&!rUW%)TLt>t)r<*5w4N2jF%~MH#$>DV-BMdNwDID8h`%8>N)Du{{ z_(*Hs=)*G1jFh7cCB|fJRPr5rye5*~yh^Q+xmOs6MGdO1$m5GrWLn*1Wio~^gv*t$ zV_SJQTT{tNJn?B$h;dZhDD{fr9W^`3oE4GPX&W4CgZ#iVT#~AKJ59nICt7n3B$!)2jcI7+DtwkFu+1$@F!Mj}Q#xzxF$EIYqp~rPsQm*o) zZq!4!Dvs{1u3@unn{4Gieiik?^-nrin9;b8x)aWiVS7pCR1M_aM?U_IH*2OXp-OSe zZ&cDY$<;#;!Wm4D%01}hx}$jvg|t!Lsp8%t#2R%%?nNFnNnbR49ie>E^LREfw%cs8 zTV`UDwRg@c@Tym|rzK3Ow?$57UT7Oz1NF2+HJE(dR-{^)eF%N2Xgg~zuFEi z%9$DMwp5K3A_zu7F|~NDmh)Q8RRlWi7kIhaj>3#ys>t^pRMAfk+9B6fZ{Gtdjifkf z>QSmWB{*?a_0o4`RO?E4gg4Zt>Nu|jDmnY)&|PXfS9FI6b3*%g*xLLjYJBv4k5yMa z<;4~yJB0id0qqAWk0d#=g+${y#e@bMRCtnGW!w-PKi}*$0o_smF)psngYYbn{)Z*|x>m&rdl$ zca0k@t7(2+>E`ZNh`;Uc;_&IDUeV(gb9iqG@r|vmo(JYH+`l&$HezX>_L}OXeK|s! z>+@G1{^i4!a$(M?@%mgoj`7B;G-jq~zC{^#tG}WBe~(SA-7!`q*wI*$)_oov_4eWU X=~5q`=RaxAfBap^6yZWbdBaF##i-64 literal 4537 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 X%1?{ppZ)Y%pZ+f7ig2MJSU*~P4v@(W diff --git a/data/cs_timeline_data.rda b/data/cs_timeline_data.rda new file mode 100644 index 0000000000000000000000000000000000000000..93ae1a4f5fd181156eb0c50e4d5a3b5154b42dec GIT binary patch literal 3026 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 literal 0 HcmV?d00001 diff --git a/dev/app.R b/dev/app.R index b420f394..d21a4b3b 100644 --- a/dev/app.R +++ b/dev/app.R @@ -21,22 +21,30 @@ app_data <- get_appdata(data = merged_data, meta = metadata) app_vars <- get_meta_vars(data = app_data, meta = metadata) # Build a 'app_tables' -app_tables <- lapply( - setNames(names(app_data), names(app_data)), \(x){ - create_table(app_data[[x]], expected_columns = names(app_vars$items[[x]])) - }) +# app_tables <- lapply( +# setNames(names(app_data), names(app_data)), \(x){ +# create_table(app_data[[x]], expected_columns = names(app_vars$items[[x]])) +# }) # Build a 'available_data' available_data <- get_available_data( data = app_data, - tables = app_tables, - all_forms = app_vars$all_forms, + # tables = app_tables, # outdated arg + # all_forms = app_vars$all_forms, # outdated arg form_repeat_name = with( meta[["table_names"]], table_name[raw_name == "form_repeat"] ) |> tryCatch(error = \(e) "N") ) + +# For timeline data +timeline_data <- get_timeline_data( + app_data, + available_data = available_data, + treatment_label = metadata$settings$treatment_label %||% "\U1F48A T\U2093" +) + # tempdir not useful for production mode data_folder <- "." # data_path <- file.path(data_folder, @@ -47,8 +55,9 @@ save_objs <- c( "metadata", "app_data", "app_vars", - "app_tables", - "available_data") + # "app_tables", + "available_data", + "timeline_data") purrr::walk(save_objs, function(x){ rds_file <- file.path(data_folder, paste0(x, ".rds")) saveRDS(get(x), rds_file) @@ -71,7 +80,7 @@ db_create(get_review_data(merged_data), ) run_app( - data = data_path, #merged_data, # or db_path works too + data = data_folder, # merged_data, # or db_path works too # user_db = db_path, # defaults to "user_db.sqlite" # onStart = \(){onStop(\(){unlink(data_folder, recursive = TRUE)})} # be careful here ) diff --git a/inst/golem-config.yml b/inst/golem-config.yml index 3c1e5ab7..89a91ccd 100644 --- a/inst/golem-config.yml +++ b/inst/golem-config.yml @@ -7,8 +7,9 @@ default: meta_data: !expr clinsight::metadata app_data: !expr clinsight::cs_app_data app_vars: !expr clinsight::cs_app_vars - app_tables: !expr clinsight::cs_app_tables + # app_tables: !expr clinsight::cs_app_tables available_data: !expr clinsight::cs_available_data + timeline_data: !expr clinsight::cs_timeline_data user_db: user_db.sqlite user_roles: Administrator: admin @@ -25,8 +26,9 @@ test: meta_data: meta_data.rds app_data: app_data.rds app_vars: app_vars.rds - app_tables: app_tables.rds + # app_tables: app_tables.rds available_data: available_data.rds + timeline_data: timeline_data.rds shinymanager: app_prod: yes user_identification: shinymanager diff --git a/man/cs_app_data.Rd b/man/cs_app_data.Rd index 08471212..89cd4d57 100644 --- a/man/cs_app_data.Rd +++ b/man/cs_app_data.Rd @@ -60,7 +60,7 @@ #> ..$ region : chr [1:381] "BEL" "BEL" "BEL" "BEL" ... #> ..$ value_scaled : num [1:381] 0.437 0.115 -0.1 -0.154 -1.2 ... #> ..$ out_of_lim : Factor w/ 2 levels "1","0": 2 2 1 1 1 1 1 2 1 1 ... -#> ..$ text_label : chr [1:381] "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 4.16 10^9/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 1.7 10^9/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 0.12 10^9/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 11.5 g/dL" ... +#> ..$ text_label : chr [1:381] "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 4.16 10^9/L\\nLimits: 1.8-7.2\\nout of limits, clinically insignificant" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 1.7 10^9/L\\nLimits: 1.4-4\\nwithin limits" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 0.12 10^9/L\\nLimits: 0.2-1\\nout of limits, clinically insignificant" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 11.5 g/dL\\nLimits: 11.9-14.5\\nout of limits, clinically insignificant" ... #> $ Conc. Procedures: cnc_prcd [28 x 22] (S3: conc_procedures/common_forms/tbl_df/tbl/data.frame) #> ..$ site_code : chr [1:28] "BEL07" "BEL07" "BEL07" "BEL07" ... #> ..$ subject_id : chr [1:28] "BEL_07_645" "BEL_07_645" "BEL_07_645" "BEL_07_645" ... @@ -112,7 +112,7 @@ #> ..$ region : chr [1:275] "BEL" "BEL" "BEL" "BEL" ... #> ..$ value_scaled : num [1:275] 0.222 1 0.778 -0.214 0.275 ... #> ..$ out_of_lim : Factor w/ 2 levels "0","1": 1 1 1 2 1 1 1 1 1 1 ... -#> ..$ text_label : chr [1:275] "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 138 mmol/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 4.5 mmol/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 105 mmol/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 20.5 mmol/L" ... +#> ..$ text_label : chr [1:275] "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 138 mmol/L\\nLimits: 136-145\\nwithin limits" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 4.5 mmol/L\\nLimits: 3-4.5\\nout of limits, clinically insignificant" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 105 mmol/L\\nLimits: 98-107\\nwithin limits" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 20.5 mmol/L\\nLimits: 22-29\\nout of limits, significance pending" ... #> $ General : general [261 x 22] (S3: general/tbl_df/tbl/data.frame) #> ..$ site_code : chr [1:261] "BEL04" "BEL04" "BEL04" "BEL04" ... #> ..$ subject_id : chr [1:261] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... @@ -164,7 +164,7 @@ #> ..$ region : chr [1:180] "BEL" "BEL" "BEL" "BEL" ... #> ..$ value_scaled : num [1:180] 0.286 0.44 1.667 0.613 0.524 ... #> ..$ out_of_lim : Factor w/ 2 levels "0","1": 1 1 2 1 1 1 2 1 1 2 ... -#> ..$ text_label : chr [1:180] "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 6 µmol/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 21 U/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 35 U/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 24 U/L" ... +#> ..$ text_label : chr [1:180] "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 6 µmol/L\\nLimits: 0-21\\nwithin limits" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 21 U/L\\nLimits: 10-35\\nout of limits, clinically insignificant" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 35 U/L\\nLimits: 10-25\\nout of limits, clinically insignificant" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 24 U/L\\nLimits: 5-36\\nwithin limits" ... #> $ Medical History : mdcl_hst [757 x 22] (S3: medical_history/common_forms/tbl_df/tbl/data.frame) #> ..$ site_code : chr [1:757] "BEL04" "BEL04" "BEL04" "BEL04" ... #> ..$ subject_id : chr [1:757] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... @@ -241,7 +241,7 @@ #> ..$ region : chr [1:135] "BEL" "BEL" "BEL" "BEL" ... #> ..$ value_scaled : num [1:135] 0.333 -0.4 0.74 1.667 0.967 ... #> ..$ out_of_lim : Factor w/ 2 levels "0","1": 1 2 1 2 1 1 1 1 1 2 ... -#> ..$ text_label : chr [1:135] "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 58 µmol/L" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 48 ml/min/1.73 m²" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 288 µmol/L" "BEL_04_133\\n2023-07-05\\nVisit 1 (day 30)\\nValue: 110 µmol/L" ... +#> ..$ text_label : chr [1:135] "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 58 µmol/L\\nLimits: 45-84\\nout of limits, clinically insignificant" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 48 ml/min/1.73 m²\\nLimits: 60-90\\nout of limits, clini"| __truncated__ "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 288 µmol/L\\nLimits: 140-340\\nwithin limits" "BEL_04_133\\n2023-07-05\\nVisit 1 (day 30)\\nValue: 110 µmol/L\\nLimits: 45-84\\nout of limits, clinically insignificant" ... #> $ Response : tibble [6 x 22] (S3: tbl_df/tbl/data.frame) #> ..$ site_code : chr [1:6] "BEL04" "BEL04" "BEL04" "BEL04" ... #> ..$ subject_id : chr [1:6] "BEL_04_133" "BEL_04_133" "BEL_04_772" "BEL_04_772" ... @@ -293,7 +293,7 @@ #> ..$ region : chr [1:478] "BEL" "BEL" "BEL" "BEL" ... #> ..$ value_scaled : num [1:478] 0.0323 0.5235 0 0.875 0.4857 ... #> ..$ out_of_lim : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 2 1 ... -#> ..$ text_label : chr [1:478] "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 50 kg" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 24.52 kg/m2" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 60 beats/min" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 19 breaths/min" ... +#> ..$ text_label : chr [1:478] "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 50 kg\\nLimits: 45-200\\nwithin limits" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 24.52 kg/m2\\nLimits: 18.5-30\\nwithin limits" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 60 beats/min\\nLimits: 60-100\\nwithin limits" "BEL_04_133\\n2023-06-05\\nScreening (day 0)\\nValue: 19 breaths/min\\nLimits: 12-20\\nwithin limits" ... }\if{html}{\out{}} } } diff --git a/man/cs_app_tables.Rd b/man/cs_app_tables.Rd deleted file mode 100644 index 8dc1f164..00000000 --- a/man/cs_app_tables.Rd +++ /dev/null @@ -1,149 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/data.R -\docType{data} -\name{cs_app_tables} -\alias{cs_app_tables} -\title{Application Tables} -\format{ -\subsection{\code{cs_app_tables}: A list with 11 objects.}{ - -\if{html}{\out{
}}\preformatted{str(cs_app_tables) -#> List of 11 -#> $ Adverse events : tibble [90 x 16] (S3: tbl_df/tbl/data.frame) -#> ..$ subject_id : chr [1:90] "BEL_07_193" "NLD_03_207" "BEL_08_885" "NLD_03_207" ... -#> ..$ form_repeat : int [1:90] 1 1 1 1 1 2 2 2 3 6 ... -#> ..$ Name : chr [1:90] "Atelectasis" "Sepsis" "Seizure" "Sepsis" ... -#> ..$ AESI : chr [1:90] "None" "None" "None" "None" ... -#> ..$ start date : chr [1:90] "2023-09-14" "2023-08-14" "2023-08-11" "2023-08-02" ... -#> ..$ end date : chr [1:90] NA "2023-08-14" NA "2023-08-14" ... -#> ..$ CTCAE severity : chr [1:90] "Grade 3" "Grade 5" "Grade 3" "Grade 3" ... -#> ..$ Treatment related : chr [1:90] "Unlikely" "Not related" "Not related" "Not related" ... -#> ..$ Treatment action : chr [1:90] "Not Applicable (Concomitant therapy/medication; Hospitalization/Prolongation of hospitalization)" "Interrupted (Concomitant therapy/medication; Hospitalization/Prolongation of hospitalization)" "Not Applicable (Hospitalization/Prolongation of hospitalization)" "Interrupted (Concomitant therapy/medication; Hospitalization/Prolongation of hospitalization)" ... -#> ..$ Serious Adverse Event: chr [1:90] "Yes" "Yes" "Yes" "Yes" ... -#> ..$ SAE Start date : chr [1:90] "2023-09-14" "2023-08-14" "2023-08-11" "2023-08-02" ... -#> ..$ SAE End date : chr [1:90] NA "2023-08-14" NA "2023-08-14" ... -#> ..$ SAE Category : chr [1:90] "Requires inpatient hospitalization or prolongation of existing hospitalization" "Results in death; Is life-threatening; Requires inpatient hospitalization or prolongation of existing hospitalization" "Requires inpatient hospitalization or prolongation of existing hospitalization" "Results in death; Is life-threatening; Requires inpatient hospitalization or prolongation of existing hospitalization" ... -#> ..$ SAE Awareness date : chr [1:90] "2023-09-14" "2023-08-02" "2023-08-15" "2023-08-02" ... -#> ..$ SAE Date of death : chr [1:90] NA "2023-08-14" NA "2023-08-14" ... -#> ..$ SAE Death reason : chr [1:90] NA "disease progression" NA "disease progression" ... -#> $ CBC regular : tibble [65 x 9] (S3: tbl_df/tbl/data.frame) -#> ..$ subject_id : chr [1:65] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... -#> ..$ event_name : chr [1:65] "Screening" "Visit 1" "Visit 2" "Visit 3" ... -#> ..$ event_date : Date[1:65], format: "2023-06-05" "2023-07-05" ... -#> ..$ Haemoglobin: chr [1:65] "11.5 g/dL" "8 g/dL" "8.2 g/dL" "10.7 g/dL" ... -#> ..$ Haematocrit: chr [1:65] "0.25 Proportion of 1.0" "0.23 Proportion of 1.0" "0.33 Proportion of 1.0" "0.21 Proportion of 1.0" ... -#> ..$ Platelets : chr [1:65] "99.14 10^9/L" "99.14 10^9/L" "99.14 10^9/L" "99.14 10^9/L" ... -#> ..$ Neutrophils: chr [1:65] "4.16 10^9/L" "1.36 10^9/L" "1.36 10^9/L" "1.36 10^9/L" ... -#> ..$ Lymphocytes: chr [1:65] "1.7 10^9/L" "1.55 10^9/L" "1.6 10^9/L" "1.09 10^9/L" ... -#> ..$ Monocytes : chr [1:65] "0.12 10^9/L" "0.1 10^9/L" "0.83 10^9/L" "0.12 10^9/L" ... -#> $ Conc. Procedures: tibble [4 x 9] (S3: tbl_df/tbl/data.frame) -#> ..$ subject_id : chr [1:4] "BEL_07_645" "BEL_07_645" "DEU_02_866" "NLD_06_755" -#> ..$ form_repeat : int [1:4] 1 2 1 1 -#> ..$ Name : chr [1:4] "Appendectomy" "Amputation" "Thrombolysis" "Amputation" -#> ..$ Indication : chr [1:4] "Prophylaxis" "Pain" "Hypertension" "Infection" -#> ..$ Start Date : chr [1:4] "2019-NK-NK" "2019-NK-NK" "2023-08-18" "2023-08-04" -#> ..$ Ongoing : chr [1:4] "No" "No" "No" "Yes" -#> ..$ End Date : chr [1:4] "2019-NK-NK" "2019-NK-NK" "2023-08-18" NA -#> ..$ Related Medical History: chr [1:4] "Sickle cell anemia" "Sickle cell anemia" "Epilepsy" "Familial Mediterranean fever" -#> ..$ Related AE : chr [1:4] NA NA NA "Joint pain" -#> $ Electrolytes : tibble [46 x 9] (S3: tbl_df/tbl/data.frame) -#> ..$ subject_id : chr [1:46] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... -#> ..$ event_name : chr [1:46] "Screening" "Visit 1" "Visit 3" "Visit 5" ... -#> ..$ event_date : Date[1:46], format: "2023-06-05" "2023-07-05" ... -#> ..$ Sodium : chr [1:46] "138 mmol/L" "138 mmol/L" "140 mmol/L" "138 mmol/L" ... -#> ..$ Potassium : chr [1:46] "4.5 mmol/L" "4.14 mmol/L" "4.65 mmol/L" "4.74 mmol/L" ... -#> ..$ Chloride : chr [1:46] "105 mmol/L" "103 mmol/L" "105 mmol/L" "104 mmol/L" ... -#> ..$ Bicarbonate: chr [1:46] "20.5 mmol/L" "23 mmol/L" "23.7 mmol/L" "21.4 mmol/L" ... -#> ..$ Calcium : chr [1:46] "2.26 mmol/L" "2.53 mmol/L" "2.43 mmol/L" "2.39 mmol/L" ... -#> ..$ Magnesium : chr [1:46] "0.87 mmol/L" "0.83 mmol/L" "0.75 mmol/L" "0.88 mmol/L" ... -#> $ General : tibble [25 x 23] (S3: tbl_df/tbl/data.frame) -#> ..$ subject_id : chr [1:25] "BEL_04_133" "BEL_04_772" "BEL_07_193" "BEL_07_431" ... -#> ..$ Age : chr [1:25] "88" "78" "26" "42" ... -#> ..$ Sex : chr [1:25] "Male" "Male" "Female" "Male" ... -#> ..$ ECOG : chr [1:25] "1" "0" "1" "1" ... -#> ..$ Eligible : chr [1:25] "Yes" "Yes" "Yes" NA ... -#> ..$ Eligible_Date : chr [1:25] "2023-07-06" "2023-08-17" "2023-08-23" NA ... -#> ..$ WHO.classification : chr [1:25] "Syndrome K" "Syndrome O" "Syndrome D" NA ... -#> ..$ WHO.subclassification : chr [1:25] NA NA NA NA ... -#> ..$ Race : chr [1:25] "White" "White" "Not reported" "Not reported" ... -#> ..$ ChildbearingPotential : chr [1:25] "No" "No" NA NA ... -#> ..$ MenopauseReason : chr [1:25] "Postmenopausal" "Postmenopausal" NA NA ... -#> ..$ DiscontinuationDate : chr [1:25] NA NA NA NA ... -#> ..$ DiscontinuationReason : chr [1:25] NA NA NA NA ... -#> ..$ DisconDeathDate : chr [1:25] NA NA NA NA ... -#> ..$ DrugAdminDate : chr [1:25] NA NA NA NA ... -#> ..$ DrugAdminDose : chr [1:25] NA NA NA NA ... -#> ..$ DoseModificationDate : chr [1:25] NA NA NA NA ... -#> ..$ DoseModificationReason : chr [1:25] NA NA NA NA ... -#> ..$ DoseModificationNewDose: chr [1:25] NA NA NA NA ... -#> ..$ DrugDiscontDate : chr [1:25] NA NA NA NA ... -#> ..$ DrugDiscontReason : chr [1:25] NA NA NA NA ... -#> ..$ subject_status : chr [1:25] "Enrolled" "Enrolled" "Enrolled" "Unknown" ... -#> ..$ status_label : chr [1:25] "BEL_04_133
Sex: Male
Age: 88yrs.
Status: Enrolled
ECOG: 1
"| __truncated__ "BEL_04_772
Sex: Male
Age: 78yrs.
Status: Enrolled
ECOG: 0
"| __truncated__ "BEL_07_193
Sex: Female
Age: 26yrs.
Status: Enrolled
ECOG: 1
<"| __truncated__ "BEL_07_431
Sex: Male
Age: 42yrs.
Status: Unknown
ECOG: 1
Dx: NA" ... -#> $ Liver function : tibble [45 x 7] (S3: tbl_df/tbl/data.frame) -#> ..$ subject_id: chr [1:45] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... -#> ..$ event_name: chr [1:45] "Screening" "Visit 1" "Visit 3" "Visit 5" ... -#> ..$ event_date: Date[1:45], format: "2023-06-05" "2023-07-05" ... -#> ..$ Bilirubin : chr [1:45] "6 µmol/L" "11 µmol/L" "8 µmol/L" "7 µmol/L" ... -#> ..$ AST : chr [1:45] "21 U/L" "32 U/L" "43 U/L" "42 U/L" ... -#> ..$ ALT : chr [1:45] "35 U/L" "45 U/L" "19 U/L" "27 U/L" ... -#> ..$ gGT : chr [1:45] "24 U/L" "25 U/L" "26 U/L" "21 U/L" ... -#> $ Medical History : tibble [152 x 8] (S3: tbl_df/tbl/data.frame) -#> ..$ subject_id : chr [1:152] "BEL_04_133" "BEL_04_772" "BEL_04_772" "BEL_04_772" ... -#> ..$ form_repeat: int [1:152] 1 1 2 3 4 5 6 7 8 9 ... -#> ..$ Name : chr [1:152] "Epilepsy" "Hypertension" "COPD" "Osteoporosis" ... -#> ..$ Start Date : chr [1:152] NA "2020-NK-NK" "1995-NK-NK" "2005-NK-NK" ... -#> ..$ Ongoing : chr [1:152] "Yes" "Yes" "Yes" "Yes" ... -#> ..$ End Date : chr [1:152] NA NA NA NA ... -#> ..$ Treatment : chr [1:152] "Medication" "Medication" "Medication" "Medication" ... -#> ..$ Comment : chr [1:152] NA NA NA NA ... -#> $ Medication : tibble [283 x 10] (S3: tbl_df/tbl/data.frame) -#> ..$ subject_id : chr [1:283] "DEU_01_541" "DEU_01_541" "BEL_07_645" "BEL_07_645" ... -#> ..$ form_repeat : int [1:283] 1 2 6 7 9 10 3 10 15 33 ... -#> ..$ Name : chr [1:283] "Lisinopril (Sulfaipoetin)" "Oxycodone (Estrizotan)" "Lisinopril (Salsteridone)" "Lisinopril (Nifurasiban)" ... -#> ..$ Indication : chr [1:283] "Insomnia" "Infection" "Nausea" "Insomnia" ... -#> ..$ Dose : chr [1:283] "300 Milligram (mg) Per day (QD); Oral (p.o.)" "500 Milligram (mg) Per day (QD); Oral (p.o.)" "5 Milligram (mg) Per month (QM); Intravenous (i.v.)" "20 Milligram (mg) Per month (QM); Intravenous (i.v.)" ... -#> ..$ Start Date : chr [1:283] "2023-NK-NK" "2023-NK-NK" "2023-09-13" "2023-09-13" ... -#> ..$ Ongoing : chr [1:283] "Yes" "Yes" "Yes" "Yes" ... -#> ..$ End Date : chr [1:283] NA NA NA NA ... -#> ..$ Related Medical History: chr [1:283] NA NA NA NA ... -#> ..$ Related AE : chr [1:283] NA NA NA NA ... -#> $ Renal function : tibble [46 x 6] (S3: tbl_df/tbl/data.frame) -#> ..$ subject_id: chr [1:46] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... -#> ..$ event_name: chr [1:46] "Screening" "Visit 1" "Visit 3" "Visit 5" ... -#> ..$ event_date: Date[1:46], format: "2023-06-05" "2023-07-05" ... -#> ..$ Creatinine: chr [1:46] "58 µmol/L" "110 µmol/L" "61 µmol/L" "117 µmol/L" ... -#> ..$ eGFR : chr [1:46] "48 ml/min/1.73 m²" "89 ml/min/1.73 m²" "90 ml/min/1.73 m²" "47 ml/min/1.73 m²" ... -#> ..$ Urate : chr [1:46] "288 µmol/L" "4.1 mmol/L" "7.5 mmol/L" "294 µmol/L" ... -#> $ Response : tibble [3 x 6] (S3: tbl_df/tbl/data.frame) -#> ..$ subject_id : chr [1:3] "BEL_04_133" "BEL_04_772" "NLD_06_72" -#> ..$ event_name : chr [1:3] "Visit 5" "Visit 5" "Visit 5" -#> ..$ event_repeat: int [1:3] 5 5 5 -#> ..$ event_date : Date[1:3], format: "2023-08-30" "2023-08-30" ... -#> ..$ Response : chr [1:3] "Stable disease (SD)" "Cured" "Stable disease (SD)" -#> ..$ Responder : chr [1:3] "No" "Yes" "No" -#> $ Vital signs : tibble [68 x 11] (S3: tbl_df/tbl/data.frame) -#> ..$ subject_id : chr [1:68] "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... -#> ..$ event_name : chr [1:68] "Screening" "Visit 1" "Visit 2" "Visit 3" ... -#> ..$ event_date : Date[1:68], format: "2023-06-05" "2023-07-05" ... -#> ..$ Systolic blood pressure : chr [1:68] "108 mmHg" "123 mmHg" "122 mmHg" "137 mmHg" ... -#> ..$ Diastolic blood pressure : chr [1:68] "62 mmHg" "69 mmHg" "68 mmHg" "72 mmHg" ... -#> ..$ Pulse : chr [1:68] "60 beats/min" "67 beats/min" "69 beats/min" "78 beats/min" ... -#> ..$ Resp : chr [1:68] "19 breaths/min" "19 breaths/min" "18 breaths/min" "16 breaths/min" ... -#> ..$ Temperature : chr [1:68] "36.7 °C" "36.5 °C" "36.2 °C" "36.7 °C" ... -#> ..$ Weight change since screening: chr [1:68] "0 \%" "24 \%" NA "2 \%" ... -#> ..$ BMI : chr [1:68] "24.52 kg/m2" "17.1 kg/m2" NA "24.52 kg/m2" ... -#> ..$ Weight : chr [1:68] "50 kg" "62 kg" NA "51 kg" ... -}\if{html}{\out{
}} -} -} -\source{ -See \code{raw-data/clinsightful_data.R} for details. -} -\usage{ -cs_app_tables -} -\description{ -A list of data frames containing all application tables. -} -\keyword{datasets} diff --git a/man/cs_available_data.Rd b/man/cs_available_data.Rd index aba55e37..2218e71a 100644 --- a/man/cs_available_data.Rd +++ b/man/cs_available_data.Rd @@ -5,17 +5,19 @@ \alias{cs_available_data} \title{Application 'Available Data'} \format{ -a data.frame with 1974 rows and -6 variables. +a data.frame with 2235 rows and +7 variables. \if{html}{\out{
}}\preformatted{str(cs_available_data) -#> tibble [1,974 x 6] (S3: tbl_df/tbl/data.frame) -#> $ subject_id : chr [1:1974] "BEL_04_772" "BEL_04_772" "BEL_04_772" "BEL_04_772" ... -#> $ item_name : chr [1:1974] "Hypotension" "Atrial Fibrillation (N: 2)" "Tachycardia" "Urinary Tract Infection" ... -#> $ form_repeat: int [1:1974] 1 2 3 4 5 1 1 1 3 2 ... -#> $ item_group : chr [1:1974] "Adverse events" "Adverse events" "Adverse events" "Adverse events" ... -#> $ event_name : chr [1:1974] "Any visit" "Any visit" "Any visit" "Any visit" ... -#> $ event_label: chr [1:1974] "Any visit" "Any visit" "Any visit" "Any visit" ... +#> 'data.frame': 2235 obs. of 7 variables: +#> $ subject_id : chr "BEL_04_772" "BEL_04_772" "BEL_04_772" "BEL_04_772" ... +#> $ item_name : chr "Hypotension" "Atrial Fibrillation (Form Repeat: 2)" "Tachycardia" "Urinary Tract Infection" ... +#> $ form_repeat: int 1 2 3 4 5 1 1 1 2 3 ... +#> $ item_group : chr "Adverse events" "Adverse events" "Adverse events" "Adverse events" ... +#> $ event_name : chr "Any visit" "Any visit" "Any visit" "Any visit" ... +#> $ event_label: Factor w/ 8 levels "SCR","V1","V2",..: NA NA NA NA NA NA NA NA NA NA ... +#> $ event_date : Date, format: "2023-08-31" "2023-08-31" ... +#> - attr(*, "synch_time")= chr "2023-09-15 10:10:00 UTC" }\if{html}{\out{
}} } \source{ diff --git a/man/cs_timeline_data.Rd b/man/cs_timeline_data.Rd new file mode 100644 index 00000000..34940108 --- /dev/null +++ b/man/cs_timeline_data.Rd @@ -0,0 +1,38 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/data.R +\docType{data} +\name{cs_timeline_data} +\alias{cs_timeline_data} +\title{Application Timeline Data} +\format{ +\subsection{\code{cs_timeline_data}: data.frame formatted for comsumption by}{ + +\code{timevis} package. + +\if{html}{\out{
}}\preformatted{str(cs_timeline_data) +#> 'data.frame': 203 obs. of 11 variables: +#> $ subject_id : chr "BEL_04_133" "BEL_04_133" "BEL_04_133" "BEL_04_133" ... +#> $ content : chr "Screening" "Visit 1" "Visit 2" "Visit 3" ... +#> $ form_repeat: int NA NA NA NA NA NA NA NA NA NA ... +#> $ item_group : chr NA NA NA NA ... +#> $ start : Date, format: "2023-06-05" "2023-07-05" ... +#> $ group : Factor w/ 4 levels "SAE","Adverse event",..: 4 4 4 4 4 4 4 4 4 4 ... +#> $ end : Date, format: NA NA ... +#> $ title : chr "2023-06-05 | Screening" "2023-07-05 | Visit 1" "2023-07-19 | Visit 2" "2023-08-02 | Visit 3" ... +#> $ className : chr "bg-light" "bg-light" "bg-light" "bg-light" ... +#> $ id : int 1 2 3 4 5 6 7 8 9 10 ... +#> $ order : num 4 4 4 4 4 4 4 4 4 4 ... +#> - attr(*, "synch_time")= chr "2023-09-15 10:10:00 UTC" +}\if{html}{\out{
}} +} +} +\source{ +See \code{raw-data/clinsightful_data.R} for details. +} +\usage{ +cs_timeline_data +} +\description{ +A data.frame containing timeline data. +} +\keyword{datasets} diff --git a/tests/testthat/test-mod_main_sidebar.R b/tests/testthat/test-mod_main_sidebar.R index f375871a..ff56dd73 100644 --- a/tests/testthat/test-mod_main_sidebar.R +++ b/tests/testthat/test-mod_main_sidebar.R @@ -14,7 +14,8 @@ describe("mod_main_sidebar. Feature 1 | Load application module in isolation.", ), db_path = "", forms_to_review = reactiveVal(), - available_data = data.frame() + available_data = data.frame(), + timeline_data = data.frame() ) it("Can load the module UI, with functioning internal parameters.", { From b5d631f03c29bb50aca94d5e109d71a15e565a85 Mon Sep 17 00:00:00 2001 From: aclark02-arcus Date: Tue, 30 Dec 2025 09:26:34 -0800 Subject: [PATCH 09/14] removed duplicate str(metadata) --- R/data.R | 4 ---- man/metadata.Rd | 57 ------------------------------------------------- 2 files changed, 61 deletions(-) diff --git a/R/data.R b/R/data.R index 39abd2eb..7c093046 100644 --- a/R/data.R +++ b/R/data.R @@ -107,10 +107,6 @@ #' in-depth information. #' #' @format ## `metadata`: A list with `r length(metadata)` objects. -#' -#' ```{r } -#' str(metadata) -#' ``` #' #' @source Can be created with an Excel file. The Excel file format is chosen so #' that the metadata can be changed easily per study. See diff --git a/man/metadata.Rd b/man/metadata.Rd index 3f0c031a..0b447e3c 100644 --- a/man/metadata.Rd +++ b/man/metadata.Rd @@ -66,63 +66,6 @@ } \subsection{\code{metadata}: A list with 9 objects.}{ - -\if{html}{\out{
}}\preformatted{str(metadata) -#> List of 9 -#> $ column_names : tibble [10 x 2] (S3: tbl_df/tbl/data.frame) -#> ..$ name_raw: chr [1:10] "SiteCode" "SubjectId" "EventId" "EventDate" ... -#> ..$ name_new: chr [1:10] "site_code" "subject_id" "event_id" "event_date" ... -#> $ events : tibble [10 x 10] (S3: tbl_df/tbl/data.frame) -#> ..$ event_id : chr [1:10] "SCR" "VIS1" "VIS2" "VIS3" ... -#> ..$ event_id_pattern : chr [1:10] "^SCR$" "^VIS1$" "^VIS2$" "^VIS3$" ... -#> ..$ is_regular_visit : logi [1:10] TRUE TRUE TRUE TRUE TRUE TRUE ... -#> ..$ event_label_custom : chr [1:10] NA "V1" "V2" "V3" ... -#> ..$ event_name_custom : chr [1:10] "Screening" "Visit 1" "Visit 2" "Visit 3" ... -#> ..$ is_baseline_event : logi [1:10] TRUE FALSE FALSE FALSE FALSE FALSE ... -#> ..$ generate_labels : logi [1:10] FALSE FALSE FALSE FALSE FALSE FALSE ... -#> ..$ meta_event_order : int [1:10] 1 2 3 4 5 6 7 8 9 10 -#> ..$ add_visit_number : logi [1:10] FALSE FALSE FALSE FALSE FALSE FALSE ... -#> ..$ add_event_repeat_number: logi [1:10] FALSE FALSE FALSE FALSE FALSE FALSE ... -#> $ common_forms :'data.frame': 44 obs. of 4 variables: -#> ..$ item_name : chr [1:44] "AE Number" "AE Name" "AESI" "AE start date" ... -#> ..$ item_type : chr [1:44] "other" "other" "other" "other" ... -#> ..$ item_group: chr [1:44] "Adverse events" "Adverse events" "Adverse events" "Adverse events" ... -#> ..$ merge_with: chr [1:44] NA NA NA NA ... -#> $ study_forms :'data.frame': 29 obs. of 6 variables: -#> ..$ item_name : chr [1:29] "Systolic blood pressure" "Diastolic blood pressure" "Pulse" "Resp" ... -#> ..$ item_type : chr [1:29] "continuous" "continuous" "continuous" "continuous" ... -#> ..$ item_group : chr [1:29] "Vital signs" "Vital signs" "Vital signs" "Vital signs" ... -#> ..$ unit : chr [1:29] "mmHg" "mmHg" "beats/min" "breaths/min" ... -#> ..$ lower_limit: chr [1:29] "90" "55" "60" "12" ... -#> ..$ upper_limit: chr [1:29] "160" "90" "100" "20" ... -#> $ general :'data.frame': 20 obs. of 3 variables: -#> ..$ item_name : chr [1:20] "Age" "Sex" "ECOG" "Eligible" ... -#> ..$ item_type : chr [1:20] "other" "other" "other" "other" ... -#> ..$ item_group: chr [1:20] "General" "General" "General" "General" ... -#> $ form_level_data:'data.frame': 11 obs. of 4 variables: -#> ..$ item_group : chr [1:11] "Adverse events" "Medication" "Conc. Procedures" "Medical History" ... -#> ..$ item_scale : logi [1:11] NA NA NA NA FALSE TRUE ... -#> ..$ use_unscaled_limits: logi [1:11] NA NA NA NA TRUE FALSE ... -#> ..$ review_required : logi [1:11] TRUE TRUE TRUE TRUE TRUE TRUE ... -#> $ table_names : tibble [16 x 2] (S3: tbl_df/tbl/data.frame) -#> ..$ table_name: chr [1:16] "Edit date" "Date" "Event" "Event" ... -#> ..$ raw_name : chr [1:16] "edit_date_time" "event_date" "event_label" "event_name" ... -#> $ settings :List of 4 -#> ..$ pre_pivot_fns : chr "apply_study_specific_suffix_fixes" -#> ..$ post_pivot_fns : chr "apply_edc_specific_changes" -#> ..$ post_merge_fns : chr "apply_study_specific_fixes" -#> ..$ treatment_label: chr "💊 Tₓ" -#> $ items_expanded : tibble [220 x 9] (S3: tbl_df/tbl/data.frame) -#> ..$ form_type : chr [1:220] "common_forms" "common_forms" "common_forms" "common_forms" ... -#> ..$ var : chr [1:220] "AE_AESPID" "AE_AETERM" "AE_AESI" "AE_AESTDAT" ... -#> ..$ suffix : chr [1:220] NA NA NA NA ... -#> ..$ item_name : chr [1:220] "AE Number" "AE Name" "AESI" "AE start date" ... -#> ..$ item_type : chr [1:220] "other" "other" "other" "other" ... -#> ..$ item_group : chr [1:220] "Adverse events" "Adverse events" "Adverse events" "Adverse events" ... -#> ..$ unit : chr [1:220] NA NA NA NA ... -#> ..$ lower_limit: chr [1:220] NA NA NA NA ... -#> ..$ upper_limit: chr [1:220] NA NA NA NA ... -}\if{html}{\out{
}} } } \source{ From cfe7130ce75f5a255ad89b0c7f28c7ebd4a3afab Mon Sep 17 00:00:00 2001 From: aclark02-arcus Date: Tue, 30 Dec 2025 09:29:12 -0800 Subject: [PATCH 10/14] fixed creation of 'cs_available_data' --- data-raw/clinsightful_data.R | 2 +- data/cs_available_data.rda | Bin 5577 -> 5598 bytes man/cs_available_data.Rd | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data-raw/clinsightful_data.R b/data-raw/clinsightful_data.R index 6d27606f..8cf3c1ba 100644 --- a/data-raw/clinsightful_data.R +++ b/data-raw/clinsightful_data.R @@ -24,7 +24,7 @@ cs_available_data <- get_available_data( # tables = cs_app_tables, # outdated arg # all_forms = cs_app_vars$all_forms, # outdated arg form_repeat_name = with( - meta[["table_names"]], + metadata[["table_names"]], table_name[raw_name == "form_repeat"] ) |> tryCatch(error = \(e) "N") diff --git a/data/cs_available_data.rda b/data/cs_available_data.rda index 32faba73cd0dd49f7e567605f33e580a0776c0fe..74d4f02993b71d4967368de7f4e3ab092b27aeba 100644 GIT binary patch literal 5598 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 literal 5577 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 X=~5q`=RaxAfBap^6yZWbdBaF##i-64 diff --git a/man/cs_available_data.Rd b/man/cs_available_data.Rd index 2218e71a..4e05bc6b 100644 --- a/man/cs_available_data.Rd +++ b/man/cs_available_data.Rd @@ -11,7 +11,7 @@ a data.frame with 2235 rows and \if{html}{\out{
}}\preformatted{str(cs_available_data) #> 'data.frame': 2235 obs. of 7 variables: #> $ subject_id : chr "BEL_04_772" "BEL_04_772" "BEL_04_772" "BEL_04_772" ... -#> $ item_name : chr "Hypotension" "Atrial Fibrillation (Form Repeat: 2)" "Tachycardia" "Urinary Tract Infection" ... +#> $ item_name : chr "Hypotension" "Atrial Fibrillation (N: 2)" "Tachycardia" "Urinary Tract Infection" ... #> $ form_repeat: int 1 2 3 4 5 1 1 1 2 3 ... #> $ item_group : chr "Adverse events" "Adverse events" "Adverse events" "Adverse events" ... #> $ event_name : chr "Any visit" "Any visit" "Any visit" "Any visit" ... From 2ee494dc71ebc8768c5cae9e91091705aed2a208 Mon Sep 17 00:00:00 2001 From: Aaron Clark <162465159+aclark02-arcus@users.noreply.github.com> Date: Tue, 30 Dec 2025 12:32:23 -0500 Subject: [PATCH 11/14] Update R/run_app.R to check for character timeline_data object before reading it in Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- R/run_app.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/run_app.R b/R/run_app.R index e7270177..ff117b5d 100644 --- a/R/run_app.R +++ b/R/run_app.R @@ -50,7 +50,7 @@ run_app <- function( if(is.character(app_vars)) app_vars <- file.path(data_folder, basename(app_vars)) # if(is.character(app_tables)) app_tables <- file.path(data_folder, basename(app_tables)) if(is.character(available_data)) available_data <- file.path(data_folder, basename(available_data)) - if(is.character(available_data)) timeline_data <- file.path(data_folder, basename(timeline_data)) + if(is.character(timeline_data)) timeline_data <- file.path(data_folder, basename(timeline_data)) user_db <- file.path(data_folder, basename(user_db)) if(!is.null(credentials_db)){ credentials_db <- file.path(data_folder, basename(credentials_db)) From 7f84adc426ee444c588fb19e3cd0a52c3a2fee5b Mon Sep 17 00:00:00 2001 From: aclark02-arcus Date: Tue, 30 Dec 2025 09:35:09 -0800 Subject: [PATCH 12/14] fix typo in Rd --- R/data.R | 2 +- man/cs_timeline_data.Rd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/data.R b/R/data.R index 7c093046..e7ff854e 100644 --- a/R/data.R +++ b/R/data.R @@ -157,7 +157,7 @@ #' #' A data.frame containing timeline data. #' -#' @format ## `cs_timeline_data`: data.frame formatted for comsumption by +#' @format ## `cs_timeline_data`: data.frame formatted for consumption by #' `timevis` package. #' #' ```{r } diff --git a/man/cs_timeline_data.Rd b/man/cs_timeline_data.Rd index 34940108..674d40df 100644 --- a/man/cs_timeline_data.Rd +++ b/man/cs_timeline_data.Rd @@ -5,7 +5,7 @@ \alias{cs_timeline_data} \title{Application Timeline Data} \format{ -\subsection{\code{cs_timeline_data}: data.frame formatted for comsumption by}{ +\subsection{\code{cs_timeline_data}: data.frame formatted for consumption by}{ \code{timevis} package. From cd8b547c656307e2d21c78682167cd7b3a028929 Mon Sep 17 00:00:00 2001 From: Aaron Clark <162465159+aclark02-arcus@users.noreply.github.com> Date: Tue, 30 Dec 2025 12:53:26 -0500 Subject: [PATCH 13/14] Update R/fct_test_clinsight.R to use 'meta_data' instead of 'meta' Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- R/fct_test_clinsight.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/fct_test_clinsight.R b/R/fct_test_clinsight.R index 0806bef7..ba570d60 100644 --- a/R/fct_test_clinsight.R +++ b/R/fct_test_clinsight.R @@ -55,7 +55,7 @@ test_clinsight <- function( # tables = app_tables, # outdated arg # all_forms = app_vars$all_forms, # outdated arg form_repeat_name = with( - meta[["table_names"]], + meta_data[["table_names"]], table_name[raw_name == "form_repeat"] ) |> tryCatch(error = \(e) "N") From d0403fd1b304d5fac7c32d92a759b87bba93cb6f Mon Sep 17 00:00:00 2001 From: aclark02-arcus Date: Tue, 30 Dec 2025 10:07:03 -0800 Subject: [PATCH 14/14] whoops, fix a couple of issues copilot caught --- NAMESPACE | 1 + R/data.R | 7 +- R/fct_appdata_summary_tables.R | 2 +- R/mod_plot_efficacy.R | 294 --------------------------------- R/run_app.R | 2 +- dev/app.R | 2 +- man/get_timeline_data.Rd | 1 - man/metadata.Rd | 7 +- 8 files changed, 10 insertions(+), 306 deletions(-) delete mode 100644 R/mod_plot_efficacy.R diff --git a/NAMESPACE b/NAMESPACE index 61c96dc7..33800869 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -26,6 +26,7 @@ export(get_metadata) export(get_raw_csv_data) export(get_review_data) export(get_test_results) +export(get_timeline_data) export(key_columns) export(merge_meta_with_data) export(run_app) diff --git a/R/data.R b/R/data.R index e7ff854e..0361c289 100644 --- a/R/data.R +++ b/R/data.R @@ -99,19 +99,18 @@ #' Application Metadata #' #' A list of data frames and settings containing metadata that will be used for -#' the application. The metadata will be merged with with raw data. It controls +#' the application. The metadata will be merged with raw data. It controls #' the variables that will be used in the application, and in which tab the #' variables will be shown. The goal is that most, if not all, study-specific #' data will be captured in the metadata, leaving the scripts to run the -#' application largely unaltered between studies.See `vignette("Metadata")` for +#' application largely unaltered between studies. See `vignette("Metadata")` for #' in-depth information. #' -#' @format ## `metadata`: A list with `r length(metadata)` objects. +#' @format `metadata`: A list with `r length(metadata)` objects. #' #' @source Can be created with an Excel file. The Excel file format is chosen so #' that the metadata can be changed easily per study. See #' `raw-data/metadata.R` for details. -#' "metadata" diff --git a/R/fct_appdata_summary_tables.R b/R/fct_appdata_summary_tables.R index 5db77adf..5f4a4063 100644 --- a/R/fct_appdata_summary_tables.R +++ b/R/fct_appdata_summary_tables.R @@ -16,7 +16,7 @@ #' treatment item in the timeline. #' #' @return A data frame with timeline data. -#' @keywords internal +#' @export #' get_timeline_data <- function( data, diff --git a/R/mod_plot_efficacy.R b/R/mod_plot_efficacy.R deleted file mode 100644 index 9314d6d0..00000000 --- a/R/mod_plot_efficacy.R +++ /dev/null @@ -1,294 +0,0 @@ -#' plot_efficacy UI Function -#' -#' @description A shiny Module. -#' -#' @param id,input,output,session Internal parameters for {shiny}. -#' -#' @noRd -#' -#' @importFrom shiny NS tagList -mod_plot_efficacy_ui <- function(id) { - ns <- NS(id) - # Create custom class to color navset_card_tab background to white - div( - class = "efficacy-card", - tags$style(HTML( - " - .efficacy-card .card-header { - background-color: #ffffff !important; - } - " - )), - bslib::navset_card_tab( - bslib::nav_panel( - title = "Waterfall Plot", - plotly::plotlyOutput(ns("waterfall_plot")) - ), - bslib::nav_panel( - title = "Spider Plot", - plotly::plotlyOutput(ns("spider_plot")) - ), - full_screen = TRUE - ) - ) -} - -#' plot_efficacy Server Functions -#' -#' @noRd -mod_plot_efficacy_server <- function( - id, - form, - form_data, - form_review_data, - review_type = NULL, - active_subject = NULL -) { - moduleServer(id, function(input, output, session) { - ns <- session$ns - - # Track selected patient (shared between both plots) - selected_patient <- reactiveVal(NULL) - - observeEvent( - { - review_type() - active_subject() - }, - { - rt <- review_type() - as <- active_subject() - - if (!is.null(rt) && !is.null(as)) { - if (rt == "subject") { - # Only update if actually different to force invalidation - if (!identical(selected_patient(), as)) { - selected_patient(as) - } - } else if (rt == "form") { - if (!is.null(selected_patient())) { - selected_patient(NULL) - } - } - } - }, - priority = 100 - ) - - data_p <- reactive({ - req(form_data()) - - form_data() |> - dplyr::mutate( - # Clean HTML - dplyr::across( - .cols = where(is.character), - .fns = \(x) clean_html(x) - ), - # Convert to numeric - dplyr::across( - .cols = c( - `Day in Study`, - Measurement, - `Too Small to Measure`, - `Not Evaluable`, - `Sum of Target Lesion Diameters`, - `Baseline - Sum of Target Lesion Diameters`, - `% Change - TL SOD from Baseline`, - `Nadir`, - `TL SOD Change from Nadir`, - `% Change - TL SOD from Nadir`, - `Best % Change - Sum of Target Lesion Diameters`, - `Best % Change - Sum of Target Lesion Diameters Imputed` - ), - .fns = \(x) as.numeric(x) - ) - ) - }) - - data_wf <- reactive({ - req(data_p()) - data_p() |> - dplyr::select( - subject_id, - `Best % Change - Sum of Target Lesion Diameters`, - `Best RECIST OR` - ) |> - dplyr::distinct() |> - stats::na.omit() - }) - - data_s <- reactive({ - req(data_p()) - data_p() |> - dplyr::select( - subject_id, - `Day in Study`, - `% Change - TL SOD from Baseline`, - `Best RECIST OR` - ) |> - dplyr::mutate( - `Day in Study` = pmax(0, `Day in Study`, na.rm = TRUE) - ) |> - dplyr::distinct() |> - stats::na.omit() - }) - - # Waterfall Plot - output$waterfall_plot <- plotly::renderPlotly({ - req(data_wf()) - - plot_data <- data_wf() - selected <- selected_patient() - - # Modify opacity based on selection - if (!is.null(selected)) { - plot_data$plot_opacity <- ifelse( - plot_data$subject_id == selected, - 1, - 0.2 - ) - } else { - plot_data$plot_opacity <- 1 - } - - arcus.viz::plot_waterfall( - data = plot_data, - id = subject_id, - response = `Best % Change - Sum of Target Lesion Diameters`, - status = `Best RECIST OR`, - static = FALSE, - label_xaxis = "Unique Subject Identifier", - label_yaxis = "Best % Change - Sum of Target Lesion Diameters", - label_legend = "Best RECIST OR", - textposition = "none", - hovertext = rlang::expr( - glue::glue( - " - {label_xaxis}: {subject_id} - {label_yaxis}: {round(`Best % Change - Sum of Target Lesion Diameters`, 2)}% - {label_legend}: {`Best RECIST OR`} - " - ) - ), - colors = c( - "Partial Response (PR)" = "#4DAF4A", - "Progressive Disease (PD)" = "#000000", - "Complete Response (CR)" = "#377EB8", - "Stable Disease (SD)" = "#FFC72C" - ), - opacity = plot_data$plot_opacity, - event_register = "plotly_click", - source = "waterfall" - ) |> - plotly::layout( - title = "Best Percentage Change - Sum of Target Lesion Diameters per Unique Subject Identifier" - ) - }) - - # Spider plot - spider_data <- reactive({ - req(data_s()) - ds <- data_s() |> - dplyr::mutate( - subject_id = as.character(subject_id) # ensure character for matching - ) - - sel <- selected_patient() - - ds$plot_opacity <- if (!is.null(sel)) { - ifelse(ds$subject_id == sel, 1, 0.2) - } else { - 1 - } - ds - }) - output$spider_plot <- plotly::renderPlotly({ - req(data_s()) - sel <- selected_patient() - ds <- data_s() |> - dplyr::arrange(subject_id, `Day in Study`) - - arcus.viz::plot_spider( - data = ds, - id = subject_id, - time = `Day in Study`, - value = `% Change - TL SOD from Baseline`, - color = `Best RECIST OR`, - colors = c( - "Partial Response (PR)" = "#4DAF4A", - "Progressive Disease (PD)" = "#000000", - "Complete Response (CR)" = "#377EB8", - "Stable Disease (SD)" = "#FFC72C" - ), - marker_size = 14, - highlight_id = sel, - highlight_marker_size = 16, - faded_opacity = 0.2, - highlight_opacity = 1, - trace_lines = TRUE, - event_register = "plotly_click", - source = "spider", - ytitle = "% Change - TL SOD from Baseline" - ) - }) - - # Force complete re-render by changing output ID - outputOptions(output, "spider_plot", suspendWhenHidden = TRUE) - - # Click handlers - observeEvent( - plotly::event_data("plotly_click", source = "waterfall"), - { - click_data <- plotly::event_data("plotly_click", source = "waterfall") - if (!is.null(click_data)) { - clicked_patient <- click_data$customdata - golem::cat_dev("Waterfall click - clicked patient:", clicked_patient, "\n") - - if (identical(selected_patient(), clicked_patient)) { - selected_patient(NULL) - } else { - selected_patient(clicked_patient) - } - } - }, - priority = 50 - ) - - observeEvent( - plotly::event_data("plotly_click", source = "spider"), - { - click_data <- plotly::event_data("plotly_click", source = "spider") - golem::cat_dev("Spider click event received!\n") - # golem::cat_dev("Click data:\n") - # print(click_data) - - if (!is.null(click_data) && !is.null(click_data$customdata)) { - clicked_patient <- as.character(click_data$customdata[1]) # Get first element and convert to character - golem::cat_dev("Spider click - clicked patient:", clicked_patient, "\n") - - # Only toggle if clicking the same patient that's already selected - if (identical(selected_patient(), clicked_patient)) { - golem::cat_dev("Deselecting patient\n") - selected_patient(NULL) - } else { - golem::cat_dev("Selecting new patient:", clicked_patient, "\n") - selected_patient(clicked_patient) - } - } - }, - priority = 50, - ignoreNULL = TRUE, - ignoreInit = TRUE - ) - - # Debug selected_patient changes - observeEvent( - selected_patient(), - { - golem::cat_dev("Selected patient is now:", selected_patient(), "\n") - }, - ignoreInit = TRUE - ) - }) -} diff --git a/R/run_app.R b/R/run_app.R index ff117b5d..d3fc2f49 100644 --- a/R/run_app.R +++ b/R/run_app.R @@ -203,7 +203,7 @@ run_app <- function( # app_tables = app_tables, available_data = available_data, timeline_data = timeline_data, - data = data, + # data = data, user_db = user_db, credentials_db = credentials_db, credentials_pwd = credentials_pwd, diff --git a/dev/app.R b/dev/app.R index d21a4b3b..cc95d608 100644 --- a/dev/app.R +++ b/dev/app.R @@ -32,7 +32,7 @@ available_data <- get_available_data( # tables = app_tables, # outdated arg # all_forms = app_vars$all_forms, # outdated arg form_repeat_name = with( - meta[["table_names"]], + metadata[["table_names"]], table_name[raw_name == "form_repeat"] ) |> tryCatch(error = \(e) "N") diff --git a/man/get_timeline_data.Rd b/man/get_timeline_data.Rd index 161567c4..91e46aff 100644 --- a/man/get_timeline_data.Rd +++ b/man/get_timeline_data.Rd @@ -39,4 +39,3 @@ A data frame with timeline data. Function to create timeline data, to be used in a \code{timevis::timeline()} object. } -\keyword{internal} diff --git a/man/metadata.Rd b/man/metadata.Rd index 0b447e3c..3a57c5de 100644 --- a/man/metadata.Rd +++ b/man/metadata.Rd @@ -65,8 +65,7 @@ }\if{html}{\out{
}} } -\subsection{\code{metadata}: A list with 9 objects.}{ -} +\code{metadata}: A list with 9 objects. } \source{ Can be created with an Excel file. The Excel file format is chosen so @@ -92,11 +91,11 @@ application largely unaltered between studies.See \code{vignette("Metadata")} fo in-depth information. A list of data frames and settings containing metadata that will be used for -the application. The metadata will be merged with with raw data. It controls +the application. The metadata will be merged with raw data. It controls the variables that will be used in the application, and in which tab the variables will be shown. The goal is that most, if not all, study-specific data will be captured in the metadata, leaving the scripts to run the -application largely unaltered between studies.See \code{vignette("Metadata")} for +application largely unaltered between studies. See \code{vignette("Metadata")} for in-depth information. } \keyword{datasets}