Unit V · Basics of Python Programming for Pharmaceutical Sciences (BP101T) · As per PCI B.Pharmacy Syllabus, NEP 2020
Pharmaceutical research and practice generate large quantities of numerical data — plasma drug-concentration measurements from pharmacokinetic studies, adverse-event frequencies from pharmacovigilance databases, and in-vitro dissolution measurements used while developing solid oral dosage forms. Converting these numbers into clear, accurate visual representations is an essential skill for pharmacists, pharmaceutical scientists, and clinical researchers, and Python-based visualization is especially valuable here because the same reproducible script can be reused, shared, and applied to larger datasets. This post walks through two of the most important pharmaceutical plot types in the BP101T syllabus: the concentration-time curve for both intravenous and oral drug administration, and the visualization of adverse drug reaction (ADR) reporting rates across drugs.

1. Concentration-Time Curves: The Core Pharmacokinetic Plot
A concentration-time (C-t) curve shows how the concentration of a drug present in a biological fluid or tissue changes over time after the drug is given. The overall shape of this curve is governed by the combined effects of Absorption, Distribution, Metabolism, and Excretion — commonly abbreviated as ADME. Several important pharmacokinetic parameters can be read directly off, or calculated from, a concentration-time profile:
- Peak concentration (Cmax, mg/L): the highest plasma concentration the drug reaches after administration; important for judging both therapeutic efficacy and the risk of toxicity.
- Time to peak (Tmax, h): the time at which Cmax is reached; its value depends on how quickly the drug is absorbed.
- Elimination half-life (t½, h): the time needed for the plasma concentration to drop to half its value, calculated as t½ = 0.693 / ke, where ke is the elimination rate constant.
- Area under the curve (AUC, mg·h/L): a measure of total drug exposure over time, proportional to the amount of dose absorbed.
- Volume of distribution (Vd, L): the apparent volume into which the drug distributes throughout the body; for an IV dose, Vd = Dose / C0.
- Clearance (CL, L/h): the volume of plasma completely cleared of drug per unit time, related to the other parameters by CL = ke × Vd.
- Minimum effective concentration (MEC, mg/L): the lowest plasma concentration at which the drug still produces a therapeutic effect.
- Maximum safe concentration (MSC, mg/L): the concentration above which toxic effects start to appear.
The concentration range between the MEC and the MSC is called the therapeutic window. Effective pharmacotherapy aims to keep drug concentrations within this window for an appropriate proportion of the dosing interval — a concept you will see visually whenever a concentration-time curve is plotted alongside horizontal reference lines for MEC and MSC.
2. Intravenous Bolus Administration
When a drug is given as an intravenous (IV) bolus, the entire dose enters the bloodstream immediately, so no absorption phase is needed. Under a one-compartment model, the drug is assumed to distribute uniformly throughout its apparent volume of distribution and then undergo first-order elimination.
The IV Bolus Concentration Equation
The plasma concentration at time t is given by an exponential decay equation:
C(t) = C0 × e^(-ke × t)
where C(t) is the concentration at time t, C0 is the concentration immediately after administration, ke is the elimination rate constant, and t is time. The initial concentration relates to dose and volume of distribution as C0 = Dose / Vd, and the elimination rate constant relates to clearance as ke = CL / Vd. It can equally be derived from the half-life using t½ = 0.693 / ke.
When concentration is plotted against time on ordinary linear axes, the result is a downward-curving exponential profile. If concentration is instead plotted on a logarithmic axis against linear time, the relationship becomes approximately linear for first-order elimination — a technique called a semi-logarithmic plot, whose negative slope equals -ke / 2.303. Semi-log plots are widely used in pharmacokinetic analysis to estimate elimination parameters and to detect patterns suggestive of multi-compartment drug disposition.
Python Program: IV Bolus Concentration-Time Curve
import numpy as np
import matplotlib.pyplot as plt
# Time in hours
time_iv = np.linspace(0, 24, 100)
# IV bolus parameters
C0 = 10 # Initial concentration (mg/L)
ke = 0.15 # Elimination rate constant (h^-1)
# IV bolus concentration equation
concentration_iv = C0 * np.exp(-ke * time_iv)
# Plot IV curve
plt.figure(figsize=(6, 4))
plt.plot(
time_iv,
concentration_iv,
linewidth=2,
label='IV Bolus'
)
plt.xlabel('Time (h)')
plt.ylabel('Plasma Concentration (mg/L)')
plt.title('IV Bolus Concentration-Time Curve')
plt.grid(True)
plt.legend()
plt.show()
Because the entire dose enters systemic circulation immediately, concentration is highest at time zero and then decreases steadily as elimination proceeds through metabolism and excretion. A steep decline indicates relatively rapid elimination, while a gradual decline indicates slower elimination. Such curves help students understand parameters like half-life, dosing interval, and duration of drug action.
3. Oral Administration
Oral administration is pharmacokinetically more complex than IV administration because the drug must first be absorbed from the gastrointestinal tract before reaching systemic circulation. A one-compartment model incorporating first-order absorption and first-order elimination produces a concentration-time curve that initially rises, reaches a peak, and then declines.
The Oral Concentration Equation
C(t) = (F × Dose × Ka) / (Vd × (Ka − Ke)) × [e^(-Ke × t) − e^(-Ka × t)]
where F is bioavailability, Dose is the administered dose, Vd is the volume of distribution, Ka is the absorption rate constant, and Ke is the elimination rate constant. For the first-order absorption-and-elimination model, the time of peak concentration is:
Tmax = ln(Ka / Ke) / (Ka − Ke)
Cmax = (Dose / Vd) × (Ka / (Ka − Ke)) × [e^(-Ke × Tmax) − e^(-Ka × Tmax)]
The ascending portion of the oral curve is the absorption phase, during which the rate of drug entering systemic circulation exceeds the rate of elimination. Once the curve reaches Cmax at Tmax, elimination becomes dominant and the concentration falls.
Python Program: Oral Concentration-Time Curve
import numpy as np
import matplotlib.pyplot as plt
# Time array
time_oral = np.linspace(0, 24, 100)
# Oral PK parameters
F = 1 # Bioavailability
Dose = 500 # mg
Vd = 50 # L
ka = 1.2 # Absorption rate constant
ke = 0.15 # Elimination rate constant
# Oral concentration equation
concentration_oral = (
(F * Dose * ka) /
(Vd * (ka - ke))
) * (
np.exp(-ke * time_oral) -
np.exp(-ka * time_oral)
)
# Plot oral curve
plt.figure(figsize=(6, 4))
plt.plot(
time_oral,
concentration_oral,
linewidth=2,
label='Oral Administration'
)
plt.xlabel('Time (h)')
plt.ylabel('Plasma Concentration (mg/L)')
plt.title('Oral Concentration-Time Curve')
plt.grid(True)
plt.legend()
plt.show()
Unlike the IV bolus curve, the oral curve begins near zero and rises as the drug is absorbed, reaching Cmax at Tmax before elimination takes over. A faster absorption rate constant (Ka) generally produces an earlier, sharper peak, while slower absorption produces a delayed, flatter peak. Such curves are useful for comparing different formulations of the same drug and for evaluating differences in bioavailability.
4. ADR Reporting Rates Across Drugs
An adverse drug reaction (ADR) is a harmful and unintended response associated with the use of a drug at normally used doses for prevention, diagnosis, treatment, or modification of physiological function. Regulatory and public-health organizations maintain pharmacovigilance systems to collect and evaluate ADR information, and patterns in this data can help identify safety signals — statistical associations between a drug and an adverse event that warrant further investigation.
Visualizing ADR data helps pharmacists and researchers identify drugs associated with unusually frequent reports of particular reactions, compare the ADR burden between drugs or drug classes, communicate safety information to healthcare professionals, examine changes in reporting patterns over time, and support pharmacovigilance signal detection. Real-world ADR datasets typically contain multiple drugs, adverse-event categories, patient characteristics, and time periods, so choosing an appropriate visualization method matters when interpreting pharmacovigilance data.
Building and Visualizing a Simulated ADR Dataset
The example below uses a small, simulated dataset representing ADR reports collected for a set of common drugs, purely for illustration:
import matplotlib.pyplot as plt
import pandas as pd
# 1. Create a sample dataset (simulating pharmacy ADR reports)
data = {
"Drug Name": ['Aspirin', 'Metformin', 'Lisinopril', 'Aspirin', 'Amlodipine',
'Metformin', 'Aspirin', 'Atorvastatin', 'Lisinopril', 'Aspirin'],
"Reaction Severity": ['Mild', 'Moderate', 'Mild', 'Severe', 'Mild',
'Mild', 'Moderate', 'Mild', 'Mild', 'Moderate']
}
df = pd.DataFrame(data)
# 2. Calculate the number of reports per drug
adr_counts = df['Drug Name'].value_counts()
# 3. Visualize the data
plt.figure(figsize=(8, 5))
adr_counts.plot(kind="bar", color="salmon")
# Adding labels for pharmaceutical context
plt.title('ADR Reporting Frequency by Drug')
plt.xlabel("Drug Name")
plt.ylabel('Number of Reports')
plt.xticks(rotation=45)
plt.grid(axis="y", linestyle='--', alpha=0.7)
plt.show()
# Print the table for quick reference
print("Summary of ADR Reports:")
print(adr_counts)
Running this script counts how many rows correspond to each drug using value_counts(), then renders a bar chart where a taller bar means more reports were logged for that drug within the dataset: Aspirin (4 reports), Metformin (2), Lisinopril (2), Amlodipine (1), and Atorvastatin (1). A bar chart is the natural choice here because ADR reporting frequency is a comparison across discrete categories (drug names), which is exactly what bar charts are designed to show.
5. Reading the Concentration-Time and ADR Plots Together
Both plot types illustrate a broader principle in pharmaceutical data visualization: the choice of plot type must match the nature of the underlying data. A concentration-time relationship is continuous and time-based, so a line plot is appropriate. ADR frequency across named drugs is categorical, so a bar chart is appropriate. Applying the wrong plot type — for instance, using a line plot to connect ADR counts across unrelated drug names — can visually imply a trend or ordering that does not actually exist in the data.
| Feature | IV Bolus Curve | Oral Administration Curve |
|---|---|---|
| Concentration at t = 0 | Maximum (C0) | Zero (near-zero) |
| Absorption phase | Not applicable | Present (ascending limb) |
| Governing equation | C(t) = C0 × e(-ke·t) | C(t) with Ka and Ke terms (biexponential) |
| Key parameters read from curve | C0, t½, AUC | Cmax, Tmax, AUC |
Frequently Asked Questions
Why does the oral concentration-time curve have a rising portion while the IV curve does not?
The oral curve rises because the drug must first dissolve and be absorbed across the gastrointestinal membrane before it enters the bloodstream, so concentration builds up gradually until absorption is overtaken by elimination. An IV bolus places the drug directly into the bloodstream, so there is no absorption phase to model — concentration is already at its highest at time zero.
Is the sample ADR dataset in this post real pharmacovigilance data?
No. The dataset used in the example code is entirely fictional and constructed only to demonstrate how value_counts() and a bar chart can summarise reporting frequency in Python. It should never be cited as evidence about the actual safety profile of any named drug.
Can the same np.exp()-based approach be used to model other pharmacokinetic processes?
Yes. First-order exponential decay and biexponential absorption-elimination models, built using NumPy’s np.exp() function, are also used to describe processes such as multi-compartment distribution and, with a related equation, drug release from a dosage form (dissolution kinetics) — an extension of the same core visualization skills covered here.
Summary
Concentration-time curves and ADR reporting-rate charts are two of the most practically important visualizations a pharmacy student will build in Python. IV bolus administration produces a simple exponential decay curve governed by C0 and ke, while oral administration produces a rise-then-fall curve governed additionally by the absorption rate constant Ka, with Cmax and Tmax as its defining features. ADR reporting data, being categorical rather than continuous, is best visualized with a bar chart using pandas.value_counts() paired with Matplotlib. In every case, matching the plot type to the nature of the data — and clearly labeling axes, titles, and legends — is what turns a numerical dataset into a scientifically valid and communicable figure.
References
- Pharmacy Council of India (PCI) – B.Pharm Regulations, NEP 2020, BP101T Syllabus (Basics of Python Programming for Pharmaceutical Sciences)
- Python Software Foundation – Official Python Documentation, docs.python.org
- Matplotlib Development Team – Official Matplotlib Documentation, matplotlib.org
- pandas Development Team – Official pandas Documentation, pandas.pydata.org
- World Health Organization (WHO) – Uppsala Monitoring Centre, Pharmacovigilance and Signal Detection Guidance, who-umc.org
