Murmur sounds cvs

Reading File
Finding Sources
Finding Sources
Finding Sources
Reading File
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Loading Image
Reading File
Loading Image
Reading File
I now have comprehensive information to deliver a thorough answer. Let me compile everything.

Heart Murmurs - CVS (Cardiovascular System)

What is a Heart Murmur?

A heart murmur is an audible vibration caused by increased turbulence in blood flow. Turbulence arises from:
  • Accelerated blood flow through a normal or abnormal orifice
  • Flow through a narrowed or irregular orifice into a dilated vessel/chamber
  • Backward (regurgitant) flow through an incompetent valve, VSD, or PDA
Blood flow is laminar and silent up to a critical velocity. Above that velocity (e.g., beyond an obstruction or through a narrow orifice), it becomes turbulent and audible. - Ganong's Review of Medical Physiology, p. 543

Classification by Timing

The primary step in identifying a murmur is establishing its timing in the cardiac cycle.
Principal Heart Murmur Diagrams
A = Presystolic murmur (MS/TS in sinus rhythm); B = Holosystolic (MR/TR/VSD); C = Aortic ejection murmur (begins after ejection click, fades before S2); D = Pulmonic stenosis spilling past A2; E = Aortic/pulmonary diastolic (decrescendo); F = Mitral stenosis after opening snap; G = Short mid-diastolic inflow after S3; H = Continuous murmur (PDA)

1. Systolic Murmurs

Begin with or after S1, terminate at or before the component of S2.
TypeTimingShapeKey Causes
Early systolicStarts at S1, ends well before S2DecrescendoAcute MR (papillary rupture, chordal rupture), muscular VSD, TR with normal PA pressure
Mid-systolic (ejection)After S1, ends before S2Crescendo-decrescendo (diamond)Aortic stenosis, pulmonic stenosis, HCM, aortic sclerosis, high-output states
Holosystolic (pansystolic)Spans entire systole, S1 to S2Plateau (constant)Chronic MR, TR, VSD
Late systolicStarts mid-to-late systoleOften crescendoMitral valve prolapse (after click), papillary muscle dysfunction
Key principle: In AV valve regurgitation (MR, TR), the LV-LA pressure gradient persists throughout systole - hence a plateau-shaped holosystolic murmur. In semilunar valve stenosis (AS, PS), flow accelerates then decelerates - hence a crescendo-decrescendo ejection murmur that starts after S1. - Fuster & Hurst's The Heart, 15th Ed.

2. Diastolic Murmurs

Begin with or after S2, end at or before the subsequent S1. Almost always pathological.
TypeTimingShapeKey Causes
Early diastolic (decrescendo)Begins immediately after S2Decrescendo (blowing, high-pitched)Aortic regurgitation, pulmonary regurgitation
Mid-diastolicAfter S2 with brief gapRumbling, low-pitched (use bell)Mitral stenosis, tricuspid stenosis, Austin Flint murmur
PresystolicJust before S1CrescendoMitral stenosis (sinus rhythm only), tricuspid stenosis
Note on MS murmur: It follows the opening snap (OS). The interval between A2 and OS shortens as LA pressure rises (more severe MS). The murmur is low-pitched and rumbling because the LA-LV pressure gradient is small - use the bell of the stethoscope. - Harrison's Principles of Internal Medicine, 22nd Ed.

3. Continuous Murmurs

Not confined to one phase - begin in early systole and continue through S2 into all or part of diastole.
CauseDescription
Patent Ductus Arteriosus (PDA)Classic "machinery murmur" - peaks around S2, continuous throughout
Arteriovenous fistulaContinuous
Venous humHeard at neck/clavicle, disappears with neck vein compression
Cervical bruitOver carotid stenosis

Grading of Murmur Intensity (Levine Scale I-VI)

GradeDescription
I/VIVery soft; heard only with great effort
II/VISoft but easily heard
III/VILoud; no thrill
IV/VILoud; accompanied by a palpable thrill
V/VIHeard with the edge of stethoscope on chest
VI/VIHeard with stethoscope off the chest
Grades ≥III/VI (especially holosystolic or late systolic) and all diastolic/continuous murmurs warrant echocardiography. Soft midsystolic murmurs (I-II/VI) in asymptomatic young patients are usually benign (innocent murmurs). - Harrison's, p. 1886

