BP101T · Semester 1 · B.Pharm

Unit V — Data Visualization with Matplotlib

Basics of Python Programming for Pharmaceutical Sciences

This study page introduces Data Visualization with Matplotlib in Basics of Python Programming for Pharmaceutical Sciences (BP101T), B.Pharm Semester 1. Read the full notes below, or download the unit PDF for offline study.

Topics in this unit

  • Matplotlib line plots, histograms, scatter plots, and box plots
  • Axes, titles, and legends
  • Concentration-time curves for oral and IV administration
  • ADR reporting rates, dissolution profiles, and scientific interpretation of plots

Full notes for this unit

Read the notes here, or download the PDF below for offline study. Plots and diagrams are in the PDF. All data in the examples is synthetic teaching data.

Figure, Axes, Labels

Parts checklist

  • Title - one-line result
  • xlabel / ylabel - with units
  • Curves + markers - one style each
  • Legend - never cover data
  • Grid - light, reading aid only
first_plot.py
# first line plot - dissolution rises with time
import matplotlib.pyplot as plt
x = [0, 1, 2, 3, 4, 5] # time, min
y = [0, 4, 9, 15, 24, 36] # % dissolved
plt.plot(x, y, marker='o', label='Batch A')
plt.xlabel('Time (min)'); plt.ylabel('% dissolved')
plt.title('Dissolution rises with time'); plt.legend()
plt.savefig('first.png', dpi=110)

Figure saved: one rising curve with markers, axes labelled, legend top-left. Reading: release climbs from 0 to 36% over 5 min - monotonic rise, no plateau yet.

Conc-Time: Oral vs IV

Pharma story

IV bolus starts at its peak and falls (elimination only). Oral starts at zero, rises to Cmax at Tmax (absorption beats elimination), then falls. Two curves on one Axes make the comparison instant.

conc_time.py
# conc-time curves: oral vs IV (synthetic teaching data)
import numpy as np; import matplotlib.pyplot as plt
t = np.linspace(0, 12, 200) # hours
iv = 18 * np.exp(-0.55 * t)
to = t - 0.4; oral = np.where(to>0, 15.5*(np.exp(-0.5*to)-np.exp(-2.4*to)), 0)
fig, ax = plt.subplots(figsize=(5, 3.2), dpi=110)
ax.plot(t, iv, label='IV bolus'); ax.plot(t, oral, label='Oral tablet')
ax.set_xlabel('Time (h)'); ax.set_ylabel('Plasma conc. (mg/L)')
ax.legend(); fig.savefig('conc.png', bbox_inches='tight')

Why two curves, one Axes? Same x (time) and same y (mg/L) means the eye compares shapes directly: IV peak at t = 0 vs oral delayed peak. Separate figures would hide that contrast.

Reading the curves (exam lines)

IV: C0 ~ 18 mg/L at t = 0, exponential fall - no absorption phase. Oral: Cmax ~ 8.1 mg/L at Tmax ~ 1.2 h - then declines parallel to IV (same elimination). One-line interpretation: oral lags IV, peaks lower and later, then eliminates similarly - exactly what first-pass + absorption delay predicts. Synthetic teaching data. IV curve always starts highest; oral curve crosses it only on the way down - state both facts for full marks.

Dissolution-% Distribution

histogram.py
# distribution of dissolution at 30 min, n=120 tablets
rng = np.random.default_rng(5)
d = np.clip(rng.normal(82, 6, 120), 60, 100)
ax.hist(d, bins=12, edgecolor='white')
ax.axvline(d.mean(), ls='--', label='Mean') # dashed pink line
ax.set_xlabel('Dissolution at 30 min (%)')

What the histogram says

Mean ~ 80.9%, bulk of tablets 75-90% - a tight, near-symmetric mound. Any bar far left of the main mound, such as below 70%, would mark suspect tablets worth retesting. Exam line: histograms show spread, line plots show trend - if asked why not a line plot here, say the x-axis is value-bins, not time.

Dose-vs-Response + Trend

scatter.py
# dose-response scatter with fitted trend line
dose = np.array([50, 75, 100, 150, 200, 250, 300, 350, 400])
m, b = np.polyfit(dose, resp, 1) # straight-line fit
ax.scatter(dose, resp, s=42, label='Patients')
ax.plot(xx, m*xx+b, label='Trend') # orange line
ax.set_xlabel('Dose (mg)'); ax.set_ylabel('Response (%)')

Trend reading

