Make aesthetic mind map note for bams sanskrit 1st year
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
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}")