Create new file
Browse files
app.py
ADDED
@@ -0,0 +1,336 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import pandas as pd
|
3 |
+
import transformers
|
4 |
+
import re
|
5 |
+
|
6 |
+
import zipfile
|
7 |
+
import postt
|
8 |
+
from postt import postcor , precor
|
9 |
+
from transformers import pipeline, TokenClassificationPipeline, BertForTokenClassification , AutoTokenizer , TextClassificationPipeline , AutoModelForSequenceClassification
|
10 |
+
|
11 |
+
st.set_page_config(layout="wide")
|
12 |
+
|
13 |
+
st.image("persEsi.png",width = 200)
|
14 |
+
|
15 |
+
st.title("Knowledge extraction: EDCs")
|
16 |
+
st.write("This tool lets you extract relation triples concerning interactions between: endocrine disrupting chemicals, hormones, receptors and cancers. It is the result of an end of studies project within ESI school and dedicated to biomedical researchers looking to extract precise information about the subject without digging into long publications.")
|
17 |
+
|
18 |
+
|
19 |
+
|
20 |
+
|
21 |
+
form = st.form(key='my-form')
|
22 |
+
x = form.text_area('Enter text', height=200)
|
23 |
+
submit = form.form_submit_button('Submit')
|
24 |
+
|
25 |
+
|
26 |
+
|
27 |
+
|
28 |
+
|
29 |
+
if submit and len(x) != 0:
|
30 |
+
#model.to("cpu")
|
31 |
+
st.write("Execution in progress... Results will be displayed below in a while or can be downloaded from the sidebar, please be patient.")
|
32 |
+
|
33 |
+
tokenizer = AutoTokenizer.from_pretrained("dmis-lab/biobert-large-cased-v1.1", truncation = True, padding=True, model_max_length=512,)
|
34 |
+
model_checkpoint = BertForTokenClassification.from_pretrained("dexay/Ner2HgF", )
|
35 |
+
st.caption("Downloading models")
|
36 |
+
model_re = AutoModelForSequenceClassification.from_pretrained("dexay/reDs3others", )
|
37 |
+
|
38 |
+
token_classifier = pipeline("token-classification", tokenizer = tokenizer,model=model_checkpoint, )
|
39 |
+
|
40 |
+
|
41 |
+
|
42 |
+
if x[-1] not in ".?:":
|
43 |
+
x += "."
|
44 |
+
|
45 |
+
biotext = precor(x)
|
46 |
+
|
47 |
+
#split document or text into sentences
|
48 |
+
|
49 |
+
lstbiotext = []
|
50 |
+
|
51 |
+
flag = 0
|
52 |
+
tempsen = ""
|
53 |
+
for e in biotext:
|
54 |
+
tempsen += e
|
55 |
+
if e=="(":
|
56 |
+
flag = 1
|
57 |
+
if e==")":
|
58 |
+
flag = 0
|
59 |
+
if (e =="." or e =="?" or e ==":" ) and flag == 0 :
|
60 |
+
lstbiotext += [tempsen.strip()]
|
61 |
+
tempsen = ""
|
62 |
+
|
63 |
+
ddata = lstbiotext
|
64 |
+
|
65 |
+
#tokenized_dat = tokenize_function(ddata)
|
66 |
+
|
67 |
+
|
68 |
+
az = token_classifier(ddata)
|
69 |
+
|
70 |
+
|
71 |
+
#code to convert NER output to RE input compatible format
|
72 |
+
|
73 |
+
#tg_inorder are decoding of labels on which the model was fine tuned on
|
74 |
+
|
75 |
+
tg_inorder = ['O',
|
76 |
+
'B-HORMONE',
|
77 |
+
'B-EXP_PER',
|
78 |
+
'I-HORMONE',
|
79 |
+
'I-CANCER',
|
80 |
+
'I-EDC',
|
81 |
+
'B-RECEPTOR',
|
82 |
+
'B-CANCER',
|
83 |
+
'I-RECEPTOR',
|
84 |
+
'B-EDC',
|
85 |
+
'PAD']
|
86 |
+
|
87 |
+
lstSentEnc = []
|
88 |
+
lstSentbilbl = []
|
89 |
+
lstSentEnt = []
|
90 |
+
for itsent in az:
|
91 |
+
|
92 |
+
sentaz = itsent
|
93 |
+
ph = []
|
94 |
+
phl = []
|
95 |
+
for e in sentaz:
|
96 |
+
if e["word"][0]=="#" and len(ph)!=0:
|
97 |
+
ph[-1]+= e["word"][2:]
|
98 |
+
else:
|
99 |
+
ph += [e["word"]]
|
100 |
+
phl += [e["entity"]]
|
101 |
+
|
102 |
+
|
103 |
+
phltr = []
|
104 |
+
for e in phl:
|
105 |
+
phltr += [tg_inorder[int(e[-1])] if len(e)==7 else tg_inorder[int(e[-2:])]]
|
106 |
+
|
107 |
+
|
108 |
+
nwph = []
|
109 |
+
nwphltr = []
|
110 |
+
flag = 0
|
111 |
+
for i in range(len(phltr)-2):
|
112 |
+
if phltr[i]=="O" and flag != 3 :
|
113 |
+
nwph += [ph[i]]
|
114 |
+
nwphltr += [phltr[i]]
|
115 |
+
continue
|
116 |
+
elif flag == 3:
|
117 |
+
nwph[-1] += " "+ph[i]
|
118 |
+
flag = 1
|
119 |
+
continue
|
120 |
+
elif phltr[i][2:]==phltr[i+1][2:] and phltr[i+1][0]=="I" and flag == 0:
|
121 |
+
nwph += [ph[i]]
|
122 |
+
nwphltr += [phltr[i]]
|
123 |
+
flag = 1
|
124 |
+
continue
|
125 |
+
elif phltr[i][2:]==phltr[i+1][2:] and phltr[i+1][0]=="I" and flag == 1:
|
126 |
+
nwph[-1] += " "+ph[i]
|
127 |
+
continue
|
128 |
+
# xox with flag == 3
|
129 |
+
elif phltr[i][2:]==phltr[i+2][2:] and phltr[i+1]=="O" and phltr[i+2][0]=="I" and flag == 0:
|
130 |
+
nwph += [ph[i]]
|
131 |
+
nwphltr += [phltr[i]]
|
132 |
+
flag = 3
|
133 |
+
continue
|
134 |
+
elif phltr[i][2:]==phltr[i+2][2:] and phltr[i+1]=="O" and phltr[i+2][0]=="I" and flag == 1:
|
135 |
+
nwph[-1] += " "+ph[i]
|
136 |
+
flag = 3
|
137 |
+
continue
|
138 |
+
#\ xox
|
139 |
+
elif flag == 1:
|
140 |
+
nwph[-1] += " "+ph[i]
|
141 |
+
flag = 0
|
142 |
+
continue
|
143 |
+
else :
|
144 |
+
nwph += [ph[i]]
|
145 |
+
nwphltr += [phltr[i]]
|
146 |
+
continue
|
147 |
+
|
148 |
+
|
149 |
+
# nwph,nwphltr,len(nwph),len(nwphltr)
|
150 |
+
|
151 |
+
|
152 |
+
if nwphltr.count("O") <= len(nwphltr)-2:
|
153 |
+
for i in range(len(nwph)-1):
|
154 |
+
if nwphltr[i] != "O":
|
155 |
+
for j in range(i,len(nwph)):
|
156 |
+
if nwphltr[j] != "O" and nwphltr[j] != nwphltr[i] and {nwphltr[j], nwphltr[i]} != {"B-CANCER","B-RECEPTOR"}:
|
157 |
+
sen2ad = ""
|
158 |
+
for g in range(i):
|
159 |
+
sen2ad += nwph[g]+" "
|
160 |
+
sen2ad += "<e1>"+nwph[i]+"</e1> "
|
161 |
+
|
162 |
+
for t in range(i+1,j):
|
163 |
+
sen2ad += nwph[t]+" "
|
164 |
+
sen2ad += "<e2>"+nwph[j]+"</e2>"
|
165 |
+
if j<len(nwph):
|
166 |
+
for l in range(j+1,len(nwph)):
|
167 |
+
sen2ad += " "+nwph[l]
|
168 |
+
lstSentEnc += [sen2ad]
|
169 |
+
lstSentbilbl += [[nwphltr[i],nwphltr[j]]]
|
170 |
+
lstSentEnt += [[nwph[i],nwph[j]]]
|
171 |
+
|
172 |
+
|
173 |
+
|
174 |
+
#lstSentEnc,lstSentEnt,lstSentbilbl
|
175 |
+
|
176 |
+
st.caption("Entities detected.")
|
177 |
+
st.caption("Next: Relation detection ...")
|
178 |
+
|
179 |
+
|
180 |
+
# Relation extraction part
|
181 |
+
|
182 |
+
token_classifier = pipeline("text-classification", tokenizer = tokenizer,model=model_re, )
|
183 |
+
|
184 |
+
rrdata = lstSentEnc
|
185 |
+
|
186 |
+
|
187 |
+
|
188 |
+
outre = token_classifier(rrdata)
|
189 |
+
|
190 |
+
|
191 |
+
trLABELS = ['INCREASE_RISK(e1,e2)',
|
192 |
+
'SPEED_UP(e2,e1)',
|
193 |
+
'DECREASE_ACTIVITY(e1,e2)',
|
194 |
+
'NO_ASSOCIATION(e1,e2)',
|
195 |
+
'DECREASE(e1,e2)',
|
196 |
+
'BLOCK(e1,e2)',
|
197 |
+
'CAUSE(e1,e2)',
|
198 |
+
'ACTIVATE(e2,e1)',
|
199 |
+
'DEVELOP(e2,e1)',
|
200 |
+
'ALTER(e1,e2)',
|
201 |
+
'INCREASE_RISK(e2,e1)',
|
202 |
+
'SPEED_UP(e1,e2)',
|
203 |
+
'INTERFER(e1,e2)',
|
204 |
+
'DECREASE(e2,e1)',
|
205 |
+
'NO_ASSOCIATION(e2,e1)',
|
206 |
+
'INCREASE(e2,e1)',
|
207 |
+
'INTERFER(e2,e1)',
|
208 |
+
'ACTIVATE(e1,e2)',
|
209 |
+
'INCREASE(e1,e2)',
|
210 |
+
'MIMIC(e1,e2)',
|
211 |
+
'MIMIC(e2,e1)',
|
212 |
+
'BLOCK(e2,e1)',
|
213 |
+
'other',
|
214 |
+
'BIND(e2,e1)',
|
215 |
+
'INCREASE_ACTIVITY(e2,e1)',
|
216 |
+
'ALTER(e2,e1)',
|
217 |
+
'CAUSE(e2,e1)',
|
218 |
+
'BIND(e1,e2)',
|
219 |
+
'DEVELOP(e1,e2)',
|
220 |
+
'DECREASE_ACTIVITY(e2,e1)']
|
221 |
+
|
222 |
+
|
223 |
+
|
224 |
+
outrelbl = []
|
225 |
+
for e in outre:
|
226 |
+
outrelbl += [trLABELS[int(e['label'][-1])] if len(e["label"])==7 else trLABELS[int(e['label'][-2:])] ]
|
227 |
+
|
228 |
+
for i in range(len(outrelbl)):
|
229 |
+
if "(e2,e1)" in outrelbl[i]:
|
230 |
+
lstSentbilbl[i][0],lstSentbilbl[i][1] = lstSentbilbl[i][1],lstSentbilbl[i][0]
|
231 |
+
lstSentEnt[i][0],lstSentEnt[i][1] = lstSentEnt[i][1],lstSentEnt[i][0]
|
232 |
+
|
233 |
+
|
234 |
+
edccan = []
|
235 |
+
edccanbis = []
|
236 |
+
|
237 |
+
for i in range(len(outrelbl)):
|
238 |
+
if outrelbl[i] != "other":
|
239 |
+
edccanbis += [[lstSentEnt[i][0], lstSentEnt[i][1], outrelbl[i][:-7], lstSentEnc[i], lstSentbilbl[i]]]
|
240 |
+
#edccan += [[lstSentEnc[i],lstSentEnt[i][0]+" ["+lstSentbilbl[i][0][2:]+"]", lstSentEnt[i][1]+" ["+lstSentbilbl[i][1][2:]+"]",outrelbl[i][:-7]]]
|
241 |
+
|
242 |
+
edccanbis = postcor(edccanbis)
|
243 |
+
|
244 |
+
|
245 |
+
|
246 |
+
edccann = []
|
247 |
+
edchorm = []
|
248 |
+
edcrecep = []
|
249 |
+
hormrecep = []
|
250 |
+
hormcan = []
|
251 |
+
|
252 |
+
for e in edccanbis:
|
253 |
+
if e[-1]== ["B-EDC","B-CANCER"] and e[2] in ["CAUSE","INCREASE_RISK","SPEED_UP","NO_ASSOCIATION"]:
|
254 |
+
edccann += [[e[0],e[1],e[2]]]
|
255 |
+
edccan += [[e[3],e[0]+" ["+e[-1][0][2:]+"]", e[1]+" ["+e[-1][1][2:]+"]",e[2]]]
|
256 |
+
|
257 |
+
elif e[-1]== ["B-EDC","B-HORMONE"] and e[2] in ["ALTER", "INCREASE", "DECREASE", "MIMIC", "INCREASE_ACTIVITY","DECREASE_ACTIVITY"]:
|
258 |
+
edchorm += [[e[0],e[1],e[2]]]
|
259 |
+
edccan += [[e[3],e[0]+" ["+e[-1][0][2:]+"]", e[1]+" ["+e[-1][1][2:]+"]",e[2]]]
|
260 |
+
|
261 |
+
elif e[-1]== ["B-EDC","B-RECEPTOR"] and e[2] in ["BLOCK", "ACTIVATE", "INTERFER"] :
|
262 |
+
edcrecep += [[e[0],e[1],e[2]]]
|
263 |
+
edccan += [[e[3],e[0]+" ["+e[-1][0][2:]+"]", e[1]+" ["+e[-1][1][2:]+"]",e[2]]]
|
264 |
+
|
265 |
+
elif e[-1]== ["B-HORMONE","B-RECEPTOR"] and e[2] in ["BIND"] :
|
266 |
+
hormrecep += [[e[0],e[1],e[2]]]
|
267 |
+
edccan += [[e[3],e[0]+" ["+e[-1][0][2:]+"]", e[1]+" ["+e[-1][1][2:]+"]",e[2]]]
|
268 |
+
|
269 |
+
elif e[-1]== ["B-HORMONE","B-CANCER"] and e[2] in ["DEVELOP"]:
|
270 |
+
hormcan += [[e[0],e[1],e[2]]]
|
271 |
+
edccan += [[e[3],e[0]+" ["+e[-1][0][2:]+"]", e[1]+" ["+e[-1][1][2:]+"]",e[2]]]
|
272 |
+
|
273 |
+
|
274 |
+
edcrecepdf = pd.DataFrame(edcrecep, columns=["EDC", "RECEPTOR", "RELATION"])
|
275 |
+
edccanndf = pd.DataFrame(edccann, columns= ["EDC", "CANCER", "RELATION"] )
|
276 |
+
edchormdf = pd.DataFrame(edchorm , columns = ["EDC", "HORMONE", "RELATION"])
|
277 |
+
hormrecepdf = pd.DataFrame(hormrecep, columns = ["HORMONE", "RECEPTOR", "RELATION"])
|
278 |
+
hormcandf = pd.DataFrame(hormcan, columns = ["HORMONE", "CANCER", "RELATION"])
|
279 |
+
|
280 |
+
edccancsv = edccanndf.to_csv('edccan.csv')
|
281 |
+
edcrecepcsv = edcrecepdf.to_csv('edcrecep.csv')
|
282 |
+
edchormcsv = edchormdf.to_csv('edchorm.csv')
|
283 |
+
hormcancsv = hormcandf.to_csv('hormcan.csv')
|
284 |
+
hormrecepcsv = hormrecepdf.to_csv('hormrecep.csv')
|
285 |
+
|
286 |
+
|
287 |
+
|
288 |
+
|
289 |
+
|
290 |
+
edccandf = pd.DataFrame(edccan, columns= ["Sentence", "Entity 1", "Entity 2", "Relation"] )
|
291 |
+
|
292 |
+
edccandf.to_csv("table.csv")
|
293 |
+
|
294 |
+
|
295 |
+
with zipfile.ZipFile("allcsvs.zip", "w") as zipf:
|
296 |
+
if len(edccan)!=0:
|
297 |
+
zipf.write('table.csv')
|
298 |
+
if len(edccann)!=0:
|
299 |
+
zipf.write('edccan.csv')
|
300 |
+
|
301 |
+
if len(edcrecep)!=0:
|
302 |
+
zipf.write('edcrecep.csv')
|
303 |
+
if len(edchorm)!=0:
|
304 |
+
zipf.write('edchorm.csv')
|
305 |
+
if len(hormcan)!=0:
|
306 |
+
zipf.write('hormcan.csv')
|
307 |
+
if len(hormrecep)!=0:
|
308 |
+
zipf.write('hormrecep.csv')
|
309 |
+
|
310 |
+
|
311 |
+
zipf.close()
|
312 |
+
|
313 |
+
st.table(edccandf)
|
314 |
+
csv = edccandf.to_csv(index=False).encode('utf-8')
|
315 |
+
with st.sidebar:
|
316 |
+
st.subheader("You can only choose one download !!")
|
317 |
+
st.caption("we recommed ZIP file.")
|
318 |
+
st.write("Download table only :")
|
319 |
+
st.download_button(
|
320 |
+
label="Download CSV",
|
321 |
+
data=csv,
|
322 |
+
file_name='Relation_triples_table.csv',
|
323 |
+
mime='text/csv',
|
324 |
+
)
|
325 |
+
st.write("Download table plus separate csvs for each family of pairs :")
|
326 |
+
with open("allcsvs.zip", "rb") as fp:
|
327 |
+
btn = st.download_button(
|
328 |
+
label="Download ZIP",
|
329 |
+
data=fp,
|
330 |
+
file_name="SeparateCsvs.zip",
|
331 |
+
mime="application/zip"
|
332 |
+
)
|
333 |
+
|
334 |
+
|
335 |
+
|
336 |
+
|