Key Memory Aid: Valve Timing Table

ValveAbnormalityMurmur Timing
Aortic / PulmonaryStenosisSystolic
Aortic / PulmonaryRegurgitationDiastolic
Mitral / TricuspidStenosisDiastolic
Mitral / TricuspidRegurgitationSystolic
  • Ganong's Review of Medical Physiology, Table 30-2

Location and Radiation

Murmur locations and radiation on chest
MurmurBest heardRadiation
Aortic stenosis2nd RICS (aortic area)Carotids, neck
Pulmonic stenosis2nd LICSLeft shoulder/neck
Mitral regurgitationApexLeft axilla
Tricuspid regurgitationLower left sternal borderNone / right side
VSD3rd-4th LICSLeft sternal border
HCMLower left sternal border / apexBoth carotids (but decreases with Valsalva release)

Special Murmur Characters

MurmurQuality
Aortic regurgitationBlowing, high-pitched decrescendo diastolic
Mitral stenosisRumbling, low-pitched mid-diastolic (use bell)
Aortic stenosisHarsh, rough crescendo-decrescendo
PDAMachinery continuous murmur
Mitral prolapseClick followed by late systolic murmur
Innocent (flow) murmurSoft, vibratory, midsystolic; common in children

Innocent vs. Pathological

Innocent murmurs (common in children/young adults):
  • Grade I-II/VI, midsystolic
  • Soft and vibratory ("Still's murmur")
  • No radiation
  • No associated symptoms, thrill, or abnormal S2
  • Disappear with standing / decrease with Valsalva
Pathological features suggesting further investigation:
  • Diastolic or continuous murmur (always investigate)
  • Grade ≥III systolic murmur, especially holosystolic or late systolic
  • Associated thrill, click, abnormal S2 splitting, or symptoms

Sources: Harrison's Principles of Internal Medicine, 22nd Ed. (2025) | Fuster & Hurst's The Heart, 15th Ed. | Ganong's Review of Medical Physiology, 26th Ed.

Create a quick reference PDF of murmur timing, grading, and bedside maneuvers

Reading File
Reading File
Running Command

mkdir -p /home/daytona/workspace/murmur-pdf

Writing File

~/murmur-pdf/create_murmur_pdf.py

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_CENTER, TA_LEFT
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether
)
from reportlab.lib.colors import HexColor

OUTPUT = "/home/daytona/workspace/murmur-pdf/Heart_Murmurs_Quick_Reference.pdf"

# ── Colour palette (medical deep teal / crimson accent) ──────────────────────
C_HEADER    = HexColor("#1A3A4A")   # dark teal – page header bar
C_SEC       = HexColor("#1E6E8A")   # section heading blue
C_ACCENT    = HexColor("#C0392B")   # crimson accent
C_SYS       = HexColor("#D4EFFA")   # light blue – systolic rows
C_DIA       = HexColor("#FAD7D4")   # light pink – diastolic rows
C_CON       = HexColor("#D4FAD7")   # light green – continuous rows
C_TBLHDR    = HexColor("#1A3A4A")   # table header bg
C_ALT       = HexColor("#F4F8FB")   # alternating row
C_GRADE_HDR = HexColor("#2C3E50")
C_MANV_HDR  = HexColor("#17455A")
WHITE       = colors.white
BLACK       = colors.black

PAGE_W, PAGE_H = A4
MARGIN = 1.5 * cm

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    leftMargin=MARGIN, rightMargin=MARGIN,
    topMargin=1.8*cm, bottomMargin=1.8*cm,
    title="Heart Murmurs Quick Reference",
    author="Orris Medical"
)

styles = getSampleStyleSheet()

def S(name, **kw):
    return ParagraphStyle(name, parent=styles["Normal"], **kw)

# Custom styles
TITLE_STYLE = S("MyTitle", fontSize=22, textColor=WHITE,
                fontName="Helvetica-Bold", alignment=TA_CENTER, leading=28)
