Explain medication titration in icu using the infusion pump
medication titration infusion pump ICU critical care nursing principles
https://www.myamericannurse.com/medication-titration
https://www.augusta.edu/mcg/center-for-digital-health/docume…
| Role | Responsibility |
|---|---|
| Prescriber (Physician/NP/PA) | Writes a complete titration order with goal, starting dose, increment, frequency, and maximum dose |
| Pharmacist | Verifies order for appropriateness, drug interactions, concentration, and prepares the infusion bag |
| Critical Care Nurse | Performs the titration at the bedside, assesses the patient before and after each rate change, and documents |
Goal MAP >65 mmHg. Start at 0.05 mcg/kg/min. Titrate by 0.05 mcg/kg/min every 5 minutes. Max dose 2 mcg/kg/min. Notify provider if MAP <55 or >110 mmHg.
Goal RASS 0 to -2. Start at 5 mcg/kg/min. Adjust by 5 mcg/kg/min every 15 minutes. Max dose 80 mcg/kg/min. Notify provider if RASS < -4.
Rate (mL/hr) = [Dose (mcg/kg/min) × Weight (kg) × 60 min] ÷ Concentration (mcg/mL)
Rate = 2 mcg/min × 60 min ÷ 4 mcg/mL = 30 mL/hr
| Drug Class | Monitor | Frequency |
|---|---|---|
| Vasopressors (norepinephrine, epinephrine, dopamine) | MAP, heart rate, urine output, skin perfusion | Every 5-15 min during active titration; hourly once goal achieved |
| Sedatives (propofol, midazolam, dexmedetomidine) | RASS score, respiratory rate, blood pressure | Hourly |
| Analgesics (fentanyl, morphine) | CPOT or NRS pain score, respiratory rate, RASS | Hourly |
| Antihypertensives (nicardipine, labetalol, nitroprusside) | SBP/DBP/MAP, HR | Every 2-5 min during active titration |
| Antiarrhythmics (esmolol, amiodarone) | HR, BP, rhythm on monitor | Every 2 min during titration |
| Drug | Class | Starting Dose | Titration Increment | Interval | Max Dose | Goal |
|---|---|---|---|---|---|---|
| Norepinephrine | Vasopressor | 0.05 mcg/kg/min | 0.05 mcg/kg/min | 5 min | 2 mcg/kg/min | MAP >65 mmHg |
| Epinephrine | Vasopressor/inotrope | 0.01 mcg/kg/min | 0.01 mcg/kg/min | 5 min | 0.5 mcg/kg/min | MAP, CO target |
| Vasopressin (septic shock) | Vasopressin agonist | 1.8 units/hr | Fixed - do not titrate | - | 2.4 units/hr | Adjunct (fixed dose) |
| Dopamine | Inotrope/vasopressor | 2-5 mcg/kg/min | 2 mcg/kg/min | 10 min | 20 mcg/kg/min | MAP, urine output |
| Propofol | Sedation | 5 mcg/kg/min | 5 mcg/kg/min | 15-30 min | 80 mcg/kg/min | RASS goal |
| Dexmedetomidine | Sedation | 0.2 mcg/kg/hr | 0.1 mcg/kg/hr | 30 min | 1.5 mcg/kg/hr | RASS goal |
| Fentanyl | Analgesia | 0.5 mcg/kg/hr | 0.5 mcg/kg/hr | 60 min | 10 mcg/kg/hr | CPOT/NRS goal |
| Nicardipine | Antihypertensive | 5 mg/hr | 2.5 mg/hr | 5 min | 15 mg/hr | SBP/MAP target |
| Nitroprusside | Antihypertensive | 0.3 mcg/kg/min | 0.5 mcg/kg/min | 2 min | 3 mcg/kg/min | SBP/MAP target |
| Esmolol | Beta-blocker | 50 mcg/kg/min | 50 mcg/kg/min | 2 min | 200-300 mcg/kg/min | HR goal |
Generate a quick-reference protocol poster for ICU titration of vasopressors and sedatives
A professional ICU clinical quick-reference protocol poster titled "ICU TITRATION PROTOCOL: Vasopressors & Sedatives". Dark navy blue background with white and bright accent text. Clean medical infographic layout with two main sections side by side. LEFT SECTION - "VASOPRESSORS" with red/orange accent header: Table with columns: Drug | Start Dose | Increment | Interval | Max Dose | Goal - Norepinephrine | 0.05 mcg/kg/min | +0.05 | 5 min | 2 mcg/kg/min | MAP >65 - Epinephrine | 0.01 mcg/kg/min | +0.01 | 5 min | 0.5 mcg/kg/min | MAP/CO - Dopamine | 2 mcg/kg/min | +2 | 10 min | 20 mcg/kg/min | MAP/UO - Vasopressin | 1.8 units/hr | Fixed | — | 2.4 units/hr | Do not titrate - Phenylephrine | 0.5 mcg/kg/min | +0.1 | 5 min | 3 mcg/kg/min | MAP >65 RIGHT SECTION - "SEDATIVES & ANALGESICS" with blue/teal accent header: Table with columns: Drug | Start Dose | Increment | Interval | Max Dose | Goal - Propofol | 5 mcg/kg/min | +5 | 15 min | 80 mcg/kg/min | RASS goal - Dexmedetomidine | 0.2 mcg/kg/hr | +0.1 | 30 min | 1.5 mcg/kg/hr | RASS goal - Midazolam | 1 mg/hr | +0.5 | 30 min | 20 mg/hr | RASS goal - Fentanyl | 0.5 mcg/kg/hr | +0.5 | 60 min | 10 mcg/kg/hr | CPOT/NRS - Morphine | 2 mg/hr | +1 | 30 min | 30 mg/hr | RASS/NRS BOTTOM SECTION - "SAFETY REMINDERS" with yellow warning accent icons: Five bullet points in a row: 1) All drips via infusion pump only 2) Central line preferred for vasopressors 3) Check volume status before uptitrating 4) Document: rate change + clinical assessment 5) Never abruptly stop vasopressors - wean RASS SCALE sidebar on right: -5 Unarousable to 0 Alert to +4 Combative with color coding green to red. Small footer: "Notify provider if max dose reached or goal unmet after 3 titrations" Clean, clinical, high-contrast design suitable for hospital wall display. Professional medical typography.

When assessing an older adult's functional status, which tool best evaluates their ability to live independently? Braden Scale Edinburgh Depression Scale Activities of Daily Living (ADL) scale Mini-Mental State Exam (MMSE)
| ADL Domain | What It Measures |
|---|---|
| Bathing | Can the person bathe without assistance? |
| Dressing | Can they select and put on clothing independently? |
| Toileting | Can they manage toileting and hygiene? |
| Transferring | Can they move from bed to chair independently? |
| Continence | Do they have control of bladder and bowel? |
| Feeding | Can they feed themselves? |
| Option | Tool's Actual Purpose | Why It Doesn't Answer the Question |
|---|---|---|
| A - Braden Scale | Predicts pressure ulcer (pressure injury) risk based on sensory perception, moisture, activity, mobility, nutrition, and friction/shear | It tells you skin breakdown risk, not functional independence |
| B - Edinburgh Postnatal Depression Scale | Screens for postpartum/perinatal depression in new mothers | Designed for a specific population (postpartum); has no role in general geriatric functional assessment |
| D - MMSE (Mini-Mental State Exam) | Screens for cognitive impairment and dementia - tests orientation, recall, attention, language, and visuospatial ability | It measures cognitive function, not physical functional status; a person can have mild cognitive impairment but still live independently, or have normal cognition but severe physical disability |
Create a study guide on geriatric assessment tools
comprehensive geriatric assessment tools MMSE ADL IADL GDS Braden nursing study guide
https://www.msdmanuals.com/professional/geriatrics/approach-…
| Domain | What It Assesses |
|---|---|
| Functional Status | ADLs, IADLs, mobility |
| Cognitive Status | Memory, orientation, executive function |
| Psychological/Affective | Depression, anxiety |
| Physical Health | Comorbidities, nutrition, frailty, pain |
| Social/Environmental | Support systems, living situation |
| Polypharmacy | Medication burden and appropriateness |
| ADL Item | Independent = 1 | Dependent = 0 |
|---|---|---|
| Bathing | Bathes self or only needs help with one body part | Needs help with more than one part |
| Dressing | Dresses without help (except tying shoes) | Needs help getting dressed |
| Toileting | Goes to toilet, cleans self | Needs help with toileting |
| Transferring | Moves in/out of bed and chair independently | Needs help or bedbound |
| Continence | Controls bladder and bowel | Partial or full incontinence |
| Feeding | Feeds self without help | Needs help feeding or is tube-fed |
| IADL Domain | Score 0-1 Each |
|---|---|
| Using telephone | |
| Shopping | |
| Food preparation | |
| Housekeeping | |
| Laundry | |
| Transportation | |
| Managing medications | |
| Managing finances |
Exam Tip: ADLs = "Can they care for their body?" IADLs = "Can they manage their life?" When a question asks about independent living, think IADLs (Lawton). When it asks about basic self-care, think ADLs (Katz).
| Section | Points |
|---|---|
| Orientation to time (year, season, date, day, month) | 5 |
| Orientation to place (country, state, county, hospital, floor) | 5 |
| Registration (repeat 3 words) | 3 |
| Attention & Calculation (serial 7s or spell "WORLD" backward) | 5 |
| Recall (recall 3 words) | 3 |
| Language (naming, repetition, 3-stage command) | 8 |
| Visuospatial (copy intersecting pentagons) | 1 |
| Total | 30 |
Limitations: Influenced by education level, language, and motor ability. Not diagnostic - a screening tool only.
MoCA vs MMSE: MoCA catches early/mild cognitive impairment that MMSE misses. MoCA preferred when MCI is suspected.
Exam Tip: Mini-Cog is the preferred bedside screening tool per ACS/AGS surgical guidelines due to its speed, ease, and focus on attention and executive function.
Not a diagnostic tool - positive screening requires clinical interview and DSM criteria confirmation.
Key Distinction: CAM = delirium screen. GDS = depression screen. MMSE/MoCA = dementia/cognitive impairment screen. These are NOT interchangeable.
| Item | Question |
|---|---|
| F - Fatigue | "How much of the time did you feel tired over the past 4 weeks?" |
| R - Resistance | "Do you have difficulty climbing a flight of stairs?" |
| A - Ambulation | "Do you have difficulty walking 100 yards?" |
| I - Illness | "Do you have more than 5 illnesses?" |
| L - Loss of weight | "Have you lost more than 5% of your weight in the past year?" |
| Tool | Domain | Time | Scoring | Key Cut-off | Use When |
|---|---|---|---|---|---|
| Katz ADL | Function - basic | 5 min | 0-6 | <4 = impaired | Assessing basic self-care ability |
| Lawton IADL | Function - complex | 10 min | 0-8 | Lower = dependent | Assessing community living capacity |
| TUG | Mobility/Falls | 5 min | Seconds | >12 sec = at risk | Fall risk screening |
| MMSE | Cognition | 10 min | 0-30 | <24 = impaired | Dementia tracking, moderate-severe |
| MoCA | Cognition | 15 min | 0-30 | <26 = impaired | Early/mild cognitive impairment |
| Mini-Cog | Cognition | 3 min | 0-5 | ≤2 = impaired | Rapid bedside screen |
| GDS-15 | Depression | 5-10 min | 0-15 | >5 = depressed | Depression in elderly |
| PHQ-2 | Depression | 1 min | 0-6 | ≥3 = positive | Ultra-rapid depression screen |
| CAM | Delirium | 5 min | +/- | All 4 = delirium | Inpatient delirium detection |
| FRAIL Scale | Frailty | 3 min | 0-5 | ≥3 = frail | Quick frailty screen |
| Fried Phenotype | Frailty | 15 min | 0-5 | ≥3 = frail | Detailed frailty classification |
| MNA-SF | Nutrition | 5 min | 0-14 | <12 = at risk | Malnutrition screening |
| Braden Scale | Pressure injury | 5 min | 6-23 | ≤18 = at risk | Skin integrity/pressure ulcer prevention |
| PAINAD | Pain | 5 min | 0-10 | Higher = more pain | Non-verbal dementia patients |
| Wrong Choice | Why It's Wrong | Correct Tool |
|---|---|---|
| MMSE for independent living | MMSE tests cognition, not function | Katz ADL / Lawton IADL |
| Braden for functional status | Braden assesses pressure ulcer risk | Katz ADL |
| GDS for delirium | GDS screens depression | CAM |
| Edinburgh Scale in general elderly | Edinburgh is for postpartum depression | GDS-15 |
| ADL for community living | ADL = basic self-care only | IADL (Lawton) |
IADLs decline first → ADLs decline next → Basic mobility affected
(managing money, (bathing, dressing, (transferring, then
cooking, meds) toileting, eating) feeding last)
Teach me the various IV solutions and categorize them in groups based on their tonicity
IV intravenous fluids tonicity classification isotonic hypotonic hypertonic nursing
https://wtcs.pressbooks.pub/nursingfundamentals/chapter/15-3…
| Tonicity | Osmolarity | Effect on Cells | Direction of Water Movement |
|---|---|---|---|
| Isotonic | 275-295 mOsm/L | No change | No net movement |
| Hypotonic | < 275 mOsm/L | Cells swell (lyse if severe) | Water moves INTO cells |
| Hypertonic | > 295 mOsm/L | Cells shrink (crenate) | Water moves OUT of cells |
There are two main categories of IV fluids: crystalloids (small molecules that pass through membranes) and colloids (large molecules that stay in the vascular space). Tonicity classification applies primarily to crystalloids.
Same osmolarity as blood. No osmotic gradient is created. Fluid stays in the extracellular/intravascular space.
| Property | Value |
|---|---|
| Osmolarity | 308 mOsm/L |
| Na⁺ | 154 mEq/L |
| Cl⁻ | 154 mEq/L |
| pH | 5.5 |
| Property | Value |
|---|---|
| Osmolarity | 273 mOsm/L |
| Na⁺ | 130 mEq/L |
| K⁺ | 4 mEq/L |
| Ca²⁺ | 2.7 mEq/L |
| Cl⁻ | 109 mEq/L |
| Lactate | 28 mEq/L |
| pH | 6.5 |
| Property | Value |
|---|---|
| Osmolarity | 294 mOsm/L |
| Na⁺ | 140 mEq/L |
| K⁺ | 5 mEq/L |
| Mg²⁺ | 3 mEq/L |
| Cl⁻ | 98 mEq/L |
| Acetate | 27 mEq/L |
| Gluconate | 23 mEq/L |
| pH | 7.4 (Plasma-Lyte A) |
| Property | Value |
|---|---|
| Osmolarity (in bag) | 252 mOsm/L (effectively isotonic with dextrose) |
| Dextrose | 5 g/100 mL |
| Na⁺/Cl⁻ | 0 |
Special case: D5W starts as isotonic in the IV bag because the glucose molecules contribute to osmolarity. However, glucose is rapidly metabolized by cells after infusion, leaving only free water behind - making it functionally hypotonic in the body.
Lower osmolarity than blood. Creates an osmotic gradient pulling water from the bloodstream INTO cells. Expands the intracellular compartment.
| Property | Value |
|---|---|
| Osmolarity | 154 mOsm/L |
| Na⁺ | 77 mEq/L |
| Cl⁻ | 77 mEq/L |
| Property | Value |
|---|---|
| Osmolarity | 103 mOsm/L |
| Na⁺ | 51 mEq/L |
| Cl⁻ | 51 mEq/L |
| Property | Value |
|---|---|
| Osmolarity | ~405 mOsm/L (before dextrose metabolized) |
| Behaves as | Hypotonic after dextrose is metabolized |
[4 mL/kg × first 10 kg] + [2 mL/kg × second 10 kg] + [1 mL/kg × each kg >20 kg]
Example (70 kg patient):
(4×10) + (2×10) + (1×50) = 40 + 20 + 50 = 110 mL/hr
Higher osmolarity than blood. Pulls water out of cells and into the bloodstream. Expands intravascular volume rapidly at the expense of intracellular volume.
| Property | Value |
|---|---|
| Osmolarity | ~1,026 mOsm/L |
| Na⁺ | 513 mEq/L |
| Cl⁻ | 513 mEq/L |
| Property | Value |
|---|---|
| Osmolarity | ~1,710 mOsm/L |
| Property | Value |
|---|---|
| Osmolarity | ~505 mOsm/L |
| Dextrose | 100 g/L |
Large molecules that remain in the intravascular space and exert oncotic (colloid osmotic) pressure, pulling fluid from interstitial spaces into the bloodstream.
Key principle from Goldman-Cecil Medicine: "There is no clear advantage of colloid over crystalloid solutions, so crystalloids - which are less expensive - are preferred" for initial resuscitation. Hetastarches are never recommended (associated with worse outcomes, including AKI).
| Type | Tonicity | Use |
|---|---|---|
| 5% Albumin | Isotonic | Volume expansion in hypovolemia/shock |
| 25% Albumin | Hypertonic | Severe hypoalbuminemia, hepatorenal syndrome, spontaneous bacterial peritonitis |
| Solution | Tonicity | Osmolarity | Compartment Expanded | Primary Use | Key Warning |
|---|---|---|---|---|---|
| 0.9% NaCl (NS) | Isotonic | 308 | Extracellular/intravascular | Resuscitation, blood transfusion, TBI | Hyperchloremic acidosis with large volumes |
| Lactated Ringer's | Isotonic | 273 | Extracellular/intravascular | Burns, trauma, surgery | Avoid in alkalosis, hyperkalemia, TBI, renal failure |
| Plasma-Lyte A | Isotonic | 294 | Extracellular/intravascular | Balanced resuscitation | Most physiologic; avoid in hyperkalemia |
| D5W | Isotonic→Hypotonic | 252 | Intracellular (after metabolism) | Hypernatremia, free water, medication diluent | Never resuscitate; cerebral edema risk |
| 0.45% NaCl (½NS) | Hypotonic | 154 | Intracellular | Hypernatremia, cellular dehydration, DKA | Hyponatremia, cerebral edema |
| 0.33% NaCl (⅓NS) | Hypotonic | 103 | Intracellular | Pediatric maintenance | High hyponatremia risk |
| D5 ½NS | Hypotonic (after) | ~405→hypotonic | Intracellular | Maintenance fluid, NPO patients | Not for resuscitation |
| 3% NaCl | Hypertonic | 1,026 | Draws water into vessels | Symptomatic hyponatremia, cerebral edema | Slow infusion only; ODS risk; central line required |
| 5% NaCl | Hypertonic | 1,710 | Draws water into vessels | Critical hyponatremia | Same as 3% - extreme caution |
| D10W | Hypertonic | 505 | Intravascular + calories | Hypoglycemia, neonates, TPN | Monitor glucose |
| 5% Albumin | Isotonic (colloid) | ~308 | Intravascular | Hypovolemia + low albumin | Expensive; monitor for fluid overload |
| 25% Albumin | Hypertonic (colloid) | ~1,500 | Pulls fluid into vessels | Hypoalbuminemia, cirrhosis, SBP | Hypervolemia risk |
| Hetastarch | Isotonic (colloid) | ~308 | Intravascular | AVOID | AKI, coagulopathy, increased mortality |
Design a mind map of the basic metabolic panel and correlate how they relate to one another
A detailed, professional medical mind map of the Basic Metabolic Panel (BMP) on a deep navy blue background. The mind map has a central node labeled "BASIC METABOLIC PANEL (BMP)" in bold white text with a bright cyan border. Eight main branches radiate outward from the center, each representing a BMP component with its own color-coded node and sub-branches showing normal range, clinical significance, and key correlations: 1. SODIUM (Na+) - orange node - 135-145 mEq/L - sub-branches: "Hypernatremia → dehydration, DI", "Hyponatremia → SIADH, heart failure, cirrhosis", "Correlates with: Chloride, Osmolality, BUN" 2. POTASSIUM (K+) - yellow node - 3.5-5.0 mEq/L - sub-branches: "Hyperkalemia → renal failure, acidosis", "Hypokalemia → diuretics, vomiting, alkalosis", "Correlates with: pH/CO2 (inverse), Creatinine" 3. CHLORIDE (Cl-) - light green node - 98-106 mEq/L - sub-branches: "Low Cl → metabolic alkalosis", "High Cl → metabolic acidosis (normal saline)", "Correlates with: Anion Gap = Na - (Cl + HCO3)" 4. BICARBONATE/CO2 (HCO3-) - teal node - 22-29 mEq/L - sub-branches: "Low HCO3 → metabolic acidosis, DKA", "High HCO3 → metabolic alkalosis, vomiting", "Correlates with: Chloride (reciprocal), Anion Gap", "Anion Gap = Na - (Cl + HCO3) normal 8-12" 5. BUN (Blood Urea Nitrogen) - red node - 7-20 mg/dL - sub-branches: "Elevated → dehydration, renal failure, GI bleed", "BUN:Creatinine ratio >20:1 = prerenal", "BUN:Creatinine ratio <10:1 = intrinsic renal", "Correlates with: Creatinine, Sodium" 6. CREATININE (Cr) - pink/rose node - 0.6-1.2 mg/dL - sub-branches: "Elevated → AKI, CKD, rhabdomyolysis", "eGFR calculated from creatinine", "Correlates with: BUN, Potassium (renal failure → hyperkalemia)" 7. GLUCOSE - purple node - 70-100 mg/dL fasting - sub-branches: "Hyperglycemia → DM, DKA, HHS, steroids", "Hypoglycemia → insulin excess, liver failure", "DKA: high glucose + low CO2 + high anion gap", "Correlates with: CO2 (DKA), Sodium (pseudohyponatremia)" 8. CALCIUM (Ca2+) - gold/amber node - 8.5-10.2 mg/dL - sub-branches: "Hypercalcemia → malignancy, hyperparathyroidism", "Hypocalcemia → hypoparathyroidism, low vitamin D, pancreatitis", "Correlates with: Phosphate (inverse), Albumin (adjust total Ca)" In the CENTER-BOTTOM area, a special highlighted box labeled "KEY CORRELATIONS" shows three connection arrows: - "↑BUN + ↑Cr = RENAL FAILURE → watch K+ and HCO3-" - "Low HCO3 + High Anion Gap = METABOLIC ACIDOSIS (DKA, lactic acid, toxins)" - "Na/K/Cl/HCO3 = ELECTROLYTE CLUSTER → assess fluid and acid-base status together" Color-coded connecting dotted lines link related nodes: Na-Cl-HCO3 (acid-base cluster in teal), BUN-Creatinine (renal cluster in red), Glucose-CO2 (DKA cluster in purple). Clean sans-serif medical typography. Professional infographic quality suitable for medical education. White and light text on dark background. Organized radial layout, not cluttered.

| BUN:Cr Ratio | Interpretation |
|---|---|
| >20:1 | Pre-renal (dehydration, GI bleed, heart failure) |
| 10-20:1 | Normal |
| <10:1 | Intrinsic renal disease or low protein intake |
Now gere
Yes, mind map for comprehensive metabolic panel and their interrelation to one another
A detailed professional medical mind map of the Comprehensive Metabolic Panel (CMP) on a deep dark navy blue background. The mind map has a large central node labeled "COMPREHENSIVE METABOLIC PANEL (CMP)" in bold white text with a bright gold/yellow glowing border. Subtitle below: "14 Components • Liver + Kidney + Electrolytes + Glucose + Protein" Fourteen color-coded branches radiate outward in a circular arrangement, grouped into 4 visible clusters with subtle background shading: CLUSTER 1 - ELECTROLYTES (blue-teal shading, left side): 1. SODIUM (Na+) - cyan node - "135-145 mEq/L" - sub-text: "Fluid balance • Hypernatremia=dehydration • Hyponatremia=SIADH/HF • Links to Cl, HCO3, Glucose" 2. POTASSIUM (K+) - sky blue node - "3.5-5.0 mEq/L" - sub-text: "Cardiac rhythm • Inverse to pH • ↑ in renal failure/acidosis • ↓ with diuretics/alkalosis" 3. CHLORIDE (Cl-) - light teal node - "98-106 mEq/L" - sub-text: "Acid-base balance • ANION GAP = Na-(Cl+HCO3) • Reciprocal to HCO3" 4. BICARBONATE (HCO3-) - green-teal node - "22-29 mEq/L" - sub-text: "Acid-base buffer • ↓=metabolic acidosis/DKA • ↑=metabolic alkalosis • Links to Cl (reciprocal), AG" CLUSTER 2 - RENAL FUNCTION (red-pink shading, right side): 5. BUN - red node - "7-20 mg/dL" - sub-text: "Protein catabolism • BUN:Cr>20=prerenal • ↑ in dehydration/GI bleed • Links to Creatinine, Na" 6. CREATININE - rose node - "0.6-1.2 mg/dL" - sub-text: "Muscle metabolism • Calculates eGFR • ↑ AKI/CKD → ↑K+, ↓HCO3 • Links to BUN, K+" 7. GLUCOSE - purple node - "70-100 mg/dL" - sub-text: "Energy metabolism • DKA=high glucose+low HCO3+high AG • Pseudohyponatremia when high • Links to Na, HCO3" 8. CALCIUM (Ca2+) - amber/gold node - "8.5-10.2 mg/dL" - sub-text: "Bone/nerve/muscle • Correct for albumin: Ca+0.8×(4-Alb) • Inverse to Phosphate • ↑ malignancy/hyperPTH" CLUSTER 3 - LIVER FUNCTION (orange-yellow shading, bottom): 9. TOTAL PROTEIN - orange node - "6.3-8.2 g/dL" - sub-text: "= Albumin + Globulin • ↓ in liver failure/malnutrition • Links to Albumin, Bilirubin" 10. ALBUMIN - yellow-orange node - "3.5-5.0 g/dL" - sub-text: "Oncotic pressure/transport • ↓ in liver disease/malnutrition/nephrotic • Affects Ca correction • Links to Total Protein, Ca" 11. TOTAL BILIRUBIN - yellow node - "0.1-1.2 mg/dL" - sub-text: "Heme breakdown product • ↑ liver disease/hemolysis/bile obstruction • Links to AST, ALT, Alk Phos" 12. AST (Aspartate Aminotransferase) - lime green node - "10-40 U/L" - sub-text: "Hepatocellular damage • Also in heart/muscle • AST:ALT>2=alcoholic hepatitis • Links to ALT, Bilirubin" 13. ALT (Alanine Aminotransferase) - green node - "7-56 U/L" - sub-text: "Liver-specific enzyme • Best marker hepatocellular injury • Links to AST, Bilirubin, Alk Phos" 14. ALKALINE PHOSPHATASE (ALP) - olive node - "44-147 U/L" - sub-text: "Biliary/bone disease • ↑ cholestasis, bone mets, Paget's • Links to Bilirubin, GGT (not in CMP)" THREE KEY CORRELATION BOXES at the bottom center connected by colored arrows: BOX 1 (red): "RENAL CLUSTER: ↑BUN+↑Cr → eGFR↓ → watch K+↑ and HCO3↓" BOX 2 (orange): "LIVER CLUSTER: ↑AST+↑ALT+↑Bili → hepatocellular injury | ↑ALP+↑Bili → cholestasis" BOX 3 (cyan): "ACID-BASE: Na-(Cl+HCO3)=Anion Gap | DKA: ↑Glucose+↓HCO3+↑AG" Thin dotted colored connector lines link related components across clusters: Albumin↔Calcium (white), BUN↔Sodium (yellow), Glucose↔HCO3 (purple), AST↔ALT (green), Bilirubin↔ALP (orange). Clean medical typography, organized radial mind map layout with clear cluster groupings, professional clinical infographic quality for medical education wall display. All text clearly readable on dark background.

| Pattern | Likely Cause |
|---|---|
| AST + ALT both elevated | Hepatocellular injury (hepatitis, cirrhosis) |
| AST:ALT ratio >2:1 | Alcoholic liver disease |
| ALP + Bilirubin elevated | Cholestatic/obstructive pattern (bile duct obstruction, PBC) |
| Isolated ALT elevation | Early/mild hepatocellular damage (most liver-specific enzyme) |
| Added in CMP | What It Tells You |
|---|---|
| Total Protein | Overall protein synthesis and nutritional status |
| Albumin | Liver synthetic function, nutritional status, drug binding |
| Total Bilirubin | Liver excretory function, hemolysis |
| AST | Hepatocellular damage (also muscle/heart) |
| ALT | Liver-specific damage marker |
| ALP | Cholestatic/biliary disease or bone pathology |
Generate a diagnostic flowchart for elevated liver enzymes
A professional medical diagnostic flowchart titled "DIAGNOSTIC APPROACH TO ELEVATED LIVER ENZYMES" on a clean white background with dark text and color-coded decision boxes. Vertical top-to-bottom flowchart with branching paths. TOP START BOX (dark navy blue, wide): "ELEVATED LIVER ENZYMES DETECTED" subtitle: "AST, ALT, ALP, GGT, or Bilirubin above normal range" Arrow down to STEP 1 BOX (dark teal): "STEP 1: Identify the Pattern" — two branches side by side: LEFT branch (orange box): "HEPATOCELLULAR PATTERN" — "AST and/or ALT predominantly elevated (>3x ULN)" — "Suggests liver cell damage" RIGHT branch (purple box): "CHOLESTATIC PATTERN" — "ALP and/or GGT predominantly elevated" — "Suggests bile flow obstruction" HEPATOCELLULAR BRANCH continues down: Arrow to grey box: "STEP 2A: Check AST:ALT Ratio" THREE sub-branches: - LEFT (red box): "AST:ALT > 2:1" → "Alcoholic Liver Disease" → "Check: alcohol history, GGT elevated, biopsy" - CENTER (orange box): "ALT > AST" → "Viral Hepatitis / NAFLD / Drug-induced" → "Check: Hep A/B/C serology, ultrasound, medication review, BMI/metabolic syndrome" - RIGHT (yellow box): "Massively elevated AST+ALT (>1000)" → "Ischemic hepatitis / Acute viral hepatitis / Drug toxicity (acetaminophen)" → "Check: Echo, BP history, acetaminophen level, viral panel" Further down from center orange box: "STEP 3A: Additional Workup" box (light orange): "• Hepatitis B surface antigen (HBsAg)" "• Hepatitis C antibody (anti-HCV)" "• ANA, ASMA → Autoimmune hepatitis" "• Ferritin, transferrin saturation → Hemochromatosis" "• Ceruloplasmin → Wilson disease (age <40)" "• Alpha-1 antitrypsin level" "• TSH (hypothyroid can elevate AST)" "• Liver ultrasound" CHOLESTATIC BRANCH continues down: Arrow to grey box: "STEP 2B: Is ALP Elevated?" TWO sub-branches: - LEFT (purple box): "ALP + GGT both elevated" → "TRUE HEPATIC/BILIARY cause" → "Liver or bile duct origin confirmed" - RIGHT (lavender box): "ALP elevated, GGT normal" → "BONE SOURCE of ALP" → "Consider: Paget's disease, bone mets, healing fracture, pregnancy" From TRUE HEPATIC box: "STEP 3B: Imaging" (blue box): "RIGHT UPPER QUADRANT ULTRASOUND" TWO branches: - LEFT (dark blue box): "DUCTAL DILATION seen" → "EXTRAHEPATIC OBSTRUCTION" → "Gallstones (choledocholithiasis), Cholangiocarcinoma, Pancreatic cancer, PSC/PBC" → "→ MRCP or ERCP" - RIGHT (medium blue box): "NO DUCTAL DILATION" → "INTRAHEPATIC CHOLESTASIS" → "Primary Biliary Cholangitis (PBC): check AMA, IgM" → "Primary Sclerosing Cholangitis (PSC): check p-ANCA, MRCP" → "Drug-induced cholestasis" → "Infiltrative disease (lymphoma, sarcoid)" BOTTOM SECTION - wide box spanning full width (dark green): "STEP 4: SEVERITY ASSESSMENT — When to refer/biopsy?" Four columns: Column 1: "MILD (<3x ULN)" → "Repeat LFTs in 3-6 months, lifestyle modification, stop offending drugs" Column 2: "MODERATE (3-10x ULN)" → "Full workup, imaging, hepatology referral" Column 3: "SEVERE (>10x ULN)" → "Urgent hepatology consult, assess for acute liver failure" Column 4: "ACUTE LIVER FAILURE signs" → "INR >1.5 + encephalopathy → ICU admission" BOTTOM FOOTER BOX (dark red): "RED FLAGS — Immediate Action Required: Jaundice + coagulopathy + encephalopathy = Acute Liver Failure | Painless jaundice + weight loss = Rule out malignancy | Fever + RUQ pain + jaundice = Charcot's Triad = Ascending Cholangitis" Color-coded arrows: orange for hepatocellular path, purple for cholestatic path, green for final management. Clean sans-serif medical font. Professional clinical quality. All text clearly readable.

| Pattern | Dominant Elevation | Think |
|---|---|---|
| Hepatocellular | AST and/or ALT | Liver cell death/injury |
| Cholestatic | ALP and/or GGT | Bile flow impairment |
| Mixed | All enzymes elevated | Overlap - needs full workup |
GGT is the key differentiator: if ALP is elevated but GGT is normal, the ALP is coming from bone, not liver.
| Ratio | Diagnosis to Consider |
|---|---|
| >2:1 (AST much higher) | Alcoholic hepatitis (especially if GGT also elevated) |
| ALT > AST | Viral hepatitis, NAFLD/NASH, drug-induced liver injury |
| Both >1000 U/L | Ischemic hepatitis ("shock liver"), acute viral hepatitis, acetaminophen toxicity |
| Test | Rules In |
|---|---|
| HBsAg, anti-HCV | Hepatitis B or C |
| ANA, anti-smooth muscle Ab (ASMA) | Autoimmune hepatitis |
| Ferritin + transferrin saturation >45% | Hemochromatosis |
| Ceruloplasmin (if age <40) | Wilson's disease |
| Alpha-1 antitrypsin level | Alpha-1 antitrypsin deficiency |
| TSH | Hypothyroidism (can raise AST mildly) |
| Severity | Action |
|---|---|
| <3x ULN | Repeat in 3-6 months, remove offending drugs, lifestyle changes |
| 3-10x ULN | Full workup + imaging + hepatology referral |
| >10x ULN | Urgent hepatology consult |
| Coagulopathy + encephalopathy | Acute liver failure - ICU admission |
Create a clinical case study showing how to interprete an abnormal CMP
| Component | Patient Value | Normal Range | Status |
|---|---|---|---|
| Sodium (Na⁺) | 128 mEq/L | 135-145 | 🔴 LOW |
| Potassium (K⁺) | 5.8 mEq/L | 3.5-5.0 | 🔴 HIGH |
| Chloride (Cl⁻) | 94 mEq/L | 98-106 | 🟡 LOW |
| Bicarbonate (HCO₃⁻) | 14 mEq/L | 22-29 | 🔴 LOW |
| BUN | 68 mg/dL | 7-20 | 🔴 HIGH |
| Creatinine | 4.2 mg/dL | 0.6-1.2 | 🔴 HIGH |
| Glucose | 312 mg/dL | 70-100 | 🔴 HIGH |
| Calcium (Ca²⁺) | 7.4 mg/dL | 8.5-10.2 | 🔴 LOW |
| Total Protein | 4.8 g/dL | 6.3-8.2 | 🔴 LOW |
| Albumin | 1.9 g/dL | 3.5-5.0 | 🔴 LOW |
| Total Bilirubin | 8.6 mg/dL | 0.1-1.2 | 🔴 HIGH |
| AST | 312 U/L | 10-40 | 🔴 HIGH |
| ALT | 148 U/L | 7-56 | 🔴 HIGH |
| Alkaline Phosphatase (ALP) | 198 U/L | 44-147 | 🔴 HIGH |
Formula: Anion Gap = Na⁺ - (Cl⁻ + HCO₃⁻)
AG = 128 - (94 + 14)
AG = 128 - 108
AG = 20 mEq/L ← ELEVATED (normal 8-12)
| Calculation | Value | Meaning |
|---|---|---|
| BUN | 68 mg/dL | Severely elevated |
| Creatinine | 4.2 mg/dL | Severely elevated |
| BUN:Cr Ratio | 68 ÷ 4.2 = 16:1 | Normal ratio despite both high |
| eGFR (estimated) | ~14 mL/min/1.73m² | Stage 5 - severe renal impairment |
⚠️ Potassium 5.8 mEq/L is a medical emergency. At K⁺ >6.0, fatal cardiac arrhythmias (ventricular fibrillation) can occur. This patient needs an immediate ECG.
AST ÷ ALT = 312 ÷ 148 = 2.1:1 ← > 2:1
AST:ALT > 2:1 is the hallmark of alcoholic liver disease.
| Finding | Value | Clinical Significance |
|---|---|---|
| AST | 312 U/L (~8x ULN) | Hepatocellular damage |
| ALT | 148 U/L (~3x ULN) | AST > ALT = alcohol pattern |
| ALP | 198 U/L (~1.3x ULN) | Mildly elevated - some cholestatic component |
| Total Bilirubin | 8.6 mg/dL (~7x ULN) | Significant - jaundice visible at >2.5 mg/dL |
| Finding | Value | Clinical Significance |
|---|---|---|
| Albumin | 1.9 g/dL (severely low) | Liver can no longer synthesize albumin |
| Total Protein | 4.8 g/dL (low) | Reflects low albumin + decreased synthesis |
Corrected Ca = Measured Ca + 0.8 × (4 - Albumin)
Corrected Ca = 7.4 + 0.8 × (4 - 1.9)
Corrected Ca = 7.4 + 0.8 × 2.1
Corrected Ca = 7.4 + 1.68
Corrected Ca = 9.1 mg/dL ← NORMAL
| Finding | Value | Cause |
|---|---|---|
| Na⁺ 128 mEq/L | Hyponatremia | Dilutional - fluid retention in cirrhosis + heart failure physiology; also SIADH from liver disease |
| K⁺ 5.8 mEq/L | Hyperkalemia | AKI - kidneys not excreting K⁺; also acidosis shifts K⁺ out of cells |
| Cl⁻ 94 mEq/L | Low-normal | Consistent with metabolic acidosis and volume changes |
| HCO₃⁻ 14 mEq/L | Metabolic acidosis | Uremic acid accumulation (AKI) + possible lactic acidosis from hypotension |
Corrected Na for hyperglycemia:
Add 1.6 mEq/L Na per 100 mg/dL glucose >100
Glucose above 100 = 312 - 100 = 212 mg/dL above normal
Correction = (212/100) × 1.6 = +3.4 mEq/L
True Na⁺ ≈ 128 + 3.4 = ~131.4 mEq/L (still hyponatremic, but less severe)
| Problem | CMP Evidence | Clinical Correlation |
|---|---|---|
| Alcoholic cirrhosis | AST:ALT >2:1, high bilirubin, low albumin, high ALP | Jaundice, ascites, spider angiomata, palmar erythema |
| Acute Kidney Injury (AKI) | Cr 4.2, BUN 68, BUN:Cr 16:1 | Hypotension (pre-renal) + diabetic nephropathy |
| High Anion Gap Metabolic Acidosis | HCO₃ 14, AG = 20 | Uremia from AKI; possible lactic acidosis |
| Hyperkalemia | K⁺ 5.8 mEq/L | AKI + acidosis → K⁺ exits cells |
| Dilutional hyponatremia | Na⁺ 128 mEq/L | Cirrhosis + fluid overload |
| Pseudohypocalcemia | Ca 7.4 → corrected 9.1 | Low albumin, not true calcium deficiency |
| Hyperglycemia | Glucose 312 mg/dL | Poorly controlled DM2 |
| Principle | Lesson |
|---|---|
| Always calculate the anion gap | Elevated AG changed the entire diagnostic approach |
| AST:ALT ratio directs diagnosis | >2:1 = alcohol; don't just note "transaminitis" |
| Correct calcium for albumin | Never treat "low calcium" without this correction first |
| Correct sodium for glucose | Hyperglycemia artificially lowers reported Na⁺ |
| BUN + Cr + K⁺ + HCO₃ move together | AKI creates a predictable 4-value pattern |
| Albumin is a window into the liver | Hypoalbuminemia explains ascites, edema, AND pseudohypocalcemia |
Generate a quick reference PDF for normal CMP ranges and interpretations
ls -la /home/daytona/workspace/ 2>/dev/null || mkdir -p /home/daytona/workspace …
mkdir -p /home/daytona/workspace/cmp-reference && python3 -c "import reportlab; …
~/cmp-reference/generate_cmp_pdf.py
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.platypus import PageBreak
OUTPUT = "/home/daytona/workspace/cmp-reference/CMP_Quick_Reference.pdf"
# ── Colour palette ──────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1A2645")
TEAL = colors.HexColor("#0D7377")
ORANGE = colors.HexColor("#E07B39")
RED = colors.HexColor("#C0392B")
GREEN = colors.HexColor("#1E8449")
PURPLE = colors.HexColor("#6C3483")
GOLD = colors.HexColor("#B7950B")
LIGHT_BG = colors.HexColor("#F4F6F9")
MID_GREY = colors.HexColor("#BDC3C7")
WHITE = colors.white
BLACK = colors.black
DARK_GREY = colors.HexColor("#2C3E50")
# ── Styles ───────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def PS(name, parent="Normal", **kw):
return ParagraphStyle(name, parent=styles[parent], **kw)
title_style = PS("Title2", fontSize=22, textColor=WHITE,
alignment=TA_CENTER, spaceAfter=4, fontName="Helvetica-Bold")
sub_style = PS("Sub", fontSize=11, textColor=colors.HexColor("#A8D8EA"),
alignment=TA_CENTER, spaceAfter=2, fontName="Helvetica")
section_hdr = PS("SecHdr", fontSize=12, textColor=WHITE,
alignment=TA_CENTER, fontName="Helvetica-Bold", spaceAfter=0)
body = PS("Body2", fontSize=8.5, textColor=DARK_GREY, leading=12)
bold_body = PS("BoldB", fontSize=8.5, textColor=DARK_GREY,
fontName="Helvetica-Bold", leading=12)
footer_style = PS("Footer", fontSize=7.5, textColor=MID_GREY,
alignment=TA_CENTER)
note_style = PS("Note", fontSize=8, textColor=DARK_GREY,
backColor=colors.HexColor("#FEF9E7"), leading=11)
red_note = PS("RedNote",fontSize=8, textColor=RED,
fontName="Helvetica-Bold", leading=11)
# ── Helper: coloured section header row ─────────────────────────────────────
def section_row(label, col, span=5):
return ([Paragraph(label, section_hdr)],
[("BACKGROUND", (0,0),(-1,-1), col),
("TEXTCOLOR", (0,0),(-1,-1), WHITE),
("SPAN", (0,0),(span-1,0)),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING",(0,0),(-1,-1),5),
("LEFTPADDING",(0,0),(-1,-1), 6)])
def cell(txt, bold=False, color=DARK_GREY, bg=None, align=TA_LEFT, size=8.2):
st = ParagraphStyle("c", fontSize=size, textColor=color,
fontName="Helvetica-Bold" if bold else "Helvetica",
alignment=align, leading=11,
backColor=bg if bg else colors.white)
return Paragraph(txt, st)
# ── Page canvas (header banner + footer) ────────────────────────────────────
def on_page(canvas, doc):
W, H = letter
# Top banner
canvas.setFillColor(NAVY)
canvas.rect(0, H-54, W, 54, fill=1, stroke=0)
canvas.setFillColor(TEAL)
canvas.rect(0, H-58, W, 4, fill=1, stroke=0)
canvas.setFont("Helvetica-Bold", 18)
canvas.setFillColor(WHITE)
canvas.drawCentredString(W/2, H-34, "COMPREHENSIVE METABOLIC PANEL (CMP)")
canvas.setFont("Helvetica", 10)
canvas.setFillColor(colors.HexColor("#A8D8EA"))
canvas.drawCentredString(W/2, H-48,
"Quick Reference Guide • Normal Ranges, Interpretations & Clinical Pearls")
# Footer
canvas.setFont("Helvetica", 7.5)
canvas.setFillColor(MID_GREY)
canvas.drawCentredString(W/2, 18,
"For educational purposes only • Always correlate with clinical context "
f"• Page {doc.page}")
canvas.setFillColor(TEAL)
canvas.rect(0, 28, W, 2, fill=1, stroke=0)
# ── Build document ───────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT,
pagesize=letter,
topMargin=0.85*inch,
bottomMargin=0.5*inch,
leftMargin=0.45*inch,
rightMargin=0.45*inch,
)
story = []
COL_W = [1.35*inch, 0.85*inch, 0.75*inch, 1.65*inch, 2.35*inch]
total_w = sum(COL_W)
BASE_STYLE = [
("FONTNAME", (0,0),(-1,-1), "Helvetica"),
("FONTSIZE", (0,0),(-1,-1), 8.2),
("ROWBACKGROUND", (0,0),(-1,-1), [LIGHT_BG, WHITE]),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#D5D8DC")),
("VALIGN", (0,0),(-1,-1), "TOP"),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 5),
("RIGHTPADDING", (0,0),(-1,-1), 5),
]
HDR_STYLE = BASE_STYLE + [
("BACKGROUND", (0,0),(-1,0), DARK_GREY),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,0), 8.5),
("ALIGN", (0,0),(-1,0), "CENTER"),
]
def hdr_row():
return [cell("COMPONENT", bold=True, color=WHITE, bg=DARK_GREY),
cell("NORMAL RANGE", bold=True, color=WHITE, bg=DARK_GREY, align=TA_CENTER),
cell("UNIT", bold=True, color=WHITE, bg=DARK_GREY, align=TA_CENTER),
cell("LOW ▼ MEANS…", bold=True, color=WHITE, bg=DARK_GREY),
cell("HIGH ▲ MEANS…", bold=True, color=WHITE, bg=DARK_GREY)]
def mk_row(name, rng, unit, low, high, bg=None):
bg = bg or WHITE
return [cell(name, bold=True, color=NAVY),
cell(rng, align=TA_CENTER),
cell(unit, align=TA_CENTER),
cell(low, color=colors.HexColor("#1A5276")),
cell(high, color=colors.HexColor("#7B241C"))]
# ═══════════════════════════════════════════════════════════════════════
# CLUSTER 1: ELECTROLYTES
# ═══════════════════════════════════════════════════════════════════════
story.append(Spacer(1, 0.12*inch))
elec_data = [
hdr_row(),
mk_row("Sodium (Na⁺)", "135 – 145", "mEq/L",
"Hyponatremia → SIADH, heart failure,\ncirrhosis, hypothyroidism, polydipsia",
"Hypernatremia → dehydration, DI,\nexcessive Na intake, fever"),
mk_row("Potassium (K⁺)", "3.5 – 5.0", "mEq/L",
"Hypokalemia → diuretics, vomiting,\nalkalosis, diarrhea, low intake",
"Hyperkalemia → AKI/CKD, acidosis,\nACE inhibitors, Addison's, hemolysis"),
mk_row("Chloride (Cl⁻)", "98 – 106", "mEq/L",
"Hypochloremia → vomiting, NG suction,\nmetabolic alkalosis, diuretics",
"Hyperchloremia → diarrhea, RTA,\nnormal saline overload, dehydration"),
mk_row("Bicarbonate (HCO₃⁻)","22 – 29", "mEq/L",
"Metabolic acidosis → DKA, lactic\nacidosis, renal failure, diarrhea",
"Metabolic alkalosis → vomiting,\nNG suction, diuretics, antacid excess"),
]
elec_sec_hdr = [cell("ELECTROLYTES (Acid-Base & Fluid Balance Cluster)", bold=True, color=WHITE)]
elec_tbl = Table([[elec_sec_hdr[0]]], colWidths=[total_w])
elec_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), TEAL),
("TOPPADDING",(0,0),(-1,-1),5), ("BOTTOMPADDING",(0,0),(-1,-1),5),
("LEFTPADDING",(0,0),(-1,-1),8)]))
story.append(elec_tbl)
t = Table(elec_data, colWidths=COL_W, repeatRows=1)
t.setStyle(TableStyle(HDR_STYLE + [
("ROWBACKGROUNDS",(0,1),(-1,-1),[LIGHT_BG, WHITE])]))
story.append(t)
story.append(Spacer(1, 0.06*inch))
# Anion Gap callout
ag_txt = (
"<b>KEY FORMULA — Anion Gap (AG):</b> AG = Na⁺ − (Cl⁻ + HCO₃⁻) "
"| <b>Normal: 8–12 mEq/L</b><br/>"
"High AG metabolic acidosis (MUDPILES): <b>M</b>ethanol · <b>U</b>remia · "
"<b>D</b>KA · <b>P</b>ropylene glycol · <b>I</b>soniazid/Iron · "
"<b>L</b>actic acidosis · <b>E</b>thylene glycol · <b>S</b>alicylates<br/>"
"Normal AG metabolic acidosis (HARDUPS): diarrhea, RTA, hyperchloremic acidosis"
)
ag_tbl = Table([[Paragraph(ag_txt, PS("ag", fontSize=8, textColor=DARK_GREY,
leading=12, backColor=colors.HexColor("#EBF5FB")))]],
colWidths=[total_w])
ag_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), colors.HexColor("#EBF5FB")),
("BOX",(0,0),(-1,-1),1, TEAL),
("TOPPADDING",(0,0),(-1,-1),6),("BOTTOMPADDING",(0,0),(-1,-1),6),
("LEFTPADDING",(0,0),(-1,-1),8),("RIGHTPADDING",(0,0),(-1,-1),8)]))
story.append(ag_tbl)
story.append(Spacer(1, 0.12*inch))
# ═══════════════════════════════════════════════════════════════════════
# CLUSTER 2: RENAL + GLUCOSE + CALCIUM
# ═══════════════════════════════════════════════════════════════════════
renal_sec = Table([[cell("RENAL FUNCTION + GLUCOSE + CALCIUM", bold=True, color=WHITE)]],
colWidths=[total_w])
renal_sec.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), RED),
("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5),
("LEFTPADDING",(0,0),(-1,-1),8)]))
story.append(renal_sec)
renal_data = [
hdr_row(),
mk_row("BUN\n(Blood Urea Nitrogen)", "7 – 20", "mg/dL",
"Low protein intake, liver failure,\noverhydration, malnutrition",
"Dehydration, GI bleed, renal failure,\nhigh protein diet, catabolic state"),
mk_row("Creatinine (Cr)", "0.6 – 1.2", "mg/dL",
"Low muscle mass (elderly, malnutrition),\npregnancy, severe liver disease",
"AKI, CKD, rhabdomyolysis, drugs\n(NSAIDs, aminoglycosides, contrast)"),
mk_row("Glucose", "70 – 100", "mg/dL",
"Hypoglycemia → insulin excess,\nliver failure, Addison's, sepsis",
"Hyperglycemia → DM, DKA, HHS,\nsteroids, pancreatitis, stress response"),
mk_row("Calcium (Ca²⁺)", "8.5 – 10.2","mg/dL",
"Hypocalcemia → hypoparathyroidism,\nvit D deficiency, pancreatitis, CKD",
"Hypercalcemia → malignancy, primary\nhyperPTH, sarcoid, vit D toxicity"),
]
t2 = Table(renal_data, colWidths=COL_W, repeatRows=1)
t2.setStyle(TableStyle(HDR_STYLE + [
("ROWBACKGROUNDS",(0,1),(-1,-1),[LIGHT_BG, WHITE])]))
story.append(t2)
story.append(Spacer(1, 0.06*inch))
# BUN:Cr ratio box
bun_txt = (
"<b>BUN : Creatinine Ratio (Normal 10–20:1)</b><br/>"
" >20:1 → Pre-renal (dehydration, GI bleed, heart failure) | "
" 10–20:1 → Normal or intrinsic renal | "
" <10:1 → Liver failure, low protein intake, ATN<br/>"
"<b>Calcium Correction for Low Albumin:</b> "
"Corrected Ca = Measured Ca + 0.8 × (4 − Albumin g/dL)<br/>"
"<b>Glucose ↔ Sodium:</b> For every 100 mg/dL glucose >100, "
"add 1.6 mEq/L to reported Na⁺ to get true Na⁺"
)
bun_tbl = Table([[Paragraph(bun_txt, PS("bun", fontSize=8, textColor=DARK_GREY,
leading=12, backColor=colors.HexColor("#FDEDEC")))]], colWidths=[total_w])
bun_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), colors.HexColor("#FDEDEC")),
("BOX",(0,0),(-1,-1),1, RED),
("TOPPADDING",(0,0),(-1,-1),6),("BOTTOMPADDING",(0,0),(-1,-1),6),
("LEFTPADDING",(0,0),(-1,-1),8),("RIGHTPADDING",(0,0),(-1,-1),8)]))
story.append(bun_tbl)
story.append(Spacer(1, 0.12*inch))
# ═══════════════════════════════════════════════════════════════════════
# CLUSTER 3: LIVER / PROTEIN
# ═══════════════════════════════════════════════════════════════════════
liv_sec = Table([[cell("LIVER FUNCTION + PROTEIN (Hepatic Synthetic & Excretory Cluster)",
bold=True, color=WHITE)]], colWidths=[total_w])
liv_sec.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), ORANGE),
("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5),
("LEFTPADDING",(0,0),(-1,-1),8)]))
story.append(liv_sec)
liver_data = [
hdr_row(),
mk_row("Total Protein", "6.3 – 8.2", "g/dL",
"Liver failure, malnutrition,\nnephrotic syndrome, malabsorption",
"Chronic inflammation, dehydration,\nmultiple myeloma, sarcoidosis"),
mk_row("Albumin", "3.5 – 5.0", "g/dL",
"Liver disease (cirrhosis), malnutrition,\nnephrotic syndrome, chronic illness",
"Dehydration (relative elevation)\n— rarely clinically significant"),
mk_row("Total Bilirubin", "0.1 – 1.2", "mg/dL",
"Rarely significant when mildly low\n(normal variation)",
"Jaundice >2.5; hepatitis, cirrhosis,\nhemolysis, bile duct obstruction"),
mk_row("AST\n(Aspartate Aminotransferase)", "10 – 40", "U/L",
"Rarely clinically significant\n(low muscle mass)",
"Liver injury, MI, muscle damage,\nalcoholic hepatitis (AST:ALT >2:1)"),
mk_row("ALT\n(Alanine Aminotransferase)", "7 – 56", "U/L",
"Rarely significant",
"Hepatocellular injury (most liver-\nspecific enzyme), viral hepatitis, NAFLD"),
mk_row("Alkaline Phosphatase (ALP)", "44 – 147", "U/L",
"Hypothyroidism, pernicious anemia,\nzinc deficiency (rare)",
"Cholestasis, bile obstruction, bone\ndisease, Paget's, bone mets, pregnancy"),
]
t3 = Table(liver_data, colWidths=COL_W, repeatRows=1)
t3.setStyle(TableStyle(HDR_STYLE + [
("ROWBACKGROUNDS",(0,1),(-1,-1),[LIGHT_BG, WHITE])]))
story.append(t3)
story.append(Spacer(1, 0.06*inch))
# Liver pattern box
liv_txt = (
"<b>LIVER ENZYME PATTERNS:</b><br/>"
" Hepatocellular (AST+ALT >> ALP): "
"viral hepatitis, NAFLD, alcoholic hepatitis, drug-induced, ischemia<br/>"
" Cholestatic (ALP+GGT >> AST/ALT): "
"gallstones, cholangiocarcinoma, pancreatic cancer, PBC, PSC, drugs<br/>"
" <b>AST:ALT >2:1</b> → alcoholic liver disease | "
"<b>AST or ALT >1000</b> → ischemic hepatitis / acute viral / acetaminophen toxicity<br/>"
" <b>ALP elevated + GGT normal</b> → BONE source (Paget's, mets, healing fracture)"
)
liv_box = Table([[Paragraph(liv_txt, PS("lb", fontSize=8, textColor=DARK_GREY,
leading=12))]], colWidths=[total_w])
liv_box.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), colors.HexColor("#FEF5E7")),
("BOX",(0,0),(-1,-1),1, ORANGE),
("TOPPADDING",(0,0),(-1,-1),6),("BOTTOMPADDING",(0,0),(-1,-1),6),
("LEFTPADDING",(0,0),(-1,-1),8),("RIGHTPADDING",(0,0),(-1,-1),8)]))
story.append(liv_box)
story.append(Spacer(1, 0.14*inch))
# ═══════════════════════════════════════════════════════════════════════
# CRITICAL VALUES & RED FLAGS
# ═══════════════════════════════════════════════════════════════════════
crit_sec = Table([[cell("CRITICAL VALUES — Immediate Action Required", bold=True, color=WHITE)]],
colWidths=[total_w])
crit_sec.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), colors.HexColor("#922B21")),
("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5),
("LEFTPADDING",(0,0),(-1,-1),8)]))
story.append(crit_sec)
crit_data = [
[cell("VALUE", bold=True, color=WHITE, bg=DARK_GREY),
cell("CRITICAL THRESHOLD", bold=True, color=WHITE, bg=DARK_GREY, align=TA_CENTER),
cell("IMMEDIATE CONCERN", bold=True, color=WHITE, bg=DARK_GREY),
cell("PRIORITY ACTION", bold=True, color=WHITE, bg=DARK_GREY)],
[cell("Sodium"), cell("< 120 or > 160", align=TA_CENTER),
cell("Seizures, cerebral edema, coma"),
cell("Neurology/nephrology consult; correct slowly")],
[cell("Potassium"), cell("< 2.5 or > 6.5", align=TA_CENTER),
cell("Fatal cardiac arrhythmia (V-fib)"),
cell("STAT ECG; calcium gluconate if >6.5")],
[cell("Bicarbonate"), cell("< 10 or > 40", align=TA_CENTER),
cell("Severe acid-base crisis"),
cell("ABG, ICU consult, treat underlying cause")],
[cell("Creatinine"), cell("> 10 (acute rise)", align=TA_CENTER),
cell("Acute renal failure, dialysis needed"),
cell("Nephrology consult; assess AEIOU indications")],
[cell("Glucose"), cell("< 40 or > 500", align=TA_CENTER),
cell("Neuroglycopenia / DKA / HHS"),
cell("D50W IV for hypoglycemia; insulin protocol for hyper")],
[cell("Calcium"), cell("< 6.0 or > 13.0", align=TA_CENTER),
cell("Tetany, cardiac arrest / hypercalcemic crisis"),
cell("IV calcium (if low); IV fluids + bisphosphonate (if high)")],
[cell("Total Bilirubin"),cell("> 15 in adults", align=TA_CENTER),
cell("Severe liver failure or biliary obstruction"),
cell("Hepatology consult; rule out obstruction urgently")],
]
crit_col = [1.25*inch, 1.1*inch, 1.9*inch, 2.5*inch]
tc = Table(crit_data, colWidths=crit_col)
tc.setStyle(TableStyle([
("FONTSIZE",(0,0),(-1,-1),8),
("ROWBACKGROUNDS",(0,1),(-1,-1),[colors.HexColor("#FDEDEC"), WHITE]),
("GRID",(0,0),(-1,-1),0.4,MID_GREY),
("VALIGN",(0,0),(-1,-1),"TOP"),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
("LEFTPADDING",(0,0),(-1,-1),5),
("BACKGROUND",(0,0),(-1,0),DARK_GREY),
("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
]))
story.append(tc)
story.append(Spacer(1, 0.14*inch))
# ═══════════════════════════════════════════════════════════════════════
# CLINICAL PATTERNS QUICK TABLE
# ═══════════════════════════════════════════════════════════════════════
pat_sec = Table([[cell("COMMON CLINICAL PATTERNS ON CMP", bold=True, color=WHITE)]],
colWidths=[total_w])
pat_sec.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), PURPLE),
("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5),
("LEFTPADDING",(0,0),(-1,-1),8)]))
story.append(pat_sec)
pat_col = [1.6*inch, 2.2*inch, 2.95*inch]
pat_data = [
[cell("CONDITION", bold=True, color=WHITE, bg=DARK_GREY),
cell("CMP PATTERN", bold=True, color=WHITE, bg=DARK_GREY),
cell("KEY CLUES", bold=True, color=WHITE, bg=DARK_GREY)],
[cell("DKA"),
cell("↑ Glucose, ↓ HCO₃, ↑ Anion Gap, ↑ K⁺ (initially)"),
cell("Type 1 DM; fruity breath; Kussmaul respirations")],
[cell("AKI (Acute Kidney Injury)"),
cell("↑ Cr, ↑ BUN, ↑ K⁺, ↓ HCO₃, ↑ Anion Gap"),
cell("Oliguria; recent nephrotoxin/hypotension; rising Cr")],
[cell("Liver Cirrhosis"),
cell("↑ AST/ALT, ↑ Bili, ↓ Albumin, ↓ Na⁺, ↑ ALP"),
cell("Jaundice, ascites, spider angiomata, AST:ALT >2:1")],
[cell("Heart Failure"),
cell("↓ Na⁺ (dilutional), ↑ BUN, ↑ Cr, ↓ HCO₃"),
cell("Edema, JVD, crackles; BNP elevated (not on CMP)")],
[cell("Dehydration"),
cell("↑ Na⁺, ↑ BUN, ↑ Cr, BUN:Cr >20:1"),
cell("Dry mucosa, tachycardia, concentrated urine")],
[cell("Primary Hyperparathyroidism"),
cell("↑ Ca²⁺, ↓ Phosphate (not on CMP), ↑ ALP"),
cell("'Bones, stones, groans, moans'; ↑ PTH confirms")],
[cell("Alcoholic Hepatitis"),
cell("↑ AST > ALT (ratio >2:1), ↑ Bili, ↓ Albumin, ↑ ALP"),
cell("Heavy alcohol use; GGT markedly elevated (not on CMP)")],
[cell("SIADH"),
cell("↓ Na⁺, normal BUN/Cr, normal glucose"),
cell("Euvolemic hyponatremia; concentrated urine")],
[cell("Nephrotic Syndrome"),
cell("↓ Albumin, ↓ Total Protein, normal/↑ Cr"),
cell("Heavy proteinuria; edema; hyperlipidemia; frothy urine")],
[cell("Rhabdomyolysis"),
cell("↑ Cr (disproportionate), ↑ K⁺, ↑ Ca²⁺ then ↓ Ca²⁺"),
cell("Dark urine; muscle pain; ↑ CK >10,000 (not on CMP)")],
]
tp = Table(pat_data, colWidths=pat_col, repeatRows=1)
tp.setStyle(TableStyle([
("FONTSIZE",(0,0),(-1,-1),8),
("ROWBACKGROUNDS",(0,1),(-1,-1),[colors.HexColor("#F4ECF7"), WHITE]),
("GRID",(0,0),(-1,-1),0.4,MID_GREY),
("VALIGN",(0,0),(-1,-1),"TOP"),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
("LEFTPADDING",(0,0),(-1,-1),5),
("BACKGROUND",(0,0),(-1,0),DARK_GREY),
("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
]))
story.append(tp)
story.append(Spacer(1, 0.14*inch))
# ═══════════════════════════════════════════════════════════════════════
# STEP-BY-STEP CMP INTERPRETATION GUIDE
# ═══════════════════════════════════════════════════════════════════════
steps_sec = Table([[cell("5-STEP CMP INTERPRETATION FRAMEWORK", bold=True, color=WHITE)]],
colWidths=[total_w])
steps_sec.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), GREEN),
("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5),
("LEFTPADDING",(0,0),(-1,-1),8)]))
story.append(steps_sec)
steps_txt = (
"<b>Step 1 — Scan for critical values first.</b> "
"K⁺ >6.5 or <2.5 mEq/L, Na⁺ <120 mEq/L, glucose <40 mg/dL → act immediately.<br/><br/>"
"<b>Step 2 — Assess acid-base status.</b> "
"Look at HCO₃⁻. Low = acidosis. High = alkalosis. "
"Then calculate Anion Gap = Na − (Cl + HCO₃). AG >12 = high gap metabolic acidosis (MUDPILES).<br/><br/>"
"<b>Step 3 — Evaluate renal function.</b> "
"Check BUN and Creatinine together. Calculate BUN:Cr ratio. "
"Elevated Cr → also expect ↑K⁺ and ↓HCO₃. Correct calcium for albumin level.<br/><br/>"
"<b>Step 4 — Interpret the liver panel.</b> "
"Is the pattern hepatocellular (AST/ALT dominant) or cholestatic (ALP/Bili dominant)? "
"Calculate AST:ALT ratio. Check albumin and total protein for synthetic function.<br/><br/>"
"<b>Step 5 — Synthesize the full picture.</b> "
"No value exists in isolation. Combine all clusters: "
"low albumin → correct calcium; high glucose → correct sodium; "
"AKI → expect hyperkalemia + acidosis; cirrhosis → expect hyponatremia + low albumin + coagulopathy."
)
steps_tbl = Table([[Paragraph(steps_txt, PS("st", fontSize=8.5, textColor=DARK_GREY,
leading=13))]], colWidths=[total_w])
steps_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), colors.HexColor("#EAFAF1")),
("BOX",(0,0),(-1,-1),1, GREEN),
("TOPPADDING",(0,0),(-1,-1),8),("BOTTOMPADDING",(0,0),(-1,-1),8),
("LEFTPADDING",(0,0),(-1,-1),10),("RIGHTPADDING",(0,0),(-1,-1),10)]))
story.append(steps_tbl)
# ── Build ────────────────────────────────────────────────────────────────────
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print("PDF generated:", OUTPUT)
cd /home/daytona/workspace/cmp-reference && python3 generate_cmp_pdf.py
ls -lh /home/daytona/workspace/cmp-reference/CMP_Quick_Reference.pdf
CMP Quick Reference
PDF Document · PDF
Create a list of normal lab values of Commonly asked NCLEX test
NCLEX normal lab values 2024 2025 commonly tested reference ranges
https://simplenursing.com/nclex-lab-values-nclex-practice-qu…
Next Gen NCLEX Note: The current NCLEX now provides reference ranges with lab questions. However, knowing these values deeply helps you recognize abnormals instantly and choose the correct nursing action - which is what the exam actually tests.
| Lab Test | Normal Range | Critical Values | NCLEX Pearl |
|---|---|---|---|
| WBC | 5,000–10,000 /µL | <2,000 or >30,000 | >10,000 = infection/inflammation; <2,500 = neutropenia precautions |
| RBC (male) | 4.5–6.2 million/µL | — | Low = anemia; high = polycythemia |
| RBC (female) | 4.0–5.5 million/µL | — | |
| Hemoglobin (male) | 14–18 g/dL | <7 or >20 | Transfuse typically when Hgb <7-8 g/dL |
| Hemoglobin (female) | 12–16 g/dL | <7 or >20 | |
| Hematocrit (male) | 42–52% | <21% or >66% | Hct ≈ 3× Hgb (quick check) |
| Hematocrit (female) | 37–47% | <21% or >66% | |
| Platelets | 150,000–400,000 /mm³ | <50,000 or >1,000,000 | <50,000 = bleeding risk; <20,000 = spontaneous bleed risk |
| MCV | 80–100 fL | — | Low = microcytic (iron def); High = macrocytic (B12/folate def) |
| MCH | 27–33 pg | — | Low = hypochromic |
| Reticulocytes | 0.5–2% | — | High = active RBC production (hemolysis, treatment response) |
| Lab Test | Normal Range | Critical Values | NCLEX Pearl |
|---|---|---|---|
| Sodium (Na⁺) | 135–145 mEq/L | <120 or >160 | Low = SIADH/overhydration; High = dehydration/DI |
| Potassium (K⁺) | 3.5–5.0 mEq/L | <2.5 or >6.5 | ECG changes at extremes; hold digoxin if K⁺ <3.5 |
| Chloride (Cl⁻) | 98–106 mEq/L | <80 or >115 | Reciprocal to HCO₃; low Cl = metabolic alkalosis |
| Bicarbonate (HCO₃⁻) | 22–29 mEq/L | <10 or >40 | Low = acidosis (DKA, renal failure); High = alkalosis (vomiting) |
| Calcium (Ca²⁺) | 8.5–10.2 mg/dL | <6.0 or >13.0 | Low = Chvostek's/Trousseau's sign; High = "bones, stones, groans, moans" |
| Magnesium (Mg²⁺) | 1.5–2.5 mEq/L | <1.0 or >4.0 | Low = cardiac arrhythmia, seizures; toxic = respiratory depression (esp. eclampsia Mg drip) |
| Phosphorus (PO₄) | 3.0–4.5 mg/dL | <1.0 or >8.0 | Inverse to calcium; low in hyperPTH, DKA treatment |
| Lab Test | Normal Range | Critical Values | NCLEX Pearl |
|---|---|---|---|
| BUN | 7–20 mg/dL | >100 | BUN:Cr >20:1 = pre-renal; hold contrast and metformin if elevated |
| Creatinine | 0.6–1.2 mg/dL | >10 (acute rise) | Best marker of kidney function; check before contrast dye |
| eGFR | ≥60 mL/min/1.73m² | <15 = kidney failure | <30 = avoid metformin; <60 = modify drug doses |
| Uric Acid | 3.5–8.0 mg/dL | — | Elevated in gout, tumor lysis syndrome |
| Lab Test | Normal Range | NCLEX Pearl |
|---|---|---|
| Fasting Blood Glucose | 70–100 mg/dL | <70 = hypoglycemia (give 15g carbs); >126 = diabetes diagnosis |
| 2-hr Glucose Tolerance | <140 mg/dL | 140–199 = prediabetes; ≥200 = diabetes |
| HbA1c | <5.7% | 5.7–6.4% = prediabetes; ≥6.5% = diabetes; target <7% for diabetics |
| Critical glucose | <40 or >500 = critical action needed |
| Component | Normal Range | Low Means | High Means |
|---|---|---|---|
| pH | 7.35–7.45 | Acidosis (<7.35) | Alkalosis (>7.45) |
| PaO₂ | 80–100 mmHg | Hypoxemia | Hyperoxia |
| PaCO₂ | 35–45 mmHg | Respiratory alkalosis (hyperventilation) | Respiratory acidosis (hypoventilation) |
| HCO₃⁻ | 22–26 mEq/L | Metabolic acidosis | Metabolic alkalosis |
| SaO₂ | >95% | Inadequate oxygenation | — |
| Base Excess | -2 to +2 | Metabolic acidosis | Metabolic alkalosis |
Respiratory Opposite — pH and PaCO₂ move in opposite directions Metabolic Equal — pH and HCO₃ move in the same direction
| Pattern | pH | PaCO₂ | HCO₃ | Common Cause |
|---|---|---|---|---|
| Respiratory Acidosis | ↓ | ↑ | Normal | COPD, hypoventilation, opioids |
| Respiratory Alkalosis | ↑ | ↓ | Normal | Hyperventilation, anxiety, PE |
| Metabolic Acidosis | ↓ | Normal | ↓ | DKA, renal failure, diarrhea |
| Metabolic Alkalosis | ↑ | Normal | ↑ | Vomiting, NG suction, diuretics |
| Lab Test | Normal Range | Therapeutic Range | Drug Monitored | NCLEX Pearl |
|---|---|---|---|---|
| PT (Prothrombin Time) | 11–12.5 seconds | 16–31 sec (1.5–2.5× normal) | Warfarin | Antidote: Vitamin K (slow) or FFP (fast) |
| INR | 0.8–1.1 | 2.0–3.0 (most); 2.5–3.5 (mechanical valves) | Warfarin | Hold warfarin if INR >3.0; reverse with Vitamin K |
| aPTT | 30–40 seconds | 45–80 sec (1.5–2× normal) | Heparin (unfractionated) | Antidote: Protamine sulfate |
| Fibrinogen | 200–400 mg/dL | — | — | Low in DIC, liver failure |
| D-dimer | <0.5 µg/mL | — | — | Elevated in DVT, PE, DIC (high sensitivity, low specificity) |
| Bleeding Time | 2–9 minutes | — | — | Measures platelet function |
| Lab Test | Normal Range | Elevated Suggests |
|---|---|---|
| AST | 10–40 U/L | Liver cell damage, MI, muscle injury |
| ALT | 7–56 U/L | Liver-specific damage (most sensitive) |
| ALP | 44–147 U/L | Cholestasis, bone disease |
| Total Bilirubin | 0.1–1.2 mg/dL | Jaundice appears >2.5; hepatitis, obstruction, hemolysis |
| Direct Bilirubin | 0–0.3 mg/dL | Obstructive jaundice (post-hepatic) |
| Albumin | 3.5–5.0 g/dL | Low = liver failure, malnutrition, nephrotic syndrome |
| Total Protein | 6.3–8.2 g/dL | Low = liver disease, malnutrition |
| Ammonia | 15–45 µg/dL | Elevated in hepatic encephalopathy; diet restriction + lactulose |
| Lab Test | Normal Range | NCLEX Pearl |
|---|---|---|
| Troponin I | <0.04 ng/mL | Rises 3–6 hrs after MI; peaks 14–18 hrs; most specific cardiac marker |
| Troponin T | <0.01 ng/mL | Any elevation is abnormal; remains elevated 7–10 days |
| CK-MB | <5% of total CK | Rises 4–8 hrs; peaks 12–24 hrs; returns to normal in 48–72 hrs |
| BNP | <100 pg/mL | >100 = heart failure likely; >400 = strong indicator |
| NT-proBNP | <125 pg/mL (<75 yrs) | Used to diagnose and monitor heart failure |
| Myoglobin | <90 µg/L | Earliest MI marker (rises 1–3 hrs) but not specific |
| Lab Test | Desirable Range | NCLEX Pearl |
|---|---|---|
| Total Cholesterol | <200 mg/dL | 200–239 = borderline; ≥240 = high |
| LDL | <100 mg/dL (optimal) | "Bad" cholesterol; target <70 in high-risk patients |
| HDL (male) | 35–65 mg/dL | "Good" cholesterol — HIGHER is better |
| HDL (female) | 35–80 mg/dL | <40 (male) or <50 (female) = cardiovascular risk factor |
| Triglycerides | <150 mg/dL | ≥200 = high; ≥500 = pancreatitis risk |
| Lab Test | Normal Range | Low Suggests | High Suggests |
|---|---|---|---|
| TSH | 0.4–4.0 mIU/L | Hyperthyroidism (T4 suppressing TSH) | Hypothyroidism |
| Free T4 | 0.8–1.8 ng/dL | Hypothyroidism | Hyperthyroidism |
| Total T4 | 5–12 µg/dL | Hypothyroidism | Hyperthyroidism |
| Total T3 | 70–205 ng/dL | Hypothyroidism | Hyperthyroidism |
NCLEX Tip: TSH is the best initial screening test for thyroid disorders. TSH and T4 move in opposite directions in primary thyroid disease.
| Drug | Therapeutic Range | Toxic Level | NCLEX Action if Toxic |
|---|---|---|---|
| Digoxin | 0.5–2.0 ng/mL | >2.0 ng/mL | Hold drug; check K⁺ (hypokalemia worsens toxicity); monitor ECG |
| Lithium | 0.6–1.2 mEq/L | >1.5 mEq/L | Hold; push fluids; check renal function |
| Phenytoin (Dilantin) | 10–20 µg/mL | >20 µg/mL | Hold; check for nystagmus, ataxia, confusion |
| Theophylline | 10–20 µg/mL | >20 µg/mL | Hold; monitor cardiac rhythm |
| Vancomycin (trough) | 10–20 µg/mL | >20 µg/mL | Nephrotoxic + ototoxic; check BUN/Cr |
| Carbamazepine | 4–12 µg/mL | >12 µg/mL | Hold; monitor CBC (aplastic anemia risk) |
| Valproic Acid | 50–100 µg/mL | >100 µg/mL | Hold; check liver function |
| Cyclosporine | 100–400 ng/mL | >400 ng/mL | Nephrotoxic; check Cr before dose |
| Lab Test | Normal Range | NCLEX Pearl |
|---|---|---|
| Urine Specific Gravity | 1.010–1.030 | <1.010 = dilute (overhydrated, DI); >1.030 = concentrated (dehydrated, SIADH) |
| Urine pH | 4.5–8.0 | Acidic urine (<5) in acidosis, starvation; alkaline in UTI, vegetarian diet |
| Creatinine Clearance | 85–135 mL/min | Measures true GFR; decreases with renal disease and aging |
| Urine Protein | <150 mg/24 hr | >300 mg/24 hr in pregnancy = preeclampsia; heavy proteinuria = nephrotic syndrome |
| Urine Glucose | Negative | Present when blood glucose >180 mg/dL (renal threshold) |
| Urine Ketones | Negative | Present in DKA, starvation, low-carb diet |
| Lab Test | Normal Range | Low Suggests | High Suggests |
|---|---|---|---|
| Serum Iron | 50–150 µg/dL | Iron-deficiency anemia | Hemochromatosis, hemolysis |
| TIBC (Total Iron Binding Capacity) | 250–370 µg/dL | Anemia of chronic disease | Iron-deficiency anemia |
| Ferritin | 12–300 ng/mL | Iron-deficiency | Hemochromatosis, inflammation, liver disease |
| Transferrin Saturation | 20–50% | Iron deficiency if <20% | Hemochromatosis if >50% |
| Lab Test | Normal Range | NCLEX Pearl |
|---|---|---|
| ESR (male) | 0–15 mm/hr | Nonspecific inflammatory marker; elevated in RA, lupus, infection |
| ESR (female) | 0–20 mm/hr | |
| CRP | <1.0 mg/dL | More sensitive/faster than ESR; used for cardiac risk stratification |
| Prealbumin | 15–36 mg/dL | Better short-term nutritional marker than albumin (half-life 2 days) |
| Serum Osmolality | 285–295 mOsm/kg | Low = overhydration/SIADH; High = dehydration/hyperglycemia/DI |
| Lactic Acid | 0.7–2.1 mmol/L | >2 = tissue hypoperfusion; >4 = severe sepsis/shock |
| Ammonia | 15–45 µg/dL | Elevated in hepatic encephalopathy |
| Lipase | 0–160 U/L | Elevated in pancreatitis (more specific than amylase) |
| Amylase | 25–125 U/L | Elevated in pancreatitis, parotitis |
| When you see… | Think… | Do… |
|---|---|---|
| K⁺ >5.5 or <2.5 | Cardiac arrhythmia risk | ECG first; notify provider |
| Platelets <50,000 | Bleeding precautions | Avoid invasive procedures; no IM injections |
| INR >3.0 on warfarin | Supratherapeutic anticoagulation | Hold warfarin; notify provider |
| aPTT >80 on heparin | Bleeding risk | Hold heparin; check for bleeding |
| Na⁺ <120 | Severe hyponatremia | Seizure precautions; careful correction (not faster than 8-10 mEq/L/24hr) |
| Troponin elevated | Acute myocardial injury | 12-lead ECG; notify provider immediately |
| Digoxin >2.0 + low K⁺ | Digoxin toxicity | Hold dig; replace K⁺; ECG monitoring |
| pH <7.35 | Acidosis | Determine if respiratory (↑PaCO₂) or metabolic (↓HCO₃) |
| Glucose <40 | Critical hypoglycemia | D50W IV (conscious: OJ/glucose tabs) |
| WBC >30,000 | Severe infection or leukemia | Blood cultures before antibiotics |
Generate a printable NCLEX lab values cheat sheet PDF
mkdir -p /home/daytona/workspace/nclex-labs && python3 -c "from reportlab.lib.pa…
~/nclex-labs/generate_nclex_cheatsheet.py
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.units import inch
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT
OUTPUT = "/home/daytona/workspace/nclex-labs/NCLEX_Lab_Values_Cheat_Sheet.pdf"
# ── Palette ──────────────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1B2A4A")
TEAL = colors.HexColor("#0B7A75")
ORANGE = colors.HexColor("#D9622B")
RED = colors.HexColor("#B03A2E")
GREEN = colors.HexColor("#1D6A39")
PURPLE = colors.HexColor("#5B2C6F")
GOLD = colors.HexColor("#9A7D0A")
BLUE = colors.HexColor("#1A5276")
PINK = colors.HexColor("#7B2D8B")
LBLUE = colors.HexColor("#EAF4FB")
LGREEN = colors.HexColor("#EAFAF1")
LORANGE = colors.HexColor("#FEF5E7")
LPURPLE = colors.HexColor("#F5EEF8")
LRED = colors.HexColor("#FDEDEC")
LTEAL = colors.HexColor("#E8F8F5")
LGOLD = colors.HexColor("#FDFAE5")
WHITE = colors.white
DGREY = colors.HexColor("#2C3E50")
MGREY = colors.HexColor("#BDC3C7")
LGREY = colors.HexColor("#F4F6F9")
def PS(name, **kw):
defaults = dict(fontName="Helvetica", fontSize=7.5, textColor=DGREY,
leading=10, spaceAfter=0, spaceBefore=0)
defaults.update(kw)
return ParagraphStyle(name, **defaults)
hdr_ps = PS("h", fontName="Helvetica-Bold", fontSize=7.8, textColor=WHITE)
bold_ps = PS("b", fontName="Helvetica-Bold", fontSize=7.5, textColor=NAVY)
red_ps = PS("r", fontName="Helvetica-Bold", fontSize=7.3, textColor=RED)
body_ps = PS("bd", fontSize=7.3, textColor=DGREY)
ctr_ps = PS("c", fontSize=7.3, textColor=DGREY, alignment=TA_CENTER)
ctr_b_ps = PS("cb", fontName="Helvetica-Bold", fontSize=7.3,
textColor=DGREY, alignment=TA_CENTER)
def C(txt, ps=None, **kw):
if ps is None:
ps = PS("_", **kw)
return Paragraph(str(txt), ps)
def sec_hdr(label, bg):
tbl = Table([[Paragraph(label,
PS("sh", fontName="Helvetica-Bold", fontSize=8.5,
textColor=WHITE, alignment=TA_CENTER))]],
colWidths=[7.5*inch])
tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), bg),
("TOPPADDING",(0,0),(-1,-1),4),
("BOTTOMPADDING",(0,0),(-1,-1),4),
]))
return tbl
BASE = [
("FONTNAME", (0,0),(-1,-1), "Helvetica"),
("FONTSIZE", (0,0),(-1,-1), 7.3),
("ROWBACKGROUNDS", (0,1),(-1,-1), [LGREY, WHITE]),
("GRID", (0,0),(-1,-1), 0.35, MGREY),
("VALIGN", (0,0),(-1,-1), "TOP"),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 4),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("BACKGROUND", (0,0),(-1,0), DGREY),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,0), 7.5),
("ALIGN", (0,0),(-1,0), "CENTER"),
]
def mktbl(data, col_w, extra=None):
t = Table(data, colWidths=col_w, repeatRows=1)
style = list(BASE)
if extra:
style += extra
t.setStyle(TableStyle(style))
return t
def row(vals, ps_list=None):
if ps_list is None:
ps_list = [body_ps]*len(vals)
return [C(v, p) for v, p in zip(vals, ps_list)]
def hrow(vals):
return [C(v, hdr_ps) for v in vals]
# ── Page callbacks ────────────────────────────────────────────────────────────
PAGE_W, PAGE_H = letter
def page_cb(canvas, doc):
# Top banner
canvas.setFillColor(NAVY)
canvas.rect(0, PAGE_H-50, PAGE_W, 50, fill=1, stroke=0)
canvas.setFillColor(TEAL)
canvas.rect(0, PAGE_H-54, PAGE_W, 4, fill=1, stroke=0)
canvas.setFont("Helvetica-Bold", 17)
canvas.setFillColor(WHITE)
canvas.drawCentredString(PAGE_W/2, PAGE_H-30,
"NCLEX LAB VALUES CHEAT SHEET")
canvas.setFont("Helvetica", 9)
canvas.setFillColor(colors.HexColor("#A8D8EA"))
canvas.drawCentredString(PAGE_W/2, PAGE_H-44,
"Quick Reference • Normal Ranges • Critical Values • Nursing Actions")
# Footer
canvas.setFillColor(TEAL)
canvas.rect(0, 26, PAGE_W, 2, fill=1, stroke=0)
canvas.setFont("Helvetica", 6.8)
canvas.setFillColor(MGREY)
canvas.drawCentredString(PAGE_W/2, 14,
f"For educational/NCLEX prep purposes only • Always verify with institutional reference ranges • Page {doc.page}")
# ── Build story ───────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(OUTPUT, pagesize=letter,
topMargin=0.75*inch, bottomMargin=0.45*inch,
leftMargin=0.45*inch, rightMargin=0.45*inch)
story = []
SP = lambda n=0.07: Spacer(1, n*inch)
# ╔══════════════════════════════════════════════════════════╗
# TWO-COLUMN LAYOUT via side-by-side tables
# ╚══════════════════════════════════════════════════════════╝
LW = 3.60*inch # left column width (total inner)
RW = 3.60*inch # right column
GAP = 0.30*inch
# ── Helper to place two blocks side-by-side ───────────────
def two_col(left_items, right_items):
lt = Table([[item] for item in left_items],
colWidths=[LW])
lt.setStyle(TableStyle([("TOPPADDING",(0,0),(-1,-1),0),
("BOTTOMPADDING",(0,0),(-1,-1),2),
("LEFTPADDING",(0,0),(-1,-1),0),
("RIGHTPADDING",(0,0),(-1,-1),0)]))
rt = Table([[item] for item in right_items],
colWidths=[RW])
rt.setStyle(TableStyle([("TOPPADDING",(0,0),(-1,-1),0),
("BOTTOMPADDING",(0,0),(-1,-1),2),
("LEFTPADDING",(0,0),(-1,-1),0),
("RIGHTPADDING",(0,0),(-1,-1),0)]))
outer = Table([[lt, Spacer(GAP, 1), rt]],
colWidths=[LW, GAP, RW])
outer.setStyle(TableStyle([
("VALIGN",(0,0),(-1,-1),"TOP"),
("TOPPADDING",(0,0),(-1,-1),0),
("BOTTOMPADDING",(0,0),(-1,-1),0),
("LEFTPADDING",(0,0),(-1,-1),0),
("RIGHTPADDING",(0,0),(-1,-1),0),
]))
return outer
# ──────────────────────────────────────────────────────────────────────────────
# LEFT COL BLOCK 1 — CBC
# ──────────────────────────────────────────────────────────────────────────────
cbc_sh = Table([[C("🔴 COMPLETE BLOOD COUNT (CBC)", PS("s",fontName="Helvetica-Bold",
fontSize=8,textColor=WHITE,alignment=TA_CENTER))]],
colWidths=[LW])
cbc_sh.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),RED),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4)]))
CBC_CW = [1.08*inch, 0.82*inch, 0.78*inch, 0.92*inch]
cbc_data = [
hrow(["TEST","NORMAL","CRITICAL","PEARL"]),
row(["WBC", "5,000–10,000 /µL", "<2K or >30K", "↑=infection; ↓=neutropenia precautions"]),
row(["Hgb (M)", "14–18 g/dL", "<7 g/dL", "Transfuse threshold ~7-8 g/dL"]),
row(["Hgb (F)", "12–16 g/dL", "<7 g/dL", "Hgb × 3 ≈ Hct (quick check)"]),
row(["Hct (M)", "42–52%", "<21% or >66%", "Low=anemia; High=polycythemia"]),
row(["Hct (F)", "37–47%", "<21% or >66%", ""]),
row(["Platelets", "150K–400K /mm³", "<50K or >1M", "<50K=bleed risk; <20K=spontaneous bleed"]),
row(["MCV", "80–100 fL", "—", "Low=iron def; High=B12/folate def"]),
row(["Reticulocytes", "0.5–2%", "—", "↑=active RBC production"]),
]
cbc_tbl = mktbl(cbc_data, CBC_CW)
# ──────────────────────────────────────────────────────────────────────────────
# LEFT COL BLOCK 2 — ABGs
# ──────────────────────────────────────────────────────────────────────────────
abg_sh = Table([[C("🫁 ARTERIAL BLOOD GASES (ABGs)", PS("s",fontName="Helvetica-Bold",
fontSize=8,textColor=WHITE,alignment=TA_CENTER))]],
colWidths=[LW])
abg_sh.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),TEAL),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4)]))
ABG_CW = [0.72*inch, 0.82*inch, 1.08*inch, 0.98*inch]
abg_data = [
hrow(["VALUE","NORMAL","LOW = ACIDOSIS","HIGH = ALKALOSIS"]),
row(["pH", "7.35–7.45", "Acidosis (<7.35)", "Alkalosis (>7.45)"]),
row(["PaO₂", "80–100 mmHg", "Hypoxemia", "Hyperoxia"]),
row(["PaCO₂", "35–45 mmHg", "Resp. Alkalosis (hypervent)", "Resp. Acidosis (hypovent)"]),
row(["HCO₃⁻", "22–26 mEq/L", "Metabolic Acidosis", "Metabolic Alkalosis"]),
row(["SaO₂", ">95%", "Hypoxia — intervene", "—"]),
]
abg_tbl = mktbl(abg_data, ABG_CW)
rome_txt = ("<b>ROME:</b> <b>R</b>esp <b>O</b>pposite (pH↓ + PaCO₂↑) | "
"<b>M</b>etabolic <b>E</b>qual (pH↓ + HCO₃↓)<br/>"
"Partially compensated = both values abnormal | "
"Fully compensated = pH normal, both others abnormal")
rome_box = Table([[Paragraph(rome_txt, PS("rm", fontSize=7.1, textColor=BLUE,
leading=10, backColor=LBLUE))]],
colWidths=[LW])
rome_box.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),LBLUE),
("BOX",(0,0),(-1,-1),0.8,TEAL),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
("LEFTPADDING",(0,0),(-1,-1),5),("RIGHTPADDING",(0,0),(-1,-1),5)]))
# ──────────────────────────────────────────────────────────────────────────────
# LEFT COL BLOCK 3 — COAGULATION
# ──────────────────────────────────────────────────────────────────────────────
coag_sh = Table([[C("🩸 COAGULATION STUDIES", PS("s",fontName="Helvetica-Bold",
fontSize=8,textColor=WHITE,alignment=TA_CENTER))]],
colWidths=[LW])
coag_sh.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),PURPLE),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4)]))
COAG_CW = [0.72*inch, 0.72*inch, 0.80*inch, 1.36*inch]
coag_data = [
hrow(["TEST","NORMAL","THERAPEUTIC","NURSING ACTION"]),
row(["PT", "11–12.5 sec", "16–31 sec\n(warfarin)", "Antidote: Vit K (slow) or FFP (fast)"]),
row(["INR", "0.8–1.1", "2.0–3.0\n(2.5–3.5 valves)","Hold warfarin if INR >3.0"]),
row(["aPTT", "30–40 sec", "45–80 sec\n(heparin)", "Antidote: Protamine sulfate"]),
row(["Fibrinogen","200–400 mg/dL","—", "Low in DIC & liver failure"]),
row(["D-dimer", "<0.5 µg/mL", "—", "↑ in DVT/PE/DIC (sensitive not specific)"]),
row(["Platelets", "150K–400K", "—", "<50K: no IM injections or invasive procedures"]),
]
coag_tbl = mktbl(coag_data, COAG_CW)
# ──────────────────────────────────────────────────────────────────────────────
# LEFT COL BLOCK 4 — LIPIDS
# ──────────────────────────────────────────────────────────────────────────────
lip_sh = Table([[C("🫀 LIPID PANEL", PS("s",fontName="Helvetica-Bold",
fontSize=8,textColor=WHITE,alignment=TA_CENTER))]],
colWidths=[LW])
lip_sh.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),GOLD),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4)]))
LIP_CW = [1.0*inch, 0.90*inch, 1.70*inch]
lip_data = [
hrow(["TEST","DESIRABLE","NCLEX PEARL"]),
row(["Total Cholesterol","<200 mg/dL", "200–239=borderline; ≥240=high risk"]),
row(["LDL", "<100 mg/dL", "\"Bad\" chol; target <70 in high-risk; statins lower LDL"]),
row(["HDL (M)", "35–65 mg/dL", "\"Good\" chol — HIGHER IS BETTER"]),
row(["HDL (F)", "35–80 mg/dL", "<40M or <50F = CV risk factor"]),
row(["Triglycerides", "<150 mg/dL", "≥500 = pancreatitis risk; fasting test"]),
]
lip_tbl = mktbl(lip_data, LIP_CW)
# ──────────────────────────────────────────────────────────────────────────────
# RIGHT COL BLOCK 1 — ELECTROLYTES
# ──────────────────────────────────────────────────────────────────────────────
elec_sh = Table([[C("⚡ ELECTROLYTES (BMP/CMP)", PS("s",fontName="Helvetica-Bold",
fontSize=8,textColor=WHITE,alignment=TA_CENTER))]],
colWidths=[RW])
elec_sh.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),BLUE),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4)]))
EL_CW = [0.80*inch, 0.78*inch, 0.78*inch, 1.24*inch]
elec_data = [
hrow(["TEST","NORMAL","CRITICAL","NCLEX PEARL"]),
row(["Na⁺", "135–145 mEq/L","<120 or >160","Low=SIADH/HF; High=dehydration/DI"]),
row(["K⁺", "3.5–5.0 mEq/L","<2.5 or >6.5","Cardiac arrhythmia at extremes; hold digoxin if <3.5"]),
row(["Cl⁻", "98–106 mEq/L", "<80 or >115", "Reciprocal to HCO₃; low=metabolic alkalosis"]),
row(["HCO₃⁻", "22–29 mEq/L", "<10 or >40", "Low=acidosis (DKA/renal); High=alkalosis (vomiting)"]),
row(["Ca²⁺", "8.5–10.2 mg/dL","<6 or >13", "Low=Chvostek/Trousseau; High=bones/stones/groans"]),
row(["Mg²⁺", "1.5–2.5 mEq/L","<1 or >4", "Low=arrhythmia; Toxic=resp depression (eclampsia)"]),
row(["PO₄", "3.0–4.5 mg/dL", "<1.0", "Inverse to Ca²⁺; low in hyperPTH & DKA treatment"]),
row(["BUN", "7–20 mg/dL", ">100", "BUN:Cr >20:1 = pre-renal; hold metformin if elevated"]),
row(["Creatinine","0.6–1.2 mg/dL",">10 (acute)","Check before contrast; rising Cr=AKI"]),
row(["Glucose","70–100 mg/dL", "<40 or >500", "HbA1c <5.7% normal; ≥6.5%=DM diagnosis"]),
]
elec_tbl = mktbl(elec_data, EL_CW)
ag_box = Table([[Paragraph(
"<b>Anion Gap = Na − (Cl + HCO₃) Normal: 8–12 mEq/L</b><br/>"
"High AG = MUDPILES: Methanol · Uremia · DKA · Propylene glycol · "
"Isoniazid · Lactic acidosis · Ethylene glycol · Salicylates",
PS("ag", fontSize=7, textColor=BLUE, leading=10, backColor=LBLUE))]],
colWidths=[RW])
ag_box.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),LBLUE),
("BOX",(0,0),(-1,-1),0.8,BLUE),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3),
("LEFTPADDING",(0,0),(-1,-1),5),("RIGHTPADDING",(0,0),(-1,-1),5)]))
# ──────────────────────────────────────────────────────────────────────────────
# RIGHT COL BLOCK 2 — LIVER + CARDIAC
# ──────────────────────────────────────────────────────────────────────────────
liv_sh = Table([[C("🟡 LIVER FUNCTION TESTS", PS("s",fontName="Helvetica-Bold",
fontSize=8,textColor=WHITE,alignment=TA_CENTER))]],
colWidths=[RW])
liv_sh.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),ORANGE),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4)]))
LV_CW = [0.82*inch, 0.70*inch, 1.68*inch]
liv_data = [
hrow(["TEST","NORMAL","NCLEX PEARL"]),
row(["AST", "10–40 U/L", "Liver, MI, muscle; AST:ALT >2:1 = alcoholic hepatitis"]),
row(["ALT", "7–56 U/L", "Most liver-specific; best marker hepatocellular injury"]),
row(["ALP", "44–147 U/L", "Cholestasis or bone disease; ALP↑ + GGT normal = bone source"]),
row(["Total Bili", "0.1–1.2 mg/dL", "Jaundice visible >2.5; hepatitis/obstruction/hemolysis"]),
row(["Albumin", "3.5–5.0 g/dL", "Low=liver failure/malnutrition; corrects Ca²⁺ calculation"]),
row(["Total Protein","6.3–8.2 g/dL", "= Albumin + Globulin; low=malnutrition/liver disease"]),
row(["Ammonia", "15–45 µg/dL", "↑=hepatic encephalopathy → lactulose; low-protein diet"]),
]
liv_tbl = mktbl(liv_data, LV_CW)
card_sh = Table([[C("❤️ CARDIAC MARKERS", PS("s",fontName="Helvetica-Bold",
fontSize=8,textColor=WHITE,alignment=TA_CENTER))]],
colWidths=[RW])
card_sh.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),RED),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4)]))
CARD_CW = [0.85*inch, 0.70*inch, 1.65*inch]
card_data = [
hrow(["TEST","NORMAL","NCLEX PEARL"]),
row(["Troponin I", "<0.04 ng/mL", "Rises 3–6hr post-MI; peaks 14–18hr; stays elevated 7–10d"]),
row(["Troponin T", "<0.01 ng/mL", "Any elevation = abnormal; most specific for cardiac damage"]),
row(["CK-MB", "<5% total CK", "Rises 4–8hr; peaks 12–24hr; returns normal in 48–72hr"]),
row(["BNP", "<100 pg/mL", ">100=HF likely; >400=strong HF indicator"]),
row(["Myoglobin", "<90 µg/L", "Earliest MI marker (1–3hr) but NOT specific"]),
]
card_tbl = mktbl(card_data, CARD_CW)
# ──────────────────────────────────────────────────────────────────────────────
# RIGHT COL BLOCK 3 — THYROID + DRUG LEVELS
# ──────────────────────────────────────────────────────────────────────────────
thy_sh = Table([[C("🦋 THYROID FUNCTION", PS("s",fontName="Helvetica-Bold",
fontSize=8,textColor=WHITE,alignment=TA_CENTER))]],
colWidths=[RW])
thy_sh.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),GREEN),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4)]))
THY_CW = [0.62*inch, 0.75*inch, 1.08*inch, 1.15*inch]
thy_data = [
hrow(["TEST","NORMAL","LOW SUGGESTS","HIGH SUGGESTS"]),
row(["TSH", "0.4–4.0 mIU/L", "Hyperthyroidism", "Hypothyroidism → levothyroxine"]),
row(["Free T4","0.8–1.8 ng/dL","Hypothyroidism", "Hyperthyroidism → PTU/methimazole"]),
row(["Total T4","5–12 µg/dL", "Hypothyroidism", "Hyperthyroidism"]),
row(["Total T3","70–205 ng/dL","Hypothyroidism", "Hyperthyroidism"]),
]
thy_tbl = mktbl(thy_data, THY_CW)
thy_note = Table([[Paragraph(
"<b>TSH is the BEST initial thyroid screening test.</b> "
"TSH and T4 move in OPPOSITE directions in primary thyroid disease.",
PS("tn", fontSize=7, textColor=GREEN, leading=10, backColor=LGREEN))]],
colWidths=[RW])
thy_note.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),LGREEN),
("BOX",(0,0),(-1,-1),0.8,GREEN),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3),
("LEFTPADDING",(0,0),(-1,-1),5),("RIGHTPADDING",(0,0),(-1,-1),5)]))
# ──────────────────────────────────────────────────────────────────────────────
# FULL-WIDTH — DRUG THERAPEUTIC LEVELS
# ──────────────────────────────────────────────────────────────────────────────
drug_sh = Table([[C("💊 DRUG THERAPEUTIC LEVELS (High-Alert Medications)",
PS("s",fontName="Helvetica-Bold",fontSize=8.5,
textColor=WHITE,alignment=TA_CENTER))]],
colWidths=[7.5*inch])
drug_sh.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),PURPLE),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4)]))
DR_CW = [0.90*inch, 0.88*inch, 0.85*inch, 1.30*inch, 3.57*inch]
drug_data = [
hrow(["DRUG","THERAPEUTIC","TOXIC LEVEL","ANTIDOTE","NURSING ACTION IF TOXIC"]),
row(["Digoxin", "0.5–2.0 ng/mL", ">2.0 ng/mL", "Digibind (Digoxin Immune Fab)",
"Hold drug; check K⁺ (hypoK worsens toxicity); ECG monitoring; signs: N/V, yellow-green halos"]),
row(["Lithium", "0.6–1.2 mEq/L", ">1.5 mEq/L", "None (supportive)",
"Hold lithium; push fluids; check renal function; signs: tremor, ataxia, confusion"]),
row(["Phenytoin", "10–20 µg/mL", ">20 µg/mL", "None (supportive)",
"Hold drug; monitor for nystagmus, ataxia, diplopia; check serum level"]),
row(["Theophylline", "10–20 µg/mL", ">20 µg/mL", "None (supportive)",
"Hold drug; ECG monitoring; signs: tachycardia, nausea, seizures"]),
row(["Vancomycin", "10–20 µg/mL\n(trough)", ">20 µg/mL","None (supportive)",
"Hold dose; nephrotoxic + ototoxic; check BUN/Cr; notify prescriber"]),
row(["Heparin (UFH)", "aPTT 45–80 sec", "aPTT >80 sec", "Protamine sulfate",
"Hold infusion; check for bleeding; 1 mg protamine per 100 units heparin given"]),
row(["Warfarin", "INR 2.0–3.0", "INR >3.0", "Vitamin K / FFP",
"Hold warfarin; Vit K for slow reversal; FFP for immediate reversal; monitor for bleeding"]),
row(["Carbamazepine", "4–12 µg/mL", ">12 µg/mL", "None (supportive)",
"Hold drug; CBC (aplastic anemia risk); liver function tests"]),
]
drug_tbl = mktbl(drug_data, DR_CW)
# ──────────────────────────────────────────────────────────────────────────────
# FULL-WIDTH — CRITICAL VALUES + NURSING ACTIONS
# ──────────────────────────────────────────────────────────────────────────────
crit_sh = Table([[C("🚨 CRITICAL VALUES — IMMEDIATE NURSING ACTION REQUIRED",
PS("s",fontName="Helvetica-Bold",fontSize=8.5,
textColor=WHITE,alignment=TA_CENTER))]],
colWidths=[7.5*inch])
crit_sh.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),colors.HexColor("#922B21")),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4)]))
CR_CW = [0.85*inch, 1.05*inch, 0.80*inch, 4.80*inch]
crit_data = [
hrow(["LAB","CRITICAL VALUE","CONCERN","PRIORITY NURSING ACTION"]),
row(["K⁺", ">6.5 or <2.5", "Cardiac arrest", "STAT ECG; calcium gluconate IV (if >6.5); insulin+dextrose; notify MD immediately"]),
row(["Na⁺", "<120 or >160", "Seizures/coma", "Seizure precautions; slow correction (max 8–10 mEq/L/24hr); frequent neuro checks"]),
row(["Glucose", "<40 or >500", "Brain damage/DKA", "<40: D50W IV or OJ/glucose tabs if conscious; >500: insulin protocol + fluids"]),
row(["Ca²⁺", "<6.0 or >13", "Tetany/arrest", "Low: IV calcium gluconate; High: IV fluids + loop diuretic + bisphosphonate"]),
row(["Troponin", "Any elevation", "Acute MI", "12-lead ECG immediately; notify MD; prepare for ACS protocol; aspirin if ordered"]),
row(["Hgb", "<7 g/dL", "Severe anemia", "Assess symptoms; anticipate transfusion order; type & screen; O₂ therapy"]),
row(["Platelets", "<50,000", "Bleeding risk", "Bleeding precautions; no IM injections; soft toothbrush; avoid aspirin/NSAIDs"]),
row(["INR", ">3.0", "Hemorrhage risk", "Hold warfarin; assess for active bleeding; notify MD; prepare Vit K or FFP"]),
row(["pH", "<7.20 or >7.60","Organ failure", "Notify MD immediately; ABG confirmation; prepare for ICU transfer"]),
row(["Creatinine", "Acute >10", "Renal failure", "I&O every hour; hold nephrotoxic drugs; nephrology consult; assess dialysis need"]),
row(["Ammonia", ">100 µg/dL", "Hepatic enceph.", "Neuro checks; lactulose; low-protein diet; fall/seizure precautions"]),
]
crit_tbl = mktbl(crit_data, CR_CW, extra=[
("ROWBACKGROUNDS",(0,1),(-1,-1),[LRED, WHITE])])
# ──────────────────────────────────────────────────────────────────────────────
# FULL-WIDTH — URINE + MISC
# ──────────────────────────────────────────────────────────────────────────────
misc_sh = Table([[C("🔬 URINE STUDIES + MISCELLANEOUS HIGH-YIELD VALUES",
PS("s",fontName="Helvetica-Bold",fontSize=8.5,
textColor=WHITE,alignment=TA_CENTER))]],
colWidths=[7.5*inch])
misc_sh.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),colors.HexColor("#1A5276")),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4)]))
# Two sub-tables side by side
MISC_L_CW = [1.1*inch, 0.85*inch, 1.65*inch]
urine_data = [
hrow(["URINE TEST","NORMAL","NCLEX PEARL"]),
row(["Specific Gravity","1.010–1.030","<1.010=dilute(DI/overhydrated); >1.030=concentrated(SIADH/dehydrated)"]),
row(["pH", "4.5–8.0", "Acidic in acidosis/starvation; alkaline in UTI/vegetarian diet"]),
row(["Protein", "<150 mg/24h","≥300mg=preeclampsia; heavy proteinuria=nephrotic syndrome"]),
row(["Glucose", "Negative", "Present when blood glucose >180 mg/dL (renal threshold)"]),
row(["Ketones", "Negative", "Present in DKA, starvation, low-carb diet"]),
row(["Creat. Clearance","85–135 mL/min","Decreases with age and renal disease; true GFR measure"]),
]
urine_tbl = mktbl(urine_data, MISC_L_CW)
MISC_R_CW = [1.1*inch, 0.82*inch, 1.68*inch]
misc_data = [
hrow(["MISC TEST","NORMAL","NCLEX PEARL"]),
row(["HbA1c", "<5.7%", "5.7–6.4%=prediabetes; ≥6.5%=DM; therapeutic target <7%"]),
row(["Serum Osmol.","285–295 mOsm/kg","Low=SIADH/overhydration; High=dehydration/hypernatremia"]),
row(["Lactic Acid", "0.7–2.1 mmol/L", ">2=tissue hypoperfusion; >4=severe sepsis/shock"]),
row(["Lipase", "0–160 U/L", "Best marker for pancreatitis (more specific than amylase)"]),
row(["Amylase", "25–125 U/L", "Pancreatitis, parotitis; less specific than lipase"]),
row(["Prealbumin", "15–36 mg/dL", "Short-term nutritional marker (half-life 2 days)"]),
row(["BNP", "<100 pg/mL", "Best marker for heart failure; guides diuretic therapy"]),
]
misc_tbl = mktbl(misc_data, MISC_R_CW)
misc_combined = Table([[urine_tbl, Spacer(0.30*inch, 1), misc_tbl]],
colWidths=[3.60*inch, 0.30*inch, 3.60*inch])
misc_combined.setStyle(TableStyle([
("VALIGN",(0,0),(-1,-1),"TOP"),
("TOPPADDING",(0,0),(-1,-1),0),
("BOTTOMPADDING",(0,0),(-1,-1),0),
("LEFTPADDING",(0,0),(-1,-1),0),
("RIGHTPADDING",(0,0),(-1,-1),0),
]))
# ──────────────────────────────────────────────────────────────────────────────
# ASSEMBLE STORY
# ──────────────────────────────────────────────────────────────────────────────
story.append(SP(0.05))
# Two-column: CBC + electrolytes
story.append(two_col(
[cbc_sh, cbc_tbl, SP(), abg_sh, abg_tbl, SP(0.04), rome_box,
SP(), coag_sh, coag_tbl, SP(), lip_sh, lip_tbl],
[elec_sh, elec_tbl, SP(0.04), ag_box,
SP(), liv_sh, liv_tbl,
SP(), card_sh, card_tbl,
SP(), thy_sh, thy_tbl, SP(0.04), thy_note]
))
story.append(SP(0.08))
story.append(drug_sh)
story.append(drug_tbl)
story.append(SP(0.08))
story.append(crit_sh)
story.append(crit_tbl)
story.append(SP(0.08))
story.append(misc_sh)
story.append(misc_combined)
# ── Build ─────────────────────────────────────────────────────────────────────
doc.build(story, onFirstPage=page_cb, onLaterPages=page_cb)
print("SUCCESS:", OUTPUT)
cd /home/daytona/workspace/nclex-labs && python3 generate_nclex_cheatsheet.py 2>…
~/nclex-labs/generate_nclex_cheatsheet.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/nclex-labs/generate_nclex_cheatsheet.py'
cd /home/daytona/workspace/nclex-labs && python3 generate_nclex_cheatsheet.py 2>…
ls -lh /home/daytona/workspace/nclex-labs/NCLEX_Lab_Values_Cheat_Sheet.pdf
NCLEX Lab Values Cheat Sheet
PDF Document · PDF
Create flash cards using these lab values
~/nclex-labs/generate_flashcards.py
"""
NCLEX Lab Values Flashcards — ReportLab
Layout: 3 × 3 grid per page, each card 2.5" × 3.3"
Pages alternate FRONT (question) then BACK (answer) so they can be
printed double-sided (flip on short edge) and cut out.
"""
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors
from reportlab.lib.units import inch
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.platypus import PageBreak
OUTPUT = "/home/daytona/workspace/nclex-labs/NCLEX_Lab_Flashcards.pdf"
# ── Dimensions ────────────────────────────────────────────────────────────────
CARD_W = 2.50 * inch
CARD_H = 3.30 * inch
COLS = 3
ROWS = 3
PER_PAGE = COLS * ROWS # 9 cards per page
# ── Colour palette ────────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1B2A4A")
TEAL = colors.HexColor("#0B7A75")
RED = colors.HexColor("#B03A2E")
ORANGE = colors.HexColor("#D9622B")
GREEN = colors.HexColor("#1D6A39")
PURPLE = colors.HexColor("#5B2C6F")
GOLD = colors.HexColor("#9A7D0A")
BLUE = colors.HexColor("#1A5276")
PINK = colors.HexColor("#7B2D8B")
WHITE = colors.white
LGREY = colors.HexColor("#F4F6F9")
DGREY = colors.HexColor("#2C3E50")
MGREY = colors.HexColor("#BDC3C7")
# Category → accent colour
CAT_COLOR = {
"CBC": RED,
"ELECTRO": BLUE,
"ABG": TEAL,
"COAG": PURPLE,
"LIVER": ORANGE,
"CARDIAC": RED,
"THYROID": GREEN,
"DRUG": PINK,
"LIPID": GOLD,
"URINE": NAVY,
"MISC": DGREY,
}
def PS(name, **kw):
base = dict(fontName="Helvetica", fontSize=8, textColor=DGREY,
leading=11, alignment=TA_CENTER)
base.update(kw)
return ParagraphStyle(name, **base)
# ── Raw flashcard data ────────────────────────────────────────────────────────
# Each entry: (category, question_front, answer_back)
CARDS = [
# ── CBC ──────────────────────────────────────────────────────────────────
("CBC",
"What is the normal\nWBC count?",
"5,000 – 10,000 /µL\n\n"
"↑ WBC = infection / inflammation\n"
"↓ WBC < 2,500 = neutropenia\n"
"→ protective isolation precautions"),
("CBC",
"Normal Hemoglobin\n(male vs female)?",
"Male: 14 – 18 g/dL\n"
"Female: 12 – 16 g/dL\n\n"
"Critical: < 7 g/dL\n"
"Transfusion threshold ≈ 7–8 g/dL\n"
"Quick check: Hgb × 3 ≈ Hct"),
("CBC",
"Normal Hematocrit\n(male vs female)?",
"Male: 42 – 52%\n"
"Female: 37 – 47%\n\n"
"Critical: < 21% or > 66%\n"
"Low = anemia\n"
"High = polycythemia / dehydration"),
("CBC",
"Normal Platelet count\nand critical values?",
"Normal: 150,000 – 400,000 /mm³\n\n"
"Critical: < 50,000 or > 1,000,000\n\n"
"< 50,000 → bleeding precautions;\n"
"no IM injections\n"
"< 20,000 → spontaneous bleeding risk"),
("CBC",
"What does MCV tell you\nand what is normal?",
"Normal MCV: 80 – 100 fL\n\n"
"↓ Low MCV (< 80) = Microcytic\n"
"→ Iron-deficiency anemia, thalassemia\n\n"
"↑ High MCV (> 100) = Macrocytic\n"
"→ B12 or Folate deficiency"),
# ── ELECTROLYTES ─────────────────────────────────────────────────────────
("ELECTRO",
"Normal Sodium (Na⁺)\nand critical levels?",
"Normal: 135 – 145 mEq/L\n\n"
"Critical: < 120 or > 160\n\n"
"↓ Hyponatremia → SIADH, HF, cirrhosis\n"
"↑ Hypernatremia → dehydration, DI\n"
"Correct Na max 8–10 mEq/L per 24 hr"),
("ELECTRO",
"Normal Potassium (K⁺)\nand critical levels?",
"Normal: 3.5 – 5.0 mEq/L\n\n"
"Critical: < 2.5 or > 6.5\n\n"
"↓ Hypokalemia → diuretics, vomiting\n"
"↑ Hyperkalemia → AKI, acidosis\n"
"Hold digoxin if K⁺ < 3.5\n"
"> 6.5 → STAT ECG!"),
("ELECTRO",
"Normal Calcium (Ca²⁺)\nand clinical signs?",
"Normal: 8.5 – 10.2 mg/dL\n\n"
"Critical: < 6.0 or > 13.0\n\n"
"↓ Hypocalcemia → Chvostek's sign,\n"
"Trousseau's sign, tetany\n"
"↑ Hypercalcemia → 'Bones, Stones,\n"
"Groans & Moans'; malignancy, hyperPTH"),
("ELECTRO",
"Normal Magnesium (Mg²⁺)\nand nursing concern?",
"Normal: 1.5 – 2.5 mEq/L\n\n"
"Critical: < 1.0 or > 4.0\n\n"
"↓ Low Mg → arrhythmia, seizures\n"
"↑ High Mg (toxicity) → loss of DTRs,\n"
"respiratory depression\n"
"(esp. Mg sulfate in eclampsia)"),
("ELECTRO",
"What is the Anion Gap\nformula and normal?",
"AG = Na⁺ − (Cl⁻ + HCO₃⁻)\n\n"
"Normal: 8 – 12 mEq/L\n\n"
"High AG = MUDPILES:\n"
"Methanol · Uremia · DKA\n"
"Propylene glycol · Isoniazid\n"
"Lactic acidosis · EG · Salicylates"),
("ELECTRO",
"Normal BUN and\nBUN:Cr ratio significance?",
"Normal BUN: 7 – 20 mg/dL\n\n"
"BUN:Cr Ratio:\n"
"> 20:1 → Pre-renal (dehydration,\n"
" GI bleed, heart failure)\n"
"10–20:1 → Normal\n"
"< 10:1 → Intrinsic renal / liver failure\n"
"Hold metformin if BUN ↑"),
("ELECTRO",
"Normal Creatinine\nand its clinical use?",
"Normal: 0.6 – 1.2 mg/dL\n\n"
"Critical: acute rise > 10 mg/dL\n\n"
"Best routine marker of renal function\n"
"Calculates eGFR\n"
"Always check BEFORE contrast dye\n"
"Rising Cr → hold nephrotoxic drugs"),
# ── ABGs ─────────────────────────────────────────────────────────────────
("ABG",
"Normal ABG values\n(all 5 components)?",
"pH: 7.35 – 7.45\n"
"PaO₂: 80 – 100 mmHg\n"
"PaCO₂: 35 – 45 mmHg\n"
"HCO₃⁻: 22 – 26 mEq/L\n"
"SaO₂: > 95%\n\n"
"pH < 7.35 = Acidosis\n"
"pH > 7.45 = Alkalosis"),
("ABG",
"What causes Respiratory\nAcidosis and Alkalosis?",
"Resp. Acidosis (↓pH, ↑PaCO₂):\n"
"COPD, hypoventilation, opioids,\n"
"sedation, airway obstruction\n\n"
"Resp. Alkalosis (↑pH, ↓PaCO₂):\n"
"Hyperventilation, anxiety, PE,\n"
"mechanical over-ventilation, fever"),
("ABG",
"What causes Metabolic\nAcidosis and Alkalosis?",
"Metab. Acidosis (↓pH, ↓HCO₃):\n"
"DKA, renal failure, diarrhea,\n"
"lactic acidosis (MUDPILES)\n\n"
"Metab. Alkalosis (↑pH, ↑HCO₃):\n"
"Vomiting, NG suction, diuretics,\n"
"antacid excess, Cushing's"),
("ABG",
"What is the ROME rule\nfor ABG interpretation?",
"R — Respiratory = Opposite\n"
" pH ↓ and PaCO₂ ↑ (acidosis)\n"
" pH ↑ and PaCO₂ ↓ (alkalosis)\n\n"
"M — Metabolic = Equal\n"
" pH ↓ and HCO₃ ↓ (acidosis)\n"
" pH ↑ and HCO₃ ↑ (alkalosis)"),
# ── COAGULATION ──────────────────────────────────────────────────────────
("COAG",
"Normal PT, INR\nand therapeutic ranges?",
"PT: 11 – 12.5 seconds\n"
"INR: 0.8 – 1.1 (normal)\n\n"
"Therapeutic INR: 2.0 – 3.0\n"
"(2.5 – 3.5 for mechanical heart valves)\n\n"
"Drug monitored: WARFARIN\n"
"Antidote: Vitamin K (slow)\n"
" FFP (rapid reversal)"),
("COAG",
"Normal aPTT and\ntherapeutic range?",
"Normal aPTT: 30 – 40 seconds\n\n"
"Therapeutic: 45 – 80 seconds\n"
"(1.5 – 2× normal)\n\n"
"Drug monitored: HEPARIN (UFH)\n"
"Antidote: Protamine sulfate\n"
"(1 mg per 100 units heparin given)"),
("COAG",
"What does D-dimer\nindicate?",
"Normal D-dimer: < 0.5 µg/mL\n\n"
"Elevated in:\n"
"• DVT / Pulmonary Embolism (PE)\n"
"• DIC (Disseminated Intravascular\n"
" Coagulation)\n"
"• Post-surgery / trauma\n\n"
"HIGH sensitivity, LOW specificity\n"
"(good to RULE OUT PE if negative)"),
# ── LIVER ────────────────────────────────────────────────────────────────
("LIVER",
"Normal AST and ALT\nand significance?",
"AST: 10 – 40 U/L\n"
"ALT: 7 – 56 U/L\n\n"
"ALT = most liver-specific enzyme\n\n"
"AST:ALT > 2:1 → Alcoholic hepatitis\n"
"AST or ALT > 1000 → Ischemic hepatitis,\n"
"acute viral hepatitis, or\n"
"acetaminophen toxicity"),
("LIVER",
"Normal ALP and Bilirubin\nand what elevation means?",
"ALP: 44 – 147 U/L\n"
"Total Bilirubin: 0.1 – 1.2 mg/dL\n\n"
"↑ ALP + ↑ Bili = Cholestatic pattern\n"
"→ gallstones, PBC, PSC, obstruction\n\n"
"↑ ALP + normal GGT = BONE source\n"
"→ Paget's, bone mets, fracture\n\n"
"Jaundice visible when Bili > 2.5"),
("LIVER",
"Normal Albumin\nand clinical significance?",
"Normal: 3.5 – 5.0 g/dL\n\n"
"Low albumin causes:\n"
"• Ascites (↓ oncotic pressure)\n"
"• Edema\n"
"• Pseudohypocalcemia\n\n"
"Ca correction formula:\n"
"Corrected Ca = Measured Ca\n"
"+ 0.8 × (4 − albumin)"),
# ── CARDIAC ──────────────────────────────────────────────────────────────
("CARDIAC",
"Normal Troponin levels\nand timing after MI?",
"Troponin I: < 0.04 ng/mL\n"
"Troponin T: < 0.01 ng/mL\n\n"
"Timing after MI:\n"
"• Rises: 3 – 6 hours\n"
"• Peaks: 14 – 18 hours\n"
"• Returns normal: 7 – 10 days\n\n"
"Most specific cardiac marker\n"
"Any elevation = ABNORMAL"),
("CARDIAC",
"Normal BNP and\nwhat it indicates?",
"Normal BNP: < 100 pg/mL\n\n"
"100–400 → Possible heart failure\n"
"> 400 → Strong HF indicator\n\n"
"NT-proBNP (< 75 yrs): < 125 pg/mL\n\n"
"Used to diagnose and monitor\n"
"heart failure severity\n"
"Guides diuretic therapy"),
("CARDIAC",
"What is the earliest\nmarker of MI?",
"MYOGLOBIN rises first:\n"
"• Rises: 1 – 3 hours after MI\n"
"• Normal: < 90 µg/L\n\n"
"BUT: NOT cardiac-specific\n"
"(also elevated in muscle injury)\n\n"
"Order of rise:\n"
"Myoglobin → CK-MB → Troponin\n"
"(Troponin = most specific & lasts longest)"),
# ── THYROID ──────────────────────────────────────────────────────────────
("THYROID",
"Normal TSH and\nhow to interpret it?",
"Normal TSH: 0.4 – 4.0 mIU/L\n\n"
"TSH = BEST initial screening test\n\n"
"↓ Low TSH → Hyperthyroidism\n"
"(T4 suppressing pituitary TSH)\n\n"
"↑ High TSH → Hypothyroidism\n"
"(pituitary working harder)\n\n"
"TSH and T4 move in OPPOSITE directions"),
("THYROID",
"Normal T3 and T4\nand drug treatments?",
"Free T4: 0.8 – 1.8 ng/dL\n"
"Total T4: 5 – 12 µg/dL\n"
"Total T3: 70 – 205 ng/dL\n\n"
"Hypothyroidism treatment:\n"
"→ Levothyroxine (Synthroid)\n"
"Take on empty stomach; check TSH\n\n"
"Hyperthyroidism treatment:\n"
"→ PTU or Methimazole"),
# ── DRUG LEVELS ──────────────────────────────────────────────────────────
("DRUG",
"Therapeutic & toxic level\nfor DIGOXIN?",
"Therapeutic: 0.5 – 2.0 ng/mL\n"
"Toxic: > 2.0 ng/mL\n\n"
"Antidote: Digibind (Digoxin Fab)\n\n"
"Toxicity signs:\n"
"N/V, bradycardia, yellow-green halos,\n"
"dysrhythmias\n\n"
"HYPOKALEMIA worsens toxicity!\n"
"Hold if K⁺ < 3.5 or HR < 60"),
("DRUG",
"Therapeutic & toxic level\nfor LITHIUM?",
"Therapeutic: 0.6 – 1.2 mEq/L\n"
"Toxic: > 1.5 mEq/L\n"
"Severe: > 2.0 mEq/L\n\n"
"Antidote: None (supportive care)\n\n"
"Toxicity signs:\n"
"Tremor, ataxia, confusion,\n"
"slurred speech, seizures\n\n"
"Maintain adequate fluid/Na intake"),
("DRUG",
"Therapeutic & toxic level\nfor WARFARIN (INR)?",
"Therapeutic INR: 2.0 – 3.0\n"
"(2.5–3.5 for mechanical valves)\n\n"
"Toxic: INR > 3.0\n\n"
"Antidote:\n"
"• Vitamin K — slow reversal\n"
"• FFP — rapid reversal\n"
"• Andexanet alfa (Factor Xa)\n\n"
"Monitor for bleeding signs;\n"
"educate on consistent vitamin K diet"),
("DRUG",
"Therapeutic & toxic level\nfor HEPARIN (aPTT)?",
"Therapeutic aPTT: 45 – 80 sec\n"
"(1.5 – 2× normal)\n\n"
"Toxic: aPTT > 80 sec\n\n"
"Antidote: Protamine sulfate\n"
"(1 mg per 100 units heparin)\n\n"
"Signs of toxicity: bleeding,\n"
"hematuria, petechiae, hematoma\n"
"Monitor platelet count (HIT risk)"),
("DRUG",
"Therapeutic & toxic level\nfor PHENYTOIN?",
"Therapeutic: 10 – 20 µg/mL\n"
"Toxic: > 20 µg/mL\n\n"
"Antidote: None (supportive)\n\n"
"Toxicity signs (SAND):\n"
"S — Slurred speech\n"
"A — Ataxia\n"
"N — Nystagmus\n"
"D — Diplopia\n\n"
"Hold dose; check serum level"),
("DRUG",
"Therapeutic & toxic level\nfor VANCOMYCIN?",
"Therapeutic trough: 10 – 20 µg/mL\n"
"Toxic: > 20 µg/mL\n\n"
"Antidote: None (supportive)\n\n"
"Side effects:\n"
"• NEPHROTOXIC → check BUN/Cr\n"
"• OTOTOXIC → monitor hearing\n"
"• Red Man Syndrome (rapid infusion)\n"
"→ slow infusion rate; pre-medicate"),
# ── LIPIDS ───────────────────────────────────────────────────────────────
("LIPID",
"Desirable lipid levels\n(all four values)?",
"Total Cholesterol: < 200 mg/dL\n"
"LDL: < 100 mg/dL (optimal)\n"
" < 70 mg/dL (high-risk pts)\n"
"HDL: > 60 mg/dL (protective)\n"
" < 40M / < 50F = CV risk\n"
"Triglycerides: < 150 mg/dL\n\n"
"HDL = 'Good' — HIGHER is BETTER\n"
"LDL = 'Bad' — LOWER is BETTER"),
("LIPID",
"When do triglycerides\nbecome dangerous?",
"Normal: < 150 mg/dL\n"
"Borderline: 150 – 199\n"
"High: 200 – 499\n"
"Very High: ≥ 500 mg/dL\n\n"
"≥ 500 mg/dL = PANCREATITIS RISK\n\n"
"Causes: DM, alcohol, hypothyroidism,\n"
"obesity, certain medications\n"
"Must be FASTING test for accuracy"),
# ── URINE ────────────────────────────────────────────────────────────────
("URINE",
"Normal urine specific\ngravity and meaning?",
"Normal: 1.010 – 1.030\n\n"
"< 1.010 = DILUTE urine\n"
"→ Overhydration, DI (diabetes insipidus),\n"
" renal failure\n\n"
"> 1.030 = CONCENTRATED urine\n"
"→ Dehydration, SIADH,\n"
" hypovolemia, fever"),
("URINE",
"Normal HbA1c and\ndiabetes thresholds?",
"Normal: < 5.7%\n"
"Pre-diabetes: 5.7 – 6.4%\n"
"Diabetes: ≥ 6.5%\n\n"
"Therapeutic target for diabetics: < 7%\n\n"
"Represents average blood glucose\n"
"over the past 2–3 months\n"
"Not affected by fasting status"),
# ── MISCELLANEOUS ─────────────────────────────────────────────────────────
("MISC",
"Normal Lactic Acid\nand clinical meaning?",
"Normal: 0.7 – 2.1 mmol/L\n\n"
"> 2.0 mmol/L → Tissue hypoperfusion,\n"
"sepsis, shock, liver failure\n\n"
"> 4.0 mmol/L → Severe sepsis / shock\n"
"→ ICU admission; fluid resuscitation;\n"
" identify and treat source\n\n"
"Lactic acidosis = HIGH anion gap"),
("MISC",
"Normal Lipase\nvs Amylase?",
"Lipase: 0 – 160 U/L\n"
"Amylase: 25 – 125 U/L\n\n"
"Lipase = MORE SPECIFIC for pancreatitis\n"
"(not elevated in parotitis)\n\n"
"Amylase = less specific\n"
"(also elevated in parotitis,\n"
"bowel obstruction, ectopic pregnancy)\n\n"
"Order LIPASE first for pancreatitis"),
("MISC",
"Normal serum osmolality\nand interpretation?",
"Normal: 285 – 295 mOsm/kg\n\n"
"↓ Low (<280) → SIADH, overhydration,\n"
"hyponatremia\n\n"
"↑ High (>295) → Dehydration,\n"
"hypernatremia, hyperglycemia, DI,\n"
"uremia, ethanol ingestion\n\n"
"Quick formula:\n"
"Osm ≈ 2(Na) + Glucose/18 + BUN/2.8"),
("MISC",
"Critical value for Ammonia\nand nursing actions?",
"Normal: 15 – 45 µg/dL\n\n"
"Elevated in: Hepatic encephalopathy,\n"
"liver failure, Reye syndrome\n\n"
"Nursing actions:\n"
"• Neuro checks (LOC, asterixis)\n"
"• Administer lactulose\n"
"• Low-protein diet (acute)\n"
"• Fall and seizure precautions\n"
"• Safety environment"),
]
# ── Card rendering ────────────────────────────────────────────────────────────
def make_card_front(cat, question):
"""Returns a Table cell representing the FRONT of a flashcard."""
accent = CAT_COLOR.get(cat, NAVY)
cat_label = {
"CBC": "CBC", "ELECTRO": "ELECTROLYTES", "ABG": "BLOOD GASES",
"COAG": "COAGULATION", "LIVER": "LIVER FUNCTION",
"CARDIAC": "CARDIAC MARKERS", "THYROID": "THYROID",
"DRUG": "DRUG LEVELS", "LIPID": "LIPID PANEL",
"URINE": "URINE / MISC", "MISC": "MISCELLANEOUS",
}.get(cat, cat)
cat_p = Paragraph(cat_label, ParagraphStyle("cl",
fontName="Helvetica-Bold", fontSize=7, textColor=WHITE,
alignment=TA_CENTER, leading=9))
q_p = Paragraph(question.replace("\n","<br/>"),
ParagraphStyle("qp", fontName="Helvetica-Bold",
fontSize=10, textColor=NAVY,
alignment=TA_CENTER, leading=14))
hint = Paragraph("▼ answer on back ▼",
ParagraphStyle("ht", fontName="Helvetica-Oblique",
fontSize=7, textColor=colors.HexColor("#95A5A6"),
alignment=TA_CENTER, leading=9))
inner = Table(
[[cat_p], [Spacer(1, 0.08*inch)], [q_p], [Spacer(1, 0.1*inch)], [hint]],
colWidths=[CARD_W - 0.18*inch]
)
inner.setStyle(TableStyle([
("ALIGN", (0,0),(-1,-1), "CENTER"),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("TOPPADDING", (0,0),(-1,-1), 2),
("BOTTOMPADDING", (0,0),(-1,-1), 2),
("LEFTPADDING", (0,0),(-1,-1), 4),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("BACKGROUND", (0,0),(0,0), accent),
("TOPPADDING", (0,0),(0,0), 4),
("BOTTOMPADDING", (0,0),(0,0), 4),
]))
return inner
def make_card_back(cat, answer):
"""Returns a Table cell representing the BACK of a flashcard."""
accent = CAT_COLOR.get(cat, NAVY)
ans_p = Paragraph(answer.replace("\n","<br/>"),
ParagraphStyle("ap", fontName="Helvetica",
fontSize=8.2, textColor=DGREY,
alignment=TA_LEFT, leading=12))
inner = Table(
[[ans_p]],
colWidths=[CARD_W - 0.22*inch]
)
inner.setStyle(TableStyle([
("ALIGN", (0,0),(-1,-1), "LEFT"),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("TOPPADDING", (0,0),(-1,-1), 8),
("BOTTOMPADDING", (0,0),(-1,-1), 8),
("LEFTPADDING", (0,0),(-1,-1), 8),
("RIGHTPADDING", (0,0),(-1,-1), 6),
]))
# Wrap with coloured left border via outer table
border = Table([[inner]], colWidths=[CARD_W - 0.10*inch])
border.setStyle(TableStyle([
("LEFTPADDING", (0,0),(-1,-1), 5),
("TOPPADDING", (0,0),(-1,-1), 0),
("BOTTOMPADDING", (0,0),(-1,-1), 0),
("RIGHTPADDING", (0,0),(-1,-1), 0),
("LINEBEFORE", (0,0),(0,-1), 3, accent),
]))
return border
# ── Card cell wrapper (adds border + background) ──────────────────────────────
def card_cell(inner, bg=WHITE):
t = Table([[inner]], colWidths=[CARD_W], rowHeights=[CARD_H])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), bg),
("BOX", (0,0),(-1,-1), 1.2, MGREY),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 4),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("ALIGN", (0,0),(-1,-1), "CENTER"),
]))
return t
def blank_card():
t = Table([[""]], colWidths=[CARD_W], rowHeights=[CARD_H])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), LGREY),
("BOX", (0,0),(-1,-1), 0.5, MGREY),
]))
return t
# ── Build grid pages ──────────────────────────────────────────────────────────
def build_grid_page(cells):
"""Takes a flat list of 9 card-cell Tables, returns a 3×3 Table."""
while len(cells) < PER_PAGE:
cells.append(blank_card())
rows_data = []
for r in range(ROWS):
rows_data.append([cells[r*COLS+c] for c in range(COLS)])
grid = Table(rows_data,
colWidths=[CARD_W]*COLS,
rowHeights=[CARD_H]*ROWS)
grid.setStyle(TableStyle([
("TOPPADDING", (0,0),(-1,-1), 2),
("BOTTOMPADDING", (0,0),(-1,-1), 2),
("LEFTPADDING", (0,0),(-1,-1), 2),
("RIGHTPADDING", (0,0),(-1,-1), 2),
("ALIGN", (0,0),(-1,-1), "CENTER"),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]))
return grid
# ── Page callback ─────────────────────────────────────────────────────────────
PAGE_W, PAGE_H = letter
def on_front_page(canvas, doc):
# tiny top label
canvas.setFillColor(NAVY)
canvas.rect(0, PAGE_H-22, PAGE_W, 22, fill=1, stroke=0)
canvas.setFont("Helvetica-Bold", 10)
canvas.setFillColor(WHITE)
canvas.drawCentredString(PAGE_W/2, PAGE_H-14,
"NCLEX LAB VALUES FLASHCARDS — FRONT (Questions)")
canvas.setFont("Helvetica", 7)
canvas.setFillColor(MGREY)
canvas.drawCentredString(PAGE_W/2, 10,
f"Print double-sided (flip on SHORT edge) then cut along card borders • Page {doc.page}")
def on_back_page(canvas, doc):
canvas.setFillColor(TEAL)
canvas.rect(0, PAGE_H-22, PAGE_W, 22, fill=1, stroke=0)
canvas.setFont("Helvetica-Bold", 10)
canvas.setFillColor(WHITE)
canvas.drawCentredString(PAGE_W/2, PAGE_H-14,
"NCLEX LAB VALUES FLASHCARDS — BACK (Answers)")
canvas.setFont("Helvetica", 7)
canvas.setFillColor(MGREY)
canvas.drawCentredString(PAGE_W/2, 10,
f"Print double-sided (flip on SHORT edge) then cut along card borders • Page {doc.page}")
# ── Alternate page callback ───────────────────────────────────────────────────
page_types = [] # will be filled: 'F' or 'B'
def on_page(canvas, doc):
idx = doc.page - 1
if idx < len(page_types) and page_types[idx] == 'B':
on_back_page(canvas, doc)
else:
on_front_page(canvas, doc)
# ── Assemble story ────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(OUTPUT, pagesize=letter,
topMargin=0.32*inch, bottomMargin=0.20*inch,
leftMargin=0.28*inch, rightMargin=0.28*inch)
story = []
# Chunk cards into pages of 9
chunks = [CARDS[i:i+PER_PAGE] for i in range(0, len(CARDS), PER_PAGE)]
for chunk in chunks:
# FRONT page
front_cells = [card_cell(make_card_front(cat, q)) for cat, q, _ in chunk]
story.append(build_grid_page(front_cells))
page_types.append('F')
story.append(PageBreak())
# BACK page — mirror column order for double-sided printing
back_cells_raw = [card_cell(make_card_back(cat, a), bg=colors.HexColor("#FDFEFE"))
for cat, _, a in chunk]
# Pad to 9
while len(back_cells_raw) < PER_PAGE:
back_cells_raw.append(blank_card())
# Mirror columns (col 0↔2) for correct flip alignment
mirrored = []
for r in range(ROWS):
row_cells = back_cells_raw[r*COLS:(r+1)*COLS]
mirrored.extend(reversed(row_cells))
story.append(build_grid_page(mirrored))
page_types.append('B')
story.append(PageBreak())
# Remove final PageBreak
if story and isinstance(story[-1], PageBreak):
story.pop()
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print(f"SUCCESS: {OUTPUT} ({len(CARDS)} cards, {len(chunks)*2} pages)")
cd /home/daytona/workspace/nclex-labs && python3 generate_flashcards.py 2>&1
ls -lh /home/daytona/workspace/nclex-labs/NCLEX_Lab_Flashcards.pdf
NCLEX Lab Flashcards
PDF Document · PDF
| Color | Category | Cards |
|---|---|---|
| 🔴 Red | CBC | WBC, Hgb, Hct, Platelets, MCV |
| 🔵 Blue | Electrolytes/BMP | Na, K, Ca, Mg, Anion Gap, BUN, Creatinine |
| 🟢 Teal | ABGs | Normal values, Resp/Metabolic patterns, ROME rule |
| 🟣 Purple | Coagulation | PT/INR, aPTT, D-dimer |
| 🟠 Orange | Liver Function | AST/ALT, ALP/Bili, Albumin |
| 🔴 Red | Cardiac Markers | Troponin, BNP, Myoglobin |
| 🌿 Green | Thyroid | TSH, T3/T4 |
| 🩷 Pink | Drug Levels | Digoxin, Lithium, Warfarin, Heparin, Phenytoin, Vancomycin |
| 🟡 Gold | Lipids | Cholesterol, LDL/HDL, Triglycerides |
| 🔵 Navy | Urine/Misc | Specific gravity, HbA1c, Lactic acid, Lipase, Osmolality, Ammonia |
Create a pharmacology quick reference guide on common drug-lab value interactions
common drug lab value interactions nursing pharmacology monitoring reference 2024
~/nclex-labs/generate_drug_lab_guide.py
"""
Pharmacology Quick Reference Guide: Drug-Lab Value Interactions
ReportLab PDF — organized by drug class
"""
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors
from reportlab.lib.units import inch
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak, HRFlowable
)
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
OUTPUT = "/home/daytona/workspace/nclex-labs/Drug_Lab_Interactions_Guide.pdf"
# ── Palette ──────────────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1B2A4A")
TEAL = colors.HexColor("#0B7A75")
RED = colors.HexColor("#B03A2E")
ORANGE = colors.HexColor("#D9622B")
GREEN = colors.HexColor("#1D6A39")
PURPLE = colors.HexColor("#5B2C6F")
GOLD = colors.HexColor("#9A7D0A")
BLUE = colors.HexColor("#1A5276")
MAROON = colors.HexColor("#7B241C")
SLATE = colors.HexColor("#2E4057")
WHITE = colors.white
DGREY = colors.HexColor("#2C3E50")
MGREY = colors.HexColor("#BDC3C7")
LGREY = colors.HexColor("#F4F6F9")
LRED = colors.HexColor("#FDEDEC")
LGREEN = colors.HexColor("#EAFAF1")
LBLUE = colors.HexColor("#EBF5FB")
LORANGE= colors.HexColor("#FEF5E7")
LPURPLE= colors.HexColor("#F5EEF8")
PAGE_W, PAGE_H = letter
def PS(name, **kw):
base = dict(fontName="Helvetica", fontSize=8, textColor=DGREY, leading=11)
base.update(kw)
return ParagraphStyle(name, **base)
hdr_ps = PS("h", fontName="Helvetica-Bold", fontSize=8, textColor=WHITE)
body_ps = PS("b", fontSize=7.8, textColor=DGREY, leading=11)
bold_ps = PS("bd", fontName="Helvetica-Bold", fontSize=7.8, textColor=NAVY, leading=11)
red_ps = PS("r", fontName="Helvetica-Bold", fontSize=7.8, textColor=RED, leading=11)
ctr_ps = PS("c", fontSize=7.8, textColor=DGREY, leading=11,
alignment=TA_CENTER)
def C(txt, ps=body_ps):
return Paragraph(str(txt), ps)
BASE_TBL = [
("FONTNAME", (0,0),(-1,-1), "Helvetica"),
("FONTSIZE", (0,0),(-1,-1), 7.8),
("ROWBACKGROUNDS", (0,1),(-1,-1), [LGREY, WHITE]),
("GRID", (0,0),(-1,-1), 0.35, MGREY),
("VALIGN", (0,0),(-1,-1), "TOP"),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 5),
("RIGHTPADDING", (0,0),(-1,-1), 5),
("BACKGROUND", (0,0),(-1,0), DGREY),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,0), 8),
("ALIGN", (0,0),(-1,0), "CENTER"),
]
FULL_W = 7.5 * inch
COL_W = [1.30*inch, 0.95*inch, 0.90*inch, 1.15*inch, 1.55*inch, 1.65*inch]
def hrow(vals):
return [C(v, hdr_ps) for v in vals]
def mktbl(data, cw=None, extra=None):
if cw is None: cw = COL_W
t = Table(data, colWidths=cw, repeatRows=1)
style = list(BASE_TBL)
if extra: style += extra
t.setStyle(TableStyle(style))
return t
def sec_hdr(label, bg, sub=""):
lines = [C(label, PS("sh", fontName="Helvetica-Bold", fontSize=10,
textColor=WHITE, alignment=TA_CENTER, leading=13))]
if sub:
lines.append(C(sub, PS("ss", fontSize=7.5, textColor=colors.HexColor("#D5D8DC"),
alignment=TA_CENTER, leading=10)))
cells = [[item] for item in lines]
t = Table(cells, colWidths=[FULL_W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), bg),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 8),
]))
return t
def note_box(txt, bg, border_col):
t = Table([[Paragraph(txt, PS("nb", fontSize=7.5, textColor=DGREY,
leading=11, backColor=bg))]],
colWidths=[FULL_W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), bg),
("BOX", (0,0),(-1,-1), 1, border_col),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 8),
("RIGHTPADDING", (0,0),(-1,-1), 8),
]))
return t
SP = lambda n=0.08: Spacer(1, n*inch)
# ── Page banner ───────────────────────────────────────────────────────────────
def on_page(canvas, doc):
canvas.setFillColor(NAVY)
canvas.rect(0, PAGE_H-52, PAGE_W, 52, fill=1, stroke=0)
canvas.setFillColor(TEAL)
canvas.rect(0, PAGE_H-56, PAGE_W, 4, fill=1, stroke=0)
canvas.setFont("Helvetica-Bold", 16)
canvas.setFillColor(WHITE)
canvas.drawCentredString(PAGE_W/2, PAGE_H-28,
"PHARMACOLOGY QUICK REFERENCE: Drug-Lab Value Interactions")
canvas.setFont("Helvetica", 9)
canvas.setFillColor(colors.HexColor("#A8D8EA"))
canvas.drawCentredString(PAGE_W/2, PAGE_H-44,
"Drugs That Affect Lab Values • Required Monitoring • Critical Actions & Antidotes")
canvas.setFillColor(TEAL)
canvas.rect(0, 26, PAGE_W, 2, fill=1, stroke=0)
canvas.setFont("Helvetica", 7)
canvas.setFillColor(MGREY)
canvas.drawCentredString(PAGE_W/2, 14,
f"For educational use only • Verify with current clinical guidelines & institutional protocols • Page {doc.page}")
# ═══════════════════════════════════════════════════════════════════════════════
story = []
SP0 = Spacer(1, 0.10*inch)
MAIN_COLS = ["DRUG / CLASS", "AFFECTED LAB", "DIRECTION", "MECHANISM", "NURSING MONITOR", "ACTION IF ABNORMAL"]
# ╔══════════════════════════════════════════════════════════════════════════╗
# 1. CARDIOVASCULAR DRUGS
# ╚══════════════════════════════════════════════════════════════════════════╝
story.append(SP0)
story.append(sec_hdr("1. CARDIOVASCULAR DRUGS",
NAVY, "ACE Inhibitors • ARBs • Diuretics • Digoxin • Statins • Antiarrhythmics"))
story.append(mktbl([
hrow(MAIN_COLS),
[C("ACE Inhibitors\n(lisinopril, enalapril,\ncaptopril)", bold_ps),
C("Potassium (K⁺)\nCreatinine\nBUN"),
C("↑ K⁺\n↑ Cr\n↑ BUN"),
C("Block angiotensin II → ↓ aldosterone → K⁺ retention; ↓ GFR in renal artery stenosis"),
C("K⁺, Cr, BUN at baseline, 1–2 wks after start, then every 3–6 months"),
C("Hold if K⁺ >5.5 or Cr rises >30% from baseline; notify provider; avoid NSAIDs + ACEi combo")],
[C("ARBs\n(losartan, valsartan,\nirbesartan)", bold_ps),
C("Potassium (K⁺)\nCreatinine"),
C("↑ K⁺\n↑ Cr"),
C("Same mechanism as ACEi (block AT1 receptor); same renal and K⁺ effects"),
C("Same as ACEi: K⁺, Cr, BUN at baseline and periodically"),
C("Do NOT combine ARB + ACEi — doubles hyperkalemia/AKI risk")],
[C("Loop Diuretics\n(furosemide,\nbumetanide)", bold_ps),
C("K⁺, Na⁺, Mg²⁺\nBUN, Cr\nUric Acid"),
C("↓ K⁺, Na⁺, Mg²⁺\n↑ BUN, Cr\n↑ Uric Acid"),
C("Block Na-K-2Cl in loop of Henle → electrolyte wasting; volume depletion → prerenal azotemia"),
C("Daily weight, electrolytes, BUN/Cr; watch K⁺ <3.5; magnesium often overlooked"),
C("Replace K⁺ and Mg²⁺; hold if signs of dehydration; Caution: hypoK worsens digoxin toxicity")],
[C("Thiazide Diuretics\n(HCTZ,\nchlorthalidone)", bold_ps),
C("K⁺, Na⁺\nGlucose\nUric Acid, Ca²⁺"),
C("↓ K⁺, Na⁺\n↑ Glucose\n↑ Uric Acid, ↑ Ca²⁺"),
C("Na-Cl block in distal tubule; ↑ Ca reabsorption; impair insulin release"),
C("Electrolytes, glucose, BUN/Cr, uric acid at baseline and periodically"),
C("Monitor for new/worsening diabetes; hold if K⁺ <3.0; caution in gout")],
[C("K⁺-Sparing Diuretics\n(spironolactone,\namiloride)", bold_ps),
C("Potassium (K⁺)\nCreatinine\nTestosterone"),
C("↑ K⁺\n↑ Cr\n↓ Testosterone (spiro)"),
C("Block aldosterone receptor or ENaC → K⁺ retention; spironolactone is anti-androgenic"),
C("K⁺ and Cr at baseline and 1 month after dose change; avoid with ACEi/ARB if possible"),
C("Hold if K⁺ >5.5; gynecomastia with spironolactone — may need dose adjustment")],
[C("Digoxin", bold_ps),
C("Digoxin level\nK⁺\nMg²⁺\nCreatinine"),
C("Toxic >2.0 ng/mL\n↓ K⁺ worsens\n↓ Mg²⁺ worsens\n↑ Cr → toxicity"),
C("Narrow therapeutic index; renal clearance — impaired kidneys ↑ drug levels; hypoK/Mg sensitize myocardium"),
C("Digoxin trough level; K⁺, Mg²⁺, Cr before each dose change and at least q6 months"),
C("Hold if level >2.0, K⁺ <3.5, HR <60; Antidote: Digibind (Digoxin Immune Fab)")],
[C("Statins\n(atorvastatin,\nrosuvastatin,\nsimvastatin)", bold_ps),
C("CK (CPK)\nLFTs (AST/ALT)\nGlucose/HbA1c"),
C("↑ CK → myopathy\n↑ AST/ALT\n↑ Glucose"),
C("Inhibit HMG-CoA → ↓ cholesterol; also ↓ CoQ10 → muscle dysfunction; mild hepatotoxic"),
C("LFTs at baseline; CK if muscle pain reported; HbA1c annually (↑ diabetes risk)"),
C("Hold if CK >10× ULN (rhabdomyolysis); stop if AST/ALT >3× ULN × 2 readings; drug holiday")],
[C("Amiodarone", bold_ps),
C("TFTs (TSH/T4)\nLFTs\nCreatinine\nINR (if on warfarin)"),
C("↑ or ↓ TSH/T4\n↑ LFTs\n↑ Cr\n↑ INR"),
C("Contains 37% iodine → thyroid dysfunction (hypo OR hyper); inhibits CYP2C9 → ↑ warfarin effect"),
C("TFTs every 6 months; LFTs and CXR annually; reduce warfarin dose 30–50% when starting"),
C("Notify provider for any TSH abnormality; reduce warfarin dose; monitor pulmonary function")],
]))
story.append(SP())
story.append(note_box(
"<b>KEY CARDIOVASCULAR PEARLS:</b> "
"ACEi/ARBs → always check K⁺ and Cr before and after starting. "
"Loop diuretics → hypokalemia worsens digoxin toxicity — treat both. "
"Amiodarone inhibits CYP2C9/3A4 — can double warfarin effect within days. "
"Statins → CK only needed if patient reports muscle pain (not routine).",
LBLUE, NAVY))
# ╔══════════════════════════════════════════════════════════════════════════╗
# 2. ANTICOAGULANTS & ANTIPLATELETS
# ╚══════════════════════════════════════════════════════════════════════════╝
story.append(SP())
story.append(sec_hdr("2. ANTICOAGULANTS & ANTIPLATELETS",
MAROON, "Warfarin • Heparin • DOACs • Aspirin • Clopidogrel"))
story.append(mktbl([
hrow(MAIN_COLS),
[C("Warfarin (Coumadin)", bold_ps),
C("INR\nPT"),
C("↑ INR, ↑ PT"),
C("Inhibits Vit K-dependent factors (II, VII, IX, X); many drug and food interactions via CYP2C9"),
C("INR at baseline, daily while loading, then weekly until stable, then monthly"),
C("INR >3.0: hold warfarin; >4.5: Vit K oral; >5.0 + bleeding: IV Vit K + FFP; Antidote: Vit K / FFP")],
[C("Heparin (UFH)", bold_ps),
C("aPTT\nPlatelet count"),
C("↑ aPTT\n↓ Platelets (HIT)"),
C("Activates antithrombin III; aPTT reflects anticoagulation; HIT = immune-mediated platelet destruction"),
C("aPTT every 6 hrs until therapeutic (45–80 sec), then daily; platelet count every 2–3 days for HIT"),
C("Antidote: Protamine sulfate. If platelets drop >50% → STOP heparin; suspect HIT; use argatroban/bivalirudin")],
[C("LMWH\n(enoxaparin,\ndalteparin)", bold_ps),
C("Anti-Xa level\nCreatinine\nPlatelet count"),
C("Anti-Xa 0.5–1.0\n(therapeutic)\n↑ Cr → drug accum."),
C("Predictable pharmacokinetics; no routine aPTT needed; renally cleared — accumulates in CKD"),
C("Anti-Xa level in renal impairment, obesity, or pregnancy; Cr before starting; platelets for HIT"),
C("Partial antidote: Protamine sulfate (reverses ~60%); dose-reduce or switch to UFH if eGFR <30")],
[C("DOACs\n(rivaroxaban,\napixaban,\ndabigatran)", bold_ps),
C("Creatinine/eGFR\nLFTs\n(PT/aPTT not\nreliable for DOACs)"),
C("↑ Cr → accumulation\n↑ LFTs (rare)"),
C("Renally cleared (dabigatran >rivaroxaban >apixaban); liver-metabolized; PT/aPTT NOT reliable monitors"),
C("Cr/eGFR at baseline and every 6–12 months; hold if eGFR <15; LFTs at baseline"),
C("Antidotes: Idarucizumab (dabigatran); Andexanet alfa (Factor Xa inhibitors); activated charcoal if recent ingestion")],
[C("Aspirin", bold_ps),
C("Bleeding time\nHgb / Hct\nUric Acid"),
C("↑ Bleeding time\n↓ Hgb (chronic)\n↑ Uric Acid (low dose)"),
C("Irreversibly inhibits COX-1 → platelet dysfunction for 7–10 days; GI bleeding risk; competes with uric acid excretion"),
C("Hgb/Hct annually (GI bleed risk); stool guaiac; renal function if high-dose use"),
C("Hold 7–10 days before elective surgery; monitor for GI bleeding signs; avoid in gout")],
[C("Clopidogrel\n(Plavix)", bold_ps),
C("CBC (Hgb, Plt)\nLFTs (rare TTP)"),
C("↓ Hgb (bleeding)\n↓ Plt (TTP — rare)"),
C("P2Y12 inhibitor; prodrug requiring CYP2C19 activation — poor metabolizers get less effect"),
C("Baseline CBC and LFTs; monitor for unusual bruising, petechiae, or neurological changes (TTP)"),
C("Hold 5 days before surgery; TTP = rare emergency — STOP drug + plasmapheresis")],
]))
story.append(SP())
story.append(note_box(
"<b>ANTICOAGULANT ANTIDOTES SUMMARY:</b> "
"Warfarin → Vitamin K (slow) / FFP (fast) | "
"UFH → Protamine sulfate | "
"LMWH → Protamine (partial) | "
"Dabigatran → Idarucizumab (Praxbind) | "
"Factor Xa inhibitors → Andexanet alfa | "
"HIT: STOP all heparin products immediately — switch to argatroban or bivalirudin.",
LRED, RED))
# ╔══════════════════════════════════════════════════════════════════════════╗
# 3. ANTIBIOTICS & ANTI-INFECTIVES
# ╚══════════════════════════════════════════════════════════════════════════╝
story.append(SP())
story.append(sec_hdr("3. ANTIBIOTICS & ANTI-INFECTIVES",
GREEN, "Vancomycin • Aminoglycosides • Fluoroquinolones • Antifungals • Antitubercular"))
story.append(mktbl([
hrow(MAIN_COLS),
[C("Vancomycin", bold_ps),
C("Vancomycin trough\nBUN / Creatinine"),
C("Toxic >20 µg/mL\n↑ BUN, Cr"),
C("Nephrotoxic (proximal tubule damage); ototoxic at high levels; narrow therapeutic index"),
C("Trough before 4th dose (target 10–20 µg/mL); BUN/Cr 2–3× per week; hold if Cr ↑ significantly"),
C("Reduce dose/extend interval in renal impairment; Audiology consult for prolonged therapy; AUC-guided dosing preferred")],
[C("Aminoglycosides\n(gentamicin,\ntobramycin,\namikacin)", bold_ps),
C("Drug trough level\nBUN / Creatinine\nAudiology"),
C("↑ Cr, ↑ BUN\nOtotoxicity"),
C("Proximal tubule damage; free radical injury to cochlear hair cells; accumulate in renal failure"),
C("Peak AND trough levels; BUN/Cr daily; urine output hourly in critically ill; baseline audiogram"),
C("Hold if Cr rising; extended-interval dosing (once daily) reduces nephrotoxicity; avoid loop diuretics combo")],
[C("Fluoroquinolones\n(ciprofloxacin,\nlevofloxacin)", bold_ps),
C("BUN / Creatinine\nBlood glucose\nQTc interval"),
C("↑ Cr (mild)\n↑ or ↓ Glucose\n↑ QTc"),
C("Rare nephrotoxicity; alter glucose metabolism (hypoglycemia in diabetics); prolong QT interval"),
C("Monitor blood glucose (especially in diabetics on sulfonylureas); ECG if QTc concern; Cr baseline"),
C("Avoid with other QT-prolonging drugs (amiodarone, antipsychotics); hold in hypoglycemia")],
[C("Azole Antifungals\n(fluconazole,\nvoriconazole)", bold_ps),
C("LFTs (AST/ALT)\nINR (if on warfarin)\nCreatinine"),
C("↑ LFTs\n↑ INR\n↑ Cr (voriconazole IV)"),
C("Hepatotoxic; strong CYP2C9 inhibitors → ↑ warfarin dramatically; IV voriconazole vehicle (SBECD) is nephrotoxic"),
C("LFTs weekly; INR frequently if on warfarin (reduce warfarin 50%); Cr for IV voriconazole"),
C("Switch IV voriconazole to oral if Cr ↑; adjust warfarin dose proactively; stop if LFTs >5× ULN")],
[C("Antitubercular Drugs\n(rifampin, isoniazid,\npyrazinamide)", bold_ps),
C("LFTs (AST/ALT)\nUric Acid\nINR, drug levels"),
C("↑ LFTs\n↑ Uric Acid (PZA)\n↓ INR (rifampin)"),
C("Isoniazid/pyrazinamide = hepatotoxic; rifampin = potent CYP inducer → ↓ warfarin, OCP, many drugs"),
C("LFTs monthly (or more if symptomatic); uric acid if gout history; warn about drug interactions"),
C("Hold if AST/ALT >5× ULN or symptoms; rifampin reduces efficacy of contraceptives — counsel patients")],
]))
# ╔══════════════════════════════════════════════════════════════════════════╗
# 4. DIABETES MEDICATIONS
# ╚══════════════════════════════════════════════════════════════════════════╝
story.append(SP())
story.append(sec_hdr("4. DIABETES MEDICATIONS",
PURPLE, "Metformin • Sulfonylureas • Insulin • GLP-1 Agonists • SGLT-2 Inhibitors"))
story.append(mktbl([
hrow(MAIN_COLS),
[C("Metformin", bold_ps),
C("Creatinine/eGFR\nB12 level\nLactic Acid"),
C("Monitor Cr\n↓ B12 (chronic)\n↑ Lactic acid (rare)"),
C("Not nephrotoxic but renally cleared; causes lactic acidosis if Cr ↑; impairs B12 absorption in ileum"),
C("Cr/eGFR before start and every 3–6 months; B12 annually if long-term use; HOLD before contrast dye"),
C("HOLD if eGFR <30; hold 48 hrs before and after contrast; resume only when Cr stable; supplement B12")],
[C("Sulfonylureas\n(glipizide, glyburide,\nglimepiride)", bold_ps),
C("Blood Glucose\nHbA1c\nCreatinine"),
C("↓ Glucose\n↓ HbA1c\n↑ Cr → drug accum."),
C("Stimulate insulin release regardless of glucose → hypoglycemia risk; renally cleared (glyburide worst)"),
C("Blood glucose frequently; HbA1c every 3 months until stable; renal function monitoring"),
C("Avoid glyburide in elderly/CKD → switch to glipizide; treat hypoglycemia with 15g fast-acting carbs")],
[C("Insulin\n(all types)", bold_ps),
C("Blood Glucose\nK⁺\nHbA1c"),
C("↓ Glucose\n↓ K⁺ (insulin drives\nK into cells)\n↓ HbA1c"),
C("Glucose uptake; used therapeutically to shift K⁺ intracellularly in hyperkalemia treatment"),
C("Blood glucose per protocol (AC/HS or q1–4h in ICU); K⁺ monitoring in DKA/hyperkalemia treatment"),
C("Hypoglycemia (<70): give D50W IV (unconscious) or 15g carbs (conscious); always give dextrose with insulin for hyperkalemia")],
[C("GLP-1 Agonists\n(semaglutide,\nliraglutide)", bold_ps),
C("Amylase/Lipase\nCreatinine\nHbA1c"),
C("↑ Amylase/Lipase\n↑ Cr (rarely)\n↓ HbA1c"),
C("GLP-1 receptor activation; associated with pancreatitis; slows GI motility; weight loss"),
C("Amylase/lipase if abdominal pain develops; Cr/eGFR baseline; HbA1c every 3 months"),
C("HOLD and evaluate if severe abdominal pain develops (pancreatitis); avoid in personal/family history of medullary thyroid cancer")],
[C("SGLT-2 Inhibitors\n(empagliflozin,\ndapagliflozin)", bold_ps),
C("Cr/eGFR\nHbA1c\nK⁺\nUrine glucose"),
C("↑ Cr (initial, transient)\n↓ HbA1c\n↑ K⁺ (mild)\n+ Urine glucose"),
C("Block glucose reabsorption in proximal tubule; osmotic diuresis → volume depletion; euglycemic DKA risk"),
C("Cr/eGFR at baseline and periodically; HbA1c; urine glucose will be positive (expected effect)"),
C("HOLD before surgery/fasting (euglycemic DKA risk); avoid if eGFR <20–30; monitor for UTI/genital yeast infections")],
]))
# ╔══════════════════════════════════════════════════════════════════════════╗
# 5. NEUROLOGICAL / PSYCHIATRIC DRUGS
# ╚══════════════════════════════════════════════════════════════════════════╝
story.append(SP())
story.append(sec_hdr("5. NEUROLOGICAL & PSYCHIATRIC DRUGS",
SLATE, "Anticonvulsants • Lithium • Antipsychotics • SSRIs • Opioids"))
story.append(mktbl([
hrow(MAIN_COLS),
[C("Phenytoin (Dilantin)", bold_ps),
C("Phenytoin level\nAlbumin\nCBC\nLFTs"),
C("Toxic >20 µg/mL\nFalse low if albumin↓\n↓ CBC (aplastic)\n↑ LFTs"),
C("Narrow TI; highly protein-bound (albumin) — low albumin → more free drug; induces CYP enzymes"),
C("Trough level (target 10–20); albumin (correct level if low); CBC and LFTs annually"),
C("Correct phenytoin for albumin: Corrected level = measured ÷ (0.2 × albumin + 0.1); hold if SAND signs appear")],
[C("Valproic Acid\n(Depakote)", bold_ps),
C("Valproate level\nLFTs\nNH₃ (Ammonia)\nPlatelet count"),
C("Toxic >100 µg/mL\n↑ LFTs\n↑ Ammonia\n↓ Platelets"),
C("Hepatotoxic (especially in children <2); elevates ammonia even without liver disease; inhibits platelet aggregation"),
C("Drug level (target 50–100 µg/mL); LFTs and ammonia at baseline and every 3–6 months; CBC for platelets"),
C("Stop if severe LFT elevation; encephalopathy despite normal LFTs → check ammonia; supplement carnitine")],
[C("Carbamazepine\n(Tegretol)", bold_ps),
C("Carbamazepine level\nCBC\nNa⁺\nLFTs"),
C("Toxic >12 µg/mL\n↓ WBC (aplastic anemia)\n↓ Na⁺ (SIADH effect)\n↑ LFTs"),
C("Autoinduces own metabolism; can cause SIADH-like hyponatremia; agranulocytosis/aplastic anemia risk"),
C("Drug level (target 4–12 µg/mL); CBC with diff at baseline and monthly × 3, then annually; Na⁺ and LFTs"),
C("Hold if WBC <3,000 or ANC <1,500; treat hyponatremia cautiously; Black Box: aplastic anemia risk")],
[C("Lithium", bold_ps),
C("Lithium level\nCreatinine/eGFR\nTSH / T4\nNa⁺"),
C("Toxic >1.5 mEq/L\n↑ Cr (nephrotoxic)\n↑ TSH (hypothyroid)\n↑ Li if Na↓"),
C("Narrow TI; renally cleared; competes with Na⁺ — low Na diet/dehydration/diuretics ↑ lithium toxicity; causes hypothyroidism"),
C("Lithium level every 5–7 days until stable, then every 3–6 months; Cr, TFTs, Na every 6 months"),
C("HOLD if Cr rises; maintain adequate Na/fluid intake; hold diuretics if possible; antidote: none — supportive + dialysis if severe")],
[C("Antipsychotics\n(haloperidol,\nolanzapine,\nquetiapine)", bold_ps),
C("Glucose / HbA1c\nLipids\nProlactin\nQTc (ECG)\nCBC (clozapine)"),
C("↑ Glucose\n↑ Lipids\n↑ Prolactin\n↑ QTc\n↓ WBC (clozapine)"),
C("Metabolic syndrome; dopamine block → ↑ prolactin; QT prolongation (especially haloperidol IV, ziprasidone)"),
C("Fasting glucose and lipids at baseline and annually; ECG for QTc; prolactin if symptoms; CBC weekly for clozapine"),
C("Clozapine: HOLD if ANC <1,500 — registered REMS program; use ECG to monitor QTc; counsel on metabolic syndrome")],
[C("SSRIs\n(fluoxetine,\nsertraline,\ncitalopram)", bold_ps),
C("Na⁺ (SIADH)\nINR (if on warfarin)\nPlatelet function"),
C("↓ Na⁺\n↑ INR\n↓ Platelet function"),
C("SIADH (especially in elderly); inhibit serotonin uptake in platelets → ↑ bleeding; inhibit CYP2C9 → ↑ warfarin"),
C("Na⁺ in elderly within 2 weeks of starting; INR if on warfarin; monitor for unusual bruising"),
C("Hyponatremia → fluid restrict; seizure precautions if severe; adjust warfarin dose; serotonin syndrome if combined with MAOIs")],
]))
# ╔══════════════════════════════════════════════════════════════════════════╗
# 6. IMMUNOSUPPRESSANTS & BIOLOGICS
# ╚══════════════════════════════════════════════════════════════════════════╝
story.append(SP())
story.append(sec_hdr("6. IMMUNOSUPPRESSANTS, CHEMOTHERAPY & BIOLOGICS",
TEAL, "Methotrexate • Cyclosporine • Corticosteroids • TNF Inhibitors"))
story.append(mktbl([
hrow(MAIN_COLS),
[C("Methotrexate", bold_ps),
C("CBC\nLFTs\nCreatinine\nAlbumin"),
C("↓ WBC, Plt, RBC\n↑ LFTs\n↑ Cr\n↓ Albumin"),
C("Folate antagonist → bone marrow suppression and mucositis; hepatotoxic; renally excreted"),
C("CBC, LFTs, Cr at baseline and every 1–3 months; hold 1 week before elective surgery"),
C("Leucovorin rescue for toxicity; hold if WBC <3,000 or Cr ↑; avoid NSAIDs (↑ methotrexate levels); supplement folic acid")],
[C("Cyclosporine /\nTacrolimus", bold_ps),
C("Drug level (trough)\nCreatinine/eGFR\nK⁺, Mg²⁺\nGlucose (tacrolimus)\nLFTs"),
C("Toxic levels vary\n↑ Cr\n↑ K⁺, ↓ Mg²⁺\n↑ Glucose\n↑ LFTs"),
C("Calcineurin inhibitors; nephrotoxic; tacrolimus causes new-onset DM post-transplant (NODAT)"),
C("Trough levels 2× per week initially, then monthly; Cr, K⁺, Mg²⁺ weekly; fasting glucose; LFTs monthly"),
C("Reduce dose if Cr ↑ >25% from baseline; replace Mg²⁺; adjust for drug interactions (CYP3A4 inducers/inhibitors)")],
[C("Corticosteroids\n(prednisone,\nmethylprednisolone,\ndexamethasone)", bold_ps),
C("Blood Glucose\nK⁺\nBone density\nCBC (WBC ↑)\nLFTs (NASH)"),
C("↑ Glucose\n↓ K⁺\n↓ Bone density\n↑ WBC (false)\n↑ LFTs (long-term)"),
C("Gluconeogenesis ↑; mineralocorticoid effect → Na retention, K⁺ loss; suppress bone formation; ↑ WBC by demargination"),
C("Blood glucose AC/HS; electrolytes; bone density (DEXA) if long-term; BP; infection surveillance"),
C("Sliding scale insulin for steroid-induced hyperglycemia; K⁺ replacement; calcium/Vit D supplementation; taper — never abrupt stop")],
[C("TNF Inhibitors\n(infliximab,\nadalimumab,\netanercept)", bold_ps),
C("CBC\nLFTs\nTB testing\n(QuantiFERON)\nANA"),
C("↓ WBC (rare)\n↑ LFTs (rare)\n+ TB reactivation\n↑ ANA (drug-induced lupus)"),
C("Immunosuppression → TB reactivation, opportunistic infections; rare hepatotoxicity; can unmask autoimmune conditions"),
C("CBC and LFTs at baseline and every 3–6 months; TB test before initiating; chest X-ray; monitor for infection signs"),
C("HOLD and evaluate for any active infection; STOP if active TB — treat TB before restarting biologic; monitor for lupus-like symptoms")],
]))
# ╔══════════════════════════════════════════════════════════════════════════╗
# 7. CRITICAL INTERACTIONS SUMMARY TABLE
# ╚══════════════════════════════════════════════════════════════════════════╝
story.append(SP())
story.append(sec_hdr("7. CRITICAL DRUG-LAB INTERACTIONS AT A GLANCE",
RED, "High-Alert Combinations Requiring Immediate Action"))
CRIT_CW = [1.55*inch, 1.55*inch, 1.50*inch, 2.90*inch]
story.append(mktbl([
hrow(["DRUG", "LAB VALUE", "CRITICAL THRESHOLD", "IMMEDIATE NURSING ACTION"]),
[C("Digoxin", bold_ps), C("Digoxin level"), C("> 2.0 ng/mL"), C("Hold drug; STAT ECG; check K⁺ and Mg²⁺; Antidote: Digibind")],
[C("Warfarin", bold_ps), C("INR"), C("> 3.0 (or >5.0)"), C("Hold warfarin; Vit K PO (>3.0) or IV + FFP (>5.0 + bleeding)")],
[C("Heparin UFH", bold_ps), C("aPTT"), C("> 80 seconds"), C("Hold infusion; assess for bleeding; reduce dose per protocol")],
[C("Heparin (all)", bold_ps),C("Platelets"), C("Drop >50% from baseline"), C("STOP all heparin; HIT panel; switch to argatroban or bivalirudin")],
[C("Lithium", bold_ps), C("Lithium level"), C("> 1.5 mEq/L"), C("Hold lithium; IV fluids; dialysis if >2.5; neuro monitoring")],
[C("Phenytoin", bold_ps), C("Phenytoin level"), C("> 20 µg/mL"), C("Hold dose; assess for SAND signs (nystagmus, ataxia); correct for albumin")],
[C("Vancomycin", bold_ps), C("Trough level"), C("> 20 µg/mL"), C("Hold dose; extend interval; check BUN/Cr; adjust per renal function")],
[C("Metformin", bold_ps), C("Creatinine/eGFR"), C("eGFR < 30 mL/min"),C("HOLD metformin; assess for lactic acidosis; do not restart until Cr stable")],
[C("ACEi / ARBs", bold_ps), C("K⁺"), C("> 5.5 mEq/L"), C("Hold drug; dietary K⁺ restriction; ECG; treat hyperkalemia")],
[C("Statins", bold_ps), C("CK (CPK)"), C("> 10× ULN"), C("STOP statin; aggressive IV hydration (rhabdomyolysis); monitor Cr and urine output")],
[C("Amiodarone", bold_ps), C("TSH"), C("< 0.1 or > 10"), C("Notify provider; endocrinology consult; treat thyroid dysfunction")],
[C("Clozapine", bold_ps), C("ANC (WBC)"), C("ANC < 1,500 /µL"), C("STOP clozapine immediately; do not rechallenge until ANC recovers")],
[C("Corticosteroids", bold_ps),C("Blood Glucose"), C("> 300 mg/dL"), C("Insulin per sliding scale; notify provider; monitor for DKA symptoms")],
[C("Loop Diuretics", bold_ps),C("K⁺"), C("< 3.0 mEq/L"), C("K⁺ replacement IV or oral; hold digoxin if also prescribed; ECG")],
], cw=CRIT_CW, extra=[("ROWBACKGROUNDS",(0,1),(-1,-1),[LRED, WHITE])]))
story.append(SP())
story.append(note_box(
"<b>UNIVERSAL MONITORING RULES:</b> "
"(1) Always check a drug level BEFORE giving the next dose (trough level = just before next dose). "
"(2) Narrow Therapeutic Index (NTI) drugs require more frequent monitoring: "
"Digoxin · Lithium · Phenytoin · Theophylline · Vancomycin · Warfarin · Cyclosporine/Tacrolimus. "
"(3) HOLD nephrotoxic drugs (aminoglycosides, NSAIDs, contrast dye, metformin) if Cr is rising. "
"(4) Any drug that inhibits CYP2C9 (amiodarone, azoles, SSRIs) will INCREASE warfarin effect — reduce warfarin dose proactively. "
"(5) CYP3A4 inducers (rifampin, carbamazepine, phenytoin) DECREASE levels of many drugs including warfarin, cyclosporine, and oral contraceptives.",
LGREEN, GREEN))
# ── Build ──────────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(OUTPUT, pagesize=letter,
topMargin=0.80*inch, bottomMargin=0.45*inch,
leftMargin=0.45*inch, rightMargin=0.45*inch)
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print(f"SUCCESS: {OUTPUT}")
cd /home/daytona/workspace/nclex-labs && python3 generate_drug_lab_guide.py 2>&1
ls -lh /home/daytona/workspace/nclex-labs/Drug_Lab_Interactions_Guide.pdf
Drug Lab Interactions Guide
PDF Document · PDF
Make a printable study schedule template for NCLEX prep
~/nclex-labs/generate_study_schedule.py
"""
NCLEX Prep Study Schedule Template — ReportLab PDF
8-week planner with daily study blocks, topic rotation, and progress tracking
"""
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors
from reportlab.lib.units import inch
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak
)
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.platypus import HRFlowable
OUTPUT = "/home/daytona/workspace/nclex-labs/NCLEX_Study_Schedule.pdf"
# ── Palette ──────────────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1B2A4A")
TEAL = colors.HexColor("#0B7A75")
RED = colors.HexColor("#B03A2E")
ORANGE = colors.HexColor("#D9622B")
GREEN = colors.HexColor("#1D6A39")
PURPLE = colors.HexColor("#5B2C6F")
GOLD = colors.HexColor("#9A7D0A")
BLUE = colors.HexColor("#1A5276")
SLATE = colors.HexColor("#2E4057")
ROSE = colors.HexColor("#922B21")
WHITE = colors.white
DGREY = colors.HexColor("#2C3E50")
MGREY = colors.HexColor("#BDC3C7")
LGREY = colors.HexColor("#F4F6F9")
XLGREY = colors.HexColor("#FAFAFA")
LTEAL = colors.HexColor("#E8F8F5")
LBLUE = colors.HexColor("#EBF5FB")
LGREEN = colors.HexColor("#EAFAF1")
LORANGE = colors.HexColor("#FEF5E7")
LPURPLE = colors.HexColor("#F5EEF8")
LRED = colors.HexColor("#FDEDEC")
LNAVY = colors.HexColor("#EAF0FB")
LGOLD = colors.HexColor("#FDFAE5")
PAGE_W, PAGE_H = letter
# ── Styles ────────────────────────────────────────────────────────────────────
def PS(name, **kw):
base = dict(fontName="Helvetica", fontSize=8, textColor=DGREY, leading=11)
base.update(kw)
return ParagraphStyle(name, **base)
def C(txt, **kw):
ps = PS("_", **kw)
return Paragraph(str(txt), ps)
def CB(txt, **kw):
kw.setdefault("fontName","Helvetica-Bold")
return C(txt, **kw)
def CW(txt, **kw):
kw["textColor"] = WHITE
kw.setdefault("fontName","Helvetica-Bold")
return C(txt, **kw)
def CC(txt, **kw):
kw["alignment"] = TA_CENTER
return C(txt, **kw)
def CCB(txt, **kw):
kw["alignment"] = TA_CENTER
kw.setdefault("fontName","Helvetica-Bold")
return C(txt, **kw)
BASE = [
("FONTNAME", (0,0),(-1,-1), "Helvetica"),
("FONTSIZE", (0,0),(-1,-1), 8),
("GRID", (0,0),(-1,-1), 0.4, MGREY),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 5),
("RIGHTPADDING", (0,0),(-1,-1), 5),
]
SP = lambda n=0.07: Spacer(1, n*inch)
FULL = 7.5*inch
def banner(title, subtitle, bg):
rows = [[CW(title, fontSize=10, alignment=TA_CENTER)]]
if subtitle:
rows.append([C(subtitle, fontSize=7.5, textColor=colors.HexColor("#D5D8DC"),
alignment=TA_CENTER, leading=10)])
t = Table(rows, colWidths=[FULL])
t.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), bg),
("TOPPADDING",(0,0),(-1,-1), 5),
("BOTTOMPADDING",(0,0),(-1,-1), 5),
]))
return t
# ── Page callback ─────────────────────────────────────────────────────────────
def on_page(canvas, doc):
canvas.setFillColor(NAVY)
canvas.rect(0, PAGE_H-54, PAGE_W, 54, fill=1, stroke=0)
canvas.setFillColor(TEAL)
canvas.rect(0, PAGE_H-58, PAGE_W, 4, fill=1, stroke=0)
canvas.setFont("Helvetica-Bold", 18)
canvas.setFillColor(WHITE)
canvas.drawCentredString(PAGE_W/2, PAGE_H-32,
"NCLEX PREP — 8-WEEK STUDY SCHEDULE TEMPLATE")
canvas.setFont("Helvetica", 9)
canvas.setFillColor(colors.HexColor("#A8D8EA"))
canvas.drawCentredString(PAGE_W/2, PAGE_H-48,
"Customize dates • Check off completed topics • Track your progress • Stay consistent!")
canvas.setFillColor(TEAL)
canvas.rect(0, 26, PAGE_W, 2, fill=1, stroke=0)
canvas.setFont("Helvetica", 7.5)
canvas.setFillColor(MGREY)
canvas.drawCentredString(PAGE_W/2, 14,
f"NCLEX Study Planner • Printable Template • Page {doc.page}")
# =============================================================================
story = []
story.append(SP(0.08))
# ── OVERVIEW / HOW TO USE ─────────────────────────────────────────────────────
story.append(banner("HOW TO USE THIS PLANNER", "", SLATE))
how_data = [
[CB("✏️ Fill in dates"), CB("📚 Follow the topic plan"), CB("✅ Check off daily"), CB("📊 Track weekly scores")],
[C("Write your exam date at the top\nof each week. Work backward to\nset weekly goals.",fontSize=7.5,leading=10),
C("Each week targets a core NCLEX\ncontent area. Rotate topics and\nreview weak areas on weekends.",fontSize=7.5,leading=10),
C("Check the box each day after\ncompleting your study session\nand practice questions.",fontSize=7.5,leading=10),
C("Log your practice test score\neach week. Aim to trend upward.\nTarget ≥ 60% before exam.",fontSize=7.5,leading=10)],
]
t = Table(how_data, colWidths=[FULL/4]*4)
t.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,0), NAVY),
("TEXTCOLOR",(0,0),(-1,0), WHITE),
("BACKGROUND",(0,1),(-1,1), LNAVY),
("GRID",(0,0),(-1,-1),0.5,MGREY),
("TOPPADDING",(0,0),(-1,-1),5),
("BOTTOMPADDING",(0,0),(-1,-1),5),
("LEFTPADDING",(0,0),(-1,-1),6),
("VALIGN",(0,0),(-1,-1),"TOP"),
("ALIGN",(0,0),(-1,0),"CENTER"),
]))
story.append(t)
story.append(SP(0.06))
# ── DAILY TIME BLOCKS ─────────────────────────────────────────────────────────
story.append(banner("RECOMMENDED DAILY STUDY STRUCTURE", "Adapt to your schedule — consistency matters more than hours", TEAL))
time_data = [
[CCB("TIME BLOCK", textColor=WHITE), CCB("ACTIVITY", textColor=WHITE),
CCB("DURATION", textColor=WHITE), CCB("TOOLS / RESOURCES", textColor=WHITE)],
[CC("Morning\n(6–8 AM)"), C("Content Review — Read / Watch lecture on today's topic"),
CC("45–60 min"), C("Textbook, ATI, Saunders, Uworld content")],
[CC("Mid-Morning\n(9–11 AM)"), C("Practice Questions — NCLEX-style Q bank (focused on today's topic)"),
CC("60–75 min"), C("UWorld, Kaplan, NCLEX Mastery app — 50–75 Qs")],
[CC("Afternoon\n(1–2 PM)"), C("Review WRONG answers — Read rationales; re-read content for missed Qs"),
CC("45–60 min"), C("Q bank review mode; highlight key concepts")],
[CC("Evening\n(7–8 PM)"), C("Flashcards / Lab values / Meds — Quick active recall review"),
CC("30–45 min"), C("This flashcard deck, Anki, or paper cards")],
[CC("Before Bed\n(Optional)"), C("Read summary notes only — NO new content; light review"),
CC("15–20 min"), C("Personal summary notes, mind maps")],
]
t2 = Table(time_data, colWidths=[1.0*inch, 3.0*inch, 0.85*inch, 2.65*inch])
t2.setStyle(TableStyle(BASE + [
("BACKGROUND",(0,0),(-1,0), TEAL),
("TEXTCOLOR",(0,0),(-1,0), WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LTEAL, WHITE]),
("ALIGN",(0,0),(0,-1),"CENTER"),
("ALIGN",(2,0),(2,-1),"CENTER"),
]))
story.append(t2)
story.append(SP(0.08))
# ── NCLEX CONTENT AREA BREAKDOWN ─────────────────────────────────────────────
story.append(banner("NCLEX-RN CONTENT DISTRIBUTION (Next Gen NCLEX)", "Know where the most points are", BLUE))
content_data = [
[CCB("CONTENT AREA",textColor=WHITE), CCB("% OF EXAM",textColor=WHITE),
CCB("KEY TOPICS",textColor=WHITE), CCB("PRIORITY",textColor=WHITE)],
[C("Safe & Effective Care\nManagement"), CC("26–38%"),
C("Delegation, prioritization, infection control, safety, legal/ethical, emergency response"),
CCB("⭐⭐⭐ HIGHEST", textColor=RED)],
[C("Health Promotion &\nMaintenance"), CC("6–12%"),
C("Developmental stages, immunizations, health screening, prenatal, newborn care"),
CCB("⭐⭐ MODERATE", textColor=ORANGE)],
[C("Psychosocial Integrity"), CC("6–12%"),
C("Mental health, therapeutic communication, crisis, abuse, coping, addiction"),
CCB("⭐⭐ MODERATE", textColor=ORANGE)],
[C("Physiological Integrity\n(Basic Care)"), CC("6–12%"),
C("Nutrition, mobility, rest, hygiene, assistive devices, elimination, comfort"),
CCB("⭐⭐ MODERATE", textColor=ORANGE)],
[C("Physiological Integrity\n(Pharmacological)"), CC("12–18%"),
C("Drug actions, adverse effects, therapeutic levels, antidotes, client education"),
CCB("⭐⭐⭐ HIGH", textColor=RED)],
[C("Physiological Integrity\n(Reduction of Risk)"), CC("9–15%"),
C("Lab values, diagnostic tests, pre/post-op care, potential complications"),
CCB("⭐⭐⭐ HIGH", textColor=RED)],
[C("Physiological Integrity\n(Physiological Adaptation)"), CC("11–17%"),
C("Acute/chronic illness, fluid balance, medical emergencies, pathophysiology"),
CCB("⭐⭐⭐ HIGH", textColor=RED)],
]
t3 = Table(content_data, colWidths=[1.7*inch, 0.85*inch, 3.55*inch, 1.40*inch])
t3.setStyle(TableStyle(BASE + [
("BACKGROUND",(0,0),(-1,0), BLUE),
("TEXTCOLOR",(0,0),(-1,0), WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LBLUE, WHITE]),
("ALIGN",(1,0),(1,-1),"CENTER"),
]))
story.append(t3)
# ── PAGE 2 — 8-WEEK SCHEDULE ─────────────────────────────────────────────────
story.append(PageBreak())
story.append(SP(0.08))
WEEK_COLORS = [NAVY, TEAL, BLUE, GREEN, PURPLE, ORANGE, RED, SLATE]
WEEK_LIGHT = [LNAVY, LTEAL, LBLUE, LGREEN, LPURPLE, LORANGE, LRED, LGREY]
WEEK_PLANS = [
("WEEK 1", "Foundation & Safety", "Safe Care Management • Infection Control • Delegation • Prioritization • Legal/Ethical",
[("Mon", "Delegation principles + NCLEX priority frameworks (ABC, Maslow, safety first)"),
("Tue", "Infection control: Standard precautions, transmission-based precautions, isolation"),
("Wed", "Legal & ethical: Informed consent, advance directives, HIPAA, scope of practice"),
("Thu", "Emergency response: Triage, disaster nursing, rapid response"),
("Fri", "Lab values review: CBC, BMP/CMP, ABGs (use lab flashcards)"),
("Sat", "Practice test: 75 questions (safety & management focus) + full review of rationales"),
("Sun", "Rest day OR weak area review — ONLY topics you missed this week")]),
("WEEK 2", "Cardiovascular & Respiratory", "Cardiac Disorders • Heart Failure • Dysrhythmias • Respiratory Disorders • ABGs",
[("Mon", "Cardiac: MI, angina, heart failure — S/S, labs (troponin, BNP), interventions"),
("Tue", "ECG basics: rhythm identification, ACLS medications, cardioversion vs. defibrillation"),
("Wed", "Respiratory: Pneumonia, asthma, COPD, TB, ARDS — priority interventions"),
("Thu", "ABG interpretation: ROME method, compensation, nursing actions for each imbalance"),
("Fri", "Drug-lab review: Digoxin, amiodarone, loop diuretics, anticoagulants (Weeks 1–2 drugs)"),
("Sat", "Practice test: 75 questions (cardio/resp focus) + review rationales"),
("Sun", "Weak area review OR rest")]),
("WEEK 3", "Neurological & Musculoskeletal", "Stroke • ICP • Spinal Cord • Seizures • Fractures • Orthopedic",
[("Mon", "Stroke: FAST, tPA criteria, post-stroke care, hemorrhagic vs ischemic"),
("Tue", "Increased ICP: S/S, Cushing's triad, positioning, mannitol, monitoring"),
("Wed", "Spinal cord injury: Level classifications, autonomic dysreflexia, bladder/bowel care"),
("Thu", "Seizures: Types, medications (phenytoin levels!), safety, status epilepticus"),
("Fri", "Musculoskeletal: Hip fracture, compartment syndrome, fat embolism, traction, casts"),
("Sat", "Practice test: 75 questions (neuro/MSK focus) + review rationales"),
("Sun", "Weak area review OR rest")]),
("WEEK 4", "Endocrine & GI", "Diabetes • Thyroid • Adrenal • GI Disorders • Liver Disease",
[("Mon", "Diabetes: DKA vs HHS (compare!), insulin types, hypoglycemia, sick-day rules, HbA1c"),
("Tue", "Thyroid: Hypo vs Hyper — S/S, meds (levothyroxine, PTU), thyroid storm, myxedema"),
("Wed", "Adrenal: Cushing's vs Addison's — compare labs, meds, crisis management"),
("Thu", "GI: Peptic ulcer, Crohn's vs UC, liver cirrhosis, hepatic encephalopathy, CMP review"),
("Fri", "Drug-lab: Metformin/sulfonylureas/insulin, antiepileptics, GI drugs, steroids"),
("Sat", "Practice test: 75 questions (endocrine/GI focus) + review rationales"),
("Sun", "Midpoint check: Review total % correct trend. Adjust weak areas for Weeks 5–8")]),
("WEEK 5", "Renal, Fluids & Electrolytes", "AKI • CKD • Dialysis • IV Fluids • Electrolyte Imbalances",
[("Mon", "AKI vs CKD: Causes, oliguric vs recovery phases, labs (BUN/Cr/K⁺/HCO₃)"),
("Tue", "Dialysis: Hemodialysis vs peritoneal — assessment, access care, complications"),
("Wed", "IV fluids: Isotonic/hypotonic/hypertonic solutions — when to use each, tonicity effects"),
("Thu", "Electrolytes: Hypo/Hypernatremia, Hypo/Hyperkalemia, Hypo/Hypercalcemia — all S/S"),
("Fri", "Drug-lab: ACEi/ARBs, diuretics, drug effects on electrolytes, correction formulas"),
("Sat", "Practice test: 75 questions (renal/fluids focus) + review rationales"),
("Sun", "Weak area review OR rest")]),
("WEEK 6", "Pharmacology & Med Administration", "Drug Safety • High-Alert Meds • Therapeutic Levels • Pain Management",
[("Mon", "Rights of medication administration + high-alert drugs: anticoagulants, insulin, digoxin"),
("Tue", "Anticoagulants full review: Warfarin INR, Heparin aPTT, DOACs, antidotes"),
("Wed", "Pain management: Opioids, PCA, non-opioid analgesics, equianalgesic dosing"),
("Thu", "Psychiatric meds: Lithium, antipsychotics (clozapine!), SSRIs, MAOIs — lab monitoring"),
("Fri", "Drug-lab interactions full review (entire Drug-Lab guide — all 7 sections)"),
("Sat", "Practice test: 75 questions (pharmacology focus) + review rationales"),
("Sun", "Weak area review OR rest")]),
("WEEK 7", "Maternal-Newborn & Pediatrics", "Prenatal Care • Labor & Delivery • Postpartum • Pediatric Milestones",
[("Mon", "Prenatal: Normal vs at-risk pregnancy, pre-eclampsia (Mg sulfate monitoring!), HELLP"),
("Tue", "Labor & delivery: Stages of labor, fetal monitoring, shoulder dystocia, emergency delivery"),
("Wed", "Postpartum: BUBBLE-HE assessment, PPH, mastitis, postpartum depression"),
("Thu", "Newborn: APGAR, normal vs abnormal findings, common conditions, immunizations"),
("Fri", "Pediatrics: Developmental milestones, common childhood illnesses, growth parameters"),
("Sat", "Practice test: 75 questions (OB/peds focus) + review rationales"),
("Sun", "Weak area review OR rest")]),
("WEEK 8", "Final Review & Exam Prep", "Comprehensive Review • Full-Length Practice Exams • Test Strategy",
[("Mon", "Full-length practice exam (150–265 Q) — simulate real NCLEX conditions"),
("Tue", "Thorough rationale review of full-length exam. Flag and re-study all missed topics"),
("Wed", "High-yield review: ABCs, Maslow, delegation rules, infection precautions, priority Qs"),
("Thu", "Lab values final review + Drug-lab interactions cheat sheet + flashcard run-through"),
("Fri", "Light content review only — no new material. Trust your preparation."),
("Sat", "Exam-day prep: Lay out supplies, confirm location/time, early bedtime. Light review only."),
("Sun", "EXAM DAY 🎓 — Arrive early, breathe, trust yourself. You've got this!")]),
]
DAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
for i, (week, theme, topics, days_plan) in enumerate(WEEK_PLANS):
wc = WEEK_COLORS[i]
wlc = WEEK_LIGHT[i]
# Week header
hdr_tbl = Table([
[CW(f"{week}: {theme}", fontSize=11, alignment=TA_CENTER),
CW("EXAM DATE: ___________________", fontSize=8.5, alignment=TA_RIGHT)]
], colWidths=[5.0*inch, 2.5*inch])
hdr_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), wc),
("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5),
("LEFTPADDING",(0,0),(-1,-1),8),("RIGHTPADDING",(0,0),(-1,-1),8),
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
story.append(hdr_tbl)
# Topics row
topic_tbl = Table([[C(f"📖 Focus: {topics}", fontSize=7.5, textColor=DGREY,
backColor=wlc, leading=10)]],
colWidths=[FULL])
topic_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),wlc),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3),
("LEFTPADDING",(0,0),(-1,-1),8),("RIGHTPADDING",(0,0),(-1,-1),8),
]))
story.append(topic_tbl)
# Daily plan grid
day_header = [
CC("✓", fontName="Helvetica-Bold", textColor=WHITE),
CC("DAY", fontName="Helvetica-Bold", textColor=WHITE),
CW("TODAY'S STUDY TOPIC", fontSize=8, alignment=TA_LEFT),
CC("Qs Done", fontName="Helvetica-Bold", textColor=WHITE, fontSize=7.5),
CC("% Correct", fontName="Helvetica-Bold", textColor=WHITE, fontSize=7.5),
CW("Notes / Weak Areas", fontSize=7.5, alignment=TA_LEFT),
]
day_rows = [day_header]
for j, (day, topic) in enumerate(days_plan):
bg = wlc if j % 2 == 0 else WHITE
day_rows.append([
C("☐", fontSize=11, alignment=TA_CENTER),
CB(day, alignment=TA_CENTER, textColor=wc),
C(topic, fontSize=7.5, leading=10),
C("", alignment=TA_CENTER),
C("", alignment=TA_CENTER),
C("", fontSize=7.5),
])
day_tbl = Table(day_rows, colWidths=[0.28*inch, 0.40*inch, 3.45*inch, 0.65*inch, 0.72*inch, 1.95*inch])
day_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,0), DGREY),
("TEXTCOLOR",(0,0),(-1,0), WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("FONTSIZE",(0,0),(-1,0),7.8),
("ALIGN",(0,0),(0,-1),"CENTER"),
("ALIGN",(1,0),(1,-1),"CENTER"),
("ALIGN",(3,0),(4,-1),"CENTER"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[wlc, WHITE]),
("GRID",(0,0),(-1,-1),0.4,MGREY),
("TOPPADDING",(0,0),(-1,-1),3),
("BOTTOMPADDING",(0,0),(-1,-1),3),
("LEFTPADDING",(0,0),(-1,-1),4),
("RIGHTPADDING",(0,0),(-1,-1),4),
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
story.append(day_tbl)
# Weekly reflection row
refl_tbl = Table([[
CB("Weekly Reflection:", textColor=wc, fontSize=7.5),
C("Practice Exam Score: _______ / 100 Weak areas this week: _________________________________", fontSize=7.5),
CB("✓ Week Complete", textColor=GREEN, fontSize=7.5, alignment=TA_RIGHT),
]], colWidths=[1.2*inch, 5.0*inch, 1.3*inch])
refl_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), LGREY),
("GRID",(0,0),(-1,-1),0.4,MGREY),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
("LEFTPADDING",(0,0),(-1,-1),6),
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
story.append(refl_tbl)
story.append(SP(0.10))
# ── PAGE 3 — PROGRESS TRACKER + QUICK TIPS ───────────────────────────────────
story.append(PageBreak())
story.append(SP(0.08))
# Progress tracker
story.append(banner("8-WEEK PROGRESS TRACKER", "Log your weekly practice scores — aim for an upward trend", GREEN))
prog_data = [
[CCB("WEEK",textColor=WHITE), CCB("DATES",textColor=WHITE),
CCB("TOPIC FOCUS",textColor=WHITE), CCB("Q's COMPLETED",textColor=WHITE),
CCB("% CORRECT",textColor=WHITE), CCB("WEAK AREAS",textColor=WHITE),
CCB("✓ DONE",textColor=WHITE)],
[CC("1"), C("___/___ to ___/___"), C("Safety & Management"), CC("______"), CC("______"), C("_______________________"), CC("☐")],
[CC("2"), C("___/___ to ___/___"), C("Cardio & Respiratory"), CC("______"), CC("______"), C("_______________________"), CC("☐")],
[CC("3"), C("___/___ to ___/___"), C("Neuro & MSK"), CC("______"), CC("______"), C("_______________________"), CC("☐")],
[CC("4"), C("___/___ to ___/___"), C("Endocrine & GI"), CC("______"), CC("______"), C("_______________________"), CC("☐")],
[CC("5"), C("___/___ to ___/___"), C("Renal & Fluids"), CC("______"), CC("______"), C("_______________________"), CC("☐")],
[CC("6"), C("___/___ to ___/___"), C("Pharmacology"), CC("______"), CC("______"), C("_______________________"), CC("☐")],
[CC("7"), C("___/___ to ___/___"), C("OB & Pediatrics"), CC("______"), CC("______"), C("_______________________"), CC("☐")],
[CC("8"), C("___/___ to ___/___"), C("Final Review"), CC("______"), CC("______"), C("_______________________"), CC("☐")],
[CCB("TOTAL",textColor=NAVY), C(""), C(""), CCB("____________",textColor=NAVY),
CCB("Avg: ________",textColor=NAVY), C("EXAM DATE: ______________"), CCB("🎓",textColor=GREEN, fontSize=14)],
]
prog_cw = [0.42*inch, 1.25*inch, 1.45*inch, 0.95*inch, 0.90*inch, 2.0*inch, 0.53*inch]
prog_tbl = Table(prog_data, colWidths=prog_cw)
prog_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,0), GREEN),
("TEXTCOLOR",(0,0),(-1,0), WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("BACKGROUND",(0,-1),(-1,-1), LGREEN),
("FONTNAME",(0,-1),(-1,-1),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-2),[LGREEN, WHITE]),
("GRID",(0,0),(-1,-1),0.5,MGREY),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
("LEFTPADDING",(0,0),(-1,-1),5),
("ALIGN",(0,0),(0,-1),"CENTER"),
("ALIGN",(3,0),(4,-1),"CENTER"),
("ALIGN",(6,0),(6,-1),"CENTER"),
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
story.append(prog_tbl)
story.append(SP(0.10))
# ── NCLEX STRATEGY TIPS ───────────────────────────────────────────────────────
story.append(banner("NCLEX QUESTION STRATEGY TIPS", "Apply these every time you answer a question", PURPLE))
tips_data = [
[CCB("PRIORITY FRAMEWORK",textColor=WHITE), CCB("DELEGATION RULES",textColor=WHITE),
CCB("WHEN IN DOUBT",textColor=WHITE), CCB("COMMON TRAPS",textColor=WHITE)],
[C("1. Is it a safety issue? → Act FIRST\n"
"2. ABC: Airway > Breathing > Circulation\n"
"3. Maslow: Physiological > Safety > Love\n"
"4. Acute before chronic\n"
"5. Unstable before stable\n"
"6. Assess before intervene", fontSize=7.5, leading=11),
C("RN delegates to:\n"
"• LPN: Stable patients, meds (except IV push)\n"
"• UAP: Basic care, VS on stable patients\n\n"
"RN CANNOT delegate:\n"
"• Assessment / Teaching\n"
"• IV meds / Blood products\n"
"• Unstable/new admission patients", fontSize=7.5, leading=11),
C("• Read ALL options before choosing\n"
"• Eliminate obviously wrong answers first\n"
"• 'Assess first' is usually right early in a question\n"
"• 'Notify provider' is usually NOT the best first action\n"
"• Choose the MOST COMPLETE safe answer\n"
"• SATA: treat each option as True/False", fontSize=7.5, leading=11),
C("• 'Always' and 'never' = usually wrong\n"
"• Reassure without addressing = wrong\n"
"• 'Tell the client not to worry' = wrong\n"
"• Normal findings after surgery = expected, don't act\n"
"• Highest priority ≠ most interesting finding\n"
"• First action ≠ most important intervention", fontSize=7.5, leading=11)],
]
tips_tbl = Table(tips_data, colWidths=[FULL/4]*4)
tips_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,0), PURPLE),
("TEXTCOLOR",(0,0),(-1,0), WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("BACKGROUND",(0,1),(-1,1), LPURPLE),
("GRID",(0,0),(-1,-1),0.5,MGREY),
("TOPPADDING",(0,0),(-1,-1),6),("BOTTOMPADDING",(0,0),(-1,-1),6),
("LEFTPADDING",(0,0),(-1,-1),6),
("VALIGN",(0,0),(-1,-1),"TOP"),
("ALIGN",(0,0),(-1,0),"CENTER"),
]))
story.append(tips_tbl)
story.append(SP(0.10))
# ── EXAM DAY CHECKLIST ────────────────────────────────────────────────────────
story.append(banner("EXAM DAY CHECKLIST", "", RED))
exam_data = [
[CCB("NIGHT BEFORE",textColor=WHITE), CCB("MORNING OF EXAM",textColor=WHITE),
CCB("AT THE TEST CENTER",textColor=WHITE), CCB("DURING THE EXAM",textColor=WHITE)],
[C("☐ Lay out all required ID documents\n"
"☐ Confirm test center address + parking\n"
"☐ Pack a healthy snack and water\n"
"☐ Set two alarms\n"
"☐ Review summary notes only (no new content)\n"
"☐ Sleep at least 7–8 hours\n"
"☐ Avoid cramming — trust your prep", fontSize=7.5, leading=11),
C("☐ Eat a protein-rich breakfast\n"
"☐ Arrive 30 minutes early\n"
"☐ Avoid discussing content with others\n"
"☐ Use bathroom before entering\n"
"☐ Take deep breaths — manage anxiety\n"
"☐ Bring valid photo ID (two forms)\n"
"☐ Leave phone/smartwatch in car/locker", fontSize=7.5, leading=11),
C("☐ Follow ALL check-in procedures\n"
"☐ Use provided scratch paper/whiteboard\n"
"☐ Read the tutorial carefully\n"
"☐ Use scheduled breaks (every 2 hours)\n"
"☐ Stretch + breathe during breaks\n"
"☐ Do not discuss questions with others\n"
"☐ Stay until you are sure — no rushing", fontSize=7.5, leading=11),
C("☐ Read each question COMPLETELY\n"
"☐ Apply NCLEX priority frameworks\n"
"☐ Eliminate 2 obviously wrong options\n"
"☐ For SATA: treat each choice T/F\n"
"☐ Don't second-guess first instinct\n"
"☐ Don't count questions — trust the CAT\n"
"☐ Breathe. You are READY. 🎓", fontSize=7.5, leading=11)],
]
exam_tbl = Table(exam_data, colWidths=[FULL/4]*4)
exam_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,0), RED),
("TEXTCOLOR",(0,0),(-1,0), WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("BACKGROUND",(0,1),(-1,1), LRED),
("GRID",(0,0),(-1,-1),0.5,MGREY),
("TOPPADDING",(0,0),(-1,-1),6),("BOTTOMPADDING",(0,0),(-1,-1),6),
("LEFTPADDING",(0,0),(-1,-1),6),
("VALIGN",(0,0),(-1,-1),"TOP"),
("ALIGN",(0,0),(-1,0),"CENTER"),
]))
story.append(exam_tbl)
story.append(SP(0.08))
# Final motivational note
motiv = Table([[Paragraph(
"<b>\"The secret of getting ahead is getting started.\"</b> "
"One focused hour every day beats one all-night cram session. "
"You have everything you need. <b>NOW GO PASS THAT NCLEX! 🎓</b>",
PS("m", fontSize=9, textColor=NAVY, alignment=TA_CENTER,
fontName="Helvetica-Bold", leading=13))]],
colWidths=[FULL])
motiv.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), LNAVY),
("BOX",(0,0),(-1,-1), 1.5, NAVY),
("TOPPADDING",(0,0),(-1,-1), 8),("BOTTOMPADDING",(0,0),(-1,-1), 8),
("LEFTPADDING",(0,0),(-1,-1),10),("RIGHTPADDING",(0,0),(-1,-1),10),
]))
story.append(motiv)
# ── Build ─────────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(OUTPUT, pagesize=letter,
topMargin=0.80*inch, bottomMargin=0.45*inch,
leftMargin=0.45*inch, rightMargin=0.45*inch)
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print(f"SUCCESS: {OUTPUT}")
cd /home/daytona/workspace/nclex-labs && python3 generate_study_schedule.py 2>&1
ls -lh /home/daytona/workspace/nclex-labs/NCLEX_Study_Schedule.pdf
NCLEX Study Schedule
PDF Document · PDF
| Week | Focus |
|---|---|
| 1 | Safety, Delegation, Infection Control, Legal/Ethics |
| 2 | Cardiovascular & Respiratory, ABGs |
| 3 | Neurological & Musculoskeletal |
| 4 | Endocrine & GI (midpoint check-in) |
| 5 | Renal, Fluids & Electrolytes |
| 6 | Pharmacology & Drug-Lab Interactions |
| 7 | Maternal-Newborn & Pediatrics |
| 8 | Final Review, Full-Length Practice, Exam Prep |
Create a comprehensive NCLEX question bank by topic (with detailed rationales)
Create a comprehensive NCLEX question bank by topic (with detailed rationales)
Create a comprehensive NCLEX question bank by topic (with detailed rationales)
Create a final checklist of the top 100 NCLEX concepts nurse must know before exam day
~/nclex-labs/generate_top100_checklist.py
"""
Top 100 NCLEX Concepts Checklist — ReportLab PDF
Organized by category with checkboxes, brief explanations, and exam tips
"""
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors
from reportlab.lib.units import inch
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak
)
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
OUTPUT = "/home/daytona/workspace/nclex-labs/NCLEX_Top100_Concepts_Checklist.pdf"
PAGE_W, PAGE_H = letter
# ── Palette ──────────────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1B2A4A")
TEAL = colors.HexColor("#0B7A75")
RED = colors.HexColor("#B03A2E")
ORANGE = colors.HexColor("#D9622B")
GREEN = colors.HexColor("#1D6A39")
PURPLE = colors.HexColor("#5B2C6F")
GOLD = colors.HexColor("#9A7D0A")
BLUE = colors.HexColor("#1A5276")
SLATE = colors.HexColor("#2E4057")
ROSE = colors.HexColor("#7B241C")
WHITE = colors.white
DGREY = colors.HexColor("#2C3E50")
MGREY = colors.HexColor("#BDC3C7")
LGREY = colors.HexColor("#F4F6F9")
LNAVY = colors.HexColor("#EAF0FB")
LTEAL = colors.HexColor("#E8F8F5")
LGREEN = colors.HexColor("#EAFAF1")
LRED = colors.HexColor("#FDEDEC")
LORANGE= colors.HexColor("#FEF5E7")
LPURPLE= colors.HexColor("#F5EEF8")
LBLUE = colors.HexColor("#EBF5FB")
LGOLD = colors.HexColor("#FDFAE5")
FULL = 7.5 * inch
def PS(name, **kw):
base = dict(fontName="Helvetica", fontSize=8, textColor=DGREY, leading=11)
base.update(kw)
return ParagraphStyle(name, **base)
def C(txt, **kw): return Paragraph(str(txt), PS("_", **kw))
def CB(txt, **kw): kw.setdefault("fontName","Helvetica-Bold"); return C(txt, **kw)
def CW(txt, **kw): kw["textColor"]=WHITE; kw.setdefault("fontName","Helvetica-Bold"); return C(txt, **kw)
def CC(txt, **kw): kw["alignment"]=TA_CENTER; return C(txt, **kw)
SP = lambda n=0.06: Spacer(1, n*inch)
# ── Page callback ─────────────────────────────────────────────────────────────
def on_page(canvas, doc):
canvas.setFillColor(NAVY)
canvas.rect(0, PAGE_H-54, PAGE_W, 54, fill=1, stroke=0)
canvas.setFillColor(TEAL)
canvas.rect(0, PAGE_H-58, PAGE_W, 4, fill=1, stroke=0)
canvas.setFont("Helvetica-Bold", 17)
canvas.setFillColor(WHITE)
canvas.drawCentredString(PAGE_W/2, PAGE_H-32,
"TOP 100 NCLEX CONCEPTS: Pre-Exam Checklist")
canvas.setFont("Helvetica", 9)
canvas.setFillColor(colors.HexColor("#A8D8EA"))
canvas.drawCentredString(PAGE_W/2, PAGE_H-48,
"Check off each concept as you master it • Review any unchecked items before exam day • You've got this! 🎓")
canvas.setFillColor(TEAL)
canvas.rect(0, 26, PAGE_W, 2, fill=1, stroke=0)
canvas.setFont("Helvetica", 7.5)
canvas.setFillColor(MGREY)
canvas.drawCentredString(PAGE_W/2, 14,
f"NCLEX Prep Series • For educational use only • Page {doc.page}")
# ── Section header helper ─────────────────────────────────────────────────────
def sec(num, title, subtitle, bg, light):
rows = [[CW(f" SECTION {num}: {title.upper()}", fontSize=10, alignment=TA_LEFT)]]
if subtitle:
rows.append([C(f" {subtitle}", fontSize=7.5,
textColor=colors.HexColor("#D5D8DC"), leading=10)])
t = Table(rows, colWidths=[FULL])
t.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),bg),
("TOPPADDING",(0,0),(-1,-1),5),
("BOTTOMPADDING",(0,0),(-1,-1),5),
]))
return t
# ── Checklist item builder ─────────────────────────────────────────────────────
def items(concepts, bg_light):
"""
concepts = list of (num, concept_title, one_line_explanation)
Returns a Table with two columns (left half, right half) for compact layout.
"""
rows = []
for n, title, explanation in concepts:
rows.append((n, title, explanation))
# Split into two columns
mid = (len(rows) + 1) // 2
left = rows[:mid]
right = rows[mid:]
# Pad right to same length
while len(right) < len(left):
right.append(None)
table_rows = []
for l, r in zip(left, right):
lc = _item_cell(l, bg_light) if l else Paragraph("", PS("e"))
rc = _item_cell(r, bg_light) if r else Paragraph("", PS("e"))
table_rows.append([lc, rc])
COL = (FULL - 0.15*inch) / 2
t = Table(table_rows, colWidths=[COL, COL], hAlign="LEFT")
t.setStyle(TableStyle([
("TOPPADDING", (0,0),(-1,-1), 1.5),
("BOTTOMPADDING", (0,0),(-1,-1), 1.5),
("LEFTPADDING", (0,0),(-1,-1), 0),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
return t
def _item_cell(item, bg):
if item is None:
return Paragraph("", PS("e"))
n, title, explanation = item
content = (
f'<font name="Helvetica-Bold" size="8" color="#2C3E50">☐ {n}. {title}</font><br/>'
f'<font name="Helvetica" size="7" color="#5D6D7E"> {explanation}</font>'
)
p = Paragraph(content, PS("ic", leading=12, backColor=bg))
box = Table([[p]], colWidths=[(FULL - 0.15*inch)/2 - 4])
box.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), bg),
("TOPPADDING",(0,0),(-1,-1), 3),
("BOTTOMPADDING",(0,0),(-1,-1), 3),
("LEFTPADDING",(0,0),(-1,-1), 3),
("RIGHTPADDING",(0,0),(-1,-1), 3),
("BOX",(0,0),(-1,-1), 0.3, MGREY),
]))
return box
# ═════════════════════════════════════════════════════════════════════════════
# QUESTION DATA
# ═════════════════════════════════════════════════════════════════════════════
S1 = [ # SAFETY & MANAGEMENT (1–14)
(1, "ABC Priority Framework",
"Airway > Breathing > Circulation — always address in this order unless cardiac arrest (then CAB)"),
(2, "Maslow's Hierarchy in NCLEX",
"Physiological needs first, then safety, then psychosocial. Physiological needs = priority over emotional needs"),
(3, "SATA Strategy",
"Treat each option independently as True or False. All correct options MUST be selected — partial credit = 0"),
(4, "Delegation to LPN",
"LPN can: give medications (not IV push), care for stable patients, perform wound care, insert urinary catheters"),
(5, "Delegation to UAP",
"UAP can: VS on stable patients, basic ADLs (bathing, feeding), I&O, transport. CANNOT assess or teach"),
(6, "What RN Cannot Delegate",
"Assessment, teaching, IV push medications, care of unstable/new admissions, blood transfusion initiation"),
(7, "Infection Control: Standard Precautions",
"Hand hygiene + gloves for ALL patients. Add mask/gown/goggles when splash risk. Applies to blood, body fluids, non-intact skin"),
(8, "Contact Precautions",
"Gloves + gown. Private room. MRSA, VRE, C. diff, wound infections, scabies, norovirus"),
(9, "Droplet Precautions",
"Surgical mask within 3 feet. Private room. Influenza, meningitis, pertussis, mumps, rubella, Group A strep pharyngitis"),
(10, "Airborne Precautions",
"N95 respirator, negative pressure room. TB, measles (rubeola), chickenpox (varicella), disseminated herpes zoster"),
(11, "Priority Question Strategy",
"'Most important first action' = ASSESSMENT before INTERVENTION unless patient safety is immediately threatened"),
(12, "Triage: Most Critical First",
"Unstable before stable. New symptom before chronic. Life-threatening before non-life-threatening"),
(13, "Informed Consent",
"Nurse witnesses signature only. Provider explains procedure, risks, benefits, alternatives. Patient must be competent and not coerced"),
(14, "Advance Directives / DNR",
"DNR = no CPR, no intubation. Still provide comfort care, pain meds, oxygen. Honor unless patient revokes"),
]
S2 = [ # CARDIOVASCULAR (15–24)
(15, "MI: Priority Nursing Actions",
"MONA: Morphine, Oxygen, Nitroglycerin, Aspirin. 12-lead ECG first. Aspirin 325 mg immediately. Notify provider STAT"),
(16, "Troponin Timing",
"Rises 3–6 hrs after MI, peaks 14–18 hrs, stays elevated 7–10 days. Most specific cardiac marker — any elevation is abnormal"),
(17, "Heart Failure: Left vs Right",
"Left HF → pulmonary edema (crackles, SOB, pink frothy sputum). Right HF → systemic edema (JVD, peripheral edema, ascites)"),
(18, "Digoxin Toxicity Signs",
"Bradycardia, nausea/vomiting, yellow-green halos. Hold if HR <60 or K⁺ <3.5. Antidote: Digibind"),
(19, "Hypertensive Emergency",
"BP >180/120 + end-organ damage. IV labetalol or nicardipine. Lower BP gradually (25% in first hour) — NOT rapidly"),
(20, "Warfarin (INR) Monitoring",
"Therapeutic INR: 2.0–3.0 (2.5–3.5 for mechanical heart valves). Hold if INR >3.0. Antidote: Vitamin K / FFP"),
(21, "Heparin (aPTT) Monitoring",
"Therapeutic aPTT: 45–80 sec (1.5–2× normal). Hold if >80 sec. Antidote: Protamine sulfate"),
(22, "Peripheral Artery Disease (PAD) vs DVT",
"PAD: pale, pulseless, pain, paresthesia, paralysis (6 Ps) — ARTERIAL. DVT: warm, red, swollen calf — VENOUS"),
(23, "Post-Cardiac Cath Care",
"Check insertion site every 15 min × 1 hr. Keep limb straight 4–6 hrs. Monitor distal pulses. Push fluids to flush contrast dye"),
(24, "BNP and Heart Failure",
"BNP >100 pg/mL = HF likely. >400 = strong indicator. Used to diagnose and monitor response to treatment"),
]
S3 = [ # RESPIRATORY (25–32)
(25, "ABG: ROME Method",
"Respiratory = Opposite (pH↓/PaCO₂↑). Metabolic = Equal (pH↓/HCO₃↓). Normal: pH 7.35–7.45, PaCO₂ 35–45, HCO₃ 22–26"),
(26, "COPD: Priority Concern",
"Low-flow oxygen (1–3 L/min via nasal cannula). High-flow O₂ removes hypoxic drive → respiratory arrest. Target SaO₂ 88–92%"),
(27, "Asthma: Peak Flow Zones",
"Green (80–100% personal best) = OK. Yellow (50–80%) = caution, increase meds. Red (<50%) = emergency, call 911"),
(28, "Chest Tube: Priority Checks",
"Water-seal chamber: tidaling (rises with inspiration) = normal. Continuous bubbling in water seal = air leak. Clamp only briefly"),
(29, "Pneumothorax vs Hemothorax",
"Pneumothorax: absent breath sounds, tracheal deviation AWAY from affected side (tension). Hemothorax: dullness to percussion"),
(30, "Pulmonary Embolism (PE) Signs",
"Sudden chest pain, SOB, tachycardia, hemoptysis. Risk factors: Virchow's triad (stasis, hypercoagulability, vessel damage)"),
(31, "TB: Precautions & Treatment",
"Airborne precautions (N95, negative pressure room). Treatment: RIPE — Rifampin, Isoniazid, Pyrazinamide, Ethambutol × 2 months; then RI × 4 months"),
(32, "Ventilator Alarm: High Pressure",
"First action: assess the patient. Common causes: coughing, biting tube, secretions, bronchospasm, pneumothorax"),
]
S4 = [ # FLUIDS, ELECTROLYTES & RENAL (33–44)
(33, "Hyponatremia (Na⁺ <135)",
"Signs: confusion, seizures, cerebral edema. Causes: SIADH, HF, cirrhosis, overhydration. Correct SLOWLY (max 8–10 mEq/L/24 hr)"),
(34, "Hypernatremia (Na⁺ >145)",
"Signs: thirst, dry mucosa, confusion, lethargy. Causes: DI, dehydration, excess Na intake. Treatment: hypotonic fluids slowly"),
(35, "Hypokalemia (K⁺ <3.5)",
"Signs: muscle weakness, leg cramps, dysrhythmias, U waves on ECG. Causes: diuretics, vomiting, NG suction. Hold digoxin if K⁺ <3.5"),
(36, "Hyperkalemia (K⁺ >5.0)",
"Signs: peaked T waves, wide QRS, bradycardia → V-fib. STAT ECG. Calcium gluconate (cardiac protection), insulin+dextrose (shift K in)"),
(37, "Hypocalcemia Signs",
"Chvostek's sign (tap cheek → facial twitch), Trousseau's sign (BP cuff → carpal spasm), tetany, seizures. Give IV calcium gluconate"),
(38, "Magnesium Toxicity (Eclampsia Drip)",
"Loss of DTRs (first sign), respiratory depression (fatal). Antidote: Calcium gluconate. Keep at bedside during Mg sulfate infusion"),
(39, "IV Fluid Selection",
"Isotonic (NS, LR): volume expansion. Hypotonic (½NS, D5W): cellular dehydration/hypernatremia. Hypertonic (3% NaCl): severe hyponatremia, cerebral edema"),
(40, "AKI vs CKD",
"AKI: sudden rise in Cr/BUN, oliguria, reversible. CKD: chronic Cr >1.2, GFR <60 × 3 months, irreversible. Both → ↑K⁺, ↓HCO₃"),
(41, "Dialysis Indications (AEIOU)",
"A-Acidosis, E-Electrolytes (K⁺ >6.5), I-Intoxication, O-Volume Overload, U-Uremia. AV fistula = no BP/sticks on that arm"),
(42, "Anion Gap Formula",
"AG = Na − (Cl + HCO₃). Normal 8–12. High AG = MUDPILES: Methanol, Uremia, DKA, Propylene glycol, Isoniazid, Lactic acidosis, Ethylene glycol, Salicylates"),
(43, "Dehydration vs SIADH",
"Dehydration: ↑Na, ↑BUN, ↑specific gravity, ↓urine output. SIADH: ↓Na, ↓serum osmolality, ↑urine specific gravity (concentrated urine despite ↓serum Na)"),
(44, "Pre/Post-Renal Differentiation",
"BUN:Cr >20:1 = pre-renal (dehydration, HF, GI bleed). <10:1 = intrinsic renal (ATN). BUN:Cr 10–20:1 = normal or mixed"),
]
S5 = [ # ENDOCRINE (45–52)
(45, "DKA vs HHS — Key Differences",
"DKA: Type 1 DM, rapid onset, ketones, pH <7.3, glucose 250–600. HHS: Type 2 DM, insidious, NO ketones, pH normal, glucose >600"),
(46, "DKA Management Priority",
"1. IV normal saline (fluid first). 2. Insulin drip (AFTER fluids). 3. K⁺ replacement (check K⁺ before insulin — if <3.5, hold insulin)"),
(47, "Hypoglycemia Treatment (15-15 Rule)",
"If glucose <70 and conscious: 15g fast-acting carbs (4 oz juice, glucose tabs). Recheck in 15 min. If unconscious: D50W IV"),
(48, "Insulin Types & Peak Times",
"Lispro/Aspart (rapid): peak 1–2 hr. Regular (short): peak 2–4 hr. NPH (intermediate): peak 4–12 hr. Glargine/Detemir: NO peak (basal)"),
(49, "Hypothyroid vs Hyperthyroid",
"Hypo (↑TSH, ↓T4): cold, constipated, weight gain, bradycardia, myxedema. Hyper (↓TSH, ↑T4): hot, diarrhea, weight loss, tachycardia, exophthalmos"),
(50, "Cushing's Syndrome Signs",
"Moon face, buffalo hump, purple striae, central obesity, hyperglycemia, hypertension, hypokalemia, thin skin, immunosuppression"),
(51, "Addison's Disease Crisis",
"Hypotension, ↓Na, ↑K, hypoglycemia, hyperpigmentation. Addisonian crisis = shock. Treatment: hydrocortisone IV + NS + dextrose"),
(52, "SIADH vs DI",
"SIADH: too much ADH → concentrated urine, dilute blood (↓Na, ↓osmolality). DI: no ADH → dilute urine (specific gravity <1.005), concentrated blood (↑Na)"),
]
S6 = [ # NEUROLOGICAL (53–60)
(53, "Stroke: FAST & tPA Criteria",
"FAST: Face drooping, Arm weakness, Speech difficulty, Time to call 911. tPA within 3–4.5 hrs of symptom onset. Contraindication: recent bleeding/surgery"),
(54, "Increased ICP: Cushing's Triad",
"Hypertension + bradycardia + irregular respirations = late sign of herniation. HOB 30°, avoid neck flexion, NO Trendelenburg"),
(55, "Glasgow Coma Scale (GCS)",
"Eyes (1–4) + Verbal (1–5) + Motor (1–6) = 3–15. Score ≤8 = intubate. Best possible = 15. Score 13–15 = mild TBI"),
(56, "Seizure Nursing Priority",
"Do NOT restrain. Turn to side (aspiration prevention). Time the seizure. Protect from injury. O₂ and suction ready. Post-ictal: reorient"),
(57, "Spinal Cord Injury Levels",
"C1–C4: ventilator-dependent. C5–C6: some arm function. T1–T4: paraplegia. T5 and below: progressively better leg function"),
(58, "Autonomic Dysreflexia",
"SCI above T6. Sudden severe hypertension + pounding headache + flushing. CAUSE: bladder/bowel distension. Sit up + empty bladder FIRST"),
(59, "Meningitis Precautions",
"Bacterial meningitis: droplet precautions × 24 hrs of antibiotics. Kernig's sign (knee can't extend when hip flexed), Brudzinski's sign"),
(60, "Myasthenia Gravis vs GBS",
"MG: weakness worsens with activity, improves with rest. Ptosis. Anticholinesterase meds. GBS: ascending paralysis after infection, areflexia"),
]
S7 = [ # PHARMACOLOGY (61–72)
(61, "High-Alert Medications",
"Anticoagulants, insulin, opioids, concentrated electrolytes (KCl, hypertonic NaCl). Require double-check verification before administration"),
(62, "Opioid Side Effects & Antidote",
"Respiratory depression, constipation, urinary retention, sedation, miosis. Antidote: Naloxone (Narcan). Assess resp rate before giving"),
(63, "ACE Inhibitors: -pril Drugs",
"Lisinopril, enalapril, captopril. Monitor: K⁺ (↑), Cr (↑). Side effect: dry cough (switch to ARB). Teratogenic — avoid in pregnancy"),
(64, "Beta-Blockers: -olol Drugs",
"Metoprolol, atenolol, carvedilol. Hold if HR <50 or SBP <90. NEVER abruptly stop — rebound hypertension/MI. Mask hypoglycemia signs"),
(65, "Corticosteroid Side Effects",
"Hyperglycemia, ↓K⁺, Na/fluid retention, immunosuppression, osteoporosis, Cushing's features. NEVER stop abruptly — taper required"),
(66, "Metformin: When to Hold",
"Hold 48 hrs before and after contrast dye. Hold if eGFR <30. Risk of lactic acidosis (NOT nephrotoxic itself). Supplement B12 long-term"),
(67, "Lithium Toxicity",
"Therapeutic: 0.6–1.2 mEq/L. Toxic: >1.5. Signs: tremor, ataxia, confusion. Caused by: low Na diet, dehydration, NSAIDs, diuretics. Antidote: none — supportive"),
(68, "Phenytoin (Dilantin) Key Facts",
"Therapeutic: 10–20 µg/mL. Correct for albumin. Toxicity: SAND (Slurred speech, Ataxia, Nystagmus, Diplopia). IV: no faster than 50 mg/min"),
(69, "Aminoglycosides Toxicity",
"Nephrotoxic + ototoxic. Monitor peak and trough levels. Check BUN/Cr daily. Avoid loop diuretics concurrently. Baseline audiology"),
(70, "Statins: When to Hold",
"Hold if CK >10× ULN (rhabdomyolysis risk). Check LFTs at baseline. Monitor for unexplained muscle pain — myopathy warning sign"),
(71, "Antipsychotics: EPS Signs",
"Extrapyramidal: akathisia, dystonia, tardive dyskinesia, pseudo-parkinsonism. Treat with benztropine. Clozapine: weekly CBC for agranulocytosis"),
(72, "SSRIs + Serotonin Syndrome",
"Do NOT combine SSRIs with MAOIs (wait 14 days). Serotonin syndrome: hyperthermia, agitation, clonus, diaphoresis, diarrhea. Treatment: cyproheptadine"),
]
S8 = [ # MATERNAL-NEWBORN (73–80)
(73, "Pre-eclampsia vs Eclampsia",
"Pre-eclampsia: BP >140/90, proteinuria ≥300 mg/24hr, edema after 20 weeks. Eclampsia = seizures. Treatment: Mg sulfate + antihypertensives"),
(74, "HELLP Syndrome",
"Hemolysis, Elevated Liver enzymes, Low Platelets. Emergency — may need immediate delivery. Severe epigastric pain is a red flag"),
(75, "Placenta Previa vs Abruption",
"Previa: painless bright red bleeding (low-lying placenta). Abruption: painful dark bleeding + rigid board-like abdomen + fetal distress"),
(76, "Fetal Heart Rate Decelerations",
"Early decels: head compression (normal). Variable: cord compression. Late decels: uteroplacental insufficiency (EMERGENCY — turn, O₂, call provider)"),
(77, "Postpartum Hemorrhage (PPH)",
"Blood loss >500 mL (vaginal) or >1,000 mL (C-section). Boggy uterus = #1 cause. Fundal massage + oxytocin first. Check for lacerations"),
(78, "Newborn APGAR Score",
"Appearance, Pulse, Grimace, Activity, Respiration. 0–3: immediate resuscitation. 4–6: stimulate. 7–10: normal. Assessed at 1 and 5 minutes"),
(79, "Magnesium Sulfate Monitoring",
"For pre-eclampsia/eclampsia. Monitor: DTRs (loss = first toxicity sign), resp rate (hold if <12), urine output (hold if <25–30 mL/hr). Antidote: calcium gluconate"),
(80, "Postpartum BUBBLE-HE",
"Breasts, Uterus (firm, midline), Bladder (voiding), Bowel, Lochia (color/odor/amount), Episiotomy/incision, Homans sign, Emotions"),
]
S9 = [ # PEDIATRICS & MENTAL HEALTH (81–90)
(81, "Pediatric Vital Sign Norms",
"Newborn HR: 100–160. Toddler HR: 80–130. Infant RR: 30–60. Toddler RR: 20–30. BP increases with age. Weight doubles by 6 months, triples by 1 year"),
(82, "Epiglottitis vs Croup",
"Epiglottitis: sudden, NO cough, drooling, tripod position, muffled voice. MEDICAL EMERGENCY — do NOT use tongue blade. Croup: barking cough, inspiratory stridor, gradual"),
(83, "Febrile Seizure Management",
"Common in children 6 months–5 years. Protect from injury, time seizure, do NOT restrain. Antipyretics after. Reassure parents (usually benign)"),
(84, "Pyloric Stenosis",
"Projectile non-bilious vomiting in newborns 2–8 weeks. Olive-shaped mass in RUQ. Metabolic alkalosis (↑pH, ↓K, ↓Cl). Surgery: pyloromyotomy"),
(85, "Therapeutic Communication Rules",
"Open-ended questions. Reflect feelings. Avoid: false reassurance ('everything will be OK'), why questions, changing subject, giving advice"),
(86, "Suicide Risk Assessment",
"Ask directly about plan, means, intent, timeline. Remove means from environment. 1:1 supervision for high risk. Contract for safety"),
(87, "Schizophrenia: Positive vs Negative",
"Positive symptoms: hallucinations, delusions, disorganized speech (added behaviors). Negative: flat affect, alogia, avolition, anhedonia (absent behaviors)"),
(88, "Alcohol Withdrawal Timeline",
"6–24 hrs: anxiety, tremors, diaphoresis. 24–48 hrs: seizures. 48–72 hrs: delirium tremens (DTs) — hallucinations, hyperthermia, tachycardia. Treat with benzodiazepines"),
(89, "Antidepressants: SSRI vs MAOI",
"SSRIs: first-line (sertraline, fluoxetine). MAOIs: avoid tyramine foods (aged cheese, cured meats, beer). 14-day washout between SSRIs and MAOIs"),
(90, "Eating Disorders: Priority",
"Anorexia nervosa: lowest weight, medical instability, refeeding syndrome risk (↓K, ↓P, ↓Mg on refeeding). Monitor electrolytes during refeeding"),
]
S10 = [ # LAB VALUES & CLINICAL CALCULATIONS (91–100)
(91, "Critical K⁺ Values",
"Normal 3.5–5.0 mEq/L. Critical: <2.5 or >6.5. ECG changes: low K = U waves; high K = peaked T waves, wide QRS. STAT ECG for both"),
(92, "Critical Glucose Values",
"Normal fasting 70–100. Critical: <40 (D50W IV) or >500 (insulin + fluids). HbA1c <5.7% normal; ≥6.5% = DM diagnosis"),
(93, "Corrected Calcium Formula",
"Corrected Ca = Measured Ca + 0.8 × (4 − Albumin). Low albumin causes pseudohypocalcemia — always correct before treating"),
(94, "BUN:Creatinine Ratio",
">20:1 = pre-renal (dehydration, GI bleed). 10–20:1 = normal. <10:1 = intrinsic renal disease or low protein intake"),
(95, "IV Drip Rate Calculation",
"mL/hr = (Volume to infuse ÷ Time in hours). Drops/min = (Volume × Drop factor) ÷ (Time in minutes). Check pump settings with 2 nurses"),
(96, "Pediatric Weight-Based Dosing",
"Safe dose range: ordered dose must fall between minimum and maximum mg/kg. Calculate: child weight in kg × mg/kg = safe dose range"),
(97, "Urine Specific Gravity",
"Normal: 1.010–1.030. <1.010 = dilute (DI, overhydration, SIADH early). >1.030 = concentrated (dehydration, SIADH late, fever)"),
(98, "Therapeutic Drug Levels",
"Digoxin 0.5–2.0; Lithium 0.6–1.2; Phenytoin 10–20; Vancomycin trough 10–20; Theophylline 10–20; all in respective units"),
(99, "Blood Transfusion Reactions",
"Acute hemolytic (STOP immediately, NS only, urine output): fever, chills, back/flank pain, hypotension within minutes. Most dangerous reaction"),
(100,"Oxygen Delivery Devices",
"Nasal cannula 1–6 L/min (24–44% FiO₂). Simple mask 6–10 L/min (35–60%). Non-rebreather mask 10–15 L/min (~80–90%). Venturi mask = precise FiO₂"),
]
# ═════════════════════════════════════════════════════════════════════════════
# BUILD STORY
# ═════════════════════════════════════════════════════════════════════════════
story = []
story.append(SP(0.08))
# Intro box
intro = Table([[Paragraph(
"<b>HOW TO USE:</b> Work through each section and check off (☐ → ✓) every concept you can explain confidently. "
"Anything unchecked = review before exam day. "
"<b>Goal: 100% checked before sitting for NCLEX.</b> "
"Use this alongside your flashcards, cheat sheet, and study schedule for maximum results.",
PS("ib", fontSize=8, textColor=NAVY, leading=12, fontName="Helvetica"))
]], colWidths=[FULL])
intro.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), LNAVY),
("BOX",(0,0),(-1,-1),1.5,NAVY),
("TOPPADDING",(0,0),(-1,-1),7),("BOTTOMPADDING",(0,0),(-1,-1),7),
("LEFTPADDING",(0,0),(-1,-1),10),("RIGHTPADDING",(0,0),(-1,-1),10),
]))
story.append(intro)
story.append(SP(0.10))
SECTIONS = [
(1, "Safety, Delegation & Management", "Concepts 1–14 | Highest-yield NCLEX area (26–38% of exam)", NAVY, LNAVY, S1),
(2, "Cardiovascular Nursing", "Concepts 15–24 | MI, HF, dysrhythmias, anticoagulation", RED, LRED, S2),
(3, "Respiratory Nursing", "Concepts 25–32 | ABGs, COPD, PE, TB, chest tubes", TEAL, LTEAL, S3),
(4, "Fluids, Electrolytes & Renal", "Concepts 33–44 | Electrolyte imbalances, IV fluids, AKI/CKD", BLUE, LBLUE, S4),
(5, "Endocrine Nursing", "Concepts 45–52 | DKA, HHS, thyroid, adrenal, DI vs SIADH", PURPLE,LPURPLE,S5),
(6, "Neurological Nursing", "Concepts 53–60 | Stroke, ICP, seizures, spinal cord", SLATE, LGREY, S6),
(7, "Pharmacology", "Concepts 61–72 | High-alert drugs, toxicities, antidotes", GREEN, LGREEN, S7),
(8, "Maternal-Newborn Nursing", "Concepts 73–80 | Pre-eclampsia, fetal monitoring, postpartum", ROSE, LRED, S8),
(9, "Pediatrics & Mental Health", "Concepts 81–90 | Pediatric emergencies, therapeutic communication", ORANGE, LORANGE, S9),
(10,"Lab Values & Calculations", "Concepts 91–100 | Critical labs, formulas, drug levels", GOLD, LGOLD, S10),
]
for num, title, subtitle, bg, light, data in SECTIONS:
story.append(sec(num, title, subtitle, bg, light))
story.append(items(data, light))
story.append(SP(0.10))
# Final score tracker
story.append(SP(0.05))
score_data = [
[CC("SECTION", fontName="Helvetica-Bold", textColor=WHITE, fontSize=8),
CC("TOPIC", fontName="Helvetica-Bold", textColor=WHITE, fontSize=8),
CC("CONCEPTS", fontName="Helvetica-Bold", textColor=WHITE, fontSize=8),
CC("# CHECKED", fontName="Helvetica-Bold", textColor=WHITE, fontSize=8),
CC("% MASTERED", fontName="Helvetica-Bold", textColor=WHITE, fontSize=8),
CC("READY?", fontName="Helvetica-Bold", textColor=WHITE, fontSize=8)],
[CC("1"), C("Safety & Management"), CC("14"), CC("___ / 14"), CC("______"), CC("☐")],
[CC("2"), C("Cardiovascular"), CC("10"), CC("___ / 10"), CC("______"), CC("☐")],
[CC("3"), C("Respiratory"), CC("8"), CC("___ / 8"), CC("______"), CC("☐")],
[CC("4"), C("Fluids, Electrolytes & Renal"),CC("12"), CC("___ / 12"), CC("______"), CC("☐")],
[CC("5"), C("Endocrine"), CC("8"), CC("___ / 8"), CC("______"), CC("☐")],
[CC("6"), C("Neurological"), CC("8"), CC("___ / 8"), CC("______"), CC("☐")],
[CC("7"), C("Pharmacology"), CC("12"), CC("___ / 12"), CC("______"), CC("☐")],
[CC("8"), C("Maternal-Newborn"), CC("8"), CC("___ / 8"), CC("______"), CC("☐")],
[CC("9"), C("Pediatrics & Mental Health"), CC("10"), CC("___ / 10"), CC("______"), CC("☐")],
[CC("10"),C("Lab Values & Calculations"), CC("10"), CC("___ / 10"), CC("______"), CC("☐")],
[CB("TOTAL", textColor=NAVY, alignment=TA_CENTER), C("All Sections"),
CB("100", textColor=NAVY, alignment=TA_CENTER),
CB("___ / 100", textColor=NAVY, alignment=TA_CENTER),
CB("______%", textColor=NAVY, alignment=TA_CENTER),
CB("🎓 READY!", textColor=GREEN, alignment=TA_CENTER, fontSize=9)],
]
score_tbl = Table(score_data, colWidths=[0.6*inch, 2.4*inch, 0.75*inch, 0.95*inch, 0.95*inch, 0.8*inch])
score_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,0), DGREY),
("TEXTCOLOR",(0,0),(-1,0), WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("BACKGROUND",(0,-1),(-1,-1), LGREEN),
("FONTNAME",(0,-1),(-1,-1),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-2),[LGREY, WHITE]),
("GRID",(0,0),(-1,-1),0.4,MGREY),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
("LEFTPADDING",(0,0),(-1,-1),5),
("ALIGN",(0,0),(0,-1),"CENTER"),
("ALIGN",(2,0),(5,-1),"CENTER"),
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
story.append(sec(0, "MASTERY SELF-ASSESSMENT TRACKER", "Log how many concepts you have checked off per section", GREEN, LGREEN))
story.append(score_tbl)
story.append(SP(0.08))
final = Table([[Paragraph(
'<b>"Nursing is not for everyone. It takes a very strong, intelligent, and compassionate person to take on '
'the aches of others without breaking down themselves." — You are that person.</b> '
"You have studied hard. You have prepared. Now go pass that NCLEX! 🎓",
PS("fin", fontSize=9, textColor=NAVY, alignment=TA_CENTER,
fontName="Helvetica-Bold", leading=13))]], colWidths=[FULL])
final.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), LGOLD),
("BOX",(0,0),(-1,-1),1.5,GOLD),
("TOPPADDING",(0,0),(-1,-1),8),("BOTTOMPADDING",(0,0),(-1,-1),8),
("LEFTPADDING",(0,0),(-1,-1),10),("RIGHTPADDING",(0,0),(-1,-1),10),
]))
story.append(final)
# ── Build ─────────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(OUTPUT, pagesize=letter,
topMargin=0.80*inch, bottomMargin=0.45*inch,
leftMargin=0.45*inch, rightMargin=0.45*inch)
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print(f"SUCCESS: {OUTPUT}")
cd /home/daytona/workspace/nclex-labs && python3 generate_top100_checklist.py 2>…
ls -lh /home/daytona/workspace/nclex-labs/NCLEX_Top100_Concepts_Checklist.pdf
NCLEX Top100 Concepts Checklist
PDF Document · PDF
| # | Section | Concepts | Color |
|---|---|---|---|
| 1 | Safety, Delegation & Management | 1–14 | Navy |
| 2 | Cardiovascular Nursing | 15–24 | Red |
| 3 | Respiratory Nursing | 25–32 | Teal |
| 4 | Fluids, Electrolytes & Renal | 33–44 | Blue |
| 5 | Endocrine Nursing | 45–52 | Purple |
| 6 | Neurological Nursing | 53–60 | Slate |
| 7 | Pharmacology | 61–72 | Green |
| 8 | Maternal-Newborn Nursing | 73–80 | Rose |
| 9 | Pediatrics & Mental Health | 81–90 | Orange |
| 10 | Lab Values & Calculations | 91–100 | Gold |
Design a critical thinking worksheet for analyzing NCLEX test questions
~/nclex-labs/generate_critical_thinking_worksheet.py
"""
NCLEX Critical Thinking Worksheet — ReportLab PDF
Page 1: Step-by-step question analysis framework (fillable)
Page 2: Practice question walk-through template × 3 questions
Page 3: Common mistake tracker + personal strategy notes
"""
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors
from reportlab.lib.units import inch
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak
)
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
OUTPUT = "/home/daytona/workspace/nclex-labs/NCLEX_Critical_Thinking_Worksheet.pdf"
PAGE_W, PAGE_H = letter
# ── Palette ───────────────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1B2A4A")
TEAL = colors.HexColor("#0B7A75")
RED = colors.HexColor("#B03A2E")
ORANGE = colors.HexColor("#D9622B")
GREEN = colors.HexColor("#1D6A39")
PURPLE = colors.HexColor("#5B2C6F")
GOLD = colors.HexColor("#9A7D0A")
BLUE = colors.HexColor("#1A5276")
SLATE = colors.HexColor("#2E4057")
WHITE = colors.white
DGREY = colors.HexColor("#2C3E50")
MGREY = colors.HexColor("#BDC3C7")
LGREY = colors.HexColor("#F4F6F9")
XLGREY = colors.HexColor("#FAFAFA")
LNAVY = colors.HexColor("#EAF0FB")
LTEAL = colors.HexColor("#E8F8F5")
LGREEN = colors.HexColor("#EAFAF1")
LRED = colors.HexColor("#FDEDEC")
LPURPLE= colors.HexColor("#F5EEF8")
LBLUE = colors.HexColor("#EBF5FB")
LORANGE= colors.HexColor("#FEF5E7")
LGOLD = colors.HexColor("#FDFAE5")
FULL = 7.5 * inch
def PS(name, **kw):
base = dict(fontName="Helvetica", fontSize=8, textColor=DGREY, leading=11)
base.update(kw)
return ParagraphStyle(name, **base)
def C(t, **kw): return Paragraph(str(t), PS("_", **kw))
def CB(t, **kw): kw.setdefault("fontName","Helvetica-Bold"); return C(t, **kw)
def CW(t, **kw): kw["textColor"]=WHITE; kw.setdefault("fontName","Helvetica-Bold"); return C(t, **kw)
def CC(t, **kw): kw["alignment"]=TA_CENTER; return C(t, **kw)
def CCB(t,**kw): kw["alignment"]=TA_CENTER; kw.setdefault("fontName","Helvetica-Bold"); return C(t,**kw)
SP = lambda n=0.07: Spacer(1, n*inch)
FULL = 7.5*inch
# ── Line / blank field helper ─────────────────────────────────────────────────
def blank_line(label="", lines=1, width=FULL, bg=XLGREY):
content = label + "\n" * lines if label else "\n" * lines
t = Table([[C(content, fontSize=7.8, textColor=DGREY, leading=14)]],
colWidths=[width])
t.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), bg),
("BOX",(0,0),(-1,-1),0.5,MGREY),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
("LEFTPADDING",(0,0),(-1,-1),6),("RIGHTPADDING",(0,0),(-1,-1),6),
]))
return t
def lined_box(num_lines=3, width=FULL, bg=XLGREY):
"""Box with horizontal ruled lines for writing."""
line_h = 0.22 * inch
rows = [[""] for _ in range(num_lines)]
t = Table(rows, colWidths=[width], rowHeights=[line_h]*num_lines)
t.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), bg),
("BOX",(0,0),(-1,-1),0.8,MGREY),
("LINEBELOW",(0,0),(-1,-2),0.4,MGREY),
("TOPPADDING",(0,0),(-1,-1),0),
("BOTTOMPADDING",(0,0),(-1,-1),0),
("LEFTPADDING",(0,0),(-1,-1),5),
]))
return t
def section_banner(title, sub, bg, light=None):
rows = [[CW(title, fontSize=10, alignment=TA_CENTER)]]
if sub:
rows.append([C(sub, fontSize=7.5, textColor=colors.HexColor("#D5D8DC"),
alignment=TA_CENTER, leading=10)])
t = Table(rows, colWidths=[FULL])
t.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),bg),
("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5),
]))
return t
def step_header(step_num, title, color, light):
t = Table([[
CCB(f"STEP {step_num}", textColor=WHITE, fontSize=9),
CB(title, textColor=WHITE, fontSize=9)
]], colWidths=[0.70*inch, FULL-0.70*inch])
t.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), color),
("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5),
("LEFTPADDING",(0,0),(-1,-1),8),
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
return t
# ── Page callbacks ────────────────────────────────────────────────────────────
current_page_title = [""]
def on_page(canvas, doc):
canvas.setFillColor(NAVY)
canvas.rect(0, PAGE_H-54, PAGE_W, 54, fill=1, stroke=0)
canvas.setFillColor(TEAL)
canvas.rect(0, PAGE_H-58, PAGE_W, 4, fill=1, stroke=0)
canvas.setFont("Helvetica-Bold", 17)
canvas.setFillColor(WHITE)
canvas.drawCentredString(PAGE_W/2, PAGE_H-32,
"NCLEX CRITICAL THINKING WORKSHEET")
canvas.setFont("Helvetica", 9)
canvas.setFillColor(colors.HexColor("#A8D8EA"))
canvas.drawCentredString(PAGE_W/2, PAGE_H-48,
"Analyze every practice question systematically • Build reasoning skills • Eliminate wrong answers with confidence")
canvas.setFillColor(TEAL)
canvas.rect(0, 26, PAGE_W, 2, fill=1, stroke=0)
canvas.setFont("Helvetica", 7.5)
canvas.setFillColor(MGREY)
canvas.drawCentredString(PAGE_W/2, 14,
f"NCLEX Prep Series • Critical Thinking Framework • Page {doc.page}")
# =============================================================================
story = []
story.append(SP(0.08))
# ─────────────────────────────────────────────────────────────────────────────
# PAGE 1 — THE 7-STEP CRITICAL THINKING FRAMEWORK
# ─────────────────────────────────────────────────────────────────────────────
story.append(section_banner(
"THE 7-STEP NCLEX CRITICAL THINKING FRAMEWORK",
"Apply these steps to EVERY practice question. Slow down — the goal is to build a thinking habit, not guess faster.",
NAVY))
story.append(SP(0.08))
# Step 1
story.append(step_header(1, "READ THE QUESTION STEM — Identify What Is REALLY Being Asked", RED, LRED))
story.append(SP(0.04))
cues_data = [
[CB("Key Words to Underline:", textColor=RED),
C("first, priority, most important, best, immediate, initial, except, NOT, contraindicated, next")],
[CB("Question Type:", textColor=RED),
C("☐ Priority/First Action ☐ Assessment ☐ Intervention ☐ SATA ☐ Teaching/Education ☐ Safety ☐ Delegation")],
[CB("Setting/Scenario:", textColor=RED),
C("☐ Emergency/Acute ☐ Post-op ☐ Chronic/Outpatient ☐ Pediatric ☐ OB ☐ Mental Health ☐ Community")],
]
cues_tbl = Table(cues_data, colWidths=[1.6*inch, FULL-1.6*inch])
cues_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),LRED),("GRID",(0,0),(-1,-1),0.3,MGREY),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
("LEFTPADDING",(0,0),(-1,-1),6),("VALIGN",(0,0),(-1,-1),"TOP"),
]))
story.append(cues_tbl)
story.append(SP(0.06))
# Step 2
story.append(step_header(2, "IDENTIFY THE PATIENT — Who Are They and What's the Clinical Context?", ORANGE, LORANGE))
story.append(SP(0.04))
pt_data = [
[C("Age / developmental stage:"), lined_box(1, FULL*0.35, LORANGE),
C("Diagnosis / chief complaint:"), lined_box(1, FULL*0.35, LORANGE)],
]
pt_tbl = Table(pt_data, colWidths=[1.4*inch, FULL*0.35, 1.55*inch, FULL*0.35-0.3*inch])
pt_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),LORANGE),("TOPPADDING",(0,0),(-1,-1),4),
("BOTTOMPADDING",(0,0),(-1,-1),4),("LEFTPADDING",(0,0),(-1,-1),5),
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
story.append(pt_tbl)
story.append(SP(0.04))
vitals_row = Table([[
C("Relevant vitals / labs noted:"),
lined_box(1, FULL*0.55, LORANGE),
C("Medications noted:"),
lined_box(1, FULL*0.22, LORANGE),
]], colWidths=[1.6*inch, FULL*0.55, 1.0*inch, FULL*0.22-0.2*inch])
vitals_row.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),LORANGE),("TOPPADDING",(0,0),(-1,-1),3),
("BOTTOMPADDING",(0,0),(-1,-1),3),("LEFTPADDING",(0,0),(-1,-1),5),
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
story.append(vitals_row)
story.append(SP(0.06))
# Step 3
story.append(step_header(3, "APPLY YOUR PRIORITY FRAMEWORK Before Looking at Options", GOLD, LGOLD))
story.append(SP(0.04))
pf_data = [
[CCB("FRAMEWORK", textColor=WHITE, fontSize=8),
CCB("WHEN TO USE", textColor=WHITE, fontSize=8),
CCB("APPLIES HERE?", textColor=WHITE, fontSize=8),
CCB("WHAT IT TELLS YOU", textColor=WHITE, fontSize=8)],
[CB("ABC"), C("Any acute physiological problem"),
CC("☐ Yes ☐ No"), C("Airway > Breathing > Circulation. Address in this order first")],
[CB("Maslow"), C("Comparing physiological vs psychosocial needs"),
CC("☐ Yes ☐ No"), C("Physiological need wins unless all are physiological, then use ABC")],
[CB("Safety"), C("Risk of harm, fall, infection, medication error"),
CC("☐ Yes ☐ No"), C("Prevent harm before addressing comfort or education")],
[CB("Acute vs Chronic"), C("Multiple patients or multiple problems"),
CC("☐ Yes ☐ No"), C("Acute/new onset trumps chronic/expected finding")],
[CB("Unstable vs Stable"), C("Delegation or assignment questions"),
CC("☐ Yes ☐ No"), C("Unstable patient always stays with RN; stable can be delegated")],
]
pf_tbl = Table(pf_data, colWidths=[0.95*inch, 1.85*inch, 1.0*inch, 3.7*inch])
pf_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,0),DGREY),("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LGOLD,WHITE]),
("GRID",(0,0),(-1,-1),0.3,MGREY),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3),
("LEFTPADDING",(0,0),(-1,-1),5),("VALIGN",(0,0),(-1,-1),"MIDDLE"),
("ALIGN",(2,0),(2,-1),"CENTER"),
]))
story.append(pf_tbl)
story.append(SP(0.06))
# Step 4
story.append(step_header(4, "ELIMINATE — Cross Off Wrong Answers ONE at a Time", PURPLE, LPURPLE))
story.append(SP(0.04))
elim_data = [
[CCB("OPTION",textColor=WHITE), CCB("ELIMINATE IF…",textColor=WHITE), CCB("KEEP IF…",textColor=WHITE), CCB("MY REASONING",textColor=WHITE)],
[CB("A"), C("Contains 'always/never', reassures without action, requires MD order first"),
C("Directly addresses ABC/safety, is assessment-focused if no acute crisis"),
lined_box(1, 2.40*inch, LPURPLE)],
[CB("B"), C("Same as above"), C("Same as above"), lined_box(1, 2.40*inch, LPURPLE)],
[CB("C"), C("Same as above"), C("Same as above"), lined_box(1, 2.40*inch, LPURPLE)],
[CB("D"), C("Same as above"), C("Same as above"), lined_box(1, 2.40*inch, LPURPLE)],
]
elim_tbl = Table(elim_data, colWidths=[0.40*inch, 1.95*inch, 2.30*inch, 2.85*inch])
elim_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,0),PURPLE),("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LPURPLE,WHITE]),
("GRID",(0,0),(-1,-1),0.3,MGREY),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3),
("LEFTPADDING",(0,0),(-1,-1),5),("ALIGN",(0,0),(0,-1),"CENTER"),
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
story.append(elim_tbl)
story.append(SP(0.06))
# Step 5
story.append(step_header(5, "SELECT YOUR ANSWER — Apply the Final Decision Rules", TEAL, LTEAL))
story.append(SP(0.04))
rules_data = [
[CB("My selected answer:", textColor=TEAL),
lined_box(1, 1.2*inch, LTEAL),
CB("Confidence level:", textColor=TEAL),
C("☐ Sure ☐ 50/50 ☐ Guessing")],
]
rules_tbl = Table(rules_data, colWidths=[1.45*inch, 1.2*inch, 1.2*inch, 3.65*inch])
rules_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),LTEAL),("TOPPADDING",(0,0),(-1,-1),4),
("BOTTOMPADDING",(0,0),(-1,-1),4),("LEFTPADDING",(0,0),(-1,-1),6),
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
story.append(rules_tbl)
decision_rules = Table([[Paragraph(
"<b>Final Decision Rules:</b> "
"(1) If two answers both seem right, pick the one that is MORE complete or addresses a higher-level need. "
"(2) 'Assess/Evaluate' is usually correct EARLY in a clinical sequence — before intervening. "
"(3) 'Notify the provider' is rarely the best FIRST action — do something yourself first unless outside nursing scope. "
"(4) Eliminate options that delegate assessment, teaching, or IV push to non-RN staff. "
"(5) For SATA: each option is independent — select ALL that are true, even if it feels like too many.",
PS("dr", fontSize=7.8, textColor=BLUE, leading=11))]], colWidths=[FULL])
decision_rules.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),LBLUE),("BOX",(0,0),(-1,-1),0.8,BLUE),
("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5),
("LEFTPADDING",(0,0),(-1,-1),8),("RIGHTPADDING",(0,0),(-1,-1),8),
]))
story.append(SP(0.04))
story.append(decision_rules)
story.append(SP(0.06))
# Steps 6 & 7 side by side
story.append(step_header(6, "REVIEW THE RATIONALE — Right or Wrong, Learn From Every Question", GREEN, LGREEN))
story.append(SP(0.04))
review_data = [
[CB("Correct answer was:", textColor=GREEN),
lined_box(1, 0.5*inch, LGREEN),
CB("☐ I was correct ☐ I was wrong", textColor=GREEN),
CB("Why was the correct answer RIGHT?", textColor=GREEN)],
[C(""), C(""), C(""), lined_box(2, FULL*0.45, LGREEN)],
[CB("Why was my answer WRONG\n(if incorrect)?", textColor=GREEN),
lined_box(2, FULL*0.5, LGREEN), C(""),
CB("What concept do I need to review?", textColor=GREEN)],
[C(""), C(""), C(""), lined_box(1, FULL*0.45, LGREEN)],
]
rev_tbl = Table(review_data,
colWidths=[1.5*inch, FULL*0.5, 0.05*inch, FULL*0.45-0.05*inch])
rev_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),LGREEN),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3),
("LEFTPADDING",(0,0),(-1,-1),5),("VALIGN",(0,0),(-1,-1),"TOP"),
]))
story.append(rev_tbl)
story.append(SP(0.06))
story.append(step_header(7, "CLASSIFY YOUR MISTAKE — Track Patterns to Stop Repeating Errors", SLATE, LGREY))
story.append(SP(0.04))
mistake_types = [
("Content Gap", "I didn't know the information. Need to study this topic."),
("Misread Question", "I didn't read carefully. I missed a key word (NOT, EXCEPT, FIRST)."),
("Second-Guessed", "My first instinct was right but I changed my answer."),
("Wrong Framework", "I didn't apply ABC/Maslow correctly. Picked comfort over safety."),
("Option Confusion", "Two options looked similar. I picked the less complete one."),
("SATA Error", "I under-selected or over-selected. Need to treat each option independently."),
("Delegation Error", "I delegated something the RN cannot delegate (assessment, IV push, unstable pt)."),
("Normal vs Abnormal", "I didn't recognize the finding as normal or expected — acted when I shouldn't have."),
]
mk_data = [[CCB("MISTAKE TYPE",textColor=WHITE), CCB("DESCRIPTION",textColor=WHITE),
CCB("☐ THIS WAS MY ERROR",textColor=WHITE)]]
for t, d in mistake_types:
mk_data.append([CB(t), C(d), CC("☐")])
mk_tbl = Table(mk_data, colWidths=[1.45*inch, 4.80*inch, 1.25*inch])
mk_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,0),SLATE),("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LGREY,WHITE]),
("GRID",(0,0),(-1,-1),0.3,MGREY),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3),
("LEFTPADDING",(0,0),(-1,-1),5),("ALIGN",(2,0),(2,-1),"CENTER"),
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
story.append(mk_tbl)
# ─────────────────────────────────────────────────────────────────────────────
# PAGE 2 — PRACTICE QUESTION ANALYSIS TEMPLATE (3 questions)
# ─────────────────────────────────────────────────────────────────────────────
story.append(PageBreak())
story.append(SP(0.08))
story.append(section_banner(
"PRACTICE QUESTION ANALYSIS TEMPLATE",
"Use this page for each practice session. Photocopy as needed. Date your sessions to track progress.",
BLUE))
story.append(SP(0.08))
def q_block(q_num, accent, light):
rows = []
hdr = Table([[
CCB(f"Q{q_num}", textColor=WHITE, fontSize=11),
CW(f"Question {q_num} Analysis", fontSize=9),
CW("Date: ________________", fontSize=8, alignment=TA_LEFT),
]], colWidths=[0.40*inch, 5.5*inch, 1.6*inch])
hdr.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),accent),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
("LEFTPADDING",(0,0),(-1,-1),6),("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
rows.append(hdr)
# Write question area
q_box = Table([[C("Write the question stem here (or paste question number/first line):", fontSize=7.5, textColor=DGREY)]],
colWidths=[FULL])
q_box.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),light),("LEFTPADDING",(0,0),(-1,-1),6),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),2)]))
rows.append(q_box)
rows.append(lined_box(2, FULL, light))
# Answer options
opts = Table([
[CB("A:", textColor=accent), lined_box(1, FULL*0.38, light),
CB("B:", textColor=accent), lined_box(1, FULL*0.38, light)],
[CB("C:", textColor=accent), lined_box(1, FULL*0.38, light),
CB("D:", textColor=accent), lined_box(1, FULL*0.38, light)],
], colWidths=[0.22*inch, FULL*0.38, 0.22*inch, FULL*0.38+0.05*inch])
opts.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),light),("TOPPADDING",(0,0),(-1,-1),2),
("BOTTOMPADDING",(0,0),(-1,-1),2),("LEFTPADDING",(0,0),(-1,-1),4),
("VALIGN",(0,0),(-1,-1),"MIDDLE")]))
rows.append(opts)
# Analysis row
analysis = Table([[
Table([
[CB("Key word(s) I underlined:", textColor=accent)],
[lined_box(1, FULL*0.28-0.1*inch, light)],
[CB("Question type:", textColor=accent)],
[C("☐ Priority ☐ Assessment ☐ Intervention\n☐ Delegation ☐ SATA ☐ Teaching",
fontSize=7.3, leading=11)],
], colWidths=[FULL*0.28-0.1*inch]),
Table([
[CB("Framework I used:", textColor=accent)],
[C("☐ ABC ☐ Maslow ☐ Safety ☐ Acute vs Chronic", fontSize=7.3)],
[CB("My answer:"), lined_box(1, FULL*0.28-0.1*inch, light)],
[CB("Correct answer:"), lined_box(1, FULL*0.28-0.1*inch, light)],
], colWidths=[FULL*0.28-0.1*inch]),
Table([
[CB("Result:", textColor=accent)],
[C("☐ Correct ☐ Wrong ☐ 50/50 guess", fontSize=7.3)],
[CB("Mistake type:", textColor=accent)],
[C("☐ Content gap\n☐ Misread question\n☐ Second-guessed\n☐ Wrong framework\n☐ SATA error\n☐ Normal vs abnormal",
fontSize=7.3, leading=10)],
], colWidths=[FULL*0.28-0.1*inch]),
]], colWidths=[FULL*0.28, FULL*0.28, FULL*0.28])
analysis.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),light),
("GRID",(0,0),(-1,-1),0.3,MGREY),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3),
("LEFTPADDING",(0,0),(-1,-1),5),("VALIGN",(0,0),(-1,-1),"TOP"),
]))
rows.append(analysis)
# Rationale
rat_hdr = Table([[CB("What the rationale taught me / concept to review:", textColor=accent, fontSize=7.8)]],
colWidths=[FULL])
rat_hdr.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),light),
("LEFTPADDING",(0,0),(-1,-1),6),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),2)]))
rows.append(rat_hdr)
rows.append(lined_box(2, FULL, light))
outer = Table([[item] for item in rows], colWidths=[FULL])
outer.setStyle(TableStyle([
("TOPPADDING",(0,0),(-1,-1),0),("BOTTOMPADDING",(0,0),(-1,-1),1),
("LEFTPADDING",(0,0),(-1,-1),0),("RIGHTPADDING",(0,0),(-1,-1),0),
("BOX",(0,0),(-1,-1),1.2,accent),
]))
return outer
story.append(q_block(1, NAVY, LNAVY))
story.append(SP(0.10))
story.append(q_block(2, RED, LRED))
story.append(SP(0.10))
story.append(q_block(3, GREEN, LGREEN))
# ─────────────────────────────────────────────────────────────────────────────
# PAGE 3 — ERROR TRACKER + STRATEGY NOTES
# ─────────────────────────────────────────────────────────────────────────────
story.append(PageBreak())
story.append(SP(0.08))
story.append(section_banner(
"SESSION ERROR TRACKER & PERSONAL STRATEGY NOTES",
"Complete after every practice session. Patterns = your roadmap to improvement.",
PURPLE))
story.append(SP(0.08))
# Session log table
story.append(CB("📊 SESSION PERFORMANCE LOG", textColor=PURPLE, fontSize=9))
story.append(SP(0.04))
log_data = [
[CCB("DATE",textColor=WHITE), CCB("# QUESTIONS",textColor=WHITE), CCB("# CORRECT",textColor=WHITE),
CCB("% SCORE",textColor=WHITE), CCB("TOPIC FOCUS",textColor=WHITE), CCB("TOP MISTAKE TYPE",textColor=WHITE),
CCB("TOPICS TO REVIEW",textColor=WHITE)],
]
for _ in range(10):
log_data.append(["","","","","","",""])
log_tbl = Table(log_data,
colWidths=[0.72*inch,0.82*inch,0.82*inch,0.72*inch,1.10*inch,1.20*inch,2.08*inch])
log_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,0),PURPLE),("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LPURPLE,WHITE]),
("GRID",(0,0),(-1,-1),0.4,MGREY),
("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5),
("ALIGN",(0,0),(3,-1),"CENTER"),
("FONTSIZE",(0,1),(-1,-1),8),
]))
story.append(log_tbl)
story.append(SP(0.10))
# Error pattern tracker
story.append(CB("🔍 CUMULATIVE ERROR PATTERN TRACKER", textColor=RED, fontSize=9))
story.append(SP(0.04))
error_data = [
[CCB("MISTAKE TYPE",textColor=WHITE), CCB("TALLY (add mark each time)",textColor=WHITE),
CCB("TOTAL",textColor=WHITE), CCB("MY CORRECTIVE STRATEGY",textColor=WHITE)],
[CB("Content Gap"), lined_box(1, 2.80*inch, LRED), CC(""),
C("Flag topics → add to study schedule weak areas section")],
[CB("Misread Question"), lined_box(1, 2.80*inch, LRED), CC(""),
C("Underline key words BEFORE reading options. Circle NOT/EXCEPT")],
[CB("Second-Guessed"), lined_box(1, 2.80*inch, LRED), CC(""),
C("Write first instinct. Only change with CLEAR reason, not anxiety")],
[CB("Wrong Framework"), lined_box(1, 2.80*inch, LRED), CC(""),
C("Ask: Is there an ABC issue? If yes → that trumps everything")],
[CB("Option Confusion"), lined_box(1, 2.80*inch, LRED), CC(""),
C("Cover all options. Predict answer before reading choices")],
[CB("SATA Error"), lined_box(1, 2.80*inch, LRED), CC(""),
C("Each option = True/False. Select all TRUE ones, even if 4–5")],
[CB("Delegation Error"), lined_box(1, 2.80*inch, LRED), CC(""),
C("RN CANNOT delegate: assessment, teaching, IV push, unstable patients")],
[CB("Normal vs Abnormal"), lined_box(1, 2.80*inch, LRED), CC(""),
C("Review expected post-op/post-procedure findings before exam")],
]
err_tbl = Table(error_data, colWidths=[1.30*inch, 2.80*inch, 0.55*inch, 2.85*inch])
err_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,0),RED),("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LRED,WHITE]),
("GRID",(0,0),(-1,-1),0.4,MGREY),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3),
("LEFTPADDING",(0,0),(-1,-1),5),("ALIGN",(2,0),(2,-1),"CENTER"),
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
story.append(err_tbl)
story.append(SP(0.10))
# Personal strategy notes
story.append(CB("✏️ MY PERSONAL NCLEX STRATEGY NOTES", textColor=NAVY, fontSize=9))
story.append(SP(0.04))
strategy_prompts = [
("My biggest content weakness right now:", 2),
("The priority framework I keep forgetting to apply:", 1),
("Words or phrases I need to underline more carefully:", 1),
("Topics I've reviewed this week:", 2),
("My score trend (circle): Getting better / About the same / Needs work", 1),
("One thing I will do differently on my next practice session:", 2),
("My exam date:", 1),
]
for label, lines in strategy_prompts:
lbl_tbl = Table([[CB(label, textColor=NAVY, fontSize=7.8)]],
colWidths=[FULL])
lbl_tbl.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),LNAVY),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),2),
("LEFTPADDING",(0,0),(-1,-1),6),
]))
story.append(lbl_tbl)
story.append(lined_box(lines, FULL, WHITE))
story.append(SP(0.04))
# Motivational close
final_box = Table([[Paragraph(
"<b>\"The expert in anything was once a beginner.\"</b> "
"Every question you analyze carefully — right or wrong — makes you a sharper thinker. "
"Work the process. The score will follow. <b>You are going to pass this exam. 🎓</b>",
PS("fin", fontSize=9, textColor=NAVY, alignment=TA_CENTER,
fontName="Helvetica-Bold", leading=14))]], colWidths=[FULL])
final_box.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),LGOLD),("BOX",(0,0),(-1,-1),1.5,GOLD),
("TOPPADDING",(0,0),(-1,-1),8),("BOTTOMPADDING",(0,0),(-1,-1),8),
("LEFTPADDING",(0,0),(-1,-1),10),("RIGHTPADDING",(0,0),(-1,-1),10),
]))
story.append(final_box)
# ── Build ─────────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(OUTPUT, pagesize=letter,
topMargin=0.80*inch, bottomMargin=0.45*inch,
leftMargin=0.45*inch, rightMargin=0.45*inch)
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print(f"SUCCESS: {OUTPUT}")
cd /home/daytona/workspace/nclex-labs && python3 generate_critical_thinking_work…
~/nclex-labs/generate_critical_thinking_worksheet.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/nclex-labs/generate_critical_thinking_worksheet.py'
cd /home/daytona/workspace/nclex-labs && python3 generate_critical_thinking_work…
~/nclex-labs/generate_critical_thinking_worksheet.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/nclex-labs/generate_critical_thinking_worksheet.py'
cd /home/daytona/workspace/nclex-labs && python3 generate_critical_thinking_work…
~/nclex-labs/generate_critical_thinking_worksheet.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/nclex-labs/generate_critical_thinking_worksheet.py'
~/nclex-labs/generate_critical_thinking_worksheet.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/nclex-labs/generate_critical_thinking_worksheet.py'
cd /home/daytona/workspace/nclex-labs && python3 generate_critical_thinking_work…
Failed to execute session command:
We encountered an error while processing your request. Please try again or reach out to us for help.
Design a critical thinking worksheet for analyzing NCLEX test questions
~/nclex-labs/gen_worksheet.py
"""
NCLEX Critical Thinking Worksheet — ReportLab PDF
3 pages: Framework | Practice Templates | Error Tracker
"""
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors
from reportlab.lib.units import inch
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak, HRFlowable
)
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
OUTPUT = "/home/daytona/workspace/nclex-labs/NCLEX_Critical_Thinking_Worksheet.pdf"
PAGE_W, PAGE_H = letter
# ── Palette ──────────────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1B2A4A")
TEAL = colors.HexColor("#0B7A75")
RED = colors.HexColor("#B03A2E")
ORANGE = colors.HexColor("#D9622B")
GREEN = colors.HexColor("#1D6A39")
PURPLE = colors.HexColor("#5B2C6F")
GOLD = colors.HexColor("#9A7D0A")
BLUE = colors.HexColor("#1A5276")
SLATE = colors.HexColor("#2E4057")
WHITE = colors.white
DGREY = colors.HexColor("#2C3E50")
MGREY = colors.HexColor("#BDC3C7")
LGREY = colors.HexColor("#F4F6F9")
LNAVY = colors.HexColor("#EAF0FB")
LTEAL = colors.HexColor("#E8F8F5")
LGREEN = colors.HexColor("#EAFAF1")
LRED = colors.HexColor("#FDEDEC")
LPURPLE= colors.HexColor("#F5EEF8")
LBLUE = colors.HexColor("#EBF5FB")
LORANGE= colors.HexColor("#FEF5E7")
LGOLD = colors.HexColor("#FDFAE5")
XLGREY = colors.HexColor("#FAFAFA")
FULL = 7.5 * inch
# ── Style helpers ─────────────────────────────────────────────────────────────
def PS(name, **kw):
base = dict(fontName="Helvetica", fontSize=8, textColor=DGREY, leading=11)
base.update(kw)
return ParagraphStyle(name, **base)
def P(txt, **kw): return Paragraph(str(txt), PS("x", **kw))
def PB(txt, **kw): kw.setdefault("fontName","Helvetica-Bold"); return P(txt, **kw)
def PW(txt, **kw): kw["textColor"]=WHITE; kw.setdefault("fontName","Helvetica-Bold"); return P(txt,**kw)
def PC(txt, **kw): kw["alignment"]=TA_CENTER; return P(txt, **kw)
def PCB(txt,**kw): kw["alignment"]=TA_CENTER; kw.setdefault("fontName","Helvetica-Bold"); return P(txt,**kw)
SP = lambda n=0.06: Spacer(1, n*inch)
FULL = 7.5*inch
BASE = [
("FONTNAME", (0,0),(-1,-1),"Helvetica"),
("FONTSIZE", (0,0),(-1,-1),8),
("GRID", (0,0),(-1,-1),0.4,MGREY),
("VALIGN", (0,0),(-1,-1),"MIDDLE"),
("TOPPADDING", (0,0),(-1,-1),3),
("BOTTOMPADDING", (0,0),(-1,-1),3),
("LEFTPADDING", (0,0),(-1,-1),5),
("RIGHTPADDING", (0,0),(-1,-1),5),
]
def row_tbl(rows_data, col_widths, extra=None):
t = Table(rows_data, colWidths=col_widths)
style = list(BASE)
if extra: style += extra
t.setStyle(TableStyle(style))
return t
def banner(title, sub, bg):
rows = [[PW(title, fontSize=10, alignment=TA_CENTER)]]
if sub:
rows.append([P(sub, fontSize=7.5, textColor=colors.HexColor("#D5D8DC"),
alignment=TA_CENTER, leading=10)])
t = Table(rows, colWidths=[FULL])
t.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),bg),
("TOPPADDING",(0,0),(-1,-1),5),
("BOTTOMPADDING",(0,0),(-1,-1),5)]))
return t
def step_hdr(num, title, bg):
t = Table([[PCB(f"STEP {num}", textColor=WHITE, fontSize=9),
PW(title, fontSize=9)]],
colWidths=[0.72*inch, FULL-0.72*inch])
t.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),bg),
("TOPPADDING",(0,0),(-1,-1),4),
("BOTTOMPADDING",(0,0),(-1,-1),4),
("LEFTPADDING",(0,0),(-1,-1),6),
("VALIGN",(0,0),(-1,-1),"MIDDLE")]))
return t
def write_lines(n, width=FULL, bg=XLGREY):
"""n ruled lines for handwriting."""
H = 0.24*inch
data = [[P("", fontSize=1)] for _ in range(n)]
t = Table(data, colWidths=[width], rowHeights=[H]*n)
t.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),bg),
("BOX",(0,0),(-1,-1),0.6,MGREY),
("LINEBELOW",(0,0),(-1,-2),0.4,MGREY),
("TOPPADDING",(0,0),(-1,-1),0),
("BOTTOMPADDING",(0,0),(-1,-1),0),
("LEFTPADDING",(0,0),(-1,-1),5),
("RIGHTPADDING",(0,0),(-1,-1),5),
]))
return t
def info_box(txt, bg, border):
t = Table([[P(txt, fontSize=7.8, textColor=DGREY, leading=11)]],
colWidths=[FULL])
t.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),bg),
("BOX",(0,0),(-1,-1),1,border),
("TOPPADDING",(0,0),(-1,-1),5),
("BOTTOMPADDING",(0,0),(-1,-1),5),
("LEFTPADDING",(0,0),(-1,-1),8),
("RIGHTPADDING",(0,0),(-1,-1),8)]))
return t
# ── Page callback ─────────────────────────────────────────────────────────────
def on_page(canvas, doc):
canvas.setFillColor(NAVY)
canvas.rect(0, PAGE_H-54, PAGE_W, 54, fill=1, stroke=0)
canvas.setFillColor(TEAL)
canvas.rect(0, PAGE_H-58, PAGE_W, 4, fill=1, stroke=0)
canvas.setFont("Helvetica-Bold", 17)
canvas.setFillColor(WHITE)
canvas.drawCentredString(PAGE_W/2, PAGE_H-32,
"NCLEX CRITICAL THINKING WORKSHEET")
canvas.setFont("Helvetica", 9)
canvas.setFillColor(colors.HexColor("#A8D8EA"))
canvas.drawCentredString(PAGE_W/2, PAGE_H-48,
"Analyze every practice question systematically • Build reasoning skills • Eliminate wrong answers with confidence")
canvas.setFillColor(TEAL)
canvas.rect(0, 26, PAGE_W, 2, fill=1, stroke=0)
canvas.setFont("Helvetica", 7.5)
canvas.setFillColor(MGREY)
canvas.drawCentredString(PAGE_W/2, 14,
f"NCLEX Prep Series • Critical Thinking Framework • Page {doc.page}")
# =============================================================================
# PAGE 1 — THE 7-STEP FRAMEWORK
# =============================================================================
story = []
story.append(SP(0.08))
story.append(info_box(
"<b>HOW TO USE:</b> Work through all 7 steps for EVERY practice question you get wrong — "
"and even for ones you got right by guessing. "
"The goal is to build a <b>thinking habit</b>, not just memorize answers. "
"Photocopy pages 2–3 for each practice session.",
LNAVY, NAVY))
story.append(SP(0.08))
# ── STEP 1 ────────────────────────────────────────────────────────────────────
story.append(step_hdr(1, "READ THE STEM — Identify What Is REALLY Being Asked", RED))
story.append(SP(0.03))
story.append(row_tbl([
[PB("Underline / Circle:", textColor=RED),
P("first • priority • most important • best • immediate • initial • EXCEPT • NOT • contraindicated • next")],
[PB("Question Type:", textColor=RED),
P("☐ Priority / First Action ☐ Assessment ☐ Intervention ☐ SATA ☐ Teaching / Education ☐ Safety ☐ Delegation")],
[PB("Clinical Setting:", textColor=RED),
P("☐ Emergency / Acute ☐ Post-op ☐ Chronic / Outpatient ☐ Pediatric ☐ OB / Maternity ☐ Mental Health")],
], [1.5*inch, FULL-1.5*inch], extra=[
("BACKGROUND",(0,0),(-1,-1),LRED),
("ROWBACKGROUNDS",(0,0),(-1,-1),[LRED,colors.HexColor("#FEF3F2")]),
]))
story.append(SP(0.07))
# ── STEP 2 ────────────────────────────────────────────────────────────────────
story.append(step_hdr(2, "IDENTIFY THE PATIENT — Who Are They and What's the Clinical Context?", ORANGE))
story.append(SP(0.03))
story.append(row_tbl([
[PB("Age / stage:", textColor=ORANGE), P("________________________________"),
PB("Diagnosis:", textColor=ORANGE), P("________________________________"),
PB("Acuity:", textColor=ORANGE), P("☐ Stable ☐ Unstable ☐ Unknown")],
[PB("Key vitals / labs:", textColor=ORANGE), P("______________________________"),
PB("Medications noted:", textColor=ORANGE), P("______________________________"),
PB("Other clues:", textColor=ORANGE), P("______________________________")],
], [0.90*inch,1.50*inch, 0.80*inch,1.50*inch, 0.65*inch,2.15*inch], extra=[
("BACKGROUND",(0,0),(-1,-1),LORANGE),
]))
story.append(SP(0.07))
# ── STEP 3 ────────────────────────────────────────────────────────────────────
story.append(step_hdr(3, "APPLY YOUR PRIORITY FRAMEWORK Before Reading the Options", GOLD))
story.append(SP(0.03))
story.append(row_tbl([
[PCB("FRAMEWORK",textColor=WHITE), PCB("WHEN TO USE",textColor=WHITE),
PCB("APPLIES?",textColor=WHITE), PCB("WHAT IT TELLS YOU",textColor=WHITE)],
[PB("ABC"), P("Any acute physiological problem"),
PC("☐ Yes ☐ No"),
P("Airway > Breathing > Circulation — address in this order first")],
[PB("Maslow"), P("Physiological vs psychosocial needs"),
PC("☐ Yes ☐ No"),
P("Physiological need wins over emotional/psychological needs")],
[PB("Safety First"), P("Risk of harm, fall, infection, error"),
PC("☐ Yes ☐ No"),
P("Prevent harm before comfort or education")],
[PB("Acute > Chronic"), P("Multiple problems / patients to prioritize"),
PC("☐ Yes ☐ No"),
P("New / acute symptom trumps known chronic finding")],
[PB("Unstable > Stable"), P("Delegation or assignment questions"),
PC("☐ Yes ☐ No"),
P("Unstable patient stays with RN; stable may be delegated to LPN/UAP")],
], [0.90*inch,1.95*inch,0.80*inch,3.85*inch], extra=[
("BACKGROUND",(0,0),(-1,0),DGREY),("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LGOLD,WHITE]),
("ALIGN",(2,0),(2,-1),"CENTER"),
]))
story.append(SP(0.07))
# ── STEP 4 ────────────────────────────────────────────────────────────────────
story.append(step_hdr(4, "ELIMINATE — Cross Off Wrong Answers One at a Time", PURPLE))
story.append(SP(0.03))
story.append(row_tbl([
[PCB("OPTION",textColor=WHITE), PCB("ELIMINATE IF…",textColor=WHITE),
PCB("KEEP IF…",textColor=WHITE), PCB("MY REASONING (write it)",textColor=WHITE)],
[PCB("A"), P("Contains 'always/never', reassures without action, requires MD order before nursing action"),
P("Addresses ABC/safety directly; assessment-focused if no acute crisis"), write_lines(1,2.20*inch,LPURPLE)],
[PCB("B"), P("Same criteria as above"), P("Same criteria as above"), write_lines(1,2.20*inch,LPURPLE)],
[PCB("C"), P("Same criteria as above"), P("Same criteria as above"), write_lines(1,2.20*inch,LPURPLE)],
[PCB("D"), P("Same criteria as above"), P("Same criteria as above"), write_lines(1,2.20*inch,LPURPLE)],
], [0.38*inch,1.85*inch,1.82*inch,2.20*inch+0.25*inch], extra=[
("BACKGROUND",(0,0),(-1,0),PURPLE),("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LPURPLE,WHITE]),
("ALIGN",(0,0),(0,-1),"CENTER"),
]))
story.append(SP(0.07))
# ── STEP 5 ────────────────────────────────────────────────────────────────────
story.append(step_hdr(5, "SELECT YOUR ANSWER — Apply the Final Decision Rules", TEAL))
story.append(SP(0.03))
story.append(row_tbl([
[PB("My selected answer:", textColor=TEAL), P("________"),
PB("Confidence:", textColor=TEAL),
P("☐ Certain ☐ 50/50 ☐ Guessing — circle one")],
], [1.50*inch,0.55*inch,0.80*inch,4.65*inch], extra=[
("BACKGROUND",(0,0),(-1,-1),LTEAL),
]))
story.append(SP(0.04))
story.append(info_box(
"<b>Final Decision Rules:</b> "
"(1) If two answers both seem right — pick the MORE complete one or the higher-level need. "
"(2) <b>Assess first</b>, then intervene — unless patient safety is immediately threatened. "
"(3) <b>'Notify the provider'</b> is rarely the BEST first action — do something yourself first unless it's outside nursing scope. "
"(4) <b>SATA:</b> each option is True/False independently — select ALL that are true, even if it feels like too many.",
LBLUE, BLUE))
story.append(SP(0.07))
# ── STEPS 6 & 7 side by side (each as separate section) ──────────────────────
story.append(step_hdr(6, "REVIEW THE RATIONALE — Learn From Every Question, Right or Wrong", GREEN))
story.append(SP(0.03))
story.append(row_tbl([
[PB("Correct answer:", textColor=GREEN), P("_______"),
PB("☐ I was correct ☐ I was wrong", textColor=GREEN),
PB("Why was the correct answer RIGHT?", textColor=GREEN)],
[P(""), P(""), P(""), write_lines(2,3.70*inch,LGREEN)],
[PB("Why was MY answer WRONG?", textColor=GREEN),
write_lines(2,2.50*inch,LGREEN), P(""),
PB("Topic / concept I must review:", textColor=GREEN)],
[P(""), P(""), P(""), write_lines(1,3.70*inch,LGREEN)],
], [1.55*inch,2.50*inch,0.10*inch,3.35*inch], extra=[
("BACKGROUND",(0,0),(-1,-1),LGREEN),
("TOPPADDING",(0,0),(-1,-1),4),
]))
story.append(SP(0.07))
story.append(step_hdr(7, "CLASSIFY YOUR MISTAKE — Track Patterns to Stop Repeating Errors", SLATE))
story.append(SP(0.03))
mistake_rows = [
[PCB("TYPE",textColor=WHITE), PCB("DESCRIPTION",textColor=WHITE), PCB("☐ MY ERROR",textColor=WHITE)],
[PB("Content Gap"), P("I didn't know the content. Flag this topic for study."), PC("☐")],
[PB("Misread Question"), P("I missed a key word: NOT, EXCEPT, FIRST, PRIORITY, BEST."), PC("☐")],
[PB("Second-Guessed"), P("My first instinct was correct but I changed my answer."), PC("☐")],
[PB("Wrong Framework"), P("I didn't apply ABC/Maslow. I chose comfort over safety or physiology."), PC("☐")],
[PB("Option Confusion"), P("Two options looked similar. I chose the less complete one."), PC("☐")],
[PB("SATA Error"), P("I under-selected or over-selected. I need to treat each option as T/F."), PC("☐")],
[PB("Delegation Error"), P("I delegated something RN cannot: assessment, teaching, IV push, unstable."),PC("☐")],
[PB("Normal/Abnormal"), P("I didn't recognize the finding as expected/normal. I acted when I shouldn't."),PC("☐")],
]
story.append(row_tbl(mistake_rows, [1.45*inch,5.30*inch,0.75*inch], extra=[
("BACKGROUND",(0,0),(-1,0),SLATE),("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LGREY,WHITE]),
("ALIGN",(2,0),(2,-1),"CENTER"),
]))
# =============================================================================
# PAGE 2 — PRACTICE QUESTION ANALYSIS TEMPLATE × 3
# =============================================================================
story.append(PageBreak())
story.append(SP(0.08))
story.append(banner(
"PRACTICE QUESTION ANALYSIS TEMPLATE",
"Use one block per practice question. Photocopy this page for each study session.",
BLUE))
story.append(SP(0.08))
ACCENTS = [NAVY, RED, GREEN]
LIGHTS = [LNAVY, LRED, LGREEN]
for qi in range(1, 4):
ac = ACCENTS[qi-1]
lc = LIGHTS[qi-1]
# Header row
story.append(row_tbl([
[PCB(f"Q{qi}", textColor=WHITE, fontSize=11),
PW(f"Question {qi} Analysis", fontSize=9),
PW("Date: _____________________", fontSize=8)],
], [0.42*inch, 5.5*inch, 1.58*inch], extra=[
("BACKGROUND",(0,0),(-1,-1),ac),
("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5),
]))
# Write question
story.append(row_tbl([
[PB("Question stem / Q# from bank:", textColor=ac)],
],[FULL], extra=[("BACKGROUND",(0,0),(-1,-1),lc),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),2)]))
story.append(write_lines(2, FULL, lc))
# Answer options — two per row
LH = (FULL - 2*0.28*inch) / 2
story.append(row_tbl([
[PB("A:", textColor=ac), write_lines(1,LH-0.04*inch,lc),
PB("B:", textColor=ac), write_lines(1,LH-0.04*inch,lc)],
[PB("C:", textColor=ac), write_lines(1,LH-0.04*inch,lc),
PB("D:", textColor=ac), write_lines(1,LH-0.04*inch,lc)],
], [0.28*inch,LH,0.28*inch,LH], extra=[
("BACKGROUND",(0,0),(-1,-1),lc),
("TOPPADDING",(0,0),(-1,-1),2),("BOTTOMPADDING",(0,0),(-1,-1),2),
]))
# Analysis row
story.append(row_tbl([
[PB("Key words underlined:", textColor=ac), write_lines(1,1.40*inch,lc),
PB("Question type:", textColor=ac),
P("☐ Priority ☐ Assess\n☐ Intervene ☐ Delegate\n☐ SATA ☐ Teaching", fontSize=7.3, leading=10)],
], [1.30*inch,1.40*inch,0.92*inch,3.88*inch], extra=[
("BACKGROUND",(0,0),(-1,-1),lc),
("GRID",(0,0),(-1,-1),0.3,MGREY),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3),
]))
# Result row
story.append(row_tbl([
[PB("Framework used:", textColor=ac),
P("☐ ABC ☐ Maslow ☐ Safety ☐ Acute/Chronic"),
PB("My answer:", textColor=ac), write_lines(1,0.50*inch,lc),
PB("Correct:", textColor=ac), write_lines(1,0.50*inch,lc),
PB("Result:", textColor=ac), P("☐ Correct ☐ Wrong")],
], [1.0*inch,1.75*inch,0.72*inch,0.50*inch,0.60*inch,0.50*inch,0.50*inch,1.93*inch], extra=[
("BACKGROUND",(0,0),(-1,-1),lc),
("GRID",(0,0),(-1,-1),0.3,MGREY),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3),
]))
# Mistake + rationale
story.append(row_tbl([
[PB("Mistake type:", textColor=ac),
P("☐ Content gap ☐ Misread ☐ Second-guessed ☐ Wrong framework ☐ SATA ☐ Normal/abnormal ☐ Delegation")],
], [0.95*inch, FULL-0.95*inch], extra=[
("BACKGROUND",(0,0),(-1,-1),lc),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
]))
story.append(row_tbl([
[PB("Rationale / what I learned / concept to review:", textColor=ac)],
],[FULL], extra=[("BACKGROUND",(0,0),(-1,-1),lc),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),2)]))
story.append(write_lines(2, FULL, lc))
story.append(SP(0.10))
# =============================================================================
# PAGE 3 — ERROR TRACKER + STRATEGY NOTES
# =============================================================================
story.append(PageBreak())
story.append(SP(0.08))
story.append(banner(
"SESSION ERROR TRACKER & PERSONAL STRATEGY NOTES",
"Fill in after every practice session. Patterns show you exactly where to focus next.",
PURPLE))
story.append(SP(0.08))
# Session log
story.append(PB("📊 SESSION PERFORMANCE LOG", textColor=PURPLE, fontSize=9))
story.append(SP(0.04))
log_hdr = [PCB("DATE",textColor=WHITE), PCB("# Qs",textColor=WHITE),
PCB("# Correct",textColor=WHITE), PCB("% Score",textColor=WHITE),
PCB("TOPIC FOCUS",textColor=WHITE), PCB("TOP MISTAKE",textColor=WHITE),
PCB("TOPICS TO REVIEW",textColor=WHITE)]
log_rows = [log_hdr] + [["","","","","","",""] for _ in range(10)]
log_cw = [0.75*inch,0.60*inch,0.78*inch,0.68*inch,1.15*inch,1.20*inch,2.34*inch]
story.append(row_tbl(log_rows, log_cw, extra=[
("BACKGROUND",(0,0),(-1,0),PURPLE),("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LPURPLE,WHITE]),
("ALIGN",(0,0),(3,-1),"CENTER"),
("ROWHEIGHTS",(0,1),(-1,-1),18),
]))
story.append(SP(0.10))
# Cumulative error tally
story.append(PB("🔍 CUMULATIVE ERROR PATTERN TALLY", textColor=RED, fontSize=9))
story.append(SP(0.04))
err_rows = [
[PCB("MISTAKE TYPE",textColor=WHITE), PCB("TALLY (add a mark each occurrence)",textColor=WHITE),
PCB("TOTAL",textColor=WHITE), PCB("MY CORRECTIVE ACTION",textColor=WHITE)],
[PB("Content Gap"), write_lines(1,2.40*inch,LRED), PC(""),
P("Flag topic → add to weak-areas list → schedule extra review")],
[PB("Misread Question"), write_lines(1,2.40*inch,LRED), PC(""),
P("Underline key words BEFORE reading answer options every time")],
[PB("Second-Guessed"), write_lines(1,2.40*inch,LRED), PC(""),
P("Write first instinct. Only change answer with clear logical reason")],
[PB("Wrong Framework"), write_lines(1,2.40*inch,LRED), PC(""),
P("Ask: Is there an ABC issue? If yes → that answer wins every time")],
[PB("Option Confusion"), write_lines(1,2.40*inch,LRED), PC(""),
P("Cover options, predict answer first, then match to choices")],
[PB("SATA Error"), write_lines(1,2.40*inch,LRED), PC(""),
P("Each option = independent True/False. Select ALL that are true")],
[PB("Delegation Error"), write_lines(1,2.40*inch,LRED), PC(""),
P("RN cannot delegate: assessment, teaching, IV push, unstable patients")],
[PB("Normal/Abnormal"), write_lines(1,2.40*inch,LRED), PC(""),
P("Review expected post-op/procedure findings before each exam session")],
]
story.append(row_tbl(err_rows, [1.30*inch,2.40*inch,0.55*inch,3.25*inch], extra=[
("BACKGROUND",(0,0),(-1,0),RED),("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LRED,WHITE]),
("ALIGN",(2,0),(2,-1),"CENTER"),
]))
story.append(SP(0.10))
# Personal notes
story.append(PB("✏️ MY PERSONAL STRATEGY NOTES", textColor=NAVY, fontSize=9))
story.append(SP(0.04))
prompts = [
("My biggest content weakness right now:", 2),
("The priority framework I keep forgetting to apply:", 1),
("Key words / phrases I must circle before reading options:", 1),
("My current score trend: ☐ Improving ☐ Stable ☐ Needs work", 1),
("One thing I will do differently in my NEXT practice session:", 2),
("My target exam date:", 1),
]
for label, n in prompts:
story.append(row_tbl([[PB(label, textColor=NAVY, fontSize=7.8)]],
[FULL], extra=[("BACKGROUND",(0,0),(-1,-1),LNAVY),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),2),
("LEFTPADDING",(0,0),(-1,-1),6)]))
story.append(write_lines(n, FULL, WHITE))
story.append(SP(0.04))
# Closing
story.append(row_tbl([[P(
'<b>"The expert in anything was once a beginner."</b> '
'Every question you analyze carefully — right or wrong — makes you a sharper thinker. '
'Work the process. The score will follow. <b>You are going to pass this exam. 🎓</b>',
fontName="Helvetica-Bold", fontSize=9, textColor=NAVY,
alignment=TA_CENTER, leading=14)]], [FULL], extra=[
("BACKGROUND",(0,0),(-1,-1),LGOLD),
("BOX",(0,0),(-1,-1),1.5,GOLD),
("TOPPADDING",(0,0),(-1,-1),8),("BOTTOMPADDING",(0,0),(-1,-1),8),
("LEFTPADDING",(0,0),(-1,-1),10),("RIGHTPADDING",(0,0),(-1,-1),10),
]))
# ── Build ─────────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(OUTPUT, pagesize=letter,
topMargin=0.80*inch, bottomMargin=0.45*inch,
leftMargin=0.45*inch, rightMargin=0.45*inch)
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print(f"SUCCESS: {OUTPUT}")
cd /home/daytona/workspace/nclex-labs && python3 gen_worksheet.py 2>&1
python3 -c " from reportlab.lib.pagesizes import letter from reportlab.lib impor…
~/nclex-labs/gen_worksheet_v2.py
"""
NCLEX Critical Thinking Worksheet — final version
Writing areas use custom WritingLines Flowable (never nested in table cells)
"""
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors
from reportlab.lib.units import inch
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
PageBreak, HRFlowable
)
from reportlab.platypus.flowables import Flowable
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
OUTPUT = "/home/daytona/workspace/nclex-labs/NCLEX_Critical_Thinking_Worksheet.pdf"
PAGE_W, PAGE_H = letter
# ── Palette ──────────────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1B2A4A")
TEAL = colors.HexColor("#0B7A75")
RED = colors.HexColor("#B03A2E")
ORANGE = colors.HexColor("#D9622B")
GREEN = colors.HexColor("#1D6A39")
PURPLE = colors.HexColor("#5B2C6F")
GOLD = colors.HexColor("#9A7D0A")
BLUE = colors.HexColor("#1A5276")
SLATE = colors.HexColor("#2E4057")
WHITE = colors.white
DGREY = colors.HexColor("#2C3E50")
MGREY = colors.HexColor("#BDC3C7")
LGREY = colors.HexColor("#F4F6F9")
LNAVY = colors.HexColor("#EAF0FB")
LTEAL = colors.HexColor("#E8F8F5")
LGREEN = colors.HexColor("#EAFAF1")
LRED = colors.HexColor("#FDEDEC")
LPURPLE= colors.HexColor("#F5EEF8")
LBLUE = colors.HexColor("#EBF5FB")
LORANGE= colors.HexColor("#FEF5E7")
LGOLD = colors.HexColor("#FDFAE5")
XLGREY = colors.HexColor("#FAFAFA")
FULL = 7.5 * inch
# ── Custom writing-lines Flowable ─────────────────────────────────────────────
class WL(Flowable):
"""Horizontal ruled writing lines."""
def __init__(self, n=2, w=None, h=0.24*inch, bg=XLGREY, border=True):
super().__init__()
self.n = n
self._w = w or FULL
self._lh = h
self.bg = bg
self._border = border
def wrap(self, aW, aH):
self._actual_w = min(self._w, aW)
return (self._actual_w, self.n * self._lh)
def draw(self):
c = self.canv
total_h = self.n * self._lh
c.setFillColor(self.bg)
c.rect(0, 0, self._actual_w, total_h, fill=1, stroke=0)
c.setStrokeColor(MGREY)
c.setLineWidth(0.4)
if self._border:
c.rect(0, 0, self._actual_w, total_h, fill=0, stroke=1)
for i in range(1, self.n):
y = i * self._lh
c.line(2, y, self._actual_w - 2, y)
# ── Helpers ───────────────────────────────────────────────────────────────────
def PS(name, **kw):
base = dict(fontName="Helvetica", fontSize=8, textColor=DGREY, leading=11)
base.update(kw)
return ParagraphStyle(name, **base)
def P(t, **kw): return Paragraph(str(t), PS("_", **kw))
def PB(t,**kw): kw.setdefault("fontName","Helvetica-Bold"); return P(t, **kw)
def PW(t,**kw): kw["textColor"]=WHITE; kw.setdefault("fontName","Helvetica-Bold"); return P(t, **kw)
def PC(t,**kw): kw["alignment"]=TA_CENTER; return P(t, **kw)
def PCB(t,**kw): kw["alignment"]=TA_CENTER; kw.setdefault("fontName","Helvetica-Bold"); return P(t,**kw)
SP = lambda n=0.06: Spacer(1, n*inch)
BASE = [
("FONTNAME", (0,0),(-1,-1), "Helvetica"),
("FONTSIZE", (0,0),(-1,-1), 8),
("GRID", (0,0),(-1,-1), 0.4, MGREY),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 5),
("RIGHTPADDING", (0,0),(-1,-1), 5),
]
def T(rows, cw, extra=None):
t = Table(rows, colWidths=cw)
s = list(BASE) + (extra or [])
t.setStyle(TableStyle(s))
return t
def banner(title, sub, bg):
rows = [[PW(title, fontSize=10, alignment=TA_CENTER)]]
if sub:
rows.append([P(sub, fontSize=7.5,
textColor=colors.HexColor("#D5D8DC"),
alignment=TA_CENTER, leading=10)])
t = Table(rows, colWidths=[FULL])
t.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),bg),
("TOPPADDING",(0,0),(-1,-1),5),
("BOTTOMPADDING",(0,0),(-1,-1),5)]))
return t
def step_hdr(num, title, bg):
t = Table([[PCB(f"STEP {num}", textColor=WHITE, fontSize=9),
PW(title, fontSize=9)]],
colWidths=[0.72*inch, FULL-0.72*inch])
t.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),bg),
("TOPPADDING",(0,0),(-1,-1),4),
("BOTTOMPADDING",(0,0),(-1,-1),4),
("LEFTPADDING",(0,0),(-1,-1),6),
("VALIGN",(0,0),(-1,-1),"MIDDLE")]))
return t
def ibox(txt, bg, bc):
t = Table([[P(txt, fontSize=7.8, textColor=DGREY, leading=11)]],
colWidths=[FULL])
t.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),bg),
("BOX",(0,0),(-1,-1),1,bc),
("TOPPADDING",(0,0),(-1,-1),5),
("BOTTOMPADDING",(0,0),(-1,-1),5),
("LEFTPADDING",(0,0),(-1,-1),8),
("RIGHTPADDING",(0,0),(-1,-1),8)]))
return t
def lbl(txt, ac, bg):
t = Table([[PB(txt, textColor=ac, fontSize=7.8)]], colWidths=[FULL])
t.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),bg),
("TOPPADDING",(0,0),(-1,-1),3),
("BOTTOMPADDING",(0,0),(-1,-1),2),
("LEFTPADDING",(0,0),(-1,-1),6)]))
return t
# ── Page callback ─────────────────────────────────────────────────────────────
def on_page(canvas, doc):
canvas.setFillColor(NAVY)
canvas.rect(0, PAGE_H-54, PAGE_W, 54, fill=1, stroke=0)
canvas.setFillColor(TEAL)
canvas.rect(0, PAGE_H-58, PAGE_W, 4, fill=1, stroke=0)
canvas.setFont("Helvetica-Bold", 17)
canvas.setFillColor(WHITE)
canvas.drawCentredString(PAGE_W/2, PAGE_H-32,
"NCLEX CRITICAL THINKING WORKSHEET")
canvas.setFont("Helvetica", 9)
canvas.setFillColor(colors.HexColor("#A8D8EA"))
canvas.drawCentredString(PAGE_W/2, PAGE_H-48,
"Analyze every question systematically • Build reasoning habits • Eliminate wrong answers with confidence")
canvas.setFillColor(TEAL)
canvas.rect(0, 26, PAGE_W, 2, fill=1, stroke=0)
canvas.setFont("Helvetica", 7.5)
canvas.setFillColor(MGREY)
canvas.drawCentredString(PAGE_W/2, 14,
f"NCLEX Prep Series • Critical Thinking Framework • Page {doc.page}")
# =============================================================================
# PAGE 1 — 7-STEP FRAMEWORK
# =============================================================================
story = []
story.append(SP(0.08))
story.append(ibox(
"<b>HOW TO USE:</b> Apply all 7 steps to every practice question you miss — "
"and any you got right by guessing. The goal is to build a thinking habit, not memorize answers. "
"Photocopy pages 2–3 for each study session.",
LNAVY, NAVY))
story.append(SP(0.08))
# Step 1
story.append(step_hdr(1, "READ THE STEM — Identify What Is REALLY Being Asked", RED))
story.append(SP(0.03))
story.append(T([
[PB("Circle Key Words:", textColor=RED),
P("first • priority • most important • best • immediate • initial • EXCEPT • NOT • contraindicated • next")],
[PB("Question Type:", textColor=RED),
P("☐ Priority/First Action ☐ Assessment ☐ Intervention ☐ SATA ☐ Teaching ☐ Safety ☐ Delegation")],
[PB("Setting:", textColor=RED),
P("☐ Emergency/Acute ☐ Post-op ☐ Chronic/Outpatient ☐ Pediatric ☐ OB/Maternity ☐ Mental Health")],
], [1.5*inch, FULL-1.5*inch], extra=[
("ROWBACKGROUNDS",(0,0),(-1,-1),[LRED, colors.HexColor("#FEF3F2")]),
]))
story.append(SP(0.07))
# Step 2
story.append(step_hdr(2, "IDENTIFY THE PATIENT — Clinical Context Matters", ORANGE))
story.append(SP(0.03))
story.append(T([
[PB("Age:", textColor=ORANGE), P("________________"),
PB("Diagnosis:", textColor=ORANGE), P("___________________________"),
PB("Acuity:", textColor=ORANGE), P("☐ Stable ☐ Unstable")],
[PB("Key vitals/labs:", textColor=ORANGE), P("___________________"),
PB("Medications:", textColor=ORANGE), P("___________________________"),
PB("Other clues:", textColor=ORANGE), P("___________________")],
], [0.78*inch,1.20*inch, 0.82*inch,1.88*inch, 0.70*inch,2.12*inch], extra=[
("BACKGROUND",(0,0),(-1,-1),LORANGE),
]))
story.append(SP(0.07))
# Step 3
story.append(step_hdr(3, "APPLY YOUR PRIORITY FRAMEWORK Before Reading Answer Options", GOLD))
story.append(SP(0.03))
story.append(T([
[PCB("FRAMEWORK",textColor=WHITE), PCB("WHEN TO USE",textColor=WHITE),
PCB("APPLIES?",textColor=WHITE), PCB("WHAT IT TELLS YOU",textColor=WHITE)],
[PB("ABC"),
P("Any acute physiological problem"), PC("☐ Yes ☐ No"),
P("Airway > Breathing > Circulation — address in this order first")],
[PB("Maslow"),
P("Physiology vs psychosocial needs"), PC("☐ Yes ☐ No"),
P("Physiological need always wins over emotional/psychological needs")],
[PB("Safety"),
P("Risk of harm, fall, medication error"), PC("☐ Yes ☐ No"),
P("Prevent harm before comfort or teaching")],
[PB("Acute > Chronic"),
P("Multiple problems to prioritize"), PC("☐ Yes ☐ No"),
P("New/acute symptom trumps a known chronic finding")],
[PB("Unstable > Stable"),
P("Delegation or assignment questions"), PC("☐ Yes ☐ No"),
P("Unstable stays with RN; stable may be delegated to LPN/UAP")],
], [0.90*inch,1.95*inch,0.80*inch,3.85*inch], extra=[
("BACKGROUND",(0,0),(-1,0),DGREY),("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LGOLD,WHITE]),
("ALIGN",(2,0),(2,-1),"CENTER"),
]))
story.append(SP(0.07))
# Step 4
story.append(step_hdr(4, "ELIMINATE — Cross Off Wrong Answers One at a Time", PURPLE))
story.append(SP(0.03))
story.append(T([
[PCB("OPT",textColor=WHITE), PCB("ELIMINATE IF…",textColor=WHITE),
PCB("KEEP IF…",textColor=WHITE), PCB("My reasoning (write here)",textColor=WHITE)],
[PCB("A"), P("Contains 'always/never'; reassures without action; requires MD order before nursing step"),
P("Addresses ABC/safety; assessment-focused if no acute crisis"), P("_________________________________")],
[PCB("B"), P("Same criteria"), P("Same criteria"), P("_________________________________")],
[PCB("C"), P("Same criteria"), P("Same criteria"), P("_________________________________")],
[PCB("D"), P("Same criteria"), P("Same criteria"), P("_________________________________")],
], [0.38*inch,2.10*inch,2.10*inch,2.92*inch], extra=[
("BACKGROUND",(0,0),(-1,0),PURPLE),("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LPURPLE,WHITE]),
("ALIGN",(0,0),(0,-1),"CENTER"),
]))
story.append(SP(0.07))
# Step 5
story.append(step_hdr(5, "SELECT YOUR ANSWER — Apply Final Decision Rules", TEAL))
story.append(SP(0.03))
story.append(T([[
PB("My selected answer:", textColor=TEAL), P("_______"),
PB("Confidence:", textColor=TEAL),
P("☐ Certain ☐ 50/50 ☐ Guessing"),
]], [1.50*inch,0.55*inch,0.80*inch,4.65*inch], extra=[
("BACKGROUND",(0,0),(-1,-1),LTEAL),
]))
story.append(SP(0.04))
story.append(ibox(
"<b>Final Decision Rules:</b> "
"(1) Two options both right? Pick the MORE complete one / higher-level need. "
"(2) Assess BEFORE intervening — unless safety is immediately threatened. "
"(3) 'Notify the provider' is rarely the BEST first nursing action. "
"(4) SATA: treat each option as independent True/False — select ALL that are true.",
LBLUE, BLUE))
story.append(SP(0.07))
# Step 6
story.append(step_hdr(6, "REVIEW THE RATIONALE — Learn From Every Question", GREEN))
story.append(SP(0.03))
story.append(T([
[PB("Correct answer:", textColor=GREEN), P("_______"),
PB("☐ I was correct ☐ I was wrong", textColor=GREEN)],
], [1.5*inch,0.55*inch,5.45*inch], extra=[
("BACKGROUND",(0,0),(-1,-1),LGREEN),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
]))
story.append(lbl("Why was the correct answer RIGHT? / What did the rationale teach me?", GREEN, LGREEN))
story.append(WL(2, FULL, bg=LGREEN))
story.append(lbl("Why was MY answer WRONG (if incorrect)? / Concept to review:", GREEN, LGREEN))
story.append(WL(2, FULL, bg=LGREEN))
story.append(SP(0.07))
# Step 7
story.append(step_hdr(7, "CLASSIFY YOUR MISTAKE — Track Patterns to Stop Repeating Errors", SLATE))
story.append(SP(0.03))
story.append(T([
[PCB("MISTAKE TYPE",textColor=WHITE), PCB("DESCRIPTION",textColor=WHITE), PCB("☐",textColor=WHITE)],
[PB("Content Gap"), P("I didn't know the content. Flag this topic for study."), PC("☐")],
[PB("Misread Question"), P("I missed a key word: NOT, EXCEPT, FIRST, PRIORITY, BEST."), PC("☐")],
[PB("Second-Guessed"), P("My first instinct was correct but I changed my answer."), PC("☐")],
[PB("Wrong Framework"), P("I didn't apply ABC/Maslow correctly. Chose comfort over safety."), PC("☐")],
[PB("Option Confusion"), P("Two options looked similar. I chose the less complete one."), PC("☐")],
[PB("SATA Error"), P("I under-selected or over-selected. Must treat each option as T/F."), PC("☐")],
[PB("Delegation Error"), P("I delegated: assessment, teaching, IV push, or care of unstable patient."), PC("☐")],
[PB("Normal/Abnormal"), P("I didn't recognize an expected/normal finding. Acted when I shouldn't have."), PC("☐")],
], [1.45*inch,5.30*inch,0.75*inch], extra=[
("BACKGROUND",(0,0),(-1,0),SLATE),("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LGREY,WHITE]),
("ALIGN",(2,0),(2,-1),"CENTER"),
]))
# =============================================================================
# PAGE 2 — PRACTICE QUESTION ANALYSIS TEMPLATE × 3
# =============================================================================
story.append(PageBreak())
story.append(SP(0.08))
story.append(banner(
"PRACTICE QUESTION ANALYSIS TEMPLATE",
"Use one block per question. Photocopy this page for each study session.",
BLUE))
story.append(SP(0.08))
ACCENTS = [NAVY, RED, GREEN]
LIGHTS = [LNAVY, LRED, LGREEN]
for qi in range(1, 4):
ac = ACCENTS[qi-1]
lc = LIGHTS[qi-1]
# Header
story.append(T([[
PCB(f"Q{qi}", textColor=WHITE, fontSize=11),
PW(f"Question {qi} Analysis", fontSize=9),
PW("Date: _____________________", fontSize=8),
]], [0.42*inch, 5.5*inch, 1.58*inch], extra=[
("BACKGROUND",(0,0),(-1,-1),ac),
("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5),
]))
story.append(lbl("Write the question stem here (or paste Q# / first line from question bank):", ac, lc))
story.append(WL(2, FULL, bg=lc))
# Options A–D
story.append(T([
[PB("A:", textColor=ac), P("_______________________________"),
PB("B:", textColor=ac), P("_______________________________")],
[PB("C:", textColor=ac), P("_______________________________"),
PB("D:", textColor=ac), P("_______________________________")],
], [0.28*inch,3.47*inch,0.28*inch,3.47*inch], extra=[
("BACKGROUND",(0,0),(-1,-1),lc),
("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
]))
# Analysis
story.append(T([[
PB("Key words I circled:", textColor=ac),
P("__________________________"),
PB("Type:", textColor=ac),
P("☐ Priority ☐ Assess ☐ Intervene\n☐ Delegate ☐ SATA ☐ Teaching", fontSize=7.3, leading=10),
PB("Framework:", textColor=ac),
P("☐ ABC ☐ Maslow\n☐ Safety ☐ Acute/Chronic", fontSize=7.3, leading=10),
]], [1.28*inch,1.60*inch,0.40*inch,1.60*inch,0.72*inch,1.90*inch], extra=[
("BACKGROUND",(0,0),(-1,-1),lc),
("GRID",(0,0),(-1,-1),0.3,MGREY),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3),
]))
# Result
story.append(T([[
PB("My answer:", textColor=ac), P("_______"),
PB("Correct answer:", textColor=ac), P("_______"),
PB("Result:", textColor=ac), P("☐ Correct ☐ Wrong ☐ Guessed"),
PB("Mistake:", textColor=ac),
P("☐ Content ☐ Misread ☐ 2nd-guessed ☐ Framework ☐ SATA ☐ Delegation ☐ Normal/Abnormal",
fontSize=7.3, leading=10),
]], [0.80*inch,0.60*inch,1.05*inch,0.60*inch,0.52*inch,1.55*inch,0.60*inch,2.28*inch], extra=[
("BACKGROUND",(0,0),(-1,-1),lc),
("GRID",(0,0),(-1,-1),0.3,MGREY),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3),
]))
story.append(lbl("What the rationale taught me / concept to review:", ac, lc))
story.append(WL(2, FULL, bg=lc))
story.append(SP(0.10))
# =============================================================================
# PAGE 3 — ERROR TRACKER + STRATEGY NOTES
# =============================================================================
story.append(PageBreak())
story.append(SP(0.08))
story.append(banner(
"SESSION ERROR TRACKER & PERSONAL STRATEGY NOTES",
"Fill in after every practice session. Patterns show you exactly where to focus next.",
PURPLE))
story.append(SP(0.08))
# Session log
story.append(PB("📊 SESSION PERFORMANCE LOG", textColor=PURPLE, fontSize=9))
story.append(SP(0.04))
log_rows = [[PCB("DATE",textColor=WHITE), PCB("# Qs",textColor=WHITE),
PCB("Correct",textColor=WHITE), PCB("% Score",textColor=WHITE),
PCB("TOPIC FOCUS",textColor=WHITE), PCB("TOP MISTAKE",textColor=WHITE),
PCB("REVIEW NEEDED",textColor=WHITE)]]
log_rows += [["","","","","","",""] for _ in range(10)]
story.append(T(log_rows,
[0.72*inch,0.55*inch,0.65*inch,0.65*inch,1.18*inch,1.22*inch,2.53*inch], extra=[
("BACKGROUND",(0,0),(-1,0),PURPLE),("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LPURPLE,WHITE]),
("ALIGN",(0,0),(3,-1),"CENTER"),
("ROWHEIGHTS",(0,1),(-1,-1),16),
]))
story.append(SP(0.10))
# Error tally
story.append(PB("🔍 CUMULATIVE MISTAKE TALLY", textColor=RED, fontSize=9))
story.append(SP(0.04))
err_rows = [[PCB("MISTAKE TYPE",textColor=WHITE), PCB("TALLY (mark each occurrence)",textColor=WHITE),
PCB("TOTAL",textColor=WHITE), PCB("MY CORRECTIVE STRATEGY",textColor=WHITE)]]
mistakes = [
("Content Gap", "Flag topic → review in study schedule weak-areas section"),
("Misread Question", "Circle key words BEFORE reading answer options — every time"),
("Second-Guessed", "Write first instinct first. Change only with a clear logical reason"),
("Wrong Framework", "Ask: Is there an ABC problem? If yes → that answer wins every time"),
("Option Confusion", "Cover options, predict answer first, then match to choices"),
("SATA Error", "Each option = independent T/F. Select ALL that are true"),
("Delegation Error", "RN cannot delegate: assessment, teaching, IV push, unstable patients"),
("Normal/Abnormal", "Review expected post-op/procedure findings before each session"),
]
for m, strategy in mistakes:
err_rows.append([PB(m), P(""), PC(""), P(strategy)])
story.append(T(err_rows, [1.30*inch,2.55*inch,0.55*inch,3.10*inch], extra=[
("BACKGROUND",(0,0),(-1,0),RED),("TEXTCOLOR",(0,0),(-1,0),WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LRED,WHITE]),
("ALIGN",(2,0),(2,-1),"CENTER"),
("ROWHEIGHTS",(0,1),(-1,-1),18),
]))
story.append(SP(0.10))
# Personal notes
story.append(PB("✏️ MY PERSONAL STRATEGY NOTES", textColor=NAVY, fontSize=9))
story.append(SP(0.04))
prompts = [
("My biggest content weakness right now:", 2),
("The priority framework I keep forgetting to apply:", 1),
("Key words / phrases I must circle before reading answer options:", 1),
("My current score trend: ☐ Improving ☐ About the same ☐ Needs significant work", 1),
("One thing I will do differently in my NEXT practice session:", 2),
("My target NCLEX exam date:", 1),
]
for label, n in prompts:
story.append(T([[PB(label, textColor=NAVY, fontSize=7.8)]], [FULL], extra=[
("BACKGROUND",(0,0),(-1,-1),LNAVY),
("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),2),
("LEFTPADDING",(0,0),(-1,-1),6)]))
story.append(WL(n, FULL, bg=WHITE))
story.append(SP(0.04))
# Closing motivational box
story.append(T([[P(
'<b>"The expert in anything was once a beginner."</b> '
'Every question you analyze carefully — right or wrong — makes you a sharper clinical thinker. '
'Work the process. The score will follow. <b>You are going to pass this exam! 🎓</b>',
fontName="Helvetica-Bold", fontSize=9, textColor=NAVY,
alignment=TA_CENTER, leading=14)]], [FULL], extra=[
("BACKGROUND",(0,0),(-1,-1),LGOLD),
("BOX",(0,0),(-1,-1),1.5,GOLD),
("TOPPADDING",(0,0),(-1,-1),8),("BOTTOMPADDING",(0,0),(-1,-1),8),
("LEFTPADDING",(0,0),(-1,-1),10),("RIGHTPADDING",(0,0),(-1,-1),10),
]))
# ── Build ─────────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(OUTPUT, pagesize=letter,
topMargin=0.80*inch, bottomMargin=0.45*inch,
leftMargin=0.45*inch, rightMargin=0.45*inch)
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print(f"SUCCESS: {OUTPUT}")
cd /home/daytona/workspace/nclex-labs && python3 gen_worksheet_v2.py 2>&1
ls -lh /home/daytona/workspace/nclex-labs/NCLEX_Critical_Thinking_Worksheet.pdf
NCLEX Critical Thinking Worksheet
PDF Document · PDF
| Step | Purpose |
|---|---|
| 1. Read the Stem | Identify key words, question type, clinical setting |
| 2. Identify the Patient | Age, diagnosis, acuity, vitals, medications |
| 3. Apply Priority Framework | ABC, Maslow, Safety, Acute vs Chronic, Unstable vs Stable |
| 4. Eliminate Options | Why each option stays or goes — with reasoning space |
| 5. Select Your Answer | Confidence level + final decision rules (assess before intervene, etc.) |
| 6. Review the Rationale | What was right, what was wrong, concept to revisit |
| 7. Classify Your Mistake | 8 error types with checkboxes to identify your pattern |