Lower limb bone identification

Reading File
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Loading Image
Reading File
Finding Sources
Finding Sources
Reading File
Loading Image
I now have rich content and images. Let me compile the complete lower limb bone identification guide.

Lower Limb Bone Identification

The lower limb is divided into four regions - gluteal region, thigh, leg, and foot - each with distinct bones. Sources: Gray's Anatomy for Students and Forensic Anthropology: A Comprehensive Introduction, 2e.
Regions of the Lower Limb - anterior and posterior views showing pelvis, thigh, leg, and foot

1. Femur (Thigh Bone)

The femur is the longest and heaviest bone in the body. It articulates proximally with the acetabulum of the os coxa and distally with the tibia and patella.
Proximal femur - posterior view showing fovea, neck, trochanters, trochanteric fossa

Proximal End

StructureDescription
HeadSphere-shaped; articulates with acetabulum via ball-and-socket joint. More spherical than the humeral head (identification tip).
Fovea capitisSmall notch on the medial surface of the head; attachment for the ligamentum teres.
NeckCylindrical strut connecting head to shaft; projects supero-medially at ~125° to the shaft, and slightly forward.
Greater trochanterLarge lateral prominence; insertion for gluteus minimus, gluteus medius, obturator internus, piriformis.
Trochanteric fossaDeep groove on the medial surface of the greater trochanter (posterior).
Lesser trochanterSmaller, blunt, posteromedial projection; attachment for psoas major and iliacus (iliopsoas).
Intertrochanteric lineAnterior ridge between the two trochanters.
Intertrochanteric crestPosterior ridge; bears the quadrate tubercle for quadratus femoris.

Shaft

StructureDescription
Linea asperaProminent posterior ridge running the length of the shaft; site of attachment for adductors, some quadriceps and hamstrings.
Pectineal lineProximal medial continuation of linea aspera.
Gluteal tuberosityProximal lateral continuation of linea aspera; may form a third trochanter in some individuals.
Nutrient foramenOn posterior surface near linea aspera; opens distally ("flees the knee").

Distal End

StructureDescription
Medial condyleLarge articular surface; projects more distally than the lateral condyle.
Lateral condyleArticular surface for the tibia; raised lateral lip guards against patellar dislocation.
Medial & lateral epicondylesBony projections on each condyle; sites of ligamentous and muscle attachment.
Patellar articular surfaceSmooth anterior surface allowing patella to glide during flexion/extension.
Intercondylar fossaDeep posterior groove between condyles; houses cruciate ligament attachments.
Siding the femur: Head is proximal and medial. Greater trochanter is lateral. Nutrient foramen opens away from the knee. Patellar surface is anterior. Lesser trochanter and linea aspera are posterior.

2. Patella (Kneecap)

The patella is a large sesamoid bone (develops within the quadriceps tendon). It articulates with the patellar articular surface of the distal femur.
StructureDescription
ApexPointed, non-articular, points distally.
Medial articular facetPosterior surface; smaller of the two facets.
Lateral articular facetPosterior surface; larger facet (the patella is asymmetric - lateral is bigger).
Siding the patella: Place it with the articular surface down and apex pointing away - it will fall to the side it came from (the larger lateral articular surface tips it).

3. Tibia (Shin Bone)

The tibia is the larger, medial bone of the leg, supporting the majority of body weight. It articulates superiorly with the femur, laterally with the fibula, and distally with the talus.
StructureDescription
Tibial plateauProximal surface articulating with femoral condyles; divided into medial and lateral condyles.
Medial condyleLarger proximal compartment.
Lateral condyleSmaller; has the superior fibular articular facet on its postero-inferior surface.
Tibial tuberosityAnterior projection just below the plateau; attachment for the patellar ligament.
Anterior crestSharp anterior shaft ridge - the "shin."
Interosseous crestLateral shaft ridge; attachment for interosseous membrane binding tibia to fibula.
Nutrient foramenPosterior surface, proximal to midshaft; opens away from the knee.
Medial malleolusBony projection on the disto-medial tibia; forms the medial ankle bulge; articulates with the talus.
Fibular notchDisto-lateral edge; site of the distal tibiofibular syndesmosis.
Siding the tibia: Plateau is proximal. Medial malleolus is distal and medial. Fibular notch is distal and lateral. Tibial tuberosity and anterior crest are anterior. Nutrient foramen opens away from the knee.

4. Fibula (Lateral Leg Bone)

The fibula is the smaller, lateral bone of the leg. It is non-weight-bearing (connected to the tibia by the interosseous membrane) and primarily provides muscle attachment and ankle stability.
StructureDescription
HeadProximal end; articulates with the postero-inferior lateral condyle of the tibia.
NeckJust distal to the head; the common fibular nerve wraps around here (clinically important).
ShaftLong and slender; triangular cross-section.
Interosseous crestMedial ridge for interosseous membrane.
Lateral malleolusDistal end; forms the lateral ankle bulge - extends more distally than the medial malleolus.
Siding the fibula: Head is proximal. Lateral malleolus is distal. The interosseous crest faces medially (toward the tibia). The nutrient foramen opens proximally ("flees from the knee" - opposite to tibia and femur).

5. Tarsal Bones (7 bones)