SUBTITLE_STYLE = S("MySub", fontSize=11, textColor=HexColor("#B0D4E8"),
                   fontName="Helvetica", alignment=TA_CENTER, leading=15)
SEC_STYLE = S("MySec", fontSize=13, textColor=WHITE,
              fontName="Helvetica-Bold", alignment=TA_LEFT, leading=17,
              spaceBefore=6, spaceAfter=4)
BODY = S("MyBody", fontSize=9, leading=13, textColor=BLACK)
SMALL = S("MySmall", fontSize=8, leading=11, textColor=HexColor("#333333"))
BOLD_CELL = S("BoldCell", fontSize=8.5, fontName="Helvetica-Bold",
              leading=11, textColor=BLACK)
ITALIC_CELL = S("ItalicCell", fontSize=8, fontName="Helvetica-Oblique",
                leading=11, textColor=HexColor("#444444"))
NOTE_STYLE = S("MyNote", fontSize=8, textColor=HexColor("#555555"),
               fontName="Helvetica-Oblique", leading=11)
FOOTER_STYLE = S("Footer", fontSize=7.5, textColor=HexColor("#888888"),
                 alignment=TA_CENTER)

# ── Helper: section banner ────────────────────────────────────────────────────
def section_banner(title, bg=C_SEC):
    tbl = Table([[Paragraph(title, SEC_STYLE)]], colWidths=[PAGE_W - 2*MARGIN])
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), bg),
        ("ROUNDEDCORNERS", [4]),
        ("TOPPADDING",    (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
        ("LEFTPADDING",   (0,0), (-1,-1), 8),
    ]))
    return tbl

# ── Helper: generic styled table ─────────────────────────────────────────────
def make_table(headers, rows, col_widths, row_colors=None):
    """row_colors: list same length as rows, each a hex string or None"""
    header_row = [Paragraph(f"<b>{h}</b>", S("TH", fontSize=9,
                  textColor=WHITE, fontName="Helvetica-Bold", leading=12))
                  for h in headers]
    data = [header_row]
    for r in rows:
        data.append([Paragraph(str(cell), SMALL) for cell in r])

    tbl = Table(data, colWidths=col_widths, repeatRows=1)
    ts = [
        ("BACKGROUND",   (0, 0), (-1, 0), C_TBLHDR),
        ("TEXTCOLOR",    (0, 0), (-1, 0), WHITE),
        ("FONTNAME",     (0, 0), (-1, 0), "Helvetica-Bold"),
        ("GRID",         (0, 0), (-1,-1), 0.4, HexColor("#CCCCCC")),
        ("ROWBACKGROUNDS",(0, 1), (-1,-1), [WHITE, C_ALT]),
        ("TOPPADDING",   (0, 0), (-1,-1), 4),
        ("BOTTOMPADDING",(0, 0), (-1,-1), 4),
        ("LEFTPADDING",  (0, 0), (-1,-1), 6),
        ("RIGHTPADDING", (0, 0), (-1,-1), 6),
        ("VALIGN",       (0, 0), (-1,-1), "TOP"),
    ]
    if row_colors:
        for i, rc in enumerate(row_colors, start=1):
            if rc:
                ts.append(("BACKGROUND", (0, i), (-1, i), rc))
    tbl.setStyle(TableStyle(ts))
    return tbl

# ════════════════════════════════════════════════════════════════════════════
# BUILD CONTENT
# ════════════════════════════════════════════════════════════════════════════
story = []

# ── TITLE BLOCK ──────────────────────────────────────────────────────────────
title_tbl = Table(
    [[Paragraph("HEART MURMURS", TITLE_STYLE)],
     [Paragraph("Quick Reference Card  ·  CVS Auscultation", SUBTITLE_STYLE)]],
    colWidths=[PAGE_W - 2*MARGIN]
)
title_tbl.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,-1), C_HEADER),
    ("TOPPADDING",    (0,0), (-1,-1), 12),
    ("BOTTOMPADDING", (0,0), (-1,-1), 10),
    ("LEFTPADDING",   (0,0), (-1,-1), 12),
    ("ROUNDEDCORNERS",[6]),
]))
story.append(title_tbl)
story.append(Spacer(1, 10))

