Skip to content

Commit

Permalink
Major reworking of refit_curves.
Browse files Browse the repository at this point in the history
  • Loading branch information
Hefin Rhys committed Apr 3, 2024
1 parent 7b38b3f commit ee6ff94
Show file tree
Hide file tree
Showing 23 changed files with 314 additions and 139 deletions.
6 changes: 3 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: luminary
Title: Tools for Working with xMAP INTELLIFLEX Data
Version: 0.0.1
Version: 0.0.9
Authors@R:
person(
given = "Hefin",
Expand All @@ -14,7 +14,7 @@ Description: An R package for importing and working with Luminex data acquired
License: GPL (>= 3) + file LICENSE
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.3
RoxygenNote: 7.3.1
RdMacros: mathjaxr
Suggests:
knitr,
Expand All @@ -35,6 +35,6 @@ Imports:
mathjaxr
Config/testthat/edition: 3
Depends:
R (>= 2.10),
R (>= 3.0),
S7
LazyData: true
6 changes: 4 additions & 2 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Generated by roxygen2: do not edit by hand

S3method(print,intelliframe)
S3method(str,intelliframe)
export(get_analytes)
export(get_curve_data)
export(get_expected)
Expand All @@ -14,6 +12,10 @@ export(intelliframe)
export(plot_curves)
export(read_xmap)
export(refit_curves)
export(update_recovery)
export(update_recovery_avg)
export(update_summary_data)
export(update_well_data)
importFrom(S7,props)
importFrom(rlang,.data)
importFrom(stats,reformulate)
Expand Down
3 changes: 1 addition & 2 deletions R/extract_sheet_data.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
#'
#' @return A tibble.
#'
#' @examples
#' 1 + 1
#' @noRd
extract_sheet_data <- function(file, sheet, numeric_data = TRUE) {
readxl::read_xlsx(path = file, sheet = sheet, skip = 24, na = c("-", " ")) |>
dplyr::filter(.data$Location != "Location") |>
Expand Down
3 changes: 2 additions & 1 deletion R/plot_curves.R
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ plot_curves <- function(.intelliframe, analytes = NULL, type = "individual", int
ggplot2::aes(.data[["Result"]], .data[["Predicted"]]),
inherit.aes = FALSE
) +
ggplot2::scale_colour_brewer(type = "qual", palette = "Set1") +
# ggplot2::scale_colour_brewer(type = "qual", palette = "Set1") +
ggplot2::scale_colour_manual(values = c("Control" = "#E41A1C", "Standard" = "#377EB8", "Unknown" = "#4DAF4A")) +
suppressWarnings(
ggplot2::geom_point(
data = experimental_data,
Expand Down
8 changes: 4 additions & 4 deletions R/print.R
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#' print method for intelliframe class
#'
#'
#' @param x An intelliframe object.
#' @param max.level How many levels to print.
#' @param ... Unused.
#'
#' @exportS3Method
print.intelliframe <- function(x, max.level = 1, ...) {
counts <- get_well_data(x) |>
dplyr::summarise(.by = "Type", dplyr::n())
#' @noRd
method(print, intelliframe) <- function(x, max.level = 1, ...) {
counts <- dplyr::summarise(get_well_data(x), .by = "Type", dplyr::n())

counts <- lapply(c("Standard", "Control", "Unknown"), function(.type) {
if(.type %in% counts$Type) {
Expand Down
8 changes: 7 additions & 1 deletion R/read_xmap.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@ read_xmap <- function(file) {
}) |> stats::setNames(well_data_sheets)

messages <- extract_sheet_data(file, sheet = "Messages", numeric_data = FALSE)
excluded_wells <- readxl::read_xlsx(file, sheet = "Excluded Wells", skip = 20)

excluded_wells <- readxl::read_xlsx(
file,
sheet = "Excluded Wells",
skip = 20,
col_types = "text"
)

expected <- sheet_data$Expected

Expand Down
88 changes: 49 additions & 39 deletions R/refit_curves.R
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
#' @param add_to_zeroes A numeric value (\code{0.1} by default) added to zeros during
#' the curve fitting procedure as it requires the concentration to be
#' log10-transformed.
#' @param use_excluded Logical flag indicating whether wells with a value of
#' \code{TRUE} in the \code{Excluded} column are used to refit the curves and
#' calculate summary statistics. Defaults to \code{FALSE}.
#' @param silent Logical flag indicating whether warnings and/or messages during
#' curve fitting should be silenced. Defaults to \code{FALSE}.
#'
Expand All @@ -74,26 +77,42 @@
#'
#' @examples
#' 1+1
refit_curves <- function(.intelliframe, npars = "all", weight_method = "res", LPweight = 0.25, add_to_zeroes = 0.02, silent = FALSE) {
refit_curves <- function(
.intelliframe,
npars = "all",
weight_method = "res",
LPweight = 0.25,
add_to_zeroes = 0.02,
use_excluded = FALSE,
silent = FALSE
) {

well_data <- get_well_data(.intelliframe)

standards <- dplyr::filter(well_data, .data[["Type"]] == "Standard")

ident_cols <- c(
"Plate", "Group", "Location", "Well ID", "Sample ID", "Standard", "Type",
"Analyte", "Expected"
)

excluded_wells <- well_data$Excluded

expected <- get_expected(.intelliframe) |>
dplyr::select("Plate", "Group", "Well ID", "Sample ID", "Standard", "Type", "Analyte", "Expected")
dplyr::select(dplyr::all_of(ident_cols))

standard_list <- dplyr::left_join(
standards,
expected,
by = c("Plate", "Group", "Well ID", "Sample ID", "Standard", "Type", "Analyte", "Expected")
)
standard_list <- dplyr::left_join(standards, expected, by = ident_cols)

standard_list <- split(standard_list, standard_list$Analyte)

fits <- lapply(standard_list, function(analyte) {

if(!use_excluded) {
analyte <- analyte[-excluded_wells, ]
}

non_zero <- ifelse(
analyte$Expected < 1,
analyte$Expected == 0,
analyte$Expected + add_to_zeroes,
analyte$Expected
)
Expand All @@ -108,41 +127,32 @@ refit_curves <- function(.intelliframe, npars = "all", weight_method = "res", LP
)
})

intelliframe_out <- .intelliframe

names(fits) <- names(standard_list)

suppressWarnings({
refitted <- lapply(names(fits), function(analyte) {
maximum <- max(standard_list[[analyte]]$MFI)
dplyr::filter(well_data, .data[["Analyte"]] == analyte) |>
dplyr::mutate(Result = nplr::getEstimates(fits[[analyte]], targets = .data[["MFI"]] / maximum)$x)
}) |> dplyr::bind_rows()
})
prop(intelliframe_out, "well_data") <-
update_well_data(well_data, fits, standard_list, silent)

intelliframe_out <- .intelliframe
intelliframe_out@well_data <- refitted

intelliframe_out@recovery <- dplyr::filter(refitted, .data[["Type"]] %in% c("Standard", "Control")) |>
dplyr::mutate(Recovery = dplyr::case_when(
.data[["Expected"]] == 0 ~ NA_real_,
.default = .data[["Result"]] / .data[["Expected"]]
)) |>
dplyr::select(-c("MFI", "Result", "Messages", "Exclude Reason", "Excluded", "Expected"))

intelliframe_out@recovery_avg <- intelliframe_out@recovery |>
dplyr::select(-.data[["Location"]]) |>
dplyr::left_join(
dplyr::select(intelliframe_out@recovery_avg, -.data[["Recovery"]]),
by = c("Plate", "Group", "Well ID", "Sample ID", "Standard", "Type", "Analyte")
) |>
dplyr::select(
"Plate", "Group", "Location", "Well ID", "Sample ID", "Standard", "Type",
"Analyte", "Recovery"
) |>
dplyr::summarise(
.by = c("Plate", "Group", "Location", "Well ID", "Sample ID", "Standard",
"Type", "Analyte"),
Recovery = mean(.data[["Recovery"]], na.rm = TRUE)
prop(intelliframe_out, "recovery") <-
update_recovery(well_data)

prop(intelliframe_out, "recovery_avg") <-
update_recovery_avg(
get_recovery(intelliframe_out),
get_recovery_avg(intelliframe_out),
use_excluded,
excluded_wells
)

prop(intelliframe_out, "summary_data") <-
update_summary_data(
well_data,
get_summary_data(intelliframe_out),
use_excluded,
excluded_wells
)

intelliframe_out
}

23 changes: 0 additions & 23 deletions R/str.R

This file was deleted.

68 changes: 68 additions & 0 deletions R/update_curve_data.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
lapply(names(fits), function(x) {

lloq <- dplyr::filter(
u5plex@summary_data,
Analyte == x,
Type == "Standard",
Result_CV <= 0.2,
Result_Avg / Expected > 0.8,
Result_Avg / Expected < 1.2
) |>
dplyr::pull(Expected) |>
min()

blank <- dplyr::filter(
u5plex@well_data,
Analyte == x,
Type == "Standard",
Expected == 0
) |>
dplyr::pull(MFI)

blank_targets <-
(mean(blank) + 2.5*sd(blank)) /
max(dplyr::filter(u5plex@well_data, Analyte == x)$MFI)

suppressWarnings({
suppressMessages({
mdd <- nplr::getEstimates(
fits[[x]],
targets = blank_targets
)$x
})
})

df_low <- data.frame(
x = 10^(fits[[x]]@x),
y = fits[[x]]@y
)[10^(fits[[x]]@x) %in% unique(10^(fits[[x]]@x))[1:3],]

fit_low <- nplr::nplr(
x = df_low$x,
y = df_low$y#,
# npars = npars,
# method = weight_method,
# LPweight = LPweight,
# silent = silent
)

suppressWarnings({
suppressMessages({
lod <- nplr::getEstimates(
fit_low,
targets = blank_targets
)$x
})
})

tibble::tibble(
Analyte = x,
Fit = paste0("nplr ", fits[[x]]@npars, "PL"),
LLoQ = lloq,
MDD = mdd,
LoD = lod,
`R Squared` = fits[[x]]@goodness$gof,
Slope = fits[[x]]@pars$s
)
}) |> dplyr::bind_rows()

23 changes: 23 additions & 0 deletions R/update_recovery.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#' update_recovery
#'
#' Update the recovery property from an intelliframe object using up-to-date
#' well_data. Not meant to be called by the user.
#'
#' @param .well_data A tibble containing the well_data property.
#'
#' @return An intelliframe
#' @export
#'
#' @noRd
update_recovery <- function(.well_data){
dplyr::filter(.well_data, .data[["Type"]] %in% c("Standard", "Control")) |>

dplyr::mutate(
Recovery = dplyr::case_when(
.data[["Expected"]] == 0 ~ NA_real_,
.default = .data[["Result"]] / .data[["Expected"]]
)
) |>

dplyr::select(-c("MFI", "Result", "Messages", "Exclude Reason", "Excluded", "Expected"))
}
39 changes: 39 additions & 0 deletions R/update_recovery_avg.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#' update_recovery_avg
#'
#' Update the recovery_avg property from an intelliframe object using up-to-date
#' recovery. Not meant to be called by the user.
#'
#' @param .recovery A tibble containing the recovery property.
#' @param .recovery A tibble containing the original recovery_avg property.
#' @param .use_excluded Logical flag indicating whether wells with a value of
#' \code{TRUE} in the \code{Excluded} column are used to calculate summary
#' statistics.
#' @param .excluded_wells Logical vector indicating whether each well is
#' excluded.
#'
#' @return An intelliframe
#' @export
#'
#' @noRd
update_recovery_avg <- function(.recovery, .recovery_avg, .use_excluded, .excluded_wells) {
correct_location <- dplyr::select(.recovery, -Location) |>
dplyr::left_join(
dplyr::select(.recovery_avg, -Recovery),
by = c("Plate", "Group", "Well ID", "Sample ID", "Standard", "Type", "Analyte")
) |>
dplyr::select(
"Plate", "Group", "Location", "Well ID", "Sample ID", "Standard", "Type",
"Analyte", "Recovery"
)

if(!.use_excluded) {
correct_location <- correct_location[-.excluded_wells, ]
}

dplyr::summarise(
correct_location,
.by = c("Plate", "Group", "Location", "Well ID", "Sample ID", "Standard",
"Type", "Analyte"),
Recovery = mean(Recovery, na.rm = TRUE)
)
}
Loading

0 comments on commit ee6ff94

Please sign in to comment.