Make aesthetic mind map note for bams sanskrit 1st year
What format do you want for the mind map? · Which Sanskrit 1st year BAMS topics should be covered?
BAMS 1st year Sanskrit syllabus topics Laghu Siddhanta Kaumudi Amarakosha Vyakarana
mkdir -p /home/daytona/workspace/bams-sanskrit-mindmap && ls /home/daytona/workspace/bams-sanskrit-mindmap/
~/bams-sanskrit-mindmap/mindmap.py
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
import matplotlib.patheffects as pe
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
# ── Colour palette ──────────────────────────────────────────────────────────
BG = "#1a1a2e" # deep navy
CENTER_C = "#e94560" # crimson-rose – centre node
BRANCH_C = ["#0f3460","#16213e","#533483","#0f3460","#16213e"]
LEAF_PAL = {
"Laghu Siddhanta\nKaumudi": "#f5a623",
"Vyakarana\n(Grammar)": "#7ed957",
"Amarakosha": "#4fc3f7",
"Vaidyakeeya\nSubhashitam": "#f06292",
"Sanskrit\nLiterature": "#ce93d8",
}
TEXT_LIGHT = "#f0f0f0"
TEXT_DARK = "#1a1a2e"
# ── Mind-map data ────────────────────────────────────────────────────────────
branches = {
"Laghu Siddhanta\nKaumudi": [
"Sanjña Prakarana\n(Technical Terms)",
"Hal Sandhi\n(Consonant Junction)",
"Swar Sandhi\n(Vowel Junction)",
"Visarga Sandhi\n(Visarga Rules)",
"Karaka Prakarana\n(Case Relations)",
"Samasodhanam\n(Translation Verses)",
],
"Vyakarana\n(Grammar)": [
"Ashtadhyayi\nBasics (Panini)",
"Dhatu Paatha\n(Verb Roots)",
"Vibhakti\n(7 Cases / Declensions)",
"Lakara\n(10 Tenses & Moods)",
"Krit & Taddhita\n(Suffixes)",
"Samasa\n(Compound Words)",
],
"Amarakosha": [
"Swargadi Kanda\n(Heaven chapter)",
"Bhuvargadi Kanda\n(Earth chapter)",
"Samanya Kanda\n(General chapter)",
"Dravya Names\n(Herbs & Substances)",
"Anatomical Terms\n(Sharira Nama)",
"Disease Names\n(Roga Nama)",
],
"Vaidyakeeya\nSubhashitam": [
"Subhashitas from\nCharaka Samhita",
"Subhashitas from\nSushruta Samhita",
"Subhashitas from\nAshtanga Hridayam",
"Moral & Ethical\nVerses (Niti)",
"Medical Aphorisms\n(Vaidya Vakya)",
],
"Sanskrit\nLiterature": [
"Devanagari Script\n& Pronunciation",
"Shloka & Metre\n(Anushtup, Arya)",
"Sandhi Rules\n(Review)",
"Translation Practice\n(Sanskrit→English)",
"Medical Texts\nIntroduction",
],
}
# ── Layout helpers ────────────────────────────────────────────────────────────
def polar(r, deg):
rad = np.deg2rad(deg)
return r * np.cos(rad), r * np.sin(rad)
def draw_rounded_box(ax, x, y, text, width, height, facecolor, textcolor,
fontsize=9, zorder=3, bold=False):
box = FancyBboxPatch((x - width/2, y - height/2), width, height,
boxstyle="round,pad=0.06", linewidth=1.4,
edgecolor="white", facecolor=facecolor,
zorder=zorder, alpha=0.93)
ax.add_patch(box)
weight = "bold" if bold else "normal"
ax.text(x, y, text, ha='center', va='center', fontsize=fontsize,
color=textcolor, fontweight=weight, zorder=zorder+1,
multialignment='center',
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
def curved_arrow(ax, x0, y0, x1, y1, color, lw=1.5):
ax.annotate("", xy=(x1, y1), xytext=(x0, y0),
arrowprops=dict(arrowstyle="-", color=color, lw=lw,
connectionstyle="arc3,rad=0.15"),
zorder=1)
# ── Figure ────────────────────────────────────────────────────────────────────
fig, ax = plt.subplots(figsize=(22, 16))
fig.patch.set_facecolor(BG)
ax.set_facecolor(BG)
ax.set_xlim(-11, 11); ax.set_ylim(-8.5, 8.5)
ax.axis('off')
# ── Decorative starfield ──────────────────────────────────────────────────────
rng = np.random.default_rng(42)
sx = rng.uniform(-11, 11, 250); sy = rng.uniform(-8.5, 8.5, 250)
ss = rng.uniform(0.3, 2.5, 250)
ax.scatter(sx, sy, s=ss, color='white', alpha=0.35, zorder=0)
# ── Title banner ──────────────────────────────────────────────────────────────
ax.text(0, 8.0, "BAMS 1st Year · Sanskrit", ha='center', va='center',
fontsize=20, color='#f5a623', fontweight='bold',
path_effects=[pe.withStroke(linewidth=3, foreground='black')])
ax.text(0, 7.5, "Comprehensive Mind Map", ha='center', va='center',
fontsize=13, color='#ce93d8', style='italic')
# ── Centre node ──────────────────────────────────────────────────────────────
draw_rounded_box(ax, 0, 0, "संस्कृत\nSanskrit", 2.4, 1.4,
CENTER_C, TEXT_LIGHT, fontsize=16, zorder=5, bold=True)
# ── Branch angles ─────────────────────────────────────────────────────────────
branch_angles = [150, 80, 10, 300, 220] # degrees from centre for each branch
branch_r = 4.2 # centre → branch-node distance
leaf_r = 3.3 # branch → leaf offset
branch_names = list(branches.keys())
branch_colors = list(LEAF_PAL.values())
for i, (bname, angle) in enumerate(zip(branch_names, branch_angles)):
bc = branch_colors[i]
bx, by = polar(branch_r, angle)
# line: centre → branch
curved_arrow(ax, 0, 0, bx*0.85, by*0.85, color=bc, lw=2.2)
# branch node
draw_rounded_box(ax, bx, by, bname, 2.3, 1.1, bc, TEXT_DARK,
fontsize=10.5, zorder=4, bold=True)
# leaves
leaves = branches[bname]
n = len(leaves)
# spread leaves ±35° around the branch direction, pushed further out
spread = 38
if n == 1:
leaf_angles = [angle]
else:
leaf_angles = [angle + spread*(k - (n-1)/2)/(n-1)*2 for k in range(n)]
for j, (leaf, la) in enumerate(zip(leaves, leaf_angles)):
lx = bx + leaf_r * np.cos(np.deg2rad(la))
ly = by + leaf_r * np.sin(np.deg2rad(la))
# clamp to canvas
lx = np.clip(lx, -10.0, 10.0)
ly = np.clip(ly, -7.8, 7.8)
# line: branch → leaf
curved_arrow(ax, bx, by, lx, ly, color=bc, lw=1.3)
# leaf node – lighter shade
leaf_face = bc + "99" # add alpha hex
draw_rounded_box(ax, lx, ly, leaf, 2.1, 0.85, bc+"55", TEXT_LIGHT,
fontsize=8.5, zorder=3)
# ── Footer ────────────────────────────────────────────────────────────────────
ax.text(0, -8.1, "© BAMS Sanskrit 1st Year | Mind Map Notes | 2026",
ha='center', va='center', fontsize=8, color='#888888')
plt.tight_layout(pad=0.3)
# ── Save PDF ──────────────────────────────────────────────────────────────────
out = "/home/daytona/workspace/bams-sanskrit-mindmap/BAMS_Sanskrit_1stYear_MindMap.pdf"
with PdfPages(out) as pdf:
pdf.savefig(fig, facecolor=BG, bbox_inches='tight', dpi=200)
print(f"Saved → {out}")
plt.close()
cd /home/daytona/workspace/bams-sanskrit-mindmap && python mindmap.py 2>&1
~/bams-sanskrit-mindmap/mindmap.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/bams-sanskrit-mindmap/mindmap.py'
~/bams-sanskrit-mindmap/mindmap_v2.py
"""
BAMS 1st Year Sanskrit – Aesthetic Mind Map (PDF)
Dark theme · Coloured branches · Rounded nodes · Star background
"""
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyBboxPatch, Circle, Wedge
import matplotlib.patheffects as pe
from matplotlib.backends.backend_pdf import PdfPages
import numpy as np
# ══════════════════════════════════════════════════════════════════════════════
# COLOUR PALETTE
# ══════════════════════════════════════════════════════════════════════════════
BG = "#12102b" # deep indigo night
CENTER_C = "#e63946" # vivid red
GLOW_C = "#ff6b6b" # glow ring
BRANCH_COLORS = {
"Laghu Siddhanta\nKaumudi" : {"node": "#f4a261", "leaf": "#2d1a08"},
"Vyakarana\n(Grammar)" : {"node": "#06d6a0", "leaf": "#062d1e"},
"Amarakosha" : {"node": "#4cc9f0", "leaf": "#062030"},
"Vaidyakeeya\nSubhashitam" : {"node": "#f72585", "leaf": "#2d0617"},
"Sanskrit\nLiterature" : {"node": "#a29bfe", "leaf": "#150d2e"},
}
# ══════════════════════════════════════════════════════════════════════════════
# MIND-MAP DATA
# ══════════════════════════════════════════════════════════════════════════════
branches = {
"Laghu Siddhanta\nKaumudi": {
"desc": "Varadaraja's\ngrammar primer",
"leaves": [
"Sanjña Prakarana\n(Technical Terms)",
"Swar Sandhi\n(Vowel Junction)",
"Hal Sandhi\n(Consonant Junction)",
"Visarga Sandhi\n(Visarga Rules)",
"Karaka Prakarana\n(Case Relations)",
"Samasodhanam\n(Translation Verses)",
],
},
"Vyakarana\n(Grammar)": {
"desc": "Paninian\ngrammar system",
"leaves": [
"Ashtadhyayi Basics\n(Panini's sutras)",
"Dhatu Paatha\n(Verb Roots)",
"Vibhakti\n(7 Case Endings)",
"Lakara\n(10 Tenses & Moods)",
"Krit & Taddhita\n(Suffixes)",
"Samasa\n(Compound Words)",
],
},
"Amarakosha": {
"desc": "Amarasimha's\nthesaurus",
"leaves": [
"Svargadi Kanda\n(Heavenly chapter)",
"Bhuvargadi Kanda\n(Earth chapter)",
"Samanya Kanda\n(General chapter)",
"Herb & Drug Names\n(Dravya Naama)",
"Anatomical Terms\n(Sharira Naama)",
"Disease Names\n(Roga Naama)",
],
},
"Vaidyakeeya\nSubhashitam": {
"desc": "Medical aphorisms\nfrom classics",
"leaves": [
"Charaka Samhita\nSubhashitas",
"Sushruta Samhita\nSubhashitas",
"Ashtanga Hridayam\nSubhashitas",
"Niti (Ethics)\nVerses",
"Vaidya Vakya\n(Physician Maxims)",
],
},
"Sanskrit\nLiterature": {
"desc": "Script, metre\n& translation",
"leaves": [
"Devanagari Script\n& Pronunciation",
"Shloka Metres\n(Anushtup, Arya)",
"Sandhi Rules\n(Revision)",
"Translation Practice\n(Sanskrit→English)",
"Introduction to\nMedical Texts",
],
},
}
# ══════════════════════════════════════════════════════════════════════════════
# HELPERS
# ══════════════════════════════════════════════════════════════════════════════
def polar(r, deg):
rad = np.deg2rad(deg)
return r * np.cos(rad), r * np.sin(rad)
def draw_box(ax, x, y, text, w, h, face, text_col="#f0f0f0",
fs=9, zorder=3, bold=False, alpha=0.92, radius=0.12):
box = FancyBboxPatch((x - w/2, y - h/2), w, h,
boxstyle=f"round,pad={radius}",
linewidth=1.5, edgecolor="white",
facecolor=face, zorder=zorder, alpha=alpha)
ax.add_patch(box)
weight = "bold" if bold else "normal"
ax.text(x, y, text, ha='center', va='center', fontsize=fs,
color=text_col, fontweight=weight, zorder=zorder+1,
multialignment='center', linespacing=1.4,
path_effects=[pe.withStroke(linewidth=1.5, foreground='black')])
def draw_glow_circle(ax, x, y, r, color, alpha=0.18, zorder=2):
for i in range(4):
c = Circle((x, y), r * (1 + 0.35*i), color=color,
alpha=alpha * (0.7**i), zorder=zorder, linewidth=0)
ax.add_patch(c)
def curved_line(ax, x0, y0, x1, y1, color, lw=1.6, rad=0.2):
ax.annotate("", xy=(x1, y1), xytext=(x0, y0),
arrowprops=dict(
arrowstyle="-",
color=color, lw=lw,
connectionstyle=f"arc3,rad={rad}",
alpha=0.75,
),
zorder=1)
# ══════════════════════════════════════════════════════════════════════════════
# FIGURE SETUP
# ══════════════════════════════════════════════════════════════════════════════
fig, ax = plt.subplots(figsize=(24, 17))
fig.patch.set_facecolor(BG)
ax.set_facecolor(BG)
ax.set_xlim(-12, 12); ax.set_ylim(-9, 9)
ax.axis('off')
# ── Starfield ─────────────────────────────────────────────────────────────────
rng = np.random.default_rng(7)
sx = rng.uniform(-12, 12, 320); sy = rng.uniform(-9, 9, 320)
ss = rng.uniform(0.2, 3.5, 320)
ax.scatter(sx, sy, s=ss, color='white', alpha=0.28, zorder=0)
# ── Background radial gradient rings ─────────────────────────────────────────
for r, a in [(8, 0.04), (6, 0.06), (4, 0.08), (2.5, 0.07)]:
c = Circle((0, 0), r, color="#5e4fa2", alpha=a, zorder=0)
ax.add_patch(c)
# ── Title ─────────────────────────────────────────────────────────────────────
ax.text(0, 8.5, "BAMS 1st Year · Sanskrit", ha='center',
fontsize=24, color='#f4a261', fontweight='bold',
path_effects=[pe.withStroke(linewidth=4, foreground='black')])
ax.text(0, 8.0, "Comprehensive Mind Map · 2026", ha='center',
fontsize=13, color='#a29bfe', style='italic')
# thin divider line
ax.plot([-8, 8], [7.65, 7.65], color='#a29bfe', lw=0.8, alpha=0.4, zorder=1)
# ── Centre node ───────────────────────────────────────────────────────────────
draw_glow_circle(ax, 0, 0, 1.4, CENTER_C, alpha=0.22, zorder=1)
draw_box(ax, 0, 0, "SANSKRIT\nBAMS 1st Year", 2.8, 1.5,
CENTER_C, "#ffffff", fs=15, zorder=5, bold=True, alpha=0.97, radius=0.18)
# ══════════════════════════════════════════════════════════════════════════════
# BRANCHES & LEAVES
# ══════════════════════════════════════════════════════════════════════════════
branch_angles = [145, 75, 5, 290, 215] # one per branch
branch_r = 4.5 # centre → branch node
leaf_r_base = 3.2 # branch → leaf node
branch_names = list(branches.keys())
for i, (bname, angle) in enumerate(zip(branch_names, branch_angles)):
palette = BRANCH_COLORS[bname]
nc = palette["node"]
lc = palette["leaf"]
data = branches[bname]
leaves = data["leaves"]
n = len(leaves)
bx, by = polar(branch_r, angle)
# ── Centre → Branch line
curved_line(ax, 0, 0, bx * 0.80, by * 0.80, color=nc, lw=2.5,
rad=0.12 * (1 if i % 2 == 0 else -1))
# ── Branch glow
draw_glow_circle(ax, bx, by, 1.1, nc, alpha=0.15, zorder=2)
# ── Branch node
draw_box(ax, bx, by, bname, 2.5, 1.15,
nc, "#0d0d0d", fs=11, zorder=4, bold=True, alpha=0.95)
# ── Small description badge below branch node
ax.text(bx, by - 0.78, data["desc"], ha='center', va='top',
fontsize=7.5, color=nc, alpha=0.75, style='italic',
multialignment='center', zorder=4)
# ── Leaf spread
spread = 44
if n == 1:
leaf_angles = [angle]
else:
leaf_angles = [angle + spread * (k - (n-1)/2) / ((n-1)/2)
for k in range(n)]
for j, (leaf, la) in enumerate(zip(leaves, leaf_angles)):
lx = bx + leaf_r_base * np.cos(np.deg2rad(la))
ly = by + leaf_r_base * np.sin(np.deg2rad(la))
# clamp to canvas edges
lx = np.clip(lx, -10.8, 10.8)
ly = np.clip(ly, -8.0, 7.5)
# ── Branch → Leaf line
curved_line(ax, bx, by, lx, ly, color=nc, lw=1.4,
rad=0.10 * (1 if j % 2 == 0 else -1))
# ── Leaf node (semi-transparent dark fill with coloured border)
leaf_face = lc
box = FancyBboxPatch((lx - 1.15, ly - 0.5), 2.3, 1.0,
boxstyle="round,pad=0.07",
linewidth=1.6, edgecolor=nc,
facecolor=leaf_face, zorder=3, alpha=0.88)
ax.add_patch(box)
ax.text(lx, ly, leaf, ha='center', va='center', fontsize=8.2,
color="#e8e8e8", zorder=4, multialignment='center',
linespacing=1.35,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
# ══════════════════════════════════════════════════════════════════════════════
# LEGEND / KEY BOX
# ══════════════════════════════════════════════════════════════════════════════
legend_x, legend_y = -11.5, -5.5
ax.text(legend_x, legend_y + 1.6, "BRANCH KEY", ha='left', fontsize=9,
color='#cccccc', fontweight='bold',
path_effects=[pe.withStroke(linewidth=1.5, foreground='black')])
for k, (bname, pal) in enumerate(BRANCH_COLORS.items()):
label = bname.replace('\n', ' ')
swatch = FancyBboxPatch((legend_x, legend_y + 1.1 - k*0.45 - 0.18),
0.3, 0.28, boxstyle="round,pad=0.03",
facecolor=pal["node"], edgecolor='white',
linewidth=0.7, zorder=4)
ax.add_patch(swatch)
ax.text(legend_x + 0.45, legend_y + 1.1 - k*0.45, label,
ha='left', va='center', fontsize=8, color='#dddddd', zorder=4)
# ══════════════════════════════════════════════════════════════════════════════
# FOOTER
# ══════════════════════════════════════════════════════════════════════════════
ax.text(0, -8.7,
"BAMS Sanskrit Paper I: Laghu Siddhanta Kaumudi · Paper II: Vaidyakeeya Subhashitam · Amarakosha · 2026",
ha='center', fontsize=7.8, color='#666688', zorder=1)
plt.tight_layout(pad=0.2)
# ══════════════════════════════════════════════════════════════════════════════
# SAVE
# ══════════════════════════════════════════════════════════════════════════════
out = "/home/daytona/workspace/bams-sanskrit-mindmap/BAMS_Sanskrit_1stYear_MindMap.pdf"
with PdfPages(out) as pdf:
pdf.savefig(fig, facecolor=BG, bbox_inches='tight', dpi=220)
print(f"Saved -> {out}")
plt.close()
cd /home/daytona/workspace/bams-sanskrit-mindmap && python mindmap_v2.py 2>&1
ls -lh /home/daytona/workspace/bams-sanskrit-mindmap/
BAMS Sanskrit 1stYear MindMap
PDF Document · PDF
| Branch | Colour | Sub-topics covered |
|---|---|---|
| Laghu Siddhanta Kaumudi | 🟠 Amber | Sanjña, Swar/Hal/Visarga Sandhi, Karaka, Samasodhanam |
| Vyakarana (Grammar) | 🟢 Teal | Ashtadhyayi, Dhatu Paatha, Vibhakti, Lakara, Samasa |
| Amarakosha | 🔵 Blue | Svargadi/Bhuvargadi/Samanya Kanda, Herb/Anatomy/Disease names |
| Vaidyakeeya Subhashitam | 🩷 Pink | Charaka, Sushruta, Ashtanga Hridayam subhashitas, Niti verses |
| Sanskrit Literature | 🟣 Purple | Devanagari, Shloka metres, Sandhi revision, Translation practice |
Make aesthetic notes for sanskrit bams chapter 1
Which Chapter 1 topic are you referring to? · What format do you want?
BAMS Sanskrit 1st year Chapter 1 Sanjña Prakarana Laghu Siddhanta Kaumudi syllabus content sutras
https://www.sanskritfromhome.org/course-details/laghu_siddha…
~/bams-sanskrit-mindmap/chapter1_notes.py
"""
BAMS 1st Year Sanskrit
Chapter 1 – Sanjña Prakarana (Laghu Siddhanta Kaumudi)
Aesthetic Multi-Page PDF Notes
"""
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
import matplotlib.patheffects as pe
from matplotlib.backends.backend_pdf import PdfPages
import numpy as np
# ══════════════════════════════════════════════════════════════════════════════
# THEME
# ══════════════════════════════════════════════════════════════════════════════
BG = "#0f0e17"
CARD = "#1a1a2e"
ACCENT1 = "#f4a261" # gold-orange
ACCENT2 = "#4cc9f0" # sky blue
ACCENT3 = "#06d6a0" # mint green
ACCENT4 = "#f72585" # hot pink
ACCENT5 = "#a29bfe" # lavender
WHITE = "#f0f0f0"
MUTED = "#aaaacc"
DIVIDER = "#2a2a4a"
HEADING_COLORS = [ACCENT1, ACCENT2, ACCENT3, ACCENT4, ACCENT5]
def star_bg(ax, n=200, seed=42):
rng = np.random.default_rng(seed)
ax.scatter(rng.uniform(0,1,n), rng.uniform(0,1,n),
s=rng.uniform(0.2,2.8,n), color='white', alpha=0.22,
transform=ax.transAxes, zorder=0, clip_on=False)
def gradient_rect(ax, x, y, w, h, color, alpha=0.18, zorder=1):
box = FancyBboxPatch((x,y), w, h,
boxstyle="round,pad=0.01",
facecolor=color, edgecolor='none',
alpha=alpha, zorder=zorder)
ax.add_patch(box)
def section_header(ax, x, y, text, color, fontsize=13):
ax.text(x, y, text, fontsize=fontsize, color=color, fontweight='bold',
va='top', ha='left', transform=ax.transAxes,
path_effects=[pe.withStroke(linewidth=2, foreground='black')])
# underline
ax.axhline(y=y - 0.002, xmin=x, xmax=x+0.6,
color=color, lw=1.2, alpha=0.5, transform=ax.transAxes)
def body_text(ax, x, y, text, color=WHITE, fontsize=9.5, style='normal'):
ax.text(x, y, text, fontsize=fontsize, color=color,
va='top', ha='left', transform=ax.transAxes,
style=style, wrap=True,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
def bullet(ax, x, y, text, color=ACCENT1, fontsize=9.2):
ax.text(x, y, "◆", fontsize=7, color=color, va='top', ha='left',
transform=ax.transAxes)
ax.text(x+0.025, y, text, fontsize=fontsize, color=WHITE, va='top',
ha='left', transform=ax.transAxes,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
def card(ax, x, y, w, h, title, lines, hcolor, seed=0):
"""Draw a rounded card with title + bullet lines."""
# background
box = FancyBboxPatch((x, y), w, h,
boxstyle="round,pad=0.012",
facecolor=CARD, edgecolor=hcolor,
linewidth=1.5, alpha=0.92,
transform=ax.transAxes, zorder=3)
ax.add_patch(box)
# title bar
tbar = FancyBboxPatch((x, y+h-0.065), w, 0.062,
boxstyle="round,pad=0.008",
facecolor=hcolor, edgecolor='none', alpha=0.85,
transform=ax.transAxes, zorder=4)
ax.add_patch(tbar)
ax.text(x + w/2, y+h-0.033, title,
fontsize=9, color='#0d0d0d', fontweight='bold',
ha='center', va='center', transform=ax.transAxes, zorder=5,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
for k, line in enumerate(lines):
ax.text(x+0.014, y+h-0.09 - k*0.042, f"• {line}",
fontsize=8.2, color=WHITE, va='top', ha='left',
transform=ax.transAxes, zorder=5,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
def page_frame(fig, title_main, title_sub, page_num, total_pages, color):
fig.patch.set_facecolor(BG)
ax = fig.add_axes([0, 0, 1, 1])
ax.set_xlim(0,1); ax.set_ylim(0,1)
ax.axis('off')
ax.set_facecolor(BG)
# stars
star_bg(ax, n=220, seed=page_num*7)
# top banner
banner = FancyBboxPatch((0.0, 0.935), 1.0, 0.065,
boxstyle="square,pad=0",
facecolor=color, edgecolor='none', alpha=0.90,
transform=ax.transAxes, zorder=3)
ax.add_patch(banner)
ax.text(0.5, 0.968, title_main, fontsize=16, color='#0d0d0d',
fontweight='bold', ha='center', va='center',
transform=ax.transAxes, zorder=4)
# subtitle bar
subbar = FancyBboxPatch((0.0, 0.900), 1.0, 0.034,
boxstyle="square,pad=0",
facecolor=CARD, edgecolor='none', alpha=0.97,
transform=ax.transAxes, zorder=3)
ax.add_patch(subbar)
ax.text(0.5, 0.917, title_sub, fontsize=10, color=color,
ha='center', va='center', style='italic',
transform=ax.transAxes, zorder=4)
# bottom footer
foot = FancyBboxPatch((0.0, 0.0), 1.0, 0.032,
boxstyle="square,pad=0",
facecolor=CARD, edgecolor='none', alpha=0.97,
transform=ax.transAxes, zorder=3)
ax.add_patch(foot)
ax.text(0.5, 0.016,
f"BAMS 1st Year · Sanskrit · Laghu Siddhanta Kaumudi · Page {page_num}/{total_pages}",
fontsize=7.5, color=MUTED, ha='center', va='center',
transform=ax.transAxes, zorder=4)
# side accent lines
ax.plot([0.008, 0.008], [0.035, 0.897], color=color, lw=2.5, alpha=0.35,
transform=ax.transAxes, zorder=2)
ax.plot([0.992, 0.992], [0.035, 0.897], color=color, lw=2.5, alpha=0.35,
transform=ax.transAxes, zorder=2)
return ax
# ══════════════════════════════════════════════════════════════════════════════
# PAGE DATA
# ══════════════════════════════════════════════════════════════════════════════
out = "/home/daytona/workspace/bams-sanskrit-mindmap/BAMS_Sanskrit_Ch1_SanjñaPrakarana.pdf"
TOTAL = 5
with PdfPages(out) as pdf:
# ══════════════════════════════════════════════════════════════════════════
# PAGE 1 – OVERVIEW & INTRODUCTION
# ══════════════════════════════════════════════════════════════════════════
fig = plt.figure(figsize=(11.69, 8.27)) # A4 landscape
ax = page_frame(fig,
"Chapter 1 · Sanjña Prakarana (Sanjña Prakaranam)",
"Laghu Siddhanta Kaumudi · BAMS 1st Year Sanskrit",
1, TOTAL, ACCENT1)
# ── Overview card (left) ─────────────────────────────────────────────────
card(ax, 0.03, 0.66, 0.44, 0.22, "WHAT IS SANJÑA PRAKARANA?",
["Sanjña = Technical term / Name",
"Prakarana = Chapter / Section",
"Deals with technical terms used in Paninian grammar",
"Foundation for understanding all grammar rules (sutras)",
"From Laghu Siddhanta Kaumudi by Varadaraja"],
ACCENT1)
# ── Author card (right) ──────────────────────────────────────────────────
card(ax, 0.53, 0.66, 0.44, 0.22, "ABOUT THE TEXT",
["Laghu Siddhanta Kaumudi – by Varadaraja",
"Varadaraja = student of Bhattoji Dikshita",
"Condensed from Vaiyakarana Siddhanta Kaumudi",
"Contains ~1270 sutras (approx. 30% of Ashtadhyayi)",
"Best entry-level text for Paninian grammar"],
ACCENT2)
# ── Importance ───────────────────────────────────────────────────────────
ax.text(0.03, 0.64, "WHY IS THIS CHAPTER IMPORTANT?",
fontsize=11.5, color=ACCENT3, fontweight='bold',
va='top', transform=ax.transAxes,
path_effects=[pe.withStroke(linewidth=2, foreground='black')])
ax.axhline(y=0.625, xmin=0.03, xmax=0.97,
color=ACCENT3, lw=0.8, alpha=0.4, transform=ax.transAxes)
reasons = [
("It-Sanjña (इत्संज्ञा)", "Markers used to indicate phonological operations – not pronounced but carry meaning"),
("Swara Classification", "Classifies all vowels (Swaras) into short, long, pluta, and Anudatta/Udatta/Svarita"),
("Sthana & Prayatna", "Place (Sthana) and effort (Prayatna) of articulation for every letter"),
("Savarna (सवर्ण)", "Defines homogeneous sounds – critical for Sandhi and substitution rules"),
("Anubandhas", "Auxiliary markers in sutras that trigger specific grammatical operations"),
]
for k, (term, desc) in enumerate(reasons):
ypos = 0.598 - k * 0.082
# coloured pill
pill = FancyBboxPatch((0.03, ypos-0.003), 0.22, 0.042,
boxstyle="round,pad=0.006",
facecolor=HEADING_COLORS[k], edgecolor='none',
alpha=0.85, transform=ax.transAxes, zorder=3)
ax.add_patch(pill)
ax.text(0.14, ypos+0.018, term, fontsize=8.5,
color='#0d0d0d', fontweight='bold', ha='center', va='center',
transform=ax.transAxes, zorder=4)
ax.text(0.265, ypos+0.018, desc, fontsize=8.5,
color=WHITE, va='center', ha='left',
transform=ax.transAxes, zorder=3,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
pdf.savefig(fig, facecolor=BG, bbox_inches='tight')
plt.close()
# ══════════════════════════════════════════════════════════════════════════
# PAGE 2 – IT-SANJÑA (ANUBANDHA)
# ══════════════════════════════════════════════════════════════════════════
fig = plt.figure(figsize=(11.69, 8.27))
ax = page_frame(fig,
"It-Sanjña (इत्संज्ञा) · Anubandha Markers",
"Chapter 1 · Sanjña Prakarana",
2, TOTAL, ACCENT2)
ax.text(0.05, 0.875, "DEFINITION ◆ Sutra: 1.3.2 – upadese'janunasika it",
fontsize=10, color=ACCENT2, fontweight='bold',
va='top', transform=ax.transAxes,
path_effects=[pe.withStroke(linewidth=2, foreground='black')])
body_text(ax, 0.05, 0.848,
'"An anunasika (nasal) vowel in an upadesa (grammatical recitation) is called It."',
color=MUTED, fontsize=9.5, style='italic')
body_text(ax, 0.05, 0.818,
"It-sanjña letters are technical markers (anubandhas) added to roots, suffixes, and sutras.\n"
"They are NEVER actually pronounced in the final word — they serve only as grammatical signals.",
color=WHITE, fontsize=9.2)
# table of It markers
headers = ["It Marker", "Type", "Location", "Function / Effect"]
rows = [
["a (अ)", "Short a", "End of verb root (Dhatu)", "Indicates the root takes Atmanepada endings"],
["i (इ)", "Short i", "End of Krit suffix", "Indicates Guna does NOT apply to the root vowel"],
["u (उ)", "Short u", "End of suffix", "Indicates the suffix is Nit – prevents Vriddhi"],
["n (ण्)", "Consonant N", "After prefix", "Converts 'n' to retroflex 'N' (Natva rule)"],
["k (क्)", "Consonant K", "End of suffix / sutra", "Kit suffix – prevents Guna/Vriddhi of root vowel"],
["p (प्)", "Consonant P", "End of suffix", "Pit suffix – specific phonological behaviour"],
["m (म्)", "Consonant M", "End of taddhita suffix", "Mit suffix – indicates specific accent"],
["t (त्)", "Consonant T", "End of suffix", "Tit suffix – inserted before final consonant of base"],
]
col_widths = [0.14, 0.10, 0.21, 0.44]
col_starts = [0.03, 0.18, 0.29, 0.51]
row_h = 0.052
# header row
for j, (hdr, xs, wd) in enumerate(zip(headers, col_starts, col_widths)):
hbox = FancyBboxPatch((xs, 0.71), wd-0.005, 0.038,
boxstyle="round,pad=0.005",
facecolor=ACCENT2, edgecolor='none', alpha=0.9,
transform=ax.transAxes, zorder=3)
ax.add_patch(hbox)
ax.text(xs + (wd-0.005)/2, 0.729, hdr,
fontsize=8.5, color='#0d0d0d', fontweight='bold',
ha='center', va='center', transform=ax.transAxes, zorder=4)
for i, row in enumerate(rows):
yrow = 0.704 - i * row_h
rowcol = CARD if i % 2 == 0 else "#1f1f38"
full_bg = FancyBboxPatch((0.03, yrow), 0.930, row_h-0.004,
boxstyle="round,pad=0.004",
facecolor=rowcol, edgecolor=DIVIDER,
linewidth=0.5, alpha=0.88,
transform=ax.transAxes, zorder=3)
ax.add_patch(full_bg)
for j, (cell, xs, wd) in enumerate(zip(row, col_starts, col_widths)):
tc = ACCENT1 if j == 0 else WHITE
ax.text(xs+0.008, yrow + row_h/2 - 0.003, cell,
fontsize=8.0, color=tc, va='center',
transform=ax.transAxes, zorder=4,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
# Memory tip
tip_box = FancyBboxPatch((0.03, 0.042), 0.94, 0.072,
boxstyle="round,pad=0.01",
facecolor="#1a2e1a", edgecolor=ACCENT3,
linewidth=1.5, alpha=0.92,
transform=ax.transAxes, zorder=3)
ax.add_patch(tip_box)
ax.text(0.05, 0.097, "MEMORY TIP:", fontsize=9, color=ACCENT3,
fontweight='bold', va='center', transform=ax.transAxes, zorder=4)
ax.text(0.19, 0.097,
"It letters are like 'silent instructions' baked into the grammar code – they guide rules but never appear in the spoken or written word.",
fontsize=8.8, color=WHITE, va='center', transform=ax.transAxes, zorder=4,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
pdf.savefig(fig, facecolor=BG, bbox_inches='tight')
plt.close()
# ══════════════════════════════════════════════════════════════════════════
# PAGE 3 – SWARA CLASSIFICATION & VARNA SAMAMNAYA
# ══════════════════════════════════════════════════════════════════════════
fig = plt.figure(figsize=(11.69, 8.27))
ax = page_frame(fig,
"Swara (Vowel) Classification & Varna Samamnaya",
"Chapter 1 · Sanjña Prakarana",
3, TOTAL, ACCENT3)
# Left column: Swara types
ax.text(0.03, 0.878, "SWARA (VOWEL) CLASSIFICATION",
fontsize=11, color=ACCENT3, fontweight='bold',
va='top', transform=ax.transAxes,
path_effects=[pe.withStroke(linewidth=2, foreground='black')])
ax.axhline(y=0.868, xmin=0.03, xmax=0.50, color=ACCENT3,
lw=0.8, alpha=0.4, transform=ax.transAxes)
swara_data = [
("Hrasva (ह्रस्व)", "Short", "a, i, u, r̥, l̥", ACCENT1, "1 Matra (unit of time)"),
("Dirgha (दीर्घ)", "Long", "aa, ii, uu, r̥r̥", ACCENT2, "2 Matras"),
("Pluta (प्लुत)", "Prolonged", "a3, i3, u3", ACCENT4, "3 Matras — Vedic chanting"),
("Udatta (उदात्त)", "High tone", "Marked with acute ′", ACCENT5, "High-pitched accent"),
("Anudatta (अनुदात्त)", "Low tone", "Marked with underscore _", ACCENT3, "Low-pitched accent"),
("Svarita (स्वरित)", "Mixed tone", "Marked with vertical |", ACCENT1, "Rising-falling tone"),
]
for k, (name, eng, eg, col, note) in enumerate(swara_data):
y0 = 0.840 - k * 0.095
pill = FancyBboxPatch((0.03, y0), 0.200, 0.060,
boxstyle="round,pad=0.008",
facecolor=col, edgecolor='none', alpha=0.82,
transform=ax.transAxes, zorder=3)
ax.add_patch(pill)
ax.text(0.130, y0+0.032, name, fontsize=8.8, color='#0d0d0d',
fontweight='bold', ha='center', va='center',
transform=ax.transAxes, zorder=4)
ax.text(0.244, y0+0.042, f"({eng})", fontsize=8.2, color=col,
fontweight='bold', va='center', transform=ax.transAxes, zorder=4,
path_effects=[pe.withStroke(linewidth=1.2, foreground='black')])
ax.text(0.244, y0+0.020, f"Eg: {eg}", fontsize=8.0, color=WHITE,
va='center', transform=ax.transAxes, zorder=4,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
ax.text(0.244, y0+0.002, f"→ {note}", fontsize=7.5, color=MUTED,
va='center', transform=ax.transAxes, zorder=4)
# Right column: Maheshvara Sutras
ax.text(0.54, 0.878, "MAHESHVARA SUTRAS (Shiva Sutras)",
fontsize=11, color=ACCENT4, fontweight='bold',
va='top', transform=ax.transAxes,
path_effects=[pe.withStroke(linewidth=2, foreground='black')])
ax.axhline(y=0.868, xmin=0.54, xmax=0.98, color=ACCENT4,
lw=0.8, alpha=0.4, transform=ax.transAxes)
body_text(ax, 0.54, 0.850,
"14 sutras revealed to Panini by Lord Shiva's drum (Damaru).\n"
"They list all Sanskrit phonemes in a specific order\n"
"enabling Panini to write shorthand notations (Pratyaharas).",
color=WHITE, fontsize=9.0)
sutras = [
"1. a i u N", "2. r̥ l̥ K",
"3. e o N", "4. ai au C",
"5. ha ya va ra T", "6. la N",
"7. na ma na na nam M", "8. jha bha N",
"9. gha dha dha S", "10. ja ba ga da da SH",
"11. kha pha cha tha tha ca ta ta V", "12. ka pa Y",
"13. sha sha sa R", "14. ha L",
]
for k, s in enumerate(sutras):
col_idx = k % 2
xs_s = 0.54 + col_idx * 0.235
ys_s = 0.720 - (k // 2) * 0.068
sbox = FancyBboxPatch((xs_s, ys_s), 0.218, 0.055,
boxstyle="round,pad=0.006",
facecolor=CARD, edgecolor=ACCENT4,
linewidth=1.0, alpha=0.90,
transform=ax.transAxes, zorder=3)
ax.add_patch(sbox)
ax.text(xs_s + 0.109, ys_s + 0.027, s,
fontsize=8.2, color=WHITE, ha='center', va='center',
transform=ax.transAxes, zorder=4,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
# Pratyahara note
note_box = FancyBboxPatch((0.54, 0.038), 0.425, 0.070,
boxstyle="round,pad=0.01",
facecolor="#1e1428", edgecolor=ACCENT5,
linewidth=1.5, alpha=0.93,
transform=ax.transAxes, zorder=3)
ax.add_patch(note_box)
ax.text(0.555, 0.090, "PRATYAHARA:", fontsize=9, color=ACCENT5,
fontweight='bold', va='center', transform=ax.transAxes, zorder=4)
ax.text(0.555, 0.063,
"A Pratyahara is a shorthand for a group of phonemes.\n"
"Eg: 'AC' = all vowels | 'HAL' = all consonants | 'AL' = all letters",
fontsize=8.5, color=WHITE, va='center', transform=ax.transAxes, zorder=4,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
pdf.savefig(fig, facecolor=BG, bbox_inches='tight')
plt.close()
# ══════════════════════════════════════════════════════════════════════════
# PAGE 4 – STHANA & PRAYATNA + SAVARNA
# ══════════════════════════════════════════════════════════════════════════
fig = plt.figure(figsize=(11.69, 8.27))
ax = page_frame(fig,
"Sthana (Place) · Prayatna (Effort) · Savarna",
"Chapter 1 · Sanjña Prakarana",
4, TOTAL, ACCENT4)
# Sthana table
ax.text(0.03, 0.878, "STHANA (Place of Articulation)",
fontsize=11, color=ACCENT4, fontweight='bold',
va='top', transform=ax.transAxes,
path_effects=[pe.withStroke(linewidth=2, foreground='black')])
ax.axhline(y=0.866, xmin=0.03, xmax=0.62, color=ACCENT4,
lw=0.8, alpha=0.4, transform=ax.transAxes)
sthana_data = [
("Kantha (कण्ठ)", "Throat / Velar", "a, aa, ka-varga (k kh g gh ng), h, visarga", ACCENT1),
("Talu (तालु)", "Palatal", "i, ii, ca-varga (c ch j jh ñ), y, sh", ACCENT2),
("Murdha (मूर्धा)", "Retroflex / Cerebral","r̥, r̥r̥, ta-varga (T Th D Dh N), r, Sh", ACCENT4),
("Danta (दन्त)", "Dental", "l̥, ta-varga (t th d dh n), l, s", ACCENT3),
("Oshtha (ओष्ठ)", "Labial", "u, uu, pa-varga (p ph b bh m), Upadhmaniya", ACCENT5),
("Kantha-Talu", "Throat + Palate", "e, ai", ACCENT1),
("Kantha-Oshtha", "Throat + Lips", "o, au", ACCENT2),
("Danta-Oshtha", "Teeth + Lips", "v (labio-dental)", ACCENT3),
("Nasika (नासिका)","Nasal", "All nasal consonants (ng ñ N n m)", ACCENT4),
]
for k, (sth, eng, letters, col) in enumerate(sthana_data):
y0 = 0.843 - k * 0.073
bg = FancyBboxPatch((0.03, y0), 0.56, 0.062,
boxstyle="round,pad=0.005",
facecolor=CARD if k%2==0 else "#1f1f38",
edgecolor=col, linewidth=0.9, alpha=0.90,
transform=ax.transAxes, zorder=3)
ax.add_patch(bg)
ax.text(0.042, y0+0.032, sth, fontsize=8.5, color=col,
fontweight='bold', va='center', transform=ax.transAxes,
zorder=4,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
ax.text(0.220, y0+0.042, eng, fontsize=7.8, color=MUTED,
va='center', transform=ax.transAxes, zorder=4)
ax.text(0.220, y0+0.018, letters, fontsize=7.8, color=WHITE,
va='center', transform=ax.transAxes, zorder=4,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
# Prayatna column
ax.text(0.64, 0.878, "PRAYATNA (Effort of Articulation)",
fontsize=11, color=ACCENT5, fontweight='bold',
va='top', transform=ax.transAxes,
path_effects=[pe.withStroke(linewidth=2, foreground='black')])
ax.axhline(y=0.866, xmin=0.64, xmax=0.98, color=ACCENT5,
lw=0.8, alpha=0.4, transform=ax.transAxes)
prayatna_groups = {
"BAHYA PRAYATNA\n(External Effort)": {
"color": ACCENT2,
"items": [
("Sprishta", "Complete contact – stops (k,c,T,t,p…)"),
("Ishat Sprishta", "Slight contact – semi-vowels (y,r,l,v)"),
("Vivrita", "Open – vowels & fricatives (h,sh,s)"),
]
},
"ABHYANTARA PRAYATNA\n(Internal Effort)": {
"color": ACCENT4,
"items": [
("Ghosa", "Voiced – vowels & voiced consonants"),
("Aghosa", "Voiceless – k,kh,c,ch,T,Th,t,th,p,ph,sh,Sh,s"),
("Alpaprana", "Unaspirated – 1st & 3rd in each varga"),
("Mahaprana", "Aspirated – 2nd & 4th in each varga"),
("Anunasika", "Nasal – 5th in each varga (ng,ñ,N,n,m)"),
]
},
}
yp = 0.843
for grp, gdata in prayatna_groups.items():
gc = gdata["color"]
grp_box = FancyBboxPatch((0.64, yp - 0.018), 0.34, 0.052,
boxstyle="round,pad=0.006",
facecolor=gc, edgecolor='none', alpha=0.85,
transform=ax.transAxes, zorder=3)
ax.add_patch(grp_box)
ax.text(0.81, yp+0.009, grp, fontsize=8.0, color='#0d0d0d',
fontweight='bold', ha='center', va='center',
transform=ax.transAxes, zorder=4, multialignment='center')
yp -= 0.055
for term, desc in gdata["items"]:
row_bg = FancyBboxPatch((0.64, yp-0.004), 0.34, 0.046,
boxstyle="round,pad=0.004",
facecolor=CARD, edgecolor=gc,
linewidth=0.8, alpha=0.88,
transform=ax.transAxes, zorder=3)
ax.add_patch(row_bg)
ax.text(0.652, yp+0.030, term, fontsize=8.0, color=gc,
fontweight='bold', va='center', transform=ax.transAxes,
zorder=4,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
ax.text(0.652, yp+0.008, desc, fontsize=7.8, color=WHITE,
va='center', transform=ax.transAxes, zorder=4,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
yp -= 0.050
# Savarna box
sv = FancyBboxPatch((0.03, 0.038), 0.94, 0.078,
boxstyle="round,pad=0.012",
facecolor="#1a2b1a", edgecolor=ACCENT3,
linewidth=1.8, alpha=0.94,
transform=ax.transAxes, zorder=3)
ax.add_patch(sv)
ax.text(0.05, 0.100, "SAVARNA (सवर्ण) — Homogeneous Sounds:",
fontsize=9.5, color=ACCENT3, fontweight='bold',
va='center', transform=ax.transAxes, zorder=4)
ax.text(0.05, 0.070,
"Two sounds are Savarna if they share the same Sthana (place) AND same Abhyantara Prayatna (internal effort).\n"
"Eg: 'a' and 'aa' are Savarna | 'i' and 'ii' are Savarna | Short & Long vowels of same place = Savarna.",
fontsize=8.8, color=WHITE, va='center', transform=ax.transAxes, zorder=4,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
pdf.savefig(fig, facecolor=BG, bbox_inches='tight')
plt.close()
# ══════════════════════════════════════════════════════════════════════════
# PAGE 5 – KEY SUTRAS, QUICK REVISION TABLE & EXAM TIPS
# ══════════════════════════════════════════════════════════════════════════
fig = plt.figure(figsize=(11.69, 8.27))
ax = page_frame(fig,
"Key Sutras · Quick Revision · Exam Tips",
"Chapter 1 · Sanjña Prakarana",
5, TOTAL, ACCENT5)
# Key sutras
ax.text(0.03, 0.878, "IMPORTANT SUTRAS TO MEMORISE",
fontsize=11, color=ACCENT5, fontweight='bold',
va='top', transform=ax.transAxes,
path_effects=[pe.withStroke(linewidth=2, foreground='black')])
ax.axhline(y=0.866, xmin=0.03, xmax=0.97, color=ACCENT5,
lw=0.8, alpha=0.4, transform=ax.transAxes)
key_sutras = [
("1.3.2", "Upadese'janunasika it", "Nasal vowel in upadesa = It (marker)"),
("1.3.3", "Halantyam", "Final consonant of a sutra/suffix = It"),
("1.3.9", "Tasya lopaḥ", "Lopa (deletion) of It letters — they vanish"),
("1.1.69", "Anuditta atmanepade", "Anudatta vowel in Dhatu = Atmanepada verb"),
("1.1.70", "Tapara stata-kala-sya", "T-final marker = only that duration (Hrasva/Dirgha)"),
("1.1.68", "Svarasya", "Rule specifically about vowels (svaras)"),
("8.4.68", "A a", "Savarna = same Sthana and Prayatna"),
("1.1.60", "Adicante savarne dirgha", "Two Savarna vowels merge into one long (Dirgha) vowel"),
]
col_w = [0.075, 0.22, 0.60]
col_x = [0.03, 0.115, 0.345]
hdr_labels = ["Sutra No.", "Sutra (Transliterated)", "Meaning / Application"]
# header
for j, (hdr, xs, wd) in enumerate(zip(hdr_labels, col_x, col_w)):
hb = FancyBboxPatch((xs, 0.808), wd-0.005, 0.040,
boxstyle="round,pad=0.004",
facecolor=ACCENT5, edgecolor='none', alpha=0.88,
transform=ax.transAxes, zorder=3)
ax.add_patch(hb)
ax.text(xs+(wd-0.005)/2, 0.828, hdr, fontsize=8.5,
color='#0d0d0d', fontweight='bold', ha='center', va='center',
transform=ax.transAxes, zorder=4)
for i, (num, sutra, meaning) in enumerate(key_sutras):
yr = 0.802 - i * 0.063
bg2 = FancyBboxPatch((0.03, yr), 0.94, 0.053,
boxstyle="round,pad=0.004",
facecolor=CARD if i%2==0 else "#1f1f38",
edgecolor=DIVIDER, linewidth=0.5, alpha=0.88,
transform=ax.transAxes, zorder=3)
ax.add_patch(bg2)
ax.text(0.068, yr+0.026, num, fontsize=8.2, color=ACCENT5,
fontweight='bold', ha='center', va='center',
transform=ax.transAxes, zorder=4,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
ax.text(0.120, yr+0.026, sutra, fontsize=8.2, color=ACCENT2,
va='center', transform=ax.transAxes, zorder=4, style='italic',
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
ax.text(0.350, yr+0.026, meaning, fontsize=8.2, color=WHITE,
va='center', transform=ax.transAxes, zorder=4,
path_effects=[pe.withStroke(linewidth=1, foreground='black')])
# Exam tips cards (bottom row)
tips = [
("EXAM TIPS", ACCENT1, [
"Define Sanjña, It-Sanjña in your own words",
"List all Sthanas with examples of letters",
"Distinguish Savarna vs. non-Savarna",
"State any 3 key sutras with meaning",
]),
("COMMON MISTAKES", ACCENT4, [
"Confusing Sthana with Prayatna",
"Forgetting that It letters are deleted (Lopa)",
"Mixing up Hrasva/Dirgha/Pluta durations",
"Not knowing Ghosa vs Aghosa distinction",
]),
("CONNECTIONS", ACCENT3, [
"Sanjña → foundation for Sandhi rules (Ch 2-4)",
"Savarna → used in Savarna-Dirgha Sandhi",
"Sthana-Prayatna → used in Shcutva & Stutva Sandhi",
"It-Sanjña → used throughout Dhatu Paatha",
]),
]
for k, (title, col, items) in enumerate(tips):
tx = 0.03 + k * 0.325
card(ax, tx, 0.038, 0.310, 0.250, title, items, col)
pdf.savefig(fig, facecolor=BG, bbox_inches='tight')
plt.close()
print(f"Saved -> {out}")