# ── SECTION 1 – MURMUR TIMING ────────────────────────────────────────────────
story.append(section_banner("1.  MURMUR TIMING"))
story.append(Spacer(1, 5))

story.append(Paragraph(
    "The <b>first and most important</b> step in identifying any murmur is establishing "
    "its timing within the cardiac cycle relative to S1 and S2.",
    BODY))
story.append(Spacer(1, 6))

# 1a Systolic
story.append(Paragraph("<b>A.  Systolic Murmurs</b>  (S1 → S2)", BODY))
story.append(Spacer(1, 3))

sys_headers = ["Sub-type", "Onset / End", "Shape", "Key Causes"]
sys_rows = [
    ["Early Systolic",
     "Begins at S1; ends well before S2",
     "Decrescendo",
     "Acute MR (papillary / chordal rupture); muscular VSD; TR with normal PA pressure"],
    ["Mid-Systolic\n(Ejection)",
     "Starts after S1 (after IVCT); ends before S2",
     "Crescendo-decrescendo (diamond)",
     "Aortic stenosis; pulmonic stenosis; HCM; aortic sclerosis; high-output states (anaemia, pregnancy, thyrotoxicosis)"],
    ["Holosystolic\n(Pansystolic)",
     "S1 to S2 – spans all of systole",
     "Plateau (constant)",
     "Chronic MR; tricuspid regurgitation; VSD (restrictive)"],
    ["Late Systolic",
     "Mid-to-late systole; ends at S2",
     "Crescendo (often preceded by click)",
     "Mitral valve prolapse; papillary muscle dysfunction"],
]
sys_colors = [C_SYS, C_SYS, C_SYS, C_SYS]
story.append(make_table(sys_headers, sys_rows,
    [3.2*cm, 4.2*cm, 3.5*cm, 6.5*cm], row_colors=sys_colors))
story.append(Spacer(1, 6))

# 1b Diastolic
story.append(Paragraph("<b>B.  Diastolic Murmurs</b>  (S2 → S1) – Almost always pathological", BODY))
story.append(Spacer(1, 3))

dia_headers = ["Sub-type", "Onset / End", "Quality", "Key Causes"]
dia_rows = [
    ["Early Diastolic",
     "Immediately after S2; decrescendo",
     "Blowing, high-pitched\n(use diaphragm)",
     "Aortic regurgitation; pulmonary regurgitation (Graham Steell)"],
    ["Mid-Diastolic",
     "After brief gap post-S2",
     "Rumbling, low-pitched\n(use BELL)",
     "Mitral stenosis (follows OS); tricuspid stenosis; Austin Flint murmur"],
    ["Presystolic",
     "Just before S1; ends at S1",
     "Crescendo rumble",
     "Mitral stenosis (sinus rhythm only); tricuspid stenosis"],
]
dia_colors = [C_DIA, C_DIA, C_DIA]
story.append(make_table(dia_headers, dia_rows,
    [3.2*cm, 4.2*cm, 3.5*cm, 6.5*cm], row_colors=dia_colors))
story.append(Spacer(1, 6))

# 1c Continuous
story.append(Paragraph("<b>C.  Continuous Murmurs</b>  (systole + diastole)", BODY))
story.append(Spacer(1, 3))

con_headers = ["Cause", "Character", "Notes"]
con_rows = [
    ["Patent Ductus Arteriosus (PDA)",
     "Machinery murmur – peaks around S2; heard continuously",
     "2nd LICS; louder in systole and around S2"],
    ["Arteriovenous fistula",
     "Continuous bruit",
     "At site of fistula"],
    ["Venous hum",
     "Continuous, low humming",
     "At neck/clavicle; disappears with neck vein compression – INNOCENT"],
    ["Cervical bruit (carotid stenosis)",
     "Systolic > diastolic",
     "Heard at neck; obliterates with stethoscope pressure"],
]
con_colors = [C_CON]*4
story.append(make_table(con_headers, con_rows,
    [4.5*cm, 5.5*cm, 7.4*cm], row_colors=con_colors))
