Skip to content

Commit 5d912eb

Browse files
author
mounika
committed
update to the app
1 parent a7fa99b commit 5d912eb

File tree

6 files changed

+233
-1444
lines changed

6 files changed

+233
-1444
lines changed

.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ FHIR_SERVER_BASE_URL=http://pwebmedcit.services.brown.edu:9091/fhir
22
FHIR_USERNAME=bcbifhir
33
FHIR_PASSWORD=fancy-company-attraction-p3rson
44
FHIR_PORT=5000
5+
R_HOME=/Library/Frameworks/R.framework/Resources # Adjust this path based on your findings
6+
R_USER=/Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/library # Adjust this path based on your R version and user library path

README.md

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,62 @@
1-
# Under development
1+
# ASCVD Risk Calculator
22

3-
# This is a repo which has code to ASCVD risk calculator web app
3+
This ASCVD Risk calculator is used to study the risk prediction for cardiovascular disease (CVD).
44

5+
This calculator uses the Pooled Cohort risk prediction equations to predict 10-year atherosclerotic cardiovascular disease risk. More information about the predictor equation can be found here https://github.com/bcjaeger/PooledCohort/tree/master
6+
7+
# Steps to run the ASCVD Risk Calculator
8+
9+
## 1. Check if R and python are installed where you are running this app.
10+
11+
```
12+
python3 --version
13+
R --version
14+
```
15+
16+
## 2. Before running the app
17+
18+
Change these parameters in the .env file. Use the port number assigned to you to run the app for FHIR_PORT.
19+
20+
```
21+
FHIR_SERVER_BASE_URL= http://pwebmedcit.services.brown.edu:????/fhir
22+
FHIR_USERNAME = ???
23+
FHIR_PASSWORD = ???
24+
FHIR_PORT=????
25+
R_HOME=???
26+
R_USER=????
27+
```
28+
29+
Start R and run the R.home() and .libPaths() commands to get the directory names and update them in .env file
30+
31+
```
32+
> R.home()
33+
[1] "/Library/Frameworks/R.framework/Resources"
34+
> .libPaths()
35+
[1] "/Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/library"
36+
```
37+
38+
## 3. Clone the repo
39+
```
40+
git clone https://github.com/bcbi/ASCVD-Risk-Calculator.git
41+
42+
cd ASCVD-Risk-Calculator
43+
```
44+
## 4. Run the setup script
45+
```
46+
./setup_environment.sh
47+
```
48+
49+
## 5. Activate the virtual environment
50+
```
51+
source venv/bin/activate
52+
```
53+
54+
## 6. Run the flask app
55+
```
56+
python src/app.py
57+
```
58+
59+
This will start the app on port "FHIR_PORT". You can open your preferred browser and see the app running on `http://localhost:FHIR_PORT` replace the FHIR_PORT with the actual port number assigned to you.
60+
The exact URL to the app can also be found on the terminal output after running the app.
561

662

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ requests==2.31.0
1313
urllib3==2.0.5
1414
Werkzeug==2.3.7
1515
zipp==3.17.0
16+
rpy2==3.4.5

setup_environment.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/bash
2+
3+
python3 -m venv venv
4+
source venv/bin/activate
5+
6+
# install python packages
7+
pip install -r requirements.txt
8+
9+
# install R pacakges
10+
Rscript -e "install.packages('devtools', repos='http://cran.rstudio.com/')"
11+
Rscript -e "devtools::install_github('bcjaeger/PooledCohort')"

src/app.py

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,31 @@
1-
import requests
21
import os
2+
3+
4+
5+
import requests
6+
import rpy2.robjects as ro
7+
from rpy2.robjects.packages import importr
8+
from rpy2.robjects.vectors import FloatVector, StrVector
39
from flask import Flask, request, render_template, redirect, url_for
410
from dotenv import load_dotenv
511
from datetime import datetime
612

713
app = Flask(__name__)
814

9-
FHIR_SERVER_BASE_URL = "http://pwebmedcit.services.brown.edu:9091/fhir"
15+
# Import the PooledCohort package in R
16+
pooled_cohort = importr("PooledCohort")
1017

18+
# Load environment variables
1119
load_dotenv()
1220

21+
FHIR_SERVER_BASE_URL = os.getenv("FHIR_SERVER_BASE_URL")
1322
username = os.getenv("FHIR_USERNAME")
1423
password = os.getenv("FHIR_PASSWORD")
1524

25+
# Set environment variables for R from .env
26+
os.environ['R_HOME'] = os.getenv('R_HOME')
27+
os.environ['R_USER'] = os.getenv('R_USER')
28+
1629
observation_codes = {
1730
"Systolic Blood Pressure": "8480-6",
1831
"Diastolic Blood Pressure": "8462-4",
@@ -21,6 +34,14 @@
2134
"LDL Cholesterol": "18262-6"
2235
}
2336

