generated from streamlit/blank-app-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstreamlit_app.py
354 lines (322 loc) · 13.8 KB
/
streamlit_app.py
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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
import streamlit as st
pubmed_search_url = "https://pubmed.ncbi.nlm.nih.gov/?term="
text_area_height = 250
collapse_search_string_exp= 1000
# example term lists
mesh_term_example = \
"""
asthenia
fatigue
frailty
muscle weakness
muscle atrophy
""".strip()
subheading_example = \
"""
diagnosis
epidemiology
""".strip()
proximity_topic1_example = \
"""
asthenia
debility
fatigue
frailty
muscle weakness
muscular weakness
muscle atrophy
muscular atrophy
sarcopenia
""".strip()
proximity_topic2_example = \
"""
assess
assessment
diagnosis
diagnoses
diagnostic
evaluate
evaluation
instrument
instruments
index
indices
measure
measures
scale
scales
score
scores
scoring
screen
screens
screening
screenings
test
tests
testing
tool
tools
""".strip()
intersection_topic1_example = \
"""
asthenia
debilit*
fatigue
frail*
musc* atroph*
musc* wast*
musc* weak*
sarcopenia*
""".strip()
intersection_topic2_example = \
"""
assess*
diagnos*
evaluat*
index
indic*
instrument*
measure*
scale*
score*
screen*
test*
tool*
""".strip()
# clear form button callback
def clear_form():
st.session_state["mesh"] = ""
st.session_state["subheadings"] = ""
st.session_state["proximity topic 1"] = ""
st.session_state["proximity topic 2"] = ""
st.session_state["intersection topic 1"] = ""
st.session_state["intersection topic 2"] = ""
st.session_state["pd"] = 2
st.session_state["pf"] = "tiab"
st.session_state["sf"] = "tw"
st.session_state["majr"] = False
st.session_state["noexp"] = False
# load examples button callback
def load_examples():
st.session_state['mesh'] = mesh_term_example
st.session_state['subheadings'] = subheading_example
st.session_state["proximity topic 1"] = proximity_topic1_example
st.session_state["proximity topic 2"] = proximity_topic2_example
st.session_state["intersection topic 1"] = intersection_topic1_example
st.session_state["intersection topic 2"] = intersection_topic2_example
st.session_state["pd"] = 4
st.session_state["pf"] = "tiab"
st.session_state["sf"] = "tw"
st.set_page_config(
page_title = "Pairwise PubMed Search Generator",
page_icon = "🔎",
# menu_items = {
# "Get help":"mailto:[email protected]",
# "Report a Bug":"https://github.com/marijane/pairwise-pubmed-search-generator/issues",
# "About": "Made by Marijane White with Streamlit",
# }
)
st.title("Pairwise PubMed Search Generator", anchor=False)
# info/instructions sidebar
with st.sidebar:
st.write("""
This app:
* Generates PubMed search strings from two lists of input terms, which can be easily copied to your clipboard
* Provides buttons to execute the generated search strings in PubMed in a new browser tab
Use it to:
* Combine a list of MeSH Main Headings with a list of MeSH Subheadings
* Work around the truncation linitation in PubMed's proximity search
* Combine two lists of terms with the AND operator
Note:
* A set of example term lists for a search on *frailty measures* is provided as placeholder text
* Use the :red[Load example terms] button to load the frailty measures terms into the form for search string generation
* Generated search URLs can be quite long, but it is possible to hit a length limit, which is not documented
* A PubMed search can have no more than 256 wildcard characters
""")
with st.form("enter_terms_form", enter_to_submit=False):
st.header("Pairwise MeSH Main/Subheading Search", divider=True, anchor=False)
mcol1, mcol2 = st.columns(2)
with mcol1:
mesh_terms = st.text_area(
height = text_area_height,
key = "mesh",
label = "Enter MeSH Main Headings, one per line.",
placeholder = mesh_term_example,
).splitlines()
subcol1, subcol2 = st.columns(2)
with subcol1:
majr = st.checkbox("MeSH Major Topic", key="majr")
with subcol2:
noexp = st.checkbox("Do not explode", key="noexp")
with mcol2:
subheadings = st.text_area(
height = text_area_height,
key = "subheadings",
label = "Enter MeSH Subheadings, one per line.",
placeholder = subheading_example,
).splitlines()
st.header("Pairwise Keyword Proximity Search", divider=True, anchor=False)
pcol1, pcol2 = st.columns(2)
with pcol1:
proximity_topic1_terms = st.text_area(
height = text_area_height,
key = "proximity topic 1",
label = "Enter Topic 1 terms, one per line, no truncation.",
placeholder = proximity_topic1_example,
).splitlines()
proximity_field = st.selectbox(
index=1,
key="pf",
label="Proximity field",
options=["ti", "tiab", "ad"],
)
with pcol2:
proximity_topic2_terms = st.text_area(
height = text_area_height,
key = "proximity topic 2",
label = "Enter Topic 2 terms, one per line, no truncation.",
placeholder = proximity_topic2_example,
).splitlines()
proximity_distance = st.number_input(
key = "pd",
label = "Proximity distance",
min_value = 0,
step = 1,
value = 2,
)
st.header("Pairwise Keyword Intersection Search (Boolean AND)", divider=True, anchor=False)
icol1, icol2 = st.columns(2)
with icol1:
intersection_topic1_terms = st.text_area(
height = text_area_height,
key = "intersection topic 1",
label = "Enter Topic 1 terms, one per line.",
placeholder = intersection_topic1_example,
).splitlines()
with icol2:
intersection_topic2_terms = st.text_area(
height = text_area_height,
key = "intersection topic 2",
label = "Enter Topic 2 terms, one per line.",
placeholder = intersection_topic2_example,
).splitlines()
search_field = st.selectbox(
index = 2,
label = "Search field",
key = "sf",
options = ["ti", "tiab", "tw", "all"],
)
st.divider()
bcol1, bcol2 = st.columns(2)
with bcol1:
clear = st.form_submit_button(
label = "Clear form inputs",
on_click = clear_form,
use_container_width = True,
)
with bcol2:
load_example = st.form_submit_button(
label = "Load example terms",
on_click = load_examples,
use_container_width = True,
)
submitted = st.form_submit_button(
label = "Generate pairwise search strings and PubMed search buttons",
use_container_width = True,
type="primary",
)
if submitted:
if (mesh_terms and subheadings) or (proximity_topic1_terms and proximity_topic2_terms) or (intersection_topic1_terms and intersection_topic2_terms):
st.header("Generated Search Strings", divider=True, anchor=False)
mesh_search_string = ""
if (mesh_terms and subheadings):
st.subheader("Pairwise MeSH Main/Subheading", divider=True, anchor=False)
if majr:
field = "majr"
else:
field = "mh"
if noexp:
field = field + ":noexp"
mesh_searches = [
f"{mesh_term}/{subheading}[{field}]"
for mesh_term in mesh_terms
for subheading in subheadings
]
mesh_search_string = " OR ".join(mesh_searches)
mesh_search_string_len = len(mesh_search_string)
mesh_search_string_exp = mesh_search_string_len < collapse_search_string_exp
if mesh_search_string:
with st.expander(f"Search String (length:{mesh_search_string_len} characters)", expanded=mesh_search_string_exp):
st.code(mesh_search_string, language="python", wrap_lines=True)
st.link_button(
label = "Search PubMed with pairwise MeSH heading/subheading search string",
type = "primary",
url = pubmed_search_url+mesh_search_string.replace(" ", "+"),
use_container_width = True,
)
# keyword_proximity_search_string = ""
if (proximity_topic1_terms and proximity_topic2_terms):
st.subheader("Pairwise Keyword Proximity", divider=True, anchor=False)
keyword_proximity_searches = [
f'"{ptopic1_term} {ptopic2_term}"[{proximity_field}:~{proximity_distance}]'
for ptopic1_term in proximity_topic1_terms
for ptopic2_term in proximity_topic2_terms
]
keyword_proximity_search_string = " OR ".join(keyword_proximity_searches)
keyword_proximity_search_string_len = len(keyword_proximity_search_string)
keyword_proximity_search_string_exp = keyword_proximity_search_string_len < collapse_search_string_exp
if keyword_proximity_search_string:
with st.expander(f"Search String (length: {len(keyword_proximity_search_string)} characters)", expanded=keyword_proximity_search_string_exp):
st.code(keyword_proximity_search_string, language="python", wrap_lines=True)
st.link_button(
label = "Search PubMed with pairwise keyword proximity search string",
type = "primary",
url = pubmed_search_url+keyword_proximity_search_string.replace(" ", "+"),
use_container_width = True,
)
if mesh_search_string:
mesh_proximity_search_string = " OR ".join([mesh_search_string, keyword_proximity_search_string])
mesh_proximity_search_string_len = len(mesh_proximity_search_string)
mesh_proximity_search_string_exp = mesh_proximity_search_string_len < collapse_search_string_exp
with st.expander(f"Union (Boolean OR) with MeSH search string (length: {len(mesh_proximity_search_string)} characters)", expanded=keyword_proximity_search_string_exp):
st.code(mesh_proximity_search_string, language="python", wrap_lines=True)
st.link_button(
label = "Search PubMed with union of pairwise MeSH/proximity search strings",
url = pubmed_search_url+mesh_proximity_search_string.replace(" ", "+"),
use_container_width = True,
)
# keyword_intersection_search_string = ""
if (intersection_topic1_terms and intersection_topic2_terms):
st.subheader("Pairwise Keyword Intersection", divider=True, anchor=False)
keyword_intersection_searches = [
f"({itopic1_term}[{search_field}] AND {itopic2_term}[{search_field}])"
for itopic1_term in intersection_topic1_terms
for itopic2_term in intersection_topic2_terms
]
keyword_intersection_search_string = " OR ".join(keyword_intersection_searches)
keyword_intersection_search_string_len = len(keyword_intersection_search_string)
keyword_intersection_search_string_exp = keyword_intersection_search_string_len < collapse_search_string_exp
if keyword_intersection_search_string:
with st.expander(f"Search String (length: {len(keyword_intersection_search_string)} characters)", expanded=keyword_intersection_search_string_exp):
st.code(keyword_intersection_search_string, language="python", wrap_lines=True)
st.link_button(
label = "Search PubMed with pairwise keyword intersection search string",
type = "primary",
url = pubmed_search_url+keyword_intersection_search_string.replace(" ", "+"),
use_container_width = True,
)
if mesh_search_string:
mesh_intersection_search_string = " OR ".join([mesh_search_string, keyword_intersection_search_string])
mesh_intersection_search_string_len = len(mesh_intersection_search_string)
mesh_intersection_search_string_exp = mesh_intersection_search_string_len < collapse_search_string_exp
with st.expander(f"Union (Boolean OR) with MeSH search string (length: {len(mesh_intersection_search_string)} characters, wildcard count: {keyword_intersection_search_string.count('*')})", expanded=keyword_intersection_search_string_exp):
st.code(mesh_intersection_search_string, language="python", wrap_lines=True)
st.link_button(
label = "Search PubMed with union of pairwise MeSH/intersection search strings",
url = pubmed_search_url+mesh_intersection_search_string.replace(" ", "+"),
use_container_width = True,
)
else:
# if not (mesh_terms and proximity_topic1_terms and intersection_topic1_terms):
st.error("Empty form inputs, no search strings generated.")