From 9b65fe91ac2a777f8512675ba42fd379bec6f400 Mon Sep 17 00:00:00 2001 From: Jeremy Wildfire Date: Mon, 28 Oct 2024 17:20:30 -0700 Subject: [PATCH] add PK KRI options. fix #1919 #1911 --- R/util-MakeBounds.R | 3 + inst/examples/pk_kri.R | 76 +++++++++++++++++++++++++ inst/workflow/1_mappings/PK.yaml | 23 ++++++++ inst/workflow/2_metrics/kri0013.yaml | 81 +++++++++++++++++++++++++++ inst/workflow/2_metrics/kri0013a.yaml | 80 ++++++++++++++++++++++++++ 5 files changed, 263 insertions(+) create mode 100644 inst/examples/pk_kri.R create mode 100644 inst/workflow/1_mappings/PK.yaml create mode 100644 inst/workflow/2_metrics/kri0013.yaml create mode 100644 inst/workflow/2_metrics/kri0013a.yaml diff --git a/R/util-MakeBounds.R b/R/util-MakeBounds.R index 2b7cb71e4..f414b38d2 100644 --- a/R/util-MakeBounds.R +++ b/R/util-MakeBounds.R @@ -60,6 +60,9 @@ MakeBounds <- function( as.list() vThreshold <- ParseThreshold(strThreshold = lMetric$Threshold) if (!is.null(lMetric$AnalysisType) && + tolower(unique(lMetric$AnalysisType)) %in% c("identity")) { + dfBounds <- NULL + } else if (!is.null(lMetric$AnalysisType) && tolower(unique(lMetric$AnalysisType)) %in% c("poisson")) { dfBounds <- Analyze_Poisson_PredictBounds( dfResult, diff --git a/inst/examples/pk_kri.R b/inst/examples/pk_kri.R new file mode 100644 index 000000000..7765cac0e --- /dev/null +++ b/inst/examples/pk_kri.R @@ -0,0 +1,76 @@ +devtools::load_all() +library(tidyr) +set.seed(1234) + +# Step 0 - Simulate PK data for clindata participants +mapped_pk <- tidyr::crossing( + subjid = unique(clindata::rawplus_dm$subjid), + pktpt = c( + "Cycle 1 Day 1", + "Cycle 1 Day 1", + "Cycle 1 Day 1", + "Cycle 1 Day 15", + "Cycle 1 Day 2", + "Cycle 1 Day 4", + "Cycle 1 Day 8" + ) +) +mapped_pk$pkperf <- sample(c("Yes","No"), prob=c(0.95,0.05),nrow(mapped_pk), replace = TRUE) + +pk_data <-list( + Mapped_SUBJ= clindata::rawplus_dm, + Mapped_PK= mapped_pk +) + +# Example 1 - Standard KRI with normal approximation +pk_kri <- gsm::RunWorkflows( + lWorkflow = MakeWorkflowList(strName = "kri0013.yaml"), + lData = pk_data +) +Widget_BarChart(dfResults = pk_kri$Analysis_kri0013$Analysis_Summary) + +# Example 2 - KRI with custom flagging based on 90% threshold + +pk_kri_alt <- gsm::RunWorkflows( + lWorkflow = MakeWorkflowList(strName = "kri0013a.yaml"), + lData = pk_data +) +Widget_BarChart(dfResults = pk_kri_alt$Analysis_kri0013a$Analysis_Summary) + + +# Example 3 - Run Reports with other KRIs +lSource <- list( + Source_SUBJ = clindata::rawplus_dm, + Source_AE = clindata::rawplus_ae, + Source_PD = clindata::ctms_protdev, + Source_LB = clindata::rawplus_lb, + Source_STUDCOMP = clindata::rawplus_studcomp, + Source_SDRGCOMP = clindata::rawplus_sdrgcomp %>% dplyr::filter(.data$phase == 'Blinded Study Drug Completion'), + Source_DATACHG = clindata::edc_data_points, + Source_DATAENT = clindata::edc_data_pages, + Source_QUERY = clindata::edc_queries, + Source_ENROLL = clindata::rawplus_enroll, + Source_SITE = clindata::ctms_site, + Source_STUDY = clindata::ctms_study, + Source_PK = pk_data$Mapped_PK # only new line +) + +# Step 0 - Data Ingestion - standardize tables/columns names +mappings_wf <- MakeWorkflowList(strPath = "workflow/1_mappings") +mappings_spec <- CombineSpecs(mappings_wf) +lRaw <- Ingest(lSource, mappings_spec) + +# Step 1 - Create Mapped Data Layer - filter, aggregate and join raw data to create mapped data layer +mapped <- RunWorkflows(mappings_wf, lRaw) + +# Step 2 - Create Metrics - calculate metrics using mapped data +metrics_wf <- MakeWorkflowList(strPath = "workflow/2_metrics") +analyzed <- RunWorkflows(metrics_wf, mapped) + +# Step 3 - Create Reporting Layer - create reports using metrics data +reporting_wf <- MakeWorkflowList(strPath = "workflow/3_reporting") +reporting <- RunWorkflows(reporting_wf, c(mapped, list(lAnalyzed = analyzed, lWorkflows = metrics_wf))) + +# Step 4 - Create KRI Report - create KRI report using reporting data +module_wf <- MakeWorkflowList(strPath = "workflow/4_modules") +lReports <- RunWorkflows(module_wf, reporting) diff --git a/inst/workflow/1_mappings/PK.yaml b/inst/workflow/1_mappings/PK.yaml new file mode 100644 index 000000000..c4df7e050 --- /dev/null +++ b/inst/workflow/1_mappings/PK.yaml @@ -0,0 +1,23 @@ +meta: + Type: Mapped + ID: PK + Description: PK Data Mapping + Priority: 1 +spec: + Raw_PK: + subjid: + required: true + type: character + pktpt: + required: true + type: character + pkperf: + required: true + type: character +steps: + - output: Mapped_PK + name: = + params: + lhs: Mapped_PK + rhs: Raw_PK + diff --git a/inst/workflow/2_metrics/kri0013.yaml b/inst/workflow/2_metrics/kri0013.yaml new file mode 100644 index 000000000..783071b5e --- /dev/null +++ b/inst/workflow/2_metrics/kri0013.yaml @@ -0,0 +1,81 @@ +meta: + Type: Analysis + ID: kri0013 + GroupLevel: Site + Abbreviation: PK + Metric: PK Rate + Numerator: PK Measures Completed + Denominator: PK Measures Expected + Model: Normal Approximation + Score: Adjusted Z-Score + AnalysisType: binary + Threshold: -3,-2,2,3 + nMinDenominator: 10 +spec: + Mapped_SUBJ: + subjid: + required: true + type: character + invid: + required: true + type: character + Mapped_PK: + subjid: + required: true + type: character + pktpt: + required: true + type: character + pkperf: + required: true + type: character +steps: + - output: vThreshold + name: ParseThreshold + params: + strThreshold: Threshold + - output: Temp_PK_Complete + name: RunQuery + params: + df: Mapped_PK + strQuery: "SELECT * FROM df WHERE pkperf = 'Yes'" + - output: Analysis_Input + name: Input_Rate + params: + dfSubjects: Mapped_SUBJ + dfNumerator: Temp_PK_Complete + dfDenominator: Mapped_PK + strSubjectCol: subjid + strGroupCol: invid + strGroupLevel: GroupLevel + strNumeratorMethod: Count + strDenominatorMethod: Count + - output: Analysis_Transformed + name: Transform_Rate + params: + dfInput: Analysis_Input + - output: Analysis_Analyzed + name: Analyze_NormalApprox + params: + dfTransformed: Analysis_Transformed + strType: AnalysisType + - output: Analysis_Flagged + name: Flag_NormalApprox + params: + dfAnalyzed: Analysis_Analyzed + vThreshold: vThreshold + - output: Analysis_Summary + name: Summarize + params: + dfFlagged: Analysis_Flagged + nMinDenominator: nMinDenominator + - output: lAnalysis + name: list + params: + ID: ID + Analysis_Input: Analysis_Input + Analysis_Transformed: Analysis_Transformed + Analysis_Analyzed: Analysis_Analyzed + Analysis_Flagged: Analysis_Flagged + Analysis_Summary: Analysis_Summary + diff --git a/inst/workflow/2_metrics/kri0013a.yaml b/inst/workflow/2_metrics/kri0013a.yaml new file mode 100644 index 000000000..ee751f629 --- /dev/null +++ b/inst/workflow/2_metrics/kri0013a.yaml @@ -0,0 +1,80 @@ +meta: + Type: Analysis + ID: kri0013a + GroupLevel: Site + Abbreviation: PKi + Metric: PK Rate - Identity + Numerator: PK Measures Completed + Denominator: PK Measures Expected + Model: Identity + Score: Percent Complete + AnalysisType: identity + Threshold: "0.9,1.0" + nMinDenominator: 10 +spec: + Mapped_SUBJ: + subjid: + required: true + type: character + invid: + required: true + type: character + Mapped_PK: + subjid: + required: true + type: character + pktpt: + required: true + type: character + pkperf: + required: true + type: character +steps: + - output: vThreshold + name: ParseThreshold + params: + strThreshold: Threshold + - output: Temp_PK_Complete + name: RunQuery + params: + df: Mapped_PK + strQuery: "SELECT * FROM df WHERE pkperf = 'Yes'" + - output: Analysis_Input + name: Input_Rate + params: + dfSubjects: Mapped_SUBJ + dfNumerator: Temp_PK_Complete + dfDenominator: Mapped_PK + strSubjectCol: subjid + strGroupCol: invid + strGroupLevel: GroupLevel + strNumeratorMethod: Count + strDenominatorMethod: Count + - output: Analysis_Transformed + name: Transform_Rate + params: + dfInput: Analysis_Input + - output: Analysis_Analyzed + name: Analyze_Identity + params: + dfTransformed: Analysis_Transformed + - output: Analysis_Flagged + name: Flag + params: + dfAnalyzed: Analysis_Analyzed + vThreshold: vThreshold + - output: Analysis_Summary + name: Summarize + params: + dfFlagged: Analysis_Flagged + nMinDenominator: nMinDenominator + - output: lAnalysis + name: list + params: + ID: ID + Analysis_Input: Analysis_Input + Analysis_Transformed: Analysis_Transformed + Analysis_Analyzed: Analysis_Analyzed + Analysis_Flagged: Analysis_Flagged + Analysis_Summary: Analysis_Summary +