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
Merged

init reporter tmc #518

merged 16 commits into from
Jul 1, 2022

Conversation

Polkas
Copy link
Contributor

@Polkas Polkas commented Jun 24, 2022

closes #470

depends on insightsengineering/teal.reporter#84 which have to be merge first.

Introduce the teal.reporter functionality to the 5 tmc modules.

follow the guidelines from #505

  • tm_t_summary
  • tm_g_km
  • tm_t_events
  • tm_t_tte
  • tm_a_mmrm

Critical Encoding is not added to any of the modules.
All important encoding seems to be already part of modules table/plot

MMRM module has internal tabPanel with separated elements, plots and tables.
MMRM reporter card could catch only one plot/table at a time (when add card button is clicked).
This comes from the design of the MMRM module, each module plot/table is evaluated separately and have own Show R code. The MMRM card could be added only after the regression model is evaluated.

the with_reporter if condition is a preparation for the future independence of teal modules.

New Issues:

Example:

all 5 modules plus one WITHOUT the reporter (tm_t_coxreg).

library(scda)

ADSL <- synthetic_cdisc_data("latest")$adsl
ADTTE <- synthetic_cdisc_data("latest")$adtte
ADAE <- synthetic_cdisc_data("latest")$adae
ADQS <- synthetic_cdisc_data("latest")$adqs %>%
  dplyr::filter(ABLFL != "Y" & ABLFL2 != "Y") %>%
  dplyr::filter(AVISIT %in% c("WEEK 1 DAY 8", "WEEK 2 DAY 15", "WEEK 3 DAY 22")) %>%
  dplyr::mutate(
    AVISIT = as.factor(AVISIT),
    AVISITN = rank(AVISITN) %>%
      as.factor() %>%
      as.numeric() %>%
      as.factor() # making consecutive numeric factor
  )

arm_ref_comp <- list(
  ACTARMCD = list(
    ref = "ARM B",
    comp = c("ARM A", "ARM C")
  ),
  ARM = list(
    ref = "B: Placebo",
    comp = c("A: Drug X", "C: Combination")
  ),
  ARMCD = list(
    ref = "ARM B",
    comp = c("ARM A", "ARM C")
  )
)

