cmcmaster commited on
Commit
9f0b3d4
·
verified ·
1 Parent(s): 53cfe0d

Migrate to Gradio

Browse files
Files changed (1) hide show
  1. main.py +165 -277
main.py CHANGED
@@ -1,94 +1,15 @@
1
- from fasthtml.common import *
2
  from datasets import load_dataset
3
  import datetime
4
  from pbs_data import PBSPublicDataAPIClient
5
  import os
6
- from fasthtml_hf import setup_hf_backup
7
- from fasthtml import FastHTML
8
  from apscheduler.schedulers.background import BackgroundScheduler
9
  from apscheduler.triggers.interval import IntervalTrigger
10
  import atexit
11
 
12
  HF_TOKEN = os.environ.get("HF_TOKEN")
13
-
14
-
15
- custom_css = Style("""
16
- body {
17
- font-family: Arial, sans-serif;
18
- line-height: 1.6;
19
- color: #333;
20
- max-width: 800px;
21
- margin: 0 auto;
22
- padding: 20px;
23
- background-color: #f0f0f0;
24
- }
25
- h1 {
26
- color: #2c3e50;
27
- text-align: center;
28
- margin-bottom: 30px;
29
- }
30
- form {
31
- background-color: #ffffff;
32
- padding: 20px;
33
- border-radius: 8px;
34
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
35
- }
36
- label {
37
- display: block;
38
- margin-bottom: 5px;
39
- font-weight: bold;
40
- color: #2c3e50;
41
- }
42
- select, button {
43
- width: 100%;
44
- padding: 10px;
45
- margin-bottom: 15px;
46
- border: 1px solid #ddd;
47
- border-radius: 4px;
48
- background-color: #fff;
49
- color: #333;
50
- }
51
- button {
52
- background-color: #3498db;
53
- color: white;
54
- font-weight: bold;
55
- cursor: pointer;
56
- transition: background-color 0.3s;
57
- }
58
- button:hover {
59
- background-color: #2980b9;
60
- }
61
- #results {
62
- margin-top: 30px;
63
- background-color: #ffffff;
64
- padding: 20px;
65
- border-radius: 8px;
66
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
67
- }
68
- #results h2 {
69
- color: #2c3e50;
70
- border-bottom: 2px solid #3498db;
71
- padding-bottom: 10px;
72
- }
73
- #results p {
74
- margin-bottom: 10px;
75
- color: #333;
76
- }
77
- #results hr {
78
- border: none;
79
- border-top: 1px solid #eee;
80
- margin: 20px 0;
81
- }
82
- a {
83
- color: #3498db;
84
- text-decoration: none;
85
- }
86
- a:hover {
87
- text-decoration: underline;
88
- }
89
- """)
90
-
91
  DATASET_NAME = "cmcmaster/rheumatology-biologics-dataset"
 
92
 
93
  def load_data():
94
  try:
@@ -125,16 +46,14 @@ def load_data():
125
 
126
  biologics_data = load_data()
127
 
128
- app, rt = fast_app()
129
-
130
- def search_biologics(drug, brand, formulation, indication, treatment_phase, hospital_type):
131
- results = biologics_data['combinations'].filter(
132
  lambda x: (not drug or x['drug'] == drug) and
133
- (not brand or x['brand'] == brand) and
134
- (not formulation or x['formulation'] == formulation) and
135
- (not indication or x['indication'] == indication) and
136
- (not treatment_phase or x['treatment_phase'] == treatment_phase) and
137
- (not hospital_type or x['hospital_type'] == hospital_type)
138
  )
139
 
140
  if len(results) == 0:
@@ -143,198 +62,167 @@ def search_biologics(drug, brand, formulation, indication, treatment_phase, hosp
143
  output = ""
144
  for item in results:
145
  output += f"""
146
- <div class="result-item">
147
- <h2>{item['drug']} ({item['brand']})</h2>
148
- <p><strong>PBS Code:</strong> <a href="https://www.pbs.gov.au/medicine/item/{item['pbs_code']}" target="_blank">{item['pbs_code']}</a></p>
149
- <p><strong>Formulation:</strong> {item['formulation']}</p>
150
- <p><strong>Indication:</strong> {item['indication']}</p>
151
- <p><strong>Treatment Phase:</strong> {item['treatment_phase']}</p>
152
- <p><strong>Streamlined Code:</strong> {item['streamlined_code'] or 'N/A'}</p>
153
- <p><strong>Authority Method:</strong> {item['authority_method']}</p>
154
- <p><strong>Online Application:</strong> {'Yes' if item['online_application'] else 'No'}</p>
155
- <p><strong>Hospital Type:</strong> {item['hospital_type']}</p>
156
- <p><strong>Schedule Year:</strong> {item['schedule_year']}</p>
157
- <p><strong>Schedule Month:</strong> {item['schedule_month']}</p>
158
- </div>
159
- <hr>
160
- """
161
-
162
  return output
163
 
164
- def update_options(drug, brand, formulation, indication, treatment_phase, hospital_type):
165
- filtered = biologics_data['combinations'].filter(
166
- lambda x: (not drug or x['drug'] == drug) and
167
- (not brand or x['brand'] == brand) and
168
- (not formulation or x['formulation'] == formulation) and
169
- (not indication or x['indication'] == indication) and
170
- (not treatment_phase or x['treatment_phase'] == treatment_phase) and
171
- (not hospital_type or x['hospital_type'] == hospital_type)
172
- )
173
-
174
- options = {
175
- 'drugs': sorted(set(filtered['drug'])),
176
- 'brands': sorted(set(filtered['brand'])),
177
- 'formulations': sorted(set(filtered['formulation'])),
178
- 'indications': sorted(set(filtered['indication'])),
179
- 'treatment_phases': sorted(set(filtered['treatment_phase'])),
180
- 'hospital_types': sorted(set(filtered['hospital_type']))
181
- }
182
-
183
- return options
184
-
185
- @rt('/')
186
- def get():
187
- return Div(
188
- custom_css,
189
- H1("Biologics Prescriber Helper"),
190
- Form(
191
- Div(
192
- Label("Drug:"),
193
- Select(Option("All", value=""), *[Option(drug, value=drug) for drug in biologics_data['drugs']], name="drug", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
194
- ),
195
- Div(
196
- Label("Brand:"),
197
- Select(Option("All", value=""), *[Option(brand, value=brand) for brand in biologics_data['brands']], name="brand", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
198
- ),
199
- Div(
200
- Label("Formulation:"),
201
- Select(Option("All", value=""), *[Option(formulation, value=formulation) for formulation in biologics_data['formulations']], name="formulation", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
202
- ),
203
- Div(
204
- Label("Indication:"),
205
- Select(Option("All", value=""), *[Option(indication, value=indication) for indication in biologics_data['indications']], name="indication", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
206
- ),
207
- Div(
208
- Label("Treatment Phase:"),
209
- Select(Option("All", value=""), *[Option(phase, value=phase) for phase in biologics_data['treatment_phases']], name="treatment_phase", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
210
- ),
211
- Div(
212
- Label("Hospital Type:"),
213
- Select(Option("All", value=""), *[Option(ht, value=ht) for ht in biologics_data['hospital_types']], name="hospital_type", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
214
- ),
215
- Div(
216
- Button("Search", type="submit"),
217
- Button("Reset", hx_get="/reset", hx_target="#options")
218
- ),
219
- hx_post="/search",
220
- hx_target="#results",
221
- id="options"
222
- ),
223
- Div(id="results")
224
- )
225
-
226
- @rt('/reset')
227
- def get():
228
- return Div(
229
- custom_css,
230
- Form(
231
- Div(
232
- Label("Drug:"),
233
- Select(Option("All", value=""), *[Option(drug, value=drug) for drug in biologics_data['drugs']], name="drug", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
234
- ),
235
- Div(
236
- Label("Brand:"),
237
- Select(Option("All", value=""), *[Option(brand, value=brand) for brand in biologics_data['brands']], name="brand", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
238
- ),
239
- Div(
240
- Label("Formulation:"),
241
- Select(Option("All", value=""), *[Option(formulation, value=formulation) for formulation in biologics_data['formulations']], name="formulation", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
242
- ),
243
- Div(
244
- Label("Indication:"),
245
- Select(Option("All", value=""), *[Option(indication, value=indication) for indication in biologics_data['indications']], name="indication", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
246
- ),
247
- Div(
248
- Label("Treatment Phase:"),
249
- Select(Option("All", value=""), *[Option(phase, value=phase) for phase in biologics_data['treatment_phases']], name="treatment_phase", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
250
- ),
251
- Div(
252
- Label("Hospital Type:"),
253
- Select(Option("All", value=""), *[Option(ht, value=ht) for ht in biologics_data['hospital_types']], name="hospital_type", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
254
- ),
255
- Div(
256
- Button("Search", type="submit"),
257
- Button("Reset", hx_get="/reset", hx_target="#options")
258
- ),
259
- hx_post="/search",
260
- hx_target="#results",
261
- id="options"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  )
263
- )
264
 
265
- @rt('/update_options')
266
- def get(drug: str = '', brand: str = '', formulation: str = '', indication: str = '', treatment_phase: str = '', hospital_type: str = ''):
267
- options = update_options(drug, brand, formulation, indication, treatment_phase, hospital_type)
268
- return Div(
269
- custom_css,
270
- Form(
271
- Div(
272
- Label("Drug:"),
273
- Select(Option("All", value=""), *[Option(d, value=d, selected=(d == drug)) for d in options['drugs']], name="drug", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
274
- ),
275
- Div(
276
- Label("Brand:"),
277
- Select(Option("All", value=""), *[Option(b, value=b, selected=(b == brand)) for b in options['brands']], name="brand", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
278
- ),
279
- Div(
280
- Label("Formulation:"),
281
- Select(Option("All", value=""), *[Option(f, value=f, selected=(f == formulation)) for f in options['formulations']], name="formulation", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
282
- ),
283
- Div(
284
- Label("Indication:"),
285
- Select(Option("All", value=""), *[Option(i, value=i, selected=(i == indication)) for i in options['indications']], name="indication", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
286
- ),
287
- Div(
288
- Label("Treatment Phase:"),
289
- Select(Option("All", value=""), *[Option(p, value=p, selected=(p == treatment_phase)) for p in options['treatment_phases']], name="treatment_phase", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
290
- ),
291
- Div(
292
- Label("Hospital Type:"),
293
- Select(Option("All", value=""), *[Option(ht, value=ht, selected=(ht == hospital_type)) for ht in options['hospital_types']], name="hospital_type", hx_get="/update_options", hx_target="#options", hx_trigger="change", hx_include="[name='drug'],[name='brand'],[name='formulation'],[name='indication'],[name='treatment_phase'],[name='hospital_type']")
294
- ),
295
- Div(
296
- Button("Search", type="submit"),
297
- Button("Reset", hx_get="/reset", hx_target="#options")
298
- ),
299
- hx_post="/search",
300
- hx_target="#results",
301
- id="options"
302
  )
303
- )
304
-
305
- @rt('/search')
306
- def post(drug: str = '', brand: str = '', formulation: str = '', indication: str = '', treatment_phase: str = '', hospital_type: str = ''):
307
- results = search_biologics(drug, brand, formulation, indication, treatment_phase, hospital_type)
308
- return results
309
 
310
- def update_data():
311
- print(f"Updating data at {datetime.datetime.now()}")
312
- client = PBSPublicDataAPIClient("2384af7c667342ceb5a736fe29f1dc6b", rate_limit=0.2)
313
- try:
314
- data = client.fetch_rheumatology_biologics_data()
315
- client.save_data_to_hf(data, HF_TOKEN, DATASET_NAME)
316
- print("Data updated successfully")
317
- global biologics_data
318
- biologics_data = load_data()
319
- except Exception as e:
320
- print(f"An error occurred while updating data: {str(e)}")
321
-
322
- # Set up the scheduler
323
- update_data()
324
- # Set up the scheduler
325
- scheduler = BackgroundScheduler()
326
- scheduler.add_job(
327
- func=update_data,
328
- trigger=IntervalTrigger(hours=24),
329
- id='update_data',
330
- name='Update Data',
331
- replace_existing=True
332
- )
333
- scheduler.start()
334
-
335
- # Make sure to shut down the scheduler when the app is terminated
336
 
337
- atexit.register(lambda: scheduler.shutdown())
 
338
 
339
- setup_hf_backup(app)
340
- serve()
 
 
 
1
+ import gradio as gr
2
  from datasets import load_dataset
3
  import datetime
4
  from pbs_data import PBSPublicDataAPIClient
5
  import os
 
 
6
  from apscheduler.schedulers.background import BackgroundScheduler
7
  from apscheduler.triggers.interval import IntervalTrigger
8
  import atexit
9
 
10
  HF_TOKEN = os.environ.get("HF_TOKEN")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  DATASET_NAME = "cmcmaster/rheumatology-biologics-dataset"
12
+ UPDATE_INTERVAL = 1
13
 
14
  def load_data():
15
  try:
 
46
 
47
  biologics_data = load_data()
48
 
49
+ def search_biologics(drug, brand, formulation, indication, treatment_phase, hospital_type, state):
50
+ results = state['combinations'].filter(
 
 
51
  lambda x: (not drug or x['drug'] == drug) and
52
+ (not brand or x['brand'] == brand) and
53
+ (not formulation or x['formulation'] == formulation) and
54
+ (not indication or x['indication'] == indication) and
55
+ (not treatment_phase or x['treatment_phase'] == treatment_phase) and
56
+ (not hospital_type or x['hospital_type'] == hospital_type)
57
  )
58
 
59
  if len(results) == 0:
 
62
  output = ""
63
  for item in results:
64
  output += f"""
65
+ ### {item['drug']} ({item['brand']})
66
+
67
+ * **PBS Code:** [{item['pbs_code']}](https://www.pbs.gov.au/medicine/item/{item['pbs_code']})
68
+ * **Formulation:** {item['formulation']}
69
+ * **Indication:** {item['indication']}
70
+ * **Treatment Phase:** {item['treatment_phase']}
71
+ * **Streamlined Code:** {item['streamlined_code'] or 'N/A'}
72
+ * **Authority Method:** {item['authority_method']}
73
+ * **Online Application:** {'Yes' if item['online_application'] else 'No'}
74
+ * **Hospital Type:** {item['hospital_type']}
75
+ * **Schedule:** {item['schedule_month']} {item['schedule_year']}
76
+
77
+ ---
78
+ """
 
 
79
  return output
80
 
81
+ def update_data():
82
+ # Check the date - if it's the first day of the month then update the data, otherwise
83
+ if datetime.datetime.now().day == 1:
84
+ print(f"Updating data at {datetime.datetime.now()}")
85
+ client = PBSPublicDataAPIClient("2384af7c667342ceb5a736fe29f1dc6b", rate_limit=0.2)
86
+ try:
87
+ data = client.fetch_rheumatology_biologics_data()
88
+ client.save_data_to_hf(data, HF_TOKEN, DATASET_NAME)
89
+ print("Data updated successfully")
90
+ global biologics_data
91
+ biologics_data = load_data()
92
+ except Exception as e:
93
+ print(f"An error occurred while updating data: {str(e)}")
94
+ else:
95
+ print(f"Not updating data at {datetime.datetime.now()}")
96
+
97
+ def create_interface():
98
+ with gr.Blocks(title="Biologics Prescriber Helper") as demo:
99
+ gr.Markdown("# Biologics Prescriber Helper")
100
+
101
+ # Create session state to store filtered data for each user
102
+ session_data = gr.State(biologics_data)
103
+
104
+ def update_dropdown_choices(drug, brand, formulation, indication, treatment_phase, hospital_type, state):
105
+ # Filter the dataset based on current selections
106
+ filtered = state['combinations'].filter(
107
+ lambda x: (not drug or x['drug'] == drug) and
108
+ (not brand or x['brand'] == brand) and
109
+ (not formulation or x['formulation'] == formulation) and
110
+ (not indication or x['indication'] == indication) and
111
+ (not treatment_phase or x['treatment_phase'] == treatment_phase) and
112
+ (not hospital_type or x['hospital_type'] == hospital_type)
113
+ )
114
+
115
+ # Get unique values for each field from filtered dataset
116
+ available_options = {
117
+ 'drugs': [""] + sorted(set(filtered['drug'])),
118
+ 'brands': [""] + sorted(set(filtered['brand'])),
119
+ 'formulations': [""] + sorted(set(filtered['formulation'])),
120
+ 'indications': [""] + sorted(set(filtered['indication'])),
121
+ 'treatment_phases': [""] + sorted(set(filtered['treatment_phase'])),
122
+ 'hospital_types': [""] + sorted(set(filtered['hospital_type']))
123
+ }
124
+
125
+ # Return the choices and current values for each dropdown
126
+ return (
127
+ gr.Dropdown(choices=available_options['drugs'], value=drug if drug in available_options['drugs'] else ""),
128
+ gr.Dropdown(choices=available_options['brands'], value=brand if brand in available_options['brands'] else ""),
129
+ gr.Dropdown(choices=available_options['formulations'], value=formulation if formulation in available_options['formulations'] else ""),
130
+ gr.Dropdown(choices=available_options['indications'], value=indication if indication in available_options['indications'] else ""),
131
+ gr.Dropdown(choices=available_options['treatment_phases'], value=treatment_phase if treatment_phase in available_options['treatment_phases'] else ""),
132
+ gr.Dropdown(choices=available_options['hospital_types'], value=hospital_type if hospital_type in available_options['hospital_types'] else ""),
133
+ state # Return state unchanged
134
+ )
135
+
136
+ with gr.Row():
137
+ with gr.Column():
138
+ drug = gr.Dropdown(
139
+ choices=[""] + biologics_data['drugs'],
140
+ label="Drug",
141
+ value="",
142
+ interactive=True
143
+ )
144
+ brand = gr.Dropdown(
145
+ choices=[""] + biologics_data['brands'],
146
+ label="Brand",
147
+ value="",
148
+ interactive=True
149
+ )
150
+ formulation = gr.Dropdown(
151
+ choices=[""] + biologics_data['formulations'],
152
+ label="Formulation",
153
+ value="",
154
+ interactive=True
155
+ )
156
+
157
+ with gr.Column():
158
+ indication = gr.Dropdown(
159
+ choices=[""] + biologics_data['indications'],
160
+ label="Indication",
161
+ value="",
162
+ interactive=True
163
+ )
164
+ treatment_phase = gr.Dropdown(
165
+ choices=[""] + biologics_data['treatment_phases'],
166
+ label="Treatment Phase",
167
+ value="",
168
+ interactive=True
169
+ )
170
+ hospital_type = gr.Dropdown(
171
+ choices=[""] + biologics_data['hospital_types'],
172
+ label="Hospital Type",
173
+ value="",
174
+ interactive=True
175
+ )
176
+
177
+ with gr.Row():
178
+ search_btn = gr.Button("Search", variant="primary")
179
+ clear_btn = gr.Button("Reset")
180
+
181
+ results = gr.Markdown()
182
+
183
+ def reset_inputs(state):
184
+ return (*update_dropdown_choices("", "", "", "", "", "", state)[:-1], state)
185
+
186
+ # Update dropdowns when any selection changes
187
+ all_dropdowns = [drug, brand, formulation, indication, treatment_phase, hospital_type]
188
+ for dropdown in all_dropdowns:
189
+ dropdown.change(
190
+ fn=update_dropdown_choices,
191
+ inputs=[drug, brand, formulation, indication, treatment_phase, hospital_type, session_data],
192
+ outputs=[drug, brand, formulation, indication, treatment_phase, hospital_type, session_data]
193
+ )
194
+
195
+ search_btn.click(
196
+ fn=search_biologics,
197
+ inputs=[drug, brand, formulation, indication, treatment_phase, hospital_type, session_data],
198
+ outputs=results
199
  )
 
200
 
201
+ clear_btn.click(
202
+ fn=reset_inputs,
203
+ inputs=[session_data],
204
+ outputs=[drug, brand, formulation, indication, treatment_phase, hospital_type, session_data]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  )
 
 
 
 
 
 
206
 
207
+ return demo
208
+
209
+ if UPDATE_INTERVAL > 0:
210
+ # Set up the scheduler
211
+ update_data()
212
+ scheduler = BackgroundScheduler()
213
+ scheduler.add_job(
214
+ func=update_data,
215
+ trigger=IntervalTrigger(days=UPDATE_INTERVAL),
216
+ id='update_data',
217
+ name='Update Data',
218
+ replace_existing=True
219
+ )
220
+ scheduler.start()
 
 
 
 
 
 
 
 
 
 
 
 
221
 
222
+ # Shutdown scheduler when app terminates
223
+ atexit.register(lambda: scheduler.shutdown())
224
 
225
+ # Create and launch the interface
226
+ if __name__ == "__main__":
227
+ demo = create_interface()
228
+ demo.launch()