fulviodeo commited on
Commit
b4ecf44
·
1 Parent(s): 9635e4f

Changed main app title

Browse files
Dockerfile CHANGED
@@ -17,4 +17,4 @@ RUN mamba env create --prefix $HOME/env -f ./environment.yml
17
  EXPOSE 7860
18
  WORKDIR $HOME/app
19
 
20
- CMD mamba run -p $HOME/env --no-capture-output voila --no-browser notebooks/PopulationHealthScreener-Anthro.ipynb
 
17
  EXPOSE 7860
18
  WORKDIR $HOME/app
19
 
20
+ CMD mamba run -p $HOME/env --no-capture-output voila --no-browser notebooks/PopulationHealthScreener.ipynb
notebooks/PopulationHealthScreener-Anthro.ipynb DELETED
@@ -1,47 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "code",
5
- "execution_count": null,
6
- "id": "35bcc7331ef5d1dc",
7
- "metadata": {
8
- "ExecuteTime": {
9
- "end_time": "2025-04-10T15:52:17.264471Z",
10
- "start_time": "2025-04-10T15:52:17.156072Z"
11
- }
12
- },
13
- "outputs": [],
14
- "source": "import subprocess\nimport logging\nimport os\nimport base64\nimport uuid\nimport warnings\nfrom datetime import date\nfrom dateutil.relativedelta import relativedelta\n\nimport ipywidgets as widgets\nfrom IPython.display import clear_output, HTML, Javascript\nfrom IPython.utils.capture import capture_output\n\nfrom src.utils.prediction_table import PredictionTable\n\nwarnings.filterwarnings(\"ignore\")\nos.environ['TRANSFORMERS_VERBOSITY'] = 'error'\nos.environ['TQDM_DISABLE'] = '1'\nlogging.getLogger(\"transformers\").setLevel(logging.ERROR)\nlogging.getLogger(\"torch\").setLevel(logging.ERROR)\n\nwith capture_output():\n from src.handlers.model_wrapper import available_models\n\nfrom src.utils.ui_elements import (\n inject_styles, BOX_WIDTH, BUTTON_WIDTH, QUERY_WIDTH,\n make_button, make_separator, make_spacer, make_section_header,\n RunButton, error_html\n)\n\ninject_styles()\n\n# --- Globals ---\n\narticles_table = None\nmodel_loaded = False\noutput_dir = os.path.join(os.getcwd(), 'outputs')\nos.makedirs(output_dir, exist_ok=True)\ndirectory = output_dir\n\n# --- UI Elements ---\n\nmodel_dropdown = widgets.Dropdown(\n options=[m.name for m in available_models],\n value=available_models[0].name,\n description='',\n disabled=False,\n layout=widgets.Layout(width=BOX_WIDTH)\n)\n\n# Hidden Python-state widget for query source; visual display handled by _query_selector_ui below\nquery_selector = widgets.Dropdown(\n options=['paper', 'custom'],\n value='paper',\n layout=widgets.Layout(display='none')\n)\n\n_qid = query_selector.model_id\n_rname = f\"qs_{uuid.uuid4().hex[:8]}\"\n\ndef _js_sync(val):\n return (\n f\"(function(){{\"\n f\"try{{requirejs(['@jupyter-widgets/base'],function(b){{\"\n f\"var ms=b.ManagerBase._managers;\"\n f\"var mgr=ms?Object.values(ms)[0]:null;\"\n f\"mgr&&mgr.get_model('{_qid}').then(function(m){{m.set('value','{val}');m.save_changes();}});\"\n f\"}})}}catch(e){{}}\"\n f\"}})();\"\n )\n\ndef _render_query_html(disabled=False):\n dis = 'disabled' if disabled else ''\n opacity = 'opacity:0.6;' if disabled else ''\n cursor = 'default' if disabled else 'pointer'\n p_chk = 'checked' if query_selector.value == 'paper' else ''\n c_chk = 'checked' if query_selector.value == 'custom' else ''\n url = 'https://www.thelancet.com/journals/lancet/article/PIIS0140-6736(16)30054-X/abstract'\n return (\n f\"<div style='font-size:13px;line-height:2.2;{opacity}'>\"\n f\"<label style='cursor:{cursor};display:block;'>\"\n f\"<input type='radio' name='{_rname}' value='paper' {p_chk} {dis} onchange=\\\"{_js_sync('paper')}\\\">\"\n f\"&nbsp;Use the query from the \"\n f\"<a href='{url}' target='_blank' style='color:inherit;text-decoration:underline;'>\"\n f\"2016 paper by the NCD-RisC</a>\"\n f\"</label>\"\n f\"<label style='cursor:{cursor};display:block;'>\"\n f\"<input type='radio' name='{_rname}' value='custom' {c_chk} {dis} onchange=\\\"{_js_sync('custom')}\\\">\"\n f\"&nbsp;Use a custom query\"\n f\"</label>\"\n f\"</div>\"\n )\n\n_query_selector_ui = widgets.HTML(value=_render_query_html())\n\nquery_input = widgets.Textarea(\n placeholder='Enter PubMed query...',\n disabled=True,\n layout=widgets.Layout(width=QUERY_WIDTH, height='60px')\n)\n\ndef on_query_source_change(change):\n query_input.disabled = (change.new == 'paper')\n\nquery_selector.observe(on_query_source_change, names='value')\n\nstart_date_value = date.today() - relativedelta(months=1)\nend_date_value = date.today()\n\n_label_style = \"text-align:right; display:inline-block; width:75px; font-size:13px; line-height:28px; padding-right:6px;\"\n\nstart_date = widgets.DatePicker(value=start_date_value, description='')\nend_date = widgets.DatePicker(value=end_date_value, description='')\n\nstart_date_row = widgets.HBox([\n widgets.HTML(f\"<span style='{_label_style}'>Start date:</span>\"),\n start_date\n])\nend_date_row = widgets.HBox([\n widgets.HTML(f\"<span style='{_label_style}'>End date:</span>\"),\n end_date\n])\n\nrecall_target = widgets.Dropdown(\n options=[('95%', 95), ('90%', 90), ('80%', 80), ('70%', 70), ('60%', 60)],\n value=95,\n description='',\n disabled=True,\n layout=widgets.Layout(width='120px')\n)\n\n# RunButtons\nload_run = RunButton('Load', executing_msg='Loading...', error_label='Model')\nsearch_run = RunButton('Search', executing_msg='Searching...', error_label='Search')\npredict_run = RunButton('Screen articles', executing_msg='Screening...', error_label='Screening')\npredict_run.btn.disabled = True\n\n_predict_reset_btn = widgets.Button(\n description='\\u21ba',\n layout=widgets.Layout(width='32px', height='28px', display='none'),\n style=widgets.ButtonStyle()\n)\n\nunload_btn = make_button('Unload', width='100px')\nunload_btn.layout.display = 'none'\n\nfile_uploader = widgets.FileUpload(\n accept='.csv',\n multiple=False,\n description='Upload',\n layout=widgets.Layout(width=BUTTON_WIDTH, height='28px')\n)\n\n# Status widget — blank until articles are loaded\narticles_status = widgets.HTML(value='')\n\n# Error outputs\nload_file_error_out = widgets.Output()\n\n# Progress kept in memory for screen_articles.py callbacks (not displayed)\n_screen_progress = widgets.IntProgress(value=0, min=0, max=1)\n\ndef _on_screen_progress(change):\n if predict_run.btn.disabled:\n predict_run.btn.description = f'Screening... {change.new}/{_screen_progress.max}'\n\n_screen_progress.observe(_on_screen_progress, names='value')\n\n\n# --- Download link helpers ---\n# Each renders as: Download [editable box] .ext\n# \"Download\" is the underlined clickable word; the box sets the filename.\n\n_DL_SPAN = \"display:inline-flex;align-items:center;margin-left:12px;line-height:28px;\"\n_DL_LINK = \"font-size:12px;color:black;text-decoration:underline;line-height:28px;margin-right:3px;\"\n_DL_BOX = \"font-size:12px;border:1px solid #ccc;border-radius:3px;padding:1px 5px;height:20px;line-height:18px;width:130px;margin:0 2px;\"\n_DL_EXT = \"font-size:12px;line-height:28px;\"\n\n\ndef _download_link(df, default_stem):\n \"\"\"Download [box].csv\"\"\"\n b64 = base64.b64encode(df.to_csv(index=False).encode()).decode()\n uid = uuid.uuid4().hex[:8]\n return (\n f\"<span style='{_DL_SPAN}'>\"\n f\"<a id='anc-{uid}' href='data:text/csv;base64,{b64}' style='display:none'></a>\"\n f\"<a href='#' style='{_DL_LINK}'\"\n f\" onclick=\\\"var s=document.getElementById('inp-{uid}').value||'{default_stem}';\"\n f\"document.getElementById('anc-{uid}').download=s+'.csv';\"\n f\"document.getElementById('anc-{uid}').click();return false;\\\">Download</a>\"\n f\"<input id='inp-{uid}' type='text' value='{default_stem}' style='{_DL_BOX}'>\"\n f\"<span style='{_DL_EXT}'>.csv</span>\"\n f\"</span>\"\n )\n\n\ndef _ris_content(df):\n lines = []\n for _, row in df.iterrows():\n lines.append(\"TI - \" + str(row.get('Title') or ''))\n lines.append(\"AB - \" + str(row.get('Abstract') or ''))\n for author in str(row.get('Authors') or '').split(','):\n lines.append(\"AU - \" + author.strip())\n lines.append(\"DO - \" + str(row.get('DOI') or ''))\n lines.append(\"PM - \" + str(row.get('PMID') or ''))\n lines.append(\"PY - \" + str(row.get('Year') or ''))\n lines.append(\"JO - \" + str(row.get('Journal') or ''))\n lines.append(\"ER - \")\n lines.append(\"\")\n return \"\\n\".join(lines)\n\n\ndef _download_link_combined(df, default_stem):\n \"\"\"Download [box].csv — also triggers .ris download on same click.\"\"\"\n csv_b64 = base64.b64encode(df.to_csv(index=False).encode()).decode()\n ris_b64 = base64.b64encode(_ris_content(df).encode('utf-8')).decode()\n uid = uuid.uuid4().hex[:8]\n return (\n f\"<span style='{_DL_SPAN}'>\"\n f\"<a id='csv-{uid}' href='data:text/csv;base64,{csv_b64}' style='display:none'></a>\"\n f\"<a id='ris-{uid}' href='data:application/x-research-info-systems;base64,{ris_b64}' style='display:none'></a>\"\n f\"<a href='#' style='{_DL_LINK}'\"\n f\" onclick=\\\"var s=document.getElementById('inp-{uid}').value||'{default_stem}';\"\n f\"document.getElementById('csv-{uid}').download=s+'.csv';\"\n f\"document.getElementById('csv-{uid}').click();\"\n f\"setTimeout(function(){{document.getElementById('ris-{uid}').download=s+'.ris';\"\n f\"document.getElementById('ris-{uid}').click();}},150);\"\n f\"return false;\\\">Download</a>\"\n f\"<input id='inp-{uid}' type='text' value='{default_stem}' style='{_DL_BOX}'>\"\n f\"<span style='{_DL_EXT}'>.csv</span>\"\n f\"</span>\"\n )\n\n\ndef _download_link_predictions(df, default_stem):\n \"\"\"Download [box] predictions.csv\"\"\"\n b64 = base64.b64encode(df.to_csv(index=False).encode()).decode()\n uid = uuid.uuid4().hex[:8]\n return (\n f\"<span style='{_DL_SPAN}'>\"\n f\"<a id='anc-{uid}' href='data:text/csv;base64,{b64}' style='display:none'></a>\"\n f\"<a href='#' style='{_DL_LINK}'\"\n f\" onclick=\\\"var s=document.getElementById('inp-{uid}').value||'{default_stem}';\"\n f\"document.getElementById('anc-{uid}').download=s+' predictions.csv';\"\n f\"document.getElementById('anc-{uid}').click();return false;\\\">Download</a>\"\n f\"<input id='inp-{uid}' type='text' value='{default_stem}' style='{_DL_BOX}'>\"\n f\"<span style='{_DL_EXT}'>&nbsp;predictions.csv</span>\"\n f\"</span>\"\n )\n\n\ndef _set_search_side_disabled(disabled):\n query_selector.disabled = disabled\n _query_selector_ui.value = _render_query_html(disabled)\n query_input.disabled = disabled or (query_selector.value == 'paper')\n start_date.disabled = disabled\n end_date.disabled = disabled\n search_run.btn.disabled = disabled\n\n\ndef _set_load_side_disabled(disabled):\n file_uploader.disabled = disabled\n\n\ndef _update_predict_state():\n ready = model_loaded and articles_table is not None\n recall_target.disabled = not ready\n predict_run.btn.disabled = not ready\n\n\ndef _set_articles(table, display_name):\n global articles_table\n articles_table = table\n articles_status.value = (\n f\"<span style='color:#28a745; font-size:13px; line-height:28px; margin-right:10px;'>\"\n f\"Loaded {display_name}</span>\"\n )\n unload_btn.layout.display = ''\n _update_predict_state()\n\n\ndef _unset_articles():\n global articles_table\n articles_table = None\n articles_status.value = ''\n unload_btn.layout.display = 'none'\n _update_predict_state()\n\n\n# --- Event Handlers ---\n\ndef run_load_model(b):\n global model_loaded\n load_run.start()\n try:\n with capture_output():\n with open(os.path.abspath(os.path.join(os.getcwd(), 'src/choose_model.py'))) as f:\n exec(f.read(), globals())\n model_loaded = True\n load_run.done('\\u2713 Model loaded')\n _update_predict_state()\n except Exception as e:\n model_loaded = False\n load_run.fail(e)\n\n\ndef run_search(b):\n global articles_table\n search_run.start()\n _saved_start = start_date.value\n _saved_end = end_date.value\n _set_search_side_disabled(True)\n start_date.value = _saved_start\n end_date.value = _saved_end\n try:\n with capture_output():\n with open(os.path.abspath(os.path.join(os.getcwd(), 'src/search_pubmed.py'))) as f:\n exec(f.read(), globals())\n search_run.done('\\u2713 Search completed')\n _set_load_side_disabled(True)\n _set_articles(articles_table, 'Articles.csv')\n search_run.out.value = _download_link(articles_table.df, 'Articles')\n except Exception as e:\n _set_search_side_disabled(False)\n search_run.fail(e)\n\n\ndef on_file_uploaded(change):\n if not change.new:\n return\n with load_file_error_out:\n clear_output(wait=True)\n try:\n file_info = change.new[0]\n name = file_info['name']\n content = bytes(file_info['content'])\n table = PredictionTable.from_bytes(content)\n file_uploader.description = '\\u2713 Upload completed'\n file_uploader.add_class('done-button')\n _set_articles(table, name)\n _set_search_side_disabled(True)\n except Exception as e:\n from IPython.display import display\n with load_file_error_out:\n clear_output(wait=True)\n display(widgets.HTML(\n f\"<span style='color:#dc3545; font-size:12px; margin-left:12px; line-height:28px;'>\"\n f\"<b>{type(e).__name__}</b>: {e}</span>\"\n ))\n\nfile_uploader.observe(on_file_uploaded, names='value')\n\n\ndef on_unload(b):\n _unset_articles()\n _set_search_side_disabled(False)\n _set_load_side_disabled(False)\n file_uploader.description = 'Upload'\n file_uploader.remove_class('done-button')\n search_run.reset()\n _predict_reset_btn.layout.display = 'none'\n with load_file_error_out:\n clear_output(wait=True)\n\n\ndef run_screen_articles(b):\n predict_run.start()\n _predict_reset_btn.layout.display = 'none'\n _screen_progress.value = 0\n try:\n with capture_output():\n with open(os.path.abspath(os.path.join(os.getcwd(), 'src/screen_articles.py'))) as f:\n exec(f.read(), globals())\n predict_run.done('\\u2713 Screening completed')\n _predict_reset_btn.layout.display = ''\n review_df = globals().get('review_data')\n pred_df = globals().get('data')\n predict_run.out.value = (\n _download_link_combined(review_df, 'Screened articles') +\n '<br>' +\n _download_link_predictions(pred_df, 'Screened articles')\n )\n except Exception as e:\n predict_run.fail(e)\n\n\ndef on_predict_reset(b):\n predict_run.reset()\n _predict_reset_btn.layout.display = 'none'\n _update_predict_state()\n\n_predict_reset_btn.on_click(on_predict_reset)\n\nload_run.on_click(run_load_model)\nsearch_run.on_click(run_search)\npredict_run.on_click(run_screen_articles)\nunload_btn.on_click(on_unload)\n\n# --- Layout ---\n\nheader = widgets.HTML(\n \"<h2 style='margin: 8px 0 12px 12px; font-size:22px; font-weight:bold;'>PopulationHealthScreener</h2>\"\n)\n\n# 1 - Choose a model\nchoose_model = widgets.VBox([\n make_section_header('Choose a model'),\n model_dropdown,\n make_spacer('20px'),\n load_run.row,\n], layout=widgets.Layout(margin='0 0 0 12px'))\n\n# 2 - Search PubMed (left) | or + Load from file (right) | articles status (bottom)\n_search_left = widgets.VBox([\n make_section_header('Search PubMed'),\n make_spacer('8px'),\n query_selector,\n _query_selector_ui,\n make_spacer('2px'),\n query_input,\n make_spacer('10px'),\n start_date_row,\n end_date_row,\n make_spacer('12px'),\n search_run.row,\n])\n\n_load_content = widgets.VBox([\n make_section_header('Load articles from a file'),\n make_spacer('8px'),\n widgets.HBox([file_uploader, load_file_error_out]),\n], layout=widgets.Layout(margin='0 0 0 20px'))\n\n_load_section = widgets.HBox(\n [widgets.HTML(\"<span style='font-size:16px;'>or</span>\"), _load_content],\n layout=widgets.Layout(align_items='flex-start', margin='0 0 0 24px')\n)\n\nsearch_pubmed = widgets.VBox([\n widgets.HBox(\n [_search_left, _load_section],\n layout=widgets.Layout(align_items='flex-start')\n ),\n make_spacer('12px'),\n widgets.HBox([articles_status, unload_btn]),\n], layout=widgets.Layout(margin='0 0 0 12px'))\n\n# 3 - Screen articles\n_screen_title_row = widgets.HBox([\n make_section_header('Screen articles'),\n _predict_reset_btn,\n], layout=widgets.Layout(align_items='center'))\n\nscreen_articles = widgets.VBox([\n _screen_title_row,\n make_spacer('8px'),\n widgets.HBox([\n widgets.HTML(\"<span style='font-size:13px; line-height:28px; margin-right:8px;'>Target recall</span>\"),\n recall_target,\n widgets.HTML(\"<span style='font-size:13px; color:gray; margin-left:12px; line-height:28px;'>Based on the recall achieved in previous testing; the higher the recall, the more inclusive the model</span>\"),\n ], layout=widgets.Layout(align_items='center')),\n make_spacer('12px'),\n predict_run.row,\n], layout=widgets.Layout(margin='0 0 0 12px'))\n\n\ndisplay(header, choose_model, make_separator(), search_pubmed, make_separator(), screen_articles)\n"
15
- },
16
- {
17
- "cell_type": "code",
18
- "execution_count": null,
19
- "id": "eeebfa287ae99109",
20
- "metadata": {},
21
- "outputs": [],
22
- "source": ""
23
- }
24
- ],
25
- "metadata": {
26
- "kernelspec": {
27
- "display_name": "Python 3 (ipykernel)",
28
- "language": "python",
29
- "name": "python3"
30
- },
31
- "language_info": {
32
- "codemirror_mode": {
33
- "name": "ipython",
34
- "version": 3
35
- },
36
- "file_extension": ".py",
37
- "mimetype": "text/x-python",
38
- "name": "python",
39
- "nbconvert_exporter": "python",
40
- "pygments_lexer": "ipython3",
41
- "version": "3.12.9"
42
- },
43
- "trusted": true
44
- },
45
- "nbformat": 4,
46
- "nbformat_minor": 5
47
- }