Spaces:
Running
Running
File size: 12,813 Bytes
0e43c47 c47c7dc 0e43c47 db283f8 0e43c47 db283f8 0e43c47 db283f8 0e43c47 db283f8 0e43c47 db283f8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
OTHERS_ID = 18
SUM_INPUTS = 20
OUTPUT_PATH = 'meddec_annots.json'
sum_examples = [
[['examples/note%d.txt'%i for i in range(1,n)]]
for n in range(5,1, -1)
]
text_examples = [
["a 72 year old female with chronic indwelling foley. GNR identified in her blood and there is concern for possible resistant pseudomonas. vanco discontinued and ceftriaxone replaced with zosyn. "],
["This is a 73 year old man with CMML with recent admission to OSH for emergent splenectomy after splenic rupture who is admitted for hypoxemia and worsening bilateral ground glass opacities. He was treated aggressively on the floor with antibiotics and other etiologies (PE, MI, etc) were appropriately addressed. He was fluid resusitated and continued on his CMML regimen. Despite this, the patient became progressively hypotensive and was transferred to the ICU for further care.\n"
"In the ICU the patient continued to deteriorate and developed progressive hypotension and acidosis despite aggressive fluid repletion, pressor support, and bicarbonate drip. He received >8L NS, 8amps bicarb, pressor support w/ levophed and vasopressin, and maximum ventilatory support. Despite these measures, his lactate continued to trend upwards and he became progressively more hypotensive on the PEEP settings required to adequately oxygenate him. Furthermore, the patient developed tumor lysis syndrome in the setting of his chemotherapy and became anuric producing only 40cc of urine over 8hr. Renal service was called emergently to consider dialysis but the family elected to change his code status to DNR/DNI and focus care on comfort as a priority, after discussion w/ his oncologist Dr [**First Name (STitle) 1557**] and to defer more aggressive therapy."],
["48 year old male with complicated past medical history, multiple problems notably including ESRD s/p renal transplant complicated by collapsing FSGS, recent MRSA line sepsis, here with fevers and hypotension at dialysis, code sepsis."
"He met sepsis criteria with fever, tachycardia and likely source of infection at site of tunneled dialysis catheter. Also had leukocytosis with L shift. CXR clear, urine not produced for sample. No central line placed [**3-5**] lack of access. Treated with 2 doses linezolid PO; d/w renal team - preferred vanco use, patient switched to vanco by level and d/c on vanco at HD. Underwent stim test; failed, started on hydrocort at stress dose levels (50 q6), d/w renal, felt uneccessary, patient started on prednisone taper back to home dose of 5 mg PO qd. Held HTN meds in setting of sepsis. Received dose of vanco prior to d/c."
"Dialysis Catheter - noted morning after admission to be clotted; question whether this was related to blood draw. Instilled tPA in catheter overnight; were able to use cath in AM for HD. "
"ESRD - Started on prograf; monitored levels, d/c on home dose. As per pharm, must continue to monitor levels in context of using itraconazole. Continued patient on bactrim for prophylaxis given tacrolimus use. To go to dialysis. 7 point HCT drop noted during admission; thought elevated HCT hemoconcentration. Hemolysis labs neg, no stool to guaiac. "
"PTT elevation - noted on admission, resolved in ICU. DIC labs negative. PT/PTT elevation at discharge c/w warfarin/SC heparin use."
"Hypertension: History of HTN, on lopressor and diltiazem. "
"Pulmonary Aspergillus: Stable. On itraconazole and followed by pulmonary as an outpatient. Continued in house"
"Atrial fibrillation: He is normally rate controlled with metoprolol and anticoagulated with coumadin. NSR on EKG here, continued warfarin, held beta blocker . "
"..."
"Call your PCP or return to the ED for fevers/chills/shakes, chest pain, shortness of breath, pain at the site of your dialysis catheter, nausea, vomiting, or swelling in your legs/feet. "]
]
keys = ['c', 'g', 'p', 't', 'd', 'p', 'e', 'f', 'a', 'l']
categories = ['Contact related', 'Gathering additional information', 'Defining problem',
'Treatment goal', 'Drug related', 'Therapeutic procedure related', 'Evaluating test result',
'Deferment', 'Advice and precaution', 'Legal and insurance related']
det_desc = ['Admit, discharge, follow-up, referral',
'Ordering test, consulting colleague, seeking external information',
'Diagnostic conclusion, evaluation of health state, etiological inference, prognostic judgment',
'Quantitative or qualitative',
'Start, stop, alter, maintain, refrain',
'Start, stop, alter, maintain, refrain',
'Positive, negative, ambiguous test results',
'Transfer responsibility, wait and see, change subject',
'Advice or precaution',
'Sick leave, drug refund, insurance, disability']
unicode_symbols = [
"\U0001F91D", # Handshake
"\U0001F50D", # Magnifying glass
"\U0001F9E9", # Puzzle piece
"\U0001F3AF", # Target
"\U0001F48A", # Pill
"\U00002702", # Surgical scissors
"\U0001F9EA", # Test tube
"\U000023F0", # Alarm clock
"\U000026A0", # Warning sign
"\U0001F4C4" # Document
]
colors = ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd']
color_map = {cat: colors[i] for i,cat in enumerate(categories)}
annotator_desc = """
## Interactive Narrative Annotator
This tool allows you to manually annotate medical text for detailed analysis and model training. Follow these steps:
1. **Input Text:** Enter or paste the text you want to annotate into the text box. You can also use the provided examples.
2. **Generate Predictions (Optional):** Click "Generate Predictions" to pre-annotate the text using a machine learning model. This can serve as a starting point, which you can then review and modify. Note: Generating predictions will lock the input textbox to prevent accidental edits.
3. **Select Text:** In the **output box below**, highlight the portion of the text you wish to annotate.
4. **Annotate:** Click one of the category buttons to apply the annotation to the selected text. The selected text will be highlighted with the corresponding color.
5. **Remove/Undo:**
* **Remove (q):** Click "Remove" or press 'q' to remove the annotation from the selected text.
* **Undo (z):** Click "Undo" or press 'z' to revert the last annotation action.
6. **Download/View Annotations:**
* **Annotator ID & Discharge Summary ID:** Enter an identifier for the annotator and an optional ID for the discharge summary. These IDs will be included in the downloaded JSON data.
* **Refresh Annotations:** Click "Refresh Annotations" to display the current annotations in JSON format.
* **Download Annotated Text:** Click "Download Annotated Text" to save your annotations as a JSON file.
7. **Clear Annotations:** Click "Clear Annotations" to remove all annotations and start over. This will also unlock the input textbox.
**Keyboard Shortcuts:**
* Use the keys indicated on the buttons to annotate selections.
* `q`: Remove annotation
* `z`: Undo last action
"""
label_desc = """
## Decision Extraction & Classification
This tool allows you to quickly identify and categorize key clinical decisions within a single clinical note.
1. **Input Text:** Enter or paste the clinical note into the text box. You can also select from the provided examples.
2. **Run:** Click the "Run" button to process the text.
3. **View Results:** The labeled output will be displayed, highlighting the identified clinical decisions with color-coded categories.
This provides a simplified overview of the patient's history and key decisions at a glance.
"""
vis_desc = """
## Patient Visualization
This tool allows you to visualize the timeline of clinical decisions across multiple clinical notes for a single patient.
1. **Upload Clinical Notes:** Upload multiple clinical notes in text format. You can also select from the provided examples.
2. **Add/Remove Notes:** Use the "+" and "-" buttons to add or remove input fields for additional notes.
3. **Filter Timeline:**
* **Decision Type:** Select one or more decision types from the dropdown menu to filter the timeline. Select "All" to display all decision types.
* **Start/End Date:** Enter a start and end date (MM/DD/YYYY) to filter the timeline by date range.
* **Filter:** Click the "Filter Timeline" button to apply the selected filters.
4. **Generate Summary:** Click the "Generate Summary" button to generate a summarized view of the clinical decisions organized by date and category. This will also update the timeline plot.
5. **View Timeline:** The interactive timeline plot displays the clinical decisions over time. Hover over each data point to view details.
This visualization helps to understand the progression of clinical decisions and identify trends in patient care.
"""
title = """
<h1 style="text-align: center;">Medical Decisions Extraction, Visualization, and Annotation</h1>
<p style="font-size:1.2em;">This application offers three interactive tools for working with clinical text data:</p>
<p style="font-size:1.2em;">1. <b>Decision Extraction & Classification:</b> Process individual notes and receive highlighted key clinical decisions.</br>
2. <b>Patient Visualization:</b> Upload multiple notes to visualize the timeline of decisions.</br>
3. <b>Interactive Narrative Annotator:</b> Manually annotate text for detailed analysis and model training.</p>
"""
desc = '### Decision Categories\n'
desc += '| | |\n| --- | --- |\n'
for i,cat in enumerate(categories):
desc += f'| {unicode_symbols[i]} **{cat}** | {det_desc[i]}|\n'
shortcut_js_template = """
<script>
function shortcuts(e) {
switch (e.target.tagName.toLowerCase()) {
case "input":
case "textarea":
break;
default:
if (e.key.toLowerCase() === 'q') {
document.getElementById('btn_q').click();
} else if (e.key.toLowerCase() === 'z') {
document.getElementById('btn_z').click();
} else {
const buttonKeys = %s;
for (const key of buttonKeys) {
if (e.key.toLowerCase() === key) {
document.getElementById(`btn_${key}`).click();
break;
}
}
}
}
}
document.addEventListener('keypress', shortcuts, false);
</script>
"""
# JavaScript for handling text selection
select_js = """
function(x) {
const element = document.getElementById('annotated-text');
if (!element) {
console.log("Element not found");
return [0, 0];
}
const selection = window.getSelection();
if (!selection.rangeCount) {
console.log("No selection found");
return [0, 0];
}
const range = selection.getRangeAt(0);
if (!element.contains(range.commonAncestorContainer)) {
console.log("Selection not within element");
return [0, 0];
}
const start = getCharacterOffset(element, range.startContainer, range.startOffset);
const end = getCharacterOffset(element, range.endContainer, range.endOffset);
console.log("Selection:", start, end);
return [start, end];
function getCharacterOffset(root, node, offset) {
let currentOffset = 0;
const iterator = document.createNodeIterator(root, NodeFilter.SHOW_TEXT);
let currentNode;
while (currentNode = iterator.nextNode()) {
if (currentNode === node) {
return currentOffset + offset;
}
currentOffset += currentNode.textContent.length;
}
return currentOffset;
}
}
"""
css="""
.category-legend {border:1px dashed black;}
.text-sm {font-size: 1.5rem; line-height: 200%;}
.gr-sample-textbox {width: 1000px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;}
.gallery {width: 1000px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;}
.text-limit label textarea {height: 150px !important; overflow: scroll; }
.text-gray-500 {color: #111827; font-weight: 600; font-size: 1.25em; margin-top: 1.6em; margin-bottom: 0.6em; 'line-height: 1.6;}
#sum-out {border: 2px solid #007bff; padding: 20px; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); max-height: 300px; overflow-y: auto;}
#annotated-text { font-family: monospace; padding: 10px; border: 1px solid #ccc; }
#refresh_btn { max-width: 20px; max-height: 40px;}
.locked-input { background-color: #f0f0f0; border: 1px solid #ccc; pointer-events: none; }
body {
--text-sm: 12px;
--text-md: 16px;
--text-lg: 18px;
--input-text-size: 16px;
--section-text-size: 16px;
--input-background: --neutral-50;
}
"""
|