Properties of skeleton muscle according to Sembulingm for knrush university exam for bpt

Reading File
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Searching the Web

Sembulingam physiology properties of skeletal muscle BPT exam excitability contractility extensibility elasticity

Reading Web Page

https://pharmdguru.com/physiological-properties-of-skeletal-…

I now have comprehensive content. Let me compile the full answer based on Sembulingam's chapter on Properties of Skeletal Muscle (Chapter 26), cross-referenced with the library and web sources.

Properties of Skeletal Muscle - Sembulingam (BPT Exam Notes)

Sembulingam's Essentials of Medical Physiology (Chapter 26) classifies skeletal muscle properties into two main groups:

A. ELECTRICAL PROPERTIES

1. Excitability (Irritability)

The ability of muscle to receive and respond to a stimulus.
  • Stimulus can be electrical, chemical, or mechanical
  • Muscle cells respond by generating action potentials
  • Resting Membrane Potential (RMP): -90 mV
  • Firing level (threshold): -50 mV
  • Amplitude of action potential: 120 mV
  • Duration: 2-4 ms
Types of stimulation:
  • Direct stimulation - electrode placed directly on muscle
  • Indirect stimulation - nerve supplying the muscle is stimulated
Key features:
  • A single muscle fiber obeys the All-or-None Law (the entire fiber contracts maximally or not at all)
  • Whole skeletal muscle does NOT obey all-or-none law (different fibers have different thresholds)
  • Has a Refractory Period:
    • Absolute refractory period: 1-3 ms
    • Relative refractory period follows
  • Latent period - brief delay between stimulus and mechanical response
Because the absolute refractory period ends BEFORE the mechanical response begins, tetanization of skeletal muscle is possible.

2. Conductivity

The ability of the muscle to propagate action potentials along its membrane (sarcolemma).
  • Conduction velocity: 3-5 m/s (similar to unmyelinated nerve fibers)
  • Action potential spreads in both directions from the point of stimulation along the sarcolemma
  • Travels via T-tubules to trigger excitation-contraction coupling

B. MECHANICAL PROPERTIES

3. Contractility

The ability to shorten and develop tension (force) when stimulated.
  • Mechanical activity begins only when electrical activity is about to end (the muscle twitch follows the action potential)
  • Involves the sliding filament mechanism - actin and myosin filaments slide over each other
Types of contraction:
TypeMuscle LengthTensionExample
IsometricNo changeIncreasesPushing a wall, postural muscles
IsotonicDecreases (shortens)ConstantLifting a weight, walking
Factors affecting force of contraction:
  • Strength of stimulus (up to maximal stimulus)
  • Frequency of stimulation (summation, tetanus)
  • Initial length of muscle (Starling's law - force is maximum at optimal resting length)
  • Temperature
  • Blood supply and metabolic state
  • Number of motor units recruited
Staircase effect (Treppe): Successive stimuli at low frequency produce progressively stronger contractions due to increasing Ca²⁺ availability.

4. Extensibility

The ability of the muscle to be stretched beyond its resting length without being damaged.
  • Antagonist muscles must lengthen when agonists contract
  • During elbow flexion, the triceps must extend
  • Loss of extensibility causes spasticity
  • Important for smooth, coordinated movement

5. Elasticity

The ability of muscle to return to its original resting length after being stretched or contracted.
  • Due to the elastic components within the muscle fiber (titin protein, connective tissue)
  • Helps maintain muscle tone and passive tension
  • Prevents overstretching injury

Summary Table

PropertyTypeDefinition
ExcitabilityElectricalAbility to respond to a stimulus
ConductivityElectricalAbility to propagate action potentials
ContractilityMechanicalAbility to shorten and develop tension
ExtensibilityMechanicalAbility to be stretched without damage
ElasticityMechanicalAbility to return to original length after stretch

Additional Points for Exam

Action Potential of Skeletal Muscle vs Nerve:
  • Skeletal muscle AP has all the same characteristics as a nerve AP
  • Amplitude: 120 mV | Duration: 2-4 ms | Conduction velocity: 3-5 m/s
Comparison with Cardiac Muscle:
  • Cardiac muscle obeys all-or-none law for the whole muscle (syncytium)
  • Cardiac muscle has a much longer action potential (200-300 ms) - hence NO tetanus is possible
  • Skeletal muscle - only single fiber obeys all-or-none law; tetanus IS possible
Twitch vs Tetanus:
  • Single twitch - response to a single stimulus
  • Summation - responses add up with repeated stimuli
  • Incomplete tetanus - partial relaxation between stimuli
  • Complete tetanus - no relaxation between stimuli; maximal sustained contraction

These notes follow Sembulingam Chapter 26 structure. The classification into electrical (excitability, conductivity) and mechanical (contractility, extensibility, elasticity) properties is the standard format expected in KNRush University BPT physiology examinations.

Create a detailed summary PDF with diagrams on skeletal muscle properties

Reading File
Running Command

mkdir -p /home/daytona/workspace/skeletal-muscle-pdf && ls /home/daytona/workspace/

Writing File

~/skeletal-muscle-pdf/generate_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.lib import colors
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether, PageBreak
)
from reportlab.platypus.flowables import Flowable
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Circle, Polygon, Path
from reportlab.graphics import renderPDF
from reportlab.platypus import Image as RLImage
import io

OUTPUT = "/home/daytona/workspace/skeletal-muscle-pdf/Skeletal_Muscle_Properties_BPT.pdf"

# ─── Colour palette ───────────────────────────────────────────────
NAVY    = colors.HexColor("#1a3a5c")
BLUE    = colors.HexColor("#2563eb")
LBLUE   = colors.HexColor("#dbeafe")
TEAL    = colors.HexColor("#0d9488")
LTEAL   = colors.HexColor("#ccfbf1")
ORANGE  = colors.HexColor("#ea580c")
LORANGE = colors.HexColor("#ffedd5")
RED     = colors.HexColor("#dc2626")
LRED    = colors.HexColor("#fee2e2")
GREEN   = colors.HexColor("#16a34a")
LGREEN  = colors.HexColor("#dcfce7")
PURPLE  = colors.HexColor("#7c3aed")
LPURPLE = colors.HexColor("#ede9fe")
YELLOW  = colors.HexColor("#ca8a04")
LYELLOW = colors.HexColor("#fef9c3")
GRAY    = colors.HexColor("#6b7280")
LGRAY   = colors.HexColor("#f3f4f6")
WHITE   = colors.white
BLACK   = colors.black

W, H = A4  # 595.27 x 841.89 pts

# ─── Styles ───────────────────────────────────────────────────────
def make_styles():
    base = getSampleStyleSheet()
    s = {}
    s['title'] = ParagraphStyle('title', fontSize=22, fontName='Helvetica-Bold',
                                 textColor=WHITE, alignment=TA_CENTER, spaceAfter=4)
    s['subtitle'] = ParagraphStyle('subtitle', fontSize=11, fontName='Helvetica',
                                    textColor=LBLUE, alignment=TA_CENTER, spaceAfter=2)
    s['h1'] = ParagraphStyle('h1', fontSize=14, fontName='Helvetica-Bold',
                              textColor=WHITE, spaceBefore=8, spaceAfter=4,
                              leftIndent=0, borderPad=4)
    s['h2'] = ParagraphStyle('h2', fontSize=12, fontName='Helvetica-Bold',
                              textColor=NAVY, spaceBefore=6, spaceAfter=3)
    s['h3'] = ParagraphStyle('h3', fontSize=10, fontName='Helvetica-Bold',
                              textColor=TEAL, spaceBefore=4, spaceAfter=2)
    s['body'] = ParagraphStyle('body', fontSize=9, fontName='Helvetica',
                                textColor=colors.HexColor("#1f2937"),
                                leading=14, spaceAfter=4, alignment=TA_JUSTIFY)
    s['bullet'] = ParagraphStyle('bullet', fontSize=9, fontName='Helvetica',
                                  textColor=colors.HexColor("#1f2937"),
                                  leading=13, spaceAfter=2,
                                  leftIndent=14, firstLineIndent=-10)
    s['kv'] = ParagraphStyle('kv', fontSize=9, fontName='Helvetica-Bold',
                               textColor=NAVY, leading=13, spaceAfter=2, leftIndent=14)
    s['note'] = ParagraphStyle('note', fontSize=8.5, fontName='Helvetica-Oblique',
                                textColor=GRAY, leading=12, spaceAfter=3, leftIndent=10)
    s['caption'] = ParagraphStyle('caption', fontSize=8, fontName='Helvetica-Oblique',
                                   textColor=GRAY, alignment=TA_CENTER, spaceAfter=4)
    s['table_hdr'] = ParagraphStyle('table_hdr', fontSize=9, fontName='Helvetica-Bold',
                                     textColor=WHITE, alignment=TA_CENTER)
    s['table_body'] = ParagraphStyle('table_body', fontSize=8.5, fontName='Helvetica',
                                      textColor=BLACK, alignment=TA_LEFT, leading=12)
    s['small'] = ParagraphStyle('small', fontSize=8, fontName='Helvetica',
                                  textColor=GRAY, leading=11)
    return s

S = make_styles()

# ─── Helper Flowables ─────────────────────────────────────────────
def section_header(text, bg=NAVY, width=None):
    w = width or (W - 3.6*cm)
    d = Drawing(w, 28)
    d.add(Rect(0, 0, w, 28, fillColor=bg, strokeColor=None))
    d.add(String(10, 8, text, fontName='Helvetica-Bold', fontSize=13, fillColor=WHITE))
    return d

def subsection_bar(text, bg=TEAL, width=None):
    w = width or (W - 3.6*cm)
    d = Drawing(w, 22)
    d.add(Rect(0, 0, w, 22, fillColor=bg, strokeColor=None, rx=3))
    d.add(String(8, 6, text, fontName='Helvetica-Bold', fontSize=10.5, fillColor=WHITE))
    return d

def info_box(text, bg=LBLUE, border=BLUE, width=None):
    """A simple info paragraph wrapped in a coloured table cell."""
    w = width or (W - 3.6*cm)
    data = [[Paragraph(text, ParagraphStyle('ib', fontSize=9, fontName='Helvetica',
                                             textColor=NAVY, leading=13))]]
    t = Table(data, colWidths=[w])
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), bg),
        ('BOX', (0,0), (-1,-1), 0.8, border),
        ('LEFTPADDING', (0,0), (-1,-1), 8),
        ('RIGHTPADDING', (0,0), (-1,-1), 8),
        ('TOPPADDING', (0,0), (-1,-1), 6),
        ('BOTTOMPADDING', (0,0), (-1,-1), 6),
        ('ROWBACKGROUNDS', (0,0), (-1,-1), [bg]),
    ]))
    return t

def bullet(text, color=BLUE):
    return Paragraph(f'<font color="#{color.hexval()[1:]}">&#9658;</font>  {text}', S['bullet'])

def sub_bullet(text):
    return Paragraph(f'&nbsp;&nbsp;&nbsp;&nbsp;<font color="#6b7280">&#9702;</font>  {text}',
                     ParagraphStyle('sb', fontSize=8.5, fontName='Helvetica',
                                     textColor=colors.HexColor("#374151"),
                                     leading=12, spaceAfter=1, leftIndent=22, firstLineIndent=-10))

# ─── Diagram helpers ──────────────────────────────────────────────

def ap_diagram(width=460, height=180):
    """Action potential diagram for skeletal muscle."""
    d = Drawing(width, height)
    d.add(Rect(0, 0, width, height, fillColor=colors.HexColor("#f8fafc"), strokeColor=LGRAY, strokeWidth=0.5))
    d.add(String(width/2 - 80, height-14, "Action Potential of Skeletal Muscle",
                 fontName='Helvetica-Bold', fontSize=9, fillColor=NAVY))

    # axes
    ox, oy, aw, ah = 55, 20, width-80, height-50
    d.add(Line(ox, oy, ox, oy+ah, strokeColor=GRAY, strokeWidth=1))
    d.add(Line(ox, oy+ah*0.35, ox+aw, oy+ah*0.35, strokeColor=GRAY, strokeWidth=1))

    # Y labels
    d.add(String(ox-52, oy+ah*0.35-4, "RMP = -90 mV", fontName='Helvetica', fontSize=7, fillColor=GRAY))
    d.add(String(ox-52, oy+ah-6, "+30 mV", fontName='Helvetica', fontSize=7, fillColor=GRAY))
    d.add(String(ox-52, oy+2, "-90 mV", fontName='Helvetica', fontSize=7, fillColor=GRAY))
    d.add(String(ox-32, oy+ah*0.6, "mV", fontName='Helvetica-Bold', fontSize=7, fillColor=NAVY))

    # X labels
    d.add(String(ox, oy+ah*0.35-16, "0", fontName='Helvetica', fontSize=7, fillColor=GRAY))
    d.add(String(ox+aw-10, oy+ah*0.35-16, "Time (ms)", fontName='Helvetica', fontSize=7, fillColor=GRAY))

    # AP shape path
    pts = [
        (ox, oy+ah*0.35),
        (ox+aw*0.10, oy+ah*0.35),   # baseline
        (ox+aw*0.18, oy+ah*0.85),   # rapid depol
        (ox+aw*0.25, oy+ah),        # peak +30
        (ox+aw*0.38, oy+ah*0.05),   # rapid repol
        (ox+aw*0.50, oy),           # hyperpolarisation
        (ox+aw*0.65, oy+ah*0.35),   # return to RMP
        (ox+aw, oy+ah*0.35),
    ]
    path = Path(strokeColor=BLUE, strokeWidth=2, fillColor=None)
    path.moveTo(pts[0][0], pts[0][1])
    for px, py in pts[1:]:
        path.lineTo(px, py)
    d.add(path)

    # annotations
    d.add(Line(ox+aw*0.10, oy+ah*0.35, ox+aw*0.10, oy+ah*0.35+30,
               strokeColor=colors.HexColor("#9ca3af"), strokeWidth=0.7, strokeDashArray=[2,2]))
    d.add(String(ox+aw*0.05, oy+ah*0.35+32, "Threshold\n-50 mV", fontName='Helvetica', fontSize=6.5, fillColor=RED))

    d.add(Line(ox+aw*0.25, oy+ah, ox+aw*0.25, oy+ah+10,
               strokeColor=colors.HexColor("#9ca3af"), strokeWidth=0.7, strokeDashArray=[2,2]))
    d.add(String(ox+aw*0.22, oy+ah+11, "Peak\n+30mV", fontName='Helvetica', fontSize=6.5, fillColor=RED))

    # duration bar
    d.add(Line(ox+aw*0.10, oy+ah*0.35-12, ox+aw*0.65, oy+ah*0.35-12, strokeColor=ORANGE, strokeWidth=1))
    d.add(String(ox+aw*0.3, oy+ah*0.35-20, "Duration: 2-4 ms", fontName='Helvetica', fontSize=7, fillColor=ORANGE))

    # phases
    d.add(String(ox+aw*0.14, oy+ah*0.70, "Depol.", fontName='Helvetica', fontSize=6.5, fillColor=GREEN))
    d.add(String(ox+aw*0.36, oy+ah*0.55, "Repol.", fontName='Helvetica', fontSize=6.5, fillColor=PURPLE))
    d.add(String(ox+aw*0.44, oy+ah*0.20, "After-\nhyperpol.", fontName='Helvetica', fontSize=6.5, fillColor=TEAL))

    # ARP marker
    d.add(Rect(ox+aw*0.10, oy+3, aw*0.28, 8, fillColor=colors.HexColor("#fecaca"),
               strokeColor=None, rx=2))
    d.add(String(ox+aw*0.16, oy+5.5, "ARP (1-3 ms)", fontName='Helvetica', fontSize=6.5, fillColor=RED))

    return d


def muscle_twitch_diagram(width=460, height=160):
    """Muscle twitch with latent, contraction, relaxation phases."""
    d = Drawing(width, height)
    d.add(Rect(0, 0, width, height, fillColor=colors.HexColor("#f8fafc"), strokeColor=LGRAY, strokeWidth=0.5))
    d.add(String(width/2 - 70, height-14, "Skeletal Muscle Twitch",
                 fontName='Helvetica-Bold', fontSize=9, fillColor=NAVY))

    ox, oy, aw, ah = 45, 15, width-65, height-48

    d.add(Line(ox, oy, ox, oy+ah, strokeColor=GRAY, strokeWidth=1))
    d.add(Line(ox, oy+12, ox+aw, oy+12, strokeColor=GRAY, strokeWidth=1))

    d.add(String(ox-40, oy+ah-6, "Force", fontName='Helvetica-Bold', fontSize=7, fillColor=NAVY))
    d.add(String(ox+aw-18, oy+5, "Time", fontName='Helvetica-Bold', fontSize=7, fillColor=NAVY))

    # Twitch curve
    pts = [
        (ox, oy+12),
        (ox+aw*0.08, oy+12),        # latent
        (ox+aw*0.35, oy+ah),        # peak contraction
        (ox+aw*0.75, oy+12),        # relaxation
        (ox+aw, oy+12),
    ]
    path = Path(strokeColor=TEAL, strokeWidth=2.5, fillColor=None)
    path.moveTo(pts[0][0], pts[0][1])
    path.lineTo(pts[1][0], pts[1][1])
    path.curveTo(pts[1][0]+aw*0.08, pts[1][1], pts[2][0]-aw*0.05, pts[2][1], pts[2][0], pts[2][1])
    path.curveTo(pts[2][0]+aw*0.05, pts[2][1], pts[3][0]-aw*0.1, pts[3][1], pts[3][0], pts[3][1])
    path.lineTo(pts[4][0], pts[4][1])
    d.add(path)

    # Phase separators
    x_lat  = ox+aw*0.08
    x_peak = ox+aw*0.35
    x_end  = ox+aw*0.75

    for x in [x_lat, x_peak, x_end]:
        d.add(Line(x, oy+12, x, oy-5, strokeColor=GRAY, strokeWidth=0.7, strokeDashArray=[2,2]))

    # Phase labels under X axis
    def phase_label(x1, x2, label, clr):
        mx = (x1+x2)/2
        d.add(Line(x1+2, oy-2, x2-2, oy-2, strokeColor=clr, strokeWidth=1.2))
        d.add(String(mx-len(label)*2.5, oy-14, label, fontName='Helvetica', fontSize=7, fillColor=clr))

    phase_label(ox, x_lat, "Latent", ORANGE)
    phase_label(x_lat, x_peak, "Contraction", GREEN)
    phase_label(x_peak, x_end, "Relaxation", PURPLE)

    # Stimulus arrow
    d.add(String(ox+2, oy+12+3, "Stimulus", fontName='Helvetica', fontSize=6.5, fillColor=RED))

    # Peak label
    d.add(String(x_peak+3, oy+ah-5, "Peak tension", fontName='Helvetica', fontSize=6.5, fillColor=TEAL))

    return d


def sarcomere_diagram(width=460, height=130):
    """Simplified sarcomere / sliding filament."""
    d = Drawing(width, height)
    d.add(Rect(0, 0, width, height, fillColor=colors.HexColor("#f8fafc"), strokeColor=LGRAY, strokeWidth=0.5))
    d.add(String(width/2 - 85, height-14, "Sarcomere Structure & Sliding Filament Theory",
                 fontName='Helvetica-Bold', fontSize=9, fillColor=NAVY))

    cy = height/2 + 5
    # Z lines
    for x in [50, width-50]:
        d.add(Line(x, cy-28, x, cy+28, strokeColor=NAVY, strokeWidth=3))
        label = "Z line"
        d.add(String(x-12, cy+32, label, fontName='Helvetica', fontSize=7, fillColor=NAVY))

    # Sarcomere brace
    d.add(Line(50, cy-40, width-50, cy-40, strokeColor=GRAY, strokeWidth=0.7))
    d.add(String(width/2 - 25, cy-50, "Sarcomere", fontName='Helvetica-Bold', fontSize=8, fillColor=GRAY))

    # Thick filaments (myosin) - centre
    for y_off in [-8, 8]:
        d.add(Rect(120, cy+y_off-4, width-240, 8, fillColor=colors.HexColor("#dc2626"),
                   strokeColor=None, rx=4))
    d.add(String(width/2-20, cy-22, "Myosin (thick)", fontName='Helvetica', fontSize=7, fillColor=RED))

    # Thin filaments (actin) - full length
    for y_off in [-18, 18]:
        d.add(Rect(52, cy+y_off-3, width-106, 6, fillColor=colors.HexColor("#2563eb"),
                   strokeColor=None, rx=3))
    d.add(String(60, cy+24, "Actin (thin)", fontName='Helvetica', fontSize=7, fillColor=BLUE))

    # Cross bridges
    for x in range(135, width-130, 35):
        d.add(Line(x, cy-8, x+8, cy-18, strokeColor=ORANGE, strokeWidth=1.2))
        d.add(Line(x, cy+8, x+8, cy+18, strokeColor=ORANGE, strokeWidth=1.2))

    # M line
    d.add(Line(width/2, cy-28, width/2, cy+28, strokeColor=ORANGE, strokeWidth=1.5, strokeDashArray=[3,2]))
    d.add(String(width/2+3, cy+30, "M line", fontName='Helvetica', fontSize=7, fillColor=ORANGE))

    # Legend
    legend_x = width - 130
    d.add(Rect(legend_x-5, 5, 130, 42, fillColor=WHITE, strokeColor=LGRAY, strokeWidth=0.5, rx=3))
    d.add(Rect(legend_x, 35, 18, 7, fillColor=RED, strokeColor=None, rx=2))
    d.add(String(legend_x+22, 35, "Myosin (thick)", fontName='Helvetica', fontSize=7, fillColor=BLACK))
    d.add(Rect(legend_x, 22, 18, 7, fillColor=BLUE, strokeColor=None, rx=2))
    d.add(String(legend_x+22, 22, "Actin (thin)", fontName='Helvetica', fontSize=7, fillColor=BLACK))
    d.add(Line(legend_x, 12, legend_x+18, 12, strokeColor=ORANGE, strokeWidth=1.2))
    d.add(String(legend_x+22, 8, "Cross bridges", fontName='Helvetica', fontSize=7, fillColor=BLACK))

    return d


def contraction_types_diagram(width=460, height=155):
    """Isometric vs isotonic contraction."""
    d = Drawing(width, height)
    d.add(Rect(0, 0, width, height, fillColor=colors.HexColor("#f8fafc"), strokeColor=LGRAY, strokeWidth=0.5))
    d.add(String(width/2-80, height-14, "Types of Muscle Contraction",
                 fontName='Helvetica-Bold', fontSize=9, fillColor=NAVY))

    half = width/2 - 10
    # Isometric box
    d.add(Rect(8, 12, half-8, height-30, fillColor=LRED, strokeColor=RED, strokeWidth=1, rx=4))
    d.add(String(half/2-30, height-26, "ISOMETRIC", fontName='Helvetica-Bold', fontSize=9, fillColor=RED))

    # muscle bar - constant length
    bar_y = height/2
    for x in [25, half-40]:
        d.add(Rect(x, bar_y-6, 15, 12, fillColor=RED, strokeColor=None, rx=3))
    d.add(Rect(40, bar_y-4, half-75, 8, fillColor=colors.HexColor("#f87171"), strokeColor=None))
    # wall
    for y in range(int(bar_y)-20, int(bar_y)+22, 8):
        d.add(Line(half-28, y, half-20, y+6, strokeColor=NAVY, strokeWidth=1.5))
    d.add(Line(half-28, bar_y-20, half-28, bar_y+22, strokeColor=NAVY, strokeWidth=2))
    d.add(String(25, bar_y-24, "No change in length", fontName='Helvetica', fontSize=7.5, fillColor=RED))
    d.add(String(25, bar_y-34, "Tension increases", fontName='Helvetica', fontSize=7.5, fillColor=RED))
    d.add(String(25, 18, "e.g. pushing a wall", fontName='Helvetica-Oblique', fontSize=7, fillColor=GRAY))

    # Isotonic box
    ox2 = half + 12
    d.add(Rect(ox2, 12, half-8, height-30, fillColor=LGREEN, strokeColor=GREEN, strokeWidth=1, rx=4))
    d.add(String(ox2 + (half-8)/2 - 32, height-26, "ISOTONIC", fontName='Helvetica-Bold', fontSize=9, fillColor=GREEN))

    # muscle bar - shortening
    cx = ox2 + 20
    d.add(Rect(cx, bar_y-6, 12, 12, fillColor=GREEN, strokeColor=None, rx=3))
    # shorter after contraction
    d.add(Rect(cx+12, bar_y-4, half-80, 8, fillColor=colors.HexColor("#86efac"), strokeColor=None))
    d.add(Rect(cx+half-70, bar_y-6, 12, 12, fillColor=GREEN, strokeColor=None, rx=3))
    # weight
    d.add(Rect(cx+half-64, bar_y-18, 20, 14, fillColor=YELLOW, strokeColor=None, rx=2))
    d.add(String(cx+half-60, bar_y-14, "W", fontName='Helvetica-Bold', fontSize=8, fillColor=WHITE))
    # arrow showing shortening
    d.add(Line(cx+12, bar_y+14, cx+half-80, bar_y+14, strokeColor=GREEN, strokeWidth=1.2))
    d.add(String(cx+20, bar_y+16, "shortening", fontName='Helvetica', fontSize=7, fillColor=GREEN))
    d.add(String(cx, bar_y-24, "Length decreases", fontName='Helvetica', fontSize=7.5, fillColor=GREEN))
    d.add(String(cx, bar_y-34, "Tension constant", fontName='Helvetica', fontSize=7.5, fillColor=GREEN))
    d.add(String(cx, 18, "e.g. lifting a weight", fontName='Helvetica-Oblique', fontSize=7, fillColor=GRAY))

    return d


def tetanus_diagram(width=460, height=155):
    """Single twitch, summation, incomplete & complete tetanus."""
    d = Drawing(width, height)
    d.add(Rect(0, 0, width, height, fillColor=colors.HexColor("#f8fafc"), strokeColor=LGRAY, strokeWidth=0.5))
    d.add(String(width/2-95, height-14, "Summation, Incomplete & Complete Tetanus",
                 fontName='Helvetica-Bold', fontSize=9, fillColor=NAVY))

    ox, oy, aw, ah = 45, 18, width-60, height-50

    d.add(Line(ox, oy, ox, oy+ah, strokeColor=GRAY, strokeWidth=1))
    d.add(Line(ox, oy+10, ox+aw, oy+10, strokeColor=GRAY, strokeWidth=1))
    d.add(String(ox-40, oy+ah/2, "Tension", fontName='Helvetica-Bold', fontSize=7, fillColor=NAVY))

    def twitch_curve(start_x, peak_h, clr, width_frac=0.12):
        px = start_x + aw*width_frac*0.6
        path = Path(strokeColor=clr, strokeWidth=1.8, fillColor=None)
        path.moveTo(start_x, oy+10)
        path.curveTo(start_x+aw*width_frac*0.3, oy+10,
                     px-aw*width_frac*0.1, oy+10+peak_h,
                     px, oy+10+peak_h)
        end_x = start_x + aw*width_frac*1.2
        path.curveTo(px+aw*width_frac*0.1, oy+10+peak_h,
                     end_x-aw*width_frac*0.1, oy+10,
                     end_x, oy+10)
        d.add(path)

    # Single twitch
    twitch_curve(ox+aw*0.02, ah*0.4, TEAL)
    d.add(String(ox+aw*0.01, oy+2, "Single\nTwitch", fontName='Helvetica', fontSize=6, fillColor=TEAL))

    # Summation (2 close twitches, second higher)
    base2 = ox+aw*0.22
    twitch_curve(base2, ah*0.4, BLUE, 0.10)
    twitch_curve(base2+aw*0.07, ah*0.55, BLUE, 0.10)
    d.add(String(base2+aw*0.01, oy+2, "Summation", fontName='Helvetica', fontSize=6, fillColor=BLUE))

    # Incomplete tetanus (wavy plateau)
    base3 = ox+aw*0.44
    # draw as a series of bumps
    path3 = Path(strokeColor=ORANGE, strokeWidth=1.8, fillColor=None)
    path3.moveTo(base3, oy+10)
    # rising
    path3.curveTo(base3+10, oy+10, base3+18, oy+10+ah*0.55, base3+22, oy+10+ah*0.55)
    for bx in range(int(base3+22), int(base3+aw*0.18), 12):
        path3.curveTo(bx+2, oy+10+ah*0.7, bx+6, oy+10+ah*0.45, bx+12, oy+10+ah*0.55)
    path3.curveTo(base3+aw*0.20, oy+10+ah*0.55, base3+aw*0.22, oy+10, base3+aw*0.22, oy+10)
    d.add(path3)
    d.add(String(base3+aw*0.01, oy+2, "Incomplete\nTetanus", fontName='Helvetica', fontSize=6, fillColor=ORANGE))

    # Complete tetanus (smooth plateau)
    base4 = ox+aw*0.70
    path4 = Path(strokeColor=RED, strokeWidth=2.2, fillColor=None)
    path4.moveTo(base4, oy+10)
    path4.curveTo(base4+8, oy+10, base4+14, oy+10+ah*0.78, base4+18, oy+10+ah*0.78)
    path4.lineTo(base4+aw*0.22, oy+10+ah*0.78)
    path4.curveTo(base4+aw*0.24, oy+10+ah*0.78, base4+aw*0.27, oy+10, base4+aw*0.27, oy+10)
    d.add(path4)
    d.add(String(base4+aw*0.01, oy+2, "Complete\nTetanus", fontName='Helvetica', fontSize=6, fillColor=RED))

    # stimulus markers
    for sx in [ox+aw*0.02, ox+aw*0.22, ox+aw*0.26, ox+aw*0.44,
               ox+aw*0.47, ox+aw*0.50, ox+aw*0.53, ox+aw*0.56,
               ox+aw*0.70, ox+aw*0.72, ox+aw*0.74, ox+aw*0.76, ox+aw*0.78]:
        d.add(Line(sx, oy+10-4, sx, oy+10-9, strokeColor=NAVY, strokeWidth=1))

    d.add(String(ox+aw*0.02, oy-10, "Stimuli", fontName='Helvetica', fontSize=6.5, fillColor=NAVY))

    return d


def starling_law_diagram(width=460, height=145):
    """Length-tension relationship (Starling's law for skeletal muscle)."""
    d = Drawing(width, height)
    d.add(Rect(0, 0, width, height, fillColor=colors.HexColor("#f8fafc"), strokeColor=LGRAY, strokeWidth=0.5))
    d.add(String(width/2-105, height-14, "Length-Tension Relationship (Starling's Law of Muscle)",
                 fontName='Helvetica-Bold', fontSize=9, fillColor=NAVY))

    ox, oy, aw, ah = 55, 18, width-80, height-50

    d.add(Line(ox, oy, ox, oy+ah, strokeColor=GRAY, strokeWidth=1))
    d.add(Line(ox, oy, ox+aw, oy, strokeColor=GRAY, strokeWidth=1))
    d.add(String(ox-50, oy+ah/2, "Tension", fontName='Helvetica-Bold', fontSize=7.5, fillColor=NAVY))
    d.add(String(ox+aw/2-20, oy-14, "Initial Muscle Length", fontName='Helvetica-Bold', fontSize=7.5, fillColor=NAVY))

    # Bell-shaped curve
    import math
    pts = []
    for i in range(101):
        x_frac = i/100
        x = ox + aw*x_frac
        # Gaussian-like curve peaking at 60%
        y_frac = math.exp(-((x_frac - 0.60)**2) / (2*0.18**2))
        y = oy + ah*0.92*y_frac
        pts.append((x, y))

    path = Path(strokeColor=PURPLE, strokeWidth=2.5, fillColor=None)
    path.moveTo(pts[0][0], pts[0][1])
    for px, py in pts[1:]:
        path.lineTo(px, py)
    d.add(path)

    # Optimal length marker
    opt_x = ox + aw*0.60
    d.add(Line(opt_x, oy, opt_x, oy+ah*0.95, strokeColor=GREEN, strokeWidth=1, strokeDashArray=[3,2]))
    d.add(String(opt_x-5, oy+ah*0.96+2, "Optimal\nLength", fontName='Helvetica', fontSize=7, fillColor=GREEN))
    d.add(String(opt_x-18, oy+ah*0.93+12, "Max Tension", fontName='Helvetica-Bold', fontSize=7, fillColor=GREEN))

    # Zones
    d.add(String(ox+5, oy+5, "Too\nshort", fontName='Helvetica', fontSize=7, fillColor=ORANGE))
    d.add(String(ox+aw*0.82, oy+5, "Too\nlong", fontName='Helvetica', fontSize=7, fillColor=ORANGE))
    d.add(String(ox+aw*0.48, oy+ah*0.5, "Optimal zone", fontName='Helvetica', fontSize=7.5, fillColor=PURPLE))

    return d


def properties_mind_map(width=460, height=200):
    """Central node with 5 property branches."""
    d = Drawing(width, height)
    d.add(Rect(0, 0, width, height, fillColor=colors.HexColor("#f8fafc"), strokeColor=LGRAY, strokeWidth=0.5))

    cx, cy = width/2, height/2+8
    # Central node
    d.add(Circle(cx, cy, 38, fillColor=NAVY, strokeColor=None))
    d.add(String(cx-28, cy+5, "SKELETAL", fontName='Helvetica-Bold', fontSize=8, fillColor=WHITE))
    d.add(String(cx-22, cy-6, "MUSCLE", fontName='Helvetica-Bold', fontSize=8, fillColor=WHITE))
    d.add(String(cx-24, cy-17, "PROPERTIES", fontName='Helvetica-Bold', fontSize=7, fillColor=LBLUE))

    import math
    props = [
        ("EXCITABILITY", BLUE,   90,  -70),
        ("CONDUCTIVITY", TEAL,   60,   70),
        ("CONTRACTILITY", GREEN, -30,   90),
        ("EXTENSIBILITY", ORANGE,-80,  -20),
        ("ELASTICITY",   PURPLE, -20,  -80),
    ]

    for name, clr, dx, dy in props:
        ex, ey = cx+dx, cy+dy
        # spoke
        d.add(Line(cx+28*(dx/abs(dx) if dx != 0 else 0)*0.8,
                   cy+28*(dy/abs(dy) if dy != 0 else 0)*0.8,
                   ex, ey, strokeColor=clr, strokeWidth=1.8))
        # node
        d.add(Rect(ex-38, ey-10, 76, 20, fillColor=clr, strokeColor=None, rx=8))
        d.add(String(ex-len(name)*2.8, ey-4, name, fontName='Helvetica-Bold', fontSize=7, fillColor=WHITE))

    d.add(String(5, 5, "Fig: Mind Map - Properties of Skeletal Muscle",
                 fontName='Helvetica-Oblique', fontSize=7, fillColor=GRAY))
    return d


# ─── Cover page ───────────────────────────────────────────────────
def cover_page():
    elems = []
    # full-width header block
    cover_bg = Drawing(W - 3.6*cm, 160)
    cover_bg.add(Rect(0, 0, W-3.6*cm, 160, fillColor=NAVY, strokeColor=None, rx=6))
    # decorative circles
    for cx_, cy_, r_, alpha_ in [(320,130,60,0.12),(30,20,45,0.10),(W-120,40,80,0.08)]:
        cover_bg.add(Circle(cx_, cy_, r_, fillColor=WHITE, strokeColor=None,
                            fillOpacity=alpha_))
    cover_bg.add(String(20, 118, "KNRUSH UNIVERSITY", fontName='Helvetica-Bold', fontSize=11, fillColor=LBLUE))
    cover_bg.add(String(20, 100, "Bachelor of Physiotherapy (BPT)", fontName='Helvetica', fontSize=9.5, fillColor=LBLUE))
    cover_bg.add(String(20, 75, "PROPERTIES OF", fontName='Helvetica-Bold', fontSize=26, fillColor=WHITE))
    cover_bg.add(String(20, 48, "SKELETAL MUSCLE", fontName='Helvetica-Bold', fontSize=26, fillColor=YELLOW))
    cover_bg.add(String(20, 28, "Based on: Sembulingam's Essentials of Medical Physiology",
                        fontName='Helvetica', fontSize=9, fillColor=LBLUE))
    cover_bg.add(String(20, 14, "Chapter 26  |  Physiology Study Notes with Diagrams",
                        fontName='Helvetica', fontSize=8.5, fillColor=LGRAY))
    elems.append(cover_bg)
    elems.append(Spacer(1, 0.4*cm))

    # Mind map
    elems.append(properties_mind_map(W-3.6*cm, 200))
    elems.append(Paragraph("<i>Fig 1: Overview - Properties of Skeletal Muscle</i>", S['caption']))
    elems.append(Spacer(1, 0.3*cm))

    # Quick overview table
    data = [
        [Paragraph("Property", S['table_hdr']),
         Paragraph("Type", S['table_hdr']),
         Paragraph("One-line definition", S['table_hdr'])],
        [Paragraph("Excitability", S['table_body']), Paragraph("Electrical", S['table_body']),
         Paragraph("Ability to receive and respond to a stimulus", S['table_body'])],
        [Paragraph("Conductivity", S['table_body']), Paragraph("Electrical", S['table_body']),
         Paragraph("Propagate action potentials along sarcolemma (3-5 m/s)", S['table_body'])],
        [Paragraph("Contractility", S['table_body']), Paragraph("Mechanical", S['table_body']),
         Paragraph("Shorten and develop tension when stimulated", S['table_body'])],
        [Paragraph("Extensibility", S['table_body']), Paragraph("Mechanical", S['table_body']),
         Paragraph("Stretch beyond resting length without damage", S['table_body'])],
        [Paragraph("Elasticity", S['table_body']), Paragraph("Mechanical", S['table_body']),
         Paragraph("Recoil to original resting length after stretch", S['table_body'])],
    ]
    col_w = [(W-3.6*cm)*f for f in [0.22, 0.18, 0.60]]
    t = Table(data, colWidths=col_w)
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), NAVY),
        ('BACKGROUND', (0,1), (-1,1), LBLUE),
        ('BACKGROUND', (0,2), (-1,2), LTEAL),
        ('BACKGROUND', (0,3), (-1,3), LGREEN),
        ('BACKGROUND', (0,4), (-1,4), LORANGE),
        ('BACKGROUND', (0,5), (-1,5), LPURPLE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#cbd5e1")),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
    ]))
    elems.append(t)
    elems.append(Paragraph("<i>Table 1: Classification of Skeletal Muscle Properties</i>", S['caption']))
    return elems


# ─── Section 1: Electrical Properties ───────────────────────────
def electrical_section():
    elems = []
    elems.append(PageBreak())
    elems.append(section_header("A.  ELECTRICAL PROPERTIES"))
    elems.append(Spacer(1, 0.25*cm))

    # --- 1. Excitability ---
    elems.append(subsection_bar("1.  EXCITABILITY (Irritability)"))
    elems.append(Spacer(1, 0.1*cm))

    elems.append(Paragraph(
        "Excitability is the ability of the skeletal muscle to receive and respond to a stimulus. "
        "A stimulus can be electrical, chemical, or mechanical in nature.", S['body']))

    # AP values table
    ap_data = [
        [Paragraph("Parameter", S['table_hdr']), Paragraph("Value", S['table_hdr'])],
        [Paragraph("Resting Membrane Potential (RMP)", S['table_body']), Paragraph("-90 mV", S['table_body'])],
        [Paragraph("Threshold / Firing Level", S['table_body']), Paragraph("-50 mV", S['table_body'])],
        [Paragraph("Amplitude of Action Potential", S['table_body']), Paragraph("120 mV", S['table_body'])],
        [Paragraph("Duration of Action Potential", S['table_body']), Paragraph("2 - 4 ms", S['table_body'])],
        [Paragraph("Absolute Refractory Period (ARP)", S['table_body']), Paragraph("1 - 3 ms", S['table_body'])],
        [Paragraph("Conduction Velocity", S['table_body']), Paragraph("3 - 5 m/s", S['table_body'])],
    ]
    col_w2 = [(W-3.6*cm)*f for f in [0.65, 0.35]]
    t2 = Table(ap_data, colWidths=col_w2)
    t2.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), BLUE),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LBLUE]),
        ('GRID', (0,0), (-1,-1), 0.4, colors.HexColor("#bfdbfe")),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('TOPPADDING', (0,0), (-1,-1), 4),
        ('BOTTOMPADDING', (0,0), (-1,-1), 4),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
    ]))
    elems.append(t2)
    elems.append(Paragraph("<i>Table 2: Action Potential Parameters - Skeletal Muscle</i>", S['caption']))
    elems.append(Spacer(1, 0.2*cm))

    # AP diagram
    elems.append(ap_diagram(W-3.6*cm, 185))
    elems.append(Paragraph("<i>Fig 2: Action Potential of Skeletal Muscle</i>", S['caption']))
    elems.append(Spacer(1, 0.2*cm))

    elems.append(bullet("Single muscle fiber obeys the <b>All-or-None Law</b> - fires maximally or not at all."))
    elems.append(bullet("The whole skeletal muscle does <b>NOT</b> obey all-or-none law (different fibers have different thresholds)."))
    elems.append(bullet("Muscle can be stimulated <b>directly</b> (electrode on muscle) or <b>indirectly</b> (via motor nerve)."))
    elems.append(bullet("Mechanical activity begins only when the electrical activity is <b>about to end</b>."))
    elems.append(bullet("Because ARP ends before the mechanical response begins, <b>tetanization is possible</b> in skeletal muscle."))

    elems.append(Spacer(1, 0.15*cm))
    elems.append(info_box(
        "<b>EXAM TIP:</b> Cardiac muscle obeys all-or-none law for the WHOLE muscle (syncytium) and cannot be tetanized "
        "because its ARP (200-300 ms) lasts as long as the mechanical response. Skeletal muscle CAN be tetanized.",
        bg=LYELLOW, border=YELLOW))
    elems.append(Spacer(1, 0.3*cm))

    # --- 2. Conductivity ---
    elems.append(subsection_bar("2.  CONDUCTIVITY"))
    elems.append(Spacer(1, 0.1*cm))
    elems.append(Paragraph(
        "Conductivity is the ability of the muscle to propagate action potentials along the sarcolemma "
        "in both directions from the point of stimulation.", S['body']))
    elems.append(bullet("Conduction velocity: <b>3 - 5 m/s</b> (similar to unmyelinated nerve fibers)"))
    elems.append(bullet("Action potential travels along the sarcolemma and enters the muscle via <b>T-tubules</b>"))
    elems.append(bullet("T-tubules trigger Ca²⁺ release from sarcoplasmic reticulum (SR) - the basis of <b>excitation-contraction coupling</b>"))
    elems.append(bullet("Ca²⁺ binds troponin C → tropomyosin shifts → myosin cross-bridge formation proceeds"))

    return elems


