Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

init reporter tmc #518

Merged
merged 16 commits into from
Jul 1, 2022
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Imports:
styler,
teal.code (>= 0.1.1),
teal.logger (>= 0.1.0),
teal.reporter (>= 0.1.0),
teal.transform (>= 0.1.1),
teal.widgets (>= 0.1.1),
tern.mmrm (>= 0.1.1),
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### Enhancements
* Reverted missing data checkbox in `tm_t_summary` (encoding and filtering should be separate).
* Implemented a new widget that allows dragging and dropping to select comparison groups.
* Added the `teal.reporter` functionality to the `tm_t_summary`, `tm_g_km`, `tm_t_events`, `tm_t_tte` and `tm_a_mmrm` modules.

### Bug fixes
* Fixed bug in `tm_g_barchart_simple` which prevented graph from being shown.
Expand Down
52 changes: 52 additions & 0 deletions R/tm_a_mmrm.R
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,14 @@ ui_mmrm <- function(id, ...) {
teal.widgets::plot_with_settings_ui(id = ns("mmrm_plot"))
),
encoding = shiny::div(
### Reporter
shiny::tags$div(
teal.reporter::add_card_button_ui(ns("addReportCard")),
teal.reporter::download_report_button_ui(ns("downloadButton")),
teal.reporter::reset_report_button_ui(ns("resetButton"))
),
shiny::tags$br(),
###
shiny::tags$label("Encodings", class = "text-primary"),
teal.transform::datanames_input(a[c("arm_var", "paramcd", "id_var", "visit_var", "cov_var", "aval_var")]),
teal.widgets::panel_group(
Expand Down Expand Up @@ -798,6 +806,7 @@ ui_mmrm <- function(id, ...) {
#' @noRd
srv_mmrm <- function(id,
datasets,
reporter,
dataname,
parentname,
arm_var,
Expand All @@ -814,6 +823,7 @@ srv_mmrm <- function(id,
basic_table_args,
ggplot2_args) {
stopifnot(is_cdisc_data(datasets))
with_reporter <- !missing(reporter) && inherits(reporter, "Reporter")
shiny::moduleServer(id, function(input, output, session) {
teal.code::init_chunks()

Expand Down Expand Up @@ -1403,5 +1413,47 @@ srv_mmrm <- function(id,
code_header = label,
disable_buttons = disable_r_code
)

### REPORTER
if (with_reporter) {
card_fun <- function(comment) {
card <- teal.reporter::TealReportCard$new()
card$set_name("MMRM")
card$append_text("Mixed Model Repeated Measurements (MMRM) analysis", "header2")
card$append_text(
paste0(
"Mixed Models procedure analyzes results from repeated measures designs",
"in which the outcome is continuous and measured at fixed time points"
),
"header3"
)
card$append_text("Filter State", "header3")
card$append_fs(datasets)
card$append_text("Main Element", "header3")
if (!is.null(mmrm_table())) {
card$append_table(mmrm_table())
}
if (!is.null(mmrm_plot_reactive())) {
card$append_plot(mmrm_plot_reactive())
}
Comment on lines +1433 to +1438
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I wonder if we should have the name of the plot/table i.e. the value of the radio button also included in the report)
  2. I can imagine the method used to fit the model - could be useful information from the encoding panel in the report?
  3. What happens if you add to report before you've fitted the model?

Copy link
Contributor Author

@Polkas Polkas Jun 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. We could change the subtitle dynamically.
  2. You mean the Optimization Algorithm? we could add it too.
  3. Card WIll not be added. App is NOT crashed.

The only place I feel encoding could be valuable is MMRM, still in the first table visible after estimation we see most of the important parameters.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Card WIll not be added. App is NOT crashed.

True but you click the Add card button in the modal and nothing happens (i.e. there's no feedback to the user as to what is going on and they have to click cancel)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only place I feel encoding could be valuable is MMRM, still in the first table visible after estimation we see most of the important parameters.

I'm not sure about that - for example in the KM plot in the example we have these fixed:
image but they could be configurable? And their output is not on the plot. Similarly we are stratifying by SEX by default that is not included and can be changed

image

And also these are probably useful:
image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could investigate it tomorrow. For sure is not a part of this PR more a candidate for an issue in the teal.reporter.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stratification, comparison settings would be nice to be added as footnotes as those are non-critical enough to be on the subtitles session

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The redundant click in the MMRM is solved here insightsengineering/teal.reporter#87
I added the try clause and print a proper message if the process failed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks all for work on the MMRM module, please check with me for any larger scale changes on functionality etc.

Also I am wondering if it would be better to split out the MMRM module mid-term (few months) in a separate package. Since then we could split this off the main NEST release and have it shipped separately with mmrm, tern.mmrm, teal.modules.mmrm outside of NEST - no longer limited by infrastructure problems etc.
@pawelru fyi re: our discussion today.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it sounds good to split things up sensibly - my only concern would be as the number of packages we've created grows - we need a proper support model for maintaining/updating/releasing them all - even for trivial fixes - @dinakar29 @pawelru and I'm not clear we have one yet - e.g. internal users will still need these packages available internally (not on old infrastructure of course) and things will break and/or become inconsistent as newer versions of R/R packages are released.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maintaining - better integration tests
updating/releasing - simpler release model

I have chatted a little with Dinakar and I might have an idea for the latter one. But this goes way beyond that PR so let's close this topic not to destroy the review.

if (!comment == "") {
card$append_text("Comment", "header3")
card$append_text(comment)
}
card$append_text("Show R Code", "header3")
card$append_src(paste(get_rcode(
chunks = teal.code::get_chunks_object(parent_idx = 1L),
datasets = datasets,
title = "",
description = ""
), collapse = "\n"))
card
}

teal.reporter::add_card_button_srv("addReportCard", reporter = reporter, card_fun = card_fun)
teal.reporter::download_report_button_srv("downloadButton", reporter = reporter)
teal.reporter::reset_report_button_srv("resetButton", reporter)
}
###
})
}
41 changes: 41 additions & 0 deletions R/tm_g_km.R
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,14 @@ ui_g_km <- function(id, ...) {
)
),
encoding = shiny::div(
### Reporter
shiny::tags$div(
teal.reporter::add_card_button_ui(ns("addReportCard")),
teal.reporter::download_report_button_ui(ns("downloadButton")),
teal.reporter::reset_report_button_ui(ns("resetButton"))
),
shiny::tags$br(),
###
shiny::tags$label("Encodings", class = "text-primary"),
teal.transform::datanames_input(a[c("arm_var", "paramcd", "strata_var", "facet_var", "aval_var", "cnsr_var")]),
teal.transform::data_extract_ui(
Expand Down Expand Up @@ -580,6 +588,7 @@ ui_g_km <- function(id, ...) {
#'
srv_g_km <- function(id,
datasets,
reporter,
dataname,
parentname,
paramcd,
Expand All @@ -594,6 +603,7 @@ srv_g_km <- function(id,
plot_height,
plot_width) {
stopifnot(is_cdisc_data(datasets))
with_reporter <- !missing(reporter) && inherits(reporter, "Reporter")
shiny::moduleServer(id, function(input, output, session) {
teal.code::init_chunks()

Expand Down Expand Up @@ -762,5 +772,36 @@ srv_g_km <- function(id,
),
modal_title = label
)

### REPORTER
if (with_reporter) {
card_fun <- function(comment) {
card <- teal.reporter::TealReportCard$new()
card$set_name("Kaplan Meier Plot")
card$append_text("Kaplan Meier Plot", "header2")
card$append_text("Non-parametric method used to estimate the survival function from lifetime data", "header3")
card$append_text("Filter State", "header3")
card$append_fs(datasets)
card$append_text("Main Element", "header3")
card$append_plot(km_plot())
if (!comment == "") {
card$append_text("Comment", "header3")
card$append_text(comment)
}
card$append_text("Show R Code", "header3")
card$append_src(paste(get_rcode(
chunks = teal.code::get_chunks_object(parent_idx = 1L),
datasets = datasets,
title = "",
description = ""
), collapse = "\n"))
card
}

teal.reporter::add_card_button_srv("addReportCard", reporter = reporter, card_fun = card_fun)
teal.reporter::download_report_button_srv("downloadButton", reporter = reporter)
teal.reporter::reset_report_button_srv("resetButton", reporter)
}
###
})
}
40 changes: 40 additions & 0 deletions R/tm_t_events.R
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,14 @@ ui_t_events_byterm <- function(id, ...) {
teal.widgets::table_with_settings_ui(ns("table"))
),
encoding = shiny::div(
### Reporter
shiny::tags$div(
teal.reporter::add_card_button_ui(ns("addReportCard")),
teal.reporter::download_report_button_ui(ns("downloadButton")),
teal.reporter::reset_report_button_ui(ns("resetButton"))
),
shiny::tags$br(),
###
shiny::tags$label("Encodings", class = "text-primary"),
teal.transform::datanames_input(a[c("arm_var", "hlt", "llt")]),
teal.transform::data_extract_ui(
Expand Down Expand Up @@ -619,6 +627,7 @@ ui_t_events_byterm <- function(id, ...) {
#' @noRd
srv_t_events_byterm <- function(id,
datasets,
reporter,
dataname,
parentname,
event_type,
Expand All @@ -629,6 +638,7 @@ srv_t_events_byterm <- function(id,
label,
basic_table_args) {
stopifnot(is_cdisc_data(datasets))
with_reporter <- !missing(reporter) && inherits(reporter, "Reporter")
shiny::moduleServer(id, function(input, output, session) {
teal.code::init_chunks()

Expand Down Expand Up @@ -757,5 +767,35 @@ srv_t_events_byterm <- function(id,
modal_title = "Event Table",
code_header = label
)

### REPORTER
if (with_reporter) {
card_fun <- function(comment) {
card <- teal.reporter::TealReportCard$new()
card$set_name("Events by Term Table")
card$append_text("Events by Term Table", "header2")
card$append_text("Filter State", "header3")
card$append_fs(datasets)
card$append_text("Main Element", "header3")
card$append_table(table())
if (!comment == "") {
card$append_text("Comment", "header3")
card$append_text(comment)
}
card$append_text("Show R Code", "header3")
card$append_src(paste(get_rcode(
chunks = teal.code::get_chunks_object(parent_idx = 1L),
datasets = datasets,
title = "",
description = ""
), collapse = "\n"))
card
}

teal.reporter::add_card_button_srv("addReportCard", reporter = reporter, card_fun = card_fun)
teal.reporter::download_report_button_srv("downloadButton", reporter = reporter)
teal.reporter::reset_report_button_srv("resetButton", reporter)
}
###
})
}
40 changes: 40 additions & 0 deletions R/tm_t_summary.R
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,14 @@ ui_summary <- function(id, ...) {
teal.widgets::standard_layout(
output = teal.widgets::white_small_well(teal.widgets::table_with_settings_ui(ns("table"))),
encoding = shiny::div(
### Reporter
shiny::tags$div(
teal.reporter::add_card_button_ui(ns("addReportCard")),
teal.reporter::download_report_button_ui(ns("downloadButton")),
teal.reporter::reset_report_button_ui(ns("resetButton"))
),
shiny::tags$br(),
###
shiny::tags$label("Encodings", class = "text-primary"),
teal.transform::datanames_input(a[c("arm_var", "summarize_vars")]),
teal.transform::data_extract_ui(
Expand Down Expand Up @@ -403,6 +411,7 @@ ui_summary <- function(id, ...) {
#' @noRd
srv_summary <- function(id,
datasets,
reporter,
dataname,
parentname,
arm_var,
Expand All @@ -413,6 +422,7 @@ srv_summary <- function(id,
label,
basic_table_args) {
stopifnot(is_cdisc_data(datasets))
with_reporter <- !missing(reporter) && inherits(reporter, "Reporter")
shiny::moduleServer(id, function(input, output, session) {
teal.code::init_chunks()

Expand Down Expand Up @@ -546,5 +556,35 @@ srv_summary <- function(id,
modal_title = "R Code for the current Summary Table",
code_header = label
)

### REPORTER
if (with_reporter) {
card_fun <- function(comment) {
card <- teal.reporter::TealReportCard$new()
card$set_name("Summary Table")
card$append_text("Summary Table", "header2")
card$append_text("Filter State", "header3")
card$append_fs(datasets)
card$append_text("Main Element", "header3")
card$append_table(table())
if (!comment == "") {
card$append_text("Comment", "header3")
card$append_text(comment)
}
card$append_text("Show R Code", "header3")
card$append_src(paste(get_rcode(
chunks = teal.code::get_chunks_object(parent_idx = 1L),
datasets = datasets,
title = "",
description = ""
), collapse = "\n"))
card
}

teal.reporter::add_card_button_srv("addReportCard", reporter = reporter, card_fun = card_fun)
teal.reporter::download_report_button_srv("downloadButton", reporter = reporter)
teal.reporter::reset_report_button_srv("resetButton", reporter)
}
###
})
}
40 changes: 40 additions & 0 deletions R/tm_t_tte.R
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,14 @@ ui_t_tte <- function(id, ...) {
teal.widgets::standard_layout(
output = teal.widgets::white_small_well(teal.widgets::table_with_settings_ui(ns("table"))),
encoding = shiny::div(
### Reporter
shiny::tags$div(
teal.reporter::add_card_button_ui(ns("addReportCard")),
teal.reporter::download_report_button_ui(ns("downloadButton")),
teal.reporter::reset_report_button_ui(ns("resetButton"))
),
shiny::tags$br(),
###
shiny::tags$label("Encodings", class = "text-primary"),
teal.transform::datanames_input(
a[c("arm_var", "paramcd", "aval_var", "cnsr_var", "strata_var", "event_desc_var")]
Expand Down Expand Up @@ -681,6 +689,7 @@ ui_t_tte <- function(id, ...) {
#' @noRd
srv_t_tte <- function(id,
datasets,
reporter,
arm_var,
paramcd,
aval_var,
Expand All @@ -695,6 +704,7 @@ srv_t_tte <- function(id,
label,
basic_table_args) {
stopifnot(is_cdisc_data(datasets))
with_reporter <- !missing(reporter) && inherits(reporter, "Reporter")
shiny::moduleServer(id, function(input, output, session) {
teal.code::init_chunks()

Expand Down Expand Up @@ -878,5 +888,35 @@ srv_t_tte <- function(id,
),
modal_title = label
)

### REPORTER
if (with_reporter) {
card_fun <- function(comment) {
card <- teal.reporter::TealReportCard$new()
card$set_name("Time To Event Table")
card$append_text("Time To Event Table", "header2")
card$append_text("Filter State", "header3")
card$append_fs(datasets)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gogonzo are there implication here using datasets during the teal refactor? Though we will need the state of the filter panel for the report

Copy link
Contributor Author

@Polkas Polkas Jun 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need not only state, we are need the format method. That is why we need to pass here datasets as a whole. This was surprising for me and @mhallal1 to have this FilterData argument here , still we not oppose to it at that moment.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah it's fine for now, I imagine once the state of the filter panel is decoupled from the data then this will need to be changed - but that's ok

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be affected once we decide to push data instead of datasets. This means that we will probably $add_text and $add_metadata directly.

https://github.com/insightsengineering/teal.reporter/blob/66ebb849bc7b8c67412fa1a75a19207637c7f361/R/TealReportCard.R#L44

card$append_text("Main Element", "header3")
card$append_table(table())
if (!comment == "") {
card$append_text("Comment", "header3")
card$append_text(comment)
}
card$append_text("Show R Code", "header3")
card$append_src(paste(get_rcode(
chunks = teal.code::get_chunks_object(parent_idx = 1L),
datasets = datasets,
title = "",
description = ""
), collapse = "\n"))
card
}

teal.reporter::add_card_button_srv("addReportCard", reporter = reporter, card_fun = card_fun)
teal.reporter::download_report_button_srv("downloadButton", reporter = reporter)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that it's not for tmc but rather teal.reporter itself but let me comment that as this is the very first time we can see it in action.
I don't yet feel the need of download from the module window. It's like for online shopping - you add items to your cart and then see the summary and proceed to the checkout. I wonder if removing this could simplify the user journey as well as implementation.

Copy link
Contributor Author

@Polkas Polkas Jun 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we assume to leave the Download/Reset buttons there from the beginning . This gives more flexible journey for an ad-hoc analysis, when sb does not have time to jump into the Previewer. Moreover we assume that more options is better than less.
@kpagacz

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so if we want we can remove the download button here and in the UI for modules without needing to change teal.reporter I think

Copy link
Contributor Author

@Polkas Polkas Jun 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it is as easy as to remove 2 lines of code in the UI and server each (for each tmc module). Still I am not recommending it.

teal.reporter::reset_report_button_srv("resetButton", reporter)
}
###
})
}
3 changes: 3 additions & 0 deletions staged_dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ upstream_repos:
insightsengineering/teal.logger:
repo: insightsengineering/teal.logger
host: https://github.com
insightsengineering/teal.reporter:
repo: insightsengineering/teal.reporter
host: https://github.com
insightsengineering/teal.widgets:
repo: insightsengineering/teal.widgets
host: https://github.com
Expand Down