can request and display some data in json format
parent
57529ee595
commit
3e65b9fbdd
@ -0,0 +1,50 @@
|
|||||||
|
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 db_interface
|
||||||
|
#db_interface.check_connection(app)
|
||||||
|
|
||||||
|
from . import formularies_matching
|
||||||
|
app.register_blueprint(formularies_matching.bp)
|
||||||
|
|
||||||
|
|
||||||
|
return app
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
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 ="""
|
||||||
|
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}
|
||||||
|
|
||||||
@ -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,47 @@
|
|||||||
|
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,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#setup blueprint
|
||||||
|
bp = Blueprint("formularies validation", __name__, url_prefix='/link/formularies')
|
||||||
|
|
||||||
|
@bp.route("/", methods=['GET'])
|
||||||
|
def get_remaining():
|
||||||
|
#get db connection
|
||||||
|
#db_conn = get_db()
|
||||||
|
|
||||||
|
#get required data
|
||||||
|
connection_valid = get_connection_details()
|
||||||
|
|
||||||
|
#return html
|
||||||
|
return connection_valid
|
||||||
|
|
||||||
|
|
||||||
|
@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":
|
||||||
|
pass
|
||||||
|
#get list of potential matches for each of the formularies
|
||||||
|
#get trial summary
|
||||||
|
summary = get_trial_summary(db_conn,nct_id)
|
||||||
|
|
||||||
|
#render template
|
||||||
|
return summary
|
||||||
|
|
||||||
|
elif request.method == "POST":
|
||||||
|
pass
|
||||||
|
#build array of data to insert
|
||||||
|
|
||||||
|
else:
|
||||||
|
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()
|
||||||
Binary file not shown.
@ -0,0 +1,22 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<title>{% block title %}{% endblock %} - ClinicalTrialsProject</title>
|
||||||
|
<!--<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">-->
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
<h1>Nav</h1>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="{{ url_for('hello') }}">Linking Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ url_for('formularies validation.get_remaining') }}">Linking Formularies</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<section class="content">
|
||||||
|
<header>
|
||||||
|
{% block header %}{% endblock %}
|
||||||
|
</header>
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</section>
|
||||||
@ -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,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,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 @@
|
|||||||
|
waitress-serve --port=5000 --call 'Icd10ConditionsMatching:create_app'
|
||||||
Loading…
Reference in New Issue