story.append(Spacer(1, 8))

# ── SECTION 2 – VALVE TIMING RULE ───────────────────────────────────────────
story.append(section_banner("2.  VALVE TIMING RULE (Memory Aid)", C_ACCENT))
story.append(Spacer(1, 5))

vt_headers = ["Valve", "Abnormality", "Murmur Timing", "Mnemonic"]
vt_rows = [
    ["Aortic / Pulmonary", "Stenosis",      "Systolic",  "SAS – Systolic Aortic Stenosis"],
    ["Aortic / Pulmonary", "Regurgitation", "Diastolic", "ARD – Aortic Regurgitation = Diastolic"],
    ["Mitral / Tricuspid", "Stenosis",      "Diastolic", "MSD – Mitral Stenosis = Diastolic"],
    ["Mitral / Tricuspid", "Regurgitation", "Systolic",  "MRS – Mitral Regurgitation = Systolic"],
]
story.append(make_table(vt_headers, vt_rows,
    [4.5*cm, 4*cm, 3.5*cm, 5.4*cm]))
story.append(Spacer(1, 6))
story.append(Paragraph(
    "<i>Rule: Stenosis of a semilunar valve = systolic (blocked outflow); "
    "Regurgitation of an AV valve = systolic (backward during high-pressure systole). "
    "Everything flips for the other group.</i>", NOTE_STYLE))
story.append(Spacer(1, 8))

# ── SECTION 3 – GRADING (LEVINE SCALE) ──────────────────────────────────────
story.append(section_banner("3.  GRADING OF INTENSITY — Levine Scale (I – VI)"))
story.append(Spacer(1, 5))

grade_headers = ["Grade", "Description", "Thrill?", "Clinical Significance"]
grade_rows = [
    ["I / VI",   "Very soft; heard only with deliberate effort", "No",  "Borderline clinical significance; often innocent"],
    ["II / VI",  "Soft but easily audible",                      "No",  "Common; may be innocent or pathological"],
    ["III / VI", "Moderately loud",                              "No",  "Usually pathological; echocardiography warranted"],
    ["IV / VI",  "Loud",                                         "YES", "Structural heart disease very likely"],
    ["V / VI",   "Very loud; heard with stethoscope edge on chest","YES","Significant structural pathology"],
    ["VI / VI",  "Heard with stethoscope off the chest",         "YES", "Severe structural pathology"],
]
rc = [C_ALT, WHITE, C_SYS, HexColor("#FDEBD0"), C_DIA, HexColor("#FADBD8")]
story.append(make_table(grade_headers, grade_rows,
    [2*cm, 6.5*cm, 2.2*cm, 6.7*cm], row_colors=rc))

story.append(Spacer(1, 5))
story.append(Paragraph(
    "<b>Rule of thumb:</b>  Grade <b>I–II</b> midsystolic in asymptomatic young patients = likely innocent. "
    "Grade <b>≥ III</b> systolic (especially holosystolic or late systolic), "
    "or <b>any diastolic / continuous</b> murmur = echocardiography indicated.", BODY))
story.append(Spacer(1, 8))

# ── SECTION 4 – LOCATION & RADIATION ────────────────────────────────────────
story.append(section_banner("4.  LOCATION & RADIATION"))
story.append(Spacer(1, 5))

