Cookbook 347: Offline Clinical Urology NMIBC EAU Risk Stratification & BCG Unresponsive Engine

This cookbook details how to deploy a localized, containerized urology, urologic oncology, and endourology decision-support engine for outpatient urology clinics, cystoscopy surveillance suites, and surgical oncology tumor boards to ingest transurethral resection of bladder tumor ($\text{TURBT}$) histopathology, tumor multifocality and diameter metrics, carcinoma in situ ($\text{CIS}$) status, prior intravesical immunotherapy chronologies, and recurrence intervals, classify tumors according to the Revised EAU 2024 & AUA / SUO NMIBC Risk Stratification (Low, Intermediate, High, Very High Risk), generate SWOG 8507 Intravesical Bacillus Calmette-Guérin ($\text{BCG}$) Induction & 3-Year Maintenance Schedules, audit FDA / AUA BCG-Unresponsive Status, guide Second-Line Salvage Therapy (Early Radical Cystectomy vs Sequential Gemcitabine-Docetaxel vs Pembrolizumab vs Nadofaragene Firadenovec vs Nogapendekin Alfa Inbakicept), and enforce the BCG Mycobacterial Sepsis Absolute Contraindication Sentinel according to European Association of Urology ($\text{EAU 2024}$), AUA / SUO, and NCCN consensus guidelines without external cloud API reliance.


1. Clinical Background & Urologic Oncology Architecture

Non-Muscle Invasive Bladder Cancer ($\text{NMIBC}$), comprising stages $\text{Ta}$, $\text{T1}$, and $\text{CIS}$, accounts for $75 - 80\%$ of newly diagnosed urothelial carcinomas of the bladder:


2. Pipeline & Workflow Architecture

[Patient Telemetry: TURBT Histology, T-Stage, Grade, CIS, Size, LVI, Prior BCG Doses]
                                         │
                                         â–¼
      [EAU 2024 & AUA Risk Stratifier: Low vs Intermediate vs High vs Very High Risk]
                                         │
                                         â–¼
      [Adequate BCG Assessment: Evaluates Induction >= 5/6 + Maintenance >= 2/3 Doses]
                                         │
                                         â–¼
      [FDA/AUA BCG-Unresponsive Classifier: Persistent CIS <= 12m or HG Ta/T1 <= 6m]
                                         │
                                         â–¼
      [Salvage Strategy Generator: Early Radical Cystectomy vs Gem/Doce vs Pembrolizumab]
                                         │
                                         â–¼
      [BCG Sepsis Absolute Contraindication Sentinel: Hematuria/Trauma/Early Post-Op Gate]

3. Environment & Prerequisites

Install required scientific Python and urologic oncology modeling packages:

pip install numpy scipy pandas torch torchvision matplotlib

4. Complete Offline Python / PyTorch Implementation

"""
Cookbook 347: Offline Urology NMIBC EAU Risk Stratification & BCG Unresponsive Engine
OpenPHR Clinical AI Working Group (https://openphr.org)
"""

import math
import numpy as np
import pandas as pd
from typing import Dict, List, Tuple, Optional
from dataclasses import dataclass

@dataclass
class NMIBCPatientTelemetry:
    patient_id: str
    age_years: float = 68.0
    sex: str = "Male"
    # TURBT Pathological & Cystoscopic Telemetry
    t_stage: str = "T1" # "Ta", "T1"
    who_grade: str = "High Grade (HG)" # "Low Grade (LG)", "High Grade (HG)"
    carcinoma_in_situ_present: bool = True # Concurrent or isolated CIS
    tumor_diameter_cm: float = 3.5 # >= 3.0 cm is high risk
    is_multifocal: bool = True # >= 3 tumors
    lymphovascular_invasion_present: bool = True # LVI = Very High Risk!
    variant_histology_present: bool = False # e.g. Micropapillary, Plasmacytoid, Nested
    prostatic_urethra_involvement: bool = False
    # Intravesical BCG Exposure Telemetry
    prior_bcg_induction_doses: int = 6 # Completed 6/6 induction
    prior_bcg_maintenance_doses: int = 3 # Completed 3/3 maintenance cycle #1 (Adequate BCG!)
    months_since_last_bcg_exposure: float = 5.0 # Recurrence at 5 months post-BCG
    current_cystoscopy_finding: str = "Persistent High-Grade T1 + CIS"
    # Safety Telemetry on Day of Planned Instillation
    gross_hematuria_present: bool = False
    traumatic_catheterization_today: bool = False
    days_since_turbt_resection: int = 24 # > 14 days (Safe mucosal healing)

@dataclass
class NMIBCEvaluationReport:
    patient_id: str
    eau_2024_risk_category: str # "VERY HIGH RISK NMIBC"
    aua_suo_risk_category: str # "High Risk"
    risk_factors_detected: List[str]
    bcg_unresponsive_status: str # "🚨 CONFIRMED BCG-UNRESPONSIVE NMIBC (FDA / AUA Definition Met)"
    treatment_recommendations: List[str]
    safety_sentinels: List[str]
    clinical_eau_aua_directive: str

