Add files via upload

This commit is contained in:
Arpan Ghosh 2023-07-25 23:37:02 -04:00 committed by GitHub
parent 10b92192c2
commit 13e6ee7a1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 200 additions and 1 deletions

View File

@ -1 +1,11 @@
# fitbit-web-ui-app
# Dash Default Template: Fitbit_API_Web_UI
Created on 2023-07-25 23:24:41.162732
Welcome to your [Plotly Dash](https://plotly.com/dash/) App! This is a template for your Fitbit_API_Web_UI app.
See the [Dash Documentation](https://dash.plotly.com/introduction) for more information on how to get your app up and running.
## Running the App
Run `src/app.py` and navigate to http://127.0.0.1:8050/ in your browser.

14
render.yaml Normal file
View File

@ -0,0 +1,14 @@
services:
# See https://render.com/docs/blueprint-spec for more info on render blueprints
- type: web
name: fitbit_api_web_ui
env: python
plan: free
# A requirements.txt file must exist
buildCommand: "pip install -r requirements.txt"
# A src/app.py file must exist and contain `server=app.server`
startCommand: "gunicorn --chdir src app:server"
envVars:
- key: PYTHON_VERSION
value: 3.10.0

6
requirements.txt Normal file
View File

@ -0,0 +1,6 @@
dash==2.11.1
pandas==2.0.3
plotly==5.15.0
requests==2.29.0
gunicorn
dash-tools

1
src/__init__.py Normal file
View File

@ -0,0 +1 @@
# Auto-generated at 2023-07-25 23:24:41.181367

168
src/app.py Normal file
View File

@ -0,0 +1,168 @@
# %%
import dash, requests, math
from dash import dcc
from dash import html
from dash.dependencies import Output, State, Input
import pandas as pd
import plotly.express as px
from datetime import datetime, timedelta
# %%
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
server = app.server
# assume you have a "long-form" data frame
# see https://plotly.com/python/px-arguments/ for more options
app.layout = html.Div(children=[
# All elements from the top of the page
html.Div(style={
'display': 'flex',
'align-items': 'center',
'justify-content': 'center',
'gap': '20px',
'margin': 'auto',
'flex-wrap': 'wrap'
},children=[
dcc.DatePickerRange(
id='my-date-picker-range',
minimum_nights=30,
max_date_allowed=datetime.today().date() - timedelta(days=1),
min_date_allowed=datetime.today().date() - timedelta(days=720),
end_date=datetime.today().date() - timedelta(days=1),
start_date=datetime.today().date() - timedelta(days=365)
),
dcc.Input(id='input-on-submit', value="", placeholder='API ACCESS TOKEN', type='text'),
html.Button(id='submit-button', type='submit', children='Submit', n_clicks=0),
]),
html.Div(id='loading-div', style={'margin-top': '40px'}, children=[
dcc.Loading(
id="loading-progress",
type="default",
children=html.Div(id="loading-output-1")
),
]),
html.Div(id='output_div', children=[
dcc.Graph(
id='graph_RHR',
figure=px.line(),
config= {'displaylogo': False}
),
dcc.Graph(
id='graph_steps',
figure=px.bar(),
config= {'displaylogo': False}
),
dcc.Graph(
id='graph_activity_minutes',
figure=px.bar(),
config= {'displaylogo': False}
),
dcc.Graph(
id='graph_weight',
figure=px.line(),
config= {'displaylogo': False}
),
dcc.Graph(
id='graph_spo2',
figure=px.line(),
config= {'displaylogo': False}
),
]),
])
@app.callback(Output('graph_RHR', 'figure'), Output('graph_steps', 'figure'), Output('graph_activity_minutes', 'figure'), Output('graph_weight', 'figure'), Output('graph_spo2', 'figure'), Output("loading-output-1", "children"),
Input('submit-button', 'n_clicks'),
State('input-on-submit', 'value'), State('my-date-picker-range', 'start_date'), State('my-date-picker-range', 'end_date'),
prevent_initial_call=True
)
def update_output(n_clicks, value, start_date, end_date):
start_date = datetime.fromisoformat(start_date).strftime("%Y-%m-%d")
end_date = datetime.fromisoformat(end_date).strftime("%Y-%m-%d")
headers = {
"Authorization": "Bearer " + value,
"Accept": "application/json"
}
# Collecting data-----------------------------------------------------------------------------------------------------------------------
response_heartrate = requests.get("https://api.fitbit.com/1/user/-/activities/heart/date/"+ start_date +"/"+ end_date +".json", headers=headers).json()
response_steps = requests.get("https://api.fitbit.com/1/user/-/activities/steps/date/"+ start_date +"/"+ end_date +".json", headers=headers).json()
response_weight = requests.get("https://api.fitbit.com/1/user/-/body/weight/date/"+ start_date +"/"+ end_date +".json", headers=headers).json()
response_spo2 = requests.get("https://api.fitbit.com/1/user/-/spo2/date/"+ start_date +"/"+ end_date +".json", headers=headers).json()
# Processing data-----------------------------------------------------------------------------------------------------------------------
dates_list = []
dates_str_list = []
rhr_list = []
steps_list = []
weight_list = []
spo2_list = []
fat_burn_minutes_list, cardio_minutes_list, peak_minutes_list = [], [], []
for entry in response_heartrate['activities-heart']:
dates_str_list.append(entry['dateTime'])
dates_list.append(datetime.strptime(entry['dateTime'], '%Y-%m-%d'))
try:
fat_burn_minutes_list.append(entry["value"]["heartRateZones"][1]["minutes"])
cardio_minutes_list.append(entry["value"]["heartRateZones"][2]["minutes"])
peak_minutes_list.append(entry["value"]["heartRateZones"][3]["minutes"])
except KeyError as E:
fat_burn_minutes_list.append(None)
cardio_minutes_list.append(None)
peak_minutes_list.append(None)
if 'restingHeartRate' in entry['value']:
rhr_list.append(entry['value']['restingHeartRate'])
else:
rhr_list.append(None)
for entry in response_steps['activities-steps']:
steps_list.append(int(entry['value']))
for entry in response_weight["body-weight"]:
weight_list.append(float(entry['value']))
for entry in response_spo2:
spo2_list += [None]*(dates_str_list.index(entry["dateTime"])-len(spo2_list))
spo2_list.append(entry["value"]["avg"])
df_merged = pd.DataFrame({
"Date": dates_list,
"Resting Heart Rate": rhr_list,
"Steps Count": steps_list,
"Fat Burn Minutes": fat_burn_minutes_list,
"Cardio Minutes": cardio_minutes_list,
"Peak Minutes": peak_minutes_list,
"weight": weight_list,
"SPO2": spo2_list
})
# Plotting data-----------------------------------------------------------------------------------------------------------------------
fig_rhr = px.line(df_merged, x="Date", y="Resting Heart Rate", line_shape="spline", range_y=(40,80), color_discrete_sequence=["#6b3908"], title="Daily Resting Heart Rate")
fig_steps = px.bar(df_merged, x="Date", y="Steps Count", title="Daily Steps Count")
fig_activity_minutes = px.bar(df_merged, x="Date", y=["Fat Burn Minutes", "Cardio Minutes", "Peak Minutes"], title="Activity Minutes")
fig_activity_minutes.update_layout(yaxis_title='Active Minutes')
fig_weight = px.line(df_merged, x="Date", y="weight", line_shape="spline", color_discrete_sequence=["#6b3908"], title="Weight")
fig_spo2 = px.bar(df_merged, x="Date", y="SPO2", title="SPO2 Percentage", range_y=(80,100))
return fig_rhr, fig_steps, fig_activity_minutes, fig_weight, fig_spo2, ""
if __name__ == '__main__':
app.run_server(debug=True)
# %%