Download sapbert_core/src/preprocessing/acronym_expander.py from gitmodelmujtaba/medical-guidelines-kg: direct link, hf CLI and curl.
- Browser
- Download file 10.3 kB
-
https://huggingface.co/spaces/gitmodelmujtaba/medical-guidelines-kg/resolve/main/sapbert_core/src/preprocessing/acronym_expander.py
- Command line
-
hf download hf://spaces/gitmodelmujtaba/medical-guidelines-kg/sapbert_core/src/preprocessing/acronym_expander.py
-
curl -L -o acronym_expander.py https://huggingface.co/spaces/gitmodelmujtaba/medical-guidelines-kg/resolve/main/sapbert_core/src/preprocessing/acronym_expander.py
10.3 kB
| """ | |
| Clinical Acronym and Abbreviation Expansion Engine. | |
| Provides high-coverage clinical abbreviation normalization, context-sensitive | |
| disambiguation, and query augmentation across SNOMED CT, LOINC, and RxNorm domains. | |
| """ | |
| import re | |
| from typing import Dict, List, Optional, Tuple | |
| # Core clinical abbreviation mappings: Acronym -> Canonical Expansion | |
| CLINICAL_ACRONYMS: Dict[str, str] = { | |
| # Cardiovascular | |
| "HTN": "Hypertension", | |
| "CAD": "Coronary artery disease", | |
| "CABG": "Coronary artery bypass graft", | |
| "CHF": "Congestive heart failure", | |
| "HF": "Heart failure", | |
| "HFpEF": "Heart failure with preserved ejection fraction", | |
| "HFrEF": "Heart failure with reduced ejection fraction", | |
| "AF": "Atrial fibrillation", | |
| "AFIB": "Atrial fibrillation", | |
| "A-FIB": "Atrial fibrillation", | |
| "AFL": "Atrial flutter", | |
| "STEMI": "ST elevation myocardial infarction", | |
| "NSTEMI": "Non-ST elevation myocardial infarction", | |
| "SVT": "Supraventricular tachycardia", | |
| "VT": "Ventricular tachycardia", | |
| "VF": "Ventricular fibrillation", | |
| "DVT": "Deep vein thrombosis", | |
| "PAD": "Peripheral artery disease", | |
| "PVD": "Peripheral vascular disease", | |
| "AAA": "Abdominal aortic aneurysm", | |
| "AS": "Aortic valve stenosis", | |
| "AR": "Aortic regurgitation", | |
| "MR": "Mitral regurgitation", | |
| # Respiratory | |
| "COPD": "Chronic obstructive pulmonary disease", | |
| "SOB": "Shortness of breath", | |
| "DOE": "Dyspnea on exertion", | |
| "URI": "Upper respiratory infection", | |
| "OSA": "Obstructive sleep apnea", | |
| "ARDS": "Acute respiratory distress syndrome", | |
| "PNA": "Pneumonia", | |
| "CAP": "Community acquired pneumonia", | |
| "HAP": "Hospital acquired pneumonia", | |
| "CF": "Cystic fibrosis", | |
| "ILD": "Interstitial lung disease", | |
| "IPF": "Idiopathic pulmonary fibrosis", | |
| # Endocrine & Metabolic | |
| "DM": "Diabetes mellitus", | |
| "DM1": "Type 1 diabetes mellitus", | |
| "T1DM": "Type 1 diabetes mellitus", | |
| "DM2": "Type 2 diabetes mellitus", | |
| "T2DM": "Type 2 diabetes mellitus", | |
| "DKA": "Diabetic ketoacidosis", | |
| "HHS": "Hyperosmolar hyperglycemic state", | |
| "HTG": "Hypertriglyceridemia", | |
| "HLD": "Hyperlipidemia", | |
| "PCOS": "Polycystic ovary syndrome", | |
| # Nephrology & Urology | |
| "AKI": "Acute kidney injury", | |
| "CKD": "Chronic kidney disease", | |
| "ESRD": "End stage renal disease", | |
| "UTI": "Urinary tract infection", | |
| "BPH": "Benign prostatic hyperplasia", | |
| "ATN": "Acute tubular necrosis", | |
| "GN": "Glomerulonephritis", | |
| # Neurological | |
| "CVA": "Cerebrovascular accident", | |
| "TIA": "Transient ischemic attack", | |
| "ICH": "Intracerebral hemorrhage", | |
| "SAH": "Subarachnoid hemorrhage", | |
| "SDH": "Subdural hematoma", | |
| "ALS": "Amyotrophic lateral sclerosis", | |
| "PD": "Parkinson's disease", | |
| "AD": "Alzheimer's disease", | |
| "ICP": "Intracranial pressure", | |
| # Gastrointestinal | |
| "GERD": "Gastroesophageal reflux disease", | |
| "IBD": "Inflammatory bowel disease", | |
| "IBS": "Irritable bowel syndrome", | |
| "PUD": "Peptic ulcer disease", | |
| "UGIB": "Upper gastrointestinal bleeding", | |
| "LGIB": "Lower gastrointestinal bleeding", | |
| "SBO": "Small bowel obstruction", | |
| "LBO": "Large bowel obstruction", | |
| "NASH": "Nonalcoholic steatohepatitis", | |
| "NAFLD": "Nonalcoholic fatty liver disease", | |
| # Rheumatology & Infectious Disease | |
| "RA": "Rheumatoid arthritis", | |
| "OA": "Osteoarthritis", | |
| "SLE": "Systemic lupus erythematosus", | |
| "HIV": "Human immunodeficiency virus infection", | |
| "AIDS": "Acquired immunodeficiency syndrome", | |
| "TB": "Tuberculosis", | |
| "MRSA": "Methicillin resistant Staphylococcus aureus", | |
| "MSSA": "Methicillin susceptible Staphylococcus aureus", | |
| "C. DIFF": "Clostridioides difficile infection", | |
| "CDIFF": "Clostridioides difficile infection", | |
| # Common Labs (LOINC domain) | |
| "CBC": "Complete blood count", | |
| "BMP": "Basic metabolic panel", | |
| "CMP": "Comprehensive metabolic panel", | |
| "LFT": "Liver function tests", | |
| "HGB": "Hemoglobin", | |
| "HB": "Hemoglobin", | |
| "HCT": "Hematocrit", | |
| "WBC": "White blood cell count", | |
| "RBC": "Red blood cell count", | |
| "PLT": "Platelet count", | |
| "INR": "International normalized ratio", | |
| "PT": "Prothrombin time", | |
| "PTT": "Partial thromboplastin time", | |
| "CR": "Creatinine", | |
| "BUN": "Blood urea nitrogen", | |
| "HBA1C": "Hemoglobin A1c", | |
| "A1C": "Hemoglobin A1c", | |
| "TSH": "Thyroid stimulating hormone", | |
| "ESR": "Erythrocyte sedimentation rate", | |
| "CRP": "C-reactive protein", | |
| "BNP": "B-type natriuretic peptide", | |
| "UA": "Urinalysis", | |
| # Procedures & Diagnostics | |
| "EGD": "Esophagogastroduodenoscopy", | |
| "CXR": "Chest X-ray", | |
| "CT": "Computed tomography", | |
| "CTA": "Computed tomography angiography", | |
| "MRI": "Magnetic resonance imaging", | |
| "MRA": "Magnetic resonance angiography", | |
| "ECHO": "Echocardiogram", | |
| "EKG": "Electrocardiogram", | |
| "ECG": "Electrocardiogram", | |
| "US": "Ultrasound", | |
| "LP": "Lumbar puncture", | |
| } | |
| # Context-dependent disambiguation rules: | |
| # Acronym -> List of (ContextKeywords, DisambiguatedExpansion) | |
| CONTEXT_DISAMBIGUATION_RULES: Dict[str, List[Tuple[List[str], str]]] = { | |
| "MS": [ | |
| (["valve", "mitral", "murmur", "stenosis", "rheumatic", "cardiac", "heart"], "Mitral valve stenosis"), | |
| (["sclerosis", "demyelinating", "relapse", "flare", "neurologic", "mri", "brain", "spine", "optic"], "Multiple sclerosis"), | |
| (["mental", "status", "alert", "oriented", "confused"], "Mental status"), | |
| ], | |
| "MI": [ | |
| (["chest", "pain", "troponin", "stemi", "nstemi", "cardiac", "coronary", "ecg", "ekg"], "Myocardial infarction"), | |
| (["mitral", "insufficiency", "valve", "regurgitation", "murmur"], "Mitral valve insufficiency"), | |
| ], | |
| "PE": [ | |
| (["chest", "pain", "shortness", "breath", "d-dimer", "cta", "thrombus", "embolism", "clot", "dvt", "lung"], "Pulmonary embolism"), | |
| (["exam", "physical", "vital", "abdomen", "extremities", "heent", "neuro", "pupils", "clear"], "Physical examination"), | |
| (["effusion", "pleural", "thoracentesis", "fluid"], "Pleural effusion"), | |
| ], | |
| "MR": [ | |
| (["valve", "mitral", "regurgitation", "systolic", "murmur", "cardiac"], "Mitral regurgitation"), | |
| (["retardation", "mental", "intellectual"], "Mental retardation"), | |
| (["resonance", "magnetic", "scan", "imaging"], "Magnetic resonance"), | |
| ], | |
| "AS": [ | |
| (["valve", "aortic", "stenosis", "systolic", "murmur", "cardiac", "tavr", "echo"], "Aortic valve stenosis"), | |
| (["ankylosing", "spondylitis", "hla-b27", "back", "sacroiliac"], "Ankylosing spondylitis"), | |
| ], | |
| "RA": [ | |
| (["arthritis", "rheumatoid", "joint", "swelling", "rf", "anti-ccp", "methotrexate"], "Rheumatoid arthritis"), | |
| (["atrium", "right", "atrial", "cardiac", "enlargement"], "Right atrium"), | |
| ], | |
| "PT": [ | |
| (["inr", "prothrombin", "coagulation", "warfarin", "bleeding"], "Prothrombin time"), | |
| (["physical", "therapy", "rehab", "ambulation", "gait", "exercises"], "Physical therapy"), | |
| (["patient"], "Patient"), | |
| ], | |
| } | |
| class ClinicalAcronymExpander: | |
| """ | |
| Normalizes clinical shorthand and expands domain acronyms | |
| into fully qualified medical terminology. | |
| """ | |
| def __init__(self, custom_dict: Optional[Dict[str, str]] = None): | |
| self.lexicon = dict(CLINICAL_ACRONYMS) | |
| if custom_dict: | |
| self.lexicon.update(custom_dict) | |
| self.context_rules = dict(CONTEXT_DISAMBIGUATION_RULES) | |
| def disambiguate(self, acronym: str, context: Optional[str] = None) -> Optional[str]: | |
| """ | |
| Disambiguates an acronym using contextual note keywords if ambiguous. | |
| """ | |
| acr_upper = acronym.strip().upper() | |
| if acr_upper in self.context_rules: | |
| if context: | |
| context_lower = context.lower() | |
| best_expansion = None | |
| max_matches = 0 | |
| for keywords, expansion in self.context_rules[acr_upper]: | |
| matches = sum(1 for kw in keywords if re.search(rf"\b{re.escape(kw)}\b", context_lower)) | |
| if matches > max_matches: | |
| max_matches = matches | |
| best_expansion = expansion | |
| if best_expansion and max_matches > 0: | |
| return best_expansion | |
| # Default to first expansion if no context matched | |
| return self.context_rules[acr_upper][0][1] | |
| return self.lexicon.get(acr_upper, None) | |
| def expand_mention(self, mention: str, context: Optional[str] = None) -> str: | |
| """ | |
| Expands a standalone clinical mention string if it is an acronym, | |
| or returns the original mention if not recognized. | |
| """ | |
| cleaned = mention.strip() | |
| cleaned_upper = cleaned.upper() | |
| expansion = self.disambiguate(cleaned_upper, context) | |
| if expansion: | |
| return expansion | |
| return cleaned | |
| def get_search_queries(self, mention: str, context: Optional[str] = None) -> List[str]: | |
| """ | |
| Generates enriched search query representations for retrieval: | |
| e.g. ['HTN', 'Hypertension', 'HTN (Hypertension)'] | |
| """ | |
| cleaned = mention.strip() | |
| expansion = self.disambiguate(cleaned, context) | |
| queries = [cleaned] | |
| if expansion and expansion.lower() != cleaned.lower(): | |
| queries.append(expansion) | |
| queries.append(f"{cleaned} ({expansion})") | |
| return list(dict.fromkeys(queries)) | |
| def normalize_text_acronyms(self, text: str) -> str: | |
| """ | |
| Scans a clinical narrative for known unambiguous uppercase acronyms | |
| and attaches their expansions inline: e.g. 'c/o SOB' -> 'c/o SOB (Shortness of breath)' | |
| """ | |
| def replace_fn(match): | |
| word = match.group(0) | |
| word_upper = word.upper() | |
| if word_upper in self.lexicon and word_upper not in self.context_rules: | |
| exp = self.lexicon[word_upper] | |
| return f"{word} ({exp})" | |
| return word | |
| # Only target standalone uppercase words of length 2 to 5 | |
| pattern = r"\b[A-Z0-9\-\.]{2,6}\b" | |
| return re.sub(pattern, replace_fn, text) | |