My name is Raghul Balaji not snigdha. Change it and add necessary image accurateley align it properly and provide me the premium version of this pdf. Don't change any content. Don't spoil the originality
cd /home/daytona/workspace/attachments/dfdca7dc-2d7a-42e9-bfc2-2c417ed733ea/ && ls -la
cd "/home/daytona/workspace/attachments/dfdca7dc-2d7a-42e9-bfc2-2c417ed733ea/" && python3 -c " import pdfplumber with pdfplumber.open('Atypical_Cardiomyopathy_Pediatrics (1).pdf') as pdf: print(f'Total pages: {len(pdf.pages)}') for i, page in enumerate(pdf.pages): print(f'\n=== PAGE {i+1} ===') print(page.extract_text()) "
cd "/home/daytona/workspace/attachments/dfdca7dc-2d7a-42e9-bfc2-2c417ed733ea/" && python3 -c " import pdfplumber with pdfplumber.open('Atypical_Cardiomyopathy_Pediatrics (1).pdf') as pdf: for i, page in enumerate(pdf.pages): print(f'\n=== PAGE {i+1} SIZE: {page.width} x {page.height} ===') images = page.images print(f'Images on page: {len(images)}') for img in images: print(f' Image: x0={img[\"x0\"]:.1f}, y0={img[\"y0\"]:.1f}, x1={img[\"x1\"]:.1f}, y1={img[\"y1\"]:.1f}') # Also get words with positions for layout analysis words = page.extract_words() # Just show first and last few if words: print(f' First word: {words[0]}') print(f' Last word: {words[-1]}') "
Left Ventricular Non-Compaction echocardiogram trabeculations NC:C ratio
Arrhythmogenic Right Ventricular Cardiomyopathy ARVC CMR fatty replacement
Restrictive Cardiomyopathy RCM biatrial enlargement cardiac MRI
mkdir -p /home/daytona/workspace/cardiomyopathy-pdf && ls /home/daytona/workspace/cardiomyopathy-pdf/
cd /home/daytona/workspace/cardiomyopathy-pdf && node /home/daytona/skills/shared/scripts/fetch_images.js \ "https://cdn.orris.care/cdss_images/roco_radiology_ROCO_34107_1766648009726.png" \ "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_357542c2331ed72981d56d0bc1576fed60ab0e2bc99a057901028eedb2b7e7c2.jpg" \ "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_de6691d6f8b26f6d03469bef12a4c7f30bfd7f0f0bccdcc79a4a3ed61bfb3a95.jpg" > images_result.json && python3 -c " import json, base64 with open('images_result.json') as f: result = json.load(f) names = ['lvnc_echo.png', 'arvc_cmr.jpg', 'rcm_cmr.jpg'] for i, img in enumerate(result): if img.get('base64'): raw = base64.b64decode(img['base64'].split(',')[1]) with open(names[i], 'wb') as f: f.write(raw) print(f'Saved {names[i]}: {len(raw)} bytes') else: print(f'Failed {names[i]}: {img.get(\"error\")}') "
~/cardiomyopathy-pdf/build_pdf.py
#!/usr/bin/env python3
"""
Premium Atypical Cardiomyopathy Pediatrics PDF
Author: Raghul Balaji | 4th Year MBBS | Group 8 | Jalalabad State University
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, Image, KeepTogether, PageBreak
)
from reportlab.platypus.flowables import Flowable
from reportlab.lib.colors import HexColor, white, black
import os
# ─── Colour palette ──────────────────────────────────────────────────────────
NAVY = HexColor('#0D2B55') # deep navy – headers / rule lines
TEAL = HexColor('#1A7A8A') # teal – section titles
ACCENT = HexColor('#E8F4F8') # very light blue – shaded rows / callout bg
GOLD = HexColor('#C8860A') # gold – bullet icon colour
LIGHT_GREY = HexColor('#F5F5F5') # table alt row
MID_GREY = HexColor('#CCCCCC') # dividers
DARK_GREY = HexColor('#333333') # body text
RED_LIGHT = HexColor('#FFF0F0') # key-points box bg
RED_BORDER = HexColor('#CC2222') # key-points box border
W, H = A4
MARGIN = 18 * mm
# ─── Custom flowables ─────────────────────────────────────────────────────────
class ColorBar(Flowable):
"""Full-width colour bar used as section dividers."""
def __init__(self, w, h, color):
super().__init__()
self.bar_w = w
self.bar_h = h
self.color = color
def draw(self):
self.canv.setFillColor(self.color)
self.canv.rect(0, 0, self.bar_w, self.bar_h, fill=1, stroke=0)
def wrap(self, aW, aH):
return self.bar_w, self.bar_h
class RoundedBox(Flowable):
"""Rounded-corner coloured box wrapping a list of text lines."""
def __init__(self, lines, bg, border, width, font='Helvetica', size=8.5):
super().__init__()
self.lines = lines
self.bg = bg
self.border = border
self.bw = width
self.font = font
self.size = size
self.padding = 8
def wrap(self, aW, aH):
self.bw = min(self.bw, aW)
lh = self.size * 1.35
self.bh = self.padding * 2 + len(self.lines) * lh
return self.bw, self.bh
def draw(self):
c = self.canv
c.setFillColor(self.bg)
c.setStrokeColor(self.border)
c.setLineWidth(1.2)
c.roundRect(0, 0, self.bw, self.bh, 6, fill=1, stroke=1)
c.setFillColor(DARK_GREY)
c.setFont(self.font, self.size)
lh = self.size * 1.35
y = self.bh - self.padding - self.size
for line in self.lines:
c.drawString(self.padding, y, line)
y -= lh
# ─── Style sheet ─────────────────────────────────────────────────────────────
def make_styles():
base = getSampleStyleSheet()
s = {}
# Cover-page title
s['cover_univ'] = ParagraphStyle('cover_univ', fontName='Helvetica-Bold',
fontSize=13, leading=16, textColor=NAVY, alignment=TA_CENTER, spaceAfter=2)
s['cover_faculty'] = ParagraphStyle('cover_faculty', fontName='Helvetica',
fontSize=10, leading=13, textColor=NAVY, alignment=TA_CENTER, spaceAfter=4)
s['cover_main'] = ParagraphStyle('cover_main', fontName='Helvetica-Bold',
fontSize=28, leading=33, textColor=white, alignment=TA_CENTER, spaceAfter=2)
s['cover_sub'] = ParagraphStyle('cover_sub', fontName='Helvetica',
fontSize=13, leading=17, textColor=white, alignment=TA_CENTER, spaceAfter=6)
s['cover_meta'] = ParagraphStyle('cover_meta', fontName='Helvetica',
fontSize=10.5, leading=15, textColor=ACCENT, alignment=TA_CENTER, spaceAfter=3)
# Section headers
s['page_header'] = ParagraphStyle('page_header', fontName='Helvetica-Bold',
fontSize=14, leading=18, textColor=white, alignment=TA_LEFT,
leftIndent=8, spaceAfter=6)
s['page_subhdr'] = ParagraphStyle('page_subhdr', fontName='Helvetica',
fontSize=9.5, leading=13, textColor=white, alignment=TA_LEFT,
leftIndent=8, spaceAfter=4)
s['section_title'] = ParagraphStyle('section_title', fontName='Helvetica-Bold',
fontSize=11.5, leading=15, textColor=TEAL, spaceBefore=8, spaceAfter=4)
# Body
s['body'] = ParagraphStyle('body', fontName='Helvetica',
fontSize=8.8, leading=13, textColor=DARK_GREY, alignment=TA_JUSTIFY,
spaceAfter=4)
s['bullet'] = ParagraphStyle('bullet', fontName='Helvetica',
fontSize=8.5, leading=12.5, textColor=DARK_GREY, leftIndent=14,
firstLineIndent=-10, spaceAfter=2)
s['bullet2'] = ParagraphStyle('bullet2', fontName='Helvetica',
fontSize=8.2, leading=12, textColor=DARK_GREY, leftIndent=26,
firstLineIndent=-10, spaceAfter=1.5)
# Caption
s['caption'] = ParagraphStyle('caption', fontName='Helvetica-Oblique',
fontSize=7.8, leading=10, textColor=TEAL, alignment=TA_CENTER, spaceAfter=6)
s['fig_label'] = ParagraphStyle('fig_label', fontName='Helvetica-Bold',
fontSize=7.8, leading=10, textColor=TEAL, alignment=TA_CENTER)
# Table
s['tbl_hdr'] = ParagraphStyle('tbl_hdr', fontName='Helvetica-Bold',
fontSize=8, leading=10, textColor=white, alignment=TA_CENTER)
s['tbl_cell'] = ParagraphStyle('tbl_cell', fontName='Helvetica',
fontSize=7.8, leading=10.5, textColor=DARK_GREY, alignment=TA_LEFT)
s['tbl_cell_c'] = ParagraphStyle('tbl_cell_c', fontName='Helvetica',
fontSize=7.8, leading=10.5, textColor=DARK_GREY, alignment=TA_CENTER)
# Footer / misc
s['footer'] = ParagraphStyle('footer', fontName='Helvetica',
fontSize=7.5, textColor=MID_GREY, alignment=TA_CENTER)
s['topics'] = ParagraphStyle('topics', fontName='Helvetica',
fontSize=10, leading=15, textColor=NAVY, leftIndent=12, spaceAfter=3)
s['conclusion'] = ParagraphStyle('conclusion', fontName='Helvetica',
fontSize=8.8, leading=13.5, textColor=DARK_GREY, alignment=TA_JUSTIFY,
spaceAfter=4)
s['thank_you'] = ParagraphStyle('thank_you', fontName='Helvetica-Bold',
fontSize=26, leading=32, textColor=NAVY, alignment=TA_CENTER, spaceBefore=20)
s['thank_sub'] = ParagraphStyle('thank_sub', fontName='Helvetica',
fontSize=11, leading=15, textColor=TEAL, alignment=TA_CENTER, spaceAfter=4)
return s
# ─── Helper builders ─────────────────────────────────────────────────────────
def hline(color=MID_GREY, thickness=0.5):
return HRFlowable(width='100%', thickness=thickness, color=color, spaceAfter=4, spaceBefore=2)
def sp(pts=6):
return Spacer(1, pts)
def section_header_block(title, subtitle, s, width):
"""Navy bar with white title + subtitle."""
bar_h = 36
items = [
(ColorBar(width, bar_h, NAVY), 0, 0, bar_h),
]
# We'll use a Table with a coloured background instead
data = [[Paragraph(title, s['page_header'])],
[Paragraph(subtitle, s['page_subhdr'])]]
tbl = Table(data, colWidths=[width])
tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), NAVY),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 10),
('RIGHTPADDING', (0,0), (-1,-1), 10),
('ROWBACKGROUNDS',(0,0), (-1,-1), [NAVY]),
]))
return tbl
def key_points_box(title, points, s, width):
"""Red-bordered key-points box."""
content = [Paragraph(f'<b>{title}</b>', ParagraphStyle('kp_title',
fontName='Helvetica-Bold', fontSize=9, leading=12,
textColor=RED_BORDER, spaceAfter=3))]
for pt in points:
content.append(Paragraph(f'• {pt}', ParagraphStyle('kp_pt',
fontName='Helvetica', fontSize=8.2, leading=12,
textColor=DARK_GREY, leftIndent=8, spaceAfter=1)))
data = [[content]]
tbl = Table([[content]], colWidths=[width])
tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), RED_LIGHT),
('BOX', (0,0), (-1,-1), 1.2, RED_BORDER),
('ROUNDEDCORNERS',[4]),
('TOPPADDING', (0,0), (-1,-1), 8),
('BOTTOMPADDING', (0,0), (-1,-1), 8),
('LEFTPADDING', (0,0), (-1,-1), 10),
('RIGHTPADDING', (0,0), (-1,-1), 10),
]))
return tbl
def img_with_caption(path, caption, s, img_w, img_h, label=''):
"""Return [Image, caption Paragraph] as a list."""
elements = []
if os.path.exists(path):
im = Image(path, width=img_w, height=img_h)
im.hAlign = 'CENTER'
elements.append(im)
if label:
elements.append(Paragraph(label, s['fig_label']))
elements.append(Paragraph(caption, s['caption']))
return elements
# ─── Page callback for headers/footers ───────────────────────────────────────
PAGE_TITLES = {
1: '', # cover
2: 'Atypical Cardiomyopathies in Children & Adolescents',
3: 'Atypical Cardiomyopathies in Children & Adolescents',
4: 'Atypical Cardiomyopathies in Children & Adolescents',
5: 'Atypical Cardiomyopathies in Children & Adolescents',
}
def on_page(canvas, doc):
pg = doc.page
if pg == 1:
return
canvas.saveState()
# Top rule
canvas.setStrokeColor(NAVY)
canvas.setLineWidth(1.5)
canvas.line(MARGIN, H - 14*mm, W - MARGIN, H - 14*mm)
# Running head
canvas.setFont('Helvetica', 7.5)
canvas.setFillColor(NAVY)
canvas.drawString(MARGIN, H - 11*mm, PAGE_TITLES.get(pg, ''))
canvas.drawRightString(W - MARGIN, H - 11*mm, 'Raghul Balaji | 4th MBBS | Gr 8')
# Bottom rule
canvas.setStrokeColor(MID_GREY)
canvas.setLineWidth(0.8)
canvas.line(MARGIN, 14*mm, W - MARGIN, 14*mm)
canvas.setFont('Helvetica', 7.5)
canvas.setFillColor(MID_GREY)
canvas.drawCentredString(W/2, 10*mm,
f'Atypical Cardiomyopathies in Children & Adolescents | Page {pg} of 5')
canvas.restoreState()
# ─── Content builders ─────────────────────────────────────────────────────────
def build_cover(s, cw):
story = []
story.append(sp(28))
# University badge area
uni_data = [
[Paragraph('JALALABAD STATE UNIVERSITY', s['cover_univ'])],
[Paragraph('Faculty of Medicine — Named after B. Osmonova', s['cover_faculty'])],
]
uni_tbl = Table(uni_data, colWidths=[cw])
uni_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), ACCENT),
('BOX', (0,0), (-1,-1), 1.5, NAVY),
('TOPPADDING', (0,0), (-1,-1), 10),
('BOTTOMPADDING', (0,0), (-1,-1), 10),
]))
story.append(uni_tbl)
story.append(sp(30))
# Hero banner
hero_data = [
[Paragraph('ATYPICAL FORMS OF', s['cover_main'])],
[Paragraph('CARDIOMYOPATHY', s['cover_main'])],
[Paragraph('in Children and Adolescents', s['cover_sub'])],
]
hero_tbl = Table(hero_data, colWidths=[cw])
hero_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), NAVY),
('TOPPADDING', (0,0), (-1,-1), 14),
('BOTTOMPADDING', (0,0), (-1,-1), 14),
('ROWBACKGROUNDS',(0,0), (-1,-1), [NAVY]),
]))
story.append(hero_tbl)
story.append(sp(20))
# Topic block
topic_title = Paragraph('<b>Topics Covered</b>', ParagraphStyle('tp', fontName='Helvetica-Bold',
fontSize=11, textColor=TEAL, alignment=TA_CENTER, spaceAfter=8))
topics = [
'● Left Ventricular Non-Compaction (LVNC)',
'● Arrhythmogenic Cardiomyopathy (ACM / ARVC)',
'● Restrictive Cardiomyopathy (RCM)',
'● Takotsubo & Myocarditis-related Cardiomyopathy',
'● Metabolic / Storage Cardiomyopathies',
]
topic_rows = [[topic_title]]
for t in topics:
topic_rows.append([Paragraph(t, s['topics'])])
topic_tbl = Table(topic_rows, colWidths=[cw])
topic_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), ACCENT),
('BOX', (0,0), (-1,-1), 1, TEAL),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 16),
]))
story.append(topic_tbl)
story.append(sp(30))
# Author info table
meta_rows = [
['Topic :-', 'Long-term monitoring and atypical forms of cardiomyopathy'],
['Done by :-', 'Raghul Balaji'],
['Year :-', '4th MBBS'],
['Group :-', '8th'],
]
meta_style = ParagraphStyle('meta_l', fontName='Helvetica-Bold',
fontSize=10, textColor=NAVY)
meta_style_r = ParagraphStyle('meta_r', fontName='Helvetica',
fontSize=10, textColor=DARK_GREY)
meta_data = [[Paragraph(r[0], meta_style), Paragraph(r[1], meta_style_r)] for r in meta_rows]
meta_tbl = Table(meta_data, colWidths=[cw*0.28, cw*0.72])
meta_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), white),
('BOX', (0,0), (-1,-1), 1.2, NAVY),
('INNERGRID', (0,0), (-1,-1), 0.4, MID_GREY),
('TOPPADDING', (0,0), (-1,-1), 6),
('BOTTOMPADDING', (0,0), (-1,-1), 6),
('LEFTPADDING', (0,0), (-1,-1), 12),
('ROWBACKGROUNDS',(0,0), (-1,-1), [ACCENT, white, ACCENT, white]),
# Highlight "Done by" row
('BACKGROUND', (0,1), (-1,1), HexColor('#D0EAF5')),
('FONTNAME', (1,1), (1,1), 'Helvetica-Bold'),
]))
story.append(meta_tbl)
return story
def build_page2(s, cw, img_path):
"""LVNC page"""
story = []
story.append(sp(8))
# Header bar
story.append(section_header_block(
'Introduction & LVNC',
'Overview of atypical cardiomyopathies · Left Ventricular Non-Compaction',
s, cw))
story.append(sp(10))
# Intro paragraph
story.append(Paragraph('<b>Introduction :-</b>', s['section_title']))
story.append(Paragraph(
'Cardiomyopathies are myocardial diseases with structural and functional abnormality in the '
'absence of coronary artery disease, hypertension, or valvular disease. While dilated (DCM) and '
'hypertrophic (HCM) forms are well-known, a significant subset in children falls into atypical forms — '
'rare, heterogeneous, and often under-recognised. These represent a major cause of heart failure, '
'sudden cardiac death (SCD), and cardiac transplantation in the young. Modern tools — cardiac MRI '
'(CMR), genetic panels, and advanced echocardiography — allow precise phenotyping and guide '
'individualised management.', s['body']))
story.append(hline())
story.append(Paragraph('<b>1. Left Ventricular Non-Compaction (LVNC) :-</b>', s['section_title']))
# Two-column: text left, image right
lvnc_bullets = [
'<b>Pathophysiology:</b> Arrest of normal myocardial compaction at 5–8 weeks gestation → '
'prominent trabeculations + deep intertrabecular recesses communicating with LV cavity',
'<b>Genetics:</b> TAZ (Barth syndrome, X-linked), MYH7, MYBPC3, LDB3, ACTC1; 30–50% have an '
'affected first-degree relative',
'<b>Associations:</b> Barth syndrome (DCM+LVNC+neutropenia), Danon disease, Noonan, '
'mitochondrial disorders',
'<b>Diagnosis:</b> Echo NC:C ratio >2.0 (adult), >1.4 (paediatric); CMR = gold standard — '
'confirms NC extent + late gadolinium enhancement (LGE)',
'<b>Classic triad:</b> Heart failure · Ventricular arrhythmias · Thromboembolism',
'<b>Management:</b> ACEi + beta-blockers + diuretics; anticoagulation if EF <35% or AF; '
'ICD for high-risk VT/syncope; transplant for end-stage disease',
]
text_content = [[Paragraph(b, s['bullet'])] for b in lvnc_bullets]
text_tbl = Table(text_content, colWidths=[cw * 0.55])
text_tbl.setStyle(TableStyle([
('TOPPADDING', (0,0),(-1,-1), 2),
('BOTTOMPADDING',(0,0),(-1,-1), 2),
('LEFTPADDING', (0,0),(-1,-1), 0),
('RIGHTPADDING', (0,0),(-1,-1), 0),
]))
# Image + caption
img_w = cw * 0.40
img_h = img_w * 0.72
img_cap_content = []
if os.path.exists(img_path):
im = Image(img_path, width=img_w, height=img_h)
im.hAlign = 'CENTER'
img_cap_content.append(im)
img_cap_content.append(Paragraph(
'<i>LVNC Echo: NC:C >2, apical trabeculations</i>', s['caption']))
img_cap_content.append(Paragraph(
'Fig 1 – LVNC echocardiogram: prominent trabeculations, NC:C >2', s['fig_label']))
from reportlab.platypus import KeepInFrame
img_tbl = Table([[img_cap_content]], colWidths=[cw * 0.43])
img_tbl.setStyle(TableStyle([
('ALIGN', (0,0),(-1,-1), 'CENTER'),
('VALIGN', (0,0),(-1,-1), 'TOP'),
('TOPPADDING', (0,0),(-1,-1), 0),
('BOTTOMPADDING',(0,0),(-1,-1), 0),
('LEFTPADDING', (0,0),(-1,-1), 0),
('RIGHTPADDING', (0,0),(-1,-1), 0),
('BOX', (0,0),(-1,-1), 0.8, TEAL),
('BACKGROUND', (0,0),(-1,-1), ACCENT),
]))
two_col = Table([[text_tbl, img_tbl]], colWidths=[cw*0.57, cw*0.43])
two_col.setStyle(TableStyle([
('VALIGN', (0,0),(-1,-1), 'TOP'),
('LEFTPADDING', (0,0),(-1,-1), 0),
('RIGHTPADDING', (0,0),(-1,-1), 4),
('TOPPADDING', (0,0),(-1,-1), 0),
('BOTTOMPADDING',(0,0),(-1,-1), 0),
]))
story.append(two_col)
story.append(sp(8))
# Key points box
story.append(key_points_box('✦ LVNC Key Points', [
'1–7% of all paediatric cardiomyopathies; most common in infancy',
'Barth syndrome = LVNC + DCM + neutropenia + 3-methylglutaconic aciduria (TAZ mutation)',
'CMR gold standard; differentiates from HCM by absence of marked LV hypertrophy',
], s, cw))
return story
def build_page3(s, cw, img_path):
"""ARVC page"""
story = []
story.append(sp(8))
story.append(section_header_block(
'Arrhythmogenic Cardiomyopathy (ACM / ARVC)',
'Leading cause of SCD in young athletes — desmosomal disease',
s, cw))
story.append(sp(10))
story.append(Paragraph('<b>2. Arrhythmogenic Cardiomyopathy (ACM / ARVC) :-</b>', s['section_title']))
story.append(Paragraph(
'ACM is a heritable cardiomyopathy characterised by fibrofatty replacement of the myocardium, '
'predominantly the right ventricle (though biventricular and LV-dominant forms exist). It is the leading '
'cause of SCD in young competitive athletes, accounting for up to 20% of sport-related deaths. '
'Physical exercise accelerates disease progression by stressing defective desmosomes.', s['body']))
# Two-column: text + image
arvc_bullets = [
'<b>Genetics:</b> PKP2 (~40%), DSP, DSG2, DSC2, JUP mutations → impaired desmosomal adhesion '
'→ apoptosis → fibrofatty remodelling',
'<b>Classic triangle of dysplasia:</b> RVOT · RV apex · Subtricuspid area',
'<b>Paediatric ACM:</b> LV-dominant or biventricular forms more common than adults; worse prognosis',
]
text_content = [[Paragraph(b, s['bullet'])] for b in arvc_bullets]
text_tbl = Table(text_content, colWidths=[cw * 0.55])
text_tbl.setStyle(TableStyle([
('TOPPADDING', (0,0),(-1,-1), 2),
('BOTTOMPADDING',(0,0),(-1,-1), 2),
('LEFTPADDING', (0,0),(-1,-1), 0),
('RIGHTPADDING', (0,0),(-1,-1), 0),
]))
img_w = cw * 0.40
img_h = img_w * 0.68
img_cap_content = []
if os.path.exists(img_path):
im = Image(img_path, width=img_w, height=img_h)
im.hAlign = 'CENTER'
img_cap_content.append(im)
img_cap_content.append(Paragraph(
'<i>ARVC CMR: Fatty RV replacement, RV dilatation</i>', s['caption']))
img_cap_content.append(Paragraph(
'Fig 2 – CMR in ARVC: fatty RV free wall replacement and RV dilatation', s['fig_label']))
img_tbl = Table([[img_cap_content]], colWidths=[cw * 0.43])
img_tbl.setStyle(TableStyle([
('ALIGN', (0,0),(-1,-1), 'CENTER'),
('VALIGN', (0,0),(-1,-1), 'TOP'),
('TOPPADDING', (0,0),(-1,-1), 0),
('BOTTOMPADDING',(0,0),(-1,-1), 0),
('LEFTPADDING', (0,0),(-1,-1), 0),
('RIGHTPADDING', (0,0),(-1,-1), 0),
('BOX', (0,0),(-1,-1), 0.8, TEAL),
('BACKGROUND', (0,0),(-1,-1), ACCENT),
]))
two_col = Table([[text_tbl, img_tbl]], colWidths=[cw*0.57, cw*0.43])
two_col.setStyle(TableStyle([
('VALIGN', (0,0),(-1,-1), 'TOP'),
('LEFTPADDING', (0,0),(-1,-1), 0),
('RIGHTPADDING', (0,0),(-1,-1), 4),
('TOPPADDING', (0,0),(-1,-1), 0),
('BOTTOMPADDING',(0,0),(-1,-1), 0),
]))
story.append(two_col)
story.append(sp(6))
# Diagnosis criteria box
story.append(Paragraph('<b>Diagnosis — 2010 Revised Task Force Criteria</b>', s['section_title']))
diag_note = Paragraph(
'<i>Definite: 2 major | 1 major + 2 minor | 4 minor criteria from different categories</i>',
ParagraphStyle('diag_n', fontName='Helvetica-Oblique', fontSize=8, textColor=TEAL,
spaceAfter=4))
story.append(diag_note)
c1 = [
Paragraph('<b>Structural (Major):</b> RV regional akinesia/dyskinesia + RVEDV/BSA ≥110 (M)/100 (F) mL/m² on CMR/echo', s['bullet']),
Paragraph('<b>Tissue (Major):</b> Fibrofatty replacement on biopsy (residual myocytes <60%)', s['bullet']),
Paragraph('<b>Repolarisation (Major):</b> T-wave inversions V1–V4 in >14 yr without complete RBBB', s['bullet']),
]
c2 = [
Paragraph('<b>Depolarisation (Major):</b> Epsilon wave in V1–V3', s['bullet']),
Paragraph('<b>Arrhythmia (Major):</b> Sustained/non-sustained VT with LBBB morphology, superior axis', s['bullet']),
Paragraph('<b>Family (Major):</b> First-degree relative with confirmed ACM or identified pathogenic mutation', s['bullet']),
]
diag_tbl = Table([[c1, c2]], colWidths=[cw*0.50, cw*0.50])
diag_tbl.setStyle(TableStyle([
('VALIGN', (0,0),(-1,-1), 'TOP'),
('TOPPADDING', (0,0),(-1,-1), 0),
('BOTTOMPADDING',(0,0),(-1,-1), 0),
('LEFTPADDING', (0,0),(-1,-1), 2),
('RIGHTPADDING', (0,0),(-1,-1), 2),
('LINEBEFORE', (1,0),(1,-1), 0.5, MID_GREY),
]))
story.append(diag_tbl)
story.append(sp(6))
# Management
story.append(Paragraph('<b>Management</b>', s['section_title']))
mgmt = [
'<b>Mandatory sport restriction</b> — exercise is the most important modifiable trigger for disease progression',
'<b>Beta-blockers</b> (sotalol / amiodarone) for arrhythmia suppression; ICD mandatory in high-risk patients (SCD survivors, sustained VT, syncope, severe RV dysfunction)',
'<b>Catheter ablation</b> for recurrent VT storms; cardiac transplantation for end-stage disease',
]
for m in mgmt:
story.append(Paragraph(f'• {m}', s['bullet']))
story.append(sp(6))
story.append(key_points_box('✦ ARVC Key Points', [
'Epsilon wave (low-amp signal after QRS in V1–V3) = pathognomonic ECG sign of ARVC',
'LBBB-morphology VT in a young athlete = suspect ARVC; screen all first-degree relatives',
'PKP2 most common mutation (~40%); exercise restriction is life-saving even pre-symptomatically',
], s, cw))
return story
def build_page4(s, cw, img_path):
"""RCM + Takotsubo + Myocarditis page"""
story = []
story.append(sp(8))
story.append(section_header_block(
'RCM · Takotsubo · Myocarditis-related CMP',
'Restrictive · Stress · Inflammatory cardiomyopathies in children',
s, cw))
story.append(sp(10))
story.append(Paragraph('<b>3. Restrictive Cardiomyopathy (RCM) :-</b>', s['section_title']))
rcm_bullets = [
'<b>Etiology:</b> Idiopathic (most common in children; TNNI3, MYH7, ACTC1 mutations); '
'infiltrative (amyloid, Gaucher, Fabry); fibrotic (post-myocarditis, scleroderma)',
'<b>Pathophysiology:</b> Non-compliant stiff ventricles → elevated filling pressures → '
'biatrial enlargement → pulmonary venous/arterial hypertension',
'<b>Clinical:</b> Dyspnoea, exercise intolerance, hepatomegaly, ascites, AF, thromboembolism',
'<b>Diagnosis:</b> Echo — biatrial enlargement + diastolic dysfunction Grade III/IV (E/A >2, '
'DT <150 ms, E/e\' >15); CMR ± LGE; endomyocardial biopsy',
'<b>Mx:</b> Diuretics, anticoagulation; NO disease-modifying therapy; early cardiac transplant '
'listing — worst prognosis of all paediatric CMPs; 5-yr survival ~50% without Tx',
]
text_content = [[Paragraph(b, s['bullet'])] for b in rcm_bullets]
text_tbl = Table(text_content, colWidths=[cw * 0.55])
text_tbl.setStyle(TableStyle([
('TOPPADDING', (0,0),(-1,-1), 2),
('BOTTOMPADDING',(0,0),(-1,-1), 2),
('LEFTPADDING', (0,0),(-1,-1), 0),
('RIGHTPADDING', (0,0),(-1,-1), 0),
]))
img_w = cw * 0.40
img_h = img_w * 0.72
img_cap_content = []
if os.path.exists(img_path):
im = Image(img_path, width=img_w, height=img_h)
im.hAlign = 'CENTER'
img_cap_content.append(im)
img_cap_content.append(Paragraph(
'<i>RCM CMR: Biatrial enlargement, normal LV</i>', s['caption']))
img_cap_content.append(Paragraph(
'Fig 3 – CMR in RCM: biatrial enlargement, normal ventricular dimensions, preserved LVEF',
s['fig_label']))
img_tbl = Table([[img_cap_content]], colWidths=[cw * 0.43])
img_tbl.setStyle(TableStyle([
('ALIGN', (0,0),(-1,-1), 'CENTER'),
('VALIGN', (0,0),(-1,-1), 'TOP'),
('TOPPADDING', (0,0),(-1,-1), 0),
('BOTTOMPADDING',(0,0),(-1,-1), 0),
('LEFTPADDING', (0,0),(-1,-1), 0),
('RIGHTPADDING', (0,0),(-1,-1), 0),
('BOX', (0,0),(-1,-1), 0.8, TEAL),
('BACKGROUND', (0,0),(-1,-1), ACCENT),
]))
two_col = Table([[text_tbl, img_tbl]], colWidths=[cw*0.57, cw*0.43])
two_col.setStyle(TableStyle([
('VALIGN', (0,0),(-1,-1), 'TOP'),
('LEFTPADDING', (0,0),(-1,-1), 0),
('RIGHTPADDING', (0,0),(-1,-1), 4),
('TOPPADDING', (0,0),(-1,-1), 0),
('BOTTOMPADDING',(0,0),(-1,-1), 0),
]))
story.append(two_col)
story.append(sp(8))
# Takotsubo + Myocarditis side-by-side
story.append(Paragraph('<b>4. Takotsubo (Stress) CMP & 5. Myocarditis-related CMP :-</b>', s['section_title']))
tako_rows = [
[Paragraph('<b>Takotsubo CMP</b>', ParagraphStyle('t_h', fontName='Helvetica-Bold',
fontSize=9, textColor=white)),
Paragraph('<b>Myocarditis-related CMP</b>', ParagraphStyle('t_h2', fontName='Helvetica-Bold',
fontSize=9, textColor=white))],
[Paragraph('• Rare in children; stress-induced catecholamine surge → transient apical LV ballooning', s['bullet']),
Paragraph('• Viral triggers: Coxsackie B, adenovirus, parvovirus B19, SARS-CoV-2/MIS-C', s['bullet'])],
[Paragraph('• Triggers: emotional stress, seizures, SAH, pheochromocytoma', s['bullet']),
Paragraph('• Acute: DCM-like systolic dysfunction; Chronic: fibrosis → ACM phenocopy', s['bullet'])],
[Paragraph('• ECG: ST elevation / deep T inversions; normal coronaries', s['bullet']),
Paragraph('• CMR: T2↑ (oedema) + mid-wall LGE (fibrosis); Biopsy: Dallas criteria', s['bullet'])],
[Paragraph('• Usually reversible in 4–8 weeks; Rx = supportive (beta-blockers, ACEi)', s['bullet']),
Paragraph('• Rx: IVIG (fulminant); immunosuppression (chronic); standard HF therapy', s['bullet'])],
]
tako_tbl = Table(tako_rows, colWidths=[cw*0.50, cw*0.50])
tako_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), TEAL),
('ROWBACKGROUNDS',(0,1), (-1,-1), [white, ACCENT]),
('BOX', (0,0), (-1,-1), 1, TEAL),
('INNERGRID', (0,0), (-1,-1), 0.4, MID_GREY),
('LINEBEFORE', (1,0), (1,-1), 0.8, TEAL),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 8),
('VALIGN', (0,0), (-1,-1), 'TOP'),
]))
story.append(tako_tbl)
story.append(sp(8))
story.append(key_points_box('✦ RCM Key Points', [
'Worst prognosis of all paediatric CMPs — early transplant listing is life-saving',
'Key differentiator: constrictive pericarditis (septal bounce, pericardial calcification on CT) vs RCM (E/e\' >15, tissue Doppler)',
'Any child with unexplained biatrial enlargement + pulmonary hypertension → suspect RCM',
], s, cw))
return story
def build_page5(s, cw):
"""Metabolic + Summary + Conclusion page"""
story = []
story.append(sp(8))
story.append(section_header_block(
'Metabolic CMPs · Summary · Conclusion',
'Storage disorders · Comparative table · Key takeaways',
s, cw))
story.append(sp(10))
story.append(Paragraph('<b>6. Metabolic & Storage Cardiomyopathies :-</b>', s['section_title']))
story.append(Paragraph(
'Metabolic cardiomyopathies arise from inherited enzyme deficiencies, lysosomal storage disorders, '
'or mitochondrial dysfunction. Multi-system involvement is the clue — cardiac findings alongside '
'neurological, skeletal, renal, or haematological features should prompt targeted enzyme assays and genetics.',
s['body']))
# Metabolic table
h = lambda t: Paragraph(t, s['tbl_hdr'])
c = lambda t: Paragraph(t, s['tbl_cell'])
cc = lambda t: Paragraph(t, s['tbl_cell_c'])
met_data = [
[h('Disorder'), h('Gene/Defect'), h('CMP Phenotype'), h('Key Feature'), h('Treatment')],
[c('Pompe (GSD II)'), cc('GAA'), cc('HCM-like'),
c('Hypotonia, absent acid α-glucosidase'), c('ERT (alglucosidase alfa)')],
[c('Fabry disease'), cc('GLA (XL)'), cc('HCM'),
c('Renal, neuro, skin, corneal whorls'), c('ERT (agalsidase)')],
[c('Barth syndrome'), cc('TAZ (XL)'), cc('DCM+LVNC'),
c('Neutropenia, 3-MGA, myopathy'), c('Supportive; ERT trials')],
[c('Danon disease'), cc('LAMP2 (XL)'), cc('HCM'),
c('Cognitive impairment, WPW, retinopathy'), c('Transplant; gene therapy')],
[c('Mitochondrial'), cc('mtDNA/nuclear'), cc('HCM or DCM'),
c('Multi-system, lactic acidosis'), c('Supportive + cofactors')],
]
col_w = [cw*0.19, cw*0.12, cw*0.14, cw*0.31, cw*0.24]
met_tbl = Table(met_data, colWidths=col_w)
met_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), NAVY),
('ROWBACKGROUNDS',(0,1), (-1,-1), [white, LIGHT_GREY]),
('BOX', (0,0), (-1,-1), 1, NAVY),
('INNERGRID', (0,0), (-1,-1), 0.4, MID_GREY),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 5),
('RIGHTPADDING', (0,0), (-1,-1), 5),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('ALIGN', (0,0), (-1,0), 'CENTER'),
]))
story.append(met_tbl)
story.append(sp(8))
# Comparative summary table
story.append(Paragraph('<b>Comparative Summary :-</b>', s['section_title']))
sum_data = [
[h('Type'), h('Key Genetics'), h('Hallmark Imaging'), h('ECG Sign'), h('Prognosis')],
[c('LVNC'), c('TAZ, MYH7'), c('Echo NC:C>2 / CMR'), c('LVH, WPW'), c('Variable')],
[c('ACM/ARVC'), c('PKP2, DSP'), c('CMR fatty RV wall'), c('Epsilon wave, LBBB-VT'), c('SCD risk ↑')],
[c('RCM'), c('TNNI3, MYH7'), c('Biatrial enlargement'), c('AF, CHB'), c('Worst')],
[c('Takotsubo'), c('None'), c('Apical ballooning'), c('ST elevation'), c('Good')],
[c('Metabolic'), c('Various'), c('HCM or DCM pattern'), c('Variable/WPW'), c('Disease-dep.')],
]
col_w2 = [cw*0.14, cw*0.16, cw*0.25, cw*0.25, cw*0.20]
sum_tbl = Table(sum_data, colWidths=col_w2)
sum_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), TEAL),
('ROWBACKGROUNDS',(0,1), (-1,-1), [white, ACCENT]),
('BOX', (0,0), (-1,-1), 1, TEAL),
('INNERGRID', (0,0), (-1,-1), 0.4, MID_GREY),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
('LEFTPADDING', (0,0), (-1,-1), 5),
('RIGHTPADDING', (0,0), (-1,-1), 5),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
]))
story.append(sum_tbl)
story.append(sp(8))
# Conclusion
story.append(Paragraph('<b>Conclusion :-</b>', s['section_title']))
story.append(Paragraph(
'Atypical cardiomyopathies in children are clinically heterogeneous but share a need for early '
'diagnosis, genetic workup, and family screening. LVNC and ARVC demand vigilance for SCD risk; RCM '
'requires prompt transplant listing; Takotsubo is generally reversible; and metabolic CMPs benefit '
'from targeted enzyme replacement. CMR, genetic panels, and multidisciplinary care are the '
'cornerstones of modern paediatric cardiomyopathy management.', s['conclusion']))
# Final key-points exam box
story.append(key_points_box('✦ Final Key Points for Exams', [
'LVNC: NC:C >2 on echo | Barth syndrome (TAZ) = LVNC+DCM+neutropenia',
'ARVC: Epsilon wave + LBBB-VT in young athlete | PKP2 most common | restrict sport',
'RCM: Worst prognosis | biatrial enlargement + preserved LVEF | early transplant list',
'Takotsubo: Stress-triggered, apical ballooning, reversible — Rx supportive',
'Metabolic: Pompe=GAA, Fabry=GLA, Barth=TAZ, Danon=LAMP2 — multisystem clues',
], s, cw))
story.append(sp(16))
# Thank you
story.append(Paragraph('THANK YOU', s['thank_you']))
story.append(sp(6))
story.append(hline(TEAL, 1.5))
story.append(Paragraph(
'Raghul Balaji | 4th Year MBBS | Group 8 | Jalalabad State University',
s['thank_sub']))
return story
# ─── Main ─────────────────────────────────────────────────────────────────────
def main():
out = '/home/daytona/workspace/cardiomyopathy-pdf/Atypical_Cardiomyopathy_Pediatrics_RaghulBalaji.pdf'
base = '/home/daytona/workspace/cardiomyopathy-pdf'
doc = SimpleDocTemplate(
out,
pagesize=A4,
leftMargin=MARGIN, rightMargin=MARGIN,
topMargin=20*mm, bottomMargin=20*mm,
title='Atypical Forms of Cardiomyopathy in Children and Adolescents',
author='Raghul Balaji',
subject='Atypical Cardiomyopathies in Pediatrics',
creator='Jalalabad State University – Faculty of Medicine',
)
cw = W - 2 * MARGIN # usable content width
s = make_styles()
story = []
# ── Cover (page 1) ────────────────────────────────────────────────────────
story += build_cover(s, cw)
story.append(PageBreak())
# ── Page 2: LVNC ─────────────────────────────────────────────────────────
story += build_page2(s, cw, os.path.join(base, 'lvnc_echo.png'))
story.append(PageBreak())
# ── Page 3: ARVC ─────────────────────────────────────────────────────────
story += build_page3(s, cw, os.path.join(base, 'arvc_cmr.jpg'))
story.append(PageBreak())
# ── Page 4: RCM + Takotsubo + Myocarditis ────────────────────────────────
story += build_page4(s, cw, os.path.join(base, 'rcm_cmr.jpg'))
story.append(PageBreak())
# ── Page 5: Metabolic + Summary + Conclusion ──────────────────────────────
story += build_page5(s, cw)
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print(f'PDF saved → {out}')
if __name__ == '__main__':
main()
cd /home/daytona/workspace/cardiomyopathy-pdf && python3 build_pdf.py 2>&1
cd /home/daytona/workspace/cardiomyopathy-pdf && python3 -c " import pdfplumber with pdfplumber.open('Atypical_Cardiomyopathy_Pediatrics_RaghulBalaji.pdf') as pdf: print(f'Pages: {len(pdf.pages)}') for i, page in enumerate(pdf.pages): text = page.extract_text() or '' # Check for name occurrences if 'Raghul' in text or 'Snigdha' in text: print(f'Page {i+1}: Raghul={text.count(\"Raghul\")}, Snigdha={text.count(\"Snigdha\")}') imgs = page.images print(f'Page {i+1}: {len(imgs)} images, {len(text)} chars') " && ls -lh Atypical_Cardiomyopathy_Pediatrics_RaghulBalaji.pdf
| What | Original | Updated |
|---|---|---|
| Name | Snigdha Mandaokar | Raghul Balaji |
| Running header | — | Raghul Balaji | 4th MBBS | Gr 8 |
| Thank You footer | Snigdha Mandaokar | Raghul Balaji |
| Author metadata | Snigdha | Raghul Balaji |
Atypical Cardiomyopathy Pediatrics RaghulBalaji
PDF Document · PDF
Add necessary images on each page and align the text properly