# ─── Section 2: Mechanical Properties ────────────────────────────
def mechanical_section():
    elems = []
    elems.append(PageBreak())
    elems.append(section_header("B.  MECHANICAL PROPERTIES", bg=TEAL))
    elems.append(Spacer(1, 0.25*cm))

    # --- 3. Contractility ---
    elems.append(subsection_bar("3.  CONTRACTILITY", bg=GREEN))
    elems.append(Spacer(1, 0.1*cm))
    elems.append(Paragraph(
        "Contractility is the ability of the skeletal muscle to shorten and develop tension (force) "
        "when stimulated by an action potential. It is the fundamental property underlying all movement.",
        S['body']))

    # Sarcomere diagram
    elems.append(sarcomere_diagram(W-3.6*cm, 135))
    elems.append(Paragraph("<i>Fig 3: Sarcomere Structure and Sliding Filament Theory</i>", S['caption']))
    elems.append(Spacer(1, 0.15*cm))

    elems.append(Paragraph("<b>Sliding Filament Theory:</b>", S['h3']))
    elems.append(bullet("Actin (thin) filaments slide over myosin (thick) filaments → sarcomere shortens"))
    elems.append(bullet("Filament length does NOT change - only degree of overlap changes"))
    elems.append(bullet("Requires ATP hydrolysis by myosin ATPase for cross-bridge cycling"))

    elems.append(Spacer(1, 0.2*cm))

    # Muscle twitch diagram
    elems.append(muscle_twitch_diagram(W-3.6*cm, 160))
    elems.append(Paragraph("<i>Fig 4: Skeletal Muscle Twitch - Latent, Contraction and Relaxation Phases</i>", S['caption']))
    elems.append(Spacer(1, 0.15*cm))

    elems.append(Paragraph("<b>Phases of a Single Muscle Twitch:</b>", S['h3']))
    twitch_data = [
        [Paragraph("Phase", S['table_hdr']), Paragraph("Duration", S['table_hdr']),
         Paragraph("Description", S['table_hdr'])],
        [Paragraph("Latent period", S['table_body']), Paragraph("~2 ms", S['table_body']),
         Paragraph("Delay between stimulus and onset of contraction; E-C coupling occurs", S['table_body'])],
        [Paragraph("Contraction phase", S['table_body']), Paragraph("~40 ms", S['table_body']),
         Paragraph("Tension rises to peak; cross-bridge cycling; Ca²⁺ released", S['table_body'])],
        [Paragraph("Relaxation phase", S['table_body']), Paragraph("~50 ms", S['table_body']),
         Paragraph("Tension falls; Ca²⁺ pumped back to SR; cross-bridges detach", S['table_body'])],
    ]
    col_w3 = [(W-3.6*cm)*f for f in [0.22, 0.15, 0.63]]
    t3 = Table(twitch_data, colWidths=col_w3)
    t3.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), TEAL),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LTEAL]),
        ('GRID', (0,0), (-1,-1), 0.4, colors.HexColor("#99f6e4")),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('TOPPADDING', (0,0), (-1,-1), 4),
        ('BOTTOMPADDING', (0,0), (-1,-1), 4),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
    ]))
    elems.append(t3)
    elems.append(Paragraph("<i>Table 3: Phases of a Single Muscle Twitch</i>", S['caption']))
    elems.append(Spacer(1, 0.2*cm))

    # Types of contraction
    elems.append(contraction_types_diagram(W-3.6*cm, 160))
    elems.append(Paragraph("<i>Fig 5: Types of Muscle Contraction - Isometric vs Isotonic</i>", S['caption']))
    elems.append(Spacer(1, 0.15*cm))

    contr_data = [
        [Paragraph("Feature", S['table_hdr']), Paragraph("Isometric", S['table_hdr']),
         Paragraph("Isotonic", S['table_hdr'])],
        [Paragraph("Muscle length", S['table_body']), Paragraph("No change", S['table_body']),
         Paragraph("Decreases (shortens)", S['table_body'])],
        [Paragraph("Tension", S['table_body']), Paragraph("Increases", S['table_body']),
         Paragraph("Remains constant", S['table_body'])],
        [Paragraph("External work", S['table_body']), Paragraph("No (energy → heat)", S['table_body']),
         Paragraph("Yes (moves a load)", S['table_body'])],
        [Paragraph("Examples", S['table_body']), Paragraph("Pushing a wall, postural muscles", S['table_body']),
         Paragraph("Lifting weight, walking", S['table_body'])],
    ]
    col_w4 = [(W-3.6*cm)*f for f in [0.25, 0.38, 0.37]]
    t4 = Table(contr_data, colWidths=col_w4)
    t4.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), GREEN),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LGREEN]),
        ('GRID', (0,0), (-1,-1), 0.4, colors.HexColor("#bbf7d0")),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('TOPPADDING', (0,0), (-1,-1), 4),
        ('BOTTOMPADDING', (0,0), (-1,-1), 4),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
    ]))
    elems.append(t4)
    elems.append(Paragraph("<i>Table 4: Isometric vs Isotonic Contraction</i>", S['caption']))

    return elems


# ─── Section 3: Summation & Tetanus + Starling's Law ─────────────
def advanced_contractility():
    elems = []
    elems.append(PageBreak())
    elems.append(section_header("SUMMATION, TETANUS & FACTORS AFFECTING CONTRACTION", bg=PURPLE))
    elems.append(Spacer(1, 0.25*cm))

    elems.append(tetanus_diagram(W-3.6*cm, 158))
    elems.append(Paragraph("<i>Fig 6: Summation and Tetanus in Skeletal Muscle</i>", S['caption']))
    elems.append(Spacer(1, 0.2*cm))

    tetanus_data = [
        [Paragraph("Type", S['table_hdr']), Paragraph("Mechanism", S['table_hdr']),
         Paragraph("Result", S['table_hdr'])],
        [Paragraph("Single Twitch", S['table_body']), Paragraph("One stimulus", S['table_body']),
         Paragraph("Brief contraction and relaxation", S['table_body'])],
        [Paragraph("Summation", S['table_body']), Paragraph("Second stimulus before complete relaxation", S['table_body']),
         Paragraph("Greater tension than single twitch", S['table_body'])],
        [Paragraph("Incomplete Tetanus", S['table_body']), Paragraph("Rapid stimuli with partial relaxation", S['table_body']),
         Paragraph("Wavy sustained contraction", S['table_body'])],
        [Paragraph("Complete Tetanus", S['table_body']), Paragraph("Very rapid stimuli, no relaxation", S['table_body']),
         Paragraph("Smooth maximal sustained contraction", S['table_body'])],
        [Paragraph("Staircase (Treppe)", S['table_body']),
         Paragraph("Low freq successive stimuli; more Ca²⁺ available", S['table_body']),
         Paragraph("Progressively stronger twitches", S['table_body'])],
    ]
    col_w5 = [(W-3.6*cm)*f for f in [0.24, 0.38, 0.38]]
    t5 = Table(tetanus_data, colWidths=col_w5)
    t5.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), PURPLE),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LPURPLE]),
        ('GRID', (0,0), (-1,-1), 0.4, colors.HexColor("#ddd6fe")),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('TOPPADDING', (0,0), (-1,-1), 4),
        ('BOTTOMPADDING', (0,0), (-1,-1), 4),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
    ]))
    elems.append(t5)
    elems.append(Paragraph("<i>Table 5: Types of Muscle Response</i>", S['caption']))
    elems.append(Spacer(1, 0.25*cm))

    # Starling's law
    elems.append(subsection_bar("Starling's Law of Skeletal Muscle (Length-Tension Relationship)", bg=PURPLE))
    elems.append(Spacer(1, 0.1*cm))
    elems.append(starling_law_diagram(W-3.6*cm, 148))
    elems.append(Paragraph("<i>Fig 7: Length-Tension Relationship in Skeletal Muscle</i>", S['caption']))
    elems.append(Spacer(1, 0.12*cm))
    elems.append(bullet("Force of contraction is maximum when muscle is at its <b>optimal resting length</b>"))
    elems.append(bullet("Too short: overlap of actin filaments from both sides → reduced cross-bridges"))
    elems.append(bullet("Too long: reduced overlap between actin and myosin → fewer cross-bridges"))
    elems.append(Spacer(1, 0.2*cm))

    elems.append(subsection_bar("Factors Affecting Force of Contraction", bg=colors.HexColor("#7c3aed")))
    elems.append(Spacer(1, 0.1*cm))

    factors_data = [
        [Paragraph("Factor", S['table_hdr']),
         Paragraph("Effect", S['table_hdr'])],
        [Paragraph("Stimulus strength", S['table_body']),
         Paragraph("More motor units recruited → greater force (up to maximal)", S['table_body'])],
        [Paragraph("Stimulus frequency", S['table_body']),
         Paragraph("Higher frequency → summation → tetanus → max force", S['table_body'])],
        [Paragraph("Initial muscle length", S['table_body']),
         Paragraph("Optimal length → maximal cross-bridge formation → max force", S['table_body'])],
        [Paragraph("Temperature", S['table_body']),
         Paragraph("Warm muscle → faster enzyme activity → more force (to a limit)", S['table_body'])],
        [Paragraph("Blood supply", S['table_body']),
         Paragraph("O₂ and glucose delivery → sustained contraction", S['table_body'])],
        [Paragraph("Fatigue", S['table_body']),
         Paragraph("ATP depletion, lactic acid accumulation → reduced force", S['table_body'])],
    ]
    col_w6 = [(W-3.6*cm)*f for f in [0.32, 0.68]]
    t6 = Table(factors_data, colWidths=col_w6)
    t6.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), colors.HexColor("#7c3aed")),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LPURPLE]),
        ('GRID', (0,0), (-1,-1), 0.4, colors.HexColor("#ddd6fe")),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('TOPPADDING', (0,0), (-1,-1), 4),
        ('BOTTOMPADDING', (0,0), (-1,-1), 4),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
    ]))
    elems.append(t6)
    elems.append(Paragraph("<i>Table 6: Factors Affecting Force of Skeletal Muscle Contraction</i>", S['caption']))

    return elems