class NMIBCDecisionEngine:
    """
    Offline clinical engine for EAU 2024 / AUA risk stratification,
    BCG-unresponsive classification, and second-line salvage gating.
    """

    def stratify_eau_risk(self, d: NMIBCPatientTelemetry) -> Tuple[str, str, List[str]]:
        factors = []

        is_t1 = d.t_stage == "T1"
        is_hg = "High Grade" in d.who_grade
        has_cis = d.carcinoma_in_situ_present
        is_large = d.tumor_diameter_cm >= 3.0
        is_multi = d.is_multifocal
        has_lvi = d.lymphovascular_invasion_present
        has_variant = d.variant_histology_present
        has_prostate = d.prostatic_urethra_involvement

        if has_lvi: factors.append("Lymphovascular invasion (LVI) present")
        if has_variant: factors.append("Variant urothelial histology (micropapillary/plasmacytoid)")
        if has_cis: factors.append("Carcinoma in Situ (CIS) present")
        if is_t1 and is_hg: factors.append("T1 High-Grade invasive tumor")
        if is_large: factors.append(f"Large tumor diameter ({d.tumor_diameter_cm:.1f} cm >= 3.0 cm)")
        if is_multi: factors.append("Multifocal tumor burden")

        # 1. Very High Risk (EAU 2024)
        if (is_t1 and is_hg and has_cis) or has_lvi or has_variant or (is_t1 and is_hg and (is_large or is_multi)) or has_prostate:
            eau_risk = "VERY HIGH RISK NMIBC"
            aua_risk = "High Risk NMIBC"
        # 2. High Risk (EAU 2024)
        elif (is_t1 and is_hg) or has_cis or (not is_t1 and is_hg and (is_large or is_multi)):
            eau_risk = "HIGH RISK NMIBC"
            aua_risk = "High Risk NMIBC"
        # 3. Intermediate Risk
        elif is_large or is_multi or (not is_t1 and is_hg and not is_large and not is_multi):
            eau_risk = "INTERMEDIATE RISK NMIBC"
            aua_risk = "Intermediate Risk NMIBC"
        # 4. Low Risk
        else:
            eau_risk = "LOW RISK NMIBC"
            aua_risk = "Low Risk NMIBC"

        return eau_risk, aua_risk, factors

    def evaluate_bcg_unresponsive_status(self, d: NMIBCPatientTelemetry) -> str:
        received_adequate_bcg = (d.prior_bcg_induction_doses >= 5 and d.prior_bcg_maintenance_doses >= 2) or (d.prior_bcg_induction_doses >= 10)

        if not received_adequate_bcg:
            return "BCG Incomplete / Inadequate Exposure (< 5/6 induction or < 2/3 maintenance). Does not meet BCG-unresponsive criteria."

        is_hg = "High Grade" in d.who_grade or "CIS" in d.current_cystoscopy_finding
        has_cis = d.carcinoma_in_situ_present or "CIS" in d.current_cystoscopy_finding

        if has_cis and d.months_since_last_bcg_exposure <= 12.0:
            return f"🚨 CONFIRMED BCG-UNRESPONSIVE NMIBC: Persistent/recurrent CIS at {d.months_since_last_bcg_exposure:.0f} months following adequate BCG (FDA/AUA Definition Met)."
        elif is_hg and d.months_since_last_bcg_exposure <= 6.0:
            return f"🚨 CONFIRMED BCG-UNRESPONSIVE NMIBC: Recurrent High-Grade Ta/T1 tumor at {d.months_since_last_bcg_exposure:.0f} months following adequate BCG (FDA/AUA Definition Met)."
        elif d.months_since_last_bcg_exposure > 12.0 and is_hg:
            return f"Late High-Grade BCG Relapse ({d.months_since_last_bcg_exposure:.0f} months). May consider repeat BCG challenge vs salvage therapy."
        else:
            return "BCG-Responsive / No Active Failure."

    def generate_treatment_plan(self, eau_risk: str, bcg_status: str, d: NMIBCPatientTelemetry) -> Tuple[List[str], List[str]]:
        plan = []
        sentinels = []

        # Safety Sentinel: BCG Sepsis Risk on Day of Instillation
        if d.gross_hematuria_present or d.traumatic_catheterization_today or d.days_since_turbt_resection < 14:
            sentinels.append("🚨 ABSOLUTE BCG CONTRAINDICATION: Instilling BCG in the presence of gross hematuria, traumatic catheterization, or early post-TURBT (< 2 weeks) causes systemic intravasation of live Mycobacterium bovis resulting in FATAL MYCOBACTERIAL SEPSIS & SHOCK. STAT CANCEL/POSTPONE BCG INSTILLATION!")

        # Treatment Strategy
        if "CONFIRMED BCG-UNRESPONSIVE" in bcg_status or "VERY HIGH RISK" in eau_risk:
            plan.append("1. PRIMARY FIRST-LINE RECOMMENDATION: EARLY RADICAL CYSTECTOMY with Bilateral Pelvic Lymphadenectomy (Offers >80-90% cure before muscle invasion).")
            plan.append("2. BLADDER-PRESERVATION SECOND-LINE SALVAGE (If cystectomy ineligible or patient refuses):")
            plan.append("   • OPTION A: Sequential Intravesical Gemcitabine (1.0g in 50mL x 90 min) + Docetaxel (37.5mg in 50mL x 120 min) weekly x 6 induction, then monthly maintenance.")
            plan.append("   • OPTION B (FDA Approved for CIS): IV Pembrolizumab 200 mg q3w (or 400 mg q6w) for up to 24 months.")
            plan.append("   • OPTION C (Gene Therapy): Intravesical Nadofaragene Firadenovec (Adstiladrin 75 mL) once every 3 months.")
            plan.append("   • OPTION D: Nogapendekin Alfa Inbakicept (Anktiva 400 mcg) + BCG intravesical weekly x 6, then maintenance.")
        elif "HIGH RISK" in eau_risk:
            plan.append("1. FULL-DOSE INTRAVESICAL BCG IMMUNOTHERAPY (SWOG 8507 Protocol):")
            plan.append("   • Induction: 6 weekly instillations initiated 2-4 weeks post-TURBT.")
            plan.append("   • 3-Year Maintenance: 3 weekly instillations at Months 3, 6, 12, 18, 24, 30, and 36.")
        elif "INTERMEDIATE RISK" in eau_risk:
            plan.append("1. Intravesical Chemotherapy (e.g. Mitomycin C or Gemcitabine) or BCG for 1 year.")
        else:
            plan.append("1. Single immediate post-operative instillation of intravesical chemotherapy (Gemcitabine 2.0g) within 6 hours of TURBT; no maintenance needed.")

        return plan, sentinels

    def evaluate_case(self, data: NMIBCPatientTelemetry) -> NMIBCEvaluationReport:
        eau_risk, aua_risk, factors = self.stratify_eau_risk(data)
        bcg_status = self.evaluate_bcg_unresponsive_status(data)
        rx_plan, sentinels = self.generate_treatment_plan(eau_risk, bcg_status, data)

        directives = []
        directives.append(f"STRATIFICATION: {eau_risk} ({aua_risk}).")
        directives.append(f"BCG STATUS: {bcg_status}.")
        directives.append("RECOMMENDATION: Early radical cystectomy vs sequential Gemcitabine-Docetaxel salvage.")

        return NMIBCEvaluationReport(
            patient_id=data.patient_id,
            eau_2024_risk_category=eau_risk,
            aua_suo_risk_category=aua_risk,
            risk_factors_detected=factors,
            bcg_unresponsive_status=bcg_status,
            treatment_recommendations=rx_plan,
            safety_sentinels=sentinels,
            clinical_eau_aua_directive=" ".join(directives)
        )

