From 9cbb7e4f4d8d332d2638791e3d25d70637d50790 Mon Sep 17 00:00:00 2001 From: Bartosz Stachowiak Date: Tue, 30 May 2023 20:03:31 +0200 Subject: [PATCH 1/3] adjust stage 2 layout --- dashboard/app.py | 7 +- dashboard/assets/style.css | 22 -- .../pages/primary_screening/callbacks.py | 7 +- .../stages/s2_outliers_purging.py | 278 +++++++++--------- 4 files changed, 154 insertions(+), 160 deletions(-) diff --git a/dashboard/app.py b/dashboard/app.py index 81fdd4e..0d16cff 100644 --- a/dashboard/app.py +++ b/dashboard/app.py @@ -7,13 +7,18 @@ BOOTSTRAP_CDN = ( "https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" ) +FONT_AWESOME_CDN = ( + "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" +) VERSION = "v1.0.0-dev" fs_dir = os.environ.get("DRUG_SCREENING_DATA_DIR", ".drug-screening-data") file_storage = LocalFileStorage.set_data_folder(fs_dir) -app = Dash(__name__, external_stylesheets=[BOOTSTRAP_CDN], use_pages=True) +app = Dash( + __name__, external_stylesheets=[BOOTSTRAP_CDN, FONT_AWESOME_CDN], use_pages=True +) app.layout = html.Div( diff --git a/dashboard/assets/style.css b/dashboard/assets/style.css index 6f2803b..acc8bcf 100644 --- a/dashboard/assets/style.css +++ b/dashboard/assets/style.css @@ -71,25 +71,3 @@ .fixed-width-150 { width: 150px; } - -.dash-spreadsheet-container { - max-height: 200px; -} - -@media only screen and (min-height: 800px) { - .dash-spreadsheet-container { - max-height: 250px; - } -} - -@media only screen and (min-height: 900px) { - .dash-spreadsheet-container { - max-height: 350px; - } -} - -@media only screen and (min-height: 1000px) { - .dash-spreadsheet-container { - max-height: 450px; - } -} diff --git a/dashboard/pages/primary_screening/callbacks.py b/dashboard/pages/primary_screening/callbacks.py index a9df2f6..b70bdb3 100644 --- a/dashboard/pages/primary_screening/callbacks.py +++ b/dashboard/pages/primary_screening/callbacks.py @@ -64,8 +64,9 @@ def upload_bmg_data(contents, names, last_modified, stored_uuid, file_storage): # === STAGE 2 === -DISPLAYED_PLATES = 9 -DIM = int(np.ceil(np.sqrt(DISPLAYED_PLATES))) +DISPLAYED_PLATES = 12 +N_ROWS = 4 +N_COLS = DISPLAYED_PLATES // N_ROWS def on_heatmap_controls_clicked( @@ -156,7 +157,7 @@ def on_outlier_purge_stage_entry( heatmap_start_index : heatmap_start_index + DISPLAYED_PLATES ] - fig = visualize_multiple_plates(vis_bmg_df, vis_bmg_vals, DIM, DIM) + fig = visualize_multiple_plates(vis_bmg_df, vis_bmg_vals, N_ROWS, N_COLS) index_text = f"{heatmap_start_index + 1} - {heatmap_start_index + DISPLAYED_PLATES} / {bmg_vals.shape[0]}" final_vis_df = ( diff --git a/dashboard/pages/primary_screening/stages/s2_outliers_purging.py b/dashboard/pages/primary_screening/stages/s2_outliers_purging.py index b74bd3e..c983162 100644 --- a/dashboard/pages/primary_screening/stages/s2_outliers_purging.py +++ b/dashboard/pages/primary_screening/stages/s2_outliers_purging.py @@ -37,155 +37,165 @@ ], ) -OUTLIERS_PURGING_STAGE = html.Div( - id="outliers_purging_stage", - className="container h-100 d-flex flex-column", +CONTROLS = html.Div( + className="d-flex justify-content-center gap-2 mt-3", children=[ - html.H1( - children=["Outliers Purging"], - className="text-center", + html.Button( + id="heatmap-first-btn", + children=[ + html.I(className="fa-solid fa-angles-left"), + ], + className="btn btn-primary", + ), + html.Button( + id="heatmap-previous-btn", + children=[ + html.I(className="fa-solid fa-angle-left"), + ], + className="btn btn-primary", ), html.Div( - className="row flex-grow-1", + id="heatmap-index-display", + children=["0/0"], + className="text-center my-auto fixed-width-150 text-muted", + ), + html.Button( + id="heatmap-next-btn", + children=[ + html.I(className="fa-solid fa-angle-right"), + ], + className="btn btn-primary", + ), + html.Button( + id="heatmap-last-btn", + children=[ + html.I(className="fa-solid fa-angles-right"), + ], + className="btn btn-primary", + ), + ], +) + +HEATMAP_SECTION = html.Div( + className="col w-50 h-100", + children=[ + html.Div( + className="d-flex flex-column gap-3 h-100", children=[ html.Div( - className="col w-50 h-100", + className="overflow-auto mx-2 border border-3 rounded shadow bg-body-tertiary bg-primary flex-grow-1", children=[ - html.Div( - className="d-flex flex-column gap-3 h-100", - children=[ - html.H2( - children=["Plates Heatmap"], - className="text-center", - ), - html.Div( - className="overflow-auto mx-2 border border-3 rounded shadow bg-body-tertiary bg-primary flex-grow-1", - children=[ - dcc.Graph( - id="plates-heatmap-graph", - figure={}, - style={"height": "100%"}, - ), - ], - ), - html.Div( - className="d-flex justify-content-center gap-2 mt-3", - children=[ - html.Button( - id="heatmap-first-btn", - children=["First"], - className="btn btn-secondary fixed-width-100", - ), - html.Button( - id="heatmap-previous-btn", - children=["Previous"], - className="btn btn-primary fixed-width-100", - ), - html.Div( - id="heatmap-index-display", - children=["0/0"], - className="text-center my-auto fixed-width-150 text-muted", - ), - html.Button( - id="heatmap-next-btn", - children=["Next"], - className="btn btn-primary fixed-width-100", - ), - html.Button( - id="heatmap-last-btn", - children=["Last"], - className="btn btn-secondary fixed-width-100", - ), - ], - ), - html.Div( - className="d-flex justify-content-center gap-2 mt-3", - children=[ - dcc.Checklist( - id="heatmap-outliers-checklist", - options=["Show only with outliers"], - inputClassName="me-2", - ), - ], - ), - ], + dcc.Graph( + id="plates-heatmap-graph", + figure={}, + style={"height": "100%"}, ), ], ), + ], + ), + ], +) +DATATABLE_SECTION = html.Div( + className="col d-flex flex-column gap-3 w-50 h-100", + children=[ + html.Div( + className="d-flex flex-column gap-3 flex-grow-1 h-100", + children=[ html.Div( - className="col d-flex flex-column gap-3 w-50 h-100", + className="overflow-auto mx-2 border border-3 rounded shadow bg-body-tertiary", + children=[_COMPOUNDS_DATATABLE], + ), + ], + ), + ], +) +STATS_SECTION = html.Div( + className="d-flex flex-row justify-content-between align-items-center", + children=[ + html.Div( + children=[ + html.Span( + className="mx-2", children=[ - html.Div( - className="d-flex flex-column gap-3 flex-grow-1 h-100", - children=[ - html.H2( - children=["Plates Summary"], - className="text-center", - ), - html.Div( - className="overflow-auto mx-2 border border-3 rounded shadow bg-body-tertiary", - children=[_COMPOUNDS_DATATABLE], - ), - ], + html.Span( + children=["Total Plates:"], + className="me-2", ), - html.Div( - className="d-flex flex-column gap-3 mb-5", - children=[ - html.H2( - children=["Assay Stats"], - className="text-center", - ), - html.Div( - className="mx-5", - children=[ - html.Div( - className="row border-bottom", - children=[ - html.H3( - children=["Total Plates:"], - className="col-6 text-start my-auto fs-4", - ), - html.H3( - id="total-plates", - children=["0"], - className="col-6 text-end pe-3 my-auto fs-4", - ), - ], - ), - html.Div( - className="row border-bottom", - children=[ - html.H3( - children=["Total Compounds:"], - className="col-6 text-start my-auto fs-4", - ), - html.H3( - id="total-compounds", - children=["0"], - className="col-6 text-end pe-3 my-auto fs-4", - ), - ], - ), - html.Div( - className="row border-bottom", - children=[ - html.H3( - children=["Total Outliers:"], - className="col-6 text-start my-auto fs-4", - ), - html.H3( - id="total-outliers", - children=["0"], - className="col-6 text-end pe-3 my-auto fs-4", - ), - ], - ), - ], - ), - ], + html.Span( + id="total-plates", + children=["0"], + className="", ), ], ), + html.Span( + className="mx-2", + children=[ + html.Span( + children=["Total Compounds:"], + className="me-2", + ), + html.Span( + id="total-compounds", + children=["0"], + className="", + ), + ], + ), + html.Span( + className="mx-2", + children=[ + html.Span( + children=["Total Outliers:"], + className="me-2", + ), + html.Span( + id="total-outliers", + children=["0"], + className="", + ), + ], + ), + ] + ), + html.Div( + children=[ + dcc.Checklist( + id="heatmap-outliers-checklist", + options=["Show only with outliers"], + inputClassName="me-2", + ), + ], + ), + ], +) + +OUTLIERS_PURGING_STAGE = html.Div( + id="outliers_purging_stage", + className="container h-100 d-flex flex-column", + children=[ + html.H1( + children=["Outliers Purging"], + className="text-center", + ), + html.Div( + className="row mb-2 pb-2 border-bottom", + children=[ + STATS_SECTION, + ], + ), + html.Div( + className="row flex-grow-1", + children=[ + HEATMAP_SECTION, + DATATABLE_SECTION, + ], + ), + html.Div( + className="row", + children=[ + CONTROLS, ], ), dcc.Store(id="heatmap-start-index", data=0), From 03e78cc27a443afa4ae179a098117079b8bbec0b Mon Sep 17 00:00:00 2001 From: Bartosz Stachowiak Date: Tue, 30 May 2023 20:20:24 +0200 Subject: [PATCH 2/3] hide plot controls --- .../pages/primary_screening/stages/s2_outliers_purging.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dashboard/pages/primary_screening/stages/s2_outliers_purging.py b/dashboard/pages/primary_screening/stages/s2_outliers_purging.py index c983162..05bab26 100644 --- a/dashboard/pages/primary_screening/stages/s2_outliers_purging.py +++ b/dashboard/pages/primary_screening/stages/s2_outliers_purging.py @@ -89,6 +89,10 @@ id="plates-heatmap-graph", figure={}, style={"height": "100%"}, + config={ + "displayModeBar": False, + "scrollZoom": False, + }, ), ], ), From 7ad5c2bd018ef7b1aad07470e5aeb843ce196fa5 Mon Sep 17 00:00:00 2001 From: Bartosz Stachowiak Date: Thu, 1 Jun 2023 19:00:18 +0200 Subject: [PATCH 3/3] disable zooming and panning on heatmap plots --- dashboard/visualization/plots.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/dashboard/visualization/plots.py b/dashboard/visualization/plots.py index f589d91..e2f7aae 100644 --- a/dashboard/visualization/plots.py +++ b/dashboard/visualization/plots.py @@ -97,7 +97,17 @@ def visualize_multiple_plates( p[1], ) - fig.update_layout({f"yaxis{i}": {"scaleanchor": f"x{i}"}, "autosize": True}) + fig.update_layout( + { + f"xaxis{i}": {"fixedrange": True, "showgrid": False}, + f"yaxis{i}": { + "fixedrange": True, + "showgrid": False, + "scaleanchor": f"x{i}", + }, + "autosize": True, + } + ) fig.update_layout( coloraxis={"colorscale": "viridis"},