# ─── Section 4: Extensibility & Elasticity ───────────────────────
def ext_elastic_section():
    elems = []
    elems.append(PageBreak())
    elems.append(section_header("EXTENSIBILITY & ELASTICITY", bg=ORANGE))
    elems.append(Spacer(1, 0.25*cm))

    # --- 4. Extensibility ---
    elems.append(subsection_bar("4.  EXTENSIBILITY", bg=ORANGE))
    elems.append(Spacer(1, 0.1*cm))
    elems.append(Paragraph(
        "Extensibility is the capacity of the muscle to be stretched beyond its resting length "
        "without being damaged. This property is essential for smooth, coordinated movement.",
        S['body']))
    elems.append(bullet("Antagonist muscles must lengthen when agonists contract"))
    elems.append(bullet("During elbow flexion: biceps contracts → triceps must extend"))
    elems.append(bullet("Loss of extensibility leads to <b>spasticity</b> (seen in UMN lesions)"))
    elems.append(bullet("Extensibility is limited by the connective tissue sheaths (epimysium, perimysium, endomysium)"))
    elems.append(bullet("Important for physiotherapy stretching exercises and range-of-motion assessment"))
    elems.append(Spacer(1, 0.2*cm))

    # Extensibility diagram
    ext_d = Drawing(W-3.6*cm, 120)
    ext_d.add(Rect(0, 0, W-3.6*cm, 120, fillColor=LORANGE, strokeColor=ORANGE, strokeWidth=0.5, rx=4))
    ext_d.add(String(10, 105, "Extensibility - Stretch Beyond Resting Length",
                     fontName='Helvetica-Bold', fontSize=9, fillColor=ORANGE))
    mid_y = 65
    # Resting muscle
    rx0 = 30
    ext_d.add(Rect(rx0, mid_y-8, 100, 16, fillColor=colors.HexColor("#fed7aa"), strokeColor=ORANGE, rx=5))
    ext_d.add(String(rx0+20, mid_y-4, "REST (100%)", fontName='Helvetica', fontSize=7.5, fillColor=ORANGE))
    # Arrow
    ext_d.add(Line(rx0+115, mid_y, rx0+155, mid_y, strokeColor=NAVY, strokeWidth=1.5))
    ext_d.add(String(rx0+118, mid_y+4, "Stretch", fontName='Helvetica', fontSize=7, fillColor=NAVY))
    # Stretched muscle
    ext_d.add(Rect(rx0+160, mid_y-8, 155, 16, fillColor=colors.HexColor("#fdba74"), strokeColor=ORANGE, rx=5))
    ext_d.add(String(rx0+195, mid_y-4, "STRETCHED (>100%)", fontName='Helvetica', fontSize=7.5, fillColor=ORANGE))
    # Labels
    ext_d.add(String(rx0+20, mid_y-22, "Resting Length", fontName='Helvetica', fontSize=7, fillColor=GRAY))
    ext_d.add(String(rx0+195, mid_y-22, "No damage within physiological limits",
                     fontName='Helvetica', fontSize=7, fillColor=GRAY))
    # Connective tissue label
    ext_d.add(String(10, 15, "Limited by: Titin protein | Connective tissue (epimysium, perimysium, endomysium)",
                     fontName='Helvetica-Oblique', fontSize=7.5, fillColor=colors.HexColor("#9a3412")))
    elems.append(ext_d)
    elems.append(Paragraph("<i>Fig 8: Extensibility - Muscle Stretch Without Damage</i>", S['caption']))
    elems.append(Spacer(1, 0.3*cm))

    # --- 5. Elasticity ---
    elems.append(subsection_bar("5.  ELASTICITY", bg=PURPLE))
    elems.append(Spacer(1, 0.1*cm))
    elems.append(Paragraph(
        "Elasticity is the ability of the muscle to return to its original resting length after "
        "being stretched or after contraction. It is a passive property dependent on the elastic "
        "components within the muscle fiber.",
        S['body']))
    elems.append(bullet("Due to <b>titin</b> (connectin) - the giant elastic protein spanning the sarcomere"))
    elems.append(bullet("Also contributed by surrounding connective tissue (endomysium, perimysium)"))
    elems.append(bullet("Helps maintain <b>muscle tone</b> and passive tension at rest"))
    elems.append(bullet("Prevents overstretching injury by generating passive restoring force"))
    elems.append(bullet("In physiotherapy: elastic recoil assists return to neutral position after stretch"))
    elems.append(Spacer(1, 0.2*cm))

    # Elasticity diagram
    elas_d = Drawing(W-3.6*cm, 120)
    elas_d.add(Rect(0, 0, W-3.6*cm, 120, fillColor=LPURPLE, strokeColor=PURPLE, strokeWidth=0.5, rx=4))
    elas_d.add(String(10, 105, "Elasticity - Recoil to Original Length After Stretch",
                      fontName='Helvetica-Bold', fontSize=9, fillColor=PURPLE))
    mid_y2 = 65
    rx1 = 20
    # States: rest → stretched → recoil
    for i, (label, w, clr) in enumerate([
        ("REST", 90, colors.HexColor("#c4b5fd")),
        ("STRETCHED", 155, colors.HexColor("#a78bfa")),
        ("RECOIL (back)", 90, colors.HexColor("#7c3aed")),
    ]):
        x = rx1 + i*160
        elas_d.add(Rect(x, mid_y2-8, w, 16, fillColor=clr, strokeColor=PURPLE, rx=5))
        elas_d.add(String(x+5, mid_y2-4, label, fontName='Helvetica-Bold', fontSize=7, fillColor=WHITE))
        if i < 2:
            arw = "→" if i == 0 else "→"
            lbl = "stretch" if i == 0 else "release"
            ax = x + w + 5
            elas_d.add(Line(ax, mid_y2, ax+22, mid_y2, strokeColor=GRAY, strokeWidth=1.3))
            elas_d.add(String(ax+1, mid_y2+4, lbl, fontName='Helvetica', fontSize=7, fillColor=GRAY))

    elas_d.add(String(10, 15, "Structural basis: Titin protein (sarcomere) + Connective tissue sheaths",
                      fontName='Helvetica-Oblique', fontSize=7.5, fillColor=colors.HexColor("#5b21b6")))
    elems.append(elas_d)
    elems.append(Paragraph("<i>Fig 9: Elasticity - Muscle Recoil After Stretch</i>", S['caption']))

    return elems


