## ----eval=TRUE, include=FALSE-------------------------------------------------
# convenience variables
cgx <- BiocStyle::Biocpkg("CoreGx")
pgx <- BiocStyle::Biocpkg("PharmacoGx")
dt <- BiocStyle::CRANpkg("data.table")

# knitr options
knitr::opts_chunk$set(warning=FALSE)

## ----load_dependencies_eval, eval=TRUE, echo=FALSE----------------------------
suppressPackageStartupMessages({
    library(PharmacoGx)
    library(CoreGx)
    library(data.table)
    library(ggplot2)
})

## ----load_dependencies_echo, eval=FALSE, echo=TRUE----------------------------
# library(PharmacoGx)
# library(CoreGx)
# library(data.table)
# library(ggplot2)

## -----------------------------------------------------------------------------
input_file <- system.file("extdata/mathews_griner.csv.tar.gz",
    package="PharmacoGx")
mathews_griner <- fread(input_file)

## ----experiment_design_hypothesis---------------------------------------------
groups <- list(
    rowDataMap=c(
        treatment1id="RowName", treatment2id="ColName",
        treatment1dose="RowConcs", treatment2dose="ColConcs"
    ),
    colDataMap=c("sampleid")
)
groups[["assayMap"]] <- c(groups$rowDataMap, groups$colDataMap)
(groups)

## ----handling_technical_replicates--------------------------------------------
# The := operator modifies a data.table by reference (i.e., without making a copy)
mathews_griner[, tech_rep := seq_len(.N), by=c(groups[["assayMap"]])]
if (max(mathews_griner[["tech_rep"]]) > 1) {
    groups[["colDataMap"]] <- c(groups[["colDataMap"]], "tech_rep")
    groups[["assayMap"]] <- c(groups[["assayMap"]], "tech_rep")
} else {
    # delete the additional column if not needed
    message("No technical replicates in this dataset!")
    mathews_griner[["tech_reps"]] <- NULL
}

## ----build_tredatamapper------------------------------------------------------
(treMapper <- TREDataMapper(rawdata=mathews_griner))

## ----evaluate_tre_mapping_guess-----------------------------------------------
(guess <- guessMapping(treMapper, groups, subset=TRUE))

## ----update_tredatamapper_with_guess------------------------------------------
metadataMap(treMapper) <- list(experiment_metadata=guess$metadata$mapped_columns)
rowDataMap(treMapper) <- guess$rowDataMap
colDataMap(treMapper) <- guess$colDataMap
assayMap(treMapper) <- list(raw=guess$assayMap)
treMapper

## ----metaconstruct_the_tre----------------------------------------------------
(tre <- metaConstruct(treMapper))

## ----normalize_to_dose_0_0_control--------------------------------------------
raw <- tre[["raw"]]
raw[,
    viability := viability / .SD[treatment1dose == 0 & treatment2dose == 0, viability],
    by=c("treatment1id", "treatment2id", "sampleid", "tech_rep")
]
raw[, viability := pmax(0, viability)]  # truncate min viability at 0
tre[["raw"]] <- raw

## ----sanity_check_viability---------------------------------------------------
tre[["raw"]][, range(viability)]

## ----find_bad_viability_treatment, warning=FALSE------------------------------
(bad_treatments <- tre[["raw"]][viability > 2, unique(treatment1id)])

## ----remove_bad_viability_treatment, warning=FALSE----------------------------
(tre <- subset(tre, !(treatment1id %in% bad_treatments)))

## ----sanity_check_viability2--------------------------------------------------
tre[["raw"]][, range(viability)]

## ----creating_monotherapy_assay-----------------------------------------------
tre_qc <- tre |>
    endoaggregate(
        subset=treatment2dose == 0,  # filter to only monotherapy rows
        assay="raw",
        target="mono_viability",  # create a new assay named mono_viability
        mean_viability=pmin(1, mean(viability)),
        by=c("treatment1id", "treatment1dose", "sampleid")
    )

