Forces acting on hip joint & PathoMechanics of hip joint MPT level 15 marks answer

| Activity | Force on Hip Joint |
|---|---|
| Lifting leg from bed (straight-leg raise) | 1.5 × BW |
| Double limb stance (quiet standing) | ~BW |
| Single limb stance | 3 × BW |
| Walking (gait cycle - stance phase) | 3-5 × BW (analytical models: up to 5.0×; instrumented prostheses: 2.6-3.0×) |
| Running / jumping | Up to 10 × BW |
"Calculated peak contact forces across the hip joint during gait range from 3.5 to 5.0 times the body weight and up to six times the body weight during single-limb stance." - Campbell's Operative Orthopaedics, 15th Ed

| Factor | Effect on JRF |
|---|---|
| Increasing body weight | Increases JRF proportionally |
| Walking with a cane (contralateral hand) | Reduces JRF by ~30% |
| Trendelenburg lean (lateral trunk shift toward stance leg) | Reduces external adduction moment arm, reduces abductor force needed, reduces JRF |
| Arthritis (loss of femoral head height) | Shortens abductor lever arm → increases ratio → increases JRF |
| Coxa valga (increased neck-shaft angle) | Decreases abductor moment arm → higher abductor force → higher JRF |
| Coxa vara (decreased neck-shaft angle) | Increases abductor moment arm → lower abductor force needed → lower JRF |
| Medialization of acetabulum | Shortens body weight lever arm → reduces JRF (Charnley principle) |
| Lengthening abductor lever arm (high-offset stem, lateral trochanteric transfer) | Reduces required abductor force → reduces JRF |

