Define Bone it's type classification and cartilage and it's classification and types from text book
"Bone is a specialized form of connective tissue that, like other connective tissues, consists of cells and extracellular matrix. The feature that distinguishes bone from other connective tissues is the mineralization of its matrix, which produces an extremely hard tissue capable of providing support and protection. The mineral is calcium phosphate in the form of hydroxyapatite crystals [Ca₁₀(PO₄)₆(OH)₂]."
| Feature | Compact (Dense) Bone | Spongy (Cancellous/Trabecular) Bone |
|---|---|---|
| Appearance | Dense, solid outer shell | Sponge-like meshwork of trabeculae |
| Location | Forms outer shell of ALL bones | Interior of bones |
| Internal spaces | Minimal; contains osteons (Haversian systems) | Spaces filled with marrow and blood vessels |
| Structural units | Osteons (Haversian systems) | Trabeculae (thin, anastomosing spicules) |
"A compact, dense layer forms the outside of the bone (compact bone); a sponge-like meshwork consisting of trabeculae (thin, anastomosing spicules of bone tissue) forms the interior of the bone (spongy bone)."
| Type | Shape | Examples |
|---|---|---|
| Long bones | Tubular | Humerus (upper limb), Femur (lower limb) |
| Short bones | Cuboidal | Carpal bones (wrist), Tarsal bones (ankle) |
| Flat bones | Two compact plates separated by spongy bone | Skull, Scapula |
| Irregular bones | Various/complex shapes | Bones of the face, Vertebrae |
| Sesamoid bones | Round or oval; develop in tendons | Patella (largest), sesamoids in thumb/big toe flexor tendons |
"Sesamoid bones are embedded within tendons... There are many other sesamoids in the body, particularly in tendons of the hands and feet, and most frequently in flexor tendons of the thumb and big toe."
| Feature | Mature (Lamellar) Bone | Immature (Woven) Bone |
|---|---|---|
| Structural unit | Osteons (Haversian systems) | No organized lamellae |
| Collagen arrangement | Organized, parallel lamellae | Randomly arranged collagen fibers |
| Occurrence | Normal adult bone | Fetal bone; fracture repair (temporary) |
| Cell Type | Origin | Function |
|---|---|---|
| Osteoprogenitor cells | Mesenchymal stem cells | Precursors; differentiate into osteoblasts |
| Osteoblasts | Osteoprogenitor cells | Secrete bone matrix (osteoid) |
| Osteocytes | Trapped osteoblasts | Maintain bone matrix; mechanosensing |
| Bone-lining cells | Osteoblasts | Resting cells lining bone surfaces |
| Osteoclasts | Hematopoietic progenitor cells | Bone resorption/remodeling |
"All bones come from mesenchyme by either intramembranous ossification, in which mesenchymal models of bones undergo ossification, or endochondral ossification, in which cartilaginous models of bones form from mesenchyme and undergo ossification."
| Type | Mechanism | Examples |
|---|---|---|
| Intramembranous ossification | Mesenchyme → bone directly | Flat bones of the skull |
| Endochondral ossification | Cartilage model → replaced by bone | Long bones, base of skull |
"Cartilage is a form of connective tissue composed of cells called chondrocytes and a highly specialized extracellular matrix. Cartilage is an avascular tissue that consists of chondrocytes and an extensive extracellular matrix. More than 95% of cartilage volume consists of extracellular matrix."
"Hyaline cartilage is distinguished by a homogeneous, amorphous matrix. It appears glassy in the living state, hence the name hyaline [Gr. hyalos, glassy]."
| Feature | Detail |
|---|---|
| Matrix components | Type II collagen fibrils, GAGs, proteoglycans, multiadhesive glycoproteins |
| Appearance | Glassy/translucent, homogeneous |
| Perichondrium | Present (except at articular surfaces and epiphyseal plates) |
| Calcification | Yes - during endochondral ossification and aging |
| Locations | - Articular surfaces of synovial joints |
| - Epiphyseal (growth) plates | |
| - Costal cartilages of the rib cage | |
| - Cartilages of nasal cavity | |
| - Larynx (thyroid, cricoid, arytenoid cartilages) | |
| - Rings of trachea and plates in bronchi | |
| - Fetal skeletal tissue (precursor for endochondral ossification) | |
| Functions | Resists compression; low-friction joint surface; structural support in respiratory tract; template for fetal bone development |
"In addition to containing the normal components of hyaline cartilage matrix, elastic cartilage matrix also contains a dense network of branching and anastomosing elastic fibers and interconnecting sheets of elastic material."
| Feature | Detail |
|---|---|
| Matrix components | Type II collagen + elastic fibers and lamellae (stained with resorcin-fuchsin or orcein) |
| Perichondrium | Present |
| Calcification | Does NOT calcify with aging |
| Locations | - Pinna (external ear) |
| - Walls of external acoustic meatus | |
| - Auditory (Eustachian) tube | |
| - Epiglottis of larynx | |
| - Vocal folds | |
| Functions | Provides flexibility and elasticity |
"Fibrocartilage is a combination of dense regular connective tissue and hyaline cartilage. The chondrocytes are dispersed among the collagen fibers singularly, in rows, and in isogenous groups."
| Feature | Detail |
|---|---|
| Matrix components | Abundant type I collagen fibers + hyaline cartilage matrix components |
| Perichondrium | Absent (no surrounding perichondrium) |
| Calcification | Variable |
| Locations | - Intervertebral discs |
| - Pubic symphysis | |
| - Articular discs of some joints (e.g., TMJ, knee menisci) | |
| - Sites of tendon/ligament attachment to bone | |
| Functions | Withstands compressive and tensile forces; provides strength at high-stress sites |
| Feature | Hyaline | Elastic | Fibrocartilage |
|---|---|---|---|
| Collagen type | Type II | Type II | Type I (predominant) |
| Elastic fibers | Absent | Present (abundant) | Absent |
| Perichondrium | Yes* | Yes | No |
| Calcifies | Yes (aging, ossification) | No | Variable |
| Ground substance | Abundant | Moderate | Sparse |
| Main function | Support, low-friction | Flexibility | Strength, load-bearing |
| Zone | Location | Key Content |
|---|---|---|
| Capsular (pericellular) matrix | Immediately around each chondrocyte | Highest sulfated proteoglycans; type VI collagen; fibronectin, laminin |
| Territorial matrix | Surrounds the isogenous group | Type II collagen network; lower proteoglycan concentration |
| Interterritorial matrix | Between chondrocyte groups | Largest zone; bulk of the matrix |
Make me flow charts of this in easy way and pdf
ls /home/daytona/workspace/ 2>/dev/null && echo "---" && python3 -c "import reportlab; print('reportlab ok')" && python3 -c "import matplotlib; print('matplotlib ok')"
mkdir -p /home/daytona/workspace/bone-cartilage-flowchart
~/bone-cartilage-flowchart/generate_flowcharts.py
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
import matplotlib.patheffects as pe
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import inch, cm
from reportlab.platypus import SimpleDocTemplate, Spacer, Image as RLImage, Paragraph, HRFlowable
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
import os
OUTPUT_DIR = "/home/daytona/workspace/bone-cartilage-flowchart"
# ─────────────────────────────────────────────────────────────
# COLOUR PALETTE
# ─────────────────────────────────────────────────────────────
C_BONE_DARK = "#1A5276" # deep navy
C_BONE_MID = "#2E86C1" # mid blue
C_BONE_LIGHT = "#AED6F1" # pale blue
C_BONE_XLIGHT = "#EAF4FB" # very pale blue
C_CART_DARK = "#1E8449" # deep green
C_CART_MID = "#27AE60" # mid green
C_CART_LIGHT = "#A9DFBF" # pale green
C_CART_XLIGHT = "#EAFAF1" # very pale green
C_ACCENT = "#F39C12" # amber highlight
C_ARROW = "#5D6D7E" # grey arrows
C_TEXT_DARK = "#1C2833"
C_TEXT_WHITE = "#FFFFFF"
C_BG = "#FDFEFE"
def rounded_box(ax, x, y, w, h, text, bg, fg=C_TEXT_DARK,
fontsize=9, bold=False, radius=0.03,
wrap=True, ha='center', va='center'):
"""Draw a rounded-corner box with centred text."""
box = FancyBboxPatch((x - w/2, y - h/2), w, h,
boxstyle=f"round,pad=0.01,rounding_size={radius}",
linewidth=1.2, edgecolor=C_TEXT_DARK,
facecolor=bg, zorder=3)
ax.add_patch(box)
weight = 'bold' if bold else 'normal'
ax.text(x, y, text, ha=ha, va=va, fontsize=fontsize,
color=fg, fontweight=weight, wrap=wrap,
multialignment='center', zorder=4)
def arrow(ax, x1, y1, x2, y2, color=C_ARROW):
ax.annotate("", xy=(x2, y2), xytext=(x1, y1),
arrowprops=dict(arrowstyle="-|>", color=color,
lw=1.4, mutation_scale=12), zorder=2)
# ═══════════════════════════════════════════════════════════════
# PAGE 1 – BONE OVERVIEW FLOWCHART
# ═══════════════════════════════════════════════════════════════
def make_bone_overview():
fig, ax = plt.subplots(figsize=(12, 16))
ax.set_xlim(0, 12); ax.set_ylim(0, 16)
ax.axis('off')
fig.patch.set_facecolor(C_BG)
ax.set_facecolor(C_BG)
# ── Title ──
ax.text(6, 15.4, "BONE – Overview Flowchart", ha='center', va='center',
fontsize=18, fontweight='bold', color=C_BONE_DARK,
path_effects=[pe.withStroke(linewidth=3, foreground='white')])
ax.text(6, 15.0, "Source: Gray's Anatomy for Students & Histology: A Text and Atlas",
ha='center', va='center', fontsize=8, color='#7F8C8D', style='italic')
# ── ROOT: BONE ──
rounded_box(ax, 6, 14.2, 3.2, 0.6,
"BONE\n(Calcified Living Connective Tissue)",
C_BONE_DARK, C_TEXT_WHITE, fontsize=11, bold=True)
# ── Level 1 splits ──
arrow(ax, 6, 13.9, 6, 13.3)
rounded_box(ax, 6, 13.0, 10, 0.5,
"Mineralized extracellular matrix | Calcium Phosphate (Hydroxyapatite) | Type I Collagen (90 %)",
C_BONE_LIGHT, C_TEXT_DARK, fontsize=8.5)
# ── FUNCTIONS ──
arrow(ax, 6, 12.75, 6, 12.25)
rounded_box(ax, 6, 11.95, 3.0, 0.5, "FUNCTIONS OF BONE",
C_BONE_MID, C_TEXT_WHITE, fontsize=10, bold=True)
funcs = ["1. Support – structural framework",
"2. Protection – vital organs",
"3. Reservoir – Ca²⁺ & PO₄³⁻",
"4. Leverage – muscle action",
"5. Haematopoiesis – blood cell production"]
for i, f in enumerate(funcs):
yy = 11.45 - i * 0.42
rounded_box(ax, 6, yy, 7.5, 0.35, f, C_BONE_XLIGHT, C_TEXT_DARK, fontsize=8.5)
if i == 0:
arrow(ax, 6, 11.70, 6, 11.63)
else:
arrow(ax, 6, yy + 0.35/2 + 0.07, 6, yy + 0.35/2)
# ── STRUCTURAL TYPES ──
y_struct = 9.28
arrow(ax, 6, 9.28 - 0.21 - 0.07, 6, 9.28 + 0.28) # arrow up into next
arrow(ax, 6, 9.28 - 0.28, 3.0, 8.55)
arrow(ax, 6, 9.28 - 0.28, 9.0, 8.55)
rounded_box(ax, 6, y_struct, 4.0, 0.5, "STRUCTURAL TYPES OF BONE TISSUE",
C_BONE_MID, C_TEXT_WHITE, fontsize=10, bold=True)
arrow(ax, 6, 9.02, 3.0, 8.72)
arrow(ax, 6, 9.02, 9.0, 8.72)
rounded_box(ax, 3.0, 8.42, 4.2, 0.55,
"COMPACT (Dense) Bone\nForms outer shell of all bones",
C_BONE_MID, C_TEXT_WHITE, fontsize=9, bold=True)
rounded_box(ax, 9.0, 8.42, 4.2, 0.55,
"SPONGY (Cancellous/Trabecular) Bone\nForms interior of bones",
C_CART_MID, C_TEXT_WHITE, fontsize=9, bold=True)
compact_pts = ["Structural unit: Osteon (Haversian system)",
"Concentric lamellae of matrix",
"Central Haversian canal (vessels/nerves)",
"Surrounds spongy bone"]
spongy_pts = ["Structural unit: Trabeculae (spicules)",
"Sponge-like meshwork",
"Spaces filled with bone marrow",
"Interior of long / flat bones"]
for i, (cp, sp) in enumerate(zip(compact_pts, spongy_pts)):
yy = 8.0 - i * 0.42
rounded_box(ax, 3.0, yy, 4.1, 0.35, cp, C_BONE_XLIGHT, C_TEXT_DARK, fontsize=7.8)
rounded_box(ax, 9.0, yy, 4.1, 0.35, sp, "#EAFAF1", C_TEXT_DARK, fontsize=7.8)
# ── CLASSIFICATION BY SHAPE ──
arrow(ax, 6, 5.72, 6, 6.28)
rounded_box(ax, 6, 6.58, 4.5, 0.5,
"CLASSIFICATION OF BONES BY SHAPE",
C_BONE_DARK, C_TEXT_WHITE, fontsize=10, bold=True)
shapes = [
("Long Bones", "Tubular shape\ne.g. Humerus, Femur", C_BONE_MID),
("Short Bones", "Cuboidal shape\ne.g. Carpals, Tarsals", "#1A7A4A"),
("Flat Bones", "Two compact plates + spongy\ne.g. Skull, Scapula", "#7D3C98"),
("Irregular Bones", "Complex shape\ne.g. Vertebrae, Facial bones", "#B7770D"),
("Sesamoid Bones", "Oval; in tendons\ne.g. Patella, Thumb sesamoids", "#C0392B"),
]
xs = [1.2, 3.6, 6.0, 8.4, 10.8]
for (name, desc, col), x in zip(shapes, xs):
arrow(ax, 6, 6.33, x, 5.90)
rounded_box(ax, x, 5.55, 2.0, 0.65, f"{name}\n{desc}",
col, C_TEXT_WHITE, fontsize=7.5, bold=False)
# ── DEVELOPMENT ──
arrow(ax, 6, 5.22, 6, 4.75)
rounded_box(ax, 6, 4.50, 4.0, 0.45,
"BONE DEVELOPMENT (Ossification)",
C_BONE_DARK, C_TEXT_WHITE, fontsize=10, bold=True)
arrow(ax, 6, 4.27, 3.2, 3.85)
arrow(ax, 6, 4.27, 8.8, 3.85)
rounded_box(ax, 3.2, 3.55, 5.0, 0.55,
"Intramembranous Ossification\nMesenchyme → bone directly\ne.g. Flat bones of skull",
"#1F618D", C_TEXT_WHITE, fontsize=8)
rounded_box(ax, 8.8, 3.55, 5.0, 0.55,
"Endochondral Ossification\nCartilage model → replaced by bone\ne.g. Long bones",
"#1E8449", C_TEXT_WHITE, fontsize=8)
# ── CELLS ──
arrow(ax, 6, 3.27, 6, 2.80)
rounded_box(ax, 6, 2.55, 3.5, 0.45,
"CELLS OF BONE TISSUE",
C_BONE_DARK, C_TEXT_WHITE, fontsize=10, bold=True)
cells = [
("Osteoprogenitor\nCells", "Precursors\n(Mesenchymal stem cells)", "#2471A3"),
("Osteoblasts", "Secrete bone\nmatrix (osteoid)", "#1A5276"),
("Osteocytes", "Mature cells;\nmaintain matrix", "#117A65"),
("Bone-Lining\nCells", "Resting surface\ncells", "#6E2F98"),
("Osteoclasts", "Bone resorption\n(haematopoietic origin)", "#C0392B"),
]
xs_c = [1.2, 3.6, 6.0, 8.4, 10.8]
for (name, desc, col), x in zip(cells, xs_c):
arrow(ax, 6, 2.32, x, 1.85)
rounded_box(ax, x, 1.52, 2.0, 0.60, f"{name}\n{desc}",
col, C_TEXT_WHITE, fontsize=7.2)
# footer
ax.text(6, 0.18, "© Orris Medical AI | Based on Gray's Anatomy for Students & Histology: A Text and Atlas",
ha='center', va='center', fontsize=7, color='#95A5A6', style='italic')
plt.tight_layout(pad=0.3)
path = os.path.join(OUTPUT_DIR, "01_bone_overview.png")
plt.savefig(path, dpi=180, bbox_inches='tight', facecolor=C_BG)
plt.close()
print(f"Saved: {path}")
return path
# ═══════════════════════════════════════════════════════════════
# PAGE 2 – CARTILAGE OVERVIEW FLOWCHART
# ═══════════════════════════════════════════════════════════════
def make_cartilage_overview():
fig, ax = plt.subplots(figsize=(12, 15))
ax.set_xlim(0, 12); ax.set_ylim(0, 15)
ax.axis('off')
fig.patch.set_facecolor(C_BG)
ax.set_facecolor(C_BG)
ax.text(6, 14.4, "CARTILAGE – Overview Flowchart", ha='center', va='center',
fontsize=18, fontweight='bold', color=C_CART_DARK,
path_effects=[pe.withStroke(linewidth=3, foreground='white')])
ax.text(6, 14.05, "Source: Histology: A Text and Atlas (Pawlina & Ross)",
ha='center', va='center', fontsize=8, color='#7F8C8D', style='italic')
# ROOT
rounded_box(ax, 6, 13.35, 5.5, 0.6,
"CARTILAGE\n(Avascular Connective Tissue – Chondrocytes + ECM)",
C_CART_DARK, C_TEXT_WHITE, fontsize=11, bold=True)
arrow(ax, 6, 13.05, 6, 12.55)
rounded_box(ax, 6, 12.28, 9.0, 0.45,
"> 95 % Extracellular Matrix | Chondrocytes in Lacunae | No blood vessels (avascular) | Perichondrium present (usually)",
C_CART_LIGHT, C_TEXT_DARK, fontsize=8)
# THREE TYPES header
arrow(ax, 6, 12.05, 6, 11.60)
rounded_box(ax, 6, 11.35, 4.5, 0.45,
"THREE TYPES OF CARTILAGE",
C_CART_DARK, C_TEXT_WHITE, fontsize=10, bold=True)
arrow(ax, 6, 11.12, 2.0, 10.62)
arrow(ax, 6, 11.12, 6.0, 10.62)
arrow(ax, 6, 11.12, 10.0, 10.62)
# ── HYALINE ──
rounded_box(ax, 2.0, 10.32, 3.6, 0.55,
"1. HYALINE CARTILAGE\n(Most common type)",
"#1F618D", C_TEXT_WHITE, fontsize=9, bold=True)
hyaline_pts = [
"Matrix: Type II collagen + GAGs",
"Appearance: Glassy/translucent",
"Perichondrium: Present*",
"Calcifies: Yes (aging/ossification)",
"LOCATIONS:",
" • Articular surfaces",
" • Epiphyseal (growth) plates",
" • Costal cartilages",
" • Trachea, Bronchi, Larynx",
" • Nasal cartilages",
"FUNCTION: Resist compression,",
" low-friction surface, fetal skeleton",
]
for i, pt in enumerate(hyaline_pts):
yy = 9.92 - i * 0.41
col = "#EAF4FB" if not pt.startswith("LOCA") and not pt.startswith("FUNC") else "#D6EAF8"
rounded_box(ax, 2.0, yy, 3.5, 0.35, pt,
col, C_TEXT_DARK, fontsize=7.5)
# ── ELASTIC ──
rounded_box(ax, 6.0, 10.32, 3.6, 0.55,
"2. ELASTIC CARTILAGE\n(Flexible type)",
"#1E8449", C_TEXT_WHITE, fontsize=9, bold=True)
elastic_pts = [
"Matrix: Type II collagen +",
" elastic fibers & lamellae",
"Stain: Resorcin-fuchsin/Orcein",
"Perichondrium: Present",
"Calcifies: NO",
"LOCATIONS:",
" • Pinna (external ear)",
" • External acoustic meatus",
" • Auditory (Eustachian) tube",
" • Epiglottis",
" • Vocal folds",
"FUNCTION: Flexibility & elasticity",
]
for i, pt in enumerate(elastic_pts):
yy = 9.92 - i * 0.41
col = "#EAFAF1" if not pt.startswith("LOCA") and not pt.startswith("FUNC") else "#D5F5E3"
rounded_box(ax, 6.0, yy, 3.5, 0.35, pt,
col, C_TEXT_DARK, fontsize=7.5)
# ── FIBROCARTILAGE ──
rounded_box(ax, 10.0, 10.32, 3.6, 0.55,
"3. FIBROCARTILAGE\n(Strongest type)",
"#7D3C98", C_TEXT_WHITE, fontsize=9, bold=True)
fibro_pts = [
"Matrix: Type I collagen",
" (abundant) + hyaline matrix",
"Perichondrium: ABSENT",
"Calcifies: Variable",
"Transition zone: dense CT",
"LOCATIONS:",
" • Intervertebral discs",
" • Pubic symphysis",
" • Knee menisci",
" • Articular discs (TMJ)",
" • Tendon/ligament insertions",
"FUNCTION: Compressive & tensile strength",
]
for i, pt in enumerate(fibro_pts):
yy = 9.92 - i * 0.41
col = "#F5EEF8" if not pt.startswith("LOCA") and not pt.startswith("FUNC") else "#E8DAEF"
rounded_box(ax, 10.0, yy, 3.5, 0.35, pt,
col, C_TEXT_DARK, fontsize=7.5)
# ── COMPARISON TABLE header ──
y_comp = 4.82
rounded_box(ax, 6, y_comp, 5.0, 0.45,
"QUICK COMPARISON TABLE",
C_CART_DARK, C_TEXT_WHITE, fontsize=10, bold=True)
arrow(ax, 6, y_comp - 0.22, 6, 4.42)
cols_h = ["Feature", "Hyaline", "Elastic", "Fibrocartilage"]
rows = [
["Collagen type", "Type II", "Type II", "Type I (main)"],
["Elastic fibers", "Absent", "Present", "Absent"],
["Perichondrium", "Yes*", "Yes", "No"],
["Calcifies", "Yes", "No", "Variable"],
["Ground substance", "Abundant", "Moderate", "Sparse"],
["Main function", "Support/surface","Flexibility", "Load-bearing"],
]
col_w = [2.2, 2.2, 2.2, 2.2]
col_x = [1.1, 3.3, 5.5, 7.7]
hdr_bg = [C_CART_DARK, "#1F618D", "#1E8449", "#7D3C98"]
y_row = 4.35
row_h = 0.38
for ci, (header, bkg) in enumerate(zip(cols_h, hdr_bg)):
rounded_box(ax, col_x[ci], y_row, col_w[ci] - 0.08, row_h - 0.04,
header, bkg, C_TEXT_WHITE, fontsize=8.5, bold=True)
for ri, row in enumerate(rows):
y_row -= row_h
row_bkg = C_BG if ri % 2 == 0 else "#ECF0F1"
for ci, cell in enumerate(row):
rounded_box(ax, col_x[ci], y_row, col_w[ci] - 0.08, row_h - 0.04,
cell, row_bkg, C_TEXT_DARK, fontsize=7.8)
# ── GROWTH MECHANISMS ──
y_gr = y_row - 0.50
rounded_box(ax, 6, y_gr, 5.0, 0.45,
"CARTILAGE GROWTH MECHANISMS",
C_CART_DARK, C_TEXT_WHITE, fontsize=10, bold=True)
arrow(ax, 6, y_gr - 0.22, 3.2, y_gr - 0.65)
arrow(ax, 6, y_gr - 0.22, 8.8, y_gr - 0.65)
rounded_box(ax, 3.2, y_gr - 0.95, 5.0, 0.55,
"Interstitial Growth\nChondrocytes divide within lacunae\n(distensible matrix expands)",
"#1F618D", C_TEXT_WHITE, fontsize=8)
rounded_box(ax, 8.8, y_gr - 0.95, 5.0, 0.55,
"Appositional Growth\nNew chondroblasts from perichondrium\ndeposit matrix on surface",
"#1E8449", C_TEXT_WHITE, fontsize=8)
ax.text(6, 0.18, "© Orris Medical AI | Based on Histology: A Text and Atlas (Pawlina & Ross)",
ha='center', va='center', fontsize=7, color='#95A5A6', style='italic')
plt.tight_layout(pad=0.3)
path = os.path.join(OUTPUT_DIR, "02_cartilage_overview.png")
plt.savefig(path, dpi=180, bbox_inches='tight', facecolor=C_BG)
plt.close()
print(f"Saved: {path}")
return path
# ═══════════════════════════════════════════════════════════════
# PAGE 3 – BONE vs CARTILAGE COMPARISON FLOWCHART
# ═══════════════════════════════════════════════════════════════
def make_comparison():
fig, ax = plt.subplots(figsize=(14, 10))
ax.set_xlim(0, 14); ax.set_ylim(0, 10)
ax.axis('off')
fig.patch.set_facecolor(C_BG)
ax.set_facecolor(C_BG)
ax.text(7, 9.5, "BONE vs CARTILAGE – Side-by-Side Comparison",
ha='center', va='center', fontsize=17, fontweight='bold', color=C_TEXT_DARK,
path_effects=[pe.withStroke(linewidth=3, foreground='white')])
# column headers
rounded_box(ax, 3.5, 8.8, 5.5, 0.55, "BONE", C_BONE_DARK, C_TEXT_WHITE, fontsize=14, bold=True)
rounded_box(ax, 10.5, 8.8, 5.5, 0.55, "CARTILAGE", C_CART_DARK, C_TEXT_WHITE, fontsize=14, bold=True)
comparisons = [
("Tissue type", "Connective tissue", "Connective tissue"),
("Vascularity", "Vascular (periosteum + nutrient artery)", "Avascular"),
("Matrix mineral", "Hydroxyapatite Ca₁₀(PO₄)₆(OH)₂", "Not mineralized (usually)"),
("Main collagen", "Type I collagen (~90%)", "Type II (hyaline/elastic)\nType I (fibrocartilage)"),
("Cells", "Osteoblasts, Osteocytes,\nOsteoclasts, OPCs", "Chondroblasts, Chondrocytes"),
("Cell housing", "Lacunae (osteocytes)", "Lacunae (chondrocytes)"),
("Covering", "Periosteum (outer)\nEndosteum (inner)", "Perichondrium (most types)"),
("Nutrition", "Blood vessels (periosteum &\nHaversian canals)", "Diffusion through matrix"),
("Rigidity", "Very rigid/hard", "Firm but pliable/resilient"),
("Repair capacity", "Good (periosteum-mediated)", "Poor (limited in adults)"),
("Main functions", "Support, protection,\nmovement, haematopoiesis","Cushioning, flexibility,\ngrowth plate, template"),
("Development", "Intramembranous or\nEndochondral ossification","From mesenchymal cells\n(chondrogenesis)"),
]
row_h = 0.52
y0 = 8.35
for i, (feature, bone_val, cart_val) in enumerate(comparisons):
yy = y0 - i * row_h
bkg_b = C_BONE_XLIGHT if i % 2 == 0 else "#D6EAF8"
bkg_c = C_CART_XLIGHT if i % 2 == 0 else "#D5F5E3"
bkg_f = "#F2F3F4" if i % 2 == 0 else "#E5E7E9"
rounded_box(ax, 7, yy, 1.8, row_h - 0.06, feature, bkg_f, C_TEXT_DARK, fontsize=8.5, bold=True)
rounded_box(ax, 3.5, yy, 5.3, row_h - 0.06, bone_val, bkg_b, C_TEXT_DARK, fontsize=8.2)
rounded_box(ax, 10.5, yy, 5.3, row_h - 0.06, cart_val, bkg_c, C_TEXT_DARK, fontsize=8.2)
ax.text(7, 0.25, "© Orris Medical AI | Based on Gray's Anatomy for Students & Histology: A Text and Atlas",
ha='center', va='center', fontsize=7, color='#95A5A6', style='italic')
plt.tight_layout(pad=0.3)
path = os.path.join(OUTPUT_DIR, "03_comparison.png")
plt.savefig(path, dpi=180, bbox_inches='tight', facecolor=C_BG)
plt.close()
print(f"Saved: {path}")
return path
# ═══════════════════════════════════════════════════════════════
# ASSEMBLE PDF
# ═══════════════════════════════════════════════════════════════
def build_pdf(images):
pdf_path = os.path.join(OUTPUT_DIR, "Bone_and_Cartilage_Flowcharts.pdf")
doc = SimpleDocTemplate(pdf_path, pagesize=A4,
leftMargin=1.5*cm, rightMargin=1.5*cm,
topMargin=1.5*cm, bottomMargin=1.5*cm)
styles = getSampleStyleSheet()
title_style = ParagraphStyle(
'TitleStyle', parent=styles['Title'],
fontSize=20, leading=26, textColor=colors.HexColor("#1A5276"),
alignment=TA_CENTER, spaceAfter=4
)
sub_style = ParagraphStyle(
'SubStyle', parent=styles['Normal'],
fontSize=10, leading=14, textColor=colors.HexColor("#7F8C8D"),
alignment=TA_CENTER, spaceAfter=16, fontName='Helvetica-Oblique'
)
caption_style = ParagraphStyle(
'CaptionStyle', parent=styles['Normal'],
fontSize=9, leading=13, textColor=colors.HexColor("#2C3E50"),
alignment=TA_CENTER, spaceBefore=4, spaceAfter=12
)
story = []
story.append(Paragraph("Bone & Cartilage", title_style))
story.append(Paragraph("Classification, Types & Flowcharts", title_style))
story.append(Spacer(1, 0.1*inch))
story.append(Paragraph(
"Based on: <i>Gray's Anatomy for Students</i> & "
"<i>Histology: A Text and Atlas with Correlated Cell and Molecular Biology</i>",
sub_style
))
story.append(HRFlowable(width="100%", thickness=2,
color=colors.HexColor("#2E86C1"), spaceAfter=20))
captions = [
("Flowchart 1", "Bone – Definition, Structure, Classification by Shape, Bone Types, Cells & Development"),
("Flowchart 2", "Cartilage – Definition, Three Types (Hyaline, Elastic, Fibrocartilage), Comparison Table & Growth"),
("Flowchart 3", "Bone vs. Cartilage – Side-by-Side Comparison of Key Features"),
]
page_w = A4[0] - 3*cm
for img_path, (fc_num, caption_text) in zip(images, captions):
from PIL import Image as PILImage
with PILImage.open(img_path) as im:
iw, ih = im.size
aspect = ih / iw
display_w = page_w
display_h = display_w * aspect
# keep within page height
max_h = A4[1] - 5*cm
if display_h > max_h:
display_h = max_h
display_w = display_h / aspect
story.append(RLImage(img_path, width=display_w, height=display_h))
story.append(Paragraph(
f"<b>{fc_num}:</b> {caption_text}", caption_style))
story.append(HRFlowable(width="100%", thickness=0.5,
color=colors.HexColor("#BDC3C7"), spaceAfter=14))
doc.build(story)
print(f"PDF saved: {pdf_path}")
return pdf_path
if __name__ == "__main__":
p1 = make_bone_overview()
p2 = make_cartilage_overview()
p3 = make_comparison()
pdf = build_pdf([p1, p2, p3])
print(f"\nDONE: {pdf}")
cd /home/daytona/workspace/bone-cartilage-flowchart && python3 generate_flowcharts.py 2>&1
Bone and Cartilage Flowcharts
PDF Document · PDF
Make it open able
python3 -c " from pypdf import PdfReader r = PdfReader('/home/daytona/workspace/bone-cartilage-flowchart/Bone_and_Cartilage_Flowcharts.pdf') print(f'Pages: {len(r.pages)}') print(f'File size: $(du -sh /home/daytona/workspace/bone-cartilage-flowchart/Bone_and_Cartilage_Flowcharts.pdf)') " ls -lh /home/daytona/workspace/bone-cartilage-flowchart/
Generate a comparison poster summarizing bone vs cartilage