37+
race_mapping = {
38+
"American Indian or Alaska Native": "white",
39+
"Asian": "white",
40+
"Black or African American": "black",
41+
"Native Hawaiian or Other Pacific Islander": "white",
42+
"White": "white"
43+
}
44+
2445
def get_observation_value(entry):
2546
if 'valueQuantity' in entry['resource']:
2647
return entry['resource']['valueQuantity']['value']
@@ -48,15 +69,12 @@ def get_patient_demographics(patient_id, credentials):
4869
age = calculate_age(birth_date)
4970
sex = patient['gender']
5071
race = 'Not Found'
51-
52-
# Extract race from extensions
5372
for extension in patient.get('extension', []):
5473
if extension['url'] == 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race':
5574
for ext in extension.get('extension', []):
5675
if ext['url'] == 'ombCategory':
57-
race = ext['valueCoding']['display']
76+
race = race_mapping.get(ext['valueCoding']['display'], 'white')
5877
break
59-
6078
return {'age': age, 'sex': sex, 'race': race}
6179
else:
6280
return {'age': 'Not Found', 'sex': 'Not Found', 'race': 'Not Found'}
@@ -76,26 +94,6 @@ def get_patient_observations(patient_id, credentials):
7694
observations[obs_name] = 'Not Found'
7795
return observations, demographics
7896

79-
def calculate_ascvd_risk(age, sex, race, total_cholesterol, hdl_cholesterol, systolic_bp, on_hypertension_treatment, diabetes, smoker):
80-
# Simplified ASCVD risk calculation
81-
# Note: This is a placeholder. Use a proper ASCVD risk calculator for accurate results.
82-
risk_score = 0
83-
if sex == 'male':
84-
risk_score += 1
85-
if race == 'African American':
86-
risk_score += 1
87-
risk_score += age / 10
88-
risk_score += total_cholesterol / 50
89-
risk_score -= hdl_cholesterol / 50
90-
risk_score += systolic_bp / 20
91-
if on_hypertension_treatment == 'yes':
92-
risk_score += 1
93-
if diabetes == 'yes':
94-
risk_score += 1
95-
if smoker == 'yes':
96-
risk_score += 1
97-
return round(risk_score, 2)
98-
9997
@app.route('/', methods=['GET', 'POST'])
10098
def index():
10199
observations = None
@@ -124,21 +122,46 @@ def calculate_risk():
124122
smoker = request.form['smoker']
125123
hypertension = request.form['hypertension']
126124

127-
ascvd_risk = calculate_ascvd_risk(age, sex, race, total_cholesterol, hdl_cholesterol, systolic_bp, hypertension, diabetes, smoker)
125+
# Convert sex and race to R compatible formats
126+
sex_r = StrVector([sex])
127+
race_r = StrVector([race_mapping.get(race, 'white')])
128+
129+
# Convert other inputs to R compatible formats
130+
age_r = FloatVector([age])
131+
total_cholesterol_r = FloatVector([total_cholesterol])
132+
hdl_cholesterol_r = FloatVector([hdl_cholesterol])
133+
systolic_bp_r = FloatVector([systolic_bp])
134+
diabetes_r = StrVector(['yes' if diabetes == 'yes' else 'no'])
135+
smoker_r = StrVector(['yes' if smoker == 'yes' else 'no'])
136+
hypertension_r = StrVector(['yes' if hypertension == 'yes' else 'no'])
137+
138+
# Call the ASCVD risk calculation function from PooledCohort
139+
ascvd_risk_r = pooled_cohort.predict_10yr_ascvd_risk(
140+
sex=sex_r,
141+
race=race_r,
142+
age_years=age_r,
143+
chol_total_mgdl=total_cholesterol_r,
144+
chol_hdl_mgdl=hdl_cholesterol_r,
145+
bp_sys_mmhg=systolic_bp_r,
146+
bp_meds=hypertension_r,
147+
smoke_current=smoker_r,
148+
diabetes=diabetes_r
149+
)
150+
151+
# Convert the result back to Python
152+
ascvd_risk = list(ascvd_risk_r)[0]*100
128153

129-
# Maintain the form values for observations and demographics
130154
demographics = {'age': age, 'sex': sex, 'race': race}
131155
observations = {
132156
'Total Cholesterol': total_cholesterol,
133157
'HDL Cholesterol': hdl_cholesterol,
134158
'Systolic Blood Pressure': systolic_bp,
135-
'Diastolic Blood Pressure': request.form['diastolic_blood_pressure'] if 'diastolic_blood_pressure' in request.form else 'Not Found',
136-
'LDL Cholesterol': request.form['ldl_cholesterol'] if 'ldl_cholesterol' in request.form else 'Not Found'
159+
'Diastolic Blood Pressure': request.form['diastolic_blood_pressure'] if 'diastolic_blood_pressure' in request.form else 'Not Found'
137160
}
138161

139162
return render_template('index.html', ascvd_risk=ascvd_risk, demographics=demographics, observations=observations, patient_id=patient_id)
140163

141164
if __name__ == '__main__':
142-
port_str = os.environ['FHIR_PORT']
165+
port_str = os.getenv('FHIR_PORT', '5000')
143166
port_int = int(port_str)
144167
app.run(debug=True, port=port_int)

0 commit comments

Comments
 (0)