loc_headers = ["Murmur", "Best Heard At", "Radiates To", "Key Feature"]
loc_rows = [
    ["Aortic Stenosis",       "2nd RICS (aortic area)",        "Carotids, neck",           "Slow-rising pulse; ejection click (mild AS)"],
    ["Pulmonic Stenosis",     "2nd LICS",                      "Left shoulder / neck",     "Wide split S2; RV heave"],
    ["Mitral Regurgitation",  "Apex (mitral area)",            "Left axilla",              "S3 often present; anterior jet = LSB radiation"],
    ["Tricuspid Regurgitation","Lower LSB (4th LICS)",         "Right side; no radiation", "Increases with inspiration (Carvallo's sign)"],
    ["VSD",                   "3rd–4th LICS",                  "Entire precordium",        "Thrill at LSB; louder = smaller defect"],
    ["Mitral Stenosis",       "Apex (left lateral position)",  "Minimal",                  "Rumbling; opening snap; loud S1"],
    ["Aortic Regurgitation",  "3rd LICS (Erb's point)",        "Apex",                     "Austin Flint murmur; Corrigan's pulse"],
    ["PDA",                   "2nd LICS infraclavicular",      "Left shoulder",            "Continuous 'machinery' murmur"],
    ["HCM",                   "Lower LSB / apex",              "Carotids (variable)",      "Increases with Valsalva / standing; decreases with squatting"],
]
story.append(make_table(loc_headers, loc_rows,
    [3.8*cm, 4*cm, 3.8*cm, 5.8*cm]))
story.append(Spacer(1, 8))

# ── PAGE BREAK before bedside maneuvers ──────────────────────────────────────
from reportlab.platypus import PageBreak
story.append(PageBreak())

# ── SECTION 5 – BEDSIDE MANEUVERS ────────────────────────────────────────────
story.append(section_banner("5.  BEDSIDE MANEUVERS & THEIR EFFECTS", C_MANV_HDR))
story.append(Spacer(1, 5))

story.append(Paragraph(
    "Maneuvers alter <b>preload</b>, <b>afterload</b>, or <b>contractility</b>, "
    "changing murmur intensity or timing in predictable ways. "
    "Key principle: most murmurs <i>increase</i> with greater volume/flow, "
    "except <b>HCM</b> and <b>MVP</b> which behave paradoxically.",
    BODY))
story.append(Spacer(1, 6))

man_headers = ["Maneuver", "Preload", "Afterload", "HCM", "MVP (click timing)", "AS / MR / VSD"]
man_rows = [
    ["Valsalva (strain phase)",  "Decreases", "Decreases",
     "LOUDER (obstruction worse)", "Click moves EARLIER (louder murmur, longer)",
     "Softer"],
    ["Valsalva release\n(post-strain)",
     "Increases", "Increases",
     "Softer", "Click moves LATER (shorter murmur)",
     "Louder (transient)"],
    ["Standing (from squat)",
     "Decreases", "Decreases",
     "LOUDER", "Click earlier; murmur louder",
     "Softer"],
    ["Squatting (from stand)",
     "Increases", "Increases",
     "Softer", "Click later; murmur softer/shorter",
     "LOUDER"],
    ["Passive leg raise",
     "Increases", "–",
     "Softer", "Click later; murmur softer",
     "Louder"],
    ["Isometric handgrip\n(sustained)",
     "–", "Increases (SVR up)",
     "Softer", "Click later; murmur softer",
     "MR, VSD, AR louder; AS softer"],
    ["Amyl nitrite\n(vasodilator)",
     "Decreases (pooling)", "Decreases",
     "LOUDER", "Click earlier; murmur louder",
     "AS louder; AR softer; MR softer"],
    ["Inspiration",
     "Increases (right-sided)", "–",
     "Variable", "Variable",
     "Right-sided murmurs LOUDER (Carvallo's); left-sided unchanged"],
    ["Expiration",
     "–", "–",
     "Variable", "Variable",
     "Left-sided murmurs slightly louder; aortic click louder"],
]
story.append(make_table(man_headers, man_rows,
    [3.2*cm, 2*cm, 2*cm, 3.2*cm, 4*cm, 3*cm]))
story.append(Spacer(1, 8))

# ── SECTION 6 – MANEUVER QUICK MEMORY ───────────────────────────────────────
story.append(section_banner("6.  QUICK MEMORY: MANEUVER EFFECTS", C_ACCENT))
story.append(Spacer(1, 5))

