leucorrhea case tracking chart
What format would you like the leucorrhea case tracking chart in? · What is the chart primarily for?
ls /home/daytona/workspace/ 2>/dev/null && echo "---" && ls /home/daytona/workspace/attachments/ 2>/dev/null || echo "no attachments"
mkdir -p /home/daytona/workspace/leucorrhea-chart && python3 - << 'PYEOF' from reportlab.lib.pagesizes import A4 from reportlab.lib import colors from reportlab.lib.units import mm, cm from reportlab.platypus import (SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, HRFlowable, KeepTogether) from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT from reportlab.pdfgen import canvas from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate import datetime OUTPUT = "/home/daytona/workspace/leucorrhea-chart/leucorrhea_case_tracking_chart.pdf" # ── Colours ────────────────────────────────────────────────────────────────── TEAL = colors.HexColor("#1a7f8e") TEAL_LIGHT = colors.HexColor("#e6f4f6") TEAL_MID = colors.HexColor("#a8d8df") GREY_HEAD = colors.HexColor("#374151") GREY_ROW = colors.HexColor("#f9fafb") WHITE = colors.white RED_LIGHT = colors.HexColor("#fff0f0") AMBER = colors.HexColor("#fffbea") GREEN_LIGHT= colors.HexColor("#f0fff4") # ── Styles ──────────────────────────────────────────────────────────────────── styles = getSampleStyleSheet() def style(name, **kw): base = styles[name] if name in styles else styles["Normal"] return ParagraphStyle(name+"_custom_"+str(id(kw)), parent=base, **kw) title_s = style("Title", fontSize=18, textColor=WHITE, alignment=TA_CENTER, leading=24, fontName="Helvetica-Bold") sub_s = style("Normal", fontSize=9, textColor=TEAL_LIGHT, alignment=TA_CENTER, leading=12, fontName="Helvetica") sec_s = style("Normal", fontSize=11, textColor=WHITE, alignment=TA_LEFT, leading=14, fontName="Helvetica-Bold") label_s = style("Normal", fontSize=8, textColor=GREY_HEAD, alignment=TA_LEFT, leading=11, fontName="Helvetica-Bold") cell_s = style("Normal", fontSize=8, textColor=GREY_HEAD, alignment=TA_LEFT, leading=11, fontName="Helvetica") cell_c = style("Normal", fontSize=8, textColor=GREY_HEAD, alignment=TA_CENTER,leading=11, fontName="Helvetica") note_s = style("Normal", fontSize=7, textColor=colors.HexColor("#6b7280"), alignment=TA_LEFT, leading=10, fontName="Helvetica-Oblique") footer_s = style("Normal", fontSize=7, textColor=colors.HexColor("#9ca3af"), alignment=TA_CENTER, leading=10, fontName="Helvetica") W, H = A4 MARGIN = 15*mm # ── Helper: section header row ──────────────────────────────────────────────── def sec_row(text, cols): return ([Paragraph(text, sec_s)] + [""] * (cols - 1),) # ── Page callback (header + footer) ─────────────────────────────────────────── def on_page(cv, doc): cv.saveState() # ---- header band ---- cv.setFillColor(TEAL) cv.rect(0, H - 28*mm, W, 28*mm, fill=1, stroke=0) cv.setFillColor(WHITE) cv.setFont("Helvetica-Bold", 16) cv.drawCentredString(W/2, H - 14*mm, "Leucorrhea (Vaginal Discharge) — Clinical Case Tracking Chart") cv.setFont("Helvetica", 8) cv.setFillColor(TEAL_LIGHT) cv.drawCentredString(W/2, H - 21*mm, "For clinical patient follow-up use · Date generated: " + datetime.date.today().strftime("%d %B %Y")) # ---- footer ---- cv.setFillColor(colors.HexColor("#6b7280")) cv.setFont("Helvetica", 7) cv.drawString(MARGIN, 8*mm, "Clinician:_________________________ Clinic/Dept:_________________________ Page: %d" % doc.page) cv.drawRightString(W - MARGIN, 8*mm, "Confidential — Patient Medical Record") cv.restoreState() # ── Document ────────────────────────────────────────────────────────────────── doc = BaseDocTemplate(OUTPUT, pagesize=A4, leftMargin=MARGIN, rightMargin=MARGIN, topMargin=32*mm, bottomMargin=18*mm) frame = Frame(MARGIN, 18*mm, W - 2*MARGIN, H - 50*mm, id="main") doc.addPageTemplates([PageTemplate(id="all", frames=[frame], onPage=on_page)]) # ── Content ─────────────────────────────────────────────────────────────────── story = [] def spacer(h=4): story.append(Spacer(1, h*mm)) def hr(): story.append(HRFlowable(width="100%", thickness=0.5, color=TEAL_MID, spaceAfter=2*mm)) def table(data, col_widths, style_cmds, row_heights=None): t = Table(data, colWidths=col_widths, rowHeights=row_heights, repeatRows=1) t.setStyle(TableStyle([ ("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#d1d5db")), ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, GREY_ROW]), ("TOPPADDING", (0,0), (-1,-1), 4), ("BOTTOMPADDING",(0,0), (-1,-1), 4), ("LEFTPADDING", (0,0), (-1,-1), 4), ("RIGHTPADDING",(0,0), (-1,-1), 4), ("VALIGN", (0,0), (-1,-1), "MIDDLE"), ] + style_cmds)) story.append(t) # ───────────────────────────────────────────────────────────────────────────── # SECTION 1 — PATIENT DEMOGRAPHICS # ───────────────────────────────────────────────────────────────────────────── spacer(2) story.append(Paragraph("▌ SECTION 1: PATIENT INFORMATION", style("Normal", fontSize=11, textColor=TEAL, fontName="Helvetica-Bold", leading=14))) spacer(2) dem_data = [ [Paragraph("Field", label_s), Paragraph("Details", label_s), Paragraph("Field", label_s), Paragraph("Details", label_s)], [Paragraph("Patient Name", cell_s), Paragraph("_"*35, cell_s), Paragraph("Date of Birth", cell_s), Paragraph("__/__/____", cell_s)], [Paragraph("Patient ID / MRN", cell_s), Paragraph("_"*35, cell_s), Paragraph("Age", cell_s), Paragraph("_______ years", cell_s)], [Paragraph("Contact Number", cell_s), Paragraph("_"*35, cell_s), Paragraph("Marital Status", cell_s), Paragraph("□ Single □ Married □ Widowed □ Other", cell_s)], [Paragraph("Address", cell_s), Paragraph("_"*35, cell_s), Paragraph("Occupation", cell_s), Paragraph("_"*25, cell_s)], [Paragraph("Referred By", cell_s), Paragraph("_"*35, cell_s), Paragraph("Insurance / Payer", cell_s), Paragraph("_"*25, cell_s)], ] cw = [(W-2*MARGIN)*0.22, (W-2*MARGIN)*0.28, (W-2*MARGIN)*0.22, (W-2*MARGIN)*0.28] table(dem_data, cw, [ ("BACKGROUND", (0,0), (-1,0), TEAL), ("TEXTCOLOR", (0,0), (-1,0), WHITE), ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"), ]) # ───────────────────────────────────────────────────────────────────────────── # SECTION 2 — OBSTETRIC & GYNAECOLOGICAL HISTORY # ───────────────────────────────────────────────────────────────────────────── spacer(3) story.append(Paragraph("▌ SECTION 2: OBSTETRIC & GYNAECOLOGICAL HISTORY", style("Normal", fontSize=11, textColor=TEAL, fontName="Helvetica-Bold", leading=14))) spacer(2) obs_data = [ [Paragraph("Parameter", label_s), Paragraph("Details", label_s), Paragraph("Parameter", label_s), Paragraph("Details", label_s)], [Paragraph("LMP (Last Menstrual Period)", cell_s), Paragraph("__/__/____", cell_s), Paragraph("Cycle Regularity", cell_s), Paragraph("□ Regular □ Irregular", cell_s)], [Paragraph("Gravida / Para / Abortus", cell_s), Paragraph("G___ P___ A___", cell_s), Paragraph("Contraceptive Use", cell_s), Paragraph("□ None □ OCP □ IUD □ Condom □ Other:___", cell_s)], [Paragraph("Menopausal Status", cell_s), Paragraph("□ Pre □ Peri □ Post", cell_s), Paragraph("Prior STI History", cell_s), Paragraph("□ No □ Yes → specify:____________", cell_s)], [Paragraph("Previous Vaginal Infections", cell_s), Paragraph("□ BV □ Candidiasis □ Trichomoniasis □ Other", cell_s), Paragraph("Cervical Smear (Pap) Date", cell_s), Paragraph("__/__/____ Result:_____________", cell_s)], [Paragraph("Recent Antibiotic Use", cell_s), Paragraph("□ No □ Yes → agent:______________", cell_s), Paragraph("Immunocompromised", cell_s), Paragraph("□ No □ Yes → reason:_______________", cell_s)], ] table(obs_data, cw, [ ("BACKGROUND", (0,0), (-1,0), TEAL), ("TEXTCOLOR", (0,0), (-1,0), WHITE), ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"), ]) # ───────────────────────────────────────────────────────────────────────────── # SECTION 3 — PRESENTING COMPLAINTS & DISCHARGE CHARACTERISATION # ───────────────────────────────────────────────────────────────────────────── spacer(3) story.append(Paragraph("▌ SECTION 3: PRESENTING COMPLAINTS & DISCHARGE CHARACTERISATION", style("Normal", fontSize=11, textColor=TEAL, fontName="Helvetica-Bold", leading=14))) spacer(2) disc_data = [ [Paragraph("Feature", label_s), Paragraph("Findings / Tick Applicable", label_s), Paragraph("Feature", label_s), Paragraph("Findings / Tick Applicable", label_s)], [Paragraph("Duration of Discharge", cell_s), Paragraph("___________ days / weeks", cell_s), Paragraph("Onset", cell_s), Paragraph("□ Sudden □ Gradual", cell_s)], [Paragraph("Colour", cell_s), Paragraph("□ White □ Yellow □ Green □ Grey □ Blood-tinged □ Clear", cell_s), Paragraph("Consistency", cell_s), Paragraph("□ Thin/watery □ Thick □ Curd-like □ Frothy", cell_s)], [Paragraph("Odour", cell_s), Paragraph("□ None □ Fishy □ Foul □ Musty", cell_s), Paragraph("Volume", cell_s), Paragraph("□ Scanty □ Moderate □ Heavy", cell_s)], [Paragraph("Associated Symptoms", cell_s), Paragraph("□ Pruritus □ Burning □ Dysuria □ Dyspareunia □ Lower abdominal pain □ Intermenstrual bleeding □ Postcoital bleeding", cell_s), Paragraph("Cyclical Variation", cell_s), Paragraph("□ No □ Yes → when:______________", cell_s)], [Paragraph("Partner Symptoms", cell_s), Paragraph("□ Asymptomatic □ Urethral discharge □ Dysuria □ Not known", cell_s), Paragraph("New Sexual Partner (last 3 mo)", cell_s), Paragraph("□ No □ Yes", cell_s)], ] table(disc_data, cw, [ ("BACKGROUND", (0,0), (-1,0), TEAL), ("TEXTCOLOR", (0,0), (-1,0), WHITE), ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"), ("SPAN", (1,4), (1,4)), ("SPAN", (1,5), (1,5)), ]) # ───────────────────────────────────────────────────────────────────────────── # SECTION 4 — CLINICAL EXAMINATION # ───────────────────────────────────────────────────────────────────────────── spacer(3) story.append(Paragraph("▌ SECTION 4: CLINICAL EXAMINATION", style("Normal", fontSize=11, textColor=TEAL, fontName="Helvetica-Bold", leading=14))) spacer(2) exam_data = [ [Paragraph("Finding", label_s), Paragraph("Observation", label_s), Paragraph("Finding", label_s), Paragraph("Observation", label_s)], [Paragraph("External Genitalia", cell_s), Paragraph("□ Normal □ Erythema □ Oedema □ Excoriation □ Ulcer □ Condyloma", cell_s), Paragraph("Vaginal Wall", cell_s), Paragraph("□ Normal □ Erythema □ Discharge adherent", cell_s)], [Paragraph("Cervix — Appearance", cell_s), Paragraph("□ Normal □ Ectropion □ Contact bleeding □ Friable □ Polyp", cell_s), Paragraph("Cervical Motion Tenderness", cell_s), Paragraph("□ Absent □ Present", cell_s)], [Paragraph("Adnexal Tenderness", cell_s), Paragraph("□ No □ Right □ Left □ Bilateral", cell_s), Paragraph("Uterine Tenderness", cell_s), Paragraph("□ No □ Yes", cell_s)], [Paragraph("Vaginal pH", cell_s), Paragraph("_______ (normal <4.5)", cell_s), Paragraph("Whiff Test (KOH)", cell_s), Paragraph("□ Negative □ Positive (fishy odour)", cell_s)], [Paragraph("Wet Prep / Microscopy", cell_s), Paragraph("□ Clue cells □ WBCs □ Lactobacilli reduced □ Hyphae/spores □ Trichomonas □ Normal flora", cell_s), Paragraph("Additional Notes", cell_s), Paragraph("_"*28, cell_s)], ] table(exam_data, cw, [ ("BACKGROUND", (0,0), (-1,0), TEAL), ("TEXTCOLOR", (0,0), (-1,0), WHITE), ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"), ]) # ───────────────────────────────────────────────────────────────────────────── # SECTION 5 — INVESTIGATIONS # ───────────────────────────────────────────────────────────────────────────── spacer(3) story.append(Paragraph("▌ SECTION 5: INVESTIGATIONS", style("Normal", fontSize=11, textColor=TEAL, fontName="Helvetica-Bold", leading=14))) spacer(2) inv_data = [ [Paragraph("Test", label_s), Paragraph("Ordered", label_s), Paragraph("Date Collected", label_s), Paragraph("Result / Finding", label_s), Paragraph("Interpreted By", label_s)], [Paragraph("High Vaginal Swab (HVS) — M/C/S", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("__/__/____", cell_c), Paragraph("_"*22, cell_s), Paragraph("_"*15, cell_s)], [Paragraph("Cervical Swab — GC/Chlamydia NAAT", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("__/__/____", cell_c), Paragraph("_"*22, cell_s), Paragraph("_"*15, cell_s)], [Paragraph("KOH Preparation (Candida)", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("__/__/____", cell_c), Paragraph("_"*22, cell_s), Paragraph("_"*15, cell_s)], [Paragraph("Wet Mount (Trichomonas / BV)", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("__/__/____", cell_c), Paragraph("_"*22, cell_s), Paragraph("_"*15, cell_s)], [Paragraph("Pap Smear / Cervical Cytology", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("__/__/____", cell_c), Paragraph("_"*22, cell_s), Paragraph("_"*15, cell_s)], [Paragraph("HIV Screening", cell_s), Paragraph("□ Yes □ No □ Declined", cell_c), Paragraph("__/__/____", cell_c), Paragraph("_"*22, cell_s), Paragraph("_"*15, cell_s)], [Paragraph("RPR / Syphilis Serology", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("__/__/____", cell_c), Paragraph("_"*22, cell_s), Paragraph("_"*15, cell_s)], [Paragraph("Urine R&M / UFEME", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("__/__/____", cell_c), Paragraph("_"*22, cell_s), Paragraph("_"*15, cell_s)], [Paragraph("Ultrasound Pelvis", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("__/__/____", cell_c), Paragraph("_"*22, cell_s), Paragraph("_"*15, cell_s)], [Paragraph("Other:________________", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("__/__/____", cell_c), Paragraph("_"*22, cell_s), Paragraph("_"*15, cell_s)], ] cw5 = [(W-2*MARGIN)*0.30, (W-2*MARGIN)*0.15, (W-2*MARGIN)*0.15, (W-2*MARGIN)*0.25, (W-2*MARGIN)*0.15] table(inv_data, cw5, [ ("BACKGROUND", (0,0), (-1,0), TEAL), ("TEXTCOLOR", (0,0), (-1,0), WHITE), ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"), ]) # ───────────────────────────────────────────────────────────────────────────── # SECTION 6 — DIFFERENTIAL DIAGNOSIS CHECKLIST # ───────────────────────────────────────────────────────────────────────────── spacer(3) story.append(Paragraph("▌ SECTION 6: DIFFERENTIAL DIAGNOSIS CHECKLIST", style("Normal", fontSize=11, textColor=TEAL, fontName="Helvetica-Bold", leading=14))) spacer(2) dd_data = [ [Paragraph("Diagnosis", label_s), Paragraph("Key Features", label_s), Paragraph("pH", label_s), Paragraph("Microscopy", label_s), Paragraph("Considered", label_s), Paragraph("Confirmed / Excluded", label_s)], [Paragraph("Bacterial Vaginosis (BV)", cell_s), Paragraph("Thin grey-white discharge, fishy odour, Amsel criteria ≥3/4", cell_s), Paragraph("≥4.5", cell_c), Paragraph("Clue cells", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("□ Confirmed □ Excluded", cell_c)], [Paragraph("Vulvovaginal Candidiasis", cell_s), Paragraph("Thick, curd-like, pruritus, vulvar erythema", cell_s), Paragraph("Normal (<4.5)", cell_c), Paragraph("Hyphae/spores on KOH", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("□ Confirmed □ Excluded", cell_c)], [Paragraph("Trichomoniasis", cell_s), Paragraph("Frothy yellow-green, malodorous, strawberry cervix", cell_s), Paragraph(">4.5", cell_c), Paragraph("Motile trichomonads", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("□ Confirmed □ Excluded", cell_c)], [Paragraph("Gonorrhoea / Chlamydia (Cervicitis)", cell_s), Paragraph("Mucopurulent, contact bleeding, cervical friability", cell_s), Paragraph("Variable", cell_c), Paragraph("WBCs, NAAT positive", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("□ Confirmed □ Excluded", cell_c)], [Paragraph("Atrophic Vaginitis", cell_s), Paragraph("Postmenopausal, thin vaginal walls, scanty discharge", cell_s), Paragraph(">4.5", cell_c), Paragraph("Parabasal cells", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("□ Confirmed □ Excluded", cell_c)], [Paragraph("Foreign Body / Retained Tampon", cell_s), Paragraph("Foul-smelling, recurrent, visualised on exam", cell_s), Paragraph("Variable", cell_c), Paragraph("Mixed flora", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("□ Confirmed □ Excluded", cell_c)], [Paragraph("Cervical Ectropion / Polyp", cell_s), Paragraph("Mucoid, usually non-malodorous, postcoital spotting", cell_s), Paragraph("Normal", cell_c), Paragraph("Normal", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("□ Confirmed □ Excluded", cell_c)], [Paragraph("PID (Pelvic Inflammatory Disease)", cell_s), Paragraph("Cervical motion tenderness, adnexal tenderness, fever", cell_s), Paragraph("Variable", cell_c), Paragraph("WBCs, endocervical discharge", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("□ Confirmed □ Excluded", cell_c)], [Paragraph("Cervical / Vaginal Malignancy", cell_s), Paragraph("Blood-tinged, watery, postcoital or postmenopausal bleeding", cell_s), Paragraph("Variable", cell_c), Paragraph("Atypical cells on cytology", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("□ Confirmed □ Excluded", cell_c)], ] cw6 = [(W-2*MARGIN)*0.22, (W-2*MARGIN)*0.28, (W-2*MARGIN)*0.07, (W-2*MARGIN)*0.17, (W-2*MARGIN)*0.12, (W-2*MARGIN)*0.14] table(dd_data, cw6, [ ("BACKGROUND", (0,0), (-1,0), TEAL), ("TEXTCOLOR", (0,0), (-1,0), WHITE), ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"), ("BACKGROUND", (0,2), (-1,2), GREEN_LIGHT), ("BACKGROUND", (0,3), (-1,3), AMBER), ("BACKGROUND", (0,4), (-1,4), RED_LIGHT), ]) # ───────────────────────────────────────────────────────────────────────────── # SECTION 7 — DIAGNOSIS & MANAGEMENT PLAN # ───────────────────────────────────────────────────────────────────────────── spacer(3) story.append(Paragraph("▌ SECTION 7: DIAGNOSIS & MANAGEMENT PLAN", style("Normal", fontSize=11, textColor=TEAL, fontName="Helvetica-Bold", leading=14))) spacer(2) mgmt_data = [ [Paragraph("Item", label_s), Paragraph("Details", label_s), Paragraph("Item", label_s), Paragraph("Details", label_s)], [Paragraph("Working Diagnosis", cell_s), Paragraph("_"*40, cell_s), Paragraph("Date of Diagnosis", cell_s), Paragraph("__/__/____", cell_s)], [Paragraph("Confirmed Diagnosis", cell_s), Paragraph("_"*40, cell_s), Paragraph("Diagnosing Clinician", cell_s), Paragraph("_"*28, cell_s)], [Paragraph("Treatment Prescribed", cell_s), Paragraph("Drug:________________ Dose:________ Route:______ Duration:______", cell_s), Paragraph("Prescription Date", cell_s), Paragraph("__/__/____", cell_s)], [Paragraph("2nd-Line / Alternative Rx", cell_s), Paragraph("Drug:________________ Dose:________ Route:______ Duration:______", cell_s), Paragraph("Reason for Change", cell_s), Paragraph("_"*28, cell_s)], [Paragraph("Partner Treatment", cell_s), Paragraph("□ Not indicated □ Notified □ Treated □ Declined", cell_s), Paragraph("Counselling Provided", cell_s), Paragraph("□ Safe sex □ Compliance □ Hygiene □ Abstinence", cell_s)], [Paragraph("Additional Referral", cell_s), Paragraph("□ Colposcopy □ STI clinic □ Gynaecology □ Oncology □ Other:__________", cell_s), Paragraph("Referral Date", cell_s), Paragraph("__/__/____", cell_s)], ] table(mgmt_data, cw, [ ("BACKGROUND", (0,0), (-1,0), TEAL), ("TEXTCOLOR", (0,0), (-1,0), WHITE), ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"), ]) # ───────────────────────────────────────────────────────────────────────────── # SECTION 8 — FOLLOW-UP TRACKING TABLE # ───────────────────────────────────────────────────────────────────────────── spacer(3) story.append(Paragraph("▌ SECTION 8: FOLLOW-UP VISIT LOG", style("Normal", fontSize=11, textColor=TEAL, fontName="Helvetica-Bold", leading=14))) spacer(2) fu_hdr = [ Paragraph("Visit #", label_s), Paragraph("Date", label_s), Paragraph("Symptom Change", label_s), Paragraph("Discharge Character", label_s), Paragraph("Exam Findings", label_s), Paragraph("Investigations", label_s), Paragraph("Rx / Adjustment", label_s), Paragraph("Clinician Sign.", label_s), ] fu_row = lambda n: [ Paragraph(str(n), cell_c), Paragraph("__/__/____", cell_c), Paragraph("□ Better □ Same □ Worse", cell_s), Paragraph("Colour:____ Odour:____ Vol:____", cell_s), Paragraph("_"*15, cell_s), Paragraph("_"*15, cell_s), Paragraph("_"*15, cell_s), Paragraph("_"*12, cell_s), ] fu_data = [fu_hdr] + [fu_row(i) for i in range(1, 7)] cw8 = [(W-2*MARGIN)*x for x in [0.06, 0.09, 0.14, 0.17, 0.14, 0.14, 0.14, 0.12]] table(fu_data, cw8, [ ("BACKGROUND", (0,0), (-1,0), TEAL), ("TEXTCOLOR", (0,0), (-1,0), WHITE), ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"), ], row_heights=[None] + [18]*6) # ───────────────────────────────────────────────────────────────────────────── # SECTION 9 — AMSEL CRITERIA SCORER # ───────────────────────────────────────────────────────────────────────────── spacer(3) story.append(Paragraph("▌ SECTION 9: AMSEL CRITERIA RAPID SCORER (Bacterial Vaginosis)", style("Normal", fontSize=11, textColor=TEAL, fontName="Helvetica-Bold", leading=14))) spacer(2) amsel_data = [ [Paragraph("Criterion", label_s), Paragraph("Present?", label_s), Paragraph("Notes", label_s)], [Paragraph("1. Homogeneous thin white / grey discharge", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("_"*35, cell_s)], [Paragraph("2. Vaginal pH ≥ 4.5", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("Measured pH: _______", cell_s)], [Paragraph("3. Positive whiff test (KOH — fishy odour)", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("_"*35, cell_s)], [Paragraph("4. Clue cells on microscopy (>20% epithelial cells)", cell_s), Paragraph("□ Yes □ No", cell_c), Paragraph("_"*35, cell_s)], [Paragraph("Total positive criteria (BV diagnosed if ≥ 3/4)", label_s), Paragraph(" / 4", cell_c), Paragraph("□ BV Diagnosed □ BV Not Diagnosed", cell_s)], ] cw9 = [(W-2*MARGIN)*0.50, (W-2*MARGIN)*0.16, (W-2*MARGIN)*0.34] table(amsel_data, cw9, [ ("BACKGROUND", (0,0), (-1,0), TEAL), ("TEXTCOLOR", (0,0), (-1,0), WHITE), ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"), ("BACKGROUND", (0,5), (-1,5), TEAL_LIGHT), ("FONTNAME", (0,5), (0,5), "Helvetica-Bold"), ]) # ───────────────────────────────────────────────────────────────────────────── # SECTION 10 — CLINICAL NOTES # ───────────────────────────────────────────────────────────────────────────── spacer(3) story.append(Paragraph("▌ SECTION 10: CLINICAL NOTES & ADDITIONAL OBSERVATIONS", style("Normal", fontSize=11, textColor=TEAL, fontName="Helvetica-Bold", leading=14))) spacer(2) notes_data = [ [Paragraph("Visit Date", label_s), Paragraph("SOAP Notes (Subjective / Objective / Assessment / Plan)", label_s)], ] + [ [Paragraph("__/__/____", cell_c), Paragraph("S: ___________________________ O: ___________________________ A: ___________________________ P: ___________________________", cell_s)] for _ in range(4) ] cw10 = [(W-2*MARGIN)*0.12, (W-2*MARGIN)*0.88] table(notes_data, cw10, [ ("BACKGROUND", (0,0), (-1,0), TEAL), ("TEXTCOLOR", (0,0), (-1,0), WHITE), ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"), ], row_heights=[None] + [28]*4) # ───────────────────────────────────────────────────────────────────────────── # LEGEND / NOTES BOX # ───────────────────────────────────────────────────────────────────────────── spacer(3) legend_data = [[ Paragraph( "<b>Reference Notes:</b> " "BV = Bacterial Vaginosis | KOH = Potassium Hydroxide prep | " "NAAT = Nucleic Acid Amplification Test | HVS = High Vaginal Swab | " "M/C/S = Microscopy, Culture & Sensitivity | STI = Sexually Transmitted Infection | " "PID = Pelvic Inflammatory Disease | OCP = Oral Contraceptive Pill | " "IUD = Intrauterine Device | RPR = Rapid Plasma Reagin | LMP = Last Menstrual Period", note_s) ]] t = Table(legend_data, colWidths=[W - 2*MARGIN]) t.setStyle(TableStyle([ ("BACKGROUND", (0,0), (-1,-1), TEAL_LIGHT), ("BOX", (0,0), (-1,-1), 0.8, TEAL), ("TOPPADDING", (0,0), (-1,-1), 5), ("BOTTOMPADDING",(0,0), (-1,-1), 5), ("LEFTPADDING", (0,0), (-1,-1), 6), ("RIGHTPADDING",(0,0), (-1,-1), 6), ])) story.append(t) # ── Build ───────────────────────────────────────────────────────────────────── doc.build(story) print("PDF created:", OUTPUT) PYEOF
leucorrhea case tracking chart
PDF Document · PDF
| Section | Content |
|---|---|
| 1 | Patient demographics & contact info |
| 2 | Obstetric & gynaecological history (LMP, G/P/A, contraception, prior STIs, Pap smear) |
| 3 | Discharge characterisation — colour, consistency, odour, volume, associated symptoms |
| 4 | Clinical examination findings (vulva, vagina, cervix, pH, whiff test, wet prep/microscopy) |
| 5 | Investigations log (HVS, NAAT, KOH prep, Pap smear, HIV, syphilis, pelvic US, urine) |
| 6 | Differential diagnosis checklist — BV, candidiasis, trichomoniasis, gonorrhoea/chlamydia, atrophic vaginitis, foreign body, cervical malignancy, PID with key distinguishing features |
| 7 | Diagnosis & management plan (1st and 2nd-line treatment, partner treatment, referrals) |
| 8 | 6-visit follow-up log (symptom change, discharge character, exam, investigations, Rx) |
| 9 | Amsel criteria rapid scorer for BV (tick-box, auto-scores ≥3/4) |
| 10 | SOAP-format clinical notes (4 visit slots) |