# Example Execution & Verification
if __name__ == "__main__":
    engine = NMIBCDecisionEngine()

    print("=" * 80)
    print("OpenPHR Clinical Urology NMIBC EAU Risk & BCG Unresponsive Engine")
    print("=" * 80)

    # Test Case 1: 68-year-old male with recurrent High-Grade T1 bladder cancer + CIS + LVI (Very High Risk).
    # Prior BCG: Completed 6/6 induction + 3/3 maintenance (Adequate BCG).
    # Recurrence: High-Grade T1 + CIS at 5 months post-BCG -> CONFIRMED BCG-UNRESPONSIVE!
    # Triage: Early Radical Cystectomy vs Sequential Gemcitabine-Docetaxel / Pembrolizumab / Adstiladrin!
    nmibc1 = NMIBCPatientTelemetry(
        patient_id="URO-NMIBC-8801",
        age_years=68.0,
        t_stage="T1",
        who_grade="High Grade (HG)",
        carcinoma_in_situ_present=True,
        tumor_diameter_cm=3.5,
        is_multifocal=True,
        lymphovascular_invasion_present=True,
        variant_histology_present=False,
        prior_bcg_induction_doses=6,
        prior_bcg_maintenance_doses=3,
        months_since_last_bcg_exposure=5.0,
        current_cystoscopy_finding="Persistent High-Grade T1 + CIS",
        gross_hematuria_present=False,
        traumatic_catheterization_today=False,
        days_since_turbt_resection=24
    )

    rep1 = engine.evaluate_case(nmibc1)

    print(f"\n[Patient {rep1.patient_id} - Urologic Oncology Assessment]")
    print(f"EAU 2024 Risk Category: {rep1.eau_2024_risk_category}")
    print(f"AUA / SUO Risk Category: {rep1.aua_suo_risk_category}")
    print("\nRisk Factors Detected:")
    for rf in rep1.risk_factors_detected:
        print(f"  • {rf}")
    print(f"\nBCG Response Status:\n  {rep1.bcg_unresponsive_status}")
    print("\nTherapeutic Recommendations:")
    for rx in rep1.treatment_recommendations:
        print(f"  {rx}")
    if rep1.safety_sentinels:
        print("\nSafety Sentinels:")
        for s in rep1.safety_sentinels:
            print(f"  🚨 {s}")
    print(f"\nEAU / AUA Consensus Directive:\n{rep1.clinical_eau_aua_directive}")

5. Clinical Verification & Guideline Conformance


6. References