Positive slope ~ 0.18 response-% per mg - response rises with dose but flattens past ~300 mg (diminishing returns). Exam line: a scatter proves association, not causation - always add that caveat before claiming efficacy.

ADR Rates Across 3 Drugs

boxplot.py
# ADR reports per 1000 patients, 3 drugs (synthetic teaching data)
ax.boxplot([A, B, C], labels=['Drug A', 'Drug B', 'Drug C'])
ax.set_ylabel('ADR reports per 1000 patients')
# box = IQR (Q1-Q3), line = median, whiskers = range, dots = outliers

Median / IQR reading

Drug A lowest median (~6) + narrow box - safest, most consistent. Drug B middle median (~11) but widest box - variable reporting. Drug C highest median (~17) - needs safety review. Exam definitions: median = middle line, IQR = box height, outliers = dots. Wide box = inconsistent; high median = frequent ADRs.

Multi-Batch Release Curves

dissolution.py
# % released vs time for three batches (synthetic teaching data)
tm = np.array([0, 5, 10, 15, 30, 45, 60])
ax.plot(tm, b1, marker='o', label='Batch 1 (ref)')
ax.plot(tm, b2, marker='s', label='Batch 2')
ax.plot(tm, b3, marker='..', label='Batch 3 (slow)')
ax.set_ylim(0, 105); ax.legend()

Similarity reading (no jargon needed)

Batch 2 hugs Batch 1 at every time point - similar release. Batch 3 runs 10-15 points lower throughout - slower release, likely different granulation or coating. Exam line: compare whole curves, not one time point - curves that stay close at all points are similar; one that sags everywhere is not.

The 4-Line Finish

Master checklist

xlabel / ylabel - quantity + unit, e.g. Time (min). No unit = half mark gone. title - states the finding, not the method: 'Oral peaks later than IV' beats 'Conc vs time'. legend - names every curve; move it off the data with loc='best'. order - label everything before savefig(); anything after saving never appears.

What Examiners Ask

Plot typeExaminer asksModel answer stem
LineWhere is the peak? What falls faster?Peaks at ... then declines; A falls faster than B
HistogramWhere is the bulk? Any outliers?Bulk at ...; bars below ... are suspect
ScatterTrend? Strength?Positive trend, slope ~...; association, not proof
BoxWhich median highest? Which IQR widest?C highest median; B widest IQR = most variable
DissolutionWhich batch matches ref?Batch 2 hugs ref; Batch 3 sags throughout

Three-sentence template

Sentence 1: describe (rises/falls/peaks at ...). Sentence 2: compare (higher/wider/closer than ...). Sentence 3: conclude (so Batch 2 is similar / Drug C needs review). Practice it under every figure. Numbers beat adjectives: quote Cmax, Tmax, mean, median, slope - then interpret them in one pharma sentence.

Fix It Fast

oops.py
# ERROR 1: x and y lengths differ
ax.plot([0,1,2], [5, 9]) # ValueError: x and y must have same first dimension
# FIX: check len(x) == len(y) before plotting
# ERROR 2: labels after savefig() never appear
fig.savefig('a.png'); ax.set_xlabel('Time') # too late!
# FIX: xlabel, legend, title FIRST, savefig() LAST

Missing labels + show() order

Blank-looking figure? You called savefig() before xlabel() / legend(). Rule: plot - label - legend - title - save, in that order. Legend covering data? Add loc='best' or bbox_to_anchor - never let the box hide the peak you are asked about. Notebook shows nothing? In scripts use savefig(); plt.show() is for interactive windows and blocks scripts after it.

Which Plot When?

QuestionPlotFunction
Trend over time (conc, release)Lineplt.plot / ax.plot
Spread of values (dissolution %)Histogramax.hist
Relation of two variablesScatter + trendax.scatter + polyfit
Compare groups (ADR by drug)Box plotax.boxplot
Several batches vs timeMulti-lineax.plot x N + legend

Decision rule

One variable over time: line. One variable's spread: histogram. Two variables' relation: scatter. Group comparison: box plot. If the examiner's question has the word 'distribution', reach for a histogram; 'trend' or 'profile', a line; 'across groups', a box plot.

Memory hook

Lines move, bars pile, dots relate, boxes compare. Say it once before choosing and you will rarely pick wrong.

Annotate the Peak

3-step drill (do it on every conc-time Q)

1 Top the peak - highest point of the oral curve: Cmax ~ 8.1 mg/L (dot + arrow). 2 Drop to x-axis - dotted line down: Tmax ~ 1.2 h. Read across for Cmax, down for Tmax. 3 Trace across - dotted line to y-axis confirms the value; quote both numbers, then add: oral lags IV, peaks lower and later. Code behind the arrows: ax.annotate(..., arrowprops) marks the peak, dotted ax.plot guides the eye to each axis.

