Case Study: Atrial Fibrillation Ablation Outcomes
This case study demonstrates how to use CDT to build a research cohort for studying stroke and TIA outcomes in patients with atrial fibrillation, comparing those who underwent catheter ablation versus medical management alone.
Research Question
"Is the incidence of stroke or transient ischemic attack (TIA) different between atrial fibrillation patients who underwent pulmonary vein isolation versus those managed medically?"
Extraction Strategy
To answer this question, we need to extract three concept types from clinical notes:
| Step | Concept Type | Purpose |
|---|---|---|
| 1. Cohort Selection | Atrial fibrillation | Identify eligible patients |
| 2. Subcohort Assignment | Pulmonary vein isolation / catheter ablation | Divide into PVI vs no-PVI groups |
| 3. Outcome Event | Stroke / TIA | Identify outcome events |
SNOMED CT Codes
Atrial Fibrillation (Cohort Selection)
| SNOMED CT Code | Term |
|---|---|
| 49436004 | Atrial fibrillation |
| 706923002 | Longstanding persistent atrial fibrillation |
| 282825002 | Paroxysmal atrial fibrillation |
| 440028005 | Permanent atrial fibrillation |
| 440059007 | Persistent atrial fibrillation |
Note
This list may not be exhaustive.
Ablation Procedure (Subcohort Assignment)
| SNOMED CT Code | Term |
|---|---|
| 1332525002 | Cardiac ablation for atrial fibrillation |
| 473229000 | Catheter ablation of arrhythmogenic focus |
| 18286008 | Catheter ablation of tissue of heart |
| 431626004 | Endocardial ablation of pulmonary vein using fluoroscopic guidance with contrast |
| 707831001 | Percutaneous transluminal ablation of pulmonary vein to left atrium conducting system |
| 1363214008 | Radiofrequency ablation operation on left atrium for arrhythmia |
| 1366473002 | Thoracoscopic bilateral video-assisted pulmonary vein isolation with excision of left atrial appendage |
Note
This list may not be exhaustive.
Outcome Events (TIA / Stroke)
| SNOMED CT Code | Term |
|---|---|
| 432504007 | Cerebral infarction |
| 230690007 | Cerebrovascular accident |
| 422504002 | Ischemic stroke |
| 266257000 | Transient ischemic attack |
Note
This list may not be exhaustive.
Example Clinical Notes
Below are three example clinical letters from different patients. In a real study, you would process hundreds or thousands of such notes.
Patient A - AF with ablation, subsequent TIA
Cardiology Follow-up - 15 March 2025
67-year-old male with history of paroxysmal atrial fibrillation diagnosed in
2021, hypertension, and hyperlipidemia. Patient underwent pulmonary vein
isolation in September 2023. Post-procedure, he remained
in sinus rhythm for 14 months on flecainide.
Presenting today after episode of right-sided weakness and slurred speech
lasting approximately 45 minutes yesterday, now fully resolved. MRI brain
shows no acute infarct. Assessment: Transient ischemic attack, likely
cardioembolic. Recommend resuming anticoagulation with apixaban.
Patient B - AF with ablation, no events
Electrophysiology Clinic - 20 March 2025
54-year-old female with persistent atrial fibrillation, status post catheter
ablation with pulmonary vein isolation in June 2024. She reports no
palpitations or symptoms of arrhythmia recurrence. Holter monitor shows
sinus rhythm throughout. No thromboembolic events.
Impression: Successful ablation outcome. Continue rate control medications.
Discontinue anticoagulation given CHA2DS2-VASc score of 1. Follow-up in
12 months.
Patient C - AF without ablation (medical management)
Cardiology Outpatient Letter - 10 March 2025
71-year-old female with long-standing persistent atrial fibrillation managed
with rate control strategy. Comorbidities include heart failure with preserved
ejection fraction, type 2 diabetes, and chronic kidney disease stage 3.
Patient declined catheter ablation due to procedural concerns.
Currently on metoprolol for rate control and rivaroxaban for stroke
prevention. Remains in atrial fibrillation with controlled ventricular rate.
No history of stroke or TIA. Continue current management.
Processing Notes with CDT
Submit each clinical note to the API:
curl -X POST "https://cdt-beta.healthsage.ai/generate" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"note": "67-year-old male with history of paroxysmal atrial fibrillation...",
"specialty": "Cardiology",
"letter_date": "2025-03-15"
}'
Response:
Retrieve results once processing completes:
curl "https://cdt-beta.healthsage.ai/tasks/a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
-H "X-API-Key: YOUR_API_KEY"
Example API Response (Patient A)
{
"task_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "SUCCESS",
"letter_date": "2025-03-15",
"patient_dob": null,
// ...
"json_data": {
"extractions": [
{
"id": "44a6ceb4-953b-4dbf-a317-784d4c9203e9",
"snomed_ct_code": "282825002",
"snomed_ct_term": "Paroxysmal atrial fibrillation (disorder)",
"concept_type": "disorder",
"status": "confirmed",
"date": "2021",
"end_date": null,
"location": null,
"source": "paroxysmal atrial fibrillation",
"start": 71,
"end": 101
},
{
"id": "be5a3e72-1944-4a0b-8023-21d3ba28c119",
"snomed_ct_code": "38341003",
"snomed_ct_term": "Hypertensive disorder, systemic arterial (disorder)",
"concept_type": "disorder",
"status": "confirmed",
"date": null,
"end_date": null,
"location": null,
"source": "hypertension",
"start": 121,
"end": 133
},
{
"id": "5341d36c-453b-46f4-bc90-0bef69295dcb",
"snomed_ct_code": "55822004",
"snomed_ct_term": "Hyperlipidaemia",
"concept_type": "disorder",
"status": "confirmed",
"date": null,
"end_date": null,
"location": null,
"source": "hyperlipidemia",
"start": 139,
"end": 153
},
{
"id": "a78d1d1f-f6a2-45ba-8cd0-4ff933745630",
"snomed_ct_code": "707831001",
"snomed_ct_term": "Percutaneous transluminal ablation of pulmonary vein to left atrium conducting system",
"concept_type": "procedure",
"status": "confirmed",
"date": "2023-09",
"end_date": null,
"location": null,
"source": "pulmonary vein\nisolation",
"start": 173,
"end": 197
},
{
"id": "c3459bbb-d70f-4f33-9252-a668787ceea1",
"snomed_ct_code": "278286009",
"snomed_ct_term": "Right hemiparesis (disorder)",
"concept_type": "disorder",
"status": "confirmed",
"date": "2025-03-14",
"end_date": "2025-03-14",
"location": "right",
"source": "right-sided weakness",
"start": 325,
"end": 345
},
{
"id": "b8b044d0-71ad-41da-90c1-737504725825",
"snomed_ct_code": "289195008",
"snomed_ct_term": "Slurred speech (finding)",
"concept_type": "finding",
"status": "confirmed",
"date": "2025-03-14",
"end_date": "2025-03-14",
"location": null,
"source": "slurred speech",
"start": 350,
"end": 364,
},
{
"id": "ffa08d7d-011e-481e-acd0-54b223f1ab33",
"snomed_ct_code": "816077007",
"snomed_ct_term": "MRI of brain",
"concept_type": "procedure",
"status": "confirmed",
"date": "2025-03-15",
"end_date": null,
"location": null,
"source": "MRI brain",
"start": 451,
"end": 460
},
{
"id": "0a3d4630-03eb-4ed3-8a28-505f1b56be0d",
"snomed_ct_code": "266257000",
"snomed_ct_term": "Transient ischemic attack (disorder)",
"concept_type": "disorder",
"status": "confirmed",
"date": "2025-03-14",
"end_date": "2025-03-14",
"location": "right",
"source": "Transient ischemic attack",
"start": 475,
"end": 500,
},
{
"id": "7ee71ddc-2bb8-4df0-9a0d-4e78c5653c37",
"snomed_ct_code": "1251566005",
"snomed_ct_term": "Embolism from heart",
"concept_type": "disorder",
"status": "provisional",
"date": "2025-03-14",
"end_date": null,
"location": null,
"source": "cardioembolic",
"start": 509,
"end": 522,
}
],
"specialty": "Cardiology",
"snomed_ct_version": "2026-01-01"
},
// ...
}
Processing API Responses
To process the API responses, we can extract the relevant concept and format them as follows:
from typing import Any
from pydantic import BaseModel
AF_CODES = [
"49436004", # Atrial fibrillation
"706923002", # Longstanding persistent atrial fibrillation
"282825002", # Paroxysmal atrial fibrillation
"440028005", # Permanent atrial fibrillation
"440059007", # Persistent atrial fibrillation
]
ABLATION_CODES = [
"1332525002", # Cardiac ablation for atrial fibrillation
"473229000", # Catheter ablation of arrhythmogenic focus
"18286008", # Catheter ablation of tissue of heart
"431626004", # Endocardial ablation of pulmonary vein
"707831001", # Percutaneous transluminal ablation of pulmonary vein
"1363214008", # Radiofrequency ablation on left atrium
"1366473002", # Thoracoscopic bilateral video-assisted PVI
]
OUTCOME_CODES = [
"432504007", # Cerebral infarction
"230690007", # Cerebrovascular accident
"422504002", # Ischemic stroke
"266257000", # Transient ischemic attack
]
class PatientData(BaseModel):
patient_id: str
has_af: bool
has_pvi: bool
pvi_date: str | None
has_outcome: bool
outcome_date: str | None
def process_patient_response(patient_id: str, response: dict[str, Any]) -> PatientData:
"""Extract study-relevant data from a CDT API response."""
extractions = response["json_data"]["extractions"]
# Check for AF diagnosis (cohort inclusion)
has_af = any(
e["snomed_ct_code"] in AF_CODES
for e in extractions
)
# Find ablation procedure and date (subcohort assignment)
ablation = next(
(e for e in extractions if e["snomed_ct_code"] in ABLATION_CODES),
None
)
# Check for TIA or stroke outcome
outcome = next(
(e for e in extractions if e["snomed_ct_code"] in OUTCOME_CODES),
None
)
return PatientData(
patient_id=patient_id,
has_af=has_af,
has_pvi=ablation is not None,
pvi_date=ablation["date"] if ablation else None,
has_outcome=outcome is not None,
outcome_date=outcome["date"] if outcome else None
)
patient_A_data = process_patient_response("A", patient_A_response)
patient_B_data = process_patient_response("B", patient_B_response)
patient_C_data = process_patient_response("C", patient_C_response)
records = [patient_A_data.model_dump(), patient_B_data.model_dump(), patient_C_data.model_dump()]
df = pd.DataFrame(records)
This will produce something of the form:
| patient_id | has_af | has_pvi | pvi_date | has_outcome | outcome_date |
|---|---|---|---|---|---|
| A | True | True | 2023-09 | True | 2025-03-14 |
| B | True | True | 2024-06 | False | N/A |
| C | True | False | N/A | False | N/A |
Suggested Analyses
With a sufficiently large cohort, the structured table above enables several analyses:
- Incidence comparison: Compare the proportion of stroke/TIA events (
has_outcome) between the PVI group (has_pvi = True) and the medical management group (has_pvi = False). - Time-to-event analysis: Using
pvi_dateandoutcome_date, compute time from ablation to outcome and construct Kaplan-Meier survival curves with a log-rank test comparing the two groups. - Cox proportional hazards model: Model the hazard of stroke/TIA as a function of PVI status, adjusting for covariates that could be extracted from additional CDT fields (e.g., comorbidities).