Prepare hand written notes of this which is also useful in gtu b.pharm exam
mkdir -p /tmp/workspace/pharma-notes && ls /tmp/workspace/pharma-notes/
~/pharma-notes/generate_notes.py
from PIL import Image, ImageDraw, ImageFont
import textwrap
import os
# ── Colour palette ─────────────────────────────────────────────
BG = (255, 252, 235) # cream / ruled-paper look
LINE_CLR = (180, 200, 220) # light blue ruled lines
MARGIN_CLR= (210, 150, 150) # red left margin line
H1 = (15, 60, 130) # dark blue headings
H2 = (0, 100, 60) # dark green sub-headings
BODY = (30, 30, 30) # near-black body text
HIGHLIGHT = (180, 40, 40) # red for key terms
BULLET = (0, 120, 200) # blue bullet
W, H_PG = 1240, 1754 # A4 at 150 dpi
FONT_DIR = "/usr/share/fonts/truetype"
def load_font(size, bold=False):
candidates = [
f"{FONT_DIR}/liberation/LiberationSans-{'Bold' if bold else 'Regular'}.ttf",
f"{FONT_DIR}/dejavu/DejaVuSans{'-Bold' if bold else ''}.ttf",
f"{FONT_DIR}/freefont/FreeSans{'Bold' if bold else ''}.ttf",
]
for p in candidates:
if os.path.exists(p):
return ImageFont.truetype(p, size)
return ImageFont.load_default()
# ── Helper: wrapped text block ──────────────────────────────────
def draw_wrapped(draw, text, x, y, max_w, font, color, line_gap=6):
"""Draw wrapped text, return new y position."""
avg_char_w = font.getlength("x")
chars_per_line = max(1, int(max_w / avg_char_w))
lines = textwrap.wrap(text, width=chars_per_line)
if not lines:
lines = [""]
for ln in lines:
draw.text((x, y), ln, font=font, fill=color)
bbox = font.getbbox(ln)
y += (bbox[3] - bbox[1]) + line_gap
return y
def draw_bullet_item(draw, label, text, x, y, max_w, fonts, line_gap=5):
"""
label: bold key (or None)
text : body string
"""
f_bold = fonts["bold"]
f_body = fonts["body"]
# bullet dot
draw.ellipse([(x-12, y+5), (x-4, y+13)], fill=BULLET)
cx = x + 4
if label:
lw = f_bold.getlength(label + " ")
draw.text((cx, y), label, font=f_bold, fill=H1)
# remaining width
rest_x = cx + lw
rest_w = max_w - lw - 4
y = draw_wrapped(draw, text, rest_x, y, rest_w, f_body, BODY, line_gap)
else:
y = draw_wrapped(draw, text, cx, y, max_w - 4, f_body, BODY, line_gap)
return y + 4
def new_page():
img = Image.new("RGB", (W, H_PG), BG)
draw = ImageDraw.Draw(img)
# ruled lines
for yy in range(100, H_PG - 40, 30):
draw.line([(80, yy), (W - 40, yy)], fill=LINE_CLR, width=1)
# left margin
draw.line([(80, 60), (80, H_PG - 40)], fill=MARGIN_CLR, width=2)
return img, draw
def page_title(draw, title, subtitle, fonts):
# title bar
draw.rectangle([(80, 20), (W - 40, 70)], fill=H1)
draw.text((100, 26), title, font=fonts["title"], fill=(255,255,255))
tw = fonts["title"].getlength(title)
draw.text((110 + tw, 32), subtitle, font=fonts["sub"], fill=(200,230,255))
def section_heading(draw, text, y, fonts, color=H2):
draw.rectangle([(80, y), (W - 40, y + 30)], fill=color)
draw.text((90, y + 4), text, font=fonts["h2"], fill=(255,255,255))
return y + 38
def divider(draw, y):
draw.line([(80, y), (W - 40, y)], fill=(150,150,180), width=1)
return y + 8
# ════════════════════════════════════════════════════════════════
# PAGE 1 – BELLADONNA: Intro
# ════════════════════════════════════════════════════════════════
def make_page_bella1(fonts):
img, draw = new_page()
page_title(draw, "BELLADONNA", "(Tropane Alkaloids) – GTU B.Pharm", fonts)
y = 85
y = section_heading(draw, "1. Synonyms & Biological Source", y, fonts)
y = draw_bullet_item(draw, "Synonym:", "Belladonna leaf, Belladonna folium, Deadly night shade leaf (European belladonna)", 100, y, W-160, fonts)
y += 4
y = draw_bullet_item(draw, "Biological Source:", "Dried leaves or aerial parts of Atropa belladonna Linn. (European) or Atropa acuminata Royle ex-Lindley (Indian belladonna), or mixture of both species collected at flowering. Family: Solanaceae.", 100, y, W-160, fonts)
y += 4
y = draw_bullet_item(draw, "Alkaloid content:", "Not less than 0.3% calculated as hyoscyamine.", 100, y, W-160, fonts)
y += 4
y = draw_bullet_item(draw, "Geographical Source:", "England & European countries. India: Western Himalayas (Shimla to Kashmir), Himachal Pradesh, Jammu, Sindhu & Chanab valley.", 100, y, W-160, fonts)
y += 10
y = divider(draw, y)
y = section_heading(draw, "2. Macroscopic Characters", y, fonts)
tbl = [
("Colour", "Leaves – Green to brownish-green | Flowers – Purple to yellowish-brown | Fruits – Green to brown"),
("Odour", "Slight and characteristic"),
("Taste", "Bitter and acrid"),
("Size", "Leaves 5–25 cm long, 2.5–12 cm wide | Flowers (corolla) 2.5 cm long, 1.5 cm wide | Fruits ~10 cm diameter"),
("Shape", "Leaves – Ovate/lanceolate to broadly ovate, acuminate apex, decurrent lamina, entire margin, petiolate, brittle & transversely broken | Flowers – Campanulate with 5 small reflexed lobes | Fruits – Berries, sub-globular with numerous flat seeds"),
]
for lbl, txt in tbl:
y = draw_bullet_item(draw, lbl+":", txt, 100, y, W-160, fonts)
y += 2
y += 10
y = divider(draw, y)
y = section_heading(draw, "3. Microscopic Characters", y, fonts)
micro = [
("Epidermal cells:", "Slightly sinuous anticlinal wall with striated cuticle"),
("Stomata:", "Anisocytic; occasionally uniseriate multicellular covering trichomes; glandular trichomes – uniseriate with unicellular heads"),
("Palisade ratio:", "5 to 7"),
("Key structures:", "Striated cuticle, Palisade, Perimedullary phloem, Xylem, Phloem, Idioblast, Club-shaped glandular trichomes, Uniseriate covering trichome"),
]
for lbl, txt in micro:
y = draw_bullet_item(draw, lbl, txt, 100, y, W-160, fonts)
y += 2
# footer
draw.text((W//2 - 60, H_PG - 32), "Page 1 / 4 | GTU B.Pharm Notes", font=fonts["foot"], fill=(120,120,160))
return img
# ════════════════════════════════════════════════════════════════
# PAGE 2 – BELLADONNA: Chemical Constituents, Test, Uses
# ════════════════════════════════════════════════════════════════
def make_page_bella2(fonts):
img, draw = new_page()
page_title(draw, "BELLADONNA", "Chemical Constituents & Uses – GTU B.Pharm", fonts)
y = 85
y = section_heading(draw, "4. Chemical Constituents", y, fonts)
chem = [
("Total alkaloid content:", "0.4 – 1% | Root 0.6% | Stems 0.05% | Leaves 0.4% | Unripe & ripe berries 0.19–0.21% | Seeds 0.33%"),
("Main alkaloids:", "Hyoscyamine (primary) & its racemic form Atropine"),
("Other alkaloids:", "Belladonine, Scopoletin (methyl aesculetin), Hyoscine (Scopolamine)"),
("Volatile bases:", "Pyridine, N-methyl pyrroline"),
("Homatropine:", "Synthetic compound – preferred in practice because natural synthesis of atropine/hyoscyamine is very costly"),
]
for lbl, txt in chem:
y = draw_bullet_item(draw, lbl, txt, 100, y, W-160, fonts)
y += 3
y += 8
y = divider(draw, y)
y = section_heading(draw, "5. Chemical Test", y, fonts)
draw.text((100, y), "★ Vitali-Morin Test: ", font=fonts["bold"], fill=HIGHLIGHT)
draw.text((100 + fonts["bold"].getlength("★ Vitali-Morin Test: "), y), "POSITIVE", font=fonts["bold"], fill=(0,140,0))
y += 28
y = draw_bullet_item(draw, "Procedure:", "To the alkaloidal drug add a few drops of H₂SO₄ or HNO₃, evaporate to dryness, then add methanolic KOH solution.", 100, y, W-160, fonts)
y = draw_bullet_item(draw, "Result:", "Violet / bright purple colour → confirms presence of Tropane alkaloids.", 100, y, W-160, fonts)
y += 8
y = divider(draw, y)
y = section_heading(draw, "6. Pharmacological Actions & Uses", y, fonts)
uses = [
("Action:", "Parasympatholytic drug with Anticholinergic properties"),
("Uses:", "① Reduces secretions (sweat, saliva, gastric juice)\n② Reduces intestinal spasm from purgatives\n③ Antidote in opium & choral hydrate poisoning"),
("Dose:", "0.6 to 1 mL as belladonna tincture, 4 times a day"),
]
for lbl, txt in uses:
y = draw_bullet_item(draw, lbl, txt, 100, y, W-160, fonts)
y += 4
y += 10
y = divider(draw, y)
# Quick Revision Box
draw.rectangle([(90, y), (W-50, y+140)], outline=H1, width=2)
draw.rectangle([(90, y), (W-50, y+28)], fill=H1)
draw.text((100, y+4), "QUICK REVISION – Belladonna at a Glance", font=fonts["bold"], fill=(255,255,255))
y += 34
qr = [
"Family: Solanaceae | Drug: Dried leaves/aerial parts",
"Main alkaloid: Hyoscyamine → racemic = Atropine",
"Microscopy: Anisocytic stomata, Palisade ratio 5–7, Club-shaped glandular trichomes",
"Test: Vitali-Morin → Positive (violet/purple with KOH/methanol)",
"Use: Anticholinergic, reduces secretions, antidote to opium poisoning",
]
for q in qr:
draw.text((104, y), "✔ " + q, font=fonts["small"], fill=BODY)
y += 22
draw.text((W//2 - 60, H_PG - 32), "Page 2 / 4 | GTU B.Pharm Notes", font=fonts["foot"], fill=(120,120,160))
return img
# ════════════════════════════════════════════════════════════════
# PAGE 3 – OPIUM: Intro, Macro, Varieties
# ════════════════════════════════════════════════════════════════
def make_page_opium1(fonts):
img, draw = new_page()
page_title(draw, "OPIUM", "(Quinoline & Isoquinoline Alkaloids) – GTU B.Pharm", fonts)
y = 85
y = section_heading(draw, "1. Synonyms & Biological Source", y, fonts)
intro = [
("Synonym:", "Raw Opium"),
("Biological Source:", "Air-dried milky exudate (dried latex) from incisions of unripe capsules of Papaver somniferum Linn. Family: Papaveraceae. Dried by heat or spontaneous evaporation → irregularly shaped masses (Natural opium) or uniform masses (Manipulated opium)."),
("Standards:", "Contains ≥ 10% morphine & ≥ 2.0% codeine (both as anhydrous morphine)"),
("Geographical Source:", "India (Rajasthan, M.P., U.P.), Pakistan, Afghanistan, Turkey, Russia, China, Iran"),
]
for lbl, txt in intro:
y = draw_bullet_item(draw, lbl, txt, 100, y, W-160, fonts)
y += 3
y += 6
y = divider(draw, y)
y = section_heading(draw, "2. Macroscopic Characters", y, fonts)
macro = [
("Plant:", "Annual, erect stem ~1–1.5 m height"),
("Form:", "Rounded/somewhat flattened masses, 8–15 cm diameter, 300 g – 2 kg"),
("Ext. colour:", "Pale olive-brown or olive-gray, covered with fragments of poppy leaves"),
("Int. colour:", "Coarsely granular or nearly smooth, reddish-brown, interspersed with lighter areas, somewhat lustrous"),
("Odour:", "Strong and characteristic"),
("Taste:", "Bitter and characteristic"),
]
for lbl, txt in macro:
y = draw_bullet_item(draw, lbl, txt, 100, y, W-160, fonts)
y += 2
y += 8
y = divider(draw, y)
y = section_heading(draw, "3. Varieties of Opium", y, fonts)
varieties = [
("Indian Opium", "Dark brown | Cubical pieces ~900 g for marketing | Enclosed in tissue paper | Brittle & plastic | Internally homogenous | Powder packs of 5–10 kg"),
("Persian Opium", "Dark brown | Brick-shaped masses ~450 g | Hygroscopic, granular, brittle fracture"),
("Natural Turkish / European", "Brown or dark brown | Conical/rounded flattened masses 250–1000 g | On keeping → hard & brittle | Covered with poppy leaves"),
("Manipulated Turkish", "Chocolate brown internally, covered with broken poppy leaves externally | Oval masses ~2000 g | Somewhat plastic or brittle"),
("Manipulated European", "Dark brown internally, broken leaves externally | Elongated masses 150–500 g | Firm, plastic, brittle fracture"),
]
for title, desc in varieties:
# mini sub-heading
draw.text((95, y), "▶ " + title + ":", font=fonts["bold"], fill=HIGHLIGHT)
y += 22
y = draw_wrapped(draw, desc, 116, y, W-180, fonts["body"], BODY, 5)
y += 6
draw.text((W//2 - 60, H_PG - 32), "Page 3 / 4 | GTU B.Pharm Notes", font=fonts["foot"], fill=(120,120,160))
return img
# ════════════════════════════════════════════════════════════════
# PAGE 4 – OPIUM: Cultivation, Chemical Constituents, Uses
# ════════════════════════════════════════════════════════════════
def make_page_opium2(fonts):
img, draw = new_page()
page_title(draw, "OPIUM", "Cultivation & Chemical Constituents – GTU B.Pharm", fonts)
y = 85
y = section_heading(draw, "4. Cultivation & Collection", y, fonts)
cult = [
("Legal control:", "Narcotic Drugs & Psychotropic Substances Act, 1985. Confined to U.P., M.P., Rajasthan. Divided into 12 opium divisions."),
("Soil & Climate:", "Sandy loam preferred. Cannot endure extreme cold, frost, hailstorms. Cultivated as rabi crop (sown winter, harvested spring), follows maize/Kharif crops."),
("Propagation:", "By seeds mixed with earth/ashes; broadcast method Oct–Nov at 3.5 kg/ha. Land prepared in September by repeated ploughing & harrowing to fine tilth. Frequent light irrigation until seedlings established."),
("Manure:", "Superphosphate applied in 2 stages (during ploughing & cultivation). Nitrogenous feed in later growth → increases opium yield AND morphine content."),
]
for lbl, txt in cult:
y = draw_bullet_item(draw, lbl, txt, 100, y, W-160, fonts)
y += 3
y += 6
y = divider(draw, y)
y = section_heading(draw, "5. Harvesting (Lancing / Scarification)", y, fonts)
harv = [
"Plant flowers 75–80 days after germination.",
"Petals fall off 24–72 hrs after bud opening.",
"Capsules fully swollen in 8–10 more days → ready for lancing.",
"Collection period: end of January to April.",
"Field divided into 3 portions; each portion lanced every 3rd day. Each capsule lanced 3–4 times (sometimes 8–10 times) until no more latex exudes.",
"India: vertical incisions upward using 'Nushtur' (special knife with 3–4 blades for uniform depth). Incisions repeated after 2–3 days.",
"Lancing done after midday. Latex left overnight → coagulates (milky white → pale pink → smoky white).",
"Morning (before sunrise): coagulated latex scraped with blunt iron scoop. Capsules cleaned by rubbing with thumb.",
"Day's produce stored separately in earthen/metal pots (tilted to drain moisture). Turned every 10 days for uniform consistency.",
"Dried in sun on earthen plates. First lancing → higher morphine%; stored/delivered separately.",
"Purity tested: 'Degree of consistency' = % solid matter. Stored in double bags (inner: canvas; outer: jute sacking).",
"Government fixed-rate opium = 'Damdeta opium'.",
"Yield: 28–48 g/1000 capsules; Average 13–18 kg/ha; Up to 27–56 kg/ha recorded.",
]
for h in harv:
y = draw_bullet_item(draw, None, h, 100, y, W-160, fonts)
y += 1
y += 8
y = divider(draw, y)
y = section_heading(draw, "6. Chemical Constituents", y, fonts)
cc = [
("Alkaloid type:", "Derived from amino acids phenylalanine & tyrosine → bezylisoquinoline & phenanthrene types"),
("Bezylisoquinoline:", "Narcotine (Noscapine), Narceine, Papaverine"),
("Phenanthrene:", "Morphine, Codeine, Thebaine"),
("Minor alkaloids:", "Protopine, Hydrocotarnine"),
("Others:", "Sugar, wax, mucilage, Ca/K/Mg salts. No tannins, starch or calcium oxalate."),
("Meconic acid:", "Opium alkaloids are present as salts of meconic acid (diagnostic marker)"),
("Seeds:", "Contain 30–35% drying fixed oil (colorless, tasteless, transparent) → used in oil paint industry"),
]
for lbl, txt in cc:
y = draw_bullet_item(draw, lbl, txt, 100, y, W-160, fonts)
y += 2
y += 6
y = divider(draw, y)
y = section_heading(draw, "7. Properties of Key Alkaloids", y, fonts, color=(80,30,120))
props = [
("Morphine:", "Monoacidic, levorotatory phenolic alkaloid. Alcoholic –OH at C-6. Soluble in alkali hydroxides (not NH₄OH). Very slightly soluble in ether, CHCl₃, alcohol, water. Diacetyl derivative = Heroin."),
("Codeine:", "(Methyl morphine) Strong monoacidic base, laevorotatory. Soluble in water & organic solvents."),
("Papaverine:", "Weak monoacidic base, optically inactive. Slightly soluble in organic solvents, insoluble in water."),
("Narcotine:", "Weak monoacidic base, levorotatory (salts dextrorotatory). Soluble in acetone, benzene, CHCl₃; insoluble in water, alcohol, ether."),
]
for lbl, txt in props:
y = draw_bullet_item(draw, lbl, txt, 100, y, W-160, fonts)
y += 3
draw.text((W//2 - 60, H_PG - 32), "Page 4 / 4 | GTU B.Pharm Notes", font=fonts["foot"], fill=(120,120,160))
return img
# ════════════════════════════════════════════════════════════════
# MAIN
# ════════════════════════════════════════════════════════════════
fonts = {
"title": load_font(30, bold=True),
"h2": load_font(20, bold=True),
"bold": load_font(18, bold=True),
"body": load_font(17),
"sub": load_font(18),
"small": load_font(15),
"foot": load_font(14),
}
pages = [
make_page_bella1(fonts),
make_page_bella2(fonts),
make_page_opium1(fonts),
make_page_opium2(fonts),
]
out = "/tmp/workspace/pharma-notes/Belladonna_Opium_Notes.pdf"
pages[0].save(out, "PDF", save_all=True, append_images=pages[1:])
print("DONE:", out)
cd /tmp/workspace/pharma-notes && python generate_notes.py 2>&1
Belladonna Opium Notes
PDF Document · PDF