Make poster of this case ...make editable inforgraphic poater
mkdir -p /tmp/workspace/asd-poster && ls /tmp/workspace/
~/asd-poster/create_poster.py
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.oxml.ns import qn
from lxml import etree
from io import BytesIO
# ── Colours ──────────────────────────────────────────────────────────────────
DEEP_TEAL = RGBColor(0x00, 0x5C, 0x7A) # header / panel headers
TEAL_MID = RGBColor(0x00, 0x8B, 0xA8) # accent borders
TEAL_LIGHT = RGBColor(0xD0, 0xF0, 0xF5) # panel background
GOLD = RGBColor(0xE8, 0xA1, 0x00) # highlight / bullet icons
ORANGE_ACC = RGBColor(0xF4, 0x6A, 0x1C) # Rx badge
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
DARK_GREY = RGBColor(0x22, 0x22, 0x22)
MID_GREY = RGBColor(0x44, 0x44, 0x44)
LIGHT_GREY = RGBColor(0xF5, 0xF5, 0xF5)
GREEN_IMP = RGBColor(0x1A, 0x7A, 0x3C) # improvement colour
GREEN_LIGHT = RGBColor(0xD4, 0xED, 0xDA)
RED_LIGHT = RGBColor(0xFF, 0xEB, 0xEB)
AMBER_LIGHT = RGBColor(0xFF, 0xF3, 0xCD)
SECTION_BG = RGBColor(0x00, 0x4D, 0x66) # darker header background
# ── Slide dimensions (A1-ish portrait poster: 24" wide × 36" tall) ───────────
W = Inches(24)
H = Inches(36)
prs = Presentation()
prs.slide_width = W
prs.slide_height = H
blank_layout = prs.slide_layouts[6]
slide = prs.slides.add_slide(blank_layout)
# ─────────────────────────────────────────────────────────────────────────────
# HELPER FUNCTIONS
# ─────────────────────────────────────────────────────────────────────────────
def add_rect(slide, x, y, w, h, fill_color, line_color=None, line_width_pt=0):
shape = slide.shapes.add_shape(1, x, y, w, h) # MSO_SHAPE_TYPE.RECTANGLE
shape.fill.solid()
shape.fill.fore_color.rgb = fill_color
if line_color:
shape.line.color.rgb = line_color
shape.line.width = Pt(line_width_pt)
else:
shape.line.fill.background()
return shape
def add_textbox(slide, x, y, w, h, text, font_name="Calibri", font_size=11,
bold=False, italic=False, color=DARK_GREY, align=PP_ALIGN.LEFT,
wrap=True, v_anchor=MSO_ANCHOR.TOP,
margin_l=Inches(0.08), margin_r=Inches(0.08),
margin_t=Inches(0.04), margin_b=Inches(0.04)):
tb = slide.shapes.add_textbox(x, y, w, h)
tf = tb.text_frame
tf.word_wrap = wrap
tf.vertical_anchor = v_anchor
tf.margin_left = margin_l
tf.margin_right = margin_r
tf.margin_top = margin_t
tf.margin_bottom = margin_b
p = tf.paragraphs[0]
p.alignment = align
run = p.add_run()
run.text = text
run.font.name = font_name
run.font.size = Pt(font_size)
run.font.bold = bold
run.font.italic = italic
run.font.color.rgb = color
return tb
def add_multiline_textbox(slide, x, y, w, h, lines, font_name="Calibri",
font_size=11, bold=False, color=DARK_GREY,
align=PP_ALIGN.LEFT, line_spacing_pt=None,
margin_l=Inches(0.1), margin_r=Inches(0.08)):
"""lines: list of (text, bold_override, font_size_override, color_override)"""
tb = slide.shapes.add_textbox(x, y, w, h)
tf = tb.text_frame
tf.word_wrap = True
tf.margin_left = margin_l
tf.margin_right = margin_r
tf.margin_top = Inches(0.04)
tf.margin_bottom = Inches(0.04)
first = True
for item in lines:
if isinstance(item, str):
txt, b, fs, col = item, bold, font_size, color
else:
txt = item[0]
b = item[1] if len(item) > 1 else bold
fs = item[2] if len(item) > 2 else font_size
col = item[3] if len(item) > 3 else color
if first:
p = tf.paragraphs[0]
first = False
else:
p = tf.add_paragraph()
p.alignment = align
if line_spacing_pt:
from pptx.util import Pt as PPt
from pptx.oxml.ns import qn
from lxml import etree
spcAft = etree.SubElement(p._p, qn('a:spcAft'))
spcPts = etree.SubElement(spcAft, qn('a:spcPts'))
spcPts.set('val', str(int(line_spacing_pt * 100)))
run = p.add_run()
run.text = txt
run.font.name = font_name
run.font.size = Pt(fs)
run.font.bold = b
run.font.color.rgb = col
return tb
def section_header(slide, x, y, w, h, title, subtitle=None):
"""Coloured banner with title."""
add_rect(slide, x, y, w, h, DEEP_TEAL)
# accent bar left
add_rect(slide, x, y, Inches(0.08), h, GOLD)
tb = slide.shapes.add_textbox(x + Inches(0.15), y, w - Inches(0.2), h)
tf = tb.text_frame
tf.word_wrap = False
tf.margin_left = Inches(0.05)
tf.margin_top = 0
tf.margin_bottom = 0
p = tf.paragraphs[0]
p.alignment = PP_ALIGN.LEFT
run = p.add_run()
run.text = title.upper()
run.font.name = "Calibri"
run.font.size = Pt(15)
run.font.bold = True
run.font.color.rgb = WHITE
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
if subtitle:
p2 = tf.add_paragraph()
r2 = p2.add_run()
r2.text = subtitle
r2.font.size = Pt(10)
r2.font.color.rgb = TEAL_LIGHT
return tb
def panel_header(slide, x, y, w, h, title, bg=TEAL_MID):
add_rect(slide, x, y, w, h, bg)
tb = slide.shapes.add_textbox(x + Inches(0.08), y, w - Inches(0.1), h)
tf = tb.text_frame
tf.word_wrap = False
tf.margin_left = 0; tf.margin_top = 0; tf.margin_bottom = 0
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
p = tf.paragraphs[0]
run = p.add_run()
run.text = title.upper()
run.font.name = "Calibri"
run.font.size = Pt(12)
run.font.bold = True
run.font.color.rgb = WHITE
def bullet_list(slide, x, y, w, h, items, font_size=10.5, color=DARK_GREY,
bullet_color=TEAL_MID, line_h=Inches(0.30)):
"""Render bullet points with coloured dot."""
cy = y
for item in items:
# dot
dot = slide.shapes.add_shape(9, x, cy + Inches(0.08), Inches(0.12), Inches(0.12)) # oval
dot.fill.solid()
dot.fill.fore_color.rgb = bullet_color
dot.line.fill.background()
add_textbox(slide, x + Inches(0.18), cy, w - Inches(0.18), line_h,
item, font_size=font_size, color=color)
cy += line_h
return cy
def follow_up_row(slide, x, y, w, h, date, symptoms, rx, bg):
add_rect(slide, x, y, w, h, bg, line_color=TEAL_MID, line_width_pt=0.5)
col_w = [Inches(1.8), Inches(7.5), Inches(4.5)]
cx = x
for i, (txt, cw) in enumerate(zip([date, symptoms, rx], col_w)):
b = (i == 0)
add_textbox(slide, cx + Inches(0.05), y + Inches(0.04),
cw - Inches(0.1), h - Inches(0.08),
txt, font_size=9.5, bold=b,
color=DEEP_TEAL if i == 0 else DARK_GREY,
wrap=True)
cx += cw
# ═════════════════════════════════════════════════════════════════════════════
# BACKGROUND
# ═════════════════════════════════════════════════════════════════════════════
add_rect(slide, 0, 0, W, H, LIGHT_GREY)
# Left accent stripe
add_rect(slide, 0, 0, Inches(0.35), H, DEEP_TEAL)
# Top header band
HEADER_H = Inches(2.2)
add_rect(slide, 0, 0, W, HEADER_H, SECTION_BG)
# gold accent line under header
add_rect(slide, 0, HEADER_H, W, Inches(0.06), GOLD)
# ═════════════════════════════════════════════════════════════════════════════
# HEADER
# ═════════════════════════════════════════════════════════════════════════════
# Main title
add_textbox(slide, Inches(0.5), Inches(0.12), Inches(22), Inches(0.95),
"A CASE OF AUTISM SPECTRUM DISORDER (ASD)",
font_name="Calibri", font_size=36, bold=True,
color=WHITE, align=PP_ALIGN.CENTER)
add_textbox(slide, Inches(0.5), Inches(1.0), Inches(22), Inches(0.6),
"Treated with Homoeopathic Medicine — Baryta Carbonica 200",
font_name="Calibri", font_size=20, bold=False,
color=TEAL_LIGHT, align=PP_ALIGN.CENTER)
add_textbox(slide, Inches(0.5), Inches(1.55), Inches(22), Inches(0.5),
"Dr. Jaykumar Chandarana | Dr. Harsh Patel | National Journal of Homoeopathy, October 2023 | Periodic Table Row 6",
font_name="Calibri", font_size=13, bold=False,
color=GOLD, align=PP_ALIGN.CENTER)
# ═════════════════════════════════════════════════════════════════════════════
# LAYOUT GRID (3 columns)
# ═════════════════════════════════════════════════════════════════════════════
MARGIN = Inches(0.45)
COL_GAP = Inches(0.3)
COL_W = (W - MARGIN*2 - COL_GAP*2) / 3
TOP_Y = HEADER_H + Inches(0.35)
C1X = MARGIN
C2X = MARGIN + COL_W + COL_GAP
C3X = MARGIN + (COL_W + COL_GAP)*2
# ─────────────────────────────────────────────────────────────────────────────
# COLUMN 1 — Patient Overview + History
# ─────────────────────────────────────────────────────────────────────────────
cy1 = TOP_Y
# ── Patient snapshot card ──────────────────────────────────────────────────
CARD_H = Inches(2.0)
add_rect(slide, C1X, cy1, COL_W, CARD_H, TEAL_LIGHT,
line_color=TEAL_MID, line_width_pt=1.2)
# inner accent top
add_rect(slide, C1X, cy1, COL_W, Inches(0.06), TEAL_MID)
add_textbox(slide, C1X + Inches(0.1), cy1 + Inches(0.1), COL_W - Inches(0.2), Inches(0.45),
"PATIENT SNAPSHOT", font_size=13, bold=True, color=DEEP_TEAL)
snap_items = [
("👦 Age:", "5-year-old boy"),
("📋 Chief complaint:", "ASD with hyperactivity, no eye contact, no speech"),
("🏥 Diagnosed:", "Autism Spectrum Disorder (Neurologist)"),
("⚕ Current therapy:", "Occupational therapy (Gandhinagar)"),
]
cy_snap = cy1 + Inches(0.55)
for label, val in snap_items:
tb = slide.shapes.add_textbox(C1X + Inches(0.15), cy_snap,
COL_W - Inches(0.25), Inches(0.30))
tf = tb.text_frame
tf.word_wrap = True
tf.margin_left = 0; tf.margin_top = 0; tf.margin_bottom = 0
p = tf.paragraphs[0]
r1 = p.add_run(); r1.text = label + " "; r1.font.size = Pt(10); r1.font.bold = True; r1.font.color.rgb = DEEP_TEAL; r1.font.name = "Calibri"
r2 = p.add_run(); r2.text = val; r2.font.size = Pt(10); r2.font.bold = False; r2.font.color.rgb = DARK_GREY; r2.font.name = "Calibri"
cy_snap += Inches(0.31)
cy1 += CARD_H + Inches(0.22)
# ── Chief Complaints ──────────────────────────────────────────────────────
COMP_H = Inches(0.38)
section_header(slide, C1X, cy1, COL_W, COMP_H, "Chief Complaints")
cy1 += COMP_H + Inches(0.05)
add_rect(slide, C1X, cy1, COL_W, Inches(4.3), WHITE,
line_color=TEAL_MID, line_width_pt=0.8)
complaints = [
"Bites himself when angry",
"Puts everything in the mouth",
"Moves on abdomen when in bed",
"No eye-to-eye contact",
"Attention deficit — prominent",
"Does not respond when spoken to",
"Restless 3+ — whole day moving/wandering",
"Hardly sits for 45 minutes",
"Unable to do any responsible activity",
"Likes swinging to and fro",
"No conditioned toilet habits",
"Does not play with / mingle with other children",
"Cries when hungry; indicates food by expression",
"Recognises only mummy & therapist voice",
"Cannot write ABCD; speaks meaningless words",
"Fear of heights; clings to parents",
"Salivation from mouth; open mouth mostly",
"Does not cry when injured",
"Forgetfulness ++",
]
bullet_list(slide, C1X + Inches(0.1), cy1 + Inches(0.1),
COL_W - Inches(0.2), Inches(4.0),
complaints, font_size=9.8, line_h=Inches(0.20))
cy1 += Inches(4.3) + Inches(0.22)
# ── Birth + Developmental History ─────────────────────────────────────────
BH = Inches(0.38)
section_header(slide, C1X, cy1, COL_W, BH, "Birth & Developmental History")
cy1 += BH + Inches(0.05)
bh_text = [
("Birth History", True, 11, DEEP_TEAL),
("2nd full-term child after 8yr sister (normal).", False, 10, DARK_GREY),
("LSCS birth • Birth weight: 3.9 kg", False, 10, DARK_GREY),
("Normal cry at birth • No complaints in pregnancy/delivery", False, 10, DARK_GREY),
("", False, 5, DARK_GREY),
("Developmental History", True, 11, DEEP_TEAL),
("No complaints till 1.5 years.", False, 10, DARK_GREY),
("No speech by age 2 yrs → diagnosed ASD by neurologist.", False, 10, DARK_GREY),
("Therapies started during COVID period.", False, 10, DARK_GREY),
("Walking: 15 months • Dentition: 9 months • Sitting: 8 months", False, 10, DARK_GREY),
]
bh_h = Inches(2.6)
add_rect(slide, C1X, cy1, COL_W, bh_h, WHITE,
line_color=TEAL_MID, line_width_pt=0.8)
add_multiline_textbox(slide, C1X + Inches(0.1), cy1 + Inches(0.1),
COL_W - Inches(0.2), bh_h - Inches(0.15),
bh_text, font_size=10)
cy1 += bh_h + Inches(0.22)
# ── Past History ───────────────────────────────────────────────────────────
PH = Inches(0.38)
section_header(slide, C1X, cy1, COL_W, PH, "Past History")
cy1 += PH + Inches(0.05)
ph_items = [
"Recurrent URTI — cough, cold, coryza (watery) every 10 days",
"Viral fever 2-3 times",
"Falling from bed many times",
]
ph_h = Inches(1.05)
add_rect(slide, C1X, cy1, COL_W, ph_h, WHITE,
line_color=TEAL_MID, line_width_pt=0.8)
bullet_list(slide, C1X + Inches(0.1), cy1 + Inches(0.08),
COL_W - Inches(0.2), ph_h,
ph_items, font_size=10, line_h=Inches(0.32))
cy1 += ph_h + Inches(0.22)
# ─────────────────────────────────────────────────────────────────────────────
# COLUMN 2 — Personal History + Totality + Repertorisation
# ─────────────────────────────────────────────────────────────────────────────
cy2 = TOP_Y
# ── Personal History ───────────────────────────────────────────────────────
PH2 = Inches(0.38)
section_header(slide, C2X, cy2, COL_W, PH2, "Personal History (Miasmatic Profile)")
cy2 += PH2 + Inches(0.05)
personal = [
("Thermal", "Chilly 2+ | Worse: cold drinks, food, cold air/water"),
("Perspiration", "Normal as per season"),
("Appetite", "Decreased | Eructation 3+"),
("Diet", "Vegetarian"),
("Desire", "Sweet, Maize"),
("Aversion", "Dal, Vegetables"),
("Thirst", "As per season | 1.5–2 lit/day"),
("Urine", "No burning, transparent"),
("Bowels", "Smell 1+, slimy, sticky stool | Better in morning | No fixed time"),
("Habits", "Everything puts in mouth"),
("Sleep", "8 hours | No complaints"),
("Dreams", "Grinding of teeth"),
]
ph2_h = Inches(3.9)
add_rect(slide, C2X, cy2, COL_W, ph2_h, WHITE,
line_color=TEAL_MID, line_width_pt=0.8)
cx_label = C2X + Inches(0.1)
cx_val = C2X + Inches(2.1)
cy_ph2 = cy2 + Inches(0.1)
for label, val in personal:
add_textbox(slide, cx_label, cy_ph2, Inches(1.9), Inches(0.28),
label + ":", font_size=9.8, bold=True, color=DEEP_TEAL)
add_textbox(slide, cx_val, cy_ph2, COL_W - Inches(2.2), Inches(0.28),
val, font_size=9.8, color=DARK_GREY, wrap=True)
cy_ph2 += Inches(0.295)
cy2 += ph2_h + Inches(0.22)
# ── Totality of Symptoms ─────────────────────────────────────────────────
TOT_H = Inches(0.38)
section_header(slide, C2X, cy2, COL_W, TOT_H, "Totality of Symptoms")
cy2 += TOT_H + Inches(0.05)
totality = [
"Autism",
"Everything puts in mouth",
"Likes swinging — to and fro movement",
"Developmental milestones delayed",
"Fear of high places; mingling with other children",
"Sits in corners",
"Inattentive; not taking tasks seriously; forgetful",
"Restless; constantly moving, wandering",
"Stool: slimy, offensive, mucus, sticky",
"Thermal: Chilly",
"Tendency to catch cold easily",
"Desire: sweet, maize",
"Grinding teeth in sleep",
]
tot_h = Inches(2.85)
add_rect(slide, C2X, cy2, COL_W, tot_h, TEAL_LIGHT,
line_color=TEAL_MID, line_width_pt=0.8)
bullet_list(slide, C2X + Inches(0.1), cy2 + Inches(0.08),
COL_W - Inches(0.2), tot_h,
totality, font_size=10, bullet_color=GOLD, line_h=Inches(0.205))
cy2 += tot_h + Inches(0.22)
# ── Repertorisation Summary ───────────────────────────────────────────────
REP_H = Inches(0.38)
section_header(slide, C2X, cy2, COL_W, REP_H, "Repertorisation — Complete Repertory (Zomeo Pro)")
cy2 += REP_H + Inches(0.05)
rep_rubrics = [
("Mind — Absent-minded (Forgetful)", "Lyc, Sep, Sulph, Calc, Merc — high"),
("Mind — Restlessness, Nervousness", "Lyc, Sep, Sulph, Calc, Merc, Bell — high"),
("Mouth — Salivation", "Merc, Kali-c prominent"),
("Stomach — Desire: Sweets", "Lyc, Sulph — prominent"),
("Teeth — Grinding", "Bell, Caust, Chin — prominent"),
("Generalities — Cold agg.", "Lyc, Sep, Calc, Nux-v — prominent"),
]
rep_box_h = Inches(2.1)
add_rect(slide, C2X, cy2, COL_W, rep_box_h, WHITE,
line_color=TEAL_MID, line_width_pt=0.8)
# Table header
add_rect(slide, C2X, cy2, COL_W, Inches(0.28), DEEP_TEAL)
add_textbox(slide, C2X + Inches(0.1), cy2, Inches(5.0), Inches(0.28),
"RUBRIC", font_size=9, bold=True, color=WHITE)
add_textbox(slide, C2X + Inches(5.1), cy2, COL_W - Inches(5.2), Inches(0.28),
"TOP REMEDIES", font_size=9, bold=True, color=WHITE)
cy_rep = cy2 + Inches(0.28)
for i, (rubric, remedies) in enumerate(rep_rubrics):
row_bg = TEAL_LIGHT if i % 2 == 0 else WHITE
add_rect(slide, C2X, cy_rep, COL_W, Inches(0.28), row_bg)
add_textbox(slide, C2X + Inches(0.1), cy_rep, Inches(5.0), Inches(0.28),
rubric, font_size=9, color=DARK_GREY)
add_textbox(slide, C2X + Inches(5.1), cy_rep, COL_W - Inches(5.2), Inches(0.28),
remedies, font_size=9, color=TEAL_MID, bold=True)
cy_rep += Inches(0.28)
# Final remedy scores
add_rect(slide, C2X, cy_rep, COL_W, Inches(0.30), AMBER_LIGHT)
add_textbox(slide, C2X + Inches(0.1), cy_rep, COL_W - Inches(0.2), Inches(0.30),
"TOP SCORES: Lyc 15 | Sep 15 | Sulph 14 | Calc 13 | Merc 13 | Nux-v 12 | Pib 12 | Bell 12 | Caust 12 | Kali-c 12 | Ars 11 | Bar-c 11",
font_size=9, bold=True, color=DEEP_TEAL)
cy2 += rep_box_h + Inches(0.22)
# ─────────────────────────────────────────────────────────────────────────────
# COLUMN 3 — Prescription + Justification + Follow-up
# ─────────────────────────────────────────────────────────────────────────────
cy3 = TOP_Y
# ── Prescription Badge ─────────────────────────────────────────────────────
RX_CARD_H = Inches(2.1)
add_rect(slide, C3X, cy3, COL_W, RX_CARD_H, DEEP_TEAL,
line_color=GOLD, line_width_pt=2.0)
# Big Rx symbol
add_textbox(slide, C3X + Inches(0.1), cy3 + Inches(0.08), Inches(1.8), Inches(0.6),
"℞", font_size=46, bold=True, color=GOLD, align=PP_ALIGN.CENTER)
add_textbox(slide, C3X + Inches(0.1), cy3 + Inches(0.62), COL_W - Inches(0.2), Inches(0.5),
"BARYTA CARBONICA 200",
font_size=26, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
add_textbox(slide, C3X + Inches(0.1), cy3 + Inches(1.15), COL_W - Inches(0.2), Inches(0.35),
"Infrequent doses | Periodic Table Row 6",
font_size=13, color=TEAL_LIGHT, align=PP_ALIGN.CENTER)
add_textbox(slide, C3X + Inches(0.1), cy3 + Inches(1.5), COL_W - Inches(0.2), Inches(0.5),
"Initial: 3 doses daily × 3 days + SL 30 TDS × 1 week",
font_size=11.5, color=GOLD, align=PP_ALIGN.CENTER)
cy3 += RX_CARD_H + Inches(0.22)
# ── Prescription Justification ────────────────────────────────────────────
JUS_H = Inches(0.38)
section_header(slide, C3X, cy3, COL_W, JUS_H, "Prescription Justification")
cy3 += JUS_H + Inches(0.05)
just_items = [
("Dr J H Clarke:", "Want of self-confidence & aversion to strangers. Child does not want to play. Cannot remember and learn. Chilliness predominates. Worse in company, better alone."),
("Dr J T Kent:", "Dwarfishness in body and mind. Late in learning and developing. Does not pay attention. Baryta-carb holds intellect and memory; begins feeble state and travels towards imbecility."),
("Case Match:", "Prominent features of Baryta-carb in this child: social withdrawal, late milestones, forgetfulness, fear, chilly, salivation — remarkable improvement seen."),
]
just_h = Inches(3.1)
add_rect(slide, C3X, cy3, COL_W, just_h, WHITE,
line_color=TEAL_MID, line_width_pt=0.8)
cy_just = cy3 + Inches(0.1)
for label, text in just_items:
add_rect(slide, C3X + Inches(0.1), cy_just, COL_W - Inches(0.2), Inches(0.9),
TEAL_LIGHT, line_color=TEAL_MID, line_width_pt=0.5)
add_textbox(slide, C3X + Inches(0.2), cy_just + Inches(0.05),
COL_W - Inches(0.35), Inches(0.28),
label, font_size=10, bold=True, color=DEEP_TEAL)
add_textbox(slide, C3X + Inches(0.2), cy_just + Inches(0.30),
COL_W - Inches(0.35), Inches(0.58),
text, font_size=9.5, color=DARK_GREY, wrap=True)
cy_just += Inches(0.98)
cy3 += just_h + Inches(0.22)
# ── Follow-up Timeline ────────────────────────────────────────────────────
FU_H = Inches(0.38)
section_header(slide, C3X, cy3, COL_W, FU_H, "Follow-up Timeline")
cy3 += FU_H + Inches(0.05)
fu_data = [
("11/03/2023", "As case discussed (baseline)", "Baryta-carb 200 — 3 doses daily × 3 days\nSL 30 TDS × 1 week"),
("18/03/2023", "Sleeps well • Now hears others • Restlessness decreased", "Baryta-carb 200 — 4 doses; 1 dose every Sunday\nSL 30 TDS × 1 month"),
("19/04/2023", "Follows parents & therapist instructions\nSees when spoken to • Hyperactivity decreased", "Baryta-carb 200 — 4 doses; 1 dose every Sunday\nSL 30 TDS × 1 month"),
("17/05/2023", "Comes when called • Tries to speak looking at book\nWears right shoes • Follows instructions", "Baryta-carb 200 — 4 doses; 1 dose every Sunday\nSL 30 TDS × 1 month"),
("12/07/2023", "REMARKABLE IMPROVEMENT: Proper eye contact • Says 'Bye'\nMemory improved • Follows commands\nSits & focused • Restlessness much less", "Baryta-carb STOPPED\n(continuous improvement noted)\nSL 30 TDS × 1 month"),
]
# Header row
add_rect(slide, C3X, cy3, COL_W, Inches(0.30), DEEP_TEAL)
for i, (label, cw) in enumerate(zip(["DATE", "SYMPTOMS / PROGRESS", "PRESCRIPTION"],
[Inches(1.8), Inches(7.5), Inches(4.5)])):
cx = C3X + sum([Inches(1.8), Inches(7.5), Inches(4.5)][:i])
add_textbox(slide, cx + Inches(0.05), cy3, cw, Inches(0.30),
label, font_size=9, bold=True, color=WHITE)
cy3 += Inches(0.30)
row_bgs = [TEAL_LIGHT, WHITE, TEAL_LIGHT, WHITE, GREEN_LIGHT]
row_heights = [Inches(0.55), Inches(0.65), Inches(0.65), Inches(0.65), Inches(0.90)]
for idx, ((date, symp, rx), bg, rh) in enumerate(zip(fu_data, row_bgs, row_heights)):
follow_up_row(slide, C3X, cy3, COL_W, rh, date, symp, rx, bg)
cy3 += rh
cy3 += Inches(0.22)
# ── Outcome Summary card ───────────────────────────────────────────────────
OUT_H = Inches(1.65)
add_rect(slide, C3X, cy3, COL_W, OUT_H, GREEN_LIGHT,
line_color=GREEN_IMP, line_width_pt=1.5)
add_rect(slide, C3X, cy3, COL_W, Inches(0.06), GREEN_IMP)
add_textbox(slide, C3X + Inches(0.15), cy3 + Inches(0.10), COL_W - Inches(0.3), Inches(0.38),
"TREATMENT OUTCOME", font_size=14, bold=True, color=GREEN_IMP)
outcomes = [
"✔ Eye contact established",
"✔ Follows commands and instructions",
"✔ Memory improved — says 'Bye'",
"✔ Sits focused — restlessness resolved",
"✔ Baryta-carb stopped at 4 months — improvement sustained",
]
cy_out = cy3 + Inches(0.50)
for o in outcomes:
add_textbox(slide, C3X + Inches(0.15), cy_out, COL_W - Inches(0.3), Inches(0.22),
o, font_size=10, color=GREEN_IMP)
cy_out += Inches(0.22)
cy3 += OUT_H + Inches(0.22)
# ═════════════════════════════════════════════════════════════════════════════
# BOTTOM FULL-WIDTH BANNER — Periodic Table Row 6 note
# ═════════════════════════════════════════════════════════════════════════════
FOOT_Y = H - Inches(0.55)
add_rect(slide, 0, FOOT_Y, W, Inches(0.55), SECTION_BG)
add_textbox(slide, Inches(0.5), FOOT_Y, W - Inches(1.0), Inches(0.55),
"National Journal of Homoeopathy | October 2023 | Periodic Table Row 6 | "
"Baryta Carbonica belongs to Row 6 — indicating themes of dependence, delayed development, and need for structure.",
font_size=10.5, color=TEAL_LIGHT, align=PP_ALIGN.CENTER,
v_anchor=MSO_ANCHOR.MIDDLE)
# ═════════════════════════════════════════════════════════════════════════════
# SAVE
# ═════════════════════════════════════════════════════════════════════════════
out_path = "/tmp/workspace/asd-poster/ASD_Case_Poster_Baryta_Carb.pptx"
buf = BytesIO()
prs.save(buf)
with open(out_path, "wb") as f:
f.write(buf.getvalue())
print(f"Saved: {out_path}")
print(f"Slide size: {prs.slide_width.inches:.2f}\" × {prs.slide_height.inches:.2f}\"")
cd /tmp/workspace/asd-poster && python create_poster.py 2>&1
ls -lh /tmp/workspace/asd-poster/
ASD Case Poster Baryta Carb
Presentation · PPTX