mem_data = [
    [Paragraph("<b>Decreases preload</b>\n(Standing, Valsalva strain, Amyl nitrite)", SMALL),
     Paragraph(
         "HCM: <b>LOUDER</b> (LV outflow tract narrows)\n"
         "MVP: click moves EARLIER, murmur longer\n"
         "Most others: SOFTER (less flow)", SMALL)],
    [Paragraph("<b>Increases preload</b>\n(Squatting, Passive leg raise, Post-Valsalva release)", SMALL),
     Paragraph(
         "HCM: <b>SOFTER</b> (better LV filling, less obstruction)\n"
         "MVP: click moves LATER, murmur shorter\n"
         "Most others: LOUDER", SMALL)],
    [Paragraph("<b>Increases afterload</b>\n(Isometric handgrip, Squatting)", SMALL),
     Paragraph(
         "MR, VSD, AR: LOUDER (more pressure gradient)\n"
         "AS: SOFTER (relative)\n"
         "HCM: SOFTER (LV does not need to obstruct as hard)", SMALL)],
    [Paragraph("<b>Inspiration</b>", SMALL),
     Paragraph(
         "Right-sided murmurs LOUDER (TR, PS, TS)\n"
         "Carvallo's sign: TR murmur increases with inspiration\n"
         "S3/S4 from right side: louder on inspiration", SMALL)],
]
mem_tbl = Table(mem_data, colWidths=[6*cm, 11.4*cm])
mem_tbl.setStyle(TableStyle([
    ("BACKGROUND",    (0, 0), (0, -1), HexColor("#EAF4FB")),
    ("BACKGROUND",    (1, 0), (1, -1), WHITE),
    ("ROWBACKGROUNDS",(0, 0), (-1,-1), [HexColor("#EAF4FB"), HexColor("#FDF6F0"),
                                         HexColor("#F0FBF0"), HexColor("#FBF0F0")]),
    ("GRID",          (0, 0), (-1,-1), 0.4, HexColor("#CCCCCC")),
    ("VALIGN",        (0, 0), (-1,-1), "TOP"),
    ("TOPPADDING",    (0, 0), (-1,-1), 5),
    ("BOTTOMPADDING", (0, 0), (-1,-1), 5),
    ("LEFTPADDING",   (0, 0), (-1,-1), 7),
    ("RIGHTPADDING",  (0, 0), (-1,-1), 7),
]))
story.append(mem_tbl)
story.append(Spacer(1, 8))

# ── SECTION 7 – INNOCENT vs PATHOLOGICAL ─────────────────────────────────────
story.append(section_banner("7.  INNOCENT vs PATHOLOGICAL MURMURS"))
story.append(Spacer(1, 5))

ip_headers = ["Feature", "Innocent Murmur", "Pathological Murmur"]
ip_rows = [
    ["Timing",       "Mid-systolic only",                  "Holosystolic, late systolic, diastolic, or continuous"],
    ["Grade",        "I–II / VI",                          "Often III / VI or louder"],
    ["Thrill",       "Absent",                             "May be present (grade IV+)"],
    ["Quality",      "Soft, vibratory (Still's murmur)",   "Harsh, blowing, or rumbling"],
    ["Radiation",    "Minimal / none",                     "Often radiates (axilla, neck, etc.)"],
    ["S2",           "Normal split",                       "May be abnormal (fixed split, absent, etc.)"],
    ["Associated Sx","None – asymptomatic",                "Dyspnoea, syncope, chest pain, cyanosis"],
    ["Response",     "Decreases with standing / Valsalva", "Variable; persists or worsens"],
    ["Echocardiography","Not required if typical features","Indicated (any diastolic/continuous; grade ≥ III systolic)"],
]
story.append(make_table(ip_headers, ip_rows,
    [4*cm, 5.5*cm, 7.9*cm]))
story.append(Spacer(1, 8))

# ── SECTION 8 – SPECIAL MURMUR CHARACTERS ────────────────────────────────────
story.append(section_banner("8.  CHARACTERISTIC MURMUR DESCRIPTIONS"))
story.append(Spacer(1, 5))