app <- init(
  data = cdisc_data(
    cdisc_dataset("ADSL", ADSL, code = 'ADSL <- synthetic_cdisc_data("latest")$adsl'),
    cdisc_dataset("ADAE", ADAE, code = 'ADAE <- synthetic_cdisc_data("latest")$adae'),
    cdisc_dataset("ADTTE", ADTTE, code = 'ADTTE <- synthetic_cdisc_data("latest")$adtte'),
    cdisc_dataset("ADQS", ADQS,
                  code = 'ADQS <- synthetic_cdisc_data("latest")$adqs %>%
              dplyr::filter(ABLFL != "Y" & ABLFL2 != "Y") %>%
              dplyr::filter(AVISIT %in% c("WEEK 1 DAY 8", "WEEK 2 DAY 15", "WEEK 3 DAY 22")) %>%
              dplyr::mutate(
                AVISIT = as.factor(AVISIT),
                AVISITN = rank(AVISITN) %>%
                  as.factor() %>%
                  as.numeric() %>%
                  as.factor() # making consecutive numeric factor
              )'
    ),
    check = TRUE
  ),
  modules = modules(
    tm_g_km(
      label = "KM PLOT",
      dataname = "ADTTE",
      arm_var = choices_selected(
        variable_choices(ADSL, c("ARM", "ARMCD", "ACTARMCD")),
        "ARM"
      ),
      paramcd = choices_selected(
        value_choices(ADTTE, "PARAMCD", "PARAM"),
        "OS"
      ),
      arm_ref_comp = arm_ref_comp,
      strata_var = choices_selected(
        variable_choices(ADSL, c("SEX", "BMRKR2")),
        "SEX"
      ),
      facet_var = choices_selected(
        variable_choices(ADSL, c("SEX", "BMRKR2")),
        NULL
      )
    ),
    tm_t_summary(
      label = "Demographic Table",
      dataname = "ADSL",
      arm_var = choices_selected(c("ARM", "ARMCD"), "ARM"),
      add_total = TRUE,
      summarize_vars = choices_selected(
        c("SEX", "RACE", "BMRKR2", "EOSDY", "DCSREAS", "AGE"),
        c("SEX", "RACE")
      ),
      useNA = "ifany"
    ),
    tm_a_mmrm(
      label = "MMRM",
      dataname = "ADQS",
      aval_var = choices_selected(c("AVAL", "CHG"), "AVAL"),
      id_var = choices_selected(c("USUBJID", "SUBJID"), "USUBJID"),
      arm_var = choices_selected(c("ARM", "ARMCD"), "ARM"),
      visit_var = choices_selected(c("AVISIT", "AVISITN"), "AVISIT"),
      arm_ref_comp = arm_ref_comp,
      paramcd = choices_selected(
        choices = value_choices(ADQS, "PARAMCD", "PARAM"),
        selected = "FKSI-FWB"
      ),
      cov_var = choices_selected(c("BASE", "AGE", "SEX", "BASE:AVISIT"), NULL)
    ),
    tm_t_events(
      label = "Adverse Event Table",
      dataname = "ADAE",
      arm_var = choices_selected(c("ARM", "ARMCD"), "ARM"),
      llt = choices_selected(
        choices = variable_choices(ADAE, c("AETERM", "AEDECOD")),
        selected = c("AEDECOD")
      ),
      hlt = choices_selected(
        choices = variable_choices(ADAE, c("AEBODSYS", "AESOC")),
        selected = "AEBODSYS"
      ),
      add_total = TRUE,
      event_type = "adverse event"
    ),
    tm_t_tte(
      label = "Time To Event Table",
      dataname = "ADTTE",
      arm_var = choices_selected(
        variable_choices(ADSL, c("ARM", "ARMCD", "ACTARMCD")),
        "ARM"
      ),
      arm_ref_comp = arm_ref_comp,
      paramcd = choices_selected(
        value_choices(ADTTE, "PARAMCD", "PARAM"),
        "OS"
      ),
      strata_var = choices_selected(
        variable_choices(ADSL, c("SEX", "BMRKR2")),
        "SEX"
      ),
      time_points = choices_selected(c(182, 243), 182),
      event_desc_var = choices_selected(
        variable_choices(ADTTE, "EVNTDESC"),
        "EVNTDESC",
        fixed = TRUE
      )
    ),
    tm_t_coxreg(
      label = "Cox Reg.",
      dataname = "ADTTE",
      arm_var = choices_selected(c("ARM", "ARMCD", "ACTARMCD"), "ARM"),
      arm_ref_comp = arm_ref_comp,
      paramcd = choices_selected(
        value_choices(ADTTE, "PARAMCD", "PARAM"), "OS"
      ),
      strata_var = choices_selected(
        c("COUNTRY", "STRATA1", "STRATA2"), "STRATA1"
      ),
      cov_var = choices_selected(
        c("AGE", "BMRKR1", "BMRKR2", "REGION1"), "AGE"
      ),
      multivariate = TRUE
    )
  )
)

shinyApp(ui = app$ui, server = app$server)

@Polkas Polkas added the core label Jun 24, 2022
@Polkas Polkas marked this pull request as ready for review June 27, 2022 14:51
@github-actions
Copy link
Contributor

github-actions bot commented Jun 27, 2022

Unit Tests Summary

    1 files    32 suites   10s ⏱️
140 tests 140 ✔️ 0 💤 0
155 runs  155 ✔️ 0 💤 0

Results for commit 6d4f942.

♻️ This comment has been updated with latest results.

@Polkas Polkas requested review from a team June 28, 2022 11:52
@nikolas-burkoff nikolas-burkoff self-assigned this Jun 28, 2022
@nikolas-burkoff
Copy link
Contributor