## ----monotherapy_curve_fits, messages=TRUE, eval=FALSE------------------------
# tre_fit <- tre_qc |>
#     endoaggregate(
#         {  # the entire code block is evaluated for each group in our group by
#             # 1. fit a log logistic curve over the dose range
#             fit <- PharmacoGx::logLogisticRegression(treatment1dose, mean_viability,
#                 viability_as_pct=FALSE)
#             # 2. compute curve summary metrics
#             ic50 <- PharmacoGx::computeIC50(treatment1dose, Hill_fit=fit)
#             aac <- PharmacoGx::computeAUC(treatment1dose, Hill_fit=fit)
#             # 3. assemble the results into a list, each item will become a
#             #   column in the target assay.
#             list(
#                 HS=fit[["HS"]],
#                 E_inf = fit[["E_inf"]],
#                 EC50 = fit[["EC50"]],
#                 Rsq=as.numeric(unlist(attributes(fit))),
#                 aac_recomputed=aac,
#                 ic50_recomputed=ic50
#             )
#         },
#         assay="mono_viability",
#         target="mono_profiles",
#         enlist=FALSE,  # this option enables the use of a code block for aggregation
#         by=c("treatment1id", "sampleid"),
#         nthread=2  # parallelize over multiple cores to speed up the computation
#     )

## ----create_combo_viability, message=FALSE, eval=FALSE------------------------
# tre_combo <- tre_fit |>
#     endoaggregate(
#         assay="raw",
#         target="combo_viability",
#         mean(viability),
#         by=c("treatment1id", "treatment2id", "treatment1dose", "treatment2dose",
#             "sampleid")
#     )

## ----add_monotherapy_fits_to_combo_viability, eval=FALSE----------------------
# tre_combo <- tre_combo |>
#     mergeAssays(
#         x="combo_viability",
#         y="mono_profiles",
#         by=c("treatment1id", "sampleid")
#     ) |>
#     mergeAssays(
#         x="combo_viability",
#         y="mono_profiles",
#         by.x=c("treatment2id", "sampleid"),
#         by.y=c("treatment1id", "sampleid"),
#         suffixes=c("_1", "_2")  # add sufixes to duplicate column names
#     )

## ----eval=FALSE---------------------------------------------------------------
# tre_combo <- tre_combo |>
#     endoaggregate(
#         viability_1=.SD[treatment2dose == 0, mean_viability],
#         assay="combo_viability",
#         by=c("treatment1id", "treatment1dose", "sampleid")
#     ) |>
#     endoaggregate(
#         viability_2=.SD[treatment1dose == 0, mean_viability],
#         assay="combo_viability",
#         by=c("treatment1id", "treatment2dose", "sampleid")
#     )

## ----compute_synergy_null_hypotheses, message=FALSE, eval=FALSE---------------
# tre_synergy <- tre_combo |>
#     endoaggregate(
#         assay="combo_viability",
#         HSA_ref=PharmacoGx::computeHSA(viability_1, viability_2),
#         Bliss_ref=PharmacoGx::computeBliss(viability_1, viability_2),
#         Loewe_ref=PharmacoGx::computeLoewe(
#             treatment1dose, HS_1=HS_1, EC50_1=EC50_1, E_inf_1=E_inf_1,
#             treatment2dose, HS_2=HS_2, EC50_2=EC50_2, E_inf_2=E_inf_2
#         ),
#         ZIP_ref=computeZIP(
#             treatment1dose, HS_1=HS_1, EC50_1=EC50_1, E_inf_1=E_inf_1,
#             treatment2dose, HS_2=HS_2, EC50_2=EC50_2, E_inf_2=E_inf_2
#         ),
#         by=assayKeys(tre_combo, "combo_viability"),
#         nthread=2
#     )

## ----synergy_score_vs_reference, eval=FALSE-----------------------------------
# tre_synergy <- tre_synergy |>
#     endoaggregate(
#         assay="combo_viability",
#         HSA_score=HSA_ref - mean_viability,
#         Bliss_score=Bliss_ref - mean_viability,
#         Loewe_score=Loewe_ref - mean_viability,
#         ZIP_score=ZIP_ref - mean_viability,
#         by=assayKeys(tre_synergy, "combo_viability")
#     )