char_headers = ["Murmur", "Classic Description", "Key Additional Sign"]
char_rows = [
    ["Aortic Stenosis",        "Harsh, rough crescendo-decrescendo ejection murmur; may sound musical at apex (Gallavardin)", "Slow-rising carotid pulse; systolic thrill at 2nd RICS"],
    ["Aortic Regurgitation",   "Soft, blowing, high-pitched decrescendo diastolic (Erb's point); sometimes audible unaided", "Corrigan's (water-hammer) pulse; Austin Flint mid-diastolic rumble"],
    ["Mitral Stenosis",        "Low-pitched, rumbling mid-diastolic; loud S1; opening snap (OS) after S2", "OS-S2 interval inversely proportional to severity; presystolic accentuation in SR"],
    ["Mitral Regurgitation",   "Holosystolic plateau murmur; best at apex; radiates to axilla", "S3 gallop; displaced hyperdynamic apex"],
    ["Mitral Valve Prolapse",  "Mid-systolic click followed by late systolic murmur (crescendo to S2)", "Click moves earlier and murmur lengthens with standing / Valsalva"],
    ["PDA",                    "'Machinery' continuous murmur; peaks around S2; heard under left clavicle", "Bounding peripheral pulses; wide pulse pressure"],
    ["VSD (restrictive)",      "Loud (grade IV–V) holosystolic murmur at LSB; thrill usually present", "Louder murmur paradoxically = smaller, more restrictive defect"],
    ["HCM",                    "Harsh mid-systolic ejection at LSB/apex; does NOT radiate well to neck", "Dynamic obstruction; increases with Valsalva / standing"],
    ["TR",                     "Holosystolic at lower LSB; softer than MR", "Carvallo's sign (louder with inspiration); prominent v wave in JVP"],
    ["Graham Steell",          "Early diastolic decrescendo at pulmonary area", "Pulmonary regurgitation due to pulmonary hypertension"],
    ["Austin Flint",           "Mid-diastolic rumble at apex (mimics MS)",      "Seen in severe AR; no opening snap; S1 not loud"],
]
story.append(make_table(char_headers, char_rows,
    [4*cm, 6.8*cm, 6.6*cm]))
story.append(Spacer(1, 6))

# ── FOOTER NOTE ──────────────────────────────────────────────────────────────
story.append(HRFlowable(width="100%", thickness=0.5, color=HexColor("#AAAAAA")))
story.append(Spacer(1, 4))
story.append(Paragraph(
    "Sources: Harrison's Principles of Internal Medicine 22nd Ed. (2025) · "
    "Fuster &amp; Hurst's The Heart 15th Ed. · Ganong's Review of Medical Physiology 26th Ed.  "
    "| Orris Medical Quick Reference · For clinical use — always correlate with full patient assessment.",
    FOOTER_STYLE))

# ── BUILD ─────────────────────────────────────────────────────────────────────
doc.build(story)
print("PDF created:", OUTPUT)
Running Command

cd /home/daytona/workspace/murmur-pdf && python create_murmur_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/murmur-pdf/Heart_Murmurs_Quick_Reference.pdf

Your quick reference PDF is ready:

Heart Murmurs Quick Reference

PDF Document · PDF


Here is what is packed into the 2-page A4 card:
Page 1
  1. Murmur Timing - colour-coded tables for systolic (blue), diastolic (pink), and continuous (green) murmurs with sub-types, onset/end, shape, and key causes
  2. Valve Timing Rule - the SADS/MRDS memory aid table
  3. Levine Grading Scale (I-VI) - with thrill presence and clinical significance per grade
  4. Location & Radiation - 9 murmurs mapped to their best-heard site, radiation, and key feature
Page 2 5. Bedside Maneuvers - full table: Valsalva, standing/squatting, handgrip, amyl nitrite, inspiration/expiration - with effects on preload, afterload, HCM, MVP, and other murmurs 6. Quick Memory Box - preload down/up, afterload up, and inspiration effects all at a glance 7. Innocent vs Pathological - 9-point comparison table 8. Characteristic Descriptions - 11 named murmurs (AS, AR, MS, MR, MVP, PDA, VSD, HCM, TR, Graham Steell, Austin Flint) with classic descriptors and associated signs
Sources: Harrison's 22nd Ed. (2025), Fuster & Hurst's The Heart 15th Ed., Ganong's 26th Ed.
This is a shared conversation. Sign in to Orris to start your own chat.