Create a detailed PDF of 'APPROACH TO THE PATIENT AND GENERAL EXAMINATION OF PATIENT'
mkdir -p /tmp/workspace/patient-examination && ls /tmp/workspace/patient-examination/
~/patient-examination/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, ListFlowable, ListItem, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus.flowables import HRFlowable
OUTPUT_PATH = "/tmp/workspace/patient-examination/Approach_to_Patient_General_Examination.pdf"
# ─── Page layout ───────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT_PATH,
pagesize=A4,
topMargin=2*cm, bottomMargin=2*cm,
leftMargin=2.2*cm, rightMargin=2.2*cm,
title="Approach to the Patient & General Examination",
author="Orris Medical Reference",
subject="Clinical Medicine"
)
# ─── Colour palette ────────────────────────────────────────────────────────────
DARK_BLUE = colors.HexColor("#1A3A5C")
MID_BLUE = colors.HexColor("#2E6DA4")
LIGHT_BLUE = colors.HexColor("#D6E8F7")
ACCENT = colors.HexColor("#E8A020")
LIGHT_GRAY = colors.HexColor("#F5F5F5")
MED_GRAY = colors.HexColor("#CCCCCC")
TEXT_COLOR = colors.HexColor("#1A1A1A")
WHITE = colors.white
# ─── Styles ────────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
cover_title = ParagraphStyle(
"CoverTitle", fontSize=28, leading=34, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER, spaceAfter=10
)
cover_sub = ParagraphStyle(
"CoverSub", fontSize=15, leading=20, textColor=colors.HexColor("#C8DCEF"),
fontName="Helvetica", alignment=TA_CENTER, spaceAfter=6
)
cover_ref = ParagraphStyle(
"CoverRef", fontSize=9, leading=13, textColor=colors.HexColor("#A0C0E0"),
fontName="Helvetica-Oblique", alignment=TA_CENTER
)
h1 = ParagraphStyle(
"H1", fontSize=16, leading=20, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_LEFT,
spaceBefore=14, spaceAfter=4, leftIndent=0
)
h2 = ParagraphStyle(
"H2", fontSize=13, leading=17, textColor=DARK_BLUE,
fontName="Helvetica-Bold", alignment=TA_LEFT,
spaceBefore=12, spaceAfter=4
)
h3 = ParagraphStyle(
"H3", fontSize=11, leading=15, textColor=MID_BLUE,
fontName="Helvetica-Bold", alignment=TA_LEFT,
spaceBefore=8, spaceAfter=3
)
body = ParagraphStyle(
"Body", fontSize=10, leading=15, textColor=TEXT_COLOR,
fontName="Helvetica", alignment=TA_JUSTIFY,
spaceBefore=3, spaceAfter=3
)
bullet_style = ParagraphStyle(
"Bullet", fontSize=10, leading=14, textColor=TEXT_COLOR,
fontName="Helvetica", alignment=TA_LEFT,
leftIndent=14, spaceBefore=2, spaceAfter=2,
bulletIndent=4
)
note_style = ParagraphStyle(
"Note", fontSize=9, leading=13, textColor=colors.HexColor("#4A4A4A"),
fontName="Helvetica-Oblique", alignment=TA_LEFT,
leftIndent=10, spaceBefore=2, spaceAfter=2
)
caption_style = ParagraphStyle(
"Caption", fontSize=8, leading=11, textColor=MID_BLUE,
fontName="Helvetica-Bold", alignment=TA_CENTER, spaceAfter=4
)
# ─── Helper: section banner ────────────────────────────────────────────────────
def section_banner(text):
tbl = Table([[Paragraph(text, h1)]], colWidths=[doc.width])
tbl.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, -1), DARK_BLUE),
("TOPPADDING", (0, 0), (-1, -1), 8),
("BOTTOMPADDING", (0, 0), (-1, -1), 8),
("LEFTPADDING", (0, 0), (-1, -1), 12),
("RIGHTPADDING", (0, 0), (-1, -1), 12),
("ROUNDEDCORNERS", [4, 4, 4, 4]),
]))
return tbl
def info_box(text, bg=LIGHT_BLUE, border=MID_BLUE):
tbl = Table([[Paragraph(text, body)]], colWidths=[doc.width])
tbl.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, -1), bg),
("BOX", (0, 0), (-1, -1), 1.2, border),
("TOPPADDING", (0, 0), (-1, -1), 8),
("BOTTOMPADDING", (0, 0), (-1, -1), 8),
("LEFTPADDING", (0, 0), (-1, -1), 12),
("RIGHTPADDING", (0, 0), (-1, -1), 12),
]))
return tbl
def accent_box(title, rows):
"""Two-column key-value highlight box."""
data = [[Paragraph(f"<b>{k}</b>", body), Paragraph(v, body)] for k, v in rows]
col_w = [doc.width * 0.35, doc.width * 0.65]
tbl = Table(data, colWidths=col_w)
tbl.setStyle(TableStyle([
("BACKGROUND", (0, 0), (0, -1), LIGHT_BLUE),
("BACKGROUND", (1, 0), (1, -1), colors.HexColor("#FAFCFF")),
("ROWBACKGROUNDS", (0, 0), (-1, -1), [LIGHT_BLUE, colors.HexColor("#EAF3FC")]),
("BOX", (0, 0), (-1, -1), 1, MID_BLUE),
("INNERGRID", (0, 0), (-1, -1), 0.5, MED_GRAY),
("TOPPADDING", (0, 0), (-1, -1), 5),
("BOTTOMPADDING", (0, 0), (-1, -1), 5),
("LEFTPADDING", (0, 0), (-1, -1), 8),
("RIGHTPADDING", (0, 0), (-1, -1), 8),
("VALIGN", (0, 0), (-1, -1), "TOP"),
]))
return tbl
def two_col_table(data, header_row=None):
col_w = [doc.width * 0.35, doc.width * 0.65]
rows = []
if header_row:
rows.append([Paragraph(f"<b>{h}</b>", body) for h in header_row])
for k, v in data:
rows.append([Paragraph(f"<b>{k}</b>", body), Paragraph(v, body)])
tbl = Table(rows, colWidths=col_w)
style_cmds = [
("BOX", (0, 0), (-1, -1), 1, MID_BLUE),
("INNERGRID", (0, 0), (-1, -1), 0.5, MED_GRAY),
("TOPPADDING", (0, 0), (-1, -1), 5),
("BOTTOMPADDING", (0, 0), (-1, -1), 5),
("LEFTPADDING", (0, 0), (-1, -1), 8),
("RIGHTPADDING", (0, 0), (-1, -1), 8),
("VALIGN", (0, 0), (-1, -1), "TOP"),
]
if header_row:
style_cmds += [
("BACKGROUND", (0, 0), (-1, 0), DARK_BLUE),
("TEXTCOLOR", (0, 0), (-1, 0), WHITE),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
]
else:
style_cmds += [("ROWBACKGROUNDS", (0, 0), (-1, -1), [LIGHT_BLUE, WHITE])]
tbl.setStyle(TableStyle(style_cmds))
return tbl
def bullets(items):
return [Paragraph(f"• {item}", bullet_style) for item in items]
def hr():
return HRFlowable(width="100%", thickness=1.2, color=MID_BLUE, spaceAfter=6, spaceBefore=6)
# ─── COVER PAGE ────────────────────────────────────────────────────────────────
def cover_page():
elems = []
# top colour block
cover_data = [[
Paragraph("APPROACH TO THE PATIENT", cover_title),
Paragraph("& GENERAL EXAMINATION", cover_title),
Spacer(1, 0.4*cm),
Paragraph("A Comprehensive Clinical Reference", cover_sub),
Spacer(1, 0.3*cm),
Paragraph("Based on Goldman-Cecil Medicine · Fuster & Hurst's The Heart · Bailey & Love's Surgery · S. Das Manual on Clinical Surgery · Neuroanatomy Through Clinical Cases", cover_ref),
Spacer(1, 0.5*cm),
Paragraph("Orris Medical Reference | July 2026", cover_ref),
]]
cover_tbl = Table(cover_data, colWidths=[doc.width])
cover_tbl.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, -1), DARK_BLUE),
("TOPPADDING", (0, 0), (-1, -1), 28),
("BOTTOMPADDING", (0, 0), (-1, -1), 28),
("LEFTPADDING", (0, 0), (-1, -1), 24),
("RIGHTPADDING", (0, 0), (-1, -1), 24),
]))
elems.append(Spacer(1, 2*cm))
elems.append(cover_tbl)
elems.append(Spacer(1, 1*cm))
# TOC box
toc_items = [
("1.", "Approach to the Patient — Principles"),
("2.", "History Taking — Structure & Components"),
("3.", "General Appearance & First Impression"),
("4.", "Vital Signs — Temperature, Pulse, BP, RR, SpO₂"),
("5.", "Systematic General Examination Head to Toe"),
("6.", "Examination of Hands, Nails & Peripheral Circulation"),
("7.", "Examination of the Head & Neck"),
("8.", "Chest & Cardiovascular Examination Overview"),
("9.", "Abdominal Examination Overview"),
("10.", "Neurological General Examination"),
("11.", "Lymph Nodes, Skin & Musculoskeletal Assessment"),
("12.", "Assessment, Differential Diagnosis & Plan"),
("13.", "Special Populations & Key Clinical Pearls"),
]
toc_data = [[Paragraph(f"<b>{n}</b>", body), Paragraph(desc, body)] for n, desc in toc_items]
toc_tbl = Table(toc_data, colWidths=[doc.width * 0.1, doc.width * 0.9])
toc_tbl.setStyle(TableStyle([
("ROWBACKGROUNDS", (0, 0), (-1, -1), [LIGHT_BLUE, WHITE]),
("BOX", (0, 0), (-1, -1), 1, MID_BLUE),
("INNERGRID", (0, 0), (-1, -1), 0.3, MED_GRAY),
("TOPPADDING", (0, 0), (-1, -1), 4),
("BOTTOMPADDING", (0, 0), (-1, -1), 4),
("LEFTPADDING", (0, 0), (-1, -1), 8),
("RIGHTPADDING", (0, 0), (-1, -1), 8),
]))
toc_header = Table([[Paragraph("<b>TABLE OF CONTENTS</b>", ParagraphStyle("TOCHead",
fontSize=12, fontName="Helvetica-Bold", textColor=WHITE, alignment=TA_CENTER))]],
colWidths=[doc.width])
toc_header.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, -1), MID_BLUE),
("TOPPADDING", (0, 0), (-1, -1), 7),
("BOTTOMPADDING", (0, 0), (-1, -1), 7),
]))
elems.append(toc_header)
elems.append(toc_tbl)
elems.append(PageBreak())
return elems
# ─── CONTENT ───────────────────────────────────────────────────────────────────
story = []
story += cover_page()
# ═══ SECTION 1: APPROACH TO THE PATIENT — PRINCIPLES ══════════════════════════
story.append(section_banner("1. APPROACH TO THE PATIENT — PRINCIPLES"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
"The clinical encounter is the foundation of medical practice. Every clinician must develop a "
"systematic, reproducible approach to each patient — one that is thorough, empathetic, and "
"efficient. The goal is to gather sufficient information through history, examination, and "
"investigations to reach a diagnosis and formulate a management plan.",
body
))
story.append(Spacer(1, 0.2*cm))
story.append(info_box(
"<b>Core Principle (Goldman-Cecil Medicine):</b> \"Care of the patient is guided by integration "
"of the chief complaint, history, vital signs, and findings on physical examination. Physicians "
"should be keenly aware of a patient's vital signs, because they are important markers of "
"clinical stability.\""
))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("The Five Pillars of Patient Assessment", h2))
pillar_data = [
("Chief Complaint", "The primary symptom or reason for the patient's presentation, stated in their own words."),
("History", "A structured account of the present illness, past medical/surgical history, medications, allergies, family & social history."),
("Vital Signs", "Temperature, pulse, blood pressure, respiratory rate, oxygen saturation — objective markers of physiologic stability."),
("Physical Examination", "A systematic head-to-toe inspection, palpation, percussion, and auscultation."),
("Assessment & Plan", "Integration of all data into a diagnosis (or differential) and a management strategy."),
]
story.append(two_col_table(pillar_data, header_row=["Pillar", "Description"]))
story.append(Spacer(1, 0.4*cm))
story.append(Paragraph("Key Principles from Fuster & Hurst's The Heart (15th Ed.)", h3))
story.append(Paragraph(
"Each clinician needs to develop his or her own stepwise approach to the cardiovascular "
"examination — and by extension, all physical examinations. The initial history should be "
"taken with the patient fully dressed to allow a one-to-one relationship to be built. "
"For a comprehensive physical examination, the patient must be undressed with an appropriate "
"gown. An examination should <b>never</b> be done by placing the stethoscope under a shirt or "
"blouse; full inspection of the chest and extremities is always necessary.",
body
))
story.append(Spacer(1, 0.5*cm))
# ═══ SECTION 2: HISTORY TAKING ══════════════════════════════════════════════
story.append(section_banner("2. HISTORY TAKING — STRUCTURE & COMPONENTS"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
"A thorough history is the single most important diagnostic tool. Studies show that in the "
"majority of cases, a diagnosis can be made from history alone. The history must be systematic, "
"complete, and documented in a standard order.",
body
))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("A. Identifying Data & Chief Complaint", h2))
story.append(Paragraph(
"Begin every history with identifying data: patient's name, age, sex, occupation, "
"and source of referral. The chief complaint (CC) is the main symptom in the patient's own "
"words, e.g., 'chest pain for 2 hours.' Always record its duration.",
body
))
story.append(Paragraph("B. History of Present Illness (HPI) — SOCRATES Framework", h2))
socrates_data = [
("S — Site", "Where is the problem? Does it radiate anywhere?"),
("O — Onset", "When did it start? Was onset sudden or gradual?"),
("C — Character", "What is the quality? (Sharp, dull, burning, colicky, throbbing)"),
("R — Radiation", "Does it spread? (E.g., angina radiating to the left arm/jaw)"),
("A — Associations", "Associated symptoms? (Nausea, sweating, dyspnoea, etc.)"),
("T — Time course", "Constant or intermittent? Getting better or worse?"),
("E — Exacerbating/Relieving", "What makes it worse or better? (Exercise, rest, food, position)"),
("S — Severity", "Score 1–10. How does it affect daily activities?"),
]
story.append(two_col_table(socrates_data, header_row=["Component", "Key Questions"]))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("C. Past Medical & Surgical History (PMH/PSH)", h2))
story += bullets([
"Previous illnesses, hospitalisations, operations, procedures",
"Childhood illnesses (rheumatic fever, measles, pertussis)",
"Trauma, accidents",
"Obstetric history in women (G×P×, complications, menstrual history)",
"Psychiatric history"
])
story.append(Paragraph("D. Medications & Allergies", h2))
story += bullets([
"Current medications: name, dose, frequency, duration, compliance",
"Over-the-counter drugs, herbal/complementary medicines",
"Drug allergies: document the reaction type (rash, anaphylaxis, intolerance)",
"Vaccinations and immunisation history"
])
story.append(Paragraph("E. Family History", h2))
story += bullets([
"First-degree relatives: parents, siblings, children",
"Heritable conditions: coronary artery disease, diabetes, hypertension, cancer, stroke",
"Genetic disorders, consanguinity in some populations",
"Note age and cause of death of parents if deceased"
])
story.append(Paragraph("F. Social & Personal History", h2))
story += bullets([
"Smoking: pack-year history (packs/day × years)",
"Alcohol: units per week; CAGE questionnaire if indicated",
"Recreational/illicit drug use (non-judgmentally)",
"Occupation and occupational exposures (asbestos, silica, radiation)",
"Marital/relationship status, living conditions, social support",
"Travel history (tropical infections, endemic diseases)",
"Sexual history (orientation, partners, protected sex, STI screening)",
"Military service history (exposures, injuries, PTSD risk)"
])
story.append(Spacer(1, 0.3*cm))
story.append(info_box(
"<b>Clinical Pearl:</b> The social history often unlocks diagnoses that the rest of the history "
"misses. Occupation, travel, and substance use are frequently under-elicited. The [CDC "
"guidelines] recommend routinely collecting sexual orientation and gender identity "
"data to improve care equity."
))
story.append(Spacer(1, 0.5*cm))
# ═══ SECTION 3: GENERAL APPEARANCE ══════════════════════════════════════════
story.append(section_banner("3. GENERAL APPEARANCE & FIRST IMPRESSION"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
"Before touching the patient, spend 30–60 seconds observing their overall appearance. "
"This 'end-of-bed' assessment can yield critical diagnostic information instantly.",
body
))
story.append(Spacer(1, 0.2*cm))
story.append(info_box(
"<b>Goldman-Cecil Medicine:</b> \"Clinicians should never forget that the most important vital sign "
"is what the patient looks like; general appearance is a sign that guides the intensity and "
"urgency of the evaluation.\""
))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("End-of-Bed Observations", h2))
appear_data = [
("Level of consciousness", "Alert, drowsy, confused, stuporous, comatose (use GCS)"),
("Distress / discomfort", "Acute distress, pain grimacing, laboured breathing, agitation"),
("Body habitus", "Obese, cachectic, well-nourished; BMI estimation; muscular wasting"),
("Posture", "Sitting forward (cardiac tamponade, pericarditis, COPD), writhing (colic), rigid (peritonitis)"),
("Skin colour", "Pale (anaemia/shock), jaundiced, cyanosed, flushed, ashen, mottled"),
("Dysmorphic features", "Syndromic features: Marfan, Turner, Down, Cushing — may guide diagnosis immediately"),
("Age vs appearance", "Does the patient look older than stated age? (Chronic disease, lifestyle, neglect)"),
("Hygiene & dress", "Self-neglect may suggest psychiatric illness, dementia, or social deprivation"),
("Assistive devices", "Wheelchair, walking aids, oxygen, hearing aids, glasses"),
("Affect & mood", "Anxious, depressed, flat, irritable — psychiatric assessment prompt"),
]
story.append(two_col_table(appear_data, header_row=["Observation", "Clinical Significance"]))
story.append(Spacer(1, 0.5*cm))
# ═══ SECTION 4: VITAL SIGNS ══════════════════════════════════════════════════
story.append(section_banner("4. VITAL SIGNS"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
"The five key vital signs are temperature, pulse, blood pressure, respiratory rate, and oxygen "
"saturation (pulse oximetry). They are objective, reproducible markers of physiologic stability. "
"Each should be measured accurately and documented at every clinical encounter.",
body
))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("A. Temperature", h2))
temp_data = [
("Normal range", "36.1 – 37.2 °C (97 – 99 °F) orally; rectally ~0.5°C higher"),
("Fever (pyrexia)", ">38.0 °C — infection (bacterial, viral, fungal), inflammatory, malignancy, drugs"),
("Hyperpyrexia", ">40°C — severe sepsis, heatstroke, malignant hyperthermia, neuroleptic malignant syndrome"),
("Hypothermia", "<35°C — exposure, hypothyroidism, sepsis (especially elderly), alcohol intoxication"),
("Methods", "Oral (most common), rectal (most accurate), tympanic, axillary (least accurate), temporal"),
("Fever patterns", "Continuous (lobar pneumonia), intermittent (malaria), remittent (typhoid), hectic/septic (abscess)"),
]
story.append(two_col_table(temp_data))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("B. Pulse", h2))
pulse_data = [
("Normal rate", "60–100 bpm (adults); higher in children, infants"),
("Tachycardia", ">100 bpm — fever, pain, anxiety, anaemia, heart failure, hyperthyroidism, shock"),
("Bradycardia", "<60 bpm — athletes, vagal tone, heart block, hypothyroidism, raised ICP (Cushing reflex), beta-blockers"),
("Rhythm", "Regular or irregular? If irregular — is it regularly irregular (2° heart block) or irregularly irregular (AF)?"),
("Volume", "Full/bounding (fever, AR, PDA, CO₂ retention) vs. weak/thready (shock, dehydration, AS)"),
("Character", "Slow-rising (AS), collapsing (AR, PDA), bisferiens (mixed AS+AR), pulsus alternans (LVF), paradoxus (cardiac tamponade, severe asthma)"),
("Rate variability", "Pulsus paradoxus: >10 mmHg fall in SBP on inspiration — tamponade, severe asthma/COPD"),
("Radial-femoral delay","Coarctation of aorta — always check in young hypertensives"),
]
story.append(two_col_table(pulse_data))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("C. Blood Pressure", h2))
bp_data = [
("Normal", "Systolic 90–120 mmHg; Diastolic 60–80 mmHg"),
("Prehypertension", "120–139/80–89 mmHg — lifestyle modification advised"),
("Stage 1 HTN", "140–159/90–99 mmHg"),
("Stage 2 HTN", "≥160/≥100 mmHg"),
("Hypertensive urgency","≥180/≥120 mmHg without end-organ damage"),
("Hypertensive emergency","≥180/≥120 mmHg WITH end-organ damage (brain, heart, kidneys, eyes)"),
("Hypotension", "<90/60 mmHg — septic, cardiogenic, hypovolaemic, neurogenic, anaphylactic shock"),
("Measurement", "Both arms routinely — >10 mmHg difference suggests subclavian stenosis or aortic dissection"),
("Postural BP", "Lying→standing — fall >20 mmHg systolic or >10 mmHg diastolic = orthostatic hypotension"),
("Pulse pressure", "SBP - DBP; widened (>60) in AR, atherosclerosis; narrowed (<25) in AS, tamponade, shock"),
]
story.append(two_col_table(bp_data))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("D. Respiratory Rate", h2))
rr_data = [
("Normal", "12–20 breaths/min (adults)"),
("Tachypnoea", ">20 — pneumonia, PE, heart failure, metabolic acidosis, pain, anxiety"),
("Bradypnoea", "<12 — opioid overdose, raised ICP, metabolic alkalosis, hypothyroidism"),
("Patterns", "Cheyne-Stokes (CCF, uraemia, raised ICP), Kussmaul (metabolic acidosis), Biot's (raised ICP)"),
("Note", "RR is the most sensitive early indicator of deterioration — often under-recorded. Count for a full 60 seconds."),
]
story.append(two_col_table(rr_data))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("E. Oxygen Saturation (SpO₂)", h2))
spo2_data = [
("Normal", "≥95% on room air (94–98% acceptable range)"),
("Mild hypoxia", "90–94% — supplemental oxygen, investigate cause"),
("Moderate hypoxia","85–89% — high-flow oxygen, close monitoring"),
("Severe hypoxia", "<85% — life-threatening, may need respiratory support"),
("Limitation", "Unreliable in carbon monoxide poisoning (CO-oximetry required); inaccurate in poor perfusion, nail polish, dark pigmentation"),
("Fifth vital sign","Now considered standard alongside T, P, BP, RR in all clinical settings"),
]
story.append(two_col_table(spo2_data))
story.append(Spacer(1, 0.3*cm))
story.append(info_box(
"<b>Additional Metrics to Record:</b> Height and weight → BMI (kg/m²). BMI <18.5 = underweight; "
"18.5–24.9 = normal; 25–29.9 = overweight; ≥30 = obese. Waist circumference (metabolic risk). "
"In elective settings, always record BMI."
))
story.append(Spacer(1, 0.5*cm))
# ═══ SECTION 5: SYSTEMATIC GENERAL EXAMINATION ═══════════════════════════════
story.append(section_banner("5. SYSTEMATIC GENERAL EXAMINATION — HEAD TO TOE"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
"The physical examination proceeds systematically from head to toe. This ensures no region "
"is missed. The four techniques — inspection, palpation, percussion, auscultation (IPPA) — "
"are applied in order to each region, except the abdomen where auscultation precedes palpation.",
body
))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("Sequence of a Complete Physical Examination", h2))
seq_data = [
("1", "General appearance, nutritional status, hydration, mental state"),
("2", "Vital signs (T, P, BP, RR, SpO₂, height, weight, BMI)"),
("3", "Hands, nails, peripheral circulation, radial pulse"),
("4", "Head — scalp, face, eyes (PERLA, fundi), ears, nose, mouth/teeth, throat"),
("5", "Neck — thyroid, trachea, carotids, JVP, lymph nodes"),
("6", "Chest — respiratory system (inspection, palpation, percussion, auscultation)"),
("7", "Cardiovascular — precordium (inspection, palpation, auscultation)"),
("8", "Abdomen — inspection, auscultation, palpation (light then deep), percussion"),
("9", "Genitalia, hernial orifices, per rectal/vaginal examination if indicated"),
("10","Extremities — upper and lower, oedema, peripheral pulses, joints"),
("11","Neurological examination — cranial nerves, motor, sensory, reflexes, coordination, gait"),
("12","Musculoskeletal — joints, spine, muscles"),
("13","Dermatological — skin, hair, nails — systematic survey"),
("14","Lymph nodes — all groups"),
]
seq_table_data = [[Paragraph(f"<b>Step {n}</b>", body), Paragraph(desc, body)] for n, desc in seq_data]
seq_tbl = Table(seq_table_data, colWidths=[doc.width * 0.18, doc.width * 0.82])
seq_tbl.setStyle(TableStyle([
("ROWBACKGROUNDS", (0, 0), (-1, -1), [LIGHT_BLUE, WHITE]),
("BOX", (0, 0), (-1, -1), 1, MID_BLUE),
("INNERGRID", (0, 0), (-1, -1), 0.4, MED_GRAY),
("TOPPADDING", (0, 0), (-1, -1), 4),
("BOTTOMPADDING", (0, 0), (-1, -1), 4),
("LEFTPADDING", (0, 0), (-1, -1), 8),
("RIGHTPADDING", (0, 0), (-1, -1), 8),
("VALIGN", (0, 0), (-1, -1), "TOP"),
]))
story.append(seq_tbl)
story.append(Spacer(1, 0.5*cm))
# ═══ SECTION 6: HANDS, NAILS & PERIPHERAL CIRCULATION ═══════════════════════
story.append(section_banner("6. HANDS, NAILS & PERIPHERAL CIRCULATION"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
"Examination of the hands takes only 30 seconds but yields enormous diagnostic information. "
"Shaking a patient's hand gives a simultaneous frailty assessment, tissue perfusion estimate, "
"myotonia screen, and temperature assessment.",
body
))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("Nail Signs", h2))
nail_data = [
("Clubbing", "Grade I–IV. Causes: bronchogenic carcinoma, suppurative lung disease (abscess, bronchiectasis), cyanotic CHD, infective endocarditis, IBD, cirrhosis, mesothelioma"),
("Koilonychia", "Spoon-shaped nails — iron deficiency anaemia (chronic, severe)"),
("Leuconychia", "White nails — hypoalbuminaemia (chronic liver disease, nephrotic syndrome, malnutrition)"),
("Terry's nails", "White proximally, pink distally — liver cirrhosis, CCF, diabetes"),
("Splinter haemorrhages","Longitudinal brown-red lines — infective endocarditis (distal splinters are often traumatic)"),
("Onycholysis", "Nail lifting from bed — hyperthyroidism (Plummer's nails), psoriasis, trauma, fungal infection"),
("Beau's lines", "Transverse grooves — periods of severe systemic illness, nutritional deficiency, chemotherapy"),
("Mees' lines", "White transverse bands — arsenic poisoning, renal failure, chemotherapy"),
("Cyanosis (peripheral)","Blue discolouration of nails — vasospasm, cold exposure, peripheral vascular disease"),
("Pitting", "Small pits — psoriasis, alopecia areata"),
]
story.append(two_col_table(nail_data, header_row=["Sign", "Causes / Significance"]))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("Hand Signs", h2))
hand_data = [
("Pallor of palmar creases", "Haemoglobin <7–8 g/dL — significant anaemia"),
("Palmar erythema", "Chronic liver disease, pregnancy, RA, hyperthyroidism, idiopathic"),
("Dupuytren's contracture", "Fibrosis of palmar fascia — liver cirrhosis (alcohol), diabetes, trauma, genetic"),
("Tremor", "Resting (Parkinson's), intention (cerebellar), postural (essential tremor, thyrotoxicosis)"),
("Wasting of thenar eminence","Carpal tunnel syndrome (median nerve), T1 root lesion"),
("Wasting of hypothenar", "Ulnar nerve palsy, C8/T1 root lesion, syringomyelia"),
("Heberden's nodes", "DIP joint osteophytes — primary osteoarthritis"),
("Bouchard's nodes", "PIP joint osteophytes — osteoarthritis"),
("Osler's nodes", "Painful nodules on fingertips — infective endocarditis (immune complex)"),
("Janeway lesions", "Non-tender haemorrhagic macules on palms/soles — infective endocarditis (septic emboli)"),
("Xanthomata", "Cholesterol deposits — hypercholesterolaemia, familial hyperlipidaemia"),
]
story.append(two_col_table(hand_data))
story.append(Spacer(1, 0.5*cm))
# ═══ SECTION 7: HEAD & NECK ══════════════════════════════════════════════════
story.append(section_banner("7. HEAD & NECK EXAMINATION"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("Eyes", h2))
eye_data = [
("Conjunctival pallor", "Anaemia — pull down lower lid; pale pink/white mucosa"),
("Scleral icterus", "Jaundice — bilirubin >35 µmol/L; best seen in natural light"),
("Corneal arcus", "Lipid ring — hyperlipidaemia in <45 years; normal in elderly"),
("Xanthelasmata", "Yellow plaques at inner canthi — hyperlipidaemia"),
("Proptosis/exophthalmos", "Hyperthyroidism (Graves'), retro-orbital tumour"),
("Ptosis", "CN III palsy (with dilated pupil), Horner's (with miosis), myasthenia gravis (fatigable)"),
("Kayser-Fleischer rings", "Copper deposits in Descemet's membrane — Wilson's disease"),
("Pupils", "PERLA (pupils equal, round, reactive to light and accommodation). Anisocoria, fixed dilated, pinpoint"),
("Fundoscopy", "Papilloedema (raised ICP), hypertensive retinopathy (AV nipping, haemorrhages), diabetic retinopathy"),
]
story.append(two_col_table(eye_data))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("Face & Mouth", h2))
face_data = [
("Moon face", "Cushing's syndrome — round plethoric face, acne, hirsutism"),
("Malar flush", "Mitral stenosis — bilateral reddish-cyanotic cheeks"),
("Butterfly rash", "SLE — erythematous rash across cheeks and nose bridge, sparing nasolabial folds"),
("Acromegalic facies", "Protruding jaw, large nose, coarse features, widely spaced teeth — GH excess"),
("Myxoedematous facies","Periorbital puffiness, thick dry skin, hoarse voice, sparse lateral eyebrows — hypothyroidism"),
("Central cyanosis", "Bluish discolouration of lips and tongue — cardiorespiratory failure, Hb <5 g/dL of deoxygenated blood"),
("Angular cheilosis", "Iron deficiency, B₂ deficiency, ill-fitting dentures"),
("Mouth/teeth", "Dental caries/infection — source of bacteraemia; gum disease; oral candidiasis (immunosuppression)"),
]
story.append(two_col_table(face_data))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("Neck", h2))
neck_data = [
("JVP", "Jugular venous pressure — internal jugular at 45°. Normal <3 cm above sternal angle. Elevated in CCF, SVCO, pericardial disease, TR"),
("Tracheal position", "Central vs. deviated — trachea deviates away from tension pneumothorax, towards collapse/fibrosis"),
("Thyroid", "Size, consistency, nodularity, tenderness, bruit, lymphadenopathy, dysphagia, tracheal compression"),
("Carotid pulse", "Rate, character, bruits (→ carotid artery disease)"),
("Cervical LN", "Anterior/posterior triangle; supraclavicular (Virchow's node — left = GI malignancy, right = lung/mediastinal)"),
]
story.append(two_col_table(neck_data))
story.append(Spacer(1, 0.5*cm))
# ═══ SECTION 8: CHEST & CARDIOVASCULAR ═══════════════════════════════════════
story.append(section_banner("8. CHEST & CARDIOVASCULAR EXAMINATION OVERVIEW"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("Stepwise Cardiovascular Examination (Fuster & Hurst's The Heart)", h2))
cardio_data = [
("Sitting — Step 1", "General inspection including dental examination (source of endocarditis)"),
("Sitting — Step 2", "Shake hands → palpate radial pulse; inspect nail beds (clubbing, cyanosis, splinters)"),
("Sitting — Step 3", "Manual blood pressure both arms (>10 mmHg difference is significant)"),
("Sitting — Step 4", "Inspect chest and lower extremities — skin, scars, deformity"),
("Sitting — Step 5", "Palpation + auscultation of carotids — upstroke character, bruits"),
("Sitting — Step 6", "Palpation of chest — PMI, heaves, thrills"),
("Sitting — Step 7", "Lung examination — percussion + auscultation (crackles in CCF/pneumonia, wheeze in COPD/asthma)"),
("Sitting — Step 8", "Auscultation of precordium with diaphragm: upper sternal border → right upper sternal → down to apex"),
("Sitting→Supine", "Estimate central venous pressure via JVP; may need to lower head of bed"),
("Supine — Step 10", "Inspect precordium — apex beat position, visible heave"),
("Supine — Step 11", "Palpate apical impulse + right ventricular heave"),
("Supine — Step 12", "Auscultate with diaphragm: apex → sternal border → left upper border → right upper sternal"),
("Left lateral decubitus","Palpate and auscultate apex with bell — mitral stenosis rumble best heard here"),
("Remaining exam", "Liver size (hepatomegaly in CCF), ascites, ankle/sacral oedema, vascular exam of legs"),
]
story.append(two_col_table(cardio_data, header_row=["Position / Step", "Examination Element"]))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("Respiratory Examination Highlights", h2))
resp_data = [
("Inspection", "Respiratory rate, pattern, depth; use of accessory muscles; chest shape (barrel = hyperinflation), asymmetry, scars; tracheal position; pursed-lip breathing"),
("Palpation", "Chest expansion (normal = symmetric, ≥5 cm); tactile vocal fremitus (increased = consolidation; decreased = effusion/pneumothorax)"),
("Percussion", "Resonant (normal), dull (consolidation, effusion, collapse), hyper-resonant (pneumothorax, emphysema)"),
("Auscultation", "Breath sounds: vesicular (normal), bronchial (consolidation, above effusion). Added sounds: crackles (fine=fibrosis/LVF, coarse=secretions), wheeze (airway narrowing), pleural rub"),
]
story.append(two_col_table(resp_data))
story.append(Spacer(1, 0.5*cm))
# ═══ SECTION 9: ABDOMINAL EXAMINATION ════════════════════════════════════════
story.append(section_banner("9. ABDOMINAL EXAMINATION OVERVIEW"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
"The patient should be lying flat with hips and knees extended (pillow if needed) with the "
"abdomen adequately exposed from xiphisternum to inguinal ligaments. For palpation, flex "
"hips and knees to relax abdominal muscles. (Bailey & Love's Surgery, 28th Ed.)",
body
))
story.append(Spacer(1, 0.2*cm))
abd_data = [
("Inspection",
"Weight loss, dehydration, pedal oedema, anaemia, jaundice, abnormal pigmentation. "
"Scars, distension, visible peristalsis, dilated veins (caput medusae in portal HTN), "
"pulsatile mass, visible hernias. "
"Grey Turner's sign = flank bruising (retroperitoneal haemorrhage — pancreatitis, AAA). "
"Cullen's sign = periumbilical bruising (pancreatitis, ruptured ectopic, liver trauma)."),
("Auscultation",
"Before palpation. Normal bowel sounds q5–15 seconds. "
"Absent = paralytic ileus, peritonitis. "
"Tinkling/high-pitched = mechanical obstruction. "
"Arterial bruits = renal artery stenosis (renal bruits), AAA."),
("Palpation — Light",
"Superficial palpation with warm hands, watching the face. "
"Tenderness, guarding (voluntary/involuntary), rebound tenderness (peritonism). "
"Start away from the area of pain."),
("Palpation — Deep",
"Organomegaly: liver (measure in cm below costal margin), spleen (Traube's space, left lateral decubitus), kidneys (bimanual ballottement). "
"Identify masses: location, size, shape, consistency, surface, mobility, pulsatility, transillumination."),
("Percussion",
"Liver span (6–12 cm). "
"Splenomegaly (dull in Traube's space). "
"Shifting dullness + fluid thrill = ascites (≥1.5L for shifting dullness). "
"Suprapubic dullness = bladder distension."),
("Hernial orifices",
"Inguinal (medial = direct, lateral = indirect), femoral (below and lateral to pubic tubercle), umbilical, incisional scars. "
"Ask patient to cough; check for reducibility, auscultate if suspected bowel."),
("PR examination",
"Rectal mass, haemorrhoids, prostate size/consistency, cervix, peritoneal deposits ('shelf'). "
"Observe stool on glove: blood, mucus, melaena."),
]
story.append(two_col_table(abd_data, header_row=["Technique", "Key Findings"]))
story.append(Spacer(1, 0.5*cm))
# ═══ SECTION 10: NEUROLOGICAL GENERAL EXAMINATION ═══════════════════════════
story.append(section_banner("10. NEUROLOGICAL GENERAL EXAMINATION"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
"The neurological examination proceeds systematically. Localization is the cornerstone — "
"identifying where in the nervous system the lesion is, before considering what it is. "
"(Neuroanatomy Through Clinical Cases, 3rd Ed.)",
body
))
story.append(Spacer(1, 0.2*cm))
neuro_data = [
("Mental State", "Consciousness (GCS/AVPU), orientation (time, place, person), memory (short/long term), language, affect, higher functions — MMSE/MoCA if indicated"),
("Cranial Nerves I–XII","CN I: smell. CN II: acuity, fields, fundi, RAPD. CN III/IV/VI: eye movements, pupils. CN V: facial sensation + jaw. CN VII: facial muscles. CN VIII: hearing, Rinne/Weber. CN IX/X: palate, gag. CN XI: trapezius/SCM. CN XII: tongue (wasting, fasciculations, deviation)"),
("Motor System", "Tone (normal/spastic/rigid/flaccid), power (MRC 0–5 scale), bulk (wasting, hypertrophy), involuntary movements (tremor, fasciculations, chorea, athetosis)"),
("Reflexes", "DTRs: biceps C5, triceps C7, supinator C6, knee L3-4, ankle S1. Plantar response (upgoing=UMN). Reinforcement (Jendrassik). Clonus. Primitive reflexes (frontal lobe)"),
("Sensation", "Light touch, pinprick, temperature, vibration (128 Hz tuning fork), proprioception (joint position sense), two-point discrimination, stereognosis, graphaesthesia"),
("Coordination", "Finger-nose test (dysmetria, intention tremor), heel-shin, rapid alternating movements (dysdiadochokinesis), Romberg's test"),
("Gait", "Observe: stride, base, arm swing, turning. Hemiplegic, spastic (scissors), steppage (foot drop), ataxic (broad-based), parkinsonian (shuffling, festinant, reduced arm swing), apraxic (dementia)"),
("Signs of meningism", "Neck stiffness, Kernig's sign (knee extension from 90° flexion), Brudzinski's sign — bacterial meningitis, SAH, meningeal carcinomatosis"),
]
story.append(two_col_table(neuro_data, header_row=["Component", "Assessment"]))
story.append(Spacer(1, 0.5*cm))
# ═══ SECTION 11: LYMPH NODES, SKIN, MSK ══════════════════════════════════════
story.append(section_banner("11. LYMPH NODES, SKIN & MUSCULOSKELETAL ASSESSMENT"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("Lymph Node Examination", h2))
ln_data = [
("Cervical groups", "Submental, submandibular, anterior/posterior cervical chains, preauricular, postauricular, occipital, supraclavicular"),
("Axillary groups", "Anterior (pectoral), posterior (subscapular), lateral, medial (brachial), apical — examine with arm supported"),
("Inguinal groups", "Horizontal (superficial inguinal), vertical"),
("Other groups", "Epitrochlear (forearm/hand infections, secondary syphilis), popliteal (rare)"),
("Palpation features","Size, shape, consistency (hard=malignant; rubbery=lymphoma; soft=reactive), surface, tenderness, fixation, matting, overlying skin"),
("Virchow's node", "Left supraclavicular lymphadenopathy — Troisier's sign — GI malignancy (especially gastric). Right supraclavicular — lung, mediastinum"),
("Causes of generalised LN", "Infections (EBV, HIV, TB, brucella), haematological malignancy (CLL, lymphoma), SLE, sarcoidosis, drugs"),
]
story.append(two_col_table(ln_data, header_row=["Region/Feature", "Details"]))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("Key Dermatological Signs in General Examination", h2))
derm_data = [
("Jaundice", "Skin + sclera yellow → pre-hepatic (haemolysis), hepatic (liver disease), post-hepatic (biliary obstruction)"),
("Pallor", "Anaemia, shock, vasoconstriction — assess conjunctivae, palms, mucous membranes"),
("Central cyanosis", "Lips, tongue, buccal mucosa — right-to-left shunts, severe respiratory failure"),
("Peripheral cyanosis", "Fingers, toes, nose, ears — vasoconstriction, Raynaud's, peripheral vascular disease"),
("Spider naevi", ">5 in distribution of SVC (face, neck, upper arms, trunk) — chronic liver disease; also seen in pregnancy"),
("Purpura/petechiae", "Non-blanching — thrombocytopaenia, meningococcaemia, vasculitis, DIC, Henoch-Schönlein purpura"),
("Oedema", "Pedal/ankle oedema: CCF, hypoalbuminaemia (nephrotic/hepatic), venous insufficiency, lymphoedema, drug-induced. Sacral oedema in bed-bound patients"),
("Rashes", "Distribution, character (macular, papular, vesicular, pustular, plaques), blanching — document carefully"),
("Hyperpigmentation", "Addison's disease (buccal mucosa, pressure areas, scars), haemochromatosis (bronzing), primary biliary cholangitis"),
("Striae", "Silver (old) or purple/red (active — Cushing's/rapid weight change)"),
]
story.append(two_col_table(derm_data))
story.append(Spacer(1, 0.5*cm))
# ═══ SECTION 12: ASSESSMENT, DIFFERENTIAL & PLAN ═════════════════════════════
story.append(section_banner("12. ASSESSMENT, DIFFERENTIAL DIAGNOSIS & PLAN"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
"After completing the history and examination, the clinician synthesises all findings into "
"a structured Assessment and Plan. This is the clinical reasoning step — moving from data "
"collection to diagnosis and management.",
body
))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("Structure of Assessment", h2))
story.append(Paragraph(
"<b>Step 1 — Summary formulation:</b> A 1–2 sentence summary encapsulating the patient's key clinical "
"features and most likely diagnosis.",
body
))
story.append(Paragraph(
"<i>Example: \"This is a 53-year-old man with cardiac risk factors of hypertension and family "
"history of coronary artery disease who presents with substernal chest pain and EKG changes "
"suggestive of anterolateral wall myocardial infarction.\"</i>",
note_style
))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
"<b>Step 2 — Differential diagnosis:</b> List alternative diagnoses in order of likelihood. "
"Use the mnemonic VINDICATE or a systems-based approach.",
body
))
story.append(Paragraph(
"<b>Step 3 — Problem list:</b> Break down all active problems.",
body
))
story.append(Paragraph(
"<b>Step 4 — Management plan:</b> For each problem, outline investigations, treatments, "
"monitoring, referrals, and patient education.",
body
))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("Neurological Differential Diagnosis — Arrowhead Approach", h2))
story.append(Paragraph(
"In neurology, the assessment is first anatomical (localization), then aetiological. "
"Use the mnemonic <b>VITAMIN C(D)</b> for the neurological differential:",
body
))
vitamin_data = [
("V — Vascular", "Stroke, TIA, haemorrhage, vasculitis, venous thrombosis"),
("I — Infectious", "Meningitis, encephalitis, abscess, HIV, PML, neurosyphilis"),
("T — Traumatic/Toxic", "Head injury, spinal cord injury, metabolic encephalopathy, drugs/alcohol"),
("A — Autoimmune", "MS, NMO, anti-NMDAR encephalitis, Guillain-Barré, myasthenia gravis, vasculitis"),
("M — Metabolic", "Hepatic/renal encephalopathy, hypoglycaemia, electrolyte disorders, thiamine deficiency"),
("I — Idiopathic", "Epilepsy, Parkinson's disease, essential tremor"),
("N — Neoplastic", "Primary brain tumour, metastases, paraneoplastic syndromes, meningeal carcinomatosis"),
("C — Congenital", "Malformations, neurocutaneous syndromes (NF1/2, TSC, Sturge-Weber)"),
("D — Degenerative", "Alzheimer's, frontotemporal dementia, motor neurone disease, Huntington's, MSA"),
]
story.append(two_col_table(vitamin_data, header_row=["Category", "Examples"]))
story.append(Spacer(1, 0.5*cm))
# ═══ SECTION 13: SPECIAL POPULATIONS & CLINICAL PEARLS ═══════════════════════
story.append(section_banner("13. SPECIAL POPULATIONS & KEY CLINICAL PEARLS"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("Special Populations", h2))
pop_data = [
("Paediatric", "Adjust normal ranges for age (HR, BP, RR). Use PEWS score for deterioration. Assess growth parameters, developmental milestones, immunisation status, safeguarding concerns"),
("Geriatric", "Polypharmacy (>5 medications — increased interaction risk). Atypical presentations of common diseases. Falls, cognitive decline, functional status (ADLs/IADLs), nutritional screening, pressure sores, urinary incontinence"),
("Pregnant", "Physiological changes: HR+10–15 bpm, BP drops in 2nd trimester, RR may increase. Avoid supine position in late pregnancy (aortocaval compression). Fundal height, foetal heart sounds, presentation, engagement"),
("Immunocompromised","Atypical/absent fever, minimal examination signs despite severe infection. Low threshold for investigation. Screen for opportunistic infections (PCP, CMV, fungal)"),
("Renal/hepatic impairment", "Drug dosing adjustments mandatory. Monitor for encephalopathy (hepatic), uraemia (renal). Fluid balance critically important"),
("Psychiatric/alcohol/drug","Non-judgmental approach. Cognitive assessment. Withdrawal risk scoring (CIWA for alcohol). Nutritional status, infectious disease screening (HIV, Hep B/C), safeguarding"),
]
story.append(two_col_table(pop_data, header_row=["Population", "Special Considerations"]))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("Key Clinical Pearls", h2))
pearls = [
"The history gives the diagnosis in 70–80% of cases. Time invested in history is never wasted.",
"Vital signs are the most sensitive early indicators of deterioration — respiratory rate especially. Always count the RR for a full 60 seconds.",
"Never examine through clothing. Proper exposure is non-negotiable for a thorough examination.",
"Always examine the other limb, the contralateral lymph nodes, and adjacent structures before diagnosing a localised lesion.",
"In any patient with a swelling suspected to be malignant, metastatic sites must be systematically assessed — chest (cough, haemoptysis), liver, abdomen (peritoneal), bones (spine, pelvis, skull). (S. Das, Manual on Clinical Surgery)",
"Lymph node enlargement always requires examination of all lymph node groups to identify the cause.",
"Grey Turner's sign and Cullen's sign indicate retroperitoneal/intra-abdominal haemorrhage — early recognition can be life-saving.",
"A 'positive shaking hands' examination gives frailty assessment, tone, temperature, pulse, and bilateral BP asymmetry simultaneously.",
"Virchow's node (left supraclavicular lymphadenopathy) is a red flag for intra-abdominal or thoracic malignancy — never ignore it.",
"Document all findings clearly: positive AND pertinent negative findings both contribute to the clinical picture and medicolegal record.",
"In elderly patients, always assess functional status alongside clinical examination — a patient's ability to perform ADLs often predicts outcome better than lab values.",
"Pain is sometimes considered the 'sixth vital sign' — always assess and document it."
]
for pearl in pearls:
story.append(Paragraph(f"★ {pearl}", bullet_style))
story.append(Spacer(1, 0.1*cm))
story.append(Spacer(1, 0.4*cm))
story.append(hr())
# ─── References ───────────────────────────────────────────────────────────────
story.append(Paragraph("References & Sources", h2))
refs = [
"Goldman L, Cooney KA (eds). Goldman-Cecil Medicine International Edition, 2-Volume Set. 26th ed. Elsevier, 2023.",
"Fuster V, Harrington RA, Narula J, Eapen ZJ (eds). Fuster and Hurst's The Heart. 15th ed. McGraw-Hill, 2022.",
"Williams NS, O'Connell PR, McCaskie AW (eds). Bailey and Love's Short Practice of Surgery. 28th ed. CRC Press/Taylor & Francis, 2023.",
"Das S. A Manual on Clinical Surgery. 13th ed. Dr S Das, 2020.",
"Blumenfeld H. Neuroanatomy Through Clinical Cases. 3rd ed. Sinauer/Oxford University Press, 2021.",
"Bradley WG, Daroff RB et al. Bradley and Daroff's Neurology in Clinical Practice. 8th ed. Elsevier, 2022.",
]
for ref in refs:
story.append(Paragraph(f"• {ref}", note_style))
story.append(Spacer(1, 0.5*cm))
# ─── Footer note ──────────────────────────────────────────────────────────────
footer_box_data = [[Paragraph(
"<b>Disclaimer:</b> This document is compiled from authoritative medical textbooks for "
"educational purposes only. It does not constitute clinical advice. Clinical decisions must "
"be made by qualified healthcare professionals taking into account the individual patient's "
"full clinical context.",
ParagraphStyle("FooterNote", fontSize=8, leading=12, textColor=colors.HexColor("#555555"),
fontName="Helvetica-Oblique", alignment=TA_LEFT)
)]]
footer_tbl = Table(footer_box_data, colWidths=[doc.width])
footer_tbl.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, -1), LIGHT_GRAY),
("BOX", (0, 0), (-1, -1), 0.8, MED_GRAY),
("TOPPADDING", (0, 0), (-1, -1), 8),
("BOTTOMPADDING", (0, 0), (-1, -1), 8),
("LEFTPADDING", (0, 0), (-1, -1), 10),
("RIGHTPADDING", (0, 0), (-1, -1), 10),
]))
story.append(footer_tbl)
# ─── Build ─────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF successfully created: {OUTPUT_PATH}")
cd /tmp/workspace/patient-examination && python generate_pdf.py
ls -lh /tmp/workspace/patient-examination/Approach_to_Patient_General_Examination.pdf
Approach to Patient General Examination
PDF Document · PDF
Make a visual infographic poster of the IPPA examination techniques
A detailed medical education infographic poster titled "IPPA Examination Techniques" showing all four physical examination methods. The poster is divided into four bold color-coded sections arranged in a 2x2 grid layout: TOP LEFT - INSPECTION (deep blue background): Icon of an eye. Key points listed: General appearance, skin color, body shape, posture, movements, swellings, scars, rashes, deformities, breathing pattern, visible pulsations. Sub-note: "Always inspect before touching." TOP RIGHT - PALPATION (teal/green background): Icon of a hand touching. Key points: Light palpation (superficial tenderness, guarding), Deep palpation (organomegaly, masses), Texture, temperature, consistency, tenderness, fluctuation, pulsatility, crepitus, fremitus. Sub-note: "Warm hands. Watch the patient's face." BOTTOM LEFT - PERCUSSION (orange/amber background): Icon of fingers tapping. Percussion notes listed in a small legend: Resonant (normal lung), Dull (consolidation/effusion/mass), Hyper-resonant (pneumothorax/emphysema), Stony dull (pleural effusion), Tympanic (gas-filled bowel). Technique tip: Middle finger of non-dominant hand flat on skin, tap with dominant middle finger. Sub-note: "Elicits sound and vibration through tissues." BOTTOM RIGHT - AUSCULTATION (purple/violet background): Icon of a stethoscope. Key points: Use diaphragm for high-pitched sounds (breath sounds, normal heart sounds, bowel sounds), Use bell for low-pitched sounds (mitral stenosis murmur, S3/S4 gallop). Added sounds: Crackles (fine=fibrosis, coarse=secretions), Wheeze (airway narrowing), Pleural rub, Bruit (turbulent flow). Sub-note: "Silence the room. Listen systematically." CENTER of poster: Bold title "IPPA — The Four Pillars of Physical Examination" with a circular diagram showing the order I → P → P → A with arrows (note: abdomen uses I → A → P → P order). Bottom strip: "Exception: In abdominal examination, AUSCULTATION precedes palpation and percussion to avoid stimulating bowel sounds artificially." Clean professional medical infographic style, white text on colored backgrounds, clear icons, well-spaced readable typography, suitable for clinical teaching.
