From b00a009dc4af257d9b44616fb246a7cfd1fb4629 Mon Sep 17 00:00:00 2001 From: Steve Choy Date: Thu, 5 Dec 2024 04:39:57 +0100 Subject: [PATCH] v0.2.11 --- DESCRIPTION | 6 +- NAMESPACE | 2 + NEWS.md | 13 + ...ctions_v_0_2_10.R => functions_v_0_2_11.R} | 37 ++- ...ings_v_0_2_10.R => ui_settings_v_0_2_11.R} | 16 +- README.Rmd | 4 +- README.md | 18 +- docs/404.html | 2 +- docs/LICENSE.html | 2 +- docs/articles/index.html | 2 +- docs/articles/supply-passwords.html | 2 +- docs/authors.html | 2 +- docs/index.html | 6 +- docs/news/index.html | 16 +- docs/pkgdown.yml | 2 +- .../add_linear_regression_formula.html | 4 +- docs/reference/add_watermark.html | 4 +- docs/reference/binary_cat_dist.html | 4 +- docs/reference/calc_summary_stats.html | 4 +- .../reference/calc_summary_stats_as_list.html | 4 +- docs/reference/cdc.expand.html | 2 +- docs/reference/check_and_combine_df.html | 4 +- docs/reference/check_cov_name.html | 4 +- docs/reference/check_cov_name_duplicate.html | 4 +- docs/reference/check_matrix.html | 4 +- docs/reference/code_preamble.html | 2 +- docs/reference/compare_dist_histogram.html | 4 +- .../convert_to_plotly_watermark.html | 4 +- docs/reference/create_alert.html | 4 +- docs/reference/create_value_box.html | 4 +- docs/reference/do_data_page_plot.html | 14 +- docs/reference/drawDetails.watermark.html | 4 +- docs/reference/draw_correlation_plot.html | 4 +- docs/reference/eval_parse.html | 4 +- docs/reference/extract_matrix.html | 4 +- docs/reference/extract_model_params.html | 4 +- docs/reference/general_warning_modal.html | 4 +- docs/reference/generate_dosing_regimens.html | 4 +- docs/reference/generate_log_breaks.html | 4 +- docs/reference/gm_mean.html | 4 +- docs/reference/gm_mean_cv.html | 4 +- docs/reference/index.html | 2 +- docs/reference/lm_eqn.html | 4 +- docs/reference/lm_eqn_old.html | 4 +- docs/reference/lowerFn.html | 4 +- docs/reference/ls_all.html | 2 +- docs/reference/model_examples_list.html | 2 +- docs/reference/model_switch_conditions.html | 2 +- docs/reference/nhanes.filtered.html | 2 +- docs/reference/pct_above_y_at_x.html | 4 +- docs/reference/pd_gompertz_effect.html | 2 +- docs/reference/pdfNCA_wm.html | 4 +- docs/reference/pipe.html | 2 +- docs/reference/pk_adaptive_dosing_int.html | 2 +- docs/reference/pk_seq_first_order.html | 2 +- docs/reference/pknca_table.html | 4 +- docs/reference/pkpd_adaptive_dosing.html | 2 +- docs/reference/plot_data_with_nm.html | 4 +- docs/reference/plot_iiv_data_with_nm.html | 4 +- docs/reference/plot_three_data_with_nm.html | 4 +- docs/reference/print_cov_plot.html | 4 +- docs/reference/print_demog_plots.html | 4 +- docs/reference/quantile_output.html | 4 +- docs/reference/quantize.html | 4 +- docs/reference/reconstruct_matrices.html | 4 +- docs/reference/run_mvp.html | 2 +- docs/reference/run_single_sim.html | 4 +- docs/reference/safely_eval.html | 4 +- docs/reference/safely_parse.html | 4 +- docs/reference/safely_run_single_sim.html | 4 +- docs/reference/sample_age_wt.html | 4 +- docs/reference/sanitize_numeric_input.html | 4 +- docs/reference/smart_x_axis.html | 4 +- docs/reference/split_data_frame.html | 4 +- docs/reference/today_numeric.html | 4 +- docs/reference/update_model_choices.html | 2 +- docs/reference/update_model_object.html | 4 +- docs/reference/update_resistant_popover.html | 4 +- docs/reference/update_variability.html | 4 +- docs/reference/useShinydashboardMVP.html | 4 +- docs/reference/who.expand.html | 2 +- docs/search.json | 2 +- inst/shiny/app.R | 279 ++++++++++++++---- ...ctions_v_0_2_10.R => functions_v_0_2_11.R} | 37 ++- ...ings_v_0_2_10.R => ui_settings_v_0_2_11.R} | 16 +- man/add_linear_regression_formula.Rd | 2 +- man/add_watermark.Rd | 2 +- man/binary_cat_dist.Rd | 2 +- man/calc_summary_stats.Rd | 2 +- man/calc_summary_stats_as_list.Rd | 2 +- man/check_and_combine_df.Rd | 2 +- man/check_cov_name.Rd | 2 +- man/check_cov_name_duplicate.Rd | 2 +- man/check_matrix.Rd | 2 +- man/compare_dist_histogram.Rd | 2 +- man/convert_to_plotly_watermark.Rd | 2 +- man/create_alert.Rd | 2 +- man/create_value_box.Rd | 2 +- man/do_data_page_plot.Rd | 8 +- man/drawDetails.watermark.Rd | 2 +- man/draw_correlation_plot.Rd | 2 +- man/eval_parse.Rd | 2 +- man/extract_matrix.Rd | 2 +- man/extract_model_params.Rd | 2 +- man/general_warning_modal.Rd | 2 +- man/generate_dosing_regimens.Rd | 2 +- man/generate_log_breaks.Rd | 2 +- man/gm_mean.Rd | 2 +- man/gm_mean_cv.Rd | 2 +- man/lm_eqn.Rd | 2 +- man/lm_eqn_old.Rd | 2 +- man/lowerFn.Rd | 2 +- man/pct_above_y_at_x.Rd | 2 +- man/pdfNCA_wm.Rd | 2 +- man/pknca_table.Rd | 2 +- man/plot_data_with_nm.Rd | 2 +- man/plot_iiv_data_with_nm.Rd | 2 +- man/plot_three_data_with_nm.Rd | 2 +- man/print_cov_plot.Rd | 2 +- man/print_demog_plots.Rd | 2 +- man/quantile_output.Rd | 2 +- man/quantize.Rd | 2 +- man/reconstruct_matrices.Rd | 2 +- man/run_single_sim.Rd | 2 +- man/safely_eval.Rd | 2 +- man/safely_parse.Rd | 2 +- man/safely_run_single_sim.Rd | 2 +- man/sample_age_wt.Rd | 2 +- man/sanitize_numeric_input.Rd | 2 +- man/smart_x_axis.Rd | 2 +- man/split_data_frame.Rd | 2 +- man/today_numeric.Rd | 2 +- man/update_model_object.Rd | 2 +- man/update_resistant_popover.Rd | 2 +- man/update_variability.Rd | 2 +- man/useShinydashboardMVP.Rd | 2 +- 136 files changed, 547 insertions(+), 269 deletions(-) rename R/{functions_v_0_2_10.R => functions_v_0_2_11.R} (98%) rename R/{ui_settings_v_0_2_10.R => ui_settings_v_0_2_11.R} (96%) rename inst/shiny/{functions_v_0_2_10.R => functions_v_0_2_11.R} (98%) rename inst/shiny/{ui_settings_v_0_2_10.R => ui_settings_v_0_2_11.R} (96%) diff --git a/DESCRIPTION b/DESCRIPTION index 6db8050..56ac46d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: MVPapp Title: Model Visualization Platform -Version: 0.2.10 +Version: 0.2.11 Authors@R: c( person("Steve", "Choy", email = "steve.choy@outlook.com", role = c("aut", "cre")), person("Jin Gyu", "Kim", role = "aut")) @@ -51,9 +51,9 @@ Suggests: readr, Depends: R (>= 3.5.0) LazyData: true Collate: "utils-pipe.R" - "ui_settings_v_0_2_10.R" + "ui_settings_v_0_2_11.R" "code_templates_v_0_2_10.R" - "functions_v_0_2_10.R" + "functions_v_0_2_11.R" "config.R" "run_mvp.R" "data.R" diff --git a/NAMESPACE b/NAMESPACE index a618dd5..fe5a30d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -48,6 +48,7 @@ export(bspop_do_sim_plotly) export(bspop_dose) export(bspop_dose_value) export(bspop_download_cpp_model) +export(bspop_download_plot) export(bspop_dp_checkbox) export(bspop_generate_model) export(bspop_infdur) @@ -63,6 +64,7 @@ export(bspop_password_github) export(bspop_percentiles) export(bspop_plotly_file_name_label) export(bspop_plotly_width_height) +export(bspop_plotly_width_height_corr) export(bspop_rate) export(bspop_scale_x_axis) export(bspop_seed) diff --git a/NEWS.md b/NEWS.md index 03b8e7f..2630b96 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,16 @@ +# MVPapp 0.2.11 (2024-12-04) + +## Features + +* Support for uploading tab-delimited .txt files on Data Upload, with the option to automatically create ID column. (#9) +* Uses dose column instead of manually entering dose amount for NCA. +* Download Options now support non-interactive plots, with a dedicated "Download Non-Interactive Plot" button. (#11) + +## Bugfixes + +* NCA Clearance unit corrected to be based on the supplied time unit. +* Linear regression is center aligned for ggplots (#10) + # MVPapp 0.2.10 (2024-11-28) ## Features diff --git a/R/functions_v_0_2_10.R b/R/functions_v_0_2_11.R similarity index 98% rename from R/functions_v_0_2_10.R rename to R/functions_v_0_2_11.R index b59eef1..32b162e 100644 --- a/R/functions_v_0_2_10.R +++ b/R/functions_v_0_2_11.R @@ -219,6 +219,8 @@ log10_axis_label[seq(1, length(logbreaks_y_minor), 9)] <- as.character(logbreaks #' @param plot_title Optional plot title #' @param label_size font size for geom_text labels (N=x for boxplots or linear regressions) #' @param discrete_threshold Draws geom_count if there are <= this number of unique Y-values +#' @param boxplot_x_threshold Throws an error when the unique values of x-axis exceeds this number +#' @param error_text_color error text color for element text #' @param debug show debugging messages #' #' @returns a ggplot object @@ -248,6 +250,8 @@ do_data_page_plot <- function(nmd, plot_title, label_size = 3, discrete_threshold = 5, + boxplot_x_threshold = 20, + error_text_color = "#F8766D", debug = FALSE) { if(debug) { message(paste0("Creating data_page_plot")) @@ -268,6 +272,13 @@ do_data_page_plot <- function(nmd, } if(boxplot) { + if(length(unique(nmd[[x_axis]])) > boxplot_x_threshold) { + a <- ggplot2::ggplot() + + ggplot2::labs(title = paste0('ERROR: There are too many X-axis categories (>', boxplot_x_threshold, ') for boxplots.')) + + ggplot2::theme(panel.background = ggplot2::element_blank(), + plot.title = ggplot2::element_text(color = error_text_color)) + return(a) + } nmd[[x_axis]] <- as.factor(nmd[[x_axis]]) if(is.character(nmd[[y_axis]]) || length(unique(nmd[[y_axis]])) <= discrete_threshold ) { # ... or if there are <= discrete_threshold unique values of y-axis @@ -321,12 +332,20 @@ do_data_page_plot <- function(nmd, if(treat_y_axis_as_discrete) { a <- a + - ggplot2::geom_count() + ggplot2::scale_size_area(max_size = 12) + - ggplot2::geom_text(data = df_count, aes(x = .data[[x_axis]], y = .data[[y_axis]], label = paste0(n), size = n, group = NULL), color = "black", vjust = 2, size = label_size) + ggplot2::geom_count() + ggplot2::scale_size_area(max_size = 12) + + if(label_size > 0) { + a <- a + + ggplot2::geom_text(data = df_count, aes(x = .data[[x_axis]], y = .data[[y_axis]], label = paste0(n), size = n, group = NULL), color = "black", vjust = 2, size = label_size) + } + } else { a <- a + - ggplot2::geom_boxplot(varwidth = TRUE) + - ggplot2::geom_text(data = df_count, aes(x = .data[[x_axis]], y = max(nmd[[y_axis]]) * 1.02, label = paste0("N=", n), group = NULL), color = "black", vjust = 2, size = label_size) + ggplot2::geom_boxplot(varwidth = TRUE) + if(label_size > 0) { + a <- a + + ggplot2::geom_text(data = df_count, aes(x = .data[[x_axis]], y = max(nmd[[y_axis]]) * 1.02, label = paste0("N=", n), group = NULL), color = "black", vjust = 2, size = label_size) + } } } else { # end of boxplot check @@ -374,8 +393,10 @@ do_data_page_plot <- function(nmd, max_y <- max(data$y, na.rm = TRUE) a <- a + ggplot2::stat_smooth(ggplot2::aes(group = NULL), method = "lm", formula = y ~ x, se = FALSE, colour = "grey", show.legend = FALSE) - a <- a + ggplot2::geom_text(data = df_stats, aes(label = label, x = med_x, y = max_y, group = NULL, color = NULL), - hjust = 0, vjust = 1, show.legend = FALSE, size = label_size) + if(label_size > 0) { + a <- a + ggplot2::geom_text(data = df_stats, aes(label = label, x = med_x, y = max_y, group = NULL, color = NULL), + hjust = 0.5, vjust = 1, show.legend = FALSE, size = label_size) + } } if (facet_name != "") { @@ -448,6 +469,7 @@ lowerFn <- function(data, mapping, method = "lm", ...) { ## Plots linear regress #' @returns a ggplot object #' @importFrom dplyr distinct select all_of #' @importFrom GGally ggpairs wrap +#' @importFrom ggplot2 theme_bw #' @export #------------------------------------------------------------------------------- @@ -485,7 +507,8 @@ draw_correlation_plot <- function(input_df, corr_plot <- GGally::ggpairs(corr_data_id_trimmed, cardinality_threshold = 30, mapping = mapping, - lower = list(continuous = GGally::wrap(lowerFn, method = "lm"))) + lower = list(continuous = GGally::wrap(lowerFn, method = "lm"))) + + ggplot2::theme_bw() return(corr_plot) } diff --git a/R/ui_settings_v_0_2_10.R b/R/ui_settings_v_0_2_11.R similarity index 96% rename from R/ui_settings_v_0_2_10.R rename to R/ui_settings_v_0_2_11.R index ce2726d..95fc71e 100644 --- a/R/ui_settings_v_0_2_10.R +++ b/R/ui_settings_v_0_2_11.R @@ -54,7 +54,7 @@ bspop_calc_nca <- 'Whenever the above settings are adjusted, a new NCA sh #' @export bspop_dose_value <- '(Optional) Provide a dose amount to derive metrics normalized by dose.' #' @export -bspop_mw_value <- '(Optional) Provide a molecular weight to derive metrics related to Clearance and Volume.' +bspop_mw_value <- '(Optional) Provide a molecular weight to derive metrics related to Clearance and Volume (assumed to be in L).' ## Plotting options #' @export @@ -84,24 +84,26 @@ plot_title_placeholder<- "Insert optional plot title" #' @export select_label_size_label<- "Text Label Size" #' @export -bspop_select_label_size<- "Label sizes are only applicable for linear regression formulae or boxplot counts (N=x)." +bspop_select_label_size<- "Label sizes are only applicable for linear regression formulae or counts (N=x)." #' @export add_data_stat_sum <- 'Median line [dataset]' #' @export -bspop_data_stat_sum <- 'Insert a line connecting median values for grouped observations in equidistant time bins' +bspop_data_stat_sum <- 'Insert a line connecting median values for grouped observations in equidistant time bins for non-boxplots.' #' @export boxplot_label <- 'Boxplot' #' @export bspop_do_boxplot <- 'Boxplot figure assumes the X-axis variable is categorical, the Y-axis variable is continuous, and counts (N) represents the number of unique IDs i.e. usually the baseline value.