@shajoezhu @danielinteractive I'm taking a look at this from a code perspective but I think you guys (or someone in your teams) should have a look as well -> Note the new issues at the top of the PR that @Polkas has already created

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

R/tm_t_tte.R Outdated
}
card$append_text("Show R Code", "header3")
card$append_src(paste(get_rcode(
chunks = session$userData[[session$ns(character(0))]]$chunks,
Copy link
Contributor

Choose a reason for hiding this comment

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

I think there's a function teal.code::get_chunks_object() to get this?

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 tried before the proposed solution and did not work.

Copy link
Contributor

Choose a reason for hiding this comment

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

:(

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah that should work - I am quite surprised that it's not. Can you give another try?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

teal.code::get_chunks_object() vs session$userData[[session$ns(character(0))]]$chunks

Error in get_rcode(chunks = teal.code::get_chunks_object(), datasets = datasets, : No code chunks given

I think I know why teal.code::get_chunks_object() not works. The session$ns is incorrect in the add card module as uses the local session$ns not the one from the tm_module_srv body.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Alternative is usage of chunks = teal.code::get_chunks_object(parent_idx = 1L)

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.

@nikolas-burkoff thanks for the proposal. just update it.

Comment on lines +1432 to +1437
if (!is.null(mmrm_table())) {
card$append_table(mmrm_table())
}
if (!is.null(mmrm_plot_reactive())) {
card$append_plot(mmrm_plot_reactive())
}
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.

Copy link
Contributor

@nikolas-burkoff nikolas-burkoff left a comment

Choose a reason for hiding this comment

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

So from a code and functionality perspective this looks really good.

  • I suspect there will be more things needed in the cards (possibly in footnotes) - @kumamiao @insightsengineering/nest-sme will need to specify what -> Joe and Nina should decide how we are going to do that review - i.e. it could be that we merge this in and there's a separate issue for Nina/SME to review all the tmc modules to request what else is added or it could be done for these modules before merging in.

Not for this PR but:

  • I also suspect there will need to be some changes to what happens with the show R code, I suspect a lot of users will not want a whole huge block of R code between each output when rendering to say pdf/html especially if there's a few hundred lines of pre-processing included in every report card - I can think of a few different approaches:

    • have an option to add echo = FALSE to the R Code markdown chunk
    • only output the code for the module in the card and put the pre-processing code in an appendix/at the beginning of the report
    • have an option when creating the report card whether to include the show r code
    • move all the show r code to an appendix
  • I think there could be other really nice to have bits of functionality users may want which we should capture in the backlog - the sprint review could be a really good time to show people and to get feedback to make sure we make the reporter as useful as possible

Thoughts @kumamiao ?

}

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.

R/tm_t_summary.R Outdated Show resolved Hide resolved
@Polkas Polkas added the blocked label Jun 29, 2022
@Polkas Polkas removed the blocked label Jun 30, 2022
@Polkas
Copy link
Contributor Author

Polkas commented Jun 30, 2022

The PR is now unblocked:)

@gogonzo
Copy link
Contributor

gogonzo commented Jul 1, 2022

I checked example app and run efficacy also. They fail after clicking "add card" (second "add card" after editing comment)

image

@nikolas-burkoff
Copy link
Contributor

I checked example app and run efficacy also. They fail after clicking "add card" (second "add card" after editing comment)

The example at the top of the PR which previously worked for me now fails as well so something has changed somewhere...

@nikolas-burkoff
Copy link
Contributor

ah I needed to merge main into insightsengineering/teal.reporter#84 so it should be all good now @gogonzo

Copy link
Contributor

@gogonzo gogonzo left a comment

Choose a reason for hiding this comment

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

Everything works as expected. No risk of breaking anything as change only adds stuff. We can talk later about the style of the buttons

@Polkas Polkas merged commit a410508 into main Jul 1, 2022
@Polkas Polkas deleted the 470_reporter5@main branch July 1, 2022 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add teal.reporter to 5 tmc modules
6 participants