From 642bee8cf189f206214e8c4826a1fe3a5d5ac6c7 Mon Sep 17 00:00:00 2001 From: jreps Date: Wed, 8 May 2024 22:10:55 -0400 Subject: [PATCH 01/64] estimation module - adding estimation module that includes CM/SCCS/Evidence synthesis --- NAMESPACE | 3 + R/components-helpInfo.R | 2 +- R/estimation-cm-diagnostics.R | 263 +++++++++++++ R/estimation-cohort-method-full-result.R | 163 ++++++++ R/estimation-cohort-method-plots.R | 116 ++++++ R/estimation-cohort-method-results.R | 470 +++++++++++++++++++++++ R/estimation-main.R | 383 ++++++++++++++++++ R/estimation-sccs-diagnostics.R | 255 ++++++++++++ R/estimation-sccs-results-full.R | 427 ++++++++++++++++++++ R/estimation-sccs-results.R | 318 +++++++++++++++ R/report-main.R | 159 +++++--- extras/examples/app.R | 13 + inst/estimation-www/estimation.html | 0 tests/testthat/test-report-main.R | 31 ++ 14 files changed, 2555 insertions(+), 48 deletions(-) create mode 100644 R/estimation-cm-diagnostics.R create mode 100644 R/estimation-cohort-method-full-result.R create mode 100644 R/estimation-cohort-method-plots.R create mode 100644 R/estimation-cohort-method-results.R create mode 100644 R/estimation-main.R create mode 100644 R/estimation-sccs-diagnostics.R create mode 100644 R/estimation-sccs-results-full.R create mode 100644 R/estimation-sccs-results.R create mode 100644 inst/estimation-www/estimation.html create mode 100644 tests/testthat/test-report-main.R diff --git a/NAMESPACE b/NAMESPACE index 37b82f11..1fba30b5 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -65,6 +65,9 @@ export(databaseInformationView) export(datasourcesHelperFile) export(datasourcesServer) export(datasourcesViewer) +export(estimationHelperFile) +export(estimationServer) +export(estimationViewer) export(evidenceSynthesisHelperFile) export(evidenceSynthesisServer) export(evidenceSynthesisViewer) diff --git a/R/components-helpInfo.R b/R/components-helpInfo.R index eae6f807..77f46a3c 100644 --- a/R/components-helpInfo.R +++ b/R/components-helpInfo.R @@ -6,7 +6,7 @@ infoHelperViewer <- function( shinydashboard::box( collapsible = TRUE, - collapsed = FALSE, + collapsed = TRUE, title = shiny::span( shiny::icon("circle-question"), "Help & Information"), width = "100%", shiny::htmlTemplate(helpLocation) diff --git a/R/estimation-cm-diagnostics.R b/R/estimation-cm-diagnostics.R new file mode 100644 index 00000000..c623f314 --- /dev/null +++ b/R/estimation-cm-diagnostics.R @@ -0,0 +1,263 @@ +estimationCmDiagnosticViewer <- function(id=1) { + ns <- shiny::NS(id) + + resultTableViewer(ns("cmDiagnosticsTable")) + +} + + +estimationCmDiagnosticServer <- function( + id, + connectionHandler, + resultDatabaseSettings = list(port = 1), + targetIds, + comparatorIds, + outcomeId +) { + shiny::moduleServer( + id, + function(input, output, session) { + + + + cmDiagnostics <- shiny::reactive({ + estimationGetCmDiagnostics( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = targetIds, + comparatorIds = comparatorIds, + outcomeId = outcomeId + ) + }) + + resultTableServer( + id = "cmDiagnosticsTable", + df = cmDiagnostics, + colDefsInput = estimationGetCmDiagnosticColDefs(), + selectedCols = c( + 'databaseName', + 'analysis', + 'target', + 'comparator', + 'summaryValue' + ) + ) + + + } + ) +} + + +estimationGetCmDiagnostics <- function( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = targetIds, + comparatorIds = comparatorIds, + outcomeId = outcomeId +){ + targetIds <- targetIds() + comparatorIds <- comparatorIds() + outcomeId <- outcomeId() + + sql <- " + SELECT DISTINCT + dmd.cdm_source_abbreviation database_name, + cma.description analysis, + cgcd1.cohort_name target, + cgcd2.cohort_name comparator, + cgcd3.cohort_name outcome, + cmds.max_sdm, + cmds.shared_max_sdm, + cmds.equipoise, + cmds.mdrr, + cmds.ease, + cmds.balance_diagnostic, + cmds.shared_balance_diagnostic, -- added back + cmds.equipoise_diagnostic, + cmds.mdrr_diagnostic, + cmds.ease_diagnostic, + cmds.unblind + FROM + @schema.@cm_table_prefixdiagnostics_summary cmds + INNER JOIN @schema.@cm_table_prefixanalysis cma ON cmds.analysis_id = cma.analysis_id + INNER JOIN @schema.@database_table dmd ON dmd.database_id = cmds.database_id + INNER JOIN @schema.@cg_table_prefixcohort_definition cgcd1 ON cmds.target_id = cgcd1.cohort_definition_id + INNER JOIN @schema.@cg_table_prefixcohort_definition cgcd2 ON cmds.comparator_id = cgcd2.cohort_definition_id + INNER JOIN @schema.@cg_table_prefixcohort_definition cgcd3 ON cmds.outcome_id = cgcd3.cohort_definition_id + + where cgcd1.cohort_definition_id in (@targets) + {@use_comparators}?{and cgcd2.cohort_definition_id in (@comparators)} + and cgcd3.cohort_definition_id in (@outcomes) + {@use_analyses}?{and cma.analysis_id in (@analyses)} + ; + " + + result <- connectionHandler$queryDb( + sql = sql, + schema = resultDatabaseSettings$schema, + cm_table_prefix = resultDatabaseSettings$cmTablePrefix, + cg_table_prefix = resultDatabaseSettings$cgTablePrefix, + database_table = resultDatabaseSettings$databaseTable, + + targets = paste0(targetIds, collapse = ','), + comparators = paste0(comparatorIds, collapse = ','), + outcomes = paste0(outcomeId, collapse = ','), + + use_comparators = T, + use_analyses = F + ) + + # adding percent fail for summary + result$summaryValue <- apply( + X = result[, grep('Diagnostic', colnames(result))], + MARGIN = 1, + FUN = function(x){ + + if(sum(x %in% c('FAIL'))>0){ + return('Fail') + } else if(sum(x %in% c('WARNING')) >0){ + return(sum(x %in% c('WARNING'))) + } else{ + return('Pass') + } + } + ) + + # add summaryValue after outcome + result <- result %>% + dplyr::relocate(.data$summaryValue, .after = .data$outcome) + + return( + result + ) + +} + + +estimationGetCmDiagnosticColDefs <- function(){ + result <- list( + databaseName = reactable::colDef( + header = withTooltip( + "Database", + "The database name" + ), + sticky = "left" + ), + target = reactable::colDef( + header = withTooltip( + "Target", + "The target cohort of interest" + ), + sticky = "left" + ), + comparator = reactable::colDef( + header = withTooltip( + "Comparator", + "The comparator cohort of interest" + ), + sticky = "left" + ), + outcome = reactable::colDef( + show = F + ), + summaryValue = reactable::colDef( + header = withTooltip( + "Diagnostic", + "The overall result of the diagostics" + ), + style = function(value) { + color <- 'orange' + if(is.na(value)){ + color <- 'black' + }else if(value == 'Pass'){ + color <- '#AFE1AF' + }else if(value == 'Fail'){ + color <- '#E97451' + } + list(background = color) + } + ), + analysis = reactable::colDef( + header = withTooltip( + "Analysis", + "The analysis name" + ) + ), + + mdrr = reactable::colDef( + header = withTooltip( + "MDRR", + "The minimum detectible relative risk" + ), + format = reactable::colFormat(digits = 4) + ), + ease = reactable::colDef( + header = withTooltip( + "EASE", + "The expected absolute systematic error" + ), + format = reactable::colFormat(digits = 4) + ), + maxSdm = reactable::colDef( + header = withTooltip( + "Max SDM", + "The maximum absolute standardized difference of mean" + ), + format = reactable::colFormat(digits = 4) + ), + sharedMaxSdm = reactable::colDef( + header = withTooltip( + "Shared Max SDM", + "The maximum absolute standardized difference of mean of the shared balance (shared across outcomes)" + ), + format = reactable::colFormat(digits = 4) + ), + equipoise = reactable::colDef( + header = withTooltip( + "Equipoise", + "The fraction of the study population with a preference score between 0.3 and 0.7" + ), + format = reactable::colFormat(digits = 4) + ), + balanceDiagnostic = reactable::colDef( + header = withTooltip( + "Balance Diagnostic", + "Pass / warning / fail classification of the balance diagnostic (Max SDM)" + ) + ), + mdrrDiagnostic = reactable::colDef( + header = withTooltip( + "MDRR Diagnostic", + "Pass / warning / fail classification of the MDRR diagnostic" + ) + ), + sharedBalanceDiagnostic = reactable::colDef( + header = withTooltip( + "Shared Balance Diagnostic", + "Pass / warning / fail classification of the shared balance diagnostic (Shared Max SDM)" + ) + ), + easeDiagnostic = reactable::colDef( + header = withTooltip( + "Ease Diagnostic", + "Pass / warning / fail classification of the EASE diagnostic" + ) + ), + equipoiseDiagnostic = reactable::colDef( + header = withTooltip( + "Equipoise Diagnostic", + "Pass / warning / fail classification of the equipoise diagnostic" + ) + ), + + unblind = reactable::colDef( + header = withTooltip( + "Unblind", + "If the value is 1 then the diagnostics passed and results can be unblinded" + ) + ) + ) + + return(result) +} \ No newline at end of file diff --git a/R/estimation-cohort-method-full-result.R b/R/estimation-cohort-method-full-result.R new file mode 100644 index 00000000..76987d5c --- /dev/null +++ b/R/estimation-cohort-method-full-result.R @@ -0,0 +1,163 @@ +estimationCmFullResultViewer <- function(id) { + ns <- shiny::NS(id) + + shiny::div( + # add selected settings + + inputSelectionDfViewer( + id = ns("input-selection-df"), + title = 'Result Selected: ' + ), + + shiny::tabsetPanel( + id = ns("fullTabsetPanel"), + type = 'pills', + shiny::tabPanel( + title = "Power", + cohortMethodPowerViewer(ns("power")) + ), + shiny::tabPanel( + title = "Attrition", + cohortMethodAttritionViewer(ns("attrition")) + ), + shiny::tabPanel( + title = "Population characteristics", + cohortMethodPopulationCharacteristicsViewer(ns("popCharacteristics")) + ), + shiny::tabPanel( + title = "Propensity model", + cohortMethodPropensityModelViewer(ns("propensityModel")) + ), + shiny::tabPanel( + title = "Propensity scores", + cohortMethodPropensityScoreDistViewer(ns("propensityScoreDist")) + ), + shiny::tabPanel( + title = "Covariate balance", + cohortMethodCovariateBalanceViewer(ns("covariateBalance")) + ), + shiny::tabPanel( + title = "Systematic error", + cohortMethodSystematicErrorViewer(ns("systematicError")) + ), + shiny::tabPanel( + title = "Kaplan-Meier", + cohortMethodKaplanMeierViewer(ns("kaplanMeier")) + ) + ) + ) + +} + +estimationCmFullResultServer <- function( + id, + connectionHandler, + resultDatabaseSettings, + selectedRow, + actionCount +) { + + shiny::moduleServer( + id, + function(input, output, session) { + + # reset the tab when a new result is selected + shiny::observeEvent(actionCount(), { + shiny::updateTabsetPanel(session, "fullTabsetPanel", selected = "Power") + }) + + modifiedRow <- shiny::reactive({ + selectedRow() %>% + dplyr::select( + "target", + "comparator", + "outcome", + "description", + "cdmSourceAbbreviation" + ) %>% + dplyr::rename( + 'Target' = .data$target, + 'Comparator' = .data$comparator, + 'Outcome' = .data$outcome, + 'Analysis' = .data$description, + 'Database' = .data$cdmSourceAbbreviation + ) + }) + + inputSelectionDfServer( + id = "input-selection-df", + dataFrameRow = modifiedRow, + ncol = 2 + ) + + shiny::observeEvent(selectedRow(),{ + if(!is.null(selectedRow()$unblind)){ + if (selectedRow()$unblind == 1) { + shiny::showTab("fullTabsetPanel", "Kaplan-Meier", session = session) + } else{ + shiny::hideTab("fullTabsetPanel", "Kaplan-Meier", session = session) + } + } + }) + + # selected row: : - reactive list with: psStrategy + + cohortMethodPowerServer( + id = "power", + selectedRow = selectedRow, + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings + ) + + cohortMethodAttritionServer( + id = "attrition", + selectedRow = selectedRow, + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings + ) + + cohortMethodPopulationCharacteristicsServer( + id = "popCharacteristics", + selectedRow = selectedRow, + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings + ) + + cohortMethodPropensityModelServer( + id = "propensityModel", + selectedRow = selectedRow, + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings + ) + + cohortMethodPropensityScoreDistServer( + id = "propensityScoreDist", + selectedRow = selectedRow, + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings + ) + + cohortMethodCovariateBalanceServer( + id = "covariateBalance", + selectedRow = selectedRow, + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings + ) + + cohortMethodSystematicErrorServer( + id = "systematicError", + selectedRow = selectedRow, + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings + ) + + cohortMethodKaplanMeierServer( + id = "kaplanMeier", + selectedRow = selectedRow, + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings + ) + + } + ) +} diff --git a/R/estimation-cohort-method-plots.R b/R/estimation-cohort-method-plots.R new file mode 100644 index 00000000..0caa8684 --- /dev/null +++ b/R/estimation-cohort-method-plots.R @@ -0,0 +1,116 @@ +estimationCmPlotsViewer <- function(id=1) { + ns <- shiny::NS(id) + shiny::plotOutput(ns('esCohortMethodPlot')) +} + + +estimationCmPlotsServer <- function( + id, + connectionHandler, + resultDatabaseSettings = list(port = 1), + cmData +) { + shiny::moduleServer( + id, + function(input, output, session) { + + output$esCohortMethodPlot <- shiny::renderPlot( + estimationCreateCmPlot( + data = cmData + ) + ) + + } + ) +} + +estimationCreateCmPlot <- function(data) { + print('PLOT') + data <- data() + data <- data[!is.na(data$calibratedRr),] + data$database <- data$cdmSourceAbbreviation + + print(data) + if(is.null(data$comparator)){ + return(NULL) + } + + + # TODO create plot for each target + + compText <- data.frame( + comparatorText = paste0('Comp', 1:length(unique(data$comparator))), + comparator = unique(data$comparator) + ) + + data <- merge( + data, + compText, + by = "comparator" + ) + + # make sure bayesian is at top + db <- unique(data$database) + bInd <- grep('bayesian', tolower(db)) + withoutb <- db[-bInd] + b <- db[bInd] + data$database <- factor( + x = data$database, + levels = c(b, sort(withoutb)) + ) + metadata <- data[data$database == b,] + + breaks <- c(0.1, 0.25, 0.5, 1, 2, 4, 6, 8) + title <- sprintf("%s", data$target[1]) + plot <- ggplot2::ggplot( + data = data, + ggplot2::aes(x = .data$calibratedRr, y = .data$comparatorText)) + + ggplot2::geom_vline(xintercept = 1, size = 0.5) + + ggplot2::geom_point(color = "#000088", alpha = 0.8) + + ggplot2::geom_errorbarh( + ggplot2::aes( + xmin = .data$calibratedCi95Lb, + xmax = .data$calibratedCi95Ub + ), + height = 0.5, + color = "#000088", + alpha = 0.8 + ) + + ggplot2::scale_x_log10( + "Effect size (Hazard Ratio)", + breaks = breaks, + labels = breaks + ) + + + # shade the bayesian + ggplot2::geom_rect( + data = metadata, + ggplot2::aes(fill = .data$database), + xmin = -Inf, + xmax = Inf, + ymin = -Inf, + ymax = Inf, + alpha = 0.2 + ) + + + ggplot2::coord_cartesian(xlim = c(0.1, 10)) + + ggplot2::facet_grid(.data$database ~ .data$description) + + ggplot2::ggtitle(title) + + ggplot2::theme( + axis.title.y = ggplot2::element_blank(), + panel.grid.minor = ggplot2::element_blank(), + strip.text.y.right = ggplot2::element_text(angle = 0), + legend.position = "none" + ) + + ggplot2::labs( + caption = paste( + apply( + X = compText, + MARGIN = 1, + FUN = function(x){paste0(paste(substring(x, 1, 50),collapse = ': ', sep=':'), '...')} + ), + collapse = '\n ') + ) + + return(plot) +} diff --git a/R/estimation-cohort-method-results.R b/R/estimation-cohort-method-results.R new file mode 100644 index 00000000..43cd8bc9 --- /dev/null +++ b/R/estimation-cohort-method-results.R @@ -0,0 +1,470 @@ +# @file cohort-method-resultSummary +# +# Copyright 2024 Observational Health Data Sciences and Informatics +# +# This file is part of OhdsiShinyModules +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +estimationCmResultsViewer <- function(id) { + ns <- shiny::NS(id) + + shiny::tabsetPanel( + type = 'hidden', + id = ns('resultPanel'), + + shiny::tabPanel( + title = "Table", + resultTableViewer(ns("resultSummaryTable")) + ), + + shiny::tabPanel( + title = "Results", + shiny::actionButton( + inputId = ns('goBackCmResults'), + label = "Back To Result Summary", + shiny::icon("arrow-left"), + style="color: #fff; background-color: #337ab7; border-color: #2e6da4" + ), + estimationCmFullResultViewer(ns("cmFullResults")) + ) + + ) + + +} + + +estimationCmResultsServer <- function( + id, + connectionHandler, + resultDatabaseSettings, + targetIds, + comparatorIds, + outcomeId +) { + + shiny::moduleServer( + id, + function(input, output, session) { + + shiny::observeEvent( + eventExpr = input$goBackCmResults, + { + shiny::updateTabsetPanel(session, "resultPanel", selected = "Table") + }) + + # extract results from CM tables + cmData <- shiny::reactive({ + estimationGetCmResultData( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = targetIds, + comparatorIds = comparatorIds, + outcomeId = outcomeId + ) + }) + + # extract results from ES tables if tables exist + esData <- shiny::reactive({ + tryCatch( + { + estimationGetCMMetaEstimation( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = targetIds, + outcomeId = outcomeId + ) + }, error = function(e){print('CM ES error');return(NULL)} + ) + }) + + data <- shiny::reactive({ + rbind(cmData(), esData()) + }) + + resultTableOutputs <- resultTableServer( + id = "resultSummaryTable", + df = data, + colDefsInput = estimationGetCmResultSummaryTableColDef(), + addActions = c('results') # TODO wont work for esData + ) + + selectedRow <- shiny::reactiveVal(value = NULL) + shiny::observeEvent(resultTableOutputs$actionCount(), { + if(resultTableOutputs$actionType() == 'results'){ # add an and here to only work for cmData + selectedRow(data()[resultTableOutputs$actionIndex()$index,]) + shiny::updateTabsetPanel(session, "resultPanel", selected = "Results") + } + }) + + estimationCmFullResultServer( + id = "cmFullResults", + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + selectedRow = selectedRow, + actionCount = resultTableOutputs$actionCount + ) + + + return(data) + + } + ) +} + + +estimationGetCmResultSummaryTableColDef <- function(){ + result <- list( + + analysisId = reactable::colDef(show = F), + description = reactable::colDef( + header = withTooltip( + "Analysis", + "The analysis description" + ), + minWidth = 140 + ), + databaseId = reactable::colDef(show = F), + + cdmSourceAbbreviation = reactable::colDef( + header = withTooltip( + "Database", + "The database name" + ) + ), + + targetId = reactable::colDef(show = F), + target = reactable::colDef( + header = withTooltip( + "Target", + "The target cohort of interest" + ), + minWidth = 300 + ), + + comparatorId = reactable::colDef(show = F), + comparator = reactable::colDef( + header = withTooltip( + "Comparator", + "The comparator cohort of interest" + ), + minWidth = 300 + ), + + outcomeId = reactable::colDef(show = F), + outcome = reactable::colDef( + header = withTooltip( + "Outcome", + "The outcome of interest" + ), + minWidth = 300 + ), + + rr = reactable::colDef( + header = withTooltip( + "RR", + "The estimated relative risk (e.g. the hazard ratio)" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ), + + ci95Lb = reactable::colDef( + header = withTooltip( + "Lower 95% CI", + "The lower bound of the 95% confidence internval of the uncalibrated relative risk" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ), + + ci95Ub = reactable::colDef( + header = withTooltip( + "Upper 95% CI", + "The upper bound of the 95% confidence internval of the uncalibrated relative risk" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ), + + p = reactable::colDef( + header = withTooltip( + "p-val", + "The two-sided p-value of the uncalibrated relative risk" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ), + + calibratedRr = reactable::colDef( + header = withTooltip( + "Calibrated RR", + "The calibrated relative risk" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ), + + calibratedCi95Lb = reactable::colDef( + header = withTooltip( + "Calibrated Lower 95% CI", + "The lower bound of the 95% confidence internval of the calibrated relative risk" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ), + + calibratedCi95Ub = reactable::colDef( + header = withTooltip( + "Calibrated Upper 95% CI", + "The upper bound of the 95% confidence internval of the calibrated relative risk" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ), + + calibratedP = reactable::colDef( + header = withTooltip( + "Calibrated p-val", + "The two-sided p-value of the calibrated relative risk" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ), + + logRr = reactable::colDef(show = F), + seLogRr = reactable::colDef(show = F), + targetSubjects = reactable::colDef(show = F), + comparatorSubjects = reactable::colDef(show = F), + targetDays = reactable::colDef(show = F), + comparatorDays = reactable::colDef(show = F), + targetOutcomes = reactable::colDef(show = F), + comparatorOutcomes = reactable::colDef(show = F), + calibratedLogRr = reactable::colDef(show = F), + calibratedSeLogRr = reactable::colDef(show = F), + calibratedSeLogRr = reactable::colDef(show = F), + unblind = reactable::colDef(show = F) + ) + + return(result) +} + +estimationGetCmResultData <- function( + connectionHandler, + resultDatabaseSettings, + targetIds, + comparatorIds, + outcomeId, + runEvidenceSynthesis = F +) { + + targetIds = targetIds() + comparatorIds = comparatorIds() + outcomeId = outcomeId() + + if(is.null(comparatorIds) || is.null(targetIds) || is.null(outcomeId) ){ + return(NULL) + } + + + sql <- " + SELECT + cma.analysis_id, + cma.description description, + dmd.database_id database_id, + dmd.cdm_source_abbreviation cdm_source_abbreviation, + cmr.target_id, + cg1.cohort_name as target, + cmr.outcome_id, + cg2.cohort_name as outcome, + cmr.comparator_id, + cg3.cohort_name as comparator, + case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.rr end rr, + case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.ci_95_lb end ci_95_lb, + case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.ci_95_ub end ci_95_ub, + case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.p end p, + case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.log_rr end log_rr, + case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.se_log_rr end se_log_rr, + cmr.target_subjects, + cmr.comparator_subjects, + cmr.target_days, + cmr.comparator_days, + cmr.target_outcomes, + cmr.comparator_outcomes, + case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.calibrated_rr end calibrated_rr, + case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.calibrated_ci_95_lb end calibrated_ci_95_lb, + case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.calibrated_ci_95_ub end calibrated_ci_95_ub, + case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.calibrated_p end calibrated_p, + case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.calibrated_log_rr end calibrated_log_rr, + case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.calibrated_se_log_rr end calibrated_se_log_rr, + COALESCE(cmds.unblind, 0) unblind +FROM + @schema.@cm_table_prefixanalysis cma + JOIN @schema.@cm_table_prefixresult cmr + on cmr.analysis_id = cma.analysis_id + + JOIN @schema.@database_table dmd + on dmd.database_id = cmr.database_id + + LEFT JOIN @schema.@cm_table_prefixdiagnostics_summary cmds + on cmds.analysis_id = cmr.analysis_id + AND cmds.target_id = cmr.target_id + AND cmds.comparator_id = cmr.comparator_id + AND cmds.outcome_id = cmr.outcome_id + AND cmds.database_id = cmr.database_id + + inner join @schema.@cg_table_prefixcohort_definition cg1 + on cg1.cohort_definition_id = cmr.target_id + + inner join @schema.@cg_table_prefixcohort_definition cg2 + on cg2.cohort_definition_id = cmr.outcome_id + + inner join @schema.@cg_table_prefixcohort_definition cg3 + on cg3.cohort_definition_id = cmr.comparator_id + + where cmr.target_id in (@targets) + {@use_comparators}?{and cmr.comparator_id in (@comparators)} + and cmr.outcome_id in (@outcomes) + ; + " + + result <- connectionHandler$queryDb( + sql = sql, + schema = resultDatabaseSettings$schema, + cm_table_prefix = resultDatabaseSettings$cmTablePrefix, + cg_table_prefix = resultDatabaseSettings$cgTablePrefix, + database_table = resultDatabaseSettings$databaseTable, + + targets = paste0(targetIds, collapse = ','), + comparators = paste0(comparatorIds, collapse = ','), + outcomes = paste0(outcomeId, collapse = ','), + use_comparators = !is.null(comparatorIds), + ) + + return( + result + ) +} + + +estimationGetCMMetaEstimation <- function( + connectionHandler, + resultDatabaseSettings, + targetIds, + outcomeId +){ + targetIds <- targetIds() + outcomeId <- outcomeId() + + sql <- "select + r.analysis_id, + a.description, + 0 as database_id, + ev.evidence_synthesis_description as cdm_source_abbreviation, + r.target_id, + c1.cohort_name as target, + r.outcome_id, + c3.cohort_name as outcome, + r.comparator_id, + c2.cohort_name as comparator, + NULL as rr, + NULL as ci_95_lb, + NULL as ci_95_ub, + NULL as p, + NULL as log_rr, + NULL as se_log_rr, + 0 as target_subjects, + 0 as comparator_subjects, + 0 as target_days, + 0 as comparator_days, + 0 as target_outcomes, + 0 as comparator_outcomes, + r.calibrated_rr, + r.calibrated_ci_95_lb, + r.calibrated_ci_95_ub, + r.calibrated_p, + r.calibrated_log_rr, + r.calibrated_se_log_rr, + 1 unblind + + from + @schema.@es_table_prefixcm_result as r + inner join + @schema.@cm_table_prefixtarget_comparator_outcome as tco + on + r.target_id = tco.target_id and + r.comparator_id = tco.comparator_id and + r.outcome_id = tco.outcome_id + + inner join + + @schema.@es_table_prefixcm_diagnostics_summary as unblind + on + r.analysis_id = unblind.analysis_id and + r.target_id = unblind.target_id and + r.comparator_id = unblind.comparator_id and + r.outcome_id = unblind.outcome_id + + inner join + @schema.@cg_table_prefixcohort_definition as c1 + on c1.cohort_definition_id = r.target_id + + inner join + @schema.@cg_table_prefixcohort_definition as c2 + on c2.cohort_definition_id = r.comparator_id + + inner join + @schema.@cg_table_prefixcohort_definition as c3 + on c3.cohort_definition_id = r.outcome_id + + inner join + @schema.@cm_table_prefixanalysis as a + on a.analysis_id = r.analysis_id + + inner join + @schema.@es_table_prefixanalysis as ev + on ev.evidence_synthesis_analysis_id = r.evidence_synthesis_analysis_id + + where + r.calibrated_rr != 0 and + tco.outcome_of_interest = 1 and + unblind.unblind = 1 and + r.target_id in (@target_ids) and + r.outcome_id = @outcome_id + ;" + + result <- connectionHandler$queryDb( + sql = sql, + schema = resultDatabaseSettings$schema, + cm_table_prefix = resultDatabaseSettings$cmTablePrefix, + cg_table_prefix = resultDatabaseSettings$cgTablePrefix, + es_table_prefix = resultDatabaseSettings$esTablePrefix, + outcome_id = outcomeId, + target_ids = paste0(targetIds, collapse = ',') + ) %>% + dplyr::mutate( + calibratedP = ifelse( + .data$calibratedRr < 1, + computeTraditionalP( + logRr = .data$calibratedLogRr, + seLogRr = .data$calibratedSeLogRr, + twoSided = FALSE, + upper = TRUE + ), + .data$calibratedP / 2) + ) + + return(unique(result)) +} diff --git a/R/estimation-main.R b/R/estimation-main.R new file mode 100644 index 00000000..1eaac499 --- /dev/null +++ b/R/estimation-main.R @@ -0,0 +1,383 @@ +# @file Estimation-main.R +# +# Copyright 2024 Observational Health Data Sciences and Informatics +# +# This file is part of OhdsiShinyModules +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +#' The location of the estimation module helper file +#' +#' @details +#' Returns the location of the characterization helper file +#' +#' @return +#' string location of the characterization helper file +#' +#' @export +estimationHelperFile <- function(){ + fileLoc <- system.file('estimation-www', "estimation.html", package = "OhdsiShinyModules") + return(fileLoc) +} + +#' The module viewer for exploring characterization studies +#' +#' @details +#' The user specifies the id for the module +#' +#' @param id the unique reference id for the module +#' +#' @return +#' The user interface to the characterization viewer module +#' +#' @export +estimationViewer <- function(id=1) { + ns <- shiny::NS(id) + + shinydashboard::box( + status = 'info', + width = '100%', + title = shiny::span( shiny::icon("table"), "Estimation Viewer"), + solidHeader = TRUE, + + # pick a targetId of interest + shiny::uiOutput(ns("targetSelection")), + + inputSelectionDfViewer(id = ns('targetSelected'), title = 'Selected'), + + + # first show diagnostics with: + # database, analysis, pass/fail, viewResult/viewDiagnostic + # extracts from SCCS/CM/Evidence Synthesis + + conditionalPanel( + condition = 'input.targetSelect', + ns = ns, + + shiny::tabsetPanel( + type = 'pills', + id = ns('mainPanel'), + + shiny::tabPanel( + title = 'Diagnostics', + shiny::tabsetPanel( + type = 'pills', + id = ns('diagnosticsPanel') + ) + ), + + shiny::tabPanel( + title = 'Results', + shiny::tabsetPanel( + type = 'pills', + id = ns('resultsPanel') + ) + ), + ) + ) # end conditional panel + + ) + +} + + +#' The module server for exploring estimation studies +#' +#' @details +#' The user specifies the id for the module +#' +#' @param id the unique reference id for the module +#' @param connectionHandler a connection to the database with the results +#' @param resultDatabaseSettings a list containing the characterization result schema, dbms, tablePrefix, databaseTable and cgTablePrefix +#' +#' @return +#' The server for the estimation module +#' +#' @export +estimationServer <- function( + id, + connectionHandler, + resultDatabaseSettings = list(port = 1) +) { + shiny::moduleServer( + id, + function(input, output, session) { + + # this function checks tables exist for the tabs + # and returns the tabs that should be displayed + # as the tables exist + estimationTypes <- getEstimationTypes( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings + ) + + # add the tabs based on results + types <- list( + c("Cohort Method","estimationCmDiagnosticViewer", "estimationCmDiagnostic", "diagnosticsPanel", "Cohort Method"), + c("SCCS", "estimationSccsDiagnosticViewer", "estimationSccsDiagnostic", "diagnosticsPanel", "SCCS"), + c("Cohort Method", "estimationCmResultsViewer", "estimationCmResults", "resultsPanel", "Cohort Method Table"), + c("Cohort Method", "estimationCmPlotsViewer", "estimationCmPlots", "resultsPanel", "Cohort Method Plot"), + c("SCCS", "estimationSccsResultsViewer", "estimationSccsResults", "resultsPanel", "SCCS Table") + ) + selectValD <- T + selectValR <- T + for( type in types){ + if(type[1] %in% estimationTypes){ + shiny::insertTab( + inputId = type[4], + tab = shiny::tabPanel( + title = type[5], + do.call(what = type[2], args = list(id = session$ns(type[3]))) + ), + select = ifelse(type[4] == "diagnosticsPanel", selectValD, selectValR) + ) + if(type[4] == "diagnosticsPanel"){ + selectValD = F + } else{ + selectValR = F + } + } + + } + + + + # use the function in report-main to get parent Ts with all children Ts, the outcomes for the Ts and the Cs + options <- OhdsiShinyModules:::getTandOs( + connectionHandler, + resultDatabaseSettings, + includeCharacterization = F, + includeCohortIncidence = F, + includeCohortMethod = T, + includePrediction = F, + includeSccs = F # slow so turning off + ) + + # Targets + targets <- lapply(options$groupedTs, function(x) x$cohortId) + targets <- unlist(targets) + + # initial outcomes for first T + outcomeDf <- options$tos[[1]] + initialOutcomes <- outcomeDf$outcomeId + names(initialOutcomes ) <- outcomeDf$outcomeName + outcomes <- shiny::reactiveVal() + + shiny::observeEvent(input$targetId,{ + + outcomes(unique( + do.call( + 'rbind', + lapply( + options$groupedTs[[which(targets == input$targetId)]]$subsets$targetId, + function(id){ + if(id %in% names(options$tos)){ + return(options$tos[[which(id == names(options$tos))]]) + } else{ + return(NULL) + } + } + ) + ) + )) + + + if(length(options()$outcomeId)>0){ + outcomeDf <- options() + outcomesVector <- options()$outcomeId + names(outcomesVector) <- options()$outcomeName + + shiny::updateSelectInput( + session = session, + inputId = 'outcomeId', + label = 'Outcome: ', + choices = outcomesVector, + selected = outcomesVector[1] + ) + } + }) + + output$targetSelection <- shiny::renderUI({ + shiny::fluidRow( + shiny::div( + shiny::selectInput( + inputId = session$ns('targetId'), + label = 'Target: ', + choices = targets, + selected = 1, + multiple = FALSE, + selectize = TRUE, + width = NULL, + size = NULL + ), + shiny::selectInput( + inputId = session$ns('outcomeId'), + label = 'Outcome: ', + choices = initialOutcomes, + selected = initialOutcomes[1], + multiple = FALSE, + selectize = TRUE, + width = NULL, + size = NULL + ), + style = 'margin-left: 2%; width: 78%; display: inline-block; vertical-align: middle;' + ), + div( + shiny::actionButton( + inputId = session$ns('targetSelect'), + label = 'Select', + icon = shiny::icon('redo') + ), + style = 'display: inline-block; vertical-align: bottom; margin-bottom: 20px' + ) + ) + }) + + + targetSelected <- shiny::reactiveVal() + comparatorIds <- shiny::reactiveVal() + targetIds <- shiny::reactiveVal() + outcomeId <- shiny::reactiveVal() + + shiny::observeEvent(input$targetSelect, { + + targetSelected( + data.frame( + Target = names(targets)[targets == input$targetId], + Outcome = outcomes()$outcomeName[outcomes()$outcomeId == input$outcomeId] + ) + ) + inputSelectionDfServer( + id = 'targetSelected', + dataFrameRow = targetSelected, + ncol = 1 + ) + + #======================================== + # code to update diagnostics database + #======================================== + # get all the ids that are children of the id selected + targetIdsTemp <- options$groupedTs[[which(targets == input$targetId)]]$subsets$targetId + + comparators <- do.call( + 'rbind', + lapply( + options$groupedTs[[which(targets == input$targetId)]]$subsets$targetId, + function(id){ + if(id %in% names(options$cs)){ + return(options$cs[[which(id == names(options$cs))]]) + } else{ + return(NULL) + } + } + ) + ) + targetIds(targetIdsTemp) + comparatorIds(comparators$comparatorId) + outcomeId(input$outcomeId) + }) + + #======================================= + # SERVERS + #======================================= + estimationCmDiagnosticServer( + id = 'estimationCmDiagnostic', + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = targetIds, + comparatorIds = comparatorIds, + outcomeId = outcomeId + ) + + cmData <- estimationCmResultsServer( + id = 'estimationCmResults', + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = targetIds, + comparatorIds = comparatorIds, + outcomeId = outcomeId + ) + + estimationCmPlotsServer( + id = 'estimationCmPlots', + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + cmData = cmData + ) + + estimationSccsDiagnosticServer( + id = 'estimationSccsDiagnostic', + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = targetIds, + outcomeId = outcomeId + ) + + estimationSccsResultsServer( + id = 'estimationSccsResults', + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = targetIds, + outcomeId = outcomeId + ) + + } + ) +} + + + + +getEstimationTypes <- function( + connectionHandler, + resultDatabaseSettings +){ + + results <- c() + + conn <- DatabaseConnector::connect( + connectionDetails = connectionHandler$connectionDetails + ) + on.exit(DatabaseConnector::disconnect(conn)) + tbls <- DatabaseConnector::getTableNames( + connection = conn, + databaseSchema = resultDatabaseSettings$schema + ) + + # Cohort Method + if(paste0( + resultDatabaseSettings$cmTablePrefix, + c('result') + ) %in% tbls){ + results <- c(results, "Cohort Method") + } + + # SCCS + if(paste0( + resultDatabaseSettings$sccsTablePrefix, + 'result' + ) %in% tbls){ + results <- c(results, "SCCS") + } + + # Evidence Synthesis + if(paste0( + resultDatabaseSettings$esTablePrefix, + 'result' + ) %in% tbls){ + results <- c(results, "Evidence Synthesis") + } + + return(results) +} diff --git a/R/estimation-sccs-diagnostics.R b/R/estimation-sccs-diagnostics.R new file mode 100644 index 00000000..cbe13b52 --- /dev/null +++ b/R/estimation-sccs-diagnostics.R @@ -0,0 +1,255 @@ +estimationSccsDiagnosticViewer <- function(id=1) { + ns <- shiny::NS(id) + resultTableViewer(ns("sccsDiagnosticsTable")) +} + + +estimationSccsDiagnosticServer <- function( + id, + connectionHandler, + resultDatabaseSettings = list(port = 1), + targetIds, + outcomeId +) { + shiny::moduleServer( + id, + function(input, output, session) { + + + + sccsDiagnostics <- shiny::reactive({ + estimationGetSccsDiagnostics( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = targetIds, + outcomeId = outcomeId + ) + }) + + resultTableServer( + id = "sccsDiagnosticsTable", + df = sccsDiagnostics, + colDefsInput = estimationGetSccsDiagnosticColDefs(), + selectedCols = c( + 'databaseName', + 'analysis', + 'target', + 'indication', + 'summaryValue' + ) + ) + + + } + ) +} + + +estimationGetSccsDiagnostics <- function( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = targetIds, + outcomeId = outcomeId +){ + targetIds <- targetIds() + outcomeId <- outcomeId() + + sql <- " + SELECT + d.cdm_source_abbreviation as database_name, + a.description as analysis, + c2.cohort_name as target, + c3.cohort_name as indication, + c.cohort_name as outcome, + cov.covariate_name, + ds.* + FROM @schema.@sccs_table_prefixdiagnostics_summary ds + inner join + @schema.@sccs_table_prefixexposures_outcome_set eos + on ds.exposures_outcome_set_id = eos.exposures_outcome_set_id + inner join + @schema.@cg_table_prefixcohort_definition as c + on c.cohort_definition_id = eos.outcome_id + + INNER JOIN + @schema.@database_table_prefix@database_table d + on d.database_id = ds.database_id + + INNER JOIN + @schema.@sccs_table_prefixanalysis a + on a.analysis_id = ds.analysis_id + + INNER JOIN + @schema.@sccs_table_prefixcovariate cov + on cov.covariate_id = ds.covariate_id and + cov.exposures_outcome_set_id = ds.exposures_outcome_set_id and + cov.analysis_id = ds.analysis_id and + cov.database_id = ds.database_id + + inner join + @schema.@cg_table_prefixcohort_definition as c2 + on cov.era_id = c2.cohort_definition_id + + left join + @schema.@cg_table_prefixcohort_definition as c3 + on eos.nesting_cohort_id = c3.cohort_definition_id + + where + + cov.era_id in (@target_ids) + and eos.outcome_id in (@outcome_ids) + ; + " + result <- connectionHandler$queryDb( + sql, + schema = resultDatabaseSettings$schema, + cg_table_prefix = resultDatabaseSettings$cgTablePrefix, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, + database_table_prefix = resultDatabaseSettings$databaseTablePrefix, + database_table = resultDatabaseSettings$databaseTable, + + target_ids = paste0(targetIds, collapse = ','), + outcome_ids = paste0(outcomeId, collapse = ','), + snakeCaseToCamelCase = TRUE + ) + + result <- result %>% + dplyr::select(-c("analysisId","exposuresOutcomeSetId","databaseId","covariateId")) + + result$summaryValue <- apply( + X = result[, grep('Diagnostic', colnames(result))], + MARGIN = 1, + FUN = function(x){ + + if(sum(x %in% c('FAIL'))>0){ + return('Fail') + } else if(sum(x %in% c('WARNING')) >0){ + return(sum(x %in% c('WARNING'), na.rm = T)) + } else{ + return('Pass') + } + } + ) + + # add summaryValue after outcome + result <- result %>% + dplyr::relocate(.data$summaryValue, .after = .data$outcome) + + return( + result + ) + +} + + + + + +estimationGetSccsDiagnosticColDefs <- function(){ + result <- list( + databaseName = reactable::colDef( + header = withTooltip( + "Database", + "The database name" + ) + ), + target = reactable::colDef( + header = withTooltip( + "Target", + "The target cohort of interest " + ) + ), + outcome = reactable::colDef( + header = withTooltip( + "Outcome", + "The outcome of interest " + ) + ), + summaryValue = reactable::colDef( + header = withTooltip( + "Diagnostic", + "The overall result of the diagostics" + ), + style = function(value) { + color <- 'orange' + if(is.na(value)){ + color <- 'black' + }else if(value == 'Pass'){ + color <- '#AFE1AF' + }else if(value == 'Fail'){ + color <- '#E97451' + } + list(background = color) + } + ), + analysis = reactable::colDef( + header = withTooltip( + "Analysis", + "The analysis name " + ) + ), + covariateName = reactable::colDef( + header = withTooltip( + "Time Period", + "The time period of interest" + ) + ), + mdrr = reactable::colDef( + header = withTooltip( + "mdrr", + "The minimum detectible relative risk" + ) + ), + ease = reactable::colDef( + header = withTooltip( + "ease", + "The ..." + ) + ), + timeTrendP = reactable::colDef( + header = withTooltip( + "timeTrendP", + "The ..." + ) + ), + preExposureP = reactable::colDef( + header = withTooltip( + "preExposureP", + "The ..." + ) + ), + mdrrDiagnostic = reactable::colDef( + header = withTooltip( + "mdrrDiagnostic", + "The ..." + ) + ), + easeDiagnostic = reactable::colDef( + header = withTooltip( + "easeDiagnostic", + "The ..." + ) + ), + timeTrendDiagnostic = reactable::colDef( + header = withTooltip( + "timeTrendDiagnostic", + "The ..." + ) + ), + preExposureDiagnostic = reactable::colDef( + header = withTooltip( + "preExposureDiagnostic", + "The ..." + ) + ), + + unblind = reactable::colDef( + header = withTooltip( + "unblind", + "If the value is 1 then the diagnostics passed and results can be unblinded" + ) + ) + ) + + return(result) +} \ No newline at end of file diff --git a/R/estimation-sccs-results-full.R b/R/estimation-sccs-results-full.R new file mode 100644 index 00000000..73eca306 --- /dev/null +++ b/R/estimation-sccs-results-full.R @@ -0,0 +1,427 @@ +estimationSccsFullResultViewer <- function(id) { + ns <- shiny::NS(id) + + shiny::div( + + # add selection module + inputSelectionDfViewer( + id = ns("input-selection-df"), + title = 'Result Selected' + ), + + shiny::tabsetPanel( + id = ns("fullTabsetPanel"), + type = 'pills', + + shiny::tabPanel( + "Power", + shiny::div(shiny::strong("Table 1."), "For each variable of interest: the number of cases (people with at least one outcome), the number of years those people were observed, the number of outcomes, the number of subjects with at least one exposure, the number of patient-years exposed, the number of outcomes while exposed, and the minimum detectable relative risk (MDRR)."), + resultTableViewer(ns('powerTable')) + ), + shiny::tabPanel( + "Attrition", + shiny::plotOutput(ns("attritionPlot"), width = 600, height = 500), + shiny::div( + shiny::strong("Figure 1."), + "Attrition, showing the number of cases (number of subjects with at least one outcome), and number of outcomes (number of ocurrences of the outcome) after each step in the study.") + ), + shiny::tabPanel( + "Model", + shiny::tabsetPanel( + id = ns("modelTabsetPanel"), + shiny::tabPanel( + "Model coefficients", + shiny::div( + shiny::strong("Table 2."), + "The fitted non-zero coefficent (incidence rate ratio) and 95 percent confidence interval for all variables in the model." + ), + shiny::tableOutput(ns("modelTable")) + ), + shiny::tabPanel( + "Age spline", + shiny::plotOutput(ns("ageSplinePlot")), + shiny::div(shiny::strong("Figure 2a."), "Spline fitted for age.") + ), + shiny::tabPanel( + "Season spline", + shiny::plotOutput(ns("seasonSplinePlot")), + shiny::div(shiny::strong("Figure 2b."), "Spline fitted for season") + ), + shiny::tabPanel( + "Calendar time spline", + shiny::plotOutput(ns("calendarTimeSplinePlot")), + shiny::div(shiny::strong("Figure 2c."), "Spline fitted for calendar time") + ) + ) + ), + shiny::tabPanel( + "Spanning", + shiny::radioButtons(ns("spanningType"), label = "Type:", choices = c("Age", "Calendar time")), + shiny::plotOutput(ns("spanningPlot")), + shiny::div(shiny::strong("Figure 3."), "Number of subjects observed for 3 consecutive months, centered on the indicated month.") + ), + shiny::tabPanel( + "Time trend", + shiny::plotOutput(ns("timeTrendPlot"), height = 600), + shiny::div( + shiny::strong("Figure 4."), + "The ratio of observed to expected outcomes per month. The expected count is computing either assuming a constant rate (bottom plot) or adjusting for calendar time, seasonality, and / or age, as specified in the model (top plot)." + ) + ), + shiny::tabPanel( + "Time to event", + shiny::plotOutput(ns("timeToEventPlot")), + shiny::div( + shiny::strong("Figure 5."), + "The number of events and subjects observed per week relative to the start of the first exposure (indicated by the thick vertical line)." + ) + ), + shiny::tabPanel( + "Event dep. observation", + shiny::plotOutput(ns("eventDepObservationPlot")), + shiny::div(shiny::strong("Figure 6."), "Histograms for the number of months between the first occurrence of the outcome and the end of observation, stratified by whether the end of observation was censored (inferred as not being equal to the end of database time), or uncensored (inferred as having the subject still be observed at the end of database time)." + ) + ), + shiny::tabPanel( + "Systematic error", + shiny::plotOutput(ns("controlEstimatesPlot")), + shiny::div(shiny::strong("Figure 7."), "Systematic error. Effect size estimates for the negative controls (true incidence rate ratio = 1) + and positive controls (true incidence rate ratio > 1), before and after calibration. Estimates below the diagonal dashed + lines are statistically significant (alpha = 0.05) different from the true effect size. A well-calibrated + estimator should have the true effect size within the 95 percent confidence interval 95 percent of times.") + ) + ) + + ) + +} + + +estimationSccsFullResultServer <- function( + id, + connectionHandler, + resultDatabaseSettings, + selectedRow, + actionCount +) { + + shiny::moduleServer( + id, + function(input, output, session) { + + # reset the tab when a new result is selected + shiny::observeEvent(actionCount(), { + shiny::updateTabsetPanel(session, "fullTabsetPanel", selected = "Power") + }) + + modifiedRow <- shiny::reactive({ + selectedRow() %>% + dplyr::select( + "covariateName", + "outcome", + "description", + "databaseName" + ) %>% + dplyr::rename( + 'Outcome' = .data$outcome, + 'Analysis' = .data$description, + 'Database' = .data$databaseName + ) + }) + + inputSelectionDfServer( + id = "input-selection-df", + dataFrameRow = modifiedRow, + ncol = 2 + ) + + powerTable <- shiny::reactive({ + row <- selectedRow() + if (is.null(row)) { + return(NULL) + } else { + resTargetTable <- row %>% + dplyr::mutate(outcomeEvents = ifelse(.data$unblind == 1, .data$outcomeEvents, NA)) %>% + dplyr::select( + "covariateName", + "outcomeSubjects", + "observedDays", + "outcomeEvents", + "covariateSubjects", + "covariateDays", + "covariateOutcomes", + "mdrr" + ) %>% + dplyr::mutate(observedDays = .data$observedDays / 365.25, + covariateDays = .data$covariateDays / 365.25) + + return(resTargetTable) + } + }) + + colDefsInput <- list( + covariateName = reactable::colDef( + header = withTooltip( + "Variable", + "The covariate" + )), + outcomeSubjects = reactable::colDef( + header = withTooltip( + "Cases", + "The number of cases" + )), + observedDays = reactable::colDef( + format = reactable::colFormat(digits = 2), + header = withTooltip( + "Years observed", + "The total years observed" + )), + outcomeEvents = reactable::colDef( + header = withTooltip( + "Outcomes", + "The total number of outcomes" + )), + covariateSubjects = reactable::colDef( + header = withTooltip( + "Persons exposed", + "The total number of people exposed" + )), + covariateDays = reactable::colDef( + format = reactable::colFormat(digits = 2), + header = withTooltip( + "Years exposed", + "The total number of years exposed" + )), + covariateOutcomes = reactable::colDef( + header = withTooltip( + "Outcomes while exposed", + "The total number of outcomes while exposed" + )), + mdrr = reactable::colDef( + format = reactable::colFormat(digits = 4), + header = withTooltip( + "MDRR", + "The minimal detectable relative risk" + )) + ) + + # move these to a different submodule? + resultTableServer( + id = "powerTable", # how is this working without session$ns + df = powerTable, + colDefsInput = colDefsInput + ) + + output$attritionPlot <- shiny::renderPlot({ + + row <- selectedRow() + if (is.null(row)) { + return(NULL) + } else { + attrition <- getSccsAttrition( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + outcomeId = row$outcomeId, + databaseId = row$databaseId, + analysisId = row$analysisId, + covariateId = row$covariateId + ) + drawAttritionDiagram(attrition) + } + }) + + output$modelTable <- shiny::renderTable({ + row <- selectedRow() + if (is.null(row)) { + return(NULL) + } else { + resTargetTable <- getSccsModel( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + exposureId = row$eraId, + outcomeId = row$outcomeId, + databaseId = row$databaseId, + analysisId = row$analysisId + ) + + resTargetTable <- resTargetTable %>% + dplyr::arrange(.data$covariateId) %>% + dplyr::select(-"covariateId") + + colnames(resTargetTable) <- c("Variable", + "IRR", + "LB", + "UB") + return(resTargetTable) + } + }) + + output$timeTrendPlot <- shiny::renderPlot({ + row <- selectedRow() + if (is.null(row)) { + return(NULL) + } else { + timeTrend <- getSccsTimeTrend( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + exposureId = row$eraId, + outcomeId = row$outcomeId, + databaseId = row$databaseId, + analysisId = row$analysisId + ) + + if (all(c(hasData(timeTrend$ratio), hasData(timeTrend$adjustedRatio)))) { + plotTimeTrend(timeTrend) + } else { + plotTimeTrendStability(timeTrend) + } + } + }) + + output$timeToEventPlot <- shiny::renderPlot({ + row <- selectedRow() + if (is.null(row)) { + return(NULL) + } else { + timeToEvent <- getSccsTimeToEvent( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + outcomeId = row$outcomeId, + exposureId = row$eraId, + covariateId = row$covariateId, + databaseId = row$databaseId, + analysisId = row$analysisId + ) + plotTimeToEventSccs(timeToEvent) + } + }) + + output$eventDepObservationPlot <- shiny::renderPlot({ + row <- selectedRow() + if (is.null(row)) { + return(NULL) + } else { + eventDepObservation <- getSccsEventDepObservation( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + outcomeId = row$outcomeId, + databaseId = row$databaseId, + analysisId = row$analysisId + ) + plotEventDepObservation(eventDepObservation) + } + }) + + output$spanningPlot <- shiny::renderPlot({ + row <- selectedRow() + if (is.null(row)) { + return(NULL) + } else { + if (input$spanningType == "Age") { + ageSpanning <- getSccsAgeSpanning( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + outcomeId = row$outcomeId, + databaseId = row$databaseId, + analysisId = row$analysisId + ) + plotSpanning(ageSpanning, type = "age") + } else { + calendarTimeSpanning <- getSccsCalendarTimeSpanning( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + outcomeId = row$outcomeId, + databaseId = row$databaseId, + analysisId = row$analysisId + ) + plotSpanning(calendarTimeSpanning, type = "calendar time") + } + } + }) + + output$ageSplinePlot <- shiny::renderPlot({ + + row <- selectedRow() + if (is.null(row)) { + return(NULL) + } else { + ageSpline <- getSccsSpline( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + outcomeId = row$outcomeId, + databaseId = row$databaseId, + analysisId = row$analysisId, + splineType = "age" + ) + if (nrow(ageSpline) == 0) { + return(NULL) + } + plotAgeSpline(ageSpline) + } + }) + + output$seasonSplinePlot <- shiny::renderPlot({ + row <- selectedRow() + if (is.null(row)) { + return(NULL) + } else { + seasonSpline <- getSccsSpline( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + outcomeId = row$outcomeId, + databaseId = row$databaseId, + analysisId = row$analysisId, + splineType = "season" + ) + if (nrow(seasonSpline) == 0) { + return(NULL) + } + plotSeasonSpline(seasonSpline) + } + }) + + output$calendarTimeSplinePlot <- shiny::renderPlot({ + row <- selectedRow() + if (is.null(row)) { + return(NULL) + } else { + calendarTimeSpline <- getSccsSpline( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + outcomeId = row$outcomeId, + databaseId = row$databaseId, + analysisId = row$analysisId, + splineType = "calendar time" + ) + if (nrow(calendarTimeSpline) == 0) { + return(NULL) + } + plotCalendarTimeSpline(calendarTimeSpline) + } + }) + + output$controlEstimatesPlot <- shiny::renderPlot({ + row <- selectedRow() + if (is.null(row)) { + return(NULL) + } else { + controlEstimates <- getSccsControlEstimates( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + covariateId = row$covariateId, + databaseId = row$databaseId, + analysisId = row$analysisId + ) + plotControlEstimates(controlEstimates) + } + }) + + } + ) +} + + + + + + diff --git a/R/estimation-sccs-results.R b/R/estimation-sccs-results.R new file mode 100644 index 00000000..31192317 --- /dev/null +++ b/R/estimation-sccs-results.R @@ -0,0 +1,318 @@ +estimationSccsResultsViewer <- function(id = "sccs-results") { + ns <- shiny::NS(id) + + shiny::tabsetPanel( + type = 'hidden', + id = ns('resultPanel'), + + shiny::tabPanel( + title = "Table", + resultTableViewer(ns("resultSummaryTable")) + ), + + shiny::tabPanel( + title = "Results", + shiny::actionButton( + inputId = ns('goBackSccsResults'), + label = "Back To Result Summary", + shiny::icon("arrow-left"), + style="color: #fff; background-color: #337ab7; border-color: #2e6da4" + ), + estimationSccsFullResultViewer(ns("sccsFullResults")) + ) + + ) + + + +} + + +estimationSccsResultsServer <- function( + id, + connectionHandler, + resultDatabaseSettings = list(port = 1), + targetIds, + outcomeId +) { + ns <- shiny::NS(id) + + shiny::moduleServer(id, function(input, output, session) { + + shiny::observeEvent( + eventExpr = input$goBackSccsResults, + { + shiny::updateTabsetPanel(session, "resultPanel", selected = "Table") + } + ) + + data <- shiny::reactive({ + estimationGetSccsResults( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + exposureIds = targetIds, + outcomeIds = outcomeId + ) + }) + + # add evidence synth if exists + + resultTableOutputs <- resultTableServer( + id = "resultSummaryTable", + df = data, + colDefsInput = estimationGetSccsResultSummaryTableColDef(), + addActions = c('results') + ) + + selectedRow <- shiny::reactiveVal(value = NULL) + shiny::observeEvent(resultTableOutputs$actionCount(), { + if(resultTableOutputs$actionType() == 'results'){ + selectedRow(data()[resultTableOutputs$actionIndex()$index,]) + shiny::updateTabsetPanel(session, "resultPanel", selected = "Results") + } + }) + + estimationSccsFullResultServer( + id = "sccsFullResults", + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + selectedRow = selectedRow, + actionCount = resultTableOutputs$actionCount + ) + + # return data for plot server + + } + ) +} + + +estimationGetSccsResultSummaryTableColDef <- function(){ + + results <- list( + + databaseId = reactable::colDef(show = F), + covariateId = reactable::colDef(show = F), + eraId = reactable::colDef(show = F), + covariateAnalysisId = reactable::colDef(show = F), + analysisId = reactable::colDef(show = F), + outcomeId = reactable::colDef(show = F), + outcomeSubjects = reactable::colDef(show = F), + outcomeEvents = reactable::colDef(show = F), + outcomeObservationPeriods = reactable::colDef(show = F), + covariateSubjects = reactable::colDef(show = F), + covariateDays = reactable::colDef(show = F), + covariateEras = reactable::colDef(show = F), + covariateOutcomes = reactable::colDef(show = F), + observedDays = reactable::colDef(show = F), + mdrr = reactable::colDef(show = F), + unblind = reactable::colDef(show = F), + + logRr = reactable::colDef(show = F), + seLogRr = reactable::colDef(show = F), + calibratedLogRr = reactable::colDef(show = F), + calibratedSeLogRr = reactable::colDef(show = F), + llr = reactable::colDef(show = F), + + description = reactable::colDef( + filterable = TRUE, + header = withTooltip( + "Analysis", + "Analysis" + ), + minWidth = 300 + ), + databaseName = reactable::colDef( + filterable = TRUE, + header = withTooltip( + "Data source", + "Data source" + )), + outcome = reactable::colDef( + filterable = TRUE, + header = withTooltip( + "Outcome", + "Outcome of interest" + ), + minWidth = 300 + ), + rr = reactable::colDef( + header = withTooltip( + "IRR", + "Incidence rate ratio (uncalibrated)" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ), + ci95Lb = reactable::colDef( + header = withTooltip( + "LB", + "Lower bound of the 95 percent confidence interval (uncalibrated)" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ), + ci95Ub = reactable::colDef( + header = withTooltip( + "UB", + "Upper bound of the 95 percent confidence interval (uncalibrated)" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ), + p = reactable::colDef( + header = withTooltip( + "P", + "Two-sided p-value (uncalibrated)" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ), + calibratedRr = reactable::colDef( + header = withTooltip( + "Cal.IRR", + "Incidence rate ratio (calibrated)" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ), + calibratedCi95Lb = reactable::colDef( + header = withTooltip( + "Cal.LB", + "Lower bound of the 95 percent confidence interval (calibrated)" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ), + calibratedCi95Ub = reactable::colDef( + header = withTooltip( + "Cal.UB", + "Upper bound of the 95 percent confidence interval (calibrated)" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ), + calibratedP = reactable::colDef( + header = withTooltip( + "Cal.P", + "Two-sided p-value (calibrated)" + ), + format = reactable::colFormat(digits = 4), + na = "-" + ) + ) + + return(results) +} + +estimationGetSccsResults <- function(connectionHandler, + resultDatabaseSettings, + exposureIds, + outcomeIds + ) { + exposureIds <- exposureIds() + outcomeIds <- outcomeIds() + print('SCCS main') + print(exposureIds) + print(outcomeIds ) + + sql <- " + SELECT + + ds.cdm_source_abbreviation as database_name, + sr.database_id, + sc.covariate_id, + sc.covariate_name, + sc.era_id, + sc.covariate_analysis_id, + sr.analysis_id, + a.description, + eos.outcome_id, + cg1.cohort_name as outcome, + + sr.outcome_subjects, + sr.outcome_events, + sr.outcome_observation_periods, + sr.covariate_subjects, + sr.covariate_days, + sr.covariate_eras, + sr.covariate_outcomes, + sr.observed_days, + + case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.rr end rr, + case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.ci_95_lb end ci_95_lb, + case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.ci_95_ub end ci_95_ub, + case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.p end p, + case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.log_rr end log_rr, + case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.se_log_rr end se_log_rr, + case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.calibrated_rr end calibrated_rr, + case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.calibrated_ci_95_lb end calibrated_ci_95_lb, + case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.calibrated_ci_95_ub end calibrated_ci_95_ub, + case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.calibrated_p end calibrated_p, + case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.calibrated_log_rr end calibrated_log_rr, + case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.calibrated_se_log_rr end calibrated_se_log_rr, + + case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.llr end llr, + + + sds.mdrr, + --sds.ease, + --sds.time_trend_p, + --sds.pre_exposure_p, + --sds.mdrr_diagnostic, + --sds.ease_diagnostic, + --sds.time_trend_diagnostic, + --sds.pre_exposure_diagnostic, + sds.unblind + + FROM @schema.@sccs_table_prefixresult sr + INNER JOIN + @schema.@database_table_prefix@database_table ds + ON sr.database_id = ds.database_id + INNER JOIN + @schema.@sccs_table_prefixdiagnostics_summary sds ON ( + sds.exposures_outcome_set_id = sr.exposures_outcome_set_id AND + sds.database_id = sr.database_id AND + sds.analysis_id = sr.analysis_id AND + sds.covariate_id = sr.covariate_id + ) + INNER JOIN + @schema.@sccs_table_prefixcovariate sc ON ( + sc.exposures_outcome_set_id = sr.exposures_outcome_set_id AND + sc.database_id = sr.database_id AND + sc.analysis_id = sr.analysis_id AND + sc.covariate_id = sr.covariate_id + ) + INNER JOIN @schema.@sccs_table_prefixexposures_outcome_set eos + ON + eos.exposures_outcome_set_id = sr.exposures_outcome_set_id + INNER JOIN + @schema.@sccs_table_prefixanalysis a + on a.analysis_id = sr.analysis_id + + inner join + @schema.@cg_table_prefixcohort_definition cg1 + on cg1.cohort_definition_id = eos.outcome_id + + WHERE + eos.outcome_id IN (@outcome_ids) + AND sc.era_id IN (@exposure_ids) + ; + " + + results <- connectionHandler$queryDb( + sql, + schema = resultDatabaseSettings$schema, + database_table_prefix = resultDatabaseSettings$databaseTablePrefix, + database_table = resultDatabaseSettings$databaseTable, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, + cg_table_prefix = resultDatabaseSettings$cgTablePrefix, + outcome_ids = paste(outcomeIds, collapse = ','), + exposure_ids = paste(exposureIds, collapse = ','), + snakeCaseToCamelCase = TRUE + ) + + return(results) +} + + diff --git a/R/report-main.R b/R/report-main.R index 6e09d227..fc63cb2a 100644 --- a/R/report-main.R +++ b/R/report-main.R @@ -733,7 +733,12 @@ reportServer <- function( getTandOs <- function( connectionHandler, - resultDatabaseSettings + resultDatabaseSettings, + includeCharacterization = T, + includeCohortIncidence = T, + includeCohortMethod = T, + includePrediction = T, + includeSccs = T ){ # get cohorts @@ -744,38 +749,68 @@ getTandOs <- function( cg_table_prefix = resultDatabaseSettings$cgTablePrefix ) - characterization <- tryCatch( - {nrow(connectionHandler$queryDb( - 'select * from @schema.@c_table_prefixcohort_details limit 1;', - schema = resultDatabaseSettings$schema, - c_table_prefix = resultDatabaseSettings$cTablePrefix - ))>=0}, - error = function(e){return(F)} - ) - cohortIncidence <- tryCatch( - {nrow(connectionHandler$queryDb( - 'select * from @schema.@ci_table_prefixincidence_summary limit 1;', - schema = resultDatabaseSettings$schema, - ci_table_prefix = resultDatabaseSettings$incidenceTablePrefix - ))>=0}, - error = function(e){return(F)} - ) - cohortMethod <- tryCatch( - {nrow(connectionHandler$queryDb( - 'select * from @schema.@cm_table_prefixtarget_comparator_outcome limit 1;', - schema = resultDatabaseSettings$schema, - cm_table_prefix = resultDatabaseSettings$cmTablePrefix - ))>=0}, - error = function(e){return(F)} - ) - prediction <- tryCatch( - {nrow(connectionHandler$queryDb( - 'select * from @schema.@plp_table_prefixmodel_designs limit 1;', - schema = resultDatabaseSettings$schema, - plp_table_prefix = resultDatabaseSettings$plpTablePrefix - ))>=0}, - error = function(e){return(F)} - ) + if(includeCharacterization){ + characterization <- tryCatch( + {nrow(connectionHandler$queryDb( + 'select * from @schema.@c_table_prefixcohort_details limit 1;', + schema = resultDatabaseSettings$schema, + c_table_prefix = resultDatabaseSettings$cTablePrefix + ))>=0}, + error = function(e){return(F)} + ) + } else{ + characterization <- F + } + + if(includeCohortIncidence){ + cohortIncidence <- tryCatch( + {nrow(connectionHandler$queryDb( + 'select * from @schema.@ci_table_prefixincidence_summary limit 1;', + schema = resultDatabaseSettings$schema, + ci_table_prefix = resultDatabaseSettings$incidenceTablePrefix + ))>=0}, + error = function(e){return(F)} + ) + } else{ + cohortIncidence <- F + } + + if(includeCohortMethod){ + cohortMethod <- tryCatch( + {nrow(connectionHandler$queryDb( + 'select * from @schema.@cm_table_prefixtarget_comparator_outcome limit 1;', + schema = resultDatabaseSettings$schema, + cm_table_prefix = resultDatabaseSettings$cmTablePrefix + ))>=0}, + error = function(e){return(F)} + ) + } else{ + cohortMethod <- F + } + + if(includePrediction){ + prediction <- tryCatch( + {nrow(connectionHandler$queryDb( + 'select * from @schema.@plp_table_prefixmodel_designs limit 1;', + schema = resultDatabaseSettings$schema, + plp_table_prefix = resultDatabaseSettings$plpTablePrefix + ))>=0}, + error = function(e){return(F)} + )} else{ + prediction <- F + } + + if(includeSccs){ + sccs <- tryCatch( + {nrow(connectionHandler$queryDb( + 'select * from @schema.@sccs_table_prefixexposures_outcome_set limit 1;', + schema = resultDatabaseSettings$schema, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix + ))>=0}, + error = function(e){return(F)} + )} else{ + sccs <- F + } # get T and O pairs sql <- "select distinct tid, oid from @@ -790,14 +825,14 @@ getTandOs <- function( } {@cohort_incidence} ? { - union + {@characterization}?{union} select distinct TARGET_COHORT_DEFINITION_ID as tid, OUTCOME_COHORT_DEFINITION_ID as oid from @schema.@ci_table_prefixincidence_summary } {@cohort_method} ? { - union + {@cohort_incidence | @characterization}?{union} select distinct TARGET_ID as tid, OUTCOME_ID as oid from @schema.@cm_table_prefixtarget_comparator_outcome where OUTCOME_OF_INTEREST = 1 @@ -805,7 +840,8 @@ getTandOs <- function( } {@prediction} ? { - union + {@cohort_method | @cohort_incidence | @characterization}?{union} + select distinct c1.cohort_definition_id as tid, c2.cohort_definition_id as oid from @schema.@plp_table_prefixmodel_designs md inner join @schema.@plp_table_prefixcohorts c1 @@ -814,6 +850,28 @@ getTandOs <- function( on c2.cohort_id = md.outcome_id } + {@sccs} ? { + {@cohort_method | @cohort_incidence | @characterization | @prediction}?{union} + + SELECT distinct + cov.era_id as tid, + eos.outcome_id as oid + + FROM @schema.@sccs_table_prefixdiagnostics_summary ds + + inner join + @schema.@sccs_table_prefixexposures_outcome_set eos + on ds.exposures_outcome_set_id = eos.exposures_outcome_set_id + + INNER JOIN + @schema.@sccs_table_prefixcovariate cov + on cov.covariate_id = ds.covariate_id and + cov.exposures_outcome_set_id = ds.exposures_outcome_set_id and + cov.analysis_id = ds.analysis_id and + cov.database_id = ds.database_id + + } + ) temp_t_o ;" @@ -824,10 +882,12 @@ getTandOs <- function( ci_table_prefix = resultDatabaseSettings$incidenceTablePrefix, cm_table_prefix = resultDatabaseSettings$cmTablePrefix, plp_table_prefix = resultDatabaseSettings$plpTablePrefix, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, characterization = characterization, cohort_incidence = cohortIncidence, cohort_method = cohortMethod, - prediction = prediction + prediction = prediction, + sccs = sccs ) # add cohort names @@ -873,11 +933,18 @@ getTandOs <- function( cg$subsetDefinitionId[is.na(cg$subsetDefinitionId)] <- 0 if(sum(cg$isSubset == 0) > 0 ){ - parents <- cg[cg$isSubset == 0,] - groupedCohorts <- lapply(1:nrow(parents), function(i){ - x <- parents$cohortDefinitionId[i]; - - if(x %in% unique(res$tid)){ + # + parentChild <- unique( + merge( + x = cg[, c('cohortDefinitionId','subsetParent')], + y = res, + by.x = 'cohortDefinitionId', + by.y = 'tid' + ) + ) + parents <- unique(parentChild$subsetParent) + groupedCohorts <- lapply(1:length(parents), function(i){ + x <- parents[i]; list( cohortId = x, cohortName = cg$cohortName[cg$cohortDefinitionId == x], @@ -886,15 +953,13 @@ getTandOs <- function( targetName = cg$cohortName[cg$subsetParent == x], subsetId = cg$subsetDefinitionId[cg$subsetParent == x] ) - ) - }else{ - return(NULL) - }; + ); }) - names(groupedCohorts) <- parents$cohortName + names(groupedCohorts) <- unlist(lapply(groupedCohorts, function(x){x$cohortName})) }} # get comparators + cs <- NULL if(cohortMethod){ comps <- connectionHandler$queryDb( 'select distinct target_id, comparator_id from diff --git a/extras/examples/app.R b/extras/examples/app.R index 0c354deb..38a0188e 100644 --- a/extras/examples/app.R +++ b/extras/examples/app.R @@ -20,12 +20,25 @@ if(!dir.exists('./drivers')){ connectionDetails <- OhdsiShinyModules::getExampleConnectionDetails() schema <- "main" +est <- ShinyAppBuilder::createModuleConfig( + moduleId = 'estimation', + tabName = 'Estimation', + shinyModulePackage = 'OhdsiShinyModules', + moduleUiFunction = 'estimationViewer', + moduleServerFunction = 'estimationServer', + moduleInfoBoxFile = 'esimationHelperFile()', + moduleIcon = 'list' + ) + # Specify the config - create a new one and then add # each shiny module you want to include config <- initializeModuleConfig() %>% addModuleConfig( createDefaultAboutConfig() ) %>% + addModuleConfig( + est + ) %>% addModuleConfig( createDefaultDatasourcesConfig() ) %>% diff --git a/inst/estimation-www/estimation.html b/inst/estimation-www/estimation.html new file mode 100644 index 00000000..e69de29b diff --git a/tests/testthat/test-report-main.R b/tests/testthat/test-report-main.R new file mode 100644 index 00000000..1b9e235a --- /dev/null +++ b/tests/testthat/test-report-main.R @@ -0,0 +1,31 @@ +context("report-main") + +shiny::testServer(reportServer, args = list( + id = "testReportServer", + connectionHandler = connectionHandlerEs, + resultDatabaseSettings = resultDatabaseSettingsEs#, + #server = Sys.getenv("RESULTS_SERVER"), + #username = Sys.getenv("RESULTS_USER"), + #password = Sys.getenv("RESULTS_PASSWORD"), + #dbms = "postgresql" +), { + + # input$cmTargetNext + # input$cmTargetPrevious + # input$comparatorNext + # input$comparatorPrevious + # input$outcomeNext + # input$outcomePrevious + # input$generatePrevious + + session$setInputs(cmTargetNext = TRUE) + session$setInputs(cmTargetPrevious = TRUE) + +}) + +test_that("Test report ui", { + # Test ui + ui <- reportViewer() + checkmate::expect_list(ui) + checkmate::expect_file_exists(reportHelperFile()) +}) From 8b1b3ad96a6d1a66e5d619336f0a43ba7d0e4485 Mon Sep 17 00:00:00 2001 From: jreps Date: Thu, 9 May 2024 14:49:19 -0400 Subject: [PATCH 02/64] estimation module updates - adding evidence synth into SCCS - adding plots for SCCS and CM --- R/estimation-cohort-method-plots.R | 79 ++++-- R/estimation-main.R | 12 +- R/estimation-sccs-plots.R | 150 +++++++++++ R/estimation-sccs-results-full.R | 402 ++++++++++++++++++++++++++--- R/estimation-sccs-results.R | 171 +++++++++++- 5 files changed, 748 insertions(+), 66 deletions(-) create mode 100644 R/estimation-sccs-plots.R diff --git a/R/estimation-cohort-method-plots.R b/R/estimation-cohort-method-plots.R index 0caa8684..b90860c5 100644 --- a/R/estimation-cohort-method-plots.R +++ b/R/estimation-cohort-method-plots.R @@ -1,6 +1,9 @@ estimationCmPlotsViewer <- function(id=1) { ns <- shiny::NS(id) - shiny::plotOutput(ns('esCohortMethodPlot')) + shinyWidgets::addSpinner( + shiny::plotOutput(ns('esCohortMethodPlot')), + spin = 'rotating-plane' + ) } @@ -14,10 +17,18 @@ estimationCmPlotsServer <- function( id, function(input, output, session) { + height <- shiny::reactive({ + if(is.null(cmData()$target)){ + return(100) + } + length(unique(cmData()$target))*250 + 250 + }) + output$esCohortMethodPlot <- shiny::renderPlot( estimationCreateCmPlot( data = cmData - ) + ), + height = height ) } @@ -36,16 +47,20 @@ estimationCreateCmPlot <- function(data) { } - # TODO create plot for each target - - compText <- data.frame( - comparatorText = paste0('Comp', 1:length(unique(data$comparator))), - comparator = unique(data$comparator) + renameDf <- data.frame( + shortName = paste0( + 1:length(unique(data$comparator)), + ') ', + substring(sort(unique(data$comparator)), 1,50), + '...' + ), + comparator = sort(unique(data$comparator)) ) + data <- merge( data, - compText, + renameDf, by = "comparator" ) @@ -61,10 +76,31 @@ estimationCreateCmPlot <- function(data) { metadata <- data[data$database == b,] breaks <- c(0.1, 0.25, 0.5, 1, 2, 4, 6, 8) - title <- sprintf("%s", data$target[1]) - plot <- ggplot2::ggplot( - data = data, - ggplot2::aes(x = .data$calibratedRr, y = .data$comparatorText)) + + + ### Add table above the graph + renameDf$comparator <- sapply( + strwrap(renameDf$comparator, width = 150, simplify = FALSE), + paste, + collapse = "\n" + ) + + tt <- gridExtra::ttheme_default( + base_size = 8, + colhead=list(fg_params = list(parse=TRUE)) + ) + tbl <- gridExtra::tableGrob( + renameDf, + rows=NULL, + theme=tt + ) + plotList <- list(tbl) # adding table first + + for(target in unique(data$target)){ # per targets + + title <- sprintf("%s", target) + plotList[[length(plotList) + 1]] <- ggplot2::ggplot( + data = data %>% dplyr::filter(.data$target == !!target), + ggplot2::aes(x = .data$calibratedRr, y = .data$shortName)) + ggplot2::geom_vline(xintercept = 1, size = 0.5) + ggplot2::geom_point(color = "#000088", alpha = 0.8) + ggplot2::geom_errorbarh( @@ -84,7 +120,7 @@ estimationCreateCmPlot <- function(data) { # shade the bayesian ggplot2::geom_rect( - data = metadata, + data = metadata %>% dplyr::filter(.data$target == !!target), ggplot2::aes(fill = .data$database), xmin = -Inf, xmax = Inf, @@ -101,16 +137,13 @@ estimationCreateCmPlot <- function(data) { panel.grid.minor = ggplot2::element_blank(), strip.text.y.right = ggplot2::element_text(angle = 0), legend.position = "none" - ) + - ggplot2::labs( - caption = paste( - apply( - X = compText, - MARGIN = 1, - FUN = function(x){paste0(paste(substring(x, 1, 50),collapse = ': ', sep=':'), '...')} - ), - collapse = '\n ') - ) + ) + } + + plot <- do.call( + gridExtra::grid.arrange, + list(grobs = plotList, ncol =1) + ) return(plot) } diff --git a/R/estimation-main.R b/R/estimation-main.R index 1eaac499..9c61d895 100644 --- a/R/estimation-main.R +++ b/R/estimation-main.R @@ -128,7 +128,8 @@ estimationServer <- function( c("SCCS", "estimationSccsDiagnosticViewer", "estimationSccsDiagnostic", "diagnosticsPanel", "SCCS"), c("Cohort Method", "estimationCmResultsViewer", "estimationCmResults", "resultsPanel", "Cohort Method Table"), c("Cohort Method", "estimationCmPlotsViewer", "estimationCmPlots", "resultsPanel", "Cohort Method Plot"), - c("SCCS", "estimationSccsResultsViewer", "estimationSccsResults", "resultsPanel", "SCCS Table") + c("SCCS", "estimationSccsResultsViewer", "estimationSccsResults", "resultsPanel", "SCCS Table"), + c("SCCS", "estimationSccsPlotsViewer", "estimationSccsPlots", "resultsPanel", "SCCS Plot") ) selectValD <- T selectValR <- T @@ -324,7 +325,7 @@ estimationServer <- function( outcomeId = outcomeId ) - estimationSccsResultsServer( + sccsData <- estimationSccsResultsServer( id = 'estimationSccsResults', connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, @@ -332,6 +333,13 @@ estimationServer <- function( outcomeId = outcomeId ) + estimationSccsPlotsServer( + id = 'estimationSccsPlots', + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + sccsData = sccsData + ) + } ) } diff --git a/R/estimation-sccs-plots.R b/R/estimation-sccs-plots.R new file mode 100644 index 00000000..40afc902 --- /dev/null +++ b/R/estimation-sccs-plots.R @@ -0,0 +1,150 @@ +estimationSccsPlotsViewer <- function(id=1) { + ns <- shiny::NS(id) + shinyWidgets::addSpinner( + output = shiny::plotOutput(ns('esSccsPlot')), + spin = 'rotating-plane' + ) +} + + +estimationSccsPlotsServer <- function( + id, + connectionHandler, + resultDatabaseSettings = list(port = 1), + sccsData +) { + shiny::moduleServer( + id, + function(input, output, session) { + + height <- shiny::reactive({ + if(is.null(sccsData()$indication)){ + return(100) + } + length(unique(sccsData()$indication))*200 + 200 + }) + + output$esSccsPlot <- shiny::renderPlot( + estimationCreateSccsPlot( + data = sccsData + ), + height = height + ) + + } + ) +} + +estimationCreateSccsPlot <- function(data) { + data <- data() + data <- data[!is.na(data$calibratedRr),] + data$database <- data$databaseName + data$type <- data$covariateName + data$indication[is.null(data$indication)] <- 'no indication' + data$indication[is.na(data$indication)] <- 'no indication' + + if(is.null(data)){ + return(NULL) + } + + # change the description to add at bottom + renameDf <- data.frame( + shortName = paste0( + 1:length(unique(data$description)), + ') ', + substring(sort(unique(data$description)), 1, 15), + '...' + ), + description = sort(unique(data$description)) + ) + + data <- merge( + x = data, + y = renameDf, + by = 'description' + ) + + # make sure bayesian is at top + db <- unique(data$database) + bInd <- grep('bayesian', tolower(db)) + withoutb <- db[-bInd] + b <- db[bInd] + data$database <- factor( + x = data$database, + levels = c(b, sort(withoutb)) + ) + metadata <- data[data$database == b,] + + breaks <- c(0.1, 0.25, 0.5, 1, 2, 4, 6, 8) + + # TODO loop over target-indications pairs + + ### Add table above the graph + renameDf$description <- sapply( + strwrap(renameDf$description, width = 50, simplify = FALSE), + paste, + collapse = "\n" + ) + + tt <- gridExtra::ttheme_default( + base_size = 8, + colhead=list(fg_params = list(parse=TRUE)) + ) + tbl <- gridExtra::tableGrob( + renameDf, + rows=NULL, + theme=tt + ) + plotList <- list(tbl) # adding table first + + for(indication in unique(data$indication)){ # TODO do indication + target combo? + plotList[[length(plotList)+1]] <- ggplot2::ggplot( + data = data %>% dplyr::filter(.data$indication == !!indication), #restrict to indication + ggplot2::aes(x = .data$calibratedRr, y = .data$type) + ) + + ggplot2::geom_vline(xintercept = 1, size = 0.5) + + ggplot2::geom_point(color = "#000088", alpha = 0.8) + + ggplot2::geom_errorbarh( + ggplot2::aes( + xmin = .data$calibratedCi95Lb, + xmax = .data$calibratedCi95Ub + ), + height = 0.5, + color = "#000088", + alpha = 0.8 + ) + + ggplot2::scale_x_log10( + "Effect size (Incidence Rate Ratio)", + breaks = breaks, + labels = breaks + ) + + + # shade the bayesian + ggplot2::geom_rect( + data = metadata %>% dplyr::filter(.data$indication == !!indication), + ggplot2::aes(fill = .data$database), + xmin = -Inf, + xmax = Inf, + ymin = -Inf, + ymax = Inf, + alpha = 0.2 + ) + + + ggplot2::coord_cartesian(xlim = c(0.1, 10)) + + ggplot2::facet_grid(.data$database ~ .data$shortName) + + ggplot2::ggtitle(indication) + + ggplot2::theme( + axis.title.y = ggplot2::element_blank(), + panel.grid.minor = ggplot2::element_blank(), + strip.text.y.right = ggplot2::element_text(angle = 0), + legend.position = "none" + ) +} + + plot <- do.call( + gridExtra::grid.arrange, + list(grobs = plotList, ncol =1) + ) + + return(plot) +} diff --git a/R/estimation-sccs-results-full.R b/R/estimation-sccs-results-full.R index 73eca306..8c1e832f 100644 --- a/R/estimation-sccs-results-full.R +++ b/R/estimation-sccs-results-full.R @@ -16,11 +16,15 @@ estimationSccsFullResultViewer <- function(id) { shiny::tabPanel( "Power", shiny::div(shiny::strong("Table 1."), "For each variable of interest: the number of cases (people with at least one outcome), the number of years those people were observed, the number of outcomes, the number of subjects with at least one exposure, the number of patient-years exposed, the number of outcomes while exposed, and the minimum detectable relative risk (MDRR)."), - resultTableViewer(ns('powerTable')) + shinyWidgets::addSpinner( + resultTableViewer(ns('powerTable')) + ) ), shiny::tabPanel( "Attrition", - shiny::plotOutput(ns("attritionPlot"), width = 600, height = 500), + shinyWidgets::addSpinner( + shiny::plotOutput(ns("attritionPlot"), width = 600, height = 500) + ), shiny::div( shiny::strong("Figure 1."), "Attrition, showing the number of cases (number of subjects with at least one outcome), and number of outcomes (number of ocurrences of the outcome) after each step in the study.") @@ -39,17 +43,23 @@ estimationSccsFullResultViewer <- function(id) { ), shiny::tabPanel( "Age spline", - shiny::plotOutput(ns("ageSplinePlot")), + shinyWidgets::addSpinner( + shiny::plotOutput(ns("ageSplinePlot")) + ), shiny::div(shiny::strong("Figure 2a."), "Spline fitted for age.") ), shiny::tabPanel( "Season spline", - shiny::plotOutput(ns("seasonSplinePlot")), + shinyWidgets::addSpinner( + shiny::plotOutput(ns("seasonSplinePlot")) + ), shiny::div(shiny::strong("Figure 2b."), "Spline fitted for season") ), shiny::tabPanel( "Calendar time spline", - shiny::plotOutput(ns("calendarTimeSplinePlot")), + shinyWidgets::addSpinner( + shiny::plotOutput(ns("calendarTimeSplinePlot")) + ), shiny::div(shiny::strong("Figure 2c."), "Spline fitted for calendar time") ) ) @@ -57,12 +67,16 @@ estimationSccsFullResultViewer <- function(id) { shiny::tabPanel( "Spanning", shiny::radioButtons(ns("spanningType"), label = "Type:", choices = c("Age", "Calendar time")), - shiny::plotOutput(ns("spanningPlot")), + shinyWidgets::addSpinner( + shiny::plotOutput(ns("spanningPlot")) + ), shiny::div(shiny::strong("Figure 3."), "Number of subjects observed for 3 consecutive months, centered on the indicated month.") ), shiny::tabPanel( "Time trend", - shiny::plotOutput(ns("timeTrendPlot"), height = 600), + shinyWidgets::addSpinner( + shiny::plotOutput(ns("timeTrendPlot"), height = 600) + ), shiny::div( shiny::strong("Figure 4."), "The ratio of observed to expected outcomes per month. The expected count is computing either assuming a constant rate (bottom plot) or adjusting for calendar time, seasonality, and / or age, as specified in the model (top plot)." @@ -70,7 +84,9 @@ estimationSccsFullResultViewer <- function(id) { ), shiny::tabPanel( "Time to event", - shiny::plotOutput(ns("timeToEventPlot")), + shinyWidgets::addSpinner( + shiny::plotOutput(ns("timeToEventPlot")) + ), shiny::div( shiny::strong("Figure 5."), "The number of events and subjects observed per week relative to the start of the first exposure (indicated by the thick vertical line)." @@ -78,13 +94,17 @@ estimationSccsFullResultViewer <- function(id) { ), shiny::tabPanel( "Event dep. observation", - shiny::plotOutput(ns("eventDepObservationPlot")), + shinyWidgets::addSpinner( + shiny::plotOutput(ns("eventDepObservationPlot")) + ), shiny::div(shiny::strong("Figure 6."), "Histograms for the number of months between the first occurrence of the outcome and the end of observation, stratified by whether the end of observation was censored (inferred as not being equal to the end of database time), or uncensored (inferred as having the subject still be observed at the end of database time)." ) ), shiny::tabPanel( "Systematic error", - shiny::plotOutput(ns("controlEstimatesPlot")), + shinyWidgets::addSpinner( + shiny::plotOutput(ns("controlEstimatesPlot")) + ), shiny::div(shiny::strong("Figure 7."), "Systematic error. Effect size estimates for the negative controls (true incidence rate ratio = 1) and positive controls (true incidence rate ratio > 1), before and after calibration. Estimates below the diagonal dashed lines are statistically significant (alpha = 0.05) different from the true effect size. A well-calibrated @@ -114,15 +134,18 @@ estimationSccsFullResultServer <- function( shiny::updateTabsetPanel(session, "fullTabsetPanel", selected = "Power") }) + # show what was selected modifiedRow <- shiny::reactive({ selectedRow() %>% dplyr::select( "covariateName", + 'indication', "outcome", "description", "databaseName" ) %>% dplyr::rename( + 'Indication' = .data$indication, 'Outcome' = .data$outcome, 'Analysis' = .data$description, 'Database' = .data$databaseName @@ -218,13 +241,13 @@ estimationSccsFullResultServer <- function( if (is.null(row)) { return(NULL) } else { - attrition <- getSccsAttrition( + attrition <- estimationGetSccsAttrition( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, databaseId = row$databaseId, analysisId = row$analysisId, - covariateId = row$covariateId + covariateId = row$covariateId, + exposuresOutcomeSetId = row$exposuresOutcomeSetId ) drawAttritionDiagram(attrition) } @@ -235,11 +258,11 @@ estimationSccsFullResultServer <- function( if (is.null(row)) { return(NULL) } else { - resTargetTable <- getSccsModel( + resTargetTable <- estimationGetSccsModel( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, exposureId = row$eraId, - outcomeId = row$outcomeId, + exposuresOutcomeSetId = row$exposuresOutcomeSetId, databaseId = row$databaseId, analysisId = row$analysisId ) @@ -261,11 +284,11 @@ estimationSccsFullResultServer <- function( if (is.null(row)) { return(NULL) } else { - timeTrend <- getSccsTimeTrend( + timeTrend <- estimationGetSccsTimeTrend( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, exposureId = row$eraId, - outcomeId = row$outcomeId, + exposuresOutcomeSetId = row$exposuresOutcomeSetId, databaseId = row$databaseId, analysisId = row$analysisId ) @@ -283,10 +306,10 @@ estimationSccsFullResultServer <- function( if (is.null(row)) { return(NULL) } else { - timeToEvent <- getSccsTimeToEvent( + timeToEvent <- estimationGetSccsTimeToEvent( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, + exposuresOutcomeSetId = row$exposuresOutcomeSetId, exposureId = row$eraId, covariateId = row$covariateId, databaseId = row$databaseId, @@ -301,10 +324,10 @@ estimationSccsFullResultServer <- function( if (is.null(row)) { return(NULL) } else { - eventDepObservation <- getSccsEventDepObservation( + eventDepObservation <- estimationGetSccsEventDepObservation( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, + exposuresOutcomeSetId = row$exposuresOutcomeSetId, databaseId = row$databaseId, analysisId = row$analysisId ) @@ -318,19 +341,19 @@ estimationSccsFullResultServer <- function( return(NULL) } else { if (input$spanningType == "Age") { - ageSpanning <- getSccsAgeSpanning( + ageSpanning <- estimationGetSccsAgeSpanning( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, + exposuresOutcomeSetId = row$exposuresOutcomeSetId, databaseId = row$databaseId, analysisId = row$analysisId ) plotSpanning(ageSpanning, type = "age") } else { - calendarTimeSpanning <- getSccsCalendarTimeSpanning( + calendarTimeSpanning <- estimationGetSccsCalendarTimeSpanning( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, + exposuresOutcomeSetId = row$exposuresOutcomeSetId, databaseId = row$databaseId, analysisId = row$analysisId ) @@ -345,10 +368,10 @@ estimationSccsFullResultServer <- function( if (is.null(row)) { return(NULL) } else { - ageSpline <- getSccsSpline( + ageSpline <- estimationGetSccsSpline( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, + exposuresOutcomeSetId = row$exposuresOutcomeSetId, databaseId = row$databaseId, analysisId = row$analysisId, splineType = "age" @@ -365,10 +388,10 @@ estimationSccsFullResultServer <- function( if (is.null(row)) { return(NULL) } else { - seasonSpline <- getSccsSpline( + seasonSpline <- estimationGetSccsSpline( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, + exposuresOutcomeSetId = row$exposuresOutcomeSetId, databaseId = row$databaseId, analysisId = row$analysisId, splineType = "season" @@ -385,10 +408,10 @@ estimationSccsFullResultServer <- function( if (is.null(row)) { return(NULL) } else { - calendarTimeSpline <- getSccsSpline( + calendarTimeSpline <- estimationGetSccsSpline( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, + exposuresOutcomeSetId = row$exposuresOutcomeSetId, databaseId = row$databaseId, analysisId = row$analysisId, splineType = "calendar time" @@ -405,12 +428,13 @@ estimationSccsFullResultServer <- function( if (is.null(row)) { return(NULL) } else { - controlEstimates <- getSccsControlEstimates( + controlEstimates <- estimationGetSccsControlEstimates( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, covariateId = row$covariateId, databaseId = row$databaseId, - analysisId = row$analysisId + analysisId = row$analysisId, + eraId = row$eraId ) plotControlEstimates(controlEstimates) } @@ -421,7 +445,319 @@ estimationSccsFullResultServer <- function( } +estimationGetSccsAttrition <- function( + connectionHandler, + resultDatabaseSettings, + databaseId, + analysisId, + covariateId, + exposuresOutcomeSetId +) { + sql <- " + SELECT * + FROM @schema.@sccs_table_prefixattrition + WHERE database_id = '@database_id' + AND analysis_id = @analysis_id + AND exposures_outcome_set_id = @exposures_outcome_set_id + AND covariate_id = @covariate_id + " + connectionHandler$queryDb( + sql, + schema = resultDatabaseSettings$schema, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, + database_id = databaseId, + analysis_id = analysisId, + covariate_id = covariateId, + exposures_outcome_set_id = exposuresOutcomeSetId, + snakeCaseToCamelCase = TRUE + ) +} +estimationGetSccsModel <- function( + connectionHandler, + resultDatabaseSettings, + exposuresOutcomeSetId, + databaseId, + analysisId, + exposureId +) { + sql <- " + SELECT + CASE + WHEN era.era_name IS NULL THEN sc.covariate_name + ELSE CONCAT(sc.covariate_name, ' : ', era.era_name) + END as covariate_name, + scr.covariate_id, scr.rr, scr.ci_95_lb, scr.ci_95_ub + FROM @schema.@sccs_table_prefixcovariate_result scr + INNER JOIN @schema.@sccs_table_prefixcovariate sc ON ( + sc.exposures_outcome_set_id = scr.exposures_outcome_set_id AND + sc.database_id = scr.database_id AND + sc.analysis_id = scr.analysis_id AND + sc.covariate_id = scr.covariate_id + ) + LEFT JOIN @schema.@cg_table_prefixcohort_definition cd + ON cd.cohort_definition_id = sc.era_id + LEFT JOIN @schema.@sccs_table_prefixera era ON ( + era.exposures_outcome_set_id = scr.exposures_outcome_set_id AND + era.database_id = scr.database_id AND + era.analysis_id = scr.analysis_id AND + era.era_id = sc.era_id + ) + WHERE scr.database_id = '@database_id' + AND scr.analysis_id = @analysis_id + AND sc.era_id = @exposure_id + AND scr.rr IS NOT NULL + AND scr.exposures_outcome_set_id = @exposures_outcome_set_id + " + + connectionHandler$queryDb(sql, + schema = resultDatabaseSettings$schema, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, + cg_table_prefix = resultDatabaseSettings$cgTablePrefix, + database_id = databaseId, + analysis_id = analysisId, + exposure_id = exposureId, + exposures_outcome_set_id = exposuresOutcomeSetId, + snakeCaseToCamelCase = TRUE) +} + + +estimationGetSccsTimeTrend <- function( + connectionHandler, + resultDatabaseSettings, + exposureId, + exposuresOutcomeSetId, + databaseId, + analysisId +) { + sql <- " + SELECT * + FROM @schema.@sccs_table_prefixtime_trend + WHERE database_id = '@database_id' + AND analysis_id = @analysis_id + AND exposures_outcome_set_id = @exposures_outcome_set_id + " + connectionHandler$queryDb( + sql, + schema = resultDatabaseSettings$schema, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, + database_id = databaseId, + analysis_id = analysisId, + exposures_outcome_set_id = exposuresOutcomeSetId, + snakeCaseToCamelCase = TRUE + ) +} + +estimationGetSccsTimeToEvent <- function( + connectionHandler, + resultDatabaseSettings, + exposureId, + exposuresOutcomeSetId, + covariateId, + databaseId, + analysisId +) { + + sql <- " + SELECT pre_exposure_p + FROM @schema.@sccs_table_prefixdiagnostics_summary + + WHERE database_id = '@database_id' + AND covariate_id = @covariate_id + AND analysis_id = @analysis_id + AND exposures_outcome_set_id = @exposures_outcome_set_id + " + + p <- connectionHandler$queryDb( + sql, + schema = resultDatabaseSettings$schema, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, + database_id = databaseId, + analysis_id = analysisId, + exposures_outcome_set_id = exposuresOutcomeSetId, + covariate_id = covariateId, + snakeCaseToCamelCase = TRUE + ) + + sql <- " + SELECT *, @p as p + FROM @schema.@sccs_table_prefixtime_to_event + + WHERE database_id = '@database_id' + AND era_id = @exposure_id + AND analysis_id = @analysis_id + AND exposures_outcome_set_id = @exposures_outcome_set_id; + " + + timeToEvent <- connectionHandler$queryDb( + sql, + schema = resultDatabaseSettings$schema, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, + database_id = databaseId, + analysis_id = analysisId, + exposures_outcome_set_id = exposuresOutcomeSetId, + exposure_id = exposureId, + p = ifelse(is.null(p$preExposureP), -1, p$preExposureP), + snakeCaseToCamelCase = TRUE + ) + + return(timeToEvent) +} + + +estimationGetSccsEventDepObservation <- function( + connectionHandler, + resultDatabaseSettings, + exposuresOutcomeSetId, + databaseId, + analysisId +) { + sql <- " + SELECT * + FROM @schema.@sccs_table_prefixevent_dep_observation + + WHERE database_id = '@database_id' + AND analysis_id = @analysis_id + AND exposures_outcome_set_id = @exposures_outcome_set_id; + " + connectionHandler$queryDb( + sql, + schema = resultDatabaseSettings$schema, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, + database_id = databaseId, + analysis_id = analysisId, + exposures_outcome_set_id = exposuresOutcomeSetId, + snakeCaseToCamelCase = TRUE + ) +} + + +estimationGetSccsAgeSpanning <- function( + connectionHandler, + resultDatabaseSettings, + exposuresOutcomeSetId, + databaseId, + analysisId +) { + sql <- " + SELECT * + FROM @schema.@sccs_table_prefixage_spanning + + WHERE database_id = '@database_id' + AND analysis_id = @analysis_id + AND exposures_outcome_set_id = @exposures_outcome_set_id + " + connectionHandler$queryDb( + sql, + schema = resultDatabaseSettings$schema, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, + database_id = databaseId, + analysis_id = analysisId, + exposures_outcome_set_id = exposuresOutcomeSetId, + snakeCaseToCamelCase = TRUE + ) +} + +estimationGetSccsCalendarTimeSpanning <- function( + connectionHandler, + resultDatabaseSettings, + exposuresOutcomeSetId, + databaseId, + analysisId +) { + sql <- " + SELECT * + FROM @schema.@sccs_table_prefixcalendar_time_spanning + + WHERE database_id = '@database_id' + AND analysis_id = @analysis_id + AND exposures_outcome_set_id = @exposures_outcome_set_id + " + connectionHandler$queryDb( + sql, + schema = resultDatabaseSettings$schema, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, + database_id = databaseId, + analysis_id = analysisId, + exposures_outcome_set_id = exposuresOutcomeSetId, + snakeCaseToCamelCase = TRUE + ) +} + +estimationGetSccsSpline <- function( + connectionHandler, + resultDatabaseSettings, + exposuresOutcomeSetId, + databaseId, + analysisId, + splineType = "age" +) { + + sql <- " + SELECT * + FROM @schema.@sccs_table_prefixspline + + WHERE database_id = '@database_id' + AND analysis_id = @analysis_id + AND exposures_outcome_set_id = @exposures_outcome_set_id + AND spline_type = '@spline_type'; + " + connectionHandler$queryDb( + sql, + schema = resultDatabaseSettings$schema, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, + database_id = databaseId, + spline_type = splineType, + analysis_id = analysisId, + exposures_outcome_set_id = exposuresOutcomeSetId, + snakeCaseToCamelCase = TRUE + ) +} + + + +estimationGetSccsControlEstimates <- function( + connectionHandler, + resultDatabaseSettings, + databaseId, + analysisId, + covariateId, + eraId +) { + + sql <- " + SELECT ci_95_lb, ci_95_ub, log_rr, se_log_rr, calibrated_ci_95_lb, calibrated_ci_95_ub, calibrated_log_rr, + calibrated_se_log_rr, se.true_effect_size + FROM + (select * from @schema.@sccs_table_prefixresult + WHERE database_id = '@database_id' + AND analysis_id = @analysis_id + AND covariate_id = @covariate_id + ) sr + INNER JOIN @schema.@sccs_table_prefixcovariate sc ON ( + sc.exposures_outcome_set_id = sr.exposures_outcome_set_id AND + sc.database_id = sr.database_id AND + sc.analysis_id = sr.analysis_id AND + sc.covariate_id = sr.covariate_id + ) + INNER JOIN @schema.@sccs_table_prefixexposure se ON ( + se.exposures_outcome_set_id = sr.exposures_outcome_set_id AND + se.era_id = sc.era_id + ) + WHERE sc.era_id = @era_id + ; + " + connectionHandler$queryDb( + sql, + schema = resultDatabaseSettings$schema, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, + database_id = databaseId, + covariate_id = covariateId, + analysis_id = analysisId, + era_id = eraId, + snakeCaseToCamelCase = TRUE + ) +} diff --git a/R/estimation-sccs-results.R b/R/estimation-sccs-results.R index 31192317..336486e8 100644 --- a/R/estimation-sccs-results.R +++ b/R/estimation-sccs-results.R @@ -46,7 +46,7 @@ estimationSccsResultsServer <- function( } ) - data <- shiny::reactive({ + sccsData <- shiny::reactive({ estimationGetSccsResults( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, @@ -55,7 +55,23 @@ estimationSccsResultsServer <- function( ) }) - # add evidence synth if exists + # add evidence synth if existsesData <- shiny::reactive({ + esData <- shiny::reactive({ + tryCatch( + { + estimationGetSccsEsResults( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + exposureIds = targetIds, + outcomeIds = outcomeId + ) + }, error = function(e){print('SCCS ES error');return(NULL)} + ) + }) + + data <- shiny::reactive({ + rbind(sccsData(), esData()) + }) resultTableOutputs <- resultTableServer( id = "resultSummaryTable", @@ -66,7 +82,7 @@ estimationSccsResultsServer <- function( selectedRow <- shiny::reactiveVal(value = NULL) shiny::observeEvent(resultTableOutputs$actionCount(), { - if(resultTableOutputs$actionType() == 'results'){ + if(resultTableOutputs$actionType() == 'results'){ # TODO only work if non meta selectedRow(data()[resultTableOutputs$actionIndex()$index,]) shiny::updateTabsetPanel(session, "resultPanel", selected = "Results") } @@ -81,7 +97,7 @@ estimationSccsResultsServer <- function( ) # return data for plot server - + return(data) } ) } @@ -97,6 +113,7 @@ estimationGetSccsResultSummaryTableColDef <- function(){ covariateAnalysisId = reactable::colDef(show = F), analysisId = reactable::colDef(show = F), outcomeId = reactable::colDef(show = F), + indicationId = reactable::colDef(show = F), outcomeSubjects = reactable::colDef(show = F), outcomeEvents = reactable::colDef(show = F), outcomeObservationPeriods = reactable::colDef(show = F), @@ -107,6 +124,7 @@ estimationGetSccsResultSummaryTableColDef <- function(){ observedDays = reactable::colDef(show = F), mdrr = reactable::colDef(show = F), unblind = reactable::colDef(show = F), + exposuresOutcomeSetId = reactable::colDef(show = F), logRr = reactable::colDef(show = F), seLogRr = reactable::colDef(show = F), @@ -128,6 +146,22 @@ estimationGetSccsResultSummaryTableColDef <- function(){ "Data source", "Data source" )), + target = reactable::colDef( + filterable = TRUE, + header = withTooltip( + "Target", + "Target Cohort" + ), + minWidth = 300 + ), + indication = reactable::colDef( + filterable = TRUE, + header = withTooltip( + "Indication", + "Target cohort is nested in this indication" + ), + minWidth = 300 + ), outcome = reactable::colDef( filterable = TRUE, header = withTooltip( @@ -212,9 +246,6 @@ estimationGetSccsResults <- function(connectionHandler, ) { exposureIds <- exposureIds() outcomeIds <- outcomeIds() - print('SCCS main') - print(exposureIds) - print(outcomeIds ) sql <- " SELECT @@ -229,7 +260,11 @@ estimationGetSccsResults <- function(connectionHandler, a.description, eos.outcome_id, cg1.cohort_name as outcome, - + cg2.cohort_name as target, + cg3.cohort_name as indication, + eos.nesting_cohort_id as indication_id, + eos.exposures_outcome_set_id, + sr.outcome_subjects, sr.outcome_events, sr.outcome_observation_periods, @@ -293,6 +328,14 @@ estimationGetSccsResults <- function(connectionHandler, inner join @schema.@cg_table_prefixcohort_definition cg1 on cg1.cohort_definition_id = eos.outcome_id + + inner join + @schema.@cg_table_prefixcohort_definition as cg2 + on cg2.cohort_definition_id = sc.era_id + + left join + @schema.@cg_table_prefixcohort_definition as cg3 + on eos.nesting_cohort_id = cg3.cohort_definition_id WHERE eos.outcome_id IN (@outcome_ids) @@ -312,7 +355,119 @@ estimationGetSccsResults <- function(connectionHandler, snakeCaseToCamelCase = TRUE ) + print(results[1,]) return(results) } +estimationGetSccsEsResults <- function( + connectionHandler, + resultDatabaseSettings, + exposureIds, + outcomeIds +) { + + exposureIds <- exposureIds() + outcomeIds <- outcomeIds() + +sql <- "select distinct + ev.evidence_synthesis_description as database_name, + 0 as database_id, + cov.covariate_id, -- exists? + cov.covariate_name, + cov.era_id, + 0 as covariate_analysis_id, + esr.analysis_id, + a.description, + eos.outcome_id, + c3.cohort_name as outcome, + c1.cohort_name as target, + c4.cohort_name as indication, + eos.nesting_cohort_id as indication_id, + eos.exposures_outcome_set_id, + esr.outcome_subjects, + esr.outcome_events, + esr.outcome_observation_periods, + esr.covariate_subjects, + esr.covariate_days, + esr.covariate_eras, + esr.covariate_outcomes, + esr.observed_days, + esr.rr, + esr.ci_95_lb, + esr.ci_95_ub, + esr.p, + esr.log_rr, + esr.se_log_rr, + esr.calibrated_rr, + esr.calibrated_ci_95_lb, + esr.calibrated_ci_95_ub, + esr.calibrated_p, + esr.calibrated_log_rr, + esr.calibrated_se_log_rr, + NULL as llr, + esd.mdrr, + esd.unblind as unblind + + from + @schema.@es_table_prefixsccs_result as esr + inner join + @schema.@sccs_table_prefixexposures_outcome_set as eos + on + esr.exposures_outcome_set_id = eos.exposures_outcome_set_id + + inner join + @schema.@sccs_table_prefixcovariate as cov + on + esr.covariate_id = cov.covariate_id and + esr.analysis_id = cov.analysis_id and + esr.exposures_outcome_set_id = cov.exposures_outcome_set_id + + inner join + + @schema.@es_table_prefixsccs_diagnostics_summary as esd + on + esr.analysis_id = esd.analysis_id and + esr.exposures_outcome_set_id = esd.exposures_outcome_set_id and + esr.covariate_id = esd.covariate_id and + esr.evidence_synthesis_analysis_id = esd.evidence_synthesis_analysis_id + + inner join + @schema.@cg_table_prefixcohort_definition as c1 + on c1.cohort_definition_id = cov.era_id + + inner join + @schema.@cg_table_prefixcohort_definition as c3 + on c3.cohort_definition_id = eos.outcome_id + + inner join + @schema.@sccs_table_prefixanalysis as a + on a.analysis_id = esr.analysis_id + + inner join + @schema.@es_table_prefixanalysis as ev + on ev.evidence_synthesis_analysis_id = esr.evidence_synthesis_analysis_id + + left join + @schema.@cg_table_prefixcohort_definition as c4 + on eos.nesting_cohort_id = c4.cohort_definition_id + + where + esr.calibrated_rr != 0 and + esd.unblind = 1 and + cov.era_id in (@target_ids) and + eos.outcome_id in (@outcome_id) + ;" + +result <- connectionHandler$queryDb( + sql = sql, + schema = resultDatabaseSettings$schema, + es_table_prefix = resultDatabaseSettings$esTablePrefix, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, + cg_table_prefix = resultDatabaseSettings$cgTablePrefix, + outcome_id = paste0(outcomeIds, collapse = ','), + target_ids = paste0(exposureIds, collapse = ',') +) + +return(result) +} From 0e6c0f501383fbaf9788716540c88503fe8eab8d Mon Sep 17 00:00:00 2001 From: jreps Date: Thu, 9 May 2024 15:45:17 -0400 Subject: [PATCH 03/64] estimation edits - optimizing sccs negative control plot - removing prints --- R/estimation-cohort-method-plots.R | 4 +-- R/estimation-sccs-results-full.R | 44 ++++++++++++++++++++++-------- R/estimation-sccs-results.R | 1 - 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/R/estimation-cohort-method-plots.R b/R/estimation-cohort-method-plots.R index b90860c5..d58c8665 100644 --- a/R/estimation-cohort-method-plots.R +++ b/R/estimation-cohort-method-plots.R @@ -36,12 +36,10 @@ estimationCmPlotsServer <- function( } estimationCreateCmPlot <- function(data) { - print('PLOT') data <- data() data <- data[!is.na(data$calibratedRr),] data$database <- data$cdmSourceAbbreviation - - print(data) + if(is.null(data$comparator)){ return(NULL) } diff --git a/R/estimation-sccs-results-full.R b/R/estimation-sccs-results-full.R index 8c1e832f..c71cbfb2 100644 --- a/R/estimation-sccs-results-full.R +++ b/R/estimation-sccs-results-full.R @@ -730,27 +730,41 @@ estimationGetSccsControlEstimates <- function( sql <- " SELECT ci_95_lb, ci_95_ub, log_rr, se_log_rr, calibrated_ci_95_lb, calibrated_ci_95_ub, calibrated_log_rr, - calibrated_se_log_rr, se.true_effect_size + calibrated_se_log_rr, exposures_outcome_set_id FROM (select * from @schema.@sccs_table_prefixresult WHERE database_id = '@database_id' AND analysis_id = @analysis_id AND covariate_id = @covariate_id ) sr - INNER JOIN @schema.@sccs_table_prefixcovariate sc ON ( - sc.exposures_outcome_set_id = sr.exposures_outcome_set_id AND - sc.database_id = sr.database_id AND - sc.analysis_id = sr.analysis_id AND - sc.covariate_id = sr.covariate_id - ) - INNER JOIN @schema.@sccs_table_prefixexposure se ON ( - se.exposures_outcome_set_id = sr.exposures_outcome_set_id AND - se.era_id = sc.era_id + ; + " + res <- connectionHandler$queryDb( + sql, + schema = resultDatabaseSettings$schema, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, + database_id = databaseId, + covariate_id = covariateId, + analysis_id = analysisId, + era_id = eraId, + snakeCaseToCamelCase = TRUE ) - WHERE sc.era_id = @era_id + + sql <- " + select e.true_effect_size, c.exposures_outcome_set_id + from + @schema.@sccs_table_prefixexposure e + INNER JOIN + @schema.@sccs_table_prefixcovariate c + on e.era_id = c.era_id + and e.exposures_outcome_set_id = c.exposures_outcome_set_id + WHERE e.era_id = @era_id + and c.database_id = '@database_id' + AND c.analysis_id = @analysis_id + AND c.covariate_id = @covariate_id ; " - connectionHandler$queryDb( + res2 <- connectionHandler$queryDb( sql, schema = resultDatabaseSettings$schema, sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, @@ -760,4 +774,10 @@ estimationGetSccsControlEstimates <- function( era_id = eraId, snakeCaseToCamelCase = TRUE ) + # only keep the positive or negative controls (trueEffectSize 1 or >1) + res2 <- res2[!is.na(res2$trueEffectSize),] + + allres <- merge(res, res2, by = 'exposuresOutcomeSetId') + + return(allres) } diff --git a/R/estimation-sccs-results.R b/R/estimation-sccs-results.R index 336486e8..75fad592 100644 --- a/R/estimation-sccs-results.R +++ b/R/estimation-sccs-results.R @@ -355,7 +355,6 @@ estimationGetSccsResults <- function(connectionHandler, snakeCaseToCamelCase = TRUE ) - print(results[1,]) return(results) } From 9ac2d1af1b73b9ae11a382fab31360cbe4e946c2 Mon Sep 17 00:00:00 2001 From: jreps Date: Fri, 17 May 2024 15:43:54 -0400 Subject: [PATCH 04/64] - updating characterization - updating characterization --- NAMESPACE | 4 - R/characterization-aggregateFeatures.R | 870 ------------------ R/characterization-caseSeries.R | 421 +++++++++ R/characterization-cohorts.R | 702 ++++++++------ R/characterization-database.R | 281 ++++++ R/characterization-dechallengeRechallenge.R | 85 +- R/characterization-incidence.R | 584 +++++------- R/characterization-main.R | 582 ++++++++++-- R/characterization-riskFactors.R | 392 ++++++++ R/characterization-timeToEvent.R | 83 +- R/components-data-viewer.R | 5 +- extras/examples/app.R | 16 +- inst/extdata/results.sqlite | Bin 3084288 -> 3100672 bytes inst/extdata/results_old.sqlite | Bin 0 -> 3084288 bytes man/OhdsiShinyModules.Rd | 10 - ...characterizationAggregateFeaturesServer.Rd | 28 - ...characterizationAggregateFeaturesViewer.Rd | 20 - ...cterizationDechallengeRechallengeServer.Rd | 4 +- man/characterizationIncidenceServer.Rd | 11 +- man/characterizationTableServer.Rd | 24 - man/characterizationTableViewer.Rd | 20 - man/characterizationTimeToEventServer.Rd | 4 +- man/estimationHelperFile.Rd | 17 + man/estimationServer.Rd | 28 + man/estimationViewer.Rd | 20 + man/resultTableViewer.Rd | 6 +- 26 files changed, 2344 insertions(+), 1873 deletions(-) delete mode 100644 R/characterization-aggregateFeatures.R create mode 100644 R/characterization-caseSeries.R create mode 100644 R/characterization-database.R create mode 100644 R/characterization-riskFactors.R create mode 100755 inst/extdata/results_old.sqlite delete mode 100644 man/OhdsiShinyModules.Rd delete mode 100644 man/characterizationAggregateFeaturesServer.Rd delete mode 100644 man/characterizationAggregateFeaturesViewer.Rd delete mode 100644 man/characterizationTableServer.Rd delete mode 100644 man/characterizationTableViewer.Rd create mode 100644 man/estimationHelperFile.Rd create mode 100644 man/estimationServer.Rd create mode 100644 man/estimationViewer.Rd diff --git a/NAMESPACE b/NAMESPACE index 1fba30b5..c372141f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -4,16 +4,12 @@ export(LargeDataTable) export(aboutHelperFile) export(aboutServer) export(aboutViewer) -export(characterizationAggregateFeaturesServer) -export(characterizationAggregateFeaturesViewer) export(characterizationDechallengeRechallengeServer) export(characterizationDechallengeRechallengeViewer) export(characterizationHelperFile) export(characterizationIncidenceServer) export(characterizationIncidenceViewer) export(characterizationServer) -export(characterizationTableServer) -export(characterizationTableViewer) export(characterizationTimeToEventServer) export(characterizationTimeToEventViewer) export(characterizationViewer) diff --git a/R/characterization-aggregateFeatures.R b/R/characterization-aggregateFeatures.R deleted file mode 100644 index 0f64b826..00000000 --- a/R/characterization-aggregateFeatures.R +++ /dev/null @@ -1,870 +0,0 @@ -# @file characterization-aggregateFeatures.R -# -# Copyright 2024 Observational Health Data Sciences and Informatics -# -# This file is part of OhdsiShinyModules -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -#' The module viewer for exploring aggregate feature results -#' -#' @details -#' The user specifies the id for the module -#' -#' @param id the unique reference id for the module -#' -#' @return -#' The user interface to the description aggregate feature module -#' -#' @export -characterizationAggregateFeaturesViewer <- function(id) { - ns <- shiny::NS(id) - - shiny::div( - - infoHelperViewer( - id = "helper", - helpLocation= system.file("characterization-www", "help-OutcomeStratified.html", package = utils::packageName()) - ), - - - # module that does input selection for a single row DF - inputSelectionViewer( - id = ns("input-selection") - ), - - # COV: RUN_ID DATABASE_ID COHORT_DEFINITION_ID COVARIATE_ID SUM_VALUE AVERAGE_VALUE - # COV REF: RUN_ID DATABASE_ID COVARIATE_ID COVARIATE_NAME ANALYSIS_ID CONCEPT_ID - # settings: RUN_ID DATABASE_ID COVARIATE_SETTING_JSON RISK_WINDOW_START START_ANCHOR RISK_WINDOW_END END_ANCHOR - # cohort_details: RUN_ID DATABASE_ID COHORT_DEFINITION_ID TARGET_COHORT_ID OUTCOME_COHORT_ID COHORT_TYPE - # analysis_ref: RUN_ID DATABASE_ID ANALYSIS_ID ANALYSIS_NAME DOMAIN_ID START_DAY END_DAY IS_BINARY MISSING_MEANS_ZERO - # cov cont: RUN_ID DATABASE_ID COHORT_DEFINITION_ID COVARIATE_ID COUNT_VALUE MIN_VALUE MAX_VALUE AVERAGE_VALUE STANDARD_DEVIATION MEDIAN_VALUE P_10_VALUE P_25_VALUE P_75_VALUE P_90_VALUE - # add table with options to select T, O and TAR - - # add UI to pick database/type 1 and database/type 2 - - shiny::conditionalPanel( - condition = 'input.generate != 0', - ns = shiny::NS(ns("input-selection")), - - shinydashboard::tabBox( - width = "100%", - # Title can include an icon - title = shiny::tagList(shiny::icon("gear"), "Table and Plots"), - shiny::tabPanel("Binary Feature Table", - resultTableViewer(ns('binaryTable')) - ), - shiny::tabPanel("Continuous Feature Table", - resultTableViewer(ns('continuousTable')) - ), - shiny::tabPanel("Binary Feature Plot", - shinycssloaders::withSpinner( - plotly::plotlyOutput(ns("binaryPlot")) - ) - ), - shiny::tabPanel("Continuous Feature Plot", - shinycssloaders::withSpinner( - plotly::plotlyOutput(ns("continuousPlot")) - ) - ) - ) - ) - ) -} - - -#' The module server for exploring aggregate features results -#' -#' @details -#' The user specifies the id for the module -#' -#' @param id the unique reference id for the module -#' @param connectionHandler the connection to the prediction result database -#' @param resultDatabaseSettings a list containing the characterization result schema, dbms, tablePrefix, databaseTable and cgTablePrefix -#' -#' @return -#' The server to the description aggregate features module -#' -#' @export -characterizationAggregateFeaturesServer <- function( - id, - connectionHandler, - resultDatabaseSettings -) { - shiny::moduleServer( - id, - function(input, output, session) { - - # get the possible options - options <- getAggregateFeatureOptions( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - # get databases - databases <- getAggregateFeatureDatabases( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - # input selection component - inputSelected <- inputSelectionServer( - id = "input-selection", - inputSettingList = list( - createInputSetting( - rowNumber = 1, - columnWidth = 4, - varName = 'targetIds', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Target: ', - choices = options$targets, - selected = options$targets[1], - multiple = F, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ), - createInputSetting( - rowNumber = 1, - columnWidth = 4, - varName = 'outcomeIds', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Outcome: ', - choices = options$outcomes, - selected = options$outcomes[1], - multiple = F, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ) - , - createInputSetting( - rowNumber = 1, - columnWidth = 4, - varName = 'tarIds', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Time at risk: ', - choices = options$tars, - selected = options$tars[1], - multiple = F, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ) - , - createInputSetting( - rowNumber = 2, - columnWidth = 6, - varName = 'database', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Database: ', - choices = databases, - selected = databases[1], - multiple = F, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ) - , - createInputSetting( - rowNumber = 2, - columnWidth = 3, - varName = 'firstO', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Restrict to first O: ', - choices = c(T,F), - selected = T, - multiple = F - ) - ) - , - createInputSetting( - rowNumber = 2, - columnWidth = 3, - varName = 'index', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Index: ', - choices = c('T', 'O'), - selected = 'T', - multiple = F - ) - ) - ) - ) - - allData <- shiny::reactive({ - characterizationGetAggregateData( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - targetId = inputSelected()$targetIds, - outcomeId = inputSelected()$outcomeIds, - riskWindowStart = options$tarList[[which(options$tars == ifelse(is.null(inputSelected()$tarIds),options$tars[1],inputSelected()$tarIds))]]$riskWindowStart, - riskWindowEnd = options$tarList[[which(options$tars == ifelse(is.null(inputSelected()$tarIds),options$tars[1],inputSelected()$tarIds))]]$riskWindowEnd, - startAnchor = options$tarList[[which(options$tars == ifelse(is.null(inputSelected()$tarIds),options$tars[1],inputSelected()$tarIds))]]$startAnchor, - endAnchor = options$tarList[[which(options$tars == ifelse(is.null(inputSelected()$tarIds),options$tars[1],inputSelected()$tarIds))]]$endAnchor, - database = inputSelected()$database, - firstO = inputSelected()$firstO, - index = inputSelected()$index - ) - }) - - output$binaryPlot <- plotly::renderPlotly( - characterizationFeaturePlot( - data = allData()$binary, - valueColumn = 'averageValue' - ) - ) - output$continuousPlot <- plotly::renderPlotly( - characterizationFeaturePlot( - data = allData()$continuous, - valueColumn = 'averageValue' - ) - ) - - binaryData <- shiny::reactive({ - characterizationFeatureTable( - data = allData()$binary - ) - }) - - continuousData <- shiny::reactive({ - characterizationFeatureTable( - data = allData()$continuous - ) - }) - - binTableOutputs <- resultTableServer( - id = "binaryTable", - df = binaryData, - colDefsInput = list( - covariateName = reactable::colDef( - name = "Covariate Name", - filterable = T - ), - comp1T = reactable::colDef( - name = "T without O mean", - format = reactable::colFormat(digits = 2, percent = T) - ), - comp1sdT = reactable::colDef( - name = "T without O stdev", - format = reactable::colFormat(digits = 2) - ), - comp2T = reactable::colDef( - name = "T with O mean", - format = reactable::colFormat(digits = 2, percent = T) - ), - comp2sdT = reactable::colDef( - name = "T with O stdev", - format = reactable::colFormat(digits = 2) - ), - comp1O = reactable::colDef( - name = "O without T mean", - format = reactable::colFormat(digits = 2, percent = T) - ), - comp1sdO = reactable::colDef( - name = "O without T stdev", - format = reactable::colFormat(digits = 2) - ), - comp2O = reactable::colDef( - name = "O with T mean", - format = reactable::colFormat(digits = 2, percent = T) - ), - comp2sdO = reactable::colDef( - name = "O with T stdev", - format = reactable::colFormat(digits = 2) - ), - analysisName = reactable::colDef( # not sure this will work now - filterInput = function(values, name) { - shiny::tags$select( - # Set to undefined to clear the filter - onchange = sprintf("Reactable.setFilter('desc-bin-select', '%s', event.target.value || undefined)", name), - # "All" has an empty value to clear the filter, and is the default option - shiny::tags$option(value = "", "All"), - lapply(unique(values), shiny::tags$option), - "aria-label" = sprintf("Filter %s", name), - style = "width: 100%; height: 28px;" - ) - } - ), - standardizedMeanDiff = reactable::colDef( - format = reactable::colFormat(digits = 2) - ) - ), - addActions = NULL - ) - - conTableOutputs <- resultTableServer( - id = "continuousTable", - df = continuousData, - colDefsInput = list( - covariateName = reactable::colDef( - name = "Covariate Name", - filterable = T - ), - comp1T = reactable::colDef( - name = "T without O mean", - format = reactable::colFormat(digits = 2) - ), - comp1sdT = reactable::colDef( - name = "T without O stdev", - format = reactable::colFormat(digits = 2) - ), - comp2T = reactable::colDef( - name = "T with O mean", - format = reactable::colFormat(digits = 2) - ), - comp2sdT = reactable::colDef( - name = "T with O stdev", - format = reactable::colFormat(digits = 2) - ), - comp1O = reactable::colDef( - name = "O without T mean", - format = reactable::colFormat(digits = 2) - ), - comp1sdO = reactable::colDef( - name = "O without T stdev", - format = reactable::colFormat(digits = 2) - ), - comp2O = reactable::colDef( - name = "O with T mean", - format = reactable::colFormat(digits = 2) - ), - comp2sdO = reactable::colDef( - name = "O with T stdev", - format = reactable::colFormat(digits = 2) - ), - analysisName = reactable::colDef( - filterInput = function(values, name) { - shiny::tags$select( - # Set to undefined to clear the filter - onchange = sprintf("Reactable.setFilter('desc-cont-select', '%s', event.target.value || undefined)", name), - # "All" has an empty value to clear the filter, and is the default option - shiny::tags$option(value = "", "All"), - lapply(unique(values), shiny::tags$option), - "aria-label" = sprintf("Filter %s", name), - style = "width: 100%; height: 28px;" - ) - } - ), - standardizedMeanDiff = reactable::colDef( - format = reactable::colFormat(digits = 2) - ) - ), - addActions = NULL - ) - - #elementId = "desc-cont-select" - - - - return(invisible(NULL)) - } - ) -} - - -getAggregateFeatureOptions <- function( - connectionHandler, - resultDatabaseSettings -){ - - - shiny::withProgress(message = 'Getting feature comparison options', value = 0, { - - sql <- "SELECT DISTINCT t.COHORT_NAME as TARGET, cd.TARGET_COHORT_ID, - o.COHORT_NAME as outcome, cd.OUTCOME_COHORT_ID, - s.RISK_WINDOW_START, s.START_ANCHOR, s.RISK_WINDOW_END, s.END_ANCHOR - FROM @schema.@c_table_prefixCOHORT_DETAILS cd - inner join @schema.@c_table_prefixSETTINGS s - on cd.run_id = s.run_id and cd.database_id = s.database_id - inner join @schema.@cg_table_prefixCOHORT_DEFINITION t - on cd.TARGET_COHORT_ID = t.COHORT_DEFINITION_ID - inner join @schema.@cg_table_prefixCOHORT_DEFINITION o - on cd.OUTCOME_COHORT_ID = o.COHORT_DEFINITION_ID - WHERE cd.TARGET_COHORT_ID != 0 AND cd.OUTCOME_COHORT_ID != 0;" - - shiny::incProgress(1/2, detail = paste("Extracting options")) - - options <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - c_table_prefix = resultDatabaseSettings$cTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix - ) - - shiny::incProgress(2/2, detail = paste("Finished")) - - }) - - targets <- unique(options$targetCohortId) - names(targets) <- unique(options$target) - - outcomes <- unique(options$outcomeCohortId) - names(outcomes) <- unique(options$outcome) - - options <- unique( - options %>% - dplyr::select( - "riskWindowStart", - "riskWindowEnd", - "startAnchor", - "endAnchor" - ) - ) - - tarList <- lapply( - 1:nrow(options), - function(i){ - list( - riskWindowStart = options$riskWindowStart[i], - riskWindowEnd = options$riskWindowEnd[i], - startAnchor = options$startAnchor[i], - endAnchor = options$endAnchor[i] - ) - }) - - tars <- unlist( - lapply( - 1:nrow(options), - function(i){ - paste0( - '(',options$startAnchor[i],' + ', options$riskWindowStart[i], - ') - (', options$endAnchor[i],' + ', options$riskWindowEnd[i], - ')' - ) - }) - ) - - return( - list( - targets = targets, - outcomes = outcomes, - tars = tars, - tarList = tarList - ) - ) -} - -getAggregateFeatureDatabases <- function( - connectionHandler, - resultDatabaseSettings -){ - - shiny::withProgress(message = 'Finding databases', value = 0, { - sql <- "SELECT DISTINCT s.DATABASE_ID, d.CDM_SOURCE_ABBREVIATION as database_name - FROM @schema.@c_table_prefixCOHORT_DETAILS cd - inner join @schema.@database_table d - on cd.database_id = d.database_id - inner join @schema.@c_table_prefixSETTINGS s - on s.database_id = d.database_id - and s.run_id = cd.run_id;" - - shiny::incProgress(1/2, detail = paste("Extracting databases")) - - - databases <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - c_table_prefix = resultDatabaseSettings$cTablePrefix, - database_table = resultDatabaseSettings$databaseTable - ) - - shiny::incProgress(2/2, detail = paste("Finished")) - - } - ) - - dbs <- databases$databaseId - names(dbs) <- databases$databaseName - - return(dbs) -} - -# pulls all data for a target and outcome -# edited to only use Ts and TnOs -characterizationGetAggregateData <- function( - connectionHandler, - resultDatabaseSettings, - targetId, - outcomeId, - riskWindowStart, - riskWindowEnd, - startAnchor, - endAnchor, - database, - firstO, - index -){ - - if(is.null(targetId)){ - return(NULL) - } - - #get types based on index and first - outcomeType <- ifelse(firstO, 'firstO', 'O') - firstPart <- ifelse(index == 'T', 'T', outcomeType) - secondPart <- ifelse(index == 'T',outcomeType, 'T') - - type1 <- firstPart - type2 <- paste0(firstPart, 'n', secondPart) - - # if type is TnOc TnfirstOc the extract T minus TnO / TnOfirst - - shiny::withProgress(message = 'Getting Feature Comparison Data', value = 0, { - sql <- "SELECT s.RUN_ID, cd.COHORT_DEFINITION_ID - FROM @schema.@c_table_prefixSETTINGS s - inner join - @schema.@c_table_prefixCOHORT_DETAILS cd - on cd.database_id = s.database_id and - cd.run_id = s.run_id - WHERE cd.TARGET_COHORT_ID = @target_id and cd.OUTCOME_COHORT_ID = @outcome_id - and s.RISK_WINDOW_START = @risk_window_start and s.START_ANCHOR = '@start_anchor' - and s.RISK_WINDOW_END = @risk_window_end and s.END_ANCHOR = '@end_anchor' - and s.DATABASE_ID = '@database_id' and cd.COHORT_TYPE = '@type';" - - settingsFirst <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - c_table_prefix = resultDatabaseSettings$cTablePrefix, - target_id = ifelse(type1 %in% c('firstO','O'), 0, targetId), - outcome_id = ifelse(type1 %in% c('T', 'allT'), 0, outcomeId), - risk_window_start = riskWindowStart, - start_anchor = startAnchor, - risk_window_end = riskWindowEnd, - end_anchor = endAnchor, - database_id = database, - type = type1 - ) - - shiny::incProgress(1/5, detail = paste("Got first runId and cohortId")) - - - sql <- "SELECT s.RUN_ID, cd.COHORT_DEFINITION_ID - FROM @schema.@c_table_prefixSETTINGS s - inner join - @schema.@c_table_prefixCOHORT_DETAILS cd - on cd.database_id = s.database_id and - cd.run_id = s.run_id - WHERE cd.TARGET_COHORT_ID = @target_id and cd.OUTCOME_COHORT_ID = @outcome_id - and s.RISK_WINDOW_START = @risk_window_start and s.START_ANCHOR = '@start_anchor' - and s.RISK_WINDOW_END = @risk_window_end and s.END_ANCHOR = '@end_anchor' - and s.DATABASE_ID = '@database_id' and cd.COHORT_TYPE = '@type';" - - settingsSecond <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - c_table_prefix = resultDatabaseSettings$cTablePrefix, - target_id = ifelse(type2 %in% c('firstO','O'), 0, targetId), - outcome_id = ifelse(type2 %in% c('T', 'allT'), 0, outcomeId), - risk_window_start = riskWindowStart, - start_anchor = startAnchor, - risk_window_end = riskWindowEnd, - end_anchor = endAnchor, - database_id = database, - type = type2 - ) - - if(nrow(settingsSecond) == 0){ - print('no second setting') - settingsSecond <- settingsFirst - } - - shiny::incProgress(2/5, detail = paste("Got second runId and CohortId")) - - sql <- "SELECT - case when t.covariate_id is NULL then tno.covariate_id else t.covariate_id end covariate_id, - t.sum_value - tno.sum_value as comp1_count, - tno.sum_value as comp2_count, - case when (t.sum_value - tno.sum_value)*1.0/(cc.row_count - cctno.row_count) is NULL then 0 else (t.sum_value - tno.sum_value)*1.0/(cc.row_count - cctno.row_count) end as comp1_@index, - case when tno.average_value is NULL then 0 else tno.average_value end as comp2_@index, - sqrt( (t.sum_value - tno.sum_value)*1.0/(cc.row_count - cctno.row_count) * (1-( (t.sum_value - tno.sum_value)*1.0/(cc.row_count - cctno.row_count) )) ) as comp1sd_@index, - sqrt( (tno.average_value)*(1-(tno.average_value))) as comp2sd_@index, - cov_ref.COVARIATE_NAME, - an_ref.ANALYSIS_NAME - - FROM - - (select * FROM @schema.@c_table_prefixCOVARIATES - where - DATABASE_ID = '@database_id' and - COHORT_DEFINITION_ID = @cohort_def_1 and - RUN_ID in (@run_id_1) - ) t - full join - (select * FROM @schema.@c_table_prefixCOVARIATES - where - DATABASE_ID = '@database_id' and - COHORT_DEFINITION_ID = @cohort_def_2 and - RUN_ID in (@run_id_2) - ) tno - - on - t.covariate_id = tno.covariate_id - and t.run_id = tno.run_id - - INNER JOIN - @schema.@c_table_prefixCOHORT_COUNTS cc - on cc.cohort_definition_id = t.cohort_definition_id - and cc.run_id = t.run_id - and cc.database_id = t.database_id - - INNER JOIN - @schema.@c_table_prefixCOHORT_COUNTS cctno - on cctno.cohort_definition_id = tno.cohort_definition_id - and cctno.run_id = tno.run_id - and cctno.database_id = tno.database_id - - INNER JOIN - @schema.@c_table_prefixCOVARIATE_REF cov_ref - ON cov_ref.covariate_id = t.covariate_id - and cov_ref.run_id = case when t.run_id is NULL then tno.run_id else t.run_id end - and cov_ref.database_id = t.database_id - - INNER JOIN - @schema.@c_table_prefixANALYSIS_REF an_ref - ON an_ref.analysis_id = cov_ref.analysis_id - and an_ref.run_id = cov_ref.run_id - and an_ref.database_id = cov_ref.database_id - - ;" - - shiny::incProgress(3/5, detail = paste("Getting binary data")) - - binary <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - c_table_prefix = resultDatabaseSettings$cTablePrefix, - cohort_def_1 = settingsFirst$cohortDefinitionId[1], - cohort_def_2 = settingsSecond$cohortDefinitionId[1], - database_id = database, - run_id_1 = paste(settingsFirst$runId, collapse = ','), - run_id_2 = paste(settingsSecond$runId, collapse = ','), - index = index - ) - - shiny::incProgress(4/5, detail = paste("Getting continuous data")) - - sql <- "SELECT - case when t.covariate_id is NULL then tno.covariate_id else t.covariate_id end covariate_id, - t.count_value - tno.count_value as comp1_count, - tno.count_value as comp2_count, - case when (t.count_value*t.average_value - tno.count_value*tno.average_value)*1.0/(cc.row_count-tnocc.row_count) is NULL then 0 else (t.count_value*t.average_value - tno.count_value*tno.average_value)*1.0/(cc.row_count-tnocc.row_count) end as comp1_@index, - case when tno.average_value is NULL then 0 else tno.average_value end as comp2_@index, - sqrt( (square(t.standard_deviation)*cc.row_count - square(tno.standard_deviation)*tnocc.row_count)/ (cc.row_count - tnocc.row_count)) as comp1sd_@index, - tno.standard_deviation as comp2sd_@index, - cov_ref.COVARIATE_NAME, - an_ref.ANALYSIS_NAME - - FROM - - (select * FROM @schema.@c_table_prefixCOVARIATES_continuous - where - DATABASE_ID = '@database_id' and - COHORT_DEFINITION_ID = @cohort_def_1 and - RUN_ID in (@run_id_1) - ) t - full join - (select * FROM @schema.@c_table_prefixCOVARIATES_continuous - where - DATABASE_ID = '@database_id' and - COHORT_DEFINITION_ID = @cohort_def_2 and - RUN_ID in (@run_id_2) - ) tno - - on - t.covariate_id = tno.covariate_id - and t.run_id = tno.run_id - - INNER JOIN - @schema.@c_table_prefixCOHORT_COUNTS cc - on cc.cohort_definition_id = t.cohort_definition_id - and cc.run_id = t.run_id - and cc.database_id = t.database_id - - INNER JOIN - @schema.@c_table_prefixCOHORT_COUNTS tnocc - on tnocc.cohort_definition_id = tno.cohort_definition_id - and tnocc.run_id = tno.run_id - and tnocc.database_id = tno.database_id - - INNER JOIN - @schema.@c_table_prefixCOVARIATE_REF cov_ref - ON cov_ref.covariate_id = t.covariate_id - and cov_ref.run_id = case when t.run_id is NULL then tno.run_id else t.run_id end - and cov_ref.database_id = t.database_id - - INNER JOIN - @schema.@c_table_prefixANALYSIS_REF an_ref - ON an_ref.analysis_id = cov_ref.analysis_id - and an_ref.run_id = cov_ref.run_id - and an_ref.database_id = cov_ref.database_id - - ;" - - continuous <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - c_table_prefix = resultDatabaseSettings$cTablePrefix, - cohort_def_1 = settingsFirst$cohortDefinitionId[1], - cohort_def_2 = settingsSecond$cohortDefinitionId[1], - database_id = database, - run_id_1 = paste(settingsFirst$runId, collapse = ','), - run_id_2 = paste(settingsSecond$runId, collapse = ','), - index = index - ) - - shiny::incProgress(5/5, detail = paste("Finished")) - } - ) - - return(list( - binary = binary, - continuous = continuous - )) -} - -characterizationFeaturePlot <- function( - data, - valueColumn = 'averageValue' -){ - - if(is.null(data)){ - return(NULL) - } - - # selecting the column anmes that has _index appended to it - comp1Name <- paste0('comp1', c('O', 'T'))[paste0('comp1', c('O', 'T')) %in% colnames(data)] - comp2Name <- paste0('comp2', c('O', 'T'))[paste0('comp2', c('O', 'T')) %in% colnames(data)] - data$comp1 <- data[,comp1Name] - data$comp2 <- data[,comp2Name] - - maxval <- max(max(data$comp1),max(data$comp2)) - - plot <- plotly::plot_ly( - data = data, - x = ~.data$comp1, - y = ~.data$comp2, - showlegend = F - ) %>% - plotly::add_markers(color=factor(data$analysisName), - hoverinfo = 'text', - text = ~paste( - '\n',descGetType(data$covariateName), - '\n',descGetName(data$covariateName), - '\n',descGetTime(data$covariateName) - ), - showlegend = T - ) %>% - plotly::add_trace(x= c(0,maxval), y = c(0,maxval),mode = 'lines', - line = list(dash = "dash"), color = I('black'), - type='scatter', showlegend = FALSE) %>% - plotly::layout(#title = 'Prevalance of baseline predictors in persons with and without outcome', - xaxis = list(title = "Prevalance in selection 1"), - yaxis = list(title = "Prevalance in selection 2"), - #legend = l, showlegend = T, - legend = list(orientation = 'h', y = -0.3), showlegend = T) - - - return(plot) -} - -descGetType <- function(x){ - return(unlist(lapply(strsplit(x = x, split = ' during'), function(y){y[1]}))) -} - -descGetName <- function(x){ - return(unlist(lapply(strsplit(x = x, split = ': '), function(y){y[length(y)]}))) -} - -descGetTime <- function(x){ - part1 <- unlist(lapply(strsplit(x = x, split = ' during '), function(y){y[2]})) - return(unlist(lapply(strsplit(x = part1, split = ': '), function(y){y[1]}))) -} - - -characterizationFeatureTable <- function( - data -){ - - if(is.null(data)){ - return(NULL) - } - - # selecting the column that as _index appended to it - comp1Name <- paste0('comp1', c('O', 'T'))[paste0('comp1', c('O', 'T')) %in% colnames(data)] - comp2Name <- paste0('comp2', c('O', 'T'))[paste0('comp2', c('O', 'T')) %in% colnames(data)] - comp1sdName <- paste0('comp1sd', c('O', 'T'))[paste0('comp1sd', c('O', 'T')) %in% colnames(data)] - comp2sdName <- paste0('comp2sd', c('O', 'T'))[paste0('comp2sd', c('O', 'T')) %in% colnames(data)] - - if(sum(is.null(data[comp1sdName]))>0){ - data[comp1sdName][is.null(data[comp1sdName])] <- 0 - } - if(sum(is.null(data[comp2sdName]))>0){ - data[comp2sdName][is.null(data[comp2sdName])] <- 0 - } - - data <- data %>% - dplyr::mutate( - standardizedMeanDiff = (.data[[comp1Name]] - .data[[comp2Name]])/(sqrt((.data[[comp1sdName]]^2 + .data[[comp2sdName]]^2))) - ) %>% - dplyr::select( - "covariateName", - "analysisName", - comp1Name, - comp1sdName, - comp2Name, - comp2sdName, - "standardizedMeanDiff" - ) - - if(sum(is.null(data$standardizedMeanDiff))>0){ - data$standardizedMeanDiff[is.null(data$standardizedMeanDiff)] <- 0 - } - - if(sum(!is.finite(data$standardizedMeanDiff))>0){ - data$standardizedMeanDiff[!is.finite(data$standardizedMeanDiff)] <- 0 - } - - return(data) -} diff --git a/R/characterization-caseSeries.R b/R/characterization-caseSeries.R new file mode 100644 index 00000000..8897dc2a --- /dev/null +++ b/R/characterization-caseSeries.R @@ -0,0 +1,421 @@ +# @file characterization-aggregateFeatures.R +# +# Copyright 2024 Observational Health Data Sciences and Informatics +# +# This file is part of OhdsiShinyModules +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + + +characterizationCaseSeriesViewer <- function(id) { + ns <- shiny::NS(id) + + shiny::div( + + # module that does input selection for a single row DF + shiny::uiOutput(ns("inputs")), + + shiny::conditionalPanel( + condition = 'input.generate != 0', + ns = ns, + shinydashboard::tabBox( + width = "100%", + # Title can include an icon + title = shiny::tagList(shiny::icon("gear"), "Case Series"), + shiny::tabPanel("Binary Feature Table", + resultTableViewer(ns('binaryTable')) + ), + shiny::tabPanel("Continuous Feature Table", + resultTableViewer(ns('continuousTable')) + ) + ) + ) + ) + +} + + + +characterizationCaseSeriesServer <- function( + id, + connectionHandler, + resultDatabaseSettings, + targetId, #reactive + outcomeId #reactive +) { + shiny::moduleServer( + id, + function(input, output, session) { + + # get databases + options <- shiny::reactive({ + characterizationGetCaseSeriesOptions( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetId = targetId(), + outcomeId = outcomeId() + ) + }) + + output$inputs <- shiny::renderUI({ # need to make reactive? + + shiny::div( + shiny::selectInput( + inputId = session$ns('databaseId'), + label = 'Database: ', + choices = options()$databaseIds, + selected = options()$databaseIds[1], + multiple = F + ), + + shiny::selectInput( + inputId = session$ns('tarId'), + label = 'Time-at-risk: ', + choices = options()$tarIds, + selected = options()$tarIds[1], + multiple = F + ), + + shiny::actionButton( + inputId = session$ns('generate'), + label = 'Generate' + ) + ) + + }) + + shiny::observeEvent(input$generate, { + + allData <- characterizationGetCaseSeriesData( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetId = targetId(), + outcomeId = outcomeId(), + databaseId = input$databaseId, + timeAtRiskId = input$tarId + ) + + binTableOutputs <- resultTableServer( + id = "binaryTable", + df = allData$binary, + colDefsInput = colDefs(), # function below + addActions = NULL + ) + + conTableOutputs <- resultTableServer( + id = "continuousTable", + df = allData$continuous, + colDefsInput = colDefs(), # function below + addActions = NULL + ) + + }) + + return(invisible(NULL)) + } + ) +} + + +characterizationGetCaseSeriesOptions <- function( + connectionHandler, + resultDatabaseSettings, + targetId, + outcomeId +){ + + sql <- "SELECT distinct cd.database_id, d.CDM_SOURCE_ABBREVIATION as database_name, + cd.time_at_risk_id, + t.RISK_WINDOW_START, t.RISK_WINDOW_END, + t.START_ANCHOR, t.END_ANCHOR + from + @schema.@c_table_prefixcohort_details cd + inner join @schema.@database_meta_table d + on cd.database_id = d.database_id + inner join @schema.@c_table_prefixtime_at_risk t + on t.database_id = cd.database_id + and t.run_id = cd.run_id + and t.time_at_risk_id = cd.time_at_risk_id + + where cd.target_cohort_id = @target_id + and cd.outcome_cohort_id = @outcome_id + and cd.time_at_risk_id != 0 + ;" + + options <- connectionHandler$queryDb( + sql = sql, + schema = resultDatabaseSettings$schema, + c_table_prefix = resultDatabaseSettings$cTablePrefix, + database_meta_table = resultDatabaseSettings$databaseTable, + target_id = targetId, + outcome_id = outcomeId + ) + + db <- unique(options$databaseId) + names(db) <- unique(options$databaseName) + + tar <- unique(options$timeAtRiskId) + names(tar) <- paste0('(', options$startAnchor, ' + ', options$riskWindowStart, ') - (', + options$endAnchor, ' + ', options$riskWindowEnd, ')' + ) + + return( + list( + databaseIds = db, + tarIds = tar + ) + ) + +} + + +characterizationGetCaseSeriesData <- function( + connectionHandler, + resultDatabaseSettings, + targetId, + outcomeId, + databaseId, + timeAtRiskId +){ + + ids <- + + shiny::withProgress(message = 'Getting case series data', value = 0, { + shiny::incProgress(1/4, detail = paste("Extracting ids")) + + sql <- "SELECT cohort_definition_id, cohort_type + from + @schema.@c_table_prefixcohort_details + where target_cohort_id = @target_id + and outcome_cohort_id = @outcome_id + and database_id = '@database_id' + and time_at_risk_id = @time_at_risk_id + and cohort_type in ('TnObetween','OnT','TnO') + ;" + + ids <- connectionHandler$queryDb( + sql = sql, + schema = resultDatabaseSettings$schema, + c_table_prefix = resultDatabaseSettings$cTablePrefix, + target_id = targetId, + outcome_id = outcomeId, + database_id = databaseId, + time_at_risk_id = timeAtRiskId + ) + + shiny::incProgress(2/4, detail = paste("Extracting binary")) + + sql <- "SELECT cov.cohort_definition_id, cr.covariate_name, cov.covariate_id, cov.sum_value, cov.average_value + from + @schema.@c_table_prefixcovariates cov + inner join @schema.@c_table_prefixcovariate_ref cr + on cov.run_id = cr.run_id and + cov.database_id = cr.database_id and + cov.covariate_id = cr.covariate_id + where cov.cohort_definition_id in (@ids) + and cov.database_id = '@database_id' + ;" + + binary <- connectionHandler$queryDb( + sql = sql, + schema = resultDatabaseSettings$schema, + c_table_prefix = resultDatabaseSettings$cTablePrefix, + ids = paste0(ids$cohortDefinitionId, collapse = ','), + database_id = databaseId + ) + + # now process into table + binary <- caseSeriesTable( + data = binary, + ids = ids + ) + + shiny::incProgress(3/4, detail = paste("Extracting continuous")) + + sql <- "SELECT cov.cohort_definition_id, cr.covariate_name, cov.covariate_id, + cov.count_value, cov.min_value, cov.max_value, cov.average_value, + cov.standard_deviation, cov.median_value, cov.p_10_value, + cov.p_25_value, cov.p_75_value, cov.p_90_value + from + @schema.@c_table_prefixcovariates_continuous cov + inner join @schema.@c_table_prefixcovariate_ref cr + on cov.run_id = cr.run_id and + cov.database_id = cr.database_id and + cov.covariate_id = cr.covariate_id + where cov.cohort_definition_id in (@ids) + and cov.database_id = '@database_id' + ;" + + # TODO - how to remove prior outcomes?? + continuous <- connectionHandler$queryDb( + sql = sql, + schema = resultDatabaseSettings$schema, + c_table_prefix = resultDatabaseSettings$cTablePrefix, + ids = paste0(ids$cohortDefinitionId, collapse = ','), + database_id = databaseId + ) + + # add type + ids <- merge(ids, data.frame( + cohortType = c('TnObetween','OnT','TnO'), + type = c('During', "After", 'Before') + ), by = 'cohortType') %>% + dplyr::select("cohortDefinitionId","type") + continuous <- merge(ids, continuous, by = 'cohortDefinitionId') + + shiny::incProgress(4/4, detail = paste("Done")) + + }) + + return( + list( + binary = binary, + continuous = continuous + ) + ) +} + + +# now process into table +caseSeriesTable <- function( + data, + ids +){ + + timeBeforeId <- ids$cohortDefinitionId[ids$cohortType == 'TnO'] + timeDuringId <- ids$cohortDefinitionId[ids$cohortType == 'TnObetween'] + timeAfterId <- ids$cohortDefinitionId[ids$cohortType == 'OnT'] + + + # Before Index Cases + beforeData <- data %>% + dplyr::filter(.data$cohortDefinitionId == !!timeBeforeId) %>% + dplyr::select(-"cohortDefinitionId") + Nbefore <- beforeData$sumValue[1]/beforeData$averageValue[1] + + # After Index Cases + afterData <- data %>% + dplyr::filter(.data$cohortDefinitionId == !!timeAfterId) %>% + dplyr::select(-"cohortDefinitionId") + Nafter <- afterData$sumValue[1]/afterData$averageValue[1] + + # During Index Cases + duringData <- data %>% + dplyr::filter(.data$cohortDefinitionId == !!timeDuringId) %>% + dplyr::select(-"cohortDefinitionId") + Nduring <- duringData$sumValue[1]/duringData$averageValue[1] + + + beforeData <- beforeData %>% + dplyr::mutate( + sumValueBefore = .data$sumValue, + averageValueBefore = .data$averageValue, + ) %>% + dplyr::select("covariateName", "covariateId", "sumValueBefore", "averageValueBefore") + + afterData <-afterData %>% + dplyr::mutate( + sumValueAfter = .data$sumValue, + averageValueAfter = .data$averageValue, + ) %>% + dplyr::select("covariateName", "covariateId", "sumValueAfter", "averageValueAfter") + + duringData <- duringData %>% + dplyr::mutate( + sumValueDuring = .data$sumValue, + averageValueDuring = .data$averageValue, + ) %>% + dplyr::select("covariateName", "covariateId", "sumValueDuring", "averageValueDuring") + + + + allResults <- beforeData %>% + dplyr::full_join( + y = duringData, + by = c("covariateName", "covariateId") + ) %>% + dplyr::full_join( + y = afterData, + by = c("covariateName", "covariateId") + ) + + return(allResults) +} + +colDefs <- function(){ + result <- list( + covariateName = reactable::colDef( + name = "Covariate Name", + filterable = T + ), + covariateId = reactable::colDef( + show = F + ), + sumValueBefore = reactable::colDef( + name = "Number of cases with feature before exposure", + format = reactable::colFormat(digits = 2, percent = F), + cell = function(value) { + if(is.null(value)){return('< min threshold')} + if(is.na(value)){return('< min threshold')} + if (value != -1) value else '< min threshold' + } + ), + averageValueBefore = reactable::colDef( + name = "% of cases with feature before exposure", + format = reactable::colFormat(digits = 2, percent = T) + ), + sumValueDuring = reactable::colDef( + name = "Number of cases with feature during exposure", + format = reactable::colFormat(digits = 2, percent = F), + cell = function(value) { + if(is.null(value)){return('< min threshold')} + if(is.na(value)){return('< min threshold')} + if (value != -1) value else '< min threshold' + } + ), + averageValueDuring = reactable::colDef( + name = "% of cases with feature during exposure", + format = reactable::colFormat(digits = 2, percent = T) + ), + sumValueAfter = reactable::colDef( + name = "Number of cases with feature after exposure", + format = reactable::colFormat(digits = 2, percent = F), + cell = function(value) { + if(is.null(value)){return('< min threshold')} + if(is.na(value)){return('< min threshold')} + if (value != -1) value else '< min threshold' + } + ), + averageValueAfter = reactable::colDef( + name = "% of cases with feature after exposure", + format = reactable::colFormat(digits = 2, percent = T) + ), + + analysisName = reactable::colDef( + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('desc-cont-select', '%s', event.target.value || undefined)", name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } + ) + ) + return(result) +} + diff --git a/R/characterization-cohorts.R b/R/characterization-cohorts.R index ea314c98..ca452043 100644 --- a/R/characterization-cohorts.R +++ b/R/characterization-cohorts.R @@ -17,214 +17,309 @@ # limitations under the License. -#' The module viewer for exploring 1 or more cohorts features -#' -#' @details -#' The user specifies the id for the module -#' -#' @param id the unique reference id for the module -#' -#' @return -#' The user interface to the description cohorts features -#' -#' @export -characterizationTableViewer <- function(id) { +# view two cohorts and compare +characterizationCohortComparisonViewer <- function(id) { ns <- shiny::NS(id) - shiny::div( - - infoHelperViewer( - id = "helper", - helpLocation= system.file("characterization-www", "help-targetViewer.html", package = utils::packageName()) - ), - - + # module that does input selection for a single row DF - inputSelectionViewer( - id = ns("input-selection") - ), - - shiny::conditionalPanel( - condition = 'input.generate != 0', - ns = shiny::NS(ns("input-selection")), + shiny::div( - # add basic table - resultTableViewer(id = ns('mainTable')) - + # UI for inputs + # summary table + shinydashboard::box( + collapsible = TRUE, + title = "Options", + width = "100%", + shiny::uiOutput(ns("inputs")) + ), + + # displayed inputs + shiny::conditionalPanel( + condition = "input.generate != 0", + ns = ns, + + inputSelectionDfViewer(id = ns('inputSelected'), title = 'Selected'), + + # add basic table + resultTableViewer(id = ns('countTable'), boxTitle = 'Counts'), + resultTableViewer(id = ns('mainTable'), boxTitle = 'Binary') + + ) ) - ) } -#' The module server for exploring 1 or more cohorts features -#' -#' @details -#' The user specifies the id for the module -#' -#' @param id the unique reference id for the module -#' @param connectionHandler the connection to the prediction result database -#' @param resultDatabaseSettings a list containing the characterization result schema, dbms, tablePrefix, databaseTable and cgTablePrefix -#' -#' @return -#' The server to the cohorts features server -#' -#' @export -characterizationTableServer <- function( + +characterizationCohortComparisonServer <- function( id, connectionHandler, - resultDatabaseSettings + resultDatabaseSettings, + options, + parents, + parentIndex # reactive ) { shiny::moduleServer( id, function(input, output, session) { - inputVals <- getDecCohortsInputs( - connectionHandler, - resultDatabaseSettings + inputVals <- characterizationGetCohortsInputs( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings ) - # input selection component - inputSelected <- inputSelectionServer( - id = "input-selection", - inputSettingList = list( - createInputSetting( - rowNumber = 1, - columnWidth = 6, - varName = 'targetIds', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Target: ', - choices = inputVals$cohortIds, - selected = inputVals$cohortIds, - multiple = F, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) + children <- shiny::reactive({ + characterizationGetChildren(options, parentIndex()) + }) + + # update targetId2 + initialChildren2 <- characterizationGetChildren(options, 1) + + children2 <- shiny::reactiveVal() + shiny::observeEvent(input$parentTargetId2,{ + newIndex <- which(input$parentTargetId2 == parents) + result <- characterizationGetChildren(options, newIndex) + children2(result) + shinyWidgets::updatePickerInput( + session = session, + inputId = 'targetId2', + label = 'Second Target: ', + choices = result, + selected = result[1] ) - ), - createInputSetting( - rowNumber = 1, - columnWidth = 6, - varName = 'databaseIds', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Database: ', - choices = inputVals$databaseIds, - selected = inputVals$databaseIds[1], - multiple = T, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) + + }) + + output$inputs <- shiny::renderUI({ + + shiny::div( + shinyWidgets::pickerInput( + inputId = session$ns('targetId1'), + label = 'First Target: ', + choices = children(), + selected = 1, + multiple = F, + options = shinyWidgets::pickerOptions( + actionsBox = TRUE, + liveSearch = TRUE, + size = 10, + liveSearchStyle = "contains", + liveSearchPlaceholder = "Type here to search", + virtualScroll = 50 ) ), + shiny::selectInput( + inputId = session$ns('parentTargetId2'), + label = 'Second Parent Target: ', + choices = parents, + selected = parents[1], + multiple = F + ), - createInputSetting( - rowNumber = 2, - columnWidth = 6, - varName = 'analysisIds', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Covariate Type: ', - choices = inputVals$analysisIds, - selected = inputVals$analysisIds[1], - multiple = F, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) + shinyWidgets::pickerInput( + inputId = session$ns('targetId2'), + label = 'Second Target: ', + choices = initialChildren2, + selected = initialChildren2[1], + multiple = F, + options = shinyWidgets::pickerOptions( + actionsBox = TRUE, + liveSearch = TRUE, + size = 10, + liveSearchStyle = "contains", + liveSearchPlaceholder = "Type here to search", + virtualScroll = 50 ) + ), + + shinyWidgets::pickerInput( + inputId = session$ns('databaseId'), + label = 'Database: ', + choices = inputVals$databaseIds, + selected = inputVals$databaseIds[1], + multiple = F, + options = shinyWidgets::pickerOptions( + actionsBox = TRUE, + liveSearch = TRUE, + size = 10, + liveSearchStyle = "contains", + liveSearchPlaceholder = "Type here to search", + virtualScroll = 50 ) - - ) + ), + + shiny::actionButton( + inputId = session$ns('generate'), + label = 'Generate' + ) ) - columns <- shiny::reactive({ - - result <- list( + }) + + + columns <- list( + covariateName = reactable::colDef( + header = withTooltip( + "Covariate Name", + "The name of the covariate" + ) + ), covariateId = reactable::colDef( + show = F, header = withTooltip("Covariate ID", "Unique identifier of the covariate") ), - covariateName = reactable::colDef( - header = withTooltip( - "Covariate Name", - "The name of the covariate" - ) + firstVar = reactable::colDef( + show = F + ), + secondVar = reactable::colDef( + show = F + ), + sumValue_1 = reactable::colDef( + header = withTooltip("First Sum", + "The total sum of the covariate for the first selected cohort."), + cell = function(value) { + if (value >= 0) value else '< min threshold' + } + ), + sumValue_2 = reactable::colDef( + header = withTooltip("Second Sum", + "The total sum of the covariate for the second selected cohort."), + cell = function(value) { + if (value >= 0) value else '< min threshold' + } + ), + averageValue_1 = reactable::colDef( + header = withTooltip("First Mean", + "The mean of the covariate for the first selected cohort."), + cell = function(value) { + if (value >= 0) round(value, digits = 3) else '< min threshold' + } ), + averageValue_2 = reactable::colDef( + header = withTooltip("Second Mean", + "The mean of the covariate for the second selected cohort."), + cell = function(value) { + if (value >= 0) round(value, digits = 3) else '< min threshold' + } + ), + SMD = reactable::colDef( + header = withTooltip("SMD", + "Standardized mean difference"), + format = reactable::colFormat(digits = 3) + ), + absSMD = reactable::colDef( + header = withTooltip("absSMD", + "Absolute standardized mean difference"), + format = reactable::colFormat(digits = 3) + ), analysisName = reactable::colDef( header = withTooltip( "Covariate Class", "Class/type of the covariate" ) ) + + # add other columns ) + + # show selected inputs to user + inputSelectionDfServer( + id = 'inputSelected', + dataFrameRow = selected, + ncol = 1 + ) + + #get results + selected <- shiny::reactiveVal() + shiny::observeEvent(input$generate,{ - if(is.null(inputSelected()$targetIds) | is.null(inputSelected()$databaseIds)){ - return(result) - } else{ - temp <- expand.grid(inputSelected()$targetIds,inputSelected()$databaseIds) - temp[,2] <- as.double(as.character(temp[,2])) - - for(i in 1:nrow(temp)){ - - targetName = names(inputVals$cohortIds)[temp[i,1] == inputVals$cohortIds] - databaseName = names(inputVals$databaseIds)[temp[i,2] == inputVals$databaseIds] - - result[[length(result) + 1]] <- reactable::colDef( - header = withTooltip( - paste0("Count-", temp[i,1], '-',temp[i,2]), - paste0("The number of patients in database ", databaseName, ' and target ', targetName, ' who has the covariate') - ) - ) - - names(result)[length(result)] <- paste0('countT', temp[i,1], 'D', ifelse(temp[i,2] <0, 'n', ''), abs(temp[i,2]) ) - - result[[length(result) + 1]] <- reactable::colDef( - header = withTooltip( - paste0("Mean-", temp[i,1], '-', temp[i,2]), - paste0("The mean covariate value for patients in database ", databaseName, ' and target ', targetName) - ), - format = reactable::colFormat( - digits = 3 - ) - ) - names(result)[length(result)] <- paste0('averageT', temp[i,1], 'D', ifelse(temp[i,2] <0, 'n', ''), abs(temp[i,2]) ) - - } - return(result) + runTables <- TRUE + + if(is.null(input$targetId1) | is.null(input$targetId2)){ + runTables <- FALSE + } + if(is.null(input$databaseId)){ + runTables <- FALSE } - }) - - #get results - resultTable <- shiny::reactive({ - getCohortData( + if(input$targetId1 == input$targetId2){ + runTables <- FALSE + shiny::showNotification('Must select different cohorts') + } + + selected( + data.frame( + `First Target` = names(children())[which(input$targetId1 == children())], + `Second Target` = names(children2())[which(input$targetId2 == children2())], + Database = names(inputVals$databaseIds)[input$databaseId == inputVals$databaseIds] + ) + ) + + selection1 <- options[[parentIndex()]]$children[[which(input$targetId1 == children())]]$charIds %>% + dplyr::filter(.data$databaseId == input$databaseId) %>% + dplyr::filter(.data$cohortDefinitionId == input$targetId1) + + if(nrow(selection1) == 0){ + runTables <- FALSE + shiny::showNotification('No results for section 1') + } + + selection2 <- options[[which(input$parentTargetId2 == parents)]]$children[[which(input$targetId2 == children2())]]$charIds %>% + dplyr::filter(.data$databaseId == input$databaseId) %>% + dplyr::filter(.data$cohortDefinitionId == input$targetId2) + + if(nrow(selection2) == 0){ + runTables <- FALSE + shiny::showNotification('No results for section 2') + } + + + if(runTables){ + resultTable <- characterizatonGetCohortComparisonData( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - targetIds = inputSelected()$targetIds, - databaseIds = inputSelected()$databaseIds, - analysisIds = inputSelected()$analysisIds + targetId1 = selection1$charCohortId[1], + targetId2 = selection2$charCohortId[1], + databaseId = input$databaseId, + minThreshold = 0.01, + addSMD = T ) - }) - - resultTableServer( - id = 'mainTable', - df = resultTable, - colDefsInput = columns() - ) + + countTable <- characterizatonGetCohortCounts( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = c(selection1$charCohortId[1],selection2$charCohortId[1]), + targetNames = c( + names(children())[which(input$targetId1 == children())], + names(children2())[which(input$targetId2 == children2())] + ), + databaseId = input$databaseId + ) + + resultTableServer( + id = 'mainTable', + df = resultTable, + colDefsInput = columns + ) + + resultTableServer( + id = 'countTable', + df = countTable, + colDefsInput = NULL + )} else{ + resultTableServer( + id = 'mainTable', + df = data.frame(), + colDefsInput = columns + ) + + resultTableServer( + id = 'countTable', + df = data.frame(), + colDefsInput = NULL + ) + } + }) return(invisible(NULL)) @@ -232,136 +327,177 @@ characterizationTableServer <- function( } +characterizatonGetCohortComparisonData <- function( + connectionHandler, + resultDatabaseSettings, + targetId1, + targetId2, + databaseId, + minThreshold, + addSMD +){ + result <- characterizatonGetCohortData( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = c(targetId1, targetId2), + databaseIds = c(databaseId,databaseId), + minThreshold = minThreshold, + addSMD = addSMD + ) + + return(result) +} + -getCohortData <- function( +characterizatonGetCohortCounts <- function( connectionHandler, resultDatabaseSettings, targetIds, - databaseIds, - analysisIds + targetNames, + databaseId ){ - if(is.null(targetIds) | is.null(databaseIds)){ - return(NULL) - } + start <- Sys.time() + result <- connectionHandler$queryDb( + sql = " +select cc.* + from + @schema.@c_table_prefixcohort_counts cc + + where cc.cohort_definition_id in (@target_ids) + and cc.database_id = '@database_id' + and cc.run_id = 1 + ; + ", + schema = resultDatabaseSettings$schema, + c_table_prefix = resultDatabaseSettings$cTablePrefix, + target_ids = paste0(targetIds, collapse= ','), + database_id = databaseId + ) + end <- Sys.time() - start + message(paste0('Extracting ', nrow(result) ,' cohort count rows took: ', round(end, digits = 2), ' ', units(end))) - combinations <- expand.grid(targetIds, databaseIds) - combinations[,2] <- as.double(as.character(combinations[,2])) + result <- merge( + x = result, + y = data.frame( + selection = c('First','Second'), + cohortDefinitionId = targetIds, + cohortName = targetNames + ), + by = 'cohortDefinitionId' + ) -sql <- paste0( -"select ref.covariate_id, ref.covariate_name, an.analysis_name,", - -paste( - lapply(1:nrow(combinations), function(i){ - paste0( -"max(case when temp.selection_id = ",i," then temp.sum_value else 0 end) as count_t",combinations[i,1],'_d',ifelse(combinations[i,2] <0, 'n', ''),abs(combinations[i,2]),",", -"max(case when temp.selection_id = ",i," then temp.average_value else 0 end) as average_t",combinations[i,1],'_d',ifelse(combinations[i,2] <0, 'n', ''),abs(combinations[i,2]) -)}), collapse = ','), - -" from @schema.@c_table_prefixcovariate_ref ref - inner join @schema.@c_table_prefixanalysis_ref an - on an.RUN_ID = ref.RUN_ID and - an.analysis_id = ref.analysis_id and - ref.analysis_id in (@analysis_ids) + result <- result %>% dplyr::select( + 'selection', + 'cohortName', + 'rowCount', + 'personCount' + ) + return(result) + +} - left join -( ", +characterizatonGetCohortData <- function( + connectionHandler, + resultDatabaseSettings, + targetIds, + databaseIds, + minThreshold = 0.01, + addSMD = F +){ + if(is.null(targetIds) | is.null(databaseIds)){ + warning('Ids cannot be NULL') + return(NULL) + } -paste( - lapply(1:nrow(combinations), function(i){ + shiny::withProgress(message = 'characterizatonGetCohortData', value = 0, { + + shiny::incProgress(1/4, detail = paste("Setting types")) + + types <- data.frame( + type = 1:length(targetIds), + cohortDefinitionId = targetIds, + databaseId = databaseIds + ) + + shiny::incProgress(2/4, detail = paste("Extracting data")) + + sql <- paste0( paste0( - " - select - co",i,".run_id, co",i,".COVARIATE_ID, co",i,".SUM_VALUE, co",i,".AVERAGE_VALUE, - ",i," as selection_id - from - @schema.@c_table_prefixCOVARIATES co",i," - inner join - (select * from @schema.@c_table_prefixcohort_details - where DATABASE_ID = '@database",i,"' and - TARGET_COHORT_ID = @target",i," and COHORT_TYPE = 'T' - ) as cd",i," - on co",i,".COHORT_DEFINITION_ID = cd",i,".COHORT_DEFINITION_ID - and co",i,".DATABASE_ID = cd",i,".DATABASE_ID" - ) - - }), collapse = ' union '), - -") temp -on ref.run_id = temp.run_id and -ref.covariate_id = temp.covariate_id - -group by -ref.covariate_id, ref.covariate_name, an.analysis_name -" - -) - - - inputs <- c( - as.character(combinations$Var2), - as.character(combinations$Var1), - resultDatabaseSettings$schema, - resultDatabaseSettings$cTablePrefix, - paste0(analysisIds, collapse = ',') - ) - names(inputs) <- c( - paste0('database', 1:nrow(combinations)), - paste0('target', 1:nrow(combinations)), - 'schema', - 'c_table_prefix', - 'analysis_ids' - ) - inputs <- as.list(inputs) - inputs$sql <- sql + paste0( + "select ref.covariate_name, cov.* from + @schema.@c_table_prefixCOVARIATES cov + inner join + @schema.@c_table_prefixcovariate_ref ref + on cov.covariate_id = ref.covariate_id + and cov.run_id = ref.run_id + and cov.database_id = ref.database_id + + where cov.cohort_definition_id = @target_id",1:length(targetIds), + " and cov.database_id = '@database_id",1:length(targetIds),"' + and cov.average_value >= @min_threshold" + ), collapse = ' union ' + ),';' + ) + + inputList <- as.list(c(targetIds, databaseIds)) + names(inputList) <- c(paste0('target_id', 1:length(targetIds)), paste0('database_id', 1:length(databaseIds))) + inputList$sql <- sql + inputList$schema <- resultDatabaseSettings$schema + inputList$c_table_prefix <- resultDatabaseSettings$cTablePrefix + inputList$min_threshold <- minThreshold + + start <- Sys.time() + # settings.min_characterization_mean needed? + res <- do.call(what = connectionHandler$queryDb, args = inputList) + end <- Sys.time() - start + shiny::incProgress(3/4, detail = paste("Extracted data")) + message(paste0('Extracting ', nrow(res) ,' characterization cohort rows took: ', round(end, digits = 2), ' ', units(end))) + + # add the first/section type + res <- merge(res, types, by = c('cohortDefinitionId','databaseId')) + + # pivot + result <- tidyr::pivot_wider( + data = res, + id_cols = c('covariateName', 'covariateId'), + names_from = 'type', + values_from = c('sumValue', 'averageValue'), + values_fn = mean, + values_fill = -1 + ) + + if(addSMD == T){ + # TODO get min_characterization_mean from settings table + # minCharacterizationMean <- minThreshold + # add SMD + convertMissing <- function(vec){sapply(vec, function(x) ifelse(x==-1, minThreshold, x))} + result$firstVar <- convertMissing(result$averageValue_1)*(1-convertMissing(result$averageValue_1))^2 + result$secondVar <- convertMissing(result$averageValue_2)*(1-convertMissing(result$averageValue_2))^2 + result$SMD <- (convertMissing(result$averageValue_1) - convertMissing(result$averageValue_2))/(sqrt((result$firstVar+result$secondVar)/2)) + result$absSMD <- abs(result$SMD) + } + + shiny::incProgress(4/4, detail = paste("Done")) + }) - result <- do.call(connectionHandler$queryDb, inputs) - -return(result) + return(result) } -getDecCohortsInputs <- function( +characterizationGetCohortsInputs <- function( connectionHandler, resultDatabaseSettings ) { - #shiny::withProgress(message = 'Getting target comparison inputs', value = 0, { - - - sql <- - ' select distinct c.cohort_definition_id, c.cohort_name from - @schema.@cg_table_prefixcohort_definition c - inner join - (select distinct TARGET_COHORT_ID as id - from @schema.@c_table_prefixcohort_details - ) ids - on ids.id = c.cohort_definition_id - ;' - - #shiny::incProgress(1/4, detail = paste("Extracting targetIds")) - - idVals <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - c_table_prefix = resultDatabaseSettings$cTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix - ) - ids <- idVals$cohortDefinitionId - names(ids) <- idVals$cohortName - - #shiny::incProgress(2/4, detail = paste("Extracted targetIds")) - - + sql <- 'select d.database_id, d.cdm_source_abbreviation as database_name from @schema.@database_table d;' - #shiny::incProgress(3/4, detail = paste("Extracting databaseIds")) - database <- connectionHandler$queryDb( sql = sql, schema = resultDatabaseSettings$schema, @@ -369,32 +505,10 @@ getDecCohortsInputs <- function( ) databaseIds <- database$databaseId names(databaseIds) <- database$databaseName - - - sql <- 'select distinct analysis_id, analysis_name - from @schema.@c_table_prefixanalysis_ref order by analysis_name desc;' - - #shiny::incProgress(3/4, detail = paste("Extracting databaseIds")) - - analyses <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - c_table_prefix = resultDatabaseSettings$cTablePrefix - ) - analysisIds <- analyses$analysisId - names(analysisIds) <- analyses$analysisName - - - #shiny::incProgress(4/4, detail = paste("Done")) - - # }) - + return( list( - cohortIds = ids, - databaseIds = databaseIds, - analysisIds = analysisIds + databaseIds = databaseIds ) ) - } diff --git a/R/characterization-database.R b/R/characterization-database.R new file mode 100644 index 00000000..33c3b441 --- /dev/null +++ b/R/characterization-database.R @@ -0,0 +1,281 @@ +# @file characterization-timeToEvent.R +# +# Copyright 2024 Observational Health Data Sciences and Informatics +# +# This file is part of OhdsiShinyModules +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# view two cohorts and compare +characterizationDatabaseComparisonViewer <- function(id) { + ns <- shiny::NS(id) + + shiny::div( + + # UI for inputs + # summary table + shinydashboard::box( + collapsible = TRUE, + title = "Options", + width = "100%", + shiny::uiOutput(ns("inputs")) + ), + + # displayed inputs + shiny::conditionalPanel( + condition = "input.generate != 0", + ns = ns, + + inputSelectionDfViewer(id = ns('inputSelected'), title = 'Selected'), + + # add basic table + resultTableViewer(id = ns('mainTable'), boxTitle = 'Binary') + + ) + ) +} + + + +characterizationDatabaseComparisonServer <- function( + id, + connectionHandler, + resultDatabaseSettings, + options, + parents, + parentIndex # reactive +) { + shiny::moduleServer( + id, + function(input, output, session) { + + # TODO replace this with database input + inputVals <- characterizationGetCohortsInputs( + connectionHandler, + resultDatabaseSettings + ) + + children <- shiny::reactive({ + characterizationGetChildren(options, parentIndex()) + }) + + output$inputs <- shiny::renderUI({ + + shiny::div( + shinyWidgets::pickerInput( + inputId = session$ns('targetId'), + label = 'Target: ', + choices = children(), + selected = 1, + multiple = F, + options = shinyWidgets::pickerOptions( + actionsBox = TRUE, + liveSearch = TRUE, + size = 10, + liveSearchStyle = "contains", + liveSearchPlaceholder = "Type here to search", + virtualScroll = 50 + ) + ), + + shiny::selectInput( + inputId = session$ns('databaseIds'), + label = 'Databases: ', + choices = inputVals$databaseIds, + selected = 1, + multiple = T + ), + + shiny::sliderInput( + inputId = session$ns('minThreshold'), + label = 'Covariate Threshold', + min = 0, + max = 1, + value = 0.01, + step = 0.01, + ticks = F + ), + + shiny::actionButton( + inputId = session$ns('generate'), + label = 'Generate' + ) + ) + + }) + + + # show selected inputs to user + inputSelectionDfServer( + id = 'inputSelected', + dataFrameRow = selected, + ncol = 1 + ) + + #get results + selected <- shiny::reactiveVal() + shiny::observeEvent(input$generate,{ + + if(is.null(input$targetId)){ + return(NULL) + } + + selected( + data.frame( + Target = names(children())[which(input$targetId == children())], + minTreshold = input$minThreshold + ) + ) + + selectedChildChar <- options[[parentIndex()]]$children[[which(input$targetId == children())]]$charIds + + + #get results + if(sum(selectedChildChar$databaseId %in% input$databaseIds) > 0){ + result <- characterizatonGetDatabaseComparisonData( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = selectedChildChar$charCohortId[selectedChildChar$databaseId %in% input$databaseIds], + databaseIds = selectedChildChar$databaseId[selectedChildChar$databaseId %in% input$databaseIds], + minThreshold = input$minThreshold + ) + databaseNames <- result$databaseNames + + meanColumns <- lapply(1:nrow(databaseNames), function(i){ + reactable::colDef( + header = withTooltip( + paste0("Mean ", databaseNames$databaseName[i]), + paste0("The mean of the covariate for database ", databaseNames$databaseName[i]) + ), + cell = function(value) { + if (value >= 0) round(value, digits = 3) else '< min threshold' + } + ) + }) + names(meanColumns) <- unlist(lapply(1:nrow(databaseNames), function(i) paste0('averageValue_',databaseNames$id[i]))) + + sumColumns <- lapply(1:nrow(databaseNames), function(i){ + reactable::colDef( + header = withTooltip( + paste0("Sum ", databaseNames$databaseName[i]), + paste0("The sums of the covariate for database ", databaseNames$databaseName[i]) + ), + cell = function(value) { + if (value >= 0) value else '< min threshold' + } + ) + }) + names(sumColumns) <- unlist(lapply(1:nrow(databaseNames), function(i) paste0('sumValue_',databaseNames$id[i]))) + + print('HERE 3') + + columns <- append( + list( + covariateName = reactable::colDef( + header = withTooltip( + "Covariate Name", + "The name of the covariate" + ) + ), + covariateId = reactable::colDef( + show = F, + header = withTooltip("Covariate ID", + "Unique identifier of the covariate") + ) + ), + append( + sumColumns, + meanColumns + ) + ) + + print('HERE 4') + + resultTableServer( + id = 'mainTable', + df = result$table, + colDefsInput = columns + ) + } else{ + shiny::showNotification('No results') + resultTableServer( + id = 'mainTable', + df = data.frame(), + colDefsInput = list( + covariateName = reactable::colDef( + header = withTooltip( + "Covariate Name", + "The name of the covariate" + ) + ), + covariateId = reactable::colDef( + show = F, + header = withTooltip("Covariate ID", + "Unique identifier of the covariate") + ) + ) + ) + } + + + }) + + + return(invisible(NULL)) + + }) + +} + +characterizatonGetDatabaseComparisonData <- function( + connectionHandler, + resultDatabaseSettings, + targetIds, + databaseIds, + minThreshold +){ + + result <- characterizatonGetCohortData( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = targetIds, + databaseIds = databaseIds, + minThreshold = minThreshold, + addSMD = F # unless two databases? + ) + + databaseNames <- connectionHandler$queryDb( + sql = "select cdm_source_abbreviation as database_name, database_id + from @schema.@database_table;", + schema = resultDatabaseSettings$schema, + database_table = resultDatabaseSettings$databaseTable + ) + + databaseNames <- merge( + databaseNames, + data.frame( + id = 1:length(databaseIds), + databaseId = databaseIds + ), + by = 'databaseId' + ) + + return( + list( + table = result, + databaseNames = databaseNames + ) + ) + +} diff --git a/R/characterization-dechallengeRechallenge.R b/R/characterization-dechallengeRechallenge.R index 3ecbb464..14ab6768 100644 --- a/R/characterization-dechallengeRechallenge.R +++ b/R/characterization-dechallengeRechallenge.R @@ -31,24 +31,7 @@ characterizationDechallengeRechallengeViewer <- function(id) { ns <- shiny::NS(id) shiny::div( - - # helper component module - infoHelperViewer( - id = "helper", - helpLocation= system.file("characterization-www", "help-dechallengeRechallenge.html", package = utils::packageName()) - ), - - # input component module - inputSelectionViewer(id = ns('input-selection')), - - shiny::conditionalPanel( - condition = 'input.generate != 0', - ns = shiny::NS(ns("input-selection")), - resultTableViewer(ns('tableResults')) - - - ) ) } @@ -69,74 +52,21 @@ characterizationDechallengeRechallengeViewer <- function(id) { characterizationDechallengeRechallengeServer <- function( id, connectionHandler, - resultDatabaseSettings + resultDatabaseSettings, + targetId, + outcomeId ) { shiny::moduleServer( id, function(input, output, session) { - # get the possible target ids - bothIds <- dechalRechalGetIds( - connectionHandler, - resultDatabaseSettings - ) - - # input selection component - inputSelected <- inputSelectionServer( - id = "input-selection", - inputSettingList = list( - createInputSetting( - rowNumber = 1, - columnWidth = 6, - varName = 'targetId', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Target: ', - choices = bothIds$targetIds, - #choicesOpt = list(style = rep_len("color: black;", 999)), - selected = bothIds$targetIds[1], - multiple = F, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ), - - createInputSetting( - rowNumber = 1, - columnWidth = 6, - varName = 'outcomeId', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Outcome: ', - choices = bothIds$outcomeIds, - #choicesOpt = list(style = rep_len("color: black;", 999)), - selected = bothIds$outcomeIds[1], - multiple = F, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ) - ) - ) # fetch data when targetId changes allData <-shiny::reactive({ getDechalRechalInputsData( - targetId = inputSelected()$targetId, - outcomeId = inputSelected()$outcomeId, + targetId = targetId(), + outcomeId = outcomeId(), connectionHandler = connectionHandler, resultDatabaseSettings ) @@ -183,8 +113,8 @@ characterizationDechallengeRechallengeServer <- function( if(!is.null(tableOutputs$actionType())){ if(tableOutputs$actionType() == 'fails'){ result <- getDechalRechalFailData( - targetId = inputSelected()$targetId, - outcomeId = inputSelected()$outcomeId, + targetId = targetId(), + outcomeId = outcomeId(), databaseId = allData()$databaseId[tableOutputs$actionIndex()$index], # update? dechallengeStopInterval = allData()$dechallengeStopInterval[tableOutputs$actionIndex()$index], dechallengeEvaluationWindow = allData()$dechallengeEvaluationWindow[tableOutputs$actionIndex()$index], @@ -227,6 +157,7 @@ characterizationDechallengeRechallengeServer <- function( ) } +# can delete? dechalRechalGetIds <- function( connectionHandler, resultDatabaseSettings diff --git a/R/characterization-incidence.R b/R/characterization-incidence.R index 370e091b..ce29f65f 100644 --- a/R/characterization-incidence.R +++ b/R/characterization-incidence.R @@ -38,43 +38,6 @@ as_ggplot <- function(x){ } -# is_null_unit <- function (x) -# { -# if (!grid::is.unit(x)) { -# return(FALSE) -# } -# all(grid::unitType(x) == "null") -# } -# -# force_panelsizes <- function(rows = NULL, cols = NULL, respect = NULL, total_width = NULL, total_height = NULL) { -# if (!is.null(rows) & !grid::is.unit(rows)) { -# rows <- grid::unit(rows, "null") -# } -# if (!is.null(cols) & !grid::is.unit(cols)) { -# cols <- grid::unit(cols, "null") -# } -# if (!is.null(total_width)) { -# if (grid::is.unit(cols) && !is_null_unit(cols)) { -# stop("Cannot set {.arg total_width} when {.arg cols} is not relative.") -# } -# if (!grid::is.unit(total_width)) { -# stop("{.arg total_width} must be a {.cls unit} object.") -# } -# rlang::arg_match0(grid::unitType(total_width), c("cm", "mm", "inches", "points")) -# } -# if (!is.null(total_height)) { -# if (grid::is.unit(rows) && !is_null_unit(rows)) { -# stop("Cannot set {.arg total_height} when {.arg rows} is not relative.") -# } -# if (!grid::is.unit(total_height)) { -# stop("{.arg total_height} must be a {.cls unit} object.") -# } -# rlang::arg_match0(grid::unitType(total_height), c("cm", "mm", "inches", "points")) -# } -# structure(list(rows = rows, cols = cols, respect = respect, total_width = total_width, total_height = total_height), class = "forcedsize") -# } - - # Define the custom age sorting function custom_age_sort <- function(age_categories) { # Extract the largest integer from each category @@ -99,10 +62,6 @@ break_setter = function(n = 5) { - - - - #' The module viewer for exploring incidence results #' #' @details @@ -117,19 +76,12 @@ break_setter = function(n = 5) { characterizationIncidenceViewer <- function(id) { ns <- shiny::NS(id) shiny::div( - - infoHelperViewer( - id = "helper", - helpLocation= system.file("characterization-www", "help-incidenceRate.html", package = utils::packageName()) - ), - inputSelectionViewer( - id = ns("input-selection-results") - ), + shiny::uiOutput(ns("inputOptions")), shiny::conditionalPanel( condition = 'input.generate != 0', - ns = shiny::NS(ns("input-selection-results")), + ns = ns, shiny::tabsetPanel( type = 'pills', @@ -292,185 +244,167 @@ characterizationIncidenceViewer <- function(id) { characterizationIncidenceServer <- function( id, connectionHandler, - resultDatabaseSettings + resultDatabaseSettings, + options, + parents, + parentIndex, # reactive + outcomes, # reactive + subTargets# reactive ) { shiny::moduleServer( id, function(input, output, session) { - ## ns <- session$ns - options <- getIncidenceOptions( # written using getTargetOutcomes - connectionHandler, - resultDatabaseSettings - ) + ages <- c(2:12, NA) + names(ages) <- c(sapply(2:12, function(i) paste0((i-2)*10,' - ',(i-1)*10-1)), 'All') + + sex <- c(8507, 8532 , NA) + names(sex) <- c('Male', 'Female', 'All') + + startYear <- c(NA, format(Sys.Date(), "%Y"):1990) + names(startYear) <- c('All', format(Sys.Date(), "%Y"):1990) + + # get tar and then call cohortIncidenceFormatTar() + + tarDf <- data.frame( + tarId = 1:3, + tarStartWith = c('start','start','start'), + tarStartOffset = c(1,1,1), + tarEndWith = c('start','start','end'), + tarEndOffset = c(9999,30,0) + ) + sortedTars <- tarDf$tarId + names(sortedTars) <- cohortIncidenceFormatTar(tarDf) + + output$inputOptions <- shiny::renderUI({ + shinydashboard::box( + collapsible = TRUE, + title = "Options", + width = "100%", + + shiny::div( + "Select Your Results", + style = "font-weight: bold; font-size: 20px; text-align: center; margin-bottom: 20px;" + ), + + shiny::selectInput( + inputId = session$ns('targetIds'), + label = 'Target: ', + choices = subTargets(), + selected = 1, + multiple = T, + selectize = TRUE, + width = NULL, + size = NULL + ), + + shiny::selectInput( + inputId = session$ns('outcomeIds'), + label = 'Outcome: ', + choices = outcomes(), + selected = 1, + multiple = T, + selectize = TRUE, + width = NULL, + size = NULL + ), + + shinyWidgets::pickerInput( + inputId = session$ns('ageIds'), + label = 'Filter By Age Group: ', + choices = ages, + selected = ages, + multiple = T, + options = shinyWidgets::pickerOptions( + actionsBox = TRUE, + liveSearch = TRUE, + size = 10, + dropupAuto = TRUE, + liveSearchStyle = "contains", + liveSearchPlaceholder = "Type here to search", + virtualScroll = 50 + ) + ), + + shinyWidgets::pickerInput( + inputId = session$ns('sexIds'), + label = 'Filter By Sex: ', + choices = sex, + selected = sex, + multiple = T, + options = shinyWidgets::pickerOptions( + actionsBox = TRUE, + liveSearch = TRUE, + size = 10, + dropupAuto = TRUE, + liveSearchStyle = "contains", + liveSearchPlaceholder = "Type here to search", + virtualScroll = 50 + ) + ), + + shinyWidgets::pickerInput( + inputId = session$ns('startYears'), + label = 'Filter By Start Year: ', + choices = startYear, + selected = startYear, + multiple = T, + options = shinyWidgets::pickerOptions( + actionsBox = TRUE, + liveSearch = TRUE, + size = 10, + dropupAuto = TRUE, + liveSearchStyle = "contains", + liveSearchPlaceholder = "Type here to search", + virtualScroll = 50 + ) + ), + + shinyWidgets::pickerInput( + inputId = session$ns('tars'), + label = 'Select Time at risk (TAR)', + choices = sortedTars, + selected = sortedTars[1], + multiple = F, + options = shinyWidgets::pickerOptions( + actionsBox = TRUE, + liveSearch = TRUE, + size = 10, + dropupAuto = TRUE, + liveSearchStyle = "contains", + liveSearchPlaceholder = "Type here to search", + virtualScroll = 50 + ) + ), + + shiny::actionButton( + inputId = session$ns('generate'), + label = 'Generate', + icon = shiny::icon('redo') + ) + ) + }) - sortedAges <- custom_age_sort(options$ageGroupName) + outcomeIds <- shiny::reactiveVal(NULL) + targetIds <- shiny::reactiveVal(NULL) + incidenceRateTarFilter <- shiny::reactiveVal(NULL) + incidenceRateCalendarFilter <- shiny::reactiveVal(NULL) + incidenceRateAgeFilter <- shiny::reactiveVal(NULL) + incidenceRateGenderFilter <- shiny::reactiveVal(NULL) + shiny::observeEvent(input$generate,{ + incidenceRateTarFilter(input$tars) + incidenceRateCalendarFilter(input$startYears) + incidenceRateAgeFilter(input$ageIds) + incidenceRateGenderFilter(input$sexIds) + outcomeIds(input$outcomeIds) + targetIds(input$targetIds) + }) - # Extract the integers from each TAR string - tarIntegers <- as.integer(gsub("[^0-9]", "", options$tar)) - # Sort the vector based on the extracted integers - sortedTars <- options$tar[order(tarIntegers)] - # input selection component - inputSelectedResults <- inputSelectionServer( - id = "input-selection-results", - inputSettingList = list( - createInputSetting( - rowNumber = 1, - columnWidth = 12, - varName = 'firsttext', - inputReturn = T, - uiFunction = 'shiny::div', - uiInputs = list( - "Select Your Results", - style = "font-weight: bold; font-size: 20px; text-align: center; margin-bottom: 20px;" - ) - ), - createInputSetting( - rowNumber = 2, - columnWidth = 6, - varName = 'targetIds', - uiFunction = 'shinyWidgets::pickerInput', - updateFunction = 'shinyWidgets::updatePickerInput', - uiInputs = list( - label = 'Target: ', - choices = options$targetIds, - selected = options$targetIds[1], #default should be just one (the first) - multiple = T, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ), - createInputSetting( - rowNumber = 2, - columnWidth = 6, - varName = 'outcomeIds', - uiFunction = 'shinyWidgets::pickerInput', - updateFunction = 'shinyWidgets::updatePickerInput', - uiInputs = list( - label = 'Outcome: ', - choices = options$outcomeIds, - selected = options$outcomeIds[1], #default should be just one (the first) - multiple = T, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ), - - # third row - createInputSetting( - rowNumber = 3, - columnWidth = 3, - varName = 'incidenceRateAgeFilter', - uiFunction = 'shinyWidgets::pickerInput', - updateFunction = 'shinyWidgets::updatePickerInput', - collapse = T, - uiInputs = list( - label = 'Filter By Age Group: ', - choices = sortedAges, - selected = sortedAges, - multiple = T, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - dropupAuto = TRUE, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ), - - - createInputSetting( - rowNumber = 3, - columnWidth = 3, - varName = 'incidenceRateGenderFilter', - uiFunction = 'shinyWidgets::pickerInput', - updateFunction = 'shinyWidgets::updatePickerInput', - collapse = T, - uiInputs = list( - label = 'Filter By Sex: ', - choices = sort(options$genderName, decreasing = F), - selected = options$genderName, - multiple = T, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - dropupAuto = TRUE, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ), - - createInputSetting( - rowNumber = 3, - columnWidth = 3, - varName = 'incidenceRateCalendarFilter', - uiFunction = 'shinyWidgets::pickerInput', - updateFunction = 'shinyWidgets::updatePickerInput', - collapse = T, - uiInputs = list( - label = 'Filter By Start Year: ', - choices = sort(options$startYear, decreasing = T), - selected = options$startYear, - multiple = T, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - dropupAuto = TRUE, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ), - - createInputSetting( - rowNumber = 3, - columnWidth = 3, - varName = 'incidenceRateTarFilter', - uiFunction = 'shinyWidgets::pickerInput', - updateFunction = 'shinyWidgets::updatePickerInput', - uiInputs = list( - label = 'Select Time at risk (TAR)', - choices = sortedTars, - selected = sortedTars[1], - multiple = F, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - dropupAuto = TRUE, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ) - ) - ) - - # 4th row text + options <- getIncidenceOptions() + inputSelectedCustomPlot <- inputSelectionServer( id = "input-selection-custom-plot", inputSettingList = list( @@ -667,21 +601,21 @@ characterizationIncidenceServer <- function( filteredData <- shiny::reactive( { - if (is.null(inputSelectedResults()$targetIds) | - is.null(inputSelectedResults()$outcomeIds) + if (is.null(targetIds()) | + is.null(outcomeIds()) ) { return(data.frame()) } - else if(inputSelectedResults()$targetIds==inputSelectedResults()$outcomeIds && - length(inputSelectedResults()$targetIds)==1 && length(inputSelectedResults()$outcomeIds)==1 + else if(targetIds() == outcomeIds() && + length(targetIds())==1 && length(outcomeIds())==1 ){ shiny::validate("Target and outcome cohorts must differ from each other. Make a different selection.") } else { - getIncidenceData(targetIds = inputSelectedResults()$targetIds, - outcomeIds = inputSelectedResults()$outcomeIds, + getIncidenceData(targetIds = targetIds(), + outcomeIds = outcomeIds(), connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings ) %>% @@ -691,9 +625,9 @@ characterizationIncidenceServer <- function( dplyr::across(dplyr::where(is.numeric), round, 4), targetIdShort = paste("C", .data$targetCohortDefinitionId, sep = "-"), outcomeIdShort = paste("C", .data$outcomeCohortDefinitionId, sep = "-")) %>% - dplyr::filter(.data$ageGroupName %in% !!inputSelectedResults()$incidenceRateAgeFilter & - .data$genderName %in% !!inputSelectedResults()$incidenceRateGenderFilter & - .data$startYear %in% !!inputSelectedResults()$incidenceRateCalendarFilter + dplyr::filter(.data$ageGroupName %in% !! incidenceRateAgeFilter() & + .data$genderName %in% !! incidenceRateGenderFilter() & + .data$startYear %in% !! incidenceRateCalendarFilter() ) %>% dplyr::relocate("targetIdShort", .after = "targetName") %>% dplyr::relocate("outcomeIdShort", .after = "outcomeName") @@ -703,21 +637,21 @@ characterizationIncidenceServer <- function( filteredDataAggregateForPlot <- shiny::reactive( { - if (is.null(inputSelectedResults()$targetIds) | - is.null(inputSelectedResults()$outcomeIds) + if (is.null(targetIds()) | + is.null(outcomeIds()) ) { return(data.frame()) } - else if(inputSelectedResults()$targetIds==inputSelectedResults()$outcomeIds && - length(inputSelectedResults()$targetIds)==1 && length(inputSelectedResults()$outcomeIds)==1 + else if(targetIds() == outcomeIds() && + length(targetIds()) == 1 && length(outcomeIds()) == 1 ){ shiny::validate("Target and outcome cohorts must differ from each other. Make a different selection.") } else { - getIncidenceData(targetIds = inputSelectedResults()$targetIds, - outcomeIds = inputSelectedResults()$outcomeIds, + getIncidenceData(targetIds = targetIds(), + outcomeIds = outcomeIds(), connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings ) %>% @@ -769,14 +703,14 @@ characterizationIncidenceServer <- function( #ir plots irPlotCustom <- shiny::reactive( { - if (is.null(inputSelectedResults()$targetIds) | - is.null(inputSelectedResults()$outcomeIds)) { + if (is.null(targetIds()) | + is.null(outcomeIds())) { return(data.frame()) } - ifelse(inputSelectedResults()$incidenceRateTarFilter %in% filteredData()$tar, + ifelse(incidenceRateTarFilter() %in% filteredData()$tar, plotData <- filteredData() %>% - dplyr::filter(.data$tar %in% inputSelectedResults()$incidenceRateTarFilter), + dplyr::filter(.data$tar %in% incidenceRateTarFilter()), shiny::validate("Selected TAR is not found in your result data. Revise input selections or select a different TAR.") ) @@ -1054,45 +988,12 @@ characterizationIncidenceServer <- function( legend.box.spacing = ggplot2::unit(3, "pt"), legend.text = ggplot2::element_text(size=10), legend.title = ggplot2::element_text(size=16, face = "bold"), - #plot.caption = ggplot2::element_text(hjust = 0, face = "italic", size = 12), - #legend.spacing.x = ggplot2::unit(2.0, 'cm'), - # legend.box = "horizontal", - # legend.key.size = ggplot2::unit(3, 'points'), #change legend key size - # legend.title = ggplot2::element_text(size=30), #change legend title font size - # legend.text = ggplot2::element_text(size=20), - panel.spacing = ggplot2::unit(2, "lines"), - # strip.background = ggplot2::element_blank(), + panel.spacing = ggplot2::unit(2, "lines"), strip.text = ggplot2::element_text(face="bold", size = 14) ) + ggplot2::guides(shape = ggplot2::guide_legend(override.aes = list(size = 6)), color = ggplot2::guide_legend(override.aes = list(size = 6))) - # - # # Create a custom color scale - # color_scale <- RColorBrewer::colorRampPalette(brewer.pal(9, "YlOrRd"))(100) - # - # # Create a faceted heatmap by outcome and data source - # p <- ggplot2::ggplot(data = plotData, aes(x = targetIdShort, y = ageGroupName, - # text = paste("Outcome ID:", outcomeIdShort, "
Outcome:", outcomeName, - # "
Target ID:", targetIdShort, "
Target:", targetName, - # "
TAR:", tar, "
Age:", ageGroupName, "
Sex:", genderName, - # "
TAR:", - # "
Incidence Rate:", incidenceRateP100py))) + - # ggplot2::geom_tile(aes(fill = incidenceRateP100py), color = "white") + - # ggplot2::scale_fill_gradient(colors = color_scale, name = "Incidence Rate") + - # ggplot2::labs(title = "Incidence Rate by Strata Variables", - # x = "Target Population Cohort", - # y = "Age Category") + - # ggplot2::theme_minimal() + - # ggplot2::theme(axis.text.x = ggplot2::element_text(angle = 45, hjust = 1), - # plot.title = element_text(hjust = 0.5)) + - # ggplot2::facet_grid(outcome ~ data_source, scales = "free_x", space = "free_x") - # - # # Convert the ggplot plot to a Plotly plot - # p <- plotly::ggplotly(p) - # - # - } @@ -1109,14 +1010,14 @@ characterizationIncidenceServer <- function( #render the event reactive incidence plot without legend renderIrPlotCustomNoLegend <- shiny::reactive( { - if (is.null(inputSelectedResults()$targetIds) | - is.null(inputSelectedResults()$outcomeIds)) { + if (is.null(targetIds()) | + is.null(outcomeIds())) { shiny::validate("Please select at least one target and one outcome.") } else { plotData <- filteredData() %>% - dplyr::filter(.data$tar %in% inputSelectedResults()$incidenceRateTarFilter) + dplyr::filter(.data$tar %in% incidenceRateTarFilter()) # Get the number of facets in both rows and columns num_rows <- length(unique(plotData[[inputSelectedCustomPlot()$plotXTrellis]])) @@ -1163,14 +1064,14 @@ characterizationIncidenceServer <- function( #render the event reactive incidence plot without legend renderIrPlotCustom <- shiny::reactive( { - if (is.null(inputSelectedResults()$targetIds) | - is.null(inputSelectedResults()$outcomeIds)) { + if (is.null(targetIds()) | + is.null(outcomeIds())) { shiny::validate("Please select at least one target and one outcome.") } else { plotData <- filteredData() %>% - dplyr::filter(.data$tar %in% inputSelectedResults()$incidenceRateTarFilter) + dplyr::filter(.data$tar %in% incidenceRateTarFilter()) # Get the number of facets in both rows and columns num_rows <- length(unique(plotData[[inputSelectedCustomPlot()$plotXTrellis]])) @@ -1227,25 +1128,25 @@ characterizationIncidenceServer <- function( renderIrPlotStandardAge <- shiny::reactive( { - if (is.null(inputSelectedResults()$targetIds) | - is.null(inputSelectedResults()$outcomeIds)) { + if (is.null(targetIds()) | + is.null(outcomeIds())) { return(data.frame()) } - ifelse(inputSelectedResults()$incidenceRateTarFilter %in% filteredData()$tar, + ifelse(incidenceRateTarFilter() %in% filteredData()$tar, plotData <- filteredData() %>% - dplyr::filter(.data$tar %in% inputSelectedResults()$incidenceRateTarFilter), + dplyr::filter(.data$tar %in% incidenceRateTarFilter()), shiny::validate("Selected TAR is not found in your result data. Revise input selections or select a different TAR.") ) #add check to make sure facetted plots fit nicely in plotting window (600px). this is currently nrow * ncol in facet_wrap() - ifelse(length(inputSelectedResults()$targetId) * length(inputSelectedResults()$outcomeId) <= 10, + ifelse(length(targetIds()) * length(outcomeIds()) <= 10, plotData <- filteredData(), shiny::validate("Too many Target-Outcome pairs selected to plot efficiently. Please choose fewer targets and/or outcomes.") ) #add check to make sure "> 1 distinct age is selected for by age plot"any" is in selection for year and sex - ifelse("Any" %in% inputSelectedResults()$incidenceRateCalendarFilter & "Any" %in% inputSelectedResults()$incidenceRateGenderFilter, + ifelse("Any" %in% incidenceRateCalendarFilter() & "Any" %in% incidenceRateGenderFilter(), plotData <- filteredData(), shiny::validate("This standard plot is designed to show results aggregated over all (`Any`) year and sex categories. Please make sure you have selected `Any` in the `Select your results` section above for these variables.") ) @@ -1331,13 +1232,7 @@ characterizationIncidenceServer <- function( legend.title.align = 0.5, plot.caption = ggplot2::element_text(hjust = 0, face = "italic", size = 12, margin = ggplot2::margin(t = 20)), - #legend.spacing.x = ggplot2::unit(2.0, 'cm'), - # legend.box = "horizontal", - # legend.key.size = ggplot2::unit(3, 'points'), #change legend key size - # legend.title = ggplot2::element_text(size=30), #change legend title font size - # legend.text = ggplot2::element_text(size=20), panel.spacing = ggplot2::unit(2, "lines"), - # strip.background = ggplot2::element_blank(), strip.text = ggplot2::element_text(face="bold", size = 14), strip.background = ggplot2::element_blank(), strip.clip = "off" @@ -1375,25 +1270,25 @@ characterizationIncidenceServer <- function( renderIrPlotStandardAgeSex <- shiny::reactive( { - if (is.null(inputSelectedResults()$targetIds) | - is.null(inputSelectedResults()$outcomeIds)) { + if (is.null(targetIds()) | + is.null(outcomeIds())) { return(data.frame()) } - ifelse(inputSelectedResults()$incidenceRateTarFilter %in% filteredData()$tar, + ifelse(incidenceRateTarFilter() %in% filteredData()$tar, plotData <- filteredData() %>% - dplyr::filter(.data$tar %in% inputSelectedResults()$incidenceRateTarFilter), + dplyr::filter(.data$tar %in% incidenceRateTarFilter()), shiny::validate("Selected TAR is not found in your result data. Revise input selections or select a different TAR.") ) #add check to make sure facetted plots fit nicely in plotting window (600px). this is currently nrow * ncol in facet_wrap() - ifelse(length(inputSelectedResults()$targetId) * length(inputSelectedResults()$outcomeId) <= 10, + ifelse(length(targetIds()) * length(outcomeIds()) <= 10, plotData <- filteredData(), shiny::validate("Too many Target-Outcome pairs selected to plot efficiently. Please choose fewer targets and/or outcomes.") ) #add check to make sure "Any" is in the year filter - ifelse("Any" %in% inputSelectedResults()$incidenceRateCalendarFilter, + ifelse("Any" %in% incidenceRateCalendarFilter(), plotData <- filteredData(), shiny::validate("This standard plot is designed to show results aggregated over all (`Any`) year categories. Please make sure you have selected `Any` in the `Select your results` section above for this variable.") ) @@ -1479,13 +1374,7 @@ renderIrPlotStandardAgeSex <- shiny::reactive( legend.title.align = 0.5, plot.caption = ggplot2::element_text(hjust = 0, face = "italic", size = 12, margin = ggplot2::margin(t = 20)), - #legend.spacing.x = ggplot2::unit(2.0, 'cm'), - # legend.box = "horizontal", - # legend.key.size = ggplot2::unit(3, 'points'), #change legend key size - # legend.title = ggplot2::element_text(size=30), #change legend title font size - # legend.text = ggplot2::element_text(size=20), panel.spacing = ggplot2::unit(2, "lines"), - # strip.background = ggplot2::element_blank(), strip.text = ggplot2::element_text(face="bold", size = 14), strip.background = ggplot2::element_blank(), strip.clip = "off" @@ -1521,25 +1410,25 @@ output$downloadPlotStandardAgeSex <- shiny::downloadHandler( renderIrPlotStandardYear <- shiny::reactive( { - if (is.null(inputSelectedResults()$targetIds) | - is.null(inputSelectedResults()$outcomeIds)) { + if (is.null(targetIds()) | + is.null(outcomeIds())) { return(data.frame()) } - ifelse(inputSelectedResults()$incidenceRateTarFilter %in% filteredData()$tar, + ifelse(incidenceRateTarFilter() %in% filteredData()$tar, plotData <- filteredData() %>% - dplyr::filter(.data$tar %in% inputSelectedResults()$incidenceRateTarFilter), + dplyr::filter(.data$tar %in% incidenceRateTarFilter()), shiny::validate("Selected TAR is not found in your result data. Revise input selections or select a different TAR.") ) - ifelse(length(inputSelectedResults()$incidenceRateTarFilter %in% filteredData()$tar) == 1, + ifelse(length(incidenceRateTarFilter() %in% filteredData()$tar) == 1, plotData <- filteredData() %>% - dplyr::filter(.data$tar %in% inputSelectedResults()$incidenceRateTarFilter), + dplyr::filter(.data$tar %in% incidenceRateTarFilter()), shiny::validate("Please select only one TAR at a time to view yearly plots.") ) - ifelse((length(inputSelectedResults()$targetIds) == 1) & - (length(inputSelectedResults()$outcomeIds) == 1), + ifelse((length(targetIds()) == 1) & + (length(outcomeIds()) == 1), plotData <- plotData, shiny::validate("Please select only one Target and Outcome at a time to view yearly plots.") ) @@ -1590,24 +1479,12 @@ renderIrPlotStandardYear <- shiny::reactive( ) + ggplot2::geom_line(ggplot2::aes(linetype = genderName)) + ggplot2::scale_colour_brewer(palette = "Paired") + - #geom_jitter() + - #scale_size_continuous(range = c(5,15)) + - # ggplot2::scale_colour_brewer(palette = "Paired") + - # ggplot2::facet_grid( - # rows = dplyr::vars(Outcome), - # cols = dplyr::vars(Age), - # labeller = ggplot2::labeller(.rows = outcomeLabeller, - # .cols = ageLabeller), - # scales = "free_y" - # ) + ggplot2::facet_wrap( ~Age, labeller = "label_both", scales = "free_x", nrow = 2 ) + - # scale_y_continuous(#breaks = base_breaks(), - # trans = 'log10') ggplot2::scale_y_continuous(trans=scales::pseudo_log_trans(base = 10), n.breaks = 3) @@ -1617,9 +1494,7 @@ renderIrPlotStandardYear <- shiny::reactive( x = paste(names(options$irPlotCategoricalChoices[options$irPlotCategoricalChoices %in% "startYear"]), "\n"), y = paste(names(options$irPlotNumericChoices[options$irPlotNumericChoices %in% "incidenceRateP100py"]), " (log10 scale)"), color = names(options$irPlotCategoricalChoices[options$irPlotCategoricalChoices %in% "cdmSourceAbbreviation"]), - #size = names(options$irPlotNumericChoices[options$irPlotNumericChoices %in% "outcomes"]), shape = names(options$irPlotCategoricalChoices[options$irPlotCategoricalChoices %in% "genderName"]), - #linetype = names(options$irPlotCategoricalChoices[options$irPlotCategoricalChoices %in% "genderName"]), caption = caption_text ) + ggplot2::guides(alpha = "none", size = "none", linetype = "none") + # Remove the alpha and size legend @@ -1638,13 +1513,7 @@ renderIrPlotStandardYear <- shiny::reactive( legend.title.align = 0.5, plot.caption = ggplot2::element_text(hjust = 0, face = "italic", size = 12, margin = ggplot2::margin(t = 20)), - #legend.spacing.x = ggplot2::unit(2.0, 'cm'), - # legend.box = "horizontal", - # legend.key.size = ggplot2::unit(3, 'points'), #change legend key size - # legend.title = ggplot2::element_text(size=30), #change legend title font size - # legend.text = ggplot2::element_text(size=20), panel.spacing = ggplot2::unit(2, "lines"), - # strip.background = ggplot2::element_blank(), strip.text = ggplot2::element_text(face="bold", size = 14), strip.background = ggplot2::element_blank(), strip.clip = "off" @@ -1686,19 +1555,19 @@ output$downloadPlotStandardYear <- shiny::downloadHandler( renderIrPlotStandardAggregate <- shiny::reactive( { - if (is.null(inputSelectedResults()$targetIds) | - is.null(inputSelectedResults()$outcomeIds)) { + if (is.null(targetIds()) | + is.null(outcomeIds())) { return(data.frame()) } - ifelse(inputSelectedResults()$incidenceRateTarFilter %in% filteredData()$tar, + ifelse(incidenceRateTarFilter() %in% filteredData()$tar, plotData <- filteredDataAggregateForPlot() %>% - dplyr::filter(.data$tar %in% inputSelectedResults()$incidenceRateTarFilter), + dplyr::filter(.data$tar %in% incidenceRateTarFilter()), shiny::validate("Selected TAR is not found in your result data. Revise input selections or select a different TAR.") ) #add check to make sure facetted plots fit nicely in plotting window (600px). this is currently nrow * ncol in facet_wrap() - ifelse(length(inputSelectedResults()$targetId) * length(inputSelectedResults()$outcomeId) <= 10, + ifelse(length(targetIds()) * length(outcomeIds()) <= 10, plotData <- filteredData(), shiny::validate("Too many Target-Outcome pairs selected to plot efficiently. Please choose fewer targets and/or outcomes.") ) @@ -1758,8 +1627,6 @@ renderIrPlotStandardAggregate <- shiny::reactive( x = paste(names(options$irPlotCategoricalChoices[options$irPlotCategoricalChoices %in% "startYear"]), "\n"), y = names(options$irPlotNumericChoices[options$irPlotNumericChoices %in% "incidenceRateP100py"]), color = names(options$irPlotCategoricalChoices[options$irPlotCategoricalChoices %in% "cdmSourceAbbreviation"]), - #size = names(options$irPlotNumericChoices[options$irPlotNumericChoices %in% "outcomes"]), - #shape = names(options$irPlotCategoricalChoices[options$irPlotCategoricalChoices %in% "genderName"]), caption = caption_text ) + ggplot2::guides(alpha = "none", size = "none") + # Remove the alpha and size legend @@ -1778,13 +1645,7 @@ renderIrPlotStandardAggregate <- shiny::reactive( legend.title.align = 0.5, plot.caption = ggplot2::element_text(hjust = 0, face = "italic", size = 12, margin = ggplot2::margin(t = 20)), - #legend.spacing.x = ggplot2::unit(2.0, 'cm'), - # legend.box = "horizontal", - # legend.key.size = ggplot2::unit(3, 'points'), #change legend key size - # legend.title = ggplot2::element_text(size=30), #change legend title font size - # legend.text = ggplot2::element_text(size=20), panel.spacing = ggplot2::unit(2, "lines"), - # strip.background = ggplot2::element_blank(), strip.text = ggplot2::element_text(face="bold", size = 14), strip.background = ggplot2::element_blank(), strip.clip = "off" @@ -1843,7 +1704,7 @@ getIncidenceData <- function( if(!is.null(targetIds) & !is.null(outcomeIds)){ - #shiny::withProgress(message = 'Getting incidence data', value = 0, { + shiny::withProgress(message = 'Getting incidence data', value = 0, { sql <- 'select d.cdm_source_abbreviation, i.* from @result_schema.@incidence_table_prefixINCIDENCE_SUMMARY i @@ -1853,7 +1714,7 @@ getIncidenceData <- function( and outcome_cohort_definition_id in (@outcome_ids) ;' - #shiny::incProgress(1/2, detail = paste("Created SQL - Extracting...")) + shiny::incProgress(1/2, detail = paste("Created SQL - Extracting...")) resultTable <- connectionHandler$queryDb( sql = sql, @@ -1864,12 +1725,14 @@ getIncidenceData <- function( database_table_name = resultDatabaseSettings$databaseTable ) - #shiny::incProgress(2/2, detail = paste("Done...")) + shiny::incProgress(2/2, detail = paste("Done...")) - #}) + }) # format the tar - resultTable$tar <- paste0('(',resultTable$tarStartWith, " + ", resultTable$tarStartOffset, ') - (', resultTable$tarEndWith, " + ", resultTable$tarEndOffset, ')') + ##Jenna edit resultTable$tar <- paste0('(',resultTable$tarStartWith, " + ", resultTable$tarStartOffset, ') - (', resultTable$tarEndWith, " + ", resultTable$tarEndOffset, ')') + resultTable$tar <- cohortIncidenceFormatTar(resultTable) + resultTable <- resultTable %>% dplyr::select(-c("tarStartWith","tarStartOffset","tarEndWith","tarEndOffset", "tarId", "subgroupName")) @@ -1882,8 +1745,13 @@ getIncidenceData <- function( } } +# Jenna added +cohortIncidenceFormatTar <- function(x){ + result <- paste0('(',x$tarStartWith, " + ", x$tarStartOffset, ') - (', x$tarEndWith, " + ", x$tarEndOffset, ')') + return(result) +} -getIncidenceOptions <- function( +getIncidenceOptionsOld <- function( connectionHandler, resultDatabaseSettings ){ @@ -1972,7 +1840,9 @@ getIncidenceOptions <- function( # shiny::incProgress(3/3, detail = paste("Done")) # }) - +} + +getIncidenceOptions <- function(){ irPlotCategoricalChoices <- list( "cdmSourceAbbreviation", "ageGroupName", @@ -2025,14 +1895,14 @@ getIncidenceOptions <- function( return( list( - targetIds = targetIds, - outcomeIds = outcomeIds, - tar = tar, + #targetIds = targetIds, + #outcomeIds = outcomeIds, + #tar = tar, irPlotNumericChoices = irPlotNumericChoices, - irPlotCategoricalChoices = irPlotCategoricalChoices, - ageGroupName = ageGroupName, - genderName = genderName, - startYear = startYear + irPlotCategoricalChoices = irPlotCategoricalChoices + #ageGroupName = ageGroupName, + #genderName = genderName, + #startYear = startYear ) ) diff --git a/R/characterization-main.R b/R/characterization-main.R index 5cfdf43e..a191bfd2 100644 --- a/R/characterization-main.R +++ b/R/characterization-main.R @@ -46,14 +46,22 @@ characterizationViewer <- function(id=1) { ns <- shiny::NS(id) shinydashboard::box( - status = 'info', width = 12, + status = 'info', width = '100%', title = shiny::span( shiny::icon("table"), "Characterization Viewer"), solidHeader = TRUE, - - shiny::tabsetPanel( - type = 'pills', - id = ns('mainPanel') - ) + + # pick a targetId of interest + shiny::uiOutput(ns("targetSelection")), + + shiny::conditionalPanel( + condition = 'input.targetSelect', + ns = ns, + inputSelectionDfViewer(id = ns('targetSelected'), title = 'Selected'), + shiny::tabsetPanel( + type = 'pills', + id = ns('mainPanel') + ) + ) ) } @@ -79,7 +87,139 @@ characterizationServer <- function( shiny::moduleServer( id, function(input, output, session) { + + #================================================ + # GETTING OPTIONS FOR INPTUS + #================================================ + options <- characterizationGetOptions( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings + ) + + #================================================ + # PARENT TARGET SELECTION UI + #================================================ + parents <- characterizationGetParents(options) + # add an input for all char that lets you select cohort of interest + output$targetSelection <- shiny::renderUI({ + shiny::div( + shiny::selectInput( + inputId = session$ns('targetId'), + label = 'Parent Target: ', + choices = parents, + selected = 1, + multiple = FALSE, + selectize = TRUE, + width = NULL, + size = NULL + ), + shiny::actionButton( + inputId = session$ns('targetSelect'), + label = 'Select', + icon = shiny::icon('redo') + ) + ) + }) + + #================================================ + # PARENT TARGET SELECTION ACTION + #================================================ + # reactives updated when parent target is selected + parentIndex <- shiny::reactiveVal(1) + outcomes <- shiny::reactiveVal() + subTargets <- shiny::reactiveVal() + targetSelected <- shiny::reactiveVal() + # output the selected target + shiny::observeEvent(input$targetSelect, { + + # First create input dataframe and add to the inputServer to display + targetSelected( + data.frame( + `Parent Target` = names(parents)[parents == input$targetId] + ) + ) + inputSelectionDfServer( + id = 'targetSelected', + dataFrameRow = targetSelected, + ncol = 1 + ) + + # update the parentIndex of interest + parentIndex(which(parents == input$targetId )) + # update the outcomes for the selected parent target id + outcomes(characterizationGetOutcomes(options, parentIndex())) + # update the child targets for the selected parent target id + subTargets(characterizationGetChildren(options, parentIndex())) + + # create the outcome selector for the case exposure tabs + output$outcomeSelection <- shiny::renderUI({ + shinydashboard::box( + collapsible = TRUE, + title = "Options", + width = "100%", + shiny::selectInput( + inputId = session$ns('subTargetId'), + label = 'Target: ', + choices = subTargets(), + selected = 1, + multiple = FALSE, + selectize = TRUE, + width = NULL, + size = NULL + ), + shiny::selectInput( + inputId = session$ns('outcomeId'), + label = 'Outcome: ', + choices = outcomes(), + selected = 1, + multiple = FALSE, + selectize = TRUE, + width = NULL, + size = NULL + ), + shiny::actionButton( + inputId = session$ns('outcomeSelect'), + label = 'Select', + icon = shiny::icon('redo') + ) + ) + }) + + }) + + #================================================ + # OUTCOME SELECTION ACTION + #================================================ + # used by the case exposure tabs + # show the selected outcome + outcomeSelected <- shiny::reactiveVal() + outcomeId <- shiny::reactiveVal() + subTargetId <- shiny::reactiveVal() + + shiny::observeEvent(input$outcomeSelect, { + outcomeSelected( + data.frame( + Target = names(subTargets())[subTargets() == input$subTargetId], + Outcome = names(outcomes())[outcomes() == input$outcomeId] + ) + ) + + # store the outcome and subTargetIds for the case exposure tabs + outcomeId(input$outcomeId) + subTargetId(input$subTargetId) + + inputSelectionDfServer( + id = 'outcomeSelected', + dataFrameRow = outcomeSelected, + ncol = 1 + ) + }) + + + #================================================ + # CREATE TABS BASED ON RESULTS TABLES + #================================================ # this function checks tables exist for the tabs # and returns the tabs that should be displayed # as the tables exist @@ -87,109 +227,264 @@ characterizationServer <- function( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings ) - - # add the tabs based on results - types <- list( - c("Target Viewer","characterizationTableViewer", "descriptiveTableTab"), - c("Outcome Stratified", "characterizationAggregateFeaturesViewer", "aggregateFeaturesTab"), - c("Incidence Rate", "characterizationIncidenceViewer", "incidenceTab"), - c("Time To Event", "characterizationTimeToEventViewer", "timeToEventTab"), - c("Dechallenge Rechallenge", 'characterizationDechallengeRechallengeViewer', 'dechallengeRechallengeTab') + + # MAIN PANELS + #first populate the mainPanel + typesMainPanel <- list( + list( + title = 'Cohort Summary', + shiny::tabsetPanel( + type = 'pills', + id = session$ns('cohortSummaryPanel') + ) + ), + list( + title = 'Exposed Cases Summary', + shiny::uiOutput(session$ns("outcomeSelection")), + shiny::conditionalPanel( + condition = 'input.outcomeSelect', + ns = session$ns, + inputSelectionDfViewer(id = session$ns('outcomeSelected'), title = 'Selected'), + shiny::tabsetPanel( + type = 'pills', + id = session$ns('exposedCasesPanel') + ) + ) + ), + list( + title = 'Cohort Incidence', + shiny::tabsetPanel( + type = 'pills', + id = session$ns('cohortIncidencePanel') + ) ) + ) + selectVal <- T - for( type in types){ - if(type[1] %in% charTypes){ + for( type in typesMainPanel){ + if(type$title %in% charTypes$mainPanel){ shiny::insertTab( - inputId = "mainPanel", - tab = shiny::tabPanel( - type[1], - do.call(what = type[2], args = list(id = session$ns(type[3]))) - ), + inputId = 'mainPanel', + tab = do.call( + what = shiny::tabPanel, + args = type + ), select = selectVal ) selectVal = F } - } + + # SUB PANELS + # now populate the subpanel + # add the tabs based on results + types <- rbind( + c("Database Comparison","characterizationDatabaseComparisonViewer", "databaseComparisonTab", "cohortSummaryPanel"), + c("Cohort Comparison", "characterizationCohortComparisonViewer", "cohortComparisonTab", "cohortSummaryPanel"), - previouslyLoaded <- shiny::reactiveVal(c()) + c("Risk Factor", "characterizationRiskFactorViewer", "riskFactorTab", "exposedCasesPanel"), + c("Case Series", "characterizationCaseSeriesViewer", "caseSeriesTab", "exposedCasesPanel"), + c("Time-to-event", "characterizationTimeToEventViewer", "timeToEventTab", "exposedCasesPanel"), + c("Dechallenge Rechallenge", 'characterizationDechallengeRechallengeViewer', 'dechallengeRechallengeTab', "exposedCasesPanel"), + + c("Incidence Results", "characterizationIncidenceViewer", "cohortIncidenceTab", "cohortIncidencePanel") + ) + colnames(types) <- c('c1', 'c2', 'c3', 'c4') + types <- as.data.frame(types) - # only render the tab when selected + for(subPanel in c("cohortSummaryPanel", "exposedCasesPanel", "cohortIncidencePanel")){ + typesOfInterest <- types %>% dplyr::filter(.data$c4 == subPanel) + if(nrow(typesOfInterest)>0){ + selectVal <- T + for( i in 1:nrow(typesOfInterest)){ + if(typesOfInterest[i,1] %in% charTypes$subPanel){ + shiny::insertTab( + inputId = typesOfInterest[i,4], + tab = shiny::tabPanel( + typesOfInterest[i,1], + do.call(what = typesOfInterest[i,2], args = list(id = session$ns(typesOfInterest[i,3]))) + ), + select = selectVal + ) + selectVal = F + } + } + } + } + + + # ============================= + # TRACK CURRENT TAB + # ============================= + # set the current tab + mainPanel <- shiny::reactiveVal('None') shiny::observeEvent(input$mainPanel,{ + mainPanel(input$mainPanel) + }) + cohortSummaryPanel <- shiny::reactiveVal('None') + shiny::observeEvent(input$cohortSummaryPanel,{ + cohortSummaryPanel(input$cohortSummaryPanel) + }) + exposedCasesPanel <- shiny::reactiveVal('None') + shiny::observeEvent(input$exposedCasesPanel,{ + exposedCasesPanel(input$exposedCasesPanel) + }) + + currentTab <- shiny::reactive({ + if(mainPanel() == "Cohort Summary" & cohortSummaryPanel() == 'Cohort Comparison'){ + return('Cohort Comparison') + } + if(mainPanel() == "Cohort Summary" & cohortSummaryPanel() == 'Database Comparison'){ + return('Database Comparison') + } + if(mainPanel() == "Exposed Cases Summary" & exposedCasesPanel() == 'Risk Factor'){ + return('Risk Factor') + } + if(mainPanel() == "Exposed Cases Summary" & exposedCasesPanel() == 'Case Series'){ + return('Case Series') + } + if(mainPanel() == "Exposed Cases Summary" & exposedCasesPanel() == 'Time-to-event'){ + return('Time-to-event') + } + if(mainPanel() == "Exposed Cases Summary" & exposedCasesPanel() == 'Dechallenge Rechallenge'){ + return('Dechallenge Rechallenge') + } + if(mainPanel() == "Cohort Incidence"){ + return("Cohort Incidence") + } + + return('None') + }) + + # ============================= + # MODULE SERVERS + # ============================= + # store what servers have been loaded and only load them the first time + # when the corresponding tab is loaded + previouslyLoaded <- shiny::reactiveVal(c()) + # only render the tab when selected + shiny::observeEvent(currentTab(), { # ============================= - # Table of cohorts + # Cohort Comparison # ============================= - if(input$mainPanel == "Target Viewer"){ - if(!"Target Viewer" %in% previouslyLoaded()){ - characterizationTableServer( - id = 'descriptiveTableTab', + if(currentTab() == 'Cohort Comparison'){ + if(!"Cohort Comparison" %in% previouslyLoaded()){ + characterizationCohortComparisonServer( + id = 'cohortComparisonTab', connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings + resultDatabaseSettings = resultDatabaseSettings, + options = options, + parents = parents, + parentIndex = parentIndex ) - previouslyLoaded(c(previouslyLoaded(), "Target Viewer")) + previouslyLoaded(c(previouslyLoaded(), "Cohort Comparison")) } } - - - # ============================= - # Aggregrate Features - # ============================= - if(input$mainPanel == "Outcome Stratified"){ - if(!"Outcome Stratified" %in% previouslyLoaded()){ - characterizationAggregateFeaturesServer( - id = 'aggregateFeaturesTab', + + # ============================= + # Database Comparison + # ============================= + if(currentTab() == "Database Comparison"){ + if(!"Database Comparison" %in% previouslyLoaded()){ + characterizationDatabaseComparisonServer( + id = 'databaseComparisonTab', connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings + resultDatabaseSettings = resultDatabaseSettings, + options = options, + parents = parents, + parentIndex = parentIndex ) - previouslyLoaded(c(previouslyLoaded(), "Outcome Stratified")) + previouslyLoaded(c(previouslyLoaded(), "Database Comparison")) } } - + # ============================= - # Incidence + # Risk Factor # ============================= - if(input$mainPanel == "Incidence Rate"){ - if(!"Incidence Rate" %in% previouslyLoaded()){ - characterizationIncidenceServer( - id = 'incidenceTab', + if(currentTab() == "Risk Factor"){ + if(!"Risk Factor" %in% previouslyLoaded()){ + characterizationRiskFactorServer( + id = 'riskFactorTab', connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings + resultDatabaseSettings = resultDatabaseSettings, + targetId = subTargetId, + outcomeId = outcomeId ) - previouslyLoaded(c(previouslyLoaded(), "Incidence Rate")) + previouslyLoaded(c(previouslyLoaded(), "Risk Factor")) } } - - - # ============================= - # Time To Event - # ============================= - if(input$mainPanel == "Time To Event"){ - if(!"Time To Event" %in% previouslyLoaded()){ + + # ============================= + # Case Series + # ============================= + if(currentTab() == 'Case Series'){ + if(!"Case Series" %in% previouslyLoaded()){ + characterizationCaseSeriesServer( + id = 'caseSeriesTab', + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetId = subTargetId, + outcomeId = outcomeId + ) + previouslyLoaded(c(previouslyLoaded(), "Case Series")) + } + } + + # ============================= + # Time-to-event + # ============================= + if(currentTab() == 'Time-to-event'){ + if(!"Time-to-event" %in% previouslyLoaded()){ characterizationTimeToEventServer( - id = 'timeToEventTab', + id = 'timeToEventTab', connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings + resultDatabaseSettings = resultDatabaseSettings, + targetId = subTargetId, + outcomeId = outcomeId ) - previouslyLoaded(c(previouslyLoaded(), "Time To Event")) + previouslyLoaded(c(previouslyLoaded(), "Time-to-event")) } } - - # ============================= - # Dechallenge Rechallenge - # ============================= - if(input$mainPanel == "Dechallenge Rechallenge"){ + + # ============================= + # Dechallenge Rechallenge + # ============================= + if(currentTab() == 'Dechallenge Rechallenge'){ if(!"Dechallenge Rechallenge" %in% previouslyLoaded()){ characterizationDechallengeRechallengeServer( - id = 'dechallengeRechallengeTab', + id = 'dechallengeRechallengeTab', connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings + resultDatabaseSettings = resultDatabaseSettings, + targetId = subTargetId, + outcomeId = outcomeId ) previouslyLoaded(c(previouslyLoaded(), "Dechallenge Rechallenge")) } } - }) # end observed input tab + + # ============================= + # Incidence + # ============================= + if(currentTab() == "Cohort Incidence"){ + if(!"Incidence Results" %in% previouslyLoaded()){ + characterizationIncidenceServer( + id = 'cohortIncidenceTab', + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + options = options, + parents = parents, + parentIndex = parentIndex, # reactive + outcomes = outcomes, # reactive + subTargets = subTargets# reactive + ) + previouslyLoaded(c(previouslyLoaded(), "Incidence Results")) + } + } + }) + + } ) @@ -210,13 +505,21 @@ getCharacterizationTypes <- function( connection = conn, databaseSchema = resultDatabaseSettings$schema ) - + + #"Database Comparison" - TODO check multiple databases? + # check Targets if(sum(paste0( resultDatabaseSettings$cTablePrefix, c('covariates', 'covariate_ref', 'cohort_details', 'settings') ) %in% tbls) == 4){ - results <- c(results, "Target Viewer", "Outcome Stratified" ) + results <- rbind( + results, + c("Database Comparison",'Cohort Summary', 'cohortSummaryPanel'), + c("Cohort Comparison",'Cohort Summary', 'cohortSummaryPanel'), + c("Risk Factor",'Exposed Cases Summary', 'exposedCasesPanel'), + c("Case Series",'Exposed Cases Summary', 'exposedCasesPanel') + ) } # check dechallenge_rechallenge @@ -224,7 +527,10 @@ getCharacterizationTypes <- function( resultDatabaseSettings$cTablePrefix, 'dechallenge_rechallenge' ) %in% tbls){ - results <- c(results, "Dechallenge Rechallenge") + results <- rbind( + results, + c("Dechallenge Rechallenge",'Exposed Cases Summary', 'exposedCasesPanel') + ) } # check time_to_event @@ -232,7 +538,10 @@ getCharacterizationTypes <- function( resultDatabaseSettings$cTablePrefix, 'time_to_event' ) %in% tbls){ - results <- c(results, "Time To Event") + results <- rbind( + results, + c("Time-to-event",'Exposed Cases Summary', 'exposedCasesPanel') + ) } # check incidence @@ -240,8 +549,133 @@ getCharacterizationTypes <- function( resultDatabaseSettings$incidenceTablePrefix, 'incidence_summary' ) %in% tbls){ - results <- c(results, "Incidence Rate") + results <- rbind( + results, + c("Incidence Results",'Cohort Incidence', 'cohortIncidencePanel') + ) } - return(results) + + + return(list( + mainPanel = unique(results[,2]), + subPanel = unique(results[,1]) + )) +} + + +characterizationGetOptions <- function( + connectionHandler, + resultDatabaseSettings + ){ + + # get cohorts + cg <- connectionHandler$queryDb( + sql = 'select * from @schema.@cg_table_prefixcohort_definition;', + schema = resultDatabaseSettings$schema, + cg_table_prefix = resultDatabaseSettings$cgTablePrefix + ) + +# database_id needed for old results but not for new ones +cohorts <- connectionHandler$queryDb( +sql = " +select database_id, cohort_definition_id as char_cohort_id, outcome_cohort_id as cohort_definition_id, cohort_type +from @schema.@c_table_prefixcohort_details +where cohort_type = 'O' + +union + +select database_id, cohort_definition_id as char_cohort_id, outcome_cohort_id as cohort_definition_id, cohort_type +from @schema.@c_table_prefixcohort_details +where cohort_type = 'Oall' + +union + +select database_id, cohort_definition_id as char_cohort_id, target_cohort_id as cohort_definition_id, cohort_type +from @schema.@c_table_prefixcohort_details +where cohort_type = 'T' + +union + +select database_id, cohort_definition_id as char_cohort_id, target_cohort_id as cohort_definition_id, cohort_type +from @schema.@c_table_prefixcohort_details +where cohort_type = 'Tall' +;", +schema = resultDatabaseSettings$schema, +c_table_prefix = resultDatabaseSettings$cTablePrefix +) + +TnOs <- connectionHandler$queryDb( + sql = " +select distinct +cd.target_cohort_id, +cd.outcome_cohort_id, +c.cohort_name +from @schema.@c_table_prefixcohort_details cd +inner join + @schema.@cg_table_prefixcohort_definition c + on cd.outcome_cohort_id = c.cohort_definition_id +where cd.cohort_type = 'TnO' +;", + schema = resultDatabaseSettings$schema, + c_table_prefix = resultDatabaseSettings$cTablePrefix, + cg_table_prefix = resultDatabaseSettings$cgTablePrefix +) +# fix backwards compatability +cg$subsetParent[is.na(cg$isSubset)] <- cg$cohortDefinitionId +cg$subsetDefinitionId[is.na(cg$isSubset)] <- cg$cohortDefinitionId +cg$isSubset[is.na(cg$isSubset)] <- 0 + +parents <- unique(cg$cohortDefinitionId[cg$isSubset == 0]) +results <- lapply(parents, function(id){ + list( + cohortName = cg$cohortName[cg$cohortDefinitionId == id], + cohortId = id, + children = lapply(cg$cohortDefinitionId[cg$subsetParent == id], function(sid){ + list( + subsetName = cg$cohortName[cg$cohortDefinitionId == sid], + subsetId = sid, + charIds = cohorts[cohorts$cohortDefinitionId == sid,], + outcomeIds = unique(TnOs$outcomeCohortId[TnOs$targetCohortId == sid]), + outcomeNames = unique(TnOs$cohortName[TnOs$targetCohortId == sid]) + # add outcomes from case exposures + ) + } + ) + ) +}) + +return(results) + +} + +characterizationGetParents <- function(options){ + parentTs <- unlist(lapply(options, function(x) x$cohortId)) + names(parentTs) <- unlist(lapply(options, function(x) x$cohortName)) + + return(parentTs) +} + +characterizationGetChildren <- function(options, index){ + children <- unlist(lapply(options[[index]]$children, function(x) x$subsetId)) + names(children) <- unlist(lapply(options[[index]]$children, function(x) x$subsetName)) + + return(children) +} + +characterizationGetOutcomes <- function(options, index){ + result <- unique( + do.call( + 'rbind', + lapply( + X = options[[index]]$children, + FUN = function(x) data.frame(ids = x$outcomeIds, names = x$outcomeNames) + ) + ) + ) + + outcomes <- result$ids + names(outcomes) <- result$names + return(outcomes) } + diff --git a/R/characterization-riskFactors.R b/R/characterization-riskFactors.R new file mode 100644 index 00000000..90a54300 --- /dev/null +++ b/R/characterization-riskFactors.R @@ -0,0 +1,392 @@ +# @file characterization-aggregateFeatures.R +# +# Copyright 2024 Observational Health Data Sciences and Informatics +# +# This file is part of OhdsiShinyModules +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + + +characterizationRiskFactorViewer <- function(id) { + ns <- shiny::NS(id) + + shiny::div( + + # module that does input selection for a single row DF + shiny::uiOutput(ns("inputs")), + + shiny::conditionalPanel( + condition = 'input.generate != 0', + ns = ns, + shinydashboard::tabBox( + width = "100%", + # Title can include an icon + title = shiny::tagList(shiny::icon("gear"), "Risk Factors"), + shiny::tabPanel("Binary Feature Table", + resultTableViewer(ns('binaryTable')) + ), + shiny::tabPanel("Continuous Feature Table", + resultTableViewer(ns('continuousTable')) + ) + ) + ) + ) + +} + + + +characterizationRiskFactorServer <- function( + id, + connectionHandler, + resultDatabaseSettings, + targetId, #reactive + outcomeId #reactive +) { + shiny::moduleServer( + id, + function(input, output, session) { + + # get databases + options <- shiny::reactive({ + characterizationGetCaseSeriesOptions( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetId = targetId(), + outcomeId = outcomeId() + ) + }) + + output$inputs <- shiny::renderUI({ # need to make reactive? + + shiny::div( + shiny::selectInput( + inputId = session$ns('databaseId'), + label = 'Database: ', + choices = options()$databaseIds, + selected = options()$databaseIds[1], + multiple = F + ), + + shiny::selectInput( + inputId = session$ns('tarId'), + label = 'Time-at-risk: ', + choices = options()$tarIds, + selected = options()$tarIds[1], + multiple = F + ), + + shiny::actionButton( + inputId = session$ns('generate'), + label = 'Generate' + ) + ) + + }) + + shiny::observeEvent(input$generate, { + + allData <- characterizationGetRiskFactorData( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetId = targetId(), + outcomeId = outcomeId(), + databaseId = input$databaseId, + timeAtRiskId = input$tarId + ) + + binTableOutputs <- resultTableServer( + id = "binaryTable", + df = allData$binary, + colDefsInput = characteriationRiskFactorColDefs(), # function below + addActions = NULL + ) + + conTableOutputs <- resultTableServer( + id = "continuousTable", + df = allData$continuous, + colDefsInput = characteriationRiskFactorColDefs(), # function below + addActions = NULL + ) + + }) + + return(invisible(NULL)) + } + ) +} + + +characterizationGetRiskFactorData <- function( + connectionHandler, + resultDatabaseSettings, + targetId, + outcomeId, + databaseId, + timeAtRiskId +){ + + shiny::withProgress(message = 'Getting risk factor data', value = 0, { + shiny::incProgress(1/4, detail = paste("Extracting ids")) + + sql <- "SELECT cohort_definition_id, cohort_type + from + @schema.@c_table_prefixcohort_details + where target_cohort_id = @target_id + and outcome_cohort_id in (0, @outcome_id) + and database_id = '@database_id' + and time_at_risk_id in (0, @time_at_risk_id) + and cohort_type in ('T','TnO', 'TnOprior') + ;" + + ids <- connectionHandler$queryDb( + sql = sql, + schema = resultDatabaseSettings$schema, + c_table_prefix = resultDatabaseSettings$cTablePrefix, + target_id = targetId, + outcome_id = outcomeId, + database_id = databaseId, + time_at_risk_id = timeAtRiskId + ) + + shiny::incProgress(2/4, detail = paste("Extracting binary")) + + sql <- "SELECT cov.cohort_definition_id, cr.covariate_name, cov.covariate_id, cov.sum_value, cov.average_value + from + @schema.@c_table_prefixcovariates cov + inner join @schema.@c_table_prefixcovariate_ref cr + on cov.run_id = cr.run_id and + cov.database_id = cr.database_id and + cov.covariate_id = cr.covariate_id + where cov.cohort_definition_id in (@ids) + and cov.database_id = '@database_id' + and cr.analysis_id not in (109, 110, 217, 218, 305, 417, 418, 505, 605, 713, 805, 926, 927) + ;" + + binary <- connectionHandler$queryDb( + sql = sql, + schema = resultDatabaseSettings$schema, + c_table_prefix = resultDatabaseSettings$cTablePrefix, + ids = paste0(ids$cohortDefinitionId, collapse = ','), + database_id = databaseId + ) + + # now process into table + binary <- riskFactorTable( + data = binary, + ids = ids + ) + + shiny::incProgress(3/4, detail = paste("Extracting continuous")) + + sql <- "SELECT cov.cohort_definition_id, cr.covariate_name, cov.covariate_id, + cov.count_value, cov.min_value, cov.max_value, cov.average_value, + cov.standard_deviation, cov.median_value, cov.p_10_value, + cov.p_25_value, cov.p_75_value, cov.p_90_value + from + @schema.@c_table_prefixcovariates_continuous cov + inner join @schema.@c_table_prefixcovariate_ref cr + on cov.run_id = cr.run_id and + cov.database_id = cr.database_id and + cov.covariate_id = cr.covariate_id + where cov.cohort_definition_id in (@ids) + and cov.database_id = '@database_id' + and cr.analysis_id not in (109, 110, 217, 218, 305, 417, 418, 505, 605, 713, 805, 926, 927) + ;" + + # TODO - how to remove prior outcomes?? + continuous <- connectionHandler$queryDb( + sql = sql, + schema = resultDatabaseSettings$schema, + c_table_prefix = resultDatabaseSettings$cTablePrefix, + ids = paste0(ids$cohortDefinitionId, collapse = ','), + database_id = databaseId + ) + + shiny::incProgress(4/4, detail = paste("Done")) + + }) + + return( + list( + binary = binary, + continuous = continuous + ) + ) +} + + +# now process into table +riskFactorTable <- function( + data, + ids +){ + + caseId <- ids$cohortDefinitionId[ids$cohortType == 'TnO'] + if(length(caseId ) == 0){ + caseId <- -1 + } + caseData <- data %>% + dplyr::filter(.data$cohortDefinitionId == !!caseId) %>% + dplyr::select(-"cohortDefinitionId") + + allId <- ids$cohortDefinitionId[ids$cohortType == 'T'] + allData <- data %>% + dplyr::filter(.data$cohortDefinitionId == !!allId) %>% + dplyr::select(-"cohortDefinitionId") + allData$N <- allData$sumValue[1]/allData$averageValue[1] + + excludeId <- ids$cohortDefinitionId[ids$cohortType == 'TnOprior'] + if(length(excludeId) == 0){ + excludeId <- -1 + } + excludeData <- data %>% + dplyr::filter(.data$cohortDefinitionId == !!excludeId) %>% + dplyr::select(-"cohortDefinitionId") + + if(nrow(excludeData) > 0 ){ + excludeData$exclude_N <- excludeData$sumValue[1]/excludeData$averageValue[1] + colnames(excludeData)[!colnames(excludeData) %in% c('covariateId', 'covariateName')] <- paste0('exclude_',colnames(excludeData)) + + # if prior Os then exclude from T + allData <- allData %>% + dplyr::full_join(excludeData, by = c('covariateId', 'covariateName')) %>% + dplyr::mutate( + sumValue = .data$sumValue - .data$prior_sumValue, + averageValue = (.data$sumValue - .data$prior_sumValue)/(.data$N-.data$exclude_N) + ) %>% + dplyr::mutate( + N = .data$N-.data$exclude_N + ) %>% + dplyr::select("covariateId","covariateName","sumValue","averageValue", "N") + + } + + if(nrow(caseData) > 0){ + caseData$caseN <- caseData$sumValue[1]/caseData$averageValue[1] + caseData <- caseData %>% + dplyr::mutate( + caseSumValue = .data$sumValue, + caseAverageValue = .data$averageValue + ) %>% + dplyr::select("covariateId","covariateName","caseSumValue","caseAverageValue", "caseN") + + # join with cases + allData <- allData %>% + dplyr::full_join(caseData, by = c('covariateId', 'covariateName')) %>% + dplyr::mutate( + nonCaseSumValue = .data$sumValue - .data$caseSumValue, + nonCaseAverageValue = (.data$sumValue - .data$caseSumValue)/(.data$N-.data$caseN) + ) %>% + dplyr::mutate( + nonCaseN = .data$N-.data$caseN + ) %>% + dplyr::select( + "covariateId","covariateName", + "caseSumValue","caseAverageValue", + "nonCaseSumValue","nonCaseAverageValue" + ) + + # add abs smd + allData <- allData %>% + dplyr::mutate( + meanDiff = (.data$caseAverageValue - .data$nonCaseAverageValue), + std1 = .data$caseAverageValue*(1-.data$caseAverageValue), + std2 = .data$nonCaseAverageValue*(1-.data$nonCaseAverageValue) + ) %>% + dplyr::mutate( + SMD = .data$meanDiff/sqrt((.data$std1^2 + .data$std2^2)/2), + absSMD = abs(.data$meanDiff/sqrt((.data$std1^2 + .data$std2^2)/2)) + ) + + + } else{ + allData <- allData %>% + dplyr::mutate( + nonCaseSumValue = .data$sumValue, + nonCaseAverageValue = .data$averageValue + ) %>% + dplyr::select( + "covariateId","covariateName", + "nonCaseSumValue","nonCaseAverageValue" + ) + } + + + return(allData) +} + +characteriationRiskFactorColDefs <- function(){ + result <- list( + covariateName = reactable::colDef( + name = "Covariate Name", + filterable = T + ), + covariateId = reactable::colDef( + show = F + ), + nonCaseSumValue = reactable::colDef( + name = "Number of non-cases with feature before exposure", + format = reactable::colFormat(digits = 2, percent = F), + cell = function(value) { + if(is.null(value)){return('< min threshold')} + if(is.na(value)){return('< min threshold')} + if (value != -1) value else '< min threshold' + } + ), + caseSumValue = reactable::colDef( + name = "Number of cases with feature before exposure", + format = reactable::colFormat(digits = 2, percent = F), + cell = function(value) { + if(is.null(value)){return('< min threshold')} + if(is.na(value)){return('< min threshold')} + if (value != -1) value else '< min threshold' + } + ), + nonCaseAverageValue = reactable::colDef( + name = "% of non-cases with feature before exposure", + format = reactable::colFormat(digits = 2, percent = T) + ), + caseAverageValue = reactable::colDef( + name = "% of cases with feature before exposure", + format = reactable::colFormat(digits = 2, percent = T) + ), + + SMD = reactable::colDef( + name = "Standardized mean difference", + format = reactable::colFormat(digits = 2, percent = F) + ), + + absSMD = reactable::colDef( + name = "Absolute standardized mean difference", + format = reactable::colFormat(digits = 2, percent = F) + ), + + analysisName = reactable::colDef( + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('desc-cont-select', '%s', event.target.value || undefined)", name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } + ) + ) + return(result) +} + diff --git a/R/characterization-timeToEvent.R b/R/characterization-timeToEvent.R index 8b0f6041..86a6e724 100644 --- a/R/characterization-timeToEvent.R +++ b/R/characterization-timeToEvent.R @@ -31,19 +31,7 @@ characterizationTimeToEventViewer <- function(id) { ns <- shiny::NS(id) shiny::div( - - infoHelperViewer( - id = "helper", - helpLocation= system.file("characterization-www", "help-timeToEvent.html", package = utils::packageName()) - ), - - # input component module - inputSelectionViewer(id = ns('input-selection')), - - shiny::conditionalPanel( - condition = 'input.generate != 0', - ns = shiny::NS(ns("input-selection")), - + shinydashboard::box( width = "100%", title = shiny::tagList(shiny::icon("gear"), "Results"), @@ -62,9 +50,6 @@ characterizationTimeToEventViewer <- function(id) { ) ) ) - - - ) } @@ -84,73 +69,18 @@ characterizationTimeToEventViewer <- function(id) { characterizationTimeToEventServer <- function( id, connectionHandler, - resultDatabaseSettings + resultDatabaseSettings, + targetId, + outcomeId ) { shiny::moduleServer( id, function(input, output, session) { - # get the possible target ids - bothIds <- timeToEventGetIds( - connectionHandler, - resultDatabaseSettings - ) - - - # input selection component - inputSelected <- inputSelectionServer( - id = "input-selection", - inputSettingList = list( - createInputSetting( - rowNumber = 1, - columnWidth = 6, - varName = 'targetId', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Target: ', - choices = bothIds$targetIds, - #choicesOpt = list(style = rep_len("color: black;", 999)), - selected = bothIds$targetIds[1], - multiple = F, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ), - - createInputSetting( - rowNumber = 1, - columnWidth = 6, - varName = 'outcomeId', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Outcome: ', - choices = bothIds$outcomeIds, - #choicesOpt = list(style = rep_len("color: black;", 999)), - selected = bothIds$outcomeIds[1], - multiple = F, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ) - ) - ) - allData <- shiny::reactive({ getTimeToEventData( - targetId = inputSelected()$targetId, - outcomeId = inputSelected()$outcomeId, + targetId = targetId(), + outcomeId = outcomeId(), connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings ) @@ -196,6 +126,7 @@ characterizationTimeToEventServer <- function( ) } +# can remove timeToEventGetIds <- function( connectionHandler, resultDatabaseSettings diff --git a/R/components-data-viewer.R b/R/components-data-viewer.R index e9a52f15..cdccb6a2 100644 --- a/R/components-data-viewer.R +++ b/R/components-data-viewer.R @@ -14,13 +14,14 @@ #' resultTableViewer <- function( id = "result-table", - downloadedFileName = NULL + downloadedFileName = NULL, + boxTitle = 'Table' ) { ns <- shiny::NS(id) shiny::div(# UI shinydashboard::box( width = "100%", - title = shiny::span(shiny::icon("table"), "Table"), + title = shiny::span(shiny::icon("table"), boxTitle), shiny::fluidPage( shiny::fluidRow( shiny::column( diff --git a/extras/examples/app.R b/extras/examples/app.R index 38a0188e..5f61dafc 100644 --- a/extras/examples/app.R +++ b/extras/examples/app.R @@ -36,9 +36,6 @@ config <- initializeModuleConfig() %>% addModuleConfig( createDefaultAboutConfig() ) %>% - addModuleConfig( - est - ) %>% addModuleConfig( createDefaultDatasourcesConfig() ) %>% @@ -48,21 +45,15 @@ config <- initializeModuleConfig() %>% addModuleConfig( createDefaultCohortDiagnosticsConfig() ) %>% + addModuleConfig( + est + ) %>% addModuleConfig( createDefaultCharacterizationConfig() ) %>% addModuleConfig( createDefaultPredictionConfig() ) %>% - addModuleConfig( - createDefaultCohortMethodConfig() - ) %>% - addModuleConfig( - createDefaultSccsConfig() - ) %>% - #addModuleConfig( - # createDefaultEvidenceSynthesisConfig() - #) %>% addModuleConfig( ShinyAppBuilder::createDefaultReportConfig() ) @@ -83,4 +74,3 @@ ShinyAppBuilder::createShinyApp( protocolLink = 'http://ohdsi.org' ) - diff --git a/inst/extdata/results.sqlite b/inst/extdata/results.sqlite index 84245e286257f84cbe170f982d68c3173246fe00..22bcf4a4943e8a5292219785af47fa185221550b 100755 GIT binary patch delta 158019 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

9cotAk&Xv+37=>^P4(p7FE~6r6RMlfh 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 AQ~&?~ delta 198296 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%0A9%^RnIP1Y1eoieU-oqU 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 D5=FQ; diff --git a/inst/extdata/results_old.sqlite b/inst/extdata/results_old.sqlite new file mode 100755 index 0000000000000000000000000000000000000000..84245e286257f84cbe170f982d68c3173246fe00 GIT binary patch literal 3084288 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 z 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

u@SfW=9L%xD9DiI`}C$w`F}ZQzCAa#Epkw4w6p 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�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≈qxAzj*%E+Kx@`({3VfF|8KV)s3Qf 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

BF4KokbU8 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

q3 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


L81ybinm+ry8-cfwc0BjHH!VQ?e37VHoF`Umwl z>Sycs);_MiTl;qH@!EF(@BZ8VtNvqt;C<-*(7WjE_sa0?idV4$#R?QFP^>_)0>uja zUsgaaF~}G40J;S5Y&Jk*nmnTb z;lbS0e-T6JNAcIhfj8voJf!y!(o@+;i79$MeJP1SK9>jZZUXphHb7#EPNoAAgM20r z;9UgpL^eQTik?mfBnJ6Z9>6;Z;FH+^i79#_9grC0@jQS#2;i}7fW#CXO$Q_f`FI{c iK>(++0TNU6)pS5&kVo Date: Tue, 21 May 2024 01:48:12 -0400 Subject: [PATCH 05/64] improving characterization --- R/characterization-cohorts.R | 439 ++++++++++++++++++++++--------- R/characterization-database.R | 42 ++- R/characterization-incidence.R | 14 +- R/characterization-main.R | 89 ++++--- R/characterization-riskFactors.R | 230 ++++++++++++++-- R/estimation-main.R | 18 +- R/report-main.R | 55 +++- extras/examples/app.R | 11 +- 8 files changed, 653 insertions(+), 245 deletions(-) diff --git a/R/characterization-cohorts.R b/R/characterization-cohorts.R index ca452043..8f71e506 100644 --- a/R/characterization-cohorts.R +++ b/R/characterization-cohorts.R @@ -41,8 +41,21 @@ characterizationCohortComparisonViewer <- function(id) { inputSelectionDfViewer(id = ns('inputSelected'), title = 'Selected'), # add basic table - resultTableViewer(id = ns('countTable'), boxTitle = 'Counts'), - resultTableViewer(id = ns('mainTable'), boxTitle = 'Binary') + shiny::tabsetPanel( + type = 'pills', + shiny::tabPanel( + title = 'Counts', + resultTableViewer(id = ns('countTable'), boxTitle = 'Counts') + ), + shiny::tabPanel( + title = 'Binary', + resultTableViewer(id = ns('mainTable'), boxTitle = 'Binary') + ), + shiny::tabPanel( + title = 'Continuous', + resultTableViewer(id = ns('continuousTable'), boxTitle = 'continuous') + ) + ) ) ) @@ -56,7 +69,8 @@ characterizationCohortComparisonServer <- function( resultDatabaseSettings, options, parents, - parentIndex # reactive + parentIndex, # reactive + subTargetId # reactive ) { shiny::moduleServer( id, @@ -67,36 +81,17 @@ characterizationCohortComparisonServer <- function( resultDatabaseSettings = resultDatabaseSettings ) - children <- shiny::reactive({ - characterizationGetChildren(options, parentIndex()) - }) - - # update targetId2 - initialChildren2 <- characterizationGetChildren(options, 1) - - children2 <- shiny::reactiveVal() - shiny::observeEvent(input$parentTargetId2,{ - newIndex <- which(input$parentTargetId2 == parents) - result <- characterizationGetChildren(options, newIndex) - children2(result) - shinyWidgets::updatePickerInput( - session = session, - inputId = 'targetId2', - label = 'Second Target: ', - choices = result, - selected = result[1] - ) - - }) + # initial comp chilren + comparatorOptions <- characterizationGetChildren(options, 1) output$inputs <- shiny::renderUI({ shiny::div( shinyWidgets::pickerInput( - inputId = session$ns('targetId1'), - label = 'First Target: ', - choices = children(), - selected = 1, + inputId = session$ns('comparatorGroup'), + label = 'Comparator Group: ', + choices = parents, + selected = parents[1], multiple = F, options = shinyWidgets::pickerOptions( actionsBox = TRUE, @@ -107,29 +102,14 @@ characterizationCohortComparisonServer <- function( virtualScroll = 50 ) ), + shiny::selectInput( - inputId = session$ns('parentTargetId2'), - label = 'Second Parent Target: ', - choices = parents, - selected = parents[1], + inputId = session$ns('comparatorId'), + label = 'Comparator: ', + choices = comparatorOptions, + selected = comparatorOptions[1], multiple = F ), - - shinyWidgets::pickerInput( - inputId = session$ns('targetId2'), - label = 'Second Target: ', - choices = initialChildren2, - selected = initialChildren2[1], - multiple = F, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ), shinyWidgets::pickerInput( inputId = session$ns('databaseId'), @@ -140,10 +120,11 @@ characterizationCohortComparisonServer <- function( options = shinyWidgets::pickerOptions( actionsBox = TRUE, liveSearch = TRUE, + dropupAuto = F, size = 10, liveSearchStyle = "contains", liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 + virtualScroll = 500 ) ), @@ -155,72 +136,23 @@ characterizationCohortComparisonServer <- function( }) - - columns <- list( - covariateName = reactable::colDef( - header = withTooltip( - "Covariate Name", - "The name of the covariate" - ) - ), - covariateId = reactable::colDef( - show = F, - header = withTooltip("Covariate ID", - "Unique identifier of the covariate") - ), - firstVar = reactable::colDef( - show = F - ), - secondVar = reactable::colDef( - show = F - ), - sumValue_1 = reactable::colDef( - header = withTooltip("First Sum", - "The total sum of the covariate for the first selected cohort."), - cell = function(value) { - if (value >= 0) value else '< min threshold' - } - ), - sumValue_2 = reactable::colDef( - header = withTooltip("Second Sum", - "The total sum of the covariate for the second selected cohort."), - cell = function(value) { - if (value >= 0) value else '< min threshold' - } - ), - averageValue_1 = reactable::colDef( - header = withTooltip("First Mean", - "The mean of the covariate for the first selected cohort."), - cell = function(value) { - if (value >= 0) round(value, digits = 3) else '< min threshold' - } - ), - averageValue_2 = reactable::colDef( - header = withTooltip("Second Mean", - "The mean of the covariate for the second selected cohort."), - cell = function(value) { - if (value >= 0) round(value, digits = 3) else '< min threshold' - } - ), - SMD = reactable::colDef( - header = withTooltip("SMD", - "Standardized mean difference"), - format = reactable::colFormat(digits = 3) - ), - absSMD = reactable::colDef( - header = withTooltip("absSMD", - "Absolute standardized mean difference"), - format = reactable::colFormat(digits = 3) - ), - analysisName = reactable::colDef( - header = withTooltip( - "Covariate Class", - "Class/type of the covariate" - ) - ) - - # add other columns + # update comparatorId + comparatorGroups <- shiny::reactiveVal() + comparatorIndex <- shiny::reactiveVal(1) + shiny::observeEvent(input$comparatorGroup,{ + comparatorIndex(which(input$comparatorGroup == parents)) + result <- characterizationGetChildren(options, comparatorIndex()) + comparatorGroups(result) + shiny::updateSelectInput( + session = session, + inputId = 'comparatorId', + label = 'Comparator: ', + choices = result, + selected = result[1] ) + }) + + # show selected inputs to user inputSelectionDfServer( @@ -235,38 +167,43 @@ characterizationCohortComparisonServer <- function( runTables <- TRUE - if(is.null(input$targetId1) | is.null(input$targetId2)){ + if(is.null(subTargetId()) | is.null(input$comparatorId)){ runTables <- FALSE } if(is.null(input$databaseId)){ runTables <- FALSE } - if(input$targetId1 == input$targetId2){ + if(subTargetId() == input$comparatorId){ runTables <- FALSE shiny::showNotification('Must select different cohorts') } + # ADDED + subTargetIds <- unlist(lapply(options[[parentIndex()]]$children, function(x){x$subsetId})) + subTargetNames <- unlist(lapply(options[[parentIndex()]]$children, function(x){x$subsetName})) + selected( data.frame( - `First Target` = names(children())[which(input$targetId1 == children())], - `Second Target` = names(children2())[which(input$targetId2 == children2())], + Comparator = names(comparatorGroups())[which(comparatorGroups() == input$comparatorId)], Database = names(inputVals$databaseIds)[input$databaseId == inputVals$databaseIds] ) ) - selection1 <- options[[parentIndex()]]$children[[which(input$targetId1 == children())]]$charIds %>% + selection1 <- options[[parentIndex()]]$children[[which(subTargetIds == subTargetId())]]$charIds %>% dplyr::filter(.data$databaseId == input$databaseId) %>% - dplyr::filter(.data$cohortDefinitionId == input$targetId1) + dplyr::filter(.data$cohortType %in% c('T','O')) %>% + dplyr::filter(.data$cohortDefinitionId == subTargetId()) # is this needed? if(nrow(selection1) == 0){ runTables <- FALSE shiny::showNotification('No results for section 1') } - selection2 <- options[[which(input$parentTargetId2 == parents)]]$children[[which(input$targetId2 == children2())]]$charIds %>% + selection2 <- options[[comparatorIndex()]]$children[[which(comparatorGroups() == input$comparatorId)]]$charIds %>% dplyr::filter(.data$databaseId == input$databaseId) %>% - dplyr::filter(.data$cohortDefinitionId == input$targetId2) + dplyr::filter(.data$cohortType %in% c('T','O')) %>% + dplyr::filter(.data$cohortDefinitionId == input$comparatorId) if(nrow(selection2) == 0){ runTables <- FALSE @@ -290,16 +227,29 @@ characterizationCohortComparisonServer <- function( resultDatabaseSettings = resultDatabaseSettings, targetIds = c(selection1$charCohortId[1],selection2$charCohortId[1]), targetNames = c( - names(children())[which(input$targetId1 == children())], - names(children2())[which(input$targetId2 == children2())] + subTargetNames[which(subTargetIds == subTargetId())], # modified + names(comparatorGroups())[which(input$comparatorId== comparatorGroups())] ), databaseId = input$databaseId ) + continuousTable <- characterizatonGetCohortComparisonDataContinuous( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = c(selection1$charCohortId[1],selection2$charCohortId[1]), + databaseIds = rep(input$databaseId,2) + ) + resultTableServer( id = 'mainTable', df = resultTable, - colDefsInput = columns + colDefsInput = characterizationCohortsColumns() + ) + + resultTableServer( + id = 'continuousTable', + df = continuousTable, + colDefsInput = characterizationCohortsColumnsContinuous() ) resultTableServer( @@ -327,6 +277,159 @@ characterizationCohortComparisonServer <- function( } + +characterizationCohortsColumns <- function(x){ + list( + covariateName = reactable::colDef( + header = withTooltip( + "Covariate Name", + "The name of the covariate" + ) + ), + covariateId = reactable::colDef( + show = F, + header = withTooltip("Covariate ID", + "Unique identifier of the covariate") + ), + firstVar = reactable::colDef( + show = F + ), + secondVar = reactable::colDef( + show = F + ), + sumValue_1 = reactable::colDef( + header = withTooltip("First Sum", + "The total sum of the covariate for the first selected cohort."), + cell = function(value) { + if (value >= 0) value else '< min threshold' + } + ), + sumValue_2 = reactable::colDef( + header = withTooltip("Second Sum", + "The total sum of the covariate for the second selected cohort."), + cell = function(value) { + if (value >= 0) value else '< min threshold' + } + ), + averageValue_1 = reactable::colDef( + header = withTooltip("First Mean", + "The mean of the covariate for the first selected cohort."), + cell = function(value) { + if (value >= 0) round(value, digits = 3) else '< min threshold' + } + ), + averageValue_2 = reactable::colDef( + header = withTooltip("Second Mean", + "The mean of the covariate for the second selected cohort."), + cell = function(value) { + if (value >= 0) round(value, digits = 3) else '< min threshold' + } + ), + SMD = reactable::colDef( + header = withTooltip("SMD", + "Standardized mean difference"), + format = reactable::colFormat(digits = 3) + ), + absSMD = reactable::colDef( + header = withTooltip("absSMD", + "Absolute standardized mean difference"), + format = reactable::colFormat(digits = 3) + ), + analysisName = reactable::colDef( + header = withTooltip( + "Covariate Class", + "Class/type of the covariate" + ) + ) + + # add other columns +) +} + +characterizationCohortsColumnsContinuous <- function(x){ + list( + covariateName = reactable::colDef( + header = withTooltip( + "Covariate Name", + "The name of the covariate" + ) + ), + covariateId = reactable::colDef( + show = F, + header = withTooltip("Covariate ID", + "Unique identifier of the covariate") + ), + countValue_1 = reactable::colDef( + header = withTooltip("First Count", + "Number of people with the covariate for the first selected cohort."), + cell = function(value) { + if (value >= 0) value else '< min threshold' + } + ), + countValue_2 = reactable::colDef( + header = withTooltip("Second Count", + "Number of people with the covariate for the second selected cohort."), + cell = function(value) { + if (value >= 0) value else '< min threshold' + } + ), + averageValue_1 = reactable::colDef( + header = withTooltip("First Mean", + "The mean of the covariate for the first selected cohort."), + cell = function(value) { + if (value >= 0) round(value, digits = 3) else '< min threshold' + } + ), + averageValue_2 = reactable::colDef( + header = withTooltip("Second Mean", + "The mean of the covariate for the second selected cohort."), + cell = function(value) { + if (value >= 0) round(value, digits = 3) else '< min threshold' + } + ), + standardDeviation_1 = reactable::colDef( + header = withTooltip("First StDev", + "The standard deviation of the covariate for the first selected cohort."), + cell = function(value) { + if (value >= 0) round(value, digits = 3) else '< min threshold' + } + ), + standardDeviation_2 = reactable::colDef( + header = withTooltip("Second StDev", + "The standard deviation of the covariate for the second selected cohort."), + cell = function(value) { + if (value >= 0) round(value, digits = 3) else '< min threshold' + } + ), + medianValue_1 = reactable::colDef( + header = withTooltip("First Median", + "The median of the covariate for the first selected cohort."), + cell = function(value) { + round(value, digits = 3) + } + ), + medianValue_2 = reactable::colDef( + header = withTooltip("Second Median", + "The median of the covariate for the second selected cohort."), + cell = function(value) { + round(value, digits = 3) + } + ), + SMD = reactable::colDef( + header = withTooltip("SMD", + "Standardized mean difference"), + format = reactable::colFormat(digits = 3) + ), + absSMD = reactable::colDef( + header = withTooltip("absSMD", + "Absolute standardized mean difference"), + format = reactable::colFormat(digits = 3) + ) + + # add other columns + ) +} + characterizatonGetCohortComparisonData <- function( connectionHandler, resultDatabaseSettings, @@ -412,7 +515,7 @@ characterizatonGetCohortData <- function( warning('Ids cannot be NULL') return(NULL) } - + shiny::withProgress(message = 'characterizatonGetCohortData', value = 0, { shiny::incProgress(1/4, detail = paste("Setting types")) @@ -488,6 +591,90 @@ characterizatonGetCohortData <- function( } +characterizatonGetCohortComparisonDataContinuous <- function( + connectionHandler, + resultDatabaseSettings, + targetIds, + databaseIds +){ + + if(is.null(targetIds) | is.null(databaseIds)){ + warning('Ids cannot be NULL') + return(NULL) + } + + shiny::withProgress(message = 'characterizatonGetCohortDataContinuous', value = 0, { + + shiny::incProgress(1/4, detail = paste("Setting types")) + + types <- data.frame( + type = 1:length(targetIds), + cohortDefinitionId = targetIds, + databaseId = databaseIds + ) + + shiny::incProgress(2/4, detail = paste("Extracting data")) + + sql <- paste0( + paste0( + paste0( + "select ref.covariate_name, cov.* from + @schema.@c_table_prefixCOVARIATES_continuous cov + inner join + @schema.@c_table_prefixcovariate_ref ref + on cov.covariate_id = ref.covariate_id + and cov.run_id = ref.run_id + and cov.database_id = ref.database_id + + where cov.cohort_definition_id = @target_id",1:length(targetIds), + " and cov.database_id = '@database_id",1:length(targetIds),"'" + ), collapse = ' union ' + ),';' + ) + + inputList <- as.list(c(targetIds, databaseIds)) + names(inputList) <- c(paste0('target_id', 1:length(targetIds)), paste0('database_id', 1:length(databaseIds))) + inputList$sql <- sql + inputList$schema <- resultDatabaseSettings$schema + inputList$c_table_prefix <- resultDatabaseSettings$cTablePrefix + + start <- Sys.time() + # settings.min_characterization_mean needed? + res <- do.call(what = connectionHandler$queryDb, args = inputList) + end <- Sys.time() - start + shiny::incProgress(3/4, detail = paste("Extracted data")) + message(paste0('Extracting ', nrow(res) ,' characterization cohort rows took: ', round(end, digits = 2), ' ', units(end))) + + # add the first/section type + res <- merge(res, types, by = c('cohortDefinitionId','databaseId')) + + # pivot + result <- tidyr::pivot_wider( + data = res, + id_cols = c('covariateName', 'covariateId'), + names_from = 'type', + values_from = c('countValue', 'averageValue', 'standardDeviation', 'medianValue','minValue', 'maxValue', 'p25Value','p75Value'), + values_fn = mean, + values_fill = -1 + ) + + # if both have results then add SMD + if(length(unique(res$type)) > 1){ + result <- result %>% + dplyr::mutate( + SMD = (.data$averageValue_1-.data$averageValue_2)/(sqrt((.data$standardDeviation_1^2 + .data$standardDeviation_2^2)/2)) + ) %>% + dplyr::mutate( + absSMD = abs(.data$SMD) + ) + } + + shiny::incProgress(4/4, detail = paste("Done")) + }) + + return(result) +} + characterizationGetCohortsInputs <- function( diff --git a/R/characterization-database.R b/R/characterization-database.R index 33c3b441..ecda5ca6 100644 --- a/R/characterization-database.R +++ b/R/characterization-database.R @@ -54,7 +54,8 @@ characterizationDatabaseComparisonServer <- function( resultDatabaseSettings, options, parents, - parentIndex # reactive + parentIndex, # reactive + subTargetId # reactive ) { shiny::moduleServer( id, @@ -73,27 +74,11 @@ characterizationDatabaseComparisonServer <- function( output$inputs <- shiny::renderUI({ shiny::div( - shinyWidgets::pickerInput( - inputId = session$ns('targetId'), - label = 'Target: ', - choices = children(), - selected = 1, - multiple = F, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ), - shiny::selectInput( inputId = session$ns('databaseIds'), label = 'Databases: ', choices = inputVals$databaseIds, - selected = 1, + selected = inputVals$databaseIds[1], multiple = T ), @@ -127,19 +112,28 @@ characterizationDatabaseComparisonServer <- function( selected <- shiny::reactiveVal() shiny::observeEvent(input$generate,{ - if(is.null(input$targetId)){ + if(is.null(input$databaseIds)){ + shiny::showNotification('No databases selected') + return(NULL) + } + if(length(input$databaseIds) == 0 ){ + shiny::showNotification('No databases selected') return(NULL) } + selectedDatabases <- paste0( + names(inputVals$databaseIds)[which(inputVals$databaseIds %in% input$databaseIds)], + collapse = ',' + ) + selected( data.frame( - Target = names(children())[which(input$targetId == children())], + Databases = selectedDatabases, minTreshold = input$minThreshold ) ) - selectedChildChar <- options[[parentIndex()]]$children[[which(input$targetId == children())]]$charIds - + selectedChildChar <- options[[parentIndex()]]$children[[which(subTargetId() == children())]]$charIds #get results if(sum(selectedChildChar$databaseId %in% input$databaseIds) > 0){ @@ -178,8 +172,6 @@ characterizationDatabaseComparisonServer <- function( }) names(sumColumns) <- unlist(lapply(1:nrow(databaseNames), function(i) paste0('sumValue_',databaseNames$id[i]))) - print('HERE 3') - columns <- append( list( covariateName = reactable::colDef( @@ -200,8 +192,6 @@ characterizationDatabaseComparisonServer <- function( ) ) - print('HERE 4') - resultTableServer( id = 'mainTable', df = result$table, diff --git a/R/characterization-incidence.R b/R/characterization-incidence.R index ce29f65f..fdbeef59 100644 --- a/R/characterization-incidence.R +++ b/R/characterization-incidence.R @@ -249,7 +249,7 @@ characterizationIncidenceServer <- function( parents, parentIndex, # reactive outcomes, # reactive - subTargets# reactive + targetIds # reactive ) { shiny::moduleServer( id, @@ -289,16 +289,6 @@ characterizationIncidenceServer <- function( style = "font-weight: bold; font-size: 20px; text-align: center; margin-bottom: 20px;" ), - shiny::selectInput( - inputId = session$ns('targetIds'), - label = 'Target: ', - choices = subTargets(), - selected = 1, - multiple = T, - selectize = TRUE, - width = NULL, - size = NULL - ), shiny::selectInput( inputId = session$ns('outcomeIds'), @@ -388,7 +378,6 @@ characterizationIncidenceServer <- function( }) outcomeIds <- shiny::reactiveVal(NULL) - targetIds <- shiny::reactiveVal(NULL) incidenceRateTarFilter <- shiny::reactiveVal(NULL) incidenceRateCalendarFilter <- shiny::reactiveVal(NULL) incidenceRateAgeFilter <- shiny::reactiveVal(NULL) @@ -399,7 +388,6 @@ characterizationIncidenceServer <- function( incidenceRateAgeFilter(input$ageIds) incidenceRateGenderFilter(input$sexIds) outcomeIds(input$outcomeIds) - targetIds(input$targetIds) }) diff --git a/R/characterization-main.R b/R/characterization-main.R index a191bfd2..1d5f4dce 100644 --- a/R/characterization-main.R +++ b/R/characterization-main.R @@ -51,12 +51,18 @@ characterizationViewer <- function(id=1) { solidHeader = TRUE, # pick a targetId of interest - shiny::uiOutput(ns("targetSelection")), + shinydashboard::box( + title = 'Target Of Interest', + width = '100%', + status = "primary", + collapsible = T, + shiny::uiOutput(ns("targetSelection")) + ), shiny::conditionalPanel( condition = 'input.targetSelect', ns = ns, - inputSelectionDfViewer(id = ns('targetSelected'), title = 'Selected'), + inputSelectionDfViewer(id = ns('targetSelected'), title = 'Selected Target'), shiny::tabsetPanel( type = 'pills', id = ns('mainPanel') @@ -100,13 +106,32 @@ characterizationServer <- function( # PARENT TARGET SELECTION UI #================================================ parents <- characterizationGetParents(options) + parentIndex <- shiny::reactiveVal(1) + subTargets <- shiny::reactiveVal() + # add an input for all char that lets you select cohort of interest output$targetSelection <- shiny::renderUI({ shiny::div( - shiny::selectInput( + shinyWidgets::pickerInput( inputId = session$ns('targetId'), - label = 'Parent Target: ', + label = 'Target Group: ', choices = parents, + selected = parents[1], + multiple = FALSE, + options = shinyWidgets::pickerOptions( + actionsBox = TRUE, + liveSearch = TRUE, + dropupAuto = F, + size = 10, + liveSearchStyle = "contains", + liveSearchPlaceholder = "Type here to search", + virtualScroll = 500 + ) + ), + shiny::selectInput( + inputId = session$ns('subTargetId'), + label = 'Target: ', + choices = characterizationGetChildren(options,1), selected = 1, multiple = FALSE, selectize = TRUE, @@ -121,22 +146,35 @@ characterizationServer <- function( ) }) - + #================================================ + # UPDATE TARGET BASED ON TARGET GROUP + #================================================ + shiny::observeEvent(input$targetId,{ + parentIndex(which(parents == input$targetId)) + subTargets(characterizationGetChildren(options,which(parents == input$targetId))) + shiny::updateSelectInput( + inputId = 'subTargetId', + label = 'Target: ', + choices = subTargets(), + selected = subTargets()[1] + ) + }) + #================================================ # PARENT TARGET SELECTION ACTION #================================================ # reactives updated when parent target is selected - parentIndex <- shiny::reactiveVal(1) outcomes <- shiny::reactiveVal() - subTargets <- shiny::reactiveVal() targetSelected <- shiny::reactiveVal() + subTargetId <- shiny::reactiveVal() # output the selected target shiny::observeEvent(input$targetSelect, { # First create input dataframe and add to the inputServer to display targetSelected( data.frame( - `Parent Target` = names(parents)[parents == input$targetId] + `Target group` = names(parents)[parents == input$targetId], + `Target` = names(subTargets())[subTargets() == input$subTargetId] ) ) inputSelectionDfServer( @@ -145,29 +183,17 @@ characterizationServer <- function( ncol = 1 ) - # update the parentIndex of interest - parentIndex(which(parents == input$targetId )) + subTargetId(input$subTargetId) + # update the outcomes for the selected parent target id outcomes(characterizationGetOutcomes(options, parentIndex())) - # update the child targets for the selected parent target id - subTargets(characterizationGetChildren(options, parentIndex())) - + # create the outcome selector for the case exposure tabs output$outcomeSelection <- shiny::renderUI({ shinydashboard::box( collapsible = TRUE, title = "Options", width = "100%", - shiny::selectInput( - inputId = session$ns('subTargetId'), - label = 'Target: ', - choices = subTargets(), - selected = 1, - multiple = FALSE, - selectize = TRUE, - width = NULL, - size = NULL - ), shiny::selectInput( inputId = session$ns('outcomeId'), label = 'Outcome: ', @@ -195,19 +221,19 @@ characterizationServer <- function( # show the selected outcome outcomeSelected <- shiny::reactiveVal() outcomeId <- shiny::reactiveVal() - subTargetId <- shiny::reactiveVal() + #subTargetId <- shiny::reactiveVal() shiny::observeEvent(input$outcomeSelect, { outcomeSelected( data.frame( - Target = names(subTargets())[subTargets() == input$subTargetId], + #Target = names(subTargets())[subTargets() == input$subTargetId], Outcome = names(outcomes())[outcomes() == input$outcomeId] ) ) # store the outcome and subTargetIds for the case exposure tabs outcomeId(input$outcomeId) - subTargetId(input$subTargetId) + #subTargetId(input$subTargetId) inputSelectionDfServer( id = 'outcomeSelected', @@ -376,7 +402,8 @@ characterizationServer <- function( resultDatabaseSettings = resultDatabaseSettings, options = options, parents = parents, - parentIndex = parentIndex + parentIndex = parentIndex, + subTargetId = subTargetId ) previouslyLoaded(c(previouslyLoaded(), "Cohort Comparison")) } @@ -393,7 +420,8 @@ characterizationServer <- function( resultDatabaseSettings = resultDatabaseSettings, options = options, parents = parents, - parentIndex = parentIndex + parentIndex = parentIndex, + subTargetId = subTargetId ) previouslyLoaded(c(previouslyLoaded(), "Database Comparison")) } @@ -477,7 +505,7 @@ characterizationServer <- function( parents = parents, parentIndex = parentIndex, # reactive outcomes = outcomes, # reactive - subTargets = subTargets# reactive + targetIds = subTargetId# reactive ) previouslyLoaded(c(previouslyLoaded(), "Incidence Results")) } @@ -571,7 +599,8 @@ characterizationGetOptions <- function( # get cohorts cg <- connectionHandler$queryDb( - sql = 'select * from @schema.@cg_table_prefixcohort_definition;', + sql = 'select * from @schema.@cg_table_prefixcohort_definition + ORDER BY cohort_name;', schema = resultDatabaseSettings$schema, cg_table_prefix = resultDatabaseSettings$cgTablePrefix ) diff --git a/R/characterization-riskFactors.R b/R/characterization-riskFactors.R index 90a54300..05141591 100644 --- a/R/characterization-riskFactors.R +++ b/R/characterization-riskFactors.R @@ -116,7 +116,7 @@ characterizationRiskFactorServer <- function( conTableOutputs <- resultTableServer( id = "continuousTable", df = allData$continuous, - colDefsInput = characteriationRiskFactorColDefs(), # function below + colDefsInput = characteriationRiskFactorContColDefs(), # function below addActions = NULL ) @@ -140,14 +140,20 @@ characterizationGetRiskFactorData <- function( shiny::withProgress(message = 'Getting risk factor data', value = 0, { shiny::incProgress(1/4, detail = paste("Extracting ids")) - sql <- "SELECT cohort_definition_id, cohort_type + sql <- "SELECT cd.cohort_definition_id, cd.cohort_type, cc.person_count as N from - @schema.@c_table_prefixcohort_details - where target_cohort_id = @target_id - and outcome_cohort_id in (0, @outcome_id) - and database_id = '@database_id' - and time_at_risk_id in (0, @time_at_risk_id) - and cohort_type in ('T','TnO', 'TnOprior') + @schema.@c_table_prefixcohort_details cd + left join + @schema.@c_table_prefixcohort_counts cc + on cd.run_id = cc.run_id + and cd.database_id = cc.database_id + and cd.cohort_definition_id = cc.cohort_definition_id + + where cd.target_cohort_id = @target_id + and cd.outcome_cohort_id in (0, @outcome_id) + and cd.database_id = '@database_id' + and cd.time_at_risk_id in (0, @time_at_risk_id) + and cd.cohort_type in ('T','TnO', 'TnOprior') ;" ids <- connectionHandler$queryDb( @@ -212,6 +218,11 @@ characterizationGetRiskFactorData <- function( c_table_prefix = resultDatabaseSettings$cTablePrefix, ids = paste0(ids$cohortDefinitionId, collapse = ','), database_id = databaseId + ) + + continuous <- riskFactorContinuousTable( + data = continuous, + ids = ids ) shiny::incProgress(4/4, detail = paste("Done")) @@ -285,6 +296,7 @@ riskFactorTable <- function( # join with cases allData <- allData %>% dplyr::full_join(caseData, by = c('covariateId', 'covariateName')) %>% + dplyr::mutate_if(is.numeric,dplyr::coalesce,0) %>% dplyr::mutate( nonCaseSumValue = .data$sumValue - .data$caseSumValue, nonCaseAverageValue = (.data$sumValue - .data$caseSumValue)/(.data$N-.data$caseN) @@ -295,20 +307,22 @@ riskFactorTable <- function( dplyr::select( "covariateId","covariateName", "caseSumValue","caseAverageValue", - "nonCaseSumValue","nonCaseAverageValue" + "nonCaseSumValue","nonCaseAverageValue", + "N","caseN" ) # add abs smd allData <- allData %>% dplyr::mutate( - meanDiff = (.data$caseAverageValue - .data$nonCaseAverageValue), - std1 = .data$caseAverageValue*(1-.data$caseAverageValue), - std2 = .data$nonCaseAverageValue*(1-.data$nonCaseAverageValue) + meanDiff = .data$caseAverageValue - .data$nonCaseAverageValue, + std1 = sqrt(((1-.data$caseAverageValue)^2*.data$caseSumValue + (-.data$caseAverageValue)^2*(.data$caseN - .data$caseSumValue))/.data$caseN), + std2 = sqrt(((1-.data$nonCaseAverageValue)^2*.data$nonCaseSumValue + (-.data$nonCaseAverageValue)^2*(.data$N - .data$nonCaseSumValue))/.data$N) ) %>% dplyr::mutate( SMD = .data$meanDiff/sqrt((.data$std1^2 + .data$std2^2)/2), absSMD = abs(.data$meanDiff/sqrt((.data$std1^2 + .data$std2^2)/2)) - ) + ) %>% + dplyr::select(-"meanDiff",-"std1", -"std2",-"N",-"caseN") } else{ @@ -327,6 +341,86 @@ riskFactorTable <- function( return(allData) } + +riskFactorContinuousTable <- function( + data, + ids # have N in them +){ + + print(ids) + + caseId <- ids$cohortDefinitionId[ids$cohortType == 'TnO'] + if(length(caseId ) == 0){ + caseId <- -1 + } + caseData <- data %>% + dplyr::filter(.data$cohortDefinitionId == !!caseId) %>% + dplyr::select(-"cohortDefinitionId") + + allId <- ids$cohortDefinitionId[ids$cohortType == 'T'] + allData <- data %>% + dplyr::filter(.data$cohortDefinitionId == !!allId) %>% + dplyr::select(-"cohortDefinitionId") + + if(nrow(caseData) > 0){ + + caseData <- caseData %>% + dplyr::mutate( + caseCountValue = .data$countValue, + caseAverageValue = .data$averageValue, + caseStandardDeviation = .data$standardDeviation, + caseMedianValue = .data$medianValue, + caseMinValue = .data$minValue, + caseMaxValue = .data$maxValue, + caseP10Value = .data$p10Value, + caseP25Value = .data$p25Value, + caseP75Value = .data$p75Value, + caseP90Value = .data$p90Value + ) %>% + dplyr::select("covariateId","covariateName","caseCountValue","caseAverageValue", + "caseStandardDeviation", "caseMedianValue", "caseP10Value", "caseP25Value", + "caseP75Value", "caseP90Value", "caseMaxValue", "caseMinValue") + + # join with cases + allData <- allData %>% + dplyr::full_join(caseData, by = c('covariateId', 'covariateName')) %>% + dplyr::mutate( + targetCountValue = .data$countValue, + targetAverageValue = .data$averageValue, + targetStandardDeviation = .data$standardDeviation, + targetMedianValue = .data$medianValue, + targetMinValue = .data$minValue, + targetMaxValue = .data$maxValue, + targetP10Value = .data$p10Value, + targetP25Value = .data$p25Value, + targetP75Value = .data$p75Value, + targetP90Value = .data$p90Value + ) %>% + dplyr::select("covariateId","covariateName","caseCountValue","caseAverageValue", + "caseStandardDeviation", "caseMedianValue", "caseP10Value", "caseP25Value", + "caseP75Value", "caseP90Value", "caseMaxValue", "caseMinValue", + + "targetCountValue","targetAverageValue", + "targetStandardDeviation", "targetMedianValue", "targetP10Value", "targetP25Value", + "targetP75Value", "targetP90Value","targetMaxValue", "targetMinValue",) + + # add abs smd + allData <- allData %>% + dplyr::mutate( + SMD = (.data$caseAverageValue - .data$targetAverageValue)/sqrt((.data$caseStandardDeviation^2 + .data$targetStandardDeviation^2)/2), + absSMD = abs((.data$caseAverageValue - .data$targetAverageValue)/sqrt((.data$caseStandardDeviation^2 + .data$targetStandardDeviation^2)/2)), + targetBoxPlot = 0, + caseBoxPlot = 0 + ) + + + } + + + return(allData) + +} + characteriationRiskFactorColDefs <- function(){ result <- list( covariateName = reactable::colDef( @@ -338,7 +432,10 @@ characteriationRiskFactorColDefs <- function(){ ), nonCaseSumValue = reactable::colDef( name = "Number of non-cases with feature before exposure", - format = reactable::colFormat(digits = 2, percent = F), + format = reactable::colFormat( + percent = F, + separators = TRUE + ), cell = function(value) { if(is.null(value)){return('< min threshold')} if(is.na(value)){return('< min threshold')} @@ -347,7 +444,10 @@ characteriationRiskFactorColDefs <- function(){ ), caseSumValue = reactable::colDef( name = "Number of cases with feature before exposure", - format = reactable::colFormat(digits = 2, percent = F), + format = reactable::colFormat( + separators = TRUE, + percent = F + ), cell = function(value) { if(is.null(value)){return('< min threshold')} if(is.na(value)){return('< min threshold')} @@ -371,20 +471,96 @@ characteriationRiskFactorColDefs <- function(){ absSMD = reactable::colDef( name = "Absolute standardized mean difference", format = reactable::colFormat(digits = 2, percent = F) + ) + ) + return(result) +} + + + +characteriationRiskFactorContColDefs <- function(){ + result <- list( + covariateName = reactable::colDef( + name = "Covariate Name", + filterable = T + ), + covariateId = reactable::colDef( + show = F + ), + targetCountValue = reactable::colDef( + name = "Number of target population with feature", + format = reactable::colFormat( + percent = F, + separators = TRUE + ), + cell = function(value) { + if(is.null(value)){return('< min threshold')} + if(is.na(value)){return('< min threshold')} + if (value != -1) value else '< min threshold' + } ), - - analysisName = reactable::colDef( - filterInput = function(values, name) { - shiny::tags$select( - # Set to undefined to clear the filter - onchange = sprintf("Reactable.setFilter('desc-cont-select', '%s', event.target.value || undefined)", name), - # "All" has an empty value to clear the filter, and is the default option - shiny::tags$option(value = "", "All"), - lapply(unique(values), shiny::tags$option), - "aria-label" = sprintf("Filter %s", name), - style = "width: 100%; height: 28px;" - ) + caseCountValue = reactable::colDef( + name = "Number of cases with feature", + format = reactable::colFormat( + separators = TRUE, + percent = F + ), + cell = function(value) { + if(is.null(value)){return('< min threshold')} + if(is.na(value)){return('< min threshold')} + if (value != -1) value else '< min threshold' } + ), + targetAverageValue = reactable::colDef( + name = "Target mean feature value", + format = reactable::colFormat(digits = 2, percent = F) + ), + caseAverageValue = reactable::colDef( + name = "Cases mean feature value", + format = reactable::colFormat(digits = 2, percent = F) + ), + + targetStandardDeviation = reactable::colDef( + name = "Target standard deviation", + format = reactable::colFormat(digits = 2, percent = F) + ), + caseStandardDeviation = reactable::colDef( + name = "Cases standard deviation", + format = reactable::colFormat(digits = 2, percent = F) + ), + + #targetBoxPlot = reactable::colDef(cell = function(value, index) { + # ggplot2::ggplot() + + # ggplot2::geom_boxplot( + # ggplot2::aes( + # x = 1, + # ymin = data$targetMinValue[index], + # lower = data$targetP10Value[index], + # middle = data$targetMedianValue[index], + # upper = data$targetP90Value[index], + # ymax = data$targetMaxValue[index] + # ), + # stat = "identity" + # ) + #}), + #caseBoxPlot = reactable::colDef(cell = function(value, index) { + # sparkline(vcs_boxp_data$em_red_per_th[[index]], type = "box") + # }), + #caseBoxPlot = reactable::colDef(cell = function(value, index) { + # sparkline::sparkline(vcs_boxp_data$em_red_per_th[[index]], type = "box") + # }), + + # low_outlier, low_whisker, q1, median, q3, high_whisker, high_outlier + #sparkline::spk_chr(c(data$targetMinValue[index], data$targetP10Value[index], data$targetP25Value[index], data$targetMedianValue[index], 3, 6, 6), type="box", raw = TRUE, width = 200) + + SMD = reactable::colDef( + name = "SMD", + format = reactable::colFormat(digits = 2, percent = F) + ), + + absSMD = reactable::colDef( + name = "Absolute SMD", + format = reactable::colFormat(digits = 2, percent = F) ) ) return(result) diff --git a/R/estimation-main.R b/R/estimation-main.R index 9c61d895..9a725a63 100644 --- a/R/estimation-main.R +++ b/R/estimation-main.R @@ -155,7 +155,7 @@ estimationServer <- function( # use the function in report-main to get parent Ts with all children Ts, the outcomes for the Ts and the Cs - options <- OhdsiShinyModules:::getTandOs( + options <- getTandOs( connectionHandler, resultDatabaseSettings, includeCharacterization = F, @@ -212,15 +212,21 @@ estimationServer <- function( output$targetSelection <- shiny::renderUI({ shiny::fluidRow( shiny::div( - shiny::selectInput( + shinyWidgets::pickerInput( inputId = session$ns('targetId'), label = 'Target: ', choices = targets, - selected = 1, + selected = targets[1], multiple = FALSE, - selectize = TRUE, - width = NULL, - size = NULL + options = shinyWidgets::pickerOptions( + actionsBox = TRUE, + liveSearch = TRUE, + dropupAuto = F, + size = 10, + liveSearchStyle = "contains", + liveSearchPlaceholder = "Type here to search", + virtualScroll = 500 + ) ), shiny::selectInput( inputId = session$ns('outcomeId'), diff --git a/R/report-main.R b/R/report-main.R index fc63cb2a..c4bd8396 100644 --- a/R/report-main.R +++ b/R/report-main.R @@ -116,7 +116,7 @@ reportServer <- function( server = Sys.getenv("RESULTS_SERVER"), username = Sys.getenv("RESULTS_USER"), password = Sys.getenv("RESULTS_PASSWORD"), - dbms = "postgresql" + dbms = Sys.getenv("RESULTS_DBMS") ) { shiny::moduleServer( id, @@ -125,7 +125,9 @@ reportServer <- function( # get input options tnos <- getTandOs( connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings + resultDatabaseSettings = resultDatabaseSettings, + includeCohortIncidence = F, # turning off for speed + includeSccs = F # turning off for speed ) ## update input selectors @@ -226,8 +228,13 @@ reportServer <- function( } subsetTargets <- tnos$groupedTs[[which(unlist(lapply(tnos$groupedTs, function(x) ifelse(is.null(x$cohortId), F, x$cohortId == input$targetId))))]]$subsets ind <- !is.na(subsetTargets$subsetId) - cts <- subsetTargets$subsetId[ind] - names(cts) <- subsetTargets$targetName[ind] + if(sum(ind)>0){ + cts <- subsetTargets$subsetId[ind] + names(cts) <- subsetTargets$targetName[ind] + } else{ + cts <- '' + names(cts) <- 'No indication' + } cmTargets(cts) } ) @@ -312,10 +319,18 @@ reportServer <- function( if(!is.null(input$cmSubsetId) & !is.null(input$targetId)){ if(input$cmSubsetId != ''){ multipler <- ifelse(input$cmSubsetId == 0, 1, 1000) - temp <- tnos$cs[[which(names(tnos$cs) == as.double(input$targetId)*multipler + as.double(input$cmSubsetId))]] - comps <- temp$comparatorId - names(comps) <- temp$comparatorName - comparators(comps) + if(length(which(names(tnos$cs) == as.double(input$targetId)*multipler + as.double(input$cmSubsetId)))>0){ + temp <- tnos$cs[[which(names(tnos$cs) == as.double(input$targetId)*multipler + as.double(input$cmSubsetId))]] + comps <- temp$comparatorId + names(comps) <- temp$comparatorName + comparators(comps) + } else{ + comps <- '' + names(comps) <- 'No Comparator' + comparators(comps) + } + } else{ + shiny::showNotification('No indication available') } } @@ -415,10 +430,21 @@ reportServer <- function( if(is.null(input$targetId)){ return(NULL) } - temp <- tnos$tos[[which(names(tnos$tos) == input$targetId)]] - os <- temp$outcomeId - names(os) <- temp$outcomeName - outcomes(os) + + multipler <- ifelse(input$cmSubsetId == 0, 1, 1000) + cmTargetId <- as.double(input$targetId)*multipler + as.double(input$cmSubsetId) + + if(length(which(names(tnos$tos) %in% c(input$targetId, cmTargetId) ))>0){ + temp <- tnos$tos[[which(names(tnos$tos) %in% c(input$targetId, cmTargetId))[1] ]] + os <- temp$outcomeId + names(os) <- temp$outcomeName + outcomes(os) + } else{ + os <- '' + names(os) <- 'None' + outcomes(os) + shiny::showNotification('No Outcomes') + } } ) @@ -585,7 +611,8 @@ reportServer <- function( width = 6, shiny::dateRangeInput( inputId = session$ns('dateRestriction'), - label = 'Study date restriction' + label = 'Study date restriction', + start = '1990-01-01' ) ), shiny::column( @@ -742,7 +769,7 @@ getTandOs <- function( ){ # get cohorts - sql <- 'select * from @schema.@cg_table_prefixcohort_definition;' + sql <- 'select distinct * from @schema.@cg_table_prefixcohort_definition order by cohort_name;' cg <- connectionHandler$queryDb( sql = sql, schema = resultDatabaseSettings$schema, diff --git a/extras/examples/app.R b/extras/examples/app.R index 5f61dafc..e6b74054 100644 --- a/extras/examples/app.R +++ b/extras/examples/app.R @@ -1,5 +1,5 @@ -#remotes::install_github('ohdsi/OhdsiShinyModules', ref = 'develop') -#remotes::install_github("ohdsi/ShinyAppBuilder", ref = "develop") +#remotes::install_github('ohdsi/OhdsiShinyModules', ref = 'estimation') +#remotes::install_github("ohdsi/ShinyAppBuilder", ref = "estimation") library(dplyr) library(ShinyAppBuilder) # need to install if you do not have it library(markdown) @@ -20,6 +20,11 @@ if(!dir.exists('./drivers')){ connectionDetails <- OhdsiShinyModules::getExampleConnectionDetails() schema <- "main" +#Sys.setenv(RESULTS_SERVER = system.file("extdata", "results.sqlite", package = "OhdsiShinyModules")) +#Sys.unsetenv('RESULTS_USER') +#Sys.unsetenv('RESULTS_PASSWORD') +#Sys.setenv(RESULTS_DBMS = "sqlite") + est <- ShinyAppBuilder::createModuleConfig( moduleId = 'estimation', tabName = 'Estimation', @@ -46,7 +51,7 @@ config <- initializeModuleConfig() %>% createDefaultCohortDiagnosticsConfig() ) %>% addModuleConfig( - est + createDefaultEstimationConfig() ) %>% addModuleConfig( createDefaultCharacterizationConfig() From e269342f185f890eab6ba529a1ec2f4888e2de04 Mon Sep 17 00:00:00 2001 From: jreps Date: Tue, 21 May 2024 09:21:19 -0400 Subject: [PATCH 06/64] Update characterization-incidence.R - adding code to use CI TAR lookup if available --- R/characterization-incidence.R | 204 +++++++++++++++++++++------------ 1 file changed, 132 insertions(+), 72 deletions(-) diff --git a/R/characterization-incidence.R b/R/characterization-incidence.R index fdbeef59..29fc356c 100644 --- a/R/characterization-incidence.R +++ b/R/characterization-incidence.R @@ -257,24 +257,22 @@ characterizationIncidenceServer <- function( ## ns <- session$ns - ages <- c(2:12, NA) - names(ages) <- c(sapply(2:12, function(i) paste0((i-2)*10,' - ',(i-1)*10-1)), 'All') + ages <- c(2:12, 'Any') + names(ages) <- c(sapply(2:12, function(i) paste0((i-2)*10,' - ',(i-1)*10-1)), 'Any') - sex <- c(8507, 8532 , NA) - names(sex) <- c('Male', 'Female', 'All') + sex <- c(8507, 8532 , 'Any') + names(sex) <- c('Male', 'Female', 'Any') - startYear <- c(NA, format(Sys.Date(), "%Y"):1990) - names(startYear) <- c('All', format(Sys.Date(), "%Y"):1990) + startYear <- c('Any', format(Sys.Date(), "%Y"):1990) + names(startYear) <- c('Any', format(Sys.Date(), "%Y"):1990) # get tar and then call cohortIncidenceFormatTar() - tarDf <- data.frame( - tarId = 1:3, - tarStartWith = c('start','start','start'), - tarStartOffset = c(1,1,1), - tarEndWith = c('start','start','end'), - tarEndOffset = c(9999,30,0) + tarDf <- characterizationGetCiTars( + connectionHandler, + resultDatabaseSettings ) + sortedTars <- tarDf$tarId names(sortedTars) <- cohortIncidenceFormatTar(tarDf) @@ -383,7 +381,7 @@ characterizationIncidenceServer <- function( incidenceRateAgeFilter <- shiny::reactiveVal(NULL) incidenceRateGenderFilter <- shiny::reactiveVal(NULL) shiny::observeEvent(input$generate,{ - incidenceRateTarFilter(input$tars) + incidenceRateTarFilter(names(sortedTars)[sortedTars == input$tars]) # filter needs actual value incidenceRateCalendarFilter(input$startYears) incidenceRateAgeFilter(input$ageIds) incidenceRateGenderFilter(input$sexIds) @@ -587,74 +585,63 @@ characterizationIncidenceServer <- function( ) - filteredData <- shiny::reactive( + extractedData <- shiny::reactiveVal() + shiny::observeEvent(input$generate , { if (is.null(targetIds()) | is.null(outcomeIds()) ) { - return(data.frame()) + extractededData(data.frame()) } - else if(targetIds() == outcomeIds() && + else if(targetIds()[1] == outcomeIds()[1] && length(targetIds())==1 && length(outcomeIds())==1 ){ shiny::validate("Target and outcome cohorts must differ from each other. Make a different selection.") } else { - getIncidenceData(targetIds = targetIds(), + result <- getIncidenceData(targetIds = targetIds(), outcomeIds = outcomeIds(), connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings - ) %>% + ) + extractedData(result) + } + } + ) + + filteredData <- shiny::reactive({ + if(nrow(extractedData()) > 0){ + extractedData() %>% dplyr::relocate("tar", .before = "outcomes") %>% dplyr::mutate(incidenceProportionP100p = as.numeric(.data$incidenceProportionP100p), incidenceRateP100py = as.numeric(.data$incidenceRateP100py), dplyr::across(dplyr::where(is.numeric), round, 4), targetIdShort = paste("C", .data$targetCohortDefinitionId, sep = "-"), outcomeIdShort = paste("C", .data$outcomeCohortDefinitionId, sep = "-")) %>% - dplyr::filter(.data$ageGroupName %in% !! incidenceRateAgeFilter() & - .data$genderName %in% !! incidenceRateGenderFilter() & + dplyr::filter(.data$ageId %in% !! incidenceRateAgeFilter() & + .data$genderId %in% !! incidenceRateGenderFilter() & .data$startYear %in% !! incidenceRateCalendarFilter() ) %>% - dplyr::relocate("targetIdShort", .after = "targetName") %>% - dplyr::relocate("outcomeIdShort", .after = "outcomeName") - } + dplyr::relocate("targetIdShort", .after = "targetName") %>% + dplyr::relocate("outcomeIdShort", .after = "outcomeName") } - ) + }) - filteredDataAggregateForPlot <- shiny::reactive( - { - if (is.null(targetIds()) | - is.null(outcomeIds()) - ) { - return(data.frame()) - } - - else if(targetIds() == outcomeIds() && - length(targetIds()) == 1 && length(outcomeIds()) == 1 - ){ - shiny::validate("Target and outcome cohorts must differ from each other. Make a different selection.") - } - - else { - getIncidenceData(targetIds = targetIds(), - outcomeIds = outcomeIds(), - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) %>% - dplyr::relocate("tar", .before = "outcomes") %>% - dplyr::mutate(incidenceProportionP100p = as.numeric(.data$incidenceProportionP100p), - incidenceRateP100py = as.numeric(.data$incidenceRateP100py), - dplyr::across(dplyr::where(is.numeric), round, 4), - targetIdShort = paste("C", .data$targetCohortDefinitionId, sep = "-"), - outcomeIdShort = paste("C", .data$outcomeCohortDefinitionId, sep = "-")) %>% - dplyr::relocate("targetIdShort", .after = "targetName") %>% - dplyr::relocate("outcomeIdShort", .after = "outcomeName") - - } + filteredDataAggregateForPlot <- shiny::reactive({ + if(nrow(extractedData()) > 0){ + extractedData() %>% + dplyr::relocate("tar", .before = "outcomes") %>% + dplyr::mutate(incidenceProportionP100p = as.numeric(.data$incidenceProportionP100p), + incidenceRateP100py = as.numeric(.data$incidenceRateP100py), + dplyr::across(dplyr::where(is.numeric), round, 4), + targetIdShort = paste("C", .data$targetCohortDefinitionId, sep = "-"), + outcomeIdShort = paste("C", .data$outcomeCohortDefinitionId, sep = "-")) %>% + dplyr::relocate("targetIdShort", .after = "targetName") %>% + dplyr::relocate("outcomeIdShort", .after = "outcomeName") } - ) + }) @@ -668,15 +655,15 @@ characterizationIncidenceServer <- function( ## CHECK - caused error for me but it is in Nate's latest code class(incidenceColList$genderName$filterMethod) <- "JS_EVAL" - renderIrTable <- shiny::reactive( - { - filteredData() - } - ) + #renderIrTable <- shiny::reactive( + # { + # filteredData() + # } + #) resultTableServer( id = "incidenceRateTable", - df = renderIrTable, + df = filteredData, #renderIrTable, selectedCols = c("cdmSourceAbbreviation", "targetName", "targetIdShort", "outcomeName", "outcomeIdShort", "ageGroupName", "genderName", "startYear", "tar", "outcomes", "incidenceProportionP100p", "incidenceRateP100py"), @@ -687,14 +674,18 @@ characterizationIncidenceServer <- function( ) '%!in%' <- function(x,y)!('%in%'(x,y)) + #ir plots - irPlotCustom <- shiny::reactive( + irPlotCustom <- shiny::reactive( # observeEvent generate instead? { if (is.null(targetIds()) | is.null(outcomeIds())) { return(data.frame()) } + if(nrow(filteredData()) == 0){ + return(FALSE) + } ifelse(incidenceRateTarFilter() %in% filteredData()$tar, plotData <- filteredData() %>% @@ -1002,6 +993,9 @@ characterizationIncidenceServer <- function( is.null(outcomeIds())) { shiny::validate("Please select at least one target and one outcome.") } + if(nrow(filteredData()) == 0){ + shiny::validate("No results.") + } else { plotData <- filteredData() %>% @@ -1056,6 +1050,9 @@ characterizationIncidenceServer <- function( is.null(outcomeIds())) { shiny::validate("Please select at least one target and one outcome.") } + if(nrow(filteredData()) == 0){ + shiny::validate("No results.") + } else { plotData <- filteredData() %>% @@ -1120,6 +1117,9 @@ characterizationIncidenceServer <- function( is.null(outcomeIds())) { return(data.frame()) } + if(nrow(filteredData()) == 0){ + shiny::validate("No results.") + } ifelse(incidenceRateTarFilter() %in% filteredData()$tar, plotData <- filteredData() %>% @@ -1262,6 +1262,9 @@ renderIrPlotStandardAgeSex <- shiny::reactive( is.null(outcomeIds())) { return(data.frame()) } + if(nrow(filteredData()) == 0){ + return(data.frame()) + } ifelse(incidenceRateTarFilter() %in% filteredData()$tar, plotData <- filteredData() %>% @@ -1402,6 +1405,9 @@ renderIrPlotStandardYear <- shiny::reactive( is.null(outcomeIds())) { return(data.frame()) } + if(nrow(filteredData()) == 0){ + return(data.frame()) + } ifelse(incidenceRateTarFilter() %in% filteredData()$tar, plotData <- filteredData() %>% @@ -1547,6 +1553,9 @@ renderIrPlotStandardAggregate <- shiny::reactive( is.null(outcomeIds())) { return(data.frame()) } + if(nrow(filteredData()) == 0){ + return(data.frame()) + } ifelse(incidenceRateTarFilter() %in% filteredData()$tar, plotData <- filteredDataAggregateForPlot() %>% @@ -1692,6 +1701,9 @@ getIncidenceData <- function( if(!is.null(targetIds) & !is.null(outcomeIds)){ + print(targetIds) + print(outcomeIds) + shiny::withProgress(message = 'Getting incidence data', value = 0, { sql <- 'select d.cdm_source_abbreviation, i.* @@ -1713,19 +1725,22 @@ getIncidenceData <- function( database_table_name = resultDatabaseSettings$databaseTable ) - shiny::incProgress(2/2, detail = paste("Done...")) + shiny::incProgress(2/2, detail = paste("Extracted ", nrow(resultTable)," rows")) }) - # format the tar - ##Jenna edit resultTable$tar <- paste0('(',resultTable$tarStartWith, " + ", resultTable$tarStartOffset, ') - (', resultTable$tarEndWith, " + ", resultTable$tarEndOffset, ')') - resultTable$tar <- cohortIncidenceFormatTar(resultTable) - - resultTable <- resultTable %>% - dplyr::select(-c("tarStartWith","tarStartOffset","tarEndWith","tarEndOffset", "tarId", "subgroupName")) - - resultTable[is.na(resultTable)] <- 'Any' - resultTable <- unique(resultTable) + if(nrow(resultTable)>0){ + + # format the tar + ##Jenna edit resultTable$tar <- paste0('(',resultTable$tarStartWith, " + ", resultTable$tarStartOffset, ') - (', resultTable$tarEndWith, " + ", resultTable$tarEndOffset, ')') + resultTable$tar <- cohortIncidenceFormatTar(resultTable) + + resultTable <- resultTable %>% + dplyr::select(-c("tarStartWith","tarStartOffset","tarEndWith","tarEndOffset", "tarId", "subgroupName")) + + resultTable[is.na(resultTable)] <- 'Any' + resultTable <- unique(resultTable) + } return(resultTable) } else{ @@ -1896,3 +1911,48 @@ getIncidenceOptions <- function(){ } + + +characterizationGetCiTars <- function( + connectionHandler, + resultDatabaseSettings +){ + + useLookup <- tryCatch( + { + connectionHandler$queryDb( + sql = "SELECT * + from + @schema.@ci_table_prefixtar_lookup limit 1;", + schema = resultDatabaseSettings$schema, + ci_table_prefix = resultDatabaseSettings$incidenceTablePrefix + ) + }, + error = function(e) return(c()) + ) + + if(length(useLookup)>0){ + sql <- "SELECT distinct * + from + @schema.@ci_table_prefixtar_lookup;" + + tars <- connectionHandler$queryDb( + sql = sql, + schema = resultDatabaseSettings$schema, + ci_table_prefix = resultDatabaseSettings$incidenceTablePrefix + ) + } else{ + sql <- "SELECT distinct TAR_ID, TAR_START_WITH, TAR_START_OFFSET, + TAR_END_WITH, TAR_END_OFFSET + from + @schema.@ci_table_prefixincidence_summary;" + + tars <- connectionHandler$queryDb( + sql = sql, + schema = resultDatabaseSettings$schema, + ci_table_prefix = resultDatabaseSettings$incidenceTablePrefix + ) + } + return(tars) +} + From 9b62ec46e1ad672c41e869617607bb18c427e013 Mon Sep 17 00:00:00 2001 From: jreps Date: Wed, 22 May 2024 09:05:17 -0400 Subject: [PATCH 07/64] minor exclude fixes minor exclude fixes --- R/characterization-caseSeries.R | 4 +- R/characterization-riskFactors.R | 13 +- hs_err_pid47729.log | 1199 ++++++++++++++++++++++++++++++ 3 files changed, 1209 insertions(+), 7 deletions(-) create mode 100644 hs_err_pid47729.log diff --git a/R/characterization-caseSeries.R b/R/characterization-caseSeries.R index 8897dc2a..c17d0247 100644 --- a/R/characterization-caseSeries.R +++ b/R/characterization-caseSeries.R @@ -166,9 +166,9 @@ characterizationGetCaseSeriesOptions <- function( names(db) <- unique(options$databaseName) tar <- unique(options$timeAtRiskId) - names(tar) <- paste0('(', options$startAnchor, ' + ', options$riskWindowStart, ') - (', + names(tar) <- unique(paste0('(', options$startAnchor, ' + ', options$riskWindowStart, ') - (', options$endAnchor, ' + ', options$riskWindowEnd, ')' - ) + )) return( list( diff --git a/R/characterization-riskFactors.R b/R/characterization-riskFactors.R index 05141591..ce0da5e0 100644 --- a/R/characterization-riskFactors.R +++ b/R/characterization-riskFactors.R @@ -252,6 +252,8 @@ riskFactorTable <- function( dplyr::filter(.data$cohortDefinitionId == !!caseId) %>% dplyr::select(-"cohortDefinitionId") + print(paste0(caseData, 'cases')) + allId <- ids$cohortDefinitionId[ids$cohortType == 'T'] allData <- data %>% dplyr::filter(.data$cohortDefinitionId == !!allId) %>% @@ -267,18 +269,19 @@ riskFactorTable <- function( dplyr::select(-"cohortDefinitionId") if(nrow(excludeData) > 0 ){ - excludeData$exclude_N <- excludeData$sumValue[1]/excludeData$averageValue[1] + excludeData$N <- excludeData$sumValue[1]/excludeData$averageValue[1] + excludeN <- excludeData$sumValue[1]/excludeData$averageValue[1] colnames(excludeData)[!colnames(excludeData) %in% c('covariateId', 'covariateName')] <- paste0('exclude_',colnames(excludeData)) - + # if prior Os then exclude from T allData <- allData %>% dplyr::full_join(excludeData, by = c('covariateId', 'covariateName')) %>% dplyr::mutate( - sumValue = .data$sumValue - .data$prior_sumValue, - averageValue = (.data$sumValue - .data$prior_sumValue)/(.data$N-.data$exclude_N) + sumValue = .data$sumValue - .data$exclude_sumValue, + averageValue = (.data$sumValue - .data$exclude_sumValue)/(.data$N-!!excludeN) ) %>% dplyr::mutate( - N = .data$N-.data$exclude_N + N = .data$N-!!excludeN ) %>% dplyr::select("covariateId","covariateName","sumValue","averageValue", "N") diff --git a/hs_err_pid47729.log b/hs_err_pid47729.log new file mode 100644 index 00000000..9a096be6 --- /dev/null +++ b/hs_err_pid47729.log @@ -0,0 +1,1199 @@ +# +# A fatal error has been detected by the Java Runtime Environment: +# +# SIGSEGV (0xb) at pc=0x000000010d4ca9d8, pid=47729, tid=259 +# +# JRE version: OpenJDK Runtime Environment Corretto-17.0.5.8.1 (17.0.5+8) (build 17.0.5+8-LTS) +# Java VM: OpenJDK 64-Bit Server VM Corretto-17.0.5.8.1 (17.0.5+8-LTS, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, bsd-aarch64) +# Problematic frame: +# V [libjvm.dylib+0x4ca9d8] jni_GetObjectClass+0x124 +# +# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again +# +# If you would like to submit a bug report, please visit: +# https://github.com/corretto/corretto-17/issues/ +# + +--------------- S U M M A R Y ------------ + +Command Line: -Djava.awt.headless=true -Xmx512m -Xrs vfprintf exit -Xss2m + +Host: "MacBookPro18,3" arm64, 8 cores, 16G, Darwin 23.5.0, macOS 14.5 (23F79) +Time: Wed May 22 09:03:48 2024 EDT elapsed time: 74.128281 seconds (0d 0h 1m 14s) + +--------------- T H R E A D --------------- + +Current thread (0x000000011e307600): JavaThread "main" [_thread_in_vm, id=259, stack(0x000000016b494000,0x000000016bc90000)] + +Stack: [0x000000016b494000,0x000000016bc90000], sp=0x000000016bc7a5c0, free space=8089k +Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) +V [libjvm.dylib+0x4ca9d8] jni_GetObjectClass+0x124 +C [rJava.so+0x60fc] RcallMethod+0x37c +C [libR.dylib+0x847ec] do_External+0x12c +C [libR.dylib+0xbb9ec] bcEval+0x6eec +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd030c] Rf_applyClosure+0x20c +C [libR.dylib+0xbb6b0] bcEval+0x6bb0 +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd030c] Rf_applyClosure+0x20c +C [libR.dylib+0x11d400] dispatchMethod+0x300 +C [libR.dylib+0x11d0c0] Rf_usemethod+0x300 +C [libR.dylib+0x11d768] do_usemethod+0x2e8 +C [libR.dylib+0xbc0b0] bcEval+0x75b0 +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd030c] Rf_applyClosure+0x20c +C [libR.dylib+0xb479c] Rf_eval+0x51c +C [libR.dylib+0xd4264] do_begin+0x1a4 +C [libR.dylib+0xb46c8] Rf_eval+0x448 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd030c] Rf_applyClosure+0x20c +C [libR.dylib+0xbb6b0] bcEval+0x6bb0 +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd28e4] R_execMethod+0x2a4 +C [methods.so+0x3db0] R_dispatchGeneric+0x9b0 +C [libR.dylib+0x11fdb8] do_standardGeneric+0x1b8 +C [libR.dylib+0xbb9ec] bcEval+0x6eec +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd030c] Rf_applyClosure+0x20c +C [libR.dylib+0xbb6b0] bcEval+0x6bb0 +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd28e4] R_execMethod+0x2a4 +C [methods.so+0x3db0] R_dispatchGeneric+0x9b0 +C [libR.dylib+0x11fdb8] do_standardGeneric+0x1b8 +C [libR.dylib+0xbb9ec] bcEval+0x6eec +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd030c] Rf_applyClosure+0x20c +C [libR.dylib+0xb479c] Rf_eval+0x51c +C [libR.dylib+0xd4264] do_begin+0x1a4 +C [libR.dylib+0xb46c8] Rf_eval+0x448 +C [libR.dylib+0xcfa24] forcePromise+0xa4 +C [libR.dylib+0xdb938] getvar+0x2b8 +C [libR.dylib+0xb8a90] bcEval+0x3f90 +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xcfa24] forcePromise+0xa4 +C [libR.dylib+0xdb938] getvar+0x2b8 +C [libR.dylib+0xb8a90] bcEval+0x3f90 +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xcfa24] forcePromise+0xa4 +C [libR.dylib+0xdb938] getvar+0x2b8 +C [libR.dylib+0xb8a90] bcEval+0x3f90 +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xcfa24] forcePromise+0xa4 +C [libR.dylib+0xdb938] getvar+0x2b8 +C [libR.dylib+0xb8a90] bcEval+0x3f90 +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd030c] Rf_applyClosure+0x20c +C [libR.dylib+0xbb6b0] bcEval+0x6bb0 +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd030c] Rf_applyClosure+0x20c +C [libR.dylib+0xbb6b0] bcEval+0x6bb0 +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd030c] Rf_applyClosure+0x20c +C [libR.dylib+0xbb6b0] bcEval+0x6bb0 +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd030c] Rf_applyClosure+0x20c +C [libR.dylib+0xb479c] Rf_eval+0x51c +C [libR.dylib+0xd4264] do_begin+0x1a4 +C [libR.dylib+0xb46c8] Rf_eval+0x448 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd030c] Rf_applyClosure+0x20c +C [libR.dylib+0xbb6b0] bcEval+0x6bb0 +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd030c] Rf_applyClosure+0x20c +C [libR.dylib+0xb479c] Rf_eval+0x51c +C [libR.dylib+0xd4264] do_begin+0x1a4 +C [libR.dylib+0xb46c8] Rf_eval+0x448 +C [libR.dylib+0xd36d0] do_for+0xa50 +C [libR.dylib+0xb46c8] Rf_eval+0x448 +C [libR.dylib+0xd4264] do_begin+0x1a4 +C [libR.dylib+0xb46c8] Rf_eval+0x448 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd030c] Rf_applyClosure+0x20c +C [libR.dylib+0xbb6b0] bcEval+0x6bb0 +C [libR.dylib+0xb44c8] Rf_eval+0x248 +C [libR.dylib+0xd1ad4] R_execClosure+0xc54 +C [libR.dylib+0xd28e4] R_execMethod+0x2a4 +C [methods.so+0x3db0] R_dispatchGeneric+0x9b0 +C [libR.dylib+0x11fdb8] do_standardGeneric+0x1b8 +...... + + +siginfo: si_signo: 11 (SIGSEGV), si_code: 2 (SEGV_ACCERR), si_addr: 0x0000000000000000 + +Register to memory mapping: + + x0=0x0 is NULL + x1=0x000000011c7d4198 points into unknown readable memory: 0x0000000000000000 | 00 00 00 00 00 00 00 00 + x2=0x000000010d4ca8b4: jni_GetObjectClass+0 in /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/server/libjvm.dylib at 0x000000010d000000 + x3=0x000000016bc7a9e0 is pointing into the stack for thread: 0x000000011e307600 + x4=0x000000016bc7aa08 is pointing into the stack for thread: 0x000000011e307600 + x5=0x0 is NULL + x6=0x000000010b0b2cf8 points into unknown readable memory: 0x0000000611000006 | 06 00 00 11 06 00 00 00 + x7=0x000000017af81398 points into unknown readable memory: 0x0000000400100004 | 04 00 10 00 04 00 00 00 + x8=0x0000000000000001 is an unknown value + x9=0x0000000000000006 is an unknown value +x10=0x2010002030300000 is an unknown value +x11=0x0000ffff11000000 is an unknown value +x12=0xffff0000eeffffff is an unknown value +x13=0x000000000000ffff is an unknown value +x14=0x000000011e03d840 points into unknown readable memory: 0x0000000211000008 | 08 00 00 11 02 00 00 00 +x15=0xffff0000eeffffff is an unknown value +x16=0x000000018cd9bd7c: pthread_jit_write_protect_np+0 in /usr/lib/system/libsystem_pthread.dylib at 0x000000018cd94000 +x17=0x000000011d9f76e0 points into unknown readable memory: 0xfffffffffffffffe | fe ff ff ff ff ff ff ff +x18=0x0 is NULL +x19=0x0000000000000001 is an unknown value +x20=0x000000011e307600 is a thread +x21=0x000000011e307600 is a thread +x22=0x000000011c7d4198 points into unknown readable memory: 0x0000000000000000 | 00 00 00 00 00 00 00 00 +x23=0x000000010dc15000: _dyld_private+0 in /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/server/libjvm.dylib at 0x000000010d000000 +x24=0x0 is NULL +x25=0x000000011e285800 points into unknown readable memory: 0x00000001f1000013 | 13 00 00 f1 01 00 00 00 +x26=0x0000000105ccdd50: R_NilValue+0 in /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libR.dylib at 0x0000000105890000 +x27=0x0000000105ccdd50: R_NilValue+0 in /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libR.dylib at 0x0000000105890000 +x28=0x0000000105ccdb58: R_BCNodeStackTop+0 in /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libR.dylib at 0x0000000105890000 + + +Registers: + x0=0x0000000000000000 x1=0x000000011c7d4198 x2=0x000000010d4ca8b4 x3=0x000000016bc7a9e0 + x4=0x000000016bc7aa08 x5=0x0000000000000000 x6=0x000000010b0b2cf8 x7=0x000000017af81398 + x8=0x0000000000000001 x9=0x0000000000000006 x10=0x2010002030300000 x11=0x0000ffff11000000 +x12=0xffff0000eeffffff x13=0x000000000000ffff x14=0x000000011e03d840 x15=0xffff0000eeffffff +x16=0x000000018cd9bd7c x17=0x000000011d9f76e0 x18=0x0000000000000000 x19=0x0000000000000001 +x20=0x000000011e307600 x21=0x000000011e307600 x22=0x000000011c7d4198 x23=0x000000010dc15000 +x24=0x0000000000000000 x25=0x000000011e285800 x26=0x0000000105ccdd50 x27=0x0000000105ccdd50 +x28=0x0000000105ccdb58 fp=0x000000016bc7a610 lr=0x000000010d4ca9c8 sp=0x000000016bc7a5c0 +pc=0x000000010d4ca9d8 cpsr=0x0000000040001000 +Top of Stack: (sp=0x000000016bc7a5c0) +0x000000016bc7a5c0: 000000011e307600 0000000000000000 +0x000000016bc7a5d0: 000000016bc7a610 000000010520d230 +0x000000016bc7a5e0: 0000000105ccdd50 000000017a753600 +0x000000016bc7a5f0: 000000017a753670 000000011c7d4198 +0x000000016bc7a600: 0000000000000000 000000011e3078a8 +0x000000016bc7a610: 000000016bc7a9b0 00000001052060fc +0x000000016bc7a620: 0000000163d2af48 00000001787e85d8 +0x000000016bc7a630: 000000016bc7b348 000000010b0b03c8 +0x000000016bc7a640: 0000000000000000 000000011e0207c8 +0x000000016bc7a650: 00000001200d9e10 00000001635143d8 +0x000000016bc7a660: 0000000163a1a580 0000000163a1a510 +0x000000016bc7a670: 0000000163a1a468 a9885dc159fb0020 +0x000000016bc7a680: 000000016bc7a6e0 0000000105961fac +0x000000016bc7a690: 0000000105ccdd50 0000000105ccdce8 +0x000000016bc7a6a0: 000000011e0208e0 0000000105ccdd68 +0x000000016bc7a6b0: 0000000000000000 000000011e0511c8 +0x000000016bc7a6c0: 0000000163a1dd90 0000000163a1a468 +0x000000016bc7a6d0: 000000011e084408 000000011e0d2198 +0x000000016bc7a6e0: 000000016bc7a750 000000010596031c +0x000000016bc7a6f0: 0000000105ccd570 000000011e020758 +0x000000016bc7a700: 0000000105ccdb58 0000000163a1dd90 +0x000000016bc7a710: 000000016bc7a750 0000000105960410 +0x000000016bc7a720: 000000010b35a0e0 000000011e084408 +0x000000016bc7a730: 0000000000000000 000000011e012c48 +0x000000016bc7a740: 0000000000000000 0000000105ccdd50 +0x000000016bc7a750: 000000011e01fdf0 000000011e609be0 +0x000000016bc7a760: 0000000178bb8e78 0000000178bb8dd0 +0x000000016bc7a770: 000000016bc7a7b0 00000001058c396c +0x000000016bc7a780: 0000000000000000 000000010b0b2c50 +0x000000016bc7a790: 0000000105bc4000 0000000105ccdd50 +0x000000016bc7a7a0: 00000001200d9e28 0000000105ccdfd0 +0x000000016bc7a7b0: 0000000105ccdd00 000000017a753670 + +Instructions: (pc=0x000000010d4ca9d8) +0x000000010d4ca8d8: 9102e008 b8bfc108 129bd549 0b090108 +0x000000010d4ca8e8: 7100091f 540000a3 aa1503e0 941361b9 +0x000000010d4ca8f8: d2800015 1400000a b4000135 b9427ab3 +0x000000010d4ca908: 34000093 b9027abf 52800000 940be1db +0x000000010d4ca918: 52800018 aa1503f4 14000004 d2800014 +0x000000010d4ca928: 52800013 52800038 910ce288 528000a9 +0x000000010d4ca938: 889ffd09 d5033bbf 910d0288 f8bfc108 +0x000000010d4ca948: 36000088 aa1403e0 52800021 940e0293 +0x000000010d4ca958: b9432e88 35000088 b9432a88 721e051f +0x000000010d4ca968: 54000080 aa1403e0 52800001 941367d1 +0x000000010d4ca978: 910ce288 528000c9 889ffd09 a9007ff4 +0x000000010d4ca988: f9400688 b4000068 910003e0 940cdcca +0x000000010d4ca998: aa1703e0 aa1603e1 d503201f f0003a57 +0x000000010d4ca9a8: 37000096 f94046e8 aa1603e0 14000004 +0x000000010d4ca9b8: d10006c0 f0003a68 f9471108 d63f0100 +0x000000010d4ca9c8: d0003c68 91168508 39400108 340001c8 +0x000000010d4ca9d8: b9400808 90003a89 911e0129 f940012a +0x000000010d4ca9e8: b9400929 9ac92108 8b0a0108 f9403900 +0x000000010d4ca9f8: b4000100 f94046e8 d63f0100 aa0003e1 +0x000000010d4caa08: 14000005 f9400408 f9403900 b5ffff40 +0x000000010d4caa18: d2800001 aa1503e0 52800002 9400fc69 +0x000000010d4caa28: aa0003f5 d503201f f94007e8 b4000068 +0x000000010d4caa38: 910003e0 940cdcca f9407696 f9400ac8 +0x000000010d4caa48: f9400109 b4000089 aa1603e0 97fd1692 +0x000000010d4caa58: f9400ac8 f94006c9 f9000928 f9400ec8 +0x000000010d4caa68: f94006c9 f9000d28 f94012c8 f94006c9 +0x000000010d4caa78: f9001128 910a2280 97fa5350 d5033bbf +0x000000010d4caa88: 910ce288 52800089 889ffd09 370000f8 +0x000000010d4caa98: b9427a88 6b13011f 54000080 b9027a93 +0x000000010d4caaa8: aa1303e0 940be175 aa1503e0 a9457bfd +0x000000010d4caab8: a9444ff4 a94357f6 a9425ff8 910183ff +0x000000010d4caac8: d65f03c0 a9bc5ff8 a90157f6 a9024ff4 + + +Stack slot to memory mapping: +stack at sp + 0 slots: 0x000000011e307600 is a thread +stack at sp + 1 slots: 0x0 is NULL +stack at sp + 2 slots: 0x000000016bc7a610 is pointing into the stack for thread: 0x000000011e307600 +stack at sp + 3 slots: 0x000000010520d230: getJNIEnv+0x70 in /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/rJava/libs/rJava.so at 0x0000000105200000 +stack at sp + 4 slots: 0x0000000105ccdd50: R_NilValue+0 in /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libR.dylib at 0x0000000105890000 +stack at sp + 5 slots: 0x000000017a753600 points into unknown readable memory: 0x0000000000000002 | 02 00 00 00 00 00 00 00 +stack at sp + 6 slots: 0x000000017a753670 points into unknown readable memory: 0x0000000100000002 | 02 00 00 00 01 00 00 00 +stack at sp + 7 slots: 0x000000011c7d4198 points into unknown readable memory: 0x0000000000000000 | 00 00 00 00 00 00 00 00 + + +--------------- P R O C E S S --------------- + +Threads class SMR info: +_java_thread_list=0x000000010c704350, length=11, elements={ +0x000000011e307600, 0x000000010c88d400, 0x000000010c8c7400, 0x000000011e7fa800, +0x000000011e2bd600, 0x000000011e32f600, 0x000000010cac2200, 0x000000011cc09200, +0x000000011f155600, 0x000000011ce61800, 0x000000011e71fe00 +} + +Java Threads: ( => current thread ) +=>0x000000011e307600 JavaThread "main" [_thread_in_vm, id=259, stack(0x000000016b494000,0x000000016bc90000)] + 0x000000010c88d400 JavaThread "Reference Handler" daemon [_thread_blocked, id=18179, stack(0x000000016ccb0000,0x000000016ceb3000)] + 0x000000010c8c7400 JavaThread "Finalizer" daemon [_thread_blocked, id=19971, stack(0x000000016cebc000,0x000000016d0bf000)] + 0x000000011e7fa800 JavaThread "Attach Listener" daemon [_thread_blocked, id=31491, stack(0x000000016d1e0000,0x000000016d3e3000)] + 0x000000011e2bd600 JavaThread "Service Thread" daemon [_thread_blocked, id=31235, stack(0x000000016d3ec000,0x000000016d5ef000)] + 0x000000011e32f600 JavaThread "Monitor Deflation Thread" daemon [_thread_blocked, id=30979, stack(0x000000016d5f8000,0x000000016d7fb000)] + 0x000000010cac2200 JavaThread "C2 CompilerThread0" daemon [_thread_blocked, id=23043, stack(0x000000016d804000,0x000000016da07000)] + 0x000000011cc09200 JavaThread "C1 CompilerThread0" daemon [_thread_blocked, id=23299, stack(0x000000016da10000,0x000000016dc13000)] + 0x000000011f155600 JavaThread "Sweeper thread" daemon [_thread_blocked, id=23555, stack(0x000000016dc1c000,0x000000016de1f000)] + 0x000000011ce61800 JavaThread "Notification Thread" daemon [_thread_blocked, id=23811, stack(0x000000016de28000,0x000000016e02b000)] + 0x000000011e71fe00 JavaThread "Common-Cleaner" daemon [_thread_blocked, id=29187, stack(0x000000016e240000,0x000000016e443000)] + +Other Threads: + 0x000000011d9c8140 VMThread "VM Thread" [stack: 0x000000016caa4000,0x000000016cca7000] [id=17411] + 0x000000011c7dcb70 WatcherThread [stack: 0x000000016e034000,0x000000016e237000] [id=29443] + 0x0000000105723230 GCTaskThread "GC Thread#0" [stack: 0x000000016c068000,0x000000016c26b000] [id=12035] + 0x000000010e199ff0 GCTaskThread "GC Thread#1" [stack: 0x000000016e7fc000,0x000000016e9ff000] [id=43015] + 0x000000010e196760 GCTaskThread "GC Thread#2" [stack: 0x000000016ea08000,0x000000016ec0b000] [id=33795] + 0x00000001057bab20 GCTaskThread "GC Thread#3" [stack: 0x000000016ec14000,0x000000016ee17000] [id=34051] + 0x00000001057bb320 GCTaskThread "GC Thread#4" [stack: 0x000000016ee20000,0x000000016f023000] [id=34307] + 0x000000010e195130 GCTaskThread "GC Thread#5" [stack: 0x000000016f02c000,0x000000016f22f000] [id=41987] + 0x000000011dae5a70 ConcurrentGCThread "G1 Main Marker" [stack: 0x000000016c274000,0x000000016c477000] [id=14595] + 0x000000011d9e4db0 ConcurrentGCThread "G1 Conc#0" [stack: 0x000000016c480000,0x000000016c683000] [id=12803] + 0x000000011dcc0640 ConcurrentGCThread "G1 Conc#1" [stack: 0x000000016e5f0000,0x000000016e7f3000] [id=43283] + 0x000000011c7212a0 ConcurrentGCThread "G1 Refine#0" [stack: 0x000000016c68c000,0x000000016c88f000] [id=13315] + 0x000000011c710c20 ConcurrentGCThread "G1 Service" [stack: 0x000000016c898000,0x000000016ca9b000] [id=13827] + +Threads with active compile tasks: + +VM state: not at safepoint (normal execution) + +VM Mutex/Monitor currently owned by a thread: None + +Heap address: 0x00000007e0000000, size: 512 MB, Compressed Oops mode: Zero based, Oop shift amount: 3 + +CDS archive(s) mapped at: [0x0000000800000000-0x0000000800bd8000-0x0000000800bd8000), size 12419072, SharedBaseAddress: 0x0000000800000000, ArchiveRelocationMode: 0. +Compressed class space mapped at: 0x0000000800c00000-0x0000000840c00000, reserved size: 1073741824 +Narrow klass base: 0x0000000800000000, Narrow klass shift: 0, Narrow klass range: 0x100000000 + +GC Precious Log: + CPUs: 8 total, 8 available + Memory: 16384M + Large Page Support: Disabled + NUMA Support: Disabled + Compressed Oops: Enabled (Zero based) + Heap Region Size: 1M + Heap Min Capacity: 8M + Heap Initial Capacity: 256M + Heap Max Capacity: 512M + Pre-touch: Disabled + Parallel Workers: 8 + Concurrent Workers: 2 + Concurrent Refinement Workers: 8 + Periodic GC: Disabled + +Heap: + garbage-first heap total 24576K, used 10704K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 3 young (3072K), 1 survivors (1024K) + Metaspace used 9354K, committed 9472K, reserved 1064960K + class space used 1004K, committed 1088K, reserved 1048576K + +Heap Regions: E=young(eden), S=young(survivor), O=old, HS=humongous(starts), HC=humongous(continues), CS=collection set, F=free, OA=open archive, CA=closed archive, TAMS=top-at-mark-start (previous, next) +| 0|0x00000007e0000000, 0x00000007e00b3090, 0x00000007e0100000| 69%| O| |TAMS 0x00000007e00b3090, 0x00000007e0000000| Untracked +| 1|0x00000007e0100000, 0x00000007e01ffff0, 0x00000007e0200000| 99%| O| |TAMS 0x00000007e01ffff0, 0x00000007e0100000| Untracked +| 2|0x00000007e0200000, 0x00000007e0203e20, 0x00000007e0300000| 1%| O| |TAMS 0x00000007e0203e20, 0x00000007e0200000| Complete +| 3|0x00000007e0300000, 0x00000007e0400000, 0x00000007e0400000|100%|HS| |TAMS 0x00000007e0400000, 0x00000007e0300000| Complete +| 4|0x00000007e0400000, 0x00000007e0500000, 0x00000007e0500000|100%|HS| |TAMS 0x00000007e0500000, 0x00000007e0400000| Complete +| 5|0x00000007e0500000, 0x00000007e0600000, 0x00000007e0600000|100%|HS| |TAMS 0x00000007e0600000, 0x00000007e0500000| Complete +| 6|0x00000007e0600000, 0x00000007e06c4200, 0x00000007e0700000| 76%| O| |TAMS 0x00000007e0600000, 0x00000007e0600000| Untracked +| 7|0x00000007e0700000, 0x00000007e0800000, 0x00000007e0800000|100%|HS| |TAMS 0x00000007e0700000, 0x00000007e0700000| Complete +| 8|0x00000007e0800000, 0x00000007e0800000, 0x00000007e0900000| 0%| F| |TAMS 0x00000007e0800000, 0x00000007e0800000| Untracked +| 9|0x00000007e0900000, 0x00000007e0900000, 0x00000007e0a00000| 0%| F| |TAMS 0x00000007e0900000, 0x00000007e0900000| Untracked +| 10|0x00000007e0a00000, 0x00000007e0a00000, 0x00000007e0b00000| 0%| F| |TAMS 0x00000007e0a00000, 0x00000007e0a00000| Untracked +| 11|0x00000007e0b00000, 0x00000007e0b00000, 0x00000007e0c00000| 0%| F| |TAMS 0x00000007e0b00000, 0x00000007e0b00000| Untracked +| 12|0x00000007e0c00000, 0x00000007e0c00000, 0x00000007e0d00000| 0%| F| |TAMS 0x00000007e0c00000, 0x00000007e0c00000| Untracked +| 13|0x00000007e0d00000, 0x00000007e0d00f70, 0x00000007e0e00000| 0%| S|CS|TAMS 0x00000007e0d00000, 0x00000007e0d00000| Complete +| 14|0x00000007e0e00000, 0x00000007e0e00000, 0x00000007e0f00000| 0%| F| |TAMS 0x00000007e0e00000, 0x00000007e0e00000| Untracked +| 15|0x00000007e0f00000, 0x00000007e1000000, 0x00000007e1000000|100%| E|CS|TAMS 0x00000007e0f00000, 0x00000007e0f00000| Complete +| 16|0x00000007e1000000, 0x00000007e1000000, 0x00000007e1100000| 0%| F| |TAMS 0x00000007e1000000, 0x00000007e1000000| Untracked +| 17|0x00000007e1100000, 0x00000007e1100000, 0x00000007e1200000| 0%| F| |TAMS 0x00000007e1100000, 0x00000007e1100000| Untracked +| 18|0x00000007e1200000, 0x00000007e1200000, 0x00000007e1300000| 0%| F| |TAMS 0x00000007e1200000, 0x00000007e1200000| Untracked +| 19|0x00000007e1300000, 0x00000007e136e288, 0x00000007e1400000| 43%| E| |TAMS 0x00000007e1300000, 0x00000007e1300000| Complete +| 231|0x00000007ee700000, 0x00000007ee800000, 0x00000007ee800000|100%| O| |TAMS 0x00000007ee800000, 0x00000007ee700000| Untracked +| 232|0x00000007ee800000, 0x00000007ee900000, 0x00000007ee900000|100%| O| |TAMS 0x00000007ee900000, 0x00000007ee800000| Untracked +| 510|0x00000007ffe00000, 0x00000007ffe78000, 0x00000007fff00000| 46%|OA| |TAMS 0x00000007ffe78000, 0x00000007ffe00000| Untracked +| 511|0x00000007fff00000, 0x00000007fff80000, 0x0000000800000000| 50%|CA| |TAMS 0x00000007fff80000, 0x00000007fff00000| Untracked + +Card table byte_map: [0x000000010c100000,0x000000010c200000] _byte_map_base: 0x0000000108200000 + +Marking Bits (Prev, Next): (CMBitMap*) 0x000000011f7a4410, (CMBitMap*) 0x000000011f7a4450 + Prev Bits: [0x000000010f800000, 0x0000000110000000) + Next Bits: [0x0000000118000000, 0x0000000118800000) + +Polling page: 0x000000010507c000 + +Metaspace: + +Usage: + Non-class: 8.15 MB used. + Class: 1004.40 KB used. + Both: 9.14 MB used. + +Virtual space: + Non-class space: 16.00 MB reserved, 8.19 MB ( 51%) committed, 2 nodes. + Class space: 1.00 GB reserved, 1.06 MB ( <1%) committed, 1 nodes. + Both: 1.02 GB reserved, 9.25 MB ( <1%) committed. + +Chunk freelists: + Non-Class: 3.81 MB + Class: 2.95 MB + Both: 6.77 MB + +MaxMetaspaceSize: unlimited +CompressedClassSpaceSize: 1.00 GB +Initial GC threshold: 21.00 MB +Current GC threshold: 21.00 MB +CDS: on +MetaspaceReclaimPolicy: balanced + - commit_granule_bytes: 65536. + - commit_granule_words: 8192. + - virtual_space_node_default_size: 1048576. + - enlarge_chunks_in_place: 1. + - new_chunks_are_fully_committed: 0. + - uncommit_free_chunks: 1. + - use_allocation_guard: 0. + - handle_deallocations: 1. + + +Internal statistics: + +num_allocs_failed_limit: 0. +num_arena_births: 38. +num_arena_deaths: 0. +num_vsnodes_births: 3. +num_vsnodes_deaths: 0. +num_space_committed: 148. +num_space_uncommitted: 0. +num_chunks_returned_to_freelist: 0. +num_chunks_taken_from_freelist: 163. +num_chunk_merges: 0. +num_chunk_splits: 97. +num_chunks_enlarged: 61. +num_purges: 0. +num_inconsistent_stats: 0. + +CodeHeap 'non-profiled nmethods': size=120032Kb used=697Kb max_used=697Kb free=119334Kb + bounds [0x000000014f4dc000, 0x000000014f74c000, 0x0000000156a14000] +CodeHeap 'profiled nmethods': size=120016Kb used=3427Kb max_used=3427Kb free=116588Kb + bounds [0x0000000147fa8000, 0x0000000148308000, 0x000000014f4dc000] +CodeHeap 'non-nmethods': size=5712Kb used=1180Kb max_used=1235Kb free=4531Kb + bounds [0x0000000147a14000, 0x0000000147c84000, 0x0000000147fa8000] + total_blobs=2051 nmethods=1560 adapters=408 + compilation: enabled + stopped_count=0, restarted_count=0 + full_count=0 + +Compilation events (20 events): +Event: 23.905 Thread 0x000000011b6e6a00 1552 4 java.util.concurrent.locks.AbstractQueuedSynchronizer::signalNext (34 bytes) +Event: 23.905 Thread 0x000000011b6e6a00 nmethod 1552 0x000000014f586490 code [0x000000014f586600, 0x000000014f5866b0] +Event: 23.907 Thread 0x000000011cc09200 1553 3 org.postgresql.jdbc.PgResultSet::next (259 bytes) +Event: 23.907 Thread 0x000000011b6e6a00 1554 4 org.postgresql.jdbc.PgResultSet::checkClosed (29 bytes) +Event: 23.907 Thread 0x000000010cac2200 1555 4 org.postgresql.util.internal.Nullness::castNonNull (39 bytes) +Event: 23.907 Thread 0x000000011b6e6a00 nmethod 1554 0x000000014f586790 code [0x000000014f586900, 0x000000014f5869b0] +Event: 23.907 Thread 0x000000010cac2200 nmethod 1555 0x000000014f586a90 code [0x000000014f586c00, 0x000000014f586c60] +Event: 23.907 Thread 0x000000011b6e6a00 1556 ! 4 jdk.internal.math.FloatingDecimal::readJavaFormatString (826 bytes) +Event: 23.907 Thread 0x000000010cac2200 1557 ! 4 org.postgresql.jdbc.PgResultSet::getLong (121 bytes) +Event: 23.907 Thread 0x000000011cc09200 nmethod 1553 0x00000001482ff110 code [0x00000001482ff480, 0x00000001483006a8] +Event: 23.912 Thread 0x000000010cac2200 nmethod 1557 0x000000014f586d90 code [0x000000014f587000, 0x000000014f587770] +Event: 23.912 Thread 0x000000010cac2200 1558 4 java.lang.StringLatin1::trim (76 bytes) +Event: 23.912 Thread 0x000000010cac2200 nmethod 1558 0x000000014f587d90 code [0x000000014f587f40, 0x000000014f588070] +Event: 23.916 Thread 0x000000011b6e6a00 nmethod 1556 0x000000014f588190 code [0x000000014f588440, 0x000000014f589080] +Event: 23.937 Thread 0x000000010cac2200 1559 4 java.nio.HeapByteBuffer::putLong (32 bytes) +Event: 23.937 Thread 0x000000011b6e6a00 1560 4 java.nio.HeapByteBuffer::getDouble (35 bytes) +Event: 23.937 Thread 0x000000010cac2200 nmethod 1559 0x000000014f589990 code [0x000000014f589b40, 0x000000014f589ce0] +Event: 23.937 Thread 0x000000011b6e6a00 nmethod 1560 0x000000014f589e90 code [0x000000014f58a040, 0x000000014f58a1a0] +Event: 45.448 Thread 0x000000011cc09200 1561 1 org.postgresql.core.QueryExecutorBase::isClosed (5 bytes) +Event: 45.448 Thread 0x000000011cc09200 nmethod 1561 0x000000014f58a390 code [0x000000014f58a500, 0x000000014f58a5e8] + +GC Heap History (20 events): +Event: 9.766 GC heap before +{Heap before GC invocations=8 (full 2): + garbage-first heap total 35840K, used 20680K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 9 young (9216K), 0 survivors (0K) + Metaspace used 9266K, committed 9472K, reserved 1064960K + class space used 1002K, committed 1088K, reserved 1048576K +} +Event: 9.767 GC heap after +{Heap after GC invocations=9 (full 2): + garbage-first heap total 35840K, used 21683K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 2 young (2048K), 2 survivors (2048K) + Metaspace used 9266K, committed 9472K, reserved 1064960K + class space used 1002K, committed 1088K, reserved 1048576K +} +Event: 9.861 GC heap before +{Heap before GC invocations=9 (full 2): + garbage-first heap total 35840K, used 23731K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 4 young (4096K), 2 survivors (2048K) + Metaspace used 9293K, committed 9472K, reserved 1064960K + class space used 1002K, committed 1088K, reserved 1048576K +} +Event: 9.862 GC heap after +{Heap after GC invocations=10 (full 2): + garbage-first heap total 149504K, used 21468K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 1 young (1024K), 1 survivors (1024K) + Metaspace used 9293K, committed 9472K, reserved 1064960K + class space used 1002K, committed 1088K, reserved 1048576K +} +Event: 9.862 GC heap before +{Heap before GC invocations=10 (full 2): + garbage-first heap total 149504K, used 21468K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 2 young (2048K), 1 survivors (1024K) + Metaspace used 9293K, committed 9472K, reserved 1064960K + class space used 1002K, committed 1088K, reserved 1048576K +} +Event: 9.866 GC heap after +{Heap after GC invocations=11 (full 3): + garbage-first heap total 48128K, used 12544K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 0 young (0K), 0 survivors (0K) + Metaspace used 9293K, committed 9472K, reserved 1064960K + class space used 1002K, committed 1088K, reserved 1048576K +} +Event: 9.945 GC heap before +{Heap before GC invocations=11 (full 3): + garbage-first heap total 48128K, used 13568K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 3 young (3072K), 0 survivors (0K) + Metaspace used 9305K, committed 9472K, reserved 1064960K + class space used 1002K, committed 1088K, reserved 1048576K +} +Event: 9.949 GC heap after +{Heap after GC invocations=12 (full 4): + garbage-first heap total 48128K, used 12554K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 0 young (0K), 0 survivors (0K) + Metaspace used 9305K, committed 9472K, reserved 1064960K + class space used 1002K, committed 1088K, reserved 1048576K +} +Event: 10.626 GC heap before +{Heap before GC invocations=12 (full 4): + garbage-first heap total 48128K, used 14602K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 3 young (3072K), 0 survivors (0K) + Metaspace used 9327K, committed 9472K, reserved 1064960K + class space used 1003K, committed 1088K, reserved 1048576K +} +Event: 10.630 GC heap after +{Heap after GC invocations=13 (full 5): + garbage-first heap total 20480K, used 4212K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 0 young (0K), 0 survivors (0K) + Metaspace used 9327K, committed 9472K, reserved 1064960K + class space used 1003K, committed 1088K, reserved 1048576K +} +Event: 19.612 GC heap before +{Heap before GC invocations=13 (full 5): + garbage-first heap total 20480K, used 6260K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 3 young (3072K), 0 survivors (0K) + Metaspace used 9329K, committed 9472K, reserved 1064960K + class space used 1003K, committed 1088K, reserved 1048576K +} +Event: 19.618 GC heap after +{Heap after GC invocations=14 (full 6): + garbage-first heap total 20480K, used 4145K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 0 young (0K), 0 survivors (0K) + Metaspace used 9329K, committed 9472K, reserved 1064960K + class space used 1003K, committed 1088K, reserved 1048576K +} +Event: 23.636 GC heap before +{Heap before GC invocations=14 (full 6): + garbage-first heap total 20480K, used 6193K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 3 young (3072K), 0 survivors (0K) + Metaspace used 9330K, committed 9472K, reserved 1064960K + class space used 1003K, committed 1088K, reserved 1048576K +} +Event: 23.639 GC heap after +{Heap after GC invocations=15 (full 7): + garbage-first heap total 20480K, used 4155K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 0 young (0K), 0 survivors (0K) + Metaspace used 9330K, committed 9472K, reserved 1064960K + class space used 1003K, committed 1088K, reserved 1048576K +} +Event: 23.871 GC heap before +{Heap before GC invocations=15 (full 7): + garbage-first heap total 20480K, used 8251K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 3 young (3072K), 0 survivors (0K) + Metaspace used 9330K, committed 9472K, reserved 1064960K + class space used 1003K, committed 1088K, reserved 1048576K +} +Event: 23.876 GC heap after +{Heap after GC invocations=16 (full 8): + garbage-first heap total 20480K, used 4795K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 0 young (0K), 0 survivors (0K) + Metaspace used 9330K, committed 9472K, reserved 1064960K + class space used 1003K, committed 1088K, reserved 1048576K +} +Event: 23.876 GC heap before +{Heap before GC invocations=16 (full 8): + garbage-first heap total 20480K, used 6843K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 1 young (1024K), 0 survivors (0K) + Metaspace used 9330K, committed 9472K, reserved 1064960K + class space used 1003K, committed 1088K, reserved 1048576K +} +Event: 23.876 GC heap after +{Heap after GC invocations=17 (full 8): + garbage-first heap total 20480K, used 7617K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 1 young (1024K), 1 survivors (1024K) + Metaspace used 9330K, committed 9472K, reserved 1064960K + class space used 1003K, committed 1088K, reserved 1048576K +} +Event: 23.876 GC heap before +{Heap before GC invocations=17 (full 8): + garbage-first heap total 20480K, used 8641K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 2 young (2048K), 1 survivors (1024K) + Metaspace used 9330K, committed 9472K, reserved 1064960K + class space used 1003K, committed 1088K, reserved 1048576K +} +Event: 23.877 GC heap after +{Heap after GC invocations=18 (full 8): + garbage-first heap total 20480K, used 8656K [0x00000007e0000000, 0x0000000800000000) + region size 1024K, 1 young (1024K), 1 survivors (1024K) + Metaspace used 9330K, committed 9472K, reserved 1064960K + class space used 1003K, committed 1088K, reserved 1048576K +} + +Dll operation events (8 events): +Event: 0.004 Loaded shared library /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libjava.dylib +Event: 0.025 Loaded shared library /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libnio.dylib +Event: 0.026 Loaded shared library /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libzip.dylib +Event: 3.973 Loaded shared library /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libjimage.dylib +Event: 4.013 Loaded shared library /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libnet.dylib +Event: 4.076 Loaded shared library /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libextnet.dylib +Event: 4.083 Loaded shared library /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libmanagement.dylib +Event: 4.084 Loaded shared library /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libmanagement_ext.dylib + +Deoptimization events (20 events): +Event: 9.898 Thread 0x000000011e307600 DEOPT PACKING pc=0x00000001481e45fc sp=0x000000016bc2a950 +Event: 9.898 Thread 0x000000011e307600 DEOPT UNPACKING pc=0x0000000147a52b7c sp=0x000000016bc2a6c0 mode 0 +Event: 9.949 Thread 0x000000011e307600 DEOPT PACKING pc=0x0000000148287a14 sp=0x000000016bc1e4c0 +Event: 9.949 Thread 0x000000011e307600 DEOPT UNPACKING pc=0x0000000147a52b7c sp=0x000000016bc1e160 mode 0 +Event: 10.061 Thread 0x000000011e307600 Uncommon trap: trap_request=0xffffff45 fr.pc=0x000000014f556890 relative=0x0000000000000390 +Event: 10.061 Thread 0x000000011e307600 Uncommon trap: reason=unstable_if action=reinterpret pc=0x000000014f556890 method=java.nio.Buffer.(IIIILjdk/internal/access/foreign/MemorySegmentProxy;)V @ 50 c2 +Event: 10.061 Thread 0x000000011e307600 DEOPT PACKING pc=0x000000014f556890 sp=0x000000016bc2bc10 +Event: 10.061 Thread 0x000000011e307600 DEOPT UNPACKING pc=0x0000000147a52d1c sp=0x000000016bc2baf0 mode 2 +Event: 10.162 Thread 0x000000011e307600 DEOPT PACKING pc=0x00000001481a215c sp=0x000000016bc2c0c0 +Event: 10.162 Thread 0x000000011e307600 DEOPT UNPACKING pc=0x0000000147a52b7c sp=0x000000016bc2bd60 mode 0 +Event: 10.281 Thread 0x000000011e307600 Uncommon trap: trap_request=0xffffffde fr.pc=0x000000014f540b04 relative=0x0000000000000184 +Event: 10.281 Thread 0x000000011e307600 Uncommon trap: reason=class_check action=maybe_recompile pc=0x000000014f540b04 method=java.util.regex.Pattern$BmpCharProperty.match(Ljava/util/regex/Matcher;ILjava/lang/CharSequence;)Z @ 19 c2 +Event: 10.281 Thread 0x000000011e307600 DEOPT PACKING pc=0x000000014f540b04 sp=0x000000016bc2cd00 +Event: 10.281 Thread 0x000000011e307600 DEOPT UNPACKING pc=0x0000000147a52d1c sp=0x000000016bc2cc90 mode 2 +Event: 10.281 Thread 0x000000011e307600 Uncommon trap: trap_request=0xffffffde fr.pc=0x000000014f540b04 relative=0x0000000000000184 +Event: 10.281 Thread 0x000000011e307600 Uncommon trap: reason=class_check action=maybe_recompile pc=0x000000014f540b04 method=java.util.regex.Pattern$BmpCharProperty.match(Ljava/util/regex/Matcher;ILjava/lang/CharSequence;)Z @ 19 c2 +Event: 10.281 Thread 0x000000011e307600 DEOPT PACKING pc=0x000000014f540b04 sp=0x000000016bc2cd00 +Event: 10.281 Thread 0x000000011e307600 DEOPT UNPACKING pc=0x0000000147a52d1c sp=0x000000016bc2cc90 mode 2 +Event: 23.883 Thread 0x000000011e307600 DEOPT PACKING pc=0x0000000148297d44 sp=0x000000016bc2be30 +Event: 23.883 Thread 0x000000011e307600 DEOPT UNPACKING pc=0x0000000147a52b7c sp=0x000000016bc2bb40 mode 3 + +Classes unloaded (0 events): +No events + +Classes redefined (0 events): +No events + +Internal exceptions (20 events): +Event: 8.723 Thread 0x000000011e307600 Exception (0x00000007efb25268) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 8.723 Thread 0x000000011e307600 Exception (0x00000007efb258d8) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 8.723 Thread 0x000000011e307600 Exception (0x00000007efb25f48) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 8.723 Thread 0x000000011e307600 Exception (0x00000007efb26618) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 8.723 Thread 0x000000011e307600 Exception (0x00000007efb26c88) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 8.723 Thread 0x000000011e307600 Exception (0x00000007efb272f8) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 8.723 Thread 0x000000011e307600 Exception (0x00000007efb279c8) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 10.062 Thread 0x000000011e307600 Exception (0x00000007e2afcc10) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 10.062 Thread 0x000000011e307600 Exception (0x00000007e2afd2e0) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 10.062 Thread 0x000000011e307600 Exception (0x00000007e2afd950) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 10.062 Thread 0x000000011e307600 Exception (0x00000007e2afe020) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 10.062 Thread 0x000000011e307600 Exception (0x00000007e2afe690) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 10.062 Thread 0x000000011e307600 Exception (0x00000007e2afed00) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 10.063 Thread 0x000000011e307600 Exception (0x00000007e2aff3d0) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 10.063 Thread 0x000000011e307600 Exception (0x00000007e2affa40) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 10.063 Thread 0x000000011e307600 Exception (0x00000007e2961388) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 10.063 Thread 0x000000011e307600 Exception (0x00000007e2961a58) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 10.063 Thread 0x000000011e307600 Exception (0x00000007e29620c8) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 10.063 Thread 0x000000011e307600 Exception (0x00000007e2962738) +thrown [src/hotspot/share/prims/jni.cpp, line 516] +Event: 10.063 Thread 0x000000011e307600 Exception (0x00000007e2962e08) +thrown [src/hotspot/share/prims/jni.cpp, line 516] + +VM Operations (20 events): +Event: 9.945 Executing VM operation: G1CollectFull +Event: 9.949 Executing VM operation: G1CollectFull done +Event: 10.626 Executing VM operation: G1CollectFull +Event: 10.630 Executing VM operation: G1CollectFull done +Event: 19.612 Executing VM operation: G1CollectFull +Event: 19.618 Executing VM operation: G1CollectFull done +Event: 23.632 Executing VM operation: Cleanup +Event: 23.632 Executing VM operation: Cleanup done +Event: 23.636 Executing VM operation: G1CollectFull +Event: 23.639 Executing VM operation: G1CollectFull done +Event: 23.871 Executing VM operation: G1CollectFull +Event: 23.876 Executing VM operation: G1CollectFull done +Event: 23.876 Executing VM operation: G1TryInitiateConcMark +Event: 23.876 Executing VM operation: G1TryInitiateConcMark done +Event: 23.876 Executing VM operation: G1TryInitiateConcMark +Event: 23.877 Executing VM operation: G1TryInitiateConcMark done +Event: 23.879 Executing VM operation: G1Concurrent +Event: 23.880 Executing VM operation: G1Concurrent done +Event: 23.881 Executing VM operation: G1Concurrent +Event: 23.881 Executing VM operation: G1Concurrent done + +Events (20 events): +Event: 8.863 loading class java/util/concurrent/atomic/AtomicReferenceFieldUpdater +Event: 8.863 loading class java/util/concurrent/atomic/AtomicReferenceFieldUpdater done +Event: 8.863 loading class java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl +Event: 8.863 loading class java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl done +Event: 8.863 loading class java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl$1 +Event: 8.863 loading class java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl$1 done +Event: 8.863 loading class sun/reflect/misc/ReflectUtil +Event: 8.863 loading class sun/reflect/misc/ReflectUtil done +Event: 8.882 loading class java/io/CharArrayReader +Event: 8.882 loading class java/io/CharArrayReader done +Event: 8.882 loading class java/net/UnknownHostException +Event: 8.882 loading class java/net/UnknownHostException done +Event: 9.638 loading class jdk/internal/access/foreign/MemorySegmentProxy +Event: 9.638 loading class jdk/internal/access/foreign/MemorySegmentProxy done +Event: 23.883 Thread 0x000000011b6e6a00 Thread added: 0x000000011b6e6a00 +Event: 23.883 Protecting memory [0x000000016facc000,0x000000016fad8000] with protection modes 0 +Event: 23.905 loading class java/util/concurrent/locks/AbstractQueuedSynchronizer$Node +Event: 23.905 loading class java/util/concurrent/locks/AbstractQueuedSynchronizer$Node done +Event: 28.942 Protecting memory [0x000000016facc000,0x000000016fad8000] with protection modes 3 +Event: 28.943 Thread 0x000000011b6e6a00 Thread exited: 0x000000011b6e6a00 + + +Dynamic libraries: +0x0000000104170000 /Applications/RStudio.app/Contents/Resources/app/bin/rsession-arm64 +0x0000000105584000 /Applications/RStudio.app/Contents/Resources/app/Frameworks/arm64/libssl.3.dylib +0x0000000106184000 /Applications/RStudio.app/Contents/Resources/app/Frameworks/arm64/libcrypto.3.dylib +0x000000019069e000 /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit +0x00000001919db000 /System/Library/PrivateFrameworks/UIFoundation.framework/Versions/A/UIFoundation +0x00000002285bb000 /System/Library/PrivateFrameworks/CollectionViewCore.framework/Versions/A/CollectionViewCore +0x00000001a0c91000 /System/Library/PrivateFrameworks/RemoteViewServices.framework/Versions/A/RemoteViewServices +0x00000001978c5000 /System/Library/PrivateFrameworks/XCTTargetBootstrap.framework/Versions/A/XCTTargetBootstrap +0x000000019c054000 /System/Library/PrivateFrameworks/InternationalSupport.framework/Versions/A/InternationalSupport +0x000000019c0a8000 /System/Library/PrivateFrameworks/UserActivity.framework/Versions/A/UserActivity +0x000000024ca12000 /System/Library/PrivateFrameworks/WindowManagement.framework/Versions/A/WindowManagement +0x000000018dbd1000 /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration +0x000000019b4c2000 /usr/lib/libspindump.dylib +0x0000000191b90000 /System/Library/Frameworks/UniformTypeIdentifiers.framework/Versions/A/UniformTypeIdentifiers +0x000000019573c000 /usr/lib/libapp_launch_measurement.dylib +0x0000000194b62000 /System/Library/PrivateFrameworks/CoreAnalytics.framework/Versions/A/CoreAnalytics +0x0000000195743000 /System/Library/PrivateFrameworks/CoreAutoLayout.framework/Versions/A/CoreAutoLayout +0x000000019370a000 /System/Library/Frameworks/CoreData.framework/Versions/A/CoreData +0x00000001970e5000 /System/Library/Frameworks/Metal.framework/Versions/A/Metal +0x000000019806d000 /usr/lib/liblangid.dylib +0x00000001978cb000 /System/Library/PrivateFrameworks/CoreSVG.framework/Versions/A/CoreSVG +0x0000000192555000 /System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/SkyLight +0x00000001929f6000 /System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics +0x00000001a136b000 /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate +0x000000019b31c000 /System/Library/PrivateFrameworks/IconServices.framework/Versions/A/IconServices +0x00000001970c3000 /System/Library/Frameworks/IOSurface.framework/Versions/A/IOSurface +0x0000000194b91000 /usr/lib/libDiagnosticMessagesClient.dylib +0x000000019995a000 /usr/lib/libz.1.dylib +0x00000001a4b10000 /System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices +0x00000001978ad000 /System/Library/PrivateFrameworks/DFRFoundation.framework/Versions/A/DFRFoundation +0x000000018fef8000 /usr/lib/libicucore.A.dylib +0x000000019d0b2000 /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox +0x000000019c063000 /System/Library/PrivateFrameworks/DataDetectorsCore.framework/Versions/A/DataDetectorsCore +0x00000001b5ad6000 /System/Library/PrivateFrameworks/TextInput.framework/Versions/A/TextInput +0x000000018df51000 /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation +0x00000001924a6000 /usr/lib/libMobileGestalt.dylib +0x00000001975e9000 /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox +0x0000000195068000 /System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore +0x000000018fb25000 /System/Library/Frameworks/Security.framework/Versions/A/Security +0x00000001a0cd1000 /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SpeechRecognition.framework/Versions/A/SpeechRecognition +0x000000019546a000 /System/Library/PrivateFrameworks/CoreUI.framework/Versions/A/CoreUI +0x000000018f41e000 /System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio +0x0000000194c75000 /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration +0x000000019b91e000 /System/Library/PrivateFrameworks/MultitouchSupport.framework/Versions/A/MultitouchSupport +0x00000001924a4000 /usr/lib/libenergytrace.dylib +0x00000001ab1cf000 /System/Library/PrivateFrameworks/RenderBox.framework/Versions/A/RenderBox +0x0000000190552000 /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit +0x00000001a10a6000 /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices +0x00000001956c8000 /System/Library/PrivateFrameworks/PerformanceAnalysis.framework/Versions/A/PerformanceAnalysis +0x00000001e3a7b000 /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL +0x000000019578d000 /usr/lib/libxml2.2.dylib +0x0000000198d9c000 /System/Library/PrivateFrameworks/MobileKeyBag.framework/Versions/A/MobileKeyBag +0x000000018c9bc000 /usr/lib/libobjc.A.dylib +0x000000018ccb0000 /usr/lib/libc++.1.dylib +0x0000000199a18000 /usr/lib/libSystem.B.dylib +0x00000001a1023000 /System/Library/Frameworks/Accessibility.framework/Versions/A/Accessibility +0x00000001930d6000 /System/Library/Frameworks/ColorSync.framework/Versions/A/ColorSync +0x000000018cdfc000 /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation +0x0000000197c28000 /System/Library/Frameworks/CoreImage.framework/Versions/A/CoreImage +0x000000018f229000 /System/Library/Frameworks/CoreText.framework/Versions/A/CoreText +0x00000001e82da000 /System/Library/Frameworks/CoreTransferable.framework/Versions/A/CoreTransferable +0x00000001e879f000 /System/Library/Frameworks/DeveloperToolsSupport.framework/Versions/A/DeveloperToolsSupport +0x0000000197906000 /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO +0x000000022275b000 /System/Library/Frameworks/Symbols.framework/Versions/A/Symbols +0x0000000199a1e000 /System/Library/PrivateFrameworks/SoftLinking.framework/Versions/A/SoftLinking +0x000000019ca64000 /usr/lib/swift/libswiftCore.dylib +0x00000001b2763000 /usr/lib/swift/libswiftCoreFoundation.dylib +0x00000001b01cc000 /usr/lib/swift/libswiftCoreGraphics.dylib +0x00000001b27ad000 /usr/lib/swift/libswiftCoreImage.dylib +0x00000001b01d3000 /usr/lib/swift/libswiftDarwin.dylib +0x00000001a2716000 /usr/lib/swift/libswiftDispatch.dylib +0x00000001b27ae000 /usr/lib/swift/libswiftIOKit.dylib +0x00000001be208000 /usr/lib/swift/libswiftMetal.dylib +0x00000001cb8cd000 /usr/lib/swift/libswiftOSLog.dylib +0x00000001a4f8b000 /usr/lib/swift/libswiftObjectiveC.dylib +0x00000001c293c000 /usr/lib/swift/libswiftQuartzCore.dylib +0x00000001c6a41000 /usr/lib/swift/libswiftUniformTypeIdentifiers.dylib +0x00000001b2775000 /usr/lib/swift/libswiftXPC.dylib +0x0000000254eb9000 /usr/lib/swift/libswift_Concurrency.dylib +0x00000001a4f8f000 /usr/lib/swift/libswiftos.dylib +0x00000001b5a3a000 /usr/lib/swift/libswiftsimd.dylib +0x0000000199bcd000 /usr/lib/libcompression.dylib +0x000000019bfae000 /System/Library/PrivateFrameworks/TextureIO.framework/Versions/A/TextureIO +0x000000019afc8000 /usr/lib/libate.dylib +0x0000000199a12000 /usr/lib/system/libcache.dylib +0x00000001999cc000 /usr/lib/system/libcommonCrypto.dylib +0x00000001999f8000 /usr/lib/system/libcompiler_rt.dylib +0x00000001999ee000 /usr/lib/system/libcopyfile.dylib +0x000000018cb00000 /usr/lib/system/libcorecrypto.dylib +0x000000018cbe6000 /usr/lib/system/libdispatch.dylib +0x000000018cda1000 /usr/lib/system/libdyld.dylib +0x0000000199a08000 /usr/lib/system/libkeymgr.dylib +0x00000001999a4000 /usr/lib/system/libmacho.dylib +0x0000000198e84000 /usr/lib/system/libquarantine.dylib +0x0000000199a05000 /usr/lib/system/libremovefile.dylib +0x000000019251c000 /usr/lib/system/libsystem_asl.dylib +0x000000018ca95000 /usr/lib/system/libsystem_blocks.dylib +0x000000018cc31000 /usr/lib/system/libsystem_c.dylib +0x00000001999fc000 /usr/lib/system/libsystem_collections.dylib +0x000000019805c000 /usr/lib/system/libsystem_configuration.dylib +0x0000000197098000 /usr/lib/system/libsystem_containermanager.dylib +0x000000019963b000 /usr/lib/system/libsystem_coreservices.dylib +0x00000001901bf000 /usr/lib/system/libsystem_darwin.dylib +0x0000000255206000 /usr/lib/system/libsystem_darwindirectory.dylib +0x0000000199a09000 /usr/lib/system/libsystem_dnssd.dylib +0x000000025520a000 /usr/lib/system/libsystem_eligibility.dylib +0x000000018cc2e000 /usr/lib/system/libsystem_featureflags.dylib +0x000000018cdcf000 /usr/lib/system/libsystem_info.dylib +0x0000000199969000 /usr/lib/system/libsystem_m.dylib +0x000000018cba9000 /usr/lib/system/libsystem_malloc.dylib +0x0000000192489000 /usr/lib/system/libsystem_networkextension.dylib +0x0000000190635000 /usr/lib/system/libsystem_notify.dylib +0x0000000198061000 /usr/lib/system/libsystem_sandbox.dylib +0x000000025520e000 /usr/lib/system/libsystem_sanitizers.dylib +0x0000000199a01000 /usr/lib/system/libsystem_secinit.dylib +0x000000018cd59000 /usr/lib/system/libsystem_kernel.dylib +0x000000018cdc7000 /usr/lib/system/libsystem_platform.dylib +0x000000018cd94000 /usr/lib/system/libsystem_pthread.dylib +0x0000000193f0c000 /usr/lib/system/libsystem_symptoms.dylib +0x000000018cae5000 /usr/lib/system/libsystem_trace.dylib +0x00000001999da000 /usr/lib/system/libunwind.dylib +0x000000018ca9a000 /usr/lib/system/libxpc.dylib +0x000000018cd3d000 /usr/lib/libc++abi.dylib +0x00000001999e6000 /usr/lib/liboah.dylib +0x000000019ae74000 /usr/lib/liblzma.5.dylib +0x0000000199a1a000 /usr/lib/libfakelink.dylib +0x00000001920b5000 /System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork +0x0000000199a6e000 /usr/lib/libarchive.2.dylib +0x000000019efa4000 /System/Library/Frameworks/Combine.framework/Versions/A/Combine +0x00000002285cf000 /System/Library/PrivateFrameworks/CollectionsInternal.framework/Versions/A/CollectionsInternal +0x000000023ef7f000 /System/Library/PrivateFrameworks/ReflectionInternal.framework/Versions/A/ReflectionInternal +0x000000023f511000 /System/Library/PrivateFrameworks/RuntimeInternal.framework/Versions/A/RuntimeInternal +0x000000025500d000 /usr/lib/swift/libswift_StringProcessing.dylib +0x00000001904d0000 /System/Library/PrivateFrameworks/CoreServicesInternal.framework/Versions/A/CoreServicesInternal +0x0000000198eab000 /usr/lib/libbsm.0.dylib +0x00000001999ac000 /usr/lib/system/libkxld.dylib +0x0000000195704000 /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/FSEvents.framework/Versions/A/FSEvents +0x00000001901ca000 /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore +0x0000000194bda000 /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata +0x0000000199641000 /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices +0x0000000199af7000 /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit +0x0000000193e8d000 /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE +0x000000018d2d5000 /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices +0x000000019ae1d000 /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/DictionaryServices.framework/Versions/A/DictionaryServices +0x0000000195711000 /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SharedFileList.framework/Versions/A/SharedFileList +0x0000000199b97000 /usr/lib/libapple_nghttp2.dylib +0x0000000193b01000 /usr/lib/libsqlite3.dylib +0x0000000193f15000 /System/Library/Frameworks/Network.framework/Versions/A/Network +0x00000002538ca000 /usr/lib/libCoreEntitlements.dylib +0x0000000239e89000 /System/Library/PrivateFrameworks/MessageSecurity.framework/Versions/A/MessageSecurity +0x0000000193ae7000 /System/Library/PrivateFrameworks/ProtocolBuffer.framework/Versions/A/ProtocolBuffer +0x000000019956a000 /System/Library/PrivateFrameworks/AppleFSCompression.framework/Versions/A/AppleFSCompression +0x0000000198e93000 /usr/lib/libcoretls.dylib +0x000000019ae93000 /usr/lib/libcoretls_cfhelpers.dylib +0x0000000199bc7000 /usr/lib/libpam.2.dylib +0x000000019af05000 /usr/lib/libxar.1.dylib +0x000000019b2f3000 /usr/lib/libheimdal-asn1.dylib +0x00000001920b4000 /usr/lib/libnetwork.dylib +0x0000000199a1f000 /usr/lib/libpcap.A.dylib +0x0000000193f01000 /usr/lib/libdns_services.dylib +0x0000000198069000 /System/Library/PrivateFrameworks/AppleSystemInfo.framework/Versions/A/AppleSystemInfo +0x0000000198b91000 /System/Library/PrivateFrameworks/IOMobileFramebuffer.framework/Versions/A/IOMobileFramebuffer +0x0000000254f64000 /usr/lib/swift/libswift_RegexParser.dylib +0x000000019962e000 /usr/lib/libbz2.1.0.dylib +0x0000000198e87000 /usr/lib/libCheckFix.dylib +0x0000000192534000 /System/Library/PrivateFrameworks/TCC.framework/Versions/A/TCC +0x000000019806f000 /System/Library/PrivateFrameworks/CoreNLP.framework/Versions/A/CoreNLP +0x0000000194b93000 /System/Library/PrivateFrameworks/MetadataUtilities.framework/Versions/A/MetadataUtilities +0x0000000198ebd000 /usr/lib/libmecab.dylib +0x000000018dc65000 /usr/lib/libCRFSuite.dylib +0x0000000198f19000 /usr/lib/libgermantok.dylib +0x0000000199b6e000 /usr/lib/libThaiTokenizer.dylib +0x0000000194c7e000 /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage +0x00000001a107d000 /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib +0x000000019af4c000 /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib +0x0000000198a6c000 /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib +0x000000018d6dc000 /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib +0x0000000199ca2000 /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib +0x0000000198f1c000 /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLinearAlgebra.dylib +0x0000000199bb2000 /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libSparseBLAS.dylib +0x0000000199c9d000 /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libQuadrature.dylib +0x0000000198198000 /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBNNS.dylib +0x000000018db6a000 /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libSparse.dylib +0x00000002385d8000 /System/Library/PrivateFrameworks/MIL.framework/Versions/A/MIL +0x0000000199a55000 /usr/lib/libiconv.2.dylib +0x00000001999a0000 /usr/lib/libcharset.1.dylib +0x00000001956e4000 /System/Library/Frameworks/OpenDirectory.framework/Versions/A/Frameworks/CFOpenDirectory.framework/Versions/A/CFOpenDirectory +0x00000001956d4000 /System/Library/Frameworks/OpenDirectory.framework/Versions/A/OpenDirectory +0x000000019ae95000 /System/Library/PrivateFrameworks/APFS.framework/Versions/A/APFS +0x0000000198dc3000 /System/Library/Frameworks/SecurityFoundation.framework/Versions/A/SecurityFoundation +0x000000019af14000 /usr/lib/libutil.dylib +0x0000000236739000 /System/Library/PrivateFrameworks/InstalledContentLibrary.framework/Versions/A/InstalledContentLibrary +0x0000000190511000 /System/Library/PrivateFrameworks/CoreServicesStore.framework/Versions/A/CoreServicesStore +0x0000000225d7c000 /System/Library/PrivateFrameworks/AppleMobileFileIntegrity.framework/Versions/A/AppleMobileFileIntegrity +0x00000001b2731000 /usr/lib/libmis.dylib +0x00000001c2e23000 /System/Library/PrivateFrameworks/MobileSystemServices.framework/Versions/A/MobileSystemServices +0x00000001e0e85000 /System/Library/PrivateFrameworks/ConfigProfileHelper.framework/Versions/A/ConfigProfileHelper +0x0000000199b70000 /System/Library/PrivateFrameworks/AppleSauce.framework/Versions/A/AppleSauce +0x000000018ebaf000 /System/Library/PrivateFrameworks/LanguageModeling.framework/Versions/A/LanguageModeling +0x000000019af18000 /usr/lib/libxslt.1.dylib +0x0000000199a5c000 /usr/lib/libcmph.dylib +0x0000000198b5d000 /System/Library/PrivateFrameworks/CoreEmoji.framework/Versions/A/CoreEmoji +0x0000000198192000 /System/Library/PrivateFrameworks/LinguisticData.framework/Versions/A/LinguisticData +0x000000018da78000 /System/Library/PrivateFrameworks/Lexicon.framework/Versions/A/Lexicon +0x0000000198e51000 /System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Versions/A/BackgroundTaskManagement +0x0000000253ab4000 /usr/lib/libTLE.dylib +0x000000019b7e4000 /System/Library/PrivateFrameworks/AppleJPEG.framework/Versions/A/AppleJPEG +0x000000019b2d8000 /usr/lib/libexpat.1.dylib +0x000000019be0c000 /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib +0x000000019be37000 /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib +0x000000019bf22000 /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib +0x000000019b82a000 /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJP2.dylib +0x000000019bec7000 /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib +0x000000019bebe000 /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libRadiance.dylib +0x0000000197484000 /System/Library/PrivateFrameworks/FontServices.framework/libFontParser.dylib +0x0000000193e26000 /System/Library/PrivateFrameworks/RunningBoardServices.framework/Versions/A/RunningBoardServices +0x00000001a79d1000 /System/Library/PrivateFrameworks/IOSurfaceAccelerator.framework/Versions/A/IOSurfaceAccelerator +0x000000019b91a000 /System/Library/PrivateFrameworks/WatchdogClient.framework/Versions/A/WatchdogClient +0x000000018ed95000 /System/Library/Frameworks/CoreDisplay.framework/Versions/A/CoreDisplay +0x000000019733b000 /System/Library/Frameworks/CoreMedia.framework/Versions/A/CoreMedia +0x00000001970db000 /System/Library/PrivateFrameworks/IOAccelerator.framework/Versions/A/IOAccelerator +0x0000000195877000 /System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo +0x0000000199bc5000 /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/MetalPerformanceShaders +0x000000019b95d000 /System/Library/Frameworks/VideoToolbox.framework/Versions/A/VideoToolbox +0x0000000195913000 /System/Library/PrivateFrameworks/UserManagement.framework/Versions/A/UserManagement +0x0000000193d4d000 /System/Library/PrivateFrameworks/BaseBoard.framework/Versions/A/BaseBoard +0x0000000198067000 /System/Library/PrivateFrameworks/AggregateDictionary.framework/Versions/A/AggregateDictionary +0x0000000225bb6000 /System/Library/PrivateFrameworks/AppleKeyStore.framework/Versions/A/AppleKeyStore +0x000000019beb9000 /System/Library/PrivateFrameworks/GPUWrangler.framework/Versions/A/GPUWrangler +0x000000019be99000 /System/Library/PrivateFrameworks/IOPresentment.framework/Versions/A/IOPresentment +0x000000019bec1000 /System/Library/PrivateFrameworks/DSExternalDisplay.framework/Versions/A/DSExternalDisplay +0x00000002327c6000 /System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/libllvm-flatbuffers.dylib +0x00000001e3a6e000 /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreFSCache.dylib +0x000000022f42a000 /System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/libGPUCompilerUtils.dylib +0x000000019bf28000 /System/Library/PrivateFrameworks/CMCaptureCore.framework/Versions/A/CMCaptureCore +0x00000001e88c2000 /System/Library/Frameworks/ExtensionFoundation.framework/Versions/A/ExtensionFoundation +0x00000001a2f7f000 /System/Library/PrivateFrameworks/CoreTime.framework/Versions/A/CoreTime +0x000000019b4ac000 /System/Library/PrivateFrameworks/AppServerSupport.framework/Versions/A/AppServerSupport +0x000000019da40000 /System/Library/PrivateFrameworks/perfdata.framework/Versions/A/perfdata +0x000000018eeb9000 /System/Library/PrivateFrameworks/AudioToolboxCore.framework/Versions/A/AudioToolboxCore +0x0000000197311000 /System/Library/PrivateFrameworks/caulk.framework/Versions/A/caulk +0x000000019d2ae000 /usr/lib/libAudioStatistics.dylib +0x00000001b1a6a000 /System/Library/PrivateFrameworks/SystemPolicy.framework/Versions/A/SystemPolicy +0x000000019d587000 /usr/lib/libSMC.dylib +0x00000001a6f79000 /System/Library/Frameworks/CoreMIDI.framework/Versions/A/CoreMIDI +0x000000019bdd3000 /usr/lib/libAudioToolboxUtility.dylib +0x00000001ace6b000 /System/Library/PrivateFrameworks/OSAServicesClient.framework/Versions/A/OSAServicesClient +0x000000019da4e000 /usr/lib/libperfcheck.dylib +0x00000001a2a36000 /System/Library/PrivateFrameworks/BoardServices.framework/Versions/A/BoardServices +0x000000019b1c0000 /System/Library/PrivateFrameworks/PlugInKit.framework/Versions/A/PlugInKit +0x0000000198db5000 /System/Library/PrivateFrameworks/AssertionServices.framework/Versions/A/AssertionServices +0x00000001a608a000 /System/Library/PrivateFrameworks/ASEProcessing.framework/Versions/A/ASEProcessing +0x00000001ced54000 /System/Library/PrivateFrameworks/Symbolication.framework/Versions/A/Symbolication +0x000000023dd6c000 /System/Library/PrivateFrameworks/PhotosensitivityProcessing.framework/Versions/A/PhotosensitivityProcessing +0x000000019b45d000 /System/Library/PrivateFrameworks/GraphVisualizer.framework/Versions/A/GraphVisualizer +0x00000001e3ad0000 /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib +0x00000001e3a8f000 /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGFXShared.dylib +0x00000001e3c68000 /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib +0x00000001e3a98000 /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLImage.dylib +0x00000001e3a8c000 /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCVMSPluginSupport.dylib +0x0000000253a6c000 /usr/lib/libRosetta.dylib +0x00000001e3a75000 /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreVMClient.dylib +0x000000022d630000 /System/Library/PrivateFrameworks/FontServices.framework/Versions/A/FontServices +0x000000019b469000 /System/Library/PrivateFrameworks/OTSVG.framework/Versions/A/OTSVG +0x0000000195418000 /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontRegistry.dylib +0x000000019b4b7000 /System/Library/PrivateFrameworks/FontServices.framework/libhvf.dylib +0x000000022d631000 /System/Library/PrivateFrameworks/FontServices.framework/libXTFontStaticRegistryData.dylib +0x0000000197fae000 /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSCore.framework/Versions/A/MPSCore +0x00000001994d8000 /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSImage.framework/Versions/A/MPSImage +0x0000000198f31000 /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSNeuralNetwork.framework/Versions/A/MPSNeuralNetwork +0x000000019937c000 /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSMatrix.framework/Versions/A/MPSMatrix +0x0000000199187000 /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSRayIntersector.framework/Versions/A/MPSRayIntersector +0x00000001993ae000 /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSNDArray.framework/Versions/A/MPSNDArray +0x00000001ea19c000 /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSFunctions.framework/Versions/A/MPSFunctions +0x00000001ea181000 /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSBenchmarkLoop.framework/Versions/A/MPSBenchmarkLoop +0x000000018d590000 /System/Library/PrivateFrameworks/MetalTools.framework/Versions/A/MetalTools +0x00000001b6c13000 /System/Library/PrivateFrameworks/IOAccelMemoryInfo.framework/Versions/A/IOAccelMemoryInfo +0x00000001c2d1c000 /System/Library/PrivateFrameworks/kperf.framework/Versions/A/kperf +0x00000001b2756000 /System/Library/PrivateFrameworks/GPURawCounter.framework/Versions/A/GPURawCounter +0x00000001a2e51000 /System/Library/PrivateFrameworks/CoreSymbolication.framework/Versions/A/CoreSymbolication +0x00000001b2702000 /System/Library/PrivateFrameworks/MallocStackLogging.framework/Versions/A/MallocStackLogging +0x000000019b062000 /System/Library/PrivateFrameworks/CrashReporterSupport.framework/Versions/A/CrashReporterSupport +0x00000001a2e0c000 /System/Library/PrivateFrameworks/DebugSymbols.framework/Versions/A/DebugSymbols +0x00000001c1683000 /System/Library/PrivateFrameworks/OSAnalytics.framework/Versions/A/OSAnalytics +0x000000024ac65000 /System/Library/PrivateFrameworks/VideoToolboxParavirtualizationSupport.framework/Versions/A/VideoToolboxParavirtualizationSupport +0x000000019b28c000 /System/Library/PrivateFrameworks/AppleVA.framework/Versions/A/AppleVA +0x000000019d2f6000 /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS +0x0000000193285000 /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices +0x000000019bf36000 /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore +0x000000019d6e0000 /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD +0x000000019d6d4000 /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSyncLegacy.framework/Versions/A/ColorSyncLegacy +0x000000019d2c6000 /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis +0x000000019bef2000 /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATSUI.framework/Versions/A/ATSUI +0x000000019d667000 /usr/lib/libcups.2.dylib +0x000000019da5c000 /System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos +0x000000019da6d000 /System/Library/Frameworks/GSS.framework/Versions/A/GSS +0x000000019d375000 /usr/lib/libresolv.9.dylib +0x000000019b4c8000 /System/Library/PrivateFrameworks/Heimdal.framework/Versions/A/Heimdal +0x00000001a4ef8000 /System/Library/Frameworks/Kerberos.framework/Versions/A/Libraries/libHeimdalProxy.dylib +0x000000019dac7000 /System/Library/PrivateFrameworks/CommonAuth.framework/Versions/A/CommonAuth +0x00000001e76a8000 /System/Library/Frameworks/AVFAudio.framework/Versions/A/AVFAudio +0x00000001aceba000 /System/Library/PrivateFrameworks/AXCoreUtilities.framework/Versions/A/AXCoreUtilities +0x0000000237cb0000 /System/Library/PrivateFrameworks/IsolatedCoreAudioClient.framework/Versions/A/IsolatedCoreAudioClient +0x000000019d232000 /System/Library/PrivateFrameworks/AudioSession.framework/Versions/A/AudioSession +0x000000019ed43000 /System/Library/Frameworks/IOBluetooth.framework/Versions/A/IOBluetooth +0x000000019b397000 /System/Library/PrivateFrameworks/MediaExperience.framework/Versions/A/MediaExperience +0x000000019d071000 /System/Library/PrivateFrameworks/AudioSession.framework/libSessionUtility.dylib +0x000000019d6ec000 /System/Library/PrivateFrameworks/AudioResourceArbitration.framework/Versions/A/AudioResourceArbitration +0x00000001a1dc4000 /System/Library/PrivateFrameworks/PowerLog.framework/Versions/A/PowerLog +0x00000001a1ce2000 /System/Library/Frameworks/CoreBluetooth.framework/Versions/A/CoreBluetooth +0x00000001a4ef9000 /System/Library/Frameworks/AudioUnit.framework/Versions/A/AudioUnit +0x0000000198c1e000 /System/Library/PrivateFrameworks/CoreUtils.framework/Versions/A/CoreUtils +0x000000022b87b000 /System/Library/PrivateFrameworks/CoreUtilsExtras.framework/Versions/A/CoreUtilsExtras +0x00000002365c6000 /System/Library/PrivateFrameworks/IO80211.framework/Versions/A/IO80211 +0x00000001a297a000 /System/Library/PrivateFrameworks/FrontBoardServices.framework/Versions/A/FrontBoardServices +0x00000001a44c1000 /System/Library/PrivateFrameworks/BackBoardServices.framework/Versions/A/BackBoardServices +0x000000019b2fe000 /System/Library/PrivateFrameworks/IconFoundation.framework/Versions/A/IconFoundation +0x00000001a0cbd000 /System/Library/PrivateFrameworks/SpeechRecognitionCore.framework/Versions/A/SpeechRecognitionCore +0x00000001aced9000 /usr/lib/libAccessibility.dylib +0x00000001a13b7000 /System/Library/Frameworks/MediaAccessibility.framework/Versions/A/MediaAccessibility +0x00000001d2408000 /System/Library/Frameworks/OSLog.framework/Versions/A/OSLog +0x00000001b2690000 /System/Library/PrivateFrameworks/LoggingSupport.framework/Versions/A/LoggingSupport +0x00000001054f0000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libRblas.0.dylib +0x0000000105d84000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libgfortran.5.dylib +0x0000000105648000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libquadmath.0.dylib +0x0000000105520000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libgcc_s.1.1.dylib +0x00000001b6bdf000 /usr/lib/libncurses.5.4.dylib +0x0000000105098000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/methods/libs/methods.so +0x00000001050d4000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/utils/libs/utils.so +0x0000000105264000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/grDevices/libs/grDevices.so +0x000000019b598000 /System/Library/PrivateFrameworks/login.framework/Versions/A/login +0x00000001a2b50000 /System/Library/Frameworks/LocalAuthentication.framework/Versions/A/LocalAuthentication +0x00000001958d6000 /System/Library/PrivateFrameworks/login.framework/Versions/A/Frameworks/loginsupport.framework/Versions/A/loginsupport +0x0000000238462000 /System/Library/PrivateFrameworks/LocalAuthenticationCore.framework/Versions/A/LocalAuthenticationCore +0x00000001a2b9b000 /System/Library/Frameworks/LocalAuthentication.framework/Support/SharedUtils.framework/Versions/A/SharedUtils +0x00000001a2aeb000 /System/Library/Frameworks/CryptoTokenKit.framework/Versions/A/CryptoTokenKit +0x00000001052c8000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/graphics/libs/graphics.so +0x00000001053bc000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/stats/libs/stats.so +0x0000000105f4c000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libRlapack.dylib +0x0000000253757000 /usr/lib/i18n/libiconv_std.dylib +0x000000025373f000 /usr/lib/i18n/libUTF8.dylib +0x000000025375f000 /usr/lib/i18n/libmapper_none.dylib +0x0000000105314000 /Users/jreps/Library/R/arm64/4.2/library/cli/libs/cli.so +0x000000010d000000 /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/server/libjvm.dylib +0x0000000105200000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/rJava/libs/rJava.so +0x0000000105350000 /Users/jreps/Library/R/arm64/4.2/library/bit/libs/bit.so +0x000000010537c000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/bit64/libs/bit64.so +0x0000000106110000 /Users/jreps/Library/R/arm64/4.2/library/rlang/libs/rlang.so +0x00000001050b4000 /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libjimage.dylib +0x0000000105800000 /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libjava.dylib +0x0000000253737000 /usr/lib/i18n/libUTF1632.dylib +0x0000000105834000 /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libnio.dylib +0x0000000105854000 /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libnet.dylib +0x0000000108498000 /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libzip.dylib +0x000000015b000000 /Library/Developer/CommandLineTools/usr/lib/libclang.dylib +0x00000001084c0000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/tools/libs/tools.so +0x000000010c400000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/modules/internet.so +0x00000001a4813000 /usr/lib/libcurl.4.dylib +0x0000000253e1a000 /usr/lib/libcrypto.46.dylib +0x0000000254b3c000 /usr/lib/libssl.48.dylib +0x00000001a44e7000 /System/Library/Frameworks/LDAP.framework/Versions/A/LDAP +0x00000001a4523000 /System/Library/PrivateFrameworks/TrustEvaluationAgent.framework/Versions/A/TrustEvaluationAgent +0x000000019d38e000 /usr/lib/libsasl2.2.dylib +0x000000010c554000 /Users/jreps/Library/R/arm64/4.2/library/digest/libs/digest.so +0x0000000105464000 /Users/jreps/Library/R/arm64/4.2/library/fastmap/libs/fastmap.so +0x000000010524c000 /Users/jreps/Library/R/arm64/4.2/library/htmltools/libs/htmltools.so +0x000000010e290000 /Users/jreps/Library/R/arm64/4.2/library/Rcpp/libs/Rcpp.so +0x000000010e07c000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/later/libs/later.so +0x00000001053a8000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/magrittr/libs/magrittr.so +0x000000010c528000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/promises/libs/promises.so +0x000000010e434000 /Users/jreps/Library/R/arm64/4.2/library/httpuv/libs/httpuv.so +0x0000000105574000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/mime/libs/mime.so +0x00000001056e4000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/ellipsis/libs/ellipsis.so +0x000000010e544000 /Users/jreps/Library/R/arm64/4.2/library/vctrs/libs/vctrs.so +0x0000000105878000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/glue/libs/glue.so +0x000000010c580000 /Users/jreps/Library/R/arm64/4.2/library/fansi/libs/fansi.so +0x000000010e200000 /Users/jreps/Library/R/arm64/4.2/library/utf8/libs/utf8.so +0x0000000106168000 /Users/jreps/Library/R/arm64/4.2/library/tibble/libs/tibble.so +0x000000010c5a4000 /Users/jreps/Library/R/arm64/4.2/library/dplyr/libs/dplyr.so +0x000000010c5c0000 /Users/jreps/Library/R/arm64/4.2/library/checkmate/libs/checkmate.so +0x00000001084e8000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/backports/libs/backports.so +0x000000011c000000 /Users/jreps/Library/R/arm64/4.2/library/readr/libs/readr.so +0x000000010e374000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/tzdb/libs/tzdb.so +0x000000019ca06000 /usr/lib/libusrtcp.dylib +0x0000000191feb000 /usr/lib/libboringssl.dylib +0x00000001087ec000 /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libextnet.dylib +0x000000010c5e0000 /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libmanagement.dylib +0x000000010e0c8000 /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/libmanagement_ext.dylib +0x000000011c098000 /Users/jreps/Library/R/arm64/4.2/library/triebeard/libs/triebeard.so +0x000000010e3c4000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/urltools/libs/urltools.so +0x0000000156cb0000 /Users/jreps/Library/R/arm64/4.2/library/sass/libs/sass.so +0x000000010e258000 /Users/jreps/Library/R/arm64/4.2/library/jsonlite/libs/jsonlite.so +0x00000001087d8000 /Users/jreps/Library/R/arm64/4.2/library/cachem/libs/cachem.so +0x000000010e6a0000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/yaml/libs/yaml.so +0x000000011de00000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/grid/libs/grid.so +0x000000010e274000 /Users/jreps/Library/R/arm64/4.2/library/colorspace/libs/colorspace.so +0x000000011deb8000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/data.table/libs/data_table.so +0x000000010e0dc000 /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/lazyeval/libs/lazyeval.so +0x000000010e324000 /Users/jreps/Library/R/arm64/4.2/library/purrr/libs/purrr.so +0x000000010e6d0000 /Users/jreps/Library/R/arm64/4.2/library/tidyr/libs/tidyr.so +0x0000000253767000 /usr/lib/i18n/libmapper_serial.dylib +0x0000000253763000 /usr/lib/i18n/libmapper_parallel.dylib +0x000000025375b000 /usr/lib/i18n/libmapper_646.dylib +0x000000025376b000 /usr/lib/i18n/libmapper_std.dylib + + +VM Arguments: +jvm_args: -Djava.awt.headless=true -Xmx512m -Xrs vfprintf exit -Xss2m +java_command: +java_class_path (initial): /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library/rJava/java/boot +Launcher Type: generic + +[Global flags] + intx CICompilerCount = 4 {product} {ergonomic} + uint ConcGCThreads = 2 {product} {ergonomic} + uint G1ConcRefinementThreads = 8 {product} {ergonomic} + size_t G1HeapRegionSize = 1048576 {product} {ergonomic} + uintx GCDrainStackTargetSize = 64 {product} {ergonomic} + size_t InitialHeapSize = 268435456 {product} {ergonomic} + size_t MarkStackSize = 4194304 {product} {ergonomic} + size_t MaxHeapSize = 536870912 {product} {command line} + size_t MaxNewSize = 321912832 {product} {ergonomic} + size_t MinHeapDeltaBytes = 1048576 {product} {ergonomic} + size_t MinHeapSize = 8388608 {product} {ergonomic} + uintx NonNMethodCodeHeapSize = 5839564 {pd product} {ergonomic} + uintx NonProfiledCodeHeapSize = 122909338 {pd product} {ergonomic} + uintx ProfiledCodeHeapSize = 122909338 {pd product} {ergonomic} + bool ReduceSignalUsage = true {product} {command line} + uintx ReservedCodeCacheSize = 251658240 {pd product} {ergonomic} + bool SegmentedCodeCache = true {product} {ergonomic} + size_t SoftMaxHeapSize = 536870912 {manageable} {ergonomic} + intx ThreadStackSize = 2048 {pd product} {command line} + bool UseCompressedClassPointers = true {product lp64_product} {ergonomic} + bool UseCompressedOops = true {product lp64_product} {ergonomic} + bool UseG1GC = true {product} {ergonomic} + bool UseNUMA = false {product} {ergonomic} + bool UseNUMAInterleaving = false {product} {ergonomic} + +Logging: +Log output configuration: + #0: stdout all=warning uptime,level,tags + #1: stderr all=off uptime,level,tags + +Environment Variables: +PATH=/Library/Frameworks/Python.framework/Versions/3.11/bin:/Library/Frameworks/Python.framework/Versions/3.11/bin:/Library/Frameworks/Python.framework/Versions/3.11/bin:/Library/Frameworks/Python.framework/Versions/3.11/bin:/Library/Frameworks/Python.framework/Versions/3.11/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/TeX/texbin:/Users/jreps/Applications/quarto/bin:/usr/ucb:/Applications/quarto/bin:/usr/texbin:/Applications/RStudio.app/Contents/Resources/app/bin/postback:/Applications/RStudio.app/Contents/Resources/app/bin/postback:/Applications/RStudio.app/Contents/Resources/app/bin/postback:/Applications/RStudio.app/Contents/Resources/app/bin/postback +SHELL=/bin/zsh +DISPLAY=:0 +LANG=en_US.UTF-8 +LC_CTYPE=en_US.UTF-8 +TERM=xterm-256color +TMPDIR=/var/folders/68/4qxz0vzd2z1dt6bvj379jwl80000gp/T/ +DYLD_LIBRARY_PATH=/Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/lib/server +DYLD_FALLBACK_LIBRARY_PATH=/Library/Frameworks/R.framework/Resources/lib:/Library/Java/JavaVirtualMachines/jdk-17.0.1+12/Contents/Home/lib/server:/var/folders/68/4qxz0vzd2z1dt6bvj379jwl80000gp/T/rstudio-fallback-library-path-1123487826 + +Signal Handlers: + SIGSEGV: crash_handler in libjvm.dylib, mask=11100110000111110111111111111111, flags=SA_RESTART|SA_SIGINFO + SIGBUS: crash_handler in libjvm.dylib, mask=11100110000111110111111111111111, flags=SA_RESTART|SA_SIGINFO + SIGFPE: crash_handler in libjvm.dylib, mask=11100110000111110111111111111111, flags=SA_RESTART|SA_SIGINFO + SIGPIPE: javaSignalHandler in libjvm.dylib, mask=11100110000111110111111111111111, flags=SA_RESTART|SA_SIGINFO + SIGXFSZ: javaSignalHandler in libjvm.dylib, mask=11100110000111110111111111111111, flags=SA_RESTART|SA_SIGINFO + SIGILL: crash_handler in libjvm.dylib, mask=11100110000111110111111111111111, flags=SA_RESTART|SA_SIGINFO + SIGUSR2: SIG_IGN, mask=00000000000000000000000000000000, flags=none + *** Handler was modified! + *** Expected: SR_handler in libjvm.dylib, mask=11000000000000000000000000000000, flags=SA_RESTART|SA_SIGINFO + SIGHUP: SIG_DFL, mask=00000000000000000000000000000000, flags=none + SIGINT: rstudio_boost::asio::detail::reactive_socket_accept_op_base, rstudio_boost::asio::ip::tcp>::do_perform+620944 in rsession-arm64, mask=00000000000000000000000000000000, flags=SA_RESTART + SIGTERM: SIG_DFL, mask=00000000000000000000000000000000, flags=none + SIGQUIT: SIG_DFL, mask=00000000000000000000000000000000, flags=none + SIGTRAP: crash_handler in libjvm.dylib, mask=11100110000111110111111111111111, flags=SA_RESTART|SA_SIGINFO + + +--------------- S Y S T E M --------------- + +OS: +uname: Darwin 23.5.0 Darwin Kernel Version 23.5.0: Wed May 1 20:12:58 PDT 2024; root:xnu-10063.121.3~5/RELEASE_ARM64_T6000 arm64 +OS uptime: 0 days 9:23 hours +rlimit (soft/hard): STACK 8176k/65520k , CORE 0k/infinity , NPROC 2666/4000 , NOFILE 12544/infinity , AS infinity/infinity , CPU infinity/infinity , DATA infinity/infinity , FSIZE infinity/infinity , MEMLOCK infinity/infinity , RSS infinity/infinity +load average: 2.40 2.95 4.51 + +CPU: total 8 (initial active 8) 0x61:0x0:0x1b588bb3:0, fp, simd, crc, lse + +Memory: 16k page, physical 16777216k(758240k free), swap 0k(0k free) + +vm_info: OpenJDK 64-Bit Server VM (17.0.5+8-LTS) for bsd-aarch64 JRE (17.0.5+8-LTS), built on Oct 13 2022 05:06:05 by "ec2user" with clang Apple LLVM 13.0.0 (clang-1300.0.29.30) + +END. From 427f8eaec227084594dc6eabdd56d6ad60c09195 Mon Sep 17 00:00:00 2001 From: jreps Date: Wed, 22 May 2024 10:36:22 -0400 Subject: [PATCH 08/64] Update characterization-riskFactors.R --- R/characterization-riskFactors.R | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/R/characterization-riskFactors.R b/R/characterization-riskFactors.R index ce0da5e0..06f5d3e7 100644 --- a/R/characterization-riskFactors.R +++ b/R/characterization-riskFactors.R @@ -140,7 +140,7 @@ characterizationGetRiskFactorData <- function( shiny::withProgress(message = 'Getting risk factor data', value = 0, { shiny::incProgress(1/4, detail = paste("Extracting ids")) - sql <- "SELECT cd.cohort_definition_id, cd.cohort_type, cc.person_count as N + sql <- "SELECT distinct cd.cohort_definition_id, cd.cohort_type, cc.person_count as N from @schema.@c_table_prefixcohort_details cd left join @@ -252,7 +252,6 @@ riskFactorTable <- function( dplyr::filter(.data$cohortDefinitionId == !!caseId) %>% dplyr::select(-"cohortDefinitionId") - print(paste0(caseData, 'cases')) allId <- ids$cohortDefinitionId[ids$cohortType == 'T'] allData <- data %>% @@ -350,8 +349,6 @@ riskFactorContinuousTable <- function( ids # have N in them ){ - print(ids) - caseId <- ids$cohortDefinitionId[ids$cohortType == 'TnO'] if(length(caseId ) == 0){ caseId <- -1 From a9675e0591d3da2fba96a2f7adf37ccc7640080d Mon Sep 17 00:00:00 2001 From: jreps Date: Wed, 22 May 2024 12:35:14 -0400 Subject: [PATCH 09/64] fixes fixes --- R/characterization-caseSeries.R | 39 ++++++++++++++----- R/characterization-riskFactors.R | 67 +++++++++++++++++++++++++------- 2 files changed, 83 insertions(+), 23 deletions(-) diff --git a/R/characterization-caseSeries.R b/R/characterization-caseSeries.R index c17d0247..fc65b8a4 100644 --- a/R/characterization-caseSeries.R +++ b/R/characterization-caseSeries.R @@ -194,7 +194,7 @@ characterizationGetCaseSeriesData <- function( shiny::withProgress(message = 'Getting case series data', value = 0, { shiny::incProgress(1/4, detail = paste("Extracting ids")) - sql <- "SELECT cohort_definition_id, cohort_type + sql <- "SELECT distinct cohort_definition_id, cohort_type from @schema.@c_table_prefixcohort_details where target_cohort_id = @target_id @@ -216,13 +216,20 @@ characterizationGetCaseSeriesData <- function( shiny::incProgress(2/4, detail = paste("Extracting binary")) - sql <- "SELECT cov.cohort_definition_id, cr.covariate_name, cov.covariate_id, cov.sum_value, cov.average_value + sql <- "SELECT cov.cohort_definition_id, cr.covariate_name, + s.min_prior_observation, s.outcome_washout_days, + cov.covariate_id, cov.sum_value, cov.average_value from @schema.@c_table_prefixcovariates cov inner join @schema.@c_table_prefixcovariate_ref cr on cov.run_id = cr.run_id and cov.database_id = cr.database_id and cov.covariate_id = cr.covariate_id + + inner join @schema.@c_table_prefixsettings s + on cov.run_id = s.run_id + and cov.database_id = s.database_id + where cov.cohort_definition_id in (@ids) and cov.database_id = '@database_id' ;" @@ -243,7 +250,8 @@ characterizationGetCaseSeriesData <- function( shiny::incProgress(3/4, detail = paste("Extracting continuous")) - sql <- "SELECT cov.cohort_definition_id, cr.covariate_name, cov.covariate_id, + sql <- "SELECT cov.cohort_definition_id, cr.covariate_name, + s.min_prior_observation, s.outcome_washout_days, cov.covariate_id, cov.count_value, cov.min_value, cov.max_value, cov.average_value, cov.standard_deviation, cov.median_value, cov.p_10_value, cov.p_25_value, cov.p_75_value, cov.p_90_value @@ -253,6 +261,11 @@ characterizationGetCaseSeriesData <- function( on cov.run_id = cr.run_id and cov.database_id = cr.database_id and cov.covariate_id = cr.covariate_id + + inner join @schema.@c_table_prefixsettings s + on cov.run_id = s.run_id + and cov.database_id = s.database_id + where cov.cohort_definition_id in (@ids) and cov.database_id = '@database_id' ;" @@ -322,32 +335,32 @@ caseSeriesTable <- function( sumValueBefore = .data$sumValue, averageValueBefore = .data$averageValue, ) %>% - dplyr::select("covariateName", "covariateId", "sumValueBefore", "averageValueBefore") + dplyr::select("covariateName", "covariateId", 'minPriorObservation', 'outcomeWashoutDays', "sumValueBefore", "averageValueBefore") afterData <-afterData %>% dplyr::mutate( sumValueAfter = .data$sumValue, averageValueAfter = .data$averageValue, ) %>% - dplyr::select("covariateName", "covariateId", "sumValueAfter", "averageValueAfter") + dplyr::select("covariateName", "covariateId", 'minPriorObservation', 'outcomeWashoutDays', "sumValueAfter", "averageValueAfter") duringData <- duringData %>% dplyr::mutate( sumValueDuring = .data$sumValue, averageValueDuring = .data$averageValue, ) %>% - dplyr::select("covariateName", "covariateId", "sumValueDuring", "averageValueDuring") + dplyr::select("covariateName", "covariateId", 'minPriorObservation', 'outcomeWashoutDays', "sumValueDuring", "averageValueDuring") allResults <- beforeData %>% dplyr::full_join( y = duringData, - by = c("covariateName", "covariateId") + by = c("covariateName", "covariateId", 'minPriorObservation', 'outcomeWashoutDays') ) %>% dplyr::full_join( y = afterData, - by = c("covariateName", "covariateId") + by = c("covariateName", "covariateId", 'minPriorObservation', 'outcomeWashoutDays') ) return(allResults) @@ -362,6 +375,12 @@ colDefs <- function(){ covariateId = reactable::colDef( show = F ), + minPriorObservation = reactable::colDef( + name = "Minimum prior observation" + ), + outcomeWashoutDays = reactable::colDef( + name = "outcome washout days" + ), sumValueBefore = reactable::colDef( name = "Number of cases with feature before exposure", format = reactable::colFormat(digits = 2, percent = F), @@ -376,7 +395,7 @@ colDefs <- function(){ format = reactable::colFormat(digits = 2, percent = T) ), sumValueDuring = reactable::colDef( - name = "Number of cases with feature during exposure", + name = "Number of cases with feature between exposure and outcome", format = reactable::colFormat(digits = 2, percent = F), cell = function(value) { if(is.null(value)){return('< min threshold')} @@ -385,7 +404,7 @@ colDefs <- function(){ } ), averageValueDuring = reactable::colDef( - name = "% of cases with feature during exposure", + name = "% of cases with feature between exposure and outcome", format = reactable::colFormat(digits = 2, percent = T) ), sumValueAfter = reactable::colDef( diff --git a/R/characterization-riskFactors.R b/R/characterization-riskFactors.R index 06f5d3e7..c120a5fa 100644 --- a/R/characterization-riskFactors.R +++ b/R/characterization-riskFactors.R @@ -168,13 +168,20 @@ characterizationGetRiskFactorData <- function( shiny::incProgress(2/4, detail = paste("Extracting binary")) - sql <- "SELECT cov.cohort_definition_id, cr.covariate_name, cov.covariate_id, cov.sum_value, cov.average_value + sql <- "SELECT distinct cov.cohort_definition_id, cr.covariate_name, + s.min_prior_observation, s.outcome_washout_days, + cov.covariate_id, cov.sum_value, cov.average_value from @schema.@c_table_prefixcovariates cov inner join @schema.@c_table_prefixcovariate_ref cr on cov.run_id = cr.run_id and cov.database_id = cr.database_id and cov.covariate_id = cr.covariate_id + + inner join @schema.@c_table_prefixsettings s + on cov.run_id = s.run_id + and cov.database_id = s.database_id + where cov.cohort_definition_id in (@ids) and cov.database_id = '@database_id' and cr.analysis_id not in (109, 110, 217, 218, 305, 417, 418, 505, 605, 713, 805, 926, 927) @@ -196,7 +203,8 @@ characterizationGetRiskFactorData <- function( shiny::incProgress(3/4, detail = paste("Extracting continuous")) - sql <- "SELECT cov.cohort_definition_id, cr.covariate_name, cov.covariate_id, + sql <- "SELECT distinct cov.cohort_definition_id, cr.covariate_name, + s.min_prior_observation, s.outcome_washout_days,cov.covariate_id, cov.count_value, cov.min_value, cov.max_value, cov.average_value, cov.standard_deviation, cov.median_value, cov.p_10_value, cov.p_25_value, cov.p_75_value, cov.p_90_value @@ -206,6 +214,12 @@ characterizationGetRiskFactorData <- function( on cov.run_id = cr.run_id and cov.database_id = cr.database_id and cov.covariate_id = cr.covariate_id + + inner join @schema.@c_table_prefixsettings s + on cov.run_id = s.run_id + and cov.database_id = s.database_id + + where cov.cohort_definition_id in (@ids) and cov.database_id = '@database_id' and cr.analysis_id not in (109, 110, 217, 218, 305, 417, 418, 505, 605, 713, 805, 926, 927) @@ -243,6 +257,8 @@ riskFactorTable <- function( data, ids ){ + + data <- unique(data) caseId <- ids$cohortDefinitionId[ids$cohortType == 'TnO'] if(length(caseId ) == 0){ @@ -251,7 +267,7 @@ riskFactorTable <- function( caseData <- data %>% dplyr::filter(.data$cohortDefinitionId == !!caseId) %>% dplyr::select(-"cohortDefinitionId") - + #write.csv(caseData, '/Users/jreps/Documents/caseData.csv') allId <- ids$cohortDefinitionId[ids$cohortType == 'T'] allData <- data %>% @@ -259,6 +275,8 @@ riskFactorTable <- function( dplyr::select(-"cohortDefinitionId") allData$N <- allData$sumValue[1]/allData$averageValue[1] + #write.csv(allData, '/Users/jreps/Documents/allData.csv') + excludeId <- ids$cohortDefinitionId[ids$cohortType == 'TnOprior'] if(length(excludeId) == 0){ excludeId <- -1 @@ -270,11 +288,12 @@ riskFactorTable <- function( if(nrow(excludeData) > 0 ){ excludeData$N <- excludeData$sumValue[1]/excludeData$averageValue[1] excludeN <- excludeData$sumValue[1]/excludeData$averageValue[1] - colnames(excludeData)[!colnames(excludeData) %in% c('covariateId', 'covariateName')] <- paste0('exclude_',colnames(excludeData)) + colnamesInclude <- !colnames(excludeData) %in% c('covariateId', 'covariateName', 'minPriorObservation', 'outcomeWashoutDays') + colnames(excludeData)[colnamesInclude] <- paste0('exclude_',colnames(excludeData)[colnamesInclude]) # if prior Os then exclude from T allData <- allData %>% - dplyr::full_join(excludeData, by = c('covariateId', 'covariateName')) %>% + dplyr::full_join(excludeData, by = c('covariateId', 'covariateName', 'minPriorObservation', 'outcomeWashoutDays')) %>% dplyr::mutate( sumValue = .data$sumValue - .data$exclude_sumValue, averageValue = (.data$sumValue - .data$exclude_sumValue)/(.data$N-!!excludeN) @@ -282,7 +301,7 @@ riskFactorTable <- function( dplyr::mutate( N = .data$N-!!excludeN ) %>% - dplyr::select("covariateId","covariateName","sumValue","averageValue", "N") + dplyr::select("covariateId","covariateName","sumValue","averageValue", "N", 'minPriorObservation', 'outcomeWashoutDays') } @@ -293,11 +312,11 @@ riskFactorTable <- function( caseSumValue = .data$sumValue, caseAverageValue = .data$averageValue ) %>% - dplyr::select("covariateId","covariateName","caseSumValue","caseAverageValue", "caseN") + dplyr::select("covariateId","covariateName","caseSumValue","caseAverageValue", "caseN", 'minPriorObservation', 'outcomeWashoutDays') # join with cases allData <- allData %>% - dplyr::full_join(caseData, by = c('covariateId', 'covariateName')) %>% + dplyr::full_join(caseData, by = c('covariateId', 'covariateName', 'minPriorObservation', 'outcomeWashoutDays')) %>% dplyr::mutate_if(is.numeric,dplyr::coalesce,0) %>% dplyr::mutate( nonCaseSumValue = .data$sumValue - .data$caseSumValue, @@ -308,6 +327,7 @@ riskFactorTable <- function( ) %>% dplyr::select( "covariateId","covariateName", + 'minPriorObservation', 'outcomeWashoutDays', "caseSumValue","caseAverageValue", "nonCaseSumValue","nonCaseAverageValue", "N","caseN" @@ -326,6 +346,8 @@ riskFactorTable <- function( ) %>% dplyr::select(-"meanDiff",-"std1", -"std2",-"N",-"caseN") + #write.csv(allData, '/Users/jreps/Documents/finalData.csv') + } else{ allData <- allData %>% @@ -335,12 +357,13 @@ riskFactorTable <- function( ) %>% dplyr::select( "covariateId","covariateName", + 'minPriorObservation', 'outcomeWashoutDays', "nonCaseSumValue","nonCaseAverageValue" ) } - return(allData) + return(unique(allData)) } @@ -349,6 +372,8 @@ riskFactorContinuousTable <- function( ids # have N in them ){ + data <- unique(data) + caseId <- ids$cohortDefinitionId[ids$cohortType == 'TnO'] if(length(caseId ) == 0){ caseId <- -1 @@ -377,13 +402,15 @@ riskFactorContinuousTable <- function( caseP75Value = .data$p75Value, caseP90Value = .data$p90Value ) %>% - dplyr::select("covariateId","covariateName","caseCountValue","caseAverageValue", + dplyr::select("covariateId","covariateName", + 'minPriorObservation', 'outcomeWashoutDays', + "caseCountValue","caseAverageValue", "caseStandardDeviation", "caseMedianValue", "caseP10Value", "caseP25Value", "caseP75Value", "caseP90Value", "caseMaxValue", "caseMinValue") # join with cases allData <- allData %>% - dplyr::full_join(caseData, by = c('covariateId', 'covariateName')) %>% + dplyr::full_join(caseData, by = c('covariateId', 'covariateName', 'minPriorObservation', 'outcomeWashoutDays')) %>% dplyr::mutate( targetCountValue = .data$countValue, targetAverageValue = .data$averageValue, @@ -396,7 +423,9 @@ riskFactorContinuousTable <- function( targetP75Value = .data$p75Value, targetP90Value = .data$p90Value ) %>% - dplyr::select("covariateId","covariateName","caseCountValue","caseAverageValue", + dplyr::select("covariateId","covariateName", + 'minPriorObservation', 'outcomeWashoutDays', + "caseCountValue","caseAverageValue", "caseStandardDeviation", "caseMedianValue", "caseP10Value", "caseP25Value", "caseP75Value", "caseP90Value", "caseMaxValue", "caseMinValue", @@ -417,7 +446,7 @@ riskFactorContinuousTable <- function( } - return(allData) + return(unique(allData)) } @@ -430,6 +459,12 @@ characteriationRiskFactorColDefs <- function(){ covariateId = reactable::colDef( show = F ), + minPriorObservation = reactable::colDef( + name = "Minimum prior observation" + ), + outcomeWashoutDays = reactable::colDef( + name = "outcome washout days" + ), nonCaseSumValue = reactable::colDef( name = "Number of non-cases with feature before exposure", format = reactable::colFormat( @@ -487,6 +522,12 @@ characteriationRiskFactorContColDefs <- function(){ covariateId = reactable::colDef( show = F ), + minPriorObservation = reactable::colDef( + name = "Minimum prior observation" + ), + outcomeWashoutDays = reactable::colDef( + name = "outcome washout days" + ), targetCountValue = reactable::colDef( name = "Number of target population with feature", format = reactable::colFormat( From a9918ce16e28fd1a8ed26dccd0470cd8b4c0e2c9 Mon Sep 17 00:00:00 2001 From: jreps Date: Wed, 22 May 2024 13:48:04 -0400 Subject: [PATCH 10/64] Update characterization-caseSeries.R adding two extra columns --- R/characterization-caseSeries.R | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/R/characterization-caseSeries.R b/R/characterization-caseSeries.R index fc65b8a4..52076ee6 100644 --- a/R/characterization-caseSeries.R +++ b/R/characterization-caseSeries.R @@ -218,6 +218,7 @@ characterizationGetCaseSeriesData <- function( sql <- "SELECT cov.cohort_definition_id, cr.covariate_name, s.min_prior_observation, s.outcome_washout_days, + s.case_post_outcome_duration, s.case_pre_target_duration, cov.covariate_id, cov.sum_value, cov.average_value from @schema.@c_table_prefixcovariates cov @@ -251,7 +252,9 @@ characterizationGetCaseSeriesData <- function( shiny::incProgress(3/4, detail = paste("Extracting continuous")) sql <- "SELECT cov.cohort_definition_id, cr.covariate_name, - s.min_prior_observation, s.outcome_washout_days, cov.covariate_id, + s.min_prior_observation, s.outcome_washout_days, + s.case_post_outcome_duration, s.case_pre_target_duration, + cov.covariate_id, cov.count_value, cov.min_value, cov.max_value, cov.average_value, cov.standard_deviation, cov.median_value, cov.p_10_value, cov.p_25_value, cov.p_75_value, cov.p_90_value @@ -335,32 +338,32 @@ caseSeriesTable <- function( sumValueBefore = .data$sumValue, averageValueBefore = .data$averageValue, ) %>% - dplyr::select("covariateName", "covariateId", 'minPriorObservation', 'outcomeWashoutDays', "sumValueBefore", "averageValueBefore") + dplyr::select("covariateName", "covariateId", 'minPriorObservation', 'outcomeWashoutDays','casePostOutcomeDuration', 'casePreTargetDuration', "sumValueBefore", "averageValueBefore") afterData <-afterData %>% dplyr::mutate( sumValueAfter = .data$sumValue, averageValueAfter = .data$averageValue, ) %>% - dplyr::select("covariateName", "covariateId", 'minPriorObservation', 'outcomeWashoutDays', "sumValueAfter", "averageValueAfter") + dplyr::select("covariateName", "covariateId", 'minPriorObservation', 'outcomeWashoutDays','casePostOutcomeDuration', 'casePreTargetDuration', "sumValueAfter", "averageValueAfter") duringData <- duringData %>% dplyr::mutate( sumValueDuring = .data$sumValue, averageValueDuring = .data$averageValue, ) %>% - dplyr::select("covariateName", "covariateId", 'minPriorObservation', 'outcomeWashoutDays', "sumValueDuring", "averageValueDuring") + dplyr::select("covariateName", "covariateId", 'minPriorObservation', 'outcomeWashoutDays','casePostOutcomeDuration', 'casePreTargetDuration', "sumValueDuring", "averageValueDuring") allResults <- beforeData %>% dplyr::full_join( y = duringData, - by = c("covariateName", "covariateId", 'minPriorObservation', 'outcomeWashoutDays') + by = c("covariateName", "covariateId", 'minPriorObservation', 'outcomeWashoutDays','casePostOutcomeDuration', 'casePreTargetDuration') ) %>% dplyr::full_join( y = afterData, - by = c("covariateName", "covariateId", 'minPriorObservation', 'outcomeWashoutDays') + by = c("covariateName", "covariateId", 'minPriorObservation', 'outcomeWashoutDays','casePostOutcomeDuration', 'casePreTargetDuration') ) return(allResults) @@ -381,6 +384,12 @@ colDefs <- function(){ outcomeWashoutDays = reactable::colDef( name = "outcome washout days" ), + casePostOutcomeDuration = reactable::colDef( + name = "Time after outcome we look for covariate" + ), + casePreTargetDuration = reactable::colDef( + name = "Time before exposure we look for covariate" + ), sumValueBefore = reactable::colDef( name = "Number of cases with feature before exposure", format = reactable::colFormat(digits = 2, percent = F), @@ -408,7 +417,7 @@ colDefs <- function(){ format = reactable::colFormat(digits = 2, percent = T) ), sumValueAfter = reactable::colDef( - name = "Number of cases with feature after exposure", + name = "Number of cases with feature after outcome", format = reactable::colFormat(digits = 2, percent = F), cell = function(value) { if(is.null(value)){return('< min threshold')} @@ -417,7 +426,7 @@ colDefs <- function(){ } ), averageValueAfter = reactable::colDef( - name = "% of cases with feature after exposure", + name = "% of cases with feature after outcome", format = reactable::colFormat(digits = 2, percent = T) ), From faa14208297c165d448da43e8ecf9726b85341d9 Mon Sep 17 00:00:00 2001 From: jreps Date: Wed, 22 May 2024 13:55:33 -0400 Subject: [PATCH 11/64] Update characterization-caseSeries.R restricting case series to during covariates --- R/characterization-caseSeries.R | 2 ++ 1 file changed, 2 insertions(+) diff --git a/R/characterization-caseSeries.R b/R/characterization-caseSeries.R index 52076ee6..866660f9 100644 --- a/R/characterization-caseSeries.R +++ b/R/characterization-caseSeries.R @@ -233,6 +233,7 @@ characterizationGetCaseSeriesData <- function( where cov.cohort_definition_id in (@ids) and cov.database_id = '@database_id' + and cr.analysis_id in (109, 110, 217, 218, 305, 417, 418, 505, 605, 713, 805, 926, 927) ;" binary <- connectionHandler$queryDb( @@ -271,6 +272,7 @@ characterizationGetCaseSeriesData <- function( where cov.cohort_definition_id in (@ids) and cov.database_id = '@database_id' + and cr.analysis_id in (109, 110, 217, 218, 305, 417, 418, 505, 605, 713, 805, 926, 927) ;" # TODO - how to remove prior outcomes?? From 35e837b2d407c0aa1f50c02bf44e410f0e7f8d17 Mon Sep 17 00:00:00 2001 From: jreps Date: Wed, 22 May 2024 17:15:19 -0400 Subject: [PATCH 12/64] Update characterization-main.R adding CI outcomes to char options --- R/characterization-main.R | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/R/characterization-main.R b/R/characterization-main.R index 1d5f4dce..421e2904 100644 --- a/R/characterization-main.R +++ b/R/characterization-main.R @@ -628,7 +628,8 @@ union select database_id, cohort_definition_id as char_cohort_id, target_cohort_id as cohort_definition_id, cohort_type from @schema.@c_table_prefixcohort_details -where cohort_type = 'Tall' +where cohort_type = 'Tall' + ;", schema = resultDatabaseSettings$schema, c_table_prefix = resultDatabaseSettings$cTablePrefix @@ -636,19 +637,29 @@ c_table_prefix = resultDatabaseSettings$cTablePrefix TnOs <- connectionHandler$queryDb( sql = " -select distinct -cd.target_cohort_id, -cd.outcome_cohort_id, -c.cohort_name -from @schema.@c_table_prefixcohort_details cd +select distinct temp.*, c.cohort_name + +from +(select distinct +target_cohort_id, +outcome_cohort_id +from @schema.@c_table_prefixcohort_details +where cohort_type = 'TnO' + +union + +select * +from @schema.@ci_table_prefixcohorts_lookup + +) temp inner join - @schema.@cg_table_prefixcohort_definition c - on cd.outcome_cohort_id = c.cohort_definition_id -where cd.cohort_type = 'TnO' +@schema.@cg_table_prefixcohort_definition c +on temp.outcome_cohort_id = c.cohort_definition_id ;", schema = resultDatabaseSettings$schema, c_table_prefix = resultDatabaseSettings$cTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix + cg_table_prefix = resultDatabaseSettings$cgTablePrefix, + ci_table_prefix = resultDatabaseSettings$incidenceTablePrefix ) # fix backwards compatability cg$subsetParent[is.na(cg$isSubset)] <- cg$cohortDefinitionId From e5e321c30b20bf5d95f7d200bef02a76154efb59 Mon Sep 17 00:00:00 2001 From: jreps Date: Thu, 23 May 2024 14:33:47 -0400 Subject: [PATCH 13/64] Update characterization-riskFactors.R fixing multiple washout and min obs bug in risk factors --- R/characterization-riskFactors.R | 82 +++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 22 deletions(-) diff --git a/R/characterization-riskFactors.R b/R/characterization-riskFactors.R index c120a5fa..cf2b83e6 100644 --- a/R/characterization-riskFactors.R +++ b/R/characterization-riskFactors.R @@ -140,7 +140,9 @@ characterizationGetRiskFactorData <- function( shiny::withProgress(message = 'Getting risk factor data', value = 0, { shiny::incProgress(1/4, detail = paste("Extracting ids")) - sql <- "SELECT distinct cd.cohort_definition_id, cd.cohort_type, cc.person_count as N + sql <- "SELECT distinct + cd.cohort_definition_id, cd.cohort_type, + cc.person_count as N from @schema.@c_table_prefixcohort_details cd left join @@ -191,7 +193,7 @@ characterizationGetRiskFactorData <- function( sql = sql, schema = resultDatabaseSettings$schema, c_table_prefix = resultDatabaseSettings$cTablePrefix, - ids = paste0(ids$cohortDefinitionId, collapse = ','), + ids = paste0(unique(ids$cohortDefinitionId), collapse = ','), database_id = databaseId ) @@ -259,7 +261,7 @@ riskFactorTable <- function( ){ data <- unique(data) - + caseId <- ids$cohortDefinitionId[ids$cohortType == 'TnO'] if(length(caseId ) == 0){ caseId <- -1 @@ -267,15 +269,25 @@ riskFactorTable <- function( caseData <- data %>% dplyr::filter(.data$cohortDefinitionId == !!caseId) %>% dplyr::select(-"cohortDefinitionId") - #write.csv(caseData, '/Users/jreps/Documents/caseData.csv') + casecounts <- caseData %>% + dplyr::mutate(N = .data$sumValue/.data$averageValue) %>% + dplyr::select('minPriorObservation', 'outcomeWashoutDays', 'N') %>% + dplyr::group_by(.data$minPriorObservation, .data$outcomeWashoutDays) %>% + dplyr::summarise(caseN = round(max(.data$N))) + + #write.csv(caseData, '/Users/jreps/Documents/caseData.csv') + allId <- ids$cohortDefinitionId[ids$cohortType == 'T'] allData <- data %>% dplyr::filter(.data$cohortDefinitionId == !!allId) %>% dplyr::select(-"cohortDefinitionId") - allData$N <- allData$sumValue[1]/allData$averageValue[1] - #write.csv(allData, '/Users/jreps/Documents/allData.csv') + allcounts <- allData %>% + dplyr::mutate(N = .data$sumValue/.data$averageValue) %>% + dplyr::select('minPriorObservation', 'outcomeWashoutDays', 'N') %>% + dplyr::group_by(.data$minPriorObservation, .data$outcomeWashoutDays) %>% + dplyr::summarise(N = round(max(.data$N))) excludeId <- ids$cohortDefinitionId[ids$cohortType == 'TnOprior'] if(length(excludeId) == 0){ @@ -284,43 +296,68 @@ riskFactorTable <- function( excludeData <- data %>% dplyr::filter(.data$cohortDefinitionId == !!excludeId) %>% dplyr::select(-"cohortDefinitionId") + excludecounts <- excludeData %>% + dplyr::mutate(N = .data$sumValue/.data$averageValue) %>% + dplyr::select('minPriorObservation', 'outcomeWashoutDays', 'N') %>% + dplyr::group_by(.data$minPriorObservation, .data$outcomeWashoutDays) %>% + dplyr::summarise(exclude_N = round(max(.data$N))) + if(nrow(excludeData) > 0 ){ - excludeData$N <- excludeData$sumValue[1]/excludeData$averageValue[1] - excludeN <- excludeData$sumValue[1]/excludeData$averageValue[1] colnamesInclude <- !colnames(excludeData) %in% c('covariateId', 'covariateName', 'minPriorObservation', 'outcomeWashoutDays') colnames(excludeData)[colnamesInclude] <- paste0('exclude_',colnames(excludeData)[colnamesInclude]) # if prior Os then exclude from T allData <- allData %>% - dplyr::full_join(excludeData, by = c('covariateId', 'covariateName', 'minPriorObservation', 'outcomeWashoutDays')) %>% - dplyr::mutate( + dplyr::left_join(excludeData, by = c('covariateId', 'covariateName', 'minPriorObservation', 'outcomeWashoutDays')) %>% + dplyr::left_join( # add N per washout/min obs + allcounts, + by = c('minPriorObservation', 'outcomeWashoutDays') + ) %>% + dplyr::left_join( # add N per washout/min obs + excludecounts, + by = c('minPriorObservation', 'outcomeWashoutDays') + ) %>% + dplyr::mutate_if(is.numeric,dplyr::coalesce,0) %>% + dplyr::mutate( # add exclude N per washout/min obs sumValue = .data$sumValue - .data$exclude_sumValue, - averageValue = (.data$sumValue - .data$exclude_sumValue)/(.data$N-!!excludeN) + averageValue = (.data$sumValue - .data$exclude_sumValue)/(.data$N-.data$exclude_N) ) %>% dplyr::mutate( - N = .data$N-!!excludeN + N = .data$N-.data$exclude_N ) %>% dplyr::select("covariateId","covariateName","sumValue","averageValue", "N", 'minPriorObservation', 'outcomeWashoutDays') } - + if(nrow(caseData) > 0){ - caseData$caseN <- caseData$sumValue[1]/caseData$averageValue[1] caseData <- caseData %>% dplyr::mutate( caseSumValue = .data$sumValue, caseAverageValue = .data$averageValue ) %>% - dplyr::select("covariateId","covariateName","caseSumValue","caseAverageValue", "caseN", 'minPriorObservation', 'outcomeWashoutDays') + dplyr::select("covariateId","covariateName","caseSumValue","caseAverageValue", 'minPriorObservation', 'outcomeWashoutDays') # join with cases allData <- allData %>% dplyr::full_join(caseData, by = c('covariateId', 'covariateName', 'minPriorObservation', 'outcomeWashoutDays')) %>% + dplyr::left_join( + casecounts, + by = c('minPriorObservation', 'outcomeWashoutDays') + ) %>% dplyr::mutate_if(is.numeric,dplyr::coalesce,0) %>% dplyr::mutate( - nonCaseSumValue = .data$sumValue - .data$caseSumValue, - nonCaseAverageValue = (.data$sumValue - .data$caseSumValue)/(.data$N-.data$caseN) + nonCaseSumValue = ifelse( + .data$sumValue > 0, + .data$sumValue - .data$caseSumValue, + 0 + ) + , + nonCaseAverageValue = ifelse( + .data$sumValue > 0, + (.data$sumValue - .data$caseSumValue)/(.data$N-.data$caseN), + 0 + ) ) %>% dplyr::mutate( nonCaseN = .data$N-.data$caseN @@ -329,26 +366,27 @@ riskFactorTable <- function( "covariateId","covariateName", 'minPriorObservation', 'outcomeWashoutDays', "caseSumValue","caseAverageValue", - "nonCaseSumValue","nonCaseAverageValue", - "N","caseN" + "nonCaseSumValue","nonCaseAverageValue" + ,"nonCaseN", "caseN", "N" ) + # add abs smd allData <- allData %>% dplyr::mutate( meanDiff = .data$caseAverageValue - .data$nonCaseAverageValue, std1 = sqrt(((1-.data$caseAverageValue)^2*.data$caseSumValue + (-.data$caseAverageValue)^2*(.data$caseN - .data$caseSumValue))/.data$caseN), - std2 = sqrt(((1-.data$nonCaseAverageValue)^2*.data$nonCaseSumValue + (-.data$nonCaseAverageValue)^2*(.data$N - .data$nonCaseSumValue))/.data$N) + std2 = sqrt(((1-.data$nonCaseAverageValue)^2*.data$nonCaseSumValue + (-.data$nonCaseAverageValue)^2*(.data$nonCaseN - .data$nonCaseSumValue))/.data$nonCaseN) ) %>% dplyr::mutate( SMD = .data$meanDiff/sqrt((.data$std1^2 + .data$std2^2)/2), absSMD = abs(.data$meanDiff/sqrt((.data$std1^2 + .data$std2^2)/2)) ) %>% - dplyr::select(-"meanDiff",-"std1", -"std2",-"N",-"caseN") + dplyr::select(-"meanDiff",-"std1", -"std2", -"N",-"caseN", -"nonCaseN") #write.csv(allData, '/Users/jreps/Documents/finalData.csv') - + } else{ allData <- allData %>% dplyr::mutate( From 6a3e48214cb1b90d89d2fbe8b7979f8cfaed00ac Mon Sep 17 00:00:00 2001 From: jreps Date: Fri, 31 May 2024 22:47:53 -0400 Subject: [PATCH 14/64] updating for new char tables updating for new char tables --- R/characterization-caseSeries.R | 161 ++++++++++----------- R/characterization-cohorts.R | 136 +++++++++++++----- R/characterization-database.R | 30 ++-- R/characterization-main.R | 65 +++++---- R/characterization-riskFactors.R | 238 ++++++++++++++++++------------- 5 files changed, 359 insertions(+), 271 deletions(-) diff --git a/R/characterization-caseSeries.R b/R/characterization-caseSeries.R index 866660f9..87c6eb52 100644 --- a/R/characterization-caseSeries.R +++ b/R/characterization-caseSeries.R @@ -80,10 +80,10 @@ characterizationCaseSeriesServer <- function( ), shiny::selectInput( - inputId = session$ns('tarId'), + inputId = session$ns('tarInd'), label = 'Time-at-risk: ', - choices = options()$tarIds, - selected = options()$tarIds[1], + choices = options()$tarInds, + selected = options()$tarInds[1], multiple = F ), @@ -103,7 +103,7 @@ characterizationCaseSeriesServer <- function( targetId = targetId(), outcomeId = outcomeId(), databaseId = input$databaseId, - timeAtRiskId = input$tarId + tar = options()$tarList[[which(options()$tarInds == input$tarInd)]] ) binTableOutputs <- resultTableServer( @@ -135,45 +135,47 @@ characterizationGetCaseSeriesOptions <- function( outcomeId ){ - sql <- "SELECT distinct cd.database_id, d.CDM_SOURCE_ABBREVIATION as database_name, - cd.time_at_risk_id, - t.RISK_WINDOW_START, t.RISK_WINDOW_END, - t.START_ANCHOR, t.END_ANCHOR + sql <- "SELECT distinct s.database_id, d.CDM_SOURCE_ABBREVIATION as database_name, + s.setting_id, + s.RISK_WINDOW_START, s.RISK_WINDOW_END, + s.START_ANCHOR, s.END_ANCHOR from - @schema.@c_table_prefixcohort_details cd + @schema.@c_table_prefixsettings s inner join @schema.@database_meta_table d - on cd.database_id = d.database_id - inner join @schema.@c_table_prefixtime_at_risk t - on t.database_id = cd.database_id - and t.run_id = cd.run_id - and t.time_at_risk_id = cd.time_at_risk_id - - where cd.target_cohort_id = @target_id + on s.database_id = d.database_id + inner join @schema.@c_table_prefixcohort_details cd + on s.setting_id = cd.setting_id + and s.database_id = cd.database_id + and cd.target_cohort_id = @target_id and cd.outcome_cohort_id = @outcome_id - and cd.time_at_risk_id != 0 + and cd.cohort_type = 'TnO' ;" options <- connectionHandler$queryDb( sql = sql, schema = resultDatabaseSettings$schema, c_table_prefix = resultDatabaseSettings$cTablePrefix, - database_meta_table = resultDatabaseSettings$databaseTable, target_id = targetId, - outcome_id = outcomeId + outcome_id = outcomeId, + database_meta_table = resultDatabaseSettings$databaseTable ) db <- unique(options$databaseId) names(db) <- unique(options$databaseName) - tar <- unique(options$timeAtRiskId) - names(tar) <- unique(paste0('(', options$startAnchor, ' + ', options$riskWindowStart, ') - (', - options$endAnchor, ' + ', options$riskWindowEnd, ')' + tar <- unique(options[,c('startAnchor','riskWindowStart', 'endAnchor', 'riskWindowEnd')]) + tarList <- lapply(1:nrow(tar), function(i) as.list(tar[i,])) + #tar <- unique(options$settingId) + tarInds <- 1:nrow(tar) + names(tarInds) <- unique(paste0('(', tar$startAnchor, ' + ', tar$riskWindowStart, ') - (', + tar$endAnchor, ' + ', tar$riskWindowEnd, ')' )) return( list( databaseIds = db, - tarIds = tar + tarInds = tarInds, + tarList = tarList ) ) @@ -186,52 +188,41 @@ characterizationGetCaseSeriesData <- function( targetId, outcomeId, databaseId, - timeAtRiskId + tar ){ - ids <- - shiny::withProgress(message = 'Getting case series data', value = 0, { - shiny::incProgress(1/4, detail = paste("Extracting ids")) - - sql <- "SELECT distinct cohort_definition_id, cohort_type - from - @schema.@c_table_prefixcohort_details - where target_cohort_id = @target_id - and outcome_cohort_id = @outcome_id - and database_id = '@database_id' - and time_at_risk_id = @time_at_risk_id - and cohort_type in ('TnObetween','OnT','TnO') - ;" - - ids <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - c_table_prefix = resultDatabaseSettings$cTablePrefix, - target_id = targetId, - outcome_id = outcomeId, - database_id = databaseId, - time_at_risk_id = timeAtRiskId - ) - - shiny::incProgress(2/4, detail = paste("Extracting binary")) + shiny::incProgress(1/4, detail = paste("Extracting binary")) - sql <- "SELECT cov.cohort_definition_id, cr.covariate_name, + sql <- "SELECT + case + when cov.cohort_type = 'TnO' then 'Before' + when cov.cohort_type = 'TnObetween' then 'During' + when cov.cohort_type = 'OnT' then 'After' + end as type, + cr.covariate_name, s.min_prior_observation, s.outcome_washout_days, s.case_post_outcome_duration, s.case_pre_target_duration, cov.covariate_id, cov.sum_value, cov.average_value from @schema.@c_table_prefixcovariates cov inner join @schema.@c_table_prefixcovariate_ref cr - on cov.run_id = cr.run_id and + on cov.setting_id = cr.setting_id and cov.database_id = cr.database_id and cov.covariate_id = cr.covariate_id inner join @schema.@c_table_prefixsettings s - on cov.run_id = s.run_id + on cov.setting_id = s.setting_id and cov.database_id = s.database_id - - where cov.cohort_definition_id in (@ids) + + where cov.target_cohort_id = @target_id + and cov.outcome_cohort_id = @outcome_id + and cov.cohort_type in ('TnObetween','OnT','TnO') + --and cov.setting_id = @setting_id + and s.risk_window_start = @risk_window_start + and s.risk_window_end = @risk_window_end + and s.start_anchor = '@start_anchor' + and s.end_anchor = '@end_anchor' and cov.database_id = '@database_id' and cr.analysis_id in (109, 110, 217, 218, 305, 417, 418, 505, 605, 713, 805, 926, 927) ;" @@ -240,19 +231,29 @@ characterizationGetCaseSeriesData <- function( sql = sql, schema = resultDatabaseSettings$schema, c_table_prefix = resultDatabaseSettings$cTablePrefix, - ids = paste0(ids$cohortDefinitionId, collapse = ','), + target_id = targetId, + outcome_id = outcomeId, + risk_window_start = tar$riskWindowStart, + risk_window_end = tar$riskWindowEnd, + start_anchor = tar$startAnchor, + end_anchor = tar$endAnchor, database_id = databaseId ) # now process into table binary <- caseSeriesTable( - data = binary, - ids = ids + data = binary ) shiny::incProgress(3/4, detail = paste("Extracting continuous")) - sql <- "SELECT cov.cohort_definition_id, cr.covariate_name, + sql <- "SELECT + case + when cov.cohort_type = 'TnO' then 'Before' + when cov.cohort_type = 'TnObetween' then 'During' + when cov.cohort_type = 'OnT' then 'After' + end as type, + cr.covariate_name, s.min_prior_observation, s.outcome_washout_days, s.case_post_outcome_duration, s.case_pre_target_duration, cov.covariate_id, @@ -262,15 +263,21 @@ characterizationGetCaseSeriesData <- function( from @schema.@c_table_prefixcovariates_continuous cov inner join @schema.@c_table_prefixcovariate_ref cr - on cov.run_id = cr.run_id and + on cov.setting_id = cr.setting_id and cov.database_id = cr.database_id and cov.covariate_id = cr.covariate_id inner join @schema.@c_table_prefixsettings s - on cov.run_id = s.run_id + on cov.setting_id = s.setting_id and cov.database_id = s.database_id - where cov.cohort_definition_id in (@ids) + where cov.target_cohort_id = @target_id + and cov.outcome_cohort_id = @outcome_id + and cov.cohort_type in ('TnObetween','OnT','TnO') + and s.risk_window_start = @risk_window_start + and s.risk_window_end = @risk_window_end + and s.start_anchor = '@start_anchor' + and s.end_anchor = '@end_anchor' and cov.database_id = '@database_id' and cr.analysis_id in (109, 110, 217, 218, 305, 417, 418, 505, 605, 713, 805, 926, 927) ;" @@ -280,18 +287,15 @@ characterizationGetCaseSeriesData <- function( sql = sql, schema = resultDatabaseSettings$schema, c_table_prefix = resultDatabaseSettings$cTablePrefix, - ids = paste0(ids$cohortDefinitionId, collapse = ','), + target_id = targetId, + outcome_id = outcomeId, + risk_window_start = tar$riskWindowStart, + risk_window_end = tar$riskWindowEnd, + start_anchor = tar$startAnchor, + end_anchor = tar$endAnchor, database_id = databaseId ) - # add type - ids <- merge(ids, data.frame( - cohortType = c('TnObetween','OnT','TnO'), - type = c('During', "After", 'Before') - ), by = 'cohortType') %>% - dplyr::select("cohortDefinitionId","type") - continuous <- merge(ids, continuous, by = 'cohortDefinitionId') - shiny::incProgress(4/4, detail = paste("Done")) }) @@ -307,31 +311,22 @@ characterizationGetCaseSeriesData <- function( # now process into table caseSeriesTable <- function( - data, - ids + data ){ - timeBeforeId <- ids$cohortDefinitionId[ids$cohortType == 'TnO'] - timeDuringId <- ids$cohortDefinitionId[ids$cohortType == 'TnObetween'] - timeAfterId <- ids$cohortDefinitionId[ids$cohortType == 'OnT'] - - # Before Index Cases beforeData <- data %>% - dplyr::filter(.data$cohortDefinitionId == !!timeBeforeId) %>% - dplyr::select(-"cohortDefinitionId") + dplyr::filter(.data$type == 'Before') Nbefore <- beforeData$sumValue[1]/beforeData$averageValue[1] # After Index Cases afterData <- data %>% - dplyr::filter(.data$cohortDefinitionId == !!timeAfterId) %>% - dplyr::select(-"cohortDefinitionId") + dplyr::filter(.data$type == 'After') Nafter <- afterData$sumValue[1]/afterData$averageValue[1] # During Index Cases duringData <- data %>% - dplyr::filter(.data$cohortDefinitionId == !!timeDuringId) %>% - dplyr::select(-"cohortDefinitionId") + dplyr::filter(.data$type == 'During') Nduring <- duringData$sumValue[1]/duringData$averageValue[1] diff --git a/R/characterization-cohorts.R b/R/characterization-cohorts.R index 8f71e506..de8a93a6 100644 --- a/R/characterization-cohorts.R +++ b/R/characterization-cohorts.R @@ -76,10 +76,11 @@ characterizationCohortComparisonServer <- function( id, function(input, output, session) { - inputVals <- characterizationGetCohortsInputs( + inputVals <- shiny::reactive({characterizationGetCohortsInputs( connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) + resultDatabaseSettings = resultDatabaseSettings, + targetId = subTargetId + )}) # initial comp chilren @@ -114,8 +115,8 @@ characterizationCohortComparisonServer <- function( shinyWidgets::pickerInput( inputId = session$ns('databaseId'), label = 'Database: ', - choices = inputVals$databaseIds, - selected = inputVals$databaseIds[1], + choices = inputVals()$databaseIds, + selected = inputVals()$databaseIds[1], multiple = F, options = shinyWidgets::pickerOptions( actionsBox = TRUE, @@ -186,26 +187,30 @@ characterizationCohortComparisonServer <- function( selected( data.frame( Comparator = names(comparatorGroups())[which(comparatorGroups() == input$comparatorId)], - Database = names(inputVals$databaseIds)[input$databaseId == inputVals$databaseIds] + Database = names(inputVals()$databaseIds)[input$databaseId == inputVals()$databaseIds] ) ) - selection1 <- options[[parentIndex()]]$children[[which(subTargetIds == subTargetId())]]$charIds %>% - dplyr::filter(.data$databaseId == input$databaseId) %>% - dplyr::filter(.data$cohortType %in% c('T','O')) %>% - dplyr::filter(.data$cohortDefinitionId == subTargetId()) # is this needed? + selection1 <- subTargetId() + #selection1 <- options[[parentIndex()]]$children[[which(subTargetIds == subTargetId())]]$charIds %>% + # dplyr::filter(.data$databaseId == input$databaseId) %>% + # dplyr::filter(.data$cohortType %in% c('T','O')) %>% + # dplyr::filter(.data$cohortDefinitionId == subTargetId()) # is this needed? - if(nrow(selection1) == 0){ + #if(nrow(selection1) == 0){ + if(length(selection1) == 0){ runTables <- FALSE shiny::showNotification('No results for section 1') } - selection2 <- options[[comparatorIndex()]]$children[[which(comparatorGroups() == input$comparatorId)]]$charIds %>% - dplyr::filter(.data$databaseId == input$databaseId) %>% - dplyr::filter(.data$cohortType %in% c('T','O')) %>% - dplyr::filter(.data$cohortDefinitionId == input$comparatorId) + selection2 <- input$comparatorId + #selection2 <- options[[comparatorIndex()]]$children[[which(comparatorGroups() == input$comparatorId)]]$charIds %>% + # dplyr::filter(.data$databaseId == input$databaseId) %>% + # dplyr::filter(.data$cohortType %in% c('T','O')) %>% + # dplyr::filter(.data$cohortDefinitionId == input$comparatorId) - if(nrow(selection2) == 0){ + #if(nrow(selection2) == 0){ + if(length(selection2) == 0){ runTables <- FALSE shiny::showNotification('No results for section 2') } @@ -215,8 +220,10 @@ characterizationCohortComparisonServer <- function( resultTable <- characterizatonGetCohortComparisonData( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - targetId1 = selection1$charCohortId[1], - targetId2 = selection2$charCohortId[1], + #targetId1 = selection1$charCohortId[1], + #targetId2 = selection2$charCohortId[1], + targetId1 = selection1, + targetId2 = selection2, databaseId = input$databaseId, minThreshold = 0.01, addSMD = T @@ -225,7 +232,8 @@ characterizationCohortComparisonServer <- function( countTable <- characterizatonGetCohortCounts( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - targetIds = c(selection1$charCohortId[1],selection2$charCohortId[1]), + #targetIds = c(selection1$charCohortId[1],selection2$charCohortId[1]), + targetIds = c(selection1,selection2), targetNames = c( subTargetNames[which(subTargetIds == subTargetId())], # modified names(comparatorGroups())[which(input$comparatorId== comparatorGroups())] @@ -236,7 +244,8 @@ characterizationCohortComparisonServer <- function( continuousTable <- characterizatonGetCohortComparisonDataContinuous( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - targetIds = c(selection1$charCohortId[1],selection2$charCohortId[1]), + #targetIds = c(selection1$charCohortId[1],selection2$charCohortId[1]), + targetIds = c(selection1,selection2), databaseIds = rep(input$databaseId,2) ) @@ -463,13 +472,29 @@ characterizatonGetCohortCounts <- function( start <- Sys.time() result <- connectionHandler$queryDb( sql = " -select cc.* +select distinct cc.target_cohort_id as cohort_definition_id, + cc.min_prior_observation, + cc.row_count, + cc.person_count from @schema.@c_table_prefixcohort_counts cc + where + cc.target_cohort_id in (@target_ids) + and cc.cohort_type = 'Target' + AND cc.database_id = '@database_id' + + union - where cc.cohort_definition_id in (@target_ids) - and cc.database_id = '@database_id' - and cc.run_id = 1 + select cc.outcome_cohort_id as cohort_definition_id, + cc.min_prior_observation, + cc.row_count, + cc.person_count + from + @schema.@c_table_prefixcohort_counts cc + where + cc.outcome_cohort_id in (@target_ids) + and cc.cohort_type = 'Outcome' + AND cc.database_id = '@database_id' ; ", schema = resultDatabaseSettings$schema, @@ -493,6 +518,7 @@ select cc.* result <- result %>% dplyr::select( 'selection', 'cohortName', + 'minPriorObservation', 'rowCount', 'personCount' ) @@ -526,22 +552,33 @@ characterizatonGetCohortData <- function( databaseId = databaseIds ) + # + shiny::incProgress(2/4, detail = paste("Extracting data")) sql <- paste0( paste0( paste0( - "select ref.covariate_name, cov.* from + "select ref.covariate_name, + s.min_prior_observation, + cov.target_cohort_id as cohort_definition_id, + cov.* from @schema.@c_table_prefixCOVARIATES cov inner join @schema.@c_table_prefixcovariate_ref ref on cov.covariate_id = ref.covariate_id - and cov.run_id = ref.run_id + and cov.setting_id = ref.setting_id and cov.database_id = ref.database_id + inner join + @schema.@c_table_prefixsettings s + on s.database_id = cov.database_id + and s.setting_id = cov.setting_id - where cov.cohort_definition_id = @target_id",1:length(targetIds), - " and cov.database_id = '@database_id",1:length(targetIds),"' - and cov.average_value >= @min_threshold" + where + (cov.target_cohort_id = @target_id",1:length(targetIds), + " and cov.cohort_type = 'Target') + AND cov.database_id = '@database_id",1:length(targetIds),"' + AND cov.average_value >= @min_threshold" ), collapse = ' union ' ),';' ) @@ -566,7 +603,7 @@ characterizatonGetCohortData <- function( # pivot result <- tidyr::pivot_wider( data = res, - id_cols = c('covariateName', 'covariateId'), + id_cols = c('covariateName', 'covariateId','minPriorObservation'), names_from = 'type', values_from = c('sumValue', 'averageValue'), values_fn = mean, @@ -618,16 +655,26 @@ characterizatonGetCohortComparisonDataContinuous <- function( sql <- paste0( paste0( paste0( - "select ref.covariate_name, cov.* from + "select ref.covariate_name, + s.min_prior_observation, + cov.target_cohort_id as cohort_definition_id, + cov.* from @schema.@c_table_prefixCOVARIATES_continuous cov inner join @schema.@c_table_prefixcovariate_ref ref on cov.covariate_id = ref.covariate_id - and cov.run_id = ref.run_id + and cov.setting_id = ref.setting_id and cov.database_id = ref.database_id + inner join + @schema.@c_table_prefixsettings s + on cov.setting_id = s.setting_id + and cov.database_id = s.database_id - where cov.cohort_definition_id = @target_id",1:length(targetIds), - " and cov.database_id = '@database_id",1:length(targetIds),"'" + where + (cov.target_cohort_id = @target_id",1:length(targetIds), + " and cov.cohort_type = 'Target') + AND cov.database_id = '@database_id",1:length(targetIds),"' + " ), collapse = ' union ' ),';' ) @@ -651,7 +698,7 @@ characterizatonGetCohortComparisonDataContinuous <- function( # pivot result <- tidyr::pivot_wider( data = res, - id_cols = c('covariateName', 'covariateId'), + id_cols = c('covariateName', 'covariateId','minPriorObservation'), names_from = 'type', values_from = c('countValue', 'averageValue', 'standardDeviation', 'medianValue','minValue', 'maxValue', 'p25Value','p75Value'), values_fn = mean, @@ -679,16 +726,27 @@ characterizatonGetCohortComparisonDataContinuous <- function( characterizationGetCohortsInputs <- function( connectionHandler, - resultDatabaseSettings + resultDatabaseSettings, + targetId # reactive ) { - sql <- 'select d.database_id, d.cdm_source_abbreviation as database_name - from @schema.@database_table d;' + sql <- "select distinct + d.database_id, d.cdm_source_abbreviation as database_name + from @schema.@database_table d + + inner join + @schema.@c_table_prefixcohort_details cd + on d.database_id = cd.database_id + where cd.target_cohort_id = @target_id + and cd.cohort_type = 'Target' + ;" database <- connectionHandler$queryDb( sql = sql, schema = resultDatabaseSettings$schema, - database_table = resultDatabaseSettings$databaseTable + database_table = resultDatabaseSettings$databaseTable, + c_table_prefix = resultDatabaseSettings$cTablePrefix, + target_id = targetId() ) databaseIds <- database$databaseId names(databaseIds) <- database$databaseName diff --git a/R/characterization-database.R b/R/characterization-database.R index ecda5ca6..3f007f38 100644 --- a/R/characterization-database.R +++ b/R/characterization-database.R @@ -61,15 +61,13 @@ characterizationDatabaseComparisonServer <- function( id, function(input, output, session) { - # TODO replace this with database input - inputVals <- characterizationGetCohortsInputs( + # TODO react to subTargetId + inputVals <- shiny::reactive({ + characterizationGetCohortsInputs( connectionHandler, - resultDatabaseSettings - ) - - children <- shiny::reactive({ - characterizationGetChildren(options, parentIndex()) - }) + resultDatabaseSettings, + targetId = subTargetId + )}) output$inputs <- shiny::renderUI({ @@ -77,8 +75,8 @@ characterizationDatabaseComparisonServer <- function( shiny::selectInput( inputId = session$ns('databaseIds'), label = 'Databases: ', - choices = inputVals$databaseIds, - selected = inputVals$databaseIds[1], + choices = inputVals()$databaseIds, + selected = inputVals()$databaseIds[1], multiple = T ), @@ -122,7 +120,7 @@ characterizationDatabaseComparisonServer <- function( } selectedDatabases <- paste0( - names(inputVals$databaseIds)[which(inputVals$databaseIds %in% input$databaseIds)], + names(inputVals()$databaseIds)[which(inputVals()$databaseIds %in% input$databaseIds)], collapse = ',' ) @@ -133,15 +131,15 @@ characterizationDatabaseComparisonServer <- function( ) ) - selectedChildChar <- options[[parentIndex()]]$children[[which(subTargetId() == children())]]$charIds - + #get results - if(sum(selectedChildChar$databaseId %in% input$databaseIds) > 0){ + #if(sum(selectedChildChar$databaseId %in% input$databaseIds) > 0){ + if(length(input$databaseIds) > 0){ result <- characterizatonGetDatabaseComparisonData( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - targetIds = selectedChildChar$charCohortId[selectedChildChar$databaseId %in% input$databaseIds], - databaseIds = selectedChildChar$databaseId[selectedChildChar$databaseId %in% input$databaseIds], + targetIds = subTargetId(), + databaseIds = input$databaseIds, minThreshold = input$minThreshold ) databaseNames <- result$databaseNames diff --git a/R/characterization-main.R b/R/characterization-main.R index 421e2904..1f32b6d2 100644 --- a/R/characterization-main.R +++ b/R/characterization-main.R @@ -94,12 +94,24 @@ characterizationServer <- function( id, function(input, output, session) { + + # this function checks tables exist for the tabs + # and returns the tabs that should be displayed + # as the tables exist + charTypes <- getCharacterizationTypes( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings + ) + #================================================ # GETTING OPTIONS FOR INPTUS #================================================ + #TODO add time-to-event and dechal-rechal options options <- characterizationGetOptions( connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings + resultDatabaseSettings = resultDatabaseSettings, + includeAggregate = "Risk Factor" %in% charTypes$subPanel, + includeIncidence = "Incidence Results" %in% charTypes$subPanel ) #================================================ @@ -246,14 +258,7 @@ characterizationServer <- function( #================================================ # CREATE TABS BASED ON RESULTS TABLES #================================================ - # this function checks tables exist for the tabs - # and returns the tabs that should be displayed - # as the tables exist - charTypes <- getCharacterizationTypes( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - + # MAIN PANELS #first populate the mainPanel typesMainPanel <- list( @@ -594,7 +599,9 @@ getCharacterizationTypes <- function( characterizationGetOptions <- function( connectionHandler, - resultDatabaseSettings + resultDatabaseSettings, + includeAggregate, + includeIncidence ){ # get cohorts @@ -606,29 +613,13 @@ characterizationGetOptions <- function( ) # database_id needed for old results but not for new ones + # TODO - add tte and decha rechal? cohorts <- connectionHandler$queryDb( sql = " -select database_id, cohort_definition_id as char_cohort_id, outcome_cohort_id as cohort_definition_id, cohort_type -from @schema.@c_table_prefixcohort_details -where cohort_type = 'O' - -union - -select database_id, cohort_definition_id as char_cohort_id, outcome_cohort_id as cohort_definition_id, cohort_type -from @schema.@c_table_prefixcohort_details -where cohort_type = 'Oall' - -union -select database_id, cohort_definition_id as char_cohort_id, target_cohort_id as cohort_definition_id, cohort_type +select distinct database_id, target_cohort_id as cohort_definition_id, cohort_type from @schema.@c_table_prefixcohort_details -where cohort_type = 'T' - -union - -select database_id, cohort_definition_id as char_cohort_id, target_cohort_id as cohort_definition_id, cohort_type -from @schema.@c_table_prefixcohort_details -where cohort_type = 'Tall' +where cohort_type = 'Target' ;", schema = resultDatabaseSettings$schema, @@ -640,17 +631,24 @@ TnOs <- connectionHandler$queryDb( select distinct temp.*, c.cohort_name from -(select distinct +( +{@include_aggregate} ? { +select distinct target_cohort_id, outcome_cohort_id from @schema.@c_table_prefixcohort_details where cohort_type = 'TnO' +{@include_incidence} ? { union +} +} + +{@include_incidence} ? { select * from @schema.@ci_table_prefixcohorts_lookup - +} ) temp inner join @schema.@cg_table_prefixcohort_definition c @@ -659,7 +657,9 @@ on temp.outcome_cohort_id = c.cohort_definition_id schema = resultDatabaseSettings$schema, c_table_prefix = resultDatabaseSettings$cTablePrefix, cg_table_prefix = resultDatabaseSettings$cgTablePrefix, - ci_table_prefix = resultDatabaseSettings$incidenceTablePrefix + ci_table_prefix = resultDatabaseSettings$incidenceTablePrefix, + include_incidence = includeIncidence, + include_aggregate = includeAggregate ) # fix backwards compatability cg$subsetParent[is.na(cg$isSubset)] <- cg$cohortDefinitionId @@ -675,7 +675,6 @@ results <- lapply(parents, function(id){ list( subsetName = cg$cohortName[cg$cohortDefinitionId == sid], subsetId = sid, - charIds = cohorts[cohorts$cohortDefinitionId == sid,], outcomeIds = unique(TnOs$outcomeCohortId[TnOs$targetCohortId == sid]), outcomeNames = unique(TnOs$cohortName[TnOs$targetCohortId == sid]) # add outcomes from case exposures diff --git a/R/characterization-riskFactors.R b/R/characterization-riskFactors.R index cf2b83e6..da858cd5 100644 --- a/R/characterization-riskFactors.R +++ b/R/characterization-riskFactors.R @@ -80,10 +80,10 @@ characterizationRiskFactorServer <- function( ), shiny::selectInput( - inputId = session$ns('tarId'), + inputId = session$ns('tarInd'), label = 'Time-at-risk: ', - choices = options()$tarIds, - selected = options()$tarIds[1], + choices = options()$tarInds, + selected = options()$tarInds[1], multiple = F ), @@ -103,7 +103,7 @@ characterizationRiskFactorServer <- function( targetId = targetId(), outcomeId = outcomeId(), databaseId = input$databaseId, - timeAtRiskId = input$tarId + tar = options()$tarList[[which(options()$tarInds == input$tarInd)]] ) binTableOutputs <- resultTableServer( @@ -134,58 +134,63 @@ characterizationGetRiskFactorData <- function( targetId, outcomeId, databaseId, - timeAtRiskId + tar ){ shiny::withProgress(message = 'Getting risk factor data', value = 0, { shiny::incProgress(1/4, detail = paste("Extracting ids")) - sql <- "SELECT distinct - cd.cohort_definition_id, cd.cohort_type, - cc.person_count as N + sql <- "SELECT distinct setting_id from - @schema.@c_table_prefixcohort_details cd - left join - @schema.@c_table_prefixcohort_counts cc - on cd.run_id = cc.run_id - and cd.database_id = cc.database_id - and cd.cohort_definition_id = cc.cohort_definition_id + @schema.@c_table_prefixsettings + where database_id = '@database_id' + and risk_window_start = @risk_window_start + and risk_window_end = @risk_window_end + and start_anchor = '@start_anchor' + and end_anchor = '@end_anchor' - where cd.target_cohort_id = @target_id - and cd.outcome_cohort_id in (0, @outcome_id) - and cd.database_id = '@database_id' - and cd.time_at_risk_id in (0, @time_at_risk_id) - and cd.cohort_type in ('T','TnO', 'TnOprior') + union + + SELECT distinct setting_id + from + @schema.@c_table_prefixsettings + where database_id = '@database_id' + and risk_window_start is NULL ;" ids <- connectionHandler$queryDb( sql = sql, schema = resultDatabaseSettings$schema, c_table_prefix = resultDatabaseSettings$cTablePrefix, - target_id = targetId, - outcome_id = outcomeId, database_id = databaseId, - time_at_risk_id = timeAtRiskId + risk_window_start = tar$riskWindowStart, + start_anchor = tar$startAnchor, + risk_window_end = tar$riskWindowEnd, + end_anchor = tar$endAnchor ) shiny::incProgress(2/4, detail = paste("Extracting binary")) - sql <- "SELECT distinct cov.cohort_definition_id, cr.covariate_name, + sql <- "SELECT distinct cov.cohort_type, cr.covariate_name, s.min_prior_observation, s.outcome_washout_days, cov.covariate_id, cov.sum_value, cov.average_value from @schema.@c_table_prefixcovariates cov inner join @schema.@c_table_prefixcovariate_ref cr - on cov.run_id = cr.run_id and + on cov.setting_id = cr.setting_id and cov.database_id = cr.database_id and cov.covariate_id = cr.covariate_id inner join @schema.@c_table_prefixsettings s - on cov.run_id = s.run_id + on cov.setting_id = s.setting_id and cov.database_id = s.database_id - where cov.cohort_definition_id in (@ids) + where + cov.target_cohort_id = @target_id + and cov.outcome_cohort_id in (0,@outcome_id) + and cov.cohort_type in ('Target','TnO', 'TnOprior') and cov.database_id = '@database_id' + and cov.setting_id in (@setting_ids) and cr.analysis_id not in (109, 110, 217, 218, 305, 417, 418, 505, 605, 713, 805, 926, 927) ;" @@ -193,19 +198,20 @@ characterizationGetRiskFactorData <- function( sql = sql, schema = resultDatabaseSettings$schema, c_table_prefix = resultDatabaseSettings$cTablePrefix, - ids = paste0(unique(ids$cohortDefinitionId), collapse = ','), - database_id = databaseId + target_id = targetId, + outcome_id = outcomeId, + database_id = databaseId, + setting_ids = paste0(ids$settingId, collapse=',') ) # now process into table binary <- riskFactorTable( - data = binary, - ids = ids + data = binary ) shiny::incProgress(3/4, detail = paste("Extracting continuous")) - sql <- "SELECT distinct cov.cohort_definition_id, cr.covariate_name, + sql <- "SELECT distinct cov.cohort_type, cr.covariate_name, s.min_prior_observation, s.outcome_washout_days,cov.covariate_id, cov.count_value, cov.min_value, cov.max_value, cov.average_value, cov.standard_deviation, cov.median_value, cov.p_10_value, @@ -213,17 +219,19 @@ characterizationGetRiskFactorData <- function( from @schema.@c_table_prefixcovariates_continuous cov inner join @schema.@c_table_prefixcovariate_ref cr - on cov.run_id = cr.run_id and + on cov.setting_id = cr.setting_id and cov.database_id = cr.database_id and cov.covariate_id = cr.covariate_id inner join @schema.@c_table_prefixsettings s - on cov.run_id = s.run_id + on cov.setting_id = s.setting_id and cov.database_id = s.database_id - - where cov.cohort_definition_id in (@ids) + where cov.target_cohort_id = @target_id + and cov.outcome_cohort_id = @outcome_id + and cov.cohort_type in ('Target','TnO', 'TnOprior') and cov.database_id = '@database_id' + and cov.setting_id in (@setting_ids) and cr.analysis_id not in (109, 110, 217, 218, 305, 417, 418, 505, 605, 713, 805, 926, 927) ;" @@ -232,13 +240,14 @@ characterizationGetRiskFactorData <- function( sql = sql, schema = resultDatabaseSettings$schema, c_table_prefix = resultDatabaseSettings$cTablePrefix, - ids = paste0(ids$cohortDefinitionId, collapse = ','), - database_id = databaseId + target_id = targetId, + outcome_id = outcomeId, + database_id = databaseId, + setting_ids = paste0(ids$settingId, collapse=',') ) continuous <- riskFactorContinuousTable( - data = continuous, - ids = ids + data = continuous ) shiny::incProgress(4/4, detail = paste("Done")) @@ -256,67 +265,74 @@ characterizationGetRiskFactorData <- function( # now process into table riskFactorTable <- function( - data, - ids + data ){ data <- unique(data) - caseId <- ids$cohortDefinitionId[ids$cohortType == 'TnO'] - if(length(caseId ) == 0){ - caseId <- -1 - } - caseData <- data %>% - dplyr::filter(.data$cohortDefinitionId == !!caseId) %>% - dplyr::select(-"cohortDefinitionId") - - casecounts <- caseData %>% - dplyr::mutate(N = .data$sumValue/.data$averageValue) %>% - dplyr::select('minPriorObservation', 'outcomeWashoutDays', 'N') %>% - dplyr::group_by(.data$minPriorObservation, .data$outcomeWashoutDays) %>% - dplyr::summarise(caseN = round(max(.data$N))) + outcomeWashoutDays <- unique(data$outcomeWashoutDays) + outcomeWashoutDays <- outcomeWashoutDays[!is.na(outcomeWashoutDays)] - #write.csv(caseData, '/Users/jreps/Documents/caseData.csv') - - allId <- ids$cohortDefinitionId[ids$cohortType == 'T'] allData <- data %>% - dplyr::filter(.data$cohortDefinitionId == !!allId) %>% - dplyr::select(-"cohortDefinitionId") + dplyr::filter(.data$cohortType == 'Target') %>% + dplyr::select(-"cohortType", -"outcomeWashoutDays") allcounts <- allData %>% dplyr::mutate(N = .data$sumValue/.data$averageValue) %>% - dplyr::select('minPriorObservation', 'outcomeWashoutDays', 'N') %>% - dplyr::group_by(.data$minPriorObservation, .data$outcomeWashoutDays) %>% + dplyr::select('minPriorObservation', 'N') %>% + dplyr::group_by(.data$minPriorObservation) %>% dplyr::summarise(N = round(max(.data$N))) - excludeId <- ids$cohortDefinitionId[ids$cohortType == 'TnOprior'] - if(length(excludeId) == 0){ - excludeId <- -1 + getN <- function(priorObs){ + sapply(priorObs, function(x){ + allcounts$N[allcounts$minPriorObservation == x] + }) } + + completeData <- c() + for(outcomeWashoutDay in outcomeWashoutDays){ + caseData <- data %>% + dplyr::filter( + .data$cohortType == 'TnO' & + .data$outcomeWashoutDays == !!outcomeWashoutDay + ) %>% + dplyr::select(-"cohortType") + + casecounts <- caseData %>% + dplyr::mutate(N = .data$sumValue/.data$averageValue) %>% + dplyr::select('minPriorObservation', 'N') %>% + dplyr::group_by(.data$minPriorObservation) %>% + dplyr::summarise(caseN = round(max(.data$N))) + excludeData <- data %>% - dplyr::filter(.data$cohortDefinitionId == !!excludeId) %>% - dplyr::select(-"cohortDefinitionId") + dplyr::filter( + .data$cohortType == 'TnOprior' & + .data$outcomeWashoutDays == !!outcomeWashoutDay + ) %>% + dplyr::select(-"cohortType") + excludecounts <- excludeData %>% dplyr::mutate(N = .data$sumValue/.data$averageValue) %>% - dplyr::select('minPriorObservation', 'outcomeWashoutDays', 'N') %>% - dplyr::group_by(.data$minPriorObservation, .data$outcomeWashoutDays) %>% - dplyr::summarise(exclude_N = round(max(.data$N))) - + dplyr::select('minPriorObservation', 'N') %>% + dplyr::group_by(.data$minPriorObservation) %>% + dplyr::summarise(exclude_N = round(max(.data$N, na.rm = T))) if(nrow(excludeData) > 0 ){ - colnamesInclude <- !colnames(excludeData) %in% c('covariateId', 'covariateName', 'minPriorObservation', 'outcomeWashoutDays') + colnamesInclude <- !colnames(excludeData) %in% c('covariateId', 'covariateName', 'minPriorObservation') colnames(excludeData)[colnamesInclude] <- paste0('exclude_',colnames(excludeData)[colnamesInclude]) # if prior Os then exclude from T allData <- allData %>% - dplyr::left_join(excludeData, by = c('covariateId', 'covariateName', 'minPriorObservation', 'outcomeWashoutDays')) %>% - dplyr::left_join( # add N per washout/min obs + dplyr::left_join( + excludeData, + by = c('covariateId', 'covariateName', 'minPriorObservation')) %>% + dplyr::inner_join( # add N per washout/min obs allcounts, - by = c('minPriorObservation', 'outcomeWashoutDays') - ) %>% - dplyr::left_join( # add N per washout/min obs + by = c('minPriorObservation') + ) %>% + dplyr::inner_join( # add N per washout/min obs excludecounts, - by = c('minPriorObservation', 'outcomeWashoutDays') + by = c('minPriorObservation') ) %>% dplyr::mutate_if(is.numeric,dplyr::coalesce,0) %>% dplyr::mutate( # add exclude N per washout/min obs @@ -326,7 +342,18 @@ riskFactorTable <- function( dplyr::mutate( N = .data$N-.data$exclude_N ) %>% - dplyr::select("covariateId","covariateName","sumValue","averageValue", "N", 'minPriorObservation', 'outcomeWashoutDays') + dplyr::select("covariateId","covariateName","sumValue","averageValue", "N", 'minPriorObservation') + + allcounts <- allData %>% + dplyr::select('minPriorObservation', 'N') %>% + dplyr::group_by(.data$minPriorObservation) %>% + dplyr::summarise(N = round(max(.data$N))) + + getN <- function(priorObs){ + sapply(priorObs, function(x){ + allcounts$N[allcounts$minPriorObservation == x] + }) + } } @@ -336,14 +363,22 @@ riskFactorTable <- function( caseSumValue = .data$sumValue, caseAverageValue = .data$averageValue ) %>% - dplyr::select("covariateId","covariateName","caseSumValue","caseAverageValue", 'minPriorObservation', 'outcomeWashoutDays') + dplyr::select("covariateId","covariateName","caseSumValue","caseAverageValue", 'minPriorObservation') # join with cases allData <- allData %>% - dplyr::full_join(caseData, by = c('covariateId', 'covariateName', 'minPriorObservation', 'outcomeWashoutDays')) %>% + dplyr::full_join(caseData, + by = c('covariateId', 'covariateName', 'minPriorObservation')) %>% dplyr::left_join( casecounts, - by = c('minPriorObservation', 'outcomeWashoutDays') + by = c('minPriorObservation') + ) %>% + dplyr::mutate( + N = ifelse( + is.na(.data$N), + getN(.data$minPriorObservation), + .data$N + ) ) %>% dplyr::mutate_if(is.numeric,dplyr::coalesce,0) %>% dplyr::mutate( @@ -364,7 +399,7 @@ riskFactorTable <- function( ) %>% dplyr::select( "covariateId","covariateName", - 'minPriorObservation', 'outcomeWashoutDays', + 'minPriorObservation', "caseSumValue","caseAverageValue", "nonCaseSumValue","nonCaseAverageValue" ,"nonCaseN", "caseN", "N" @@ -384,46 +419,49 @@ riskFactorTable <- function( ) %>% dplyr::select(-"meanDiff",-"std1", -"std2", -"N",-"caseN", -"nonCaseN") - #write.csv(allData, '/Users/jreps/Documents/finalData.csv') - - } else{ + # add outcomewashout back here allData <- allData %>% + dplyr::mutate( + outcomeWashoutDays = !!outcomeWashoutDay + ) + + completeData <- rbind(allData, completeData) + + } + + } # end outcomeWashoutDays loop + + if(nrow(completeData) == 0){ + completeData <- allData %>% dplyr::mutate( nonCaseSumValue = .data$sumValue, nonCaseAverageValue = .data$averageValue ) %>% dplyr::select( "covariateId","covariateName", - 'minPriorObservation', 'outcomeWashoutDays', + 'minPriorObservation', "nonCaseSumValue","nonCaseAverageValue" ) } - - return(unique(allData)) + return(unique(completeData)) } riskFactorContinuousTable <- function( - data, - ids # have N in them + data ){ data <- unique(data) - caseId <- ids$cohortDefinitionId[ids$cohortType == 'TnO'] - if(length(caseId ) == 0){ - caseId <- -1 - } caseData <- data %>% - dplyr::filter(.data$cohortDefinitionId == !!caseId) %>% - dplyr::select(-"cohortDefinitionId") + dplyr::filter(.data$cohortType == 'TnO') %>% + dplyr::select(-"cohortType") - allId <- ids$cohortDefinitionId[ids$cohortType == 'T'] allData <- data %>% - dplyr::filter(.data$cohortDefinitionId == !!allId) %>% - dplyr::select(-"cohortDefinitionId") + dplyr::filter(.data$cohortType == 'Target') %>% + dplyr::select(-"cohortType", -"outcomeWashoutDays") if(nrow(caseData) > 0){ @@ -448,7 +486,7 @@ riskFactorContinuousTable <- function( # join with cases allData <- allData %>% - dplyr::full_join(caseData, by = c('covariateId', 'covariateName', 'minPriorObservation', 'outcomeWashoutDays')) %>% + dplyr::full_join(caseData, by = c('covariateId', 'covariateName', 'minPriorObservation')) %>% dplyr::mutate( targetCountValue = .data$countValue, targetAverageValue = .data$averageValue, From 3b498b4ec6bbcd9d76c5f0555ffa64f218d0d381 Mon Sep 17 00:00:00 2001 From: jreps Date: Mon, 3 Jun 2024 13:41:29 -0400 Subject: [PATCH 15/64] Update characterization-riskFactors.R --- R/characterization-riskFactors.R | 3 +++ 1 file changed, 3 insertions(+) diff --git a/R/characterization-riskFactors.R b/R/characterization-riskFactors.R index da858cd5..ab9db3a4 100644 --- a/R/characterization-riskFactors.R +++ b/R/characterization-riskFactors.R @@ -269,6 +269,9 @@ riskFactorTable <- function( ){ data <- unique(data) + if(nrow(data) == 0){ + return(data) + } outcomeWashoutDays <- unique(data$outcomeWashoutDays) outcomeWashoutDays <- outcomeWashoutDays[!is.na(outcomeWashoutDays)] From 5d2a28c2f5b839f969e98279bf1907de5b895d9b Mon Sep 17 00:00:00 2001 From: Nathan Hall Date: Mon, 3 Jun 2024 14:56:47 -0400 Subject: [PATCH 16/64] updating bug fixes and column cleanliness --- R/characterization-caseSeries.R | 153 +++++++++- R/characterization-cohorts.R | 101 +++++-- R/characterization-database.R | 2 +- R/characterization-dechallengeRechallenge.R | 182 +++++++++++- R/characterization-incidence.R | 69 ++++- R/characterization-riskFactors.R | 177 ++++++++++-- R/characterization-timeToEvent.R | 4 +- R/cohort-generator-main.R | 291 ++++++++++++-------- R/datasources-main.R | 3 + man/characterizationIncidenceServer.Rd | 2 +- man/reportServer.Rd | 2 +- 11 files changed, 800 insertions(+), 186 deletions(-) diff --git a/R/characterization-caseSeries.R b/R/characterization-caseSeries.R index 866660f9..6232cd1f 100644 --- a/R/characterization-caseSeries.R +++ b/R/characterization-caseSeries.R @@ -109,14 +109,14 @@ characterizationCaseSeriesServer <- function( binTableOutputs <- resultTableServer( id = "binaryTable", df = allData$binary, - colDefsInput = colDefs(), # function below + colDefsInput = colDefsBinary(), # function below addActions = NULL ) conTableOutputs <- resultTableServer( id = "continuousTable", df = allData$continuous, - colDefsInput = colDefs(), # function below + colDefsInput = colDefsContinuous(), # function below addActions = NULL ) @@ -371,29 +371,40 @@ caseSeriesTable <- function( return(allResults) } -colDefs <- function(){ +colDefsBinary <- function(){ result <- list( covariateName = reactable::colDef( - name = "Covariate Name", + header = withTooltip("Covariate Name", + "Name of the covariate"), filterable = T ), covariateId = reactable::colDef( show = F ), minPriorObservation = reactable::colDef( - name = "Minimum prior observation" + header = withTooltip("Min Prior Observation", + "Minimum prior observation time (days)"), + filterable = T ), outcomeWashoutDays = reactable::colDef( - name = "outcome washout days" + header = withTooltip("Outcome Washout Days", + "Number of days for the outcome washout"), + filterable = T ), casePostOutcomeDuration = reactable::colDef( - name = "Time after outcome we look for covariate" + header = withTooltip("Days Post-outcome Covariate Window", + "Number of days after the outcome we look for the covariate"), + filterable = T ), casePreTargetDuration = reactable::colDef( - name = "Time before exposure we look for covariate" + header = withTooltip("Days Pre-exposure Covariate Window", + "Number of days before the exposure we look for the covariate"), + filterable = T ), sumValueBefore = reactable::colDef( - name = "Number of cases with feature before exposure", + header = withTooltip("# Cases with Feature Pre-exposure", + "Number of cases with the covariate prior to exposure"), + filterable = T, format = reactable::colFormat(digits = 2, percent = F), cell = function(value) { if(is.null(value)){return('< min threshold')} @@ -402,11 +413,15 @@ colDefs <- function(){ } ), averageValueBefore = reactable::colDef( - name = "% of cases with feature before exposure", + header = withTooltip("% of Cases with Feature Pre-exposure", + "Percent of cases with the covariate prior to exposure"), + filterable = T, format = reactable::colFormat(digits = 2, percent = T) ), sumValueDuring = reactable::colDef( - name = "Number of cases with feature between exposure and outcome", + header = withTooltip("# of Cases with Feature Between Exposure & Outcome", + "Number of cases with the covariate between the exposure and outcome"), + filterable = T, format = reactable::colFormat(digits = 2, percent = F), cell = function(value) { if(is.null(value)){return('< min threshold')} @@ -415,11 +430,15 @@ colDefs <- function(){ } ), averageValueDuring = reactable::colDef( - name = "% of cases with feature between exposure and outcome", + header = withTooltip("% of Cases with Feature Between Exposure & Outcome", + "Percent of cases with the covariate between the exposure and outcome"), + filterable = T, format = reactable::colFormat(digits = 2, percent = T) ), sumValueAfter = reactable::colDef( - name = "Number of cases with feature after outcome", + header = withTooltip("# of Cases with Feautre Post-outcome", + "Number of cases with the covariate after the outcome"), + filterable = T, format = reactable::colFormat(digits = 2, percent = F), cell = function(value) { if(is.null(value)){return('< min threshold')} @@ -428,7 +447,9 @@ colDefs <- function(){ } ), averageValueAfter = reactable::colDef( - name = "% of cases with feature after outcome", + header = withTooltip("% of Cases with Feature Post-outcome", + "Percent of cases with the covariate after the outcome"), + filterable = T, format = reactable::colFormat(digits = 2, percent = T) ), @@ -449,3 +470,107 @@ colDefs <- function(){ return(result) } +colDefsContinuous <- function(){ + result <- list( + cohortDefinitionId = reactable::colDef( + header = withTooltip("Cohort ID", + "Unique identifier of the cohort"), + filterable = T + ), + type = reactable::colDef( + header = withTooltip("Time of Cases Relative to Index", + "Time period relative to index date for cases for the covariate"), + filterable = T + ), + covariateName = reactable::colDef( + header = withTooltip("Covariate Name", + "Name of the covariate"), + filterable = T + ), + covariateId = reactable::colDef( + show = F + ), + minPriorObservation = reactable::colDef( + header = withTooltip("Min Prior Observation", + "Minimum prior observation time (days)"), + filterable = T + ), + outcomeWashoutDays = reactable::colDef( + header = withTooltip("Outcome Washout Days", + "Number of days for the outcome washout"), + filterable = T + ), + casePostOutcomeDuration = reactable::colDef( + header = withTooltip("Days Post-outcome Covariate Window", + "Number of days after the outcome we look for the covariate"), + filterable = T + ), + casePreTargetDuration = reactable::colDef( + header = withTooltip("Days Pre-exposure Covariate Window", + "Number of days before the exposure we look for the covariate"), + filterable = T + ), + countValue = reactable::colDef( + header = withTooltip("# Cases with Feature", + "Number of cases with the covariate"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + minValue = reactable::colDef( + header = withTooltip("Min Value", + "Minimum value of the covariate"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + maxValue = reactable::colDef( + header = withTooltip("Max Value", + "Maximum value of the covariate"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + averageValue = reactable::colDef( + header = withTooltip("Average Value", + "Average value of the covariate"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + standardDeviation = reactable::colDef( + header = withTooltip("SD", + "Standard deviation of the covariate"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + medianValue = reactable::colDef( + header = withTooltip("Median Value", + "Median value of the covariate"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + p10Value = reactable::colDef( + header = withTooltip("10th %tile", + "10th percentile value of the covariate"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + p25Value = reactable::colDef( + header = withTooltip("25th %tile", + "25th percentile value of the covariate"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + p75Value = reactable::colDef( + header = withTooltip("75th %tile", + "75th percentile value of the covariate"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + p90Value = reactable::colDef( + header = withTooltip("90th %tile", + "90th percentile value of the covariate"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ) + ) + return(result) +} + diff --git a/R/characterization-cohorts.R b/R/characterization-cohorts.R index 8f71e506..da28db42 100644 --- a/R/characterization-cohorts.R +++ b/R/characterization-cohorts.R @@ -53,7 +53,7 @@ characterizationCohortComparisonViewer <- function(id) { ), shiny::tabPanel( title = 'Continuous', - resultTableViewer(id = ns('continuousTable'), boxTitle = 'continuous') + resultTableViewer(id = ns('continuousTable'), boxTitle = 'Continuous') ) ) @@ -99,7 +99,9 @@ characterizationCohortComparisonServer <- function( size = 10, liveSearchStyle = "contains", liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 + virtualScroll = 50, + #container = "div.tabbable", + dropupAuto = FALSE ) ), @@ -233,6 +235,32 @@ characterizationCohortComparisonServer <- function( databaseId = input$databaseId ) + characteriationCountTableColDefs <- function(){ + result <- list( + selection = reactable::colDef( + header = withTooltip("Selected Cohort", + "Which cohort of the above selections"), + filterable = T + ), + covariateName = reactable::colDef( + header = withTooltip("Covariate Name", + "Name of the covariate"), + filterable = T + ), + rowCount = reactable::colDef( + header = withTooltip("Record Count", + "Count of the number of records"), + filterable = T + ), + personCount = reactable::colDef( + header = withTooltip("Person Count", + "Count of the number of persons"), + filterable = T + ) + ) + return(result) + } + continuousTable <- characterizatonGetCohortComparisonDataContinuous( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, @@ -255,20 +283,21 @@ characterizationCohortComparisonServer <- function( resultTableServer( id = 'countTable', df = countTable, - colDefsInput = NULL - )} else{ - resultTableServer( - id = 'mainTable', - df = data.frame(), - colDefsInput = columns - ) - - resultTableServer( - id = 'countTable', - df = data.frame(), - colDefsInput = NULL - ) - } + colDefsInput = characteriationCountTableColDefs() + )} + # else{ + # resultTableServer( + # id = 'mainTable', + # df = data.frame(), + # colDefsInput = columns + # ) + # + # resultTableServer( + # id = 'countTable', + # df = data.frame(), + # colDefsInput = NULL + # ) + # } }) return(invisible(NULL)) @@ -424,6 +453,46 @@ characterizationCohortsColumnsContinuous <- function(x){ header = withTooltip("absSMD", "Absolute standardized mean difference"), format = reactable::colFormat(digits = 3) + ), + minValue_2 = reactable::colDef( + header = withTooltip("Second Min Value", + "Minimum value of the second selected cohort"), + format = reactable::colFormat(digits = 3) + ), + minValue_1 = reactable::colDef( + header = withTooltip("First Min Value", + "Minimum value of the first selected cohort"), + format = reactable::colFormat(digits = 3) + ), + maxValue_2 = reactable::colDef( + header = withTooltip("Second Max Value", + "Maximum value of the second selected cohort"), + format = reactable::colFormat(digits = 3) + ), + maxValue_1 = reactable::colDef( + header = withTooltip("First Max Value", + "Maximum value of the first selected cohort"), + format = reactable::colFormat(digits = 3) + ), + p25Value_2 = reactable::colDef( + header = withTooltip("Second 25th %tile", + "25th percentile value of the second selected cohort"), + format = reactable::colFormat(digits = 3) + ), + p25Value_1 = reactable::colDef( + header = withTooltip("First 25th %tile", + "25th percentile value of the first selected cohort"), + format = reactable::colFormat(digits = 3) + ), + p75Value_2 = reactable::colDef( + header = withTooltip("Second 75th %tile", + "75th percentile value of the second selected cohort"), + format = reactable::colFormat(digits = 3) + ), + p75Value_1 = reactable::colDef( + header = withTooltip("First 75th %tile", + "75th percentile value of the first selected cohort"), + format = reactable::colFormat(digits = 3) ) # add other columns diff --git a/R/characterization-database.R b/R/characterization-database.R index ecda5ca6..00314e32 100644 --- a/R/characterization-database.R +++ b/R/characterization-database.R @@ -129,7 +129,7 @@ characterizationDatabaseComparisonServer <- function( selected( data.frame( Databases = selectedDatabases, - minTreshold = input$minThreshold + `Minimum Covariate Threshold` = input$minThreshold ) ) diff --git a/R/characterization-dechallengeRechallenge.R b/R/characterization-dechallengeRechallenge.R index 14ab6768..2f1a0e15 100644 --- a/R/characterization-dechallengeRechallenge.R +++ b/R/characterization-dechallengeRechallenge.R @@ -31,7 +31,26 @@ characterizationDechallengeRechallengeViewer <- function(id) { ns <- shiny::NS(id) shiny::div( - resultTableViewer(ns('tableResults')) + shiny::fluidPage( + shiny::fluidRow( + shinydashboard::box( + status = 'warning', + width = '100%', + title = shiny::span( shiny::icon("triangle-exclamation"),'Warnings (if any)'), + solidHeader = TRUE, + shiny::htmlOutput(ns('warningTextTarget')), + shiny::htmlOutput(ns('warningTextOutcome')) + ) + ), + shiny::fluidRow( + shinydashboard::box( + status = 'info', + width = '100%', + solidHeader = TRUE, + resultTableViewer(ns('tableResults')) + ) + ) + ) ) } @@ -75,36 +94,150 @@ characterizationDechallengeRechallengeServer <- function( #databases(allData$databaseId) #dechallengeStopInterval(allData$dechallengeStopInterval) #dechallengeEvaluationWindow(allData$dechallengeEvaluationWindow) - - tableOutputs <- resultTableServer( - id = "tableResults", - df = allData, - colDefsInput = list( - targetCohortDefinitionId = reactable::colDef(show = F), - databaseId = reactable::colDef(show = F), - outcomeCohortDefinitionId = reactable::colDef(show = F), - - databaseName = reactable::colDef(name = 'Database'), - + + countDataTarget <- shiny::reactive({getCohortCounts(connection, + resultDatabaseSettings) %>% + dplyr::filter(cohortId %in% targetId()) + }) + + countDataOutcome <- shiny::reactive({getCohortCounts(connection, + resultDatabaseSettings) %>% + dplyr::filter(cohortId %in% outcomeId()) + }) + + warningTextTarget <- reactive({ + ifelse(countDataTarget()$cohortEntries[1] == countDataTarget()$cohortSubjects[1], + 'WARNING: The target cohort does not have multiple records per person, so observing rechallenge attempts not possible.', + '') + }) + + warningTextOutcome <- reactive({ + ifelse(countDataOutcome()$cohortEntries[1] == countDataOutcome()$cohortSubjects[1], + 'WARNING: The outcome cohort does not have multiple records per person, so observing dechallenge and rechallenge failures is not possible.', + '') + }) + + output$warningTextTarget <- renderText(warningTextTarget()) + output$warningTextOutcome <- renderText(warningTextOutcome()) + + + + + characteriationDechalRechalColDefs <- function(){ + result <- list( + databaseName = reactable::colDef( + header = withTooltip("Database", + "Name of the database"), + filterable = T + ), + databaseId = reactable::colDef( + show = F + ), + targetCohortDefinitionId = reactable::colDef( + show = F + ), + outcomeCohortDefinitionId = reactable::colDef( + show = F + ), + dechallengeStopInterval = reactable::colDef( + header = withTooltip("Dechallenge Stop Interval", + ""), + filterable = T + ), + dechallengeEvaluationWindow = reactable::colDef( + header = withTooltip("Dechallenge Evaluation Window", + ""), + filterable = T + ), + numExposureEras = reactable::colDef( + header = withTooltip("# of Exposure Eras", + ""), + filterable = T + ), + numPersonsExposed = reactable::colDef( + header = withTooltip("# of Exposed Persons", + ""), + filterable = T + ), + numCases = reactable::colDef( + header = withTooltip("# of Cases", + ""), + filterable = T + ), + dechallengeAttempt = reactable::colDef( + header = withTooltip("# of Dechallenge Attempts", + ""), + filterable = T + ), + dechallengeFail = reactable::colDef( + header = withTooltip("# of Dechallenge Fails", + ""), + filterable = T + ), + dechallengeSuccess = reactable::colDef( + header = withTooltip("# of Dechallenge Successes", + ""), + filterable = T + ), + rechallengeAttempt = reactable::colDef( + header = withTooltip("# of Rechallenge Attempts", + ""), + filterable = T + ), + rechallengeFail = reactable::colDef( + header = withTooltip("# of Rechallenge Fails", + ""), + filterable = T + ), + rechallengeSuccess = reactable::colDef( + header = withTooltip("# of Rechallenge Successes", + ""), + filterable = T + ), pctDechallengeAttempt = reactable::colDef( + header = withTooltip("% of Dechallenge Attempts", + ""), + filterable = T, format = reactable::colFormat(digits = 2, percent = T) ), pctDechallengeSuccess = reactable::colDef( + header = withTooltip("% of Dechallenge Success", + ""), + filterable = T, format = reactable::colFormat(digits = 2, percent = T) ), pctDechallengeFail = reactable::colDef( + header = withTooltip("% of Dechallenge Fail", + ""), + filterable = T, format = reactable::colFormat(digits = 2, percent = T) ), pctRechallengeAttempt = reactable::colDef( + header = withTooltip("% of Rechallenge Attempts", + ""), + filterable = T, format = reactable::colFormat(digits = 2, percent = T) ), pctRechallengeSuccess = reactable::colDef( + header = withTooltip("% of Rechallenge Success", + ""), + filterable = T, format = reactable::colFormat(digits = 2, percent = T) ), pctRechallengeFail = reactable::colDef( + header = withTooltip("% of Rechallenge Fail", + ""), + filterable = T, format = reactable::colFormat(digits = 2, percent = T) ) - ), + ) + return(result) + } + + tableOutputs <- resultTableServer( + id = "tableResults", + df = allData, + colDefsInput = characteriationDechalRechalColDefs(), addActions = c('fails') ) @@ -307,6 +440,29 @@ getDechalRechalFailData <- function( } +getCohortCounts <- function( + connectionHandler, + resultDatabaseSettings +) { + + sql <- "SELECT cc.cohort_id, cc.cohort_entries, cc.cohort_subjects + FROM @schema.@cg_table_prefixCOHORT_COUNT cc + join @schema.@database_table_prefix@database_table dt + on cc.database_id = dt.database_id + join @schema.@cg_table_prefixCOHORT_DEFINITION cd + on cd.cohort_definition_id = cc.cohort_id + ;" + return( + connectionHandler$queryDb( + sql = sql, + schema = resultDatabaseSettings$schema, + cg_table_prefix = resultDatabaseSettings$cgTablePrefix, + database_table = resultDatabaseSettings$databaseTable, + database_table_prefix = resultDatabaseSettings$databaseTablePrefix + ) + ) +} + plotDechalRechal <- function( dechalRechalData, i = 1 diff --git a/R/characterization-incidence.R b/R/characterization-incidence.R index 29fc356c..fea0c89e 100644 --- a/R/characterization-incidence.R +++ b/R/characterization-incidence.R @@ -276,6 +276,17 @@ characterizationIncidenceServer <- function( sortedTars <- tarDf$tarId names(sortedTars) <- cohortIncidenceFormatTar(tarDf) + databases <- c("IBM MDCR", + "IBM MDCD", + "JMDC", + "France DA", + "LPDAU", + "Optum EHR", + "IBM CCAE", + "PharMetrics", + "OPTUM Extended SES", + "German DA") + output$inputOptions <- shiny::renderUI({ shinydashboard::box( collapsible = TRUE, @@ -299,6 +310,23 @@ characterizationIncidenceServer <- function( size = NULL ), + shinyWidgets::pickerInput( + inputId = session$ns('databaseSelector'), + label = 'Filter By Database: ', + choices = databases, + selected = databases, + multiple = T, + options = shinyWidgets::pickerOptions( + actionsBox = TRUE, + liveSearch = TRUE, + size = 10, + dropupAuto = TRUE, + liveSearchStyle = "contains", + liveSearchPlaceholder = "Type here to search", + virtualScroll = 50 + ) + ), + shinyWidgets::pickerInput( inputId = session$ns('ageIds'), label = 'Filter By Age Group: ', @@ -380,11 +408,13 @@ characterizationIncidenceServer <- function( incidenceRateCalendarFilter <- shiny::reactiveVal(NULL) incidenceRateAgeFilter <- shiny::reactiveVal(NULL) incidenceRateGenderFilter <- shiny::reactiveVal(NULL) + incidenceRateDbFilter <- shiny::reactiveVal(NULL) shiny::observeEvent(input$generate,{ incidenceRateTarFilter(names(sortedTars)[sortedTars == input$tars]) # filter needs actual value incidenceRateCalendarFilter(input$startYears) incidenceRateAgeFilter(input$ageIds) incidenceRateGenderFilter(input$sexIds) + incidenceRateDbFilter(input$databaseSelector) outcomeIds(input$outcomeIds) }) @@ -591,7 +621,7 @@ characterizationIncidenceServer <- function( if (is.null(targetIds()) | is.null(outcomeIds()) ) { - extractededData(data.frame()) + extractedData(data.frame()) } else if(targetIds()[1] == outcomeIds()[1] && @@ -622,7 +652,9 @@ characterizationIncidenceServer <- function( outcomeIdShort = paste("C", .data$outcomeCohortDefinitionId, sep = "-")) %>% dplyr::filter(.data$ageId %in% !! incidenceRateAgeFilter() & .data$genderId %in% !! incidenceRateGenderFilter() & - .data$startYear %in% !! incidenceRateCalendarFilter() + .data$startYear %in% !! incidenceRateCalendarFilter() & + .data$tar %in% incidenceRateTarFilter() & + .data$cdmSourceAbbreviation %in% !! incidenceRateDbFilter() ) %>% dplyr::relocate("targetIdShort", .after = "targetName") %>% dplyr::relocate("outcomeIdShort", .after = "outcomeName") @@ -1284,8 +1316,14 @@ renderIrPlotStandardAgeSex <- shiny::reactive( shiny::validate("This standard plot is designed to show results aggregated over all (`Any`) year categories. Please make sure you have selected `Any` in the `Select your results` section above for this variable.") ) + #add check to make sure males and females are included + ifelse(8507 %in% incidenceRateGenderFilter() & 8532 %in% incidenceRateGenderFilter(), + plotData <- filteredData(), + shiny::validate("This standard plot is designed to show results stratified by male and female biological sex. Please make sure you have both `Male` and `Female` selected above and try again.") + ) + plotData <- plotData %>% - dplyr::filter(ageGroupName != "Any" & + dplyr::filter( #ageGroupName != "Any" & genderName != "Any" & startYear == "Any") %>% dplyr::mutate(targetLabel = paste(targetIdShort, " = ", targetName), @@ -1427,6 +1465,12 @@ renderIrPlotStandardYear <- shiny::reactive( shiny::validate("Please select only one Target and Outcome at a time to view yearly plots.") ) + ifelse((length(incidenceRateCalendarFilter()) == 1) & + (incidenceRateCalendarFilter() == "Any"), + shiny::validate("Please select at least one start year besides `Any`. This plot depicts calendar trends over time on the x-axis, so at least one distinct year is required."), + plotData <- plotData + ) + plotData <- plotData %>% @@ -1459,6 +1503,11 @@ renderIrPlotStandardYear <- shiny::reactive( # Take the specific tar value you want to plot tar_value <- unique(plotData$tar)[1] + plotData <- plotData %>% + dplyr::filter("Any" %!in% startYear) %>% + dplyr::mutate(startYear = as.Date(paste0(startYear, "-01-01")) + ) + base_plot <- ggplot2::ggplot( data = plotData, ggplot2::aes(x = startYear, @@ -1480,7 +1529,12 @@ renderIrPlotStandardYear <- shiny::reactive( nrow = 2 ) + ggplot2::scale_y_continuous(trans=scales::pseudo_log_trans(base = 10), - n.breaks = 3) + n.breaks = 3) + + ggplot2::scale_x_date(breaks= seq(min(plotData$startYear), max(plotData$startYear), by = "3 years"), + date_labels = "%Y", + limits = c(min(plotData$startYear), + max(plotData$startYear)) + ) base_plot <- base_plot + ggplot2::labs( title = paste("Incidence Rate for Time at Risk:", tar_value), @@ -1569,6 +1623,13 @@ renderIrPlotStandardAggregate <- shiny::reactive( shiny::validate("Too many Target-Outcome pairs selected to plot efficiently. Please choose fewer targets and/or outcomes.") ) + ifelse("Any" %in% incidenceRateAgeFilter() & + "Any" %in% incidenceRateGenderFilter() & + "Any" %in% incidenceRateCalendarFilter(), + plotData <- filteredData(), + shiny::validate("This plot requires the `Any` category to be selected to aggregate over all ages, sexes, and years. Please ensure `Any` is selected in each of these inputs above and try again.") + ) + plotData <- plotData %>% dplyr::filter(ageGroupName == "Any" & genderName == "Any") %>% diff --git a/R/characterization-riskFactors.R b/R/characterization-riskFactors.R index cf2b83e6..38239f20 100644 --- a/R/characterization-riskFactors.R +++ b/R/characterization-riskFactors.R @@ -490,21 +490,28 @@ riskFactorContinuousTable <- function( characteriationRiskFactorColDefs <- function(){ result <- list( - covariateName = reactable::colDef( - name = "Covariate Name", - filterable = T - ), covariateId = reactable::colDef( show = F ), + covariateName = reactable::colDef( + header = withTooltip("Covariate Name", + "Name of the covariate"), + filterable = T + ), minPriorObservation = reactable::colDef( - name = "Minimum prior observation" + header = withTooltip("Min Prior Observation", + "Minimum prior observation time (days)"), + filterable = T ), outcomeWashoutDays = reactable::colDef( - name = "outcome washout days" + header = withTooltip("Outcome Washout Days", + "Number of days for the outcome washout"), + filterable = T ), nonCaseSumValue = reactable::colDef( - name = "Number of non-cases with feature before exposure", + header = withTooltip("# Non-cases with Feature Before Exposure", + "Number of non-cases for the outcome with the feature before exposure"), + filterable = T, format = reactable::colFormat( percent = F, separators = TRUE @@ -516,7 +523,9 @@ characteriationRiskFactorColDefs <- function(){ } ), caseSumValue = reactable::colDef( - name = "Number of cases with feature before exposure", + header = withTooltip("# Cases with Feature Before Exposure", + "Number of cases for the outcome with the feature before exposure"), + filterable = T, format = reactable::colFormat( separators = TRUE, percent = F @@ -528,21 +537,29 @@ characteriationRiskFactorColDefs <- function(){ } ), nonCaseAverageValue = reactable::colDef( - name = "% of non-cases with feature before exposure", + header = withTooltip("% Non-cases with Feature Before Exposure", + "Percent of non-cases for the outcome with the feature before exposure"), + filterable = T, format = reactable::colFormat(digits = 2, percent = T) ), caseAverageValue = reactable::colDef( - name = "% of cases with feature before exposure", + header = withTooltip("% Cases with Feature Before Exposure", + "Percent of Cases for the outcome with the feature before exposure"), + filterable = T, format = reactable::colFormat(digits = 2, percent = T) ), SMD = reactable::colDef( - name = "Standardized mean difference", + header = withTooltip("SMD", + "Standardized mean difference"), + filterable = T, format = reactable::colFormat(digits = 2, percent = F) ), absSMD = reactable::colDef( - name = "Absolute standardized mean difference", + header = withTooltip("absSMD", + "Absolute value of standardized mean difference"), + filterable = T, format = reactable::colFormat(digits = 2, percent = F) ) ) @@ -554,20 +571,28 @@ characteriationRiskFactorColDefs <- function(){ characteriationRiskFactorContColDefs <- function(){ result <- list( covariateName = reactable::colDef( - name = "Covariate Name", + header = withTooltip("Covariate Name", + "Name of the covariate"), filterable = T ), covariateId = reactable::colDef( show = F ), minPriorObservation = reactable::colDef( - name = "Minimum prior observation" + header = withTooltip("Min Prior Observation", + "Minimum prior observation time (days)"), + filterable = T ), outcomeWashoutDays = reactable::colDef( - name = "outcome washout days" + header = withTooltip("Outcome Washout Days", + "Number of days for the outcome washout"), + filterable = T ), targetCountValue = reactable::colDef( - name = "Number of target population with feature", + header = withTooltip("# of Target with Feature", + "Number of the target population with feature"), + filterable = T + , format = reactable::colFormat( percent = F, separators = TRUE @@ -579,7 +604,9 @@ characteriationRiskFactorContColDefs <- function(){ } ), caseCountValue = reactable::colDef( - name = "Number of cases with feature", + header = withTooltip("# of Cases with Feature", + "Number of the cases in the target population with feature"), + filterable = T, format = reactable::colFormat( separators = TRUE, percent = F @@ -591,23 +618,120 @@ characteriationRiskFactorContColDefs <- function(){ } ), targetAverageValue = reactable::colDef( - name = "Target mean feature value", + header = withTooltip("Target Mean Feature Value", + "Mean value of the feature in the target population"), + filterable = T, format = reactable::colFormat(digits = 2, percent = F) ), caseAverageValue = reactable::colDef( - name = "Cases mean feature value", + header = withTooltip("Cases Mean Feature Value", + "Mean value of the feature in the cases"), + filterable = T, format = reactable::colFormat(digits = 2, percent = F) ), targetStandardDeviation = reactable::colDef( - name = "Target standard deviation", + header = withTooltip("Target SD Feature Value", + "Standard deviation of the feature value in the target population"), + filterable = T, format = reactable::colFormat(digits = 2, percent = F) ), caseStandardDeviation = reactable::colDef( - name = "Cases standard deviation", + header = withTooltip("Cases SD Feature Value", + "Standard deviation of the feature value in the cases"), + filterable = T, format = reactable::colFormat(digits = 2, percent = F) ), - + caseMedianValue = reactable::colDef( + header = withTooltip("Cases Median Feature Value", + "Median of the feature value in the cases"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + caseP10Value = reactable::colDef( + header = withTooltip("Cases 10th %ile Feature Value", + "10th percentile of the feature value in the cases"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + caseP25Value = reactable::colDef( + header = withTooltip("Cases 25th %tile Feature Value", + "25th percentile of the feature value in the cases"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + caseP75Value = reactable::colDef( + header = withTooltip("Cases 75th %tile Feature Value", + "75th percentile of the feature value in the cases"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + caseP90Value = reactable::colDef( + header = withTooltip("Cases 90th %tile Feature Value", + "90th percentile of the feature value in the cases"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + caseMaxValue = reactable::colDef( + header = withTooltip("Cases Max Feature Value", + "Maximum of the feature value in the cases"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + caseMinValue = reactable::colDef( + header = withTooltip("Cases Min Feature Value", + "Minimum of the feature value in the cases"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + targetMedianValue = reactable::colDef( + header = withTooltip("Target Median Feature Value", + "Median of the feature value in the target population"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + targetP10Value = reactable::colDef( + header = withTooltip("Target 10th %ile Feature Value", + "10th percentile of the feature value in the target population"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + targetP25Value = reactable::colDef( + header = withTooltip("Target 25th %tile Feature Value", + "25th percentile of the feature value in the target population"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + targetP75Value = reactable::colDef( + header = withTooltip("Target 75th %tile Feature Value", + "75th percentile of the feature value in the target population"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + targetP90Value = reactable::colDef( + header = withTooltip("Target 90th %tile Feature Value", + "90th percentile of the feature value in the target population"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + targetMaxValue = reactable::colDef( + header = withTooltip("Target Max Feature Value", + "Maximum of the feature value in the target population"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + targetMinValue = reactable::colDef( + header = withTooltip("Target Min Feature Value", + "Minimum of the feature value in the target population"), + filterable = T, + format = reactable::colFormat(digits = 2, percent = F) + ), + targetBoxPlot = reactable::colDef( + show = F + ), + caseBoxPlot = reactable::colDef( + show = F + ), #targetBoxPlot = reactable::colDef(cell = function(value, index) { # ggplot2::ggplot() + # ggplot2::geom_boxplot( @@ -633,12 +757,15 @@ characteriationRiskFactorContColDefs <- function(){ #sparkline::spk_chr(c(data$targetMinValue[index], data$targetP10Value[index], data$targetP25Value[index], data$targetMedianValue[index], 3, 6, 6), type="box", raw = TRUE, width = 200) SMD = reactable::colDef( - name = "SMD", + header = withTooltip("SMD", + "Standardized mean difference"), + filterable = T, format = reactable::colFormat(digits = 2, percent = F) ), - absSMD = reactable::colDef( - name = "Absolute SMD", + header = withTooltip("absSMD", + "Absolute value of the standardized mean difference"), + filterable = T, format = reactable::colFormat(digits = 2, percent = F) ) ) diff --git a/R/characterization-timeToEvent.R b/R/characterization-timeToEvent.R index 86a6e724..ec0844de 100644 --- a/R/characterization-timeToEvent.R +++ b/R/characterization-timeToEvent.R @@ -274,7 +274,9 @@ plotTimeToEvent <- function( ggplot2::facet_wrap(ncol = nDatabases , .data$timeScale ~ .data$databaseName , scales = 'free' ) + - ggplot2::theme_minimal() + ggplot2::theme_minimal() + + ggplot2::guides(fill=ggplot2::guide_legend(title="Outcome Type")) + + ggplot2::labs(y= "# of Events", x = "Time (days) to Event") shiny::incProgress(2/2, detail = paste("Finished")) diff --git a/R/cohort-generator-main.R b/R/cohort-generator-main.R index 4a1b6cb0..f7691c15 100644 --- a/R/cohort-generator-main.R +++ b/R/cohort-generator-main.R @@ -119,6 +119,9 @@ cohortGeneratorViewer <- function(id) { title = shiny::span( shiny::icon("table"), 'Generation Table'), #solidHeader = TRUE, + shiny::uiOutput(ns("selectColsCohortGeneration") + ), + reactable::reactableOutput( outputId = ns("cohortGeneration") ) @@ -167,7 +170,10 @@ cohortGeneratorViewer <- function(id) { title = shiny::span( shiny::icon("table"), 'Attrition Table'), #solidHeader = TRUE, - reactable::reactableOutput(ns('attritionTable')) + # shiny::uiOutput(ns("selectColsCohortAttrition") + # ), + + resultTableViewer(ns('attritionTable')) ), shinydashboard::box( @@ -359,19 +365,65 @@ cohortGeneratorServer <- function( } ) - output$cohortGeneration <- reactable::renderReactable({ - data <- getCohortGeneratorCohortMeta( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) %>% - dplyr::select("cdmSourceName", - "cohortId", - "cohortName", - "generationStatus", - "startTime", - "endTime", - "generationDuration") - reactable::reactable(data, + inputColsCohortGeneration <- colnames(getCohortGeneratorCohortMeta( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings + ) %>% + dplyr::select("cdmSourceName", + "cohortId", + "cohortName", + "generationStatus", + "startTime", + "endTime", + "generationDuration") + ) + + names(inputColsCohortGeneration) <- c("Database Name", + "Cohort ID", + "Cohort Name", + "Is the Cohort Generated?", + "Generation Start Time", + "Generation End Time", + "Generation Duration (mins)") + + output$selectColsCohortGeneration <- shiny::renderUI({ + + shinyWidgets::pickerInput( + inputId = session$ns('cohortGenerationCols'), + label = 'Select Columns to Display: ', + choices = inputColsCohortGeneration, + selected = inputColsCohortGeneration, + choicesOpt = list(style = rep_len("color: black;", 999)), + multiple = T, + options = shinyWidgets::pickerOptions( + actionsBox = TRUE, + liveSearch = TRUE, + size = 10, + liveSearchStyle = "contains", + liveSearchPlaceholder = "Type here to search", + virtualScroll = 50 + ), + width = "50%" + ) + + }) + + dataGen <- getCohortGeneratorCohortMeta( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings + ) %>% + dplyr::select("cdmSourceName", + "cohortId", + "cohortName", + "generationStatus", + "startTime", + "endTime", + "generationDuration") + + cgTable <- shiny::reactive({ + + reactable::reactable(dataGen %>% + dplyr::select(input$cohortGenerationCols), columns = list( # Render a "show details" button in the last column of the table. # This button won't do anything by itself, but will trigger the custom @@ -430,6 +482,24 @@ cohortGeneratorServer <- function( ) }) + output$cohortGeneration <- reactable::renderReactable({ + + tryCatch({ + cgTable() + }, + + error = function(e){ + shiny::showNotification( + paste0( + "Loading..." + ) + ); + return(NULL) + } + + ) + }) + # download button - generation output$downloadCohortGeneration <- shiny::downloadHandler( filename = function() { @@ -579,97 +649,98 @@ cohortGeneratorServer <- function( data <- inputValsClean %>% - dplyr::filter(.data$cdmSourceName %in% input$selectedDatabaseId & - .data$cohortName %in% input$selectedCohortName & - .data$modeId %in% input$selectedModeId - ) + dplyr::filter(.data$cdmSourceName %in% input$selectedDatabaseId & + .data$cohortName %in% input$selectedCohortName & + .data$modeId %in% input$selectedModeId + ) reactiveData <- shiny::reactive(data) if(!is.null(data)){ - - output$attritionTable <- reactable::renderReactable( - reactable::reactable( - data = reactiveData() %>% - dplyr::select(c("cdmSourceName", "cohortName", "ruleName", - "personCount", "dropCount", - "dropPerc", "retainPerc") + + resultTableServer( + id = 'attritionTable', + df = reactiveData() %>% + dplyr::select(c("cdmSourceName", "cohortName", "ruleName", + "personCount", "dropCount", + "dropPerc", "retainPerc") + ) + + , + # rownames = FALSE, + # defaultPageSize = 5, + # showPageSizeOptions = T, + # striped = T, + colDefsInput = list( + cdmSourceName = reactable::colDef( + filterable = TRUE, + header = withTooltip( + "Database Name", + "The name of the database" + )), + cohortName = reactable::colDef( + filterable = TRUE, + header = withTooltip( + "Cohort Name", + "The name of the cohort" + )), + ruleName = reactable::colDef( + header = withTooltip( + "Inclusion Rule Name", + "The name of the inclusion rule" + )), + personCount = reactable::colDef( + format = reactable::colFormat(separators = TRUE), + header = withTooltip( + "Subject/Record Count", + "The number of subjects or records (depending on your selection) remaining after the inclusion rule was applied" + )), + dropCount = reactable::colDef( + format = reactable::colFormat(separators = TRUE), + header = withTooltip( + "Number Lost", + "The number of subjects or records (depending on your selection) removed/lost after the inclusion rule was applied" + )), + dropPerc = reactable::colDef( + format = reactable::colFormat(separators = TRUE), + header = withTooltip( + "Percentage Lost", + "The percentage of subjects or records (depending on your selection) removed/lost after the inclusion rule was applied compared to the previous rule count" + )), + retainPerc = reactable::colDef( + format = reactable::colFormat(separators = TRUE), + header = withTooltip( + "Percentage Retained", + "The percentage of subjects or records (depending on your selection) retained after the inclusion rule was applied compared to the previous rule count" + )) ) - - , - rownames = FALSE, - defaultPageSize = 5, - showPageSizeOptions = T, - striped = T, - columns = list( - cdmSourceName = reactable::colDef( - filterable = TRUE, - header = withTooltip( - "Database Name", - "The name of the database" - )), - cohortName = reactable::colDef( - filterable = TRUE, - header = withTooltip( - "Cohort Name", - "The name of the cohort" - )), - ruleName = reactable::colDef( - header = withTooltip( - "Inclusion Rule Name", - "The name of the inclusion rule" - )), - personCount = reactable::colDef( - format = reactable::colFormat(separators = TRUE), - header = withTooltip( - "Subject/Record Count", - "The number of subjects or records (depending on your selection) remaining after the inclusion rule was applied" - )), - dropCount = reactable::colDef( - format = reactable::colFormat(separators = TRUE), - header = withTooltip( - "Number Lost", - "The number of subjects or records (depending on your selection) removed/lost after the inclusion rule was applied" - )), - dropPerc = reactable::colDef( - format = reactable::colFormat(separators = TRUE), - header = withTooltip( - "Percentage Lost", - "The percentage of subjects or records (depending on your selection) removed/lost after the inclusion rule was applied compared to the previous rule count" - )), - retainPerc = reactable::colDef( - format = reactable::colFormat(separators = TRUE), - header = withTooltip( - "Number Retained", - "The number of subjects or records (depending on your selection) retained after the inclusion rule was applied compared to the previous rule count" - )) - ), - - filterable = TRUE, - sortable = TRUE, - defaultColDef = reactable::colDef( - align = "left" + #, + + # filterable = TRUE, + # sortable = TRUE, + # defaultColDef = reactable::colDef( + # align = "left" + # ) + ) + #) + + #attrition plot + output$attritionPlot <- plotly::renderPlotly( + getCohortAttritionPlot( + data ) ) - ) - - #attrition plot - output$attritionPlot <- plotly::renderPlotly( - getCohortAttritionPlot( - data + + # download button + output$downloadAttritionTable <- shiny::downloadHandler( + filename = function() { + paste('cohort-attrition-data-', Sys.Date(), '.csv', sep='') + }, + content = function(con) { + utils::write.csv(data() + , con) + } ) - ) - - # download button - output$downloadAttritionTable <- shiny::downloadHandler( - filename = function() { - paste('cohort-attrition-data-', Sys.Date(), '.csv', sep='') - }, - content = function(con) { - utils::write.csv(data() - , con) - } - ) } else{ @@ -677,20 +748,20 @@ cohortGeneratorServer <- function( } } - ) - - }, + ) - error = function(e){ - shiny::showNotification( - paste0( - "No cohort inclusion result data present." - ) - ); - return(NULL) - } - - ) + }, + + error = function(e){ + shiny::showNotification( + paste0( + "No cohort inclusion result data present." + ) + ); + return(NULL) + } + + ) # end of server diff --git a/R/datasources-main.R b/R/datasources-main.R index 591421a1..4304eea6 100644 --- a/R/datasources-main.R +++ b/R/datasources-main.R @@ -167,6 +167,9 @@ datasourcesServer <- function( resultTableServer(id = "datasourcesTable", df = datasourcesData, colDefsInput = datasourcesColList, + selectedCols = c("cdmSourceName", "cdmSourceAbbreviation", "cdmHolder", + "sourceReleaseDate", "cdmReleaseDate", "cdmVersion", + "vocabularyVersion", "maxObsPeriodEndDate"), downloadedFileName = "datasourcesTable-") return(invisible(NULL)) diff --git a/man/characterizationIncidenceServer.Rd b/man/characterizationIncidenceServer.Rd index f1758335..df648028 100644 --- a/man/characterizationIncidenceServer.Rd +++ b/man/characterizationIncidenceServer.Rd @@ -12,7 +12,7 @@ characterizationIncidenceServer( parents, parentIndex, outcomes, - subTargets + targetIds ) } \arguments{ diff --git a/man/reportServer.Rd b/man/reportServer.Rd index 61466c47..fd450a2e 100644 --- a/man/reportServer.Rd +++ b/man/reportServer.Rd @@ -11,7 +11,7 @@ reportServer( server = Sys.getenv("RESULTS_SERVER"), username = Sys.getenv("RESULTS_USER"), password = Sys.getenv("RESULTS_PASSWORD"), - dbms = "postgresql" + dbms = Sys.getenv("RESULTS_DBMS") ) } \arguments{ From 3955eedeaa2024302a3d66aaf1ca1b66c414f416 Mon Sep 17 00:00:00 2001 From: jreps Date: Tue, 4 Jun 2024 14:38:03 -0400 Subject: [PATCH 17/64] Update characterization-timeToEvent.R changing selection for tte --- R/characterization-timeToEvent.R | 158 ++++++++++++++----------------- 1 file changed, 71 insertions(+), 87 deletions(-) diff --git a/R/characterization-timeToEvent.R b/R/characterization-timeToEvent.R index ec0844de..c057830c 100644 --- a/R/characterization-timeToEvent.R +++ b/R/characterization-timeToEvent.R @@ -32,24 +32,16 @@ characterizationTimeToEventViewer <- function(id) { ns <- shiny::NS(id) shiny::div( - shinydashboard::box( - width = "100%", - title = shiny::tagList(shiny::icon("gear"), "Results"), - - shiny::fluidRow( - shiny::column( - width = 2, - shiny::uiOutput(ns('timeToEventPlotInputs')) - ), - shiny::column( - width = 10, - shinycssloaders::withSpinner( - shiny::plotOutput(ns('timeToEvent')) - ) - ) - ) + shinydashboard::box( + width = "100%", + title = "", + + shiny::uiOutput(ns('timeToEventPlotInputs')), + shinycssloaders::withSpinner( + shiny::plotOutput(ns('timeToEvent')) ) ) + ) } @@ -91,21 +83,50 @@ characterizationTimeToEventServer <- function( shiny::fluidPage( shiny::fluidRow( - shiny::checkboxGroupInput( - inputId = session$ns("databases"), + shiny::selectInput( + inputId = session$ns("databases"), label = "Databases:", - choiceNames = unique(allData()$databaseName), - choiceValues = unique(allData()$databaseName), + multiple = T, + choices = unique(allData()$databaseName), selected = unique(allData()$databaseName) - ), - shiny::checkboxGroupInput( - inputId = session$ns("times"), - label = "Timespan:", - choiceNames = unique(allData()$timeScale), - choiceValues = unique(allData()$timeScale), - selected = unique(allData()$timeScale) + ), + + shiny::fluidRow( + shiny::column( + width = 3, + shiny::selectInput( + inputId = session$ns("times"), + label = "Timespan:", + multiple = T, + choices = unique(allData()$timeScale), + selected = unique(allData()$timeScale) + ) + ), + + shiny::column( + width = 3, + shiny::selectInput( + inputId = session$ns("outcomeTypes"), + label = "Outcome occurrence type:", + multiple = T, + choices = unique(allData()$outcomeType), + selected = unique(allData()$outcomeType) + ) + ), + + shiny::column( + width = 6, + shiny::selectInput( + inputId = session$ns("targetOutcomeTypes"), + label = "Timing of outcome:", + multiple = T, + choices = unique(allData()$targetOutcomeType), + selected = unique(allData()$targetOutcomeType) + ) + ) ) + ) ) } @@ -115,7 +136,9 @@ characterizationTimeToEventServer <- function( plotTimeToEvent( timeToEventData = allData, # reactive databases = input$databases, - times = input$times + times = input$times, + outcomeType = input$outcomeTypes, + targetOutcomeType = input$targetOutcomeTypes ) ) @@ -126,62 +149,6 @@ characterizationTimeToEventServer <- function( ) } -# can remove -timeToEventGetIds <- function( - connectionHandler, - resultDatabaseSettings -){ - - shiny::withProgress(message = 'Getting time to event T and O ids', value = 0, { - - sql <- "SELECT DISTINCT - t.COHORT_NAME as target, TARGET_COHORT_DEFINITION_ID, - o.COHORT_NAME as outcome, OUTCOME_COHORT_DEFINITION_ID - FROM @schema.@c_table_prefixTIME_TO_EVENT tte - inner join @schema.@cg_table_prefixCOHORT_DEFINITION t - on tte.TARGET_COHORT_DEFINITION_ID = t.COHORT_DEFINITION_ID - inner join @schema.@cg_table_prefixCOHORT_DEFINITION o - on tte.OUTCOME_COHORT_DEFINITION_ID = o.COHORT_DEFINITION_ID - ;" - - - shiny::incProgress(1/4, detail = paste("Fetching ids")) - - bothIds <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - c_table_prefix = resultDatabaseSettings$cTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix - ) - - shiny::incProgress(3/4, detail = paste("Processing ids")) - - targetUnique <- bothIds %>% - dplyr::select(c("targetCohortDefinitionId", "target")) %>% - dplyr::distinct() - - targetIds <- targetUnique$targetCohortDefinitionId - names(targetIds) <- targetUnique$target - - outcomeUnique <- bothIds %>% - dplyr::select(c("outcomeCohortDefinitionId", "outcome")) %>% - dplyr::distinct() - - outcomeIds <- outcomeUnique$outcomeCohortDefinitionId - names(outcomeIds) <- outcomeUnique$outcome - - shiny::incProgress(4/4, detail = paste("Finished")) - - }) - - return( - list( - targetIds = targetIds, - outcomeIds = outcomeIds - ) - ) -} - # pulls all data for a target and outcome getTimeToEventData <- function( targetId, @@ -217,13 +184,17 @@ getTimeToEventData <- function( }) + #write.csv(data,'/Users/jreps/Documents/tte_data.csv') + return(data) } plotTimeToEvent <- function( timeToEventData, databases, - times + times, + outcomeTypes, + targetOutcomeTypes ){ if(is.null(timeToEventData())){ @@ -233,14 +204,27 @@ plotTimeToEvent <- function( timeToEventData <- timeToEventData() %>% dplyr::filter(.data$databaseName %in% databases) - if(is.null(timeToEventData)){ + if(nrow(timeToEventData) == 0){ + shiny::showNotification('No results for selected databases') return(NULL) } timeToEventData <- timeToEventData %>% dplyr::filter(.data$timeScale %in% times) - if(is.null(timeToEventData)){ + if(nrow(timeToEventData) == 0){ + shiny::showNotification('No results for selected databases and times') + return(NULL) + } + + timeToEventData <- timeToEventData %>% + dplyr::filter( + .data$outcomeType %in% outcomeTypes & + .data$targetOutcomeType %in% targetOutcomeTypes + ) + + if(nrow(timeToEventData) == 0){ + shiny::showNotification('No results for selection') return(NULL) } From f36352207682fcf50617dee8a00244ebc309ba14 Mon Sep 17 00:00:00 2001 From: jreps Date: Wed, 5 Jun 2024 22:26:30 -0400 Subject: [PATCH 18/64] cleaning characterization tables cleaning characterization tables --- R/characterization-caseSeries.R | 6 +- R/characterization-cohorts.R | 747 +++++++++++++++++-------------- R/characterization-database.R | 119 ++--- R/characterization-riskFactors.R | 48 +- 4 files changed, 521 insertions(+), 399 deletions(-) diff --git a/R/characterization-caseSeries.R b/R/characterization-caseSeries.R index d2d9e579..6379ad35 100644 --- a/R/characterization-caseSeries.R +++ b/R/characterization-caseSeries.R @@ -371,7 +371,8 @@ colDefsBinary <- function(){ covariateName = reactable::colDef( header = withTooltip("Covariate Name", "Name of the covariate"), - filterable = T + filterable = T, + minWidth = 300 ), covariateId = reactable::colDef( show = F @@ -480,7 +481,8 @@ colDefsContinuous <- function(){ covariateName = reactable::colDef( header = withTooltip("Covariate Name", "Name of the covariate"), - filterable = T + filterable = T, + minWidth = 300 ), covariateId = reactable::colDef( show = F diff --git a/R/characterization-cohorts.R b/R/characterization-cohorts.R index 9a507078..c3aa6eb7 100644 --- a/R/characterization-cohorts.R +++ b/R/characterization-cohorts.R @@ -100,7 +100,7 @@ characterizationCohortComparisonServer <- function( size = 10, liveSearchStyle = "contains", liveSearchPlaceholder = "Type here to search", - virtualScroll = 50, + #virtualScroll = 50, #container = "div.tabbable", dropupAuto = FALSE ) @@ -155,8 +155,7 @@ characterizationCohortComparisonServer <- function( ) }) - - + # show selected inputs to user inputSelectionDfServer( id = 'inputSelected', @@ -194,24 +193,14 @@ characterizationCohortComparisonServer <- function( ) selection1 <- subTargetId() - #selection1 <- options[[parentIndex()]]$children[[which(subTargetIds == subTargetId())]]$charIds %>% - # dplyr::filter(.data$databaseId == input$databaseId) %>% - # dplyr::filter(.data$cohortType %in% c('T','O')) %>% - # dplyr::filter(.data$cohortDefinitionId == subTargetId()) # is this needed? - - #if(nrow(selection1) == 0){ + if(length(selection1) == 0){ runTables <- FALSE shiny::showNotification('No results for section 1') } selection2 <- input$comparatorId - #selection2 <- options[[comparatorIndex()]]$children[[which(comparatorGroups() == input$comparatorId)]]$charIds %>% - # dplyr::filter(.data$databaseId == input$databaseId) %>% - # dplyr::filter(.data$cohortType %in% c('T','O')) %>% - # dplyr::filter(.data$cohortDefinitionId == input$comparatorId) - - #if(nrow(selection2) == 0){ + if(length(selection2) == 0){ runTables <- FALSE shiny::showNotification('No results for section 2') @@ -219,14 +208,11 @@ characterizationCohortComparisonServer <- function( if(runTables){ - resultTable <- characterizatonGetCohortComparisonData( + resultTable <- characterizatonGetCohortData( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - #targetId1 = selection1$charCohortId[1], - #targetId2 = selection2$charCohortId[1], - targetId1 = selection1, - targetId2 = selection2, - databaseId = input$databaseId, + targetIds = c(selection1,selection2), + databaseIds = input$databaseId, minThreshold = 0.01, addSMD = T ) @@ -234,59 +220,29 @@ characterizationCohortComparisonServer <- function( countTable <- characterizatonGetCohortCounts( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - #targetIds = c(selection1$charCohortId[1],selection2$charCohortId[1]), targetIds = c(selection1,selection2), - targetNames = c( - subTargetNames[which(subTargetIds == subTargetId())], # modified - names(comparatorGroups())[which(input$comparatorId== comparatorGroups())] - ), - databaseId = input$databaseId + databaseIds = input$databaseId ) - - characteriationCountTableColDefs <- function(){ - result <- list( - selection = reactable::colDef( - header = withTooltip("Selected Cohort", - "Which cohort of the above selections"), - filterable = T - ), - covariateName = reactable::colDef( - header = withTooltip("Covariate Name", - "Name of the covariate"), - filterable = T - ), - rowCount = reactable::colDef( - header = withTooltip("Record Count", - "Count of the number of records"), - filterable = T - ), - personCount = reactable::colDef( - header = withTooltip("Person Count", - "Count of the number of persons"), - filterable = T - ) - ) - return(result) - } - + continuousTable <- characterizatonGetCohortComparisonDataContinuous( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - #targetIds = c(selection1$charCohortId[1],selection2$charCohortId[1]), targetIds = c(selection1,selection2), - databaseIds = rep(input$databaseId,2) + databaseIds = input$databaseId ) - + resultTableServer( id = 'mainTable', df = resultTable, - colDefsInput = characterizationCohortsColumns() + colDefsInput = characterizationCohortsColumns( + addExtras = T + ) ) resultTableServer( id = 'continuousTable', df = continuousTable, - colDefsInput = characterizationCohortsColumnsContinuous() + colDefsInput = characterizationCohortsColumnsContinuous(addExtras = T) ) resultTableServer( @@ -294,19 +250,7 @@ characterizationCohortComparisonServer <- function( df = countTable, colDefsInput = characteriationCountTableColDefs() )} - # else{ - # resultTableServer( - # id = 'mainTable', - # df = data.frame(), - # colDefsInput = columns - # ) - # - # resultTableServer( - # id = 'countTable', - # df = data.frame(), - # colDefsInput = NULL - # ) - # } + }) return(invisible(NULL)) @@ -316,217 +260,327 @@ characterizationCohortComparisonServer <- function( } -characterizationCohortsColumns <- function(x){ - list( - covariateName = reactable::colDef( - header = withTooltip( - "Covariate Name", - "The name of the covariate" - ) - ), - covariateId = reactable::colDef( - show = F, - header = withTooltip("Covariate ID", - "Unique identifier of the covariate") - ), - firstVar = reactable::colDef( - show = F - ), - secondVar = reactable::colDef( - show = F - ), - sumValue_1 = reactable::colDef( - header = withTooltip("First Sum", - "The total sum of the covariate for the first selected cohort."), - cell = function(value) { - if (value >= 0) value else '< min threshold' - } - ), - sumValue_2 = reactable::colDef( - header = withTooltip("Second Sum", - "The total sum of the covariate for the second selected cohort."), - cell = function(value) { - if (value >= 0) value else '< min threshold' - } - ), - averageValue_1 = reactable::colDef( - header = withTooltip("First Mean", - "The mean of the covariate for the first selected cohort."), - cell = function(value) { - if (value >= 0) round(value, digits = 3) else '< min threshold' - } - ), - averageValue_2 = reactable::colDef( - header = withTooltip("Second Mean", - "The mean of the covariate for the second selected cohort."), - cell = function(value) { - if (value >= 0) round(value, digits = 3) else '< min threshold' - } - ), - SMD = reactable::colDef( - header = withTooltip("SMD", - "Standardized mean difference"), - format = reactable::colFormat(digits = 3) - ), - absSMD = reactable::colDef( - header = withTooltip("absSMD", - "Absolute standardized mean difference"), - format = reactable::colFormat(digits = 3) - ), - analysisName = reactable::colDef( - header = withTooltip( - "Covariate Class", - "Class/type of the covariate" +characterizationCohortsColumns <- function( + addExtras = F + ){ + + res <- list( + covariateName = reactable::colDef( + header = withTooltip( + "Covariate Name", + "The name of the covariate" + ), + minWidth = 300 + ), + covariateId = reactable::colDef( + show = F, + header = withTooltip("Covariate ID", + "Unique identifier of the covariate") + ), + minPriorObservation = reactable::colDef( + header = withTooltip( + "Min Prior Obs", + "The minimum prior observation a patient in the target + population must have to be included."), + filterable = T + ), + SMD = reactable::colDef( + header = withTooltip("SMD", + "Standardized mean difference between the target and comparator percentages"), + format = reactable::colFormat(digits = 3) + ), + absSMD = reactable::colDef( + header = withTooltip("absSMD", + "Absolute standardized mean difference between the target and comparator percentages"), + format = reactable::colFormat(digits = 3) + ), + analysisName = reactable::colDef( + header = withTooltip( + "Covariate Class", + "Class/type of the covariate" + ) ) ) - # add other columns -) + if(addExtras){ + res <- append( + res, + list( + sumValue_1 = reactable::colDef( + header = withTooltip("Target Sum", + "The total sum of the covariate for the target cohort."), + cell = function(value) { + if (value >= 0) value else '< min threshold' + } + ), + sumValue_2 = reactable::colDef( + header = withTooltip("Compatator Sum", + "The total sum of the covariate for the comparator cohort."), + cell = function(value) { + if (value >= 0) value else '< min threshold' + } + ), + averageValue_1 = reactable::colDef( + header = withTooltip("Target %", + "The percentage of the target cohort who had the covariate prior to index."), + cell = function(value) { + if (value >= 0) paste0(round(value*100, digits = 3),'%') else '< min threshold' + } + ), + averageValue_2 = reactable::colDef( + header = withTooltip("Comparator %", + "The percentage of the comparator cohort who had the covariate prior to index"), + cell = function(value) { + if (value >= 0) paste0(round(value*100, digits = 3),'%') else '< min threshold' + } + ) + ) + ) + } + return(res) } -characterizationCohortsColumnsContinuous <- function(x){ - list( +characteriationCountTableColDefs <- function( + ){ + result <- list( + selection = reactable::colDef( + filterable = T + ), + cohortName = reactable::colDef( + header = withTooltip("Cohort", + "Name of the cohort"), + filterable = T + ), + minPriorObservation = reactable::colDef( + header = withTooltip( + "Min Prior Obs", + "The minimum prior observation a patient in the target + population must have to be included."), + filterable = T + ), + rowCount = reactable::colDef( + header = withTooltip("Record Count", + "Count of the number of records"), + filterable = T + ), + personCount = reactable::colDef( + header = withTooltip("Person Count", + "Count of the number of persons"), + filterable = T + ) + ) + return(result) +} + +characterizationCohortsColumnsContinuous <- function( + addExtras = F + ){ + res <- list( covariateName = reactable::colDef( header = withTooltip( "Covariate Name", "The name of the covariate" - ) + ), + filterable = T, + minWidth = 300, + ), + databaseName = reactable::colDef( + header = withTooltip( + "Database", + "The name of the database" + ), + filterable = T ), covariateId = reactable::colDef( show = F, header = withTooltip("Covariate ID", "Unique identifier of the covariate") ), - countValue_1 = reactable::colDef( - header = withTooltip("First Count", - "Number of people with the covariate for the first selected cohort."), - cell = function(value) { - if (value >= 0) value else '< min threshold' - } - ), - countValue_2 = reactable::colDef( - header = withTooltip("Second Count", - "Number of people with the covariate for the second selected cohort."), + minPriorObservation = reactable::colDef( + header = withTooltip( + "Min Prior Obs", + "The minimum prior observation a patient in the target + population must have to be included."), + filterable = T + ), + outcomeWashoutPeriod = reactable::colDef( + show = F + ), + countValue = reactable::colDef( + header = withTooltip("Count", + "Number of people with the covariate in the cohort."), cell = function(value) { if (value >= 0) value else '< min threshold' } ), - averageValue_1 = reactable::colDef( - header = withTooltip("First Mean", - "The mean of the covariate for the first selected cohort."), - cell = function(value) { - if (value >= 0) round(value, digits = 3) else '< min threshold' - } - ), - averageValue_2 = reactable::colDef( - header = withTooltip("Second Mean", - "The mean of the covariate for the second selected cohort."), - cell = function(value) { - if (value >= 0) round(value, digits = 3) else '< min threshold' - } - ), - standardDeviation_1 = reactable::colDef( - header = withTooltip("First StDev", - "The standard deviation of the covariate for the first selected cohort."), + averageValue = reactable::colDef( + header = withTooltip("Mean", + "The mean value of the covariate in the cohort"), cell = function(value) { if (value >= 0) round(value, digits = 3) else '< min threshold' } ), - standardDeviation_2 = reactable::colDef( - header = withTooltip("Second StDev", - "The standard deviation of the covariate for the second selected cohort."), + standardDeviation = reactable::colDef( + header = withTooltip("StDev", + "The standard deviation value of the covariate in the cohort"), cell = function(value) { if (value >= 0) round(value, digits = 3) else '< min threshold' } ), - medianValue_1 = reactable::colDef( - header = withTooltip("First Median", - "The median of the covariate for the first selected cohort."), + medianValue = reactable::colDef( + header = withTooltip("Median", + "The median value of the covariate in the cohort."), cell = function(value) { round(value, digits = 3) } ), - medianValue_2 = reactable::colDef( - header = withTooltip("Second Median", - "The median of the covariate for the second selected cohort."), - cell = function(value) { - round(value, digits = 3) - } - ), - SMD = reactable::colDef( - header = withTooltip("SMD", - "Standardized mean difference"), + minValue = reactable::colDef( + header = withTooltip("Min Value", + "Minimum value of the covariate in the cohort"), format = reactable::colFormat(digits = 3) ), - absSMD = reactable::colDef( - header = withTooltip("absSMD", - "Absolute standardized mean difference"), + maxValue = reactable::colDef( + header = withTooltip("Max Value", + "Maximum value the covariate in the cohort"), format = reactable::colFormat(digits = 3) ), - minValue_2 = reactable::colDef( - header = withTooltip("Second Min Value", - "Minimum value of the second selected cohort"), + p25Value = reactable::colDef( + header = withTooltip("25th %tile", + "25th percentile value of the covariate in the cohort"), format = reactable::colFormat(digits = 3) ), - minValue_1 = reactable::colDef( - header = withTooltip("First Min Value", - "Minimum value of the first selected cohort"), + p75Value = reactable::colDef( + header = withTooltip("75th %tile", + "75th percentile value of the covariate in the cohort"), format = reactable::colFormat(digits = 3) ), - maxValue_2 = reactable::colDef( - header = withTooltip("Second Max Value", - "Maximum value of the second selected cohort"), + p10Value = reactable::colDef( + header = withTooltip("10th %tile", + "10th percentile value of the covariate in the cohort"), format = reactable::colFormat(digits = 3) ), - maxValue_1 = reactable::colDef( - header = withTooltip("First Max Value", - "Maximum value of the first selected cohort"), - format = reactable::colFormat(digits = 3) - ), - p25Value_2 = reactable::colDef( - header = withTooltip("Second 25th %tile", - "25th percentile value of the second selected cohort"), - format = reactable::colFormat(digits = 3) - ), - p25Value_1 = reactable::colDef( - header = withTooltip("First 25th %tile", - "25th percentile value of the first selected cohort"), - format = reactable::colFormat(digits = 3) - ), - p75Value_2 = reactable::colDef( - header = withTooltip("Second 75th %tile", - "75th percentile value of the second selected cohort"), - format = reactable::colFormat(digits = 3) - ), - p75Value_1 = reactable::colDef( - header = withTooltip("First 75th %tile", - "75th percentile value of the first selected cohort"), + p90Value = reactable::colDef( + header = withTooltip("90th %tile", + "90th percentile value of the covariate in the cohort"), format = reactable::colFormat(digits = 3) ) - - # add other columns - ) -} - -characterizatonGetCohortComparisonData <- function( - connectionHandler, - resultDatabaseSettings, - targetId1, - targetId2, - databaseId, - minThreshold, - addSMD -){ - result <- characterizatonGetCohortData( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - targetIds = c(targetId1, targetId2), - databaseIds = c(databaseId,databaseId), - minThreshold = minThreshold, - addSMD = addSMD ) - return(result) + if(addExtras){ + res <- append( + res, + list( + SMD = reactable::colDef( + header = withTooltip("SMD", + "Standardized mean difference"), + format = reactable::colFormat(digits = 3) + ), + absSMD = reactable::colDef( + header = withTooltip("absSMD", + "Absolute standardized mean difference"), + format = reactable::colFormat(digits = 3) + ), + countValue_1 = reactable::colDef( + header = withTooltip("Target Count", + "Number of people with the covariate for the target cohort."), + cell = function(value) { + if (value >= 0) value else '< min threshold' + } + ), + countValue_2 = reactable::colDef( + header = withTooltip("Comparator Count", + "Number of people with the covariate for the comparator cohort."), + cell = function(value) { + if (value >= 0) value else '< min threshold' + } + ), + averageValue_1 = reactable::colDef( + header = withTooltip("Target Mean", + "The mean of the covariate for the target cohort."), + cell = function(value) { + if (value >= 0) round(value, digits = 3) else '< min threshold' + } + ), + averageValue_2 = reactable::colDef( + header = withTooltip("Comparator Mean", + "The mean of the covariate for the comparator cohort."), + cell = function(value) { + if (value >= 0) round(value, digits = 3) else '< min threshold' + } + ), + standardDeviation_1 = reactable::colDef( + header = withTooltip("Target StDev", + "The standard deviation of the covariate for the target cohort."), + cell = function(value) { + if (value >= 0) round(value, digits = 3) else '< min threshold' + } + ), + standardDeviation_2 = reactable::colDef( + header = withTooltip("Comparator StDev", + "The standard deviation of the covariate for the comparator cohort."), + cell = function(value) { + if (value >= 0) round(value, digits = 3) else '< min threshold' + } + ), + medianValue_1 = reactable::colDef( + header = withTooltip("Target Median", + "The median of the covariate for the target cohort."), + cell = function(value) { + round(value, digits = 3) + } + ), + medianValue_2 = reactable::colDef( + header = withTooltip("Comparator Median", + "The median of the covariate for the comparator cohort."), + cell = function(value) { + round(value, digits = 3) + } + ), + minValue_2 = reactable::colDef( + header = withTooltip("Comparator Min Value", + "Minimum value of the comparator cohort"), + format = reactable::colFormat(digits = 3) + ), + minValue_1 = reactable::colDef( + header = withTooltip("Target Min Value", + "Minimum value of the target cohort"), + format = reactable::colFormat(digits = 3) + ), + maxValue_2 = reactable::colDef( + header = withTooltip("Comparator Max Value", + "Maximum value of the comparator cohort"), + format = reactable::colFormat(digits = 3) + ), + maxValue_1 = reactable::colDef( + header = withTooltip("Target Max Value", + "Maximum value of the target cohort"), + format = reactable::colFormat(digits = 3) + ), + p25Value_2 = reactable::colDef( + header = withTooltip("Comparator 25th %tile", + "25th percentile value of the comparator cohort"), + format = reactable::colFormat(digits = 3) + ), + p25Value_1 = reactable::colDef( + header = withTooltip("Target 25th %tile", + "25th percentile value of the target cohort"), + format = reactable::colFormat(digits = 3) + ), + p75Value_2 = reactable::colDef( + header = withTooltip("Comparator 75th %tile", + "75th percentile value of the comparator cohort"), + format = reactable::colFormat(digits = 3) + ), + p75Value_1 = reactable::colDef( + header = withTooltip("Target 75th %tile", + "75th percentile value of the target cohort"), + format = reactable::colFormat(digits = 3) + ) + ) + ) + } + + return(res) } @@ -534,55 +588,57 @@ characterizatonGetCohortCounts <- function( connectionHandler, resultDatabaseSettings, targetIds, - targetNames, - databaseId + databaseIds ){ start <- Sys.time() result <- connectionHandler$queryDb( sql = " -select distinct cc.target_cohort_id as cohort_definition_id, +select distinct + cc.target_cohort_id as cohort_definition_id, cc.min_prior_observation, cc.row_count, - cc.person_count - from + cc.person_count, + d.cdm_source_abbreviation as database_name, + d.database_id, + cg.cohort_name + from + @schema.@database_table d + inner join @schema.@c_table_prefixcohort_counts cc - where + on d.database_id = cc.database_id + inner join + @schema.@cg_table_prefixcohort_definition cg + on cg.cohort_definition_id = cc.target_cohort_id + + where cc.target_cohort_id in (@target_ids) and cc.cohort_type = 'Target' - AND cc.database_id = '@database_id' - - union - - select cc.outcome_cohort_id as cohort_definition_id, - cc.min_prior_observation, - cc.row_count, - cc.person_count - from - @schema.@c_table_prefixcohort_counts cc - where - cc.outcome_cohort_id in (@target_ids) - and cc.cohort_type = 'Outcome' - AND cc.database_id = '@database_id' + AND cc.database_id in (@database_ids) ; ", schema = resultDatabaseSettings$schema, c_table_prefix = resultDatabaseSettings$cTablePrefix, + cg_table_prefix = resultDatabaseSettings$cgTablePrefix, target_ids = paste0(targetIds, collapse= ','), - database_id = databaseId + database_ids = paste0("'",databaseIds,"'",collapse= ','), + database_table = resultDatabaseSettings$databaseTable ) end <- Sys.time() - start message(paste0('Extracting ', nrow(result) ,' cohort count rows took: ', round(end, digits = 2), ' ', units(end))) + if(length(targetIds)>1){ result <- merge( x = result, y = data.frame( - selection = c('First','Second'), - cohortDefinitionId = targetIds, - cohortName = targetNames + selection = c('Target','Comparator'), + cohortDefinitionId = targetIds ), by = 'cohortDefinitionId' ) + } else{ + result$selection <- result$databaseName + } result <- result %>% dplyr::select( 'selection', @@ -616,19 +672,14 @@ characterizatonGetCohortData <- function( shiny::incProgress(1/4, detail = paste("Setting types")) types <- data.frame( - type = 1:length(targetIds), - cohortDefinitionId = targetIds, - databaseId = databaseIds + type = 1:(length(targetIds)*length(databaseIds)), + cohortDefinitionId = rep(targetIds, length(databaseIds)), + databaseId = rep(databaseIds, length(targetIds)) ) - # - shiny::incProgress(2/4, detail = paste("Extracting data")) - sql <- paste0( - paste0( - paste0( - "select ref.covariate_name, + sql <- "select ref.covariate_name, s.min_prior_observation, cov.target_cohort_id as cohort_definition_id, cov.* from @@ -644,24 +695,21 @@ characterizatonGetCohortData <- function( and s.setting_id = cov.setting_id where - (cov.target_cohort_id = @target_id",1:length(targetIds), - " and cov.cohort_type = 'Target') - AND cov.database_id = '@database_id",1:length(targetIds),"' - AND cov.average_value >= @min_threshold" - ), collapse = ' union ' - ),';' - ) - - inputList <- as.list(c(targetIds, databaseIds)) - names(inputList) <- c(paste0('target_id', 1:length(targetIds)), paste0('database_id', 1:length(databaseIds))) - inputList$sql <- sql - inputList$schema <- resultDatabaseSettings$schema - inputList$c_table_prefix <- resultDatabaseSettings$cTablePrefix - inputList$min_threshold <- minThreshold - + cov.target_cohort_id in (@target_ids) + and cov.cohort_type = 'Target' + AND cov.database_id in (@database_ids) + AND cov.average_value >= @min_threshold;" + start <- Sys.time() # settings.min_characterization_mean needed? - res <- do.call(what = connectionHandler$queryDb, args = inputList) + res <- connectionHandler$queryDb( + sql = sql, + target_ids = paste0(targetIds, collapse = ','), + database_ids = paste0("'",databaseIds,"'", collapse = ','), + schema = resultDatabaseSettings$schema, + c_table_prefix = resultDatabaseSettings$cTablePrefix, + min_threshold = minThreshold + ) end <- Sys.time() - start shiny::incProgress(3/4, detail = paste("Extracted data")) message(paste0('Extracting ', nrow(res) ,' characterization cohort rows took: ', round(end, digits = 2), ' ', units(end))) @@ -683,13 +731,18 @@ characterizatonGetCohortData <- function( # TODO get min_characterization_mean from settings table # minCharacterizationMean <- minThreshold # add SMD - convertMissing <- function(vec){sapply(vec, function(x) ifelse(x==-1, minThreshold, x))} - result$firstVar <- convertMissing(result$averageValue_1)*(1-convertMissing(result$averageValue_1))^2 - result$secondVar <- convertMissing(result$averageValue_2)*(1-convertMissing(result$averageValue_2))^2 - result$SMD <- (convertMissing(result$averageValue_1) - convertMissing(result$averageValue_2))/(sqrt((result$firstVar+result$secondVar)/2)) - result$absSMD <- abs(result$SMD) + if(sum(c('averageValue_1','averageValue_2') %in% colnames(result)) == 2){ + convertMissing <- function(vec){sapply(vec, function(x) ifelse(x==-1, minThreshold, x))} + result$firstVar <- convertMissing(result$averageValue_1)*(1-convertMissing(result$averageValue_1))^2 + result$secondVar <- convertMissing(result$averageValue_2)*(1-convertMissing(result$averageValue_2))^2 + result$SMD <- (convertMissing(result$averageValue_1) - convertMissing(result$averageValue_2))/(sqrt((result$firstVar+result$secondVar)/2)) + result$absSMD <- abs(result$SMD) + result <- result %>% dplyr::select(-"firstVar",-"secondVar") + + } else{ + shiny::showNotification('Unable to add SMD due to missing columns') + } } - shiny::incProgress(4/4, detail = paste("Done")) }) @@ -701,33 +754,36 @@ characterizatonGetCohortComparisonDataContinuous <- function( connectionHandler, resultDatabaseSettings, targetIds, - databaseIds + databaseIds, + pivot = T ){ - + if(is.null(targetIds) | is.null(databaseIds)){ warning('Ids cannot be NULL') return(NULL) } + targetIds <- unique(targetIds) + databaseIds <- unique(databaseIds) shiny::withProgress(message = 'characterizatonGetCohortDataContinuous', value = 0, { shiny::incProgress(1/4, detail = paste("Setting types")) types <- data.frame( - type = 1:length(targetIds), - cohortDefinitionId = targetIds, - databaseId = databaseIds + type = 1:(length(targetIds)*length(databaseIds)), + cohortDefinitionId = rep(targetIds, length(databaseIds)), + databaseId = rep(databaseIds, length(targetIds)) ) shiny::incProgress(2/4, detail = paste("Extracting data")) - sql <- paste0( - paste0( - paste0( - "select ref.covariate_name, + sql <- "select ref.covariate_name, s.min_prior_observation, cov.target_cohort_id as cohort_definition_id, - cov.* from + cov.*, + d.CDM_SOURCE_ABBREVIATION as database_name + + from @schema.@c_table_prefixCOVARIATES_continuous cov inner join @schema.@c_table_prefixcovariate_ref ref @@ -738,67 +794,74 @@ characterizatonGetCohortComparisonDataContinuous <- function( @schema.@c_table_prefixsettings s on cov.setting_id = s.setting_id and cov.database_id = s.database_id + inner join @schema.@database_meta_table d + on s.database_id = d.database_id where - (cov.target_cohort_id = @target_id",1:length(targetIds), - " and cov.cohort_type = 'Target') - AND cov.database_id = '@database_id",1:length(targetIds),"' - " - ), collapse = ' union ' - ),';' - ) - - inputList <- as.list(c(targetIds, databaseIds)) - names(inputList) <- c(paste0('target_id', 1:length(targetIds)), paste0('database_id', 1:length(databaseIds))) - inputList$sql <- sql - inputList$schema <- resultDatabaseSettings$schema - inputList$c_table_prefix <- resultDatabaseSettings$cTablePrefix + cov.target_cohort_id in (@target_ids) + and cov.cohort_type = 'Target' + AND cov.database_id in (@database_ids);" start <- Sys.time() # settings.min_characterization_mean needed? - res <- do.call(what = connectionHandler$queryDb, args = inputList) + res <- connectionHandler$queryDb( + sql = sql, + target_ids = paste0(targetIds, collapse = ','), + database_ids = paste0("'",databaseIds,"'", collapse = ','), + schema = resultDatabaseSettings$schema, + c_table_prefix = resultDatabaseSettings$cTablePrefix, + database_meta_table = resultDatabaseSettings$databaseTable + ) end <- Sys.time() - start shiny::incProgress(3/4, detail = paste("Extracted data")) - message(paste0('Extracting ', nrow(res) ,' characterization cohort rows took: ', round(end, digits = 2), ' ', units(end))) + message(paste0('Extracting ', nrow(res) ,' continuous characterization cohort rows took: ', round(end, digits = 2), ' ', units(end))) # add the first/section type res <- merge(res, types, by = c('cohortDefinitionId','databaseId')) - # pivot - result <- tidyr::pivot_wider( - data = res, - id_cols = c('covariateName', 'covariateId','minPriorObservation'), - names_from = 'type', - values_from = c('countValue', 'averageValue', 'standardDeviation', 'medianValue','minValue', 'maxValue', 'p25Value','p75Value'), - values_fn = mean, - values_fill = -1 - ) - - # if both have results then add SMD - if(length(unique(res$type)) > 1){ - result <- result %>% - dplyr::mutate( - SMD = (.data$averageValue_1-.data$averageValue_2)/(sqrt((.data$standardDeviation_1^2 + .data$standardDeviation_2^2)/2)) - ) %>% - dplyr::mutate( - absSMD = abs(.data$SMD) - ) + if(pivot){ + # if pivot + res <- tidyr::pivot_wider( + data = res, + id_cols = c('covariateName', 'covariateId','minPriorObservation'), + names_from = 'type', + values_from = c('countValue', 'averageValue', 'standardDeviation', 'medianValue','minValue', 'maxValue', 'p25Value','p75Value'), + values_fn = mean, + values_fill = -1 + ) + + # if both have results then add SMD + if(length(unique(res$type)) == 2){ + res <- res %>% + dplyr::mutate( + SMD = (.data$averageValue_1-.data$averageValue_2)/(sqrt((.data$standardDeviation_1^2 + .data$standardDeviation_2^2)/2)) + ) %>% + dplyr::mutate( + absSMD = abs(.data$SMD) + ) + } + } else{ + # if multiple databases make the type the databaseName + res$type <- res$databaseName + res <- res %>% dplyr::select(-"cohortDefinitionId", -"databaseId", -"type", + -"settingId", -"targetCohortId", -"outcomeCohortId", + -"cohortType") %>% + dplyr::relocate(.data$databaseName, .after = .data$covariateName) } shiny::incProgress(4/4, detail = paste("Done")) }) - return(result) + return(res) } - characterizationGetCohortsInputs <- function( connectionHandler, resultDatabaseSettings, targetId # reactive ) { - + sql <- "select distinct d.database_id, d.cdm_source_abbreviation as database_name from @schema.@database_table d @@ -819,10 +882,10 @@ characterizationGetCohortsInputs <- function( ) databaseIds <- database$databaseId names(databaseIds) <- database$databaseName - + return( list( databaseIds = databaseIds ) ) -} +} \ No newline at end of file diff --git a/R/characterization-database.R b/R/characterization-database.R index d8d93b3d..54050890 100644 --- a/R/characterization-database.R +++ b/R/characterization-database.R @@ -40,8 +40,21 @@ characterizationDatabaseComparisonViewer <- function(id) { inputSelectionDfViewer(id = ns('inputSelected'), title = 'Selected'), # add basic table - resultTableViewer(id = ns('mainTable'), boxTitle = 'Binary') - + shiny::tabsetPanel( + type = 'pills', + shiny::tabPanel( + title = 'Counts', + resultTableViewer(id = ns('countTable'), boxTitle = 'Counts') + ), + shiny::tabPanel( + title = 'Binary', + resultTableViewer(id = ns('mainTable'), boxTitle = 'Binary') + ), + shiny::tabPanel( + title = 'Continuous', + resultTableViewer(id = ns('continuousTable'), boxTitle = 'Continuous') + ) + ) ) ) } @@ -133,8 +146,25 @@ characterizationDatabaseComparisonServer <- function( #get results - #if(sum(selectedChildChar$databaseId %in% input$databaseIds) > 0){ + results <- list( + table = data.frame(), + databaseNames = data.frame( + id = 1, + databaseName = 'None' + ) + ) + continuousTable <- data.frame() + countTable <- data.frame() + if(length(input$databaseIds) > 0){ + + countTable <- characterizatonGetCohortCounts( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = subTargetId(), + databaseIds = input$databaseIds + ) + result <- characterizatonGetDatabaseComparisonData( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, @@ -142,16 +172,30 @@ characterizationDatabaseComparisonServer <- function( databaseIds = input$databaseIds, minThreshold = input$minThreshold ) + + continuousTable <- characterizatonGetCohortComparisonDataContinuous( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = subTargetId(), + databaseIds = input$databaseIds, + pivot = F + ) + + } else{ + shiny::showNotification('No results') + } + + databaseNames <- result$databaseNames meanColumns <- lapply(1:nrow(databaseNames), function(i){ reactable::colDef( header = withTooltip( - paste0("Mean ", databaseNames$databaseName[i]), - paste0("The mean of the covariate for database ", databaseNames$databaseName[i]) + paste0(databaseNames$databaseName[i], ' %'), + paste0("The percentage of the target population in database ", databaseNames$databaseName[i], ' who had the covariate prior.') ), cell = function(value) { - if (value >= 0) round(value, digits = 3) else '< min threshold' + if (value >= 0) paste0(round(value*100, digits = 3),' %') else '< min threshold' } ) }) @@ -160,8 +204,8 @@ characterizationDatabaseComparisonServer <- function( sumColumns <- lapply(1:nrow(databaseNames), function(i){ reactable::colDef( header = withTooltip( - paste0("Sum ", databaseNames$databaseName[i]), - paste0("The sums of the covariate for database ", databaseNames$databaseName[i]) + paste0(databaseNames$databaseName[i], " Count"), + paste0("The number of people in the target cohort in database ", databaseNames$databaseName[i], ' who have the covariate prior.') ), cell = function(value) { if (value >= 0) value else '< min threshold' @@ -169,54 +213,29 @@ characterizationDatabaseComparisonServer <- function( ) }) names(sumColumns) <- unlist(lapply(1:nrow(databaseNames), function(i) paste0('sumValue_',databaseNames$id[i]))) - - columns <- append( - list( - covariateName = reactable::colDef( - header = withTooltip( - "Covariate Name", - "The name of the covariate" - ) - ), - covariateId = reactable::colDef( - show = F, - header = withTooltip("Covariate ID", - "Unique identifier of the covariate") - ) - ), - append( - sumColumns, - meanColumns - ) - ) + resultTableServer( - id = 'mainTable', - df = result$table, - colDefsInput = columns + id = 'countTable', + df = countTable, + colDefsInput = characteriationCountTableColDefs() ) - } else{ - shiny::showNotification('No results') resultTableServer( id = 'mainTable', - df = data.frame(), - colDefsInput = list( - covariateName = reactable::colDef( - header = withTooltip( - "Covariate Name", - "The name of the covariate" - ) - ), - covariateId = reactable::colDef( - show = F, - header = withTooltip("Covariate ID", - "Unique identifier of the covariate") + df = result$table, + colDefsInput = append( + characterizationCohortsColumns(), + append( + sumColumns, + meanColumns ) ) - ) - } - - + ) + resultTableServer( + id = 'continuousTable', + df = continuousTable, + colDefsInput = characterizationCohortsColumnsContinuous() + ) }) @@ -240,7 +259,7 @@ characterizatonGetDatabaseComparisonData <- function( targetIds = targetIds, databaseIds = databaseIds, minThreshold = minThreshold, - addSMD = F # unless two databases? + addSMD = length(databaseIds) == 2 ) databaseNames <- connectionHandler$queryDb( diff --git a/R/characterization-riskFactors.R b/R/characterization-riskFactors.R index 98443d36..ac19abfc 100644 --- a/R/characterization-riskFactors.R +++ b/R/characterization-riskFactors.R @@ -97,6 +97,13 @@ characterizationRiskFactorServer <- function( shiny::observeEvent(input$generate, { + # add database and tar here + selected <- data.frame( + database = names(options()$databaseIds)[which(input$databaseId == options()$databaseIds)], + time_at_risk = names(options()$tarInds)[which(input$tarInd == options()$tarInds)] + ) + print(selected) + allData <- characterizationGetRiskFactorData( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, @@ -203,6 +210,7 @@ characterizationGetRiskFactorData <- function( database_id = databaseId, setting_ids = paste0(ids$settingId, collapse=',') ) + message(paste0('Extracted ',nrow(binary),' binary RF rows')) # now process into table binary <- riskFactorTable( @@ -228,7 +236,7 @@ characterizationGetRiskFactorData <- function( and cov.database_id = s.database_id where cov.target_cohort_id = @target_id - and cov.outcome_cohort_id = @outcome_id + and cov.outcome_cohort_id in (0,@outcome_id) and cov.cohort_type in ('Target','TnO', 'TnOprior') and cov.database_id = '@database_id' and cov.setting_id in (@setting_ids) @@ -244,7 +252,9 @@ characterizationGetRiskFactorData <- function( outcome_id = outcomeId, database_id = databaseId, setting_ids = paste0(ids$settingId, collapse=',') - ) + ) + + message(paste0('Extracted ',nrow(binary),' continuous RF rows')) continuous <- riskFactorContinuousTable( data = continuous @@ -268,6 +278,10 @@ riskFactorTable <- function( data ){ + if(is.null(data)){ + return(data) + } + data <- unique(data) if(nrow(data) == 0){ return(data) @@ -275,6 +289,22 @@ riskFactorTable <- function( outcomeWashoutDays <- unique(data$outcomeWashoutDays) outcomeWashoutDays <- outcomeWashoutDays[!is.na(outcomeWashoutDays)] + if(length(outcomeWashoutDays) == 0){ + shiny::showNotification('No cases') + data <- data %>% + dplyr::filter(.data$cohortType == 'Target') %>% + dplyr::select(-"cohortType", -"outcomeWashoutDays") %>% + dplyr::mutate( + nonCaseSumValue = .data$sumValue, + nonCaseAverageValue = .data$averageValue + ) %>% + dplyr::select( + "covariateId","covariateName", + 'minPriorObservation', + "nonCaseSumValue","nonCaseAverageValue" + ) + return(data) + } allData <- data %>% dplyr::filter(.data$cohortType == 'Target') %>% @@ -294,6 +324,7 @@ riskFactorTable <- function( completeData <- c() for(outcomeWashoutDay in outcomeWashoutDays){ + caseData <- data %>% dplyr::filter( .data$cohortType == 'TnO' & @@ -320,6 +351,7 @@ riskFactorTable <- function( dplyr::group_by(.data$minPriorObservation) %>% dplyr::summarise(exclude_N = round(max(.data$N, na.rm = T))) + if(nrow(excludeData) > 0 ){ colnamesInclude <- !colnames(excludeData) %in% c('covariateId', 'covariateName', 'minPriorObservation') colnames(excludeData)[colnamesInclude] <- paste0('exclude_',colnames(excludeData)[colnamesInclude]) @@ -427,7 +459,9 @@ riskFactorTable <- function( allData <- allData %>% dplyr::mutate( outcomeWashoutDays = !!outcomeWashoutDay - ) + ) %>% + dplyr::relocate(.data$outcomeWashoutDays, + .after = .data$minPriorObservation) completeData <- rbind(allData, completeData) @@ -448,6 +482,7 @@ riskFactorTable <- function( ) } + return(unique(completeData)) } @@ -456,6 +491,7 @@ riskFactorContinuousTable <- function( data ){ + data <- unique(data) caseData <- data %>% @@ -537,7 +573,8 @@ characteriationRiskFactorColDefs <- function(){ covariateName = reactable::colDef( header = withTooltip("Covariate Name", "Name of the covariate"), - filterable = T + filterable = T, + minWidth = 300 ), minPriorObservation = reactable::colDef( header = withTooltip("Min Prior Observation", @@ -614,7 +651,8 @@ characteriationRiskFactorContColDefs <- function(){ covariateName = reactable::colDef( header = withTooltip("Covariate Name", "Name of the covariate"), - filterable = T + filterable = T, + minWidth = 300 ), covariateId = reactable::colDef( show = F From b39f5c09e8c85238713e6b5108c21791f7365d75 Mon Sep 17 00:00:00 2001 From: jreps Date: Thu, 6 Jun 2024 08:19:35 -0400 Subject: [PATCH 19/64] minor update adding box to show selected tar/database for RF and case series. --- R/characterization-caseSeries.R | 16 ++++++++++++++++ R/characterization-riskFactors.R | 20 +++++++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/R/characterization-caseSeries.R b/R/characterization-caseSeries.R index 6379ad35..d0cf5692 100644 --- a/R/characterization-caseSeries.R +++ b/R/characterization-caseSeries.R @@ -29,6 +29,9 @@ characterizationCaseSeriesViewer <- function(id) { shiny::conditionalPanel( condition = 'input.generate != 0', ns = ns, + + inputSelectionDfViewer(id = ns('inputSelected'), title = 'Selected'), + shinydashboard::tabBox( width = "100%", # Title can include an icon @@ -95,8 +98,21 @@ characterizationCaseSeriesServer <- function( }) + # save the selections + selected <- shiny::reactive({ + data.frame( + database = names(options()$databaseIds)[which(input$databaseId == options()$databaseIds)], + time_at_risk = names(options()$tarInds)[which(input$tarInd == options()$tarInds)] + )}) + shiny::observeEvent(input$generate, { + inputSelectionDfServer( + id = 'inputSelected', + dataFrameRow = selected, + ncol = 1 + ) + allData <- characterizationGetCaseSeriesData( connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, diff --git a/R/characterization-riskFactors.R b/R/characterization-riskFactors.R index ac19abfc..589683b5 100644 --- a/R/characterization-riskFactors.R +++ b/R/characterization-riskFactors.R @@ -29,10 +29,14 @@ characterizationRiskFactorViewer <- function(id) { shiny::conditionalPanel( condition = 'input.generate != 0', ns = ns, + + inputSelectionDfViewer(id = ns('inputSelected'), title = 'Selected'), + shinydashboard::tabBox( width = "100%", # Title can include an icon title = shiny::tagList(shiny::icon("gear"), "Risk Factors"), + shiny::tabPanel("Binary Feature Table", resultTableViewer(ns('binaryTable')) ), @@ -95,14 +99,20 @@ characterizationRiskFactorServer <- function( }) + # save the selections + selected <- shiny::reactive({ + data.frame( + database = names(options()$databaseIds)[which(input$databaseId == options()$databaseIds)], + time_at_risk = names(options()$tarInds)[which(input$tarInd == options()$tarInds)] + )}) + shiny::observeEvent(input$generate, { - # add database and tar here - selected <- data.frame( - database = names(options()$databaseIds)[which(input$databaseId == options()$databaseIds)], - time_at_risk = names(options()$tarInds)[which(input$tarInd == options()$tarInds)] + inputSelectionDfServer( + id = 'inputSelected', + dataFrameRow = selected, + ncol = 1 ) - print(selected) allData <- characterizationGetRiskFactorData( connectionHandler = connectionHandler, From bf594b93d0f549fa372e8d4893bbf14009dd9db0 Mon Sep 17 00:00:00 2001 From: jreps Date: Thu, 6 Jun 2024 12:19:50 -0400 Subject: [PATCH 20/64] Update characterization-dechallengeRechallenge.R updating warning for dechal-rechal --- R/characterization-dechallengeRechallenge.R | 49 +++++++++++---------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/R/characterization-dechallengeRechallenge.R b/R/characterization-dechallengeRechallenge.R index 2f1a0e15..17baf1cd 100644 --- a/R/characterization-dechallengeRechallenge.R +++ b/R/characterization-dechallengeRechallenge.R @@ -91,28 +91,31 @@ characterizationDechallengeRechallengeServer <- function( ) }) - #databases(allData$databaseId) - #dechallengeStopInterval(allData$dechallengeStopInterval) - #dechallengeEvaluationWindow(allData$dechallengeEvaluationWindow) - - countDataTarget <- shiny::reactive({getCohortCounts(connection, - resultDatabaseSettings) %>% - dplyr::filter(cohortId %in% targetId()) + + targetUniquePeople <- shiny::reactive({ + isCohortUniquePeople( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + cohortId = targetId() + ) }) - countDataOutcome <- shiny::reactive({getCohortCounts(connection, - resultDatabaseSettings) %>% - dplyr::filter(cohortId %in% outcomeId()) + outcomeUniquePeople <- shiny::reactive({ + isCohortUniquePeople( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + cohortId = outcomeId() + ) }) warningTextTarget <- reactive({ - ifelse(countDataTarget()$cohortEntries[1] == countDataTarget()$cohortSubjects[1], + ifelse(targetUniquePeople(), 'WARNING: The target cohort does not have multiple records per person, so observing rechallenge attempts not possible.', '') }) warningTextOutcome <- reactive({ - ifelse(countDataOutcome()$cohortEntries[1] == countDataOutcome()$cohortSubjects[1], + ifelse(outcomeUniquePeople(), 'WARNING: The outcome cohort does not have multiple records per person, so observing dechallenge and rechallenge failures is not possible.', '') }) @@ -440,27 +443,25 @@ getDechalRechalFailData <- function( } -getCohortCounts <- function( +isCohortUniquePeople <- function( connectionHandler, - resultDatabaseSettings + resultDatabaseSettings, + cohortId ) { - sql <- "SELECT cc.cohort_id, cc.cohort_entries, cc.cohort_subjects + sql <- "SELECT + cc.database_id, cc.cohort_id, cc.cohort_entries, cc.cohort_subjects FROM @schema.@cg_table_prefixCOHORT_COUNT cc - join @schema.@database_table_prefix@database_table dt - on cc.database_id = dt.database_id - join @schema.@cg_table_prefixCOHORT_DEFINITION cd - on cd.cohort_definition_id = cc.cohort_id + where cc.cohort_id = @cohort_id ;" - return( - connectionHandler$queryDb( + res <- connectionHandler$queryDb( sql = sql, schema = resultDatabaseSettings$schema, cg_table_prefix = resultDatabaseSettings$cgTablePrefix, - database_table = resultDatabaseSettings$databaseTable, - database_table_prefix = resultDatabaseSettings$databaseTablePrefix + cohort_id = cohortId ) - ) + + return(sum(res$cohortEntries == res$cohortSubjects) == nrow(res)) } plotDechalRechal <- function( From 2ed680eeb4906caf4982e7a750e8592f729b2c82 Mon Sep 17 00:00:00 2001 From: jreps Date: Thu, 6 Jun 2024 14:25:19 -0400 Subject: [PATCH 21/64] Update characterization-dechallengeRechallenge.R - only display warning when there are warnings --- R/characterization-dechallengeRechallenge.R | 64 ++++++++++----------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/R/characterization-dechallengeRechallenge.R b/R/characterization-dechallengeRechallenge.R index 17baf1cd..0a73723c 100644 --- a/R/characterization-dechallengeRechallenge.R +++ b/R/characterization-dechallengeRechallenge.R @@ -31,26 +31,15 @@ characterizationDechallengeRechallengeViewer <- function(id) { ns <- shiny::NS(id) shiny::div( - shiny::fluidPage( - shiny::fluidRow( - shinydashboard::box( - status = 'warning', - width = '100%', - title = shiny::span( shiny::icon("triangle-exclamation"),'Warnings (if any)'), - solidHeader = TRUE, - shiny::htmlOutput(ns('warningTextTarget')), - shiny::htmlOutput(ns('warningTextOutcome')) - ) - ), - shiny::fluidRow( + + shiny::uiOutput(ns('warning')), + shinydashboard::box( status = 'info', width = '100%', solidHeader = TRUE, resultTableViewer(ns('tableResults')) ) - ) - ) ) } @@ -90,8 +79,9 @@ characterizationDechallengeRechallengeServer <- function( resultDatabaseSettings ) }) - - + + + # warning when not unique targetUniquePeople <- shiny::reactive({ isCohortUniquePeople( connectionHandler = connectionHandler, @@ -108,24 +98,30 @@ characterizationDechallengeRechallengeServer <- function( ) }) - warningTextTarget <- reactive({ - ifelse(targetUniquePeople(), - 'WARNING: The target cohort does not have multiple records per person, so observing rechallenge attempts not possible.', - '') - }) - - warningTextOutcome <- reactive({ - ifelse(outcomeUniquePeople(), - 'WARNING: The outcome cohort does not have multiple records per person, so observing dechallenge and rechallenge failures is not possible.', - '') - }) - - output$warningTextTarget <- renderText(warningTextTarget()) - output$warningTextOutcome <- renderText(warningTextOutcome()) - - - - + output$warning <- shiny::renderUI( + if(targetUniquePeople() || outcomeUniquePeople()){ + shinydashboard::box( + status = 'warning', + width = '100%', + title = shiny::span( shiny::icon("triangle-exclamation"),'Warnings'), + solidHeader = TRUE, + shiny::p( + ifelse(targetUniquePeople(), + 'WARNING: The target cohort does not have multiple records per person, so observing rechallenge attempts not possible.', + '') + ), + shiny::p( + ifelse(outcomeUniquePeople(), + 'WARNING: The outcome cohort does not have multiple records per person, so observing rechallenge attempts not possible.', + '') + ) + ) + } else{ + shiny::renderUI(shiny::div()) + } + ) + + characteriationDechalRechalColDefs <- function(){ result <- list( databaseName = reactable::colDef( From bbfa0c520123f4948ba35663b4acdfff89bc3ac2 Mon Sep 17 00:00:00 2001 From: Nathan Hall Date: Thu, 6 Jun 2024 15:41:42 -0400 Subject: [PATCH 22/64] fixing column alignment and incidence error messages --- R/characterization-incidence.R | 42 ++++++++++++++++++++++------------ R/components-data-viewer.R | 5 ++-- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/R/characterization-incidence.R b/R/characterization-incidence.R index fea0c89e..160e7d6f 100644 --- a/R/characterization-incidence.R +++ b/R/characterization-incidence.R @@ -621,7 +621,7 @@ characterizationIncidenceServer <- function( if (is.null(targetIds()) | is.null(outcomeIds()) ) { - extractedData(data.frame()) + shiny::validate("Please wait...") } else if(targetIds()[1] == outcomeIds()[1] && @@ -642,6 +642,7 @@ characterizationIncidenceServer <- function( ) filteredData <- shiny::reactive({ + shiny::req(nrow(extractedData() > 0)) if(nrow(extractedData()) > 0){ extractedData() %>% dplyr::relocate("tar", .before = "outcomes") %>% @@ -687,23 +688,36 @@ characterizationIncidenceServer <- function( ## CHECK - caused error for me but it is in Nate's latest code class(incidenceColList$genderName$filterMethod) <- "JS_EVAL" - #renderIrTable <- shiny::reactive( + # renderIrTable <- shiny::reactive( # { # filteredData() # } - #) + # ) - resultTableServer( - id = "incidenceRateTable", - df = filteredData, #renderIrTable, - selectedCols = c("cdmSourceAbbreviation", "targetName", "targetIdShort", "outcomeName", "outcomeIdShort", - "ageGroupName", "genderName", "startYear", "tar", "outcomes", - "incidenceProportionP100p", "incidenceRateP100py"), - sortedCols = c("ageGroupName", "genderName", "startYear", "incidenceRateP100py"), - elementId = "incidence-select", - colDefsInput = incidenceColList, - downloadedFileName = "incidenceRateTable-" - ) + resultTableServer( + id = "incidenceRateTable", + df = filteredData, #renderIrTable, + selectedCols = c("cdmSourceAbbreviation", "targetName", "targetIdShort", "outcomeName", "outcomeIdShort", + "ageGroupName", "genderName", "startYear", "tar", "outcomes", + "incidenceProportionP100p", "incidenceRateP100py"), + sortedCols = c("ageGroupName", "genderName", "startYear", "incidenceRateP100py"), + elementId = "incidence-select", + colDefsInput = incidenceColList, + downloadedFileName = "incidenceRateTable-" + ) + + + # resultTableServer( + # id = "incidenceRateTable", + # df = filteredData, #renderIrTable, + # selectedCols = c("cdmSourceAbbreviation", "targetName", "targetIdShort", "outcomeName", "outcomeIdShort", + # "ageGroupName", "genderName", "startYear", "tar", "outcomes", + # "incidenceProportionP100p", "incidenceRateP100py"), + # sortedCols = c("ageGroupName", "genderName", "startYear", "incidenceRateP100py"), + # elementId = "incidence-select", + # colDefsInput = incidenceColList, + # downloadedFileName = "incidenceRateTable-" + # ) '%!in%' <- function(x,y)!('%in%'(x,y)) diff --git a/R/components-data-viewer.R b/R/components-data-viewer.R index cdccb6a2..5b1f5cb3 100644 --- a/R/components-data-viewer.R +++ b/R/components-data-viewer.R @@ -246,6 +246,7 @@ resultTableServer <- function( onClick <- NULL } + output$columnSelector <- shiny::renderUI({ shinyWidgets::pickerInput( @@ -267,6 +268,7 @@ resultTableServer <- function( ) }) + #need to try adding browser() to all reactives to see why selected cols isnt working @@ -324,7 +326,6 @@ function filterMinValue(rows, columnId, filterValue) { }); } " - output$resultData <- reactable::renderReactable({ if (is.null(input$dataCols)) { data = newdf() @@ -356,7 +357,7 @@ function filterMinValue(rows, columnId, filterValue) { showSortIcon = TRUE, striped = TRUE, highlight = TRUE, - defaultColDef = reactable::colDef(align = "left"), + #defaultColDef = reactable::colDef(align = "left"), defaultSorted = sortedColumns(), rowStyle = list( height = height From 1a15567c49a085b7939122adf925c4593b8aa9dd Mon Sep 17 00:00:00 2001 From: jreps Date: Fri, 7 Jun 2024 12:04:54 -0400 Subject: [PATCH 23/64] adding drop down and slide filters --- R/characterization-caseSeries.R | 116 +++++++++++++++++++++++++++---- R/characterization-cohorts.R | 108 +++++++++++++++++++++++++--- R/characterization-database.R | 18 +++-- R/characterization-riskFactors.R | 116 +++++++++++++++++++++++++++---- 4 files changed, 315 insertions(+), 43 deletions(-) diff --git a/R/characterization-caseSeries.R b/R/characterization-caseSeries.R index d0cf5692..b143415b 100644 --- a/R/characterization-caseSeries.R +++ b/R/characterization-caseSeries.R @@ -125,15 +125,21 @@ characterizationCaseSeriesServer <- function( binTableOutputs <- resultTableServer( id = "binaryTable", df = allData$binary, - colDefsInput = colDefsBinary(), # function below - addActions = NULL + colDefsInput = colDefsBinary( + elementId = session$ns('binary-table-filter') + ), # function below + addActions = NULL, + elementId = session$ns('binary-table-filter') ) conTableOutputs <- resultTableServer( id = "continuousTable", df = allData$continuous, - colDefsInput = colDefsContinuous(), # function below - addActions = NULL + colDefsInput = colDefsContinuous( + elementId = session$ns('continuous-table-filter') + ), # function below + addActions = NULL, + elementId = session$ns('continuous-table-filter') ) }) @@ -382,7 +388,9 @@ caseSeriesTable <- function( return(allResults) } -colDefsBinary <- function(){ +colDefsBinary <- function( + elementId + ){ result <- list( covariateName = reactable::colDef( header = withTooltip("Covariate Name", @@ -396,12 +404,34 @@ colDefsBinary <- function(){ minPriorObservation = reactable::colDef( header = withTooltip("Min Prior Observation", "Minimum prior observation time (days)"), - filterable = T + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } ), outcomeWashoutDays = reactable::colDef( header = withTooltip("Outcome Washout Days", "Number of days for the outcome washout"), - filterable = T + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } ), casePostOutcomeDuration = reactable::colDef( header = withTooltip("Days Post-outcome Covariate Window", @@ -466,10 +496,11 @@ colDefsBinary <- function(){ ), analysisName = reactable::colDef( + filterable = T, filterInput = function(values, name) { shiny::tags$select( # Set to undefined to clear the filter - onchange = sprintf("Reactable.setFilter('desc-cont-select', '%s', event.target.value || undefined)", name), + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), # "All" has an empty value to clear the filter, and is the default option shiny::tags$option(value = "", "All"), lapply(unique(values), shiny::tags$option), @@ -482,7 +513,9 @@ colDefsBinary <- function(){ return(result) } -colDefsContinuous <- function(){ +colDefsContinuous <- function( + elementId + ){ result <- list( cohortDefinitionId = reactable::colDef( header = withTooltip("Cohort ID", @@ -492,7 +525,18 @@ colDefsContinuous <- function(){ type = reactable::colDef( header = withTooltip("Time of Cases Relative to Index", "Time period relative to index date for cases for the covariate"), - filterable = T + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } ), covariateName = reactable::colDef( header = withTooltip("Covariate Name", @@ -506,22 +550,66 @@ colDefsContinuous <- function(){ minPriorObservation = reactable::colDef( header = withTooltip("Min Prior Observation", "Minimum prior observation time (days)"), - filterable = T + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } ), outcomeWashoutDays = reactable::colDef( header = withTooltip("Outcome Washout Days", "Number of days for the outcome washout"), - filterable = T + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } ), casePostOutcomeDuration = reactable::colDef( header = withTooltip("Days Post-outcome Covariate Window", "Number of days after the outcome we look for the covariate"), - filterable = T + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } ), casePreTargetDuration = reactable::colDef( header = withTooltip("Days Pre-exposure Covariate Window", "Number of days before the exposure we look for the covariate"), - filterable = T + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } ), countValue = reactable::colDef( header = withTooltip("# Cases with Feature", diff --git a/R/characterization-cohorts.R b/R/characterization-cohorts.R index c3aa6eb7..15335851 100644 --- a/R/characterization-cohorts.R +++ b/R/characterization-cohorts.R @@ -235,20 +235,29 @@ characterizationCohortComparisonServer <- function( id = 'mainTable', df = resultTable, colDefsInput = characterizationCohortsColumns( - addExtras = T - ) + addExtras = T, + elementId = session$ns('main-table-filter') + ), + elementId = session$ns('main-table-filter') ) resultTableServer( id = 'continuousTable', df = continuousTable, - colDefsInput = characterizationCohortsColumnsContinuous(addExtras = T) + colDefsInput = characterizationCohortsColumnsContinuous( + addExtras = T, + elementId = session$ns('continuous-table-filter') + ), + elementId = session$ns('continuous-table-filter') ) resultTableServer( id = 'countTable', df = countTable, - colDefsInput = characteriationCountTableColDefs() + colDefsInput = characteriationCountTableColDefs( + elementId = session$ns('count-table-filter') + ), + elementId = session$ns('count-table-filter') )} }) @@ -261,7 +270,8 @@ characterizationCohortComparisonServer <- function( characterizationCohortsColumns <- function( - addExtras = F + addExtras = F, + elementId ){ res <- list( @@ -282,7 +292,18 @@ characterizationCohortsColumns <- function( "Min Prior Obs", "The minimum prior observation a patient in the target population must have to be included."), - filterable = T + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } ), SMD = reactable::colDef( header = withTooltip("SMD", @@ -292,7 +313,25 @@ characterizationCohortsColumns <- function( absSMD = reactable::colDef( header = withTooltip("absSMD", "Absolute standardized mean difference between the target and comparator percentages"), - format = reactable::colFormat(digits = 3) + format = reactable::colFormat(digits = 3), + filterable = TRUE, + filterMethod = reactable::JS("function(rows, columnId, filterValue) { + return rows.filter(function(row) { + return row.values[columnId] >= filterValue + }) + }"), + filterInput = function(values, name) { + oninput <- sprintf("Reactable.setFilter('%s', '%s', this.value)", elementId, name) + shiny::tags$input( + type = "range", + min = floor(min(values)), + max = ceiling(max(values)), + value = floor(min(values)), + oninput = oninput, + onchange = oninput, # For IE11 support + "aria-label" = sprintf("Filter by minimum %s", name) + ) + } ), analysisName = reactable::colDef( header = withTooltip( @@ -341,6 +380,7 @@ characterizationCohortsColumns <- function( } characteriationCountTableColDefs <- function( + elementId ){ result <- list( selection = reactable::colDef( @@ -356,7 +396,18 @@ characteriationCountTableColDefs <- function( "Min Prior Obs", "The minimum prior observation a patient in the target population must have to be included."), - filterable = T + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } ), rowCount = reactable::colDef( header = withTooltip("Record Count", @@ -373,7 +424,8 @@ characteriationCountTableColDefs <- function( } characterizationCohortsColumnsContinuous <- function( - addExtras = F + addExtras = F, + elementId ){ res <- list( covariateName = reactable::colDef( @@ -389,7 +441,18 @@ characterizationCohortsColumnsContinuous <- function( "Database", "The name of the database" ), - filterable = T + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } ), covariateId = reactable::colDef( show = F, @@ -401,7 +464,18 @@ characterizationCohortsColumnsContinuous <- function( "Min Prior Obs", "The minimum prior observation a patient in the target population must have to be included."), - filterable = T + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } ), outcomeWashoutPeriod = reactable::colDef( show = F @@ -411,6 +485,18 @@ characterizationCohortsColumnsContinuous <- function( "Number of people with the covariate in the cohort."), cell = function(value) { if (value >= 0) value else '< min threshold' + }, + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) } ), averageValue = reactable::colDef( diff --git a/R/characterization-database.R b/R/characterization-database.R index 54050890..df7fcc66 100644 --- a/R/characterization-database.R +++ b/R/characterization-database.R @@ -218,23 +218,33 @@ characterizationDatabaseComparisonServer <- function( resultTableServer( id = 'countTable', df = countTable, - colDefsInput = characteriationCountTableColDefs() + colDefsInput = characteriationCountTableColDefs( + elementId = session$ns('count-table-filter') + ), + elementId = session$ns('count-table-filter') ) resultTableServer( id = 'mainTable', df = result$table, colDefsInput = append( - characterizationCohortsColumns(), + characterizationCohortsColumns( + elementId = session$ns('main-table-filter') + ), append( sumColumns, meanColumns ) - ) + ), + elementId = session$ns('main-table-filter') ) + resultTableServer( id = 'continuousTable', df = continuousTable, - colDefsInput = characterizationCohortsColumnsContinuous() + colDefsInput = characterizationCohortsColumnsContinuous( + elementId = session$ns('continuous-table-filter') + ), + elementId = session$ns('continuous-table-filter') ) }) diff --git a/R/characterization-riskFactors.R b/R/characterization-riskFactors.R index 589683b5..f60b31ce 100644 --- a/R/characterization-riskFactors.R +++ b/R/characterization-riskFactors.R @@ -126,15 +126,21 @@ characterizationRiskFactorServer <- function( binTableOutputs <- resultTableServer( id = "binaryTable", df = allData$binary, - colDefsInput = characteriationRiskFactorColDefs(), # function below - addActions = NULL + colDefsInput = characteriationRiskFactorColDefs( + elementId = session$ns('binary-table-filter') + ), # function below + addActions = NULL, + elementId = session$ns('binary-table-filter') ) conTableOutputs <- resultTableServer( id = "continuousTable", df = allData$continuous, - colDefsInput = characteriationRiskFactorContColDefs(), # function below - addActions = NULL + colDefsInput = characteriationRiskFactorContColDefs( + elementId = session$ns('continuous-table-filter') + ), # function below + addActions = NULL, + elementId = session$ns('continuous-table-filter') ) }) @@ -575,7 +581,9 @@ riskFactorContinuousTable <- function( } -characteriationRiskFactorColDefs <- function(){ +characteriationRiskFactorColDefs <- function( + elementId + ){ result <- list( covariateId = reactable::colDef( show = F @@ -589,12 +597,34 @@ characteriationRiskFactorColDefs <- function(){ minPriorObservation = reactable::colDef( header = withTooltip("Min Prior Observation", "Minimum prior observation time (days)"), - filterable = T + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } ), outcomeWashoutDays = reactable::colDef( header = withTooltip("Outcome Washout Days", "Number of days for the outcome washout"), - filterable = T + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } ), nonCaseSumValue = reactable::colDef( header = withTooltip("# Non-cases with Feature Before Exposure", @@ -647,8 +677,25 @@ characteriationRiskFactorColDefs <- function(){ absSMD = reactable::colDef( header = withTooltip("absSMD", "Absolute value of standardized mean difference"), - filterable = T, - format = reactable::colFormat(digits = 2, percent = F) + format = reactable::colFormat(digits = 2, percent = F), + filterable = TRUE, + filterMethod = reactable::JS("function(rows, columnId, filterValue) { + return rows.filter(function(row) { + return row.values[columnId] >= filterValue + }) + }"), + filterInput = function(values, name) { + oninput <- sprintf("Reactable.setFilter('%s', '%s', this.value)", elementId, name) + shiny::tags$input( + type = "range", + min = floor(min(values)), + max = ceiling(max(values)), + value = floor(min(values)), + oninput = oninput, + onchange = oninput, # For IE11 support + "aria-label" = sprintf("Filter by minimum %s", name) + ) + } ) ) return(result) @@ -656,7 +703,9 @@ characteriationRiskFactorColDefs <- function(){ -characteriationRiskFactorContColDefs <- function(){ +characteriationRiskFactorContColDefs <- function( + elementId + ){ result <- list( covariateName = reactable::colDef( header = withTooltip("Covariate Name", @@ -670,12 +719,34 @@ characteriationRiskFactorContColDefs <- function(){ minPriorObservation = reactable::colDef( header = withTooltip("Min Prior Observation", "Minimum prior observation time (days)"), - filterable = T + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } ), outcomeWashoutDays = reactable::colDef( header = withTooltip("Outcome Washout Days", "Number of days for the outcome washout"), - filterable = T + filterable = T, + filterInput = function(values, name) { + shiny::tags$select( + # Set to undefined to clear the filter + onchange = sprintf("Reactable.setFilter('%s', '%s', event.target.value || undefined)", elementId, name), + # "All" has an empty value to clear the filter, and is the default option + shiny::tags$option(value = "", "All"), + lapply(unique(values), shiny::tags$option), + "aria-label" = sprintf("Filter %s", name), + style = "width: 100%; height: 28px;" + ) + } ), targetCountValue = reactable::colDef( header = withTooltip("# of Target with Feature", @@ -854,8 +925,25 @@ characteriationRiskFactorContColDefs <- function(){ absSMD = reactable::colDef( header = withTooltip("absSMD", "Absolute value of the standardized mean difference"), - filterable = T, - format = reactable::colFormat(digits = 2, percent = F) + format = reactable::colFormat(digits = 2, percent = F), + filterable = TRUE, + filterMethod = reactable::JS("function(rows, columnId, filterValue) { + return rows.filter(function(row) { + return row.values[columnId] >= filterValue + }) + }"), + filterInput = function(values, name) { + oninput <- sprintf("Reactable.setFilter('%s', '%s', this.value)", elementId, name) + shiny::tags$input( + type = "range", + min = floor(min(values)), + max = ceiling(max(values)), + value = floor(min(values)), + oninput = oninput, + onchange = oninput, # For IE11 support + "aria-label" = sprintf("Filter by minimum %s", name) + ) + } ) ) return(result) From 674f05dc12f7e42cfc7d7d99b864e6ed26524c06 Mon Sep 17 00:00:00 2001 From: jreps Date: Fri, 7 Jun 2024 13:58:50 -0400 Subject: [PATCH 24/64] fixing scrolls fixing scrolls --- R/characterization-cohorts.R | 6 +++--- R/characterization-riskFactors.R | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/R/characterization-cohorts.R b/R/characterization-cohorts.R index 15335851..bbf593a3 100644 --- a/R/characterization-cohorts.R +++ b/R/characterization-cohorts.R @@ -324,9 +324,9 @@ characterizationCohortsColumns <- function( oninput <- sprintf("Reactable.setFilter('%s', '%s', this.value)", elementId, name) shiny::tags$input( type = "range", - min = floor(min(values)), - max = ceiling(max(values)), - value = floor(min(values)), + min = floor(min(values, na.rm = T)), + max = ceiling(max(values, na.rm = T)), + value = floor(min(values, na.rm = T)), oninput = oninput, onchange = oninput, # For IE11 support "aria-label" = sprintf("Filter by minimum %s", name) diff --git a/R/characterization-riskFactors.R b/R/characterization-riskFactors.R index f60b31ce..c479b73b 100644 --- a/R/characterization-riskFactors.R +++ b/R/characterization-riskFactors.R @@ -688,9 +688,9 @@ characteriationRiskFactorColDefs <- function( oninput <- sprintf("Reactable.setFilter('%s', '%s', this.value)", elementId, name) shiny::tags$input( type = "range", - min = floor(min(values)), - max = ceiling(max(values)), - value = floor(min(values)), + min = floor(min(values, na.rm = T)), + max = ceiling(max(values, na.rm = T)), + value = floor(min(values, na.rm = T)), oninput = oninput, onchange = oninput, # For IE11 support "aria-label" = sprintf("Filter by minimum %s", name) @@ -936,9 +936,9 @@ characteriationRiskFactorContColDefs <- function( oninput <- sprintf("Reactable.setFilter('%s', '%s', this.value)", elementId, name) shiny::tags$input( type = "range", - min = floor(min(values)), - max = ceiling(max(values)), - value = floor(min(values)), + min = floor(min(values, na.rm = T)), + max = ceiling(max(values, na.rm = T)), + value = floor(min(values, na.rm = T)), oninput = oninput, onchange = oninput, # For IE11 support "aria-label" = sprintf("Filter by minimum %s", name) From 7160607c4dc6f850b2e8a0a8f93f380426b832ba Mon Sep 17 00:00:00 2001 From: jreps Date: Tue, 11 Jun 2024 08:21:28 -0400 Subject: [PATCH 25/64] Update characterization-cohorts.R fixing SMD calculation in cohorts --- R/characterization-cohorts.R | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/R/characterization-cohorts.R b/R/characterization-cohorts.R index bbf593a3..d943ae63 100644 --- a/R/characterization-cohorts.R +++ b/R/characterization-cohorts.R @@ -819,11 +819,24 @@ characterizatonGetCohortData <- function( # add SMD if(sum(c('averageValue_1','averageValue_2') %in% colnames(result)) == 2){ convertMissing <- function(vec){sapply(vec, function(x) ifelse(x==-1, minThreshold, x))} - result$firstVar <- convertMissing(result$averageValue_1)*(1-convertMissing(result$averageValue_1))^2 - result$secondVar <- convertMissing(result$averageValue_2)*(1-convertMissing(result$averageValue_2))^2 + + Ns <- c() + for(minPriorObservation in unique(result$minPriorObservation)){ + ind <- result$minPriorObservation == minPriorObservation + Ns <- rbind(Ns, + data.frame( + minPriorObservation = minPriorObservation, + N_1 = max(result$sumValue_1[ind]/result$averageValue_1[ind], na.rm = T), + N_2 = max(result$sumValue_2[ind]/result$averageValue_2[ind], na.rm = T) + ) + ) + } + result <- merge(result, Ns, by = 'minPriorObservation') + result$firstVar <- ((convertMissing(result$averageValue_1)-1)^2*result$sumValue_1 + (convertMissing(result$averageValue_1)-0)^2*(result$N_1-result$sumValue_1))/result$N_1 + result$secondVar <- ((convertMissing(result$averageValue_2)-1)^2*result$sumValue_2 + (convertMissing(result$averageValue_2)-0)^2*(result$N_2-result$sumValue_2))/result$N_2 result$SMD <- (convertMissing(result$averageValue_1) - convertMissing(result$averageValue_2))/(sqrt((result$firstVar+result$secondVar)/2)) result$absSMD <- abs(result$SMD) - result <- result %>% dplyr::select(-"firstVar",-"secondVar") + result <- result %>% dplyr::select(-"firstVar",-"secondVar", -"N_1", -"N_2") } else{ shiny::showNotification('Unable to add SMD due to missing columns') From 8326b094b5f3eac27f7d6b4e7d99c6399754a8aa Mon Sep 17 00:00:00 2001 From: jreps Date: Tue, 11 Jun 2024 09:58:36 -0400 Subject: [PATCH 26/64] minor bug fixes - fixing tar changing before generate in case series - fixing columns showing in selection that should be hidden --- R/characterization-caseSeries.R | 11 ++++++----- R/components-data-viewer.R | 13 ++++++++++--- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/R/characterization-caseSeries.R b/R/characterization-caseSeries.R index b143415b..abb2808c 100644 --- a/R/characterization-caseSeries.R +++ b/R/characterization-caseSeries.R @@ -99,14 +99,15 @@ characterizationCaseSeriesServer <- function( }) # save the selections - selected <- shiny::reactive({ - data.frame( - database = names(options()$databaseIds)[which(input$databaseId == options()$databaseIds)], - time_at_risk = names(options()$tarInds)[which(input$tarInd == options()$tarInds)] - )}) + selected <- shiny::reactiveVal(NULL) shiny::observeEvent(input$generate, { + selected(data.frame( + database = names(options()$databaseIds)[which(input$databaseId == options()$databaseIds)], + time_at_risk = names(options()$tarInds)[which(input$tarInd == options()$tarInds)] + )) + inputSelectionDfServer( id = 'inputSelected', dataFrameRow = selected, diff --git a/R/components-data-viewer.R b/R/components-data-viewer.R index 5b1f5cb3..5788fd04 100644 --- a/R/components-data-viewer.R +++ b/R/components-data-viewer.R @@ -175,6 +175,13 @@ resultTableServer <- function( id, function(input, output, session) { + + # find the columns that are set to show=F + colNames <- names(colDefsInput) + showCol <- unlist(lapply(colDefsInput, function(x) ifelse(is.null(x$show), T, x$show))) + showColNames <- colNames[showCol] + + # convert a data.frame to a reactive if(!inherits(df, 'reactive')){ df <- shiny::reactiveVal(df) @@ -200,8 +207,8 @@ resultTableServer <- function( if(!is.null(selectedCols)){ intersect(colnames(newdf()), selectedCols) } - else{ - colnames(newdf()) + else{ # edited to restrict to colDef - show = T columns + intersect(colnames(newdf()), showColNames) } }) @@ -252,7 +259,7 @@ resultTableServer <- function( shinyWidgets::pickerInput( inputId = session$ns('dataCols'), label = 'Select Columns to Display: ', - choices = colnames(newdf()), + choices = intersect(colnames(newdf()), showColNames), # edited to only show columns show = T selected = selectedColumns(), choicesOpt = list(style = rep_len("color: black;", 999)), multiple = T, From d01fbf59fe45301c0b4e5830b0c912021d2213e5 Mon Sep 17 00:00:00 2001 From: jreps Date: Tue, 11 Jun 2024 14:47:32 -0400 Subject: [PATCH 27/64] updating table download - updating csv export to excel export with a details sheet --- DESCRIPTION | 1 + R/components-data-viewer.R | 12 +++++++----- man/resultTableServer.Rd | 3 +++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 9b6c6ee0..50d599c0 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -24,6 +24,7 @@ Imports: htmltools, lubridate, methods, + openxlsx, ParallelLogger, plotly, purrr, diff --git a/R/components-data-viewer.R b/R/components-data-viewer.R index 5788fd04..f7035f65 100644 --- a/R/components-data-viewer.R +++ b/R/components-data-viewer.R @@ -149,6 +149,7 @@ ohdsiReactableTheme <- reactable::reactableTheme( #' @param id string, table id must match resultsTableViewer function #' @param df reactive that returns a data frame #' @param colDefsInput named list of reactable::colDefs +#' @param details The details of the results such as cohort names and database names #' @param selectedCols string vector of columns the reactable should display to start by default. Defaults to ALL if not specified. #' @param sortedCols string vector of columns the reactable should sort by by default. Defaults to no sort if not specified. #' @param elementId optional string vector of element Id name for custom dropdown filtering if present in the customColDef list. Defaults to NULL. @@ -164,6 +165,7 @@ resultTableServer <- function( id, #string df, #data.frame colDefsInput, + details = data.frame(), # details about the data.frame such as target and database name selectedCols = NULL, sortedCols = NULL, elementId = NULL, @@ -382,11 +384,11 @@ function filterMinValue(rows, columnId, filterValue) { paste('result-data-full-', downloadedFileName, Sys.Date(), '.csv', sep = '') }, content = function(con) { - utils::write.csv( - x = df(), - file = con, - row.names = F - ) + wb <- openxlsx::buildWorkbook(x = list( + details = details, + results = df() + )) + openxlsx::saveWorkbook(wb = wb, file = con) } ) diff --git a/man/resultTableServer.Rd b/man/resultTableServer.Rd index 8ca67d84..4fb62e67 100644 --- a/man/resultTableServer.Rd +++ b/man/resultTableServer.Rd @@ -8,6 +8,7 @@ resultTableServer( id, df, colDefsInput, + details = data.frame(), selectedCols = NULL, sortedCols = NULL, elementId = NULL, @@ -23,6 +24,8 @@ resultTableServer( \item{colDefsInput}{named list of reactable::colDefs} +\item{details}{The details of the results such as cohort names and database names} + \item{selectedCols}{string vector of columns the reactable should display to start by default. Defaults to ALL if not specified.} \item{sortedCols}{string vector of columns the reactable should sort by by default. Defaults to no sort if not specified.} From c3bffd703307d6768db5a958ab9e35780c1c9ae6 Mon Sep 17 00:00:00 2001 From: jreps Date: Tue, 11 Jun 2024 14:53:38 -0400 Subject: [PATCH 28/64] Update components-data-viewer.R changing saving file type --- R/components-data-viewer.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/components-data-viewer.R b/R/components-data-viewer.R index f7035f65..29d770e9 100644 --- a/R/components-data-viewer.R +++ b/R/components-data-viewer.R @@ -381,7 +381,7 @@ function filterMinValue(rows, columnId, filterValue) { # download full data button output$downloadDataFull <- shiny::downloadHandler( filename = function() { - paste('result-data-full-', downloadedFileName, Sys.Date(), '.csv', sep = '') + paste('result-data-full-', downloadedFileName, Sys.Date(), '.xlsx', sep = '') }, content = function(con) { wb <- openxlsx::buildWorkbook(x = list( From 114d2d0d43aeecc01412a86444403bf76be4ad2a Mon Sep 17 00:00:00 2001 From: jreps Date: Tue, 11 Jun 2024 15:24:56 -0400 Subject: [PATCH 29/64] adding details to exported results adding details to exported results for characterization cohorts and databases --- R/characterization-cohorts.R | 25 ++++++++++++++++++++++++- R/characterization-database.R | 22 ++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/R/characterization-cohorts.R b/R/characterization-cohorts.R index d943ae63..e7e79394 100644 --- a/R/characterization-cohorts.R +++ b/R/characterization-cohorts.R @@ -167,6 +167,8 @@ characterizationCohortComparisonServer <- function( selected <- shiny::reactiveVal() shiny::observeEvent(input$generate,{ + targetGroups <- characterizationGetChildren(options, parentIndex()) + runTables <- TRUE if(is.null(subTargetId()) | is.null(input$comparatorId)){ @@ -230,10 +232,17 @@ characterizationCohortComparisonServer <- function( targetIds = c(selection1,selection2), databaseIds = input$databaseId ) - + resultTableServer( id = 'mainTable', df = resultTable, + details = data.frame( + Target = names(targetGroups)[which(targetGroups == subTargetId())], + Comparator = names(comparatorGroups())[which(comparatorGroups() == input$comparatorId)], + Database = names(inputVals()$databaseIds)[input$databaseId == inputVals()$databaseIds], + Analysis = 'Cohort comparison within database' + ), + downloadedFileName = 'cohort_comparison_binary', colDefsInput = characterizationCohortsColumns( addExtras = T, elementId = session$ns('main-table-filter') @@ -244,6 +253,13 @@ characterizationCohortComparisonServer <- function( resultTableServer( id = 'continuousTable', df = continuousTable, + details = data.frame( + Target = names(targetGroups)[which(targetGroups == subTargetId())], + Comparator = names(comparatorGroups())[which(comparatorGroups() == input$comparatorId)], + Database = names(inputVals()$databaseIds)[input$databaseId == inputVals()$databaseIds], + Analysis = 'Cohort comparison within database' + ), + downloadedFileName = 'cohort_comparison_cont', colDefsInput = characterizationCohortsColumnsContinuous( addExtras = T, elementId = session$ns('continuous-table-filter') @@ -254,6 +270,13 @@ characterizationCohortComparisonServer <- function( resultTableServer( id = 'countTable', df = countTable, + details = data.frame( + Target = names(targetGroups)[which(targetGroups == subTargetId())], + Comparator = names(comparatorGroups())[which(comparatorGroups() == input$comparatorId)], + Database = names(inputVals()$databaseIds)[input$databaseId == inputVals()$databaseIds], + Analysis = 'Cohort comparison within database' + ), + downloadedFileName = 'cohort_comparison_count', colDefsInput = characteriationCountTableColDefs( elementId = session$ns('count-table-filter') ), diff --git a/R/characterization-database.R b/R/characterization-database.R index df7fcc66..46b3b31e 100644 --- a/R/characterization-database.R +++ b/R/characterization-database.R @@ -214,10 +214,18 @@ characterizationDatabaseComparisonServer <- function( }) names(sumColumns) <- unlist(lapply(1:nrow(databaseNames), function(i) paste0('sumValue_',databaseNames$id[i]))) + targetGroups <- characterizationGetChildren(options, parentIndex()) resultTableServer( id = 'countTable', df = countTable, + details = data.frame( + Target = names(targetGroups)[which(targetGroups == subTargetId())], + Databases = selectedDatabases, + `Minimum Covariate Threshold` = input$minThreshold, + Analysis = 'Cohort comparison across databases' + ), + downloadedFileName = 'database_comparison_counts', colDefsInput = characteriationCountTableColDefs( elementId = session$ns('count-table-filter') ), @@ -226,6 +234,13 @@ characterizationDatabaseComparisonServer <- function( resultTableServer( id = 'mainTable', df = result$table, + details = data.frame( + Target = names(targetGroups)[which(targetGroups == subTargetId())], + Databases = selectedDatabases, + `Minimum Covariate Threshold` = input$minThreshold, + Analysis = 'Cohort comparison across databases' + ), + downloadedFileName = 'database_comparison_binary', colDefsInput = append( characterizationCohortsColumns( elementId = session$ns('main-table-filter') @@ -241,6 +256,13 @@ characterizationDatabaseComparisonServer <- function( resultTableServer( id = 'continuousTable', df = continuousTable, + details = data.frame( + Target = names(targetGroups)[which(targetGroups == subTargetId())], + Databases = selectedDatabases, + `Minimum Covariate Threshold` = input$minThreshold, + Analysis = 'Cohort comparison across databases' + ), + downloadedFileName = 'database_comparison_cont', colDefsInput = characterizationCohortsColumnsContinuous( elementId = session$ns('continuous-table-filter') ), From 95bd9a1bf7ef662520f8e93240606182129ee187 Mon Sep 17 00:00:00 2001 From: jreps Date: Wed, 12 Jun 2024 08:42:20 -0400 Subject: [PATCH 30/64] Update components-data-viewer.R fixing actions not being includes as it is an extra column that is added outside the coldDef --- R/components-data-viewer.R | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/R/components-data-viewer.R b/R/components-data-viewer.R index 29d770e9..eefba624 100644 --- a/R/components-data-viewer.R +++ b/R/components-data-viewer.R @@ -181,7 +181,11 @@ resultTableServer <- function( # find the columns that are set to show=F colNames <- names(colDefsInput) showCol <- unlist(lapply(colDefsInput, function(x) ifelse(is.null(x$show), T, x$show))) - showColNames <- colNames[showCol] + if(is.null(addActions)){ + showColNames <- colNames[showCol] + } else{ + showColNames <- c(colNames[showCol],'actions') + } # convert a data.frame to a reactive From 7aa59101a969a18886040d170d5c5eeefea730dc Mon Sep 17 00:00:00 2001 From: jreps Date: Wed, 12 Jun 2024 11:10:01 -0400 Subject: [PATCH 31/64] Update characterization-caseSeries.R - adding details to case-series download --- R/characterization-caseSeries.R | 45 ++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/R/characterization-caseSeries.R b/R/characterization-caseSeries.R index abb2808c..c343e861 100644 --- a/R/characterization-caseSeries.R +++ b/R/characterization-caseSeries.R @@ -125,7 +125,15 @@ characterizationCaseSeriesServer <- function( binTableOutputs <- resultTableServer( id = "binaryTable", - df = allData$binary, + df = allData$binary, + details = data.frame( + database = names(options()$databaseIds)[which(input$databaseId == options()$databaseIds)], + tar = names(options()$tarInds)[which(input$tarInd == options()$tarInds)], + target = options()$targetName, + outcome = options()$outcomeName, + description = "Case series binary features before target index, during exposure and after outcome index" + ), + downloadedFileName = 'case_series_binary', colDefsInput = colDefsBinary( elementId = session$ns('binary-table-filter') ), # function below @@ -136,6 +144,14 @@ characterizationCaseSeriesServer <- function( conTableOutputs <- resultTableServer( id = "continuousTable", df = allData$continuous, + details = data.frame( + database = names(options()$databaseIds)[which(input$databaseId == options()$databaseIds)], + tar = names(options()$tarInds)[which(input$tarInd == options()$tarInds)], + target = options()$targetName, + outcome = options()$outcomeName, + description = "Case series continuous features before target index, during exposure and after outcome index" + ), + downloadedFileName = 'case_series_continuous', colDefsInput = colDefsContinuous( elementId = session$ns('continuous-table-filter') ), # function below @@ -161,7 +177,10 @@ characterizationGetCaseSeriesOptions <- function( sql <- "SELECT distinct s.database_id, d.CDM_SOURCE_ABBREVIATION as database_name, s.setting_id, s.RISK_WINDOW_START, s.RISK_WINDOW_END, - s.START_ANCHOR, s.END_ANCHOR + s.START_ANCHOR, s.END_ANCHOR, + ct1.cohort_name as target_name, + ct2.cohort_name as outcome_name + from @schema.@c_table_prefixsettings s inner join @schema.@database_meta_table d @@ -172,6 +191,18 @@ characterizationGetCaseSeriesOptions <- function( and cd.target_cohort_id = @target_id and cd.outcome_cohort_id = @outcome_id and cd.cohort_type = 'TnO' + + inner join + @schema.@cg_table_prefixcohort_definition ct1 + on + ct1.cohort_definition_id = cd.target_cohort_id + + inner join + @schema.@cg_table_prefixcohort_definition ct2 + on + ct2.cohort_definition_id = cd.outcome_cohort_id + + ;" options <- connectionHandler$queryDb( @@ -180,9 +211,13 @@ characterizationGetCaseSeriesOptions <- function( c_table_prefix = resultDatabaseSettings$cTablePrefix, target_id = targetId, outcome_id = outcomeId, - database_meta_table = resultDatabaseSettings$databaseTable + database_meta_table = resultDatabaseSettings$databaseTable, + cg_table_prefix = resultDatabaseSettings$cgTablePrefix ) + outcomeName <- unique(options$outcomeName) + targetName <- unique(options$targetName) + db <- unique(options$databaseId) names(db) <- unique(options$databaseName) @@ -198,7 +233,9 @@ characterizationGetCaseSeriesOptions <- function( list( databaseIds = db, tarInds = tarInds, - tarList = tarList + tarList = tarList, + outcomeName = outcomeName, + targetName = targetName ) ) From 26a15d9f67071e4dcbe9ed84487abebac24f80c7 Mon Sep 17 00:00:00 2001 From: jreps Date: Thu, 13 Jun 2024 13:11:52 -0400 Subject: [PATCH 32/64] fixing issue with SCCS not showing fixing issue with SCCS not showing --- R/estimation-main.R | 111 +++++++++++++++++++++++--------------------- R/report-main.R | 10 +++- 2 files changed, 66 insertions(+), 55 deletions(-) diff --git a/R/estimation-main.R b/R/estimation-main.R index 9a725a63..8f7eaf60 100644 --- a/R/estimation-main.R +++ b/R/estimation-main.R @@ -160,9 +160,9 @@ estimationServer <- function( resultDatabaseSettings, includeCharacterization = F, includeCohortIncidence = F, - includeCohortMethod = T, + includeCohortMethod = "Cohort Method" %in% estimationTypes, includePrediction = F, - includeSccs = F # slow so turning off + includeSccs = "SCCS" %in% estimationTypes # slow so turning off ) # Targets @@ -171,9 +171,9 @@ estimationServer <- function( # initial outcomes for first T outcomeDf <- options$tos[[1]] + outcomes <- shiny::reactiveVal(outcomeDf) initialOutcomes <- outcomeDf$outcomeId names(initialOutcomes ) <- outcomeDf$outcomeName - outcomes <- shiny::reactiveVal() shiny::observeEvent(input$targetId,{ @@ -194,10 +194,9 @@ estimationServer <- function( )) - if(length(options()$outcomeId)>0){ - outcomeDf <- options() - outcomesVector <- options()$outcomeId - names(outcomesVector) <- options()$outcomeName + if(length(outcomes()$outcomeId)>0){ + outcomesVector <- outcomes()$outcomeId + names(outcomesVector) <- outcomes()$outcomeName shiny::updateSelectInput( session = session, @@ -258,7 +257,7 @@ estimationServer <- function( outcomeId <- shiny::reactiveVal() shiny::observeEvent(input$targetSelect, { - + targetSelected( data.frame( Target = names(targets)[targets == input$targetId], @@ -298,53 +297,57 @@ estimationServer <- function( #======================================= # SERVERS #======================================= - estimationCmDiagnosticServer( - id = 'estimationCmDiagnostic', - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - targetIds = targetIds, - comparatorIds = comparatorIds, - outcomeId = outcomeId - ) - - cmData <- estimationCmResultsServer( - id = 'estimationCmResults', - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - targetIds = targetIds, - comparatorIds = comparatorIds, - outcomeId = outcomeId - ) - - estimationCmPlotsServer( - id = 'estimationCmPlots', - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - cmData = cmData - ) - - estimationSccsDiagnosticServer( - id = 'estimationSccsDiagnostic', - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - targetIds = targetIds, - outcomeId = outcomeId - ) - - sccsData <- estimationSccsResultsServer( - id = 'estimationSccsResults', - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - targetIds = targetIds, - outcomeId = outcomeId - ) + if('Cohort Method' %in% estimationTypes){ + estimationCmDiagnosticServer( + id = 'estimationCmDiagnostic', + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = targetIds, + comparatorIds = comparatorIds, + outcomeId = outcomeId + ) + + cmData <- estimationCmResultsServer( + id = 'estimationCmResults', + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = targetIds, + comparatorIds = comparatorIds, + outcomeId = outcomeId + ) + + estimationCmPlotsServer( + id = 'estimationCmPlots', + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + cmData = cmData + ) + } - estimationSccsPlotsServer( - id = 'estimationSccsPlots', - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - sccsData = sccsData - ) + if('SCCS' %in% estimationTypes){ + estimationSccsDiagnosticServer( + id = 'estimationSccsDiagnostic', + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = targetIds, + outcomeId = outcomeId + ) + + sccsData <- estimationSccsResultsServer( + id = 'estimationSccsResults', + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = targetIds, + outcomeId = outcomeId + ) + + estimationSccsPlotsServer( + id = 'estimationSccsPlots', + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + sccsData = sccsData + ) + } } ) diff --git a/R/report-main.R b/R/report-main.R index c4bd8396..f38c6953 100644 --- a/R/report-main.R +++ b/R/report-main.R @@ -896,6 +896,14 @@ getTandOs <- function( cov.exposures_outcome_set_id = ds.exposures_outcome_set_id and cov.analysis_id = ds.analysis_id and cov.database_id = ds.database_id + + -- adding code to remove the negative controls + INNER JOIN + @schema.@sccs_table_prefixcovariate_analysis ca + on + ca.analysis_id = cov.analysis_id and + ca.covariate_analysis_id = cov.covariate_analysis_id + where ca.variable_of_interest = 1 } @@ -941,7 +949,7 @@ getTandOs <- function( # get target heirarchy groupedCohorts <- lapply(unique(res$tid), function(tid){ - data.frame( + list( cohortId = tid, cohortName = unique(res$targetName[res$tid == tid]), subsets = data.frame( From 651775f9ff8d9ed246b43f4699c4f84b786e2a41 Mon Sep 17 00:00:00 2001 From: Nathan Hall Date: Thu, 13 Jun 2024 13:22:03 -0400 Subject: [PATCH 33/64] fixing characterization updating data downloads for char tables, fixing cohort names in CI, adding caption to custom CI plot --- R/characterization-dechallengeRechallenge.R | 50 +++++--- R/characterization-incidence.R | 90 +++++++++++--- R/characterization-riskFactors.R | 8 ++ R/characterization-timeToEvent.R | 127 ++++++++++++++++++-- 4 files changed, 230 insertions(+), 45 deletions(-) diff --git a/R/characterization-dechallengeRechallenge.R b/R/characterization-dechallengeRechallenge.R index 0a73723c..d2190a96 100644 --- a/R/characterization-dechallengeRechallenge.R +++ b/R/characterization-dechallengeRechallenge.R @@ -68,6 +68,16 @@ characterizationDechallengeRechallengeServer <- function( id, function(input, output, session) { + + options <- shiny::reactive({ + characterizationGetCaseSeriesOptions( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetId = targetId(), + outcomeId = outcomeId() + ) + }) + # fetch data when targetId changes @@ -140,92 +150,92 @@ characterizationDechallengeRechallengeServer <- function( ), dechallengeStopInterval = reactable::colDef( header = withTooltip("Dechallenge Stop Interval", - ""), + "An integer specifying the how much time to add to the cohort_end when determining whether the event starts during cohort and ends after"), filterable = T ), dechallengeEvaluationWindow = reactable::colDef( header = withTooltip("Dechallenge Evaluation Window", - ""), + "A period of time evaluated for outcome recurrence after discontinuation of exposure, among patients with challenge outcomes"), filterable = T ), numExposureEras = reactable::colDef( header = withTooltip("# of Exposure Eras", - ""), + "Distinct number of exposure events (i.e. drug eras) in a given target cohort"), filterable = T ), numPersonsExposed = reactable::colDef( header = withTooltip("# of Exposed Persons", - ""), + "Distinct nuber of people exposed in target cohort. A person must have at least 1 day exposure to be included"), filterable = T ), numCases = reactable::colDef( header = withTooltip("# of Cases", - ""), + "Distinct number of persons in outcome cohort. A person must have at least 1 day of observation time to be included"), filterable = T ), dechallengeAttempt = reactable::colDef( header = withTooltip("# of Dechallenge Attempts", - ""), + "Distinct count of people with observable time after discontinuation of the exposure era during which the challenge outcome occurred"), filterable = T ), dechallengeFail = reactable::colDef( header = withTooltip("# of Dechallenge Fails", - ""), + "Among people with challenge outcomes, the distinct number of people with outcomes during dechallengeEvaluationWindow"), filterable = T ), dechallengeSuccess = reactable::colDef( header = withTooltip("# of Dechallenge Successes", - ""), + "Among people with challenge outcomes, the distinct number of people without outcomes during the dechallengeEvaluationWindow"), filterable = T ), rechallengeAttempt = reactable::colDef( header = withTooltip("# of Rechallenge Attempts", - ""), + "Number of people with a new exposure era after the occurrence of an outcome during a prior exposure era"), filterable = T ), rechallengeFail = reactable::colDef( header = withTooltip("# of Rechallenge Fails", - ""), + "Number of people with a new exposure era during which an outcome occurred, after the occurrence of an outcome during a prior exposure era"), filterable = T ), rechallengeSuccess = reactable::colDef( header = withTooltip("# of Rechallenge Successes", - ""), + "Number of people with a new exposure era during which an outcome did not occur, after the occurrence of an outcome during a prior exposure era"), filterable = T ), pctDechallengeAttempt = reactable::colDef( header = withTooltip("% of Dechallenge Attempts", - ""), + "Percent of people with observable time after discontinuation of the exposure era during which the challenge outcome occurred"), filterable = T, format = reactable::colFormat(digits = 2, percent = T) ), pctDechallengeSuccess = reactable::colDef( header = withTooltip("% of Dechallenge Success", - ""), + "Among people with challenge outcomes, the percent of people with outcomes during dechallengeEvaluationWindow"), filterable = T, format = reactable::colFormat(digits = 2, percent = T) ), pctDechallengeFail = reactable::colDef( header = withTooltip("% of Dechallenge Fail", - ""), + "Among people with challenge outcomes, the percent of people without outcomes during the dechallengeEvaluationWindow"), filterable = T, format = reactable::colFormat(digits = 2, percent = T) ), pctRechallengeAttempt = reactable::colDef( header = withTooltip("% of Rechallenge Attempts", - ""), + "Percent of people with a new exposure era after the occurrence of an outcome during a prior exposure era"), filterable = T, format = reactable::colFormat(digits = 2, percent = T) ), pctRechallengeSuccess = reactable::colDef( header = withTooltip("% of Rechallenge Success", - ""), + "Percent of people with a new exposure era during which an outcome occurred, after the occurrence of an outcome during a prior exposure era"), filterable = T, format = reactable::colFormat(digits = 2, percent = T) ), pctRechallengeFail = reactable::colDef( header = withTooltip("% of Rechallenge Fail", - ""), + "Percent of people with a new exposure era during which an outcome did not occur, after the occurrence of an outcome during a prior exposure era"), filterable = T, format = reactable::colFormat(digits = 2, percent = T) ) @@ -236,6 +246,12 @@ characterizationDechallengeRechallengeServer <- function( tableOutputs <- resultTableServer( id = "tableResults", df = allData, + details = data.frame( + target = options()$targetName, + outcome = options()$outcomeName, + Analysis = 'Exposed Cases Summary - Dechallenge-Rechallenge' + ), + downloadedFileName = 'dechallege-rechallenge', colDefsInput = characteriationDechalRechalColDefs(), addActions = c('fails') ) diff --git a/R/characterization-incidence.R b/R/characterization-incidence.R index 160e7d6f..c8c281df 100644 --- a/R/characterization-incidence.R +++ b/R/characterization-incidence.R @@ -421,6 +421,15 @@ characterizationIncidenceServer <- function( options <- getIncidenceOptions() + optionsGlobal <- shiny::reactive({ + characterizationGetCaseSeriesOptions( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetId = targetId(), + outcomeId = outcomeId() + ) + }) + inputSelectedCustomPlot <- inputSelectionServer( id = "input-selection-custom-plot", inputSettingList = list( @@ -646,6 +655,9 @@ characterizationIncidenceServer <- function( if(nrow(extractedData()) > 0){ extractedData() %>% dplyr::relocate("tar", .before = "outcomes") %>% + dplyr::select(-c("targetName", "outcomeName")) %>% + dplyr::rename(targetName = targetCohortName, + outcomeName = outcomeCohortName) %>% dplyr::mutate(incidenceProportionP100p = as.numeric(.data$incidenceProportionP100p), incidenceRateP100py = as.numeric(.data$incidenceRateP100py), dplyr::across(dplyr::where(is.numeric), round, 4), @@ -657,6 +669,8 @@ characterizationIncidenceServer <- function( .data$tar %in% incidenceRateTarFilter() & .data$cdmSourceAbbreviation %in% !! incidenceRateDbFilter() ) %>% + dplyr::relocate("targetName", .after = "cdmSourceAbbreviation") %>% + dplyr::relocate("outcomeName", .after = "targetName") %>% dplyr::relocate("targetIdShort", .after = "targetName") %>% dplyr::relocate("outcomeIdShort", .after = "outcomeName") } @@ -735,7 +749,10 @@ characterizationIncidenceServer <- function( ifelse(incidenceRateTarFilter() %in% filteredData()$tar, plotData <- filteredData() %>% - dplyr::filter(.data$tar %in% incidenceRateTarFilter()), + dplyr::filter(.data$tar %in% incidenceRateTarFilter()) %>% + dplyr::mutate(targetLabel = paste(targetIdShort, " = ", targetName), + outcomeLabel = paste(outcomeIdShort, " = ", outcomeName) + ), shiny::validate("Selected TAR is not found in your result data. Revise input selections or select a different TAR.") ) @@ -768,6 +785,16 @@ characterizationIncidenceServer <- function( trellis_aesthetic_x <- NULL trellis_aesthetic_y <- NULL + # Get unique target and outcome labels + unique_target_labels <- strwrap(unique(plotData$targetLabel), width = 300) + unique_outcome_labels <- strwrap(unique(plotData$outcomeLabel), width = 300) + + # Combine all unique values into a final vector + final_unique_values <- unique(c(unique_target_labels, unique_outcome_labels)) + + # Create the caption text with line breaks + caption_text <- paste(final_unique_values, collapse = "\n") + if (inputSelectedCustomPlot()$plotColor == "Target Cohort" | inputSelectedCustomPlot()$plotColor == "Outcome Cohort") { color_aesthetic <- if (inputSelectedCustomPlot()$plotColor == "Target Cohort") { dplyr::vars(.data$targetIdShort) @@ -990,6 +1017,8 @@ characterizationIncidenceServer <- function( } + + # Rest of your ggplot code remains the same base_plot <- base_plot + ggplot2::labs( title = paste("Incidence Rate for TAR:", tar_value), @@ -997,8 +1026,8 @@ characterizationIncidenceServer <- function( y = names(options$irPlotNumericChoices[options$irPlotNumericChoices %in% inputSelectedCustomPlot()$plotYAxis]), color = names(options$irPlotCategoricalChoices[options$irPlotCategoricalChoices %in% inputSelectedCustomPlot()$plotColor]), size = names(options$irPlotNumericChoices[options$irPlotNumericChoices %in% inputSelectedCustomPlot()$plotSize]), - shape = names(options$irPlotCategoricalChoices[options$irPlotCategoricalChoices %in% inputSelectedCustomPlot()$plotShape] - ) + shape = names(options$irPlotCategoricalChoices[options$irPlotCategoricalChoices %in% inputSelectedCustomPlot()$plotShape]), + caption = caption_text ) + ggplot2::scale_y_log10(breaks = scales::breaks_log(n=6)) + ggplot2::guides(alpha = "none") + # Remove the alpha legend @@ -1014,7 +1043,9 @@ characterizationIncidenceServer <- function( legend.text = ggplot2::element_text(size=10), legend.title = ggplot2::element_text(size=16, face = "bold"), panel.spacing = ggplot2::unit(2, "lines"), - strip.text = ggplot2::element_text(face="bold", size = 14) + strip.text = ggplot2::element_text(face="bold", size = 14), + plot.caption = ggplot2::element_text(hjust = 0, face = "italic", size = 12, + margin = ggplot2::margin(t = 20)) ) + ggplot2::guides(shape = ggplot2::guide_legend(override.aes = list(size = 6)), color = ggplot2::guide_legend(override.aes = list(size = 6))) @@ -1781,13 +1812,16 @@ getIncidenceData <- function( shiny::withProgress(message = 'Getting incidence data', value = 0, { - sql <- 'select d.cdm_source_abbreviation, i.* - from @result_schema.@incidence_table_prefixINCIDENCE_SUMMARY i - inner join @result_schema.@database_table_name d + sql <- 'select d.cdm_source_abbreviation, i.*, ct1.cohort_name as target_cohort_name, ct2.cohort_name as outcome_cohort_name +from @result_schema.@incidence_table_prefixINCIDENCE_SUMMARY i +inner join @result_schema.@database_table_name d on d.database_id = i.database_id - where target_cohort_definition_id in (@target_ids) - and outcome_cohort_definition_id in (@outcome_ids) - ;' +inner join @result_schema.@cg_table_prefixcohort_definition ct1 + on ct1.cohort_definition_id = i.target_cohort_definition_id +inner join @result_schema.@cg_table_prefixcohort_definition ct2 + on ct2.cohort_definition_id = i.outcome_cohort_definition_id +where i.target_cohort_definition_id in (@target_ids) + and i.outcome_cohort_definition_id in (@outcome_ids);' shiny::incProgress(1/2, detail = paste("Created SQL - Extracting...")) @@ -1795,6 +1829,7 @@ getIncidenceData <- function( sql = sql, result_schema = resultDatabaseSettings$schema, incidence_table_prefix = resultDatabaseSettings$incidenceTablePrefix, + cg_table_prefix = resultDatabaseSettings$cgTablePrefix, target_ids = paste(as.double(targetIds), collapse = ','), outcome_ids = paste(as.double(outcomeIds), collapse = ','), database_table_name = resultDatabaseSettings$databaseTable @@ -1836,32 +1871,47 @@ getIncidenceOptionsOld <- function( # shiny::withProgress(message = 'Getting incidence inputs', value = 0, { - sql <- 'select distinct target_cohort_definition_id, target_name - from @result_schema.@incidence_table_prefixINCIDENCE_SUMMARY;' + sql <- 'select distinct i.target_cohort_definition_id, ct1.cohort_name + from @result_schema.@incidence_table_prefixINCIDENCE_SUMMARY i + + inner join + @result_schema.@cg_table_prefixcohort_definition ct1 + on + ct1.cohort_definition_id = i.target_cohort_definition_id + + ;' #shiny::incProgress(1/3, detail = paste("Created SQL - Extracting targets")) targets <- connectionHandler$queryDb( sql = sql, result_schema = resultDatabaseSettings$schema, - incidence_table_prefix = resultDatabaseSettings$incidenceTablePrefix + incidence_table_prefix = resultDatabaseSettings$incidenceTablePrefix, + cg_table_prefix = resultDatabaseSettings$cgTablePrefix ) targetIds <- targets$targetCohortDefinitionId - names(targetIds) <- targets$targetName + names(targetIds) <- targets$cohortName - sql <- 'select distinct outcome_cohort_definition_id, outcome_name - from @result_schema.@incidence_table_prefixINCIDENCE_SUMMARY;' + sql <- 'select distinct i.outcome_cohort_definition_id, ct1.cohort_name + from @result_schema.@incidence_table_prefixINCIDENCE_SUMMARY i + + inner join + @result_schema.@cg_table_prefixcohort_definition ct1 + on + ct1.cohort_definition_id = i.outcome_cohort_definition_id + + ;' - #shiny::incProgress(2/3, detail = paste("Created SQL - Extracting outcomes")) + #shiny::incProgress(1/3, detail = paste("Created SQL - Extracting targets")) outcomes <- connectionHandler$queryDb( sql = sql, result_schema = resultDatabaseSettings$schema, - incidence_table_prefix = resultDatabaseSettings$incidenceTablePrefix + incidence_table_prefix = resultDatabaseSettings$incidenceTablePrefix, + cg_table_prefix = resultDatabaseSettings$cgTablePrefix ) - outcomeIds <- outcomes$outcomeCohortDefinitionId - names(outcomeIds) <- outcomes$outcomeName + names(outcomeIds) <- outcomes$cohortName sql <- 'select distinct tar_id, tar_start_with, tar_start_offset, tar_end_with, tar_end_offset from @result_schema.@incidence_table_prefixINCIDENCE_SUMMARY;' diff --git a/R/characterization-riskFactors.R b/R/characterization-riskFactors.R index c479b73b..32e4a2c0 100644 --- a/R/characterization-riskFactors.R +++ b/R/characterization-riskFactors.R @@ -126,6 +126,14 @@ characterizationRiskFactorServer <- function( binTableOutputs <- resultTableServer( id = "binaryTable", df = allData$binary, + details = data.frame( + target = options()$targetName, + outcome = options()$outcomeName, + Database = names(options()$databaseIds)[which(input$databaseId == options()$databaseIds)], + TimeAtRisk = options()$tarList[[which(options()$tarInds == input$tarInd)]], + Analysis = 'Exposed Cases Summary - Risk Factor' + ), + downloadedFileName = 'risk_factor_binary', colDefsInput = characteriationRiskFactorColDefs( elementId = session$ns('binary-table-filter') ), # function below diff --git a/R/characterization-timeToEvent.R b/R/characterization-timeToEvent.R index c057830c..6c197895 100644 --- a/R/characterization-timeToEvent.R +++ b/R/characterization-timeToEvent.R @@ -31,17 +31,37 @@ characterizationTimeToEventViewer <- function(id) { ns <- shiny::NS(id) shiny::div( + + shiny::tabsetPanel( + type = 'pills', + id = ns('tteMainPanel'), + + shiny::tabPanel( + title = "Time-to-event Plots", - shinydashboard::box( - width = "100%", - title = "", + shinydashboard::box( + width = "100%", + title = "", + + shiny::uiOutput(ns('timeToEventPlotInputs')), + shinycssloaders::withSpinner( + shiny::plotOutput(ns('timeToEvent')) + ) + ) + ), + + shiny::tabPanel( + title = "Time-to-event Table", - shiny::uiOutput(ns('timeToEventPlotInputs')), - shinycssloaders::withSpinner( - shiny::plotOutput(ns('timeToEvent')) + shinydashboard::box( + status = 'info', + width = '100%', + solidHeader = TRUE, + resultTableViewer(ns('tableResults')) + ) ) ) - ) + ) } @@ -69,14 +89,105 @@ characterizationTimeToEventServer <- function( id, function(input, output, session) { + options <- shiny::reactive({ + characterizationGetCaseSeriesOptions( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetId = targetId(), + outcomeId = outcomeId() + ) + }) + allData <- shiny::reactive({ getTimeToEventData( targetId = targetId(), outcomeId = outcomeId(), connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings - ) + ) %>% + dplyr::mutate(targetName = options()$targetName, + outcomeName = options()$outcomeName) %>% + dplyr::relocate(databaseName, .before = databaseId) %>% + dplyr::relocate(targetName, .after = databaseName) %>% + dplyr::relocate(outcomeName, .after = targetName) }) + + + characterizationTimeToEventColDefs <- function(){ + result <- list( + databaseName = reactable::colDef( + header = withTooltip("Database", + "Name of the database"), + filterable = T + ), + databaseId = reactable::colDef( + header = withTooltip("Database ID", + "Unique ID of the database"), + filterable = T, + show = F + ), + targetCohortDefinitionId = reactable::colDef( + header = withTooltip("Target ID", + "Unique ID of the target cohort"), + filterable = T, + show = F + ), + targetName = reactable::colDef( + header = withTooltip("Target Name", + "Name of the target cohort"), + filterable = T + ), + outcomeCohortDefinitionId = reactable::colDef( + header = withTooltip("Outcome ID", + "Unique ID of the outcome cohort"), + filterable = T, + show = F + ), + outcomeName = reactable::colDef( + header = withTooltip("Outcome Name", + "Name of the outcome cohort"), + filterable = T + ), + outcomeType = reactable::colDef( + header = withTooltip("Outcome Type", + "Type of the outcome, either first or subsequent occurrence"), + filterable = T + ), + targetOutcomeType = reactable::colDef( + header = withTooltip("Target-Outcome Type", + "The timing of the event relative to the target era"), + filterable = T + ), + timeToEvent = reactable::colDef( + header = withTooltip("Time (in days) To Event", + "The time in days relative to target index until the event occurred"), + filterable = T + ), + numEvents = reactable::colDef( + header = withTooltip("# of Events", + "The number of events that occurred"), + filterable = T + ), + timeScale = reactable::colDef( + header = withTooltip("Time Scale", + "The time scale in which the events occurred"), + filterable = T + ) + ) + return(result) + } + + tableOutputs <- resultTableServer( + id = "tableResults", + df = allData, + details = data.frame( + target = options()$targetName, + outcome = options()$outcomeName, + Analysis = 'Exposed Cases Summary - Time-to-event' + ), + downloadedFileName = 'time_to_event', + colDefsInput = characterizationTimeToEventColDefs() + ) output$timeToEventPlotInputs <- shiny::renderUI({ From ad60fab1476da5f291748180a503844b54f9e9c7 Mon Sep 17 00:00:00 2001 From: jreps Date: Thu, 13 Jun 2024 13:57:48 -0400 Subject: [PATCH 34/64] Update characterization-main.R sorting outcomes in char --- R/characterization-main.R | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/R/characterization-main.R b/R/characterization-main.R index 1f32b6d2..760a5c8e 100644 --- a/R/characterization-main.R +++ b/R/characterization-main.R @@ -206,15 +206,21 @@ characterizationServer <- function( collapsible = TRUE, title = "Options", width = "100%", - shiny::selectInput( + + shinyWidgets::pickerInput( inputId = session$ns('outcomeId'), label = 'Outcome: ', choices = outcomes(), selected = 1, multiple = FALSE, - selectize = TRUE, - width = NULL, - size = NULL + options = shinyWidgets::pickerOptions( + actionsBox = F, + dropupAuto = F, + size = 10, + liveSearch = TRUE, + liveSearchStyle = "contains", + liveSearchPlaceholder = "Type here to search" + ) ), shiny::actionButton( inputId = session$ns('outcomeSelect'), @@ -596,7 +602,7 @@ getCharacterizationTypes <- function( )) } - +# TODO add tte and dechal as include options characterizationGetOptions <- function( connectionHandler, resultDatabaseSettings, @@ -612,8 +618,7 @@ characterizationGetOptions <- function( cg_table_prefix = resultDatabaseSettings$cgTablePrefix ) -# database_id needed for old results but not for new ones - # TODO - add tte and decha rechal? +# TODO - add tte and decha rechal? cohorts <- connectionHandler$queryDb( sql = " @@ -653,6 +658,7 @@ from @schema.@ci_table_prefixcohorts_lookup inner join @schema.@cg_table_prefixcohort_definition c on temp.outcome_cohort_id = c.cohort_definition_id + ;", schema = resultDatabaseSettings$schema, c_table_prefix = resultDatabaseSettings$cTablePrefix, @@ -715,6 +721,9 @@ characterizationGetOutcomes <- function(options, index){ outcomes <- result$ids names(outcomes) <- result$names + + # sort the outcomes alphabetically + outcomes <- outcomes[order(names(outcomes))] return(outcomes) } From 576006f3411047a6a30e5de22daa664583bfdd67 Mon Sep 17 00:00:00 2001 From: jreps Date: Fri, 14 Jun 2024 08:49:52 -0400 Subject: [PATCH 35/64] fixing estimation - adding missing shiny:: - updating code to get T and Os for SCCS so it removed negative controls --- R/estimation-main.R | 2 +- R/report-main.R | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/R/estimation-main.R b/R/estimation-main.R index 8f7eaf60..18665069 100644 --- a/R/estimation-main.R +++ b/R/estimation-main.R @@ -61,7 +61,7 @@ estimationViewer <- function(id=1) { # database, analysis, pass/fail, viewResult/viewDiagnostic # extracts from SCCS/CM/Evidence Synthesis - conditionalPanel( + shiny::conditionalPanel( condition = 'input.targetSelect', ns = ns, diff --git a/R/report-main.R b/R/report-main.R index f38c6953..8a17933a 100644 --- a/R/report-main.R +++ b/R/report-main.R @@ -899,11 +899,10 @@ getTandOs <- function( -- adding code to remove the negative controls INNER JOIN - @schema.@sccs_table_prefixcovariate_analysis ca - on - ca.analysis_id = cov.analysis_id and - ca.covariate_analysis_id = cov.covariate_analysis_id - where ca.variable_of_interest = 1 + @schema.@sccs_table_prefixexposure e + ON e.exposures_outcome_set_id = ds.exposures_outcome_set_id + AND e.era_id = cov.era_id + where e.true_effect_size is NULL } From eb594364abb602f2d4f43a2d324e698d4e500a1d Mon Sep 17 00:00:00 2001 From: jreps Date: Fri, 14 Jun 2024 09:59:11 -0400 Subject: [PATCH 36/64] adding fix for ci_lookup adding fix for ci_lookup --- R/characterization-main.R | 21 ++++++++++++++++++--- R/helpers-sccsPlots.R | 8 +++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/R/characterization-main.R b/R/characterization-main.R index 760a5c8e..4e6d0718 100644 --- a/R/characterization-main.R +++ b/R/characterization-main.R @@ -618,6 +618,15 @@ characterizationGetOptions <- function( cg_table_prefix = resultDatabaseSettings$cgTablePrefix ) + # check whether lookup table in CI exists + ciLookup <- !is.null(tryCatch({ + connectionHandler$queryDb( + sql = 'select * from @schema.@ci_table_prefixcohorts_lookup limit 1;', + schema = resultDatabaseSettings$schema, + ci_table_prefix = resultDatabaseSettings$incidenceTablePrefix + ) + }, error = function(e){return(NULL)})) + # TODO - add tte and decha rechal? cohorts <- connectionHandler$queryDb( sql = " @@ -650,9 +659,14 @@ union } {@include_incidence} ? { +{@ci_lookup} ? +{select * from @schema.@ci_table_prefixcohorts_lookup} : { +select distinct target_cohort_definition_id as target_cohort_id, +outcome_cohort_definition_id as outcome_cohort_id +from +@schema.@ci_table_prefixincidence_summary +} -select * -from @schema.@ci_table_prefixcohorts_lookup } ) temp inner join @@ -665,7 +679,8 @@ on temp.outcome_cohort_id = c.cohort_definition_id cg_table_prefix = resultDatabaseSettings$cgTablePrefix, ci_table_prefix = resultDatabaseSettings$incidenceTablePrefix, include_incidence = includeIncidence, - include_aggregate = includeAggregate + include_aggregate = includeAggregate, + ci_lookup = ciLookup ) # fix backwards compatability cg$subsetParent[is.na(cg$isSubset)] <- cg$cohortDefinitionId diff --git a/R/helpers-sccsPlots.R b/R/helpers-sccsPlots.R index e2b7f066..b7344a8a 100644 --- a/R/helpers-sccsPlots.R +++ b/R/helpers-sccsPlots.R @@ -538,6 +538,9 @@ cyclicSplineDesign <- function(x, knots, ord = 4) { } plotControlEstimates <- function(controlEstimates) { + if(nrow(controlEstimates) == 0){ + shiny::validate('No rows') + } size <- 2 labelY <- 0.7 d <- rbind(data.frame(yGroup = "Uncalibrated", @@ -556,7 +559,10 @@ plotControlEstimates <- function(controlEstimates) { d <- d[!is.na(d$ci95Lb),] d <- d[!is.na(d$ci95Ub),] if (nrow(d) == 0) { - return(NULL) + shiny::validate('No rows') + } + if (nrow(d) == 1) { + shiny::validate('Only one row so cannot aggregate') } d$Group <- as.factor(d$trueRr) d$Significant <- d$ci95Lb > d$trueRr | d$ci95Ub < d$trueRr From 2ff98b96576a41aeba21815244149d46be9fc416 Mon Sep 17 00:00:00 2001 From: jreps Date: Thu, 20 Jun 2024 12:31:31 -0400 Subject: [PATCH 37/64] Update estimation-sccs-results-full.R --- R/estimation-sccs-results-full.R | 55 +++++++++++++------------------- 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/R/estimation-sccs-results-full.R b/R/estimation-sccs-results-full.R index c71cbfb2..f337ef5e 100644 --- a/R/estimation-sccs-results-full.R +++ b/R/estimation-sccs-results-full.R @@ -508,8 +508,8 @@ estimationGetSccsModel <- function( WHERE scr.database_id = '@database_id' AND scr.analysis_id = @analysis_id - AND sc.era_id = @exposure_id - AND scr.rr IS NOT NULL + --AND sc.era_id = @exposure_id + --AND scr.rr IS NOT NULL AND scr.exposures_outcome_set_id = @exposures_outcome_set_id " @@ -729,42 +729,33 @@ estimationGetSccsControlEstimates <- function( ) { sql <- " - SELECT ci_95_lb, ci_95_ub, log_rr, se_log_rr, calibrated_ci_95_lb, calibrated_ci_95_ub, calibrated_log_rr, - calibrated_se_log_rr, exposures_outcome_set_id - FROM - (select * from @schema.@sccs_table_prefixresult - WHERE database_id = '@database_id' - AND analysis_id = @analysis_id - AND covariate_id = @covariate_id - ) sr - ; - " - res <- connectionHandler$queryDb( - sql, - schema = resultDatabaseSettings$schema, - sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, - database_id = databaseId, - covariate_id = covariateId, - analysis_id = analysisId, - era_id = eraId, - snakeCaseToCamelCase = TRUE - ) + SELECT r.ci_95_lb, r.ci_95_ub, r.log_rr, r.se_log_rr, + r.calibrated_ci_95_lb, r.calibrated_ci_95_ub, r.calibrated_log_rr, + r.calibrated_se_log_rr, r.exposures_outcome_set_id, + e.true_effect_size, c.exposures_outcome_set_id - sql <- " - select e.true_effect_size, c.exposures_outcome_set_id - from + FROM + @schema.@sccs_table_prefixresult r + INNER JOIN @schema.@sccs_table_prefixexposure e + on r.exposures_outcome_set_id = e.exposures_outcome_set_id + INNER JOIN @schema.@sccs_table_prefixcovariate c on e.era_id = c.era_id and e.exposures_outcome_set_id = c.exposures_outcome_set_id + and c.database_id = r.database_id + and c.analysis_id = r.analysis_id + and c.covariate_id = r.covariate_id + WHERE e.era_id = @era_id - and c.database_id = '@database_id' - AND c.analysis_id = @analysis_id - AND c.covariate_id = @covariate_id + AND r.database_id = '@database_id' + AND r.analysis_id = @analysis_id + AND r.covariate_id = @covariate_id + AND e.true_effect_size is not NULL ; " - res2 <- connectionHandler$queryDb( + res <- connectionHandler$queryDb( sql, schema = resultDatabaseSettings$schema, sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, @@ -774,10 +765,8 @@ estimationGetSccsControlEstimates <- function( era_id = eraId, snakeCaseToCamelCase = TRUE ) - # only keep the positive or negative controls (trueEffectSize 1 or >1) - res2 <- res2[!is.na(res2$trueEffectSize),] - allres <- merge(res, res2, by = 'exposuresOutcomeSetId') + #allres <- merge(res, res2, by = 'exposuresOutcomeSetId') - return(allres) + return(res) } From eb97b6028c0c81a9b1258e0829d01162af682801 Mon Sep 17 00:00:00 2001 From: Nathan Hall <106178605+nhall6@users.noreply.github.com> Date: Thu, 20 Jun 2024 13:56:43 -0400 Subject: [PATCH 38/64] Update DESCRIPTION adding Nathan Hall and Jamie Gilbert as co-authors --- DESCRIPTION | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 39e7a303..774d648e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,7 +2,11 @@ Package: OhdsiShinyModules Type: Package Title: Repository of Shiny Modules for OHDSI Result Viewers Version: 2.1.4 -Author: Jenna Reps +Authors@R: c( + person("Jenna", "Reps", email = "jreps@its.jnj.com", role = c("aut", "cre")), + person("Nathan", "Hall", role = c("aut")), + person("Jamie", "Gibert", role = c("aut")) +) Maintainer: Jenna Reps Description: Install this package to access useful shiny modules for building shiny apps to explore results using the OHDSI tools . License: Apache License 2.0 From a1836db3e5c801adbc03d0f4ca37156d6d372efd Mon Sep 17 00:00:00 2001 From: jreps Date: Fri, 28 Jun 2024 11:20:51 -0400 Subject: [PATCH 39/64] minor updates - fixed bug with control estimates plot not showing all results - added ease value to control estimate plot - added validation checks to print informative reason for missing plots --- R/estimation-sccs-results-full.R | 45 ++++++++++++++++++++----- R/helpers-sccsPlots.R | 39 +++++++++++++++++++-- R/sccs-results-full.R | 2 +- tests/testthat/test-helpers-sccsPlots.R | 2 +- 4 files changed, 75 insertions(+), 13 deletions(-) diff --git a/R/estimation-sccs-results-full.R b/R/estimation-sccs-results-full.R index f337ef5e..492be46a 100644 --- a/R/estimation-sccs-results-full.R +++ b/R/estimation-sccs-results-full.R @@ -436,7 +436,10 @@ estimationSccsFullResultServer <- function( analysisId = row$analysisId, eraId = row$eraId ) - plotControlEstimates(controlEstimates) + plotControlEstimates( + controlEstimates = controlEstimates$plotResult, + ease = controlEstimates$ease + ) } }) @@ -582,8 +585,13 @@ estimationGetSccsTimeToEvent <- function( snakeCaseToCamelCase = TRUE ) + # if NULL set to NA so code below works + if(is.null(p$preExposureP)){ + p$preExposureP <- NA + } + sql <- " - SELECT *, @p as p + SELECT * , @p as p FROM @schema.@sccs_table_prefixtime_to_event WHERE database_id = '@database_id' @@ -600,10 +608,11 @@ estimationGetSccsTimeToEvent <- function( analysis_id = analysisId, exposures_outcome_set_id = exposuresOutcomeSetId, exposure_id = exposureId, - p = ifelse(is.null(p$preExposureP), -1, p$preExposureP), + p = ifelse(is.na(p$preExposureP), -1, p$preExposureP), snakeCaseToCamelCase = TRUE ) + return(timeToEvent) } @@ -739,7 +748,7 @@ estimationGetSccsControlEstimates <- function( INNER JOIN @schema.@sccs_table_prefixexposure e on r.exposures_outcome_set_id = e.exposures_outcome_set_id - + INNER JOIN @schema.@sccs_table_prefixcovariate c on e.era_id = c.era_id @@ -748,13 +757,14 @@ estimationGetSccsControlEstimates <- function( and c.analysis_id = r.analysis_id and c.covariate_id = r.covariate_id - WHERE e.era_id = @era_id - AND r.database_id = '@database_id' + WHERE r.database_id = '@database_id' AND r.analysis_id = @analysis_id AND r.covariate_id = @covariate_id AND e.true_effect_size is not NULL + -- AND e.era_id = @era_id ; " + res <- connectionHandler$queryDb( sql, schema = resultDatabaseSettings$schema, @@ -766,7 +776,26 @@ estimationGetSccsControlEstimates <- function( snakeCaseToCamelCase = TRUE ) - #allres <- merge(res, res2, by = 'exposuresOutcomeSetId') + # get ease for the plot + sql <- "SELECT top 1 ds.ease + FROM @schema.@sccs_table_prefixdiagnostics_summary ds + WHERE ds.database_id = '@database_id' + AND ds.analysis_id = @analysis_id + AND ds.covariate_id = @covariate_id;" - return(res) + ease <- connectionHandler$queryDb( + sql, + schema = resultDatabaseSettings$schema, + sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, + database_id = databaseId, + covariate_id = covariateId, + analysis_id = analysisId, + snakeCaseToCamelCase = TRUE + ) + + return(list( + plotResult = res, + ease = ease$ease + ) + ) } diff --git a/R/helpers-sccsPlots.R b/R/helpers-sccsPlots.R index b7344a8a..f7700ec5 100644 --- a/R/helpers-sccsPlots.R +++ b/R/helpers-sccsPlots.R @@ -120,7 +120,9 @@ plotTimeTrend <- function(timeTrend) { plotTimeToEventSccs <- function(timeToEvent) { - + if(nrow(timeToEvent) == 0){ + shiny::validate('No Rows') + } events <- timeToEvent %>% dplyr::transmute(.data$week, type = "Events", @@ -300,12 +302,23 @@ drawAttritionDiagram <- function(attrition) { } plotEventDepObservation <- function(eventDepObservation, maxMonths = 12) { + if(nrow(eventDepObservation) == 0){ + shiny::validate('No Rows') + } + eventDepObservation <- eventDepObservation %>% dplyr::filter(.data$monthsToEnd <= maxMonths) %>% dplyr::mutate( outcomes = pmax(0, .data$outcomes), censoring = ifelse(.data$censored == 1, "Censored", "Uncensored") ) + if(nrow(eventDepObservation) == 0){ + shiny::validate('No Rows after filtering') + } + if(is.infinite(max(eventDepObservation$monthsToEnd))){ + shiny::validate('Infinite max') + } + timeBreaks <- 0:ceiling(max(eventDepObservation$monthsToEnd)) timeLabels <- timeBreaks * 30.5 @@ -335,7 +348,20 @@ plotEventDepObservation <- function(eventDepObservation, maxMonths = 12) { } plotSpanning <- function(spanning, type = "age") { + + if(nrow(spanning) == 0){ + shiny::validate('No rows') + } + if (type == "age") { + + if(is.infinite(min(spanning$ageMonth))){ + shiny::validate('infinte min age month') + } + if(is.infinite(max(spanning$ageMonth))){ + shiny::validate('infinte max age month') + } + spanning <- spanning %>% dplyr::mutate(x = .data$ageMonth) labels <- seq(ceiling(min(spanning$ageMonth) / 12), floor(max(spanning$ageMonth) / 12)) @@ -537,10 +563,16 @@ cyclicSplineDesign <- function(x, knots, ord = 4) { X1 } -plotControlEstimates <- function(controlEstimates) { +plotControlEstimates <- function( + controlEstimates, + ease = NULL + ) { if(nrow(controlEstimates) == 0){ shiny::validate('No rows') } + + titleText <- paste('Ease: ', ease) + size <- 2 labelY <- 0.7 d <- rbind(data.frame(yGroup = "Uncalibrated", @@ -636,7 +668,8 @@ plotControlEstimates <- function(controlEstimates) { strip.text.x = theme, strip.text.y = theme, strip.background = ggplot2::element_blank(), - legend.position = "none") + legend.position = "none") + + ggplot2::ggtitle(label = titleText) return(plot) } diff --git a/R/sccs-results-full.R b/R/sccs-results-full.R index 279349d8..2d5e1d9c 100644 --- a/R/sccs-results-full.R +++ b/R/sccs-results-full.R @@ -412,7 +412,7 @@ sccsFullResultServer <- function( databaseId = row$databaseId, analysisId = row$analysisId ) - plotControlEstimates(controlEstimates) + plotControlEstimates(controlEstimates = controlEstimates) } }) diff --git a/tests/testthat/test-helpers-sccsPlots.R b/tests/testthat/test-helpers-sccsPlots.R index 018a3eac..24602d42 100644 --- a/tests/testthat/test-helpers-sccsPlots.R +++ b/tests/testthat/test-helpers-sccsPlots.R @@ -130,7 +130,7 @@ test_that("plotControlEstimates", { trueEffectSize = rep(1,100) ) - res <- plotControlEstimates(df) + res <- plotControlEstimates(controlEstimates = df) testthat::expect_is(res, "ggplot") }) From 926c16eb0846739bb7e3cd8bc1b3a0a98f3a95cb Mon Sep 17 00:00:00 2001 From: jreps Date: Fri, 28 Jun 2024 11:29:27 -0400 Subject: [PATCH 40/64] error handling for estimation plots replacing estimation plot error message with useful notification --- R/estimation-cohort-method-plots.R | 9 +++++++++ R/estimation-sccs-plots.R | 13 +++++++++++++ 2 files changed, 22 insertions(+) diff --git a/R/estimation-cohort-method-plots.R b/R/estimation-cohort-method-plots.R index d58c8665..314a9c93 100644 --- a/R/estimation-cohort-method-plots.R +++ b/R/estimation-cohort-method-plots.R @@ -37,10 +37,19 @@ estimationCmPlotsServer <- function( estimationCreateCmPlot <- function(data) { data <- data() + if(nrow(data) == 0){ + shiny::showNotification('No results to plot') + return(NULL) + } data <- data[!is.na(data$calibratedRr),] + if(nrow(data) == 0){ + shiny::showNotification('No results to plot') + return(NULL) + } data$database <- data$cdmSourceAbbreviation if(is.null(data$comparator)){ + shiny::showNotification('No results to plot') return(NULL) } diff --git a/R/estimation-sccs-plots.R b/R/estimation-sccs-plots.R index 40afc902..aad17c61 100644 --- a/R/estimation-sccs-plots.R +++ b/R/estimation-sccs-plots.R @@ -37,13 +37,26 @@ estimationSccsPlotsServer <- function( estimationCreateSccsPlot <- function(data) { data <- data() + if(nrow(data) == 0){ + shiny::showNotification('No results to plot') + return(NULL) + } data <- data[!is.na(data$calibratedRr),] + if(nrow(data) == 0){ + shiny::showNotification('No results to plot') + return(NULL) + } data$database <- data$databaseName data$type <- data$covariateName data$indication[is.null(data$indication)] <- 'no indication' data$indication[is.na(data$indication)] <- 'no indication' if(is.null(data)){ + shiny::showNotification('No results to plot') + return(NULL) + } + if(nrow(data) == 0){ + shiny::showNotification('No results to plot') return(NULL) } From 3061e5c561641d9c4aaf526f66456d568715df71 Mon Sep 17 00:00:00 2001 From: jreps Date: Fri, 28 Jun 2024 15:44:12 -0400 Subject: [PATCH 41/64] minor updates to estimation - removing old sccs and cohort method files - making estimation options be ordered by cohort name - adding indication column into sccs diagnostics - updating estimation outcome input to have the search options --- NAMESPACE | 10 - R/cohort-method-diagnosticsSummary.R | 389 --------------- R/cohort-method-full-result.R | 163 ------ R/cohort-method-main.R | 290 ----------- R/cohort-method-resultSummary.R | 359 -------------- ...R => estimation-cohort-method-attrition.R} | 0 ...timation-cohort-method-covariateBalance.R} | 0 ...> estimation-cohort-method-kaplainMeier.R} | 0 ...cohort-method-populationCharacteristics.R} | 7 +- ...wer.R => estimation-cohort-method-power.R} | 0 ...stimation-cohort-method-propensityModel.R} | 0 ...hort-method-propensityScoreDistribution.R} | 0 ...stimation-cohort-method-systematicError.R} | 0 R/estimation-main.R | 18 +- R/estimation-sccs-diagnostics.R | 6 + R/report-main.R | 26 +- R/sccs-diagnosticsSummary.R | 465 ------------------ R/sccs-main.R | 212 -------- R/sccs-results-full.R | 427 ---------------- R/sccs-results.R | 335 ------------- man/cohortMethodDiagnosticsSummaryServer.Rd | 28 -- man/cohortMethodDiagnosticsSummaryViewer.Rd | 17 - man/cohortMethodHelperFile.Rd | 17 - man/cohortMethodResultSummaryServer.Rd | 28 -- man/cohortMethodResultSummaryViewer.Rd | 17 - man/cohortMethodServer.Rd | 21 - man/cohortMethodViewer.Rd | 17 - man/sccsHelperFile.Rd | 17 - man/sccsServer.Rd | 24 - man/sccsView.Rd | 14 - 30 files changed, 42 insertions(+), 2865 deletions(-) delete mode 100644 R/cohort-method-diagnosticsSummary.R delete mode 100644 R/cohort-method-full-result.R delete mode 100644 R/cohort-method-main.R delete mode 100644 R/cohort-method-resultSummary.R rename R/{cohort-method-attrition.R => estimation-cohort-method-attrition.R} (100%) rename R/{cohort-method-covariateBalance.R => estimation-cohort-method-covariateBalance.R} (100%) rename R/{cohort-method-kaplainMeier.R => estimation-cohort-method-kaplainMeier.R} (100%) rename R/{cohort-method-populationCharacteristics.R => estimation-cohort-method-populationCharacteristics.R} (98%) rename R/{cohort-method-power.R => estimation-cohort-method-power.R} (100%) rename R/{cohort-method-propensityModel.R => estimation-cohort-method-propensityModel.R} (100%) rename R/{cohort-method-propensityScoreDistribution.R => estimation-cohort-method-propensityScoreDistribution.R} (100%) rename R/{cohort-method-systematicError.R => estimation-cohort-method-systematicError.R} (100%) delete mode 100644 R/sccs-diagnosticsSummary.R delete mode 100644 R/sccs-main.R delete mode 100644 R/sccs-results-full.R delete mode 100644 R/sccs-results.R delete mode 100644 man/cohortMethodDiagnosticsSummaryServer.Rd delete mode 100644 man/cohortMethodDiagnosticsSummaryViewer.Rd delete mode 100644 man/cohortMethodHelperFile.Rd delete mode 100644 man/cohortMethodResultSummaryServer.Rd delete mode 100644 man/cohortMethodResultSummaryViewer.Rd delete mode 100644 man/cohortMethodServer.Rd delete mode 100644 man/cohortMethodViewer.Rd delete mode 100644 man/sccsHelperFile.Rd delete mode 100644 man/sccsServer.Rd delete mode 100644 man/sccsView.Rd diff --git a/NAMESPACE b/NAMESPACE index c372141f..f87eb69c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -26,9 +26,6 @@ export(cohortMethodAttritionServer) export(cohortMethodAttritionViewer) export(cohortMethodCovariateBalanceServer) export(cohortMethodCovariateBalanceViewer) -export(cohortMethodDiagnosticsSummaryServer) -export(cohortMethodDiagnosticsSummaryViewer) -export(cohortMethodHelperFile) export(cohortMethodKaplanMeierServer) export(cohortMethodKaplanMeierViewer) export(cohortMethodPopulationCharacteristicsServer) @@ -39,12 +36,8 @@ export(cohortMethodPropensityModelServer) export(cohortMethodPropensityModelViewer) export(cohortMethodPropensityScoreDistServer) export(cohortMethodPropensityScoreDistViewer) -export(cohortMethodResultSummaryServer) -export(cohortMethodResultSummaryViewer) -export(cohortMethodServer) export(cohortMethodSystematicErrorServer) export(cohortMethodSystematicErrorViewer) -export(cohortMethodViewer) export(cohortOverlapView) export(compareCohortCharacterizationView) export(conceptsInDataSourceView) @@ -109,8 +102,5 @@ export(phevaluatorViewer) export(reportHelperFile) export(reportServer) export(reportViewer) -export(sccsHelperFile) -export(sccsServer) -export(sccsView) export(timeDistributionsView) export(visitContextView) diff --git a/R/cohort-method-diagnosticsSummary.R b/R/cohort-method-diagnosticsSummary.R deleted file mode 100644 index 72f0a66b..00000000 --- a/R/cohort-method-diagnosticsSummary.R +++ /dev/null @@ -1,389 +0,0 @@ -# @file cohort-method-diagnosticsSummary -# -# Copyright 2024 Observational Health Data Sciences and Informatics -# -# This file is part of OhdsiShinyModules -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -#' The module viewer for rendering the PLE diagnostics results -#' -#' @param id the unique reference id for the module -#' -#' @return -#' The user interface to the cohort method diagnostics viewer -#' -#' @export -cohortMethodDiagnosticsSummaryViewer <- function(id) { - ns <- shiny::NS(id) - - shiny::div( - - shiny::tabsetPanel( - type = 'pills', - id = ns('diagnosticsTablePanel'), - shiny::tabPanel( - title = 'Summary', - resultTableViewer(ns("diagnosticsSummaryTable")) - ), - shiny::tabPanel( - title = 'Full', - resultTableViewer(ns("diagnosticsTable")) - ) - ) - #) - ) -} - - -#' The module server for rendering the PLE diagnostics summary -#' -#' @param id the unique reference id for the module -#' @param connectionHandler the connection to the PLE results database -#' @param resultDatabaseSettings a list containing the result schema and prefixes -#' @param inputSelected The target id, comparator id, outcome id and analysis id selected by the user -#' -#' @return -#' the PLE diagnostics summary results -#' -#' @export -cohortMethodDiagnosticsSummaryServer <- function( - id, - connectionHandler, - resultDatabaseSettings, - inputSelected -) { - - shiny::moduleServer( - id, - function(input, output, session) { - - data <- shiny::reactive({ - getCmDiagnosticsData( - connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - inputSelected = inputSelected - ) - }) - - data2 <- shiny::reactive({ - diagnosticSummaryFormat(data) - }) - - customColDefs <- list( - databaseName = reactable::colDef( - header = withTooltip( - "Database", - "The database name" - ) - ), - target = reactable::colDef( - header = withTooltip( - "Target", - "The target cohort of interest" - ), - minWidth = 300 - ), - comparator = reactable::colDef( - header = withTooltip( - "Comparator", - "The comparator cohort of interest" - ), - minWidth = 300 - ), - outcome = reactable::colDef( - header = withTooltip( - "Outcome", - "The outcome of interest" - ) - ), - analysis = reactable::colDef( - header = withTooltip( - "Analysis", - "The analysis name" - ) - ), - - mdrr = reactable::colDef( - header = withTooltip( - "MDRR", - "The minimum detectible relative risk" - ), - format = reactable::colFormat(digits = 4) - ), - ease = reactable::colDef( - header = withTooltip( - "EASE", - "The expected absolute systematic error" - ), - format = reactable::colFormat(digits = 4) - ), - maxSdm = reactable::colDef( - header = withTooltip( - "Max SDM", - "The maximum absolute standardized difference of mean" - ), - format = reactable::colFormat(digits = 4) - ), - sharedMaxSdm = reactable::colDef( - header = withTooltip( - "Shared Max SDM", - "The maximum absolute standardized difference of mean of the shared balance (shared across outcomes)" - ), - format = reactable::colFormat(digits = 4) - ), - equipoise = reactable::colDef( - header = withTooltip( - "Equipoise", - "The fraction of the study population with a preference score between 0.3 and 0.7" - ), - format = reactable::colFormat(digits = 4) - ), - balanceDiagnostic = reactable::colDef( - header = withTooltip( - "Balance Diagnostic", - "Pass / warning / fail classification of the balance diagnostic (Max SDM)" - ) - ), - mdrrDiagnostic = reactable::colDef( - header = withTooltip( - "MDRR Diagnostic", - "Pass / warning / fail classification of the MDRR diagnostic" - ) - ), - sharedBalanceDiagnostic = reactable::colDef( - header = withTooltip( - "Shared Balance Diagnostic", - "Pass / warning / fail classification of the shared balance diagnostic (Shared Max SDM)" - ) - ), - easeDiagnostic = reactable::colDef( - header = withTooltip( - "Ease Diagnostic", - "Pass / warning / fail classification of the EASE diagnostic" - ) - ), - equipoiseDiagnostic = reactable::colDef( - header = withTooltip( - "Equipoise Diagnostic", - "Pass / warning / fail classification of the equipoise diagnostic" - ) - ), - - unblind = reactable::colDef( - header = withTooltip( - "Unblind", - "If the value is 1 then the diagnostics passed and results can be unblinded" - ) - ), - - summaryValue = reactable::colDef(show = F) - - ) - - resultTableServer( - id = "diagnosticsTable", - df = data, - colDefsInput = customColDefs - ) - - resultTableServer( - id = "diagnosticsSummaryTable", - df = data2, - colDefsInput = getColDefsCmDiag( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - ) - - } - ) -} - -getColDefsCmDiag <- function( - connectionHandler, - resultDatabaseSettings -){ - - fixedColumns = list( - databaseName = reactable::colDef( - header = withTooltip( - "Database", - "The database name" - ), - sticky = "left" - ), - target = reactable::colDef( - header = withTooltip( - "Target", - "The target cohort of interest" - ), - sticky = "left" - ), - comparator = reactable::colDef( - header = withTooltip( - "Comparator", - "The comparator cohort of interest" - ), - sticky = "left" - ) - ) - - outcomes <- getCmCohorts( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - type = 'outcome' - ) - analyses <- getCmAnalyses( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - colnameFormat <- merge(unique(names(outcomes)), unique(names(analyses))) - colnameFormat <- apply(colnameFormat, 1, function(x){paste(x, collapse = '_', sep = '_')}) - - styleList <- lapply( - colnameFormat, - FUN = function(x){ - reactable::colDef( - header = withTooltip( - paste0(substring(x,1,35), "...", sep=""), - x - ), - style = function(value) { - color <- 'orange' - if(is.na(value)){ - color <- 'black' - }else if(value == 'Pass'){ - color <- '#AFE1AF' - }else if(value == 'Fail'){ - color <- '#E97451' - } - list(background = color) - } - ) - } - ) - names(styleList) <- colnameFormat - result <- append(fixedColumns, styleList) - - return(result) -} - -diagnosticSummaryFormat <- function( - data, - idCols = c('databaseName','target', 'comparator'), - namesFrom = c('outcome','analysis') - ){ - - if(is.null(data())){ - return(NULL) - } - - data2 <- tidyr::pivot_wider( - data = data(), - id_cols = idCols, - names_from = namesFrom, - values_from = c('summaryValue') - ) - - return(data2) -} - - - -getCmDiagnosticsData <- function( - connectionHandler, - resultDatabaseSettings, - inputSelected -) { - - targetIds = inputSelected()$targetIds - outcomeIds = inputSelected()$outcomeIds - comparatorIds = inputSelected()$comparatorIds - analysisIds = inputSelected()$analysisIds - - if(is.null(targetIds) || is.null(outcomeIds)){ - return(NULL) - } - - sql <- " - SELECT DISTINCT - dmd.cdm_source_abbreviation database_name, - cma.description analysis, - cgcd1.cohort_name target, - cgcd2.cohort_name comparator, - cgcd3.cohort_name outcome, - cmds.max_sdm, - cmds.shared_max_sdm, - cmds.equipoise, - cmds.mdrr, - cmds.ease, - cmds.balance_diagnostic, - cmds.shared_balance_diagnostic, -- added back - cmds.equipoise_diagnostic, - cmds.mdrr_diagnostic, - cmds.ease_diagnostic, - cmds.unblind - FROM - @schema.@cm_table_prefixdiagnostics_summary cmds - INNER JOIN @schema.@cm_table_prefixanalysis cma ON cmds.analysis_id = cma.analysis_id - INNER JOIN @schema.@database_table dmd ON dmd.database_id = cmds.database_id - INNER JOIN @schema.@cg_table_prefixcohort_definition cgcd1 ON cmds.target_id = cgcd1.cohort_definition_id - INNER JOIN @schema.@cg_table_prefixcohort_definition cgcd2 ON cmds.comparator_id = cgcd2.cohort_definition_id - INNER JOIN @schema.@cg_table_prefixcohort_definition cgcd3 ON cmds.outcome_id = cgcd3.cohort_definition_id - - where cgcd1.cohort_definition_id in (@targets) - {@use_comparators}?{and cgcd2.cohort_definition_id in (@comparators)} - and cgcd3.cohort_definition_id in (@outcomes) - {@use_analyses}?{and cma.analysis_id in (@analyses)} - ; - " - - result <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - cm_table_prefix = resultDatabaseSettings$cmTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix, - database_table = resultDatabaseSettings$databaseTable, - - targets = paste0(targetIds, collapse = ','), - comparators = paste0(comparatorIds, collapse = ','), - outcomes = paste0(outcomeIds, collapse = ','), - analyses = paste0(analysisIds, collapse = ','), - - use_comparators = !is.null(comparatorIds), - use_analyses = !is.null(analysisIds) - ) - - # adding percent fail for summary - result$summaryValue <- apply( - X = result[, grep('Diagnostic', colnames(result))], - MARGIN = 1, - FUN = function(x){ - - if(sum(x %in% c('FAIL'))>0){ - return('Fail') - } else if(sum(x %in% c('WARNING')) >0){ - return(sum(x %in% c('WARNING'))) - } else{ - return('Pass') - } - } - ) - - return( - result - ) -} diff --git a/R/cohort-method-full-result.R b/R/cohort-method-full-result.R deleted file mode 100644 index 2c05c501..00000000 --- a/R/cohort-method-full-result.R +++ /dev/null @@ -1,163 +0,0 @@ -cohortMethodFullResultViewer <- function(id) { - ns <- shiny::NS(id) - - shiny::div( - # add selected settings - - inputSelectionDfViewer( - id = ns("input-selection-df"), - title = 'Result Selected: ' - ), - - shiny::tabsetPanel( - id = ns("fullTabsetPanel"), - type = 'pills', - shiny::tabPanel( - title = "Power", - cohortMethodPowerViewer(ns("power")) - ), - shiny::tabPanel( - title = "Attrition", - cohortMethodAttritionViewer(ns("attrition")) - ), - shiny::tabPanel( - title = "Population characteristics", - cohortMethodPopulationCharacteristicsViewer(ns("popCharacteristics")) - ), - shiny::tabPanel( - title = "Propensity model", - cohortMethodPropensityModelViewer(ns("propensityModel")) - ), - shiny::tabPanel( - title = "Propensity scores", - cohortMethodPropensityScoreDistViewer(ns("propensityScoreDist")) - ), - shiny::tabPanel( - title = "Covariate balance", - cohortMethodCovariateBalanceViewer(ns("covariateBalance")) - ), - shiny::tabPanel( - title = "Systematic error", - cohortMethodSystematicErrorViewer(ns("systematicError")) - ), - shiny::tabPanel( - title = "Kaplan-Meier", - cohortMethodKaplanMeierViewer(ns("kaplanMeier")) - ) - ) - ) - -} - -cohortMethodFullResultServer <- function( - id, - connectionHandler, - resultDatabaseSettings, - selectedRow, - actionCount -) { - - shiny::moduleServer( - id, - function(input, output, session) { - - # reset the tab when a new result is selected - shiny::observeEvent(actionCount(), { - shiny::updateTabsetPanel(session, "fullTabsetPanel", selected = "Power") - }) - - modifiedRow <- shiny::reactive({ - selectedRow() %>% - dplyr::select( - "target", - "comparator", - "outcome", - "description", - "cdmSourceAbbreviation" - ) %>% - dplyr::rename( - 'Target' = .data$target, - 'Comparator' = .data$comparator, - 'Outcome' = .data$outcome, - 'Analysis' = .data$description, - 'Database' = .data$cdmSourceAbbreviation - ) - }) - - inputSelectionDfServer( - id = "input-selection-df", - dataFrameRow = modifiedRow, - ncol = 2 - ) - - shiny::observeEvent(selectedRow(),{ - if(!is.null(selectedRow()$unblind)){ - if (selectedRow()$unblind == 1) { - shiny::showTab("fullTabsetPanel", "Kaplan-Meier", session = session) - } else{ - shiny::hideTab("fullTabsetPanel", "Kaplan-Meier", session = session) - } - } - }) - - # selected row: : - reactive list with: psStrategy - - cohortMethodPowerServer( - id = "power", - selectedRow = selectedRow, - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - cohortMethodAttritionServer( - id = "attrition", - selectedRow = selectedRow, - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - cohortMethodPopulationCharacteristicsServer( - id = "popCharacteristics", - selectedRow = selectedRow, - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - cohortMethodPropensityModelServer( - id = "propensityModel", - selectedRow = selectedRow, - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - cohortMethodPropensityScoreDistServer( - id = "propensityScoreDist", - selectedRow = selectedRow, - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - cohortMethodCovariateBalanceServer( - id = "covariateBalance", - selectedRow = selectedRow, - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - cohortMethodSystematicErrorServer( - id = "systematicError", - selectedRow = selectedRow, - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - cohortMethodKaplanMeierServer( - id = "kaplanMeier", - selectedRow = selectedRow, - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - } - ) -} diff --git a/R/cohort-method-main.R b/R/cohort-method-main.R deleted file mode 100644 index 7d81487d..00000000 --- a/R/cohort-method-main.R +++ /dev/null @@ -1,290 +0,0 @@ -# @file cohort-method-main.R -# -# Copyright 2024 Observational Health Data Sciences and Informatics -# -# This file is part of PatientLevelPrediction -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -#' The location of the cohort method module helper file -#' -#' @details -#' Returns the location of the cohort method helper file -#' -#' @return -#' string location of the cohort method helper file -#' -#' @export -cohortMethodHelperFile <- function(){ - fileLoc <- system.file('cohort-method-www', "cohort-method.html", package = "OhdsiShinyModules") - return(fileLoc) -} - -#' The viewer of the main cohort method module -#' -#' @param id the unique reference id for the module -#' -#' @return -#' The user interface to the cohort method results viewer -#' -#' @export -cohortMethodViewer <- function(id) { - ns <- shiny::NS(id) - - shinydashboard::box( - status = 'info', - width = 12, - title = shiny::span( shiny::icon("chart-column"), 'Cohort Method'), - solidHeader = TRUE, - - - - # Input selection of T, C and Os - inputSelectionViewer(ns("input-selection")), - - shiny::conditionalPanel( - condition = 'input.generate != 0', - ns = shiny::NS(ns("input-selection")), - - shiny::tabsetPanel( - type = 'pills', - id = ns('mainPanel'), - - shiny::tabPanel( - title = "Diagnostics", - cohortMethodDiagnosticsSummaryViewer(ns("cmDiganostics")) - ), - - shiny::tabPanel( - title = "Results", - cohortMethodResultSummaryViewer(ns("cmResults")) - ) - ) - ) - - ) -} - - -#' The module server for the main cohort method module -#' -#' @param id the unique reference id for the module -#' @param connectionHandler a connection to the database with the results -#' @param resultDatabaseSettings a named list containing the PLE results database connection details -#' -#' @return -#' the PLE results viewer main module server -#' -#' @export -cohortMethodServer <- function( - id, - connectionHandler, - resultDatabaseSettings - ) { - - shiny::moduleServer( - id, - function(input, output, session) { - - dataFolder <- NULL - - targetIds <- getCmCohorts( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - type = 'target' - ) - outcomeIds <- getCmCohorts( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - type = 'outcome' - ) - comparatorIds <- getCmCohorts( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - type = 'comparator' - ) - analysisIds <- getCmAnalyses( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - inputSelected <- inputSelectionServer( - id = "input-selection", - inputSettingList = list( - createInputSetting( - rowNumber = 1, - columnWidth = 6, - varName = 'targetIds', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Target: ', - choices = targetIds, - selected = targetIds[1], - multiple = T, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ), - createInputSetting( - rowNumber = 1, - columnWidth = 6, - varName = 'outcomeIds', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Outcome: ', - choices = outcomeIds, - selected = outcomeIds[1], - multiple = T, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ), - createInputSetting( - rowNumber = 2, - columnWidth = 6, - varName = 'comparatorIds', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Comparator: ', - choices = comparatorIds, - selected = comparatorIds[1], - multiple = T, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ), - - createInputSetting( - rowNumber = 2, - columnWidth = 6, - varName = 'analysisIds', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Analysis: ', - choices = analysisIds, - selected = analysisIds[1], - multiple = T, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ) - ) - ) - - cohortMethodDiagnosticsSummaryServer( - id = "cmDiganostics", - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - inputSelected = inputSelected - ) - - cohortMethodResultSummaryServer( - id = "cmResults", - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - inputSelected = inputSelected - ) - - } - ) -} - -getCmCohorts <- function( - connectionHandler, - resultDatabaseSettings, - type = 'target' -){ - - sql <- " - SELECT DISTINCT - cgcd1.cohort_name as names, - cgcd1.cohort_definition_id - FROM - @schema.@cm_table_prefixresult cmds - INNER JOIN - @schema.@cg_table_prefixcohort_definition cgcd1 - ON cmds.@type_id = cgcd1.cohort_definition_id; - " - - result <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - cm_table_prefix = resultDatabaseSettings$cmTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix, - type = type - ) - - res <- result$cohortDefinitionId - names(res) <- result$names - - return( - res - ) -} - -getCmAnalyses <- function( - connectionHandler, - resultDatabaseSettings -){ - - sql <- " - SELECT DISTINCT - cma.analysis_id, - cma.description as names - FROM - @schema.@cm_table_prefixresult cmds - INNER JOIN - @schema.@cm_table_prefixanalysis cma - ON cmds.analysis_id = cma.analysis_id - ; - " - - result <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - cm_table_prefix = resultDatabaseSettings$cmTablePrefix - ) - - res <- result$analysisId - names(res) <- result$names - - return( - res - ) - -} diff --git a/R/cohort-method-resultSummary.R b/R/cohort-method-resultSummary.R deleted file mode 100644 index 4e8ea8df..00000000 --- a/R/cohort-method-resultSummary.R +++ /dev/null @@ -1,359 +0,0 @@ -# @file cohort-method-resultSummary -# -# Copyright 2024 Observational Health Data Sciences and Informatics -# -# This file is part of OhdsiShinyModules -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -#' The module viewer for rendering the cohort method results -#' -#' @param id the unique reference id for the module -#' -#' @return -#' The user interface to the cohort method diagnostics viewer -#' -#' @export -cohortMethodResultSummaryViewer <- function(id) { - ns <- shiny::NS(id) - - shiny::tabsetPanel( - type = 'hidden', - id = ns('resultPanel'), - - shiny::tabPanel( - title = "Table", - #shinydashboard::box( - # status = 'info', - # width = '100%', - # title = shiny::span('Result Summary'), - # solidHeader = TRUE, - resultTableViewer(ns("resultSummaryTable")) - # ) - ), - - shiny::tabPanel( - title = "Results", - shiny::actionButton( - inputId = ns('goBackCmResults'), - label = "Back To Result Summary", - shiny::icon("arrow-left"), - style="color: #fff; background-color: #337ab7; border-color: #2e6da4" - ), - cohortMethodFullResultViewer(ns("cmFullResults")) - ) - - ) - - -} - - -#' The module server for rendering the PLE diagnostics summary -#' -#' @param id the unique reference id for the module -#' @param connectionHandler the connection to the PLE results database -#' @param resultDatabaseSettings a list containing the result schema and prefixes -#' @param inputSelected The target id, comparator id, outcome id and analysis id selected by the user -#' -#' @return -#' the PLE diagnostics summary results -#' -#' @export -cohortMethodResultSummaryServer <- function( - id, - connectionHandler, - resultDatabaseSettings, - inputSelected -) { - - shiny::moduleServer( - id, - function(input, output, session) { - - shiny::observeEvent( - eventExpr = input$goBackCmResults, - { - shiny::updateTabsetPanel(session, "resultPanel", selected = "Table") - }) - - data <- shiny::reactive({ - getCmResultData( - connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - inputSelected = inputSelected - ) - }) - - resultTableOutputs <- resultTableServer( - id = "resultSummaryTable", - df = data, - colDefsInput = getCmResultSummaryTableColDef(), - addActions = c('results') - ) - - selectedRow <- shiny::reactiveVal(value = NULL) - shiny::observeEvent(resultTableOutputs$actionCount(), { - if(resultTableOutputs$actionType() == 'results'){ - selectedRow(data()[resultTableOutputs$actionIndex()$index,]) - shiny::updateTabsetPanel(session, "resultPanel", selected = "Results") - } - }) - - cohortMethodFullResultServer( - id = "cmFullResults", - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - selectedRow = selectedRow, - actionCount = resultTableOutputs$actionCount - ) - - } - ) -} - - -getCmResultSummaryTableColDef <- function(){ - result <- list( - - analysisId = reactable::colDef(show = F), - description = reactable::colDef( - header = withTooltip( - "Analysis", - "The analysis description" - ), - minWidth = 140 - ), - databaseId = reactable::colDef(show = F), - - cdmSourceAbbreviation = reactable::colDef( - header = withTooltip( - "Database", - "The database name" - ) - ), - - targetId = reactable::colDef(show = F), - target = reactable::colDef( - header = withTooltip( - "Target", - "The target cohort of interest" - ), - minWidth = 300 - ), - - comparatorId = reactable::colDef(show = F), - comparator = reactable::colDef( - header = withTooltip( - "Comparator", - "The comparator cohort of interest" - ), - minWidth = 300 - ), - - outcomeId = reactable::colDef(show = F), - outcome = reactable::colDef( - header = withTooltip( - "Outcome", - "The outcome of interest" - ), - minWidth = 300 - ), - - rr = reactable::colDef( - header = withTooltip( - "RR", - "The estimated relative risk (e.g. the hazard ratio)" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ), - - ci95Lb = reactable::colDef( - header = withTooltip( - "Lower 95% CI", - "The lower bound of the 95% confidence internval of the uncalibrated relative risk" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ), - - ci95Ub = reactable::colDef( - header = withTooltip( - "Upper 95% CI", - "The upper bound of the 95% confidence internval of the uncalibrated relative risk" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ), - - p = reactable::colDef( - header = withTooltip( - "p-val", - "The two-sided p-value of the uncalibrated relative risk" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ), - - calibratedRr = reactable::colDef( - header = withTooltip( - "Calibrated RR", - "The calibrated relative risk" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ), - - calibratedCi95Lb = reactable::colDef( - header = withTooltip( - "Calibrated Lower 95% CI", - "The lower bound of the 95% confidence internval of the calibrated relative risk" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ), - - calibratedCi95Ub = reactable::colDef( - header = withTooltip( - "Calibrated Upper 95% CI", - "The upper bound of the 95% confidence internval of the calibrated relative risk" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ), - - calibratedP = reactable::colDef( - header = withTooltip( - "Calibrated p-val", - "The two-sided p-value of the calibrated relative risk" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ), - - logRr = reactable::colDef(show = F), - seLogRr = reactable::colDef(show = F), - targetSubjects = reactable::colDef(show = F), - comparatorSubjects = reactable::colDef(show = F), - targetDays = reactable::colDef(show = F), - comparatorDays = reactable::colDef(show = F), - targetOutcomes = reactable::colDef(show = F), - comparatorOutcomes = reactable::colDef(show = F), - calibratedLogRr = reactable::colDef(show = F), - calibratedSeLogRr = reactable::colDef(show = F), - calibratedSeLogRr = reactable::colDef(show = F), - unblind = reactable::colDef(show = F) - ) - - return(result) -} - -getCmResultData <- function( - connectionHandler, - resultDatabaseSettings, - inputSelected -) { - - targetIds = inputSelected()$targetIds - outcomeIds = inputSelected()$outcomeIds - comparatorIds = inputSelected()$comparatorIds - analysisIds = inputSelected()$analysisIds - - if(is.null(comparatorIds) || is.null(targetIds) || is.null(outcomeIds) || is.null(analysisIds)){ - return(NULL) - } - - sql <- " - SELECT - cma.analysis_id, - cma.description description, - dmd.database_id database_id, - dmd.cdm_source_abbreviation cdm_source_abbreviation, - cmr.target_id, - cg1.cohort_name as target, - cmr.outcome_id, - cg2.cohort_name as outcome, - cmr.comparator_id, - cg3.cohort_name as comparator, - case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.rr end rr, - case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.ci_95_lb end ci_95_lb, - case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.ci_95_ub end ci_95_ub, - case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.p end p, - case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.log_rr end log_rr, - case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.se_log_rr end se_log_rr, - cmr.target_subjects, - cmr.comparator_subjects, - cmr.target_days, - cmr.comparator_days, - cmr.target_outcomes, - cmr.comparator_outcomes, - case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.calibrated_rr end calibrated_rr, - case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.calibrated_ci_95_lb end calibrated_ci_95_lb, - case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.calibrated_ci_95_ub end calibrated_ci_95_ub, - case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.calibrated_p end calibrated_p, - case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.calibrated_log_rr end calibrated_log_rr, - case when COALESCE(cmds.unblind, 0) = 0 then NULL else cmr.calibrated_se_log_rr end calibrated_se_log_rr, - COALESCE(cmds.unblind, 0) unblind -FROM - @schema.@cm_table_prefixanalysis cma - JOIN @schema.@cm_table_prefixresult cmr - on cmr.analysis_id = cma.analysis_id - - JOIN @schema.@database_table dmd - on dmd.database_id = cmr.database_id - - LEFT JOIN @schema.@cm_table_prefixdiagnostics_summary cmds - on cmds.analysis_id = cmr.analysis_id - AND cmds.target_id = cmr.target_id - AND cmds.comparator_id = cmr.comparator_id - AND cmds.outcome_id = cmr.outcome_id - AND cmds.database_id = cmr.database_id - - inner join @schema.@cg_table_prefixcohort_definition cg1 - on cg1.cohort_definition_id = cmr.target_id - - inner join @schema.@cg_table_prefixcohort_definition cg2 - on cg2.cohort_definition_id = cmr.outcome_id - - inner join @schema.@cg_table_prefixcohort_definition cg3 - on cg3.cohort_definition_id = cmr.comparator_id - - where cmr.target_id in (@targets) - {@use_comparators}?{and cmr.comparator_id in (@comparators)} - and cmr.outcome_id in (@outcomes) - {@use_analyses}?{and cmr.analysis_id in (@analyses)} - ; - " - - result <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - cm_table_prefix = resultDatabaseSettings$cmTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix, - database_table = resultDatabaseSettings$databaseTable, - - targets = paste0(targetIds, collapse = ','), - comparators = paste0(comparatorIds, collapse = ','), - outcomes = paste0(outcomeIds, collapse = ','), - analyses = paste0(analysisIds, collapse = ','), - - use_comparators = !is.null(comparatorIds), - use_analyses = !is.null(analysisIds) - ) - - return( - result - ) -} diff --git a/R/cohort-method-attrition.R b/R/estimation-cohort-method-attrition.R similarity index 100% rename from R/cohort-method-attrition.R rename to R/estimation-cohort-method-attrition.R diff --git a/R/cohort-method-covariateBalance.R b/R/estimation-cohort-method-covariateBalance.R similarity index 100% rename from R/cohort-method-covariateBalance.R rename to R/estimation-cohort-method-covariateBalance.R diff --git a/R/cohort-method-kaplainMeier.R b/R/estimation-cohort-method-kaplainMeier.R similarity index 100% rename from R/cohort-method-kaplainMeier.R rename to R/estimation-cohort-method-kaplainMeier.R diff --git a/R/cohort-method-populationCharacteristics.R b/R/estimation-cohort-method-populationCharacteristics.R similarity index 98% rename from R/cohort-method-populationCharacteristics.R rename to R/estimation-cohort-method-populationCharacteristics.R index c37cde83..778a04ae 100644 --- a/R/cohort-method-populationCharacteristics.R +++ b/R/estimation-cohort-method-populationCharacteristics.R @@ -149,7 +149,8 @@ cohortMethodPopulationCharacteristicsServer <- function( digits = 2 ), sortable = F - ) + ), + label = reactable::colDef(show = T) ) ) @@ -251,7 +252,7 @@ getCohortMethodPopChar <- function( .data$covariateName ) - # remove text before covariateNames + # remove text before covariateNames - TODO generalize this? txtRms <- c( 'age group: ', 'condition_era group during day -365 through 0 days relative to index: ', @@ -260,7 +261,7 @@ getCohortMethodPopChar <- function( for(txtRm in txtRms){ result$covariateName <- gsub(txtRm,'', result$covariateName) } - + return( result ) diff --git a/R/cohort-method-power.R b/R/estimation-cohort-method-power.R similarity index 100% rename from R/cohort-method-power.R rename to R/estimation-cohort-method-power.R diff --git a/R/cohort-method-propensityModel.R b/R/estimation-cohort-method-propensityModel.R similarity index 100% rename from R/cohort-method-propensityModel.R rename to R/estimation-cohort-method-propensityModel.R diff --git a/R/cohort-method-propensityScoreDistribution.R b/R/estimation-cohort-method-propensityScoreDistribution.R similarity index 100% rename from R/cohort-method-propensityScoreDistribution.R rename to R/estimation-cohort-method-propensityScoreDistribution.R diff --git a/R/cohort-method-systematicError.R b/R/estimation-cohort-method-systematicError.R similarity index 100% rename from R/cohort-method-systematicError.R rename to R/estimation-cohort-method-systematicError.R diff --git a/R/estimation-main.R b/R/estimation-main.R index 18665069..9aa9f521 100644 --- a/R/estimation-main.R +++ b/R/estimation-main.R @@ -167,7 +167,7 @@ estimationServer <- function( # Targets targets <- lapply(options$groupedTs, function(x) x$cohortId) - targets <- unlist(targets) + targets <- unlist(targets) # initial outcomes for first T outcomeDf <- options$tos[[1]] @@ -198,7 +198,7 @@ estimationServer <- function( outcomesVector <- outcomes()$outcomeId names(outcomesVector) <- outcomes()$outcomeName - shiny::updateSelectInput( + shinyWidgets::updatePickerInput( session = session, inputId = 'outcomeId', label = 'Outcome: ', @@ -227,15 +227,21 @@ estimationServer <- function( virtualScroll = 500 ) ), - shiny::selectInput( + shinyWidgets::pickerInput( inputId = session$ns('outcomeId'), label = 'Outcome: ', choices = initialOutcomes, selected = initialOutcomes[1], multiple = FALSE, - selectize = TRUE, - width = NULL, - size = NULL + options = shinyWidgets::pickerOptions( + actionsBox = TRUE, + liveSearch = TRUE, + dropupAuto = F, + size = 10, + liveSearchStyle = "contains", + liveSearchPlaceholder = "Type here to search", + virtualScroll = 500 + ) ), style = 'margin-left: 2%; width: 78%; display: inline-block; vertical-align: middle;' ), diff --git a/R/estimation-sccs-diagnostics.R b/R/estimation-sccs-diagnostics.R index cbe13b52..0c721fdd 100644 --- a/R/estimation-sccs-diagnostics.R +++ b/R/estimation-sccs-diagnostics.R @@ -165,6 +165,12 @@ estimationGetSccsDiagnosticColDefs <- function(){ "The outcome of interest " ) ), + indication = reactable::colDef( + header = withTooltip( + "Indication", + "The indication of interest " + ) + ), summaryValue = reactable::colDef( header = withTooltip( "Diagnostic", diff --git a/R/report-main.R b/R/report-main.R index 8a17933a..9bba523d 100644 --- a/R/report-main.R +++ b/R/report-main.R @@ -926,17 +926,28 @@ getTandOs <- function( # add cohort names res <- merge( - res,cg[,c('cohortDefinitionId','cohortName')], - by.x = 'tid', + x = res, + y = cg[,c('cohortDefinitionId','cohortName')], + by.x = 'tid', by.y = 'cohortDefinitionId' ) %>% - dplyr::rename(targetName = 'cohortName') + dplyr::rename( + targetName = 'cohortName' + ) + res <- merge( - res,cg[,c('cohortDefinitionId','cohortName')], + x = res, + y = cg[,c('cohortDefinitionId','cohortName')], by.x = 'oid', by.y = 'cohortDefinitionId' ) %>% - dplyr::rename(outcomeName = 'cohortName') + dplyr::rename( + outcomeName = 'cohortName' + ) %>% + dplyr::arrange( + .data$targetName, + .data$outcomeName + ) tos <- lapply(unique(res$tid), function(tid){ data.frame( @@ -975,6 +986,8 @@ getTandOs <- function( by.x = 'cohortDefinitionId', by.y = 'tid' ) + ) %>% dplyr::arrange( # adding order to make options orders + .data$targetName ) parents <- unique(parentChild$subsetParent) groupedCohorts <- lapply(1:length(parents), function(i){ @@ -1029,7 +1042,8 @@ getTandOs <- function( characterization = characterization, cohortIncidence = cohortIncidence, cohortMethod = cohortMethod, - prediction = prediction + prediction = prediction, + sccs = sccs ) ) diff --git a/R/sccs-diagnosticsSummary.R b/R/sccs-diagnosticsSummary.R deleted file mode 100644 index ccfe77a3..00000000 --- a/R/sccs-diagnosticsSummary.R +++ /dev/null @@ -1,465 +0,0 @@ -# @file sccs-diagnosticsSummary -# -# Copyright 2024 Observational Health Data Sciences and Informatics -# -# This file is part of OhdsiShinyModules -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -sccsDiagnosticsSummaryViewer <- function(id) { - ns <- shiny::NS(id) - - #shinydashboard::box( - # status = 'info', - # width = '100%', - # title = shiny::span('Diagnostic Results'), - # solidHeader = TRUE, - shiny::div( - shiny::tabsetPanel( - type = 'pills', - id = ns('diagnosticsTablePanel'), - shiny::tabPanel( - title = 'Summary', - resultTableViewer(ns("diagnosticsSummaryTable")) - ), - shiny::tabPanel( - title = 'Full', - resultTableViewer(ns("diagnosticsTable")) - ) - ) - ) - -} - -sccsDiagnosticsSummaryServer <- function( - id, - connectionHandler, - resultDatabaseSettings, - inputSelected -) { - - shiny::moduleServer( - id, - function(input, output, session) { - - - data <- shiny::reactive({ - exposure <- inputSelected()$exposure - - if (is.character(exposure)) { - exposureGroup <- strsplit(exposure, " ")[[1]] - targetId <- exposureGroup[[1]] - indidcationId <- exposureGroup[[2]] - } else { - targetId <- -1 - indidcationId <- -1 - } - - getSccsAllDiagnosticsSummary( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - targetIds = targetId, - outcomeIds = inputSelected()$outcome, - analysisIds = inputSelected()$analysis, - indicationIds = indidcationId - ) - }) - - data2 <- shiny::reactive({ # use CM diag function - diagnosticSummaryFormat( - data = data, - idCols = c('databaseName','target','covariateName'), - namesFrom = c('outcome','analysis') - ) - }) - - customColDefs <- list( - databaseName = reactable::colDef( - header = withTooltip( - "Database", - "The database name" - ) - ), - target = reactable::colDef( - header = withTooltip( - "Target", - "The target cohort of interest " - ) - ), - outcome = reactable::colDef( - header = withTooltip( - "Outcome", - "The outcome of interest " - ) - ), - analysis = reactable::colDef( - header = withTooltip( - "Analysis", - "The analysis name " - ) - ), - covariateName = reactable::colDef( - header = withTooltip( - "Time Period", - "The time period of interest" - ) - ), - mdrr = reactable::colDef( - header = withTooltip( - "mdrr", - "The minimum detectible relative risk" - ) - ), - ease = reactable::colDef( - header = withTooltip( - "ease", - "The ..." - ) - ), - timeTrendP = reactable::colDef( - header = withTooltip( - "timeTrendP", - "The ..." - ) - ), - preExposureP = reactable::colDef( - header = withTooltip( - "preExposureP", - "The ..." - ) - ), - mdrrDiagnostic = reactable::colDef( - header = withTooltip( - "mdrrDiagnostic", - "The ..." - ) - ), - easeDiagnostic = reactable::colDef( - header = withTooltip( - "easeDiagnostic", - "The ..." - ) - ), - timeTrendDiagnostic = reactable::colDef( - header = withTooltip( - "timeTrendDiagnostic", - "The ..." - ) - ), - preExposureDiagnostic = reactable::colDef( - header = withTooltip( - "preExposureDiagnostic", - "The ..." - ) - ), - - unblind = reactable::colDef( - header = withTooltip( - "unblind", - "If the value is 1 then the diagnostics passed and results can be unblinded" - ) - ) - - ) - - resultTableServer( - id = "diagnosticsTable", - df = data, - colDefsInput = customColDefs - ) - - - resultTableServer( - id = "diagnosticsSummaryTable", - df = data2, - colDefsInput = getColDefsSccsDiag( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - ) - - } - ) -} - - - -getSccsDiagAnalyses <- function( - connectionHandler, - resultDatabaseSettings -){ - - sql <- " - SELECT distinct - a.analysis_id, - a.description as analysis - - FROM - @schema.@sccs_table_prefixanalysis a - ; - " - result <- connectionHandler$queryDb( - sql, - schema = resultDatabaseSettings$schema, - sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, - snakeCaseToCamelCase = TRUE - ) - - res <- result$analysisId - names(res) <- result$analysis - - return(res) -} - - -getSccsDiagOutcomes <- function( - connectionHandler, - resultDatabaseSettings -){ - - sql <- " - SELECT distinct - c.cohort_name as outcome, - c.cohort_definition_id - - FROM @schema.@sccs_table_prefixdiagnostics_summary ds - inner join - @schema.@sccs_table_prefixexposures_outcome_set eos - on ds.exposures_outcome_set_id = eos.exposures_outcome_set_id - inner join - @schema.@cg_table_prefixcohort_definition as c - on c.cohort_definition_id = eos.outcome_id - ; - " - result <- connectionHandler$queryDb( - sql, - schema = resultDatabaseSettings$schema, - sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix, - snakeCaseToCamelCase = TRUE - ) - - res <- result$cohortDefinitionId - names(res) <- result$outcome - - return(res) -} - -getSccsDiagTargets <- function( - connectionHandler, - resultDatabaseSettings -){ - - sql <- " - SELECT distinct - c2.cohort_name as target, - c2.cohort_definition_id - - FROM @schema.@sccs_table_prefixdiagnostics_summary ds - - INNER JOIN - @schema.@sccs_table_prefixcovariate cov - on cov.covariate_id = ds.covariate_id and - cov.exposures_outcome_set_id = ds.exposures_outcome_set_id and - cov.analysis_id = ds.analysis_id and - cov.database_id = ds.database_id - - inner join - @schema.@cg_table_prefixcohort_definition as c2 - on cov.era_id = c2.cohort_definition_id - ; - " - result <- connectionHandler$queryDb( - sql, - schema = resultDatabaseSettings$schema, - sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix, - snakeCaseToCamelCase = TRUE - ) - - res <- result$cohortDefinitionId - names(res) <- result$target - - return(res) -} - - -getSccsAllDiagnosticsSummary <- function( - connectionHandler, - resultDatabaseSettings, - targetIds, - outcomeIds, - analysisIds = NULL, - indicationIds = NULL -) { - - if(is.null(targetIds) || is.null(outcomeIds)){ - return(NULL) - } - - if (any(indicationIds == -1)) { - indicationIds <- NULL - } - - sql <- " - SELECT - d.cdm_source_abbreviation as database_name, - c.cohort_name as outcome, - c2.cohort_name as target, - a.description as analysis, - cov.covariate_name, - ds.* - FROM @schema.@sccs_table_prefixdiagnostics_summary ds - inner join - @schema.@sccs_table_prefixexposures_outcome_set eos - on ds.exposures_outcome_set_id = eos.exposures_outcome_set_id - inner join - @schema.@cg_table_prefixcohort_definition as c - on c.cohort_definition_id = eos.outcome_id - - INNER JOIN - @schema.@database_table_prefix@database_table d - on d.database_id = ds.database_id - - INNER JOIN - @schema.@sccs_table_prefixanalysis a - on a.analysis_id = ds.analysis_id - - INNER JOIN - @schema.@sccs_table_prefixcovariate cov - on cov.covariate_id = ds.covariate_id and - cov.exposures_outcome_set_id = ds.exposures_outcome_set_id and - cov.analysis_id = ds.analysis_id and - cov.database_id = ds.database_id - - inner join - @schema.@cg_table_prefixcohort_definition as c2 - on cov.era_id = c2.cohort_definition_id - - - where - - c2.cohort_definition_id in (@target_ids) - and c.cohort_definition_id in (@outcome_ids) - {@use_analysis}?{and a.analysis_id in (@analysis_ids)} - {@use_indications} ? {and eos.nesting_cohort_id IN (@indication_ids)} : {and eos.nesting_cohort_id IS NULL} - ; - " - result <- connectionHandler$queryDb( - sql, - schema = resultDatabaseSettings$schema, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix, - sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, - database_table_prefix = resultDatabaseSettings$databaseTablePrefix, - database_table = resultDatabaseSettings$databaseTable, - - target_ids = paste0(targetIds, collapse = ','), - outcome_ids = paste0(outcomeIds, collapse = ','), - analysis_ids = paste0(analysisIds, collapse = ','), - indication_ids = paste0(indicationIds, collapse = ','), - use_analysis = !is.null(analysisIds), - use_indications = !is.null(indicationIds), - snakeCaseToCamelCase = TRUE - ) - - result <- result %>% - dplyr::select(-c("analysisId","exposuresOutcomeSetId","databaseId","covariateId")) - - result$summaryValue <- apply( - X = result[, grep('Diagnostic', colnames(result))], - MARGIN = 1, - FUN = function(x){ - - if(sum(x %in% c('FAIL'))>0){ - return('Fail') - } else if(sum(x %in% c('WARNING')) >0){ - return(sum(x %in% c('WARNING'), na.rm = T)) - } else{ - return('Pass') - } - } - ) - return(result) - -} - - -getColDefsSccsDiag <- function( - connectionHandler, - resultDatabaseSettings -){ - - fixedColumns = list( - databaseName = reactable::colDef( - header = withTooltip( - "Database", - "The database name" - ), - sticky = "left" - ), - target = reactable::colDef( - header = withTooltip( - "Target", - "The target cohort of interest " - ), - sticky = "left" - ), - covariateName = reactable::colDef( - header = withTooltip( - "Time Period", - "The time period of interest" - ), - sticky = "left" - ) - ) - - outcomes <- getSccsDiagOutcomes( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - analyses <- getSccsDiagAnalyses( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - colnameFormat <- merge(unique(names(outcomes)), unique(names(analyses))) - colnameFormat <- apply(colnameFormat, 1, function(x){paste(x, collapse = '_', sep = '_')}) - - styleList <- lapply( - colnameFormat, - FUN = function(x){ - reactable::colDef( - header = withTooltip( - substring(x,1,40), - x - ), - style = function(value) { - color <- 'orange' - if(is.na(value)){ - color <- 'black' - }else if(value == 'Pass'){ - color <- '#AFE1AF' - }else if(value == 'Fail'){ - color <- '#E97451' - } - list(background = color) - } - ) - } - ) - names(styleList) <- colnameFormat - result <- append(fixedColumns, styleList) - - return(result) -} diff --git a/R/sccs-main.R b/R/sccs-main.R deleted file mode 100644 index 54a2168f..00000000 --- a/R/sccs-main.R +++ /dev/null @@ -1,212 +0,0 @@ -#' SCCS shiny module UI code -#' @description -#' Load the ui for the sccs module -#' @param id id for module -#' @export -sccsView <- function(id = "sccs-module") { - ns <- shiny::NS(id) - tags <- shiny::tags - - shinydashboard::box( - status = 'info', - width = 12, - title = shiny::span( shiny::icon("people-arrows"), 'Self Controlled Case Series'), - solidHeader = TRUE, - - - inputSelectionViewer(ns("input-selection-sccs")), - - shiny::conditionalPanel( - condition = 'input.generate != 0', - ns = shiny::NS(ns("input-selection-sccs")), - - shiny::tabsetPanel( - type = 'pills', - id = ns("mainTabsetPanel"), - - shiny::tabPanel( - title = "Diagnostics", - sccsDiagnosticsSummaryViewer(ns("sccsDiganostics")) - ), - shiny::tabPanel( - title = 'Results', - sccsResultsViewer(ns("sccsResults")), - ) - ) - - ) # end condition - ) -} - -#' Gets input selection box for use with SCCS exposure indication selection -#' @noRd -.getSccsExposureIndicationSelection <- function(connectionHandler, - resultDatabaseSettings) { - migrations <- getMigrations(connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - tablePrefix = resultDatabaseSettings$sccsTablePrefix) - - # Migration_2-v5_1_0.sql - useNestingIndications <- migrations %>% migrationPresent(2) - - if (useNestingIndications) { - # Requires migration in 5.1.0 of cohort generator - expIndicationsTbl <- sccsGetExposureIndications( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - } else { - # Backwards compatability - expIndicationsTbl <- sccsGetExposures( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - } - - expIndicationsTbl <- expIndicationsTbl %>% - dplyr::mutate(exposureIndicationId = paste(.data$exposureId, - .data$indicationId)) - - exposureChoices <- expIndicationsTbl %>% - shinyWidgets::prepare_choices(label = .data$indicationName, - value = .data$exposureIndicationId, - group_by = .data$exposureName, - alias = .data$exposureName) - - namesCallback <- function(inputSelected) { - if (is.null(inputSelected)) - return("") - - vars <- strsplit(inputSelected, " ")[[1]] - - res <- expIndicationsTbl %>% - dplyr::filter(.data$exposureId == vars[[1]], - .data$indicationId == vars[[2]]) %>% - dplyr::select("exposureName", - "indicationName") - - paste(res$exposureName, "\n\t-", res$indicationName) - } - - return( - createInputSetting( - rowNumber = 1, - columnWidth = 12, - varName = 'exposure', - uiFunction = 'shinyWidgets::virtualSelectInput', - updateFunction = "shinyWidgets::updateVirtualSelectInput", - uiInputs = list( - label = 'Target/Indication: ', - choices = exposureChoices, - multiple = FALSE, - search = TRUE, - searchGroup = TRUE, - hasOptionDescription = TRUE, - keepAlwaysOpen = FALSE - ), - namesCallback = namesCallback - ) - ) -} - - -#' The module server for exploring SCCS -#' -#' @details -#' The user specifies the id for the module -#' -#' @param id the unique reference id for the module -#' @param connectionHandler a connection to the database with the results -#' @param resultDatabaseSettings a list containing the prediction result schema and connection details -#' -#' @return -#' The server for the PatientLevelPrediction module -#' -#' @export -sccsServer <- function( - id, - connectionHandler, - resultDatabaseSettings = list(port = 1) -) { - ns <- shiny::NS(id) - - # create functions to result list - outcomes <- sccsGetOutcomes( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - analyses <- sccsGetAnalyses( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - shiny::moduleServer(id, function(input, output, session) { - - inputSettings <- list( - .getSccsExposureIndicationSelection(connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings), - createInputSetting( - rowNumber = 2, - columnWidth = 6, - varName = 'outcome', - uiFunction = 'shinyWidgets::virtualSelectInput', - updateFunction = "shinyWidgets::updateVirtualSelectInput", - uiInputs = list( - label = 'Outcome: ', - choices = outcomes, - selected = outcomes[1], - multiple = F, - search = TRUE - ) - ), - createInputSetting( - rowNumber = 2, - columnWidth = 6, - varName = 'analysis', - uiFunction = 'shinyWidgets::virtualSelectInput', - updateFunction = "shinyWidgets::updateVirtualSelectInput", - uiInputs = list( - label = 'Analysis: ', - choices = analyses, - selected = analyses, - multiple = T - ) - ) - ) - - inputSelected <- inputSelectionServer( - id = "input-selection-sccs", - inputSettingList = inputSettings - ) - - sccsDiagnosticsSummaryServer( - id = "sccsDiganostics", - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - inputSelected = inputSelected - ) - - sccsResultsServer( - id = "sccsResults", - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - inputSelected = inputSelected - ) - }) -} - -#' The location of the description module helper file -#' -#' @details -#' Returns the location of the description helper file -#' -#' @return -#' string location of the description helper file -#' -#' @export -sccsHelperFile <- function() { - fileLoc <- system.file('sccs-www', "sccs.html", package = utils::packageName()) - return(fileLoc) -} diff --git a/R/sccs-results-full.R b/R/sccs-results-full.R deleted file mode 100644 index 2d5e1d9c..00000000 --- a/R/sccs-results-full.R +++ /dev/null @@ -1,427 +0,0 @@ -sccsFullResultViewer <- function(id) { - ns <- shiny::NS(id) - - shiny::div( - - # add selection module - inputSelectionDfViewer( - id = ns("input-selection-df"), - title = 'Result Selected' - ), - - shiny::tabsetPanel( - id = ns("fullTabsetPanel"), - type = 'pills', - - shiny::tabPanel( - "Power", - shiny::div(shiny::strong("Table 1."), "For each variable of interest: the number of cases (people with at least one outcome), the number of years those people were observed, the number of outcomes, the number of subjects with at least one exposure, the number of patient-years exposed, the number of outcomes while exposed, and the minimum detectable relative risk (MDRR)."), - resultTableViewer(ns('powerTable')) - ), - shiny::tabPanel( - "Attrition", - shiny::plotOutput(ns("attritionPlot"), width = 600, height = 500), - shiny::div( - shiny::strong("Figure 1."), - "Attrition, showing the number of cases (number of subjects with at least one outcome), and number of outcomes (number of ocurrences of the outcome) after each step in the study.") - ), - shiny::tabPanel( - "Model", - shiny::tabsetPanel( - id = ns("modelTabsetPanel"), - shiny::tabPanel( - "Model coefficients", - shiny::div( - shiny::strong("Table 2."), - "The fitted non-zero coefficent (incidence rate ratio) and 95 percent confidence interval for all variables in the model." - ), - shiny::tableOutput(ns("modelTable")) - ), - shiny::tabPanel( - "Age spline", - shiny::plotOutput(ns("ageSplinePlot")), - shiny::div(shiny::strong("Figure 2a."), "Spline fitted for age.") - ), - shiny::tabPanel( - "Season spline", - shiny::plotOutput(ns("seasonSplinePlot")), - shiny::div(shiny::strong("Figure 2b."), "Spline fitted for season") - ), - shiny::tabPanel( - "Calendar time spline", - shiny::plotOutput(ns("calendarTimeSplinePlot")), - shiny::div(shiny::strong("Figure 2c."), "Spline fitted for calendar time") - ) - ) - ), - shiny::tabPanel( - "Spanning", - shiny::radioButtons(ns("spanningType"), label = "Type:", choices = c("Age", "Calendar time")), - shiny::plotOutput(ns("spanningPlot")), - shiny::div(shiny::strong("Figure 3."), "Number of subjects observed for 3 consecutive months, centered on the indicated month.") - ), - shiny::tabPanel( - "Time trend", - shiny::plotOutput(ns("timeTrendPlot"), height = 600), - shiny::div( - shiny::strong("Figure 4."), - "The ratio of observed to expected outcomes per month. The expected count is computing either assuming a constant rate (bottom plot) or adjusting for calendar time, seasonality, and / or age, as specified in the model (top plot)." - ) - ), - shiny::tabPanel( - "Time to event", - shiny::plotOutput(ns("timeToEventPlot")), - shiny::div( - shiny::strong("Figure 5."), - "The number of events and subjects observed per week relative to the start of the first exposure (indicated by the thick vertical line)." - ) - ), - shiny::tabPanel( - "Event dep. observation", - shiny::plotOutput(ns("eventDepObservationPlot")), - shiny::div(shiny::strong("Figure 6."), "Histograms for the number of months between the first occurrence of the outcome and the end of observation, stratified by whether the end of observation was censored (inferred as not being equal to the end of database time), or uncensored (inferred as having the subject still be observed at the end of database time)." - ) - ), - shiny::tabPanel( - "Systematic error", - shiny::plotOutput(ns("controlEstimatesPlot")), - shiny::div(shiny::strong("Figure 7."), "Systematic error. Effect size estimates for the negative controls (true incidence rate ratio = 1) - and positive controls (true incidence rate ratio > 1), before and after calibration. Estimates below the diagonal dashed - lines are statistically significant (alpha = 0.05) different from the true effect size. A well-calibrated - estimator should have the true effect size within the 95 percent confidence interval 95 percent of times.") - ) - ) - - ) - -} - - -sccsFullResultServer <- function( - id, - connectionHandler, - resultDatabaseSettings, - selectedRow, - actionCount -) { - - shiny::moduleServer( - id, - function(input, output, session) { - - # reset the tab when a new result is selected - shiny::observeEvent(actionCount(), { - shiny::updateTabsetPanel(session, "fullTabsetPanel", selected = "Power") - }) - - modifiedRow <- shiny::reactive({ - selectedRow() %>% - dplyr::select( - "covariateName", - "outcome", - "description", - "databaseName" - ) %>% - dplyr::rename( - 'Outcome' = .data$outcome, - 'Analysis' = .data$description, - 'Database' = .data$databaseName - ) - }) - - inputSelectionDfServer( - id = "input-selection-df", - dataFrameRow = modifiedRow, - ncol = 2 - ) - - powerTable <- shiny::reactive({ - row <- selectedRow() - if (is.null(row)) { - return(NULL) - } else { - resTargetTable <- row %>% - dplyr::mutate(outcomeEvents = ifelse(.data$unblind == 1, .data$outcomeEvents, NA)) %>% - dplyr::select( - "covariateName", - "outcomeSubjects", - "observedDays", - "outcomeEvents", - "covariateSubjects", - "covariateDays", - "covariateOutcomes", - "mdrr" - ) %>% - dplyr::mutate(observedDays = .data$observedDays / 365.25, - covariateDays = .data$covariateDays / 365.25) - - return(resTargetTable) - } - }) - - colDefsInput <- list( - covariateName = reactable::colDef( - header = withTooltip( - "Variable", - "The covariate" - )), - outcomeSubjects = reactable::colDef( - header = withTooltip( - "Cases", - "The number of cases" - )), - observedDays = reactable::colDef( - format = reactable::colFormat(digits = 2), - header = withTooltip( - "Years observed", - "The total years observed" - )), - outcomeEvents = reactable::colDef( - header = withTooltip( - "Outcomes", - "The total number of outcomes" - )), - covariateSubjects = reactable::colDef( - header = withTooltip( - "Persons exposed", - "The total number of people exposed" - )), - covariateDays = reactable::colDef( - format = reactable::colFormat(digits = 2), - header = withTooltip( - "Years exposed", - "The total number of years exposed" - )), - covariateOutcomes = reactable::colDef( - header = withTooltip( - "Outcomes while exposed", - "The total number of outcomes while exposed" - )), - mdrr = reactable::colDef( - format = reactable::colFormat(digits = 4), - header = withTooltip( - "MDRR", - "The minimal detectable relative risk" - )) - ) - - # move these to a different submodule? - resultTableServer( - id = "powerTable", # how is this working without session$ns - df = powerTable, - colDefsInput = colDefsInput - ) - - output$attritionPlot <- shiny::renderPlot({ - - row <- selectedRow() - if (is.null(row)) { - return(NULL) - } else { - attrition <- getSccsAttrition( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, - databaseId = row$databaseId, - analysisId = row$analysisId, - covariateId = row$covariateId - ) - drawAttritionDiagram(attrition) - } - }) - - output$modelTable <- shiny::renderTable({ - row <- selectedRow() - if (is.null(row)) { - return(NULL) - } else { - resTargetTable <- getSccsModel( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - exposureId = row$eraId, - outcomeId = row$outcomeId, - databaseId = row$databaseId, - analysisId = row$analysisId - ) - - resTargetTable <- resTargetTable %>% - dplyr::arrange(.data$covariateId) %>% - dplyr::select(-"covariateId") - - colnames(resTargetTable) <- c("Variable", - "IRR", - "LB", - "UB") - return(resTargetTable) - } - }) - - output$timeTrendPlot <- shiny::renderPlot({ - row <- selectedRow() - if (is.null(row)) { - return(NULL) - } else { - timeTrend <- getSccsTimeTrend( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - exposureId = row$eraId, - outcomeId = row$outcomeId, - databaseId = row$databaseId, - analysisId = row$analysisId - ) - - if (all(c(hasData(timeTrend$ratio), hasData(timeTrend$adjustedRatio)))) { - plotTimeTrend(timeTrend) - } else { - plotTimeTrendStability(timeTrend) - } - } - }) - - output$timeToEventPlot <- shiny::renderPlot({ - row <- selectedRow() - if (is.null(row)) { - return(NULL) - } else { - timeToEvent <- getSccsTimeToEvent( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, - exposureId = row$eraId, - covariateId = row$covariateId, - databaseId = row$databaseId, - analysisId = row$analysisId - ) - plotTimeToEventSccs(timeToEvent) - } - }) - - output$eventDepObservationPlot <- shiny::renderPlot({ - row <- selectedRow() - if (is.null(row)) { - return(NULL) - } else { - eventDepObservation <- getSccsEventDepObservation( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, - databaseId = row$databaseId, - analysisId = row$analysisId - ) - plotEventDepObservation(eventDepObservation) - } - }) - - output$spanningPlot <- shiny::renderPlot({ - row <- selectedRow() - if (is.null(row)) { - return(NULL) - } else { - if (input$spanningType == "Age") { - ageSpanning <- getSccsAgeSpanning( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, - databaseId = row$databaseId, - analysisId = row$analysisId - ) - plotSpanning(ageSpanning, type = "age") - } else { - calendarTimeSpanning <- getSccsCalendarTimeSpanning( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, - databaseId = row$databaseId, - analysisId = row$analysisId - ) - plotSpanning(calendarTimeSpanning, type = "calendar time") - } - } - }) - - output$ageSplinePlot <- shiny::renderPlot({ - - row <- selectedRow() - if (is.null(row)) { - return(NULL) - } else { - ageSpline <- getSccsSpline( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, - databaseId = row$databaseId, - analysisId = row$analysisId, - splineType = "age" - ) - if (nrow(ageSpline) == 0) { - return(NULL) - } - plotAgeSpline(ageSpline) - } - }) - - output$seasonSplinePlot <- shiny::renderPlot({ - row <- selectedRow() - if (is.null(row)) { - return(NULL) - } else { - seasonSpline <- getSccsSpline( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, - databaseId = row$databaseId, - analysisId = row$analysisId, - splineType = "season" - ) - if (nrow(seasonSpline) == 0) { - return(NULL) - } - plotSeasonSpline(seasonSpline) - } - }) - - output$calendarTimeSplinePlot <- shiny::renderPlot({ - row <- selectedRow() - if (is.null(row)) { - return(NULL) - } else { - calendarTimeSpline <- getSccsSpline( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - outcomeId = row$outcomeId, - databaseId = row$databaseId, - analysisId = row$analysisId, - splineType = "calendar time" - ) - if (nrow(calendarTimeSpline) == 0) { - return(NULL) - } - plotCalendarTimeSpline(calendarTimeSpline) - } - }) - - output$controlEstimatesPlot <- shiny::renderPlot({ - row <- selectedRow() - if (is.null(row)) { - return(NULL) - } else { - controlEstimates <- getSccsControlEstimates( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - covariateId = row$covariateId, - databaseId = row$databaseId, - analysisId = row$analysisId - ) - plotControlEstimates(controlEstimates = controlEstimates) - } - }) - - } - ) -} - - - - - - diff --git a/R/sccs-results.R b/R/sccs-results.R deleted file mode 100644 index 0f5b7e54..00000000 --- a/R/sccs-results.R +++ /dev/null @@ -1,335 +0,0 @@ -sccsResultsViewer <- function(id = "sccs-results") { - ns <- shiny::NS(id) - - shiny::tabsetPanel( - type = 'hidden', - id = ns('resultPanel'), - - shiny::tabPanel( - title = "Table", - resultTableViewer(ns("resultSummaryTable")) - #) - ), - - shiny::tabPanel( - title = "Results", - shiny::actionButton( - inputId = ns('goBackCmResults'), - label = "Back To Result Summary", - shiny::icon("arrow-left"), - style="color: #fff; background-color: #337ab7; border-color: #2e6da4" - ), - sccsFullResultViewer(ns("sccsFullResults")) - ) - - ) - - - -} - - -sccsResultsServer <- function( - id, - connectionHandler, - resultDatabaseSettings = list(port = 1), - inputSelected -) { - ns <- shiny::NS(id) - - shiny::moduleServer(id, function(input, output, session) { - - shiny::observeEvent( - eventExpr = input$goBackCmResults, - { - shiny::updateTabsetPanel(session, "resultPanel", selected = "Table") - } - ) - - data <- shiny::reactive({ - - exposure <- inputSelected()$exposure - if (is.character(exposure)) { - exposureGroup <- strsplit(exposure, " ")[[1]] - targetId <- exposureGroup[[1]] - indidcationId <- exposureGroup[[2]] - } else { - targetId <- -1 - indidcationId <- -1 - } - - getSccsResults( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - exposureIds = targetId, - outcomeIds = inputSelected()$outcome, - #databaseIds = inputSelected()$database, - analysisIds = inputSelected()$analysis, - indicationIds = indidcationId - ) - }) - - resultTableOutputs <- resultTableServer( - id = "resultSummaryTable", - df = data, - colDefsInput = getSccsResultSummaryTableColDef(), - addActions = c('results') - ) - - selectedRow <- shiny::reactiveVal(value = NULL) - shiny::observeEvent(resultTableOutputs$actionCount(), { - if(resultTableOutputs$actionType() == 'results'){ - selectedRow(data()[resultTableOutputs$actionIndex()$index,]) - shiny::updateTabsetPanel(session, "resultPanel", selected = "Results") - } - }) - - sccsFullResultServer( - id = "sccsFullResults", - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - selectedRow = selectedRow, - actionCount = resultTableOutputs$actionCount - ) - - - } - ) -} - - -getSccsResultSummaryTableColDef <- function(){ - - results <- list( - - databaseId = reactable::colDef(show = F), - covariateId = reactable::colDef(show = F), - eraId = reactable::colDef(show = F), - covariateAnalysisId = reactable::colDef(show = F), - analysisId = reactable::colDef(show = F), - outcomeId = reactable::colDef(show = F), - outcomeSubjects = reactable::colDef(show = F), - outcomeEvents = reactable::colDef(show = F), - outcomeObservationPeriods = reactable::colDef(show = F), - covariateSubjects = reactable::colDef(show = F), - covariateDays = reactable::colDef(show = F), - covariateEras = reactable::colDef(show = F), - covariateOutcomes = reactable::colDef(show = F), - observedDays = reactable::colDef(show = F), - mdrr = reactable::colDef(show = F), - unblind = reactable::colDef(show = F), - - logRr = reactable::colDef(show = F), - seLogRr = reactable::colDef(show = F), - calibratedLogRr = reactable::colDef(show = F), - calibratedSeLogRr = reactable::colDef(show = F), - llr = reactable::colDef(show = F), - - description = reactable::colDef( - filterable = TRUE, - header = withTooltip( - "Analysis", - "Analysis" - ), - minWidth = 300 - ), - databaseName = reactable::colDef( - filterable = TRUE, - header = withTooltip( - "Data source", - "Data source" - )), - outcome = reactable::colDef( - filterable = TRUE, - header = withTooltip( - "Outcome", - "Outcome of interest" - ), - minWidth = 300 - ), - rr = reactable::colDef( - header = withTooltip( - "IRR", - "Incidence rate ratio (uncalibrated)" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ), - ci95Lb = reactable::colDef( - header = withTooltip( - "LB", - "Lower bound of the 95 percent confidence interval (uncalibrated)" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ), - ci95Ub = reactable::colDef( - header = withTooltip( - "UB", - "Upper bound of the 95 percent confidence interval (uncalibrated)" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ), - p = reactable::colDef( - header = withTooltip( - "P", - "Two-sided p-value (uncalibrated)" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ), - calibratedRr = reactable::colDef( - header = withTooltip( - "Cal.IRR", - "Incidence rate ratio (calibrated)" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ), - calibratedCi95Lb = reactable::colDef( - header = withTooltip( - "Cal.LB", - "Lower bound of the 95 percent confidence interval (calibrated)" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ), - calibratedCi95Ub = reactable::colDef( - header = withTooltip( - "Cal.UB", - "Upper bound of the 95 percent confidence interval (calibrated)" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ), - calibratedP = reactable::colDef( - header = withTooltip( - "Cal.P", - "Two-sided p-value (calibrated)" - ), - format = reactable::colFormat(digits = 4), - na = "-" - ) - ) - - return(results) -} - -getSccsResults <- function(connectionHandler, - resultDatabaseSettings, - exposureIds, - outcomeIds, - #databaseIds, - analysisIds, - indicationIds = NULL) { - - if (any(indicationIds == -1)) { - indicationIds <- NULL - } - - sql <- " - SELECT - - ds.cdm_source_abbreviation as database_name, - sr.database_id, - sc.covariate_id, - sc.covariate_name, - sc.era_id, - sc.covariate_analysis_id, - sr.analysis_id, - a.description, - eos.outcome_id, - cg1.cohort_name as outcome, - - sr.outcome_subjects, - sr.outcome_events, - sr.outcome_observation_periods, - sr.covariate_subjects, - sr.covariate_days, - sr.covariate_eras, - sr.covariate_outcomes, - sr.observed_days, - - case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.rr end rr, - case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.ci_95_lb end ci_95_lb, - case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.ci_95_ub end ci_95_ub, - case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.p end p, - case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.log_rr end log_rr, - case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.se_log_rr end se_log_rr, - case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.calibrated_rr end calibrated_rr, - case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.calibrated_ci_95_lb end calibrated_ci_95_lb, - case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.calibrated_ci_95_ub end calibrated_ci_95_ub, - case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.calibrated_p end calibrated_p, - case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.calibrated_log_rr end calibrated_log_rr, - case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.calibrated_se_log_rr end calibrated_se_log_rr, - - case when COALESCE(sds.unblind, 0) = 0 then NULL else sr.llr end llr, - - - sds.mdrr, - --sds.ease, - --sds.time_trend_p, - --sds.pre_exposure_p, - --sds.mdrr_diagnostic, - --sds.ease_diagnostic, - --sds.time_trend_diagnostic, - --sds.pre_exposure_diagnostic, - sds.unblind - - FROM @schema.@sccs_table_prefixresult sr - INNER JOIN - @schema.@database_table_prefix@database_table ds - ON sr.database_id = ds.database_id - INNER JOIN - @schema.@sccs_table_prefixdiagnostics_summary sds ON ( - sds.exposures_outcome_set_id = sr.exposures_outcome_set_id AND - sds.database_id = sr.database_id AND - sds.analysis_id = sr.analysis_id AND - sds.covariate_id = sr.covariate_id - ) - INNER JOIN - @schema.@sccs_table_prefixcovariate sc ON ( - sc.exposures_outcome_set_id = sr.exposures_outcome_set_id AND - sc.database_id = sr.database_id AND - sc.analysis_id = sr.analysis_id AND - sc.covariate_id = sr.covariate_id - ) - INNER JOIN @schema.@sccs_table_prefixexposures_outcome_set eos - ON - eos.exposures_outcome_set_id = sr.exposures_outcome_set_id - INNER JOIN - @schema.@sccs_table_prefixanalysis a - on a.analysis_id = sr.analysis_id - - inner join - @schema.@cg_table_prefixcohort_definition cg1 - on cg1.cohort_definition_id = eos.outcome_id - - WHERE sr.analysis_id IN (@analysis_ids) - -- AND sr.database_id IN (@database_ids) - AND eos.outcome_id IN (@outcome_ids) - AND sc.era_id IN (@exposure_ids) - {@use_indications} ? {and eos.nesting_cohort_id IN (@indication_ids)} : {and eos.nesting_cohort_id IS NULL} - " - - results <- connectionHandler$queryDb( - sql, - schema = resultDatabaseSettings$schema, - database_table_prefix = resultDatabaseSettings$databaseTablePrefix, - database_table = resultDatabaseSettings$databaseTable, - sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix, - #database_ids = paste(quoteLiterals(databaseIds), collapse = ','), - analysis_ids = paste(analysisIds, collapse = ','), - outcome_ids = paste(outcomeIds, collapse = ','), - exposure_ids = paste(exposureIds, collapse = ','), - use_indications = !is.null(indicationIds), - indication_ids = indicationIds, - snakeCaseToCamelCase = TRUE - ) - - return(results) -} - - diff --git a/man/cohortMethodDiagnosticsSummaryServer.Rd b/man/cohortMethodDiagnosticsSummaryServer.Rd deleted file mode 100644 index b9660fed..00000000 --- a/man/cohortMethodDiagnosticsSummaryServer.Rd +++ /dev/null @@ -1,28 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-diagnosticsSummary.R -\name{cohortMethodDiagnosticsSummaryServer} -\alias{cohortMethodDiagnosticsSummaryServer} -\title{The module server for rendering the PLE diagnostics summary} -\usage{ -cohortMethodDiagnosticsSummaryServer( - id, - connectionHandler, - resultDatabaseSettings, - inputSelected -) -} -\arguments{ -\item{id}{the unique reference id for the module} - -\item{connectionHandler}{the connection to the PLE results database} - -\item{resultDatabaseSettings}{a list containing the result schema and prefixes} - -\item{inputSelected}{The target id, comparator id, outcome id and analysis id selected by the user} -} -\value{ -the PLE diagnostics summary results -} -\description{ -The module server for rendering the PLE diagnostics summary -} diff --git a/man/cohortMethodDiagnosticsSummaryViewer.Rd b/man/cohortMethodDiagnosticsSummaryViewer.Rd deleted file mode 100644 index c14dcde7..00000000 --- a/man/cohortMethodDiagnosticsSummaryViewer.Rd +++ /dev/null @@ -1,17 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-diagnosticsSummary.R -\name{cohortMethodDiagnosticsSummaryViewer} -\alias{cohortMethodDiagnosticsSummaryViewer} -\title{The module viewer for rendering the PLE diagnostics results} -\usage{ -cohortMethodDiagnosticsSummaryViewer(id) -} -\arguments{ -\item{id}{the unique reference id for the module} -} -\value{ -The user interface to the cohort method diagnostics viewer -} -\description{ -The module viewer for rendering the PLE diagnostics results -} diff --git a/man/cohortMethodHelperFile.Rd b/man/cohortMethodHelperFile.Rd deleted file mode 100644 index 01ba84ca..00000000 --- a/man/cohortMethodHelperFile.Rd +++ /dev/null @@ -1,17 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-main.R -\name{cohortMethodHelperFile} -\alias{cohortMethodHelperFile} -\title{The location of the cohort method module helper file} -\usage{ -cohortMethodHelperFile() -} -\value{ -string location of the cohort method helper file -} -\description{ -The location of the cohort method module helper file -} -\details{ -Returns the location of the cohort method helper file -} diff --git a/man/cohortMethodResultSummaryServer.Rd b/man/cohortMethodResultSummaryServer.Rd deleted file mode 100644 index b32b7b21..00000000 --- a/man/cohortMethodResultSummaryServer.Rd +++ /dev/null @@ -1,28 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-resultSummary.R -\name{cohortMethodResultSummaryServer} -\alias{cohortMethodResultSummaryServer} -\title{The module server for rendering the PLE diagnostics summary} -\usage{ -cohortMethodResultSummaryServer( - id, - connectionHandler, - resultDatabaseSettings, - inputSelected -) -} -\arguments{ -\item{id}{the unique reference id for the module} - -\item{connectionHandler}{the connection to the PLE results database} - -\item{resultDatabaseSettings}{a list containing the result schema and prefixes} - -\item{inputSelected}{The target id, comparator id, outcome id and analysis id selected by the user} -} -\value{ -the PLE diagnostics summary results -} -\description{ -The module server for rendering the PLE diagnostics summary -} diff --git a/man/cohortMethodResultSummaryViewer.Rd b/man/cohortMethodResultSummaryViewer.Rd deleted file mode 100644 index d1545136..00000000 --- a/man/cohortMethodResultSummaryViewer.Rd +++ /dev/null @@ -1,17 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-resultSummary.R -\name{cohortMethodResultSummaryViewer} -\alias{cohortMethodResultSummaryViewer} -\title{The module viewer for rendering the cohort method results} -\usage{ -cohortMethodResultSummaryViewer(id) -} -\arguments{ -\item{id}{the unique reference id for the module} -} -\value{ -The user interface to the cohort method diagnostics viewer -} -\description{ -The module viewer for rendering the cohort method results -} diff --git a/man/cohortMethodServer.Rd b/man/cohortMethodServer.Rd deleted file mode 100644 index 83f734dd..00000000 --- a/man/cohortMethodServer.Rd +++ /dev/null @@ -1,21 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-main.R -\name{cohortMethodServer} -\alias{cohortMethodServer} -\title{The module server for the main cohort method module} -\usage{ -cohortMethodServer(id, connectionHandler, resultDatabaseSettings) -} -\arguments{ -\item{id}{the unique reference id for the module} - -\item{connectionHandler}{a connection to the database with the results} - -\item{resultDatabaseSettings}{a named list containing the PLE results database connection details} -} -\value{ -the PLE results viewer main module server -} -\description{ -The module server for the main cohort method module -} diff --git a/man/cohortMethodViewer.Rd b/man/cohortMethodViewer.Rd deleted file mode 100644 index ae650d1a..00000000 --- a/man/cohortMethodViewer.Rd +++ /dev/null @@ -1,17 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-main.R -\name{cohortMethodViewer} -\alias{cohortMethodViewer} -\title{The viewer of the main cohort method module} -\usage{ -cohortMethodViewer(id) -} -\arguments{ -\item{id}{the unique reference id for the module} -} -\value{ -The user interface to the cohort method results viewer -} -\description{ -The viewer of the main cohort method module -} diff --git a/man/sccsHelperFile.Rd b/man/sccsHelperFile.Rd deleted file mode 100644 index f2bc86ab..00000000 --- a/man/sccsHelperFile.Rd +++ /dev/null @@ -1,17 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/sccs-main.R -\name{sccsHelperFile} -\alias{sccsHelperFile} -\title{The location of the description module helper file} -\usage{ -sccsHelperFile() -} -\value{ -string location of the description helper file -} -\description{ -The location of the description module helper file -} -\details{ -Returns the location of the description helper file -} diff --git a/man/sccsServer.Rd b/man/sccsServer.Rd deleted file mode 100644 index d1679ce0..00000000 --- a/man/sccsServer.Rd +++ /dev/null @@ -1,24 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/sccs-main.R -\name{sccsServer} -\alias{sccsServer} -\title{The module server for exploring SCCS} -\usage{ -sccsServer(id, connectionHandler, resultDatabaseSettings = list(port = 1)) -} -\arguments{ -\item{id}{the unique reference id for the module} - -\item{connectionHandler}{a connection to the database with the results} - -\item{resultDatabaseSettings}{a list containing the prediction result schema and connection details} -} -\value{ -The server for the PatientLevelPrediction module -} -\description{ -The module server for exploring SCCS -} -\details{ -The user specifies the id for the module -} diff --git a/man/sccsView.Rd b/man/sccsView.Rd deleted file mode 100644 index 5a01ddbd..00000000 --- a/man/sccsView.Rd +++ /dev/null @@ -1,14 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/sccs-main.R -\name{sccsView} -\alias{sccsView} -\title{SCCS shiny module UI code} -\usage{ -sccsView(id = "sccs-module") -} -\arguments{ -\item{id}{id for module} -} -\description{ -Load the ui for the sccs module -} From 32796bca07c0616959ea46a5be01c8b2b61afb99 Mon Sep 17 00:00:00 2001 From: jreps Date: Tue, 2 Jul 2024 14:13:20 -0400 Subject: [PATCH 42/64] characterization test updates - updating characterization tests and fixing issues identified by tests --- R/characterization-dechallengeRechallenge.R | 12 +- R/characterization-incidence.R | 12 +- R/characterization-main.R | 9 ++ R/characterization-riskFactors.R | 13 +- R/components-data-viewer.R | 12 +- ...=> codeToCreateCharacterizationDatabase.R} | 41 +++-- extras/examples/largeTable.R | 47 ------ tests/resources/cDatabase/databaseFile.sqlite | Bin 0 -> 229376 bytes .../databaseFile.sqlite | Bin 131072 -> 0 bytes tests/testthat/setup.R | 3 +- ...test-characterization-aggregate-features.R | 33 ---- .../test-characterization-caseSeries.R | 76 ++++++++++ .../testthat/test-characterization-cohorts.R | 102 +++++++++++-- .../testthat/test-characterization-database.R | 85 +++++++++++ ...-characterization-dechallengeRechallenge.R | 37 +++-- .../test-characterization-incidence.R | 76 ++++++++-- tests/testthat/test-characterization-main.R | 143 ++++++++++++++++-- .../test-characterization-riskFactors.R | 69 +++++++++ .../test-characterization-timeToEvent.R | 39 +++-- 19 files changed, 631 insertions(+), 178 deletions(-) rename extras/{codeToCreateDescriptiveDatabase.R => codeToCreateCharacterizationDatabase.R} (78%) delete mode 100644 extras/examples/largeTable.R create mode 100644 tests/resources/cDatabase/databaseFile.sqlite delete mode 100644 tests/resources/characterizationDatabase/databaseFile.sqlite delete mode 100644 tests/testthat/test-characterization-aggregate-features.R create mode 100644 tests/testthat/test-characterization-caseSeries.R create mode 100644 tests/testthat/test-characterization-database.R create mode 100644 tests/testthat/test-characterization-riskFactors.R diff --git a/R/characterization-dechallengeRechallenge.R b/R/characterization-dechallengeRechallenge.R index d2190a96..a8b01018 100644 --- a/R/characterization-dechallengeRechallenge.R +++ b/R/characterization-dechallengeRechallenge.R @@ -466,14 +466,20 @@ isCohortUniquePeople <- function( FROM @schema.@cg_table_prefixCOHORT_COUNT cc where cc.cohort_id = @cohort_id ;" - res <- connectionHandler$queryDb( + res <- tryCatch({connectionHandler$queryDb( sql = sql, schema = resultDatabaseSettings$schema, cg_table_prefix = resultDatabaseSettings$cgTablePrefix, cohort_id = cohortId - ) + )}, error = function(e){return(NULL)} + ) - return(sum(res$cohortEntries == res$cohortSubjects) == nrow(res)) + # if table is missing the warning will not happen + if(is.null(res)){ + return(T) + }else{ + return(sum(res$cohortEntries == res$cohortSubjects) == nrow(res)) + } } plotDechalRechal <- function( diff --git a/R/characterization-incidence.R b/R/characterization-incidence.R index c8c281df..af150129 100644 --- a/R/characterization-incidence.R +++ b/R/characterization-incidence.R @@ -245,7 +245,7 @@ characterizationIncidenceServer <- function( id, connectionHandler, resultDatabaseSettings, - options, + options, # this gets overwritten in code below - why here? parents, parentIndex, # reactive outcomes, # reactive @@ -276,6 +276,7 @@ characterizationIncidenceServer <- function( sortedTars <- tarDf$tarId names(sortedTars) <- cohortIncidenceFormatTar(tarDf) + # Problematic for other apps with different data! databases <- c("IBM MDCR", "IBM MDCD", "JMDC", @@ -421,15 +422,6 @@ characterizationIncidenceServer <- function( options <- getIncidenceOptions() - optionsGlobal <- shiny::reactive({ - characterizationGetCaseSeriesOptions( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - targetId = targetId(), - outcomeId = outcomeId() - ) - }) - inputSelectedCustomPlot <- inputSelectionServer( id = "input-selection-custom-plot", inputSettingList = list( diff --git a/R/characterization-main.R b/R/characterization-main.R index 4e6d0718..f70df1a5 100644 --- a/R/characterization-main.R +++ b/R/characterization-main.R @@ -683,6 +683,15 @@ on temp.outcome_cohort_id = c.cohort_definition_id ci_lookup = ciLookup ) # fix backwards compatability +if(!'isSubset' %in% colnames(cg)){ + cg$isSubset <- NA +} +if(!'subsetParent' %in% colnames(cg)){ + cg$subsetParent <- cg$cohortDefinitionId +} +if(!'subsetDefinitionId' %in% colnames(cg)){ + cg$subsetDefinitionId <- cg$cohortDefinitionId +} cg$subsetParent[is.na(cg$isSubset)] <- cg$cohortDefinitionId cg$subsetDefinitionId[is.na(cg$isSubset)] <- cg$cohortDefinitionId cg$isSubset[is.na(cg$isSubset)] <- 0 diff --git a/R/characterization-riskFactors.R b/R/characterization-riskFactors.R index 32e4a2c0..5817058a 100644 --- a/R/characterization-riskFactors.R +++ b/R/characterization-riskFactors.R @@ -100,14 +100,17 @@ characterizationRiskFactorServer <- function( }) # save the selections - selected <- shiny::reactive({ - data.frame( - database = names(options()$databaseIds)[which(input$databaseId == options()$databaseIds)], - time_at_risk = names(options()$tarInds)[which(input$tarInd == options()$tarInds)] - )}) + selected <- shiny::reactiveVal(value = NULL) shiny::observeEvent(input$generate, { + selected( + data.frame( + database = names(options()$databaseIds)[which(input$databaseId == options()$databaseIds)], + time_at_risk = names(options()$tarInds)[which(input$tarInd == options()$tarInds)] + ) + ) + inputSelectionDfServer( id = 'inputSelected', dataFrameRow = selected, diff --git a/R/components-data-viewer.R b/R/components-data-viewer.R index eefba624..149e17f8 100644 --- a/R/components-data-viewer.R +++ b/R/components-data-viewer.R @@ -180,12 +180,8 @@ resultTableServer <- function( # find the columns that are set to show=F colNames <- names(colDefsInput) - showCol <- unlist(lapply(colDefsInput, function(x) ifelse(is.null(x$show), T, x$show))) - if(is.null(addActions)){ - showColNames <- colNames[showCol] - } else{ - showColNames <- c(colNames[showCol],'actions') - } + hideCol <- unlist(lapply(colDefsInput, function(x) ifelse(is.null(x$show), F, !x$show))) + hideColNames <- colNames[hideCol] # convert a data.frame to a reactive @@ -214,7 +210,7 @@ resultTableServer <- function( intersect(colnames(newdf()), selectedCols) } else{ # edited to restrict to colDef - show = T columns - intersect(colnames(newdf()), showColNames) + setdiff(colnames(newdf()), hideColNames) } }) @@ -265,7 +261,7 @@ resultTableServer <- function( shinyWidgets::pickerInput( inputId = session$ns('dataCols'), label = 'Select Columns to Display: ', - choices = intersect(colnames(newdf()), showColNames), # edited to only show columns show = T + choices = setdiff(colnames(newdf()), hideColNames), # edited to only show columns show = T selected = selectedColumns(), choicesOpt = list(style = rep_len("color: black;", 999)), multiple = T, diff --git a/extras/codeToCreateDescriptiveDatabase.R b/extras/codeToCreateCharacterizationDatabase.R similarity index 78% rename from extras/codeToCreateDescriptiveDatabase.R rename to extras/codeToCreateCharacterizationDatabase.R index eb84c1c7..76373a25 100644 --- a/extras/codeToCreateDescriptiveDatabase.R +++ b/extras/codeToCreateCharacterizationDatabase.R @@ -3,7 +3,7 @@ testDir <- tempdir() testDir <- '/Users/jreps/Documents/github/OhdsiShinyModules/tests/resources' -library(DescriptiveStudies) +library(Characterization) connectionDetails <- Eunomia::getEunomiaConnectionDetails() Eunomia::createCohorts(connectionDetails) @@ -20,41 +20,59 @@ covSet <- FeatureExtraction::createCovariateSettings(useDemographicsGender = T, endDays = -1 ) -descSet <- DescriptiveStudies::createCharacterizationSettings( - timeToEventSettings = DescriptiveStudies::createTimeToEventSettings( +charSet <- Characterization::createCharacterizationSettings( + timeToEventSettings = Characterization::createTimeToEventSettings( targetIds = targetIds, outcomeIds = outcomeIds ) , - dechallengeRechallengeSettings = DescriptiveStudies::createDechallengeRechallengeSettings( + dechallengeRechallengeSettings = Characterization::createDechallengeRechallengeSettings( targetIds = targetIds, outcomeIds = outcomeIds ), - aggregateCovariateSettings = DescriptiveStudies::createAggregateCovariateSettings( - targetIds = targetIds, + aggregateCovariateSettings = Characterization::createAggregateCovariateSettings( + targetIds = targetIds, minPriorObservation = 365, outcomeWashoutDays = 90, outcomeIds = outcomeIds, riskWindowStart = 1, riskWindowEnd = 365, covariateSettings = covSet ) ) -DescriptiveStudies::runCharacterizationAnalyses( +Characterization::runCharacterizationAnalyses( connectionDetails = connectionDetails, targetDatabaseSchema = "main", targetTable = "cohort", outcomeDatabaseSchema = "main", outcomeTable = "cohort", cdmDatabaseSchema = "main", - characterizationSettings = descSet, - saveDirectory = file.path(testDir,'descDatabase'), + characterizationSettings = charSet, + saveDirectory = file.path(testDir,'charDatabase'), databaseId = 'eunomia', tablePrefix = 'c_' ) +serverDesc <- "tests/resources/charDatabase/databaseFile.sqlite" +connectionDetailsDesc <- DatabaseConnector::createConnectionDetails( + dbms = 'sqlite', + server = serverDesc +) + +Characterization::createCharacterizationTables( + connectionDetails = connectionDetailsDesc, + resultSchema = 'main', + createTables = T + ) + +Characterization::insertResultsToDatabase( + connectionDetails = connectionDetailsDesc, + schema = 'main', + resultsFolder = file.path(testDir,'charDatabase', 'results'), + tablePrefix = 'c_' + ) if(F){ # add in rhe database_meta_data and cohort_definitions tables -serverDesc <- "tests/resources/descDatabase/databaseFile.sqlite" +serverDesc <- "tests/resources/charDatabase/databaseFile.sqlite" connectionDetailsDesc <- DatabaseConnector::createConnectionDetails( dbms = 'sqlite', server = serverDesc @@ -78,6 +96,9 @@ DatabaseConnector::insertTable( description = rep('',4), json = rep('{}', 4), sqlCommand = rep('',4) + #,isSubset = rep(0, 4) + #,subsetParent = rep(NULL, 4) + #,subsetDefinitionId = rep(NULL, 4) ), createTable = T, dropTableIfExists = T, camelCaseToSnakeCase = T diff --git a/extras/examples/largeTable.R b/extras/examples/largeTable.R deleted file mode 100644 index 21fb5639..00000000 --- a/extras/examples/largeTable.R +++ /dev/null @@ -1,47 +0,0 @@ -# -# This is a Shiny web application. You can run the application by clicking -# the 'Run App' button above. -# -# Find out more about building applications with Shiny here: -# -# http://shiny.rstudio.com/ -# -library(OhdsiShinyModules) -library(shiny) - -if (FALSE) - RSQLite::rsqliteVersion() - -ui <- fluidPage( - - # Application title - titlePanel("Big table example"), - largeTableView("tblView") - -) -###--- Fill in connection details with a real db ---### -connectionDetails <- DatabaseConnector::createConnectionDetails(dbms = "sqlite", server = ":memory:") -ch <- ResultModelManager::ConnectionHandler$new(connectionDetails) -# 1 million random rows -bigData <- data.frame(row_id = 1:1e6, value = stats::runif(1e6)) -DatabaseConnector::insertTable(ch$getConnection(), data = bigData, tableName = "big_table") - -server <- function(input, output) { - - baseQuery <- "SELECT * FROM main.big_table WHERE row_id >= @min_row" - countQuery <- "SELECT count(*) FROM main.big_table WHERE row_id >= @min_row" - - ldt <- createLargeSqlQueryDt(connectionHandler = connectionHandler, - baseQuery = baseQuery, - countQuery = countQuery) - - largeTableServer(id = "tblView", - ldt = ldt, - inputParams = reactive(list(min_row = 1)), - columns = list( - "rowId" = reactable::colDef(name = "row id") - )) -} - -# Run the application -shinyApp(ui = ui, server = server) diff --git a/tests/resources/cDatabase/databaseFile.sqlite b/tests/resources/cDatabase/databaseFile.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..796a5d3a80724057c277c4419c66d72307bdcfc4 GIT binary patch literal 229376 zcmeEv2VfM()&K7GzJMeI2+#@9C4mG;2cjHmfM^0qbmQZ6I!R})$X5ViFkakyjguHB zcCceRnAmZ5?AUR4>@UT}ag&pexW~j5_Y(X6X76ricJEHySV&I(-|G7!qnY{5ynXZL z?YuIxEvuLNqF#GPC>(G{?K7Dn49hYL?RJJ?M#KMR!~c>$L*XBqrI~ENI zf4e*`chK$ciTEO}u(!iiA^qFBcfL`dUslGRQ5JQ#`Mn;OC)5=RM_ujSsN3g{$p1Fg zH8<3>HrQKhYL_?I<+b+7COiB@ywRvH*y-}M+kL^PePvUtedU_v%S(mIb~g;&=;GtS9~nWy19gYJuEdnL$HFpd<1Ipws4FQ1sco_mDv*+y23`K*qRdi~oKYkn z$$uNquG8xColf?myo6-5dttTs{oY`w7uK@)Zx1Y1@ei^>CzG2D%@SfnECbBq)P+fQ z5{ZVoT`;?7rv2&GIzg8gn#2SSC+0X!d+F+H_jdS#J|sa%SG4&$Q!WTVuvB&(5-XVCG)(@LaPT9qQCrS?8#QmWL_$sjEK)jD0i*O__gla!H9 z2bv&5mHylXYJGlVBYWxggkm6Zh%16zf+7j~yzm<7t5zdZ5q-5y=!vqja15=;_|p?y z{{L8O#I=EItG6eO){4a1PV&Nv5|vbfGla;A8V8g{n>U=M6LPM_*74UKu-NMgb#%as zAzL7N@nsK7YSFBSOE%7iHd30zhsrog+ScEDm}9em954A)SrM0PoDFT?M@{tpD!cLy#pKNwZ?PR4C3_5X>MwcII%&Zehuw0*^EmB|g z+B1q-eSS#^d-m>xc8vPKT8M^R-fiAs)Z>!;sgmhGNhRIJsE-%L@!Gs387VPvW@NIR z(zc$J+L~lf8U+JW9%o&;t&+g6h{x^623IOQnb$xcJS(*)=}-4!#kGhR;+jZ85{2ZG zK^yd^Kr4vge3dSLbxCFsln4TnIkEsOaV{5r+04i`S92f0Z)P0W=AUvO*lx4+*lKNN z>vPt9R*$vB^0DQ9%juS7mK^gd=IhK`%`;73n;tctZ)!0W7+*KuY>XP`88wDK8m=&$ zU>L7|SAVB|m%c%7)jhBKna-;#(|)RbKzpWkg*H#~cg-&~0Zpa)-|ENJ7pm8)$Ew~^ z-J;sAa;o&~U)UeBE_M?00do%`<`_R!i;M+EHs8Urh2B^&6!5v#9lmfRTGIi0dAr{o zi6-_vc2J|sb)Yir6=h(pRW(rHmT57ro&vX2gK>2fxFrOxmIAj}kH@Q_z%3%4Zy^P) z!HCCmQsC>Z_!{RTI-Uivl-CjrlT@0ymq$&7i6u5E%HGi1CUja1#lB z+9_}oh?i|41+ExBU**^YE*o(fhs9+K#c)N$^o^##*$HtepuiR4$EzAefg4Lq-$)AF z7~=UxP~b)r)0anLz0VijpAa7H`}l^Tl2!_2HwQw*mk9#2Jq(-Al}D;${BcD@OI zkKxVmd-Ng|{8n?z;WtyvJD0N zQ2S5qZQ7mMI;}bQpg_L53oWMzQr`Kuq7g_js~_^gw@i(7KyML8d!q} zTSx<|7hz5sSe*!4Km)54Ve@HVH6m;t4Q!zZn@a=3K7(o+*aC61IW(~OB5XDdY@P^n z(7@)3uqql@wFs-Efz1(NvuI$mMc7Olm_vlkpn+A1unHPjr3fphfz1+O(`jHcMc6bN z*bEU?Mgyx5VWl*%auHTS1Dh_wrqaNsiLfa&Fzh0jOam(wN1H?gD-mH6X<$=D*aRBb z6cIL_1~yrQ71O{biLh}ru!$n9hz2%6gxP6e#UiYb1~yKFjirGViLfy=Fcfx;$52Mo zzzRiJ0S#=d2pdHM8zaI-(!fTGun{z{0uh!^0~;m6hSR`Cim*Hy*a#7pO9RUnVL3Fg z;Ua7p4J=QD4W)tQim)LxupAM_(ZGg@FdGeQs0g#tz=nu03k{4DVP+bbO@x_fVAu;_ zq=8{CfPn^P7Kzl;z;IYjM+3t_PHmPjuvm*A633#rbfGF?k81h|Oyk!Ka|eJ6AsiP6 zCyiNEA7E_W>;Wv*D}b=WtjNqBf_^DK3I`MpC>&5Ypm0FpfWiTV0}2Ne4k#Q@IG}Jq z;lTf|95A5=Q|$l$U#C}jE`&5YAaDT1|5@$; z!yVx6;x1O0qHsXrfWiTV0}2Ne4k#Q@IG}Jq;ef&cg#!u)6b=jm2ga-O;0OTAs#J#f zPkc;tmY|hIRYp_`|1lbjdf_K=%wX(TwaKJWtDGn zAruZM98fr*a6sXJ!U2T?3I`MpC>&5Ypm0FpfWm=3Ind0)MYUGr7-PO6$6&O=-S_Yt z{xA8X*C(6-@vjotD}?WRzyh1M_L^U~UC$&xyKC3kjeK#@`cKgRw+dJI;h&TQ@ zIkC9KdveSh^mt{}_1-|JGwkl}@_8bQVbkIbLxX5ImV}e_HJu2ZxpHwh6zk61qS-Bs zo&nzw?F#xlzG#oMgSt?#UHF)%(0N1Hy*w1`Z1si%(q{GHSSM7rz#c4`zJ))56Pnb+ z7i6J>vYAzt2{r}1?Y>w5bu4L6F}pm`06sk%j;7SlOjZNylATs05Wb+tA8Yrv*Cjua z3(w;5c1IiA(b$_dCz`q2+w0+bi_n2P7>%@s8sji%LQbQ1$M@>2Ar6yumO`1Fq-Zqk z^1%0;5TWD5&-b>(KhPW*m!upu>xczWBlzlaeOtY^!yWTS#Rsm3k2a43>D+DF%m&Ug zvK$K{e9mSSYn-5(pi(6->r#X`zJe7Yj`KmjBK~897-?Ejp^|G#EKH|m$EE17`dAn~ zbPgRPb>TQP^+^qvTDvM7@_6AZ(%vSICl(GPHJ;k2-n-4`@irtr$Cz5b!s|v~FAl)h z3{xwc@OQUUE7$rWK3LR(@~R8P(&1AyN*Y}^PCl<`G~Kvt^ju0uX#`|k3Pq%j8wZ~g zKBk6?H%jQYI{4tc+XJ7u^X(MAMqOPU*LcEA$`syiHn1`N^+CJf3t$7%zt{je|F7cS zVz{@skA>H{@=M`>!U2T?3I`MpC>&5Ypm0FpfWiTV0}2Ne4k#S>FXey*K4K_-Q^2BO z3yevRCyM{)+7>X}yWC6M1Kjo8#oSKrM6RBj&W*BtYkR}?tnC5YuWVP?PPKK}TA`ux zqi{gsfWiTV0}2Ne4k#Q@IG}Jq;ef&cg#-TwIgp#H1H;lVGLZwOZgqzt7(FaUD9yvA zet+&TNlQ(08{O{p26Ie8T@J2m3by7L<%Q7I2!phL74Baz?O&)# z_OFw6rBb8*wemvfKVJidMohoh{YbS?A(D?O61@*o2~{HXsPkd0tPGl?_azwo{C`l$l}A=Mpm0FpfWiTV z0}2Ne4k#Q@IG}Jq;lTej4h+`|wtg~>oG|utbA{qOqS)`xk+n^j`@>|#344EN9&`cr zezJ?W!9PUSv0(9YvO>Y+x8(?UkpyJ(TSw^yo1ewzJ6OAd(Qg?oR25095_YpWPpHfx zD#3C#rItc(M)?@n@HfcEAT58ryf?x0*QJ)i7}}9Q57_=9J)-fiDG+M#V-VKAI#;N} zPl3#TRZhH6jQt}3ivQ=C?`OEjxC^n4SY5Rb`%v6+!Hk>Fx(WW#3-@-G=GI&?sf( zC>pXybomDP_lEMJ05DdN0J1)Q7YJFhVb%~dgo8wA$p+#L9%SK$IUITtXCd(<%%PMM z@yR}Fw=_>w?)i^l;iD0!G;P;Dn#{E z%5iz3V8e7Xf>e$qM^SA~cLG0Nw!vXS0B0cyV86_Gu3xO!P+~;DiaZH$f9iDssANN> z0X3d08HMQ;c`ChNKrG%+t_N5`q?0`BTc&5}5F#$qNyM>*x?GFMiwkuU)wfiaYtT4x zsZJvL7V8Q%AQEDoM3C~BMy@MWXpp#ECm~q~b~THhCN9`XShkXl;{SQJTN&HCwp(ov z+Wv0)iZj~DPh!d=Tf%>9G=klVxkh6{3=x#iqkZYl?oru--zP&lA)K;eMG0fhq! z2NVt{98fr*a6sXJ!hr$ifK3a*@MNBVDo^sKI+uf5RkD`7GDlLa8D@oQW3qavq*6OX zf@KbIL$n2~*q2IujZIcC!743KJ!O#94-yQ)@Ssry75 z(N;0vF=x!R=<=JUu#68be62xZFXvzbE30xWe8JSB3O%>)!cB zeSTRPdq!E*-RAdtT=ClnUG3he+vktO|7IA&IQ2{4dkg^YJLVYSXmU(bU2{WCYlFSD zrgnLQ-J>~yt;;VdVb5@g6mD~eeQtP4cpyX|@#hdJR$6JFEL<5HiQi1?^0nK2!Ki&@ zQ>%UDn&r#m_tdt-EwpX!h!@pDzaF^BadJg@`4m|*JSenl^L3_ngj)pN0k6HaVLc2Z z8A_a&w1jx#S7;(S;{C_zTh-jSqNaI+eObc>`(%RHQagUEQac{p*FMEGWu`%wzqlx~ zge0I5Bpu0r8&7Z3>+_3>*t59=-;*`CjX}okWQze|bfR~mzSdHk9U&z_J(V_8*Xlnfh59}&$u@1i)?jmhvgL7?h@|k#8twdu);iW z;WL(($|><~Ng!O=jA8IcMv(A8-C?gQDxB1Ewa3E3C88J|ZxM<_T}irA+eqXj$rN9E zshyA+kPPk%Hb39#WG~7~Ome#yMBeZB20PL6694Ui#VP(lR_J6RkfB*ZB8b5;w^COZ z*-0cC>UP0IdBfY>e#8UWDk9r@p-D_&mTPPY7vTghAr5fFbde6u`@)%@=fsdqj9e0v+&0 zB5*yiE8ukpBd(p^a44mTL=*`Lkg6>45d@9pH0knN$}(##>01ivEoq54tM^*QcaE&L z<2a9rMV+8FKABP-l%^_C6z%EuV(upAPr}{|E4@@cY-v(+h@+JfgMeZ#72xZ{vfUSW`&_WTo;~4IvCpAJ!twy#&`syjc>9VqL3`uL8Gla|#kDu~RCN;tL z)f$45Porg|{A>4i_=3WR2Jq`yrj}&<%>vQw4a1wwwbd&uL|J!{SldZnPZSTA;0&RZ zy@|`bUBOtO%^Obh5F~@d*2(1$+o@1T2gpyhz_^mg7MA2kR>UP6XG0q)P2xjk93^e* z?>)@1SwN1Le5$O7OE%7iHi-rx77M)W3HgvLiBhtLd~FH~pw!-nyrl0Q{4{U@oU+ZgpRE$OY0BwG^7T{2C5BP1`I87ay(K}oWIN$Xju ztx5KzQ7|y&an=dDZkg^A_!aTE{rKgVN>AoB&-?MeF6@dwwUrxVvi5|St+pA6cd zKLuJr1m~-C`KwDZi=adhkjzO6)ZnKvAYYBu@HAs&ix}fGw$Uc5?h(VK>UVSzwup1t ze#woter+CO(#Cx{rseVf{@}lX;$UNO<|hyM;4?x|AH42ncwFKiBP;WC`PspMSt4x2 znGHF@YCNwdu^JPz=|P{LNVqUys~7)sxNJ2_+QuCOgbM9zzabT@!SSTjQbDHAZ6uC~*=s((!!A=}lOBsA>u%KPY$QNWr_MSi!7Oz{mW<^7D zV_ia~KyK0$ySI76Zg6s>se(C!?`ws@28OTX#CN;(9`Oj0CrOv_oF;>z!rXL7!+?>(isGQofmqCJv=p$wyb2JH^}MZ@0zAn)jz zn?~u81N*#&gleg8s9RFAe0jsl#SN}z{BMsdLxt3Vy(MG2ErJf(QeOjMshXAsS7ZGa zF$%GT?7OA4X_c#SWotw8+M4BC>=4TmLQ9f14N$eFrnRwYrE6W|%KD~tM7!3S=EV)I zuDYfrP0g)9^`gd=jY3N_qS#y0n%26e6%EH~2KvF(uzpoj%bMl}S3`463(*CtTh-9q z(zLQA-ll;Z0M*vPgOUjHF>6{|8&<4pCHf<47u7UodiItzb#)CbWVggLxl+3&Yh~S% zRjJ*sszdC<(vaG8^Cf7C??>fLLt*%it{oJH_|mt>f6x?l%w??m76wNDlgh$PRABoFCKu|seYB18~)>=C}9 zYmasTq_fLjR)NYQ_ORCvo9t~~do%==AmlJq+t>Qw+r)MVEXCkslD-IYNaefD$>)zk z1nt$T)FMGF^X5at27#cOV5cwC-V^DD@7(&__D}~Hb`VnYbTNl&9y9Qkkpini1ZB*3 zv7fy*2$Zb~`Fpw%L7otNwHV0pKF#Y#2;_Jr++%5>H?WMDF%^CkglNDvz0lt@WebmXSl$j-6UO~-}H3bAaH0o9Ii`5^kLRI zLSe5v9AFMPJFen~<_T2wNT@pJ$-xkCDOJ%fUnhvR^TaN`AXk_{D@oI5{+>gFz^O&Z z;DN8u+9CSokL`$C;=r@*;6{l8b$QqFxj6#I_DHB(eZ&4ipsqFSjs<`wkG(AnvGs(Q z0a><3_=&>=rWKQ9eR{&pPY(iF4G~Wl1Z6#4pr$}2`0PmgqR4#|aTBQQfH)#}UYSD+ zo-y-7h6?=KE+KT%SYeINUHI~q7Y;dUOwGm zZ}))K7hXRLe*Yprf)nV{ldO7w&-s@P0$p{G3l@Vs3rKuQC^J|Eg48jG=G$iTDjSfd z;a!-tQB~XT8wA2?g5H47%^cF*^(sH!iip@t$o%lLU#uPkA_(qm_eHzx!I0e_ibUe? z#9+kZ1E*=w8-ZPf_OVNOgGJ!gR?Ms66^jQ$!!|{cEZGCdc?hK3(#2cM0x1zp3deU1 zhK`8Kd0QC7sw*zw>Mu(8T$3gR!)%S z)gNyh1cKK1&4IOt29=t`CXTImh}WqEYJ4hH(yn8luNjQjS3@KOuld9~en%0X%OXO+z{G?c zoH`&H5G?XCJ_5g|@~h$Z6y5>9C-VjHd(v+BHE}cinotA3#uupIH_N>PznN0*9aXt% z4BSERIr|3tEc+mPGy4&;{>AMw=W;$X%dIu;;_6KAbLFO23@;hZ;l^+#(;uwQ86LNNZo11_Vc23} zbr0&tSjQSxSj~oN%NK@8x@RqK8o(Z~9MZq9yIF6t{9gZx<)Ho#mY?eHvYe&gulw8* z(O+!YqTi)^!?Hr}vsCNXS|;i1EV=q}?Rc$C^M&R$%^x*)Yp&Itr-^D#)GX1=(2UmT z)E}yQ)sLxfQU65sPupvzYqbxm_i9(^uCzXAh^YPAo3xi1J9WJESBBr%{$x7ecCTrh z?K+cN=eJ#CTCQGe>oGZu&AN5AcGEaplgVnm!Z=^MOINEa)eYBH+p3LU7$@r(!B6ue;_ehG&FJHNnxm#KUZwlrvY0+J`4rA_=7J&+9?vNBAb;{f> zDMAX3xlLLGDuwxtwCGvOSIn)_B3SCoEs`R%-k4uYi$L<3gE?>(MSN@(bAeCK+?)qx z+T==AF)aJQlV!{SS*hvK=RG~luVkgh-LGtain%GJ)bsuv=0;g5bJr`DUobbwN{y!) z&U=~pWoqg6)y(y&rJkpl>rzWs)iC>IrOapE&PL`J^3spae1m1Km6v|-_P1X$*T_rn zVt?{0=I8R#J43I(%KR*)wDOHP%+)ESxwS7d`%+5H7r2?L7Ms1m>;E-y1$ykT#-`hDC%J@Pbr=849i@WQd<7fNaoU% z(y_m9WG<1H-u`x8BXe;|>Fb@ZG8d(k9v;Rs7p9c{{lQ-`7syM$+SOdaoG&l^@WN&{ zbDpf!7&ynZnmJci%6u{XhA)|O!1&QApg~xTI8dE>+uohhqSC@UdwZlswXOMI z?T{9&8g=g8?b4!^xl`M=NsH>NyN<-9MOAxlxGyR#>UwiXI3g|T9NFC#mKJpsZh7Qn zY0;*KgI9G+i<-9PheOh$m4AN!wVhwHx6SMJu96pm-~6>Ec_BEhPg%v% zY1_LzrEv8P2bReT!Bcr?X-eUwvoAie9Kcx?>TLBXafX+eIZQaTQ(&_B}Cyw&chQQLJNF zN+HA*hNcvPXMc#i5V_SkDUXmt+a@hS?q#d22wb@qX%TX%nq@^`zL{i2V7?ipMaZjX zkQISprk55W!%QbFLWY@ERs@EbMpgt?n3^bxTbi=fB0M6B|EswVP=i?z|NoTx0KNe5 zlW#H4kYn)3j@YLO%)JxO_s`ph7tM;jasv1=;`!;(Ydj;FcR1~)O3&k0CmO4a5}IpabH;kaE?1@R z679tF&MPX6ZLOQX78^IEZ;bY6sf|~rZ;W`XQuzbw&M#s&?%LN} zIey8K42|JkoYM2O#n6~#bF_q<3EvrI1Z7+8eDJ&NBZrPPCp(|EC{ueu<(};P^Ne}# zlK78U&4vp>JAhxg1*dE0@3!T5Y^u!Bps^6PzUs@M$Pp%Vze)Rgc zIDdNM64jULd&JhY8Cs*Af!=xHdw<<ccw?8y-$} zUN$RJbJ%V%?>P@2*lqq``JQC+sWaovRq_>DT$1O!A?&KtUHo>kZOM#8TRA0#buJ;DZAqOX zd`Bp*Q-(SpzQDsh_E=uB?`hLAwHNl4YUfX$sJLmwy(fz8%QClz{4%}s;M;TVI(_3X zv3+Ug_Mn4uosa!;O8t|s*v0lG8QY_Mp~`v58TMDV{rh#X{nU)@kEsNpk1K^H0O&Ce9-gs(NeMB(HYtnY)Yk} zAVb^yh|T%Cx99w0+x8cd{g#b_wy+B&S2Eg##uxGw=L44zl?4S8eqX@NA2(RL%14D?ZfG>rvw z*Llr-kH0Zt1CyNa67)fVG>zk%4cVSv_=rHd#$d3fl7T)Vkft$GPN}Uy*D*1$`+1 zT9dj7^<7+Ib6zjC%BBjR2!N(CGGLd%J7281=7bvyk0iUDioOkix|OwsO~!4`!~cBu zoR-hNNVc8ArY9jEB?Zjnd*F9DKN)^cUxVWRD((^Z%~W!)agV4^Q+KGBt7oW3sJ>DC zL-m;ICe`_1g|Al4;@*L;0{oWy1$QnF5AmKXbH0WEiLR>>`9i{>`KcRc7{b|e%t&<^R4E~%rWzN^IY>- zv)1&k={eJVrfW=Rn0%&{rkSP@#(x`MGd^iNXuQ<8&A7?9&^WO2ioH zPk{m5&@~)Bb@o>Bm zjR!BK@F{6);0@HaGi?oWH1(vdK_aswZ4DBb?P+UjAsDwUZ4DBZSlSvSD$%qxEKGPL zl?%y@$00BpP>%LlDB54Ly~h+ zhB_oUz6^CJ0M(VD4kc-HW~f7{8XcMHAYsFssSeUM+B4Nb@`fiv9ZKP7%Tx!69PUhY zkj}9sQynCAxH8p2y2go_>L6)jbEZ02Z6{=^g9MIE8R}3P$Hq)`kj$|mQynC4tWRAH z@hxX~UD_J7y4R+yL92UB+8VUFThrE{)!mY|26=;<)7OCOcXiqt&Wu!I^iRU$*CepGx+tno$nXI=U#WOdZ0uR=CPP5LTiQ7lYfh3p4s`YL2CEJ$C4 zY=imftB@ryFMSo-_s>mVg?9PX>8sG5eolre@Gs0xUxoJTjto_>JFiM#h1>*{8LD98 zJ!?dKzVIF0!h98%%uHWVST`emMZu0duWFlbczIzfSr z%v1-WF(N}9a@*u*s6&D=JVPCF$mFF}!pQrQo3;jtOitPwBr(I%)*yiynzjbX%aF7+ zNa1m5YmmOPrL95g&YHFcX*)PZEtn8k!6U;4iKRJh4bpX{^flnDFs7|R;%Z1=1JbHb zTZ4pEm%avMRhu8D8mqauFF_-ggLOIsO|Zl!)gW_4un}K?`iivO3rw*>wbiz}NbLY4BPa6sXJ!U2T?3I`MpC>&5Ypm0FpfWiTV1DQBb zZ5?VXU=1TxDi)H>z%moR=%#KJzPqG8!XCCyUsxA=>Gb<%)h{%yyz?D?_RdMg$%b>Lwdjp=AkLiGkTZ1cq@O#bxIg{DjY>3U{qxd5GM9Ex&ZA!KMU>J3JN z(P&HtM+Ki;B6x@n__Aj^kBt4!_mb)T@dg0|aa3rIAS4LI6H)8KGxUkB*_5sYpAFG< zyYrntM}G9>v+oq^5Kpe@&DN8dbdKwthgOHv{_fLO!-9poh&L{4@`$tIJN=zWb zR@*+t_Kxi@wtcp{xSv6se;4QGp5dI_c&5Ypm0FpfWiTV0}2Ne z4k#Q@IG}J~;5Yz5Ya?=^B(MAteJ3c!FR2kdBPhl%sS*7iW=PZkKLhS9>D4fyd}rjm zNDiZt`z(wpnIuAV9r*?fDPXx*LZ1Q_eGodk5ZWh3mU$kusbTwsV?>jZb|Mh1KB7*k zNO%rZ!xMP~#$-xe+%bUS|7M$=;U3}6jHP&lA)K;eMG0fhq!2mX(6V7z&VkjWrCu1aMv7!vkl!sccJrbVVj<4mYkUOZMT zYvuRH+l)6#dV&rUJtgdVHozWc505iQdXlt4J)t(^^^%@2O$lqC4X78W7mU+MdXlt4 zJ)t(m+95*DL(0>|y#s7OZvY!#gBqoIxK=mn2Q`_mhOy9*f8zwz1j+LwE1M0#$05)M zk>eliW&@JH;DP3<2sq0Uq#hH#Yu7v$$V)f&F|n+N^&tD7jHP&lA);J=FllUVf{;|gDA{9E9zin49xu9>cK7kpSg>~(GP zhSB$ar$tWoqx^rCdx?SnSAG-@C>&5Ypm0FpfWiTV0}2Ne4k#Q@IG}Jq;ef({|1u6t zqO$+LVYqMp%N|f6SK)xd0fhq!2NVt{98fr*a6sXJ!U2T?3I`MpC>+R&18TL=7|;Lz zoZ&vt3ZgVpIG}Jq;ef&cg#!u)6b>jHP&lA)K;eMG0fhq!2mX6Fpl4P2<@ zEB60?&(tZDDjZNapm0FpfWiTV0}2Ne4k#Q@IG}Jq;ef({tT|v%=Nkq4AI1L{G50Xs zAGk}n^;{8r2k61?qu~m}35N0dclCGbcj+7SR^9WupXt21GVQ0@2efBuS7`Gzf7kp{ z6VOzu|E+#peW7}-daUX#)h(*+DyK@%{)PQ9>tZJ{9{@4O{;667AFE{Z9V}azyhXCZ z7mh@0I-=gN-S3V>?NQ-Nn|5!oeYvh13ME!ALL9R+R)fvcs! zE!N}lYAA4vi04~Kfom}0@thR6dOTj`f&|W(#r)Ob;pS5eSBr8ACB#5ixzEDR6c|TnZ>~ zh4}HRMp59#64N)50yldyC~*12 zau`N|8&1dz`ha}4d-6PjFGDDBxx{!J1ulnpJ{tvY7=g1=;D!=!6$=G!2r-_S0>=@2 zF;U=bn9fRL0+)?ivWjY{(m(;Th_EU>1(jw(s&y1N6S0c46gVTEg-Q*@<6&l2sVRoj z6OX5&!08AaOM%nk#fR+w2IlUh{cpGZ)Ak$N4%ILb`&9Qk-RZie zx}n;awbyDpwbL}8YJR6VU9(J+qwZDzLfxgFrutNMziO|lQN^*(v-{XKb~0H1cOTpM zXP7D;)&`4ojVP-sb!G>^DlBz8ERO7fO(M|2!|D)#qQ{}H5myp3!@~l}e#jNXkg!Cu zA96V!(!s+b$sW0kM8Y!39=Q|?QWXyiCHu#06d$vShozD|aESaqOW1))Bx{X@Ir(AsxGEfHfFcwJQP4YHckPnNxKN4Q_#mbL^xc zv>FrY=%E45A%Ht*fU^nUb{Zhz8E|Z)0ag+t#%O>uF|aC{0A@9dGw^IgXa=mn13JPq zz;e9rcbrTEoKB3`O#_@p07EpuG6EQ+0hZ!bTop(Fvzm<(aW<;_G`J}u&ast-(1`@0 zC(#TzK^(BkM}sRCagHt;LhZy?B7k4Nyx^+CpJq zZ6I*X6u9+R+f=Qlz^%i$%2f%RC^UT-Mr%cxscNDaZVlmVSV@6vCD^ip0@s2?v}!p8 zu9={783k@N5#U@(fm?+Iw5pK;*F-$u5(*q?WiF<`t-#}<{Qnx2j^Uo>F6U0*CfMG$ z-D5k=)@U1MeZ_jcHDIl>d}sNCn^%%$kxK*`-eU81F^|I5L&zXm^@c|^;u=gTAKp}hVJOFH3FHQz9vw z#7P6I6JZNzV6`G_J`Jo!gw3OYVe@$|4GiZDRMWt)(LIL-HeYE zJPmBJI9f3cY?25YM+2KE!is2M*d1c0ffb9R71F@QiLkLWup$vQh6ZLAVWVkag(9qg z1}5wkgjdHX8rT?dw2?Hh(IRXF4Xi+f<EX}LNY81?~ZX<#@7Ktlt=o&z-v3_Cbf$=upP@Gs~e=WO@ z(P-3vQeUZdsVA#GQr)LIoqLMAjN8PGx4mb(+qTEH#5UC0YrRgjl-+0DYMp8M+VZI7 zd`pX^!2G)TW^=?m*Q_@EkLhyLCR4HTU&cF(r>KS)>x^c@bB28ekD)~WvHpJj>H1~* z9NjCr>vUUnGqqo9AJv|(ZP6C6FKAxZ+^mUc=CbS9vCNyyL0>p&+b91EdCCy3Wf=9v zf~}vlQu~U)w~E5TTm)9C5bZ6@2H1ju7g7ONW8ei;K%AbyoKFA~IpnJ1B-MR5^4I_x zd}dXpV3vOfdE~+ai}rk9oFWbSe^DVxi~a~uE@Xd+WA;JrMuFP658)jed0#2=cnJ+m z@%*G5ib;5Wz>8B$!^uVB1k}VACE`sb`6B6aM(8xq{3n6K!6H|&3r!<4qM(^sc_izK8Xs4ZEqhH4x7VWR5)x8cT(Z7 zt=U0^!^WnU3Wu%Db}Ae;H$7B1Y&f=2;jrcCrov&XB))r zSqlwpy$EZjfvpo^t7%|3>tGcPY>hZt6AcU-f-7lY*bH1j18WwETuuYSw&OAy7`7aj z(!iQTA{$Zue?9XHhI^8`h->8vY_HjFvW0Aw)~~G(ThF$xu;y4^wp?rJw3L}YHviVV z$J}5xo1QiO*t8ie{dbJF8e_(}M%M78;X*@;VWj@B{sz4tBL83L9@L!y+5bbdFKDmU zwrMA8-q+lz*{NBm(W(EazD&Iy&i=olI-u%SRk7c&kFe*kO>7?X3J@ayaqy6tA{et` z;=QI1%d!?PR0j{aDcK`y@KSZ~ke!k}av@e?RXpUU2uLygrY~x77}vo=f=c#7F2ETa z4jxievPTlfza2azsbr5N4uCs&NK?rkNgM%p@Q|pIJ+hjd&P6oHIaq@__y!u}Y!X>d zgLL5hCI??fgCq`vJNQ}}WF;xKH8e=#K)8d4`yaBOm6;@m;0B27kuylSg*za!M^=!M z0M|fdk1WTYTn7&qL1d4dj&~Uj9Ys;?%f-Y zB{WFl^tgkcN`oZMk30A&G{^!R^>Xl&X^^8x4o#v#jwDszL>lA>^0hL721%SGckttB zki$teR7``+!%M}%kE226l5$%_gUlhRg&QQYU)aOQG2sr0?2$w9PSe4|EfU!yhmh35 zMH1N~Ig(nqN+Nrt4NG4Y50^;@$gC6?jw@I3qiBHS8XHMNtC?J5BWRE&{FDwpp9V>s zGI#L9X^;kz+B_Php4?u*#S+=irjA@=aJ5ACNG+DVDjqJEkjg<{Q6ucmaPV-ugmlQh zfa~#NR`GDZMD{~spGFnW(Ezb~!ok~UXl+%A=6Drvr5O_YD5`i14G_B6FSL;XU4(o2v z1$46@lK+VITpj3?tmXciGGbqQfJGSi92Kwu0}oLF>oM?I zDqtN3K0^h>iCD~EsDL;Vi}^DZ5T{}>f1(27=m_&iDj-hcV*ZB;h!46kPg4Q$Q8(r( zDj+`W#{7W_m`FHFc%^ZYXkTksnkD*C(z`5XZ1%M_$Xw6&QjmR(x)F(L;=t&;DbLs! z5}Q=a#Z*8X^Zjp4{*47g0iU}s=HMVMa~>6Qa1JeVE)@`G(K6>y0heQCbv6}n83vw3 z1zd`OXHo$hG4Kp3;1UcxoeD_2t@cs@iMN#)?h#Ghz9ffuTb+jD|HTG|;hx|w;F`G+ zw*R$VZ`*3CuzqfRzkcqtS0H zH+*8a*Kmqq0d%AMC>&5Ypm0FpfWiTV1OEjan9C=wZB(g>6Xyo|vI5uudl+qW5+}{7 z`NZ9gDmIDkYvaKNc1gf+eW7EVB<|XY>99mQB*!7q>P}BBA1ij@dxxNubFq9kUvBtZ*_VZm!Md;Z{fC zP@l-;K4xema|R~Z!NbLl@!Q~&1or`*7bcN#vt!oCu>lg9a@Z?`$DcFr!(c2$G(tFzyT5m4|hIhk0d^)=HTJh$Lx`H zScK5||0?yT$Bh459OiG6aeK|y^pX2`j=(YU11exJDset%U9P@W7AQ4gd8x@d3j9D&Q;(e3%M269XTj0?xp|-%|lAFz`VtU^xap zKn0wRfxn{y3NAI64=1uVlO-bV#2#lYWE0ZTCOUMk>J47`U5I0XamrUFjJz`Lk` zlQ8g36#p+^wlkd1_77XL^)a~HZ$I4XcaiB^Q>XDI;|jwKh9do0y7zUPw6|*uG`rRB zs9WHxeHH9})&Q{Y`@`D`3~YgxKUt+o-fqVj{eL_0h$j?m_eFi7pvxO}+dIRdShsz0 zU9xa7`nw_QULFc|wtB;XDfaeQ*ca@ygBrA#K~TaT?SdwqUG}mHR2H#^y?%Gpx6Nyh zhU~szyLU&meXTF-_S+-AU@QV7MVLb>-)&Ale-t8UuU4fN31XQy9~w3Y1l0sPeWCWA zNVne|@wx4x4tpdT3b;L8%%Pgc47_Eez^V{I8S`E2XRi$cWvfE|o^C{tC*%(WfgJDC zyncj0j#om?I&JSDkkf+atY-74d|tjVWh_a_*P*?GLCLx9#@O&~mp2)(u)eXx2JHVXr$JU=BGuuHuL02~_n+s5IP`CPq{ewVVYuFtN08JiyTiERjCd3TLvOU62940WWm?Z1d6K;Nb5XfqX zc)Gk{pQj7d6sQEB9cf=Tl7GZapt8g3LBhuzTJVgSA2L+n-*yS1lg?@$1VW_}*X0hj z14)l`^LaxA-bqx(r(?Dp7zC1PJh7V}y}#%D z%Lak2x=_#)i$svhNGLPV9D>v_hvwU6^C}yVrr}+fv{6;t?;8ZdYJy%!fn^Tq?s}CU zZ$(7xC1ig1*)LWP0ucmvw)>)8_F%~F4@DyJcVaN&@r7cMpf>`$2<>B+@&=2*tF4$< z!z&gKhK6m5B3ZHryzPi%+FQDKi&-Egf=S`{uEEd|aXD`bgIION1zi0_37=~cCQwa~ z<3BiK5GJr8(B0J&@q#jinF6^c$U6ErIBqL&DMpaB`nIEkKvo^>Q-h%1iEXI*U!U+M zgFp|l*E2t}crdinsva-w@Vwn!;l!Nj9K1#^5aYqjG2hf39t`I6LiM&lKCrI<^k2ekiL2LZ+-5r=S=I#5&*P z%^HEAlkr4pUZ_7Z2n4ls3%e6|VYq`^{a)q}JMTN*tWKfkz}iEDN=;%D$5uSV>r?_Y zK9wqI*Rjvn494rLArgYueBvFyqlnLC5g}k;VnPm19SjZF5)FI1qajbo<3V;W*aU)= z?1o)#;A&+5Ph`$T_WxbBan?&LpIJ6oDlMG(7IUNNbQ}JOAQtJzvzQ{ zi|&AKvGz?Zuic=n&>A(bY97{9sDGoLqPk8sn!OCX0_T1&r@-zSVV>4t83tvuGdroN z7n}f7z-)GhqsSf5=8bOmdV{b^x(gq(=>KWLey z13G@Hdg)bxdeJ-Olz@84(s=xSoJgZrdXZkyED$ImUI3t1vV1#!KT6~Zr57m_^?ZR0 zI1QCt!kQ-|Uk&8cG)1D`5Xe&EZP?4snZ;}7r7+{b+TMYr0y877&w4?h?U^f3v5C+k z&(}OMkW`R*tQYi{wOXKHJ3+z0snr8XL1qQk8@PJx96ej0n!p;8vY|fW?(~8wWA6dq zM?^JoHma}0^~EKqUhphd+wHR|?Pc(Lj(Va))~>Kl(ym-+H%mRSO4hDm6WMO2(BDkx zuTs`7KO$)-^fz;sx^0%g&O$8QrGkcx}z|{sNOdB3}J*Zc!bW8-D~?Z!YVIpk9~eWOypV^ zqW#`274nDZDBN;)e}eGF{C-VDO~4;&_r+&AxAl=N)8vn^^3U(T(4R-}_(R>k_E0A{(%CC>OaE|U znJ_{=euPES-tE^2jcu{+aHzuzEE@XxIa^BQPq0Yu>R10udfLOV`)LRB21ap z=)MSdUtKu&=l$tEG1;&Uj0p2>do{0pqA&>IJ96B3+GqV4WEISUduOP-C+uq%bga#J zf@gyKQL1_`8QY&xR{CH*I$~jWFd9Po!)AKZHC`Bm&>yA7o_^_%`p}LZKN2nUrdXsJ zUkq<8O^H#oQJB5uMV+u+h9d;??TZ>#)GTi(Y8^KYwVFh<;{V(uwi4RRqv`Tdt=x!vs-WsBS%M37&MAwj%htB)Tt zR-lORzc9=vpFEr8*0*02N!|Dzp%B=t3+{^X6=Q_yn}hWR!+f-~{OKQ7w(Nq3IO27K z>H$7(bHn_`qapJj2M_3Ipjoq*@PH1#&mSHHitAuCfZr1~A|BYXh3#&S$Jg!+0xPx8 zo`LND(ac_k+i5#uYqLILZLr*Cv74_j9W}KX|Hrt%aI0ag{t~@acc%8Jwo7wZvqAlg zx&AH3@EQ4&{&&pgC^9NvxAa3PNdWV@_^*4Xwhnygg zatf9!^C|CTsT95+DT`ry7zXto^@7V2NllkG5DJIEapYxsRUcl%8#f_Q=Y5zYhGmAm zKA`+*@glJVzbEYay!N(OILP$YTx8`98wFZArL-K*Ql)=C1}*Z1Bgh3SA;rR*HwdHz z2vV4DE<0svcI)YTl9CJ=ql5@BfP5ZsdG;>6=`!B1K7}!$v@cf;C^aeCx)*6{-8z93 z!e_%UpM7x8-T@_rU`*K8#`HQJb9nVyfsoDQ41F^6pQeE%q&5cc`>1_;Cg%zn2{``SR#fs>kgQBsq6 zl|X_-v3=XTZa~*>JtWA1#T4HjwENHw1{7OO!5rS!Bv3;{kr@V3tOk@JnR2UoQEruG zr9co7AcgJmO;4XRkTWFTg~pSrdQno9X@x)zv3CJ-&Utb`*OHW+cs5lp%BIR)E)XNl zSMvAt4kT~-PNV8YX;ju_0$D_K65dFwZ#XcJWM#;o>P7ieg-a1VdkLQg!$AJjp@F0) z>%^&ElsIK<6gWoi`It{9owacwDU?c;kTKPZGNx=x1X?5-05Ya-A4pmnh z1%f1bjF2jI)j$$dmpMnO7jmRdSp+0$_|^Ee0Vz_C3?xB`+^AlZ8#Sf@jZVrlY7z`lG6ueTCh`^g;(2f41$0$JFw5cyWNbeRpjm zxPd+1cF4eWL1IEI3?4g=H<`{)7szjk35mR+Zix5`TYvV;1)m(+vr8Cv4LR;7FRChz z=eTW<)9DU+QD&Jh5P&;7qmUl!?(P8se*N63rw9bJkOX{q!1&SeBcL|y^LE(5@d|_b z?cN>8k1Keb*e~Z_T@u?V$X5d%zfQevujr9ZoUN#bNMrI?#rHFK>cI|1;TyMy-9L2F zA9wT!!!EGa|eLQ4JgEivh%=Ezdx5h7~3YF+?Bag+XmoS18_9O4Y`UiY|b}dL}S9R#A2?q z?mBY(hi%%?lZe>uA3Ak&Br1$rgPB~l=Z5=^|EM+KiW5Sq`>h{evn?W@SqPekkN==` zL@0efgwnT%g>f74!$K&10A^MaVBZe`_H8H29~c7cj~xF8Cd2OgA?&`bTRtv?-LE?S zTji4rLH?u1pUXt(e?Nr&cbp^)OT7Fb^uKWc zhLt1)>>pb4=qWy7WWol4gn-MA|Hvt60{bCNAlfAiPRLg6^*^gU{)2nGeh5wM@U_8C zgF7SADU3?I7HVU^-hcc@6;l@W4^^Mm(;*DH0;^|8SvYX~2bCo0v)4J;Xf1(1f0bq=x~}(?lx7en^Gjr?tVj z+PyO|yCKNjJbgedG|`;~AtvOLg}^QB>>=4d7697@4j_eMkj@Ny6rnWSo;(=XJO4=s zuXYQJA`Hr$araCeNCOx4;Ber`V|Ro32B#)_HE#{$hipM?O0D>6AnC}QQ_+iZ zDvU0HB#A!_G8hKbi!Jr138@RcD0RVlqA*E>7Xs1%b`B(SGRFUV6Y>AC%nb~8HfOb6 zVH<9}%9>-j%#vq5$80oRVtmu+HT>EzN&ld}0`mTcYj4z!(_97l{!c>=zym4=dk0$r z-~s>PSw4PWzy@+L-kDqbasXl#;6n&NKEwBP9)L|1=(aa@HrQ+0?3>m=mQZB+HniZp zn^6{Vi#Hq#sGgcO@&K>lg*yVsqmT@9r}+YRzlm4^_Eis@TJRp5j{FeM@bMb~Bw?yM zzS!N6Um~7&T&(T?jI07yfXY9Xc$R&BQ9B<$;7_ET zGRz%&-mmC4FBUbdt(d-OZJp|=vX5`;;Ds~$e6eKW-Cxb=_b^L@Lz*5qfCvMEzCMhVAzguXFpen%u)5`}z1;`sos0 zl)p5x-!wF#4F;qy!<{g0x4)ft9B2w{w+DRwEX3iDm+(d&9f+4^WHGnD-uY_(SrZCC zTAIDt-3f=++Khy=&d_fS1r%wlckB+u$d5ONi z{qGO{s^25kh1xrOaFfb0Rov61{4Cy#sMt%mcp2uaUCqbQsSmls*r^}zdLR<&L+2*Z z#X^BLxZWZZ=s~CdL4u=Dyv+-H1h_~D4jp#*W1(;;;sF<;$KDz9wYwpr!G5{0@VVV^ zt{X9rFwPm~!wZ{HD*SPZf#8(Ju(!+I=7ZD0$wTx0@yh3m`0Ziv=6&$aL3(P?)rPgvJr?!EWM z@f0m#U|~q%{)j{hAp~na$N{y2j=9U!%119YzkK{2yv_~bDabmv!%PUmfvA9k5|Nk} z{i_Sk%SC~hcb4zu(Fu1gPq?ud<^%oJ4~Oq5ST-;b^DC^U^5`_X zmM7z8Ec>_WSC8M|E8v<8Pn-kIDAg6tnZ+};*)MC=Mew3QC)l;p7tMF?Ek2G@(HJ}_ zep8Mx1#q|rE+c~j%5cd5c(;P=mo;bjdw6tmUCR@J0EYSI?Qh>Xetc+l!&>ZwfMu7U z(u7l{ps*g?b_$OUt800}%f&EX_U=250#GBI%;>R4Jdk4?MEVn@K*Lh}EU=AdgwY9i zB8>jy^Pf77Pww63^KM7XkH9H#Zy*8#zgfFuk1#F~%ww1@_U*gv_>Ef&h8_wP!;97L z+nLbN&g&oDeyT7s;p2ilvXgI_a{NYa>4qqIKpG@=u0J)N|9>;XZMS`FJHh&aHDJ|P zwwfO^&oo_N{M2|pME^VV@9Q_}9@SNA4{Aqh&R2h>_NiV|ZDjw%&Sh>MaMK?Tz*~5S z!3cRa;5$it@&|Hxk7nmO>DMuo)Rf*sD5clNR|)h$DpGB{LBJ#lxJrwa}o zdXkqI98w#83NMjLfuazm=m)$$hMy%6b?dM}n6AZe>I-gA48naRs_(i$ozE2L z@L)QAh-+-D{0xB%aEvCT!X72>OAqu`%)G0zr@|n*5~K4|t6Y$4?iiIR#Vm ztR+h?cE474bC(z0{TK4JgI_&)1;rtD?yqoK)x)Q*^SngN5nc4QLUH=$7L`prOc&}{GI(P?<(%pocE zynh@#tBq^XbVg$l7%A}XS$qzU&cthZ$rZJCy<+)AznMeG!4h!uffpjV&yAEc#iB`h z6c$0mz7hh5FlpPs>p1PAe7=}Rhv>C?3rG%}YB=xZev^f~I!Hj^<`-bT+wSf_HM3W=GkbX9+5ujYll;+{Z?OGlzzQM^3Mv?) z@h~#-s`c1AVnN|fUe#0c{~9@ok6$lPLdFq3c>CKg`%OVB_($FF5{vocQH1#?oeF9u zeszFU&9Fb|ztb2*2E2=)K_MX`g3`vpmj|o%*wMOaYyA*E6|N89CGpccL$ANuZzimR z7s0WEb<-*ec`c8w1JLqBvIfMGE8pn9vIj38TzxOx*l{eE`m}M2ko`Z3xd7e&*K4b_ z-esL?Im>+5ywUV~(=_9c46hoT`WyARx?S3LvdSY;(x^`CPae-6J?;MN|J zx*z^F{t0}ez%y&>|HJQ!%HwMVn$-l&AD(?dmPh9MHQTKa1xCIK$f)$eg;Bzn z4z>op;7gx>`8qItYY<^P90wP*-G^m$gR$>u@%nb6@3p}F6rnKOM+XG$s^;_gg#xF@ z*ZY6Shcj5-38V>M&Ped;2l#MCF~0y2fxeuPAmTsr!x?sdzCh*}OlEuIV2FDiKG`oE zWzY0+kNdatdVZcTpIb4FKh(!PjQm`I6ddP+O#g9%pmSvj|A$b*e=c7w%$-)`%dq$U zIv9KYI!Lz?ZgGP!3Ah6whXgKr3`Ni<-83(q!<+dz0+X<=`a!>dlEcpy*o1ZZ|7-6% zpsT8~{?C2wzW#s!Ap}Su)FkhP(4=2N2oQu2LI7zAAqgQsib<$~c%LYu2-et85fBj@ zO{IvUqcY%#7!(jkz>1<+u#P(N?R{Un_nvd6tjw_f-~W4Av)0JozkSZR=bgIGE)ag8 z$7T4F&m*2So@+d_Jrg`bJ!zgc z9-I3o_s8y|?)~nq?t9!T+*i8`+*i8$x;wd>xh}cBa=qtz-L=!T-gT>MiL1<&@5*rb zT=6ce^GD}L&bOQ|I3IV`JFj%+9BG1uzzSjV&7-qV!soz5R}{V?UFs&-oj37U)qk_Uba1HyT|6YRoJewW!ikU zIGf4(jrElEHS0F(1J)a@S6io9M_7AU+gh#S_u@z5+u{N78Sx?U7IBeSBIb#bm@3AJ z7R&dRvz9k4do7Py?y|_1O3PHsNK0=^2aCu2J7_$PoBw3qW`59ovw5Mp#GGPoWj32G zLJY*enD&@9o9;ASXR0twF^w?wGPO6kjlUT`H@<6p#rTYIopF_Mfw9<_YaC=uHpUuF zhVKlg4R08B8y+>>VOVaMXP9glZs=)9G`NIcg>%B&!oDWv_((X_giIk;Lx`U$wA2t{ zYlRks7+0D@FJ1;h(C(Am+QJ+!XsBSLNme%ls!0g$00wkquBAw`dTL4Nc3eY|Cic*h z&`0=ciu7E%mV_R?)f8z>cP$BB=ND>8=#pDSk!Gc7N$5daNs*5GbR_VQU!WzS3v2~N zI_}kxz-4tFMLM3UC82}qT#EErik5`_pmQivPO^>!UiI^JBnaNHL`y;s&vJ@%V>cZM zTrp?sNZ=<~Mv>~f>PQehVUd=EzK*jf(nDReBy>wG)swFKsk4@(I1o~#cAa!2@bs_K zk}#gcVv2O6myQHZg2fbRR!1!f1N982NPFE{61r#=P^6kRNYczp<9Q)YLr6*yTImGg z(BRaP&`qyMOTrMS({&_>nlp?d9d_tQ5Yr};BK5HANDu^Z0!6xL(~>YA%}|Q8)v6;w zo|X)XR3qw05J+{JmV^mbhESxT7A*;rpGXvGidjd3#3X|$(s`4P1bIUS=}3^oV<1Ip zFltF)+3?B$inQ0DBS9jJ{!MYIwS|^i0W1+>kP=y_!3Kalp%ug^+etbSgw*Z;LrE}% zm+hpKzFI;;<`r5({M0^LLTqhsEx~xcUvt=M!aD@9VN7oFR~->k@sjtoL{mkZZ$A^< zI^w)Nxqk>QEm29FOHS#D%|5=Lyhjnw>>ww#L?se8IiV*)%3E?=PlUv?xig&B!~1wQ1g*L>xq!|k{r|#QOiYM*AY?AL|)So zzq{CU3OS=Eg64<3swaZ7h5SiJL~RCnMNb4x0(n_S#M?YM0F%QOo~InTCWpP6S*XBdFOi_skM-DU6WH4$hq=;JT+GJ-lzQfQy`p1lddkT+vh{^Ud`F zu2m5dCL|GXVTzEZ)qds{a21M>FsX=u>q~?*<>`#U0xl*I(zxrdIU)#JQgTxt#C}$z za&s4S7Mf~Ftye7|moy|yGD7~)kT5L>`MZ|XJb5DdT|*jkXx%LGn}&qhKFF_H5+vv# zf76hL9f~a=zi3I2WP|*yCHcGbAwOwInQ!I|CO>LPkUWF@pe4DMo+jUGNyY^WgytF& zX2c*DwWLiC_7P&VBuHpMzSENOW4|WfYDsA;Hj{5Oq>SeWJWamVkOpj=)RJ7#kT9VI z`AS3T_smfr`BFo|j1=U&hJ@)O$QN4D^36|^&ow09gElugry-?&S<#t%rX@j2A)$$u z1c@Wary5d9tFi3_kA{?d#p|2NCmIqevB*mr5(cs-r?n(V&q`j@l0c(F_G?LS79uZb zNT|pl`!pm}Cy>1w5*&~2Cm(1@klvK+(URbTO?GQZU@=af*O1U?n>?o_fz>p5R!aig zWwJ|40yAQ=Q$s?NUa~_&LZe!;T}uM9R7K5$p5TO_1a7TI*bhWu65$=LD-${G0fhcnogN zPl@-7E5$moNX!ujh+V}NqQUZw<*$}Qmgg)REw@>gS>{+KS%z8CE$tve;4hFJu)+Ki zcnjQTzR_H3o?#wk?qzQ0Iq!ML^P*>q=MK+O&n!=_r@yD8$L;>b{gL}G?&sX=-8Z}E zyJxsZxqG?Wxoxf=TxVQ|K%elS>n2yNtH71*>g7ss*+H9d*7=6>Ip-tJ)y@UZBIjt( zC3JAQ9KSd|b{ui+acpv|0Zl@&V~pbpM+b+?{)_!1`sXe?##W(Pv}4>nz=@RNM>5 z<2tGht;xxwG^!(7Z~5YNZ!3ROI$$qI@Jz8z$%t^g(5$9M*@S!;?2nTDp)#4~%R=!i;)uNe&D z#YA132zpYJ>nSLt`^aMuKZ>J>kdR{>gLtZyo``ufa`n}t3pMfUp_n^pvYv>UF2*v5 zr(*SmVhjp$i=K)e(?q7I;K@v`(-(_=#>@3k417Rt(nB$`&{Z_?j$acfB4ozMVGw7w zq==BTVhn@WtOZ2`x8!T}M9eTWi6TPoiO~#VLv#IiqOm=Bgn~knh$|Vy4KaEm#uHyg z5h16;C!2ogbVq^RIlK-TMv#rTCYDIzH7+UkiIsr(v!p%}A-+^naf{{VTIqC&g~a)Z8D z%+xS~LA=AGmq&LbvYDcS_W*fFPetQ>@*qV8b9%ClqC(U-@&HAJFmB|2Jr#qhk^3kr zggGPkQd9^#M(&}g5Cn|WQ&b4cMee4k5JijJMNuK*6}gk5Li{Om2StU5P~>)s3UQmr zZF(w3P9kg3{=Wm6OgwYlC)@*FJ6uW5RgRw>CHBMieztWsyR}yQP|UZyWO=|c-_pXo z%RIsKgXwNlcZdL3Vz^{@&@fQ=Kv*s$l08s}`fs{it5{#ehOI&%Quyg`z|f$RA-Xww zd-mzAgx8s0HapRq4$cdUYr%sBLzFBiO{}W|x4M$jMg0>aF~RF0CU}WlqmgJ0 z0q!*UYNeWpeIp#<{&NX%r^?kz@iCFF0NrC_dMOl~z8-?pPm`4&sC|4*I#D^I_$rY=6ISsTd5>6=^);JqXt$uvVT29_Aijjl;R`f7PaV&`8~30t04Lp zxc*`m<*(nLCePBfA9eDLsUQ~;6I9Krf)wnI<);edQeFH1!&#uG%Oy$$k+mD&0UFc( zF%S(6@}n132=(?Ohm+)D5sXqH&2;dYoS9|1y*v|9kY+lBVq}?aDi=Xh&2l7410ndT zdl~HNm|620Fl(Moo}u(##5~gky8O$~q_Ggos7f6)qF*nFQd6k((ERWc2XW2d@%Az_ zN9|=)R5=&2r8W%uwiCF87GU@IBbJc=FJwZ7j+(CgY7y@>d}X=}-4u!47fDClfa!?i zLK{f zc%_pfi#hyeU;=g-nx@|MW>p2+L=ywjQPIO?c$*zHf+N7_EK-C#?y9MTvn zTg_LR&Y4!4x*Gp%EHg^RSi?7lgHTxXFWLkD*&b-?kAu5_p_5<@9)yhNF_sU+@m&o5 zinWGL{#MBE9p)#cAYaLG*gr9`S8oXClh~`Dv6DYmi%ZDV;JPcgUVv+<#l=rm<9aIP z^~Ca8XmPQ%8k|yI&tAp?e{-1nCOLBDgj|dZ8grvkWnHX?tc%nAF-irID;vB%_GwH7 zkz7mlkZWn0znM~g?rcPlv?6cwV;W2V`|B(0!Qtt zO3+wA9qoTjFYr5+j*3hMH0W(i4KS9VhDGHS@D=gxFBbY8N(B+UA=&~rssdG##(GH7 zIKyvOYKZu&qG@qsYRD}I)n^ezqMirwpX*z1dZoZ`)AbUXDmSKzI#9vP1m}GmP_1tt zTIjdxdZ`QypBqyFX3#2zA*CpYTd$0p;TLti1U_XG8&iWOX=Obmt(@Vv=&Jy`?Eg>| zBcPuO*BAQDx_&}C@5WT2&VX4D888d{CZ&eRgg~?L#?+7tfeFEXAJewh$8P`&3Z_tS>!h;HAEIzv}tcl4LNXhhB!WzB}($y`q)12P4x>(9g)WpG?H&j z9kXF|#Z12S%}>V^`HAie#(}+kV@g+Y*_F*(Tnuj-SjWM%LV3CFcL0~i1&yggofo(s z@&Xsg*D5tch7ub8H>L(v`qFwxUs@M!7 zNsQ|uiSZ2i8l{5B;*EX|jj3P^jMOR!9JvU>JPGwNUwkxOUZPYHIgX*zw199UR|7et^5dTfe`<4c7I~*>AE>v8USpupPB+ zu+`ay+ge%ATVJrQ1|R%X@pthr;ySTf%oJN%&Rh0bR$B@z-7N<5JLb*iMc^6G#`Lx6 zfawlXiK&mtYCLJ&Vq9b#X^b~~ZFt%6fT7ZmVQ3B>@_U85gfgMO;DV<9TYo7N>_WUv zh%pJG7k?XVS_R4D%IGOF>Elz+Gwy#>rPG_dg8#va5F};!RX`LTzc~4#C!Muz9ajrpB`&HEqqc}x^UoYL*Y&IC(dnM`h=abhw^u@kV{V5|kVDR##O7@Kaupq>k zRpZQr1C7}5QKY~0;-!UgP1`v_h5Lr{@Z=IWx?U|E=`rw&=5ot0K8ueB-EW5Ua>2a~ z?W!k-@x!=yjIfpJXj;6~V!a?H>N|!Bh(705_OHckaz17=0n}%C5n1e>!A+vPDjD1hu zd2v7(J&1!w!wR}31373kkf6~6IB0yzr(4pWgT{z9O{EPf$A+%l^L@D8{WxfJMQbiS zI^zYy67Q>FbYC7Cywohxs>en?{o0a4Ve}OoH2R?pm0sQ`Y{L@!;s$c0oF`b(!Ov(aS^dD5QO4LkULVi=#o#s3UW@&@U)6^S1%`1{9Ud@>i0 zYnEBsq%A+STL7j0|$+>nMSwgp zE0a^g@K#(nOiQnHpx?Gf-`eqh7#_=m{{#^wsFRJiB@d31vbD71rMJ)B`R1~4=`DD0 z4CFwSp3*!3SI=SWnZOj*pU-31V4T5p$<5f{zy#Kp+>{N*`Ae7Fgbl{&OP~BbY%rcU z=#t%RaNxk9KhwL|;J|r94|cM_c-)|y;b4Pt#c@av?|to)PLoOK2T!rH!GXhu?o6Lz z*Lg;R$09w5^VcAJ3ZfTSDR+elGLUql6Q-&;^$ar|#V+rR&#U>lrSU6;C zm(G0t)lK7n`Xz+zCa{|jTbm^98Fb~|FXo3YS$O{+PxcYdG0$etLeEG~ocp|cpL?}? zy4wd){f@dGan-moUCo`Jg3tX*=T**bj$a*bIMz8T9E0HYf5yJee!YF7y_@ZK@TT8j zn{OLwi?@Dd-EUoEEwrYIm&CWkhsCSKp<;~XE6aY%8cUg_uf=9QWq!iE)O@A6wdo7f zZm=MjXzFDA!T2ZR9mXPKcknAXVtCk44R`-$!iT~(@Gr;_+LEuJnd(2E9Nf{>tE#~` zwlZJ2b6vDaJMMaPaI>3-hq}cl2RC(EfPewbM+|}BzRnPUKsyce2}TZX?JNOs9ildO zpB&uX83LFXgxXboa&UuZ2%sO1Nm{QvRLQ|To*}Rk+(n$y?$^_ob-Mq)P%ov*%xxaJ z6_#20(3UDQ_j!P$BE%|fThZP*Cw@z$bmm46a8wx3M?5*W)2sIfX{=ENO%AdD~n&Xp$J3cL-cr-HlKe+9)1i*!nI)3%G5~M4E)VKU)AD8XeMe&px%FI{T%F0Pg>60XS#RVe}H70N4WPiN_GYGXPrv zUGJ!$%_rk2fFl6&fH6w(9KaUf%mX|Num#Xdjqwe59$*XL#9{o>cqU*A>;(TUMh$o_ z;0VA>qlQMRjAsK7&<^gv>8FN1+RJ!4V8L->QteNb@qEC72XvqM>yeBn1Qr~%pN!J+ zjKG59w5Qg&jxwGS6nI3ZsmubfgYhp74dqlB&j+khadlwy2%ZpFaJcPUq}tq3#xnw| z5vWpBH3ClutWr@;NR^r@=Rbd>h|cy3Yl{ym`%_sYSe0*%L&fKm;6Wda|o zzsca1OW-!JBUajW_a7^kAO9^}{&F51XEj~?wLCaZQJ1tqch^|PgX09HOJB-`!}N@o zb}p*e^h1jmLTyjECIDB@PV9QPn$(!3)h8!@y{WG;3|_(p%pDByk;K0PxUriRV z!8k3g(mgSYCcS%Y_~e(ekPXI3*-U!;$8#G8zJG1F%?sFI3{pYAjm&3*abkL;M>h=l zp!wI~Q)NmW8;sMEF1eNs#vPvOI&Vz?tQoK2{hhu^U(JEzP5L~2ldk5%;e41Xy|nkW zHB#G!p$_y_1>w5$yW)c6C)Y_QVir}5b)5>~y_LM;F;W0Ero0tAI9$}X(p@u;2gj*N zU)1OF;6H#vI$io49-KXs%Xx5|$xWokwBy!0n+HdSak?>OJovNVA5M4VEFK&k$7y&e z7Y-ifG`xfh2Ul|%Ud)Aq4>}E>$%CVFIt?%4!oh2uhR@)_!JVCk7jog?=T5^5xNvZ4 zr{UANaPW4g;nTQqSkBu?&uZ5s?^G@v{Nw4;r|{tDI8VbTbKwv(iiTgsg+sh{3Z614 z0M~3q;d7#X!P-_f8QEw;o;4o27C!}+ju&o{zx^tMQS`*TEOi=U-J{}YNPz5iCiF!35 zmB$1F1w*Bo{`UyY@xV}NN{EoG+;)Oq13|^jPT1`V*5X z;^$HGC znXi2~Ol7|I<}ond&%wG;KaASC!!wx0~rvJ>*JkAt5n*%zQE7=?{)f&a) zG}xFNRK;ZTID4&Z4qPZl@;E(2CI^=*3!4LLl{q#re=0xvx#COsk3$fUjt@=%~bR}#Lr%QZ|6o?@3UIjB8Z%;cb|WD%2tdXa@p4k|$wFgZA3<}*2{ z-l$`8P?u4wUxz|_4gO@O1P_<3tYU61TUo_iT(+``IpHVAvuyZ)8mwDc#T*=_vWnR` zOl1|bahS>~X5}!IRZQeCl~ad>!&FWkW*!sIy(SJ*Ig%K8Og!2eI85cdBJh}aULpG9 zMX+y^QphC^3m$m?;IQC5_wO85Y%Te{E&Pr))ty9rvL(N9xXLC=e&upu_>sTyxH$UA zFFY;|KJqhsne8u6xm?B@oDuR6$zAgp&42INsHU~!37inZV!@^tsKbpH-9`v2^H+H|97jw#2~ z!_?CFtMRn)72{^h!k4Onukb z3L#Hl7n|Aoh4oGAcJ~T%UwHff-E5a9gsts6!=h!n_bzT-;2_UwB;H zPRScQE^0W*VIEhBgn5X|#fX@H=5jGI=0PqOBV@kL<0_FdU*mEyV&VM98B&t};6}@wm$D z+{ojiNe$W1LHTXri8rJ+Q1k|>7hdwXMTD1B<>!aR8Gl^u9UL`>ZYBp^cE<8J?OaR_ zdhX;f1{|EU@nlNgb+JRYnnB|ILiDa9Nft|&8kJXlYP7(YSy zA&@-C;VM==WF40auY%+OE*BmF$^ASo8t0JvcwDr^A@}mQ%DwC!9v5wFNIjQ}gZXYA zR~gKA@wiGr=R0{^WvJi5c=+^O$>G7-e`^Jww;`6pgImFld3@g1mK+|Qn&xtNIFRRX zcsNkYIXt+7+&`PoyQ2k%hv%#^xc4asxNx3^fC5<24&wt1i>Wx<-~$Ys37$3h0K;a& zO$;Akm`wDU!3P*76YpWkaBoCrWG4yDwpsZ6!eHSIzbk$}Jx5WSLT+V?;q|NwTMSh# zWHnn1Z*HC0V#@rzg)N4cx=tK1Fdic}vw6z2U&SsG?{pp6VyMF*H?hTlcRqO7-8ZQWnHUvl5(E^_y98(ha+n_Tl~Gm0vRBv#+8wr2w#RLYY$I$ft)E(VS+BQ_vnGn)h%bt3#TjBc>9OD>)^-BqR-aBPc?*EsfE3>BRs z&*q@xry2{S)0^AY5Berz+bNfE(4bE|BJCeNAl8r@@wk`K_6`<#wYjsR=}?`og)^b1 z_++%b!v$aCr5)ZMQ>5p9>wfF38>%A$Xnn^NP&5QyX}9y(hD(RuiU^?n9a{izVOHt( z*4>5QCLN6kpamXV0MEJYrR`d$cb|+lcx(YY#M-61XS{ILjPlWu8qf-lEr2Im%E8|! zqa7Yw0B>cCZ$L{tjsRTLx=6cDoWHe8>u|i1R2gmYKtOGAW(rw9(@_Crw8dk=aTjO6 z(H4&d$32#c3y>?a;w10 zDdVfhas^OTLX8NYoWmD@DcnxlX1z6bLVE8=lg4lb@Qz9a=45VJ7Tv;lSXj`@T$t_rEIPM>hc%@Bl!ZL;A04k;0u7(k0CIeF951QhCmiq0QG|m zfnj_BP#Q7>GWi0aUS|jl+57JSE!i6p%|t2;lOc+qN5hcy?JoOdG6@#1^1LXBH@4JUK}{y5~-!j zEB6e-^$T_|-q^Y4b9aqdVhJrosd5ia@qx%=`ruD;ItPvq8H}#!&Vl0_2G#gfIgJCy z-MESLi1sX(D*HHav}j{&-d-MDab(hM-ks#sAYA3zr)+&n$g=PuH&ssI6pNZ7I*5{- z%!9+3fa<{%xtjuSZxVE_mZ}qX*x3>9|04{y5zi6G08r_XJWb%Oe>>Rx=eiSJ-?|RC zZgb6Wb$1c4^Iz|*bPjad9VZ=|9d(W@M@x9`-vhD#CfPgNezLu8yW3W3>kTjb$E@qE zm0(|Q72g#f6BmiuVmw6t+hbW}nGBKti20~_y}8;v#OyJh0UQ72rm?03<2T0r##@Y& zjh(@+{}pIX^zZ*@52X2r!0i&fE+W_5kU_4Zb?+tZ)1Kec{1R6}F?_0&-Yhk2d}zXu z&+9|x6qJbEr$en$(v1=7RGa1>$gc#INz_`F<{!Y9Ky6Z6>FG-g zhnWV1@3LwB{(K44CQ)^G{rv(GDs7U=pqV;3d;NWRcvO^9yRz4R1rLw2^b}zXz`Z zW|Tm$Kb?mU#O={-pI(1=9v-z^9%;Sy=Hm6I@$jhTa!C&yzV&2Q?uF1?@cMmRJiK;L zKX7NiH;9KlE~thI4j{~N7t!Q+{i(cyQGrJ3WxW0rE*_p9sD}9b$)SdX^at7eB? znY;UwxFX6bDlC*<88SG#$(P{(xZV97{(%UZG-pc(jBV$>@q{PTurz=Bph#qO4>gS7 zq8KmTV43&Crqf~FWOsiezY;~ozD?TR{;9XNU;jX)k_3JwxGGYWc>V1H5~@{E<$2Xl zs!y+(eXMJGs0OdUEf0^YT!wUC&dKB)aa07~hKI*huD!Hs$BLhSg6K3Mjfg)!h^Kx( zT;<4aY5N!AkR}6)LIPfYYhDGoN-UMOBsIkL^Ispq$MNvEN>Cr*^S9zPNYRGBCq0`m z>5K=WSBAeJmM4JfaPuJPZ0_%)Ge&og2(;u1!0a^Jq%#F#*|M@{Ljo!O76Ad(>G&G zRDUxb9DK~urTyD{+bc(}4K+Q@-!uSMopD0G0LmGsSbFiM?~boqF*PF5ge#%U&LPsy z{WA`=x>a??@%#e`n4DG8%kBF8e)Oks;J!4!n=gTL({Y}&F|t%;N0vY zZE?T(w>Hmx8~F|=UjnBlRfpH_2uP@=rpkArg>>KNYYz8#F&w?h>$mgpcwk|aZ{y){ zDz}s#=veYe_aXa2U*Ppyd3c=4Zt3={T?d+Mjs&Uoi#$9|=|g!{f~FC~fZTY)Gtq zF@iU6@vx0k?eY1AAU-lNLvsNZ3Sp;o_O;T(XI<+;75MywD*y|HaEo+$ey=&wCkI0U zDf04wfNG%#duX(l)@#2vRlYWerrHBerd_4u4L@I+a7%|!;i>X69vmD`?~~4~TKn9P zZ+eE{De_WYTViYJSubA$Xyya9vP_VD(%yR)Tm=!$LglB)OL!82P5cV!^|p66&3=4d zNWu>H%<+~z#5%{CW9?yWDgG*+7GDuJi8qR~#Zh9a=(c=oX|U|^oC6KPv!44s%fTyP zq{r)N>i*Gv%Kf5yqkE-$9%u`CL*~FgTpzg(x}I>Yb=A49at(B~cbT2%okt)-z&*~T z&Kb@uXE&$Aal!GHV>?(7%y&$3^mD}9{|-?EU$$?w-(WAZXWLWkF55S@2HP%MJ=haW zu??~%*bLTBtOu=+TW|b7dMS>6cC-hgJrM1IXb(hsfHEpn6z#FK-6``*#cUyHUim49 z8}KIigvV9P^FQWs(F%lo#N#Rk_#g7Pii!PM9#=83Kf~psiT!EHdNORLK|Wyf@WqS# zmCeKFE%H8_hi_Tr6q|<+SL8i55A7((Nj49kX~+r6Uq){sL_TA5LfFiKyhE8q2P_Vh zW6}tYD4vMUlVcoF<-9bUD~g^V4O~&UUuE$`6(fkZd0aGjAV+yz#S!E!E*Hn)5niM4 zLN<&i8g*AxyLRr3x+_+c7X=&=3EA;a-4!X@Z)NtOeQG9S*2A<_R-ip>F}$V^Ws50` z({8qyqIhGADeKnrY%#pF4`GWbOWJd6F}%A=95M7sc$Uq>2Y9lJT_l>s4(5n~r8e2g z=Ha6|*}*OnUmymt#qjZ+Y-fw%L&QL~7(T+2ZEP_#(jCASQ&#zB*kY*G=+73zM|tuz zTMV@u{WxOi!toSG43r#wIb!I-@g$pv5A);+c9EzDxq>5x4i#HDVxSJ`!)Bq1v^R$Z zI*wlKvrke=Pc|bVvj>|IKQ$fS{{_#d1pXKOi}paY2ckU??SW_yM0+6G1JNFc_CT}; zqCF7pfoKmzd*FX_55x(k`1tsswWjv}@cwTVy~K0KbB8D1ebVi7%y?YD(esx7N=am+h6&6>`uBxdkEGeB;URhpOURBAW_07!7 z%E-@3%+DA)IxBGo3o;|It344|`r-=9OJ*d3^ypL-yRxXFbVg!+)>ZimwWPGRxTd@s zYgbX{)N1}&d-XhMY(+&;B@~FF_HH-k#fz~$dkU+sRKBLXFgqtRdstRZW>(?&31h}& z}GBXsND%GWf328f}w;G#xU~my1h_ zYE%_fm)5|5t1T?5E37H6om*H9BQ!j2bxev=SW>jOmL;MvXn3#>*digON-RXuRuQ7A zfaR6NEAv8GBZ#D;=LdHW#LLepcSZjM1vkP-C)yH6bHE zdu&eOr0kqwV<)L_`5Ad5vhoWv$BrDEmk+HTo}H7eAaNdtf8wzd@-xSd$@*uooC#wJ zv#!b=JAOi5R$*3N#&}f`$ji;j8$UK@d;pWBt^m22uzaW`)Sr-%pPw}*H(ynrnmarr zoA>SGCuC-3jaL_|`k4ypV%1z-v1%4wY;GoYUt~1UMe7m&ybN6fumE)<*j1?+iV zNEP;Oa+f$UHa%UC7b~N?qzL}6sJ67QqO`6E=4xFLP3fZ@&om%7ki!hz@xpssaY;oX zdy7zUie}ENDP2%r6xjjo-7;EPVke{t1Qx{7MX>pm!%QujUst94yRf*hx~Oy@-kR=u+2S+3&a12>)qmC6@yO=i?zc0zsXaN`TySVY={4d{zZEr z+5^!Zi1t9V2ckU??SW_yM0+6G1JNFc_CT};qCIe#dLYhZ5xlOZE>l3oo!Bd}bWu@7 p^}Nz+mbEfkgcM*IgX+r&C(aNMG6aQsL|Cl^iw(;Qa?&H5{{cs!0^!EaXLw7q&snU0)(+)ugG@nxFyD~ zu^n(6*SNmVcuif%RONDo8j$$C!j0Z?MR5U&|xdBsNhnQlEE!a z;ZQ?uDApK@Cu{4%^^s^K8Hq&;{cb?birLkxW(%vTXD*s8Y%WBySvbupK$BKnZKQ6q z0Njg4GR@Iob9l3`YWCVy__uZ8L?|9~qL1+%{%==w% zdpI6!25w5@dP?3vvIAp3>5%xIz%n7Km(|(ZG&&eiYt{E-hLK8k14K}qUB8ijnM?>M3q}=Eno*HYhl@1@yW%|qg zrtG-e?7ys@*csaD~&>lXbZ+)*OT-SU3Q{;zGeS*oGD^igkhzj>1x7e*xaw z5{U-mZ8RXlx{D+dk!VA0b2u1H)b0w$V{*t#tuWh4%gVS+Omn08uXYH;cwq zx!>z`6ERnbO|qO?6qgxOy zPq+@EINqtqC=uhpyA9!Fp_W){5*WjUnq)c2wiYslox`(xOtw-{w}S#cqh>s3WXDlOlCN1^JKD(YME?Hp3IgIN}!aPk&~-z z$Xbe=h?7%b_3CEUhQcaXioz;b3aY|6{5+S@Ryuz^_v7yJ3eeKwp@9$+k3g=*u8CSC zg>5xy*21YI$qQoCD3V~wqkig~igomV{PG~vzIJOEZvdKgk!am=Rv4xZU5)v(o-Qp| z9b3Zj0*i}v2c^z!JIQcutiB!scSjk?=G0NPT)60vaXI3S*v8Ho+NqOjDMu(D+D89+$hLBD`)HATWC@EX6fKtU{?5Qbnwk%_-5+hn`=|_RqNoJ z!}M>44!+qAMW3jHZ) zNZBeU=}2Msf@l#9eh)m)mNc|Z!$A{6Lj!RGAVu;uY+$Q!*{w4 zzADBq<8<&fjs3=quB~HSHa7C9hoizmFeQwp{|S>z5zP;1ZKMQ z*TEN1x>wmx2OrN2Utb-3ex`qYbnp#ehOblyUw?+Lw+_C3j9+@`;Oooi>#2jU595~- z9ekzCa_FIhuQxMay6fQU#rUP04!)j@KA#T05~hD%9eh0)K93H*?#!;@*1^|}(dW{^ z=VSch)WPRf?5uFed>si(9vYS^>^j)ol&#XH!%7!3tF1ctoXje+=-_iGqflYi(LKeP zl_nkPY)tozI{2&%AJ-v1fYokkDg5b@T=1uJjt2qlZs?EVPtgNK4-`F6^gz)AMGq7` zQ1n3214R!MJy7&O(E~*f{QuPh2>)}wTMh8P;!n{7MGq7`Q1n3214R!MJy7&O(E~*f z6g^P%K+yw55B#rtU=`P^KgT&Z{Nr%g9X9+UAAje0lhbK78O2wwLO=UE`u`aJd(Je# z|GL5X|8I|Wgz$vQ>_Be(ZhnP6KPoCXp!~4Sn(OZzQc(7^UWT8IT zlnA4D#^^6shPSnb;T>yLvx032U>-HTvI08=-CfYyj6|xM$4wlIn-l15;=I=Jq!HYd6E_Z1N1~yo*1B+A zP40#Xuphn4KEDp>T)z<$1?%c&!RwL09E>Itt77vB6A&mv72f$j5Hy=GsRZR&q&6j) zjMs+X6(D5ZK>8B*O8IT^fy7=!RNop!B=8>ftSz&`^}*JrB<N{Z99I9<_V`OllKT>DYe(&(z}7!x~Tdle^aal-zmPS_)+ zRneuP>}Vr9V~ZiSm=WMK;y*FO9!4`ZTh8GLn;pc#fqIh47Q<{Y%>HMFS%m*>-YX2g zCw!OqHu^?-zxVzY{#pDfdZ6fmq6dl|D0-mifuaYB9w>UC=z*dKiXJF>;Qzb_#@OHr z1Fn3C!Qjh10W@l!*0KLwvTnQ;F;pN1gIsGdu@vxl4?k>Uf46Ro1(=K#y^I`X;`SAK z?uLH%ub=#|Zj2de8O3Tbvl7vhK=$A3#+rb^F^*+m+sPwI_BZP$7?Fx9mczml&!S$!P~<^ zG6t6@)`fRY7Usl*p(I@5E5z!Bcw~#=m{>LGTmfrb&1!6FJJ!`2;U3hc)}7?)dCkgz2VH+X|1&T5Uffnx8Yl7q*Zw=$Z) z-tfz(x=8cvM5qyN(hW66fc<@YK5&V(2BD=9Iv#C+ zqW}reeE6kA|Ge&g_0{vQc9CXvck5#@m}t}QYu(u|ue)Ey;v>39Dd{e{PdwfLvn?Km zK_;WS{7K2!7pvaLc>44I7WQ|M>J{NoYdj8@#-4nNO?!8g)UyvVBE_*rEEwBW(|uVO zEQm&6uoWLP;;)S)gdLG&qmT#(;c{?jC!ZIh z#u6b2t}*!V2xxx!{FoPOR#vZ1YV4|DMuPbkP!HQT-n2}AFW=$83YAFZYr5_9F7oW` z=9b2`L>Mv^n7^=O8O2|`-r~lJr%@mKmf!tF7b&iRq!G^T3GgA3)`Z;E55J1Lu*Pbt z(e=u{U0tM+_!hnv0$-+TOW^5iIA*e6)$GJNm5J;6!`!Y~tIOKLaEdV8(ioS!Xsv35 zW5o~*M=4#r@6N88xN~6(gs&DvVVg1j(AZ$dn#vVTH@C#Q$eA_NgT@o)Z8oe(Nh0m0 zjWfGS5qxP2rLC}$p>!Ir38QD|HmgRZ`Ryyu>>`z`n@H9Q2nOZPSS2UE6SZKK3PLjf zY1Ri_q;h2o1_`j41fyGzZR-q*Upo48pi^MO)Ovd53ZY&fF!3O{Y$h*P;uBFTtON{^b6D-`{+H@x9@D$@{4H zdT-iW=bhyp?6r8_@jT(V!IOnA0?hOX?ti&ohpz(cckghoc8_;=cYW%5)^)q$ID2>7 z=eFl;x7#kVon@P68)maw-?2Vsz0SJFy2(1#I>2(m@;ZD$;9AQ$mQ9xFmVm`ze#?Bs ze9$bJgXU^;nVB;kH$7sy#LKcZT!mkg7I$SCB|msB4fGH!M(>l!ClWu@O6P{ zTtCCNsH=vuR=9rBWHH)uBinw&VECc++CKvbe$*3jPxxw3S+Wqx8J1TK_lS?|uk$@W zb)AsFB%E5x(0d*=ifgzB2X49Zej#3n!nS^eMckSiI^z5F*9+SUP@K5@?15IXMOx7J zDbw$SmI4&t$5OA_#qF||SOJP}AG-WIMN700#m!G`F^QXHEzN}}&VRB8r3f@(3Wut< z-!5zIC(a>e1hy6+K!utdfpAs<9p6A*#Vpp#J&6>efXatgOjk>M?{$ZT#sU4H53l08TExk0Lb4a{;D~1@%jKC2p156z<5qXpsoM`0?s)CAyhyIg15@l*iwiB zu%|*1EI@&9Af*UwE?~xI0N1D)wFN{Va7F#eZ$cDib`B#1L{;z`^V$(|af#>7+&E_L z-TV0s`R#xw=&a$_=eI+qPx<|4;&ygcq2xT*0e)Q`J4&V%@oV$iQOdhSy!BY0$oq4K z@Mq+=L!wB#?_ZOr9;J0T_5RiQ&5#o1n)y|E(p`|p*u(^xtp1gG>?r-9>?`uvQK~RR zylUHt_a5y(f?uBB4*R-OJe$N0|FS&sXdkBHm*%s>j!CWKm*lmh9j;Bh_nCv;qy_!> z#rf^9Em8HtBGhhSrp{r5qv`cc9}E|NbLkh0TF(72un@uG@RqDusCkC{TPfiaUswz}$Q@4BtZZ z%b5|FQ-}b9A0?PwfB;3V9Dy*afDzw7;4+Kn$z81}K!F06NtBlCUs18q8kku?2@YI2 zZ&eo(0fDQZc+cVIU-1ooQkYSI0s|I0KRvG+PVy(LCz&LniUeo9^9JzARfd7E>^34N#yJX*ePtA|%3?d?9#A zI>f|3pIm=%cbzc05Jiu_?6--rKL4C_`uSH2qY6?SzlRzkjLfGn{P2(cU%16xvZ>{m zLS-sm`P@|TiBHcMGyWH!l#M7vf-1yQienZrXJ?=g1q8AlVp^Ubd;tm+$dviv zFGK+um{F8RrECDEP>=rC5XlS|ioaS^f)oY%V-j^|aSoR2Y`+2oI0wshwr>G5NDh{p z9DNE=;2bPRQCfh4n@;wm+88GUFgYyn-SgWaX4AFk?}po1SK}N^?f~!0V<$OSPP{j-9mV{0;?4IDzVW|? zo$!0|#N(Ks6YtJvhnVjZ_ul-6r`Pvb>38L^;}lJ1_dD~O(VmcNcH}ps3@)eKo~Imb z8FXRuw!C(dDry(1ghYcJ&ynKTDWLyVLAJ}g~TnqMJ|L5Z;fa@QYZ-<>AT&}`gTsv^tCLpdA z&)sGJ^JO!fKYsDK^WSeJT+Wkm9Wi}ic^+{s`C!Dt#ebgR{Kfd||MBJ+!sRH;1y>)L zJ}|8ajGj?5FZ$w?pWA0RXFT}b&*#b(+E2!{+4O<&Pl&7fv2~YTe%B0VuRTZKeEXfD z*c-OOT-JWqnLgl-3t(aE%ZZl9Z=c~@a_@gneddN?g9Z;DIl)?(%lwnKPQ_&@%w_F& z0CRzb^=lt^CEIg`Gv;}Jd9OE+H%3k{7v@4Y>wLh41mH>p&m8P+n&J5Ru7)R0G$ISj zCzwvgbvVZr8g|R}6X6-o(;J>&Ju;2C#v3sgOeXb=GI@fg4|XGG?0#?3vx#eGxPo^M zUfVDq8#taj8B;A{0{dcTzxnNNKAqtjzxulye`&`|2>;J9JYews&UdMAt*^}cH}Bov zHt$TY%kzTgYIxdT?*0;<^rzhm-6gKqT-Up{y2d-dcRuF4(7Dpt-|-j6FC9t8REOFA zwEd^{4fesdk8JnacH3s#Jk}Sj*IL8YQI@aa>3!C+*wV}VhWQ3_v$?|bPty~oADh;g zc;maqJB&MwqS3}Z2X7J7a>ERtf-(R8r*ck*K6e;S3UDRaBIetevvu$-RK5aPIZFrM z0_K~xH9Gj_F?=(1@Xckua#^i|Zw}MH89Ml8J6ghVVcaNqp`udM!8c3MS211Y>&Ul8 zYZP_Ubf}xDsH>c+gRhzyhABGuW;m&x6_a&zPo!*>lXR$?&V2lHq7J@kO!umE@J(g( zRqEiI!mPdu9ek6S;hUg?ZxZum;qf~7CNg}d>)@+m{4!1lUnQe&tPZ{kX8gwJ;G4jV z!)P6R;~6_g>EJt^@ykdZeB+pLFW130mf;(rgKrG;(ca-Y_(m&!sW?sM>qs;kr7ZVh zI@FD1x;In@UpX`ELv-+sV1{q74!+^c^c>F~4P*3`>EIj6_*2lqH-y=2 z13LHyDgCS9WxkF~mx0Q3@#|1m#th#89ee^aUHa?b3n<;I?5Bf|XNIq@4n9BAzdkzn z1~9`{s)MgT!`E8}Uq8k#y>#&PW%Tvb!PkfJONkD?Qf4{y(81T6nJ?XS@bzN+(oF|n zPevcW9S2uh#c=@{aGUBQ@kFw^9$t(Q-~!;J0Cy$A?Y;;Dlra7C>fr0a@WHiy9oE;K z*;U*+__{IrTsruCj9<`8=NH{NSwd$~yE@oC+ zb?`ZvRboo4+6}R+!pRMK>zpud+={CR7$WmI5fxUTs59z@h?+morLaJ=rH3_%2*}A z>cEUN+MG(`5@uv1SRfr&xtLK2OQho}7bz;MBv>RJ=Um8g!ZPVN=K^ISRZ6f>I^NCs zw40R@ER~Kk&ZCS~60DVu+d5b2Wu*kGrQ<5+Fe(jtRL)l1Q?*AAV-3T2t{%pjN++w% z(Zg7+FjnrC89TJLW>Du;o~?&(I_0a{rN_|8ilJ3)dKf1$j63x(PGlH&=wW0k16AAg zFjg=cTlFxGR~RdkGGm8E@pNT05_%MlQxsOk^)QZA^8TuAdKkwr8e8-*j%FBRdKgDB zj8Q#|Bb8NL*(@`5Xf(>{XjC@o;Tul*sp$aP_diVxWK6vF=M+_I3 zp=i*<7+@Id^)U8VGQp~_9>#u*#yUNWeHq4(9>zY(lB(PyGj?dY^`@gy8Pvnqi}F=% z)?;W-riZn97)uz&O?nu6C=QDU6k8%8VTvMXxd%>+~pe zFru$yq^ebV7%hyYD|G;@bqwDM9eit*Xj8dd z2j3YAU&S(+k4~CX0HZZ@&Qvbdp>8!(Y*?a$Zx!Q~#X9&_DpRy_kq*8UjGYU0@GWN^ za4yinw@jI!mGgD*EoJ&QPX`~1GUw{xTde3q_?-^IRFzW&}ndvEr}ycM4B zJx4v~c@}$0+^@I~x*Oc1Twl6=?b_p-?Q%JvcV6k-=p5wuo8wMLt7D3Tvp;G7v3;ez zukE<)Mq88ZbnD-(kHAfV3#{ENf3jR-*rB&e6j;NePKn(ri7P6Isq#dN`|;_*Ny==;34@23JWl^>9|O)3#a`StI?g#pInhxi!BLQobB<;` z1cyO7&N+(p5S$0;IOj;E`dlT!iI9$Smb1QvGa()4WS$aNNpLEpx-1ZP7!&N-CzEu0SNIOhEZ0hdT5v)&c1Bu8>)x154)`l(Zk6+Nv@Ix>*4IphM_@vID08erAiv8hqEU; zZ_D&>max{s36hR4>>jL6I78BL&hAR4StY?Kl8$qBW37dQBpv7UvDU&-l8$qFmDyJ* z!C?~2*`WZYJYBAo;513c8QC=k$4NSFtBYM@aG<2)oKB^eRT3O2={P6zl(|ZRLnR&O zw6oU2v67B++Sv304wiJB)5@+fI9k$iPKz@4DkV5vf;s6tIMrj+b<9Qvr%Ti-PsO-a z>1L$_=Sw=S@(il7Qu66xTum9PB(EM@S1EP0O39-~6a_w@>a9N#CJ1=*xb^0BD zcH9Ja`i-@JWq;6qwtYH?DgG2aQ1n3214R!MJy7(({|7uUMUszg7>$GEQ?#e5EO5=- zag;lZudG0?e@&L;vl~V($9<}-jBDPlVute@=m@By`V@tI&>UizCrL3m;W3tV!0s~* zzr@UAk=2u=s2<*_hO1cKW<9*T;cA6aOR!zI2Gqowx4;& zJWj>Agyqbg^XSm1EM__LPI{b5=OVVBc}G1?#kr83LwRRCPQ|%E;jEPM4tt!6b3R(w z_$A{iDett$sTk+6>pJha$Ei5yvZWk2@1d?YoQiV}yHw!BN5?s5vn4Ay^U-lm=5^{S z2~K@p%nixpzMMU+jQA7f72+rCvD_kFJZA#Kk&I%@j1D)rDV#rrQ0(qHhX8#43 z;22kBN1K)D>flObBvPEN+UZ=JuFL}Z-#S|8&pv4LMA30$Uu0qfM zJ>C}$zK?t_`hMfP(RZ1z4ZZ^~&o|!3`>fuNp{e*&^gz)AMGq7`Q1n3214R!MJy7&O z(E~*f6g^P%z<;I(dV6eef`}_I(UW0N`i3tFl)CZndnvz16-H~ngS}l^255lK0hBn= z@9jRy08;jrIN+Cdj{efL6h1f5+pd;iMAde z{a#UN1SvCmncUC=z*dKiXJF>py+|32Z|mjdZ6fm{|i0P&1~h+ zd4IE9->9qWW+K1I6$t9;dKl4fj7FnOV|w58es|95K)+*th46ow;Rb{6Jl_ECZQd%+ zlb%)Xx7|D4Ue^Ivx%1b~8II>1tL^XF+iYLh8f_fh>et<}&-?@23RvT6 zR%27!v98vbXx-A(x)ThFMUnO$@kk;G`g73Arxzh2xz#1@isVm4}$=P z)Q3aJ8-`=k|KLjau_+>J%CPnoU1Z9lUc<@ zYE6cP?Gbp5L1<}&jz=3J$w&e;AATv(Kd-xAef9jSU8Gsv-TGJzCffA-T6gx#>+YAa z_=ql2O1c|tY6{02V7A4>Fvw(dmp>^P`(o7_8Bc%y-@^VbQoSM^YK_Ok(d5ae*tB;? zNj>`@BT^h|#DcM1HQkqm!GdT623zq#VLS(E(QtDlXgFrQ?`_Feg7qkIwfA{1P3|H+Oc(L2ipGSdSOSkLXh?)2 zvDQR1oPaQ6dHgcT+yh$@rakUmH@~ZU#Z(b(J#E32Z)N(MdvuLecyfG!s8T>4NGjDwnx5QJ!hc5m~$J$CxAy2VsokB|S@ zReh_8#UWt8jtR%WVJD3xLJ(YI3ABfpUp_zP#hR7X>ysM0DwvUAz6I37_Ki0!)8ET? zc(6hxQu&&0JH3lMJG;51u`LmXOa zo-l8-VMR(3X*X@0*;R^S(IiS+VIxE7G+q-%&(LjFjY{*|SDx8LDpxm=tQ8Op%Ac`H zPJAb7!73GmWd75v54uR@$`%X~VAl*rw>H7>aZ`Utn6bVZI(+8m-QRVQz7>sOgid0S zIuzq_vy+>0OVp(8Fmo?fAL=4~vlB7M|K;R=XW0%8 zt6Hq6x^2YiU8HJdG7hin#zL`B2og=my8!$`fD6K2)qD-Y|3eMy48F9_Kgwh6g|x`q?lS_ox@0Av0TV-&YrJZNR(j{{W^h3AV&zJHt_KUw6~q^>eWF z5=Hu|(oZ@gy*kkn0VvAt>-ODy8)j=wACtMUGr||g;w_N&he7)1KiV`4OYcifuYO?4 z9i5UMZh=Igj>tcDxV8q%?@#4Vx&Dmaosqv3z0{ouCt*+I_W5SDY?+A_lu-qf15f$gx;}FbXd*JqY-|iKv#ySR39h2_-!|2ZFSQ$gF#0xczO)>BlQu6pEp&1$_ zRX6SZrZY;GHHM?XU9pz7+;Dis4O>Kww<=$~l<$m^B@q~j`qntSXdgop*6Vy{!*r}e zS!Qsso$0~+M6A9EbpVFJ^~q}+rfRGo`C;?W z&d6T|#>eVoO(1>GtDB~1tRLxUtM82TS+SjMO~GdD9oHP=hRGW1%lj5`_H+B3&ptJ1q7A@rxg%E*Hl)UuHNYhfaP!VI zVb1Ku)r)4AttzWRM8gy!>De|)gh{5vE5S^Qq$J}8!{=Xg@2Z@KEzrs-$h6Of>_8tL zHcJZf=zXZE%Q8r)+W_9!9)$8p6BJ8=p%4U(DD0S)=QFJnaA%d=$6)x^iZga~(QZ8p ziqjAYiC!p^K!FHSuIm1i;^T3D75L%%iL}3qlrC#+Y9^=>?pPt13*g6zXPQsPIu-a~ zelqbz7wKG@NQPrKTm@6e1dP1#);c8V!fGg62)V;zO`zX2BZ1edzM*IpT;cfIak*oh{ds$f-D|tew$S>a^#bc@ zmfu;z7K8aZ^K{d3lVmD0erJ5ac$+Z`;)*{-4=^6^M*%_@hj8}X$&(L)4Pl5jLK_6u zgmFkSYObKogUV4eKF~2)5GGUzqu|d;rXfvgvOtZBY%C_5U>dSjP1b)sOEw-$8xPXX zQj?V?RAgA%_z9*>5m=pONkP9grtRB1g&!fP$LgU_5Q0k9u%|aPV)+Vok3{$Ut26Rz z;3hlJ5a;&w`{!jF8?bZ*KQ3Fgy;Ima*pv*Ty#k#_I%4b&q8_deSx%isVAageYEx={Dv<_%g6mLKiwA`NpvL+!!Z^%^JD2R7f| z84cCVFiGhs559NPnOK3c5H=*NTD;?8tnWuzJE zOi6ft2-CFmoQ1))Sb-8#&%C3$Q`2Y(z!%6iqflf=71z?rSJt0_RVYtSmZ#6|RM>8W zf+c=>((}!d;2Mqn%SUt{-5Cerf_Fnx8$bl)qMlEVsa>rZgJu0L*xnfxv(a{g9)u$Y z^^|Vgv)=LCN3# zym1-Upkyv{Mt{^P7tP<&3J(w=@q&H-+w*IeYDQp=t+rF*<%d{+tHA#5A2)7Tf)yxv z-K^i2ZtBbk%z^rIFxm#=+x_Z~H!a4}l?giQ$_?*!MtU_=W1A!JWB^%z$?3I=H13&| z8dljE`S8F8irVO~BT{g|icUqjM6jtj3?(@9*r)sYw%`IRUx}hMJ-%Gh znGRHk!m!atqVU)rPoeV1HqOT?lo?v%+5Ki`R4j$+Xl#``tU-tKH+>-Cdu$o^{>sy3iGI&2pF5s)+~&9lz7@F0F%nJ_d~AQleuw=Ms3t74kF$5TeQtZscDwB& z+gY}GwqZ7_^&RVD*6XZ$tedP;tphA4EU#OBW4YFHj%AZ&x+MS=hquf}%m>YqIcTmn zmzg=JK0IQ&#LKcZTt$V5O*6dF*X|)8Ox0h?mg}a?s`t*YPo4#Kj;U4jk{dK+wcn1oYHfeNTmT*Ey$ zaLb+d3-Lk}P^PqqTT??ve82vBVOs$TR8q8xEz*L%Pnmuvv=pE~)jzwqUDgsSK!K`s ziWUUGO%}DKsHSETH_KWO2G65_>KCO5Aoy*vI8?nwl`3%#F(ZJ0x0V3CsF5QO5aibC z_y*pqFpKqaPa=gV;LQiGn68%i-s=tvjRh#s8wylLprL>nU&D(7)QtK9 zIId02s4XA@9j>PSN09cdD2~Qj?pG2$Yk}e%wtE#4=MYKJa%+caEN%-wiE9?+J6MU zJii^z^*P0}N$l`1%M*{z;ZgBR^V#9V9JP*LlGlz-xV4G*K69{}w4fiqIKLf^rBU_5 zBGk?XmBR)HdSW_U{LQ6bENVIT!@xpJ!3^$U@_%P@wfr&EQ2u!LIkiWWCG2;-}}eqxDXW^iRX>?2z_`^_=qqKQ)gXtw)!501f7d zi~Lja*wKmc9J_yVelsjr+B_+*86AkuHS_2=i@I-UIV!fJlPo4PYdc-d+Gm%JtnFQf-&V9TEvcw)d?>x9z^QQ!=$zH;kBgZspUVFf5i26mS0 zv!MkjP=s-c+hrL;3Q&*?ET?5~AqvRA%wkZsbWkA*2tt%1Fc4EP^Y2b(K-NP{%kzUTK!F08GC%xA3SHdF?1Bd&NCuJ@P&B+i?yihXuZSemlf$ zx)%N2a69X2oP)_7;C*@QBnQih_vW>un7>ZE`ToH-{@1V*eovlw9P@MH-TCYg^L^sp zoB#0i`W`F&t~_>}qRH%jXMQu<6LQUt{AQHF<&@j=l%p+!E^OYG*N(OfI+1y6UOU<| zCW!}b8oInB_A}m+-wu0*N8J6^+E?!Q=u*EKx3jLtDO}DxQ$9OvDK2qmtXn?_P5~os zXV($hQVb7@zrJwGf=FsF&*cf=U{9e_2jTxX=QH@;^gRq`0CxIT!_EIC-Y>l`cn^86 zg7W}ty;X1~;9Jj2p8GxfJlj31Jrg|L-JiIhcHiP|cZb~7?ttrr>t)w{uFG99*Amw# zm)rTF^C{=8&I_E4&biKEFg))$o^;&k$U5pAvm9miAMCH&581D@x7t_O$JpJrzuBI& z-C#@EYHd?(eXZYEU$EY7z1X_dI?p=PYPP&>Ic)hEVE+x4sh0lc@6E56A29#a95*jD zk1{(=@0lJqU1!>3+GLt$8esh1_^R=c@ham^;~B;(V=4D7_Y!wMcLkT^R&nE?lmGrF zAZfrO+|+0=;MKh5vbmGb|HBbM(x697ftIsFydcz4_R0q@`y~t?l{^DT(0UeS5xj)a zqq5%7b&zm))g-oj^!3(vuep?$FnUxIz=F4mdvgRBJgN!sikBt$C5#e0ZHa)7d6Nc2yiw>y{v(b(2kZS9VTAVU`IrN;nhVIS2@bf zpYf6gJR$;Eeatu!^hm)o5TNBZP`v58^>>Wh_%tsO{HP*;({&e*UKHx{+i@2O62_5g5}a+B#Q%bJAQB`DCAB1Q6455! z_THpt6W6>aNEl6ONg&i!r4}2r4ug#Y;(t0uqLm z8X*|w&@O9$CF-&PWd|1V7dcBb$P$y_>_8S0kO;J7W+({x9QO8{t$qnZOLmUeqGgzC z=Oqj**+o{1=CD<~nK;!iVO*&afab6w0K-a^05rkqsPGbol_~->e;5J`E7b%re<(pf zBB+w-4OwO%CDG$F{V}sr2IxPl+%N8riKLN{0s@kni>+6^jpN8eejPUVZ5m!L0LZ| z1w&3P2`;=g{q6qrvH>3m5{8{x63F|hlz@bhr>4(1@uvfXv8RRt7bxgF!01z>2305= zV)o8?f8O2ePC>!|R6{~)tBIWBG#C^vCx)d7sl8dGBm{)2CLCV9!^NBLS@_PLKKBG9 z0zy^O$$(ccwN?W{u^#kJ3F8!kLe)a>0;fVWC=?4J$-6ue0uq6tY9V;Pr$Pt{RdL0#y^>{a&6#ehC9m zl?iyimrd|X7=EhS@qSO+G5A!qb7toN5BR z-^(WO5{8^A0u--@h&RsPedk|#&*vo!In@LZubCy5hd7UtXgowbbVqvn!=IidNO_R+ zD0w#3C?1omd=kN&bWXxu;6MUl@-*>bQmZPH21RaXb)!YIS2A>)VTyw}(EhP*;HEK|7qLnj2!U$AL0>Q~5UPL-1NEn4` zNYwRH2?J4$DXIdhgrTTb2xJz0#JfomR**0p)sUd|PEFw@f=F5St81td!K5q!0_?Ps z=a=$O=~1?d>X!&CrC|x&j+a}mQYq!Z(xYg(ImD~Je(&sMt{?d&f=g8b*gC63aH*;t zr7p4pzm$hdkE$xIQXVipsxGxk1evl5RJB$q511ZBtJNd^oXl}vGH8+OQIb5#)$-Ck z1o}GYBiy6t?KCdLpPSE!SFy~)7V${&Fey>X32pg8a2Zy4sJpWe1unzNPnU!p1u0M&Huq3>dp?C+ zhTTgZ`(pfW_`=|O!*|Gcr7!7Q?i=lMdq40#>AeA-{%`h9^Y-)n-SeX79?vD7X3s*; zX&#&VJ@>Qj+uc8QH@O$NN4V{-cU+IT4!X{9o$0D_^>lvje9n1?^T*C6=L+XIXE(=Z zaD(8Tj*A^p$707QhsXYr{b~Cz?dRL;?X&D*u;|_A?a_hN?TrcP({t;3b7b@cipLBpKDr9XoF+9IK zd-d!iLJA{8EeT|83<<`DS`rA1R&mSp2d*sLyk1CQbf_hPa;;IExAH(TP(C=2!uU{$ zSlAXEJSP$gAw>Wp4JCvEf+wR#gAfS`1ke6rrv2gzzFX8Fq%;T-lc3<~5?g+K&Vd)3 zZxK=&gh)srv!ja2QUoE=c}+-A)%ITT?tV}EZ}?!1kRlLKZ7)jgm`)RnNJ9e_gA2E` z(*z=_g^=t|_MDK?U_>m06n7~J!H60ufB;S6irf$pkf8KPNSn;QU(5;dcUGDO-T zA%%gWh6HUHbO87ifr_jmv}IV}{h#xe5B>UMKBd8m&>xZ`%69N64OT=1u&4AC&&^5D zU`0d#IU*fCK83NOlAIs{Cuv~L+w;?4Jd{Q0LhJ?~Fpkf@e`HZEBLpTY=HWdg$7rJ}UE z-__e2jQ$kHhbjTMTr3Olr!YEHx1)M7ZO711-Hr;z)BubNRR*A)kMSZ#g(?EH^U+Di zr!Xc|5umMarg&BFsj(x2&*4)T5vmCwQSB$D$w2v27!Rs!#8qQzBSwR20k8#n#a0sF z0x1jzRpWs6K*Jm2eTK0&O@DtnpTbyBB?1+Wshs#kRm{kE(=5=SFYMX#IBDf3n>i}BqUHZh>FjIjklF%j6#Ya zL5&nhhbN1V{IFy6p3{F@mLgD)PCP6Hr^6SD$1ZP~^4iU33MqmG)nZ6Gye-!y4H(2? zNO?;p38XL>R6;r-K^e2`mp}@`K@9~C`qXn64=Mo#%ODvubqhv>S`wTwXE#4AbniD- zNMTHFX}Ls(*PkK?k)6{xEtduOQv@Kg z?Kr$q1sZ$^3Q&0Si3jaJ?&E&p7ycB%hbjRmx={fb9xAI234rKk6loVRI8;_X5a7I= z3c$!vC4l7R@`(FW7#FGp;Jlm)z?e`afaK*@lO@ZiFd|eFKyb2(7mx*8n!-grAw_gLf?Erbz^+T5EDF+Dg-Br69W35Lo-zwkqyPy4N!0m`1xQE%TqZ&I ze;emf@c%O3NT0*|uJ^*H?+K$=owq0tA*%sM`!`c78SdUn*wVrKVXRWaIuzYHH+H#BKJWHLW+QP%r z|Ci18nJ+iT%nQxK%x2TuaPI$V(+<-r(|A)4K%h!O(s@YmI&~6~CPf=h%Six1UJn6|rZ zpOD5dP%TET5jOAJI4rWDmypIlP)h+?bPs(V&_H=R4iRa|lUU z8pA=gz2vy2OMK+D7f$Qh$o#l5~E*dAK2_|F)8tg^; zj#aED!z83NkPu5j*%#wH4J0Hau=7~NE$4hU@w#Uh3uyugHHvT{a53?3Ag#fKSPI63 z({h8P!GweYAKj#SG?@^J#(* z*|~zY4~9Sk5kUglKe~&1Vvqjg_?r*#X#x>d5^x<*p45C=gAtJg*kIh^b~5YvG{K0h z1X2f-JIbduAQ2>xI-u+lQsC$1SzW8Q5la~fPo^rj~_&Plv9k8Ma!o#PE-+~ zJ<2FjCt#GQB0!teXz>cN*7!8Wh-w1Zq{paj15&H&|XCYdmv4qA>*e5nlfIRAVX%XfC6n*w7M2Z zYoH-~I$M6vM=mP}X$%e7rEwq!sdKfcG)9M762LXv#Ai>R`tic`bwV2BLoEs5nriXr zrvG}?^Uho$jUl3jL{-EKq%cTSfGo0>oMOvao5E;OBLszglPFsoNMXRJ6{0Hh5yYtS ztO275s)hhYm1hm)r6DO-a3qLPO`@scX&@u+4ub!*Y9ypIkdcr8nh1z@U4|VOND;`W zwpLxk(;!AHL|wzvAVy4q;-6WR`@^R&Vr1vz0d@ME!g!Hg69-i3a|(k+l>ij}=)m|> z7%Qp;FzGX&!bnji0EM3J;?K)p=wJQtE&de7i7Em3xVk)Qd4V7)g-CD`OdnFOFF-<)VA}073y`2-=o7a;8{YlK#5jV*Ny9(L`TwhY+kGp2W8q5x zA9{c9y%C=O*LtUV`vU%d!E?9#{C_w+|9{8*nEN{S9`{D~RCj;ZKj5Cg`(0PK60YU0 zF)k0B{{Ox6CTG?ea#lOboSfq=#}UUt$6iORV>*0X?w|HI><`}@G$M%iw zPqzDQ`)u27t8Ei(J*{8C`Tu*Yms_`4ms`hKyIDT7JZHJnaP1{=NAo zbGtcgo@E|vHktlxItp(9NT$uE879GGFdjEPV!YOPj&Y-Ls&N2!f_t5Nh}+NY;?CqI zbA6$sxgURqU`!hD;0l15aL+$|c{Zbgn9z=H>Zh;e`!fV$vI5Xm`#Ayr3;~*KJGv=f zX(u?7ZAZ7<=i2#<24;c*=z@A`0H47yQ(2=xfG(G(1pW*LnMxc%1aLEaPJ=�j8=Q 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 diff --git a/tests/testthat/setup.R b/tests/testthat/setup.R index 7c668d9d..aa197e3b 100644 --- a/tests/testthat/setup.R +++ b/tests/testthat/setup.R @@ -57,7 +57,7 @@ resultDatabaseSettingsPlp <- list( # =========== characterization START -serverCharacterization <- "../resources/characterizationDatabase/databaseFile.sqlite" +serverCharacterization <- "../resources/cDatabase/databaseFile.sqlite" connectionDetailsCharacterization <- DatabaseConnector::createConnectionDetails( dbms = 'sqlite', server = serverCharacterization @@ -80,6 +80,7 @@ resultDatabaseSettingsCharacterization <- list( ) + # =========== Characterization END diff --git a/tests/testthat/test-characterization-aggregate-features.R b/tests/testthat/test-characterization-aggregate-features.R deleted file mode 100644 index 5b6633e4..00000000 --- a/tests/testthat/test-characterization-aggregate-features.R +++ /dev/null @@ -1,33 +0,0 @@ -context("characterization-aggregateFeatures") - -shiny::testServer( - app = characterizationAggregateFeaturesServer, - args = list( - connectionHandler = connectionHandlerCharacterization , - resultDatabaseSettings = resultDatabaseSettingsCharacterization - ), - expr = { - - # make sure options returns a list - testthat::expect_true(class(options) == 'list') - testthat::expect_true(length(options) >0 ) - - # check setting and generating works - session$setInputs(`input-selection_tarIds` = options$tars[1]) - session$setInputs(`input-selection_targetIds` = options$targets[1]) - session$setInputs(`input-selection_outcomeIds` = options$outcomes[1]) - session$setInputs(`input-selection_database` = 'eunomia') - session$setInputs(`input-selection_index` = 'T') - session$setInputs(`input-selection_firstO` = T) - session$setInputs(`input-selection_generate` = TRUE) - - testthat::expect_true(!is.null(allData)) - - }) - - -test_that("Test characterizationAggregateFeatures ui", { - # Test ui - ui <- characterizationAggregateFeaturesViewer(id = 'viewer') - checkmate::expect_list(ui) -}) diff --git a/tests/testthat/test-characterization-caseSeries.R b/tests/testthat/test-characterization-caseSeries.R new file mode 100644 index 00000000..fb6c3a12 --- /dev/null +++ b/tests/testthat/test-characterization-caseSeries.R @@ -0,0 +1,76 @@ +context("characterization-caseSeries") + +shiny::testServer( + app = characterizationCaseSeriesServer, + args = list( + connectionHandler = connectionHandlerCharacterization , + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + targetId = shiny::reactive(1), #reactive + outcomeId = shiny::reactive(3) + ), + expr = { + + # make sure options returns a list + testthat::expect_true(class(options()) == 'list') + testthat::expect_true(length(options()$databaseIds) > 0 ) + testthat::expect_true(length(options()$tarInds) > 0 ) + + testthat::expect_true(inherits(selected(), 'NULL')) + + # check setting and generating works + session$setInputs(tarInd = options()$tarInds[1]) + session$setInputs(databaseId = options()$databaseIds[1]) + session$setInputs(generate = TRUE) + + testthat::expect_true(inherits(selected(), 'data.frame')) + + data <- characterizationGetCaseSeriesData( + connectionHandler = connectionHandlerCharacterization , + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + targetId = 1, + outcomeId = 3, + databaseId = options()$databaseIds[1], + tar = list( + riskWindowStart = 1, + riskWindowEnd = 365, + startAnchor = 'cohort start', + endAnchor = 'cohort start' + ) + ) + + testthat::expect_true(inherits(data, 'list')) + testthat::expect_true(nrow(data$binary) > 0 ) + testthat::expect_true(nrow(data$continuous) > 0 ) + + }) + + +test_that("Test characterizationCaseSeriesViewer ui", { + # Test ui + ui <- characterizationCaseSeriesViewer(id = 'viewer') + checkmate::expect_list(ui) +}) + +test_that("Test characterizationGetCaseSeriesOptions", { +options <- characterizationGetCaseSeriesOptions( + connectionHandler = connectionHandlerCharacterization , + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + targetId = 2, + outcomeId = 3 +) + +testthat::expect_true(inherits(options, 'list')) + +}) + +test_that("Test colDefsBinary", { + colDefs <- colDefsBinary('test') + testthat::expect_true(inherits( colDefs, 'list')) + testthat::expect_true(length(colDefs) > 0 ) +}) + +test_that("Test colDefsContinuous", { + colDefs <- colDefsContinuous('test') + testthat::expect_true(inherits( colDefs, 'list')) + testthat::expect_true(length(colDefs) > 0 ) +}) diff --git a/tests/testthat/test-characterization-cohorts.R b/tests/testthat/test-characterization-cohorts.R index de1b391a..6c2cb87f 100644 --- a/tests/testthat/test-characterization-cohorts.R +++ b/tests/testthat/test-characterization-cohorts.R @@ -1,34 +1,104 @@ context("characterization-cohorts") +options <- characterizationGetOptions( + connectionHandler = connectionHandlerCharacterization, + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + includeAggregate = T, + includeIncidence = T +) +parents <- characterizationGetParents(options) + + shiny::testServer( - app = characterizationTableServer, + app = characterizationCohortComparisonServer, args = list( connectionHandler = connectionHandlerCharacterization, - resultDatabaseSettings = resultDatabaseSettingsCharacterization + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + options = options, + parents = parents, + parentIndex = shiny::reactive(1), # reactive + subTargetId = shiny::reactive(1) # reactive ), expr = { + testthat::expect_true(inherits(inputVals(), 'list')) + testthat::expect_true(length(inputVals()$databaseIds) > 0) - # make sure options returns a data.frame - testthat::expect_true(class(inputVals) == 'list') - testthat::expect_true(!is.null(inputVals$cohortIds) ) - testthat::expect_true(!is.null(inputVals$databaseIds) ) + inputTests <- characterizationGetCohortsInputs( + connectionHandler = connectionHandlerCharacterization, + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + targetId = shiny::reactive(3) + ) + testthat::expect_true(inherits(inputTests, 'list')) - # checl generate does not crash app - session$setInputs(targetIds = c(1,3)) - session$setInputs(databaseId = 'eunomia') - session$setInputs(generate = T) - # check input$columnSelect works without error - session$setInputs(columnSelect = 'countValue') - session$setInputs(columnSelect = 'averageValue') - session$setInputs(columnSelect = c('averageValue','countValue')) - + # set inputs + session$setInputs( + comparatorGroup = parents[2], + comparatorId = comparatorOptions[1], + databaseId = inputVals()$databaseIds[1] + ) + testthat::expect_true(comparatorIndex() == 2) + testthat::expect_true(comparatorGroups() == characterizationGetChildren(options, comparatorIndex())) + + session$setInputs( + comparatorId = comparatorGroups()[1] + ) + session$setInputs( + generate = T + ) + + testthat::expect_true(inherits(selected(),'data.frame')) + + resultTable <- characterizatonGetCohortData( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = c(1,2), + databaseIds = input$databaseId, + minThreshold = 0.01, + addSMD = T + ) + testthat::expect_true(nrow(resultTable) > 0) + + countTable <- characterizatonGetCohortCounts( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = c(1,2), + databaseIds = input$databaseId + ) + testthat::expect_true(nrow(countTable) > 0) + + + continuousTable <- characterizatonGetCohortComparisonDataContinuous( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = c(1,2), + databaseIds = input$databaseId + ) + testthat::expect_true(nrow(continuousTable) > 0) + }) test_that("Test characterizationTable ui", { # Test ui - ui <- characterizationTableViewer(id = 'viewer') + ui <- characterizationCohortComparisonViewer(id = 'viewer') checkmate::expect_list(ui) }) + + +test_that("Test characterizationCohortsColumns", { + cols <- characterizationCohortsColumns() + testthat::expect_true(inherits(cols, 'list')) +}) + +test_that("Test characteriationCountTableColDefs", { + cols <- characteriationCountTableColDefs() + testthat::expect_true(inherits(cols, 'list')) +}) + +test_that("Test characterizationCohortsColumnsContinuous", { + cols <- characterizationCohortsColumnsContinuous() + testthat::expect_true(inherits(cols, 'list')) +}) + diff --git a/tests/testthat/test-characterization-database.R b/tests/testthat/test-characterization-database.R new file mode 100644 index 00000000..9791f023 --- /dev/null +++ b/tests/testthat/test-characterization-database.R @@ -0,0 +1,85 @@ +context("characterization-database") + +options <- characterizationGetOptions( + connectionHandler = connectionHandlerCharacterization, + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + includeAggregate = T, + includeIncidence = T +) +parents <- characterizationGetParents(options) + + +shiny::testServer( + app = characterizationDatabaseComparisonServer, + args = list( + connectionHandler = connectionHandlerCharacterization, + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + options = options, + parents = parents, + parentIndex = shiny::reactive(1), # reactive + subTargetId = shiny::reactive(1) # reactive + ), + expr = { + + testthat::expect_true(inherits(inputVals(), 'list')) + testthat::expect_true(length(inputVals()$databaseIds) > 0) + + inputTests <- characterizationGetCohortsInputs( + connectionHandler = connectionHandlerCharacterization, + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + targetId = shiny::reactive(3) + ) + testthat::expect_true(inherits(inputTests, 'list')) + + + # set inputs + session$setInputs( + databaseIds = inputVals()$databaseIds, + minThreshold = 0.02 + ) + + session$setInputs( + generate = T + ) + + testthat::expect_true(inherits(selected(),'data.frame')) + + resultTable <- characterizatonGetDatabaseComparisonData( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = c(1), + databaseIds = input$databaseIds, + minThreshold = 0.02 + ) + testthat::expect_true(inherits(resultTable$table , 'data.frame')) + testthat::expect_true(nrow(resultTable$table ) > 0) + testthat::expect_true(inherits(resultTable$databaseNames , 'data.frame')) + testthat::expect_true(nrow(resultTable$databaseNames ) > 0) + + countTable <- characterizatonGetCohortCounts( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = c(1), + databaseIds = input$databaseIds + ) + testthat::expect_true(nrow(countTable) > 0) + + + continuousTable <- characterizatonGetCohortComparisonDataContinuous( + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings, + targetIds = c(1), + databaseIds = input$databaseIds, + pivot = F + ) + testthat::expect_true(nrow(continuousTable) > 0) + + + }) + +test_that("Test characterizationDatabaseComparison ui", { + # Test ui + ui <- characterizationDatabaseComparisonViewer(id = 'viewer') + checkmate::expect_list(ui) +}) + diff --git a/tests/testthat/test-characterization-dechallengeRechallenge.R b/tests/testthat/test-characterization-dechallengeRechallenge.R index 68c98ab7..2adf8dd0 100644 --- a/tests/testthat/test-characterization-dechallengeRechallenge.R +++ b/tests/testthat/test-characterization-dechallengeRechallenge.R @@ -4,24 +4,35 @@ shiny::testServer( app = characterizationDechallengeRechallengeServer, args = list( connectionHandler = connectionHandlerCharacterization, - resultDatabaseSettings = resultDatabaseSettingsCharacterization + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + targetId = shiny::reactive(1), + outcomeId = shiny::reactive(3) ), expr = { - # make sure bothIds returns a list - testthat::expect_true(class(bothIds) == 'list') - testthat::expect_true(!is.null(bothIds$outcomeIds) ) - - # checl targetId does not crash app - ##session$setInputs(targetId = names(bothIds$outcomeIds)[1]) + # options() is a list + testthat::expect_true(inherits(options(), 'list')) + + # allData nrows > 0 + testthat::expect_true(nrow(allData()) > 0 ) + + # targetUniquePeople(), outcomeUniquePeople() numbers + testthat::expect_true(inherits(targetUniquePeople(), "logical")) + testthat::expect_true(inherits(outcomeUniquePeople(), "logical")) + + # characteriationDechalRechalColDefs is a list + testthat::expect_true(inherits(characteriationDechalRechalColDefs(), 'list')) + + # failData NULL + testthat::expect_true(is.null(failData())) + + # tableOutputs$actionCount() + # failData not NULL + + + # add tests for functions with progress bar - # test setting inputs - not sure this works - session$setInputs(`input-selection_targetId` = names(bothIds$targetIds)[1]) - session$setInputs(`input-selection_outcomeId` = names(bothIds$outcomeIds)[1]) - session$setInputs(`input-selection_generate` = TRUE) - # check allData sets these reactices - ##testthat::expect_true(!is.null(allData())) }) diff --git a/tests/testthat/test-characterization-incidence.R b/tests/testthat/test-characterization-incidence.R index 585ede25..48d4fe65 100644 --- a/tests/testthat/test-characterization-incidence.R +++ b/tests/testthat/test-characterization-incidence.R @@ -1,30 +1,88 @@ context("characterization-incidence") +options <- characterizationGetOptions( + connectionHandler = connectionHandlerCharacterization, + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + includeAggregate = T, + includeIncidence = T +) +parents <- characterizationGetParents(options) + + shiny::testServer( app = characterizationIncidenceServer, args = list( connectionHandler = connectionHandlerCharacterization, - resultDatabaseSettings = resultDatabaseSettingsCharacterization + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + options = options, + parents = parents, + parentIndex = shiny::reactive(1), # reactive + outcomes = shiny::reactive(3), # reactive + targetIds = shiny::reactive(1) # reactive ), expr = { - # make sure options is a list - testthat::expect_true(class(options) == 'list') - testthat::expect_true(!is.null(options$targetIds)) - testthat::expect_true(!is.null(options$outcomeIds)) - # check input$generate does not crash app # need to test generate in ns("input-selection") - session$setInputs(`input-selection_generate` = 1) + session$setInputs( + outcomeIds = outcomes()[1], + databaseSelector = databases, + ageIds = ages, + sexIds = sex, + startYears = startYear[1], + tars = sortedTars[1] + ) + + # before generation the reactives should be NULL + testthat::expect_true(is.null(incidenceRateTarFilter())) + testthat::expect_true(is.null(incidenceRateCalendarFilter())) + testthat::expect_true(is.null(incidenceRateAgeFilter())) + testthat::expect_true(is.null(incidenceRateGenderFilter())) + testthat::expect_true(is.null(incidenceRateDbFilter())) + testthat::expect_true(is.null(outcomeIds())) + + session$setInputs(generate = T) + + # when generate is true the reactives should be populated + testthat::expect_true(!is.null(incidenceRateTarFilter())) + testthat::expect_true(!is.null(incidenceRateCalendarFilter())) + testthat::expect_true(!is.null(incidenceRateAgeFilter())) + testthat::expect_true(!is.null(incidenceRateGenderFilter())) + testthat::expect_true(!is.null(incidenceRateDbFilter())) + testthat::expect_true(!is.null(outcomeIds())) + + testthat::expect_true(outcomeIds() == outcomes()[1]) + + testthat::expect_true(inherits(options, 'list')) + + # should have results after generate + testthat::expect_true(!is.null(extractedData())) + idata <- getIncidenceData( - targetIds = options$targetIds[1], - outcomeIds = options$outcomeIds[1], + targetIds = targetIds(), + outcomeIds = outcomes()[1], connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings ) testthat::expect_is(idata, 'data.frame') + idata <- getIncidenceData( + targetIds = NULL, + outcomeIds = outcomes()[1], + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings + ) + testthat::expect_is(idata, 'NULL') + + idata <- getIncidenceData( + targetIds = 1, + outcomeIds = NULL, + connectionHandler = connectionHandler, + resultDatabaseSettings = resultDatabaseSettings + ) + testthat::expect_is(idata, 'NULL') + }) diff --git a/tests/testthat/test-characterization-main.R b/tests/testthat/test-characterization-main.R index 5cf9dcdd..e0750731 100644 --- a/tests/testthat/test-characterization-main.R +++ b/tests/testthat/test-characterization-main.R @@ -10,25 +10,83 @@ shiny::testServer( testthat::expect_true(inherits(connectionHandler,"ConnectionHandler")) - session$setInputs(mainPanel = 'Target Viewer') - testthat::expect_true(input$mainPanel == 'Target Viewer') + testthat::expect_true(length(charTypes)>0) + testthat::expect_true(length(options)>0) - testthat::expect_true(previouslyLoaded() == c('Target Viewer')) + testthat::expect_equal(parentIndex(), 1) - session$setInputs(mainPanel = 'Outcome Stratified') - testthat::expect_true(input$mainPanel == 'Outcome Stratified') - testthat::expect_true(sum(previouslyLoaded() %in% c('Target Viewer','Outcome Stratified')) == 2) + # check the target selection + session$setInputs( + targetId = parents[2], + subTargetId = characterizationGetChildren(options,2)[1] + ) + # generate + session$setInputs(targetSelect = T) - session$setInputs(mainPanel = 'Incidence Rate') - testthat::expect_true(input$mainPanel == 'Incidence Rate') + testthat::expect_true(inherits(targetSelected(),'data.frame')) + testthat::expect_equal(subTargetId(), characterizationGetChildren(options,2)[1]) + testthat::expect_true(length(outcomes())>0) - session$setInputs(mainPanel = 'Time To Event') - testthat::expect_true(input$mainPanel == 'Time To Event') + # check outcomeSelect + session$setInputs(outcomeId = outcomes()[1]) + session$setInputs(outcomeSelect = T) + testthat::expect_true(inherits(outcomeSelected(),'data.frame')) + testthat::expect_true(nrow(outcomeSelected()) == 1) + testthat::expect_equal(outcomeId(), outcomes()[1]) - session$setInputs(mainPanel = 'Dechallenge Rechallenge') - testthat::expect_true(input$mainPanel == 'Dechallenge Rechallenge') + # check mainPanel + testthat::expect_true(mainPanel() == 'None') + testthat::expect_true(!"Cohort Comparison" %in% previouslyLoaded()) + session$setInputs( + mainPanel = "Cohort Summary", + cohortSummaryPanel = 'Cohort Comparison' + ) + testthat::expect_true(mainPanel() == "Cohort Summary") + testthat::expect_true(cohortSummaryPanel() == 'Cohort Comparison') + testthat::expect_true("Cohort Comparison" %in% previouslyLoaded()) + + session$setInputs( + mainPanel = "Cohort Summary", + cohortSummaryPanel = 'Database Comparison' + ) + testthat::expect_true(cohortSummaryPanel() == 'Database Comparison') + testthat::expect_true('Database Comparison' %in% previouslyLoaded()) + + session$setInputs( + mainPanel = "Exposed Cases Summary", + exposedCasesPanel = "Risk Factor" + ) + testthat::expect_true(currentTab() == "Risk Factor") + testthat::expect_true("Risk Factor" %in% previouslyLoaded()) + + session$setInputs( + mainPanel = "Exposed Cases Summary", + exposedCasesPanel = 'Case Series' + ) + testthat::expect_true(currentTab() == 'Case Series') + testthat::expect_true('Case Series' %in% previouslyLoaded()) + + session$setInputs( + mainPanel = "Exposed Cases Summary", + exposedCasesPanel = 'Time-to-event' + ) + testthat::expect_true(currentTab() == 'Time-to-event') + testthat::expect_true('Time-to-event' %in% previouslyLoaded()) + + session$setInputs( + mainPanel = "Exposed Cases Summary", + exposedCasesPanel = 'Dechallenge Rechallenge' + ) + testthat::expect_true(currentTab() == 'Dechallenge Rechallenge') + testthat::expect_true('Dechallenge Rechallenge' %in% previouslyLoaded()) + + session$setInputs( + mainPanel = "Cohort Incidence" + ) + testthat::expect_true(currentTab() == "Cohort Incidence") + testthat::expect_true("Incidence Results" %in% previouslyLoaded()) }) @@ -47,6 +105,65 @@ test_that("getCharacterizationTypes", { resultDatabaseSettings = resultDatabaseSettingsCharacterization ) - testthat::expect_is(types, 'character') + testthat::expect_is(types$mainPanel, 'character') + testthat::expect_is(types$subPanel, 'character') }) + +test_that("characterizationGetOptions", { +options <- characterizationGetOptions( + connectionHandler = connectionHandlerCharacterization, + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + includeAggregate = T, + includeIncidence = T +) + +testthat::expect_true(inherits(options, 'list')) +testthat::expect_true(sum(c('cohortName','cohortId','children') %in% names(options[[1]])) == 3) + +}) + + +test_that("characterizationGetParents", { + options <- characterizationGetOptions( + connectionHandler = connectionHandlerCharacterization, + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + includeAggregate = T, + includeIncidence = T + ) + + parents <- characterizationGetParents(options) + testthat::expect_true(inherits(parents, 'numeric')) + testthat::expect_true(length(names(parents)) == length(parents)) + + testthat::expect_true(length(options) == length(parents)) +}) + +test_that("characterizationGetChildren", { + options <- characterizationGetOptions( + connectionHandler = connectionHandlerCharacterization, + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + includeAggregate = T, + includeIncidence = T + ) + + children <- characterizationGetChildren(options, 1) + testthat::expect_true(length(children) > 0 ) + testthat::expect_true(inherits(children, 'numeric')) + testthat::expect_true(length(names(children)) == length(children)) + +}) + +test_that("characterizationGetOutcomes", { + options <- characterizationGetOptions( + connectionHandler = connectionHandlerCharacterization, + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + includeAggregate = T, + includeIncidence = T + ) + + outcomes <- characterizationGetOutcomes(options, 1) + testthat::expect_true(inherits(outcomes, 'numeric')) + testthat::expect_true(length(names(outcomes)) == length(outcomes)) + + }) diff --git a/tests/testthat/test-characterization-riskFactors.R b/tests/testthat/test-characterization-riskFactors.R new file mode 100644 index 00000000..3ac620c8 --- /dev/null +++ b/tests/testthat/test-characterization-riskFactors.R @@ -0,0 +1,69 @@ +context("characterization-riskFactors") + +shiny::testServer( + app = characterizationRiskFactorServer, + args = list( + connectionHandler = connectionHandlerCharacterization , + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + targetId = shiny::reactive(1), #reactive + outcomeId = shiny::reactive(3) + ), + expr = { + + # make sure options returns a list + testthat::expect_true(class(options()) == 'list') + testthat::expect_true(length(options()$databaseIds) >0 ) + testthat::expect_true(length(options()$tarInds) >0 ) + + testthat::expect_true(inherits(selected(), 'NULL')) + + # check setting and generating works + session$setInputs(tarInd = options()$tarInds[1]) + session$setInputs(databaseId = options()$databaseIds[1]) + session$setInputs(generate = TRUE) + + testthat::expect_true(inherits(selected(), 'data.frame')) + + #testthat::expect_true(inherits(allData, 'list')) + #testthat::expect_true( nrow(allData$binary) > 0 ) + #testthat::expect_true( nrow( allData$continuous) > 0 ) + + #Test characterizationGetRiskFactorData + data <- characterizationGetRiskFactorData( + connectionHandler = connectionHandlerCharacterization , + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + targetId = 1, + outcomeId = 3, + databaseId = 'eunomia', + tar = list( + riskWindowStart = 0, + riskWindowEnd = 365, + startAnchor = 'cohort start', + endAnchor = 'cohort start' + ) + ) + + testthat::expect_true(inherits(data, 'list')) + testthat::expect_true(nrow(data$binary) > 0 ) + testthat::expect_true(nrow(data$continuous) > 0 ) + + }) + + +test_that("Test characterizationRiskFactorViewer ui", { + # Test ui + ui <- characterizationRiskFactorViewer(id = 'viewer') + checkmate::expect_list(ui) +}) + +test_that("Test characteriationRiskFactorColDefs", { + colDefs <- characteriationRiskFactorColDefs() + testthat::expect_true(inherits( colDefs, 'list')) + testthat::expect_true(length(colDefs) > 0 ) +}) + +test_that("Test characteriationRiskFactorContColDefs", { + colDefs <- characteriationRiskFactorContColDefs() + testthat::expect_true(inherits( colDefs, 'list')) + testthat::expect_true(length(colDefs) > 0 ) +}) diff --git a/tests/testthat/test-characterization-timeToEvent.R b/tests/testthat/test-characterization-timeToEvent.R index 340a85c1..cbc93906 100644 --- a/tests/testthat/test-characterization-timeToEvent.R +++ b/tests/testthat/test-characterization-timeToEvent.R @@ -4,22 +4,41 @@ shiny::testServer( app = characterizationTimeToEventServer, args = list( connectionHandler = connectionHandlerCharacterization, - resultDatabaseSettings = resultDatabaseSettingsCharacterization + resultDatabaseSettings = resultDatabaseSettingsCharacterization, + targetId = shiny::reactive(1), + outcomeId = shiny::reactive(3) ), expr = { - # make sure bothIds returns a list - testthat::expect_true(class(bothIds) == 'list') - testthat::expect_true(!is.null(bothIds$outcomeIds) ) - + testthat::expect_true(inherits(options(), 'list')) + testthat::expect_true( nrow(allData()) > 0 ) + testthat::expect_true(inherits(characterizationTimeToEventColDefs(), 'list')) + + # check plot works + session$setInputs( + databases = unique(allData()$databaseName)[1], + times = unique(allData()$timeScale)[1], + outcomeTypes = unique(allData()$outcomeType)[1], + targetOutcomeTypes = unique(allData()$targetOutcomeType)[1] + ) - # checl targetId does not crash app - session$setInputs(targetId = names(bothIds$outcomeIds)[1]) - # check input$generate does not crash app - session$setInputs(outcomeId = 3) - session$setInputs(generate = T) + data <- getTimeToEventData( + targetId = targetId(), + outcomeId = outcomeId(), + connectionHandler = connectionHandlerCharacterization, + resultDatabaseSettings = resultDatabaseSettingsCharacterization + ) + testthat::expect_true( nrow(data) > 0 ) + plot <- plotTimeToEvent( + timeToEventData = shiny::reactive(data), + databases = unique(allData()$databaseName)[1], + times = unique(allData()$timeScale)[1], + outcomeTypes = unique(allData()$outcomeType)[1], + targetOutcomeTypes = unique(allData()$targetOutcomeType)[1] + ) + testthat::expect_true( inherits(plot, "ggplot") ) }) From f6b95f9f56398a88255443fd65ed230ce63ddeeb Mon Sep 17 00:00:00 2001 From: jreps Date: Tue, 9 Jul 2024 14:48:28 -0400 Subject: [PATCH 43/64] Update characterization-main.R removing odd code --- R/characterization-main.R | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/R/characterization-main.R b/R/characterization-main.R index f70df1a5..1647e071 100644 --- a/R/characterization-main.R +++ b/R/characterization-main.R @@ -627,18 +627,6 @@ characterizationGetOptions <- function( ) }, error = function(e){return(NULL)})) -# TODO - add tte and decha rechal? -cohorts <- connectionHandler$queryDb( -sql = " - -select distinct database_id, target_cohort_id as cohort_definition_id, cohort_type -from @schema.@c_table_prefixcohort_details -where cohort_type = 'Target' - -;", -schema = resultDatabaseSettings$schema, -c_table_prefix = resultDatabaseSettings$cTablePrefix -) TnOs <- connectionHandler$queryDb( sql = " From a0ccde7bb33b7377591feadfbcb063d8f4b5bec9 Mon Sep 17 00:00:00 2001 From: jreps Date: Wed, 10 Jul 2024 10:45:15 -0400 Subject: [PATCH 44/64] passing R check - passing tests 78% coverage - cleaning checks but still some notes --- DESCRIPTION | 2 +- NAMESPACE | 5 +- NEWS.md | 8 + R/OhdsiShinyModules.R | 4 +- R/characterization-dechallengeRechallenge.R | 4 +- R/characterization-incidence.R | 47 +- R/characterization-main.R | 2 +- R/characterization-timeToEvent.R | 21 +- R/components-data-viewer.R | 2 +- R/estimation-cohort-method-covariateBalance.R | 44 +- ...=> estimation-cohort-method-diagnostics.R} | 0 R/estimation-cohort-method-results.R | 26 + R/estimation-main.R | 24 +- R/estimation-sccs-diagnostics.R | 2 +- R/evidence-synth-cm.R | 550 ------------------ R/evidence-synth-main.R | 332 ----------- R/evidence-synth-sccs.R | 537 ----------------- R/patient-level-prediction-modelSummary.R | 5 +- extras/codeToCreateEstimationDatabase.R | 358 ++++++++++-- man/OhdsiShinyModules.Rd | 11 + ...cterizationDechallengeRechallengeServer.Rd | 4 + man/characterizationIncidenceServer.Rd | 9 +- man/characterizationTimeToEventServer.Rd | 4 + man/cohortMethodAttritionServer.Rd | 2 +- man/cohortMethodAttritionViewer.Rd | 2 +- man/cohortMethodCovariateBalanceServer.Rd | 2 +- man/cohortMethodCovariateBalanceViewer.Rd | 2 +- man/cohortMethodKaplanMeierServer.Rd | 2 +- man/cohortMethodKaplanMeierViewer.Rd | 2 +- ...rtMethodPopulationCharacteristicsServer.Rd | 3 +- ...rtMethodPopulationCharacteristicsViewer.Rd | 3 +- man/cohortMethodPowerServer.Rd | 2 +- man/cohortMethodPowerViewer.Rd | 2 +- man/cohortMethodPropensityModelServer.Rd | 2 +- man/cohortMethodPropensityModelViewer.Rd | 2 +- man/cohortMethodPropensityScoreDistServer.Rd | 3 +- man/cohortMethodPropensityScoreDistViewer.Rd | 3 +- man/cohortMethodSystematicErrorServer.Rd | 2 +- man/cohortMethodSystematicErrorViewer.Rd | 2 +- man/evidenceSynthesisHelperFile.Rd | 17 - man/evidenceSynthesisServer.Rd | 28 - man/evidenceSynthesisViewer.Rd | 20 - man/resultTableViewer.Rd | 2 + .../resources/cmDatabase/databaseFile.sqlite | Bin 372736 -> 0 bytes .../resources/esDatabase/databaseFile.sqlite | Bin 479232 -> 0 bytes .../resources/estDatabase/databaseFile.sqlite | Bin 0 -> 1236992 bytes .../sccsDatabase/databaseFile.sqlite | Bin 114688 -> 0 bytes tests/testthat/setup.R | 41 +- .../test-characterization-incidence.R | 2 - .../test-cohort-method-DiagnosticsSummary.R | 66 --- tests/testthat/test-cohort-method-main.R | 22 - ...test-estimation-cohort-method-attrition.R} | 20 +- ...timation-cohort-method-covariateBalance.R} | 17 +- ...est-estimation-cohort-method-diagnostics.R | 38 ++ ...st-estimation-cohort-method-full-result.R} | 19 +- ...st-estimation-cohort-method-kaplanMeier.R} | 8 +- .../test-estimation-cohort-method-plots.R | 82 +++ ...cohort-method-populationCharacteristics.R} | 6 +- ... => test-estimation-cohort-method-power.R} | 14 +- ...stimation-cohort-method-propensityModel.R} | 6 +- ...ation-cohort-method-propensityScoreDist.R} | 12 +- .../test-estimation-cohort-method-results.R | 78 +++ ...stimation-cohort-method-systematicError.R} | 6 +- tests/testthat/test-estimation-main.R | 94 +++ .../test-estimation-sccs-diagnostics.R | 26 + tests/testthat/test-estimation-sccs-plots.R | 78 +++ .../test-estimation-sccs-results-full.R | 205 +++++++ tests/testthat/test-estimation-sccs-results.R | 76 +++ tests/testthat/test-evidence-synth-cm.R | 94 --- tests/testthat/test-evidence-synth-main.R | 63 -- tests/testthat/test-evidence-synth-sccs.R | 75 --- tests/testthat/test-report-main.R | 4 +- tests/testthat/test-sccs-main.R | 239 -------- tests/testthat/test-sccs-results-full.R | 42 -- tests/testthat/test-sccs-results.R | 29 - 75 files changed, 1242 insertions(+), 2324 deletions(-) rename R/{estimation-cm-diagnostics.R => estimation-cohort-method-diagnostics.R} (100%) delete mode 100644 R/evidence-synth-cm.R delete mode 100644 R/evidence-synth-main.R delete mode 100644 R/evidence-synth-sccs.R create mode 100644 man/OhdsiShinyModules.Rd delete mode 100644 man/evidenceSynthesisHelperFile.Rd delete mode 100644 man/evidenceSynthesisServer.Rd delete mode 100644 man/evidenceSynthesisViewer.Rd delete mode 100644 tests/resources/cmDatabase/databaseFile.sqlite delete mode 100644 tests/resources/esDatabase/databaseFile.sqlite create mode 100644 tests/resources/estDatabase/databaseFile.sqlite delete mode 100644 tests/resources/sccsDatabase/databaseFile.sqlite delete mode 100644 tests/testthat/test-cohort-method-DiagnosticsSummary.R delete mode 100644 tests/testthat/test-cohort-method-main.R rename tests/testthat/{test-cohort-method-attrition.R => test-estimation-cohort-method-attrition.R} (60%) rename tests/testthat/{test-cohort-method-CovariateBalance.R => test-estimation-cohort-method-covariateBalance.R} (89%) create mode 100644 tests/testthat/test-estimation-cohort-method-diagnostics.R rename tests/testthat/{test-cohort-method-full-result.R => test-estimation-cohort-method-full-result.R} (50%) rename tests/testthat/{test-cohort-method-KaplanMeier.R => test-estimation-cohort-method-kaplanMeier.R} (79%) create mode 100644 tests/testthat/test-estimation-cohort-method-plots.R rename tests/testthat/{test-cohort-method-PopulationCharacteristics.R => test-estimation-cohort-method-populationCharacteristics.R} (82%) rename tests/testthat/{test-cohort-method-Power.R => test-estimation-cohort-method-power.R} (80%) rename tests/testthat/{test-cohort-method-propensityModel.R => test-estimation-cohort-method-propensityModel.R} (86%) rename tests/testthat/{test-cohort-method-PropensityScoreDist.R => test-estimation-cohort-method-propensityScoreDist.R} (80%) create mode 100644 tests/testthat/test-estimation-cohort-method-results.R rename tests/testthat/{test-cohort-method-systematicError.R => test-estimation-cohort-method-systematicError.R} (91%) create mode 100644 tests/testthat/test-estimation-main.R create mode 100644 tests/testthat/test-estimation-sccs-diagnostics.R create mode 100644 tests/testthat/test-estimation-sccs-plots.R create mode 100644 tests/testthat/test-estimation-sccs-results-full.R create mode 100644 tests/testthat/test-estimation-sccs-results.R delete mode 100644 tests/testthat/test-evidence-synth-cm.R delete mode 100644 tests/testthat/test-evidence-synth-main.R delete mode 100644 tests/testthat/test-evidence-synth-sccs.R delete mode 100644 tests/testthat/test-sccs-main.R delete mode 100644 tests/testthat/test-sccs-results-full.R delete mode 100644 tests/testthat/test-sccs-results.R diff --git a/DESCRIPTION b/DESCRIPTION index 50d599c0..37529c86 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: OhdsiShinyModules Type: Package Title: Repository of Shiny Modules for OHDSI Result Viewers -Version: 2.1.5.9000 +Version: 2.2.0 Author: Jenna Reps Maintainer: Jenna Reps Description: Install this package to access useful shiny modules for building shiny apps to explore results using the OHDSI tools . diff --git a/NAMESPACE b/NAMESPACE index f87eb69c..85521f8c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -57,9 +57,6 @@ export(datasourcesViewer) export(estimationHelperFile) export(estimationServer) export(estimationViewer) -export(evidenceSynthesisHelperFile) -export(evidenceSynthesisServer) -export(evidenceSynthesisViewer) export(getEnabledCdReports) export(getExampleConnectionDetails) export(getLogoImage) @@ -104,3 +101,5 @@ export(reportServer) export(reportViewer) export(timeDistributionsView) export(visitContextView) +importFrom(dplyr,"%>%") +importFrom(rlang,.data) diff --git a/NEWS.md b/NEWS.md index 33d8bf19..315c96d4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,11 @@ +OhdsiShinyModules v2.2.0 +======================== +- Combined cohort method, sccs and evidence synthesis into one estimation module with shared target and outcome ids +- Characterizations now share the target id +- Updated tests to get them all working +- Cleaned R check (but cohort incidence still has many notes) + + OhdsiShinyModules v2.1.5 ======================== Fixed bug of orphan concepts report not displaying diff --git a/R/OhdsiShinyModules.R b/R/OhdsiShinyModules.R index 37522c46..4aaeef44 100644 --- a/R/OhdsiShinyModules.R +++ b/R/OhdsiShinyModules.R @@ -20,8 +20,8 @@ #' #' @description A selection of shiny modules for exploring standardized OHDSI results #' -#' @docType package #' @name OhdsiShinyModules +#' @keywords internal #' @importFrom dplyr %>% #' @importFrom rlang .data - +"_PACKAGE" \ No newline at end of file diff --git a/R/characterization-dechallengeRechallenge.R b/R/characterization-dechallengeRechallenge.R index a8b01018..8b03c296 100644 --- a/R/characterization-dechallengeRechallenge.R +++ b/R/characterization-dechallengeRechallenge.R @@ -52,6 +52,8 @@ characterizationDechallengeRechallengeViewer <- function(id) { #' @param id the unique reference id for the module #' @param connectionHandler the connection to the prediction result database #' @param resultDatabaseSettings a list containing the characterization result schema, dbms, tablePrefix, databaseTable and cgTablePrefix +#' @param targetId a reactive integer specifying the targetId of interest +#' @param outcomeId a reactive integer specifying the outcomeId of interest #' #' @return #' The server to the Dechallenge Rechallenge module @@ -283,7 +285,7 @@ characterizationDechallengeRechallengeServer <- function( ) ) } else{ - showNotification("No fails to display") + shiny::showNotification("No fails to display") } } } diff --git a/R/characterization-incidence.R b/R/characterization-incidence.R index af150129..40c445f9 100644 --- a/R/characterization-incidence.R +++ b/R/characterization-incidence.R @@ -50,12 +50,6 @@ custom_age_sort <- function(age_categories) { return(custom_order) } -base_breaks <- function(n = 10){ - function(x) { - axisTicks(log10(range(x, na.rm = TRUE)), log = TRUE, n = n) - } -} - break_setter = function(n = 5) { function(lims) {pretty(x = as.numeric(lims), n = n)} } @@ -236,6 +230,10 @@ characterizationIncidenceViewer <- function(id) { #' @param id the unique reference id for the module #' @param connectionHandler the connection to the prediction result database #' @param resultDatabaseSettings a list containing the characterization result schema, dbms, tablePrefix, databaseTable and cgTablePrefix +#' @param parents a list of parent cohorts +#' @param parentIndex an integer specifying the parent index of interest +#' @param outcomes a reactive object specifying the outcomes of interest +#' @param targetIds a reactive vector of integer specifying the targetIds of interest #' #' @return #' The server to the prediction incidence module @@ -245,7 +243,7 @@ characterizationIncidenceServer <- function( id, connectionHandler, resultDatabaseSettings, - options, # this gets overwritten in code below - why here? + #options, # this gets overwritten in code below - why here? parents, parentIndex, # reactive outcomes, # reactive @@ -648,8 +646,9 @@ characterizationIncidenceServer <- function( extractedData() %>% dplyr::relocate("tar", .before = "outcomes") %>% dplyr::select(-c("targetName", "outcomeName")) %>% - dplyr::rename(targetName = targetCohortName, - outcomeName = outcomeCohortName) %>% + dplyr::rename(targetName = "targetCohortName", + outcomeName = "outcomeCohortName" + ) %>% dplyr::mutate(incidenceProportionP100p = as.numeric(.data$incidenceProportionP100p), incidenceRateP100py = as.numeric(.data$incidenceRateP100py), dplyr::across(dplyr::where(is.numeric), round, 4), @@ -742,8 +741,8 @@ characterizationIncidenceServer <- function( ifelse(incidenceRateTarFilter() %in% filteredData()$tar, plotData <- filteredData() %>% dplyr::filter(.data$tar %in% incidenceRateTarFilter()) %>% - dplyr::mutate(targetLabel = paste(targetIdShort, " = ", targetName), - outcomeLabel = paste(outcomeIdShort, " = ", outcomeName) + dplyr::mutate(targetLabel = paste(.data$targetIdShort, " = ", .data$targetName), + outcomeLabel = paste(.data$outcomeIdShort, " = ", .data$outcomeName) ), shiny::validate("Selected TAR is not found in your result data. Revise input selections or select a different TAR.") ) @@ -1210,19 +1209,15 @@ characterizationIncidenceServer <- function( plotData <- plotData %>% dplyr::filter(#ageGroupName != "Any" & - genderName == "Any" & - startYear == "Any") %>% - dplyr::mutate(targetLabel = paste(targetIdShort, " = ", targetName), - outcomeLabel = paste(outcomeIdShort, " = ", outcomeName), - ageGroupName = factor(ageGroupName, levels = custom_age_sort(ageGroupName), ordered = TRUE) + .data$genderName == "Any" & + .data$startYear == "Any") %>% + dplyr::mutate(targetLabel = paste(.data$targetIdShort, " = ", .data$targetName), + outcomeLabel = paste(.data$outcomeIdShort, " = ", .data$outcomeName), + ageGroupName = factor(.data$ageGroupName, levels = custom_age_sort(.data$ageGroupName), ordered = TRUE) ) %>% - dplyr::rename("Target" = targetIdShort, - "Outcome" = outcomeIdShort, - "Age" = ageGroupName) - - # plotHeightStandardAgeSex <- shiny::reactive({ - # paste(sum(length(unique(plotData$targetLabel)), length(unique(plotData$Age)), -3)*100, "px", sep="") - # }) + dplyr::rename("Target" = "targetIdShort", + "Outcome" = "outcomeIdShort", + "Age" = "ageGroupName") # Get unique target and outcome labels unique_target_labels <- strwrap(unique(plotData$targetLabel), width = 300) @@ -1241,9 +1236,9 @@ characterizationIncidenceServer <- function( base_plot <- ggplot2::ggplot( data = plotData, - ggplot2::aes(x = Age, - y = incidenceRateP100py, - color = cdmSourceAbbreviation + ggplot2::aes(x = .data$Age, + y = .data$incidenceRateP100py, + color = .data$cdmSourceAbbreviation ) ) + ggplot2::geom_point( diff --git a/R/characterization-main.R b/R/characterization-main.R index 1647e071..1d5e4f7d 100644 --- a/R/characterization-main.R +++ b/R/characterization-main.R @@ -512,7 +512,7 @@ characterizationServer <- function( id = 'cohortIncidenceTab', connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings, - options = options, + #options = options, parents = parents, parentIndex = parentIndex, # reactive outcomes = outcomes, # reactive diff --git a/R/characterization-timeToEvent.R b/R/characterization-timeToEvent.R index 6c197895..4c6d7524 100644 --- a/R/characterization-timeToEvent.R +++ b/R/characterization-timeToEvent.R @@ -73,6 +73,8 @@ characterizationTimeToEventViewer <- function(id) { #' @param id the unique reference id for the module #' @param connectionHandler the connection to the prediction result database #' @param resultDatabaseSettings a list containing the characterization result schema, dbms, tablePrefix, databaseTable and cgTablePrefix +#' @param targetId a reactive integer specifying the targetId of interest +#' @param outcomeId a reactive integer specifying the outcomeId of interest #' #' @return #' The server to the prediction time to event module @@ -107,9 +109,9 @@ characterizationTimeToEventServer <- function( ) %>% dplyr::mutate(targetName = options()$targetName, outcomeName = options()$outcomeName) %>% - dplyr::relocate(databaseName, .before = databaseId) %>% - dplyr::relocate(targetName, .after = databaseName) %>% - dplyr::relocate(outcomeName, .after = targetName) + dplyr::relocate("databaseName", .before = "databaseId") %>% + dplyr::relocate("targetName", .after = "databaseName") %>% + dplyr::relocate("outcomeName", .after = "targetName") }) @@ -248,8 +250,8 @@ characterizationTimeToEventServer <- function( timeToEventData = allData, # reactive databases = input$databases, times = input$times, - outcomeType = input$outcomeTypes, - targetOutcomeType = input$targetOutcomeTypes + outcomeTypes = input$outcomeTypes, + targetOutcomeTypes = input$targetOutcomeTypes ) ) @@ -355,17 +357,8 @@ plotTimeToEvent <- function( ) ) + ggplot2::geom_bar( - #position="stacked", stat = "identity" ) + - #ggplot2::geom_text( - # ggplot2::aes( - # label = .data$numEvents - # ), - # vjust = 1.6, - # color = "white", - # size = 3.5 - # ) + ggplot2::facet_wrap(ncol = nDatabases , .data$timeScale ~ .data$databaseName , scales = 'free' ) + diff --git a/R/components-data-viewer.R b/R/components-data-viewer.R index 149e17f8..035af2aa 100644 --- a/R/components-data-viewer.R +++ b/R/components-data-viewer.R @@ -9,7 +9,7 @@ #' #' @param id string #' @param downloadedFileName string, desired name of downloaded data file. can use the name from the module that is being used -#' +#' @param boxTitle the title added to the box #' @return shiny module UI #' resultTableViewer <- function( diff --git a/R/estimation-cohort-method-covariateBalance.R b/R/estimation-cohort-method-covariateBalance.R index b3927b79..8806a3af 100644 --- a/R/estimation-cohort-method-covariateBalance.R +++ b/R/estimation-cohort-method-covariateBalance.R @@ -85,7 +85,8 @@ cohortMethodCovariateBalanceServer <- function( selectedRow, connectionHandler, resultDatabaseSettings, - metaAnalysisDbIds = NULL) { + metaAnalysisDbIds = NULL + ) { shiny::moduleServer( id, @@ -96,35 +97,6 @@ cohortMethodCovariateBalanceServer <- function( resultDatabaseSettings ) - # input selection component -- could be added later if desired - # inputSelectedResults <- inputSelectionServer( - # id = "input-selection-results", - # inputSettingList = list( - # createInputSetting( - # rowNumber = 1, - # columnWidth = 12, - # varName = 'covariateAnalysisId', - # uiFunction = 'shinyWidgets::pickerInput', - # updateFunction = 'shinyWidgets::updatePickerInput', - # uiInputs = list( - # label = 'Covariate Analysis Name: ', - # choices = options$covariateAnalysisId, - # selected = options$covariateAnalysisId, # - # multiple = T, - # options = shinyWidgets::pickerOptions( - # actionsBox = TRUE, - # liveSearch = TRUE, - # size = 10, - # liveSearchStyle = "contains", - # liveSearchPlaceholder = "Type here to search", - # virtualScroll = 50 - # ) - # ) - # ) - # ) - # ) - - balance <- shiny::reactive({ row <- selectedRow() if(is.null(row$targetId)){ @@ -137,9 +109,6 @@ cohortMethodCovariateBalanceServer <- function( targetId = row$targetId, comparatorId = row$comparatorId, databaseId = row$databaseId, - # covariateAnalysisId = ifelse(is.null(inputSelectedResults()$covariateAnalysisId), - # -1, - # inputSelectedResults()$covariateAnalysisId), analysisId = row$analysisId)}, error = function(e){return(data.frame())} ) @@ -299,8 +268,8 @@ cohortMethodCovariateBalanceServer <- function( dbNames <- getDatabaseName(connectionHandler = connectionHandler, resultDatabaseSettings = resultDatabaseSettings) comb <- dplyr::inner_join(balance, dbNames) %>% - dplyr::relocate(cdmSourceAbbreviation, .after = databaseId) %>% - dplyr::select(-c(databaseId)) + dplyr::relocate("cdmSourceAbbreviation", .after = "databaseId") %>% + dplyr::select(-c("databaseId")) } ) @@ -322,11 +291,6 @@ cohortMethodCovariateBalanceServer <- function( resultTableServer( id = "balanceTable", df = renderBalanceTable, - # selectedCols = c("cdmSourceAbbreviation", "targetName", "targetIdShort", "outcomeName", "outcomeIdShort", - # "ageGroupName", "genderName", "startYear", "tar", "outcomes", - # "incidenceProportionP100p", "incidenceRateP100py"), - # sortedCols = c("ageGroupName", "genderName", "startYear", "incidenceRateP100py"), - # elementId = "incidence-select", colDefsInput = cmBalanceColList, downloadedFileName = "covariateBalanceTable-" ) diff --git a/R/estimation-cm-diagnostics.R b/R/estimation-cohort-method-diagnostics.R similarity index 100% rename from R/estimation-cm-diagnostics.R rename to R/estimation-cohort-method-diagnostics.R diff --git a/R/estimation-cohort-method-results.R b/R/estimation-cohort-method-results.R index 43cd8bc9..acb73a76 100644 --- a/R/estimation-cohort-method-results.R +++ b/R/estimation-cohort-method-results.R @@ -468,3 +468,29 @@ estimationGetCMMetaEstimation <- function( return(unique(result)) } + + +# Function to format results +# used by both cm and sccs +computeTraditionalP <- function( + logRr, + seLogRr, + twoSided = TRUE, + upper = TRUE +) +{ + z <- logRr/seLogRr + + pUpperBound <- 1 - stats::pnorm(z) + pLowerBound <- stats::pnorm(z) + + if (twoSided) { + return(2 * pmin(pUpperBound, pLowerBound)) + } + else if (upper) { + return(pUpperBound) + } + else { + return(pLowerBound) + } +} diff --git a/R/estimation-main.R b/R/estimation-main.R index 9aa9f521..a93b299e 100644 --- a/R/estimation-main.R +++ b/R/estimation-main.R @@ -207,6 +207,7 @@ estimationServer <- function( ) } }) + # end observed targetId output$targetSelection <- shiny::renderUI({ shiny::fluidRow( @@ -245,7 +246,7 @@ estimationServer <- function( ), style = 'margin-left: 2%; width: 78%; display: inline-block; vertical-align: middle;' ), - div( + shiny::div( shiny::actionButton( inputId = session$ns('targetSelect'), label = 'Select', @@ -257,10 +258,10 @@ estimationServer <- function( }) - targetSelected <- shiny::reactiveVal() - comparatorIds <- shiny::reactiveVal() - targetIds <- shiny::reactiveVal() - outcomeId <- shiny::reactiveVal() + targetSelected <- shiny::reactiveVal(NULL) + comparatorIds <- shiny::reactiveVal(NULL) + targetIds <- shiny::reactiveVal(NULL) + outcomeId <- shiny::reactiveVal(NULL) shiny::observeEvent(input$targetSelect, { @@ -395,10 +396,17 @@ getEstimationTypes <- function( } # Evidence Synthesis - if(paste0( + if( + paste0( resultDatabaseSettings$esTablePrefix, - 'result' - ) %in% tbls){ + 'cm_result' + ) %in% tbls || + paste0( + resultDatabaseSettings$esTablePrefix, + 'sccs_result' + ) %in% tbls + + ){ results <- c(results, "Evidence Synthesis") } diff --git a/R/estimation-sccs-diagnostics.R b/R/estimation-sccs-diagnostics.R index 0c721fdd..81a5fe06 100644 --- a/R/estimation-sccs-diagnostics.R +++ b/R/estimation-sccs-diagnostics.R @@ -133,7 +133,7 @@ estimationGetSccsDiagnostics <- function( # add summaryValue after outcome result <- result %>% - dplyr::relocate(.data$summaryValue, .after = .data$outcome) + dplyr::relocate("summaryValue", .after = "outcome") return( result diff --git a/R/evidence-synth-cm.R b/R/evidence-synth-cm.R deleted file mode 100644 index ee61d549..00000000 --- a/R/evidence-synth-cm.R +++ /dev/null @@ -1,550 +0,0 @@ -evidenceSynthesisCmViewer <- function(id=1) { - ns <- shiny::NS(id) - - shiny::div( - - inputSelectionViewer(ns("input-selection-cm")), - - shiny::conditionalPanel( - condition = 'input.generate != 0', - ns = shiny::NS(ns("input-selection-cm")), - - shiny::tabsetPanel( - type = 'pills', - id = ns('esCohortMethodTabs'), - - # diagnostic view - shiny::tabPanel( - title = 'Diagnostics', - resultTableViewer(ns("diagnosticsCmSummaryTable")) - ), - - shiny::tabPanel( - "Plot", - shiny::plotOutput(ns('esCohortMethodPlot')) - ), - shiny::tabPanel( - "Table", - resultTableViewer(ns("esCohortMethodTable")) - ) - ) - ) - ) -} - - -evidenceSynthesisCmServer <- function( - id, - connectionHandler, - resultDatabaseSettings = list(port = 1) -) { - shiny::moduleServer( - id, - function(input, output, session) { - - targetIds <- getEsCmTargetIds( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - outcomeIds <- getEsOutcomeIds( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - inputSelected <- inputSelectionServer( - id = "input-selection-cm", - inputSettingList = list( - createInputSetting( - rowNumber = 1, - columnWidth = 6, - varName = 'targetIds', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Target: ', - choices = targetIds, - multiple = F, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ), - createInputSetting( - rowNumber = 1, - columnWidth = 6, - varName = 'outcomeIds', - uiFunction = 'shinyWidgets::pickerInput', - uiInputs = list( - label = 'Outcome: ', - choices = outcomeIds, - multiple = F, - options = shinyWidgets::pickerOptions( - actionsBox = TRUE, - liveSearch = TRUE, - size = 10, - liveSearchStyle = "contains", - liveSearchPlaceholder = "Type here to search", - virtualScroll = 50 - ) - ) - ) - ) - ) - - # plots and tables - cmdata <- shiny::reactive({ - unique( - rbind( - getCMEstimation( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - targetId = inputSelected()$targetIds, - outcomeId = inputSelected()$outcomeIds - ), - getMetaEstimation( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - targetId = inputSelected()$targetIds, - outcomeId = inputSelected()$outcomeIds - ) - ) - ) - }) - - - diagSumData <- shiny::reactive({ - getEvidenceSynthCmDiagnostics( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - inputSelected = inputSelected, - targetIds = inputSelected()$targetIds, - outcomeIds = inputSelected()$outcomeIds - ) - }) - - - resultTableServer( - id = "diagnosticsCmSummaryTable", - df = diagSumData, - colDefsInput = getColDefsESDiag( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - method = 'cm' - ) - ) - - output$esCohortMethodPlot <- shiny::renderPlot( - createPlotForAnalysis( - cmdata() - ) - ) - - - resultTableServer( - id = "esCohortMethodTable", - df = cmdata, - colDefsInput = list( - targetId = reactable::colDef(show = F), - outcomeId = reactable::colDef(show = F), - comparatorId = reactable::colDef(show = F), - analysisId = reactable::colDef(show = F), - description = reactable::colDef( - filterable = TRUE, - header = withTooltip( - "Analysis", - "Analysis" - )), - database = reactable::colDef( - filterable = TRUE, - header = withTooltip( - "Data source", - "Data source" - )), - calibratedRr = reactable::colDef( - format = reactable::colFormat(digits = 3), - header = withTooltip( - "Cal.HR", - "Hazard ratio (calibrated)" - )), - calibratedCi95Lb = reactable::colDef( - format = reactable::colFormat(digits = 3), - header = withTooltip( - "Cal.LB", - "Lower bound of the 95 percent confidence interval (calibrated)" - )), - calibratedCi95Ub = reactable::colDef( - format = reactable::colFormat(digits = 3), - header = withTooltip( - "Cal.UB", - "Upper bound of the 95 percent confidence interval (calibrated)" - )), - calibratedP = reactable::colDef( - format = reactable::colFormat(digits = 3), - header = withTooltip( - "Cal.P", - "Two-sided p-value (calibrated)" - )), - calibratedLogRr = reactable::colDef( - format = reactable::colFormat(digits = 3), - header = withTooltip( - "Cal.Log.HR", - "Log of Hazard ratio (calibrated)" - )), - calibratedSeLogRr = reactable::colDef( - format = reactable::colFormat(digits = 3), - header = withTooltip( - "Cal.Se.Log.HR", - "Log Standard Error of Hazard ratio (calibrated)" - )), - target = reactable::colDef( - minWidth = 300 - ), - outcome = reactable::colDef( - minWidth = 300 - ), - comparator = reactable::colDef( - minWidth = 300 - ) - ) - ) - - } - ) - -} - - -getEsCmTargetIds <- function( - connectionHandler, - resultDatabaseSettings -){ - - sql <- "select distinct - c1.cohort_name as target, - r.target_id - - from - @schema.@cm_table_prefixresult as r - inner join - @schema.@cg_table_prefixcohort_definition as c1 - on c1.cohort_definition_id = r.target_id - ;" - - result <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - cm_table_prefix = resultDatabaseSettings$cmTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix - ) - - output <- as.list(result$targetId) - names(output) <- result$target - - return(output) - -} - -getCMEstimation <- function( - connectionHandler, - resultDatabaseSettings, - targetId, - outcomeId -){ - - if(is.null(targetId)){ - return(NULL) - } - - sql <- "select - c1.cohort_name as target, - c2.cohort_name as comparator, - c3.cohort_name as outcome, - r.target_id, r.comparator_id, r.outcome_id, r.analysis_id, - a.description, - db.cdm_source_abbreviation as database, r.calibrated_rr, - r.calibrated_ci_95_lb, r.calibrated_ci_95_ub, r.calibrated_p, - r.calibrated_log_rr, r.calibrated_se_log_rr - - from - @schema.@cm_table_prefixresult as r - inner join - @schema.@cm_table_prefixtarget_comparator_outcome as tco - on - r.target_id = tco.target_id and - r.comparator_id = tco.comparator_id and - r.outcome_id = tco.outcome_id - - inner join - - @schema.@cm_table_prefixdiagnostics_summary as unblind - on - r.analysis_id = unblind.analysis_id and - r.target_id = unblind.target_id and - r.comparator_id = unblind.comparator_id and - r.outcome_id = unblind.outcome_id and - r.database_id = unblind.database_id - - inner join - @schema.@database_table as db - on db.database_id = r.database_id - - inner join - @schema.@cg_table_prefixcohort_definition as c1 - on c1.cohort_definition_id = r.target_id - - inner join - @schema.@cg_table_prefixcohort_definition as c2 - on c2.cohort_definition_id = r.comparator_id - - inner join - @schema.@cg_table_prefixcohort_definition as c3 - on c3.cohort_definition_id = r.outcome_id - - inner join - @schema.@cm_table_prefixanalysis as a - on a.analysis_id = r.analysis_id - - where - r.calibrated_rr != 0 and - tco.outcome_of_interest = 1 and - unblind.unblind = 1 and - r.target_id = @target_id and - r.outcome_id = @outcome_id - ;" - - result <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - database_table = resultDatabaseSettings$databaseTable, - cm_table_prefix = resultDatabaseSettings$cmTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix, - outcome_id = outcomeId, - target_id = targetId - ) %>% - dplyr::mutate( - calibratedP = ifelse( - .data$calibratedRr < 1, - computeTraditionalP( - logRr = .data$calibratedLogRr, - seLogRr = .data$calibratedSeLogRr, - twoSided = FALSE, - upper = TRUE - ), - .data$calibratedP / 2) - ) - - return(result) -} - -getMetaEstimation <- function( - connectionHandler, - resultDatabaseSettings, - targetId, - outcomeId -){ - - if(is.null(targetId)){ - return(NULL) - } - - sql <- "select - c1.cohort_name as target, - c2.cohort_name as comparator, - c3.cohort_name as outcome, - r.target_id, r.comparator_id, r.outcome_id, r.analysis_id, - a.description, - ev.evidence_synthesis_description as database, - r.calibrated_rr, - r.calibrated_ci_95_lb, r.calibrated_ci_95_ub, r.calibrated_p, - r.calibrated_log_rr, r.calibrated_se_log_rr - - from - @schema.@es_table_prefixcm_result as r - inner join - @schema.@cm_table_prefixtarget_comparator_outcome as tco - on - r.target_id = tco.target_id and - r.comparator_id = tco.comparator_id and - r.outcome_id = tco.outcome_id - - inner join - - @schema.@es_table_prefixcm_diagnostics_summary as unblind - on - r.analysis_id = unblind.analysis_id and - r.target_id = unblind.target_id and - r.comparator_id = unblind.comparator_id and - r.outcome_id = unblind.outcome_id - - inner join - @schema.@cg_table_prefixcohort_definition as c1 - on c1.cohort_definition_id = r.target_id - - inner join - @schema.@cg_table_prefixcohort_definition as c2 - on c2.cohort_definition_id = r.comparator_id - - inner join - @schema.@cg_table_prefixcohort_definition as c3 - on c3.cohort_definition_id = r.outcome_id - - inner join - @schema.@cm_table_prefixanalysis as a - on a.analysis_id = r.analysis_id - - inner join - @schema.@es_table_prefixanalysis as ev - on ev.evidence_synthesis_analysis_id = r.evidence_synthesis_analysis_id - - where - r.calibrated_rr != 0 and - tco.outcome_of_interest = 1 and - unblind.unblind = 1 and - r.target_id = @target_id and - r.outcome_id = @outcome_id - ;" - - result <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - cm_table_prefix = resultDatabaseSettings$cmTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix, - es_table_prefix = resultDatabaseSettings$esTablePrefix, - outcome_id = outcomeId, - target_id = targetId - ) %>% - dplyr::mutate( - calibratedP = ifelse( - .data$calibratedRr < 1, - computeTraditionalP( - logRr = .data$calibratedLogRr, - seLogRr = .data$calibratedSeLogRr, - twoSided = FALSE, - upper = TRUE - ), - .data$calibratedP / 2) - ) - - return(unique(result)) -} - -getEvidenceSynthCmDiagnostics <- function( - connectionHandler, - resultDatabaseSettings, - inputSelected, - targetIds, - outcomeIds -){ - - if(is.null(targetIds)){ - return(NULL) - } - - cmDiagTemp <- getCmDiagnosticsData( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - inputSelected = inputSelected - ) - - if(is.null(cmDiagTemp)){ - return(NULL) - } - - # select columns of interest and rename for consistency - cmDiagTemp <- diagnosticSummaryFormat( - data = shiny::reactive({cmDiagTemp}), - idCols = c('databaseName','target'), - namesFrom = c('analysis','comparator','outcome') - ) - - # return - return(cmDiagTemp) -} - - -createPlotForAnalysis <- function(data) { - - if(is.null(data$comparator)){ - return(NULL) - } - - compText <- data.frame( - comparatorText = paste0('Comp', 1:length(unique(data$comparator))), - comparator = unique(data$comparator) - ) - - data <- merge( - data, - compText, - by = "comparator" - ) - - # make sure bayesian is at bottom - db <- unique(data$database) - bInd <- grep('bayesian', tolower(db)) - withoutb <- db[-bInd] - b <- db[bInd] - data$database <- factor( - x = data$database, - levels = c(sort(withoutb), b) - ) - metadata <- data[data$database == b,] - - breaks <- c(0.1, 0.25, 0.5, 1, 2, 4, 6, 8) - title <- sprintf("%s", data$outcome[1]) - plot <- ggplot2::ggplot( - data = data, - ggplot2::aes(x = .data$calibratedRr, y = .data$comparatorText)) + - ggplot2::geom_vline(xintercept = 1, size = 0.5) + - ggplot2::geom_point(color = "#000088", alpha = 0.8) + - ggplot2::geom_errorbarh( - ggplot2::aes( - xmin = .data$calibratedCi95Lb, - xmax = .data$calibratedCi95Ub - ), - height = 0.5, - color = "#000088", - alpha = 0.8 - ) + - ggplot2::scale_x_log10( - "Effect size (Hazard Ratio)", - breaks = breaks, - labels = breaks - ) + - - # shade the bayesian - ggplot2::geom_rect( - data = metadata, - ggplot2::aes(fill = .data$database), - xmin = -Inf, - xmax = Inf, - ymin = -Inf, - ymax = Inf, - alpha = 0.2 - ) + - - ggplot2::coord_cartesian(xlim = c(0.1, 10)) + - ggplot2::facet_grid(.data$database ~ .data$description) + - ggplot2::ggtitle(title) + - ggplot2::theme( - axis.title.y = ggplot2::element_blank(), - panel.grid.minor = ggplot2::element_blank(), - strip.text.y.right = ggplot2::element_text(angle = 0), - legend.position = "none" - ) + - ggplot2::labs( - caption = paste( - apply( - X = compText, - MARGIN = 1, - FUN = function(x){paste0(paste(substring(x, 1, 50),collapse = ': ', sep=':'), '...')} - ), - collapse = '\n ') - ) - - return(plot) -} diff --git a/R/evidence-synth-main.R b/R/evidence-synth-main.R deleted file mode 100644 index 8394fb2f..00000000 --- a/R/evidence-synth-main.R +++ /dev/null @@ -1,332 +0,0 @@ -#' The location of the evidence synthesis module helper file -#' -#' @details -#' Returns the location of the evidence synthesis helper file -#' -#' @return -#' string location of the evidence synthesis helper file -#' -#' @export -evidenceSynthesisHelperFile <- function(){ - fileLoc <- system.file('evidence-synthesis-www', "evidence-synthesis.html", package = "OhdsiShinyModules") - return(fileLoc) -} - -#' The module viewer for exploring evidence-synthesis -#' -#' @details -#' The user specifies the id for the module -#' -#' @param id the unique reference id for the module -#' -#' @return -#' The user interface to the evidence-synthesis viewer module -#' -#' @export -evidenceSynthesisViewer <- function(id=1) { - ns <- shiny::NS(id) - - shinydashboard::box( - status = 'info', - width = 12, - title = shiny::span( shiny::icon("sliders"), 'Evidence Synthesis'), - solidHeader = TRUE, - - - # add two buttons - CM or SCCs - shiny::tabsetPanel( - id = ns('typeTab'), - type = 'pills' - ) - - ) - -} - -checkSccsTablesPresent <- function(connectionHandler, resultDatabaseSettings) { - sql <- " - SELECT 1 as present FROM @schema.@sccs_table_prefixdiagnostics_summary; - " - present <- TRUE - tryCatch({ - connectionHandler$queryDb(sql = sql, - schema = resultDatabaseSettings$schema, - sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix) - }, error = function(...) { - present <<- FALSE - }) - - return(present) -} - -checkCmTablesPresent <- function(connectionHandler, resultDatabaseSettings) { - sql <- " - SELECT 1 as present FROM @schema.@cm_table_prefixdiagnostics_summary; - " - present <- TRUE - tryCatch({ - connectionHandler$queryDb(sql = sql, - schema = resultDatabaseSettings$schema, - cm_table_prefix = resultDatabaseSettings$cmTablePrefix) - }, error = function(...) { - present <<- FALSE - }) - - return(present) -} - -#' The module server for exploring PatientLevelPrediction -#' -#' @details -#' The user specifies the id for the module -#' -#' @param id the unique reference id for the module -#' @param connectionHandler a connection to the database with the results -#' @param resultDatabaseSettings a list containing the result schema and prefixes -#' -#' @return -#' The server for the PatientLevelPrediction module -#' -#' @export -evidenceSynthesisServer <- function( - id, - connectionHandler, - resultDatabaseSettings = list(port = 1) -) { - shiny::moduleServer( - id, - function(input, output, session) { - - showSccsResults <- checkSccsTablesPresent(connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings) - - showCmResults <- checkCmTablesPresent(connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings) - - if (showCmResults) { - shiny::insertTab( - inputId = "typeTab", - tab = - shiny::tabPanel( - title = 'Cohort Method', - evidenceSynthesisCmViewer(id = session$ns('cohortMethodTab')), - ), - select = TRUE - ) - - evidenceSynthesisCmServer( - id = 'cohortMethodTab', - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - } - - if (showSccsResults) { - shiny::insertTab( - inputId = "typeTab", - tab = shiny::tabPanel( - title = "Self Controlled Case Series", - evidenceSynthesisSccsViewer(id = session$ns('sccsTab')), - ), - select = !showCmResults - ) - - evidenceSynthesisSccsServer( - id = 'sccsTab', - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - } - } - ) -} - -# Function to get outcome ids -# used by both cm and sccs -getEsOutcomeIds <- function( - connectionHandler, - resultDatabaseSettings -) { - sql <- "select distinct - c1.cohort_name as outcome, - r.outcome_id - - from - @schema.@cm_table_prefixresult as r - inner join - @schema.@cm_table_prefixtarget_comparator_outcome as tco - on - r.target_id = tco.target_id and - r.comparator_id = tco.comparator_id and - r.outcome_id = tco.outcome_id - - inner join - @schema.@cg_table_prefixcohort_definition as c1 - on c1.cohort_definition_id = r.outcome_id - - where - tco.outcome_of_interest = 1 - ;" - - result <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - cm_table_prefix = resultDatabaseSettings$cmTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix - ) - - output <- as.list(result$outcomeId) - names(output) <- result$outcome - - return(output) - -} - -# Function to format results -# used by both cm and sccs -computeTraditionalP <- function( - logRr, - seLogRr, - twoSided = TRUE, - upper = TRUE -) -{ - z <- logRr/seLogRr - - pUpperBound <- 1 - stats::pnorm(z) - pLowerBound <- stats::pnorm(z) - - if (twoSided) { - return(2 * pmin(pUpperBound, pLowerBound)) - } - else if (upper) { - return(pUpperBound) - } - else { - return(pLowerBound) - } -} - - - -# Functions to get column formatting and names -# used by both cm and sccs -getOACcombinations <- function( - connectionHandler, - resultDatabaseSettings, - method -){ - - if(method == 'cm'){ - sql <- "SELECT DISTINCT - CONCAT(cma.description, '_', cgcd2.cohort_name) as col_names - FROM - @schema.@cm_table_prefixdiagnostics_summary cmds - INNER JOIN @schema.@cm_table_prefixanalysis cma - ON cmds.analysis_id = cma.analysis_id - INNER JOIN @schema.@cg_table_prefixcohort_definition cgcd2 - ON cmds.comparator_id = cgcd2.cohort_definition_id - ;" - - result <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - cm_table_prefix = resultDatabaseSettings$cmTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix - ) - } - - if(method == 'sccs'){ - sql <- "SELECT distinct - CONCAT(a.description, '_', cov.covariate_name) as col_names - - FROM @schema.@sccs_table_prefixdiagnostics_summary ds - - INNER JOIN - @schema.@sccs_table_prefixanalysis a - on a.analysis_id = ds.analysis_id - - INNER JOIN - @schema.@sccs_table_prefixcovariate cov - on cov.covariate_id = ds.covariate_id and - cov.exposures_outcome_set_id = ds.exposures_outcome_set_id and - cov.analysis_id = ds.analysis_id - ;" - - result <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix - ) - } - - res <- result$colNames - names(res) <- result$colNames - - return(res) -} - -getColDefsESDiag <- function( - connectionHandler, - resultDatabaseSettings, - method = 'cm' # 'cm' or 'sccs' -){ - - fixedColumns = list( - databaseName = reactable::colDef( - header = withTooltip( - "Database", - "The database name" - ), - sticky = "left" - ), - target = reactable::colDef( - header = withTooltip( - "Target", - "The target cohort of interest " - ), - sticky = "left" - ) - ) - - outcomes <- getEsOutcomeIds( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - analyses <- getOACcombinations( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - method = method - ) - colnameFormat <- merge(unique(names(analyses)), unique(names(outcomes))) - colnameFormat <- apply(colnameFormat, 1, function(x){paste(x, collapse = '_', sep = '_')}) - - styleList <- lapply( - colnameFormat, - FUN = function(x){ - reactable::colDef( - header = withTooltip( - substring(x,1,40), - x - ), - style = function(value) { - color <- 'orange' - if(is.na(value)){ - color <- 'black' - }else if(value == 'Pass'){ - color <- '#AFE1AF' - }else if(value == 'Fail'){ - color <- '#E97451' - } - list(background = color) - } - ) - } - ) - names(styleList) <- colnameFormat - result <- append(fixedColumns, styleList) - - return(result) -} diff --git a/R/evidence-synth-sccs.R b/R/evidence-synth-sccs.R deleted file mode 100644 index 86d139d3..00000000 --- a/R/evidence-synth-sccs.R +++ /dev/null @@ -1,537 +0,0 @@ -evidenceSynthesisSccsViewer <- function(id=1) { - ns <- shiny::NS(id) - - shiny::div( - - inputSelectionViewer(ns("input-selection-sccs")), - - shiny::conditionalPanel( - condition = 'input.generate != 0', - ns = shiny::NS(ns("input-selection-sccs")), - - shiny::tabsetPanel( - type = 'pills', - id = ns('esSccsTabs'), - - # diagnostic view - shiny::tabPanel( - title = 'Diagnostics', - resultTableViewer(ns("diagnosticsSccsSummaryTable")) - ), - - shiny::tabPanel( - "Plot", - shiny::plotOutput(ns('esSccsPlot')) - ), - shiny::tabPanel( - "Table", - resultTableViewer(ns("esSccsTable")) - ) - ) - ) - ) -} - -evidenceSynthesisSccsServer <- function( - id, - connectionHandler, - resultDatabaseSettings = list(port = 1) -) { - shiny::moduleServer( - id, - function(input, output, session) { - - outcomeIds <- getEsOutcomeIds( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings - ) - - exposureIndicationInput <- .getSccsExposureIndicationSelection(connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings) - - inputSelected <- inputSelectionServer( - id = "input-selection-sccs", - inputSettingList = list( - exposureIndicationInput, - createInputSetting( - rowNumber = 2, - columnWidth = 12, - varName = 'outcomeIds', - uiFunction = 'shinyWidgets::virtualSelectInput', - uiInputs = list( - label = 'Outcome: ', - choices = outcomeIds, - multiple = F, - search = TRUE - ) - ) - ) - ) - - - - diagSumData <- shiny::reactive({ - getEvidenceSynthSccsDiagnostics( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - inputSelected = inputSelected, - exposure = inputSelected()$exposure, - outcomeIds = inputSelected()$outcomeIds - ) - }) - - # SCCS plots and tables - resultTableServer( - id = "diagnosticsSccsSummaryTable", - df = diagSumData, - colDefsInput = getColDefsESDiag( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - method = 'sccs' - ) - ) - - sccsData <- shiny::reactive({ - unique( - getSccsEstimation( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - exposure = inputSelected()$exposure, - outcomeId = inputSelected()$outcomeIds - ) - ) - }) - - output$esSccsPlot <- shiny::renderPlot({ - sccsRes <- sccsData() - shiny::validate(shiny::need(hasData(sccsRes), "No valid data for selected target")) - createPlotForSccsAnalysis(sccsRes) - }) - - - resultTableServer( - id = "esSccsTable", - df = sccsData, - colDefsInput = list( - targetId = reactable::colDef(show = F), - outcomeId = reactable::colDef(show = F), - analysisId = reactable::colDef(show = F), - description = reactable::colDef( - filterable = TRUE, - header = withTooltip( - "Analysis", - "Analysis" - ), - minWidth = 300 - ), - database = reactable::colDef( - filterable = TRUE, - header = withTooltip( - "Data source", - "Data source" - )), - calibratedRr = reactable::colDef( - format = reactable::colFormat(digits = 3), - header = withTooltip( - "Cal.IRR", - "Incidence rate ratio (calibrated)" - )), - calibratedCi95Lb = reactable::colDef( - format = reactable::colFormat(digits = 3), - header = withTooltip( - "Cal.LB", - "Lower bound of the 95 percent confidence interval (calibrated)" - )), - calibratedCi95Ub = reactable::colDef( - format = reactable::colFormat(digits = 3), - header = withTooltip( - "Cal.UB", - "Upper bound of the 95 percent confidence interval (calibrated)" - )), - calibratedP = reactable::colDef( - format = reactable::colFormat(digits = 3), - header = withTooltip( - "Cal.P", - "Two-sided p-value (calibrated)" - )), - calibratedLogRr = reactable::colDef( - format = reactable::colFormat(digits = 3), - header = withTooltip( - "Cal.Log.IRR", - "Log of Incidence rate ratio (calibrated)" - )), - calibratedSeLogRr = reactable::colDef( - format = reactable::colFormat(digits = 3), - header = withTooltip( - "Cal.Se.Log.IRR", - "Log Standard Error of Incidence rate ratio (calibrated)" - )), - target = reactable::colDef( - minWidth = 300 - ), - outcome = reactable::colDef( - minWidth = 300 - ) - ) - ) - - } - ) - -} - -getSccsTargets <- function( - connectionHandler, - resultDatabaseSettings -){ - - output <- sccsGetExposureIndications( - connectionHandler, - resultDatabaseSettings - ) - return(output) - -} - -getSccsEstimation <- function( - connectionHandler, - resultDatabaseSettings, - exposure, - outcomeId -){ - - if (is.null(outcomeId)) { - return(NULL) - } - - if (is.character(exposure)) { - exposureGroup <- strsplit(exposure, " ")[[1]] - targetId <- exposureGroup[[1]] - indicationIds <- exposureGroup[[2]] - } else { - targetId <- -1 - indicationIds <- -1 - } - - if (any(indicationIds == -1)) { - indicationIds <- NULL - } - - sql <- "select - c1.cohort_name as target, - c3.cohort_name as outcome, - cov.era_id as target_id, eos.outcome_id, r.analysis_id, - a.description, - cov.covariate_name as type, - db.cdm_source_abbreviation as database, - r.calibrated_rr, - r.calibrated_ci_95_lb, - r.calibrated_ci_95_ub, - r.calibrated_p, - r.calibrated_log_rr, - r.calibrated_se_log_rr - - from - @schema.@sccs_table_prefixresult as r - inner join - @schema.@sccs_table_prefixexposures_outcome_set as eos - on - r.exposures_outcome_set_id = eos.exposures_outcome_set_id - - inner join - @schema.@sccs_table_prefixcovariate as cov - on - r.covariate_id = cov.covariate_id and - r.database_id = cov.database_id and - r.analysis_id = cov.analysis_id and - r.exposures_outcome_set_id = cov.exposures_outcome_set_id - - inner join - @schema.@sccs_table_prefixexposure as ex - on - ex.era_id = cov.era_id and - ex.exposures_outcome_set_id = cov.exposures_outcome_set_id - - inner join - - @schema.@sccs_table_prefixdiagnostics_summary as unblind - on - r.analysis_id = unblind.analysis_id and - r.exposures_outcome_set_id = unblind.exposures_outcome_set_id and - r.covariate_id = unblind.covariate_id and - r.database_id = unblind.database_id - - inner join - @schema.@database_table as db - on db.database_id = r.database_id - - inner join - @schema.@cg_table_prefixcohort_definition as c1 - on c1.cohort_definition_id = cov.era_id - - inner join - @schema.@cg_table_prefixcohort_definition as c3 - on c3.cohort_definition_id = eos.outcome_id - - inner join - @schema.@sccs_table_prefixanalysis as a - on a.analysis_id = r.analysis_id - - where - r.calibrated_rr != 0 and - --ex.true_effect_size != 1 and - cov.covariate_name in ('Main', 'Second dose') and - unblind.unblind = 1 and - cov.era_id = @target_id and - eos.outcome_id = @outcome_id - {@use_indications} ? {and eos.nesting_cohort_id IN (@indication_ids)} : {and eos.nesting_cohort_id IS NULL} - ;" - - result <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - database_table = resultDatabaseSettings$databaseTable, - sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix, - outcome_id = outcomeId, - target_id = targetId, - indication_ids = indicationIds, - use_indications = !is.null(indicationIds) - ) - - sql <- "select distinct - c1.cohort_name as target, - c3.cohort_name as outcome, - cov.era_id as target_id, eos.outcome_id, r.analysis_id, - a.description, - cov.covariate_name as type, - ev.evidence_synthesis_description as database, - r.calibrated_rr, - r.calibrated_ci_95_lb, - r.calibrated_ci_95_ub, - r.calibrated_p, - r.calibrated_log_rr, - r.calibrated_se_log_rr - - from - @schema.@es_table_prefixsccs_result as r - inner join - @schema.@sccs_table_prefixexposures_outcome_set as eos - on - r.exposures_outcome_set_id = eos.exposures_outcome_set_id - - inner join - @schema.@sccs_table_prefixcovariate as cov - on - r.covariate_id = cov.covariate_id and - r.analysis_id = cov.analysis_id and - r.exposures_outcome_set_id = cov.exposures_outcome_set_id - - inner join - @schema.@sccs_table_prefixexposure as ex - on - ex.era_id = cov.era_id and - ex.exposures_outcome_set_id = cov.exposures_outcome_set_id - - inner join - - @schema.@es_table_prefixsccs_diagnostics_summary as unblind - on - r.analysis_id = unblind.analysis_id and - r.exposures_outcome_set_id = unblind.exposures_outcome_set_id and - r.covariate_id = unblind.covariate_id and - r.evidence_synthesis_analysis_id = unblind.evidence_synthesis_analysis_id - - inner join - @schema.@cg_table_prefixcohort_definition as c1 - on c1.cohort_definition_id = cov.era_id - - inner join - @schema.@cg_table_prefixcohort_definition as c3 - on c3.cohort_definition_id = eos.outcome_id - - inner join - @schema.@sccs_table_prefixanalysis as a - on a.analysis_id = r.analysis_id - - inner join - @schema.@es_table_prefixanalysis as ev - on ev.evidence_synthesis_analysis_id = r.evidence_synthesis_analysis_id - - where - r.calibrated_rr != 0 and - --ex.true_effect_size != 1 and - cov.covariate_name in ('Main', 'Second dose') and - unblind.unblind = 1 and - cov.era_id = @target_id and - eos.outcome_id = @outcome_id - {@use_indications} ? {and eos.nesting_cohort_id IN (@indication_ids)} : {and eos.nesting_cohort_id IS NULL} - ;" - - result2 <- connectionHandler$queryDb( - sql = sql, - schema = resultDatabaseSettings$schema, - es_table_prefix = resultDatabaseSettings$esTablePrefix, - sccs_table_prefix = resultDatabaseSettings$sccsTablePrefix, - cg_table_prefix = resultDatabaseSettings$cgTablePrefix, - outcome_id = outcomeId, - target_id = targetId, - indication_ids = indicationIds, - use_indications = !is.null(indicationIds) - ) - - return(rbind(result,result2)) - -} - -createPlotForSccsAnalysis <- function( - data -){ - - if(is.null(data)){ - return(NULL) - } - - # change the description to add at bottom - renameDf <- data.frame( - shortName = paste0( - 1:length(unique(data$description)), - ') ', - substring(sort(unique(data$description)), 1, 15), - '...' - ), - description = sort(unique(data$description)) - ) - data <- merge( - x = data, - y = renameDf, - by = 'description' - ) - - # make sure bayesian is at bottom - db <- unique(data$database) - bInd <- grep('bayesian', tolower(db)) - withoutb <- db[-bInd] - b <- db[bInd] - data$database <- factor( - x = data$database, - levels = c(sort(withoutb), b) - ) - metadata <- data[data$database == b,] - - breaks <- c(0.1, 0.25, 0.5, 1, 2, 4, 6, 8) - plot <- ggplot2::ggplot( - data = data, - ggplot2::aes(x = .data$calibratedRr, y = .data$type) - ) + - ggplot2::geom_vline(xintercept = 1, size = 0.5) + - ggplot2::geom_point(color = "#000088", alpha = 0.8) + - ggplot2::geom_errorbarh( - ggplot2::aes( - xmin = .data$calibratedCi95Lb, - xmax = .data$calibratedCi95Ub - ), - height = 0.5, - color = "#000088", - alpha = 0.8 - ) + - ggplot2::scale_x_log10( - "Effect size (Incidence Rate Ratio)", - breaks = breaks, - labels = breaks - ) + - - # shade the bayesian - ggplot2::geom_rect( - data = metadata, - ggplot2::aes(fill = .data$database), - xmin = -Inf, - xmax = Inf, - ymin = -Inf, - ymax = Inf, - alpha = 0.2 - ) + - - ggplot2::coord_cartesian(xlim = c(0.1, 10)) + - ggplot2::facet_grid(.data$database ~ .data$shortName) + - ggplot2::ggtitle(data$outcome[1]) + - ggplot2::theme( - axis.title.y = ggplot2::element_blank(), - panel.grid.minor = ggplot2::element_blank(), - strip.text.y.right = ggplot2::element_text(angle = 0), - legend.position = "none" - ) - - ### Add table below the graph - renameDf$description <- sapply( - strwrap(renameDf$description, width = 50, simplify = FALSE), - paste, - collapse = "\n" - ) - - tt <- gridExtra::ttheme_default( - base_size = 8, - colhead=list(fg_params = list(parse=TRUE)) - ) - tbl <- gridExtra::tableGrob( - renameDf, - rows=NULL, - theme=tt - ) - plot <- gridExtra::grid.arrange( - plot, - tbl, - nrow = 2, - as.table = TRUE - ) - - return(plot) -} - -getEvidenceSynthSccsDiagnostics <- function( - connectionHandler, - resultDatabaseSettings, - inputSelected, - exposure, - outcomeIds -){ - - if(is.null(exposure)){ - return(NULL) - } - - if (is.character(exposure)) { - exposureGroup <- strsplit(exposure, " ")[[1]] - targetId <- exposureGroup[[1]] - indicationIds <- exposureGroup[[2]] - } else { - targetId <- -1 - indicationIds <- -1 - } - - if (any(indicationIds == -1)) { - indicationIds <- NULL - } - - sccsDiagTemp <- getSccsAllDiagnosticsSummary( - connectionHandler = connectionHandler, - resultDatabaseSettings = resultDatabaseSettings, - targetIds = targetId, - indicationIds = indicationIds, - outcomeIds = outcomeIds - ) - - if(is.null(sccsDiagTemp)){ - return(NULL) - } - - # select columns of interest and rename for consistency - sccsDiagTemp <- diagnosticSummaryFormat( - data = shiny::reactive({sccsDiagTemp}), - idCols = c('databaseName','target'), - namesFrom = c('analysis','covariateName','outcome') - ) - - # return - return(sccsDiagTemp) -} diff --git a/R/patient-level-prediction-modelSummary.R b/R/patient-level-prediction-modelSummary.R index 1c2a7faf..a5f9f480 100644 --- a/R/patient-level-prediction-modelSummary.R +++ b/R/patient-level-prediction-modelSummary.R @@ -293,11 +293,11 @@ getModelDesignPerformanceSummary <- function( on c.cohort_definition_id = cd.cohort_definition_id ) AS outcomes ON results.outcome_id = outcomes.cohort_id LEFT JOIN (select dd.database_id, md.cdm_source_abbreviation database_acronym - from @schema.@database_table_prefixdatabase_meta_data md inner join + from @schema.@database_table_prefix@database_table md inner join @schema.@plp_table_prefixdatabase_details dd on md.database_id = dd.database_meta_data_id) AS d ON results.development_database_id = d.database_id LEFT JOIN (select dd.database_id, md.cdm_source_abbreviation database_acronym - from @schema.@database_table_prefixdatabase_meta_data md inner join + from @schema.@database_table_prefix@database_table md inner join @schema.@plp_table_prefixdatabase_details dd on md.database_id = dd.database_meta_data_id) AS v ON results.validation_database_id = v.database_id LEFT JOIN @schema.@plp_table_prefixtars AS tars ON results.tar_id = tars.tar_id @@ -314,6 +314,7 @@ getModelDesignPerformanceSummary <- function( plp_table_prefix = resultDatabaseSettings$plpTablePrefix, model_design_id = modelDesignId(), database_table_prefix = resultDatabaseSettings$databaseTablePrefix, + database_table = resultDatabaseSettings$databaseTable, cg_table_prefix = resultDatabaseSettings$cgTablePrefix ) diff --git a/extras/codeToCreateEstimationDatabase.R b/extras/codeToCreateEstimationDatabase.R index fe388070..0ffc9258 100644 --- a/extras/codeToCreateEstimationDatabase.R +++ b/extras/codeToCreateEstimationDatabase.R @@ -1,8 +1,8 @@ # code to create test data -testDir <- tempdir() +#testDir <- tempdir() -outputFolder <- '/Users/jreps/Documents/CohortMethodDb' +outputFolder <- file.path(getwd(), 'tests', 'resources', 'estDatabase') library(CohortMethod) connectionDetails <- Eunomia::getEunomiaConnectionDetails() @@ -24,26 +24,23 @@ tcos1 <- createTargetComparatorOutcomes( ), excludedCovariateConceptIds = c(1118084, 1124300) ) -# Empty cohorts: + tcos2 <- createTargetComparatorOutcomes( - targetId = 998, - comparatorId = 999, + targetId = 1, + comparatorId = 4, outcomes = list( createOutcome( outcomeId = 3, priorOutcomeLookback = 30 - ), - createOutcome( - outcomeId = 4, - outcomeOfInterest = FALSE, - trueEffectSize = 1 ) - ) + ), + excludedCovariateConceptIds = c(1118084, 1124300) ) targetComparatorOutcomesList <- list(tcos1, tcos2) covarSettings <- createDefaultCovariateSettings(addDescendantsToExclude = TRUE) +covarSettings$endDays <- -1 getDbCmDataArgs <- createGetDbCohortMethodDataArgs( washoutPeriod = 183, @@ -155,10 +152,10 @@ cmAnalysis4 <- createCmAnalysis( cmAnalysisList <- list(cmAnalysis1, cmAnalysis2, cmAnalysis3, cmAnalysis4) -analysesToExclude <- data.frame( - targetId = c(998, 998), - analysisId = c(3, 4) -) +#analysesToExclude <- data.frame( +# targetId = c(998, 998), +# analysisId = c(3, 4) +#) # cmAnalysis4 includes interaction terms which should throw a warning @@ -169,35 +166,48 @@ result <- runCmAnalyses( outcomeTable = "cohort", outputFolder = outputFolder, cmAnalysisList = cmAnalysisList, - targetComparatorOutcomesList = targetComparatorOutcomesList, - analysesToExclude = analysesToExclude + targetComparatorOutcomesList = targetComparatorOutcomesList#, + #analysesToExclude = analysesToExclude ) -CohortMethod::exportToCsv(outputFolder) +CohortMethod::exportToCsv(outputFolder, databaseId = 'eunomia') -# create sqlite and insert each table: -tables <- dir(file.path(outputFolder, 'export'), pattern = '.csv') resultDetails <- DatabaseConnector::createConnectionDetails( dbms = 'sqlite', server = "/Users/jreps/Documents/github/OhdsiShinyModules/tests/resources/estDatabase/databaseFile.sqlite" ) -sqliteCon <- DatabaseConnector::connect(connectionDetails = resultDetails) -for(table in tables){ - DatabaseConnector::insertTable( - connection = sqliteCon, - databaseSchema = 'main', - tableName = gsub('.csv','',table), - data = utils::read.csv(file.path(outputFolder, 'export', table)), - createTable = T, - dropTableIfExists = T, - camelCaseToSnakeCase = F - ) -} +resultsDataModel <- ResultModelManager::loadResultsDataModelSpecifications( + filePath = system.file("csv", "resultsDataModelSpecification.csv", package = "CohortMethod") +) +sql <- ResultModelManager::generateSqlSchema( + schemaDefinition = resultsDataModel +) +sql <- SqlRender::render( + sql = sql, + database_schema = 'main' +) +connection <- DatabaseConnector::connect( + connectionDetails = resultDetails +) +DatabaseConnector::executeSql( + connection = connection, + sql = sql +) +# create tables +# upload results +ResultModelManager::uploadResults( + connectionDetails = resultDetails, + schema = 'main', + resultsFolder = '/Users/jreps/Documents/github/OhdsiShinyModules/tests/resources/estDatabase/cm_export', + tablePrefix = '', + specifications = resultsDataModel, + purgeSiteDataBeforeUploading = F + ) DatabaseConnector::insertTable( - connection = sqliteCon, + connection = connection, databaseSchema = 'main', tableName = 'cg_cohort_definition', data = data.frame( @@ -212,14 +222,292 @@ DatabaseConnector::insertTable( ) DatabaseConnector::insertTable( - connection = sqliteCon, + connection = connection, databaseSchema = 'main', tableName = 'database_meta_data', data = data.frame( - databaseId = '1', + databaseId = 'eunomia', cdmSourceName = 'eunomia', cdmSourceAbbreviation = 'eunomia' ), createTable = T, dropTableIfExists = T, camelCaseToSnakeCase = T ) + +DatabaseConnector::disconnect(connection) + + + +# NOW SCCS +library(SelfControlledCaseSeries) + +sccsAnalysisList <- list( + SelfControlledCaseSeries::createSccsAnalysis( + analysisId = 1, + description = 'test 1', + getDbSccsDataArgs = SelfControlledCaseSeries::createGetDbSccsDataArgs( + maxCasesPerOutcome = 0, + exposureIds = c("exposureId1", "exposureId2", "exposureId4") + ), + createStudyPopulationArgs = SelfControlledCaseSeries::createCreateStudyPopulationArgs( + firstOutcomeOnly = T, + naivePeriod = 90, + minAge = 18 + ), + createIntervalDataArgs = SelfControlledCaseSeries::createCreateSccsIntervalDataArgs( + eraCovariateSettings = SelfControlledCaseSeries::createEraCovariateSettings( + label = "Exposure of interest", + includeEraIds = "exposureId1", + start = 1, + end = 0, + endAnchor = "era end", + profileLikelihood = TRUE, + exposureOfInterest = TRUE + ), + ageCovariateSettings = SelfControlledCaseSeries::createAgeCovariateSettings(), + seasonalityCovariateSettings = SelfControlledCaseSeries::createSeasonalityCovariateSettings(), + calendarTimeCovariateSettings = SelfControlledCaseSeries::createCalendarTimeCovariateSettings() + ), + fitSccsModelArgs = SelfControlledCaseSeries::createFitSccsModelArgs() + ), + SelfControlledCaseSeries::createSccsAnalysis( + analysisId = 2, + description = 'test 2', + getDbSccsDataArgs = SelfControlledCaseSeries::createGetDbSccsDataArgs( + maxCasesPerOutcome = 0, + exposureIds = c("exposureId1") + ), + createStudyPopulationArgs = SelfControlledCaseSeries::createCreateStudyPopulationArgs( + firstOutcomeOnly = T, + naivePeriod = 90, + minAge = 18 + ), + createIntervalDataArgs = SelfControlledCaseSeries::createCreateSccsIntervalDataArgs( + eraCovariateSettings = SelfControlledCaseSeries::createEraCovariateSettings( + label = "Exposure of interest", + includeEraIds = "exposureId1", + start = 1, + end = 0, + endAnchor = "era end", + profileLikelihood = TRUE, + exposureOfInterest = TRUE + ), + ageCovariateSettings = SelfControlledCaseSeries::createAgeCovariateSettings(), + seasonalityCovariateSettings = SelfControlledCaseSeries::createSeasonalityCovariateSettings(), + calendarTimeCovariateSettings = SelfControlledCaseSeries::createCalendarTimeCovariateSettings() + ), + fitSccsModelArgs = SelfControlledCaseSeries::createFitSccsModelArgs() + ) +) + +exposuresOutcomeList <- list( + SelfControlledCaseSeries::createExposuresOutcome( + outcomeId = 3, + exposures = list( + SelfControlledCaseSeries::createExposure( + exposureId = 1, exposureIdRef = 'exposureId1', + trueEffectSize = NA + ), + SelfControlledCaseSeries::createExposure( + exposureId = 2, exposureIdRef = 'exposureId2', + trueEffectSize = 1 + ), + SelfControlledCaseSeries::createExposure( + exposureId = 4, exposureIdRef = 'exposureId4', + trueEffectSize = 1 + ) + ) +)) + + +SelfControlledCaseSeries::runSccsAnalyses( + connectionDetails = connectionDetails, + cdmDatabaseSchema = 'main', + exposureDatabaseSchema = 'main', + exposureTable = 'cohort', + outcomeDatabaseSchema = 'main', + outcomeTable = 'cohort', + outputFolder = file.path(outputFolder, 'sccs'), + sccsAnalysisList = sccsAnalysisList, + exposuresOutcomeList = exposuresOutcomeList + ) + +SelfControlledCaseSeries::exportToCsv( + outputFolder = file.path(outputFolder, 'sccs'), + exportFolder = file.path(outputFolder, 'sccs_export'), + databaseId = 'eunomia' + ) + +resultDetails <- DatabaseConnector::createConnectionDetails( + dbms = 'sqlite', + server = "/Users/jreps/Documents/github/OhdsiShinyModules/tests/resources/estDatabase/databaseFile.sqlite" +) +resultsDataModel <- ResultModelManager::loadResultsDataModelSpecifications( + filePath = system.file("csv", "resultsDataModelSpecification.csv", package = "SelfControlledCaseSeries") +) +sql <- ResultModelManager::generateSqlSchema( + schemaDefinition = resultsDataModel +) +sql <- SqlRender::render( + sql = sql, + database_schema = 'main' +) +connection <- DatabaseConnector::connect( + connectionDetails = resultDetails +) +DatabaseConnector::executeSql( + connection = connection, + sql = sql +) + +# create tables + +# upload results +ResultModelManager::uploadResults( + connectionDetails = resultDetails, + schema = 'main', + resultsFolder = '/Users/jreps/Documents/github/OhdsiShinyModules/tests/resources/estDatabase/sccs_export', + tablePrefix = '', + specifications = resultsDataModel, + purgeSiteDataBeforeUploading = F +) + +DatabaseConnector::disconnect(connection) + +# NOW ES + +resultDetails <- DatabaseConnector::createConnectionDetails( + dbms = 'sqlite', + server = "/Users/jreps/Documents/github/OhdsiShinyModules/tests/resources/estDatabase/databaseFile.sqlite" +) +source('https://raw.github.com/OHDSI/EvidenceSynthesisModule/main/EvidenceSynthesisFunctions.R') + +createEvidenceSynthesisSource <- function(sourceMethod = "CohortMethod", + databaseIds = NULL, + analysisIds = NULL, + likelihoodApproximation = "adaptive grid") { + errorMessages <- checkmate::makeAssertCollection() + checkmate::assertChoice(sourceMethod, c("CohortMethod", "SelfControlledCaseSeries"), add = errorMessages) + if (is.character(databaseIds)) { + checkmate::assertCharacter(databaseIds, null.ok = TRUE, add = errorMessages) + } else { + checkmate::assertIntegerish(databaseIds, null.ok = TRUE, add = errorMessages) + } + checkmate::assertIntegerish(analysisIds, null.ok = TRUE, add = errorMessages) + checkmate::assertChoice(likelihoodApproximation, c("adaptive grid", "normal"), add = errorMessages) + checkmate::reportAssertions(collection = errorMessages) + + analysis <- list() + for (name in names(formals(createEvidenceSynthesisSource))) { + analysis[[name]] <- get(name) + } + class(analysis) <- "EvidenceSynthesisSource" + return(analysis) +} +createBayesianMetaAnalysis <- function(chainLength = 1100000, + burnIn = 1e+05, + subSampleFrequency = 100, + priorSd = c(2, 0.5), + alpha = 0.05, + robust = FALSE, + df = 4, + seed = 1, + evidenceSynthesisAnalysisId = 1, + evidenceSynthesisDescription = "Bayesian random-effects", + evidenceSynthesisSource = NULL, + controlType = "outcome") { + analysis <- list() + for (name in names(formals(createBayesianMetaAnalysis))) { + analysis[[name]] <- get(name) + } + class(analysis) <- c("BayesianMetaAnalysis", "EvidenceSynthesisAnalysis") + return(analysis) +} +createEsDiagnosticThresholds <- function(mdrrThreshold = 10, + easeThreshold = 0.25, + i2Threshold = 0.4, + tauThreshold = log(2)) { + errorMessages <- checkmate::makeAssertCollection() + checkmate::assertNumeric(mdrrThreshold, len = 1, lower = 0, add = errorMessages) + checkmate::assertNumeric(easeThreshold, len = 1, lower = 0, add = errorMessages) + checkmate::assertNumeric(i2Threshold, len = 1, lower = 0, add = errorMessages) + checkmate::assertNumeric(tauThreshold, len = 1, lower = 0, add = errorMessages) + checkmate::reportAssertions(collection = errorMessages) + thresholds <- list( + mdrrThreshold = mdrrThreshold, + easeThreshold = easeThreshold, + i2Threshold = i2Threshold, + tauThreshold = tauThreshold + ) + class(thresholds) <- "EsDiagnosticThresholds" + return(thresholds) +} + +writeAnalysisSpecs( + analysisSpecs = list( + createBayesianMetaAnalysis( + evidenceSynthesisSource = createEvidenceSynthesisSource(), + evidenceSynthesisAnalysisId = 1 + ), + createBayesianMetaAnalysis( + evidenceSynthesisSource = createEvidenceSynthesisSource( + sourceMethod = "SelfControlledCaseSeries" + ), evidenceSynthesisAnalysisId = 2 + ) + ), + resultsFolder = file.path(outputFolder, 'es') +) +# Note: need to download https://github.com/OHDSI/EvidenceSynthesisModule/blob/main/resultsDataModelSpecification.csv +executeEvidenceSynthesis( + connectionDetails = resultDetails, + databaseSchema = 'main', + settings = list( + createBayesianMetaAnalysis( + evidenceSynthesisSource = createEvidenceSynthesisSource(), + evidenceSynthesisAnalysisId = 1 + ), + createBayesianMetaAnalysis( + evidenceSynthesisSource = createEvidenceSynthesisSource( + sourceMethod = "SelfControlledCaseSeries" + ), evidenceSynthesisAnalysisId = 2 + ) + ), + esDiagnosticThresholds = createEsDiagnosticThresholds(), + resultsFolder = file.path(outputFolder, 'es'), + minCellCount = 5 +) + +# upload ES +resultDetails <- DatabaseConnector::createConnectionDetails( + dbms = 'sqlite', + server = "/Users/jreps/Documents/github/OhdsiShinyModules/tests/resources/estDatabase/databaseFile.sqlite" +) +resultsDataModel <- read.csv('resultsDataModelSpecification.csv') +colnames(resultsDataModel) <- SqlRender::snakeCaseToCamelCase(colnames(resultsDataModel)) +sql <- ResultModelManager::generateSqlSchema( + schemaDefinition = resultsDataModel +) +sql <- SqlRender::render( + sql = sql, + database_schema = 'main' +) +connection <- DatabaseConnector::connect( + connectionDetails = resultDetails +) +DatabaseConnector::executeSql( + connection = connection, + sql = sql +) + +# upload results +ResultModelManager::uploadResults( + connectionDetails = resultDetails, + schema = 'main', + resultsFolder = '/Users/jreps/Documents/github/OhdsiShinyModules/tests/resources/estDatabase/es', + tablePrefix = '', + specifications = resultsDataModel, + purgeSiteDataBeforeUploading = F +) + +DatabaseConnector::disconnect(connection) + diff --git a/man/OhdsiShinyModules.Rd b/man/OhdsiShinyModules.Rd new file mode 100644 index 00000000..6c1ae2c2 --- /dev/null +++ b/man/OhdsiShinyModules.Rd @@ -0,0 +1,11 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/OhdsiShinyModules.R +\docType{package} +\name{OhdsiShinyModules} +\alias{OhdsiShinyModules-package} +\alias{OhdsiShinyModules} +\title{OhdsiShinyModules} +\description{ +A selection of shiny modules for exploring standardized OHDSI results +} +\keyword{internal} diff --git a/man/characterizationDechallengeRechallengeServer.Rd b/man/characterizationDechallengeRechallengeServer.Rd index 124f5a73..214c6191 100644 --- a/man/characterizationDechallengeRechallengeServer.Rd +++ b/man/characterizationDechallengeRechallengeServer.Rd @@ -18,6 +18,10 @@ characterizationDechallengeRechallengeServer( \item{connectionHandler}{the connection to the prediction result database} \item{resultDatabaseSettings}{a list containing the characterization result schema, dbms, tablePrefix, databaseTable and cgTablePrefix} + +\item{targetId}{a reactive integer specifying the targetId of interest} + +\item{outcomeId}{a reactive integer specifying the outcomeId of interest} } \value{ The server to the Dechallenge Rechallenge module diff --git a/man/characterizationIncidenceServer.Rd b/man/characterizationIncidenceServer.Rd index df648028..6d90398c 100644 --- a/man/characterizationIncidenceServer.Rd +++ b/man/characterizationIncidenceServer.Rd @@ -8,7 +8,6 @@ characterizationIncidenceServer( id, connectionHandler, resultDatabaseSettings, - options, parents, parentIndex, outcomes, @@ -21,6 +20,14 @@ characterizationIncidenceServer( \item{connectionHandler}{the connection to the prediction result database} \item{resultDatabaseSettings}{a list containing the characterization result schema, dbms, tablePrefix, databaseTable and cgTablePrefix} + +\item{parents}{a list of parent cohorts} + +\item{parentIndex}{an integer specifying the parent index of interest} + +\item{outcomes}{a reactive object specifying the outcomes of interest} + +\item{targetIds}{a reactive vector of integer specifying the targetIds of interest} } \value{ The server to the prediction incidence module diff --git a/man/characterizationTimeToEventServer.Rd b/man/characterizationTimeToEventServer.Rd index c4fe7e16..e4e3443f 100644 --- a/man/characterizationTimeToEventServer.Rd +++ b/man/characterizationTimeToEventServer.Rd @@ -18,6 +18,10 @@ characterizationTimeToEventServer( \item{connectionHandler}{the connection to the prediction result database} \item{resultDatabaseSettings}{a list containing the characterization result schema, dbms, tablePrefix, databaseTable and cgTablePrefix} + +\item{targetId}{a reactive integer specifying the targetId of interest} + +\item{outcomeId}{a reactive integer specifying the outcomeId of interest} } \value{ The server to the prediction time to event module diff --git a/man/cohortMethodAttritionServer.Rd b/man/cohortMethodAttritionServer.Rd index 6e3444cc..5620957d 100644 --- a/man/cohortMethodAttritionServer.Rd +++ b/man/cohortMethodAttritionServer.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-attrition.R +% Please edit documentation in R/estimation-cohort-method-attrition.R \name{cohortMethodAttritionServer} \alias{cohortMethodAttritionServer} \title{The module server for rendering the PLE attrition results} diff --git a/man/cohortMethodAttritionViewer.Rd b/man/cohortMethodAttritionViewer.Rd index 9b16769e..e97d9e71 100644 --- a/man/cohortMethodAttritionViewer.Rd +++ b/man/cohortMethodAttritionViewer.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-attrition.R +% Please edit documentation in R/estimation-cohort-method-attrition.R \name{cohortMethodAttritionViewer} \alias{cohortMethodAttritionViewer} \title{The module viewer for rendering the PLE attrition results} diff --git a/man/cohortMethodCovariateBalanceServer.Rd b/man/cohortMethodCovariateBalanceServer.Rd index 41a874bc..5dc6b21e 100644 --- a/man/cohortMethodCovariateBalanceServer.Rd +++ b/man/cohortMethodCovariateBalanceServer.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-covariateBalance.R +% Please edit documentation in R/estimation-cohort-method-covariateBalance.R \name{cohortMethodCovariateBalanceServer} \alias{cohortMethodCovariateBalanceServer} \title{The module server for rendering the covariate balance plot} diff --git a/man/cohortMethodCovariateBalanceViewer.Rd b/man/cohortMethodCovariateBalanceViewer.Rd index 5e9011c5..e53d4bce 100644 --- a/man/cohortMethodCovariateBalanceViewer.Rd +++ b/man/cohortMethodCovariateBalanceViewer.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-covariateBalance.R +% Please edit documentation in R/estimation-cohort-method-covariateBalance.R \name{cohortMethodCovariateBalanceViewer} \alias{cohortMethodCovariateBalanceViewer} \title{The module viewer for rendering the PLE covariate balance analysis} diff --git a/man/cohortMethodKaplanMeierServer.Rd b/man/cohortMethodKaplanMeierServer.Rd index 0f3f3c4b..1d40d8b5 100644 --- a/man/cohortMethodKaplanMeierServer.Rd +++ b/man/cohortMethodKaplanMeierServer.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-kaplainMeier.R +% Please edit documentation in R/estimation-cohort-method-kaplainMeier.R \name{cohortMethodKaplanMeierServer} \alias{cohortMethodKaplanMeierServer} \title{The module server for rendering the Kaplan Meier curve} diff --git a/man/cohortMethodKaplanMeierViewer.Rd b/man/cohortMethodKaplanMeierViewer.Rd index a896e9b1..04fae120 100644 --- a/man/cohortMethodKaplanMeierViewer.Rd +++ b/man/cohortMethodKaplanMeierViewer.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-kaplainMeier.R +% Please edit documentation in R/estimation-cohort-method-kaplainMeier.R \name{cohortMethodKaplanMeierViewer} \alias{cohortMethodKaplanMeierViewer} \title{The module viewer for rendering the PLE Kaplan Meier curve} diff --git a/man/cohortMethodPopulationCharacteristicsServer.Rd b/man/cohortMethodPopulationCharacteristicsServer.Rd index 34119408..9e2ed648 100644 --- a/man/cohortMethodPopulationCharacteristicsServer.Rd +++ b/man/cohortMethodPopulationCharacteristicsServer.Rd @@ -1,5 +1,6 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-populationCharacteristics.R +% Please edit documentation in +% R/estimation-cohort-method-populationCharacteristics.R \name{cohortMethodPopulationCharacteristicsServer} \alias{cohortMethodPopulationCharacteristicsServer} \title{The module server for rendering the population characteristics} diff --git a/man/cohortMethodPopulationCharacteristicsViewer.Rd b/man/cohortMethodPopulationCharacteristicsViewer.Rd index 9262f9e3..08d408aa 100644 --- a/man/cohortMethodPopulationCharacteristicsViewer.Rd +++ b/man/cohortMethodPopulationCharacteristicsViewer.Rd @@ -1,5 +1,6 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-populationCharacteristics.R +% Please edit documentation in +% R/estimation-cohort-method-populationCharacteristics.R \name{cohortMethodPopulationCharacteristicsViewer} \alias{cohortMethodPopulationCharacteristicsViewer} \title{The module viewer for rendering the PLE population characteristics} diff --git a/man/cohortMethodPowerServer.Rd b/man/cohortMethodPowerServer.Rd index d9b9b201..5ace2ae4 100644 --- a/man/cohortMethodPowerServer.Rd +++ b/man/cohortMethodPowerServer.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-power.R +% Please edit documentation in R/estimation-cohort-method-power.R \name{cohortMethodPowerServer} \alias{cohortMethodPowerServer} \title{The module server for rendering the PLE power analysis results} diff --git a/man/cohortMethodPowerViewer.Rd b/man/cohortMethodPowerViewer.Rd index cea46b77..3694c777 100644 --- a/man/cohortMethodPowerViewer.Rd +++ b/man/cohortMethodPowerViewer.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-power.R +% Please edit documentation in R/estimation-cohort-method-power.R \name{cohortMethodPowerViewer} \alias{cohortMethodPowerViewer} \title{The module viewer for rendering the PLE power analysis} diff --git a/man/cohortMethodPropensityModelServer.Rd b/man/cohortMethodPropensityModelServer.Rd index 1c0ab242..3d01fd6b 100644 --- a/man/cohortMethodPropensityModelServer.Rd +++ b/man/cohortMethodPropensityModelServer.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-propensityModel.R +% Please edit documentation in R/estimation-cohort-method-propensityModel.R \name{cohortMethodPropensityModelServer} \alias{cohortMethodPropensityModelServer} \title{The module server for rendering the propensity score model} diff --git a/man/cohortMethodPropensityModelViewer.Rd b/man/cohortMethodPropensityModelViewer.Rd index d05b543a..9e6dc59c 100644 --- a/man/cohortMethodPropensityModelViewer.Rd +++ b/man/cohortMethodPropensityModelViewer.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-propensityModel.R +% Please edit documentation in R/estimation-cohort-method-propensityModel.R \name{cohortMethodPropensityModelViewer} \alias{cohortMethodPropensityModelViewer} \title{The module viewer for rendering the PLE propensity score model covariates/coefficients} diff --git a/man/cohortMethodPropensityScoreDistServer.Rd b/man/cohortMethodPropensityScoreDistServer.Rd index a5b57e16..6168e02f 100644 --- a/man/cohortMethodPropensityScoreDistServer.Rd +++ b/man/cohortMethodPropensityScoreDistServer.Rd @@ -1,5 +1,6 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-propensityScoreDistribution.R +% Please edit documentation in +% R/estimation-cohort-method-propensityScoreDistribution.R \name{cohortMethodPropensityScoreDistServer} \alias{cohortMethodPropensityScoreDistServer} \title{The module server for rendering a PLE propensity score distribution} diff --git a/man/cohortMethodPropensityScoreDistViewer.Rd b/man/cohortMethodPropensityScoreDistViewer.Rd index ba8e780a..4d48a7a5 100644 --- a/man/cohortMethodPropensityScoreDistViewer.Rd +++ b/man/cohortMethodPropensityScoreDistViewer.Rd @@ -1,5 +1,6 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-propensityScoreDistribution.R +% Please edit documentation in +% R/estimation-cohort-method-propensityScoreDistribution.R \name{cohortMethodPropensityScoreDistViewer} \alias{cohortMethodPropensityScoreDistViewer} \title{The module viewer for rendering the propensity score distribution} diff --git a/man/cohortMethodSystematicErrorServer.Rd b/man/cohortMethodSystematicErrorServer.Rd index 3f44490e..112a8b82 100644 --- a/man/cohortMethodSystematicErrorServer.Rd +++ b/man/cohortMethodSystematicErrorServer.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-systematicError.R +% Please edit documentation in R/estimation-cohort-method-systematicError.R \name{cohortMethodSystematicErrorServer} \alias{cohortMethodSystematicErrorServer} \title{The module server for rendering the systematic error objects} diff --git a/man/cohortMethodSystematicErrorViewer.Rd b/man/cohortMethodSystematicErrorViewer.Rd index c4dea713..8b8e4d5e 100644 --- a/man/cohortMethodSystematicErrorViewer.Rd +++ b/man/cohortMethodSystematicErrorViewer.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cohort-method-systematicError.R +% Please edit documentation in R/estimation-cohort-method-systematicError.R \name{cohortMethodSystematicErrorViewer} \alias{cohortMethodSystematicErrorViewer} \title{The module viewer for rendering the PLE systematic error objects} diff --git a/man/evidenceSynthesisHelperFile.Rd b/man/evidenceSynthesisHelperFile.Rd deleted file mode 100644 index aa65874e..00000000 --- a/man/evidenceSynthesisHelperFile.Rd +++ /dev/null @@ -1,17 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/evidence-synth-main.R -\name{evidenceSynthesisHelperFile} -\alias{evidenceSynthesisHelperFile} -\title{The location of the evidence synthesis module helper file} -\usage{ -evidenceSynthesisHelperFile() -} -\value{ -string location of the evidence synthesis helper file -} -\description{ -The location of the evidence synthesis module helper file -} -\details{ -Returns the location of the evidence synthesis helper file -} diff --git a/man/evidenceSynthesisServer.Rd b/man/evidenceSynthesisServer.Rd deleted file mode 100644 index cf33e7d6..00000000 --- a/man/evidenceSynthesisServer.Rd +++ /dev/null @@ -1,28 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/evidence-synth-main.R -\name{evidenceSynthesisServer} -\alias{evidenceSynthesisServer} -\title{The module server for exploring PatientLevelPrediction} -\usage{ -evidenceSynthesisServer( - id, - connectionHandler, - resultDatabaseSettings = list(port = 1) -) -} -\arguments{ -\item{id}{the unique reference id for the module} - -\item{connectionHandler}{a connection to the database with the results} - -\item{resultDatabaseSettings}{a list containing the result schema and prefixes} -} -\value{ -The server for the PatientLevelPrediction module -} -\description{ -The module server for exploring PatientLevelPrediction -} -\details{ -The user specifies the id for the module -} diff --git a/man/evidenceSynthesisViewer.Rd b/man/evidenceSynthesisViewer.Rd deleted file mode 100644 index 6e4b215e..00000000 --- a/man/evidenceSynthesisViewer.Rd +++ /dev/null @@ -1,20 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/evidence-synth-main.R -\name{evidenceSynthesisViewer} -\alias{evidenceSynthesisViewer} -\title{The module viewer for exploring evidence-synthesis} -\usage{ -evidenceSynthesisViewer(id = 1) -} -\arguments{ -\item{id}{the unique reference id for the module} -} -\value{ -The user interface to the evidence-synthesis viewer module -} -\description{ -The module viewer for exploring evidence-synthesis -} -\details{ -The user specifies the id for the module -} diff --git a/man/resultTableViewer.Rd b/man/resultTableViewer.Rd index 4ebc79cd..9bb60f51 100644 --- a/man/resultTableViewer.Rd +++ b/man/resultTableViewer.Rd @@ -14,6 +14,8 @@ resultTableViewer( \item{id}{string} \item{downloadedFileName}{string, desired name of downloaded data file. can use the name from the module that is being used} + +\item{boxTitle}{the title added to the box} } \value{ shiny module UI diff --git a/tests/resources/cmDatabase/databaseFile.sqlite b/tests/resources/cmDatabase/databaseFile.sqlite deleted file mode 100644 index 45d191b27aa49ea1379fbf7be9ae8c8372c93f74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 372736 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
  • @@ -68,7 +92,7 @@
  • @@ -69,7 +93,7 @@