The tarsals form the proximal foot skeleton. Listed proximal to distal:
BoneKey FeaturesArticulations
Talus"Ankle bone." Has the trochlea (pulley-shaped body) that sits in the ankle mortise. No muscle attachments.Tibia & fibula above; calcaneus below; navicular anteriorly.
CalcaneusLargest tarsal bone; forms the heel. Has the sustentaculum tali (medial shelf supporting talus).Talus above; cuboid anteriorly.
NavicularBowl-shaped; concave proximal surface for talus head. Has a projecting medial tubercle (palpable landmark).Talus proximally; 3 cuneiforms distally.
CuboidLateral side of foot. Has cuboid tuberosity on infero-lateral surface.Calcaneus proximally; navicular & lateral cuneiform medially; 4th & 5th metatarsals distally.
Medial (1st) cuneiformLargest cuneiform.Navicular proximally; 1st metatarsal distally.
Intermediate (2nd) cuneiformSmallest cuneiform.Navicular proximally; 2nd metatarsal distally.
Lateral (3rd) cuneiformMid-sized.Navicular proximally; 3rd metatarsal distally; cuboid laterally.

6. Metatarsals (5 bones)

The metatarsals lie between the tarsals (proximally) and phalanges (distally), forming the arch of the foot. Each has a concave or flat base proximally and a rounded head distally.
BoneDistinguishing Feature
1st metatarsalShortest but most robust; single round head.
2nd metatarsalLongest; its base is keyed between the three cuneiforms (most stable, most often fractured in "march fracture").
3rd metatarsalIntermediate length; articulates with lateral cuneiform.
4th metatarsalArticulates with cuboid and lateral cuneiform.
5th metatarsalHas a large styloid process (tuberosity) at the base; palpable laterally. Avulsion fractures common here (peroneus brevis attachment).

7. Phalanges (Toe Bones)

  • 14 phalanges total: 3 per toe (proximal, middle, distal) except the great toe (hallux), which has only 2 (proximal + distal).
  • The hallux phalanges are much larger and more robust than the lesser toe phalanges.
  • Each phalanx has a base (proximal), shaft, and head (distal).

Quick Reference: Lower Limb Bone Count

RegionBonesCount
ThighFemur1
KneePatella1
LegTibia, Fibula2
TarsusTalus, Calcaneus, Navicular, Cuboid, 3 Cuneiforms7
MetatarsusMetatarsals 1-55
ToesPhalanges14
Total (one limb)30

Key Identification Tips (Siding Mnemonics)

  • Femur: "Nutrient foramen flees the knee" (opens distally). Head is medial.
  • Tibia: "Nutrient foramen flees the knee." Medial malleolus is the distal medial bump.
  • Fibula: Nutrient foramen opens proximally (toward the knee) - opposite to the other long bones.
  • Patella: Falls toward the side it came from (larger lateral facet tips it).
  • 5th metatarsal: Only metatarsal with a prominent lateral base tuberosity.
  • Calcaneus: Only tarsal with a posterior heel projection (calcaneal tuber).
  • Talus: Only bone in the body with no muscle attachments.
Sources: Gray's Anatomy for Students (9780323934237), p. 639-658; Forensic Anthropology: A Comprehensive Introduction, 2e (9781498736121), pp. 122-128.

Create a study guide PDF on lower limb bone features and siding

Reading File
Running Command

mkdir -p /home/daytona/workspace/lower-limb-study && ls /home/daytona/workspace/…

Writing File

~/lower-limb-study/generate_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, PageBreak, KeepTogether
)
from reportlab.platypus.flowables import HRFlowable
from reportlab.lib.colors import HexColor

OUTPUT = "/home/daytona/workspace/lower-limb-study/Lower_Limb_Bone_Study_Guide.pdf"

# ── Colour palette ─────────────────────────────────────────────────────────────
NAVY      = HexColor("#1B3A6B")
TEAL      = HexColor("#1A7A8A")
GOLD      = HexColor("#E8A020")
LIGHT_BG  = HexColor("#F0F5FA")
ROW_ALT   = HexColor("#E8F2F8")
WHITE     = colors.white
BLACK     = colors.black
DARK_GREY = HexColor("#333333")
MED_GREY  = HexColor("#666666")
SIDE_CLR  = HexColor("#FFF3CD")   # warm yellow for siding rows

# ── Styles ──────────────────────────────────────────────────────────────────────
def make_styles():
    base = getSampleStyleSheet()

    cover_title = ParagraphStyle("cover_title",
        fontName="Helvetica-Bold", fontSize=30, textColor=WHITE,
        alignment=TA_CENTER, spaceAfter=8, leading=36)

    cover_sub = ParagraphStyle("cover_sub",
        fontName="Helvetica", fontSize=14, textColor=HexColor("#CCDFEE"),
        alignment=TA_CENTER, spaceAfter=4)

    cover_source = ParagraphStyle("cover_source",
        fontName="Helvetica-Oblique", fontSize=9, textColor=HexColor("#AACCDD"),
        alignment=TA_CENTER)

    h1 = ParagraphStyle("h1",
        fontName="Helvetica-Bold", fontSize=16, textColor=WHITE,
        spaceAfter=4, spaceBefore=10, leading=20)

    h2 = ParagraphStyle("h2",
        fontName="Helvetica-Bold", fontSize=12, textColor=NAVY,
        spaceAfter=3, spaceBefore=8, leading=15)

    h3 = ParagraphStyle("h3",
        fontName="Helvetica-Bold", fontSize=10, textColor=TEAL,
        spaceAfter=2, spaceBefore=5)

    body = ParagraphStyle("body",
        fontName="Helvetica", fontSize=9, textColor=DARK_GREY,
        spaceAfter=4, leading=13, alignment=TA_JUSTIFY)

    bullet = ParagraphStyle("bullet",
        fontName="Helvetica", fontSize=9, textColor=DARK_GREY,
        spaceAfter=2, leading=12, leftIndent=12, bulletIndent=0)

    note = ParagraphStyle("note",
        fontName="Helvetica-Oblique", fontSize=8, textColor=MED_GREY,
        spaceAfter=3, leading=11)

    mnemonic = ParagraphStyle("mnemonic",
        fontName="Helvetica-Bold", fontSize=9, textColor=HexColor("#5C3D00"),
        spaceAfter=2, leading=12, leftIndent=8)

    tbl_hdr = ParagraphStyle("tbl_hdr",
        fontName="Helvetica-Bold", fontSize=8.5, textColor=WHITE,
        alignment=TA_LEFT)

    tbl_cell = ParagraphStyle("tbl_cell",
        fontName="Helvetica", fontSize=8.5, textColor=DARK_GREY,
        leading=11, alignment=TA_LEFT)

    tbl_bold = ParagraphStyle("tbl_bold",
        fontName="Helvetica-Bold", fontSize=8.5, textColor=DARK_GREY,
        leading=11)

    page_num = ParagraphStyle("page_num",
        fontName="Helvetica", fontSize=8, textColor=MED_GREY,
        alignment=TA_CENTER)

    return dict(cover_title=cover_title, cover_sub=cover_sub,
                cover_source=cover_source, h1=h1, h2=h2, h3=h3,
                body=body, bullet=bullet, note=note, mnemonic=mnemonic,
                tbl_hdr=tbl_hdr, tbl_cell=tbl_cell, tbl_bold=tbl_bold,
                page_num=page_num)