# ─── Section 5: Comparison & Quick Revision ──────────────────────
def comparison_section():
    elems = []
    elems.append(PageBreak())
    elems.append(section_header("COMPARISON & QUICK REVISION", bg=colors.HexColor("#0f766e")))
    elems.append(Spacer(1, 0.25*cm))

    # Skeletal vs Cardiac vs Smooth comparison
    elems.append(subsection_bar("Comparison: Skeletal vs Cardiac vs Smooth Muscle Properties", bg=colors.HexColor("#0f766e")))
    elems.append(Spacer(1, 0.1*cm))

    comp_data = [
        [Paragraph("Feature", S['table_hdr']),
         Paragraph("Skeletal Muscle", S['table_hdr']),
         Paragraph("Cardiac Muscle", S['table_hdr']),
         Paragraph("Smooth Muscle", S['table_hdr'])],
        [Paragraph("Control", S['table_body']),
         Paragraph("Voluntary", S['table_body']),
         Paragraph("Involuntary", S['table_body']),
         Paragraph("Involuntary", S['table_body'])],
        [Paragraph("RMP", S['table_body']),
         Paragraph("-90 mV", S['table_body']),
         Paragraph("-90 mV", S['table_body']),
         Paragraph("-50 to -60 mV", S['table_body'])],
        [Paragraph("AP duration", S['table_body']),
         Paragraph("2-4 ms", S['table_body']),
         Paragraph("200-300 ms", S['table_body']),
         Paragraph("10-50 ms", S['table_body'])],
        [Paragraph("All-or-None", S['table_body']),
         Paragraph("Single fiber only", S['table_body']),
         Paragraph("Whole muscle (syncytium)", S['table_body']),
         Paragraph("Variable", S['table_body'])],
        [Paragraph("Tetanus possible?", S['table_body']),
         Paragraph("YES", S['table_body']),
         Paragraph("NO (ARP = mechanical)", S['table_body']),
         Paragraph("YES (in some)", S['table_body'])],
        [Paragraph("Striations", S['table_body']),
         Paragraph("Present", S['table_body']),
         Paragraph("Present", S['table_body']),
         Paragraph("Absent", S['table_body'])],
        [Paragraph("Regeneration", S['table_body']),
         Paragraph("Limited (satellite cells)", S['table_body']),
         Paragraph("Poor", S['table_body']),
         Paragraph("Good", S['table_body'])],
    ]
    col_w7 = [(W-3.6*cm)*f for f in [0.22, 0.26, 0.26, 0.26]]
    t7 = Table(comp_data, colWidths=col_w7)
    t7.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), colors.HexColor("#0f766e")),
        ('BACKGROUND', (1,1), (1,-1), colors.HexColor("#e0f2fe")),
        ('BACKGROUND', (2,1), (2,-1), colors.HexColor("#fce7f3")),
        ('BACKGROUND', (3,1), (3,-1), colors.HexColor("#fef3c7")),
        ('BACKGROUND', (0,1), (0,-1), LGRAY),
        ('GRID', (0,0), (-1,-1), 0.4, colors.HexColor("#cbd5e1")),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('TOPPADDING', (0,0), (-1,-1), 4),
        ('BOTTOMPADDING', (0,0), (-1,-1), 4),
        ('LEFTPADDING', (0,0), (-1,-1), 5),
    ]))
    elems.append(t7)
    elems.append(Paragraph("<i>Table 7: Comparison of Muscle Types</i>", S['caption']))
    elems.append(Spacer(1, 0.3*cm))

    # One-line rapid revision
    elems.append(subsection_bar("RAPID REVISION - KEY NUMBERS TO REMEMBER", bg=RED))
    elems.append(Spacer(1, 0.1*cm))

    rev_data = [
        [Paragraph("Parameter", S['table_hdr']), Paragraph("Value", S['table_hdr']),
         Paragraph("Significance", S['table_hdr'])],
        [Paragraph("RMP", S['table_body']), Paragraph("-90 mV", S['table_body']),
         Paragraph("Resting state; K⁺ and Cl⁻ dominant", S['table_body'])],
        [Paragraph("Threshold", S['table_body']), Paragraph("-50 mV", S['table_body']),
         Paragraph("Level at which AP fires", S['table_body'])],
        [Paragraph("AP amplitude", S['table_body']), Paragraph("120 mV", S['table_body']),
         Paragraph("From RMP (-90) to peak (+30 mV)", S['table_body'])],
        [Paragraph("AP duration", S['table_body']), Paragraph("2-4 ms", S['table_body']),
         Paragraph("Very short - allows tetanization", S['table_body'])],
        [Paragraph("ARP", S['table_body']), Paragraph("1-3 ms", S['table_body']),
         Paragraph("Shorter than mechanical response - tetanus possible", S['table_body'])],
        [Paragraph("Conduction velocity", S['table_body']), Paragraph("3-5 m/s", S['table_body']),
         Paragraph("Along sarcolemma; similar to unmyelinated nerve", S['table_body'])],
    ]
    col_w8 = [(W-3.6*cm)*f for f in [0.24, 0.16, 0.60]]
    t8 = Table(rev_data, colWidths=col_w8)
    t8.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), RED),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LRED]),
        ('GRID', (0,0), (-1,-1), 0.4, colors.HexColor("#fca5a5")),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('TOPPADDING', (0,0), (-1,-1), 4),
        ('BOTTOMPADDING', (0,0), (-1,-1), 4),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
    ]))
    elems.append(t8)
    elems.append(Paragraph("<i>Table 8: Key Numbers - Skeletal Muscle Properties</i>", S['caption']))
    elems.append(Spacer(1, 0.3*cm))

    # Exam questions box
    elems.append(subsection_bar("PROBABLE EXAM QUESTIONS (KNRush BPT)", bg=colors.HexColor("#1d4ed8")))
    elems.append(Spacer(1, 0.1*cm))
    qs = [
        "1. Enumerate the properties of skeletal muscle and describe excitability in detail with the action potential.",
        "2. What is the All-or-None law? How does it apply to skeletal muscle vs cardiac muscle?",
        "3. Describe the types of muscle contraction with examples.",
        "4. Explain Starling's law as applied to skeletal muscle.",
        "5. What is tetanus? Differentiate complete and incomplete tetanus.",
        "6. Write a short note on: (a) Muscle twitch  (b) Treppe  (c) Extensibility  (d) Elasticity",
        "7. Compare skeletal, cardiac, and smooth muscle properties.",
        "8. Why can skeletal muscle be tetanized but not cardiac muscle?",
    ]
    for q in qs:
        elems.append(Paragraph(q, S['bullet']))

    return elems


# ─── Page numbering ───────────────────────────────────────────────
def add_page_num(canvas, doc):
    canvas.saveState()
    canvas.setFont('Helvetica', 7.5)
    canvas.setFillColor(GRAY)
    page_num = canvas.getPageNumber()
    canvas.drawString(2*cm, 1.2*cm, "KNRush University BPT | Skeletal Muscle Properties | Sembulingam Ch.26")
    canvas.drawRightString(W - 2*cm, 1.2*cm, f"Page {page_num}")
    canvas.restoreState()


# ─── Build PDF ────────────────────────────────────────────────────
def build():
    doc = SimpleDocTemplate(
        OUTPUT,
        pagesize=A4,
        leftMargin=1.8*cm, rightMargin=1.8*cm,
        topMargin=1.8*cm, bottomMargin=2*cm,
        title="Properties of Skeletal Muscle - BPT",
        author="KNRush University",
        subject="Sembulingam Medical Physiology"
    )

    story = []
    story += cover_page()
    story += electrical_section()
    story += mechanical_section()
    story += advanced_contractility()
    story += ext_elastic_section()
    story += comparison_section()

    doc.build(story, onFirstPage=add_page_num, onLaterPages=add_page_num)
    print(f"PDF saved: {OUTPUT}")

if __name__ == "__main__":
    build()
Your credits are exhausted. You can purchase a top-up or subscribe to a plan to continue using Orris. If you're already subscribed, your daily credits will reset tomorrow.

Chemical changes during muscle contraction according to Sembulingm for knrush university exam for bpt

Your credits are exhausted. You can purchase a top-up or subscribe to a plan to continue using Orris. If you're already subscribed, your daily credits will reset tomorrow.

Create a detailed PDF summary on chemical changes during muscle contraction

Your credits are exhausted. You can purchase a top-up or subscribe to a plan to continue using Orris. If you're already subscribed, your daily credits will reset tomorrow.
This is a shared conversation. Sign in to Orris to start your own chat.