Compare commits

2 Commits

26 changed files with 457 additions and 3756 deletions
Vendored
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+47 -107
View File
@@ -23,26 +23,6 @@ library(car)
library(dplyr) library(dplyr)
library(scales) library(scales)
#' Estimate correlations
#'
#' returns the correlation of 2 vectors
#'
#' @param vec1 The 1st vector.
#' @param vec2 The 2nd vector.
#' @returns A float as correlatioin estimate
#' @export
#' @examples
#' suppressMessages(source("../../dev/setup.R"))
#' vector1 <- c(1,2,3,4,5)
#' vector2 <- c(5.1,4.3,NA,1.9,1.2)
#' te <- COR_FUNC(vector1,vector2)
#' print(te)
COR_FUNC <- function(vec1, vec2) {
df <- data.frame(v1 = vec1, v2 = vec2)
df2 <- df[complete.cases(df),]
#browser()
return(cor(df2[,1],df2[,2]))
}
#' Levenberg Marquard fit of 4 pl #' Levenberg Marquard fit of 4 pl
#' #'
@@ -66,9 +46,8 @@ COR_FUNC <- function(vec1, vec2) {
#' Dat <- list() #' Dat <- list()
#' te <- Fitting_FUNC(dat, TransF) #' te <- Fitting_FUNC(dat, TransF)
#' print(te) #' print(te)
Fitting_FUNC <- function(ro_new, TransFlag = FALSE, nameWS ="") { Fitting_FUNC <- function(ro_new, TransFlag = FALSE) {
#browser() CORro <- cor(ro_new[, 1], ro_new[, ncol(ro_new)])
CORro <- COR_FUNC(ro_new[, 1], ro_new[, ncol(ro_new)])
# browser() # browser()
all_l <- melt(data.frame(ro_new), id.vars = "log_dose", variable.name = "replname", value.name = "readout") all_l <- melt(data.frame(ro_new), id.vars = "log_dose", variable.name = "replname", value.name = "readout")
isRef <- rep(c(1, 0), 1, each = nrow(all_l) / 2) isRef <- rep(c(1, 0), 1, each = nrow(all_l) / 2)
@@ -90,7 +69,6 @@ Fitting_FUNC <- function(ro_new, TransFlag = FALSE, nameWS ="") {
}, },
warning = function(e) { warning = function(e) {
mr <<- "In nlsModel singular gradient matrix" mr <<- "In nlsModel singular gradient matrix"
} }
) )
# Stop if singular gradient matrix # Stop if singular gradient matrix
@@ -104,12 +82,6 @@ Fitting_FUNC <- function(ro_new, TransFlag = FALSE, nameWS ="") {
}, },
error = function(err) { error = function(err) {
s_mr <- NULL s_mr <- NULL
showModal(modalDialog(
title = " fit",
paste("fit not possible: EC50 outside concentration range for dataset", nameWS),
easyClose = TRUE,
footer = NULL
))
} }
) )
} else { } else {
@@ -126,7 +98,7 @@ Fitting_FUNC <- function(ro_new, TransFlag = FALSE, nameWS ="") {
if (!TransFlag) { if (!TransFlag) {
startlistmu <- list( startlistmu <- list(
as = min(ro_new[, 2]), bs = SLOPE, ds = max(ro_new[, 2]), cs = mean(all_l$log_dose), as = min(ro_new[, 2]), bs = SLOPE, ds = max(ro_new[, 2]), cs = mean(all_l$log_dose),
at = min(ro_new[, 4]), bt = SLOPE, dt = max(ro_new[, 4]), r = 0 at = min(ro_new[, 2]), bt = SLOPE, dt = max(ro_new[, 2]), r = 0
) )
tryCatch( tryCatch(
{ {
@@ -148,19 +120,13 @@ Fitting_FUNC <- function(ro_new, TransFlag = FALSE, nameWS ="") {
summary(mu) summary(mu)
}, },
error = function(msg) { error = function(msg) {
showModal(modalDialog(
title = "4PL fit",
paste("fit not possible: EC50 outside concentration range for dataset", nameWS),
easyClose = TRUE,
footer = NULL
))
return(0) return(0)
} }
) )
} else { } else {
startlistmu <- list( startlistmu <- list(
as = log(min(ro_new[, 2])), bs = SLOPE, ds = log(max(ro_new[, 2])), cs = mean(all_l$log_dose), as = log(min(ro_new[, 2])), bs = SLOPE, ds = log(max(ro_new[, 2])), cs = mean(all_l$log_dose),
at = log(min(ro_new[, 4])), bt = SLOPE, dt = log(max(ro_new[, 4])), r = 0 at = log(min(ro_new[, 2])), bt = SLOPE, dt = log(max(ro_new[, 2])), r = 0
) )
tryCatch( tryCatch(
{ {
@@ -186,28 +152,17 @@ Fitting_FUNC <- function(ro_new, TransFlag = FALSE, nameWS ="") {
} }
) )
} }
#browser()
if (!TransFlag) { if (!TransFlag) {
#browser()
if (length(s_mr) ==1 | length(Sum_u) ==1) {
return("failed")
} else {
pot_est <- exp(confintd(mr, "r", method = "asymptotic")) pot_est <- exp(confintd(mr, "r", method = "asymptotic"))
potU_est <- exp(confintd(mu, "r", method = "asymptotic")) potU_est <- exp(confintd(mu, "r", method = "asymptotic"))
PRED <- predict(mr) PRED <- predict(mr)
PREDu <- predict(mu) PREDu <- predict(mu)
}
} else {
if (length(s_mr) ==1 | length(Sum_u) ==1) {
return("failed")
} else { } else {
pot_est <- exp(confintd(mrT, "r", method = "asymptotic")) pot_est <- exp(confintd(mrT, "r", method = "asymptotic"))
potU_est <- exp(confintd(muT, "r", method = "asymptotic")) potU_est <- exp(confintd(muT, "r", method = "asymptotic"))
PRED <- predict(mrT) PRED <- predict(mrT)
PREDu <- predict(muT) PREDu <- predict(muT)
} }
}
return(list(s_mr, Sum_u, pot_est, potU_est, PRED, PREDu)) return(list(s_mr, Sum_u, pot_est, potU_est, PRED, PREDu))
} }
@@ -257,7 +212,7 @@ Fitting_FUNC <- function(ro_new, TransFlag = FALSE, nameWS ="") {
#' p <- plotSingularity(dat) #' p <- plotSingularity(dat)
#' print(p) #' print(p)
plotSingularity <- function(dat) { # sigmoid,det_sig, plotSingularity <- function(dat) { # sigmoid,det_sig,
CORdat <- COR_FUNC(dat[, 1], dat[, ncol(dat)]) CORdat <- cor(dat[, 1], dat[, ncol(dat)])
# browser() # browser()
all_l <- melt(data.frame(dat), id.vars = "log_dose", variable.name = "replname", value.name = "readout") all_l <- melt(data.frame(dat), id.vars = "log_dose", variable.name = "replname", value.name = "readout")
isRef <- rep(c(1, 0), 1, each = nrow(all_l) / 2) isRef <- rep(c(1, 0), 1, each = nrow(all_l) / 2)
@@ -317,7 +272,7 @@ plotSingularity <- function(dat) { # sigmoid,det_sig,
#' p <- plot_f(dat, TransFlag) #' p <- plot_f(dat, TransFlag)
#' print(p) #' print(p)
plot_f <- function(dat, TransFlag = FALSE) { # sigmoid,det_sig, plot_f <- function(dat, TransFlag = FALSE) { # sigmoid,det_sig,
CORdat <- COR_FUNC(dat[, 1], dat[, ncol(dat)]) CORdat <- cor(dat[, 1], dat[, ncol(dat)])
# browser() # browser()
all_l <- melt(data.frame(dat), id.vars = "log_dose", variable.name = "replname", value.name = "readout") all_l <- melt(data.frame(dat), id.vars = "log_dose", variable.name = "replname", value.name = "readout")
isRef <- rep(c(1, 0), 1, each = nrow(all_l) / 2) isRef <- rep(c(1, 0), 1, each = nrow(all_l) / 2)
@@ -711,7 +666,6 @@ ANOVAlintests <- function(ro_new, circles, Lim, PureErrFlag) {
all_l$isRef <- isRef all_l$isRef <- isRef
all_l$isSample <- isSample all_l$isSample <- isSample
all_l$Conc <- exp(all_l$log_dose) all_l$Conc <- exp(all_l$log_dose)
all_l <- all_l[complete.cases(all_l),]
all_lA <- all_l[all_l$isSample == 1, ] # TEST all_lA <- all_l[all_l$isSample == 1, ] # TEST
all_lB <- all_l[all_l$isSample == 0, ] # REF all_lB <- all_l[all_l$isSample == 0, ] # REF
# browser() # browser()
@@ -799,40 +753,40 @@ ANOVAlintests <- function(ro_new, circles, Lim, PureErrFlag) {
} }
# treatment # treatment
SStreat <- print(sum((predict(lm(readout ~ factor(log_dose) * isSample, circ_ABl)) - mean(circ_ABl$readout, na.rm = T))^2, na.rm = T)) SStreat <- print(sum((predict(lm(readout ~ factor(log_dose) * isSample, circ_ABl)) - mean(circ_ABl$readout))^2))
F_treat <- (SStreat / dfTreat) / (SSRes / dfRes) F_treat <- (SStreat / dfTreat) / (SSRes / dfRes)
# Preparation # Preparation
SSprep <- print(sum((predict(lm(readout ~ isSample, circ_ABl)) - mean(circ_ABl$readout, na.rm = T))^2, na.rm = T)) SSprep <- print(sum((predict(lm(readout ~ isSample, circ_ABl)) - mean(circ_ABl$readout))^2))
F_prep <- (SSprep / dfTreat) / (SSRes / dfRes) F_prep <- (SSprep / dfTreat) / (SSRes / dfRes)
# Regression # Regression
# ANOVA tape II SS of regression # ANOVA tape II SS of regression
SSreg <- Anova(lm(readout ~ log_dose + isSample, circ_ABl))[1, 1] SSreg <- Anova(lm(readout ~ log_dose + isSample, circ_ABl))[1, 1]
# Non-parallelism # Non-parallelism
# diff of RSS of restricted and unrestricted model # diff of RSS of restricted and unrestricted model
SSnonpar <- sum(resid(modAB)^2, na.rm = T) - sum(resid(modABu)^2, na.rm = T) SSnonpar <- sum(resid(modAB)^2) - sum(resid(modABu)^2)
F_nonpar <- SSnonpar / (sum(resid(lm(readout ~ factor(log_dose) * isSample, circ_ABl))^2, na.rm = T) / (lenCirc - 4)) F_nonpar <- SSnonpar / (sum(resid(lm(readout ~ factor(log_dose) * isSample, circ_ABl))^2) / (lenCirc - 4))
# non-linearity # non-linearity
SSnonlin <- sum((predict(modABu) - predict(lm(readout ~ as.factor(log_dose) * isSample, circ_ABl)))^2, na.rm = T) SSnonlin <- sum((predict(modABu) - predict(lm(readout ~ as.factor(log_dose) * isSample, circ_ABl)))^2)
# = RSS-SSE # = RSS-SSE
# Total SS # Total SS
SStot <- sum((circ_ABl$readout - mean(circ_ABl$readout, na.rm = T))^2, na.rm=T) SStot <- sum((circ_ABl$readout - mean(circ_ABl$readout))^2)
# Significance of R^2 F-ratio # Significance of R^2 F-ratio
# MSR/MSE # MSR/MSE
# sample A # sample A
F_R2_A <- sum((predict(lm(readout ~ log_dose + I(log_dose^2), circ_Al)) - mean(predict(modA), na.rm = T))^2 - (predict(modA) - mean(circ_Al$readout, na.rm = T))^2, na.rm = T) / F_R2_A <- sum((predict(lm(readout ~ log_dose + I(log_dose^2), circ_Al)) - mean(predict(modA)))^2 - (predict(modA) - mean(circ_Al$readout))^2) /
(sum((predict(lm(readout ~ log_dose + I(log_dose^2), circ_Al)) - circ_Al$readout)^2, na.rm = T) / (nrow(circ_Al) - 3)) (sum((predict(lm(readout ~ log_dose + I(log_dose^2), circ_Al)) - circ_Al$readout)^2) / (nrow(circ_Al) - 3))
pFR2_A <- round(pf(F_R2_A, 1, 6), 4) pFR2_A <- round(pf(F_R2_A, 1, 6), 4)
# sample B # sample B
F_R2_B <- sum((predict(lm(readout ~ log_dose + I(log_dose^2), circ_Bl)) - mean(predict(modB), na.rm = T))^2 - (predict(modB) - mean(circ_Bl$readout))^2, na.rm = T) / F_R2_B <- sum((predict(lm(readout ~ log_dose + I(log_dose^2), circ_Bl)) - mean(predict(modB)))^2 - (predict(modB) - mean(circ_Bl$readout))^2) /
(sum((predict(lm(readout ~ log_dose + I(log_dose^2), circ_Bl)) - circ_Bl$readout)^2, na.rm = T) / (nrow(circ_Bl) - 3)) (sum((predict(lm(readout ~ log_dose + I(log_dose^2), circ_Bl)) - circ_Bl$readout)^2) / (nrow(circ_Bl) - 3))
pFR2_B <- round(pf(F_R2_B, 1, 6), 4) pFR2_B <- round(pf(F_R2_B, 1, 6), 4)
# sign of non-lin with pure error: MSSnonlin/MSSE # sign of non-lin with pure error: MSSnonlin/MSSE
F_nonlin <- (SSnonlin / 2) / (SSE / dfPureE) F_nonlin <- (SSnonlin / 2) / (SSE / dfPureE)
# sign of slope # sign of slope
F_slope_B <- sum((predict(modB) - mean(circ_Bl$readout, na.rm = T))^2) / (sum((circ_Bl$readout - predict(modB))^2, na.rm = T) / (nrow(circ_Bl) - 2)) F_slope_B <- sum((predict(modB) - mean(circ_Bl$readout))^2) / (sum((circ_Bl$readout - predict(modB))^2) / (nrow(circ_Bl) - 2))
F_slope_A <- sum((predict(modA) - mean(circ_Al$readout, na.rm = T))^2) / (sum((circ_Al$readout - predict(modA))^2, na.rm = T) / (nrow(circ_Al) - 2)) F_slope_A <- sum((predict(modA) - mean(circ_Al$readout))^2) / (sum((circ_Al$readout - predict(modA))^2) / (nrow(circ_Al) - 2))
# F-test on regression: MSSreg/MSSE # F-test on regression: MSSreg/MSSE
if (is.na(F_nonlin)) F_nonlin <- 0 if (is.na(F_nonlin)) F_nonlin <- 0
if (F_nonlin > 0) { if (F_nonlin > 0) {
@@ -945,12 +899,11 @@ PlotLinPLA_FUNC <- function(circle, sigmoid, all_l2, pl_df, indS, indT) {
} }
p <- ggplot(all_l2, aes(x = log_dose, y = readout, color = factor(isRef))) + p <- ggplot(all_l2, aes(x = log_dose, y = readout, color = factor(isRef))) +
geom_point(size = 2) + geom_point(size = 2) +
# labs(title=paste("linear regression model", indS,indT), color="product") + # labs(title=paste("linear regression model", indS,indT), color="product") +
scale_colour_manual(labels = c("test", "reference"), values = c("#C2173F", "#4545BA")) + scale_colour_manual(labels = c("test", "reference"), values = c("#C2173F", "#4545BA")) +
ylim(min(all_l2$readout), max(all_l2$readout)) +
scale_x_continuous(breaks = scales::pretty_breaks(n = 10)) + scale_x_continuous(breaks = scales::pretty_breaks(n = 10)) +
scale_y_continuous(breaks = scales::pretty_breaks(n = 10)) + scale_y_continuous(breaks = scales::pretty_breaks(n = 10)) +
theme_bw() theme_bw()
@@ -984,7 +937,6 @@ PlotLinPLA_FUNC <- function(circle, sigmoid, all_l2, pl_df, indS, indT) {
x = log_dose, y = readout, shape = factor(isRef), x = log_dose, y = readout, shape = factor(isRef),
size = 5, alpha = 0.2 size = 5, alpha = 0.2
), col = c("black"), inherit.aes = FALSE) + ), col = c("black"), inherit.aes = FALSE) +
ylim(min(all_l2$readout), max(all_l2$readout)) +
scale_shape_manual(labels = c("test", "reference"), values = c(21, 21)) scale_shape_manual(labels = c("test", "reference"), values = c(21, 21))
# fit intercept for test and ref and common slope # fit intercept for test and ref and common slope
@@ -1021,7 +973,6 @@ PlotLinPLA_FUNC <- function(circle, sigmoid, all_l2, pl_df, indS, indT) {
title = paste("restricted linear regression model"), title = paste("restricted linear regression model"),
subtitle = paste("Regression on highlighted points") subtitle = paste("Regression on highlighted points")
) + ) +
ylim(min(all_l2$readout), max(all_l2$readout)) +
theme(legend.position = "none", axis.text = element_text(size = 14)) theme(legend.position = "none", axis.text = element_text(size = 14))
pr3 <- pr2 + geom_point(circle, mapping = aes( pr3 <- pr2 + geom_point(circle, mapping = aes(
x = log_dose, y = readout, shape = factor(isRef), x = log_dose, y = readout, shape = factor(isRef),
@@ -1067,7 +1018,7 @@ pot4plFUNC <- function(ro_new, PureErrFlag) {
all_l$readout[all_l$readout < 0] <- 0.01 all_l$readout[all_l$readout < 0] <- 0.01
all_l$readouttrans <- log(all_l$readout) all_l$readouttrans <- log(all_l$readout)
# browser() # browser()
CORdat <- COR_FUNC(ro_new[, 1], ro_new[, ncol(ro_new)]) CORdat <- cor(ro_new[, 1], ro_new[, ncol(ro_new)])
if (CORdat < 0) SLOPE <- -1 else SLOPE <- 1 if (CORdat < 0) SLOPE <- -1 else SLOPE <- 1
# #
FITs <- Fitting_FUNC(ro_new, TransFlag = FALSE) FITs <- Fitting_FUNC(ro_new, TransFlag = FALSE)
@@ -1161,8 +1112,8 @@ ParamCI_F <- function(xt, xs, se_xt, se_xs, CoVar, DFs, Conf = 0.975) {
var_log_xt <- (se_xt / xt)^2 var_log_xt <- (se_xt / xt)^2
se_log_ratio <- sqrt(var_log_xs + var_log_xt) #-2*CoVar/(xs*xt) se_log_ratio <- sqrt(var_log_xs + var_log_xt) #-2*CoVar/(xs*xt)
lower_log_ratio <- log_xs - log_xt - qt(Conf, DFs) * se_log_ratio lower_log_ratio <- log_xt - log_xs - qt(Conf, DFs) * se_log_ratio
upper_log_ratio <- log_xs - log_xt + qt(Conf, DFs) * se_log_ratio upper_log_ratio <- log_xt - log_xs + qt(Conf, DFs) * se_log_ratio
ci_ratio <- exp(c(lower_log_ratio, upper_log_ratio)) ci_ratio <- exp(c(lower_log_ratio, upper_log_ratio))
return(ci_ratio) return(ci_ratio)
} }
@@ -1192,9 +1143,6 @@ ParamCI_F <- function(xt, xs, se_xt, se_xs, CoVar, DFs, Conf = 0.975) {
#' #'
#' tests_FUNC(ro_new=dat, Lim, PureErrF) #' tests_FUNC(ro_new=dat, Lim, PureErrF)
tests_FUNC <- function(ro_new, Lim, PureErrFlag) { tests_FUNC <- function(ro_new, Lim, PureErrFlag) {
DatL <- list()
all_l <- melt(data.frame(ro_new), id.vars = "log_dose", variable.name = "replname", value.name = "readout") all_l <- melt(data.frame(ro_new), id.vars = "log_dose", variable.name = "replname", value.name = "readout")
isRef <- rep(c(1, 0), 1, each = nrow(all_l) / 2) isRef <- rep(c(1, 0), 1, each = nrow(all_l) / 2)
isSample <- rep(c(0, 1), 1, each = nrow(all_l) / 2) isSample <- rep(c(0, 1), 1, each = nrow(all_l) / 2)
@@ -1202,7 +1150,6 @@ tests_FUNC <- function(ro_new, Lim, PureErrFlag) {
all_l$isSample <- isSample all_l$isSample <- isSample
all_l$Conc <- exp(all_l$log_dose) all_l$Conc <- exp(all_l$log_dose)
all_l$readout[all_l$readout < 0] <- 0.01 all_l$readout[all_l$readout < 0] <- 0.01
all_l <- all_l[complete.cases(all_l),]
# browser() # browser()
FITs <- Fitting_FUNC(ro_new = ro_new, TransFlag = FALSE) FITs <- Fitting_FUNC(ro_new = ro_new, TransFlag = FALSE)
if (is.character(FITs)) { if (is.character(FITs)) {
@@ -1225,7 +1172,7 @@ tests_FUNC <- function(ro_new, Lim, PureErrFlag) {
VCOVpure <- V_V * meanPureErr VCOVpure <- V_V * meanPureErr
DFsPure <- FitAnova[4, 1] DFsPure <- FitAnova[4, 1]
#browser()
testPOTr <- logical() testPOTr <- logical()
if (POTr_CI[1] * 100 > Lim[[9]] & POTr_CI[2] * 100 < Lim[[10]]) testPOTr <- 0 else testPOTr <- 1 if (POTr_CI[1] * 100 > Lim[[9]] & POTr_CI[2] * 100 < Lim[[10]]) testPOTr <- 0 else testPOTr <- 1
@@ -1241,19 +1188,19 @@ tests_FUNC <- function(ro_new, Lim, PureErrFlag) {
noConc <- length(unique(all_l$Conc)) noConc <- length(unique(all_l$Conc))
nofitted <- noConc nofitted <- noConc
AnovaDFs <- c(nofitted - 1, 1, 3, nofitted - 4 - 1, nrow(all_l) - nofitted, nofitted, nrow(all_l) - 2 * nofitted, nrow(all_l) - 1) AnovaDFs <- c(nofitted - 1, 1, 3, nofitted - 4 - 1, nrow(all_l) - nofitted, nofitted, nrow(all_l) - 2 * nofitted, nrow(all_l) - 1)
SStreat <- round(sum((predPotU - mean(all_l$readout, na.rm = T))^2, na.rm = T), 5) SStreat <- round(sum((predPotU - mean(all_l$readout))^2), 5)
SSregr <- round(sum((predPot - mean(all_l$readout, na.rm=T))^2, na.rm=T), 5) SSregr <- round(sum((predPot - mean(all_l$readout))^2), 5)
# non-parallelism # non-parallelism
SSnonparall <- round(sum(smr$residuals^2, na.rm=T) - sum(smu$residuals^2, na.rm=T), 5) SSnonparall <- round(sum(smr$residuals^2) - sum(smu$residuals^2), 5)
SSprep <- round(sum((predict(lm(readout ~ isSample, all_l)) - mean(all_l$readout, na.rm=T))^2, na.rm=T), 5) SSprep <- round(sum((predict(lm(readout ~ isSample, all_l)) - mean(all_l$readout))^2), 5)
# browser()
RSS <- round(sum(smu$residuals^2, na.rm=T), 5) RSS <- round(sum(smu$residuals^2), 5)
RSS_df <- AnovaDFs[5] RSS_df <- AnovaDFs[5]
MSEunr <- RSS / RSS_df MSEunr <- RSS / RSS_df
RMSEunr <- sqrt(RSS / RSS_df) RMSEunr <- sqrt(RSS / RSS_df)
# Pure Err # Pure Err
FitAnova <- anova(lm(readout ~ factor(Conc) * isSample, all_l)) FitAnova <- anova(lm(readout ~ factor(Conc) * isSample, all_l))
SSE <- sum(resid(lm(readout ~ factor(Conc) * isSample, all_l))^2, na.rm=T) # =FitAnova[4,2] SSE <- sum(resid(lm(readout ~ factor(Conc) * isSample, all_l))^2) # =FitAnova[4,2]
SSE_df <- FitAnova[4, 1] SSE_df <- FitAnova[4, 1]
PureMSE <- SSE / SSE_df PureMSE <- SSE / SSE_df
RMSE_pure <- sqrt(PureMSE) RMSE_pure <- sqrt(PureMSE)
@@ -1278,12 +1225,12 @@ tests_FUNC <- function(ro_new, Lim, PureErrFlag) {
test_a <- test_b <- test_d <- test_ad <- logical() test_a <- test_b <- test_d <- test_ad <- logical()
RSS_r <- round(sum(smr$residuals^2, na.rm=T), 5) RSS_r <- round(sum(smr$residuals^2), 5)
MSE_r <- RSS_r / (nrow(all_l) - 5) MSE_r <- RSS_r / (nrow(all_l) - 5)
RMSE_r <- round(sqrt(MSE_r), 6) RMSE_r <- round(sqrt(MSE_r), 6)
DatL$RMSE_r <- RMSE_r Dat$RMSE_r <- RMSE_r
DatL$RMSE_pure <- RMSE_pure Dat$RMSE_pure <- RMSE_pure
DatL$RMSE_unr <- round(RMSEunr, 6) Dat$RMSE_unr <- round(RMSEunr, 6)
coeffs <- smu$coefficients[, 1] coeffs <- smu$coefficients[, 1]
# browser() # browser()
@@ -1295,7 +1242,6 @@ tests_FUNC <- function(ro_new, Lim, PureErrFlag) {
lCI_laDiff <- lAs_diff - qt(0.975, smu$df[2]) * sqrt(smu$coefficients["ds", 2]^2 + smu$coefficients["dt", 2]^2) lCI_laDiff <- lAs_diff - qt(0.975, smu$df[2]) * sqrt(smu$coefficients["ds", 2]^2 + smu$coefficients["dt", 2]^2)
if (uCI_laDiff < Lim[[2]] & lCI_laDiff > Lim[[1]]) test_la_diff <- 0 else test_la_diff <- 1 if (uCI_laDiff < Lim[[2]] & lCI_laDiff > Lim[[1]]) test_la_diff <- 0 else test_la_diff <- 1
#browser()
#### EQ test on upper asymptote ratio ---- #### EQ test on upper asymptote ratio ----
# as <- coeffs["as"] # as <- coeffs["as"]
# at <- coeffs["at"] # at <- coeffs["at"]
@@ -1308,12 +1254,11 @@ tests_FUNC <- function(ro_new, Lim, PureErrFlag) {
if (PureErrFlag) se_dt <- sqrt(VCOVpure["dt", "dt"]) else se_dt <- smu$coefficients["dt", 2] if (PureErrFlag) se_dt <- sqrt(VCOVpure["dt", "dt"]) else se_dt <- smu$coefficients["dt", 2]
if (PureErrFlag) CoVarlog_d <- VCOVpure["dt", "ds"] else CoVarlog_d <- vcovMU["dt", "ds"] if (PureErrFlag) CoVarlog_d <- VCOVpure["dt", "ds"] else CoVarlog_d <- vcovMU["dt", "ds"]
if (PureErrFlag) DFs <- DFsPure else DFs <- nrow(all_l) - 8 if (PureErrFlag) DFs <- DFsPure else DFs <- nrow(all_l) - 8
uAsCI2 <- ParamCI_F(ds, dt, se_dt, se_ds, CoVarlog_d, DFs, Conf = 0.975) uAsCI2 <- ParamCI_F(dt, ds, se_dt, se_ds, CoVarlog_d, DFs, Conf = 0.975)
if (uAsCI2[1] > Lim[[7]] & uAsCI2[2] < Lim[[8]]) test_a <- 0 else test_a <- 1 if (uAsCI2[1] > Lim[[7]] & uAsCI2[2] < Lim[[8]]) test_a <- 0 else test_a <- 1
estUppA <- round(dt / ds, 5) estUppA <- round(at / as, 5)
DatL$uAsCI <- uAsCI2 Dat$uAsCI <- uAsCI2
# browser()
#### EQ test on slope ratio ---- #### EQ test on slope ratio ----
# bs <- coeffs["bs"] # bs <- coeffs["bs"]
@@ -1326,11 +1271,11 @@ tests_FUNC <- function(ro_new, Lim, PureErrFlag) {
if (PureErrFlag) se_bs <- sqrt(VCOVpure["bs", "bs"]) else se_bs <- smu$coefficients["bs", 2] if (PureErrFlag) se_bs <- sqrt(VCOVpure["bs", "bs"]) else se_bs <- smu$coefficients["bs", 2]
if (PureErrFlag) se_bt <- sqrt(VCOVpure["bt", "bt"]) else se_bt <- smu$coefficients["bt", 2] if (PureErrFlag) se_bt <- sqrt(VCOVpure["bt", "bt"]) else se_bt <- smu$coefficients["bt", 2]
if (PureErrFlag) CoVarlog_b <- VCOVpure["bt", "bs"] else CoVarlog_b <- vcovMU["bt", "bs"] if (PureErrFlag) CoVarlog_b <- VCOVpure["bt", "bs"] else CoVarlog_b <- vcovMU["bt", "bs"]
slopeCI2 <- ParamCI_F(bs, bt, se_bt, se_bs, CoVarlog_b, DFs, Conf = 0.975) slopeCI2 <- ParamCI_F(bt, bs, se_bt, se_bs, CoVarlog_b, DFs, Conf = 0.975)
if (slopeCI2[1] > Lim[[5]] & slopeCI2[2] < Lim[[6]]) test_b <- 0 else test_b <- 1 if (slopeCI2[1] > Lim[[5]] & slopeCI2[2] < Lim[[6]]) test_b <- 0 else test_b <- 1
estSlope <- round(abs(bt) / abs(bs), 5) estUppA <- round(at / as, 5)
DatL$slopeRatioCI <- slopeCI2 Dat$slopeRatioCI <- slopeCI2
#### EQ test on lower As ratio ---- #### EQ test on lower As ratio ----
@@ -1342,11 +1287,11 @@ tests_FUNC <- function(ro_new, Lim, PureErrFlag) {
if (PureErrFlag) se_as <- sqrt(VCOVpure["as", "as"]) else se_as <- smu$coefficients["as", 2] if (PureErrFlag) se_as <- sqrt(VCOVpure["as", "as"]) else se_as <- smu$coefficients["as", 2]
if (PureErrFlag) se_at <- sqrt(VCOVpure["at", "at"]) else se_at <- smu$coefficients["at", 2] if (PureErrFlag) se_at <- sqrt(VCOVpure["at", "at"]) else se_at <- smu$coefficients["at", 2]
if (PureErrFlag) CoVarlog_a <- VCOVpure["at", "as"] else CoVarlog_a <- vcovMU["at", "as"] if (PureErrFlag) CoVarlog_a <- VCOVpure["at", "as"] else CoVarlog_a <- vcovMU["at", "as"]
lAsCI2 <- ParamCI_F(as, at, se_at, se_as, CoVarlog_a, DFs, Conf = 0.975) lAsCI2 <- ParamCI_F(at, as, se_at, se_as, CoVarlog_a, DFs, Conf = 0.975)
if (lAsCI2[1] > Lim[[3]] & lAsCI2[2] < Lim[[4]]) test_d <- 0 else test_d <- 1 if (lAsCI2[1] > Lim[[3]] & lAsCI2[2] < Lim[[4]]) test_d <- 0 else test_d <- 1
estLowA <- round(at / as, 5) estLowA <- round(at / as, 5)
DatL$lAsCI <- lAsCI2 Dat$lAsCI <- lAsCI2
#### EQtest on ratio of As difference ---- #### EQtest on ratio of As difference ----
AsDiffRatio <- (dt - at) / (ds - as) AsDiffRatio <- (dt - at) / (ds - as)
@@ -1360,11 +1305,11 @@ tests_FUNC <- function(ro_new, Lim, PureErrFlag) {
if (PureErrFlag) se_ds_as <- se_ds_asPure else se_ds_as <- se_ds_asRMSE if (PureErrFlag) se_ds_as <- se_ds_asPure else se_ds_as <- se_ds_asRMSE
if (PureErrFlag) se_dt_at <- se_dt_atPure else se_dt_at <- se_dt_atRMSE if (PureErrFlag) se_dt_at <- se_dt_atPure else se_dt_at <- se_dt_atRMSE
AsDiffCI2 <- ParamCI_F( ds_as,dt_at, se_dt_at, se_ds_as, CoVar = 0, DFs, Conf = 0.975) AsDiffCI2 <- ParamCI_F(dt_at, ds_as, se_dt_at, se_ds_as, CoVar = 0, DFs, Conf = 0.975)
if (AsDiffCI2[1] > Lim[[11]] & AsDiffCI2[2] < Lim[[12]]) test_ad <- 0 else test_ad <- 1 if (AsDiffCI2[1] > Lim[[11]] & AsDiffCI2[2] < Lim[[12]]) test_ad <- 0 else test_ad <- 1
estDiffA <- round(dt_at /ds_as, 5) estLowA <- round(at / as, 5)
Dat$estDiffA <- estDiffA Dat$up_lowAs <- abs(ds - as)
lowerCIlowerA <- lAsCI2[1] lowerCIlowerA <- lAsCI2[1]
lowerCIupperA <- uAsCI2[1] lowerCIupperA <- uAsCI2[1]
@@ -1392,8 +1337,8 @@ tests_FUNC <- function(ro_new, Lim, PureErrFlag) {
), ),
estimate = c( estimate = c(
round(p_F_regr, 3), round(lAs_diff, 5), round(p_F_regr, 3), round(lAs_diff, 5),
estLowA, estSlope, estUppA, p_F_nonlin, estLowA, round(bs / bt, 5), estUppA, p_F_nonlin,
estDiffA, round(potAll2[1] * 100, 2), round(potAllU2[1] * 100, 2) round(dt_at / ds_as, 5), round(potAll2[1] * 100, 2), round(potAllU2[1] * 100, 2)
), ),
lower_limit = c("-", Lim[[1]], Lim[[3]], Lim[[5]], Lim[[7]], "-", Lim[[11]], Lim[[9]], Lim[[9]]), lower_limit = c("-", Lim[[1]], Lim[[3]], Lim[[5]], Lim[[7]], "-", Lim[[11]], Lim[[9]], Lim[[9]]),
upper_limit = c("-", Lim[[2]], Lim[[4]], Lim[[6]], Lim[[8]], "-", Lim[[12]], Lim[[10]], Lim[[10]]), upper_limit = c("-", Lim[[2]], Lim[[4]], Lim[[6]], Lim[[8]], "-", Lim[[12]], Lim[[10]], Lim[[10]]),
@@ -1430,10 +1375,7 @@ tests_FUNC <- function(ro_new, Lim, PureErrFlag) {
#' ANOVA4plUnresfunc(ro_new) #' ANOVA4plUnresfunc(ro_new)
#' #'
ANOVA4plUnresfunc <- function(ro_new) { ANOVA4plUnresfunc <- function(ro_new) {
all_l <- melt(data.frame(ro_new), id.vars = "log_dose", variable.name = "replname", value.name = "readout") all_l <- melt(data.frame(ro_new), id.vars = "log_dose", variable.name = "replname", value.name = "readout")
#browser()
all_len <- nrow(all_l) all_len <- nrow(all_l)
isRef <- rep(c(1, 0), 1, each = all_len / 2) isRef <- rep(c(1, 0), 1, each = all_len / 2)
isSample <- rep(c(0, 1), 1, each = all_len / 2) isSample <- rep(c(0, 1), 1, each = all_len / 2)
@@ -1441,8 +1383,6 @@ ANOVA4plUnresfunc <- function(ro_new) {
all_l$isSample <- isSample all_l$isSample <- isSample
all_l$Conc <- exp(all_l$log_dose) all_l$Conc <- exp(all_l$log_dose)
all_l$readout[all_l$readout < 0] <- 0.01 all_l$readout[all_l$readout < 0] <- 0.01
all_l <- all_l[complete.cases(all_l),]
FITs <- Fitting_FUNC(ro_new = ro_new, TransFlag = FALSE) FITs <- Fitting_FUNC(ro_new = ro_new, TransFlag = FALSE)
smr <- FITs[[1]] smr <- FITs[[1]]
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
-335
View File
@@ -1,335 +0,0 @@
---
output:
pdf_document:
extra_dependencies: ["float"]
number_sections: true
toc: true
toc_depth: 3
header_includes:
-\usepackage{fancyheadr}
-\setlength{\headheight}{22pt}%
-\usepackage{lastpage}
-\pagestyle{fancy}
-\usepackage{pdflscape}
-\usepackage{longtable}
-\rhead{\includegraphics[width=.15\textwidth]{`r getwd()`/logov2.png}}
params:
FileName: NA
author: NA
NoP: NA
Assay: NA
REP: NA
coeffs: NA
author: "Author: `r params$author`"
title: |
| ![](logov2.png){width=1in}
| 4PL bioassay evaluation
subtitle: |
`r params$FileName`
<left> Unique time: </left> <right> `r Sys.time()`</right>
date: "`r paste(params$NoP, params$Assay)`"
---
<!-- \fancyfoot[C]{\thepage\ of \pageref{LastPage}} -->
<!-- \newpage -->
<!-- \newpage -->
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(knitr)
library(DT)
library(kableExtra)
REP <- params$REP
author <- params$author
coeffs <- params$coeffs
all_l <- REP$all_l
#ANOVAXLS <- REP$ANOVAXLS
#XLplot4pl <- REP$XLplot4pl
DiagnTable <- REP$DiagnTable
UnRPLAausw <- REP$UnRPLAausw
UnRPLBend <- REP$UnRPLBend
PLAausw <- REP$PLAausw
PLbend <- REP$PLBend
pottab4plXL <- REP$pottab4plXL
Lim <- REP$Lim
XLdat2 <- REP$XLdat2
PureErr <- REP$PureErr
ro_newROUT <- REP$ro_newROUT
ROUTplot <- REP$ROUTplot
ANOVA_ROUT <- REP$ANOVA_ROUT
CIplot <- REP$CIplot
testsTabROUT <- REP$testsTabROUT
relpotTestPlot <- REP$relpotTestPlot
#browser()
```
# Introduction
Bioassay potency estimation uses statistical methods to quantify the strength of a biological product or drug by comparing its response to that of a reference standard. Because biological responses are inherently variable, affected by assay conditions, cell systems or organisms, and measurement noise, the 4-parametric logistic regression is used to obtain reliable potency values.
USP<1034> recommends calculation of standard errors of ratios of the parameters using Fieller's theorem [1] or using the "delta" method (for a discussion about the "delta" method see [3]). The gradient approach using the differences on the log-scale is mathematically more stable und thus preferable compared to a ratio approach [2].
# Raw data
All data used for the 4PL evaluation is shown in table 1:
```{r alll, echo=FALSE, warning=FALSE, results='asis'}
kable(XLdat2, format = "markdown", caption= "Uploaded data (test and reference) ", digits=3)
if (!is.null(ro_newROUT)) {
kable(ro_newROUT, format = "markdown", caption= "Data after exclusion of suspected outliers (see [6]) ", digits=3)
}
```
# Results
## Overall result
```{r Over_all, echo=FALSE, comment=NA, warning=NA, message=NA}
browser()
potFlag <- 0
if (pottab4plXL["test_result"][[1]][1]=="failed") potFlag <- 1
AnalysisFlag <- FALSE
if (potFlag==1 | sum(testsTabROUT$test_results)>0) AnalysisFlag <- TRUE
colFmt <- function() {
outputFormat <- knitr::opts_knit$get("rmarkdown.pandoc.to")
if(AnalysisFlag) {
text <- paste("\\textcolor{red}{Analysis failed}",sep="")
} else {
text <- paste("\\textcolor{black}{Analysis succeeded}",sep="")
}
return(text)
}
```
`r colFmt()`
## 4pl-regression
Relative potency (absolute and relative confidence limits) are shown in Table 3. `r if(PureErr) {"Pure Error is used for calculations."}`
`r if (!PureErr) {"RMSE of restricted model is used for confidence limit calculation."}`
```{r Pot_tab4pl, echo=FALSE, comment=NA, warning=NA, message=NA}
#browser()
if (pottab4plXL["test_result"][[1]][1]==1) { cat(paste("FAILED: relative potency CL result of restricted model outside limits: ", Lim[[9]], "to" ,Lim[[10]] ))}
if (pottab4plXL["test_result"][[1]][1]==0) { cat(paste("PASSED: relative potency CL result of restricted model within limits: ", Lim[[9]], "to" ,Lim[[10]] ))}
kable(pottab4plXL, format = "markdown", caption= "Relative potency with absolute and relative CLs ", digits=3, row.names = F) %>%
kable_styling(latex_options = "hold_position")
```
NOTE: results of unrestricted model for Information only.
## Plot of the data and models
Plots in Figure 1 shows the restricted model.
```{r XLplot, echo=FALSE, warning=FALSE, fig.height=4, fig.width=6, fig.cap="Plot of models", fig.align='left', comment=F, message=F, results='asis', fig.pos='H'}
plot(ROUTplot)
```
## ANOVA table
The ANOVA of the unconstrained model is listed in table 4. Bates and Watts [4] proposed a test on parallelism which compares the residual sum of squares of the restricted model (ResRSSE) with the residual sum of squares of the unrestricted model (UnresRSSE). If the UnresRSSE is significantly smaller than the ResRSSE, the p-value of "Non-parallelism" is smaller than 0.05 (line 4 in table 4). This test is for information only as it may be overly sensitive in case of small overall variability of the data.
```{r anovaxls, echo=FALSE, warning=FALSE, results='asis'}
kable(ANOVA_ROUT, format = "markdown", caption= "Analysis of variance", digits=3) %>%
kable_styling(latex_options = "hold_position")
```
## Assay suitability tests
Table 5 lists the chosen suitability test results with confidence limits, where applicable. F-tests should be read with caution, if the overall variability is small, as the test gets overly sensitive.
```{r SST_ergebn, echo=FALSE, cache=FALSE, warning=FALSE, message=FALSE, tidy=TRUE}
kable(testsTabROUT, row.names = F, format = "markdown", caption="Assay suitability results", digits=4)
```
\footnotesize
```{r Fussnote, echo=F, comment=NA}
cat("*...The estimate for F-test on regression and on non-linearity is the p-value")
cat( "F-test on regression passes if F-value > F-crit and thus p < 0.05")
cat( "F-test on non-linearity passes if F-value < F-crit and thus p > 0.05")
cat( "Test results outcome:")
cat(" 0 ... test passed (for EQ tests: CL within limits);")
cat(" 1 ... test failed (for EQ tests: CL not within limits);")
```
\normalsize
```{r AST_Ergebn, echo=FALSE, cache=FALSE, warning=FALSE, message=FALSE, tidy=TRUE}
TestsTabFlag <- FALSE
if (sum(testsTabROUT$test_results)>0) TestsTabFlag <- TRUE
colFmt2 <- function() {
outputFormat <- knitr::opts_knit$get("rmarkdown.pandoc.to")
if(TestsTabFlag) {
text <- paste("\\textcolor{red}{Assay suitability tests failed}",sep="")
} else {
text <- paste("\\textcolor{black}{Assay suitability tests succeeded}",sep="")
}
return(text)
}
```
`r colFmt2()`
## Fitting results with curve points
The results of the non-linear fitting procedure for the restricted model (5 parameters) is listed in table 5:
```{r PLAausw, echo=FALSE, warning=FALSE, results='asis'}
kable(PLAausw, format = "markdown", caption= "Restricted 4PL model", digits=3, row.names = F)
```
Sebaugh et al proposed bend points for test and reference samples, that define the points with highest turning behavior. Table 6 lists these bendpoints as well as asymptote points ~ twice as far from the center as the bendpoints.
```{r PLBend, echo=FALSE, warning=FALSE, results='asis'}
kable(PLbend, format = "markdown", caption= "Bendpoints and asymptote points of restricted 4PL model", digits=3)
```
The results of the non-linear fitting procedure for the unrestricted model (8 parameters) is listed in table 7:
```{r UnRPLAausw, echo=FALSE, warning=FALSE, results='asis'}
kable(UnRPLAausw, format = "markdown", caption= "Unrestricted 4PL model", digits=3, row.names = F)
```
# Signature
\vspace{1.5cm}
\noindent
\begin{tabular}{p{6cm}p{1cm}p{6cm}}
\cline{1-1} \cline{3-3}
Date & & Signature
\end{tabular}
\newpage
# Appendix: Formulas
## 4PL regression
$$
Y = D + \frac{A-D} {1+(\frac{C} {x})^B } + \epsilon
$$
where: x ... concentration of the analyte
A: upper asymptote
B: slope
D: lower asymptote
C ... EC50
## log-logistic 4P regression
$$
Y = D + \frac{A-D} {1+e^{(B*(C - log(x))) }} + \epsilon
$$
## Intercept for slope at EC50
$$
I = A+\frac{D-A}{2}-B_{true}*EC50
$$
## Slope at EC50
$$
B_{true}=B*\frac{D-A}{4}
$$
## Confidence intervals
In general, the confidence intervals are calculated as follows:
$$
CI = \hat\theta\pm se(\hat\theta)*q^{t_{n-p}}_{1-\frac{\alpha}{2}}
$$
…where $\hat\theta$ is a fitted parameter or a linear combination thereof, q is the 1-alpha/2 quantile of the Students t-distribution with n-p degrees of freedom and se is the standard error derived from any covariance matrix.
Let $\theta$ be the 4+1 parameters of the fit (a, b, d, EC50 of reference and EC50 difference). It can be shown that the least squares estimator $\hat\theta$ is normally distributed with asymptotic covariance matrix. The gradient method provides one of several ways to calculate the covariance matrix:
$$
\hat{V(\theta)}= \sigma^2(A(\hat\theta)^T*A(\hat\theta))^{-1}
$$
where A($\theta$) is the n x p matrix of the first partial derivatives for each parameter (i.e. gradient) realized at the fitted parameter estimates. The RMSE of the model or the pure error is used as estimate of $\sigma$. The square root of the diagonals of $\hat{V(\theta)}$ gives the standard errors and with that confidence intervals (CI) can be computed.
# Literature
[1] Finney, D.J.: (1978) Statistical Method in Biological Assay, London: Charles Griffin House, 3rd edition (pp. 80-82)
[2] Franz, V.H.: Ratios: A short guide to confidence limits and proper use. arXiv:0710.2024v1, 10 Oct 2007
[3] VerHoef, J.M.: Who invented the Delta Method? The American Statistician, 2012, 66:2, 124-127 DOI: 10.1080/00031305.2012.687494
[4] Bates, D.M., Watts, D.G. (1988). Comparing models. In: Nonlinear Regression Analysis and Its Applications. New York: Wiley, pp 103-108
[5] Bates, D.M., Watts, D.G. (1988) 2. In: Nonlinear Regression Analysis and Its Applications. New York: Wiley, pp 52-58
[6] Motulsky, Brown Outlier testing
-267
View File
@@ -1,267 +0,0 @@
################################################################################
# F.Innerbichler
# Jun 2026
# Robust Outlier detection
################################################################################
# Code acc. to Mutulsky and Brown hpptps://pubmed.ncbi.nlm.nih.gov/16526949/
# except line 175 p <- 2*(1-pt(z, length(residuals)-5)) was exchanged with p <- 2*(1-pcauchy(z)) to be robust
library(minpack.lm)
library(ggplot2)
library(rstudioapi)
# Getting path for current open file
current_path = rstudioapi::getActiveDocumentContext()$path
setwd(dirname(current_path))
outsPlot_FUN <- function(all_l,OUTs_, TS, PROC = "not specified", PROBE="", Q=0.01, par) {
#browser()
#all_l_rout <- all_l[KEEP,]
klein <- min(log(all_l$conc))
gross <- max(log(all_l$conc))
x_seq <- seq(klein, gross, (gross-klein)/100)
samTRUE <- f4pl(x=x_seq, bottom=par["a"], top=par["d"],hill=par["b"], logEC50=par["cs"]-par["r"])
refTRUE <- f4pl(x=x_seq, bottom=par["a"], top=par["d"],hill=par["b"], logEC50=par["cs"])
pl_T <- data.frame(cbind(x_seq, refTRUE, samTRUE))
p <- ggplot(all_l) +
geom_point(aes(x=log(conc), y=y, shape=factor(isRef)), size=2) +
theme_bw()
p2 <- p + geom_point(OUTs_, mapping=aes(x=log(conc), y=y, shape=factor(isRef)),
size=5, color="violetred", stroke=2, inherit.aes = FALSE) +
scale_shape_manual(label=c("R",TS), values = c(21,25)) +
ggtitle(paste(PROC, PROBE, TS, "Threshold=", Q)) +
theme(legend.title=element_blank())
p3 <- p2 + geom_line(data=pl_T, aes(x=x_seq, y=refTRUE), color="blue", inherit.aes = F) +
geom_line(data=pl_T, aes(x=x_seq, y=samTRUE), color="red", inherit.aes = F)
p3
}
#### 4PL model ----
f4pl <- function(x, bottom, top, logEC50, hill) {
bottom+(top-bottom)/(1+exp((logEC50-x)*hill))
}
#### residuals for joint REF/TEST fit ----
resid_4pl_joint <- function(par,x,y, is_ref) {
bottom <- par["bottom"]
top <- par["top"]
hill <- par["hill"]
le50_r <- par["logEC50_ref"]
le50_t <- par["logEC50_test"]
le50 <- ifelse(is_ref, le50_r, le50_t)
yhat <- f4pl(x, bottom, top, le50, hill)
y - yhat
}
jac_4pl_joint <- function(par, x,y,is_ref) {
bottom <- par["bottom"]
top <- par["top"]
hill <- par["hill"]
le50_r <- par["logEC50_ref"]
le50_t <- par["logEC50_test"]
le50 <- ifelse(is_ref, le50_r, le50_t)
# useful intermediates
texp <- exp((le50-x)*hill) # t = 10^((le50-x)*hill))
den <- (1-texp)
frac <- (top-bottom)/den
dyhat_dbottom <- 1-1/den
dyhat_dtop <- 1/den
d_invden_dle50 <- -(texp*log(2.718282)*hill)/(den^2)
d_invden_dhill <- -(texp*log(2.718282)*(le50-x))/(den^2)
dyhat_dle50 <- (top-bottom)* d_invden_dle50
dyhat_dhill <- (top-bottom)* d_invden_dhill
J <- cbind(
bottom = -dyhat_dbottom,
topm = -dyhat_dtop,
hill = -dyhat_dhill,
logEC50_ref = ifelse(is_ref, -dyhat_dle50,0),
logEC50_test = ifelse(!is_ref, -dyhat_dle50,0)
)
J
}
robust_fit_irls <- function(par_start, x,y, is_ref,
max_outer = 30, control = nls.lm.control(maxiter=200, ftol=1e-10, ptol=1e-10)) {
par <- par_start
#browser()
for (k in seq_len(max_outer)) {
r <- resid_4pl_joint(par,x,y,is_ref)
# Mot Brown
rSD <- quantile(r, 0.6827)*length(is_ref)/(length(is_ref)-5)
# Robust scale (MAD); fallback if MAD ~0
# s <- median(abs(r))/0.6745
# Lorentzian / Cauchy weights acc. Mot/Brown
w <- 1/log(1+(abs(r)/rSD)^2)
# weighted residual function lor LM: sqrt(w)*r
fn_w <- function(p) {
rr <- resid_4pl_joint(p,x,y,is_ref)
sqrt(w)*rr
# w*rr
}
jac_w <- function(p) {
JJ <- jac_4pl_joint(p,x,y,is_ref)
JJ*sqrt(w) # row-wise scaling
# JJ*w
}
#browser()
fit <- tryCatch(nls.lm(par=par, fn=fn_w, jac=jac_w, control=control),
error=function(e) {
paste("error at robust fit irls", k)
# tau <<- tau *10
#Return zero delta to avoid NaN updates
return(rep(0, length(par)))
})
if (max(abs(fit$par -par)) < 1e-8) {
par <- fit$par
break
}
par <- fit$par
}
r_final <- resid_4pl_joint(par,x,y,is_ref)
# s_final <- median(abs(r_final))/0.6745
rSD <- quantile(r, 0.6827)*length(r)/(length(r)-5)
# Robust scale (MAD); fallback if MAD ~0
# s <- median(abs(r))/0.6745
list(par=par, residuals=r_final, scale=rSD)
}
# ROUT outlier detection via BH-FDR [1] https://cran.r-project.org/web//packages/minpack.lm/refman/minpack.lm.html)[6]
rout_detect <- function(residuals, scale, Q=0.01) {
z <- abs(residuals/scale)
p <- 2*(1 - pcauchy(z))
# p <- 2*(1-pt(z, length(residuals)-5))
o <- order(p)
p_sorted <- p[o]
m <- length(p)
# thresh <- (seq_len(m)/m) # *Q
keep <- p_sorted <= Q # thresh
(out_idx <- o[keep])
sort(out_idx)
}
# Final OLS LM refit after removing outliers
ols_refit <- function(par_start, x,y,is_ref, keep_idx,
control = nls.lm.control(maxiter=400, ftol=1e-12, ptol=1e-12)) {
xk <- x[keep_idx]; yk <- y[keep_idx]; rk <- is_ref[keep_idx]
fn_w <- function(p) resid_4pl_joint(p,xk,yk,rk)
jac_w <- function(p) jac_4pl_joint(p,xk,yk,rk)
#browser()
fit <- tryCatch(nls.lm(par=par_start, fn=fn_w, jac=jac_w, control=control),
error=function(e) {
paste("error at ols_refits")
# tau <<- tau *10
#Return zero delta to avoid NaN updates
return(rep(0, length(par)))
})
list(par = fit$par, residuals = fn_w(fit$par), keep=keep_idx)
}
#. high-level ROUT 4PL analysis
rout_4pl_potency <- function(df, Q=0.01, par_start=NULL, max_outer = 30) {
stopifnot(all(c("sample","conc","y") %in% names(df))) # "rep",
#browser()
x <- log(df$conc)
y <- df$y
is_ref <- df$isRef == 1
# start values if not provided
if (is.null(par_start)) {
bottom0 = min(y, na.rm = T)
top0 = max(y, na.rm = T)
if (df$y[1]>df$y[8]) hill0 <- 1 else hill0 <- -1
le50_r0 <- median(x[is_ref], na.rm = T)
le50_t0 <- median(x[!is_ref], na.rm = T)
par_start <- c(bottom=bottom0, top=top0, hill=hill0, logEC50_ref = le50_r0 , logEC50_test = le50_t0)
}
# Step1 : robust fit
robust <- robust_fit_irls(par_start, x,y,is_ref, max_outer = max_outer)
# Step 2: outlier detection
out_idx <- rout_detect(robust$residuals, robust$scale, Q=Q)
keep_idx <- setdiff(seq_len(nrow(df)), out_idx)
# Step 3: OLS refit
ols <- ols_refit(robust$par, x,y,is_ref, keep_idx)
# Relative potency
rp <- exp(ols$par["logEC50_ref"] - ols$par["logEC50_test"])*100
list(Q=Q, outliers=out_idx,
kept=keep_idx,
par_robust = robust$par,
par_final = ols$par,
rp_percent = rp,
df=df)
}
# sheets <- openxlsx::getSheetNames("~/plateflow/outlierFUB.xlsx")
# all_dat <- lapply(sheets, openxlsx::read.xlsx, xlsxFile="~/plateflow/outlierFUB.xlsx")
# names(all_dat) <- sheets
#
# Plate <- 1
#
# PlanteN <- sheets[Plate]
# NoDils <- 8
# Nreps <- 3
# DAT <- all_dat[[Plate]]
# colnames(DAT) <- DAT[2,]
# REF <- DAT[3:10,1:4]
# SAM1 <- DAT[13:20,1:4]
# SAM2 <- DAT[23:30,1:4]
# SAM3 <- DAT[33:40,1:4]
#
# REF_ <- sapply(REF, as.numeric)
# colnames(REF_) <- colnames(REF)
# SAM1_ <- sapply(SAM1, as.numeric)
# colnames(SAM1_) <- colnames(SAM1)
# SAM2_ <- sapply(SAM2, as.numeric)
# colnames(SAM2_) <- colnames(SAM2)
# SAM3_ <- sapply(SAM3, as.numeric)
# colnames(SAM3_) <- colnames(SAM3)
#
# plot_df <- rbind(REF_, SAM1_, SAM2_,SAM3_)
#
# plot_df_ <- cbind(as.data.frame(plot_df), sample=c(rep("R", NoDils),rep("S1R", NoDils),rep("S2", NoDils),rep("S3", NoDils)))
# test_df <- plot_df_[1:16,]
# test_df2 <- plot_df_[c(1:8, 17:24),]
# test_df3 <- plot_df_[c(1:8, 25:32),]
#
# all_l <- melt(test_df, id.vars = c("sample","Dose"), variable.name="replname", value.name="readout")
# colnames(all_l) <- c("sample","conc","rep","y")
#
# for (Q in c(0.01,0.015,0.02)) {
# res <- rout_4pl_potency(all_l, Q)
# OUTs_ <- all_l[res$outliers,]
# print(outsPlot_FUN(all_l, OUTs_, TS=all_l$sample[9], PROC="ROUT",PROBE="Sheet 1",Q,par=res$par_final))
# }
+43 -3035
View File
File diff suppressed because it is too large Load Diff
+143
View File
@@ -0,0 +1,143 @@
explore_4pl <- tagList(
div(),#empty, just for spacing
navset_pill(
id = "tab_menu_2",
nav_panel("normal option TODO",
tags$div("graphs 4pl TODO"),
accordion(
open = FALSE,
accordion_panel(
title = "4PL-Tests",
p("This is the content inside the expandable box."),
)
),
accordion(
open = FALSE,
accordion_panel(
title = "unrestricted ANOVA for 4PL",
p("This is the content inside the expandable box."),
)
),
accordion(
open = FALSE,
accordion_panel(
title = "Error calculations:", #TODO NAME?
p("This is the content inside the expandable box."),
)
)
),
nav_panel("ln-transformed y",
tags$div("graphs 4pl ln transformed y TODO"),
accordion(
open = FALSE,
accordion_panel(
title = "4PL-Tests for ln-transformed y",
p("This is the content inside the expandable box."),
)
)
),
),
)
explore_linear <- tagList(
tags$p("graphs linear TODO"),
accordion(
open = FALSE,
accordion_panel(
title = "Tests for linear PLA:",
p("This is the content inside the expandable box."),
)
),
accordion(
open = FALSE,
accordion_panel(
title = "ANOVA for parallel line assay:",
p("This is the content inside the expandable box."),
)
),
accordion(
open = FALSE,
accordion_panel(
title = "Unrestricted linear model (SSSI):",
p("This is the content inside the expandable box."),
)
),
accordion(
open = FALSE,
accordion_panel(
title = "Restricted linear model (CSSI):",
p("This is the content inside the expandable box."),
)
)
)
explore_page <- layout_sidebar(
sidebar = sidebar(
class = "sidebar",
tags$div( class = "sidebar_collector",
tags$h5( class = "sidebar_collector_header",
"Exploration Settings"
),
sliderInput("sdfac", "Variability of lower to upper asymptote [%]:", min = 0, max = 100, value = 50),
sliderInput("potencydiff", "Potency of test [%]:", min = 0, max = 200, value = 100),
checkboxInput("PureErrMeta","Use pure error", FALSE),
checkboxInput("heterosked","Heteroskedastic noise", FALSE),
),
tags$div( class = "sidebar_collector",
tags$h5( class = "sidebar_collector_header", "Curve Settings"),
numericInput("lowAsymptREF", "lower asymptote REF", 10, step = 1, min = 0),
numericInput("lowAsymptTEST", "lower asymptote TEST", 10, step = 1, min = 0),
numericInput("uppAsymptREF", "upper asymptote REF", 110, step = 1, min = 0),
numericInput("uppAsymptTEST", "upper asymptote TEST", 110, step = 1, min = 0),
numericInput("slopeREF", "slope REF", 1, step = 0.1, min = -10),
numericInput("slopeTEST", "slope TEST", 1, step = 0.1, min = -10),
numericInput("EC50", "EC50 REF", -3.5),
numericInput("potDiff", "potency difference", 0)
),
tags$div( class = "sidebar_collector",
tags$h5( class = "sidebar_collector_header", "Dilutions"),
numericInput("CONC1", "highest concentration", 0.3, min = -3.5),
numericInput("CONC2", "2nd concentration", 0.15),
numericInput("CONC3", "3rd concentration", 0.075),
numericInput("CONC4", "4th concentration", 0.0375),
numericInput("CONC5", "5th concentration", 0.01875),
numericInput("CONC6", "6th concentration", 0.00938),
numericInput("CONC7", "7th concentration", 0.00469),
numericInput("CONC8", "8thd concentration", 0.00235),
numericInput("CONC9", "9thd concentration", value = NA),
numericInput("CONC10", "10th concentration", value = NA),
numericInput("CONC11", "11th concentration", value = NA),
numericInput("CONC12", "lowest concentration", NA)
),
tags$div( class = "sidebar_collector",
tags$h5( class = "sidebar_collector_header", "Geometric Dilution Scheme"),
numericInput("ConcStart", "starting concentration", value = NA, min = 0),
numericInput("dilutionFac", "dilution factor", value = NA, min = 0, max = 10),
numericInput("NoDil", "no. of dilutions", value = NA, min = 8),
numericInput("NoDilSer", "no. of dil. series", value = NA, min = 0), #TODO 1?
),
),
# Main content goes here (can be multiple elements)
navset_pill(
id = "tab_menu_1",
nav_panel("4PL", explore_4pl),
nav_panel("LINEAR", explore_linear)
),
accordion(
open = FALSE,
accordion_panel(
title = "Input-Data with added random noise:",
box( # TODO
title = "Simulated data per log-concentration", solidHeader = TRUE, width = 12, "incl. mean, sd and CV%",
DT::dataTableOutput("ConctabMeta")
),
)
)
)
+44
View File
@@ -0,0 +1,44 @@
home_page <- tagList(
tags$div( style = "align-self: center",
tags$div( class = "home-text-section",
tags$h3("Welcome to Plateflow"),
tags$p("Plateflow allows you to EXPLORE, INSPECT and OPTIMIZE your data in
the context of a 4 PL fit or a linear regression fit. "),
),
tags$div( class = "home-text-section",
tags$h4("Readable formats and expected structure"),
tags$p("Plateflow is optimized for uploadfiles in the folowing formats:
.xlsx, .csv and .numbers."),
tags$ul(
tags$li("1 column with the dilution concentrations (first or last column) is expected"),
tags$li("The column name of the dilution concentrations can be as follows: concentration, dose, log_concentration, log_dose (first letter can be capital).
It is assumed, that the concentrations are in anti-log or in natural log mode."),
tags$li("2 columns of reference and test sample readouts, respectively, in this order, are expected"),
tags$li("The column names for reference and test are free to set, but must differ for all columns"),
),
tags$p("You can download an example", tags$a("TestFile.xlsx ", target = "self", href = "TestFile.xlsx"), "File here."),
tags$h6("Example filestructure:"),
tags$img(src= "example_file.png", width = "800px", alt="example filestructure for upload", style = " max-width:800px"),
tags$br(),
),
tags$div( class = "home-text-section",
tags$br(),
tags$h4("Information on dilution settings"), #TODO
tags$p("Bend points are calculated according to following formula:",
withMathJax(" $$bp_{1/2} = \\pm\\frac{1.31696}{Hill's slope}$$"),
"Please refer to this", a(href = "ADONIS.pdf", "Whitepaper", download = NA, target = "_blank"), "for further details.", #TODO this link does not work for me
),
tags$br(),
),
tags$div( class = "home-text-section",
tags$h4("Plateflow Point of Contact"),
tags$p("At InnerAnalytics, we are happy to hear from you. You can contact us under: ",
tags$a("info@inner-analytics.eu", href = "mailto:info@inner-analytics.eu")),
tags$p("If you would like to report a bug, we would appreciate it if you sent us the following infos to help us solve your request as fast as possible: "),
verbatimTextOutput("sessioninfo"), #TODO actually output this
),
)
)
+61
View File
@@ -0,0 +1,61 @@
optimize_4pl <- tagList(
tags$p("graphs optimize 4pl TODO"),
accordion(
open = FALSE,
accordion_panel(
title = "Tests for linear PLA:",
p("This is the content inside the expandable box."),
)
),
)
dilution_slider <- tagList(
tags$h2("Finder for optimal dilutions"),
tags$p("graphs optimize dilution-slider TODO"),
accordion(
open = FALSE,
accordion_panel(
title = "Adjusted dilution factors:",
p("This is the content inside the expandable box."),
)
),
)
histograms <- tagList(
accordion(
open = FALSE,
accordion_panel(
title = "Parameter Histograms",
p("This is the content inside the expandable box."),
)
),
)
optimize_report <- tagList(
tags$p("download optimize report TODO"),
)
optimize_page <- layout_sidebar(
sidebar = sidebar(
class = "sidebar",
tags$div( class = "sidebar_collector",
tags$h5( class = "sidebar_collector_header",
"Optimization Settings"
),
sliderInput("TODO", "Adjust the dilutions (+- change in %):", min = -100, max = 100, value = 0),
checkboxInput("TODO2","Fix highest concentration instead of center", FALSE),
p("Wider dilution ranges increase the CIs of the relative potency, and decrease the CIs of the upper and lower asymptotes ratios, as well as the Hill's slope ratios."),
),
),
# Main content goes here (can be multiple elements)
optimize_4pl,
dilution_slider,
histograms,
optimize_report
)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 KiB

After

Width:  |  Height:  |  Size: 292 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

+107
View File
@@ -0,0 +1,107 @@
:root {
color-scheme: light;
--text-dark: #000000;
--text-light: #ffffff;
--grey-900: #1f2937;
--grey-800: #2b3441;
--grey-200: #b1b9c5;
--grey-100: #e7f1ff;
--grey-white: #ffffff;
--blue-light: #7faeff;
--blue: #5757fd;
--blue-dark: #4545ba;
}
body {
background: var(--grey-white);
color: var(--text-dark);
}
/*------------------------header-------------------------------------------*/
.navbar {
background-color: var(--grey-100);
border-bottom: 1px solid var(--blue-light) !important;
align-items: center;
width: 100;
}
/* The app title */
.navbar-brand {
color: var(--text-dark);
font-size: 1.4rem;
}
/* Nav container */
.navbar-nav {
display: flex;
justify-content: space-evenly;
align-self: center;
}
/*Header buttons*/
.navbar-nav .nav-link {
padding: 0.2rem 1.2rem !important;
margin: 0.4rem 0rem;
border: none;
border-radius: 5px;
}
/*----------------------------------------------------------------------------*/
.navbar-nav .nav-link.active,
.tab-button:hover,
.navbar-nav .nav-link.focus,
.tab-button:focus,
#tab_menu_1 .nav-link.active,
#tab_menu_2 .nav-link.active{
background-color: var(--blue-light);
color: var(--text-light)
}
/* Center the tab buttons */
#tab_menu_1,
#tab_menu_2{
justify-content: center;
}
/* Style individual tab buttons */
#tab_menu_1 .nav-link,
#tab_menu_2 .nav-link{
background-color: var(--grey-100);
border-radius: 4px;
margin: 0rem 1rem;
color: var(--text-dark)
}
/*----------------------------------------------------------------------------*/
.sidebar {
background-color: var(--grey-100) !important;
border-right: 1px solid var(--blue-light) !important;
}
.sidebar_collector{
border: 1px solid var(--blue-light);
border-radius: 4px;
padding: 10px;
}
.sidebar_collector_header{
border-bottom: 1px dashed var(--blue-light);
padding: 0 0 15px 0;
}
/*----------------------------------------------------------------------------*/
.home-text-section{
background-color: var(--grey-white);
padding: 10px;
border-radius: 4px;
max-width: 900px;
align-self: start;
}