Helmut
★★★
avatar
Homepage
Vienna, Austria,
2020-11-05 14:30
(1262 d 02:44 ago)

Posting: # 22059
Views: 3,137
 

 partial AUCs [NCA / SHAM]

Dear all,

since partial AUC are required for some MR-products, I’m facing a increasing number of miscalculations in reports…
For users of Phoenix/WinNonlin: Please RTFM (User’s Guide → Noncompartmental Analysis → Partial areas).
If we split the AUC at certain (≥1) cut-off time(s), the sum of partial AUCs should equal AUC0–t. If not, something went wrong in the calculation.

Let’s explore a recent example. A multiphasic release product, cut-off time 4 h, linear-up / logarithmic-down trapezoidal method (data at the end):

[image]

Correct:

AUC0–t = 980.78 ng/mL, pAUC0–4 = 54.05 ng/mL, pAUC4–72 = 926.73 ng/mL; Σ pAUC = AUC0–t✔️

Reported:

AUC0–t = 980.78 ng/mL, pAUC0–4 = 54.05 ng/mL, pAUC4–72 = 966.33 ng/mL; Σ pAUC > AUC0–t


What’s going on here? The CRO split the data set at four hours and performed separate NCAs on the splits. Works fine for the first one but fails for the second because naturally all time points <4 h are missing and the software automatically added t=0 and C=0. Consequently the area of the triangle given by \(\small{t_0|C_0,\,t_4|C_0,\,t_4|C_4}\) was added: \(\small{AUC_{\textit{i}-\textit{i}+1}=\frac{1}{2}(t_{\textit{i}+1}-t_\textit{i})(C_{\textit{i}+1}+C_\textit{i})=\frac{1}{2}(4-0)(19.80+0)=2\times19.80=39.60}\).

[image]

I asked the CRO for the project-file to check. Of course, the “Core output” contained the information:
   Time       Conc.      AUC
      h       ng/mL    h*ng/mL
------------------------------
 0.0000 @    0.0000    0.0000
 4.000      19.80     39.60
 4.500      22.80     50.25
...
@) Note - the concentration at dose time was added for extrapolation purposes.


You can’t avoid that. If you think about adding a concentration 0 at 4 hours, you would be punished by

[image]

and
*** ERROR 14062: Duplicate time values on data file. Please ensure you have defined a unique profile

There’s another flaw when splitting the data set in case of missings and/or deviations from scheduled sampling time points. Even when the split is performed on the scheduled ones, one might end up with an apples-and-oranges comparison. Contrary to that, partial AUCs in PHX/WNL are calculated exactly for the specified start- / end-times and inter-/extrapolated according to the selected AUC method.

AFAIK, partial AUCs were introduced in PHX/WNL 6.0 (2009!). In earlier versions one has to work with split data sets. In all but the first one: Generate a new column where e.g., new.time = time – cut-off and map this one to time in NCA.


Data and correct calculation:
 t       C   Δ C  Δ AUC  AUC0–t   pAUC4–t
 0      0.00       0.00   0.00
 0.5    0.00  ↔    0.00   0.00
 1      7.23  ↑    1.81   1.81
 1.25  10.10  ↑    2.17   3.97
 1.5   12.80  ↑    2.86   6.84
 1.75  17.60  ↑    3.80   10.64
 2     21.50  ↑    4.89   15.52
 2.25  18.60  ↓    5.00   20.53
 2.5   20.40  ↑    4.88   25.40
 3     18.60  ↓    9.74   35.15
 3.5   18.60  ↔    9.30   44.45
 4     19.80  ↑    9.60   54.05    0.00
 4.5   22.80  ↑   10.65   64.70   10.65
 5     27.30  ↑   12.53   77.22   23.18
 5.5   34.00  ↑   15.33   92.55   38.50
 6     40.00  ↑   18.50  111.05   57.00
 6.5   38.00  ↓   19.50  130.54   76.50
 7     37.30  ↓   18.82  149.37   95.32
 7.5   36.30  ↓   18.40  167.76  113.72
 8     34.90  ↓   17.80  185.56  131.52
 9     35.30  ↑   35.10  220.66  166.92
12     28.30  ↓   95.01  315.68  261.63
24     18.00  ↓  273.16  588.83  534.79
36     11.10  ↓  171.28  760.11  706.06
48      7.01  ↓  106.79  866.90  812.85
72      3.03  ↓  113.88  980.78  926.73   54.05 + 926.73 = 980.78 ✔️


