Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
@@ -12,15 +12,21 @@ from spacy.matcher import PhraseMatcher
|
|
12 |
from spacy.tokens import Span
|
13 |
#import en_ner_bc5cdr_md
|
14 |
import re
|
15 |
-
|
16 |
-
|
17 |
from streamlit.components.v1 import html
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
|
|
|
|
|
|
|
|
23 |
|
|
|
|
|
|
|
|
|
24 |
#nlp = en_core_web_lg.load()
|
25 |
nlp = spacy.load("en_ner_bc5cdr_md")
|
26 |
|
@@ -135,6 +141,7 @@ dailyNoteChange.rename(columns={'STORETIME':'Time of Record',
|
|
135 |
dailyNote = df4['Full Text'].loc[(df4['Patient_ID'] == patient) & (df4['Admission_ID']==HospitalAdmission)]
|
136 |
dailyNote = dailyNote.unique()
|
137 |
|
|
|
138 |
##========= Buttons to the 5 tabs ======== Temp disabled Discharge Plan and Social Notes
|
139 |
##col1, col2, col3, col4, col5 = st.columns([1,1,1,1,1]) -- to uncomment and comment below line to include discharge plan and social notes
|
140 |
col1, col2, col5 = st.columns([1,1,1])
|
@@ -142,14 +149,11 @@ col6, col7 =st.columns([2,2])
|
|
142 |
with st.container():
|
143 |
with col1:
|
144 |
btnAdmission = st.button("🏥 Admission")
|
145 |
-
|
146 |
-
|
147 |
-
inputNote = "Input Admission Note"
|
148 |
with col2:
|
149 |
btnDailyNarrative = st.button('📆Daily Narrative')
|
150 |
-
|
151 |
-
inputNote = "Input Daily Narrative Note"
|
152 |
-
# with col3:
|
153 |
# btnDischargePlan = st.button('🗒️Discharge Plan')
|
154 |
# if btnDischargePlan:
|
155 |
# inputNote = "Input Discharge Plan"
|
@@ -159,61 +163,11 @@ with st.container():
|
|
159 |
# inputNote = "Input Social Note"
|
160 |
with col5:
|
161 |
btnPastHistory = st.button('📇Past History (6 Mths)')
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
##========= on Past History Tab =========
|
166 |
|
167 |
-
with st.container():
|
168 |
-
if btnPastHistory:
|
169 |
-
with col6:
|
170 |
-
st.markdown('**No. of admission past 6 months:**')
|
171 |
-
st.markdown(countOfAdmission)
|
172 |
-
|
173 |
-
with col7:
|
174 |
-
#st.date_input('Select Admission Date') # To replace with a dropdown filter instead
|
175 |
-
#st.selectbox('Past Episodes',pastHistoryEp)
|
176 |
-
pastHistory = st.selectbox('Select Past History Admission', pastHistoryEpDate, format_func=lambda x: 'Select an option' if x == '' else x)
|
177 |
-
|
178 |
-
if btnPastHistory:
|
179 |
-
|
180 |
-
#st.write('Past History')
|
181 |
-
historyAdmission = df3.query(
|
182 |
-
"Patient_ID == @patient & CHARTDATE_HADM_ID == @pastHistory"
|
183 |
-
)
|
184 |
-
runtext = historyAdmission['hospital_course_processed'].values[0]
|
185 |
-
|
186 |
-
if not(btnPastHistory) and not(btnDailyNarrative):
|
187 |
-
runtext =st.text_area(inputNote, str(original_text2)[1:-1], height=300)
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
##========= END on Past History Tab =========
|
193 |
-
|
194 |
-
## ===== Commented out as no longer in use =====
|
195 |
-
# Extract words associated with each entity
|
196 |
-
#def genEntities(ann, entity):
|
197 |
-
# # entity colour dict
|
198 |
-
# #ent_col = {'DISEASE':'#B42D1B', 'CHEMICAL':'#F06292'}
|
199 |
-
# ent_col = {'DISEASE':'pink', 'CHEMICAL':'orange'}
|
200 |
-
# # separate into the different entities
|
201 |
-
# entities = trans_df['Class'].unique()
|
202 |
-
#
|
203 |
-
# if entity in entities:
|
204 |
-
# ent = list(trans_df[trans_df['Class']==entity]['Entity'].unique())
|
205 |
-
# entlist = ",".join(ent)
|
206 |
-
# st.markdown(f'<p style="background-color:{ent_col[entity]};color:#080808;font-size:16px;">{entlist}</p>', #unsafe_allow_html=True)
|
207 |
|
208 |
|
209 |
##======================== Start of NER Tagging ========================
|
210 |
-
|
211 |
-
# doc = nlp(str(original_text2))
|
212 |
-
# colors = { "DISEASE": "pink","CHEMICAL": "orange"}
|
213 |
-
# options = {"ents": [ "DISEASE", "CHEMICAL"],"colors": colors}
|
214 |
-
# ent_html = displacy.render(doc, style="ent", options=options)
|
215 |
-
# ====== End of Old NER ======
|
216 |
-
|
217 |
#lemmatizing the notes to capture all forms of negation(e.g., deny: denies, denying)
|
218 |
def lemmatize(note, nlp):
|
219 |
doc = nlp(note)
|
@@ -281,21 +235,7 @@ def dedupe(items):
|
|
281 |
yield item
|
282 |
seen.add(item)
|
283 |
|
284 |
-
lem_clinical_note= lemmatize(runtext, nlp)
|
285 |
-
#creating a doc object using BC5CDR model
|
286 |
-
doc = nlp(lem_clinical_note)
|
287 |
-
options = get_entity_options()
|
288 |
-
|
289 |
-
#list of negative concepts from clinical note identified by negspacy
|
290 |
-
results0 = negation_handling(lem_clinical_note, neg_model)
|
291 |
-
|
292 |
-
matcher = match(nlp, results0,"NEG_ENTITY")
|
293 |
-
|
294 |
-
#doc0: new doc object with added "NEG_ENTITY label"
|
295 |
-
doc0 = overwrite_ent_lbl(matcher,doc)
|
296 |
|
297 |
-
#visualizing identified Named Entities in clinical input text
|
298 |
-
ent_html = displacy.render(doc0, style='ent', options=options)
|
299 |
|
300 |
##======================== End of NER Tagging ========================
|
301 |
|
@@ -329,11 +269,76 @@ def run_model(input_text):
|
|
329 |
|
330 |
st.success(output)
|
331 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
332 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
333 |
col1, col2 = st.columns([1,1])
|
334 |
|
335 |
#to not show summary and references text for Past History and Daily Narrative
|
336 |
-
if
|
|
|
|
|
|
|
337 |
with col1:
|
338 |
st.button('Summarize')
|
339 |
run_model(runtext)
|
@@ -359,51 +364,66 @@ if not(btnPastHistory) and not(btnDailyNarrative):
|
|
359 |
st.markdown('**NER**')
|
360 |
with st.expander("See NER Details"):
|
361 |
st.markdown(ent_html, unsafe_allow_html=True)
|
362 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
363 |
with st.container():
|
364 |
st.markdown('Daily Progress Note (24 hour event only):')
|
365 |
st.markdown(str(dailyNote)[1:-1])
|
366 |
|
367 |
|
368 |
with st.container():
|
369 |
-
# hide_table_row_index = """
|
370 |
-
# <style>
|
371 |
-
# thead tr th:first-child {display:none}
|
372 |
-
# tbody th {display:none}
|
373 |
-
# </style>
|
374 |
-
# """
|
375 |
-
#
|
376 |
-
# # Inject CSS with Markdown
|
377 |
-
# st.markdown(hide_table_row_index, unsafe_allow_html=True)
|
378 |
-
# st.table(dailyNoteChange)
|
379 |
styler = dailyNoteChange.style.hide_index()
|
380 |
st.write(styler.to_html(), unsafe_allow_html=True)
|
381 |
st.markdown(f'<p style="color:#828080;font-size:12px;">*Current prototype displays only a single section within the daily progress note, could also potentially include all sections within each progress note and allow user to select the section changes the user wants to look at</p>', unsafe_allow_html=True)
|
382 |
|
383 |
#else:
|
384 |
-
|
|
|
|
|
|
|
385 |
# ===== Adding the Disease/Chemical into a list =====
|
386 |
problem_entities = list(dedupe([t for t in doc0.ents if t.label_ == 'DISEASE']))
|
387 |
medication_entities = list(dedupe([t for t in doc0.ents if t.label_ == 'CHEMICAL']))
|
388 |
-
|
389 |
-
|
390 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
391 |
#st.markdown('Summary: ')
|
392 |
st.markdown(f'<p style="color:#080808;font-size:16px;"><b>Summary: </b></p>', unsafe_allow_html=True)
|
393 |
|
394 |
|
395 |
if model == "BertSummarizer":
|
396 |
-
|
|
|
|
|
|
|
397 |
elif model == "t5seq2eq":
|
398 |
-
|
|
|
|
|
|
|
399 |
st.markdown(f'<p style="color:#080808;font-size:16px;"><b>Diagnosis: </b></p>', unsafe_allow_html=True)
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
|
|
|
|
|
|
|
|
|
12 |
from spacy.tokens import Span
|
13 |
#import en_ner_bc5cdr_md
|
14 |
import re
|
|
|
|
|
15 |
from streamlit.components.v1 import html
|
16 |
|
17 |
+
if "load_state" not in st.session_state:
|
18 |
+
st.session_state.load_state = False
|
19 |
+
|
20 |
+
if "button_clicked" not in st.session_state:
|
21 |
+
st.session_state.button_clicked = False
|
22 |
+
|
23 |
+
if "daily_button_clicked" not in st.session_state:
|
24 |
+
st.session_state.daily_button_clicked = False
|
25 |
|
26 |
+
if "past_button_clicked" not in st.session_state:
|
27 |
+
st.session_state.past_button_clicked = False
|
28 |
+
|
29 |
+
|
30 |
#nlp = en_core_web_lg.load()
|
31 |
nlp = spacy.load("en_ner_bc5cdr_md")
|
32 |
|
|
|
141 |
dailyNote = df4['Full Text'].loc[(df4['Patient_ID'] == patient) & (df4['Admission_ID']==HospitalAdmission)]
|
142 |
dailyNote = dailyNote.unique()
|
143 |
|
144 |
+
|
145 |
##========= Buttons to the 5 tabs ======== Temp disabled Discharge Plan and Social Notes
|
146 |
##col1, col2, col3, col4, col5 = st.columns([1,1,1,1,1]) -- to uncomment and comment below line to include discharge plan and social notes
|
147 |
col1, col2, col5 = st.columns([1,1,1])
|
|
|
149 |
with st.container():
|
150 |
with col1:
|
151 |
btnAdmission = st.button("🏥 Admission")
|
152 |
+
inputNote = "Input Admission Note"
|
153 |
+
|
|
|
154 |
with col2:
|
155 |
btnDailyNarrative = st.button('📆Daily Narrative')
|
156 |
+
# with col3:what
|
|
|
|
|
157 |
# btnDischargePlan = st.button('🗒️Discharge Plan')
|
158 |
# if btnDischargePlan:
|
159 |
# inputNote = "Input Discharge Plan"
|
|
|
163 |
# inputNote = "Input Social Note"
|
164 |
with col5:
|
165 |
btnPastHistory = st.button('📇Past History (6 Mths)')
|
|
|
|
|
|
|
|
|
166 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
167 |
|
168 |
|
169 |
##======================== Start of NER Tagging ========================
|
170 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
171 |
#lemmatizing the notes to capture all forms of negation(e.g., deny: denies, denying)
|
172 |
def lemmatize(note, nlp):
|
173 |
doc = nlp(note)
|
|
|
235 |
yield item
|
236 |
seen.add(item)
|
237 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
238 |
|
|
|
|
|
239 |
|
240 |
##======================== End of NER Tagging ========================
|
241 |
|
|
|
269 |
|
270 |
st.success(output)
|
271 |
|
272 |
+
##========= on Past History Tab =========
|
273 |
+
if btnAdmission or st.session_state["button_clicked"]:
|
274 |
+
st.session_state["daily_button_clicked"] = False
|
275 |
+
st.session_state["past_button_clicked"] = False
|
276 |
+
st.session_state["button_clicked"] = True
|
277 |
+
|
278 |
+
|
279 |
+
runtext =st.text_area(inputNote, str(original_text2)[1:-1], height=300)
|
280 |
+
|
281 |
+
if btnPastHistory or st.session_state["past_button_clicked"]:
|
282 |
+
st.session_state["button_clicked"] = False
|
283 |
+
st.session_state["daily_button_clicked"] = False
|
284 |
+
st.session_state["past_button_clicked"] = True
|
285 |
+
|
286 |
+
with st.container():
|
287 |
+
with col6:
|
288 |
+
|
289 |
+
st.markdown('**No. of admission past 6 months:**')
|
290 |
+
st.markdown(countOfAdmission)
|
291 |
+
|
292 |
+
with col7:
|
293 |
+
#st.date_input('Select Admission Date') # To replace with a dropdown filter instead
|
294 |
+
#st.selectbox('Past Episodes',pastHistoryEp)
|
295 |
+
pastHistory = st.selectbox('Select Past History Admission', pastHistoryEpDate, format_func=lambda x: 'Select an option' if x == '' else x)
|
296 |
+
|
297 |
+
historyAdmission = df3.query(
|
298 |
+
"Patient_ID == @patient & CHARTDATE_HADM_ID == @pastHistory"
|
299 |
+
)
|
300 |
+
|
301 |
+
|
302 |
+
if historyAdmission.shape[0] == 0:
|
303 |
+
runtext = "No past episodes"
|
304 |
+
else:
|
305 |
+
#runtext = historyAdmission['hospital_course_processed'].values[0]
|
306 |
+
runtext = historyAdmission['hospital_course_processed'].values[0]
|
307 |
+
|
308 |
+
if btnDailyNarrative or st.session_state["daily_button_clicked"]:
|
309 |
+
st.session_state["button_clicked"] = False
|
310 |
+
st.session_state["past_button_clicked"] = False
|
311 |
+
st.session_state["daily_button_clicked"] = True
|
312 |
+
|
313 |
+
|
314 |
+
|
315 |
+
|
316 |
|
317 |
+
lem_clinical_note= lemmatize(runtext, nlp)
|
318 |
+
#creating a doc object using BC5CDR model
|
319 |
+
doc = nlp(lem_clinical_note)
|
320 |
+
options = get_entity_options()
|
321 |
+
|
322 |
+
#list of negative concepts from clinical note identified by negspacy
|
323 |
+
results0 = negation_handling(lem_clinical_note, neg_model)
|
324 |
+
|
325 |
+
matcher = match(nlp, results0,"NEG_ENTITY")
|
326 |
+
|
327 |
+
#doc0: new doc object with added "NEG_ENTITY label"
|
328 |
+
doc0 = overwrite_ent_lbl(matcher,doc)
|
329 |
+
|
330 |
+
#visualizing identified Named Entities in clinical input text
|
331 |
+
ent_html = displacy.render(doc0, style='ent', options=options)
|
332 |
+
|
333 |
+
|
334 |
+
|
335 |
col1, col2 = st.columns([1,1])
|
336 |
|
337 |
#to not show summary and references text for Past History and Daily Narrative
|
338 |
+
if btnAdmission or st.session_state["button_clicked"]:
|
339 |
+
st.session_state["daily_button_clicked"] = False
|
340 |
+
st.session_state["past_button_clicked"] = False
|
341 |
+
st.session_state["button_clicked"] = True
|
342 |
with col1:
|
343 |
st.button('Summarize')
|
344 |
run_model(runtext)
|
|
|
364 |
st.markdown('**NER**')
|
365 |
with st.expander("See NER Details"):
|
366 |
st.markdown(ent_html, unsafe_allow_html=True)
|
367 |
+
|
368 |
+
|
369 |
+
elif btnDailyNarrative or st.session_state["daily_button_clicked"]:
|
370 |
+
st.session_state["daily_button_clicked"] = True
|
371 |
+
st.session_state["past_button_clicked"] = False
|
372 |
+
st.session_state["button_clicked"] = False
|
373 |
+
|
374 |
with st.container():
|
375 |
st.markdown('Daily Progress Note (24 hour event only):')
|
376 |
st.markdown(str(dailyNote)[1:-1])
|
377 |
|
378 |
|
379 |
with st.container():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
380 |
styler = dailyNoteChange.style.hide_index()
|
381 |
st.write(styler.to_html(), unsafe_allow_html=True)
|
382 |
st.markdown(f'<p style="color:#828080;font-size:12px;">*Current prototype displays only a single section within the daily progress note, could also potentially include all sections within each progress note and allow user to select the section changes the user wants to look at</p>', unsafe_allow_html=True)
|
383 |
|
384 |
#else:
|
385 |
+
elif btnPastHistory or st.session_state["past_button_clicked"]:
|
386 |
+
st.session_state["past_button_clicked"] = True
|
387 |
+
st.session_state["button_clicked"] = False
|
388 |
+
st.session_state["daily_button_clicked"] = False
|
389 |
# ===== Adding the Disease/Chemical into a list =====
|
390 |
problem_entities = list(dedupe([t for t in doc0.ents if t.label_ == 'DISEASE']))
|
391 |
medication_entities = list(dedupe([t for t in doc0.ents if t.label_ == 'CHEMICAL']))
|
392 |
+
if historyAdmission.shape[0] == 0:
|
393 |
+
st.markdown('Admission Date: NA')
|
394 |
+
st.markdown('Date of Discharge: NA')
|
395 |
+
st.markdown('Days from current admission: NA')
|
396 |
+
else:
|
397 |
+
st.markdown('Admission Date: ' + historyAdmission['ADMITTIME'].values[0])
|
398 |
+
st.markdown('Date of Discharge: ' + historyAdmission['DISCHTIME'].values[0])
|
399 |
+
st.markdown('Days from current admission: ' + str(historyAdmission['days_from_index'].values[0]) +' days')
|
400 |
+
|
401 |
#st.markdown('Summary: ')
|
402 |
st.markdown(f'<p style="color:#080808;font-size:16px;"><b>Summary: </b></p>', unsafe_allow_html=True)
|
403 |
|
404 |
|
405 |
if model == "BertSummarizer":
|
406 |
+
if historyAdmission.shape[0] == 0:
|
407 |
+
st.markdown('NA')
|
408 |
+
else:
|
409 |
+
st.markdown(str(historyAdmission['BertSummarizer'].values[0]))
|
410 |
elif model == "t5seq2eq":
|
411 |
+
if historyAdmission.shape[0] == 0:
|
412 |
+
st.markdown('NA')
|
413 |
+
else:
|
414 |
+
st.markdown(str(historyAdmission['t5seq2eq'].values[0]))
|
415 |
st.markdown(f'<p style="color:#080808;font-size:16px;"><b>Diagnosis: </b></p>', unsafe_allow_html=True)
|
416 |
+
|
417 |
+
if historyAdmission.shape[0] == 0:
|
418 |
+
st.markdown('NA')
|
419 |
+
else:
|
420 |
+
st.markdown(str(historyAdmission['Diagnosis_Description'].values[0]))
|
421 |
+
st.markdown('**PROBLEM/ISSUE**')
|
422 |
+
st.markdown(f'<p style="background-color:PINK;color:#080808;font-size:16px;">{str(problem_entities)[1:-1]}</p>', unsafe_allow_html=True)
|
423 |
+
st.markdown('**MEDICATION**')
|
424 |
+
st.markdown(f'<p style="background-color:orange;color:#080808;font-size:16px;">{str(medication_entities)[1:-1]}</p>', unsafe_allow_html=True)
|
425 |
+
st.markdown('Discharge Disposition: ' + str(historyAdmission['DISCHARGE_LOCATION'].values[0]))
|
426 |
+
with st.expander('Full Discharge Summary'):
|
427 |
+
#st.write("line 1 \n line 2 \n line 3")
|
428 |
+
fulldischargesummary = historyAdmission['TEXT'].values[0]
|
429 |
+
st.write(fulldischargesummary)
|