| Principle | Clinical Relevance |
|---|---|
| JRF = BW + Abductor muscle force | JRF is always GREATER than BW |
| Lever arm ratio = 2.5:1 (BW:abductor) | Explains why muscles must exert >> BW |
| Single-limb stance = 3× BW | Basis of Trendelenburg test interpretation |
| Cane in opposite hand | Reduces JRF (increases abductor lever arm effectively) |
| Charnley's principle (medialization + high offset) | Reduces JRF by optimizing lever arms |
| Trunk lean toward stance leg | Reduces external moment → reduces JRF |
| Coxa valga + dysplasia = highest stress | Explains why this combination leads to early OA |
Create a study guide document on hip biomechanics for exam prep
ls /home/daytona/workspace/ && python3 -c "import reportlab; print('reportlab ok')"
mkdir -p /home/daytona/workspace/hip-biomechanics-guide
~/hip-biomechanics-guide/generate_guide.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.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import Flowable
import reportlab.rl_config
OUTPUT = "/home/daytona/workspace/hip-biomechanics-guide/Hip_Biomechanics_MPT_Study_Guide.pdf"
# ── colour palette ──────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1a3a5c")
TEAL = colors.HexColor("#0d7377")
GOLD = colors.HexColor("#e8a020")
LTBLUE = colors.HexColor("#e8f4f8")
LTYELL = colors.HexColor("#fff8e1")
LTGREEN = colors.HexColor("#e8f5e9")
LTRED = colors.HexColor("#fce4ec")
WHITE = colors.white
GRAY = colors.HexColor("#555555")
LGRAY = colors.HexColor("#f5f5f5")
DKGRAY = colors.HexColor("#333333")
PAGE_W, PAGE_H = A4
MARGIN = 2 * cm
# ── document ─────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=MARGIN, rightMargin=MARGIN,
topMargin=MARGIN, bottomMargin=MARGIN,
title="Hip Biomechanics - MPT Study Guide",
author="Orris Medical Education"
)
styles = getSampleStyleSheet()
W = PAGE_W - 2 * MARGIN # usable width
# ── custom paragraph styles ───────────────────────────────────────────────────
def PS(name, parent="Normal", **kw):
return ParagraphStyle(name, parent=styles[parent], **kw)
cover_title = PS("CoverTitle", fontSize=30, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=36)
cover_sub = PS("CoverSub", fontSize=14, textColor=colors.HexColor("#d0e8f5"),
fontName="Helvetica", alignment=TA_CENTER, leading=20)
cover_note = PS("CoverNote", fontSize=10, textColor=colors.HexColor("#a0c8e0"),
fontName="Helvetica-Oblique", alignment=TA_CENTER)
h1 = PS("H1", fontSize=16, textColor=WHITE, fontName="Helvetica-Bold",
spaceBefore=4, spaceAfter=6, leading=20, alignment=TA_LEFT)
h2 = PS("H2", fontSize=12, textColor=NAVY, fontName="Helvetica-Bold",
spaceBefore=10, spaceAfter=4, leading=15)
h3 = PS("H3", fontSize=10.5, textColor=TEAL, fontName="Helvetica-Bold",
spaceBefore=7, spaceAfter=3, leading=13)
body = PS("Body", fontSize=9.5, textColor=DKGRAY,
fontName="Helvetica", spaceAfter=4, leading=14, alignment=TA_JUSTIFY)
bullet= PS("Bullet", fontSize=9.5, textColor=DKGRAY,
fontName="Helvetica", leftIndent=14, firstLineIndent=-10,
spaceAfter=3, leading=13)
small = PS("Small", fontSize=8.5, textColor=GRAY,
fontName="Helvetica-Oblique", spaceAfter=2, leading=12)
bold_body = PS("BoldBody", fontSize=9.5, textColor=DKGRAY,
fontName="Helvetica-Bold", spaceAfter=3, leading=13)
tbl_hdr = PS("TblHdr", fontSize=9, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=12)
tbl_cell = PS("TblCell", fontSize=8.5, textColor=DKGRAY,
fontName="Helvetica", alignment=TA_LEFT, leading=12)
tbl_cell_c = PS("TblCellC", fontSize=8.5, textColor=DKGRAY,
fontName="Helvetica", alignment=TA_CENTER, leading=12)
highlight_p = PS("HighlightP", fontSize=9.5, textColor=DKGRAY,
fontName="Helvetica", spaceAfter=3, leading=13,
borderPad=6, leftIndent=8, rightIndent=8)
exam_tip = PS("ExamTip", fontSize=9, textColor=colors.HexColor("#b71c1c"),
fontName="Helvetica-Bold", spaceAfter=2, leading=13)
# ── helper flowables ──────────────────────────────────────────────────────────
def section_header(text, color=NAVY):
"""Coloured banner heading."""
tbl = Table([[Paragraph(text, h1)]], colWidths=[W])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), color),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 10),
("RIGHTPADDING", (0,0),(-1,-1), 10),
("ROUNDEDCORNERS", [4]),
]))
return tbl
def colored_box(content_rows, bg=LTBLUE, border=TEAL):
"""Box with coloured background for key-point blocks."""
tbl = Table([[r] for r in content_rows], colWidths=[W - 0.4*cm])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("LINEABOVE", (0,0), (-1,0), 1, border),
("LINEBELOW", (0,-1),(-1,-1), 1, border),
("LINEBEFORE", (0,0), (0,-1), 3, border),
("LINEAFTER", (-1,0),(-1,-1), 0.5, border),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
return tbl
def two_col(left_items, right_items, left_w_frac=0.5):
lw = W * left_w_frac - 5
rw = W * (1 - left_w_frac) - 5
rows = []
n = max(len(left_items), len(right_items))
for i in range(n):
l = left_items[i] if i < len(left_items) else Paragraph("", body)
r = right_items[i] if i < len(right_items) else Paragraph("", body)
rows.append([l, r])
tbl = Table(rows, colWidths=[lw, rw])
tbl.setStyle(TableStyle([
("VALIGN", (0,0),(-1,-1), "TOP"),
("TOPPADDING", (0,0),(-1,-1), 2),
("BOTTOMPADDING",(0,0),(-1,-1), 2),
("LEFTPADDING", (0,0),(-1,-1), 4),
("RIGHTPADDING",(0,0),(-1,-1), 4),
]))
return tbl
def data_table(headers, rows, col_widths=None):
data = [[Paragraph(h, tbl_hdr) for h in headers]]
for row in rows:
data.append([Paragraph(str(c), tbl_cell) for c in row])
tbl = Table(data, colWidths=col_widths or [W/len(headers)]*len(headers))
style = [
("BACKGROUND", (0,0),(-1,0), NAVY),
("BACKGROUND", (0,1),(-1,-1), LGRAY),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, LGRAY]),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#cccccc")),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 6),
("RIGHTPADDING", (0,0),(-1,-1), 6),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("LINEBELOW", (0,0),(-1,0), 1, TEAL),
]
for i in range(1, len(rows)+1, 2):
style.append(("BACKGROUND", (0,i),(-1,i), LTBLUE))
tbl.setStyle(TableStyle(style))
return tbl
def hr():
return HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#cccccc"),
spaceAfter=6, spaceBefore=6)
def sp(h=6):
return Spacer(1, h)
def b(txt): return f"<b>{txt}</b>"
def it(txt): return f"<i>{txt}</i>"
def col(txt, c): return f'<font color="{c}">{txt}</font>'
def exam_box(text):
"""Red-bordered exam tip box."""
inner = [
Paragraph(col("EXAM TIP", "#b71c1c"), exam_tip),
Paragraph(text, PS("ETBody", fontSize=9, textColor=DKGRAY,
fontName="Helvetica", leading=13)),
]
return colored_box(inner, bg=LTRED, border=colors.HexColor("#b71c1c"))
def key_box(text):
inner = [Paragraph(col("KEY POINT", "#0d7377"), PS("KPH", fontSize=9,
textColor=TEAL, fontName="Helvetica-Bold", leading=12)),
Paragraph(text, PS("KPB", fontSize=9, textColor=DKGRAY,
fontName="Helvetica", leading=13))]
return colored_box(inner, bg=LTBLUE, border=TEAL)
def formula_box(formula_text):
tbl = Table([[Paragraph(formula_text,
PS("FML", fontSize=11, textColor=NAVY, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=16))]],
colWidths=[W - 2*cm])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), colors.HexColor("#e3f0ff")),
("BOX", (0,0),(-1,-1), 1.5, NAVY),
("TOPPADDING", (0,0),(-1,-1), 10),
("BOTTOMPADDING", (0,0),(-1,-1), 10),
("LEFTPADDING", (0,0),(-1,-1), 20),
("RIGHTPADDING", (0,0),(-1,-1), 20),
("ALIGN", (0,0),(-1,-1), "CENTER"),
]))
return tbl
# ════════════════════════════════════════════════════════════════════════════
# BUILD CONTENT
# ════════════════════════════════════════════════════════════════════════════
story = []
# ── COVER PAGE ────────────────────────────────────────────────────────────────
cover_bg = Table(
[[Paragraph("HIP JOINT BIOMECHANICS", cover_title)],
[Paragraph("Forces & Pathomechanics", cover_sub)],
[sp(6)],
[Paragraph("MPT Exam Preparation Study Guide", cover_sub)],
[sp(10)],
[Paragraph("Based on: Campbell's Operative Orthopaedics (15th Ed 2026) | "
"Bailey & Love's Short Practice of Surgery (28th Ed) | "
"Firestein & Kelley's Textbook of Rheumatology | "
"Miller's Review of Orthopaedics (9th Ed)", cover_note)],
[sp(6)],
[Paragraph("Orris Medical Education • June 2026", cover_note)],
],
colWidths=[W]
)
cover_bg.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), NAVY),
("TOPPADDING", (0,0),(-1,-1), 30),
("BOTTOMPADDING", (0,0),(-1,-1), 30),
("LEFTPADDING", (0,0),(-1,-1), 20),
("RIGHTPADDING", (0,0),(-1,-1), 20),
("ROUNDEDCORNERS", [8]),
]))
story.append(sp(40))
story.append(cover_bg)
story.append(sp(20))
toc_data = [
["1", "Basic Concepts & Terminology"],
["2", "Forces Acting on the Hip Joint"],
["3", "Lever Arm Mechanics & Moment Analysis"],
["4", "Activity-Specific Hip Forces"],
["5", "Pathomechanics of the Hip"],
["6", "Gait Deviations"],
["7", "Clinical Applications & Interventions"],
["8", "Quick-Reference Summary Tables"],
["9", "High-Yield Exam MCQs & SAQs"],
]
toc_tbl = Table(
[[Paragraph(b("CONTENTS"), PS("TOC_H", fontSize=13, textColor=NAVY,
fontName="Helvetica-Bold", alignment=TA_LEFT))]]+
[[Paragraph(f" {r[0]}.", tbl_cell_c),
Paragraph(r[1], PS("TOCItem", fontSize=10, textColor=NAVY,
fontName="Helvetica", leading=16))] for r in toc_data],
colWidths=[0.7*cm, W-0.7*cm]
)
toc_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), LTBLUE),
("LINEBELOW", (0,0),(-1,0), 1, TEAL),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 8),
("GRID", (0,1),(-1,-1), 0.3, colors.HexColor("#dddddd")),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, LGRAY]),
]))
story.append(toc_tbl)
story.append(PageBreak())
# ── SECTION 1: BASIC CONCEPTS ─────────────────────────────────────────────────
story.append(section_header("1. BASIC CONCEPTS & TERMINOLOGY"))
story.append(sp(8))
story.append(Paragraph("1.1 The Hip Joint", h2))
story.append(Paragraph(
"The hip is a ball-and-socket (enarthrodial) synovial joint formed by the "
"femoral head articulating with the acetabulum of the os coxae. It provides "
"3 degrees of freedom: flexion/extension, abduction/adduction, and internal/"
"external rotation. The joint must simultaneously provide <b>stability</b> "
"during high-load activities and <b>mobility</b> across all three planes.", body))
story.append(sp(4))
concepts = [
("Force (F)", "A push or pull acting on a body; vector quantity with magnitude and direction. Unit: Newtons (N)."),
("Moment (M) / Torque", "Rotational effect of a force about an axis. M = F × d (perpendicular distance). Unit: N·m."),
("Lever Arm (Moment Arm)", "Perpendicular distance from the line of action of a force to the axis of rotation."),
("Joint Contact Force (JCF)", "Total compressive force across the articular surface, including contributions from muscles, ligaments and body weight."),
("Joint Reaction Force (JRF)", "Often used interchangeably with JCF; strictly the reaction force at the joint surface."),
("Ground Reaction Force (GRF)", "Equal and opposite force exerted by the ground on the foot during stance phase."),
("Center of Mass (COM)", "Point through which body weight acts; located ~anterior to S2 vertebra in anatomical position."),
("Static Equilibrium", "Condition where net force = 0 and net moment = 0; body is not accelerating."),
("Inverse Dynamics", "Method of calculating joint forces/moments from motion data and GRF measurements."),
]
rows = [[Paragraph(b(t), bold_body), Paragraph(d, body)] for t, d in concepts]
tbl = Table(rows, colWidths=[4.5*cm, W-4.5*cm])
tbl.setStyle(TableStyle([
("VALIGN", (0,0),(-1,-1), "TOP"),
("GRID", (0,0),(-1,-1), 0.3, colors.HexColor("#dddddd")),
("ROWBACKGROUNDS",(0,0),(-1,-1), [WHITE, LGRAY]),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING",(0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 6),
("BACKGROUND", (0,0),(0,-1), LTBLUE),
]))
story.append(tbl)
story.append(sp(8))
story.append(Paragraph("1.2 Newton's Laws Applied to the Hip", h2))
left = [
Paragraph(b("1st Law (Inertia):"), body),
Paragraph("During quiet standing, the hip is in static equilibrium; net forces and moments = 0.", bullet),
sp(4),
Paragraph(b("2nd Law (F = ma):"), body),
Paragraph("During dynamic activities (gait, running), unbalanced forces produce acceleration. ΣF = ma, ΣM = Iα", bullet),
]
right = [
Paragraph(b("3rd Law (Action-Reaction):"), body),
Paragraph("For every force the femoral head exerts on the acetabulum, an equal and opposite force is exerted back (joint reaction force).", bullet),
sp(4),
Paragraph(b("Lever Principle:"), body),
Paragraph("The hip acts as a Class 1 lever; the fulcrum is the femoral head, body weight is the load, and abductor muscles are the effort.", bullet),
]
story.append(two_col(left, right))
story.append(sp(6))
story.append(key_box("Muscles insert close to the joint → short internal lever arm → muscles must exert forces MUCH larger than the external load to maintain equilibrium. This is why hip JCF >> body weight alone."))
story.append(PageBreak())
# ── SECTION 2: FORCES ACTING ON THE HIP ────────────────────────────────────────
story.append(section_header("2. FORCES ACTING ON THE HIP JOINT"))
story.append(sp(8))
story.append(Paragraph("2.1 The Lever Model (Coronal Plane Analysis)", h2))
story.append(Paragraph(
"In single-limb stance, the hip joint can be modelled as a first-class lever. "
"The body's center of gravity lies medial to the hip joint axis, creating an "
"adduction moment. The abductor muscles on the lateral side resist this moment.", body))
story.append(sp(6))
story.append(formula_box("Joint Contact Force (JCF) = Abductor Muscle Force + Body Weight"))
story.append(sp(8))
lever_data = [
["Parameter", "Description", "Typical Value"],
["Body weight lever arm", "Distance from body COM to femoral head center", "~2.5× abductor arm"],
["Abductor lever arm", "Distance from greater trochanter to femoral head center", "Reference (1×)"],
["Lever arm ratio (BW:ABD)", "Normal hip", "2.5 : 1"],
["Lever arm ratio (BW:ABD)", "Arthritic hip (head/neck loss)", "Up to 4 : 1"],
["Abductor force needed", "To maintain level pelvis in 1-leg stance", "~2.5 × BW"],
["Resulting JCF", "Stance phase of gait", "3–5 × BW"],
]
story.append(data_table(lever_data[0], lever_data[1:],
col_widths=[5.5*cm, 7.5*cm, 4*cm]))
story.append(sp(8))
story.append(Paragraph("2.2 Forces in the Three Planes", h2))
planes = [
("Coronal Plane", LTBLUE, TEAL,
["GRF passes medial to hip axis → external hip ADDUCTION moment (clockwise)",
"Hip abductors generate internal ABDUCTION moment (counterclockwise) to maintain pelvic level",
"If abductors fail → contralateral pelvic drop (Trendelenburg sign)",
"JCF is greatest in the coronal plane during single-limb stance"]),
("Sagittal Plane", LTGREEN, colors.HexColor("#2e7d32"),
["Body COM is posterior to hip joint axis → bending moment tends to flex the hip",
"Forces in this plane bend the femoral stem posteriorly",
"Amplified when hip is loaded in flexion (e.g., rising from chair, stair climbing)",
"Generates anterior-posterior shear at the femoral neck"]),
("Transverse Plane", LTYELL, colors.HexColor("#e65100"),
["Torsional (rotational) forces act along the long axis of the femoral stem",
"Generated during rotational activities and gait",
"Cause femoral stem torsion and rotational loosening in THA",
"External rotation deformity shortens abductor lever arm → increases JCF"]),
]
for plane_name, bg, bdr, items in planes:
story.append(Paragraph(b(plane_name), h3))
inner = [Paragraph(f"• {it}", body) for it in items]
story.append(colored_box(inner, bg=bg, border=bdr))
story.append(sp(4))
story.append(sp(4))
story.append(exam_box("CLASSIC EXAM Q: 'Why does JCF exceed body weight?' → Because muscle forces (especially abductors) must overcome the disadvantageous lever arm ratio and are added directly to BW. JCF = BW + Muscle Force."))
story.append(PageBreak())
# ── SECTION 3: LEVER ARM MECHANICS ────────────────────────────────────────────
story.append(section_header("3. LEVER ARM MECHANICS & MOMENT ANALYSIS"))
story.append(sp(8))
story.append(Paragraph("3.1 Moment Equilibrium in Single-Limb Stance", h2))
story.append(Paragraph(
"During single-limb stance, for the pelvis to remain level (static equilibrium), "
"the sum of moments about the hip joint axis must equal zero:", body))
story.append(sp(4))
story.append(formula_box("BW × d₁ = F_abductor × d₂"))
story.append(sp(4))
story.append(Paragraph(
"Where d₁ = body weight lever arm (medial); d₂ = abductor lever arm (lateral). "
"Since d₁ >> d₂ (ratio ~2.5:1), F_abductor must be ~2.5× BW.", body))
story.append(sp(8))
story.append(Paragraph("3.2 Factors That Modify the Lever Arms", h2))
mod_data = [
["Factor", "Effect on Abductor Lever Arm", "Effect on JCF"],
["Coxa valga (NSA >135°)", "Decreases (abductors more vertical)", "Increases"],
["Coxa vara (NSA <125°)", "Increases", "Decreases"],
["Acetabular medialization", "No change (but BW arm decreases)", "Decreases"],
["High-offset femoral stem", "Increases", "Decreases"],
["Lateral trochanteric transfer", "Increases", "Decreases"],
["Loss of femoral head height (OA)", "Decreases", "Increases"],
["Coxa breva (short neck)", "Decreases", "Increases"],
]
story.append(data_table(mod_data[0], mod_data[1:],
col_widths=[5.5*cm, 5.5*cm, 5*cm]))
story.append(sp(8))
story.append(Paragraph("3.3 Charnley's Biomechanical Principles (THA)", h2))
story.append(Paragraph(
"Sir John Charnley identified two surgical modifications to reduce hip JCF:", body))
charnley = [
("Medialization of acetabulum", "Moves hip centre medially → shortens BW lever arm → reduces abductor force needed → reduces JCF. Also improves cup coverage."),
("Lateralization of greater trochanter", "Lengthening abductor lever arm → abductors need less force → reduces JCF. Achieved by lateral/distal reattachment of osteotomised trochanter or using high-offset stems."),
]
for title, desc in charnley:
story.append(Paragraph(f"• {b(title)}: {desc}", bullet))
story.append(sp(4))
story.append(key_box("Theoretically, optimising lever arms (ratio approaching 1:1) can reduce total hip JCF by ~30%. Modern THA preserves bone rather than emphasising formal trochanteric osteotomy, but high-offset stems achieve similar lever arm benefits."))
story.append(PageBreak())
# ── SECTION 4: ACTIVITY-SPECIFIC FORCES ───────────────────────────────────────
story.append(section_header("4. ACTIVITY-SPECIFIC HIP JOINT FORCES"))
story.append(sp(8))
story.append(Paragraph(
"Hip joint forces vary dramatically with activity. These values are derived from "
"analytical models and instrumented hip prostheses (in vivo measurement):", body))
story.append(sp(6))
act_data = [
["Activity", "JCF (× Body Weight)", "Clinical Implication"],
["Supine rest", "~0.3×", "Safe immediately post-op"],
["Lifting leg from bed (SLR)", "1.5×", "Significant despite appearance of being 'gentle'"],
["Bilateral stance (even)", "~1×", "Low load; safest weight-bearing"],
["Walking on level surface", "3–5× (in vivo 2.6–3.0×)", "Most common daily load"],
["Single-limb stance", "3–4×", "Basis of Trendelenburg mechanics"],
["Stair climbing", "~3.5×", "Increased compared to level walking"],
["Rising from chair", "3.5–4×", "Sagittal plane forces amplified"],
["Running", "5–8×", "High cyclic loading; risk for fatigue failure"],
["Jumping / hopping", "Up to 10×", "Maximum recorded forces"],
["Stumbling / falling", "Can exceed 10×", "Fracture risk in osteoporotic bone"],
]
story.append(data_table(act_data[0], act_data[1:],
col_widths=[5.5*cm, 4.5*cm, 7*cm]))
story.append(sp(8))
story.append(Paragraph("4.1 Why Measured Forces Are Lower Than Predicted", h2))
story.append(Paragraph(
"Analytical models predict forces of 3.5–5.0× BW during gait, while instrumented "
"prostheses measure 2.6–3.0× BW. This discrepancy occurs because:", body))
for pt in ["Instrumented prostheses capture forces after periprosthetic soft tissue remodelling",
"Patients modify gait patterns to offload painful/replaced joints",
"Analytical models assume worst-case muscle co-contraction",
"Post-surgical pain and muscle inhibition reduce actual muscle forces generated"]:
story.append(Paragraph(f"• {pt}", bullet))
story.append(sp(6))
story.append(exam_box("Remember: Straight-leg raise generates ~1.5× BW at the hip, the SAME as gait stance phase forces predicted by early models. This is why SLR is NOT a 'safe' low-load exercise after hip surgery/fracture — it creates significant joint stress."))
story.append(PageBreak())
# ── SECTION 5: PATHOMECHANICS ─────────────────────────────────────────────────
story.append(section_header("5. PATHOMECHANICS OF THE HIP JOINT"))
story.append(sp(8))
story.append(Paragraph(
"Pathomechanics refers to abnormal mechanical behaviour arising from structural "
"deformity, muscle dysfunction, or disease. Each condition alters the force "
"distribution and lever arm relationships described in the previous sections.", body))
story.append(sp(6))
# 5.1 Trendelenburg
story.append(Paragraph("5.1 Trendelenburg Sign & Gait", h2))
story.append(Paragraph(b("Normal mechanism:"), h3))
story.append(Paragraph(
"During single-limb stance, hip abductors (primarily gluteus medius and minimus) "
"generate a force from the greater trochanter to maintain pelvic level. The "
"internal abduction moment must equal the external adduction moment created by "
"body weight passing medial to the hip.", body))
story.append(sp(4))
tren_rows = [
[b("Positive Trendelenburg"), b("Compensated Trendelenburg (Gluteus Medius Lurch)")],
["Contralateral pelvis drops >2 cm during single-limb stance",
"Patient shifts trunk toward stance leg to compensate"],
["Indicates failure of hip abductor mechanism",
"Moves body COM closer to hip axis → reduces external adduction moment"],
["Causes: abductor weakness, pain inhibition, joint instability, coxa valga, short neck",
"Reduces required abductor muscle force → reduces JCF by reducing moment arm requirement"],
["Test: patient stands on one leg; watch contralateral side of pelvis",
"Gait appearance: lateral trunk lurch toward affected side each step"],
]
tbl = Table(tren_rows, colWidths=[W/2 - 3, W/2 - 3])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), NAVY),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#cccccc")),
("ROWBACKGROUNDS",(0,1),(-1,-1), [LTBLUE, WHITE]),
("VALIGN", (0,0),(-1,-1), "TOP"),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 6),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 9),
]))
story.append(tbl)
story.append(sp(6))
# 5.2 Coxa Valga
story.append(Paragraph("5.2 Coxa Valga (Neck-Shaft Angle >135°)", h2))
left2 = [
Paragraph(b("Pathomechanics:"), h3),
Paragraph("• Abductor force line more vertical → reduced perpendicular moment arm (D)", bullet),
Paragraph("• More abductor force required for same moment → JCF increases", bullet),
Paragraph("• Increased bending moment arm (I) → higher shear force at femoral neck", bullet),
Paragraph("• Femoral head contact more superolateral → eccentric loading", bullet),
Paragraph("• Often co-occurs with acetabular dysplasia → stress concentrates", bullet),
]
right2 = [
Paragraph(b("Clinical consequences:"), h3),
Paragraph("• Accelerated acetabular cartilage wear", bullet),
Paragraph("• Early osteoarthritis (especially if + dysplasia)", bullet),
Paragraph("• Risk of femoral neck stress fractures", bullet),
Paragraph("• Hip instability / subluxation tendency", bullet),
Paragraph("• Trendelenburg gait", bullet),
]
story.append(two_col(left2, right2))
story.append(sp(4))
story.append(key_box("Stress = Force / Area. Coxa valga + acetabular dysplasia = MORE force over LESS area = dramatically elevated cartilage stress → fastest route to early OA."))
story.append(sp(6))
# 5.3 Coxa Vara
story.append(Paragraph("5.3 Coxa Vara (Neck-Shaft Angle <125°)", h2))
left3 = [
Paragraph(b("Pathomechanics:"), h3),
Paragraph("• Larger abductor moment arm (D) → less abductor force needed → JCF relatively lower", bullet),
Paragraph("• Femoral neck more horizontal → increased compressive forces on medial neck (tension on lateral)", bullet),
Paragraph("• Bending moment arm (I) across the neck decreases → less neck shear", bullet),
Paragraph("• Functional limb shortening from reduced neck length/angle", bullet),
]
right3 = [
Paragraph(b("Clinical consequences:"), h3),
Paragraph("• Protective against femoral head OA (lower JCF)", bullet),
Paragraph("• Risk of varus malunion / progressive varus deformity (in children)", bullet),
Paragraph("• Abductor muscle shortening → functional weakness despite better moment arm", bullet),
Paragraph("• Trendelenburg gait (due to abductor shortening/weakness)", bullet),
Paragraph("• Associated: Paget's disease, rickets, osteogenesis imperfecta", bullet),
]
story.append(two_col(left3, right3))
story.append(sp(6))
# 5.4 Acetabular Dysplasia
story.append(Paragraph("5.4 Acetabular Dysplasia", h2))
story.append(Paragraph(
"Reduced acetabular coverage of the femoral head leads to decreased contact area "
"at the articulation. Since Stress = Force/Area, even normal JCF magnitudes "
"generate pathologically elevated contact pressures:", body))
for pt in [
"Superolateral rim bears the majority of load → focal cartilage overload",
"Labrum hypertrophies initially to extend the effective contact area ('suction seal' function)",
"Progressive labral tears → loss of joint seal → increased micromotion → cartilage damage",
"Hip instability → compensatory muscle co-contraction → further JCF elevation",
"End result: early secondary osteoarthritis (often by 4th–5th decade)",
"Combined coxa valga + dysplasia: both force AND area are adversely affected → highest risk group"
]:
story.append(Paragraph(f"• {pt}", bullet))
story.append(sp(6))
# 5.5 FAI
story.append(Paragraph("5.5 Femoroacetabular Impingement (FAI)", h2))
fai_rows = [
["", b("CAM Impingement"), b("PINCER Impingement"), b("Mixed")],
[b("Morphology"), "Aspherical femoral head / pistol-grip deformity; abnormal head-neck junction",
"Acetabular over-coverage: coxa profunda, acetabular retroversion, protrusio",
"Features of both; most common (>80%)"],
[b("Mechanism"), "'Outside-in': aspherical head abuts rim during flexion-IR; cartilage shears",
"Linear rim-to-neck contact; labral crush/ossification; contre-coup posterior lesion",
"Combined impingement from both sides"],
[b("Lesion"), "Anterosuperior acetabular cartilage; labral base detachment",
"Labral damage + posterior chondral contre-coup; labral ossification",
"Variable"],
[b("Demographics"), "Young athletic males (M:F = 3:1)", "Middle-aged females (F:M = 3:1)", "Both"],
[b("OA risk"), "Moderate to high", "Moderate", "Highest"],
]
fai_tbl = Table(fai_rows, colWidths=[2.8*cm, 4.5*cm, 4.5*cm, 4.5*cm])
fai_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), NAVY),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("BACKGROUND", (0,0),(0,-1), LTBLUE),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#cccccc")),
("VALIGN", (0,0),(-1,-1), "TOP"),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8.5),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 5),
]))
story.append(fai_tbl)
story.append(sp(6))
story.append(exam_box("CAM = femur problem (too much bone on head-neck junction). PINCER = acetabulum problem (too much coverage). CAM is more strongly associated with OA development."))
story.append(PageBreak())
# 5.6 OA Hip
story.append(Paragraph("5.6 Hip Osteoarthritis — Biomechanical Progression", h2))
story.append(Paragraph(b("Vicious cycle of mechanical deterioration:"), h3))
oa_steps = [
("1. Initiating Factor", "Altered joint geometry (FAI, dysplasia, coxa valga) or primary cartilage failure"),
("2. Abnormal Stress Distribution", "Focal cartilage overload → chondrocyte apoptosis → matrix breakdown (proteoglycan loss, collagen disruption)"),
("3. Joint Space Narrowing", "Loss of cartilage → incongruent joint → further altered mechanics and force concentration"),
("4. Bone Remodelling", "Subchondral bone thickening (sclerosis), cyst formation, osteophyte formation at joint margins"),
("5. Deformity", "Loss of femoral head height/sphericity → shortened abductor lever arm → JCF increases → accelerates damage"),
("6. Muscle Inhibition", "Pain → reflex inhibition of abductors → Trendelenburg gait → further mechanical disadvantage"),
("7. Contracture", "Adduction/flexion contracture → altered pelvic alignment → secondary lumbar changes"),
]
for step, desc in oa_steps:
story.append(Paragraph(f"<b>{step}:</b> {desc}", bullet))
story.append(sp(4))
story.append(Paragraph("5.7 Avascular Necrosis (AVN) of the Femoral Head", h2))
story.append(Paragraph(
"Interruption of blood supply (artery of ligamentum teres + medial circumflex "
"femoral artery) → bone death → structural failure under normal loads:", body))
for pt in [
"Subchondral fracture (crescent sign) → collapse of femoral head → loss of sphericity",
"Incongruent joint loading → shear forces concentrate at collapse interface",
"Progressive deformity → same mechanical cascade as OA above",
"Ficat staging (I–IV) correlates with degree of mechanical compromise",
]:
story.append(Paragraph(f"• {pt}", bullet))
story.append(PageBreak())
# ── SECTION 6: GAIT DEVIATIONS ────────────────────────────────────────────────
story.append(section_header("6. HIP PATHOLOGY & GAIT DEVIATIONS"))
story.append(sp(8))
gait_data = [
["Gait Deviation", "Pathomechanical Cause", "Muscle/Structure Implicated"],
["Trendelenburg gait (uncompensated)", "Abductor force < external adduction moment → contralateral pelvic drop", "Gluteus medius, minimus; superior gluteal n."],
["Gluteus medius lurch (compensated Trendelenburg)", "Lateral trunk lean reduces external moment arm → reduces required abductor force", "Compensation for abductor weakness/pain"],
["Antalgic gait (shortened stance phase)", "Pain inhibits full weight bearing; reduces time of JCF application", "Pain from any hip pathology"],
["Hip hiking", "Weak hip flexors → pelvis elevation to clear swing limb", "Iliopsoas weakness"],
["Circumduction", "Weak hip flexors + extensors → arc swing to clear foot", "Iliopsoas, quadriceps"],
["Excessive anterior pelvic tilt", "Hip flexor tightness → pelvis tilts forward → increased lumbar lordosis", "Iliopsoas contracture (OA, post-THA)"],
["In-toeing / out-toeing", "Altered femoral rotation (anteversion/retroversion, deformity)", "Altered femoral torsion"],
["Vaulting (contralateral side)", "Compensation for ipsilateral limb shortening", "AVN, coxa vara, OA"],
]
story.append(data_table(gait_data[0], gait_data[1:],
col_widths=[4.5*cm, 7*cm, 5*cm]))
story.append(sp(6))
story.append(Paragraph("Functional Consequences of Gait Deviations", h2))
for pt in [
"Chronic Trendelenburg gait → IT band tightness → lateral knee pain + trochanteric bursitis",
"Compensated Trendelenburg → contralateral lumbar scoliosis → low back pain",
"Antalgic gait → contralateral lower limb overloading → knee/ankle OA",
"Hip flexion contracture → knee extension moment arm shift → anterior knee pain (patellofemoral syndrome)",
]:
story.append(Paragraph(f"• {pt}", bullet))
story.append(PageBreak())
# ── SECTION 7: CLINICAL APPLICATIONS ────────────────────────────────────────────
story.append(section_header("7. CLINICAL APPLICATIONS & INTERVENTIONS"))
story.append(sp(8))
story.append(Paragraph("7.1 Reducing Hip Joint Contact Force — Clinical Strategies", h2))
strat_data = [
["Strategy", "Biomechanical Mechanism", "Reduction in JCF"],
["Walking cane (contralateral hand)", "Cane GRF shifts body COM toward stance hip → reduces external adduction moment", "~20–30%"],
["Weight loss", "Reduces body weight component directly", "Proportional to weight lost"],
["Lateral trunk lean (Trendelenburg compensation)", "Shortens BW lever arm", "Moderate reduction"],
["Hip abductor strengthening", "Reduces compensatory co-contraction; more efficient force generation", "Indirect reduction"],
["Orthotics / shoe modifications", "Alters GRF line and moment arms", "Variable"],
["Acetabular medialization (THA)", "Shortens BW lever arm (Charnley principle)", "~15–20%"],
["High-offset femoral stem (THA)", "Lengthens abductor lever arm", "~10–15%"],
["Proximal femoral osteotomy (varus)", "Increases abductor moment arm; improves congruence", "Significant in dysplasia"],
]
story.append(data_table(strat_data[0], strat_data[1:],
col_widths=[4.5*cm, 7*cm, 4.5*cm]))
story.append(sp(6))
story.append(Paragraph("7.2 Physiotherapy Assessment — Key Biomechanical Tests", h2))
tests = [
("Trendelenburg Test", "Single-leg stance × 30 sec; positive if contralateral pelvis drops >2 cm", "Gluteus medius/minimus function; assesses abductor lever arm adequacy"),
("Hip Abductor Strength (MMT/dynamometry)", "Graded 0–5; dynamometer gives force in Newtons", "Correlates with JCF reduction capacity"),
("Thomas Test", "Hip flexion contracture angle", "Identifies anterior pelvic tilt contribution to altered hip mechanics"),
("FABER / FADDIR", "Flexion-Abduction-External Rotation / Flexion-Adduction-Internal Rotation", "FAI / labral pathology screening; reproduces impingement"),
("Craig's Test (femoral anteversion)", "Prone, palpate greater trochanter, rotate hip to maximally lateral position; measure tibial angle", "Identifies abnormal femoral torsion contributing to pathomechanics"),
("Ober's Test", "Side-lying; assess IT band / TFL tightness", "TFL tightness alters abductor mechanism and iliotibial band tension"),
("Single-leg squat / hop test", "Dynamic loading; observe pelvic drop, knee valgus", "Functional abductor control; FAI impingement testing"),
]
for test, technique, purpose in tests:
story.append(Paragraph(b(test), h3))
story.append(Paragraph(f"{b('Technique:')} {technique}", body))
story.append(Paragraph(f"{b('Purpose:')} {purpose}", body))
story.append(sp(2))
story.append(PageBreak())
story.append(Paragraph("7.3 Exercise Prescription — Biomechanical Principles", h2))
story.append(Paragraph(b("Hip Abductor Strengthening:"), h3))
for pt in [
"Side-lying hip abduction: 1.5–2× BW at hip; effective for isolated gluteus medius training",
"Single-leg stance exercises: functional loading at 3–4× BW; builds neuromuscular control",
"Clamshells: low load; good for early rehab and external rotator co-activation",
"Lateral band walks: eccentric abductor loading; functional closed-chain",
"Avoid: hip abduction machine with heavy weights early post-THA (excessive JCF on new prosthesis)",
]:
story.append(Paragraph(f"• {pt}", bullet))
story.append(sp(4))
story.append(Paragraph(b("Activity Progression (post-THA / hip fracture repair):"), h3))
prog_data = [
["Phase", "Activity", "Estimated JCF", "Rationale"],
["Acute (0–2 wk)", "Supine exercises, toe-touch WB", "0.3–1.5× BW", "Minimise load during fixation/healing"],
["Early (2–6 wk)", "Partial WB, level walking with aid", "1.5–3× BW", "Progressive loading as tolerated"],
["Intermediate (6–12 wk)", "Full WB, stairs, gentle cycling", "3–4× BW", "Restore normal gait mechanics"],
["Late (3–6 mo)", "Swimming, walking, ergometer", "3–5× BW", "Endurance and strength building"],
["Return to activity", "Sport-specific, high-impact", "5–10× BW", "Only with full healing and strength"],
]
story.append(data_table(prog_data[0], prog_data[1:],
col_widths=[3*cm, 4.5*cm, 3.5*cm, 6*cm]))
story.append(PageBreak())
# ── SECTION 8: QUICK REFERENCE TABLES ────────────────────────────────────────────
story.append(section_header("8. QUICK-REFERENCE SUMMARY TABLES"))
story.append(sp(8))
story.append(Paragraph("8.1 JCF Values — Memory Aid", h2))
jcf_mem = [
["Activity", "JCF (× BW)", "Mnemonic"],
["Bed rest / supine", "0.3×", "Basically nothing"],
["SLR / lifting leg", "1.5×", "One and a HALF"],
["Quiet bilateral standing", "~1×", "Just your weight"],
["Single-leg stance / walking", "3×", "THREE times"],
["Running", "5–8×", "FIVE to EIGHT"],
["Jumping / hopping", "10×", "TEN (max!)"],
]
story.append(data_table(jcf_mem[0], jcf_mem[1:],
col_widths=[5.5*cm, 3.5*cm, 7*cm]))
story.append(sp(8))
story.append(Paragraph("8.2 Pathological Conditions — Summary", h2))
path_sum = [
["Condition", "NSA", "Abductor Arm", "JCF", "Primary Risk"],
["Normal", "125–135°", "Normal", "Normal", "-"],
["Coxa valga", ">135°", "Decreased", "Increased", "OA, neck # risk"],
["Coxa vara", "<125°", "Increased", "Decreased", "Deformity, lurch"],
["Acetabular dysplasia", "Variable", "Often decreased", "Normal or ↑", "Early OA (stress)"],
["FAI - CAM", "Normal", "Normal", "Normal (until OA)", "Labral tear → OA"],
["FAI - Pincer", "Normal", "Normal", "Normal", "Labral crush → OA"],
["Hip OA (advanced)", "Variable (↓ head)", "Decreased", "Increased", "Accelerating OA"],
["AVN (Stage III-IV)", "Collapse", "Decreased", "Increased", "Rapid joint failure"],
["Post-THA (low offset)", "Restored", "Decreased", "Increased", "Trendelenburg, dislocation"],
]
story.append(data_table(path_sum[0], path_sum[1:],
col_widths=[4.5*cm, 2.2*cm, 3.2*cm, 2.2*cm, 5*cm]))
story.append(sp(8))
story.append(Paragraph("8.3 Key Biomechanical Principles at a Glance", h2))
principles = [
"JCF = Body Weight Component + Abductor Muscle Force → JCF is ALWAYS > BW",
"Lever arm ratio (BW arm : Abductor arm) = 2.5:1 normal; up to 4:1 in arthritic hip",
"Abductor force ≈ 2.5× BW in single-limb stance to maintain pelvic level",
"Cane in contralateral hand reduces JCF by ~20–30%",
"Trunk lean toward stance leg reduces external moment arm → reduces JCF",
"Coxa valga → shorter abductor arm → more force needed → higher JCF",
"Coxa vara → longer abductor arm → less force needed → lower JCF",
"Stress = F/A: even normal JCF causes pathological stress with reduced contact area (dysplasia)",
"Charnley: Medialization + high offset → optimised lever arms → reduces JCF by ~30%",
"Maximum hip forces: Jumping = 10× BW; Running = 5–8× BW",
]
for i, p in enumerate(principles, 1):
story.append(Paragraph(f"<b>{i}.</b> {p}", bullet))
story.append(PageBreak())
# ── SECTION 9: MCQs & SAQs ────────────────────────────────────────────────────
story.append(section_header("9. HIGH-YIELD EXAM MCQs & SHORT ANSWER QUESTIONS"))
story.append(sp(8))
story.append(Paragraph("9.1 Multiple Choice Questions", h2))
mcqs = [
("Q1. During single-limb stance, the hip joint contact force (JCF) equals approximately:",
["A. Equal to body weight",
"B. 1.5 × body weight",
"C. 3 × body weight ✓",
"D. 5 × body weight"],
"Answer: C. JCF = abductor force (~2.5× BW) + body weight contribution ≈ 3× BW in single-limb stance. The abductor mechanism must counteract the external adduction moment created by body weight passing medial to the hip axis."),
("Q2. A patient walks with a lateral trunk lean toward the right side. The MOST likely cause is:",
["A. Right hip flexor weakness",
"B. Right hip abductor weakness ✓",
"C. Left hip abductor weakness",
"D. Right hip adductor tightness"],
"Answer: B. Lateral trunk lean toward the stance limb is the compensated Trendelenburg (gluteus medius lurch). The patient leans toward the AFFECTED (stance) side to reduce the external adduction moment and reduce required abductor force."),
("Q3. In coxa valga, the abductor moment arm is reduced because:",
["A. The neck-shaft angle is less than 125°",
"B. The abductor line of action becomes more vertical, reducing the perpendicular distance ✓",
"C. The femoral head is displaced medially",
"D. The greater trochanter is displaced laterally"],
"Answer: B. With a larger neck-shaft angle (>135°), the greater trochanter moves relatively upward/medially, and the abductor force vector becomes more vertical — decreasing the perpendicular (moment) arm from the hip axis."),
("Q4. Which activity generates the MAXIMUM force at the hip joint?",
["A. Walking on level ground",
"B. Straight-leg raise",
"C. Single-leg stance",
"D. Jumping and hopping ✓"],
"Answer: D. Jumping/hopping generates up to 10× body weight at the hip joint. Running generates 5–8×, single-leg stance 3×, and SLR 1.5×."),
("Q5. The Charnley medialization principle in THA reduces JCF by:",
["A. Increasing the abductor muscle strength",
"B. Shortening the body weight lever arm ✓",
"C. Lengthening the abductor lever arm",
"D. Reducing the body weight"],
"Answer: B. Medialization of the acetabulum moves the hip center of rotation medially, which shortens the distance from the body's COG to the hip joint (body weight lever arm), reducing the moment the abductors must counteract, thereby reducing JCF."),
("Q6. The combination of coxa valga AND acetabular dysplasia leads to accelerated OA primarily because:",
["A. Both reduce total JCF",
"B. JCF is increased AND contact area is reduced — leading to the highest articular stress ✓",
"C. The neck-shaft angle is below normal",
"D. Abductor muscles are hypertrophied"],
"Answer: B. Stress = Force/Area. Coxa valga increases required abductor force → higher JCF. Dysplasia reduces contact area. Together, articular stress rises dramatically, accelerating cartilage breakdown."),
]
for i, (q, opts, ans) in enumerate(mcqs, 1):
story.append(colored_box(
[Paragraph(q, PS("QQ", fontSize=9.5, textColor=NAVY, fontName="Helvetica-Bold", leading=13))],
bg=LTBLUE, border=TEAL))
for opt in opts:
story.append(Paragraph(f" {opt}", bullet))
story.append(colored_box(
[Paragraph(ans, PS("ANS", fontSize=9, textColor=DKGRAY,
fontName="Helvetica", leading=13, leftIndent=4))],
bg=LTGREEN, border=colors.HexColor("#2e7d32")))
story.append(sp(6))
story.append(PageBreak())
story.append(Paragraph("9.2 Short Answer Question Templates", h2))
story.append(sp(4))
saqs = [
("5-mark SAQ: Explain the lever mechanism at the hip during single-limb stance.",
[
"Define hip as Class 1 lever; identify fulcrum (femoral head), effort (abductors at GT), load (body weight at COM) [1 mark]",
"State lever arm ratio: BW arm = 2.5× abductor arm [1 mark]",
"Calculate: Abductor force ≈ 2.5× BW [1 mark]",
"JCF = Abductor force + BW contribution ≈ 3× BW [1 mark]",
"Clinical implication: why JCF >> BW; why abductors are prone to fatigue/pathology [1 mark]",
]),
("10-mark SAQ: Describe the pathomechanics of hip osteoarthritis.",
[
"Define pathomechanics [0.5]",
"Normal joint mechanics / contact stress [0.5]",
"Initiating causes: dysplasia, FAI, coxa valga (structural) vs primary [1]",
"Altered stress distribution: stress = F/A; focal overload [1]",
"Cartilage failure pathway: proteoglycan → collagen → chondrocyte death [1.5]",
"Joint space narrowing → incongruence → further mechanical disruption [1]",
"Bone changes: subchondral sclerosis, cysts, osteophytes [1]",
"Abductor mechanism deterioration: shortened lever arm → Trendelenburg [1.5]",
"Deformity and contracture [1]",
"Therapeutic implications (at least 2) [1]",
]),
("15-mark SAQ: Forces acting on the hip joint & pathomechanics (this paper!).",
[
"Introduction: hip as class 1 lever; equilibrium requirement [1]",
"Lever arm analysis: BW arm vs abductor arm; ratio 2.5:1 [2]",
"JCF formula and derivation; normal values [1]",
"Activity-specific forces: table with ≥5 activities [2]",
"Three-plane force analysis (coronal, sagittal, transverse) [2]",
"Pathomechanics Part 1: Trendelenburg (positive & compensated) [2]",
"Pathomechanics Part 2: Coxa valga & coxa vara (compare/contrast) [2]",
"Pathomechanics Part 3: Dysplasia / FAI / OA / AVN (at least 2) [2]",
"Clinical applications: interventions to reduce JCF (cane, weight loss, surgery) [1]",
]),
]
for title, points in saqs:
story.append(colored_box(
[Paragraph(title, PS("SAQQ", fontSize=10, textColor=NAVY, fontName="Helvetica-Bold", leading=14))],
bg=LTYELL, border=GOLD))
story.append(Paragraph("Marking scheme / answer guide:", PS("MG", fontSize=9, textColor=GRAY,
fontName="Helvetica-Oblique", leading=12)))
for pt in points:
story.append(Paragraph(f"• {pt}", bullet))
story.append(sp(6))
# ── FINAL PAGE: REFERENCE & GLOSSARY ─────────────────────────────────────────
story.append(PageBreak())
story.append(section_header("SOURCES & ABBREVIATIONS", color=TEAL))
story.append(sp(8))
story.append(Paragraph("Textbook Sources", h2))
refs = [
"Campbell's Operative Orthopaedics, 15th Edition (2026) — Chapter 4: Applied Biomechanics of THA; Forces Acting on the Hip",
"Bailey & Love's Short Practice of Surgery, 28th Edition — Chapter 39: Biomechanics of the Hip Joint",
"Firestein & Kelley's Textbook of Rheumatology, 2-Volume Set — Chapter 6: Statics, Kinetics, and Hip Biomechanics",
"Miller's Review of Orthopaedics, 9th Edition — Hip Arthroplasty: Restoration of Abductor Tension",
"Rockwood and Green's Fractures in Adults, 10th Edition (2025) — Biomechanics section",
]
for ref in refs:
story.append(Paragraph(f"• {ref}", bullet))
story.append(sp(8))
story.append(Paragraph("Abbreviations", h2))
abbrevs = [
("AVN", "Avascular Necrosis"), ("BW", "Body Weight"),
("COM", "Center of Mass"), ("FAI", "Femoroacetabular Impingement"),
("GRF", "Ground Reaction Force"), ("GT", "Greater Trochanter"),
("IR", "Internal Rotation"), ("JCF", "Joint Contact Force"),
("JRF", "Joint Reaction Force"), ("NSA", "Neck-Shaft Angle"),
("OA", "Osteoarthritis"), ("THA", "Total Hip Arthroplasty"),
("TFL", "Tensor Fasciae Latae"), ("WB", "Weight Bearing"),
]
rows_ab = [[Paragraph(b(a), tbl_cell), Paragraph(d, tbl_cell),
Paragraph(b(abbrevs[i+1][0]), tbl_cell) if i+1 < len(abbrevs) else Paragraph("", tbl_cell),
Paragraph(abbrevs[i+1][1], tbl_cell) if i+1 < len(abbrevs) else Paragraph("", tbl_cell)]
for i, (a, d) in enumerate(abbrevs) if i % 2 == 0]
ab_tbl = Table(rows_ab, colWidths=[2.5*cm, 5.5*cm, 2.5*cm, 5.5*cm])
ab_tbl.setStyle(TableStyle([
("GRID", (0,0),(-1,-1), 0.3, colors.HexColor("#dddddd")),
("ROWBACKGROUNDS",(0,0),(-1,-1), [WHITE, LGRAY]),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 6),
]))
story.append(ab_tbl)
story.append(sp(12))
footer = Table([[Paragraph(
"This study guide was generated by Orris AI for MPT examination preparation. "
"Always verify clinical information against current guidelines and primary textbooks. "
"Not for clinical decision-making.",
PS("Disc", fontSize=8, textColor=GRAY, fontName="Helvetica-Oblique",
alignment=TA_CENTER, leading=12))]],
colWidths=[W])
footer.setStyle(TableStyle([
("LINEABOVE", (0,0),(-1,-1), 0.5, GRAY),
("TOPPADDING",(0,0),(-1,-1), 6),
]))
story.append(footer)
# ── PAGE NUMBERS ──────────────────────────────────────────────────────────────
def add_page_number(canvas, doc):
canvas.saveState()
canvas.setFont("Helvetica", 8)
canvas.setFillColor(GRAY)
page_num = canvas.getPageNumber()
canvas.drawCentredString(PAGE_W / 2, 1.2 * cm,
f"Hip Biomechanics — MPT Study Guide | Page {page_num}")
canvas.restoreState()
doc.build(story, onFirstPage=add_page_number, onLaterPages=add_page_number)
print("PDF generated successfully:", OUTPUT)
Create a study guide document on hip biomechanics for exam prep
Generate a PowerPoint presentation on hip biomechanics