Turning off interactive plots may achieve better visual results for Boxplots (Color variable is dodged and boxplot widths are proportional to the square-roots of the number of observations in the groups).' #' @export -bspop_do_data_plotly <- 'Interactive plots using the "plotly" package could take a longer time for big datasets. Turning it off may achieve better visual results for Boxplots.

Note - "Download Options" do not apply when plots are not interactive.' +bspop_do_data_plotly <- 'Interactive plots using the "plotly" package could take a longer time for big datasets. Turning it off may achieve better visual results for Boxplots.'#

Note - "Download Options" do not apply when plots are not interactive.' +#' @export +bspop_download_plot <- 'Adjust output settings in the "Download Options" box below.' #' @export plotly_filename_label <- "Plot name" #' @export -bspop_plotly_file_name_label <- 'The plot can be downloaded by hovering over the plot and clicking on the Camera icon.' +bspop_plotly_file_name_label <- 'The plot can be downloaded by hovering over the plot and clicking on the Camera icon (for interactive plots), or by clicking the Download Plot button (for non-interactive plots).' #' @export plotly_format_label <- "File format" #' @export @@ -110,6 +112,8 @@ plotly_width_label <- "Width (px)" plotly_height_label <- "Height (px)" #' @export bspop_plotly_width_height <- 'Leave empty to use current dimensions.' +#' @export +bspop_plotly_width_height_corr <- 'Leave empty to use current dimensions.

