Make me flow charts in pdf
cd /home/daytona/workspace && python3 -c " import pdfplumber with pdfplumber.open('attachments/6c15b3c4-fc9b-416c-89e8-22ebec4be073/Circulatory system.pdf') as pdf: for i, page in enumerate(pdf.pages): print(f'=== PAGE {i+1} ===') text = page.extract_text() print(text) print() "
mkdir -p /home/daytona/workspace/circulatory-flowcharts && python3 -c "import matplotlib; import reportlab; print('libs ok')"
~/circulatory-flowcharts/make_flowcharts.py
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyArrowPatch, FancyBboxPatch
from matplotlib.backends.backend_pdf import PdfPages
import numpy as np
OUTPUT = "/home/daytona/workspace/circulatory-flowcharts/Circulatory_System_Flowcharts.pdf"
# ── colour palette ──────────────────────────────────────────────────────────
C_TITLE = "#1A237E" # deep navy
C_BOX_BLU = "#E3F2FD" # light blue fill
C_BOX_RED = "#FFEBEE" # light red fill
C_BOX_GRN = "#E8F5E9" # light green fill
C_BOX_ORG = "#FFF3E0" # light orange fill
C_BOX_PUR = "#F3E5F5" # light purple fill
C_BOX_GRY = "#F5F5F5" # light grey fill
C_ARR = "#37474F" # arrow / border colour
C_TXT = "#1A1A2E" # body text
def rounded_box(ax, x, y, w, h, text, facecolor, edgecolor=C_ARR,
fontsize=9, bold=False, radius=0.04):
box = FancyBboxPatch((x - w/2, y - h/2), w, h,
boxstyle=f"round,pad=0.01,rounding_size={radius}",
facecolor=facecolor, edgecolor=edgecolor, linewidth=1.2,
zorder=3)
ax.add_patch(box)
ax.text(x, y, text, ha='center', va='center', fontsize=fontsize,
fontweight='bold' if bold else 'normal', color=C_TXT,
zorder=4, wrap=True,
multialignment='center')
def diamond(ax, x, y, w, h, text, facecolor=C_BOX_ORG, fontsize=8.5):
dx, dy = w/2, h/2
xs = [x, x+dx, x, x-dx, x]
ys = [y+dy, y, y-dy, y, y+dy]
ax.fill(xs, ys, facecolor=facecolor, edgecolor=C_ARR, linewidth=1.2, zorder=3)
ax.text(x, y, text, ha='center', va='center', fontsize=fontsize,
color=C_TXT, zorder=4, multialignment='center')
def arrow(ax, x1, y1, x2, y2, label='', color=C_ARR):
ax.annotate('', xy=(x2, y2), xytext=(x1, y1),
arrowprops=dict(arrowstyle='->', color=color, lw=1.5),
zorder=2)
if label:
mx, my = (x1+x2)/2, (y1+y2)/2
ax.text(mx+0.02, my, label, fontsize=7.5, color='#555555', zorder=5)
def page_title(ax, title, subtitle=''):
ax.text(0.5, 0.97, title, transform=ax.transAxes,
ha='center', va='top', fontsize=14, fontweight='bold', color=C_TITLE)
if subtitle:
ax.text(0.5, 0.93, subtitle, transform=ax.transAxes,
ha='center', va='top', fontsize=9, color='#555555')
def clean_ax(ax, xlim=(0,1), ylim=(0,1)):
ax.set_xlim(*xlim)
ax.set_ylim(*ylim)
ax.axis('off')
# ═══════════════════════════════════════════════════════════════════════════
# PAGE 1 – Pulmonary & Systemic Circulation
# ═══════════════════════════════════════════════════════════════════════════
def page_pulmonary_systemic(pdf):
fig, ax = plt.subplots(figsize=(8.5, 11))
clean_ax(ax, (0, 10), (0, 14))
page_title(ax, "Flowchart 1: The Two Main Circulatory Circuits",
"Pulmonary Circulation | Systemic Circulation | Portal Circulation")
BW, BH = 3.6, 0.55 # box width / height
# ── LEFT column: Pulmonary ──────────────────────────────────────────
lx = 2.6
nodes_l = [
(lx, 12.5, "Upper & Lower Body Tissues\n(deoxygenated blood)", C_BOX_RED),
(lx, 11.5, "Superior & Inferior Vena Cava", C_BOX_BLU),
(lx, 10.5, "Right Atrium", C_BOX_BLU),
(lx, 9.5, "Right Ventricle", C_BOX_BLU),
(lx, 8.5, "Pulmonary Arteries", C_BOX_BLU),
(lx, 7.5, "Lungs\n(O₂ absorbed / CO₂ released)", C_BOX_GRN),
]
for (x, y, t, c) in nodes_l:
rounded_box(ax, x, y, BW, BH, t, c)
for i in range(len(nodes_l)-1):
arrow(ax, nodes_l[i][0], nodes_l[i][1]-BH/2,
nodes_l[i+1][0], nodes_l[i+1][1]+BH/2)
ax.text(lx, 13.3, "PULMONARY CIRCULATION", ha='center', fontsize=10,
fontweight='bold', color='#1565C0')
# ── RIGHT column: Systemic ──────────────────────────────────────────
rx = 7.4
nodes_r = [
(rx, 7.5, "Pulmonary Veins\n(oxygenated blood)", C_BOX_GRN),
(rx, 8.5, "Left Atrium", C_BOX_RED),
(rx, 9.5, "Left Ventricle", C_BOX_RED),
(rx, 10.5, "Aorta", C_BOX_RED),
(rx, 11.5, "Body Tissues / Organs", C_BOX_ORG),
(rx, 12.5, "Systemic Capillaries\n(O₂ delivered / CO₂ collected)", C_BOX_ORG),
]
for (x, y, t, c) in nodes_r:
rounded_box(ax, x, y, BW, BH, t, c)
for i in range(len(nodes_r)-1):
arrow(ax, nodes_r[i][0], nodes_r[i][1]+BH/2,
nodes_r[i+1][0], nodes_r[i+1][1]-BH/2)
ax.text(rx, 13.3, "SYSTEMIC CIRCULATION", ha='center', fontsize=10,
fontweight='bold', color='#B71C1C')
# Heart box in the middle
rounded_box(ax, 5.0, 6.4, 2.2, 0.65, "HEART\n(Central Pump)",
"#FFF9C4", edgecolor="#F9A825", fontsize=9, bold=True)
# Arrows: heart ↔ columns
arrow(ax, 3.8, 7.5, 4.0, 6.6) # lungs→heart left
arrow(ax, 4.0, 6.2, 3.8, 7.2) # heart→pulm art (right ventricle side)
arrow(ax, 6.0, 6.6, 6.2, 7.5) # heart→pulm veins
arrow(ax, 6.2, 7.2, 6.0, 6.2)
# ── Portal circulation inset ────────────────────────────────────────
px = 5.0
rounded_box(ax, px, 4.8, 7.5, 0.5,
"PORTAL CIRCULATION – A special part of the systemic circuit",
C_BOX_PUR, bold=True, fontsize=9)
portal_nodes = [
(px, 4.0, "Digestive Organs\n(stomach, bowel, pancreas, spleen)", C_BOX_GRN),
(px, 3.1, "Portal Vein", C_BOX_BLU),
(px, 2.2, "Liver Capillary Bed\n(filtering & metabolic processing)", C_BOX_ORG),
(px, 1.3, "Hepatic Veins → Inferior Vena Cava", C_BOX_BLU),
]
PW = 4.2
for (x, y, t, c) in portal_nodes:
rounded_box(ax, x, y, PW, 0.62, t, c, fontsize=8.5)
for i in range(len(portal_nodes)-1):
arrow(ax, portal_nodes[i][0], portal_nodes[i][1]-0.31,
portal_nodes[i+1][0], portal_nodes[i+1][1]+0.31)
arrow(ax, px, 4.8-0.25, px, 4.0+0.31)
ax.text(0.12, 0.018, "Source: THIEME Atlas of Anatomy – General Anatomy, Sections 6.1–6.3",
transform=ax.transAxes, fontsize=7, color='#888888')
plt.tight_layout()
pdf.savefig(fig, bbox_inches='tight')
plt.close(fig)
# ═══════════════════════════════════════════════════════════════════════════
# PAGE 2 – Functional Pressure Systems
# ═══════════════════════════════════════════════════════════════════════════
def page_pressure_systems(pdf):
fig, ax = plt.subplots(figsize=(8.5, 11))
clean_ax(ax, (0, 10), (0, 14))
page_title(ax, "Flowchart 2: Functional Pressure Systems",
"High-Pressure System → Capillary Exchange → Low-Pressure System")
BW, BH = 3.8, 0.60
# High pressure column (left)
lx = 2.5
ax.text(lx, 13.3, "HIGH-PRESSURE SYSTEM (~100 mmHg)", ha='center',
fontsize=10, fontweight='bold', color='#B71C1C')
hp = [
(lx, 12.6, "Left Ventricle\n(Pump origin, systole ~120 mmHg)", C_BOX_RED),
(lx, 11.5, "Elastic Arteries (e.g. Aorta)\n• Expand during systole\n• Elastic recoil during diastole\n → converts pulsatile to continuous flow", C_BOX_RED),
(lx, 10.1, "Muscular Arteries\n• Active vasodilation / vasoconstriction\n• Control vascular resistance\n• Regulate local blood flow", C_BOX_RED),
(lx, 8.9, "Arterioles\n(Pressure drops significantly here)", C_BOX_ORG),
]
heights = [0.60, 1.2, 1.0, 0.60]
for i,(x,y,t,c) in enumerate(hp):
h = heights[i]
box = FancyBboxPatch((x-BW/2, y-h/2), BW, h,
boxstyle="round,pad=0.01,rounding_size=0.04",
facecolor=c, edgecolor=C_ARR, linewidth=1.2, zorder=3)
ax.add_patch(box)
ax.text(x, y, t, ha='center', va='center', fontsize=8.2,
color=C_TXT, zorder=4, multialignment='center')
# arrows
y_bottoms = [y-h/2 for (x,y,t,c),h in zip(hp, heights)]
y_tops = [y+h/2 for (x,y,t,c),h in zip(hp, heights)]
for i in range(len(hp)-1):
arrow(ax, hp[i][0], y_bottoms[i], hp[i+1][0], y_tops[i+1])
# Capillary exchange (centre)
cx = 5.0
ax.text(cx, 7.9, "CAPILLARY EXCHANGE ZONE", ha='center', fontsize=10,
fontweight='bold', color='#1B5E20')
cap_nodes = [
(cx, 7.3, "Precapillary Sphincters\n(regulate entry; only 25–35% open at rest)", C_BOX_GRN, 0.65),
(cx, 6.3, "Capillary Bed (5–15 µm)\n• 800× cross-section of aorta\n• Flow drops: 50 cm/s → 0.05 cm/s\n• ~1 second for metabolic exchange", C_BOX_GRN, 1.1),
(cx, 4.85, "Starling Forces\nArterial end: HP 35 > COP 25 → fluid OUT\nVenous end: HP 15 < COP 25 → fluid IN\nExcess → Lymphatic capillaries", C_BOX_GRN, 1.0),
]
for (x,y,t,c,h) in cap_nodes:
box = FancyBboxPatch((x-2.2, y-h/2), 4.4, h,
boxstyle="round,pad=0.01,rounding_size=0.04",
facecolor=c, edgecolor=C_ARR, linewidth=1.2, zorder=3)
ax.add_patch(box)
ax.text(x, y, t, ha='center', va='center', fontsize=8.2,
color=C_TXT, zorder=4, multialignment='center')
for i in range(len(cap_nodes)-1):
arrow(ax, cap_nodes[i][0], cap_nodes[i][1]-cap_nodes[i][4]/2,
cap_nodes[i+1][0], cap_nodes[i+1][1]+cap_nodes[i+1][4]/2)
# Low pressure column (right)
rx = 7.5
ax.text(rx, 13.3, "LOW-PRESSURE SYSTEM (< 20 mmHg)", ha='center',
fontsize=10, fontweight='bold', color='#1565C0')
lp = [
(rx, 12.6, "Venules\n(postcapillary)", C_BOX_BLU),
(rx, 11.6, "Veins\n(capacitance vessels)\n• Hold ~80% of total blood volume\n• Serve as blood reservoir", C_BOX_BLU),
(rx, 10.2, "Pulmonary Vessels\n(also low pressure < 20 mmHg)\n• Lung capillary bed", C_BOX_BLU),
(rx, 9.1, "Right Atrium / Right Ventricle", C_BOX_BLU),
]
lp_h = [0.6, 1.0, 0.9, 0.6]
for i,(x,y,t,c) in enumerate(lp):
h = lp_h[i]
box = FancyBboxPatch((x-BW/2, y-h/2), BW, h,
boxstyle="round,pad=0.01,rounding_size=0.04",
facecolor=c, edgecolor=C_ARR, linewidth=1.2, zorder=3)
ax.add_patch(box)
ax.text(x, y, t, ha='center', va='center', fontsize=8.2,
color=C_TXT, zorder=4, multialignment='center')
lp_bottoms = [y-h/2 for (x,y,t,c),h in zip(lp, lp_h)]
lp_tops = [y+h/2 for (x,y,t,c),h in zip(lp, lp_h)]
for i in range(len(lp)-1):
arrow(ax, lp[i][0], lp_bottoms[i], lp[i+1][0], lp_tops[i+1])
# Connecting arrows across columns to capillary box
arrow(ax, hp[-1][0]+BW/2-0.2, hp[-1][1], cx-2.2, cap_nodes[0][1], color='#E65100')
arrow(ax, cx+2.2, cap_nodes[0][1], lp[0][0]-BW/2+0.2, lp[0][1], color='#0D47A1')
# Lymphatic inset
rounded_box(ax, 5.0, 2.8, 5.5, 0.55,
"Lymphatic System: collects excess interstitial fluid → lymph nodes → returns to venous blood",
C_BOX_PUR, fontsize=8.5)
arrow(ax, cx, cap_nodes[-1][1]-cap_nodes[-1][4]/2, 5.0, 2.8+0.28, color='#6A1B9A')
ax.text(0.12, 0.018, "Source: THIEME Atlas of Anatomy – General Anatomy, Sections 6.1–6.3",
transform=ax.transAxes, fontsize=7, color='#888888')
plt.tight_layout()
pdf.savefig(fig, bbox_inches='tight')
plt.close(fig)
# ═══════════════════════════════════════════════════════════════════════════
# PAGE 3 – Structure of Blood Vessel Walls
# ═══════════════════════════════════════════════════════════════════════════
def page_vessel_structure(pdf):
fig, ax = plt.subplots(figsize=(8.5, 11))
clean_ax(ax, (0, 10), (0, 14))
page_title(ax, "Flowchart 3: Structure of Blood Vessel Walls",
"Three Fundamental Layers | Artery vs. Vein Differences")
# Three layers (stacked large boxes)
layers = [
(5.0, 11.8, "LAYER 1 – Tunica Intima (Innermost)",
"• Spindle-shaped endothelial cells aligned along vessel axis\n"
"• Resting on basement membrane + thin subendothelial connective tissue\n"
"• In muscular arteries: separated from media by internal elastic membrane\n"
"• Function: Exchange of gases, fluids & substances through vessel wall",
C_BOX_GRN),
(5.0, 9.5, "LAYER 2 – Tunica Media (Middle)",
"• Circular arrangement of smooth muscle cells\n"
"• Elastic and collagenous fibres + proteoglycans\n"
"• Muscular arteries may have external elastic membrane\n"
"• Function: Regulates blood flow via contraction / relaxation of smooth muscle",
C_BOX_ORG),
(5.0, 7.2, "LAYER 3 – Tunica Adventitia (Outermost)",
"• Longitudinally aligned connective tissue; veins may also have smooth muscle\n"
"• Contains autonomic nerves to vessel wall muscle\n"
"• Larger vessels: vasa vasorum (supply outer third of vessel wall)\n"
"• Function: Integrates blood vessel into surrounding tissue",
C_BOX_BLU),
]
for (x, y, title, detail, col) in layers:
h = 1.8
box = FancyBboxPatch((x-4.5, y-h/2), 9.0, h,
boxstyle="round,pad=0.02,rounding_size=0.06",
facecolor=col, edgecolor=C_ARR, linewidth=1.4, zorder=3)
ax.add_patch(box)
ax.text(x, y+0.55, title, ha='center', va='center', fontsize=9.5,
fontweight='bold', color=C_TITLE, zorder=4)
ax.text(x, y-0.15, detail, ha='center', va='center', fontsize=8.0,
color=C_TXT, zorder=4, multialignment='center')
arrow(ax, 5.0, 10.9, 5.0, 10.4)
arrow(ax, 5.0, 8.6, 5.0, 8.1)
# Artery vs Vein comparison boxes
ax.text(5.0, 5.7, "Artery vs. Vein – Key Differences",
ha='center', fontsize=10, fontweight='bold', color=C_TITLE)
art_detail = (
"ARTERIES\n"
"• Thick, densely packed smooth muscle in media\n"
"• Prominent internal elastic membrane\n"
"• Elastic type (aorta): expand & recoil\n"
"• Muscular type: active vasoconstriction /\n"
" vasodilation for flow regulation"
)
vein_detail = (
"VEINS\n"
"• More connective tissue (collagen & elastic fibres)\n"
"• Looser wall structure\n"
"• No prominent internal elastic membrane\n"
"• Capacitance vessels: hold ~80% blood volume\n"
"• May have smooth muscle in adventitia"
)
for x, text, col in [(2.8, art_detail, C_BOX_RED), (7.2, vein_detail, C_BOX_BLU)]:
box = FancyBboxPatch((x-2.4, 3.2), 4.8, 2.2,
boxstyle="round,pad=0.02,rounding_size=0.06",
facecolor=col, edgecolor=C_ARR, linewidth=1.2, zorder=3)
ax.add_patch(box)
ax.text(x, 4.3, text, ha='center', va='center', fontsize=8.0,
color=C_TXT, zorder=4, multialignment='center')
# VS label
ax.text(5.0, 4.3, "VS", ha='center', va='center', fontsize=14,
fontweight='bold', color='#757575')
# Capillary note at bottom
rounded_box(ax, 5.0, 2.3, 8.5, 0.70,
"CAPILLARIES – Simplest vessels\n"
"Only endothelial layer + basal lamina (no media or adventitia) | Diameter: 5–15 µm",
C_BOX_GRY, fontsize=8.5)
ax.text(0.12, 0.018, "Source: THIEME Atlas of Anatomy – General Anatomy, Section 6.2",
transform=ax.transAxes, fontsize=7, color='#888888')
plt.tight_layout()
pdf.savefig(fig, bbox_inches='tight')
plt.close(fig)
# ═══════════════════════════════════════════════════════════════════════════
# PAGE 4 – Microcirculation & Capillary Endothelium Types
# ═══════════════════════════════════════════════════════════════════════════
def page_microcirculation(pdf):
fig, ax = plt.subplots(figsize=(8.5, 11))
clean_ax(ax, (0, 10), (0, 14))
page_title(ax, "Flowchart 4: Terminal Vascular Bed & Microcirculation",
"Afferent Limb → Capillary Bed → Efferent Limb | Capillary Endothelium Types")
BW = 4.0
# Afferent → capillary → efferent
flow = [
(5.0, 12.8, "Arteriole\n(afferent arterial limb)", C_BOX_RED, 0.65),
(5.0, 12.0, "Metarteriole", C_BOX_RED, 0.55),
(5.0, 11.1, "Precapillary Sphincter\n(circular muscle; opens/closes capillary entry)\nResting: only 25–35% of capillaries open", C_BOX_ORG, 0.9),
]
for (x,y,t,c,h) in flow:
box = FancyBboxPatch((x-BW/2, y-h/2), BW, h,
boxstyle="round,pad=0.01,rounding_size=0.04",
facecolor=c, edgecolor=C_ARR, linewidth=1.2, zorder=3)
ax.add_patch(box)
ax.text(x, y, t, ha='center', va='center', fontsize=8.2,
color=C_TXT, zorder=4, multialignment='center')
arrow(ax, 5.0, 12.8-0.33, 5.0, 12.0+0.28)
arrow(ax, 5.0, 12.0-0.28, 5.0, 11.1+0.45)
# Capillary bed
cap_h = 1.3
box = FancyBboxPatch((5.0-BW/2, 9.5-cap_h/2), BW, cap_h,
boxstyle="round,pad=0.02,rounding_size=0.06",
facecolor=C_BOX_GRN, edgecolor="#2E7D32", linewidth=2, zorder=3)
ax.add_patch(box)
ax.text(5.0, 9.5, "CAPILLARY BED\nDiameter: 5–15 µm\nCross-section: 800× that of aorta\nBlood velocity: 50 cm/s (aorta) → 0.05 cm/s\nExchange time: ~1 second",
ha='center', va='center', fontsize=8.2, color=C_TXT, zorder=4, multialignment='center')
arrow(ax, 5.0, flow[-1][1]-flow[-1][4]/2, 5.0, 9.5+cap_h/2)
# AV shunt side branch
ax.annotate('', xy=(7.8, 9.5), xytext=(7.8, 11.4),
arrowprops=dict(arrowstyle='->', color='#E65100', lw=1.4,
connectionstyle='arc3,rad=0'))
ax.text(8.2, 10.45, "AV\nAnastomosis\n(shunt)", ha='center', va='center',
fontsize=7.5, color='#E65100',
bbox=dict(facecolor='#FFF3E0', edgecolor='#E65100', boxstyle='round'))
# Efferent
eff = [
(5.0, 8.5, "Postcapillary Venule\n(efferent venous limb)", C_BOX_BLU, 0.65),
(5.0, 7.6, "Venule → Vein", C_BOX_BLU, 0.55),
]
for (x,y,t,c,h) in eff:
box = FancyBboxPatch((x-BW/2, y-h/2), BW, h,
boxstyle="round,pad=0.01,rounding_size=0.04",
facecolor=c, edgecolor=C_ARR, linewidth=1.2, zorder=3)
ax.add_patch(box)
ax.text(x, y, t, ha='center', va='center', fontsize=8.2,
color=C_TXT, zorder=4, multialignment='center')
arrow(ax, 5.0, 9.5-cap_h/2, 5.0, eff[0][1]+eff[0][4]/2)
arrow(ax, 5.0, eff[0][1]-eff[0][4]/2, 5.0, eff[1][1]+eff[1][4]/2)
# Capillary endothelium types table
ax.text(5.0, 6.7, "Types of Capillary Endothelium", ha='center', fontsize=10,
fontweight='bold', color=C_TITLE)
types = [
("Type I", "Continuous, no fenestrations\nContinuous basal lamina", "Nervous system", C_BOX_GRY),
("Type II", "Continuous, with pinocytotic activity", "Cardiac & skeletal muscle", C_BOX_BLU),
("Type III", "Fenestrated by a diaphragm", "Gastrointestinal tract, kidneys", C_BOX_ORG),
("Type IV", "Intercellular gaps\nNo continuous basal lamina", "Liver (sinusoids)", C_BOX_RED),
]
col_xs = [1.4, 4.5, 8.0]
col_labels = ["Type", "Structure", "Location"]
header_y = 6.15
for lx, label in zip(col_xs, col_labels):
ax.text(lx, header_y, label, ha='center', va='center', fontsize=9,
fontweight='bold', color='white',
bbox=dict(facecolor=C_TITLE, boxstyle='round,pad=0.3'))
row_h = 0.75
for i, (typ, struct, loc, col) in enumerate(types):
y = header_y - (i+1)*row_h - 0.1
box = FancyBboxPatch((0.2, y-row_h/2+0.05), 9.6, row_h-0.1,
boxstyle="round,pad=0.01,rounding_size=0.03",
facecolor=col, edgecolor=C_ARR, linewidth=0.8, zorder=3)
ax.add_patch(box)
ax.text(col_xs[0], y, typ, ha='center', va='center', fontsize=8.5, fontweight='bold', color=C_TXT, zorder=4)
ax.text(col_xs[1], y, struct, ha='center', va='center', fontsize=8.0, color=C_TXT, zorder=4, multialignment='center')
ax.text(col_xs[2], y, loc, ha='center', va='center', fontsize=8.0, color=C_TXT, zorder=4, multialignment='center')
ax.text(0.12, 0.018, "Source: THIEME Atlas of Anatomy – General Anatomy, Section 6.3",
transform=ax.transAxes, fontsize=7, color='#888888')
plt.tight_layout()
pdf.savefig(fig, bbox_inches='tight')
plt.close(fig)
# ═══════════════════════════════════════════════════════════════════════════
# PAGE 5 – Embryonic Circulation & Lymphatics
# ═══════════════════════════════════════════════════════════════════════════
def page_embryo_lymph(pdf):
fig, ax = plt.subplots(figsize=(8.5, 11))
clean_ax(ax, (0, 10), (0, 14))
page_title(ax, "Flowchart 5: Embryonic Circulation & Lymphatic System",
"3–4 Week Embryo | Three Circulatory Systems | Lymphatic Pathway")
BW = 4.0
# Header
ax.text(5.0, 13.0, "EARLY EMBRYONIC CARDIOVASCULAR SYSTEM (Weeks 3–4)",
ha='center', fontsize=10, fontweight='bold', color=C_TITLE)
rounded_box(ax, 5.0, 12.4, 6.0, 0.55,
"Two-chambered heart + Three distinct circulatory systems",
"#E8EAF6", bold=True, fontsize=9)
# Three circuits
circuits = [
(1.8, [
(1.8, 11.3, "Intraembryonic\nSystemic Circulation", C_BOX_ORG),
(1.8, 10.3, "Ventral & Dorsal Aorta\nBranchial / Aortic Arches", C_BOX_ORG),
(1.8, 9.3, "Anterior & Posterior\nCardinal Veins", C_BOX_ORG),
]),
(5.0, [
(5.0, 11.3, "Extraembryonic Vitelline\nCirculation", C_BOX_GRN),
(5.0, 10.3, "Omphalomesenteric\nArteries", C_BOX_GRN),
(5.0, 9.3, "Omphalomesenteric\n(Vitelline) Veins", C_BOX_GRN),
]),
(8.2, [
(8.2, 11.3, "Placental Circulation", C_BOX_BLU),
(8.2, 10.3, "Umbilical Arteries\n(deoxygenated blood to placenta)", C_BOX_BLU),
(8.2, 9.3, "Umbilical Vein\n(O₂-rich blood to embryo\n– note: vein carries O₂ blood!)", C_BOX_BLU),
]),
]
for (_, nodes) in circuits:
for (x,y,t,c) in nodes:
rounded_box(ax, x, y, 3.0, 0.70, t, c, fontsize=8.2)
for i in range(len(nodes)-1):
arrow(ax, nodes[i][0], nodes[i][1]-0.35, nodes[i+1][0], nodes[i+1][1]+0.35)
arrow(ax, 5.0, 12.4-0.28, nodes[0][0], nodes[0][1]+0.35)
# Note about symmetry loss
rounded_box(ax, 5.0, 8.4, 8.5, 0.65,
"Initially: largely symmetrical vascular arrangement\n"
"With development: symmetry lost → LEFT-sided preponderance\n"
"(e.g., left 4th aortic arch becomes the definitive aortic arch)",
C_BOX_PUR, fontsize=8.5)
# Lymphatic system
ax.text(5.0, 7.5, "LYMPHATIC SYSTEM", ha='center', fontsize=10,
fontweight='bold', color=C_TITLE)
lymph = [
(5.0, 6.9, "Interstitium\n(excess fluid from capillary exchange)", C_BOX_GRY),
(5.0, 6.0, "Blind-ended Lymphatic Capillaries\n(initial collectors)", C_BOX_PUR),
(5.0, 5.1, "Lymph Nodes\n(biological filtration of lymph)", C_BOX_PUR),
(5.0, 4.2, "Progressively Larger Lymphatic Vessels\n(thoracic duct / right lymphatic duct)", C_BOX_PUR),
(5.0, 3.3, "Venous Blood\n(subclavian vein junction – returns lymph to circulation)", C_BOX_BLU),
]
for (x,y,t,c) in lymph:
rounded_box(ax, x, y, 5.5, 0.65, t, c, fontsize=8.5)
for i in range(len(lymph)-1):
arrow(ax, lymph[i][0], lymph[i][1]-0.33, lymph[i+1][0], lymph[i+1][1]+0.33)
# Key rule callout
rounded_box(ax, 5.0, 2.1, 8.5, 0.65,
"KEY RULE: All vessels leading AWAY from the heart = Arteries\n"
"All vessels leading TOWARD the heart = Veins (regardless of O₂ content)",
"#FFFDE7", edgecolor="#F9A825", fontsize=8.5, bold=False)
ax.text(0.12, 0.018, "Source: THIEME Atlas of Anatomy – General Anatomy, Sections 1.6 & 6.1",
transform=ax.transAxes, fontsize=7, color='#888888')
plt.tight_layout()
pdf.savefig(fig, bbox_inches='tight')
plt.close(fig)
# ═══════════════════════════════════════════════════════════════════════════
# COVER PAGE
# ═══════════════════════════════════════════════════════════════════════════
def page_cover(pdf):
fig, ax = plt.subplots(figsize=(8.5, 11))
clean_ax(ax, (0, 1), (0, 1))
# Background gradient blocks
for i, col in enumerate(["#E3F2FD","#E8F5E9","#FFF3E0","#F3E5F5","#FFEBEE"]):
ax.add_patch(FancyBboxPatch((0.05, 0.08+i*0.13), 0.9, 0.12,
boxstyle="round,pad=0.01", facecolor=col,
edgecolor='none', zorder=1))
ax.add_patch(FancyBboxPatch((0.04, 0.06), 0.92, 0.68,
boxstyle="round,pad=0.01", facecolor='white',
edgecolor=C_TITLE, linewidth=2, zorder=2))
ax.text(0.5, 0.92, "THE CIRCULATORY SYSTEM", ha='center', fontsize=22,
fontweight='bold', color=C_TITLE, transform=ax.transAxes)
ax.text(0.5, 0.86, "Visual Flowchart Reference", ha='center', fontsize=14,
color='#37474F', transform=ax.transAxes)
ax.text(0.5, 0.82, "Based on: THIEME Atlas of Anatomy – General Anatomy\n"
"Sections 1.6, 6.1, 6.2, 6.3",
ha='center', fontsize=10, color='#555555', transform=ax.transAxes,
multialignment='center')
charts = [
("1", "The Two Main Circulatory Circuits", "Pulmonary · Systemic · Portal", C_BOX_RED),
("2", "Functional Pressure Systems", "High-pressure · Capillary Exchange · Low-pressure", C_BOX_ORG),
("3", "Structure of Blood Vessel Walls", "Tunica Intima · Media · Adventitia", C_BOX_GRN),
("4", "Terminal Vascular Bed & Microcirculation", "Precapillary sphincters · Starling forces · Capillary types", C_BOX_BLU),
("5", "Embryonic Circulation & Lymphatic System", "3-circuit embryo · Lymphatic pathway", C_BOX_PUR),
]
for i, (num, title, sub, col) in enumerate(charts):
y = 0.70 - i*0.13
ax.add_patch(FancyBboxPatch((0.06, y-0.045), 0.88, 0.09,
boxstyle="round,pad=0.01,rounding_size=0.02",
facecolor=col, edgecolor=C_ARR, linewidth=0.8,
transform=ax.transAxes, zorder=3))
ax.text(0.11, y+0.005, f"#{num}", ha='center', va='center', fontsize=13,
fontweight='bold', color=C_TITLE, transform=ax.transAxes)
ax.text(0.62, y+0.018, title, ha='center', va='center', fontsize=10,
fontweight='bold', color=C_TXT, transform=ax.transAxes)
ax.text(0.62, y-0.015, sub, ha='center', va='center', fontsize=8,
color='#555555', transform=ax.transAxes)
ax.text(0.5, 0.035, "Generated June 2026 | For educational use only",
ha='center', fontsize=8, color='#999999', transform=ax.transAxes)
pdf.savefig(fig, bbox_inches='tight')
plt.close(fig)
# ═══════════════════════════════════════════════════════════════════════════
# MAIN
# ═══════════════════════════════════════════════════════════════════════════
with PdfPages(OUTPUT) as pdf:
page_cover(pdf)
page_pulmonary_systemic(pdf)
page_pressure_systems(pdf)
page_vessel_structure(pdf)
page_microcirculation(pdf)
page_embryo_lymph(pdf)
d = pdf.infodict()
d['Title'] = 'Circulatory System – Flowchart Reference'
d['Author'] = 'Orris AI'
d['Subject'] = 'Human Circulatory System'
d['Keywords']= 'circulatory system, heart, blood vessels, anatomy, flowchart'
print("PDF saved to:", OUTPUT)
python3 /home/daytona/workspace/circulatory-flowcharts/make_flowcharts.py 2>&1