Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: Identifying points used in half-life calculation #387

Open
billdenney opened this issue Feb 8, 2025 · 3 comments
Open

Comments

@billdenney
Copy link
Owner

billdenney commented Feb 8, 2025

Discussed in #386

Originally posted by @john-harrold February 8, 2025
Howdy in the example below there are two subjects. For one the data to calculate half-life is specified and for the second PKNCA is figuring it out. Is there a way to extract from the result object which points were actually used for NCA calculations?

library(PKNCA)

# Perform calculations for subject 1, only
data_conc <- as.data.frame(datasets::Theoph)[datasets::Theoph$Subject %in% c(1, 2), ]

# Keep all points
conc_obj <-
  PKNCAconc(
    data_conc,
    conc~Time|Subject
  )

# Only calculate half-life and parameters required for half-life
current_intervals <- data.frame(start=0, end=Inf, half.life=TRUE)
data_obj <- PKNCAdata(conc_obj, intervals=current_intervals)
result_obj <- pk.nca(data_obj)


data_conc$include_hl <- c(data_conc$Time > 3 & data_conc$Subject == 1)
data_conc$include_hl[ !(data_conc$include_hl)  ] = NA
#data_conc$include_hl = FALSE

# Drop one point
conc_obj_include <-
  PKNCAconc(
    data_conc,
    conc~Time|Subject,
    include_half.life="include_hl")

data_obj_include <- PKNCAdata(conc_obj_include, intervals=current_intervals)

# Perform the calculations
result_obj_include <- pk.nca(data_obj_include)
```</div>
@billdenney
Copy link
Owner Author

The way to create this will be:

  1. Create a return vector with the length of to NA.
  2. Check if include_half.life is set in the PKNCAconc object. If yes, then for rows where that column is not NA, set that value in the column.
  3. Check if exclude_half.life is set in the PKNCAconc object. If yes, then for rows were that column is TRUE and the value is not already set (due to include_half.life), set it to FALSE.
  4. Look at the PKNCAresult, and for intervals where half-life is calculated and the return value is NA, set it to TRUE from lambda.z.time.first to tlast.

As described above there are at least two bug to be avoided:

  • If a point may be used for half-life calculation in more than one interval with automatic point selection and there is any difference in the points selected, it may be wrong. Imagine that you calculate a half-life with data from time 0 to 24 hours and then also from 0 to Inf. Different points may be used for 0 to 24 compared to 0 to Inf. This would not differentiate those.
  • If include_half.life points are set with points selected, but a half-life is never calculated for the interval, it will show the points as being used for half-life calculation.

There is also one output subtlety to be aware of. With that algorithm, values will be TRUE or FALSE when a point is or is not used for half-life calculation. Values which are never considered for half-life calculation will be NA. This output note seems like a feature as it will let you be aware when you're not trying to calculate half-life. It will also be set to TRUE even when the half-life has been excluded, e.g. due to span ratio issues. It will be set to NA if the half-life could not be calculated, e.g. due to an increasing slope.

I can imagine two interfaces for this:

  1. The as_PKNCAconc.PKNCAresults() method gets an add_half.life_points = "new_colname" argument. If NULL (the default), the PKNCAconc object from the PKNCAresults is returned as-is. If a single character string, it is used as the column name for a new column in the PKNCAconc object's $data. That way, you can extract the data from that object for plotting with the requested column added.
  2. A new get_half.life_points() function that takes in a PKNCAresults object and does the above calculation returning a logical vector.

How does that sound?

@john-harrold
Copy link

I think I understand most of that. I didn't realize that it could be interval-specific, but I now see how it could be. Since this is done for each interval would it make sense to return a column for each interval?

@john-harrold
Copy link

Actually thinking about it, it probably just makes sense to ask folks who want to do multiple intervals where they want to manually specify the points to just separate it into different analyses. I think option 2 would be fine.

I could just take that result and cbind it to the original dataset right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants