How to calculate half how to see volume of distribution and clearance

Checking Date & Time
Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Loading Image
Here is a complete explanation of all three pharmacokinetic parameters and how they relate to each other.

Pharmacokinetics: Half-Life, Volume of Distribution & Clearance


1. Volume of Distribution (V_d)

Definition: The apparent volume that would be required to contain the total amount of drug in the body at the same concentration as measured in plasma.
Formula:
$$V_d = \frac{\text{Amount of drug in body}}{\text{Plasma concentration (C)}}$$
Or rearranged:
$$V_d = \frac{\text{Dose}}{C_0}$$
where C₀ = plasma concentration at time zero (after IV bolus).
Units: Liters (L) or L/kg body weight
Interpretation:
V_dWhat it means
~0.04 L/kg (≈3 L)Drug stays in plasma (e.g., heparin, large proteins)
~0.2 L/kg (≈14 L)Distributes into extracellular fluid (e.g., aminoglycosides)
~0.6 L/kg (≈42 L)Distributes into total body water (e.g., ethanol)
>1 L/kg (can be 100s of L)Extensive tissue binding; very little in plasma (e.g., digoxin ~7 L/kg, chloroquine)
A large V_d does NOT mean a large physical volume — it means the drug is sequestered in tissues, so plasma concentrations are low relative to the total dose.

2. Clearance (CL)

Definition: The volume of plasma completely cleared of drug per unit time. It measures the efficiency of elimination.
Formula:
$$CL = \frac{\text{Rate of elimination}}{\text{Plasma concentration (C)}}$$
For first-order kinetics, it can be calculated from:
$$CL = \frac{\text{Dose}}{\text{AUC}}$$
where AUC = Area Under the Concentration–Time curve.
Total clearance = sum of organ clearances:
$$CL_{total} = CL_{renal} + CL_{hepatic} + CL_{other}$$
Units: mL/min or L/hr
Key concepts:
  • Clearance is independent of V_d — the two are separate primary parameters
  • For high-extraction drugs (e.g., lidocaine, propranolol): clearance depends mainly on blood flow to the eliminating organ
  • For low-extraction drugs (e.g., warfarin, phenytoin): clearance depends on enzyme activity and protein binding
  • Capacity-limited (zero-order) drugs (e.g., phenytoin, ethanol, aspirin at high doses) have non-constant clearance — the Dose/AUC formula does NOT apply

3. Half-Life (t½)

Definition: The time required for the plasma concentration (or the amount of drug in the body) to decrease by 50% during the elimination phase.
Formula:
$$\boxed{t_{1/2} = \frac{0.693 \times V_d}{CL}}$$
The 0.693 = ln(2), derived from first-order exponential decay.
How to calculate it step by step:
  1. Determine V_d (Dose ÷ C₀, or from published data)
  2. Determine CL (Dose ÷ AUC, or organ clearance data)
  3. Plug into: t½ = (0.693 × V_d) / CL
Alternatively, from the elimination rate constant (K_e):
$$K_e = \frac{CL}{V_d}$$
$$t_{1/2} = \frac{0.693}{K_e}$$
K_e can be measured graphically as the slope of the log(concentration) vs. time plot during the elimination phase.

The Critical Relationship Between All Three

↑ V_d (same CL)→ t½ increases
↑ CL (same V_d)→ t½ decreases
Both ↓ proportionally→ t½ unchanged
This is why half-life alone can be misleading. Example: In chronic renal failure, digoxin has both decreased CL and decreased V_d — so the t½ doesn't change as much as you'd expect from the CL drop alone. — Goldman-Cecil Medicine

Practical Significance of t½

Drug accumulation and elimination curve
Half-lives elapsed% of steady state reached (accumulation)% remaining after stopping
150%50%
275%25%
387.5%12.5%
493.75%~6%
~5>97%<3% (effectively eliminated)
Rule of thumb: It takes ~4–5 half-lives to reach steady state (or to fully eliminate a drug after stopping).

Summary Table

ParameterFormulaWhat it tells you
V_dDose / C₀How widely the drug distributes in body tissues
CLDose / AUCHow efficiently the body eliminates the drug
0.693 × V_d / CLHow long the drug stays active in the body
K_eCL / V_dFractional rate of elimination per unit time

Sources: Katzung's Basic and Clinical Pharmacology, 16th Ed.; Goldman-Cecil Medicine, International Edition

With examples

Finding Sources
Finding Sources
Reading File
Reading File
I now have everything needed for a rich, example-driven explanation. Here it is:

Pharmacokinetics With Worked Examples


1. Volume of Distribution (V_d) — With Examples

$$V_d = \frac{\text{Amount of drug in body (Dose)}}{\text{Plasma concentration (C)}}$$

Worked Example 1 — Basic Calculation

10 mg of drug is given IV. Plasma concentration at time zero = 2 mg/L
$$V_d = \frac{10 \text{ mg}}{2 \text{ mg/L}} = \mathbf{5 \text{ L}}$$
Now if the concentration was only 1 mg/L instead (more tissue binding):
$$V_d = \frac{10 \text{ mg}}{1 \text{ mg/L}} = \mathbf{10 \text{ L}} \quad \leftarrow \text{drug is "hiding" in tissues}$$
Barash's Clinical Anesthesia, 9e

Real Drug Examples

DrugV_d (L/kg)V_d in 70 kg adultMeaning
Heparin~0.06~4 LStays in plasma
Amoxicillin0.47~33 LMostly ECF
Phenytoin0.4–0.8~42 LTotal body water
Carbamazepine1.2~84 LSome tissue binding
Digoxin4–7~350–490 LExtensive tissue (muscle/heart) binding
Chloroquine>200>14,000 LMassive tissue sequestration
Digoxin's V_d of 4–7 L/kg tells us that only a tiny fraction of the total drug is in the plasma at any given time — most is bound to Na⁺/K⁺-ATPase in muscle and cardiac tissue. This is why plasma levels can seem low even with therapeutic dosing, and why dialysis does NOT effectively remove digoxin (you'd have to remove an enormous "apparent volume"). — Rosen's Emergency Medicine

Clinical Use: Loading Dose Calculation

$$\text{Loading Dose} = V_d \times \text{Target Concentration}$$
Phenytoin example (70 kg patient, target level = 10 mg/L):
  • V_d = 0.6 L/kg × 70 kg = 42 L
  • Loading dose = 42 L × 10 mg/L = 420 mg
To bring a subtherapeutic level (5 mg/L) up to 15 mg/L:
  • Dose needed = 0.6 L/kg × 70 kg × (15 − 5 mg/L) = 420 mg
Goldman-Cecil Medicine

2. Clearance (CL) — With Examples

$$CL = \frac{\text{Dose}}{\text{AUC}} \quad \text{(first-order drugs only)}$$

Worked Example 2 — From AUC

500 mg IV dose given. AUC = 100 mg·hr/L
$$CL = \frac{500 \text{ mg}}{100 \text{ mg·hr/L}} = \mathbf{5 \text{ L/hr}} \approx 83 \text{ mL/min}$$

Real Drug Examples

DrugTotal CL (mL/min)Primary routeNotes
Amoxicillin417Renal (86%)Dose-reduce in renal failure
Aspirin (low dose)575–725Hepatic (>95%)High extraction
Phenytoin167HepaticCapacity-limited at high doses
Lithium20–40Renal (95–99%)Mirrors GFR exactly
Carbamazepine50–125HepaticInduces its own metabolism
Digoxin~130Renal (~70%)Reduce dose in renal failure
Goldman-Cecil Medicine, Table 25 Pharmacokinetic Parameters

Zero-Order Exception (Phenytoin, Ethanol, High-dose Aspirin)

At high doses, these drugs saturate their enzymes. Clearance is no longer constant — it falls as concentration rises. This is why a small phenytoin dose increase can cause a disproportionately large rise in blood levels (and toxicity).

3. Half-Life (t½) — With Examples

$$t_{1/2} = \frac{0.693 \times V_d}{CL}$$

Worked Example 3 — Calculate t½ from V_d and CL

Drug: V_d = 42 L, CL = 5 L/hr
$$t_{1/2} = \frac{0.693 \times 42}{5} = \frac{29.1}{5} = \mathbf{5.8 \text{ hours}}$$

Real Drug t½ Comparison

DrugV_d (L) in 70 kgCL (L/hr)Clinical implication
Aspirin~11 L~40 L/hr~15–20 minVery short; must give frequently or as infusion
Amoxicillin~33 L~25 L/hr~1.2 hrDose every 8 hr
Carbamazepine~84 L~5 L/hr~12–17 hrDose twice daily
Lithium~56 L~1.7 L/hr~20–24 hrOnce daily; closely monitor levels
Digoxin~350–490 L~7.5 L/hr~36–48 hrReaches steady state in ~7–10 days
Amiodarone~4,200 Lvariable~40–55 daysEnormous V_d → extremely long t½

Example 4 — Disease Changes t½ (Digoxin in Renal Failure)

In chronic renal failure:
  • CL of digoxin ↓ (less renal excretion)
  • V_d also ↓ (loss of muscle mass = less binding sites)
Both drop proportionally, so:
$$t_{1/2} = \frac{0.693 \times \downarrow V_d}{\downarrow CL}$$
The t½ does not rise as much as expected — because the smaller V_d partially compensates for reduced clearance. This is why digoxin toxicity in renal failure is partly due to lower V_d (more drug stays in plasma), not just reduced clearance. — Katzung, 16th Ed.

Example 5 — Age Changes t½ (Diazepam)

In elderly patients:
  • CL of diazepam → unchanged
  • V_d → increases (more body fat, drug distributes more widely)
$$t_{1/2} = \frac{0.693 \times \uparrow V_d}{\text{CL (same)}} \quad \Rightarrow \quad t_{1/2} \uparrow$$
Diazepam's half-life doubles or triples in the elderly — purely because fat mass increases and V_d expands. This causes sedation to persist much longer. Dose reduction is required. — Katzung, 16th Ed.

4. Half-Life in Practice — Drug Elimination Timeline

Accumulation and elimination curves
Example: A drug with t½ = 6 hours
Time% of drug remaining
6 hr (1 t½)50%
12 hr (2 t½)25%
18 hr (3 t½)12.5%
24 hr (4 t½)6.25%
30 hr (5 t½)~3% → practically eliminated
And during dosing — steady state is reached after ~4–5 half-lives regardless of the dose size or dosing frequency (only the rate of infusion/dose determines the level at steady state, not how fast it's reached).

One-Line Summary

ParameterFormulaMnemonic
V_dDose ÷ C₀"How widely it spreads"
CLDose ÷ AUC"How fast it's cleared"
0.693 × V_d ÷ CL"How long it lasts"
t½ goes UP when V_d is large (drug hides in tissues) or CL is low (poor elimination). t½ goes DOWN when V_d is small or CL is high.
Sources: Katzung's Basic & Clinical Pharmacology 16e; Goldman-Cecil Medicine; Barash's Clinical Anesthesia 9e; Rosen's Emergency Medicine

How to calculate it

Asking for Preferences
Here is a full step-by-step calculation guide for all three — starting from raw data and working through to the final answer.

Step-by-Step Calculations


SCENARIO

A patient receives 500 mg IV bolus of a drug.
  • Plasma concentration at time 0 (C₀) = 10 mg/L
  • AUC (area under concentration-time curve) = 100 mg·hr/L
  • Patient weight = 70 kg

STEP 1 — Calculate Volume of Distribution (V_d)

Formula: $$V_d = \frac{\text{Dose}}{C_0}$$
Plug in: $$V_d = \frac{500 \text{ mg}}{10 \text{ mg/L}}$$
$$\boxed{V_d = 50 \text{ L}}$$
Per kg: $$V_d = \frac{50 \text{ L}}{70 \text{ kg}} = 0.71 \text{ L/kg}$$
Interpretation: 0.71 L/kg → drug distributes into total body water + some tissue binding (similar to lithium or carbamazepine range).

STEP 2 — Calculate Clearance (CL)

Formula: $$CL = \frac{\text{Dose}}{\text{AUC}}$$
Plug in: $$CL = \frac{500 \text{ mg}}{100 \text{ mg·hr/L}}$$
$$\boxed{CL = 5 \text{ L/hr} = 83 \text{ mL/min}}$$
Interpretation: Moderate clearance. For reference — normal renal clearance (creatinine) is ~120 mL/min.

STEP 3 — Calculate Half-Life (t½)

Formula: $$t_{1/2} = \frac{0.693 \times V_d}{CL}$$
Plug in: $$t_{1/2} = \frac{0.693 \times 50 \text{ L}}{5 \text{ L/hr}}$$
$$t_{1/2} = \frac{34.65}{5}$$
$$\boxed{t_{1/2} = 6.93 \text{ hours} \approx 7 \text{ hours}}$$

STEP 4 — Calculate Elimination Rate Constant (K_e)

This is the fractional rate of elimination per hour.
Formula: $$K_e = \frac{CL}{V_d} = \frac{0.693}{t_{1/2}}$$
Plug in: $$K_e = \frac{5 \text{ L/hr}}{50 \text{ L}} = 0.1 \text{ hr}^{-1}$$
Meaning: 10% of the drug remaining in the body is eliminated every hour.

STEP 5 — Verify Using Concentration at Any Time Point

Once you have K_e, you can predict drug concentration at any time:
$$C_t = C_0 \times e^{-K_e \times t}$$
What is the concentration at t = 7 hours?
$$C_7 = 10 \times e^{-0.1 \times 7} = 10 \times e^{-0.7} = 10 \times 0.497$$
$$\boxed{C_7 \approx 5 \text{ mg/L}}$$
That is exactly half of 10 mg/L — confirms t½ = 7 hours. ✓

STEP 6 — Calculate Loading Dose (bonus)

If you need a target concentration of 8 mg/L:
$$\text{Loading Dose} = V_d \times C_{target}$$
$$= 50 \text{ L} \times 8 \text{ mg/L} = \mathbf{400 \text{ mg}}$$

STEP 7 — Predict Drug Elimination Timeline

With t½ = 7 hours, starting at C₀ = 10 mg/L:
Time# of t½Concentration% Remaining
0 hr010 mg/L100%
7 hr15 mg/L50%
14 hr22.5 mg/L25%
21 hr31.25 mg/L12.5%
28 hr40.625 mg/L6.25%
35 hr50.31 mg/L~3% → eliminated

Quick Reference — What You Need to Calculate Each

To findYou needFormula
V_dDose + C₀Dose ÷ C₀
CLDose + AUCDose ÷ AUC
V_d + CL0.693 × V_d ÷ CL
K_eCL + V_dCL ÷ V_d
C at time tC₀ + K_e + timeC₀ × e^(−K_e × t)
Loading doseV_d + target CV_d × C_target

How to Get AUC From a Graph

If you have a plasma concentration vs. time graph, AUC is the area under that curve. It can be calculated by:
  1. Trapezoidal rule — divide the curve into trapezoids, sum the areas
  2. From C₀ and K_e (for one-compartment model):
$$AUC = \frac{C_0}{K_e} = \frac{C_0 \times t_{1/2}}{0.693}$$
Using our example: AUC = 10 ÷ 0.1 = 100 mg·hr/L ✓ — matches the given value.

Give with examples and make timetable

Checking Date & Time
Reading File
Running Command

ls -la /home/daytona/workspace/ 2>/dev/null || echo "workspace not found"

Running Command

mkdir -p /home/daytona/workspace/pharmacokinetics && ls /home/daytona/workspace/

Writing File

~/pharmacokinetics/pk_timetable.py

import openpyxl
from openpyxl.styles import (
    PatternFill, Font, Alignment, Border, Side, GradientFill
)
from openpyxl.utils import get_column_letter
from openpyxl.chart import LineChart, Reference
from openpyxl.chart.series import DataPoint
import math

wb = openpyxl.Workbook()

# ─── COLOURS ───────────────────────────────────────────────────────────────
DARK_BLUE  = "1F4E79"
MED_BLUE   = "2E75B6"
LIGHT_BLUE = "BDD7EE"
HEADER_BG  = "1F4E79"
ALT_ROW    = "EBF3FB"
WHITE      = "FFFFFF"
GREEN      = "375623"
GREEN_BG   = "E2EFDA"
ORANGE_BG  = "FCE4D6"
ORANGE     = "833C00"
YELLOW_BG  = "FFF2CC"
PURPLE_BG  = "E9D7F5"
RED        = "C00000"
GREY_BG    = "F2F2F2"

def hdr_font(size=11, bold=True, color=WHITE):
    return Font(name="Arial", size=size, bold=bold, color=color)

def body_font(size=10, bold=False, color="000000"):
    return Font(name="Arial", size=size, bold=bold, color=color)

def fill(hex_color):
    return PatternFill("solid", fgColor=hex_color)

def thin_border():
    s = Side(style="thin", color="AAAAAA")
    return Border(left=s, right=s, top=s, bottom=s)

def center():
    return Alignment(horizontal="center", vertical="center", wrap_text=True)

def left():
    return Alignment(horizontal="left", vertical="center", wrap_text=True)

def merge_title(ws, cell_range, text, bg, fg=WHITE, size=13, bold=True):
    ws.merge_cells(cell_range)
    c = ws[cell_range.split(":")[0]]
    c.value = text
    c.font = Font(name="Arial", size=size, bold=bold, color=fg)
    c.fill = fill(bg)
    c.alignment = center()


# ══════════════════════════════════════════════════════════════════════════════
# SHEET 1 — FORMULAS & CONCEPTS
# ══════════════════════════════════════════════════════════════════════════════
ws1 = wb.active
ws1.title = "Formulas & Concepts"
ws1.sheet_view.showGridLines = False
ws1.column_dimensions["A"].width = 28
ws1.column_dimensions["B"].width = 32
ws1.column_dimensions["C"].width = 36
ws1.column_dimensions["D"].width = 38

# Title
ws1.row_dimensions[1].height = 36
merge_title(ws1, "A1:D1",
            "PHARMACOKINETICS — Formulas & Key Concepts",
            DARK_BLUE, WHITE, 14)

ws1.row_dimensions[2].height = 8  # spacer

# Sub-headers
headers = ["Parameter", "Formula", "What You Need", "Interpretation"]
for col, h in enumerate(headers, 1):
    c = ws1.cell(row=3, column=col, value=h)
    c.font = hdr_font(11)
    c.fill = fill(MED_BLUE)
    c.alignment = center()
    c.border = thin_border()
ws1.row_dimensions[3].height = 22

rows = [
    ("Volume of Distribution\n(Vd)",
     "Vd = Dose ÷ C₀\n\nLoading Dose = Vd × C_target",
     "Dose (mg)\nC₀ = plasma conc. at time 0 (mg/L)",
     "Small Vd → stays in plasma\nLarge Vd → hides in tissues\nVd > total body volume → extensive tissue binding"),

    ("Clearance\n(CL)",
     "CL = Dose ÷ AUC\nCL = Ke × Vd\n\nCL_total = CL_renal + CL_hepatic",
     "Dose (mg)\nAUC = area under conc-time curve (mg·hr/L)",
     "How efficiently the body removes drug\nHigh CL → rapid elimination\nLow CL → drug accumulates"),

    ("Elimination Rate Constant\n(Ke)",
     "Ke = CL ÷ Vd\nKe = 0.693 ÷ t½",
     "CL (L/hr)\nVd (L)",
     "Fraction of drug eliminated per unit time\nUnits: hr⁻¹\nSlope of log(C) vs time graph"),

    ("Half-Life\n(t½)",
     "t½ = 0.693 × Vd ÷ CL\nt½ = 0.693 ÷ Ke",
     "Vd (L)\nCL (L/hr)\nOR Ke (hr⁻¹)",
     "Time for plasma conc to fall by 50%\n↑Vd → ↑t½\n↑CL → ↓t½\nSteady state reached after ~5 × t½"),

    ("Concentration at Time t\n[C(t)]",
     "C(t) = C₀ × e^(−Ke × t)",
     "C₀ (mg/L)\nKe (hr⁻¹)\nt = time point (hr)",
     "Predicts plasma level at any time\nAfter 1 t½: 50% of C₀\nAfter 2 t½: 25% of C₀\nAfter n t½: C₀ × (0.5)ⁿ"),

    ("AUC (Area Under Curve)",
     "AUC = C₀ ÷ Ke\nAUC = C₀ × t½ ÷ 0.693",
     "C₀ (mg/L)\nKe (hr⁻¹)\nOR C₀ + t½",
     "Total drug exposure\nUsed to calculate CL\nLarger AUC = more drug exposure"),
]

bg_colors = [LIGHT_BLUE, GREEN_BG, YELLOW_BG, ORANGE_BG, PURPLE_BG, GREY_BG]
for r_idx, (row, bg) in enumerate(zip(rows, bg_colors), 4):
    ws1.row_dimensions[r_idx].height = 68
    for col_idx, val in enumerate(row, 1):
        c = ws1.cell(row=r_idx, column=col_idx, value=val)
        c.fill = fill(bg)
        c.border = thin_border()
        c.alignment = left() if col_idx > 1 else center()
        if col_idx == 1:
            c.font = Font(name="Arial", size=10, bold=True, color=DARK_BLUE)
        elif col_idx == 2:
            c.font = Font(name="Arial", size=10, bold=False, color="000000")
        else:
            c.font = body_font(9)


# ══════════════════════════════════════════════════════════════════════════════
# SHEET 2 — WORKED EXAMPLES
# ══════════════════════════════════════════════════════════════════════════════
ws2 = wb.create_sheet("Worked Examples")
ws2.sheet_view.showGridLines = False
for col, w in zip("ABCDE", [6, 28, 22, 32, 32]):
    ws2.column_dimensions[col].width = w

ws2.row_dimensions[1].height = 36
merge_title(ws2, "A1:E1", "PHARMACOKINETICS — Worked Examples (3 Drugs)", DARK_BLUE)

ws2.row_dimensions[2].height = 8

# ── Example drugs data ──────────────────────────────────────────────────────
drugs = [
    {
        "name": "Drug A — Amoxicillin",
        "color": GREEN_BG, "hdr_color": "375623",
        "dose": 500, "C0": 15.15, "AUC": 1.2,
        "note": "Antibiotic; renally cleared; short t½ → dose every 8 hrs",
    },
    {
        "name": "Drug B — Phenytoin",
        "color": ORANGE_BG, "hdr_color": ORANGE,
        "dose": 300, "C0": 7.14, "AUC": 60,
        "note": "Antiepileptic; hepatically cleared; zero-order at high doses",
    },
    {
        "name": "Drug C — Digoxin",
        "color": PURPLE_BG, "hdr_color": "4B0082",
        "dose": 0.5, "C0": 0.001, "AUC": 0.1,
        "note": "Cardiac glycoside; large Vd due to tissue binding; renally cleared",
    },
]

row = 3
for drug in drugs:
    dose = drug["dose"]
    C0   = drug["C0"]
    AUC  = drug["AUC"]
    Vd   = round(dose / C0, 2)
    CL   = round(dose / AUC, 4)
    Ke   = round(CL / Vd, 4)
    t_half = round(0.693 / Ke, 2)

    # Drug header
    ws2.row_dimensions[row].height = 22
    ws2.merge_cells(f"A{row}:E{row}")
    c = ws2[f"A{row}"]
    c.value = drug["name"]
    c.font  = Font(name="Arial", size=12, bold=True, color=drug["hdr_color"])
    c.fill  = fill(drug["color"])
    c.alignment = center()
    row += 1

    # Column headers
    ws2.row_dimensions[row].height = 20
    for col, h in enumerate(["Step", "What We're Calculating", "Formula Used", "Calculation", "Result"], 1):
        c = ws2.cell(row=row, column=col, value=h)
        c.font  = hdr_font(10)
        c.fill  = fill(MED_BLUE)
        c.alignment = center()
        c.border = thin_border()
    row += 1

    steps = [
        ("1", "Volume of Distribution (Vd)",
         "Vd = Dose ÷ C₀",
         f"{dose} mg ÷ {C0} mg/L",
         f"Vd = {Vd} L"),
        ("2", "Clearance (CL)",
         "CL = Dose ÷ AUC",
         f"{dose} mg ÷ {AUC} mg·hr/L",
         f"CL = {CL} L/hr"),
        ("3", "Elimination Rate Constant (Ke)",
         "Ke = CL ÷ Vd",
         f"{CL} ÷ {Vd}",
         f"Ke = {Ke} hr⁻¹"),
        ("4", "Half-Life (t½)",
         "t½ = 0.693 ÷ Ke",
         f"0.693 ÷ {Ke}",
         f"t½ = {t_half} hr"),
        ("5", "AUC Verification",
         "AUC = C₀ ÷ Ke",
         f"{C0} ÷ {Ke}",
         f"AUC ≈ {round(C0/Ke, 2)} mg·hr/L"),
    ]

    for step in steps:
        ws2.row_dimensions[row].height = 22
        for col, val in enumerate(step, 1):
            c = ws2.cell(row=row, column=col, value=val)
            c.font   = body_font(10, bold=(col == 5))
            c.fill   = fill(drug["color"])
            c.border = thin_border()
            c.alignment = center() if col in (1, 3, 5) else left()
        row += 1

    # Note row
    ws2.row_dimensions[row].height = 20
    ws2.merge_cells(f"A{row}:E{row}")
    c = ws2[f"A{row}"]
    c.value = f"📋 Note: {drug['note']}"
    c.font  = Font(name="Arial", size=9, italic=True, color="555555")
    c.fill  = fill(GREY_BG)
    c.alignment = left()
    row += 2  # spacer


# ══════════════════════════════════════════════════════════════════════════════
# SHEET 3 — ELIMINATION TIMETABLE (3 drugs)
# ══════════════════════════════════════════════════════════════════════════════
ws3 = wb.create_sheet("Elimination Timetable")
ws3.sheet_view.showGridLines = False

# Column widths
ws3.column_dimensions["A"].width = 14   # Time (hr)
ws3.column_dimensions["B"].width = 10   # # half-lives
ws3.column_dimensions["C"].width = 18   # Amoxicillin C
ws3.column_dimensions["D"].width = 16   # Amox % remain
ws3.column_dimensions["E"].width = 18   # Phenytoin C
ws3.column_dimensions["F"].width = 16   # Phenyt % remain
ws3.column_dimensions["G"].width = 18   # Digoxin C
ws3.column_dimensions["H"].width = 16   # Digoxin % remain

ws3.row_dimensions[1].height = 36
merge_title(ws3, "A1:H1",
            "ELIMINATION TIMETABLE — Plasma Concentration Over Time (First-Order Kinetics)",
            DARK_BLUE)

ws3.row_dimensions[2].height = 8

# Drug params for timetable
# Amox: C0=15.15 mg/L, t½=1.2 hr, Ke=0.577
# Phenytoin: C0=7.14 mg/L, t½=14 hr, Ke=0.0495
# Digoxin: C0=0.001 mg/L (1 µg/L), t½=40 hr, Ke=0.01733

drugs_t = [
    {"name": "Amoxicillin",  "C0": 15.15, "t_half": 1.2,  "Ke": round(0.693/1.2, 4),  "unit": "mg/L",  "dose": "500 mg"},
    {"name": "Phenytoin",    "C0": 7.14,  "t_half": 14.0, "Ke": round(0.693/14.0, 4), "unit": "mg/L",  "dose": "300 mg"},
    {"name": "Digoxin",      "C0": 1.0,   "t_half": 40.0, "Ke": round(0.693/40.0, 4), "unit": "µg/L",  "dose": "0.5 mg"},
]

# Drug sub-headers row 3
ws3.row_dimensions[3].height = 16
ws3.merge_cells("C3:D3")
ws3["C3"].value = f"Amoxicillin (t½={drugs_t[0]['t_half']} hr)"
ws3["C3"].font  = Font(name="Arial", size=10, bold=True, color=GREEN)
ws3["C3"].fill  = fill(GREEN_BG)
ws3["C3"].alignment = center()
ws3.merge_cells("E3:F3")
ws3["E3"].value = f"Phenytoin (t½={drugs_t[1]['t_half']} hr)"
ws3["E3"].font  = Font(name="Arial", size=10, bold=True, color=ORANGE)
ws3["E3"].fill  = fill(ORANGE_BG)
ws3["E3"].alignment = center()
ws3.merge_cells("G3:H3")
ws3["G3"].value = f"Digoxin (t½={drugs_t[2]['t_half']} hr)"
ws3["G3"].font  = Font(name="Arial", size=10, bold=True, color="4B0082")
ws3["G3"].fill  = fill(PURPLE_BG)
ws3["G3"].alignment = center()

# Column headers row 4
ws3.row_dimensions[4].height = 22
col_headers = [
    "Time (hr)", "# Half-Lives",
    f"Conc ({drugs_t[0]['unit']})", "% Remaining",
    f"Conc ({drugs_t[1]['unit']})", "% Remaining",
    f"Conc ({drugs_t[2]['unit']})", "% Remaining",
]
col_fills = [DARK_BLUE, DARK_BLUE, MED_BLUE, MED_BLUE, "A0522D", "A0522D", "4B0082", "4B0082"]
for col, (h, bg) in enumerate(zip(col_headers, col_fills), 1):
    c = ws3.cell(row=4, column=col, value=h)
    c.font      = hdr_font(10)
    c.fill      = fill(bg)
    c.alignment = center()
    c.border    = thin_border()

# Time points — smart: covers 5 half-lives of the longest drug (digoxin, 40 hr → 200 hr)
time_points = [0, 1, 2, 4, 6, 8, 12, 14, 20, 24, 28, 40, 48, 56, 60, 80, 100, 120, 140, 160, 200]

row_colors = [WHITE, ALT_ROW]

for r_idx, t in enumerate(time_points, 5):
    ws3.row_dimensions[r_idx].height = 18
    bg = row_colors[r_idx % 2]

    n_half_lives_amox = round(t / drugs_t[0]["t_half"], 2)

    row_data = [t, n_half_lives_amox]

    for drug in drugs_t:
        C0   = drug["C0"]
        Ke   = drug["Ke"]
        Ct   = round(C0 * math.exp(-Ke * t), 4)
        pct  = round((Ct / C0) * 100, 2)
        row_data.extend([Ct, pct])

    for col, val in enumerate(row_data, 1):
        c = ws3.cell(row=r_idx, column=col, value=val)
        c.border    = thin_border()
        c.alignment = center()

        # Color by drug column
        if col in (1, 2):
            c.fill = fill(GREY_BG)
            c.font = body_font(10, bold=True, color=DARK_BLUE)
        elif col in (3, 4):
            pct_val = row_data[3]
            if pct_val < 5:
                c.fill = fill("C6EFCE")   # green = eliminated
                c.font = body_font(9, color=GREEN)
            elif pct_val < 25:
                c.fill = fill(GREEN_BG)
                c.font = body_font(9)
            else:
                c.fill = fill(bg)
                c.font = body_font(10)
        elif col in (5, 6):
            pct_val = row_data[5]
            if pct_val < 5:
                c.fill = fill("C6EFCE")
                c.font = body_font(9, color=GREEN)
            elif pct_val < 25:
                c.fill = fill(ORANGE_BG)
                c.font = body_font(9)
            else:
                c.fill = fill(bg)
                c.font = body_font(10)
        else:
            pct_val = row_data[7]
            if pct_val < 5:
                c.fill = fill("C6EFCE")
                c.font = body_font(9, color=GREEN)
            elif pct_val < 25:
                c.fill = fill(PURPLE_BG)
                c.font = body_font(9)
            else:
                c.fill = fill(bg)
                c.font = body_font(10)

        # Format % columns nicely
        if col in (4, 6, 8):
            c.number_format = '0.00"%"'

# Key milestone rows — highlight "~eliminated" rows
# Add legend below table
legend_row = 5 + len(time_points) + 2
ws3.merge_cells(f"A{legend_row}:H{legend_row}")
c = ws3[f"A{legend_row}"]
c.value = "LEGEND:   Green shading = < 5% remaining (drug effectively eliminated)   |   ~5 half-lives needed for >97% elimination"
c.font  = Font(name="Arial", size=9, italic=True, color="333333")
c.fill  = fill("C6EFCE")
c.alignment = left()


# ══════════════════════════════════════════════════════════════════════════════
# SHEET 4 — REAL DRUG COMPARISON TABLE
# ══════════════════════════════════════════════════════════════════════════════
ws4 = wb.create_sheet("Real Drug PK Data")
ws4.sheet_view.showGridLines = False

col_widths4 = [22, 8, 22, 24, 12, 18, 22, 30]
for col, w in enumerate(col_widths4, 1):
    ws4.column_dimensions[get_column_letter(col)].width = w

ws4.row_dimensions[1].height = 36
merge_title(ws4, "A1:H1",
            "REAL DRUG PHARMACOKINETIC REFERENCE TABLE",
            DARK_BLUE)
ws4.row_dimensions[2].height = 8

headers4 = ["Drug", "Dose\n(mg)", "Vd\n(L/kg)", "CL\n(mL/min)", "t½", "Primary\nClearance", "Protein\nBinding (%)", "Clinical Note"]
ws4.row_dimensions[3].height = 30
for col, h in enumerate(headers4, 1):
    c = ws4.cell(row=3, column=col, value=h)
    c.font      = hdr_font(10)
    c.fill      = fill(MED_BLUE)
    c.alignment = center()
    c.border    = thin_border()

drug_data = [
    # (Drug, Dose, Vd L/kg, CL mL/min, t½, Primary CL, Protein binding %, Clinical note, row_color)
    ("Heparin (UFH)",       5000,  0.06,  "~40",       "1–2 hr",   "Reticuloendothelial", "High",    "Stays in plasma; monitor aPTT", WHITE),
    ("Amoxicillin",         500,   0.47,  417,         "1.2 hr",   "Renal (86%)",         "17–18%",  "Dose-reduce in renal failure", ALT_ROW),
    ("Aspirin (low dose)",  325,   0.17,  "575–725",   "15–20 min","Hepatic (>95%)",       "80–90%",  "Very short t½; antithrombotic effect lasts 7–10 days (irreversible COX inhibition)", WHITE),
    ("Gentamicin",          80,    0.25,  "50–100",    "2–3 hr",   "Renal (>90%)",        "<10%",    "Narrow TI; once-daily dosing preferred; nephrotoxic", ALT_ROW),
    ("Phenytoin",           300,   0.6,   167,         "12–24 hr", "Hepatic (>95%)",       "88–93%",  "ZERO-ORDER at high doses — small dose increase causes big conc rise", WHITE),
    ("Carbamazepine",       400,   1.2,   "50–125",    "12–17 hr", "Hepatic (>95%)",       "75–90%",  "Induces own metabolism (autoinduction); t½ shortens with long-term use", ALT_ROW),
    ("Lithium",             300,   0.85,  "20–40",     "20–24 hr", "Renal (95–99%)",       "0%",      "Mirrors GFR exactly; monitor closely in renal impairment", WHITE),
    ("Warfarin",            5,     0.14,  "~3",        "36–42 hr", "Hepatic (>99%)",       "99%",     "Very low CL; many drug interactions via CYP2C9", ALT_ROW),
    ("Digoxin",             0.5,   5.0,   "~130",      "36–48 hr", "Renal (70–80%)",       "25%",     "Huge Vd → not dialysable; toxic in renal failure", WHITE),
    ("Diazepam",            10,    1.1,   "~25",       "20–100 hr","Hepatic (>99%)",        "96–99%",  "t½ DOUBLES in elderly due to ↑Vd (more body fat)", ALT_ROW),
    ("Amiodarone",          200,   "60+", "~2",        "40–55 DAYS","Hepatic",              "96%",     "Enormous Vd; t½ weeks–months; effects persist long after stopping", WHITE),
    ("Vancomycin",          1000,  0.7,   "~65",       "6–12 hr",  "Renal (>90%)",         "<55%",    "Dose-adjust by renal function; monitor trough levels", ALT_ROW),
]

for r_idx, row in enumerate(drug_data, 4):
    ws4.row_dimensions[r_idx].height = 34
    *data, bg = row
    for col, val in enumerate(data, 1):
        c = ws4.cell(row=r_idx, column=col, value=val)
        c.fill      = fill(bg)
        c.border    = thin_border()
        c.alignment = center() if col < 8 else left()
        if col == 1:
            c.font = Font(name="Arial", size=10, bold=True, color=DARK_BLUE)
        elif col == 7:
            # Highlight amiodarone t½
            if "DAYS" in str(val):
                c.font = Font(name="Arial", size=10, bold=True, color=RED)
            else:
                c.font = body_font(10)
        else:
            c.font = body_font(10)

# Footer note
note_row = 4 + len(drug_data) + 1
ws4.merge_cells(f"A{note_row}:H{note_row}")
c = ws4[f"A{note_row}"]
c.value = "* Values are approximate averages from published literature. TI = Therapeutic Index. CL = Clearance. Vd = Volume of Distribution."
c.font  = Font(name="Arial", size=8, italic=True, color="666666")
c.alignment = left()


# ══════════════════════════════════════════════════════════════════════════════
# SHEET 5 — LOADING DOSE & STEADY STATE CALCULATOR
# ══════════════════════════════════════════════════════════════════════════════
ws5 = wb.create_sheet("Loading Dose & Steady State")
ws5.sheet_view.showGridLines = False
for col, w in zip("ABCDE", [28, 20, 24, 28, 28]):
    ws5.column_dimensions[col].width = w

ws5.row_dimensions[1].height = 36
merge_title(ws5, "A1:E1",
            "LOADING DOSE & STEADY-STATE CALCULATIONS",
            DARK_BLUE)

ws5.row_dimensions[2].height = 8

# Section 1: Loading dose
merge_title(ws5, "A3:E3", "SECTION 1 — Loading Dose Examples", MED_BLUE, size=11)

ws5.row_dimensions[4].height = 20
for col, h in enumerate(["Drug", "Target Conc\n(mg/L)", "Vd (L/kg)", "Patient Wt\n(kg)", "Loading Dose (mg)"], 1):
    c = ws5.cell(row=4, column=col, value=h)
    c.font = hdr_font(10); c.fill = fill(MED_BLUE); c.alignment = center(); c.border = thin_border()

ld_examples = [
    ("Phenytoin",    10,  0.6, 70,  0.6*70*10),
    ("Phenytoin",    15,  0.6, 70,  0.6*70*15),
    ("Digoxin",      1.5, 5.0, 70,  5.0*70*0.0015),   # target in µg/L converted
    ("Vancomycin",   20,  0.7, 70,  0.7*70*20),
    ("Lithium",      0.8, 0.85,70,  0.85*70*0.8),
]
ld_colors = [WHITE, ALT_ROW, WHITE, ALT_ROW, WHITE]
for r_idx, (row, bg) in enumerate(zip(ld_examples, ld_colors), 5):
    ws5.row_dimensions[r_idx].height = 20
    drug_name, target, vd_per_kg, wt, ld = row
    for col, val in enumerate([drug_name, target, vd_per_kg, wt, round(ld,1)], 1):
        c = ws5.cell(row=r_idx, column=col, value=val)
        c.fill = fill(bg); c.border = thin_border(); c.alignment = center()
        c.font = Font(name="Arial", size=10, bold=(col==5), color=(DARK_BLUE if col==5 else "000000"))

# Formula note
ws5.row_dimensions[10].height = 20
ws5.merge_cells("A10:E10")
c = ws5["A10"]
c.value = "Formula: Loading Dose = Vd (L/kg) × Weight (kg) × Target Concentration (mg/L)"
c.font  = Font(name="Arial", size=10, italic=True, bold=True, color=DARK_BLUE)
c.fill  = fill(LIGHT_BLUE); c.alignment = left()

ws5.row_dimensions[11].height = 12  # spacer

# Section 2: Steady State
merge_title(ws5, "A12:E12", "SECTION 2 — Time to Steady State (5 × t½ Rule)", MED_BLUE, size=11)

ws5.row_dimensions[13].height = 20
for col, h in enumerate(["Drug", "t½", "1 × t½\n(50% SS)", "3 × t½\n(87.5% SS)", "5 × t½\n(≈97% SS = Steady State)"], 1):
    c = ws5.cell(row=13, column=col, value=h)
    c.font = hdr_font(10); c.fill = fill(MED_BLUE); c.alignment = center(); c.border = thin_border()

ss_drugs = [
    ("Aspirin",      "15–20 min",  "15–20 min",   "45–60 min",  "75–100 min"),
    ("Amoxicillin",  "1.2 hr",     "1.2 hr",       "3.6 hr",      "6 hr"),
    ("Vancomycin",   "6–12 hr",    "6–12 hr",      "18–36 hr",    "1.25–2.5 days"),
    ("Phenytoin",    "12–24 hr",   "12–24 hr",     "1.5–3 days",  "2.5–5 days"),
    ("Digoxin",      "36–48 hr",   "36–48 hr",     "4.5–6 days",  "7.5–10 days"),
    ("Warfarin",     "36–42 hr",   "36–42 hr",     "4.5–5.3 days","7.5–8.75 days"),
    ("Diazepam",     "20–100 hr",  "20–100 hr",    "2.5–12.5 days","4–20 days"),
    ("Amiodarone",   "40–55 days", "40–55 days",   "4–6 months",  "6–9 months"),
]
ss_colors = [WHITE, ALT_ROW] * 5
for r_idx, (row, bg) in enumerate(zip(ss_drugs, ss_colors), 14):
    ws5.row_dimensions[r_idx].height = 20
    for col, val in enumerate(row, 1):
        c = ws5.cell(row=r_idx, column=col, value=val)
        c.fill = fill(bg); c.border = thin_border(); c.alignment = center()
        if col == 5:
            c.font = Font(name="Arial", size=10, bold=True, color=DARK_BLUE)
            c.fill = fill(GREEN_BG)
        elif col == 1:
            c.font = Font(name="Arial", size=10, bold=True, color="000000")
        else:
            c.font = body_font(10)

# Key rule note
last_row = 14 + len(ss_drugs) + 1
ws5.merge_cells(f"A{last_row}:E{last_row}")
c = ws5[f"A{last_row}"]
c.value = "KEY RULE: Regardless of dose size, it always takes ~5 half-lives to reach steady state — only the LEVEL (not speed) changes with dose."
c.font  = Font(name="Arial", size=10, italic=True, bold=True, color=RED)
c.fill  = fill(YELLOW_BG); c.alignment = left()


# ══════════════════════════════════════════════════════════════════════════════
# SAVE
# ══════════════════════════════════════════════════════════════════════════════
out_path = "/home/daytona/workspace/pharmacokinetics/Pharmacokinetics_PK_Timetable.xlsx"
wb.save(out_path)
print(f"Saved: {out_path}")
Running Command

cd /home/daytona/workspace/pharmacokinetics && python pk_timetable.py

You've run out of free credits. Sign up for a free account to continue using Orris.
This is a shared conversation. Sign in to Orris to start your own chat.