Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
3a3a9a3
Update streamlit_app.py
salmon-raye Jan 11, 2024
e2ff554
Update streamlit_app.py
salmon-raye Jan 11, 2024
010ec2b
Update streamlit_app.py
salmon-raye Jan 11, 2024
000ad40
Update requirements.txt
salmon-raye Jan 11, 2024
515d85d
Update streamlit_app.py
salmon-raye Jan 11, 2024
f25775e
Update requirements.txt
salmon-raye Jan 11, 2024
21e04bc
Update requirements.txt
salmon-raye Jan 11, 2024
09c1a87
Update requirements.txt
salmon-raye Jan 11, 2024
e98a211
Update streamlit_app.py
salmon-raye Jan 11, 2024
f3cc66d
Update streamlit_app.py
salmon-raye Jan 11, 2024
788906d
Update requirements.txt
salmon-raye Jan 11, 2024
0b90d11
Update streamlit_app.py
salmon-raye Jan 11, 2024
5e373c6
Update streamlit_app.py
salmon-raye Jan 11, 2024
f99c286
Update requirements.txt
salmon-raye Jan 11, 2024
ffcb837
Update streamlit_app.py
salmon-raye Jan 11, 2024
98312a8
Update streamlit_app.py
salmon-raye Jan 11, 2024
aeda74d
Update streamlit_app.py
salmon-raye Jan 11, 2024
e20ed68
Update requirements.txt
salmon-raye Jan 11, 2024
0a4f96f
Update streamlit_app.py
salmon-raye Jan 11, 2024
12055b2
Update streamlit_app.py
salmon-raye Jan 11, 2024
b5156b0
Update requirements.txt
salmon-raye Jan 11, 2024
583b7e3
Update streamlit_app.py
salmon-raye Jan 11, 2024
f072235
Update requirements.txt
salmon-raye Jan 12, 2024
55e16f4
Update streamlit_app.py
salmon-raye Jan 12, 2024
b7dcdc5
Update streamlit_app.py
salmon-raye Jan 12, 2024
0e1ee92
Update streamlit_app.py
salmon-raye Jan 12, 2024
2ef4e98
Update streamlit_app.py
salmon-raye Jan 12, 2024
940f006
Create packages.txt
salmon-raye Jan 12, 2024
48876ec
Update streamlit_app.py
salmon-raye Jan 12, 2024
7e59c8b
Update streamlit_app.py
salmon-raye Jan 12, 2024
fbfe353
Update streamlit_app.py
salmon-raye Jan 12, 2024
bdbf4ea
Update streamlit_app.py
salmon-raye Jan 12, 2024
f2c6a6d
Update streamlit_app.py
salmon-raye Jan 12, 2024
c9d5d7d
Update streamlit_app.py
salmon-raye Jan 12, 2024
c3b2411
Update streamlit_app.py
salmon-raye Jan 12, 2024
d486474
Update streamlit_app.py
salmon-raye Jan 12, 2024
9b2a6fb
Update streamlit_app.py
salmon-raye Jan 12, 2024
fe2f5f2
Update streamlit_app.py
salmon-raye Jan 12, 2024
9c4767d
Update streamlit_app.py
salmon-raye Jan 12, 2024
5ed1e0a
Create main.yml
salmon-raye Jan 20, 2024
8009d42
Update streamlit_app.py
salmon-raye Jan 20, 2024
871875a
Update main.yml
salmon-raye Jan 20, 2024
190a14d
Update streamlit_app.py
salmon-raye Jan 20, 2024
cab572f
Update main.yml
salmon-raye Jan 20, 2024
a402e69
Update main.yml
salmon-raye Jan 20, 2024
c06f316
Update main.yml
salmon-raye Jan 20, 2024
f5e0a1e
Update main.yml
salmon-raye Jan 20, 2024
9c5bc50
Update main.yml
salmon-raye Jan 20, 2024
2a129c5
add quotation marks
cobaltB12 Jan 20, 2024
3831df2
added RBC count
cobaltB12 Jan 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: secret-test
on: [push]
jobs:
Explore-GitHub-Actions:
runs-on: ubuntu-latest
steps:
- name: Hello world action
run: echo "JUST LOADING SECRET ONLY"
env:
API_KEY: ${{ secrets.API_KEY }}
1 change: 1 addition & 0 deletions packages.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
libgl1-mesa-glx
6 changes: 4 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
altair
pandas
opencv_python
paddleocr
paddlepaddle
streamlit
openai
223 changes: 189 additions & 34 deletions streamlit_app.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,195 @@
import altair as alt
import numpy as np
import pandas as pd
import streamlit as st
import pandas as pd
import numpy as np
import os
import time
import base64
import json
from openai import OpenAI
import cv2
from paddleocr import PaddleOCR