S = make_styles()

# ── Table helpers ───────────────────────────────────────────────────────────────
def make_table(headers, rows, col_widths, alt_rows=True, siding_col=None):
    """Build a styled table.  siding_col = index of a 'Siding' header row (highlighted)."""
    data = [[Paragraph(h, S["tbl_hdr"]) for h in headers]]
    for i, row in enumerate(rows):
        data.append([Paragraph(str(cell), S["tbl_cell"]) for cell in row])

    style = [
        # Header
        ("BACKGROUND", (0, 0), (-1, 0), NAVY),
        ("TOPPADDING",  (0, 0), (-1, 0), 5),
        ("BOTTOMPADDING",(0, 0), (-1, 0), 5),
        ("LEFTPADDING", (0, 0), (-1, -1), 6),
        ("RIGHTPADDING",(0, 0), (-1, -1), 6),
        ("GRID", (0, 0), (-1, -1), 0.4, HexColor("#BBCDD8")),
        ("ROWBACKGROUNDS", (0, 1), (-1, -1),
         [WHITE, ROW_ALT] if alt_rows else [WHITE]),
        ("VALIGN", (0, 0), (-1, -1), "TOP"),
        ("TOPPADDING", (0, 1), (-1, -1), 4),
        ("BOTTOMPADDING", (0, 1), (-1, -1), 4),
    ]

    t = Table(data, colWidths=col_widths, repeatRows=1)
    t.setStyle(TableStyle(style))
    return t


def section_header(title, subtitle=None):
    """Navy banner with white title text."""
    inner = [Paragraph(title, S["h1"])]
    if subtitle:
        inner.append(Paragraph(subtitle, ParagraphStyle(
            "banner_sub", fontName="Helvetica-Oblique", fontSize=9,
            textColor=HexColor("#AACCDD"), spaceAfter=0)))

    tbl = Table([[inner]], colWidths=[17*cm])
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), NAVY),
        ("LEFTPADDING", (0,0), (-1,-1), 10),
        ("RIGHTPADDING",(0,0), (-1,-1), 10),
        ("TOPPADDING",  (0,0), (-1,-1), 7),
        ("BOTTOMPADDING",(0,0), (-1,-1), 7),
        ("ROUNDEDCORNERS", [4]),
    ]))
    return tbl


def siding_box(text):
    """Gold-background siding tip box."""
    inner = [Paragraph("<b>SIDING TIP</b>", ParagraphStyle(
                "stip_hdr", fontName="Helvetica-Bold", fontSize=8.5,
                textColor=HexColor("#7A5000"))),
             Paragraph(text, ParagraphStyle(
                "stip_body", fontName="Helvetica", fontSize=8.5,
                textColor=HexColor("#3D2800"), leading=12))]
    tbl = Table([[inner]], colWidths=[17*cm])
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), HexColor("#FFF3CD")),
        ("LEFTPADDING", (0,0), (-1,-1), 10),
        ("RIGHTPADDING",(0,0), (-1,-1), 10),
        ("TOPPADDING",  (0,0), (-1,-1), 6),
        ("BOTTOMPADDING",(0,0), (-1,-1), 6),
        ("BOX", (0,0), (-1,-1), 1.2, GOLD),
        ("ROUNDEDCORNERS", [3]),
    ]))
    return tbl


def info_box(text, colour=LIGHT_BG, border=TEAL):
    inner = Paragraph(text, S["body"])
    tbl = Table([[inner]], colWidths=[17*cm])
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), colour),
        ("LEFTPADDING", (0,0), (-1,-1), 10),
        ("TOPPADDING",  (0,0), (-1,-1), 6),
        ("BOTTOMPADDING",(0,0), (-1,-1), 6),
        ("BOX", (0,0), (-1,-1), 1, border),
    ]))
    return tbl


# ── Page callbacks ──────────────────────────────────────────────────────────────
def on_later_page(canvas, doc):
    canvas.saveState()
    w, h = A4
    # Top bar
    canvas.setFillColor(NAVY)
    canvas.rect(0, h - 1.1*cm, w, 1.1*cm, fill=1, stroke=0)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica-Bold", 9)
    canvas.drawCentredString(w/2, h - 0.72*cm,
        "Lower Limb Bone Identification & Siding – Study Guide")
    # Bottom bar
    canvas.setFillColor(LIGHT_BG)
    canvas.rect(0, 0, w, 0.85*cm, fill=1, stroke=0)
    canvas.setFillColor(MED_GREY)
    canvas.setFont("Helvetica", 8)
    canvas.drawCentredString(w/2, 0.32*cm,
        f"Page {doc.page}  |  Sources: Gray's Anatomy for Students · Forensic Anthropology (2e)")
    canvas.restoreState()


def on_first_page(canvas, doc):
    on_later_page(canvas, doc)


# ── Document build ──────────────────────────────────────────────────────────────
def build_pdf():
    doc = SimpleDocTemplate(
        OUTPUT,
        pagesize=A4,
        leftMargin=2*cm, rightMargin=2*cm,
        topMargin=1.8*cm, bottomMargin=1.8*cm,
        title="Lower Limb Bone Study Guide",
        author="Orris Medical Education",
    )

    story = []
    SP = Spacer

    # ── COVER ──────────────────────────────────────────────────────────────────
    # Full-page navy cover box
    cover_data = [[
        [
            SP(1, 2.5*cm),
            Paragraph("Lower Limb Bone", S["cover_title"]),
            Paragraph("Identification &amp; Siding", S["cover_title"]),
            SP(1, 0.4*cm),
            HRFlowable(width="60%", color=GOLD, thickness=2),
            SP(1, 0.4*cm),
            Paragraph("Comprehensive Study Guide for Anatomy &amp; Forensic Anthropology", S["cover_sub"]),
            SP(1, 1*cm),
            Paragraph("Femur · Patella · Tibia · Fibula · Tarsals · Metatarsals · Phalanges", S["cover_sub"]),
            SP(1, 1.5*cm),
            Paragraph("Sources: Gray's Anatomy for Students (9780323934237) &amp; "
                       "Forensic Anthropology: A Comprehensive Introduction, 2e (9781498736121)",
                       S["cover_source"]),
            SP(1, 0.5*cm),
        ]
    ]]
    cover = Table(cover_data, colWidths=[17*cm], rowHeights=[22*cm])
    cover.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), NAVY),
        ("LEFTPADDING", (0,0), (-1,-1), 20),
        ("RIGHTPADDING",(0,0), (-1,-1), 20),
        ("VALIGN", (0,0), (-1,-1), "MIDDLE"),
    ]))
    story.append(cover)
    story.append(PageBreak())

    # ── OVERVIEW ───────────────────────────────────────────────────────────────
    story.append(section_header("Overview: Bones of the Lower Limb",
                                "30 bones per limb | 4 anatomical regions"))
    story.append(SP(1, 0.3*cm))

    overview_rows = [
        ["Thigh", "Femur", "1", "Hip joint → Knee joint"],
        ["Knee", "Patella", "1", "Sesamoid in quadriceps tendon"],
        ["Leg", "Tibia + Fibula", "2", "Knee joint → Ankle joint"],
        ["Tarsus", "Talus, Calcaneus, Navicular, Cuboid, 3 Cuneiforms", "7", "Proximal foot"],
        ["Metatarsus", "Metatarsals 1–5", "5", "Midfoot arch"],
        ["Toes", "Phalanges (2 in hallux, 3 in toes 2–5)", "14", "Distal foot"],
        ["TOTAL", "", "30", ""],
    ]
    story.append(make_table(
        ["Region", "Bones", "Count", "Location"],
        overview_rows,
        [3*cm, 6.5*cm, 2*cm, 5.5*cm]
    ))
    story.append(SP(1, 0.4*cm))

    story.append(info_box(
        "<b>Siding rules – general principles:</b> Once you orient the bone proximally vs. distally, "
        "identify which surface is anterior (smooth/articular) vs. posterior (ridges/foramina). "
        "Nutrient foramina on the femur and tibia open <b>away from the knee</b> (distally); "
        "the fibula foramen opens <b>toward the knee</b> (proximally). "
        "The lateral malleolus (fibula) descends <b>more distally</b> than the medial malleolus (tibia)."
    ))
    story.append(SP(1, 0.5*cm))

    # ── FEMUR ─────────────────────────────────────────────────────────────────
    story.append(section_header("1. Femur", "Longest and heaviest bone in the body"))
    story.append(SP(1, 0.3*cm))
    story.append(Paragraph(
        "The femur articulates proximally with the acetabulum (hip joint) and distally with the tibia "
        "and patella (knee joint). Its shaft angles 7° from vertical so the distal end is closer to "
        "the midline than the proximal end.",
        S["body"]))
    story.append(SP(1, 0.3*cm))

    story.append(Paragraph("Proximal End", S["h2"]))
    femur_prox = [
        ["Head", "Spherical (more so than humeral head). Articulates with acetabulum via ball-and-socket joint."],
        ["Fovea capitis", "Small pit on medial surface of head. Attachment for ligamentum teres."],
        ["Neck", "Cylindrical strut; projects supero-medially ~125° to shaft, slightly forward."],
        ["Greater trochanter", "Large lateral prominence. Insertions: gluteus minimus, gluteus medius, obturator internus, piriformis."],
        ["Trochanteric fossa", "Deep groove on posterior-medial surface of greater trochanter."],
        ["Lesser trochanter", "Smaller, blunt, posteromedial projection. Attachment: iliopsoas (psoas major + iliacus)."],
        ["Intertrochanteric line", "Anterior ridge connecting the two trochanters."],
        ["Intertrochanteric crest", "Posterior ridge; bears the quadrate tubercle for quadratus femoris."],
    ]
    story.append(make_table(["Feature", "Description"], femur_prox, [4.5*cm, 12.5*cm]))
    story.append(SP(1, 0.3*cm))

    story.append(Paragraph("Shaft", S["h2"]))
    femur_shaft = [
        ["Linea aspera", "Prominent posterior ridge; attachment for adductors, some quadriceps & hamstrings."],
        ["Pectineal line", "Proximal medial continuation of linea aspera (curls under lesser trochanter)."],
        ["Gluteal tuberosity", "Proximal lateral continuation of linea aspera; may form a 3rd trochanter."],
        ["Nutrient foramen", "Posterior surface near linea aspera. Opens DISTALLY ('flees the knee')."],
    ]
    story.append(make_table(["Feature", "Description"], femur_shaft, [4.5*cm, 12.5*cm]))
    story.append(SP(1, 0.3*cm))

    story.append(Paragraph("Distal End", S["h2"]))
    femur_distal = [
        ["Medial condyle", "Large articular surface; projects MORE distally than the lateral condyle."],
        ["Lateral condyle", "Articular surface for tibia; raised lateral lip guards against patellar dislocation."],
        ["Medial epicondyle", "Projection on medial condyle surface; ligamentous attachment."],
        ["Lateral epicondyle", "Projection on lateral condyle; ligament & muscle attachment."],
        ["Patellar articular surface", "Smooth anterior groove for patella glide during flexion/extension."],
        ["Intercondylar fossa", "Deep posterior groove between condyles; cruciate ligament attachments."],
        ["Popliteal surface", "Smooth triangular posterior area above intercondylar fossa."],
    ]
    story.append(make_table(["Feature", "Description"], femur_distal, [4.5*cm, 12.5*cm]))
    story.append(SP(1, 0.3*cm))

    story.append(siding_box(
        "Head is PROXIMAL and MEDIAL. Greater trochanter is LATERAL. Lesser trochanter and linea aspera "
        "are POSTERIOR. Patellar articular surface is ANTERIOR. Nutrient foramen opens DISTALLY "
        "('flees the knee'). The medial condyle projects more distally than the lateral condyle. "
        "Key distinction from humerus: femoral head is a full sphere; humeral head is hemispheric."
    ))
    story.append(SP(1, 0.5*cm))

    # ── PATELLA ──────────────────────────────────────────────────────────────
    story.append(section_header("2. Patella", "Largest sesamoid bone — the kneecap"))
    story.append(SP(1, 0.3*cm))
    story.append(Paragraph(
        "The patella develops and is encased within the quadriceps femoris tendon. It articulates "
        "with the patellar articular surface of the distal femur and improves the mechanical advantage "
        "of the quadriceps by acting as a pulley.",
        S["body"]))
    story.append(SP(1, 0.3*cm))

    patella_rows = [
        ["Apex", "Pointed non-articular inferior tip; points DISTALLY."],
        ["Base", "Broad superior aspect; attachment of quadriceps tendon."],
        ["Anterior surface", "Rough, convex; no articular cartilage. Palpable in vivo."],
        ["Medial articular facet", "Posterior surface — SMALLER of the two facets."],
        ["Lateral articular facet", "Posterior surface — LARGER of the two facets."],
    ]
    story.append(make_table(["Feature", "Description"], patella_rows, [4.5*cm, 12.5*cm]))
    story.append(SP(1, 0.3*cm))

    story.append(siding_box(
        "Place the patella on a flat surface with the articular processes touching the surface and "
        "apex pointing AWAY from you. The patella will fall toward the side it came from — "
        "because the LARGER articular facet is LATERAL and tips it that way."
    ))
    story.append(SP(1, 0.5*cm))

    # ── TIBIA ─────────────────────────────────────────────────────────────────
    story.append(PageBreak())
    story.append(section_header("3. Tibia", "Larger, medial bone of the leg — the shin bone"))
    story.append(SP(1, 0.3*cm))
    story.append(Paragraph(
        "The tibia supports the majority of weight placed on the leg. It articulates superiorly "
        "with the femoral condyles, laterally with the fibula at both ends, and distally with "
        "the talus to form the ankle joint.",
        S["body"]))
    story.append(SP(1, 0.3*cm))

    story.append(Paragraph("Proximal End", S["h2"]))
    tibia_prox = [
        ["Tibial plateau", "Proximal articular surface for femoral condyles; divided into medial and lateral condyles."],
        ["Medial condyle", "Larger, oval; slightly concave articular surface."],
        ["Lateral condyle", "Smaller; has the superior fibular articular facet on its postero-inferior surface."],
        ["Tibial tuberosity", "Anterior prominence just below the plateau; attachment for the patellar ligament."],
        ["Gerdy's tubercle", "Anterolateral condyle; attachment for iliotibial band."],
    ]
    story.append(make_table(["Feature", "Description"], tibia_prox, [4.5*cm, 12.5*cm]))
    story.append(SP(1, 0.3*cm))

    story.append(Paragraph("Shaft", S["h2"]))
    tibia_shaft = [
        ["Anterior crest", "Sharp ridge forming the palpable 'shin.' Runs from tibial tuberosity to medial malleolus."],
        ["Interosseous crest", "Lateral sharp ridge; attachment for interosseous membrane binding tibia to fibula."],
        ["Nutrient foramen", "Posterior surface, proximal to midshaft. Opens DISTALLY ('flees the knee')."],
        ["Soleal line", "Oblique posterior ridge near proximal end; origin of soleus muscle."],
    ]
    story.append(make_table(["Feature", "Description"], tibia_shaft, [4.5*cm, 12.5*cm]))
    story.append(SP(1, 0.3*cm))

    story.append(Paragraph("Distal End", S["h2"]))
    tibia_distal = [
        ["Medial malleolus", "Bony projection on disto-MEDIAL tibia. Forms the medial ankle bulge; articulates with talus."],
        ["Fibular notch", "Disto-lateral concavity; site of the distal tibiofibular syndesmosis."],
        ["Inferior fibular articular surface", "Articular surface on inferior fibular notch — part of ankle mortise."],
        ["Inferior articular surface", "Distal face of tibia; articulates with superior trochlea of talus."],
    ]
    story.append(make_table(["Feature", "Description"], tibia_distal, [4.5*cm, 12.5*cm]))
    story.append(SP(1, 0.3*cm))

    story.append(siding_box(
        "Tibial plateau is PROXIMAL. Medial malleolus is DISTAL and MEDIAL. Fibular notch is DISTAL "
        "and LATERAL. Tibial tuberosity and anterior crest are ANTERIOR. Nutrient foramen opens "
        "DISTALLY ('flees the knee'). Soleal line is on the POSTERIOR surface."
    ))
    story.append(SP(1, 0.5*cm))

    # ── FIBULA ────────────────────────────────────────────────────────────────
    story.append(section_header("4. Fibula", "Smaller, lateral bone of the leg — non-weight-bearing"))
    story.append(SP(1, 0.3*cm))
    story.append(Paragraph(
        "The fibula is a slender bone providing lateral ankle stability and muscle attachment "
        "surfaces. It bears virtually no body weight — that function belongs to the tibia. "
        "The common fibular (peroneal) nerve winds around the fibular neck and is vulnerable "
        "to injury there.",
        S["body"]))
    story.append(SP(1, 0.3*cm))

    fibula_rows = [
        ["Head", "Proximal end; articulates with postero-inferior surface of lateral tibial condyle."],
        ["Neck", "Just distal to head. Common fibular nerve passes here — clinically important."],
        ["Shaft", "Long, slender, quadrilateral/triangular cross-section."],
        ["Interosseous crest", "Medial ridge; attachment for interosseous membrane (faces tibia)."],
        ["Nutrient foramen", "Opens PROXIMALLY — toward the knee (OPPOSITE to femur and tibia)."],
        ["Lateral malleolus", "Distal end; forms lateral ankle bulge. Extends MORE distally than medial malleolus."],
        ["Malleolar articular surface", "Medial surface of lateral malleolus; articulates with lateral surface of talus."],
    ]
    story.append(make_table(["Feature", "Description"], fibula_rows, [4.5*cm, 12.5*cm]))
    story.append(SP(1, 0.3*cm))

    story.append(siding_box(
        "Head is PROXIMAL. Lateral malleolus is DISTAL. Interosseous crest faces MEDIALLY (toward tibia). "
        "Nutrient foramen opens PROXIMALLY ('toward the knee') — opposite to the femur and tibia. "
        "The lateral malleolus extends more DISTALLY than the medial malleolus (tibia)."
    ))
    story.append(SP(1, 0.5*cm))

    # ── TARSALS ───────────────────────────────────────────────────────────────
    story.append(PageBreak())
    story.append(section_header("5. Tarsal Bones (7)", "Proximal foot skeleton"))
    story.append(SP(1, 0.3*cm))

    tarsal_rows = [
        ["Talus", "Trochlea (pulley body), head, neck",
         "Tibia & fibula above; calcaneus below; navicular anteriorly",
         "ONLY bone in the body with NO muscle attachments. Trochlea wider anteriorly."],
        ["Calcaneus", "Calcaneal tuber (heel), sustentaculum tali, anterior articular surface",
         "Talus above; cuboid anteriorly",
         "Largest tarsal. Sustentaculum tali supports talus medially."],
        ["Navicular", "Concave proximal surface, 3-part distal surface, medial tubercle",
         "Talus proximally; 3 cuneiforms distally",
         "Bowl-shaped. Medial tubercle is palpable. Concave surface faces the talus."],
        ["Cuboid", "Cuboid tuberosity (infero-lateral), groove for fibularis longus",
         "Calcaneus proximally; navicular & lat. cuneiform medially; MT 4–5 distally",
         "Lateral foot. Peroneal groove on inferior surface."],
        ["Medial (1st) cuneiform", "L-shaped facet medially",
         "Navicular proximally; 1st MT distally; 2nd cuneiform laterally",
         "LARGEST cuneiform."],
        ["Intermediate (2nd) cuneiform", "Pistol-shaped facet",
         "Navicular proximally; 2nd MT distally",
         "SMALLEST cuneiform."],
        ["Lateral (3rd) cuneiform", "Butterfly-wing double facet",
         "Navicular proximally; 3rd MT distally; cuboid laterally",
         "Mid-sized cuneiform."],
    ]
    story.append(make_table(
        ["Bone", "Key Features", "Articulations", "ID / Siding Tips"],
        tarsal_rows,
        [2.8*cm, 4.2*cm, 5.2*cm, 4.8*cm]
    ))
    story.append(SP(1, 0.5*cm))

    # ── METATARSALS ───────────────────────────────────────────────────────────
    story.append(section_header("6. Metatarsals (5)", "Arch of the foot — each has a base, shaft, and head"))
    story.append(SP(1, 0.3*cm))

    mt_rows = [
        ["1st (Hallux)", "Shortest but most ROBUST. Single round head inferior groove.",
         "1st cuneiform", "Flat non-articular medial surface. Grooved inferior head."],
        ["2nd", "LONGEST metatarsal. Base keyed between 3 cuneiforms.",
         "2nd cuneiform (primarily)", "Most stable; most common 'march fracture' site."],
        ["3rd", "Intermediate length.",
         "Lateral cuneiform", "Standard morphology."],
        ["4th", "Slender shaft.",
         "Cuboid + lateral cuneiform", "Base articulates with cuboid laterally."],
        ["5th", "Styloid TUBEROSITY at lateral base (very prominent).",
         "Cuboid", "Only MT with large lateral base tuberosity. Avulsion fx here (peroneus brevis). Most lateral."],
    ]
    story.append(make_table(
        ["Metatarsal", "Key Feature", "Proximal Articulation", "ID Notes"],
        mt_rows,
        [2.5*cm, 5*cm, 4.5*cm, 5*cm]
    ))
    story.append(SP(1, 0.3*cm))
    story.append(info_box(
        "<b>General siding for metatarsals:</b> Base (concave/flat) is proximal; rounded head is distal. "
        "The lateral side of the head has an articular facet for the adjacent (lateral) metatarsal; "
        "the medial side has one for the adjacent (medial) metatarsal. The 1st MT has no medial facet. "
        "The 5th MT has no lateral facet. Use facet presence/absence plus the styloid to side the bone."
    ))
    story.append(SP(1, 0.5*cm))

    # ── PHALANGES ─────────────────────────────────────────────────────────────
    story.append(section_header("7. Phalanges (14)", "Toe bones — 2 in hallux, 3 in toes 2–5"))
    story.append(SP(1, 0.3*cm))

    pha_rows = [
        ["Proximal phalanx", "Largest of the three in each ray. Concave oval base (for MT head). Trochlear head."],
        ["Middle phalanx", "Absent in hallux. Trochlear base and head."],
        ["Distal phalanx", "Smallest. Ungual tuberosity at distal tip (supports nail bed)."],
    ]
    story.append(make_table(
        ["Type", "Key Features"],
        pha_rows,
        [4*cm, 13*cm]
    ))
    story.append(SP(1, 0.3*cm))
    story.append(info_box(
        "<b>Hallux vs. lesser toe phalanges:</b> Hallux (great toe) phalanges are considerably larger and "
        "more robust. The distal phalanx has a flat ungual tuberosity. For siding phalanges: "
        "The base is proximal (concave); the head is distal. Medial vs. lateral can be determined by "
        "articular facet orientation and any asymmetry of the base."
    ))
    story.append(SP(1, 0.5*cm))

    # ── QUICK-REFERENCE SIDING SUMMARY ────────────────────────────────────────
    story.append(PageBreak())
    story.append(section_header("Quick-Reference: Siding Summary",
                                "Essential rules for left vs. right identification"))
    story.append(SP(1, 0.3*cm))

    siding_summary = [
        ["Femur",
         "Head proximal & medial; GT lateral; Lesser trochanter posteromedial; "
         "Linea aspera posterior; Patellar surface anterior; "
         "Nutrient foramen opens DISTALLY."],
        ["Patella",
         "Apex distal; Larger articular facet is LATERAL — bone falls to its side of origin."],
        ["Tibia",
         "Plateau proximal; Medial malleolus distal-medial; Fibular notch distal-lateral; "
         "Tibial tuberosity & anterior crest anterior; "
         "Nutrient foramen opens DISTALLY."],
        ["Fibula",
         "Head proximal; Lateral malleolus distal (extends more distally than medial malleolus); "
         "Interosseous crest medial; "
         "Nutrient foramen opens PROXIMALLY (toward knee)."],
        ["Talus",
         "Trochlea superior; head/neck anterior; no muscle attachments. "
         "Lateral process larger than medial."],
        ["Calcaneus",
         "Calcaneal tuber posterior; sustentaculum tali medial; anterior facet for cuboid."],
        ["Navicular",
         "Concave surface proximal (faces talus); three-part surface distal; tubercle medial."],
        ["Cuboid",
         "Flat/non-articular surface lateral; tuberosity infero-lateral; "
         "'ballerina's foot' — toe points to side of origin."],
        ["1st cuneiform",
         "L-shaped facet anteriorly — tip of L points to side of origin."],
        ["2nd cuneiform",
         "Pistol-shaped facet — barrel points to side of origin."],
        ["3rd cuneiform",
         "Butterfly-wing double facet — narrower side to side of origin."],
        ["1st metatarsal",
         "Flat non-articular medial surface; grooved inferior head; NO medial facet."],
        ["5th metatarsal",
         "Prominent styloid tuberosity at lateral base; NO lateral facet. Most lateral."],
    ]
    story.append(make_table(
        ["Bone", "Siding Rule"],
        siding_summary,
        [3.5*cm, 13.5*cm]
    ))
    story.append(SP(1, 0.5*cm))

    # ── MNEMONICS & CLINICAL NOTES ─────────────────────────────────────────────
    story.append(section_header("Mnemonics & Clinical Pearls"))
    story.append(SP(1, 0.3*cm))

    mnemonics = [
        ("Nutrient foramen direction",
         "Femur & Tibia: foramen 'FLEES THE KNEE' (opens distally).\n"
         "Fibula: foramen FACES the knee (opens proximally) — the exception to the rule."),
        ("Medial vs. lateral malleolus height",
         "Lateral malleolus (fibula) sits LOWER (more distal) than the medial malleolus (tibia). "
         "Remember: 'Lateral is Lower.'"),
        ("Talus — the muscle-free bone",
         "The talus is the only bone in the body with NO muscular attachments — "
         "only ligamentous and articular connections. Useful for identification."),
        ("Femur vs. Humerus — head shape",
         "Femoral head = full SPHERE. Humeral head = HEMISPHERE. "
         "If it looks like a complete ball, it belongs to the lower limb."),
        ("March fracture",
         "Stress fracture through the 2nd (or 3rd) metatarsal shaft from repetitive loading — "
         "the 2nd MT is most tightly wedged between the cuneiforms and least mobile."),
        ("Peroneus brevis avulsion",
         "A forceful inversion of the ankle can avulse the styloid process of the 5th metatarsal "
         "where peroneus (fibularis) brevis inserts. Key differential from a Jones fracture "
         "(transverse fracture 1.5–2 cm distal to base of 5th MT)."),
        ("Fibular neck fracture",
         "The common fibular nerve wraps around the fibular neck. A fracture here "
         "causes foot drop (loss of dorsiflexion and eversion)."),
        ("Sustentaculum tali",
         "The medial shelf of the calcaneus that 'sustains' (supports) the head of the talus. "
         "The flexor hallucis longus tendon passes in a groove beneath it."),
    ]

    for title, text in mnemonics:
        row_data = [
            [Paragraph(title, S["h3"]),
             Paragraph(text.replace("\n", "<br/>"), S["body"])]
        ]
        t = Table(row_data, colWidths=[4.5*cm, 12.5*cm])
        t.setStyle(TableStyle([
            ("VALIGN", (0,0), (-1,-1), "TOP"),
            ("TOPPADDING", (0,0), (-1,-1), 4),
            ("BOTTOMPADDING", (0,0), (-1,-1), 4),
            ("LEFTPADDING", (0,0), (-1,-1), 4),
            ("LINEBELOW", (0,0), (-1,-1), 0.4, HexColor("#DDDDDD")),
        ]))
        story.append(t)

    story.append(SP(1, 0.5*cm))

    # ── SELF-TEST ─────────────────────────────────────────────────────────────
    story.append(PageBreak())
    story.append(section_header("Self-Test: Bone Feature Identification"))
    story.append(SP(1, 0.3*cm))
    story.append(Paragraph(
        "Cover the 'Answer' column and test yourself. These questions reflect the kind of "
        "identification challenges encountered in anatomy practicals and forensic anthropology labs.",
        S["body"]))
    story.append(SP(1, 0.3*cm))

    quiz = [
        ["1", "You find a bone with a spherical head, fovea capitis, greater and lesser trochanters, "
              "and a posterior linea aspera.", "Femur"],
        ["2", "A small triangular bone with a larger posterior facet on one side "
              "and a pointed inferior tip.", "Patella"],
        ["3", "A long bone with a tibial plateau, prominent anterior crest, "
              "medial malleolus, and nutrient foramen opening distally.", "Tibia"],
        ["4", "A slender long bone whose nutrient foramen opens proximally and "
              "whose distal end extends further than the corresponding tibia landmark.", "Fibula"],
        ["5", "The only tarsal bone with no muscle attachments, "
              "with a pulley-shaped superior surface.", "Talus"],
        ["6", "The largest tarsal bone, forming the heel, with a medial shelf "
              "supporting another tarsal bone.", "Calcaneus"],
        ["7", "A tarsal bone with a bowl-shaped concave proximal surface "
              "and a three-part distal articular surface.", "Navicular"],
        ["8", "The shortest but most robust metatarsal, with a grooved inferior head "
              "and a flat non-articular medial surface.", "1st Metatarsal"],
        ["9", "A metatarsal with a very prominent lateral styloid process at its base; "
              "common site of avulsion fracture.", "5th Metatarsal"],
        ["10", "The smallest cuneiform, with a pistol-shaped articular facet.", "Intermediate (2nd) Cuneiform"],
        ["11", "You are siding a femur. The nutrient foramen opens toward the distal end. "
               "The head is on the LEFT side of the bone. Which side?", "LEFT femur"],
        ["12", "You are siding a fibula. The lateral malleolus is in your hand. "
               "The interosseous crest (roughened medial border) faces left. Which side?", "LEFT fibula"],
    ]

    story.append(make_table(
        ["#", "Clues", "Answer"],
        quiz,
        [0.8*cm, 11.2*cm, 5*cm]
    ))

    story.append(SP(1, 0.6*cm))
    story.append(Paragraph(
        "Sources: Gray's Anatomy for Students, 4e (ISBN 9780323934237) · "
        "Forensic Anthropology: A Comprehensive Introduction, 2e (ISBN 9781498736121)",
        S["note"]))

    # ── BUILD ──────────────────────────────────────────────────────────────────
    doc.build(story,
              onFirstPage=on_first_page,
              onLaterPages=on_later_page)
    print(f"PDF created: {OUTPUT}")


