Merge branch 'main' of ssh://git.youainti.com:3022/Research/ClinicalTrials_DataLinkers
commit
363dc5e3da
@ -0,0 +1,47 @@
|
||||
from flask import (Flask,render_template)
|
||||
import os
|
||||
from .db_interface import get_connection_details, check_connection
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def create_app(test_config=None):
|
||||
# create and configure the app
|
||||
app = Flask(__name__, instance_relative_config=True)
|
||||
app.config.from_mapping(
|
||||
SECRET_KEY='6e674d6e41b733270fd01c6257b3a1b4769eb80f3f773cd0fe8eff25f350fc1f',
|
||||
POSTGRES_DB="aact_db",
|
||||
POSTGRES_USER="root",
|
||||
POSTGRES_HOST="localhost",
|
||||
POSTGRES_PORT=5432,
|
||||
POSTGRES_PASSWORD="root",
|
||||
)
|
||||
|
||||
|
||||
# ensure the instance folder exists
|
||||
try:
|
||||
os.makedirs(app.instance_path)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# a simple page that says hello
|
||||
@app.route('/')
|
||||
def hello():
|
||||
return render_template("index.html")
|
||||
|
||||
|
||||
@app.route('/debug')
|
||||
def debug_info():
|
||||
return {
|
||||
"connection": get_connection_details(),
|
||||
}
|
||||
|
||||
|
||||
|
||||
from . import matching
|
||||
app.register_blueprint(matching.bp)
|
||||
|
||||
|
||||
return app
|
||||
@ -0,0 +1,163 @@
|
||||
import psycopg as psyco
|
||||
from datetime import datetime
|
||||
from flask import current_app,g
|
||||
|
||||
|
||||
def get_db(**kwargs):
|
||||
|
||||
if "db" not in g:
|
||||
g.db = psyco.connect(
|
||||
dbname=current_app.config["POSTGRES_DB"]
|
||||
,user=current_app.config["POSTGRES_USER"]
|
||||
,host=current_app.config["POSTGRES_HOST"]
|
||||
,port=current_app.config["POSTGRES_PORT"]
|
||||
,password=current_app.config["POSTGRES_PASSWORD"]
|
||||
,**kwargs
|
||||
)
|
||||
return g.db
|
||||
|
||||
def close_db(e=None):
|
||||
db = g.pop('db', None)
|
||||
|
||||
if db is not None:
|
||||
db.close()
|
||||
|
||||
def get_connection_details():
|
||||
return {
|
||||
"dbname":current_app.config["POSTGRES_DB"]
|
||||
,"user":current_app.config["POSTGRES_USER"]
|
||||
,"host":current_app.config["POSTGRES_HOST"]
|
||||
,"port":current_app.config["POSTGRES_PORT"]
|
||||
,"password":current_app.config["POSTGRES_PASSWORD"]
|
||||
}
|
||||
|
||||
def check_connection(app):
|
||||
db = get_db()
|
||||
with db.cursor() as curse:
|
||||
curse.execute("select count(*) from \"DiseaseBurden\".trial_to_icd10")
|
||||
curse.fetchall()
|
||||
#just checking if everything is going to fail
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def get_trial_summary(db_conn,nct_id):
|
||||
sql_summary ="""
|
||||
/*get brief and detailed descriptions*/
|
||||
select
|
||||
s.nct_id,
|
||||
brief_title ,
|
||||
official_title ,
|
||||
bs.description as brief_description,
|
||||
dd.description as detailed_description
|
||||
from ctgov.studies s
|
||||
left join ctgov.brief_summaries bs
|
||||
on bs.nct_id = s.nct_id
|
||||
left join ctgov.detailed_descriptions dd
|
||||
on dd.nct_id = s.nct_id
|
||||
where s.nct_id = %s
|
||||
;
|
||||
"""
|
||||
sql_conditions="""
|
||||
--conditions mentioned
|
||||
select * from ctgov.conditions c
|
||||
where c.nct_id = %s
|
||||
;
|
||||
"""
|
||||
sql_keywords="""
|
||||
/*get keywords*/
|
||||
select nct_id ,downcase_name
|
||||
from ctgov.keywords k
|
||||
where k.nct_id = %s
|
||||
;
|
||||
"""
|
||||
|
||||
sql_indications='''
|
||||
select downcase_mesh_term
|
||||
from ctgov.browse_interventions bi
|
||||
where bi.nct_id = %s and mesh_type = 'mesh-list'
|
||||
'''
|
||||
|
||||
|
||||
with db_conn.cursor() as curse:
|
||||
curse.execute(sql_summary,[nct_id])
|
||||
summary = curse.fetchall()
|
||||
|
||||
curse.execute(sql_keywords,[nct_id])
|
||||
keywords = [ x[1] for x in curse.fetchall()]
|
||||
|
||||
curse.execute(sql_conditions,[nct_id])
|
||||
conditions = [ x[2] for x in curse.fetchall()]
|
||||
|
||||
curse.execute(sql_indications,[nct_id])
|
||||
indications = [ x[0] for x in curse.fetchall()]
|
||||
|
||||
return {
|
||||
"summary":summary,
|
||||
"keywords":keywords,
|
||||
"conditions":conditions,
|
||||
"indications":indications
|
||||
}
|
||||
|
||||
|
||||
def get_trials_unmatched_to_formularies(db_conn):
|
||||
"""
|
||||
Get the NCT_IDs of trials not yet matchec to formularies
|
||||
|
||||
For each formulary
|
||||
get list
|
||||
add to dsp
|
||||
"""
|
||||
|
||||
#setup sql for each formulary
|
||||
uspdc_sql = '''\
|
||||
/*
|
||||
Get the trials that have not been proceesed.
|
||||
First: get most recent matched status
|
||||
Second: only include those who have non-null status
|
||||
Third: check list of trials against this and remove any of them.
|
||||
This leaves unmatched trials.
|
||||
*/
|
||||
select distinct(nct_id)
|
||||
from "DiseaseBurden".trial_to_icd10 tti
|
||||
where nct_id not in (
|
||||
select nct_id from "Formularies".uspdc_most_recent_matched_status umrms
|
||||
where status is not null
|
||||
)
|
||||
and nct_id in (select distinct nct_id from public.formatted_data_mat fd )
|
||||
;
|
||||
'''
|
||||
uspmmg_sql = '''\
|
||||
/*
|
||||
Get the trials that have not been proceesed.
|
||||
First: get most recent matched status
|
||||
Second: only include those who have non-null status
|
||||
Third: check list of trials against this and remove any of them.
|
||||
This leaves unmatched trials.
|
||||
*/
|
||||
select distinct(nct_id)
|
||||
from "DiseaseBurden".trial_to_icd10 tti
|
||||
where nct_id not in (
|
||||
select nct_id from "Formularies".uspmmg_most_recent_matched_status umrms
|
||||
where status is not null
|
||||
)
|
||||
and nct_id in (select distinct nct_id from public.formatted_data_mat fd )
|
||||
;
|
||||
'''
|
||||
vaform_sql = ''' Null; '''
|
||||
|
||||
#query each formulary, adding data to dict
|
||||
formulary_list = dict()
|
||||
|
||||
with db_conn.cursor() as curse:
|
||||
|
||||
# uspdc
|
||||
curse.execute(uspdc_sql)
|
||||
formulary_list["uspdc"] = curse.fetchall()
|
||||
|
||||
# uspmm
|
||||
curse.execute(uspmmg_sql)
|
||||
formulary_list["uspmmg"] = curse.fetchall()
|
||||
# vaform
|
||||
|
||||
return formulary_list
|
||||
@ -0,0 +1,25 @@
|
||||
import psycopg as psyco
|
||||
from datetime import datetime
|
||||
|
||||
from flask import current_app, g
|
||||
|
||||
|
||||
|
||||
|
||||
def get_all_formulary_groups(db_conn):
|
||||
'''
|
||||
Get the list of active formulary groups
|
||||
TODO: IMplement for the given formulary
|
||||
'''
|
||||
pass
|
||||
|
||||
def get_formulary_groups_per_NCTID(db_conn, nct_id):
|
||||
'''
|
||||
Get the list of formulary groups associated with
|
||||
the drugs found in a trial identified by NCTID
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
def store_trial_to_formulary_group_matches():
|
||||
pass
|
||||
@ -0,0 +1,175 @@
|
||||
import psycopg2 as psyco
|
||||
from psycopg2 import extras
|
||||
from datetime import datetime
|
||||
|
||||
import click #used for cli commands. Not needed for what I am doing.
|
||||
from flask import current_app, g
|
||||
|
||||
def get_db(**kwargs):
|
||||
|
||||
if "db" not in g:
|
||||
g.db = psyco.connect(
|
||||
dbname=current_app.config["POSTGRES_DB"]
|
||||
,user=current_app.config["POSTGRES_USER"]
|
||||
,host=current_app.config["POSTGRES_HOST"]
|
||||
,port=current_app.config["POSTGRES_PORT"]
|
||||
,password=current_app.config["POSTGRES_PASSWORD"]
|
||||
,**kwargs
|
||||
)
|
||||
return g.db
|
||||
|
||||
def close_db(e=None):
|
||||
db = g.pop('db', None)
|
||||
|
||||
if db is not None:
|
||||
db.close()
|
||||
|
||||
def check_initialization(app):
|
||||
db = get_db()
|
||||
with db.cursor() as curse:
|
||||
curse.execute("select count(*) from \"DiseaseBurden\".trial_to_icd10")
|
||||
curse.fetchall()
|
||||
#just checking if everything is going to fail
|
||||
|
||||
def init_database(app):
|
||||
#check_initialization(app)
|
||||
app.teardown_appcontext(close_db)
|
||||
|
||||
|
||||
|
||||
|
||||
def select_remaing_trials_to_analyze(db_conn):
|
||||
'''
|
||||
This will get the set of trials that need to be analyzed.
|
||||
'''
|
||||
sql = '''
|
||||
select distinct nct_id
|
||||
from "DiseaseBurden".trial_to_icd10 tti
|
||||
where tti.approved is null
|
||||
order by nct_id
|
||||
;
|
||||
'''
|
||||
with db_conn.cursor() as cursor:
|
||||
cursor.execute(sql)
|
||||
return cursor.fetchall()
|
||||
|
||||
|
||||
def select_analyzed_trials(db_conn):
|
||||
'''
|
||||
This will get the set of trials that have been analyzed.
|
||||
'''
|
||||
sql = '''
|
||||
select distinct nct_id, max(approval_timestamp)
|
||||
from "DiseaseBurden".trial_to_icd10 tti
|
||||
where tti.approved in ('accepted','rejected')
|
||||
group by nct_id
|
||||
order by max(approval_timestamp) desc
|
||||
;
|
||||
'''
|
||||
with db_conn.cursor() as cursor:
|
||||
cursor.execute(sql)
|
||||
return cursor.fetchall()
|
||||
|
||||
def select_unmatched_trials(db_conn):
|
||||
'''
|
||||
This will get the set of trials that have been analyzed.
|
||||
'''
|
||||
sql = '''
|
||||
select distinct nct_id
|
||||
from "DiseaseBurden".trial_to_icd10 tti
|
||||
where tti.approved = 'unmatched'
|
||||
order by nct_id
|
||||
;
|
||||
'''
|
||||
with db_conn.cursor() as cursor:
|
||||
cursor.execute(sql)
|
||||
return cursor.fetchall()
|
||||
|
||||
|
||||
def get_trial_conditions_and_proposed_matches(db_conn, nct_id):
|
||||
sql = '''
|
||||
select *
|
||||
from "DiseaseBurden".trial_to_icd10 tti
|
||||
where nct_id = %s
|
||||
'''
|
||||
with db_conn.cursor() as cursor:
|
||||
cursor.execute(sql,[nct_id])
|
||||
return cursor.fetchall()
|
||||
|
||||
|
||||
def store_validation(db_conn, list_of_insert_data):
|
||||
sql = """
|
||||
update "DiseaseBurden".trial_to_icd10
|
||||
set approved=%s, approval_timestamp=%s
|
||||
where id=%s
|
||||
;
|
||||
"""
|
||||
with db_conn.cursor() as cursor:
|
||||
for l in list_of_insert_data:
|
||||
cursor.execute(sql, l)
|
||||
db_conn.commit()
|
||||
|
||||
def get_trial_summary(db_conn,nct_id):
|
||||
sql_summary ="""
|
||||
select
|
||||
s.nct_id,
|
||||
brief_title ,
|
||||
official_title ,
|
||||
bs.description as brief_description,
|
||||
dd.description as detailed_description
|
||||
from ctgov.studies s
|
||||
left join ctgov.brief_summaries bs
|
||||
on bs.nct_id = s.nct_id
|
||||
left join ctgov.detailed_descriptions dd
|
||||
on dd.nct_id = s.nct_id
|
||||
where s.nct_id = %s
|
||||
;
|
||||
"""
|
||||
sql_conditions="""
|
||||
--conditions mentioned
|
||||
select * from ctgov.conditions c
|
||||
where c.nct_id = %s
|
||||
;
|
||||
"""
|
||||
sql_keywords="""
|
||||
select nct_id ,downcase_name
|
||||
from ctgov.keywords k
|
||||
where k.nct_id = %s
|
||||
;
|
||||
"""
|
||||
with db_conn.cursor() as curse:
|
||||
curse.execute(sql_summary,[nct_id])
|
||||
summary = curse.fetchall()
|
||||
|
||||
curse.execute(sql_keywords,[nct_id])
|
||||
keywords = curse.fetchall()
|
||||
|
||||
curse.execute(sql_conditions,[nct_id])
|
||||
conditions = curse.fetchall()
|
||||
|
||||
return {"summary":summary, "keywords":keywords, "conditions":conditions}
|
||||
|
||||
def get_list_icd10_codes(db_conn):
|
||||
sql = """
|
||||
select distinct code
|
||||
from "DiseaseBurden".icd10_to_cause itc
|
||||
order by code;
|
||||
"""
|
||||
with db_conn.cursor() as curse:
|
||||
curse.execute(sql)
|
||||
codes = curse.fetchall()
|
||||
|
||||
return [ x[0] for x in codes ]
|
||||
|
||||
def record_suggested_matches(db_conn, nct_id,condition,icd10_code):
|
||||
sql1 = """
|
||||
INSERT INTO "DiseaseBurden".trial_to_icd10
|
||||
(nct_id,"condition",ui,"source",approved,approval_timestamp)
|
||||
VALUES (%s,%s,%s,'hand matched','accepted',%s)
|
||||
;
|
||||
"""
|
||||
|
||||
|
||||
with db_conn.cursor() as curse:
|
||||
curse.execute(sql1,[nct_id,condition,icd10_code,datetime.now()])
|
||||
db_conn.commit()
|
||||
@ -0,0 +1,105 @@
|
||||
import functools
|
||||
from flask import (Blueprint, flash, g, redirect, render_template, request, session, url_for)
|
||||
from datetime import datetime
|
||||
|
||||
from FormulariesMatching.db_interface import (
|
||||
get_db,
|
||||
get_connection_details,
|
||||
get_trial_summary,
|
||||
get_trials_unmatched_to_formularies,
|
||||
)
|
||||
import FormulariesMatching.uspdc_db as uspdc
|
||||
import FormulariesMatching.uspmmg_db as uspmmg
|
||||
import FormulariesMatching.vaform_db as vaform
|
||||
|
||||
import re
|
||||
|
||||
FORMULARIES = {
|
||||
"USP DC":uspdc,
|
||||
"USP MMG":uspmmg,
|
||||
# "VA Formulary":vaform,
|
||||
}
|
||||
|
||||
|
||||
#setup blueprint
|
||||
bp = Blueprint("formularies", __name__, url_prefix='/link/formularies')
|
||||
|
||||
@bp.route("/", methods=['GET'])
|
||||
def get_remaining_trials():
|
||||
#get db connection
|
||||
db_conn = get_db()
|
||||
|
||||
#get list of trials
|
||||
unmatched_trials = get_trials_unmatched_to_formularies(db_conn)
|
||||
unmatched_trials_list = list(set([ x[0] for y in unmatched_trials for x in unmatched_trials[y]] ))
|
||||
|
||||
#return html
|
||||
# return {"formularies":unmatched_trials,"nctids":nctid_list}
|
||||
return render_template('formulary_index.html',
|
||||
unmatched_trials=unmatched_trials_list,
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/<nct_id>", methods=['GET',"POST"])
|
||||
def match_trial_to_formulary_groups(nct_id):
|
||||
#get db connection
|
||||
db_conn = get_db()
|
||||
|
||||
if request.method == "GET":
|
||||
|
||||
#get list of potential matches for each of the formularies
|
||||
potential_matches = {}
|
||||
class_lists = {}
|
||||
|
||||
for formulary in FORMULARIES:
|
||||
potential_matches[formulary] = FORMULARIES[formulary].get_groups_per_nctid(db_conn,nct_id)
|
||||
class_lists[formulary] = FORMULARIES[formulary].get_all_formulary_groups(db_conn)
|
||||
|
||||
#get trial summary
|
||||
summary = get_trial_summary(db_conn,nct_id)
|
||||
|
||||
#render template
|
||||
# return [potential_matches,class_lists,summary]
|
||||
return render_template('trial_formularies.html',
|
||||
nct_id=nct_id,
|
||||
potential_matches=potential_matches,
|
||||
class_lists=class_lists,
|
||||
summary=summary,
|
||||
)
|
||||
|
||||
elif request.method == "POST":
|
||||
|
||||
#For each Formulary
|
||||
translation={"('":None,"')":None}
|
||||
|
||||
for key in request.form.keys():
|
||||
match key.split("|"):
|
||||
case ["select_box", formulary]:
|
||||
#parse data
|
||||
result = request.form["select_box|{}".format(formulary)]
|
||||
if result == 'difficult':
|
||||
FORMULARIES[formulary].insert_match(db_conn,nct_id,None,None,'difficult')
|
||||
else:
|
||||
category,uspclass = [re.sub("['\(\)]","",x).strip() for x in result.split("', '")]
|
||||
|
||||
FORMULARIES[formulary].insert_match(db_conn,nct_id,category,uspclass,'accepted')
|
||||
|
||||
|
||||
case ["check_box", data]:
|
||||
formulary_trial,category,uspclass = [re.sub("['\(\)]","",x).strip() for x in data.split("', '")]
|
||||
formulary,_ = formulary_trial.split(",")
|
||||
#Insert data
|
||||
|
||||
FORMULARIES[formulary].insert_match(db_conn,nct_id,category,uspclass,'accepted')
|
||||
|
||||
case _:
|
||||
return 400
|
||||
|
||||
return redirect(url_for("formularies.get_remaining_trials"))
|
||||
|
||||
|
||||
|
||||
else:
|
||||
raise Exception("HTTP method <{}> not implemented".format(request.method))
|
||||
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
.table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid;
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}">
|
||||
|
||||
<title>{% block title %}{% endblock %} - ClinicalTrialsProject</title>
|
||||
|
||||
<nav>
|
||||
<h1>Nav</h1>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ url_for('hello') }}">Linking Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ url_for('formularies.get_remaining_trials') }}">Linking Formularies</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
{% block header %}{% endblock %}
|
||||
{% block content %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,47 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block header %}
|
||||
<h1>{% block title %} Linking Trials to Formularies{% endblock %}</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h2>Unlinked Trials</h2>
|
||||
|
||||
<ul>
|
||||
{% for trial in unmatched_trials %}
|
||||
<li> <a href="{{ url_for('formularies.match_trial_to_formulary_groups', nct_id=trial ) }}">
|
||||
{{ trial }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h2>Linked Trials</h2>
|
||||
|
||||
<table>
|
||||
<th>Trials Links</th>
|
||||
{% for trial in validated_list %}
|
||||
<tr><td>
|
||||
<a href="{{ url_for('.validate_trial', nct_id=trial[0] ) }}">
|
||||
{{ trial [0] }}
|
||||
</a>
|
||||
(Most recently updated {{trial[1]}})
|
||||
</td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
<h2>Flagged for later Trials</h2>
|
||||
|
||||
<table>
|
||||
<th>Trial Links</th>
|
||||
{% for trial in unmatched_list %}
|
||||
<tr><td>
|
||||
<a href="{{ url_for('.validate_trial', nct_id=trial[0] ) }}">
|
||||
{{ trial [0] }}
|
||||
</a>
|
||||
</td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
||||
@ -0,0 +1,49 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block header %}
|
||||
<h1>{% block title %} ICD-10 to Trial Conditions Validation {% endblock %}</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h2>Trials to Validate</h2>
|
||||
|
||||
<table>
|
||||
<th>Trials</th>
|
||||
{% for trial in list_to_validate %}
|
||||
<tr><td>
|
||||
<a href="{{ url_for('.validate_trial', nct_id=trial[0] ) }}">
|
||||
{{ trial [0] }}
|
||||
</a>
|
||||
</td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
<h2>Trials that have been Validated</h2>
|
||||
|
||||
<table>
|
||||
<th>Trials Links</th>
|
||||
{% for trial in validated_list %}
|
||||
<tr><td>
|
||||
<a href="{{ url_for('.validate_trial', nct_id=trial[0] ) }}">
|
||||
{{ trial [0] }}
|
||||
</a>
|
||||
(Most recently updated {{trial[1]}})
|
||||
</td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
<h2>Trials that don't have a good match</h2>
|
||||
|
||||
<table>
|
||||
<th>Trial Links</th>
|
||||
{% for trial in unmatched_list %}
|
||||
<tr><td>
|
||||
<a href="{{ url_for('.validate_trial', nct_id=trial[0] ) }}">
|
||||
{{ trial [0] }}
|
||||
</a>
|
||||
</td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
||||
@ -0,0 +1,24 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block header %}
|
||||
<h1>
|
||||
{% block title %}
|
||||
Formulary Matching
|
||||
{% endblock %}
|
||||
</h1>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
||||
This is the home page for matching things to clinical trials
|
||||
|
||||
There are a few major efforts related to matching.
|
||||
|
||||
The first is to match trials to IDC10 codes
|
||||
|
||||
The second is to link trials to formulary groups.
|
||||
|
||||
{% endblock %}
|
||||
@ -0,0 +1,132 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block header %}
|
||||
<h1>
|
||||
{% block title %}
|
||||
Match Trial {{nct_id}} to Formularies
|
||||
{% endblock %}
|
||||
</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class=trial_summary>
|
||||
<h3> Trial Summary </h3>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Short Title</th>
|
||||
<td>{{ summary['summary'][0][1] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Complete Title</th>
|
||||
<td>{{ summary['summary'][0][2] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Summary</th>
|
||||
<td>{{ summary['summary'][0][3] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Summary 2</th>
|
||||
<td>{{ summary['summary'][0][4] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Indicated Drugs</th>
|
||||
<td>
|
||||
<ul>
|
||||
{% for drug in summary['indications'] %}
|
||||
<li>
|
||||
<a
|
||||
href="https://www.drugs.com/search.php?searchterm={{drug}}"
|
||||
target="_blank"
|
||||
>
|
||||
{{drug}}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Conditions</th>
|
||||
<td>
|
||||
<ul>
|
||||
{% for condition in summary['conditions'] %}
|
||||
<li>
|
||||
<a
|
||||
href="https://www.mayoclinic.org/search/search-results?q={{condition}}"
|
||||
target="_blank"
|
||||
>
|
||||
{{condition}}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>keywords</th>
|
||||
<td>{{ summary['keywords'] }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<form method="post">
|
||||
<h2>Matching Classes</h2>
|
||||
{% for formulary in potential_matches %}
|
||||
<div class=formulary_matches>
|
||||
<h3>
|
||||
{{ formulary }}
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Category</th>
|
||||
<th>Class</th>
|
||||
<th>Select</th>
|
||||
</tr>
|
||||
{% for row in potential_matches[formulary] %}
|
||||
<tr>
|
||||
<td> {{ row[1] }} </td>
|
||||
<td> {{ row[2] }} </td>
|
||||
<td> <input
|
||||
type="checkbox"
|
||||
id="{{ formulary,row }}"
|
||||
name="check_box|{{ formulary,row }}"
|
||||
value="selected">
|
||||
</td>
|
||||
<!-- add checkbox here -->
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
</p>
|
||||
<p>
|
||||
If you've determined it belongs to another class
|
||||
<select name="select_box|{{ formulary }}" id="{{ formularay }}-select_box">
|
||||
<option disabled selected value> -- select an option -- </option>
|
||||
<option value="difficult">
|
||||
Difficult to choose
|
||||
</option>
|
||||
|
||||
{% for option in class_lists[formulary] %}
|
||||
<option value="{{ (option[0],option[1]) }}">
|
||||
Cat:{{ option[0] }} Class:{{ option[1] }}
|
||||
<!-- FIX this is really hard to read -->
|
||||
<!-- FIX try to add opgroups? -->
|
||||
</option>
|
||||
{% endfor %}
|
||||
|
||||
</select>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
</p>
|
||||
<p>
|
||||
<input type="submit" value="Submit">
|
||||
</p>
|
||||
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@ -0,0 +1,61 @@
|
||||
import psycopg as psyco
|
||||
from datetime import datetime
|
||||
|
||||
from flask import current_app, g
|
||||
|
||||
|
||||
|
||||
|
||||
def get_all_formulary_groups(db_conn):
|
||||
'''
|
||||
Get the list of active formulary groups
|
||||
TODO: IMplement for the given formulary
|
||||
'''
|
||||
sql = '''\
|
||||
select distinct "USP Category", "USP Class"
|
||||
from "Formularies".usp_dc ud
|
||||
order by "USP Category", "USP Class"
|
||||
;
|
||||
'''
|
||||
#query
|
||||
with db_conn.cursor() as curse:
|
||||
curse.execute(sql)
|
||||
return curse.fetchall()
|
||||
|
||||
|
||||
|
||||
|
||||
def get_groups_per_nctid(db_conn, nct_id):
|
||||
'''
|
||||
Get the list of formulary groups associated with
|
||||
the drugs found in a trial identified by NCTID
|
||||
'''
|
||||
pass
|
||||
sql = '''\
|
||||
select * from "Formularies".uspdc_trial_to_category_class ttucc
|
||||
where nct_id = %(nctid)s
|
||||
;
|
||||
'''
|
||||
|
||||
#query
|
||||
with db_conn.cursor() as curse:
|
||||
curse.execute(sql, {"nctid":nct_id})
|
||||
return curse.fetchall()
|
||||
|
||||
|
||||
def insert_match(db_conn, nct_id, category,uspclass,status):
|
||||
sql = '''\
|
||||
INSERT INTO "Formularies".uspdc_matching
|
||||
VALUES
|
||||
(
|
||||
%(nct_id)s
|
||||
,%(category)s
|
||||
,%(uspclass)s
|
||||
,%(status)s
|
||||
,NOW()
|
||||
)
|
||||
;
|
||||
'''
|
||||
with db_conn.cursor() as curse:
|
||||
curse.execute(sql, {"nct_id":nct_id, "category":category, "uspclass":uspclass, "status":status} )
|
||||
db_conn.commit()
|
||||
@ -0,0 +1,62 @@
|
||||
import psycopg as psyco
|
||||
from datetime import datetime
|
||||
|
||||
from flask import current_app, g
|
||||
|
||||
|
||||
|
||||
|
||||
def get_all_formulary_groups(db_conn):
|
||||
'''
|
||||
Get the list of active formulary groups
|
||||
TODO: IMplement for the given formulary
|
||||
'''
|
||||
sql = '''\
|
||||
select distinct "USP Category", "USP Class"
|
||||
from "Formularies".usp_mmg ud
|
||||
order by "USP Category", "USP Class"
|
||||
;
|
||||
'''
|
||||
#query
|
||||
with db_conn.cursor() as curse:
|
||||
curse.execute(sql)
|
||||
return curse.fetchall()
|
||||
|
||||
|
||||
|
||||
|
||||
def get_groups_per_nctid(db_conn, nct_id):
|
||||
'''
|
||||
Get the list of formulary groups associated with
|
||||
the drugs found in a trial identified by NCTID
|
||||
'''
|
||||
pass
|
||||
sql = '''\
|
||||
select * from "Formularies".uspmmg_trial_to_category_class ttucc
|
||||
where nct_id = %(nctid)s
|
||||
;
|
||||
'''
|
||||
|
||||
#query
|
||||
with db_conn.cursor() as curse:
|
||||
curse.execute(sql, {"nctid":nct_id})
|
||||
return curse.fetchall()
|
||||
|
||||
|
||||
|
||||
def insert_match(db_conn, nct_id, category,uspclass,status):
|
||||
sql = '''\
|
||||
INSERT INTO "Formularies".uspmmg_matching
|
||||
VALUES
|
||||
(
|
||||
%(nct_id)s
|
||||
,%(category)s
|
||||
,%(uspclass)s
|
||||
,%(status)s
|
||||
,NOW()
|
||||
)
|
||||
;
|
||||
'''
|
||||
with db_conn.cursor() as curse:
|
||||
curse.execute(sql, {"nct_id":nct_id, "category":category, "uspclass":uspclass, "status":status} )
|
||||
db_conn.commit()
|
||||
@ -0,0 +1,35 @@
|
||||
import psycopg as psyco
|
||||
from datetime import datetime
|
||||
|
||||
from flask import current_app, g
|
||||
|
||||
|
||||
|
||||
|
||||
def get_all_formulary_groups(db_conn):
|
||||
'''
|
||||
Get the list of active formulary groups
|
||||
TODO: IMplement for the given formulary
|
||||
'''
|
||||
sql = '''\
|
||||
select distinct "USP Category", "USP Class"
|
||||
from "Formularies".usp_dc ud
|
||||
order by "USP Category", "USP Class"
|
||||
;
|
||||
'''
|
||||
|
||||
#query
|
||||
with db_conn.cursor() as curse:
|
||||
curse.execute(sql)
|
||||
return curse.fetchall()
|
||||
|
||||
def get_formulary_groups_per_NCTID(db_conn, nct_id):
|
||||
'''
|
||||
Get the list of formulary groups associated with
|
||||
the drugs found in a trial identified by NCTID
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
def store_trial_to_formulary_group_matches():
|
||||
pass
|
||||
@ -0,0 +1,6 @@
|
||||
flask
|
||||
psycopg[binary]
|
||||
datetime
|
||||
watchdog
|
||||
waitress
|
||||
python-dotenv
|
||||
@ -0,0 +1,12 @@
|
||||
from setuptools import setup
|
||||
|
||||
setup(
|
||||
name='FormulariesMatching',
|
||||
packages=['FormulariesMatching'],
|
||||
include_package_data=True,
|
||||
install_requires=[
|
||||
'flask',
|
||||
'psycopg[binary]',
|
||||
'datetime',
|
||||
],
|
||||
)
|
||||
@ -0,0 +1,2 @@
|
||||
waitress-serve --port=5000 --call 'FormulariesMatching:create_app'
|
||||
#flask --app FormulariesMatching run --debug
|
||||
Loading…
Reference in New Issue