"""
# Welcome to Streamlit!
# REMOVE THIS BEFORE COPYING TO GITHUB!
API_KEY = os.environ['API_KEY']

Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
forums](https://discuss.streamlit.io).
test_attributes = {}

In the meantime, below is an example of what you can do with just a few lines of code:
client = OpenAI(api_key=API_KEY)

template_prompt = """
Extract the items from the health screening result listed below into a json format, using the example json template. Ignore other items not listed in the json template. Output data types are "test_found" (True/False), "test_value" (float), "test_unit" (string in lower case), "test_ref_min" (float), "test_ref_max" (float). If test item is not found, output False for "test_found", and output False for the other values. If test is found but reference max, reference min, or reference range is not found, output False for "test_ref_min" and "test_ref_max".

Example output json template
{
"ldl_cholesterol": {
"test_found":True,
"test_value":20,
"test_unit":"mmol/l",
"test_ref_min":False,
"test_ref_max":False
},
"hdl_cholesterol": {
"test_found":True,
"test_value":20,
"test_unit":"mmol/l",
"test_ref_min":False,
"test_ref_max":False
},
"total_cholesterol": {
"test_found":True,
"test_value":20,
"test_unit":"mmol/l",
"test_ref_min":False,
"test_ref_max":False
},
"mcv":{
"test_found":False,
"test_value":False,
"test_unit":False,
"test_ref_min":False,
"test_ref_max":False
},
"hb":{
"test_found":False,
"test_value":False,
"test_unit":False,
"test_ref_min":False,
"test_ref_max":False
},
"rbc_count":{
"test_found":False,
"test_value":False,
"test_unit":False,
"test_ref_min":False,
"test_ref_max":False
},
"uric_acid":{
"test_found":False,
"test_value":False,
"test_unit":False,
"test_ref_min":False,
"test_ref_max":False
},
"hba1c":{
"test_found":False,
"test_value":False,
"test_unit":False,
"test_ref_min":False,
"test_ref_max":False
},
"systolic_bp":{
"test_found":False,
"test_value":False,
"test_unit":False,
"test_ref_min":False,
"test_ref_max":False
},
"diastolic_bp":{
"test_found":False,
"test_value":False,
"test_unit":False,
"test_ref_min":False,
"test_ref_max":False
},
"height":{
"test_found":False,
"test_value":False,
"test_unit":False,
"test_ref_min":False,
"test_ref_max":False
},
"weight":{
"test_found":False,
"test_value":False,
"test_unit":False,
"test_ref_min":False,
"test_ref_max":False
}
}

