forked from uc-cdis/compose-services
-
Notifications
You must be signed in to change notification settings - Fork 1
Feature/dash cohort #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
bwalsh
wants to merge
18
commits into
ohsu-training
Choose a base branch
from
feature/dash-cohort
base: ohsu-training
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
fb654ad
Adds dash prototype
bwalsh a318042
Checklist per property
bwalsh 1017749
RangeSlider
bwalsh f6a5535
Update badges via client side callback
bwalsh 6c1fe49
Adds dash container
bwalsh 5bf7d0a
Queries files based on observations
bwalsh 95db4e9
Adds fhir service
bwalsh 22b1af0
Bump ES memory
bwalsh 4701e49
Adds comment how to remove objects from bucket
bwalsh b3597bc
Adds fhir_user
bwalsh 80a18c2
Adds more Observation fields
bwalsh 67abc84
Experiment with sidebar
bwalsh bafa875
Add TODO comment - tests JIRA integration ACED-48
bwalsh 560b65d
Change to local data-portal build for Windmill
lbeckman314 0e520ef
Add files via upload
matthewpeterkort 57fc62b
Add files via upload
matthewpeterkort 7d47bfd
Add files via upload
matthewpeterkort 26c417b
Merge pull request #28 from ACED-IDP/feature/local-data-portal
matthewpeterkort File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| venv/ | ||
| .idea/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| venv/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| FROM python:3.10 | ||
| WORKDIR /code | ||
|
|
||
| COPY requirements.txt / | ||
| RUN pip install -r /requirements.txt | ||
| COPY ./ ./ | ||
|
|
||
| EXPOSE 8050 | ||
|
|
||
| CMD ["python", "./app.py"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| import logging | ||
| import os | ||
|
|
||
| import dash | ||
| import dash_bootstrap_components as dbc | ||
| from dash import Dash, Output, Input, dcc | ||
| from dash import html | ||
|
|
||
| from util import get_authz | ||
|
|
||
| external_stylesheets = [dbc.themes.SKETCHY] | ||
|
|
||
| logger = logging.getLogger('dash') | ||
|
|
||
| print('DASH_URL_BASE_PATHNAME', os.environ.get('DASH_URL_BASE_PATHNAME', default="~not set~")) | ||
| app = Dash(__name__, external_stylesheets=external_stylesheets, use_pages=True) | ||
|
|
||
|
|
||
| @app.server.before_request | ||
| def check_privileges(): | ||
| """Do this before every call""" | ||
| get_authz() | ||
|
|
||
|
|
||
| # Clientside callback: refresh token by calling fence's /user endpoint | ||
| app.clientside_callback( | ||
| """ | ||
| // Call fence's /user endpoint, parse the response and update the profile | ||
| async function(n_intervals, data) { | ||
| const response = await fetch(location.origin + '/user/user'); | ||
| if (!response.ok) { | ||
| console.log('error retrieving user', response ) | ||
| return 'Profile (unauthorized)'; | ||
| } else { | ||
| const user = await response.json(); | ||
| console.log('clientside_callback you are logged in as:', user.username); | ||
| return 'Profile (' + user.username + ')'; | ||
| } | ||
| } | ||
| """, | ||
| Output('nav_item-profile', 'children'), | ||
| Input('clientside-interval', 'n_intervals') | ||
| ) | ||
|
|
||
|
|
||
| app.layout = dbc.Container([ | ||
| html.H1("ACED", className="display-3"), | ||
| html.P( | ||
| "A simple dash app.", | ||
| className="lead", | ||
| ), | ||
|
|
||
| dbc.Nav( | ||
| [ | ||
| dbc.NavItem( | ||
| dbc.NavLink(f"{page['name']}", href=page["relative_path"], id=f'nav_item-{page["name"].lower()}') | ||
| ) | ||
| for page in dash.page_registry.values() | ||
| ] | ||
| ), | ||
|
|
||
| html.Hr(className="my-2"), | ||
| # define a timed client side action here | ||
| dcc.Interval( | ||
| id='clientside-interval', | ||
| n_intervals=0, | ||
| interval=60 * 1000 # in milliseconds check every minute | ||
| ), | ||
| # other page contents goes here | ||
| dash.page_container | ||
| ]) | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| app.run_server(host="0.0.0.0", debug=True) # |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| import logging | ||
|
|
||
| import dash_bootstrap_components as dbc | ||
| import pandas as pd | ||
| import plotly.express as px | ||
| from dash import html, dcc | ||
|
|
||
| logger = logging.getLogger('dash') | ||
|
|
||
|
|
||
| def histogram_figures(histograms): | ||
| """An array of histograms figures, dataframes and names. | ||
| @return fig[], df[], name[]""" | ||
|
|
||
| dfs = [] | ||
| figs = [] | ||
| names = [] | ||
|
|
||
| assert len(histograms._aggregation.keys()) == 1 # noqa | ||
| entity = list(histograms._aggregation.keys())[0] # noqa | ||
| for k, v in histograms._aggregation[entity].items(): # noqa | ||
| v.name = k | ||
| df = pd.DataFrame(v.histogram) | ||
| fig = px.histogram(df, x="key", y="count", title=v.name, log_y=len(v.histogram) > 1, | ||
| id={ | ||
| 'index': f"{entity}-{k}", | ||
| 'type': 'query-parameter' | ||
| } | ||
| ) | ||
| fig.update_layout(legend=dict(orientation="h", title=None), | ||
| yaxis_title=None, xaxis_title=None, | ||
| plot_bgcolor='rgba(0,0,0,0)' | ||
| ) | ||
|
|
||
| figs.append(fig) | ||
| dfs.append(df) | ||
| names.append(v.name) | ||
|
|
||
| return figs, dfs, names | ||
|
|
||
|
|
||
| def histogram_selects(histograms): | ||
| """An array of histograms checklists dataframes, and names. | ||
| @return fig[], df[], name[]""" | ||
|
|
||
| dfs = [] | ||
| checklists = [] | ||
| names = [] | ||
|
|
||
| assert len(histograms._aggregation.keys()) == 1 # noqa | ||
| entity = list(histograms._aggregation.keys())[0] # noqa | ||
| for k, v in histograms._aggregation[entity].items(): # noqa | ||
| v.name = k | ||
| if not any([isinstance(h.key, str) for h in v.histogram]): | ||
| continue | ||
| df = pd.DataFrame(v.histogram) | ||
| checklist = dcc.Checklist( | ||
| id={ | ||
| 'index': f"{entity}-{k}", | ||
| 'type': 'query-parameter' | ||
| }, | ||
| options=[ | ||
| { | ||
| 'value': str(h.key), | ||
| 'label': html.Div( | ||
| [ | ||
| html.Div(h.key), | ||
| dbc.Badge(h.count, className="ms-1 term-count", color="info", | ||
| id={ | ||
| 'index': f"{entity}-{k}-{h.key}", | ||
| 'type': 'term-count' | ||
| }) | ||
| ], | ||
| style={'display': 'inline-flex', 'paddingLeft': '2em'} | ||
| ) | ||
| } | ||
| for h in v.histogram | ||
| ], | ||
| labelStyle={'display': 'flex'} | ||
| ) | ||
|
|
||
| checklists.append(checklist) | ||
| dfs.append(df) | ||
| names.append(v.name) | ||
|
|
||
| return checklists, dfs, names | ||
|
|
||
|
|
||
| def histogram_sliders(histograms): | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what are histogram sliders? |
||
| """An array of histograms sliders dataframes, and names. | ||
| @return slider[], df[], name[]""" | ||
|
|
||
| dfs = [] | ||
| sliders = [] | ||
| names = [] | ||
|
|
||
| assert len(histograms._aggregation.keys()) == 1 # noqa | ||
| entity = list(histograms._aggregation.keys())[0] # noqa | ||
| for k, v in histograms._aggregation[entity].items(): # noqa | ||
| v.name = k | ||
| if any([isinstance(h.key, str) for h in v.histogram]): | ||
| continue | ||
| if not any([isinstance(h.key, list) for h in v.histogram]): | ||
| continue | ||
|
|
||
| assert len(v.histogram) == 1 | ||
| df = pd.DataFrame(v.histogram) | ||
| min_ = int(v.histogram[0].key[0]) | ||
| max_ = int(v.histogram[0].key[1]) | ||
| # value = max_, | ||
| sliders.append( | ||
| dcc.RangeSlider(min_, max_, int((max_ - min_) / 10), | ||
| id={ | ||
| 'index': f"{entity}-{k}", | ||
| 'type': 'query-parameter' | ||
| } | ||
| ) | ||
| ) | ||
|
|
||
| dfs.append(df) | ||
| names.append(v.name) | ||
|
|
||
| return sliders, dfs, names | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
|
|
||
| import pandas as pd | ||
| import plotly.express as px | ||
| from inflection import titleize, pluralize | ||
| from models.project import project_detail_counts | ||
|
|
||
|
|
||
| def counts(): | ||
| """Horizontal bar graph. | ||
| @return fig, df""" | ||
|
|
||
| project_counts = list(project_detail_counts()) | ||
| flattened = [] | ||
| for p in project_counts: | ||
| for k, v in p.items(): | ||
| f = {'name': p.project[0].name} | ||
| if k == 'project': | ||
| continue | ||
| f['entity'] = titleize(pluralize(k.replace('_count', ''))) | ||
| f['count'] = v | ||
| flattened.append(f) | ||
| df = pd.DataFrame(flattened) | ||
| fig = px.bar(df, x="count", y="entity", color='name', orientation='h', | ||
| hover_data=["name", "count"], | ||
| height=400, | ||
| log_x=True) | ||
| fig.update_layout(legend=dict(orientation="h", title=None), yaxis_title=None, xaxis_title=None, | ||
| # paper_bgcolor='rgba(0,0,0,0)', | ||
| plot_bgcolor='rgba(0,0,0,0)' | ||
| ) | ||
| return fig, df |
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
|
|
||
| from dotwiz import DotWiz | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is DotWiz? |
||
| from util import get_guppy_service | ||
|
|
||
| import logging | ||
| logger = logging.getLogger('dash') | ||
|
|
||
|
|
||
| def get_files(dot_notation=True, variables={"filter": {"AND": []}, "sort": []}): | ||
| """Fetch histogram of counts for all projects. | ||
| @param variables: a graphql filter and sort | ||
| @type dot_notation: bool render results as a lightweight class""" | ||
| query = """ | ||
| query ($sort: JSON,$filter: JSON,) { | ||
| file (accessibility: all, offset: 0, first: 1000, , sort: $sort, filter: $filter,) { | ||
| file_id | ||
| patient_id | ||
| file_category | ||
| file_name | ||
| file_size | ||
| object_id | ||
| } | ||
| _aggregation { | ||
| file (filter: $filter, accessibility: all) { | ||
| _totalCount | ||
| } | ||
| } | ||
| } | ||
| """ | ||
| guppy_service = get_guppy_service() | ||
| data = guppy_service.graphql_query(query, variables=variables)['data'] | ||
| data = DotWiz(data) | ||
| return [f for f in data.file] | ||
|
|
||
|
|
||
| def get_file_histograms(dot_notation=True, variables={"filter": {"AND": []}}): | ||
| """Fetch histogram of counts for all projects. | ||
| @param variables: a graphql filter | ||
| @type dot_notation: bool render results as a lightweight class""" | ||
|
|
||
| histogram_query = """ | ||
| query ($filter: JSON) { | ||
| _aggregation { | ||
| file (filter: $filter, filterSelf: false, accessibility: all) { | ||
|
|
||
| project_id { | ||
| histogram { | ||
| key | ||
| count | ||
| } | ||
| }, | ||
| file_category { | ||
| histogram { | ||
| key | ||
| count | ||
| } | ||
| }, | ||
| data_type { | ||
| histogram { | ||
| key | ||
| count | ||
| } | ||
| }, | ||
| data_format { | ||
| histogram { | ||
| key | ||
| count | ||
| } | ||
| }, | ||
| patient_id { | ||
| histogram { | ||
| key | ||
| count | ||
| } | ||
| }, | ||
| patient_gender { | ||
| histogram { | ||
| key | ||
| count | ||
| } | ||
| }, | ||
| patient_disability_adjusted_life_years { | ||
| histogram { | ||
| key | ||
| count | ||
| } | ||
| }, | ||
| patient_ombCategory { | ||
| histogram { | ||
| key | ||
| count | ||
| } | ||
| }, | ||
| patient_ombCategory_detail { | ||
| histogram { | ||
| key | ||
| count | ||
| } | ||
| }, | ||
| patient_us_core_birthsex { | ||
| histogram { | ||
| key | ||
| count | ||
| } | ||
| }, | ||
| patient_quality_adjusted_life_years { | ||
| histogram { | ||
| key | ||
| count | ||
| } | ||
| }, | ||
| patient_maritalStatus_coding_0_display { | ||
| histogram { | ||
| key | ||
| count | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| """ | ||
| guppy_service = get_guppy_service() | ||
| data = guppy_service.graphql_query(histogram_query, variables=variables)['data'] | ||
| if dot_notation: | ||
| return DotWiz(data) | ||
| return data | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this a style structure?