## ----zip_two_way_fit, message=FALSE, eval=FALSE-------------------------------
# tre_zip <- tre_synergy |>
#     endoaggregate(
#         assay="combo_viability",
#         subset=treatment2dose != 0,
#         {
#             zip_fit <- estimateProjParams(
#                 dose_to=treatment1dose,
#                 combo_viability=mean_viability,
#                 dose_add=unique(treatment2dose),
#                 EC50_add=unique(EC50_2),
#                 HS_add=unique(HS_2),
#                 E_inf_add=unique(E_inf_2)
#             )
#             setNames(zip_fit, paste0(names(zip_fit), "_2_to_1"))
#         },
#         enlist=FALSE,
#         by=c("treatment1id", "treatment2id", "treatment2dose", "sampleid"),
#         nthread=2
#     )
# tre_zip <- tre_zip |>
#     endoaggregate(
#         assay="combo_viability",
#         subset=treatment1dose != 0,
#         {
#             zip_fit <- estimateProjParams(
#                 dose_to=treatment2dose,
#                 combo_viability=mean_viability,
#                 dose_add=unique(treatment1dose),
#                 EC50_add=unique(EC50_1),
#                 HS_add=unique(HS_1),
#                 E_inf_add=unique(E_inf_1)
#             )
#             setNames(zip_fit, paste0(names(zip_fit), "_1_to_2"))
#         },
#         enlist=FALSE,
#         by=c("treatment1id", "treatment2id", "treatment1dose", "sampleid"),
#         nthread=2
#     )

## ----compute_zip_delta, message=FALSE, eval=FALSE-----------------------------
# tre_zip <- tre_zip |>
#     endoaggregate(
#         assay="combo_viability",
#         ZIP_delta=.deltaScore(
#             EC50_1_to_2=EC50_proj_1_to_2, EC50_2_to_1=EC50_proj_2_to_1,
#             EC50_1=EC50_1, EC50_2=EC50_2,
#             HS_1_to_2=HS_proj_1_to_2, HS_2_to_1=HS_proj_2_to_1,
#             HS_1=HS_1, HS_2=HS_2,
#             E_inf_1_to_2=E_inf_proj_1_to_2, E_inf_2_to_1=E_inf_proj_2_to_1,
#             E_inf_1=E_inf_1, E_inf_2=E_inf_2,
#             treatment1dose=treatment1dose, treatment2dose=treatment2dose,
#             ZIP=ZIP_ref
#         ),
#         by=assayKeys(tre_zip, "combo_viability")
#     )

## ----compute_top_synergy, eval=FALSE------------------------------------------
# combo_viab <- tre_zip[["combo_viability"]]
# (top_15_combo <- combo_viab[
#     Rsq_1 > 0.5 & Rsqr_1_to_2 > 0.5 & Rsqr_2_to_1 > 0.5,
#     .(
#         max_delta=max(ZIP_delta, na.rm=TRUE),
#         mean_delta=mean(ZIP_delta, na.rm=TRUE),
#         max_bliss=max(Bliss_score, na.rm=TRUE),
#         mean_bliss=mean(Bliss_score, na.rm=TRUE)
#     ),
#     by=.(treatment1id, treatment2id, sampleid)
# ][
#     order(-max_delta),
#     unique(.SD)
# ][1:15])

## ----handle_synergy_missing, eval=FALSE---------------------------------------
# top_15_combo_df <- combo_viab[top_15_combo, on=c('treatment1id', 'treatment2id', 'sampleid')]
# # Last observation carried forward for NA/NaN delta scores, to make plot look nicer
# setnafill(top_15_combo_df, type="locf", cols="ZIP_delta")

## ----synergy_contour_plot, fig.wide=TRUE, eval=FALSE--------------------------
# top_15_combo_df |>
#     ggplot(aes(x=treatment1dose, y=treatment2dose, z=ZIP_delta * 100)) +
#     scale_x_log10(oob=scales::squish_infinite) +
#     scale_y_log10(oob=scales::squish_infinite) +
#     geom_contour_filled(
#         breaks=c(-100, -80, -40, -20, -10, -1, 1, 10, 20, 40, 80, 100)
#     ) +
#     facet_wrap(~ treatment1id, nrow=3, ncol=5) +
#     scale_fill_brewer(palette="RdBu", direction=-1, drop=FALSE)

## ----synergy_heatmap, fig.wide=TRUE, eval=FALSE-------------------------------
# top_15_combo_df |>
#     ggplot(aes(x=factor(treatment1dose), y=factor(treatment2dose))) +
#     geom_tile(aes(fill=ZIP_delta * 100)) +
#     facet_wrap(~treatment1id, nrow=3, ncol=5) +
#     scale_fill_gradient2(low="blue", mid="white", high="red", midpoint=0)

## ----sessionInfo, echo=FALSE--------------------------------------------------
sessionInfo()

