hi
get me definitions of syrup ,its types ,methods of preparations, stability problems, everything about syrups
pharmaceutical syrups definition types methods of preparation stability problems pharmacy
https://bspublications.net/downloads/0676a59035560d_Ch-1_Siv…
https://formulation.bocsci.com/resource/syrup-definition-in-…
| Ingredient | Role | Examples |
|---|---|---|
| Sugar (sucrose) | Sweetener, vehicle, preservative (via osmotic pressure) | Sucrose, glucose, fructose, sorbitol |
| Water (purified) | Solvent | Purified water (IP/USP) |
| Antimicrobial preservatives | Prevent microbial growth in diluted syrups | Sodium benzoate, parabens, alcohol |
| Flavorants | Mask bitter/unpleasant API taste | Peppermint, cherry, raspberry flavors |
| Colorants | Improve visual appeal and patient compliance | FD&C dyes |
| Viscosity enhancers | Adjust consistency | Cellulose derivatives, glycerin |
| Special solvents/solubilizers | Improve API solubility | Glycerin, propylene glycol, ethanol |
| Active Pharmaceutical Ingredients (APIs) | Therapeutic effect | Codeine phosphate, paracetamol, etc. |
| Aspect | Key Points |
|---|---|
| Definition | Concentrated aqueous sugar solution ± API, for oral use |
| Sucrose conc. (USP) | 85% w/v (65% w/w) |
| Types | Simple, Flavored, Medicated; Sugar-based, Sugar-free |
| Methods | Heat, Cold agitation, Addition to medicated liquid, Percolation |
| Best stability method | Cold agitation (no heat) |
| Main stability issues | Microbial growth, inversion, crystallization, API degradation, caramelization |
| Self-preserving threshold | ≥ 65% w/w sucrose |
| Common preservatives | Sodium benzoate, parabens, alcohol (18% for free water) |
Create a comprehensive study guide PDF on syrups for reference
mkdir -p /home/daytona/workspace/syrups-study-guide && ls /home/daytona/workspac…
~/syrups-study-guide/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate
from reportlab.lib.colors import HexColor
import os
OUTPUT_PATH = "/home/daytona/workspace/syrups-study-guide/Syrups_Study_Guide.pdf"
# ── Colour Palette ──────────────────────────────────────────────────────────
DARK_BLUE = HexColor("#1A3A5C")
MED_BLUE = HexColor("#2E6DA4")
LIGHT_BLUE = HexColor("#D6E8F7")
ACCENT_TEAL = HexColor("#0E7C7B")
ACCENT_GOLD = HexColor("#E8A020")
LIGHT_GOLD = HexColor("#FFF4D6")
LIGHT_TEAL = HexColor("#D0EEEE")
WHITE = colors.white
LIGHT_GRAY = HexColor("#F4F6F8")
MED_GRAY = HexColor("#7A8A99")
DARK_GRAY = HexColor("#2D2D2D")
TABLE_HEADER= HexColor("#1A3A5C")
TABLE_ODD = HexColor("#EEF4FB")
TABLE_EVEN = WHITE
RED_BOX = HexColor("#C0392B")
GREEN_BOX = HexColor("#1A7A4A")
# ── Styles ───────────────────────────────────────────────────────────────────
base = getSampleStyleSheet()
def S(name, **kw):
return ParagraphStyle(name, **kw)
cover_title = S("CoverTitle",
fontSize=34, leading=42, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER)
cover_sub = S("CoverSub",
fontSize=16, leading=22, textColor=HexColor("#C8DCF0"),
fontName="Helvetica", alignment=TA_CENTER)
cover_info = S("CoverInfo",
fontSize=11, leading=16, textColor=HexColor("#A0C4E8"),
fontName="Helvetica", alignment=TA_CENTER)
chapter_title = S("ChapterTitle",
fontSize=18, leading=24, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_LEFT,
spaceBefore=4, spaceAfter=4)
section_heading = S("SectionHeading",
fontSize=13, leading=18, textColor=DARK_BLUE,
fontName="Helvetica-Bold",
spaceBefore=14, spaceAfter=4,
borderPad=4)
sub_heading = S("SubHeading",
fontSize=11, leading=15, textColor=ACCENT_TEAL,
fontName="Helvetica-Bold",
spaceBefore=10, spaceAfter=3)
body = S("Body",
fontSize=10, leading=15, textColor=DARK_GRAY,
fontName="Helvetica",
spaceBefore=3, spaceAfter=3, alignment=TA_JUSTIFY)
bullet_style = S("Bullet",
fontSize=10, leading=14, textColor=DARK_GRAY,
fontName="Helvetica",
leftIndent=16, bulletIndent=4,
spaceBefore=2, spaceAfter=2)
note_style = S("Note",
fontSize=9.5, leading=14, textColor=HexColor("#1A4A6B"),
fontName="Helvetica-Oblique",
leftIndent=10, rightIndent=10,
spaceBefore=2, spaceAfter=2)
key_style = S("Key",
fontSize=10, leading=14, textColor=HexColor("#7A3800"),
fontName="Helvetica-Bold",
leftIndent=10)
def colored_box(text, style, bg_color, border_color, radius=6):
"""Wrap a paragraph in a colored rounded box using a 1-cell table."""
t = Table([[Paragraph(text, style)]], colWidths=[16.5*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), bg_color),
("ROUNDEDCORNERS",[radius]),
("BOX", (0,0),(-1,-1), 1, border_color),
("TOPPADDING", (0,0),(-1,-1), 8),
("BOTTOMPADDING", (0,0),(-1,-1), 8),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
return t
def chapter_banner(text):
"""Dark-blue banner acting as chapter header."""
t = Table([[Paragraph(text, chapter_title)]], colWidths=[17*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), DARK_BLUE),
("ROUNDEDCORNERS",[6]),
("TOPPADDING", (0,0),(-1,-1), 10),
("BOTTOMPADDING", (0,0),(-1,-1), 10),
("LEFTPADDING", (0,0),(-1,-1), 14),
("RIGHTPADDING", (0,0),(-1,-1), 14),
]))
return t
def section_bar(text):
"""Teal left-bordered section bar."""
inner = S("InnerSB", parent=section_heading,
textColor=DARK_BLUE, spaceBefore=0, spaceAfter=0)
t = Table([[Paragraph(text, inner)]], colWidths=[16.5*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), LIGHT_BLUE),
("LINEBEFOREEACH",(0,0),(0,-1), 4, ACCENT_TEAL),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING", (0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
return t
def make_table(headers, rows, col_widths):
data = [headers] + rows
n = len(data)
style = [
("BACKGROUND", (0,0),(-1,0), TABLE_HEADER),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,0), 10),
("ALIGN", (0,0),(-1,0), "CENTER"),
("VALIGN", (0,0),(-1,-1),"MIDDLE"),
("FONTNAME", (0,1),(-1,-1),"Helvetica"),
("FONTSIZE", (0,1),(-1,-1), 9.5),
("ROWBACKGROUNDS",(0,1),(-1,-1), [TABLE_ODD, TABLE_EVEN]),
("GRID", (0,0),(-1,-1), 0.4, HexColor("#B0C8E0")),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 7),
("RIGHTPADDING", (0,0),(-1,-1), 7),
]
# Wrap cell text in Paragraph for automatic word wrap
cell_style = S("Cell", fontSize=9.5, leading=13, fontName="Helvetica",
textColor=DARK_GRAY)
hdr_style = S("Hdr", fontSize=10, leading=14, fontName="Helvetica-Bold",
textColor=WHITE, alignment=TA_CENTER)
wrapped = []
for ri, row in enumerate(data):
wr = []
for ci, cell in enumerate(row):
if ri == 0:
wr.append(Paragraph(str(cell), hdr_style))
else:
wr.append(Paragraph(str(cell), cell_style))
wrapped.append(wr)
t = Table(wrapped, colWidths=col_widths)
t.setStyle(TableStyle(style))
return t
# ── Page numbering ───────────────────────────────────────────────────────────
def add_page_number(canvas, doc):
canvas.saveState()
# Footer bar
canvas.setFillColor(DARK_BLUE)
canvas.rect(0, 0, A4[0], 22, fill=1, stroke=0)
canvas.setFillColor(WHITE)
canvas.setFont("Helvetica", 8)
canvas.drawString(2*cm, 7, "Pharmaceutical Syrups - Comprehensive Study Guide")
canvas.drawRightString(A4[0]-2*cm, 7, f"Page {doc.page}")
canvas.restoreState()
# ── Cover page ───────────────────────────────────────────────────────────────
def build_cover():
story = []
# Big blue header block
cover_block = Table(
[[Paragraph("PHARMACEUTICAL<br/>SYRUPS", cover_title)],
[Spacer(1, 6)],
[Paragraph("Comprehensive Study Guide", cover_sub)],
[Spacer(1, 10)],
[Paragraph("Definition | Classification | Preparation | Stability | Preservation", cover_info)]],
colWidths=[17*cm]
)
cover_block.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), DARK_BLUE),
("TOPPADDING", (0,0),(-1,-1), 28),
("BOTTOMPADDING", (0,0),(-1,-1), 28),
("LEFTPADDING", (0,0),(-1,-1), 20),
("RIGHTPADDING", (0,0),(-1,-1), 20),
]))
story.append(cover_block)
story.append(Spacer(1, 18))
# Quick-facts strip
qf_style = S("QF", fontSize=10, leading=14, fontName="Helvetica-Bold",
textColor=DARK_BLUE, alignment=TA_CENTER)
qf_val = S("QFV", fontSize=12, leading=16, fontName="Helvetica-Bold",
textColor=ACCENT_TEAL, alignment=TA_CENTER)
facts = [
["USP Concentration\n85% w/v", "Self-preserving\nThreshold: 65% w/w",
"4 Methods of\nPreparation", "Key Stability\nIssues: 7"],
]
qf_data = [[Paragraph(c.replace("\n","<br/>"), qf_style) for c in facts[0]]]
qf_table = Table(qf_data, colWidths=[4.1*cm]*4)
qf_table.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), LIGHT_GOLD),
("BOX", (0,0),(-1,-1), 1, ACCENT_GOLD),
("INNERGRID", (0,0),(-1,-1), 0.5, ACCENT_GOLD),
("TOPPADDING", (0,0),(-1,-1), 10),
("BOTTOMPADDING", (0,0),(-1,-1), 10),
]))
story.append(qf_table)
story.append(Spacer(1, 18))
# TOC-style contents
toc_heading = S("TOCH", fontSize=13, leading=18, fontName="Helvetica-Bold",
textColor=DARK_BLUE)
toc_item = S("TOCI", fontSize=10, leading=16, fontName="Helvetica",
textColor=DARK_GRAY, leftIndent=10)
chapters = [
"1. Definition & Pharmacopoeial Standards",
"2. Composition / Formulatory Ingredients",
"3. Classification & Types of Syrups",
"4. Methods of Preparation",
"5. Advantages of Syrups",
"6. Stability Problems & Solutions",
"7. Preservation of Syrups",
"8. Storage & Packaging",
"9. Quick-Reference Summary Tables",
"10. Practice Q&A",
]
toc_rows = [[Paragraph("CONTENTS", toc_heading)]]
for ch in chapters:
toc_rows.append([Paragraph(ch, toc_item)])
toc_t = Table(toc_rows, colWidths=[17*cm])
toc_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), LIGHT_BLUE),
("LINEAFTER", (0,0),(0,-1), 3, MED_BLUE),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 12),
]))
story.append(toc_t)
story.append(Spacer(1, 14))
credits_s = S("Cred", fontSize=8.5, leading=12, fontName="Helvetica-Oblique",
textColor=MED_GRAY, alignment=TA_CENTER)
story.append(Paragraph("Prepared for Pharmacy Students | July 2026 | Based on USP/IP Pharmacopoeia Standards", credits_s))
story.append(PageBreak())
return story
# ── Main content ─────────────────────────────────────────────────────────────
def build_content():
story = []
# ─ Chapter 1: Definition ─────────────────────────────────────────────────
story.append(chapter_banner("Chapter 1: Definition & Pharmacopoeial Standards"))
story.append(Spacer(1, 10))
story.append(section_bar("1.1 General Definition"))
story.append(Paragraph(
"Syrups are <b>concentrated aqueous solutions of sucrose or sugar substitutes</b>, "
"with or without flavoring agents and medicinal substances, intended primarily for "
"<b>oral administration</b>. They are palatable liquid dosage forms designed for ease "
"of swallowing and precise dose delivery.",
body))
story.append(Spacer(1, 6))
story.append(colored_box(
"<b>Pharmacopoeial Definition (BP/USP):</b> Syrups are pharmaceutical preparations "
"containing one or more active ingredients dissolved or suspended in a concentrated "
"aqueous solution of sugar or a sugar substitute, meeting specific quality criteria "
"for composition, stability, and packaging.",
note_style, LIGHT_BLUE, MED_BLUE))
story.append(Spacer(1, 8))
story.append(section_bar("1.2 Pharmacopoeial Standards"))
headers = ["Parameter", "IP Standard", "USP Standard"]
rows = [
["Sucrose concentration", "66.67% w/w", "85% w/v (65% w/w)"],
["Water volume per litre", "~", "450 mL"],
["Sucrose mass per litre", "~", "850 g"],
["Specific gravity", "~", "1.313"],
["Chemical drug syrups (min. sugar)", "≥ 65% g/mL", "≥ 65% w/w"],
["Medicinal extract syrups (min. sugar)", "≥ 60% g/mL", "≥ 60% w/w"],
["Simple syrup (as vehicle)", "85% g/mL", "85% w/v"],
]
story.append(make_table(headers, rows, [5*cm, 5*cm, 5*cm]))
story.append(Spacer(1, 8))
story.append(colored_box(
"<b>Key Note:</b> Syrup USP is NOT saturated despite its high concentration. "
"Only 425 mL of water is needed to dissolve 850 g sucrose, but 450 mL is used. "
"This slight excess prevents crystallization during cold storage.",
note_style, LIGHT_GOLD, ACCENT_GOLD))
story.append(Spacer(1, 10))
# ─ Chapter 2: Composition ────────────────────────────────────────────────
story.append(chapter_banner("Chapter 2: Composition / Formulatory Ingredients"))
story.append(Spacer(1, 10))
story.append(section_bar("2.1 Ingredient Overview"))
ing_headers = ["Ingredient", "Role", "Examples"]
ing_rows = [
["Sugar (Sucrose)", "Sweetener, vehicle, osmotic preservative, antioxidant base", "Sucrose, glucose, fructose, sorbitol, xylitol"],
["Purified Water", "Primary solvent", "IP/USP Purified Water"],
["Antimicrobial Preservatives", "Prevent microbial growth in diluted syrups", "Sodium benzoate, methyl/propyl parabens, benzoic acid, alcohol"],
["Flavorants", "Mask unpleasant API taste; improve palatability", "Peppermint oil, cherry, raspberry, vanilla"],
["Colorants", "Visual appeal; patient compliance", "FD&C certified dyes"],
["Viscosity Enhancers / Thickeners", "Adjust consistency; prevent settling of suspended APIs", "CMC, xanthan gum, glycerin, bentonite"],
["Solubilizers / Special Solvents", "Improve API solubility", "Glycerin, propylene glycol, ethanol"],
["Buffers / pH Adjusters", "Maintain pH for stability and palatability", "Citric acid, sodium citrate, phosphate buffers"],
["Antioxidants", "Prevent oxidative degradation of APIs", "Sodium metabisulfite, ascorbic acid, BHA/BHT"],
["Chelating Agents", "Remove trace metals that catalyse oxidation", "EDTA (disodium edetate)"],
["Active Pharmaceutical Ingredient (API)", "Therapeutic effect", "Codeine phosphate, paracetamol, dextromethorphan"],
]
story.append(make_table(ing_headers, ing_rows, [3.8*cm, 6.5*cm, 5.7*cm]))
story.append(Spacer(1, 10))
# ─ Chapter 3: Classification ─────────────────────────────────────────────
story.append(chapter_banner("Chapter 3: Classification & Types of Syrups"))
story.append(Spacer(1, 10))
story.append(section_bar("3.1 Classification by Medicinal Content"))
types_data = [
["Type", "Description", "API Present?", "Examples"],
["Simple Syrup", "Concentrated sucrose in purified water only. Used as vehicle/flavoring base.", "No", "Syrup USP, Syrup IP"],
["Flavored/Aromatic Syrup", "Contains aromatic or volatile substances. Used as flavoring vehicle.", "No (flavor only)", "Peppermint Syrup, Orange Syrup, Ginger Syrup, Tolu Syrup"],
["Medicated Syrup", "Contains one or more APIs. Intended for specific therapeutic effects.", "Yes", "Codeine Phosphate Syrup, Paracetamol Syrup, Cough Syrups, Expectorants"],
]
hdr = types_data[0]
rows_ = types_data[1:]
story.append(make_table(hdr, rows_, [3.2*cm, 6*cm, 2.8*cm, 5*cm]))
story.append(Spacer(1, 10))
story.append(section_bar("3.2 Classification by Sugar Content"))
story.append(Paragraph("<b>Sugar-Based Syrups</b>", sub_heading))
for pt in [
"Use sucrose as the primary sweetener.",
"High osmotic pressure provides inherent self-preserving properties.",
"Standard syrups (Syrup USP/IP) fall into this category.",
"Self-preserving when sucrose concentration ≥ 65% w/w.",
]:
story.append(Paragraph(f"• {pt}", bullet_style))
story.append(Spacer(1, 6))
story.append(Paragraph("<b>Sugar-Free Syrups (Sorbitol / Artificial Sweetener Based)</b>", sub_heading))
sf_adv = ["Suitable for diabetic patients.", "Lower caloric content.", "Reduced risk of dental caries."]
sf_dis = ["May cause osmotic diarrhea in large doses (sorbitol).", "Less inherent preservative effect.", "Require additional antimicrobial preservatives.", "Some sweeteners (aspartame) are heat-labile."]
sf_data = [
[Paragraph("<b>Advantages</b>", S("h", fontSize=10, fontName="Helvetica-Bold", textColor=WHITE)),
Paragraph("<b>Disadvantages</b>", S("h2", fontSize=10, fontName="Helvetica-Bold", textColor=WHITE))],
["\n".join(f"• {a}" for a in sf_adv), "\n".join(f"• {d}" for d in sf_dis)]
]
sf_para = [
[Paragraph("<b>Advantages</b>", S("h", fontSize=10, fontName="Helvetica-Bold", textColor=WHITE)),
Paragraph("<b>Disadvantages</b>", S("h2", fontSize=10, fontName="Helvetica-Bold", textColor=WHITE))],
[Paragraph("\n".join(f"• {a}" for a in sf_adv), S("bc", fontSize=9.5, leading=15, fontName="Helvetica", textColor=DARK_GRAY)),
Paragraph("\n".join(f"• {d}" for d in sf_dis), S("bd", fontSize=9.5, leading=15, fontName="Helvetica", textColor=DARK_GRAY))],
]
sf_t = Table(sf_para, colWidths=[8.2*cm, 8.2*cm])
sf_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), GREEN_BOX),
("BACKGROUND", (1,0),(1,0), RED_BOX),
("BACKGROUND", (0,1),(-1,-1), LIGHT_GRAY),
("GRID", (0,0),(-1,-1), 0.5, HexColor("#B0C0D0")),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING", (0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 9),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
story.append(sf_t)
story.append(Spacer(1, 10))
story.append(PageBreak())
# ─ Chapter 4: Methods ────────────────────────────────────────────────────
story.append(chapter_banner("Chapter 4: Methods of Preparation"))
story.append(Spacer(1, 8))
story.append(Paragraph(
"Syrups are prepared by one of <b>four methods</b>, selected based on the physical and chemical "
"properties of the ingredients:",
body))
story.append(Spacer(1, 8))
methods = [
{
"num": "Method 1",
"title": "Solution with Heat (Hot Process)",
"color": MED_BLUE,
"used_when": [
"Quick preparation is required.",
"Ingredients are thermostable and non-volatile.",
"Removal of unwanted microorganisms is desirable.",
"Clarification of protein-containing materials by coagulation/filtration is needed.",
],
"steps": [
"Heat purified water in a suitable vessel.",
"Add sucrose and stir until completely dissolved.",
"Add thermostable ingredients and heat briefly (~100°C).",
"Cool the syrup, then filter if necessary.",
"Add volatile/heat-sensitive additives AFTER cooling.",
"Adjust final volume with purified water.",
],
"examples": "Simple Syrup USP/IP, Tolu Syrup NF, Cocoa Syrup NF",
"caution": "Excessive heat causes CARAMELIZATION (darkening/decomposition of sucrose). Temperature must be carefully controlled.",
},
{
"num": "Method 2",
"title": "Agitation Without Heat (Cold Process)",
"color": ACCENT_TEAL,
"used_when": [
"Ingredients are thermolabile (heat-sensitive).",
"Ingredients are volatile.",
"Maximum stability is desired — syrups by this method have the HIGHEST stability.",
],
"steps": [
"Place sucrose in a vessel with purified water at room temperature.",
"Agitate (shake or stir) until sucrose fully dissolves.",
"Add the API and other excipients.",
"Mix thoroughly, filter, and adjust to final volume.",
],
"examples": "Ephedrine Sulphate Syrup, Codeine Phosphate Syrup",
"caution": "Time-consuming compared to the heat method.",
},
{
"num": "Method 3",
"title": "Addition of Sucrose to a Medicated/Flavored Liquid",
"color": HexColor("#5A3E8A"),
"used_when": [
"Medicinal extracts (tinctures, fluidextracts) are to be incorporated into a syrup.",
"The medicating substance is already in liquid form.",
],
"steps": [
"Prepare the medicated liquid (extract, tincture, etc.) separately.",
"Dissolve sucrose directly in the medicated liquid.",
"Apply heat only if the drug permits; otherwise use cold agitation.",
"Adjust volume and filter.",
],
"examples": "Syrups prepared from fluidextracts or tinctures",
"caution": "Compatibility of sucrose with the medicated liquid must be verified.",
},
{
"num": "Method 4",
"title": "Percolation (Extraction) Method",
"color": HexColor("#B84800"),
"used_when": [
"Sucrose is to be percolated with purified water or a medicated liquid as a menstruum.",
"Extracting active constituents from crude drug materials while simultaneously forming a syrup.",
],
"steps": [
"Pack the medicating substance in a percolator.",
"Percolate purified water slowly through the drug material.",
"Collect the percolate and add sucrose; dissolve.",
"Filter and adjust volume.",
],
"examples": "Tolu Syrup, Squill Syrup",
"caution": "Rate of percolation must be controlled to ensure adequate extraction.",
},
]
for m in methods:
hdr_s = S("MH", fontSize=11, leading=15, fontName="Helvetica-Bold", textColor=WHITE)
body_s = S("MB", fontSize=9.5, leading=14, fontName="Helvetica", textColor=DARK_GRAY)
ex_s = S("ME", fontSize=9.5, leading=14, fontName="Helvetica-Bold", textColor=DARK_BLUE)
caut_s = S("MC", fontSize=9.5, leading=14, fontName="Helvetica-Oblique", textColor=HexColor("#8B0000"))
used_text = "<br/>".join(f"• {u}" for u in m["used_when"])
steps_text = "<br/>".join(f"{i+1}. {s}" for i,s in enumerate(m["steps"]))
block = Table([
[Paragraph(f"{m['num']}: {m['title']}", hdr_s)],
[Paragraph(f"<b>When to Use:</b><br/>{used_text}", body_s)],
[Paragraph(f"<b>Procedure:</b><br/>{steps_text}", body_s)],
[Paragraph(f"<b>Examples:</b> {m['examples']}", ex_s)],
[Paragraph(f"⚠ Caution: {m['caution']}", caut_s)],
], colWidths=[16.5*cm])
block.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), m["color"]),
("BACKGROUND", (0,1),(-1,-1), LIGHT_GRAY),
("BOX", (0,0),(-1,-1), 1, m["color"]),
("LINEABOVE", (0,1),(0,1), 0, m["color"]),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING", (0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
story.append(KeepTogether([block, Spacer(1, 8)]))
# Methods comparison table
story.append(section_bar("4.1 Methods Comparison Table"))
comp_h = ["Method", "Suitable For", "Speed", "Stability", "Example"]
comp_r = [
["Heat", "Thermostable, non-volatile APIs", "Fast", "Moderate", "Simple Syrup"],
["Cold Agitation", "Thermolabile, volatile APIs", "Slow", "Highest", "Ephedrine Syrup"],
["Addition to Medicated Liquid", "Liquid extracts/tinctures", "Moderate", "Moderate", "Tincture-based Syrups"],
["Percolation", "Crude drug extraction", "Slow", "Moderate", "Tolu Syrup"],
]
story.append(make_table(comp_h, comp_r, [3.5*cm, 5.5*cm, 2.2*cm, 2.2*cm, 3.6*cm]))
story.append(Spacer(1, 10))
story.append(PageBreak())
# ─ Chapter 5: Advantages ─────────────────────────────────────────────────
story.append(chapter_banner("Chapter 5: Advantages of Syrups"))
story.append(Spacer(1, 8))
adv_items = [
("Palatability", "Sweet taste masks bitterness of APIs — improves patient compliance, especially in pediatrics and geriatrics."),
("Flexible Dosing", "Liquid form allows precise dose adjustment; critical for pediatric and geriatric patients with variable dose requirements."),
("Ease of Swallowing", "Ideal for patients unable to swallow tablets or capsules (elderly, young children, post-operative patients)."),
("Antioxidant Protection", "Sucrose hydrolyzes to laevulose (fructose) and dextrose (glucose) — both are reducing sugars that RETARD oxidative degradation of APIs."),
("Inherent Preservation", "High osmotic pressure at ≥ 65% w/w sucrose inhibits microbial growth and reproduction without added preservatives."),
("Broad API Compatibility", "Accommodates APIs incompatible with solid dosage forms due to physical/chemical properties."),
("Versatility", "Can be formulated as simple vehicles, flavoring bases, or complex medicated dosage forms."),
]
adv_rows = [[Paragraph(f"<b>{t}</b>", S("at", fontSize=10, fontName="Helvetica-Bold", textColor=DARK_BLUE)),
Paragraph(d, S("ad", fontSize=10, leading=14, fontName="Helvetica", textColor=DARK_GRAY))]
for t, d in adv_items]
adv_t = Table(adv_rows, colWidths=[4.5*cm, 12*cm])
adv_t.setStyle(TableStyle([
("ROWBACKGROUNDS", (0,0),(-1,-1), [LIGHT_TEAL, WHITE]),
("GRID", (0,0),(-1,-1), 0.3, HexColor("#99BBCC")),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 9),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
story.append(adv_t)
story.append(Spacer(1, 10))
# ─ Chapter 6: Stability ──────────────────────────────────────────────────
story.append(chapter_banner("Chapter 6: Stability Problems & Solutions"))
story.append(Spacer(1, 8))
stability_items = [
{
"problem": "1. Microbial Contamination / Growth",
"cause": [
"Sucrose concentration below self-preserving threshold (< 65% w/w).",
"Contaminated equipment or water during preparation.",
"Repeated opening of containers; dilution during use.",
],
"consequence": "Growth of yeasts, molds, and bacteria; syrup spoilage; patient safety risk.",
"solution": [
"Maintain sucrose ≥ 65% w/w (self-preserving).",
"Add antimicrobial preservatives: sodium benzoate, parabens, benzoic acid, sorbic acid.",
"Use 18% alcohol to preserve free water not protected by sucrose.",
"Leverage additive preservative effects of glycerin and propylene glycol.",
"Prepare under clean/aseptic conditions; use tightly sealed containers.",
],
},
{
"problem": "2. Sucrose Inversion (Acid Hydrolysis)",
"cause": [
"Acidic pH (from acidic APIs, buffers, or CO2 absorption).",
"Elevated temperature during preparation or storage.",
"Enzyme invertase from yeast contamination.",
],
"consequence": "Invert sugar formed (glucose + fructose). Lowers pH further (autocatalytic). Alters viscosity, color (browning), and osmotic pressure, thereby reducing preservation.",
"solution": [
"Avoid excessive heating during preparation.",
"Maintain neutral to slightly alkaline pH where possible.",
"Prevent microbial (yeast) contamination — yeast secretes invertase.",
"Store in cool conditions.",
],
},
{
"problem": "3. Crystallization (Graining / Salting Out)",
"cause": [
"Storage at low temperatures causing sucrose to crystallize.",
"Evaporation of water, concentrating the solution beyond solubility.",
"Salting-out effect: syrups have lower solvent power than water; added solutes can reduce sucrose solubility.",
],
"consequence": "Crystal deposits in the bottle; non-uniform dosing; reduced palatability.",
"solution": [
"USP Syrup uses 450 mL water (slightly more than the 425 mL needed) to prevent crystallization at low temperatures.",
"Add 0.1% tartaric acid to induce partial inversion (invert sugar is more soluble).",
"Add polyols (glycerin, sorbitol) to prevent crystallization.",
"Store at controlled room temperature — avoid freezing.",
],
},
{
"problem": "4. Chemical Instability / API Degradation",
"cause": [
"Hydrolysis in the aqueous environment.",
"Oxidation by dissolved oxygen.",
"Photodegradation by UV/visible light.",
"pH changes (from inversion or CO2 absorption) degrading pH-sensitive APIs.",
"Incompatibilities with excipients or preservatives.",
],
"consequence": "Loss of potency; formation of toxic degradation products; color changes.",
"solution": [
"Buffer pH to the optimal stability range for the specific API.",
"Add antioxidants: sodium metabisulfite, ascorbic acid, BHA/BHT.",
"Package in amber/light-resistant bottles.",
"Add chelating agents (EDTA) to sequester trace metals catalyzing oxidation.",
"Select compatible preservatives; verify API-excipient compatibility.",
],
},
{
"problem": "5. Caramelization",
"cause": [
"Excessive heating during hot-process preparation.",
"Prolonged exposure to high temperatures.",
],
"consequence": "Sucrose decomposes; syrup darkens and develops a bitter, burnt taste.",
"solution": [
"Carefully control temperature — heat only until sucrose dissolves, then cool rapidly.",
"Avoid overheating; use minimum necessary temperature.",
],
},
{
"problem": "6. Physical Instability (Sedimentation / Suspension Settling)",
"cause": [
"APIs not fully dissolved form particles that settle under gravity.",
"Density difference between dispersed particles and syrup vehicle.",
],
"consequence": "Non-uniform dose distribution; risk of under- or over-dosing.",
"solution": [
"Add suspending agents: xanthan gum, CMC, sodium alginate, bentonite.",
"Add viscosity enhancers to slow sedimentation.",
'Label "Shake Well Before Use."',
],
},
{
"problem": "7. Changes in Color, Odor & Taste (Organoleptic Deterioration)",
"cause": [
"Oxidative reactions (browning of APIs).",
"Microbial growth producing off-odors and gas.",
"Chemical degradation of colorants or flavorants.",
],
"consequence": "Signs of spoilage: discoloration, turbidity, rancid odor, gas production, precipitation.",
"solution": [
"Use antioxidants and preservatives.",
"Store in cool, dark, tightly sealed containers.",
"Monitor shelf life and respect expiry dates.",
],
},
]
for item in stability_items:
p_s = S("SP", fontSize=10.5, leading=15, fontName="Helvetica-Bold", textColor=WHITE)
ca_s = S("CA", fontSize=9.5, leading=14, fontName="Helvetica", textColor=DARK_GRAY)
con_s = S("CO", fontSize=9.5, leading=14, fontName="Helvetica-Oblique", textColor=HexColor("#8B0000"))
sol_s = S("SO", fontSize=9.5, leading=14, fontName="Helvetica", textColor=HexColor("#1A5C2A"))
causes_txt = "<br/>".join(f"• {c}" for c in item["cause"])
sol_txt = "<br/>".join(f"✔ {s}" for s in item["solution"])
inner_rows = [
[Paragraph(item["problem"], p_s)],
[Paragraph(f"<b>Causes:</b><br/>{causes_txt}", ca_s)],
[Paragraph(f"<b>Consequence:</b> {item['consequence']}", con_s)],
[Paragraph(f"<b>Solutions:</b><br/>{sol_txt}", sol_s)],
]
inner_t = Table(inner_rows, colWidths=[16.5*cm])
inner_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), RED_BOX),
("BACKGROUND", (0,1),(-1,-1), HexColor("#FDF6F6")),
("BOX", (0,0),(-1,-1), 1, HexColor("#D0A0A0")),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING", (0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
story.append(KeepTogether([inner_t, Spacer(1, 8)]))
story.append(PageBreak())
# ─ Chapter 7: Preservation ───────────────────────────────────────────────
story.append(chapter_banner("Chapter 7: Preservation of Syrups"))
story.append(Spacer(1, 8))
story.append(section_bar("7.1 Self-Preservation by High Sucrose Concentration"))
story.append(Paragraph(
"Syrup USP (65% w/w) is protected from bacterial contamination by its <b>high osmotic pressure</b>. "
"This is the <b>minimum sucrose concentration</b> required to achieve self-preservation. "
"More dilute syrups do NOT self-preserve and require added preservatives.",
body))
story.append(Spacer(1, 8))
story.append(section_bar("7.2 Free Water Concept & Preservation Calculations"))
story.append(Paragraph(
"The concept of <b>free water</b> is central to syrup preservation. Only the water NOT "
"protected by sucrose (or other solutes) is available for microbial growth and must be preserved.",
body))
story.append(Spacer(1, 6))
fw_data = [
["Parameter", "Value", "Notes"],
["Sucrose apparent volume per gram", "0.647 mL/g", "550 mL occupied by 850 g sucrose"],
["Water preserved per gram sucrose", "0.53 mL/g", "450 mL preserved by 850 g sucrose"],
["Alcohol required to preserve free water", "18% v/v", "18 mL alcohol preserves 100 mL free water"],
["Glycerin preserving equivalence", "Similar to sucrose", "Preserves equal volume of free water"],
["Propylene glycol", "Equivalent to ethanol", "Used in preservation calculations"],
]
story.append(make_table(fw_data[0], fw_data[1:], [5.5*cm, 4*cm, 7*cm]))
story.append(Spacer(1, 8))
story.append(colored_box(
"<b>Example Calculation:</b> How much Alcohol USP is required to preserve 1 L of syrup "
"containing 500 g sucrose?<br/><br/>"
"Step 1: Volume occupied by sucrose = 500 × 0.647 = 323.5 mL<br/>"
"Step 2: Water preserved by sucrose = 500 × 0.53 = 265 mL<br/>"
"Step 3: Free water = 1000 - 323.5 - 265 = 411.5 mL (approx.)<br/>"
"Step 4: Alcohol needed = 411.5 × 0.18 = 74 mL Alcohol USP",
note_style, LIGHT_GOLD, ACCENT_GOLD))
story.append(Spacer(1, 8))
story.append(section_bar("7.3 Common Preservatives & Their Use"))
pres_h = ["Preservative", "Effective Against", "Typical Conc.", "Notes"]
pres_r = [
["Sodium Benzoate", "Bacteria, yeast, molds", "0.1–0.2%", "Most effective at pH < 4.5"],
["Benzoic Acid", "Bacteria, yeast", "0.1–0.3%", "Largely un-ionized at low pH"],
["Methyl Paraben", "Bacteria, molds", "0.1–0.18%", "Often combined with propyl paraben"],
["Propyl Paraben", "Bacteria, molds", "0.01–0.02%", "Synergistic with methyl paraben"],
["Sorbic Acid", "Yeast, molds", "0.05–0.2%", "Effective at pH < 6"],
["Alcohol (Ethanol)", "Bacteria, fungi", "15–20%", "18% preserves free water; imparts flavor"],
["Glycerin", "Weak antimicrobial", "> 20%", "Additive effect; also humectant"],
["Propylene Glycol", "Bacteria, molds, yeast", "10–25%", "Additive preservative effect"],
]
story.append(make_table(pres_h, pres_r, [3.5*cm, 4*cm, 3*cm, 6*cm]))
story.append(Spacer(1, 10))
# ─ Chapter 8: Storage ────────────────────────────────────────────────────
story.append(chapter_banner("Chapter 8: Storage & Packaging"))
story.append(Spacer(1, 8))
storage_points = [
("Container", "Tightly closed amber/opaque glass or plastic bottles — protects from light and prevents evaporation."),
("Temperature", "Controlled room temperature (15–30°C). Avoid extremes of heat or cold."),
("Refrigeration", "Avoid refrigerating syrups prone to crystallization. Some syrups require refrigeration per label."),
("Labeling", '"Shake Well Before Use" for suspensions. Include expiry date, storage conditions, and dosing instructions.'),
("Deterioration Signs", "Reject if rancidity, unusual odor, gas production, turbidity, discoloration, or visible precipitation is noted."),
("Freshly Prepared", "Simple syrups should be freshly prepared (extemporaneous) unless they contain appropriate antimicrobial preservatives."),
("Filling", "Fill containers to minimize headspace (air/oxygen exposure) to reduce oxidative degradation."),
]
stor_rows = [[Paragraph(f"<b>{t}</b>", S("st", fontSize=10, fontName="Helvetica-Bold", textColor=DARK_BLUE)),
Paragraph(d, S("sd", fontSize=10, leading=14, fontName="Helvetica", textColor=DARK_GRAY))]
for t, d in storage_points]
stor_t = Table(stor_rows, colWidths=[3.5*cm, 13*cm])
stor_t.setStyle(TableStyle([
("ROWBACKGROUNDS", (0,0),(-1,-1), [LIGHT_GOLD, WHITE]),
("GRID", (0,0),(-1,-1), 0.3, HexColor("#D0B080")),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 9),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
story.append(stor_t)
story.append(Spacer(1, 10))
story.append(PageBreak())
# ─ Chapter 9: Summary Tables ─────────────────────────────────────────────
story.append(chapter_banner("Chapter 9: Quick-Reference Summary Tables"))
story.append(Spacer(1, 8))
story.append(section_bar("9.1 Master Summary: Everything About Syrups"))
summ_h = ["Aspect", "Key Points"]
summ_r = [
["Definition", "Concentrated aqueous sugar solution ± API for oral use"],
["Sucrose conc. (USP)", "85% w/v (65% w/w); Specific gravity 1.313"],
["Sucrose conc. (IP)", "66.67% w/w"],
["Types", "Simple | Flavored/Aromatic | Medicated | Sugar-Free"],
["Methods", "Heat | Cold Agitation | Addition to Medicated Liquid | Percolation"],
["Best stability method", "Cold Agitation (no heat)"],
["Self-preserving threshold", "≥ 65% w/w sucrose"],
["Free water preservation", "18% alcohol preserves free water"],
["Main stability issues", "Microbial growth | Inversion | Crystallization | API degradation | Caramelization | Sedimentation | Organoleptic changes"],
["Common preservatives", "Sodium benzoate, parabens, alcohol, sorbic acid"],
["Antioxidants used", "Sodium metabisulfite, ascorbic acid, BHA/BHT"],
["Chelating agents", "EDTA (removes trace metals)"],
["Storage", "Amber bottles, tightly closed, controlled room temperature"],
]
story.append(make_table(summ_h, summ_r, [5.5*cm, 11*cm]))
story.append(Spacer(1, 10))
story.append(section_bar("9.2 Examples of Official/Common Syrups"))
ex_h = ["Syrup Name", "Type", "Key Ingredient(s)", "Method", "Use"]
ex_r = [
["Syrup USP / Syrup IP", "Simple", "Sucrose 85% w/v", "Heat", "Vehicle/Sweetener"],
["Tolu Syrup NF", "Flavored", "Tolu Balsam", "Heat / Percolation", "Flavoring vehicle"],
["Peppermint Syrup", "Flavored/Aromatic", "Peppermint oil", "Cold Agitation", "Flavoring vehicle"],
["Squill Syrup", "Medicated", "Squill (crude drug)", "Percolation", "Expectorant"],
["Cocoa Syrup NF", "Flavored", "Cocoa powder, sucrose", "Heat", "Flavoring vehicle"],
["Codeine Phosphate Syrup", "Medicated", "Codeine phosphate", "Cold Agitation", "Antitussive"],
["Ephedrine Sulphate Syrup", "Medicated", "Ephedrine sulphate", "Cold Agitation", "Bronchodilator"],
["Paracetamol Oral Syrup", "Medicated", "Paracetamol 120 mg/5 mL", "Cold Agitation", "Antipyretic/Analgesic"],
["Dextromethorphan Syrup", "Medicated", "Dextromethorphan HBr", "Cold Agitation", "Antitussive"],
]
story.append(make_table(ex_h, ex_r, [3.8*cm, 2.8*cm, 3.8*cm, 3*cm, 3.1*cm]))
story.append(Spacer(1, 10))
story.append(PageBreak())
# ─ Chapter 10: Practice Q&A ──────────────────────────────────────────────
story.append(chapter_banner("Chapter 10: Practice Q & A"))
story.append(Spacer(1, 10))
qa_style = S("QS", fontSize=10.5, leading=15, fontName="Helvetica-Bold", textColor=DARK_BLUE)
ans_style = S("AS", fontSize=10, leading=14, fontName="Helvetica", textColor=DARK_GRAY, leftIndent=10)
qa_pairs = [
("Q1. Define a syrup according to USP standards.",
"A syrup is a concentrated aqueous solution containing 85% w/v (65% w/w) sucrose in purified water, with or without flavoring/medicinal substances, intended for oral use."),
("Q2. What is the minimum sucrose concentration for a self-preserving syrup?",
"≥ 65% w/w sucrose. Below this threshold, the osmotic pressure is insufficient to inhibit microbial growth and additional preservatives must be added."),
("Q3. Which method of syrup preparation gives maximum stability and why?",
"Agitation without heat (Cold Process), because it avoids thermal degradation of heat-sensitive/volatile APIs and minimizes chemical changes (inversion, caramelization) from elevated temperatures."),
("Q4. What is sucrose inversion and why is it problematic?",
"Acid-catalyzed or enzyme-catalyzed hydrolysis of sucrose into glucose and fructose (invert sugar). It lowers pH further (autocatalytic), reduces osmotic pressure and thus preservation, and can alter color and consistency."),
("Q5. Name four common antimicrobial preservatives used in syrups.",
"1. Sodium benzoate (0.1-0.2%) 2. Methyl paraben (0.1-0.18%) 3. Propyl paraben (0.01-0.02%) 4. Ethanol/Alcohol USP (15-20%) [Also: Sorbic acid, Benzoic acid]"),
("Q6. Why does Syrup USP use 450 mL of water instead of the minimum 425 mL to dissolve 850 g sucrose?",
"The slight excess of water (25 mL extra) prevents crystallization during cold storage. If exactly 425 mL were used, the syrup would be at the saturation threshold and temperature drops could cause sucrose to crystallize out."),
("Q7. What is caramelization in syrups, and how is it prevented?",
"Caramelization is the thermal decomposition of sucrose at elevated temperatures during the heat method, causing darkening and bitter taste. It is prevented by carefully controlling temperature — heating only until sucrose dissolves, then cooling rapidly."),
("Q8. Give two examples each of medicated and flavored syrups.",
"Medicated: Codeine Phosphate Syrup, Ephedrine Sulphate Syrup. Flavored: Tolu Syrup NF, Peppermint Syrup."),
("Q9. What is 'free water' in the context of syrup preservation?",
"Free water is the volume of water in a syrup that is NOT protected by sucrose (or other solutes). Only free water supports microbial growth. It is calculated by subtracting the volume occupied by and preserved by sucrose from total volume. 18% alcohol is required to preserve each 100 mL of free water."),
("Q10. List three signs that a syrup has deteriorated.",
"1. Rancid or unusual odor 2. Gas production (effervescence) 3. Turbidity, discoloration, or visible precipitation. Others: change in taste, mold growth."),
]
for q, a in qa_pairs:
block = Table([
[Paragraph(q, qa_style)],
[Paragraph(a, ans_style)],
], colWidths=[16.5*cm])
block.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), LIGHT_BLUE),
("BACKGROUND", (0,1),(0,-1), WHITE),
("BOX", (0,0),(-1,-1), 0.8, MED_BLUE),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING", (0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 11),
("RIGHTPADDING", (0,0),(-1,-1), 11),
]))
story.append(KeepTogether([block, Spacer(1, 6)]))
return story
# ── Build Document ────────────────────────────────────────────────────────────
def build_doc():
doc = SimpleDocTemplate(
OUTPUT_PATH,
pagesize=A4,
leftMargin=2*cm, rightMargin=2*cm,
topMargin=2*cm, bottomMargin=2.2*cm,
title="Pharmaceutical Syrups - Comprehensive Study Guide",
author="Pharmacy Study Guide",
subject="Pharmaceutics - Syrups",
)
story = build_cover() + build_content()
doc.build(story, onFirstPage=add_page_number, onLaterPages=add_page_number)
print(f"PDF created: {OUTPUT_PATH}")
if __name__ == "__main__":
build_doc()
cd /home/daytona/workspace/syrups-study-guide && python generate_pdf.py 2>&1
ls -lh /home/daytona/workspace/syrups-study-guide/Syrups_Study_Guide.pdf
Syrups Study Guide
PDF Document · PDF
| Chapter | Content |
|---|---|
| 1 | Definition & Pharmacopoeial Standards (USP vs IP comparison table) |
| 2 | Composition - all 11 formulatory ingredients with roles and examples |
| 3 | Classification - Simple, Flavored, Medicated, Sugar-Free (with pros/cons table) |
| 4 | All 4 Methods of Preparation with step-by-step procedures, cautions, and a comparison table |
| 5 | 7 Advantages of syrups |
| 6 | 7 Stability Problems - each with causes, consequences, and solutions in color-coded blocks |
| 7 | Preservation - free water concept, calculation example, 8 preservatives with concentrations |
| 8 | Storage & Packaging guidelines |
| 9 | Quick-reference summary tables + 9 official syrup examples |
| 10 | 10 Practice Q&A pairs for exam preparation |
what does IP means
| Abbreviation | Full Name | Country/Region |
|---|---|---|
| IP | Indian Pharmacopoeia | India |
| USP | United States Pharmacopeia | USA |
| BP | British Pharmacopoeia | UK |
| EP | European Pharmacopoeia | Europe |
| JP | Japanese Pharmacopoeia | Japan |
| NF | National Formulary | USA (part of USP) |
why would you compare USP to IP only? generally we compare USP to BP
| Parameter | USP (USA) | BP (UK) |
|---|---|---|
| Sucrose in Syrup | 85% w/v (65% w/w) | ~66.7% w/w |
| Concentration expression | Often w/v | Often w/w |
| Preservative limits | USP <1> chapter | BP Appendix |
| Monograph style | Performance-based | More prescriptive |
| Adopted by | USA, many others | UK, Commonwealth nations, India (basis for IP) |
so it does not effect any data
do the same with aromaric waters as syrups
aromatic waters pharmaceutical definition types methods of preparation stability problems pharmacy
http://www.bspublications.net/downloads/04fc75de986c12_Pharm…
https://lecture-notes.tiu.edu.iq/wp-content/uploads/2022/11/…
~/syrups-study-guide/generate_aromatic_waters_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.lib.colors import HexColor
OUTPUT_PATH = "/home/daytona/workspace/syrups-study-guide/Aromatic_Waters_Study_Guide.pdf"
# ── Colour Palette ──────────────────────────────────────────────────────────
DARK_GREEN = HexColor("#1A4A2E")
MED_GREEN = HexColor("#2E7D52")
LIGHT_GREEN = HexColor("#D4EFE1")
ACCENT_AMBER = HexColor("#D97706")
LIGHT_AMBER = HexColor("#FEF3C7")
ACCENT_TEAL = HexColor("#0E6B6B")
LIGHT_TEAL = HexColor("#CCECEC")
WHITE = colors.white
LIGHT_GRAY = HexColor("#F4F6F8")
MED_GRAY = HexColor("#7A8A99")
DARK_GRAY = HexColor("#2D2D2D")
TABLE_HEADER = HexColor("#1A4A2E")
TABLE_ODD = HexColor("#EBF5EE")
TABLE_EVEN = WHITE
RED_BOX = HexColor("#C0392B")
BLUE_BOX = HexColor("#1A3A6E")
# ── Styles ────────────────────────────────────────────────────────────────────
def S(name, **kw):
return ParagraphStyle(name, **kw)
cover_title = S("CT", fontSize=34, leading=42, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER)
cover_sub = S("CS", fontSize=16, leading=22, textColor=HexColor("#BBDDC8"),
fontName="Helvetica", alignment=TA_CENTER)
cover_info = S("CI", fontSize=11, leading=16, textColor=HexColor("#99CCA8"),
fontName="Helvetica", alignment=TA_CENTER)
chapter_title = S("ChT", fontSize=18, leading=24, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_LEFT)
body = S("Body", fontSize=10, leading=15, textColor=DARK_GRAY,
fontName="Helvetica", spaceBefore=3, spaceAfter=3, alignment=TA_JUSTIFY)
bullet_s = S("Bul", fontSize=10, leading=14, textColor=DARK_GRAY,
fontName="Helvetica", leftIndent=16, spaceBefore=2, spaceAfter=2)
note_s = S("Note", fontSize=9.5, leading=14, textColor=HexColor("#1A4020"),
fontName="Helvetica-Oblique", leftIndent=10, rightIndent=10)
sub_h = S("SubH", fontSize=11, leading=15, textColor=ACCENT_TEAL,
fontName="Helvetica-Bold", spaceBefore=8, spaceAfter=3)
qa_q = S("QQ", fontSize=10.5, leading=15, fontName="Helvetica-Bold",
textColor=DARK_GREEN)
qa_a = S("QA", fontSize=10, leading=14, fontName="Helvetica",
textColor=DARK_GRAY, leftIndent=10)
# ── Helpers ───────────────────────────────────────────────────────────────────
def chapter_banner(text):
t = Table([[Paragraph(text, chapter_title)]], colWidths=[17*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), DARK_GREEN),
("ROUNDEDCORNERS",[6]),
("TOPPADDING", (0,0),(-1,-1), 10),
("BOTTOMPADDING",(0,0),(-1,-1), 10),
("LEFTPADDING", (0,0),(-1,-1), 14),
("RIGHTPADDING", (0,0),(-1,-1), 14),
]))
return t
def section_bar(text):
s = S("SB", fontSize=13, leading=18, textColor=DARK_GREEN,
fontName="Helvetica-Bold", spaceBefore=0, spaceAfter=0)
t = Table([[Paragraph(text, s)]], colWidths=[16.5*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), LIGHT_GREEN),
("LINEBEFOREEACH",(0,0),(0,-1), 4, MED_GREEN),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING",(0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
return t
def colored_box(text, bg, border):
t = Table([[Paragraph(text, note_s)]], colWidths=[16.5*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), bg),
("BOX", (0,0),(-1,-1), 1, border),
("TOPPADDING", (0,0),(-1,-1), 8),
("BOTTOMPADDING",(0,0),(-1,-1), 8),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
return t
def make_table(headers, rows, col_widths):
hdr_s = S("H", fontSize=10, leading=14, fontName="Helvetica-Bold",
textColor=WHITE, alignment=TA_CENTER)
cell_s = S("C", fontSize=9.5, leading=13, fontName="Helvetica", textColor=DARK_GRAY)
data = [[Paragraph(str(h), hdr_s) for h in headers]]
for row in rows:
data.append([Paragraph(str(c), cell_s) for c in row])
t = Table(data, colWidths=col_widths)
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), TABLE_HEADER),
("ROWBACKGROUNDS",(0,1),(-1,-1), [TABLE_ODD, TABLE_EVEN]),
("GRID", (0,0),(-1,-1), 0.4, HexColor("#90BCA0")),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 7),
("RIGHTPADDING", (0,0),(-1,-1), 7),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]))
return t
def add_page_number(canvas, doc):
canvas.saveState()
canvas.setFillColor(DARK_GREEN)
canvas.rect(0, 0, A4[0], 22, fill=1, stroke=0)
canvas.setFillColor(WHITE)
canvas.setFont("Helvetica", 8)
canvas.drawString(2*cm, 7, "Pharmaceutical Aromatic Waters - Comprehensive Study Guide")
canvas.drawRightString(A4[0]-2*cm, 7, f"Page {doc.page}")
canvas.restoreState()
# ── Cover ─────────────────────────────────────────────────────────────────────
def build_cover():
story = []
cover_block = Table(
[[Paragraph("PHARMACEUTICAL<br/>AROMATIC WATERS", cover_title)],
[Spacer(1, 6)],
[Paragraph("Comprehensive Study Guide", cover_sub)],
[Spacer(1, 10)],
[Paragraph("Definition | Classification | Preparation | Stability | Storage | Examples", cover_info)]],
colWidths=[17*cm])
cover_block.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), DARK_GREEN),
("TOPPADDING", (0,0),(-1,-1), 28),
("BOTTOMPADDING",(0,0),(-1,-1), 28),
("LEFTPADDING", (0,0),(-1,-1), 20),
("RIGHTPADDING", (0,0),(-1,-1), 20),
]))
story.append(cover_block)
story.append(Spacer(1, 18))
qf_s = S("QF", fontSize=10, leading=14, fontName="Helvetica-Bold",
textColor=DARK_GREEN, alignment=TA_CENTER)
qf_data = [[Paragraph(c, qf_s) for c in [
"BP Definition\nSaturated Aqueous\nSolutions",
"3 Official Methods\nof Preparation",
"2 Main Types\nSimple & Concentrated",
"Not Therapeutically\nPotent — Used as\nVehicles",
]]]
qf_t = Table(qf_data, colWidths=[4.1*cm]*4)
qf_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), LIGHT_AMBER),
("BOX", (0,0),(-1,-1), 1, ACCENT_AMBER),
("INNERGRID", (0,0),(-1,-1), 0.5, ACCENT_AMBER),
("TOPPADDING", (0,0),(-1,-1), 10),
("BOTTOMPADDING",(0,0),(-1,-1), 10),
]))
story.append(qf_t)
story.append(Spacer(1, 18))
toc_h = S("TH", fontSize=13, leading=18, fontName="Helvetica-Bold", textColor=DARK_GREEN)
toc_i = S("TI", fontSize=10, leading=16, fontName="Helvetica", textColor=DARK_GRAY, leftIndent=10)
chapters = [
"1. Definition & Pharmacopoeial Standards",
"2. Composition",
"3. Classification & Types",
"4. Uses & Applications",
"5. Methods of Preparation",
"6. Stability Problems & Solutions",
"7. Storage & Packaging",
"8. Official Examples of Aromatic Waters",
"9. Quick-Reference Summary Tables",
"10. Practice Q & A",
]
toc_rows = [[Paragraph("CONTENTS", toc_h)]] + [[Paragraph(c, toc_i)] for c in chapters]
toc_t = Table(toc_rows, colWidths=[17*cm])
toc_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), LIGHT_GREEN),
("LINEAFTER", (0,0),(0,-1), 3, MED_GREEN),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING",(0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 12),
]))
story.append(toc_t)
story.append(Spacer(1, 14))
cred = S("Cr", fontSize=8.5, leading=12, fontName="Helvetica-Oblique",
textColor=MED_GRAY, alignment=TA_CENTER)
story.append(Paragraph("Prepared for Pharmacy Students | July 2026 | Based on BP/USP/IP Pharmacopoeia Standards", cred))
story.append(PageBreak())
return story
# ── Content ───────────────────────────────────────────────────────────────────
def build_content():
story = []
# ── Chapter 1: Definition ────────────────────────────────────────────────
story.append(chapter_banner("Chapter 1: Definition & Pharmacopoeial Standards"))
story.append(Spacer(1, 10))
story.append(section_bar("1.1 Official Definition"))
story.append(Paragraph(
"Aromatic waters are <b>clear, saturated aqueous solutions of volatile oils or other "
"aromatic or volatile substances</b>, intended primarily for oral use as flavored vehicles "
"and pharmaceutical aids. They represent some of the <b>simplest formulated dosage forms</b>, "
"consisting essentially of only two components: purified water (solvent) and a volatile "
"aromatic substance (solute).",
body))
story.append(Spacer(1, 6))
story.append(colored_box(
"<b>BP Definition:</b> Aromatic waters are clear, saturated aqueous solutions of volatile oils "
"or other aromatic or volatile substances. They are saturated solutions (unless otherwise "
"specified) and are free from solid impurities and from empyreumatic (smoke-like) or "
"foreign odors.",
LIGHT_GREEN, MED_GREEN))
story.append(Spacer(1, 8))
story.append(section_bar("1.2 Key Characteristics"))
chars = [
"Clear solutions — free from solid particles or turbidity.",
"Saturated with the volatile substance — concentration is at its maximum solubility limit.",
"Very LOW concentration of active substance due to the low water-solubility of volatile oils.",
"Possess odor and taste similar to the plant/substance from which they are prepared.",
"NOT therapeutically potent on their own — used mainly as vehicles and flavoring agents.",
"Aqueous in nature — do NOT contain alcohol (simple aromatic waters).",
]
for c in chars:
story.append(Paragraph(f"• {c}", bullet_s))
story.append(Spacer(1, 10))
# ── Chapter 2: Composition ───────────────────────────────────────────────
story.append(chapter_banner("Chapter 2: Composition"))
story.append(Spacer(1, 10))
story.append(section_bar("2.1 Ingredients"))
comp_h = ["Component", "Role", "Examples"]
comp_r = [
["Purified Water", "Primary solvent; saturating medium", "IP/BP/USP Purified Water"],
["Volatile Oil / Aromatic Substance", "Active aromatic solute; imparts odor, taste, flavor", "Peppermint oil, Rose oil, Orange flower oil, Camphor, Chloroform"],
["Dispersing Agent (optional)", "Aids dissolution in solution/alternate solution method", "Purified talc, Pulped filter paper, Siliceous earth, Kaolin"],
["Alcohol (concentrated waters only)", "Solvent for concentrated form; aids dissolution of volatile oil", "Ethanol (Alcohol BP)"],
["Non-ionic Surfactant (alternate method)", "Solubilizer; helps dissolve volatile oil in water", "Tween 80 (Polysorbate 80), Tween 20"],
]
story.append(make_table(comp_h, comp_r, [3.5*cm, 5*cm, 8*cm]))
story.append(Spacer(1, 10))
# ── Chapter 3: Classification ────────────────────────────────────────────
story.append(chapter_banner("Chapter 3: Classification & Types"))
story.append(Spacer(1, 10))
story.append(section_bar("3.1 Two Main Types"))
type_data = [
["Type", "Solvent", "Alcohol Present?", "Dilution Before Use?", "Examples"],
["Simple (Dilute) Aromatic Waters",
"Purified water only",
"No",
"Ready to use",
"Chloroform Water BP, Peppermint Water, Rose Water, Camphor Water"],
["Concentrated Aromatic Waters",
"Alcohol + Water",
"Yes",
"Yes — diluted ~1:39 with purified water",
"Concentrated Peppermint Water BP, Concentrated Caraway Water BPC, Concentrated Cinnamon Water BPC, Concentrated Dill Water BPC, Concentrated Anise Water BPC"],
]
story.append(make_table(type_data[0], type_data[1:], [3.5*cm, 3*cm, 2.8*cm, 3*cm, 5.2*cm]))
story.append(Spacer(1, 8))
story.append(colored_box(
"<b>Key Note on Concentrated Waters:</b> Concentrated aromatic waters contain alcohol as the "
"solvent for the volatile constituent. Before use, they are diluted with purified water "
"(typically 1 part concentrate + 39 parts water = 40 volumes). This gives a preparation "
"equivalent to the simple aromatic water.",
LIGHT_AMBER, ACCENT_AMBER))
story.append(Spacer(1, 10))
story.append(section_bar("3.2 Classification Based on Volatile Substance Source"))
src_types = [
("From Essential Oils", "Prepared from volatile oils of plants.", "Peppermint Water, Spearmint Water, Anise Water, Orange Flower Water"),
("From Isolated Volatile Compounds", "Prepared from pure isolated aromatic chemicals.", "Chloroform Water, Camphor Water"),
("From Fresh Plant Material (Distillation only)", "Can ONLY be prepared by distillation — no other method applicable.", "Rose Water (Strong Rose Water NF), Orange Flower Water NF, Hamamelis Water"),
]
for src_t, src_d, src_e in src_types:
story.append(Paragraph(f"<b>{src_t}</b>", sub_h))
story.append(Paragraph(src_d, body))
story.append(Paragraph(f"Examples: {src_e}", S("ex", fontSize=9.5, leading=13,
fontName="Helvetica-Oblique", textColor=ACCENT_TEAL, leftIndent=10)))
story.append(Spacer(1, 4))
story.append(Spacer(1, 6))
# ── Chapter 4: Uses ──────────────────────────────────────────────────────
story.append(chapter_banner("Chapter 4: Uses & Applications"))
story.append(Spacer(1, 10))
uses_data = [
["Use", "Description", "Example"],
["Flavored Vehicle", "Provide a pleasantly flavored medium for oral drugs where taste-masking is not a major issue", "Peppermint Water as vehicle for oral solutions"],
["Liquid Phase of Emulsions", "Serve as the aqueous continuous phase in oil-in-water emulsions", "Rose Water in cold cream emulsion"],
["Liquid Phase of Suspensions", "Used as aqueous dispersing medium in suspensions", "Camphor Water in ophthalmic suspensions"],
["Carminative / Digestive", "Peppermint and anise aromatic waters used to relieve flatulence", "Peppermint Water (carminative)"],
["Expectorant Preparation", "Chloroform water used in expectorant syrups (dose 5-15 mL)", "Chloroform Water BP"],
["Eye Preparations", "Camphor water for refreshing/soothing eye drops; Hamamelis water for eye irritations", "Camphor eye drops; Hamamelis 12.5% + Naphazoline 0.01%"],
["Astringent / Cosmetic", "Hamamelis water used as astringent in aftershave and cosmetic products", "Witch Hazel Water"],
["Perfumery", "Rose water used as perfume ingredient", "Rose Water"],
["Intermediate Manufacturing", "Used as solvent/vehicle in manufacturing other pharmaceutical dosage forms", "Various preparations"],
]
story.append(make_table(uses_data[0], uses_data[1:], [3.5*cm, 7*cm, 6*cm]))
story.append(Spacer(1, 10))
story.append(PageBreak())
# ── Chapter 5: Methods of Preparation ───────────────────────────────────
story.append(chapter_banner("Chapter 5: Methods of Preparation"))
story.append(Spacer(1, 8))
story.append(Paragraph(
"Aromatic waters may be prepared by <b>three official methods</b> — selected based on the "
"nature of the aromatic substance and practical/economic considerations:",
body))
story.append(Spacer(1, 8))
methods = [
{
"num": "Method 1",
"title": "Distillation Method",
"color": DARK_GREEN,
"desc": "The most traditional method. Used especially for fresh plant materials from which essential oils are extracted simultaneously with preparation.",
"procedure": [
"Place the coarsely ground odoriferous part of the plant (or drug) in a suitable still.",
"Add sufficient purified water.",
"Distill most of the water carefully — avoid charring/scorching of the substance.",
"Excess oil in the distillate rises to the top and is separated.",
"The remaining aqueous phase (saturated with volatile material) is collected.",
"Clarify by filtration if necessary.",
"Repeat distillation (labeled as XX, XXX, XXXX — each X = one distillation) if the volatile content is very low.",
],
"examples": "Strong Rose Water NF, Orange Flower Water NF, Hamamelis Water",
"adv": "Produces highest-quality, most authentic aromatic water.",
"dis": "Slow, expensive, requires special equipment (still). Not practical for all substances.",
"note": "Aromatic waters from fresh plant material (Rose, Orange Flower, Hamamelis) can ONLY be prepared by distillation — no other method is applicable.",
},
{
"num": "Method 2",
"title": "Solution Method (Agitation / Simple Solution)",
"color": MED_GREEN,
"desc": "Simpler, quicker, and more economical than distillation. Suitable for pure volatile oils or isolated aromatic compounds.",
"procedure": [
"Add 2 mL (if liquid) or 2 g (if solid) of the volatile substance to 1000 mL purified water in a suitable container.",
"Shake intermittently for 15 minutes.",
"Add a dispersing agent (purified talc, pulped filter paper, or siliceous earth) — NOT fine talc, as it passes through filter paper.",
"Shake again vigorously for several minutes.",
"Filter through a wetted filter paper. Discard the first portions of the filtrate.",
"Collect the clear filtrate — this is the aromatic water.",
],
"examples": "Peppermint Water, Spearmint Water, Chloroform Water",
"adv": "Simple, quick, economical; no specialized equipment needed.",
"dis": "Dispersing agents (talc) may adsorb some aromatic substance, reducing concentration slightly. Fine talc passes through filter — siliceous earth or pulped filter paper preferred.",
"note": "The dispersing agent acts as a carrier to break the oil into fine particles and aid filtration — it is NOT incorporated into the final product.",
},
{
"num": "Method 3",
"title": "Alternate Solution Method (Dilution of Concentrate)",
"color": ACCENT_TEAL,
"desc": "A modern, convenient method using pre-made concentrated aromatic waters (containing alcohol or surfactant) which are diluted with purified water at point of use.",
"procedure": [
"Prepare the concentrate: dissolve volatile oil in alcohol (or non-ionic surfactant like Tween 80/20) to form a concentrated solution.",
"At time of use: dilute 1 part concentrate with 39 parts purified water (1:39 dilution ratio).",
"Mix thoroughly to produce the final simple aromatic water.",
],
"examples": "Concentrated Peppermint Water BP (diluted 1:39), Concentrated Caraway Water, Concentrated Cinnamon Water",
"adv": "Quick, convenient, no special equipment; concentrate is stable during storage.",
"dis": [
"Aqueous preparations with small amounts of alcohol are prone to oxidative degradation of alcohol — alters flavor and aroma.",
"Surfactant-based concentrates: possess objectionable odor, lower pH than official, foam excessively on agitation, develop disagreeable taste more readily, subject to mold growth.",
"More oil must be dissolved to saturate the aqueous phase to produce the same final concentration.",
],
"note": "Non-ionic surfactants (Tween 80, Tween 20) dissolve larger amounts of water-insoluble material but have the disadvantages listed above.",
},
]
for m in methods:
ps = S("MP", fontSize=11, leading=15, fontName="Helvetica-Bold", textColor=WHITE)
bs = S("MB", fontSize=9.5, leading=14, fontName="Helvetica", textColor=DARK_GRAY)
es = S("ME", fontSize=9.5, leading=14, fontName="Helvetica-Bold", textColor=DARK_GREEN)
adv_s= S("MA", fontSize=9.5, leading=14, fontName="Helvetica", textColor=HexColor("#1A5C1A"))
dis_s= S("MD", fontSize=9.5, leading=14, fontName="Helvetica", textColor=HexColor("#8B0000"))
nt_s = S("MN", fontSize=9.5, leading=14, fontName="Helvetica-Oblique", textColor=HexColor("#444400"))
steps = "<br/>".join(f"{i+1}. {s}" for i,s in enumerate(m["procedure"]))
dis_text = m["dis"] if isinstance(m["dis"], str) else "<br/>".join(f"• {d}" for d in m["dis"])
rows = [
[Paragraph(f"{m['num']}: {m['title']}", ps)],
[Paragraph(m["desc"], bs)],
[Paragraph(f"<b>Procedure:</b><br/>{steps}", bs)],
[Paragraph(f"<b>Examples:</b> {m['examples']}", es)],
[Paragraph(f"<b>Advantage:</b> {m['adv']}", adv_s)],
[Paragraph(f"<b>Disadvantage(s):</b> {dis_text}", dis_s)],
[Paragraph(f"Note: {m['note']}", nt_s)],
]
blk = Table(rows, colWidths=[16.5*cm])
blk.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), m["color"]),
("BACKGROUND", (0,1),(-1,-1), LIGHT_GRAY),
("BOX", (0,0),(-1,-1), 1, m["color"]),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING",(0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
story.append(KeepTogether([blk, Spacer(1, 8)]))
story.append(section_bar("5.1 Methods Comparison Table"))
mc_h = ["Method", "Based On", "Speed", "Cost", "Equipment", "Best For"]
mc_r = [
["Distillation", "Direct plant material steam distillation", "Slow", "High", "Still required", "Fresh plant materials (Rose, Orange Flower, Hamamelis)"],
["Solution (Agitation)", "Volatile oil + dispersing agent in water", "Moderate", "Low", "Simple", "Pure volatile oils & isolated compounds"],
["Dilution of Concentrate", "Pre-made alcoholic or surfactant concentrate", "Fast", "Lowest", "None", "Industrial-scale convenience; point-of-use dilution"],
]
story.append(make_table(mc_h, mc_r, [2.8*cm, 4.5*cm, 1.8*cm, 1.8*cm, 3.2*cm, 4.4*cm]))
story.append(Spacer(1, 10))
story.append(PageBreak())
# ── Chapter 6: Stability ─────────────────────────────────────────────────
story.append(chapter_banner("Chapter 6: Stability Problems & Solutions"))
story.append(Spacer(1, 8))
story.append(Paragraph(
"Aromatic waters are <b>NOT permanently stable preparations</b>. Instability is generally "
"attributed to improper storage and the inherent chemical reactivity of volatile organic compounds.",
body))
story.append(Spacer(1, 6))
stability = [
{
"problem": "1. Volatilization / Loss of Aromatic Substance",
"cause": "Volatile oils and aromatic compounds evaporate readily, especially from open or loosely stoppered containers and at elevated temperatures.",
"consequence": "Loss of odor, taste, and any therapeutic activity. Reduced concentration below saturation.",
"solution": [
"Store in tightly stoppered containers.",
"Keep away from heat — store in a cool place.",
"Fill containers to reduce headspace.",
"Use containers stoppered with purified cotton to allow minimal air access while excluding dust.",
],
},
{
"problem": "2. Oxidative Degradation (Autoxidation)",
"cause": "Volatile oils contain terpenes and other oxidizable compounds. Dissolved atmospheric oxygen triggers autoxidation, catalyzed by light and trace metal ions (Fe³⁺, Cu²⁺).",
"consequence": [
"Formation of peroxides, resins, and other degradation products.",
"Chloroform oxidizes to PHOSGENE (poisonous gas) in the presence of light.",
"Benzaldehyde (bitter almond water) oxidizes to benzoic acid — crystals deposit in the bottle.",
"Terpene oxidation produces off-flavors and unpleasant odors.",
],
"solution": [
"Store in AMBER/light-resistant bottles — especially critical for Chloroform Water.",
"Minimize oxygen in headspace; fill containers as full as possible.",
"Use terpeneless oils (prepared by fractional distillation/extraction) — more stable as oxidizable terpenes are removed.",
"Add antioxidants where appropriate.",
"Store in cool, dark conditions.",
],
},
{
"problem": "3. Microbial Contamination & Mold Growth",
"cause": "Aromatic waters lack any significant preservative system. Very low solute concentration means minimal osmotic pressure. Surfactant-based preparations are especially prone to mold growth.",
"consequence": "Microbial growth causing turbidity, off-odors, and potential patient harm.",
"solution": [
"Prepare using recently boiled purified water.",
"Filter through bacterial-retentive filters under aseptic conditions.",
"Store in sterilized glass containers.",
"Waters prepared aseptically with boiled water and bacterial-retentive filtration can remain stable for up to ONE YEAR.",
"Avoid surfactant-based concentrates when microbial stability is critical.",
],
},
{
"problem": "4. Oil Separation (Turbidity / Phase Separation)",
"cause": "Excess undissolved oil may separate and collect on top of the liquid if preparation or filtration was inadequate.",
"consequence": "The product becomes turbid or shows oily droplets. The first dose dispensed may have excessive oil concentration — imparting a burning taste.",
"solution": [
"Ensure proper filtration with appropriate dispersing agents.",
"Discard the first portions of the filtrate until it runs clear.",
"Use purified siliceous earth or pulped filter paper (NOT fine talc alone).",
"Label: Do not use if turbid.",
],
},
{
"problem": "5. Terpene Instability",
"cause": "Terpenes present in essential oils are chemically unstable. They polymerize, oxidize, and undergo other degradation reactions.",
"consequence": "Formation of resinous deposits, change in odor/taste, reduced quality.",
"solution": [
"Use terpeneless oils (commercially available) — prepared by fractional distillation or solvent extraction to remove terpene fractions.",
"Terpeneless oils are more water-soluble AND more stable.",
"Store away from light and heat.",
],
},
{
"problem": "6. Altered Flavor/Aroma in Concentrated Waters",
"cause": "Small amounts of alcohol in concentrated aromatic waters undergo oxidative degradation, altering flavor and aroma.",
"consequence": "Off-flavors develop; the preparation no longer has its characteristic pleasant taste/smell.",
"solution": [
"Store concentrates in tightly sealed containers, away from light and heat.",
"Use within the recommended shelf life.",
"Consider surfactant-based concentrates where alcohol is undesirable (but see disadvantages above).",
],
},
]
for item in stability:
ps = S("SP", fontSize=10.5, leading=15, fontName="Helvetica-Bold", textColor=WHITE)
cs = S("SC", fontSize=9.5, leading=14, fontName="Helvetica", textColor=DARK_GRAY)
co = S("SO", fontSize=9.5, leading=14, fontName="Helvetica-Oblique", textColor=HexColor("#8B0000"))
sol = S("SS", fontSize=9.5, leading=14, fontName="Helvetica", textColor=HexColor("#1A5C2A"))
cons = item["consequence"] if isinstance(item["consequence"], str) \
else "<br/>".join(f"• {c}" for c in item["consequence"])
sols = "<br/>".join(f"✔ {s}" for s in item["solution"])
blk = Table([
[Paragraph(item["problem"], ps)],
[Paragraph(f"<b>Cause:</b> {item['cause']}", cs)],
[Paragraph(f"<b>Consequence:</b> {cons}", co)],
[Paragraph(f"<b>Solutions:</b><br/>{sols}", sol)],
], colWidths=[16.5*cm])
blk.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), RED_BOX),
("BACKGROUND", (0,1),(-1,-1), HexColor("#FDF6F6")),
("BOX", (0,0),(-1,-1), 1, HexColor("#D0A0A0")),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING",(0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
story.append(KeepTogether([blk, Spacer(1, 8)]))
story.append(PageBreak())
# ── Chapter 7: Storage ───────────────────────────────────────────────────
story.append(chapter_banner("Chapter 7: Storage & Packaging"))
story.append(Spacer(1, 8))
stor = [
("Container Type", "Amber/light-resistant, tightly stoppered glass bottles. Cotton wool stoppers may be used to allow minimal air exchange while excluding dust."),
("Light", "PROTECT FROM SUNLIGHT — mandatory labeling in RED INK due to presence of volatile constituents. Critical for Chloroform Water (oxidizes to toxic phosgene)."),
("Temperature", "Store in a cool place — elevated temperature accelerates volatilization and oxidative degradation."),
("Shelf Life (Aseptic Prep)", "Waters prepared aseptically with recently boiled purified water filtered through bacterial-retentive filters into sterilized glass containers remain stable for up to ONE YEAR."),
("Filling", "Fill containers as full as possible to minimize headspace (reducing oxygen exposure)."),
("Labeling", '"PROTECT FROM SUNLIGHT" in red ink. Include expiry date, storage conditions, and batch details.'),
("Concentrated Waters", "Store concentrates in tightly sealed containers. Dilute at point of use with freshly prepared purified water."),
("Do Not Use If", "Turbid, discolored, has an unusual or burnt odor, or shows oil separation."),
]
stor_rows = [[Paragraph(f"<b>{t}</b>", S("st", fontSize=10, fontName="Helvetica-Bold", textColor=DARK_GREEN)),
Paragraph(d, S("sd", fontSize=10, leading=14, fontName="Helvetica", textColor=DARK_GRAY))]
for t, d in stor]
stor_t = Table(stor_rows, colWidths=[3.5*cm, 13*cm])
stor_t.setStyle(TableStyle([
("ROWBACKGROUNDS", (0,0),(-1,-1), [LIGHT_AMBER, WHITE]),
("GRID", (0,0),(-1,-1), 0.3, HexColor("#D0B060")),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 9),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
story.append(stor_t)
story.append(Spacer(1, 10))
story.append(PageBreak())
# ── Chapter 8: Official Examples ─────────────────────────────────────────
story.append(chapter_banner("Chapter 8: Official Examples of Aromatic Waters"))
story.append(Spacer(1, 8))
examples = [
{
"name": "Chloroform Water BP",
"type": "Simple",
"source": "Chloroform (CHCl₃)",
"composition": "Double-strength: Chloroform 0.5 mL + Purified water q.s. 100 mL\nConcentrated: Chloroform 10 mL + Ethanol q.s. + Purified water q.s.",
"method": "Solution method",
"uses": "Vehicle for oral preparations; expectorant (5-15 mL dose)",
"caution": "PROTECT FROM LIGHT — chloroform oxidizes to poisonous PHOSGENE gas in the presence of light. Store in amber bottles.",
"color": HexColor("#7B1F1F"),
},
{
"name": "Peppermint Water BP",
"type": "Simple / Concentrated",
"source": "Peppermint oil (Mentha piperita)",
"composition": "Peppermint oil 0.2 mL in 1000 mL purified water (simple); Concentrated: 40× strength in alcohol",
"method": "Solution method (simple); Dilution of concentrate",
"uses": "Flavored vehicle; carminative; masks unpleasant taste of other drugs",
"caution": "Store away from light and heat. Oxidative degradation of terpenes causes off-flavors.",
"color": MED_GREEN,
},
{
"name": "Rose Water (Strong Rose Water NF)",
"type": "Simple (distilled only)",
"source": "Fresh Rosa damascena petals",
"composition": "Saturated aqueous solution of rose oil; prepared only by distillation",
"method": "DISTILLATION ONLY — cannot be prepared by any other method",
"uses": "Perfume ingredient; flavoring vehicle; ophthalmic/cosmetic preparations",
"caution": "Can only be prepared by distillation from fresh plant material. Store in amber bottles.",
"color": HexColor("#8B2252"),
},
{
"name": "Orange Flower Water NF",
"type": "Simple (distilled only)",
"source": "Fresh flowers of Citrus aurantium (bitter orange)",
"composition": "Saturated aqueous solution of orange flower oil (neroli oil)",
"method": "DISTILLATION ONLY",
"uses": "Flavoring vehicle; perfumery ingredient",
"caution": "Only by distillation. Sensitive to light and heat.",
"color": HexColor("#B8540A"),
},
{
"name": "Hamamelis Water (Witch Hazel Water)",
"type": "Simple (distilled only)",
"source": "Hamamelis virginiana (witch hazel) fresh bark and twigs",
"composition": "Aqueous distillate containing ~14-15% ethanol",
"method": "DISTILLATION ONLY",
"uses": "Astringent; rub; aftershave lotion; cosmetic perfumery; Hamamelis 12.5% + Naphazoline 0.01% for eye redness",
"caution": "Distillation only. Contains ethanol naturally from the plant.",
"color": HexColor("#4A6B1A"),
},
{
"name": "Camphor Water BP",
"type": "Concentrated / Simple",
"source": "Camphor (crystalline terpenoid)",
"composition": "Camphor dissolved in purified water; concentrated form available",
"method": "Solution method",
"uses": "Eye drops (refreshing/soothing); rubefacient; counterirritant; soothing cough",
"caution": "Camphor is toxic in overdose. Handle with care. Store in cool, dark place.",
"color": HexColor("#1A3A6B"),
},
]
for ex in examples:
hs = S("EH", fontSize=11, leading=14, fontName="Helvetica-Bold", textColor=WHITE)
ls = S("EL", fontSize=9.5, leading=14, fontName="Helvetica", textColor=DARK_GRAY)
cs = S("EC", fontSize=9.5, leading=14, fontName="Helvetica-Oblique", textColor=HexColor("#8B0000"))
us = S("EU", fontSize=9.5, leading=14, fontName="Helvetica", textColor=DARK_GREEN)
comp_text = ex["composition"].replace("\n", "<br/>")
rows = [
[Paragraph(ex["name"], hs)],
[Paragraph(f"<b>Type:</b> {ex['type']} | <b>Source:</b> {ex['source']}", ls)],
[Paragraph(f"<b>Composition:</b> {comp_text}", ls)],
[Paragraph(f"<b>Method:</b> {ex['method']}", ls)],
[Paragraph(f"<b>Uses:</b> {ex['uses']}", us)],
[Paragraph(f"⚠ Caution: {ex['caution']}", cs)],
]
blk = Table(rows, colWidths=[16.5*cm])
blk.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), ex["color"]),
("BACKGROUND", (0,1),(-1,-1), LIGHT_GREEN),
("BOX", (0,0),(-1,-1), 1, ex["color"]),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING",(0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
story.append(KeepTogether([blk, Spacer(1, 8)]))
story.append(PageBreak())
# ── Chapter 9: Summary Tables ────────────────────────────────────────────
story.append(chapter_banner("Chapter 9: Quick-Reference Summary Tables"))
story.append(Spacer(1, 8))
story.append(section_bar("9.1 Master Summary"))
sum_h = ["Aspect", "Key Points"]
sum_r = [
["Definition (BP)", "Clear, saturated aqueous solutions of volatile oils or other aromatic/volatile substances"],
["Nature", "Saturated solutions; very low active substance concentration; NOT therapeutically potent"],
["Types", "Simple (aqueous only) | Concentrated (alcoholic — dilute 1:39 before use)"],
["Methods (Official)", "1. Distillation 2. Solution (Agitation) 3. Dilution of Concentrate"],
["Distillation only", "Rose Water, Orange Flower Water, Hamamelis Water"],
["Solution method", "Peppermint Water, Spearmint Water, Chloroform Water"],
["Dispersing agents", "Purified talc, Siliceous earth, Pulped filter paper (NOT fine talc alone)"],
["Main stability issues", "Volatilization | Oxidation (autoxidation) | Microbial growth | Oil separation | Terpene degradation"],
["Most critical stability issue", "Chloroform Water — oxidizes to PHOSGENE in light → must be in amber bottles"],
["Terpeneless oils", "More stable and more water-soluble; terpenes removed by fractional distillation/extraction"],
["Aseptic shelf life", "Up to 1 year when prepared with boiled water + bacterial-retentive filtration"],
["Labeling", '"PROTECT FROM SUNLIGHT" in RED INK'],
["Container", "Amber/opaque, tightly stoppered glass bottles"],
["Uses", "Flavored vehicles | Emulsion/suspension liquid phase | Carminative | Expectorant | Astringent | Cosmetic"],
]
story.append(make_table(sum_h, sum_r, [5*cm, 11.5*cm]))
story.append(Spacer(1, 10))
story.append(section_bar("9.2 Syrups vs Aromatic Waters — Key Differences"))
diff_h = ["Feature", "Syrups", "Aromatic Waters"]
diff_r = [
["Main Solute", "Sucrose (sugar)", "Volatile oil / aromatic substance"],
["Concentration", "Very high (65-85% sugar)", "Very low (saturated, but tiny amount)"],
["Therapeutic Potency", "Moderate to high (medicated syrups)", "Not therapeutically potent"],
["Primary Use", "Sweetened vehicle + medicinal", "Flavored vehicle only"],
["Preservative Mechanism", "High osmotic pressure (sugar)", "None inherent — prone to microbial growth"],
["Viscosity", "High (thick, viscous)", "Low (thin, water-like)"],
["Alcohol Content", "Optional (preservative)", "Simple = none; Concentrated = yes"],
["Storage Label", "No special light warning", "PROTECT FROM SUNLIGHT (red ink)"],
["Key Stability Issue", "Inversion, crystallization, microbial", "Oxidation, volatilization, microbial"],
["Methods", "Heat, Cold agitation, Medicated liquid, Percolation", "Distillation, Solution, Dilution of concentrate"],
]
story.append(make_table(diff_h, diff_r, [4*cm, 6.2*cm, 6.2*cm]))
story.append(Spacer(1, 10))
story.append(PageBreak())
# ── Chapter 10: Practice Q&A ─────────────────────────────────────────────
story.append(chapter_banner("Chapter 10: Practice Q & A"))
story.append(Spacer(1, 10))
qa = [
("Q1. Define aromatic waters according to the British Pharmacopoeia.",
"Aromatic waters are clear, saturated aqueous solutions of volatile oils or other aromatic or volatile substances. They are free from solid impurities and from empyreumatic or foreign odors."),
("Q2. Are aromatic waters therapeutically potent? Explain.",
"No. Aromatic waters are NOT therapeutically potent because volatile oils have very low solubility in water, so even a saturated solution contains only a very small proportion of active substance. They are used primarily as flavored vehicles, not for pharmacological effect."),
("Q3. What are the three official methods for preparing aromatic waters?",
"1. Distillation Method — plants/drugs + water in a still; excess oil separated from distillate.\n2. Solution Method (Agitation) — volatile oil shaken with purified water + dispersing agent, filtered.\n3. Dilution of Concentrate — pre-made alcoholic or surfactant concentrate diluted 1:39 with purified water."),
("Q4. Which aromatic waters can ONLY be prepared by distillation?",
"Rose Water (Strong Rose Water NF), Orange Flower Water NF, and Hamamelis Water (Witch Hazel). These are prepared from fresh plant material and cannot be made by any other method."),
("Q5. Why is Chloroform Water stored in amber bottles with 'Protect from Sunlight' label in red ink?",
"Chloroform undergoes oxidation in the presence of light to form PHOSGENE — a poisonous gas (COCl₂). Therefore, all aromatic waters (and especially Chloroform Water) must be stored in light-resistant (amber) containers and labeled 'PROTECT FROM SUNLIGHT' in red ink."),
("Q6. What dispersing agents are used in the solution method? Why is fine talc avoided?",
"Purified talc, siliceous earth (purified siliceous earth), and pulped filter paper are used. Fine (finely divided) talc is NOT used alone because it is subdivided too finely and passes through the filter paper, resulting in a turbid product. Siliceous earth or pulped filter paper are preferred."),
("Q7. What are terpeneless oils and why are they preferred?",
"Terpeneless oils are essential oils from which the terpene fractions have been removed by fractional distillation or solvent extraction. They are preferred because: (1) terpenes are chemically unstable — prone to oxidation, polymerization, and resinification; (2) terpeneless oils are more water-soluble, giving higher saturation; (3) they produce more stable aromatic waters with longer shelf life."),
("Q8. How long can aseptically prepared aromatic waters remain stable?",
"Aromatic waters prepared aseptically with recently boiled purified water, filtered through bacterial-retentive filters, and stored in sterilized glass containers remain stable for up to ONE YEAR."),
("Q9. What is the dilution ratio for concentrated aromatic waters?",
"Concentrated aromatic waters are diluted 1 part concentrate + 39 parts purified water = 1:39 dilution (1 in 40 total). This produces an aromatic water equivalent in concentration to the simple (dilute) aromatic water."),
("Q10. List three differences between syrups and aromatic waters.",
"1. Sucrose content: Syrups have very high sugar concentration (65-85%); aromatic waters have no sugar.\n2. Preservation: Syrups self-preserve via osmotic pressure; aromatic waters have no inherent preservative.\n3. Viscosity: Syrups are thick and viscous; aromatic waters are thin, water-like liquids."),
]
for q, a in qa:
blk = Table([
[Paragraph(q, qa_q)],
[Paragraph(a.replace("\n", "<br/>"), qa_a)],
], colWidths=[16.5*cm])
blk.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), LIGHT_GREEN),
("BACKGROUND", (0,1),(0,-1), WHITE),
("BOX", (0,0),(-1,-1), 0.8, MED_GREEN),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING",(0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 11),
("RIGHTPADDING", (0,0),(-1,-1), 11),
]))
story.append(KeepTogether([blk, Spacer(1, 6)]))
return story
# ── Build ─────────────────────────────────────────────────────────────────────
def build():
doc = SimpleDocTemplate(
OUTPUT_PATH, pagesize=A4,
leftMargin=2*cm, rightMargin=2*cm,
topMargin=2*cm, bottomMargin=2.2*cm,
title="Pharmaceutical Aromatic Waters - Comprehensive Study Guide",
author="Pharmacy Study Guide",
subject="Pharmaceutics - Aromatic Waters",
)
story = build_cover() + build_content()
doc.build(story, onFirstPage=add_page_number, onLaterPages=add_page_number)
print(f"PDF created: {OUTPUT_PATH}")
if __name__ == "__main__":
build()
cd /home/daytona/workspace/syrups-study-guide && python generate_aromatic_waters…
ls -lh /home/daytona/workspace/syrups-study-guide/Aromatic_Waters_Study_Guide.pd…
Aromatic Waters Study Guide
PDF Document · PDF
| Chapter | Content |
|---|---|
| 1 | Definition & BP Pharmacopoeial standards; 6 key characteristics |
| 2 | Full composition table — all 5 ingredient types with roles and examples |
| 3 | Classification — Simple vs Concentrated; by volatile substance source |
| 4 | 9 Uses — vehicle, emulsion phase, carminative, expectorant, astringent, cosmetic, etc. |
| 5 | All 3 official methods (Distillation, Solution, Dilution) — step-by-step with advantages, disadvantages, and cautions; plus a comparison table |
| 6 | 6 Stability Problems — each with cause, consequence, and solutions (includes the Chloroform → Phosgene warning) |
| 7 | Storage & Packaging — including the red-ink "Protect from Sunlight" labeling requirement |
| 8 | 6 Official examples — Chloroform Water, Peppermint Water, Rose Water, Orange Flower Water, Hamamelis Water, Camphor Water |
| 9 | Master summary table + Syrups vs Aromatic Waters comparison table |
| 10 | 10 Practice Q&A pairs for exam prep |
just add visual diagrams of the preparation methods
~/syrups-study-guide/generate_aw_with_diagrams.py
"""
Aromatic Waters Study Guide PDF — with vector flowchart diagrams
for all 3 preparation methods drawn using ReportLab graphics.
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.lib.colors import HexColor
from reportlab.graphics.shapes import (
Drawing, Rect, String, Line, Polygon, Group, Circle
)
from reportlab.platypus import Flowable
OUTPUT_PATH = "/home/daytona/workspace/syrups-study-guide/Aromatic_Waters_Study_Guide.pdf"
# ── Palette ───────────────────────────────────────────────────────────────────
DARK_GREEN = HexColor("#1A4A2E")
MED_GREEN = HexColor("#2E7D52")
LIGHT_GREEN = HexColor("#D4EFE1")
ACCENT_AMBER = HexColor("#D97706")
LIGHT_AMBER = HexColor("#FEF3C7")
ACCENT_TEAL = HexColor("#0E6B6B")
LIGHT_TEAL = HexColor("#CCECEC")
WHITE = colors.white
LIGHT_GRAY = HexColor("#F4F6F8")
MED_GRAY = HexColor("#7A8A99")
DARK_GRAY = HexColor("#2D2D2D")
TABLE_HEADER = HexColor("#1A4A2E")
TABLE_ODD = HexColor("#EBF5EE")
TABLE_EVEN = WHITE
RED_BOX = HexColor("#C0392B")
# ── Styles ────────────────────────────────────────────────────────────────────
def S(name, **kw):
return ParagraphStyle(name, **kw)
cover_title = S("CT", fontSize=34, leading=42, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)
cover_sub = S("CS", fontSize=16, leading=22, textColor=HexColor("#BBDDC8"), fontName="Helvetica", alignment=TA_CENTER)
cover_info = S("CI", fontSize=11, leading=16, textColor=HexColor("#99CCA8"), fontName="Helvetica", alignment=TA_CENTER)
chapter_title = S("ChT", fontSize=18, leading=24, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_LEFT)
body = S("Body", fontSize=10, leading=15, textColor=DARK_GRAY, fontName="Helvetica", spaceBefore=3, spaceAfter=3, alignment=TA_JUSTIFY)
bullet_s = S("Bul", fontSize=10, leading=14, textColor=DARK_GRAY, fontName="Helvetica", leftIndent=16, spaceBefore=2, spaceAfter=2)
note_s = S("Note", fontSize=9.5, leading=14, textColor=HexColor("#1A4020"), fontName="Helvetica-Oblique", leftIndent=10, rightIndent=10)
sub_h = S("SubH", fontSize=11, leading=15, textColor=ACCENT_TEAL, fontName="Helvetica-Bold", spaceBefore=8, spaceAfter=3)
qa_q = S("QQ", fontSize=10.5, leading=15, fontName="Helvetica-Bold", textColor=DARK_GREEN)
qa_a = S("QA", fontSize=10, leading=14, fontName="Helvetica", textColor=DARK_GRAY, leftIndent=10)
diag_cap = S("DC", fontSize=10, leading=14, fontName="Helvetica-Bold", textColor=DARK_GREEN, alignment=TA_CENTER, spaceBefore=4, spaceAfter=6)
# ── Page footer ───────────────────────────────────────────────────────────────
def add_page_number(canvas, doc):
canvas.saveState()
canvas.setFillColor(DARK_GREEN)
canvas.rect(0, 0, A4[0], 22, fill=1, stroke=0)
canvas.setFillColor(WHITE)
canvas.setFont("Helvetica", 8)
canvas.drawString(2*cm, 7, "Pharmaceutical Aromatic Waters - Comprehensive Study Guide")
canvas.drawRightString(A4[0]-2*cm, 7, f"Page {doc.page}")
canvas.restoreState()
# ── Layout helpers ────────────────────────────────────────────────────────────
def chapter_banner(text):
t = Table([[Paragraph(text, chapter_title)]], colWidths=[17*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), DARK_GREEN),
("ROUNDEDCORNERS",[6]),
("TOPPADDING", (0,0),(-1,-1), 10),
("BOTTOMPADDING", (0,0),(-1,-1), 10),
("LEFTPADDING", (0,0),(-1,-1), 14),
("RIGHTPADDING", (0,0),(-1,-1), 14),
]))
return t
def section_bar(text):
s = S("SB", fontSize=13, leading=18, textColor=DARK_GREEN,
fontName="Helvetica-Bold", spaceBefore=0, spaceAfter=0)
t = Table([[Paragraph(text, s)]], colWidths=[16.5*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), LIGHT_GREEN),
("LINEBEFOREEACH",(0,0),(0,-1), 4, MED_GREEN),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING", (0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
return t
def colored_box(text, bg, border):
t = Table([[Paragraph(text, note_s)]], colWidths=[16.5*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), bg),
("BOX", (0,0),(-1,-1), 1, border),
("TOPPADDING", (0,0),(-1,-1), 8),
("BOTTOMPADDING", (0,0),(-1,-1), 8),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
return t
def make_table(headers, rows, col_widths):
hdr_s = S("H", fontSize=10, leading=14, fontName="Helvetica-Bold", textColor=WHITE, alignment=TA_CENTER)
cell_s = S("C", fontSize=9.5, leading=13, fontName="Helvetica", textColor=DARK_GRAY)
data = [[Paragraph(str(h), hdr_s) for h in headers]]
for row in rows:
data.append([Paragraph(str(c), cell_s) for c in row])
t = Table(data, colWidths=col_widths)
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), TABLE_HEADER),
("ROWBACKGROUNDS",(0,1),(-1,-1), [TABLE_ODD, TABLE_EVEN]),
("GRID", (0,0),(-1,-1), 0.4, HexColor("#90BCA0")),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 7),
("RIGHTPADDING", (0,0),(-1,-1), 7),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]))
return t
# ════════════════════════════════════════════════════════════════════════════════
# DIAGRAM HELPERS — pure ReportLab vector drawings
# ════════════════════════════════════════════════════════════════════════════════
class FlowchartDiagram(Flowable):
"""
A Flowable that wraps a ReportLab Drawing so it can be placed in a story.
width / height refer to the drawing canvas size (points).
"""
def __init__(self, drawing):
super().__init__()
self.drawing = drawing
self.width = drawing.width
self.height = drawing.height
def draw(self):
self.drawing.drawOn(self.canv, 0, 0)
def wrap(self, availW, availH):
return self.width, self.height
def _draw_box(d, x, y, w, h, fill_color, text, font_size=8.5,
text_color=colors.white, bold=False, radius=6):
"""Draw a rounded rectangle with centred multi-line text."""
r = Rect(x, y, w, h,
rx=radius, ry=radius,
fillColor=fill_color,
strokeColor=colors.white,
strokeWidth=1.2)
d.add(r)
font = "Helvetica-Bold" if bold else "Helvetica"
lines = text.split("\n")
line_h = font_size * 1.35
total_h = len(lines) * line_h
start_y = y + h / 2 + total_h / 2 - line_h * 0.75
for line in lines:
s = String(x + w / 2, start_y, line,
fontName=font, fontSize=font_size,
fillColor=text_color, textAnchor="middle")
d.add(s)
start_y -= line_h
def _arrow_down(d, x, y, length=22, color=HexColor("#2E7D52")):
"""Draw a downward arrow from (x, y)."""
shaft_x = x
tip_y = y - length
# Shaft
d.add(Line(shaft_x, y, shaft_x, tip_y + 6,
strokeColor=color, strokeWidth=1.8))
# Arrowhead (triangle)
d.add(Polygon([shaft_x - 5, tip_y + 7,
shaft_x + 5, tip_y + 7,
shaft_x, tip_y],
fillColor=color, strokeColor=color, strokeWidth=0))
def _arrow_right(d, x, y, length=28, color=HexColor("#2E7D52")):
"""Draw a rightward arrow from (x, y)."""
tip_x = x + length
d.add(Line(x, y, tip_x - 6, y,
strokeColor=color, strokeWidth=1.8))
d.add(Polygon([tip_x - 7, y + 5,
tip_x - 7, y - 5,
tip_x, y],
fillColor=color, strokeColor=color, strokeWidth=0))
def _diamond(d, cx, cy, hw, hh, fill_color, text, font_size=8):
"""Draw a decision diamond centred at (cx, cy)."""
pts = [cx, cy + hh,
cx + hw, cy,
cx, cy - hh,
cx - hw, cy]
d.add(Polygon(pts, fillColor=fill_color,
strokeColor=colors.white, strokeWidth=1.2))
lines = text.split("\n")
line_h = font_size * 1.35
total_h = len(lines) * line_h
start_y = cy + total_h / 2 - line_h * 0.75
for line in lines:
d.add(String(cx, start_y, line,
fontName="Helvetica", fontSize=font_size,
fillColor=colors.white, textAnchor="middle"))
start_y -= line_h
# ────────────────────────────────────────────────────────────────────────────
# DIAGRAM 1 — Distillation Method (vertical flowchart, 500 × 560 pt)
# ────────────────────────────────────────────────────────────────────────────
def diagram_distillation():
W, H = 500, 580
d = Drawing(W, H)
# Background
d.add(Rect(0, 0, W, H, fillColor=HexColor("#F0F8F4"),
strokeColor=MED_GREEN, strokeWidth=1.5))
# Title bar
d.add(Rect(0, H - 38, W, 38, fillColor=DARK_GREEN,
strokeColor=DARK_GREEN, strokeWidth=0))
d.add(String(W / 2, H - 24, "DISTILLATION METHOD",
fontName="Helvetica-Bold", fontSize=12,
fillColor=WHITE, textAnchor="middle"))
bw, bh = 310, 38
bx = (W - bw) / 2
arrow_x = W / 2
steps = [
(HexColor("#1A4A2E"), "Coarsely grind the odoriferous plant\nor drug material"),
(HexColor("#2E6B44"), "Place in a STILL with sufficient\nPurified Water"),
(HexColor("#3A8A5A"), "Heat & distil most of the water\n(avoid charring / scorching)"),
(HexColor("#4AAA6A"), "Excess oil rises to TOP of distillate\n→ Separate & discard oil layer"),
(HexColor("#5ABB7A"), "Collect aqueous phase\n(saturated with volatile material)"),
(HexColor("#6ACC8A"), "Clarify by filtration if turbid"),
(HexColor("#2E7D52"), "AROMATIC WATER\n(Final Product) ✓"),
]
top_y = H - 56
gap = 22 # arrow length
for i, (col, txt) in enumerate(steps):
y = top_y - i * (bh + gap)
bold = (i == len(steps) - 1)
fc = HexColor("#DDFAEE") if bold else colors.white
_draw_box(d, bx, y - bh, bw, bh, col, txt,
font_size=8.5, text_color=fc, bold=bold)
if i < len(steps) - 1:
_arrow_down(d, arrow_x, y - bh, length=gap)
# Side note about XX labeling
note_y = top_y - 3 * (bh + gap) - bh / 2
d.add(Rect(bx + bw + 6, note_y - 18, 115, 40,
fillColor=LIGHT_AMBER, strokeColor=ACCENT_AMBER, strokeWidth=1))
d.add(String(bx + bw + 13, note_y + 10,
"Label: XX, XXX, XXXX",
fontName="Helvetica-Bold", fontSize=7.5,
fillColor=HexColor("#7A3800"), textAnchor="start"))
d.add(String(bx + bw + 13, note_y - 2,
"(each X = 1 distillation)",
fontName="Helvetica", fontSize=7,
fillColor=HexColor("#7A3800"), textAnchor="start"))
# arrow pointing to step 3
connect_y = top_y - 2 * (bh + gap) - bh / 2
d.add(Line(bx + bw + 6, note_y + 2,
bx + bw + 6, connect_y,
strokeColor=ACCENT_AMBER, strokeWidth=1, strokeDashArray=[3, 2]))
return FlowchartDiagram(d)
# ────────────────────────────────────────────────────────────────────────────
# DIAGRAM 2 — Solution (Agitation) Method
# ────────────────────────────────────────────────────────────────────────────
def diagram_solution():
W, H = 500, 540
d = Drawing(W, H)
d.add(Rect(0, 0, W, H, fillColor=HexColor("#F0F8F4"),
strokeColor=MED_GREEN, strokeWidth=1.5))
d.add(Rect(0, H - 38, W, 38, fillColor=MED_GREEN,
strokeColor=MED_GREEN, strokeWidth=0))
d.add(String(W / 2, H - 24, "SOLUTION (AGITATION) METHOD",
fontName="Helvetica-Bold", fontSize=12,
fillColor=WHITE, textAnchor="middle"))
bw, bh = 310, 38
bx = (W - bw) / 2
ax = W / 2
gap = 22
steps = [
(HexColor("#1A4A2E"), "Add 2 mL (liquid) or 2 g (solid)\nvolatile substance to 1000 mL Purified Water"),
(HexColor("#2E6B44"), "Shake intermittently for 15 minutes"),
(HexColor("#3A8A5A"), "Add dispersing agent\n(Purified Talc / Siliceous Earth /\nPulped Filter Paper)"),
(HexColor("#4AAA6A"), "Shake vigorously for several minutes"),
(HexColor("#5ABB7A"), "Filter through wetted filter paper\n(Discard first portions of filtrate)"),
(HexColor("#2E7D52"), "AROMATIC WATER\n(Clear Filtrate = Final Product) ✓"),
]
top_y = H - 56
for i, (col, txt) in enumerate(steps):
y = top_y - i * (bh + gap)
bold = (i == len(steps) - 1)
fc = HexColor("#DDFAEE") if bold else colors.white
_draw_box(d, bx, y - bh, bw, bh, col, txt,
font_size=8.5, text_color=fc, bold=bold)
if i < len(steps) - 1:
_arrow_down(d, ax, y - bh, length=gap)
# Warning note — no fine talc
note_x = bx + bw + 6
note_top = top_y - 2 * (bh + gap) - 2
d.add(Rect(note_x, note_top - 44, 118, 48,
fillColor=HexColor("#FDECEA"), strokeColor=RED_BOX, strokeWidth=1))
d.add(String(note_x + 6, note_top + 0,
"⚠ Avoid fine talc!",
fontName="Helvetica-Bold", fontSize=7.5,
fillColor=RED_BOX, textAnchor="start"))
d.add(String(note_x + 6, note_top - 12,
"It passes through filter",
fontName="Helvetica", fontSize=7,
fillColor=HexColor("#8B0000"), textAnchor="start"))
d.add(String(note_x + 6, note_top - 23,
"paper → turbid product.",
fontName="Helvetica", fontSize=7,
fillColor=HexColor("#8B0000"), textAnchor="start"))
d.add(String(note_x + 6, note_top - 34,
"Use siliceous earth instead.",
fontName="Helvetica", fontSize=7,
fillColor=HexColor("#8B0000"), textAnchor="start"))
return FlowchartDiagram(d)
# ────────────────────────────────────────────────────────────────────────────
# DIAGRAM 3 — Dilution of Concentrate Method
# (shows two parallel branches: Alcohol-based vs Surfactant-based)
# ────────────────────────────────────────────────────────────────────────────
def diagram_dilution():
W, H = 540, 560
d = Drawing(W, H)
d.add(Rect(0, 0, W, H, fillColor=HexColor("#EEF8F8"),
strokeColor=ACCENT_TEAL, strokeWidth=1.5))
d.add(Rect(0, H - 38, W, 38, fillColor=ACCENT_TEAL,
strokeColor=ACCENT_TEAL, strokeWidth=0))
d.add(String(W / 2, H - 24, "DILUTION OF CONCENTRATE METHOD",
fontName="Helvetica-Bold", fontSize=12,
fillColor=WHITE, textAnchor="middle"))
# ── Step 1: top centre box ───────────────────────────────────────────────
bw1, bh1 = 310, 42
bx1 = (W - bw1) / 2
top_y = H - 56
_draw_box(d, bx1, top_y - bh1, bw1, bh1,
HexColor("#0E6B6B"),
"START: Select Concentrate Type",
font_size=9, bold=True)
# Arrow down to diamond
diamond_cx = W / 2
diamond_cy = top_y - bh1 - 28
_arrow_down(d, W / 2, top_y - bh1, length=22)
# Diamond decision
_diamond(d, diamond_cx, diamond_cy, 90, 28,
HexColor("#D97706"), "Solvent\nType?", font_size=8.5)
# ── Left branch: Alcohol-based ───────────────────────────────────────────
branch_y = diamond_cy - 28 # bottom tip of diamond
left_cx = 130
right_cx = W - 130
branch_top = branch_y - 22
# Arrow left
d.add(Line(diamond_cx - 90, diamond_cy,
left_cx + 75, diamond_cy,
strokeColor=MED_GREEN, strokeWidth=1.8))
_arrow_down(d, left_cx, diamond_cy, length=diamond_cy - branch_top)
d.add(String(diamond_cx - 110, diamond_cy + 4, "Alcohol",
fontName="Helvetica-Bold", fontSize=8,
fillColor=DARK_GREEN, textAnchor="middle"))
# Arrow right
d.add(Line(diamond_cx + 90, diamond_cy,
right_cx - 75, diamond_cy,
strokeColor=ACCENT_TEAL, strokeWidth=1.8))
_arrow_down(d, right_cx, diamond_cy, length=diamond_cy - branch_top)
d.add(String(diamond_cx + 110, diamond_cy + 4, "Surfactant",
fontName="Helvetica-Bold", fontSize=8,
fillColor=ACCENT_TEAL, textAnchor="middle"))
col_w = 150
col_h = 36
gap = 20
# Left branch boxes (Alcohol)
left_steps = [
"Dissolve volatile oil\nin Ethanol (Alcohol BP)",
"Store as CONCENTRATE\n(stable during storage)",
"At use: dilute 1 part\n+ 39 parts Purified Water",
]
for i, txt in enumerate(left_steps):
y = branch_top - i * (col_h + gap)
_draw_box(d, left_cx - col_w / 2, y - col_h, col_w, col_h,
HexColor("#2E6B44"), txt, font_size=7.8)
if i < len(left_steps) - 1:
_arrow_down(d, left_cx, y - col_h, length=gap)
# Right branch boxes (Surfactant)
right_steps = [
"Dissolve volatile oil\nin Tween 80 / Tween 20",
"Store as CONCENTRATE\n(stable during storage)",
"At use: dilute 1 part\n+ 39 parts Purified Water",
]
for i, txt in enumerate(right_steps):
y = branch_top - i * (col_h + gap)
_draw_box(d, right_cx - col_w / 2, y - col_h, col_w, col_h,
ACCENT_TEAL, txt, font_size=7.8)
if i < len(right_steps) - 1:
_arrow_down(d, right_cx, y - col_h, length=gap)
# Merge lines to final box
final_top_y = branch_top - 3 * (col_h + gap)
final_bw = 300
final_bx = (W - final_bw) / 2
final_bh = 42
# Lines from both branches down to final
merge_y = final_top_y
d.add(Line(left_cx, branch_top - 3 * (col_h + gap),
left_cx, merge_y - 20,
strokeColor=MED_GREEN, strokeWidth=1.8))
d.add(Line(right_cx, branch_top - 3 * (col_h + gap),
right_cx, merge_y - 20,
strokeColor=ACCENT_TEAL, strokeWidth=1.8))
d.add(Line(left_cx, merge_y - 20,
right_cx, merge_y - 20,
strokeColor=DARK_GREEN, strokeWidth=1.8))
_arrow_down(d, W / 2, merge_y - 20, length=20)
_draw_box(d, final_bx, merge_y - 20 - 20 - final_bh,
final_bw, final_bh,
DARK_GREEN,
"AROMATIC WATER\n(Final Diluted Product) ✓",
font_size=9, bold=True, text_color=HexColor("#DDFAEE"))
# 1:39 ratio callout
ratio_y = branch_top - 2 * (col_h + gap) - col_h / 2
d.add(Rect(W / 2 - 55, ratio_y - 16, 110, 30,
fillColor=LIGHT_AMBER, strokeColor=ACCENT_AMBER, strokeWidth=1))
d.add(String(W / 2, ratio_y + 6, "Dilution Ratio = 1 : 39",
fontName="Helvetica-Bold", fontSize=8,
fillColor=HexColor("#7A3800"), textAnchor="middle"))
d.add(String(W / 2, ratio_y - 6, "(1 in 40 volumes total)",
fontName="Helvetica", fontSize=7.5,
fillColor=HexColor("#7A3800"), textAnchor="middle"))
return FlowchartDiagram(d)
# ════════════════════════════════════════════════════════════════════════════════
# COVER
# ════════════════════════════════════════════════════════════════════════════════
def build_cover():
story = []
cover_block = Table(
[[Paragraph("PHARMACEUTICAL<br/>AROMATIC WATERS", cover_title)],
[Spacer(1, 6)],
[Paragraph("Comprehensive Study Guide", cover_sub)],
[Spacer(1, 10)],
[Paragraph("Definition | Classification | Preparation | Stability | Storage | Examples", cover_info)]],
colWidths=[17*cm])
cover_block.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), DARK_GREEN),
("TOPPADDING", (0,0),(-1,-1), 28),
("BOTTOMPADDING", (0,0),(-1,-1), 28),
("LEFTPADDING", (0,0),(-1,-1), 20),
("RIGHTPADDING", (0,0),(-1,-1), 20),
]))
story.append(cover_block)
story.append(Spacer(1, 18))
qf_s = S("QF", fontSize=10, leading=14, fontName="Helvetica-Bold",
textColor=DARK_GREEN, alignment=TA_CENTER)
qf_data = [[Paragraph(c.replace("\n","<br/>"), qf_s) for c in [
"BP Definition\nSaturated Aqueous\nSolutions",
"3 Official Methods\nof Preparation",
"2 Main Types\nSimple & Concentrated",
"Not Therapeutically\nPotent\nUsed as Vehicles",
]]]
qf_t = Table(qf_data, colWidths=[4.1*cm]*4)
qf_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), LIGHT_AMBER),
("BOX", (0,0),(-1,-1), 1, ACCENT_AMBER),
("INNERGRID", (0,0),(-1,-1), 0.5, ACCENT_AMBER),
("TOPPADDING", (0,0),(-1,-1), 10),
("BOTTOMPADDING", (0,0),(-1,-1), 10),
]))
story.append(qf_t)
story.append(Spacer(1, 18))
toc_h = S("TH", fontSize=13, leading=18, fontName="Helvetica-Bold", textColor=DARK_GREEN)
toc_i = S("TI", fontSize=10, leading=16, fontName="Helvetica", textColor=DARK_GRAY, leftIndent=10)
chapters = [
"1. Definition & Pharmacopoeial Standards",
"2. Composition",
"3. Classification & Types",
"4. Uses & Applications",
"5. Methods of Preparation (with Visual Flowcharts)",
"6. Stability Problems & Solutions",
"7. Storage & Packaging",
"8. Official Examples of Aromatic Waters",
"9. Quick-Reference Summary Tables",
"10. Practice Q & A",
]
toc_rows = [[Paragraph("CONTENTS", toc_h)]] + [[Paragraph(c, toc_i)] for c in chapters]
toc_t = Table(toc_rows, colWidths=[17*cm])
toc_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), LIGHT_GREEN),
("LINEAFTER", (0,0),(0,-1), 3, MED_GREEN),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 12),
]))
story.append(toc_t)
story.append(Spacer(1, 14))
cred = S("Cr", fontSize=8.5, leading=12, fontName="Helvetica-Oblique",
textColor=MED_GRAY, alignment=TA_CENTER)
story.append(Paragraph(
"Prepared for Pharmacy Students | July 2026 | Based on BP/USP/IP Pharmacopoeia Standards", cred))
story.append(PageBreak())
return story
# ════════════════════════════════════════════════════════════════════════════════
# CONTENT (Ch 1-4 — identical to previous version, ch 5 gains diagrams)
# ════════════════════════════════════════════════════════════════════════════════
def build_content():
story = []
# ── Ch 1: Definition ─────────────────────────────────────────────────────
story.append(chapter_banner("Chapter 1: Definition & Pharmacopoeial Standards"))
story.append(Spacer(1, 10))
story.append(section_bar("1.1 Official Definition"))
story.append(Paragraph(
"Aromatic waters are <b>clear, saturated aqueous solutions of volatile oils or other "
"aromatic or volatile substances</b>, intended primarily for oral use as flavored vehicles "
"and pharmaceutical aids. They represent some of the <b>simplest formulated dosage forms</b>, "
"consisting essentially of only two components: purified water (solvent) and a volatile "
"aromatic substance (solute).",
body))
story.append(Spacer(1, 6))
story.append(colored_box(
"<b>BP Definition:</b> Aromatic waters are clear, saturated aqueous solutions of volatile oils "
"or other aromatic or volatile substances. They are saturated solutions (unless otherwise "
"specified) and are free from solid impurities and from empyreumatic (smoke-like) or "
"foreign odors.",
LIGHT_GREEN, MED_GREEN))
story.append(Spacer(1, 8))
story.append(section_bar("1.2 Key Characteristics"))
for c in [
"Clear solutions — free from solid particles or turbidity.",
"Saturated with the volatile substance — at maximum solubility.",
"Very LOW concentration of active substance due to low water-solubility of volatile oils.",
"Possess odor and taste similar to the plant/substance from which they are prepared.",
"NOT therapeutically potent — used mainly as vehicles and flavoring agents.",
"Aqueous in nature — do NOT contain alcohol (simple aromatic waters).",
]:
story.append(Paragraph(f"• {c}", bullet_s))
story.append(Spacer(1, 10))
# ── Ch 2: Composition ────────────────────────────────────────────────────
story.append(chapter_banner("Chapter 2: Composition"))
story.append(Spacer(1, 10))
story.append(section_bar("2.1 Ingredients"))
story.append(make_table(
["Component", "Role", "Examples"],
[
["Purified Water", "Primary solvent; saturating medium", "IP/BP/USP Purified Water"],
["Volatile Oil / Aromatic Substance", "Active aromatic solute; imparts odor, taste, flavor",
"Peppermint oil, Rose oil, Orange flower oil, Camphor, Chloroform"],
["Dispersing Agent (optional)", "Aids dissolution in solution method",
"Purified talc, Pulped filter paper, Siliceous earth, Kaolin"],
["Alcohol (concentrated waters only)", "Solvent for concentrated form",
"Ethanol (Alcohol BP)"],
["Non-ionic Surfactant (alternate method)", "Solubilizer",
"Tween 80 (Polysorbate 80), Tween 20"],
],
[3.5*cm, 5*cm, 8*cm]))
story.append(Spacer(1, 10))
# ── Ch 3: Classification ─────────────────────────────────────────────────
story.append(chapter_banner("Chapter 3: Classification & Types"))
story.append(Spacer(1, 10))
story.append(section_bar("3.1 Two Main Types"))
story.append(make_table(
["Type", "Solvent", "Alcohol?", "Dilution Before Use?", "Examples"],
[
["Simple (Dilute) Aromatic Waters", "Purified water only", "No",
"Ready to use",
"Chloroform Water BP, Peppermint Water, Rose Water, Camphor Water"],
["Concentrated Aromatic Waters", "Alcohol + Water", "Yes",
"Yes — diluted 1:39 with purified water",
"Concentrated Peppermint Water BP, Caraway Water BPC, Cinnamon Water BPC, Dill Water BPC"],
],
[3.5*cm, 3*cm, 2.2*cm, 3.2*cm, 5.6*cm]))
story.append(Spacer(1, 8))
story.append(colored_box(
"<b>Key Note on Concentrated Waters:</b> Concentrated aromatic waters contain alcohol as the "
"solvent for the volatile constituent. Before use, they are diluted 1 part concentrate + "
"39 parts purified water (1 in 40 total) to produce the equivalent simple aromatic water.",
LIGHT_AMBER, ACCENT_AMBER))
story.append(Spacer(1, 8))
story.append(section_bar("3.2 Classification by Source of Volatile Substance"))
for title, desc, eg in [
("From Essential Oils",
"Prepared from volatile oils of plants.",
"Peppermint Water, Spearmint Water, Anise Water, Orange Flower Water"),
("From Isolated Volatile Compounds",
"Prepared from pure isolated aromatic chemicals.",
"Chloroform Water, Camphor Water"),
("From Fresh Plant Material (Distillation only)",
"Can ONLY be prepared by distillation — no other method applicable.",
"Rose Water (Strong Rose Water NF), Orange Flower Water NF, Hamamelis Water"),
]:
story.append(Paragraph(f"<b>{title}</b>", sub_h))
story.append(Paragraph(desc, body))
story.append(Paragraph(f"Examples: {eg}",
S("ex", fontSize=9.5, leading=13, fontName="Helvetica-Oblique",
textColor=ACCENT_TEAL, leftIndent=10)))
story.append(Spacer(1, 4))
story.append(Spacer(1, 6))
# ── Ch 4: Uses ───────────────────────────────────────────────────────────
story.append(chapter_banner("Chapter 4: Uses & Applications"))
story.append(Spacer(1, 10))
story.append(make_table(
["Use", "Description", "Example"],
[
["Flavored Vehicle", "Pleasantly flavored medium for oral drugs", "Peppermint Water as oral vehicle"],
["Liquid Phase of Emulsions", "Aqueous continuous phase in O/W emulsions", "Rose Water in cold cream"],
["Liquid Phase of Suspensions", "Aqueous dispersing medium", "Camphor Water in ophthalmic suspensions"],
["Carminative / Digestive", "Relieve flatulence", "Peppermint Water"],
["Expectorant", "Chloroform water in expectorant syrups (5-15 mL)", "Chloroform Water BP"],
["Eye Preparations", "Refreshing/soothing; eye redness relief",
"Camphor eye drops; Hamamelis 12.5% + Naphazoline 0.01%"],
["Astringent / Cosmetic", "Aftershave lotion; cosmetic products", "Witch Hazel Water"],
["Perfumery", "Fragrance ingredient", "Rose Water"],
["Intermediate Manufacturing", "Solvent/vehicle in other dosage forms", "Various"],
],
[3.5*cm, 7*cm, 6*cm]))
story.append(Spacer(1, 10))
story.append(PageBreak())
# ── Ch 5: Methods — TEXT blocks + DIAGRAMS ───────────────────────────────
story.append(chapter_banner("Chapter 5: Methods of Preparation"))
story.append(Spacer(1, 8))
story.append(Paragraph(
"Aromatic waters may be prepared by <b>three official methods</b> — selected based on the "
"nature of the aromatic substance and practical/economic considerations:",
body))
story.append(Spacer(1, 10))
methods_text = [
{
"num": "Method 1", "title": "Distillation Method", "color": DARK_GREEN,
"desc": "The traditional method. Used especially for fresh plant materials.",
"procedure": [
"Coarsely grind the odoriferous plant/drug material.",
"Place in a suitable STILL with sufficient purified water.",
"Heat and distil most of the water — avoid charring/scorching.",
"Separate excess oil floating on top of the distillate.",
"Collect the aqueous phase (saturated with volatile material).",
"Clarify by filtration if necessary.",
"Label product as XX, XXX, XXXX (each X = one distillation).",
],
"examples": "Strong Rose Water NF, Orange Flower Water NF, Hamamelis Water",
"adv": "Highest quality; most authentic aromatic water.",
"dis": "Slow, expensive, requires a still. Not practical for all substances.",
"note": "Aromatic waters from fresh plant material (Rose, Orange Flower, Hamamelis) can ONLY be prepared by distillation.",
},
{
"num": "Method 2", "title": "Solution (Agitation) Method", "color": MED_GREEN,
"desc": "Simpler, quicker, and more economical. Suitable for pure volatile oils.",
"procedure": [
"Add 2 mL (liquid) or 2 g (solid) of volatile substance to 1000 mL purified water.",
"Shake intermittently for 15 minutes.",
"Add dispersing agent (purified talc, siliceous earth, or pulped filter paper).",
"Shake vigorously for several more minutes.",
"Filter through wetted filter paper; discard first portions of filtrate.",
"Collect the clear filtrate — this is the aromatic water.",
],
"examples": "Peppermint Water, Spearmint Water, Chloroform Water",
"adv": "Simple, quick, economical — no specialized equipment needed.",
"dis": "Fine talc must be avoided (passes through filter). Siliceous earth or pulped paper preferred.",
"note": "The dispersing agent breaks oil into fine particles for easier filtration — it is NOT in the final product.",
},
{
"num": "Method 3", "title": "Dilution of Concentrate Method", "color": ACCENT_TEAL,
"desc": "Modern, convenient method using pre-made concentrates diluted at point of use.",
"procedure": [
"Dissolve volatile oil in alcohol (or non-ionic surfactant: Tween 80/Tween 20) to form concentrated solution.",
"Store concentrate until needed (concentrate is stable during storage).",
"At time of use: dilute 1 part concentrate + 39 parts purified water (1:39 ratio).",
"Mix thoroughly to give final aromatic water.",
],
"examples": "Concentrated Peppermint Water BP, Concentrated Caraway Water, Concentrated Cinnamon Water",
"adv": "Quick, convenient, no special equipment. Concentrate is stable.",
"dis": "Alcohol-based: prone to oxidative flavor change. Surfactant-based: objectionable odor, foaming, mold growth risk.",
"note": "Non-ionic surfactant (Tween) concentrates dissolve more oil but have organoleptic disadvantages.",
},
]
diagrams = [diagram_distillation, diagram_solution, diagram_dilution]
diagram_captions = [
"Figure 1: Distillation Method — Step-by-Step Flowchart",
"Figure 2: Solution (Agitation) Method — Step-by-Step Flowchart",
"Figure 3: Dilution of Concentrate Method — Decision Flowchart",
]
for m, diag_fn, caption in zip(methods_text, diagrams, diagram_captions):
ps = S("MP", fontSize=11, leading=15, fontName="Helvetica-Bold", textColor=WHITE)
bs = S("MB", fontSize=9.5, leading=14, fontName="Helvetica", textColor=DARK_GRAY)
es = S("ME", fontSize=9.5, leading=14, fontName="Helvetica-Bold", textColor=DARK_GREEN)
adv_s= S("MA", fontSize=9.5, leading=14, fontName="Helvetica", textColor=HexColor("#1A5C1A"))
dis_s= S("MD", fontSize=9.5, leading=14, fontName="Helvetica", textColor=HexColor("#8B0000"))
nt_s = S("MN", fontSize=9.5, leading=14, fontName="Helvetica-Oblique",textColor=HexColor("#444400"))
steps = "<br/>".join(f"{i+1}. {s}" for i, s in enumerate(m["procedure"]))
blk = Table([
[Paragraph(f"{m['num']}: {m['title']}", ps)],
[Paragraph(m["desc"], bs)],
[Paragraph(f"<b>Procedure:</b><br/>{steps}", bs)],
[Paragraph(f"<b>Examples:</b> {m['examples']}", es)],
[Paragraph(f"<b>Advantage:</b> {m['adv']}", adv_s)],
[Paragraph(f"<b>Disadvantage:</b> {m['dis']}", dis_s)],
[Paragraph(f"Note: {m['note']}", nt_s)],
], colWidths=[16.5*cm])
blk.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), m["color"]),
("BACKGROUND", (0,1),(-1,-1), LIGHT_GRAY),
("BOX", (0,0),(-1,-1), 1, m["color"]),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING", (0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
story.append(blk)
story.append(Spacer(1, 10))
# ── DIAGRAM ──
story.append(section_bar(f"Visual Diagram: {m['title']}"))
story.append(Spacer(1, 6))
# Centre the diagram in the page
diag = diag_fn()
diag_w_pt = diag.width
margin_pt = (17*cm - diag_w_pt) / 2
if margin_pt < 0:
margin_pt = 0
centred = Table([[diag]], colWidths=[17*cm])
centred.setStyle(TableStyle([
("ALIGN", (0,0),(-1,-1), "CENTER"),
("TOPPADDING", (0,0),(-1,-1), 0),
("BOTTOMPADDING", (0,0),(-1,-1), 0),
("LEFTPADDING", (0,0),(-1,-1), 0),
("RIGHTPADDING", (0,0),(-1,-1), 0),
]))
story.append(centred)
story.append(Paragraph(caption, diag_cap))
story.append(Spacer(1, 14))
# ── Methods Comparison ───────────────────────────────────────────────────
story.append(section_bar("5.1 Methods Comparison Table"))
story.append(make_table(
["Method", "Suitable For", "Speed", "Cost", "Equipment", "Best For"],
[
["Distillation", "Fresh plant material", "Slow", "High", "Still required",
"Rose, Orange Flower, Hamamelis"],
["Solution (Agitation)", "Pure volatile oils/isolated compounds", "Moderate", "Low",
"Simple", "Peppermint, Chloroform Waters"],
["Dilution of Concentrate", "Pre-made concentrate", "Fast", "Lowest", "None",
"Industrial; point-of-use dilution"],
],
[2.8*cm, 4*cm, 1.8*cm, 1.8*cm, 3*cm, 4.5*cm]))
story.append(Spacer(1, 10))
story.append(PageBreak())
# ── Ch 6: Stability ──────────────────────────────────────────────────────
story.append(chapter_banner("Chapter 6: Stability Problems & Solutions"))
story.append(Spacer(1, 8))
story.append(Paragraph(
"Aromatic waters are <b>NOT permanently stable preparations</b>. Instability is generally "
"attributed to improper storage and the inherent chemical reactivity of volatile organic compounds.",
body))
story.append(Spacer(1, 6))
stab_items = [
("1. Volatilization / Loss of Aromatic Substance",
"Volatile oils evaporate readily from open/loosely stoppered containers and at elevated temperatures.",
"Loss of odor, taste, and activity. Concentration falls below saturation.",
["Store in tightly stoppered containers.",
"Keep in a cool place away from heat.",
"Fill containers to minimize headspace.",
"Use containers stoppered with purified cotton."]),
("2. Oxidative Degradation (Autoxidation)",
"Terpenes and other oxidizable compounds react with dissolved atmospheric oxygen; catalyzed by light and trace metal ions (Fe³⁺, Cu²⁺).",
"• Chloroform → Phosgene (poisonous gas) in light.\n• Benzaldehyde → Benzoic acid crystals deposit.\n• Terpene oxidation → off-flavors, resins.",
["Store in AMBER/light-resistant bottles (mandatory for Chloroform Water).",
"Minimize oxygen in headspace.",
"Use terpeneless oils — more stable, more water-soluble.",
"Add antioxidants where appropriate."]),
("3. Microbial Contamination & Mold Growth",
"No inherent preservative. Very low solute concentration gives negligible osmotic pressure. Surfactant-based preparations especially prone.",
"Turbidity, off-odors, and patient safety risk.",
["Prepare with recently boiled purified water.",
"Filter through bacterial-retentive filters aseptically.",
"Store in sterilized glass containers.",
"Aseptically prepared waters remain stable up to 1 YEAR."]),
("4. Oil Separation (Turbidity / Phase Separation)",
"Excess undissolved oil separates and floats on top if filtration was inadequate.",
"Turbid product; first dose has burning taste from excess oil.",
["Ensure proper filtration with appropriate dispersing agents.",
"Discard first portions of filtrate until clear.",
"Use siliceous earth or pulped filter paper (not fine talc alone)."]),
("5. Terpene Instability / Resinification",
"Terpenes polymerize, oxidize, and form resins over time.",
"Resinous deposits, changed odor/taste, reduced quality.",
["Use terpeneless oils (commercially available).",
"Store away from light and heat."]),
("6. Flavor/Aroma Alteration in Concentrated Waters",
"Small amounts of alcohol in concentrates undergo oxidative degradation.",
"Off-flavors develop; preparation loses its characteristic aroma.",
["Store concentrates sealed, away from light and heat.",
"Use within recommended shelf life."]),
]
for prob, cause, conseq, sols in stab_items:
ps = S("SP", fontSize=10.5, leading=15, fontName="Helvetica-Bold", textColor=WHITE)
cs = S("SC", fontSize=9.5, leading=14, fontName="Helvetica", textColor=DARK_GRAY)
cos = S("CO", fontSize=9.5, leading=14, fontName="Helvetica-Oblique", textColor=HexColor("#8B0000"))
ss = S("SS", fontSize=9.5, leading=14, fontName="Helvetica", textColor=HexColor("#1A5C2A"))
sol_txt = "<br/>".join(f"✔ {s}" for s in sols)
blk = Table([
[Paragraph(prob, ps)],
[Paragraph(f"<b>Cause:</b> {cause}", cs)],
[Paragraph(f"<b>Consequence:</b> {conseq.replace(chr(10),'<br/>')}", cos)],
[Paragraph(f"<b>Solutions:</b><br/>{sol_txt}", ss)],
], colWidths=[16.5*cm])
blk.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), RED_BOX),
("BACKGROUND", (0,1),(-1,-1), HexColor("#FDF6F6")),
("BOX", (0,0),(-1,-1), 1, HexColor("#D0A0A0")),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING", (0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
story.append(KeepTogether([blk, Spacer(1, 8)]))
story.append(PageBreak())
# ── Ch 7: Storage ────────────────────────────────────────────────────────
story.append(chapter_banner("Chapter 7: Storage & Packaging"))
story.append(Spacer(1, 8))
stor_data = [
("Container", "Amber/light-resistant, tightly stoppered glass bottles. Cotton wool stoppers allow minimal air exchange while excluding dust."),
("Light", "PROTECT FROM SUNLIGHT — label in RED INK. Critical for Chloroform Water (oxidizes to toxic phosgene in light)."),
("Temperature", "Store in a cool place — heat accelerates volatilization and oxidation."),
("Shelf Life (Aseptic)", "Up to ONE YEAR when prepared with boiled water + bacterial-retentive filtration into sterilized containers."),
("Filling", "Fill as full as possible to minimize headspace and oxygen exposure."),
("Labeling", '"PROTECT FROM SUNLIGHT" in red ink. Expiry date, storage conditions, batch details.'),
("Concentrates", "Store in tightly sealed containers. Dilute 1:39 with fresh purified water at point of use."),
("Do Not Use If", "Turbid, discolored, unusual/burnt odor, or oil separation is present."),
]
rows = [[Paragraph(f"<b>{t}</b>", S("st", fontSize=10, fontName="Helvetica-Bold", textColor=DARK_GREEN)),
Paragraph(d, S("sd", fontSize=10, leading=14, fontName="Helvetica", textColor=DARK_GRAY))]
for t, d in stor_data]
t = Table(rows, colWidths=[3.5*cm, 13*cm])
t.setStyle(TableStyle([
("ROWBACKGROUNDS", (0,0),(-1,-1), [LIGHT_AMBER, WHITE]),
("GRID", (0,0),(-1,-1), 0.3, HexColor("#D0B060")),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 9),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
story.append(t)
story.append(Spacer(1, 10))
story.append(PageBreak())
# ── Ch 8: Official Examples ──────────────────────────────────────────────
story.append(chapter_banner("Chapter 8: Official Examples of Aromatic Waters"))
story.append(Spacer(1, 8))
examples = [
("Chloroform Water BP", "Simple", "Chloroform (CHCl₃)",
"Double-strength: 0.5 mL chloroform + water q.s. 100 mL",
"Solution method", "Vehicle; expectorant (5-15 mL)",
"PROTECT FROM LIGHT — oxidizes to poisonous PHOSGENE", HexColor("#7B1F1F")),
("Peppermint Water BP", "Simple / Concentrated", "Peppermint oil (Mentha piperita)",
"0.2 mL oil per 1000 mL (simple); 40× alcohol concentrate",
"Solution / Dilution of concentrate", "Flavored vehicle; carminative",
"Store away from light/heat. Terpene oxidation causes off-flavors.", MED_GREEN),
("Rose Water (Strong Rose Water NF)", "Simple (distilled only)", "Rosa damascena fresh petals",
"Saturated aqueous solution of rose oil",
"DISTILLATION ONLY", "Perfume; flavoring; ophthalmic/cosmetic",
"Cannot be prepared by any other method. Store in amber bottles.", HexColor("#8B2252")),
("Orange Flower Water NF", "Simple (distilled only)", "Citrus aurantium fresh flowers",
"Saturated aqueous solution of neroli oil",
"DISTILLATION ONLY", "Flavoring vehicle; perfumery",
"Only by distillation. Sensitive to light and heat.", HexColor("#B8540A")),
("Hamamelis Water (Witch Hazel)", "Simple (distilled only)", "Hamamelis virginiana bark/twigs",
"Aqueous distillate ~14-15% ethanol (from plant)",
"DISTILLATION ONLY", "Astringent; aftershave; Hamamelis 12.5% + Naphazoline 0.01% for eye redness",
"Only by distillation. Natural ethanol content.", HexColor("#4A6B1A")),
("Camphor Water BP", "Simple / Concentrated", "Camphor (crystalline terpenoid)",
"Camphor dissolved in purified water",
"Solution method", "Eye drops (refreshing); rubefacient; cough",
"Toxic in overdose. Store cool and dark.", HexColor("#1A3A6B")),
]
for name, etype, src, comp, method, uses, caution, col in examples:
hs = S("EH", fontSize=11, leading=14, fontName="Helvetica-Bold", textColor=WHITE)
ls = S("EL", fontSize=9.5, leading=14, fontName="Helvetica", textColor=DARK_GRAY)
cs = S("EC", fontSize=9.5, leading=14, fontName="Helvetica-Oblique", textColor=HexColor("#8B0000"))
us = S("EU", fontSize=9.5, leading=14, fontName="Helvetica", textColor=DARK_GREEN)
blk = Table([
[Paragraph(name, hs)],
[Paragraph(f"<b>Type:</b> {etype} | <b>Source:</b> {src}", ls)],
[Paragraph(f"<b>Composition:</b> {comp}", ls)],
[Paragraph(f"<b>Method:</b> {method}", ls)],
[Paragraph(f"<b>Uses:</b> {uses}", us)],
[Paragraph(f"⚠ Caution: {caution}", cs)],
], colWidths=[16.5*cm])
blk.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), col),
("BACKGROUND", (0,1),(-1,-1), LIGHT_GREEN),
("BOX", (0,0),(-1,-1), 1, col),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING", (0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
story.append(KeepTogether([blk, Spacer(1, 8)]))
story.append(PageBreak())
# ── Ch 9: Summary Tables ─────────────────────────────────────────────────
story.append(chapter_banner("Chapter 9: Quick-Reference Summary Tables"))
story.append(Spacer(1, 8))
story.append(section_bar("9.1 Master Summary"))
story.append(make_table(
["Aspect", "Key Points"],
[
["Definition (BP)", "Clear, saturated aqueous solutions of volatile oils/aromatic substances"],
["Nature", "Saturated; very low active concentration; NOT therapeutically potent"],
["Types", "Simple (aqueous) | Concentrated (alcoholic) — dilute 1:39 before use"],
["Methods (Official)", "1. Distillation 2. Solution (Agitation) 3. Dilution of Concentrate"],
["Distillation only", "Rose Water, Orange Flower Water, Hamamelis Water"],
["Solution method", "Peppermint Water, Spearmint Water, Chloroform Water"],
["Dispersing agents", "Purified talc, Siliceous earth, Pulped filter paper (NOT fine talc)"],
["Main stability issues", "Volatilization | Oxidation | Microbial growth | Oil separation | Terpene degradation"],
["Most critical", "Chloroform Water → Phosgene (toxic) in light → AMBER bottles mandatory"],
["Terpeneless oils", "More stable + more water-soluble; terpenes removed by distillation/extraction"],
["Aseptic shelf life", "Up to 1 year with boiled water + bacterial-retentive filtration"],
["Labeling", '"PROTECT FROM SUNLIGHT" in RED INK'],
["Container", "Amber/opaque, tightly stoppered glass bottles"],
["Uses", "Flavored vehicles | Emulsion/suspension phase | Carminative | Astringent | Cosmetic"],
],
[5*cm, 11.5*cm]))
story.append(Spacer(1, 10))
story.append(section_bar("9.2 Syrups vs Aromatic Waters — Key Differences"))
story.append(make_table(
["Feature", "Syrups", "Aromatic Waters"],
[
["Main Solute", "Sucrose (sugar)", "Volatile oil / aromatic substance"],
["Concentration", "Very high (65-85% sugar)", "Very low (saturated, tiny amount)"],
["Therapeutic Potency", "Moderate-high (medicated syrups)", "Not therapeutically potent"],
["Primary Use", "Sweetened vehicle + medicinal", "Flavored vehicle only"],
["Preservative Mechanism", "High osmotic pressure (sugar)", "None inherent"],
["Viscosity", "High (thick, viscous)", "Low (thin, water-like)"],
["Alcohol", "Optional (preservative)", "Simple = none; Concentrated = yes"],
["Storage Label", "No special light warning", "PROTECT FROM SUNLIGHT (red ink)"],
["Key Stability Issue", "Inversion, crystallization, microbial", "Oxidation, volatilization, microbial"],
["Methods", "Heat, Cold agitation, Medicated liquid, Percolation", "Distillation, Solution, Dilution of concentrate"],
],
[4*cm, 6.2*cm, 6.2*cm]))
story.append(Spacer(1, 10))
story.append(PageBreak())
# ── Ch 10: Q&A ───────────────────────────────────────────────────────────
story.append(chapter_banner("Chapter 10: Practice Q & A"))
story.append(Spacer(1, 10))
qa_pairs = [
("Q1. Define aromatic waters (BP).",
"Clear, saturated aqueous solutions of volatile oils or other aromatic/volatile substances, free from solid impurities and empyreumatic odors."),
("Q2. Are aromatic waters therapeutically potent?",
"No — volatile oils have very low water solubility, so even a saturated solution contains only a minute proportion of active substance. They serve primarily as flavored vehicles."),
("Q3. What are the three official methods for preparing aromatic waters?",
"1. Distillation 2. Solution (Agitation) 3. Dilution of Concentrate (alcoholic or surfactant-based)"),
("Q4. Which aromatic waters can ONLY be prepared by distillation?",
"Strong Rose Water NF, Orange Flower Water NF, and Hamamelis Water — all prepared from fresh plant material."),
("Q5. Why is Chloroform Water stored in amber bottles?",
"Chloroform oxidizes in light to form PHOSGENE (COCl₂), a highly toxic gas. Storage in amber (light-resistant) bottles prevents this photodegradation. Label must state 'PROTECT FROM SUNLIGHT' in red ink."),
("Q6. What dispersing agents are used in the solution method? Why is fine talc avoided?",
"Purified talc, siliceous earth, and pulped filter paper. Fine talc is avoided because it is subdivided too finely and passes through filter paper, producing a turbid product."),
("Q7. What are terpeneless oils and why are they preferred?",
"Essential oils with terpene fractions removed by fractional distillation or solvent extraction. Preferred because terpenes are chemically unstable (oxidize, polymerize). Terpeneless oils are more stable and more water-soluble."),
("Q8. How long can aseptically prepared aromatic waters remain stable?",
"Up to ONE YEAR when prepared with recently boiled purified water, filtered through bacterial-retentive filters, stored in sterilized glass containers."),
("Q9. What is the dilution ratio for concentrated aromatic waters?",
"1 part concentrate + 39 parts purified water = 1:39 (1 in 40 volumes total)."),
("Q10. List three key differences between syrups and aromatic waters.",
"1. Sucrose: syrups have high sugar (65-85%); aromatic waters have none.\n2. Preservation: syrups self-preserve osmotically; aromatic waters have no inherent preservative.\n3. Viscosity: syrups are thick; aromatic waters are thin and water-like."),
]
for q, a in qa_pairs:
blk = Table([
[Paragraph(q, qa_q)],
[Paragraph(a.replace("\n","<br/>"), qa_a)],
], colWidths=[16.5*cm])
blk.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), LIGHT_GREEN),
("BACKGROUND", (0,1),(0,-1), WHITE),
("BOX", (0,0),(-1,-1), 0.8, MED_GREEN),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING", (0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 11),
("RIGHTPADDING", (0,0),(-1,-1), 11),
]))
story.append(KeepTogether([blk, Spacer(1, 6)]))
return story
# ── Build ─────────────────────────────────────────────────────────────────────
def build():
doc = SimpleDocTemplate(
OUTPUT_PATH, pagesize=A4,
leftMargin=2*cm, rightMargin=2*cm,
topMargin=2*cm, bottomMargin=2.2*cm,
title="Pharmaceutical Aromatic Waters - Comprehensive Study Guide",
author="Pharmacy Study Guide",
subject="Pharmaceutics - Aromatic Waters",
)
story = build_cover() + build_content()
doc.build(story, onFirstPage=add_page_number, onLaterPages=add_page_number)
print(f"PDF created: {OUTPUT_PATH}")
if __name__ == "__main__":
build()
cd /home/daytona/workspace/syrups-study-guide && python generate_aw_with_diagram…
ls -lh /home/daytona/workspace/syrups-study-guide/Aromatic_Waters_Study_Guide.pd…
Aromatic Waters Study Guide
PDF Document · PDF
explain emulsions briefly acording to pharmaceutics POV
The word comes from the Latin emulgere — "to milk out" (milk itself is a natural O/W emulsion).
| Phase | Also Called | Description |
|---|---|---|
| Dispersed phase | Internal phase, discontinuous phase | The liquid broken into droplets |
| Continuous phase | External phase, dispersion medium | The liquid surrounding the droplets |
| Category | Examples | Type of Emulsion Formed |
|---|---|---|
| Natural (hydrophilic colloids) | Acacia (gum arabic), Tragacanth, Gelatin | O/W |
| Natural (semi-solid) | Beeswax, Wool fat (lanolin), Cholesterol | W/O |
| Synthetic surfactants (non-ionic) | Polysorbates (Tween 20, 80), Spans | O/W (Tween) / W/O (Span) |
| Anionic surfactants | Sodium lauryl sulfate, Sodium stearate (soaps) | O/W |
| Finely divided solids (Pickering) | Bentonite, Magnesium hydroxide | O/W or W/O depending on wettability |
| Problem | What Happens | Cause | Reversible? |
|---|---|---|---|
| Creaming | Globules rise (O/W) or settle (W/O) — two visible layers | Density difference between phases | ✔ Yes (shake to redisperse) |
| Flocculation | Globules form loose aggregates/clusters | Reduced zeta potential; electrolyte addition | ✔ Yes |
| Coalescence | Globules merge to form larger droplets | Film rupture around droplets | ✗ No |
| Cracking (Breaking) | Complete separation into two distinct layers — emulsion destroyed | Coalescence proceeding to completion | ✗ No |
| Phase inversion | O/W converts to W/O or vice versa | Change in emulsifying agent, temperature, or phase ratio | ✗ Usually no |
| Ostwald Ripening | Small droplets shrink, large ones grow | Diffusion of dispersed phase through continuous phase | ✗ No |
Creaming and flocculation are reversible. Coalescence and cracking are irreversible — the emulsion is permanently broken.
| Test | O/W Result | W/O Result |
|---|---|---|
| Dilution test | Miscible with water | Miscible with oil |
| Conductivity test | Conducts electricity (water outside) | Non-conductor |
| Dye test — Methylene blue (water-soluble) | Whole emulsion turns blue | Only droplets turn blue |
| Dye test — Sudan III (oil-soluble) | Only droplets stain red | Whole emulsion turns red |
| Filter paper test | Spreads (water wets paper) | Does not spread (oil repels water) |
| Feature | O/W | W/O |
|---|---|---|
| External phase | Water | Oil |
| Feel | Non-greasy | Greasy |
| Dye (methylene blue) | Whole turns blue | Droplets only |
| Common use | Oral, IV, vanishing creams | Cold cream, barrier cream |
| Emulsifier HLB | 8–18 | 3–6 |
also include stability problems
Creaming / Sedimentation
↓
Flocculation
↓
Coalescence
↓
Cracking (Breaking) ← point of no return
| Feature | Detail |
|---|---|
| Definition | Upward migration of oil globules (O/W) or downward settling (W/O) forming two visible layers — but globules remain intact |
| Cause | Density difference between dispersed and continuous phases (Stokes' Law) |
| Reversibility | ✔ Reversible — gentle shaking redisperses globules |
| Problem | Leads to non-uniform dosing if not shaken before use |
V = 2r²(ρ₁ - ρ₂)g / 9η
| Feature | Detail |
|---|---|
| Definition | Globules aggregate into loose clusters (flocs) but do NOT merge — individual droplets still intact |
| Cause | Reduction in zeta potential (electrical repulsion between globules decreases); addition of electrolytes; pH change |
| Reversibility | ✔ Reversible — gentle agitation breaks up flocs |
| Problem | Precursor to coalescence if not reversed; non-uniform appearance |
| Feature | Detail |
|---|---|
| Definition | Flocculated globules merge together to form progressively larger droplets |
| Cause | Rupture of the interfacial film (emulsifier layer) around globules |
| Reversibility | ✗ Irreversible — once droplets merge, they cannot be broken apart by simple shaking |
| Problem | Directly leads to cracking; very large droplets visible |
| Feature | Detail |
|---|---|
| Definition | Complete, irreversible separation of the emulsion into two distinct bulk liquid layers |
| Cause | Coalescence proceeding to its endpoint; destruction of emulsifier |
| Reversibility | ✗ Permanently broken — cannot be restored by shaking |
| Problem | Emulsion is completely ruined and must be discarded |
| Feature | Detail |
|---|---|
| Definition | The emulsion type changes — O/W converts to W/O or vice versa |
| Cause | Change in phase volume ratio beyond critical point; change in temperature; addition of electrolytes; change or replacement of emulsifying agent |
| Reversibility | ✗ Usually irreversible or requires complete re-emulsification |
| Problem | Completely changes the pharmaceutical properties, appearance, and drug release behavior |
| Feature | Detail |
|---|---|
| Definition | Small droplets gradually dissolve and the material deposits onto larger droplets — large droplets grow, small ones disappear |
| Cause | Difference in chemical potential (Laplace pressure) between small and large droplets — small droplets have higher solubility in the continuous phase |
| Reversibility | ✗ Irreversible |
| Problem | Increases mean droplet size over time; destabilizes emulsion |
| Feature | Detail |
|---|---|
| Definition | Growth of bacteria, yeast, or molds — especially in O/W emulsions (aqueous external phase supports growth) |
| Cause | No inherent antimicrobial protection; water activity of continuous phase supports microbial growth |
| Consequence | Decomposition of emulsifier (especially natural ones like acacia, gelatin) → cracking; off-odors; patient safety risk |
| Reversibility | ✗ Irreversible damage |
| Problem | Globules Intact? | Reversible? | Stage |
|---|---|---|---|
| Creaming | ✔ Yes | ✔ Yes | Early |
| Flocculation | ✔ Yes (not merged) | ✔ Yes | Early-Mid |
| Coalescence | ✗ Merging | ✗ No | Late |
| Cracking | ✗ Fully separated | ✗ No | Final |
| Phase Inversion | ✗ Type changed | ✗ Usually no | Any |
| Ostwald Ripening | ✗ Size changing | ✗ No | Gradual |
| Microbial | Emulsifier destroyed | ✗ No | Any |
make a pdf using this data and previous answer data
~/syrups-study-guide/generate_emulsions_pdf.py
"""
Pharmaceutical Emulsions — Comprehensive Study Guide PDF
Covers: Definition, Types, Phases, Emulsifying Agents, HLB, Methods of Preparation,
Identification Tests, Stability Problems (detailed), Uses, Q&A
Includes vector flowchart diagrams for stability progression and preparation methods.
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.units import cm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.lib.colors import HexColor
from reportlab.graphics.shapes import (
Drawing, Rect, String, Line, Polygon, Circle, Group
)
from reportlab.platypus import Flowable
OUTPUT = "/home/daytona/workspace/syrups-study-guide/Emulsions_Study_Guide.pdf"
# ── Palette ───────────────────────────────────────────────────────────────────
DARK_BLUE = HexColor("#1A2E5A")
MED_BLUE = HexColor("#2B5BA8")
LIGHT_BLUE = HexColor("#D6E4F7")
STEEL_BLUE = HexColor("#3A72B0")
ACCENT_GOLD = HexColor("#D97706")
LIGHT_GOLD = HexColor("#FEF3C7")
ACCENT_RED = HexColor("#C0392B")
LIGHT_RED = HexColor("#FDECEA")
ACCENT_GREEN = HexColor("#1A7A4A")
LIGHT_GREEN = HexColor("#D4EFE1")
ACCENT_TEAL = HexColor("#0E6B6B")
LIGHT_TEAL = HexColor("#CCECEC")
WHITE = colors.white
LIGHT_GRAY = HexColor("#F4F6F8")
MED_GRAY = HexColor("#7A8A99")
DARK_GRAY = HexColor("#2D2D2D")
TABLE_HEADER = HexColor("#1A2E5A")
TABLE_ODD = HexColor("#EBF0FB")
TABLE_EVEN = WHITE
PURPLE = HexColor("#5A2D82")
LIGHT_PURPLE = HexColor("#EDE4F7")
# ── Style factory ─────────────────────────────────────────────────────────────
def S(name, **kw):
return ParagraphStyle(name, **kw)
cover_title = S("CT", fontSize=34, leading=42, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)
cover_sub = S("CS", fontSize=16, leading=22, textColor=HexColor("#B8CCF0"), fontName="Helvetica", alignment=TA_CENTER)
cover_info = S("CI", fontSize=11, leading=16, textColor=HexColor("#90AADC"), fontName="Helvetica", alignment=TA_CENTER)
chap_title = S("ChT", fontSize=18, leading=24, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_LEFT)
body = S("Bd", fontSize=10, leading=15, textColor=DARK_GRAY, fontName="Helvetica", spaceBefore=3, spaceAfter=3, alignment=TA_JUSTIFY)
bullet_s = S("Bl", fontSize=10, leading=14, textColor=DARK_GRAY, fontName="Helvetica", leftIndent=16, spaceBefore=2, spaceAfter=2)
note_s = S("Nt", fontSize=9.5, leading=14, textColor=HexColor("#1A2860"), fontName="Helvetica-Oblique", leftIndent=10, rightIndent=10)
sub_h = S("SH", fontSize=11, leading=15, textColor=MED_BLUE, fontName="Helvetica-Bold", spaceBefore=8, spaceAfter=3)
diag_cap = S("DC", fontSize=9.5, leading=13, fontName="Helvetica-Bold", textColor=DARK_BLUE, alignment=TA_CENTER, spaceBefore=4, spaceAfter=6)
qa_q = S("QQ", fontSize=10.5, leading=15, fontName="Helvetica-Bold", textColor=DARK_BLUE)
qa_a = S("QA", fontSize=10, leading=14, fontName="Helvetica", textColor=DARK_GRAY, leftIndent=10)
formula_s = S("FM", fontSize=10, leading=16, fontName="Helvetica-Bold", textColor=DARK_BLUE, alignment=TA_CENTER, spaceBefore=4, spaceAfter=4)
# ── Layout helpers ────────────────────────────────────────────────────────────
def chapter_banner(text):
t = Table([[Paragraph(text, chap_title)]], colWidths=[17*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), DARK_BLUE),
("ROUNDEDCORNERS",[6]),
("TOPPADDING", (0,0),(-1,-1), 10),
("BOTTOMPADDING", (0,0),(-1,-1), 10),
("LEFTPADDING", (0,0),(-1,-1), 14),
("RIGHTPADDING", (0,0),(-1,-1), 14),
]))
return t
def section_bar(text):
s = S("SB", fontSize=13, leading=18, textColor=DARK_BLUE,
fontName="Helvetica-Bold", spaceBefore=0, spaceAfter=0)
t = Table([[Paragraph(text, s)]], colWidths=[16.5*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), LIGHT_BLUE),
("LINEBEFOREEACH",(0,0),(0,-1), 4, MED_BLUE),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING", (0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
return t
def colored_box(text, bg, border, style=None):
st = style if style else note_s
t = Table([[Paragraph(text, st)]], colWidths=[16.5*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), bg),
("BOX", (0,0),(-1,-1), 1, border),
("TOPPADDING", (0,0),(-1,-1), 8),
("BOTTOMPADDING", (0,0),(-1,-1), 8),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
return t
def make_table(headers, rows, col_widths):
hs = S("H", fontSize=10, leading=14, fontName="Helvetica-Bold", textColor=WHITE, alignment=TA_CENTER)
cs = S("C", fontSize=9.5, leading=13, fontName="Helvetica", textColor=DARK_GRAY)
data = [[Paragraph(str(h), hs) for h in headers]]
for row in rows:
data.append([Paragraph(str(c), cs) for c in row])
t = Table(data, colWidths=col_widths)
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), TABLE_HEADER),
("ROWBACKGROUNDS",(0,1),(-1,-1), [TABLE_ODD, TABLE_EVEN]),
("GRID", (0,0),(-1,-1), 0.4, HexColor("#90A8D0")),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 7),
("RIGHTPADDING", (0,0),(-1,-1), 7),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]))
return t
def add_page_number(canvas, doc):
canvas.saveState()
canvas.setFillColor(DARK_BLUE)
canvas.rect(0, 0, A4[0], 22, fill=1, stroke=0)
canvas.setFillColor(WHITE)
canvas.setFont("Helvetica", 8)
canvas.drawString(2*cm, 7, "Pharmaceutical Emulsions - Comprehensive Study Guide")
canvas.drawRightString(A4[0]-2*cm, 7, f"Page {doc.page}")
canvas.restoreState()
# ════════════════════════════════════════════════════════════════════════════
# DIAGRAM FLOWABLE
# ════════════════════════════════════════════════════════════════════════════
class DiagramFlowable(Flowable):
def __init__(self, drawing):
super().__init__()
self.drawing = drawing
self.width = drawing.width
self.height = drawing.height
def draw(self):
self.drawing.drawOn(self.canv, 0, 0)
def wrap(self, aw, ah):
return self.width, self.height
def _box(d, x, y, w, h, fill, text, fsize=8.5, tc=colors.white, bold=False, radius=5):
d.add(Rect(x, y, w, h, rx=radius, ry=radius,
fillColor=fill, strokeColor=colors.white, strokeWidth=1.2))
font = "Helvetica-Bold" if bold else "Helvetica"
lines = text.split("\n")
lh = fsize * 1.4
sy = y + h/2 + (len(lines)*lh)/2 - lh*0.8
for ln in lines:
d.add(String(x+w/2, sy, ln, fontName=font, fontSize=fsize,
fillColor=tc, textAnchor="middle"))
sy -= lh
def _arrow_d(d, x, y, length=20, color=HexColor("#2B5BA8")):
d.add(Line(x, y, x, y-length+7, strokeColor=color, strokeWidth=1.8))
d.add(Polygon([x-5, y-length+8, x+5, y-length+8, x, y-length],
fillColor=color, strokeColor=color, strokeWidth=0))
def _arrow_r(d, x, y, length=30, color=HexColor("#2B5BA8")):
d.add(Line(x, y, x+length-7, y, strokeColor=color, strokeWidth=1.8))
d.add(Polygon([x+length-8, y+5, x+length-8, y-5, x+length, y],
fillColor=color, strokeColor=color, strokeWidth=0))
# ── DIAGRAM 1: Stability Progression ─────────────────────────────────────────
def diagram_stability_cascade():
W, H = 520, 420
d = Drawing(W, H)
d.add(Rect(0, 0, W, H, fillColor=HexColor("#F0F4FC"),
strokeColor=MED_BLUE, strokeWidth=1.5))
d.add(Rect(0, H-38, W, 38, fillColor=DARK_BLUE,
strokeColor=DARK_BLUE, strokeWidth=0))
d.add(String(W/2, H-24, "EMULSION INSTABILITY PROGRESSION CASCADE",
fontName="Helvetica-Bold", fontSize=11,
fillColor=WHITE, textAnchor="middle"))
stages = [
(HexColor("#2B6CB0"), "CREAMING / SEDIMENTATION\nGlobules migrate up (O/W) or down (W/O)\n✔ REVERSIBLE — shake to redisperse"),
(HexColor("#D97706"), "FLOCCULATION\nGlobules form loose clusters/aggregates\nbut remain individual droplets\n✔ REVERSIBLE — gentle agitation"),
(HexColor("#C05621"), "COALESCENCE\nGlobule membranes rupture — droplets MERGE\ninto progressively larger ones\n✗ IRREVERSIBLE"),
(HexColor("#C0392B"), "CRACKING (BREAKING)\nComplete separation into two bulk layers\nEmulsion permanently destroyed\n✗ IRREVERSIBLE — discard"),
]
bw, bh = 340, 52
bx = (W - bw)/2
top_y = H - 56
gap = 18
for i, (col, txt) in enumerate(stages):
y = top_y - i*(bh+gap)
_box(d, bx, y-bh, bw, bh, col, txt, fsize=8.2)
if i < len(stages)-1:
_arrow_d(d, W/2, y-bh, length=gap)
# Reversible bracket
rev_x = bx + bw + 8
rev_top = top_y
rev_bot = top_y - (bh+gap) - bh
d.add(Line(rev_x, rev_top, rev_x+8, rev_top, strokeColor=HexColor("#2B6CB0"), strokeWidth=1.5))
d.add(Line(rev_x, rev_bot, rev_x+8, rev_bot, strokeColor=HexColor("#2B6CB0"), strokeWidth=1.5))
d.add(Line(rev_x+8, rev_top, rev_x+8, rev_bot, strokeColor=HexColor("#2B6CB0"), strokeWidth=1.5))
d.add(String(rev_x+12, (rev_top+rev_bot)/2, "Reversible",
fontName="Helvetica-Bold", fontSize=8,
fillColor=HexColor("#2B6CB0"), textAnchor="start"))
# Irreversible bracket
irr_top = top_y - 2*(bh+gap)
irr_bot = top_y - 3*(bh+gap) - bh
d.add(Line(rev_x, irr_top, rev_x+8, irr_top, strokeColor=ACCENT_RED, strokeWidth=1.5))
d.add(Line(rev_x, irr_bot, rev_x+8, irr_bot, strokeColor=ACCENT_RED, strokeWidth=1.5))
d.add(Line(rev_x+8, irr_top, rev_x+8, irr_bot, strokeColor=ACCENT_RED, strokeWidth=1.5))
d.add(String(rev_x+12, (irr_top+irr_bot)/2+4, "Irreversible",
fontName="Helvetica-Bold", fontSize=8,
fillColor=ACCENT_RED, textAnchor="start"))
d.add(String(rev_x+12, (irr_top+irr_bot)/2-8, "Point of No Return",
fontName="Helvetica", fontSize=7.5,
fillColor=ACCENT_RED, textAnchor="start"))
return DiagramFlowable(d)
# ── DIAGRAM 2: O/W vs W/O comparison ─────────────────────────────────────────
def diagram_ow_wo():
W, H = 500, 280
d = Drawing(W, H)
d.add(Rect(0, 0, W, H, fillColor=HexColor("#F4F7FC"),
strokeColor=MED_BLUE, strokeWidth=1.5))
d.add(Rect(0, H-36, W, 36, fillColor=DARK_BLUE,
strokeColor=DARK_BLUE, strokeWidth=0))
d.add(String(W/2, H-22, "OIL-IN-WATER (O/W) vs WATER-IN-OIL (W/O) EMULSIONS",
fontName="Helvetica-Bold", fontSize=11,
fillColor=WHITE, textAnchor="middle"))
# O/W side
ow_cx, ow_cy = 125, 130
# Blue water background circle
d.add(Circle(ow_cx, ow_cy, 80, fillColor=HexColor("#AACCFF"),
strokeColor=MED_BLUE, strokeWidth=1.5))
d.add(String(ow_cx, ow_cy+88, "O/W (Oil-in-Water)",
fontName="Helvetica-Bold", fontSize=9,
fillColor=DARK_BLUE, textAnchor="middle"))
# Oil droplets (yellow) inside water
for (ox, oy, r) in [(115, 145, 18), (145, 118, 14), (100, 118, 12),
(130, 155, 10), (110, 100, 9), (150, 145, 11)]:
d.add(Circle(ow_cx-125+ox+58, ow_cy-130+oy+58, r,
fillColor=HexColor("#F6D860"),
strokeColor=HexColor("#B8A000"), strokeWidth=0.8))
# Labels
d.add(String(ow_cx, ow_cy-94, "Water = External phase",
fontName="Helvetica", fontSize=8,
fillColor=MED_BLUE, textAnchor="middle"))
d.add(String(ow_cx, ow_cy-106, "Oil droplets = Internal phase",
fontName="Helvetica", fontSize=8,
fillColor=HexColor("#8B6A00"), textAnchor="middle"))
# W/O side
wo_cx, wo_cy = 375, 130
d.add(Circle(wo_cx, wo_cy, 80, fillColor=HexColor("#F6D860"),
strokeColor=HexColor("#B8A000"), strokeWidth=1.5))
d.add(String(wo_cx, wo_cy+88, "W/O (Water-in-Oil)",
fontName="Helvetica-Bold", fontSize=9,
fillColor=DARK_BLUE, textAnchor="middle"))
# Water droplets (blue) inside oil
for (ox, oy, r) in [(115, 145, 18), (145, 118, 14), (100, 118, 12),
(130, 155, 10), (110, 100, 9), (150, 145, 11)]:
d.add(Circle(wo_cx-125+ox+58, wo_cy-130+oy+58, r,
fillColor=HexColor("#AACCFF"),
strokeColor=MED_BLUE, strokeWidth=0.8))
d.add(String(wo_cx, wo_cy-94, "Oil = External phase",
fontName="Helvetica", fontSize=8,
fillColor=HexColor("#8B6A00"), textAnchor="middle"))
d.add(String(wo_cx, wo_cy-106, "Water droplets = Internal phase",
fontName="Helvetica", fontSize=8,
fillColor=MED_BLUE, textAnchor="middle"))
# VS divider
d.add(Line(W/2, 20, W/2, H-44, strokeColor=MED_GRAY, strokeWidth=1,
strokeDashArray=[4,3]))
d.add(Rect(W/2-18, H/2-14, 36, 28, fillColor=DARK_BLUE,
strokeColor=DARK_BLUE, strokeWidth=0))
d.add(String(W/2, H/2-2, "VS",
fontName="Helvetica-Bold", fontSize=11,
fillColor=WHITE, textAnchor="middle"))
return DiagramFlowable(d)
# ── DIAGRAM 3: Methods of Preparation ─────────────────────────────────────────
def diagram_prep_methods():
W, H = 520, 360
d = Drawing(W, H)
d.add(Rect(0, 0, W, H, fillColor=HexColor("#F4F7FC"),
strokeColor=MED_BLUE, strokeWidth=1.5))
d.add(Rect(0, H-38, W, 38, fillColor=DARK_BLUE,
strokeColor=DARK_BLUE, strokeWidth=0))
d.add(String(W/2, H-24, "METHODS OF EMULSION PREPARATION — OVERVIEW",
fontName="Helvetica-Bold", fontSize=11,
fillColor=WHITE, textAnchor="middle"))
# Central start box
_box(d, W/2-80, H-80, 160, 34, MED_BLUE, "SELECT PREPARATION METHOD", fsize=8.5, bold=True)
# Four method boxes arranged below
methods = [
(50, "Dry Gum\nMethod\n(4:2:1)", HexColor("#1A5C8A")),
(185, "Wet Gum\nMethod\n(4:2:1)", HexColor("#2E7D52")),
(320, "Bottle\nMethod", HexColor("#7B3F00")),
(390, "Machine /\nHomogenizer", HexColor("#5A1A7A")),
]
# Draw connecting lines from central box
centre_bx = W/2
centre_by = H - 80
col_bw, col_bh = 108, 70
branch_y = H - 160
xs = [50, 170, 295, 405]
colors_m = [HexColor("#1A5C8A"), HexColor("#2E7D52"),
HexColor("#7B3F00"), HexColor("#5A1A7A")]
labels = [
"Dry Gum\nMethod\n(4:2:1 ratio)",
"Wet Gum\nMethod\n(4:2:1 ratio)",
"Bottle\nMethod\n(volatile oils)",
"Machine /\nHomogenizer\n(industrial)",
]
details = [
"Acacia+oil dry\n→ add water at once\n→ triturate → primary emulsion",
"Acacia mucilage first\n→ add oil gradually\n→ triturate",
"Gum in dry bottle\n→ add water → shake\n→ dilute",
"Colloid mill /\nUltrasonic / HPH\n→ fine uniform globules",
]
for i, (bx, col, lbl, det) in enumerate(zip(xs, colors_m, labels, details)):
# Line from centre
d.add(Line(centre_bx, centre_by,
bx + col_bw/2, branch_y + col_bh,
strokeColor=col, strokeWidth=1.2))
_box(d, bx, branch_y, col_bw, col_bh, col, lbl, fsize=8)
# Detail box below
_box(d, bx, branch_y - 88, col_bw, 82, HexColor("#E8EEF8"), det,
fsize=7.5, tc=DARK_GRAY)
_arrow_d(d, bx + col_bw/2, branch_y, length=14, color=col)
return DiagramFlowable(d)
# ── DIAGRAM 4: HLB Scale ──────────────────────────────────────────────────────
def diagram_hlb():
W, H = 500, 130
d = Drawing(W, H)
d.add(Rect(0, 0, W, H, fillColor=HexColor("#F4F7FC"),
strokeColor=MED_BLUE, strokeWidth=1.2))
d.add(String(W/2, H-16, "HLB SCALE — Selecting the Right Emulsifier",
fontName="Helvetica-Bold", fontSize=10,
fillColor=DARK_BLUE, textAnchor="middle"))
bar_y, bar_h = 52, 22
# Gradient-like HLB bar: W/O region (yellow) → transition → O/W region (blue)
zones = [
(20, 80, HexColor("#F6C030"), "W/O\n3–6"),
(100, 60, HexColor("#CCAA20"), "W/O\npreferred"),
(160, 60, HexColor("#8A9AB0"), "Wetting\nagents\n7–9"),
(220, 120, HexColor("#3A72B0"), "O/W\npreferred"),
(340, 80, HexColor("#1A3A8A"), "O/W\n8–18"),
(420, 60, HexColor("#0A1A4A"), "Solubilizers\n>15"),
]
for (x, w, col, lbl) in zones:
d.add(Rect(x, bar_y, w, bar_h, fillColor=col,
strokeColor=WHITE, strokeWidth=0.5))
lines = lbl.split("\n")
ly = bar_y - 8 - (len(lines)-1)*9
for ln in lines:
d.add(String(x+w/2, ly, ln, fontName="Helvetica", fontSize=7,
fillColor=DARK_GRAY, textAnchor="middle"))
ly -= 9
# Scale ticks
for val in [0, 3, 6, 9, 12, 15, 18, 20]:
px = 20 + val * (460/20)
d.add(Line(px, bar_y, px, bar_y+bar_h,
strokeColor=WHITE, strokeWidth=0.8))
d.add(String(px, bar_y + bar_h + 4, str(val),
fontName="Helvetica", fontSize=7,
fillColor=DARK_BLUE, textAnchor="middle"))
d.add(String(W/2, 10, "← More Lipophilic (W/O) More Hydrophilic (O/W) →",
fontName="Helvetica-Oblique", fontSize=8,
fillColor=MED_GRAY, textAnchor="middle"))
return DiagramFlowable(d)
def centre_diagram(diag):
t = Table([[diag]], colWidths=[17*cm])
t.setStyle(TableStyle([
("ALIGN", (0,0),(-1,-1), "CENTER"),
("TOPPADDING", (0,0),(-1,-1), 0),
("BOTTOMPADDING", (0,0),(-1,-1), 0),
("LEFTPADDING", (0,0),(-1,-1), 0),
("RIGHTPADDING", (0,0),(-1,-1), 0),
]))
return t
# ════════════════════════════════════════════════════════════════════════════
# COVER
# ════════════════════════════════════════════════════════════════════════════
def build_cover():
story = []
cb = Table([
[Paragraph("PHARMACEUTICAL<br/>EMULSIONS", cover_title)],
[Spacer(1, 6)],
[Paragraph("Comprehensive Study Guide", cover_sub)],
[Spacer(1, 10)],
[Paragraph("Definition | Types | Emulsifying Agents | HLB | Methods | Identification | Stability | Uses", cover_info)],
], colWidths=[17*cm])
cb.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), DARK_BLUE),
("TOPPADDING", (0,0),(-1,-1), 28),
("BOTTOMPADDING", (0,0),(-1,-1), 28),
("LEFTPADDING", (0,0),(-1,-1), 20),
("RIGHTPADDING", (0,0),(-1,-1), 20),
]))
story.append(cb)
story.append(Spacer(1, 18))
qf_s = S("QF", fontSize=10, leading=14, fontName="Helvetica-Bold",
textColor=DARK_BLUE, alignment=TA_CENTER)
qf = [[Paragraph(c.replace("\n","<br/>"), qf_s) for c in [
"2 Main Types\nO/W and W/O",
"4 Methods of\nPreparation",
"Thermodynamically\nUnstable System",
"7 Stability\nProblems",
]]]
qft = Table(qf, colWidths=[4.1*cm]*4)
qft.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), LIGHT_GOLD),
("BOX", (0,0),(-1,-1), 1, ACCENT_GOLD),
("INNERGRID", (0,0),(-1,-1), 0.5, ACCENT_GOLD),
("TOPPADDING", (0,0),(-1,-1), 10),
("BOTTOMPADDING", (0,0),(-1,-1), 10),
]))
story.append(qft)
story.append(Spacer(1, 18))
toc_h = S("TH", fontSize=13, leading=18, fontName="Helvetica-Bold", textColor=DARK_BLUE)
toc_i = S("TI", fontSize=10, leading=16, fontName="Helvetica", textColor=DARK_GRAY, leftIndent=10)
chapters = [
"1. Definition & Key Concepts",
"2. Types of Emulsions",
"3. Composition / Formulation Components",
"4. Emulsifying Agents & HLB System",
"5. Methods of Preparation",
"6. Identification of Emulsion Type",
"7. Stability Problems (Detailed)",
"8. Stability Enhancement Strategies",
"9. Pharmaceutical Uses",
"10. Quick-Reference Summary Tables",
"11. Practice Q & A",
]
toc_rows = [[Paragraph("CONTENTS", toc_h)]] + [[Paragraph(c, toc_i)] for c in chapters]
toc_t = Table(toc_rows, colWidths=[17*cm])
toc_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), LIGHT_BLUE),
("LINEAFTER", (0,0),(0,-1), 3, MED_BLUE),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 12),
]))
story.append(toc_t)
story.append(Spacer(1, 14))
story.append(Paragraph(
"Prepared for Pharmacy Students | July 2026 | Based on BP/USP/IP Pharmacopoeia Standards",
S("Cr", fontSize=8.5, leading=12, fontName="Helvetica-Oblique",
textColor=MED_GRAY, alignment=TA_CENTER)))
story.append(PageBreak())
return story
# ════════════════════════════════════════════════════════════════════════════
# CONTENT
# ════════════════════════════════════════════════════════════════════════════
def build_content():
story = []
# ── Ch 1: Definition ─────────────────────────────────────────────────────
story.append(chapter_banner("Chapter 1: Definition & Key Concepts"))
story.append(Spacer(1, 10))
story.append(section_bar("1.1 Definition"))
story.append(Paragraph(
"An emulsion is a <b>heterogeneous, thermodynamically unstable, two-phase liquid dosage form</b> "
"in which one immiscible liquid (the <b>dispersed/internal phase</b>) is broken into fine globules "
"and uniformly distributed throughout another liquid (the <b>continuous/external phase</b>), "
"stabilized by an <b>emulsifying agent (emulgent)</b>.",
body))
story.append(Spacer(1, 6))
story.append(colored_box(
"<b>Etymology:</b> From the Latin <i>emulgere</i> — \"to milk out.\" "
"Milk is the classic example of a natural O/W emulsion — fat globules dispersed in an aqueous serum.",
LIGHT_BLUE, MED_BLUE))
story.append(Spacer(1, 8))
story.append(section_bar("1.2 The Two Phases"))
story.append(make_table(
["Phase", "Synonym(s)", "Description"],
[
["Dispersed Phase", "Internal phase, discontinuous phase", "The liquid broken into fine droplets/globules"],
["Continuous Phase", "External phase, dispersion medium", "The liquid that surrounds and carries the droplets"],
],
[4*cm, 5.5*cm, 7*cm]))
story.append(Spacer(1, 8))
story.append(colored_box(
"<b>Key Rule:</b> An emulsifying agent is <b>always required</b> to stabilize an emulsion. "
"Without it, the two phases immediately separate (\"breaking\"). The emulsifier reduces "
"interfacial tension and forms a protective film around each droplet.",
LIGHT_GOLD, ACCENT_GOLD))
story.append(Spacer(1, 10))
# ── Ch 2: Types ──────────────────────────────────────────────────────────
story.append(chapter_banner("Chapter 2: Types of Emulsions"))
story.append(Spacer(1, 10))
story.append(section_bar("2.1 O/W and W/O — Visual Diagram"))
story.append(Spacer(1, 6))
story.append(centre_diagram(diagram_ow_wo()))
story.append(Paragraph("Figure 1: Schematic representation of O/W vs W/O emulsion types", diag_cap))
story.append(Spacer(1, 8))
story.append(section_bar("2.2 Classification of Emulsions"))
story.append(make_table(
["Type", "Dispersed Phase", "Continuous Phase", "Feel/Appearance", "Common Examples"],
[
["O/W (Oil-in-Water)", "Oil", "Water", "Non-greasy, water-miscible", "Cod liver oil emulsion, IV lipid emulsions, vanishing cream"],
["W/O (Water-in-Oil)", "Water", "Oil", "Greasy, oily feel", "Cold cream, butter, barrier creams"],
["W/O/W (Multiple)", "Water (inner) + Oil", "Water (outer)", "Complex; sustained release", "Vaccine adjuvants, controlled drug delivery"],
["O/W/O (Multiple)", "Oil (inner) + Water", "Oil (outer)", "Complex", "Experimental drug delivery"],
["Microemulsion", "Oil or Water", "Water or Oil", "Clear/translucent, stable", "SEDDS, lipid-based oral drug delivery"],
],
[2.8*cm, 3*cm, 3*cm, 3.5*cm, 5.2*cm]))
story.append(Spacer(1, 8))
story.append(colored_box(
"<b>Microemulsion vs Emulsion:</b> Unlike conventional emulsions, microemulsions are "
"<b>thermodynamically stable</b>, optically clear or translucent, and form spontaneously. "
"Droplet size is 10–100 nm (vs 0.1–100 µm in conventional emulsions). They require a "
"high concentration of surfactant (and often a co-surfactant).",
LIGHT_TEAL, ACCENT_TEAL))
story.append(Spacer(1, 10))
story.append(PageBreak())
# ── Ch 3: Composition ────────────────────────────────────────────────────
story.append(chapter_banner("Chapter 3: Composition / Formulation Components"))
story.append(Spacer(1, 10))
story.append(make_table(
["Component", "Role", "Examples"],
[
["Oil Phase", "Dispersed or continuous phase depending on type", "Fixed oils: arachis, olive, corn, liquid paraffin; volatile oils"],
["Aqueous Phase", "Dispersed or continuous phase depending on type", "Purified water; aromatic waters"],
["Emulsifying Agent", "Reduces interfacial tension; stabilizes globules", "Acacia, Tween, Span, Lecithin, Sodium stearate"],
["Preservatives", "Prevent microbial contamination (critical in O/W)", "Chlorocresol, Parabens, Benzalkonium chloride"],
["Antioxidants", "Prevent rancidity of oil phase", "BHA, BHT, Tocopherols, Sodium metabisulfite"],
["Sweeteners / Flavors", "Improve palatability of oral emulsions", "Sucrose syrup, Saccharin, Peppermint oil"],
["Viscosity enhancers", "Slow creaming (increase continuous phase viscosity)", "Tragacanth, CMC, Carbomer, Xanthan gum"],
["Buffers", "Maintain pH for stability of API and emulsifier", "Citrate, Phosphate buffers"],
["Active Pharmaceutical Ingredient", "Therapeutic effect", "Oil-soluble vitamins (A, D, E, K), Propofol"],
],
[3.5*cm, 5*cm, 8*cm]))
story.append(Spacer(1, 10))
# ── Ch 4: Emulsifying Agents & HLB ──────────────────────────────────────
story.append(chapter_banner("Chapter 4: Emulsifying Agents & HLB System"))
story.append(Spacer(1, 10))
story.append(section_bar("4.1 Classification of Emulsifying Agents"))
story.append(make_table(
["Category", "Examples", "Type Formed", "Mechanism"],
[
["Natural — Hydrophilic Colloids", "Acacia (gum arabic), Tragacanth, Gelatin, Pectin", "O/W", "Form multi-molecular film around oil droplets"],
["Natural — Semi-solid", "Beeswax, Wool fat (Lanolin), Cholesterol, Cetyl alcohol", "W/O", "Absorb water; form W/O emulsions"],
["Synthetic — Non-ionic (HLB > 8)", "Polysorbates (Tween 20, 40, 60, 80)", "O/W", "Hydrophilic; surround oil droplets"],
["Synthetic — Non-ionic (HLB 3–6)", "Sorbitan esters (Span 20, 40, 60, 80)", "W/O", "Lipophilic; stabilize W/O systems"],
["Synthetic — Anionic", "Sodium lauryl sulfate, Sodium stearate (soaps)", "O/W", "Negative charge on droplets → repulsion"],
["Synthetic — Cationic", "Cetrimide (CTAB), Benzalkonium chloride", "O/W", "Positive charge; also antimicrobial"],
["Finely Divided Solids (Pickering)", "Bentonite, Mg(OH)₂, Silica", "O/W or W/O (depends on wettability)", "Adsorb at oil-water interface"],
["Phospholipids", "Lecithin (egg/soy), Phosphatidylcholine", "O/W", "Forms bilayer film; used in IV emulsions"],
],
[3.5*cm, 4.5*cm, 2.5*cm, 6*cm]))
story.append(Spacer(1, 10))
story.append(section_bar("4.2 HLB System (Hydrophilic-Lipophilic Balance)"))
story.append(Paragraph(
"The <b>HLB value</b> is a numerical scale (0–20) that quantifies the relative affinity of "
"a surfactant for water vs oil. It guides selection of the correct emulsifier for the desired "
"emulsion type.",
body))
story.append(Spacer(1, 6))
story.append(centre_diagram(diagram_hlb()))
story.append(Paragraph("Figure 2: HLB Scale — Emulsifier selection guide", diag_cap))
story.append(Spacer(1, 6))
story.append(make_table(
["HLB Range", "Application", "Examples"],
[
["1–3", "Antifoaming agents", "—"],
["3–6", "W/O emulsifiers", "Span 80 (HLB 4.3), Span 60 (HLB 4.7)"],
["7–9", "Wetting/spreading agents", "Span 20 (HLB 8.6)"],
["8–18", "O/W emulsifiers", "Tween 80 (HLB 15), Tween 20 (HLB 16.7), Acacia (~8)"],
["> 15", "Solubilizers / detergents", "Tween 20, Sodium lauryl sulfate"],
],
[3*cm, 5.5*cm, 9*cm]))
story.append(Spacer(1, 8))
story.append(colored_box(
"<b>Required HLB:</b> Each oil has a specific Required HLB value for stable emulsification. "
"Blending surfactants of different HLB values (e.g., Tween + Span) allows fine-tuning to match "
"the required HLB. Mixed emulsifier systems also form more stable, denser interfacial films.",
LIGHT_BLUE, MED_BLUE))
story.append(Spacer(1, 10))
story.append(PageBreak())
# ── Ch 5: Preparation ────────────────────────────────────────────────────
story.append(chapter_banner("Chapter 5: Methods of Preparation"))
story.append(Spacer(1, 10))
story.append(Paragraph(
"The goal of all methods is to form a stable <b>primary emulsion</b> first, then dilute to "
"final volume. The primary emulsion must be formed with the correct ratio of "
"oil : water : emulsifier.",
body))
story.append(Spacer(1, 8))
story.append(centre_diagram(diagram_prep_methods()))
story.append(Paragraph("Figure 3: Overview of emulsion preparation methods", diag_cap))
story.append(Spacer(1, 10))
prep_methods = [
{
"num": "Method 1", "title": "Dry Gum Method (Continental / 4:2:1 Method)",
"color": HexColor("#1A5C8A"),
"ratio": "4 parts oil : 2 parts water : 1 part acacia",
"steps": [
"Weigh acacia into a DRY mortar; add oil — triturate gently to coat gum with oil.",
"Add ALL the water at once (the '2 parts').",
"Triturate RAPIDLY and continuously until a creamy white primary emulsion forms.",
"A characteristic CRACKLING sound confirms formation of the primary emulsion.",
"Dilute progressively with remaining vehicle (water, syrup, etc.).",
"Transfer to a bottle and shake.",
],
"note": "The dry mortar and rapid trituration are critical. Adding water in portions instead of all at once prevents primary emulsion formation.",
"example": "Liquid Paraffin Emulsion BP (4 parts paraffin : 2 parts water : 1 part acacia)",
},
{
"num": "Method 2", "title": "Wet Gum Method (English Method / 4:2:1)",
"color": HexColor("#2E7D52"),
"ratio": "Same 4:2:1 ratio as Dry Gum",
"steps": [
"Dissolve acacia in the water portion first to form a thick mucilage.",
"Add oil GRADUALLY (in small portions) to the mucilage with constant trituration.",
"Continue adding and triturating until a uniform primary emulsion forms.",
"Dilute to final volume with remaining vehicle.",
],
"note": "Slower than dry gum method but produces a finer, smoother emulsion. Better for solid or semi-solid emulsifying agents.",
"example": "Castor oil emulsion using acacia mucilage",
},
{
"num": "Method 3", "title": "Bottle (Forbes Bottle) Method",
"color": HexColor("#7B3F00"),
"ratio": "4:2:1 (oil : water : gum) — adapted for low-viscosity oils",
"steps": [
"Place measured gum in a DRY, wide-mouth bottle.",
"Add measured oil and shake to disperse gum in oil.",
"Add ALL the water at once.",
"Shake VIGOROUSLY until the crackling sound confirms primary emulsion.",
"Dilute with remaining vehicle.",
],
"note": "Used for volatile oils and non-viscous/mobile oils that cannot be triturated easily in a mortar. Suitable for small-scale/extemporaneous dispensing.",
"example": "Peppermint oil emulsion",
},
{
"num": "Method 4", "title": "Mechanical / Machine Methods (Industrial)",
"color": HexColor("#5A1A7A"),
"ratio": "Variable — depends on formulation",
"steps": [
"Mix oil phase and water phase separately, heat if needed.",
"Combine phases and pass through mechanical equipment.",
"Equipment types: Colloid Mill, Homogenizer (piston), Microfluidizer, Ultrasonic processor.",
"Multiple passes reduce globule size and narrow size distribution.",
"Cool, add heat-sensitive components, fill and seal.",
],
"note": "Used for industrial/large-scale production. Produces very fine, uniform globules (sub-micron size). Essential for parenteral (IV) emulsions.",
"example": "Intralipid® IV fat emulsion (20% soybean oil), Propofol emulsion",
},
]
for m in prep_methods:
ps = S("MP", fontSize=11, leading=14, fontName="Helvetica-Bold", textColor=WHITE)
rs = S("MR", fontSize=9.5, leading=13, fontName="Helvetica-Bold", textColor=HexColor("#FFE0A0"))
bs = S("MB", fontSize=9.5, leading=14, fontName="Helvetica", textColor=DARK_GRAY)
ns = S("MN", fontSize=9.5, leading=14, fontName="Helvetica-Oblique", textColor=HexColor("#333300"))
es = S("ME", fontSize=9.5, leading=13, fontName="Helvetica-Bold", textColor=m["color"])
steps = "<br/>".join(f"{i+1}. {s}" for i, s in enumerate(m["steps"]))
blk = Table([
[Paragraph(f"{m['num']}: {m['title']}", ps)],
[Paragraph(f"Ratio: {m['ratio']}", rs)],
[Paragraph(f"<b>Steps:</b><br/>{steps}", bs)],
[Paragraph(f"Note: {m['note']}", ns)],
[Paragraph(f"Example: {m['example']}", es)],
], colWidths=[16.5*cm])
blk.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), m["color"]),
("BACKGROUND", (0,1),(0,1), HexColor("#222222")),
("BACKGROUND", (0,2),(-1,-1), LIGHT_GRAY),
("BOX", (0,0),(-1,-1), 1, m["color"]),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING", (0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
story.append(KeepTogether([blk, Spacer(1, 8)]))
story.append(PageBreak())
# ── Ch 6: Identification ─────────────────────────────────────────────────
story.append(chapter_banner("Chapter 6: Identification of Emulsion Type"))
story.append(Spacer(1, 10))
story.append(make_table(
["Test", "O/W Result", "W/O Result", "Principle"],
[
["Dilution Test", "Miscible with water (dilutes uniformly)", "Miscible with oils only", "External phase determines miscibility"],
["Conductivity Test", "Conducts electricity (water conducts)", "Non-conductor / very poor conductor", "Water carries ions; oil does not"],
["Methylene Blue Dye (water-soluble)", "Whole emulsion turns blue uniformly", "Only droplets (inner phase) turn blue", "Dye dissolves in external water phase"],
["Sudan III Dye (oil-soluble)", "Only droplets (inner phase) stain red", "Whole emulsion turns red uniformly", "Dye dissolves in external oil phase"],
["Fluorescence Test", "Emulsion does NOT fluoresce (water outside)", "Whole emulsion fluoresces (oil outside)", "Oils fluoresce under UV light"],
["Filter Paper Test", "Spreads quickly — water wets paper", "Does not spread easily — oil repels", "Water has higher surface wetting"],
["CoCl₂ Filter Paper", "Paper turns pink (blue → pink in water)", "Paper remains blue", "Cobalt chloride reacts with water"],
],
[3.5*cm, 4.5*cm, 4.5*cm, 5*cm]))
story.append(Spacer(1, 10))
story.append(PageBreak())
# ── Ch 7: Stability Problems ─────────────────────────────────────────────
story.append(chapter_banner("Chapter 7: Stability Problems — Detailed"))
story.append(Spacer(1, 8))
story.append(Paragraph(
"Emulsions are <b>thermodynamically unstable</b> by nature — they always tend toward "
"phase separation. Instability progresses through a cascade of stages, from reversible "
"to irreversible. The diagram below shows this progression:",
body))
story.append(Spacer(1, 8))
story.append(centre_diagram(diagram_stability_cascade()))
story.append(Paragraph("Figure 4: Emulsion instability progression — from reversible to irreversible", diag_cap))
story.append(Spacer(1, 10))
stab = [
{
"num": "1", "title": "Creaming",
"color": HexColor("#2B6CB0"), "rev": "✔ REVERSIBLE",
"def_": "Upward migration of oil globules (O/W) or downward settling (W/O), forming two visible layers. Globules remain intact and individual.",
"cause": "Density difference between dispersed and continuous phases. Governed by Stokes' Law.",
"formula": "V = 2r²(ρ₁ - ρ₂)g / 9η\nV = creaming velocity | r = globule radius | ρ = phase densities | η = viscosity",
"consequence": "Non-uniform dosing if not shaken. First sign of instability but emulsion still intact.",
"prevent": [
"Reduce globule size by homogenization (r² factor in Stokes' Law — halving radius reduces creaming 4×).",
"Increase continuous phase viscosity (add CMC, carbomer, tragacanth).",
"Match densities of two phases.",
'Label "Shake well before use."',
],
},
{
"num": "2", "title": "Flocculation",
"color": HexColor("#D97706"), "rev": "✔ REVERSIBLE",
"def_": "Globules aggregate into loose clusters (flocs) but remain individual — they have NOT merged. Similar to creaming but involves clustering.",
"cause": "Reduction in zeta potential (electrical repulsion between droplets decreases); addition of electrolytes; pH change.",
"formula": "Adequate zeta potential: ideally > ±30 mV to maintain stability",
"consequence": "Precursor to coalescence. Non-uniform appearance. Increases creaming rate.",
"prevent": [
"Maintain adequate zeta potential (>±30 mV).",
"Avoid electrolyte contamination.",
"Use anionic emulsifiers to maintain surface charge.",
"Control pH.",
],
},
{
"num": "3", "title": "Coalescence",
"color": HexColor("#C05621"), "rev": "✗ IRREVERSIBLE",
"def_": "Flocculated globules merge together — the interfacial film ruptures and droplets fuse into progressively larger droplets.",
"cause": "Rupture of the emulsifier film around globules due to thermal energy, mechanical stress, or inadequate emulsifier concentration.",
"formula": "Globule size increases progressively → eventually complete separation",
"consequence": "Directly leads to cracking. Large, visible oily droplets form. Drug dose becomes non-uniform.",
"prevent": [
"Use strong, stable emulsifier films — mixed emulsifier systems (Tween + Span) form denser films.",
"Maintain optimal emulsifier concentration.",
"Avoid high temperatures (weakens protein/gum films).",
"Avoid freeze-thaw cycles.",
],
},
{
"num": "4", "title": "Cracking (Breaking)",
"color": HexColor("#C0392B"), "rev": "✗ IRREVERSIBLE — DISCARD",
"def_": "Complete, permanent separation of the emulsion into two distinct bulk liquid phases. The emulsion is destroyed.",
"cause": [
"Coalescence proceeding to completion.",
"Incompatible chemicals that destroy the emulsifier (e.g., cationic + anionic incompatibility).",
"Microbial contamination decomposing natural emulsifiers (acacia fermented by bacteria).",
"Excessive heat (boiling destroys protein-based emulsifiers like gelatin).",
"Freeze-thaw cycles — ice crystals rupture globule films.",
"Salting out — excessive electrolyte precipitates hydrophilic emulsifiers.",
],
"formula": "No restoration possible by shaking",
"consequence": "Emulsion permanently ruined. Must be discarded. Risk of incorrect dosing if used.",
"prevent": [
"Use chemically stable emulsifiers; avoid incompatibilities.",
"Add preservatives to prevent microbial decomposition of emulsifier.",
"Store within recommended temperature range.",
"Avoid freeze-thaw; avoid incompatible additives.",
],
},
{
"num": "5", "title": "Phase Inversion",
"color": PURPLE, "rev": "✗ USUALLY IRREVERSIBLE",
"def_": "The emulsion type changes — O/W inverts to W/O or vice versa. Properties and drug release are completely altered.",
"cause": "Change in phase volume ratio beyond critical point (~74%); change in temperature; addition of electrolytes; replacement/change of emulsifier.",
"formula": "Dispersed phase must not exceed ~74% v/v (critical packing fraction)",
"consequence": "Completely changes pharmaceutical properties, appearance, and drug release. May be therapeutically dangerous.",
"prevent": [
"Maintain correct phase volume ratio (<74% dispersed phase).",
"Avoid incompatible electrolytes (e.g., CaCl₂ to sodium soap O/W emulsion).",
"Maintain stable storage temperature.",
"Use phase inversion temperature (PIT) method deliberately to form fine emulsions.",
],
},
{
"num": "6", "title": "Ostwald Ripening",
"color": ACCENT_TEAL, "rev": "✗ IRREVERSIBLE",
"def_": "Small droplets gradually shrink (dissolve) and the material migrates and deposits onto larger droplets, which grow progressively larger.",
"cause": "Difference in Laplace pressure — small droplets have higher chemical potential and higher solubility in the continuous phase than large ones.",
"formula": "Rate ∝ solubility of dispersed phase in continuous phase",
"consequence": "Mean droplet size increases over time. Polydisperse system develops. Accelerates coalescence.",
"prevent": [
"Add a second poorly-soluble component to the dispersed phase (osmotic pressure counterbalance).",
"Use polymeric or rigid interfacial films (block copolymers).",
"Produce narrow initial droplet size distribution.",
],
},
{
"num": "7", "title": "Microbial Contamination",
"color": HexColor("#4A6B1A"), "rev": "✗ IRREVERSIBLE damage",
"def_": "Growth of bacteria, yeasts, and molds — especially in O/W emulsions where the aqueous continuous phase supports microbial growth.",
"cause": "No inherent antimicrobial property. Aqueous phase provides water activity for microbial growth. Natural emulsifiers (acacia, gelatin) are particularly susceptible to biodegradation.",
"formula": "Microbial decomposition of emulsifier → coalescence/cracking",
"consequence": "Decomposition of emulsifying agent → cracking. Off-odors, discoloration, gas formation. Patient safety risk.",
"prevent": [
"Add preservatives: chlorocresol, benzalkonium chloride, parabens (methyl/propyl), phenoxyethanol.",
"Preservative must partition into the AQUEOUS phase to be effective in O/W emulsions.",
"Prepare under clean conditions; fill and seal containers properly.",
"Consider antifungal agents (e.g., sorbic acid) for long shelf life.",
],
},
]
for item in stab:
ps = S("SP", fontSize=11, leading=14, fontName="Helvetica-Bold", textColor=WHITE)
rev_s = S("RV", fontSize=9, leading=12, fontName="Helvetica-Bold",
textColor=WHITE if "IRREVERSIBLE" in item["rev"] else HexColor("#CCFFCC"))
ds = S("SD", fontSize=9.5, leading=14, fontName="Helvetica", textColor=DARK_GRAY)
fs = S("SF", fontSize=9, leading=13, fontName="Helvetica-Bold", textColor=DARK_BLUE, alignment=TA_CENTER)
cs = S("SC", fontSize=9.5, leading=14, fontName="Helvetica-Oblique",textColor=HexColor("#8B0000"))
ss = S("SS", fontSize=9.5, leading=14, fontName="Helvetica", textColor=HexColor("#1A5C2A"))
cause_txt = item["cause"] if isinstance(item["cause"], str) \
else "<br/>".join(f"• {c}" for c in item["cause"])
prev_txt = "<br/>".join(f"✔ {p}" for p in item["prevent"])
blk = Table([
[Paragraph(f"Problem {item['num']}: {item['title']} — {item['rev']}", ps)],
[Paragraph(f"<b>Definition:</b> {item['def_']}", ds)],
[Paragraph(f"<b>Cause(s):</b> {cause_txt}", ds)],
[Paragraph(f"<b>Key Formula/Threshold:</b> {item['formula']}", fs)],
[Paragraph(f"<b>Consequence:</b> {item['consequence']}", cs)],
[Paragraph(f"<b>Prevention:</b><br/>{prev_txt}", ss)],
], colWidths=[16.5*cm])
blk.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), item["color"]),
("BACKGROUND", (0,1),(0,1), HexColor("#FAFAFA")),
("BACKGROUND", (0,2),(0,2), LIGHT_GRAY),
("BACKGROUND", (0,3),(0,3), LIGHT_BLUE),
("BACKGROUND", (0,4),(0,4), LIGHT_RED),
("BACKGROUND", (0,5),(0,5), LIGHT_GREEN),
("BOX", (0,0),(-1,-1), 1, item["color"]),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING", (0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 12),
("RIGHTPADDING", (0,0),(-1,-1), 12),
]))
story.append(KeepTogether([blk, Spacer(1, 8)]))
story.append(PageBreak())
# ── Ch 8: Stability Strategies ───────────────────────────────────────────
story.append(chapter_banner("Chapter 8: Stability Enhancement Strategies"))
story.append(Spacer(1, 10))
strategies = [
("Reduce Globule Size", "Homogenization / colloid milling. Halving globule radius reduces creaming velocity 4× (Stokes' Law). Increases surface area → better emulsifier coverage."),
("Increase Viscosity of Continuous Phase", "Add thickening/gelling agents: CMC, carbomer, tragacanth, xanthan gum, methylcellulose. Slows all movement — reduces creaming, flocculation, and coalescence rates."),
("Optimal Emulsifier System", "Use mixed emulsifier systems (e.g., Tween + Span) — forms denser, more rigid interfacial films. Match emulsifier HLB to required HLB of oil phase. Use correct concentration (typically 1–5%)."),
("Match Phase Densities", "Reduces density difference (ρ₁ - ρ₂) in Stokes' Law → minimizes creaming velocity. Achieved by selecting oils with densities close to water or adding density-modifying agents."),
("Maintain Adequate Zeta Potential", "Keep >±30 mV to maintain electrostatic repulsion between droplets and prevent flocculation. Control ionic strength and pH."),
("Temperature Control", "Store at controlled room temperature (15–25°C). Avoid extremes. High temperature weakens emulsifier films and accelerates oxidation. Freeze-thaw cycles rupture globule films."),
("Add Preservatives", "Essential for O/W emulsions (water = external phase). Preservative must partition into aqueous phase: chlorocresol, parabens, benzalkonium chloride."),
("Add Antioxidants", "Prevent rancidity of oil phase: BHA, BHT, mixed tocopherols. Use chelating agents (EDTA) to remove trace metal ions (Fe³⁺, Cu²⁺) that catalyze oxidation."),
("Control Phase Volume Ratio", "Dispersed phase must not exceed ~74% v/v. Beyond this, phase inversion becomes likely. For O/W, keep oil phase below 50–60% for practical stability."),
('Label "Shake Well Before Use"', "Reverses creaming and flocculation before dosing. Critical instruction for all emulsion products."),
]
rows = [[Paragraph(f"<b>{t}</b>", S("st", fontSize=10, fontName="Helvetica-Bold", textColor=DARK_BLUE)),
Paragraph(d, S("sd", fontSize=10, leading=14, fontName="Helvetica", textColor=DARK_GRAY))]
for t, d in strategies]
t = Table(rows, colWidths=[4.5*cm, 12*cm])
t.setStyle(TableStyle([
("ROWBACKGROUNDS", (0,0),(-1,-1), [TABLE_ODD, TABLE_EVEN]),
("GRID", (0,0),(-1,-1), 0.3, HexColor("#A0B8D8")),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 9),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
story.append(t)
story.append(Spacer(1, 10))
story.append(PageBreak())
# ── Ch 9: Uses ───────────────────────────────────────────────────────────
story.append(chapter_banner("Chapter 9: Pharmaceutical Uses"))
story.append(Spacer(1, 10))
story.append(make_table(
["Route", "Type", "Purpose", "Examples"],
[
["Oral", "O/W", "Improve palatability of oils; increase bioavailability of lipophilic drugs", "Liquid paraffin emulsion BP, Cod liver oil emulsion, Oil-soluble vitamins A/D"],
["Topical", "O/W (vanishing cream)", "Non-greasy moisturizing; drug delivery; cosmetics", "Aqueous cream BP, Calamine lotion, Most modern skin creams"],
["Topical", "W/O (cold cream)", "Emollient, barrier protection; greasy base for skin conditions", "Cold cream, Oily calamine cream, Barrier creams"],
["Parenteral (IV)", "O/W (fine/microemulsion)", "Total parenteral nutrition (TPN); IV delivery of lipophilic drugs", "Intralipid® 20%, Propofol (Diprivan®)"],
["Rectal", "O/W", "Laxative effect; drug delivery", "Arachis oil emulsion enema"],
["Topical (medicated)", "O/W or W/O", "Drug delivery through skin (TDDS)", "Corticosteroid creams, NSAID gels"],
["Vaccine adjuvants", "W/O or O/W", "Enhance immune response to antigens", "MF59 (Novartis), AS03 (GSK), Freund's adjuvant"],
["Dental", "O/W", "Local anesthetic delivery; antiseptic", "Benzocaine emulsion, Cetrimide-based oral emulsions"],
],
[2.5*cm, 2.5*cm, 5.5*cm, 7*cm]))
story.append(Spacer(1, 10))
story.append(PageBreak())
# ── Ch 10: Summary Tables ────────────────────────────────────────────────
story.append(chapter_banner("Chapter 10: Quick-Reference Summary Tables"))
story.append(Spacer(1, 8))
story.append(section_bar("10.1 Master Summary"))
story.append(make_table(
["Aspect", "Key Points"],
[
["Definition", "Thermodynamically unstable two-phase system: dispersed phase (droplets) in continuous phase, stabilized by emulsifier"],
["Main types", "O/W (non-greasy, water outside) | W/O (greasy, oil outside) | Multiple | Microemulsion (stable)"],
["Emulsifier role", "Reduces interfacial tension + forms protective film around droplets"],
["O/W emulsifiers (HLB 8–18)", "Tween 80 (15), Tween 20 (16.7), Acacia (~8), Sodium stearate, Lecithin"],
["W/O emulsifiers (HLB 3–6)", "Span 80 (4.3), Span 60 (4.7), Beeswax, Lanolin, Cholesterol"],
["4:2:1 ratio", "Oil : Water : Acacia (Dry Gum and Wet Gum methods)"],
["Crackling sound", "Confirms primary emulsion formation in Dry Gum / Bottle method"],
["Stability cascade", "Creaming → Flocculation (reversible) → Coalescence → Cracking (irreversible)"],
["Cracking causes", "Incompatible emulsifier, microbial decomp., excessive heat, freeze-thaw, salting out"],
["Phase inversion limit", "Dispersed phase must not exceed ~74% v/v"],
["Stokes' Law", "V = 2r²(ρ₁-ρ₂)g / 9η — halving r reduces creaming 4×"],
["Zeta potential for stability", ">±30 mV"],
["O/W identification", "Methylene blue colors whole emulsion; miscible with water; conducts electricity"],
["W/O identification", "Sudan III colors whole emulsion; miscible with oil; non-conductor"],
["Key preservatives (O/W)", "Chlorocresol, parabens, benzalkonium chloride (must be in aqueous phase)"],
],
[5*cm, 11.5*cm]))
story.append(Spacer(1, 10))
story.append(section_bar("10.2 Stability Problems — Quick Reference"))
story.append(make_table(
["Problem", "Globules Intact?", "Reversible?", "Stage", "Key Prevention"],
[
["Creaming", "Yes", "Yes", "Early", "Reduce globule size; increase viscosity"],
["Flocculation", "Yes (not merged)", "Yes", "Early-Mid", "Maintain zeta potential; control pH"],
["Coalescence", "No — merging", "No", "Late", "Strong emulsifier film; avoid heat"],
["Cracking", "No — separated", "No — DISCARD", "Final", "Stable emulsifier; preservatives; avoid incompatibilities"],
["Phase Inversion", "Type changed", "Usually no", "Any", "Phase ratio <74%; avoid incompatible electrolytes"],
["Ostwald Ripening", "Size increasing", "No", "Gradual", "Add poorly-soluble oil component; narrow size distribution"],
["Microbial", "Emulsifier destroyed", "No", "Any", "Preservatives in aqueous phase; clean preparation"],
],
[3*cm, 3*cm, 2.5*cm, 2.5*cm, 6.5*cm]))
story.append(Spacer(1, 10))
story.append(PageBreak())
# ── Ch 11: Q&A ───────────────────────────────────────────────────────────
story.append(chapter_banner("Chapter 11: Practice Q & A"))
story.append(Spacer(1, 10))
qa = [
("Q1. Define a pharmaceutical emulsion.",
"A thermodynamically unstable, two-phase liquid system in which one immiscible liquid (dispersed/internal phase) is broken into fine globules and distributed throughout another liquid (continuous/external phase), stabilized by an emulsifying agent."),
("Q2. What is the difference between an O/W and a W/O emulsion?",
"O/W: oil droplets dispersed IN water (water = external phase) — non-greasy, miscible with water, conducts electricity.\nW/O: water droplets dispersed IN oil (oil = external phase) — greasy, miscible with oil, non-conductor."),
("Q3. What is the 4:2:1 ratio in emulsion preparation?",
"4 parts oil : 2 parts water : 1 part acacia (emulsifier). Used in both Dry Gum (Continental) and Wet Gum (English) methods to form the primary emulsion."),
("Q4. How do you identify whether an emulsion is O/W or W/O using dye tests?",
"Methylene blue (water-soluble): whole emulsion turns blue = O/W; only droplets turn blue = W/O.\nSudan III (oil-soluble): whole emulsion turns red = W/O; only droplets turn red = O/W."),
("Q5. What is the HLB system? Give the HLB ranges for O/W and W/O emulsifiers.",
"HLB (Hydrophilic-Lipophilic Balance) is a numerical scale (0–20) indicating a surfactant's affinity for water vs oil.\nO/W emulsifiers: HLB 8–18. W/O emulsifiers: HLB 3–6."),
("Q6. Arrange the stability problems in order from first to last and state which are reversible.",
"Creaming (reversible) → Flocculation (reversible) → Coalescence (irreversible) → Cracking/Breaking (irreversible). Phase inversion and Ostwald ripening can occur at any stage."),
("Q7. What is the difference between coalescence and cracking?",
"Coalescence: individual globule membranes rupture and droplets merge into larger droplets — irreversible but the emulsion is not yet completely destroyed.\nCracking: coalescence proceeds to completion — full separation into two bulk liquid phases — emulsion is permanently destroyed and must be discarded."),
("Q8. State Stokes' Law and explain how it is used to prevent creaming.",
"V = 2r²(ρ₁-ρ₂)g / 9η. Reducing globule radius (r) has the greatest effect (r² term) — halving r reduces creaming velocity 4×. Also: increase η (viscosity of continuous phase) and match phase densities."),
("Q9. Why must preservatives in O/W emulsions be water-soluble?",
"In O/W emulsions, the water is the external (continuous) phase where microorganisms grow. The preservative must partition into and be active in the aqueous phase to inhibit microbial growth. A preservative that partitions into the oil phase would be ineffective."),
("Q10. Give two examples each of oral, topical O/W, topical W/O, and parenteral emulsions.",
"Oral: Liquid Paraffin Emulsion BP, Cod Liver Oil Emulsion.\nTopical O/W: Aqueous Cream BP, Calamine Lotion.\nTopical W/O: Cold Cream, Oily Calamine Cream.\nParenteral: Intralipid® 20% (TPN), Propofol (Diprivan®) — IV anesthetic."),
]
for q, a in qa:
blk = Table([
[Paragraph(q, qa_q)],
[Paragraph(a.replace("\n", "<br/>"), qa_a)],
], colWidths=[16.5*cm])
blk.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), LIGHT_BLUE),
("BACKGROUND", (0,1),(0,-1), WHITE),
("BOX", (0,0),(-1,-1), 0.8, MED_BLUE),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING", (0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 11),
("RIGHTPADDING", (0,0),(-1,-1), 11),
]))
story.append(KeepTogether([blk, Spacer(1, 6)]))
return story
# ════════════════════════════════════════════════════════════════════════════
# BUILD
# ════════════════════════════════════════════════════════════════════════════
def build():
doc = SimpleDocTemplate(
OUTPUT, pagesize=A4,
leftMargin=2*cm, rightMargin=2*cm,
topMargin=2*cm, bottomMargin=2.2*cm,
title="Pharmaceutical Emulsions - Comprehensive Study Guide",
author="Pharmacy Study Guide",
subject="Pharmaceutics - Emulsions",
)
story = build_cover() + build_content()
doc.build(story, onFirstPage=add_page_number, onLaterPages=add_page_number)
print(f"PDF created: {OUTPUT}")
if __name__ == "__main__":
build()
cd /home/daytona/workspace/syrups-study-guide && python generate_emulsions_pdf.p…
ls -lh /home/daytona/workspace/syrups-study-guide/Emulsions_Study_Guide.pdf
Emulsions Study Guide
PDF Document · PDF
| Chapter | Content |
|---|---|
| 1 | Definition, Two Phases table, key concepts |
| 2 | Types — O/W, W/O, Multiple, Microemulsion + Figure 1: O/W vs W/O schematic diagram (visual circles showing oil droplets in water vs water droplets in oil) |
| 3 | Full composition table — 9 components with roles and examples |
| 4 | Emulsifying agents (8 categories) + Figure 2: HLB Scale bar diagram with color gradient and scale ticks |
| 5 | All 4 preparation methods (Dry Gum, Wet Gum, Bottle, Machine) with step-by-step details + Figure 3: Preparation methods overview diagram |
| 6 | 7 identification tests (dye, conductivity, dilution, filter paper, CoCl₂) |
| 7 | All 7 stability problems in color-coded blocks (each has: definition, cause, formula/threshold, consequence, prevention) + Figure 4: Stability cascade flowchart (Creaming → Flocculation → Coalescence → Cracking with reversible/irreversible brackets) |
| 8 | 10 stability enhancement strategies |
| 9 | Pharmaceutical uses table (oral, topical, parenteral, vaccines) with 8 routes |
| 10 | Master summary + Stability quick-reference table |
| 11 | 10 Practice Q&A pairs |
the pdf is not downloading
ls -lh /home/daytona/workspace/syrups-study-guide/ && echo "---" && pwd
Emulsions Study Guide
PDF Document · PDF
Aromatic Waters Study Guide
PDF Document · PDF
Syrups Study Guide
PDF Document · PDF
do the same with pastes and creams
pharmaceutical creams definition types preparation stability problems bases pharmaceutics
pharmaceutical pastes definition types preparation stability problems pharmaceutics
https://clinicalgate.com/2015/02/08/emulsions-and-creams
https://www.uspnf.com/sites/default/files/usp_pdf/EN/USPNF/p…