Tip: a larger size (e.g. >5000) is recommended if there are more than a few variables.' ## shinyAce placeholder #' @export @@ -247,7 +251,7 @@ show_model_1_label <- "Show Model 1 (red)" #' @export show_model_2_label <- "Show Model 2 (blue)" #' @export -bspop_do_sim_plotly <- 'Interactive plots using the "plotly" package could take a long time for simulations with lots of data (e.g. from overlaying datasets).

Note - "Download Options" do not apply when plots are not interactive.' +bspop_do_sim_plotly <- 'Interactive plots using the "plotly" package could take a long time for simulations with lots of data (e.g. from overlaying datasets).' #

Note - "Download Options" do not apply when plots are not interactive.' #' @export diff --git a/README.Rmd b/README.Rmd index ab3b1c3..60d6b46 100644 --- a/README.Rmd +++ b/README.Rmd @@ -86,9 +86,9 @@ This is the default landing page when the App is launched. It looks a bit empty ![Camera icon from the plotly toolbar](www/plotlytoolbar.png) -### Uploading NONMEM Datasets and Data Exploration +### Uploading Datasets and Data Exploration -Uploading NONMEM-formatted datasets is supported in the "Data Input" page. Some default cleaning options are applied automatically from the "Built-in Dataset Cleaning Options" box. Further filtering and cleaning may be applied in the code editor on the left hand side. At minimum, the dataset should have the "ID", "TIME", and "DV" columns to be fully supported by the rest of the app. If missing, the user may create / rename these columns using the code editor. +Uploading NONMEM-formatted datasets (.csv) and tab-delimited text files (.txt) is supported in the "Data Input" page. Some default cleaning options are applied automatically from the "Built-in Dataset Cleaning Options" box. Further filtering and cleaning may be applied in the code editor on the left hand side. The dataset should have the "ID", "TIME", and "DV" columns to be fully supported by the rest of the app (e.g. data overlay). At minimum, only the "ID" column is required to support Data Exploration in the Data Input page. If missing, the user may create / rename these columns using the code editor. 1. The filtered dataset (i.e. after passing through the code editor) is shown on the right hand side table. 2. Summary statistics of the data per ID is shown on the second sub tab on the top right hand side. diff --git a/README.md b/README.md index ecd6bc1..0c62309 100644 --- a/README.md +++ b/README.md @@ -138,14 +138,16 @@ alt="Camera icon from the plotly toolbar" /> toolbar -### Uploading NONMEM Datasets and Data Exploration - -Uploading NONMEM-formatted datasets is supported in the “Data Input” -page. Some default cleaning options are applied automatically from the -“Built-in Dataset Cleaning Options” box. Further filtering and cleaning -may be applied in the code editor on the left hand side. At minimum, the -dataset should have the “ID”, “TIME”, and “DV” columns to be fully -supported by the rest of the app. If missing, the user may create / +### Uploading Datasets and Data Exploration + +Uploading NONMEM-formatted datasets (.csv) and tab-delimited text files +(.txt) is supported in the “Data Input” page. Some default cleaning +options are applied automatically from the “Built-in Dataset Cleaning +Options” box. Further filtering and cleaning may be applied in the code +editor on the left hand side. The dataset should have the “ID”, “TIME”, +and “DV” columns to be fully supported by the rest of the app (e.g. data +overlay). At minimum, only the “ID” column is required to support Data +Exploration in the Data Input page. If missing, the user may create / rename these columns using the code editor. 1. The filtered dataset (i.e. after passing through the code editor) is diff --git a/docs/404.html b/docs/404.html index 669b0ab..591f4bb 100644 --- a/docs/404.html +++ b/docs/404.html @@ -20,7 +20,7 @@ MVPapp - 0.2.10 + 0.2.11