--- a +++ b/openomics_web/app.py @@ -0,0 +1,209 @@ +import dash +import dash_html_components as html +from dash.dependencies import Input, Output, State + +from openomics import MultiOmics +from openomics_web.layouts import app_layout +from openomics_web.layouts.clinical_view import ClinicalDataColumnSelect, ClinicalDataTable +from openomics_web.layouts.datatable_view import ExpressionDataTable, DataTableColumnSelect, split_filter_part +from openomics_web.server import server +from openomics_web.utils.io import get_table_columns, get_expression_data, get_clinical_data + +external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] + +# running directly with Python +app = dash.Dash(__name__, + server=server, + external_stylesheets=external_stylesheets) + +app.layout = app_layout.app_main() + +user_multiomics = MultiOmics(cohort_name="TEST", ) + + +@app.callback([ + Output('data-table-column-select', 'children'), + Output('upload-data-table', 'children') +], [ + Input('upload-data-table', 'contents'), + Input('upload-data-table', 'filename') +], [ + State('data-table-type', 'value'), +]) +def update_datatable_metadata( + list_of_contents, + list_of_names, + data_type, +): + """ + Args: + list_of_contents: + list_of_names: + data_type: + """ + if list_of_contents is None: + return None, ['Drag and Drop or ', html.A('Select Files')] + + try: + columns = get_table_columns(list_of_contents, list_of_names) + + except Exception as e: + print(e) + return None, 'There was an error processing this file.' + + return DataTableColumnSelect(columns), "Uploaded {}".format(list_of_names) + + +@app.callback(Output('output-data-upload', 'children'), + [Input('upload-data-table-submit', 'n_clicks')], [ + State('data-table-cohort', 'value'), + State('data-table-type', 'value'), + State('upload-data-table', 'contents'), + State('upload-data-table', 'filename'), + State('data-table-genes-col-name', 'value'), + State('data-table-columns-select', 'value'), + State('data-table-transpose', 'value') +]) +def import_datatable_upload(n_clicks, cohort_name, data_type, list_of_contents, + list_of_names, genes_col_name, columns_select, + transposed): + """ + Args: + n_clicks: + cohort_name: + data_type: + list_of_contents: + list_of_names: + genes_col_name: + columns_select: + transposed: + """ + if list_of_contents is None: + return [] + try: + + omics_data = get_expression_data(list_of_contents, list_of_names, + data_type, cohort_name, + genes_col_name, columns_select, + transposed) + user_multiomics.add_omic(omics_data) + except Exception as e: + print(e) + return html.Div(['There was an error processing this file.']) + + return ExpressionDataTable(omics_data.expressions.head(20)) + + +@app.callback(Output('expression-datatable', "data"), [ + Input('expression-datatable', "page_current"), + Input('expression-datatable', "page_size"), + Input('expression-datatable', "sort_by"), + Input('expression-datatable', "filter_query") +]) +def update_table(page_current, page_size, sort_by, filter): + """ + Args: + page_current: + page_size: + sort_by: + filter: + """ + filtering_expressions = filter.split(' && ') + print(user_multiomics.get_omics_list()) + dff = user_multiomics[user_multiomics.get_omics_list()[0]] + for filter_part in filtering_expressions: + col_name, operator, filter_value = split_filter_part(filter_part) + + if operator in ('eq', 'ne', 'lt', 'le', 'gt', 'ge'): + # these operators match pandas series operator method names + dff = dff.loc[getattr(dff[col_name], operator)(filter_value)] + elif operator == 'contains': + dff = dff.loc[dff[col_name].str.contains(filter_value)] + elif operator == 'datestartswith': + # this is a simplification of the front-end filtering logic, + # only works with complete fields in standard format + dff = dff.loc[dff[col_name].str.startswith(filter_value)] + + if sort_by: + dff = dff.sort_values( + [col['column_id'] for col in sort_by], + ascending=[col['direction'] == 'asc' for col in sort_by], + inplace=False) + + return dff.iloc[page_current * page_size:(page_current + 1) * + page_size].to_dict('records') + + +@app.callback( + [ + Output('clinical-column-select', 'children'), + Output('upload-clinical', 'children') + ], + [ + Input('upload-clinical', 'contents'), + Input('upload-clinical', 'filename') + ], +) +def update_clinical_upload_metadata( + file_content, + file_name, +): + """ + Args: + file_content: + file_name: + """ + if file_content is None: + return None, ['Drag and Drop or ', html.A('Select Files')] + + try: + columns = get_table_columns([ + file_content, + ], [ + file_name, + ]) + + except Exception as e: + print(e) + return None, 'There was an error processing this file.' + + return ClinicalDataColumnSelect(columns), "Uploaded {}".format(file_name) + + +@app.callback(Output('output-clinical-upload', 'children'), + [Input('clinical-submit-button', 'n_clicks')], [ + State('clinical-cohort', 'value'), + State('clinical-data-type', 'value'), + State('upload-clinical', 'contents'), + State('upload-clinical', 'filename'), + State('clinical-patient-col-name', 'value'), + State('clinical-data-columns-select', 'value'), +]) +def import_datatable_upload(n_clicks, cohort_name, data_type, list_of_contents, + list_of_names, patient_id_col, columns_select): + """ + Args: + n_clicks: + cohort_name: + data_type: + list_of_contents: + list_of_names: + patient_id_col: + columns_select: + """ + if list_of_contents is None: + return [] + try: + clinical_data = get_clinical_data(list_of_contents, list_of_names, + data_type, cohort_name, + patient_id_col, columns_select) + user_multiomics.add_clinical_data(clinical_data) + except Exception as e: + print(e) + return html.Div(['There was an error processing this file.']) + + return ClinicalDataTable(clinical_data.patient.head(20)) + + +if __name__ == '__main__': + app.run_server(debug=False, port=8050)