Wrong after splitting (where the first split with AUC0–4 = 54.05 is correct):
 t       C   Δ C  Δ AUC  AUC0–t
 0 @    0.00       0.00    0.00  ← automatically added
 4     19.80  ↑   39.60   39.60
 4.5   22.80  ↑   10.65   50.25
 5     27.30  ↑   12.53   62.78
 5.5   34.00  ↑   15.33   78.10
 6     40.00  ↑   18.50   96.60
 6.5   38.00  ↓   19.50  116.10
 7     37.30  ↓   18.82  134.92
 7.5   36.30  ↓   18.40  153.32
 8     34.90  ↓   17.80  171.12
 9     35.30  ↑   35.10  206.22
12     28.30  ↓   95.01  301.23
24     18.00  ↓  273.16  574.39
36     11.10  ↓  171.28  745.66
48      7.01  ↓  106.79  852.45
72      3.03  ↓  113.88  966.33   54.05 + 966.33 = 1020.38 > 980.73

Dif-tor heh smusma 🖖🏼 Довге життя Україна! [image]
Helmut Schütz
[image]

The quality of responses received is directly proportional to the quality of the question asked. 🚮
Science Quotes
dshah
★★  

India/United Kingdom,
2020-11-05 14:39
(1262 d 02:35 ago)

@ Helmut
Posting: # 22060
Views: 2,476
 

 partial AUCs

Greetings All!
I believe we are using real time for PK characterization, so if some subject's time point does not match- it may show some difference for partial AUC's. This is my thought as currently I do not have Phoenix.
Regards,
Dshah
Helmut
★★★
avatar
Homepage
Vienna, Austria,
2020-11-05 15:15
(1262 d 01:58 ago)

@ dshah
Posting: # 22061
Views: 2,486
 

 partial AUCs

Hi Dshah,

❝ I believe we are using real time for PK characterization, …


I hope that everybody does. ;-)

❝ … so if some subject's time point does not match- it may show some difference for partial AUC's.


I think so.

❝ This is my thought as currently I do not have Phoenix.


Which software are you using and – more specifically – how are later partial AUCs calculated?

Dif-tor heh smusma 🖖🏼 Довге життя Україна! [image]
Helmut Schütz
[image]

The quality of responses received is directly proportional to the quality of the question asked. 🚮
Science Quotes
PharmCat
★    

Russia,
2020-11-13 02:16
(1254 d 14:57 ago)

@ Helmut
Posting: # 22066
Views: 2,312
 

 partial AUCs

Hi Helmut,

I don't think that Certara (Phoenix) is not motivated to do better software. Look at LMM library - this is ancient as mammoth excrement and should be rewritten years ago (it is a big luck that we have much memory and CPU time, but this still doesn't work for a large number of observations).

[image]

So... In Julia this calculated fine:
Code:
df = CSV.file("pkpart.csv") |> DataFrame
pkds       = ClinicalTrialUtilities.pkimport(df; conc = :conc, time = :time)
pk         = ClinicalTrialUtilities.nca!(pkds, calcm = :luld)
println("AUCall: ", pk[1, :AUCall])
pall = pk[1, :AUCall]
ClinicalTrialUtilities.setdosetime!(pkds, ClinicalTrialUtilities.DoseTime(dose = 120, time = 0, tau = 4))
pk         = ClinicalTrialUtilities.nca!(pkds, calcm = :luld)
println("AUCtau 0 - 4: ", pk[1, :AUCtau])
p1 = pk[1, :AUCtau]
ClinicalTrialUtilities.setdosetime!(pkds, ClinicalTrialUtilities.DoseTime(dose = 120, time = 4, tau = 72-4))
pk         = ClinicalTrialUtilities.nca!(pkds, calcm = :luld)
println("AUCtau 4 - 72: ", pk[1, :AUCtau])
p2 = pk[1, :AUCtau]
println("Check pall ≈ p1 + p2: ", pall ≈ p1 + p2)


Out:
julia>
AUCall: 980.7754537633873
AUCtau 0 - 4: 54.04557219475543
AUCtau 4 - 72: 926.7298815686318
Check pall ≈ p1 + p2: true
UA Flag
Activity
 Admin contact
22,988 posts in 4,825 threads, 1,655 registered users;
64 visitors (0 registered, 64 guests [including 7 identified bots]).
Forum time: 18:14 CEST (Europe/Vienna)

The whole purpose of education is
to turn mirrors into windows.    Sydney J. Harris

The Bioequivalence and Bioavailability Forum is hosted by
BEBAC Ing. Helmut Schütz
HTML5