Bins Lie, Labels Rescue

Bin-width verdict

30 bins: spiky, gaps distract - noise poses as structure. 5 bins: one blob - skew and suspects vanish. 12 bins: just right for n = 120. Exam line: too many bins = noise, too few = hides shape - defend your bin count in one sentence.

rescue.py
# rescue: 4 lines save the figure
ax.plot(tm, rel, marker='o', label='Batch 1')
ax.set_xlabel('Time (min)'); ax.set_ylabel('% released')
ax.legend(loc='lower right') # off the rise
fig.savefig('rescued.png') # LAST

Result: Same curve, rescued: units on both axes + legend off the data. Copy these 4 lines onto every bare plot.

Exam Points

#Point
1Line plot: IV peaks at t = 0; oral peaks later at Cmax / Tmax - state both.
2Histogram shows spread (bins), never use it for time trends.
3Scatter slope = response per unit dose; association is not causation.
4Box: line = median, box = IQR, dots = outliers; wide box = variable.
5Dissolution: compare whole curves; hugging curves are similar.
6Every figure needs xlabel + unit, ylabel + unit, legend, title.
7Order: plot - label - legend - title - savefig() LAST.
8ValueError on plot = mismatched x/y lengths; check len() first.

Say It Aloud

Examiner fires - you answer

Q: Why does oral lag IV? A: Absorption + first-pass delay; Cmax lower, Tmax later, then same elimination slope. Q: Histogram vs bar chart? A: Histogram bins one continuous variable (dissolution %); bar chart compares categories (drugs). Q: Box plot without whiskers? A: Whiskers show range beyond IQR; without them you cannot spot outliers or true spread. Q: Batch 3 sags - accept it? A: No - consistently lower release at all points signals a process deviation; investigate, do not average it away. Q: Scatter slopes down - meaning? A: Negative association: higher dose, lower response - check toxicity or data error before concluding anything.

Delivery tip

Point at the figure while answering: trace the curve with your finger as you quote Cmax, mean, or median. Examiners credit answers anchored to visible values.

Check Yourself

5 questions (answers in brackets)

  • IV vs oral: which peaks at t = 0? [IV; oral peaks at Tmax]
  • Histogram answers spread or trend? [spread; trends need line plots]
  • Box-plot box spans what? [IQR, Q1-Q3; line inside = median]
  • Two dissolution curves hug - verdict? [similar release profiles]
  • savefig() goes before or after legend()? [after - last call of all]

Summary

  • Line for trends, histogram for spread, scatter for relations, box for groups.
  • Quote the number (Cmax, mean, slope, median) then say what it means.
  • Label-legend-title-save: finish every figure the same way.

Takeaway

Matplotlib turns pharma tables into arguments: a labelled curve shows what a paragraph only claims. Master the four plot types here and CO5 is secured.

Pinpoints - Must Remember

10 hooks

1 Question says trend/profile - line; distribution/spread - histogram; relation - scatter; across groups - box. 2 Every figure: xlabel + unit, ylabel + unit, legend, finding-title. No unit = half mark gone. 3 Cmax = peak height, Tmax = peak time; read across then down. 4 Histogram words: mound, symmetric/skewed, bulk at ..., suspect bars below ... 5 Scatter: slope sign = direction; flattening = diminishing returns; association is not causation. 6 Box: line = median, box = IQR, whiskers = range, dots = outliers; wide box = variable. 7 Dissolution: compare whole curves; hugging = similar; sagging everywhere = deviation. 8 Order: plot - label - legend - title - savefig() LAST. 9 Bins: too many = noise, too few = hides shape; n = 120 likes ~12 bins. 10 Interpret in 3 sentences: describe - compare - conclude, with numbers quoted.

3 exam predictions

P1. Conc-time: label Cmax/Tmax on oral vs IV + one pharma sentence (absorption delay). P2. Box plot: highest median? widest IQR? verdict on which drug needs review. P3. Dissolution: which batch matches ref and why - whole-curve argument, not one point.

Mnemonic - LABEL-PLOT

Label axes, Annotate peaks, Bins justified, Explain numbers, Legend off data - PLOT like it matters.

Download notes

Save the PDF for offline reading. On some browsers, the file opens first; use the PDF viewer’s download button to save it.

For education and exam preparation only, not medical advice or current regulatory guidance.

Other units in this subject

Back to BP101T notes