Health screening result:
"""

num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
num_turns = st.slider("Number of turns in spiral", 1, 300, 31)

indices = np.linspace(0, 1, num_points)
theta = 2 * np.pi * num_turns * indices
radius = indices

x = radius * np.cos(theta)
y = radius * np.sin(theta)

df = pd.DataFrame({
"x": x,
"y": y,
"idx": indices,
"rand": np.random.randn(num_points),
})

st.altair_chart(alt.Chart(df, height=700, width=700)
.mark_point(filled=True)
.encode(
x=alt.X("x", axis=None),
y=alt.Y("y", axis=None),
color=alt.Color("idx", legend=None, scale=alt.Scale()),
size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
))
def load_image():
uploaded_file = st.file_uploader(label='Upload your test results image below:')
if uploaded_file is not None:
st.toast("Image uploaded") # Toast message
image_data = uploaded_file.getvalue()
st.image(image_data, caption='', use_column_width=True) # Adjust width for mobile screens
return image_data

st.title('Explain my test results please!')
st.header('Instructions')
st.markdown('Answer the questions, take a picture of your lab test results, upload it, and we will explain it to you!')

# User inputs
age = st.number_input("Enter your age", min_value=0, max_value=140, step=1,value="min")
sex = st.selectbox("Select your sex", ["Female","Male"])
race = st.selectbox("Select your race", ["Chinese", "Malay", "Indian", "Others"])
smoker = st.checkbox("Are you a smoker?")
stroke = st.checkbox("Have you ever had a stroke?")
diabetes = st.checkbox("Do you have a history of diabetes?")
heart_attack = st.checkbox("Have you ever had a heart attack?")
on_bp_meds = st.checkbox("Are you taking blood pressure medication?")
systolic_bp = st.number_input("Enter your last recorded systolic blood pressure (leave blank if not available)", min_value=50,max_value=300,value=None)

ocr_model = PaddleOCR(use_angle_cls=True, lang='en')

image = load_image()

if st.button('Analyse my results'):
# Save test attributes
test_attributes["age"] = age
test_attributes["sex"] = sex
test_attributes["race"] = race
test_attributes["smoker"] = smoker #true or false
test_attributes["stroke"] = stroke
test_attributes["diabetes"] = diabetes
test_attributes["heart_attack"] = heart_attack
test_attributes["on_BP_meds"] = on_bp_meds
test_attributes["systolic_blood_pressure"] = systolic_bp #null or integer
st.json(test_attributes)
# Extract text from image
if not image: #Image not uploaded
st.error("Upload an image of your test results first!",icon="🚨")
else: # Image uploaded
ocr_start_time = time.time()
result = ocr_model.ocr(image)
result = result[0] #idk why this needs a result[0] instead of result for Github
extracted_text = ''
for idx in range(len(result)):
txt = result[idx][1][0]
extracted_text += txt + " "
ocr_end_time = time.time()
ocr_time = int(ocr_end_time - ocr_start_time)
st.markdown(extracted_text)
st.success(f"Processed image in {ocr_time} seconds.") # Use status instead of toast/success
# Remove NRIC from extracted text

# Extract structured data from text using ChatGPT
# TODO: PUT TRY AND ERROR IF FAIL
extract_start_time = time.time()
extract_prompt = f"{template_prompt} {extracted_text}"
response = client.chat.completions.create(
model="gpt-3.5-turbo-1106",
response_format={ "type": "json_object" },
messages=[
{"role": "system", "content": "You are a helpful assistant designed to output JSON."},
{"role": "user", "content": extract_prompt}
]
)
test_results = json.loads(response.choices[0].message.content)
st.json(test_results)
st.text(response.usage)
extract_end_time = time.time()
extract_time = int(extract_end_time - extract_start_time)
st.success(f"Extracted values in {extract_time} seconds.") # Use status instead of toast/success
for test_name, test_info in test_results.items():
if test_info["test_found"]:
st.markdown(f"**Test Name:** {test_name.replace('_', ' ').upper()}")
st.markdown(f"**Test Value:** {test_info['test_value']} {test_info['test_unit']}")
#st.markdown(f"**Reference Range:** {test_info['test_ref_min']} - {test_info['test_ref_max']} {test_info['test_unit']}")
st.text("")
# Insert YT logic

st.caption('Disclaimer: Not medical advice, not liable, blah')