Summarise the graphs and add in pdf
cd /home/daytona/workspace && python3 -c " import pdfplumber with pdfplumber.open('attachments/84a19c61-b7ff-405d-bf8a-144dd6e48bd6/Amphibian graphs OMC 2022.pdf') as pdf: print(f'Pages: {len(pdf.pages)}') for i, page in enumerate(pdf.pages): print(f'\n--- PAGE {i+1} ---') text = page.extract_text() print(text if text else '[No extractable text]') tables = page.extract_tables() if tables: for j, t in enumerate(tables): print(f'Table {j+1}: {t}') "
python3 << 'PYEOF' from reportlab.lib.pagesizes import A4 from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import cm from reportlab.lib import colors from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable, PageBreak from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY output_path = "/home/daytona/workspace/Amphibian_Graphs_Summary_OMC2022.pdf" doc = SimpleDocTemplate( output_path, pagesize=A4, rightMargin=2*cm, leftMargin=2*cm, topMargin=2*cm, bottomMargin=2*cm ) styles = getSampleStyleSheet() # Custom styles title_style = ParagraphStyle( 'CustomTitle', parent=styles['Title'], fontSize=20, textColor=colors.HexColor('#1a3c6e'), spaceAfter=6, spaceBefore=0, alignment=TA_CENTER ) subtitle_style = ParagraphStyle( 'Subtitle', parent=styles['Normal'], fontSize=11, textColor=colors.HexColor('#555555'), spaceAfter=20, alignment=TA_CENTER ) graph_title_style = ParagraphStyle( 'GraphTitle', parent=styles['Heading2'], fontSize=13, textColor=colors.white, spaceAfter=4, spaceBefore=0, alignment=TA_LEFT, leftIndent=8 ) body_style = ParagraphStyle( 'Body', parent=styles['Normal'], fontSize=10, leading=15, spaceAfter=6, alignment=TA_JUSTIFY ) bullet_style = ParagraphStyle( 'Bullet', parent=styles['Normal'], fontSize=10, leading=15, leftIndent=15, spaceAfter=3, bulletIndent=5 ) section_label_style = ParagraphStyle( 'SectionLabel', parent=styles['Normal'], fontSize=9, textColor=colors.HexColor('#1a3c6e'), spaceAfter=2, fontName='Helvetica-Bold' ) def make_graph_block(num, title, summary_points, key_terms=None): """Create a styled block for each graph summary.""" elements = [] # Header row with graph number + title header_data = [[Paragraph(f"Graph {num}: {title}", ParagraphStyle( 'GT', fontSize=12, textColor=colors.white, fontName='Helvetica-Bold', leftIndent=4 ))]] header_table = Table(header_data, colWidths=[17*cm]) header_table.setStyle(TableStyle([ ('BACKGROUND', (0,0), (-1,-1), colors.HexColor('#1a3c6e')), ('ROWPADDING', (0,0), (-1,-1), 7), ('BOX', (0,0), (-1,-1), 0.5, colors.HexColor('#0d2447')), ])) elements.append(header_table) # Content rows content_rows = [] for pt in summary_points: content_rows.append([Paragraph(f"• {pt}", body_style)]) if key_terms: kt_text = " | ".join([f"<b>{k}</b>: {v}" for k, v in key_terms.items()]) content_rows.append([Paragraph(f"<i>Key labels — {kt_text}</i>", ParagraphStyle('KT', parent=styles['Normal'], fontSize=9, textColor=colors.HexColor('#444444'), leading=13, spaceAfter=2))]) content_table = Table(content_rows, colWidths=[17*cm]) content_table.setStyle(TableStyle([ ('BACKGROUND', (0,0), (-1,-1), colors.HexColor('#f0f4fa')), ('ROWPADDING', (0,0), (-1,-1), 5), ('BOX', (0,0), (-1,-1), 0.5, colors.HexColor('#bccde8')), ('LINEBELOW', (0,0), (-1,-2), 0.3, colors.HexColor('#d0daea')), ])) elements.append(content_table) elements.append(Spacer(1, 10)) return elements story = [] # ---- TITLE PAGE ---- story.append(Spacer(1, 1.5*cm)) story.append(Paragraph("Amphibian Physiology Graphs", title_style)) story.append(Paragraph("OMC 2022 — Summary of All 14 Graphs", subtitle_style)) story.append(HRFlowable(width="100%", thickness=1.5, color=colors.HexColor('#1a3c6e'), spaceAfter=12)) story.append(Paragraph( "This document summarises the key concepts, observations, and physiological significance " "of all 14 graphs from the Amphibian (Frog) Physiology practical series, OMC 2022. " "Each graph is drawn on a kymograph using frog muscle or heart preparations and demonstrates " "fundamental principles of muscle and cardiac physiology.", body_style )) story.append(Spacer(1, 0.4*cm)) # Quick index index_data = [ [Paragraph("<b>#</b>", body_style), Paragraph("<b>Graph Title</b>", body_style)], ["1", "Simple Muscle Curve (Twitch)"], ["2", "Effect of Temperature on Simple Muscle Curve"], ["3", "Effect of Increasing Strength of Stimulus on Muscle Contraction"], ["4", "Effect of Two Successive Stimuli on Muscle Contraction"], ["5", "Genesis of Tetanus"], ["6", "Genesis of Fatigue"], ["7", "Effect of Load on Muscle Contraction"], ["8", "Conduction Velocity of Nerves in Frog"], ["9", "Normal Cardiogram"], ["10", "Effect of Temperature on Frog's Heart"], ["11", "Effect of Stannius Ligatures on Frog's Heart"], ["12", "Properties of Cardiac Muscle"], ["13", "Effect of Vagal Stimulation on Frog's Heart"], ["14", "Effect of Drugs on Frog's Heart"], ] idx_table = Table(index_data, colWidths=[1.2*cm, 15.8*cm]) idx_table.setStyle(TableStyle([ ('BACKGROUND', (0,0), (-1,0), colors.HexColor('#1a3c6e')), ('TEXTCOLOR', (0,0), (-1,0), colors.white), ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'), ('FONTSIZE', (0,0), (-1,-1), 9.5), ('ROWPADDING', (0,0), (-1,-1), 5), ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.HexColor('#eef2fa'), colors.white]), ('BOX', (0,0), (-1,-1), 0.5, colors.HexColor('#bccde8')), ('INNERGRID', (0,0), (-1,-1), 0.3, colors.HexColor('#d0daea')), ])) story.append(idx_table) story.append(PageBreak()) # ---- SECTION HEADER ---- story.append(Paragraph("PART A — SKELETAL MUSCLE PHYSIOLOGY", ParagraphStyle( 'SecH', fontSize=13, textColor=colors.HexColor('#1a3c6e'), fontName='Helvetica-Bold', spaceAfter=10, spaceBefore=4 ))) # Graph 1 story += make_graph_block(1, "Simple Muscle Curve (Twitch)", [ "A single muscle twitch is the fundamental unit of skeletal muscle contraction, recorded as a " "bell-shaped curve on the kymograph after application of a single threshold stimulus.", "The curve is divided into three phases: Latent Period (LP) — brief delay between stimulus and " "start of contraction (~0.01 s), during which electrical and chemical events occur; " "Contraction Period (CP) — muscle shortens as actin–myosin cross-bridges form; " "Relaxation Period (RP) — muscle returns to resting length, taking roughly twice the contraction period.", "Point of Maximum Contraction (PMC) is the peak of the curve where tension is greatest.", "The latent period corresponds to the action potential propagation and Ca²⁺ release from the SR.", ], key_terms={"LP": "Latent Period", "CP": "Contraction Period", "RP": "Relaxation Period", "PMC": "Point of Maximum Contraction", "PR": "Point of Relaxation"}) # Graph 2 story += make_graph_block(2, "Effect of Temperature on Simple Muscle Curve", [ "Three curves are recorded at low, normal, and high temperatures to compare the three phases " "of the twitch.", "At LOW temperature: all three phases (latent, contraction, relaxation) are prolonged — " "enzymatic and ion-channel activity slows down, reducing the rate of cross-bridge cycling.", "At NORMAL temperature: the curve shows standard durations serving as the reference.", "At HIGH temperature: the curve is compressed — all phases shorten as metabolic reactions " "speed up; however, beyond a critical temperature (~42°C), proteins denature and fatigue occurs " "faster.", "Notation AB₁, AB₂, AB₃ represents latent periods; B₁C₁–B₃C₃ contraction periods; " "C₁D₁–C₃D₃ relaxation periods at the three temperatures respectively.", ]) # Graph 3 story += make_graph_block(3, "Effect of Increasing Strength of Stimulus on Muscle Contraction", [ "Demonstrates the graded response of a whole muscle (not a single fibre) to progressively " "stronger stimuli.", "Sub-threshold stimuli produce no visible contraction. As stimulus strength rises above " "threshold, more motor units are recruited (spatial summation), and the height of contraction " "increases stepwise.", "Beyond the maximal stimulus, further increases produce no additional contraction — all " "motor units are already activated (All-or-None Law at the fibre level but graded response " "at the muscle level).", "Make (M) and Break (B) stimuli: the muscle contracts at both make and break of an induction " "shock; at low frequencies make stimulus is stronger; at high frequencies break stimulus may " "be stronger.", ]) # Graph 4 story += make_graph_block(4, "Effect of Two Successive Stimuli on Muscle Contraction", [ "Two stimuli (S₁ and S₂) are applied in rapid succession to explore summation and refractory periods.", "If S₂ falls during the absolute refractory period of the first twitch, no second contraction occurs.", "If S₂ falls during the relative refractory period or the relaxation phase, a second smaller " "contraction is produced, but it is lower than the first.", "When S₂ arrives just as the muscle has not yet fully relaxed from S₁, the two twitches " "fuse — this is wave summation (treppe/staircase start), producing greater tension than a " "single twitch.", "This graph lays the groundwork for understanding tetanus.", ], key_terms={"S₁": "First Stimulus", "S₂": "Second Stimulus"}) # Graph 5 story += make_graph_block(5, "Genesis of Tetanus", [ "When stimuli are applied at increasing frequency, individual twitches begin to fuse.", "Incomplete (Unfused) Tetanus: at intermediate frequencies the muscle partially relaxes " "between stimuli, producing a sawtooth trace with oscillations but greater overall tension " "than a single twitch.", "Complete (Fused) Tetanus: at high frequencies the muscle has no time to relax; the trace " "becomes a smooth plateau at maximum tension, 3–4 times that of a single twitch.", "Tetanus is the basis of all normal voluntary muscle movements in vivo.", "The fusion frequency required for complete tetanus is ~20–30 Hz for slow fibres and " "~50–60 Hz for fast fibres in the frog gastrocnemius.", ]) # Graph 6 story += make_graph_block(6, "Genesis of Fatigue", [ "Sustained or repetitive stimulation causes a progressive decline in the height of contractions " "— this is muscular fatigue.", "When the nerve is stimulated, fatigue appears quickly at the neuromuscular junction " "(synaptic fatigue — acetylcholine depletion).", "When the muscle itself is stimulated directly, fatigue takes longer to appear, indicating " "the NMJ fatigues before the muscle fibre.", "After a rest period, the muscle shows recovery of contractile strength (recovery curve).", "Biochemical basis: depletion of ATP and phosphocreatine, accumulation of lactic acid and " "inorganic phosphate, and reduced Ca²⁺ sensitivity of troponin.", ]) # Graph 7 story += make_graph_block(7, "Effect of Load on Muscle Contraction", [ "Examines isotonic contractions under different loading conditions using a stationary vs " "moving drum arrangement.", "Free (unloaded) contraction: fastest, shortest contraction and relaxation times; " "maximum shortening achieved.", "Loaded contraction on moving drum (afterload): latent period appears extended as the " "muscle must first develop tension equal to the load before shortening begins; " "height of contraction decreases as load increases.", "At maximum load (equal to maximum isometric tension), no shortening occurs — isometric " "contraction.", "Demonstrates the force–velocity relationship: heavier loads reduce the velocity and " "extent of shortening.", ]) story.append(PageBreak()) # ---- SECTION HEADER ---- story.append(Paragraph("PART B — NERVE PHYSIOLOGY", ParagraphStyle( 'SecH2', fontSize=13, textColor=colors.HexColor('#1a3c6e'), fontName='Helvetica-Bold', spaceAfter=10, spaceBefore=4 ))) # Graph 8 story += make_graph_block(8, "Conduction Velocity of Nerves in Frog", [ "Two traces (M-curve and V-curve) are recorded when the nerve is stimulated at two points — " "close to the muscle (A) and close to the vertebra (B).", "M-curve (muscle response when stimulated close): shorter latency between stimulus artefact " "and muscle contraction.", "V-curve (response when stimulated far): longer latency because the impulse must travel the " "entire nerve length before reaching the muscle.", "Conduction velocity = Distance between two stimulation points ÷ Difference in latencies.", "In frog sciatic nerve, conduction velocity is approximately 25–35 m/s (myelinated A-fibres).", "Time tracing at 100 Hz provides the time base for calculating exact latency differences.", ], key_terms={"A": "Stimulation near muscle", "B": "Stimulation near vertebra", "M-curve": "Short latency trace", "V-curve": "Long latency trace"}) story.append(PageBreak()) # ---- SECTION HEADER ---- story.append(Paragraph("PART C — CARDIAC PHYSIOLOGY", ParagraphStyle( 'SecH3', fontSize=13, textColor=colors.HexColor('#1a3c6e'), fontName='Helvetica-Bold', spaceAfter=10, spaceBefore=4 ))) # Graph 9 story += make_graph_block(9, "Normal Cardiogram (Frog Heart)", [ "The frog heart cardiogram shows the mechanical events of the cardiac cycle recorded on the " "kymograph at different drum speeds.", "Ideal recording at slow speed (1.2 mm/sec): shows the overall wave pattern of systole and " "diastole; the upstroke represents ventricular systole, the downstroke ventricular diastole.", "Usual recording at slow speed: similar to ideal but with minor artefacts from the " "lever mechanism.", "Usual recording at fast speed: expands the time axis to reveal finer details of the " "ventricular contraction — the notch at the top represents opening of semilunar valves and " "shoulder on downstroke represents auricular contraction preceding ventricular systole.", "Frog heart rate is ~30–40 beats/min at room temperature; the two-chambered atria and " "single ventricle pattern is visible in the double humps on fast recordings.", ]) # Graph 10 story += make_graph_block(10, "Effect of Temperature on Frog's Heart", [ "Three recordings are made at cold, normal, and warm temperatures.", "At LOW temperature (e.g., 5–10°C): heart rate decreases (bradycardia), amplitude may " "decrease slightly, and the contraction/relaxation phases are prolonged — Q₁₀ effect on " "pacemaker depolarisation rate.", "At NORMAL temperature (~20°C): standard rate and amplitude serve as the control.", "At HIGH temperature (e.g., 35–40°C): heart rate increases (tachycardia), amplitude may " "increase initially then decline; extreme heat causes irregular rhythm and eventually stops " "the heart in systole (heat rigor).", "Demonstrates the direct thermal sensitivity of the SA node and cardiac contractility " "independent of nervous control.", ]) # Graph 11 story += make_graph_block(11, "Effect of Stannius Ligatures on Frog's Heart", [ "Stannius ligatures are applied to the frog heart to demonstrate the pacemaker hierarchy " "and the property of rhythmicity.", "Normal trace (before ligatures): regular contractions of both atria and ventricle at " "sinus (SA node) rate.", "After 1st Stannius Ligature (placed at sinus-atrial junction): the sinus continues to beat " "but atria and ventricle stop momentarily, then resume at a slower idioventricular rate " "after a pause of ~5 sec — the AV node takes over as subsidiary pacemaker.", "After 2nd Stannius Ligature (placed at AV junction): ventricle stops or beats very slowly " "at its own intrinsic rate (His-Purkinje pacemaker), while atria beat at AV node rate — " "demonstrating complete AV block.", "Proves that the fastest pacemaker (sinus) normally drives the heart and lower centres are " "suppressed (overdrive suppression).", ], key_terms={"1st Ligature": "Sinus-atrial junction", "2nd Ligature": "AV junction", "5 sec": "Pause intervals marked on trace"}) # Graph 12 story += make_graph_block(12, "Properties of Cardiac Muscle", [ "<b>Extra Systole (Extrasystole):</b> A premature stimulus during diastole triggers an " "extra contraction (extrasystole), followed by a Compensatory Pause (CP) before the next " "normal beat — because the sinus impulse arrives during the refractory period of the " "extrasystole.", "Stimulus applied during systole produces NO extra beat (Absolute Refractory Period of " "cardiac muscle) — this protects against tetanus in the heart.", "Post-Extrasystolic Potentiation (PSP): the beat following the compensatory pause is " "stronger than normal due to increased Ca²⁺ load.", "<b>All-or-None Law:</b> Sub-threshold stimuli (1) produce no contraction; at threshold (2) " "a full contraction occurs; supra-threshold stimuli (3 & 4) produce the same height " "contraction — cardiac muscle responds maximally or not at all.", "<b>Staircase Phenomenon (Bowditch Treppe):</b> With stimuli applied every 2 seconds, each " "successive beat is stronger than the previous one until a plateau is reached — due to " "progressive increase in intracellular Ca²⁺ with each beat.", ], key_terms={"CP": "Compensatory Pause", "PSP": "Post-Extrasystolic Potentiation"}) # Graph 13 story += make_graph_block(13, "Effect of Vagal Stimulation on Frog's Heart", [ "The vagus nerve (parasympathetic) is stimulated electrically while recording the frog " "cardiogram.", "Brief low-frequency vagal stimulation: slowing of heart rate (negative chronotropy) and " "reduced amplitude (negative inotropy).", "Prolonged or strong vagal stimulation: the heart may stop completely in diastole " "(vagal arrest / inhibition) for several seconds.", "After cessation of stimulation: the heart spontaneously resumes beating — this is the " "'escape' phenomenon due to the intrinsic pacemaker overcoming inhibition.", "Mechanism: vagal ACh acts on M₂ muscarinic receptors → ↑ K⁺ conductance (IKACh) → " "hyperpolarisation → reduced spontaneous depolarisation of SA node.", "Demonstrates the dominance of parasympathetic tone on the resting frog heart.", ]) # Graph 14 story += make_graph_block(14, "Effect of Drugs on Frog's Heart", [ "Various pharmacological agents are applied to the isolated frog heart perfused with Ringer's " "solution to demonstrate receptor-mediated cardiac effects.", "Adrenaline (Epinephrine): increases rate (positive chronotropy) and force (positive " "inotropy) via β₁-adrenergic receptors → ↑ cAMP → ↑ Ca²⁺ influx.", "Acetylcholine / Pilocarpine: mimics vagal stimulation — bradycardia, reduced amplitude, " "possible cardiac arrest in diastole (M₂ receptor activation).", "Atropine: blocks muscarinic receptors → abolishes vagal effects; heart rate increases " "(vagal block); used to reverse acetylcholine-induced bradycardia.", "Calcium (CaCl₂): increases amplitude and may cause systolic arrest at high doses " "(calcium rigor) — increased contractility via direct action on myofilaments.", "Potassium (KCl): decreases rate and amplitude; high concentrations cause diastolic " "arrest by raising resting membrane potential — hyperkalaemia effect.", "Digitalis / other glycosides (if included): positive inotropy via Na⁺/K⁺-ATPase inhibition " "→ increased intracellular Na⁺ → ↑ Ca²⁺ via Na⁺/Ca²⁺ exchanger.", ]) # Footer note story.append(HRFlowable(width="100%", thickness=1, color=colors.HexColor('#bccde8'), spaceBefore=10, spaceAfter=6)) story.append(Paragraph( "<i>Source: Amphibian Graphs, OMC 2022. Summaries based on standard frog physiology practical " "observations. All graphs are recorded on a kymograph using isolated frog preparations.</i>", ParagraphStyle('Footer', fontSize=8, textColor=colors.HexColor('#666666'), alignment=TA_CENTER) )) doc.build(story) print("PDF created successfully:", output_path) PYEOF
Amphibian Graphs Summary OMC2022
PDF Document · PDF
| # | Graph | Key Takeaway |
|---|---|---|
| 1 | Simple Muscle Twitch | Three phases - latent, contraction, relaxation periods explained |
| 2 | Effect of Temperature | Cold = slow/prolonged; Hot = fast/compressed curve |
| 3 | Increasing Stimulus Strength | Motor unit recruitment; threshold to maximal stimulus |
| 4 | Two Successive Stimuli | Wave summation; absolute vs relative refractory period |
| 5 | Genesis of Tetanus | Unfused vs fused tetanus; fusion frequency |
| 6 | Genesis of Fatigue | NMJ fatigues before the muscle; recovery shown |
| 7 | Effect of Load | Force-velocity relationship; isotonic vs isometric |
| # | Graph | Key Takeaway |
|---|---|---|
| 8 | Conduction Velocity | M-curve vs V-curve; velocity ≈ 25-35 m/s in frog sciatic nerve |
| # | Graph | Key Takeaway |
|---|---|---|
| 9 | Normal Cardiogram | Systole/diastole; slow vs fast drum speed recordings |
| 10 | Temperature on Heart | Thermal bradycardia/tachycardia; Q₁₀ effect on pacemaker |
| 11 | Stannius Ligatures | Pacemaker hierarchy; AV block; escape phenomenon |
| 12 | Properties of Cardiac Muscle | Extrasystole + CP + PSP; All-or-None Law; Staircase (Bowditch) |
| 13 | Vagal Stimulation | Vagal arrest; escape; M₂ receptor / IKACh mechanism |
| 14 | Effect of Drugs | Adrenaline, ACh, Atropine, CaCl₂, KCl effects explained |
Along with graphs
python3 -c "import fitz; print('pymupdf available')" 2>/dev/null || echo "not available" python3 -c "from pdf2image import convert_from_path; print('pdf2image available')" 2>/dev/null || echo "pdf2image not available" which pdftoppm && echo "pdftoppm available" || echo "pdftoppm not found" which gs && echo "ghostscript available" || echo "gs not found"
mkdir -p /home/daytona/workspace/amphibian_pages && python3 << 'PYEOF' from pdf2image import convert_from_path pages = convert_from_path( '/home/daytona/workspace/attachments/84a19c61-b7ff-405d-bf8a-144dd6e48bd6/Amphibian graphs OMC 2022.pdf', dpi=150 ) for i, page in enumerate(pages): path = f'/home/daytona/workspace/amphibian_pages/page_{i+1:02d}.png' page.save(path, 'PNG') print(f'Saved: {path}') print(f'Total pages: {len(pages)}') PYEOF
python3 << 'PYEOF' from reportlab.lib.pagesizes import A4 from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import cm from reportlab.lib import colors from reportlab.platypus import (SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable, PageBreak, Image, KeepTogether) from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY from PIL import Image as PILImage import os output_path = "/home/daytona/workspace/Amphibian_Graphs_With_Summary_OMC2022.pdf" PAGE_W, PAGE_H = A4 CONTENT_W = PAGE_W - 4*cm # 17 cm doc = SimpleDocTemplate( output_path, pagesize=A4, rightMargin=2*cm, leftMargin=2*cm, topMargin=2*cm, bottomMargin=2*cm ) styles = getSampleStyleSheet() title_style = ParagraphStyle('CT', fontSize=20, textColor=colors.HexColor('#1a3c6e'), spaceAfter=6, alignment=TA_CENTER, fontName='Helvetica-Bold') subtitle_style = ParagraphStyle('CS', fontSize=11, textColor=colors.HexColor('#555555'), spaceAfter=18, alignment=TA_CENTER) body_style = ParagraphStyle('CB', fontSize=9.5, leading=14, spaceAfter=4, alignment=TA_JUSTIFY) footer_style = ParagraphStyle('CF', fontSize=8, textColor=colors.HexColor('#666666'), alignment=TA_CENTER) section_style = ParagraphStyle('CSec', fontSize=13, textColor=colors.HexColor('#1a3c6e'), fontName='Helvetica-Bold', spaceAfter=8, spaceBefore=4) def get_img_flowable(img_path, max_w, max_h): """Return a ReportLab Image scaled to fit within max_w x max_h.""" pil = PILImage.open(img_path) iw, ih = pil.size ratio = min(max_w / iw, max_h / ih) return Image(img_path, width=iw*ratio, height=ih*ratio) def graph_block(num, title, img_path, summary_points, key_terms=None): els = [] # ---- Header ---- hdr = Table([[Paragraph(f"Graph {num}: {title}", ParagraphStyle('GH', fontSize=12, textColor=colors.white, fontName='Helvetica-Bold', leftIndent=4))]], colWidths=[CONTENT_W]) hdr.setStyle(TableStyle([ ('BACKGROUND', (0,0), (-1,-1), colors.HexColor('#1a3c6e')), ('ROWPADDING', (0,0), (-1,-1), 7), ('BOX', (0,0), (-1,-1), 0.5, colors.HexColor('#0d2447')), ])) els.append(hdr) # ---- Image (left) + Summary (right) side by side ---- img_col_w = 8.0*cm txt_col_w = CONTENT_W - img_col_w - 0.3*cm img_flow = get_img_flowable(img_path, img_col_w - 0.3*cm, 7.5*cm) bullets = [] for pt in summary_points: bullets.append(Paragraph(f"• {pt}", body_style)) if key_terms: kts = " | ".join([f"<b>{k}</b>: {v}" for k,v in key_terms.items()]) bullets.append(Paragraph(f"<i>Labels — {kts}</i>", ParagraphStyle('KT', fontSize=8.5, textColor=colors.HexColor('#444'), leading=12))) # Nested table: image cell | bullets cell inner = Table([[img_flow, bullets]], colWidths=[img_col_w, txt_col_w]) inner.setStyle(TableStyle([ ('VALIGN', (0,0), (-1,-1), 'TOP'), ('LEFTPADDING', (0,0), (-1,-1), 6), ('RIGHTPADDING', (0,0), (-1,-1), 6), ('TOPPADDING', (0,0), (-1,-1), 6), ('BOTTOMPADDING', (0,0), (-1,-1), 6), ('BACKGROUND', (0,0), (-1,-1), colors.HexColor('#f0f4fa')), ('BOX', (0,0), (-1,-1), 0.5, colors.HexColor('#bccde8')), ('LINEBEFORE', (1,0), (1,-1), 0.5, colors.HexColor('#bccde8')), ])) els.append(inner) els.append(Spacer(1, 10)) return [KeepTogether(els)] # ========== Build story ========== story = [] # Title page story.append(Spacer(1, 1.2*cm)) story.append(Paragraph("Amphibian Physiology Graphs", title_style)) story.append(Paragraph("OMC 2022 — All 14 Graphs with Summaries", subtitle_style)) story.append(HRFlowable(width="100%", thickness=1.5, color=colors.HexColor('#1a3c6e'), spaceAfter=10)) story.append(Paragraph( "This document presents each of the 14 amphibian (frog) physiology graphs from OMC 2022, " "with the original graph image alongside a concise physiological summary. " "Graphs are drawn on a kymograph using isolated frog muscle, nerve, and heart preparations.", body_style)) story.append(Spacer(1, 0.5*cm)) # Index table idx = [ [Paragraph("<b>#</b>", ParagraphStyle('IH', fontSize=9, textColor=colors.white, fontName='Helvetica-Bold')), Paragraph("<b>Graph Title</b>", ParagraphStyle('IH2', fontSize=9, textColor=colors.white, fontName='Helvetica-Bold'))], ["1", "Simple Muscle Curve (Twitch)"], ["2", "Effect of Temperature on Simple Muscle Curve"], ["3", "Effect of Increasing Strength of Stimulus on Muscle Contraction"], ["4", "Effect of Two Successive Stimuli on Muscle Contraction"], ["5", "Genesis of Tetanus"], ["6", "Genesis of Fatigue"], ["7", "Effect of Load on Muscle Contraction"], ["8", "Conduction Velocity of Nerves in Frog"], ["9", "Normal Cardiogram"], ["10", "Effect of Temperature on Frog's Heart"], ["11", "Effect of Stannius Ligatures on Frog's Heart"], ["12", "Properties of Cardiac Muscle"], ["13", "Effect of Vagal Stimulation on Frog's Heart"], ["14", "Effect of Drugs on Frog's Heart"], ] it = Table(idx, colWidths=[1.2*cm, 15.8*cm]) it.setStyle(TableStyle([ ('BACKGROUND', (0,0), (-1,0), colors.HexColor('#1a3c6e')), ('FONTSIZE', (0,0), (-1,-1), 9.5), ('ROWPADDING', (0,0), (-1,-1), 5), ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.HexColor('#eef2fa'), colors.white]), ('BOX', (0,0), (-1,-1), 0.5, colors.HexColor('#bccde8')), ('INNERGRID', (0,0), (-1,-1), 0.3, colors.HexColor('#d0daea')), ])) story.append(it) story.append(PageBreak()) # ===== PART A ===== story.append(Paragraph("PART A — SKELETAL MUSCLE PHYSIOLOGY", section_style)) story += graph_block(1, "Simple Muscle Curve (Twitch)", "/home/daytona/workspace/amphibian_pages/page_01.png", [ "A single threshold stimulus produces one twitch — the fundamental unit of skeletal muscle contraction.", "Latent Period (LP, ~0.01 s): delay between stimulus and contraction start; corresponds to action potential propagation and Ca²⁺ release from the SR.", "Contraction Period (CP): muscle shortens as actin-myosin cross-bridges form; ends at Point of Maximum Contraction (PMC).", "Relaxation Period (RP): muscle returns to resting length; roughly 2× the contraction period as Ca²⁺ is re-pumped into SR.", ], key_terms={"LP":"Latent Period","CP":"Contraction Period","RP":"Relaxation Period","PMC":"Max Contraction Point"}) story += graph_block(2, "Effect of Temperature on Simple Muscle Curve", "/home/daytona/workspace/amphibian_pages/page_02.png", [ "Three twitches recorded at low, normal, and high temperatures (AB₁/₂/₃ = latent periods; B₁C₁... = contraction; C₁D₁... = relaxation).", "LOW temperature: all three phases prolonged — enzymatic and ion-channel activity slows down.", "NORMAL temperature: standard durations; serves as control.", "HIGH temperature: all phases shorten (faster metabolism); beyond ~42°C, protein denaturation causes fatigue and irregular contractions.", ]) story += graph_block(3, "Effect of Increasing Strength of Stimulus on Muscle Contraction", "/home/daytona/workspace/amphibian_pages/page_03.png", [ "Sub-threshold stimuli produce no contraction. Above threshold, more motor units are recruited (spatial summation) → stepwise increase in contraction height.", "At maximal stimulus all motor units are activated; further increases produce no extra tension (maximal response plateau).", "Make (M) stimulus = moment current is switched ON; Break (B) = when switched OFF. Both can evoke contractions via current surges.", "Demonstrates graded muscle response despite All-or-None Law applying to individual fibres.", ], key_terms={"M":"Make stimulus","B":"Break stimulus"}) story += graph_block(4, "Effect of Two Successive Stimuli on Muscle Contraction", "/home/daytona/workspace/amphibian_pages/page_04.png", [ "S₁ produces a twitch. S₂ applied at varying intervals demonstrates refractory periods and summation.", "S₂ during absolute refractory period → no second contraction.", "S₂ during relative refractory period → smaller second contraction.", "S₂ during relaxation phase → wave summation — the twitches fuse and peak tension exceeds a single twitch.", "Lays the groundwork for understanding tetanus genesis.", ], key_terms={"S₁":"First Stimulus","S₂":"Second Stimulus"}) story += graph_block(5, "Genesis of Tetanus", "/home/daytona/workspace/amphibian_pages/page_05.png", [ "Increasing stimulus frequency causes successive twitches to fuse.", "Incomplete (Unfused) Tetanus: intermediate frequency; sawtooth trace with oscillations but greater tension than a single twitch.", "Complete (Fused) Tetanus: high frequency; smooth plateau at maximum tension (~3-4× single twitch) — no relaxation between stimuli.", "Fusion frequency: ~20-30 Hz for slow fibres, ~50-60 Hz for fast fibres in frog gastrocnemius.", "Basis of all normal voluntary smooth movements in vivo.", ]) story += graph_block(6, "Genesis of Fatigue", "/home/daytona/workspace/amphibian_pages/page_06.png", [ "Sustained stimulation causes progressive decline in contraction height — muscular fatigue.", "Nerve stimulation → fatigue appears faster (NMJ/synaptic fatigue: ACh depletion).", "Direct muscle stimulation → fatigue appears later, proving the NMJ is the weakest link.", "After rest, the muscle recovers full strength (recovery curve visible).", "Biochemical basis: ATP/phosphocreatine depletion, lactic acid accumulation, ↓ Ca²⁺ sensitivity of troponin.", ]) story += graph_block(7, "Effect of Load on Muscle Contraction", "/home/daytona/workspace/amphibian_pages/page_07.png", [ "Free (unloaded) contraction: maximum shortening, fastest speed.", "Loaded contraction (afterload, moving drum): latent period appears extended; height decreases as load increases — muscle must first develop tension equal to load before shortening.", "At maximum load → isometric contraction; no shortening, maximum tension.", "Demonstrates the force-velocity relationship: heavier loads reduce both velocity and extent of shortening.", ], key_terms={"Moving drum":"afterload recording","Stationary drum":"isometric equivalent"}) story.append(PageBreak()) # ===== PART B ===== story.append(Paragraph("PART B — NERVE PHYSIOLOGY", section_style)) story += graph_block(8, "Conduction Velocity of Nerves in Frog", "/home/daytona/workspace/amphibian_pages/page_08.png", [ "Nerve stimulated at two points: A (near muscle) → M-curve (short latency); B (near vertebra) → V-curve (long latency).", "Conduction velocity = Distance between A and B ÷ Difference in latencies between M and V curves.", "Time tracing at 100 Hz provides the time base (each interval = 0.01 s).", "Frog sciatic nerve conduction velocity ≈ 25-35 m/s (myelinated A-fibres via saltatory conduction).", ], key_terms={"A":"Near muscle","B":"Near vertebra","M-curve":"Short latency","V-curve":"Long latency"}) story.append(PageBreak()) # ===== PART C ===== story.append(Paragraph("PART C — CARDIAC PHYSIOLOGY", section_style)) story += graph_block(9, "Normal Cardiogram (Frog Heart)", "/home/daytona/workspace/amphibian_pages/page_09.png", [ "Upstroke = ventricular systole; downstroke = ventricular diastole recorded mechanically on the kymograph.", "Slow speed (1.2 mm/sec): shows full wave pattern; ideal vs usual recordings compared.", "Fast speed: expands time axis to reveal fine features — notch at peak (semilunar valve opening), shoulder on downstroke (auricular contraction preceding ventricular systole).", "Frog heart rate ~30-40 beats/min at room temperature. The double-hump pattern at fast speed reflects two atria contracting before the single ventricle.", ]) story += graph_block(10, "Effect of Temperature on Frog's Heart", "/home/daytona/workspace/amphibian_pages/page_10.png", [ "Cold (5-10°C): bradycardia + prolonged phases (Q₁₀ effect slows SA node depolarisation rate).", "Normal (~20°C): standard rate and amplitude; control recording.", "High (35-40°C): tachycardia + initially ↑ amplitude; extreme heat → irregular rhythm → systolic arrest (heat rigor).", "Demonstrates direct thermal sensitivity of the cardiac pacemaker independent of neural input.", ]) story += graph_block(11, "Effect of Stannius Ligatures on Frog's Heart", "/home/daytona/workspace/amphibian_pages/page_11.png", [ "Normal trace: regular sinus rhythm driving both atria and ventricle.", "1st Stannius Ligature (sinus-atrial junction): atria & ventricle stop momentarily, then resume at slower AV nodal rate after ~5 sec pause.", "2nd Stannius Ligature (AV junction): ventricle stops or beats very slowly at idioventricular (His-Purkinje) rate; complete AV block.", "Proves pacemaker hierarchy: Sinus node > AV node > Ventricular myocardium (overdrive suppression of lower pacemakers).", ], key_terms={"1st Ligature":"Sinus-atrial junction","2nd Ligature":"AV junction","5 sec":"Pause intervals"}) story += graph_block(12, "Properties of Cardiac Muscle", "/home/daytona/workspace/amphibian_pages/page_12.png", [ "Extrasystole: premature stimulus during diastole → extra beat followed by Compensatory Pause (CP) as the next sinus impulse falls in the refractory period of the extrasystole.", "Post-Extrasystolic Potentiation (PSP): beat after the CP is stronger than normal (↑ intracellular Ca²⁺ loading).", "Stimulus during systole → NO contraction (absolute refractory period) — protects heart from tetanus.", "All-or-None Law: sub-threshold (1) = no response; threshold (2) = full contraction; supra-threshold (3 & 4) = same height.", "Staircase (Bowditch Treppe): stimuli every 2 s → each beat progressively stronger until plateau; due to progressive ↑ intracellular Ca²⁺.", ], key_terms={"CP":"Compensatory Pause","PSP":"Post-Extrasystolic Potentiation"}) story += graph_block(13, "Effect of Vagal Stimulation on Frog's Heart", "/home/daytona/workspace/amphibian_pages/page_13.png", [ "Brief vagal stimulation: negative chronotropy (↓ rate) and negative inotropy (↓ amplitude).", "Strong/prolonged stimulation: vagal arrest — heart stops in diastole for several seconds.", "After stimulation ends: spontaneous resumption of beating (escape phenomenon — intrinsic pacemaker overcomes inhibition).", "Mechanism: ACh → M₂ muscarinic receptors → ↑ IKACh (K⁺ conductance) → hyperpolarisation → slowed SA node depolarisation.", ]) story += graph_block(14, "Effect of Drugs on Frog's Heart", "/home/daytona/workspace/amphibian_pages/page_14.png", [ "Adrenaline: ↑ rate + ↑ amplitude (positive chrono- & inotropy) via β₁ receptors → ↑ cAMP → ↑ Ca²⁺ influx.", "Acetylcholine / Pilocarpine: bradycardia, ↓ amplitude, possible diastolic arrest (M₂ receptor activation — mimics vagal effect).", "Atropine: blocks muscarinic receptors → abolishes ACh/vagal effects; ↑ heart rate (vagal block).", "CaCl₂: ↑ contractility; high doses → systolic arrest (calcium rigor).", "KCl: ↓ rate and amplitude; high doses → diastolic arrest (hyperkalaemia raises resting membrane potential).", "Digitalis: positive inotropy via Na⁺/K⁺-ATPase inhibition → ↑ intracellular Na⁺ → ↑ Ca²⁺ via Na/Ca exchanger.", ]) # Footer story.append(HRFlowable(width="100%", thickness=1, color=colors.HexColor('#bccde8'), spaceBefore=8, spaceAfter=5)) story.append(Paragraph( "<i>Source: Amphibian Graphs, OMC 2022. All graphs recorded on a kymograph using isolated frog preparations.</i>", footer_style)) doc.build(story) print("Done:", output_path) PYEOF
Amphibian Graphs With Summary OMC2022
PDF Document · PDF