Skip to content

Commit 8d0e6c4

Browse files
committed
Added inpshift profiler
1 parent 95061fd commit 8d0e6c4

File tree

5 files changed

+220
-4
lines changed

5 files changed

+220
-4
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export(frame_cumsum)
4141
export(get_se)
4242
export(kinfit_convolve)
4343
export(lin2tcm)
44+
export(lin2tcm_inpshiftProfile)
4445
export(ma1)
4546
export(ma1_tstar)
4647
export(ma2)

R/kinfitr_lin2tcm.R

Lines changed: 115 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#' @param inpshift Optional. The number of minutes by which to shift the timing of the input data frame forwards or backwards.
1414
#' If not specified, this will be set to 0. This can be fitted using 1TCM or 2TCM.
1515
#' @param vB Optional. The blood volume fraction. If not specified, this will
16-
#' be fitted. If specified as a numer (e.g. 0.05 for 5%), then that value will
16+
#' be fitted. If specified as a number (e.g. 0.05 for 5%), then that value will
1717
#' be used.
1818
#' @param dur Optional. Numeric vector of the time durations of the frames. If
1919
#' not included, the integrals will be calculated using trapezoidal integration.
@@ -54,8 +54,6 @@
5454
#' Raven Press, 51-79.
5555
#'
5656
#' @export
57-
58-
5957
lin2tcm <- function(t_tac, tac, input, weights = NULL, inpshift = 0,
6058
vB = NULL, dur = NULL, frameStartEnd = NULL) {
6159

@@ -310,3 +308,117 @@ plot_lin2tcmfit <- function(lin2tcmout, roiname = NULL) {
310308

311309
return(outplot)
312310
}
311+
312+
313+
#' Profile the inpshift using the linearised 2TCM
314+
#'
315+
#' Function to fit the linearised 2TCM function with several different delay
316+
#' values to find the optimal delay.
317+
#'
318+
#' @param t_tac Numeric vector of times for each frame in minutes. We use the
319+
#' time halfway through the frame as well as a zero. If a time zero frame is
320+
#' not included, it will be added.
321+
#' @param tac Numeric vector of radioactivity concentrations in the target
322+
#' tissue for each frame. We include zero at time zero: if not included, it is
323+
#' added.
324+
#' @param input Data frame containing the blood, plasma, and parent fraction
325+
#' concentrations over time. This can be generated using the
326+
#' \code{blood_interp} function.
327+
#' @param weights Optional. Numeric vector of the weights assigned to each frame
328+
#' in the fitting. We include zero at time zero: if not included, it is added.
329+
#' If not specified, uniform weights will be used.
330+
#' @param vB Optional. The blood volume fraction. If not specified, this will
331+
#' be fitted. If specified as a number (e.g. 0.05 for 5%), then that value
332+
#' will be used.
333+
#' @param dur Optional. Numeric vector of the time durations of the frames. If
334+
#' not included, the integrals will be calculated using trapezoidal
335+
#' integration.
336+
#' @param frameStartEnd Optional: This allows one to specify the beginning and
337+
#' final frame to use for modelling, e.g. c(1,20). This is to assess time
338+
#' stability.
339+
#' @param inpshift_vals Optional. The values of the inpshift to assess with the
340+
#' grid. By default, a grid between -1 and 1 with spacing of 0.01 will be
341+
#' used.
342+
#'
343+
#' @return A plot with the residual weighted sums of squares for each value of
344+
#' the input shift
345+
#'
346+
#' @examples
347+
#' data(pbr28)
348+
#'
349+
#' t_tac <- pbr28$tacs[[2]]$Times / 60
350+
#' tac <- pbr28$tacs[[2]]$FC
351+
#' weights <- pbr28$tacs[[2]]$Weights
352+
#' dur <- pbr28$tacs[[2]]$Duration/60
353+
#'
354+
#' input <- blood_interp(
355+
#' pbr28$procblood[[2]]$Time / 60, pbr28$procblood[[2]]$Cbl_dispcorr,
356+
#' pbr28$procblood[[2]]$Time / 60, pbr28$procblood[[2]]$Cpl_metabcorr,
357+
#' t_parentfrac = 1, parentfrac = 1
358+
#' )
359+
#'
360+
#' lin2tcm_inpshiftProfile(t_tac, tac, input, weights)
361+
#' lin2tcm_inpshiftProfile(t_tac, tac, input, weights, dur = dur)
362+
#' lin2tcm_inpshiftProfile(t_tac, tac, input, weights, vB=0.05,
363+
#' frameStartEnd = c(1,15))
364+
#'
365+
#' @author Granville J Matheson, \email{mathesong@@gmail.com}
366+
#'
367+
#' @references Oikonen, V (2003). Multilinear solution for 4-compartment model:
368+
#' I. Tissue compartments in series. Gjedde A, Wong DF 1990. Modeling
369+
#' neuroreceptor binding of radioligands in vivo. In: Quantitative imaging:
370+
#' neuroreceptors, neurotransmitters, and enzymes. (Eds. Frost JJ, Wagner HM
371+
#' Jr). Raven Press, 51-79.
372+
#'
373+
#' @export
374+
lin2tcm_inpshiftProfile <- function(t_tac, tac, input, weights = NULL, vB = NULL,
375+
dur = NULL, frameStartEnd = NULL,
376+
inpshift_vals = NULL) {
377+
378+
if ( is.null(inpshift_vals) ) {
379+
inpshift_vals <- seq(from = -1, to = 1, by = 0.01)
380+
}
381+
382+
383+
inpshift_RSS <- purrr::map_dbl(inpshift_vals, ~lin2tcm_RSS(
384+
t_tac, tac, input, weights, inpshift = .x,
385+
vB, dur, frameStartEnd))
386+
387+
388+
inpshift_profile <- tibble::tibble(
389+
inpshift = inpshift_vals,
390+
log_RSS = log(inpshift_RSS),
391+
lag = dplyr::lag(log_RSS, 1),
392+
lead = dplyr::lead(log_RSS, 1)
393+
)
394+
395+
inpshift_labels <- inpshift_profile %>%
396+
dplyr::mutate(Label = ifelse(log_RSS < lag & log_RSS < lead,
397+
yes = inpshift, no = NA)) %>%
398+
dplyr::filter(!is.na(Label)) %>%
399+
dplyr::arrange(log_RSS) %>%
400+
dplyr::mutate(Label = round(Label, 2)) %>%
401+
dplyr::slice(1:3)
402+
403+
inpshift_profile <- dplyr::left_join(inpshift_profile, inpshift_labels)
404+
405+
406+
ggplot(inpshift_profile, aes(x=inpshift, y=log_RSS)) +
407+
geom_line() +
408+
geom_text(aes(label=Label), nudge_y = -0.4) +
409+
geom_point(aes(x=Label), size=4, shape=1) +
410+
labs(y = "log(RSS)", x="Input Shift (min)")
411+
412+
}
413+
414+
lin2tcm_RSS <- function(t_tac, tac, input, weights = NULL, inpshift = 0,
415+
vB = NULL, dur = NULL, frameStartEnd = NULL) {
416+
417+
fit <- lin2tcm(t_tac, tac, input, weights, inpshift,
418+
vB, dur, frameStartEnd)
419+
420+
sum(weights(fit$fit) * residuals(fit$fit)^2)
421+
422+
423+
424+
}

man/lin2tcm.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/lin2tcm_inpshiftProfile.Rd

Lines changed: 88 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-artlinear.R

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,21 @@ test_that("lin2tcm with durations and frameStartEnd", {
325325
})
326326

327327

328+
# Linearised 2TCM for inpshift profiling
329+
330+
test_that("lin2tcm inpshift profiling", {
331+
332+
is1 <- lin2tcm_inpshiftProfile(t_tac, tac, input, weights)
333+
is2 <- lin2tcm_inpshiftProfile(t_tac, tac, input, weights, dur = dur)
334+
is3 <- lin2tcm_inpshiftProfile(t_tac, tac, input, weights, vB=0.05,
335+
frameStartEnd = c(1,15))
336+
337+
expect_true(any(class(is1) == "ggplot"))
338+
expect_true(any(class(is2) == "ggplot"))
339+
expect_true(any(class(is3) == "ggplot"))
340+
})
341+
342+
328343

329344

330345
#### Irreversible

0 commit comments

Comments
 (0)