if __name__ == "__main__":
    build_pdf()
Running Command

cd /home/daytona/workspace/lower-limb-study && python generate_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/lower-limb-study/Lower_Limb_Bone_Study_Guide.pdf

Your study guide PDF is ready:

Lower Limb Bone Study Guide

PDF Document · PDF


What's inside (5 pages):
SectionContent
CoverTitle page with navy/gold design
OverviewComplete bone count table — 30 bones per limb across 6 regions
FemurProximal end, shaft, and distal end feature tables with siding tip box
PatellaFeatures + the "falls to its side" siding rule
TibiaProximal, shaft, and distal feature tables + siding box
FibulaAll features including the reversed nutrient foramen rule
Tarsals (7)Combined table with key features, articulations, and siding tips for all 7
Metatarsals (5)ID notes and siding logic for each metatarsal
PhalangesHallux vs. lesser toe distinctions
Siding SummaryOne-line rule for every bone — quick-reference format
Mnemonics & Clinical Pearls8 high-yield rules (nutrient foramina, march fracture, Jones fracture, etc.)
Self-Test12 identification/siding questions with answers
Sources cited throughout: Gray's Anatomy for Students and Forensic Anthropology: A Comprehensive Introduction, 2e.
This is a shared conversation. Sign in to Orris to start your own chat.